diff --git a/frontend/assets-build/icons/latte.svg b/frontend/assets-build/icons/latte.svg new file mode 100644 index 0000000..927b015 --- /dev/null +++ b/frontend/assets-build/icons/latte.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/assets-build/icons/mocha.svg b/frontend/assets-build/icons/mocha.svg new file mode 100644 index 0000000..be50aab --- /dev/null +++ b/frontend/assets-build/icons/mocha.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/assets-build/icons/nord.svg b/frontend/assets-build/icons/nord.svg new file mode 100644 index 0000000..831f6fd --- /dev/null +++ b/frontend/assets-build/icons/nord.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/assets-build/icons/steam.svg b/frontend/assets-build/icons/steam.svg new file mode 100644 index 0000000..991fece --- /dev/null +++ b/frontend/assets-build/icons/steam.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/assets-build/icons/tokyo.svg b/frontend/assets-build/icons/tokyo.svg new file mode 100644 index 0000000..e7ed4c7 --- /dev/null +++ b/frontend/assets-build/icons/tokyo.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/electron/main.ts b/frontend/electron/main.ts index 8d3335c..09c1cb8 100644 --- a/frontend/electron/main.ts +++ b/frontend/electron/main.ts @@ -135,7 +135,14 @@ const createTray = () => { tray = new Tray(icon); tray.setToolTip('Ultimate Ban Tracker'); tray.on('click', () => { if (mainWindow) { mainWindow.show(); mainWindow.focus(); } }); - updateTrayMenu(); + + // Load initial themed icon + const config = store.get('serverConfig'); + if (config?.theme) { + setAppIcon(config.theme); + } else { + updateTrayMenu(); // Fallback to refresh menu + } } catch (e) { } }; @@ -162,6 +169,25 @@ const updateTrayMenu = () => { tray.setContextMenu(contextMenu); }; +const setAppIcon = (themeName: string = 'steam') => { + const assetsDir = path.join(__dirname, '..', 'assets-build', 'icons'); + const iconPath = path.join(assetsDir, `${themeName}.svg`); + + if (!fs.existsSync(iconPath)) return; + + const icon = nativeImage.createFromPath(iconPath); + + // Update Tray + if (tray) { + tray.setImage(icon.resize({ width: 16, height: 16 })); + } + + // Update Main Window + if (mainWindow) { + mainWindow.setIcon(icon); + } +}; + // --- Steam Logic --- const killSteam = async () => { return new Promise((resolve) => { @@ -571,6 +597,13 @@ ipcMain.handle('admin-delete-user', async (event, userId: string) => { initBacke ipcMain.handle('admin-get-accounts', async () => { initBackend(); return backend ? await backend.getAdminAccounts() : []; }); ipcMain.handle('admin-remove-account', async (event, steamId: string) => { initBackend(); if (backend) await backend.forceRemoveAccount(steamId); return true; }); +ipcMain.handle('force-sync', async () => { await syncAccounts(true); return true; }); + +ipcMain.handle('update-app-icon', (event, themeName: string) => { + setAppIcon(themeName); + return true; +}); + ipcMain.handle('switch-account', async (event, loginName: string) => { if (!loginName) return false; try { diff --git a/frontend/electron/preload.ts b/frontend/electron/preload.ts index 5da78f1..f18d9d4 100644 --- a/frontend/electron/preload.ts +++ b/frontend/electron/preload.ts @@ -10,6 +10,7 @@ contextBridge.exposeInMainWorld('electronAPI', { revokeAccountAccess: (steamId: string, targetSteamId: string) => ipcRenderer.invoke('revoke-account-access', steamId, targetSteamId), revokeAllAccountAccess: (steamId: string) => ipcRenderer.invoke('revoke-all-account-access', steamId), openExternal: (url: string) => ipcRenderer.invoke('open-external', url), + updateAppIcon: (theme: string) => ipcRenderer.invoke('update-app-icon', theme), openSteamAppLogin: () => ipcRenderer.invoke('open-steam-app-login'), openSteamLogin: (steamId: string) => ipcRenderer.invoke('open-steam-login', steamId), diff --git a/frontend/src/theme/ThemeContext.tsx b/frontend/src/theme/ThemeContext.tsx index 2f58364..4eb94a4 100644 --- a/frontend/src/theme/ThemeContext.tsx +++ b/frontend/src/theme/ThemeContext.tsx @@ -31,8 +31,18 @@ export const AppThemeProvider: React.FC<{ children: React.ReactNode }> = ({ chil if (api?.updateServerConfig) { await api.updateServerConfig({ theme }); } + if (api?.updateAppIcon) { + await api.updateAppIcon(theme); + } }; + useEffect(() => { + const api = (window as any).electronAPI; + if (api?.updateAppIcon && currentTheme) { + api.updateAppIcon(currentTheme); + } + }, [currentTheme]); + const theme = useMemo(() => getTheme(currentTheme), [currentTheme]); return (