Let each install pick its app icon

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]>
This commit is contained in:
2026-10-25 10:38:25 +01:00
co-authored by Claude Opus 5.5
parent 5a603bf61f
commit e462806438
36 changed files with 1190 additions and 68 deletions
+5
View File
@@ -11,6 +11,7 @@ import liveRelay from "./live-relay";
import enableForeignKeys from "./functions/backend/db/enable-foreign-keys";
import handleComputerProxy from "./functions/server/computers/handle-computer-proxy";
import handlePwaFile from "./functions/server/pwa/handle-pwa-file";
import handleInstallIconFile from "./functions/server/pwa/handle-install-icon-file";
import handleBuildInfo from "./functions/server/pwa/handle-build-info";
import handlePrecacheGate from "./functions/server/pwa/handle-precache-gate";
import grabPrecacheManifest from "./functions/server/pwa/grab-precache-manifest";
@@ -85,6 +86,10 @@ const server = Bun.serve({
if (pwa_file) return pwa_file;
const install_icon = await handleInstallIconFile({ pathname: url.pathname });
if (install_icon) return install_icon;
const build_info = handleBuildInfo({ pathname: url.pathname });
if (build_info) return build_info;