import { browser } from "$app/env";
import { SvelteMap } from "svelte/reactivity";
import { avatarWidths } from "#lib/avatarWidths.ts";
const VERSIONS_KEY = "tangled.avatarVersions";
const VERSION_TTL_MS = 12 * 60 * 60 * 1000;
const versions = new SvelteMap<string, string>();
type StoredVersions = Record<string, { version: string; at: number }>;
const readStored = (): StoredVersions => {
try {
const parsed: unknown = JSON.parse(localStorage.getItem(VERSIONS_KEY) ?? "{}");
return parsed && typeof parsed === "object" ? (parsed as StoredVersions) : {};
} catch {
return {};
}
};
const writeStored = (stored: StoredVersions): boolean => {
try {
localStorage.setItem(VERSIONS_KEY, JSON.stringify(stored));
return true;
} catch {
return false;
}
};
export const restoreAvatarVersions = (): void => {
if (!browser) return;
const now = Date.now();
for (const [did, entry] of Object.entries(readStored())) {
if (typeof entry?.version === "string" && now - entry.at < VERSION_TTL_MS) {
versions.set(did, entry.version);
}
}
};
export const bumpAvatar = (did: string, version: string = String(Date.now())): void => {
versions.set(did, version);
if (!browser) return;
const now = Date.now();
const kept = Object.fromEntries(
Object.entries(readStored()).filter(([, entry]) => now - entry.at < VERSION_TTL_MS)
);
writeStored({ ...kept, [did]: { version, at: now } });
};
export const avatarWidthFor = (px: number): number =>
avatarWidths.find((width) => width >= px * 2) ?? avatarWidths[avatarWidths.length - 1];
// the service wants signed urls and the secret is server side, so this points
// at the route that signs
export const avatarUrl = (
did: string,
width?: number,
format?: "webp" | "jpeg" | "png",
cid?: string
): string => {
// cids all start the same way. the end tells them apart
const version = versions.get(did) ?? cid?.slice(-12);
const query = new URLSearchParams({
...(width ? { size: String(width) } : {}),
...(format ? { format } : {}),
...(version ? { v: version } : {})
}).toString();
return `/avatar/${encodeURIComponent(did)}${query ? `?${query}` : ""}`;
};