mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-13 01:49:41 +08:00
✨ feat(shortcuts): 新增标签页切换快捷键
- 新增切换到下一个标签页动作,默认 Ctrl+Tab - 新增切换到上一个标签页动作,默认 Ctrl+Shift+Tab - 接入全局快捷键处理,按当前标签顺序首尾循环切换 - 补充快捷键默认值与全局执行链路测试 Refs #399
This commit is contained in:
@@ -162,6 +162,8 @@ describe('tool center menu entries', () => {
|
||||
['runQuery', 'gonavi:run-active-query'],
|
||||
['focusSidebarSearch', 'gonavi:focus-sidebar-search'],
|
||||
['newQueryTab', 'handleNewQuery();'],
|
||||
['switchToNextTab', 'switchActiveTabByOffset(1);'],
|
||||
['switchToPreviousTab', 'switchActiveTabByOffset(-1);'],
|
||||
['newConnection', 'handleCreateConnection();'],
|
||||
['toggleAIPanel', 'toggleAIPanel();'],
|
||||
['toggleLogPanel', 'handleToggleLogPanel();'],
|
||||
@@ -174,8 +176,11 @@ describe('tool center menu entries', () => {
|
||||
for (const [action, handler] of expectedHandlers) {
|
||||
expect(getGlobalShortcutCaseBlock(action)).toContain(handler);
|
||||
}
|
||||
expect(appSource).toContain('const switchActiveTabByOffset = useCallback((offset: 1 | -1) => {');
|
||||
expect(appSource).toContain('const nextIndex = (baseIndex + offset + tabs.length) % tabs.length;');
|
||||
expect(appSource).toContain('setActiveTab(tabs[nextIndex].id);');
|
||||
expect(appSource).toContain('handleCreateConnection, handleManualResetWindowZoom');
|
||||
expect(appSource).toContain('setTheme, toggleAIPanel, useNativeMacWindowControls');
|
||||
expect(appSource).toContain('switchActiveTabByOffset, themeMode');
|
||||
});
|
||||
|
||||
it('captures global shortcuts before Monaco/editor defaults consume them', () => {
|
||||
|
||||
@@ -1141,6 +1141,7 @@ function App() {
|
||||
const connections = useStore(state => state.connections);
|
||||
const tabs = useStore(state => state.tabs);
|
||||
const activeTabId = useStore(state => state.activeTabId);
|
||||
const setActiveTab = useStore(state => state.setActiveTab);
|
||||
const openSecurityUpdateSettings = useCallback((focusTarget: SecurityUpdateSettingsFocusTarget | null = null) => {
|
||||
setIsSecurityUpdateIntroOpen(false);
|
||||
setSecurityUpdateSettingsFocusTarget(focusTarget);
|
||||
@@ -1893,6 +1894,14 @@ function App() {
|
||||
});
|
||||
}, [activeTabId, tabs, connections, activeContext, addTab]);
|
||||
|
||||
const switchActiveTabByOffset = useCallback((offset: 1 | -1) => {
|
||||
if (tabs.length < 2) return;
|
||||
const activeIndex = tabs.findIndex(tab => tab.id === activeTabId);
|
||||
const baseIndex = activeIndex >= 0 ? activeIndex : 0;
|
||||
const nextIndex = (baseIndex + offset + tabs.length) % tabs.length;
|
||||
setActiveTab(tabs[nextIndex].id);
|
||||
}, [activeTabId, setActiveTab, tabs]);
|
||||
|
||||
const closeConnectionPackageDialog = useCallback(() => {
|
||||
setConnectionPackageDialog(createClosedConnectionPackageDialogState());
|
||||
setPendingConnectionImportPayload(null);
|
||||
@@ -2927,6 +2936,12 @@ function App() {
|
||||
case 'newQueryTab':
|
||||
handleNewQuery();
|
||||
break;
|
||||
case 'switchToNextTab':
|
||||
switchActiveTabByOffset(1);
|
||||
break;
|
||||
case 'switchToPreviousTab':
|
||||
switchActiveTabByOffset(-1);
|
||||
break;
|
||||
case 'newConnection':
|
||||
handleCreateConnection();
|
||||
break;
|
||||
@@ -2957,7 +2972,7 @@ function App() {
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleGlobalShortcut, true);
|
||||
};
|
||||
}, [activeShortcutPlatform, handleCreateConnection, handleManualResetWindowZoom, handleNewQuery, handleTitleBarWindowToggle, handleToggleLogPanel, isMacRuntime, shortcutOptions, themeMode, setTheme, toggleAIPanel, useNativeMacWindowControls]);
|
||||
}, [activeShortcutPlatform, handleCreateConnection, handleManualResetWindowZoom, handleNewQuery, handleTitleBarWindowToggle, handleToggleLogPanel, isMacRuntime, shortcutOptions, switchActiveTabByOffset, themeMode, setTheme, toggleAIPanel, useNativeMacWindowControls]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!capturingShortcutAction) {
|
||||
|
||||
@@ -200,6 +200,14 @@ describe('shortcut defaults', () => {
|
||||
mac: { combo: 'Meta+N', enabled: true },
|
||||
windows: { combo: 'Ctrl+N', enabled: true },
|
||||
});
|
||||
expect(DEFAULT_SHORTCUT_OPTIONS.switchToNextTab).toEqual({
|
||||
mac: { combo: 'Ctrl+Tab', enabled: true },
|
||||
windows: { combo: 'Ctrl+Tab', enabled: true },
|
||||
});
|
||||
expect(DEFAULT_SHORTCUT_OPTIONS.switchToPreviousTab).toEqual({
|
||||
mac: { combo: 'Ctrl+Shift+Tab', enabled: true },
|
||||
windows: { combo: 'Ctrl+Shift+Tab', enabled: true },
|
||||
});
|
||||
expect(DEFAULT_SHORTCUT_OPTIONS.toggleLogPanel).toEqual({
|
||||
mac: { combo: 'Meta+Shift+H', enabled: true },
|
||||
windows: { combo: 'Ctrl+H', enabled: true },
|
||||
|
||||
@@ -7,6 +7,8 @@ export type ShortcutAction =
|
||||
| 'sendAIChatMessage'
|
||||
| 'focusSidebarSearch'
|
||||
| 'newQueryTab'
|
||||
| 'switchToNextTab'
|
||||
| 'switchToPreviousTab'
|
||||
| 'newConnection'
|
||||
| 'toggleAIPanel'
|
||||
| 'toggleLogPanel'
|
||||
@@ -92,6 +94,8 @@ export const SHORTCUT_ACTION_ORDER: ShortcutAction[] = [
|
||||
'sendAIChatMessage',
|
||||
'focusSidebarSearch',
|
||||
'newQueryTab',
|
||||
'switchToNextTab',
|
||||
'switchToPreviousTab',
|
||||
'newConnection',
|
||||
'toggleAIPanel',
|
||||
'toggleLogPanel',
|
||||
@@ -135,6 +139,16 @@ export const SHORTCUT_ACTION_META: Record<ShortcutAction, ShortcutActionMeta> =
|
||||
label: '新建查询页',
|
||||
description: '创建一个新的 SQL 查询标签页',
|
||||
},
|
||||
switchToNextTab: {
|
||||
label: '切换到下一个标签页',
|
||||
description: '在打开的标签页中向右切换',
|
||||
allowInEditable: true,
|
||||
},
|
||||
switchToPreviousTab: {
|
||||
label: '切换到上一个标签页',
|
||||
description: '在打开的标签页中向左切换',
|
||||
allowInEditable: true,
|
||||
},
|
||||
newConnection: {
|
||||
label: '新建数据源',
|
||||
description: '创建新的数据库、运行时或其他数据源连接',
|
||||
@@ -194,6 +208,14 @@ export const DEFAULT_SHORTCUT_OPTIONS: ShortcutOptions = {
|
||||
mac: { combo: 'Meta+N', enabled: true },
|
||||
windows: { combo: 'Ctrl+N', enabled: true },
|
||||
},
|
||||
switchToNextTab: {
|
||||
mac: { combo: 'Ctrl+Tab', enabled: true },
|
||||
windows: { combo: 'Ctrl+Tab', enabled: true },
|
||||
},
|
||||
switchToPreviousTab: {
|
||||
mac: { combo: 'Ctrl+Shift+Tab', enabled: true },
|
||||
windows: { combo: 'Ctrl+Shift+Tab', enabled: true },
|
||||
},
|
||||
newConnection: {
|
||||
mac: { combo: 'Meta+Shift+N', enabled: true },
|
||||
windows: { combo: 'Ctrl+Shift+N', enabled: true },
|
||||
|
||||
Reference in New Issue
Block a user