feat: enhance WindowService with improved DevTools setup and update Sidebar layout with logo integration

This commit is contained in:
duanshuwen
2026-04-17 21:59:50 +08:00
parent e9f3a29886
commit c93f7ae2c8
3 changed files with 44 additions and 6 deletions

View File

@@ -1,7 +1,7 @@
import type { WindowNames } from '@runtime/lib/types' import type { WindowNames } from '@runtime/lib/types'
import { CONFIG_KEYS, IPC_EVENTS, WINDOW_NAMES } from '@runtime/lib/constants' import { CONFIG_KEYS, IPC_EVENTS, WINDOW_NAMES } from '@runtime/lib/constants'
import { BrowserWindow, BrowserWindowConstructorOptions, ipcMain, IpcMainInvokeEvent, type IpcMainEvent } from 'electron' import { app, BrowserWindow, BrowserWindowConstructorOptions, ipcMain, IpcMainInvokeEvent, type IpcMainEvent } from 'electron'
import { createLogo } from '@electron/utils' import { createLogo } from '@electron/utils'
import logManager from '@electron/service/logger' import logManager from '@electron/service/logger'
@@ -9,6 +9,8 @@ import configManager from '@electron/service/config-service'
import themeManager from '@electron/service/theme-service' import themeManager from '@electron/service/theme-service'
import path from 'node:path'; import path from 'node:path';
declare const MAIN_WINDOW_VITE_DEV_SERVER_URL: string | undefined;
interface WindowState { interface WindowState {
instance: BrowserWindow | void; instance: BrowserWindow | void;
isHidden: boolean; isHidden: boolean;
@@ -93,8 +95,7 @@ class WindowService {
if (this.get(name)) return; if (this.get(name)) return;
const isHiddenWin = this._isHiddenWin(name); const isHiddenWin = this._isHiddenWin(name);
let window = this._createWinInstance(name, { ...size, ...moreOpts }); let window = this._createWinInstance(name, { ...size, ...moreOpts });
this._setupDevtools(window, name);
if (this.isDev) window.webContents.openDevTools()
!isHiddenWin && this !isHiddenWin && this
._setupWinLifecycle(window, name) ._setupWinLifecycle(window, name)
@@ -120,6 +121,41 @@ class WindowService {
return window; return window;
} }
private _setupDevtools(window: BrowserWindow, name: WindowNames) {
if (!this.isDev) return;
let opened = false;
const openDevtools = () => {
if (opened || window.isDestroyed()) return;
opened = true;
try {
window.webContents.openDevTools({ mode: 'detach', activate: true });
logManager.info(`DevTools opened for window: ${name}`);
} catch (error) {
opened = false;
logManager.warn(`Failed to open DevTools for window: ${name}`, error);
}
};
window.webContents.once('did-finish-load', () => {
setTimeout(openDevtools, 150);
});
window.webContents.on('before-input-event', (_event, input) => {
const isMacDevtoolsShortcut = process.platform === 'darwin' && input.meta && input.alt && input.key.toLowerCase() === 'i';
const isF12 = input.key === 'F12';
if (!isF12 && !isMacDevtoolsShortcut) return;
if (window.webContents.isDevToolsOpened()) {
window.webContents.closeDevTools();
return;
}
openDevtools();
});
}
private _setupWinLifecycle(window: BrowserWindow, name: WindowNames) { private _setupWinLifecycle(window: BrowserWindow, name: WindowNames) {
window.once('closed', () => { window.once('closed', () => {
this._winStates[name].onClosed.forEach(callback => callback(window)); this._winStates[name].onClosed.forEach(callback => callback(window));

View File

@@ -6,7 +6,7 @@ export default function MainLayout() {
const platform = (window as any).api?.platform ?? ''; const platform = (window as any).api?.platform ?? '';
return ( return (
<div className="bg-white dark:!bg-[#0f0f10] h-screen flex flex-col"> <div className=" dark:!bg-[#0f0f10] h-screen flex flex-col">
<TitleBar /> <TitleBar />
<main <main

View File

@@ -3,6 +3,8 @@ import { Book, Clock, Code, Cpu, House, Puzzle, Settings } from 'lucide-react';
import { useI18n } from '../../i18n'; import { useI18n } from '../../i18n';
import { NAV_ITEMS, normalizeWorkspacePath } from '../../router/routes'; import { NAV_ITEMS, normalizeWorkspacePath } from '../../router/routes';
import blueLogo from '../../assets/images/login/blue_logo.png';
const MENU_MARKS: Record<string, typeof House> = { const MENU_MARKS: Record<string, typeof House> = {
'/home': House, '/home': House,
'/knowledge': Book, '/knowledge': Book,
@@ -21,7 +23,7 @@ export default function Sidebar() {
return ( return (
<aside className="box-border flex h-full w-[80px] flex-col items-center pb-[8px]"> <aside className="box-border flex h-full w-[80px] flex-col items-center pb-[8px]">
<div className="flex w-full flex-col gap-[16px]"> <div className="flex flex-1 w-full flex-col gap-[16px]">
{NAV_ITEMS.map((item) => { {NAV_ITEMS.map((item) => {
const active = currentId === item.path; const active = currentId === item.path;
const isSetting = item.path === '/setting'; const isSetting = item.path === '/setting';
@@ -64,7 +66,7 @@ export default function Sidebar() {
</div> </div>
<div className="mt-auto flex h-[48px] w-[48px] items-center justify-center overflow-hidden rounded-full border border-black/10 bg-white dark:border-[#2a2a2d] dark:bg-[#222225]"> <div className="mt-auto flex h-[48px] w-[48px] items-center justify-center overflow-hidden rounded-full border border-black/10 bg-white dark:border-[#2a2a2d] dark:bg-[#222225]">
<span className="text-[16px] font-bold text-[#2B7FFF]">Z</span> <img className="h-full w-full object-cover" src={blueLogo} alt="Logo" />
</div> </div>
</aside> </aside>
); );