Page MenuHomePhabricator

D13164.id43860.diff
No OneTemporary

D13164.id43860.diff

diff --git a/lib/push/android-notif-creators.js b/lib/push/android-notif-creators.js
--- a/lib/push/android-notif-creators.js
+++ b/lib/push/android-notif-creators.js
@@ -35,7 +35,7 @@
export type CommonNativeNotifInputData = $ReadOnly<{
+senderDeviceDescriptor: SenderDeviceDescriptor,
+notifTexts: ResolvedNotifTexts,
- +newRawMessageInfos: RawMessageInfo[],
+ +newRawMessageInfos: $ReadOnlyArray<RawMessageInfo>,
+threadID: string,
+collapseKey: ?string,
+badgeOnly: boolean,
@@ -55,10 +55,10 @@
platformDetails: tPlatformDetails,
});
-export type AndroidNotifInputData = {
+export type AndroidNotifInputData = $ReadOnly<{
...CommonNativeNotifInputData,
+notifID: string,
-};
+}>;
export const androidNotifInputDataValidator: TInterface<AndroidNotifInputData> =
tShape<AndroidNotifInputData>({
diff --git a/lib/push/apns-notif-creators.js b/lib/push/apns-notif-creators.js
--- a/lib/push/apns-notif-creators.js
+++ b/lib/push/apns-notif-creators.js
@@ -30,10 +30,10 @@
export const apnMaxNotificationPayloadByteSize = 4096;
-export type APNsNotifInputData = {
+export type APNsNotifInputData = $ReadOnly<{
...CommonNativeNotifInputData,
+uniqueID: string,
-};
+}>;
export const apnsNotifInputDataValidator: TInterface<APNsNotifInputData> =
tShape<APNsNotifInputData>({
@@ -413,13 +413,19 @@
}));
}
-type APNsBadgeOnlyNotificationInputData = {
+type SenderDescriptorWithPlatformDetails = {
+senderDeviceDescriptor: SenderDeviceDescriptor,
- +badge?: number,
- +threadID?: string,
+platformDetails: PlatformDetails,
};
+type APNsBadgeOnlyNotificationInputData = $ReadOnly<
+ | {
+ ...SenderDescriptorWithPlatformDetails,
+ +badge: string,
+ }
+ | { ...SenderDescriptorWithPlatformDetails, +threadID: string },
+>;
+
async function createAPNsBadgeOnlyNotification(
encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
inputData: APNsBadgeOnlyNotificationInputData,
diff --git a/lib/push/send-hooks.react.js b/lib/push/send-hooks.react.js
--- a/lib/push/send-hooks.react.js
+++ b/lib/push/send-hooks.react.js
@@ -1,16 +1,19 @@
// @flow
+import invariant from 'invariant';
import * as React from 'react';
import uuid from 'uuid';
import {
preparePushNotifs,
+ prepareOwnDevicesPushNotifs,
type PerUserTargetedNotifications,
} from './send-utils.js';
import { ENSCacheContext } from '../components/ens-cache-provider.react.js';
import { NeynarClientContext } from '../components/neynar-client-provider.react.js';
import { usePeerOlmSessionsCreatorContext } from '../components/peer-olm-session-creator-provider.react.js';
import { thickRawThreadInfosSelector } from '../selectors/thread-selectors.js';
+import { IdentityClientContext } from '../shared/identity-client-context.js';
import { useTunnelbroker } from '../tunnelbroker/tunnelbroker-context.js';
import type {
TargetedAPNsNotification,
@@ -27,7 +30,6 @@
TunnelbrokerWNSNotif,
} from '../types/tunnelbroker/notif-types.js';
import { getConfig } from '../utils/config.js';
-import { getContentSigningKey } from '../utils/crypto-utils.js';
import { getMessageForException } from '../utils/errors.js';
import { useSelector } from '../utils/redux-utils.js';
@@ -98,6 +100,9 @@
function useSendPushNotifs(): (
notifCreationData: ?NotificationsCreationData,
) => Promise<?PerUserTargetedNotifications> {
+ const client = React.useContext(IdentityClientContext);
+ invariant(client, 'Identity context should be set');
+ const { getAuthMetadata } = client;
const rawMessageInfos = useSelector(state => state.messageStore.messages);
const thickRawThreadInfos = useSelector(thickRawThreadInfosSelector);
const auxUserInfos = useSelector(state => state.auxUserStore.auxUserInfos);
@@ -114,9 +119,17 @@
if (!notifCreationData) {
return;
}
- const deviceID = await getContentSigningKey();
+ const { deviceID, userID: senderUserID } = await getAuthMetadata();
+ if (!deviceID || !senderUserID) {
+ return;
+ }
+
const senderDeviceDescriptor = { senderDeviceID: deviceID };
- const { messageDatas } = notifCreationData;
+ const senderInfo = {
+ senderUserID,
+ senderDeviceDescriptor,
+ };
+ const { messageDatas, rescindData, badgeUpdateData } = notifCreationData;
const pushNotifsPreparationInput = {
encryptedNotifUtilsAPI,
@@ -131,17 +144,36 @@
getFCNames,
};
- const preparedPushNotifs = await preparePushNotifs(
- pushNotifsPreparationInput,
- );
+ const ownDevicesPushNotifsPreparationInput = {
+ encryptedNotifUtilsAPI,
+ senderInfo,
+ olmSessionCreator,
+ auxUserInfos,
+ rescindData,
+ badgeUpdateData,
+ };
+
+ const [preparedPushNotifs, preparedOwnDevicesPushNotifs] =
+ await Promise.all([
+ preparePushNotifs(pushNotifsPreparationInput),
+ prepareOwnDevicesPushNotifs(ownDevicesPushNotifsPreparationInput),
+ ]);
- if (!preparedPushNotifs) {
+ if (!preparedPushNotifs && !prepareOwnDevicesPushNotifs) {
return;
}
+ let allPreparedPushNotifs = preparedPushNotifs;
+ if (preparedOwnDevicesPushNotifs && senderUserID) {
+ allPreparedPushNotifs = {
+ ...allPreparedPushNotifs,
+ [senderUserID]: preparedOwnDevicesPushNotifs,
+ };
+ }
+
const sendPromises = [];
- for (const userID in preparedPushNotifs) {
- for (const notif of preparedPushNotifs[userID]) {
+ for (const userID in allPreparedPushNotifs) {
+ for (const notif of allPreparedPushNotifs[userID]) {
if (notif.targetedNotification.notification.encryptionFailed) {
continue;
}
@@ -186,6 +218,7 @@
await Promise.all(sendPromises);
},
[
+ getAuthMetadata,
sendNotif,
encryptedNotifUtilsAPI,
olmSessionCreator,
diff --git a/lib/push/send-utils.js b/lib/push/send-utils.js
--- a/lib/push/send-utils.js
+++ b/lib/push/send-utils.js
@@ -3,8 +3,16 @@
import _pickBy from 'lodash/fp/pickBy.js';
import uuidv4 from 'uuid/v4.js';
-import { createAndroidVisualNotification } from './android-notif-creators.js';
-import { createAPNsVisualNotification } from './apns-notif-creators.js';
+import {
+ createAndroidVisualNotification,
+ createAndroidBadgeOnlyNotification,
+ createAndroidNotificationRescind,
+} from './android-notif-creators.js';
+import {
+ createAPNsVisualNotification,
+ createAPNsBadgeOnlyNotification,
+ createAPNsNotificationRescind,
+} from './apns-notif-creators.js';
import {
stringToVersionKey,
getDevicesByPlatform,
@@ -103,12 +111,12 @@
messageInfos: { +[id: string]: RawMessageInfo },
thickRawThreadInfos: ThickRawThreadInfos,
auxUserInfos: AuxUserInfos,
- messageDatas: $ReadOnlyArray<MessageData>,
+ messageDatas: ?$ReadOnlyArray<MessageData>,
): Promise<{
+pushInfos: ?PushInfo,
+rescindInfos: ?PushInfo,
}> {
- if (messageDatas.length === 0) {
+ if (!messageDatas || messageDatas.length === 0) {
return { pushInfos: null, rescindInfos: null };
}
@@ -250,6 +258,48 @@
};
}
+type SenderInfo = {
+ +senderUserID: string,
+ +senderDeviceDescriptor: SenderDeviceDescriptor,
+};
+
+type OwnDevicesPushInfo = {
+ +devices: $ReadOnlyArray<Device>,
+};
+
+function getOwnDevicesPushInfo(
+ senderInfo: SenderInfo,
+ auxUserInfos: AuxUserInfos,
+): ?OwnDevicesPushInfo {
+ const {
+ senderUserID,
+ senderDeviceDescriptor: { senderDeviceID },
+ } = senderInfo;
+
+ if (!senderDeviceID) {
+ return null;
+ }
+
+ const senderDevicesWithPlatformDetails =
+ auxUserInfos[senderUserID].devicesPlatformDetails;
+
+ if (!senderDevicesWithPlatformDetails) {
+ return null;
+ }
+
+ const devices = Object.entries(senderDevicesWithPlatformDetails)
+ .filter(([deviceID]) => deviceID !== senderDeviceID)
+ .map(([deviceID, identityPlatformDetails]) => ({
+ platformDetails: identityPlatformDetailsToPlatformDetails(
+ identityPlatformDetails,
+ ),
+ deliveryID: deviceID,
+ cryptoID: deviceID,
+ }));
+
+ return { devices };
+}
+
function pushInfoToCollapsableNotifInfo(pushInfo: PushInfo): {
+usersToCollapseKeysToInfo: {
[string]: { [string]: CollapsableNotifInfo },
@@ -393,6 +443,96 @@
return { notifTexts, newRawMessageInfos, badgeOnly };
}
+type BuildNotifsForPlatformInput<
+ PlatformType: Platform,
+ NotifCreatorinputBase,
+ TargetedNotificationType,
+ NotifCreatorInput: { +platformDetails: PlatformDetails, ... },
+> = {
+ +platform: PlatformType,
+ +encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ +notifCreatorCallback: (
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ input: NotifCreatorInput,
+ devices: $ReadOnlyArray<NotificationTargetDevice>,
+ ) => Promise<$ReadOnlyArray<TargetedNotificationType>>,
+ +notifCreatorInputBase: NotifCreatorinputBase,
+ +transformInputBase: (
+ inputBase: NotifCreatorinputBase,
+ platformDetails: PlatformDetails,
+ ) => NotifCreatorInput,
+ +versionToDevices: $ReadOnlyMap<
+ string,
+ $ReadOnlyArray<NotificationTargetDevice>,
+ >,
+};
+
+async function buildNotifsForPlatform<
+ PlatformType: Platform,
+ NotifCreatorinputBase,
+ TargetedNotificationType,
+ NotifCreatorInput: { +platformDetails: PlatformDetails, ... },
+>(
+ input: BuildNotifsForPlatformInput<
+ PlatformType,
+ NotifCreatorinputBase,
+ TargetedNotificationType,
+ NotifCreatorInput,
+ >,
+): Promise<
+ $ReadOnlyArray<{
+ +platform: PlatformType,
+ +targetedNotification: TargetedNotificationType,
+ }>,
+> {
+ const {
+ encryptedNotifUtilsAPI,
+ versionToDevices,
+ notifCreatorCallback,
+ notifCreatorInputBase,
+ platform,
+ transformInputBase,
+ } = input;
+
+ const promises: Array<
+ Promise<
+ $ReadOnlyArray<{
+ +platform: PlatformType,
+ +targetedNotification: TargetedNotificationType,
+ }>,
+ >,
+ > = [];
+
+ for (const [versionKey, devices] of versionToDevices) {
+ const { codeVersion, stateVersion, majorDesktopVersion } =
+ stringToVersionKey(versionKey);
+
+ const platformDetails = {
+ platform,
+ codeVersion,
+ stateVersion,
+ majorDesktopVersion,
+ };
+
+ const inputData = transformInputBase(
+ notifCreatorInputBase,
+ platformDetails,
+ );
+
+ promises.push(
+ (async () => {
+ return (
+ await notifCreatorCallback(encryptedNotifUtilsAPI, inputData, devices)
+ ).map(targetedNotification => ({
+ platform,
+ targetedNotification,
+ }));
+ })(),
+ );
+ }
+
+ return (await Promise.all(promises)).flat();
+}
type BuildNotifsForUserDevicesInputData = {
+encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
@@ -450,196 +590,263 @@
const iosVersionToDevices = devicesByPlatform.get('ios');
if (iosVersionToDevices) {
- for (const [versionKey, devices] of iosVersionToDevices) {
- const { codeVersion, stateVersion } = stringToVersionKey(versionKey);
- const platformDetails = {
+ promises.push(
+ buildNotifsForPlatform({
platform: 'ios',
- codeVersion,
- stateVersion,
- };
- const shimmedNewRawMessageInfos = shimUnsupportedRawMessageInfos(
- newRawMessageInfos,
- platformDetails,
- );
-
- promises.push(
- (async () => {
- return (
- await createAPNsVisualNotification(
- encryptedNotifUtilsAPI,
- {
- senderDeviceDescriptor,
- notifTexts,
- newRawMessageInfos: shimmedNewRawMessageInfos,
- threadID,
- collapseKey: undefined,
- badgeOnly,
- unreadCount: undefined,
- platformDetails,
- uniqueID: uuidv4(),
- },
- devices,
- )
- ).map(targetedNotification => ({
- platform: 'ios',
- targetedNotification,
- }));
- })(),
- );
- }
+ encryptedNotifUtilsAPI,
+ notifCreatorCallback: createAPNsVisualNotification,
+ transformInputBase: (inputBase, platformDetails) => ({
+ ...inputBase,
+ newRawMessageInfos: shimUnsupportedRawMessageInfos(
+ newRawMessageInfos,
+ platformDetails,
+ ),
+ platformDetails,
+ }),
+ notifCreatorInputBase: {
+ senderDeviceDescriptor,
+ notifTexts,
+ threadID,
+ collapseKey: undefined,
+ badgeOnly,
+ uniqueID: uuidv4(),
+ },
+ versionToDevices: iosVersionToDevices,
+ }),
+ );
}
const androidVersionToDevices = devicesByPlatform.get('android');
if (androidVersionToDevices) {
- for (const [versionKey, devices] of androidVersionToDevices) {
- const { codeVersion, stateVersion } = stringToVersionKey(versionKey);
- const platformDetails = {
+ promises.push(
+ buildNotifsForPlatform({
platform: 'android',
- codeVersion,
- stateVersion,
- };
- const shimmedNewRawMessageInfos = shimUnsupportedRawMessageInfos(
- newRawMessageInfos,
- platformDetails,
- );
-
- promises.push(
- (async () => {
- return (
- await createAndroidVisualNotification(
- encryptedNotifUtilsAPI,
- {
- senderDeviceDescriptor,
- notifTexts,
- newRawMessageInfos: shimmedNewRawMessageInfos,
- threadID,
- collapseKey: undefined,
- badgeOnly,
- unreadCount: undefined,
- platformDetails,
- notifID: uuidv4(),
- },
- devices,
- )
- ).map(targetedNotification => ({
- platform: 'android',
- targetedNotification,
- }));
- })(),
- );
- }
+ encryptedNotifUtilsAPI,
+ notifCreatorCallback: createAndroidVisualNotification,
+ transformInputBase: (inputBase, platformDetails) => ({
+ ...inputBase,
+ newRawMessageInfos: shimUnsupportedRawMessageInfos(
+ newRawMessageInfos,
+ platformDetails,
+ ),
+ platformDetails,
+ }),
+ notifCreatorInputBase: {
+ senderDeviceDescriptor,
+ notifTexts,
+ threadID,
+ collapseKey: undefined,
+ badgeOnly,
+ notifID: uuidv4(),
+ },
+ versionToDevices: androidVersionToDevices,
+ }),
+ );
}
const macosVersionToDevices = devicesByPlatform.get('macos');
if (macosVersionToDevices) {
- for (const [versionKey, devices] of macosVersionToDevices) {
- const { codeVersion, stateVersion, majorDesktopVersion } =
- stringToVersionKey(versionKey);
- const platformDetails = {
+ promises.push(
+ buildNotifsForPlatform({
platform: 'macos',
- codeVersion,
- stateVersion,
- majorDesktopVersion,
- };
- const shimmedNewRawMessageInfos = shimUnsupportedRawMessageInfos(
- newRawMessageInfos,
- platformDetails,
- );
-
- promises.push(
- (async () => {
- return (
- await createAPNsVisualNotification(
- encryptedNotifUtilsAPI,
- {
- senderDeviceDescriptor,
- notifTexts,
- newRawMessageInfos: shimmedNewRawMessageInfos,
- threadID,
- collapseKey: undefined,
- badgeOnly,
- unreadCount: undefined,
- platformDetails,
- uniqueID: uuidv4(),
- },
- devices,
- )
- ).map(targetedNotification => ({
- platform: 'macos',
- targetedNotification,
- }));
- })(),
- );
- }
+ encryptedNotifUtilsAPI,
+ notifCreatorCallback: createAPNsVisualNotification,
+ transformInputBase: (inputBase, platformDetails) => ({
+ ...inputBase,
+ newRawMessageInfos: shimUnsupportedRawMessageInfos(
+ newRawMessageInfos,
+ platformDetails,
+ ),
+ platformDetails,
+ }),
+ notifCreatorInputBase: {
+ senderDeviceDescriptor,
+ notifTexts,
+ threadID,
+ collapseKey: undefined,
+ badgeOnly,
+ uniqueID: uuidv4(),
+ },
+ versionToDevices: macosVersionToDevices,
+ }),
+ );
}
const windowsVersionToDevices = devicesByPlatform.get('windows');
if (windowsVersionToDevices) {
- for (const [versionKey, devices] of windowsVersionToDevices) {
- const { codeVersion, stateVersion, majorDesktopVersion } =
- stringToVersionKey(versionKey);
- const platformDetails = {
+ promises.push(
+ buildNotifsForPlatform({
platform: 'windows',
- codeVersion,
- stateVersion,
- majorDesktopVersion,
- };
-
- promises.push(
- (async () => {
- return (
- await createWNSNotification(
- encryptedNotifUtilsAPI,
- {
- notifTexts,
- threadID,
- senderDeviceDescriptor,
- platformDetails,
- },
- devices,
- )
- ).map(targetedNotification => ({
- platform: 'windows',
- targetedNotification,
- }));
- })(),
- );
- }
+ encryptedNotifUtilsAPI,
+ notifCreatorCallback: createWNSNotification,
+ notifCreatorInputBase: {
+ senderDeviceDescriptor,
+ notifTexts,
+ threadID,
+ },
+ transformInputBase: (inputBase, platformDetails) => ({
+ ...inputBase,
+ platformDetails,
+ }),
+ versionToDevices: windowsVersionToDevices,
+ }),
+ );
}
const webVersionToDevices = devicesByPlatform.get('web');
if (webVersionToDevices) {
- for (const [versionKey, devices] of webVersionToDevices) {
- const { codeVersion, stateVersion } = stringToVersionKey(versionKey);
- const platformDetails = {
+ promises.push(
+ buildNotifsForPlatform({
platform: 'web',
- codeVersion,
- stateVersion,
- };
+ encryptedNotifUtilsAPI,
+ notifCreatorCallback: createWebNotification,
+ notifCreatorInputBase: {
+ senderDeviceDescriptor,
+ notifTexts,
+ threadID,
+ id: uuidv4(),
+ },
+ transformInputBase: (inputBase, platformDetails) => ({
+ ...inputBase,
+ platformDetails,
+ }),
+ versionToDevices: webVersionToDevices,
+ }),
+ );
+ }
- promises.push(
- (async () => {
- return (
- await createWebNotification(
- encryptedNotifUtilsAPI,
- {
- notifTexts,
- threadID,
- senderDeviceDescriptor,
- platformDetails,
- id: uuidv4(),
- },
- devices,
- )
- ).map(targetedNotification => ({
- platform: 'web',
- targetedNotification,
- }));
- })(),
- );
- }
+ return (await Promise.all(promises)).flat();
+}
+
+async function buildRescindsForOwnDevices(
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
+ devicesByPlatform: $ReadOnlyMap<
+ Platform,
+ $ReadOnlyMap<string, $ReadOnlyArray<NotificationTargetDevice>>,
+ >,
+ rescindData: { +threadID: string },
+): Promise<$ReadOnlyArray<TargetedNotificationWithPlatform>> {
+ const { threadID } = rescindData;
+ const promises: Array<
+ Promise<$ReadOnlyArray<TargetedNotificationWithPlatform>>,
+ > = [];
+
+ const iosVersionToDevices = devicesByPlatform.get('ios');
+ if (iosVersionToDevices) {
+ promises.push(
+ buildNotifsForPlatform({
+ platform: 'ios',
+ encryptedNotifUtilsAPI,
+ notifCreatorCallback: createAPNsNotificationRescind,
+ notifCreatorInputBase: {
+ senderDeviceDescriptor,
+ threadID,
+ },
+ transformInputBase: (inputBase, platformDetails) => ({
+ ...inputBase,
+ platformDetails,
+ }),
+ versionToDevices: iosVersionToDevices,
+ }),
+ );
}
+ const androidVersionToDevices = devicesByPlatform.get('android');
+ if (androidVersionToDevices) {
+ promises.push(
+ buildNotifsForPlatform({
+ platform: 'android',
+ encryptedNotifUtilsAPI,
+ notifCreatorCallback: createAndroidNotificationRescind,
+ notifCreatorInputBase: {
+ senderDeviceDescriptor,
+ threadID,
+ },
+ transformInputBase: (inputBase, platformDetails) => ({
+ ...inputBase,
+ platformDetails,
+ }),
+ versionToDevices: androidVersionToDevices,
+ }),
+ );
+ }
+ return (await Promise.all(promises)).flat();
+}
+
+async function buildBadgeUpdatesForOwnDevices(
+ encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ senderDeviceDescriptor: SenderDeviceDescriptor,
+ devicesByPlatform: $ReadOnlyMap<
+ Platform,
+ $ReadOnlyMap<string, $ReadOnlyArray<NotificationTargetDevice>>,
+ >,
+ badgeUpdateData: { +threadID: string },
+): Promise<$ReadOnlyArray<TargetedNotificationWithPlatform>> {
+ const { threadID } = badgeUpdateData;
+ const promises: Array<
+ Promise<$ReadOnlyArray<TargetedNotificationWithPlatform>>,
+ > = [];
+
+ const iosVersionToDevices = devicesByPlatform.get('ios');
+ if (iosVersionToDevices) {
+ promises.push(
+ buildNotifsForPlatform({
+ platform: 'ios',
+ encryptedNotifUtilsAPI,
+ notifCreatorCallback: createAPNsBadgeOnlyNotification,
+ notifCreatorInputBase: {
+ senderDeviceDescriptor,
+ threadID,
+ },
+ transformInputBase: (inputBase, platformDetails) => ({
+ ...inputBase,
+ platformDetails,
+ }),
+ versionToDevices: iosVersionToDevices,
+ }),
+ );
+ }
+
+ const androidVersionToDevices = devicesByPlatform.get('android');
+ if (androidVersionToDevices) {
+ promises.push(
+ buildNotifsForPlatform({
+ platform: 'android',
+ encryptedNotifUtilsAPI,
+ notifCreatorCallback: createAndroidBadgeOnlyNotification,
+ notifCreatorInputBase: {
+ senderDeviceDescriptor,
+ threadID,
+ },
+ transformInputBase: (inputBase, platformDetails) => ({
+ ...inputBase,
+ platformDetails,
+ }),
+ versionToDevices: androidVersionToDevices,
+ }),
+ );
+ }
+
+ const macosVersionToDevices = devicesByPlatform.get('macos');
+ if (macosVersionToDevices) {
+ promises.push(
+ buildNotifsForPlatform({
+ platform: 'macos',
+ encryptedNotifUtilsAPI,
+ notifCreatorCallback: createAPNsBadgeOnlyNotification,
+ notifCreatorInputBase: {
+ senderDeviceDescriptor,
+ threadID,
+ },
+ transformInputBase: (inputBase, platformDetails) => ({
+ ...inputBase,
+ platformDetails,
+ }),
+ versionToDevices: macosVersionToDevices,
+ }),
+ );
+ }
return (await Promise.all(promises)).flat();
}
@@ -741,6 +948,43 @@
return promiseAll(perUserBuildNotifsResultPromises);
}
+async function createOlmSessionWithDevices(
+ deviceIDsToUserIDs: {
+ +[string]: string,
+ },
+ olmSessionCreator: (userID: string, deviceID: string) => Promise<void>,
+): Promise<void> {
+ const {
+ initializeCryptoAccount,
+ isNotificationsSessionInitializedWithDevices,
+ } = getConfig().olmAPI;
+ await initializeCryptoAccount();
+
+ const deviceIDsToSessionPresence =
+ await isNotificationsSessionInitializedWithDevices(
+ Object.keys(deviceIDsToUserIDs),
+ );
+
+ const olmSessionCreationPromises = [];
+ for (const deviceID in deviceIDsToSessionPresence) {
+ if (deviceIDsToSessionPresence[deviceID]) {
+ continue;
+ }
+ olmSessionCreationPromises.push(
+ olmSessionCreator(deviceIDsToUserIDs[deviceID], deviceID),
+ );
+ }
+
+ try {
+ await Promise.allSettled(olmSessionCreationPromises);
+ } catch (e) {
+ // session creation may fail for some devices
+ // but we should still pursue notification
+ // delivery for others
+ console.log(e);
+ }
+}
+
type PreparePushNotifsInputData = {
+encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+senderDeviceDescriptor: SenderDeviceDescriptor,
@@ -748,7 +992,7 @@
+messageInfos: { +[id: string]: RawMessageInfo },
+thickRawThreadInfos: ThickRawThreadInfos,
+auxUserInfos: AuxUserInfos,
- +messageDatas: $ReadOnlyArray<MessageData>,
+ +messageDatas: ?$ReadOnlyArray<MessageData>,
+userInfos: UserInfos,
+getENSNames: ?GetENSNames,
+getFCNames: ?GetFCNames,
@@ -781,12 +1025,6 @@
return null;
}
- const {
- initializeCryptoAccount,
- isNotificationsSessionInitializedWithDevices,
- } = getConfig().olmAPI;
- await initializeCryptoAccount();
-
const deviceIDsToUserIDs: { [string]: string } = {};
for (const userID in pushInfos) {
for (const device of pushInfos[userID].devices) {
@@ -794,29 +1032,7 @@
}
}
- const deviceIDsToSessionPresence =
- await isNotificationsSessionInitializedWithDevices(
- Object.keys(deviceIDsToUserIDs),
- );
-
- const olmSessionCreationPromises = [];
- for (const deviceID in deviceIDsToSessionPresence) {
- if (deviceIDsToSessionPresence[deviceID]) {
- continue;
- }
- olmSessionCreationPromises.push(
- olmSessionCreator(deviceIDsToUserIDs[deviceID], deviceID),
- );
- }
-
- try {
- await Promise.allSettled(olmSessionCreationPromises);
- } catch (e) {
- // session creation may fail for some devices
- // but we should still pursue notification
- // delivery for others
- console.log(e);
- }
+ await createOlmSessionWithDevices(deviceIDsToUserIDs, olmSessionCreator);
return await buildNotifsFromPushInfo({
encryptedNotifUtilsAPI,
@@ -829,8 +1045,65 @@
});
}
+type PrepareOwnDevicesPushNotifsInputData = {
+ +encryptedNotifUtilsAPI: EncryptedNotifUtilsAPI,
+ +senderInfo: SenderInfo,
+ +olmSessionCreator: (userID: string, deviceID: string) => Promise<void>,
+ +auxUserInfos: AuxUserInfos,
+ +rescindData?: { threadID: string },
+ +badgeUpdateData?: { threadID: string },
+};
+
+async function prepareOwnDevicesPushNotifs(
+ inputData: PrepareOwnDevicesPushNotifsInputData,
+): Promise<?$ReadOnlyArray<TargetedNotificationWithPlatform>> {
+ const {
+ encryptedNotifUtilsAPI,
+ senderInfo,
+ olmSessionCreator,
+ auxUserInfos,
+ rescindData,
+ badgeUpdateData,
+ } = inputData;
+
+ const ownDevicesPushInfo = getOwnDevicesPushInfo(senderInfo, auxUserInfos);
+
+ if (!ownDevicesPushInfo) {
+ return null;
+ }
+
+ const { senderUserID, senderDeviceDescriptor } = senderInfo;
+ const deviceIDsToUserIDs: { [string]: string } = {};
+
+ for (const device of ownDevicesPushInfo.devices) {
+ deviceIDsToUserIDs[device.cryptoID] = senderUserID;
+ }
+
+ await createOlmSessionWithDevices(deviceIDsToUserIDs, olmSessionCreator);
+ const devicesByPlatform = getDevicesByPlatform(ownDevicesPushInfo.devices);
+
+ if (rescindData) {
+ return await buildRescindsForOwnDevices(
+ encryptedNotifUtilsAPI,
+ senderDeviceDescriptor,
+ devicesByPlatform,
+ rescindData,
+ );
+ } else if (badgeUpdateData) {
+ return await buildBadgeUpdatesForOwnDevices(
+ encryptedNotifUtilsAPI,
+ senderDeviceDescriptor,
+ devicesByPlatform,
+ badgeUpdateData,
+ );
+ } else {
+ return null;
+ }
+}
+
export {
preparePushNotifs,
+ prepareOwnDevicesPushNotifs,
generateNotifUserInfoPromise,
pushInfoToCollapsableNotifInfo,
mergeUserToCollapsableInfo,
diff --git a/lib/shared/dm-ops/change-thread-read-status-spec.js b/lib/shared/dm-ops/change-thread-read-status-spec.js
--- a/lib/shared/dm-ops/change-thread-read-status-spec.js
+++ b/lib/shared/dm-ops/change-thread-read-status-spec.js
@@ -11,6 +11,15 @@
const changeThreadReadStatusSpec: DMOperationSpec<DMChangeThreadReadStatusOperation> =
Object.freeze({
+ notificationsCreationData: async (
+ dmOperation: DMChangeThreadReadStatusOperation,
+ ) => {
+ const { threadID, unread } = dmOperation;
+ if (unread) {
+ return { badgeUpdateData: { threadID } };
+ }
+ return { rescindData: { threadID } };
+ },
processDMOperation: async (
dmOperation: DMChangeThreadReadStatusOperation,
) => {
diff --git a/lib/types/notif-types.js b/lib/types/notif-types.js
--- a/lib/types/notif-types.js
+++ b/lib/types/notif-types.js
@@ -28,9 +28,14 @@
prefix: t.maybe(t.String),
});
-export type NotificationsCreationData = {
- +messageDatas: $ReadOnlyArray<MessageData>,
-};
+export type NotificationsCreationData =
+ | {
+ +messageDatas: $ReadOnlyArray<MessageData>,
+ }
+ | {
+ +rescindData: { threadID: string },
+ }
+ | { +badgeUpdateData: { threadID: string } };
export type SenderDeviceDescriptor =
| { +keyserverID: string }

File Metadata

Mime Type
text/plain
Expires
Sun, Dec 1, 9:21 PM (18 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2606148
Default Alt Text
D13164.id43860.diff (28 KB)

Event Timeline