feat: add shortcut to switch modes

This commit is contained in:
aheizi 2025-02-28 21:52:48 +08:00
parent e1836f81d7
commit 251b83629a
3 changed files with 40 additions and 0 deletions

View file

@ -31,6 +31,7 @@ interface ChatTextAreaProps {
onHeightChange?: (height: number) => void
mode: Mode
setMode: (value: Mode) => void
modeShortcutText: string
}
const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
@ -48,6 +49,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
onHeightChange,
mode,
setMode,
modeShortcutText,
},
ref,
) => {
@ -816,6 +818,11 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
minWidth: "70px",
flex: "0 0 auto",
}}>
<option
disabled
style={{ ...optionStyle, fontStyle: "italic", opacity: 0.6, padding: "2px 8px" }}>
{modeShortcutText}
</option>
{getAllModes(customModes).map((mode) => (
<option key={mode.slug} value={mode.slug} style={{ ...optionStyle }}>
{mode.name}

View file

@ -28,6 +28,7 @@ import TaskHeader from "./TaskHeader"
import AutoApproveMenu from "./AutoApproveMenu"
import { AudioType } from "../../../../src/shared/WebviewMessage"
import { validateCommand } from "../../utils/command-validation"
import { modes } from "../../../../src/shared/modes"
interface ChatViewProps {
isHidden: boolean
@ -38,6 +39,9 @@ interface ChatViewProps {
export const MAX_IMAGES_PER_MESSAGE = 20 // Anthropic limits to 20 images
const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0
const modeShortcutText = `${isMac ? "⌘" : "Ctrl"} + . for next mode`
const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryView }: ChatViewProps) => {
const {
version,
@ -963,6 +967,33 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
isWriteToolAction,
])
// Add this new function to handle mode switching
const switchToNextMode = useCallback(() => {
const currentModeIndex = modes.findIndex((m) => m.slug === mode)
const nextModeIndex = (currentModeIndex + 1) % modes.length
setMode(modes[nextModeIndex].slug)
}, [mode, setMode])
// Add keyboard event handler
const handleKeyDown = useCallback(
(event: KeyboardEvent) => {
// Check for Command + . (period)
if ((event.metaKey || event.ctrlKey) && event.key === ".") {
event.preventDefault() // Prevent default browser behavior
switchToNextMode()
}
},
[switchToNextMode],
)
// Add event listener
useEffect(() => {
window.addEventListener("keydown", handleKeyDown)
return () => {
window.removeEventListener("keydown", handleKeyDown)
}
}, [handleKeyDown])
return (
<div
style={{
@ -1171,6 +1202,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
}}
mode={mode}
setMode={setMode}
modeShortcutText={modeShortcutText}
/>
<div id="chat-view-portal" />

View file

@ -45,6 +45,7 @@ describe("ChatTextArea", () => {
onHeightChange: jest.fn(),
mode: defaultModeSlug,
setMode: jest.fn(),
modeShortcutText: "(⌘. for next mode)",
}
beforeEach(() => {