From 3e39dc390f3541f155e9aa91e449f138d01183a2 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Mon, 14 Jul 2025 14:29:56 +0000 Subject: [PATCH 1/3] feat: add Cmd+Shift+. keyboard shortcut for previous mode switching - Add switchToPreviousMode function that cycles backwards through modes array - Update handleKeyDown to detect Cmd+Shift+. keyboard combination - Update modeShortcutText to display both next and previous mode shortcuts - Add forPreviousMode translation key to all 18 language files - Implements backwards mode cycling using modulo arithmetic for proper array wrapping Fixes #5692 --- webview-ui/src/components/chat/ChatView.tsx | 22 +++++++++++++++++---- webview-ui/src/i18n/locales/ca/chat.json | 1 + webview-ui/src/i18n/locales/de/chat.json | 1 + webview-ui/src/i18n/locales/en/chat.json | 1 + webview-ui/src/i18n/locales/es/chat.json | 1 + webview-ui/src/i18n/locales/fr/chat.json | 1 + webview-ui/src/i18n/locales/hi/chat.json | 1 + webview-ui/src/i18n/locales/id/chat.json | 1 + webview-ui/src/i18n/locales/it/chat.json | 1 + webview-ui/src/i18n/locales/ja/chat.json | 1 + webview-ui/src/i18n/locales/ko/chat.json | 1 + webview-ui/src/i18n/locales/nl/chat.json | 1 + webview-ui/src/i18n/locales/pl/chat.json | 1 + webview-ui/src/i18n/locales/pt-BR/chat.json | 1 + webview-ui/src/i18n/locales/ru/chat.json | 1 + webview-ui/src/i18n/locales/tr/chat.json | 1 + webview-ui/src/i18n/locales/vi/chat.json | 1 + webview-ui/src/i18n/locales/zh-CN/chat.json | 1 + webview-ui/src/i18n/locales/zh-TW/chat.json | 1 + 19 files changed, 36 insertions(+), 4 deletions(-) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index fa4d7ec82a6..83bb814a971 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -79,7 +79,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction { + const allModes = getAllModes(customModes) + const currentModeIndex = allModes.findIndex((m) => m.slug === mode) + const previousModeIndex = (currentModeIndex - 1 + allModes.length) % allModes.length + // Update local state and notify extension to sync mode change + switchToMode(allModes[previousModeIndex].slug) + }, [mode, customModes, switchToMode]) + // Add keyboard event handler const handleKeyDown = useCallback( (event: KeyboardEvent) => { - // Check for Command + . (period) - if ((event.metaKey || event.ctrlKey) && event.key === ".") { + // Check for Command + . (period) for next mode + if ((event.metaKey || event.ctrlKey) && !event.shiftKey && event.key === ".") { event.preventDefault() // Prevent default browser behavior switchToNextMode() } + // Check for Command + Shift + . (period) for previous mode + else if ((event.metaKey || event.ctrlKey) && event.shiftKey && event.key === ".") { + event.preventDefault() // Prevent default browser behavior + switchToPreviousMode() + } }, - [switchToNextMode], + [switchToNextMode, switchToPreviousMode], ) // Add event listener diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index ade415a0a02..bcc41d2052e 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -123,6 +123,7 @@ "separator": "Separador", "edit": "Edita...", "forNextMode": "per al següent mode", + "forPreviousMode": "per al mode anterior", "error": "Error", "diffError": { "title": "Edició fallida" diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index 13f0f64e452..2c85048bf0f 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -123,6 +123,7 @@ "separator": "Trennlinie", "edit": "Bearbeiten...", "forNextMode": "für nächsten Modus", + "forPreviousMode": "für vorherigen Modus", "error": "Fehler", "diffError": { "title": "Bearbeitung fehlgeschlagen" diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index ef40ba854ba..a5c8bd83374 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -131,6 +131,7 @@ "separator": "Separator", "edit": "Edit...", "forNextMode": "for next mode", + "forPreviousMode": "for previous mode", "apiRequest": { "title": "API Request", "failed": "API Request Failed", diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index 200939d34b6..711fe7712b5 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -123,6 +123,7 @@ "separator": "Separador", "edit": "Editar...", "forNextMode": "para el siguiente modo", + "forPreviousMode": "para el modo anterior", "error": "Error", "diffError": { "title": "Edición fallida" diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index 2858400e78d..f3832174e63 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -123,6 +123,7 @@ "separator": "Séparateur", "edit": "Éditer...", "forNextMode": "pour le prochain mode", + "forPreviousMode": "pour le mode précédent", "error": "Erreur", "diffError": { "title": "Modification échouée" diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index c2db235a6bd..34e80597a86 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -123,6 +123,7 @@ "separator": "विभाजक", "edit": "संपादित करें...", "forNextMode": "अगले मोड के लिए", + "forPreviousMode": "पिछले मोड के लिए", "error": "त्रुटि", "diffError": { "title": "संपादन असफल" diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index dce04268321..c6f9c57644f 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -137,6 +137,7 @@ "separator": "Pemisah", "edit": "Edit...", "forNextMode": "untuk mode selanjutnya", + "forPreviousMode": "untuk mode sebelumnya", "apiRequest": { "title": "Permintaan API", "failed": "Permintaan API Gagal", diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index 084606605ff..080d6883aa2 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -123,6 +123,7 @@ "separator": "Separatore", "edit": "Modifica...", "forNextMode": "per la prossima modalità", + "forPreviousMode": "per la modalità precedente", "instructions": { "wantsToFetch": "Roo vuole recuperare istruzioni dettagliate per aiutare con l'attività corrente" }, diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index dc69fdf742b..6bb74ad5e27 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -123,6 +123,7 @@ "separator": "区切り", "edit": "編集...", "forNextMode": "次のモード用", + "forPreviousMode": "前のモード用", "error": "エラー", "diffError": { "title": "編集に失敗しました" diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 1be0b4cb1b8..812579a850f 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -123,6 +123,7 @@ "separator": "구분자", "edit": "편집...", "forNextMode": "다음 모드용", + "forPreviousMode": "이전 모드용", "error": "오류", "diffError": { "title": "편집 실패" diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index d2834c700f9..c0e5e92d66d 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -123,6 +123,7 @@ "separator": "Scheidingsteken", "edit": "Bewerken...", "forNextMode": "voor volgende modus", + "forPreviousMode": "voor vorige modus", "apiRequest": { "title": "API-verzoek", "failed": "API-verzoek mislukt", diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index e8020219c06..3e59b4f9816 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -123,6 +123,7 @@ "separator": "Separator", "edit": "Edytuj...", "forNextMode": "dla następnego trybu", + "forPreviousMode": "dla poprzedniego trybu", "error": "Błąd", "diffError": { "title": "Edycja nieudana" diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index a0b39e6c960..8f7dcd5dcd8 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -123,6 +123,7 @@ "separator": "Separador", "edit": "Editar...", "forNextMode": "para o próximo modo", + "forPreviousMode": "para o modo anterior", "error": "Erro", "diffError": { "title": "Edição mal-sucedida" diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index 9c751fba8cb..89502fbc768 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -123,6 +123,7 @@ "separator": "Разделитель", "edit": "Редактировать...", "forNextMode": "для следующего режима", + "forPreviousMode": "для предыдущего режима", "apiRequest": { "title": "API-запрос", "failed": "API-запрос не выполнен", diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 951877d65e1..94910edf89d 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -123,6 +123,7 @@ "separator": "Ayırıcı", "edit": "Düzenle...", "forNextMode": "sonraki mod için", + "forPreviousMode": "önceki mod için", "error": "Hata", "diffError": { "title": "Düzenleme Başarısız" diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index 7588595280d..02f27f9e378 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -123,6 +123,7 @@ "separator": "Dấu phân cách", "edit": "Chỉnh sửa...", "forNextMode": "cho chế độ tiếp theo", + "forPreviousMode": "cho chế độ trước đó", "error": "Lỗi", "diffError": { "title": "Chỉnh sửa không thành công" diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index 352da4c9d20..370543f2942 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -123,6 +123,7 @@ "separator": "分隔符", "edit": "编辑...", "forNextMode": "用于下一个模式", + "forPreviousMode": "用于上一个模式", "error": "错误", "diffError": { "title": "编辑失败" diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index ff0a541aa1b..3b9dcc795c5 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -123,6 +123,7 @@ "separator": "分隔符號", "edit": "編輯...", "forNextMode": "用於下一個模式", + "forPreviousMode": "用於上一個模式", "error": "錯誤", "diffError": { "title": "編輯失敗" From f76a359c7b73e4bc84459768ba696b5375cbf55a Mon Sep 17 00:00:00 2001 From: Roo Code Date: Mon, 14 Jul 2025 23:18:46 +0000 Subject: [PATCH 2/3] fix: correct keyboard shortcut detection for Cmd+Shift+. (previous mode) When Shift is pressed with the period key, event.key becomes ">" instead of ".". Fixed line 1576 to check for event.key === ">" for proper Cmd+Shift+. detection. Fixes keyboard shortcut issue reported in PR comment. --- webview-ui/src/components/chat/ChatView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 83bb814a971..be7b9832d12 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1573,7 +1573,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction") { event.preventDefault() // Prevent default browser behavior switchToPreviousMode() } From 6793b9a889226cf7c74b7af055076b54d924c140 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Tue, 15 Jul 2025 00:13:51 +0000 Subject: [PATCH 3/3] fix: use event.code for cross-platform keyboard shortcut compatibility - Replace event.key checks with event.code === "Period" for both shortcuts - Fixes keyboard layout compatibility issue where Shift+Period produces different characters on non-US layouts - Consolidates both shortcuts into a single conditional block for better maintainability - Addresses feedback from @daniel-lxs in PR #5695 --- webview-ui/src/components/chat/ChatView.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index be7b9832d12..0f0b056f755 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1567,15 +1567,18 @@ const ChatViewComponent: React.ForwardRefRenderFunction { - // Check for Command + . (period) for next mode - if ((event.metaKey || event.ctrlKey) && !event.shiftKey && event.key === ".") { + // Check for Command/Ctrl + Period (with or without Shift) + // Using event.code for better cross-platform compatibility + if ((event.metaKey || event.ctrlKey) && event.code === "Period") { event.preventDefault() // Prevent default browser behavior - switchToNextMode() - } - // Check for Command + Shift + . (period) for previous mode - else if ((event.metaKey || event.ctrlKey) && event.shiftKey && event.key === ">") { - event.preventDefault() // Prevent default browser behavior - switchToPreviousMode() + + if (event.shiftKey) { + // Shift + Period = Previous mode + switchToPreviousMode() + } else { + // Just Period = Next mode + switchToNextMode() + } } }, [switchToNextMode, switchToPreviousMode],