From 7f756a9f816d27032802a24179b4587cfc6d49ea Mon Sep 17 00:00:00 2001 From: enahum Date: Wed, 14 Jun 2017 09:26:13 -0400 Subject: [PATCH] RN-35 handle clear push notifications (#624) --- .../mattermost/CustomPushNotification.java | 104 ++++++++++++++---- app/mattermost.js | 12 +- .../push_notifications.android.js | 6 +- 3 files changed, 90 insertions(+), 32 deletions(-) diff --git a/android/app/src/main/java/com/mattermost/CustomPushNotification.java b/android/app/src/main/java/com/mattermost/CustomPushNotification.java index a78613d9c..455afe960 100644 --- a/android/app/src/main/java/com/mattermost/CustomPushNotification.java +++ b/android/app/src/main/java/com/mattermost/CustomPushNotification.java @@ -9,6 +9,8 @@ import android.graphics.BitmapFactory; import android.os.Bundle; import android.os.Build; import android.app.Notification; +import android.app.NotificationManager; +import java.util.LinkedHashMap; import com.wix.reactnativenotifications.core.notification.PushNotification; import com.wix.reactnativenotifications.core.AppLaunchHelper; @@ -16,12 +18,43 @@ import com.wix.reactnativenotifications.core.AppLifecycleFacade; import com.wix.reactnativenotifications.core.JsIOHelper; import com.wix.reactnativenotifications.helpers.ApplicationBadgeHelper; +import static com.wix.reactnativenotifications.Defs.NOTIFICATION_RECEIVED_EVENT_NAME; + public class CustomPushNotification extends PushNotification { + public static final int MESSAGE_NOTIFICATION_ID = 435345; + public static final String GROUP_KEY_MESSAGES = "mm_group_key_messages"; + private static LinkedHashMap channelIdToNotificationCount = new LinkedHashMap(); + public CustomPushNotification(Context context, Bundle bundle, AppLifecycleFacade appLifecycleFacade, AppLaunchHelper appLaunchHelper, JsIOHelper jsIoHelper) { super(context, bundle, appLifecycleFacade, appLaunchHelper, jsIoHelper); } + @Override + public void onReceived() throws InvalidNotificationException { + Bundle data = mNotificationProps.asBundle(); + final String channelId = data.getString("channel_id"); + final String type = data.getString("type"); + int notificationId = MESSAGE_NOTIFICATION_ID; + if (channelId != null) { + notificationId = channelId.hashCode(); + Object objCount = channelIdToNotificationCount.get(channelId); + Integer count = 1; + if (objCount != null) { + count = (Integer)objCount + 1; + } + channelIdToNotificationCount.put(channelId, count); + } + + if ("clear".equals(type)) { + cancelNotification(data, notificationId); + } else { + super.postNotification(notificationId); + } + + notifyReceivedToJS(); + } + @Override protected void postNotification(int id, Notification notification) { if (!mAppLifecycleFacade.isAppVisible()) { @@ -42,31 +75,18 @@ public class CustomPushNotification extends PushNotification { ApplicationInfo appInfo = mContext.getApplicationInfo(); title = mContext.getPackageManager().getApplicationLabel(appInfo).toString(); } - notification.setContentTitle(title); + + int notificationId = bundle.getString("channel_id").hashCode(); String channelId = bundle.getString("channel_id"); - if (channelId != null) { - notification.setGroup(channelId).setGroupSummary(true); - } - notification.setContentText(bundle.getString("message")); - - String largeIcon = bundle.getString("largeIcon"); - + String message = bundle.getString("message"); String subText = bundle.getString("subText"); - - if (subText != null) { - notification.setSubText(subText); - } - String numberString = bundle.getString("badge"); - if (numberString != null) { - ApplicationBadgeHelper.instance.setApplicationIconBadgeNumber(mContext.getApplicationContext(), Integer.parseInt(numberString)); - } + String smallIcon = bundle.getString("smallIcon"); + String largeIcon = bundle.getString("largeIcon"); int smallIconResId; int largeIconResId; - String smallIcon = bundle.getString("smallIcon"); - if (smallIcon != null) { smallIconResId = res.getIdentifier(smallIcon, "mipmap", packageName); } else { @@ -87,17 +107,55 @@ public class CustomPushNotification extends PushNotification { largeIconResId = res.getIdentifier("ic_launcher", "mipmap", packageName); } - Bitmap largeIconBitmap = BitmapFactory.decodeResource(res, largeIconResId); + if (numberString != null) { + ApplicationBadgeHelper.instance.setApplicationIconBadgeNumber(mContext.getApplicationContext(), Integer.parseInt(numberString)); + } + int numMessages = 0; + Object objCount = channelIdToNotificationCount.get(channelId); + if (objCount != null) { + numMessages = (Integer)objCount; + } + + notification + .setContentTitle(title) + .setContentText(message) + .setGroup(GROUP_KEY_MESSAGES) + .setGroupSummary(true) + .setSmallIcon(smallIconResId) + .setVisibility(Notification.VISIBILITY_PRIVATE) + .setPriority(Notification.PRIORITY_HIGH); + + if (numMessages > 1) { + notification.setNumber(numMessages); + } + + Bitmap largeIconBitmap = BitmapFactory.decodeResource(res, largeIconResId); if (largeIconResId != 0 && (largeIcon != null || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) { notification.setLargeIcon(largeIconBitmap); } - notification.setSmallIcon(smallIconResId); - notification - .setVisibility(Notification.VISIBILITY_PRIVATE) - .setPriority(Notification.PRIORITY_HIGH); + if (subText != null) { + notification.setSubText(subText); + } return notification; } + + private void notifyReceivedToJS() { + mJsIOHelper.sendEventToJS(NOTIFICATION_RECEIVED_EVENT_NAME, mNotificationProps.asBundle(), mAppLifecycleFacade.getRunningReactContext()); + } + + private void cancelNotification(Bundle data, int notificationId) { + final String channelId = data.getString("channel_id"); + + String numberString = data.getString("badge"); + if (numberString != null) { + ApplicationBadgeHelper.instance.setApplicationIconBadgeNumber(mContext.getApplicationContext(), Integer.parseInt(numberString)); + } + + channelIdToNotificationCount.remove(channelId); + final NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); + notificationManager.cancel(notificationId); + } } diff --git a/app/mattermost.js b/app/mattermost.js index 5b3460b1f..90325d53a 100644 --- a/app/mattermost.js +++ b/app/mattermost.js @@ -15,6 +15,7 @@ import DeviceInfo from 'react-native-device-info'; import semver from 'semver'; import {setAppState, setDeviceToken, setServerVersion} from 'mattermost-redux/actions/general'; +import {markChannelAsRead} from 'mattermost-redux/actions/channels'; import {logout} from 'mattermost-redux/actions/users'; import {Client4} from 'mattermost-redux/client'; import {General} from 'mattermost-redux/constants'; @@ -124,6 +125,8 @@ export default class Mattermost { onPushNotification = (deviceNotification) => { const {data, foreground, message, userInfo, userInteraction} = deviceNotification; + const {dispatch, getState} = store; + const state = getState(); const notification = { data, message @@ -133,12 +136,11 @@ export default class Mattermost { notification.localNotification = userInfo.localNotification; } - if (foreground) { + if (data.type === 'clear') { + markChannelAsRead(data.channel_id)(dispatch, getState); + } else if (foreground) { EventEmitter.emit(ViewTypes.NOTIFICATION_IN_APP, notification); } else if (userInteraction) { - const {dispatch, getState} = store; - const state = getState(); - if (!notification.localNotification) { if (!state.views.root.appInitializing) { // go to notification if the app is initialized @@ -153,7 +155,7 @@ export default class Mattermost { }; startApp = (animationType = 'none') => { - if (animationType === 'none') { + if (!this.isConfigured) { this.configurePushNotifications(); } diff --git a/app/push_notifications/push_notifications.android.js b/app/push_notifications/push_notifications.android.js index 6ec052f7e..6051c6c7b 100644 --- a/app/push_notifications/push_notifications.android.js +++ b/app/push_notifications/push_notifications.android.js @@ -10,17 +10,15 @@ class PushNotification { this.onNotification = null; NotificationsAndroid.setNotificationReceivedListener((notification) => { - const data = notification.getData(); - if (notification) { + const data = notification.getData(); this.handleNotification(data, false); } }); NotificationsAndroid.setNotificationOpenedListener((notification) => { - const data = notification.getData(); - if (notification) { + const data = notification.getData(); this.handleNotification(data, true); } });