diff --git a/apps/desktop/src/components/kv/KvKeyBrowser.vue b/apps/desktop/src/components/kv/KvKeyBrowser.vue index a3897b73bf..c450634209 100644 --- a/apps/desktop/src/components/kv/KvKeyBrowser.vue +++ b/apps/desktop/src/components/kv/KvKeyBrowser.vue @@ -4,6 +4,7 @@ import { useI18n } from "vue-i18n"; import { Pane, Splitpanes } from "splitpanes"; import "splitpanes/dist/splitpanes.css"; import { useConnectionStore } from "@/stores/connectionStore"; +import { useSettingsStore } from "@/stores/settingsStore"; import { Activity, Check, ChevronDown, ChevronRight, Clock3, Copy, Download, FolderClosed, FolderOpen, KeyRound, Loader2, LockKeyhole, Pencil, Plus, RefreshCw, Search, Square, Trash2 } from "@lucide/vue"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; @@ -237,6 +238,7 @@ const emit = defineEmits<{ const { t } = useI18n(); const { toast } = useToast(); const connectionStore = useConnectionStore(); +const settingsStore = useSettingsStore(); const searchInputRef = ref(); const prefix = ref(""); const keySuggestionOpen = ref(false); @@ -2024,7 +2026,8 @@ defineExpose({
diff --git a/apps/desktop/src/components/kv/KvValueEditor.vue b/apps/desktop/src/components/kv/KvValueEditor.vue index 735f337fec..258e9d9b62 100644 --- a/apps/desktop/src/components/kv/KvValueEditor.vue +++ b/apps/desktop/src/components/kv/KvValueEditor.vue @@ -13,6 +13,7 @@ import { properties } from "@codemirror/legacy-modes/mode/properties"; import { shell } from "@codemirror/legacy-modes/mode/shell"; import { onBeforeUnmount, onMounted, ref, watch } from "vue"; import type { KvValueFormat } from "@/lib/kv/kvValueFormat"; +import { useSettingsStore } from "@/stores/settingsStore"; const props = withDefaults( defineProps<{ @@ -28,8 +29,10 @@ const props = withDefaults( const emit = defineEmits<{ "update:modelValue": [value: string] }>(); const host = ref(); +const settingsStore = useSettingsStore(); const languageCompartment = new Compartment(); const readOnlyCompartment = new Compartment(); +const wordWrapCompartment = new Compartment(); let view: EditorView | null = null; function languageExtension(format: KvValueFormat) { @@ -48,6 +51,10 @@ function readOnlyExtensions(readOnly: boolean) { return [EditorState.readOnly.of(readOnly), EditorView.editable.of(!readOnly)]; } +function wordWrapExtension(wordWrap = settingsStore.editorSettings.wordWrap) { + return wordWrap ? EditorView.lineWrapping : []; +} + onMounted(() => { if (!host.value) return; view = new EditorView({ @@ -58,7 +65,7 @@ onMounted(() => { basicSetup, languageCompartment.of(languageExtension(props.format)), readOnlyCompartment.of(readOnlyExtensions(props.readOnly)), - EditorView.lineWrapping, + wordWrapCompartment.of(wordWrapExtension()), EditorView.theme({ "&": { height: "100%", fontSize: "13px", backgroundColor: "transparent" }, ".cm-scroller": { fontFamily: "var(--dbx-editor-font-family, ui-monospace)", overflow: "auto" }, @@ -91,6 +98,11 @@ watch( (readOnly) => view?.dispatch({ effects: readOnlyCompartment.reconfigure(readOnlyExtensions(readOnly)) }), ); +watch( + () => settingsStore.editorSettings.wordWrap, + (wordWrap) => view?.dispatch({ effects: wordWrapCompartment.reconfigure(wordWrapExtension(wordWrap)) }), +); + onBeforeUnmount(() => { view?.destroy(); view = null; diff --git a/apps/desktop/src/components/kv/__tests__/KvKeyBrowserLayout.spec.ts b/apps/desktop/src/components/kv/__tests__/KvKeyBrowserLayout.spec.ts index 582ece1960..fd4ae4dffc 100644 --- a/apps/desktop/src/components/kv/__tests__/KvKeyBrowserLayout.spec.ts +++ b/apps/desktop/src/components/kv/__tests__/KvKeyBrowserLayout.spec.ts @@ -2,6 +2,7 @@ import { readFileSync } from "node:fs"; import { describe, expect, it } from "vitest"; const browserSource = readFileSync(new URL("../KvKeyBrowser.vue", import.meta.url), "utf8"); +const valueEditorSource = readFileSync(new URL("../KvValueEditor.vue", import.meta.url), "utf8"); describe("KvKeyBrowser edit dialog layout", () => { it("keeps the value format label and selector together in the editor toolbar", () => { @@ -28,4 +29,16 @@ describe("KvKeyBrowser edit dialog layout", () => { expect(browserSource).toContain(''); expect(browserSource).toMatch(/ { + expect(browserSource).toContain(":class=\"settingsStore.editorSettings.wordWrap ? 'whitespace-pre-wrap break-words' : 'whitespace-pre'\""); + expect(browserSource).not.toContain("bg-muted/20 whitespace-pre-wrap break-words p-3"); + }); + + it("keeps shared KV value editor word wrapping aligned with the global editor setting", () => { + expect(valueEditorSource).toContain("const wordWrapCompartment = new Compartment()"); + expect(valueEditorSource).toContain("wordWrapCompartment.of(wordWrapExtension())"); + expect(valueEditorSource).toContain("wordWrapCompartment.reconfigure(wordWrapExtension(wordWrap))"); + expect(valueEditorSource).not.toContain("\n EditorView.lineWrapping,\n"); + }); }); diff --git a/apps/desktop/src/components/nacos/NacosAdminConsole.vue b/apps/desktop/src/components/nacos/NacosAdminConsole.vue index 0e872051c3..7516e55948 100644 --- a/apps/desktop/src/components/nacos/NacosAdminConsole.vue +++ b/apps/desktop/src/components/nacos/NacosAdminConsole.vue @@ -197,6 +197,7 @@ const importSource = shallowRef(null); const importSourceName = ref(""); const configEditorTheme = new Compartment(); const configEditorFontTheme = new Compartment(); +const configEditorWordWrap = new Compartment(); const configEditorLanguage = new Compartment(); const configListRequestGuard = createNacosLatestRequestGuard(); const configDetailRequestGuard = createNacosLatestRequestGuard(); @@ -553,7 +554,7 @@ async function mountConfigEditor() { configEditorLanguage.of(language), configEditorTheme.of(theme), configEditorFontTheme.of(editorFontTheme(EditorView, editorSettings.fontSize, editorSettings.fontFamily, { fixedHeight: true, scrollable: true })), - EditorView.lineWrapping, + configEditorWordWrap.of(editorSettings.wordWrap ? EditorView.lineWrapping : []), EditorState.readOnly.of(!!props.readOnly), EditorView.editable.of(!props.readOnly), EditorView.updateListener.of((update) => { @@ -2314,7 +2315,7 @@ watch( if (configEditorView.value !== view) return; configEditorFontSize.value = clampEditorFontSize(settings.fontSize); view.dispatch({ - effects: [configEditorTheme.reconfigure(theme), configEditorFontTheme.reconfigure(editorFontTheme(EditorView, settings.fontSize, settings.fontFamily, { fixedHeight: true, scrollable: true }))], + effects: [configEditorTheme.reconfigure(theme), configEditorFontTheme.reconfigure(editorFontTheme(EditorView, settings.fontSize, settings.fontFamily, { fixedHeight: true, scrollable: true })), configEditorWordWrap.reconfigure(settings.wordWrap ? EditorView.lineWrapping : [])], }); }, { deep: true }, diff --git a/apps/desktop/src/components/nacos/__tests__/NacosAdminConsoleLayout.spec.ts b/apps/desktop/src/components/nacos/__tests__/NacosAdminConsoleLayout.spec.ts index c11728c9e9..0710655da8 100644 --- a/apps/desktop/src/components/nacos/__tests__/NacosAdminConsoleLayout.spec.ts +++ b/apps/desktop/src/components/nacos/__tests__/NacosAdminConsoleLayout.spec.ts @@ -123,6 +123,13 @@ describe("NacosAdminConsole config workbench layout", () => { expect(source).toContain("configEditorZoomCommitScheduler.dispose()"); }); + it("keeps the configuration editor word wrapping aligned with the global editor setting", () => { + expect(source).toContain("const configEditorWordWrap = new Compartment()"); + expect(source).toContain("configEditorWordWrap.of(editorSettings.wordWrap ? EditorView.lineWrapping : [])"); + expect(source).toContain("configEditorWordWrap.reconfigure(settings.wordWrap ? EditorView.lineWrapping : [])"); + expect(source).not.toContain("\n EditorView.lineWrapping,\n"); + }); + it("allows optional configuration columns to be hidden without hiding the data ID", () => { const configListHeader = source.indexOf('class="sticky top-0 z-20 grid border-b bg-muted'); const columnVisibility = source.indexOf("nacos.visibleColumns"); diff --git a/apps/desktop/src/i18n/locales/en.ts b/apps/desktop/src/i18n/locales/en.ts index 5bec229775..29063a8635 100644 --- a/apps/desktop/src/i18n/locales/en.ts +++ b/apps/desktop/src/i18n/locales/en.ts @@ -5780,7 +5780,7 @@ export default { showInsertValueHintsDescription: "When enabled, the SQL editor shows column-name hints next to each value in INSERT ... VALUES clauses.", previewStatementRunButton: "Preview statement run button", wordWrap: "Word wrap", - wordWrapDescription: "Wrap long SQL lines within the editor width", + wordWrapDescription: "Wrap long lines within the editor width", vimMode: "Vim mode", vimModeDescription: "Use Vim-style modal editing in the SQL editor", autoCloseBrackets: "Auto-close brackets", diff --git a/apps/desktop/src/i18n/locales/es.ts b/apps/desktop/src/i18n/locales/es.ts index f98d847e1b..ba97bea958 100644 --- a/apps/desktop/src/i18n/locales/es.ts +++ b/apps/desktop/src/i18n/locales/es.ts @@ -5505,7 +5505,7 @@ export default withEnglishFallback({ showInsertValueHintsDescription: "Al activarlo, el editor SQL muestra el nombre de columna junto a cada valor en cláusulas INSERT ... VALUES.", previewStatementRunButton: "Botón de ejecución de sentencia en vista previa", wordWrap: "Ajuste de línea", - wordWrapDescription: "Ajustar las líneas largas de SQL al ancho del editor", + wordWrapDescription: "Ajustar las líneas largas al ancho del editor", vimMode: "Modo Vim", vimModeDescription: "Usar edición modal estilo Vim en el editor SQL", autoCloseBrackets: "Cerrar paréntesis automáticamente", diff --git a/apps/desktop/src/i18n/locales/it.ts b/apps/desktop/src/i18n/locales/it.ts index 481bcb5158..cd95acd5e0 100644 --- a/apps/desktop/src/i18n/locales/it.ts +++ b/apps/desktop/src/i18n/locales/it.ts @@ -5505,7 +5505,7 @@ export default withEnglishFallback({ showInsertValueHintsDescription: "Se attivo, l'editor SQL mostra il nome della colonna accanto a ogni valore nelle clausole INSERT ... VALUES.", previewStatementRunButton: "Pulsante di esecuzione istruzione in anteprima", wordWrap: "A capo automatico", - wordWrapDescription: "Incolonna le righe SQL lunghe entro la larghezza dell'editor", + wordWrapDescription: "Manda a capo le righe lunghe entro la larghezza dell'editor", vimMode: "Modalita Vim", vimModeDescription: "Usa la modifica modale in stile Vim nell'editor SQL", autoCloseBrackets: "Chiusura automatica parentesi", diff --git a/apps/desktop/src/i18n/locales/ja.ts b/apps/desktop/src/i18n/locales/ja.ts index 759e597fc5..39b51d46bd 100644 --- a/apps/desktop/src/i18n/locales/ja.ts +++ b/apps/desktop/src/i18n/locales/ja.ts @@ -5534,7 +5534,7 @@ export default withEnglishFallback({ showInsertValueHintsDescription: "有効にすると、INSERT ... VALUES 句の各値の横に対応する列名ヒントを表示します。", previewStatementRunButton: "文の実行ボタンのプレビュー", wordWrap: "折り返し", - wordWrapDescription: "長いSQL行をエディタ幅内で折り返します", + wordWrapDescription: "長い行をエディタ幅内で折り返します", vimMode: "Vimモード", vimModeDescription: "SQLエディタでVim形式のモーダル編集を使用します", autoCloseBrackets: "自動括弧補完", diff --git a/apps/desktop/src/i18n/locales/ko.ts b/apps/desktop/src/i18n/locales/ko.ts index 948298cd3e..e6381f7bdf 100644 --- a/apps/desktop/src/i18n/locales/ko.ts +++ b/apps/desktop/src/i18n/locales/ko.ts @@ -5266,7 +5266,7 @@ export default withEnglishFallback({ showInsertValueHintsDescription: "활성화하면 SQL 편집기가 INSERT ... VALUES 절의 각 값 옆에 컬럼 이름 힌트를 표시합니다.", previewStatementRunButton: "구문 실행 버튼 미리보기", wordWrap: "자동 줄바꿈", - wordWrapDescription: "편집기 너비 내에서 긴 SQL 줄을 줄바꿈합니다", + wordWrapDescription: "편집기 너비 내에서 긴 줄을 줄바꿈합니다", vimMode: "Vim 모드", vimModeDescription: "SQL 편집기에서 Vim 스타일의 모달 편집을 사용합니다", autoCloseBrackets: "괄호 자동 닫기", diff --git a/apps/desktop/src/i18n/locales/pt-BR.ts b/apps/desktop/src/i18n/locales/pt-BR.ts index 17c1ea16cb..fe0d163aa5 100644 --- a/apps/desktop/src/i18n/locales/pt-BR.ts +++ b/apps/desktop/src/i18n/locales/pt-BR.ts @@ -5507,7 +5507,7 @@ export default withEnglishFallback({ showInsertValueHintsDescription: "Quando ativado, o editor SQL mostra o nome da coluna ao lado de cada valor em cláusulas INSERT ... VALUES.", previewStatementRunButton: "Botão de execução de instrução na prévia", wordWrap: "Quebra de linha", - wordWrapDescription: "Quebrar linhas SQL longas dentro da largura do editor", + wordWrapDescription: "Quebrar linhas longas dentro da largura do editor", vimMode: "Modo Vim", vimModeDescription: "Usar edição modal no estilo Vim no editor SQL", autoCloseBrackets: "Fechar parênteses automaticamente", diff --git a/apps/desktop/src/i18n/locales/zh-CN.ts b/apps/desktop/src/i18n/locales/zh-CN.ts index 54be180b09..71ee8123ba 100644 --- a/apps/desktop/src/i18n/locales/zh-CN.ts +++ b/apps/desktop/src/i18n/locales/zh-CN.ts @@ -5701,7 +5701,7 @@ export default withEnglishFallback({ showInsertValueHintsDescription: "开启后,在 INSERT ... VALUES 子句的每个值旁显示对应列名提示。", previewStatementRunButton: "预览语句执行按钮", wordWrap: "自动换行", - wordWrapDescription: "长 SQL 在编辑器宽度内自动折行显示", + wordWrapDescription: "长内容在编辑器宽度内自动折行显示", vimMode: "Vim 模式", vimModeDescription: "在 SQL 编辑器中使用 Vim 风格的模态编辑", autoCloseBrackets: "自动成对补全", diff --git a/apps/desktop/src/i18n/locales/zh-TW.ts b/apps/desktop/src/i18n/locales/zh-TW.ts index 749f554c15..f11653917b 100644 --- a/apps/desktop/src/i18n/locales/zh-TW.ts +++ b/apps/desktop/src/i18n/locales/zh-TW.ts @@ -4844,7 +4844,7 @@ export default withEnglishFallback({ showInsertValueHintsDescription: "啟用後,在 INSERT ... VALUES 子句的每個值旁顯示對應欄位名稱提示。", previewStatementRunButton: "預覽語句執行按鈕", wordWrap: "自動換行", - wordWrapDescription: "長 SQL 在編輯器寬度內自動折行顯示", + wordWrapDescription: "長內容在編輯器寬度內自動折行顯示", vimMode: "Vim 模式", vimModeDescription: "在 SQL 編輯器中使用 Vim 風格的模態編輯", autoCloseBrackets: "自動成對補全",