🐛 fix(shortcuts): 同步侧边栏搜索快捷键提示

- 侧边栏 v2 搜索入口改为读取用户快捷键配置
- 修复搜索入口固定显示默认 ⌘K 的问题
- 按 macOS 语义使用 Cmd+F 作为查找类快捷键
- 移除快捷键描述中的硬编码默认组合
- 补充快捷键展示与平台冲突判断测试
This commit is contained in:
Syngnat
2026-06-01 11:03:22 +08:00
parent 35b7fdf96b
commit 999efa5947
5 changed files with 85 additions and 35 deletions

View File

@@ -66,6 +66,7 @@ const mocks = vi.hoisted(() => ({
blur: 0,
uiVersion: 'legacy',
} as any,
shortcutOptions: null as any,
},
}));
@@ -148,7 +149,7 @@ vi.mock('../store', () => ({
setSidebarTablePinned: mocks.noop,
addSqlLog: mocks.noop,
sqlLogs: [],
shortcutOptions: cloneShortcutOptions(DEFAULT_SHORTCUT_OPTIONS),
shortcutOptions: mocks.state.shortcutOptions ?? cloneShortcutOptions(DEFAULT_SHORTCUT_OPTIONS),
setAIPanelVisible: mocks.noop,
addAIContext: mocks.noop,
}),
@@ -183,6 +184,14 @@ vi.mock('../../wailsjs/runtime/runtime', () => ({
EventsOn: mocks.noop,
}));
vi.mock('../utils/appearance', async () => {
const actual = await vi.importActual<typeof import('../utils/appearance')>('../utils/appearance');
return {
...actual,
isMacLikePlatform: () => true,
};
});
describe('Sidebar locate toolbar', () => {
beforeEach(() => {
mocks.state.connections = [];
@@ -203,6 +212,7 @@ describe('Sidebar locate toolbar', () => {
blur: 0,
uiVersion: 'legacy',
};
mocks.state.shortcutOptions = cloneShortcutOptions(DEFAULT_SHORTCUT_OPTIONS);
});
it('resolves the table name used by the sidebar copy action', () => {
@@ -388,8 +398,11 @@ describe('Sidebar locate toolbar', () => {
expect(markup).toContain('gn-v2-explorer-command-trigger');
expect(markup).toContain('搜索表、连接、动作... 或问 AI');
expect(markup).toContain('gn-v2-search-shortcut');
expect(markup).toContain('<kbd>Ctrl</kbd>');
expect(markup).toContain('<kbd></kbd>');
expect(markup).toContain('<kbd>K</kbd>');
expect(source).toContain("const focusSidebarSearchShortcut = resolveShortcutDisplay(shortcutOptions, 'focusSidebarSearch', activeShortcutPlatform);");
expect(source).not.toContain('<kbd>⌘</kbd>');
expect(source).not.toContain('<kbd>K</kbd>');
expect(markup).toContain('gn-v2-explorer-filter-tabs');
expect(markup).toContain('全部');
expect(markup).toContain('视图');
@@ -439,6 +452,18 @@ describe('Sidebar locate toolbar', () => {
expect(contextMenuFunction).not.toContain('setActiveContext');
});
it('renders the v2 search shortcut from the user shortcut settings', () => {
mocks.state.shortcutOptions = cloneShortcutOptions(DEFAULT_SHORTCUT_OPTIONS);
mocks.state.shortcutOptions.focusSidebarSearch.mac = { combo: 'Meta+F', enabled: true };
const markup = renderToStaticMarkup(<Sidebar uiVersion="v2" />);
expect(markup).toContain('gn-v2-search-shortcut');
expect(markup).toContain('<kbd>⌘</kbd>');
expect(markup).toContain('<kbd>F</kbd>');
expect(markup).not.toContain('<kbd>K</kbd>');
});
it('keeps the v2 command search footer hints tied to real prefix actions', () => {
const source = readFileSync(new URL('./Sidebar.tsx', import.meta.url), 'utf8');

View File

@@ -80,7 +80,7 @@ import { resolveConnectionAccentColor, resolveConnectionIconType } from '../util
import { buildJVMTabTitle } from '../utils/jvmRuntimePresentation';
import { buildJVMDiagnosticActionDescriptor, buildJVMMonitoringActionDescriptors } from '../utils/jvmSidebarActions';
import { buildTableSelectQuery } from '../utils/objectQueryTemplates';
import { getShortcutPlatform, getShortcutPrimaryModifierDisplayLabel, resolveShortcutDisplay } from '../utils/shortcuts';
import { getShortcutPlatform, resolveShortcutDisplay } from '../utils/shortcuts';
import { buildExternalSQLDirectoryId, buildExternalSQLRootNode, buildExternalSQLTabId, type ExternalSQLTreeNode } from '../utils/externalSqlTree';
import JVMModeBadge from './jvm/JVMModeBadge';
import {
@@ -914,7 +914,10 @@ const Sidebar: React.FC<{
const disableLocalBackdropFilter = isMacLikePlatform();
const autoFetchVisible = useAutoFetchVisibility();
const activeShortcutPlatform = getShortcutPlatform(isMacLikePlatform());
const primaryShortcutModifierLabel = getShortcutPrimaryModifierDisplayLabel(activeShortcutPlatform);
const focusSidebarSearchShortcut = resolveShortcutDisplay(shortcutOptions, 'focusSidebarSearch', activeShortcutPlatform);
const focusSidebarSearchShortcutTokens = focusSidebarSearchShortcut === '-'
? []
: focusSidebarSearchShortcut.match(/Ctrl|Alt|Shift|Esc|Space|[⌘⌃⌥⇧↵↑↓←→]|[^+]/g) ?? [];
const [treeData, setTreeData] = useState<TreeNode[]>([]);
const activeTab = useMemo(() => tabs.find(tab => tab.id === activeTabId) || null, [tabs, activeTabId]);
const activeTabLocateRequest = useMemo(() => normalizeSidebarLocateObjectRequestFromTab(activeTab), [activeTab]);
@@ -8003,10 +8006,13 @@ const Sidebar: React.FC<{
>
<SearchOutlined />
<span>... AI</span>
<span className="gn-v2-search-shortcut" aria-hidden="true">
<kbd>{primaryShortcutModifierLabel}</kbd>
<kbd>K</kbd>
</span>
{focusSidebarSearchShortcutTokens.length > 0 ? (
<span className="gn-v2-search-shortcut" aria-hidden="true">
{focusSidebarSearchShortcutTokens.map((token, index) => (
<kbd key={`${token}-${index}`}>{token}</kbd>
))}
</span>
) : null}
</button>
) : (
<Input