Files
ExcaliDash/frontend/src/utils/identity.ts
T

128 lines
4.1 KiB
TypeScript

export interface UserIdentity {
id: string;
name: string;
initials: string;
color: string;
}
const TRANSFORMERS = [
{ name: "Optimus Prime", initials: "OP" },
{ name: "Megatron", initials: "ME" },
{ name: "Starscream", initials: "ST" },
{ name: "Bumblebee", initials: "BB" },
{ name: "Ultra Magnus", initials: "UM" },
{ name: "Shockwave", initials: "SH" },
{ name: "Soundwave", initials: "SW" },
{ name: "Ironhide", initials: "IR" },
{ name: "Ratchet", initials: "RA" },
{ name: "Prowl", initials: "PR" },
{ name: "Jazz", initials: "JA" },
{ name: "Hot Rod", initials: "HR" },
{ name: "Alpha Trion", initials: "AT" },
{ name: "Wheeljack", initials: "WH" },
{ name: "Sideswipe", initials: "SI" },
{ name: "Sunstreaker", initials: "SU" },
{ name: "Inferno", initials: "IN" },
{ name: "Grapple", initials: "GR" },
{ name: "Blaster", initials: "BL" },
{ name: "Perceptor", initials: "PE" },
{ name: "Trailbreaker", initials: "TR" },
{ name: "Cosmos", initials: "CO" },
{ name: "Warpath", initials: "WA" },
{ name: "Powerglide", initials: "PO" },
{ name: "Arcee", initials: "AR" },
{ name: "Springer", initials: "SP" },
{ name: "Kup", initials: "KU" },
{ name: "Blurr", initials: "BU" },
{ name: "Grimlock", initials: "GL" },
{ name: "Swoop", initials: "WO" },
{ name: "Skywarp", initials: "SK" },
{ name: "Thundercracker", initials: "TH" },
{ name: "Ramjet", initials: "AM" },
{ name: "Cyclonus", initials: "CY" },
{ name: "Scourge", initials: "SC" },
{ name: "Galvatron", initials: "GA" },
{ name: "Astrotrain", initials: "AS" },
{ name: "Blitzwing", initials: "BZ" },
{ name: "Rumble", initials: "RU" },
{ name: "Frenzy", initials: "FR" },
{ name: "Laserbeak", initials: "LA" },
{ name: "Ravage", initials: "RV" },
{ name: "Unicron", initials: "UN" },
{ name: "Devastator", initials: "DE" },
{ name: "Menasor", initials: "MN" },
{ name: "Bruticus", initials: "BR" },
{ name: "Motormaster", initials: "MO" },
{ name: "Scrapper", initials: "CR" },
{ name: "Mixmaster", initials: "MA" },
{ name: "Bonecrusher", initials: "BO" },
{ name: "Hook", initials: "HO" },
{ name: "Vortex", initials: "VO" },
{ name: "Swindle", initials: "WI" },
];
const COLORS = [
"#ef4444", // red-500
"#f97316", // orange-500
"#f59e0b", // amber-500
"#84cc16", // lime-500
"#22c55e", // green-500
"#10b981", // emerald-500
"#14b8a6", // teal-500
"#06b6d4", // cyan-500
"#0ea5e9", // sky-500
"#3b82f6", // blue-500
"#6366f1", // indigo-500
"#8b5cf6", // violet-500
"#a855f7", // purple-500
"#d946ef", // fuchsia-500
"#ec4899", // pink-500
"#f43f5e", // rose-500
];
const generateClientId = (): string => {
const cryptoObj: Crypto | undefined =
typeof globalThis !== "undefined"
? globalThis.crypto || (globalThis as any).msCrypto
: undefined;
if (cryptoObj?.randomUUID) {
return cryptoObj.randomUUID();
}
if (cryptoObj?.getRandomValues) {
const bytes = new Uint8Array(16);
cryptoObj.getRandomValues(bytes);
bytes[6] = (bytes[6] & 0x0f) | 0x40; // RFC 4122 variant
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, "0"));
return `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex
.slice(6, 8)
.join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
}
// Final fallback for very old browsers; uniqueness window-scoped only.
return `id-${Date.now().toString(16)}-${Math.random().toString(16).slice(2)}`;
};
export const getUserIdentity = (): UserIdentity => {
const stored = localStorage.getItem("excalidash-user-id");
if (stored) {
return JSON.parse(stored);
}
const randomTransformer =
TRANSFORMERS[Math.floor(Math.random() * TRANSFORMERS.length)];
const randomColor = COLORS[Math.floor(Math.random() * COLORS.length)];
const identity: UserIdentity = {
id: generateClientId(),
name: randomTransformer.name,
initials: randomTransformer.initials,
color: randomColor,
};
localStorage.setItem("excalidash-user-id", JSON.stringify(identity));
return identity;
};