98 lines
3.2 KiB
TypeScript
98 lines
3.2 KiB
TypeScript
/// <reference lib="webworker" />
|
|
import { clientsClaim } from 'workbox-core'
|
|
import { NetworkFirst } from 'workbox-strategies';
|
|
import { cleanupOutdatedCaches, createHandlerBoundToURL, precacheAndRoute } from 'workbox-precaching'
|
|
import { registerRoute, NavigationRoute } from 'workbox-routing'
|
|
import { set } from 'idb-keyval'
|
|
|
|
const SW_VERSION = '1.0.5-debug';
|
|
|
|
console.log(`[SW] Initializing Version: ${SW_VERSION}`);
|
|
|
|
|
|
|
|
declare let self: ServiceWorkerGlobalScope
|
|
|
|
self.addEventListener('message', (event) => {
|
|
if (event.data && event.data.type === 'SKIP_WAITING') {
|
|
self.skipWaiting()
|
|
}
|
|
})
|
|
|
|
// self.__WB_MANIFEST is default injection point
|
|
precacheAndRoute(self.__WB_MANIFEST)
|
|
|
|
// clean old assets
|
|
cleanupOutdatedCaches()
|
|
|
|
|
|
|
|
// allow only fallback in dev: we don't want to cache everything
|
|
let allowlist: undefined | RegExp[]
|
|
if (location.hostname === 'localhost' || location.hostname.includes('127.0.0.1'))
|
|
allowlist = [/^\/$/]
|
|
|
|
// Handle Share Target POST requests
|
|
// MUST be registered before NavigationRoute to take precedence
|
|
registerRoute(
|
|
({ request, url }) => request.method === 'POST' && url.pathname === '/upload-share-target',
|
|
async ({ event, request }) => {
|
|
console.log('SW: Intercepting Share Target request!');
|
|
try {
|
|
const formData = await request.formData()
|
|
const files = formData.getAll('file')
|
|
const title = formData.get('title')
|
|
const text = formData.get('text')
|
|
const url = formData.get('url')
|
|
|
|
console.log('SW: Share data received:', { filesLen: files.length, title, text, url });
|
|
|
|
// Store in IDB
|
|
await set('share-target', { files, title, text, url, timestamp: Date.now() })
|
|
console.log('SW: Data stored in IDB');
|
|
|
|
// Redirect to the app with success status
|
|
return Response.redirect('/new?shared=true&sw_status=success', 303)
|
|
} catch (err) {
|
|
console.error('SW: Share Target Error:', err);
|
|
// Safe error string
|
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
return Response.redirect('/new?shared=true&sw_status=error&sw_error=' + encodeURIComponent(errMsg), 303);
|
|
}
|
|
},
|
|
'POST'
|
|
);
|
|
|
|
// Navigation handler: Prefer network to get server injection, fallback to index.html
|
|
const navigationHandler = async (params: any) => {
|
|
try {
|
|
const strategy = new NetworkFirst({
|
|
cacheName: 'pages',
|
|
networkTimeoutSeconds: 3, // Fallback to cache if network is slow
|
|
plugins: [
|
|
{
|
|
cacheWillUpdate: async ({ response }) => {
|
|
return response && response.status === 200 ? response : null;
|
|
}
|
|
}
|
|
]
|
|
});
|
|
return await strategy.handle(params);
|
|
} catch (error) {
|
|
return createHandlerBoundToURL('index.html')(params);
|
|
}
|
|
};
|
|
|
|
// to allow work offline
|
|
registerRoute(new NavigationRoute(
|
|
navigationHandler,
|
|
{
|
|
allowlist,
|
|
denylist: [/^\/upload-share-target/]
|
|
}
|
|
))
|
|
|
|
self.addEventListener('activate', () => {
|
|
clientsClaim();
|
|
});
|