49a86c7cbf
The load balancer now returns a specific `Access-Control-Allow-Origin` instead of a wildcard, so credentials can be included by default. This enables `maxEntrySize` enforcement for storage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
98 lines
2.5 KiB
Plaintext
98 lines
2.5 KiB
Plaintext
importScripts("<%= javascript_url("turbo-offline-umd.min") %>")
|
|
|
|
// Documents - top-level navigation requests only
|
|
// We need `cache: "no-cache"` here to work around
|
|
// an annoying Safari PWA bug that predates offline mode
|
|
TurboOffline.addRule({
|
|
match: (request) => request.destination === "document",
|
|
except: /\/(edit|pin|watch|new)$/,
|
|
handler: TurboOffline.handlers.networkFirst({
|
|
cacheName: "main",
|
|
maxAge: 60 * 60 * 24 * 3,
|
|
networkTimeout: 3,
|
|
fetchOptions: { cache: "no-cache" },
|
|
maxEntrySize: 1024 * 1024
|
|
})
|
|
})
|
|
|
|
TurboOffline.addRule({
|
|
match: /\/assets\/.+[-\.][0-9a-f]+\.(js|css|svg|png|jpg|webp|woff2?|ico)$/,
|
|
handler: TurboOffline.handlers.cacheFirst({
|
|
cacheName: "assets",
|
|
maxAge: 60 * 60 * 24 * 7,
|
|
maxEntrySize: 1024 * 1024
|
|
})
|
|
})
|
|
|
|
TurboOffline.addRule({
|
|
match: /\/(boards|cards|users)\//,
|
|
except: /\/(edit|pin|watch|new)$/,
|
|
handler: TurboOffline.handlers.networkFirst({
|
|
cacheName: "main",
|
|
maxAge: 60 * 60 * 24 * 3,
|
|
networkTimeout: 2,
|
|
maxEntrySize: 1024 * 1024
|
|
})
|
|
})
|
|
|
|
TurboOffline.addRule({
|
|
match: /\/rails\/active_storage\//,
|
|
handler: TurboOffline.handlers.networkFirst({
|
|
cacheName: "storage",
|
|
maxAge: 60 * 60 * 24 * 7,
|
|
networkTimeout: 2,
|
|
maxEntrySize: 2 * 1024 * 1024, // 2MB covers about 95% of all Fizzy blobs
|
|
maxEntries: 500,
|
|
fetchOptions: { mode: "cors" }
|
|
})
|
|
})
|
|
|
|
// Everything else
|
|
TurboOffline.addRule({
|
|
except: /\/(service-worker\.js|edit|pin|watch|new)$/,
|
|
handler: TurboOffline.handlers.networkFirst({
|
|
cacheName: "main",
|
|
maxAge: 60 * 60 * 24,
|
|
networkTimeout: 3,
|
|
maxEntrySize: 1024 * 1024
|
|
})
|
|
})
|
|
|
|
self.addEventListener("activate", (event) => {
|
|
event.waitUntil(self.clients.claim())
|
|
})
|
|
|
|
TurboOffline.start()
|
|
|
|
|
|
self.addEventListener("push", (event) => {
|
|
const data = event.data.json()
|
|
event.waitUntil(Promise.all([ showNotification(data), updateBadgeCount(data.options) ]))
|
|
})
|
|
|
|
async function showNotification({ title, options }) {
|
|
return self.registration.showNotification(title, options)
|
|
}
|
|
|
|
async function updateBadgeCount({ data: { badge } }) {
|
|
return self.navigator.setAppBadge?.(badge || 0)
|
|
}
|
|
|
|
self.addEventListener("notificationclick", (event) => {
|
|
event.notification.close()
|
|
|
|
const url = new URL(event.notification.data.url, self.location.origin).href
|
|
event.waitUntil(openURL(url))
|
|
})
|
|
|
|
async function openURL(url) {
|
|
const clients = await self.clients.matchAll({ type: "window" })
|
|
const focused = clients.find((client) => client.focused)
|
|
|
|
if (focused) {
|
|
await focused.navigate(url)
|
|
} else {
|
|
await self.clients.openWindow(url)
|
|
}
|
|
}
|