mission-control/lib/avatar.ts
OpenClaw Bot c1c01bd21e feat: merge Gantt Board into Mission Control
- Add Projects page with Sprint Board and Backlog views
- Copy SprintBoard and BacklogView components to components/gantt/
- Copy useTaskStore for project/task/sprint management
- Add API routes for task persistence with SQLite
- Add UI components: dialog, select, table, textarea
- Add avatar and attachment utilities
- Update sidebar with Projects navigation link
- Remove static export config to support API routes
- Add dist to .gitignore
2026-02-20 18:49:52 -06:00

59 lines
1.8 KiB
TypeScript

const AVATAR_PALETTES = [
["#1f2937", "#3b82f6"],
["#0f172a", "#22c55e"],
["#172554", "#06b6d4"],
["#3f1d2e", "#ec4899"],
["#1f2937", "#f59e0b"],
["#111827", "#a855f7"],
["#052e16", "#14b8a6"],
["#3f3f46", "#e11d48"],
] as const;
export function getInitials(name?: string): string {
return (name || "User")
.split(/\s+/)
.filter(Boolean)
.slice(0, 2)
.map((part) => part[0]?.toUpperCase() || "")
.join("") || "U";
}
function hashSeed(seed: string): number {
let hash = 0;
for (let i = 0; i < seed.length; i += 1) {
hash = (hash * 31 + seed.charCodeAt(i)) >>> 0;
}
return hash;
}
export function generateAvatarDataUrl(seed: string, name?: string, paletteOffset = 0): string {
const safeSeed = seed || "default";
const hash = hashSeed(safeSeed);
const paletteIndex = (hash + paletteOffset) % AVATAR_PALETTES.length;
const palette = AVATAR_PALETTES[paletteIndex];
const initials = getInitials(name);
const svg = `
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 128 128">
<defs>
<linearGradient id="g" x1="0" y1="0" x2="1" y2="1">
<stop offset="0%" stop-color="${palette[0]}"/>
<stop offset="100%" stop-color="${palette[1]}"/>
</linearGradient>
</defs>
<rect width="128" height="128" fill="url(#g)"/>
<circle cx="64" cy="64" r="52" fill="rgba(255,255,255,0.12)"/>
<text x="64" y="78" text-anchor="middle" font-family="Arial, sans-serif" font-size="44" font-weight="700" fill="white">${initials}</text>
</svg>`;
return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
}
export function buildAvatarPresets(seed: string, name?: string, count = 6): string[] {
const urls: string[] = [];
for (let i = 0; i < count; i += 1) {
urls.push(generateAvatarDataUrl(`${seed}:${i}`, name, i));
}
return urls;
}