Skip to content

Commit

Permalink
Merge pull request #8871 from Expensify/OSBotify-cherry-pick-staging-…
Browse files Browse the repository at this point in the history
…8827

🍒 Cherry pick PR #8827 to staging 🍒
  • Loading branch information
sketchydroide authored May 6, 2022
2 parents 307c338 + 11debb2 commit 9248a50
Show file tree
Hide file tree
Showing 153 changed files with 3,305 additions and 1,777 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ Please follow these steps to propose a job:
3. If you cannot reproduce the problem, pause on this step and add a comment to the issue explaining where you are stuck or that you don't think the issue can be reproduced.

#### Propose a solution for the job
4. After you reproduce the issue, make a proposal for your solution and post it as a comment in the corresponding GitHub issue (linked in the Upwork job). Your solution proposal should include a brief technical explanation of the changes you will make.
4. After you reproduce the issue, make a proposal for your solution and post it as a comment in the corresponding GitHub issue (linked in the Upwork job). Your solution proposal should include a brief technical explanation of the changes you will make. Include "Proposal" as the first word in your comment.
- Note: Issues that have not had the `External` label applied have not yet been approved for implementation. This means, if you propose a solution to an issue without the `External` label (which you are allowed to do) it is possible that the issue will be fixed internally. If the `External` label has not yet been applied, Expensify has the right to use your proposal to fix said issue, without providing compensation for your solution. This process covers the very rare instance where we need or want to fix an issue internally.
- Note: Before submitting a proposal on an issue, be sure to read any other existing proposals. Any new proposal should be substantively different from existing proposals.
5. Pause at this step until someone from the Contributor-Plus team and / or someone from Expensify provides feedback on your proposal (do not create a pull request yet).
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ This is a persistent storage solution wrapped in a Pub/Sub library. In general t
- Collections of data are usually not stored as a single key (eg. an array with multiple objects), but as individual keys+ID (eg. `report_1234`, `report_4567`, etc.). Store collections as individual keys when a component will bind directly to one of those keys. For example: reports are stored as individual keys because `OptionRow.js` binds to the individual report keys for each link. However, report actions are stored as an array of objects because nothing binds directly to a single report action.
- Onyx allows other code to subscribe to changes in data, and then publishes change events whenever data is changed
- Anything needing to read Onyx data needs to:
1. Know what key the data is stored in (for web, you can find this by looking in the JS console > Application > local storage)
1. Know what key the data is stored in (for web, you can find this by looking in the JS console > Application > IndexedDB > OnyxDB > keyvaluepairs)
2. Subscribe to changes of the data for a particular key or set of keys. React components use `withOnyx()` and non-React libs use `Onyx.connect()`.
3. Get initialized with the current value of that key from persistent storage (Onyx does this by calling `setState()` or triggering the `callback` with the values currently on disk as part of the connection process)
- Subscribing to Onyx keys is done using a constant defined in `ONYXKEYS`. Each Onyx key represents either a collection of items or a specific entry in storage. For example, since all reports are stored as individual keys like `report_1234`, if code needs to know about all the reports (eg. display a list of them in the nav menu), then it would subscribe to the key `ONYXKEYS.COLLECTION.REPORT`.
Expand Down Expand Up @@ -160,7 +160,7 @@ That action will then call `Onyx.merge()` to [set default data and a loading sta
```js
function signIn(password, twoFactorAuthCode) {
Onyx.merge(ONYXKEYS.ACCOUNT, {loading: true});
API.Authenticate({
Authentication.Authenticate({
...defaultParams,
password,
twoFactorAuthCode,
Expand Down
19 changes: 16 additions & 3 deletions __mocks__/@react-native-community/netinfo.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
export default {
const defaultState = {
type: 'cellular',
isConnected: true,
isInternetReachable: true,
details: {
isConnectionExpensive: true,
cellularGeneration: '3g',
},
};

const RNCNetInfoMock = {
configure: () => {},
fetch: () => {},
addEventListener: () => {},
fetch: () => Promise.resolve(defaultState),
refresh: () => Promise.resolve(defaultState),
addEventListener: () => (() => {}),
useNetInfo: () => {},
};

export default RNCNetInfoMock;
5 changes: 2 additions & 3 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,10 @@ dependencies {
implementation jscFlavor
}

// Firebase libraries (using the Firebase BoM for consistency - see https://firebase.google.com/docs/android/learn-more#bom)
implementation platform("com.google.firebase:firebase-bom:29.0.3")
implementation "com.google.firebase:firebase-perf"
implementation "com.google.firebase:firebase-crashlytics"

// GIF support
implementation 'com.facebook.fresco:fresco:2.5.0'
Expand All @@ -252,9 +254,6 @@ dependencies {
// Multi Dex Support: https://developer.android.com/studio/build/multidex#mdex-gradle
implementation 'com.android.support:multidex:1.0.3'

// Crashlytics
implementation 'com.google.firebase:firebase-crashlytics:17.2.2'

// Plaid SDK
implementation project(':react-native-plaid-link-sdk')
// This okhttp3 dependency prevents the app from crashing - See https://github.com/plaid/react-native-plaid-link-sdk/issues/74#issuecomment-648435002
Expand Down
12 changes: 12 additions & 0 deletions assets/images/connect.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 10 additions & 5 deletions package-lock.json

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

15 changes: 9 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@
"scripts": {
"postinstall": "scripts/react-native-web.sh && cd desktop && npm install",
"clean": "react-native clean-project-auto",
"android": "npm run check-metro-bundler-port && react-native run-android",
"ios": "npm run check-metro-bundler-port && react-native run-ios",
"android": "npm run check-metro-bundler-port && scripts/set-pusher-suffix.sh && react-native run-android",
"ios": "npm run check-metro-bundler-port && scripts/set-pusher-suffix.sh && react-native run-ios",
"ipad": "npm run check-metro-bundler-port && react-native run-ios --simulator=\"iPad Pro (12.9-inch) (4th generation)\"",
"ipad-sm": "npm run check-metro-bundler-port && react-native run-ios --simulator=\"iPad Pro (9.7-inch)\"",
"start": "react-native start",
"web": "node web/proxy.js & webpack-dev-server --open --config config/webpack/webpack.dev.js",
"web": "scripts/set-pusher-suffix.sh && concurrently npm:web-proxy npm:web-server",
"web-proxy": "node web/proxy.js",
"web-server": "webpack-dev-server --open --config config/webpack/webpack.dev.js",
"build": "webpack --config config/webpack/webpack.common.js --env.envFile=.env.production",
"build-staging": "webpack --config config/webpack/webpack.common.js --env.envFile=.env.staging",
"desktop": "node desktop/start.js",
"desktop": "scripts/set-pusher-suffix.sh && node desktop/start.js",
"desktop-build": "scripts/build-desktop.sh production",
"desktop-build-staging": "scripts/build-desktop.sh staging",
"ios-build": "fastlane ios build",
Expand All @@ -39,10 +41,11 @@
"@formatjs/intl-pluralrules": "^4.0.13",
"@onfido/react-native-sdk": "^2.2.0",
"@react-native-async-storage/async-storage": "^1.15.5",
"@react-native-community/cameraroll": "^4.1.2",
"@react-native-community/cli": "6.2.0",
"@react-native-community/clipboard": "^1.5.1",
"@react-native-community/datetimepicker": "^3.5.2",
"@react-native-community/netinfo": "^8.0.0",
"@react-native-community/netinfo": "^8.3.0",
"@react-native-community/progress-bar-android": "^1.0.4",
"@react-native-community/progress-view": "^1.2.3",
"@react-native-firebase/analytics": "^12.3.0",
Expand Down Expand Up @@ -88,7 +91,7 @@
"react-native-image-size": "^1.1.3",
"react-native-keyboard-spacer": "^0.4.1",
"react-native-modal": "^13.0.0",
"react-native-onyx": "git+https://github.com/Expensify/react-native-onyx.git#2d42566779884bb445aa59dd48b5bcdff6c0a4e6",
"react-native-onyx": "git+https://github.com/Expensify/react-native-onyx.git#7ab6aed5ce9158f7017ee1c9fd8b5d725d57db73",
"react-native-pdf": "^6.2.2",
"react-native-performance": "^2.0.0",
"react-native-permissions": "^3.0.1",
Expand Down
24 changes: 24 additions & 0 deletions scripts/set-pusher-suffix.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash
# a script that sets Pusher room suffix (for internal usage)

# config file to be parsed for the suffix (relative to current project root)
CONFIG_FILE="../Web-Expensify/_config.local.php"

# use the suffix only when the config file can be found
if [ -f "$CONFIG_FILE" ]; then
echo "Using PUSHER_DEV_SUFFIX from $CONFIG_FILE"

PATTERN="PUSHER_DEV_SUFFIX.*'(.+)'"
while read -r line; do
if [[ $line =~ $PATTERN ]]; then
PUSHER_DEV_SUFFIX=${BASH_REMATCH[1]}
echo "Found suffix: $PUSHER_DEV_SUFFIX"
echo "Updating .env"

# delete any old suffix value and append the new one
sed -i '' '/^PUSHER_DEV_SUFFIX/d' '.env' || true
# a dash '-' is prepended to separate the suffix from trailing channel IDs (accountID, reportID, etc).
echo "PUSHER_DEV_SUFFIX=-${PUSHER_DEV_SUFFIX}" >> .env
fi
done < "$CONFIG_FILE"
fi
1 change: 1 addition & 0 deletions src/CONFIG.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export default {
IS_USING_LOCAL_WEB: useNgrok || expensifyURLRoot.includes('dev'),
PUSHER: {
APP_KEY: lodashGet(Config, 'PUSHER_APP_KEY', '268df511a204fbb60884'),
SUFFIX: lodashGet(Config, 'PUSHER_DEV_SUFFIX', ''),
CLUSTER: 'mt1',
},
SITE_TITLE: 'New Expensify',
Expand Down
21 changes: 17 additions & 4 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ const CONST = {
PENDING: 'PENDING',
},
MAX_LENGTH: {
TAX_ID_NUMBER: 9,
SSN: 4,
ZIP_CODE: 5,
},
Expand All @@ -111,7 +110,6 @@ const CONST = {
IOU_SEND: 'sendMoney',
POLICY_ROOMS: 'policyRooms',
POLICY_EXPENSE_CHAT: 'policyExpenseChat',
MONTHLY_SETTLEMENTS: 'monthlySettlements',
},
BUTTON_STATES: {
DEFAULT: 'default',
Expand Down Expand Up @@ -315,10 +313,10 @@ const CONST = {
SUCCESS: 200,
NOT_AUTHENTICATED: 407,
EXP_ERROR: 666,
UNABLE_TO_RETRY: 'unableToRetry',
},
ERROR: {
XHR_FAILED: 'xhrFailed',
API_OFFLINE: 'session.offlineMessageRetry',
UNKNOWN_ERROR: 'Unknown error',
REQUEST_CANCELLED: 'AbortError',
FAILED_TO_FETCH: 'Failed to fetch',
Expand Down Expand Up @@ -401,12 +399,25 @@ const CONST = {
},

ATTACHMENT_SOURCE_ATTRIBUTE: 'data-expensify-source',
ATTACHMENT_PREVIEW_ATTRIBUTE: 'src',
ATTACHMENT_ORIGINAL_FILENAME_ATTRIBUTE: 'data-name',

ATTACHMENT_PICKER_TYPE: {
FILE: 'file',
IMAGE: 'image',
},

ATTACHMENT_FILE_TYPE: {
FILE: 'file',
IMAGE: 'image',
VIDEO: 'video',
},

FILE_TYPE_REGEX: {
IMAGE: /\.(jpg|jpeg|png|webp|avif|gif|tiff|wbmp|ico|jng|bmp|heic|svg|svg2)$/,
VIDEO: /\.(3gp|h261|h263|h264|m4s|jpgv|jpm|jpgm|mp4|mp4v|mpg4|mpeg|mpg|ogv|ogg|mov|qt|webm|flv|mkv|wmv|wav|avi|movie|f4v|avchd|mp2|mpe|mpv|m4v|swf)$/,
},
IOS_CAMERAROLL_ACCESS_ERROR: 'Access to photo library was denied',
ADD_PAYMENT_MENU_POSITION_Y: 226,
ADD_PAYMENT_MENU_POSITION_X: 356,
EMOJI_PICKER_SIZE: {
Expand Down Expand Up @@ -632,14 +643,16 @@ const CONST = {
CARD_SECURITY_CODE: /^[0-9]{3,4}$/,
CARD_EXPIRATION_DATE: /^(0[1-9]|1[0-2])([^0-9])?([0-9]{4}|([0-9]{2}))$/,
PAYPAL_ME_USERNAME: /^[a-zA-Z0-9]+$/,
RATE_VALUE: /^\d+(\.\d*)?$/,
RATE_VALUE: /^\d{1,8}(\.\d*)?$/,

// Adapted from: https://gist.github.com/dperini/729294
// eslint-disable-next-line max-len
HYPERLINK: /^(?:(?:(?:https?|ftp):\/\/)?)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i,

// eslint-disable-next-line max-len, no-misleading-character-class
EMOJIS: /(?:\uD83D(?:\uDC41\u200D\uD83D\uDDE8|\uDC68\u200D\uD83D[\uDC68\uDC69]\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?)|\uDC69\u200D\uD83D\uDC69\u200D\uD83D(?:\uDC66(?:\u200D\uD83D\uDC66)?|\uDC67(?:\u200D\uD83D[\uDC66\uDC67])?))|[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c\ude32-\ude3a]|[\ud83c\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])/g,
TAX_ID: /^\d{9}$/,
NON_NUMERIC: /\D/g,
},

PRONOUNS: {
Expand Down
3 changes: 3 additions & 0 deletions src/ONYXKEYS.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,9 @@ export default {
// Is report data loading?
IS_LOADING_REPORT_DATA: 'isLoadingReportData',

// Is policy data loading?
IS_LOADING_POLICY_DATA: 'isLoadingPolicyData',

// Are we loading the create policy room command
IS_LOADING_CREATE_POLICY_ROOM: 'isLoadingCratePolicyRoom',

Expand Down
25 changes: 15 additions & 10 deletions src/components/AddressSearch.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import _ from 'underscore';
import React, {useRef, useState} from 'react';
import React, {useState} from 'react';
import PropTypes from 'prop-types';
import {LogBox, ScrollView, View} from 'react-native';
import {GooglePlacesAutocomplete} from 'react-native-google-places-autocomplete';
Expand Down Expand Up @@ -37,12 +37,18 @@ const propTypes = {
/** Error text to display */
errorText: PropTypes.string,

/** Hint text to display */
hint: PropTypes.string,

/** The label to display for the field */
label: PropTypes.string.isRequired,

/** The value to set the field to initially */
value: PropTypes.string,

/** The value to set the field to initially */
defaultValue: PropTypes.string,

/** A callback function when the value of this field has changed */
onInputChange: PropTypes.func.isRequired,

Expand All @@ -58,7 +64,9 @@ const defaultProps = {
shouldSaveDraft: false,
onBlur: () => {},
errorText: '',
hint: '',
value: undefined,
defaultValue: undefined,
containerStyles: [],
};

Expand All @@ -68,11 +76,6 @@ const defaultProps = {
const AddressSearch = (props) => {
const [displayListViewBorder, setDisplayListViewBorder] = useState(false);

// We use `skippedFirstOnChangeTextRef` to work around a feature of the library:
// The library is calling onChangeText with '' at the start and we don't need this
// https://github.com/FaridSafi/react-native-google-places-autocomplete/blob/47d7223dd48f85da97e80a0729a985bbbcee353f/GooglePlacesAutocomplete.js#L148
const skippedFirstOnChangeTextRef = useRef(false);

const saveLocationDetails = (details) => {
const addressComponents = details.address_components;
if (!addressComponents) {
Expand Down Expand Up @@ -168,17 +171,19 @@ const AddressSearch = (props) => {
label: props.label,
containerStyles: props.containerStyles,
errorText: props.errorText,
hint: props.hint,
value: props.value,
defaultValue: props.defaultValue,
isFormInput: props.isFormInput,
inputID: props.inputID,
shouldSaveDraft: props.shouldSaveDraft,
onBlur: props.onBlur,
autoComplete: 'off',
onChangeText: (text) => {
if (skippedFirstOnChangeTextRef.current) {
props.onInputChange({street: text});
onInputChange: (text) => {
if (props.isFormInput) {
props.onInputChange(text);
} else {
skippedFirstOnChangeTextRef.current = true;
props.onInputChange({street: text});
}

// If the text is empty, we set displayListViewBorder to false to prevent UI flickering
Expand Down
Loading

0 comments on commit 9248a50

Please sign in to comment.