Delay shortcut badge display by 150ms to avoid sidebar re-renders on quick modifier taps
This commit is contained in:
@@ -44,7 +44,7 @@ import { NestableScrollContainer } from "react-native-draggable-flatlist";
|
|||||||
import { DraggableList, type DraggableRenderItemInfo } from "./draggable-list";
|
import { DraggableList, type DraggableRenderItemInfo } from "./draggable-list";
|
||||||
import type { DraggableListDragHandleProps } from "./draggable-list.types";
|
import type { DraggableListDragHandleProps } from "./draggable-list.types";
|
||||||
import { getHostRuntimeStore, isHostRuntimeConnected } from "@/runtime/host-runtime";
|
import { getHostRuntimeStore, isHostRuntimeConnected } from "@/runtime/host-runtime";
|
||||||
import { getIsElectronRuntime, useIsCompactFormFactor } from "@/constants/layout";
|
import { useIsCompactFormFactor } from "@/constants/layout";
|
||||||
import { projectIconQueryKey } from "@/hooks/use-project-icon-query";
|
import { projectIconQueryKey } from "@/hooks/use-project-icon-query";
|
||||||
import { parseHostWorkspaceRouteFromPathname } from "@/utils/host-routes";
|
import { parseHostWorkspaceRouteFromPathname } from "@/utils/host-routes";
|
||||||
import { prepareWorkspaceTab } from "@/utils/workspace-navigation";
|
import { prepareWorkspaceTab } from "@/utils/workspace-navigation";
|
||||||
@@ -53,7 +53,7 @@ import {
|
|||||||
type SidebarWorkspaceEntry,
|
type SidebarWorkspaceEntry,
|
||||||
} from "@/hooks/use-sidebar-workspaces-list";
|
} from "@/hooks/use-sidebar-workspaces-list";
|
||||||
import { useSidebarOrderStore } from "@/stores/sidebar-order-store";
|
import { useSidebarOrderStore } from "@/stores/sidebar-order-store";
|
||||||
import { useKeyboardShortcutsStore } from "@/stores/keyboard-shortcuts-store";
|
import { useShowShortcutBadges } from "@/hooks/use-show-shortcut-badges";
|
||||||
import { ContextMenuTrigger, useContextMenu } from "@/components/ui/context-menu";
|
import { ContextMenuTrigger, useContextMenu } from "@/components/ui/context-menu";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@@ -1604,10 +1604,7 @@ export function SidebarWorkspaceList({
|
|||||||
const creatingWorkspaceTimeoutsRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(
|
const creatingWorkspaceTimeoutsRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(
|
||||||
new Map(),
|
new Map(),
|
||||||
);
|
);
|
||||||
const isDesktopApp = getIsElectronRuntime();
|
const showShortcutBadges = useShowShortcutBadges();
|
||||||
const altDown = useKeyboardShortcutsStore((state) => state.altDown);
|
|
||||||
const cmdOrCtrlDown = useKeyboardShortcutsStore((state) => state.cmdOrCtrlDown);
|
|
||||||
const showShortcutBadges = altDown || (isDesktopApp && cmdOrCtrlDown);
|
|
||||||
|
|
||||||
const getProjectOrder = useSidebarOrderStore((state) => state.getProjectOrder);
|
const getProjectOrder = useSidebarOrderStore((state) => state.getProjectOrder);
|
||||||
const setProjectOrder = useSidebarOrderStore((state) => state.setProjectOrder);
|
const setProjectOrder = useSidebarOrderStore((state) => state.setProjectOrder);
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { useKeyboardShortcutsStore } from "@/stores/keyboard-shortcuts-store";
|
||||||
|
|
||||||
|
export function useShowShortcutBadges(): boolean {
|
||||||
|
return useKeyboardShortcutsStore((state) => state.showShortcutBadges);
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import type { SidebarShortcutWorkspaceTarget } from "@/utils/sidebar-shortcuts";
|
import type { SidebarShortcutWorkspaceTarget } from "@/utils/sidebar-shortcuts";
|
||||||
|
|
||||||
|
const SHORTCUT_BADGE_DELAY_MS = 150;
|
||||||
|
|
||||||
interface KeyboardShortcutsState {
|
interface KeyboardShortcutsState {
|
||||||
commandCenterOpen: boolean;
|
commandCenterOpen: boolean;
|
||||||
projectPickerOpen: boolean;
|
projectPickerOpen: boolean;
|
||||||
@@ -8,6 +10,7 @@ interface KeyboardShortcutsState {
|
|||||||
capturingShortcut: boolean;
|
capturingShortcut: boolean;
|
||||||
altDown: boolean;
|
altDown: boolean;
|
||||||
cmdOrCtrlDown: boolean;
|
cmdOrCtrlDown: boolean;
|
||||||
|
showShortcutBadges: boolean;
|
||||||
/** Sidebar-visible workspace targets (up to 9), in top-to-bottom visual order. */
|
/** Sidebar-visible workspace targets (up to 9), in top-to-bottom visual order. */
|
||||||
sidebarShortcutWorkspaceTargets: SidebarShortcutWorkspaceTarget[];
|
sidebarShortcutWorkspaceTargets: SidebarShortcutWorkspaceTarget[];
|
||||||
/** All visible workspace targets in top-to-bottom visual order. */
|
/** All visible workspace targets in top-to-bottom visual order. */
|
||||||
@@ -24,13 +27,37 @@ interface KeyboardShortcutsState {
|
|||||||
resetModifiers: () => void;
|
resetModifiers: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useKeyboardShortcutsStore = create<KeyboardShortcutsState>((set) => ({
|
let badgeTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
|
|
||||||
|
function updateBadgeTimer(
|
||||||
|
set: (partial: Partial<KeyboardShortcutsState>) => void,
|
||||||
|
get: () => KeyboardShortcutsState,
|
||||||
|
) {
|
||||||
|
const { altDown, cmdOrCtrlDown } = get();
|
||||||
|
const modifierDown = altDown || cmdOrCtrlDown;
|
||||||
|
|
||||||
|
if (badgeTimer) {
|
||||||
|
clearTimeout(badgeTimer);
|
||||||
|
badgeTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modifierDown) {
|
||||||
|
badgeTimer = setTimeout(() => {
|
||||||
|
set({ showShortcutBadges: true });
|
||||||
|
}, SHORTCUT_BADGE_DELAY_MS);
|
||||||
|
} else {
|
||||||
|
set({ showShortcutBadges: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useKeyboardShortcutsStore = create<KeyboardShortcutsState>((set, get) => ({
|
||||||
commandCenterOpen: false,
|
commandCenterOpen: false,
|
||||||
projectPickerOpen: false,
|
projectPickerOpen: false,
|
||||||
shortcutsDialogOpen: false,
|
shortcutsDialogOpen: false,
|
||||||
capturingShortcut: false,
|
capturingShortcut: false,
|
||||||
altDown: false,
|
altDown: false,
|
||||||
cmdOrCtrlDown: false,
|
cmdOrCtrlDown: false,
|
||||||
|
showShortcutBadges: false,
|
||||||
sidebarShortcutWorkspaceTargets: [],
|
sidebarShortcutWorkspaceTargets: [],
|
||||||
visibleWorkspaceTargets: [],
|
visibleWorkspaceTargets: [],
|
||||||
|
|
||||||
@@ -38,10 +65,19 @@ export const useKeyboardShortcutsStore = create<KeyboardShortcutsState>((set) =>
|
|||||||
setProjectPickerOpen: (open) => set({ projectPickerOpen: open }),
|
setProjectPickerOpen: (open) => set({ projectPickerOpen: open }),
|
||||||
setShortcutsDialogOpen: (open) => set({ shortcutsDialogOpen: open }),
|
setShortcutsDialogOpen: (open) => set({ shortcutsDialogOpen: open }),
|
||||||
setCapturingShortcut: (capturing) => set({ capturingShortcut: capturing }),
|
setCapturingShortcut: (capturing) => set({ capturingShortcut: capturing }),
|
||||||
setAltDown: (down) => set({ altDown: down }),
|
setAltDown: (down) => {
|
||||||
setCmdOrCtrlDown: (down) => set({ cmdOrCtrlDown: down }),
|
set({ altDown: down });
|
||||||
|
updateBadgeTimer(set, get);
|
||||||
|
},
|
||||||
|
setCmdOrCtrlDown: (down) => {
|
||||||
|
set({ cmdOrCtrlDown: down });
|
||||||
|
updateBadgeTimer(set, get);
|
||||||
|
},
|
||||||
setSidebarShortcutWorkspaceTargets: (targets) =>
|
setSidebarShortcutWorkspaceTargets: (targets) =>
|
||||||
set({ sidebarShortcutWorkspaceTargets: targets }),
|
set({ sidebarShortcutWorkspaceTargets: targets }),
|
||||||
setVisibleWorkspaceTargets: (targets) => set({ visibleWorkspaceTargets: targets }),
|
setVisibleWorkspaceTargets: (targets) => set({ visibleWorkspaceTargets: targets }),
|
||||||
resetModifiers: () => set({ altDown: false, cmdOrCtrlDown: false }),
|
resetModifiers: () => {
|
||||||
|
set({ altDown: false, cmdOrCtrlDown: false });
|
||||||
|
updateBadgeTimer(set, get);
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|||||||
Reference in New Issue
Block a user