Skip to content

Commit

Permalink
Merge branch 'main' into fix-15565
Browse files Browse the repository at this point in the history
  • Loading branch information
allroundexperts committed Mar 23, 2023
2 parents e608842 + b0b31d1 commit d4fc6aa
Show file tree
Hide file tree
Showing 205 changed files with 3,744 additions and 873 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/platformDeploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,11 @@ jobs:

- name: Deploy production to S3
if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }}
run: aws s3 cp --recursive --acl public-read "$GITHUB_WORKSPACE"/dist s3://expensify-cash/ && aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE s3://expensify-cash/.well-known/apple-app-site-association s3://expensify-cash/.well-known/apple-app-site-association
run: aws s3 cp --recursive --acl public-read "$GITHUB_WORKSPACE"/dist s3://expensify-cash/ && aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE s3://expensify-cash/.well-known/apple-app-site-association s3://expensify-cash/.well-known/apple-app-site-association && aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE s3://expensify-cash/.well-known/apple-app-site-association s3://expensify-cash/apple-app-site-association

- name: Deploy staging to S3
if: ${{ !fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }}
run: aws s3 cp --recursive --acl public-read "$GITHUB_WORKSPACE"/dist s3://staging-expensify-cash/ && aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE s3://staging-expensify-cash/.well-known/apple-app-site-association s3://staging-expensify-cash/.well-known/apple-app-site-association
run: aws s3 cp --recursive --acl public-read "$GITHUB_WORKSPACE"/dist s3://staging-expensify-cash/ && aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE s3://staging-expensify-cash/.well-known/apple-app-site-association s3://staging-expensify-cash/.well-known/apple-app-site-association && aws s3 cp --acl public-read --content-type 'application/json' --metadata-directive REPLACE s3://staging-expensify-cash/.well-known/apple-app-site-association s3://staging-expensify-cash/apple-app-site-association

- name: Purge production Cloudflare cache
if: ${{ fromJSON(env.SHOULD_DEPLOY_PRODUCTION) }}
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001028302
versionName "1.2.83-2"
versionCode 1001028801
versionName "1.2.88-1"
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()

if (isNewArchitectureEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,40 @@
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuffXfermode;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.WindowManager;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.app.Person;
import androidx.core.graphics.drawable.IconCompat;

import com.urbanairship.AirshipConfigOptions;
import com.urbanairship.json.JsonMap;
import com.urbanairship.json.JsonValue;
import com.urbanairship.push.PushMessage;
import com.urbanairship.push.notifications.NotificationArguments;
import com.urbanairship.reactnative.ReactNotificationProvider;
import com.urbanairship.util.ImageUtils;

import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Timestamp;
import java.time.Instant;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
Expand All @@ -63,8 +67,6 @@ public class CustomNotificationProvider extends ReactNotificationProvider {

// Conversation JSON keys
private static final String PAYLOAD_KEY = "payload";
private static final String TYPE_KEY = "type";
private static final String REPORT_COMMENT_TYPE = "reportComment";

private final ExecutorService executorService = Executors.newCachedThreadPool();
public final HashMap<Integer, NotificationCache> cache = new HashMap<>();
Expand Down Expand Up @@ -92,16 +94,17 @@ protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @
builder.setPriority(PRIORITY_MAX);
}

// Attempt to parse data and apply custom notification styling
if (message.containsKey(PAYLOAD_KEY)) {
try {
JsonMap payload = JsonValue.parseString(message.getExtra(PAYLOAD_KEY)).optMap();

// Apply message style only for report comments
if (REPORT_COMMENT_TYPE.equals(payload.get(TYPE_KEY).getString())) {
// Apply message style using onyxData from the notification payload
if (payload.get("onyxData").getList().size() > 0) {
applyMessageStyle(context, builder, payload, arguments.getNotificationId());
}
} catch (Exception e) {
Log.e(TAG, "Failed to parse conversation. SendID=" + message.getSendId(), e);
Log.e(TAG, "Failed to parse conversation, falling back to default notification style. SendID=" + message.getSendId(), e);
}
}

Expand Down Expand Up @@ -150,7 +153,7 @@ public Bitmap getCroppedBitmap(Bitmap bitmap) {

/**
* Applies the message style to the notification builder. It also takes advantage of the
* notification cache to build conversations.
* notification cache to build conversations style notifications.
*
* @param builder Notification builder that will receive the message style
* @param payload Notification payload, which contains all the data we need to build the notifications.
Expand All @@ -163,59 +166,82 @@ private void applyMessageStyle(@NonNull Context context, NotificationCompat.Buil
}

NotificationCache notificationCache = findOrCreateNotificationCache(reportID);
JsonMap reportAction = payload.get("reportAction").getMap();
String name = reportAction.get("person").getList().get(0).getMap().get("text").getString();
String avatar = reportAction.get("avatar").getString();
String accountID = Integer.toString(reportAction.get("actorAccountID").getInt(-1));
String message = reportAction.get("message").getList().get(0).getMap().get("text").getString();
long time = Timestamp.valueOf(reportAction.get("created").getString(Instant.now().toString())).getTime();
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);
if (person == null) {
IconCompat iconCompat = fetchIcon(context, avatar);
person = new Person.Builder()
.setIcon(iconCompat)
.setKey(accountID)
.setName(name)
.build();

notificationCache.people.put(accountID, person);
}

// Store the latest report comment in the local conversation history
notificationCache.messages.add(new NotificationCache.Message(person, message, time));

// Create the messaging style notification builder for this notification.
// Associate the notification with the person who sent the report comment.
// If this conversation has 2 participants or more and there's no room name, we should mark
// it as a group conversation.
// Also set the conversation title.
NotificationCompat.MessagingStyle messagingStyle = new NotificationCompat.MessagingStyle(person)
.setGroupConversation(notificationCache.people.size() > 2 || !roomName.isEmpty())
.setConversationTitle(conversationTitle);

// 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);
}
try {
JsonMap reportMap = payload.get("onyxData").getList().get(1).getMap().get("value").getMap();
String reportId = reportMap.keySet().iterator().next();
JsonMap messageData = reportMap.get(reportId).getMap();

String name = messageData.get("person").getList().get(0).getMap().get("text").getString();
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 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);
if (person == null) {
IconCompat iconCompat = fetchIcon(context, avatar);
person = new Person.Builder()
.setIcon(iconCompat)
.setKey(accountID)
.setName(name)
.build();

notificationCache.people.put(accountID, person);
}

// Clear the previous notification associated to this conversation so it looks like we are
// replacing them with this new one we just built.
if (notificationCache.prevNotificationID != -1) {
NotificationManagerCompat.from(context).cancel(notificationCache.prevNotificationID);
}
// Store the latest report comment in the local conversation history
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(notificationCache.people.size() > 2 || !roomName.isEmpty())
.setConversationTitle(conversationTitle);

// Apply the messaging style to the notification builder
builder.setStyle(messagingStyle);
// 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);
}

// Clear the previous notification associated to this conversation so it looks like we are
// replacing them with this new one we just built.
if (notificationCache.prevNotificationID != -1) {
NotificationManagerCompat.from(context).cancel(notificationCache.prevNotificationID);
}

// Apply the messaging style to the notification builder
builder.setStyle(messagingStyle);

} catch (Exception e) {
e.printStackTrace();
}

// Store the new notification ID so we can replace the notification if this conversation
// receives more messages
notificationCache.prevNotificationID = notificationID;
}

/**
* Safely retrieve the message time in milliseconds
*/
private long getMessageTimeInMillis(String createdTime) {
if (!createdTime.isEmpty()) {
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
return sdf.parse(createdTime).getTime();
} catch (Exception e) {
Log.e(TAG, "error parsing createdTime: " + createdTime);
e.printStackTrace();
}
}
return Calendar.getInstance().getTimeInMillis();
}

/**
* Check if we are showing a notification related to a reportID.
* If not, create a new NotificationCache so we can build a conversation notification
Expand Down
11 changes: 11 additions & 0 deletions android/app/src/main/res/drawable/alert_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:insetLeft="16dp"
android:insetTop="16dp"
android:insetRight="16dp"
android:insetBottom="16dp">
<shape android:shape="rectangle">
<corners android:radius="@dimen/dialog_radius" />
<solid android:color="@color/card_highlight_bg" />
</shape>
</inset>
6 changes: 6 additions & 0 deletions android/app/src/main/res/drawable/datepicker_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/card_alternate_bg" />
<corners android:radius="@dimen/dialog_radius" />
</shape>
6 changes: 6 additions & 0 deletions android/app/src/main/res/drawable/picker_background.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/card_highlight_bg" />
<corners android:radius="@dimen/dialog_radius" />
</shape>
Binary file added android/app/src/main/res/font/expneuebold.otf
Binary file not shown.
Binary file added android/app/src/main/res/font/expneueregular.otf
Binary file not shown.
2 changes: 2 additions & 0 deletions android/app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
<color name="accent">#03D47C</color>
<color name="dark">#0b1b34</color>
<color name="gray4">#7D8B8F</color>
<color name="card_highlight_bg">#07271F</color>
<color name="card_alternate_bg">#1A3D32</color>
</resources>
5 changes: 5 additions & 0 deletions android/app/src/main/res/values/dimen.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="dialog_radius">16dp</dimen>
<dimen name="spinner_font_size">16dp</dimen>
</resources>
49 changes: 49 additions & 0 deletions android/app/src/main/res/values/styles.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
<item name="android:statusBarColor">#061B09</item>
<item name="colorAccent">@color/accent</item>
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
<item name="popupTheme">@style/AppTheme.Popup</item>
<item name="android:spinnerDropDownItemStyle">@style/TextViewSpinnerDropDownItem</item>
<item name="android:datePickerDialogTheme">@style/DatePickerDialogTheme</item>
<item name="android:alertDialogTheme">@style/AlertDialogTheme</item>
</style>

<!-- Themes unique to the boot splash page -->
Expand All @@ -18,4 +22,49 @@
<item name="android:fitsSystemWindows">true</item>
</style>

<!-- Themes used by the Picker -->
<style name="AppTheme.Popup" parent="Base.ThemeOverlay.AppCompat">
<item name="colorBackgroundFloating">@null</item>
<item name="android:background">@drawable/picker_background</item>
<item name="android:textColor">@color/white</item>
</style>

<style name="TextViewSpinnerDropDownItem" parent="Widget.AppCompat.DropDownItem.Spinner">
<item name="android:textColor">@color/white</item>
<item name="android:textSize">@dimen/spinner_font_size</item>
<item name="android:fontFamily">@font/expneuebold</item>
</style>

<!-- Theme used by the DatePicker dialog -->
<style name="DatePickerDialogTheme" parent="Theme.AppCompat.Dialog">
<item name="android:windowBackground">@drawable/datepicker_background</item>
<item name="android:datePickerStyle">@style/DatePickerStyle</item>
<item name="android:fontFamily">@font/expneuebold</item>
<item name="colorAccent">@color/accent</item>
</style>

<style name="DatePickerStyle" parent="android:Widget.Material.DatePicker">
<item name="android:headerBackground">@color/card_highlight_bg</item> <!-- header background color -->
</style>

<!-- Theme used by the Alert dialog -->
<style name="AlertDialogTheme" parent="Theme.AppCompat.Dialog.Alert">
<item name="android:windowBackground">@drawable/alert_background</item>
<item name="android:textAppearanceSmall">@style/AlertTextAppearanceSmall</item>
<item name="android:textAppearanceMedium">@style/AlertTextAppearanceMedium</item>
<item name="android:textAppearanceLarge">@style/AlertTextAppearanceLarge</item>
<item name="colorAccent">@color/accent</item>
</style>

<style name="AlertTextAppearanceSmall" parent="TextAppearance.AppCompat.Small">
<item name="android:fontFamily">@font/expneueregular</item>
</style>

<style name="AlertTextAppearanceMedium" parent="TextAppearance.AppCompat.Medium">
<item name="android:fontFamily">@font/expneueregular</item>
</style>

<style name="AlertTextAppearanceLarge" parent="TextAppearance.AppCompat.Large">
<item name="android:fontFamily">@font/expneuebold</item>
</style>
</resources>
16 changes: 16 additions & 0 deletions assets/images/calendar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit d4fc6aa

Please sign in to comment.