diff --git a/android/app/src/main/java/com/mattermost/rnbeta/CustomPushNotification.java b/android/app/src/main/java/com/mattermost/rnbeta/CustomPushNotification.java index b05473f7b..b497688f8 100644 --- a/android/app/src/main/java/com/mattermost/rnbeta/CustomPushNotification.java +++ b/android/app/src/main/java/com/mattermost/rnbeta/CustomPushNotification.java @@ -50,6 +50,7 @@ public class CustomPushNotification extends PushNotification { private static final String PUSH_TYPE_MESSAGE = "message"; private static final String PUSH_TYPE_CLEAR = "clear"; + private static final String PUSH_TYPE_SESSION = "session"; private static final String PUSH_TYPE_UPDATE_BADGE = "update_badge"; private NotificationChannel mHighImportanceChannel; @@ -163,6 +164,7 @@ public class CustomPushNotification extends PushNotification { switch(type) { case PUSH_TYPE_MESSAGE: + case PUSH_TYPE_SESSION: super.postNotification(notificationId); break; case PUSH_TYPE_CLEAR: @@ -177,8 +179,10 @@ public class CustomPushNotification extends PushNotification { public void onOpened() { Bundle data = mNotificationProps.asBundle(); final String channelId = data.getString("channel_id"); - channelIdToNotificationCount.remove(channelId); - channelIdToNotification.remove(channelId); + if (channelId != null) { + channelIdToNotificationCount.remove(channelId); + channelIdToNotification.remove(channelId); + } digestNotification(); } @@ -222,7 +226,9 @@ public class CustomPushNotification extends PushNotification { } String channelId = bundle.getString("channel_id"); - userInfoBundle.putString("channel_id", channelId); + if (channelId != null) { + userInfoBundle.putString("channel_id", channelId); + } notification.addExtras(userInfoBundle); } @@ -459,7 +465,8 @@ public class CustomPushNotification extends PushNotification { private void addNotificationReplyAction(Notification.Builder notification, int notificationId, Bundle bundle) { String postId = bundle.getString("post_id"); - if (postId == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + + if (android.text.TextUtils.isEmpty(postId) || Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { return; } diff --git a/app/utils/push_notifications.js b/app/init/push_notifications.js similarity index 83% rename from app/utils/push_notifications.js rename to app/init/push_notifications.js index 5a04ec772..f98efacdd 100644 --- a/app/utils/push_notifications.js +++ b/app/init/push_notifications.js @@ -4,11 +4,6 @@ import {Platform} from 'react-native'; import DeviceInfo from 'react-native-device-info'; -import {setDeviceToken} from '@mm-redux/actions/general'; -import {Client4} from '@mm-redux/client'; -import {General} from '@mm-redux/constants'; -import EventEmitter from '@mm-redux/utils/event_emitter'; - import {markChannelViewedAndRead, fetchPostActionWithRetry} from '@actions/views/channel'; import {dismissAllModals, popToRoot} from '@actions/navigation'; import {getPosts} from '@actions/views/post'; @@ -16,18 +11,28 @@ import { createPostForNotificationReply, loadFromPushNotification, } from '@actions/views/root'; - +import {logout} from '@actions/views/user'; import {NavigationTypes, ViewTypes} from '@constants'; import {getLocalizedMessage} from '@i18n'; +import {getCurrentServerUrl, getAppCredentials} from '@init/credentials'; +import {setDeviceToken} from '@mm-redux/actions/general'; +import {Client4} from '@mm-redux/client'; +import {General} from '@mm-redux/constants'; +import EventEmitter from '@mm-redux/utils/event_emitter'; import {getCurrentLocale} from '@selectors/i18n'; import EphemeralStore from '@store/ephemeral_store'; import Store from '@store/store'; import {waitForHydration} from '@store/utils'; import {t} from '@utils/i18n'; -import {getCurrentServerUrl, getAppCredentials} from 'app/init/credentials'; import PushNotifications from 'app/push_notifications'; +const NOTIFICATION_TYPE = { + CLEAR: 'clear', + MESSAGE: 'message', + SESSION: 'session', +}; + class PushNotificationUtils { constructor() { this.configured = false; @@ -70,20 +75,28 @@ class PushNotificationUtils { message, }; - if (data.type === 'clear') { - dispatch(markChannelViewedAndRead(data.channel_id, null, false)); - } else if (data.type === 'message') { - // get the posts for the channel as soon as possible - dispatch(fetchPostActionWithRetry(getPosts(data.channel_id))); + waitForHydration(Store.redux, () => { + switch (data.type) { + case NOTIFICATION_TYPE.CLEAR: + dispatch(markChannelViewedAndRead(data.channel_id, null, false)); + break; + case NOTIFICATION_TYPE.MESSAGE: + // get the posts for the channel as soon as possible + dispatch(fetchPostActionWithRetry(getPosts(data.channel_id))); - if (foreground) { - EventEmitter.emit(ViewTypes.NOTIFICATION_IN_APP, notification); - } else if (userInteraction && !notification?.data?.localNotification) { - waitForHydration(Store.redux, () => { + if (foreground) { + EventEmitter.emit(ViewTypes.NOTIFICATION_IN_APP, notification); + } else if (userInteraction && !notification?.data?.localNotification) { this.loadFromNotification(notification); - }); + } + break; + case NOTIFICATION_TYPE.SESSION: + // eslint-disable-next-line no-console + console.log('Session expired notification'); + dispatch(logout()); + break; } - } + }); }; onPushNotificationReply = async (data, text, completion) => { @@ -174,4 +187,4 @@ class PushNotificationUtils { }; } -export default new PushNotificationUtils(); +export default new PushNotificationUtils(); \ No newline at end of file diff --git a/app/mattermost.js b/app/mattermost.js index 7600309d9..cf6d9306f 100644 --- a/app/mattermost.js +++ b/app/mattermost.js @@ -17,6 +17,7 @@ import emmProvider from '@init/emm_provider'; import '@init/device'; import '@init/fetch'; import globalEventHandler from '@init/global_event_handler'; +import pushNotifications from '@init/push_notifications'; import {registerScreens} from '@screens'; import configureStore from '@store'; import EphemeralStore from '@store/ephemeral_store'; @@ -24,7 +25,6 @@ import getStorage from '@store/mmkv_adapter'; import Store from '@store/store'; import {waitForHydration} from '@store/utils'; import {validatePreviousVersion} from '@utils/general'; -import pushNotificationsUtils from '@utils/push_notifications'; import {captureJSException} from '@utils/sentry'; const init = async () => { @@ -37,7 +37,7 @@ const init = async () => { return; } - pushNotificationsUtils.configure(); + pushNotifications.configure(); globalEventHandler.configure({ launchApp, }); diff --git a/ios/Mattermost/AppDelegate.m b/ios/Mattermost/AppDelegate.m index 1338933e8..e976a41e9 100644 --- a/ios/Mattermost/AppDelegate.m +++ b/ios/Mattermost/AppDelegate.m @@ -71,24 +71,18 @@ NSString* const NOTIFICATION_UPDATE_BADGE_ACTION = @"update_badge"; NSString* action = [userInfo objectForKey:@"type"]; NSString* channelId = [userInfo objectForKey:@"channel_id"]; NSString* ackId = [userInfo objectForKey:@"ack_id"]; + RuntimeUtils *utils = [[RuntimeUtils alloc] init]; - if (action && [action isEqualToString: NOTIFICATION_CLEAR_ACTION]) { + if ((action && [action isEqualToString: NOTIFICATION_CLEAR_ACTION]) || (state == UIApplicationStateInactive)) { // If received a notification that a channel was read, remove all notifications from that channel (only with app in foreground/background) [self cleanNotificationsFromChannel:channelId]; - RuntimeUtils *utils = [[RuntimeUtils alloc] init]; - [[UploadSession shared] notificationReceiptWithNotificationId:ackId receivedAt:round([[NSDate date] timeIntervalSince1970] * 1000.0) type:action]; - [utils delayWithSeconds:0.2 closure:^(void) { - // This is to notify the NotificationCenter that something has changed. - completionHandler(UIBackgroundFetchResultNewData); - }]; - - return; - } else if (state == UIApplicationStateInactive) { - // When the notification is opened - [self cleanNotificationsFromChannel:channelId]; } - completionHandler(UIBackgroundFetchResultNoData); + [[UploadSession shared] notificationReceiptWithNotificationId:ackId receivedAt:round([[NSDate date] timeIntervalSince1970] * 1000.0) type:action]; + [utils delayWithSeconds:0.2 closure:^(void) { + // This is to notify the NotificationCenter that something has changed. + completionHandler(UIBackgroundFetchResultNewData); + }]; } -(void)cleanNotificationsFromChannel:(NSString *)channelId { diff --git a/ios/NotificationService/NotificationService.swift b/ios/NotificationService/NotificationService.swift index 1051541df..19cb6e462 100644 --- a/ios/NotificationService/NotificationService.swift +++ b/ios/NotificationService/NotificationService.swift @@ -49,9 +49,9 @@ class NotificationService: UNNotificationServiceExtension { bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) if let bestAttemptContent = bestAttemptContent { - let ackId = bestAttemptContent.userInfo["ack_id"] as! String - let type = bestAttemptContent.userInfo["type"] as! String - let postId = bestAttemptContent.userInfo["post_id"] as! String + let ackId = (bestAttemptContent.userInfo["ack_id"] ?? "") as! String + let type = (bestAttemptContent.userInfo["type"] ?? "") as! String + let postId = (bestAttemptContent.userInfo["post_id"] ?? "") as! String let idLoaded = (bestAttemptContent.userInfo["id_loaded"] ?? false) as! Bool fetchReceipt( diff --git a/packager/moduleNames.js b/packager/moduleNames.js index 335c7db0c..e551a1d7a 100644 --- a/packager/moduleNames.js +++ b/packager/moduleNames.js @@ -29,6 +29,7 @@ module.exports = [ 'app/init/emm_provider.js', 'app/init/fetch.js', 'app/init/global_event_handler.js', + 'app/init/push_notifications.js', 'app/mattermost.js', 'app/mattermost_bucket/index.js', 'app/mattermost_managed/index.js', @@ -182,7 +183,6 @@ module.exports = [ 'app/utils/general.js', 'app/utils/i18n.js', 'app/utils/preferences.js', - 'app/utils/push_notifications.js', 'app/utils/security.js', 'app/utils/sentry/index.js', 'app/utils/time_tracker.js', diff --git a/packager/modulePaths.js b/packager/modulePaths.js index d4ff581b1..6c59538bd 100644 --- a/packager/modulePaths.js +++ b/packager/modulePaths.js @@ -29,6 +29,7 @@ module.exports = [ './node_modules/app/init/emm_provider.js', './node_modules/app/init/fetch.js', './node_modules/app/init/global_event_handler.js', + './node_modules/app/init/push_notifications.js', './node_modules/app/mattermost.js', './node_modules/app/mattermost_bucket/index.js', './node_modules/app/mattermost_managed/index.js', @@ -182,7 +183,6 @@ module.exports = [ './node_modules/app/utils/general.js', './node_modules/app/utils/i18n.js', './node_modules/app/utils/preferences.js', - './node_modules/app/utils/push_notifications.js', './node_modules/app/utils/security.js', './node_modules/app/utils/sentry/index.js', './node_modules/app/utils/time_tracker.js',