mattermost-mobile/app/push_notifications/push_notifications.ios.js
Miguel Alatzar ba76e5eac7 [MM-16232] ID loaded push notifications (#3562)
* [MM-16232] Android: Fetch notification in notificationReceiptDelivery (#3552)

* Fetch notification in notificationReceiptDelivery

* Fix patch

* Fix patch take 2

* No need to send user_id to ack endpoint

* Just putString in mNotificationProps

* Fix patch take 3

* Revert react-native-notifications patch

* Update patch and fix rejections

* Remove trailing newline in patch

* Move PushNotification changes to end of patch

* npm cache test

* Revert "npm cache test"

This reverts commit d31030aaeeb010c1c3d22a5f6196191eeb849add.

* Created patch after upgrading node

* Created patch after upgrading node take 2

* Remove androidx changes from patch

* Patch packages then jetify

* Cache node_modules without patches

* Remove adding of default message (#3557)

* [MM-16232] iOS: Fetch id-loaded push notification from server (#3556)

* Fetch notification from server

* Parse fetched notification response

* Fix id-loaded notifications for DM/GM's

* audit fix

* Only add keys if they exist

* Throw exception if response code is not 200
2019-11-18 19:29:49 -03:00

250 lines
7.9 KiB
JavaScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {AppState} from 'react-native';
import NotificationsIOS, {
NotificationAction,
NotificationCategory,
DEVICE_REMOTE_NOTIFICATIONS_REGISTERED_EVENT,
DEVICE_NOTIFICATION_RECEIVED_FOREGROUND_EVENT,
DEVICE_NOTIFICATION_OPENED_EVENT,
} from 'react-native-notifications';
import {getBadgeCount} from 'app/selectors/views';
import ephemeralStore from 'app/store/ephemeral_store';
import {getCurrentLocale} from 'app/selectors/i18n';
import {getLocalizedMessage} from 'app/i18n';
import {t} from 'app/utils/i18n';
const CATEGORY = 'CAN_REPLY';
const REPLY_ACTION = 'REPLY_ACTION';
const replies = new Set();
class PushNotification {
constructor() {
this.deviceNotification = null;
this.onRegister = null;
this.onNotification = null;
this.onReply = null;
this.reduxStore = null;
NotificationsIOS.addEventListener(DEVICE_REMOTE_NOTIFICATIONS_REGISTERED_EVENT, this.onRemoteNotificationsRegistered);
NotificationsIOS.addEventListener(DEVICE_NOTIFICATION_RECEIVED_FOREGROUND_EVENT, this.onNotificationReceivedForeground);
NotificationsIOS.addEventListener(DEVICE_NOTIFICATION_OPENED_EVENT, this.onNotificationOpened);
}
handleNotification = (data, foreground, userInteraction) => {
this.deviceNotification = {
data,
foreground,
message: data.body || data.message,
userInfo: data.userInfo,
userInteraction,
};
if (this.onNotification) {
this.onNotification(this.deviceNotification);
}
};
handleReply = (notification, text, completion) => {
const data = notification.getData();
if (this.onReply && !replies.has(data.identifier)) {
replies.add(data.identifier);
this.onReply(data, text, completion);
} else {
completion();
}
};
configure(options) {
this.reduxStore = options.reduxStore;
this.onRegister = options.onRegister;
this.onNotification = options.onNotification;
this.onReply = options.onReply;
this.requestNotificationReplyPermissions();
if (options.popInitialNotification) {
NotificationsIOS.getInitialNotification().
then((notification) => {
if (notification) {
const data = notification.getData();
if (data) {
ephemeralStore.appStartedFromPushNotification = true;
this.handleNotification(data, false, true);
}
}
}).
catch((err) => {
console.log('iOS getInitialNotifiation() failed', err); //eslint-disable-line no-console
});
}
}
requestNotificationReplyPermissions = () => {
const replyCategory = this.createReplyCategory();
this.requestPermissions([replyCategory]);
}
createReplyCategory = () => {
const {getState} = this.reduxStore;
const state = getState();
const locale = getCurrentLocale(state);
const replyTitle = getLocalizedMessage(locale, t('mobile.push_notification_reply.title'));
const replyButton = getLocalizedMessage(locale, t('mobile.push_notification_reply.button'));
const replyPlaceholder = getLocalizedMessage(locale, t('mobile.push_notification_reply.placeholder'));
const replyAction = new NotificationAction({
activationMode: 'background',
title: replyTitle,
textInput: {
buttonTitle: replyButton,
placeholder: replyPlaceholder,
},
authenticationRequired: true,
identifier: REPLY_ACTION,
});
return new NotificationCategory({
identifier: CATEGORY,
actions: [replyAction],
context: 'default',
});
}
requestPermissions = (permissions) => {
NotificationsIOS.requestPermissions(permissions);
};
localNotificationSchedule(notification) {
if (notification.date) {
const deviceNotification = {
fireDate: notification.date.toISOString(),
body: notification.message,
alertAction: '',
userInfo: notification.userInfo,
};
NotificationsIOS.localNotification(deviceNotification);
}
}
localNotification(notification) {
this.deviceNotification = {
body: notification.message,
alertAction: '',
userInfo: notification.userInfo,
};
NotificationsIOS.localNotification(this.deviceNotification);
}
cancelAllLocalNotifications() {
NotificationsIOS.cancelAllLocalNotifications();
}
onNotificationReceivedBackground = (notification) => {
const userInteraction = AppState.currentState === 'active';
// mark the app as started as soon as possible
if (userInteraction) {
ephemeralStore.appStartedFromPushNotification = true;
}
const data = notification.getData();
const info = {
...data,
message: data.body || notification.getMessage(),
};
if (!userInteraction) {
this.handleNotification(info, false, userInteraction);
}
};
onNotificationReceivedForeground = (notification) => {
const data = notification.getData();
const info = {
...data,
message: data.body || notification.getMessage(),
};
this.handleNotification(info, true, false);
};
onNotificationOpened = (notification, completion, action) => {
if (action.identifier === REPLY_ACTION) {
this.handleReply(notification, action.text, completion);
} else {
const data = notification.getData();
const info = {
...data,
message: data.body || notification.getMessage(),
};
this.handleNotification(info, false, true);
completion();
}
};
onRemoteNotificationsRegistered = (deviceToken) => {
if (this.onRegister) {
this.onRegister({token: deviceToken});
}
};
setApplicationIconBadgeNumber(number) {
const count = number < 0 ? 0 : number;
NotificationsIOS.setBadgesCount(count);
}
getNotification() {
return this.deviceNotification;
}
resetNotification() {
this.deviceNotification = null;
}
getDeliveredNotifications(callback) {
NotificationsIOS.getDeliveredNotifications(callback);
}
clearChannelNotifications(channelId) {
NotificationsIOS.getDeliveredNotifications((notifications) => {
const ids = [];
let badgeCount = notifications.length;
if (this.reduxStore) {
const totalMentions = getBadgeCount(this.reduxStore.getState());
if (totalMentions > -1) {
badgeCount = totalMentions;
}
}
for (let i = 0; i < notifications.length; i++) {
const notification = notifications[i];
if (notification.channel_id === channelId) {
ids.push(notification.identifier);
}
}
if (ids.length) {
badgeCount -= ids.length;
NotificationsIOS.removeDeliveredNotifications(ids);
}
this.setApplicationIconBadgeNumber(badgeCount);
});
}
clearNotifications = () => {
this.setApplicationIconBadgeNumber(0);
this.cancelAllLocalNotifications(); // TODO: Only cancel the local notifications that belong to this server
}
}
export default new PushNotification();