File size: 1,325 Bytes
76fc93a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | /**
* Collab user identity: shared types, color hashing and the localStorage
* fallback used when the viewer is not authenticated yet.
*/
export interface CollabUser {
name: string;
color: string;
avatarUrl?: string;
}
const COLORS = [
"#958DF1", "#F98181", "#FBBC88", "#FAF594",
"#70CFF8", "#94FADB", "#B9F18D", "#C4B5FD",
];
/** Deterministic color from a name, used for cursors and author chips. */
export function colorFromName(name: string): string {
let hash = 0;
for (let i = 0; i < name.length; i++) hash = (hash * 31 + name.charCodeAt(i)) | 0;
return COLORS[Math.abs(hash) % COLORS.length];
}
const STORAGE_KEY = "collab-editor:fallback-user";
const FALLBACK_NAMES = ["Alice", "Bob", "Carol", "Dave", "Eve", "Frank", "Grace", "Heidi"];
/**
* Pick (and persist) a random pseudonymous user when the session is anonymous.
* Stored in localStorage so a refresh keeps the same name/color.
*/
export function stableFallbackUser(): CollabUser {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored) {
try { return JSON.parse(stored); } catch { /* fall through */ }
}
const name = FALLBACK_NAMES[Math.floor(Math.random() * FALLBACK_NAMES.length)];
const user = { name, color: colorFromName(name) };
localStorage.setItem(STORAGE_KEY, JSON.stringify(user));
return user;
}
|