From 783d0b8dff602f026271187459e1ae3be569b0ae Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Tue, 1 Aug 2023 23:13:22 +0100 Subject: [PATCH 001/125] Migrate SignInPageForm/index.js to function component --- src/components/SignInPageForm/index.js | 69 ++++++++++++-------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/src/components/SignInPageForm/index.js b/src/components/SignInPageForm/index.js index 21df710d2aa5..0de69664230e 100644 --- a/src/components/SignInPageForm/index.js +++ b/src/components/SignInPageForm/index.js @@ -1,48 +1,43 @@ -import React from 'react'; +import React, {useEffect, useRef} from 'react'; import FormElement from '../FormElement'; -class Form extends React.Component { - constructor(props) { - super(props); +function Form(props) { + const form = useRef(null); - this.preventFormDefault = this.preventFormDefault.bind(this); - } - - componentDidMount() { - if (!this.form) { - return; - } - - // Password Managers need these attributes to be able to identify the form elements properly. - this.form.setAttribute('method', 'post'); - this.form.setAttribute('action', '/'); + const preventFormDefault = (event) => { + // When enter is pressed form is submitted to action url (POST /). + // As we are using controlled component, we need to disable it here. + event.preventDefault(); + }; - this.form.addEventListener('submit', this.preventFormDefault); - } + useEffect(() => { + const formCurrent = form.current; - componentWillUnmount() { - if (!this.form) { + if (!formCurrent) { return; } - this.form.removeEventListener('submit', this.preventFormDefault); - } - - preventFormDefault(event) { - // When enter is pressed form is submitted to action url (POST /). - // As we are using controlled component, we need to disable it here. - event.preventDefault(); - } - - render() { - return ( - (this.form = el)} - // eslint-disable-next-line react/jsx-props-no-spreading - {...this.props} - /> - ); - } + formCurrent.setAttribute('method', 'post'); + formCurrent.setAttribute('action', '/'); + formCurrent.addEventListener('submit', preventFormDefault); + + return () => { + if (!formCurrent) { + return; + } + formCurrent.removeEventListener('submit', preventFormDefault); + }; + }, []); + + return ( + + ); } +Form.displayName = 'Form'; + export default Form; From f7242b99247e7126404d6d65d9abdf76ca2881fb Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Tue, 15 Aug 2023 16:47:04 +0100 Subject: [PATCH 002/125] merge conflicts resolved --- a.sh | 14 ++++++++++++++ src/components/SignInPageForm/index.js | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 a.sh diff --git a/a.sh b/a.sh new file mode 100644 index 000000000000..8a6ff7b3612a --- /dev/null +++ b/a.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +while true; do + log="$HOME/.npm/_logs/`ls $HOME/.npm/_logs/ | tail -n 1`" + echo "log: $log" + for path in `cat "$log" | grep 'ENOTEMPTY' | grep -oE "[^']+node_modules[^']+"`; do + echo "removing $path" + rm -rf "$path" + done + if npm install; then + break + fi +done \ No newline at end of file diff --git a/src/components/SignInPageForm/index.js b/src/components/SignInPageForm/index.js index c12aa5934d42..9261ca860712 100644 --- a/src/components/SignInPageForm/index.js +++ b/src/components/SignInPageForm/index.js @@ -18,7 +18,7 @@ function Form(props) { } // Prevent the browser from applying its own validation, which affects the email input - this.form.setAttribute('novalidate', ''); + formCurrent.setAttribute('novalidate', ''); formCurrent.setAttribute('method', 'post'); formCurrent.setAttribute('action', '/'); From 2aa27263ea533d75c818b77bff85c35e0c13d535 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Tue, 15 Aug 2023 16:51:05 +0100 Subject: [PATCH 003/125] Remove mistakenly added file from commit --- a.sh | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 a.sh diff --git a/a.sh b/a.sh deleted file mode 100644 index 8a6ff7b3612a..000000000000 --- a/a.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -set -e - -while true; do - log="$HOME/.npm/_logs/`ls $HOME/.npm/_logs/ | tail -n 1`" - echo "log: $log" - for path in `cat "$log" | grep 'ENOTEMPTY' | grep -oE "[^']+node_modules[^']+"`; do - echo "removing $path" - rm -rf "$path" - done - if npm install; then - break - fi -done \ No newline at end of file From e006ebb80bda0b475fee19ed5ecc05f9a781de36 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Tue, 15 Aug 2023 17:00:18 +0100 Subject: [PATCH 004/125] add comment --- src/components/SignInPageForm/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/SignInPageForm/index.js b/src/components/SignInPageForm/index.js index 9261ca860712..a1c67623a3f9 100644 --- a/src/components/SignInPageForm/index.js +++ b/src/components/SignInPageForm/index.js @@ -20,6 +20,7 @@ function Form(props) { // Prevent the browser from applying its own validation, which affects the email input formCurrent.setAttribute('novalidate', ''); + // Password Managers need these attributes to be able to identify the form elements properly. formCurrent.setAttribute('method', 'post'); formCurrent.setAttribute('action', '/'); formCurrent.addEventListener('submit', preventFormDefault); From ec137d9c0a1ad6ffb570982a310428e5a5e335b6 Mon Sep 17 00:00:00 2001 From: Rayane Djouah <77965000+rayane-djouah@users.noreply.github.com> Date: Mon, 21 Aug 2023 12:42:56 +0000 Subject: [PATCH 005/125] moving preventFormDefault function out of component --- src/components/SignInPageForm/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/SignInPageForm/index.js b/src/components/SignInPageForm/index.js index a1c67623a3f9..5a1e5a62ff23 100644 --- a/src/components/SignInPageForm/index.js +++ b/src/components/SignInPageForm/index.js @@ -1,15 +1,15 @@ import React, {useEffect, useRef} from 'react'; import FormElement from '../FormElement'; +const preventFormDefault = (event) => { + // When enter is pressed form is submitted to action url (POST /). + // As we are using controlled component, we need to disable it here. + event.preventDefault(); +}; + function Form(props) { const form = useRef(null); - const preventFormDefault = (event) => { - // When enter is pressed form is submitted to action url (POST /). - // As we are using controlled component, we need to disable it here. - event.preventDefault(); - }; - useEffect(() => { const formCurrent = form.current; From a35200e541466319f17876196d9dcd05c53fa2f9 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Tue, 22 Aug 2023 16:15:18 +0200 Subject: [PATCH 006/125] implement get option tree helper --- src/CONST.js | 2 ++ src/libs/OptionsListUtils.js | 21 ++++++++++++++ tests/unit/OptionsListUtilsTest.js | 45 ++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/src/CONST.js b/src/CONST.js index 6d7d39cc5f7e..72537304ecd4 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -2576,6 +2576,8 @@ const CONST = { NAVIGATE: 'NAVIGATE', }, }, + INDENTS: ' ', + PARENT_CHILD_SEPARATOR: ': ', }; export default CONST; diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index a5185d8352aa..6773122a5d9b 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -878,6 +878,26 @@ function getOptions( }; } +/** + * Build the options for the tree hierarchy via indents + * + * @param {Array} options - an initial strings array + * @returns {Array} + */ +function getOptionTree(options) { + const optionCollection = new Set(); + + _.each(options, (option) => { + option.split(CONST.PARENT_CHILD_SEPARATOR).forEach((optionName, index) => { + const indents = _.times(index, () => CONST.INDENTS).join(''); + + optionCollection.add(`${indents}${optionName}`); + }); + }); + + return Array.from(optionCollection); +} + /** * Build the options for the Search view * @@ -1104,4 +1124,5 @@ export { isSearchStringMatch, shouldOptionShowTooltip, getLastMessageTextForReport, + getOptionTree, }; diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index 1c176bdb1ce4..0c5801cfbb0e 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -628,4 +628,49 @@ describe('OptionsListUtils', () => { expect(results.personalDetails.length).toBe(1); expect(results.personalDetails[0].text).toBe('Spider-Man'); }); + + it('getOptionTree', () => { + const categories = [ + 'Taxi', + 'Restaurant', + 'Cafe', + 'Food: Meat', + 'Food: Milk', + 'Food: Fruits', + 'Food: Vegetables', + 'Cars: Audi', + 'Cars: BMW', + 'Cars: Mercedes-Benz', + 'Medical', + 'Travel: Meals: Breakfast', + 'Travel: Meals: Dinner', + 'Travel: Meals: Lunch', + 'Plain', + 'Health', + ]; + const result = [ + 'Taxi', + 'Restaurant', + 'Cafe', + 'Food', + ' Meat', + ' Milk', + ' Fruits', + ' Vegetables', + 'Cars', + ' Audi', + ' BMW', + ' Mercedes-Benz', + 'Medical', + 'Travel', + ' Meals', + ' Breakfast', + ' Dinner', + ' Lunch', + 'Plain', + 'Health', + ]; + + expect(OptionsListUtils.getOptionTree(categories)).toStrictEqual(result); + }); }); From 22c7397eee80ac20decb459c9aeb09a87807d0e5 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 23 Aug 2023 15:50:42 +0200 Subject: [PATCH 007/125] extend getOptionTree --- src/libs/OptionsListUtils.js | 27 ++- tests/unit/OptionsListUtilsTest.js | 275 +++++++++++++++++++++++++---- 2 files changed, 257 insertions(+), 45 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 5f38bb256e7a..84e95174dea6 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -882,21 +882,36 @@ function getOptions( /** * Build the options for the tree hierarchy via indents * - * @param {Array} options - an initial strings array - * @returns {Array} + * @param {Object[]} options - an initial strings array + * @param {Boolean} options[].enabled - a flag to enable/disable option in a list + * @param {String} options[].name - a name of an option + * @returns {Array} */ function getOptionTree(options) { - const optionCollection = new Set(); + const optionCollection = new Map(); _.each(options, (option) => { - option.split(CONST.PARENT_CHILD_SEPARATOR).forEach((optionName, index) => { + option.name.split(CONST.PARENT_CHILD_SEPARATOR).forEach((optionName, index, array) => { const indents = _.times(index, () => CONST.INDENTS).join(''); + const isChild = array.length - 1 === index; - optionCollection.add(`${indents}${optionName}`); + if (optionCollection.has(optionName)) { + return; + } + + optionCollection.set(optionName, { + text: `${indents}${optionName}`, + keyForList: optionName, + searchText: optionName, + tooltipText: optionName, + isDisabled: isChild ? !option.enabled : true, + }); }); }); - return Array.from(optionCollection); + return Array.from(optionCollection, ([, value]) => { + return value; + }); } /** diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index 2a5f8648cfbf..b6151e79e26b 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -652,46 +652,243 @@ describe('OptionsListUtils', () => { expect(results.personalDetails[0].text).toBe('Spider-Man'); }); - it('getOptionTree', () => { - const categories = [ - 'Taxi', - 'Restaurant', - 'Cafe', - 'Food: Meat', - 'Food: Milk', - 'Food: Fruits', - 'Food: Vegetables', - 'Cars: Audi', - 'Cars: BMW', - 'Cars: Mercedes-Benz', - 'Medical', - 'Travel: Meals: Breakfast', - 'Travel: Meals: Dinner', - 'Travel: Meals: Lunch', - 'Plain', - 'Health', - ]; + it('getOptionTree()', () => { + const categories = { + Taxi: { + enabled: false, + name: 'Taxi', + }, + Restaurant: { + enabled: true, + name: 'Restaurant', + }, + Food: { + enabled: true, + name: 'Food', + }, + 'Food: Meat': { + enabled: true, + name: 'Food: Meat', + }, + 'Food: Milk': { + enabled: true, + name: 'Food: Milk', + }, + 'Food: Vegetables': { + enabled: false, + name: 'Food: Vegetables', + }, + 'Cars: Audi': { + enabled: true, + name: 'Cars: Audi', + }, + 'Cars: BMW': { + enabled: false, + name: 'Cars: BMW', + }, + 'Cars: Mercedes-Benz': { + enabled: true, + name: 'Cars: Mercedes-Benz', + }, + Medical: { + enabled: false, + name: 'Medical', + }, + 'Travel: Meals': { + enabled: true, + name: 'Travel: Meals', + }, + 'Travel: Meals: Breakfast': { + enabled: true, + name: 'Travel: Meals: Breakfast', + }, + 'Travel: Meals: Dinner': { + enabled: false, + name: 'Travel: Meals: Dinner', + }, + 'Travel: Meals: Lunch': { + enabled: true, + name: 'Travel: Meals: Lunch', + }, + Plain: { + enabled: true, + name: 'Plain', + }, + Health: { + enabled: true, + name: 'Health', + }, + 'A: B: C': { + enabled: true, + name: 'A: B: C', + }, + 'A: B: C: D: E': { + enabled: true, + name: 'A: B: C: D: E', + }, + }; const result = [ - 'Taxi', - 'Restaurant', - 'Cafe', - 'Food', - ' Meat', - ' Milk', - ' Fruits', - ' Vegetables', - 'Cars', - ' Audi', - ' BMW', - ' Mercedes-Benz', - 'Medical', - 'Travel', - ' Meals', - ' Breakfast', - ' Dinner', - ' Lunch', - 'Plain', - 'Health', + { + text: 'Taxi', + keyForList: 'Taxi', + searchText: 'Taxi', + tooltipText: 'Taxi', + isDisabled: true, + }, + { + text: 'Restaurant', + keyForList: 'Restaurant', + searchText: 'Restaurant', + tooltipText: 'Restaurant', + isDisabled: false, + }, + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + }, + { + text: ' Meat', + keyForList: 'Meat', + searchText: 'Meat', + tooltipText: 'Meat', + isDisabled: false, + }, + { + text: ' Milk', + keyForList: 'Milk', + searchText: 'Milk', + tooltipText: 'Milk', + isDisabled: false, + }, + { + text: ' Vegetables', + keyForList: 'Vegetables', + searchText: 'Vegetables', + tooltipText: 'Vegetables', + isDisabled: true, + }, + { + text: 'Cars', + keyForList: 'Cars', + searchText: 'Cars', + tooltipText: 'Cars', + isDisabled: true, + }, + { + text: ' Audi', + keyForList: 'Audi', + searchText: 'Audi', + tooltipText: 'Audi', + isDisabled: false, + }, + { + text: ' BMW', + keyForList: 'BMW', + searchText: 'BMW', + tooltipText: 'BMW', + isDisabled: true, + }, + { + text: ' Mercedes-Benz', + keyForList: 'Mercedes-Benz', + searchText: 'Mercedes-Benz', + tooltipText: 'Mercedes-Benz', + isDisabled: false, + }, + { + text: 'Medical', + keyForList: 'Medical', + searchText: 'Medical', + tooltipText: 'Medical', + isDisabled: true, + }, + { + text: 'Travel', + keyForList: 'Travel', + searchText: 'Travel', + tooltipText: 'Travel', + isDisabled: true, + }, + { + text: ' Meals', + keyForList: 'Meals', + searchText: 'Meals', + tooltipText: 'Meals', + isDisabled: false, + }, + { + text: ' Breakfast', + keyForList: 'Breakfast', + searchText: 'Breakfast', + tooltipText: 'Breakfast', + isDisabled: false, + }, + { + text: ' Dinner', + keyForList: 'Dinner', + searchText: 'Dinner', + tooltipText: 'Dinner', + isDisabled: true, + }, + { + text: ' Lunch', + keyForList: 'Lunch', + searchText: 'Lunch', + tooltipText: 'Lunch', + isDisabled: false, + }, + { + text: 'Plain', + keyForList: 'Plain', + searchText: 'Plain', + tooltipText: 'Plain', + isDisabled: false, + }, + { + text: 'Health', + keyForList: 'Health', + searchText: 'Health', + tooltipText: 'Health', + isDisabled: false, + }, + { + text: 'A', + keyForList: 'A', + searchText: 'A', + tooltipText: 'A', + isDisabled: true, + }, + { + text: ' B', + keyForList: 'B', + searchText: 'B', + tooltipText: 'B', + isDisabled: true, + }, + { + text: ' C', + keyForList: 'C', + searchText: 'C', + tooltipText: 'C', + isDisabled: false, + }, + { + text: ' D', + keyForList: 'D', + searchText: 'D', + tooltipText: 'D', + isDisabled: true, + }, + { + text: ' E', + keyForList: 'E', + searchText: 'E', + tooltipText: 'E', + isDisabled: false, + }, ]; expect(OptionsListUtils.getOptionTree(categories)).toStrictEqual(result); From 1b9429e2610066d950335ce2a2dd664a2c01cc26 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 23 Aug 2023 15:57:45 +0200 Subject: [PATCH 008/125] use object instead of Map --- src/libs/OptionsListUtils.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 84e95174dea6..0bed5a7745c1 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -888,30 +888,28 @@ function getOptions( * @returns {Array} */ function getOptionTree(options) { - const optionCollection = new Map(); + const optionCollection = {}; _.each(options, (option) => { option.name.split(CONST.PARENT_CHILD_SEPARATOR).forEach((optionName, index, array) => { const indents = _.times(index, () => CONST.INDENTS).join(''); const isChild = array.length - 1 === index; - if (optionCollection.has(optionName)) { + if (_.has(optionCollection, optionName)) { return; } - optionCollection.set(optionName, { + optionCollection[optionName] = { text: `${indents}${optionName}`, keyForList: optionName, searchText: optionName, tooltipText: optionName, isDisabled: isChild ? !option.enabled : true, - }); + }; }); }); - return Array.from(optionCollection, ([, value]) => { - return value; - }); + return _.values(optionCollection); } /** From cb03605468d8bccba4c8f169e2ce15e85570a6d7 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Wed, 23 Aug 2023 17:47:11 +0200 Subject: [PATCH 009/125] extend get options for categories --- src/CONST.js | 1 + src/libs/OptionsListUtils.js | 65 +++++++++++++++++++++- tests/unit/OptionsListUtilsTest.js | 89 ++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 1 deletion(-) diff --git a/src/CONST.js b/src/CONST.js index fb10b09590bb..8ac4a0e99649 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -2593,6 +2593,7 @@ const CONST = { }, INDENTS: ' ', PARENT_CHILD_SEPARATOR: ': ', + CATEGORY_LIST_THRESHOLD: 8, }; export default CONST; diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 0bed5a7745c1..5260cc200938 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -618,6 +618,9 @@ function getOptions( includeMoneyRequests = false, excludeUnknownUsers = false, includeP2P = true, + includeCategories = false, + categories = {}, + recentlyUsedCategories = {}, }, ) { if (!isPersonalDetailsReady(personalDetails)) { @@ -626,6 +629,7 @@ function getOptions( personalDetails: [], userToInvite: null, currentUserOption: null, + categoryOptions: [], }; } @@ -871,11 +875,52 @@ function getOptions( ); } + const categoryOptions = []; + + if (includeCategories) { + const categoriesAmount = _.size(categories); + + if (categoriesAmount < CONST.CATEGORY_LIST_THRESHOLD) { + categoryOptions.push({ + title: '', // All + data: getOptionTree(categories), + }); + } else if (!_.isEmpty(searchInputValue)) { + categoryOptions.push({ + title: '', // All + data: getOptionTree(_.filter(categories, (category) => category.name.toLowerCase().includes(searchInputValue.toLowerCase()))), + }); + } else { + recentlyUsedCategories = _.without(recentlyUsedCategories, selectedOptions); + categories = _.without(categories, selectedOptions); + + if (!_.isEmpty(selectedOptions)) { + categoryOptions.push({ + title: '', // Selected + data: getOptionTree(selectedOptions), + }); + } + + if (!_.isEmpty(recentlyUsedCategories)) { + categoryOptions.push({ + title: 'Recent', + data: getOptionTree(recentlyUsedCategories.slice(0, maxRecentReportsToShow)), + }); + } + + categoryOptions.push({ + title: 'All', + data: getOptionTree(categories), + }); + } + } + return { personalDetails: personalDetailsOptions, recentReports: recentReportOptions, userToInvite, currentUserOption, + categoryOptions, }; } @@ -990,9 +1035,24 @@ function getIOUConfirmationOptionsFromParticipants(participants, amountText) { * @param {Array} [excludeLogins] * @param {Boolean} [includeOwnedWorkspaceChats] * @param {boolean} [includeP2P] + * @param {boolean} [includeCategories] + * @param {Array} [categories] + * @param {Array} [recentlyUsedCategories] * @returns {Object} */ -function getNewChatOptions(reports, personalDetails, betas = [], searchValue = '', selectedOptions = [], excludeLogins = [], includeOwnedWorkspaceChats = false, includeP2P = true) { +function getNewChatOptions( + reports, + personalDetails, + betas = [], + searchValue = '', + selectedOptions = [], + excludeLogins = [], + includeOwnedWorkspaceChats = false, + includeP2P = true, + includeCategories = false, + categories = [], + recentlyUsedCategories = [], +) { return getOptions(reports, personalDetails, { betas, searchInputValue: searchValue.trim(), @@ -1003,6 +1063,9 @@ function getNewChatOptions(reports, personalDetails, betas = [], searchValue = ' excludeLogins, includeOwnedWorkspaceChats, includeP2P, + includeCategories, + categories, + recentlyUsedCategories, }); } diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index b6151e79e26b..af1ad42524eb 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -652,6 +652,95 @@ describe('OptionsListUtils', () => { expect(results.personalDetails[0].text).toBe('Spider-Man'); }); + it('getNewChatOptions() for categories', () => { + const smallCategoriesList = { + Taxi: { + enabled: false, + name: 'Taxi', + }, + Restaurant: { + enabled: true, + name: 'Restaurant', + }, + Food: { + enabled: true, + name: 'Food', + }, + 'Food: Meat': { + enabled: true, + name: 'Food: Meat', + }, + }; + const smallResultList = [ + { + title: '', + data: [ + { + text: 'Taxi', + keyForList: 'Taxi', + searchText: 'Taxi', + tooltipText: 'Taxi', + isDisabled: true, + }, + { + text: 'Restaurant', + keyForList: 'Restaurant', + searchText: 'Restaurant', + tooltipText: 'Restaurant', + isDisabled: false, + }, + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + }, + { + text: ' Meat', + keyForList: 'Meat', + searchText: 'Meat', + tooltipText: 'Meat', + isDisabled: false, + }, + ], + }, + ]; + // const smallSearchResultList = []; + // const smallWrongSearchResultList = []; + // const largeCategoriesList = {}; + // const largeResultList = []; + // const largeSearchResultList = []; + // const largeWrongSearchResultList = []; + // const search = 'Food'; + const emptySearch = ''; + // const wrongSearch = 'bla bla'; + + const smallResult = OptionsListUtils.getNewChatOptions(REPORTS, PERSONAL_DETAILS, [], emptySearch, [], [], false, false, true, smallCategoriesList, []); + + expect(smallResult.categoryOptions).toStrictEqual(smallResultList); + + // const largeResult = OptionsListUtils.getNewChatOptions(largeCategoriesList); + + // expect(largeResult.categoryOptions).toStrictEqual(largeResultList); + + // const smallSearchResult = OptionsListUtils.getNewChatOptions(smallCategoriesList); + + // expect(smallSearchResult.categoryOptions).toStrictEqual(smallSearchResultList); + + // const smallWrongSearchResult = OptionsListUtils.getNewChatOptions(smallCategoriesList); + + // expect(smallWrongSearchResult.categoryOptions).toStrictEqual(smallWrongSearchResultList); + + // const largeSearchResult = OptionsListUtils.getNewChatOptions(largeCategoriesList); + + // expect(largeSearchResult.categoryOptions).toStrictEqual(largeSearchResultList); + + // const largeWrongSearchResult = OptionsListUtils.getNewChatOptions(largeSearchResultList); + + // expect(largeWrongSearchResult.categoryOptions).toStrictEqual(largeWrongSearchResultList); + }); + it('getOptionTree()', () => { const categories = { Taxi: { From 2b22f9c2ecbc6dd0acf56926df10ed56d3d0c34c Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 24 Aug 2023 13:27:27 +0200 Subject: [PATCH 010/125] implement category sections --- src/libs/OptionsListUtils.js | 186 +++++++++------ tests/unit/OptionsListUtilsTest.js | 369 ++++++++++++++++++++++++++--- 2 files changed, 447 insertions(+), 108 deletions(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 5260cc200938..121fa0818dff 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -585,6 +585,57 @@ function isCurrentUser(userDetails) { return _.some(_.keys(loginList), (login) => login.toLowerCase() === userDetailsLogin.toLowerCase()); } +/** + * Build the options for the tree hierarchy via indents + * + * @param {Object[]} options - an initial strings array + * @param {Boolean} options[].enabled - a flag to enable/disable option in a list + * @param {String} options[].name - a name of an option + * @param {Boolean} [isSearch] - a flag to determine if search is active + * @returns {Array} + */ +function getOptionTree(options, isSearch = false) { + const optionCollection = {}; + + _.each(options, (option) => { + if (isSearch) { + if (_.has(optionCollection, option.name)) { + return; + } + + optionCollection[option.name] = { + text: option.name, + keyForList: option.name, + searchText: option.name, + tooltipText: option.name, + isDisabled: !option.enabled, + }; + + return; + } + + option.name.split(CONST.PARENT_CHILD_SEPARATOR).forEach((optionName, index, array) => { + const indents = _.times(index, () => CONST.INDENTS).join(''); + const isChild = array.length - 1 === index; + + if (_.has(optionCollection, optionName)) { + return; + } + + optionCollection[optionName] = { + text: `${indents}${optionName}`, + keyForList: optionName, + // TODO: Clarify + searchText: optionName, + tooltipText: optionName, + isDisabled: isChild ? !option.enabled : true, + }; + }); + }); + + return _.values(optionCollection); +} + /** * Build the options * @@ -623,6 +674,58 @@ function getOptions( recentlyUsedCategories = {}, }, ) { + if (includeCategories) { + const categoryOptions = []; + + const categoriesAmount = _.size(categories); + + if (!_.isEmpty(searchInputValue)) { + categoryOptions.push({ + title: '', // Search result + data: getOptionTree( + _.filter(categories, (category) => category.name.toLowerCase().includes(searchInputValue.toLowerCase())), + true, + ), + }); + } else if (categoriesAmount < CONST.CATEGORY_LIST_THRESHOLD) { + categoryOptions.push({ + title: '', // All + data: getOptionTree(categories), + }); + } else { + const selectedOptionNames = _.map(selectedOptions, (selectedOption) => selectedOption.name); + const filteredRecentlyUsedCategories = _.filter(recentlyUsedCategories, (category) => !_.includes(selectedOptionNames, category.name)); + const filteredCategories = _.filter(categories, (category) => !_.includes(selectedOptionNames, category.name)); + + if (!_.isEmpty(selectedOptions)) { + categoryOptions.push({ + title: '', // Selected + data: getOptionTree(selectedOptions), + }); + } + + if (!_.isEmpty(filteredRecentlyUsedCategories)) { + categoryOptions.push({ + title: 'Recent', + data: getOptionTree(filteredRecentlyUsedCategories.slice(0, maxRecentReportsToShow)), + }); + } + + categoryOptions.push({ + title: 'All', + data: getOptionTree(filteredCategories), + }); + } + + return { + recentReports: [], + personalDetails: [], + userToInvite: null, + currentUserOption: null, + categoryOptions, + }; + } + if (!isPersonalDetailsReady(personalDetails)) { return { recentReports: [], @@ -875,88 +978,15 @@ function getOptions( ); } - const categoryOptions = []; - - if (includeCategories) { - const categoriesAmount = _.size(categories); - - if (categoriesAmount < CONST.CATEGORY_LIST_THRESHOLD) { - categoryOptions.push({ - title: '', // All - data: getOptionTree(categories), - }); - } else if (!_.isEmpty(searchInputValue)) { - categoryOptions.push({ - title: '', // All - data: getOptionTree(_.filter(categories, (category) => category.name.toLowerCase().includes(searchInputValue.toLowerCase()))), - }); - } else { - recentlyUsedCategories = _.without(recentlyUsedCategories, selectedOptions); - categories = _.without(categories, selectedOptions); - - if (!_.isEmpty(selectedOptions)) { - categoryOptions.push({ - title: '', // Selected - data: getOptionTree(selectedOptions), - }); - } - - if (!_.isEmpty(recentlyUsedCategories)) { - categoryOptions.push({ - title: 'Recent', - data: getOptionTree(recentlyUsedCategories.slice(0, maxRecentReportsToShow)), - }); - } - - categoryOptions.push({ - title: 'All', - data: getOptionTree(categories), - }); - } - } - return { personalDetails: personalDetailsOptions, recentReports: recentReportOptions, userToInvite, currentUserOption, - categoryOptions, + categoryOptions: [], }; } -/** - * Build the options for the tree hierarchy via indents - * - * @param {Object[]} options - an initial strings array - * @param {Boolean} options[].enabled - a flag to enable/disable option in a list - * @param {String} options[].name - a name of an option - * @returns {Array} - */ -function getOptionTree(options) { - const optionCollection = {}; - - _.each(options, (option) => { - option.name.split(CONST.PARENT_CHILD_SEPARATOR).forEach((optionName, index, array) => { - const indents = _.times(index, () => CONST.INDENTS).join(''); - const isChild = array.length - 1 === index; - - if (_.has(optionCollection, optionName)) { - return; - } - - optionCollection[optionName] = { - text: `${indents}${optionName}`, - keyForList: optionName, - searchText: optionName, - tooltipText: optionName, - isDisabled: isChild ? !option.enabled : true, - }; - }); - }); - - return _.values(optionCollection); -} - /** * Build the options for the Search view * @@ -1036,8 +1066,8 @@ function getIOUConfirmationOptionsFromParticipants(participants, amountText) { * @param {Boolean} [includeOwnedWorkspaceChats] * @param {boolean} [includeP2P] * @param {boolean} [includeCategories] - * @param {Array} [categories] - * @param {Array} [recentlyUsedCategories] + * @param {Object} [categories] + * @param {Object} [recentlyUsedCategories] * @returns {Object} */ function getNewChatOptions( @@ -1050,8 +1080,8 @@ function getNewChatOptions( includeOwnedWorkspaceChats = false, includeP2P = true, includeCategories = false, - categories = [], - recentlyUsedCategories = [], + categories = {}, + recentlyUsedCategories = {}, ) { return getOptions(reports, personalDetails, { betas, diff --git a/tests/unit/OptionsListUtilsTest.js b/tests/unit/OptionsListUtilsTest.js index af1ad42524eb..d42b5705986a 100644 --- a/tests/unit/OptionsListUtilsTest.js +++ b/tests/unit/OptionsListUtilsTest.js @@ -653,6 +653,25 @@ describe('OptionsListUtils', () => { }); it('getNewChatOptions() for categories', () => { + const search = 'Food'; + const emptySearch = ''; + const wrongSearch = 'bla bla'; + const recentlyUsedCategories = { + Taxi: { + enabled: false, + name: 'Taxi', + }, + Restaurant: { + enabled: true, + name: 'Restaurant', + }, + }; + const selectedOptions = [ + { + enabled: false, + name: 'Medical', + }, + ]; const smallCategoriesList = { Taxi: { enabled: false, @@ -706,39 +725,329 @@ describe('OptionsListUtils', () => { ], }, ]; - // const smallSearchResultList = []; - // const smallWrongSearchResultList = []; - // const largeCategoriesList = {}; - // const largeResultList = []; - // const largeSearchResultList = []; - // const largeWrongSearchResultList = []; - // const search = 'Food'; - const emptySearch = ''; - // const wrongSearch = 'bla bla'; - - const smallResult = OptionsListUtils.getNewChatOptions(REPORTS, PERSONAL_DETAILS, [], emptySearch, [], [], false, false, true, smallCategoriesList, []); + const smallSearchResultList = [ + { + title: '', + data: [ + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + }, + { + text: 'Food: Meat', + keyForList: 'Food: Meat', + searchText: 'Food: Meat', + tooltipText: 'Food: Meat', + isDisabled: false, + }, + ], + }, + ]; + const smallWrongSearchResultList = [ + { + title: '', + data: [], + }, + ]; + const largeCategoriesList = { + Taxi: { + enabled: false, + name: 'Taxi', + }, + Restaurant: { + enabled: true, + name: 'Restaurant', + }, + Food: { + enabled: true, + name: 'Food', + }, + 'Food: Meat': { + enabled: true, + name: 'Food: Meat', + }, + 'Food: Milk': { + enabled: true, + name: 'Food: Milk', + }, + 'Food: Vegetables': { + enabled: false, + name: 'Food: Vegetables', + }, + 'Cars: Audi': { + enabled: true, + name: 'Cars: Audi', + }, + 'Cars: BMW': { + enabled: false, + name: 'Cars: BMW', + }, + 'Cars: Mercedes-Benz': { + enabled: true, + name: 'Cars: Mercedes-Benz', + }, + Medical: { + enabled: false, + name: 'Medical', + }, + 'Travel: Meals': { + enabled: true, + name: 'Travel: Meals', + }, + 'Travel: Meals: Breakfast': { + enabled: true, + name: 'Travel: Meals: Breakfast', + }, + 'Travel: Meals: Dinner': { + enabled: false, + name: 'Travel: Meals: Dinner', + }, + 'Travel: Meals: Lunch': { + enabled: true, + name: 'Travel: Meals: Lunch', + }, + }; + const largeResultList = [ + { + title: '', + data: [ + { + text: 'Medical', + keyForList: 'Medical', + searchText: 'Medical', + tooltipText: 'Medical', + isDisabled: true, + }, + ], + }, + { + title: 'Recent', + data: [ + { + text: 'Taxi', + keyForList: 'Taxi', + searchText: 'Taxi', + tooltipText: 'Taxi', + isDisabled: true, + }, + { + text: 'Restaurant', + keyForList: 'Restaurant', + searchText: 'Restaurant', + tooltipText: 'Restaurant', + isDisabled: false, + }, + ], + }, + { + title: 'All', + data: [ + { + text: 'Taxi', + keyForList: 'Taxi', + searchText: 'Taxi', + tooltipText: 'Taxi', + isDisabled: true, + }, + { + text: 'Restaurant', + keyForList: 'Restaurant', + searchText: 'Restaurant', + tooltipText: 'Restaurant', + isDisabled: false, + }, + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + }, + { + text: ' Meat', + keyForList: 'Meat', + searchText: 'Meat', + tooltipText: 'Meat', + isDisabled: false, + }, + { + text: ' Milk', + keyForList: 'Milk', + searchText: 'Milk', + tooltipText: 'Milk', + isDisabled: false, + }, + { + text: ' Vegetables', + keyForList: 'Vegetables', + searchText: 'Vegetables', + tooltipText: 'Vegetables', + isDisabled: true, + }, + { + text: 'Cars', + keyForList: 'Cars', + searchText: 'Cars', + tooltipText: 'Cars', + isDisabled: true, + }, + { + text: ' Audi', + keyForList: 'Audi', + searchText: 'Audi', + tooltipText: 'Audi', + isDisabled: false, + }, + { + text: ' BMW', + keyForList: 'BMW', + searchText: 'BMW', + tooltipText: 'BMW', + isDisabled: true, + }, + { + text: ' Mercedes-Benz', + keyForList: 'Mercedes-Benz', + searchText: 'Mercedes-Benz', + tooltipText: 'Mercedes-Benz', + isDisabled: false, + }, + { + text: 'Travel', + keyForList: 'Travel', + searchText: 'Travel', + tooltipText: 'Travel', + isDisabled: true, + }, + { + text: ' Meals', + keyForList: 'Meals', + searchText: 'Meals', + tooltipText: 'Meals', + isDisabled: false, + }, + { + text: ' Breakfast', + keyForList: 'Breakfast', + searchText: 'Breakfast', + tooltipText: 'Breakfast', + isDisabled: false, + }, + { + text: ' Dinner', + keyForList: 'Dinner', + searchText: 'Dinner', + tooltipText: 'Dinner', + isDisabled: true, + }, + { + text: ' Lunch', + keyForList: 'Lunch', + searchText: 'Lunch', + tooltipText: 'Lunch', + isDisabled: false, + }, + ], + }, + ]; + const largeSearchResultList = [ + { + title: '', + data: [ + { + text: 'Food', + keyForList: 'Food', + searchText: 'Food', + tooltipText: 'Food', + isDisabled: false, + }, + { + text: 'Food: Meat', + keyForList: 'Food: Meat', + searchText: 'Food: Meat', + tooltipText: 'Food: Meat', + isDisabled: false, + }, + { + text: 'Food: Milk', + keyForList: 'Food: Milk', + searchText: 'Food: Milk', + tooltipText: 'Food: Milk', + isDisabled: false, + }, + { + text: 'Food: Vegetables', + keyForList: 'Food: Vegetables', + searchText: 'Food: Vegetables', + tooltipText: 'Food: Vegetables', + isDisabled: true, + }, + ], + }, + ]; + const largeWrongSearchResultList = [ + { + title: '', + data: [], + }, + ]; + const smallResult = OptionsListUtils.getNewChatOptions(REPORTS, PERSONAL_DETAILS, [], emptySearch, [], [], false, false, true, smallCategoriesList); expect(smallResult.categoryOptions).toStrictEqual(smallResultList); - // const largeResult = OptionsListUtils.getNewChatOptions(largeCategoriesList); - - // expect(largeResult.categoryOptions).toStrictEqual(largeResultList); - - // const smallSearchResult = OptionsListUtils.getNewChatOptions(smallCategoriesList); - - // expect(smallSearchResult.categoryOptions).toStrictEqual(smallSearchResultList); - - // const smallWrongSearchResult = OptionsListUtils.getNewChatOptions(smallCategoriesList); - - // expect(smallWrongSearchResult.categoryOptions).toStrictEqual(smallWrongSearchResultList); - - // const largeSearchResult = OptionsListUtils.getNewChatOptions(largeCategoriesList); - - // expect(largeSearchResult.categoryOptions).toStrictEqual(largeSearchResultList); - - // const largeWrongSearchResult = OptionsListUtils.getNewChatOptions(largeSearchResultList); - - // expect(largeWrongSearchResult.categoryOptions).toStrictEqual(largeWrongSearchResultList); + const smallSearchResult = OptionsListUtils.getNewChatOptions(REPORTS, PERSONAL_DETAILS, [], search, [], [], false, false, true, smallCategoriesList); + expect(smallSearchResult.categoryOptions).toStrictEqual(smallSearchResultList); + + const smallWrongSearchResult = OptionsListUtils.getNewChatOptions(REPORTS, PERSONAL_DETAILS, [], wrongSearch, [], [], false, false, true, smallCategoriesList); + expect(smallWrongSearchResult.categoryOptions).toStrictEqual(smallWrongSearchResultList); + + const largeResult = OptionsListUtils.getNewChatOptions( + REPORTS, + PERSONAL_DETAILS, + [], + emptySearch, + selectedOptions, + [], + false, + false, + true, + largeCategoriesList, + recentlyUsedCategories, + ); + expect(largeResult.categoryOptions).toStrictEqual(largeResultList); + + const largeSearchResult = OptionsListUtils.getNewChatOptions( + REPORTS, + PERSONAL_DETAILS, + [], + search, + selectedOptions, + [], + false, + false, + true, + largeCategoriesList, + recentlyUsedCategories, + ); + expect(largeSearchResult.categoryOptions).toStrictEqual(largeSearchResultList); + + const largeWrongSearchResult = OptionsListUtils.getNewChatOptions( + REPORTS, + PERSONAL_DETAILS, + [], + wrongSearch, + selectedOptions, + [], + false, + false, + true, + largeCategoriesList, + recentlyUsedCategories, + ); + expect(largeWrongSearchResult.categoryOptions).toStrictEqual(largeWrongSearchResultList); }); it('getOptionTree()', () => { From 87f69e8c2054c2bac2527691a4562e3880dad82b Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 24 Aug 2023 13:37:39 +0200 Subject: [PATCH 011/125] remove todo --- src/libs/OptionsListUtils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/OptionsListUtils.js b/src/libs/OptionsListUtils.js index 121fa0818dff..41841771bab0 100644 --- a/src/libs/OptionsListUtils.js +++ b/src/libs/OptionsListUtils.js @@ -625,7 +625,6 @@ function getOptionTree(options, isSearch = false) { optionCollection[optionName] = { text: `${indents}${optionName}`, keyForList: optionName, - // TODO: Clarify searchText: optionName, tooltipText: optionName, isDisabled: isChild ? !option.enabled : true, From 9293def637cb75f5924126f997564ea11ba65abf Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Thu, 24 Aug 2023 13:42:15 +0200 Subject: [PATCH 012/125] Migrate 'cursor' style to TypeScript --- .../utilities/cursor/{index.native.js => index.native.ts} | 6 +++++- src/styles/utilities/cursor/{index.js => index.ts} | 6 +++++- src/styles/utilities/cursor/types.ts | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-) rename src/styles/utilities/cursor/{index.native.js => index.native.ts} (72%) rename src/styles/utilities/cursor/{index.js => index.ts} (86%) create mode 100644 src/styles/utilities/cursor/types.ts diff --git a/src/styles/utilities/cursor/index.native.js b/src/styles/utilities/cursor/index.native.ts similarity index 72% rename from src/styles/utilities/cursor/index.native.js rename to src/styles/utilities/cursor/index.native.ts index 95704e55b07a..67416e750f36 100644 --- a/src/styles/utilities/cursor/index.native.js +++ b/src/styles/utilities/cursor/index.native.ts @@ -1,4 +1,6 @@ -export default { +import CursorStyles from './types'; + +const cursor: CursorStyles = { cursorDefault: {}, cursorDisabled: {}, cursorPointer: {}, @@ -11,3 +13,5 @@ export default { cursorInitial: {}, cursorText: {}, }; + +export default cursor; diff --git a/src/styles/utilities/cursor/index.js b/src/styles/utilities/cursor/index.ts similarity index 86% rename from src/styles/utilities/cursor/index.js rename to src/styles/utilities/cursor/index.ts index 00f7f9a7b1e3..e3f85107f16a 100644 --- a/src/styles/utilities/cursor/index.js +++ b/src/styles/utilities/cursor/index.ts @@ -1,4 +1,6 @@ -export default { +import CursorStyles from './types'; + +const cursor: CursorStyles = { cursorDefault: { cursor: 'default', }, @@ -33,3 +35,5 @@ export default { cursor: 'text', }, }; + +export default cursor; diff --git a/src/styles/utilities/cursor/types.ts b/src/styles/utilities/cursor/types.ts new file mode 100644 index 000000000000..6a8ce5bf4d57 --- /dev/null +++ b/src/styles/utilities/cursor/types.ts @@ -0,0 +1,5 @@ +import {CSSProperties} from 'react'; + +type CursorStyles = Record>>; + +export default CursorStyles; From a071a44940b9457593df829d8715c6b2e47b4cc5 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Thu, 24 Aug 2023 16:22:56 +0200 Subject: [PATCH 013/125] Cursor styles keys --- src/styles/utilities/cursor/types.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/styles/utilities/cursor/types.ts b/src/styles/utilities/cursor/types.ts index 6a8ce5bf4d57..9ca20c5ae123 100644 --- a/src/styles/utilities/cursor/types.ts +++ b/src/styles/utilities/cursor/types.ts @@ -1,5 +1,18 @@ import {CSSProperties} from 'react'; -type CursorStyles = Record>>; +type CursorStylesKeys = + | 'cursorDefault' + | 'cursorDisabled' + | 'cursorPointer' + | 'cursorMove' + | 'cursorUnset' + | 'cursorAuto' + | 'cursorZoomIn' + | 'cursorGrabbing' + | 'cursorZoomOut' + | 'cursorInitial' + | 'cursorText'; + +type CursorStyles = Record>>; export default CursorStyles; From 9b66b816affe754ca54316797c018e8083cd1b35 Mon Sep 17 00:00:00 2001 From: Yauheni Pasiukevich Date: Thu, 24 Aug 2023 16:44:27 +0200 Subject: [PATCH 014/125] migrate pointerEventsNone to ts --- src/styles/pointerEventsNone/index.js | 3 --- src/styles/pointerEventsNone/index.native.js | 1 - src/styles/pointerEventsNone/index.native.ts | 5 +++++ src/styles/pointerEventsNone/index.ts | 7 +++++++ src/styles/pointerEventsNone/types.ts | 5 +++++ 5 files changed, 17 insertions(+), 4 deletions(-) delete mode 100644 src/styles/pointerEventsNone/index.js delete mode 100644 src/styles/pointerEventsNone/index.native.js create mode 100644 src/styles/pointerEventsNone/index.native.ts create mode 100644 src/styles/pointerEventsNone/index.ts create mode 100644 src/styles/pointerEventsNone/types.ts diff --git a/src/styles/pointerEventsNone/index.js b/src/styles/pointerEventsNone/index.js deleted file mode 100644 index 93002d269d01..000000000000 --- a/src/styles/pointerEventsNone/index.js +++ /dev/null @@ -1,3 +0,0 @@ -export default { - pointerEvents: 'none', -}; diff --git a/src/styles/pointerEventsNone/index.native.js b/src/styles/pointerEventsNone/index.native.js deleted file mode 100644 index ff8b4c56321a..000000000000 --- a/src/styles/pointerEventsNone/index.native.js +++ /dev/null @@ -1 +0,0 @@ -export default {}; diff --git a/src/styles/pointerEventsNone/index.native.ts b/src/styles/pointerEventsNone/index.native.ts new file mode 100644 index 000000000000..d92936025c94 --- /dev/null +++ b/src/styles/pointerEventsNone/index.native.ts @@ -0,0 +1,5 @@ +import PointerEventsNone from './types'; + +const pointerEventsNone: PointerEventsNone = {}; + +export default pointerEventsNone; diff --git a/src/styles/pointerEventsNone/index.ts b/src/styles/pointerEventsNone/index.ts new file mode 100644 index 000000000000..2d6264db6c4a --- /dev/null +++ b/src/styles/pointerEventsNone/index.ts @@ -0,0 +1,7 @@ +import PointerEventsNone from './types'; + +const pointerEventsNoneStyles: PointerEventsNone = { + pointerEvents: 'none', +}; + +export default pointerEventsNoneStyles; diff --git a/src/styles/pointerEventsNone/types.ts b/src/styles/pointerEventsNone/types.ts new file mode 100644 index 000000000000..f2f5a0d88a41 --- /dev/null +++ b/src/styles/pointerEventsNone/types.ts @@ -0,0 +1,5 @@ +import {CSSProperties} from 'react'; + +type PointerEventsNone = Partial>; + +export default PointerEventsNone; From aa1985d1beb93fc1f8003bdd85aed51508d73d52 Mon Sep 17 00:00:00 2001 From: Carlos Martins Date: Thu, 24 Aug 2023 17:22:05 -0600 Subject: [PATCH 015/125] update transaction type --- src/types/onyx/Transaction.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 0e0c7a423829..5a12dba352fc 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -1,4 +1,6 @@ +import {ValueOf} from 'type-fest'; import * as OnyxCommon from './OnyxCommon'; +import CONST from '../../CONST'; type Comment = { comment?: string; @@ -17,6 +19,11 @@ type Transaction = { modifiedAmount?: number; modifiedCreated?: string; modifiedCurrency?: string; + receipt: { + receiptID?: number; + source?: string; + state?: ValueOf; + }; }; export default Transaction; From 48054884d8e6954b84a108972ae6896734059817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henriques?= Date: Fri, 25 Aug 2023 14:58:42 +0100 Subject: [PATCH 016/125] Migrate file to TS --- src/styles/addOutlineWidth/index.js | 25 ---------------------- src/styles/addOutlineWidth/index.native.js | 14 ------------ src/styles/addOutlineWidth/index.native.ts | 10 +++++++++ src/styles/addOutlineWidth/index.ts | 19 ++++++++++++++++ src/styles/addOutlineWidth/types.ts | 6 ++++++ 5 files changed, 35 insertions(+), 39 deletions(-) delete mode 100644 src/styles/addOutlineWidth/index.js delete mode 100644 src/styles/addOutlineWidth/index.native.js create mode 100644 src/styles/addOutlineWidth/index.native.ts create mode 100644 src/styles/addOutlineWidth/index.ts create mode 100644 src/styles/addOutlineWidth/types.ts diff --git a/src/styles/addOutlineWidth/index.js b/src/styles/addOutlineWidth/index.js deleted file mode 100644 index 2a2657b24910..000000000000 --- a/src/styles/addOutlineWidth/index.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Web and desktop platforms support the "addOutlineWidth" property, so it - * can be added to the object - */ - -import themeDefault from '../themes/default'; - -/** - * Adds the addOutlineWidth property to an object to be used when styling - * - * @param {Object} obj - * @param {Number} val - * @param {boolean} [error=false] - * @returns {Object} - */ -function withOutlineWidth(obj, val, error = false) { - return { - ...obj, - outlineWidth: val, - outlineStyle: val ? 'auto' : 'none', - boxShadow: val !== 0 ? `0px 0px 0px ${val}px ${error ? themeDefault.danger : themeDefault.borderFocus}` : 'none', - }; -} - -export default withOutlineWidth; diff --git a/src/styles/addOutlineWidth/index.native.js b/src/styles/addOutlineWidth/index.native.js deleted file mode 100644 index b678aa95aef0..000000000000 --- a/src/styles/addOutlineWidth/index.native.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Native platforms don't support the "addOutlineWidth" property, so this - * function is a no-op - */ - -/** - * @param {Object} obj - * @returns {Object} - */ -function withOutlineWidth(obj) { - return obj; -} - -export default withOutlineWidth; diff --git a/src/styles/addOutlineWidth/index.native.ts b/src/styles/addOutlineWidth/index.native.ts new file mode 100644 index 000000000000..69e2ffaf3a5b --- /dev/null +++ b/src/styles/addOutlineWidth/index.native.ts @@ -0,0 +1,10 @@ +/** + * Native platforms don't support the "addOutlineWidth" property, so this + * function is a no-op + */ + +import AddOutlineWidth from './types'; + +const addOutlineWidth: AddOutlineWidth = (obj) => obj; + +export default addOutlineWidth; diff --git a/src/styles/addOutlineWidth/index.ts b/src/styles/addOutlineWidth/index.ts new file mode 100644 index 000000000000..257a3de2b6cd --- /dev/null +++ b/src/styles/addOutlineWidth/index.ts @@ -0,0 +1,19 @@ +/** + * Web and desktop platforms support the "addOutlineWidth" property, so it + * can be added to the object + */ + +import themeDefault from '../themes/default'; +import AddOutlineWidth from './types'; + +/** + * Adds the addOutlineWidth property to an object to be used when styling + */ +const addOutlineWidth: AddOutlineWidth = (obj, val, error = false) => ({ + ...obj, + outlineWidth: val, + outlineStyle: val ? 'auto' : 'none', + boxShadow: val !== 0 ? `0px 0px 0px ${val}px ${error ? themeDefault.danger : themeDefault.borderFocus}` : 'none', +}); + +export default addOutlineWidth; diff --git a/src/styles/addOutlineWidth/types.ts b/src/styles/addOutlineWidth/types.ts new file mode 100644 index 000000000000..0f786143e78f --- /dev/null +++ b/src/styles/addOutlineWidth/types.ts @@ -0,0 +1,6 @@ +import {CSSProperties} from 'react'; +import {TextStyle} from 'react-native'; + +type AddOutlineWidth = (obj: TextStyle | CSSProperties, val: number, error: boolean) => TextStyle | CSSProperties; + +export default AddOutlineWidth; From 167f5ef264f3ae73ef9d5bc801791fb4980b3e75 Mon Sep 17 00:00:00 2001 From: Georgia Monahan Date: Fri, 25 Aug 2023 15:05:03 +0100 Subject: [PATCH 017/125] replace corporateCardList with cardList --- src/ONYXKEYS.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index d4d2ab1f90a6..b5bd6daf1d45 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -139,11 +139,11 @@ const ONYXKEYS = { /** The user's bank accounts */ BANK_ACCOUNT_LIST: 'bankAccountList', - /** The user's credit cards (renamed from cardList) */ + /** The user's credit / P2P cards */ FUND_LIST: 'fundList', // The user's Expensify cards - CORPORATE_CARD_LIST: 'corporateCardList', + CARD_LIST: 'cardList', /** Stores information about the user's saved statements */ WALLET_STATEMENT: 'walletStatement', @@ -327,6 +327,7 @@ type OnyxValues = { [ONYXKEYS.WALLET_TERMS]: OnyxTypes.WalletTerms; [ONYXKEYS.BANK_ACCOUNT_LIST]: Record; [ONYXKEYS.FUND_LIST]: Record; + [ONYXKEYS.CARD_LIST]: Record; [ONYXKEYS.WALLET_STATEMENT]: OnyxTypes.WalletStatement; [ONYXKEYS.PERSONAL_BANK_ACCOUNT]: OnyxTypes.PersonalBankAccount; [ONYXKEYS.REIMBURSEMENT_ACCOUNT]: OnyxTypes.ReimbursementAccount; From f1a87c2944028106d9157c1b09d3e4da9d806d14 Mon Sep 17 00:00:00 2001 From: Ali Toshmatov Date: Fri, 25 Aug 2023 21:48:51 +0500 Subject: [PATCH 018/125] Added prevent defualt to button in pdf password page --- src/components/PDFView/PDFPasswordForm.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/PDFView/PDFPasswordForm.js b/src/components/PDFView/PDFPasswordForm.js index 3a7814684ebb..9a8ca33ec744 100644 --- a/src/components/PDFView/PDFPasswordForm.js +++ b/src/components/PDFView/PDFPasswordForm.js @@ -132,6 +132,7 @@ function PDFPasswordForm({isFocused, isPasswordInvalid, shouldShowLoadingIndicat secureTextEntry />