diff --git a/src/main/appBadge.ts b/src/main/appBadge.ts index 63103e6..fda7eea 100644 --- a/src/main/appBadge.ts +++ b/src/main/appBadge.ts @@ -7,8 +7,7 @@ import { app, NativeImage, nativeImage } from "electron"; import { join } from "path"; import { BADGE_DIR, TRAY_ICON_DIR, TRAY_ICON_PATH } from "shared/paths"; -import { trayContainer } from "./mainWindow"; -import { Settings } from "./settings"; +import type { VencordBrowserWindow } from "./mainWindow"; const imgCache = new Map(); @@ -32,17 +31,24 @@ function loadTrayIcon(index: number) { let lastIndex: null | number = -1; -export function setBadgeCount(count: number) { +let mainWin: null | VencordBrowserWindow; +function getMainWin() { + if (mainWin != null) return mainWin; + return (mainWin = (require("./mainWindow") as typeof import("./mainWindow")).mainWin); +} + +export function setBadgeCount(count: number, tray: boolean = false) { const [index, description] = getBadgeIndexAndDescription(count); - if (Settings?.store.trayBadge) { - trayContainer.tray?.setImage(loadTrayIcon(index ?? 0)); + if (tray) { + getMainWin()._vencord_tray?.setImage(loadTrayIcon(index ?? 0)); } switch (process.platform) { case "linux": if (count === -1) count = 0; app.setBadgeCount(count); // Only works if libunity is installed + break; case "darwin": if (count === 0) { app.dock.setBadge(""); @@ -56,7 +62,7 @@ export function setBadgeCount(count: number) { lastIndex = index; // circular import shenanigans - const { mainWin } = require("./mainWindow") as typeof import("./mainWindow"); + const mainWin = getMainWin(); mainWin.setOverlayIcon(index === null ? null : loadBadge(index), description); break; } diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 84755f4..4003fc7 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -114,7 +114,7 @@ handle(IpcEvents.SELECT_VENCORD_DIR, async () => { return dir; }); -handle(IpcEvents.SET_BADGE_COUNT, (_, count: number) => setBadgeCount(count)); +handle(IpcEvents.SET_BADGE_COUNT, (_, count: number, tray: boolean) => setBadgeCount(count, tray)); function readCss() { return readFile(VENCORD_QUICKCSS_FILE, "utf-8").catch(() => ""); diff --git a/src/main/mainWindow.ts b/src/main/mainWindow.ts index 17e1605..892fe93 100644 --- a/src/main/mainWindow.ts +++ b/src/main/mainWindow.ts @@ -41,9 +41,6 @@ import { applyDeckKeyboardFix, askToApplySteamLayout, isDeckGameMode } from "./u import { downloadVencordFiles, ensureVencordFiles } from "./utils/vencordLoader"; let isQuitting = false; -export const trayContainer: { tray: Tray | null } = { - tray: null -}; applyDeckKeyboardFix(); @@ -51,7 +48,11 @@ app.on("before-quit", () => { isQuitting = true; }); -export let mainWin: BrowserWindow; +type VencordBrowserWindow = BrowserWindow & { + _vencord_tray?: Tray; +}; + +export let mainWin: VencordBrowserWindow; function makeSettingsListenerHelpers(o: SettingsStore) { const listeners = new Map<(data: any) => void, PropertyKey>(); @@ -74,7 +75,7 @@ function makeSettingsListenerHelpers(o: SettingsStore) { const [addSettingsListener, removeSettingsListeners] = makeSettingsListenerHelpers(Settings); const [addVencordSettingsListener, removeVencordSettingsListeners] = makeSettingsListenerHelpers(VencordSettings); -function initTray(win: BrowserWindow) { +function initTray(win: VencordBrowserWindow) { const trayMenu = Menu.buildFromTemplate([ { label: "Open", @@ -120,7 +121,7 @@ function initTray(win: BrowserWindow) { } ]); - const tray = (trayContainer.tray = new Tray(TRAY_ICON_PATH)); + const tray = new Tray(TRAY_ICON_PATH); tray.setToolTip("Vesktop"); tray.setContextMenu(trayMenu); tray.on("click", () => win.show()); @@ -331,10 +332,10 @@ function initWindowBoundsListeners(win: BrowserWindow) { win.on("move", saveBounds); } -function initSettingsListeners(win: BrowserWindow) { +function initSettingsListeners(win: VencordBrowserWindow) { addSettingsListener("tray", enable => { if (enable) initTray(win); - else trayContainer.tray?.destroy(); + else win._vencord_tray?.destroy(); }); addSettingsListener("disableMinSize", disable => { if (disable) { @@ -372,7 +373,7 @@ function initSpellCheck(win: BrowserWindow) { }); } -function createMainWindow() { +function createMainWindow(): VencordBrowserWindow { // Clear up previous settings listeners removeSettingsListeners(); removeVencordSettingsListeners(); diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts index 09eda0d..c5569b8 100644 --- a/src/preload/VesktopNative.ts +++ b/src/preload/VesktopNative.ts @@ -23,7 +23,7 @@ export const VesktopNative = { app: { relaunch: () => invoke(IpcEvents.RELAUNCH), getVersion: () => sendSync(IpcEvents.GET_VERSION), - setAppBadgeCount: (count: number) => invoke(IpcEvents.SET_BADGE_COUNT, count), + setBadgeCount: (count: number, tray: boolean = false) => invoke(IpcEvents.SET_BADGE_COUNT, count, tray), supportsWindowsTransparency: () => sendSync(IpcEvents.SUPPORTS_WINDOWS_TRANSPARENCY) }, autostart: { diff --git a/src/renderer/appBadge.ts b/src/renderer/appBadge.ts index 0c1b6af..be2cbb3 100644 --- a/src/renderer/appBadge.ts +++ b/src/renderer/appBadge.ts @@ -13,10 +13,6 @@ let GuildReadStateStore: any; let NotificationSettingsStore: any; export function setBadge() { - const { appBadge, trayBadge } = Settings.store; - - if (appBadge === false && trayBadge === false) return; - try { const mentionCount = GuildReadStateStore.getTotalMentionCount(); const pendingRequests = RelationshipStore.getPendingCount(); @@ -26,7 +22,8 @@ export function setBadge() { let totalCount = mentionCount + pendingRequests; if (!totalCount && hasUnread && !disableUnreadBadge) totalCount = -1; - if (appBadge || trayBadge) VesktopNative.app.setAppBadgeCount(totalCount); + if (Settings.store.appBadge || Settings.store.trayBadge) + VesktopNative.app.setBadgeCount(totalCount, Settings.store.trayBadge); } catch (e) { console.error(e); } diff --git a/src/renderer/components/Settings.tsx b/src/renderer/components/Settings.tsx index 13fea9c..b020768 100644 --- a/src/renderer/components/Settings.tsx +++ b/src/renderer/components/Settings.tsx @@ -20,7 +20,9 @@ export default function SettingsUi() { const { autostart } = VesktopNative; const [autoStartEnabled, setAutoStartEnabled] = useState(autostart.isEnabled()); - const allSwitches: Array boolean)?]> = [ + const allSwitches: Array< + false | [keyof typeof Settings, string, string, boolean?, (() => boolean)?, ((value: boolean) => void)?] + > = [ isWindows && [ "discordWindowsTitleBar", "Discord Titlebar", @@ -34,6 +36,18 @@ export default function SettingsUi() { true, () => Settings.tray ?? true ], + !isMac && [ + "trayBadge", + "Tray Notification Badge", + "Show mention badge on the tray icon", + false, + () => Settings.tray ?? true, + v => { + Settings.trayBadge = v; + if (v) setBadge(); + else VesktopNative.app.setBadgeCount(0, true); + } + ], ["arRPC", "Rich Presence", "Enables Rich Presence via arRPC", false], [ "disableMinSize", @@ -93,32 +107,18 @@ export default function SettingsUi() { onChange={v => { Settings.appBadge = v; if (v) setBadge(); - else VesktopNative.app.setAppBadgeCount(0); + else VesktopNative.app.setBadgeCount(0, Settings.trayBadge); }} note="Show mention badge on the app (taskbar/panel) icon" > Notification Badge - {Settings.tray && ( - { - Settings.trayBadge = v; - if (v) setBadge(); - else VesktopNative.app.setAppBadgeCount(0); - }} - note="Show mention badge on the tray icon" - > - Tray Notification Badge - - )} - - {switches.map(([key, text, note, def, predicate]) => ( + {switches.map(([key, text, note, def, predicate, onChange]) => ( (Settings[key as any] = v)} + onChange={onChange ?? (v => (Settings[key as any] = v))} note={note} key={key} >