fixing small bugs; improving background handling and removing dead code
Build and Release to Staging / Build Vision Start (push) Successful in 1m6s
Build and Release to Staging / Build Vision Start Image (push) Successful in 2m41s
Build and Release to Staging / Deploy Vision Start (staging) (push) Successful in 18s

This commit is contained in:
ivanch committed 2026-10-28 21:52:07 -03:00
1 parent 99dbea0615
commit 62e187b9f5
24 files changed
+439 -250

No files matched your search

+32 -11
View File
@@ -8,6 +8,7 @@ declare global {
local?: {
set: (items: object, callback?: () => void) => void;
get: (keys: string[] | string | null, callback: (items: { [key: string]: string }) => void) => void;
getKeys?: (callback: (keys: string[]) => void) => void;
remove: (keys: string | string[], callback?: () => void) => void;
};
};
@@ -57,17 +58,36 @@ const chromeLocalCall = <T>(
});
});
export async function getCachedIconFromChromeStorageLocal(sourceUrl: string): Promise<string | null> {
if (!checkChromeStorageLocalAvailable()) return null;
let pendingIconLookups: Map<string, ((value: string | null) => void)[]> | null = null;
const flushIconLookups = async (): Promise<void> => {
const lookups = pendingIconLookups;
pendingIconLookups = null;
if (!lookups) return;
let result: StorageResult = {};
try {
const key = getIconCacheKey(sourceUrl);
const result = await chromeLocalCall<StorageResult>((cb) =>
window.chrome?.storage?.local?.get([key], cb),
result = await chromeLocalCall<StorageResult>((cb) =>
window.chrome?.storage?.local?.get([...lookups.keys()], cb),
);
return result[key] || null;
} catch {
return null;
result = {};
}
for (const [key, resolvers] of lookups) {
const value = typeof result[key] === 'string' ? result[key] || null : null;
resolvers.forEach(resolve => resolve(value));
}
};
export function getCachedIconFromChromeStorageLocal(sourceUrl: string): Promise<string | null> {
if (!checkChromeStorageLocalAvailable()) return Promise.resolve(null);
return new Promise(resolve => {
if (!pendingIconLookups) {
pendingIconLookups = new Map();
queueMicrotask(() => void flushIconLookups());
}
const key = getIconCacheKey(sourceUrl);
pendingIconLookups.set(key, [...(pendingIconLookups.get(key) ?? []), resolve]);
});
}
export async function saveCachedIconToChromeStorageLocal(sourceUrl: string, dataUrl: string): Promise<boolean> {
@@ -98,10 +118,11 @@ export async function pruneCachedIconsFromChromeStorageLocal(keepSourceUrls: str
if (!checkChromeStorageLocalAvailable()) return 0;
try {
const keep = new Set(keepSourceUrls.map(getIconCacheKey));
const items = await chromeLocalCall<StorageResult>((cb) =>
window.chrome?.storage?.local?.get(null, cb),
);
const stale = Object.keys(items).filter(key => key.startsWith(ICON_CACHE_KEY_PREFIX) && !keep.has(key));
const local = window.chrome?.storage?.local;
const keys = local?.getKeys
? await chromeLocalCall<string[]>((cb) => local.getKeys?.(cb))
: Object.keys(await chromeLocalCall<StorageResult>((cb) => local?.get(null, cb)));
const stale = keys.filter(key => key.startsWith(ICON_CACHE_KEY_PREFIX) && !keep.has(key));
if (stale.length === 0) return 0;
await chromeLocalCall<void>((cb) =>
window.chrome?.storage?.local?.remove(stale, cb),
+19 -12
View File
@@ -4,6 +4,7 @@ import {
removeCachedIconFromChromeStorageLocal,
saveCachedIconToChromeStorageLocal,
} from './StorageLocalManager';
import { normalizeWebsiteUrl } from './urlUtils';
const MAX_CACHED_ICON_BYTES = 256 * 1024;
const MAX_RESOLVED_ICONS = 50;
@@ -138,20 +139,25 @@ const getIconFetchSource = (iconUrl: string): string | null => {
async function getWebsiteIcon(rawUrl: string): Promise<string> {
const trimmed = rawUrl.trim();
const hasProtocol = /^https?:\/\//i.test(trimmed);
const targetUrl = hasProtocol ? trimmed : `https://${trimmed}`;
try {
const parsed = new URL(targetUrl);
if (!isTrustedTld(parsed.hostname)) {
if (!hasProtocol) {
return `http://${parsed.host}/favicon.ico`;
}
return `${parsed.origin}/favicon.ico`;
const normalized = normalizeWebsiteUrl(trimmed);
if (!normalized) return '';
const parsed = new URL(normalized);
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return '';
if (!isTrustedTld(parsed.hostname)) {
if (!hasProtocol) {
return `http://${parsed.host}/favicon.ico`;
}
return `https://www.google.com/s2/favicons?domain=${parsed.hostname}&sz=128`;
} catch {
return `https://www.google.com/s2/favicons?domain=${encodeURIComponent(rawUrl)}&sz=128`;
return `${parsed.origin}/favicon.ico`;
}
return `https://www.google.com/s2/favicons?domain=${parsed.hostname}&sz=128`;
}
function getInitialIconSource(iconUrl: string): string | null | undefined {
if (!iconUrl) return null;
if (isDataUrl(iconUrl)) return iconUrl;
const inMemoryIcon = resolvedIconCache.get(iconUrl);
if (inMemoryIcon) return inMemoryIcon;
return isCacheableIconUrl(iconUrl) && checkChromeStorageLocalAvailable() ? undefined : iconUrl;
}
async function getCachedWebsiteIcon(iconUrl: string): Promise<string | null> {
@@ -245,6 +251,7 @@ async function removeCachedWebsiteIcon(iconUrl: string): Promise<void> {
export {
cacheWebsiteIcon,
getCachedWebsiteIcon,
getInitialIconSource,
getWebsiteIcon,
removeCachedWebsiteIcon,
};