Browse Source

feat: add shortcut to switch modes

aheizi 10 months ago
parent
commit
251b83629a

+ 7 - 0
webview-ui/src/components/chat/ChatTextArea.tsx

@@ -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}

+ 32 - 0
webview-ui/src/components/chat/ChatView.tsx

@@ -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" />

+ 1 - 0
webview-ui/src/components/chat/__tests__/ChatTextArea.test.tsx

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