feat(ui): redesign the default shortcut layout around a mod+k leader
Single chords stay for everyday actions; open/go actions move to two-step mod+k sequences; held mod+digit switches header session tabs and held mod+alt+digit switches context panel surfaces. Rare actions leave the shortcut schema for the command palette, every remaining action ships with a default binding, and stored overrides from the old layout reset once. Key matching now follows the physical key on non-Latin layouts and for Option-modified digits on macOS, including in the recording dialog.
This commit is contained in:
@@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
- **Faster session switching in large workspaces** (thanks @c-w-xiaohei): switching sessions no longer rebuilds the whole sidebar, returning to a recently viewed session restores its rendered messages instead of re-rendering them (file links included), and scrolling long conversations costs less. In a workspace with thousands of loaded sessions, end-to-end switch time dropped by roughly half.
|
- **Faster session switching in large workspaces** (thanks @c-w-xiaohei): switching sessions no longer rebuilds the whole sidebar, returning to a recently viewed session restores its rendered messages instead of re-rendering them (file links included), and scrolling long conversations costs less. In a workspace with thousands of loaded sessions, end-to-end switch time dropped by roughly half.
|
||||||
- **Session tabs (opt-in):** the web/desktop header can show your open sessions as browser-style tabs — turn them on in Settings → General → Navigation → Session tabs. Every session you open joins the strip, clicking a tab switches the whole workspace (chat, project, panels), and closing one (its × button, middle-click, or Alt+W — rebindable in Shortcuts) never touches the session itself. Tabs reorder by drag, scroll behind the header buttons when there are many and carry the sidebar's running/unread dot. Each tab has the full session menu — on the "..." button or right-click — plus Close other tabs; renaming works right in the tab.
|
- **Session tabs (opt-in):** the web/desktop header can show your open sessions as browser-style tabs — turn them on in Settings → General → Navigation → Session tabs. Every session you open joins the strip, clicking a tab switches the whole workspace (chat, project, panels), and closing one (its × button, middle-click, or Alt+W — rebindable in Shortcuts) never touches the session itself. Tabs reorder by drag, scroll behind the header buttons when there are many and carry the sidebar's running/unread dot. Each tab has the full session menu — on the "..." button or right-click — plus Close other tabs; renaming works right in the tab.
|
||||||
- **Keyboard shortcuts learned sequences** (thanks @ChangeHow): shortcuts can now be two steps — press Cmd/Ctrl+S, then a letter: P opens the draft's project picker, G its branch picker, L the session list. A held sequence shows no menu but forgives you: Escape or three quiet seconds cancel it, and typing into a text field never triggers one armed elsewhere. Dropdown menus and pickers now also answer Ctrl+N/Ctrl+P for down/up, the session switcher opens focused on your current session, and every tooltip and menu label shows the binding you actually have set, not the default.
|
- **Keyboard shortcuts learned sequences** (thanks @ChangeHow): shortcuts can now be two steps — press Cmd/Ctrl+S, then a letter: P opens the draft's project picker, G its branch picker, L the session list. A held sequence shows no menu but forgives you: Escape or three quiet seconds cancel it, and typing into a text field never triggers one armed elsewhere. Dropdown menus and pickers now also answer Ctrl+N/Ctrl+P for down/up, the session switcher opens focused on your current session, and every tooltip and menu label shows the binding you actually have set, not the default.
|
||||||
|
- **Keyboard shortcuts redesigned.** Defaults now follow one model: single chords for everyday actions, a two-step Cmd/Ctrl+K leader for open/go actions (K then P/G/L — project picker, branch picker, session list; T timeline, N prompt navigator, I services, H shortcut help, C theme), held Cmd/Ctrl+digit for header session tabs and held Cmd/Ctrl+Option+digit for context panel surfaces. Cmd/Ctrl+B now toggles the sidebar; when it's already open, the session-list shortcut jumps into its search. Rare actions moved into the command palette instead of carrying obscure default bindings, and custom bindings recorded under the old layout are reset once. Shortcuts also stopped requiring an English keyboard layout — bindings follow the physical key on non-Latin layouts (and Option-modified digits on macOS), including when recording custom ones.
|
||||||
- Chat: comment on a reply — select text in a chat message (or in a rendered markdown preview in Files) and choose Comment to attach exactly that quote, with a source line range when it can be located, plus your note to the next message. The selection stays highlighted while you type, and the selection menu was restyled — Add to chat is now Add to input.
|
- Chat: comment on a reply — select text in a chat message (or in a rendered markdown preview in Files) and choose Comment to attach exactly that quote, with a source line range when it can be located, plus your note to the next message. The selection stays highlighted while you type, and the selection menu was restyled — Add to chat is now Add to input.
|
||||||
- Diff: comment like a review — hovering a line shows a + button in the gutter; clicking it, clicking a line, or dragging across lines opens the comment editor for that line or range. The comment editor and saved-comment cards match the chat's comment style.
|
- Diff: comment like a review — hovering a line shows a + button in the gutter; clicking it, clicking a line, or dragging across lines opens the comment editor for that line or range. The comment editor and saved-comment cards match the chat's comment style.
|
||||||
- Composer: hovering or tapping a context chip above the input opens a stacked preview of everything attached, where a comment can be edited in place or an item removed before sending.
|
- Composer: hovering or tapping a context chip above the input opens a stacked preview of everything attached, where a comment can be edited in place or an item removed before sending.
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import { useAgentMemorySync } from '@/hooks/useAgentMemorySync';
|
|||||||
import { usePwaInstallPrompt } from '@/hooks/usePwaInstallPrompt';
|
import { usePwaInstallPrompt } from '@/hooks/usePwaInstallPrompt';
|
||||||
import { useWindowTitle } from '@/hooks/useWindowTitle';
|
import { useWindowTitle } from '@/hooks/useWindowTitle';
|
||||||
import { useConfigStore } from '@/stores/useConfigStore';
|
import { useConfigStore } from '@/stores/useConfigStore';
|
||||||
import { useKeybind } from '@/hooks/useKeybind';
|
|
||||||
import { isDesktopLocalOriginActive, isDesktopShell, restartDesktopApp, invokeDesktop } from '@/lib/desktop';
|
import { isDesktopLocalOriginActive, isDesktopShell, restartDesktopApp, invokeDesktop } from '@/lib/desktop';
|
||||||
import {
|
import {
|
||||||
getInjectedBootOutcome,
|
getInjectedBootOutcome,
|
||||||
@@ -723,10 +722,13 @@ function App({ apis }: AppProps) {
|
|||||||
|
|
||||||
useSessionStatusBootstrap({ enabled: embeddedBackgroundWorkEnabled });
|
useSessionStatusBootstrap({ enabled: embeddedBackgroundWorkEnabled });
|
||||||
|
|
||||||
useKeybind('toggle_memory_debug', () => {
|
// Palette-only action: the memory debug panel has no keyboard shortcut.
|
||||||
if (embeddedSessionChat) return false;
|
React.useEffect(() => {
|
||||||
setShowMemoryDebug((previous) => !previous);
|
if (embeddedSessionChat) return;
|
||||||
});
|
const handleToggle = () => setShowMemoryDebug((previous) => !previous);
|
||||||
|
window.addEventListener('openchamber:memory-debug-toggle', handleToggle);
|
||||||
|
return () => window.removeEventListener('openchamber:memory-debug-toggle', handleToggle);
|
||||||
|
}, [embeddedSessionChat]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (embeddedSessionChat) {
|
if (embeddedSessionChat) {
|
||||||
|
|||||||
@@ -1471,17 +1471,6 @@ export const Header: React.FC = () => {
|
|||||||
setIsDesktopServicesOpen(true);
|
setIsDesktopServicesOpen(true);
|
||||||
void refreshCurrentInstanceLabel();
|
void refreshCurrentInstanceLabel();
|
||||||
},
|
},
|
||||||
// The desktop menu holds one destination now, so this shortcut opens it
|
|
||||||
// rather than cycling. The binding is kept: it is user-configurable and
|
|
||||||
// silently dropping it would break existing setups.
|
|
||||||
cycle_services_tab: () => {
|
|
||||||
if (servicesTabs.length === 0) return false;
|
|
||||||
setIsDesktopServicesOpen(true);
|
|
||||||
void refreshCurrentInstanceLabel();
|
|
||||||
},
|
|
||||||
toggle_context_plan: () => {
|
|
||||||
handleOpenContextPlan();
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const desktopSidebarActions = (
|
const desktopSidebarActions = (
|
||||||
|
|||||||
@@ -53,17 +53,19 @@ export const KeyboardShortcutsSettings: React.FC = () => {
|
|||||||
persist(nextOverrides);
|
persist(nextOverrides);
|
||||||
};
|
};
|
||||||
const shortcutDisplay = (action: CustomizableShortcutAction): string => {
|
const shortcutDisplay = (action: CustomizableShortcutAction): string => {
|
||||||
const isSurfaceSwitch = action.id === 'switch_context_surface';
|
const isPrefixStyle = 'prefixStyle' in action && action.prefixStyle;
|
||||||
const combo = isSurfaceSwitch
|
const combo = isPrefixStyle
|
||||||
? getEffectiveShortcutPrefix(action.id, shortcutOverrides)
|
? getEffectiveShortcutPrefix(action.id, shortcutOverrides)
|
||||||
: getEffectiveShortcutCombo(action.id, shortcutOverrides);
|
: getEffectiveShortcutCombo(action.id, shortcutOverrides);
|
||||||
const formatted = formatShortcutForDisplay(
|
const formatted = formatShortcutForDisplay(
|
||||||
combo,
|
combo,
|
||||||
t('settings.openchamber.keyboardShortcuts.unassigned'),
|
t('settings.openchamber.keyboardShortcuts.unassigned'),
|
||||||
);
|
);
|
||||||
return isSurfaceSwitch && combo && combo !== UNASSIGNED_SHORTCUT
|
if (!isPrefixStyle || !combo || combo === UNASSIGNED_SHORTCUT) return formatted;
|
||||||
? `${formatted}${t('settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix')}`
|
const suffix = action.id === 'switch_session_tab'
|
||||||
: formatted;
|
? t('settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix')
|
||||||
|
: t('settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix');
|
||||||
|
return `${formatted}${suffix}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -104,15 +106,17 @@ export const KeyboardShortcutsSettings: React.FC = () => {
|
|||||||
>
|
>
|
||||||
{t('settings.openchamber.keyboardShortcuts.actions.edit')}
|
{t('settings.openchamber.keyboardShortcuts.actions.edit')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
{action.id in shortcutOverrides ? (
|
||||||
type="button"
|
<Button
|
||||||
variant="ghost"
|
type="button"
|
||||||
size="xs"
|
variant="ghost"
|
||||||
className="!font-normal"
|
size="xs"
|
||||||
onClick={() => resetOne(action.id)}
|
className="!font-normal"
|
||||||
>
|
onClick={() => resetOne(action.id)}
|
||||||
{t('settings.common.actions.reset')}
|
>
|
||||||
</Button>
|
{t('settings.common.actions.reset')}
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
</SettingsFieldRow>
|
</SettingsFieldRow>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import { settleShortcutRecordingState, updateShortcutRecordingState } from './Sh
|
|||||||
const emptyState = { chords: [], livePreview: null, settled: false };
|
const emptyState = { chords: [], livePreview: null, settled: false };
|
||||||
|
|
||||||
function keyEvent(key: string, modifiers: Partial<Record<'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey', boolean>> = {}) {
|
function keyEvent(key: string, modifiers: Partial<Record<'altKey' | 'ctrlKey' | 'metaKey' | 'shiftKey', boolean>> = {}) {
|
||||||
return { key, repeat: false, isComposing: false, altKey: false, ctrlKey: false, metaKey: false, shiftKey: false, ...modifiers };
|
const code = /^[a-z]$/i.test(key) ? `Key${key.toUpperCase()}` : /^[0-9]$/.test(key) ? `Digit${key}` : key;
|
||||||
|
return { key, code, repeat: false, isComposing: false, altKey: false, ctrlKey: false, metaKey: false, shiftKey: false, ...modifiers };
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('ShortcutRecordingDialog recording state', () => {
|
describe('ShortcutRecordingDialog recording state', () => {
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import {
|
|||||||
getShortcutBindingConflicts,
|
getShortcutBindingConflicts,
|
||||||
isRiskyBrowserShortcut,
|
isRiskyBrowserShortcut,
|
||||||
keyToShortcutToken,
|
keyToShortcutToken,
|
||||||
|
resolveShortcutEventKey,
|
||||||
normalizeCombo,
|
normalizeCombo,
|
||||||
type ShortcutActionId,
|
type ShortcutActionId,
|
||||||
type ShortcutBindingConflict,
|
type ShortcutBindingConflict,
|
||||||
@@ -27,6 +28,7 @@ const SECOND_CHORD_TIMEOUT_MS = 3000;
|
|||||||
|
|
||||||
interface RecordingKeyboardEvent {
|
interface RecordingKeyboardEvent {
|
||||||
altKey: boolean;
|
altKey: boolean;
|
||||||
|
code: string;
|
||||||
ctrlKey: boolean;
|
ctrlKey: boolean;
|
||||||
isComposing: boolean;
|
isComposing: boolean;
|
||||||
key: string;
|
key: string;
|
||||||
@@ -84,7 +86,7 @@ function keyboardEventToCombo(event: RecordingKeyboardEvent): ShortcutCombo | nu
|
|||||||
if (MODIFIER_KEYS.has(event.key.toLowerCase())) return null;
|
if (MODIFIER_KEYS.has(event.key.toLowerCase())) return null;
|
||||||
if (getPhysicalKeyCount(event, true) > MAX_SHORTCUT_KEY_COUNT) return null;
|
if (getPhysicalKeyCount(event, true) > MAX_SHORTCUT_KEY_COUNT) return null;
|
||||||
|
|
||||||
const key = keyToShortcutToken(event.key);
|
const key = keyToShortcutToken(resolveShortcutEventKey(event));
|
||||||
if (!key) return null;
|
if (!key) return null;
|
||||||
|
|
||||||
const parts: string[] = [];
|
const parts: string[] = [];
|
||||||
@@ -200,7 +202,8 @@ export const ShortcutRecordingDialog: React.FC<ShortcutRecordingDialogProps> = (
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
if (phase === 'keyup' && action?.id === 'switch_context_surface' && recording.chords.length === 0) {
|
const isPrefixStyleAction = Boolean(action && 'prefixStyle' in action && action.prefixStyle);
|
||||||
|
if (phase === 'keyup' && isPrefixStyleAction && recording.chords.length === 0) {
|
||||||
const modifierCombo = modifierKeyUpToCombo(event);
|
const modifierCombo = modifierKeyUpToCombo(event);
|
||||||
if (modifierCombo) {
|
if (modifierCombo) {
|
||||||
setRecording({ chords: [modifierCombo], livePreview: null, settled: true });
|
setRecording({ chords: [modifierCombo], livePreview: null, settled: true });
|
||||||
@@ -209,6 +212,7 @@ export const ShortcutRecordingDialog: React.FC<ShortcutRecordingDialogProps> = (
|
|||||||
}
|
}
|
||||||
const nextRecording = updateShortcutRecordingState(recording, {
|
const nextRecording = updateShortcutRecordingState(recording, {
|
||||||
altKey: event.altKey,
|
altKey: event.altKey,
|
||||||
|
code: event.nativeEvent.code,
|
||||||
ctrlKey: event.ctrlKey,
|
ctrlKey: event.ctrlKey,
|
||||||
isComposing: event.nativeEvent.isComposing,
|
isComposing: event.nativeEvent.isComposing,
|
||||||
key: event.key,
|
key: event.key,
|
||||||
@@ -216,7 +220,7 @@ export const ShortcutRecordingDialog: React.FC<ShortcutRecordingDialogProps> = (
|
|||||||
repeat: event.repeat,
|
repeat: event.repeat,
|
||||||
shiftKey: event.shiftKey,
|
shiftKey: event.shiftKey,
|
||||||
}, phase);
|
}, phase);
|
||||||
setRecording(action?.id === 'switch_context_surface' && nextRecording.chords.length > 1
|
setRecording(isPrefixStyleAction && nextRecording.chords.length > 1
|
||||||
? recording
|
? recording
|
||||||
: nextRecording);
|
: nextRecording);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,6 +26,21 @@ export const useSessionSearchEffects = ({
|
|||||||
return () => window.cancelAnimationFrame(raf);
|
return () => window.cancelAnimationFrame(raf);
|
||||||
}, [enabled, isSessionSearchOpen, sessionSearchInputRef]);
|
}, [enabled, isSessionSearchOpen, sessionSearchInputRef]);
|
||||||
|
|
||||||
|
// The open_session_list shortcut lands here when the sidebar is visible:
|
||||||
|
// the session list is already on screen, so the shortcut opens its search.
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!enabled || typeof window === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const handleOpenRequest = () => {
|
||||||
|
setIsSessionSearchOpen(true);
|
||||||
|
sessionSearchInputRef.current?.focus();
|
||||||
|
sessionSearchInputRef.current?.select();
|
||||||
|
};
|
||||||
|
window.addEventListener('openchamber:sidebar-session-search', handleOpenRequest);
|
||||||
|
return () => window.removeEventListener('openchamber:sidebar-session-search', handleOpenRequest);
|
||||||
|
}, [enabled, setIsSessionSearchOpen, sessionSearchInputRef]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!enabled || !isSessionSearchOpen || typeof document === 'undefined') {
|
if (!enabled || !isSessionSearchOpen || typeof document === 'undefined') {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ import { toast } from '@/components/ui';
|
|||||||
import { FileTypeIcon } from '@/components/icons/FileTypeIcon';
|
import { FileTypeIcon } from '@/components/icons/FileTypeIcon';
|
||||||
import type { Session } from '@opencode-ai/sdk/v2';
|
import type { Session } from '@opencode-ai/sdk/v2';
|
||||||
import { createWorktreeSession } from '@/lib/worktreeSessionCreator';
|
import { createWorktreeSession } from '@/lib/worktreeSessionCreator';
|
||||||
import { formatShortcutForDisplay, getEffectiveShortcutCombo } from '@/lib/shortcuts';
|
import { formatShortcutForDisplay, getEffectiveShortcutCombo, shortcutRegistry } from '@/lib/shortcuts';
|
||||||
|
import { showOpenCodeStatus } from '@/lib/openCodeStatus';
|
||||||
import { canUseElectronDesktopIPC, invokeDesktop, isDesktopShell, isVSCodeRuntime, isWebRuntime } from '@/lib/desktop';
|
import { canUseElectronDesktopIPC, invokeDesktop, isDesktopShell, isVSCodeRuntime, isWebRuntime } from '@/lib/desktop';
|
||||||
import { SETTINGS_PAGE_METADATA, type SettingsRuntimeContext } from '@/lib/settings/metadata';
|
import { SETTINGS_PAGE_METADATA, type SettingsRuntimeContext } from '@/lib/settings/metadata';
|
||||||
|
|
||||||
@@ -230,6 +231,25 @@ export const CommandPalette: React.FC = () => {
|
|||||||
if (currentDirectory) openContextOverview(currentDirectory);
|
if (currentDirectory) openContextOverview(currentDirectory);
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'cycle-theme',
|
||||||
|
title: t('commandPalette.item.cycleTheme'),
|
||||||
|
icon: <Icon name="palette" className="mr-2 h-4 w-4" />,
|
||||||
|
shortcutId: 'cycle_theme',
|
||||||
|
searchText: t('commandPalette.item.cycleTheme'),
|
||||||
|
onSelect: run(() => {
|
||||||
|
shortcutRegistry.invoke('cycle_theme');
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'open-status',
|
||||||
|
title: t('commandPalette.item.showOpenCodeStatus'),
|
||||||
|
icon: <Icon name="pulse" className="mr-2 h-4 w-4" />,
|
||||||
|
searchText: t('commandPalette.item.showOpenCodeStatus'),
|
||||||
|
onSelect: run(() => {
|
||||||
|
void showOpenCodeStatus();
|
||||||
|
}),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'open-settings',
|
id: 'open-settings',
|
||||||
title: t('commandPalette.item.openSettings'),
|
title: t('commandPalette.item.openSettings'),
|
||||||
@@ -239,6 +259,15 @@ export const CommandPalette: React.FC = () => {
|
|||||||
onSelect: run(() => setSettingsDialogOpen(true)),
|
onSelect: run(() => setSettingsDialogOpen(true)),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
list.push({
|
||||||
|
id: 'toggle-memory-debug',
|
||||||
|
title: t('commandPalette.item.toggleMemoryDebug'),
|
||||||
|
icon: <Icon name="bug" className="mr-2 h-4 w-4" />,
|
||||||
|
searchText: t('commandPalette.item.toggleMemoryDebug'),
|
||||||
|
onSelect: run(() => {
|
||||||
|
window.dispatchEvent(new CustomEvent('openchamber:memory-debug-toggle'));
|
||||||
|
}),
|
||||||
|
});
|
||||||
if (canUseElectronDesktopIPC()) {
|
if (canUseElectronDesktopIPC()) {
|
||||||
list.splice(1, 0, {
|
list.splice(1, 0, {
|
||||||
id: 'new-mini-chat',
|
id: 'new-mini-chat',
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { Icon } from "@/components/icon/Icon";
|
|||||||
import { useUIStore } from "@/stores/useUIStore";
|
import { useUIStore } from "@/stores/useUIStore";
|
||||||
import {
|
import {
|
||||||
getEffectiveShortcutCombo,
|
getEffectiveShortcutCombo,
|
||||||
|
getEffectiveShortcutPrefix,
|
||||||
getShortcutAction,
|
getShortcutAction,
|
||||||
formatShortcutForDisplay,
|
formatShortcutForDisplay,
|
||||||
type ShortcutActionId,
|
type ShortcutActionId,
|
||||||
@@ -156,24 +157,6 @@ export const HelpDialog: React.FC = () => {
|
|||||||
{
|
{
|
||||||
categoryKey: "helpDialog.section.panels",
|
categoryKey: "helpDialog.section.panels",
|
||||||
items: [
|
items: [
|
||||||
{
|
|
||||||
id: 'toggle_right_sidebar',
|
|
||||||
descriptionKey: 'helpDialog.item.toggleRightSidebar',
|
|
||||||
icon: "layout-right",
|
|
||||||
keys: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'open_right_sidebar_git',
|
|
||||||
descriptionKey: 'helpDialog.item.openRightSidebarGitTab',
|
|
||||||
icon: "git-branch",
|
|
||||||
keys: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'open_right_sidebar_files',
|
|
||||||
descriptionKey: 'helpDialog.item.openRightSidebarFilesTab',
|
|
||||||
icon: "layout-right",
|
|
||||||
keys: '',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'toggle_terminal',
|
id: 'toggle_terminal',
|
||||||
descriptionKey: 'helpDialog.item.toggleTerminalDock',
|
descriptionKey: 'helpDialog.item.toggleTerminalDock',
|
||||||
@@ -187,14 +170,13 @@ export const HelpDialog: React.FC = () => {
|
|||||||
keys: '',
|
keys: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'toggle_context_plan',
|
keys: [`${formatShortcutForDisplay(getEffectiveShortcutPrefix('switch_context_surface', shortcutOverrides))} + 1...0`],
|
||||||
descriptionKey: 'helpDialog.item.togglePlanContextPanel',
|
descriptionKey: "helpDialog.item.switchContextSurface",
|
||||||
icon: "time",
|
icon: "layout-right",
|
||||||
keys: '',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: [`${formatShortcutForDisplay('mod')} + 1...0`],
|
keys: [`${formatShortcutForDisplay(getEffectiveShortcutPrefix('switch_session_tab', shortcutOverrides))} + 1...9`],
|
||||||
descriptionKey: "helpDialog.item.switchContextSurface",
|
descriptionKey: "helpDialog.item.switchSessionTab",
|
||||||
icon: "layout-right",
|
icon: "layout-right",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -214,12 +196,6 @@ export const HelpDialog: React.FC = () => {
|
|||||||
icon: "stack",
|
icon: "stack",
|
||||||
keys: '',
|
keys: '',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'cycle_services_tab',
|
|
||||||
descriptionKey: 'helpDialog.item.cycleServicesTab',
|
|
||||||
icon: "stack",
|
|
||||||
keys: '',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'open_settings',
|
id: 'open_settings',
|
||||||
descriptionKey: "helpDialog.item.openSettings",
|
descriptionKey: "helpDialog.item.openSettings",
|
||||||
@@ -258,6 +234,12 @@ export const HelpDialog: React.FC = () => {
|
|||||||
const descriptionKey = shortcut.descriptionKey
|
const descriptionKey = shortcut.descriptionKey
|
||||||
?? (action?.customizable ? action.settingsLabelKey : undefined);
|
?? (action?.customizable ? action.settingsLabelKey : undefined);
|
||||||
if (!descriptionKey) return null;
|
if (!descriptionKey) return null;
|
||||||
|
// This dialog lists what the keyboard can do right now;
|
||||||
|
// an action without a binding belongs to the command
|
||||||
|
// palette and Settings, not here.
|
||||||
|
if (shortcut.id && !getEffectiveShortcutCombo(shortcut.id, shortcutOverrides)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const displayKeys = shortcut.id
|
const displayKeys = shortcut.id
|
||||||
? renderShortcut(
|
? renderShortcut(
|
||||||
shortcut.id,
|
shortcut.id,
|
||||||
@@ -320,7 +302,7 @@ export const HelpDialog: React.FC = () => {
|
|||||||
• {t('helpDialog.proTips.recentSessions')}
|
• {t('helpDialog.proTips.recentSessions')}
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
• {t('helpDialog.proTips.themeCycling')}
|
• {t('helpDialog.proTips.leaderSequences')}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,16 +2,18 @@ import type React from 'react';
|
|||||||
|
|
||||||
import { isIMECompositionEvent } from '@/lib/ime';
|
import { isIMECompositionEvent } from '@/lib/ime';
|
||||||
|
|
||||||
function getDropdownNavigationKey(event: Pick<KeyboardEvent, 'key' | 'ctrlKey' | 'metaKey' | 'altKey' | 'shiftKey'>): 'ArrowDown' | 'ArrowUp' | null {
|
function getDropdownNavigationKey(event: Pick<KeyboardEvent, 'key' | 'code' | 'ctrlKey' | 'metaKey' | 'altKey' | 'shiftKey'>): 'ArrowDown' | 'ArrowUp' | null {
|
||||||
if (!event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) return null;
|
if (!event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) return null;
|
||||||
if (event.key.toLowerCase() === 'n') return 'ArrowDown';
|
// `code` covers non-Latin layouts, where `key` is the layout's own letter.
|
||||||
if (event.key.toLowerCase() === 'p') return 'ArrowUp';
|
if (event.key.toLowerCase() === 'n' || event.code === 'KeyN') return 'ArrowDown';
|
||||||
|
if (event.key.toLowerCase() === 'p' || event.code === 'KeyP') return 'ArrowUp';
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
type DropdownNavigationEvent = Pick<
|
type DropdownNavigationEvent = Pick<
|
||||||
React.KeyboardEvent<HTMLElement>,
|
React.KeyboardEvent<HTMLElement>,
|
||||||
| 'altKey'
|
| 'altKey'
|
||||||
|
| 'code'
|
||||||
| 'ctrlKey'
|
| 'ctrlKey'
|
||||||
| 'defaultPrevented'
|
| 'defaultPrevented'
|
||||||
| 'isPropagationStopped'
|
| 'isPropagationStopped'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { isTerminalEventTarget } from '@/lib/terminalFocus';
|
import { isTerminalEventTarget } from '@/lib/terminalFocus';
|
||||||
import { useSessionUIStore } from '@/sync/session-ui-store';
|
import { useSessionUIStore } from '@/sync/session-ui-store';
|
||||||
import { closeSessionTabAndActivateNeighbour } from '@/lib/sessionTabs';
|
import { activateSessionTabByIndex, closeSessionTabAndActivateNeighbour } from '@/lib/sessionTabs';
|
||||||
import { useSelectionStore } from '@/sync/selection-store';
|
import { useSelectionStore } from '@/sync/selection-store';
|
||||||
import * as sessionActions from '@/sync/session-actions';
|
import * as sessionActions from '@/sync/session-actions';
|
||||||
import { normalizeContextPanelDirectoryKey, useUIStore } from '@/stores/useUIStore';
|
import { normalizeContextPanelDirectoryKey, useUIStore } from '@/stores/useUIStore';
|
||||||
@@ -11,13 +11,14 @@ import { useKeybinds } from '@/hooks/useKeybind';
|
|||||||
import { createWorktreeSession } from '@/lib/worktreeSessionCreator';
|
import { createWorktreeSession } from '@/lib/worktreeSessionCreator';
|
||||||
import { useConfigStore } from '@/stores/useConfigStore';
|
import { useConfigStore } from '@/stores/useConfigStore';
|
||||||
import { canUseElectronDesktopIPC, invokeDesktop, isVSCodeRuntime } from '@/lib/desktop';
|
import { canUseElectronDesktopIPC, invokeDesktop, isVSCodeRuntime } from '@/lib/desktop';
|
||||||
import { showOpenCodeStatus } from '@/lib/openCodeStatus';
|
|
||||||
import {
|
import {
|
||||||
eventMatchesShortcut,
|
eventMatchesShortcut,
|
||||||
eventMatchesShortcutPrefix,
|
eventMatchesShortcutPrefix,
|
||||||
getEffectiveShortcutCombo,
|
getEffectiveShortcutCombo,
|
||||||
getEffectiveShortcutPrefix,
|
getEffectiveShortcutPrefix,
|
||||||
normalizeCombo,
|
normalizeCombo,
|
||||||
|
resolveShortcutEventDigit,
|
||||||
|
resolveShortcutEventKey,
|
||||||
ShortcutDispatcher,
|
ShortcutDispatcher,
|
||||||
shortcutRegistry,
|
shortcutRegistry,
|
||||||
type ShortcutActionId,
|
type ShortcutActionId,
|
||||||
@@ -123,8 +124,18 @@ export const useKeyboardShortcuts = () => {
|
|||||||
},
|
},
|
||||||
open_session_list: () => {
|
open_session_list: () => {
|
||||||
const state = useUIStore.getState();
|
const state = useUIStore.getState();
|
||||||
if (state.isMobile) state.setSessionSwitcherOpen(true);
|
if (state.isMobile) {
|
||||||
else state.setSessionDropdownOpen(true);
|
state.setSessionSwitcherOpen(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The switcher dropdown only mounts while the sidebar is collapsed;
|
||||||
|
// with the sidebar visible the list is already on screen, so the
|
||||||
|
// shortcut opens the sidebar's session search instead.
|
||||||
|
if (state.isSidebarOpen) {
|
||||||
|
window.dispatchEvent(new CustomEvent('openchamber:sidebar-session-search'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.setSessionDropdownOpen(true);
|
||||||
},
|
},
|
||||||
toggle_prompt_navigator: () => {
|
toggle_prompt_navigator: () => {
|
||||||
const state = useUIStore.getState();
|
const state = useUIStore.getState();
|
||||||
@@ -146,9 +157,6 @@ export const useKeyboardShortcuts = () => {
|
|||||||
}
|
}
|
||||||
state.togglePromptNavigatorPanel();
|
state.togglePromptNavigatorPanel();
|
||||||
},
|
},
|
||||||
open_status: () => {
|
|
||||||
void showOpenCodeStatus();
|
|
||||||
},
|
|
||||||
open_help: () => {
|
open_help: () => {
|
||||||
useUIStore.getState().toggleHelpDialog();
|
useUIStore.getState().toggleHelpDialog();
|
||||||
},
|
},
|
||||||
@@ -230,25 +238,6 @@ export const useKeyboardShortcuts = () => {
|
|||||||
useSelectionStore.getState().saveSessionAgentSelection(sessionId, next);
|
useSelectionStore.getState().saveSessionAgentSelection(sessionId, next);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
toggle_right_sidebar: () => {
|
|
||||||
const state = useUIStore.getState();
|
|
||||||
if (state.isMobile || !currentDirectory) return false;
|
|
||||||
const directory = normalizeContextPanelDirectoryKey(currentDirectory);
|
|
||||||
const panel = state.contextPanelByDirectory[directory];
|
|
||||||
if (panel?.isOpen) state.closeContextPanel(directory);
|
|
||||||
else if (panel?.activeTabId) state.setActiveContextPanelTab(directory, panel.activeTabId);
|
|
||||||
else state.openContextSurface(directory, 'git');
|
|
||||||
},
|
|
||||||
open_right_sidebar_git: () => {
|
|
||||||
const state = useUIStore.getState();
|
|
||||||
if (state.isMobile || !currentDirectory) return false;
|
|
||||||
state.openContextSurface(normalizeContextPanelDirectoryKey(currentDirectory), 'git');
|
|
||||||
},
|
|
||||||
open_right_sidebar_files: () => {
|
|
||||||
const state = useUIStore.getState();
|
|
||||||
if (state.isMobile || !currentDirectory) return false;
|
|
||||||
state.openContextSurface(normalizeContextPanelDirectoryKey(currentDirectory), 'file');
|
|
||||||
},
|
|
||||||
toggle_terminal: () => {
|
toggle_terminal: () => {
|
||||||
if (useUIStore.getState().isMobile) return false;
|
if (useUIStore.getState().isMobile) return false;
|
||||||
return toggleTerminalSurface();
|
return toggleTerminalSurface();
|
||||||
@@ -482,8 +471,9 @@ export const useKeyboardShortcuts = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const switchSurfaceDigit = event.key.length === 1 && event.key >= '0' && event.key <= '9'
|
const rawDigit = resolveShortcutEventDigit(event);
|
||||||
? (event.key === '0' ? 10 : Number(event.key))
|
const switchSurfaceDigit = rawDigit !== null
|
||||||
|
? (rawDigit === '0' ? 10 : Number(rawDigit))
|
||||||
: null;
|
: null;
|
||||||
const switchSurfacePrefix = getEffectiveShortcutPrefix(
|
const switchSurfacePrefix = getEffectiveShortcutPrefix(
|
||||||
'switch_context_surface',
|
'switch_context_surface',
|
||||||
@@ -514,13 +504,32 @@ export const useKeyboardShortcuts = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sessionTabDigit = rawDigit !== null && rawDigit !== '0' ? Number(rawDigit) : null;
|
||||||
|
if (
|
||||||
|
sessionTabDigit !== null
|
||||||
|
&& !event.repeat
|
||||||
|
&& !isVSCodeRuntime()
|
||||||
|
&& useUIStore.getState().sessionTabsEnabled
|
||||||
|
&& eventMatchesShortcutPrefix(
|
||||||
|
event,
|
||||||
|
getEffectiveShortcutPrefix('switch_session_tab', useUIStore.getState().shortcutOverrides),
|
||||||
|
heldKeysRef.current,
|
||||||
|
)
|
||||||
|
&& activateSessionTabByIndex(sessionTabDigit - 1)
|
||||||
|
) {
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (dispatcher.dispatch(event)) event.preventDefault();
|
if (dispatcher.dispatch(event)) event.preventDefault();
|
||||||
};
|
};
|
||||||
const handleKeyHoldDown = (event: KeyboardEvent) => {
|
const handleKeyHoldDown = (event: KeyboardEvent) => {
|
||||||
heldKeysRef.current.add(event.key.toLowerCase());
|
heldKeysRef.current.add(event.key.toLowerCase());
|
||||||
|
heldKeysRef.current.add(resolveShortcutEventKey(event).toLowerCase());
|
||||||
};
|
};
|
||||||
const handleKeyUp = (event: KeyboardEvent) => {
|
const handleKeyUp = (event: KeyboardEvent) => {
|
||||||
heldKeysRef.current.delete(event.key.toLowerCase());
|
heldKeysRef.current.delete(event.key.toLowerCase());
|
||||||
|
heldKeysRef.current.delete(resolveShortcutEventKey(event).toLowerCase());
|
||||||
};
|
};
|
||||||
const handleBlur = () => {
|
const handleBlur = () => {
|
||||||
heldKeysRef.current.clear();
|
heldKeysRef.current.clear();
|
||||||
|
|||||||
@@ -1080,9 +1080,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'Terminal erweitert umschalten',
|
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'Terminal erweitert umschalten',
|
||||||
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Auswahl zum Chat hinzufügen',
|
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Auswahl zum Chat hinzufügen',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Seitenleiste umschalten',
|
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Seitenleiste umschalten',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': 'Rechte Seitenleiste umschalten',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.label': 'Sitzungs-Tab wechseln',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Git-Tab der rechten Seitenleiste öffnen',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix': ' + 1…9',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label': 'Datei-Tab der rechten Seitenleiste öffnen',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': 'Kontextpanel-Oberfläche wechseln',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': 'Kontextpanel-Oberfläche wechseln',
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_chat.label': 'Neue Sitzung',
|
'settings.openchamber.keyboardShortcuts.action.new_chat.label': 'Neue Sitzung',
|
||||||
@@ -1090,9 +1089,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': 'Neuer Worktree-Entwurf',
|
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': 'Neuer Worktree-Entwurf',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': 'Neues Mini-Chat-Fenster',
|
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': 'Neues Mini-Chat-Fenster',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_help.label': 'Tastenkürzel öffnen',
|
'settings.openchamber.keyboardShortcuts.action.open_help.label': 'Tastenkürzel öffnen',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label': 'Plan-Kontextpanel umschalten',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'Dienstemenü umschalten',
|
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'Dienstemenü umschalten',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': 'Dienste-Tab durchschalten',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'Thema wechseln',
|
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'Thema wechseln',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Agent wechseln',
|
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Agent wechseln',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'Favorites Modell vorwärts durchschalten',
|
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'Favorites Modell vorwärts durchschalten',
|
||||||
|
|||||||
@@ -1684,22 +1684,18 @@ export const dict = {
|
|||||||
'helpDialog.item.focusChatInput': 'Chat-Eingabe fokussieren',
|
'helpDialog.item.focusChatInput': 'Chat-Eingabe fokussieren',
|
||||||
'helpDialog.item.togglePromptNavigator': 'Aufforderungs-Navigator umschalten',
|
'helpDialog.item.togglePromptNavigator': 'Aufforderungs-Navigator umschalten',
|
||||||
'helpDialog.item.abortActiveRun': 'Aktuelle Ausführung abbrechen (Doppeltaste)',
|
'helpDialog.item.abortActiveRun': 'Aktuelle Ausführung abbrechen (Doppeltaste)',
|
||||||
'helpDialog.item.toggleRightSidebar': 'Rechte Seitenleiste umschalten',
|
|
||||||
'helpDialog.item.openRightSidebarGitTab': 'Git-Registerkarte der rechten Seitenleiste öffnen',
|
|
||||||
'helpDialog.item.openRightSidebarFilesTab': 'Datei-Registerkarte der rechten Seitenleiste öffnen',
|
|
||||||
'helpDialog.item.toggleTerminalDock': 'Terminal-Dock umschalten',
|
'helpDialog.item.toggleTerminalDock': 'Terminal-Dock umschalten',
|
||||||
'helpDialog.item.toggleTerminalExpanded': 'Terminal erweitert umschalten',
|
'helpDialog.item.toggleTerminalExpanded': 'Terminal erweitert umschalten',
|
||||||
'helpDialog.item.togglePlanContextPanel': 'Plan-Kontext-Panel umschalten',
|
|
||||||
'helpDialog.item.cycleTheme': 'Thema wechseln (Hell → Dunkel → System)',
|
'helpDialog.item.cycleTheme': 'Thema wechseln (Hell → Dunkel → System)',
|
||||||
|
'helpDialog.item.switchSessionTab': 'Sitzungs-Tab wechseln',
|
||||||
'helpDialog.item.switchContextSurface': 'Kontextpanel-Oberfläche wechseln (Zahlentaste)',
|
'helpDialog.item.switchContextSurface': 'Kontextpanel-Oberfläche wechseln (Zahlentaste)',
|
||||||
'helpDialog.item.toggleServicesMenu': 'Dienstemenü umschalten',
|
'helpDialog.item.toggleServicesMenu': 'Dienstemenü umschalten',
|
||||||
'helpDialog.item.cycleServicesTab': 'Dienste-Registerkarte durchgehen',
|
|
||||||
'helpDialog.item.openSettings': 'Einstellungen öffnen',
|
'helpDialog.item.openSettings': 'Einstellungen öffnen',
|
||||||
'helpDialog.keyCombiner.or': 'oder',
|
'helpDialog.keyCombiner.or': 'oder',
|
||||||
'helpDialog.proTips.title': 'Pro-Tipps:',
|
'helpDialog.proTips.title': 'Pro-Tipps:',
|
||||||
'helpDialog.proTips.commandPalette': 'Verwenden Sie die Befehlspalette ({shortcut}), um schnell auf alle Aktionen zuzugreifen',
|
'helpDialog.proTips.commandPalette': 'Verwenden Sie die Befehlspalette ({shortcut}), um schnell auf alle Aktionen zuzugreifen',
|
||||||
'helpDialog.proTips.recentSessions': 'Die 5 zuletzt verwendeten Sitzungen erscheinen in der Befehlspalette',
|
'helpDialog.proTips.recentSessions': 'Die 5 zuletzt verwendeten Sitzungen erscheinen in der Befehlspalette',
|
||||||
'helpDialog.proTips.themeCycling': 'Themenwechsel merken sich Ihre Einstellung über Sitzungen hinweg',
|
'helpDialog.proTips.leaderSequences': 'Zweistufige Kürzel: erst die Kombination, dann die zweite Taste — Esc bricht ab',
|
||||||
'header.actions.rightSidebarWithShortcut': 'Rechte Seitenleiste ({shortcut})',
|
'header.actions.rightSidebarWithShortcut': 'Rechte Seitenleiste ({shortcut})',
|
||||||
'header.actions.toggleRightSidebarAria': 'Rechte Seitenleiste umschalten',
|
'header.actions.toggleRightSidebarAria': 'Rechte Seitenleiste umschalten',
|
||||||
'header.actions.openAppMenu': 'OpenChamber-Menü',
|
'header.actions.openAppMenu': 'OpenChamber-Menü',
|
||||||
@@ -2293,6 +2289,9 @@ export const dict = {
|
|||||||
'commandPalette.item.toggleSidebar': 'Seitenleiste umschalten',
|
'commandPalette.item.toggleSidebar': 'Seitenleiste umschalten',
|
||||||
'commandPalette.item.showContextUsage': 'Kontextnutzung anzeigen',
|
'commandPalette.item.showContextUsage': 'Kontextnutzung anzeigen',
|
||||||
'commandPalette.item.toggleTerminal': 'Terminal umschalten',
|
'commandPalette.item.toggleTerminal': 'Terminal umschalten',
|
||||||
|
'commandPalette.item.cycleTheme': 'Thema wechseln',
|
||||||
|
'commandPalette.item.showOpenCodeStatus': 'OpenCode-Status anzeigen',
|
||||||
|
'commandPalette.item.toggleMemoryDebug': 'Memory-Debug-Panel umschalten',
|
||||||
'commandPalette.item.openSettings': 'Einstellungen öffnen...',
|
'commandPalette.item.openSettings': 'Einstellungen öffnen...',
|
||||||
'commandPalette.session.untitled': 'Unbenannte Sitzung',
|
'commandPalette.session.untitled': 'Unbenannte Sitzung',
|
||||||
'openCodeStatusDialog.title': 'OpenCode-Status',
|
'openCodeStatusDialog.title': 'OpenCode-Status',
|
||||||
|
|||||||
@@ -1142,9 +1142,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'Toggle terminal expanded',
|
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'Toggle terminal expanded',
|
||||||
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Add selection to chat',
|
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Add selection to chat',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Toggle sidebar',
|
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Toggle sidebar',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': 'Toggle context panel',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.label': 'Switch session tab',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Open Git surface',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix': ' + 1…9',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label': 'Open Files surface',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': 'Switch context panel surface',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': 'Switch context panel surface',
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_chat.label': 'New session',
|
'settings.openchamber.keyboardShortcuts.action.new_chat.label': 'New session',
|
||||||
@@ -1152,9 +1151,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': 'New worktree draft',
|
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': 'New worktree draft',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': 'New Mini Chat window',
|
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': 'New Mini Chat window',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_help.label': 'Open keyboard shortcuts',
|
'settings.openchamber.keyboardShortcuts.action.open_help.label': 'Open keyboard shortcuts',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label': 'Toggle plan context panel',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'Toggle services menu',
|
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'Toggle services menu',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': 'Cycle services tab',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'Cycle theme',
|
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'Cycle theme',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Cycle agent',
|
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Cycle agent',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'Cycle favorite model forward',
|
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'Cycle favorite model forward',
|
||||||
|
|||||||
@@ -1858,22 +1858,18 @@ export const dict = {
|
|||||||
'helpDialog.item.focusChatInput': 'Focus Chat Input',
|
'helpDialog.item.focusChatInput': 'Focus Chat Input',
|
||||||
'helpDialog.item.togglePromptNavigator': 'Toggle Prompt Navigator',
|
'helpDialog.item.togglePromptNavigator': 'Toggle Prompt Navigator',
|
||||||
'helpDialog.item.abortActiveRun': 'Abort active run (double press)',
|
'helpDialog.item.abortActiveRun': 'Abort active run (double press)',
|
||||||
'helpDialog.item.toggleRightSidebar': 'Toggle context panel',
|
|
||||||
'helpDialog.item.openRightSidebarGitTab': 'Open Git surface',
|
|
||||||
'helpDialog.item.openRightSidebarFilesTab': 'Open Files surface',
|
|
||||||
'helpDialog.item.toggleTerminalDock': 'Toggle Terminal Dock',
|
'helpDialog.item.toggleTerminalDock': 'Toggle Terminal Dock',
|
||||||
'helpDialog.item.toggleTerminalExpanded': 'Toggle Terminal Expanded',
|
'helpDialog.item.toggleTerminalExpanded': 'Toggle Terminal Expanded',
|
||||||
'helpDialog.item.togglePlanContextPanel': 'Toggle Plan Context Panel',
|
'helpDialog.item.switchSessionTab': 'Switch Session Tab',
|
||||||
'helpDialog.item.switchContextSurface': 'Switch Context Panel Surface (number key)',
|
'helpDialog.item.switchContextSurface': 'Switch Context Panel Surface (number key)',
|
||||||
'helpDialog.item.cycleTheme': 'Cycle Theme (Light → Dark → System)',
|
'helpDialog.item.cycleTheme': 'Cycle Theme (Light → Dark → System)',
|
||||||
'helpDialog.item.toggleServicesMenu': 'Toggle Services Menu',
|
'helpDialog.item.toggleServicesMenu': 'Toggle Services Menu',
|
||||||
'helpDialog.item.cycleServicesTab': 'Cycle Services Tab',
|
|
||||||
'helpDialog.item.openSettings': 'Open Settings',
|
'helpDialog.item.openSettings': 'Open Settings',
|
||||||
'helpDialog.keyCombiner.or': 'or',
|
'helpDialog.keyCombiner.or': 'or',
|
||||||
'helpDialog.proTips.title': 'Pro Tips:',
|
'helpDialog.proTips.title': 'Pro Tips:',
|
||||||
'helpDialog.proTips.commandPalette': 'Use Command Palette ({shortcut}) to quickly access all actions',
|
'helpDialog.proTips.commandPalette': 'Use Command Palette ({shortcut}) to quickly access all actions',
|
||||||
'helpDialog.proTips.recentSessions': 'The 5 most recent sessions appear in the Command Palette',
|
'helpDialog.proTips.recentSessions': 'The 5 most recent sessions appear in the Command Palette',
|
||||||
'helpDialog.proTips.themeCycling': 'Theme cycling remembers your preference across sessions',
|
'helpDialog.proTips.leaderSequences': 'Two-step shortcuts: press the first combo, then the second key — Esc cancels',
|
||||||
'header.actions.rightSidebarWithShortcut': 'Right sidebar ({shortcut})',
|
'header.actions.rightSidebarWithShortcut': 'Right sidebar ({shortcut})',
|
||||||
'header.actions.toggleRightSidebarAria': 'Toggle right sidebar',
|
'header.actions.toggleRightSidebarAria': 'Toggle right sidebar',
|
||||||
'header.actions.openAppMenu': 'OpenChamber menu',
|
'header.actions.openAppMenu': 'OpenChamber menu',
|
||||||
@@ -2483,6 +2479,9 @@ export const dict = {
|
|||||||
'commandPalette.item.toggleSidebar': 'Toggle Sidebar',
|
'commandPalette.item.toggleSidebar': 'Toggle Sidebar',
|
||||||
'commandPalette.item.showContextUsage': 'Show Context Usage',
|
'commandPalette.item.showContextUsage': 'Show Context Usage',
|
||||||
'commandPalette.item.toggleTerminal': 'Toggle Terminal',
|
'commandPalette.item.toggleTerminal': 'Toggle Terminal',
|
||||||
|
'commandPalette.item.cycleTheme': 'Cycle theme',
|
||||||
|
'commandPalette.item.showOpenCodeStatus': 'Show OpenCode status',
|
||||||
|
'commandPalette.item.toggleMemoryDebug': 'Toggle memory debug panel',
|
||||||
'commandPalette.item.openSettings': 'Open Settings...',
|
'commandPalette.item.openSettings': 'Open Settings...',
|
||||||
'commandPalette.session.untitled': 'Untitled Session',
|
'commandPalette.session.untitled': 'Untitled Session',
|
||||||
'openCodeStatusDialog.title': 'OpenCode Status',
|
'openCodeStatusDialog.title': 'OpenCode Status',
|
||||||
|
|||||||
@@ -1110,9 +1110,8 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label": "Expandir o contraer terminal",
|
"settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label": "Expandir o contraer terminal",
|
||||||
"settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label": "Agregar selección al chat",
|
"settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label": "Agregar selección al chat",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label": "Mostrar u ocultar barra lateral",
|
"settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label": "Mostrar u ocultar barra lateral",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label": 'Alternar panel de contexto',
|
"settings.openchamber.keyboardShortcuts.action.switch_session_tab.label": "Cambiar pestaña de sesión",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label": 'Abrir superficie de Git',
|
"settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix": " + 1…9",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label": 'Abrir superficie de archivos',
|
|
||||||
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.label": "Cambiar superficie del panel de contexto",
|
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.label": "Cambiar superficie del panel de contexto",
|
||||||
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix": " + 1…0",
|
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix": " + 1…0",
|
||||||
"settings.openchamber.keyboardShortcuts.action.new_chat.label": "Nueva sesión",
|
"settings.openchamber.keyboardShortcuts.action.new_chat.label": "Nueva sesión",
|
||||||
@@ -1120,9 +1119,7 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label": "Nuevo borrador de worktree",
|
"settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label": "Nuevo borrador de worktree",
|
||||||
"settings.openchamber.keyboardShortcuts.action.new_mini_chat.label": "Nueva ventana Mini Chat",
|
"settings.openchamber.keyboardShortcuts.action.new_mini_chat.label": "Nueva ventana Mini Chat",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_help.label": "Abrir atajos de teclado",
|
"settings.openchamber.keyboardShortcuts.action.open_help.label": "Abrir atajos de teclado",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label": "Alternar panel de plan de contexto",
|
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label": "Mostrar u ocultar menú de servicios",
|
"settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label": "Mostrar u ocultar menú de servicios",
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label": "Cambiar pestaña de servicios",
|
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_theme.label": "Cambiar tema",
|
"settings.openchamber.keyboardShortcuts.action.cycle_theme.label": "Cambiar tema",
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_agent.label": "Cambiar agente",
|
"settings.openchamber.keyboardShortcuts.action.cycle_agent.label": "Cambiar agente",
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label": "Siguiente modelo favorito",
|
"settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label": "Siguiente modelo favorito",
|
||||||
|
|||||||
@@ -1836,22 +1836,18 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
"helpDialog.item.focusChatInput": "Enfocar entrada de chat",
|
"helpDialog.item.focusChatInput": "Enfocar entrada de chat",
|
||||||
"helpDialog.item.togglePromptNavigator": "Mostrar u ocultar navegador de prompts",
|
"helpDialog.item.togglePromptNavigator": "Mostrar u ocultar navegador de prompts",
|
||||||
"helpDialog.item.abortActiveRun": "Detener ejecución activa (doble presionar)",
|
"helpDialog.item.abortActiveRun": "Detener ejecución activa (doble presionar)",
|
||||||
"helpDialog.item.toggleRightSidebar": 'Alternar panel de contexto',
|
|
||||||
"helpDialog.item.openRightSidebarGitTab": 'Abrir superficie de Git',
|
|
||||||
"helpDialog.item.openRightSidebarFilesTab": 'Abrir superficie de archivos',
|
|
||||||
"helpDialog.item.toggleTerminalDock": "Mostrar u ocultar dock de terminal",
|
"helpDialog.item.toggleTerminalDock": "Mostrar u ocultar dock de terminal",
|
||||||
"helpDialog.item.toggleTerminalExpanded": "Expandir o contraer terminal",
|
"helpDialog.item.toggleTerminalExpanded": "Expandir o contraer terminal",
|
||||||
"helpDialog.item.togglePlanContextPanel": "Alternar panel de contexto del plan",
|
|
||||||
"helpDialog.item.cycleTheme": "Cambiar tema (Claro → Oscuro → Sistema)",
|
"helpDialog.item.cycleTheme": "Cambiar tema (Claro → Oscuro → Sistema)",
|
||||||
|
"helpDialog.item.switchSessionTab": "Cambiar pestaña de sesión",
|
||||||
"helpDialog.item.switchContextSurface": "Cambiar superficie del panel de contexto (tecla numérica)",
|
"helpDialog.item.switchContextSurface": "Cambiar superficie del panel de contexto (tecla numérica)",
|
||||||
"helpDialog.item.toggleServicesMenu": "Mostrar u ocultar menú de servicios",
|
"helpDialog.item.toggleServicesMenu": "Mostrar u ocultar menú de servicios",
|
||||||
"helpDialog.item.cycleServicesTab": "Cambiar pestaña de servicios",
|
|
||||||
"helpDialog.item.openSettings": "Abrir configuración",
|
"helpDialog.item.openSettings": "Abrir configuración",
|
||||||
"helpDialog.keyCombiner.or": "o",
|
"helpDialog.keyCombiner.or": "o",
|
||||||
"helpDialog.proTips.title": "Consejos:",
|
"helpDialog.proTips.title": "Consejos:",
|
||||||
"helpDialog.proTips.commandPalette": "Usa la paleta de comandos ({shortcut}) para acceder rápidamente a todas las acciones",
|
"helpDialog.proTips.commandPalette": "Usa la paleta de comandos ({shortcut}) para acceder rápidamente a todas las acciones",
|
||||||
"helpDialog.proTips.recentSessions": "Las cinco sesiones más recientes aparecen en la paleta de comandos",
|
"helpDialog.proTips.recentSessions": "Las cinco sesiones más recientes aparecen en la paleta de comandos",
|
||||||
"helpDialog.proTips.themeCycling": "El ciclo de tema recuerda tu preferencia entre sesiones",
|
"helpDialog.proTips.leaderSequences": "Atajos en dos pasos: pulsa la combinación y luego la segunda tecla; Esc cancela",
|
||||||
"header.actions.rightSidebarWithShortcut": "Barra lateral derecha ({shortcut})",
|
"header.actions.rightSidebarWithShortcut": "Barra lateral derecha ({shortcut})",
|
||||||
"header.actions.toggleRightSidebarAria": "Mostrar u ocultar barra lateral derecha",
|
"header.actions.toggleRightSidebarAria": "Mostrar u ocultar barra lateral derecha",
|
||||||
"header.actions.openAppMenu": "Menú de OpenChamber",
|
"header.actions.openAppMenu": "Menú de OpenChamber",
|
||||||
@@ -2449,6 +2445,9 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
"commandPalette.item.toggleSidebar": "Mostrar u ocultar barra lateral",
|
"commandPalette.item.toggleSidebar": "Mostrar u ocultar barra lateral",
|
||||||
"commandPalette.item.showContextUsage": "Mostrar uso del contexto",
|
"commandPalette.item.showContextUsage": "Mostrar uso del contexto",
|
||||||
"commandPalette.item.toggleTerminal": "Mostrar u ocultar terminal",
|
"commandPalette.item.toggleTerminal": "Mostrar u ocultar terminal",
|
||||||
|
"commandPalette.item.cycleTheme": "Cambiar tema",
|
||||||
|
"commandPalette.item.showOpenCodeStatus": "Mostrar estado de OpenCode",
|
||||||
|
"commandPalette.item.toggleMemoryDebug": "Alternar panel de depuración de memoria",
|
||||||
"commandPalette.item.openSettings": "Abrir configuración...",
|
"commandPalette.item.openSettings": "Abrir configuración...",
|
||||||
"commandPalette.session.untitled": "Sesión sin título",
|
"commandPalette.session.untitled": "Sesión sin título",
|
||||||
"openCodeStatusDialog.title": "Estado de OpenCode",
|
"openCodeStatusDialog.title": "Estado de OpenCode",
|
||||||
|
|||||||
@@ -1028,9 +1028,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'Terminal à bascule étendu',
|
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'Terminal à bascule étendu',
|
||||||
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Ajouter la sélection au chat',
|
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Ajouter la sélection au chat',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Basculer la barre latérale',
|
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Basculer la barre latérale',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': 'Afficher/masquer le panneau de contexte',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.label': 'Basculer l’onglet de session',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Ouvrir la surface Git',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix': ' + 1…9',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label': 'Ouvrir la surface Fichiers',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': 'Basculer la surface du panneau contextuel',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': 'Basculer la surface du panneau contextuel',
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_chat.label': 'Nouvelle session',
|
'settings.openchamber.keyboardShortcuts.action.new_chat.label': 'Nouvelle session',
|
||||||
@@ -1038,9 +1037,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': 'Nouvelle ébauche d\'worktree',
|
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': 'Nouvelle ébauche d\'worktree',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': 'Nouvelle fenêtre de mini-chat',
|
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': 'Nouvelle fenêtre de mini-chat',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_help.label': 'Ouvrir les raccourcis clavier',
|
'settings.openchamber.keyboardShortcuts.action.open_help.label': 'Ouvrir les raccourcis clavier',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label': 'Basculer le panneau contextuel du plan',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'Basculer le menu des services',
|
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'Basculer le menu des services',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': 'Onglet Services vélo',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'Thème du cycle',
|
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'Thème du cycle',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Agent de cycle',
|
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Agent de cycle',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'Faire avancer le modèle favori',
|
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'Faire avancer le modèle favori',
|
||||||
|
|||||||
@@ -1616,22 +1616,18 @@ export const dict = {
|
|||||||
'helpDialog.item.focusChatInput': 'Concentration sur la saisie du chat',
|
'helpDialog.item.focusChatInput': 'Concentration sur la saisie du chat',
|
||||||
'helpDialog.item.togglePromptNavigator': 'Afficher ou masquer le navigateur de prompts',
|
'helpDialog.item.togglePromptNavigator': 'Afficher ou masquer le navigateur de prompts',
|
||||||
'helpDialog.item.abortActiveRun': 'Abandonner l’exécution active (double pression)',
|
'helpDialog.item.abortActiveRun': 'Abandonner l’exécution active (double pression)',
|
||||||
'helpDialog.item.toggleRightSidebar': 'Afficher/masquer le panneau de contexte',
|
|
||||||
'helpDialog.item.openRightSidebarGitTab': 'Ouvrir la surface Git',
|
|
||||||
'helpDialog.item.openRightSidebarFilesTab': 'Ouvrir la surface Fichiers',
|
|
||||||
'helpDialog.item.toggleTerminalDock': 'Basculer la station d\'accueil du terminal',
|
'helpDialog.item.toggleTerminalDock': 'Basculer la station d\'accueil du terminal',
|
||||||
'helpDialog.item.toggleTerminalExpanded': 'Terminal à bascule étendu',
|
'helpDialog.item.toggleTerminalExpanded': 'Terminal à bascule étendu',
|
||||||
'helpDialog.item.togglePlanContextPanel': 'Toggle Panneau contextuel du plan',
|
|
||||||
'helpDialog.item.cycleTheme': 'Basculer le thème (clair → sombre → système)',
|
'helpDialog.item.cycleTheme': 'Basculer le thème (clair → sombre → système)',
|
||||||
|
'helpDialog.item.switchSessionTab': 'Basculer l’onglet de session',
|
||||||
'helpDialog.item.switchContextSurface': 'Basculer la surface du panneau contextuel (touche numérique)',
|
'helpDialog.item.switchContextSurface': 'Basculer la surface du panneau contextuel (touche numérique)',
|
||||||
'helpDialog.item.toggleServicesMenu': 'Basculer le menu des services',
|
'helpDialog.item.toggleServicesMenu': 'Basculer le menu des services',
|
||||||
'helpDialog.item.cycleServicesTab': 'Onglet Services de vélo',
|
|
||||||
'helpDialog.item.openSettings': 'Ouvrir les paramètres',
|
'helpDialog.item.openSettings': 'Ouvrir les paramètres',
|
||||||
'helpDialog.keyCombiner.or': 'ou',
|
'helpDialog.keyCombiner.or': 'ou',
|
||||||
'helpDialog.proTips.title': 'Conseils de pro :',
|
'helpDialog.proTips.title': 'Conseils de pro :',
|
||||||
'helpDialog.proTips.commandPalette': 'Utilisez la palette de commandes ({shortcut}) pour accéder rapidement à toutes les actions',
|
'helpDialog.proTips.commandPalette': 'Utilisez la palette de commandes ({shortcut}) pour accéder rapidement à toutes les actions',
|
||||||
'helpDialog.proTips.recentSessions': 'Les 5 sessions les plus récentes apparaissent dans la palette de commandes',
|
'helpDialog.proTips.recentSessions': 'Les 5 sessions les plus récentes apparaissent dans la palette de commandes',
|
||||||
'helpDialog.proTips.themeCycling': 'Le cyclisme thématique mémorise vos préférences au fil des sessions',
|
'helpDialog.proTips.leaderSequences': 'Raccourcis en deux temps : appuyez sur la combinaison, puis sur la seconde touche — Échap annule',
|
||||||
'header.actions.rightSidebarWithShortcut': 'Barre latérale droite ({shortcut})',
|
'header.actions.rightSidebarWithShortcut': 'Barre latérale droite ({shortcut})',
|
||||||
'header.actions.toggleRightSidebarAria': 'Basculer la barre latérale droite',
|
'header.actions.toggleRightSidebarAria': 'Basculer la barre latérale droite',
|
||||||
'header.actions.openAppMenu': 'Menu de OpenChamber',
|
'header.actions.openAppMenu': 'Menu de OpenChamber',
|
||||||
@@ -2187,6 +2183,9 @@ export const dict = {
|
|||||||
'commandPalette.item.toggleSidebar': 'Basculer la barre latérale',
|
'commandPalette.item.toggleSidebar': 'Basculer la barre latérale',
|
||||||
'commandPalette.item.showContextUsage': 'Afficher l\'utilisation du contexte',
|
'commandPalette.item.showContextUsage': 'Afficher l\'utilisation du contexte',
|
||||||
'commandPalette.item.toggleTerminal': 'Basculer le terminal',
|
'commandPalette.item.toggleTerminal': 'Basculer le terminal',
|
||||||
|
'commandPalette.item.cycleTheme': 'Changer de thème',
|
||||||
|
'commandPalette.item.showOpenCodeStatus': 'Afficher le statut OpenCode',
|
||||||
|
'commandPalette.item.toggleMemoryDebug': 'Basculer le panneau de débogage mémoire',
|
||||||
'commandPalette.item.openSettings': 'Ouvrez les paramètres...',
|
'commandPalette.item.openSettings': 'Ouvrez les paramètres...',
|
||||||
'commandPalette.session.untitled': 'Session sans titre',
|
'commandPalette.session.untitled': 'Session sans titre',
|
||||||
'openCodeStatusDialog.title': 'Statut OpenCode',
|
'openCodeStatusDialog.title': 'Statut OpenCode',
|
||||||
|
|||||||
@@ -1143,9 +1143,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'ターミナル拡大の切替',
|
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': 'ターミナル拡大の切替',
|
||||||
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '選択範囲をチャットに追加',
|
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '選択範囲をチャットに追加',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'サイドバーの切替',
|
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'サイドバーの切替',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': 'コンテキストパネルの表示切替',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.label': 'セッションタブを切り替え',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Git サーフェスを開く',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix': ' + 1…9',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label': 'ファイルサーフェスを開く',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': 'コンテキストパネルのサーフェスを切り替え',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': 'コンテキストパネルのサーフェスを切り替え',
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_chat.label': '新しい Session',
|
'settings.openchamber.keyboardShortcuts.action.new_chat.label': '新しい Session',
|
||||||
@@ -1153,9 +1152,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': '新しい Worktree 下書き',
|
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': '新しい Worktree 下書き',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': '新しいミニチャットウィンドウ',
|
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': '新しいミニチャットウィンドウ',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_help.label': 'キーボードショートカットを開く',
|
'settings.openchamber.keyboardShortcuts.action.open_help.label': 'キーボードショートカットを開く',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label': '計画コンテキストパネルの切替',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'サービスメニューの切替',
|
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'サービスメニューの切替',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': 'サービスタブを順に切替',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'テーマを順に切替',
|
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'テーマを順に切替',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Agent を順に切替',
|
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Agent を順に切替',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'お気に入りモデルを次へ',
|
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'お気に入りモデルを次へ',
|
||||||
|
|||||||
@@ -1854,22 +1854,18 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'helpDialog.item.focusChatInput': 'チャット入力にフォーカス',
|
'helpDialog.item.focusChatInput': 'チャット入力にフォーカス',
|
||||||
'helpDialog.item.togglePromptNavigator': 'プロンプトナビゲーターの表示切替',
|
'helpDialog.item.togglePromptNavigator': 'プロンプトナビゲーターの表示切替',
|
||||||
'helpDialog.item.abortActiveRun': 'アクティブな実行を中止(ダブルプレス)',
|
'helpDialog.item.abortActiveRun': 'アクティブな実行を中止(ダブルプレス)',
|
||||||
'helpDialog.item.toggleRightSidebar': 'コンテキストパネルの表示切替',
|
|
||||||
'helpDialog.item.openRightSidebarGitTab': 'Git サーフェスを開く',
|
|
||||||
'helpDialog.item.openRightSidebarFilesTab': 'ファイルサーフェスを開く',
|
|
||||||
'helpDialog.item.toggleTerminalDock': 'ターミナルドックの切り替え',
|
'helpDialog.item.toggleTerminalDock': 'ターミナルドックの切り替え',
|
||||||
'helpDialog.item.toggleTerminalExpanded': 'ターミナル展開の切り替え',
|
'helpDialog.item.toggleTerminalExpanded': 'ターミナル展開の切り替え',
|
||||||
'helpDialog.item.togglePlanContextPanel': '計画コンテキストパネルの切り替え',
|
|
||||||
'helpDialog.item.cycleTheme': 'テーマ切り替え(ライト→ダーク→システム)',
|
'helpDialog.item.cycleTheme': 'テーマ切り替え(ライト→ダーク→システム)',
|
||||||
|
'helpDialog.item.switchSessionTab': 'セッションタブを切り替え',
|
||||||
'helpDialog.item.switchContextSurface': 'コンテキストパネルのサーフェスを切り替え(数字キー)',
|
'helpDialog.item.switchContextSurface': 'コンテキストパネルのサーフェスを切り替え(数字キー)',
|
||||||
'helpDialog.item.toggleServicesMenu': 'サービスの切り替え',
|
'helpDialog.item.toggleServicesMenu': 'サービスの切り替え',
|
||||||
'helpDialog.item.cycleServicesTab': 'サービス変数の切り替え',
|
|
||||||
'helpDialog.item.openSettings': '設定を開く',
|
'helpDialog.item.openSettings': '設定を開く',
|
||||||
'helpDialog.keyCombiner.or': 'または',
|
'helpDialog.keyCombiner.or': 'または',
|
||||||
'helpDialog.proTips.title': 'プロのヒント:',
|
'helpDialog.proTips.title': 'プロのヒント:',
|
||||||
'helpDialog.proTips.commandPalette': 'コマンドパレット({shortcut})を使うとすべての操作にすばやくアクセスできます',
|
'helpDialog.proTips.commandPalette': 'コマンドパレット({shortcut})を使うとすべての操作にすばやくアクセスできます',
|
||||||
'helpDialog.proTips.recentSessions': '最近の5つのセッションがコマンドパレットに表示されます',
|
'helpDialog.proTips.recentSessions': '最近の5つのセッションがコマンドパレットに表示されます',
|
||||||
'helpDialog.proTips.themeCycling': 'テーマの切り替えはセッション間で設定が記憶されます',
|
'helpDialog.proTips.leaderSequences': '2段階ショートカット:組み合わせを押してから2つ目のキーを押します(Escで取消)',
|
||||||
'header.actions.rightSidebarWithShortcut': '右サイドバー({shortcut})',
|
'header.actions.rightSidebarWithShortcut': '右サイドバー({shortcut})',
|
||||||
'header.actions.toggleRightSidebarAria': '右サイドバーの切り替え',
|
'header.actions.toggleRightSidebarAria': '右サイドバーの切り替え',
|
||||||
'header.actions.openAppMenu': 'OpenChamberメニュー',
|
'header.actions.openAppMenu': 'OpenChamberメニュー',
|
||||||
@@ -2482,6 +2478,9 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'commandPalette.item.toggleSidebar': 'サイドバーの切り替え',
|
'commandPalette.item.toggleSidebar': 'サイドバーの切り替え',
|
||||||
'commandPalette.item.showContextUsage': 'コンテキスト使用量を表示',
|
'commandPalette.item.showContextUsage': 'コンテキスト使用量を表示',
|
||||||
'commandPalette.item.toggleTerminal': 'ターミナルの切り替え',
|
'commandPalette.item.toggleTerminal': 'ターミナルの切り替え',
|
||||||
|
'commandPalette.item.cycleTheme': 'テーマを順に切替',
|
||||||
|
'commandPalette.item.showOpenCodeStatus': 'OpenCode のステータスを表示',
|
||||||
|
'commandPalette.item.toggleMemoryDebug': 'メモリデバッグパネルの切替',
|
||||||
'commandPalette.item.openSettings': '設定を開く...',
|
'commandPalette.item.openSettings': '設定を開く...',
|
||||||
'commandPalette.session.untitled': '無題のセッション',
|
'commandPalette.session.untitled': '無題のセッション',
|
||||||
'openCodeStatusDialog.title': 'OpenCodeステータス',
|
'openCodeStatusDialog.title': 'OpenCodeステータス',
|
||||||
|
|||||||
@@ -1110,9 +1110,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': '터미널 확장 토글',
|
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': '터미널 확장 토글',
|
||||||
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '선택 내용을 채팅에 추가',
|
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '선택 내용을 채팅에 추가',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': '사이드바 토글',
|
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': '사이드바 토글',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': '컨텍스트 패널 표시 전환',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.label': '세션 탭 전환',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Git 서피스 열기',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix': ' + 1…9',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label': '파일 서피스 열기',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': '컨텍스트 패널 서피스 전환',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': '컨텍스트 패널 서피스 전환',
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_chat.label': '새 세션',
|
'settings.openchamber.keyboardShortcuts.action.new_chat.label': '새 세션',
|
||||||
@@ -1120,9 +1119,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': '새 worktree 초안',
|
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': '새 worktree 초안',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': '새 Mini Chat 창',
|
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': '새 Mini Chat 창',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_help.label': '키보드 단축키 열기',
|
'settings.openchamber.keyboardShortcuts.action.open_help.label': '키보드 단축키 열기',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label': '계획 컨텍스트 패널 토글',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': '서비스 메뉴 토글',
|
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': '서비스 메뉴 토글',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': '서비스 탭 순환',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': '테마 순환',
|
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': '테마 순환',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': '에이전트 순환',
|
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': '에이전트 순환',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': '즐겨찾기 모델 앞으로 순환',
|
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': '즐겨찾기 모델 앞으로 순환',
|
||||||
|
|||||||
@@ -1860,22 +1860,18 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'helpDialog.item.focusChatInput': '채팅 입력창으로 포커스 이동',
|
'helpDialog.item.focusChatInput': '채팅 입력창으로 포커스 이동',
|
||||||
'helpDialog.item.togglePromptNavigator': '프롬프트 탐색기 표시/숨기기',
|
'helpDialog.item.togglePromptNavigator': '프롬프트 탐색기 표시/숨기기',
|
||||||
'helpDialog.item.abortActiveRun': '활성 실행 중단(두 번 누르기)',
|
'helpDialog.item.abortActiveRun': '활성 실행 중단(두 번 누르기)',
|
||||||
'helpDialog.item.toggleRightSidebar': '컨텍스트 패널 표시 전환',
|
|
||||||
'helpDialog.item.openRightSidebarGitTab': 'Git 서피스 열기',
|
|
||||||
'helpDialog.item.openRightSidebarFilesTab': '파일 서피스 열기',
|
|
||||||
'helpDialog.item.toggleTerminalDock': '터미널 독 전환',
|
'helpDialog.item.toggleTerminalDock': '터미널 독 전환',
|
||||||
'helpDialog.item.toggleTerminalExpanded': '터미널 펼치기/접기',
|
'helpDialog.item.toggleTerminalExpanded': '터미널 펼치기/접기',
|
||||||
'helpDialog.item.togglePlanContextPanel': '플랜 컨텍스트 패널 전환',
|
|
||||||
'helpDialog.item.cycleTheme': '테마 순환(라이트 → 다크 → 시스템)',
|
'helpDialog.item.cycleTheme': '테마 순환(라이트 → 다크 → 시스템)',
|
||||||
|
'helpDialog.item.switchSessionTab': '세션 탭 전환',
|
||||||
'helpDialog.item.switchContextSurface': '컨텍스트 패널 서피스 전환(숫자 키)',
|
'helpDialog.item.switchContextSurface': '컨텍스트 패널 서피스 전환(숫자 키)',
|
||||||
'helpDialog.item.toggleServicesMenu': '서비스 메뉴 전환',
|
'helpDialog.item.toggleServicesMenu': '서비스 메뉴 전환',
|
||||||
'helpDialog.item.cycleServicesTab': '서비스 탭 순환',
|
|
||||||
'helpDialog.item.openSettings': '설정 열기',
|
'helpDialog.item.openSettings': '설정 열기',
|
||||||
'helpDialog.keyCombiner.or': '또는',
|
'helpDialog.keyCombiner.or': '또는',
|
||||||
'helpDialog.proTips.title': '팁:',
|
'helpDialog.proTips.title': '팁:',
|
||||||
'helpDialog.proTips.commandPalette': '명령 팔레트({shortcut})로 모든 작업에 빠르게 접근하세요',
|
'helpDialog.proTips.commandPalette': '명령 팔레트({shortcut})로 모든 작업에 빠르게 접근하세요',
|
||||||
'helpDialog.proTips.recentSessions': '최근 세션 5개가 명령 팔레트에 표시됩니다',
|
'helpDialog.proTips.recentSessions': '최근 세션 5개가 명령 팔레트에 표시됩니다',
|
||||||
'helpDialog.proTips.themeCycling': '테마 순환은 세션 간에도 선호 설정을 기억합니다',
|
'helpDialog.proTips.leaderSequences': '2단계 단축키: 조합을 누른 뒤 두 번째 키를 누르세요 (Esc로 취소)',
|
||||||
'header.actions.rightSidebarWithShortcut': '오른쪽 사이드바 ({shortcut})',
|
'header.actions.rightSidebarWithShortcut': '오른쪽 사이드바 ({shortcut})',
|
||||||
'header.actions.toggleRightSidebarAria': '오른쪽 사이드바 토글',
|
'header.actions.toggleRightSidebarAria': '오른쪽 사이드바 토글',
|
||||||
'header.actions.openAppMenu': 'OpenChamber 메뉴',
|
'header.actions.openAppMenu': 'OpenChamber 메뉴',
|
||||||
@@ -2483,6 +2479,9 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'commandPalette.item.toggleSidebar': '토글 사이드바',
|
'commandPalette.item.toggleSidebar': '토글 사이드바',
|
||||||
'commandPalette.item.showContextUsage': '컨텍스트 사용량 표시',
|
'commandPalette.item.showContextUsage': '컨텍스트 사용량 표시',
|
||||||
'commandPalette.item.toggleTerminal': '토글 터미널',
|
'commandPalette.item.toggleTerminal': '토글 터미널',
|
||||||
|
'commandPalette.item.cycleTheme': '테마 순환',
|
||||||
|
'commandPalette.item.showOpenCodeStatus': 'OpenCode 상태 표시',
|
||||||
|
'commandPalette.item.toggleMemoryDebug': '메모리 디버그 패널 토글',
|
||||||
'commandPalette.item.openSettings': '설정... 열기',
|
'commandPalette.item.openSettings': '설정... 열기',
|
||||||
'commandPalette.session.untitled': '제목 없는 세션',
|
'commandPalette.session.untitled': '제목 없는 세션',
|
||||||
'openCodeStatusDialog.title': 'OpenCode 상태',
|
'openCodeStatusDialog.title': 'OpenCode 상태',
|
||||||
|
|||||||
@@ -818,7 +818,6 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_backward.label': 'Przełącz ulubiony model wstecz',
|
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_backward.label': 'Przełącz ulubiony model wstecz',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_model_selector.label': 'Otwórz wybór modelu',
|
'settings.openchamber.keyboardShortcuts.action.open_model_selector.label': 'Otwórz wybór modelu',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'Przełącz ulubiony model w przód',
|
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': 'Przełącz ulubiony model w przód',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': 'Przełącz zakładkę usług',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'Przełącz motyw',
|
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': 'Przełącz motyw',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Przełącz agenta',
|
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': 'Przełącz agenta',
|
||||||
'settings.openchamber.keyboardShortcuts.action.expand_input.label': 'Rozwiń pole wprowadzania',
|
'settings.openchamber.keyboardShortcuts.action.expand_input.label': 'Rozwiń pole wprowadzania',
|
||||||
@@ -831,13 +830,11 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.open_command_palette.label': 'Otwórz paletę poleceń',
|
'settings.openchamber.keyboardShortcuts.action.open_command_palette.label': 'Otwórz paletę poleceń',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_go_to_line.label': 'Przejdź do linii (edytor plików)',
|
'settings.openchamber.keyboardShortcuts.action.open_go_to_line.label': 'Przejdź do linii (edytor plików)',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_help.label': 'Otwórz skróty klawiszowe',
|
'settings.openchamber.keyboardShortcuts.action.open_help.label': 'Otwórz skróty klawiszowe',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label': 'Otwórz powierzchnię plików',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.label': 'Przełącz kartę sesji',
|
||||||
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix': ' + 1…9',
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': 'Przełącz powierzchnię panelu kontekstu',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': 'Przełącz powierzchnię panelu kontekstu',
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': 'Otwórz powierzchnię Git',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_settings.label': 'Otwórz ustawienia',
|
'settings.openchamber.keyboardShortcuts.action.open_settings.label': 'Otwórz ustawienia',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label': 'Przełącz panel kontekstu planu',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': 'Przełącz panel kontekstu',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'Przełącz menu usług',
|
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': 'Przełącz menu usług',
|
||||||
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Dodaj zaznaczenie do czatu',
|
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': 'Dodaj zaznaczenie do czatu',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Przełącz pasek boczny',
|
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': 'Przełącz pasek boczny',
|
||||||
|
|||||||
@@ -1452,6 +1452,9 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'commandPalette.item.showSessionSwitcher': 'Pokaż przełącznik sesji',
|
'commandPalette.item.showSessionSwitcher': 'Pokaż przełącznik sesji',
|
||||||
'commandPalette.item.toggleSidebar': 'Przełącz panel boczny',
|
'commandPalette.item.toggleSidebar': 'Przełącz panel boczny',
|
||||||
'commandPalette.item.toggleTerminal': 'Przełącz terminal',
|
'commandPalette.item.toggleTerminal': 'Przełącz terminal',
|
||||||
|
'commandPalette.item.cycleTheme': 'Przełącz motyw',
|
||||||
|
'commandPalette.item.showOpenCodeStatus': 'Pokaż status OpenCode',
|
||||||
|
'commandPalette.item.toggleMemoryDebug': 'Przełącz panel debugowania pamięci',
|
||||||
'commandPalette.session.untitled': 'Nienazwana sesja',
|
'commandPalette.session.untitled': 'Nienazwana sesja',
|
||||||
'commandPalette.title': 'Paleta poleceń',
|
'commandPalette.title': 'Paleta poleceń',
|
||||||
'contextPanel.actions.closePanel': 'Zamknij panel',
|
'contextPanel.actions.closePanel': 'Zamknij panel',
|
||||||
@@ -2452,7 +2455,6 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'helpDialog.item.createNewSession': 'Utwórz nową sesję',
|
'helpDialog.item.createNewSession': 'Utwórz nową sesję',
|
||||||
'helpDialog.item.createNewWorktreeDraft': 'Utwórz nowy szkic drzewa pracy',
|
'helpDialog.item.createNewWorktreeDraft': 'Utwórz nowy szkic drzewa pracy',
|
||||||
'helpDialog.item.cycleAgent': 'Przełącz agenta (w polu czatu)',
|
'helpDialog.item.cycleAgent': 'Przełącz agenta (w polu czatu)',
|
||||||
'helpDialog.item.cycleServicesTab': 'Przełącz kartę usług',
|
|
||||||
'helpDialog.item.cycleTheme': 'Przełącz motyw (Jasny → Ciemny → Systemowy)',
|
'helpDialog.item.cycleTheme': 'Przełącz motyw (Jasny → Ciemny → Systemowy)',
|
||||||
'helpDialog.item.cycleThinkingVariant': 'Przełącz wariant myślenia (skrót globalny)',
|
'helpDialog.item.cycleThinkingVariant': 'Przełącz wariant myślenia (skrót globalny)',
|
||||||
'helpDialog.item.focusChatInput': 'Ustaw fokus na polu czatu',
|
'helpDialog.item.focusChatInput': 'Ustaw fokus na polu czatu',
|
||||||
@@ -2461,13 +2463,10 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'helpDialog.item.newWindow': 'Nowe okno (tylko desktop)',
|
'helpDialog.item.newWindow': 'Nowe okno (tylko desktop)',
|
||||||
'helpDialog.item.openCommandPalette': 'Otwórz paletę poleceń',
|
'helpDialog.item.openCommandPalette': 'Otwórz paletę poleceń',
|
||||||
'helpDialog.item.openModelSelector': 'Otwórz selektor modeli',
|
'helpDialog.item.openModelSelector': 'Otwórz selektor modeli',
|
||||||
'helpDialog.item.openRightSidebarFilesTab': 'Otwórz powierzchnię plików',
|
|
||||||
'helpDialog.item.openRightSidebarGitTab': 'Otwórz powierzchnię Git',
|
|
||||||
'helpDialog.item.openSettings': 'Otwórz ustawienia',
|
'helpDialog.item.openSettings': 'Otwórz ustawienia',
|
||||||
'helpDialog.item.showKeyboardShortcuts': 'Pokaż skróty klawiaturowe (to okno)',
|
'helpDialog.item.showKeyboardShortcuts': 'Pokaż skróty klawiaturowe (to okno)',
|
||||||
|
'helpDialog.item.switchSessionTab': 'Przełącz kartę sesji',
|
||||||
'helpDialog.item.switchContextSurface': 'Przełącz powierzchnię panelu kontekstu (klawisz liczbowy)',
|
'helpDialog.item.switchContextSurface': 'Przełącz powierzchnię panelu kontekstu (klawisz liczbowy)',
|
||||||
'helpDialog.item.togglePlanContextPanel': 'Przełącz panel kontekstu planu',
|
|
||||||
'helpDialog.item.toggleRightSidebar': 'Przełącz panel kontekstu',
|
|
||||||
'helpDialog.item.toggleServicesMenu': 'Przełącz menu usług',
|
'helpDialog.item.toggleServicesMenu': 'Przełącz menu usług',
|
||||||
'helpDialog.item.toggleSessionSidebar': 'Przełącz panel sesji',
|
'helpDialog.item.toggleSessionSidebar': 'Przełącz panel sesji',
|
||||||
'helpDialog.item.addSelectionToChat': 'Dodaj zaznaczenie do czatu',
|
'helpDialog.item.addSelectionToChat': 'Dodaj zaznaczenie do czatu',
|
||||||
@@ -2476,7 +2475,7 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'helpDialog.keyCombiner.or': 'lub',
|
'helpDialog.keyCombiner.or': 'lub',
|
||||||
'helpDialog.proTips.commandPalette': 'Użyj Palety poleceń ({shortcut}), aby szybko uzyskać dostęp do wszystkich akcji',
|
'helpDialog.proTips.commandPalette': 'Użyj Palety poleceń ({shortcut}), aby szybko uzyskać dostęp do wszystkich akcji',
|
||||||
'helpDialog.proTips.recentSessions': '5 ostatnich sesji pojawia się w Palecie poleceń',
|
'helpDialog.proTips.recentSessions': '5 ostatnich sesji pojawia się w Palecie poleceń',
|
||||||
'helpDialog.proTips.themeCycling': 'Przełączanie motywów zapamiętuje twoje preferencje między sesjami',
|
'helpDialog.proTips.leaderSequences': 'Skróty dwustopniowe: naciśnij kombinację, potem drugi klawisz — Esc anuluje',
|
||||||
'helpDialog.proTips.title': 'Wskazówki:',
|
'helpDialog.proTips.title': 'Wskazówki:',
|
||||||
'helpDialog.section.interface': 'Interfejs',
|
'helpDialog.section.interface': 'Interfejs',
|
||||||
'helpDialog.section.navigationCommands': 'Nawigacja i polecenia',
|
'helpDialog.section.navigationCommands': 'Nawigacja i polecenia',
|
||||||
|
|||||||
@@ -1110,9 +1110,8 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label": "Expandir ou recolher terminal",
|
"settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label": "Expandir ou recolher terminal",
|
||||||
"settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label": "Adicionar seleção ao chat",
|
"settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label": "Adicionar seleção ao chat",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label": "Mostrar ou ocultar barra lateral",
|
"settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label": "Mostrar ou ocultar barra lateral",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label": 'Alternar painel de contexto',
|
"settings.openchamber.keyboardShortcuts.action.switch_session_tab.label": "Alternar aba de sessão",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label": 'Abrir superfície do Git',
|
"settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix": " + 1…9",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label": 'Abrir superfície de arquivos',
|
|
||||||
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.label": "Alternar superfície do painel de contexto",
|
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.label": "Alternar superfície do painel de contexto",
|
||||||
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix": " + 1…0",
|
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix": " + 1…0",
|
||||||
"settings.openchamber.keyboardShortcuts.action.new_chat.label": "Nova sessão",
|
"settings.openchamber.keyboardShortcuts.action.new_chat.label": "Nova sessão",
|
||||||
@@ -1120,9 +1119,7 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label": "Novo rascunho de worktree",
|
"settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label": "Novo rascunho de worktree",
|
||||||
"settings.openchamber.keyboardShortcuts.action.new_mini_chat.label": "Nova janela Mini Chat",
|
"settings.openchamber.keyboardShortcuts.action.new_mini_chat.label": "Nova janela Mini Chat",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_help.label": "Abrir atalhos de teclado",
|
"settings.openchamber.keyboardShortcuts.action.open_help.label": "Abrir atalhos de teclado",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label": "Alternar painel de plano de contexto",
|
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label": "Mostrar ou ocultar menu de serviços",
|
"settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label": "Mostrar ou ocultar menu de serviços",
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label": "Alternar aba de serviços",
|
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_theme.label": "Alternar tema",
|
"settings.openchamber.keyboardShortcuts.action.cycle_theme.label": "Alternar tema",
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_agent.label": "Alternar agente",
|
"settings.openchamber.keyboardShortcuts.action.cycle_agent.label": "Alternar agente",
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label": "Próximo modelo favorito",
|
"settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label": "Próximo modelo favorito",
|
||||||
|
|||||||
@@ -1836,22 +1836,18 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
"helpDialog.item.focusChatInput": "Focar entrada do chat",
|
"helpDialog.item.focusChatInput": "Focar entrada do chat",
|
||||||
"helpDialog.item.togglePromptNavigator": "Mostrar ou ocultar navegador de prompts",
|
"helpDialog.item.togglePromptNavigator": "Mostrar ou ocultar navegador de prompts",
|
||||||
"helpDialog.item.abortActiveRun": "Interromper execução ativa (duplo clique)",
|
"helpDialog.item.abortActiveRun": "Interromper execução ativa (duplo clique)",
|
||||||
"helpDialog.item.toggleRightSidebar": 'Alternar painel de contexto',
|
|
||||||
"helpDialog.item.openRightSidebarGitTab": 'Abrir superfície do Git',
|
|
||||||
"helpDialog.item.openRightSidebarFilesTab": 'Abrir superfície de arquivos',
|
|
||||||
"helpDialog.item.toggleTerminalDock": "Mostrar ou ocultar dock de terminal",
|
"helpDialog.item.toggleTerminalDock": "Mostrar ou ocultar dock de terminal",
|
||||||
"helpDialog.item.toggleTerminalExpanded": "Expandir ou recolher o terminal",
|
"helpDialog.item.toggleTerminalExpanded": "Expandir ou recolher o terminal",
|
||||||
"helpDialog.item.togglePlanContextPanel": "Alternar painel de contexto do plano",
|
|
||||||
"helpDialog.item.cycleTheme": "Alternar tema (Claro → Escuro → Sistema)",
|
"helpDialog.item.cycleTheme": "Alternar tema (Claro → Escuro → Sistema)",
|
||||||
|
"helpDialog.item.switchSessionTab": "Alternar aba de sessão",
|
||||||
"helpDialog.item.switchContextSurface": "Alternar superfície do painel de contexto (tecla numérica)",
|
"helpDialog.item.switchContextSurface": "Alternar superfície do painel de contexto (tecla numérica)",
|
||||||
"helpDialog.item.toggleServicesMenu": "Mostrar ou ocultar menu de serviços",
|
"helpDialog.item.toggleServicesMenu": "Mostrar ou ocultar menu de serviços",
|
||||||
"helpDialog.item.cycleServicesTab": "Alternar aba de serviços",
|
|
||||||
"helpDialog.item.openSettings": "Abrir configurações",
|
"helpDialog.item.openSettings": "Abrir configurações",
|
||||||
"helpDialog.keyCombiner.or": "ou",
|
"helpDialog.keyCombiner.or": "ou",
|
||||||
"helpDialog.proTips.title": "Dicas:",
|
"helpDialog.proTips.title": "Dicas:",
|
||||||
"helpDialog.proTips.commandPalette": "Use a paleta de comandos ({shortcut}) para acessar rapidamente todas as ações",
|
"helpDialog.proTips.commandPalette": "Use a paleta de comandos ({shortcut}) para acessar rapidamente todas as ações",
|
||||||
"helpDialog.proTips.recentSessions": "As cinco sessões mais recentes aparecem na paleta de comandos",
|
"helpDialog.proTips.recentSessions": "As cinco sessões mais recentes aparecem na paleta de comandos",
|
||||||
"helpDialog.proTips.themeCycling": "A alternância de tema lembra sua preferência entre sessões",
|
"helpDialog.proTips.leaderSequences": "Atalhos em duas etapas: pressione a combinação e depois a segunda tecla — Esc cancela",
|
||||||
"header.actions.rightSidebarWithShortcut": "Barra lateral direita ({shortcut})",
|
"header.actions.rightSidebarWithShortcut": "Barra lateral direita ({shortcut})",
|
||||||
"header.actions.toggleRightSidebarAria": "Mostrar ou ocultar barra lateral direita",
|
"header.actions.toggleRightSidebarAria": "Mostrar ou ocultar barra lateral direita",
|
||||||
"header.actions.openAppMenu": "Menu do OpenChamber",
|
"header.actions.openAppMenu": "Menu do OpenChamber",
|
||||||
@@ -2449,6 +2445,9 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
"commandPalette.item.toggleSidebar": "Mostrar ou ocultar barra lateral",
|
"commandPalette.item.toggleSidebar": "Mostrar ou ocultar barra lateral",
|
||||||
"commandPalette.item.showContextUsage": "Mostrar uso do contexto",
|
"commandPalette.item.showContextUsage": "Mostrar uso do contexto",
|
||||||
"commandPalette.item.toggleTerminal": "Mostrar ou ocultar terminal",
|
"commandPalette.item.toggleTerminal": "Mostrar ou ocultar terminal",
|
||||||
|
"commandPalette.item.cycleTheme": "Alternar tema",
|
||||||
|
"commandPalette.item.showOpenCodeStatus": "Mostrar status do OpenCode",
|
||||||
|
"commandPalette.item.toggleMemoryDebug": "Alternar painel de depuração de memória",
|
||||||
"commandPalette.item.openSettings": "Abrir configurações...",
|
"commandPalette.item.openSettings": "Abrir configurações...",
|
||||||
"commandPalette.session.untitled": "Sessão sem título",
|
"commandPalette.session.untitled": "Sessão sem título",
|
||||||
"openCodeStatusDialog.title": "Status do OpenCode",
|
"openCodeStatusDialog.title": "Status do OpenCode",
|
||||||
|
|||||||
@@ -1110,9 +1110,8 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label": "Розгорнути або згорнути термінал",
|
"settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label": "Розгорнути або згорнути термінал",
|
||||||
"settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label": "Додати виділення в чат",
|
"settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label": "Додати виділення в чат",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label": "Перемкнути бічну панель",
|
"settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label": "Перемкнути бічну панель",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label": 'Перемкнути контекстну панель',
|
"settings.openchamber.keyboardShortcuts.action.switch_session_tab.label": "Перемкнути вкладку сесії",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label": 'Відкрити поверхню Git',
|
"settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix": " + 1…9",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label": 'Відкрити поверхню файлів',
|
|
||||||
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.label": "Перемкнути поверхню панелі контексту",
|
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.label": "Перемкнути поверхню панелі контексту",
|
||||||
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix": " + 1…0",
|
"settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix": " + 1…0",
|
||||||
"settings.openchamber.keyboardShortcuts.action.new_chat.label": "Нова сесія",
|
"settings.openchamber.keyboardShortcuts.action.new_chat.label": "Нова сесія",
|
||||||
@@ -1120,9 +1119,7 @@ export const settingsDict = {
|
|||||||
"settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label": "Нова чернетка worktree",
|
"settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label": "Нова чернетка worktree",
|
||||||
"settings.openchamber.keyboardShortcuts.action.new_mini_chat.label": "Нове вікно Mini Chat",
|
"settings.openchamber.keyboardShortcuts.action.new_mini_chat.label": "Нове вікно Mini Chat",
|
||||||
"settings.openchamber.keyboardShortcuts.action.open_help.label": "Відкрити комбінації клавіш",
|
"settings.openchamber.keyboardShortcuts.action.open_help.label": "Відкрити комбінації клавіш",
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label": "Перемкнути контекстну панель плану",
|
|
||||||
"settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label": "Перемкнути меню сервісів",
|
"settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label": "Перемкнути меню сервісів",
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label": "Перемкнути вкладку сервісів",
|
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_theme.label": "Перемкнути тему",
|
"settings.openchamber.keyboardShortcuts.action.cycle_theme.label": "Перемкнути тему",
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_agent.label": "Перемкнути агента",
|
"settings.openchamber.keyboardShortcuts.action.cycle_agent.label": "Перемкнути агента",
|
||||||
"settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label": "Перемкнути улюблену модель вперед",
|
"settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label": "Перемкнути улюблену модель вперед",
|
||||||
|
|||||||
@@ -1836,22 +1836,18 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
"helpDialog.item.focusChatInput": "Фокус на полі вводу чату",
|
"helpDialog.item.focusChatInput": "Фокус на полі вводу чату",
|
||||||
"helpDialog.item.togglePromptNavigator": "Показати або приховати навігатор промптів",
|
"helpDialog.item.togglePromptNavigator": "Показати або приховати навігатор промптів",
|
||||||
"helpDialog.item.abortActiveRun": "Перервати активний запуск (подвійне натискання)",
|
"helpDialog.item.abortActiveRun": "Перервати активний запуск (подвійне натискання)",
|
||||||
"helpDialog.item.toggleRightSidebar": 'Перемкнути контекстну панель',
|
|
||||||
"helpDialog.item.openRightSidebarGitTab": 'Відкрити поверхню Git',
|
|
||||||
"helpDialog.item.openRightSidebarFilesTab": 'Відкрити поверхню файлів',
|
|
||||||
"helpDialog.item.toggleTerminalDock": "Перемкнути панель терміналу",
|
"helpDialog.item.toggleTerminalDock": "Перемкнути панель терміналу",
|
||||||
"helpDialog.item.toggleTerminalExpanded": "Розгорнути або згорнути термінал",
|
"helpDialog.item.toggleTerminalExpanded": "Розгорнути або згорнути термінал",
|
||||||
"helpDialog.item.togglePlanContextPanel": "Перемкнути панель контексту плану",
|
|
||||||
"helpDialog.item.cycleTheme": "Перемкнути тему (Світла → Темна → Системна)",
|
"helpDialog.item.cycleTheme": "Перемкнути тему (Світла → Темна → Системна)",
|
||||||
|
"helpDialog.item.switchSessionTab": "Перемкнути вкладку сесії",
|
||||||
"helpDialog.item.switchContextSurface": "Перемкнути поверхню панелі контексту (цифрова клавіша)",
|
"helpDialog.item.switchContextSurface": "Перемкнути поверхню панелі контексту (цифрова клавіша)",
|
||||||
"helpDialog.item.toggleServicesMenu": "Перемкнути меню сервісів",
|
"helpDialog.item.toggleServicesMenu": "Перемкнути меню сервісів",
|
||||||
"helpDialog.item.cycleServicesTab": "Перемкнути вкладку сервісів",
|
|
||||||
"helpDialog.item.openSettings": "Відкрити налаштування",
|
"helpDialog.item.openSettings": "Відкрити налаштування",
|
||||||
"helpDialog.keyCombiner.or": "або",
|
"helpDialog.keyCombiner.or": "або",
|
||||||
"helpDialog.proTips.title": "Поради:",
|
"helpDialog.proTips.title": "Поради:",
|
||||||
"helpDialog.proTips.commandPalette": "Використовуйте палітру команд ({shortcut}), щоб швидко перейти до будь-якої дії",
|
"helpDialog.proTips.commandPalette": "Використовуйте палітру команд ({shortcut}), щоб швидко перейти до будь-якої дії",
|
||||||
"helpDialog.proTips.recentSessions": "5 останніх сесій відображаються на панелі команд",
|
"helpDialog.proTips.recentSessions": "5 останніх сесій відображаються на панелі команд",
|
||||||
"helpDialog.proTips.themeCycling": "Перемикання теми запам’ятовує ваші переваги протягом сесій",
|
"helpDialog.proTips.leaderSequences": "Двокрокові шорткати: натисни комбінацію, потім другу клавішу — Esc скасовує",
|
||||||
"header.actions.rightSidebarWithShortcut": "Права бічна панель ({shortcut})",
|
"header.actions.rightSidebarWithShortcut": "Права бічна панель ({shortcut})",
|
||||||
"header.actions.toggleRightSidebarAria": "Перемкнути праву бічну панель",
|
"header.actions.toggleRightSidebarAria": "Перемкнути праву бічну панель",
|
||||||
"header.actions.openAppMenu": "Меню OpenChamber",
|
"header.actions.openAppMenu": "Меню OpenChamber",
|
||||||
@@ -2449,6 +2445,9 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
"commandPalette.item.toggleSidebar": "Перемкнути бічну панель",
|
"commandPalette.item.toggleSidebar": "Перемкнути бічну панель",
|
||||||
"commandPalette.item.showContextUsage": "Показати використання контексту",
|
"commandPalette.item.showContextUsage": "Показати використання контексту",
|
||||||
"commandPalette.item.toggleTerminal": "Перемкнути термінал",
|
"commandPalette.item.toggleTerminal": "Перемкнути термінал",
|
||||||
|
"commandPalette.item.cycleTheme": "Перемкнути тему",
|
||||||
|
"commandPalette.item.showOpenCodeStatus": "Показати статус OpenCode",
|
||||||
|
"commandPalette.item.toggleMemoryDebug": "Показати/сховати панель memory debug",
|
||||||
"commandPalette.item.openSettings": "Відкрити налаштування...",
|
"commandPalette.item.openSettings": "Відкрити налаштування...",
|
||||||
"commandPalette.session.untitled": "Сесія без назви",
|
"commandPalette.session.untitled": "Сесія без назви",
|
||||||
"openCodeStatusDialog.title": "Статус OpenCode",
|
"openCodeStatusDialog.title": "Статус OpenCode",
|
||||||
|
|||||||
@@ -1110,9 +1110,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': '切换终端展开',
|
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': '切换终端展开',
|
||||||
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '将选中内容添加到聊天',
|
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '将选中内容添加到聊天',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': '切换侧边栏',
|
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': '切换侧边栏',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': '切换上下文面板',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.label': '切换会话标签页',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': '打开 Git 界面',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix': ' + 1…9',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label': '打开文件界面',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': '切换上下文面板界面',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': '切换上下文面板界面',
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_chat.label': '新建会话',
|
'settings.openchamber.keyboardShortcuts.action.new_chat.label': '新建会话',
|
||||||
@@ -1120,9 +1119,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': '新建工作树草稿',
|
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': '新建工作树草稿',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': '新建 Mini Chat 窗口',
|
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': '新建 Mini Chat 窗口',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_help.label': '打开键盘快捷键',
|
'settings.openchamber.keyboardShortcuts.action.open_help.label': '打开键盘快捷键',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label': '切换上下文面板中的计划',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': '切换服务菜单',
|
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': '切换服务菜单',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': '轮换服务菜单标签',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': '轮换主题',
|
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': '轮换主题',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': '轮换智能体',
|
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': '轮换智能体',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': '向前轮换收藏模型',
|
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': '向前轮换收藏模型',
|
||||||
|
|||||||
@@ -1824,22 +1824,18 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'helpDialog.item.focusChatInput': '聚焦聊天输入框',
|
'helpDialog.item.focusChatInput': '聚焦聊天输入框',
|
||||||
'helpDialog.item.togglePromptNavigator': '显示或隐藏提示词导航',
|
'helpDialog.item.togglePromptNavigator': '显示或隐藏提示词导航',
|
||||||
'helpDialog.item.abortActiveRun': '中止当前运行(双击)',
|
'helpDialog.item.abortActiveRun': '中止当前运行(双击)',
|
||||||
'helpDialog.item.toggleRightSidebar': '切换上下文面板',
|
|
||||||
'helpDialog.item.openRightSidebarGitTab': '打开 Git 界面',
|
|
||||||
'helpDialog.item.openRightSidebarFilesTab': '打开文件界面',
|
|
||||||
'helpDialog.item.toggleTerminalDock': '切换终端停靠栏',
|
'helpDialog.item.toggleTerminalDock': '切换终端停靠栏',
|
||||||
'helpDialog.item.toggleTerminalExpanded': '切换终端展开状态',
|
'helpDialog.item.toggleTerminalExpanded': '切换终端展开状态',
|
||||||
'helpDialog.item.togglePlanContextPanel': '切换计划上下文面板',
|
|
||||||
'helpDialog.item.cycleTheme': '循环切换主题(浅色 → 深色 → 跟随系统)',
|
'helpDialog.item.cycleTheme': '循环切换主题(浅色 → 深色 → 跟随系统)',
|
||||||
|
'helpDialog.item.switchSessionTab': '切换会话标签页',
|
||||||
'helpDialog.item.switchContextSurface': '切换上下文面板界面(数字键)',
|
'helpDialog.item.switchContextSurface': '切换上下文面板界面(数字键)',
|
||||||
'helpDialog.item.toggleServicesMenu': '切换服务菜单',
|
'helpDialog.item.toggleServicesMenu': '切换服务菜单',
|
||||||
'helpDialog.item.cycleServicesTab': '循环服务标签',
|
|
||||||
'helpDialog.item.openSettings': '打开设置',
|
'helpDialog.item.openSettings': '打开设置',
|
||||||
'helpDialog.keyCombiner.or': '或',
|
'helpDialog.keyCombiner.or': '或',
|
||||||
'helpDialog.proTips.title': '使用提示:',
|
'helpDialog.proTips.title': '使用提示:',
|
||||||
'helpDialog.proTips.commandPalette': '使用命令面板({shortcut})可快速访问所有操作',
|
'helpDialog.proTips.commandPalette': '使用命令面板({shortcut})可快速访问所有操作',
|
||||||
'helpDialog.proTips.recentSessions': '最近 5 个会话会显示在命令面板中',
|
'helpDialog.proTips.recentSessions': '最近 5 个会话会显示在命令面板中',
|
||||||
'helpDialog.proTips.themeCycling': '主题循环会记住你在各会话中的偏好',
|
'helpDialog.proTips.leaderSequences': '两段式快捷键:先按组合键,再按第二个键(Esc 取消)',
|
||||||
'header.actions.rightSidebarWithShortcut': '右侧边栏({shortcut})',
|
'header.actions.rightSidebarWithShortcut': '右侧边栏({shortcut})',
|
||||||
'header.actions.toggleRightSidebarAria': '切换右侧边栏',
|
'header.actions.toggleRightSidebarAria': '切换右侧边栏',
|
||||||
'header.actions.openAppMenu': 'OpenChamber 菜单',
|
'header.actions.openAppMenu': 'OpenChamber 菜单',
|
||||||
@@ -2449,6 +2445,9 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'commandPalette.item.toggleSidebar': '切换侧边栏',
|
'commandPalette.item.toggleSidebar': '切换侧边栏',
|
||||||
'commandPalette.item.showContextUsage': '显示上下文用量',
|
'commandPalette.item.showContextUsage': '显示上下文用量',
|
||||||
'commandPalette.item.toggleTerminal': '切换终端',
|
'commandPalette.item.toggleTerminal': '切换终端',
|
||||||
|
'commandPalette.item.cycleTheme': '轮换主题',
|
||||||
|
'commandPalette.item.showOpenCodeStatus': '显示 OpenCode 状态',
|
||||||
|
'commandPalette.item.toggleMemoryDebug': '切换内存调试面板',
|
||||||
'commandPalette.item.openSettings': '打开设置...',
|
'commandPalette.item.openSettings': '打开设置...',
|
||||||
'commandPalette.session.untitled': '未命名会话',
|
'commandPalette.session.untitled': '未命名会话',
|
||||||
'openCodeStatusDialog.title': 'OpenCode 状态',
|
'openCodeStatusDialog.title': 'OpenCode 状态',
|
||||||
|
|||||||
@@ -1017,9 +1017,8 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': '切換終端機展開',
|
'settings.openchamber.keyboardShortcuts.action.toggle_terminal_expanded.label': '切換終端機展開',
|
||||||
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '將選取內容加入聊天',
|
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label': '將選取內容加入聊天',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': '切換側邊欄',
|
'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label': '切換側邊欄',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label': '切換上下文面板',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.label': '切換工作階段分頁',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label': '開啟 Git 介面',
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.suffix': ' + 1…9',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label': '開啟檔案介面',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': '切換上下文面板介面',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label': '切換上下文面板介面',
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.suffix': ' + 1…0',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_chat.label': '新建工作階段',
|
'settings.openchamber.keyboardShortcuts.action.new_chat.label': '新建工作階段',
|
||||||
@@ -1027,9 +1026,7 @@ export const settingsDict = {
|
|||||||
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': '新增 worktree 草稿',
|
'settings.openchamber.keyboardShortcuts.action.new_chat_worktree.label': '新增 worktree 草稿',
|
||||||
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': '新建 Mini Chat 視窗',
|
'settings.openchamber.keyboardShortcuts.action.new_mini_chat.label': '新建 Mini Chat 視窗',
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_help.label': '開啟鍵盤快速鍵',
|
'settings.openchamber.keyboardShortcuts.action.open_help.label': '開啟鍵盤快速鍵',
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label': '切換上下文面板中的計畫',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': '切換服務選單',
|
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label': '切換服務選單',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label': '輪換服務選單分頁',
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': '輪換主題',
|
'settings.openchamber.keyboardShortcuts.action.cycle_theme.label': '輪換主題',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': '輪換 agent',
|
'settings.openchamber.keyboardShortcuts.action.cycle_agent.label': '輪換 agent',
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': '向前輪換收藏模型',
|
'settings.openchamber.keyboardShortcuts.action.cycle_favorite_model_forward.label': '向前輪換收藏模型',
|
||||||
|
|||||||
@@ -1828,22 +1828,18 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'helpDialog.item.focusChatInput': '聚焦聊天輸入框',
|
'helpDialog.item.focusChatInput': '聚焦聊天輸入框',
|
||||||
'helpDialog.item.togglePromptNavigator': '顯示或隱藏提示詞導覽',
|
'helpDialog.item.togglePromptNavigator': '顯示或隱藏提示詞導覽',
|
||||||
'helpDialog.item.abortActiveRun': '中止目前執行(連按兩下)',
|
'helpDialog.item.abortActiveRun': '中止目前執行(連按兩下)',
|
||||||
'helpDialog.item.toggleRightSidebar': '切換上下文面板',
|
|
||||||
'helpDialog.item.openRightSidebarGitTab': '開啟 Git 介面',
|
|
||||||
'helpDialog.item.openRightSidebarFilesTab': '開啟檔案介面',
|
|
||||||
'helpDialog.item.toggleTerminalDock': '切換終端機停靠欄',
|
'helpDialog.item.toggleTerminalDock': '切換終端機停靠欄',
|
||||||
'helpDialog.item.toggleTerminalExpanded': '切換終端機展開狀態',
|
'helpDialog.item.toggleTerminalExpanded': '切換終端機展開狀態',
|
||||||
'helpDialog.item.togglePlanContextPanel': '切換計畫上下文面板',
|
|
||||||
'helpDialog.item.cycleTheme': '循環切換主題(淺色 → 深色 → 跟隨系統)',
|
'helpDialog.item.cycleTheme': '循環切換主題(淺色 → 深色 → 跟隨系統)',
|
||||||
|
'helpDialog.item.switchSessionTab': '切換工作階段分頁',
|
||||||
'helpDialog.item.switchContextSurface': '切換上下文面板介面(數字鍵)',
|
'helpDialog.item.switchContextSurface': '切換上下文面板介面(數字鍵)',
|
||||||
'helpDialog.item.toggleServicesMenu': '切換服務選單',
|
'helpDialog.item.toggleServicesMenu': '切換服務選單',
|
||||||
'helpDialog.item.cycleServicesTab': '循環服務標籤',
|
|
||||||
'helpDialog.item.openSettings': '開啟設定',
|
'helpDialog.item.openSettings': '開啟設定',
|
||||||
'helpDialog.keyCombiner.or': '或',
|
'helpDialog.keyCombiner.or': '或',
|
||||||
'helpDialog.proTips.title': '使用提示:',
|
'helpDialog.proTips.title': '使用提示:',
|
||||||
'helpDialog.proTips.commandPalette': '使用命令面板({shortcut})可快速存取所有操作',
|
'helpDialog.proTips.commandPalette': '使用命令面板({shortcut})可快速存取所有操作',
|
||||||
'helpDialog.proTips.recentSessions': '最近 5 個會话會顯示在命令面板中',
|
'helpDialog.proTips.recentSessions': '最近 5 個會话會顯示在命令面板中',
|
||||||
'helpDialog.proTips.themeCycling': '主題循環會記住你在各會話中的偏好',
|
'helpDialog.proTips.leaderSequences': '兩段式快捷鍵:先按組合鍵,再按第二個鍵(Esc 取消)',
|
||||||
'header.actions.rightSidebarWithShortcut': '右側邊欄({shortcut})',
|
'header.actions.rightSidebarWithShortcut': '右側邊欄({shortcut})',
|
||||||
'header.actions.toggleRightSidebarAria': '切換右側邊欄',
|
'header.actions.toggleRightSidebarAria': '切換右側邊欄',
|
||||||
'header.actions.openAppMenu': 'OpenChamber 選單',
|
'header.actions.openAppMenu': 'OpenChamber 選單',
|
||||||
@@ -2453,6 +2449,9 @@ export const dict: Record<I18nKey, string> = {
|
|||||||
'commandPalette.item.toggleSidebar': '切換側邊欄',
|
'commandPalette.item.toggleSidebar': '切換側邊欄',
|
||||||
'commandPalette.item.showContextUsage': '顯示上下文用量',
|
'commandPalette.item.showContextUsage': '顯示上下文用量',
|
||||||
'commandPalette.item.toggleTerminal': '切換終端機',
|
'commandPalette.item.toggleTerminal': '切換終端機',
|
||||||
|
'commandPalette.item.cycleTheme': '輪換主題',
|
||||||
|
'commandPalette.item.showOpenCodeStatus': '顯示 OpenCode 狀態',
|
||||||
|
'commandPalette.item.toggleMemoryDebug': '切換記憶體偵錯面板',
|
||||||
'commandPalette.item.openSettings': '開啟設定...',
|
'commandPalette.item.openSettings': '開啟設定...',
|
||||||
'commandPalette.session.untitled': '未命名會話',
|
'commandPalette.session.untitled': '未命名會話',
|
||||||
'openCodeStatusDialog.title': 'OpenCode 狀態',
|
'openCodeStatusDialog.title': 'OpenCode 狀態',
|
||||||
|
|||||||
@@ -9,6 +9,23 @@ import { useSessionUIStore } from '@/sync/session-ui-store';
|
|||||||
* count as neighbours — the same rule the strip uses for rendering. The
|
* count as neighbours — the same rule the strip uses for rendering. The
|
||||||
* session itself is never touched.
|
* session itself is never touched.
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* Activate the nth (0-based) header session tab, counting only tabs whose
|
||||||
|
* session is present in the loaded session list — the same rule the strip
|
||||||
|
* uses for rendering, so the digit matches what the user sees.
|
||||||
|
*/
|
||||||
|
export const activateSessionTabByIndex = (index: number): boolean => {
|
||||||
|
const { tabIds } = useSessionTabsStore.getState();
|
||||||
|
const sessionsById = new Map(
|
||||||
|
useGlobalSessionsStore.getState().activeSessions.map((session) => [session.id, session] as const),
|
||||||
|
);
|
||||||
|
const renderable = tabIds.filter((id) => sessionsById.has(id));
|
||||||
|
const session = renderable[index] ? sessionsById.get(renderable[index]) : null;
|
||||||
|
if (!session) return false;
|
||||||
|
useSessionUIStore.getState().setCurrentSession(session.id, resolveGlobalSessionDirectory(session));
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
export const closeSessionTabAndActivateNeighbour = (sessionId: string): void => {
|
export const closeSessionTabAndActivateNeighbour = (sessionId: string): void => {
|
||||||
const { tabIds, closeTab } = useSessionTabsStore.getState();
|
const { tabIds, closeTab } = useSessionTabsStore.getState();
|
||||||
if (!tabIds.includes(sessionId)) return;
|
if (!tabIds.includes(sessionId)) return;
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ Component interaction keys that are not application commands, such as list navig
|
|||||||
|
|
||||||
# Binding rules
|
# Binding rules
|
||||||
|
|
||||||
Bindings remain persisted as `Record<string, string>`. Each binding has one chord or at most two space-separated chords, such as `mod+s p`. `mod` is the platform-neutral primary modifier (Command on macOS, Control elsewhere), while `alt` is the platform-neutral alternate modifier (Option on macOS, Alt elsewhere); `command`, `cmd`, `meta`, and `option` are accepted input aliases but normalize to those canonical tokens. `normalizeCombo`, `parseShortcut`, `formatShortcutForDisplay`, and `getShortcutConflict` provide the shared parsing and validation behavior. Display formatting uses macOS keyboard symbols (`⌘`, `⌥`, `⌃`, `⇧`) on macOS and named modifiers (`Ctrl`, `Alt`, `Shift`) elsewhere, including tooltip and accessible text consumers. 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+k p`. `mod` is the platform-neutral primary modifier (Command on macOS, Control elsewhere), while `alt` is the platform-neutral alternate modifier (Option on macOS, Alt elsewhere); `command`, `cmd`, `meta`, and `option` are accepted input aliases but normalize to those canonical tokens. `normalizeCombo`, `parseShortcut`, `formatShortcutForDisplay`, and `getShortcutConflict` provide the shared parsing and validation behavior. Display formatting uses macOS keyboard symbols (`⌘`, `⌥`, `⌃`, `⇧`) on macOS and named modifiers (`Ctrl`, `Alt`, `Shift`) elsewhere, including tooltip and accessible text consumers. 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`, `mod+s g`, and `mod+s l` to the draft target pickers and session list.
|
The default layout follows three modes: single chords for everyday actions, the `mod+k` leader for open/go actions (`mod+k p`, `mod+k g`, `mod+k l`, `mod+k t`, `mod+k n`, `mod+k i`, `mod+k h`), and held digit prefixes — held `mod` + digit switches header session tabs, held `mod+alt` + digit switches context panel surfaces. Every schema action ships with a default binding; palette-only commands (context surfaces, OpenCode status, memory debug) live outside the schema and the palette invokes their owning modules directly. Single-chord handlers still get the first chance at a leader's chord; returning `false` lets the dispatcher arm the sequence.
|
||||||
|
|
||||||
The internal `switch_tab_*` bindings remain available to mobile handlers. Desktop numeric context-surface switching is resolved by the configurable `switch_context_surface` prefix before normal dispatcher matching and falls through on mobile.
|
The internal `switch_tab_*` bindings remain available to mobile handlers. Desktop numeric context-surface switching is resolved by the configurable `switch_context_surface` prefix before normal dispatcher matching and falls through on mobile.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { describe, expect, test } from 'bun:test';
|
import { describe, expect, test } from 'bun:test';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
eventMatchesShortcut,
|
||||||
eventMatchesShortcutPrefix,
|
eventMatchesShortcutPrefix,
|
||||||
formatShortcutForDisplay,
|
formatShortcutForDisplay,
|
||||||
getEffectiveShortcutPrefix,
|
getEffectiveShortcutPrefix,
|
||||||
@@ -9,12 +10,13 @@ import {
|
|||||||
isShortcutPrefixHeld,
|
isShortcutPrefixHeld,
|
||||||
normalizeCombo,
|
normalizeCombo,
|
||||||
parseShortcut,
|
parseShortcut,
|
||||||
|
resolveShortcutEventDigit,
|
||||||
UNASSIGNED_SHORTCUT,
|
UNASSIGNED_SHORTCUT,
|
||||||
} from './index';
|
} from './index';
|
||||||
|
|
||||||
describe('getEffectiveShortcutPrefix', () => {
|
describe('getEffectiveShortcutPrefix', () => {
|
||||||
test('falls back to the action default (bare mod) when unset', () => {
|
test('falls back to the action default (bare mod+alt) when unset', () => {
|
||||||
expect(getEffectiveShortcutPrefix('switch_context_surface', {})).toBe('mod');
|
expect(getEffectiveShortcutPrefix('switch_context_surface', {})).toBe('mod+alt');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('honors modifier + key overrides', () => {
|
test('honors modifier + key overrides', () => {
|
||||||
@@ -126,3 +128,31 @@ describe('platform shortcut labels', () => {
|
|||||||
expect(formatShortcutForDisplay('alt', 'Unassigned', 'other')).toBe('Alt');
|
expect(formatShortcutForDisplay('alt', 'Unassigned', 'other')).toBe('Alt');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('layout-independent key matching', () => {
|
||||||
|
const event = (overrides: Partial<KeyboardEvent>): KeyboardEvent =>
|
||||||
|
// SAFETY: the matcher only reads the modifier flags, key, and code
|
||||||
|
// provided here; a full KeyboardEvent is not constructible in bun tests.
|
||||||
|
({ altKey: false, ctrlKey: false, metaKey: false, shiftKey: false, key: '', code: '', ...overrides }) as KeyboardEvent;
|
||||||
|
|
||||||
|
test('a non-Latin layout letter matches through the physical key code', () => {
|
||||||
|
expect(eventMatchesShortcut(event({ ctrlKey: true, key: 'л', code: 'KeyK' }), 'mod+k')).toBe(true);
|
||||||
|
expect(eventMatchesShortcut(event({ key: 'з', code: 'KeyP' }), 'p')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('macOS Option symbol substitution matches through the digit code', () => {
|
||||||
|
expect(eventMatchesShortcut(event({ ctrlKey: true, altKey: true, key: '¡', code: 'Digit1' }), 'mod+alt+1')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Latin layouts that move keys keep their key-based meaning', () => {
|
||||||
|
// Dvorak: physical KeyT produces "y"; the binding follows the character.
|
||||||
|
expect(eventMatchesShortcut(event({ ctrlKey: true, key: 'y', code: 'KeyT' }), 'mod+y')).toBe(true);
|
||||||
|
expect(eventMatchesShortcut(event({ ctrlKey: true, key: 'y', code: 'KeyT' }), 'mod+t')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('resolveShortcutEventDigit reads the digit from the code under Option', () => {
|
||||||
|
expect(resolveShortcutEventDigit({ key: '¡', code: 'Digit1' })).toBe('1');
|
||||||
|
expect(resolveShortcutEventDigit({ key: '5', code: 'Digit5' })).toBe('5');
|
||||||
|
expect(resolveShortcutEventDigit({ key: 'a', code: 'KeyA' })).toBe(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -247,6 +247,50 @@ export function isRiskyBrowserShortcut(combo: ShortcutCombo): boolean {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CODE_KEY_MAP = new Map<string, string>([
|
||||||
|
['Comma', ','],
|
||||||
|
['Period', '.'],
|
||||||
|
['Slash', '/'],
|
||||||
|
['Backquote', '`'],
|
||||||
|
['BracketLeft', '['],
|
||||||
|
['BracketRight', ']'],
|
||||||
|
['Semicolon', ';'],
|
||||||
|
['Quote', "'"],
|
||||||
|
['Minus', '-'],
|
||||||
|
['Equal', '='],
|
||||||
|
]);
|
||||||
|
|
||||||
|
function keyFromEventCode(code: string): string | null {
|
||||||
|
if (code.startsWith('Key') && code.length === 4) return code.slice(3).toLowerCase();
|
||||||
|
if (code.startsWith('Digit') && code.length === 6) return code.slice(5);
|
||||||
|
return CODE_KEY_MAP.get(code) ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The character a physical key press should match against bindings. `key`
|
||||||
|
* carries the layout-produced character: Option on macOS substitutes symbols
|
||||||
|
* ("¡" for ⌥1) and non-Latin layouts substitute their own alphabet ("л" for
|
||||||
|
* K). Both keep the physical key in `code`, so those two cases fall back to
|
||||||
|
* it; Latin layouts that MOVE keys (Dvorak, AZERTY) keep their `key`-based
|
||||||
|
* meaning untouched.
|
||||||
|
*/
|
||||||
|
export function resolveShortcutEventKey(
|
||||||
|
event: Pick<KeyboardEvent, 'key' | 'code' | 'altKey'>,
|
||||||
|
): string {
|
||||||
|
const raw = event.key;
|
||||||
|
if (event.altKey) return keyFromEventCode(event.code) ?? raw;
|
||||||
|
if (raw.length === 1 && raw.charCodeAt(0) > 127) return keyFromEventCode(event.code) ?? raw;
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The digit a press addresses, layout- and Option-proof via `code`. */
|
||||||
|
export function resolveShortcutEventDigit(
|
||||||
|
event: Pick<KeyboardEvent, 'key' | 'code'>,
|
||||||
|
): string | null {
|
||||||
|
if (event.code.startsWith('Digit') && event.code.length === 6) return event.code.slice(5);
|
||||||
|
return event.key.length === 1 && event.key >= '0' && event.key <= '9' ? event.key : null;
|
||||||
|
}
|
||||||
|
|
||||||
export function eventMatchesShortcut(
|
export function eventMatchesShortcut(
|
||||||
event: KeyboardEvent | React.KeyboardEvent,
|
event: KeyboardEvent | React.KeyboardEvent,
|
||||||
combo: ShortcutCombo,
|
combo: ShortcutCombo,
|
||||||
@@ -280,16 +324,7 @@ export function eventMatchesShortcut(
|
|||||||
if (event.ctrlKey && !ctrlUsedAsMod) return false;
|
if (event.ctrlKey && !ctrlUsedAsMod) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let eventKeyRaw = event.key;
|
return keyToShortcutToken(resolveShortcutEventKey(event)) === keyToShortcutToken(chord.key);
|
||||||
if (event.altKey) {
|
|
||||||
if (event.code.startsWith('Key') && event.code.length === 4) {
|
|
||||||
eventKeyRaw = event.code.slice(3).toLowerCase();
|
|
||||||
} else if (event.code.startsWith('Digit') && event.code.length === 6) {
|
|
||||||
eventKeyRaw = event.code.slice(5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return keyToShortcutToken(eventKeyRaw) === keyToShortcutToken(chord.key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isShortcutPrefixHeld(prefixCombo: ShortcutCombo, heldKeys: ReadonlySet<string>): boolean {
|
export function isShortcutPrefixHeld(prefixCombo: ShortcutCombo, heldKeys: ReadonlySet<string>): boolean {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ type ShortcutCategory = 'session' | 'models' | 'panels' | 'navigation' | 'applic
|
|||||||
type ShortcutConfig = {
|
type ShortcutConfig = {
|
||||||
id: string;
|
id: string;
|
||||||
defaultBinding: ShortcutCombo;
|
defaultBinding: ShortcutCombo;
|
||||||
allowsSequenceFallback?: true;
|
|
||||||
/** The binding is a bare-modifier chord prefix (completed by another key);
|
/** The binding is a bare-modifier chord prefix (completed by another key);
|
||||||
conflict resolution compares its prefix rather than a full combo. */
|
conflict resolution compares its prefix rather than a full combo. */
|
||||||
prefixStyle?: true;
|
prefixStyle?: true;
|
||||||
@@ -17,12 +16,18 @@ type ShortcutConfig = {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Default layout, unified around three modes:
|
||||||
|
// - Single chords for everyday actions.
|
||||||
|
// - The mod+k leader for "open/go" actions, second key mnemonic.
|
||||||
|
// - Held mod + digit switches header session tabs; held mod+alt + digit
|
||||||
|
// switches context panel surfaces (mod+shift+digit is reserved by macOS
|
||||||
|
// screenshots).
|
||||||
|
// Everything else lives only in the command palette, outside this schema.
|
||||||
const SHORTCUT_GROUPS = {
|
const SHORTCUT_GROUPS = {
|
||||||
session: [
|
session: [
|
||||||
{
|
{
|
||||||
id: 'add_selection_to_chat',
|
id: 'add_selection_to_chat',
|
||||||
defaultBinding: 'mod+l',
|
defaultBinding: 'mod+l',
|
||||||
allowsSequenceFallback: true,
|
|
||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey:
|
settingsLabelKey:
|
||||||
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label',
|
'settings.openchamber.keyboardShortcuts.action.add_selection_to_chat.label',
|
||||||
@@ -35,7 +40,7 @@ const SHORTCUT_GROUPS = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'open_timeline_dialog',
|
id: 'open_timeline_dialog',
|
||||||
defaultBinding: 'mod+t',
|
defaultBinding: 'mod+k t',
|
||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey:
|
settingsLabelKey:
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label',
|
'settings.openchamber.keyboardShortcuts.action.open_timeline_dialog.label',
|
||||||
@@ -54,21 +59,21 @@ const SHORTCUT_GROUPS = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'open_draft_project_picker',
|
id: 'open_draft_project_picker',
|
||||||
defaultBinding: 'mod+s p',
|
defaultBinding: 'mod+k p',
|
||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey:
|
settingsLabelKey:
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_project_picker.label',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'open_draft_worktree_picker',
|
id: 'open_draft_worktree_picker',
|
||||||
defaultBinding: 'mod+s g',
|
defaultBinding: 'mod+k g',
|
||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey:
|
settingsLabelKey:
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label',
|
'settings.openchamber.keyboardShortcuts.action.open_draft_worktree_picker.label',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'open_session_list',
|
id: 'open_session_list',
|
||||||
defaultBinding: 'mod+s l',
|
defaultBinding: 'mod+k l',
|
||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey:
|
settingsLabelKey:
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_session_list.label',
|
'settings.openchamber.keyboardShortcuts.action.open_session_list.label',
|
||||||
@@ -146,65 +151,45 @@ const SHORTCUT_GROUPS = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'toggle_sidebar',
|
id: 'toggle_sidebar',
|
||||||
defaultBinding: 'mod+alt+l',
|
defaultBinding: 'mod+b',
|
||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey: 'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label',
|
settingsLabelKey: 'settings.openchamber.keyboardShortcuts.action.toggle_sidebar.label',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'toggle_prompt_navigator',
|
id: 'toggle_prompt_navigator',
|
||||||
defaultBinding: 'mod+alt+p',
|
defaultBinding: 'mod+k n',
|
||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey:
|
settingsLabelKey:
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label',
|
'settings.openchamber.keyboardShortcuts.action.toggle_prompt_navigator.label',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'toggle_right_sidebar',
|
id: 'switch_session_tab',
|
||||||
defaultBinding: 'mod+b',
|
|
||||||
customizable: true,
|
|
||||||
settingsLabelKey:
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_right_sidebar.label',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'open_right_sidebar_git',
|
|
||||||
defaultBinding: 'mod+shift+g',
|
|
||||||
customizable: true,
|
|
||||||
settingsLabelKey:
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_git.label',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'open_right_sidebar_files',
|
|
||||||
defaultBinding: 'mod+shift+f',
|
|
||||||
customizable: true,
|
|
||||||
settingsLabelKey:
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_right_sidebar_files.label',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'switch_context_surface',
|
|
||||||
defaultBinding: 'mod',
|
defaultBinding: 'mod',
|
||||||
// The binding is a bare modifier acting as a chord prefix (completed by
|
// The binding is a bare modifier acting as a chord prefix (completed by
|
||||||
// a digit); conflict resolution must compare its PREFIX, not a combo.
|
// a digit); conflict resolution must compare its PREFIX, not a combo.
|
||||||
prefixStyle: true,
|
prefixStyle: true,
|
||||||
customizable: true,
|
customizable: true,
|
||||||
|
settingsLabelKey:
|
||||||
|
'settings.openchamber.keyboardShortcuts.action.switch_session_tab.label',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'switch_context_surface',
|
||||||
|
defaultBinding: 'mod+alt',
|
||||||
|
prefixStyle: true,
|
||||||
|
customizable: true,
|
||||||
settingsLabelKey:
|
settingsLabelKey:
|
||||||
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label',
|
'settings.openchamber.keyboardShortcuts.action.switch_context_surface.label',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'toggle_context_plan',
|
|
||||||
defaultBinding: 'mod+shift+p',
|
|
||||||
customizable: true,
|
|
||||||
settingsLabelKey:
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_context_plan.label',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id: 'toggle_services_menu',
|
id: 'toggle_services_menu',
|
||||||
defaultBinding: 'mod+shift+s',
|
defaultBinding: 'mod+k i',
|
||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey:
|
settingsLabelKey:
|
||||||
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label',
|
'settings.openchamber.keyboardShortcuts.action.toggle_services_menu.label',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
navigation: [
|
navigation: [
|
||||||
{ id: 'save_file', defaultBinding: 'mod+s', customizable: false, allowsSequenceFallback: true },
|
{ id: 'save_file', defaultBinding: 'mod+s', customizable: false },
|
||||||
{ id: 'find_in_file', defaultBinding: 'mod+f', customizable: false },
|
{ id: 'find_in_file', defaultBinding: 'mod+f', customizable: false },
|
||||||
{
|
{
|
||||||
id: 'open_go_to_line',
|
id: 'open_go_to_line',
|
||||||
@@ -212,13 +197,6 @@ const SHORTCUT_GROUPS = {
|
|||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey: 'settings.openchamber.keyboardShortcuts.action.open_go_to_line.label',
|
settingsLabelKey: 'settings.openchamber.keyboardShortcuts.action.open_go_to_line.label',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
id: 'cycle_services_tab',
|
|
||||||
defaultBinding: 'mod+shift+[',
|
|
||||||
customizable: true,
|
|
||||||
settingsLabelKey:
|
|
||||||
'settings.openchamber.keyboardShortcuts.action.cycle_services_tab.label',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
application: [
|
application: [
|
||||||
{
|
{
|
||||||
@@ -228,7 +206,6 @@ const SHORTCUT_GROUPS = {
|
|||||||
settingsLabelKey:
|
settingsLabelKey:
|
||||||
'settings.openchamber.keyboardShortcuts.action.open_command_palette.label',
|
'settings.openchamber.keyboardShortcuts.action.open_command_palette.label',
|
||||||
},
|
},
|
||||||
{ id: 'open_status', defaultBinding: 'mod+shift+o', customizable: false },
|
|
||||||
{
|
{
|
||||||
id: 'open_settings',
|
id: 'open_settings',
|
||||||
defaultBinding: 'mod+comma',
|
defaultBinding: 'mod+comma',
|
||||||
@@ -237,17 +214,16 @@ const SHORTCUT_GROUPS = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'open_help',
|
id: 'open_help',
|
||||||
defaultBinding: 'mod+.',
|
defaultBinding: 'mod+k h',
|
||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey: 'settings.openchamber.keyboardShortcuts.action.open_help.label',
|
settingsLabelKey: 'settings.openchamber.keyboardShortcuts.action.open_help.label',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'cycle_theme',
|
id: 'cycle_theme',
|
||||||
defaultBinding: 'mod+/',
|
defaultBinding: 'mod+k c',
|
||||||
customizable: true,
|
customizable: true,
|
||||||
settingsLabelKey: 'settings.openchamber.keyboardShortcuts.action.cycle_theme.label',
|
settingsLabelKey: 'settings.openchamber.keyboardShortcuts.action.cycle_theme.label',
|
||||||
},
|
},
|
||||||
{ id: 'toggle_memory_debug', defaultBinding: 'mod+shift+d', customizable: false },
|
|
||||||
],
|
],
|
||||||
} as const satisfies Record<ShortcutCategory, readonly ShortcutConfig[]>;
|
} as const satisfies Record<ShortcutCategory, readonly ShortcutConfig[]>;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ export {
|
|||||||
keyToShortcutToken,
|
keyToShortcutToken,
|
||||||
normalizeCombo,
|
normalizeCombo,
|
||||||
parseShortcut,
|
parseShortcut,
|
||||||
|
resolveShortcutEventDigit,
|
||||||
|
resolveShortcutEventKey,
|
||||||
UNASSIGNED_SHORTCUT,
|
UNASSIGNED_SHORTCUT,
|
||||||
} from './bindings';
|
} from './bindings';
|
||||||
export type { ShortcutCombo } from './bindings';
|
export type { ShortcutCombo } from './bindings';
|
||||||
|
|||||||
@@ -39,6 +39,14 @@ export class ShortcutRegistry {
|
|||||||
return this.handlers.get(actionId)?.[0]?.handler;
|
return this.handlers.get(actionId)?.[0]?.handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Runs an action outside keyboard dispatch (command palette). Bypasses
|
||||||
|
suspension: the invoking surface, not the keyboard, owns the gesture. */
|
||||||
|
invoke(actionId: ShortcutActionId): boolean {
|
||||||
|
const handler = this.handlers.get(actionId)?.[0]?.handler;
|
||||||
|
if (!handler) return false;
|
||||||
|
return handler(new KeyboardEvent('keydown')) !== false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Temporarily disables every registered application shortcut. */
|
/** Temporarily disables every registered application shortcut. */
|
||||||
suspend(): () => void {
|
suspend(): () => void {
|
||||||
this.suspensionCount += 1;
|
this.suspensionCount += 1;
|
||||||
|
|||||||
@@ -49,13 +49,31 @@ describe('shortcut schema', () => {
|
|||||||
))).toBe(true);
|
))).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('includes session prefix bindings and metadata', () => {
|
test('keeps the mod+k leader for open/go actions', () => {
|
||||||
expect(getShortcutAction('open_draft_project_picker')?.defaultBinding).toBe('mod+s p');
|
expect(getShortcutAction('open_draft_project_picker')?.defaultBinding).toBe('mod+k p');
|
||||||
expect(getShortcutAction('open_draft_worktree_picker')?.defaultBinding).toBe('mod+s g');
|
expect(getShortcutAction('open_draft_worktree_picker')?.defaultBinding).toBe('mod+k g');
|
||||||
expect(getShortcutAction('open_session_list')?.defaultBinding).toBe('mod+s l');
|
expect(getShortcutAction('open_session_list')?.defaultBinding).toBe('mod+k l');
|
||||||
|
expect(getShortcutAction('open_timeline_dialog')?.defaultBinding).toBe('mod+k t');
|
||||||
|
expect(getShortcutAction('toggle_prompt_navigator')?.defaultBinding).toBe('mod+k n');
|
||||||
|
expect(getShortcutAction('toggle_services_menu')?.defaultBinding).toBe('mod+k i');
|
||||||
|
expect(getShortcutAction('open_help')?.defaultBinding).toBe('mod+k h');
|
||||||
|
expect(getShortcutAction('cycle_theme')?.defaultBinding).toBe('mod+k c');
|
||||||
expect(getShortcutAction('focus_input')?.category).toBe('session');
|
expect(getShortcutAction('focus_input')?.category).toBe('session');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('splits the held digit prefixes between session tabs and surfaces', () => {
|
||||||
|
expect(getShortcutAction('switch_session_tab')?.defaultBinding).toBe('mod');
|
||||||
|
expect(getShortcutAction('switch_context_surface')?.defaultBinding).toBe('mod+alt');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('every action ships with a default binding', () => {
|
||||||
|
// Palette-only commands live outside this schema entirely; an action in
|
||||||
|
// the schema without a binding would be dead weight in Settings.
|
||||||
|
for (const action of SHORTCUT_SCHEMA) {
|
||||||
|
expect(getEffectiveShortcutCombo(action.id)).not.toBe('');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
test('preserves valid overrides and falls back from malformed bindings', () => {
|
test('preserves valid overrides and falls back from malformed bindings', () => {
|
||||||
expect(getEffectiveShortcutCombo('new_chat', { new_chat: 'mod+k' })).toBe('mod+k');
|
expect(getEffectiveShortcutCombo('new_chat', { new_chat: 'mod+k' })).toBe('mod+k');
|
||||||
expect(getEffectiveShortcutCombo('new_chat', { new_chat: 'mod+k x y' })).toBe('mod+n');
|
expect(getEffectiveShortcutCombo('new_chat', { new_chat: 'mod+k x y' })).toBe('mod+n');
|
||||||
@@ -73,10 +91,8 @@ describe('shortcut schema', () => {
|
|||||||
.find((conflict) => conflict.action.id === 'find_in_file');
|
.find((conflict) => conflict.action.id === 'find_in_file');
|
||||||
const internalPrefixConflict = getShortcutBindingConflicts('new_chat', 'mod+s x')
|
const internalPrefixConflict = getShortcutBindingConflicts('new_chat', 'mod+s x')
|
||||||
.find((conflict) => conflict.action.id === 'save_file');
|
.find((conflict) => conflict.action.id === 'save_file');
|
||||||
const contextualPrefixConflict = getShortcutBindingConflicts('focus_input', 'mod+l l')
|
const leaderPrefixConflict = getShortcutBindingConflicts('new_chat', 'mod+k')
|
||||||
.find((conflict) => conflict.action.id === 'add_selection_to_chat');
|
.find((conflict) => conflict.action.id === 'open_session_list');
|
||||||
const contextualLeaderConflict = getShortcutBindingConflicts('add_selection_to_chat', 'mod+s')
|
|
||||||
.find((conflict) => conflict.action.id === 'open_draft_project_picker');
|
|
||||||
const blockingPrefixConflict = getShortcutBindingConflicts('new_chat', 'mod+p x')
|
const blockingPrefixConflict = getShortcutBindingConflicts('new_chat', 'mod+p x')
|
||||||
.find((conflict) => conflict.action.id === 'open_command_palette');
|
.find((conflict) => conflict.action.id === 'open_command_palette');
|
||||||
|
|
||||||
@@ -84,10 +100,9 @@ describe('shortcut schema', () => {
|
|||||||
expect(customizableConflict?.action.customizable).toBe(true);
|
expect(customizableConflict?.action.customizable).toBe(true);
|
||||||
expect(internalConflict?.kind).toBe('exact');
|
expect(internalConflict?.kind).toBe('exact');
|
||||||
expect(internalConflict?.action.customizable).toBe(false);
|
expect(internalConflict?.action.customizable).toBe(false);
|
||||||
expect(internalPrefixConflict?.kind).toBe('contextual-prefix');
|
expect(internalPrefixConflict?.kind).toBe('prefix');
|
||||||
expect(internalPrefixConflict?.action.customizable).toBe(false);
|
expect(internalPrefixConflict?.action.customizable).toBe(false);
|
||||||
expect(contextualPrefixConflict?.kind).toBe('contextual-prefix');
|
expect(leaderPrefixConflict?.kind).toBe('prefix');
|
||||||
expect(contextualLeaderConflict?.kind).toBe('contextual-prefix');
|
|
||||||
expect(blockingPrefixConflict?.kind).toBe('prefix');
|
expect(blockingPrefixConflict?.kind).toBe('prefix');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -15,29 +15,14 @@ export type ShortcutAction = (typeof SHORTCUT_SCHEMA)[number];
|
|||||||
export type ShortcutActionId = ShortcutAction['id'];
|
export type ShortcutActionId = ShortcutAction['id'];
|
||||||
export type ShortcutCategory = ShortcutAction['category'];
|
export type ShortcutCategory = ShortcutAction['category'];
|
||||||
export type CustomizableShortcutAction = Extract<ShortcutAction, { customizable: true }>;
|
export type CustomizableShortcutAction = Extract<ShortcutAction, { customizable: true }>;
|
||||||
|
/** 'contextual-prefix' is kept in the union for the recording dialog's
|
||||||
|
messaging even though no default layout produces it any more. */
|
||||||
export type ShortcutBindingConflictKind = ShortcutConflict | 'contextual-prefix';
|
export type ShortcutBindingConflictKind = ShortcutConflict | 'contextual-prefix';
|
||||||
export type ShortcutBindingConflict = {
|
export type ShortcutBindingConflict = {
|
||||||
action: ShortcutAction;
|
action: ShortcutAction;
|
||||||
kind: ShortcutBindingConflictKind;
|
kind: ShortcutBindingConflictKind;
|
||||||
};
|
};
|
||||||
|
|
||||||
function allowsContextualPrefix(
|
|
||||||
action: ShortcutAction,
|
|
||||||
combo: ShortcutCombo,
|
|
||||||
candidate: ShortcutAction,
|
|
||||||
candidateCombo: ShortcutCombo,
|
|
||||||
): boolean {
|
|
||||||
const chordCount = parseShortcut(combo)?.chords.length;
|
|
||||||
const candidateChordCount = parseShortcut(candidateCombo)?.chords.length;
|
|
||||||
if (chordCount === 1 && candidateChordCount === 2) {
|
|
||||||
return 'allowsSequenceFallback' in action && action.allowsSequenceFallback;
|
|
||||||
}
|
|
||||||
if (chordCount === 2 && candidateChordCount === 1) {
|
|
||||||
return 'allowsSequenceFallback' in candidate && candidate.allowsSequenceFallback;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getShortcutAction(id: string): ShortcutAction | undefined {
|
export function getShortcutAction(id: string): ShortcutAction | undefined {
|
||||||
return SHORTCUT_SCHEMA.find((action) => action.id === id);
|
return SHORTCUT_SCHEMA.find((action) => action.id === id);
|
||||||
}
|
}
|
||||||
@@ -54,7 +39,8 @@ export function getEffectiveShortcutCombo(
|
|||||||
): ShortcutCombo {
|
): ShortcutCombo {
|
||||||
const action = getShortcutAction(actionId);
|
const action = getShortcutAction(actionId);
|
||||||
if (!action) return '';
|
if (!action) return '';
|
||||||
if (!action.customizable) return action.defaultBinding;
|
const defaultBinding = action.defaultBinding === UNASSIGNED_SHORTCUT ? '' : action.defaultBinding;
|
||||||
|
if (!action.customizable) return defaultBinding;
|
||||||
|
|
||||||
const override = overrides?.[actionId];
|
const override = overrides?.[actionId];
|
||||||
if (typeof override === 'string') {
|
if (typeof override === 'string') {
|
||||||
@@ -63,7 +49,7 @@ export function getEffectiveShortcutCombo(
|
|||||||
if (isValidShortcutCombo(normalized)) return normalized;
|
if (isValidShortcutCombo(normalized)) return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
return action.defaultBinding;
|
return defaultBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getEffectiveShortcutPrefix(
|
export function getEffectiveShortcutPrefix(
|
||||||
@@ -100,12 +86,7 @@ export function getShortcutBindingConflicts(
|
|||||||
: getEffectiveShortcutCombo(candidate.id, overrides);
|
: getEffectiveShortcutCombo(candidate.id, overrides);
|
||||||
const kind = getShortcutConflict(combo, candidateCombo);
|
const kind = getShortcutConflict(combo, candidateCombo);
|
||||||
if (!kind) continue;
|
if (!kind) continue;
|
||||||
conflicts.push({
|
conflicts.push({ action: candidate, kind });
|
||||||
action: candidate,
|
|
||||||
kind: kind === 'prefix' && allowsContextualPrefix(action, combo, candidate, candidateCombo)
|
|
||||||
? 'contextual-prefix'
|
|
||||||
: kind,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return conflicts;
|
return conflicts;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2412,7 +2412,7 @@ export const useUIStore = create<UIStore>()(
|
|||||||
{
|
{
|
||||||
name: 'ui-store',
|
name: 'ui-store',
|
||||||
storage: createDeferredSafeJSONStorage(),
|
storage: createDeferredSafeJSONStorage(),
|
||||||
version: 17,
|
version: 18,
|
||||||
migrate: (persistedState, version) => {
|
migrate: (persistedState, version) => {
|
||||||
if (!persistedState || typeof persistedState !== 'object') {
|
if (!persistedState || typeof persistedState !== 'object') {
|
||||||
return persistedState;
|
return persistedState;
|
||||||
@@ -2433,6 +2433,15 @@ export const useUIStore = create<UIStore>()(
|
|||||||
delete state.expandedEditorToolbar;
|
delete state.expandedEditorToolbar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// v17 -> v18: the default shortcut layout was redesigned around the
|
||||||
|
// mod+k leader and the held digit prefixes. Old overrides were
|
||||||
|
// recorded against the previous defaults (e.g. a bare 'mod' surface
|
||||||
|
// prefix now collides with session tabs), so custom bindings start
|
||||||
|
// fresh on the new system.
|
||||||
|
if (version < 18) {
|
||||||
|
delete state.shortcutOverrides;
|
||||||
|
}
|
||||||
|
|
||||||
// v13 -> v14: the separate 'preview' surface merged into 'browser'.
|
// v13 -> v14: the separate 'preview' surface merged into 'browser'.
|
||||||
// Stored preview tabs keep their URL and become browser tabs; their
|
// Stored preview tabs keep their URL and become browser tabs; their
|
||||||
// id encodes the mode, so it is rebuilt rather than left dangling.
|
// id encodes the mode, so it is rebuilt rather than left dangling.
|
||||||
|
|||||||
@@ -172,12 +172,12 @@ checks:
|
|||||||
preconditions:
|
preconditions:
|
||||||
- Open a draft session with project and worktree selectors mounted.
|
- Open a draft session with project and worktree selectors mounted.
|
||||||
steps:
|
steps:
|
||||||
- Trigger Mod + S, P and verify the project picker opens.
|
- Trigger Mod + K, P and verify the project picker opens.
|
||||||
- Press Escape once and verify it closes.
|
- Press Escape once and verify it closes.
|
||||||
- Trigger Mod + S, G and verify the worktree picker opens.
|
- Trigger Mod + K, G and verify the worktree picker opens.
|
||||||
- Press Escape once and verify it closes.
|
- Press Escape once and verify it closes.
|
||||||
assertions:
|
assertions:
|
||||||
- A contextual Mod + S owner yields when its context is inactive.
|
- The Mod + K leader arms without a visible menu and completes on the second key.
|
||||||
- Each sequence opens only its target picker.
|
- Each sequence opens only its target picker.
|
||||||
- One non-IME Escape closes either controlled picker.
|
- One non-IME Escape closes either controlled picker.
|
||||||
evidence:
|
evidence:
|
||||||
|
|||||||
Reference in New Issue
Block a user