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 zcmeHOzl#(}6t2aEOE-}VE;tk65;;vS77h+By5O=`v%_k%_zx(Eu&`_(D2E^h3I{6) z7Z@2S1_qNjfr?__s`vxhND!8)aU5oM>-f5>cdL7SQx~momL{)1Xjcw6_+7d3RlRz(?dqQzKiHv;|0H(QJW@C^dO7_!;ZbM)Bs|L8 z8B?mxg*by4bJ~bAD^aXUmok|C&$OJ&A2^r45{We;@sLQo(J>Kzg*w{SKm*!Pwpv^q zen%w#AQC+y@j2tSSwF@zXnN>_zEyE7E$trZbmS=_(I@hX-&rh(`F-#Jud+Bg9r-(v zc{sW7A#PB`dKJ^;%-&o}5?N6+DYRKRE56Yjl z{io@F4=wh`zQQ`rX8YN*`!qGie`5am#-FE8$Lj6dZFTeJP~E-zt!(^tVe=#0D>(8xQL-pdtSdB*evP-Og&h-cKeb?XRWub1|7^;^q<8xRE z`MK*aFwAoQ0r|7ue*uHG!%X&{iF|E`neD$59I;PM|NN22Pwt2hIz}N*KCqm>&=&ms zmB>G+_jER3`UQCkq)3;{JjL-z90%3@hkAw0b2n|zZdd+HG`PgMyu-PCL?kwheEJ63 z@D4PfZ5odcf6nCz&gEa6%lGD9(x;9-y6*`eSs`h<-QkZ!a-DPOofB~B6!Vbl;29F5 zjn~SGLeB0okqntbige>#4#68TY_jXNojIe9md%5>Y+lgbgRHuE&Hk8goXd{|a*J?z zzlW?)b3BeK_U}av>m%ywfN`9r-Lv+9?5e&L&($cmKEXFDr{U*bl{w8h;!Hj4_wJ3N zGo)Fn@syX%`B+rf@x6A8422)Dwaof}wW*q&(&H5he~d-07ug-}^`4;ix(b;g@nf9^ zwjv#{CkbKu(D=a**gWu;-ix{P4QYRk|9u{QjE@UTmG;p1wGK`n!rr_JPFJ61@DDD! z#vndlq+^H+n@@W)_~o4({5UsxVe_GD2>&A&etqWi!Zs`Xz?g&I`nx0_tTvh^?2j|` z0mhGf{qY_q|eof#9MwkDzJ$|-f{Q^dp{qI*jiFx$?Zld9WI z_ie&|iq6DUa%s>5Sn=KR{{4}CaIxt7HIHeWIW!yZ!?t$)mZ44K75^d#{}Y9Bc%QZ%{so@x-9G>T 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 zcmeHONoZ9`6n&!5TQ}mO7wtyqjkIohEi^Rrsu#Vhm&8O-f;ejsjFCVRG^mIPINKp; zI|fnIMF@$;fEWnI0fjg<4snWz-}iq0{HrZ_}bTy?c; zTTU}4)39ZZ?b;QmhLNXzeQCOSbpfBZ6VsU37rVa{yjxr2^udD+{q!kEH*GS-Hgdj& z_rul|t*SC8WN2!N)4O*w>?i60Ae2Xi_J*z-^zq{iO(gR4)vGM)M>dEyF`n8!5%UUp)U^QzxKZhh^&B-#vv255zqqpHgMgAn6>8GL0q?t@lP{&v5?I~4(ME=vkB1kr=7bJp)Q zYYg^_NDk;>nU@}{xyHtu@jP-QK~t$bTfgAHw{G=ZH-pGI>@_Ftd0v=nmo6m>%Ny2A ztU+yUamU&fQa3s9Q0V|RYui|XCiH*!aDomFrs$V1IhxPsnLhgaQ?#zGh!;|ZA(ely zeT&k*YibO-d-o)L_%Ortk;~=j*|SNuuL;Q;_!HnI>%jJFp7gMekBp=l|5z+X+uPmO zat(72t~BVOLkTty&Yw@xg9j(sKJMd3Yb*u_(++&GJqNK)$oDGv!-p4e zuupmSF2~6f0Q<+!pRIb+%(Jl(+wnXHUY63Q3jT%t3Fg-LxWxlwjd_3bW}1$SWZ3>u zgpC{3HpxNa%gZq@{+*rH9usi=dWwxZr&C{V(1C#zC(ri9_!bmwIx7AJ{a?6Hw0rEk zId7hJbtMYy8XBzr2L+pkO8PJ^)_7&N{yF_DDI1bwa+x{zU%+y8~?i<~#I_aexnc{@kjM$MdwKqb&PZ z`XAZG&4{Q-Y@{RI!46CnrAp4+#Ztk2@vEun~&w_a7l?`{DcUKfwQ6@4p~} zt%q;2|K$8_J$$qMHY`s9Yp#f*D(zt`nH{$Y8IX129@H0i(k-vP| zich?Kn`3!?cPQgUUpCuCd-TiO{=LLU4i8&#P7&U}&$0MJ^fDK92j3cIeZbnJl847< zRDe5F#8Fl4qNy{x{q&CS_MSkwu43*ZzWnG>hQ+vKKx}fV<`mXx$mZ7v>`8*?YyEnY z4h*E({ecLGDIum3ghp5#$QD5UPn@#%WjWZsNI5ge?gq6<^AA3G8`7u6zG*sVl zpMqGL2tz~eF?^YZ2=X_%>@|n5H<$5)mht}N>(^o&67hMg7eU&K;D@j4@kX~Xu+A6m zJ_K{Vrzb`4+{v&vCr_SO_Xnp=CD|C9J6DWv1K^YV8hx|A z|8lf}9}(m00QgAw&hG9c`$6ygUP^}MW`7$HLFTV0W5Ox-5cYZ7(FW_42lp|i7iCs7FqJY46G9rqA% z>9c1}zuwwf)TcnRkeBy(c<09PDgjQz%YIeD8-FyTu*ymM#9iA8kbtY07!O z{Ts$bwSUHY9~nM;$gw+6>?QcS2NAAa3$}L%DSwdtGh&)0=NG&Q2@3b_WdhkP*RKe? zPELcKUoZx4=SSTCQb9e%j@3FKGBucDKubX+}XmleN4A7*m= z5c147{7)2MHl1!g{0C40`RD)u diff --git a/static/badges/10.png b/static/badges/10.png new file mode 100644 index 0000000000000000000000000000000000000000..16bb2da0f528016fea38786fd2fd42cdd4e69d76 GIT binary patch literal 1641 zcmV-v2A27WP)*t>@xB~!a%T;30_DkNULM&g|#43(f*@pwbM;$4oUjvea_i& zfp=Nbrd?Xu=Oe1hoy>5DGu+{9TBMLl9TON-I10p7H4eo2Q(i>!KwjWGg^ST_c9s^f zxebL>>KKp)PO55;(ojNG6a0_zfB!6`QVYO1kcnoqv+R=1E)*T-NX7F;5lN}4VHZ@j z2RI`lrwhqs*0SxPi0dx0LpD1xG7>J#&5Z(Q6hf$SyHwQxFIOs+zZa6p_oIo#5W~YI znq+8JI(=YcZf-*1oI;2eQ`LyVxsAEG3DW5UG|A9}g5&fR%H^+te)e8}p3B3|mR34^XLG1Y+#J7?sLJ(&+FUCC zb%AB!FD>COFXR9CBl^c5w4BK4qT`&8xb7k~Z0e|Z-l#%^8rGwa5_TL+XD2r~ew^#H zSfrH8;Z07`N~#*Ec-|=BP{UB8kV+jxBt?zzYp>D%#v7QRPY*%f)D(@BKmHh1rOG_`Agv~zH%NdXKt+0~VU8Rj$X{Ed5nWxyUs#~Z+&)T9SiQZNc$`}L`|nh3B$Lz=%jKxrNG90{ zo15i<1Oa;O8s!f^B>c)NR7qPKZI3@rGxWFLXt6v2h5!-CQ^)4S1f^UKEf#4+i$yjk zCsEI%%3oVUuUw&(L?lmu&CT-EqsrzdpWt1-OxuYQn8SyWcpQpF{CpmNd6~_rDcYWR z01Y+9+`T0D>^XKvB=V>(&@qr9A3^k(J>@2ET>IlF7I^h>yz&?5u zv2B9NpMJ`J-hLZ@ex5y{nvG_&v(&Ju!?Nw6is!wc5F$X=)}XtaAphr|DShw(mDySL ziii{~%Nn8%n>r${yI4r2{*CH60{qoguJcz{@xJ^L@2juy=jYjTs_#c!cab`58i+pd zz|h9r+~0tHZty<;9PiR4{N-i#(R4JC7@`3~Bg4a`SUCKgh%9k~zp{eAyv%+Pk)>ET z{2ar>B^oenC6iglvIc<-_TL7UHAp72&K3;Yh`R2K*ml2&EU`~SWJzqhKkB+OY{Srm zsO!!|L!rljY4+Z9G!%L)>bf&D!O*NsW<8cjJSp(5K$#X3k)pu6u|(oYGMROnWU~{) z!=)(vqv$y2E1oxsNJ>==w?RaFRI`?44MkjcksY$xg^24e0!|^7`j?2Lfs?A*!w!hZ z0x%9_qPg5GyJT}4qS@>$a27aQaGXBzyg?P|1>&k22jcuGFCuv$FRI_GZC{MK?hGwp n(;`vVodIUpXNEhR;STp-Y`t>rzT_so00000NkvXXu0mjf=TIC~ 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 zcmeHOF-sgl6dqAXYa=OA#70OX(I&MJ2&77p?u{PW1+=l2fFf5|W0{I6bA}Ox2 z5*tA*LJBJ@nYmmv(Fxz~%w=zGcXnrY@AlR>u4oAb{^w_(EaZ!GEHV=*2B{w=A_3NlETHh{BqaoD( z{*4miKDbavn}u!L=%H=Z?FYSG&}NN4iHwJxyZw-B7qmrbFfS#J$NYBr=fDqt>5lie zU*L1O=MQ!$;y=cYnuiNVqW>BmMb?ku;d5t9sUjER3}VbeB+hIGv8uQDVEUhFIhW5k zm#>LLlSmvAi3=SQ;a8}mtqB^?mSwA@rOp!~`Ho1mh{RQNJtova)4~{x&5L7s`F?zH zQO*;IW1>v)+s1>Ke+(Yr<%?r+QNAS-rwKaRvRu!n;FVRr)*G^KN|0@E-2g)tJ7}Ai zp|_E3?y$qW%MPKh1@mpjlzl&T`K0#qEPI8#xb7e$&IVYsdW|`GudPY7yZcLBT>Me( z_I+@njyCjV@R?Rze9*DQxxQCdg*rR?t!{7o_Yr7AA81lATtSv?10B~A$3i#oPb;9w zV25Ume8kU0`LJ)C-gW^EXkEOB#6gUF#PGy%nB%Mkv@TwFU&P3F?N0(f%Ua-OpzTn}{?o|U zcBpLsZE%D>IsEg7k#FvZ4?0F6P9DUZztC3t`OCaroly(nD5RYdnlAz2A$5q=zV~1Lkp-b)JjLd5f#8#j81Kv$}Weske z+)J}N`t_b5_j|S3{HczPZq?=Go$7S%g9~-Ep)ap~cuxacnhw~LNH>BFM{wtQ7Di1VcX#^P72-Q diff --git a/static/badges/11.png b/static/badges/11.png new file mode 100644 index 0000000000000000000000000000000000000000..789bb2d2c495e95932861ae96e4d75e2ce563dd6 GIT binary patch literal 1243 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 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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 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 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 G9{vN@K2C1{ 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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 sXy{Vdhy8`z#~IJBk$*Ckkb`UTi!32R0MvyZ`_I 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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 Q+#5mopD4h$XJ_l-KT2?pO#lD@ 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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 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