Files
openchamber/packages/ui/src/hooks/useMiniChatKeyboardShortcuts.ts
T
Bohdan Triapitsyn b1030d3cb7 fix(chats): align folders and session actions
Render managed Chats through the shared folder-aware session group and keep folder ownership at the Chats root, including new drafts and older per-directory scopes.

Hide worktree actions for Chats, make worktree shortcuts inert on Chat drafts, and let new-session shortcuts inherit an active session directory while explicit Chats controls still create managed Chat drafts.
2026-08-21 16:29:26 +03:00

98 lines
4.1 KiB
TypeScript

import React from 'react';
import { focusChatInput } from '@/components/chat/composer/editor/dom';
import { canUseElectronDesktopIPC, invokeDesktop } from '@/lib/desktop';
import { eventMatchesShortcut, getEffectiveShortcutCombo } from '@/lib/shortcuts';
import { useConfigStore } from '@/stores/useConfigStore';
import { useUIStore } from '@/stores/useUIStore';
import { useSelectionStore } from '@/sync/selection-store';
import { useSessionUIStore } from '@/sync/session-ui-store';
export const useMiniChatKeyboardShortcuts = () => {
const shortcutOverrides = useUIStore((state) => state.shortcutOverrides);
const openNewSessionDraft = useSessionUIStore((state) => state.openNewSessionDraft);
React.useEffect(() => {
const combo = (actionId: string) => getEffectiveShortcutCombo(actionId, shortcutOverrides);
const handleKeyDown = (event: KeyboardEvent) => {
if (eventMatchesShortcut(event, combo('focus_input'))) {
event.preventDefault();
focusChatInput();
return;
}
if (canUseElectronDesktopIPC() && eventMatchesShortcut(event, combo('new_mini_chat'))) {
event.preventDefault();
void invokeDesktop('desktop_open_draft_mini_chat_window', {
directory: '',
projectId: null,
})?.catch((error) => {
console.warn('[mini-chat-shortcuts] failed to open draft mini chat window', error);
});
return;
}
if (eventMatchesShortcut(event, combo('new_chat'))) {
event.preventDefault();
const sessionState = useSessionUIStore.getState();
openNewSessionDraft(sessionState.currentSessionId && sessionState.currentSessionDirectory
? { directoryOverride: sessionState.currentSessionDirectory }
: undefined);
focusChatInput();
return;
}
if (eventMatchesShortcut(event, combo('open_model_selector'))) {
event.preventDefault();
const { isModelSelectorOpen, setModelSelectorOpen } = useUIStore.getState();
setModelSelectorOpen(!isModelSelectorOpen);
return;
}
if (eventMatchesShortcut(event, combo('cycle_thinking_variant'))) {
const configState = useConfigStore.getState();
const variants = configState.getCurrentModelVariants();
if (variants.length === 0) {
return;
}
event.preventDefault();
configState.cycleCurrentVariant();
const nextVariant = useConfigStore.getState().currentVariant;
const sessionId = useSessionUIStore.getState().currentSessionId;
const agentName = useConfigStore.getState().currentAgentName;
const providerId = useConfigStore.getState().currentProviderId;
const modelId = useConfigStore.getState().currentModelId;
if (sessionId && agentName && providerId && modelId) {
useSelectionStore.getState().saveAgentModelVariantForSession(sessionId, agentName, providerId, modelId, nextVariant);
}
return;
}
const cyclesForward = eventMatchesShortcut(event, combo('cycle_favorite_model_forward'));
const cyclesBackward = eventMatchesShortcut(event, combo('cycle_favorite_model_backward'));
if (cyclesForward || cyclesBackward) {
const { favoriteModels, addRecentModel } = useUIStore.getState();
if (favoriteModels.length === 0) {
return;
}
event.preventDefault();
const { currentProviderId, currentModelId, setProvider, setModel } = useConfigStore.getState();
const currentIndex = favoriteModels.findIndex((favorite) => favorite.providerID === currentProviderId && favorite.modelID === currentModelId);
const delta = cyclesForward ? 1 : -1;
const next = favoriteModels[(currentIndex + delta + favoriteModels.length) % favoriteModels.length];
setProvider(next.providerID);
setModel(next.modelID);
addRecentModel(next.providerID, next.modelID);
}
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [openNewSessionDraft, shortcutOverrides]);
};