From 1e8f4c79f2b4ee90cfc2fc678e88427953c34481 Mon Sep 17 00:00:00 2001 From: Srikar Parsi Date: Fri, 14 Oct 2022 03:18:49 -0400 Subject: [PATCH 01/85] added error field to account for change in web e --- src/components/AddPlaidBankAccount.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 3aa31b8e7d31..2e0bfabeb09b 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -63,6 +63,7 @@ const defaultProps = { bankAccounts: [], isLoading: false, error: '', + errors: {}, }, selectedPlaidAccountID: '', plaidLinkToken: '', @@ -123,9 +124,9 @@ class AddPlaidBankAccount extends React.Component { )} - {Boolean(this.props.plaidData.error) && ( + {(Boolean(this.props.plaidData.error) || Boolean(this.props.plaidData.errors)) && ( - {this.props.plaidData.error} + {this.props.plaidData.errors ? Object.values(this.props.plaidData.errors)[0] : this.props.plaidData.error} )} {Boolean(token) && ( From 5abdd47bce88b93d5ba9c4c210b2ed93d0b67fe8 Mon Sep 17 00:00:00 2001 From: Srikar Parsi Date: Mon, 17 Oct 2022 11:02:51 -0400 Subject: [PATCH 02/85] use lodash --- src/components/AddPlaidBankAccount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 2e0bfabeb09b..533cd4505240 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -126,7 +126,7 @@ class AddPlaidBankAccount extends React.Component { )} {(Boolean(this.props.plaidData.error) || Boolean(this.props.plaidData.errors)) && ( - {this.props.plaidData.errors ? Object.values(this.props.plaidData.errors)[0] : this.props.plaidData.error} + {this.props.plaidData.errors ? _.chain(this.props.plaidData.errors).values().first().value() : this.props.plaidData.error} )} {Boolean(token) && ( From 651350c225b02d542c235b1eb432a2520cb7c0cc Mon Sep 17 00:00:00 2001 From: Srikar Parsi Date: Mon, 17 Oct 2022 11:08:14 -0400 Subject: [PATCH 03/85] move to constant --- src/components/AddPlaidBankAccount.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 533cd4505240..070ecbee981e 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -113,6 +113,7 @@ class AddPlaidBankAccount extends React.Component { label: `${account.addressName} ${account.mask}`, })); const {icon, iconSize} = getBankIcon(); + const plaidDataErrorMessage = this.props.plaidData.errors ? _.chain(this.props.plaidData.errors).values().first().value() : this.props.plaidData.error; // Plaid Link view if (!plaidBankAccounts.length) { @@ -126,7 +127,7 @@ class AddPlaidBankAccount extends React.Component { )} {(Boolean(this.props.plaidData.error) || Boolean(this.props.plaidData.errors)) && ( - {this.props.plaidData.errors ? _.chain(this.props.plaidData.errors).values().first().value() : this.props.plaidData.error} + {plaidDataErrorMessage} )} {Boolean(token) && ( From 064167d9dc0acbbb2cd9e15135235e703196b216 Mon Sep 17 00:00:00 2001 From: Srikar Parsi <48188732+srikarparsi@users.noreply.github.com> Date: Mon, 17 Oct 2022 14:27:20 -0400 Subject: [PATCH 04/85] use error message Co-authored-by: Neil Marcellini --- src/components/AddPlaidBankAccount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 070ecbee981e..550dfd479c9e 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -125,7 +125,7 @@ class AddPlaidBankAccount extends React.Component { )} - {(Boolean(this.props.plaidData.error) || Boolean(this.props.plaidData.errors)) && ( + {Boolean(plaidDataErrorMessage) && ( {plaidDataErrorMessage} From 2e25856fb0309a15c03e4fc9bdd36a97e33a97b3 Mon Sep 17 00:00:00 2001 From: Srikar Parsi Date: Mon, 17 Oct 2022 14:31:57 -0400 Subject: [PATCH 05/85] use not empty since {} is true --- src/components/AddPlaidBankAccount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 550dfd479c9e..29d76102b4b6 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -113,7 +113,7 @@ class AddPlaidBankAccount extends React.Component { label: `${account.addressName} ${account.mask}`, })); const {icon, iconSize} = getBankIcon(); - const plaidDataErrorMessage = this.props.plaidData.errors ? _.chain(this.props.plaidData.errors).values().first().value() : this.props.plaidData.error; + const plaidDataErrorMessage = !_.isEmpty(this.props.plaidData.errors) ? _.chain(this.props.plaidData.errors).values().first().value() : this.props.plaidData.error; // Plaid Link view if (!plaidBankAccounts.length) { From aa5310874e376f88056512e414a2a276296e8f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 12:09:35 +0100 Subject: [PATCH 06/85] feat: load custom config --- tests/e2e/config.js | 12 ++++++--- tests/e2e/config.local.js | 4 +++ tests/e2e/testRunner.js | 53 +++++++++++++++++++++------------------ 3 files changed, 41 insertions(+), 28 deletions(-) create mode 100644 tests/e2e/config.local.js diff --git a/tests/e2e/config.js b/tests/e2e/config.js index aad6b742b582..0d2601f2f88b 100644 --- a/tests/e2e/config.js +++ b/tests/e2e/config.js @@ -10,6 +10,15 @@ const TEST_NAMES = { AppStartTime: 'App start time', }; +/** + * Default config, used by CI by default. + * You can modify these values for your test run by creating a + * separate config file and pass it to the test runner like this: + * + * ```bash + * npm run test:e2e -- --config ./path/to/your/config.js + * ``` + */ module.exports = { APP_PACKAGE: 'com.expensify.chat', @@ -21,9 +30,6 @@ module.exports = { DEFAULT_BASELINE_BRANCH: 'main', - // The amount of outliers to remove from a dataset before calculating the average - DROP_WORST: 8, - // The amount of runs that should happen without counting test results WARM_UP_RUNS: 3, diff --git a/tests/e2e/config.local.js b/tests/e2e/config.local.js new file mode 100644 index 000000000000..2e582493e6cf --- /dev/null +++ b/tests/e2e/config.local.js @@ -0,0 +1,4 @@ +module.exports = { + WARM_UP_RUNS: 1, + RUNS: 7, +}; diff --git a/tests/e2e/testRunner.js b/tests/e2e/testRunner.js index a5165db1ac67..ad22d4787432 100644 --- a/tests/e2e/testRunner.js +++ b/tests/e2e/testRunner.js @@ -9,14 +9,7 @@ /* eslint-disable @lwc/lwc/no-async-await,no-restricted-syntax,no-await-in-loop */ const fs = require('fs'); const _ = require('underscore'); -const { - DEFAULT_BASELINE_BRANCH, - OUTPUT_DIR, - LOG_FILE, - RUNS, - WARM_UP_RUNS, - TESTS_CONFIG, -} = require('./config'); +const defaultConfig = require('./config'); const compare = require('./compare/compare'); const Logger = require('./utils/logger'); const execAsync = require('./utils/execAsync'); @@ -30,12 +23,22 @@ const withFailTimeout = require('./utils/withFailTimeout'); const args = process.argv.slice(2); -const baselineBranch = process.env.baseline || DEFAULT_BASELINE_BRANCH; +let config = defaultConfig; +if (args.includes('--config')) { + let configPath = args[args.indexOf('--config') + 1]; + if (!configPath.startsWith('.')) { + configPath = `./${configPath}`; + } + const customConfig = require(configPath); + config = _.extend(defaultConfig, customConfig); +} + +const baselineBranch = process.env.baseline || config.DEFAULT_BASELINE_BRANCH; // Clear all files from previous jobs try { - fs.rmSync(OUTPUT_DIR, {recursive: true, force: true}); - fs.mkdirSync(OUTPUT_DIR); + fs.rmSync(config.OUTPUT_DIR, {recursive: true, force: true}); + fs.mkdirSync(config.OUTPUT_DIR); } catch (error) { // Do nothing console.error(error); @@ -92,14 +95,14 @@ const runTestsOnBranch = async (branch, baselineOrCompare) => { }); // Run the tests - const numOfTests = _.values(TESTS_CONFIG).length; + const numOfTests = _.values(config.TESTS_CONFIG).length; for (let testIndex = 0; testIndex < numOfTests; testIndex++) { - const config = _.values(TESTS_CONFIG)[testIndex]; - server.setTestConfig(config); + const testConfig = _.values(config.TESTS_CONFIG)[testIndex]; + server.setTestConfig(testConfig); - const warmupLogs = Logger.progressInfo(`Running test '${config.name}'`); - for (let warmUpRuns = 0; warmUpRuns < WARM_UP_RUNS; warmUpRuns++) { - const progressText = `(${testIndex + 1}/${numOfTests}) Warmup for test '${config.name}' (iteration ${warmUpRuns + 1}/${WARM_UP_RUNS})`; + const warmupLogs = Logger.progressInfo(`Running test '${testConfig.name}'`); + for (let warmUpRuns = 0; warmUpRuns < config.WARM_UP_RUNS; warmUpRuns++) { + const progressText = `(${testIndex + 1}/${numOfTests}) Warmup for test '${testConfig.name}' (iteration ${warmUpRuns + 1}/${config.WARM_UP_RUNS})`; warmupLogs.updateText(progressText); await restartApp(); @@ -116,8 +119,8 @@ const runTestsOnBranch = async (branch, baselineOrCompare) => { // We run each test multiple time to average out the results const testLog = Logger.progressInfo(''); - for (let i = 0; i < RUNS; i++) { - const progressText = `(${testIndex + 1}/${numOfTests}) Running test '${config.name}' (iteration ${i + 1}/${RUNS})`; + for (let i = 0; i < config.RUNS; i++) { + const progressText = `(${testIndex + 1}/${numOfTests}) Running test '${testConfig.name}' (iteration ${i + 1}/${config.RUNS})`; testLog.updateText(progressText); await restartApp(); @@ -142,7 +145,7 @@ const runTestsOnBranch = async (branch, baselineOrCompare) => { // Calculate statistics and write them to our work file progressLog = Logger.progressInfo('Calculating statics and writing results'); - const outputFileName = `${OUTPUT_DIR}/${baselineOrCompare}.json`; + const outputFileName = `${config.OUTPUT_DIR}/${baselineOrCompare}.json`; for (const testName of _.keys(durationsByTestName)) { const stats = math.getStats(durationsByTestName[testName]); await writeTestStats( @@ -175,12 +178,12 @@ const runTests = async () => { Logger.info('\n\nE2E test suite failed due to error:', e, '\nPrinting full logs:\n\n'); // Write logcat, meminfo, emulator info to file as well: - require('node:child_process').execSync(`adb logcat -d > ${OUTPUT_DIR}/logcat.txt`); - require('node:child_process').execSync(`adb shell "cat /proc/meminfo" > ${OUTPUT_DIR}/meminfo.txt`); - require('node:child_process').execSync(`cat ~/.android/avd/${process.env.AVD_NAME || 'test'}.avd/config.ini > ${OUTPUT_DIR}/emulator-config.ini`); - require('node:child_process').execSync(`adb shell "getprop" > ${OUTPUT_DIR}/emulator-properties.txt`); + require('node:child_process').execSync(`adb logcat -d > ${config.OUTPUT_DIR}/logcat.txt`); + require('node:child_process').execSync(`adb shell "cat /proc/meminfo" > ${config.OUTPUT_DIR}/meminfo.txt`); + require('node:child_process').execSync(`cat ~/.android/avd/${process.env.AVD_NAME || 'test'}.avd/config.ini > ${config.OUTPUT_DIR}/emulator-config.ini`); + require('node:child_process').execSync(`adb shell "getprop" > ${config.OUTPUT_DIR}/emulator-properties.txt`); - require('node:child_process').execSync(`cat ${LOG_FILE}`); + require('node:child_process').execSync(`cat ${config.LOG_FILE}`); process.exit(1); } }; From 0a675065390baa7b36b7f054f7739de00a2536a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 12:20:13 +0100 Subject: [PATCH 07/85] fix gitignore of e2e results --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 768ab38507e3..8265d5fd272b 100644 --- a/.gitignore +++ b/.gitignore @@ -93,4 +93,4 @@ storybook-static .jest-cache # E2E test reports -tests/e2e/.results/ +tests/e2e/results/ From 1f6f516762b9127f0f8412f2a8a602bfc731720a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 12:20:58 +0100 Subject: [PATCH 08/85] fix path of test results --- tests/e2e/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/config.js b/tests/e2e/config.js index 0d2601f2f88b..a194ca672937 100644 --- a/tests/e2e/config.js +++ b/tests/e2e/config.js @@ -1,4 +1,4 @@ -const OUTPUT_DIR = process.env.WORKING_DIRECTORY || './results'; +const OUTPUT_DIR = process.env.WORKING_DIRECTORY || './tests/e2e/results'; /** * @typedef TestConfig From d98e7b7b7ba77fe1454d7911f8c695277e03da2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 12:33:00 +0100 Subject: [PATCH 09/85] make error handling more resilient --- tests/e2e/testRunner.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/e2e/testRunner.js b/tests/e2e/testRunner.js index ad22d4787432..18726367d38a 100644 --- a/tests/e2e/testRunner.js +++ b/tests/e2e/testRunner.js @@ -180,10 +180,14 @@ const runTests = async () => { // Write logcat, meminfo, emulator info to file as well: require('node:child_process').execSync(`adb logcat -d > ${config.OUTPUT_DIR}/logcat.txt`); require('node:child_process').execSync(`adb shell "cat /proc/meminfo" > ${config.OUTPUT_DIR}/meminfo.txt`); - require('node:child_process').execSync(`cat ~/.android/avd/${process.env.AVD_NAME || 'test'}.avd/config.ini > ${config.OUTPUT_DIR}/emulator-config.ini`); require('node:child_process').execSync(`adb shell "getprop" > ${config.OUTPUT_DIR}/emulator-properties.txt`); require('node:child_process').execSync(`cat ${config.LOG_FILE}`); + try { + require('node:child_process').execSync(`cat ~/.android/avd/${process.env.AVD_NAME || 'test'}.avd/config.ini > ${config.OUTPUT_DIR}/emulator-config.ini`); + } catch (__) { + // the file might not exist + } process.exit(1); } }; From f6fd71cb97a22930b1535db146766cbc87ebf109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 13:53:37 +0100 Subject: [PATCH 10/85] fix: running perf regression tests locally --- tests/e2e/config.js | 5 +++++ tests/e2e/config.local.js | 4 ++++ tests/e2e/testRunner.js | 9 ++++++--- tests/e2e/utils/androidReversePort.js | 6 ++++++ tests/e2e/utils/installApp.js | 11 +++-------- 5 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 tests/e2e/utils/androidReversePort.js diff --git a/tests/e2e/config.js b/tests/e2e/config.js index a194ca672937..234ea761c306 100644 --- a/tests/e2e/config.js +++ b/tests/e2e/config.js @@ -22,6 +22,11 @@ const TEST_NAMES = { module.exports = { APP_PACKAGE: 'com.expensify.chat', + APP_PATHS: { + baseline: './app-e2eRelease-baseline.apk', + compare: './app-e2eRelease-compare.apk', + }, + // The port of the testing server that communicates with the app SERVER_PORT: 4723, diff --git a/tests/e2e/config.local.js b/tests/e2e/config.local.js index 2e582493e6cf..d2c0551aac20 100644 --- a/tests/e2e/config.local.js +++ b/tests/e2e/config.local.js @@ -1,4 +1,8 @@ module.exports = { WARM_UP_RUNS: 1, RUNS: 7, + APP_PATHS: { + baseline: './android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk', + compare: './android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk', + }, }; diff --git a/tests/e2e/testRunner.js b/tests/e2e/testRunner.js index 18726367d38a..4d96b751e814 100644 --- a/tests/e2e/testRunner.js +++ b/tests/e2e/testRunner.js @@ -20,6 +20,7 @@ const installApp = require('./utils/installApp'); const math = require('./measure/math'); const writeTestStats = require('./measure/writeTestStats'); const withFailTimeout = require('./utils/withFailTimeout'); +const reversePort = require('./utils/androidReversePort'); const args = process.argv.slice(2); @@ -69,9 +70,11 @@ const runTestsOnBranch = async (branch, baselineOrCompare) => { await execAsync('npm run android-build-e2e'); } - // Install app - let progressLog = Logger.progressInfo('Installing app'); - await installApp('android', baselineOrCompare); + // Install app and reverse port + let progressLog = Logger.progressInfo('Installing app and reversing port'); + const appPath = baselineOrCompare === 'baseline' ? config.APP_PATHS.baseline : config.APP_PATHS.compare; + await installApp('android', appPath); + await reversePort(); progressLog.done(); // Start the HTTP server diff --git a/tests/e2e/utils/androidReversePort.js b/tests/e2e/utils/androidReversePort.js new file mode 100644 index 000000000000..b644ca1538dd --- /dev/null +++ b/tests/e2e/utils/androidReversePort.js @@ -0,0 +1,6 @@ +const {SERVER_PORT} = require('../config'); +const execAsync = require('./execAsync'); + +module.exports = function () { + return execAsync(`adb reverse tcp:${SERVER_PORT} tcp:${SERVER_PORT}`); +}; diff --git a/tests/e2e/utils/installApp.js b/tests/e2e/utils/installApp.js index 32c2f44c9533..48246bb67c5e 100644 --- a/tests/e2e/utils/installApp.js +++ b/tests/e2e/utils/installApp.js @@ -2,27 +2,22 @@ const {APP_PACKAGE} = require('../config'); const execAsync = require('./execAsync'); const Logger = require('./logger'); -const BASELINE_APP_PATH_FROM_ROOT = './app-e2eRelease-baseline.apk'; -const COMPARE_APP_PATH_FROM_ROOT = './app-e2eRelease-compare.apk'; - /** * Installs the app on the currently connected device for the given platform. * It removes the app first if it already exists, so it's a clean installation. * * @param {String} platform - * @param {String} baselineOrCompare + * @param {String} path * @returns {Promise} */ -module.exports = function (platform = 'android', baselineOrCompare = 'baseline') { +module.exports = function (platform = 'android', path) { if (platform !== 'android') { throw new Error(`installApp() missing implementation for platform: ${platform}`); } - const apk = baselineOrCompare === 'baseline' ? BASELINE_APP_PATH_FROM_ROOT : COMPARE_APP_PATH_FROM_ROOT; - // Uninstall first, then install return execAsync(`adb uninstall ${APP_PACKAGE}`).catch((e) => { // Ignore errors Logger.warn('Failed to uninstall app:', e); - }).finally(() => execAsync(`adb install ${apk}`)); + }).finally(() => execAsync(`adb install ${path}`)); }; From 95fa715aae9dc94a3815b5733b4ec1544fcf9566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 14:11:15 +0100 Subject: [PATCH 11/85] fix: results not calculated correctly due to runs not devidable by 4 --- tests/e2e/config.local.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/config.local.js b/tests/e2e/config.local.js index d2c0551aac20..cd0b04d7c3cf 100644 --- a/tests/e2e/config.local.js +++ b/tests/e2e/config.local.js @@ -1,6 +1,6 @@ module.exports = { WARM_UP_RUNS: 1, - RUNS: 7, + RUNS: 8, APP_PATHS: { baseline: './android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk', compare: './android/app/build/outputs/apk/e2eRelease/app-e2eRelease.apk', From 759b14438a9e13d5808ce9660ea749c93c9313ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 14:15:29 +0100 Subject: [PATCH 12/85] feat: add option to filter tests to run by --includes flag --- tests/e2e/testRunner.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/e2e/testRunner.js b/tests/e2e/testRunner.js index 4d96b751e814..f81601ac3130 100644 --- a/tests/e2e/testRunner.js +++ b/tests/e2e/testRunner.js @@ -101,6 +101,18 @@ const runTestsOnBranch = async (branch, baselineOrCompare) => { const numOfTests = _.values(config.TESTS_CONFIG).length; for (let testIndex = 0; testIndex < numOfTests; testIndex++) { const testConfig = _.values(config.TESTS_CONFIG)[testIndex]; + + // check if we want to skip the text + if (args.includes('--includes')) { + const includes = args[args.indexOf('--includes') + 1]; + + // assume that "includes" is a regexp + if (!testConfig.name.match(includes)) { + // eslint-disable-next-line no-continue + continue; + } + } + server.setTestConfig(testConfig); const warmupLogs = Logger.progressInfo(`Running test '${testConfig.name}'`); From f33026e7f8ca4a908345e37043826c0dfb545e9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 14:18:28 +0100 Subject: [PATCH 13/85] doc: CLI options --- package.json | 2 +- tests/e2e/README.md | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index f8441f2b8156..ea3726d0abb5 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.js --env envFile=.env.production", "symbolicate:android": "npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map", "symbolicate:ios": "npx metro-symbolicate main.jsbundle.map", - "test:e2e": "node tests/e2e/testRunner.js" + "test:e2e": "node tests/e2e/testRunner.js --config config.local.js" }, "dependencies": { "@expensify/react-native-web": "0.18.9", diff --git a/tests/e2e/README.md b/tests/e2e/README.md index be45d677bae7..3f221aafad25 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -17,6 +17,15 @@ To run the e2e tests: Ideally you want to run these tests on your branch before you want to merge your new feature to `main`. +## Available CLI options + +The tests can be run with the following CLI options: + +- `--config`: Extend/Overwrite the default config with your values, e.g. `--config config.local.js` +- `--includes`: Expects a string/regexp to filter the tests to run, e.g. `--includes "login|signup"` +- `--skipInstallDeps`: Skips the `npm install` step, useful during development +- `--skipBuild`: Skips to build the android app, useful during development + ## Performance regression testing The output of the tests is a set of performance metrics (see video above). From 55bdf10a23a9b250a0c569cfd95e279dd003de77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 14:32:43 +0100 Subject: [PATCH 14/85] doc: env var options --- tests/e2e/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 3f221aafad25..89be6d57a567 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -26,6 +26,12 @@ The tests can be run with the following CLI options: - `--skipInstallDeps`: Skips the `npm install` step, useful during development - `--skipBuild`: Skips to build the android app, useful during development +## Available environment variables + +The tests can be run with the following environment variables: + +- `baseline`: Change the baseline to run the tests again (default is `main`). + ## Performance regression testing The output of the tests is a set of performance metrics (see video above). From 5d5d1d5924a61f32fc6f9f06f50066660d7d71ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 17:27:06 +0100 Subject: [PATCH 15/85] add script for repackaging e2e release app --- .../android-repackage-app-bundle-and-sign.sh | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100755 scripts/android-repackage-app-bundle-and-sign.sh diff --git a/scripts/android-repackage-app-bundle-and-sign.sh b/scripts/android-repackage-app-bundle-and-sign.sh new file mode 100755 index 000000000000..c40e25e5ae46 --- /dev/null +++ b/scripts/android-repackage-app-bundle-and-sign.sh @@ -0,0 +1,105 @@ +#!/bin/sh + +### +# Takes an android app that has been built with the debug keystore, +# and re-packages it with an alternative JS bundle to run. +# It then signs the APK again, so you can simply install the app on a device. +# This is useful if you quickly want to test changes to the JS code with a +# release app, without having to rebuild the whole app. +# +# There are many outdated resources on how to re-sign an app. The main +# flow and commands have been taken from: +# - https://gist.github.com/floyd-fuh/7f7408b560672ece3ea78348559d47b6#file-repackage_apk_for_burp-py-L276-L319 +# +# This script uses `apktool` instead of manually unzipping and zipping the app. +# Only with apktool it worked without any errors, so you need to install it. +### + +BUILD_TOOLS=$ANDROID_SDK_ROOT/build-tools/31.0.0 +APK=$1 +NEW_BUNDLE_FILE=$2 + +### Helper function to use echo but print text in bold +function echo_bold() { + echo "\033[1m$@\033[0m" +} + +### Validating inputs + +if [ -z "$APK" ]; then + echo "Usage: $0 " + exit 1 +fi +if [ -z "$NEW_BUNDLE_FILE" ]; then + echo "Usage: $0 " + exit 1 +fi +APK=$(realpath $APK) +if [ ! -f "$APK" ]; then + echo "APK not found: $APK" + exit 1 +fi +NEW_BUNDLE_FILE=$(realpath $NEW_BUNDLE_FILE) +if [ ! -f "$NEW_BUNDLE_FILE" ]; then + echo "Bundle file not found: $NEW_BUNDLE_FILE" + exit 1 +fi +# check if "apktool" command is available +if ! command -v apktool &> /dev/null +then + echo "apktool could not be found. Please install it." + exit 1 +fi +# check if "jarsigner" command is available +if ! command -v jarsigner &> /dev/null +then + echo "jarsigner could not be found. Please install it." + exit 1 +fi + +KEYSTORE="$(realpath ./android/app/debug.keystore)" +ORIGINAL_WD=$(pwd) + +### Copy apk to a temp dir + +TMP_DIR=$(mktemp -d) +cp "$APK" "$TMP_DIR" +cd "$TMP_DIR" + +### Dissemble app + +echo_bold "Dissembling app..." +apktool d "$APK" -o app > /dev/null + +### Copy new bundle into assets + +echo_bold "Copying new bundle into assets..." +rm app/assets/index.android.bundle +cp "$NEW_BUNDLE_FILE" app/assets/index.android.bundle + +### Reassemble app + +echo_bold "Reassembling app..." +apktool b app -o app.apk > /dev/null + +### Do jarsigner + +echo_bold "Signing app..." +jarsigner -verbose -keystore $KEYSTORE -storepass android -keypass android app.apk androiddebugkey + +### Do zipalign + +echo_bold "Zipaligning app..." +$BUILD_TOOLS/zipalign -p -v 4 app.apk app-aligned.apk + +### Do apksigner + +echo_bold "Signing app with apksigner..." +$BUILD_TOOLS/apksigner sign --v4-signing-enabled true --ks $KEYSTORE --ks-pass pass:android --ks-key-alias androiddebugkey --key-pass pass:android app-aligned.apk + +### Copy back to original location + +echo_bold "Copying back to original location..." +cp app-aligned.apk "$ORIGINAL_WD/app-repacked-signed.apk" +echo "Done. Repacked app is at $ORIGINAL_WD/app-repacked-signed.apk" + From 17e44854040ed8b288cc7218e7fd75127df575b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Wed, 30 Nov 2022 18:16:22 +0100 Subject: [PATCH 16/85] feat: add `buildMode` option Now you can either rebuild the native app fully, skip it entirely, or just rebundle the JS bundle --- .../android-repackage-app-bundle-and-sign.sh | 16 +++---- tests/e2e/README.md | 7 ++- tests/e2e/config.js | 2 + tests/e2e/testRunner.js | 43 ++++++++++++++++--- 4 files changed, 53 insertions(+), 15 deletions(-) diff --git a/scripts/android-repackage-app-bundle-and-sign.sh b/scripts/android-repackage-app-bundle-and-sign.sh index c40e25e5ae46..ad675c24fbac 100755 --- a/scripts/android-repackage-app-bundle-and-sign.sh +++ b/scripts/android-repackage-app-bundle-and-sign.sh @@ -18,6 +18,7 @@ BUILD_TOOLS=$ANDROID_SDK_ROOT/build-tools/31.0.0 APK=$1 NEW_BUNDLE_FILE=$2 +OUTPUT_APK=$3 ### Helper function to use echo but print text in bold function echo_bold() { @@ -26,12 +27,8 @@ function echo_bold() { ### Validating inputs -if [ -z "$APK" ]; then - echo "Usage: $0 " - exit 1 -fi -if [ -z "$NEW_BUNDLE_FILE" ]; then - echo "Usage: $0 " +if [ -z "$APK" ] || [ -z "$NEW_BUNDLE_FILE" ] || [ -z "$OUTPUT_APK" ]; then + echo "Usage: $0 " exit 1 fi APK=$(realpath $APK) @@ -44,6 +41,7 @@ if [ ! -f "$NEW_BUNDLE_FILE" ]; then echo "Bundle file not found: $NEW_BUNDLE_FILE" exit 1 fi +OUTPUT_APK=$(realpath $OUTPUT_APK) # check if "apktool" command is available if ! command -v apktool &> /dev/null then @@ -100,6 +98,8 @@ $BUILD_TOOLS/apksigner sign --v4-signing-enabled true --ks $KEYSTORE --ks-pass ### Copy back to original location echo_bold "Copying back to original location..." -cp app-aligned.apk "$ORIGINAL_WD/app-repacked-signed.apk" -echo "Done. Repacked app is at $ORIGINAL_WD/app-repacked-signed.apk" +cp app-aligned.apk "$OUTPUT_APK" +echo "Done. Repacked app is at $OUTPUT_APK" +rm -rf "$TMP_DIR" +cd "$ORIGINAL_WD" diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 89be6d57a567..904642856f01 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -24,7 +24,12 @@ The tests can be run with the following CLI options: - `--config`: Extend/Overwrite the default config with your values, e.g. `--config config.local.js` - `--includes`: Expects a string/regexp to filter the tests to run, e.g. `--includes "login|signup"` - `--skipInstallDeps`: Skips the `npm install` step, useful during development -- `--skipBuild`: Skips to build the android app, useful during development +- `--buildMode`: There are three build modes, the default is `full`: + 1. **full**: rebuilds the full native app in (e2e) release mode + 2. **js-only**: only rebuilds the js bundle, and then re-packages + the existing native app with the new package. If there + is no existing native app, it will fallback to mode "full" + 3. **skip**: does not rebuild anything, and just runs the existing native app ## Available environment variables diff --git a/tests/e2e/config.js b/tests/e2e/config.js index 234ea761c306..34f81467866d 100644 --- a/tests/e2e/config.js +++ b/tests/e2e/config.js @@ -27,6 +27,8 @@ module.exports = { compare: './app-e2eRelease-compare.apk', }, + ENTRY_FILE: 'src/libs/E2E/reactNativeLaunchingTest.js', + // The port of the testing server that communicates with the app SERVER_PORT: 4723, diff --git a/tests/e2e/testRunner.js b/tests/e2e/testRunner.js index f81601ac3130..6209d9ac6223 100644 --- a/tests/e2e/testRunner.js +++ b/tests/e2e/testRunner.js @@ -53,11 +53,30 @@ const restartApp = async () => { }; const runTestsOnBranch = async (branch, baselineOrCompare) => { - if (!args.includes('--skipInstallDeps') && !args.includes('--skipBuild')) { - // Switch branch and install dependencies - Logger.log(`Preparing ${baselineOrCompare} tests on branch '${branch}'`); - await execAsync(`git checkout ${branch}`); + // There are three build modes: + // 1. full: rebuilds the full native app in (e2e) release mode + // 2. js-only: only rebuilds the js bundle, and then re-packages + // the existing native app with the new package. If there + // is no existing native app, it will fallback to mode "full" + // 3. skip: does not rebuild anything, and just runs the existing native app + let buildMode = 'full'; + if (args.includes('--buildMode')) { + buildMode = args[args.indexOf('--buildMode') + 1]; } + let appPath = baselineOrCompare === 'baseline' ? config.APP_PATHS.baseline : config.APP_PATHS.compare; + + // check if using buildMode "js-only" or "none" is possible + if (buildMode !== 'full') { + const appExists = fs.existsSync(appPath); + if (!appExists) { + Logger.warn(`Build mode "${buildMode}" is not possible, because the app does not exist. Falling back to build mode "full".`); + buildMode = 'full'; + } + } + + // Switch branch + Logger.log(`Preparing ${baselineOrCompare} tests on branch '${branch}'`); + await execAsync(`git checkout ${branch}`); if (!args.includes('--skipInstallDeps')) { Logger.log(`Preparing ${baselineOrCompare} tests on branch '${branch}' - npm install`); @@ -65,14 +84,26 @@ const runTestsOnBranch = async (branch, baselineOrCompare) => { } // Build app - if (!args.includes('--skipBuild')) { + if (buildMode === 'full') { Logger.log(`Preparing ${baselineOrCompare} tests on branch '${branch}' - building app`); await execAsync('npm run android-build-e2e'); + } else if (buildMode === 'js-only') { + Logger.log(`Preparing ${baselineOrCompare} tests on branch '${branch}' - building js bundle`); + + // Build a new JS bundle + const tempDir = `${config.OUTPUT_DIR}/temp`; + const tempBundlePath = `${tempDir}/index.android.bundle`; + await execAsync(`rm -rf ${tempDir} && mkdir ${tempDir}`); + await execAsync(`npx react-native bundle --platform android --dev false --entry-file ${config.ENTRY_FILE} --bundle-output ${tempBundlePath}`); + + // Repackage the existing native app with the new bundle + const tempApkPath = `${tempDir}/app-release.apk`; + await execAsync(`./scripts/android-repackage-app-bundle-and-sign.sh ${appPath} ${tempBundlePath} ${tempApkPath}`); + appPath = tempApkPath; } // Install app and reverse port let progressLog = Logger.progressInfo('Installing app and reversing port'); - const appPath = baselineOrCompare === 'baseline' ? config.APP_PATHS.baseline : config.APP_PATHS.compare; await installApp('android', appPath); await reversePort(); progressLog.done(); From 706967e41f04141c2dabcab0e5fb4f46fc611063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Thu, 1 Dec 2022 08:31:47 +0100 Subject: [PATCH 17/85] add tip notice on how to run tests faster --- tests/e2e/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 904642856f01..e4a1b01db961 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -14,6 +14,10 @@ To run the e2e tests: 2. Make sure Fastlane was initialized by running `bundle install` 3. Run the tests with `npm run test:e2e`. + > šŸ’” Tip: To run the tests locally faster, and you are only making changes to JS, it's recommended to + build the app once with `npm run android-build-e2e` and from then on run the tests with + `npm run test:e2e -- --buildMode js-only`. This will only rebuild the JS code, and not the + whole native app! Ideally you want to run these tests on your branch before you want to merge your new feature to `main`. From 8dc5ab51d6134f5ad7df4dfb5e4d08c89244b9de Mon Sep 17 00:00:00 2001 From: Stefan Nemeth Date: Wed, 7 Dec 2022 03:52:43 +0100 Subject: [PATCH 18/85] Convert notification avatar to software bitmap for Android --- .../chat/customairshipextender/CustomNotificationProvider.java | 3 +++ 1 file changed, 3 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 deeff81bf76d..b144fe2b08af 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 @@ -90,6 +90,9 @@ protected NotificationCompat.Builder onExtendBuilder(@NonNull Context context, @ * @param bitmap The bitmap image to modify. */ public Bitmap getCroppedBitmap(Bitmap bitmap) { + // Convert hardware bitmap to software bitmap so it can be drawn on the canvas + bitmap = bitmap.copy(Config.ARGB_8888, true); + Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(output); From a0c5a6b67cebb6ae264563c3872faec74fce218c Mon Sep 17 00:00:00 2001 From: miroslav Date: Mon, 12 Dec 2022 17:57:05 +0100 Subject: [PATCH 19/85] fix composer hidden while loading messages --- src/components/DragAndDrop/index.js | 17 +++++++++++++++++ src/pages/home/ReportScreen.js | 12 ++++++++---- src/pages/home/report/ReportActionCompose.js | 18 +++++++++++------- src/pages/home/report/ReportFooter.js | 16 ++++++++++++---- 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/components/DragAndDrop/index.js b/src/components/DragAndDrop/index.js index b35c43126c98..48ec86732064 100644 --- a/src/components/DragAndDrop/index.js +++ b/src/components/DragAndDrop/index.js @@ -17,6 +17,9 @@ const propTypes = { /** Guard for accepting drops in drop zone. Drag event is passed to this function as first parameter. This prop is necessary to be inlined to satisfy the linter */ shouldAcceptDrop: PropTypes.func, + /** Whether drag & drop should be disabled */ + disabled: PropTypes.bool, + /** Rendered child component */ children: PropTypes.node.isRequired, }; @@ -33,12 +36,18 @@ const defaultProps = { } return false; }, + disabled: false, }; export default class DragAndDrop extends React.Component { constructor(props) { super(props); + if (props.disabled) { + this.isDisabled = true; + return; + } + this.throttledDragOverHandler = _.throttle(this.dragOverHandler.bind(this), 100); this.throttledDragNDropWindowResizeListener = _.throttle(this.dragNDropWindowResizeListener.bind(this), 100); this.dropZoneDragHandler = this.dropZoneDragHandler.bind(this); @@ -52,6 +61,10 @@ export default class DragAndDrop extends React.Component { } componentDidMount() { + if (this.isDisabled) { + return; + } + this.dropZone = document.getElementById(this.props.dropZoneId); this.dropZoneRect = this.calculateDropZoneClientReact(); document.addEventListener('dragover', this.dropZoneDragListener); @@ -62,6 +75,10 @@ export default class DragAndDrop extends React.Component { } componentWillUnmount() { + if (this.isDisabled) { + return; + } + document.removeEventListener('dragover', this.dropZoneDragListener); document.removeEventListener('dragenter', this.dropZoneDragListener); document.removeEventListener('dragleave', this.dropZoneDragListener); diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index eb55a8996e08..5b665c525b38 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -236,7 +236,10 @@ class ReportScreen extends React.Component { placeholder={( <> - + + + + )} > @@ -312,9 +315,10 @@ class ReportScreen extends React.Component { {/* Note: The report should be allowed to mount even if the initial report actions are not loaded. If we prevent rendering the report while they are loading then we'll unnecessarily unmount the ReportActionsView which will clear the new marker lines initial state. */} {(!this.isReportReadyForDisplay() || isLoadingInitialReportActions) && ( - + <> + + + )} diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index 7811d1c25ee1..9fdae9d5bd1f 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -88,7 +88,10 @@ const propTypes = { isFocused: PropTypes.bool.isRequired, /** Is the composer full size */ - isComposerFullSize: PropTypes.bool.isRequired, + isComposerFullSize: PropTypes.bool, + + /** Whether user interactions should be disabled */ + disabled: PropTypes.bool, // The NVP describing a user's block status blockedFromConcierge: PropTypes.shape({ @@ -572,7 +575,7 @@ class ReportActionCompose extends React.Component { onMouseDown={e => e.preventDefault()} style={styles.composerSizeButton} underlayColor={themeColors.componentBG} - disabled={isBlockedFromConcierge} + disabled={isBlockedFromConcierge || this.props.disabled} > @@ -591,7 +594,7 @@ class ReportActionCompose extends React.Component { onMouseDown={e => e.preventDefault()} style={styles.composerSizeButton} underlayColor={themeColors.componentBG} - disabled={isBlockedFromConcierge} + disabled={isBlockedFromConcierge || this.props.disabled} > @@ -609,7 +612,7 @@ class ReportActionCompose extends React.Component { }} style={styles.chatItemAttachButton} underlayColor={themeColors.componentBG} - disabled={isBlockedFromConcierge} + disabled={isBlockedFromConcierge || this.props.disabled} > @@ -655,6 +658,7 @@ class ReportActionCompose extends React.Component { this.setState({isDraggingOver: false}); }} + disabled={this.props.disabled} > this.setTextInputShouldClear(false)} - isDisabled={isComposeDisabled || isBlockedFromConcierge} + isDisabled={isComposeDisabled || isBlockedFromConcierge || this.props.disabled} selection={this.state.selection} onSelectionChange={this.onSelectionChange} isFullComposerAvailable={this.state.isFullComposerAvailable} @@ -687,7 +691,7 @@ class ReportActionCompose extends React.Component { {canUseTouchScreen() && this.props.isMediumScreenWidth ? null : ( this.focus(true)} onEmojiSelected={this.addEmojiToTextBox} /> @@ -704,7 +708,7 @@ class ReportActionCompose extends React.Component { // Keep focus on the composer when Send message is clicked. // eslint-disable-next-line react/jsx-props-no-multi-spaces onMouseDown={e => e.preventDefault()} - disabled={this.state.isCommentEmpty || isBlockedFromConcierge || hasExceededMaxCommentLength} + disabled={this.state.isCommentEmpty || isBlockedFromConcierge || this.props.disabled || hasExceededMaxCommentLength} hitSlop={{ top: 3, right: 3, bottom: 3, left: 3, }} diff --git a/src/pages/home/report/ReportFooter.js b/src/pages/home/report/ReportFooter.js index 7c3a4191b390..3aa2feff5f80 100644 --- a/src/pages/home/report/ReportFooter.js +++ b/src/pages/home/report/ReportFooter.js @@ -21,16 +21,16 @@ import reportPropTypes from '../../reportPropTypes'; const propTypes = { /** Report object for the current report */ - report: reportPropTypes.isRequired, + report: reportPropTypes, /** Report actions for the current report */ - reportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)).isRequired, + reportActions: PropTypes.objectOf(PropTypes.shape(reportActionPropTypes)), /** Offline status */ isOffline: PropTypes.bool.isRequired, /** Callback fired when the comment is submitted */ - onSubmitComment: PropTypes.func.isRequired, + onSubmitComment: PropTypes.func, /** Any errors associated with an attempt to create a chat */ // eslint-disable-next-line react/forbid-prop-types @@ -42,13 +42,20 @@ const propTypes = { /** Whether the composer input should be shown */ shouldShowComposeInput: PropTypes.bool, + /** Whether user interactions should be disabled */ + shouldDisableCompose: PropTypes.bool, + ...windowDimensionsPropTypes, }; const defaultProps = { - shouldShowComposeInput: true, + report: {reportID: '0'}, + reportActions: {}, + onSubmitComment: () => {}, errors: {}, pendingAction: null, + shouldShowComposeInput: true, + shouldDisableCompose: false, }; class ReportFooter extends React.Component { @@ -99,6 +106,7 @@ class ReportFooter extends React.Component { reportActions={this.props.reportActions} report={this.props.report} isComposerFullSize={this.props.isComposerFullSize} + disabled={this.props.shouldDisableCompose} /> From 62828283260e159005efceb7ab7a3afd2d6be69d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Mon, 12 Dec 2022 19:54:08 +0100 Subject: [PATCH 20/85] add `--development` flag --- package.json | 2 +- tests/e2e/testRunner.js | 39 ++++++++++++++++++------- tests/e2e/utils/getCurrentBranchName.js | 10 +++++++ tests/e2e/utils/logger.js | 7 +++++ 4 files changed, 47 insertions(+), 11 deletions(-) create mode 100644 tests/e2e/utils/getCurrentBranchName.js diff --git a/package.json b/package.json index 785a4ac90508..e542ba4722b5 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.js --env envFile=.env.production", "symbolicate:android": "npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map", "symbolicate:ios": "npx metro-symbolicate main.jsbundle.map", - "test:e2e": "node tests/e2e/testRunner.js --config config.local.js" + "test:e2e": "node tests/e2e/testRunner.js --development" }, "dependencies": { "@expensify/react-native-web": "0.18.9", diff --git a/tests/e2e/testRunner.js b/tests/e2e/testRunner.js index 6209d9ac6223..10ea1eeb25c9 100644 --- a/tests/e2e/testRunner.js +++ b/tests/e2e/testRunner.js @@ -21,20 +21,42 @@ const math = require('./measure/math'); const writeTestStats = require('./measure/writeTestStats'); const withFailTimeout = require('./utils/withFailTimeout'); const reversePort = require('./utils/androidReversePort'); +const getCurrentBranchName = require('./utils/getCurrentBranchName'); const args = process.argv.slice(2); let config = defaultConfig; -if (args.includes('--config')) { - let configPath = args[args.indexOf('--config') + 1]; +const setConfigPath = (configPathParam) => { + let configPath = configPathParam; if (!configPath.startsWith('.')) { configPath = `./${configPath}`; } const customConfig = require(configPath); config = _.extend(defaultConfig, customConfig); +}; + +let baselineBranch = process.env.baseline || config.DEFAULT_BASELINE_BRANCH; + +// There are three build modes: +// 1. full: rebuilds the full native app in (e2e) release mode +// 2. js-only: only rebuilds the js bundle, and then re-packages +// the existing native app with the new package. If there +// is no existing native app, it will fallback to mode "full" +// 3. skip: does not rebuild anything, and just runs the existing native app +let buildMode = 'full'; + +// When we are in dev mode we want to apply certain default params and configs +const isDevMode = args.includes('--development'); +if (isDevMode) { + setConfigPath('config.local.js'); + baselineBranch = getCurrentBranchName(); + buildMode = 'js-only'; } -const baselineBranch = process.env.baseline || config.DEFAULT_BASELINE_BRANCH; +if (args.includes('--config')) { + const configPath = args[args.indexOf('--config') + 1]; + setConfigPath(configPath); +} // Clear all files from previous jobs try { @@ -45,6 +67,10 @@ try { console.error(error); } +if (isDevMode) { + Logger.note(`Running in development mode. Set baseline branch to same as current ${baselineBranch}`); +} + const restartApp = async () => { Logger.log('Killing app ā€¦'); await killApp('android'); @@ -53,13 +79,6 @@ const restartApp = async () => { }; const runTestsOnBranch = async (branch, baselineOrCompare) => { - // There are three build modes: - // 1. full: rebuilds the full native app in (e2e) release mode - // 2. js-only: only rebuilds the js bundle, and then re-packages - // the existing native app with the new package. If there - // is no existing native app, it will fallback to mode "full" - // 3. skip: does not rebuild anything, and just runs the existing native app - let buildMode = 'full'; if (args.includes('--buildMode')) { buildMode = args[args.indexOf('--buildMode') + 1]; } diff --git a/tests/e2e/utils/getCurrentBranchName.js b/tests/e2e/utils/getCurrentBranchName.js new file mode 100644 index 000000000000..3380bd23ef15 --- /dev/null +++ b/tests/e2e/utils/getCurrentBranchName.js @@ -0,0 +1,10 @@ +const {execSync} = require('node:child_process'); + +const getCurrentBranchName = () => { + const stdout = execSync('git rev-parse --abbrev-ref HEAD', { + encoding: 'utf8', + }); + return stdout.trim(); +}; + +module.exports = getCurrentBranchName; diff --git a/tests/e2e/utils/logger.js b/tests/e2e/utils/logger.js index a12fecd1efad..aa198aec3004 100644 --- a/tests/e2e/utils/logger.js +++ b/tests/e2e/utils/logger.js @@ -71,10 +71,17 @@ const warn = (...args) => { log(...lines); }; +const note = (...args) => { + const lines = [`\nšŸ’”${COLOR_DIM}`, ...args, `${COLOR_RESET}\n`]; + console.debug(...lines); + log(...lines); +}; + module.exports = { log, info, warn, + note, progressInfo, setLogLevelVerbose, }; From 818013e2a5d8fa49bf2cb1d54382642b0d41fc0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Mon, 12 Dec 2022 20:02:00 +0100 Subject: [PATCH 21/85] add docs --- tests/e2e/ADDING_TESTS.md | 6 ++++++ tests/e2e/README.md | 3 +++ 2 files changed, 9 insertions(+) diff --git a/tests/e2e/ADDING_TESTS.md b/tests/e2e/ADDING_TESTS.md index 43deeaf2f0b1..39cdb97ebed0 100644 --- a/tests/e2e/ADDING_TESTS.md +++ b/tests/e2e/ADDING_TESTS.md @@ -94,3 +94,9 @@ test file: Done! When you now start the test runner, your new test will be executed as well. +## Quickly test your test + +To check your new test you can simply run `npm run test:e2e`, which uses the +`--development` flag. This will run the tests on the branch you are currently on +and will do fewer iterations. + diff --git a/tests/e2e/README.md b/tests/e2e/README.md index e4a1b01db961..3262770bc55f 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -28,6 +28,9 @@ The tests can be run with the following CLI options: - `--config`: Extend/Overwrite the default config with your values, e.g. `--config config.local.js` - `--includes`: Expects a string/regexp to filter the tests to run, e.g. `--includes "login|signup"` - `--skipInstallDeps`: Skips the `npm install` step, useful during development +- `--development`: Applies some default configurations: + - Sets the config to `config.local.js`, which executes the tests with fewer iterations + - Runs the tests only on the current branch - `--buildMode`: There are three build modes, the default is `full`: 1. **full**: rebuilds the full native app in (e2e) release mode 2. **js-only**: only rebuilds the js bundle, and then re-packages From 9c6b0bfe191de37ee4aabf6f78cd6423e3d62e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Thu, 15 Dec 2022 18:16:41 +0100 Subject: [PATCH 22/85] fix script linting, use bash --- .../android-repackage-app-bundle-and-sign.sh | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/android-repackage-app-bundle-and-sign.sh b/scripts/android-repackage-app-bundle-and-sign.sh index ad675c24fbac..2a8a065252f1 100755 --- a/scripts/android-repackage-app-bundle-and-sign.sh +++ b/scripts/android-repackage-app-bundle-and-sign.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash ### # Takes an android app that has been built with the debug keystore, @@ -21,8 +21,8 @@ NEW_BUNDLE_FILE=$2 OUTPUT_APK=$3 ### Helper function to use echo but print text in bold -function echo_bold() { - echo "\033[1m$@\033[0m" +echo_bold() { + echo -e "\033[1m$@\033[0m" } ### Validating inputs @@ -31,17 +31,17 @@ if [ -z "$APK" ] || [ -z "$NEW_BUNDLE_FILE" ] || [ -z "$OUTPUT_APK" ]; then echo "Usage: $0 " exit 1 fi -APK=$(realpath $APK) +APK=$(realpath "$APK") if [ ! -f "$APK" ]; then echo "APK not found: $APK" exit 1 fi -NEW_BUNDLE_FILE=$(realpath $NEW_BUNDLE_FILE) +NEW_BUNDLE_FILE=$(realpath "$NEW_BUNDLE_FILE") if [ ! -f "$NEW_BUNDLE_FILE" ]; then echo "Bundle file not found: $NEW_BUNDLE_FILE" exit 1 fi -OUTPUT_APK=$(realpath $OUTPUT_APK) +OUTPUT_APK=$(realpath "$OUTPUT_APK") # check if "apktool" command is available if ! command -v apktool &> /dev/null then @@ -62,7 +62,7 @@ ORIGINAL_WD=$(pwd) TMP_DIR=$(mktemp -d) cp "$APK" "$TMP_DIR" -cd "$TMP_DIR" +cd "$TMP_DIR" || exit ### Dissemble app @@ -83,17 +83,17 @@ apktool b app -o app.apk > /dev/null ### Do jarsigner echo_bold "Signing app..." -jarsigner -verbose -keystore $KEYSTORE -storepass android -keypass android app.apk androiddebugkey +jarsigner -verbose -keystore "$KEYSTORE" -storepass android -keypass android app.apk androiddebugkey ### Do zipalign echo_bold "Zipaligning app..." -$BUILD_TOOLS/zipalign -p -v 4 app.apk app-aligned.apk +"$BUILD_TOOLS"/zipalign -p -v 4 app.apk app-aligned.apk ### Do apksigner echo_bold "Signing app with apksigner..." -$BUILD_TOOLS/apksigner sign --v4-signing-enabled true --ks $KEYSTORE --ks-pass pass:android --ks-key-alias androiddebugkey --key-pass pass:android app-aligned.apk +"$BUILD_TOOLS"/apksigner sign --v4-signing-enabled true --ks "$KEYSTORE" --ks-pass pass:android --ks-key-alias androiddebugkey --key-pass pass:android app-aligned.apk ### Copy back to original location @@ -101,5 +101,5 @@ echo_bold "Copying back to original location..." cp app-aligned.apk "$OUTPUT_APK" echo "Done. Repacked app is at $OUTPUT_APK" rm -rf "$TMP_DIR" -cd "$ORIGINAL_WD" +cd "$ORIGINAL_WD" || exit From b22716df269a1a5c5e8970d5a5f1a2eec30e39d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Thu, 15 Dec 2022 18:21:42 +0100 Subject: [PATCH 23/85] fix script linting --- scripts/android-repackage-app-bundle-and-sign.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/android-repackage-app-bundle-and-sign.sh b/scripts/android-repackage-app-bundle-and-sign.sh index 2a8a065252f1..fe4ee1e4b8fc 100755 --- a/scripts/android-repackage-app-bundle-and-sign.sh +++ b/scripts/android-repackage-app-bundle-and-sign.sh @@ -22,7 +22,7 @@ OUTPUT_APK=$3 ### Helper function to use echo but print text in bold echo_bold() { - echo -e "\033[1m$@\033[0m" + echo -e "\033[1m$*\033[0m" } ### Validating inputs From 1f7b20416da3908696764d44d005e4a07d179476 Mon Sep 17 00:00:00 2001 From: staszekscp Date: Tue, 20 Dec 2022 12:17:09 +0100 Subject: [PATCH 24/85] add label check: --- .github/workflows/testBuild.yml | 41 ++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index 98b75f7da3de..03aa1744c9e3 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -7,8 +7,8 @@ on: description: Pull Request number for correct placement of apps required: true pull_request_target: - types: [opened, synchronize] - branches: ['*ci-test/**'] + types: [opened, synchronize, labeled] + branches: ['main'] env: DEVELOPER_DIR: /Applications/Xcode_14.0.1.app/Contents/Developer @@ -24,12 +24,27 @@ jobs: with: GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} username: ${{ github.actor }} - team: mobile-deployers + team: expensify-expensify - getBranchRef: + validateLabel: runs-on: ubuntu-latest needs: validateActor - if: ${{ fromJSON(needs.validateActor.outputs.IS_TEAM_MEMBER) }} + outputs: + CAN_BE_BUILD: ${{steps.canBeBuild.outputs.CAN_BE_BUILD}} + steps: + - name: Remove label + if: ${{ !fromJSON(needs.validateActor.outputs.IS_TEAM_MEMBER) && github.event.label.name == 'Ready To Build'}} + uses: actions-ecosystem/action-remove-labels@v1 + with: + labels: 'Ready To Build' + - id: canBeBuild + if: ${{ fromJSON(needs.validateActor.outputs.IS_TEAM_MEMBER) || contains(github.event.pull_request.labels.*.name, 'Ready To Build') }} + run: echo "CAN_BE_BUILD=true" >> "$GITHUB_OUTPUT" + + getBranchRef: + runs-on: ubuntu-latest + needs: validateLabel + if: ${{ needs.validateLabel.outputs.CAN_BE_BUILD }} outputs: REF: ${{steps.getHeadRef.outputs.REF}} steps: @@ -48,8 +63,8 @@ jobs: android: name: Build and deploy Android for testing - needs: [validateActor, getBranchRef] - if: ${{ fromJSON(needs.validateActor.outputs.IS_TEAM_MEMBER) }} + needs: [validateLabel, getBranchRef] + if: ${{ needs.validateLabel.outputs.CAN_BE_BUILD }} runs-on: ubuntu-latest env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} @@ -98,8 +113,8 @@ jobs: iOS: name: Build and deploy iOS for testing - needs: [validateActor, getBranchRef] - if: ${{ fromJSON(needs.validateActor.outputs.IS_TEAM_MEMBER) }} + needs: [validateLabel, getBranchRef] + if: ${{ needs.validateLabel.outputs.CAN_BE_BUILD }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: macos-12 @@ -154,8 +169,8 @@ jobs: desktop: name: Build and deploy Desktop for testing - needs: [validateActor, getBranchRef] - if: ${{ fromJSON(needs.validateActor.outputs.IS_TEAM_MEMBER) }} + needs: [validateLabel, getBranchRef] + if: ${{ needs.validateLabel.outputs.CAN_BE_BUILD }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: macos-12 @@ -191,8 +206,8 @@ jobs: web: name: Build and deploy Web - needs: [validateActor, getBranchRef] - if: ${{ fromJSON(needs.validateActor.outputs.IS_TEAM_MEMBER) }} + needs: [validateLabel, getBranchRef] + if: ${{ needs.validateLabel.outputs.CAN_BE_BUILD }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: ubuntu-latest From c9372cec7ddfb641a6327077ac055f5e080c3a24 Mon Sep 17 00:00:00 2001 From: staszekscp Date: Tue, 20 Dec 2022 14:25:22 +0100 Subject: [PATCH 25/85] improve workflow --- .github/workflows/testBuild.yml | 44 ++++++++++++++++----------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index 03aa1744c9e3..cc7886e36d56 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -17,34 +17,32 @@ jobs: validateActor: runs-on: ubuntu-latest outputs: - IS_TEAM_MEMBER: ${{ fromJSON(steps.isUserDeployer.outputs.isTeamMember) }} + CAN_BE_BUILD: ${{steps.canBeBuild.outputs.CAN_BE_BUILD}} steps: - - id: isUserDeployer + - id: isUserTeamMember uses: tspascoal/get-user-teams-membership@baf2e6adf4c3b897bd65a7e3184305c165aec872 with: GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} username: ${{ github.actor }} team: expensify-expensify - - validateLabel: - runs-on: ubuntu-latest - needs: validateActor - outputs: - CAN_BE_BUILD: ${{steps.canBeBuild.outputs.CAN_BE_BUILD}} - steps: - - name: Remove label - if: ${{ !fromJSON(needs.validateActor.outputs.IS_TEAM_MEMBER) && github.event.label.name == 'Ready To Build'}} + - name: Remove label if it was added by an unauthorized user + if: ${{ !fromJSON(steps.isUserTeamMember.outputs.isTeamMember) && github.event.label.name == 'Ready To Build' }} uses: actions-ecosystem/action-remove-labels@v1 with: labels: 'Ready To Build' + - name: Throw exception if label was added by an unauthorized user + if: ${{ !fromJSON(steps.isUserTeamMember.outputs.isTeamMember) && github.event.label.name == 'Ready To Build' }} + run: | + echo "The 'Ready To Build' label was added by an unauthorized user" + exit 1 - id: canBeBuild - if: ${{ fromJSON(needs.validateActor.outputs.IS_TEAM_MEMBER) || contains(github.event.pull_request.labels.*.name, 'Ready To Build') }} - run: echo "CAN_BE_BUILD=true" >> "$GITHUB_OUTPUT" + name: Set CAN_BE_BUILD flag + run: echo "CAN_BE_BUILD=${{ fromJSON(steps.isUserTeamMember.outputs.isTeamMember) || contains(github.event.pull_request.labels.*.name, 'Ready To Build') }}" >> "$GITHUB_OUTPUT" getBranchRef: runs-on: ubuntu-latest - needs: validateLabel - if: ${{ needs.validateLabel.outputs.CAN_BE_BUILD }} + needs: validateActor + if: ${{ needs.validateActor.outputs.CAN_BE_BUILD == 'true' }} outputs: REF: ${{steps.getHeadRef.outputs.REF}} steps: @@ -63,8 +61,8 @@ jobs: android: name: Build and deploy Android for testing - needs: [validateLabel, getBranchRef] - if: ${{ needs.validateLabel.outputs.CAN_BE_BUILD }} + needs: [validateActor, getBranchRef] + if: ${{ needs.validateActor.outputs.CAN_BE_BUILD == 'true' }} runs-on: ubuntu-latest env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} @@ -113,8 +111,8 @@ jobs: iOS: name: Build and deploy iOS for testing - needs: [validateLabel, getBranchRef] - if: ${{ needs.validateLabel.outputs.CAN_BE_BUILD }} + needs: [validateActor, getBranchRef] + if: ${{ needs.validateActor.outputs.CAN_BE_BUILD == 'true' }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: macos-12 @@ -169,8 +167,8 @@ jobs: desktop: name: Build and deploy Desktop for testing - needs: [validateLabel, getBranchRef] - if: ${{ needs.validateLabel.outputs.CAN_BE_BUILD }} + needs: [validateActor, getBranchRef] + if: ${{ needs.validateActor.outputs.CAN_BE_BUILD == 'true' }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: macos-12 @@ -206,8 +204,8 @@ jobs: web: name: Build and deploy Web - needs: [validateLabel, getBranchRef] - if: ${{ needs.validateLabel.outputs.CAN_BE_BUILD }} + needs: [validateActor, getBranchRef] + if: ${{ needs.validateActor.outputs.CAN_BE_BUILD == 'true' }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: ubuntu-latest From 21c7299f3a47a745c2ca7f08be2101bd947662f3 Mon Sep 17 00:00:00 2001 From: staszekscp Date: Tue, 20 Dec 2022 14:27:31 +0100 Subject: [PATCH 26/85] switch to test branch --- .github/workflows/testBuild.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index cc7886e36d56..c40f4ef91ec5 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -8,7 +8,7 @@ on: required: true pull_request_target: types: [opened, synchronize, labeled] - branches: ['main'] + branches: ['*ci-test/**'] env: DEVELOPER_DIR: /Applications/Xcode_14.0.1.app/Contents/Developer From d5ffd895e10534124f7ca1dad62fe814ed13ea4b Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Wed, 21 Dec 2022 15:08:28 +0000 Subject: [PATCH 27/85] adding the style method --- src/styles/StyleUtils.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js index 3606cdd4e8fa..b893fe4d9c02 100644 --- a/src/styles/StyleUtils.js +++ b/src/styles/StyleUtils.js @@ -437,6 +437,18 @@ function getReportActionItemStyle(isHovered = false, isLoading = false) { }; } +/** + * Generate the styles for the ReportActionItem wrapper view. + * + * @param {Boolean} [isLoading] + * @returns {Object} + */ +function getIOUPreviewLoadingItemStyle(isLoading = false) { + return { + opacity: isLoading ? 0.5 : 1, + }; +} + /** * Generate the wrapper styles for the mini ReportActionContextMenu. * @@ -679,4 +691,5 @@ export { getHeight, fade, getHorizontalStackedAvatarBorderStyle, + getIOUPreviewLoadingItemStyle, }; From 3bc5fbde3dcd1be1e1c1d730f1fa7357e3df0075 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Wed, 21 Dec 2022 15:08:41 +0000 Subject: [PATCH 28/85] using the style method --- src/pages/iou/IOUDetailsModal.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index 7dfaaec1197a..6e6e67773348 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -22,6 +22,7 @@ import SettlementButton from '../../components/SettlementButton'; import ROUTES from '../../ROUTES'; import FixedFooter from '../../components/FixedFooter'; import networkPropTypes from '../../components/networkPropTypes'; +import * as StyleUtils from '../../styles/StyleUtils'; const propTypes = { /** URL Route params */ @@ -144,11 +145,13 @@ class IOUDetailsModal extends Component { {reportIsLoading ? : ( - + + + Date: Wed, 21 Dec 2022 15:34:34 +0000 Subject: [PATCH 29/85] this should work, but it does not, I don't think the IOU has been updated for some reason. --- src/pages/iou/IOUDetailsModal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index 6e6e67773348..62853fbefc33 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -145,7 +145,7 @@ class IOUDetailsModal extends Component { {reportIsLoading ? : ( - + Date: Wed, 21 Dec 2022 16:09:43 +0000 Subject: [PATCH 30/85] no idea if this works but saving it for now --- src/ROUTES.js | 3 ++- src/components/ReportActionItem/IOUAction.js | 2 +- src/pages/iou/IOUDetailsModal.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ROUTES.js b/src/ROUTES.js index 470ea9d99eb7..9da046e938f6 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -74,7 +74,8 @@ export default { IOU_DETAILS_ADD_DEBIT_CARD: `${IOU_DETAILS}/add-debit-card`, IOU_DETAILS_ENABLE_PAYMENTS: `${IOU_DETAILS}/enable-payments`, IOU_DETAILS_WITH_IOU_REPORT_ID: `${IOU_DETAILS}/:chatReportID/:iouReportID/`, - getIouDetailsRoute: (chatReportID, iouReportID) => `iou/details/${chatReportID}/${iouReportID}`, + getIouDetailsRoute: (chatReportID, iouReportID) => `iou/details/${chatReportID}/${iouReportID}/`, + getIouDetailsWithActionRoute: (chatReportID, iouReportID, iouReportAction) => `iou/details/${chatReportID}/${iouReportID}/${encodeURIComponent(iouReportAction)}/`, SEARCH: 'search', SET_PASSWORD_WITH_VALIDATE_CODE: 'setpassword/:accountID/:validateCode', DETAILS: 'details', diff --git a/src/components/ReportActionItem/IOUAction.js b/src/components/ReportActionItem/IOUAction.js index affa1035eb64..bb8e7792eedb 100644 --- a/src/components/ReportActionItem/IOUAction.js +++ b/src/components/ReportActionItem/IOUAction.js @@ -44,7 +44,7 @@ const defaultProps = { const IOUAction = (props) => { const launchDetailsModal = () => { - Navigation.navigate(ROUTES.getIouDetailsRoute(props.chatReportID, props.action.originalMessage.IOUReportID)); + Navigation.navigate(ROUTES.getIouDetailsWithActionRoute(props.chatReportID, props.action.originalMessage.IOUReportID, props.action)); }; const shouldShowIOUPreview = ( diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index 62853fbefc33..1c5878c87e1d 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -145,7 +145,7 @@ class IOUDetailsModal extends Component { {reportIsLoading ? : ( - + Date: Wed, 21 Dec 2022 17:44:46 +0100 Subject: [PATCH 31/85] remove composer focused border when disabled --- src/pages/home/report/ReportActionCompose.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose.js index fec72e84b783..82f376dfad1c 100644 --- a/src/pages/home/report/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose.js @@ -542,7 +542,7 @@ class ReportActionCompose extends React.Component { {shouldShowReportRecipientLocalTime && } Date: Wed, 21 Dec 2022 17:55:28 +0100 Subject: [PATCH 32/85] update disabled logic in DragAndDrop --- src/components/DragAndDrop/index.js | 35 ++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/components/DragAndDrop/index.js b/src/components/DragAndDrop/index.js index 48ec86732064..09ce3c07dd1d 100644 --- a/src/components/DragAndDrop/index.js +++ b/src/components/DragAndDrop/index.js @@ -43,11 +43,6 @@ export default class DragAndDrop extends React.Component { constructor(props) { super(props); - if (props.disabled) { - this.isDisabled = true; - return; - } - this.throttledDragOverHandler = _.throttle(this.dragOverHandler.bind(this), 100); this.throttledDragNDropWindowResizeListener = _.throttle(this.dragNDropWindowResizeListener.bind(this), 100); this.dropZoneDragHandler = this.dropZoneDragHandler.bind(this); @@ -61,10 +56,32 @@ export default class DragAndDrop extends React.Component { } componentDidMount() { - if (this.isDisabled) { + if (this.props.disabled) { + return; + } + this.addEventListeners(); + } + + componentDidUpdate(prevProps) { + const isDisabled = this.props.disabled; + if (isDisabled === prevProps.disabled) { return; } + if (isDisabled) { + this.removeEventListeners(); + } else { + this.addEventListeners(); + } + } + componentWillUnmount() { + if (this.props.disabled) { + return; + } + this.removeEventListeners(); + } + + addEventListeners() { this.dropZone = document.getElementById(this.props.dropZoneId); this.dropZoneRect = this.calculateDropZoneClientReact(); document.addEventListener('dragover', this.dropZoneDragListener); @@ -74,11 +91,7 @@ export default class DragAndDrop extends React.Component { window.addEventListener('resize', this.throttledDragNDropWindowResizeListener); } - componentWillUnmount() { - if (this.isDisabled) { - return; - } - + removeEventListeners() { document.removeEventListener('dragover', this.dropZoneDragListener); document.removeEventListener('dragenter', this.dropZoneDragListener); document.removeEventListener('dragleave', this.dropZoneDragListener); From d60002cdd2de2ae8ffed10b5dbc4cbfd135f466e Mon Sep 17 00:00:00 2001 From: Pujan Date: Thu, 22 Dec 2022 06:58:46 +0530 Subject: [PATCH 33/85] emoji picker menu height changes to display it properly and taking advantage of flatlist getItemLayout for fixed height optimization --- src/CONST.js | 6 +++--- src/components/EmojiPicker/EmojiPickerMenu/index.js | 3 +++ src/styles/styles.js | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/CONST.js b/src/CONST.js index 58df088ffc19..ef02585f6aed 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -496,11 +496,11 @@ const CONST = { ADD_PAYMENT_MENU_POSITION_X: 356, EMOJI_PICKER_SIZE: { WIDTH: 320, - HEIGHT: 400, + HEIGHT: 390, }, - NON_NATIVE_EMOJI_PICKER_LIST_HEIGHT: 298, + NON_NATIVE_EMOJI_PICKER_LIST_HEIGHT: 288, EMOJI_PICKER_ITEM_HEIGHT: 32, - EMOJI_PICKER_HEADER_HEIGHT: 38, + EMOJI_PICKER_HEADER_HEIGHT: 32, COMPOSER_MAX_HEIGHT: 125, CHAT_FOOTER_MIN_HEIGHT: 65, CHAT_SKELETON_VIEW: { diff --git a/src/components/EmojiPicker/EmojiPickerMenu/index.js b/src/components/EmojiPicker/EmojiPickerMenu/index.js index ab68b51802c1..7c7d5fd16ad6 100755 --- a/src/components/EmojiPicker/EmojiPickerMenu/index.js +++ b/src/components/EmojiPicker/EmojiPickerMenu/index.js @@ -513,6 +513,9 @@ class EmojiPickerMenu extends Component { } stickyHeaderIndices={this.state.headerIndices} onScroll={e => this.currentScrollOffset = e.nativeEvent.contentOffset.y} + getItemLayout={(data, index) => ( + {length: CONST.EMOJI_PICKER_ITEM_HEIGHT, offset: CONST.EMOJI_PICKER_ITEM_HEIGHT * index, index} + )} /> )} Date: Thu, 22 Dec 2022 09:58:44 +0530 Subject: [PATCH 34/85] getItemLayout function added --- .../EmojiPicker/EmojiPickerMenu/index.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/components/EmojiPicker/EmojiPickerMenu/index.js b/src/components/EmojiPicker/EmojiPickerMenu/index.js index 7c7d5fd16ad6..c5f7d991a23f 100755 --- a/src/components/EmojiPicker/EmojiPickerMenu/index.js +++ b/src/components/EmojiPicker/EmojiPickerMenu/index.js @@ -87,6 +87,7 @@ class EmojiPickerMenu extends Component { this.onSelectionChange = this.onSelectionChange.bind(this); this.updatePreferredSkinTone = this.updatePreferredSkinTone.bind(this); this.setFirstNonHeaderIndex = this.setFirstNonHeaderIndex.bind(this); + this.getItemLayout = this.getItemLayout.bind(this); this.currentScrollOffset = 0; this.firstNonHeaderIndex = 0; @@ -414,6 +415,15 @@ class EmojiPickerMenu extends Component { User.updatePreferredSkinTone(skinTone); } + /** + * @param {*} data + * @param {Number} index + * @returns {Object} + */ + getItemLayout(data, index) { + return {length: CONST.EMOJI_PICKER_ITEM_HEIGHT, offset: CONST.EMOJI_PICKER_ITEM_HEIGHT * index, index}; + } + /** * Given an emoji item object, render a component based on its type. * Items with the code "SPACER" return nothing and are used to fill rows up to 8 @@ -513,9 +523,7 @@ class EmojiPickerMenu extends Component { } stickyHeaderIndices={this.state.headerIndices} onScroll={e => this.currentScrollOffset = e.nativeEvent.contentOffset.y} - getItemLayout={(data, index) => ( - {length: CONST.EMOJI_PICKER_ITEM_HEIGHT, offset: CONST.EMOJI_PICKER_ITEM_HEIGHT * index, index} - )} + getItemLayout={this.getItemLayout} /> )} Date: Thu, 22 Dec 2022 10:06:19 +0530 Subject: [PATCH 35/85] lint fix --- .../EmojiPicker/EmojiPickerMenu/index.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/EmojiPicker/EmojiPickerMenu/index.js b/src/components/EmojiPicker/EmojiPickerMenu/index.js index c5f7d991a23f..e4f9fbbf6821 100755 --- a/src/components/EmojiPicker/EmojiPickerMenu/index.js +++ b/src/components/EmojiPicker/EmojiPickerMenu/index.js @@ -191,6 +191,15 @@ class EmojiPickerMenu extends Component { document.addEventListener('mousemove', this.mouseMoveHandler); } + /** + * @param {*} data + * @param {Number} index + * @returns {Object} + */ + getItemLayout(data, index) { + return {length: CONST.EMOJI_PICKER_ITEM_HEIGHT, offset: CONST.EMOJI_PICKER_ITEM_HEIGHT * index, index}; + } + /** * Cleanup all mouse/keydown event listeners that we've set up */ @@ -415,15 +424,6 @@ class EmojiPickerMenu extends Component { User.updatePreferredSkinTone(skinTone); } - /** - * @param {*} data - * @param {Number} index - * @returns {Object} - */ - getItemLayout(data, index) { - return {length: CONST.EMOJI_PICKER_ITEM_HEIGHT, offset: CONST.EMOJI_PICKER_ITEM_HEIGHT * index, index}; - } - /** * Given an emoji item object, render a component based on its type. * Items with the code "SPACER" return nothing and are used to fill rows up to 8 From 0fa0c03ac765a7b8032094c3d85de8939ddac12c Mon Sep 17 00:00:00 2001 From: Srikar Parsi Date: Thu, 22 Dec 2022 04:04:07 -0500 Subject: [PATCH 36/85] modify api request data --- src/libs/actions/Plaid.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Plaid.js b/src/libs/actions/Plaid.js index f6691b8f4a3c..4c81f33b58b4 100644 --- a/src/libs/actions/Plaid.js +++ b/src/libs/actions/Plaid.js @@ -32,7 +32,7 @@ function openPlaidBankAccountSelector(publicToken, bankName, allowDebit) { key: ONYXKEYS.PLAID_DATA, value: { isLoading: true, - error: '', + errors: null, bankName, }, }], @@ -41,7 +41,7 @@ function openPlaidBankAccountSelector(publicToken, bankName, allowDebit) { key: ONYXKEYS.PLAID_DATA, value: { isLoading: false, - error: '', + errors: null, }, }], failureData: [{ @@ -49,7 +49,6 @@ function openPlaidBankAccountSelector(publicToken, bankName, allowDebit) { key: ONYXKEYS.PLAID_DATA, value: { isLoading: false, - error: Localize.translateLocal('bankAccount.error.noBankAccountAvailable'), }, }], }); From fc8899139c4a84e93ecf6cce71ee82ff09559e35 Mon Sep 17 00:00:00 2001 From: Srikar Parsi Date: Thu, 22 Dec 2022 04:54:03 -0500 Subject: [PATCH 37/85] add errors to clear data --- src/components/AddPlaidBankAccount.js | 6 ++++-- src/libs/actions/CloseAccount.js | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 3aa31b8e7d31..29d76102b4b6 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -63,6 +63,7 @@ const defaultProps = { bankAccounts: [], isLoading: false, error: '', + errors: {}, }, selectedPlaidAccountID: '', plaidLinkToken: '', @@ -112,6 +113,7 @@ class AddPlaidBankAccount extends React.Component { label: `${account.addressName} ${account.mask}`, })); const {icon, iconSize} = getBankIcon(); + const plaidDataErrorMessage = !_.isEmpty(this.props.plaidData.errors) ? _.chain(this.props.plaidData.errors).values().first().value() : this.props.plaidData.error; // Plaid Link view if (!plaidBankAccounts.length) { @@ -123,9 +125,9 @@ class AddPlaidBankAccount extends React.Component { )} - {Boolean(this.props.plaidData.error) && ( + {Boolean(plaidDataErrorMessage) && ( - {this.props.plaidData.error} + {plaidDataErrorMessage} )} {Boolean(token) && ( diff --git a/src/libs/actions/CloseAccount.js b/src/libs/actions/CloseAccount.js index 525398446862..ea45ae86c76f 100644 --- a/src/libs/actions/CloseAccount.js +++ b/src/libs/actions/CloseAccount.js @@ -6,7 +6,7 @@ import CONST from '../../CONST'; * Clear CloseAccount error message to hide modal */ function clearError() { - Onyx.merge(ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM, {error: ''}); + Onyx.merge(ONYXKEYS.FORMS.CLOSE_ACCOUNT_FORM, {error: '', errors: null}); } /** From 3111356e83bc20cd1e8203e5c57313641d722a0c Mon Sep 17 00:00:00 2001 From: Srikar Parsi Date: Thu, 22 Dec 2022 04:57:46 -0500 Subject: [PATCH 38/85] restore accidentally commited changes --- src/components/AddPlaidBankAccount.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 29d76102b4b6..3aa31b8e7d31 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -63,7 +63,6 @@ const defaultProps = { bankAccounts: [], isLoading: false, error: '', - errors: {}, }, selectedPlaidAccountID: '', plaidLinkToken: '', @@ -113,7 +112,6 @@ class AddPlaidBankAccount extends React.Component { label: `${account.addressName} ${account.mask}`, })); const {icon, iconSize} = getBankIcon(); - const plaidDataErrorMessage = !_.isEmpty(this.props.plaidData.errors) ? _.chain(this.props.plaidData.errors).values().first().value() : this.props.plaidData.error; // Plaid Link view if (!plaidBankAccounts.length) { @@ -125,9 +123,9 @@ class AddPlaidBankAccount extends React.Component { )} - {Boolean(plaidDataErrorMessage) && ( + {Boolean(this.props.plaidData.error) && ( - {plaidDataErrorMessage} + {this.props.plaidData.error} )} {Boolean(token) && ( From 5daf294db1c9b2cc69bb5c0fff7e0f52ecd9e9d9 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Thu, 22 Dec 2022 16:09:55 +0000 Subject: [PATCH 39/85] adding reportActions --- src/pages/iou/IOUDetailsModal.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index 1c5878c87e1d..3c6da5e3da61 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -23,6 +23,7 @@ import ROUTES from '../../ROUTES'; import FixedFooter from '../../components/FixedFooter'; import networkPropTypes from '../../components/networkPropTypes'; import * as StyleUtils from '../../styles/StyleUtils'; +import reportActionPropTypes from "../home/report/reportActionPropTypes"; const propTypes = { /** URL Route params */ @@ -68,6 +69,9 @@ const propTypes = { email: PropTypes.string, }).isRequired, + /** Actions from the ChatReport */ + reportActions: PropTypes.shape(reportActionPropTypes), + /** Information about the network */ network: networkPropTypes.isRequired, @@ -76,6 +80,7 @@ const propTypes = { const defaultProps = { iou: {}, + reportActions: {}, iouReport: undefined, }; @@ -200,5 +205,9 @@ export default compose( session: { key: ONYXKEYS.SESSION, }, + reportActions: { + key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${route.params.chatReportID}`, + canEvict: false, + }, }), )(IOUDetailsModal); From add942bfe36842e9f0025bb1e2f35cd912886f87 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Thu, 22 Dec 2022 16:10:04 +0000 Subject: [PATCH 40/85] reseting this --- src/pages/iou/IOUDetailsModal.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index 3c6da5e3da61..9d1934f485a1 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -150,13 +150,11 @@ class IOUDetailsModal extends Component { {reportIsLoading ? : ( - - - + Date: Thu, 22 Dec 2022 16:23:14 +0000 Subject: [PATCH 41/85] adding method to find a pending action --- src/pages/iou/IOUDetailsModal.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index 9d1934f485a1..3789ef20ef3d 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -138,6 +138,17 @@ class IOUDetailsModal extends Component { } } + // Finds the if there is a reportAction pending for this IOU + findPendingAction() { + return _.find(this.props.reportActions, (reportAction) => { + if (Number(reportAction.originalMessage.IOUReportID) === this.props.iouReportID) { + return !_.isEmpty(reportAction.pendingAction); + } + return false; + } + ); + } + render() { const sessionEmail = lodashGet(this.props.session, 'email', null); const reportIsLoading = _.isUndefined(this.props.iouReport); From 0d798ab0c4a989ca9d15a6776a4f568cc05b3997 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Thu, 22 Dec 2022 16:24:07 +0000 Subject: [PATCH 42/85] using method --- src/pages/iou/IOUDetailsModal.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index 3789ef20ef3d..f18c83dc392a 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -152,6 +152,7 @@ class IOUDetailsModal extends Component { render() { const sessionEmail = lodashGet(this.props.session, 'email', null); const reportIsLoading = _.isUndefined(this.props.iouReport); + const pendingAction = findPendingAction(); return ( Date: Thu, 22 Dec 2022 16:24:17 +0000 Subject: [PATCH 43/85] removing routes --- src/ROUTES.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ROUTES.js b/src/ROUTES.js index 9da046e938f6..ac49189e87b2 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -75,7 +75,6 @@ export default { IOU_DETAILS_ENABLE_PAYMENTS: `${IOU_DETAILS}/enable-payments`, IOU_DETAILS_WITH_IOU_REPORT_ID: `${IOU_DETAILS}/:chatReportID/:iouReportID/`, getIouDetailsRoute: (chatReportID, iouReportID) => `iou/details/${chatReportID}/${iouReportID}/`, - getIouDetailsWithActionRoute: (chatReportID, iouReportID, iouReportAction) => `iou/details/${chatReportID}/${iouReportID}/${encodeURIComponent(iouReportAction)}/`, SEARCH: 'search', SET_PASSWORD_WITH_VALIDATE_CODE: 'setpassword/:accountID/:validateCode', DETAILS: 'details', From 85d4eaa49893b98f545e6f0ff896341ae0d92a65 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Thu, 22 Dec 2022 16:26:47 +0000 Subject: [PATCH 44/85] cleaning --- src/ROUTES.js | 2 +- src/components/ReportActionItem/IOUAction.js | 2 +- src/pages/iou/IOUDetailsModal.js | 2 +- src/styles/StyleUtils.js | 12 ------------ 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/ROUTES.js b/src/ROUTES.js index ac49189e87b2..470ea9d99eb7 100644 --- a/src/ROUTES.js +++ b/src/ROUTES.js @@ -74,7 +74,7 @@ export default { IOU_DETAILS_ADD_DEBIT_CARD: `${IOU_DETAILS}/add-debit-card`, IOU_DETAILS_ENABLE_PAYMENTS: `${IOU_DETAILS}/enable-payments`, IOU_DETAILS_WITH_IOU_REPORT_ID: `${IOU_DETAILS}/:chatReportID/:iouReportID/`, - getIouDetailsRoute: (chatReportID, iouReportID) => `iou/details/${chatReportID}/${iouReportID}/`, + getIouDetailsRoute: (chatReportID, iouReportID) => `iou/details/${chatReportID}/${iouReportID}`, SEARCH: 'search', SET_PASSWORD_WITH_VALIDATE_CODE: 'setpassword/:accountID/:validateCode', DETAILS: 'details', diff --git a/src/components/ReportActionItem/IOUAction.js b/src/components/ReportActionItem/IOUAction.js index bb8e7792eedb..affa1035eb64 100644 --- a/src/components/ReportActionItem/IOUAction.js +++ b/src/components/ReportActionItem/IOUAction.js @@ -44,7 +44,7 @@ const defaultProps = { const IOUAction = (props) => { const launchDetailsModal = () => { - Navigation.navigate(ROUTES.getIouDetailsWithActionRoute(props.chatReportID, props.action.originalMessage.IOUReportID, props.action)); + Navigation.navigate(ROUTES.getIouDetailsRoute(props.chatReportID, props.action.originalMessage.IOUReportID)); }; const shouldShowIOUPreview = ( diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index f18c83dc392a..34ad1a03180a 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -23,7 +23,7 @@ import ROUTES from '../../ROUTES'; import FixedFooter from '../../components/FixedFooter'; import networkPropTypes from '../../components/networkPropTypes'; import * as StyleUtils from '../../styles/StyleUtils'; -import reportActionPropTypes from "../home/report/reportActionPropTypes"; +import reportActionPropTypes from '../home/report/reportActionPropTypes'; const propTypes = { /** URL Route params */ diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js index b893fe4d9c02..84402d9ceb4e 100644 --- a/src/styles/StyleUtils.js +++ b/src/styles/StyleUtils.js @@ -437,18 +437,6 @@ function getReportActionItemStyle(isHovered = false, isLoading = false) { }; } -/** - * Generate the styles for the ReportActionItem wrapper view. - * - * @param {Boolean} [isLoading] - * @returns {Object} - */ -function getIOUPreviewLoadingItemStyle(isLoading = false) { - return { - opacity: isLoading ? 0.5 : 1, - }; -} - /** * Generate the wrapper styles for the mini ReportActionContextMenu. * From 5a21478f41a4b532c0ffa526b3af5f3b37e2044f Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Thu, 22 Dec 2022 16:27:26 +0000 Subject: [PATCH 45/85] missed one --- src/styles/StyleUtils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js index 84402d9ceb4e..3606cdd4e8fa 100644 --- a/src/styles/StyleUtils.js +++ b/src/styles/StyleUtils.js @@ -679,5 +679,4 @@ export { getHeight, fade, getHorizontalStackedAvatarBorderStyle, - getIOUPreviewLoadingItemStyle, }; From 54d78ea477818dfa4e9930c5df0bbc64ef6eab99 Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Thu, 22 Dec 2022 16:31:03 +0000 Subject: [PATCH 46/85] linter --- src/pages/iou/IOUDetailsModal.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index 34ad1a03180a..8baa5f851cbf 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -22,7 +22,6 @@ import SettlementButton from '../../components/SettlementButton'; import ROUTES from '../../ROUTES'; import FixedFooter from '../../components/FixedFooter'; import networkPropTypes from '../../components/networkPropTypes'; -import * as StyleUtils from '../../styles/StyleUtils'; import reportActionPropTypes from '../home/report/reportActionPropTypes'; const propTypes = { @@ -141,18 +140,17 @@ class IOUDetailsModal extends Component { // Finds the if there is a reportAction pending for this IOU findPendingAction() { return _.find(this.props.reportActions, (reportAction) => { - if (Number(reportAction.originalMessage.IOUReportID) === this.props.iouReportID) { - return !_.isEmpty(reportAction.pendingAction); - } - return false; + if (Number(reportAction.originalMessage.IOUReportID) === this.props.iouReportID) { + return !_.isEmpty(reportAction.pendingAction); } - ); + return false; + }); } render() { const sessionEmail = lodashGet(this.props.session, 'email', null); const reportIsLoading = _.isUndefined(this.props.iouReport); - const pendingAction = findPendingAction(); + const pendingAction = this.findPendingAction(); return ( Date: Thu, 22 Dec 2022 16:54:02 +0000 Subject: [PATCH 47/85] fixing the condition --- src/pages/iou/IOUDetailsModal.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index 8baa5f851cbf..3ce31d433563 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -140,10 +140,9 @@ class IOUDetailsModal extends Component { // Finds the if there is a reportAction pending for this IOU findPendingAction() { return _.find(this.props.reportActions, (reportAction) => { - if (Number(reportAction.originalMessage.IOUReportID) === this.props.iouReportID) { - return !_.isEmpty(reportAction.pendingAction); - } - return false; + return reportAction.originalMessage && + Number(reportAction.originalMessage.IOUReportID) === Number(this.props.route.params.iouReportID) && + !_.isEmpty(reportAction.pendingAction); }); } From 94f84e97a8040c5ccb2fd40585b76b73cbd5683f Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Thu, 22 Dec 2022 16:59:47 +0000 Subject: [PATCH 48/85] this is no longer used --- src/components/ReportActionItem/IOUAction.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/ReportActionItem/IOUAction.js b/src/components/ReportActionItem/IOUAction.js index affa1035eb64..d488f819ca79 100644 --- a/src/components/ReportActionItem/IOUAction.js +++ b/src/components/ReportActionItem/IOUAction.js @@ -61,7 +61,6 @@ const IOUAction = (props) => { /> {shouldShowIOUPreview && ( Date: Thu, 22 Dec 2022 17:09:54 +0000 Subject: [PATCH 49/85] linter --- src/components/ReportActionItem/IOUAction.js | 1 - src/pages/iou/IOUDetailsModal.js | 8 +++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/components/ReportActionItem/IOUAction.js b/src/components/ReportActionItem/IOUAction.js index d488f819ca79..486f3d10fdae 100644 --- a/src/components/ReportActionItem/IOUAction.js +++ b/src/components/ReportActionItem/IOUAction.js @@ -1,7 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; import {withOnyx} from 'react-native-onyx'; -import lodashGet from 'lodash/get'; import ONYXKEYS from '../../ONYXKEYS'; import IOUQuote from './IOUQuote'; import reportActionPropTypes from '../../pages/home/report/reportActionPropTypes'; diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index 3ce31d433563..eda527f35aa8 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -139,11 +139,9 @@ class IOUDetailsModal extends Component { // Finds the if there is a reportAction pending for this IOU findPendingAction() { - return _.find(this.props.reportActions, (reportAction) => { - return reportAction.originalMessage && - Number(reportAction.originalMessage.IOUReportID) === Number(this.props.route.params.iouReportID) && - !_.isEmpty(reportAction.pendingAction); - }); + return _.find(this.props.reportActions, reportAction => reportAction.originalMessage + && Number(reportAction.originalMessage.IOUReportID) === Number(this.props.route.params.iouReportID) + && !_.isEmpty(reportAction.pendingAction)); } render() { From 53bc1ea6a7a4d3447b3898e321688737394ddf15 Mon Sep 17 00:00:00 2001 From: rory Date: Thu, 22 Dec 2022 10:45:51 -0800 Subject: [PATCH 50/85] Remove unused keyboard event --- src/pages/home/report/ReportActionsView.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/pages/home/report/ReportActionsView.js b/src/pages/home/report/ReportActionsView.js index 2de35be8b5ce..bb4c8999e850 100755 --- a/src/pages/home/report/ReportActionsView.js +++ b/src/pages/home/report/ReportActionsView.js @@ -236,10 +236,6 @@ class ReportActionsView extends React.Component { } componentWillUnmount() { - if (this.keyboardEvent) { - this.keyboardEvent.remove(); - } - if (this.unsubscribeVisibilityListener) { this.unsubscribeVisibilityListener(); } From 2ff4ab4782ce368cfc648e9e290339c1c456e3ff Mon Sep 17 00:00:00 2001 From: Srikar Parsi Date: Thu, 22 Dec 2022 15:01:06 -0500 Subject: [PATCH 51/85] add back error --- src/libs/actions/Plaid.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/actions/Plaid.js b/src/libs/actions/Plaid.js index 4c81f33b58b4..0a7a85c56410 100644 --- a/src/libs/actions/Plaid.js +++ b/src/libs/actions/Plaid.js @@ -32,6 +32,7 @@ function openPlaidBankAccountSelector(publicToken, bankName, allowDebit) { key: ONYXKEYS.PLAID_DATA, value: { isLoading: true, + error: '', errors: null, bankName, }, @@ -41,6 +42,7 @@ function openPlaidBankAccountSelector(publicToken, bankName, allowDebit) { key: ONYXKEYS.PLAID_DATA, value: { isLoading: false, + error: '', errors: null, }, }], From e1ce0395fc358512996feffbbee246b3aac48fc3 Mon Sep 17 00:00:00 2001 From: Srikar Parsi Date: Thu, 22 Dec 2022 16:03:13 -0500 Subject: [PATCH 52/85] fix lint error --- src/libs/actions/Plaid.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/actions/Plaid.js b/src/libs/actions/Plaid.js index 0a7a85c56410..393b5bbc9961 100644 --- a/src/libs/actions/Plaid.js +++ b/src/libs/actions/Plaid.js @@ -1,7 +1,6 @@ import getPlaidLinkTokenParameters from '../getPlaidLinkTokenParameters'; import ONYXKEYS from '../../ONYXKEYS'; import * as API from '../API'; -import * as Localize from '../Localize'; import CONST from '../../CONST'; /** From ffd02011cc04f5640145d66f52c17d2e56c25c10 Mon Sep 17 00:00:00 2001 From: Pujan Date: Fri, 23 Dec 2022 07:47:09 +0530 Subject: [PATCH 53/85] comment added --- src/components/EmojiPicker/EmojiPickerMenu/index.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/EmojiPicker/EmojiPickerMenu/index.js b/src/components/EmojiPicker/EmojiPickerMenu/index.js index e4f9fbbf6821..87e3356b7c72 100755 --- a/src/components/EmojiPicker/EmojiPickerMenu/index.js +++ b/src/components/EmojiPicker/EmojiPickerMenu/index.js @@ -192,8 +192,13 @@ class EmojiPickerMenu extends Component { } /** - * @param {*} data - * @param {Number} index + * This function will be used with FlatList getItemLayout property for optimization purpose that allows skipping + * the measurement of dynamic content if we know the size (height or width) of items ahead of time. + * Generate and return an object with properties length(height of each individual row), + * offset(distance of the current row from the top of the FlatList), index(current row index) + * + * @param {*} data FlatList item + * @param {Number} index row index * @returns {Object} */ getItemLayout(data, index) { From 37cb19756c627331e3c556e083eefc83e85bf8cf Mon Sep 17 00:00:00 2001 From: Alberto Date: Mon, 26 Dec 2022 16:50:42 +0100 Subject: [PATCH 54/85] style cursor correctly for splits --- src/components/ReportActionItem/IOUQuote.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/IOUQuote.js b/src/components/ReportActionItem/IOUQuote.js index e59093a95aed..11544cbc60dd 100644 --- a/src/components/ReportActionItem/IOUQuote.js +++ b/src/components/ReportActionItem/IOUQuote.js @@ -49,7 +49,10 @@ const IOUQuote = props => ( {/* Get first word of IOU message */} {Str.htmlDecode(fragment.text.split(' ')[0])} - + {/* Get remainder of IOU message */} {Str.htmlDecode(fragment.text.substring(fragment.text.indexOf(' ')))} From 8c1540ecb6e95dc31e67d88ffe1096a7d07ef252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Tue, 27 Dec 2022 10:28:31 +0100 Subject: [PATCH 55/85] ignored error --- tests/e2e/testRunner.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/e2e/testRunner.js b/tests/e2e/testRunner.js index 10ea1eeb25c9..a82dc3a9212a 100644 --- a/tests/e2e/testRunner.js +++ b/tests/e2e/testRunner.js @@ -250,8 +250,9 @@ const runTests = async () => { require('node:child_process').execSync(`cat ${config.LOG_FILE}`); try { require('node:child_process').execSync(`cat ~/.android/avd/${process.env.AVD_NAME || 'test'}.avd/config.ini > ${config.OUTPUT_DIR}/emulator-config.ini`); - } catch (__) { - // the file might not exist + } catch (ignoredError) { + // the error is ignored, as the file might not exist if the test + // run wasn't started with an emulator } process.exit(1); } From b2f762fba00343811ce0716e68e5e5855065125a Mon Sep 17 00:00:00 2001 From: staszekscp Date: Tue, 27 Dec 2022 11:22:16 +0100 Subject: [PATCH 56/85] switch to READY_TO_BUILD --- .github/workflows/testBuild.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/testBuild.yml b/.github/workflows/testBuild.yml index c40f4ef91ec5..6bfcf033e5b1 100644 --- a/.github/workflows/testBuild.yml +++ b/.github/workflows/testBuild.yml @@ -17,7 +17,7 @@ jobs: validateActor: runs-on: ubuntu-latest outputs: - CAN_BE_BUILD: ${{steps.canBeBuild.outputs.CAN_BE_BUILD}} + READY_TO_BUILD: ${{steps.readyToBuild.outputs.READY_TO_BUILD}} steps: - id: isUserTeamMember uses: tspascoal/get-user-teams-membership@baf2e6adf4c3b897bd65a7e3184305c165aec872 @@ -35,14 +35,14 @@ jobs: run: | echo "The 'Ready To Build' label was added by an unauthorized user" exit 1 - - id: canBeBuild - name: Set CAN_BE_BUILD flag - run: echo "CAN_BE_BUILD=${{ fromJSON(steps.isUserTeamMember.outputs.isTeamMember) || contains(github.event.pull_request.labels.*.name, 'Ready To Build') }}" >> "$GITHUB_OUTPUT" + - id: readyToBuild + name: Set READY_TO_BUILD flag + run: echo "READY_TO_BUILD=${{ fromJSON(steps.isUserTeamMember.outputs.isTeamMember) || contains(github.event.pull_request.labels.*.name, 'Ready To Build') }}" >> "$GITHUB_OUTPUT" getBranchRef: runs-on: ubuntu-latest needs: validateActor - if: ${{ needs.validateActor.outputs.CAN_BE_BUILD == 'true' }} + if: ${{ needs.validateActor.outputs.READY_TO_BUILD == 'true' }} outputs: REF: ${{steps.getHeadRef.outputs.REF}} steps: @@ -62,7 +62,7 @@ jobs: android: name: Build and deploy Android for testing needs: [validateActor, getBranchRef] - if: ${{ needs.validateActor.outputs.CAN_BE_BUILD == 'true' }} + if: ${{ needs.validateActor.outputs.READY_TO_BUILD == 'true' }} runs-on: ubuntu-latest env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} @@ -112,7 +112,7 @@ jobs: iOS: name: Build and deploy iOS for testing needs: [validateActor, getBranchRef] - if: ${{ needs.validateActor.outputs.CAN_BE_BUILD == 'true' }} + if: ${{ needs.validateActor.outputs.READY_TO_BUILD == 'true' }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: macos-12 @@ -168,7 +168,7 @@ jobs: desktop: name: Build and deploy Desktop for testing needs: [validateActor, getBranchRef] - if: ${{ needs.validateActor.outputs.CAN_BE_BUILD == 'true' }} + if: ${{ needs.validateActor.outputs.READY_TO_BUILD == 'true' }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: macos-12 @@ -205,7 +205,7 @@ jobs: web: name: Build and deploy Web needs: [validateActor, getBranchRef] - if: ${{ needs.validateActor.outputs.CAN_BE_BUILD == 'true' }} + if: ${{ needs.validateActor.outputs.READY_TO_BUILD == 'true' }} env: PULL_REQUEST_NUMBER: ${{ github.event.number || github.event.inputs.PULL_REQUEST_NUMBER }} runs-on: ubuntu-latest From d21251aa9323b8407d2aafa447eeb5f69a9c5eef Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 27 Dec 2022 11:35:48 +0100 Subject: [PATCH 57/85] Pass style on focus --- src/components/DatePicker/index.android.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/DatePicker/index.android.js b/src/components/DatePicker/index.android.js index e034af725c17..371619b29af0 100644 --- a/src/components/DatePicker/index.android.js +++ b/src/components/DatePicker/index.android.js @@ -5,6 +5,7 @@ import _ from 'underscore'; import TextInput from '../TextInput'; import CONST from '../../CONST'; import {propTypes, defaultProps} from './datepickerPropTypes'; +import styles from "../../styles/styles"; class DatePicker extends React.Component { constructor(props) { @@ -48,7 +49,7 @@ class DatePicker extends React.Component { value={dateAsText} placeholder={this.props.placeholder} errorText={this.props.errorText} - containerStyles={this.props.containerStyles} + containerStyles={[...this.props.containerStyles, this.state.isPickerVisible ? styles.borderColorFocus : []]} onPress={this.showPicker} editable={false} disabled={this.props.disabled} From 403c67172b4bb57f71bc7c6e6bc3552e6df040cc Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 27 Dec 2022 11:36:48 +0100 Subject: [PATCH 58/85] move to inputcontainerstyles --- src/components/DatePicker/index.android.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/DatePicker/index.android.js b/src/components/DatePicker/index.android.js index 371619b29af0..324de98c9050 100644 --- a/src/components/DatePicker/index.android.js +++ b/src/components/DatePicker/index.android.js @@ -49,7 +49,8 @@ class DatePicker extends React.Component { value={dateAsText} placeholder={this.props.placeholder} errorText={this.props.errorText} - containerStyles={[...this.props.containerStyles, this.state.isPickerVisible ? styles.borderColorFocus : []]} + containerStyles={this.props.containerStyles} + textInputContainerStyles={this.state.isPickerVisible ? [styles.borderColorFocus] : []} onPress={this.showPicker} editable={false} disabled={this.props.disabled} From a867f833b97dbb5e204184565211cc81d3709a5f Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 27 Dec 2022 11:37:49 +0100 Subject: [PATCH 59/85] fix on iOS too --- src/components/DatePicker/index.ios.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/DatePicker/index.ios.js b/src/components/DatePicker/index.ios.js index 062134ea468d..c9d076b7836b 100644 --- a/src/components/DatePicker/index.ios.js +++ b/src/components/DatePicker/index.ios.js @@ -75,6 +75,7 @@ class DatePicker extends React.Component { placeholder={this.props.placeholder} errorText={this.props.errorText} containerStyles={this.props.containerStyles} + textInputContainerStyles={this.state.isPickerVisible ? [styles.borderColorFocus] : []} onPress={this.showPicker} editable={false} disabled={this.props.disabled} From 76fadd18536f5cb79a01f3defb144b73b9e2ca95 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 27 Dec 2022 12:14:16 +0100 Subject: [PATCH 60/85] mstyle --- src/components/DatePicker/index.android.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/DatePicker/index.android.js b/src/components/DatePicker/index.android.js index 324de98c9050..ec1f23f70bd6 100644 --- a/src/components/DatePicker/index.android.js +++ b/src/components/DatePicker/index.android.js @@ -5,7 +5,7 @@ import _ from 'underscore'; import TextInput from '../TextInput'; import CONST from '../../CONST'; import {propTypes, defaultProps} from './datepickerPropTypes'; -import styles from "../../styles/styles"; +import styles from '../../styles/styles'; class DatePicker extends React.Component { constructor(props) { From d287bcc7b8b43fedfcd9c5c74c2816da0e0d2510 Mon Sep 17 00:00:00 2001 From: Alberto Date: Tue, 27 Dec 2022 12:55:36 +0100 Subject: [PATCH 61/85] Do not highlight phone icon on Concierge chats --- .../VideoChatButtonAndMenu/BaseVideoChatButtonAndMenu.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/VideoChatButtonAndMenu/BaseVideoChatButtonAndMenu.js b/src/components/VideoChatButtonAndMenu/BaseVideoChatButtonAndMenu.js index ae15b2443888..9630c047f476 100755 --- a/src/components/VideoChatButtonAndMenu/BaseVideoChatButtonAndMenu.js +++ b/src/components/VideoChatButtonAndMenu/BaseVideoChatButtonAndMenu.js @@ -122,9 +122,7 @@ class BaseVideoChatButtonAndMenu extends Component { > From 30e214a4b048a36c4be20804bbcde14369bc193e Mon Sep 17 00:00:00 2001 From: OSBotify Date: Tue, 27 Dec 2022 18:05:23 +0000 Subject: [PATCH 62/85] Update version to 1.2.44-0 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 4 ++-- ios/NewExpensifyTests/Info.plist | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index bddf3a7d18b7..a6af83b1b978 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -156,8 +156,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001024301 - versionName "1.2.43-1" + versionCode 1001024400 + versionName "1.2.44-0" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index dc18ff815bb3..89ddc10e5e94 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.2.43 + 1.2.44 CFBundleSignature ???? CFBundleURLTypes @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.43.1 + 1.2.44.0 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 7af9e83e7dea..d5e076f3af3f 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.2.43 + 1.2.44 CFBundleSignature ???? CFBundleVersion - 1.2.43.1 + 1.2.44.0 diff --git a/package-lock.json b/package-lock.json index 54b0c3234ef7..1e11151c3f4c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.43-1", + "version": "1.2.44-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.43-1", + "version": "1.2.44-0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 47e984a63f4e..b0d4d0f5b3ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.43-1", + "version": "1.2.44-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.", From a4cae378bd2de4be85fbfaa809a3c7359a0b4036 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Sun, 11 Dec 2022 19:59:53 +0100 Subject: [PATCH 63/85] fix: scroll to TextInput on Picker open --- package-lock.json | 10 ++++---- package.json | 2 +- src/components/Picker/index.js | 14 +++++++++-- src/components/ScrollViewWithPickers.js | 24 +++++++++++++++++++ .../workspace/WorkspacePageWithSections.js | 9 +++---- 5 files changed, 46 insertions(+), 13 deletions(-) create mode 100644 src/components/ScrollViewWithPickers.js diff --git a/package-lock.json b/package-lock.json index 1e11151c3f4c..e94120130e34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,7 +73,7 @@ "react-native-pdf": "^6.6.2", "react-native-performance": "^2.0.0", "react-native-permissions": "^3.0.1", - "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#7f09b2c15ffae320d769788f75bdf8948714bb10", + "react-native-picker-select": "git+https://github.com/chrispader/expensify-react-native-picker-select.git#fix/scroll-to-input-on-open", "react-native-plaid-link-sdk": "^7.2.0", "react-native-reanimated": "3.0.0-rc.6", "react-native-render-html": "6.3.1", @@ -35528,8 +35528,7 @@ }, "node_modules/react-native-picker-select": { "version": "8.0.4", - "resolved": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#7f09b2c15ffae320d769788f75bdf8948714bb10", - "integrity": "sha512-fKuK7NBPYmf0rfQIPcOK1OrM31DIlQVEtdEBANWxudBXwj+okAakY9hIXPXkCd1Ow7gj5P3Z2XNle2ak6NtYPg==", + "resolved": "git+ssh://git@github.com/chrispader/expensify-react-native-picker-select.git#235fb856d07470cd3b550cb5c2aaeffd0d1631c8", "license": "MIT", "dependencies": { "lodash.isequal": "^4.5.0" @@ -69867,9 +69866,8 @@ "requires": {} }, "react-native-picker-select": { - "version": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#7f09b2c15ffae320d769788f75bdf8948714bb10", - "integrity": "sha512-fKuK7NBPYmf0rfQIPcOK1OrM31DIlQVEtdEBANWxudBXwj+okAakY9hIXPXkCd1Ow7gj5P3Z2XNle2ak6NtYPg==", - "from": "react-native-picker-select@git+https://github.com/Expensify/react-native-picker-select.git#7f09b2c15ffae320d769788f75bdf8948714bb10", + "version": "git+ssh://git@github.com/chrispader/expensify-react-native-picker-select.git#235fb856d07470cd3b550cb5c2aaeffd0d1631c8", + "from": "react-native-picker-select@git+https://github.com/chrispader/expensify-react-native-picker-select.git#fix/scroll-to-input-on-open", "requires": { "lodash.isequal": "^4.5.0" } diff --git a/package.json b/package.json index b0d4d0f5b3ea..a3f8afdd6fb6 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "react-native-pdf": "^6.6.2", "react-native-performance": "^2.0.0", "react-native-permissions": "^3.0.1", - "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#7f09b2c15ffae320d769788f75bdf8948714bb10", + "react-native-picker-select": "git+https://github.com/chrispader/expensify-react-native-picker-select.git#fix/scroll-to-input-on-open", "react-native-plaid-link-sdk": "^7.2.0", "react-native-reanimated": "3.0.0-rc.6", "react-native-render-html": "6.3.1", diff --git a/src/components/Picker/index.js b/src/components/Picker/index.js index 62cb9c2b427e..0f3ce9bb8325 100644 --- a/src/components/Picker/index.js +++ b/src/components/Picker/index.js @@ -10,6 +10,7 @@ import Text from '../Text'; import styles from '../../styles/styles'; import themeColors from '../../styles/themes/default'; import pickerStyles from './pickerStyles'; +import {ScrollViewWithPickersContext} from '../ScrollViewWithPickers'; const propTypes = { /** Picker label */ @@ -91,8 +92,8 @@ const defaultProps = { {...(size === 'small' ? {width: styles.pickerSmall.icon.width, height: styles.pickerSmall.icon.height} : {})} /> ), - onBlur: () => {}, - innerRef: () => {}, + onBlur: () => { }, + innerRef: () => { }, }; class Picker extends PureComponent { @@ -149,6 +150,13 @@ class Picker extends PureComponent { render() { const hasError = !_.isEmpty(this.props.errorText); + + let scrollViewRef; + if (this.context != null + && this.context.scrollViewRef != null) { + scrollViewRef = this.context.scrollViewRef; + } + return ( <> @@ -201,6 +210,7 @@ class Picker extends PureComponent { Picker.propTypes = propTypes; Picker.defaultProps = defaultProps; +Picker.contextType = ScrollViewWithPickersContext; // eslint-disable-next-line react/jsx-props-no-spreading export default React.forwardRef((props, ref) => ); diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithPickers.js new file mode 100644 index 000000000000..144d61ef7e53 --- /dev/null +++ b/src/components/ScrollViewWithPickers.js @@ -0,0 +1,24 @@ +import React, {useRef} from 'react'; +import {ScrollView} from 'react-native'; + +// eslint-disable-next-line rulesdir/no-inline-named-export +export const ScrollViewWithPickersContext = React.createContext(); + +// eslint-disable-next-line react/forbid-foreign-prop-types +const propTypes = ScrollView.propTypes; + +export default function ScrollViewWithPickers(props) { + // eslint-disable-next-line react/destructuring-assignment + const {children, ...restProps} = props; + const scrollViewRef = useRef(null); + + return ( + // eslint-disable-next-line react/jsx-props-no-spreading + + + {children} + + + ); +} +ScrollViewWithPickers.propTypes = propTypes; diff --git a/src/pages/workspace/WorkspacePageWithSections.js b/src/pages/workspace/WorkspacePageWithSections.js index 0816075726f3..8306f97d5222 100644 --- a/src/pages/workspace/WorkspacePageWithSections.js +++ b/src/pages/workspace/WorkspacePageWithSections.js @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import {View, ScrollView} from 'react-native'; +import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import lodashGet from 'lodash/get'; import _ from 'underscore'; @@ -20,6 +20,7 @@ import withPolicy from './withPolicy'; import {withNetwork} from '../../components/OnyxProvider'; import networkPropTypes from '../../components/networkPropTypes'; import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoundView'; +import ScrollViewWithPickers from '../../components/ScrollViewWithPickers'; const propTypes = { shouldSkipVBBACall: PropTypes.bool, @@ -67,7 +68,7 @@ const propTypes = { }; const defaultProps = { - children: () => {}, + children: () => { }, user: {}, reimbursementAccount: {}, footer: null, @@ -121,7 +122,7 @@ class WorkspacePageWithSections extends React.Component { /> {this.props.shouldUseScrollView ? ( - @@ -130,7 +131,7 @@ class WorkspacePageWithSections extends React.Component { {this.props.children(hasVBA, policyID, isUsingECard)} - + ) : this.props.children(hasVBA, policyID, isUsingECard)} {this.props.footer} From 1bb5e425aefa2667612354dc5ed2a2f85c1966eb Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 14 Dec 2022 22:48:49 +0100 Subject: [PATCH 64/85] fix: simplify null check on scrollViewRef --- src/components/Picker/index.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/components/Picker/index.js b/src/components/Picker/index.js index 0f3ce9bb8325..241cf7c00335 100644 --- a/src/components/Picker/index.js +++ b/src/components/Picker/index.js @@ -151,12 +151,6 @@ class Picker extends PureComponent { render() { const hasError = !_.isEmpty(this.props.errorText); - let scrollViewRef; - if (this.context != null - && this.context.scrollViewRef != null) { - scrollViewRef = this.context.scrollViewRef; - } - return ( <> From 38d24f89cb92920d51389af880322ad5c95b25a3 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 14 Dec 2022 22:53:47 +0100 Subject: [PATCH 65/85] add comment for ScrollViewWithPickers component --- src/components/ScrollViewWithPickers.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithPickers.js index 144d61ef7e53..ae0b16a4702b 100644 --- a/src/components/ScrollViewWithPickers.js +++ b/src/components/ScrollViewWithPickers.js @@ -7,6 +7,13 @@ export const ScrollViewWithPickersContext = React.createContext(); // eslint-disable-next-line react/forbid-foreign-prop-types const propTypes = ScrollView.propTypes; +/* +* is a wrapper around that provides a ref to the . +* can be used as a direct replacement for +* if it contains one or more / components. +* Using this wrapper will automatically hadnle scrolling to the picker's +* when the picker modal is opened +*/ export default function ScrollViewWithPickers(props) { // eslint-disable-next-line react/destructuring-assignment const {children, ...restProps} = props; From e26e4e9839da793295488f8db09c62277c7a44d0 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 14 Dec 2022 22:57:22 +0100 Subject: [PATCH 66/85] convert ScrollViewWithPickers to class component --- src/components/ScrollViewWithPickers.js | 32 +++++++++++++++---------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithPickers.js index ae0b16a4702b..404fd23c717b 100644 --- a/src/components/ScrollViewWithPickers.js +++ b/src/components/ScrollViewWithPickers.js @@ -1,4 +1,4 @@ -import React, {useRef} from 'react'; +import React from 'react'; import {ScrollView} from 'react-native'; // eslint-disable-next-line rulesdir/no-inline-named-export @@ -14,18 +14,24 @@ const propTypes = ScrollView.propTypes; * Using this wrapper will automatically hadnle scrolling to the picker's * when the picker modal is opened */ -export default function ScrollViewWithPickers(props) { - // eslint-disable-next-line react/destructuring-assignment - const {children, ...restProps} = props; - const scrollViewRef = useRef(null); +class ScrollViewWithPickers extends React.Component { + setScrollViewRef(ref) { + this.scrollViewRef = ref; + } - return ( - // eslint-disable-next-line react/jsx-props-no-spreading - - - {children} - - - ); + render() { + // eslint-disable-next-line react/destructuring-assignment + const {children, ...propsWithoutChildren} = this.props; + return ( + // eslint-disable-next-line react/jsx-props-no-spreading + + + {children} + + + ); + } } ScrollViewWithPickers.propTypes = propTypes; + +export default ScrollViewWithPickers; From ed9a6cd2f79b7da45d624cd5dfed6e748e5fdaf4 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 14 Dec 2022 23:01:20 +0100 Subject: [PATCH 67/85] fix: formatting --- src/components/Picker/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Picker/index.js b/src/components/Picker/index.js index 241cf7c00335..48fd6a1fd765 100644 --- a/src/components/Picker/index.js +++ b/src/components/Picker/index.js @@ -92,8 +92,8 @@ const defaultProps = { {...(size === 'small' ? {width: styles.pickerSmall.icon.width, height: styles.pickerSmall.icon.height} : {})} /> ), - onBlur: () => { }, - innerRef: () => { }, + onBlur: () => {}, + innerRef: () => {}, }; class Picker extends PureComponent { From 6ba04a2bacdf3f65af842911893ad4224e510ec5 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 14 Dec 2022 23:04:15 +0100 Subject: [PATCH 68/85] fix: formatting --- src/pages/workspace/WorkspacePageWithSections.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspacePageWithSections.js b/src/pages/workspace/WorkspacePageWithSections.js index 8306f97d5222..3a22d264eab9 100644 --- a/src/pages/workspace/WorkspacePageWithSections.js +++ b/src/pages/workspace/WorkspacePageWithSections.js @@ -68,7 +68,7 @@ const propTypes = { }; const defaultProps = { - children: () => { }, + children: () => {}, user: {}, reimbursementAccount: {}, footer: null, From 480139de519e3d82ac9430e72426c2e2e7938003 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 14 Dec 2022 23:28:19 +0100 Subject: [PATCH 69/85] fix: scrollView ref passing --- src/components/ScrollViewWithPickers.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithPickers.js index 404fd23c717b..926926434ffa 100644 --- a/src/components/ScrollViewWithPickers.js +++ b/src/components/ScrollViewWithPickers.js @@ -15,8 +15,10 @@ const propTypes = ScrollView.propTypes; * when the picker modal is opened */ class ScrollViewWithPickers extends React.Component { - setScrollViewRef(ref) { - this.scrollViewRef = ref; + constructor(props) { + super(props); + + this.scrollViewRef = React.createRef(null); } render() { @@ -24,7 +26,7 @@ class ScrollViewWithPickers extends React.Component { const {children, ...propsWithoutChildren} = this.props; return ( // eslint-disable-next-line react/jsx-props-no-spreading - + {children} From 014cb6d6d61f617f8b29e19e1bf22a4a812af8b0 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 15 Dec 2022 00:06:21 +0100 Subject: [PATCH 70/85] pass scrollViewContentOffsetY to Picker --- src/components/Picker/index.js | 1 + src/components/ScrollViewWithPickers.js | 30 +++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/components/Picker/index.js b/src/components/Picker/index.js index 48fd6a1fd765..5524a707c793 100644 --- a/src/components/Picker/index.js +++ b/src/components/Picker/index.js @@ -194,6 +194,7 @@ class Picker extends PureComponent { this.props.innerRef(el); }} scrollViewRef={this.context && this.context.scrollViewRef} + scrollViewContentOffsetY={this.context && this.context.contentOffsetY} /> diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithPickers.js index 926926434ffa..5b4aa256fb31 100644 --- a/src/components/ScrollViewWithPickers.js +++ b/src/components/ScrollViewWithPickers.js @@ -18,16 +18,38 @@ class ScrollViewWithPickers extends React.Component { constructor(props) { super(props); + this.state = { + contentOffsetY: 0, + }; this.scrollViewRef = React.createRef(null); + + this.handleScroll = this.handleScroll.bind(this); + } + + handleScroll(event) { + if (this.props.onScroll) { + this.props.onScroll(event); + } + this.setState({contentOffsetY: event.nativeEvent.contentOffset.y}); } render() { // eslint-disable-next-line react/destructuring-assignment - const {children, ...propsWithoutChildren} = this.props; + const {children, scrollEventThrottle, ...propsWithoutChildrenAndScrollEventThrottle} = this.props; return ( - // eslint-disable-next-line react/jsx-props-no-spreading - - + + {children} From 2687bda58875249355c1c312e2f04a23a5838cb5 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 15 Dec 2022 00:09:31 +0100 Subject: [PATCH 71/85] update react-native-picker-select github commit in package-lock.json --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index e94120130e34..414ee7ec5bda 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35528,7 +35528,7 @@ }, "node_modules/react-native-picker-select": { "version": "8.0.4", - "resolved": "git+ssh://git@github.com/chrispader/expensify-react-native-picker-select.git#235fb856d07470cd3b550cb5c2aaeffd0d1631c8", + "resolved": "git+ssh://git@github.com/chrispader/expensify-react-native-picker-select.git#f72d50ccff5d2d229f7dee21d10293bbc203605a", "license": "MIT", "dependencies": { "lodash.isequal": "^4.5.0" @@ -69866,7 +69866,7 @@ "requires": {} }, "react-native-picker-select": { - "version": "git+ssh://git@github.com/chrispader/expensify-react-native-picker-select.git#235fb856d07470cd3b550cb5c2aaeffd0d1631c8", + "version": "git+ssh://git@github.com/chrispader/expensify-react-native-picker-select.git#f72d50ccff5d2d229f7dee21d10293bbc203605a", "from": "react-native-picker-select@git+https://github.com/chrispader/expensify-react-native-picker-select.git#fix/scroll-to-input-on-open", "requires": { "lodash.isequal": "^4.5.0" From c5f1d86670e6e8da91aa7536d81cb50e0362694b Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Thu, 15 Dec 2022 00:19:55 +0100 Subject: [PATCH 72/85] fix: add scrolling fix for other screens --- src/components/Form.js | 7 ++++--- src/components/ScrollViewWithPickers.js | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/Form.js b/src/components/Form.js index 25db26e182f5..7b0769f01686 100644 --- a/src/components/Form.js +++ b/src/components/Form.js @@ -1,6 +1,6 @@ import lodashGet from 'lodash/get'; import React from 'react'; -import {ScrollView, View} from 'react-native'; +import {View} from 'react-native'; import PropTypes from 'prop-types'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; @@ -10,6 +10,7 @@ import * as FormActions from '../libs/actions/FormActions'; import * as ErrorUtils from '../libs/ErrorUtils'; import styles from '../styles/styles'; import FormAlertWithSubmitButton from './FormAlertWithSubmitButton'; +import ScrollViewWithPickers from './ScrollViewWithPickers'; const propTypes = { /** A unique Onyx key identifying the form */ @@ -249,7 +250,7 @@ class Form extends React.Component { render() { return ( <> - )} - + ); } diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithPickers.js index 5b4aa256fb31..cafd1fd4aea9 100644 --- a/src/components/ScrollViewWithPickers.js +++ b/src/components/ScrollViewWithPickers.js @@ -43,6 +43,7 @@ class ScrollViewWithPickers extends React.Component { ref={this.scrollViewRef} onScroll={this.handleScroll} scrollEventThrottle={scrollEventThrottle || 16} + scrollToOverflowEnabled > Date: Fri, 16 Dec 2022 09:20:13 +0100 Subject: [PATCH 73/85] Update src/components/ScrollViewWithPickers.js Co-authored-by: Tim Golen --- src/components/ScrollViewWithPickers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithPickers.js index cafd1fd4aea9..c253a3203b70 100644 --- a/src/components/ScrollViewWithPickers.js +++ b/src/components/ScrollViewWithPickers.js @@ -11,7 +11,7 @@ const propTypes = ScrollView.propTypes; * is a wrapper around that provides a ref to the . * can be used as a direct replacement for * if it contains one or more / components. -* Using this wrapper will automatically hadnle scrolling to the picker's +* Using this wrapper will automatically handle scrolling to the picker's * when the picker modal is opened */ class ScrollViewWithPickers extends React.Component { From 1e6579373c4e0c328b6c1d1129a7c641f755d459 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Fri, 16 Dec 2022 09:23:13 +0100 Subject: [PATCH 74/85] rename scrollHandler --- src/components/ScrollViewWithPickers.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithPickers.js index c253a3203b70..5889778e4af0 100644 --- a/src/components/ScrollViewWithPickers.js +++ b/src/components/ScrollViewWithPickers.js @@ -23,10 +23,10 @@ class ScrollViewWithPickers extends React.Component { }; this.scrollViewRef = React.createRef(null); - this.handleScroll = this.handleScroll.bind(this); + this.handleScroll = this.setContextScrollPosition.bind(this); } - handleScroll(event) { + setContextScrollPosition(event) { if (this.props.onScroll) { this.props.onScroll(event); } @@ -41,7 +41,7 @@ class ScrollViewWithPickers extends React.Component { // eslint-disable-next-line react/jsx-props-no-spreading {...propsWithoutChildrenAndScrollEventThrottle} ref={this.scrollViewRef} - onScroll={this.handleScroll} + onScroll={this.setContextScrollPosition} scrollEventThrottle={scrollEventThrottle || 16} scrollToOverflowEnabled > From a89b139a4bbb1b5e164b9c6543b4a9ba409e300f Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 20 Dec 2022 19:54:08 +0100 Subject: [PATCH 75/85] chore: update react-native-picker-select dependency --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a3f8afdd6fb6..65138961023f 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "react-native-pdf": "^6.6.2", "react-native-performance": "^2.0.0", "react-native-permissions": "^3.0.1", - "react-native-picker-select": "git+https://github.com/chrispader/expensify-react-native-picker-select.git#fix/scroll-to-input-on-open", + "react-native-picker-select": "git+https://github.com/Expensify/expensify-react-native-picker-select.git", "react-native-plaid-link-sdk": "^7.2.0", "react-native-reanimated": "3.0.0-rc.6", "react-native-render-html": "6.3.1", From a9d4bf0abb84cbb38f6cc7e6d1880f2129092990 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 20 Dec 2022 19:55:43 +0100 Subject: [PATCH 76/85] chore: add commit sha --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 65138961023f..ad55dda3e9a4 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "react-native-pdf": "^6.6.2", "react-native-performance": "^2.0.0", "react-native-permissions": "^3.0.1", - "react-native-picker-select": "git+https://github.com/Expensify/expensify-react-native-picker-select.git", + "react-native-picker-select": "git+https://github.com/Expensify/expensify-react-native-picker-select.git#77cc9d42c474a693755941b10ee4c2d6f50e5346", "react-native-plaid-link-sdk": "^7.2.0", "react-native-reanimated": "3.0.0-rc.6", "react-native-render-html": "6.3.1", From 88047d05efb72c559651f90b0ea181671aaa3463 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 20 Dec 2022 19:57:19 +0100 Subject: [PATCH 77/85] fix: wrong repo name --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ad55dda3e9a4..9c8571dee354 100644 --- a/package.json +++ b/package.json @@ -104,7 +104,7 @@ "react-native-pdf": "^6.6.2", "react-native-performance": "^2.0.0", "react-native-permissions": "^3.0.1", - "react-native-picker-select": "git+https://github.com/Expensify/expensify-react-native-picker-select.git#77cc9d42c474a693755941b10ee4c2d6f50e5346", + "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#77cc9d42c474a693755941b10ee4c2d6f50e5346", "react-native-plaid-link-sdk": "^7.2.0", "react-native-reanimated": "3.0.0-rc.6", "react-native-render-html": "6.3.1", From 9ac0ac8d34d99286ffd02661f5eb02615a41eff2 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 20 Dec 2022 20:02:13 +0100 Subject: [PATCH 78/85] chore: update package-lock.json --- package-lock.json | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 414ee7ec5bda..c0009063b59c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -73,7 +73,7 @@ "react-native-pdf": "^6.6.2", "react-native-performance": "^2.0.0", "react-native-permissions": "^3.0.1", - "react-native-picker-select": "git+https://github.com/chrispader/expensify-react-native-picker-select.git#fix/scroll-to-input-on-open", + "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#77cc9d42c474a693755941b10ee4c2d6f50e5346", "react-native-plaid-link-sdk": "^7.2.0", "react-native-reanimated": "3.0.0-rc.6", "react-native-render-html": "6.3.1", @@ -35528,7 +35528,8 @@ }, "node_modules/react-native-picker-select": { "version": "8.0.4", - "resolved": "git+ssh://git@github.com/chrispader/expensify-react-native-picker-select.git#f72d50ccff5d2d229f7dee21d10293bbc203605a", + "resolved": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#77cc9d42c474a693755941b10ee4c2d6f50e5346", + "integrity": "sha512-KhadZYEWeoTQv/dj2tXpCRQvoY3L9tMGcVnopiYNSzlPdbnDzJUdvdDwf2bVdR3zQXrmHjzsYUVUJx3FFu6LAA==", "license": "MIT", "dependencies": { "lodash.isequal": "^4.5.0" @@ -69866,8 +69867,9 @@ "requires": {} }, "react-native-picker-select": { - "version": "git+ssh://git@github.com/chrispader/expensify-react-native-picker-select.git#f72d50ccff5d2d229f7dee21d10293bbc203605a", - "from": "react-native-picker-select@git+https://github.com/chrispader/expensify-react-native-picker-select.git#fix/scroll-to-input-on-open", + "version": "git+ssh://git@github.com/Expensify/react-native-picker-select.git#77cc9d42c474a693755941b10ee4c2d6f50e5346", + "integrity": "sha512-KhadZYEWeoTQv/dj2tXpCRQvoY3L9tMGcVnopiYNSzlPdbnDzJUdvdDwf2bVdR3zQXrmHjzsYUVUJx3FFu6LAA==", + "from": "react-native-picker-select@git+https://github.com/Expensify/react-native-picker-select.git#77cc9d42c474a693755941b10ee4c2d6f50e5346", "requires": { "lodash.isequal": "^4.5.0" } From de1c7e1b62e227334f7503c39ffd7194696d50c9 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Tue, 20 Dec 2022 20:15:03 +0100 Subject: [PATCH 79/85] fix: wrong this binding --- src/components/ScrollViewWithPickers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithPickers.js index 5889778e4af0..362a5775eef6 100644 --- a/src/components/ScrollViewWithPickers.js +++ b/src/components/ScrollViewWithPickers.js @@ -23,7 +23,7 @@ class ScrollViewWithPickers extends React.Component { }; this.scrollViewRef = React.createRef(null); - this.handleScroll = this.setContextScrollPosition.bind(this); + this.setContextScrollPosition = this.setContextScrollPosition.bind(this); } setContextScrollPosition(event) { From 23740e07cd6fdcf778777267aa0bebfbf5185d54 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 28 Dec 2022 14:58:02 +0100 Subject: [PATCH 80/85] fix: requested changes --- src/components/ScrollViewWithPickers.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithPickers.js index 362a5775eef6..fd8ff4b8a452 100644 --- a/src/components/ScrollViewWithPickers.js +++ b/src/components/ScrollViewWithPickers.js @@ -1,8 +1,9 @@ import React from 'react'; import {ScrollView} from 'react-native'; -// eslint-disable-next-line rulesdir/no-inline-named-export -export const ScrollViewWithPickersContext = React.createContext(); +const MIN_SMOOTH_SCROLL_EVENT_THROTTLE = 16; + +const ScrollContext = React.createContext(); // eslint-disable-next-line react/forbid-foreign-prop-types const propTypes = ScrollView.propTypes; @@ -14,7 +15,7 @@ const propTypes = ScrollView.propTypes; * Using this wrapper will automatically handle scrolling to the picker's * when the picker modal is opened */ -class ScrollViewWithPickers extends React.Component { +class ScrollViewWithScrollContext extends React.Component { constructor(props) { super(props); @@ -34,29 +35,28 @@ class ScrollViewWithPickers extends React.Component { } render() { - // eslint-disable-next-line react/destructuring-assignment - const {children, scrollEventThrottle, ...propsWithoutChildrenAndScrollEventThrottle} = this.props; return ( - - {children} - + {this.props.children} + ); } } -ScrollViewWithPickers.propTypes = propTypes; +ScrollViewWithScrollContext.propTypes = propTypes; -export default ScrollViewWithPickers; +export default ScrollViewWithScrollContext; +module.exports.ScrollViewWithPickersContext = ScrollContext; From 858b7a7b7d5f88df6e228d62e0bf60285f108d97 Mon Sep 17 00:00:00 2001 From: Christoph Pader Date: Wed, 28 Dec 2022 15:39:20 +0100 Subject: [PATCH 81/85] fix: rename ScrollViewWithContext component everywhere --- src/components/Form.js | 6 +++--- src/components/Picker/index.js | 4 ++-- ...ViewWithPickers.js => ScrollViewWithContext.js} | 14 ++++++++------ src/pages/workspace/WorkspacePageWithSections.js | 6 +++--- 4 files changed, 16 insertions(+), 14 deletions(-) rename src/components/{ScrollViewWithPickers.js => ScrollViewWithContext.js} (83%) diff --git a/src/components/Form.js b/src/components/Form.js index 7b0769f01686..f3f4a5a0cfb2 100644 --- a/src/components/Form.js +++ b/src/components/Form.js @@ -10,7 +10,7 @@ import * as FormActions from '../libs/actions/FormActions'; import * as ErrorUtils from '../libs/ErrorUtils'; import styles from '../styles/styles'; import FormAlertWithSubmitButton from './FormAlertWithSubmitButton'; -import ScrollViewWithPickers from './ScrollViewWithPickers'; +import ScrollViewWithContext from './ScrollViewWithContext'; const propTypes = { /** A unique Onyx key identifying the form */ @@ -250,7 +250,7 @@ class Form extends React.Component { render() { return ( <> - )} - + ); } diff --git a/src/components/Picker/index.js b/src/components/Picker/index.js index 5524a707c793..5fa626751984 100644 --- a/src/components/Picker/index.js +++ b/src/components/Picker/index.js @@ -10,7 +10,7 @@ import Text from '../Text'; import styles from '../../styles/styles'; import themeColors from '../../styles/themes/default'; import pickerStyles from './pickerStyles'; -import {ScrollViewWithPickersContext} from '../ScrollViewWithPickers'; +import {ScrollContext} from '../ScrollViewWithContext'; const propTypes = { /** Picker label */ @@ -205,7 +205,7 @@ class Picker extends PureComponent { Picker.propTypes = propTypes; Picker.defaultProps = defaultProps; -Picker.contextType = ScrollViewWithPickersContext; +Picker.contextType = ScrollContext; // eslint-disable-next-line react/jsx-props-no-spreading export default React.forwardRef((props, ref) => ); diff --git a/src/components/ScrollViewWithPickers.js b/src/components/ScrollViewWithContext.js similarity index 83% rename from src/components/ScrollViewWithPickers.js rename to src/components/ScrollViewWithContext.js index fd8ff4b8a452..6d6c74c33245 100644 --- a/src/components/ScrollViewWithPickers.js +++ b/src/components/ScrollViewWithContext.js @@ -9,13 +9,13 @@ const ScrollContext = React.createContext(); const propTypes = ScrollView.propTypes; /* -* is a wrapper around that provides a ref to the . -* can be used as a direct replacement for +* is a wrapper around that provides a ref to the . +* can be used as a direct replacement for * if it contains one or more / components. * Using this wrapper will automatically handle scrolling to the picker's * when the picker modal is opened */ -class ScrollViewWithScrollContext extends React.Component { +class ScrollViewWithContext extends React.Component { constructor(props) { super(props); @@ -56,7 +56,9 @@ class ScrollViewWithScrollContext extends React.Component { ); } } -ScrollViewWithScrollContext.propTypes = propTypes; +ScrollViewWithContext.propTypes = propTypes; -export default ScrollViewWithScrollContext; -module.exports.ScrollViewWithPickersContext = ScrollContext; +export default ScrollViewWithContext; +export { + ScrollContext, +}; diff --git a/src/pages/workspace/WorkspacePageWithSections.js b/src/pages/workspace/WorkspacePageWithSections.js index 3a22d264eab9..cfe5cc40aa4b 100644 --- a/src/pages/workspace/WorkspacePageWithSections.js +++ b/src/pages/workspace/WorkspacePageWithSections.js @@ -20,7 +20,7 @@ import withPolicy from './withPolicy'; import {withNetwork} from '../../components/OnyxProvider'; import networkPropTypes from '../../components/networkPropTypes'; import FullPageNotFoundView from '../../components/BlockingViews/FullPageNotFoundView'; -import ScrollViewWithPickers from '../../components/ScrollViewWithPickers'; +import ScrollViewWithContext from '../../components/ScrollViewWithContext'; const propTypes = { shouldSkipVBBACall: PropTypes.bool, @@ -122,7 +122,7 @@ class WorkspacePageWithSections extends React.Component { /> {this.props.shouldUseScrollView ? ( - @@ -131,7 +131,7 @@ class WorkspacePageWithSections extends React.Component { {this.props.children(hasVBA, policyID, isUsingECard)} - + ) : this.props.children(hasVBA, policyID, isUsingECard)} {this.props.footer} From cafc2db0f89d2760b30602efc69ac09e3d89f028 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Wed, 28 Dec 2022 18:45:24 +0000 Subject: [PATCH 82/85] Update version to 1.2.45-0 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 4 ++-- ios/NewExpensifyTests/Info.plist | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index a6af83b1b978..f8e15f523d45 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -156,8 +156,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001024400 - versionName "1.2.44-0" + versionCode 1001024500 + versionName "1.2.45-0" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 89ddc10e5e94..29b28ed12972 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.2.44 + 1.2.45 CFBundleSignature ???? CFBundleURLTypes @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.44.0 + 1.2.45.0 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index d5e076f3af3f..7ddd3c276223 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.2.44 + 1.2.45 CFBundleSignature ???? CFBundleVersion - 1.2.44.0 + 1.2.45.0 diff --git a/package-lock.json b/package-lock.json index c0009063b59c..f211abba92bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.44-0", + "version": "1.2.45-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.44-0", + "version": "1.2.45-0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 9c8571dee354..7e74ca6ae71c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.44-0", + "version": "1.2.45-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.", From f0dea50a1bee780bc68a682b78ead3e094df194a Mon Sep 17 00:00:00 2001 From: Andre Fonseca Date: Thu, 29 Dec 2022 14:24:31 +0000 Subject: [PATCH 83/85] Update src/pages/iou/IOUDetailsModal.js Co-authored-by: Youssef Lourayad --- src/pages/iou/IOUDetailsModal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/IOUDetailsModal.js b/src/pages/iou/IOUDetailsModal.js index eda527f35aa8..f5144a1ba1d0 100644 --- a/src/pages/iou/IOUDetailsModal.js +++ b/src/pages/iou/IOUDetailsModal.js @@ -137,7 +137,7 @@ class IOUDetailsModal extends Component { } } - // Finds the if there is a reportAction pending for this IOU + // Finds if there is a reportAction pending for this IOU findPendingAction() { return _.find(this.props.reportActions, reportAction => reportAction.originalMessage && Number(reportAction.originalMessage.IOUReportID) === Number(this.props.route.params.iouReportID) From a71021398487b743326a230bfda91aaf5ad1c250 Mon Sep 17 00:00:00 2001 From: daraksha Date: Thu, 29 Dec 2022 21:32:48 +0530 Subject: [PATCH 84/85] use isEmpty --- src/pages/workspace/WorkspaceMembersPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceMembersPage.js b/src/pages/workspace/WorkspaceMembersPage.js index 92ac6559f895..65e7d556c575 100644 --- a/src/pages/workspace/WorkspaceMembersPage.js +++ b/src/pages/workspace/WorkspaceMembersPage.js @@ -257,7 +257,7 @@ class WorkspaceMembersPage extends React.Component { this.dismissError(item)} pendingAction={item.pendingAction} errors={item.errors}> this.willTooltipShowForLogin(item.login, true)} onHoverOut={() => this.setState({showTooltipForLogin: ''})}> this.toggleUser(item.login, item.pendingAction)} activeOpacity={0.7} > From 5585074cad69fed441d8225acd20ea81e7082765 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Thu, 29 Dec 2022 19:19:06 +0000 Subject: [PATCH 85/85] Update version to 1.2.46-0 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 4 ++-- ios/NewExpensifyTests/Info.plist | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index f8e15f523d45..d9113769a1db 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -156,8 +156,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001024500 - versionName "1.2.45-0" + versionCode 1001024600 + versionName "1.2.46-0" buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() if (isNewArchitectureEnabled()) { diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 29b28ed12972..7f282a292bd5 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.2.45 + 1.2.46 CFBundleSignature ???? CFBundleURLTypes @@ -30,7 +30,7 @@ CFBundleVersion - 1.2.45.0 + 1.2.46.0 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 7ddd3c276223..96a597740774 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -15,10 +15,10 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 1.2.45 + 1.2.46 CFBundleSignature ???? CFBundleVersion - 1.2.45.0 + 1.2.46.0 diff --git a/package-lock.json b/package-lock.json index f211abba92bb..a3ac89f9a689 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.2.45-0", + "version": "1.2.46-0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.2.45-0", + "version": "1.2.46-0", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index a150a56136c4..c589aa337ed0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.2.45-0", + "version": "1.2.46-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.",