Request permissions for Android push notifications and refactor code to use network client (#7059)

This commit is contained in:
Elias Nahum
2023-01-31 21:33:35 +02:00
committed by GitHub
parent aa6c1ff058
commit 265b8b2193
10 changed files with 178 additions and 281 deletions

View File

@@ -0,0 +1,28 @@
package com.mattermost.helpers
import android.graphics.Bitmap
import android.util.LruCache
class BitmapCache {
private var memoryCache: LruCache<String, Bitmap>
init {
val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
val cacheSize = maxMemory / 8
memoryCache = object : LruCache<String, Bitmap>(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)
}
}
}

View File

@@ -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");
@@ -75,7 +77,7 @@ public class CustomPushNotificationHelper {
if (serverUrl != null && !type.equals(CustomPushNotificationHelper.PUSH_TYPE_SESSION)) {
try {
Bitmap avatar = userAvatar(context, serverUrl, senderId, urlOverride);
Bitmap avatar = userAvatar(serverUrl, senderId, urlOverride);
if (avatar != null) {
sender.setIcon(IconCompat.createWithBitmap(avatar));
}
@@ -177,12 +179,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);
@@ -254,15 +256,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");
@@ -275,7 +269,7 @@ public class CustomPushNotificationHelper {
if (serverUrl != null && !type.equals(CustomPushNotificationHelper.PUSH_TYPE_SESSION)) {
try {
Bitmap avatar = userAvatar(context, serverUrl, "me", urlOverride);
Bitmap avatar = userAvatar(serverUrl, "me", urlOverride);
if (avatar != null) {
sender.setIcon(IconCompat.createWithBitmap(avatar));
}
@@ -288,7 +282,7 @@ public class CustomPushNotificationHelper {
String conversationTitle = getConversationTitle(bundle);
setMessagingStyleConversationTitle(messagingStyle, conversationTitle, bundle);
addMessagingStyleMessages(context, messagingStyle, conversationTitle, bundle);
addMessagingStyleMessages(messagingStyle, conversationTitle, bundle);
return messagingStyle;
}
@@ -315,25 +309,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) {
@@ -365,7 +340,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;
@@ -389,8 +364,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);
}
@@ -403,20 +378,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);
}
@@ -426,29 +399,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;
Response response;
if (!TextUtils.isEmpty(urlOverride)) {
request = new Request.Builder().url(urlOverride).build();
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);
}

View File

@@ -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");

View File

@@ -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());
}

View File

@@ -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.");
}

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}

View File

@@ -353,7 +353,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)
@@ -942,7 +942,7 @@ SPEC CHECKSUMS:
react-native-image-picker: 8cb4280e2c1efc3daeb2d9d597f9429a60472e40
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: fb7156dc75960c9895ddd9b9d68eeb874c9f323a
react-native-safe-area-context: 39c2d8be3328df5d437ac1700f4f3a4f75716acc

14
package-lock.json generated
View File

@@ -19,7 +19,7 @@
"@gorhom/bottom-sheet": "4.4.5",
"@mattermost/compass-icons": "0.1.35",
"@mattermost/react-native-emm": "1.3.4",
"@mattermost/react-native-network-client": "1.2.0",
"@mattermost/react-native-network-client": "1.3.0",
"@mattermost/react-native-paste-input": "0.6.1",
"@mattermost/react-native-turbo-log": "0.2.2",
"@mattermost/react-native-turbo-mailer": "0.2.3",
@@ -3241,9 +3241,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.20.2"
@@ -24293,9 +24293,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.20.2"

View File

@@ -16,7 +16,7 @@
"@gorhom/bottom-sheet": "4.4.5",
"@mattermost/compass-icons": "0.1.35",
"@mattermost/react-native-emm": "1.3.4",
"@mattermost/react-native-network-client": "1.2.0",
"@mattermost/react-native-network-client": "1.3.0",
"@mattermost/react-native-paste-input": "0.6.1",
"@mattermost/react-native-turbo-log": "0.2.2",
"@mattermost/react-native-turbo-mailer": "0.2.3",