// Local user preferences — title, bio, signature, avatar, default agent. // Persisted in localStorage; reactive across tabs. Identity (name, email) // is owned by the arcadia session, not this store — see ~/lib/session.ts. import { useEffect, useSyncExternalStore } from "react" export type Profile = { title: string bio: string signature: string avatarUrl: string defaultAgentId: string } export const DEFAULT_PROFILE: Profile = { title: "", bio: "", signature: "", avatarUrl: "", defaultAgentId: "", } 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 { title: typeof parsed.title === "string" ? parsed.title : DEFAULT_PROFILE.title, bio: typeof parsed.bio === "string" ? parsed.bio : DEFAULT_PROFILE.bio, signature: typeof parsed.signature === "string" ? parsed.signature : DEFAULT_PROFILE.signature, avatarUrl: typeof parsed.avatarUrl === "string" ? parsed.avatarUrl : DEFAULT_PROFILE.avatarUrl, defaultAgentId: typeof parsed.defaultAgentId === "string" ? parsed.defaultAgentId : DEFAULT_PROFILE.defaultAgentId, } } 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 }