feat: add workspace and tab navigation keyboard shortcuts
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import { useKeyboardShortcutsStore } from "./keyboard-shortcuts-store";
|
||||
|
||||
beforeEach(() => {
|
||||
useKeyboardShortcutsStore.setState({
|
||||
commandCenterOpen: false,
|
||||
shortcutsDialogOpen: false,
|
||||
altDown: false,
|
||||
cmdOrCtrlDown: false,
|
||||
sidebarShortcutWorkspaceTargets: [],
|
||||
visibleWorkspaceTargets: [],
|
||||
messageInputActionRequest: null,
|
||||
nextMessageInputActionRequestId: 1,
|
||||
workspaceTabActionRequest: null,
|
||||
nextWorkspaceTabActionRequestId: 1,
|
||||
});
|
||||
});
|
||||
|
||||
describe("keyboard-shortcuts-store", () => {
|
||||
it("queues and clears workspace tab action requests", () => {
|
||||
useKeyboardShortcutsStore.getState().requestWorkspaceTabAction({
|
||||
serverId: "srv-1",
|
||||
workspaceId: "/repo/main",
|
||||
kind: "navigate-index",
|
||||
index: 3,
|
||||
});
|
||||
|
||||
const request = useKeyboardShortcutsStore.getState().workspaceTabActionRequest;
|
||||
expect(request).toEqual({
|
||||
id: 1,
|
||||
serverId: "srv-1",
|
||||
workspaceId: "/repo/main",
|
||||
kind: "navigate-index",
|
||||
index: 3,
|
||||
});
|
||||
|
||||
useKeyboardShortcutsStore.getState().clearWorkspaceTabActionRequest(999);
|
||||
expect(useKeyboardShortcutsStore.getState().workspaceTabActionRequest).not.toBeNull();
|
||||
|
||||
useKeyboardShortcutsStore.getState().clearWorkspaceTabActionRequest(1);
|
||||
expect(useKeyboardShortcutsStore.getState().workspaceTabActionRequest).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -8,6 +8,28 @@ export type MessageInputActionRequest = {
|
||||
kind: MessageInputKeyboardActionKind;
|
||||
};
|
||||
|
||||
export type WorkspaceTabActionRequest =
|
||||
| {
|
||||
id: number;
|
||||
serverId: string;
|
||||
workspaceId: string;
|
||||
kind: "new" | "close-current";
|
||||
}
|
||||
| {
|
||||
id: number;
|
||||
serverId: string;
|
||||
workspaceId: string;
|
||||
kind: "navigate-index";
|
||||
index: number;
|
||||
}
|
||||
| {
|
||||
id: number;
|
||||
serverId: string;
|
||||
workspaceId: string;
|
||||
kind: "navigate-relative";
|
||||
delta: 1 | -1;
|
||||
};
|
||||
|
||||
interface KeyboardShortcutsState {
|
||||
commandCenterOpen: boolean;
|
||||
shortcutsDialogOpen: boolean;
|
||||
@@ -15,14 +37,19 @@ interface KeyboardShortcutsState {
|
||||
cmdOrCtrlDown: boolean;
|
||||
/** Sidebar-visible workspace targets (up to 9), in top-to-bottom visual order. */
|
||||
sidebarShortcutWorkspaceTargets: SidebarShortcutWorkspaceTarget[];
|
||||
/** All visible workspace targets in top-to-bottom visual order. */
|
||||
visibleWorkspaceTargets: SidebarShortcutWorkspaceTarget[];
|
||||
messageInputActionRequest: MessageInputActionRequest | null;
|
||||
nextMessageInputActionRequestId: number;
|
||||
workspaceTabActionRequest: WorkspaceTabActionRequest | null;
|
||||
nextWorkspaceTabActionRequestId: number;
|
||||
|
||||
setCommandCenterOpen: (open: boolean) => void;
|
||||
setShortcutsDialogOpen: (open: boolean) => void;
|
||||
setAltDown: (down: boolean) => void;
|
||||
setCmdOrCtrlDown: (down: boolean) => void;
|
||||
setSidebarShortcutWorkspaceTargets: (targets: SidebarShortcutWorkspaceTarget[]) => void;
|
||||
setVisibleWorkspaceTargets: (targets: SidebarShortcutWorkspaceTarget[]) => void;
|
||||
resetModifiers: () => void;
|
||||
|
||||
requestMessageInputAction: (input: {
|
||||
@@ -30,6 +57,26 @@ interface KeyboardShortcutsState {
|
||||
kind: MessageInputKeyboardActionKind;
|
||||
}) => void;
|
||||
clearMessageInputActionRequest: (id: number) => void;
|
||||
|
||||
requestWorkspaceTabAction: (input:
|
||||
| {
|
||||
serverId: string;
|
||||
workspaceId: string;
|
||||
kind: "new" | "close-current";
|
||||
}
|
||||
| {
|
||||
serverId: string;
|
||||
workspaceId: string;
|
||||
kind: "navigate-index";
|
||||
index: number;
|
||||
}
|
||||
| {
|
||||
serverId: string;
|
||||
workspaceId: string;
|
||||
kind: "navigate-relative";
|
||||
delta: 1 | -1;
|
||||
}) => void;
|
||||
clearWorkspaceTabActionRequest: (id: number) => void;
|
||||
}
|
||||
|
||||
export const useKeyboardShortcutsStore = create<KeyboardShortcutsState>(
|
||||
@@ -39,8 +86,11 @@ export const useKeyboardShortcutsStore = create<KeyboardShortcutsState>(
|
||||
altDown: false,
|
||||
cmdOrCtrlDown: false,
|
||||
sidebarShortcutWorkspaceTargets: [],
|
||||
visibleWorkspaceTargets: [],
|
||||
messageInputActionRequest: null,
|
||||
nextMessageInputActionRequestId: 1,
|
||||
workspaceTabActionRequest: null,
|
||||
nextWorkspaceTabActionRequestId: 1,
|
||||
|
||||
setCommandCenterOpen: (open) => set({ commandCenterOpen: open }),
|
||||
setShortcutsDialogOpen: (open) => set({ shortcutsDialogOpen: open }),
|
||||
@@ -48,6 +98,7 @@ export const useKeyboardShortcutsStore = create<KeyboardShortcutsState>(
|
||||
setCmdOrCtrlDown: (down) => set({ cmdOrCtrlDown: down }),
|
||||
setSidebarShortcutWorkspaceTargets: (targets) =>
|
||||
set({ sidebarShortcutWorkspaceTargets: targets }),
|
||||
setVisibleWorkspaceTargets: (targets) => set({ visibleWorkspaceTargets: targets }),
|
||||
resetModifiers: () => set({ altDown: false, cmdOrCtrlDown: false }),
|
||||
|
||||
requestMessageInputAction: ({ agentKey, kind }) => {
|
||||
@@ -64,5 +115,23 @@ export const useKeyboardShortcutsStore = create<KeyboardShortcutsState>(
|
||||
}
|
||||
set({ messageInputActionRequest: null });
|
||||
},
|
||||
|
||||
requestWorkspaceTabAction: (input) => {
|
||||
const id = get().nextWorkspaceTabActionRequestId;
|
||||
set({
|
||||
workspaceTabActionRequest: {
|
||||
...input,
|
||||
id,
|
||||
} as WorkspaceTabActionRequest,
|
||||
nextWorkspaceTabActionRequestId: id + 1,
|
||||
});
|
||||
},
|
||||
clearWorkspaceTabActionRequest: (id) => {
|
||||
const current = get().workspaceTabActionRequest;
|
||||
if (!current || current.id !== id) {
|
||||
return;
|
||||
}
|
||||
set({ workspaceTabActionRequest: null });
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user