From 31799ccfb0300b105e1d329c997911827ba21c94 Mon Sep 17 00:00:00 2001 From: V Date: Fri, 23 Jun 2023 17:20:54 +0200 Subject: [PATCH] Add Notification badge --- src/main/about.ts | 4 +-- src/main/appBadge.ts | 50 +++++++++++++++++++++++++++ src/main/firstLaunch.ts | 4 +-- src/main/ipc.ts | 3 ++ src/main/splash.ts | 4 +-- src/preload/VencordDesktopNative.ts | 3 +- src/renderer/appBadge.ts | 43 +++++++++++++++++++++++ src/renderer/components/Settings.tsx | 13 +++++++ src/renderer/index.ts | 1 + src/shared/IpcEvents.ts | 2 ++ src/shared/paths.ts | 2 ++ src/shared/settings.d.ts | 1 + src/updater/main.ts | 4 +-- static/badges/1.ico | Bin 0 -> 15086 bytes static/badges/10.ico | Bin 0 -> 15086 bytes static/badges/11.ico | Bin 0 -> 15086 bytes static/badges/2.ico | Bin 0 -> 15086 bytes static/badges/3.ico | Bin 0 -> 15086 bytes static/badges/4.ico | Bin 0 -> 15086 bytes static/badges/5.ico | Bin 0 -> 15086 bytes static/badges/6.ico | Bin 0 -> 15086 bytes static/badges/7.ico | Bin 0 -> 15086 bytes static/badges/8.ico | Bin 0 -> 15086 bytes static/badges/9.ico | Bin 0 -> 15086 bytes static/{ => views}/about.html | 0 static/{ => views}/first-launch.html | 0 static/{ => views}/splash.html | 0 static/{ => views}/updater.html | 0 28 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 src/main/appBadge.ts create mode 100644 src/renderer/appBadge.ts create mode 100644 static/badges/1.ico create mode 100644 static/badges/10.ico create mode 100644 static/badges/11.ico create mode 100644 static/badges/2.ico create mode 100644 static/badges/3.ico create mode 100644 static/badges/4.ico create mode 100644 static/badges/5.ico create mode 100644 static/badges/6.ico create mode 100644 static/badges/7.ico create mode 100644 static/badges/8.ico create mode 100644 static/badges/9.ico rename static/{ => views}/about.html (100%) rename static/{ => views}/first-launch.html (100%) rename static/{ => views}/splash.html (100%) rename static/{ => views}/updater.html (100%) diff --git a/src/main/about.ts b/src/main/about.ts index a335b85..c15f2b8 100644 --- a/src/main/about.ts +++ b/src/main/about.ts @@ -7,7 +7,7 @@ import { app, BrowserWindow } from "electron"; import { readFileSync } from "fs"; import { join } from "path"; -import { ICON_PATH, STATIC_DIR } from "shared/paths"; +import { ICON_PATH, VIEW_DIR } from "shared/paths"; import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally"; @@ -20,7 +20,7 @@ export function createAboutWindow() { makeLinksOpenExternally(about); - const html = readFileSync(join(STATIC_DIR, "about.html"), "utf-8").replaceAll("%VERSION%", app.getVersion()); + const html = readFileSync(join(VIEW_DIR, "about.html"), "utf-8").replaceAll("%VERSION%", app.getVersion()); about.loadURL("data:text/html;charset=utf-8," + html); diff --git a/src/main/appBadge.ts b/src/main/appBadge.ts new file mode 100644 index 0000000..2887498 --- /dev/null +++ b/src/main/appBadge.ts @@ -0,0 +1,50 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import { app, NativeImage, nativeImage } from "electron"; +import { join } from "path"; +import { BADGE_DIR } from "shared/paths"; + +const imgCache = new Map(); +function loadBadge(index: number) { + const cached = imgCache.get(index); + if (cached) return cached; + + const img = nativeImage.createFromPath(join(BADGE_DIR, `${index}.ico`)); + imgCache.set(index, img); + + return img; +} + +let lastIndex: null | number = -1; + +export function setBadgeCount(count: number) { + switch (process.platform) { + case "darwin": + case "linux": + if (count === -1) count = 0; + app.setBadgeCount(count); + break; + case "win32": + const [index, description] = getBadgeIndexAndDescription(count); + if (lastIndex === index) break; + + lastIndex = index; + + // circular import shenanigans + const { mainWin } = require("./mainWindow") as typeof import("./mainWindow"); + mainWin.setOverlayIcon(index === null ? null : loadBadge(index), description); + break; + } +} + +function getBadgeIndexAndDescription(count: number): [number | null, string] { + if (count === -1) return [11, "Unread Messages"]; + if (count === 0) return [null, "No Notifications"]; + + const index = Math.max(1, Math.min(count, 10)); + return [index, `${index} Notification`]; +} diff --git a/src/main/firstLaunch.ts b/src/main/firstLaunch.ts index e635fbd..f1b39dd 100644 --- a/src/main/firstLaunch.ts +++ b/src/main/firstLaunch.ts @@ -9,7 +9,7 @@ import { BrowserWindow } from "electron/main"; import { copyFileSync, mkdirSync, readdirSync } from "fs"; import { join } from "path"; import { SplashProps } from "shared/browserWinProperties"; -import { STATIC_DIR } from "shared/paths"; +import { VIEW_DIR } from "shared/paths"; import { autoStart } from "./autoStart"; import { DATA_DIR } from "./constants"; @@ -33,7 +33,7 @@ export function createFirstLaunchTour() { width: 550 }); - win.loadFile(join(STATIC_DIR, "first-launch.html")); + win.loadFile(join(VIEW_DIR, "first-launch.html")); win.webContents.addListener("console-message", (_e, _l, msg) => { if (msg === "cancel") return app.exit(); diff --git a/src/main/ipc.ts b/src/main/ipc.ts index 617cccf..138ad76 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -11,6 +11,7 @@ import { join } from "path"; import { debounce } from "shared/utils/debounce"; import { IpcEvents } from "../shared/IpcEvents"; +import { setBadgeCount } from "./appBadge"; import { autoStart } from "./autoStart"; import { VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE } from "./constants"; import { mainWin } from "./mainWindow"; @@ -89,6 +90,8 @@ ipcMain.handle(IpcEvents.SELECT_VENCORD_DIR, async () => { return dir; }); +ipcMain.handle(IpcEvents.SET_BADGE_COUNT, (_, count: number) => setBadgeCount(count)); + function readCss() { return readFile(VENCORD_QUICKCSS_FILE, "utf-8").catch(() => ""); } diff --git a/src/main/splash.ts b/src/main/splash.ts index b158a58..728c688 100644 --- a/src/main/splash.ts +++ b/src/main/splash.ts @@ -7,12 +7,12 @@ import { BrowserWindow } from "electron"; import { join } from "path"; import { SplashProps } from "shared/browserWinProperties"; -import { STATIC_DIR } from "shared/paths"; +import { VIEW_DIR } from "shared/paths"; export function createSplashWindow() { const splash = new BrowserWindow(SplashProps); - splash.loadFile(join(STATIC_DIR, "splash.html")); + splash.loadFile(join(VIEW_DIR, "splash.html")); return splash; } diff --git a/src/preload/VencordDesktopNative.ts b/src/preload/VencordDesktopNative.ts index 2e56324..d526fa8 100644 --- a/src/preload/VencordDesktopNative.ts +++ b/src/preload/VencordDesktopNative.ts @@ -13,7 +13,8 @@ import { invoke, sendSync } from "./typedIpcs"; export const VencordDesktopNative = { app: { relaunch: () => invoke(IpcEvents.RELAUNCH), - getVersion: () => sendSync(IpcEvents.GET_VERSION) + getVersion: () => sendSync(IpcEvents.GET_VERSION), + setBadgeCount: (count: number) => invoke(IpcEvents.SET_BADGE_COUNT, count) }, autostart: { isEnabled: () => sendSync(IpcEvents.AUTOSTART_ENABLED), diff --git a/src/renderer/appBadge.ts b/src/renderer/appBadge.ts new file mode 100644 index 0000000..ea40b60 --- /dev/null +++ b/src/renderer/appBadge.ts @@ -0,0 +1,43 @@ +/* + * SPDX-License-Identifier: GPL-3.0 + * Vencord Desktop, a desktop app aiming to give you a snappier Discord Experience + * Copyright (c) 2023 Vendicated and Vencord contributors + */ + +import { filters, waitFor } from "@vencord/types/webpack"; +import { RelationshipStore } from "@vencord/types/webpack/common"; + +import { Settings } from "./settings"; + +let GuildReadStateStore: any; +let NotificationSettingsStore: any; + +export function setBadge() { + if (Settings.store.appBadge === false) return; + + const mentionCount = GuildReadStateStore.getTotalMentionCount(); + const pendingRequests = RelationshipStore.getPendingCount(); + const hasUnread = GuildReadStateStore.hasAnyUnread(); + const disableUnreadBadge = NotificationSettingsStore.getDisableUnreadBadge(); + + let totalCount = mentionCount + pendingRequests; + if (!totalCount && hasUnread && !disableUnreadBadge) totalCount = -1; + + VencordDesktopNative.app.setBadgeCount(totalCount); +} + +let toFind = 3; + +function waitForAndSubscribeToStore(name: string, cb?: (m: any) => void) { + waitFor(filters.byStoreName(name), store => { + cb?.(store); + store.addChangeListener(setBadge); + + toFind--; + if (toFind === 0) setBadge(); + }); +} + +waitForAndSubscribeToStore("GuildReadStateStore", store => (GuildReadStateStore = store)); +waitForAndSubscribeToStore("NotificationSettingsStore", store => (NotificationSettingsStore = store)); +waitForAndSubscribeToStore("RelationshipStore"); diff --git a/src/renderer/components/Settings.tsx b/src/renderer/components/Settings.tsx index 1c43b79..bf915b0 100644 --- a/src/renderer/components/Settings.tsx +++ b/src/renderer/components/Settings.tsx @@ -8,6 +8,7 @@ import "./settings.css"; import { Margins } from "@vencord/types/utils"; import { Button, Forms, Select, Switch, Text, useState } from "@vencord/types/webpack/common"; +import { setBadge } from "renderer/appBadge"; import { useSettings } from "renderer/settings"; export default function SettingsUi() { @@ -72,6 +73,18 @@ export default function SettingsUi() { Start With System + { + Settings.appBadge = v; + if (v) setBadge(); + else VencordDesktopNative.app.setBadgeCount(0); + }} + note="Show mention badge on the app icon" + > + Notification Badge + + {switches.map(([key, text, note, def, predicate]) => ( *S$Y5b$Faxm^Ap8{q3=H#F7#Iu;pnO#Z1~*X#1`P%V29Oqz zGDZdv$-v;i0#bvD|NsBbNKG6S^+h}?>T`2c)aUb2QJ+6UF^Js^lEY_LboA%osHo2$ zqoO|l$ALeB)L=6MBpwy@`7aKA$mab8sYNyeen-|1Vt)kbftdmI zFGw5(c_jUya7NJ!3I_uEKT}aZhWle;KL00RKeGEl=>^68 zk01Z}fA;KeQ1Ji968<2yNZ|)gb13Pir{~-M8#n&o(vK2f)Eoxs0qG^z9SI5lm}6qT7)C{XK1pQ$Lw5_P%s&Y- z17sGd?ud!`;u#h7`63biMYk87e-UIBvG#-93Q`{x_4y|i?1s7JC&)~Y*@WBy3NI@8 z8)i3*28DwmKKnuG1sdNlJ$UIUQ@(@CaS(Ch#BaQ6p<#IvWCt!cfYK}}X^jl~|AOqm zWZQ_+2dY<>kUi9vkBj>*9~JdwVRZBt&{z_v z?MOC;nDJ#H$V_Ux6WzRqhX0^3yUwVnFVq}E0{cBW`pfsIs4tx$JJ9W=20tSL2e?}51_h5QQQ3>cYxf8%MYNo zIY&ySRIMlk27U>7%MwolC(V%fLWOotE2Due9 zZ@FW~&;Jz_U%_PnNDQU(_5VLuoLDo_)q&iG&CSSSpf)PHK4SPMPa@_VL2kZx@6Z2R zw;*$}AU+HeV-_woAh#jA6&oAWz613YaG8Ni{J{fEx5C_vOykl|NF3xQklV1i8C?w2 zS0iK|y8NO=KmNaa_ZQizSlQ_Mi06MKk)P^Zhw$! zCP+QVEg(1HaxXS4{Q(AiF_s0J()+45}}v-7Y24Ulfnu!u$;K11Kzrw3nhf3S8>L;*n1I zf$H-YF#kjHG-zCR=*=I&`~adsWihCZ1J#M3_@)Fy%%IQw9mws-7*wBw+9aTM6{&sz z>4EB{`}`@gA7E^VU%pm@`aqyQ5@?(NT5f^H1mN@6(a~TvgTl=)w~x|8Z@mPy;taAP V2(%{(#2TeRp#a$*24c}ZJOG~U-9G>T literal 0 HcmV?d00001 diff --git a/static/badges/10.ico b/static/badges/10.ico new file mode 100644 index 0000000000000000000000000000000000000000..1e02de381e4694340f25fdb90e603e3ae7974252 GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/static/badges/2.ico b/static/badges/2.ico new file mode 100644 index 0000000000000000000000000000000000000000..d7b6f4419574b303d7ea6f9adf373d23460d8b28 GIT binary patch literal 15086 zcmZQzU}Rus5D;KsU|>*S$Y5b$Faxm^Ap8{q3=H#F7#Iu;pnO#Z1~*X#1`P%V29Oqz zGDZdv$-v;i0#bvD|NsBbNKG6S^+h}?>T`2c)aUb2QJ+6UF^Js^lEY_LboA%osHo2$ zqoO|l$ALeB)L=6MBpwy@`7aKA$mab8sYNye|vjv@|{gW~f@`a$80p>Dx~ z@Bjb(`}cqPbgX84CZr!^&$ewp|Ns2??|)X-7j*NH^`p2yApsG8)zx3YK{;UpO89}y zLUunWy@15P_~gmo|99^E`G4xv@BdGq{teb&Q}Y!p2XYe>BZVJ0&B4=6PtUjickcZ8 z|LfPk|L@=b{l93@4|KgK@dpYAP?{h&{ebj?Fw_jVJD~1Fwi{>q1?dN2P`ZMqCs3Gz z;uVBJY=Zd*q@PsG!0`V+B^XrBfJzq!22eQ#Vlgl@fC?VeVupcKca2o_(a~R|qocn# zM@4;Zjf(obJ1Xk)ZD`p9N>?B@NURm42Bel+;S?MDojoe*i+@zq=fhD^pI>81yU6Jn z#0IH34AKMAORhT-685VsFB0Kj zWIM63FM`Y>)_#y%LF%KTKL4bG-7xq31epmkn~*y|;YB5X!|aC9pl~q6XFn*tK;s*x z2Tp?vdm@NKhkn8JUtV-a;M7XO3HJ`A!8-3_2}17H3InG33`fB%NGfk5@= zv}st|4<5*f z=;|=|pzsE@KR|YaB7@9u*onn{P#KP4ACj9<{h)dT z#SSz*C~}}M2eoHG?MP5Kyn6Nbe{(ZNTMR`Hl6fB~wI62IiWNWp|M&q(lP_NU{hyRX zR9e7hKS|*avp*x_^Z!eiAZ<}lIDp~-CWnW{7XCz~KWt{sne!cFH5eZ_@Do>isWdHw;HM+He5fxu9_h&=6??@;HSmrZa|P*pK>&x?|k* z2+z2hn$LSUPAt@FqwMBnMIhQcDjv5wasX`ipLK^q2nV z=r8xNwIA_`f%HK2>JqYt+VXL6-{qsCzATK6{sJ0HLT*Qq%!ZipWg*B+YP%ENyoQGV zpfS77sHiX0976*8IXe2w_o%2Zogh2V?WG1kG4a1BzIHgiv_hiXVUS(aa5KydP=1S! z{_>DScYwo{96cbrKz73Hr-TNX11(3$b`Lpz0NDw$n-aH!;t>=UWZF-$e?fMG+(3>W zK>3JH>79^24};u7svn}GzjP7`cl5q0Dg1BW{tCNpUZ_T2kB( zDqBHrBGwO}x`|NOgXBMdhK!G)yNwt=Deec^1#%NH?uWJsh^kkss=ogJ@&(lopmFH_ ze#n>uXxsrGhPaF1*aSEof$C|H+X(pq)FvUtT+lrA*RQC40F5Pq#!W~uhZwaWw-Mof zlG|c+bzlF3(gSk3p@knnZ9aVN2gMID;ebs|W8>HV-@ns79zbryDz( z23~tX%Xo;6{#uR8{gD0zarp_CpW51J>j#h<@wgw=@ql1UStFxe-0x!1$oDi5Bh$nF(?) z%SW9LR0h+>9&+YNKM)i%l#y_X|pT0L{IE=7S3gAoIYWHK?FE;K>un zdI-4U|Np`3M6sEPPYmQXWVd2tgW7kXz5+gTU~(-j-;kX|5*wr!W)3kl$W0)(VRJLO z7^tsCjG3VR7ifN&B!~b1|DTAtc$72`am$y5=_1M}zq_z%iA#F!0J19A(sDG)+OwpwIjr$nD4&RG)*|B%pQ`sr~@zf$F9E{3)^@ zU~GtAzE*?!7oa{8bSwi@Zhi3XuI_ JAQtVz0|2b2R{Q_} literal 0 HcmV?d00001 diff --git a/static/badges/3.ico b/static/badges/3.ico new file mode 100644 index 0000000000000000000000000000000000000000..43ce7cf299065c0ea4a17f8a7bc9a6a25e431796 GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/static/badges/5.ico b/static/badges/5.ico new file mode 100644 index 0000000000000000000000000000000000000000..1d6bf8f22a5ba34b05ab4da181a1d4445fe0c66e GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/static/badges/6.ico b/static/badges/6.ico new file mode 100644 index 0000000000000000000000000000000000000000..d0c0cd63df611a0d5a3327c15304a63cf7e198b7 GIT binary patch literal 15086 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 D*FH{f literal 0 HcmV?d00001 diff --git a/static/badges/7.ico b/static/badges/7.ico new file mode 100644 index 0000000000000000000000000000000000000000..b50750c267a29ff9a18fe175afd4b0497afa7f29 GIT binary patch literal 15086 zcmZQzU}Rus5D;KsU|>*S$Y5b$Faxm^Ap8{q3=H#F7#Iu;pnO#Z1~*X#1`P%V29Oqz zGDZdv$-v;i0#bvD|NsBbNKG6S^+h}?>T`2c)aUb2QJ+6UF^Js^lEY_LboA%osHo2$ zqoO|l$ALeB)L=6MBpwy@`7g4*m>8_)`~|5+HUs1?bbGgM{rUgFgFiUk0n!6A1L|KC zwN+JL|Nr~d|!4k%5aryr<2 z$ofERjPwK255iD0;O@YpA7}an=?7tuyFh*;C;x!-lZqJ_{{N>0gUT6D>EgfuDyKj! z28ISu!Gl`NFp%o5k*YpA`ipdQ^cUx-sL!oYQJ;55MSZ>vEt^2;3d9D9wSv@u)KV*) zVq?FvM@4<{kBa(yI4bJ%YbA{ejIrBTndN5wM z?gxfEl7G?VK2pQ}*x1kiU%Y_iMNoURtc>U|z-B*5;SclMs#QP0X#i9nf!dWYaRM~9 z@Fyw#!OSl%{__9fLr7Z~R4yeX5S15qV+nsyy8=C)2=YO3ux%TnJnHEosyxETf1ok} zU-^@f@%jJKrQiQ=+42(uA3gdDoCZO}xpTk&Cnezx1FYo_s7%CH{?^nW%6*VMxbTe| zfBt7>;Z28F%U@7@fa(TZ^$)1txp?vSe~|h3@UC4y|AWc~So%Ptan?T|`$2UhuKE{L z--G-`2!rg#QzzoBe?e{_w*7(TFM{b5)TRNM4YC6t2DOnuZKZ)~f5F@abpzeopD_EO z;V@wBZbD(W4MO@sK2N?&Q0s^jEnoC9~JerHahyt(&*?f`=g>h-vo`>Lh((I7)TDJ2BenO z?jgqf=;$xH(a~S}qocpvC$-)N>4ECiCB`mls)>vHE*};3Wnpym7tmM|F>MT-Y9MBO zSqL(dnr_5qRzt&o(3o9kRMZ!0jv;~l79IWNdsNhyPLLhg?50#KG4a1BzIHgN=?9Pc z!yvmTbuY4hP=1S!{_+ryo!~H}mORKVke$eGAeRj?2U>^)twBa@`Hm2Z~2f zSP)?sP5cJ38{`I%TS&#Ad_-<~2lc)4^6>UGN%8MtkXuM~e{}ShPEx`>KmQAO-tgYN zKmS2vCZI92loY)EbrSsWrIQr*gUVu3%Scc^_`?Utm=kOaVA(Q~#=da+2UNC#+(fJ& zKy?!-VGmQgdi4*O)4}wcH-Gjk-u2=|lR7DKiJG~WF8?>~^!;kdb( zsIfn+;f`!JsLhAZ{h;_kR!=S)HirQ7z}d4n*HjR6GrAi|`Jvsb_hOaQE zgK5yZlAeM+Ltd;>od@t1|@EX>b;4_{aDu} zLG_XBuLTQG>$CUosZyVPrkDE@6F>j|@&&aloiT&r`V61@L1P9ahcmwT*{}gI2L#Fo zpgAdg>WPrUnSMZdg9!a3`42R&0cwwe+z!K_^L}A zFCe!Oi%DG{0&*KZw}a$B?K@CkfmlDBIt5v;LadvS)sfxF6&uLhgpigZj##J~J_K(9!YjKWJ?NIT*_tWvuBR7|}uuWEaRznElkCLGehZ{6O{j3z+{Qc^WjXJM`v{V15A6pt2ZLpMdH_ zO4AR-4EoI9f!vOaLG?MPO#*6Hk?IeS9;jZr&z~au0mg>-Gst@Bjcd6X?7E literal 0 HcmV?d00001 diff --git a/static/badges/8.ico b/static/badges/8.ico new file mode 100644 index 0000000000000000000000000000000000000000..8d0ca36cfb85fb8b2d9841a47947fe2c453d5116 GIT binary patch literal 15086 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 literal 0 HcmV?d00001 diff --git a/static/about.html b/static/views/about.html similarity index 100% rename from static/about.html rename to static/views/about.html diff --git a/static/first-launch.html b/static/views/first-launch.html similarity index 100% rename from static/first-launch.html rename to static/views/first-launch.html diff --git a/static/splash.html b/static/views/splash.html similarity index 100% rename from static/splash.html rename to static/views/splash.html diff --git a/static/updater.html b/static/views/updater.html similarity index 100% rename from static/updater.html rename to static/views/updater.html