diff --git a/.editorconfig b/.editorconfig index be3c34776..8496df79f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,7 +7,7 @@ end_of_line = lf insert_final_newline = true charset = utf-8 -[*.{js,jsx,json,html}] +[*.{js,jsx,json,html,ts,tsx}] indent_style = space indent_size = 4 diff --git a/.eslintrc.json b/.eslintrc.json index b7d9dbed4..191b60b9a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -2,7 +2,8 @@ "extends": [ "plugin:mattermost/react", "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended" + "plugin:@typescript-eslint/recommended", + "plugin:react-hooks/recommended" ], "parser": "@typescript-eslint/parser", "plugins": [ diff --git a/.gitignore b/.gitignore index 8871c6170..7be23d51e 100644 --- a/.gitignore +++ b/.gitignore @@ -101,3 +101,4 @@ detox/artifacts #editor-settings .vscode +.scannerwork diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 2bcc4148f..8e49c43b2 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + @@ -44,17 +43,16 @@ + + + + + + - - - + + + keys = new ArrayList(1); - keys.add(CURRENT_SERVER_URL); - KeysReadableArray asyncStorageKeys = new KeysReadableArray() { - @Override - public int size() { - return keys.size(); - } - @Override - public String getString(int index) { - return keys.get(index); - } - }; - - HashMap asyncStorageResults = asyncStorage.multiGet(asyncStorageKeys); - String serverUrl = asyncStorageResults.get(CURRENT_SERVER_URL); final WritableMap options = Arguments.createMap(); // KeyChain module fails if `authenticationPrompt` is not set final WritableMap authPrompt = Arguments.createMap(); diff --git a/android/app/src/main/java/com/mattermost/helpers/DatabaseHelper.java b/android/app/src/main/java/com/mattermost/helpers/DatabaseHelper.java new file mode 100644 index 000000000..cf3b07338 --- /dev/null +++ b/android/app/src/main/java/com/mattermost/helpers/DatabaseHelper.java @@ -0,0 +1,34 @@ +package com.mattermost.helpers; + +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; + +import com.nozbe.watermelondb.Database; + +public class DatabaseHelper { + private static final String DEFAULT_DATABASE_NAME = "default.db"; + private static Database defaultDatabase; + + private static void setDefaultDatabase(Context context) { + String databaseName = Uri.fromFile(context.getFilesDir()).toString() + "/" + DEFAULT_DATABASE_NAME; + defaultDatabase = new Database(databaseName, context); + } + + public static String getOnlyServerUrl(Context context) { + if (defaultDatabase == null) { + setDefaultDatabase(context); + } + + String emptyArray[] = {}; + String query = "SELECT url FROM servers"; + Cursor cursor = defaultDatabase.rawQuery(query, emptyArray); + + if (cursor.getCount() == 1) { + cursor.moveToFirst(); + return cursor.getString(0); + } + + return null; + } +} 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 f5b713096..ebe9cc987 100644 --- a/android/app/src/main/java/com/mattermost/rnbeta/CustomPushNotification.java +++ b/android/app/src/main/java/com/mattermost/rnbeta/CustomPushNotification.java @@ -27,6 +27,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.mattermost.helpers.DatabaseHelper; +import com.mattermost.helpers.ResolvePromise; import com.wix.reactnativenotifications.core.notification.PushNotification; import com.wix.reactnativenotifications.core.NotificationIntentAdapter; import com.wix.reactnativenotifications.core.AppLaunchHelper; @@ -35,11 +37,10 @@ import com.wix.reactnativenotifications.core.JsIOHelper; import static com.wix.reactnativenotifications.Defs.NOTIFICATION_RECEIVED_EVENT_NAME; -import com.mattermost.helpers.ResolvePromise; - 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 = "notification"; 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"; @@ -61,6 +62,7 @@ public class CustomPushNotification extends PushNotification { public CustomPushNotification(Context context, Bundle bundle, AppLifecycleFacade appLifecycleFacade, AppLaunchHelper appLaunchHelper, JsIOHelper jsIoHelper) { super(context, bundle, appLifecycleFacade, appLaunchHelper, jsIoHelper); this.context = context; + createNotificationChannels(); } @@ -106,8 +108,10 @@ public class CustomPushNotification extends PushNotification { final boolean isIdLoaded = initialData.getString("id_loaded") != null ? initialData.getString("id_loaded").equals("true") : false; int notificationId = MESSAGE_NOTIFICATION_ID; - if (ackId != null) { - notificationReceiptDelivery(ackId, postId, type, isIdLoaded, new ResolvePromise() { + String serverUrl = initialData.getString("server_url", DatabaseHelper.getOnlyServerUrl(context)); + + if (ackId != null && serverUrl != null) { + notificationReceiptDelivery(ackId, serverUrl, postId, type, isIdLoaded, new ResolvePromise() { @Override public void resolve(@Nullable Object value) { if (isIdLoaded) { @@ -127,6 +131,11 @@ public class CustomPushNotification extends PushNotification { // so we fetch the bundle again final Bundle data = mNotificationProps.asBundle(); + if (serverUrl == null) { + String message = data.getString("message"); + data.putString("message", "Unknown Server\n" + message); + } + if (channelId != null) { notificationId = channelId.hashCode(); @@ -465,15 +474,18 @@ public class CustomPushNotification extends PushNotification { private void addNotificationReplyAction(Notification.Builder notification, int notificationId, Bundle bundle) { String postId = bundle.getString("post_id"); + String serverUrl = bundle.getString("server_url", DatabaseHelper.getOnlyServerUrl(context)); - if (android.text.TextUtils.isEmpty(postId) || Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { + if (android.text.TextUtils.isEmpty(postId) || + serverUrl == null || + Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { return; } Intent replyIntent = new Intent(mContext, NotificationReplyBroadcastReceiver.class); replyIntent.setAction(KEY_TEXT_REPLY); replyIntent.putExtra(NOTIFICATION_ID, notificationId); - replyIntent.putExtra("pushNotification", bundle); + replyIntent.putExtra(NOTIFICATION, bundle); PendingIntent replyPendingIntent = PendingIntent.getBroadcast( mContext, @@ -540,8 +552,8 @@ public class CustomPushNotification extends PushNotification { return message.replaceFirst(": ", "").trim(); } - private void notificationReceiptDelivery(String ackId, String postId, String type, boolean isIdLoaded, ResolvePromise promise) { - ReceiptDelivery.send(context, ackId, postId, type, isIdLoaded, promise); + private void notificationReceiptDelivery(String ackId, String serverUrl, String postId, String type, boolean isIdLoaded, ResolvePromise promise) { + ReceiptDelivery.send(context, ackId, serverUrl, postId, type, isIdLoaded, promise); } private void createNotificationChannels() { diff --git a/android/app/src/main/java/com/mattermost/rnbeta/MainApplication.java b/android/app/src/main/java/com/mattermost/rnbeta/MainApplication.java index 6452d4c02..fc2884bd8 100644 --- a/android/app/src/main/java/com/mattermost/rnbeta/MainApplication.java +++ b/android/app/src/main/java/com/mattermost/rnbeta/MainApplication.java @@ -46,7 +46,6 @@ import com.facebook.soloader.SoLoader; import org.unimodules.adapters.react.ModuleRegistryAdapter; import org.unimodules.adapters.react.ReactModuleRegistryProvider; -import org.unimodules.core.interfaces.SingletonModule; import com.swmansion.reanimated.ReanimatedJSIModulePackage; 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 f630fb4af..e81e46622 100644 --- a/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyBroadcastReceiver.java +++ b/android/app/src/main/java/com/mattermost/rnbeta/NotificationReplyBroadcastReceiver.java @@ -48,9 +48,11 @@ public class NotificationReplyBroadcastReceiver extends BroadcastReceiver { final ReactApplicationContext reactApplicationContext = new ReactApplicationContext(context); final int notificationId = intent.getIntExtra(CustomPushNotification.NOTIFICATION_ID, -1); + final Bundle notification = intent.getBundleExtra(CustomPushNotification.NOTIFICATION); + final String serverUrl = notification.getString("serverUrl"); - Credentials.getCredentialsForCurrentServer(reactApplicationContext, new ResolvePromise() { + Credentials.getCredentialsForServer(reactApplicationContext, serverUrl, new ResolvePromise() { @Override public void resolve(@Nullable Object value) { if (value instanceof Boolean && !(Boolean)value) { 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 2e8ab101a..256d81fa2 100644 --- a/android/app/src/main/java/com/mattermost/rnbeta/ReceiptDelivery.java +++ b/android/app/src/main/java/com/mattermost/rnbeta/ReceiptDelivery.java @@ -22,14 +22,12 @@ import com.facebook.react.bridge.WritableMap; import com.mattermost.helpers.*; public class ReceiptDelivery { - static final String CURRENT_SERVER_URL = "@currentServerUrl"; - private static final int[] FIBONACCI_BACKOFFS = new int[] { 0, 1, 2, 3, 5, 8 }; - public static void send(Context context, final String ackId, final String postId, final String type, final boolean isIdLoaded, ResolvePromise promise) { + 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); - Credentials.getCredentialsForCurrentServer(reactApplicationContext, new ResolvePromise() { + Credentials.getCredentialsForServer(reactApplicationContext, serverUrl, new ResolvePromise() { @Override public void resolve(@Nullable Object value) { if (value instanceof Boolean && !(Boolean)value) { diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 140b05030..166843b94 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -1,10 +1,7 @@ -