Skip to content
Source
Sign inSign up

usePullRequestAction.ts

65 lines2.8 KB

1import { AsyncResult } from "effect/reactivity";
2import * as Dialog from "../../components/ui/Dialog";
3import { useAtomRefresh } from "@effect/atom-react";
4import { squashAtomCommandFailure } from "@t3tools/client-runtime/state/runtime";
5import { sourceControlClients } from "@t3tools/client-runtime/source-control-clients";
6import type {
7 PullRequestAction,
8 PullRequestDetail,
9 PullRequestUpdateMethod,
10} from "@t3tools/contracts";
11import { useRef, useState } from "react";
12import { composerPullRequests } from "../../state/pull-requests";
13import { useAtomCommand } from "../../state/use-atom-command";
14import { canPerformPullRequestAction, pullRequestActionLabel } from "./pullRequestActions";
15import { pullRequestTarget, type PullRequestParams } from "./usePullRequestDiff";
16import { usePullRequestPermissions } from "./usePullRequestPermissions";
17​
18export function usePullRequestAction(params: PullRequestParams, pr: PullRequestDetail | null) {
19 const target = pullRequestTarget(params);
20 const permissions = usePullRequestPermissions(params, pr);
21 const run = useAtomCommand(composerPullRequests.runAction, { reportFailure: false });
22 const refreshActivity = useAtomRefresh(composerPullRequests.activity(target));
23 const pending = useRef(false);
24 const [busy, setBusy] = useState(false);
25 const available = (action: PullRequestAction) =>
26 pr !== null && !busy && permissions.canWrite && canPerformPullRequestAction(pr, action);
27 const perform = async (action: PullRequestAction, updateMethod?: PullRequestUpdateMethod) => {
28 if (pending.current || !available(action)) return;
29 pending.current = true;
30 setBusy(true);
31 const response = await run({
32 ...target,
33 input: { ...target.input, action, ...(updateMethod ? { updateMethod } : {}) },
34 });
35 pending.current = false;
36 setBusy(false);
37 if (AsyncResult.isFailure(response)) {
38 const cause = squashAtomCommandFailure(response);
39 Dialog.alert(
40 `Couldn't update this ${sourceControlClients.get(pr?.provider).changeRequest.singular}`,
41 cause instanceof Error ? cause.message : "Try again.",
42 );
43 return;
44 }
45 refreshActivity();
46 };
47 const confirm = (action: PullRequestAction, title: string, message: string) =>
48 Dialog.alert(title, message, [
49 { text: "Cancel", style: "cancel" },
50 {
51 text: title,
52 style: action === "close" || action === "delete-branch" ? "destructive" : "default",
53 onPress: () => void perform(action),
54 },
55 ]);
56 const confirmClose = () => {
57 const terminology = sourceControlClients.get(pr?.provider).changeRequest;
58 confirm(
59 "close",
60 pullRequestActionLabel("close", terminology),
61 `Close this ${terminology.singular} without merging its changes?`,
62 );
63 };
64 return { available, perform, confirm, confirmClose, busy };