Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chelonia in SW #2357

Merged
merged 97 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
9b89d48
Chelonia in SW
corrideat Sep 19, 2024
bce3c5c
Debug
corrideat Sep 22, 2024
4601d99
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Sep 29, 2024
15d5f86
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Oct 4, 2024
2861605
Test fixes
corrideat Oct 6, 2024
80b1385
Fix group-chat-direct-message spec
corrideat Oct 6, 2024
693173f
Fix issue with the no-results slot being (incorrectly) used
corrideat Oct 6, 2024
ba57fb4
Changes supporting failing chat tests
corrideat Oct 7, 2024
13b4357
Fix attachments in SW
corrideat Oct 9, 2024
0a90ec4
Fix Flow fypes
corrideat Oct 13, 2024
22a0f6e
Use atomic for chatroom members
corrideat Oct 13, 2024
e5f8ed2
Chat bugfixes
corrideat Oct 14, 2024
286570a
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Oct 15, 2024
ab7d69d
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Oct 17, 2024
3c78f54
Use session storage for tab logs. Refactor logging to be more generic.
corrideat Oct 17, 2024
c8a4441
Bugfixes and removal of unnecessary selectors
corrideat Oct 17, 2024
17f3e77
SW logs
corrideat Oct 19, 2024
fe4521a
Bugfix for loading preferences (fix event handlers)
corrideat Oct 20, 2024
870d9a6
State for KV events
corrideat Oct 20, 2024
001e813
Serious banner error
corrideat Oct 20, 2024
48db75e
More consistent chelonia / vuex state use
corrideat Oct 20, 2024
d99c1e0
Remove debug logging
corrideat Oct 20, 2024
90460e7
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Oct 21, 2024
279e171
Logs UI
corrideat Oct 23, 2024
933957b
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Oct 23, 2024
ce94156
Lint
corrideat Oct 23, 2024
bdd0f84
Autologout for non-exisiting identity contracts
corrideat Oct 23, 2024
218dd9b
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Oct 24, 2024
aa12e08
Safari workaround
corrideat Oct 24, 2024
fd77e0b
Bugfix
corrideat Oct 24, 2024
18046a7
Bugfixes
corrideat Oct 25, 2024
bbb7277
Logout flow fixes
corrideat Oct 25, 2024
f7bc3d4
Last logged in event
corrideat Oct 25, 2024
b08b48b
Avoid SW logs spam
corrideat Oct 25, 2024
0f55f24
Chatroom position events
corrideat Oct 25, 2024
332e8cb
Feedback
corrideat Oct 27, 2024
6fd370f
WIP
corrideat Oct 28, 2024
fe4e55d
Stability bugfixes
corrideat Nov 2, 2024
ca116a5
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Nov 2, 2024
e4f40bc
Port notifications code
corrideat Nov 3, 2024
74b2dfa
Backend functions for sending
corrideat Nov 3, 2024
a2a0d37
Server push events
corrideat Nov 4, 2024
89329d0
Improvements
corrideat Nov 15, 2024
979218b
Proposals spec selector specificity fix
corrideat Nov 15, 2024
7bdf50c
Add wait to contributions spec
corrideat Nov 15, 2024
e3a6d9a
Push subscription improvements
corrideat Nov 16, 2024
d002c75
Server: persist subscriptions
corrideat Nov 16, 2024
af90f82
Push subscription reporting fixes
corrideat Nov 17, 2024
4b7a25a
Fix to add and join chatroom
corrideat Nov 17, 2024
78c77a7
Notification permissions improvements
corrideat Nov 20, 2024
63caf86
NotificationSettings based on permission
corrideat Nov 21, 2024
dd41be7
Fixes. Bugfix for messageReceivePostEffect
corrideat Nov 22, 2024
e1b55de
Fixes
corrideat Nov 23, 2024
9cee47d
Native notifications logic for display and opening
corrideat Nov 24, 2024
1865646
PWA improvements
corrideat Nov 24, 2024
0654213
Add PWA check to background sound
corrideat Nov 24, 2024
97d4505
Node 18 cypto fixes
corrideat Nov 25, 2024
5dbd05c
Push subscription setup fixes
corrideat Nov 25, 2024
80a6a5e
Document VAPID_EMAIL
corrideat Nov 28, 2024
24535cf
Add notification enabled check to main
corrideat Nov 28, 2024
3e67bee
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Nov 28, 2024
68c6d98
Add comments
corrideat Nov 28, 2024
d065020
Feedback
corrideat Nov 29, 2024
0aed55b
Fixes
corrideat Nov 29, 2024
37ab10b
Feedback
corrideat Nov 29, 2024
a39de0c
Feedback
corrideat Nov 29, 2024
f862f65
Fix pending messages issue
corrideat Nov 30, 2024
ec2d5d7
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Nov 30, 2024
99aa0c0
Fix types. Add contractID to message
corrideat Nov 30, 2024
1b276c8
Cleanup
corrideat Nov 30, 2024
e72dd29
Better PWA detection
corrideat Nov 30, 2024
4af5291
DRY PWA check
corrideat Nov 30, 2024
2734f8b
Simplify visibility check for PWA
corrideat Dec 1, 2024
fd202ea
Lazy init indexedDB + fix types
corrideat Dec 1, 2024
84c4200
Fix query check
corrideat Dec 1, 2024
36cdd68
Notifications error handling
corrideat Dec 1, 2024
c539b02
Fix #2422 (sp: -> shelter:)
corrideat Dec 1, 2024
cff3535
Show native notification if the app isn't focused
corrideat Dec 1, 2024
659930a
Add comment to indexedDB lazy init
corrideat Dec 2, 2024
b4998ff
Feedback & createMessage as object
corrideat Dec 3, 2024
f263fa9
Fixes
corrideat Dec 3, 2024
da6d2f0
Maximum payload size
corrideat Dec 3, 2024
e7fd6b4
Add type to debug log
corrideat Dec 3, 2024
93a6860
Update VAPID cache time
corrideat Dec 3, 2024
cf128a5
Feedback
corrideat Dec 5, 2024
3b30b0e
Cleanup
corrideat Dec 5, 2024
0eee8de
App logs styling
corrideat Dec 5, 2024
9278dc0
Don't set notifications.notificationEnabled if an error occurred
corrideat Dec 5, 2024
3eac14c
Simplify RPC cleanup
corrideat Dec 5, 2024
2119a34
Remove finally(cleanup)
corrideat Dec 5, 2024
269b1a5
Add comments explaining service-worker/setup-push-subscription
corrideat Dec 5, 2024
2f842eb
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Dec 6, 2024
e83ab13
Feedback
corrideat Dec 7, 2024
6817445
Feedback
corrideat Dec 9, 2024
5a762e1
Comments
corrideat Dec 9, 2024
a4e1238
Feedback
corrideat Dec 10, 2024
63023d7
Merge branch 'master' into feature/chelonia-in-service-worker
corrideat Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions frontend/controller/actions/chatroom.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ sbp('okTurtles.events/on', MESSAGE_RECEIVE_RAW, ({
// If newMessage is undefined, it means that an existing message is being edited
newMessage
}) => {
const state = sbp('chelonia/contract/state', contractID)
const getters = sbp('state/vuex/getters')
const mentions = makeMentionFromUserID(getters.ourIdentityContractId)
const msgData = newMessage || data
Expand All @@ -42,10 +43,10 @@ sbp('okTurtles.events/on', MESSAGE_RECEIVE_RAW, ({
messageHash: msgData.hash,
height: msgData.height,
text: msgData.text,
isDMOrMention: isMentionedMe || getters.chatRoomAttributes.type === CHATROOM_TYPES.DIRECT_MESSAGE,
isDMOrMention: isMentionedMe || state.attributes?.type === CHATROOM_TYPES.DIRECT_MESSAGE,
messageType: !newMessage ? MESSAGE_TYPES.TEXT : data.type,
memberID: innerSigningContractID,
chatRoomName: getters.chatRoomAttributes.name
chatRoomName: state.attributes?.name
Comment on lines +47 to +50
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is preventing us from moving the getter definitions into a file that is shared by the frontend and the SW?

That would be much preferable to this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chatroom getters are a Vuex module, which are harder to emulate without Vuex because of state partitioning. In addition, those getters rely on currentGroupId and currentChatroomId which can't be used in contracts.

Copy link
Member

@taoeffect taoeffect Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there nothing creative that's possible here? We can't define getters in a way that has them referring to the "the chatroom that corresponds to this state"?

i.e. "state paritioned getters" ala gettersProxy? (see bottom of chelonia.js)

Copy link
Member Author

@corrideat corrideat Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the chatroom that corresponds to this state

How would that even be possible the way getters are defined? I don't really see an issue with the lines highlighted, and I'm not even sure why we'd need a getter that returns a single property.

But going to the definition:

  chatRoomAttributes (state, getters) {
    return getters.currentChatRoomState.attributes || {}
  },

Sure, in this instance state corresponds to getters.currentChatRoomState, but I don't see how generically we can know what getters.currentChatRoomState should be (generically). In the app, it works because (remember this is a global getter) there is a currentChatRoomId. In contracts it works, because currentChatRoomState can be defined to return 'state'. In the SW, the situation is analogous to the app, but there's no currentChatRoomId.

Now, this could maybe work by having a getter that takes the contractID as a function parameter, but this requires refactoring and adds complexity. I also think such getters that are simply accessors should be avoided, as they increase code line count and complexity for no benefit.

Copy link
Member Author

@corrideat corrideat Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about it, another solution along the lines of what you suggested could be something like:

const getters = sbp('chelonia/contract/getters', 'gi.contracts/chatroom', state)
getters.currentChatRoomState

But honestly, for simple accessors such as these I don't see the benefit of adding this complexity. This also adds two other factors:

  1. If the getters are hardcoded (as in, statically imported), it increases bundle size
  2. If the getters are dynamic, they'll probably need to be async (in case the contract isn't loaded) and because of sandboxing (maybe).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@corrideat would it be possible to instantiate dynamically a new batch of getters where getters. currentChatRoomState returns a specific contract state in the SW using some sort of factory function?

I also think such getters that are simply accessors should be avoided, as they increase code line count and complexity for no benefit.

Getters are very important, as they solve a lot of DRY related problems. By using getters we can ensure that the way that data is accessed everywhere will have consistent return values (e.g. because it uses tricks like || {} etc.). Whereas those considerations would have to be thought of each time you access state data directly.

Copy link
Member

@taoeffect taoeffect Oct 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const getters = sbp('chelonia/contract/getters', 'gi.contracts/chatroom', state)

Yeah, that's a great idea!

I'd make one slight modification: instead of passing in state, passing in contractID:

const getters = sbp('chelonia/contract/getters', contractID)

(EDIT: I don't think you need to pass in the name, that can be retrieved using contractID if needed)

Then yeah, at least we could reuse the contract getters that are already defined in the contracts!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update based on today's conversation: we could use getters synchronously by importing the contract getters from this actions file. However, it'd have the downside of being 'statically hardcoded' based on whatever version is imported at build time and will increase bundle size. Doing it via Chelonia is potentially possible, but it'd need to be async in case the contract isn't cached and need to be loading and also maybe because of sandboxing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this no longer seems to be needed in the context of this PR (we're importing getters in the SW as needed), can we make this a new issue, possibly linked to the sandboxing issue (#2364)?

}).catch(e => {
console.error('[action/chatroom.js] Error on messageReceivePostEffect', e)
})
Expand Down
4 changes: 2 additions & 2 deletions frontend/controller/actions/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -860,8 +860,8 @@ export default (sbp('sbp/selectors/register', {
// inside of the exception handler :-(
}
},
'gi.actions/group/notifyProposalStateInGeneralChatRoom': function ({ groupID, proposal }: { groupID: string, proposal: Object }) {
const { generalChatRoomId } = sbp('chelonia/rootState')[groupID]
'gi.actions/group/notifyProposalStateInGeneralChatRoom': async function ({ groupID, proposal }: { groupID: string, proposal: Object }) {
const { generalChatRoomId } = await sbp('chelonia/contract/state', groupID)
return sbp('gi.actions/chatroom/addMessage', {
contractID: generalChatRoomId,
data: { type: MESSAGE_TYPES.INTERACTIVE, proposal }
Expand Down
8 changes: 3 additions & 5 deletions frontend/controller/actions/identity-kv.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict'
import sbp from '@sbp/sbp'
import { KV_KEYS } from '~/frontend/utils/constants.js'
import { KV_QUEUE, ONLINE } from '~/frontend/utils/events.js'
import { KV_QUEUE, NEW_PREFERENCES, NEW_UNREAD_MESSAGES, ONLINE } from '~/frontend/utils/events.js'
import { isExpired } from '@model/notifications/utils.js'

const initNotificationStatus = (data = {}) => ({ ...data, read: false })
Expand Down Expand Up @@ -51,8 +51,7 @@ export default (sbp('sbp/selectors/register', {
'gi.actions/identity/kv/loadChatRoomUnreadMessages': () => {
return sbp('okTurtles.eventQueue/queueEvent', KV_QUEUE, async () => {
const currentChatRoomUnreadMessages = await sbp('gi.actions/identity/kv/fetchChatRoomUnreadMessages')
// TODO: Can't use state/vuex/commit
sbp('state/vuex/commit', 'setUnreadMessages', currentChatRoomUnreadMessages)
sbp('okTurtles.events/emit', NEW_UNREAD_MESSAGES, currentChatRoomUnreadMessages)
})
},
'gi.actions/identity/kv/initChatRoomUnreadMessages': ({ contractID, messageHash, createdHeight }: {
Expand Down Expand Up @@ -192,8 +191,7 @@ export default (sbp('sbp/selectors/register', {
'gi.actions/identity/kv/loadPreferences': () => {
return sbp('okTurtles.eventQueue/queueEvent', KV_QUEUE, async () => {
const preferences = await sbp('gi.actions/identity/kv/fetchPreferences')
// TODO: Can't use state/vuex/commit
sbp('state/vuex/commit', 'setPreferences', preferences)
sbp('okTurtles.events/emit', NEW_PREFERENCES, preferences)
})
},
'gi.actions/identity/kv/updateDistributionBannerVisibility': ({ contractID, hidden }: { contractID: string, hidden: boolean }) => {
Expand Down
4 changes: 1 addition & 3 deletions frontend/controller/actions/identity.js
Original file line number Diff line number Diff line change
Expand Up @@ -497,9 +497,7 @@ export default (sbp('sbp/selectors/register', {
const partnerIDs = params.data.memberIDs
.filter(memberID => memberID !== rootGetters.ourIdentityContractId)
.map(memberID => rootGetters.ourContactProfilesById[memberID].contractID)
// NOTE: 'rootState.currentGroupId' could be changed while waiting for the sbp functions to be proceeded
// So should save it as a constant variable 'currentGroupId', and use it which can't be changed
const currentGroupId = rootState.currentGroupId
const currentGroupId = params.currentGroupId

const message = await sbp('gi.actions/chatroom/create', {
data: {
Expand Down
11 changes: 10 additions & 1 deletion frontend/controller/app/identity.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { GIErrorUIRuntimeError, L, LError, LTags } from '@common/common.js'
import { cloneDeep } from '@model/contracts/shared/giLodash.js'
import sbp from '@sbp/sbp'
import Vue from 'vue'
import { LOGIN, LOGIN_COMPLETE, LOGIN_ERROR } from '~/frontend/utils/events.js'
import { LOGIN, LOGIN_COMPLETE, LOGIN_ERROR, NEW_PREFERENCES, NEW_UNREAD_MESSAGES } from '~/frontend/utils/events.js'
import { Secret } from '~/shared/domains/chelonia/Secret.js'
import { boxKeyPair, buildRegisterSaltRequest, computeCAndHc, decryptContractSalt, hash, hashPassword, randomNonce } from '~/shared/zkpp.js'
// Using relative path to crypto.js instead of ~-path to workaround some esbuild bug
Expand Down Expand Up @@ -147,6 +147,14 @@ sbp('okTurtles.events/on', LOGIN, async ({ identityContractID, encryptionParams,
}
})

sbp('okTurtles.events/on', NEW_PREFERENCES, (currentChatRoomUnreadMessages) => {
sbp('state/vuex/commit', 'setUnreadMessages', currentChatRoomUnreadMessages)
})

sbp('okTurtles.events/on', NEW_UNREAD_MESSAGES, (preferences) => {
sbp('state/vuex/commit', 'setPreferences', preferences)
})

/* Commented out as persistentActions are not being used
sbp('okTurtles.events/on', LOGOUT, (a) => {
// TODO: [SW] It may make more sense to load persistent actions in
Expand Down Expand Up @@ -223,6 +231,7 @@ export default (sbp('sbp/selectors/register', {

return userID
} catch (e) {
console.error('@@@gi.app/identity/create failed!', e.message, e.stack)
console.error('gi.app/identity/create failed!', e)
throw new GIErrorUIRuntimeError(L('Failed to create user identity: {reportError}', LError(e)))
}
Expand Down
24 changes: 3 additions & 21 deletions frontend/controller/namespace.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
'use strict'

import sbp from '@sbp/sbp'
import Vue from 'vue'

// NOTE: prefix groups with `group/` and users with `user/` ?
sbp('sbp/selectors/register', {
'namespace/lookupCached': (name: string) => {
const cache = sbp('state/vuex/state').namespaceLookups
return cache[name] ?? null
return cache?.[name] ?? null
},
'namespace/lookupReverseCached': (id: string) => {
const cache = sbp('state/vuex/state').reverseNamespaceLookups
return cache[id] ?? null
return cache?.[id] ?? null
},
'namespace/lookup': (name: string, { skipCache }: { skipCache: boolean } = { skipCache: false }) => {
if (!skipCache) {
Expand All @@ -23,23 +22,6 @@ sbp('sbp/selectors/register', {
return Promise.resolve(cached)
}
}
return fetch(`${sbp('okTurtles.data/get', 'API_URL')}/name/${encodeURIComponent(name)}`).then((r: Object) => {
if (!r.ok) {
console.warn(`namespace/lookup: ${r.status} for ${name}`)
if (r.status !== 404) {
throw new Error(`${r.status}: ${r.statusText}`)
}
return null
}
return r['text']()
}).then(value => {
if (value !== null) {
const cache = sbp('state/vuex/state').namespaceLookups
const reverseCache = sbp('state/vuex/state').reverseNamespaceLookups
Vue.set(cache, name, value)
Vue.set(reverseCache, value, name)
}
return value
})
return sbp('sw-namespace/lookup', name, { skipCache })
}
})
17 changes: 14 additions & 3 deletions frontend/controller/service-worker.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
'use strict'

import sbp from '@sbp/sbp'
import { PUBSUB_INSTANCE } from '@controller/instance-keys.js'
import { REQUEST_TYPE, PUSH_SERVER_ACTION_TYPE, PUBSUB_RECONNECTION_SUCCEEDED, createMessage } from '~/shared/pubsub.js'
import { HOURS_MILLIS } from '~/frontend/model/contracts/shared/time.js'
import sbp from '@sbp/sbp'
import { PWA_INSTALLABLE } from '@utils/events.js'
import { HOURS_MILLIS } from '~/frontend/model/contracts/shared/time.js'
import { PUBSUB_RECONNECTION_SUCCEEDED, PUSH_SERVER_ACTION_TYPE, REQUEST_TYPE, createMessage } from '~/shared/pubsub.js'
import { deserializer } from '~/shared/serdes/index.js'

const pwa = {
deferredInstallPrompt: null,
Expand All @@ -25,6 +26,7 @@ window.addEventListener('beforeinstallprompt', e => {

sbp('sbp/selectors/register', {
'service-workers/setup': async function () {
console.error('@@@SW SETUP')
// setup service worker
// TODO: move ahead with encryption stuff ignoring this service worker stuff for now
// TODO: improve updating the sw: https://stackoverflow.com/a/49748437
Expand Down Expand Up @@ -82,12 +84,19 @@ sbp('sbp/selectors/register', {
sbp('service-worker/resubscribe-push', data.subscription)
break
}
case 'event': {
console.error('@@@EVENT RECEIVED', event.data.subtype, ...deserializer(event.data.data))
sbp('okTurtles.events/emit', event.data.subtype, ...deserializer(event.data.data))
break
}
default:
console.error('[sw] Received unknown message type from the service worker:', data)
break
}
}
})

console.error('@@@SW DONE, returning')
} catch (e) {
console.error('error setting up service worker:', e)
}
Expand All @@ -104,6 +113,8 @@ sbp('sbp/selectors/register', {
}

const pubsub = sbp('okTurtles.data/get', PUBSUB_INSTANCE)
if (!pubsub) return // TODO: This needs to be moved into the service worker
// proper. pubsub will be undefined in this context.
const existingSubscription = await registration.pushManager.getSubscription()
const messageToPushServerIfSocketConnected = (msgPayload) => {
// make sure the websocket client is not in the state of CLOSING, CLOSED before sending a message.
Expand Down
127 changes: 126 additions & 1 deletion frontend/controller/serviceworkers/sw-primary.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,126 @@
'use strict'

import { PROPOSAL_ARCHIVED } from '@model/contracts/shared/constants.js'
import '@sbp/okturtles.data'
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 getters from '~/frontend/model/getters.js'
import '~/frontend/model/notifications/selectors.js'
import setupChelonia from '~/frontend/setupChelonia.js'
import { LOGIN, LOGIN_ERROR, LOGOUT } from '~/frontend/utils/events.js'
import { GIMessage } from '~/shared/domains/chelonia/GIMessage.js'
import { Secret } from '~/shared/domains/chelonia/Secret.js'
import { CONTRACTS_MODIFIED, CONTRACT_IS_SYNCING, EVENT_HANDLED } from '~/shared/domains/chelonia/events.js'
import { deserializer, serializer } from '~/shared/serdes/index.js'
import { ACCEPTED_GROUP, DELETED_CHATROOM, JOINED_CHATROOM, JOINED_GROUP, KV_EVENT, LEFT_CHATROOM, LEFT_GROUP, NAMESPACE_REGISTRATION, NEW_PREFERENCES, NEW_UNREAD_MESSAGES, NOTIFICATION_EMITTED, NOTIFICATION_REMOVED, NOTIFICATION_STATUS_LOADED, SWITCH_GROUP } from '../../utils/events.js'

deserializer.register(GIMessage)
deserializer.register(Secret)

// https://serviceworke.rs/message-relay_service-worker_doc.html
// https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers
// https://jakearchibald.com/2014/using-serviceworker-today/
// https://github.com/w3c/ServiceWorker/blob/master/explainer.md
// https://frontendian.co/service-workers
// https://stackoverflow.com/a/49748437 => https://medium.com/@nekrtemplar/self-destroying-serviceworker-73d62921d717 => https://love2dev.com/blog/how-to-uninstall-a-service-worker/

sbp('sbp/filters/global/add', (domain, selector, data) => {
// if (domainBlacklist[domain] || selectorBlacklist[selector]) return
console.debug(`[sw] [sbp] ${selector}`, data)
});

[EVENT_HANDLED, CONTRACTS_MODIFIED, CONTRACT_IS_SYNCING, LOGIN, LOGIN_ERROR, LOGOUT, ACCEPTED_GROUP, DELETED_CHATROOM, LEFT_CHATROOM, LEFT_GROUP, JOINED_CHATROOM, JOINED_GROUP, KV_EVENT, NAMESPACE_REGISTRATION, NEW_PREFERENCES, NEW_UNREAD_MESSAGES, NOTIFICATION_EMITTED, NOTIFICATION_REMOVED, NOTIFICATION_STATUS_LOADED, SWITCH_GROUP, PROPOSAL_ARCHIVED].forEach(et => {
sbp('okTurtles.events/on', et, (...args) => {
const { data } = serializer(args)
const message = {
type: 'event',
subtype: et,
data
}
self.clients.matchAll()
.then((clientList) => {
clientList.forEach((client) => {
client.postMessage(message)
})
})
})
})

sbp('sbp/selectors/register', {
'state/vuex/state': () => {
// TODO: Remove this selector once it's removed from contracts
return sbp('chelonia/rootState')
},
'state/vuex/reset': () => {
console.error('[sw] CALLED state/vuex/reset WHICH IS UNDEFINED')
},
'state/vuex/save': () => {
console.error('[sw] CALLED state/vuex/save WHICH IS UNDEFINED')
},
'state/vuex/commit': () => {
console.error('[sw] CALLED state/vuex/commit WHICH IS UNDEFINED')
},
'state/vuex/getters': () => {
const obj = Object.create(null)
corrideat marked this conversation as resolved.
Show resolved Hide resolved
Object.defineProperties(obj, Object.fromEntries(Object.entries(getters).map(([getter, fn]) => {
return [getter, {
get: () => {
const state = sbp('chelonia/rootState')
return fn(state, obj)
}
}]
})))

return obj
/* return {
chatRoomUnreadMessages () {
return []
},
getChatroomNameById () {
return ''
},
groupIdFromChatRoomId () {
return ''
},
isGroupDirectMessage () {
return false
},
notificationsByGroup () {
return []
},
ourContactProfilesByUsername: {},
ourIdentityContractId: '',
userDisplayNameFromID () {
return ''
},
usernameFromID () {
return ''
},
ourContactProfilesById: {}
}
*/
}
})

sbp('sbp/selectors/register', {
'controller/router': () => {
return { options: { base: '/app/' } }
}
corrideat marked this conversation as resolved.
Show resolved Hide resolved
})

sbp('sbp/selectors/register', {
'gi.ui/seriousErrorBanner': (...args) => {
console.error('### SERIOUS ERROR ###', ...args)
}
})

sbp('sbp/selectors/register', {
'appLogs/save': () => {}
})

self.addEventListener('install', function (event) {
console.debug('[sw] install')
event.waitUntil(self.skipWaiting())
Expand All @@ -16,7 +130,7 @@ self.addEventListener('activate', function (event) {
console.debug('[sw] activate')

// 'clients.claim()' reference: https://web.dev/articles/service-worker-lifecycle#clientsclaim
event.waitUntil(self.clients.claim())
event.waitUntil(setupChelonia().then(() => self.clients.claim()))
})

self.addEventListener('fetch', function (event) {
Expand Down Expand Up @@ -57,6 +171,17 @@ self.addEventListener('message', function (event) {
case 'store-client-id':
store.clientId = event.source.id
break
case 'sbp': {
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)
})
break
}
case 'ping':
event.source.postMessage({ type: 'pong' })
break
Expand Down
Loading