From 61446dacfcf06b0e9a6eca5c51386b52d4e46ccd Mon Sep 17 00:00:00 2001 From: Ivan Fontosh Date: Mon, 3 Aug 2026 09:21:26 +0800 Subject: [PATCH] fix(ui): hide Electron menu bar and polish editor chrome Drop the system View menu across windows, show the open project name above Game properties, and keep scene list kebab visible with truncated titles and overflow tooltips. Co-authored-by: Cursor --- app/main/index.ts | 27 ++-------------------- app/main/windows/createWindows.ts | 6 +---- app/renderer/editor/EditorApp.module.css | 22 +++++++++++++++++- app/renderer/editor/EditorApp.tsx | 22 +++++++++++++++++- app/renderer/editor/i18n/editorMessages.ts | 2 ++ 5 files changed, 47 insertions(+), 32 deletions(-) diff --git a/app/main/index.ts b/app/main/index.ts index 74b800e..7b68730 100644 --- a/app/main/index.ts +++ b/app/main/index.ts @@ -143,32 +143,9 @@ if (!gotTheLock) { const projectStore = new ZipProjectStore(); -/** Без меню Electron не вешает горячие клавиши DevTools (Ctrl+Shift+I / F12). */ -function wantsDevToolsMenu(): boolean { - return ( - process.env.NODE_ENV === 'development' || - Boolean(process.env.VITE_DEV_SERVER_URL) || - process.env.DND_OPEN_DEVTOOLS === '1' - ); -} - +/** Системная полоса меню Electron отключена во всех режимах (в т.ч. без пункта «Вид»). */ function installAppMenuForSession(): void { - if (!wantsDevToolsMenu()) { - Menu.setApplicationMenu(null); - return; - } - const template: Electron.MenuItemConstructorOptions[] = []; - if (process.platform === 'darwin') { - template.push({ - label: app.name, - submenu: [{ role: 'about' }, { type: 'separator' }, { role: 'quit' }], - }); - } - template.push({ - label: 'Вид', - submenu: [{ role: 'reload' }, { role: 'forceReload' }, { type: 'separator' }, { role: 'toggleDevTools' }], - }); - Menu.setApplicationMenu(Menu.buildFromTemplate(template)); + Menu.setApplicationMenu(null); } const effectsStore = new EffectsStore(); diff --git a/app/main/windows/createWindows.ts b/app/main/windows/createWindows.ts index 82d684c..e93e012 100644 --- a/app/main/windows/createWindows.ts +++ b/app/main/windows/createWindows.ts @@ -208,11 +208,11 @@ function createWindow(kind: WindowKind, opts?: CreateWindowOpts): BrowserWindow const win = new BrowserWindow({ width: size.width, height: size.height, + autoHideMenuBar: true, ...(kind === 'sceneDescription' ? { minWidth: 520, minHeight: 420, - autoHideMenuBar: true, } : {}), ...(kind === 'materials' @@ -222,7 +222,6 @@ function createWindow(kind: WindowKind, opts?: CreateWindowOpts): BrowserWindow minWidth: 260, maxWidth: 360, minHeight: 480, - autoHideMenuBar: true, } : {}), ...(kind === 'npcsEditor' @@ -231,7 +230,6 @@ function createWindow(kind: WindowKind, opts?: CreateWindowOpts): BrowserWindow height: NPCS_EDITOR_WINDOW_HEIGHT, minWidth: 1100, minHeight: 640, - autoHideMenuBar: true, } : {}), ...(kind === 'sceneEditor' @@ -240,7 +238,6 @@ function createWindow(kind: WindowKind, opts?: CreateWindowOpts): BrowserWindow height: 800, minWidth: 960, minHeight: 600, - autoHideMenuBar: true, } : {}), ...(kind === 'npcs' @@ -250,7 +247,6 @@ function createWindow(kind: WindowKind, opts?: CreateWindowOpts): BrowserWindow minWidth: 560, maxWidth: 900, minHeight: 480, - autoHideMenuBar: true, } : {}), show: false, diff --git a/app/renderer/editor/EditorApp.module.css b/app/renderer/editor/EditorApp.module.css index ac830cf..cb3ebec 100644 --- a/app/renderer/editor/EditorApp.module.css +++ b/app/renderer/editor/EditorApp.module.css @@ -265,6 +265,18 @@ flex-shrink: 0; } +.projectNameLabel { + font-weight: 700; + font-size: 13px; + letter-spacing: 0.02em; + margin-bottom: 10px; + color: var(--text1); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + flex-shrink: 0; +} + .inspectorScroll { flex: 1; min-height: 0; @@ -1076,6 +1088,7 @@ border: 1px solid transparent; box-sizing: border-box; background: transparent; + min-width: 0; } .sceneCard:not(.sceneCardActive):hover { @@ -1163,21 +1176,23 @@ padding: 10px; display: grid; gap: 6px; + min-width: 0; } .sceneCardHeader { display: flex; align-items: center; gap: 8px; + min-width: 0; } .badgeCurrent { font-size: var(--text-xs); color: var(--accent2); + flex-shrink: 0; } .sceneMenuBtn { - margin-left: auto; border: none; background: var(--panel2); border-radius: var(--radius-xs); @@ -1191,6 +1206,11 @@ .sceneCardTitle { font-weight: 750; + flex: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .menuBackdrop { diff --git a/app/renderer/editor/EditorApp.tsx b/app/renderer/editor/EditorApp.tsx index 8f8c825..e04c14b 100644 --- a/app/renderer/editor/EditorApp.tsx +++ b/app/renderer/editor/EditorApp.tsx @@ -1018,6 +1018,9 @@ export function EditorApp() {
{state.project ? ( <> +
+ {t('scenes.projectLabel', { name: state.project.meta.name })} +
{t('scenes.inspectorGame')}
(null); const [pendingDelete, setPendingDelete] = useState(false); + const titleRef = useRef(null); + const [titleTooltip, setTitleTooltip] = useState(undefined); useEffect(() => { if (!menu) return; @@ -2875,6 +2880,22 @@ function SceneListCard({
{scene.active ?
{t('sceneCard.current')}
: null} +
{ + const el = titleRef.current; + if (!el) { + setTitleTooltip(undefined); + return; + } + setTitleTooltip(el.scrollWidth > el.clientWidth + 1 ? scene.title : undefined); + }} + onMouseLeave={() => setTitleTooltip(undefined)} + > + {scene.title} +
-
{scene.title}
{menu && menuPos ? createPortal( diff --git a/app/renderer/editor/i18n/editorMessages.ts b/app/renderer/editor/i18n/editorMessages.ts index 979c621..5ee01d3 100644 --- a/app/renderer/editor/i18n/editorMessages.ts +++ b/app/renderer/editor/i18n/editorMessages.ts @@ -282,6 +282,7 @@ export const EDITOR_MESSAGES: Record> = { 'scenes.dropSkippedNoPath': 'не удалось получить путь к файлу', 'scenes.inspectorGame': 'Свойства игры', 'scenes.inspectorScene': 'Свойства сцены', + 'scenes.projectLabel': 'Проект: {name}', 'scenes.selectHint': 'Выберите сцену слева, чтобы редактировать её свойства.', 'scenes.openProjectHint': 'Откройте проект, чтобы редактировать кампанию и сцены.', @@ -851,6 +852,7 @@ export const EDITOR_MESSAGES: Record> = { 'scenes.dropSkippedNoPath': 'could not resolve file path', 'scenes.inspectorGame': 'Game properties', 'scenes.inspectorScene': 'Scene properties', + 'scenes.projectLabel': 'Project: {name}', 'scenes.selectHint': 'Select a scene on the left to edit its properties.', 'scenes.openProjectHint': 'Open a project to edit the campaign and scenes.',