From e10dfe7697d5cfb8b438e37c643898699fbd7b65 Mon Sep 17 00:00:00 2001 From: HandSonic <8078023+handsonic@users.noreply.github.com> Date: Sun, 23 Aug 2026 23:12:50 +0800 Subject: [PATCH 1/2] fix(titlebar): keep window controls under modal masks The app title bar has carried z-index: 10001 since the initial 4.0.0 code drop (d404467ab), where it only needed to outrank the host splash overlay convention (OpenScreenAnimation z-index 10000, removed early in init) while the bar hosted no interactive chrome. Since 277142633 the bar hosts real window controls (minimize/maximize/close via jcefApi), and antd modal masks/wraps plus the custom DraggableResizableModal overlay render at z-index 1000, so on the Windows desktop build the window close button floated above every confirmation dialog and could close the app while an unsaved-changes guard modal was open. Lower the bar to z-index 999: the highest value still below the modal layer (1000), and above every in-flow workspace stacking context (max z-index inside content is 100). Dropdown menus opened from the bar (CommunityAppMenu) are unaffected because they portal to document.body and global.ts already forces .ant-dropdown to z-index 11000. The -webkit-app-region drag area is not influenced by z-index. --- .../src/layouts/GlobalLayout/AppTitleBar/style.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/chat2db-community-client/src/layouts/GlobalLayout/AppTitleBar/style.ts b/chat2db-community-client/src/layouts/GlobalLayout/AppTitleBar/style.ts index 2a1f350eab..b9af35605b 100644 --- a/chat2db-community-client/src/layouts/GlobalLayout/AppTitleBar/style.ts +++ b/chat2db-community-client/src/layouts/GlobalLayout/AppTitleBar/style.ts @@ -19,7 +19,12 @@ export const useStyles = createStyles(({ css, token }) => { border-bottom: 1px solid ${token.colorBorderLayout}; user-select: none; -webkit-app-region: drag; - z-index: 10001; + /* Stay above workspace content (max in-flow z-index is 100) but below the + antd popup layer (modals/masks render at z-index 1000), so window + controls cannot float above confirmation dialogs. Dropdown menus + opened from the bar are unaffected: they portal to document.body and + global.ts forces .ant-dropdown to z-index 11000. */ + z-index: 999; `, windowsAppBar: css` height: 34px; From 4b0a58415535501a9f8ba0f02f2f84f0e3f21284 Mon Sep 17 00:00:00 2001 From: HandSonic <8078023+handsonic@users.noreply.github.com> Date: Sun, 23 Aug 2026 23:21:57 +0800 Subject: [PATCH 2/2] fix(titlebar): localize window control tooltips The Windows window control buttons (minimize/maximize/restore/close) hardcoded English aria-label/title strings while the rest of the title bar (CommunityAppMenu) already uses i18n('common.menu.*'). Add common.window.{minimize,maximize,restore,close} to every maintained locale (en-US, zh-CN, ja-JP, ko-KR, es-ES) and use them for both the aria-label and title of the three window control buttons. Refresh the English source hashes in scripts/i18n-source-hashes.json via 'node ./scripts/validate-i18n.cjs --write-source-hashes' (same method as dd27eb2e0) and add a key-parity test (yarn test:i18n-window-controls) asserting the four keys exist non-empty in every locale. --- chat2db-community-client/package.json | 3 +- .../scripts/i18n-source-hashes.json | 4 +- .../src/i18n/en-US/common.ts | 4 ++ .../src/i18n/es-ES/common.ts | 4 ++ .../src/i18n/ja-JP/common.ts | 4 ++ .../src/i18n/ko-KR/common.ts | 4 ++ .../src/i18n/windowControls.test.ts | 37 +++++++++++++++++++ .../src/i18n/zh-CN/common.ts | 4 ++ .../GlobalLayout/AppTitleBar/index.tsx | 13 ++++--- 9 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 chat2db-community-client/src/i18n/windowControls.test.ts diff --git a/chat2db-community-client/package.json b/chat2db-community-client/package.json index d93ebd176c..b698bc9b1e 100644 --- a/chat2db-community-client/package.json +++ b/chat2db-community-client/package.json @@ -23,7 +23,8 @@ "lint": "yarn lint:eslint && yarn lint:style", "lint:eslint": "eslint \"src/**/*.{js,jsx,ts,tsx}\" --max-warnings=0", "lint:style": "stylelint \"src/**/*.{css,less}\" --max-warnings=0", - "test:i18n": "node ./scripts/validate-i18n.cjs", + "test:i18n": "node ./scripts/validate-i18n.cjs && yarn test:i18n-window-controls", + "test:i18n-window-controls": "tsx src/i18n/windowControls.test.ts", "test:community-boundary": "node ./scripts/verify-community-boundary.cjs", "test:database-capabilities": "tsx src/utils/databaseJudgments.test.ts", "test:table-editor": "tsx src/blocks/DatabaseTableEditor/ColumnList/normalizeColumn.test.ts", diff --git a/chat2db-community-client/scripts/i18n-source-hashes.json b/chat2db-community-client/scripts/i18n-source-hashes.json index 2199ebed41..7b611a3329 100644 --- a/chat2db-community-client/scripts/i18n-source-hashes.json +++ b/chat2db-community-client/scripts/i18n-source-hashes.json @@ -5,7 +5,7 @@ "es-ES": { "ai.ts": "e7a2fcbfb3ed647bd14f63aca4b6c35c8fb402c49a6a1f36bb04f76f4e8415af", "chat.ts": "f6c6ab9cbc5c1c828c35c75d83c4adca347ade590b5177e10d64fdd18cc8aef5", - "common.ts": "24aa2228702754bc019f1e21dd7be9f6d1c6ff02ed9bd9227ab319f331248b11", + "common.ts": "1a458636e5d506e16114374bb25f50c0134ce5a9eaed7795ebe8a0245f01c578", "connection.ts": "d70578a3444978b60ea41c670e8b180849eaab297e33325db56c891e1058e899", "dashboard.ts": "b99f5e6b81271573a8db1a585ac879724441b7163050899c3abaf9498217bd21", "editTable.ts": "6d1233d574dbd2e038ed112bc8677b12f61a0fc831f56f77d5ce024a96a319f6", @@ -26,7 +26,7 @@ "ko-KR": { "ai.ts": "e7a2fcbfb3ed647bd14f63aca4b6c35c8fb402c49a6a1f36bb04f76f4e8415af", "chat.ts": "f6c6ab9cbc5c1c828c35c75d83c4adca347ade590b5177e10d64fdd18cc8aef5", - "common.ts": "24aa2228702754bc019f1e21dd7be9f6d1c6ff02ed9bd9227ab319f331248b11", + "common.ts": "1a458636e5d506e16114374bb25f50c0134ce5a9eaed7795ebe8a0245f01c578", "connection.ts": "d70578a3444978b60ea41c670e8b180849eaab297e33325db56c891e1058e899", "dashboard.ts": "b99f5e6b81271573a8db1a585ac879724441b7163050899c3abaf9498217bd21", "editTable.ts": "6d1233d574dbd2e038ed112bc8677b12f61a0fc831f56f77d5ce024a96a319f6", diff --git a/chat2db-community-client/src/i18n/en-US/common.ts b/chat2db-community-client/src/i18n/en-US/common.ts index 6eab62c62b..b58b897135 100644 --- a/chat2db-community-client/src/i18n/en-US/common.ts +++ b/chat2db-community-client/src/i18n/en-US/common.ts @@ -115,6 +115,10 @@ export default { 'common.menu.visitWebsite': 'Visit website', 'common.menu.viewDocs': 'View documentation', 'common.menu.viewChangelog': 'View changelog', + 'common.window.minimize': 'Minimize', + 'common.window.maximize': 'Maximize', + 'common.window.restore': 'Restore', + 'common.window.close': 'Close', 'common.text.saveConsole': 'Save console', 'common.text.textToSQL': 'Natural Language to SQL', 'common.text.editorRightClick': 'Right-Click of mouse', diff --git a/chat2db-community-client/src/i18n/es-ES/common.ts b/chat2db-community-client/src/i18n/es-ES/common.ts index c11369ab2a..4a71483923 100644 --- a/chat2db-community-client/src/i18n/es-ES/common.ts +++ b/chat2db-community-client/src/i18n/es-ES/common.ts @@ -115,6 +115,10 @@ export default { 'common.menu.visitWebsite': 'Visitar sitio web', 'common.menu.viewDocs': 'Ver documentación', 'common.menu.viewChangelog': 'Ver registro de cambios', + 'common.window.minimize': 'Minimizar', + 'common.window.maximize': 'Maximizar', + 'common.window.restore': 'Restaurar', + 'common.window.close': 'Cerrar', 'common.text.saveConsole': 'Guardar consola', 'common.text.textToSQL': 'Lenguaje natural a SQL', 'common.text.editorRightClick': 'Clic con el botón derecho', diff --git a/chat2db-community-client/src/i18n/ja-JP/common.ts b/chat2db-community-client/src/i18n/ja-JP/common.ts index 0da2b198f4..0499ab0d38 100644 --- a/chat2db-community-client/src/i18n/ja-JP/common.ts +++ b/chat2db-community-client/src/i18n/ja-JP/common.ts @@ -115,6 +115,10 @@ export default { 'common.menu.visitWebsite': '公式サイトを開く', 'common.menu.viewDocs': 'ドキュメントを表示', 'common.menu.viewChangelog': '変更履歴を表示', + 'common.window.minimize': '最小化', + 'common.window.maximize': '最大化', + 'common.window.restore': '元に戻す', + 'common.window.close': '閉じる', 'common.text.saveConsole': 'コンソールを保存', 'common.text.textToSQL': 'プレーンテキストをSQLに変換', 'common.text.editorRightClick': 'マウスの右ボタン', diff --git a/chat2db-community-client/src/i18n/ko-KR/common.ts b/chat2db-community-client/src/i18n/ko-KR/common.ts index 9bdcb6f2e0..6c7ba6fa48 100644 --- a/chat2db-community-client/src/i18n/ko-KR/common.ts +++ b/chat2db-community-client/src/i18n/ko-KR/common.ts @@ -114,6 +114,10 @@ export default { 'common.menu.visitWebsite': '웹사이트 방문', 'common.menu.viewDocs': '문서 보기', 'common.menu.viewChangelog': '변경 로그 보기', + 'common.window.minimize': '최소화', + 'common.window.maximize': '최대화', + 'common.window.restore': '이전 크기로 복원', + 'common.window.close': '닫기', 'common.text.saveConsole': '콘솔 저장', 'common.text.textToSQL': '자연어를 SQL로 변환', 'common.text.editorRightClick': '마우스 오른쪽 클릭', diff --git a/chat2db-community-client/src/i18n/windowControls.test.ts b/chat2db-community-client/src/i18n/windowControls.test.ts new file mode 100644 index 0000000000..748c8c8e49 --- /dev/null +++ b/chat2db-community-client/src/i18n/windowControls.test.ts @@ -0,0 +1,37 @@ +import assert from 'node:assert/strict'; + +import enUS from './en-US/common'; +import esES from './es-ES/common'; +import jaJP from './ja-JP/common'; +import koKR from './ko-KR/common'; +import zhCN from './zh-CN/common'; + +const WINDOW_CONTROL_KEYS = [ + 'common.window.minimize', + 'common.window.maximize', + 'common.window.restore', + 'common.window.close', +] as const; + +const localeCommonModules: Record> = { + 'en-US': enUS, + 'zh-CN': zhCN, + 'ja-JP': jaJP, + 'ko-KR': koKR, + 'es-ES': esES, +}; + +for (const [locale, common] of Object.entries(localeCommonModules)) { + for (const key of WINDOW_CONTROL_KEYS) { + const value = common[key]; + assert.notEqual( + value, + undefined, + `${locale}/common.ts must define ${key} for the title bar window controls`, + ); + assert.equal(typeof value, 'string', `${locale}/common.ts: ${key} must be a string`); + assert.ok(value!.trim().length > 0, `${locale}/common.ts: ${key} must not be empty`); + } +} + +console.log('windowControls.test.ts: all locales define the window control keys'); diff --git a/chat2db-community-client/src/i18n/zh-CN/common.ts b/chat2db-community-client/src/i18n/zh-CN/common.ts index bfd2168394..5ac3917528 100644 --- a/chat2db-community-client/src/i18n/zh-CN/common.ts +++ b/chat2db-community-client/src/i18n/zh-CN/common.ts @@ -113,6 +113,10 @@ export default { 'common.menu.visitWebsite': '访问官网', 'common.menu.viewDocs': '查看文档', 'common.menu.viewChangelog': '查看更新日志', + 'common.window.minimize': '最小化', + 'common.window.maximize': '最大化', + 'common.window.restore': '还原', + 'common.window.close': '关闭', 'common.text.saveConsole': '保存控制台', 'common.text.textToSQL': '自然语言转SQL', 'common.text.editorRightClick': '鼠标右键', diff --git a/chat2db-community-client/src/layouts/GlobalLayout/AppTitleBar/index.tsx b/chat2db-community-client/src/layouts/GlobalLayout/AppTitleBar/index.tsx index 50b8f21c71..4a670599ae 100644 --- a/chat2db-community-client/src/layouts/GlobalLayout/AppTitleBar/index.tsx +++ b/chat2db-community-client/src/layouts/GlobalLayout/AppTitleBar/index.tsx @@ -4,6 +4,7 @@ import { useStyles } from './style'; import { Dropdown, type MenuProps } from 'antd'; import { refreshPage } from '@/utils'; import { history } from 'umi'; +import i18n from '@/i18n'; import jcefApi from '@/jcef'; import { useGlobalStore } from '@/store/global'; import { isCommunityEnv, isDesktop } from '@/utils/env'; @@ -187,8 +188,8 @@ const AppBar = memo(({ className }) => {