Files
kandev/apps/web/components/task/task-pr-shortcut.tsx
T
João Salavisa bb290d4281 feat(web): add cmd+shift+g shortcut to open the task's github pr (#1757)
* feat(web): add cmd+shift+g shortcut to open the task's github pr

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: address PR review feedback on focus contract and null task guard

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 14:46:04 +01:00

46 lines
1.8 KiB
TypeScript

"use client";
import { useState } from "react";
import { useToast } from "@/components/toast-provider";
import { useAppStore } from "@/components/state-provider";
import { useTaskPR } from "@/hooks/domains/github/use-task-pr";
import { useKeyboardShortcut } from "@/hooks/use-keyboard-shortcut";
import { getShortcut } from "@/lib/keyboard/shortcut-overrides";
import { openExternalLink } from "@/lib/desktop/external-links";
import { resolveTaskPROpenAction } from "./task-pr-open";
import { TaskPRPickerDialog } from "./task-pr-picker-dialog";
/**
* Task-screen keybinding (default Cmd/Ctrl+Shift+G) that jumps straight to the
* task's GitHub pull request. One linked PR opens directly; several open a
* picker dialog; none shows a toast.
*/
export function TaskPRShortcut({ taskId }: { taskId: string | null }) {
const { toast } = useToast();
const { prs } = useTaskPR(taskId);
const [pickerOpen, setPickerOpen] = useState(false);
const overrides = useAppStore((s) => s.userSettings.keyboardShortcuts);
useKeyboardShortcut(
getShortcut("OPEN_TASK_PR", overrides),
() => {
const action = resolveTaskPROpenAction(prs);
if (action.kind === "none") {
toast({ description: "No pull request linked to this task" });
return;
}
if (action.kind === "open") {
void openExternalLink(action.pr.pr_url).catch(() => undefined);
return;
}
setPickerOpen(true);
},
// Capture + stopPropagation so the binding wins over focus-trapped
// surfaces (xterm.js, editors) — mirrors useEditorKeybinds. Disabled
// until the task id resolves so a transient null doesn't toast.
{ capture: true, stopPropagation: true, enabled: !!taskId },
);
return <TaskPRPickerDialog open={pickerOpen} onOpenChange={setPickerOpen} prs={prs} />;
}