diff --git a/apps/desktop/src/components/editor/EditorSettingsDialog.vue b/apps/desktop/src/components/editor/EditorSettingsDialog.vue index b9e50aec56..19e17b5148 100644 --- a/apps/desktop/src/components/editor/EditorSettingsDialog.vue +++ b/apps/desktop/src/components/editor/EditorSettingsDialog.vue @@ -821,6 +821,7 @@ const formatterEditorShortcutIds: ShortcutActionId[] = [ "selectAll", "uppercaseSelection", "lowercaseSelection", + "toggleFold", ]; const formatterEditorShortcutDefinitions = computed(() => formatterEditorShortcutIds.map((id) => SHORTCUT_DEFINITIONS.find((definition) => definition.id === id)).filter((definition): definition is (typeof SHORTCUT_DEFINITIONS)[number] => !!definition)); const filteredShortcutDefinitions = computed(() => { diff --git a/apps/desktop/src/components/editor/QueryEditor.vue b/apps/desktop/src/components/editor/QueryEditor.vue index 30b3c2b00f..88fef51f44 100644 --- a/apps/desktop/src/components/editor/QueryEditor.vue +++ b/apps/desktop/src/components/editor/QueryEditor.vue @@ -356,6 +356,7 @@ let codeMirrorRedo: typeof import("@codemirror/commands").redo | null = null; let codeMirrorSelectAll: typeof import("@codemirror/commands").selectAll | null = null; let codeMirrorInsertNewlineKeepIndent: typeof import("@codemirror/commands").insertNewlineKeepIndent | null = null; let codeMirrorToggleLineComment: typeof import("@codemirror/commands").toggleLineComment | null = null; +let codeMirrorToggleFold: typeof import("@codemirror/language").toggleFold | null = null; let pendingCompletionTabTimer: ReturnType | null = null; let setSqlDiagnosticsEffect: import("@codemirror/state").StateEffectType | null = null; let setPreviewRangeEffect: @@ -1395,6 +1396,7 @@ function runKeymapExtension(codeMirrorKeymap: (typeof import("@codemirror/view") ...binding(shortcuts.uppercaseSelection, () => convertSelectedSqlCase("upper")), ...binding(shortcuts.lowercaseSelection, () => convertSelectedSqlCase("lower")), ...binding(shortcuts.toggleLineComment, (view) => codeMirrorToggleLineComment?.(view) ?? false), + ...binding(shortcuts.toggleFold, (view) => codeMirrorToggleFold?.(view) ?? false), ...binding(shortcuts.exPasteSqlInCondition, () => { if (!supportsSqlInListPaste(props.databaseType)) return false; void pasteClipboardAsSqlInCondition(); @@ -3392,7 +3394,7 @@ onMounted(async () => { langSql, { autocompletion, startCompletion, acceptCompletion, closeBrackets, closeBracketsKeymap, snippetCompletion, completionStatus, completionKeymap, insertCompletionText, nextSnippetField }, { copyLineDown, copyLineUp, deleteLine, indentLess, indentMore, insertNewlineKeepIndent, moveLineDown, moveLineUp, redo, selectAll, undo, toggleLineComment, history, defaultKeymap, historyKeymap }, - { bracketMatching, foldGutter, indentOnInput, indentUnit, syntaxHighlighting, defaultHighlightStyle, foldKeymap, ensureSyntaxTree }, + { bracketMatching, foldGutter, indentOnInput, indentUnit, syntaxHighlighting, defaultHighlightStyle, foldKeymap, toggleFold, ensureSyntaxTree }, { searchKeymap }, ] = await Promise.all([import("@codemirror/view"), import("@codemirror/state"), import("@codemirror/lang-sql"), import("@codemirror/autocomplete"), import("@codemirror/commands"), import("@codemirror/language"), import("@codemirror/search")]); editorViewModule = { @@ -3439,6 +3441,7 @@ onMounted(async () => { codeMirrorSelectAll = selectAll; codeMirrorInsertNewlineKeepIndent = insertNewlineKeepIndent; codeMirrorToggleLineComment = toggleLineComment; + codeMirrorToggleFold = toggleFold; codeMirrorIndentUnit = indentUnit; window.addEventListener("keyup", clearTableNavigationHoverOnModifierRelease); window.addEventListener("blur", clearTableNavigationHover); diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts index 388cef63f0..2a3960e877 100644 --- a/apps/desktop/src/i18n/locales/en.ts +++ b/apps/desktop/src/i18n/locales/en.ts @@ -4642,6 +4642,7 @@ export default { shortcutEditSidebarConnection: "Edit sidebar connection", shortcutOpenDataInNewTab: "Open data in new tab (mouse click)", shortcutSendSelectionToAi: "Send selection to AI", + shortcutToggleFold: "Toggle fold", shortcutScopeGlobal: "Global", shortcutScopeEditor: "SQL editor", shortcutScopeGrid: "Data grid", diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts index 344c3a2e7f..a153ae30b5 100644 --- a/apps/desktop/src/i18n/locales/es.ts +++ b/apps/desktop/src/i18n/locales/es.ts @@ -4397,6 +4397,7 @@ export default withEnglishFallback({ shortcutEditSidebarConnection: "Editar conexión de la barra lateral", shortcutOpenDataInNewTab: "Abrir datos en una pestaña nueva (clic del ratón)", shortcutSendSelectionToAi: "Enviar selección a IA", + shortcutToggleFold: "Contraer/expandir código", shortcutScopeGlobal: "Global", shortcutScopeEditor: "Editor SQL", shortcutScopeGrid: "Cuadrícula de datos", diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts index dd32614c98..65bb7980d0 100644 --- a/apps/desktop/src/i18n/locales/it.ts +++ b/apps/desktop/src/i18n/locales/it.ts @@ -4395,6 +4395,7 @@ export default withEnglishFallback({ shortcutEditSidebarConnection: "Modifica connessione barra laterale", shortcutOpenDataInNewTab: "Apri dati in una nuova scheda (clic del mouse)", shortcutSendSelectionToAi: "Invia selezione ad AI", + shortcutToggleFold: "Comprimi/espandi codice", shortcutScopeGlobal: "Globale", shortcutScopeEditor: "Editor SQL", shortcutScopeGrid: "Griglia dati", diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts index a9394f57d8..b47191a1b4 100644 --- a/apps/desktop/src/i18n/locales/ja.ts +++ b/apps/desktop/src/i18n/locales/ja.ts @@ -4379,6 +4379,7 @@ export default withEnglishFallback({ shortcutEditSidebarConnection: "サイドバー接続を編集", shortcutOpenDataInNewTab: "新しいデータタブで開く(マウスクリック)", shortcutSendSelectionToAi: "選択範囲をAIに送信", + shortcutToggleFold: "折りたたみの切り替え", shortcutScopeGlobal: "グローバル", shortcutScopeEditor: "SQLエディタ", shortcutScopeGrid: "データグリッド", diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts index a29211b035..1c028d2492 100644 --- a/apps/desktop/src/i18n/locales/pt-BR.ts +++ b/apps/desktop/src/i18n/locales/pt-BR.ts @@ -4397,6 +4397,7 @@ export default withEnglishFallback({ shortcutEditSidebarConnection: "Editar conexão da barra lateral", shortcutOpenDataInNewTab: "Abrir dados em nova aba (clique do mouse)", shortcutSendSelectionToAi: "Enviar seleção para IA", + shortcutToggleFold: "Recolher/expandir código", shortcutScopeGlobal: "Global", shortcutScopeEditor: "Editor SQL", shortcutScopeGrid: "Grade de dados", diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts index c3ff1f4644..97dce25749 100644 --- a/apps/desktop/src/i18n/locales/zh-CN.ts +++ b/apps/desktop/src/i18n/locales/zh-CN.ts @@ -4644,6 +4644,7 @@ export default withEnglishFallback({ shortcutEditSidebarConnection: "编辑侧边栏连接", shortcutOpenDataInNewTab: "在新数据标签页中打开(鼠标点击)", shortcutSendSelectionToAi: "发送选中代码到 AI", + shortcutToggleFold: "切换折叠", shortcutScopeGlobal: "全局", shortcutScopeEditor: "SQL 编辑器", shortcutScopeGrid: "数据表格", diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts index d2c5aea23d..ad2821aef8 100644 --- a/apps/desktop/src/i18n/locales/zh-TW.ts +++ b/apps/desktop/src/i18n/locales/zh-TW.ts @@ -4052,6 +4052,7 @@ export default withEnglishFallback({ shortcutEditSidebarConnection: "編輯側邊欄連線", shortcutOpenDataInNewTab: "在新資料分頁中開啟(滑鼠點擊)", shortcutSendSelectionToAi: "傳送選取程式碼至 AI", + shortcutToggleFold: "切換折疊", shortcutScopeGlobal: "全域", shortcutScopeEditor: "SQL 編輯器", shortcutScopeGrid: "資料表格", diff --git a/apps/desktop/src/lib/__tests__/editor/shortcutRegistry.spec.ts b/apps/desktop/src/lib/__tests__/editor/shortcutRegistry.spec.ts index 565f833bbe..d58a1b4bab 100644 --- a/apps/desktop/src/lib/__tests__/editor/shortcutRegistry.spec.ts +++ b/apps/desktop/src/lib/__tests__/editor/shortcutRegistry.spec.ts @@ -19,6 +19,7 @@ describe("shortcutRegistry editor actions", () => { "uppercaseSelection", "lowercaseSelection", "exPasteSqlInCondition", + "toggleFold", ]; const sidebarShortcutActionIds: ShortcutActionId[] = ["copySidebarSelection", "pasteSidebarSelection", "editSidebarConnection"]; @@ -100,6 +101,7 @@ describe("shortcutRegistry editor actions", () => { expect(shortcuts.uppercaseSelection).toBe("Shift+Alt+U"); expect(shortcuts.lowercaseSelection).toBe("Shift+Alt+L"); expect(shortcuts.exPasteSqlInCondition).toBe(""); + expect(shortcuts.toggleFold).toBe("Mod+."); }); it("detects conflicts between formatter editor shortcuts and other editor shortcuts", () => { diff --git a/apps/desktop/src/lib/editor/shortcutRegistry.ts b/apps/desktop/src/lib/editor/shortcutRegistry.ts index dfc4e8b4aa..738ae4536f 100644 --- a/apps/desktop/src/lib/editor/shortcutRegistry.ts +++ b/apps/desktop/src/lib/editor/shortcutRegistry.ts @@ -21,6 +21,7 @@ export type ShortcutActionId = | "uppercaseSelection" | "lowercaseSelection" | "exPasteSqlInCondition" + | "toggleFold" | "copyCurrentRow" | "deleteCurrentRow" | "newQuery" @@ -202,6 +203,12 @@ export const SHORTCUT_DEFINITIONS: ShortcutDefinition[] = [ scope: "editor", defaultShortcut: "", }, + { + id: "toggleFold", + labelKey: "settings.shortcutToggleFold", + scope: "editor", + defaultShortcut: "Mod+.", + }, { id: "copyCurrentRow", labelKey: "settings.shortcutCopyCurrentRow",