Settings > General gets an App icon (super admin): one of the seven stones, or an uploaded image with the picked stone as a top-left corner mark (inside a round launcher's crop, clear of the browser's badge), previewed in both launcher crops before saving. Uploads are decoded and cropped to a stored square (no SVG); the set is drawn into DATA_DIR/install-icon/<version>/ and served publicly and immutable. The manifest, head icon links and push notifications point at it; the ember stone keeps the stock icons. The generator shares the icon renderer. Co-Authored-By: Claude Opus 5.5 <[email protected]>
21 lines
780 B
TypeScript
21 lines
780 B
TypeScript
import { z } from "zod";
|
|
import { BotHues } from "@/src/dict/bot-dict";
|
|
import { PwaInstallIconModes, PwaInstallNameMaxLength } from "@/src/data/pwa-data";
|
|
|
|
export const SaveInstallNameRequestSchema = z.object({
|
|
install_name: z.string().trim().max(PwaInstallNameMaxLength),
|
|
});
|
|
|
|
export const SaveInstallIconRequestSchema = z.object({
|
|
mode: z.enum(PwaInstallIconModes),
|
|
stone: z.enum(BotHues.map((hue) => hue.value) as [string, ...string[]], "Pick a stone"),
|
|
mark: z.boolean(),
|
|
/**
|
|
* A newly picked image as a base64 data URL; omitted to keep the
|
|
* stored one.
|
|
*/
|
|
data_url: z.string().startsWith("data:image/", "Send the image as a data URL").nullish(),
|
|
});
|
|
|
|
export type SaveInstallIconRequest = z.infer<typeof SaveInstallIconRequestSchema>;
|