b6f8a0c390
useEventsDispatcher subscribes to player.current/state via \$effect: on first transition to playing for a new track, POSTs play_started and caches the id; on track-id change while a play is open, closes the prior row as play_skipped; on natural completion (state playing→paused with position >= duration > 0), POSTs play_ended; on pagehide, navigator.sendBeacon fires a final play_skipped. Stable per-tab client_id from sessionStorage.
14 lines
382 B
TypeScript
14 lines
382 B
TypeScript
const KEY = 'minstrel.client_id';
|
|
|
|
export function getOrCreateClientId(): string {
|
|
try {
|
|
const existing = sessionStorage.getItem(KEY);
|
|
if (existing) return existing;
|
|
} catch {
|
|
// sessionStorage unavailable (non-browser env). Generate ephemerally.
|
|
}
|
|
const id = crypto.randomUUID();
|
|
try { sessionStorage.setItem(KEY, id); } catch { /* ignore */ }
|
|
return id;
|
|
}
|