feat: add fallback mechanism for floating window startup failure

This commit is contained in:
ezequielnick 2025-08-09 13:48:55 +08:00
parent 294dd75b48
commit 58732ce653
2 changed files with 87 additions and 47 deletions

View File

@ -195,7 +195,11 @@ app.whenReady().then(async () => {
registerIpcMainHandlers() registerIpcMainHandlers()
await createWindow() await createWindow()
if (showFloating) { if (showFloating) {
showFloatingWindow() try {
await showFloatingWindow()
} catch (error) {
console.error('Failed to create floating window on startup:', error)
}
} }
if (!disableTray) { if (!disableTray) {
await createTray() await createTray()

View File

@ -9,58 +9,94 @@ import { buildContextMenu, showTrayIcon } from './tray'
export let floatingWindow: BrowserWindow | null = null export let floatingWindow: BrowserWindow | null = null
async function createFloatingWindow(): Promise<void> { async function createFloatingWindow(): Promise<void> {
const floatingWindowState = windowStateKeeper({ try {
file: 'floating-window-state.json' const floatingWindowState = windowStateKeeper({
}) file: 'floating-window-state.json'
const { customTheme = 'default.css' } = await getAppConfig() })
floatingWindow = new BrowserWindow({ const { customTheme = 'default.css' } = await getAppConfig()
width: 120,
height: 42, const windowOptions: Electron.BrowserWindowConstructorOptions = {
x: floatingWindowState.x, width: 120,
y: floatingWindowState.y, height: 42,
show: false, x: floatingWindowState.x,
frame: false, y: floatingWindowState.y,
alwaysOnTop: true, show: false,
resizable: false, frame: false,
transparent: true, alwaysOnTop: true,
skipTaskbar: true, resizable: false,
minimizable: false, transparent: true,
maximizable: false, skipTaskbar: true,
fullscreenable: false, minimizable: false,
closable: false, maximizable: false,
webPreferences: { fullscreenable: false,
preload: join(__dirname, '../preload/index.js'), closable: false,
spellcheck: false, backgroundColor: '#00000000',
sandbox: false webPreferences: {
preload: join(__dirname, '../preload/index.js'),
spellcheck: false,
sandbox: false,
nodeIntegration: false,
contextIsolation: true
}
} }
})
floatingWindowState.manage(floatingWindow) // windows 添加兼容性处理
floatingWindow.on('ready-to-show', () => { if (process.platform === 'win32') {
applyTheme(customTheme) windowOptions.hasShadow = false
floatingWindow?.show() windowOptions.webPreferences!.offscreen = false
floatingWindow?.setAlwaysOnTop(true, 'screen-saver')
})
floatingWindow.on('moved', () => {
if (floatingWindow) floatingWindowState.saveState(floatingWindow)
})
ipcMain.on('updateFloatingWindow', () => {
if (floatingWindow) {
floatingWindow?.webContents.send('controledMihomoConfigUpdated')
floatingWindow?.webContents.send('appConfigUpdated')
} }
})
if (is.dev && process.env['ELECTRON_RENDERER_URL']) { floatingWindow = new BrowserWindow(windowOptions)
floatingWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/floating.html`) floatingWindowState.manage(floatingWindow)
} else {
floatingWindow.loadFile(join(__dirname, '../renderer/floating.html')) floatingWindow.webContents.on('render-process-gone', (_, details) => {
console.error('Floating window render process gone:', details.reason)
floatingWindow = null
})
floatingWindow.on('ready-to-show', () => {
try {
applyTheme(customTheme)
floatingWindow?.show()
floatingWindow?.setAlwaysOnTop(true, 'screen-saver')
} catch (error) {
console.error('Error in floating window ready-to-show:', error)
}
})
floatingWindow.on('moved', () => {
if (floatingWindow) floatingWindowState.saveState(floatingWindow)
})
ipcMain.on('updateFloatingWindow', () => {
if (floatingWindow) {
floatingWindow?.webContents.send('controledMihomoConfigUpdated')
floatingWindow?.webContents.send('appConfigUpdated')
}
})
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
await floatingWindow.loadURL(`${process.env['ELECTRON_RENDERER_URL']}/floating.html`)
} else {
await floatingWindow.loadFile(join(__dirname, '../renderer/floating.html'))
}
} catch (error) {
console.error('Failed to create floating window:', error)
floatingWindow = null
throw error
} }
} }
export async function showFloatingWindow(): Promise<void> { export async function showFloatingWindow(): Promise<void> {
if (floatingWindow) { try {
floatingWindow.show() if (floatingWindow && !floatingWindow.isDestroyed()) {
} else { floatingWindow.show()
createFloatingWindow() } else {
await createFloatingWindow()
}
} catch (error) {
console.error('Failed to show floating window:', error)
await patchAppConfig({ showFloatingWindow: false })
throw error
} }
} }