From b7abc5ee540c032e6464d074f07f194a8af63ccb Mon Sep 17 00:00:00 2001 From: fly_mc Date: Mon, 21 Oct 2024 01:37:52 +0800 Subject: [PATCH] try: fix sw cache --- packages/sw/src/sw.ts | 354 +++++++++++++++++++++--------------------- 1 file changed, 174 insertions(+), 180 deletions(-) diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts index a6e308866..0e8fae946 100644 --- a/packages/sw/src/sw.ts +++ b/packages/sw/src/sw.ts @@ -12,209 +12,203 @@ import { createEmptyNotification, createNotification } from '@/scripts/create-no import { swLang } from '@/scripts/lang.js'; import * as swos from '@/scripts/operations.js'; -globalThis.addEventListener('install', () => { - // ev.waitUntil(globalThis.skipWaiting()); +const CACHE_NAME = 'pari-cache-0'; +const urlsToCache = [ + '/', + '/emoji', + '/twemoji', + '/fluent-emoji', + '/vite', +]; + +globalThis.addEventListener('install', (event) => { + event.waitUntil( + caches.open(CACHE_NAME) + .then((cache) => cache.addAll(urlsToCache)) + ); }); -globalThis.addEventListener('activate', ev => { - ev.waitUntil( - caches.keys() - .then(cacheNames => Promise.all( - cacheNames - .filter((v) => v !== swLang.cacheName) - .map(name => caches.delete(name)), - )) - .then(() => globalThis.clients.claim()), - ); +globalThis.addEventListener('activate', (event) => { + const cacheWhitelist = [CACHE_NAME, swLang.cacheName]; + event.waitUntil( + caches.keys().then((cacheNames) => { + return Promise.all( + cacheNames.map((cacheName) => { + if (cacheWhitelist.indexOf(cacheName) === -1) { + return caches.delete(cacheName); + } + }) + ); + }).then(() => globalThis.clients.claim()) + ); +}); + +globalThis.addEventListener('fetch', (event) => { + event.respondWith( + caches.match(event.request) + .then((response) => { + if (response) { + return response; + } + return fetch(event.request).then( + (response) => { + if(!response || response.status !== 200 || response.type !== 'basic') { + return response; + } + + const responseToCache = response.clone(); + + caches.open(CACHE_NAME) + .then((cache) => { + cache.put(event.request, responseToCache); + }); + + return response; + } + ); + }) + ); }); async function offlineContentHTML() { - const i18n = await (swLang.i18n ?? swLang.fetchLocale()) as Partial>; - const messages = { - title: i18n.ts?._offlineScreen.title ?? 'Offline - Could not connect to server', - header: i18n.ts?._offlineScreen.header ?? 'Could not connect to server', - reload: i18n.ts?.reload ?? 'Reload', - }; + const i18n = await (swLang.i18n ?? swLang.fetchLocale()) as Partial>; + const messages = { + title: i18n.ts?._offlineScreen.title ?? 'Offline - Could not connect to server', + header: i18n.ts?._offlineScreen.header ?? 'Could not connect to server', + reload: i18n.ts?.reload ?? 'Reload', + }; - return `${messages.title}
${messages.header}
v${_VERSION_}
`; + return `${messages.title}
${messages.header}
v${_VERSION_}
`; } -globalThis.addEventListener('fetch', ev => { - let isHTMLRequest = false; - if (ev.request.headers.get('sec-fetch-dest') === 'document') { - isHTMLRequest = true; - } else if (ev.request.headers.get('accept')?.includes('/html')) { - isHTMLRequest = true; - } else if (ev.request.url.endsWith('/')) { - isHTMLRequest = true; - } - - if (!isHTMLRequest) return; - ev.respondWith( - fetch(ev.request) - .catch(async () => { - const html = await offlineContentHTML(); - return new Response(html, { - status: 200, - headers: { - 'content-type': 'text/html', - }, - }); - }), - ); -}); - globalThis.addEventListener('push', ev => { - // クライアント取得 - ev.waitUntil(globalThis.clients.matchAll({ - includeUncontrolled: true, - type: 'window', - }).then(async () => { - const data: PushNotificationDataMap[keyof PushNotificationDataMap] = ev.data?.json(); + ev.waitUntil(globalThis.clients.matchAll({ + includeUncontrolled: true, + type: 'window', + }).then(async () => { + const data: PushNotificationDataMap[keyof PushNotificationDataMap] = ev.data?.json(); - switch (data.type) { - // case 'driveFileCreated': - case 'notification': - case 'unreadAntennaNote': - // 1日以上経過している場合は無視 - if (Date.now() - data.dateTime > 1000 * 60 * 60 * 24) break; + switch (data.type) { + case 'notification': + case 'unreadAntennaNote': + if (Date.now() - data.dateTime > 1000 * 60 * 60 * 24) break; + return createNotification(data); + case 'readAllNotifications': + await globalThis.registration.getNotifications() + .then(notifications => notifications.forEach(n => n.tag !== 'read_notification' && n.close())); + break; + } - return createNotification(data); - case 'readAllNotifications': - await globalThis.registration.getNotifications() - .then(notifications => notifications.forEach(n => n.tag !== 'read_notification' && n.close())); - break; - } - - await createEmptyNotification(); - return; - })); + await createEmptyNotification(); + return; + })); }); globalThis.addEventListener('notificationclick', (ev: ServiceWorkerGlobalScopeEventMap['notificationclick']) => { - ev.waitUntil((async (): Promise => { - if (_DEV_) { - console.log('notificationclick', ev.action, ev.notification.data); - } + ev.waitUntil((async (): Promise => { + const { action, notification } = ev; + const data: PushNotificationDataMap[keyof PushNotificationDataMap] = notification.data ?? {}; + const { userId: loginId } = data; + let client: WindowClient | null = null; - const { action, notification } = ev; - const data: PushNotificationDataMap[keyof PushNotificationDataMap] = notification.data ?? {}; - const { userId: loginId } = data; - let client: WindowClient | null = null; + switch (data.type) { + case 'notification': + switch (action) { + case 'follow': + if ('userId' in data.body) await swos.api('following/create', loginId, { userId: data.body.userId }); + break; + case 'showUser': + if ('user' in data.body) client = await swos.openUser(Misskey.acct.toString(data.body.user), loginId); + break; + case 'reply': + if ('note' in data.body) client = await swos.openPost({ reply: data.body.note }, loginId); + break; + case 'renote': + if ('note' in data.body) await swos.api('notes/create', loginId, { renoteId: data.body.note.id }); + break; + case 'accept': + if (data.body.type === 'receiveFollowRequest') { + await swos.api('following/requests/accept', loginId, { userId: data.body.userId }); + } + break; + case 'reject': + if (data.body.type === 'receiveFollowRequest') { + await swos.api('following/requests/reject', loginId, { userId: data.body.userId }); + } + break; + case 'showFollowRequests': + client = await swos.openClient('push', '/my/follow-requests', loginId); + break; + default: + if (data.body.type === 'receiveFollowRequest') { + client = await swos.openClient('push', '/my/follow-requests', loginId); + } else if (data.body.type === 'reaction') { + client = await swos.openNote(data.body.note.id, loginId); + } else if ('note' in data.body) { + client = await swos.openNote(data.body.note.id, loginId); + } else if ('user' in data.body) { + client = await swos.openUser(Misskey.acct.toString(data.body.user), loginId); + } + break; + } + break; + case 'unreadAntennaNote': + client = await swos.openAntenna(data.body.antenna.id, loginId); + break; + default: + if (action === 'markAllAsRead') { + await globalThis.registration.getNotifications() + .then(notifications => notifications.forEach(n => n.tag !== 'read_notification' && n.close())); + await get[]>('accounts').then(accounts => { + return Promise.all((accounts ?? []).map(async account => { + await swos.sendMarkAllAsRead(account.id); + })); + }); + } else if (action === 'settings') { + client = await swos.openClient('push', '/settings/notifications', loginId); + } + } - switch (data.type) { - case 'notification': - switch (action) { - case 'follow': - if ('userId' in data.body) await swos.api('following/create', loginId, { userId: data.body.userId }); - break; - case 'showUser': - if ('user' in data.body) client = await swos.openUser(Misskey.acct.toString(data.body.user), loginId); - break; - case 'reply': - if ('note' in data.body) client = await swos.openPost({ reply: data.body.note }, loginId); - break; - case 'renote': - if ('note' in data.body) await swos.api('notes/create', loginId, { renoteId: data.body.note.id }); - break; - case 'accept': - switch (data.body.type) { - case 'receiveFollowRequest': - await swos.api('following/requests/accept', loginId, { userId: data.body.userId }); - break; - } - break; - case 'reject': - switch (data.body.type) { - case 'receiveFollowRequest': - await swos.api('following/requests/reject', loginId, { userId: data.body.userId }); - break; - } - break; - case 'showFollowRequests': - client = await swos.openClient('push', '/my/follow-requests', loginId); - break; - default: - switch (data.body.type) { - case 'receiveFollowRequest': - client = await swos.openClient('push', '/my/follow-requests', loginId); - break; - case 'reaction': - client = await swos.openNote(data.body.note.id, loginId); - break; - default: - if ('note' in data.body) { - client = await swos.openNote(data.body.note.id, loginId); - } else if ('user' in data.body) { - client = await swos.openUser(Misskey.acct.toString(data.body.user), loginId); - } - break; - } - } - break; - case 'unreadAntennaNote': - client = await swos.openAntenna(data.body.antenna.id, loginId); - break; - default: - switch (action) { - case 'markAllAsRead': - await globalThis.registration.getNotifications() - .then(notifications => notifications.forEach(n => n.tag !== 'read_notification' && n.close())); - await get[]>('accounts').then(accounts => { - return Promise.all((accounts ?? []).map(async account => { - await swos.sendMarkAllAsRead(account.id); - })); - }); - break; - case 'settings': - client = await swos.openClient('push', '/settings/notifications', loginId); - break; - } - } + if (client) { + client.focus(); + } + if (data.type === 'notification') { + await swos.sendMarkAllAsRead(loginId); + } - if (client) { - client.focus(); - } - if (data.type === 'notification') { - await swos.sendMarkAllAsRead(loginId); - } - - notification.close(); - })()); + notification.close(); + })()); }); globalThis.addEventListener('notificationclose', (ev: ServiceWorkerGlobalScopeEventMap['notificationclose']) => { - const data: PushNotificationDataMap[keyof PushNotificationDataMap] = ev.notification.data; + const data: PushNotificationDataMap[keyof PushNotificationDataMap] = ev.notification.data; - ev.waitUntil((async (): Promise => { - if (data.type === 'notification') { - await swos.sendMarkAllAsRead(data.userId); - } - return; - })()); + ev.waitUntil((async (): Promise => { + if (data.type === 'notification') { + await swos.sendMarkAllAsRead(data.userId); + } + return; + })()); }); globalThis.addEventListener('message', (ev: ServiceWorkerGlobalScopeEventMap['message']) => { - ev.waitUntil((async (): Promise => { - switch (ev.data) { - case 'clear': - // Cache Storage全削除 - await caches.keys() - .then(cacheNames => Promise.all( - cacheNames.map(name => caches.delete(name)), - )); - return; // TODO - } + ev.waitUntil((async (): Promise => { + if (ev.data === 'clear') { + await caches.keys() + .then(cacheNames => Promise.all( + cacheNames.map(name => caches.delete(name)), + )); + return; + } - if (typeof ev.data === 'object') { - // E.g. '[object Array]' → 'array' - const otype = Object.prototype.toString.call(ev.data).slice(8, -1).toLowerCase(); + if (typeof ev.data === 'object') { + const otype = Object.prototype.toString.call(ev.data).slice(8, -1).toLowerCase(); - if (otype === 'object') { - if (ev.data.msg === 'initialize') { - swLang.setLang(ev.data.lang); - } - } - } - })()); -}); + if (otype === 'object') { + if (ev.data.msg === 'initialize') { + swLang.setLang(ev.data.lang); + } + } + } + })()); +}); \ No newline at end of file