Page MenuHomePhabricator

Update unread count storage from JS and NSE
ClosedPublic

Authored by marcin on Feb 15 2024, 5:12 AM.
Tags
None
Referenced Files
Unknown Object (File)
Wed, Nov 20, 7:17 PM
Unknown Object (File)
Wed, Nov 20, 11:51 AM
Unknown Object (File)
Wed, Nov 6, 3:43 PM
Unknown Object (File)
Oct 16 2024, 3:13 PM
Unknown Object (File)
Oct 16 2024, 7:51 AM
Unknown Object (File)
Oct 16 2024, 5:48 AM
Unknown Object (File)
Oct 15 2024, 3:03 PM
Unknown Object (File)
Oct 15 2024, 3:03 PM
Subscribers

Details

Summary

This differential uses JSI introduced in parent differential to update unread count for each keyserver from JS on native.

Test Plan

Build iOS app and send notifications and/or update unread status on web client on both backgrounded and foregrounded app. Ensure unread count
functionality is not broken.

Diff Detail

Repository
rCOMM Comm
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

native/push/push-handler.react.js
111 ↗(On Diff #37256)

I was thinking about this and I reached a conclusion that we don't need to check whether we are connected to a keyserver. The reason for that is that when we receive notification it triggers redux update so that extendedUnreadCount selector is recalculated. This means that if we are disconnected from the keyserver then redux either reflects the state from the last time we were connected to the keyserver or we received a notif containing never state that triggered redux update. In either case we should the value from redux to calculate total unread count.

lib/ops/keyserver-store-ops.js
136–145 ↗(On Diff #37256)

Nit: weird that you're mixing paradigms here... why not replace your for loop with a filter, so it matches with the map / flat approach later?

native/push/push-handler.react.js
111 ↗(On Diff #37256)

I'm not sure I follow this reasoning.

The behavior before was that the unread count could be updated in one of two ways:

  • Directly from a notif. In that case, the unread count is updated by native code
  • From this code. For a given keyserver, we only want to override the unread count we got from a notif if we are connected to that keyserver – otherwise, our local store may be more out-of-date than the most recent notif

I'm concerned that the user might open the app and have the badge count immediately update based on the app's out-of-date local data, which would be bad because it may be more out-of-date than the prior badge count (based on a notif).

Restructure stack to separate unread count from multiple sessions

lib/ops/keyserver-store-ops.js
136–145 ↗(On Diff #37256)

I opted for this since in the following construction:

const removeKeyserversOperations = ops.filter(op => op.type === 'remove_keyservers')

flow doesn't understand that the array now consists of RemoveKeyserversOperation only but thinks that this array can contain any KeyserverStoreOperation. This breaks map used later. In order to use filter exclusively we need sth like this:

return ops
    .filter(op => op.type === 'remove_keyservers')
    .map(operation => operation.payload?.ids)
    .filter(Boolean)
    .flat();

Fot me personally it is even weirder since we are checking for values that we are sure that are truthy.

  1. Bring back connection check.
  2. Use updatesCurrentAsOff for each keyserver separately
lib/selectors/thread-selectors.js
293 ↗(On Diff #37884)

Can we name this something more descriptive, eg. perKeyserverUnreadCount?

native/push/push-handler.react.js
743 ↗(On Diff #37884)

Is this an unexpected condition? Should we use an invariant, or at least print an error?

lib/selectors/keyserver-selectors.js
111 ↗(On Diff #37884)

This is just KeyserverInfos

native/push/push-handler.react.js
623 ↗(On Diff #37884)

Shouldn't this be messages for keyserverID? i.e. keyserverIDToMessageInfos[keyserverID]

742–744 ↗(On Diff #37884)

extractKeyserverIDFromID returns a string, it's not possible for this to be falsy unless it's an empty string, which would mean that message.threadID was an empty string. I don't think this is possible?

lib/selectors/thread-selectors.js
293 ↗(On Diff #37884)

We already have allUpdatesCurrentAsOff selector in this file that returns similar thing. I will update to allUnreadCounts to match convention.

native/push/push-handler.react.js
623 ↗(On Diff #37884)

Definitely - my mistake.

742–744 ↗(On Diff #37884)

According to @inka explanation invariant seems to be best choice here.

  1. Address JS nits
  2. Distapch saveMessagesActionType action with message for one keyserver (fixing bug indentified by inka)

Fix bug: saveMessageInfosActionType requires rawMessageInfos field.

lib/ops/keyserver-store-ops.js
133–145 ↗(On Diff #37937)

In this case, we could consider making both transformations in the for loop instead. Also, I think that having a flat array isn't ideal, because it won't handle duplicated IDs properly.

lib/selectors/keyserver-selectors.js
111–117 ↗(On Diff #37937)

This could be expressed using lodash

native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java
52–53 ↗(On Diff #37937)

Can we define a separate constant for a separator and avoid including the separator in prefixes and suffixes?

235–242 ↗(On Diff #37937)

We can consider simplifying this logic

247 ↗(On Diff #37937)

What does -1 mean?

native/android/app/src/main/java/app/comm/android/notifications/CommNotificationsHandler.java
247 ↗(On Diff #37937)

It is explained here.

  1. Address JS nits.
  2. Separate mmkv prefixes and suffixes from separator.
  3. Use constants for mmkv key handling on iOS in the NSE code.

LGTM, although I am not familiar with our Objective-C/java code

native/ios/NotificationService/NotificationService.mm
17–19 ↗(On Diff #37965)

Do these values have to be in sync with values form CommNotificationsHandler.java? If so, should we write comment?

476–481 ↗(On Diff #37965)

Can't we do the same simplification as in here?

native/push/push-handler.react.js
742–744 ↗(On Diff #37884)

My point was actually that keyserverID should always be a non-empty string, so even the invariant is unnecessary

This revision is now accepted and ready to land.Mar 12 2024, 4:22 AM
  1. Remove invariant.
  2. Add comments for devs to make sure that constants in CommNotificationsHandler.java match constants in NotificationService.mm.
  3. Simplify total unread count calculation logic in NotificationService.mm.