feat: add keyboard shortcuts for cycling agent and thinking variant
This commit is contained in:
@@ -575,7 +575,7 @@ export const ChatInput: React.FC<ChatInputProps> = ({ onOpenSettings, scrollToBo
|
||||
}
|
||||
}
|
||||
|
||||
if (e.key === 'Tab' && !showCommandAutocomplete && !showFileMention) {
|
||||
if (e.key === 'Tab' && e.shiftKey && !showCommandAutocomplete && !showAgentAutocomplete && !showFileMention) {
|
||||
e.preventDefault();
|
||||
cycleAgent();
|
||||
return;
|
||||
|
||||
@@ -10,6 +10,8 @@ import { useUIStore } from "@/stores/useUIStore";
|
||||
import { useConfigStore } from "@/stores/useConfigStore";
|
||||
import {
|
||||
RiAddLine,
|
||||
RiAiAgentLine,
|
||||
RiAiGenerate2,
|
||||
RiArrowUpSLine,
|
||||
RiBrainAi3Line,
|
||||
RiCloseCircleLine,
|
||||
@@ -106,9 +108,19 @@ export const HelpDialog: React.FC = () => {
|
||||
description: "Toggle Session Sidebar",
|
||||
icon: RiLayoutLeftLine,
|
||||
},
|
||||
{
|
||||
keys: ["Shift + Tab"],
|
||||
description: "Cycle Agent (chat input)",
|
||||
icon: RiAiAgentLine,
|
||||
},
|
||||
{
|
||||
keys: [`Shift + ${mod} + M`],
|
||||
description: "Open Model Selector",
|
||||
icon: RiAiGenerate2,
|
||||
},
|
||||
{
|
||||
keys: [`Shift + ${mod} + T`],
|
||||
description: "Cycle Thinking Variant",
|
||||
icon: RiBrainAi3Line,
|
||||
},
|
||||
],
|
||||
@@ -118,12 +130,12 @@ export const HelpDialog: React.FC = () => {
|
||||
items: [
|
||||
{
|
||||
keys: [`${mod} + N`],
|
||||
description: settingsAutoCreateWorktree ? "Create new session in worktree" : "Create New Session",
|
||||
description: settingsAutoCreateWorktree ? "Create New Session in Worktree" : "Create New Session",
|
||||
icon: settingsAutoCreateWorktree ? RiGitBranchLine : RiAddLine,
|
||||
},
|
||||
{
|
||||
keys: [`Shift + ${mod} + N`],
|
||||
description: settingsAutoCreateWorktree ? "Create New Session" : "Create new session in worktree",
|
||||
description: settingsAutoCreateWorktree ? "Create New Session" : "Create New Session in Worktree",
|
||||
icon: settingsAutoCreateWorktree ? RiAddLine : RiGitBranchLine,
|
||||
},
|
||||
{ keys: [`${mod} + I`], description: "Focus Chat Input", icon: RiText },
|
||||
@@ -173,7 +185,7 @@ export const HelpDialog: React.FC = () => {
|
||||
|
||||
return (
|
||||
<Dialog open={isHelpDialogOpen} onOpenChange={setHelpDialogOpen}>
|
||||
<DialogContent className="max-w-2xl">
|
||||
<DialogContent className="max-w-2xl w-[min(42rem,calc(100vw-1.5rem))] max-h-[calc(100dvh-2rem)] flex flex-col overflow-hidden">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<RiSettings3Line className="h-5 w-5" />
|
||||
@@ -184,7 +196,8 @@ export const HelpDialog: React.FC = () => {
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4 mt-3">
|
||||
<div className="flex-1 overflow-y-auto mt-3 pr-1">
|
||||
<div className="space-y-4">
|
||||
{shortcuts.map((section) => (
|
||||
<div key={section.category}>
|
||||
<h3 className="typography-meta font-semibold text-muted-foreground uppercase tracking-wider mb-2">
|
||||
@@ -248,6 +261,7 @@ export const HelpDialog: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -171,6 +171,51 @@ export const useKeyboardShortcuts = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Cmd/Ctrl+Shift+T: Cycle thinking variant (same gating as Shift+M)
|
||||
if (hasModifier(e) && e.shiftKey && e.key.toLowerCase() === 't') {
|
||||
const {
|
||||
isSettingsDialogOpen,
|
||||
isCommandPaletteOpen,
|
||||
isHelpDialogOpen,
|
||||
isSessionSwitcherOpen,
|
||||
isAboutDialogOpen,
|
||||
activeMainTab,
|
||||
} = useUIStore.getState();
|
||||
|
||||
if (isSettingsDialogOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasOverlay = isCommandPaletteOpen || isHelpDialogOpen || isSessionSwitcherOpen || isAboutDialogOpen;
|
||||
const isChatActive = activeMainTab === 'chat';
|
||||
|
||||
if (hasOverlay || !isChatActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
const configState = useConfigStore.getState();
|
||||
const variants = configState.getCurrentModelVariants();
|
||||
if (variants.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
configState.cycleCurrentVariant();
|
||||
|
||||
const nextVariant = useConfigStore.getState().currentVariant;
|
||||
const sessionState = useSessionStore.getState();
|
||||
const sessionId = sessionState.currentSessionId;
|
||||
const agentName = useConfigStore.getState().currentAgentName;
|
||||
const providerId = useConfigStore.getState().currentProviderId;
|
||||
const modelId = useConfigStore.getState().currentModelId;
|
||||
|
||||
if (sessionId && agentName && providerId && modelId) {
|
||||
sessionState.saveAgentModelVariantForSession(sessionId, agentName, providerId, modelId, nextVariant);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.key === 'Escape') {
|
||||
const {
|
||||
isSettingsDialogOpen,
|
||||
|
||||
Reference in New Issue
Block a user