diff --git a/webapp/src/components/vault/WebsiteIcon.tsx b/webapp/src/components/vault/WebsiteIcon.tsx index 7ae4477..2eaecba 100644 --- a/webapp/src/components/vault/WebsiteIcon.tsx +++ b/webapp/src/components/vault/WebsiteIcon.tsx @@ -9,6 +9,7 @@ import { preloadWebsiteIcon, subscribeWebsiteIconStatus, } from '@/lib/website-icon-cache'; +import { firstCipherUri, hostFromUri, websiteIconUrl } from '@/lib/website-utils'; const ICON_LOAD_ROOT_MARGIN = '180px 0px'; @@ -17,29 +18,6 @@ interface WebsiteIconProps { fallback?: ComponentChildren; } -function firstCipherUri(cipher: Cipher): string { - const uris = cipher.login?.uris || []; - for (const uri of uris) { - const raw = uri.decUri || uri.uri || ''; - if (raw.trim()) return raw.trim(); - } - return ''; -} - -function hostFromUri(uri: string): string { - if (!uri.trim()) return ''; - try { - const normalized = /^https?:\/\//i.test(uri) ? uri : `https://${uri}`; - return new URL(normalized).hostname || ''; - } catch { - return ''; - } -} - -function websiteIconUrl(host: string): string { - return `/icons/${encodeURIComponent(host)}/icon.png?fallback=404`; -} - export default function WebsiteIcon(props: WebsiteIconProps) { const host = useMemo(() => hostFromUri(firstCipherUri(props.cipher)), [props.cipher]); const src = host ? websiteIconUrl(host) : ''; diff --git a/webapp/src/components/vault/vault-page-helpers.tsx b/webapp/src/components/vault/vault-page-helpers.tsx index cb40360..69d6062 100644 --- a/webapp/src/components/vault/vault-page-helpers.tsx +++ b/webapp/src/components/vault/vault-page-helpers.tsx @@ -148,28 +148,7 @@ export function toBooleanFieldValue(raw: string): boolean { return v === '1' || v === 'true' || v === 'yes' || v === 'on'; } -export function firstCipherUri(cipher: Cipher): string { - const uris = cipher.login?.uris || []; - for (const uri of uris) { - const raw = uri.decUri || uri.uri || ''; - if (raw.trim()) return raw.trim(); - } - return ''; -} - -export function hostFromUri(uri: string): string { - if (!uri.trim()) return ''; - try { - const normalized = /^https?:\/\//i.test(uri) ? uri : `https://${uri}`; - return new URL(normalized).hostname || ''; - } catch { - return ''; - } -} - -export function websiteIconUrl(host: string): string { - return `/icons/${encodeURIComponent(host)}/icon.png?fallback=404`; -} +export { firstCipherUri, hostFromUri, websiteIconUrl } from '@/lib/website-utils'; export function createEmptyLoginUri(): VaultDraftLoginUri { return { uri: '', match: null, originalUri: '', extra: {} }; diff --git a/webapp/src/hooks/useVaultSendActions.ts b/webapp/src/hooks/useVaultSendActions.ts index cebc47b..4eee21b 100644 --- a/webapp/src/hooks/useVaultSendActions.ts +++ b/webapp/src/hooks/useVaultSendActions.ts @@ -118,7 +118,9 @@ export default function useVaultSendActions(options: UseVaultSendActionsOptions) if (options?.includeFolders) { tasks.push(Promise.resolve(refetchFolders())); } - void Promise.all(tasks).catch(() => undefined); + void Promise.all(tasks).catch((err) => { + console.warn('Background vault sync failed:', err); + }); }; async function decryptAndPatch(encrypted: Cipher) { diff --git a/webapp/src/lib/website-icon-cache.ts b/webapp/src/lib/website-icon-cache.ts index 73570b1..9be5bc7 100644 --- a/webapp/src/lib/website-icon-cache.ts +++ b/webapp/src/lib/website-icon-cache.ts @@ -72,7 +72,6 @@ export function preloadWebsiteIcon(host: string, src: string): Promise((resolve) => { const img = new Image(); img.decoding = 'async'; - img.loading = 'eager'; img.referrerPolicy = 'no-referrer'; img.onload = () => { markWebsiteIconLoaded(host); diff --git a/webapp/src/lib/website-utils.ts b/webapp/src/lib/website-utils.ts new file mode 100644 index 0000000..739b5aa --- /dev/null +++ b/webapp/src/lib/website-utils.ts @@ -0,0 +1,24 @@ +import type { Cipher } from './types'; + +export function firstCipherUri(cipher: Cipher): string { + const uris = cipher.login?.uris || []; + for (const uri of uris) { + const raw = uri.decUri || uri.uri || ''; + if (raw.trim()) return raw.trim(); + } + return ''; +} + +export function hostFromUri(uri: string): string { + if (!uri.trim()) return ''; + try { + const normalized = /^https?:\/\//i.test(uri) ? uri : `https://${uri}`; + return new URL(normalized).hostname || ''; + } catch { + return ''; + } +} + +export function websiteIconUrl(host: string): string { + return `/icons/${encodeURIComponent(host)}/icon.png?fallback=404`; +}