| 1 | import { useAtomValue } from "@effect/atom-react"; |
| 2 | import { useFocusEffect } from "@react-navigation/native"; |
| 3 | import { squashAtomCommandFailure } from "@t3tools/client-runtime/state/runtime"; |
| 4 | import { useCallback, useRef, useState } from "react"; |
| 5 | import { usePullRequestConnected } from "../usePullRequestConnected"; |
| 6 | import { composerPullRequests } from "../../../state/pull-requests"; |
| 7 | import { useEnvironmentQuery } from "../../../state/query"; |
| 8 | import { serverEnvironment } from "../../../state/server"; |
| 9 | import { useAtomCommand } from "../../../state/use-atom-command"; |
| 10 | import { pullRequestTarget, type PullRequestParams } from "../usePullRequestDiff"; |
| 11 | |
| 12 | export function useReviewGuidesEnabled(params: PullRequestParams) { |
| 13 | const settings = useAtomValue( |
| 14 | serverEnvironment.settingsValueAtom(pullRequestTarget(params).environmentId), |
| 15 | ); |
| 16 | return settings?.reviewGuidesEnabled === true; |
| 17 | } |
| 18 | |
| 19 | export 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 | } |