- Add AccountSwitcher component for managing user accounts with UI for switching, adding, and logging out. - Create account state manager to handle snapshots of account-specific states for efficient switching. - Introduce utility functions for account management, including ID generation and avatar color assignment. - Implement Zustand store for account management, supporting addition, removal, and state retrieval of accounts.
60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
/**
|
|
* Utilities for multi-account support:
|
|
* - Account ID generation
|
|
* - Deterministic avatar colors
|
|
* - Account-scoped localStorage keys
|
|
*/
|
|
|
|
/** Generate a unique, deterministic account ID from username and server URL */
|
|
export function generateAccountId(username: string, serverUrl: string): string {
|
|
const host = new URL(serverUrl).hostname;
|
|
return `${username}@${host}`;
|
|
}
|
|
|
|
/** Deterministic avatar/accent color from an email string */
|
|
export function generateAvatarColor(email: string): string {
|
|
let hash = 0;
|
|
for (let i = 0; i < email.length; i++) {
|
|
hash = ((hash << 5) - hash + email.charCodeAt(i)) | 0;
|
|
}
|
|
// 12 distinct, accessible hues
|
|
const colors = [
|
|
'#2563eb', // blue
|
|
'#7c3aed', // violet
|
|
'#db2777', // pink
|
|
'#dc2626', // red
|
|
'#ea580c', // orange
|
|
'#d97706', // amber
|
|
'#65a30d', // lime
|
|
'#16a34a', // green
|
|
'#0d9488', // teal
|
|
'#0891b2', // cyan
|
|
'#6366f1', // indigo
|
|
'#9333ea', // purple
|
|
];
|
|
return colors[Math.abs(hash) % colors.length];
|
|
}
|
|
|
|
/** Get initials for an avatar from a display name or email */
|
|
export function getInitials(name: string, email?: string): string {
|
|
if (name) {
|
|
const parts = name.trim().split(/\s+/);
|
|
if (parts.length >= 2) {
|
|
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
}
|
|
return parts[0][0]?.toUpperCase() ?? '?';
|
|
}
|
|
if (email) {
|
|
return email[0]?.toUpperCase() ?? '?';
|
|
}
|
|
return '?';
|
|
}
|
|
|
|
/** Build an account-scoped localStorage key */
|
|
export function getAccountScopedKey(baseKey: string, accountId: string): string {
|
|
return `${baseKey}::${accountId}`;
|
|
}
|
|
|
|
/** Maximum number of accounts allowed */
|
|
export const MAX_ACCOUNTS = 5;
|