- Unlinked, noindex page listing marker PNGs from public/set/markers (discovered at build time; filenames encode device/resolution/orientation) - Detects the current screen and offers the closest match first - One-tap full-screen viewer: wake lock, hidden controls, full grid/edges toggle, fill vs fit by aspect, back button closes, deep links via hash - Offline service worker + home-screen manifest for iPhone full screen - Marketing chrome moved into an (site) route group so /set has none Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "Two Tales VFX Screen Markers",
|
||||
"short_name": "Markers",
|
||||
"start_url": "/set/",
|
||||
"scope": "/set/",
|
||||
"display": "fullscreen",
|
||||
"orientation": "any",
|
||||
"background_color": "#000000",
|
||||
"theme_color": "#000000",
|
||||
"icons": [
|
||||
{ "src": "/icon.png", "sizes": "512x512", "type": "image/png" },
|
||||
{ "src": "/apple-icon.png", "sizes": "180x180", "type": "image/png" }
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 53 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 51 KiB |
@@ -0,0 +1,54 @@
|
||||
// Offline cache for /set (screen markers). Crews often have no signal on set:
|
||||
// once the page has loaded once, it and every marker image work offline.
|
||||
const CACHE = "ttvfx-set-v1";
|
||||
|
||||
self.addEventListener("install", (event) => {
|
||||
event.waitUntil(caches.open(CACHE).then((c) => c.addAll(["/set/"])).then(() => self.skipWaiting()));
|
||||
});
|
||||
|
||||
self.addEventListener("activate", (event) => {
|
||||
event.waitUntil(
|
||||
caches
|
||||
.keys()
|
||||
.then((keys) => Promise.all(keys.filter((k) => k.startsWith("ttvfx-set-") && k !== CACHE).map((k) => caches.delete(k))))
|
||||
.then(() => self.clients.claim()),
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener("fetch", (event) => {
|
||||
const req = event.request;
|
||||
if (req.method !== "GET") return;
|
||||
const url = new URL(req.url);
|
||||
if (url.origin !== self.location.origin) return;
|
||||
|
||||
// Page: network first so updates arrive, cached copy when offline
|
||||
if (req.mode === "navigate") {
|
||||
event.respondWith(
|
||||
fetch(req)
|
||||
.then((res) => {
|
||||
const copy = res.clone();
|
||||
caches.open(CACHE).then((c) => c.put("/set/", copy));
|
||||
return res;
|
||||
})
|
||||
.catch(() => caches.match("/set/")),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Marker images, build assets, fonts, icons: cache first
|
||||
if (url.pathname.startsWith("/set/") || url.pathname.startsWith("/_next/") || /\.(png|woff2|webmanifest)$/.test(url.pathname)) {
|
||||
event.respondWith(
|
||||
caches.match(req).then(
|
||||
(hit) =>
|
||||
hit ||
|
||||
fetch(req).then((res) => {
|
||||
if (res.ok) {
|
||||
const copy = res.clone();
|
||||
caches.open(CACHE).then((c) => c.put(req, copy));
|
||||
}
|
||||
return res;
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||