feat(shortcuts): Add Ctrl/Cmd+1..4 to switch main views
Add keyboard shortcuts (Ctrl/Cmd + 1–4) to jump to the four main views: Dashboard, Repositories, Pull Requests and Issues & Boards. - Handler runs in the capture phase so editors/dialogs can still trap keys. - Switching is blocked when the app is busy or any modal/overlay is open; repeats and combinations with Alt/Shift are ignored. - When switching to the repository view the shortcut selects an existing repo tab (it will not open a native file dialog if no repo is available). Also update tab button titles to surface the shortcuts and add entries to the help overlay (English and German).
This commit is contained in:
+62
-1
@@ -5940,6 +5940,67 @@
|
||||
|
||||
// ── Event handlers ─────────────────────────────────────────────────────────
|
||||
|
||||
// ── Main view shortcuts ────────────────────────────────────────────────────
|
||||
// Ctrl/Cmd + 1…4 jump to the four main views in the order of the tab bar.
|
||||
const mainViewShortcuts: AppView[] = ["management", "repository", "review-center", "issues"];
|
||||
|
||||
function mainViewShortcutIndex(event: KeyboardEvent): number {
|
||||
if (!(event.ctrlKey || event.metaKey) || event.altKey || event.shiftKey) return 0;
|
||||
const code = event.code ?? "";
|
||||
const digit = code.startsWith("Digit")
|
||||
? Number(code.slice(5))
|
||||
: code.startsWith("Numpad")
|
||||
? Number(code.slice(6))
|
||||
: Number(event.key);
|
||||
if (!Number.isInteger(digit) || digit < 1 || digit > mainViewShortcuts.length) return 0;
|
||||
return digit;
|
||||
}
|
||||
|
||||
// Capture phase: dialogs and editors trap keys on their own nodes, and the
|
||||
// view shortcut must not depend on the event reaching window afterwards.
|
||||
function handleViewShortcutKeydown(event: KeyboardEvent) {
|
||||
const index = mainViewShortcutIndex(event);
|
||||
if (index === 0) return;
|
||||
if (import.meta.env.DEV) {
|
||||
console.debug("[gitty] view shortcut", { key: event.key, code: event.code, index, blocked: mainViewSwitchBlocked(), activeView });
|
||||
}
|
||||
event.preventDefault();
|
||||
if (!event.repeat) switchMainView(index);
|
||||
}
|
||||
|
||||
// Anything modal owns the keyboard, so the view stays where it is.
|
||||
function mainViewSwitchBlocked(): boolean {
|
||||
return isBusy
|
||||
|| commandPaletteOpen || helpOpen || globalSearchOpen || appSettingsOpen
|
||||
|| cloneDialogOpen || initRepositoryDialogOpen || credDialogOpen
|
||||
|| compareDialogOpen || compareSelectOpen || fileHistoryDialogOpen
|
||||
|| resolveDialogOpen || interactiveRebaseOpen || reflogOpen || bisectOpen
|
||||
|| worktreeDialogOpen || submoduleDialogOpen || gitLfsDialogOpen
|
||||
|| linePatchOpen || aiReviewOpen
|
||||
|| pendingSubmoduleInitialization !== null || pendingDiscard !== null
|
||||
|| newBranchCommit !== null || renameBranchTarget !== null
|
||||
|| deleteBranchTarget !== null || commitNoteTarget !== null;
|
||||
}
|
||||
|
||||
function switchMainView(index: number) {
|
||||
if (mainViewSwitchBlocked()) return;
|
||||
const view = mainViewShortcuts[index - 1];
|
||||
if (!view || view === activeView) return;
|
||||
closeRepoTabContextMenu();
|
||||
if (view === "management") {
|
||||
openRepoManagement();
|
||||
} else if (view === "review-center") {
|
||||
openReviewCenter();
|
||||
} else if (view === "issues") {
|
||||
activeView = "issues";
|
||||
} else {
|
||||
// Without an open repository the tab bar would ask for a folder; a
|
||||
// keyboard shortcut should never pop up a native file dialog.
|
||||
const path = repoTabs.find((tab) => sameRepoPath(tab.path, activeRepoPath))?.path ?? repoTabs[0]?.path;
|
||||
if (path) void selectRepoTab(path);
|
||||
}
|
||||
}
|
||||
|
||||
function handleWindowKeydown(event: KeyboardEvent) {
|
||||
if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === "k") {
|
||||
event.preventDefault();
|
||||
@@ -5992,7 +6053,7 @@
|
||||
<title>Gitty</title>
|
||||
</svelte:head>
|
||||
|
||||
<svelte:window on:click={handleWindowClick} on:keydown={handleWindowKeydown} on:contextmenu|capture={handleWindowContextMenu} />
|
||||
<svelte:window on:click={handleWindowClick} on:keydown|capture={handleViewShortcutKeydown} on:keydown={handleWindowKeydown} on:contextmenu|capture={handleWindowContextMenu} />
|
||||
|
||||
{#if sidebarSectionMenu && activeView === "repository"}
|
||||
<SidebarSectionMenu x={sidebarSectionMenu.x} y={sidebarSectionMenu.y} language={appLanguage}
|
||||
|
||||
Reference in New Issue
Block a user