1import { useAtomValue } from "@effect/atom-react";
2import { useFocusEffect } from "@react-navigation/native";
3import { squashAtomCommandFailure } from "@t3tools/client-runtime/state/runtime";
4import { useCallback, useRef, useState } from "react";
5import { usePullRequestConnected } from "../usePullRequestConnected";
6import { composerPullRequests } from "../../../state/pull-requests";
7import { useEnvironmentQuery } from "../../../state/query";
8import { serverEnvironment } from "../../../state/server";
9import { useAtomCommand } from "../../../state/use-atom-command";
10import { pullRequestTarget, type PullRequestParams } from "../usePullRequestDiff";
11
12export function useReviewGuidesEnabled(params: PullRequestParams) {
13 const settings = useAtomValue(
14 serverEnvironment.settingsValueAtom(pullRequestTarget(params).environmentId),
15 );
16 return settings?.reviewGuidesEnabled === true;
17}
18
19export function useReviewGuide(params: PullRequestParams) {
20 const target = pullRequestTarget(params);
21 const enabled = useReviewGuidesEnabled(params);
22 const query = useEnvironmentQuery(enabled ? composerPullRequests.reviewGuide(target) : null);
23 const connected = usePullRequestConnected(target.environmentId);
24 const permitted = useAtomValue(
25 composerPullRequests.generateReviewGuide.permissionAtom(target.environmentId),
26 );
27 const canWrite = connected && permitted;
28 const generate = useAtomCommand(composerPullRequests.generateReviewGuide, {
29 reportFailure: false,
30 });
31 const [starting, setStarting] = useState(false);
32 const [error, setError] = useState<string | null>(null);
33 const pending = useRef(false);
34 const running = starting || query.data?.run?._tag === "Running";
35 const refresh = query.refresh;
36 useFocusEffect(
37 useCallback(() => {
38 if (!enabled) return;
39 refresh();
40 if (!running) return;
41 const timer = setInterval(refresh, 5_000);
42 return () => clearInterval(timer);
43 }, [enabled, refresh, running]),
44 );
45 const write = async () => {
46 if (!enabled || !canWrite || running || pending.current) return;
47 pending.current = true;
48 setStarting(true);
49 setError(null);
50 try {
51 const result = await generate(target);
52 if (result._tag === "Failure") {
53 const cause = squashAtomCommandFailure(result);
54 setError(cause instanceof Error ? cause.message : "Could not start the review guide.");
55 }
56 } finally {
57 pending.current = false;
58 setStarting(false);
59 }
60 };
61 return { ...query, enabled, canWrite, running, write, startError: error };
62}