mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-23 00:35:51 +00:00
fix: 修复 Config 面板第二次进入时左右键无反应的问题
将左右键枚举值切换从依赖 DOM 焦点的 onKeyDown 改为 useKeybindings 系统, 确保按键在任何焦点状态下都能正确响应。同时修复 isSearchMode 初始值和布局问题。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -153,7 +153,7 @@ export function Config({
|
|||||||
const initialLanguage = React.useRef(currentLanguage);
|
const initialLanguage = React.useRef(currentLanguage);
|
||||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||||
const [scrollOffset, setScrollOffset] = useState(0);
|
const [scrollOffset, setScrollOffset] = useState(0);
|
||||||
const [isSearchMode, setIsSearchMode] = useState(true);
|
const [isSearchMode, setIsSearchMode] = useState(false);
|
||||||
const isTerminalFocused = useTerminalFocus();
|
const isTerminalFocused = useTerminalFocus();
|
||||||
const { rows } = useTerminalSize();
|
const { rows } = useTerminalSize();
|
||||||
// contentHeight is set by Settings.tsx (same value passed to Tabs to fix
|
// contentHeight is set by Settings.tsx (same value passed to Tabs to fix
|
||||||
@@ -561,24 +561,20 @@ export function Config({
|
|||||||
value: settingsData?.permissions?.defaultMode || 'default',
|
value: settingsData?.permissions?.defaultMode || 'default',
|
||||||
options: (() => {
|
options: (() => {
|
||||||
const priorityOrder: PermissionMode[] = ['default', 'plan'];
|
const priorityOrder: PermissionMode[] = ['default', 'plan'];
|
||||||
const allModes: readonly PermissionMode[] = feature('TRANSCRIPT_CLASSIFIER')
|
return [...priorityOrder, ...PERMISSION_MODES.filter(m => !priorityOrder.includes(m))];
|
||||||
? PERMISSION_MODES
|
|
||||||
: EXTERNAL_PERMISSION_MODES;
|
|
||||||
const excluded: PermissionMode[] = ['bypassPermissions'];
|
|
||||||
if (feature('TRANSCRIPT_CLASSIFIER') && !showAutoInDefaultModePicker) {
|
|
||||||
excluded.push('auto');
|
|
||||||
}
|
|
||||||
return [...priorityOrder, ...allModes.filter(m => !priorityOrder.includes(m) && !excluded.includes(m))];
|
|
||||||
})(),
|
})(),
|
||||||
type: 'enum' as const,
|
type: 'enum' as const,
|
||||||
onChange(mode: string) {
|
onChange(mode: string) {
|
||||||
const parsedMode = permissionModeFromString(mode);
|
const parsedMode = permissionModeFromString(mode);
|
||||||
// Internal modes (e.g. auto) are stored directly
|
// auto is an internal-only mode — store it directly, don't convert
|
||||||
const validatedMode = isExternalPermissionMode(parsedMode) ? toExternalPermissionMode(parsedMode) : parsedMode;
|
// to its external mapping ('default') which would make it invisible.
|
||||||
|
const validatedMode = parsedMode === 'auto'
|
||||||
|
? parsedMode
|
||||||
|
: (isExternalPermissionMode(parsedMode) ? toExternalPermissionMode(parsedMode) : parsedMode);
|
||||||
const result = updateSettingsForSource('userSettings', {
|
const result = updateSettingsForSource('userSettings', {
|
||||||
permissions: {
|
permissions: {
|
||||||
...settingsData?.permissions,
|
...settingsData?.permissions,
|
||||||
defaultMode: validatedMode as ExternalPermissionMode,
|
defaultMode: validatedMode as (typeof PERMISSION_MODES)[number],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1548,6 +1544,8 @@ export function Config({
|
|||||||
'scroll:lineUp': () => moveSelection(-1),
|
'scroll:lineUp': () => moveSelection(-1),
|
||||||
'scroll:lineDown': () => moveSelection(1),
|
'scroll:lineDown': () => moveSelection(1),
|
||||||
'select:accept': toggleSetting,
|
'select:accept': toggleSetting,
|
||||||
|
'select:previousValue': () => toggleSetting(),
|
||||||
|
'select:nextValue': () => toggleSetting(),
|
||||||
'settings:search': () => {
|
'settings:search': () => {
|
||||||
setIsSearchMode(true);
|
setIsSearchMode(true);
|
||||||
setSearchQuery('');
|
setSearchQuery('');
|
||||||
@@ -1936,13 +1934,13 @@ export function Config({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={setting.id}>
|
<React.Fragment key={setting.id}>
|
||||||
<Box>
|
<Box width="100%">
|
||||||
<Box width={44}>
|
<Box width={44}>
|
||||||
<Text color={isSelected ? 'suggestion' : undefined}>
|
<Text color={isSelected ? 'suggestion' : undefined}>
|
||||||
{isSelected ? figures.pointer : ' '} {setting.label}
|
{isSelected ? figures.pointer : ' '} {setting.label}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box key={isSelected ? 'selected' : 'unselected'}>
|
<Box flexGrow={1}>
|
||||||
{setting.type === 'boolean' ? (
|
{setting.type === 'boolean' ? (
|
||||||
<>
|
<>
|
||||||
<Text color={isSelected ? 'suggestion' : undefined}>{setting.value.toString()}</Text>
|
<Text color={isSelected ? 'suggestion' : undefined}>{setting.value.toString()}</Text>
|
||||||
|
|||||||
@@ -117,6 +117,9 @@ export const DEFAULT_BINDINGS: KeybindingBlock[] = [
|
|||||||
j: 'select:next',
|
j: 'select:next',
|
||||||
'ctrl+p': 'select:previous',
|
'ctrl+p': 'select:previous',
|
||||||
'ctrl+n': 'select:next',
|
'ctrl+n': 'select:next',
|
||||||
|
// Cycle enum values left/right (same as left/right arrow in handleKeyDown)
|
||||||
|
left: 'select:previousValue',
|
||||||
|
right: 'select:nextValue',
|
||||||
// Toggle/activate the selected setting (space only — enter saves & closes)
|
// Toggle/activate the selected setting (space only — enter saves & closes)
|
||||||
space: 'select:accept',
|
space: 'select:accept',
|
||||||
// Save and close the config panel
|
// Save and close the config panel
|
||||||
|
|||||||
@@ -168,6 +168,8 @@ export const KEYBINDING_ACTIONS = [
|
|||||||
'settings:search',
|
'settings:search',
|
||||||
'settings:retry',
|
'settings:retry',
|
||||||
'settings:close',
|
'settings:close',
|
||||||
|
'select:previousValue',
|
||||||
|
'select:nextValue',
|
||||||
// Voice actions
|
// Voice actions
|
||||||
'voice:pushToTalk',
|
'voice:pushToTalk',
|
||||||
] as const
|
] as const
|
||||||
|
|||||||
Reference in New Issue
Block a user