From c725352bef0dd85f110956593e8a5a79a540d900 Mon Sep 17 00:00:00 2001 From: Oleh Polisan Date: Fri, 21 Jun 2024 16:02:39 +0300 Subject: [PATCH] feat: notification badge at tray --- src/main/appBadge.ts | 17 +++++--- src/main/ipc.ts | 13 +++++- src/main/mainWindow.ts | 48 ++-------------------- src/main/tray.ts | 75 ++++++++++++++++++++++++++++++++--- src/preload/VesktopNative.ts | 8 +++- src/renderer/patches/tray.ts | 30 ++++++++++++++ src/shared/IpcEvents.ts | 4 +- static/badges/1.ico | Bin 15086 -> 0 bytes static/badges/1.png | Bin 0 -> 1073 bytes static/badges/10.ico | Bin 15086 -> 0 bytes static/badges/10.png | Bin 0 -> 1641 bytes static/badges/11.ico | Bin 15086 -> 0 bytes static/badges/11.png | Bin 0 -> 1243 bytes static/badges/2.ico | Bin 15086 -> 0 bytes static/badges/2.png | Bin 0 -> 1487 bytes static/badges/3.ico | Bin 15086 -> 0 bytes static/badges/3.png | Bin 0 -> 1593 bytes static/badges/4.ico | Bin 15086 -> 0 bytes static/badges/4.png | Bin 0 -> 1272 bytes static/badges/5.ico | Bin 15086 -> 0 bytes static/badges/5.png | Bin 0 -> 1471 bytes static/badges/6.ico | Bin 15086 -> 0 bytes static/badges/6.png | Bin 0 -> 1631 bytes static/badges/7.ico | Bin 15086 -> 0 bytes static/badges/7.png | Bin 0 -> 1306 bytes static/badges/8.ico | Bin 15086 -> 0 bytes static/badges/8.png | Bin 0 -> 1724 bytes static/badges/9.ico | Bin 15086 -> 0 bytes static/badges/9.png | Bin 0 -> 1600 bytes 29 files changed, 137 insertions(+), 58 deletions(-) delete mode 100644 static/badges/1.ico create mode 100644 static/badges/1.png delete mode 100644 static/badges/10.ico create mode 100644 static/badges/10.png delete mode 100644 static/badges/11.ico create mode 100644 static/badges/11.png delete mode 100644 static/badges/2.ico create mode 100644 static/badges/2.png delete mode 100644 static/badges/3.ico create mode 100644 static/badges/3.png delete mode 100644 static/badges/4.ico create mode 100644 static/badges/4.png delete mode 100644 static/badges/5.ico create mode 100644 static/badges/5.png delete mode 100644 static/badges/6.ico create mode 100644 static/badges/6.png delete mode 100644 static/badges/7.ico create mode 100644 static/badges/7.png delete mode 100644 static/badges/8.ico create mode 100644 static/badges/8.png delete mode 100644 static/badges/9.ico create mode 100644 static/badges/9.png diff --git a/src/main/appBadge.ts b/src/main/appBadge.ts index 46abe1d..4b32fe9 100644 --- a/src/main/appBadge.ts +++ b/src/main/appBadge.ts @@ -6,22 +6,27 @@ import { app, NativeImage, nativeImage } from "electron"; import { join } from "path"; +import { IpcEvents } from "shared/IpcEvents"; import { BADGE_DIR } from "shared/paths"; +import { mainWin } from "./mainWindow"; + const imgCache = new Map(); -function loadBadge(index: number) { +export function loadBadge(index: number) { const cached = imgCache.get(index); if (cached) return cached; - const img = nativeImage.createFromPath(join(BADGE_DIR, `${index}.ico`)); + const img = nativeImage.createFromPath(join(BADGE_DIR, `${index}.png`)); imgCache.set(index, img); return img; } -let lastIndex: null | number = -1; +let lastBadgeIndex: null | number = -1; +export var lastBadgeCount: number = -1; export function setBadgeCount(count: number) { + lastBadgeCount = count; switch (process.platform) { case "linux": if (count === -1) count = 0; @@ -36,15 +41,17 @@ export function setBadgeCount(count: number) { break; case "win32": const [index, description] = getBadgeIndexAndDescription(count); - if (lastIndex === index) break; + if (lastBadgeIndex === index) break; - lastIndex = index; + lastBadgeIndex = index; // circular import shenanigans const { mainWin } = require("./mainWindow") as typeof import("./mainWindow"); mainWin.setOverlayIcon(index === null ? null : loadBadge(index), description); break; } + + mainWin.webContents.send(IpcEvents.SET_CURRENT_VOICE_TRAY_ICON); } function getBadgeIndexAndDescription(count: number): [number | null, string] { diff --git a/src/main/ipc.ts b/src/main/ipc.ts index bfe9208..126895a 100644 --- a/src/main/ipc.ts +++ b/src/main/ipc.ts @@ -28,9 +28,17 @@ import { IpcEvents } from "../shared/IpcEvents"; import { setBadgeCount } from "./appBadge"; import { autoStart } from "./autoStart"; import { VENCORD_FILES_DIR, VENCORD_QUICKCSS_FILE, VENCORD_THEMES_DIR } from "./constants"; -import { mainWin, setTrayIcon } from "./mainWindow"; +import { mainWin } from "./mainWindow"; import { Settings } from "./settings"; -import { createTrayIcon, generateTrayIcons, getTrayIconFile, getTrayIconFileSync, pickTrayIcon } from "./tray"; +import { + createTrayIcon, + generateTrayIcons, + getIconWithBadge, + getTrayIconFile, + getTrayIconFileSync, + pickTrayIcon, + setTrayIcon +} from "./tray"; import { handle, handleSync } from "./utils/ipcWrappers"; import { PopoutWindows } from "./utils/popout"; import { isDeckGameMode, showGamePage } from "./utils/steamOS"; @@ -170,3 +178,4 @@ handle(IpcEvents.CREATE_TRAY_ICON_RESPONSE, (_, iconName, dataURL, isCustomIcon) ); handle(IpcEvents.GENERATE_TRAY_ICONS, () => generateTrayIcons()); handle(IpcEvents.SELECT_TRAY_ICON, async (_, iconName) => pickTrayIcon(iconName)); +handle(IpcEvents.GET_ICON_WITH_BADGE, async (_, dataURL) => getIconWithBadge(dataURL)); diff --git a/src/main/mainWindow.ts b/src/main/mainWindow.ts index cd60521..f27cf9b 100755 --- a/src/main/mainWindow.ts +++ b/src/main/mainWindow.ts @@ -11,8 +11,6 @@ import { dialog, Menu, MenuItemConstructorOptions, - NativeImage, - nativeImage, nativeTheme, screen, session, @@ -21,7 +19,7 @@ import { import { rm } from "fs/promises"; import { join } from "path"; import { IpcEvents } from "shared/IpcEvents"; -import { ICON_PATH, ICONS_DIR } from "shared/paths"; +import { ICON_PATH } from "shared/paths"; import { isTruthy } from "shared/utils/guards"; import { once } from "shared/utils/once"; import type { SettingsStore } from "shared/utils/SettingsStore"; @@ -40,13 +38,13 @@ import { } from "./constants"; import { Settings, State, VencordSettings } from "./settings"; import { createSplashWindow } from "./splash"; -import { generateTrayIcons, isCustomIcon, statusToSettingsKey } from "./tray"; +import { setTrayIcon } from "./tray"; import { makeLinksOpenExternally } from "./utils/makeLinksOpenExternally"; import { applyDeckKeyboardFix, askToApplySteamLayout, isDeckGameMode } from "./utils/steamOS"; import { downloadVencordFiles, ensureVencordFiles } from "./utils/vencordLoader"; let isQuitting = false; -let tray: Tray; +export let tray: Tray; applyDeckKeyboardFix(); @@ -127,14 +125,7 @@ function initTray(win: BrowserWindow) { ]); tray = new Tray(ICON_PATH); - try { - if (Settings.store.trayMainOverride) tray.setImage(join(ICONS_DIR, "icon_custom.png")); - else tray.setImage(join(ICONS_DIR, "icon.png")); - } catch (error) { - console.log("Error while loading custom tray image. Recreating new ones."); - Settings.store.trayMainOverride = false; - generateTrayIcons(); - } + setTrayIcon("icon"); tray.setToolTip("Vesktop"); tray.setContextMenu(trayMenu); tray.on("click", onTrayClick); @@ -512,34 +503,3 @@ export async function createWindows() { initArRPC(); } - -export async function setTrayIcon(iconName: string) { - if (!tray || tray.isDestroyed()) return; - const Icons = new Set(["speaking", "muted", "deafened", "idle", "icon"]); - - if (!Icons.has(iconName)) return; - try { - var trayImage: NativeImage; - if (isCustomIcon(iconName)) { - trayImage = nativeImage.createFromPath(join(ICONS_DIR, iconName + "_custom.png")); - if (trayImage.isEmpty()) { - const iconKey = statusToSettingsKey[iconName as keyof typeof statusToSettingsKey]; - Settings.store[iconKey] = false; - generateTrayIcons(); - return; - } - } else trayImage = nativeImage.createFromPath(join(ICONS_DIR, iconName + ".png")); - if (trayImage.isEmpty()) { - generateTrayIcons(); - return; - } - if (process.platform === "darwin") { - trayImage = trayImage.resize({ width: 16, height: 16 }); - } - tray.setImage(trayImage); - } catch (error) { - console.log("Error: ", error, "Regenerating tray icons."); - generateTrayIcons(); // TODO: pass here only one icon request - } - return; -} diff --git a/src/main/tray.ts b/src/main/tray.ts index 0525ec3..cdec95d 100644 --- a/src/main/tray.ts +++ b/src/main/tray.ts @@ -5,13 +5,14 @@ */ import { dialog, NativeImage, nativeImage } from "electron"; -import { copyFileSync, mkdirSync, writeFileSync } from "fs"; +import { mkdirSync, writeFileSync } from "fs"; import { readFile } from "fs/promises"; import { join } from "path"; import { IpcEvents } from "shared/IpcEvents"; import { ICONS_DIR, STATIC_DIR } from "shared/paths"; -import { mainWin } from "./mainWindow"; +import { lastBadgeCount, loadBadge } from "./appBadge"; +import { mainWin, tray } from "./mainWindow"; import { Settings } from "./settings"; export const statusToSettingsKey = { @@ -27,6 +28,62 @@ export const isCustomIcon = (status: string) => { return Settings.store[settingKey]; }; +export async function setTrayIcon(iconName: string) { + if (!tray || tray.isDestroyed()) return; + const Icons = new Set(["speaking", "muted", "deafened", "idle", "icon"]); + if (!Icons.has(iconName)) return; + + // if need to set main icon then check whether there is need of notif badge + if (iconName === "icon" && lastBadgeCount && lastBadgeCount > 0) { + var trayImage: NativeImage; + if (isCustomIcon("icon")) { + console.log("setting badge and CUSTOM icon"); + trayImage = nativeImage.createFromPath(join(ICONS_DIR, "icon_custom.png")); + } else { + console.log("setting badge and stock icon"); + trayImage = nativeImage.createFromPath(join(ICONS_DIR, "icon.png")); + } + + const badgeImg = loadBadge(lastBadgeCount); + // and send IPC call to renderer to add to image + mainWin.webContents.send(IpcEvents.ADD_BADGE_TO_ICON, trayImage.toDataURL(), badgeImg.toDataURL()); + return; + } + + try { + var trayImage: NativeImage; + if (isCustomIcon(iconName)) { + trayImage = nativeImage.createFromPath(join(ICONS_DIR, iconName + "_custom.png")); + if (trayImage.isEmpty()) { + const iconKey = statusToSettingsKey[iconName as keyof typeof statusToSettingsKey]; + Settings.store[iconKey] = false; + generateTrayIcons(); + return; + } + } else trayImage = nativeImage.createFromPath(join(ICONS_DIR, iconName + ".png")); + if (trayImage.isEmpty()) { + generateTrayIcons(); + return; + } + if (process.platform === "darwin") { + trayImage = trayImage.resize({ width: 16, height: 16 }); + } + tray.setImage(trayImage); + } catch (error) { + console.log("Error: ", error, "Regenerating tray icons."); + generateTrayIcons(); // TODO: pass here only one icon request + } + return; +} + +export async function setTrayIconWithBadge(iconDataURL: string) { + var trayImage = nativeImage.createFromDataURL(iconDataURL); + if (process.platform === "darwin") { + trayImage = trayImage.resize({ width: 16, height: 16 }); + } + tray.setImage(trayImage); +} + export async function getTrayIconFile(iconName: string) { const Icons = new Set(["speaking", "muted", "deafened", "idle"]); if (!Icons.has(iconName)) { @@ -62,7 +119,9 @@ export async function createTrayIcon(iconName: string, iconDataURL: string, isCu // primarily called from renderer using CREATE_TRAY_ICON_RESPONSE IPC call iconDataURL = iconDataURL.replace(/^data:image\/png;base64,/, ""); if (isCustomIcon) { - writeFileSync(join(ICONS_DIR, iconName + "_custom.png"), iconDataURL, "base64"); + const img = nativeImage.createFromDataURL(iconDataURL).resize({ width: 128, height: 128 }); + // writeFileSync(join(ICONS_DIR, iconName + "_custom.png"), img.toDataURL(), "base64"); + writeFileSync(join(ICONS_DIR, iconName + "_custom.png"), img.toPNG()); } else { writeFileSync(join(ICONS_DIR, iconName + ".png"), iconDataURL, "base64"); } @@ -76,7 +135,8 @@ export async function generateTrayIcons() { for (const icon of Icons) { mainWin.webContents.send(IpcEvents.CREATE_TRAY_ICON_REQUEST, icon); } - copyFileSync(join(STATIC_DIR, "icon.png"), join(ICONS_DIR, "icon.png")); + const img = nativeImage.createFromPath(join(STATIC_DIR, "icon.png")).resize({ width: 128, height: 128 }); + writeFileSync(join(ICONS_DIR, "icon.png"), img.toPNG()); mainWin.webContents.send(IpcEvents.SET_CURRENT_VOICE_TRAY_ICON); } @@ -93,6 +153,11 @@ export async function pickTrayIcon(iconName: string) { // add .svg !! const image = nativeImage.createFromPath(dir); if (image.isEmpty()) return "invalid"; - copyFileSync(dir, join(ICONS_DIR, iconName + "_custom.png")); + const img = nativeImage.createFromPath(dir).resize({ width: 128, height: 128 }); + writeFileSync(join(ICONS_DIR, iconName + "_custom.png"), img.toPNG()); return dir; } + +export async function getIconWithBadge(dataURL: string) { + tray.setImage(nativeImage.createFromDataURL(dataURL)); +} diff --git a/src/preload/VesktopNative.ts b/src/preload/VesktopNative.ts index 6ee5671..c2138bc 100644 --- a/src/preload/VesktopNative.ts +++ b/src/preload/VesktopNative.ts @@ -94,6 +94,12 @@ export const VesktopNative = { generateTrayIcons: () => invoke(IpcEvents.GENERATE_TRAY_ICONS), setCurrentVoiceIcon: (listener: (...args: any[]) => void) => { ipcRenderer.on(IpcEvents.SET_CURRENT_VOICE_TRAY_ICON, listener); - } + }, + addBadgeToIcon: (listener: (iconDataURL: string, badgeDataURL: string) => void) => { + ipcRenderer.on(IpcEvents.ADD_BADGE_TO_ICON, (_, iconDataURL: string, badgeDataURL: string) => + listener(iconDataURL, badgeDataURL) + ); + }, + returnIconWithBadge: (dataURL: string) => invoke(IpcEvents.GET_ICON_WITH_BADGE, dataURL) } }; diff --git a/src/renderer/patches/tray.ts b/src/renderer/patches/tray.ts index 3b38964..221264f 100644 --- a/src/renderer/patches/tray.ts +++ b/src/renderer/patches/tray.ts @@ -58,6 +58,36 @@ VesktopNative.tray.createIconRequest(async (iconName: string) => { } }); +VesktopNative.tray.addBadgeToIcon(async (iconDataURL: string, badgeDataURL: string) => { + const canvas = document.createElement("canvas"); + canvas.width = 128; + canvas.height = 128; + + const img = new Image(); + img.width = 128; + img.height = 128; + + img.onload = () => { + const ctx = canvas.getContext("2d"); + if (ctx) { + ctx.drawImage(img, 0, 0); + + const iconImg = new Image(); + iconImg.width = 64; + iconImg.height = 64; + + iconImg.onload = () => { + ctx.drawImage(iconImg, 64, 0, 64, 64); + VesktopNative.tray.returnIconWithBadge(canvas.toDataURL()); + }; + + iconImg.src = badgeDataURL; + } + }; + + img.src = iconDataURL; +}); + VesktopNative.tray.setCurrentVoiceIcon(() => { setCurrentTrayIcon(); }); diff --git a/src/shared/IpcEvents.ts b/src/shared/IpcEvents.ts index 425c959..96eda30 100644 --- a/src/shared/IpcEvents.ts +++ b/src/shared/IpcEvents.ts @@ -59,5 +59,7 @@ export const enum IpcEvents { GENERATE_TRAY_ICONS = "VCD_GENERATE_TRAY_ICONS", SET_CURRENT_VOICE_TRAY_ICON = "VCD_SET_CURRENT_VOICE_ICON", GET_SYSTEM_ACCENT_COLOR = "VCD_GET_ACCENT_COLOR", - SELECT_TRAY_ICON = "VCD_SELECT_TRAY_ICON" + SELECT_TRAY_ICON = "VCD_SELECT_TRAY_ICON", + ADD_BADGE_TO_ICON = "VCD_ADD_BADGE_TO_ICON", + GET_ICON_WITH_BADGE = "VCD_GET_ICON_WITH_BADGE" } diff --git a/static/badges/1.ico b/static/badges/1.ico deleted file mode 100644 index 0e2003fdc4551b838cbdc78673d127716aa3caa8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmeHO&ubJ(6z;)=y?PN3d)Qory@-18EG#VSDF<&e$q+pS{{aPA2uKcsB7%5O5F!YB z@Z?GHkV7ucA&TO`s2CT?Nf1K!*bbAV_WQcKGCkGR-PJucJ<~A_FZH8ez4yIWRj+>Z z#BmzV5$EVp2hWVN_>1G5Wo{-c|BLzus5^Z+DxYwizm7T1A1JcP45$(Ob)0kHQy(Ej z!zMMG-tlJBy#{&(awB3Mb>8tTU9FaT9(>y%kwV+#(aDI~?xwVh%iC3DM3@tLFJJCL zl@PaY`|1XC`wY=Xze`4G$gPwyvfH7RSQE-jTUE?+j#hKqm29#lS& z-pH4otT7plbK|jALO*1Cvp}5KTXD_;Bj=cj9RW`X{cN|Uiw}$&cxN)d_wkj~|CPE_ zA3!(b+P-X)d`bP(v8>V0_*s?yXBz#C;Z^DXpwZ8Dq$>T}Q>cH^{;zWUJ=gf(X#QQi zI2a=~=bvf(dHJ$0K7QO0_wM=P@#7ybBYX_wKgYK={xBxuU2go{+6vDO{r;YC-94#Z z6wt4YzYx?gS%2=|_r;qxebMU;bQ6T3{?zq{`c2p0#YI=#z3Yp&Z^Ls~0sWclFELDV z|3Uqe-hUB8iJ%I}s>pZ3I+E8V~cw(%32^mSSao>KegPG|7V5wgXnPdnoM`|z7A%knYxhmMcf zASd%237%5tm(QP*SS99os>5Yc2V6$y7ur|m{P^(U5Ap5WZXBvMZ-Q0NV|IQdex8+K zFYY6U=VM-Ze%=j!Kd`lxZbzOB-Fspwa(<@`Xfx9N$<3SJ#l}W*OzH6D*A=@zA^y7G zU(tp--yae`sm}MeaT_onYI%PyZQxkKJgepR3u!|*r|bFsNZPqKL7v# diff --git a/static/badges/1.png b/static/badges/1.png new file mode 100644 index 0000000000000000000000000000000000000000..da9c163febd0863dda99d98d94a7d4c375d8b134 GIT binary patch literal 1073 zcmV-11kU@3P)Ee(Vn)s&A9p?>i)1*z(w7&g( zL{+)U3|E}tinE!J$nzEimK1&g@~WB#@_g46ktWa-_@uDugkhZtusMgw^A>;-u&kVs#_<{=o~jzgpsI7gBN2HRt*nHWZI^RF zu*-;SMzOk@jT((L;E_TGRnALQ4e)!n+x;zCS$XNWZkbA@&5#VkDwSqhjmA5LrwSP+ zOjUCVPg{+~J4&S)hGZB*8>)A<MTEqs?N6B?KiBhW*NX{ zfM|Pr4Ja}u>*h@|i;GyUOHylPg%K5_Mq|x^XY^s{{p<8$(?>Us*A#M$;M%==Tw7ekOiwdus+#M@@fzUM!_Xu0yahx&Mr7Z< zjhUY2!iad0=Pl5~a8gNC4I|S1eUiFgzR=y?W>Qqu03~|ZoV3gsj`sJ_R*P>RJ`lfu z&(Yo;X_eoYb#38MO$loR+wf+0agHb^;zO%em(RX+916)=wUdiDk4XujEEcoReBhDIAK^vH6(3RLnjRD^f2^c*>+i=LrRFqp=H}; z`Y`m73xZul{vs_@U*>{fmp*I;aOUUBtw!Tlpvagy>+5vZ*Ey#x$92mLU>KxQX-{Rd z_eErnA4EjK1ZIP(31#PO1f+yL^bng{ZH*A$T^&=l3rYTKJm r5Y(6en+b7(pa#^qWQHrwaK-%tH8+7;zmB%A00000NkvXXu0mjfXlD3} literal 0 HcmV?d00001 diff --git a/static/badges/10.ico b/static/badges/10.ico deleted file mode 100644 index 1e02de381e4694340f25fdb90e603e3ae7974252..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 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 literal 0 HcmV?d00001 diff --git a/static/badges/11.ico b/static/badges/11.ico deleted file mode 100644 index 7ebd2edb1908cc9dc72f17adfadea813a65ba2ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmeI3zi-q?6vrKL5-km)xZ={BbPYOau0}fPB&rm2yRZr!5;WB4q@dFlRQv~^6iECB z2qBarRjLyW5=s$WL6s`9mnGqnx$np8S)9SY#`dmbE+ai`&%7Vs_vX#>cs2yVN^l{# zbSY3<4etFA1ix{&I(vSp{%7jDb}f1SISBr^90b4U5s_8VO8jpS+z_AJj4>;1(qIr> z84SX|M1PCIgt%8F&;dMIIuhCA9J#cFlxyWu>o_q0r^+nJ4 zJLegVLi6g?p$Ws2n7F4e&4Y~fL-)jIJ`TUz=u7h;laeRS^KtCDjlMLG?!y-4o8oU6 zzc}Y=&mVDUl0P<%iH;&1x%q2#G+94ZhtD+#jA=sDnN`sZk*zZuajjBEs`+60Kl2WU z(T}3vwLZt9H=(6y;=+=XG+eDo*K+*0N&2npNCcV}-gNJc!Km=bz2)?!RU- zIf;pT`WP#d$3|9tpl)caaDCsuADZ{?znG(=Z}$=OF$PZwhJ9?gF^~*(Ems!b&|lWz zsSt;8hJEU1u6^R0<+qCm9(ap%Y3y}|eQJ2F9CKW?!CRzDW4jsld5`4Ek!w{OyhXY+ zc5nvmcOCy_=HHu)_;d0eKdgOwr9LDziaPmP#QTDGCd55`t$%-6``_y|brjIaE$0**k*t<|OEd)d5h*ICo@U3JEc*CC-e60k@@)X*i5Gy~HV|D!l6WGdp5YN*( zHXc6Y9J~B17an-)*Z^Av{CmE-A3vU$D5`!A3@HDI3&1XF}ZN6(7j0O0&eDG6Knl^O! z*cAS)Jp9tbH(zCa)WxO^9X>X}Sb+c3-zAmlrM@?9=qR(}jL-iL%JoBheaGMH{9$c4 zb5%IEXKnrVy?*xL{RKvM-P-5mTemQ0-27Vh{-NxfSUI%kVk~<;EBiO*LHPT=fA017 z3v?St*kuKd1Upy&?0%k;`9BUtb^X3pMbyb=U4d9=kr7GLw!EKP5YoV)XVd8 z>jSx@8q>?)FRTx{IPxzgs b3P)w9rIyg9$&LSOdG4zFiYiSXB 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 V!9VHy$Gs1P|A|6cc+RySz5%SKR{Q_} diff --git a/static/badges/2.png b/static/badges/2.png new file mode 100644 index 0000000000000000000000000000000000000000..59581988a9261c6c455a739bbe947156aea7b554 GIT binary patch literal 1487 zcmV;=1u*)FP)aMVS|=UL4F*86vwh^Buvf zbHzW?OG}F$95aZA9Yg{zW=Ey;Chl19GSLzkH5<6>5Rsvqke4QJ-#3q<1m1Pc@~3IF zpO2_2`%GwgE~1L9}1#{^~+jsR&@O#^BERTYscP!+hYu;LVpB?iD^2mEaI7?1-_ zsp^E%Rz_7b{7w1CM}9VY3s?pUPO(^`PZoWsyYAyr7%m}_RaHYDRCNM4FCyps+1X;k zvgT8sSD{B1y;xkd{c?E;IIoaIm7P*m1H2JM(P@8n_H!qbnP*|4L6;2O%H|C|V(xJIF&A+F4w*YmLS?s(Oh3h^ii{H5%Wr zxMkp$pC5expTIiGKW%@cZwHZr()i z-bEY-bNDd!>C>1;A0=++bHrFY=oDSjKmI^BH)-CyN#m=pXjUr3 z>AibI*RHW~;|3$2e1eRP(UN%P8TxPvm?Opz*Zv2Efuzx$4UsA`%R z!~N0>nDxpl488Ocap4a?(ERyl`jjTdu!|DMk7J)bOI-8rUFu(a!JruKS7ksF&pk)# zt+xYsiJwHiB6CB_gVB2@+;@$9pt-hLagELt=O*tm3w<}bgn6CzS2#&EwX zJCrzjl+@fDGBiYs1_AYap62>G15hQ#5F@JV>_Fn_r%Ao@4w6jLqCr4CpC>An7zBaq z#28{!WSKshr=BA9?z>1bNs9&n^?aVFRANvRR){ggIK^T~L~hX|bNDdB@4bhlQnY9g zP|xRyN+kwGL~c37Vu={TgO=%mdEyC%FI+%|hiTCupq|eYl}ZfQGFuoPR1lFST`&_9 z41e$eGBQGoh9ULKmx;<{ux+qyux+qyux+qyux+qydLbfBpuiRuTR6pH$)BAq0&md4 z@P{8FjzgSS7Q^Sy(}`|u;J^7MT~jSOSFV)U!my2mWz7o&bReUn>;)02CoF58Z5XzZ z^1KQnpYea8`gzLpDs01|4d=-x=WFHii@-E()MjVd1FKFZGfx|ab`};IqqhB;h}`Bs zA|kg(ZTmGA78St3lQ|)9Q6ONzM5HcoaWs=TL7{Mm zE?M+qVWHu`g}Uorj>2#Wk*um3c0fd$s1_56#C*#0D)h*r4=K;90Ir|SUJ{WUa7tAt z=z)mb0+xY-bLC2jK3VL5Q!JK%IbhCr-6;vf85NlX(yE#U()_C`B2}O&s_SZ5D~{)_ pF#r|=;&|Q~u*M!U>~n^F?k}YPAdmS`-2VUo002ovPDHLkV1mo7x!M2# literal 0 HcmV?d00001 diff --git a/static/badges/3.ico b/static/badges/3.ico deleted file mode 100644 index 43ce7cf299065c0ea4a17f8a7bc9a6a25e431796..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 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 RNq-N7|A|7HD#zOn{{dh0HCX@v diff --git a/static/badges/3.png b/static/badges/3.png new file mode 100644 index 0000000000000000000000000000000000000000..bda326517e13172aa840a09ec2d769f29e695ae1 GIT binary patch literal 1593 zcmV-92FCe`P)U?7P2Y&Vs6wbk`X-A5 z`?gT5f~Rltk3&$71Mh|JT$#E>)I)3Vji4Y}s0H7IR2$Y-n?SdwX{FlTb~l-s=dOy! zbelgryGf;=kEkklGQ%CtaEG(mAeC%(Kwwy5Cy-XvG?3;GB@rnBC4ui1rkp}yh7DlT zf=V_!0OWvus@kipDx<0y{zv)UKPuVmIp7$OcM63WnqVEKaftn-x@D_W|G#F-dnfR!1+3IgAsR7lYv)7M90|9r;^PMAd;m)ZBIW<`}jEau3fCh>hI^S@o}u3JBdvsTghez zsAITQPE`#J(rT4@8is@yE)ZV2goYteVhqWH2cff*I8@aDIqKNlY9BF#r4l!USFW%; zHAQgxG-0U(zR&MEJ4qfmK-&{f@F%ln3-%+A;D7ZMG3^5m6Jdy`xbC2;_7a1ZO4Qze zpKC9^$ns~O5zfzp@AH3GuTp#aZGtmrh_W7fh`3a>x8k~kL>MB(_lJo|fBTK)sVS({ zSW9r`3^!?Sry1h=!$cS&RAdL6#B_HP6<)YNGgM>;5r&(k*#!3Ek7ErC@Fxud{F5hX zQkn>x2vtqfijEGf-d=8yjt=DBd$AvV6sy0VsO3*SK}#i?p{i*jY;KmO1?Il{xa-wd zS&d%3O6|iB@xS0v|@P~U0h@(l1h;} zc#!tjUq`yTX+enyn+OppscME6Tz~B~B$zFx;#}i}cbZ!t>_|XJ_%h`G(p%?{MvtMUJsa!nrx3%sux&Dn(ohQ$!ddoI+tnM9#4ZWb0O< z^!jzE)rdnx&N+p`3=xJ~9U}&N_ihpg4j^~m&8m!{?U`qY3V!?%REg;rb!={x7m-7% zYG{Df*GJn^Ptmq_FaF7sgg^a6`18+%3kygxiMjuN+V<|ndhkJ_g73Z~4iO1~Jaug9 zIEBJYWn`oPJWm5;`*v=SM1r{ zBaUExp6Z)#LJ-g>5vf|XJ<1BK@$qr$+0Q=v>+;7RcLKXvhyUf51jQnfOd{L1A;z$h z@cemdp2yOWBT%amhrqwu-+lK#tiWa!PG8?>xmf%gFvL27Q>O?{odOYL>sF+z3)9sF zzE61ZBH_XUl*=^fxRc3@vI@g$#>Q$L$>e?!nWs^z=;h0Vv$ObLe~o|Q1mW4UP%hI9 z5t;8uCigQoR$~>0wdC`QSk^F5=JqRNS;OS>i>$%04#)GR#kPk;WS-kZMCQe|haAtF zW*vqGIG#7{BodDS$Ju$MdFXfT2>0+_p0l@75M%nB3V^6v_M2cR1216jix+rj+ktkkn+4az^!Dn{}hoNuuoNc zi9tlp0mp#6bM)v8O|of$Qz*;;hk?Tt*Bun!A6AhaKw4GPK$<_4M5F|iM0Hked&=>= rX*Ph(25~%Z8kpubGu+_}cewuoBdT53r2u=T00000NkvXXu0mjfzn%Mv literal 0 HcmV?d00001 diff --git a/static/badges/4.ico b/static/badges/4.ico deleted file mode 100644 index 91bd61f30d192284326203fdcf167a65301b8405..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmeHOO=uKJ6z<@{UcHEiJ!~!udkL$TJqrs9d&*&NGf9jdOcZbGDJ(>TsHYJB@F0N* zD|_**A{aCv#J`{rFnS0E5e%&>ds-CW%cE)j2@KW8?@74R>>-Sz) zS5F*gz}e;O-tABubSA%ZoL_M?=%4>XpTlbxFP6o-cMUNY5bDez(E%c^Gt*wJq5-MdVERAv=JW0kM88qIoF%$P^o9sA z1;R1L&VmQLS@~*owER8A-Z0I*MD#C_nltJ-c!<{>hHP3K&0js}HCfbj_IGtE)Bg^LBdmsxDl&3H72>YKA-`BYHca1G71w{F7PiHWZ@8qwJ3sCh2v(&$J1H0objsli0?_HA8Ux>OS9&iOPq zSMvOhYwzDT!f|Cyrp|kp*j4*c!&ScU{M0Ge(*s*?-KvD+mhs1OZ#4Sx9O3KRdf0r zY4z*;9~*zHAN}lX$;*dowJFY@FWJ;Tw*Q{S|FQWe>ql-qed^}}@*g>YmZ1K!{%!f! zuKvjSag4eLeR4~vUt51r6KP&!{Z;iNAFf{Y^MNrW)UU0-G{-=i=g*xx74iCY-J=H& zs_b7=Z+!khf12m-;ll-S{J87U-85f1b*nr`jhnse(2fy zn{oIt+5Ptq*3UiaLr|koC+`yBd4Xpp2*()9{QZmdf2+N;70{DI>{DQibet&Mr=Y!3 zwSBAp-?6K89safZV{FX*C6_DyMYZT}qD87XYec-CzJ@Ve0}pt=273t45Ya5rI$<@f zO|;{X31o-5ZOhnL`A1rlEs%bzJprAK{v7TC=KRujOiv5!*I%uV8i3b+n=pj;s?eU{4Kvrio-2mQ}^31Uv7<~jPZxRgHr7vOsVk0mS@kRIKp?d zqer7S>LPyY_~HAY#u2^)@wJTc8{>y^+d6+4Bl;^>TEE*Mt}vb@eqdDNhR<#5r;MGC zpFD};2zibBk}-Z`{j`04F=n|(+#~+Ep}uB`9~jx+Y9GAohH)$7vN=Zmk=w(ERryrd zzrRE^z1=%8#n8G9RueCt1E!W1Kd{l9+O-3Z6Hnsxvk5!K@f^nUSl2qhpJe@<+4~FD zL%Nm*KlwG$`wQvA_vXyrAMv|jwWYxiOu&|e@UBeu(tc!=H))TL94QFg2boTvE?U(H zV6l0Bhm9nY+5Smd+ao!<{S)Bt_x&r_(9ipaoG1Ofe=FNS`Oug9=WGLFiSns0zhAHo zeopu2_an9eeXzgVci-=18*ofH(U;#(RXZYEic@4$?Dy+@-s3Uuq3Pz{8B4Zq+VPXU RpZwng;eVpgcKUAn;Xm!bMEn2% diff --git a/static/badges/4.png b/static/badges/4.png new file mode 100644 index 0000000000000000000000000000000000000000..89c71e04590795d3bb7ab16a4fee0fd2d4af7430 GIT binary patch literal 1272 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 diff --git a/static/badges/5.png b/static/badges/5.png new file mode 100644 index 0000000000000000000000000000000000000000..b75b3d518f8d5c3a5dd6356a08bc9cf7df6281ea GIT binary patch literal 1471 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 diff --git a/static/badges/6.png b/static/badges/6.png new file mode 100644 index 0000000000000000000000000000000000000000..a146e5bbb23f3735725882f4f04977731b8db708 GIT binary patch literal 1631 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 RC--|G{7)2))$?-u;XgJL=)3>` diff --git a/static/badges/7.png b/static/badges/7.png new file mode 100644 index 0000000000000000000000000000000000000000..8b2cf062b3410419be53d5a583afadec88cb556a GIT binary patch literal 1306 zcmV+#1?BpQP)@zILI^#0u!{rx z2NZkJTS9`T(u4HiNfrjiYY90dU`qvw2SF@L#L8-E6L3k1f|MQ2?#}F2Q3KOWw%H$( zNS;SjmE+8C%o&b3OG?60>8!wv!b?CwRSQ6Yf7L~#4%7vHP*`?@V4W0LMi7=tXMr*> ztEv-9PeoNN@;BulABUyVLtqK0xIwVakSs&k@x15bC|X3Mq^gD?sOkjpfrwlQFJBHE zYv=O5zrlbkgIHL|g|*ru@PR@WRYs+%26#V?<9EZ$mv6Ym;vDnyP5NZ$SGjzmQLEin z_)sBB%2YM4@L{7?yG^-#f<77g5PIHZ*lK+XOmX<8!dC0s(DNqggW&+7=S^x9t*Pp1 zj)s8P{wJz>y3uUj zWMLsk4~8DXpMF{druhF&g|*ruJy`a!<9W{mSLlOt?i^UlFgic~j6QzMfkdwCc;2UZ z-`}8%Wgl@AEh^;cL-xJ*aGraPVf=ahI`Q4R97I*~aTF~A9$gGw!cyrhA|?8yTU#6n zky2PHou!Lmud=Ed`qbIl;wY%90m^i->@~{(+FyQ2eE&WNaf(H<)6?wIcAL)q`wVCn zxJrU0A@saSRh?h}`sfkyqemPh^X8i*MQdy5JA zuFmhj6Mg+PX)-*iPFh6By!|#w?OV4Xju}y%1Ve&|)Jcgwe;)Jfv+UAVi}vl?j7mi6 zBp9AlCncHbX_BI^zJf-B6x2yDB#7#dq`(x5I4``wE>)$qx=I=Zejve+pdw48Ap6cc zB*k~{qFY;}L1CE$LxLLw>mu@y5y;7tI4{3UQhQ~EG>FJUHwe~AFzmI&2(r`Dh%xMn zA3PwwcaM}T(Z#S=MMOFbV{8oj`s*aMS5`=ah;)DoT?}2^AXrB=U4 zBl_kWQlT2SL9k92!#*5q=LA{|B9kF=@ghm>FTQ{{W>g}w<5)Y#J`DTF`~C(ZpD+L! zA1D6qJK_fq&?rK8c4*(ZLn>5neWEsT#eA9)Gc0BLXIEoe#DXFSq1R~Nw zHETy@UOav)PcIF{;1Y2yS`r~1(uY!zF!5Z95KT&XE^5m0$sZ0C?!XM Q@Bjb+07*qoM6N<$f_u+lM*si- literal 0 HcmV?d00001 diff --git a/static/badges/8.ico b/static/badges/8.ico deleted file mode 100644 index 8d0ca36cfb85fb8b2d9841a47947fe2c453d5116..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 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 diff --git a/static/badges/8.png b/static/badges/8.png new file mode 100644 index 0000000000000000000000000000000000000000..463f2d1bede4a9a3de5e91aaeb058746e7e26e6a GIT binary patch literal 1724 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 RvAzew|3snmU%$2;{sW$JQBME> diff --git a/static/badges/9.png b/static/badges/9.png new file mode 100644 index 0000000000000000000000000000000000000000..2025b41a2c03fe736a1aa0ba299e0abea5b57c27 GIT binary patch literal 1600 zcmV-G2EX}T2*wd9sH&j@s=5a_ zDk4Yx!-vb3ZI5I;Z<>T`k{BCH`%_cnz)^)1s;rl)8sJ}H82-~geE35rpC4g#v`(80 z?J5?ti&Ik<6pkyT*kG!fQ8>OhHFbevF-w~aZSY-pz+Ybe78vB-8}yf#zx7>rfHoNJ z!gt*P4T6iR+RJ^Ss=XQn7k$?q;4TbnDHgMY;d!8&`>&fYJWsKhWetW_#>Uc%_4-*= z?d5Nxs=bT#`dP-t(zIY`!T;r#abS?Y-=IG=HBJjQtEjo|Zr}(Vke(i_M;^iK+J)J% zgXs6)iDqVqW@dMeXb{jKn>Ukr^G#&iHj+?P0~Bdu zbEjbvNF6$a$>nH>s#R*IP7%${(qMXe$h`eFCY$AdB$FX^=n(bOr%7lSI7W;i#&_KT zRoz1Z_JIR5s4BIOKPH-;B`%tsW$B%F&@iOIe)?(5!w-{$s_yY!cYqi}j0C|D3COl> zn5|oB(78FH>(^P0{`MQe!~_i@g30GeN`hdB7(>~lQdpB{>&6}(x`1)(&%+8%8 zr6T)?G2AZ4I>@F?tVQSNi8DKQ(t#W?h8R`Nkw8?f5@&jQA)Tg`Xkmdk^Uy;irK&k% z47baXfX>gO^*RmWIHX>E6+~zz*(~YTUnfpiR_H*E7@Kukxp0BhOE1xodhtc9y?Y72 z|DI@J0h7&QcJ0D?{Bgv#iPJy+V7+W^R|WDUu>9F)*!%ZmvRN9ezCNtJKJG>r7U)2g z7(4477v2@}D_LEOy?c0a+ z^kBAbCAxKss9GhgR0ywK!#Q<|28|+uN`($oiLr?h)t{Bl1rrkl6BDeaYj_yhvW14= zn{VLHKS@g93NeNl6*o%YBf3~A~nmhMp%W-Dl(oo?H3BCP(4nYqFcAnD1sm${P9PEOP2_~`wo_tSU1%V zGoCliDr{PC_U;{7oSHfS4APF36>1-RKzQ{k)az`Zi%vd2LJNjgMn~)2>GUfiGDDlf zAAW#(osA+QGu`R*D~yiTX~D3TQfVH`8Uhx%{}!>VAxfor)?l~`$MYt|wg*LIhWkWB zX2iA!9nYKOE(~pOJa5uTrJevTa_?PqQmH2#&zqzThIW-o^WFLU3j*&8EVIExq$cow zcRv3DrP4fYvPoiewC=#aYp(lI7zE>p6jar)4k8kvTDB}}B;$G0BxKWpjOR@Qu3spe z6p literal 0 HcmV?d00001