Skip to content

Commit 9510cff

Browse files
committed
Merge branch 'main' into df/19631
2 parents 88ad19b + c4ef02b commit 9510cff

File tree

423 files changed

+5353
-4364
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

423 files changed

+5353
-4364
lines changed

.env.example

+17
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,20 @@ USE_WEB_PROXY=false
1111
USE_WDYR=false
1212
CAPTURE_METRICS=false
1313
ONYX_METRICS=false
14+
15+
EXPENSIFY_ACCOUNT_ID_ACCOUNTING=-1
16+
EXPENSIFY_ACCOUNT_ID_ADMIN=-1
17+
EXPENSIFY_ACCOUNT_ID_BILLS=-1
18+
EXPENSIFY_ACCOUNT_ID_CHRONOS=-1
19+
EXPENSIFY_ACCOUNT_ID_CONCIERGE=-1
20+
EXPENSIFY_ACCOUNT_ID_CONTRIBUTORS=-1
21+
EXPENSIFY_ACCOUNT_ID_FIRST_RESPONDER=-1
22+
EXPENSIFY_ACCOUNT_ID_HELP=-1
23+
EXPENSIFY_ACCOUNT_ID_INTEGRATION_TESTING_CREDS=-1
24+
EXPENSIFY_ACCOUNT_ID_PAYROLL=-1
25+
EXPENSIFY_ACCOUNT_ID_QA=-1
26+
EXPENSIFY_ACCOUNT_ID_QA_TRAVIS=-1
27+
EXPENSIFY_ACCOUNT_ID_RECEIPTS=-1
28+
EXPENSIFY_ACCOUNT_ID_REWARDS=-1
29+
EXPENSIFY_ACCOUNT_ID_STUDENT_AMBASSADOR=-1
30+
EXPENSIFY_ACCOUNT_ID_SVFG=-1

.github/workflows/platformDeploy.yml

-7
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,7 @@ jobs:
157157
ruby-version: '2.7'
158158
bundler-cache: true
159159

160-
- uses: actions/cache@v3
161-
id: cache-pods
162-
with:
163-
path: ios/Pods
164-
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
165-
166160
- name: Install cocoapods
167-
if: steps.cache-pods.outputs.cache-hit != 'true'
168161
uses: nick-invision/retry@0711ba3d7808574133d713a0d92d2941be03a350
169162
with:
170163
timeout_minutes: 10

.github/workflows/testBuild.yml

-7
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,7 @@ jobs:
140140
ruby-version: '2.7'
141141
bundler-cache: true
142142

143-
- uses: actions/cache@v3
144-
id: cache-pods
145-
with:
146-
path: ios/Pods
147-
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
148-
149143
- name: Install cocoapods
150-
if: steps.cache-pods.outputs.cache-hit != 'true'
151144
uses: nick-invision/retry@0711ba3d7808574133d713a0d92d2941be03a350
152145
with:
153146
timeout_minutes: 10

__mocks__/react-native-safe-area-context.js

+11-9
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@ const insets = {
99
};
1010

1111
function withSafeAreaInsets(WrappedComponent) {
12-
const WithSafeAreaInsets = (props) => (
13-
<WrappedComponent
14-
// eslint-disable-next-line react/jsx-props-no-spreading
15-
{...props}
16-
// eslint-disable-next-line react/prop-types
17-
ref={props.forwardedRef}
18-
insets={insets}
19-
/>
20-
);
12+
function WithSafeAreaInsets(props) {
13+
return (
14+
<WrappedComponent
15+
// eslint-disable-next-line react/jsx-props-no-spreading
16+
{...props}
17+
// eslint-disable-next-line react/prop-types
18+
ref={props.forwardedRef}
19+
insets={insets}
20+
/>
21+
);
22+
}
2123
return forwardRef((props, ref) => (
2224
<WithSafeAreaInsets
2325
// eslint-disable-next-line react/jsx-props-no-spreading

android/app/build.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ android {
106106
minSdkVersion rootProject.ext.minSdkVersion
107107
targetSdkVersion rootProject.ext.targetSdkVersion
108108
multiDexEnabled rootProject.ext.multiDexEnabled
109-
versionCode 1001032706
110-
versionName "1.3.27-6"
109+
versionCode 1001032805
110+
versionName "1.3.28-5"
111111
}
112112

113113
splits {

contributingGuides/FORMS.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,10 @@ Here's an example for a form that has two inputs, `routingNumber` and `accountNu
114114
function validate(values) {
115115
const errors = {};
116116
if (!values.routingNumber) {
117-
errors.routingNumber = props.translate(CONST.ERRORS.ROUTING_NUMBER);
117+
errors.routingNumber = CONST.ERRORS.ROUTING_NUMBER;
118118
}
119119
if (!values.accountNumber) {
120-
errors.accountNumber = props.translate(CONST.ERRORS.ACCOUNT_NUMBER);
120+
errors.accountNumber = CONST.ERRORS.ACCOUNT_NUMBER;
121121
}
122122
return errors;
123123
}
@@ -130,15 +130,15 @@ function validate(values) {
130130
let errors = {};
131131

132132
if (!ValidationUtils.isValidDisplayName(values.firstName)) {
133-
errors = ErrorUtils.addErrorMessage(errors, 'firstName', props.translate('personalDetails.error.hasInvalidCharacter'));
133+
errors = ErrorUtils.addErrorMessage(errors, 'firstName', 'personalDetails.error.hasInvalidCharacter');
134134
}
135135

136136
if (ValidationUtils.doesContainReservedWord(values.firstName, CONST.DISPLAY_NAME.RESERVED_FIRST_NAMES)) {
137-
errors = ErrorUtils.addErrorMessage(errors, 'firstName', props.translate('personalDetails.error.containsReservedWord'));
137+
errors = ErrorUtils.addErrorMessage(errors, 'firstName', 'personalDetails.error.containsReservedWord');
138138
}
139139

140140
if (!ValidationUtils.isValidDisplayName(values.lastName)) {
141-
errors.lastName = props.translate('personalDetails.error.hasInvalidCharacter');
141+
errors.lastName = 'personalDetails.error.hasInvalidCharacter';
142142
}
143143

144144
return errors;

contributingGuides/NAVIGATION.md

+72-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,72 @@
1-
This is a placeholder for the documentation of how navigation is implemented in the App.
1+
# Overview
2+
3+
The navigation in the App consists of a top-level Stack Navigator (called `RootStack`) with each of its `Screen` components handling different high-level flow. All those flows can be seen in `AuthScreens.js` file.
4+
5+
## Terminology
6+
7+
`RHP` - Right hand panel that shows content inside a dismissible modal that takes up a partial portion of the screen on large format devices e.g. desktop/web/tablets. On smaller screens the content shown in the RHP fills the entire screen.
8+
9+
Navigation Actions - User actions correspond to resulting navigation actions that we will define now. The navigation actions are: `Back`, `Up`, `Dismiss`, `Forward` and `Push`.
10+
11+
- `Back` - Moves the user “back” in the history stack by popping the screen or stack of screens. Note: This can potentially make the user exit the app itself (native) or display a previous app (not Expensify), or just the empty state of the browser.
12+
13+
- `Up` - Pops the current screen off the current stack. This action is very easy to confuse with `Back`. Unless you’ve navigated from one screen to a nested screen in a stack of screens these actions will almost always be the same. Unlike a “back” action, “up” should never result in the user exiting the app and should only be an option if there is somewhere to go “up” to.
14+
15+
- `Dismiss` - Closes any modals (outside the navigation hierarchy) or pops a nested stack of screens off returning the user to the previous screen in the main stack.
16+
17+
- `Forward` - This will take you forward in the history stack. Can only be invoked after you have gone `Back` at least once. Note: Only possible on web.
18+
19+
- `Push` - Either adds a new individual screen to the main stack or a nested stack of screens to the main stack with the user pointed at the last index of the pushed stack.
20+
21+
## Adding RHP flows
22+
23+
Most of the time, if you want to add some of the flows concerning one of your reports, e.g. `Money Request` from a user, you will most probably use `RightModalNavigator.js` and `ModalStackNavigators.js` file:
24+
25+
- Since each of those flows is kind of a modal stack, if you want to add a page to the existing flow, you should just add a page to the correct stack in `ModalStackNavigators.js`.
26+
27+
- If you want to create new flow, add a `Screen` in `RightModalNavigator.js` and make new modal in `ModalStackNavigators.js` with chosen pages.
28+
29+
When creating RHP flows, you have to remember a couple things:
30+
31+
- Since you can deeplink to different pages inside the RHP navigator, it is important to provide the possibility for the user to properly navigate back from any page with UP press (`HeaderWithBackButton` component).
32+
33+
- An example can be deeplinking to `/settings/profile/personal-details`. From there, when pressing the UP button, you should navigate to `/settings/profile`, so in order for it to work, you should provide the correct route in `onBackButtonPress` prop of `HeaderWithBackButton` (`Navigation.goBack(ROUTES.SETTINGS_PROFILE)` in this example).
34+
35+
- We use a custom `goBack` function to handle the browser and the `react-navigation` history stack. Under the hood, it resolves to either replacing the current screen with the one we navigate to (deeplinking scenario) or just going back if we reached the current page by navigating in App (pops the screen). It ensures the requested behaviors on web, which is navigating back to the place from where you deeplinked when going into the RHP flow by it.
36+
37+
- If you want to navigate to a certain report after completing a flow related to it, e.g. `RequestMoney` flow with a certain group/user, you should use `Navigation.dismissModal` with this `reportID` as an argument. If, in the future, we would like to navigate to something different than the report after such flows, the API should be rather easy to change. We do it like that in order to replace the RHP flow with the new report instead of pushing it, so pressing the back button does not navigate back to the ending page of the flow. If we were to navigate to the same report, we just pop the RHP modal.
38+
39+
### Example of usage
40+
41+
An example of adding `Settings_Workspaces` page:
42+
43+
1. Add path to `ROUTES.js`: https://github.com/Expensify/App/blob/3531af22dcadaa94ed11eccf370517dca0b8c305/src/ROUTES.js#L36
44+
45+
2. Add `Settings_Workspaces` page to proper RHP flow in `linkingConfig.js`: https://github.com/Expensify/App/blob/3531af22dcadaa94ed11eccf370517dca0b8c305/src/libs/Navigation/linkingConfig.js#L40-L42
46+
47+
3. Add your page to proper navigator (it should be aligned with where you've put it in the previous step) https://github.com/Expensify/App/blob/3531af22dcadaa94ed11eccf370517dca0b8c305/src/libs/Navigation/AppNavigator/ModalStackNavigators.js#L334-L338
48+
49+
4. Make sure `HeaderWithBackButton` leads to the previous page in navigation flow of your page: https://github.com/Expensify/App/blob/3531af22dcadaa94ed11eccf370517dca0b8c305/src/pages/workspace/WorkspacesListPage.js#L186
50+
51+
## Performance solutions
52+
53+
Using [react-freeze](https://github.com/software-mansion/react-freeze) allows us to increase performance by avoiding unnecessary re-renders of screens that aren’t visible to the user anyway.
54+
55+
- To ensure that the user doesn't ever see frozen report content, we are freezing the screens from 2 levels down the `RootStack` (which contains a `Screen` for each report), so when dismissing with a swipe, the user always sees the content of the previous report.
56+
57+
- We want to freeze as high in the view hierarchy as we can, so we do it in a `Screen` of `RootStack`, being `CentralPaneNavigator` and `SidebarScreen`.
58+
59+
- We want the report content visible as fast as possible, and at the same time we want the navigation animation to trigger instantly. To do so, we do a hack with `firstRenderRef` which renders `ReportActionsSkeletonView` instead of the messages at the first render, and the proper content afterward. It works since there are always more renders of `ReportScreen` before the content shows up (hopefully).
60+
61+
## Handling wide and narrow layouts
62+
63+
- The wide and narrow layouts are conditionally rendered with different components in `createResponsiveNavigator` depending on screen size (`isSmallScreen` prop from the `withWindowDimension.js`).
64+
65+
- The wide layout is rendered with our custom `ThreePaneView.js` and the narrow layout is rendered with `StackView` from `@react-navigation/stack`
66+
67+
- To make sure that we have the correct navigation state after changing the layout we need to force react to create new instance of the `NavigationContainer`. Without this, the navigation state could be broken after changing the type of layout.
68+
69+
- We are getting the new instance by changing the `key` prop of `NavigationContainer` that depends on the `isSmallScreenWidth`.
70+
71+
- To keep the navigation state that was present before changing the layout, we save the state on every change and use it for the `initialState` prop.
72+
Changing the layout means that every component inside `NavigationContainer` is mounted anew.

docs/articles/other/Everything-About-Chat.md

+8-25
Original file line numberDiff line numberDiff line change
@@ -25,35 +25,18 @@ All workspace members are added to the #announce room by default. The #announce
2525
All workspace admins can access the #admins room. Use the #admins room to collaborate with the other admins on your policy, and chat with your dedicated Expensify Onboarding Guide. If you have a subscription of 10 or more users, you're automatically assigned an Account Manager. You can ask for help and collaborate with your Account Manager in this same #admins room. Anytime someone on your team, your dedicated setup specialist, or your dedicated account manager makes any changes to your Workspace settings, that update is logged in the #admins room.
2626
## How to format text
2727

28-
#### Italic
29-
###### To italicize your message, place an underscore on both sides of the text:
30-
*text*
31-
32-
#### Bold
33-
###### To bold your message, place an asterisk on both sides of the text:
34-
**text**
35-
36-
#### Strikethrough
37-
###### To strikethrough your message, place a tilde on both sides of the text:
38-
~text~
39-
40-
#### Quote
41-
###### To turn your text into a blockquote, add a `>` symbol in front of the text:
42-
> your text
43-
44-
#### Code
45-
###### To turn your message into code, place a backtick on both sides of the text:
46-
`text`
47-
48-
#### Codeblock
49-
###### To turn your entire message into code block, place three backticks on both sides of the text:
28+
- To italicize your message, place an underscore on both sides of the text: *text*
29+
- To bold your message, place an asterisk on both sides of the text: **text**
30+
- To strikethrough your message, place a tilde on both sides of the text: ~text~
31+
- To turn your text into a blockquote, add a `>` symbol in front of the text: > your text
32+
- To turn your message into code, place a backtick on both sides of the text: `text`
33+
- To turn your message into a heading, place the `#` symbol in front of the text:
34+
### Heading
35+
- To turn your entire message into code block, place three backticks on both sides of the text:
5036
```
5137
text
5238
and even more text
5339
```
54-
#### Heading
55-
###### To turn your message into a heading, place the `#` symbol in front of the text:
56-
## Heading
5740

5841
# FAQs
5942
## How do I add more than one person to a chat?

ios/NewExpensify/Info.plist

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<key>CFBundlePackageType</key>
2020
<string>APPL</string>
2121
<key>CFBundleShortVersionString</key>
22-
<string>1.3.27</string>
22+
<string>1.3.28</string>
2323
<key>CFBundleSignature</key>
2424
<string>????</string>
2525
<key>CFBundleURLTypes</key>
@@ -32,7 +32,7 @@
3232
</dict>
3333
</array>
3434
<key>CFBundleVersion</key>
35-
<string>1.3.27.6</string>
35+
<string>1.3.28.5</string>
3636
<key>ITSAppUsesNonExemptEncryption</key>
3737
<false/>
3838
<key>LSApplicationQueriesSchemes</key>

ios/NewExpensifyTests/Info.plist

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
<key>CFBundlePackageType</key>
1616
<string>BNDL</string>
1717
<key>CFBundleShortVersionString</key>
18-
<string>1.3.27</string>
18+
<string>1.3.28</string>
1919
<key>CFBundleSignature</key>
2020
<string>????</string>
2121
<key>CFBundleVersion</key>
22-
<string>1.3.27.6</string>
22+
<string>1.3.28.5</string>
2323
</dict>
2424
</plist>

ios/Podfile.lock

+6
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,8 @@ PODS:
662662
- Firebase/Performance (= 8.8.0)
663663
- React-Core
664664
- RNFBApp
665+
- RNFS (2.20.0):
666+
- React-Core
665667
- RNGestureHandler (2.9.0):
666668
- React-Core
667669
- RNLocalize (2.2.6):
@@ -809,6 +811,7 @@ DEPENDENCIES:
809811
- "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
810812
- "RNFBCrashlytics (from `../node_modules/@react-native-firebase/crashlytics`)"
811813
- "RNFBPerf (from `../node_modules/@react-native-firebase/perf`)"
814+
- RNFS (from `../node_modules/react-native-fs`)
812815
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
813816
- RNLocalize (from `../node_modules/react-native-localize`)
814817
- RNPermissions (from `../node_modules/react-native-permissions`)
@@ -999,6 +1002,8 @@ EXTERNAL SOURCES:
9991002
:path: "../node_modules/@react-native-firebase/crashlytics"
10001003
RNFBPerf:
10011004
:path: "../node_modules/@react-native-firebase/perf"
1005+
RNFS:
1006+
:path: "../node_modules/react-native-fs"
10021007
RNGestureHandler:
10031008
:path: "../node_modules/react-native-gesture-handler"
10041009
RNLocalize:
@@ -1120,6 +1125,7 @@ SPEC CHECKSUMS:
11201125
RNFBApp: 729c0666395b1953198dc4a1ec6deb8fbe1c302e
11211126
RNFBCrashlytics: 2061ca863e8e2fa1aae9b12477d7dfa8e88ca0f9
11221127
RNFBPerf: 389914cda4000fe0d996a752532a591132cbf3f9
1128+
RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
11231129
RNGestureHandler: 071d7a9ad81e8b83fe7663b303d132406a7d8f39
11241130
RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81
11251131
RNPermissions: dcdb7b99796bbeda6975a6e79ad519c41b251b1c

jest/setup.js

+6
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,9 @@ jest.spyOn(console, 'debug').mockImplementation((...params) => {
2525
// eslint-disable-next-line no-console
2626
console.log('DEBUG', ...params);
2727
});
28+
29+
// This mock is required for mocking file systems when running tests
30+
jest.mock('react-native-fs', () => ({
31+
unlink: jest.fn(() => new Promise((res) => res())),
32+
CachesDirectoryPath: jest.fn(),
33+
}));

0 commit comments

Comments
 (0)