import { BrowserWindow, dialog, session } from 'electron' import path from 'node:path' import { createTaskBarButtons, getWindowSizeInfo } from './utils' import { isLinux, isWin } from '@common/utils' import { openDevTools as handleOpenDevTools } from '@main/utils' import { mainSend } from '@common/mainIpc' import { sendFocus, sendTaskbarButtonClick } from './rendererEvent' import { encodePath } from '@common/utils/electron' let browserWindow: Electron.BrowserWindow | null = null const winEvent = () => { if (!browserWindow) return browserWindow.on('close', event => { if ( global.lx.isSkipTrayQuit || !global.lx.appSetting['tray.enable'] || // linux下,如果不是点击软件上的关闭按钮退出的操作都直接退出 // https://github.com/lyswhut/lx-music-desktop/issues/191 (isLinux && !global.lx.isTrafficLightClose) ) { browserWindow!.setProgressBar(-1) // global.lx.mainWindowClosed = true global.lx.event_app.main_window_close() return } global.lx.isTrafficLightClose &&= false event.preventDefault() browserWindow!.hide() }) browserWindow.on('closed', () => { // global.lx.mainWindowClosed = true browserWindow = null }) // browserWindow.on('restore', () => { // browserWindow.webContents.send('restore') // }) browserWindow.on('focus', () => { sendFocus() global.lx.event_app.main_window_focus() }) browserWindow.on('blur', () => { global.lx.event_app.main_window_blur() }) browserWindow.once('ready-to-show', () => { showWindow() setThumbarButtons() global.lx.event_app.main_window_ready_to_show() }) browserWindow.on('show', () => { global.lx.event_app.main_window_show() // 修复隐藏窗口后再显示时任务栏按钮丢失的问题 setThumbarButtons() }) browserWindow.on('hide', () => { global.lx.event_app.main_window_hide() }) } export const createWindow = () => { closeWindow() const windowSizeInfo = getWindowSizeInfo(global.lx.appSetting['common.windowSizeId']) const { shouldUseDarkColors, theme } = global.lx.theme const ses = session.fromPartition('persist:win-main') /** * Initial window options */ const options: Electron.BrowserWindowConstructorOptions = { height: windowSizeInfo.height, useContentSize: true, width: windowSizeInfo.width, frame: false, transparent: !global.envParams.cmdParams.dt, hasShadow: global.envParams.cmdParams.dt, // enableRemoteModule: false, // icon: join(global.__static, isWin ? 'icons/256x256.ico' : 'icons/512x512.png'), resizable: false, maximizable: false, fullscreenable: true, roundedCorners: false, show: false, webPreferences: { session: ses, nodeIntegrationInWorker: true, contextIsolation: false, webSecurity: false, nodeIntegration: true, sandbox: false, enableWebSQL: false, webgl: false, spellcheck: false, // 禁用拼写检查器 }, } if (global.envParams.cmdParams.dt) options.backgroundColor = theme.colors['--color-primary-light-1000'] if (global.lx.appSetting['common.startInFullscreen']) { options.fullscreen = true if (isLinux) options.resizable = true } browserWindow = new BrowserWindow(options) const winURL = process.env.NODE_ENV !== 'production' ? 'http://localhost:9080' : `file://${path.join(encodePath(__dirname), 'index.html')}` void browserWindow.loadURL(winURL + `?dt=${!!global.envParams.cmdParams.dt}&dark=${shouldUseDarkColors}&theme=${encodeURIComponent(JSON.stringify(theme))}`) winEvent() if (global.envParams.cmdParams.odt) handleOpenDevTools(browserWindow.webContents) // global.lx.mainWindowClosed = false // browserWindow.webContents.openDevTools() } export const isExistWindow = (): boolean => !!browserWindow export const isShowWindow = (): boolean => { if (!browserWindow) return false return browserWindow.isVisible() && (isWin ? true : browserWindow.isFocused()) } export const closeWindow = () => { if (!browserWindow) return browserWindow.close() } export const sendEvent = (name: string, params?: T) => { if (!browserWindow) return mainSend(browserWindow, name, params) } export const showSelectDialog = async(options: Electron.OpenDialogOptions) => { if (!browserWindow) throw new Error('main window is undefined') return dialog.showOpenDialog(browserWindow, options) } export const showDialog = ({ type, message, detail }: Electron.MessageBoxSyncOptions) => { if (!browserWindow) return dialog.showMessageBoxSync(browserWindow, { type, message, detail, }) } export const showSaveDialog = async(options: Electron.SaveDialogOptions) => { if (!browserWindow) throw new Error('main window is undefined') return dialog.showSaveDialog(browserWindow, options) } export const minimize = () => { if (!browserWindow) return browserWindow.minimize() } export const maximize = () => { if (!browserWindow) return browserWindow.maximize() } export const unmaximize = () => { if (!browserWindow) return browserWindow.unmaximize() } export const toggleHide = () => { if (!browserWindow) return browserWindow.isVisible() ? browserWindow.hide() : browserWindow.show() } export const toggleMinimize = () => { if (!browserWindow) return if (browserWindow.isVisible()) { if (browserWindow.isMinimized()) browserWindow.restore() else browserWindow.minimize() } else browserWindow.show() } export const showWindow = () => { if (!browserWindow) return if (browserWindow.isVisible()) { if (browserWindow.isMinimized()) browserWindow.restore() else browserWindow.focus() } else browserWindow.show() } export const hideWindow = () => { if (!browserWindow) return browserWindow.hide() } export const setWindowBounds = (options: Partial) => { if (!browserWindow) return browserWindow.setBounds(options) } export const setProgressBar = (progress: number, options?: Electron.ProgressBarOptions) => { if (!browserWindow) return browserWindow.setProgressBar(progress, options) } export const setIgnoreMouseEvents = (ignore: boolean, options?: Electron.IgnoreMouseEventsOptions) => { if (!browserWindow) return browserWindow.setIgnoreMouseEvents(ignore, options) } export const toggleDevTools = () => { if (!browserWindow) return if (browserWindow.webContents.isDevToolsOpened()) { browserWindow.webContents.closeDevTools() } else { handleOpenDevTools(browserWindow.webContents) } } export const setFullScreen = (isFullscreen: boolean): boolean => { if (!browserWindow) return false if (isLinux) { // linux 需要先设置为可调整窗口大小才能全屏 if (isFullscreen) { browserWindow.setResizable(isFullscreen) browserWindow.setFullScreen(isFullscreen) } else { browserWindow.setFullScreen(isFullscreen) browserWindow.setResizable(isFullscreen) } } else { browserWindow.setFullScreen(isFullscreen) } return isFullscreen } const taskBarButtonFlags: LX.TaskBarButtonFlags = { empty: true, collect: false, play: false, next: true, prev: true, } export const setThumbarButtons = ({ empty, collect, play, next, prev }: LX.TaskBarButtonFlags = taskBarButtonFlags) => { if (!isWin || !browserWindow) return taskBarButtonFlags.empty = empty taskBarButtonFlags.collect = collect taskBarButtonFlags.play = play taskBarButtonFlags.next = next taskBarButtonFlags.prev = prev browserWindow.setThumbarButtons(createTaskBarButtons(taskBarButtonFlags, action => { sendTaskbarButtonClick(action) })) } export const setThumbnailClip = (region: Electron.Rectangle) => { if (!browserWindow) return browserWindow.setThumbnailClip(region) } export const clearCache = async() => { if (!browserWindow) throw new Error('main window is undefined') await browserWindow.webContents.session.clearCache() } export const getCacheSize = async() => { if (!browserWindow) throw new Error('main window is undefined') return browserWindow.webContents.session.getCacheSize() } export const getWebContents = (): Electron.WebContents => { if (!browserWindow) throw new Error('main window is undefined') return browserWindow.webContents }