From a37e3935e755f9a7f1a81e51d9fee696cac681c2 Mon Sep 17 00:00:00 2001 From: sowgro Date: Tue, 14 Jan 2025 16:40:02 -0500 Subject: rewrite icon system to cache better --- extension/src/Icons.ts | 105 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 extension/src/Icons.ts (limited to 'extension/src/Icons.ts') diff --git a/extension/src/Icons.ts b/extension/src/Icons.ts new file mode 100644 index 0000000..b386713 --- /dev/null +++ b/extension/src/Icons.ts @@ -0,0 +1,105 @@ +import {getBrowser} from "./main.tsx"; +import BookmarkTreeNode = browser.bookmarks.BookmarkTreeNode; +import {RGBColor} from "colorthief"; + +interface IconCacheEntry { + url?: string, + data: string, + setByUser: boolean, + source: "google" | "site" | "custom" +} + +async function getIcon(bmData: BookmarkTreeNode, setIcon: (icon: string) => void) { + let id = bmData.id; + let bmUrl = bmData.url!; + let cache: IconCacheEntry = (await getBrowser().storage.local.get("icon-cache-" + id))["icon-cache-" + id]; + + if (cache) { + // if there is an icon in the cache, set that + setIcon(cache.data); + if (cache.setByUser) { + // if the user was the one who set the icon, then quit + return; + } + + if (cache.source === "google") { + // if the cached icon came from google check to see if iconGrabber found an icon + iconFromSite(id).then(async r => { + if (r) { + // set the icon and update the cache + let iconData = toDataURL(r); + setIcon(r); + let newCache: IconCacheEntry = { + url: r, + data: await iconData, + setByUser: false, + source: "site" + } + await getBrowser().storage.local.set({["icon-cache-" +id]: newCache}) + } + }) + } + } else { + + iconFromSite(id).then(async r => { + if (r) { + // set the icon and update the cache + let iconData = toDataURL(r); + setIcon(r); + let newCache: IconCacheEntry = { + url: r, + data: await iconData, + setByUser: false, + source: "site" + } + await getBrowser().storage.local.set({["icon-cache-" +id]: newCache}) + } else { + iconFromGoogle(bmUrl).then(async r => { + if (r) { + // set the icon and update the cache + let iconData = toDataURL(r); + setIcon(r); + let newCache: IconCacheEntry = { + url: r, + data: await iconData, + setByUser: false, + source: "google" + } + await getBrowser().storage.local.set({["icon-cache-" +id]: newCache}) + } + }) + } + }) + } +} + +async function iconFromGoogle(bmUrl: string): Promise { + const url = new URL('https://www.google.com/s2/favicons'); + url.searchParams.set("sz", "256"); + url.searchParams.set("domain_url", bmUrl); + let resp = await fetch(url) + if (resp.ok) { + return url.toString() + } +} + +async function iconFromSite(id: string): Promise { + let icons_aval: string[] = (await getBrowser().storage.local.get("icon-aval-" + id))["icon-aval-" + id]; + if (icons_aval && icons_aval.length > 0) { + return icons_aval[0]; + } +} + +async function toDataURL(url: string) { + let response = await fetch(url); + let blob: Blob = await response.blob(); + return await new Promise((resolve, reject) => { + const reader = new FileReader() + // @ts-ignore + reader.onloadend = () => resolve(reader.result) + reader.onerror = reject + reader.readAsDataURL(blob) + }); +} + +export {type IconCacheEntry, getIcon} \ No newline at end of file -- cgit v1.2.3