diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 6cc5eb9de..8e1e59741 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -45,7 +45,12 @@
-
+
+
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 1812ef689..e87e25acd 100644
--- a/android/app/src/main/java/com/mattermost/rnbeta/CustomPushNotification.java
+++ b/android/app/src/main/java/com/mattermost/rnbeta/CustomPushNotification.java
@@ -11,10 +11,13 @@ import android.os.Bundle;
import android.os.Build;
import android.app.Notification;
import android.app.NotificationManager;
+import android.app.RemoteInput;
import java.util.LinkedHashMap;
import java.util.ArrayList;
+import java.lang.reflect.Field;
import com.wix.reactnativenotifications.core.notification.PushNotification;
+import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
import com.wix.reactnativenotifications.core.AppLaunchHelper;
import com.wix.reactnativenotifications.core.AppLifecycleFacade;
import com.wix.reactnativenotifications.core.JsIOHelper;
@@ -27,18 +30,25 @@ public class CustomPushNotification extends PushNotification {
public static final int MESSAGE_NOTIFICATION_ID = 435345;
public static final String GROUP_KEY_MESSAGES = "mm_group_key_messages";
public static final String NOTIFICATION_ID = "notificationId";
+ public static final String KEY_TEXT_REPLY = "CAN_REPLY";
+ public static final String NOTIFICATION_REPLIED_EVENT_NAME = "notificationReplied";
+
private static LinkedHashMap channelIdToNotificationCount = new LinkedHashMap();
private static LinkedHashMap> channelIdToNotification = new LinkedHashMap>();
+ private static AppLifecycleFacade lifecycleFacade;
+ private static Context context;
public CustomPushNotification(Context context, Bundle bundle, AppLifecycleFacade appLifecycleFacade, AppLaunchHelper appLaunchHelper, JsIOHelper jsIoHelper) {
super(context, bundle, appLifecycleFacade, appLaunchHelper, jsIoHelper);
+ this.context = context;
}
- public static void clearNotification(int notificationId) {
+ public static void clearNotification(int notificationId, String channelId) {
if (notificationId != -1) {
- String channelId = String.valueOf(notificationId);
channelIdToNotificationCount.remove(channelId);
channelIdToNotification.remove(channelId);
+ final NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ notificationManager.cancel(notificationId);
}
}
@@ -108,8 +118,9 @@ public class CustomPushNotification extends PushNotification {
title = mContext.getPackageManager().getApplicationLabel(appInfo).toString();
}
- int notificationId = bundle.getString("channel_id").hashCode();
String channelId = bundle.getString("channel_id");
+ String postId = bundle.getString("post_id");
+ int notificationId = channelId.hashCode();
String message = bundle.getString("message");
String subText = bundle.getString("subText");
String numberString = bundle.getString("badge");
@@ -143,11 +154,7 @@ public class CustomPushNotification extends PushNotification {
ApplicationBadgeHelper.instance.setApplicationIconBadgeNumber(mContext.getApplicationContext(), Integer.parseInt(numberString));
}
- int numMessages = 0;
- Object objCount = channelIdToNotificationCount.get(channelId);
- if (objCount != null) {
- numMessages = (Integer)objCount;
- }
+ int numMessages = getMessageCountInChannel(channelId);
notification
.setGroupSummary(true)
@@ -173,19 +180,40 @@ public class CustomPushNotification extends PushNotification {
style.setBigContentTitle(title);
notification.setStyle(style)
.setContentTitle(summaryTitle);
-// .setNumber(numMessages);
}
// Let's add a delete intent when the notification is dismissed
- Intent delIntent = new Intent(mContext, NotificationDismissReceiver.class);
+ Intent delIntent = new Intent(mContext, NotificationDismissService.class);
delIntent.putExtra(NOTIFICATION_ID, notificationId);
- PendingIntent deleteIntent = PendingIntent.getBroadcast(mContext, 0, delIntent, 0);
+ PendingIntent deleteIntent = NotificationIntentAdapter.createPendingNotificationIntent(mContext, delIntent, mNotificationProps);
notification.setDeleteIntent(deleteIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
notification.setGroup(GROUP_KEY_MESSAGES);
}
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && postId != null) {
+ Intent replyIntent = new Intent(mContext, NotificationReplyService.class);
+ replyIntent.setAction(KEY_TEXT_REPLY);
+ replyIntent.putExtra(NOTIFICATION_ID, notificationId);
+ replyIntent.putExtra("pushNotification", bundle);
+ PendingIntent replyPendingIntent = PendingIntent.getService(mContext, 103, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+
+ RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
+ .setLabel("Reply")
+ .build();
+
+ Notification.Action replyAction = new Notification.Action.Builder(
+ R.drawable.ic_notif_action_reply, "Reply", replyPendingIntent)
+ .addRemoteInput(remoteInput)
+ .setAllowGeneratedReplies(true)
+ .build();
+
+ notification
+ .setShowWhen(true)
+ .addAction(replyAction);
+ }
+
Bitmap largeIconBitmap = BitmapFactory.decodeResource(res, largeIconResId);
if (largeIconResId != 0 && (largeIcon != null || Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)) {
notification.setLargeIcon(largeIconBitmap);
@@ -202,6 +230,15 @@ public class CustomPushNotification extends PushNotification {
mJsIOHelper.sendEventToJS(NOTIFICATION_RECEIVED_EVENT_NAME, mNotificationProps.asBundle(), mAppLifecycleFacade.getRunningReactContext());
}
+ public static Integer getMessageCountInChannel(String channelId) {
+ Object objCount = channelIdToNotificationCount.get(channelId);
+ if (objCount != null) {
+ return (Integer)objCount;
+ }
+
+ return 0;
+ }
+
private void cancelNotification(Bundle data, int notificationId) {
final String channelId = data.getString("channel_id");
diff --git a/android/app/src/main/java/com/mattermost/rnbeta/NotificationDismissReceiver.java b/android/app/src/main/java/com/mattermost/rnbeta/NotificationDismissReceiver.java
deleted file mode 100644
index be0706b39..000000000
--- a/android/app/src/main/java/com/mattermost/rnbeta/NotificationDismissReceiver.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.mattermost.rnbeta;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.BroadcastReceiver;
-
-
-public class NotificationDismissReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- int notificationId = intent.getIntExtra(CustomPushNotification.NOTIFICATION_ID, -1);
- CustomPushNotification.clearNotification(notificationId);
- }
-}
diff --git a/android/app/src/main/java/com/mattermost/rnbeta/NotificationDismissService.java b/android/app/src/main/java/com/mattermost/rnbeta/NotificationDismissService.java
new file mode 100644
index 000000000..48406f275
--- /dev/null
+++ b/android/app/src/main/java/com/mattermost/rnbeta/NotificationDismissService.java
@@ -0,0 +1,23 @@
+package com.mattermost.rnbeta;
+
+import android.content.Context;
+import android.content.Intent;
+import android.app.IntentService;
+import android.os.Bundle;
+
+import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
+
+public class NotificationDismissService extends IntentService {
+
+ public NotificationDismissService() {
+ super("notificationDismissService");
+ }
+
+ @Override
+ protected void onHandleIntent(Intent intent) {
+ Bundle bundle = NotificationIntentAdapter.extractPendingNotificationDataFromIntent(intent);
+ int notificationId = intent.getIntExtra(CustomPushNotification.NOTIFICATION_ID, -1);
+ String channelId = bundle.getString("channel_id");
+ CustomPushNotification.clearNotification(notificationId, channelId);
+ }
+}
diff --git a/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyService.java b/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyService.java
new file mode 100644
index 000000000..cadc2abcb
--- /dev/null
+++ b/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyService.java
@@ -0,0 +1,49 @@
+package com.mattermost.rnbeta;
+
+import android.content.Context;
+import android.content.Intent;
+import android.app.NotificationManager;
+import android.app.RemoteInput;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+
+import com.facebook.react.HeadlessJsTaskService;
+import com.facebook.react.bridge.Arguments;
+import com.facebook.react.jstasks.HeadlessJsTaskConfig;
+
+
+import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
+
+public class NotificationReplyService extends HeadlessJsTaskService {
+
+ @Override
+ protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
+ if (CustomPushNotification.KEY_TEXT_REPLY.equals(intent.getAction())) {
+ CharSequence message = getReplyMessage(intent);
+
+ Bundle bundle = NotificationIntentAdapter.extractPendingNotificationDataFromIntent(intent);
+ String channelId = bundle.getString("channel_id");
+ bundle.putCharSequence("text", message);
+ bundle.putInt("msg_count", CustomPushNotification.getMessageCountInChannel(channelId));
+
+ int notificationId = intent.getIntExtra(CustomPushNotification.NOTIFICATION_ID, -1);
+ CustomPushNotification.clearNotification(notificationId, channelId);
+
+ return new HeadlessJsTaskConfig(
+ "notificationReplied",
+ Arguments.fromBundle(bundle),
+ 5000);
+
+ }
+
+ return null;
+ }
+
+ private CharSequence getReplyMessage(Intent intent) {
+ Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
+ if (remoteInput != null) {
+ return remoteInput.getCharSequence(CustomPushNotification.KEY_TEXT_REPLY);
+ }
+ return null;
+ }
+}
diff --git a/android/app/src/main/res/drawable-hdpi/ic_notif_action_reply.png b/android/app/src/main/res/drawable-hdpi/ic_notif_action_reply.png
new file mode 100644
index 000000000..d7d3365f5
Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/ic_notif_action_reply.png differ
diff --git a/android/app/src/main/res/drawable-mdpi/ic_notif_action_reply.png b/android/app/src/main/res/drawable-mdpi/ic_notif_action_reply.png
new file mode 100644
index 000000000..a144ef606
Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/ic_notif_action_reply.png differ
diff --git a/android/app/src/main/res/drawable-xhdpi/ic_notif_action_reply.png b/android/app/src/main/res/drawable-xhdpi/ic_notif_action_reply.png
new file mode 100644
index 000000000..775b2a724
Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/ic_notif_action_reply.png differ
diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_notif_action_reply.png b/android/app/src/main/res/drawable-xxhdpi/ic_notif_action_reply.png
new file mode 100644
index 000000000..c5cd53e89
Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/ic_notif_action_reply.png differ
diff --git a/android/app/src/main/res/drawable-xxxhdpi/ic_notif_action_reply.png b/android/app/src/main/res/drawable-xxxhdpi/ic_notif_action_reply.png
new file mode 100644
index 000000000..36600d49a
Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/ic_notif_action_reply.png differ
diff --git a/app/components/badge.js b/app/components/badge.js
index c5a0ab008..2efa43ced 100644
--- a/app/components/badge.js
+++ b/app/components/badge.js
@@ -91,7 +91,7 @@ export default class Badge extends PureComponent {
setTimeout(() => {
this.setNativeProps({
style: {
- display: 'flex'
+ opacity: 1
}
});
}, 100);
@@ -125,7 +125,7 @@ export default class Badge extends PureComponent {
>
{this.renderText()}
diff --git a/app/mattermost.js b/app/mattermost.js
index 8c048b7b2..e2b4c14e8 100644
--- a/app/mattermost.js
+++ b/app/mattermost.js
@@ -5,7 +5,7 @@ import 'babel-polyfill';
import Analytics from 'analytics-react-native';
import Orientation from 'react-native-orientation';
import {Provider} from 'react-redux';
-import {Navigation} from 'react-native-navigation';
+import {Navigation, NativeEventsReceiver} from 'react-native-navigation';
import {IntlProvider} from 'react-intl';
import {
Alert,
@@ -23,6 +23,7 @@ import {General} from 'mattermost-redux/constants';
import {setAppState, setDeviceToken, setServerVersion} from 'mattermost-redux/actions/general';
import {markChannelAsRead} from 'mattermost-redux/actions/channels';
import {logError} from 'mattermost-redux/actions/errors';
+import {createPost} from 'mattermost-redux/actions/posts';
import {logout} from 'mattermost-redux/actions/users';
import {close as closeWebSocket} from 'mattermost-redux/actions/websocket';
import {Client, Client4} from 'mattermost-redux/client';
@@ -149,6 +150,7 @@ export default class Mattermost {
PushNotifications.configure({
onRegister: this.onRegisterDevice,
onNotification: this.onPushNotification,
+ onReply: this.onPushNotificationReply,
popInitialNotification: true,
requestPermissions: true
});
@@ -158,24 +160,30 @@ export default class Mattermost {
const {dispatch, getState} = store;
const isActive = appState === 'active';
setAppState(isActive)(dispatch, getState);
- try {
- if (!isActive && !this.inBackgroundSince) {
- this.inBackgroundSince = Date.now();
- } else if (isActive && this.inBackgroundSince && (Date.now() - this.inBackgroundSince) >= AUTHENTICATION_TIMEOUT) {
- this.inBackgroundSince = null;
- if (this.mdmEnabled) {
- const config = await mattermostManaged.getConfig();
- const authNeeded = config.inAppPinCode && config.inAppPinCode === 'true';
- if (authNeeded) {
- const authenticated = await this.handleAuthentication(config.vendor);
- if (!authenticated) {
- mattermostManaged.quitApp();
+
+ if (isActive && this.shouldRelaunchonActive) {
+ this.launchApp();
+ this.shouldRelaunchonActive = false;
+ } else {
+ try {
+ if (!isActive && !this.inBackgroundSince) {
+ this.inBackgroundSince = Date.now();
+ } else if (isActive && this.inBackgroundSince && (Date.now() - this.inBackgroundSince) >= AUTHENTICATION_TIMEOUT) {
+ this.inBackgroundSince = null;
+ if (this.mdmEnabled) {
+ const config = await mattermostManaged.getConfig();
+ const authNeeded = config.inAppPinCode && config.inAppPinCode === 'true';
+ if (authNeeded) {
+ const authenticated = await this.handleAuthentication(config.vendor);
+ if (!authenticated) {
+ mattermostManaged.quitApp();
+ }
}
}
}
+ } catch (error) {
+ // do nothing
}
- } catch (error) {
- // do nothing
}
};
@@ -347,11 +355,33 @@ export default class Mattermost {
const state = store.getState();
if (state.views.root.hydrationComplete) {
this.unsubscribeFromStore();
- this.handleManagedConfig().then((shouldStart) => {
- if (shouldStart) {
- this.startApp();
- }
- });
+
+ const notification = PushNotifications.getNotification();
+ if (notification) {
+ // If we have a notification means that the app was started cause of a reply
+ // and the app was not sitting in the background nor opened
+ const {data, text, badge} = notification;
+ this.onPushNotificationReply(data, text, badge);
+ PushNotifications.resetNotification();
+ }
+
+ if (Platform.OS === 'android') {
+ // In case of Android we need to handle the bridge being initialized by HeadlessJS
+ Promise.resolve(Navigation.isAppLaunched()).then((appLaunched) => {
+ if (appLaunched) {
+ this.launchApp(); // App is launched -> show UI
+ } else {
+ new NativeEventsReceiver().appLaunched(this.launchApp); // App hasn't been launched yet -> show the UI only when needed.
+ }
+ });
+ } else if (AppState.currentState === 'background') {
+ // for IOS replying from push notification starts the app in the background
+ this.shouldRelaunchonActive = true;
+ this.configurePushNotifications();
+ this.startFakeApp();
+ } else {
+ this.launchApp();
+ }
}
};
@@ -366,6 +396,7 @@ export default class Mattermost {
} else {
prefix = General.PUSH_NOTIFY_ANDROID_REACT_NATIVE;
}
+
setDeviceToken(`${prefix}:${data.token}`)(dispatch, getState);
this.isConfigured = true;
};
@@ -407,6 +438,46 @@ export default class Mattermost {
}
};
+ onPushNotificationReply = (data, text, badge, completed) => {
+ const {dispatch, getState} = store;
+ const state = getState();
+ const {currentUserId} = state.entities.users;
+
+ if (currentUserId) {
+ // one thing to note is that for android it will reply to the last post in the stack
+ const rootId = data.root_id || data.post_id;
+ const post = {
+ user_id: currentUserId,
+ channel_id: data.channel_id,
+ root_id: rootId,
+ parent_id: rootId,
+ message: text
+ };
+
+ if (!Client4.getUrl()) {
+ // Make sure the Client has the server url set
+ Client4.setUrl(state.entities.general.credentials.url);
+ }
+
+ if (!Client.getToken()) {
+ // Make sure the Client has the server token set
+ Client4.setToken(state.entities.general.credentials.token);
+ }
+
+ createPost(post)(dispatch, getState);
+ markChannelAsRead(data.channel_id)(dispatch, getState);
+
+ if (badge >= 0) {
+ PushNotifications.setApplicationIconBadgeNumber(badge);
+ }
+ }
+
+ if (completed) {
+ // You must call to completed(), otherwise the action will not be triggered
+ completed();
+ }
+ };
+
resetBadgeAndVersion = () => {
const {dispatch, getState} = store;
Client4.serverVersion = '';
@@ -426,6 +497,14 @@ export default class Mattermost {
this.startApp('fade');
};
+ launchApp = () => {
+ this.handleManagedConfig().then((shouldStart) => {
+ if (shouldStart) {
+ this.startApp();
+ }
+ });
+ };
+
startFakeApp = async () => {
return Navigation.startSingleScreenApp({
screen: {
@@ -443,6 +522,10 @@ export default class Mattermost {
};
startApp = (animationType = 'none') => {
+ if (!this.isConfigured) {
+ this.configurePushNotifications();
+ }
+
Navigation.startSingleScreenApp({
screen: {
screen: 'Root',
@@ -457,9 +540,5 @@ export default class Mattermost {
},
animationType
});
-
- if (!this.isConfigured) {
- this.configurePushNotifications();
- }
};
}
diff --git a/app/push_notifications/push_notifications.android.js b/app/push_notifications/push_notifications.android.js
index 6051c6c7b..051f5ad56 100644
--- a/app/push_notifications/push_notifications.android.js
+++ b/app/push_notifications/push_notifications.android.js
@@ -1,13 +1,16 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import {AppState} from 'react-native';
+import {AppRegistry, AppState} from 'react-native';
import {NotificationsAndroid, PendingNotifications} from 'react-native-notifications';
+import Notification from 'react-native-notifications/notification.android';
class PushNotification {
constructor() {
this.onRegister = null;
this.onNotification = null;
+ this.onReply = null;
+ this.deviceNotification = null;
NotificationsAndroid.setNotificationReceivedListener((notification) => {
if (notification) {
@@ -22,6 +25,21 @@ class PushNotification {
this.handleNotification(data, true);
}
});
+
+ AppRegistry.registerHeadlessTask('notificationReplied', () => async (deviceNotification) => {
+ const notification = new Notification(deviceNotification);
+ const data = notification.getData();
+
+ if (this.onReply && AppState.currentState === 'background') {
+ this.onReply(data, data.text, parseInt(data.badge, 10) - parseInt(data.msg_count, 10));
+ } else {
+ this.deviceNotification = {
+ data,
+ text: data.text,
+ badge: parseInt(data.badge, 10) - parseInt(data.msg_count, 10)
+ };
+ }
+ });
}
handleNotification = (data, userInteraction) => {
@@ -41,6 +59,7 @@ class PushNotification {
configure(options) {
this.onRegister = options.onRegister;
this.onNotification = options.onNotification;
+ this.onReply = options.onReply;
NotificationsAndroid.refreshToken();
NotificationsAndroid.setRegistrationTokenUpdateListener((deviceToken) => {
@@ -80,6 +99,14 @@ class PushNotification {
setApplicationIconBadgeNumber(number) {
NotificationsAndroid.setBadgesCount(number);
}
+
+ getNotification() {
+ return this.deviceNotification;
+ }
+
+ resetNotification() {
+ this.deviceNotification = null;
+ }
}
export default new PushNotification();
diff --git a/app/push_notifications/push_notifications.ios.js b/app/push_notifications/push_notifications.ios.js
index eef25fadf..7cea3c312 100644
--- a/app/push_notifications/push_notifications.ios.js
+++ b/app/push_notifications/push_notifications.ios.js
@@ -2,12 +2,18 @@
// See License.txt for license information.
import {AppState} from 'react-native';
-import NotificationsIOS from 'react-native-notifications';
+import NotificationsIOS, {NotificationAction, NotificationCategory} from 'react-native-notifications';
+
+const CATEGORY = 'CAN_REPLY';
+const REPLY_ACTION = 'REPLY_ACTION';
+
+let replyCategory;
class PushNotification {
constructor() {
this.onRegister = null;
this.onNotification = null;
+ this.onReply = null;
NotificationsIOS.addEventListener('notificationReceivedForeground', (notification) => {
const info = {
@@ -32,6 +38,20 @@ class PushNotification {
};
this.handleNotification(info, false, true);
});
+
+ const replyAction = new NotificationAction({
+ activationMode: 'background',
+ title: 'Reply',
+ behavior: 'textInput',
+ authenticationRequired: true,
+ identifier: REPLY_ACTION
+ }, this.handleReply);
+
+ replyCategory = new NotificationCategory({
+ identifier: CATEGORY,
+ actions: [replyAction],
+ context: 'default'
+ });
}
handleNotification = (data, foreground, userInteraction) => {
@@ -48,9 +68,24 @@ class PushNotification {
}
};
+ handleReply = (action, completed) => {
+ if (action.identifier === REPLY_ACTION) {
+ const data = action.notification.getData();
+ const text = action.text;
+ const badge = parseInt(action.notification._badge, 10) - 1; //eslint-disable-line no-underscore-dangle
+
+ if (this.onReply) {
+ this.onReply(data, text, badge, completed);
+ }
+ } else {
+ completed();
+ }
+ };
+
configure(options) {
this.onRegister = options.onRegister;
this.onNotification = options.onNotification;
+ this.onReply = options.onReply;
NotificationsIOS.addEventListener('remoteNotificationsRegistered', (deviceToken) => {
if (this.onRegister) {
@@ -59,7 +94,7 @@ class PushNotification {
});
if (options.requestPermissions) {
- this.requestPermissions();
+ this.requestPermissions([replyCategory]);
}
if (options.popInitialNotification) {
@@ -67,8 +102,8 @@ class PushNotification {
}
}
- requestPermissions = () => {
- NotificationsIOS.requestPermissions();
+ requestPermissions = (permissions) => {
+ NotificationsIOS.requestPermissions(permissions);
};
localNotificationSchedule(notification) {
@@ -91,6 +126,10 @@ class PushNotification {
setApplicationIconBadgeNumber(number) {
NotificationsIOS.setBadgesCount(number);
}
+
+ getNotification() {
+ return null;
+ }
}
export default new PushNotification();
diff --git a/fastlane/Fastfile b/fastlane/Fastfile
index 5fdc68639..8dc07e169 100644
--- a/fastlane/Fastfile
+++ b/fastlane/Fastfile
@@ -350,7 +350,13 @@ platform :android do
)
find_replace_string(
- path_to_file: './android/app/src/main/java/com/mattermost/rn/NotificationDismissReceiver.java',
+ path_to_file: './android/app/src/main/java/com/mattermost/rn/NotificationDismissService.java',
+ old_string: 'package com.mattermost.rnbeta;',
+ new_string: 'package com.mattermost.rn;'
+ )
+
+ find_replace_string(
+ path_to_file: './android/app/src/main/java/com/mattermost/rn/NotificationReplyService.java',
old_string: 'package com.mattermost.rnbeta;',
new_string: 'package com.mattermost.rn;'
)
diff --git a/ios/Mattermost.xcodeproj/project.pbxproj b/ios/Mattermost.xcodeproj/project.pbxproj
index fa042cd0c..024e38532 100644
--- a/ios/Mattermost.xcodeproj/project.pbxproj
+++ b/ios/Mattermost.xcodeproj/project.pbxproj
@@ -5,7 +5,6 @@
};
objectVersion = 46;
objects = {
-
/* Begin PBXBuildFile section */
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
@@ -1435,7 +1434,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
- "\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1453,7 +1451,6 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
- "\"$(SRCROOT)/$(TARGET_NAME)\"",
);
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
diff --git a/ios/Mattermost/AppDelegate.m b/ios/Mattermost/AppDelegate.m
index 0dfe7074b..b73499115 100644
--- a/ios/Mattermost/AppDelegate.m
+++ b/ios/Mattermost/AppDelegate.m
@@ -60,4 +60,16 @@
{
[RNNotifications didReceiveLocalNotification:notification];
}
+
+// Required for the notification actions.
+- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler
+{
+ [RNNotifications handleActionWithIdentifier:identifier forLocalNotification:notification withResponseInfo:responseInfo completionHandler:completionHandler];
+}
+
+- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler
+{
+ [RNNotifications handleActionWithIdentifier:identifier forRemoteNotification:userInfo withResponseInfo:responseInfo completionHandler:completionHandler];
+}
+
@end
diff --git a/ios/Mattermost/Info.plist b/ios/Mattermost/Info.plist
index 13f33d3af..e326a3199 100644
--- a/ios/Mattermost/Info.plist
+++ b/ios/Mattermost/Info.plist
@@ -44,7 +44,7 @@
NSCameraUsageDescription
Take a Photo or Video and upload it to your mattermost instance
NSLocationWhenInUseUsageDescription
-
+
NSPhotoLibraryUsageDescription
Upload Photos and Videos to your Mattermost instance
UIAppFonts
@@ -57,16 +57,8 @@
MaterialIcons.ttf
Octicons.ttf
Zocial.ttf
- Entypo.ttf
- EvilIcons.ttf
- FontAwesome.ttf
- Foundation.ttf
- Ionicons.ttf
MaterialCommunityIcons.ttf
- MaterialIcons.ttf
- Octicons.ttf
SimpleLineIcons.ttf
- Zocial.ttf
OpenSans-Bold.ttf
OpenSans-BoldItalic.ttf
OpenSans-ExtraBold.ttf
diff --git a/yarn.lock b/yarn.lock
index ebc7873cf..2c8c0442e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4560,8 +4560,8 @@ react-native-navigation@1.1.131:
lodash "4.x.x"
react-native-notifications@enahum/react-native-notifications.git:
- version "1.1.11"
- resolved "https://codeload.github.com/enahum/react-native-notifications/tar.gz/a8450bcbfc6ae46ed4b97f6fe723aac44c8ad598"
+ version "1.1.15"
+ resolved "https://codeload.github.com/enahum/react-native-notifications/tar.gz/084d5e928d8149e711c1b6c384f3d87cc16072f9"
dependencies:
core-js "^1.0.0"
uuid "^2.0.3"