diff --git a/frontend/electron/main.ts b/frontend/electron/main.ts index e562715..a9dd5f6 100644 --- a/frontend/electron/main.ts +++ b/frontend/electron/main.ts @@ -16,6 +16,12 @@ const isDev = !app.isPackaged; app.name = "Ultimate Ban Tracker"; +// Force Wayland/Ozone support if on Linux +if (process.platform === 'linux') { + app.commandLine.appendSwitch('enable-features', 'UseOzonePlatform'); + app.commandLine.appendSwitch('ozone-platform', 'wayland'); +} + // Load environment variables dotenv.config({ path: path.join(app.getAppPath(), '..', '.env') }); @@ -89,35 +95,64 @@ const initBackend = () => { // --- System Tray --- const createTray = () => { + console.log('[Tray] Initializing...'); + const possiblePaths = [ - '/usr/share/pixmaps/ultimate-ban-tracker.png', - path.join(process.resourcesPath, 'assets-build', 'icon.png'), - path.join(app.getAppPath(), 'assets-build', 'icon.png'), - path.join(__dirname, '..', 'assets-build', 'icon.png') + '/usr/share/pixmaps/ultimate-ban-tracker.png', // Priority 1: System installed + path.join(process.resourcesPath, 'assets-build', 'icon.png'), // Priority 2: Unpacked resources + path.join(app.getAppPath(), 'assets-build', 'icon.png'), // Priority 3: Internal ASAR (Fallback) + path.join(__dirname, '..', 'assets-build', 'icon.png') // Priority 4: Dev ]; let iconPath = ''; - for (const p of possiblePaths) { if (p && fs.existsSync(p)) { iconPath = p; break; } } + for (const p of possiblePaths) { + console.log(`[Tray] Checking path: ${p}`); + if (p && fs.existsSync(p)) { + iconPath = p; + console.log(`[Tray] Found icon at: ${p}`); + break; + } + } - if (!iconPath) { try { tray = new Tray(nativeImage.createEmpty()); } catch (e) {} return; } + if (!iconPath) { + console.warn('[Tray] FAILED: No icon file found on disk. Using empty fallback.'); + try { tray = new Tray(nativeImage.createEmpty()); } catch (e) {} + } else { + try { + const icon = nativeImage.createFromPath(iconPath).resize({ width: 16, height: 16 }); + tray = new Tray(icon); + console.log('[Tray] Tray object created successfully'); + } catch (e: any) { + console.error(`[Tray] Failed to create Tray object: ${e.message}`); + return; + } + } - try { - const icon = nativeImage.createFromPath(iconPath).resize({ width: 16, height: 16 }); - tray = new Tray(icon); + if (tray) { tray.setToolTip('Ultimate Ban Tracker'); if (process.platform === 'linux') tray.setIgnoreMouseEvents(false); tray.on('click', () => { if (mainWindow) { mainWindow.show(); mainWindow.focus(); } }); + + // Initial menu build updateTrayMenu(); + const config = store.get('serverConfig'); if (config?.theme) setAppIcon(config.theme); - } catch (e: any) { console.error(`[Tray] Error: ${e.message}`); } + } }; const updateTrayMenu = () => { - if (!tray) return; + if (!tray) { + console.warn('[Tray] Cannot update menu: Tray is null'); + return; + } + const accounts = store.get('accounts') as Account[]; const config = store.get('serverConfig'); - const contextMenu = Menu.buildFromTemplate([ + + console.log(`[Tray] Building menu with ${accounts.length} accounts...`); + + const menuTemplate: any[] = [ { label: `Ultimate Ban Tracker v${app.getVersion()}`, enabled: false }, { type: 'separator' }, { @@ -125,34 +160,83 @@ const updateTrayMenu = () => { submenu: accounts.length > 0 ? accounts.map(acc => ({ label: `${acc.personaName} ${acc.loginName ? `(${acc.loginName})` : ''}`, enabled: !!acc.loginName, - click: () => handleSwitchAccount(acc.loginName) - })) : [{ label: 'No accounts found', enabled: false }] + click: () => { + console.log(`[Tray] Switching to account: ${acc.loginName}`); + handleSwitchAccount(acc.loginName); + } + })) : [{ label: 'No accounts tracked', enabled: false }] + }, + { + label: 'Sync Now', + enabled: !!config?.enabled, + click: () => { + console.log('[Tray] Manual sync requested'); + syncAccounts(true); + } }, - { label: 'Sync Now', enabled: !!config?.enabled, click: () => syncAccounts(true) }, { type: 'separator' }, - { label: 'Show Dashboard', click: () => { if (mainWindow) { mainWindow.show(); mainWindow.focus(); } } }, - { label: 'Quit', click: () => { - (app as any).isQuitting = true; - if (tray) tray.destroy(); - app.quit(); - } } - ]); - tray.setContextMenu(contextMenu); + { + label: 'Show Dashboard', + click: () => { + console.log('[Tray] Showing dashboard'); + if (mainWindow) { + mainWindow.show(); + mainWindow.focus(); + } + } + }, + { + label: 'Quit', + click: () => { + console.log('[Tray] Quitting application via menu'); + (app as any).isQuitting = true; + if (tray) tray.destroy(); + app.quit(); + } + } + ]; + + try { + const contextMenu = Menu.buildFromTemplate(menuTemplate); + tray.setContextMenu(contextMenu); + console.log('[Tray] Menu updated and attached'); + } catch (e: any) { + console.error(`[Tray] Failed to build or set context menu: ${e.message}`); + } }; const setAppIcon = (themeName: string = 'steam') => { + console.log(`[AppIcon] Setting icon for theme: ${themeName}`); const possiblePaths = [ - path.join(__dirname, '..', 'assets-build', 'icons', `${themeName}.svg`), path.join(app.getAppPath(), 'assets-build', 'icons', `${themeName}.svg`), + path.join(__dirname, '..', 'assets-build', 'icons', `${themeName}.svg`), + path.join(process.resourcesPath, 'assets-build', 'icons', `${themeName}.svg`), '/usr/share/pixmaps/ultimate-ban-tracker.png' ]; + let iconPath = ''; - for (const p of possiblePaths) { if (fs.existsSync(p)) { iconPath = p; break; } } - if (!iconPath) return; - const icon = nativeImage.createFromPath(iconPath); - if (tray) tray.setImage(icon.resize({ width: 16, height: 16 })); - if (mainWindow) mainWindow.setIcon(icon); - updateTrayMenu(); + for (const p of possiblePaths) { if (p && fs.existsSync(p)) { iconPath = p; break; } } + + if (!iconPath) { + console.warn(`[AppIcon] No themed icon found for ${themeName}`); + return; + } + + try { + const icon = nativeImage.createFromPath(iconPath); + if (tray) { + tray.setImage(icon.resize({ width: 16, height: 16 })); + console.log('[AppIcon] Tray icon updated'); + } + if (mainWindow) { + mainWindow.setIcon(icon); + console.log('[AppIcon] Window icon updated'); + } + // Re-build menu to ensure everything is consistent + updateTrayMenu(); + } catch (e: any) { + console.error(`[AppIcon] Failed to apply themed icon: ${e.message}`); + } }; // --- Steam Logic ---