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.
98 lines
4.1 KiB
TypeScript
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]);
|
|
};
|