diff --git a/android/app/src/main/java/com/mattermost/helpers/BitmapCache.kt b/android/app/src/main/java/com/mattermost/helpers/BitmapCache.kt new file mode 100644 index 000000000..b57673507 --- /dev/null +++ b/android/app/src/main/java/com/mattermost/helpers/BitmapCache.kt @@ -0,0 +1,28 @@ +package com.mattermost.helpers + +import android.graphics.Bitmap +import android.util.LruCache + +class BitmapCache { + private var memoryCache: LruCache + + init { + val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt() + val cacheSize = maxMemory / 8 + memoryCache = object : LruCache(cacheSize) { + override fun sizeOf(key: String, bitmap: Bitmap): Int { + return bitmap.byteCount / 1024 + } + } + } + + fun getBitmapFromMemCache(key: String): Bitmap? { + return memoryCache.get(key) + } + + fun addBitmapToMemoryCache(key: String, bitmap: Bitmap) { + if (getBitmapFromMemCache(key) == null) { + memoryCache.put(key, bitmap) + } + } +} diff --git a/android/app/src/main/java/com/mattermost/helpers/CustomPushNotificationHelper.java b/android/app/src/main/java/com/mattermost/helpers/CustomPushNotificationHelper.java index f5cc95e88..919b32694 100644 --- a/android/app/src/main/java/com/mattermost/helpers/CustomPushNotificationHelper.java +++ b/android/app/src/main/java/com/mattermost/helpers/CustomPushNotificationHelper.java @@ -7,7 +7,6 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; -import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; @@ -28,7 +27,6 @@ import androidx.core.app.Person; import androidx.core.app.RemoteInput; import androidx.core.graphics.drawable.IconCompat; -import com.facebook.react.bridge.ReactApplicationContext; import com.mattermost.rnbeta.*; import java.io.IOException; @@ -53,7 +51,11 @@ public class CustomPushNotificationHelper { private static NotificationChannel mHighImportanceChannel; private static NotificationChannel mMinImportanceChannel; - private static void addMessagingStyleMessages(Context context, NotificationCompat.MessagingStyle messagingStyle, String conversationTitle, Bundle bundle) { + private static final OkHttpClient client = new OkHttpClient(); + + private static final BitmapCache bitmapCache = new BitmapCache(); + + private static void addMessagingStyleMessages(NotificationCompat.MessagingStyle messagingStyle, String conversationTitle, Bundle bundle) { String message = bundle.getString("message", bundle.getString("body")); String senderId = bundle.getString("sender_id"); String serverUrl = bundle.getString("server_url"); @@ -74,7 +76,7 @@ public class CustomPushNotificationHelper { if (serverUrl != null && !type.equals(CustomPushNotificationHelper.PUSH_TYPE_SESSION)) { try { - Bitmap avatar = userAvatar(context, serverUrl, senderId, null); + Bitmap avatar = userAvatar(serverUrl, senderId, urlOverride); if (avatar != null) { sender.setIcon(IconCompat.createWithBitmap(avatar)); } @@ -176,12 +178,12 @@ public class CustomPushNotificationHelper { String groupId = is_crt_enabled && !android.text.TextUtils.isEmpty(rootId) ? rootId : channelId; addNotificationExtras(notification, bundle); - setNotificationIcons(context, notification, bundle); - setNotificationMessagingStyle(context, notification, bundle); + setNotificationIcons(notification, bundle); + setNotificationMessagingStyle(notification, bundle); setNotificationGroup(notification, groupId, createSummary); setNotificationBadgeType(notification); - setNotificationChannel(context, notification, bundle); + setNotificationChannel(context, notification); setNotificationDeleteIntent(context, notification, bundle, notificationId); addNotificationReplyAction(context, notification, bundle, notificationId); @@ -253,15 +255,7 @@ public class CustomPushNotificationHelper { return title; } - private static int getIconResourceId(Context context, String iconName) { - final Resources res = context.getResources(); - String packageName = context.getPackageName(); - String defType = "mipmap"; - - return res.getIdentifier(iconName, defType, packageName); - } - - private static NotificationCompat.MessagingStyle getMessagingStyle(Context context, Bundle bundle) { + private static NotificationCompat.MessagingStyle getMessagingStyle(Bundle bundle) { NotificationCompat.MessagingStyle messagingStyle; final String senderId = "me"; final String serverUrl = bundle.getString("server_url"); @@ -273,7 +267,7 @@ public class CustomPushNotificationHelper { if (serverUrl != null && !type.equals(CustomPushNotificationHelper.PUSH_TYPE_SESSION)) { try { - Bitmap avatar = userAvatar(context, serverUrl, "me", null); + Bitmap avatar = userAvatar(serverUrl, "me", urlOverride); if (avatar != null) { sender.setIcon(IconCompat.createWithBitmap(avatar)); } @@ -286,7 +280,7 @@ public class CustomPushNotificationHelper { String conversationTitle = getConversationTitle(bundle); setMessagingStyleConversationTitle(messagingStyle, conversationTitle, bundle); - addMessagingStyleMessages(context, messagingStyle, conversationTitle, bundle); + addMessagingStyleMessages(messagingStyle, conversationTitle, bundle); return messagingStyle; } @@ -313,25 +307,6 @@ public class CustomPushNotificationHelper { return getConversationTitle(bundle); } - public static int getSmallIconResourceId(Context context, String iconName) { - if (iconName == null) { - iconName = "ic_notification"; - } - - int resourceId = getIconResourceId(context, iconName); - - if (resourceId == 0) { - iconName = "ic_launcher"; - resourceId = getIconResourceId(context, iconName); - - if (resourceId == 0) { - resourceId = android.R.drawable.ic_dialog_info; - } - } - - return resourceId; - } - private static String removeSenderNameFromMessage(String message, String senderName) { int index = message.indexOf(senderName); if (index == 0) { @@ -363,7 +338,7 @@ public class CustomPushNotificationHelper { } } - private static void setNotificationChannel(Context context, NotificationCompat.Builder notification, Bundle bundle) { + private static void setNotificationChannel(Context context, NotificationCompat.Builder notification) { // If Android Oreo or above we need to register a channel if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { return; @@ -387,8 +362,8 @@ public class CustomPushNotificationHelper { notification.setDeleteIntent(deleteIntent); } - private static void setNotificationMessagingStyle(Context context, NotificationCompat.Builder notification, Bundle bundle) { - NotificationCompat.MessagingStyle messagingStyle = getMessagingStyle(context, bundle); + private static void setNotificationMessagingStyle(NotificationCompat.Builder notification, Bundle bundle) { + NotificationCompat.MessagingStyle messagingStyle = getMessagingStyle(bundle); notification.setStyle(messagingStyle); } @@ -401,20 +376,18 @@ public class CustomPushNotificationHelper { } } - private static void setNotificationIcons(Context context, NotificationCompat.Builder notification, Bundle bundle) { - String smallIcon = bundle.getString("smallIcon"); + private static void setNotificationIcons(NotificationCompat.Builder notification, Bundle bundle) { String channelName = getConversationTitle(bundle); String senderName = bundle.getString("sender_name"); String serverUrl = bundle.getString("server_url"); String urlOverride = bundle.getString("override_icon_url"); - int smallIconResId = getSmallIconResourceId(context, smallIcon); - notification.setSmallIcon(smallIconResId); + notification.setSmallIcon(R.mipmap.ic_notification); if (serverUrl != null && channelName.equals(senderName)) { try { String senderId = bundle.getString("sender_id"); - Bitmap avatar = userAvatar(context, serverUrl, senderId, urlOverride); + Bitmap avatar = userAvatar(serverUrl, senderId, urlOverride); if (avatar != null) { notification.setLargeIcon(avatar); } @@ -424,29 +397,31 @@ public class CustomPushNotificationHelper { } } - private static Bitmap userAvatar(Context context, final String serverUrl, final String userId, final String urlOverride) throws IOException { + private static Bitmap userAvatar(final String serverUrl, final String userId, final String urlOverride) throws IOException { try { - final OkHttpClient client = new OkHttpClient(); - Request request; - String url; - if (urlOverride != null) { - request = new Request.Builder().url(urlOverride).build(); + Response response; + if (!TextUtils.isEmpty(urlOverride)) { + Request request = new Request.Builder().url(urlOverride).build(); Log.i("ReactNative", String.format("Fetch override profile image %s", urlOverride)); + response = client.newCall(request).execute(); } else { - final ReactApplicationContext reactApplicationContext = new ReactApplicationContext(context); - final String token = Credentials.getCredentialsForServerSync(reactApplicationContext, serverUrl); - url = String.format("%s/api/v4/users/%s/image", serverUrl, userId); + Bitmap cached = bitmapCache.getBitmapFromMemCache(userId); + if (cached != null) { + Bitmap bitmap = cached.copy(cached.getConfig(), false); + return getCircleBitmap(bitmap); + } + String url = String.format("api/v4/users/%s/image", userId); Log.i("ReactNative", String.format("Fetch profile image %s", url)); - request = new Request.Builder() - .header("Authorization", String.format("Bearer %s", token)) - .url(url) - .build(); + response = Network.getSync(serverUrl, url, null); } - Response response = client.newCall(request).execute(); + if (response.code() == 200) { assert response.body() != null; byte[] bytes = Objects.requireNonNull(response.body()).bytes(); Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length); + if (TextUtils.isEmpty(urlOverride) && !TextUtils.isEmpty(userId)) { + bitmapCache.addBitmapToMemoryCache(userId, bitmap.copy(bitmap.getConfig(), false)); + } return getCircleBitmap(bitmap); } diff --git a/android/app/src/main/java/com/mattermost/helpers/Network.java b/android/app/src/main/java/com/mattermost/helpers/Network.java index 930a41cf7..c1622459b 100644 --- a/android/app/src/main/java/com/mattermost/helpers/Network.java +++ b/android/app/src/main/java/com/mattermost/helpers/Network.java @@ -12,6 +12,7 @@ import com.mattermost.networkclient.APIClientModule; import com.mattermost.networkclient.enums.RetryTypes; import okhttp3.HttpUrl; +import okhttp3.Response; public class Network { @@ -35,6 +36,16 @@ public class Network { clientModule.post(baseUrl, endpoint, options, promise); } + public static Response getSync(String baseUrl, String endpoint, ReadableMap options) { + createClientIfNeeded(baseUrl); + return clientModule.getSync(baseUrl, endpoint, options); + } + + public static Response postSync(String baseUrl, String endpoint, ReadableMap options) { + createClientIfNeeded(baseUrl); + return clientModule.postSync(baseUrl, endpoint, options); + } + private static void createClientOptions() { WritableMap headers = Arguments.createMap(); headers.putString("X-Requested-With", "XMLHttpRequest"); 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 89a4edd9c..181e62164 100644 --- a/android/app/src/main/java/com/mattermost/rnbeta/CustomPushNotification.java +++ b/android/app/src/main/java/com/mattermost/rnbeta/CustomPushNotification.java @@ -7,7 +7,6 @@ import android.os.Bundle; import android.text.TextUtils; import android.util.Log; -import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import java.util.Objects; @@ -17,7 +16,6 @@ import com.mattermost.helpers.DatabaseHelper; import com.mattermost.helpers.Network; import com.mattermost.helpers.NotificationHelper; import com.mattermost.helpers.PushNotificationDataHelper; -import com.mattermost.helpers.ResolvePromise; import com.mattermost.share.ShareModule; import com.wix.reactnativenotifications.core.NotificationIntentAdapter; import com.wix.reactnativenotifications.core.notification.PushNotification; @@ -56,27 +54,31 @@ public class CustomPushNotification extends PushNotification { boolean isReactInit = mAppLifecycleFacade.isReactInitialized(); if (ackId != null && serverUrl != null) { - notificationReceiptDelivery(ackId, serverUrl, postId, type, isIdLoaded, new ResolvePromise() { - @Override - public void resolve(@Nullable Object value) { - if (isIdLoaded) { - Bundle response = (Bundle) value; - if (value != null) { - response.putString("server_url", serverUrl); - Bundle current = mNotificationProps.asBundle(); - current.putAll(response); - mNotificationProps = createProps(current); - } - } + Bundle response = ReceiptDelivery.send(ackId, serverUrl, postId, type, isIdLoaded); + if (isIdLoaded && response != null) { + Bundle current = mNotificationProps.asBundle(); + if (!current.containsKey("server_url")) { + response.putString("server_url", serverUrl); } - - @Override - public void reject(String code, String message) { - Log.e("ReactNative", code + ": " + message); - } - }); + current.putAll(response); + mNotificationProps = createProps(current); + } } + finishProcessingNotification(serverUrl, type, channelId, notificationId, isReactInit); + } + + @Override + public void onOpened() { + if (mNotificationProps != null) { + digestNotification(); + + Bundle data = mNotificationProps.asBundle(); + NotificationHelper.clearChannelOrThreadNotifications(mContext, data); + } + } + + private void finishProcessingNotification(String serverUrl, String type, String channelId, int notificationId, Boolean isReactInit) { switch (type) { case CustomPushNotificationHelper.PUSH_TYPE_MESSAGE: case CustomPushNotificationHelper.PUSH_TYPE_SESSION: @@ -117,16 +119,6 @@ public class CustomPushNotification extends PushNotification { } } - @Override - public void onOpened() { - if (mNotificationProps != null) { - digestNotification(); - - Bundle data = mNotificationProps.asBundle(); - NotificationHelper.clearChannelOrThreadNotifications(mContext, data); - } - } - private void buildNotification(Integer notificationId, boolean createSummary) { final PendingIntent pendingIntent = NotificationIntentAdapter.createPendingNotificationIntent(mContext, mNotificationProps); final Notification notification = buildNotification(pendingIntent); @@ -148,10 +140,6 @@ public class CustomPushNotification extends PushNotification { return CustomPushNotificationHelper.createNotificationBuilder(mContext, intent, bundle, true); } - private void notificationReceiptDelivery(String ackId, String serverUrl, String postId, String type, boolean isIdLoaded, ResolvePromise promise) { - ReceiptDelivery.send(mContext, ackId, serverUrl, postId, type, isIdLoaded, promise); - } - private void notifyReceivedToJS() { mJsIOHelper.sendEventToJS(NOTIFICATION_RECEIVED_EVENT_NAME, mNotificationProps.asBundle(), mAppLifecycleFacade.getRunningReactContext()); } diff --git a/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyBroadcastReceiver.java b/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyBroadcastReceiver.java index 5bb41198e..d606b7671 100644 --- a/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyBroadcastReceiver.java +++ b/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyBroadcastReceiver.java @@ -8,28 +8,16 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.util.Log; -import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.core.app.Person; -import android.util.Log; -import java.io.IOException; -import java.util.Objects; - -import okhttp3.Call; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - -import org.json.JSONObject; -import org.json.JSONException; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; import com.mattermost.helpers.*; -import com.facebook.react.bridge.ReactApplicationContext; - import com.wix.reactnativenotifications.core.NotificationIntentAdapter; import com.wix.reactnativenotifications.core.notification.PushNotificationProps; @@ -53,12 +41,7 @@ public class NotificationReplyBroadcastReceiver extends BroadcastReceiver { final int notificationId = intent.getIntExtra(CustomPushNotificationHelper.NOTIFICATION_ID, -1); final String serverUrl = bundle.getString("server_url"); if (serverUrl != null) { - final ReactApplicationContext reactApplicationContext = new ReactApplicationContext(context); - final String token = Credentials.getCredentialsForServerSync(reactApplicationContext, serverUrl); - - if (token != null) { - replyToMessage(serverUrl, token, notificationId, message); - } + replyToMessage(serverUrl, notificationId, message); } else { onReplyFailed(notificationId); } @@ -67,7 +50,7 @@ public class NotificationReplyBroadcastReceiver extends BroadcastReceiver { } } - protected void replyToMessage(final String serverUrl, final String token, final int notificationId, final CharSequence message) { + protected void replyToMessage(final String serverUrl, final int notificationId, final CharSequence message) { final String channelId = bundle.getString("channel_id"); final String postId = bundle.getString("post_id"); String rootId = bundle.getString("root_id"); @@ -75,63 +58,53 @@ public class NotificationReplyBroadcastReceiver extends BroadcastReceiver { rootId = postId; } - if (token == null || serverUrl == null) { + if (serverUrl == null) { onReplyFailed(notificationId); return; } - final OkHttpClient client = new OkHttpClient(); - final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); - String json = buildReplyPost(channelId, rootId, message.toString()); - RequestBody body = RequestBody.create(json, JSON); + WritableMap headers = Arguments.createMap(); + headers.putString("Content-Type", "application/json"); + + + WritableMap body = Arguments.createMap(); + body.putString("channel_id", channelId); + body.putString("message", message.toString()); + body.putString("root_id", rootId); + + WritableMap options = Arguments.createMap(); + options.putMap("headers", headers); + options.putMap("body", body); String postsEndpoint = "/api/v4/posts?set_online=false"; - String url = String.format("%s%s", serverUrl.replaceAll("/$", ""), postsEndpoint); - Log.i("ReactNative", String.format("Reply URL=%s", url)); - Request request = new Request.Builder() - .header("Authorization", String.format("Bearer %s", token)) - .header("Content-Type", "application/json") - .url(url) - .post(body) - .build(); - - client.newCall(request).enqueue(new okhttp3.Callback() { + Network.post(serverUrl, postsEndpoint, options, new ResolvePromise() { @Override - public void onFailure(@NonNull Call call, @NonNull IOException e) { - Log.i("ReactNative", String.format("Reply FAILED exception %s", e.getMessage())); + public void resolve(@Nullable Object value) { + if (value != null) { + onReplySuccess(notificationId, message); + Log.i("ReactNative", "Reply SUCCESS"); + } else { + Log.i("ReactNative", "Reply FAILED resolved without value"); + onReplyFailed(notificationId); + } + } + + @Override + public void reject(Throwable reason) { + Log.i("ReactNative", String.format("Reply FAILED exception %s", reason.getMessage())); onReplyFailed(notificationId); } @Override - public void onResponse(@NonNull Call call, @NonNull final Response response) throws IOException { - if (response.isSuccessful()) { - onReplySuccess(notificationId, message); - Log.i("ReactNative", "Reply SUCCESS"); - } else { - Log.i("ReactNative", - String.format("Reply FAILED status %s BODY %s", - response.code(), - Objects.requireNonNull(response.body()).string() - ) - ); - onReplyFailed(notificationId); - } + public void reject(String code, String message) { + Log.i("ReactNative", + String.format("Reply FAILED status %s BODY %s", code, message) + ); + onReplyFailed(notificationId); } }); } - protected String buildReplyPost(String channelId, String rootId, String message) { - try { - JSONObject json = new JSONObject(); - json.put("channel_id", channelId); - json.put("message", message); - json.put("root_id", rootId); - return json.toString(); - } catch(JSONException e) { - return "{}"; - } - } - protected void onReplyFailed(int notificationId) { recreateNotification(notificationId, "Message failed to send."); } diff --git a/android/app/src/main/java/com/mattermost/rnbeta/ReceiptDelivery.java b/android/app/src/main/java/com/mattermost/rnbeta/ReceiptDelivery.java index 9743b2c72..9b3c8f0db 100644 --- a/android/app/src/main/java/com/mattermost/rnbeta/ReceiptDelivery.java +++ b/android/app/src/main/java/com/mattermost/rnbeta/ReceiptDelivery.java @@ -1,135 +1,60 @@ package com.mattermost.rnbeta; -import android.content.Context; import android.os.Bundle; import android.util.Log; + import java.lang.System; import java.util.Objects; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import okhttp3.HttpUrl; - import org.json.JSONObject; -import org.json.JSONException; -import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.WritableMap; import com.mattermost.helpers.*; +import okhttp3.Response; + public class ReceiptDelivery { - private static final int[] FIBONACCI_BACKOFF = new int[] { 0, 1, 2, 3, 5, 8 }; + private static final String[] ackKeys = new String[]{"post_id", "root_id", "category", "message", "team_id", "channel_id", "channel_name", "type", "sender_id", "sender_name", "version"}; - public static void send(Context context, final String ackId, final String serverUrl, final String postId, final String type, final boolean isIdLoaded, ResolvePromise promise) { - final ReactApplicationContext reactApplicationContext = new ReactApplicationContext(context); - final String token = Credentials.getCredentialsForServerSync(reactApplicationContext, serverUrl); + public static Bundle send(final String ackId, final String serverUrl, final String postId, final String type, final boolean isIdLoaded) { Log.i("ReactNative", String.format("Send receipt delivery ACK=%s TYPE=%s to URL=%s with ID-LOADED=%s", ackId, type, serverUrl, isIdLoaded)); - execute(serverUrl, postId, token, ackId, type, isIdLoaded, promise); - } + WritableMap options = Arguments.createMap(); + WritableMap headers = Arguments.createMap(); + WritableMap body = Arguments.createMap(); + headers.putString("Content-Type", "application/json"); + options.putMap("headers", headers); + body.putString("id", ackId); + body.putDouble("received_at", System.currentTimeMillis()); + body.putString("platform", "android"); + body.putString("type", type); + body.putString("post_id", postId); + body.putBoolean("is_id_loaded", isIdLoaded); + options.putMap("body", body); - protected static void execute(String serverUrl, String postId, String token, String ackId, String type, boolean isIdLoaded, ResolvePromise promise) { - if (token == null) { - promise.reject("Receipt delivery failure", "Invalid token"); - return; - } - - if (serverUrl == null) { - promise.reject("Receipt delivery failure", "Invalid server URL"); - } - - JSONObject json; - long receivedAt = System.currentTimeMillis(); - - try { - json = new JSONObject(); - json.put("id", ackId); - json.put("received_at", receivedAt); - json.put("platform", "android"); - json.put("type", type); - json.put("post_id", postId); - json.put("is_id_loaded", isIdLoaded); - } catch (JSONException e) { - Log.e("ReactNative", "Receipt delivery failed to build json payload"); - promise.reject("Receipt delivery failure", e.toString()); - return; - } - - final HttpUrl url; - if (serverUrl != null) { - url = HttpUrl.parse( - String.format("%s/api/v4/notifications/ack", serverUrl.replaceAll("/$", ""))); - if (url != null) { - final OkHttpClient client = new OkHttpClient(); - final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); - RequestBody body = RequestBody.create(json.toString(), JSON); - Request request = new Request.Builder() - .header("Authorization", String.format("Bearer %s", token)) - .header("Content-Type", "application/json") - .url(url) - .post(body) - .build(); - - makeServerRequest(client, request, isIdLoaded, 0, promise); - } - } - } - - private static void makeServerRequest(OkHttpClient client, Request request, Boolean isIdLoaded, int reRequestCount, ResolvePromise promise) { - try { - Response response = client.newCall(request).execute(); + try (Response response = Network.postSync(serverUrl, "api/v4/notifications/ack", options)) { String responseBody = Objects.requireNonNull(response.body()).string(); - if (response.code() != 200) { - switch (response.code()) { - case 302: - promise.reject("Receipt delivery failure", "StatusFound"); - return; - case 400: - promise.reject("Receipt delivery failure", "StatusBadRequest"); - return; - case 401: - promise.reject("Receipt delivery failure", "Unauthorized"); - case 403: - promise.reject("Receipt delivery failure", "Forbidden"); - return; - case 500: - promise.reject("Receipt delivery failure", "StatusInternalServerError"); - return; - case 501: - promise.reject("Receipt delivery failure", "StatusNotImplemented"); - return; - } - - throw new Exception(responseBody); - } - JSONObject jsonResponse = new JSONObject(responseBody); + return parseAckResponse(jsonResponse); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + public static Bundle parseAckResponse(JSONObject jsonResponse) { + try { Bundle bundle = new Bundle(); - String[] keys = new String[]{"post_id", "root_id", "category", "message", "team_id", "channel_id", "channel_name", "type", "sender_id", "sender_name", "version"}; - for (String key : keys) { + for (String key : ackKeys) { if (jsonResponse.has(key)) { bundle.putString(key, jsonResponse.getString(key)); } } - promise.resolve(bundle); + return bundle; } catch (Exception e) { - Log.e("ReactNative", "Receipt delivery failed to send"); - if (isIdLoaded) { - try { - reRequestCount++; - if (reRequestCount < FIBONACCI_BACKOFF.length) { - Log.i("ReactNative", "Retry attempt " + reRequestCount + " with backoff delay: " + FIBONACCI_BACKOFF[reRequestCount] + " seconds"); - Thread.sleep(FIBONACCI_BACKOFF[reRequestCount] * 1000); - makeServerRequest(client, request, true, reRequestCount, promise); - } - } catch(InterruptedException ie) { - ie.printStackTrace(); - } - } - - promise.reject("Receipt delivery failure", e.toString()); + e.printStackTrace(); + return null; } } } diff --git a/app/init/push_notifications.ts b/app/init/push_notifications.ts index 13df0a194..0f41efa76 100644 --- a/app/init/push_notifications.ts +++ b/app/init/push_notifications.ts @@ -38,7 +38,7 @@ class PushNotifications { init(register: boolean) { if (register) { - Notifications.registerRemoteNotifications(); + this.registerIfNeeded(); } Notifications.events().registerNotificationOpened(this.onNotificationOpened); @@ -50,11 +50,8 @@ class PushNotifications { async registerIfNeeded() { const isRegistered = await Notifications.isRegisteredForRemoteNotifications(); if (!isRegistered) { - if (Platform.OS === 'android') { - Notifications.registerRemoteNotifications(); - } else { - await requestNotifications(['alert', 'sound', 'badge']); - } + await requestNotifications(['alert', 'sound', 'badge']); + Notifications.registerRemoteNotifications(); } } diff --git a/ios/Podfile.lock b/ios/Podfile.lock index b09603ef6..0569a06bd 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -351,7 +351,7 @@ PODS: - React-Core - react-native-netinfo (9.3.7): - React-Core - - react-native-network-client (1.2.0): + - react-native-network-client (1.3.0): - Alamofire (~> 5.6.4) - React-Core - Starscream (~> 4.0.4) @@ -918,7 +918,7 @@ SPEC CHECKSUMS: react-native-image-picker: 60f4246eb5bb7187fc15638a8c1f13abd3820695 react-native-in-app-review: a073f67c5f3392af6ea7fb383217cdb1aa2aa726 react-native-netinfo: 2517ad504b3d303e90d7a431b0fcaef76d207983 - react-native-network-client: 04b0a2a3d2beab43698e227389c4750b41d003ec + react-native-network-client: 019b790a27f21c116ddfc43c0fc68f77f0a1b20f react-native-notifications: 83b4fd4a127a6c918fc846cae90da60f84819e44 react-native-paste-input: 88709b4fd586ea8cc56ba5e2fc4cdfe90597730c react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a diff --git a/package-lock.json b/package-lock.json index bd6042532..5980240f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,7 @@ "@gorhom/bottom-sheet": "4.4.5", "@mattermost/compass-icons": "0.1.35", "@mattermost/react-native-emm": "1.3.3", - "@mattermost/react-native-network-client": "1.2.0", + "@mattermost/react-native-network-client": "1.3.0", "@mattermost/react-native-paste-input": "0.5.2", "@mattermost/react-native-turbo-log": "0.2.1", "@mattermost/react-native-turbo-mailer": "0.2.0", @@ -3339,9 +3339,9 @@ } }, "node_modules/@mattermost/react-native-network-client": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@mattermost/react-native-network-client/-/react-native-network-client-1.2.0.tgz", - "integrity": "sha512-agK5epaTvTi1drr4Pn9HDtz5TbDjgUl19n0FiZQpNHioIvI3HP5SfOAK6qO7brCJCMj/srn6o8OKsRAVR3AWGA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@mattermost/react-native-network-client/-/react-native-network-client-1.3.0.tgz", + "integrity": "sha512-eDU/bpXBkU+GIbM7QvabzNF8i2te7oklX/WEfF5au8gMuk8MOOhU0GLDlpxaO3V/LZvr7bPoT4dY8nch43bcMQ==", "dependencies": { "validator": "13.7.0", "zod": "3.19.1" @@ -24402,9 +24402,9 @@ "requires": {} }, "@mattermost/react-native-network-client": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@mattermost/react-native-network-client/-/react-native-network-client-1.2.0.tgz", - "integrity": "sha512-agK5epaTvTi1drr4Pn9HDtz5TbDjgUl19n0FiZQpNHioIvI3HP5SfOAK6qO7brCJCMj/srn6o8OKsRAVR3AWGA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@mattermost/react-native-network-client/-/react-native-network-client-1.3.0.tgz", + "integrity": "sha512-eDU/bpXBkU+GIbM7QvabzNF8i2te7oklX/WEfF5au8gMuk8MOOhU0GLDlpxaO3V/LZvr7bPoT4dY8nch43bcMQ==", "requires": { "validator": "13.7.0", "zod": "3.19.1" diff --git a/package.json b/package.json index c09067014..be466c67f 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "@gorhom/bottom-sheet": "4.4.5", "@mattermost/compass-icons": "0.1.35", "@mattermost/react-native-emm": "1.3.3", - "@mattermost/react-native-network-client": "1.2.0", + "@mattermost/react-native-network-client": "1.3.0", "@mattermost/react-native-paste-input": "0.5.2", "@mattermost/react-native-turbo-log": "0.2.1", "@mattermost/react-native-turbo-mailer": "0.2.0",