From c5232e1563cdcd748cbf49506c64b49229129d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Iv=C3=A1n=20Vieitez=20Parra?= <3857362+corrideat@users.noreply.github.com> Date: Fri, 29 Nov 2024 21:05:57 +0000 Subject: [PATCH] Feedback --- frontend/controller/service-worker.js | 85 +++++++++++++++---- .../{ => serviceworkers}/sw-namespace.js | 2 +- .../controller/serviceworkers/sw-primary.js | 25 +++++- frontend/main.js | 77 +---------------- 4 files changed, 93 insertions(+), 96 deletions(-) rename frontend/controller/{ => serviceworkers}/sw-namespace.js (97%) diff --git a/frontend/controller/service-worker.js b/frontend/controller/service-worker.js index 0697c60267..38f543ffbc 100644 --- a/frontend/controller/service-worker.js +++ b/frontend/controller/service-worker.js @@ -3,7 +3,9 @@ import sbp from '@sbp/sbp' import { CAPTURED_LOGS, LOGIN_COMPLETE, NEW_CHATROOM_UNREAD_POSITION, PWA_INSTALLABLE, SET_APP_LOGS_FILTER } from '@utils/events.js' import { HOURS_MILLIS } from '~/frontend/model/contracts/shared/time.js' -import { deserializer } from '~/shared/serdes/index.js' +import { GIMessage } from '~/shared/domains/chelonia/GIMessage.js' +import { Secret } from '~/shared/domains/chelonia/Secret.js' +import { deserializer, serializer } from '~/shared/serdes/index.js' import { ONLINE } from '../utils/events.js' const pwa = { @@ -11,6 +13,9 @@ const pwa = { installed: false } +deserializer.register(GIMessage) +deserializer.register(Secret) + // How to provide your own in-app PWA install experience: // https://web.dev/articles/customize-install @@ -169,21 +174,67 @@ sbp('sbp/selectors/register', { }) ) -// helper method -/* -function urlBase64ToUint8Array (base64String) { - // reference: https://gist.github.com/Klerith/80abd742d726dd587f4bd5d6a0ab26b6 - const padding = '='.repeat((4 - (base64String.length % 4)) % 4) - const base64 = (base64String + padding) - .replace(/-/g, '+') - .replace(/_/g, '/') - - const rawData = atob(base64) - const outputArray = new Uint8Array(rawData.length) +const swRpc = (() => { + if (!navigator.serviceWorker) { + throw new Error('Missing service worker object') + } + let controller: ?ServiceWorker = navigator.serviceWorker.controller + navigator.serviceWorker.addEventListener('controllerchange', (ev: Event) => { + controller = (navigator.serviceWorker: any).controller + }, false) + + return (...args) => { + return new Promise((resolve, reject) => { + if (!controller) { + 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) + } + messageChannel.port1.close() + } + }, false) + messageChannel.port1.addEventListener('messageerror', (event: MessageEvent) => { + reject(event.data) + messageChannel.port1.close() + }, false) + messageChannel.port1.start() + const { data, transferables } = serializer(args) + controller.postMessage({ + type: 'sbp', + port: messageChannel.port2, + data + }, [messageChannel.port2, ...transferables]) + }) + } +})() - for (let i = 0; i < rawData.length; i++) { - outputArray[i] = rawData.charCodeAt(i) +sbp('sbp/selectors/register', { + 'gi.actions/*': swRpc +}) +sbp('sbp/selectors/register', { + 'chelonia/*': swRpc +}) +sbp('sbp/selectors/register', { + 'sw-namespace/*': (...args) => { + // Remove the `sw-` prefix from the selector + return swRpc(args[0].slice(3), ...args.slice(1)) } - return outputArray -} -*/ +}) +sbp('sbp/selectors/register', { + 'gi.notifications/*': swRpc +}) +sbp('sbp/selectors/register', { + 'swLogs/*': swRpc +}) +sbp('sbp/selectors/register', { + 'push/*': swRpc +}) diff --git a/frontend/controller/sw-namespace.js b/frontend/controller/serviceworkers/sw-namespace.js similarity index 97% rename from frontend/controller/sw-namespace.js rename to frontend/controller/serviceworkers/sw-namespace.js index 00b63ac803..ff31c2234f 100644 --- a/frontend/controller/sw-namespace.js +++ b/frontend/controller/serviceworkers/sw-namespace.js @@ -1,7 +1,7 @@ 'use strict' import sbp from '@sbp/sbp' -import { NAMESPACE_REGISTRATION } from '../utils/events.js' +import { NAMESPACE_REGISTRATION } from '@utils/events.js' // NOTE: prefix groups with `group/` and users with `user/` ? sbp('sbp/selectors/register', { diff --git a/frontend/controller/serviceworkers/sw-primary.js b/frontend/controller/serviceworkers/sw-primary.js index 92701f9b41..270d219860 100644 --- a/frontend/controller/serviceworkers/sw-primary.js +++ b/frontend/controller/serviceworkers/sw-primary.js @@ -7,7 +7,7 @@ import '@sbp/okturtles.eventqueue' import '@sbp/okturtles.events' import sbp from '@sbp/sbp' import '~/frontend/controller/actions/index.js' -import '~/frontend/controller/sw-namespace.js' +import './sw-namespace.js' import chatroomGetters from '~/frontend/model/chatroom/getters.js' import getters from '~/frontend/model/getters.js' import '~/frontend/model/notifications/selectors.js' @@ -18,7 +18,14 @@ import { GIMessage } from '~/shared/domains/chelonia/GIMessage.js' import { Secret } from '~/shared/domains/chelonia/Secret.js' import { CHELONIA_RESET, CONTRACTS_MODIFIED, CONTRACT_IS_SYNCING, EVENT_HANDLED } from '~/shared/domains/chelonia/events.js' import { deserializer, serializer } from '~/shared/serdes/index.js' -import { ACCEPTED_GROUP, CAPTURED_LOGS, CHATROOM_USER_STOP_TYPING, CHATROOM_USER_TYPING, DELETED_CHATROOM, JOINED_CHATROOM, JOINED_GROUP, KV_EVENT, LEFT_CHATROOM, LEFT_GROUP, NAMESPACE_REGISTRATION, NEW_CHATROOM_UNREAD_POSITION, NEW_LAST_LOGGED_IN, NEW_PREFERENCES, NEW_UNREAD_MESSAGES, NOTIFICATION_EMITTED, NOTIFICATION_REMOVED, NOTIFICATION_STATUS_LOADED, OFFLINE, ONLINE, SERIOUS_ERROR, SWITCH_GROUP } from '../../utils/events.js' +import { + ACCEPTED_GROUP, CAPTURED_LOGS, CHATROOM_USER_STOP_TYPING, + CHATROOM_USER_TYPING, DELETED_CHATROOM, JOINED_CHATROOM, JOINED_GROUP, + KV_EVENT, LEFT_CHATROOM, LEFT_GROUP, NAMESPACE_REGISTRATION, + NEW_CHATROOM_UNREAD_POSITION, NEW_LAST_LOGGED_IN, NEW_PREFERENCES, + NEW_UNREAD_MESSAGES, NOTIFICATION_EMITTED, NOTIFICATION_REMOVED, + NOTIFICATION_STATUS_LOADED, OFFLINE, ONLINE, SERIOUS_ERROR, SWITCH_GROUP +} from '../../utils/events.js' import './push.js' deserializer.register(GIMessage) @@ -54,9 +61,19 @@ const selectorBlacklist = [ sbp('sbp/filters/global/add', (domain, selector, data) => { if (domainBlacklist[domain] || selectorBlacklist[selector]) return console.debug(`[sbp] ${selector}`, data) -}); +}) -[CHELONIA_RESET, CONTRACTS_MODIFIED, CONTRACT_IS_SYNCING, EVENT_HANDLED, LOGIN, LOGIN_ERROR, LOGOUT, ACCEPTED_GROUP, CHATROOM_USER_STOP_TYPING, CHATROOM_USER_TYPING, DELETED_CHATROOM, LEFT_CHATROOM, LEFT_GROUP, JOINED_CHATROOM, JOINED_GROUP, KV_EVENT, MESSAGE_RECEIVE, MESSAGE_SEND, NAMESPACE_REGISTRATION, NEW_CHATROOM_UNREAD_POSITION, NEW_LAST_LOGGED_IN, NEW_PREFERENCES, NEW_UNREAD_MESSAGES, NOTIFICATION_EMITTED, NOTIFICATION_REMOVED, NOTIFICATION_STATUS_LOADED, OFFLINE, ONLINE, PROPOSAL_ARCHIVED, SERIOUS_ERROR, SWITCH_GROUP].forEach(et => { +// These are all of the events that will be forwarded to all open tabs and windows +;[ + CHELONIA_RESET, CONTRACTS_MODIFIED, CONTRACT_IS_SYNCING, EVENT_HANDLED, LOGIN, + LOGIN_ERROR, LOGOUT, ACCEPTED_GROUP, CHATROOM_USER_STOP_TYPING, + CHATROOM_USER_TYPING, DELETED_CHATROOM, LEFT_CHATROOM, LEFT_GROUP, + JOINED_CHATROOM, JOINED_GROUP, KV_EVENT, MESSAGE_RECEIVE, MESSAGE_SEND, + NAMESPACE_REGISTRATION, NEW_CHATROOM_UNREAD_POSITION, NEW_LAST_LOGGED_IN, + NEW_PREFERENCES, NEW_UNREAD_MESSAGES, NOTIFICATION_EMITTED, + NOTIFICATION_REMOVED, NOTIFICATION_STATUS_LOADED, OFFLINE, ONLINE, + PROPOSAL_ARCHIVED, SERIOUS_ERROR, SWITCH_GROUP +].forEach(et => { sbp('okTurtles.events/on', et, (...args) => { const { data } = serializer(args) const message = { diff --git a/frontend/main.js b/frontend/main.js index 9e80247a16..10349eaabf 100644 --- a/frontend/main.js +++ b/frontend/main.js @@ -35,9 +35,6 @@ import './views/utils/ui.js' import './views/utils/vError.js' import './views/utils/vFocus.js' // import './views/utils/vSafeHtml.js' // this gets imported by translations, which is part of common.js -import { GIMessage } from '~/shared/domains/chelonia/GIMessage.js' -import { Secret } from '~/shared/domains/chelonia/Secret.js' -import { deserializer, serializer } from '~/shared/serdes/index.js' import Vue from 'vue' import notificationsMixin from './model/notifications/mainNotificationsMixin.js' import './model/notifications/periodicNotifications.js' @@ -46,9 +43,6 @@ import './utils/touchInteractions.js' import { showNavMixin } from './views/utils/misc.js' import './views/utils/vStyle.js' -deserializer.register(GIMessage) -deserializer.register(Secret) - console.info('GI_VERSION:', process.env.GI_VERSION) console.info('CONTRACTS_VERSION:', process.env.CONTRACTS_VERSION) console.info('LIGHTWEIGHT_CLIENT:', process.env.LIGHTWEIGHT_CLIENT) @@ -100,9 +94,9 @@ async function startApp () { // Set up event listeners to keep local (Vuex) and Chelonia states in sync sbp('chelonia/externalStateSetup', { stateSelector: 'state/vuex/state', reactiveSet: Vue.set, reactiveDel: Vue.delete }) - // TODO: [SW] The following will be needed to keep namespace registrations - // in sync between the SW and each tab. It is not needed now because everything - // is running in the same context + // [SW] The following is be needed to keep namespace registrations in sync + // between the SW and each tab. It is not needed if everything is running in + // the same context sbp('okTurtles.events/on', NAMESPACE_REGISTRATION, ({ name, value }) => { const cache = sbp('state/vuex/state').namespaceLookups const reverseCache = sbp('state/vuex/state').reverseNamespaceLookups @@ -170,72 +164,7 @@ async function startApp () { sbp('state/vuex/commit', 'setNotificationEnabled', Notification.permission === 'granted') } - /* TODO: MOVE TO ANOTHER FILE */ sbp('okTurtles.data/set', 'API_URL', self.location.origin) - const swRpc = (() => { - if (!navigator.serviceWorker) { - throw new Error('Missing service worker object') - } - let controller: ?ServiceWorker = navigator.serviceWorker.controller - navigator.serviceWorker.addEventListener('controllerchange', (ev: Event) => { - controller = (navigator.serviceWorker: any).controller - }, false) - - return (...args) => { - return new Promise((resolve, reject) => { - if (!controller) { - 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) - } - messageChannel.port1.close() - } - }, false) - messageChannel.port1.addEventListener('messageerror', (event: MessageEvent) => { - reject(event.data) - messageChannel.port1.close() - }, false) - messageChannel.port1.start() - const { data, transferables } = serializer(args) - controller.postMessage({ - type: 'sbp', - port: messageChannel.port2, - data - }, [messageChannel.port2, ...transferables]) - }) - } - })() - - sbp('sbp/selectors/register', { - 'gi.actions/*': swRpc - }) - sbp('sbp/selectors/register', { - 'chelonia/*': swRpc - }) - sbp('sbp/selectors/register', { - 'sw-namespace/*': (...args) => { - // Remove the `sw-` prefix from the selector - return swRpc(args[0].slice(3), ...args.slice(1)) - } - }) - sbp('sbp/selectors/register', { - 'gi.notifications/*': swRpc - }) - sbp('sbp/selectors/register', { - 'swLogs/*': swRpc - }) - sbp('sbp/selectors/register', { - 'push/*': swRpc - }) /* eslint-disable no-new */ new Vue({