Ctrl K
ComunidadGuías…

lib/avatar.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { createAvatar } from "@dicebear/core";
import * as lorelei from "@dicebear/lorelei";

/**
 * The default avatar of minddy.
 *
 * An account defaults to an opaque seed (`public.user_avatars`) whose portrait
 * is drawn here. The same seed produces the same portrait on every screen. An
 * imported image bypasses this generator in `components/user-avatar.tsx`, while
 * choosing a new Lorelei avatar replaces the seed and clears that image.
 *
 * The drawing comes from the `lorelei` style of DiceBear (CC0, Lisa Wischofsky): a
 * line face on a colored solid. It ONLY frames the head, which makes it
 * still readable at 22 px — where a bust shrinks to a blob. The rendering is in
 * `components/user-avatar.tsx`, the only place in the product that draws an avatar.
 */

/**
 * The funds, which DiceBear draws from according to the seed. A color wheel
 * in steps of approximately 24°, in the same vocabulary as the categories
 * (`lib/category-colors.ts`, Tailwind 500) but covering the entire circle.
 * Fifteen places: the longer the wheel, the fewer two accounts end up on
 * the same color. Without `#` — DiceBear wants bare hexadecimals.
 */
export const AVATAR_BACKGROUNDS = [
  "ef4444", // red
  "f97316", // orange
  "f59e0b", // amber
  "eab308", // yellow
  "84cc16", // lime
  "22c55e", // green
  "10b981", // emerald
  "14b8a6", // teal
  "06b6d4", // cyan
  "0ea5e9", // sky
  "3b82f6", // blue
  "6366f1", // indigo
  "8b5cf6", // violet
  "d946ef", // fuchsia
  "ec4899", // pink
];

/**
 * Portraits already calculated, per seed.
 *
 * Two reasons to keep this cache. First `createAvatar` rebuilds the whole
 * SVG on each call, and a board redraws the same people dozens of
 * times. Then the `<img>` then share the SAME string: the browser only
 * decodes one image, and the DOM only carries one more reference.
 *
 * Bulk purge beyond the ceiling: the number of people encountered in a
 * session is counted in tens, so we do not does not reach it — it is a safeguard
 * against a leak, not a cache policy to be refined.
 */
const portraits = new Map<string, string>();
const MAX_PORTRAITS = 500;

/** The portrait of a seed, in `data:` URI ready for a `<img>`. */
export function avatarDataUri(seed: string): string {
  const known = portraits.get(seed);
  if (known) return known;

  // Without the `size` option, the SVG only carries a `viewBox`: it therefore adapts to the
  // CSS size of the image, sharp at 16 px as at 64 px, and weighs less.
  const uri = createAvatar(lorelei, {
    seed,
    backgroundColor: AVATAR_BACKGROUNDS,
  }).toDataUri();

  if (portraits.size >= MAX_PORTRAITS) portraits.clear();
  portraits.set(seed, uri);
  return uri;
}