diff --git a/client/src/lib/components/Toggle.svelte b/client/src/lib/components/Toggle.svelte index a2b11d0d..0e7db628 100644 --- a/client/src/lib/components/Toggle.svelte +++ b/client/src/lib/components/Toggle.svelte @@ -3,10 +3,11 @@ label: string; checked?: boolean; } + import { uuid } from '$lib/uuid'; let { label, checked = $bindable(), class: extraClass = '', ...rest }: Props = $props(); - const id = `toggle-${crypto.randomUUID()}`; + const id = `toggle-${uuid()}`;
diff --git a/client/src/lib/utils.ts b/client/src/lib/utils.ts index 437f7601..08424dea 100644 --- a/client/src/lib/utils.ts +++ b/client/src/lib/utils.ts @@ -1,3 +1,5 @@ +import { uuid } from './uuid'; + declare const umami: { track: (event_name: string, data?: Record) => void; identify: (unique_id: string) => void; @@ -11,7 +13,7 @@ export function initializeAnalytics(): void { const umamiIdKey = 'mvw_uuid'; let uniqueId = localStorage.getItem(umamiIdKey); if (!uniqueId) { - uniqueId = crypto.randomUUID(); + uniqueId = uuid(); localStorage.setItem(umamiIdKey, uniqueId); } umami.identify(uniqueId); diff --git a/client/src/lib/uuid.ts b/client/src/lib/uuid.ts new file mode 100644 index 00000000..2f5f0b37 --- /dev/null +++ b/client/src/lib/uuid.ts @@ -0,0 +1,23 @@ +export function uuid(): string { + if (typeof globalThis !== 'undefined' && globalThis.crypto && typeof globalThis.crypto.randomUUID === 'function') { + return globalThis.crypto.randomUUID(); + } + + if (typeof globalThis !== 'undefined' && globalThis.crypto && typeof globalThis.crypto.getRandomValues === 'function') { + const bytes = globalThis.crypto.getRandomValues(new Uint8Array(16)); + // RFC4122 v4 + bytes[6] = (bytes[6] & 0x0f) | 0x40; + bytes[8] = (bytes[8] & 0x3f) | 0x80; + const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join(''); + return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`; + } + + // Last-resort fallback (not cryptographically secure) + const hexChars = '0123456789abcdef'; + const s: string[] = new Array(36); + for (let i = 0; i < 36; i++) s[i] = hexChars[(Math.random() * 16) | 0]; + s[14] = '4'; + s[19] = hexChars[(parseInt(s[19], 16) & 0x3) | 0x8]; + s[8] = s[13] = s[18] = s[23] = '-'; + return s.join(''); +}