From 0a72a27fb677b1d35a185405a7d003c1efa8f3a9 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 25 May 2023 16:46:58 +0100 Subject: [PATCH 01/24] temporarily enable debugging for local notifications --- android/app/build.gradle | 1 + android/app/src/release/assets/airshipconfig.properties | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 2c114b067d69..3f0089c08097 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -139,6 +139,7 @@ android { signingConfig signingConfigs.debug } release { + debuggable true signingConfig signingConfigs.release minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" diff --git a/android/app/src/release/assets/airshipconfig.properties b/android/app/src/release/assets/airshipconfig.properties index 194c4577de8b..490f74552f11 100644 --- a/android/app/src/release/assets/airshipconfig.properties +++ b/android/app/src/release/assets/airshipconfig.properties @@ -1,6 +1,7 @@ -appKey = 55vypj0ARc6cN09MX7ogtQ -appSecret = EsSaqbdLSvmyC6kSBFJCtQ -inProduction = true +appKey = uulSSfTDQJ2r0PMpjRrhmQ +appSecret = D4Bhf0HrQEehrPua74Tyiw +inProduction = false +developmentLogLevel = VERBOSE # Notification Customization notificationIcon = ic_notification From 000240db52f351ea84c2ed3da31172d77b91ac18 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 25 May 2023 16:54:52 +0100 Subject: [PATCH 02/24] improve handling of missing onyxData notification payload --- .../CustomNotificationProvider.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index eff3420ee96d..ae6d23c6101e 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -28,6 +28,7 @@ import androidx.core.graphics.drawable.IconCompat; import com.urbanairship.AirshipConfigOptions; +import com.urbanairship.json.JsonList; import com.urbanairship.json.JsonMap; import com.urbanairship.json.JsonValue; import com.urbanairship.push.PushMessage; @@ -43,6 +44,7 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -68,6 +70,8 @@ public class CustomNotificationProvider extends ReactNotificationProvider { // Conversation JSON keys private static final String PAYLOAD_KEY = "payload"; + private static final String ONYX_DATA_KEY = "onyxData"; + private final ExecutorService executorService = Executors.newCachedThreadPool(); public final HashMap cache = new HashMap<>(); @@ -99,9 +103,10 @@ protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @ try { JsonMap payload = JsonValue.parseString(message.getExtra(PAYLOAD_KEY)).optMap(); - // Apply message style using onyxData from the notification payload - if (payload.get("onyxData").getList().size() > 0) { - applyMessageStyle(context, builder, payload, arguments.getNotificationId()); + if (payload.containsKey(ONYX_DATA_KEY)) { + Objects.requireNonNull(payload.get(ONYX_DATA_KEY)).isNull(); + + applyMessageStyle(context, builder, payload, arguments.getNotificationId()); } } catch (Exception e) { Log.e(TAG, "Failed to parse conversation, falling back to default notification style. SendID=" + message.getSendId(), e); From 4852fd6d34b06296f5068c93ea24c26d849ca197 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 1 Jun 2023 15:27:31 +0100 Subject: [PATCH 03/24] temporarily flip iOS Airship keys --- ios/AirshipConfig.plist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/AirshipConfig.plist b/ios/AirshipConfig.plist index 3502dc33584f..8bd4702fac10 100644 --- a/ios/AirshipConfig.plist +++ b/ios/AirshipConfig.plist @@ -9,8 +9,8 @@ developmentAppSecret D4Bhf0HrQEehrPua74Tyiw productionAppKey - 55vypj0ARc6cN09MX7ogtQ + uulSSfTDQJ2r0PMpjRrhmQ productionAppSecret - EsSaqbdLSvmyC6kSBFJCtQ + D4Bhf0HrQEehrPua74Tyiw From 20618fbad6ff73c80a13126ea8a648ac2f377fbd Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 9 Jun 2023 15:06:21 +0100 Subject: [PATCH 04/24] only use Android conversation notification style for rooms --- .../customairshipextender/CustomNotificationProvider.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index ae6d23c6101e..307201e73ba6 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -183,7 +183,7 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil String message = messageData.get("message").getList().get(0).getMap().get("text").getString(); String roomName = payload.get("roomName") == null ? "" : payload.get("roomName").getString(""); - String conversationTitle = roomName.isEmpty() ? "Chat with " + name : roomName; +// String conversationTitle = roomName.isEmpty() ? "Chat with " + name : roomName; // Retrieve or create the Person object who sent the latest report comment Person person = notificationCache.people.get(accountID); @@ -205,8 +205,8 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil // Create the messaging style notification builder for this notification, associating the // notification with the person who sent the report comment. NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(person) - .setGroupConversation(notificationCache.people.size() > 2 || !roomName.isEmpty()) - .setConversationTitle(conversationTitle); + .setGroupConversation(!roomName.isEmpty()) + .setConversationTitle(roomName); // Add all conversation messages to the notification, including the last one we just received. for (NotificationCache.Message cachedMessage : notificationCache.messages) { From c0757787de17b196b6d1f895988e9b81d79aeabe Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 9 Jun 2023 15:28:14 +0100 Subject: [PATCH 05/24] always enable conversation notifications, but disable the title for non-rooms --- .../chat/customairshipextender/CustomNotificationProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index 307201e73ba6..bc4e555a43ba 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -205,7 +205,7 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil // Create the messaging style notification builder for this notification, associating the // notification with the person who sent the report comment. NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(person) - .setGroupConversation(!roomName.isEmpty()) + .setGroupConversation(true) .setConversationTitle(roomName); // Add all conversation messages to the notification, including the last one we just received. From f24386a6e3a72d35deaecaaddc6cc7015c39eed0 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 9 Jun 2023 16:23:30 +0100 Subject: [PATCH 06/24] add notification logging --- .../CustomNotificationProvider.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index bc4e555a43ba..4fb1bbb97008 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -87,6 +87,7 @@ public CustomNotificationProvider(@NonNull Context context, @NonNull AirshipConf protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @NonNull NotificationCompat.Builder builder, @NonNull NotificationArguments arguments) { super.onExtendBuilder(context, builder, arguments); PushMessage message = arguments.getMessage(); + Log.d(TAG, "buildNotification: " + message.toString()); // Improve notification delivery by categorising as a time-critical message builder.setCategory(CATEGORY_MESSAGE); @@ -102,10 +103,10 @@ protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @ if (message.containsKey(PAYLOAD_KEY)) { try { JsonMap payload = JsonValue.parseString(message.getExtra(PAYLOAD_KEY)).optMap(); - + Log.d(TAG, "message contains payload: " + payload); if (payload.containsKey(ONYX_DATA_KEY)) { Objects.requireNonNull(payload.get(ONYX_DATA_KEY)).isNull(); - + Log.d(TAG, "payload contains onxyData"); applyMessageStyle(context, builder, payload, arguments.getNotificationId()); } } catch (Exception e) { @@ -171,6 +172,11 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil } NotificationCache notificationCache = findOrCreateNotificationCache(reportID); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + notificationCache.messages.forEach(message -> { + Log.d(TAG, "messageCache: " + message.toString()); + }); + } try { JsonMap reportMap = payload.get("onyxData").getList().get(1).getMap().get("value").getMap(); From 242a7e18d69aefb25d246e9de6604f8c870d6c13 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 15 Jun 2023 16:12:21 +0100 Subject: [PATCH 07/24] remove unused notification line and reuse const for key --- .../chat/customairshipextender/CustomNotificationProvider.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index 4fb1bbb97008..6235da0c91a5 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -179,7 +179,7 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil } try { - JsonMap reportMap = payload.get("onyxData").getList().get(1).getMap().get("value").getMap(); + JsonMap reportMap = payload.get(ONYX_DATA_KEY).getList().get(1).getMap().get("value").getMap(); String reportId = reportMap.keySet().iterator().next(); JsonMap messageData = reportMap.get(reportId).getMap(); @@ -189,7 +189,6 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil String message = messageData.get("message").getList().get(0).getMap().get("text").getString(); String roomName = payload.get("roomName") == null ? "" : payload.get("roomName").getString(""); -// String conversationTitle = roomName.isEmpty() ? "Chat with " + name : roomName; // Retrieve or create the Person object who sent the latest report comment Person person = notificationCache.people.get(accountID); From cde416dee3960b68a035016d5a814c0b5888f2dc Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 16 Jun 2023 14:46:30 +0100 Subject: [PATCH 08/24] format the AndroidManifest file correctly --- android/app/src/main/AndroidManifest.xml | 197 +++++++++++++++-------- 1 file changed, 132 insertions(+), 65 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 05302f43ef8d..2e6667b9af69 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,81 +1,148 @@ + xmlns:tools="http://schemas.android.com/tools" + package="com.expensify.chat"> - + - - + + - - + android:resizeableActivity="false" + android:roundIcon="@mipmap/ic_launcher_round" + android:supportsRtl="false" + android:theme="@style/AppTheme" + tools:replace="android:supportsRtl"> + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - From 0756a367a540b5a964dd885abf444e94e9d65b73 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 16 Jun 2023 14:46:50 +0100 Subject: [PATCH 09/24] add notification xml metadata --- android/app/src/main/AndroidManifest.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 2e6667b9af69..5fa73947a96f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -142,7 +142,13 @@ android:name="com.urbanairship.reactnative.AIRSHIP_EXTENDER" android:value="com.expensify.chat.customairshipextender.CustomAirshipExtender" /> + + From 34325ccf5cddf7d423211a8fe4f8bdfa4cca4ffc Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 16 Jun 2023 14:48:35 +0100 Subject: [PATCH 10/24] update notification categories --- .../customairshipextender/CustomNotificationProvider.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index 6235da0c91a5..f9e0e799d56e 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -63,8 +63,8 @@ public class CustomNotificationProvider extends ReactNotificationProvider { // Define notification channel public static final String CHANNEL_MESSAGES_ID = "CHANNEL_MESSAGES"; - public static final String CHANNEL_MESSAGES_NAME = "Message Notifications"; - public static final String CHANNEL_GROUP_ID = "CHANNEL_GROUP_CHATS"; + public static final String CHANNEL_MESSAGES_NAME = "Messages"; + public static final String NOTIFICATION_GROUP_CHATS = "NOTIFICATION_GROUP_CHATS"; public static final String CHANNEL_GROUP_NAME = "Chats"; // Conversation JSON keys @@ -119,9 +119,8 @@ protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @ @RequiresApi(api = Build.VERSION_CODES.O) private void createAndRegisterNotificationChannel(@NonNull Context context) { - NotificationChannelGroup channelGroup = new NotificationChannelGroup(CHANNEL_GROUP_ID, CHANNEL_GROUP_NAME); + NotificationChannelGroup channelGroup = new NotificationChannelGroup(NOTIFICATION_GROUP_CHATS, CHANNEL_GROUP_NAME); NotificationChannel channel = new NotificationChannel(CHANNEL_MESSAGES_ID, CHANNEL_MESSAGES_NAME, NotificationManager.IMPORTANCE_HIGH); - channel.setGroup(CHANNEL_GROUP_ID); NotificationManager notificationManager = context.getSystemService(NotificationManager.class); notificationManager.createNotificationChannelGroup(channelGroup); From 0082ffbf8e07954bcf20e7c5723c1f36cedf66bc Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 16 Jun 2023 14:49:19 +0100 Subject: [PATCH 11/24] cache large profile avatar for notifications --- .../CustomNotificationProvider.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index f9e0e799d56e..f73c28e1a13b 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -9,11 +9,13 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; +import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; +import android.graphics.drawable.Icon; import android.os.Build; import android.util.DisplayMetrics; import android.util.Log; @@ -186,13 +188,18 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil String avatar = messageData.get("avatar").getString(); String accountID = Integer.toString(messageData.get("actorAccountID").getInt(-1)); String message = messageData.get("message").getList().get(0).getMap().get("text").getString(); - String roomName = payload.get("roomName") == null ? "" : payload.get("roomName").getString(""); // Retrieve or create the Person object who sent the latest report comment Person person = notificationCache.people.get(accountID); + Bitmap personIcon = notificationCache.bitmapIcons.get(accountID); + + if (personIcon == null) { + personIcon = fetchIcon(context, avatar); + } + if (person == null) { - IconCompat iconCompat = fetchIcon(context, avatar); + IconCompat iconCompat = IconCompat.createWithBitmap(personIcon); person = new Person.Builder() .setIcon(iconCompat) .setKey(accountID) @@ -200,6 +207,7 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil .build(); notificationCache.people.put(accountID, person); + notificationCache.bitmapIcons.put(accountID, personIcon); } // Store the latest report comment in the local conversation history @@ -290,7 +298,7 @@ public void onDismissNotification(PushMessage message) { } } - private IconCompat fetchIcon(@NonNull Context context, String urlString) { + private Bitmap fetchIcon(@NonNull Context context, String urlString) { URL parsedUrl = null; try { parsedUrl = urlString == null ? null : new URL(urlString); @@ -314,7 +322,7 @@ private IconCompat fetchIcon(@NonNull Context context, String urlString) { try { Bitmap bitmap = future.get(MAX_ICON_FETCH_WAIT_TIME_SECONDS, TimeUnit.SECONDS); - return IconCompat.createWithBitmap(getCroppedBitmap(bitmap)); + return getCroppedBitmap(bitmap); } catch (InterruptedException e) { Log.e(TAG,"Failed to fetch icon", e); Thread.currentThread().interrupt(); @@ -329,6 +337,8 @@ private IconCompat fetchIcon(@NonNull Context context, String urlString) { private static class NotificationCache { public Map people = new HashMap<>(); public ArrayList messages = new ArrayList<>(); + + public Map bitmapIcons = new HashMap<>(); public int prevNotificationID = -1; public static class Message { From 3b90cd790f3f3c0e3d3212059a2a5b958af7c834 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 16 Jun 2023 16:14:03 +0100 Subject: [PATCH 12/24] use large notification avatar icon --- .../customairshipextender/CustomNotificationProvider.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index f73c28e1a13b..a0ef940368fe 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -29,6 +29,7 @@ import androidx.core.app.Person; import androidx.core.graphics.drawable.IconCompat; +import com.expensify.chat.R; import com.urbanairship.AirshipConfigOptions; import com.urbanairship.json.JsonList; import com.urbanairship.json.JsonMap; @@ -234,6 +235,9 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil // Apply the messaging style to the notification builder builder.setStyle(messagingStyle); + // Set notification icon + builder.setLargeIcon(personIcon); + } catch (Exception e) { e.printStackTrace(); } From 32f37b793c57f08649a6050b31806b8a68511bb1 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Mon, 19 Jun 2023 11:07:14 +0100 Subject: [PATCH 13/24] use long for reportID to prevent negative invalid reportID --- .../customairshipextender/CustomNotificationProvider.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index a0ef940368fe..9010f7f03adf 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -76,7 +76,7 @@ public class CustomNotificationProvider extends ReactNotificationProvider { private static final String ONYX_DATA_KEY = "onyxData"; private final ExecutorService executorService = Executors.newCachedThreadPool(); - public final HashMap cache = new HashMap<>(); + public final HashMap cache = new HashMap<>(); public CustomNotificationProvider(@NonNull Context context, @NonNull AirshipConfigOptions configOptions) { super(context, configOptions); @@ -168,7 +168,7 @@ public Bitmap getCroppedBitmap(Bitmap bitmap) { * @param notificationID Current notification ID */ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Builder builder, JsonMap payload, int notificationID) { - int reportID = payload.get("reportID").getInt(-1); + long reportID = payload.get("reportID").getLong(-1); if (reportID == -1) { return; } @@ -271,7 +271,7 @@ private long getMessageTimeInMillis(String createdTime) { * @param reportID Report ID. * @return Notification Cache. */ - private NotificationCache findOrCreateNotificationCache(int reportID) { + private NotificationCache findOrCreateNotificationCache(long reportID) { NotificationCache notificationCache = cache.get(reportID); if (notificationCache == null) { From 4ea026a6c7f66b7ec3a43a8ccd1321386d6e73a8 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Tue, 20 Jun 2023 16:00:09 +0100 Subject: [PATCH 14/24] fix issue where notification cache wasn't dismissed --- .../chat/customairshipextender/CustomNotificationProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index 9010f7f03adf..f1432fc730e3 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -290,7 +290,7 @@ private NotificationCache findOrCreateNotificationCache(long reportID) { public void onDismissNotification(PushMessage message) { try { JsonMap payload = JsonValue.parseString(message.getExtra(PAYLOAD_KEY)).optMap(); - int reportID = payload.get("reportID").getInt(-1); + long reportID = payload.get("reportID").getLong(-1); if (reportID == -1) { return; From bb6bc2993fe451e92ad3a31d7a4b92c0e2b7fe3c Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Tue, 20 Jun 2023 16:17:19 +0100 Subject: [PATCH 15/24] prevent peek notification from being expanded, and refactor roomName variable --- .../customairshipextender/CustomNotificationProvider.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index f1432fc730e3..a22b47de0948 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -1,7 +1,7 @@ package com.expensify.chat.customairshipextender; import static androidx.core.app.NotificationCompat.CATEGORY_MESSAGE; -import static androidx.core.app.NotificationCompat.PRIORITY_MAX; +import static androidx.core.app.NotificationCompat.PRIORITY_HIGH; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; @@ -99,7 +99,7 @@ protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { builder.setChannelId(CHANNEL_MESSAGES_ID); } else { - builder.setPriority(PRIORITY_MAX); + builder.setPriority(PRIORITY_HIGH); } // Attempt to parse data and apply custom notification styling @@ -189,7 +189,7 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil String avatar = messageData.get("avatar").getString(); String accountID = Integer.toString(messageData.get("actorAccountID").getInt(-1)); String message = messageData.get("message").getList().get(0).getMap().get("text").getString(); - String roomName = payload.get("roomName") == null ? "" : payload.get("roomName").getString(""); + String conversationName = payload.get("roomName") == null ? "" : payload.get("roomName").getString(""); // Retrieve or create the Person object who sent the latest report comment Person person = notificationCache.people.get(accountID); @@ -219,7 +219,7 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil // notification with the person who sent the report comment. NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(person) .setGroupConversation(true) - .setConversationTitle(roomName); + .setConversationTitle(conversationName); // Add all conversation messages to the notification, including the last one we just received. for (NotificationCache.Message cachedMessage : notificationCache.messages) { From b462463781027a233b5aba8f88b63e33ecf70e32 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Wed, 21 Jun 2023 16:00:17 +0100 Subject: [PATCH 16/24] revert to max priority notifications, to ensure they peek above other apps --- .../customairshipextender/CustomNotificationProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index a22b47de0948..ea51337042c5 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -1,7 +1,7 @@ package com.expensify.chat.customairshipextender; import static androidx.core.app.NotificationCompat.CATEGORY_MESSAGE; -import static androidx.core.app.NotificationCompat.PRIORITY_HIGH; +import static androidx.core.app.NotificationCompat.PRIORITY_MAX; import android.app.NotificationChannel; import android.app.NotificationChannelGroup; @@ -99,7 +99,7 @@ protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { builder.setChannelId(CHANNEL_MESSAGES_ID); } else { - builder.setPriority(PRIORITY_HIGH); + builder.setPriority(PRIORITY_MAX); } // Attempt to parse data and apply custom notification styling From 1b1ad4885098ad8124e0839996e5657815eb0887 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Wed, 21 Jun 2023 17:01:05 +0100 Subject: [PATCH 17/24] clean up unused imports --- .../customairshipextender/CustomNotificationProvider.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index ea51337042c5..94e781efe90e 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -9,13 +9,11 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; -import android.graphics.drawable.Icon; import android.os.Build; import android.util.DisplayMetrics; import android.util.Log; @@ -29,9 +27,7 @@ import androidx.core.app.Person; import androidx.core.graphics.drawable.IconCompat; -import com.expensify.chat.R; import com.urbanairship.AirshipConfigOptions; -import com.urbanairship.json.JsonList; import com.urbanairship.json.JsonMap; import com.urbanairship.json.JsonValue; import com.urbanairship.push.PushMessage; From 9ec9d6b67867bb05dee9712a66f33a51f02a64c3 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 22 Jun 2023 13:41:56 +0100 Subject: [PATCH 18/24] only use conversation notifications when multiple have been received for the specific chat --- .../CustomNotificationProvider.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index 94e781efe90e..a5262ed17855 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -176,6 +176,7 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil }); } + boolean hasExistingNotification = notificationCache.messages.size() >= 1; try { JsonMap reportMap = payload.get(ONYX_DATA_KEY).getList().get(1).getMap().get("value").getMap(); String reportId = reportMap.keySet().iterator().next(); @@ -207,19 +208,22 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil notificationCache.bitmapIcons.put(accountID, personIcon); } - // Store the latest report comment in the local conversation history + // Despite not using conversation style for the initial notification from each chat, we need to cache it to enable conversation style for future notifications long createdTimeInMillis = getMessageTimeInMillis(messageData.get("created").getString("")); notificationCache.messages.add(new NotificationCache.Message(person, message, createdTimeInMillis)); - // Create the messaging style notification builder for this notification, associating the - // notification with the person who sent the report comment. - NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(person) - .setGroupConversation(true) - .setConversationTitle(conversationName); + // The initial notification for each conversation should use default styling. Once multiple messages are being displayed we should switch to conversation styling. + if (hasExistingNotification) { + // Create the messaging style notification builder for this notification, associating it with the person who sent the report comment + NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(person) + .setGroupConversation(true) + .setConversationTitle(conversationName); - // Add all conversation messages to the notification, including the last one we just received. - for (NotificationCache.Message cachedMessage : notificationCache.messages) { - messagingStyle.addMessage(cachedMessage.text, cachedMessage.time, cachedMessage.person); + // Add all conversation messages to the notification, including the last one we just received. + for (NotificationCache.Message cachedMessage : notificationCache.messages) { + messagingStyle.addMessage(cachedMessage.text, cachedMessage.time, cachedMessage.person); + } + builder.setStyle(messagingStyle); } // Clear the previous notification associated to this conversation so it looks like we are @@ -228,9 +232,6 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil NotificationManagerCompat.from(context).cancel(notificationCache.prevNotificationID); } - // Apply the messaging style to the notification builder - builder.setStyle(messagingStyle); - // Set notification icon builder.setLargeIcon(personIcon); From 327d88ad6bb851306c54ac1d41ea61e36b5d7979 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 22 Jun 2023 13:58:05 +0100 Subject: [PATCH 19/24] improve logging and documentation of Android notification logic --- .../customairshipextender/CustomNotificationProvider.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index a5262ed17855..655189b1a238 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -176,7 +176,9 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil }); } + // Do other cached notifications exist for this chat already? boolean hasExistingNotification = notificationCache.messages.size() >= 1; + try { JsonMap reportMap = payload.get(ONYX_DATA_KEY).getList().get(1).getMap().get("value").getMap(); String reportId = reportMap.keySet().iterator().next(); @@ -195,7 +197,9 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil if (personIcon == null) { personIcon = fetchIcon(context, avatar); } + builder.setLargeIcon(personIcon); + // Persist the person and icon to the notification cache if (person == null) { IconCompat iconCompat = IconCompat.createWithBitmap(personIcon); person = new Person.Builder() @@ -232,9 +236,6 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil NotificationManagerCompat.from(context).cancel(notificationCache.prevNotificationID); } - // Set notification icon - builder.setLargeIcon(personIcon); - } catch (Exception e) { e.printStackTrace(); } From 515b35f59b644894e58b174ab71810d2a7d4cf6e Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 22 Jun 2023 15:59:26 +0100 Subject: [PATCH 20/24] update iOS pods --- ios/NewExpensify.xcodeproj/project.pbxproj | 15 +++++++++------ ios/Podfile.lock | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj index f34f8959aab0..0933ddbd436d 100644 --- a/ios/NewExpensify.xcodeproj/project.pbxproj +++ b/ios/NewExpensify.xcodeproj/project.pbxproj @@ -66,24 +66,24 @@ 37F6DD6E91B4C55BD8DDC895 /* Pods-NewExpensify.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.debug.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.debug.xcconfig"; sourceTree = ""; }; 391B5D1DB6CFBAC16FD11DC4 /* Pods-NewExpensify.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.release.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.release.xcconfig"; sourceTree = ""; }; 44BF435285B94E5B95F90994 /* ExpensifyNewKansas-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNewKansas-Medium.otf"; path = "../assets/fonts/native/ExpensifyNewKansas-Medium.otf"; sourceTree = ""; }; - 52796131E6554494B2DDB056 /* ExpensifyNeue-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Bold.otf"; path = "../assets/fonts/native/ExpensifyNeue-Bold.otf"; sourceTree = ""; }; + 52796131E6554494B2DDB056 /* ExpensifyNeue-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Bold.otf"; path = "../assets/fonts/native/ExpensifyNeue-Bold.otf"; sourceTree = ""; }; 7041848326A8E40900E09F4D /* RCTStartupTimer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RCTStartupTimer.h; path = NewExpensify/RCTStartupTimer.h; sourceTree = ""; }; 7041848426A8E47D00E09F4D /* RCTStartupTimer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RCTStartupTimer.m; path = NewExpensify/RCTStartupTimer.m; sourceTree = ""; }; 70CF6E81262E297300711ADC /* BootSplash.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = BootSplash.storyboard; path = NewExpensify/BootSplash.storyboard; sourceTree = ""; }; - 8B28D84EF339436DBD42A203 /* ExpensifyNeue-BoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-BoldItalic.otf"; path = "../assets/fonts/native/ExpensifyNeue-BoldItalic.otf"; sourceTree = ""; }; + 8B28D84EF339436DBD42A203 /* ExpensifyNeue-BoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-BoldItalic.otf"; path = "../assets/fonts/native/ExpensifyNeue-BoldItalic.otf"; sourceTree = ""; }; B37C757CE02B734BFED38097 /* Pods-NewExpensify-NewExpensifyTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debug.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debug.xcconfig"; sourceTree = ""; }; - BF6A4C5167244B9FB8E4D4E3 /* ExpensifyNeue-Italic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Italic.otf"; path = "../assets/fonts/native/ExpensifyNeue-Italic.otf"; sourceTree = ""; }; + BF6A4C5167244B9FB8E4D4E3 /* ExpensifyNeue-Italic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Italic.otf"; path = "../assets/fonts/native/ExpensifyNeue-Italic.otf"; sourceTree = ""; }; CA3A3642AEED7CF2D4CD3716 /* Pods-NewExpensify-NewExpensifyTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.release.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.release.xcconfig"; sourceTree = ""; }; D2AFB39EC1D44BF9B91D3227 /* ExpensifyNewKansas-MediumItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNewKansas-MediumItalic.otf"; path = "../assets/fonts/native/ExpensifyNewKansas-MediumItalic.otf"; sourceTree = ""; }; - DCF33E34FFEC48128CDD41D4 /* ExpensifyMono-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyMono-Bold.otf"; path = "../assets/fonts/native/ExpensifyMono-Bold.otf"; sourceTree = ""; }; + DCF33E34FFEC48128CDD41D4 /* ExpensifyMono-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyMono-Bold.otf"; path = "../assets/fonts/native/ExpensifyMono-Bold.otf"; sourceTree = ""; }; DD7904292792E76D004484B4 /* RCTBootSplash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTBootSplash.h; path = NewExpensify/RCTBootSplash.h; sourceTree = ""; }; DD79042A2792E76D004484B4 /* RCTBootSplash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RCTBootSplash.m; path = NewExpensify/RCTBootSplash.m; sourceTree = ""; }; - E704648954784DDFBAADF568 /* ExpensifyMono-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyMono-Regular.otf"; path = "../assets/fonts/native/ExpensifyMono-Regular.otf"; sourceTree = ""; }; + E704648954784DDFBAADF568 /* ExpensifyMono-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyMono-Regular.otf"; path = "../assets/fonts/native/ExpensifyMono-Regular.otf"; sourceTree = ""; }; E9DF872C2525201700607FDC /* AirshipConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AirshipConfig.plist; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; F0C450E92705020500FD2970 /* colors.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = colors.json; path = ../colors.json; sourceTree = ""; }; - F4F8A052A22040339996324B /* ExpensifyNeue-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Regular.otf"; path = "../assets/fonts/native/ExpensifyNeue-Regular.otf"; sourceTree = ""; }; + F4F8A052A22040339996324B /* ExpensifyNeue-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Regular.otf"; path = "../assets/fonts/native/ExpensifyNeue-Regular.otf"; sourceTree = ""; }; F679A86058F8C4B331D239C3 /* libPods-NewExpensify-NewExpensifyTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NewExpensify-NewExpensifyTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -648,9 +648,11 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = NewExpensify/Chat.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 368M544MTT; + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; INFOPLIST_FILE = "$(SRCROOT)/NewExpensify/Info.plist"; @@ -665,6 +667,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat; PRODUCT_NAME = "New Expensify"; PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore; + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = chat_expensify_development; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 048eeca5f76f..7ca12edb2b68 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1024,7 +1024,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Airship: c70eed50e429f97f5adb285423c7291fb7a032ae AirshipFrameworkProxy: 7bc4130c668c6c98e2d4c60fe4c9eb61a999be99 - boost: a7c83b31436843459a1961bfd74b96033dc77234 + boost: 57d2868c099736d80fcd648bf211b4431e51a558 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: ff54429f0110d3c722630a98096ba689c39f6d5f @@ -1067,7 +1067,7 @@ SPEC CHECKSUMS: Permission-LocationWhenInUse: 3ba99e45c852763f730eabecec2870c2382b7bd4 Plaid: 7d340abeadb46c7aa1a91f896c5b22395a31fcf2 PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef - RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda + RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: e9e7b8b45aa9bedb2fdad71740adf07a7265b9be RCTTypeSafety: 9ae0e9206625e995f0df4d5b9ddc94411929fb30 React: a71c8e1380f07e01de721ccd52bcf9c03e81867d From 505b002ada8b072988615405526aab66034bac69 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Thu, 22 Jun 2023 15:59:48 +0100 Subject: [PATCH 21/24] add iOS communication notification entitlement --- ios/NewExpensify/Chat.entitlements | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ios/NewExpensify/Chat.entitlements b/ios/NewExpensify/Chat.entitlements index 33bb7f9feff8..1d9bc86a21de 100644 --- a/ios/NewExpensify/Chat.entitlements +++ b/ios/NewExpensify/Chat.entitlements @@ -10,5 +10,7 @@ applinks:staging.new.expensify.com webcredentials:new.expensify.com + com.apple.developer.usernotifications.communication + From 60674e58ba3f11658f3af57703d7b18de8377502 Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 23 Jun 2023 10:00:46 +0100 Subject: [PATCH 22/24] revert the iOS changes --- ios/NewExpensify.xcodeproj/project.pbxproj | 15 ++++++--------- ios/NewExpensify/Chat.entitlements | 2 -- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj index 0933ddbd436d..f34f8959aab0 100644 --- a/ios/NewExpensify.xcodeproj/project.pbxproj +++ b/ios/NewExpensify.xcodeproj/project.pbxproj @@ -66,24 +66,24 @@ 37F6DD6E91B4C55BD8DDC895 /* Pods-NewExpensify.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.debug.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.debug.xcconfig"; sourceTree = ""; }; 391B5D1DB6CFBAC16FD11DC4 /* Pods-NewExpensify.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.release.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.release.xcconfig"; sourceTree = ""; }; 44BF435285B94E5B95F90994 /* ExpensifyNewKansas-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNewKansas-Medium.otf"; path = "../assets/fonts/native/ExpensifyNewKansas-Medium.otf"; sourceTree = ""; }; - 52796131E6554494B2DDB056 /* ExpensifyNeue-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Bold.otf"; path = "../assets/fonts/native/ExpensifyNeue-Bold.otf"; sourceTree = ""; }; + 52796131E6554494B2DDB056 /* ExpensifyNeue-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Bold.otf"; path = "../assets/fonts/native/ExpensifyNeue-Bold.otf"; sourceTree = ""; }; 7041848326A8E40900E09F4D /* RCTStartupTimer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RCTStartupTimer.h; path = NewExpensify/RCTStartupTimer.h; sourceTree = ""; }; 7041848426A8E47D00E09F4D /* RCTStartupTimer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = RCTStartupTimer.m; path = NewExpensify/RCTStartupTimer.m; sourceTree = ""; }; 70CF6E81262E297300711ADC /* BootSplash.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = BootSplash.storyboard; path = NewExpensify/BootSplash.storyboard; sourceTree = ""; }; - 8B28D84EF339436DBD42A203 /* ExpensifyNeue-BoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-BoldItalic.otf"; path = "../assets/fonts/native/ExpensifyNeue-BoldItalic.otf"; sourceTree = ""; }; + 8B28D84EF339436DBD42A203 /* ExpensifyNeue-BoldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-BoldItalic.otf"; path = "../assets/fonts/native/ExpensifyNeue-BoldItalic.otf"; sourceTree = ""; }; B37C757CE02B734BFED38097 /* Pods-NewExpensify-NewExpensifyTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.debug.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.debug.xcconfig"; sourceTree = ""; }; - BF6A4C5167244B9FB8E4D4E3 /* ExpensifyNeue-Italic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Italic.otf"; path = "../assets/fonts/native/ExpensifyNeue-Italic.otf"; sourceTree = ""; }; + BF6A4C5167244B9FB8E4D4E3 /* ExpensifyNeue-Italic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Italic.otf"; path = "../assets/fonts/native/ExpensifyNeue-Italic.otf"; sourceTree = ""; }; CA3A3642AEED7CF2D4CD3716 /* Pods-NewExpensify-NewExpensifyTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify-NewExpensifyTests.release.xcconfig"; path = "Target Support Files/Pods-NewExpensify-NewExpensifyTests/Pods-NewExpensify-NewExpensifyTests.release.xcconfig"; sourceTree = ""; }; D2AFB39EC1D44BF9B91D3227 /* ExpensifyNewKansas-MediumItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNewKansas-MediumItalic.otf"; path = "../assets/fonts/native/ExpensifyNewKansas-MediumItalic.otf"; sourceTree = ""; }; - DCF33E34FFEC48128CDD41D4 /* ExpensifyMono-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyMono-Bold.otf"; path = "../assets/fonts/native/ExpensifyMono-Bold.otf"; sourceTree = ""; }; + DCF33E34FFEC48128CDD41D4 /* ExpensifyMono-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyMono-Bold.otf"; path = "../assets/fonts/native/ExpensifyMono-Bold.otf"; sourceTree = ""; }; DD7904292792E76D004484B4 /* RCTBootSplash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTBootSplash.h; path = NewExpensify/RCTBootSplash.h; sourceTree = ""; }; DD79042A2792E76D004484B4 /* RCTBootSplash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RCTBootSplash.m; path = NewExpensify/RCTBootSplash.m; sourceTree = ""; }; - E704648954784DDFBAADF568 /* ExpensifyMono-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyMono-Regular.otf"; path = "../assets/fonts/native/ExpensifyMono-Regular.otf"; sourceTree = ""; }; + E704648954784DDFBAADF568 /* ExpensifyMono-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyMono-Regular.otf"; path = "../assets/fonts/native/ExpensifyMono-Regular.otf"; sourceTree = ""; }; E9DF872C2525201700607FDC /* AirshipConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = AirshipConfig.plist; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; F0C450E92705020500FD2970 /* colors.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = colors.json; path = ../colors.json; sourceTree = ""; }; - F4F8A052A22040339996324B /* ExpensifyNeue-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Regular.otf"; path = "../assets/fonts/native/ExpensifyNeue-Regular.otf"; sourceTree = ""; }; + F4F8A052A22040339996324B /* ExpensifyNeue-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = undefined; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Regular.otf"; path = "../assets/fonts/native/ExpensifyNeue-Regular.otf"; sourceTree = ""; }; F679A86058F8C4B331D239C3 /* libPods-NewExpensify-NewExpensifyTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NewExpensify-NewExpensifyTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -648,11 +648,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = NewExpensify/Chat.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = 368M544MTT; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 368M544MTT; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; INFOPLIST_FILE = "$(SRCROOT)/NewExpensify/Info.plist"; @@ -667,7 +665,6 @@ PRODUCT_BUNDLE_IDENTIFIER = com.chat.expensify.chat; PRODUCT_NAME = "New Expensify"; PROVISIONING_PROFILE_SPECIFIER = chat_expensify_appstore; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = chat_expensify_development; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/ios/NewExpensify/Chat.entitlements b/ios/NewExpensify/Chat.entitlements index 1d9bc86a21de..33bb7f9feff8 100644 --- a/ios/NewExpensify/Chat.entitlements +++ b/ios/NewExpensify/Chat.entitlements @@ -10,7 +10,5 @@ applinks:staging.new.expensify.com webcredentials:new.expensify.com - com.apple.developer.usernotifications.communication - From 32e43d81d9fd52db9882ee0cf3ef45a7575cf3ba Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 23 Jun 2023 10:09:29 +0100 Subject: [PATCH 23/24] remove debug config, logs, and remove unecessary newlines --- .../CustomNotificationProvider.java | 10 +--------- .../app/src/release/assets/airshipconfig.properties | 7 +++---- ios/AirshipConfig.plist | 4 ++-- ios/Podfile.lock | 4 ++-- 4 files changed, 8 insertions(+), 17 deletions(-) diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index 655189b1a238..a06695c836d5 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -68,7 +68,6 @@ public class CustomNotificationProvider extends ReactNotificationProvider { // Conversation JSON keys private static final String PAYLOAD_KEY = "payload"; - private static final String ONYX_DATA_KEY = "onyxData"; private final ExecutorService executorService = Executors.newCachedThreadPool(); @@ -102,7 +101,6 @@ protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @ if (message.containsKey(PAYLOAD_KEY)) { try { JsonMap payload = JsonValue.parseString(message.getExtra(PAYLOAD_KEY)).optMap(); - Log.d(TAG, "message contains payload: " + payload); if (payload.containsKey(ONYX_DATA_KEY)) { Objects.requireNonNull(payload.get(ONYX_DATA_KEY)).isNull(); Log.d(TAG, "payload contains onxyData"); @@ -169,14 +167,8 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil return; } + // Retrieve and check for cached notifications NotificationCache notificationCache = findOrCreateNotificationCache(reportID); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - notificationCache.messages.forEach(message -> { - Log.d(TAG, "messageCache: " + message.toString()); - }); - } - - // Do other cached notifications exist for this chat already? boolean hasExistingNotification = notificationCache.messages.size() >= 1; try { diff --git a/android/app/src/release/assets/airshipconfig.properties b/android/app/src/release/assets/airshipconfig.properties index 490f74552f11..194c4577de8b 100644 --- a/android/app/src/release/assets/airshipconfig.properties +++ b/android/app/src/release/assets/airshipconfig.properties @@ -1,7 +1,6 @@ -appKey = uulSSfTDQJ2r0PMpjRrhmQ -appSecret = D4Bhf0HrQEehrPua74Tyiw -inProduction = false -developmentLogLevel = VERBOSE +appKey = 55vypj0ARc6cN09MX7ogtQ +appSecret = EsSaqbdLSvmyC6kSBFJCtQ +inProduction = true # Notification Customization notificationIcon = ic_notification diff --git a/ios/AirshipConfig.plist b/ios/AirshipConfig.plist index 8bd4702fac10..3502dc33584f 100644 --- a/ios/AirshipConfig.plist +++ b/ios/AirshipConfig.plist @@ -9,8 +9,8 @@ developmentAppSecret D4Bhf0HrQEehrPua74Tyiw productionAppKey - uulSSfTDQJ2r0PMpjRrhmQ + 55vypj0ARc6cN09MX7ogtQ productionAppSecret - D4Bhf0HrQEehrPua74Tyiw + EsSaqbdLSvmyC6kSBFJCtQ diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 7ca12edb2b68..048eeca5f76f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1024,7 +1024,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Airship: c70eed50e429f97f5adb285423c7291fb7a032ae AirshipFrameworkProxy: 7bc4130c668c6c98e2d4c60fe4c9eb61a999be99 - boost: 57d2868c099736d80fcd648bf211b4431e51a558 + boost: a7c83b31436843459a1961bfd74b96033dc77234 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: ff54429f0110d3c722630a98096ba689c39f6d5f @@ -1067,7 +1067,7 @@ SPEC CHECKSUMS: Permission-LocationWhenInUse: 3ba99e45c852763f730eabecec2870c2382b7bd4 Plaid: 7d340abeadb46c7aa1a91f896c5b22395a31fcf2 PromisesObjC: 09985d6d70fbe7878040aa746d78236e6946d2ef - RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 + RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda RCTRequired: e9e7b8b45aa9bedb2fdad71740adf07a7265b9be RCTTypeSafety: 9ae0e9206625e995f0df4d5b9ddc94411929fb30 React: a71c8e1380f07e01de721ccd52bcf9c03e81867d From 33afa6322c4cce6f0e5a3c343a6270750532a21e Mon Sep 17 00:00:00 2001 From: Jules Rosser Date: Fri, 23 Jun 2023 10:20:41 +0100 Subject: [PATCH 24/24] rooms and group chats should always use conversational styling --- android/app/build.gradle | 1 - .../customairshipextender/CustomNotificationProvider.java | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index c3e05b3403b0..be725a09e9a2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -139,7 +139,6 @@ android { signingConfig signingConfigs.debug } release { - debuggable true signingConfig signingConfigs.release minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" diff --git a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java index a06695c836d5..d7dff0ffcf0f 100644 --- a/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java +++ b/android/app/src/main/java/com/expensify/chat/customairshipextender/CustomNotificationProvider.java @@ -208,8 +208,9 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil long createdTimeInMillis = getMessageTimeInMillis(messageData.get("created").getString("")); notificationCache.messages.add(new NotificationCache.Message(person, message, createdTimeInMillis)); - // The initial notification for each conversation should use default styling. Once multiple messages are being displayed we should switch to conversation styling. - if (hasExistingNotification) { + + // Conversational styling should be applied to groups chats, rooms, and any 1:1 chats with more than one notification (ensuring the large profile image is always shown) + if (!conversationName.isEmpty() || hasExistingNotification) { // Create the messaging style notification builder for this notification, associating it with the person who sent the report comment NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(person) .setGroupConversation(true)