From b0b4e55f216bfdcdbc8e3f182cd1e7112290f011 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Wed, 16 Feb 2022 22:58:01 -0300 Subject: [PATCH] Make iOS notifications compatible with background fetch (#5969) --- app/actions/views/root.js | 14 ++++++++------ app/init/push_notifications.ts | 13 +++++++++++++ app/types/push_notification.d.ts | 5 +++++ 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/app/actions/views/root.js b/app/actions/views/root.js index c82601b81..f60b211e0 100644 --- a/app/actions/views/root.js +++ b/app/actions/views/root.js @@ -76,7 +76,7 @@ export function loadConfigAndLicense() { }; } -export function loadFromPushNotification(notification, isInitialNotification) { +export function loadFromPushNotification(notification, isInitialNotification, skipChannelSwitch = false) { return async (dispatch, getState) => { const state = getState(); const {payload} = notification; @@ -108,12 +108,14 @@ export function loadFromPushNotification(notification, isInitialNotification) { await Promise.all(loading); } - dispatch(handleSelectTeamAndChannel(teamId, channelId)); - dispatch(selectPost('')); + if (!skipChannelSwitch) { + dispatch(handleSelectTeamAndChannel(teamId, channelId)); + dispatch(selectPost('')); - const {root_id: rootId} = notification.payload || {}; - if (isCollapsedThreadsEnabled(state) && rootId) { - dispatch(selectPost(rootId)); + const {root_id: rootId} = notification.payload || {}; + if (isCollapsedThreadsEnabled(state) && rootId) { + dispatch(selectPost(rootId)); + } } return {data: true}; }; diff --git a/app/init/push_notifications.ts b/app/init/push_notifications.ts index cf19b876d..98e92d783 100644 --- a/app/init/push_notifications.ts +++ b/app/init/push_notifications.ts @@ -173,6 +173,17 @@ class PushNotifications { EphemeralStore.setStartFromNotification(true); notification.userInteraction = true; + if (Platform.OS === 'ios') { + // when a notification is received on iOS, getInitialNotification, will return the notification + // as the app will initialized cause we are using background fetch, + // that does not necessarily mean that the app was opened cause of the notification was tapped. + // Here we are going to dettermine if the notification still exists in NotificationCenter to verify if + // the app was opened because of a tap or cause of the background fetch init + const delivered = await Notifications.ios.getDeliveredNotifications(); + notification.userInteraction = delivered.find((d) => (d as unknown as NotificationWithAck).ack_id === notification?.payload?.ack_id) == null; + notification.foreground = false; + } + // getInitialNotification may run before the store is set // that is why we run on an interval until the store is available // once we handle the notification the interval is cleared. @@ -221,6 +232,8 @@ class PushNotifications { } } } + } else if (!userInteraction && Platform.OS === 'ios') { + dispatch(loadFromPushNotification(notification, isInitialNotification, true)); } break; case NOTIFICATION_TYPE.SESSION: diff --git a/app/types/push_notification.d.ts b/app/types/push_notification.d.ts index 8f439bf7a..271db68a6 100644 --- a/app/types/push_notification.d.ts +++ b/app/types/push_notification.d.ts @@ -6,7 +6,12 @@ interface NotificationUserInfo { test?: boolean; } +interface NotificationWithAck extends Notification { + ack_id: string; +} + interface NotificationData { + ack_id: string; body?: string; channel_id: string; channel_name?: string;