From 9b40eb2ddbb39793711cab70c008139034e1d900 Mon Sep 17 00:00:00 2001 From: Chase McDougall Date: Tue, 3 Feb 2026 18:53:25 -0500 Subject: [PATCH] feat(desktop): add Cmd+Shift+P shortcut and always-visible PR button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Show PR button in changes header even when no PR exists — clicking it creates a PR. Register OPEN_PR hotkey (⌘⇧P) that opens the existing PR or creates one if none exists. --- .../workspace/$workspaceId/page.tsx | 21 ++++++++++++ .../components/PRButton/PRButton.tsx | 33 +++++++++++++++++-- apps/desktop/src/shared/hotkeys.ts | 6 ++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx index 959a7e599ba..852864e857c 100644 --- a/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx +++ b/apps/desktop/src/renderer/routes/_authenticated/_dashboard/workspace/$workspaceId/page.tsx @@ -1,3 +1,4 @@ +import { toast } from "@superset/ui/sonner"; import { createFileRoute, notFound, useNavigate } from "@tanstack/react-router"; import { useCallback, useMemo } from "react"; import { electronTrpc } from "renderer/lib/electron-trpc"; @@ -8,6 +9,7 @@ import { usePresetHotkeys } from "renderer/routes/_authenticated/_dashboard/work import { NotFound } from "renderer/routes/not-found"; import { WorkspaceInitializingView } from "renderer/screens/main/components/WorkspaceView/WorkspaceInitializingView"; import { WorkspaceLayout } from "renderer/screens/main/components/WorkspaceView/WorkspaceLayout"; +import { usePRStatus } from "renderer/screens/main/hooks"; import { useAppHotkey } from "renderer/stores/hotkeys"; import { SidebarMode, useSidebarStore } from "renderer/stores/sidebar-state"; import { getPaneDimensions } from "renderer/stores/tabs/pane-refs"; @@ -251,6 +253,25 @@ function WorkspacePage() { [workspace?.worktreePath], ); + // Open PR shortcut (⌘⇧P) + const { pr } = usePRStatus({ workspaceId }); + const createPRMutation = electronTrpc.changes.createPR.useMutation({ + onSuccess: () => toast.success("Opening GitHub..."), + onError: (error) => toast.error(`Failed: ${error.message}`), + }); + useAppHotkey( + "OPEN_PR", + () => { + if (pr?.url) { + window.open(pr.url, "_blank"); + } else if (workspace?.worktreePath) { + createPRMutation.mutate({ worktreePath: workspace.worktreePath }); + } + }, + undefined, + [pr?.url, workspace?.worktreePath], + ); + // Toggle changes sidebar (⌘L) useAppHotkey("TOGGLE_SIDEBAR", () => toggleSidebar(), undefined, [ toggleSidebar, diff --git a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/components/PRButton/PRButton.tsx b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/components/PRButton/PRButton.tsx index 35ae67542d8..3d5e8d9e2f0 100644 --- a/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/components/PRButton/PRButton.tsx +++ b/apps/desktop/src/renderer/screens/main/components/WorkspaceView/RightSidebar/ChangesView/components/ChangesHeader/components/PRButton/PRButton.tsx @@ -6,8 +6,9 @@ import { DropdownMenuTrigger, } from "@superset/ui/dropdown-menu"; import { toast } from "@superset/ui/sonner"; +import { Tooltip, TooltipContent, TooltipTrigger } from "@superset/ui/tooltip"; import { HiChevronDown } from "react-icons/hi2"; -import { LuLoaderCircle } from "react-icons/lu"; +import { LuGitPullRequest, LuLoaderCircle } from "react-icons/lu"; import { VscGitMerge } from "react-icons/vsc"; import { electronTrpc } from "renderer/lib/electron-trpc"; import { PRIcon } from "renderer/screens/main/components/PRIcon"; @@ -37,6 +38,14 @@ export function PRButton({ onError: (error) => toast.error(`Merge failed: ${error.message}`), }); + const createPRMutation = electronTrpc.changes.createPR.useMutation({ + onSuccess: () => { + toast.success("Opening GitHub..."); + onRefresh(); + }, + onError: (error) => toast.error(`Failed: ${error.message}`), + }); + const handleMergePR = (strategy: "merge" | "squash" | "rebase") => mergePRMutation.mutate({ worktreePath, strategy, deleteBranch: true }); @@ -46,7 +55,27 @@ export function PRButton({ ); } - if (!pr) return null; + if (!pr) { + return ( + + + + + Create Pull Request + + ); + } const canMerge = pr.state === "open"; diff --git a/apps/desktop/src/shared/hotkeys.ts b/apps/desktop/src/shared/hotkeys.ts index 75ead97970e..372e1e00194 100644 --- a/apps/desktop/src/shared/hotkeys.ts +++ b/apps/desktop/src/shared/hotkeys.ts @@ -646,6 +646,12 @@ export const HOTKEYS = { category: "Workspace", description: "Open an existing project folder", }), + OPEN_PR: defineHotkey({ + keys: "meta+shift+p", + label: "Open Pull Request", + category: "Workspace", + description: "Open existing PR or create a new one on GitHub", + }), // Window NEW_WINDOW: defineHotkey({