From 1ad4409609e7b08e787f2bda0dee718bf91f2b9e Mon Sep 17 00:00:00 2001 From: henrygd Date: Tue, 7 Oct 2025 14:13:41 -0400 Subject: [PATCH] update favicon to show down count in bubble --- internal/site/public/static/favicon-green.svg | 1 - internal/site/public/static/favicon-red.svg | 1 - internal/site/public/static/favicon.svg | 10 ++++- internal/site/src/lib/api.ts | 3 +- internal/site/src/lib/systemsManager.ts | 13 +------ internal/site/src/lib/utils.ts | 38 +++++++++++++++---- 6 files changed, 43 insertions(+), 23 deletions(-) delete mode 100644 internal/site/public/static/favicon-green.svg delete mode 100644 internal/site/public/static/favicon-red.svg diff --git a/internal/site/public/static/favicon-green.svg b/internal/site/public/static/favicon-green.svg deleted file mode 100644 index 5ace6e6e..00000000 --- a/internal/site/public/static/favicon-green.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/internal/site/public/static/favicon-red.svg b/internal/site/public/static/favicon-red.svg deleted file mode 100644 index 8512d9d6..00000000 --- a/internal/site/public/static/favicon-red.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/internal/site/public/static/favicon.svg b/internal/site/public/static/favicon.svg index fa4a9c5f..5cd73a8e 100644 --- a/internal/site/public/static/favicon.svg +++ b/internal/site/public/static/favicon.svg @@ -1 +1,9 @@ - \ No newline at end of file + + + + + + + + + \ No newline at end of file diff --git a/internal/site/src/lib/api.ts b/internal/site/src/lib/api.ts index eed6469f..79f4b127 100644 --- a/internal/site/src/lib/api.ts +++ b/internal/site/src/lib/api.ts @@ -3,7 +3,7 @@ import PocketBase from "pocketbase" import { basePath } from "@/components/router" import { toast } from "@/components/ui/use-toast" import type { ChartTimes, UserSettings } from "@/types" -import { $alerts, $allSystemsByName, $userSettings } from "./stores" +import { $alerts, $allSystemsById, $allSystemsByName, $userSettings } from "./stores" import { chartTimeData } from "./utils" /** PocketBase JS Client */ @@ -28,6 +28,7 @@ export const verifyAuth = () => { /** Logs the user out by clearing the auth store and unsubscribing from realtime updates. */ export function logOut() { $allSystemsByName.set({}) + $allSystemsById.set({}) $alerts.set({}) $userSettings.set({} as UserSettings) sessionStorage.setItem("lo", "t") // prevent auto login on logout diff --git a/internal/site/src/lib/systemsManager.ts b/internal/site/src/lib/systemsManager.ts index 7ff78af5..b96cac43 100644 --- a/internal/site/src/lib/systemsManager.ts +++ b/internal/site/src/lib/systemsManager.ts @@ -9,7 +9,7 @@ import { $pausedSystems, $upSystems, } from "@/lib/stores" -import { FAVICON_DEFAULT, FAVICON_GREEN, FAVICON_RED, updateFavicon } from "@/lib/utils" +import { updateFavicon } from "@/lib/utils" import type { SystemRecord } from "@/types" import { SystemStatus } from "./enums" @@ -74,9 +74,7 @@ export function init() { /** Update the longest system name length and favicon based on system status */ function onSystemsChanged(_: Record, changedSystem: SystemRecord | undefined) { - const upSystemsStore = $upSystems.get() const downSystemsStore = $downSystems.get() - const upSystems = Object.values(upSystemsStore) const downSystems = Object.values(downSystemsStore) // Update longest system name length @@ -86,14 +84,7 @@ function onSystemsChanged(_: Record, changedSystem: System $longestSystemNameLen.set(nameLen) } - // Update favicon based on system status - if (downSystems.length > 0) { - updateFavicon(FAVICON_RED) - } else if (upSystems.length > 0) { - updateFavicon(FAVICON_GREEN) - } else { - updateFavicon(FAVICON_DEFAULT) - } + updateFavicon(downSystems.length) } /** Fetch systems from collection */ diff --git a/internal/site/src/lib/utils.ts b/internal/site/src/lib/utils.ts index 8c6a4782..b16191e2 100644 --- a/internal/site/src/lib/utils.ts +++ b/internal/site/src/lib/utils.ts @@ -4,16 +4,11 @@ import { listenKeys } from "nanostores" import { timeDay, timeHour, timeMinute } from "d3-time" import { useEffect, useState } from "react" import { twMerge } from "tailwind-merge" -import { prependBasePath } from "@/components/router" import { toast } from "@/components/ui/use-toast" import type { ChartTimeData, FingerprintRecord, SemVer, SystemRecord } from "@/types" import { HourFormat, MeterState, Unit } from "./enums" import { $copyContent, $userSettings } from "./stores" -export const FAVICON_DEFAULT = "favicon.svg" -export const FAVICON_GREEN = "favicon-green.svg" -export const FAVICON_RED = "favicon-red.svg" - export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } @@ -100,9 +95,36 @@ export const formatDay = (timestamp: string) => { return dayFormatter.format(new Date(timestamp)) } -export const updateFavicon = (newIcon: string) => { - ;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = prependBasePath(`/static/${newIcon}`) -} +export const updateFavicon = (() => { + let prevDownCount = 0 + return (downCount = 0) => { + if (downCount === prevDownCount) { + return + } + prevDownCount = downCount + const svg = ` + + + + + + + + + ${ + downCount > 0 && + ` + + ${downCount} + ` + } + + ` + const blob = new Blob([svg], { type: "image/svg+xml" }) + const url = URL.createObjectURL(blob) + ;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = url + } +})() export const chartTimeData: ChartTimeData = { "1m": {