fixing small issues in the project
Build and Release to Staging / Build Vision Start (push) Successful in 40s
Build and Release to Staging / Build Vision Start Image (push) Successful in 1m8s
Build and Release to Staging / Deploy Vision Start (staging) (push) Successful in 16s

This commit is contained in:
ivanch committed 2026-10-10 23:25:20 -03:00
1 parent 032d2a100a
commit 99dbea0615
17 files changed
+166 -55

No files matched your search

+29 -4
View File
@@ -7,7 +7,7 @@ declare global {
storage?: {
local?: {
set: (items: object, callback?: () => void) => void;
get: (keys: string[] | string, callback: (items: { [key: string]: string }) => void) => void;
get: (keys: string[] | string | null, callback: (items: { [key: string]: string }) => void) => void;
remove: (keys: string | string[], callback?: () => void) => void;
};
};
@@ -94,6 +94,24 @@ export async function removeCachedIconFromChromeStorageLocal(sourceUrl: string):
}
}
export async function pruneCachedIconsFromChromeStorageLocal(keepSourceUrls: string[]): Promise<number> {
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));
if (stale.length === 0) return 0;
await chromeLocalCall<void>((cb) =>
window.chrome?.storage?.local?.remove(stale, cb),
);
return stale.length;
} catch {
return 0;
}
}
/**
* Adds a new wallpaper to chrome.storage.local.
* File uploads are stored as base64 while remote wallpapers remain URLs.
@@ -123,9 +141,16 @@ export async function addWallpaperToChromeStorageLocal(name: string, url: string
finalName = finalName || getFileNameFromUrl(parsedUrl);
}
await chromeLocalCall<void>((cb) =>
window.chrome?.storage?.local?.set({ [finalName]: url }, cb),
);
try {
await chromeLocalCall<void>((cb) =>
window.chrome?.storage?.local?.set({ [finalName]: url }, cb),
);
} catch (error) {
if (error instanceof Error && /quota/i.test(error.message)) {
throw new Error('Not enough extension storage for this wallpaper. Delete an uploaded wallpaper and try again.');
}
throw error;
}
return finalName;
}
+3 -5
View File
@@ -1,9 +1,7 @@
import { parseServerAddress } from './urlUtils';
async function ping(url: string, multiplier = 1, signal?: AbortSignal): Promise<number> {
const address = url.trim();
const target = new URL(/^[a-z][a-z\d+.-]*:\/\//i.test(address) ? address : `http://${address}`);
if (target.protocol !== 'http:' && target.protocol !== 'https:') {
throw new Error('Server addresses must use HTTP or HTTPS.');
}
const target = parseServerAddress(url);
const controller = new AbortController();
const abort = () => controller.abort();
+26 -1
View File
@@ -6,4 +6,29 @@ export const getFileNameFromUrl = (url: URL): string => {
} catch {
return pathName;
}
};
};
const SCHEME_PATTERN = /^[a-z][a-z\d+.-]*:/i;
const AUTHORITY_SCHEME_PATTERN = /^[a-z][a-z\d+.-]*:\/\//i;
const ALLOWED_WEBSITE_PROTOCOLS = new Set(['http:', 'https:', 'ftp:', 'mailto:']);
export const normalizeWebsiteUrl = (raw: string): string | null => {
const trimmed = raw.trim();
if (!trimmed) return null;
const hasScheme = AUTHORITY_SCHEME_PATTERN.test(trimmed) || (SCHEME_PATTERN.test(trimmed) && !/^[^:/]+:\d/.test(trimmed));
try {
const url = new URL(hasScheme ? trimmed : `https://${trimmed}`);
return ALLOWED_WEBSITE_PROTOCOLS.has(url.protocol) ? url.href : null;
} catch {
return null;
}
};
export const parseServerAddress = (address: string): URL => {
const trimmed = address.trim();
const target = new URL(AUTHORITY_SCHEME_PATTERN.test(trimmed) ? trimmed : `http://${trimmed}`);
if (target.protocol !== 'http:' && target.protocol !== 'https:') {
throw new Error('Server addresses must use HTTP or HTTPS.');
}
return target;
};