diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 2be9a6329..fe28b85ee 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -37,7 +37,7 @@
-
= Build.VERSION_CODES.O) {
+ String CHANNEL_ID = "channel_01";
+ String CHANNEL_NAME = "Mattermost notifications";
+
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH);
+ channel.setShowBadge(true);
+
final NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
notification.setChannelId(CHANNEL_ID);
}
+
Bundle bundle = mNotificationProps.asBundle();
String version = bundle.getString("version");
@@ -185,12 +194,10 @@ public class CustomPushNotification extends PushNotification {
String channelId = bundle.getString("channel_id");
String postId = bundle.getString("post_id");
- int notificationId = channelId != null ? channelId.hashCode() : MESSAGE_NOTIFICATION_ID;
- String message = bundle.getString("message");
- String subText = bundle.getString("subText");
- String numberString = bundle.getString("badge");
+ String badge = bundle.getString("badge");
String smallIcon = bundle.getString("smallIcon");
String largeIcon = bundle.getString("largeIcon");
+ int notificationId = channelId != null ? channelId.hashCode() : MESSAGE_NOTIFICATION_ID;
Bundle b = bundle.getBundle("userInfo");
if (b == null) {
@@ -222,67 +229,47 @@ public class CustomPushNotification extends PushNotification {
largeIconResId = res.getIdentifier("ic_launcher", "mipmap", packageName);
}
- if (numberString != null) {
- CustomPushNotification.badgeCount = Integer.parseInt(numberString);
+ if (badge != null) {
+ CustomPushNotification.badgeCount = Integer.parseInt(badge);
ApplicationBadgeHelper.instance.setApplicationIconBadgeNumber(mContext.getApplicationContext(), CustomPushNotification.badgeCount);
+ } else {
+ // HERE ADD THE DOT INDICATOR STUFF
}
- int numMessages = getMessageCountInChannel(channelId);
+ Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("You");
+ if (title != null && !title.startsWith("@")) {
+ messagingStyle
+ .setConversationTitle(title);
+ }
+
+ List bundleArray = channelIdToNotification.get(channelId);
+ List list;
+ if (bundleArray != null) {
+ list = new ArrayList(bundleArray);
+ } else {
+ list = new ArrayList();
+ }
+
+ for (Bundle data : list) {
+ String message = data.getString("message");
+ if (title == null || !title.startsWith("@")) {
+ message = removeSenderFromMessage(message);
+ }
+ messagingStyle.addMessage(message, data.getLong("time"), data.getString("sender_name"));
+ }
notification
.setContentIntent(intent)
.setGroupSummary(true)
+ .setStyle(messagingStyle)
.setSmallIcon(smallIconResId)
+ .setNumber(Integer.parseInt(badge))
.setVisibility(Notification.VISIBILITY_PRIVATE)
.setPriority(Notification.PRIORITY_HIGH)
.setAutoCancel(true);
- if (numMessages == 1) {
- notification
- .setContentTitle(title)
- .setContentText(message)
- .setStyle(new Notification.BigTextStyle()
- .bigText(message));
- } else {
- String summaryTitle = null;
-
- if (version != null && version.equals("v2")) {
- summaryTitle = String.format("(%d) %s", numMessages, title);
- } else {
- summaryTitle = String.format("%s (%d)", title, numMessages);
- }
-
- Notification.InboxStyle style = new Notification.InboxStyle();
- List bundleArray = channelIdToNotification.get(channelId);
- List list;
- if (bundleArray != null) {
- list = new ArrayList(bundleArray);
- } else {
- list = new ArrayList();
- }
-
- if (version != null && version.equals("v2")) {
- style.addLine(message);
- }
-
- for (Bundle data : list) {
- String msg = data.getString("message");
- if (msg != message) {
- style.addLine(data.getString("message"));
- }
- }
-
- if (version != null && version.equals("v2")) {
- notification
- .setContentTitle(summaryTitle)
- .setContentText(message)
- .setStyle(style);
- } else {
- style.setBigContentTitle(message)
- .setSummaryText(String.format("+%d more", (numMessages - 1)));
- notification.setStyle(style)
- .setContentTitle(summaryTitle);
- }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ notification.setBadgeIconType(Notification.BADGE_ICON_SMALL);
}
// Let's add a delete intent when the notification is dismissed
@@ -296,17 +283,11 @@ public class CustomPushNotification extends PushNotification {
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && postId != null) {
- Intent replyIntent = new Intent(mContext, NotificationReplyService.class);
+ Intent replyIntent = new Intent(mContext, NotificationReplyBroadcastReceiver.class);
replyIntent.setAction(KEY_TEXT_REPLY);
replyIntent.putExtra(NOTIFICATION_ID, notificationId);
replyIntent.putExtra("pushNotification", bundle);
- PendingIntent replyPendingIntent;
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- replyPendingIntent = PendingIntent.getForegroundService(mContext, notificationId, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- } else {
- replyPendingIntent = PendingIntent.getService(mContext, notificationId, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- }
+ PendingIntent replyPendingIntent = PendingIntent.getBroadcast(mContext, notificationId, replyIntent, PendingIntent.FLAG_UPDATE_CURRENT);
RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
.setLabel("Reply")
@@ -328,10 +309,6 @@ public class CustomPushNotification extends PushNotification {
notification.setLargeIcon(largeIconBitmap);
}
- if (subText != null) {
- notification.setSubText(subText);
- }
-
String soundUri = notificationPreferences.getNotificationSound();
if (soundUri != null) {
if (soundUri != "none") {
@@ -378,4 +355,17 @@ public class CustomPushNotification extends PushNotification {
ApplicationBadgeHelper.instance.setApplicationIconBadgeNumber(mContext.getApplicationContext(), CustomPushNotification.badgeCount);
}
+
+ private String getSenderName(String channelName, String message) {
+ if (channelName != null && channelName.startsWith("@")) {
+ return channelName;
+ }
+
+ return message.split(":")[0];
+ }
+
+ private String removeSenderFromMessage(String message) {
+ String sender = String.format("%s: ", getSenderName("", message));
+ return message.replaceFirst(sender, "");
+ }
}
diff --git a/android/app/src/main/java/com/mattermost/rnbeta/NotificationDismissService.java b/android/app/src/main/java/com/mattermost/rnbeta/NotificationDismissService.java
index 8aeefb704..6fb1598a4 100644
--- a/android/app/src/main/java/com/mattermost/rnbeta/NotificationDismissService.java
+++ b/android/app/src/main/java/com/mattermost/rnbeta/NotificationDismissService.java
@@ -11,7 +11,7 @@ import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
public class NotificationDismissService extends IntentService {
private Context mContext;
public NotificationDismissService() {
- super("notificationDismissService");
+ super("notificationDismissService");
}
@Override
diff --git a/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyBroadcastReceiver.java b/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyBroadcastReceiver.java
new file mode 100644
index 000000000..0df1a9a9c
--- /dev/null
+++ b/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyBroadcastReceiver.java
@@ -0,0 +1,156 @@
+package com.mattermost.rnbeta;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.RemoteInput;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.util.Log;
+import java.io.IOException;
+
+import okhttp3.Call;
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+import com.mattermost.react_native_interface.ResolvePromise;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.WritableMap;
+import com.oblador.keychain.KeychainModule;
+
+import com.wix.reactnativenotifications.core.NotificationIntentAdapter;
+
+public class NotificationReplyBroadcastReceiver extends BroadcastReceiver {
+ private Context mContext;
+ private Bundle bundle;
+ private NotificationManager notificationManager;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
+ mContext = context;
+ bundle = NotificationIntentAdapter.extractPendingNotificationDataFromIntent(intent);
+ notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ final ReactApplicationContext reactApplicationContext = new ReactApplicationContext(context);
+ final int notificationId = intent.getIntExtra(CustomPushNotification.NOTIFICATION_ID, -1);
+ final CharSequence message = getReplyMessage(intent);
+ final KeychainModule keychainModule = new KeychainModule(reactApplicationContext);
+
+ keychainModule.getGenericPasswordForOptions(null, new ResolvePromise() {
+ @Override
+ public void resolve(@Nullable Object value) {
+ if (value instanceof Boolean && !(Boolean)value) {
+ String channelId = bundle.getString("channel_id");
+ onReplyFailed(notificationManager, notificationId, channelId);
+ return;
+ }
+
+ WritableMap map = (WritableMap) value;
+ if (map != null) {
+ String[] credentials = map.getString("password").split(",[ ]*");
+ String token = null;
+ String serverUrl = null;
+ if (credentials.length == 2) {
+ token = credentials[0];
+ serverUrl = credentials[1];
+
+ }
+
+ Log.i("ReactNative", String.format("URL=%s TOKEN=%s", serverUrl, token));
+ replyToMessage(serverUrl, token, notificationId, message);
+ }
+ }
+ });
+ }
+ }
+
+ protected void replyToMessage(final String serverUrl, final String token, final int notificationId, final CharSequence message) {
+ final String channelId = bundle.getString("channel_id");
+ final String rootId = bundle.getString("post_id");
+
+ if (token == null || serverUrl == null) {
+ onReplyFailed(notificationManager, notificationId, channelId);
+ return;
+ }
+
+ final OkHttpClient client = new OkHttpClient();
+ final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+ String json = buildReplyPost(channelId, rootId, message.toString());
+ Log.i("ReactNative", String.format("JSON STRING %s", json));
+ RequestBody body = RequestBody.create(JSON, json);
+ Request request = new Request.Builder()
+ .header("Authorization", String.format("Bearer %s", token))
+ .header("Content-Type", "application/json")
+ .url(String.format("%s/api/v4/posts", serverUrl.replaceAll("/$", "")))
+ .post(body)
+ .build();
+
+ client.newCall(request).enqueue(new okhttp3.Callback() {
+ @Override
+ public void onFailure(Call call, IOException e) {
+ Log.i("ReactNative", String.format("Reply with message %s FAILED exception %s", message, e.getMessage()));
+ onReplyFailed(notificationManager, notificationId, channelId);
+ }
+
+ @Override
+ public void onResponse(Call call, final Response response) throws IOException {
+ if (response.isSuccessful()) {
+ onReplySuccess(notificationManager, notificationId, channelId);
+ Log.i("ReactNative", String.format("Reply with message %s", message));
+ } else {
+ Log.i("ReactNative", String.format("Reply with message %s FAILED status %s BODY %s", message, response.code(), response.body().string()));
+ onReplyFailed(notificationManager, notificationId, channelId);
+ }
+ }
+ });
+ }
+
+ protected String buildReplyPost(String channelId, String rootId, String message) {
+ return "{"
+ + "\"channel_id\": \"" + channelId + "\","
+ + "\"message\": \"" + message + "\","
+ + "\"root_id\": \"" + rootId + "\""
+ + "}";
+ }
+
+ protected void onReplyFailed(NotificationManager notificationManager, int notificationId, String channelId) {
+ String CHANNEL_ID = "Reply job";
+ Resources res = mContext.getResources();
+ String packageName = mContext.getPackageName();
+ int smallIconResId = res.getIdentifier("ic_notification", "mipmap", packageName);
+
+ NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
+ notificationManager.createNotificationChannel(channel);
+ Notification notification =
+ new Notification.Builder(mContext, CHANNEL_ID)
+ .setContentTitle("Message failed to send.")
+ .setContentText(packageName)
+ .setSmallIcon(smallIconResId)
+ .build();
+
+ CustomPushNotification.clearNotification(mContext, notificationId, channelId);
+ notificationManager.notify(notificationId, notification);
+ }
+
+ protected void onReplySuccess(NotificationManager notificationManager, int notificationId, String channelId) {
+ notificationManager.cancel(notificationId);
+ CustomPushNotification.clearNotification(mContext, notificationId, channelId);
+ }
+
+ 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/java/com/mattermost/rnbeta/NotificationReplyService.java b/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyService.java
deleted file mode 100644
index 3978284fd..000000000
--- a/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyService.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.mattermost.rnbeta;
-
-import android.app.Notification;
-import android.app.NotificationChannel;
-import android.app.NotificationManager;
-import android.app.RemoteInput;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.util.Log;
-
-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 {
- private Context mContext;
-
- @Override
- public void onCreate() {
- super.onCreate();
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
- Context mContext = this.getApplicationContext();
- final Resources res = mContext.getResources();
- String packageName = mContext.getPackageName();
- int smallIconResId = res.getIdentifier("ic_notification", "mipmap", packageName);
- String CHANNEL_ID = "Reply job";
- NotificationChannel channel = new NotificationChannel(CHANNEL_ID, CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
- ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
- Notification notification =
- new Notification.Builder(mContext, CHANNEL_ID)
- .setContentTitle("Replying to message")
- .setContentText(packageName)
- .setSmallIcon(smallIconResId)
- .build();
- startForeground(1, notification);
- }
-
- }
-
- @Override
- protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) {
- mContext = getApplicationContext();
- 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(mContext, notificationId, channelId);
-
- MainApplication app = (MainApplication) this.getApplication();
- app.replyFromPushNotification = true;
- Log.i("ReactNative", "Replying service");
- 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;
- }
-}