diff --git a/lib/utils/migration-utils.js b/lib/utils/migration-utils.js --- a/lib/utils/migration-utils.js +++ b/lib/utils/migration-utils.js @@ -3,7 +3,10 @@ import type { TranslatedThreadMessageInfos } from './message-ops-utils.js'; import { entries } from './objects.js'; import { keyserverPrefixID } from './validation-utils.js'; -import { convertRawThreadInfoToNewIDSchema } from '../_generated/migration-utils.js'; +import { + convertRawMessageInfoToNewIDSchema, + convertRawThreadInfoToNewIDSchema, +} from '../_generated/migration-utils.js'; import { parsePendingThreadID, getPendingThreadID, @@ -14,6 +17,7 @@ ClientDBDraftStoreOperation, DraftStore, } from '../types/draft-types'; +import type { RawMessageInfo } from '../types/message-types.js'; import type { ThreadStoreThreadInfos } from '../types/thread-types.js'; function convertDraftKeyToNewIDSchema(key: string): string { @@ -86,10 +90,33 @@ ); } +function convertNotificationThreadIDToNewIDSchema(threadID: string): string { + if (threadID.indexOf('|') === -1) { + return `${keyserverPrefixID}|${threadID}`; + } + return threadID; +} + +function convertNotificationMessageInfoToNewIDSchema( + messageInfosString: ?string, +): ?$ReadOnlyArray { + let messageInfos: ?$ReadOnlyArray = null; + if (messageInfosString) { + messageInfos = JSON.parse(messageInfosString); + } + + if (messageInfos?.some(message => message.threadID.indexOf('|') === -1)) { + messageInfos = messageInfos?.map(convertRawMessageInfoToNewIDSchema); + } + return messageInfos; +} + export { convertDraftKeyToNewIDSchema, convertDraftStoreToNewIDSchema, generateIDSchemaMigrationOpsForDrafts, convertMessageStoreThreadsToNewIDSchema, convertThreadStoreThreadInfosToNewIDSchema, + convertNotificationThreadIDToNewIDSchema, + convertNotificationMessageInfoToNewIDSchema, }; diff --git a/native/push/android.js b/native/push/android.js --- a/native/push/android.js +++ b/native/push/android.js @@ -3,6 +3,11 @@ import { NativeModules, NativeEventEmitter } from 'react-native'; import { mergePrefixIntoBody } from 'lib/shared/notif-utils.js'; +import type { RawMessageInfo } from 'lib/types/message-types.js'; +import { + convertNotificationThreadIDToNewIDSchema, + convertNotificationMessageInfoToNewIDSchema, +} from 'lib/utils/migration-utils.js'; type CommAndroidNotificationsConstants = { +NOTIFICATIONS_IMPORTANCE_HIGH: number, @@ -37,13 +42,28 @@ +messageInfos: ?string, }; +export type ParsedAndroidMessage = { + ...AndroidMessage, + +messageInfos: ?$ReadOnlyArray, +}; + +function parseAndroidMessage(message: AndroidMessage): ParsedAndroidMessage { + return { + ...message, + threadID: convertNotificationThreadIDToNewIDSchema(message.threadID), + messageInfos: convertNotificationMessageInfoToNewIDSchema( + message.messageInfos, + ), + }; +} + const { CommAndroidNotificationsEventEmitter } = NativeModules; const CommAndroidNotifications: CommAndroidNotificationsModuleType = NativeModules.CommAndroidNotifications; const androidNotificationChannelID = 'default'; function handleAndroidMessage( - message: AndroidMessage, + message: ParsedAndroidMessage, updatesCurrentAsOf: number, handleIfActive?: ( threadID: string, @@ -72,6 +92,7 @@ } export { + parseAndroidMessage, androidNotificationChannelID, handleAndroidMessage, getCommAndroidNotificationsEventEmitter, diff --git a/native/push/comm-ios-notification.js b/native/push/comm-ios-notification.js --- a/native/push/comm-ios-notification.js +++ b/native/push/comm-ios-notification.js @@ -2,6 +2,12 @@ import { NativeModules } from 'react-native'; +import type { RawMessageInfo } from 'lib/types/message-types.js'; +import { + convertNotificationThreadIDToNewIDSchema, + convertNotificationMessageInfoToNewIDSchema, +} from 'lib/utils/migration-utils.js'; + const { CommIOSNotifications } = NativeModules; // This is the basic data we receive from Objective-C @@ -30,20 +36,32 @@ +identifier: string, }; +export type ParsedCoreIOSNotificationData = { + ...CoreIOSNotificationData, + +messageInfos: ?$ReadOnlyArray, +}; + export class CommIOSNotification { - data: CoreIOSNotificationData; + data: ParsedCoreIOSNotificationData; remoteNotificationCompleteCallbackCalled: boolean; constructor(notification: CoreIOSNotificationData) { - this.data = notification; this.remoteNotificationCompleteCallbackCalled = false; + + this.data = { + ...notification, + threadID: convertNotificationThreadIDToNewIDSchema(notification.threadID), + messageInfos: convertNotificationMessageInfoToNewIDSchema( + notification.messageInfos, + ), + }; } getMessage(): ?string { return this.data.message; } - getData(): CoreIOSNotificationData { + getData(): ParsedCoreIOSNotificationData { return this.data; } diff --git a/native/push/push-handler.react.js b/native/push/push-handler.react.js --- a/native/push/push-handler.react.js +++ b/native/push/push-handler.react.js @@ -26,6 +26,10 @@ useDispatchActionPromise, type DispatchActionPromise, } from 'lib/utils/action-utils.js'; +import { + convertNotificationMessageInfoToNewIDSchema, + convertNotificationThreadIDToNewIDSchema, +} from 'lib/utils/migration-utils.js'; import { type NotifPermissionAlertInfo, recordNotifPermissionAlertActionType, @@ -34,6 +38,7 @@ import sleep from 'lib/utils/sleep.js'; import { + parseAndroidMessage, androidNotificationChannelID, handleAndroidMessage, getCommAndroidNotificationsEventEmitter, @@ -153,7 +158,7 @@ commIOSNotificationsEventEmitter.addListener( CommIOSNotifications.getConstants() .NOTIFICATION_RECEIVED_BACKGROUND_EVENT, - backgroundData => this.saveMessageInfos(backgroundData?.messageInfos), + this.iosBackgroundNotificationReceived, ), ); } else if (Platform.OS === 'android') { @@ -476,12 +481,10 @@ } } - saveMessageInfos(messageInfosString: ?string) { - if (!messageInfosString) { + saveMessageInfos(rawMessageInfos: ?$ReadOnlyArray) { + if (!rawMessageInfos) { return; } - const rawMessageInfos: $ReadOnlyArray = - JSON.parse(messageInfosString); const { updatesCurrentAsOf } = this.props; this.props.dispatch({ type: saveMessagesActionType, @@ -529,6 +532,18 @@ ); }; + iosBackgroundNotificationReceived = backgroundData => { + const convertedMessageInfos = convertNotificationMessageInfoToNewIDSchema( + backgroundData.messageInfos, + ); + + if (!convertedMessageInfos) { + return; + } + + this.saveMessageInfos(convertedMessageInfos); + }; + onPushNotifBootsApp() { if ( this.props.rootContext && @@ -573,18 +588,21 @@ } androidNotificationOpened = async (threadID: string) => { + const convertedThreadID = + convertNotificationThreadIDToNewIDSchema(threadID); this.onPushNotifBootsApp(); - this.onPressNotificationForThread(threadID, true); + this.onPressNotificationForThread(convertedThreadID, true); }; androidMessageReceived = async (message: AndroidMessage) => { + const parsedMessage = parseAndroidMessage(message); this.onPushNotifBootsApp(); - const { messageInfos } = message; + const { messageInfos } = parsedMessage; this.saveMessageInfos(messageInfos); handleAndroidMessage( - message, + parsedMessage, this.props.updatesCurrentAsOf, this.handleAndroidNotificationIfActive, ); diff --git a/web/push-notif/push-notifs-handler.js b/web/push-notif/push-notifs-handler.js --- a/web/push-notif/push-notifs-handler.js +++ b/web/push-notif/push-notifs-handler.js @@ -13,6 +13,7 @@ useDispatchActionPromise, useServerCall, } from 'lib/utils/action-utils.js'; +import { convertNotificationThreadIDToNewIDSchema } from 'lib/utils/migration-utils.js'; import { shouldSkipPushPermissionAlert, recordNotifPermissionAlertActionType, @@ -43,9 +44,12 @@ React.useEffect( () => electron?.onNotificationClicked?.(({ threadID }) => { + const convertedThreadID = + convertNotificationThreadIDToNewIDSchema(threadID); + const payload = { chatMode: 'view', - activeChatThreadID: threadID, + activeChatThreadID: convertedThreadID, tab: 'chat', }; diff --git a/web/push-notif/service-worker.js b/web/push-notif/service-worker.js --- a/web/push-notif/service-worker.js +++ b/web/push-notif/service-worker.js @@ -1,6 +1,7 @@ // @flow import type { WebNotification } from 'lib/types/notif-types.js'; +import { convertNotificationThreadIDToNewIDSchema } from 'lib/utils/migration-utils.js'; declare class PushMessageData { json(): Object; @@ -54,19 +55,22 @@ const selectedClient = clientList.find(client => client.focused) ?? clientList[0]; + const threadID = convertNotificationThreadIDToNewIDSchema( + event.notification.data.threadID, + ); + if (selectedClient) { if (!selectedClient.focused) { await selectedClient.focus(); } selectedClient.postMessage({ - targetThreadID: event.notification.data.threadID, + targetThreadID: threadID, }); } else { const url = (process.env.NODE_ENV === 'production' ? 'https://web.comm.app' - : 'http://localhost:3000/comm') + - `/chat/thread/${event.notification.data.threadID}/`; + : 'http://localhost:3000/comm') + `/chat/thread/${threadID}/`; clients.openWindow(url); } })(),