Skip to content

Commit

Permalink
Feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
corrideat committed Dec 5, 2024
1 parent 93a6860 commit cf128a5
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 32 deletions.
51 changes: 33 additions & 18 deletions frontend/controller/service-worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ sbp('sbp/selectors/register', {

try {
// Using hash (#) is possible, but seems to get reset when the SW restarts
const swRegistration = await navigator.serviceWorker.register(`/assets/js/sw-primary.js${isPwa() ? '?standalone=1' : ''}`, { scope: '/' })
const params = new URLSearchParams([
['routerBase', sbp('controller/router').options.base ?? ''],
['standalone', isPwa() ? '1' : '0']
])
const swRegistration = await navigator.serviceWorker.register(`/assets/js/sw-primary.js?${params}`, { scope: '/' })

// if an active service-worker exists, checks for the updates immediately first and then repeats it every 1hr
await swRegistration.update()
Expand Down Expand Up @@ -165,10 +169,10 @@ sbp('sbp/selectors/register', {
const result = await pwa.deferredInstallPrompt.prompt()
return result.outcome
}
});
})

// Events that need to be relayed to the SW
[LOGIN_COMPLETE, NEW_CHATROOM_UNREAD_POSITION, SET_APP_LOGS_FILTER].forEach((event) =>
;[LOGIN_COMPLETE, NEW_CHATROOM_UNREAD_POSITION, SET_APP_LOGS_FILTER].forEach((event) =>
sbp('okTurtles.events/on', event, (...data) => {
navigator.serviceWorker.controller?.postMessage({ type: 'event', subtype: event, data })
})
Expand All @@ -189,23 +193,34 @@ const swRpc = (() => {
reject(new Error('Service worker not ready'))
return
}
const messageChannel = new MessageChannel()
messageChannel.port1.addEventListener('message', (event: MessageEvent) => {
if (event.data && Array.isArray(event.data)) {
const r = deserializer(event.data[1])
// $FlowFixMe[incompatible-use]
if (event.data[0] === true) {
resolve(r)
} else {
reject(r)
// The revocable Proxy ensures that there are no dangling references after
// the promise resolves
const { proxy: [messageChannel, onmessage, onmessageerror, cleanup], revoke } = Proxy.revocable([
new MessageChannel(),
(event: MessageEvent) => {
if (event.data && Array.isArray(event.data)) {
const r = deserializer(event.data[1])
// $FlowFixMe[incompatible-use]
if (event.data[0] === true) {
resolve(r)
} else {
reject(r)
}
cleanup()
}
messageChannel.port1.close()
},
(event: MessageEvent) => {
reject(event.data)
cleanup()
},
() => {
messageChannel.port1.removeEventListener('message', onmessage, false)
messageChannel.port1.removeEventListener('messageerror', onmessageerror, false)
revoke()
}
}, false)
messageChannel.port1.addEventListener('messageerror', (event: MessageEvent) => {
reject(event.data)
messageChannel.port1.close()
}, false)
], {})
messageChannel.port1.addEventListener('message', onmessage, false)
messageChannel.port1.addEventListener('messageerror', onmessageerror, false)
messageChannel.port1.start()
const { data, transferables } = serializer(args)
controller.postMessage({
Expand Down
27 changes: 18 additions & 9 deletions frontend/controller/serviceworkers/push.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,13 @@ if (self.registration?.pushManager) {
self.addEventListener('push', function (event) {
// PushEvent reference: https://developer.mozilla.org/en-US/docs/Web/API/PushEvent
if (!event.data) return
const data = event.data.json()
let data
try {
data = event.data.json()
} catch (e) {
console.error('[push event] Invalid JSON:', e)
return
}
if (data.type === NOTIFICATION_TYPE.ENTRY) {
event.waitUntil(setupChelonia().then(() => {
// We have event data, so we process it
Expand All @@ -123,14 +129,17 @@ self.addEventListener('push', function (event) {
}
}, false)

self.addEventListener('pushsubscriptionchange', async function (event) {
self.addEventListener('pushsubscriptionchange', function (event) {
// NOTE: Currently there is no specific way to validate if a push-subscription is valid. So it has to be handled in the front-end.
// (reference:https://pushpad.xyz/blog/web-push-how-to-check-if-a-push-endpoint-is-still-valid)
const subscription = await self.registration.pushManager.subscribe(
event.oldSubscription.options
)

sbp('push/reportExistingSubscription', subscription?.toJSON()).catch(e => {
console.error('[pushsubscriptionchange] Error reporting subscription', e)
})
event.waitUntil((async () => {
try {
const subscription = await self.registration.pushManager.subscribe(
event.oldSubscription.options
)
await sbp('push/reportExistingSubscription', subscription?.toJSON())
} catch (e) {
console.error('[pushsubscriptionchange] Error resubscribing:', e)
}
})())
}, false)
12 changes: 8 additions & 4 deletions frontend/controller/serviceworkers/sw-primary.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,11 @@ sbp('sbp/selectors/register', {
})()
})

const x = new URL(self.location)

sbp('sbp/selectors/register', {
'controller/router': () => {
return { options: { base: '/app/' } }
return { options: { base: x.searchParams.get('routerBase') } }
}
})

Expand Down Expand Up @@ -192,13 +194,15 @@ self.addEventListener('message', function (event) {
console.debug('[sw] event received:', event.data)
switch (event.data.type) {
case 'sbp': {
const port = event.data.port;
(async () => await sbp(...deserializer(event.data.data)))().then((r) => {
const port = event.data.port
;(async () => await sbp(...deserializer(event.data.data)))().then((r) => {
const { data, transferables } = serializer(r)
port.postMessage([true, data], transferables)
}).catch((e) => {
const { data, transferables } = serializer(e)
port.postMessage([false, data], transferables)
}).finally(() => {
port.close()
})
break
}
Expand Down Expand Up @@ -250,7 +254,7 @@ self.addEventListener('notificationclick', event => {
return 0
})
if (!clientList.length) {
return self.clients.openWindow(`/app${event.notification.data.path ?? '/'}`)
return self.clients.openWindow(`${sbp('controller/router').options.base}${event.notification.data.path ?? '/'}`)
}
const client = clientList[0]
if (event.notification.data?.path) {
Expand Down
10 changes: 9 additions & 1 deletion frontend/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,10 @@ async function startApp () {
// Wait for SW to be ready
console.debug('[app] Waiting for SW to be ready')
const sw = ((navigator.serviceWorker: any): ServiceWorkerContainer)
sw.ready.then(() => {
Promise.race([
sw.ready,
new Promise((resolve, reject) => setTimeout(() => reject(new Error('SW ready timeout')), 10000))
]).then(() => {
const onready = () => {
this.ephemeral.ready = true
this.removeLoadingAnimation()
Expand All @@ -346,6 +349,11 @@ async function startApp () {
} else {
onready()
}
}).catch(e => {
console.error('[app] Service worker failed to become ready:', e)
// Fallback behavior
this.removeLoadingAnimation()
alert(L('Error while setting up service worker'))
})
})
},
Expand Down

0 comments on commit cf128a5

Please sign in to comment.