feat(t5): App-Icons, Manifest und Offline-Cache v5 (T5a A9)
- Honigzelle auf Tinte als Master-SVG; scripts/generate-icons.mjs erzeugt any/maskable 192/512, Monochrom 512, drei Shortcut-Icons, Apple-Icon und favicon.ico (16/32/48, ICO-Container von Hand) byte-gleich bei jedem Lauf. - manifest.ts exakt nach Spec 12.3, Farben gleich dem hellen --background. - Service Worker: SHELL_CACHE apicore-shell-v5, Icons im Shell-Cache; ein fehlendes Icon hält das Vorladen der Seiten nicht auf. - Proxy-Matcher: nur echte Icon-Dateien (icons/*.png) ohne Sicherheits-Header, Punkte maskiert. - BrandMark-Deckel mittig (linke Kante 18.8). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
No files matched your search
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<!-- ApiCore mark (spec 12.1): a capped honeycomb cell. Master for scripts/generate-icons.mjs;
|
||||
the geometry equals BRAND_CELL_PATHS in src/components/brand-mark.tsx. -->
|
||||
<path id="cell" d="M32 4 L56 18 V46 L32 60 L8 46 V18 Z" fill="#f0b13f" stroke="#2c1b0f" stroke-width="3.84" stroke-linejoin="round" />
|
||||
<path id="lid" d="M32 13.6 L45.2 21.3 V36.7 L32 44.4 L18.8 36.7 V21.3 Z" fill="#f9d280" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 477 B |
@@ -1,8 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<rect width="512" height="512" rx="96" fill="#0a0a0a" />
|
||||
<g fill="#f5c518">
|
||||
<rect x="156" y="176" width="200" height="52" rx="10" />
|
||||
<rect x="156" y="242" width="200" height="52" rx="10" />
|
||||
<rect x="156" y="308" width="200" height="52" rx="10" />
|
||||
</g>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><rect width="512" height="512" rx="112.64" fill="#2c1b0f"/><g transform="translate(51.2 51.2) scale(6.4)"><path d="M32 4 L56 18 V46 L32 60 L8 46 V18 Z" fill="#f0b13f" stroke="#2c1b0f" stroke-width="3.84" stroke-linejoin="round" /><path d="M32 13.6 L45.2 21.3 V36.7 L32 44.4 L18.8 36.7 V21.3 Z" fill="#f9d280" /></g></svg>
|
||||
|
Before Width: | Height: | Size: 340 B After Width: | Height: | Size: 384 B |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 9.9 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 620 B |
|
After Width: | Height: | Size: 1.9 KiB |
@@ -37,11 +37,28 @@ const {
|
||||
buildAssetsToPrune,
|
||||
} = self.ApiCoreSwRoutes;
|
||||
|
||||
const SHELL_CACHE = "apicore-shell-v4";
|
||||
// v5: new app icons and colour tokens (T5 spec 12.3) reach installed apps.
|
||||
const SHELL_CACHE = "apicore-shell-v5";
|
||||
// v2: v1 could hold answers this version never keeps (exports, downloads).
|
||||
const DATA_CACHE = "apicore-data-v2";
|
||||
const KNOWN_CACHES = [SHELL_CACHE, DATA_CACHE];
|
||||
|
||||
// The manifest icons (src/app/manifest.ts; sw.spec checks that every one of
|
||||
// them is kept): kept with the shell, so an offline start and the shortcuts
|
||||
// show the app's own icons. Not the favicon: Next links it as
|
||||
// /favicon.ico?<hash>, so a cached /favicon.ico would never answer it.
|
||||
const SHELL_ICONS = [
|
||||
"/icon.svg",
|
||||
"/icons/icon-192.png",
|
||||
"/icons/icon-512.png",
|
||||
"/icons/maskable-192.png",
|
||||
"/icons/maskable-512.png",
|
||||
"/icons/monochrome-512.png",
|
||||
"/icons/shortcut-inspection-96.png",
|
||||
"/icons/shortcut-varroa-96.png",
|
||||
"/icons/shortcut-today-96.png",
|
||||
];
|
||||
|
||||
// Same budget as every request of the app (lib/http/fetch-with-timeout.ts).
|
||||
const ASSET_TIMEOUT_MS = 4000;
|
||||
const RUNTIME_CONFIG_PATH = "/api/runtime-config";
|
||||
@@ -453,6 +470,7 @@ async function warmShell() {
|
||||
}
|
||||
}
|
||||
await keepRuntimeConfig(cache).catch(() => undefined);
|
||||
await keepIcons(cache);
|
||||
// Only with the full picture of the current build may old assets go.
|
||||
if (allPagesKept) {
|
||||
await pruneOldBuildAssets(cache, [...assets]);
|
||||
@@ -497,6 +515,21 @@ async function keepAsset(cache, asset) {
|
||||
await cache.put(asset, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the icons fresh on every warm-up (their URLs carry no build hash).
|
||||
* A missing icon is skipped; the pages do not depend on it.
|
||||
*/
|
||||
async function keepIcons(cache) {
|
||||
await Promise.allSettled(
|
||||
SHELL_ICONS.map(async (icon) => {
|
||||
const response = await fetch(icon, { cache: "no-cache" });
|
||||
if (isGoodAnswer(response)) {
|
||||
await cache.put(icon, response);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
async function keepRuntimeConfig(cache) {
|
||||
const response = await fetch(RUNTIME_CONFIG_PATH, { cache: "no-cache" });
|
||||
if (isGoodAnswer(response)) {
|
||||
|
||||