Skip to content

Commit

Permalink
Merge branch 'vit-tieredBankAccountFlow' of github.com:barttom/App-ex…
Browse files Browse the repository at this point in the history
…pensify into fix/more-styling-fixes
  • Loading branch information
MrMuzyk committed Feb 1, 2024
2 parents 68fe6c8 + fbc5e7c commit 3b288fb
Show file tree
Hide file tree
Showing 94 changed files with 1,473 additions and 760 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 1001043400
versionName "1.4.34-0"
versionCode 1001043500
versionName "1.4.35-0"
}

flavorDimensions "default"
Expand Down
2 changes: 1 addition & 1 deletion assets/images/new-expensify.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions docs/articles/new-expensify/account-settings/Preferences.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
title: Preferences
description: How to manage your Expensify Preferences
---
# Overview
Your Preferences in Expensify allow you to customize how you use New Expensify.

- Set your theme preference

# How to set your theme preference in New Expensify

To set or update your theme preference in New Expensify:
1. Go to **Settings > Preferences**
2. Tap on **Theme**
3. You can choose between the _Dark_ theme, the _Light_ theme, or _Use Device Settings_

_Use Device Settings_ is the default setting.

Selecting _Use Device Settings_ will use your device's theme settings. For example, if your device is set to adjust the appearance from light to dark during the day, we'll match that.

Your theme preference will sync across all your New Expensify apps (mobile, web, or OSX desktop apps).
4 changes: 2 additions & 2 deletions ios/NewExpensify/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.4.34</string>
<string>1.4.35</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
Expand All @@ -40,7 +40,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>1.4.34.0</string>
<string>1.4.35.0</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSApplicationQueriesSchemes</key>
Expand Down
4 changes: 2 additions & 2 deletions ios/NewExpensifyTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.4.34</string>
<string>1.4.35</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.4.34.0</string>
<string>1.4.35.0</string>
</dict>
</plist>
4 changes: 2 additions & 2 deletions ios/NotificationServiceExtension/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleShortVersionString</key>
<string>1.4.34</string>
<string>1.4.35</string>
<key>CFBundleVersion</key>
<string>1.4.34.0</string>
<string>1.4.35.0</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "new.expensify",
"version": "1.4.34-0",
"version": "1.4.35-0",
"author": "Expensify, Inc.",
"homepage": "https://new.expensify.com",
"description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
Expand Down
200 changes: 200 additions & 0 deletions patches/react-native-web+0.19.9+005+image-header-support.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
diff --git a/node_modules/react-native-web/dist/exports/Image/index.js b/node_modules/react-native-web/dist/exports/Image/index.js
index 95355d5..19109fc 100644
--- a/node_modules/react-native-web/dist/exports/Image/index.js
+++ b/node_modules/react-native-web/dist/exports/Image/index.js
@@ -135,7 +135,22 @@ function resolveAssetUri(source) {
}
return uri;
}
-var Image = /*#__PURE__*/React.forwardRef((props, ref) => {
+function raiseOnErrorEvent(uri, _ref) {
+ var onError = _ref.onError,
+ onLoadEnd = _ref.onLoadEnd;
+ if (onError) {
+ onError({
+ nativeEvent: {
+ error: "Failed to load resource " + uri + " (404)"
+ }
+ });
+ }
+ if (onLoadEnd) onLoadEnd();
+}
+function hasSourceDiff(a, b) {
+ return a.uri !== b.uri || JSON.stringify(a.headers) !== JSON.stringify(b.headers);
+}
+var BaseImage = /*#__PURE__*/React.forwardRef((props, ref) => {
var ariaLabel = props['aria-label'],
blurRadius = props.blurRadius,
defaultSource = props.defaultSource,
@@ -236,16 +251,10 @@ var Image = /*#__PURE__*/React.forwardRef((props, ref) => {
}
}, function error() {
updateState(ERRORED);
- if (onError) {
- onError({
- nativeEvent: {
- error: "Failed to load resource " + uri + " (404)"
- }
- });
- }
- if (onLoadEnd) {
- onLoadEnd();
- }
+ raiseOnErrorEvent(uri, {
+ onError,
+ onLoadEnd
+ });
});
}
function abortPendingRequest() {
@@ -277,10 +286,78 @@ var Image = /*#__PURE__*/React.forwardRef((props, ref) => {
suppressHydrationWarning: true
}), hiddenImage, createTintColorSVG(tintColor, filterRef.current));
});
-Image.displayName = 'Image';
+BaseImage.displayName = 'Image';
+
+/**
+ * This component handles specifically loading an image source with headers
+ * default source is never loaded using headers
+ */
+var ImageWithHeaders = /*#__PURE__*/React.forwardRef((props, ref) => {
+ // $FlowIgnore: This component would only be rendered when `source` matches `ImageSource`
+ var nextSource = props.source;
+ var _React$useState3 = React.useState(''),
+ blobUri = _React$useState3[0],
+ setBlobUri = _React$useState3[1];
+ var request = React.useRef({
+ cancel: () => {},
+ source: {
+ uri: '',
+ headers: {}
+ },
+ promise: Promise.resolve('')
+ });
+ var onError = props.onError,
+ onLoadStart = props.onLoadStart,
+ onLoadEnd = props.onLoadEnd;
+ React.useEffect(() => {
+ if (!hasSourceDiff(nextSource, request.current.source)) {
+ return;
+ }
+
+ // When source changes we want to clean up any old/running requests
+ request.current.cancel();
+ if (onLoadStart) {
+ onLoadStart();
+ }
+
+ // Store a ref for the current load request so we know what's the last loaded source,
+ // and so we can cancel it if a different source is passed through props
+ request.current = ImageLoader.loadWithHeaders(nextSource);
+ request.current.promise.then(uri => setBlobUri(uri)).catch(() => raiseOnErrorEvent(request.current.source.uri, {
+ onError,
+ onLoadEnd
+ }));
+ }, [nextSource, onLoadStart, onError, onLoadEnd]);
+
+ // Cancel any request on unmount
+ React.useEffect(() => request.current.cancel, []);
+ var propsToPass = _objectSpread(_objectSpread({}, props), {}, {
+ // `onLoadStart` is called from the current component
+ // We skip passing it down to prevent BaseImage raising it a 2nd time
+ onLoadStart: undefined,
+ // Until the current component resolves the request (using headers)
+ // we skip forwarding the source so the base component doesn't attempt
+ // to load the original source
+ source: blobUri ? _objectSpread(_objectSpread({}, nextSource), {}, {
+ uri: blobUri
+ }) : undefined
+ });
+ return /*#__PURE__*/React.createElement(BaseImage, _extends({
+ ref: ref
+ }, propsToPass));
+});

// $FlowIgnore: This is the correct type, but casting makes it unhappy since the variables aren't defined yet
-var ImageWithStatics = Image;
+var ImageWithStatics = /*#__PURE__*/React.forwardRef((props, ref) => {
+ if (props.source && props.source.headers) {
+ return /*#__PURE__*/React.createElement(ImageWithHeaders, _extends({
+ ref: ref
+ }, props));
+ }
+ return /*#__PURE__*/React.createElement(BaseImage, _extends({
+ ref: ref
+ }, props));
+});
ImageWithStatics.getSize = function (uri, success, failure) {
ImageLoader.getSize(uri, success, failure);
};
diff --git a/node_modules/react-native-web/dist/modules/ImageLoader/index.js b/node_modules/react-native-web/dist/modules/ImageLoader/index.js
index bc06a87..e309394 100644
--- a/node_modules/react-native-web/dist/modules/ImageLoader/index.js
+++ b/node_modules/react-native-web/dist/modules/ImageLoader/index.js
@@ -76,7 +76,7 @@ var ImageLoader = {
var image = requests["" + requestId];
if (image) {
var naturalHeight = image.naturalHeight,
- naturalWidth = image.naturalWidth;
+ naturalWidth = image.naturalWidth;
if (naturalHeight && naturalWidth) {
success(naturalWidth, naturalHeight);
complete = true;
@@ -102,11 +102,19 @@ var ImageLoader = {
id += 1;
var image = new window.Image();
image.onerror = onError;
- image.onload = e => {
+ image.onload = nativeEvent => {
// avoid blocking the main thread
- var onDecode = () => onLoad({
- nativeEvent: e
- });
+ var onDecode = () => {
+ // Append `source` to match RN's ImageLoadEvent interface
+ nativeEvent.source = {
+ uri: image.src,
+ width: image.naturalWidth,
+ height: image.naturalHeight
+ };
+ onLoad({
+ nativeEvent
+ });
+ };
if (typeof image.decode === 'function') {
// Safari currently throws exceptions when decoding svgs.
// We want to catch that error and allow the load handler
@@ -120,6 +128,32 @@ var ImageLoader = {
requests["" + id] = image;
return id;
},
+ loadWithHeaders(source) {
+ var uri;
+ var abortController = new AbortController();
+ var request = new Request(source.uri, {
+ headers: source.headers,
+ signal: abortController.signal
+ });
+ request.headers.append('accept', 'image/*');
+ var promise = fetch(request).then(response => response.blob()).then(blob => {
+ uri = URL.createObjectURL(blob);
+ return uri;
+ }).catch(error => {
+ if (error.name === 'AbortError') {
+ return '';
+ }
+ throw error;
+ });
+ return {
+ promise,
+ source,
+ cancel: () => {
+ abortController.abort();
+ URL.revokeObjectURL(uri);
+ }
+ };
+ },
prefetch(uri) {
return new Promise((resolve, reject) => {
ImageLoader.load(uri, () => {
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,7 @@ const CONST = {
USER: 'user',
},
AUTO_REPORTING_FREQUENCIES: {
INSTANT: 'instant',
IMMEDIATE: 'immediate',
WEEKLY: 'weekly',
SEMI_MONTHLY: 'semimonthly',
Expand Down
14 changes: 8 additions & 6 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ const ONYXKEYS = {
// Max width supported for HTML <canvas> element
MAX_CANVAS_WIDTH: 'maxCanvasWidth',

// Stores the recently used report fields
RECENTLY_USED_REPORT_FIELDS: 'recentlyUsedReportFields',

/** Indicates whether an forced upgrade is required */
UPDATE_REQUIRED: 'updateRequired',

Expand All @@ -260,7 +263,6 @@ const ONYXKEYS = {
POLICY_TAX_RATE: 'policyTaxRates_',
POLICY_RECENTLY_USED_TAGS: 'policyRecentlyUsedTags_',
POLICY_REPORT_FIELDS: 'policyReportFields_',
POLICY_RECENTLY_USED_REPORT_FIELDS: 'policyRecentlyUsedReportFields_',
WORKSPACE_INVITE_MEMBERS_DRAFT: 'workspaceInviteMembersDraft_',
WORKSPACE_INVITE_MESSAGE_DRAFT: 'workspaceInviteMessageDraft_',
REPORT: 'report_',
Expand Down Expand Up @@ -357,8 +359,8 @@ const ONYXKEYS = {
REPORT_VIRTUAL_CARD_FRAUD_DRAFT: 'reportVirtualCardFraudFormDraft',
GET_PHYSICAL_CARD_FORM: 'getPhysicalCardForm',
GET_PHYSICAL_CARD_FORM_DRAFT: 'getPhysicalCardFormDraft',
POLICY_REPORT_FIELD_EDIT_FORM: 'policyReportFieldEditForm',
POLICY_REPORT_FIELD_EDIT_FORM_DRAFT: 'policyReportFieldEditFormDraft',
REPORT_FIELD_EDIT_FORM: 'reportFieldEditForm',
REPORT_FIELD_EDIT_FORM_DRAFT: 'reportFieldEditFormDraft',
REIMBURSEMENT_ACCOUNT_FORM: 'reimbursementAccount',
REIMBURSEMENT_ACCOUNT_FORM_DRAFT: 'reimbursementAccountDraft',
PERSONAL_BANK_ACCOUNT: 'personalBankAccountForm',
Expand Down Expand Up @@ -447,6 +449,7 @@ type OnyxValues = {
[ONYXKEYS.MAX_CANVAS_AREA]: number;
[ONYXKEYS.MAX_CANVAS_HEIGHT]: number;
[ONYXKEYS.MAX_CANVAS_WIDTH]: number;
[ONYXKEYS.RECENTLY_USED_REPORT_FIELDS]: OnyxTypes.RecentlyUsedReportFields;
[ONYXKEYS.UPDATE_REQUIRED]: boolean;

// Collections
Expand All @@ -459,7 +462,6 @@ type OnyxValues = {
[ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS]: OnyxTypes.PolicyMember;
[ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories;
[ONYXKEYS.COLLECTION.POLICY_REPORT_FIELDS]: OnyxTypes.PolicyReportFields;
[ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_REPORT_FIELDS]: OnyxTypes.RecentlyUsedReportFields;
[ONYXKEYS.COLLECTION.DEPRECATED_POLICY_MEMBER_LIST]: OnyxTypes.PolicyMembers;
[ONYXKEYS.COLLECTION.WORKSPACE_INVITE_MEMBERS_DRAFT]: Record<string, number>;
[ONYXKEYS.COLLECTION.REPORT]: OnyxTypes.Report;
Expand Down Expand Up @@ -544,8 +546,8 @@ type OnyxValues = {
[ONYXKEYS.FORMS.REPORT_PHYSICAL_CARD_FORM_DRAFT]: OnyxTypes.Form;
[ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.GET_PHYSICAL_CARD_FORM_DRAFT]: OnyxTypes.Form;
[ONYXKEYS.FORMS.POLICY_REPORT_FIELD_EDIT_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.POLICY_REPORT_FIELD_EDIT_FORM_DRAFT]: OnyxTypes.Form;
[ONYXKEYS.FORMS.REPORT_FIELD_EDIT_FORM]: OnyxTypes.ReportFieldEditForm;
[ONYXKEYS.FORMS.REPORT_FIELD_EDIT_FORM_DRAFT]: OnyxTypes.Form;
// @ts-expect-error Different values are defined under the same key: ReimbursementAccount and ReimbursementAccountForm
[ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM]: OnyxTypes.Form;
[ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT]: OnyxTypes.ReimbursementAccountFormDraft;
Expand Down
Loading

0 comments on commit 3b288fb

Please sign in to comment.