MM-25931 Handle incoming session expired push notification (#4417)

This commit is contained in:
Elias Nahum 2020-06-17 21:30:19 -04:00
parent c9dae37414
commit b316ad5a20
No known key found for this signature in database
GPG key ID: E038DB71E0B61702
7 changed files with 57 additions and 43 deletions

View file

@ -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;
}

View file

@ -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();

View file

@ -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,
});

View file

@ -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 {

View file

@ -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(

View file

@ -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',

View file

@ -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',