Page MenuHomePhabricator

D11328.diff
No OneTemporary

D11328.diff

diff --git a/web/push-notif/badge-handler.react.js b/web/push-notif/badge-handler.react.js
--- a/web/push-notif/badge-handler.react.js
+++ b/web/push-notif/badge-handler.react.js
@@ -2,35 +2,59 @@
import * as React from 'react';
-import { connectionSelector } from 'lib/selectors/keyserver-selectors.js';
-import { unreadCount } from 'lib/selectors/thread-selectors.js';
-import type { ConnectionInfo } from 'lib/types/socket-types.js';
+import { allConnectionInfosSelector } from 'lib/selectors/keyserver-selectors.js';
+import { allUnreadCounts } from 'lib/selectors/thread-selectors.js';
-import { authoritativeKeyserverID } from '../authoritative-keyserver.js';
+import {
+ updateNotifsUnreadCountStorage,
+ queryNotifsUnreadCountStorage,
+} from './notif-crypto-utils.js';
import electron from '../electron.js';
import { useSelector } from '../redux/redux-utils.js';
import getTitle from '../title/get-title.js';
function useBadgeHandler() {
- const connection = useSelector(connectionSelector(authoritativeKeyserverID));
- const prevConnection = React.useRef<?ConnectionInfo>();
-
- const boundUnreadCount = useSelector(unreadCount);
- const prevUnreadCount = React.useRef(boundUnreadCount);
+ const connection = useSelector(allConnectionInfosSelector);
+ const unreadCount = useSelector(allUnreadCounts);
React.useEffect(() => {
- if (
- connection?.status === 'connected' &&
- (prevConnection.current?.status !== 'connected' ||
- boundUnreadCount !== prevUnreadCount.current)
- ) {
- document.title = getTitle(boundUnreadCount);
- electron?.setBadge(boundUnreadCount === 0 ? null : boundUnreadCount);
- }
-
- prevConnection.current = connection;
- prevUnreadCount.current = boundUnreadCount;
- }, [boundUnreadCount, connection]);
+ void (async () => {
+ const unreadCountUpdates: {
+ [keyserverID: string]: number,
+ } = {};
+ const unreadCountQueries: Array<string> = [];
+
+ for (const keyserverID in unreadCount) {
+ if (connection[keyserverID]?.status !== 'connected') {
+ unreadCountQueries.push(keyserverID);
+ continue;
+ }
+ unreadCountUpdates[keyserverID] = unreadCount[keyserverID];
+ }
+
+ let queriedUnreadCounts: { +[keyserverID: string]: ?number } = {};
+ [queriedUnreadCounts] = await Promise.all([
+ queryNotifsUnreadCountStorage(unreadCountQueries),
+ updateNotifsUnreadCountStorage(unreadCountUpdates),
+ ]);
+
+ let totalUnreadCount = 0;
+ for (const keyserverID in unreadCountUpdates) {
+ totalUnreadCount += unreadCountUpdates[keyserverID];
+ }
+
+ for (const keyserverID in queriedUnreadCounts) {
+ if (!queriedUnreadCounts[keyserverID]) {
+ totalUnreadCount += unreadCount[keyserverID];
+ continue;
+ }
+ totalUnreadCount += queriedUnreadCounts[keyserverID];
+ }
+
+ document.title = getTitle(totalUnreadCount);
+ electron?.setBadge(totalUnreadCount === 0 ? null : totalUnreadCount);
+ })();
+ }, [unreadCount, connection]);
}
export default useBadgeHandler;
diff --git a/web/push-notif/notif-crypto-utils.js b/web/push-notif/notif-crypto-utils.js
--- a/web/push-notif/notif-crypto-utils.js
+++ b/web/push-notif/notif-crypto-utils.js
@@ -58,6 +58,8 @@
const ASHOAT_KEYSERVER_ID_USED_ONLY_FOR_MIGRATION_FROM_LEGACY_NOTIF_STORAGE =
'256';
+const INDEXED_DB_UNREAD_COUNT_SUFFIX = 'unreadCount';
+
async function decryptWebNotification(
encryptedNotification: EncryptedWebNotification,
): Promise<PlainTextWebNotification | WebNotifDecryptionError> {
@@ -105,6 +107,11 @@
encryptedPayload,
);
+ const { unreadCount } = decryptedNotification;
+ await updateNotifsUnreadCountStorage({
+ [keyserverID]: unreadCount,
+ });
+
return { id, ...decryptedNotification };
} catch (e) {
return {
@@ -146,8 +153,9 @@
};
}
+ let decryptedNotification;
try {
- return await commonDecrypt(
+ decryptedNotification = await commonDecrypt<{ +[string]: mixed }>(
encryptedOlmData,
olmDataContentKey,
encryptionKey,
@@ -159,6 +167,27 @@
staffCanSee,
};
}
+
+ if (!keyserverID) {
+ return decryptedNotification;
+ }
+
+ // iOS notifications require that unread count is set under
+ // `badge` key. Since MacOS notifications are created by the
+ // same function the unread count is also set under `badge` key
+ const { badge } = decryptedNotification;
+ if (typeof badge === 'number') {
+ await updateNotifsUnreadCountStorage({ [(keyserverID: string)]: badge });
+ return decryptedNotification;
+ }
+
+ const { unreadCount } = decryptedNotification;
+ if (typeof unreadCount === 'number') {
+ await updateNotifsUnreadCountStorage({
+ [(keyserverID: string)]: unreadCount,
+ });
+ }
+ return decryptedNotification;
}
async function commonDecrypt<T>(
@@ -463,10 +492,53 @@
await Promise.all([...insertionPromises, ...deletionPromises]);
}
+// Multiple keyserver unread count utilities
+function getKeyserverUnreadCountKey(keyserverID: string) {
+ return [
+ INDEXED_DB_KEYSERVER_PREFIX,
+ keyserverID,
+ INDEXED_DB_UNREAD_COUNT_SUFFIX,
+ ].join(INDEXED_DB_KEY_SEPARATOR);
+}
+
+async function updateNotifsUnreadCountStorage(perKeyserverUnreadCount: {
+ +[keyserverID: string]: number,
+}) {
+ const unreadCountUpdatePromises: Array<Promise<number>> = Object.entries(
+ perKeyserverUnreadCount,
+ ).map(([keyserverID, unreadCount]) => {
+ const keyserverUnreadCountKey = getKeyserverUnreadCountKey(keyserverID);
+ return localforage.setItem<number>(keyserverUnreadCountKey, unreadCount);
+ });
+
+ await Promise.all(unreadCountUpdatePromises);
+}
+
+async function queryNotifsUnreadCountStorage(
+ keyserverIDs: $ReadOnlyArray<string>,
+): Promise<{
+ +[keyserverID: string]: ?number,
+}> {
+ const queryUnreadCountPromises: Array<Promise<[string, ?number]>> =
+ keyserverIDs.map(async keyserverID => {
+ const keyserverUnreadCountKey = getKeyserverUnreadCountKey(keyserverID);
+ const unreadCount = await localforage.getItem<number>(
+ keyserverUnreadCountKey,
+ );
+ return [keyserverID, unreadCount];
+ });
+
+ const queriedUnreadCounts: $ReadOnlyArray<[string, ?number]> =
+ await Promise.all(queryUnreadCountPromises);
+ return Object.fromEntries(queriedUnreadCounts);
+}
+
export {
decryptWebNotification,
decryptDesktopNotification,
getOlmDataContentKeyForCookie,
getOlmEncryptionKeyDBLabelForCookie,
migrateLegacyOlmNotificationsSessions,
+ updateNotifsUnreadCountStorage,
+ queryNotifsUnreadCountStorage,
};

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 2:12 AM (21 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2510598
Default Alt Text
D11328.diff (6 KB)

Event Timeline