fixing small bugs; improving background handling and removing dead code
This commit is contained in:
1 parent
99dbea0615
commit
62e187b9f5
24 files changed
+439
-250
No files matched your search
@@ -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),
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
Reference in new issue
Block a user