feat(ui): add session list shortcut
This commit is contained in:
@@ -135,6 +135,11 @@ export const HelpDialog: React.FC = () => {
|
|||||||
icon: 'git-branch',
|
icon: 'git-branch',
|
||||||
keys: '',
|
keys: '',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'open_session_list',
|
||||||
|
icon: 'list-unordered',
|
||||||
|
keys: '',
|
||||||
|
},
|
||||||
{ id: 'focus_input', descriptionKey: "helpDialog.item.focusChatInput", icon: "text", keys: '' },
|
{ id: 'focus_input', descriptionKey: "helpDialog.item.focusChatInput", icon: "text", keys: '' },
|
||||||
{
|
{
|
||||||
id: 'toggle_prompt_navigator',
|
id: 'toggle_prompt_navigator',
|
||||||
|
|||||||
@@ -99,6 +99,11 @@ export const useKeyboardShortcuts = () => {
|
|||||||
open_timeline_dialog: () => {
|
open_timeline_dialog: () => {
|
||||||
useUIStore.getState().setTimelineDialogOpen(true);
|
useUIStore.getState().setTimelineDialogOpen(true);
|
||||||
},
|
},
|
||||||
|
open_session_list: () => {
|
||||||
|
const state = useUIStore.getState();
|
||||||
|
if (state.isMobile) state.setSessionSwitcherOpen(true);
|
||||||
|
else state.setSessionDropdownOpen(true);
|
||||||
|
},
|
||||||
toggle_prompt_navigator: () => {
|
toggle_prompt_navigator: () => {
|
||||||
const state = useUIStore.getState();
|
const state = useUIStore.getState();
|
||||||
const hasOverlay = state.isSettingsDialogOpen
|
const hasOverlay = state.isSettingsDialogOpen
|
||||||
|
|||||||
@@ -1142,6 +1142,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.error.exactConflict': 'This combination is already used by {action}.',
|
'settings.openchamber.keyboardShortcuts.error.exactConflict': 'This combination is already used by {action}.',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': 'Open draft project picker',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': 'Open draft project picker',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': 'Open draft worktree picker',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': 'Open draft worktree picker',
|
||||||
|
'settings.openchamber.keyboardShortcuts.action.open_session_list.label': 'Open session list',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': 'Voice input',
|
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': 'Voice input',
|
||||||
'settings.projects.sidebar.total': 'Total {count}',
|
'settings.projects.sidebar.total': 'Total {count}',
|
||||||
'settings.projects.sidebar.actions.addProject': 'Add project',
|
'settings.projects.sidebar.actions.addProject': 'Add project',
|
||||||
|
|||||||
@@ -1109,6 +1109,7 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.keyboardShortcuts.error.exactConflict": "Esta combinación ya la usa {action}.",
|
"settings.openchamber.keyboardShortcuts.error.exactConflict": "Esta combinación ya la usa {action}.",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label": "Abrir selector de proyecto de borrador",
|
"settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label": "Abrir selector de proyecto de borrador",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label": "Abrir selector de árbol de trabajo de borrador",
|
"settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label": "Abrir selector de árbol de trabajo de borrador",
|
||||||
|
"settings.openchamber.keyboardShortcuts.action.open_session_list.label": "Abrir lista de sesiones",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_dictation.label": "Entrada de voz",
|
"settings.openchamber.keyboardShortcuts.action.toggle_dictation.label": "Entrada de voz",
|
||||||
"settings.projects.sidebar.total": "Total {count}",
|
"settings.projects.sidebar.total": "Total {count}",
|
||||||
"settings.projects.sidebar.actions.addProject": "Añadir proyecto",
|
"settings.projects.sidebar.actions.addProject": "Añadir proyecto",
|
||||||
|
|||||||
@@ -1030,6 +1030,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.error.exactConflict': 'Cette combinaison est déjà utilisée par {action}.',
|
'settings.openchamber.keyboardShortcuts.error.exactConflict': 'Cette combinaison est déjà utilisée par {action}.',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': 'Ouvrir le sélecteur de projet de brouillon',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': 'Ouvrir le sélecteur de projet de brouillon',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': 'Ouvrir le sélecteur de worktree de brouillon',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': 'Ouvrir le sélecteur de worktree de brouillon',
|
||||||
|
'settings.openchamber.keyboardShortcuts.action.open_session_list.label': 'Ouvrir la liste des sessions',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': 'Saisie vocale',
|
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': 'Saisie vocale',
|
||||||
'settings.projects.sidebar.total': 'Total {count}',
|
'settings.projects.sidebar.total': 'Total {count}',
|
||||||
'settings.projects.sidebar.actions.addProject': 'Ajouter un projet',
|
'settings.projects.sidebar.actions.addProject': 'Ajouter un projet',
|
||||||
|
|||||||
@@ -1142,6 +1142,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.error.exactConflict': 'この組み合わせは {action} で使用されています。',
|
'settings.openchamber.keyboardShortcuts.error.exactConflict': 'この組み合わせは {action} で使用されています。',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '下書きプロジェクト選択を開く',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '下書きプロジェクト選択を開く',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '下書きワークツリー選択を開く',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '下書きワークツリー選択を開く',
|
||||||
|
'settings.openchamber.keyboardShortcuts.action.open_session_list.label': 'セッション一覧を開く',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '音声入力',
|
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '音声入力',
|
||||||
'settings.projects.sidebar.total': '合計 {count}',
|
'settings.projects.sidebar.total': '合計 {count}',
|
||||||
'settings.projects.sidebar.actions.addProject': 'プロジェクトを追加',
|
'settings.projects.sidebar.actions.addProject': 'プロジェクトを追加',
|
||||||
|
|||||||
@@ -1109,6 +1109,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.error.exactConflict': '이 조합은 이미 {action}에서 사용합니다.',
|
'settings.openchamber.keyboardShortcuts.error.exactConflict': '이 조합은 이미 {action}에서 사용합니다.',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '초안 프로젝트 선택기 열기',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '초안 프로젝트 선택기 열기',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '초안 워크트리 선택기 열기',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '초안 워크트리 선택기 열기',
|
||||||
|
'settings.openchamber.keyboardShortcuts.action.open_session_list.label': '세션 목록 열기',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '음성 입력',
|
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '음성 입력',
|
||||||
'settings.projects.sidebar.total': '총 {count}개',
|
'settings.projects.sidebar.total': '총 {count}개',
|
||||||
'settings.projects.sidebar.actions.addProject': '프로젝트 추가',
|
'settings.projects.sidebar.actions.addProject': '프로젝트 추가',
|
||||||
|
|||||||
@@ -1377,6 +1377,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.error.exactConflict': 'Ta kombinacja jest już używana przez {action}.',
|
'settings.openchamber.keyboardShortcuts.error.exactConflict': 'Ta kombinacja jest już używana przez {action}.',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': 'Otwórz wybór projektu szkicu',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': 'Otwórz wybór projektu szkicu',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': 'Otwórz wybór worktree szkicu',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': 'Otwórz wybór worktree szkicu',
|
||||||
|
'settings.openchamber.keyboardShortcuts.action.open_session_list.label': 'Otwórz listę sesji',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label': 'Otwórz oś czasu rozmowy',
|
'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label': 'Otwórz oś czasu rozmowy',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': 'Wprowadzanie głosowe',
|
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': 'Wprowadzanie głosowe',
|
||||||
'settings.projects.sidebar.total': 'Suma: {count}',
|
'settings.projects.sidebar.total': 'Suma: {count}',
|
||||||
|
|||||||
@@ -1109,6 +1109,7 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.keyboardShortcuts.error.exactConflict": "Esta combinação já é usada por {action}.",
|
"settings.openchamber.keyboardShortcuts.error.exactConflict": "Esta combinação já é usada por {action}.",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label": "Abrir seletor de projeto do rascunho",
|
"settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label": "Abrir seletor de projeto do rascunho",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label": "Abrir seletor de worktree do rascunho",
|
"settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label": "Abrir seletor de worktree do rascunho",
|
||||||
|
"settings.openchamber.keyboardShortcuts.action.open_session_list.label": "Abrir lista de sessões",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_dictation.label": "Entrada por voz",
|
"settings.openchamber.keyboardShortcuts.action.toggle_dictation.label": "Entrada por voz",
|
||||||
"settings.projects.sidebar.total": "Total {count}",
|
"settings.projects.sidebar.total": "Total {count}",
|
||||||
"settings.projects.sidebar.actions.addProject": "Adicionar projeto",
|
"settings.projects.sidebar.actions.addProject": "Adicionar projeto",
|
||||||
|
|||||||
@@ -1109,6 +1109,7 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.keyboardShortcuts.error.exactConflict": "Цю комбінацію вже використовує {action}.",
|
"settings.openchamber.keyboardShortcuts.error.exactConflict": "Цю комбінацію вже використовує {action}.",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label": "Відкрити вибір проєкту чернетки",
|
"settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label": "Відкрити вибір проєкту чернетки",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label": "Відкрити вибір worktree чернетки",
|
"settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label": "Відкрити вибір worktree чернетки",
|
||||||
|
"settings.openchamber.keyboardShortcuts.action.open_session_list.label": "Відкрити список сесій",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_dictation.label": "Голосове введення",
|
"settings.openchamber.keyboardShortcuts.action.toggle_dictation.label": "Голосове введення",
|
||||||
"settings.projects.sidebar.total": "Усього {count}",
|
"settings.projects.sidebar.total": "Усього {count}",
|
||||||
"settings.projects.sidebar.actions.addProject": "Додати проєкт",
|
"settings.projects.sidebar.actions.addProject": "Додати проєкт",
|
||||||
|
|||||||
@@ -1109,6 +1109,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.error.exactConflict': '此组合已被 {action} 使用。',
|
'settings.openchamber.keyboardShortcuts.error.exactConflict': '此组合已被 {action} 使用。',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '打开草稿项目选择器',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '打开草稿项目选择器',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '打开草稿工作树选择器',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '打开草稿工作树选择器',
|
||||||
|
'settings.openchamber.keyboardShortcuts.action.open_session_list.label': '打开会话列表',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '语音输入',
|
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '语音输入',
|
||||||
'settings.projects.sidebar.total': '总计 {count}',
|
'settings.projects.sidebar.total': '总计 {count}',
|
||||||
'settings.projects.sidebar.actions.addProject': '添加项目',
|
'settings.projects.sidebar.actions.addProject': '添加项目',
|
||||||
|
|||||||
@@ -1016,6 +1016,7 @@
|
|||||||
'settings.openchamber.keyboardShortcuts.error.exactConflict': '此組合已由 {action} 使用。',
|
'settings.openchamber.keyboardShortcuts.error.exactConflict': '此組合已由 {action} 使用。',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '開啟草稿專案選擇器',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label': '開啟草稿專案選擇器',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '開啟草稿 worktree 選擇器',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label': '開啟草稿 worktree 選擇器',
|
||||||
|
'settings.openchamber.keyboardShortcuts.action.open_session_list.label': '開啟工作階段列表',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '語音輸入',
|
'settings.openchamber.keyboardShortcuts.action.toggle_dictation.label': '語音輸入',
|
||||||
'settings.projects.sidebar.total': '總計 {count}',
|
'settings.projects.sidebar.total': '總計 {count}',
|
||||||
'settings.projects.sidebar.actions.addProject': '新增專案',
|
'settings.projects.sidebar.actions.addProject': '新增專案',
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Component interaction keys that are not application commands, such as list navig
|
|||||||
|
|
||||||
Bindings remain persisted as `Record<string, string>`. Each binding has one chord or at most two space-separated chords, such as `mod+s p`. `normalizeCombo`, `parseShortcut`, `formatShortcutForDisplay`, and `getShortcutConflict` provide the shared parsing and validation behavior. A single chord conflicts with a sequence sharing its first chord; sibling sequences are valid.
|
Bindings remain persisted as `Record<string, string>`. Each binding has one chord or at most two space-separated chords, such as `mod+s p`. `normalizeCombo`, `parseShortcut`, `formatShortcutForDisplay`, and `getShortcutConflict` provide the shared parsing and validation behavior. A single chord conflicts with a sequence sharing its first chord; sibling sequences are valid.
|
||||||
|
|
||||||
Contextual internal commands may deliberately share a sequence leader. The single-chord handler gets the first chance to handle the event; returning `false` lets the dispatcher start the sequence. The active file editor therefore owns `mod+s` for saving, while a mounted but unfocused editor yields `mod+s p` and `mod+s g` to the draft target pickers.
|
Contextual internal commands may deliberately share a sequence leader. The single-chord handler gets the first chance to handle the event; returning `false` lets the dispatcher start the sequence. The active file editor therefore owns `mod+s` for saving, while a mounted but unfocused editor yields `mod+s p`, `mod+s g`, and `mod+s l` to the draft target pickers and session list.
|
||||||
|
|
||||||
Runtime-specific commands may also share an exact binding when their handlers are mutually exclusive. `open_diff_panel` handles `mod+2` on desktop, while `switch_tab_2` handles it on mobile; each returns `false` outside its runtime so the dispatcher can try the next registered action.
|
Runtime-specific commands may also share an exact binding when their handlers are mutually exclusive. `open_diff_panel` handles `mod+2` on desktop, while `switch_tab_2` handles it on mobile; each returns `false` outside its runtime so the dispatcher can try the next registered action.
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,13 @@ const SHORTCUT_GROUPS = {
|
|||||||
settingsLabelKey:
|
settingsLabelKey:
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'open_session_list',
|
||||||
|
defaultBinding: 'mod+s l',
|
||||||
|
customizable: true,
|
||||||
|
settingsLabelKey:
|
||||||
|
'settings.openchamber.keyboardShortcuts.action.open_session_list.label',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'new_chat_worktree',
|
id: 'new_chat_worktree',
|
||||||
defaultBinding: 'mod+shift+n',
|
defaultBinding: 'mod+shift+n',
|
||||||
|
|||||||
@@ -48,9 +48,10 @@ describe('shortcut schema', () => {
|
|||||||
))).toBe(true);
|
))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('includes draft prefix bindings and session metadata', () => {
|
test('includes session prefix bindings and metadata', () => {
|
||||||
expect(getShortcutAction('open_draft_project_picker')?.defaultBinding).toBe('mod+s p');
|
expect(getShortcutAction('open_draft_project_picker')?.defaultBinding).toBe('mod+s p');
|
||||||
expect(getShortcutAction('open_draft_worktree_picker')?.defaultBinding).toBe('mod+s g');
|
expect(getShortcutAction('open_draft_worktree_picker')?.defaultBinding).toBe('mod+s g');
|
||||||
|
expect(getShortcutAction('open_session_list')?.defaultBinding).toBe('mod+s l');
|
||||||
expect(getShortcutAction('focus_input')?.category).toBe('session');
|
expect(getShortcutAction('focus_input')?.category).toBe('session');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user