// Local mirror of the resolved avatar URL, so the appbar can render the // avatar before the profile fetch resolves on next mount. The real // profile (name, email, bio, phone, location, timezone, avatar) is // server-backed — see ~/lib/arcadia/profiles.ts. import { useEffect, useSyncExternalStore } from "react" export type Profile = { avatarUrl: string } export const DEFAULT_PROFILE: Profile = { avatarUrl: "", } const STORAGE_KEY = "crema.profile" const CHANGE_EVENT = "crema:profile-change" function readFromStorage(): Profile { if (typeof window === "undefined") return DEFAULT_PROFILE try { const raw = localStorage.getItem(STORAGE_KEY) if (!raw) return DEFAULT_PROFILE const parsed = JSON.parse(raw) as Partial return { avatarUrl: typeof parsed.avatarUrl === "string" ? parsed.avatarUrl : DEFAULT_PROFILE.avatarUrl, } } catch { return DEFAULT_PROFILE } } export function loadProfile(): Profile { return readFromStorage() } export function saveProfile(next: Profile) { if (typeof window === "undefined") return localStorage.setItem(STORAGE_KEY, JSON.stringify(next)) window.dispatchEvent(new CustomEvent(CHANGE_EVENT)) } export function resetProfile() { saveProfile(DEFAULT_PROFILE) } export function profileInitials(name: string): string { const words = name.trim().split(/\s+/).filter(Boolean) if (words.length === 0) return "?" if (words.length === 1) return words[0].slice(0, 2).toUpperCase() return (words[0][0] + words[words.length - 1][0]).toUpperCase() } let cached: Profile | null = null function subscribe(cb: () => void): () => void { const onChange = () => { cached = null cb() } window.addEventListener(CHANGE_EVENT, onChange) window.addEventListener("storage", (e) => { if (e.key === STORAGE_KEY) onChange() }) return () => { window.removeEventListener(CHANGE_EVENT, onChange) } } function getSnapshot(): Profile { if (!cached) cached = readFromStorage() return cached } function getServerSnapshot(): Profile { return DEFAULT_PROFILE } export function useProfile(): Profile { const value = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) useEffect(() => { cached = null }, []) return value }