Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3381369
D13164.id43870.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
28 KB
Referenced Files
None
Subscribers
None
D13164.id43870.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 29, 4:42 AM (20 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2594100
Default Alt Text
D13164.id43870.diff (28 KB)
Attached To
Mode
D13164: Implement code in lib to create thick threads rescinds and badge updates
Attached
Detach File
Event Timeline
Log In to Comment