From 6749e0abc0d041cfe0c4349c36a5982045cf1ae6 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 7 Dec 2023 22:39:15 +0700 Subject: [PATCH 001/202] fix: pdf not cached --- src/components/PDFView/index.native.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/PDFView/index.native.js b/src/components/PDFView/index.native.js index b022823d215a..417106618c6d 100644 --- a/src/components/PDFView/index.native.js +++ b/src/components/PDFView/index.native.js @@ -11,6 +11,7 @@ import withThemeStyles, {withThemeStylesPropTypes} from '@components/withThemeSt import withWindowDimensions from '@components/withWindowDimensions'; import compose from '@libs/compose'; import * as StyleUtils from '@styles/StyleUtils'; +import * as CachedPDFPaths from '@userActions/CachedPDFPaths'; import CONST from '@src/CONST'; import PDFPasswordForm from './PDFPasswordForm'; import {defaultProps, propTypes as pdfViewPropTypes} from './pdfViewPropTypes'; @@ -118,7 +119,9 @@ class PDFView extends Component { * After the PDF is successfully loaded hide PDFPasswordForm and the loading * indicator. */ - finishPDFLoad() { + finishPDFLoad(_, path) { + console.log(path) + // CachedPDFPaths.save(path); this.setState({ shouldRequestPassword: false, shouldShowLoadingIndicator: false, @@ -155,7 +158,7 @@ class PDFView extends Component { fitPolicy={0} trustAllCerts={false} renderActivityIndicator={() => } - source={{uri: this.props.sourceURL}} + source={{uri: this.props.sourceURL, cache: true, expiration: 864000}} style={pdfStyles} onError={this.handleFailureToLoadPDF} password={this.state.password} From 0624e89a3f80065d08f2c271e78b505f779520e1 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 7 Dec 2023 22:40:08 +0700 Subject: [PATCH 002/202] fix lint --- src/components/PDFView/index.native.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/PDFView/index.native.js b/src/components/PDFView/index.native.js index 417106618c6d..4f09906ad6fe 100644 --- a/src/components/PDFView/index.native.js +++ b/src/components/PDFView/index.native.js @@ -11,7 +11,6 @@ import withThemeStyles, {withThemeStylesPropTypes} from '@components/withThemeSt import withWindowDimensions from '@components/withWindowDimensions'; import compose from '@libs/compose'; import * as StyleUtils from '@styles/StyleUtils'; -import * as CachedPDFPaths from '@userActions/CachedPDFPaths'; import CONST from '@src/CONST'; import PDFPasswordForm from './PDFPasswordForm'; import {defaultProps, propTypes as pdfViewPropTypes} from './pdfViewPropTypes'; @@ -120,8 +119,6 @@ class PDFView extends Component { * indicator. */ finishPDFLoad(_, path) { - console.log(path) - // CachedPDFPaths.save(path); this.setState({ shouldRequestPassword: false, shouldShowLoadingIndicator: false, From 552592cd2ab1b75e54f10e4450dec427fe6dee02 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 7 Dec 2023 22:56:24 +0700 Subject: [PATCH 003/202] fix lint --- src/components/PDFView/index.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PDFView/index.native.js b/src/components/PDFView/index.native.js index 4f09906ad6fe..69a47ce82d9c 100644 --- a/src/components/PDFView/index.native.js +++ b/src/components/PDFView/index.native.js @@ -118,7 +118,7 @@ class PDFView extends Component { * After the PDF is successfully loaded hide PDFPasswordForm and the loading * indicator. */ - finishPDFLoad(_, path) { + finishPDFLoad() { this.setState({ shouldRequestPassword: false, shouldShowLoadingIndicator: false, From cef767ab13aad2c2c04fee5db681915e70c59976 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 9 Jan 2024 13:49:16 +0100 Subject: [PATCH 004/202] ref: started migratiing MoneyRequestConfirmationList --- ...st.js => MoneyRequestConfirmationList.tsx} | 195 ++++++++---------- 1 file changed, 91 insertions(+), 104 deletions(-) rename src/components/{MoneyRequestConfirmationList.js => MoneyRequestConfirmationList.tsx} (88%) diff --git a/src/components/MoneyRequestConfirmationList.js b/src/components/MoneyRequestConfirmationList.tsx similarity index 88% rename from src/components/MoneyRequestConfirmationList.js rename to src/components/MoneyRequestConfirmationList.tsx index 13dce9337673..5d0c12944d78 100755 --- a/src/components/MoneyRequestConfirmationList.js +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -4,8 +4,8 @@ import {isEmpty} from 'lodash'; import lodashGet from 'lodash/get'; import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useMemo, useReducer, useState} from 'react'; -import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; +import {StyleProp, View, ViewStyle} from 'react-native'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import useLocalize from '@hooks/useLocalize'; import usePermissions from '@hooks/usePermissions'; @@ -28,6 +28,7 @@ import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import * as OnyxTypes from '@src/types/onyx'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; import categoryPropTypes from './categoryPropTypes'; import ConfirmedRoute from './ConfirmedRoute'; @@ -43,135 +44,115 @@ import tagPropTypes from './tagPropTypes'; import taxPropTypes from './taxPropTypes'; import Text from './Text'; import transactionPropTypes from './transactionPropTypes'; +import type {WithCurrentUserPersonalDetailsProps} from './withCurrentUserPersonalDetails'; import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from './withCurrentUserPersonalDetails'; -const propTypes = { - /** Callback to inform parent modal of success */ - onConfirm: PropTypes.func, - - /** Callback to parent modal to send money */ - onSendMoney: PropTypes.func, - - /** Callback to inform a participant is selected */ - onSelectParticipant: PropTypes.func, - - /** Should we request a single or multiple participant selection from user */ - hasMultipleParticipants: PropTypes.bool.isRequired, - - /** IOU amount */ - iouAmount: PropTypes.number.isRequired, - - /** IOU comment */ - iouComment: PropTypes.string, - - /** IOU currency */ - iouCurrencyCode: PropTypes.string, - - /** IOU type */ - iouType: PropTypes.string, - - /** IOU date */ - iouCreated: PropTypes.string, - - /** IOU merchant */ - iouMerchant: PropTypes.string, - - /** IOU Category */ - iouCategory: PropTypes.string, +type MoneyRequestConfirmationListOnyxProps = { + iou?: OnyxTypes.IOU; + policyTaxRates?: any; + session: OnyxTypes.Session; + transaction?: OnyxTypes.Transaction; + mileageRate?: { + unit?: typeof CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES | typeof CONST.CUSTOM_UNITS.DISTANCE_UNIT_KILOMETERS; + rate?: number; + currency?: string; + }; + policyCategories?: any; + policyTags?: any; + policy?: OnyxEntry; +}; +type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & + WithCurrentUserPersonalDetailsProps & { + /** Callback to inform parent modal of success */ + onConfirm?: () => void; - /** IOU Tag */ - iouTag: PropTypes.string, + /** Callback to parent modal to send money */ + onSendMoney?: () => void; - /** IOU isBillable */ - iouIsBillable: PropTypes.bool, + /** Callback to inform a participant is selected */ + onSelectParticipant?: () => void; - /** Callback to toggle the billable state */ - onToggleBillable: PropTypes.func, + /** Should we request a single or multiple participant selection from user */ + hasMultipleParticipants: boolean; - /** Selected participants from MoneyRequestModal with login / accountID */ - selectedParticipants: PropTypes.arrayOf(optionPropTypes).isRequired, + /** IOU amount */ + iouAmount: number; - /** Payee of the money request with login */ - payeePersonalDetails: optionPropTypes, + /** IOU comment */ + iouComment?: string; - /** Can the participants be modified or not */ - canModifyParticipants: PropTypes.bool, + /** IOU currency */ + iouCurrencyCode?: string; - /** Should the list be read only, and not editable? */ - isReadOnly: PropTypes.bool, + /** IOU type */ + iouType?: string; - /** Depending on expense report or personal IOU report, respective bank account route */ - bankAccountRoute: PropTypes.string, + /** IOU date */ + iouCreated?: string; - ...withCurrentUserPersonalDetailsPropTypes, + /** IOU merchant */ + iouMerchant?: string; - /** Current user session */ - session: PropTypes.shape({ - email: PropTypes.string.isRequired, - }), + /** IOU Category */ + iouCategory?: string; - /** The policyID of the request */ - policyID: PropTypes.string, + /** IOU Tag */ + iouTag?: string; - /** The reportID of the request */ - reportID: PropTypes.string, + /** IOU isBillable */ + iouIsBillable?: boolean; - /** File path of the receipt */ - receiptPath: PropTypes.string, + /** Callback to toggle the billable state */ + onToggleBillable?: () => void; - /** File name of the receipt */ - receiptFilename: PropTypes.string, + /** Selected participants from MoneyRequestModal with login / accountID */ + selectedParticipants: OptionType[]; - /** List styles for OptionsSelector */ - listStyles: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + /** Payee of the money request with login */ + payeePersonalDetails?: OptionType; - /** ID of the transaction that represents the money request */ - transactionID: PropTypes.string, + /** Can the participants be modified or not */ + canModifyParticipants?: boolean; - /** Transaction that represents the money request */ - transaction: transactionPropTypes, + /** Should the list be read only, and not editable? */ + isReadOnly?: boolean; - /** Unit and rate used for if the money request is a distance request */ - mileageRate: PropTypes.shape({ - /** Unit used to represent distance */ - unit: PropTypes.oneOf([CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, CONST.CUSTOM_UNITS.DISTANCE_UNIT_KILOMETERS]), + /** Depending on expense report or personal IOU report, respective bank account route */ + bankAccountRoute?: string; - /** Rate used to calculate the distance request amount */ - rate: PropTypes.number, + /** The policyID of the request */ + policyID?: string; - /** The currency of the rate */ - currency: PropTypes.string, - }), + /** The reportID of the request */ + reportID?: string; - /** Whether the money request is a distance request */ - isDistanceRequest: PropTypes.bool, + /** File path of the receipt */ + receiptPath?: string; - /** Whether the money request is a scan request */ - isScanRequest: PropTypes.bool, + /** File name of the receipt */ + receiptFilename?: string; - /** Whether we're editing a split bill */ - isEditingSplitBill: PropTypes.bool, + /** List styles for OptionsSelector */ + listStyles?: StyleProp; - /** Whether we should show the amount, date, and merchant fields. */ - shouldShowSmartScanFields: PropTypes.bool, + /** ID of the transaction that represents the money request */ + transactionID?: string; - /** A flag for verifying that the current report is a sub-report of a workspace chat */ - isPolicyExpenseChat: PropTypes.bool, + /** Whether the money request is a distance request */ + isDistanceRequest?: boolean; - /* Onyx Props */ - /** Collection of categories attached to a policy */ - policyCategories: PropTypes.objectOf(categoryPropTypes), + /** Whether the money request is a scan request */ + isScanRequest?: boolean; - /** Collection of tags attached to a policy */ - policyTags: tagPropTypes, + /** Whether we're editing a split bill */ + isEditingSplitBill?: boolean; - /* Onyx Props */ - /** Collection of tax rates attached to a policy */ - policyTaxRates: taxPropTypes, + /** Whether we should show the amount, date, and merchant fields. */ + shouldShowSmartScanFields?: boolean; - /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ - iou: iouPropTypes, -}; + /** A flag for verifying that the current report is a sub-report of a workspace chat */ + isPolicyExpenseChat?: boolean; + }; const defaultProps = { onConfirm: () => {}, @@ -208,12 +189,18 @@ const defaultProps = { policyTaxRates: {}, }; -function MoneyRequestConfirmationList(props) { +function MoneyRequestConfirmationList({ + onConfirm = () => {}, + onSendMoney = () => {}, + onSelectParticipant = () => {}, + iouType = CONST.IOU.TYPE.REQUEST, + iouCategory = '', + iouTag = '', + iouIsBillable = false, + onToggleBillable = () => {}, +}: MoneyRequestConfirmationListProps) { const theme = useTheme(); const styles = useThemeStyles(); - // Destructure functions from props to pass it as a dependecy to useCallback/useMemo hooks. - // Prop functions pass props itself as a "this" value to the function which means they change every time props change. - const {onSendMoney, onConfirm, onSelectParticipant} = props; const {translate, toLocaleDigit} = useLocalize(); const transaction = props.transaction; const {canUseViolations} = usePermissions(); From d76e0dfcb8c726158f817641b432d93c4e53d330 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 9 Jan 2024 18:49:30 +0100 Subject: [PATCH 005/202] ref: keep migrating --- .../MoneyRequestConfirmationList.tsx | 522 +++++++++--------- .../TextInput/BaseTextInput/types.ts | 2 +- src/libs/ReportUtils.ts | 2 +- src/types/onyx/Policy.ts | 13 +- 4 files changed, 270 insertions(+), 269 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 5d0c12944d78..87c6db42c3b5 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -1,12 +1,12 @@ import {useIsFocused} from '@react-navigation/native'; import {format} from 'date-fns'; import {isEmpty} from 'lodash'; -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; import React, {useCallback, useEffect, useMemo, useReducer, useState} from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; -import {OnyxEntry, withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; import useLocalize from '@hooks/useLocalize'; import usePermissions from '@hooks/usePermissions'; import useTheme from '@hooks/useTheme'; @@ -22,55 +22,49 @@ import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportUtils from '@libs/ReportUtils'; +import type {Participant} from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; -import {iouDefaultProps, iouPropTypes} from '@pages/iou/propTypes'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; +import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import * as OnyxTypes from '@src/types/onyx'; +import type * as OnyxTypes from '@src/types/onyx'; +import type {MileageRate} from '@src/types/onyx/Policy'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; -import categoryPropTypes from './categoryPropTypes'; import ConfirmedRoute from './ConfirmedRoute'; import FormHelpMessage from './FormHelpMessage'; import Image from './Image'; import MenuItemWithTopDescription from './MenuItemWithTopDescription'; -import optionPropTypes from './optionPropTypes'; import OptionsSelector from './OptionsSelector'; import SettlementButton from './SettlementButton'; import ShowMoreButton from './ShowMoreButton'; import Switch from './Switch'; -import tagPropTypes from './tagPropTypes'; -import taxPropTypes from './taxPropTypes'; import Text from './Text'; -import transactionPropTypes from './transactionPropTypes'; import type {WithCurrentUserPersonalDetailsProps} from './withCurrentUserPersonalDetails'; -import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from './withCurrentUserPersonalDetails'; +import withCurrentUserPersonalDetails from './withCurrentUserPersonalDetails'; type MoneyRequestConfirmationListOnyxProps = { - iou?: OnyxTypes.IOU; - policyTaxRates?: any; + iou: OnyxEntry; + policyTaxRates: any; session: OnyxTypes.Session; - transaction?: OnyxTypes.Transaction; - mileageRate?: { - unit?: typeof CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES | typeof CONST.CUSTOM_UNITS.DISTANCE_UNIT_KILOMETERS; - rate?: number; - currency?: string; - }; - policyCategories?: any; - policyTags?: any; + transaction: OnyxTypes.Transaction; + mileageRate: OnyxEntry; + policyCategories: OnyxEntry; + policyTags: OnyxEntry; policy?: OnyxEntry; }; + type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & WithCurrentUserPersonalDetailsProps & { /** Callback to inform parent modal of success */ - onConfirm?: () => void; + onConfirm?: (selectedParticipants: Participant[]) => void; /** Callback to parent modal to send money */ - onSendMoney?: () => void; + onSendMoney?: (paymentMethod: ValueOf) => void; /** Callback to inform a participant is selected */ - onSelectParticipant?: () => void; + onSelectParticipant?: (option: Participant) => void; /** Should we request a single or multiple participant selection from user */ hasMultipleParticipants: boolean; @@ -85,7 +79,7 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & iouCurrencyCode?: string; /** IOU type */ - iouType?: string; + iouType?: ValueOf; /** IOU date */ iouCreated?: string; @@ -106,10 +100,10 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & onToggleBillable?: () => void; /** Selected participants from MoneyRequestModal with login / accountID */ - selectedParticipants: OptionType[]; + selectedParticipants: Participant[]; /** Payee of the money request with login */ - payeePersonalDetails?: OptionType; + payeePersonalDetails?: OnyxEntry; /** Can the participants be modified or not */ canModifyParticipants?: boolean; @@ -152,42 +146,11 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & /** A flag for verifying that the current report is a sub-report of a workspace chat */ isPolicyExpenseChat?: boolean; - }; -const defaultProps = { - onConfirm: () => {}, - onSendMoney: () => {}, - onSelectParticipant: () => {}, - iouType: CONST.IOU.TYPE.REQUEST, - iouCategory: '', - iouTag: '', - iouIsBillable: false, - onToggleBillable: () => {}, - payeePersonalDetails: null, - canModifyParticipants: false, - isReadOnly: false, - bankAccountRoute: '', - session: { - email: null, - }, - policyID: '', - reportID: '', - ...withCurrentUserPersonalDetailsDefaultProps, - receiptPath: '', - receiptFilename: '', - listStyles: [], - policyCategories: {}, - policyTags: {}, - transactionID: '', - transaction: {}, - mileageRate: {unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, rate: 0, currency: 'USD'}, - isDistanceRequest: false, - isScanRequest: false, - shouldShowSmartScanFields: true, - isPolicyExpenseChat: false, - iou: iouDefaultProps, - policyTaxRates: {}, -}; + hasSmartScanFailed?: boolean; + + reportActionID?: string; + }; function MoneyRequestConfirmationList({ onConfirm = () => {}, @@ -198,81 +161,114 @@ function MoneyRequestConfirmationList({ iouTag = '', iouIsBillable = false, onToggleBillable = () => {}, + payeePersonalDetails = null, + canModifyParticipants = false, + isReadOnly = false, + bankAccountRoute = '', + policyID = '', + reportID = '', + receiptPath = '', + receiptFilename = '', + transactionID = '', + mileageRate = {unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, rate: 0, currency: 'USD'}, + isDistanceRequest = false, + isScanRequest = false, + shouldShowSmartScanFields = true, + isPolicyExpenseChat = false, + transaction, + iouAmount, + policyTags, + policyCategories, + policy, + policyTaxRates, + iouCurrencyCode, + isEditingSplitBill, + hasSmartScanFailed, + iouMerchant, + currentUserPersonalDetails, + hasMultipleParticipants, + selectedParticipants, + session, + iou, + reportActionID, + iouCreated, + listStyles, + iouComment, }: MoneyRequestConfirmationListProps) { const theme = useTheme(); const styles = useThemeStyles(); const {translate, toLocaleDigit} = useLocalize(); - const transaction = props.transaction; const {canUseViolations} = usePermissions(); - const isTypeRequest = props.iouType === CONST.IOU.TYPE.REQUEST; - const isSplitBill = props.iouType === CONST.IOU.TYPE.SPLIT; - const isTypeSend = props.iouType === CONST.IOU.TYPE.SEND; + const isTypeRequest = iouType === CONST.IOU.TYPE.REQUEST; + const isSplitBill = iouType === CONST.IOU.TYPE.SPLIT; + const isTypeSend = iouType === CONST.IOU.TYPE.SEND; - const isSplitWithScan = isSplitBill && props.isScanRequest; + const isSplitWithScan = isSplitBill && isScanRequest; - const {unit, rate, currency} = props.mileageRate; - const distance = lodashGet(transaction, 'routes.route0.distance', 0); - const shouldCalculateDistanceAmount = props.isDistanceRequest && props.iouAmount === 0; + const distance = transaction?.routes?.route0.distance ?? 0; + const shouldCalculateDistanceAmount = isDistanceRequest && iouAmount === 0; // A flag for showing the categories field - const shouldShowCategories = props.isPolicyExpenseChat && (props.iouCategory || OptionsListUtils.hasEnabledOptions(_.values(props.policyCategories))); + const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories ?? {}))); // A flag and a toggler for showing the rest of the form fields const [shouldExpandFields, toggleShouldExpandFields] = useReducer((state) => !state, false); // Do not hide fields in case of send money request - const shouldShowAllFields = props.isDistanceRequest || shouldExpandFields || !props.shouldShowSmartScanFields || isTypeSend || props.isEditingSplitBill; + const shouldShowAllFields = isDistanceRequest || shouldExpandFields || !shouldShowSmartScanFields || isTypeSend || isEditingSplitBill; // In Send Money and Split Bill with Scan flow, we don't allow the Merchant or Date to be edited. For distance requests, don't show the merchant as there's already another "Distance" menu item const shouldShowDate = shouldShowAllFields && !isTypeSend && !isSplitWithScan; - const shouldShowMerchant = shouldShowAllFields && !isTypeSend && !props.isDistanceRequest && !isSplitWithScan; + const shouldShowMerchant = shouldShowAllFields && !isTypeSend && !isDistanceRequest && !isSplitWithScan; // Fetches the first tag list of the policy - const policyTag = PolicyUtils.getTag(props.policyTags); - const policyTagList = lodashGet(policyTag, 'tags', {}); - const policyTagListName = lodashGet(policyTag, 'name', translate('common.tag')); + const policyTag = PolicyUtils.getTag(policyTags); + const policyTagList = policyTag?.tags ?? {}; + const policyTagListName = policyTag?.name ?? translate('common.tag'); // A flag for showing the tags field - const shouldShowTags = props.isPolicyExpenseChat && (props.iouTag || OptionsListUtils.hasEnabledOptions(_.values(policyTagList))); + const shouldShowTags = isPolicyExpenseChat && (iouTag || OptionsListUtils.hasEnabledOptions(Object.values(policyTagList))); // A flag for showing tax fields - tax rate and tax amount - const shouldShowTax = props.isPolicyExpenseChat && props.policy.isTaxTrackingEnabled; + const shouldShowTax = isPolicyExpenseChat && policy?.isTaxTrackingEnabled; // A flag for showing the billable field - const shouldShowBillable = !lodashGet(props.policy, 'disabledFields.defaultBillable', true); + const shouldShowBillable = !policy?.disabledFields?.defaultBillable ?? true; const hasRoute = TransactionUtils.hasRoute(transaction); - const isDistanceRequestWithoutRoute = props.isDistanceRequest && !hasRoute; + const isDistanceRequestWithoutRoute = isDistanceRequest && !hasRoute; const formattedAmount = isDistanceRequestWithoutRoute ? translate('common.tbd') : CurrencyUtils.convertToDisplayString( - shouldCalculateDistanceAmount ? DistanceRequestUtils.getDistanceRequestAmount(distance, unit, rate) : props.iouAmount, - props.isDistanceRequest ? currency : props.iouCurrencyCode, + shouldCalculateDistanceAmount + ? DistanceRequestUtils.getDistanceRequestAmount(distance, mileageRate?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, mileageRate?.rate) + : iouAmount, + isDistanceRequest ? mileageRate?.currency : iouCurrencyCode, ); - const formattedTaxAmount = CurrencyUtils.convertToDisplayString(props.transaction.taxAmount, props.iouCurrencyCode); + const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction.taxAmount, iouCurrencyCode); - const defaultTaxKey = props.policyTaxRates.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${props.policyTaxRates.taxes[defaultTaxKey].name} (${props.policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; - const taxRateTitle = (props.transaction.taxRate && props.transaction.taxRate.text) || defaultTaxName; + const defaultTaxKey = policyTaxRates.defaultExternalID; + const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; + const taxRateTitle = transaction.taxRate?.text || defaultTaxName; const isFocused = useIsFocused(); - const [formError, setFormError] = useState(''); + const [formError, setFormError] = useState(null); const [didConfirm, setDidConfirm] = useState(false); const [didConfirmSplit, setDidConfirmSplit] = useState(false); const shouldDisplayFieldError = useMemo(() => { - if (!props.isEditingSplitBill) { + if (!isEditingSplitBill) { return false; } - return (props.hasSmartScanFailed && TransactionUtils.hasMissingSmartscanFields(transaction)) || (didConfirmSplit && TransactionUtils.areRequiredFieldsEmpty(transaction)); - }, [props.isEditingSplitBill, props.hasSmartScanFailed, transaction, didConfirmSplit]); + return (!!hasSmartScanFailed && TransactionUtils.hasMissingSmartscanFields(transaction)) || (didConfirmSplit && TransactionUtils.areRequiredFieldsEmpty(transaction)); + }, [isEditingSplitBill, hasSmartScanFailed, transaction, didConfirmSplit]); - const isMerchantEmpty = !props.iouMerchant || props.iouMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT; - const shouldDisplayMerchantError = props.isPolicyExpenseChat && !props.isScanRequest && isMerchantEmpty; + const isMerchantEmpty = !iouMerchant || iouMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT; + const shouldDisplayMerchantError = isPolicyExpenseChat && !isScanRequest && isMerchantEmpty; useEffect(() => { - if (shouldDisplayFieldError && props.hasSmartScanFailed) { + if (shouldDisplayFieldError && hasSmartScanFailed) { setFormError('iou.receiptScanningFailed'); return; } @@ -281,83 +277,80 @@ function MoneyRequestConfirmationList({ return; } // reset the form error whenever the screen gains or loses focus - setFormError(''); - }, [isFocused, transaction, shouldDisplayFieldError, props.hasSmartScanFailed, didConfirmSplit]); + setFormError(null); + }, [isFocused, transaction, shouldDisplayFieldError, hasSmartScanFailed, didConfirmSplit]); useEffect(() => { if (!shouldCalculateDistanceAmount) { return; } - const amount = DistanceRequestUtils.getDistanceRequestAmount(distance, unit, rate); + const amount = DistanceRequestUtils.getDistanceRequestAmount(distance, mileageRate?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, mileageRate.rate); IOU.setMoneyRequestAmount(amount); - }, [shouldCalculateDistanceAmount, distance, rate, unit]); + }, [shouldCalculateDistanceAmount, distance, mileageRate?.rate, mileageRate?.unit]); /** * Returns the participants with amount - * @param {Array} participants - * @returns {Array} */ const getParticipantsWithAmount = useCallback( - (participantsList) => { - const iouAmount = IOUUtils.calculateAmount(participantsList.length, props.iouAmount, props.iouCurrencyCode); + (participantsList: Participant[]) => { + const calculatedIouAmount = IOUUtils.calculateAmount(participantsList.length, iouAmount, iouCurrencyCode ?? ''); return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( participantsList, - props.iouAmount > 0 ? CurrencyUtils.convertToDisplayString(iouAmount, props.iouCurrencyCode) : '', + calculatedIouAmount > 0 ? CurrencyUtils.convertToDisplayString(calculatedIouAmount, iouCurrencyCode) : '', ); }, - [props.iouAmount, props.iouCurrencyCode], + [iouAmount, iouCurrencyCode], ); // If completing a split bill fails, set didConfirm to false to allow the user to edit the fields again - if (props.isEditingSplitBill && didConfirm) { + if (isEditingSplitBill && didConfirm) { setDidConfirm(false); } const splitOrRequestOptions = useMemo(() => { let text; - if (isSplitBill && props.iouAmount === 0) { + if (isSplitBill && iouAmount === 0) { text = translate('iou.split'); - } else if ((props.receiptPath && isTypeRequest) || isDistanceRequestWithoutRoute) { + } else if ((receiptPath && isTypeRequest) || isDistanceRequestWithoutRoute) { text = translate('iou.request'); - if (props.iouAmount !== 0) { - text = translate('iou.requestAmount', {amount: formattedAmount}); + if (iouAmount !== 0) { + text = translate('iou.requestAmount', {amount: Number(formattedAmount)}); } } else { const translationKey = isSplitBill ? 'iou.splitAmount' : 'iou.requestAmount'; - text = translate(translationKey, {amount: formattedAmount}); + text = translate(translationKey, {amount: Number(formattedAmount)}); } return [ { text: text[0].toUpperCase() + text.slice(1), - value: props.iouType, + value: iouType, }, ]; - }, [isSplitBill, isTypeRequest, props.iouType, props.iouAmount, props.receiptPath, formattedAmount, isDistanceRequestWithoutRoute, translate]); + }, [isSplitBill, isTypeRequest, iouType, iouAmount, receiptPath, formattedAmount, isDistanceRequestWithoutRoute, translate]); - const selectedParticipants = useMemo(() => _.filter(props.selectedParticipants, (participant) => participant.selected), [props.selectedParticipants]); - const payeePersonalDetails = useMemo(() => props.payeePersonalDetails || props.currentUserPersonalDetails, [props.payeePersonalDetails, props.currentUserPersonalDetails]); - const canModifyParticipants = !props.isReadOnly && props.canModifyParticipants && props.hasMultipleParticipants; - const shouldDisablePaidBySection = canModifyParticipants; + const selectedParticipantsMemo = useMemo(() => selectedParticipants.filter((participant) => participant.selected), [selectedParticipants]); + const payeePersonalDetailsMemo = useMemo(() => payeePersonalDetails ?? currentUserPersonalDetails, [payeePersonalDetails, currentUserPersonalDetails]); + const canModifyParticipantsValue = !isReadOnly && canModifyParticipants && hasMultipleParticipants; const optionSelectorSections = useMemo(() => { const sections = []; - const unselectedParticipants = _.filter(props.selectedParticipants, (participant) => !participant.selected); - if (props.hasMultipleParticipants) { - const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipants); - let formattedParticipantsList = _.union(formattedSelectedParticipants, unselectedParticipants); + const unselectedParticipants = selectedParticipants.filter((participant) => !participant.selected); + if (hasMultipleParticipants) { + const formattedSelectedParticipants = getParticipantsWithAmount(selectedParticipantsMemo); + let formattedParticipantsList = [...new Set([...formattedSelectedParticipants, ...unselectedParticipants])]; - if (!canModifyParticipants) { - formattedParticipantsList = _.map(formattedParticipantsList, (participant) => ({ + if (!canModifyParticipantsValue) { + formattedParticipantsList = formattedParticipantsList.map((participant) => ({ ...participant, isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID), })); } - const myIOUAmount = IOUUtils.calculateAmount(selectedParticipants.length, props.iouAmount, props.iouCurrencyCode, true); + const myIOUAmount = IOUUtils.calculateAmount(selectedParticipantsMemo.length, iouAmount, iouCurrencyCode, true); const formattedPayeeOption = OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail( - payeePersonalDetails, - props.iouAmount > 0 ? CurrencyUtils.convertToDisplayString(myIOUAmount, props.iouCurrencyCode) : '', + payeePersonalDetailsMemo, + iouAmount > 0 ? CurrencyUtils.convertToDisplayString(myIOUAmount, iouCurrencyCode) : '', ); sections.push( @@ -366,7 +359,7 @@ function MoneyRequestConfirmationList({ data: [formattedPayeeOption], shouldShow: true, indexOffset: 0, - isDisabled: shouldDisablePaidBySection, + isDisabled: canModifyParticipantsValue, }, { title: translate('moneyRequestConfirmationList.splitWith'), @@ -376,7 +369,7 @@ function MoneyRequestConfirmationList({ }, ); } else { - const formattedSelectedParticipants = _.map(props.selectedParticipants, (participant) => ({ + const formattedSelectedParticipants = selectedParticipants.map((participant) => ({ ...participant, isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID), })); @@ -389,50 +382,56 @@ function MoneyRequestConfirmationList({ } return sections; }, [ - props.selectedParticipants, - props.hasMultipleParticipants, - props.iouAmount, - props.iouCurrencyCode, - getParticipantsWithAmount, selectedParticipants, - payeePersonalDetails, + hasMultipleParticipants, + iouAmount, + iouCurrencyCode, + getParticipantsWithAmount, + payeePersonalDetailsMemo, translate, - shouldDisablePaidBySection, - canModifyParticipants, + canModifyParticipantsValue, + selectedParticipantsMemo, ]); const selectedOptions = useMemo(() => { - if (!props.hasMultipleParticipants) { + if (!hasMultipleParticipants) { return []; } - return [...selectedParticipants, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(payeePersonalDetails)]; - }, [selectedParticipants, props.hasMultipleParticipants, payeePersonalDetails]); + return [...selectedParticipantsMemo, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(payeePersonalDetailsMemo)]; + }, [selectedParticipantsMemo, hasMultipleParticipants, payeePersonalDetailsMemo]); useEffect(() => { - if (!props.isDistanceRequest) { + if (!isDistanceRequest) { return; } - const distanceMerchant = DistanceRequestUtils.getDistanceMerchant(hasRoute, distance, unit, rate, currency, translate, toLocaleDigit); - IOU.setMoneyRequestMerchant_temporaryForRefactor(props.transactionID, distanceMerchant); - }, [hasRoute, distance, unit, rate, currency, translate, toLocaleDigit, props.isDistanceRequest, props.transactionID]); + const distanceMerchant = DistanceRequestUtils.getDistanceMerchant( + hasRoute, + distance, + mileageRate?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, + mileageRate?.rate ?? 0, + mileageRate?.currency ?? 'USD', + translate, + toLocaleDigit, + ); + IOU.setMoneyRequestMerchant_temporaryForRefactor(transactionID, distanceMerchant); + }, [hasRoute, distance, mileageRate?.unit, mileageRate?.rate, mileageRate?.currency, translate, toLocaleDigit, isDistanceRequest, transactionID]); /** * @param {Object} option */ const selectParticipant = useCallback( - (option) => { + (option: Participant) => { // Return early if selected option is currently logged in user. - if (option.accountID === props.session.accountID) { + if (option.accountID === session?.accountID) { return; } onSelectParticipant(option); }, - [props.session.accountID, onSelectParticipant], + [session.accountID, onSelectParticipant], ); /** * Navigate to report details or profile of selected user - * @param {Object} option */ const navigateToReportOrUserDetail = (option) => { if (option.accountID) { @@ -444,19 +443,16 @@ function MoneyRequestConfirmationList({ } }; - /** - * @param {String} paymentMethod - */ const confirm = useCallback( - (paymentMethod) => { - if (_.isEmpty(selectedParticipants)) { + (paymentMethod: ValueOf) => { + if (selectedParticipantsMemo.length === 0) { return; } - if (props.iouCategory && props.iouCategory.length > CONST.API_TRANSACTION_CATEGORY_MAX_LENGTH) { + if (iouCategory && iouCategory.length > CONST.API_TRANSACTION_CATEGORY_MAX_LENGTH) { setFormError('iou.error.invalidCategoryLength'); return; } - if (props.iouType === CONST.IOU.TYPE.SEND) { + if (iouType === CONST.IOU.TYPE.SEND) { if (!paymentMethod) { return; } @@ -467,44 +463,44 @@ function MoneyRequestConfirmationList({ onSendMoney(paymentMethod); } else { // validate the amount for distance requests - const decimals = CurrencyUtils.getCurrencyDecimals(props.iouCurrencyCode); - if (props.isDistanceRequest && !isDistanceRequestWithoutRoute && !MoneyRequestUtils.validateAmount(String(props.iouAmount), decimals)) { + const decimals = CurrencyUtils.getCurrencyDecimals(iouCurrencyCode); + if (isDistanceRequest && !isDistanceRequestWithoutRoute && !MoneyRequestUtils.validateAmount(String(iouAmount), decimals)) { setFormError('common.error.invalidAmount'); return; } - if (props.isEditingSplitBill && TransactionUtils.areRequiredFieldsEmpty(transaction)) { + if (isEditingSplitBill && TransactionUtils.areRequiredFieldsEmpty(transaction)) { setDidConfirmSplit(true); setFormError('iou.error.genericSmartscanFailureMessage'); return; } setDidConfirm(true); - onConfirm(selectedParticipants); + onConfirm(selectedParticipantsMemo); } }, [ - selectedParticipants, + selectedParticipantsMemo, + iouCategory, + iouType, onSendMoney, - onConfirm, - props.isEditingSplitBill, - props.iouType, - props.isDistanceRequest, - props.iouCategory, + iouCurrencyCode, + isDistanceRequest, isDistanceRequestWithoutRoute, - props.iouCurrencyCode, - props.iouAmount, + iouAmount, + isEditingSplitBill, transaction, + onConfirm, ], ); const footerContent = useMemo(() => { - if (props.isReadOnly) { + if (isReadOnly) { return; } - const shouldShowSettlementButton = props.iouType === CONST.IOU.TYPE.SEND; - const shouldDisableButton = selectedParticipants.length === 0 || shouldDisplayMerchantError; + const shouldShowSettlementButton = iouType === CONST.IOU.TYPE.SEND; + const shouldDisableButton = selectedParticipantsMemo.length === 0 || shouldDisplayMerchantError; const button = shouldShowSettlementButton ? ( confirm(value)} options={splitOrRequestOptions} buttonSize={CONST.DROPDOWN_BUTTON_SIZE.LARGE} @@ -539,7 +536,7 @@ function MoneyRequestConfirmationList({ return ( <> - {!_.isEmpty(formError) && ( + {formError && ( ); }, [ - props.isReadOnly, - props.iouType, - props.bankAccountRoute, - props.iouCurrencyCode, - props.policyID, - selectedParticipants.length, + isReadOnly, + iouType, + selectedParticipantsMemo.length, shouldDisplayMerchantError, confirm, + bankAccountRoute, + iouCurrencyCode, + policyID, splitOrRequestOptions, formError, styles.ph1, @@ -565,81 +562,80 @@ function MoneyRequestConfirmationList({ translate, ]); - const {image: receiptImage, thumbnail: receiptThumbnail} = - props.receiptPath && props.receiptFilename ? ReceiptUtils.getThumbnailAndImageURIs(transaction, props.receiptPath, props.receiptFilename) : {}; + const receiptData = ReceiptUtils.getThumbnailAndImageURIs(transaction, receiptPath, receiptFilename); return ( - {props.isDistanceRequest && ( + {isDistanceRequest && ( - + )} - {(receiptImage || receiptThumbnail) && ( + {(receiptData.image || receiptData.thumbnail) && ( )} - {props.shouldShowSmartScanFields && ( + {shouldShowSmartScanFields && ( { - if (props.isDistanceRequest) { + if (isDistanceRequest) { return; } - if (props.isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(props.reportID, props.reportActionID, CONST.EDIT_REQUEST_FIELD.AMOUNT)); + if (isEditingSplitBill) { + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.AMOUNT)); return; } - Navigation.navigate(ROUTES.MONEY_REQUEST_AMOUNT.getRoute(props.iouType, props.reportID)); + Navigation.navigate(ROUTES.MONEY_REQUEST_AMOUNT.getRoute(iouType, reportID)); }} style={[styles.moneyRequestMenuItem, styles.mt2]} titleStyle={styles.moneyRequestConfirmationAmount} disabled={didConfirm} - brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} + brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} error={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction) ? translate('common.error.enterAmount') : ''} /> )} { - if (props.isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(props.reportID, props.reportActionID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION)); + if (isEditingSplitBill) { + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.DESCRIPTION)); return; } - Navigation.navigate(ROUTES.MONEY_REQUEST_DESCRIPTION.getRoute(props.iouType, props.reportID)); + Navigation.navigate(ROUTES.MONEY_REQUEST_DESCRIPTION.getRoute(iouType, reportID)); }} - style={[styles.moneyRequestMenuItem]} + style={styles.moneyRequestMenuItem} titleStyle={styles.flex1} disabled={didConfirm} - interactive={!props.isReadOnly} + interactive={!isReadOnly} numberOfLinesTitle={2} /> {!shouldShowAllFields && ( @@ -652,137 +648,133 @@ function MoneyRequestConfirmationList({ <> {shouldShowDate && ( { - if (props.isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(props.reportID, props.reportActionID, CONST.EDIT_REQUEST_FIELD.DATE)); + if (isEditingSplitBill) { + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.DATE)); return; } - Navigation.navigate(ROUTES.MONEY_REQUEST_DATE.getRoute(props.iouType, props.reportID)); + Navigation.navigate(ROUTES.MONEY_REQUEST_DATE.getRoute(iouType, reportID)); }} disabled={didConfirm} - interactive={!props.isReadOnly} - brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isCreatedMissing(transaction) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} + interactive={!isReadOnly} + brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isCreatedMissing(transaction) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} error={shouldDisplayFieldError && TransactionUtils.isCreatedMissing(transaction) ? translate('common.error.enterDate') : ''} /> )} - {props.isDistanceRequest && ( + {isDistanceRequest && ( Navigation.navigate(ROUTES.MONEY_REQUEST_DISTANCE.getRoute(props.iouType, props.reportID))} + onPress={() => Navigation.navigate(ROUTES.MONEY_REQUEST_DISTANCE.getRoute(iouType, reportID))} disabled={didConfirm || !isTypeRequest} - interactive={!props.isReadOnly} + interactive={!isReadOnly} /> )} {shouldShowMerchant && ( { - if (props.isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(props.reportID, props.reportActionID, CONST.EDIT_REQUEST_FIELD.MERCHANT)); + if (isEditingSplitBill) { + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.MERCHANT)); return; } - Navigation.navigate(ROUTES.MONEY_REQUEST_MERCHANT.getRoute(props.iouType, props.reportID)); + Navigation.navigate(ROUTES.MONEY_REQUEST_MERCHANT.getRoute(iouType, reportID)); }} disabled={didConfirm} - interactive={!props.isReadOnly} - brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} + interactive={!isReadOnly} + brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} error={shouldDisplayMerchantError || (shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction)) ? translate('common.error.enterMerchant') : ''} /> )} {shouldShowCategories && ( { - if (props.isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(props.reportID, props.reportActionID, CONST.EDIT_REQUEST_FIELD.CATEGORY)); + if (isEditingSplitBill) { + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.CATEGORY)); return; } - Navigation.navigate(ROUTES.MONEY_REQUEST_CATEGORY.getRoute(props.iouType, props.reportID)); + Navigation.navigate(ROUTES.MONEY_REQUEST_CATEGORY.getRoute(iouType, reportID)); }} - style={[styles.moneyRequestMenuItem]} + style={styles.moneyRequestMenuItem} titleStyle={styles.flex1} disabled={didConfirm} - interactive={!props.isReadOnly} - rightLabel={canUseViolations && Boolean(props.policy.requiresCategory) ? translate('common.required') : ''} + interactive={!isReadOnly} + rightLabel={canUseViolations && Boolean(policy?.requiresCategory) ? translate('common.required') : ''} /> )} {shouldShowTags && ( { - if (props.isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(props.reportID, props.reportActionID, CONST.EDIT_REQUEST_FIELD.TAG)); + if (isEditingSplitBill) { + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.TAG)); return; } - Navigation.navigate(ROUTES.MONEY_REQUEST_TAG.getRoute(props.iouType, props.reportID)); + Navigation.navigate(ROUTES.MONEY_REQUEST_TAG.getRoute(iouType, reportID)); }} - style={[styles.moneyRequestMenuItem]} + style={styles.moneyRequestMenuItem} disabled={didConfirm} - interactive={!props.isReadOnly} - rightLabel={canUseViolations && Boolean(props.policy.requiresTag) ? translate('common.required') : ''} + interactive={!isReadOnly} + rightLabel={canUseViolations && Boolean(policy?.requiresTag) ? translate('common.required') : ''} /> )} {shouldShowTax && ( - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(props.iouType, props.transaction.transactionID, props.reportID, Navigation.getActiveRouteWithoutParams()), - ) + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams())) } disabled={didConfirm} - interactive={!props.isReadOnly} + interactive={!isReadOnly} /> )} {shouldShowTax && ( - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(props.iouType, props.transaction.transactionID, props.reportID, Navigation.getActiveRouteWithoutParams()), - ) + Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams())) } disabled={didConfirm} - interactive={!props.isReadOnly} + interactive={!isReadOnly} /> )} {shouldShowBillable && ( - {translate('common.billable')} + {translate('common.billable')} )} @@ -792,13 +784,10 @@ function MoneyRequestConfirmationList({ ); } -MoneyRequestConfirmationList.propTypes = propTypes; -MoneyRequestConfirmationList.defaultProps = defaultProps; MoneyRequestConfirmationList.displayName = 'MoneyRequestConfirmationList'; export default compose( - withCurrentUserPersonalDetails, - withOnyx({ + withOnyx({ session: { key: ONYXKEYS.SESSION, }, @@ -825,4 +814,5 @@ export default compose( key: ONYXKEYS.IOU, }, }), + withCurrentUserPersonalDetails, )(MoneyRequestConfirmationList); diff --git a/src/components/TextInput/BaseTextInput/types.ts b/src/components/TextInput/BaseTextInput/types.ts index 21875d4dcc64..5564f3919542 100644 --- a/src/components/TextInput/BaseTextInput/types.ts +++ b/src/components/TextInput/BaseTextInput/types.ts @@ -111,7 +111,7 @@ type CustomBaseTextInputProps = { autoCompleteType?: string; }; -type BaseTextInputRef = ForwardedRef>>; +type BaseTextInputRef = ForwardedRef>>; type BaseTextInputProps = CustomBaseTextInputProps & TextInputProps; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 0d7658adf180..a90a1f10a2f4 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -4534,4 +4534,4 @@ export { shouldDisableThread, }; -export type {ExpenseOriginalMessage, OptionData, OptimisticChatReport}; +export type {ExpenseOriginalMessage, OptionData, OptimisticChatReport, Participant}; diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 2cd686c115b4..63091d983840 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -10,6 +10,12 @@ type Rate = { currency: string; }; +type MileageRate = { + unit: Unit; + rate: number; + currency: string; +}; + type CustomUnit = { customUnitID?: string; name?: string; @@ -79,8 +85,13 @@ type Policy = { /** The employee list of the policy */ employeeList?: []; + + /** Whether tax tracking enabled for policy */ + isTaxTrackingEnabled?: boolean; + + disabledFields?: Record; }; export default Policy; -export type {Unit}; +export type {Unit, MileageRate}; From eb8677e5005772586627d0787b9d237f21ca018a Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Wed, 10 Jan 2024 12:21:16 +0700 Subject: [PATCH 006/202] create getUserDetailsTooltipText util --- src/components/MultipleAvatars.tsx | 18 +++++++++--------- src/libs/OptionsListUtils.js | 2 +- src/libs/ReportUtils.ts | 8 ++++++++ 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/components/MultipleAvatars.tsx b/src/components/MultipleAvatars.tsx index a6f34cd459fc..82480ed0a4da 100644 --- a/src/components/MultipleAvatars.tsx +++ b/src/components/MultipleAvatars.tsx @@ -1,11 +1,10 @@ import React, {memo, useMemo} from 'react'; -import type {StyleProp, ViewStyle} from 'react-native'; -import {View} from 'react-native'; -import type {ValueOf} from 'type-fest'; +import {StyleProp, View, ViewStyle} from 'react-native'; +import {ValueOf} from 'type-fest'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {AvatarSource} from '@libs/UserUtils'; +import {AvatarSource} from '@libs/UserUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import type {Icon} from '@src/types/onyx/OnyxCommon'; @@ -13,6 +12,7 @@ import Avatar from './Avatar'; import Text from './Text'; import Tooltip from './Tooltip'; import UserDetailsTooltip from './UserDetailsTooltip'; +import * as ReportUtils from '@libs/ReportUtils'; type MultipleAvatarsProps = { /** Array of avatar URLs or icons */ @@ -143,7 +143,7 @@ function MultipleAvatars({ if (icons.length === 1 && !shouldStackHorizontally) { return ( ( maxAvatarsInRow && ( Number(icon.id)))} > {icons.length === 2 ? ( getDisplayNameForParticipant(accountIDs)).join(', '); +} + /** * For a deleted parent report action within a chat report, * let us return the appropriate display message @@ -4533,6 +4540,7 @@ export { shouldAutoFocusOnKeyPress, shouldDisplayThreadReplies, shouldDisableThread, + getUserDetailsTooltipText }; export type {ExpenseOriginalMessage, OptionData, OptimisticChatReport, OptimisticCreatedReportAction}; From e0dc2e94a3912c965421e7304a8ec483373106ca Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 10 Jan 2024 08:07:25 +0100 Subject: [PATCH 007/202] ref: wip --- src/components/MoneyRequestConfirmationList.tsx | 5 +++-- src/types/onyx/PolicyTag.ts | 1 + src/types/onyx/Transaction.ts | 12 ++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 87c6db42c3b5..741118167a26 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -240,7 +240,7 @@ function MoneyRequestConfirmationList({ ? translate('common.tbd') : CurrencyUtils.convertToDisplayString( shouldCalculateDistanceAmount - ? DistanceRequestUtils.getDistanceRequestAmount(distance, mileageRate?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, mileageRate?.rate) + ? DistanceRequestUtils.getDistanceRequestAmount(distance, mileageRate?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, mileageRate?.rate ?? 0) : iouAmount, isDistanceRequest ? mileageRate?.currency : iouCurrencyCode, ); @@ -248,6 +248,7 @@ function MoneyRequestConfirmationList({ const defaultTaxKey = policyTaxRates.defaultExternalID; const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const taxRateTitle = transaction.taxRate?.text || defaultTaxName; const isFocused = useIsFocused(); @@ -347,7 +348,7 @@ function MoneyRequestConfirmationList({ })); } - const myIOUAmount = IOUUtils.calculateAmount(selectedParticipantsMemo.length, iouAmount, iouCurrencyCode, true); + const myIOUAmount = IOUUtils.calculateAmount(selectedParticipantsMemo.length, iouAmount, iouCurrencyCode ?? '', true); const formattedPayeeOption = OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail( payeePersonalDetailsMemo, iouAmount > 0 ? CurrencyUtils.convertToDisplayString(myIOUAmount, iouCurrencyCode) : '', diff --git a/src/types/onyx/PolicyTag.ts b/src/types/onyx/PolicyTag.ts index 58a21dcf4df5..e9b909b1748a 100644 --- a/src/types/onyx/PolicyTag.ts +++ b/src/types/onyx/PolicyTag.ts @@ -8,6 +8,7 @@ type PolicyTag = { /** "General Ledger code" that corresponds to this tag in an accounting system. Similar to an ID. */ // eslint-disable-next-line @typescript-eslint/naming-convention 'GL Code': string; + tags: PolicyTags; }; type PolicyTags = Record; diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 8b7e26280305..179f473dc71f 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -3,6 +3,15 @@ import type CONST from '@src/CONST'; import type * as OnyxCommon from './OnyxCommon'; import type RecentWaypoint from './RecentWaypoint'; +type TaxRate = { + text: string; + keyForList: string; + data: { + value: string; + }; + modifiedName?: string; +}; + type Waypoint = { /** The name associated with the address of the waypoint */ name?: string; @@ -18,6 +27,7 @@ type Waypoint = { }; type WaypointCollection = Record; + type Comment = { comment?: string; waypoints?: WaypointCollection; @@ -94,6 +104,8 @@ type Transaction = { /** If the transaction was made in a foreign currency, we send the original amount and currency */ originalAmount?: number; originalCurrency?: string; + taxAmount?: number; + taxRate?: TaxRate; }; export default Transaction; From ebabfc77dd2ed34b17d8add8ef72d9c7e66f5cd1 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Wed, 10 Jan 2024 14:42:32 +0700 Subject: [PATCH 008/202] fix lint --- src/components/MultipleAvatars.tsx | 13 ++++++++----- .../BaseUserDetailsTooltip/index.tsx | 4 ++-- src/libs/ReportUtils.ts | 4 ++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/components/MultipleAvatars.tsx b/src/components/MultipleAvatars.tsx index 82480ed0a4da..5f9575e09bfd 100644 --- a/src/components/MultipleAvatars.tsx +++ b/src/components/MultipleAvatars.tsx @@ -1,10 +1,12 @@ import React, {memo, useMemo} from 'react'; -import {StyleProp, View, ViewStyle} from 'react-native'; -import {ValueOf} from 'type-fest'; +import type {StyleProp, ViewStyle} from 'react-native'; +import {View} from 'react-native'; +import type {ValueOf} from 'type-fest'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import {AvatarSource} from '@libs/UserUtils'; +import * as ReportUtils from '@libs/ReportUtils'; +import type {AvatarSource} from '@libs/UserUtils'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import type {Icon} from '@src/types/onyx/OnyxCommon'; @@ -12,7 +14,6 @@ import Avatar from './Avatar'; import Text from './Text'; import Tooltip from './Tooltip'; import UserDetailsTooltip from './UserDetailsTooltip'; -import * as ReportUtils from '@libs/ReportUtils'; type MultipleAvatarsProps = { /** Array of avatar URLs or icons */ @@ -214,7 +215,9 @@ function MultipleAvatars({ {avatars.length > maxAvatarsInRow && ( Number(icon.id)))} + text={ReportUtils.getUserDetailsTooltipText( + icons.slice(avatarRows.length * maxAvatarsInRow - 1, avatarRows.length * maxAvatarsInRow + 9).map((icon) => Number(icon.id)), + )} > getDisplayNameForParticipant(accountIDs)).join(', '); + return accountIDs.map((accountID) => getDisplayNameForParticipant(accountID)).join(', '); } /** @@ -4540,7 +4540,7 @@ export { shouldAutoFocusOnKeyPress, shouldDisplayThreadReplies, shouldDisableThread, - getUserDetailsTooltipText + getUserDetailsTooltipText, }; export type {ExpenseOriginalMessage, OptionData, OptimisticChatReport, OptimisticCreatedReportAction}; From 83b98ea8d1d4749ea7246faff24686ed7e874839 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Wed, 10 Jan 2024 15:24:06 +0700 Subject: [PATCH 009/202] fix ts lint --- src/components/MultipleAvatars.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/MultipleAvatars.tsx b/src/components/MultipleAvatars.tsx index 5f9575e09bfd..48a9bd77c09e 100644 --- a/src/components/MultipleAvatars.tsx +++ b/src/components/MultipleAvatars.tsx @@ -144,7 +144,7 @@ function MultipleAvatars({ if (icons.length === 1 && !shouldStackHorizontally) { return ( ( {icons.length === 2 ? ( Date: Wed, 10 Jan 2024 16:29:28 +0100 Subject: [PATCH 010/202] fix: wip --- src/ONYXKEYS.ts | 1 + src/components/MenuItem.tsx | 2 +- .../MoneyRequestConfirmationList.tsx | 108 +++++++++--------- src/libs/ReceiptUtils.ts | 5 +- src/libs/TransactionUtils.ts | 19 +-- src/types/onyx/Policy.ts | 4 + src/types/onyx/PolicyTaxRates.ts | 4 + src/types/onyx/index.ts | 4 + 8 files changed, 83 insertions(+), 64 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 89ddbdc06883..7fb29f348a44 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -439,6 +439,7 @@ type OnyxValues = { [ONYXKEYS.COLLECTION.POLICY_DRAFTS]: OnyxTypes.Policy; [ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategory; [ONYXKEYS.COLLECTION.POLICY_TAGS]: OnyxTypes.PolicyTags; + [ONYXKEYS.COLLECTION.POLICY_TAX_RATE]: OnyxTypes.PolicyTaxRate; [ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMembers; [ONYXKEYS.COLLECTION.POLICY_MEMBERS_DRAFTS]: OnyxTypes.PolicyMember; [ONYXKEYS.COLLECTION.POLICY_RECENTLY_USED_CATEGORIES]: OnyxTypes.RecentlyUsedCategories; diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index ce44db72598a..9b35a0963b14 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -204,7 +204,7 @@ type MenuItemProps = (IconProps | AvatarProps | NoIcon) & { shouldBlockSelection?: boolean; /** Whether should render title as HTML or as Text */ - shouldParseTitle?: false; + shouldParseTitle?: boolean; /** Should check anonymous user in onPress function */ shouldCheckActionAllowedOnPress?: boolean; diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 741118167a26..b0a9ce1d7a91 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -11,7 +11,6 @@ import useLocalize from '@hooks/useLocalize'; import usePermissions from '@hooks/usePermissions'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import DistanceRequestUtils from '@libs/DistanceRequestUtils'; import * as IOUUtils from '@libs/IOUUtils'; @@ -46,13 +45,12 @@ import withCurrentUserPersonalDetails from './withCurrentUserPersonalDetails'; type MoneyRequestConfirmationListOnyxProps = { iou: OnyxEntry; - policyTaxRates: any; - session: OnyxTypes.Session; - transaction: OnyxTypes.Transaction; + policyTaxRates: OnyxEntry; + session: OnyxEntry; mileageRate: OnyxEntry; - policyCategories: OnyxEntry; + policyCategories: OnyxEntry; policyTags: OnyxEntry; - policy?: OnyxEntry; + policy: OnyxEntry; }; type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & @@ -150,6 +148,8 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & hasSmartScanFailed?: boolean; reportActionID?: string; + + transaction: OnyxTypes.Transaction; }; function MoneyRequestConfirmationList({ @@ -210,7 +210,7 @@ function MoneyRequestConfirmationList({ const shouldCalculateDistanceAmount = isDistanceRequest && iouAmount === 0; // A flag for showing the categories field - const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories ?? {}))); + const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories))); // A flag and a toggler for showing the rest of the form fields const [shouldExpandFields, toggleShouldExpandFields] = useReducer((state) => !state, false); @@ -244,12 +244,12 @@ function MoneyRequestConfirmationList({ : iouAmount, isDistanceRequest ? mileageRate?.currency : iouCurrencyCode, ); - const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction.taxAmount, iouCurrencyCode); + const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction?.taxAmount, iouCurrencyCode); - const defaultTaxKey = policyTaxRates.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; + const defaultTaxKey = policyTaxRates?.defaultExternalID; + const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates?.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) ?? ''; // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const taxRateTitle = transaction.taxRate?.text || defaultTaxName; + const taxRateTitle = transaction?.taxRate?.text || defaultTaxName; const isFocused = useIsFocused(); const [formError, setFormError] = useState(null); @@ -286,7 +286,7 @@ function MoneyRequestConfirmationList({ return; } - const amount = DistanceRequestUtils.getDistanceRequestAmount(distance, mileageRate?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, mileageRate.rate); + const amount = DistanceRequestUtils.getDistanceRequestAmount(distance, mileageRate?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, mileageRate?.rate); IOU.setMoneyRequestAmount(amount); }, [shouldCalculateDistanceAmount, distance, mileageRate?.rate, mileageRate?.unit]); @@ -398,8 +398,10 @@ function MoneyRequestConfirmationList({ if (!hasMultipleParticipants) { return []; } - return [...selectedParticipantsMemo, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(payeePersonalDetailsMemo)]; - }, [selectedParticipantsMemo, hasMultipleParticipants, payeePersonalDetailsMemo]); + // TODO: check if this is needed + const myIOUAmount = IOUUtils.calculateAmount(selectedParticipantsMemo.length, iouAmount, iouCurrencyCode ?? '', true); + return [...selectedParticipantsMemo, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(payeePersonalDetailsMemo, String(myIOUAmount))]; + }, [hasMultipleParticipants, selectedParticipantsMemo, iouAmount, iouCurrencyCode, payeePersonalDetailsMemo]); useEffect(() => { if (!isDistanceRequest) { @@ -428,14 +430,14 @@ function MoneyRequestConfirmationList({ } onSelectParticipant(option); }, - [session.accountID, onSelectParticipant], + [session?.accountID, onSelectParticipant], ); /** * Navigate to report details or profile of selected user */ - const navigateToReportOrUserDetail = (option) => { - if (option.accountID) { + const navigateToReportOrUserDetail = (option: Participant | OnyxTypes.Report) => { + if ('accountID' in option) { const activeRoute = Navigation.getActiveRouteWithoutParams(); Navigation.navigate(ROUTES.PROFILE.getRoute(option.accountID, activeRoute)); @@ -505,6 +507,7 @@ function MoneyRequestConfirmationList({ const button = shouldShowSettlementButton ? ( - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams())) + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams()), + ) } disabled={didConfirm} interactive={!isReadOnly} @@ -758,11 +764,13 @@ function MoneyRequestConfirmationList({ - Navigation.navigate(ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(iouType, transaction.transactionID, reportID, Navigation.getActiveRouteWithoutParams())) + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams()), + ) } disabled={didConfirm} interactive={!isReadOnly} @@ -787,33 +795,29 @@ function MoneyRequestConfirmationList({ MoneyRequestConfirmationList.displayName = 'MoneyRequestConfirmationList'; -export default compose( - withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, - policyCategories: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, - }, - policyTags: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, - }, - mileageRate: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - selector: DistanceRequestUtils.getDefaultMileageRate, - }, - splitTransactionDraft: { - key: ({transactionID}) => `${ONYXKEYS.COLLECTION.SPLIT_TRANSACTION_DRAFT}${transactionID}`, - }, - policy: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - }, - policyTaxRates: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, - }, - iou: { - key: ONYXKEYS.IOU, - }, - }), - withCurrentUserPersonalDetails, -)(MoneyRequestConfirmationList); +const MoneyRequestConfirmationListWithCurrentUserPersonalDetails = withCurrentUserPersonalDetails(MoneyRequestConfirmationList); + +export default withOnyx({ + session: { + key: ONYXKEYS.SESSION, + }, + policyCategories: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, + }, + policyTags: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, + }, + mileageRate: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + selector: DistanceRequestUtils.getDefaultMileageRate, + }, + policy: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + }, + policyTaxRates: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, + }, + iou: { + key: ONYXKEYS.IOU, + }, +})(MoneyRequestConfirmationListWithCurrentUserPersonalDetails); diff --git a/src/libs/ReceiptUtils.ts b/src/libs/ReceiptUtils.ts index bcba68a3a0bd..7858c3d7277d 100644 --- a/src/libs/ReceiptUtils.ts +++ b/src/libs/ReceiptUtils.ts @@ -1,5 +1,6 @@ import Str from 'expensify-common/lib/str'; import type {ImageSourcePropType} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import ReceiptDoc from '@assets/images/receipt-doc.png'; import ReceiptGeneric from '@assets/images/receipt-generic.png'; import ReceiptHTML from '@assets/images/receipt-html.png'; @@ -28,7 +29,7 @@ type FileNameAndExtension = { * @param receiptPath * @param receiptFileName */ -function getThumbnailAndImageURIs(transaction: Transaction, receiptPath: string | null = null, receiptFileName: string | null = null): ThumbnailAndImageURI { +function getThumbnailAndImageURIs(transaction: OnyxEntry, receiptPath: string | null = null, receiptFileName: string | null = null): ThumbnailAndImageURI { // URI to image, i.e. blob:new.expensify.com/9ef3a018-4067-47c6-b29f-5f1bd35f213d or expensify.com/receipts/w_e616108497ef940b7210ec6beb5a462d01a878f4.jpg const path = transaction?.receipt?.source ?? receiptPath ?? ''; // filename of uploaded image or last part of remote URI @@ -39,7 +40,7 @@ function getThumbnailAndImageURIs(transaction: Transaction, receiptPath: string if (!Object.hasOwn(transaction?.pendingFields ?? {}, 'waypoints')) { if (hasEReceipt) { - return {thumbnail: null, image: ROUTES.ERECEIPT.getRoute(transaction.transactionID), transaction}; + return {thumbnail: null, image: ROUTES.ERECEIPT.getRoute(transaction?.transactionID), transaction}; } // For local files, we won't have a thumbnail yet diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index c34a6753c1d5..48a7d4065700 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -139,23 +139,24 @@ function hasReceipt(transaction: Transaction | undefined | null): boolean { return !!transaction?.receipt?.state || hasEReceipt(transaction); } -function isMerchantMissing(transaction: Transaction) { - const isMerchantEmpty = transaction.merchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT || transaction.merchant === ''; +function isMerchantMissing(transaction: OnyxEntry) { + const isMerchantEmpty = transaction?.merchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT || transaction?.merchant === ''; - const isModifiedMerchantEmpty = !transaction.modifiedMerchant || transaction.modifiedMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT || transaction.modifiedMerchant === ''; + const isModifiedMerchantEmpty = + !transaction?.modifiedMerchant || transaction?.modifiedMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT || transaction?.modifiedMerchant === ''; return isMerchantEmpty && isModifiedMerchantEmpty; } -function isAmountMissing(transaction: Transaction) { - return transaction.amount === 0 && (!transaction.modifiedAmount || transaction.modifiedAmount === 0); +function isAmountMissing(transaction: OnyxEntry) { + return transaction?.amount === 0 && (!transaction?.modifiedAmount || transaction?.modifiedAmount === 0); } -function isCreatedMissing(transaction: Transaction) { - return transaction.created === '' && (!transaction.created || transaction.modifiedCreated === ''); +function isCreatedMissing(transaction: OnyxEntry) { + return transaction?.created === '' && (!transaction?.created || transaction?.modifiedCreated === ''); } -function areRequiredFieldsEmpty(transaction: Transaction): boolean { +function areRequiredFieldsEmpty(transaction: OnyxEntry): boolean { const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${transaction?.reportID}`] ?? null; const isFromExpenseReport = parentReport?.type === CONST.REPORT.TYPE.EXPENSE; return (isFromExpenseReport && isMerchantMissing(transaction)) || isAmountMissing(transaction) || isCreatedMissing(transaction); @@ -434,7 +435,7 @@ function hasMissingSmartscanFields(transaction: OnyxEntry): boolean /** * Check if the transaction has a defined route */ -function hasRoute(transaction: Transaction): boolean { +function hasRoute(transaction: OnyxEntry): boolean { return !!transaction?.routes?.route0?.geometry?.coordinates; } diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index 63091d983840..af65dd57607f 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -90,6 +90,10 @@ type Policy = { isTaxTrackingEnabled?: boolean; disabledFields?: Record; + + requiresCategory?: boolean; + + requiresTag?: boolean; }; export default Policy; diff --git a/src/types/onyx/PolicyTaxRates.ts b/src/types/onyx/PolicyTaxRates.ts index d549b620f51f..492cf37a3181 100644 --- a/src/types/onyx/PolicyTaxRates.ts +++ b/src/types/onyx/PolicyTaxRates.ts @@ -7,6 +7,10 @@ type PolicyTaxRate = { /** Whether the tax is disabled */ isDisabled?: boolean; + + defaultExternalID: string; + + taxes: PolicyTaxRates; }; type PolicyTaxRates = Record; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 7bd9c321be5e..2ef702226384 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -32,6 +32,8 @@ import type {PolicyMembers} from './PolicyMember'; import type PolicyMember from './PolicyMember'; import type PolicyReportField from './PolicyReportField'; import type {PolicyTag, PolicyTags} from './PolicyTag'; +import type {PolicyTaxRates} from './PolicyTaxRates'; +import type PolicyTaxRate from './PolicyTaxRates'; import type PrivatePersonalDetails from './PrivatePersonalDetails'; import type RecentlyUsedCategories from './RecentlyUsedCategories'; import type RecentlyUsedReportFields from './RecentlyUsedReportFields'; @@ -137,4 +139,6 @@ export type { ReportUserIsTyping, PolicyReportField, RecentlyUsedReportFields, + PolicyTaxRate, + PolicyTaxRates, }; From 4ab2ec1000b86078ea558e2d8fae6b71b6c4d444 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 11 Jan 2024 17:12:11 +0700 Subject: [PATCH 011/202] Change logic page not found in profile page --- src/pages/ProfilePage.js | 239 ++++++++++++++++++--------------------- 1 file changed, 113 insertions(+), 126 deletions(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index c0c782f176ca..590a4635f9e5 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -8,12 +8,11 @@ import _ from 'underscore'; import AttachmentModal from '@components/AttachmentModal'; import AutoUpdateTime from '@components/AutoUpdateTime'; import Avatar from '@components/Avatar'; -import BlockingView from '@components/BlockingViews/BlockingView'; +import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import CommunicationsLink from '@components/CommunicationsLink'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; -import * as Illustrations from '@components/Icon/Illustrations'; import MenuItem from '@components/MenuItem'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -30,7 +29,6 @@ import {parsePhoneNumber} from '@libs/PhoneNumber'; import * as ReportUtils from '@libs/ReportUtils'; import * as UserUtils from '@libs/UserUtils'; import * as ValidationUtils from '@libs/ValidationUtils'; -import variables from '@styles/variables'; import * as PersonalDetails from '@userActions/PersonalDetails'; import * as Report from '@userActions/Report'; import * as Session from '@userActions/Session'; @@ -124,9 +122,6 @@ function ProfilePage(props) { const hasMinimumDetails = !_.isEmpty(details.avatar); const isLoading = lodashGet(details, 'isLoading', false) || _.isEmpty(details); - // If the API returns an error for some reason there won't be any details and isLoading will get set to false, so we want to show a blocking screen - const shouldShowBlockingView = !hasMinimumDetails && !isLoading; - const statusEmojiCode = lodashGet(details, 'status.emojiCode', ''); const statusText = lodashGet(details, 'status.text', ''); const hasStatus = !!statusEmojiCode; @@ -146,132 +141,124 @@ function ProfilePage(props) { return ( - Navigation.goBack(navigateBackTo)} - /> - - {hasMinimumDetails && ( - - - - {({show}) => ( - - - - - - )} - - {Boolean(displayName) && ( - + Navigation.goBack(navigateBackTo)} + /> + + {hasMinimumDetails && ( + + + - {displayName} - - )} - {hasStatus && ( - + {({show}) => ( + + + + + + )} + + {Boolean(displayName) && ( - {props.translate('statusPage.status')} + {displayName} - {statusContent} - - )} + )} + {hasStatus && ( + + + {props.translate('statusPage.status')} + + {statusContent} + + )} - {login ? ( - - - {props.translate(isSMSLogin ? 'common.phoneNumber' : 'common.email')} - - - - {isSMSLogin ? props.formatPhoneNumber(phoneNumber) : login} - - - - ) : null} - {pronouns ? ( - - - {props.translate('profilePage.preferredPronouns')} - - {pronouns} - - ) : null} - {shouldShowLocalTime && } - - {shouldShowNotificationPreference && ( - Navigation.navigate(ROUTES.REPORT_SETTINGS_NOTIFICATION_PREFERENCES.getRoute(props.report.reportID))} - wrapperStyle={[styles.mtn6, styles.mb5]} - /> - )} - {!isCurrentUser && !Session.isAnonymousUser() && ( - Report.navigateToAndOpenReportWithAccountIDs([accountID])} - wrapperStyle={styles.breakAll} - shouldShowRightIcon - /> - )} - {!_.isEmpty(props.report) && ( - ReportUtils.navigateToPrivateNotes(props.report, props.session)} - wrapperStyle={styles.breakAll} - shouldShowRightIcon - brickRoadIndicator={Report.hasErrorInPrivateNotes(props.report) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} - /> - )} - - )} - {!hasMinimumDetails && isLoading && } - {shouldShowBlockingView && ( - - )} - + {login ? ( + + + {props.translate(isSMSLogin ? 'common.phoneNumber' : 'common.email')} + + + + {isSMSLogin ? props.formatPhoneNumber(phoneNumber) : login} + + + + ) : null} + {pronouns ? ( + + + {props.translate('profilePage.preferredPronouns')} + + {pronouns} + + ) : null} + {shouldShowLocalTime && } + + {shouldShowNotificationPreference && ( + Navigation.navigate(ROUTES.REPORT_SETTINGS_NOTIFICATION_PREFERENCES.getRoute(props.report.reportID))} + wrapperStyle={[styles.mtn6, styles.mb5]} + /> + )} + {!isCurrentUser && !Session.isAnonymousUser() && ( + Report.navigateToAndOpenReportWithAccountIDs([accountID])} + wrapperStyle={styles.breakAll} + shouldShowRightIcon + /> + )} + {!_.isEmpty(props.report) && ( + ReportUtils.navigateToPrivateNotes(props.report, props.session)} + wrapperStyle={styles.breakAll} + shouldShowRightIcon + brickRoadIndicator={Report.hasErrorInPrivateNotes(props.report) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''} + /> + )} + + )} + {!hasMinimumDetails && isLoading && } + + ); } From ef6ae5f2735ca7cce0441454828f70b3be5210a3 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 11 Jan 2024 15:30:18 +0100 Subject: [PATCH 012/202] Update policyCategories type in MoneyRequestConfirmationList --- src/ONYXKEYS.ts | 2 +- .../MoneyRequestConfirmationList.tsx | 60 +++++++++---------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 45f70d1864bc..f5e8bba63361 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -437,7 +437,7 @@ type OnyxValues = { [ONYXKEYS.COLLECTION.DOWNLOAD]: OnyxTypes.Download; [ONYXKEYS.COLLECTION.POLICY]: OnyxTypes.Policy; [ONYXKEYS.COLLECTION.POLICY_DRAFTS]: OnyxTypes.Policy; - [ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategory; + [ONYXKEYS.COLLECTION.POLICY_CATEGORIES]: OnyxTypes.PolicyCategories; [ONYXKEYS.COLLECTION.POLICY_TAGS]: OnyxTypes.PolicyTags; [ONYXKEYS.COLLECTION.POLICY_TAX_RATE]: OnyxTypes.PolicyTaxRate; [ONYXKEYS.COLLECTION.POLICY_MEMBERS]: OnyxTypes.PolicyMembers; diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index b0a9ce1d7a91..9c46144d3a56 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -46,9 +46,8 @@ import withCurrentUserPersonalDetails from './withCurrentUserPersonalDetails'; type MoneyRequestConfirmationListOnyxProps = { iou: OnyxEntry; policyTaxRates: OnyxEntry; - session: OnyxEntry; mileageRate: OnyxEntry; - policyCategories: OnyxEntry; + policyCategories: OnyxEntry; policyTags: OnyxEntry; policy: OnyxEntry; }; @@ -210,7 +209,8 @@ function MoneyRequestConfirmationList({ const shouldCalculateDistanceAmount = isDistanceRequest && iouAmount === 0; // A flag for showing the categories field - const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories))); + const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories ?? {}))); + // A flag and a toggler for showing the rest of the form fields const [shouldExpandFields, toggleShouldExpandFields] = useReducer((state) => !state, false); @@ -286,7 +286,7 @@ function MoneyRequestConfirmationList({ return; } - const amount = DistanceRequestUtils.getDistanceRequestAmount(distance, mileageRate?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, mileageRate?.rate); + const amount = DistanceRequestUtils.getDistanceRequestAmount(distance, mileageRate?.unit ?? CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, mileageRate?.rate ?? 0); IOU.setMoneyRequestAmount(amount); }, [shouldCalculateDistanceAmount, distance, mileageRate?.rate, mileageRate?.unit]); @@ -299,7 +299,8 @@ function MoneyRequestConfirmationList({ return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( participantsList, calculatedIouAmount > 0 ? CurrencyUtils.convertToDisplayString(calculatedIouAmount, iouCurrencyCode) : '', - ); + // TODO: Remove assertion after OptionsListUtils will be migrated + ) as Participant[]; }, [iouAmount, iouCurrencyCode], ); @@ -795,29 +796,26 @@ function MoneyRequestConfirmationList({ MoneyRequestConfirmationList.displayName = 'MoneyRequestConfirmationList'; -const MoneyRequestConfirmationListWithCurrentUserPersonalDetails = withCurrentUserPersonalDetails(MoneyRequestConfirmationList); - -export default withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, - policyCategories: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, - }, - policyTags: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, - }, - mileageRate: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - selector: DistanceRequestUtils.getDefaultMileageRate, - }, - policy: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - }, - policyTaxRates: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, - }, - iou: { - key: ONYXKEYS.IOU, - }, -})(MoneyRequestConfirmationListWithCurrentUserPersonalDetails); +export default withCurrentUserPersonalDetails( + withOnyx({ + policyCategories: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`, + }, + policyTags: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${policyID}`, + }, + mileageRate: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + selector: DistanceRequestUtils.getDefaultMileageRate, + }, + policy: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + }, + policyTaxRates: { + key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, + }, + iou: { + key: ONYXKEYS.IOU, + }, + })(MoneyRequestConfirmationList), +); From 441e437de6ab31f4b80a4ccf5f4b8ddddfcf47c7 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 15 Jan 2024 08:40:17 +0100 Subject: [PATCH 013/202] fix: wip --- src/components/MoneyRequestConfirmationList.tsx | 2 +- src/components/TextInput/BaseTextInput/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 9c46144d3a56..5e292e310313 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -646,7 +646,7 @@ function MoneyRequestConfirmationList({ /> {!shouldShowAllFields && ( )} diff --git a/src/components/TextInput/BaseTextInput/types.ts b/src/components/TextInput/BaseTextInput/types.ts index 5564f3919542..21875d4dcc64 100644 --- a/src/components/TextInput/BaseTextInput/types.ts +++ b/src/components/TextInput/BaseTextInput/types.ts @@ -111,7 +111,7 @@ type CustomBaseTextInputProps = { autoCompleteType?: string; }; -type BaseTextInputRef = ForwardedRef>>; +type BaseTextInputRef = ForwardedRef>>; type BaseTextInputProps = CustomBaseTextInputProps & TextInputProps; From 814715b85a10ba75bc517946404639a7b96d4939 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 15 Jan 2024 09:02:53 +0100 Subject: [PATCH 014/202] fix: wip --- src/components/MoneyRequestConfirmationList.tsx | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 5e292e310313..c66a58625300 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -44,11 +44,22 @@ import type {WithCurrentUserPersonalDetailsProps} from './withCurrentUserPersona import withCurrentUserPersonalDetails from './withCurrentUserPersonalDetails'; type MoneyRequestConfirmationListOnyxProps = { + /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ iou: OnyxEntry; + + /** Collection of tax rates attached to a policy */ policyTaxRates: OnyxEntry; + + /** Unit and rate used for if the money request is a distance request */ mileageRate: OnyxEntry; + + /** Collection of categories attached to a policy */ policyCategories: OnyxEntry; + + /** Collection of tags attached to a policy */ policyTags: OnyxEntry; + + /** The policy of root parent report */ policy: OnyxEntry; }; @@ -169,7 +180,7 @@ function MoneyRequestConfirmationList({ receiptPath = '', receiptFilename = '', transactionID = '', - mileageRate = {unit: CONST.CUSTOM_UNITS.DISTANCE_UNIT_MILES, rate: 0, currency: 'USD'}, + mileageRate, isDistanceRequest = false, isScanRequest = false, shouldShowSmartScanFields = true, @@ -399,7 +410,6 @@ function MoneyRequestConfirmationList({ if (!hasMultipleParticipants) { return []; } - // TODO: check if this is needed const myIOUAmount = IOUUtils.calculateAmount(selectedParticipantsMemo.length, iouAmount, iouCurrencyCode ?? '', true); return [...selectedParticipantsMemo, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(payeePersonalDetailsMemo, String(myIOUAmount))]; }, [hasMultipleParticipants, selectedParticipantsMemo, iouAmount, iouCurrencyCode, payeePersonalDetailsMemo]); @@ -420,9 +430,6 @@ function MoneyRequestConfirmationList({ IOU.setMoneyRequestMerchant_temporaryForRefactor(transactionID, distanceMerchant); }, [hasRoute, distance, mileageRate?.unit, mileageRate?.rate, mileageRate?.currency, translate, toLocaleDigit, isDistanceRequest, transactionID]); - /** - * @param {Object} option - */ const selectParticipant = useCallback( (option: Participant) => { // Return early if selected option is currently logged in user. From e5921cee015660fa3a5b59b453a9617dbeefa53a Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 17 Jan 2024 10:39:47 +0100 Subject: [PATCH 015/202] fix: resolve comments --- src/components/ConfirmedRoute.tsx | 6 +- .../MoneyRequestConfirmationList.tsx | 65 ++++++++++++------- src/libs/ReportUtils.ts | 5 +- src/types/onyx/OriginalMessage.ts | 4 +- src/types/onyx/Policy.ts | 3 + src/types/onyx/PolicyTaxRates.ts | 2 + 6 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/components/ConfirmedRoute.tsx b/src/components/ConfirmedRoute.tsx index c01f7c6250f4..8a3b39305dba 100644 --- a/src/components/ConfirmedRoute.tsx +++ b/src/components/ConfirmedRoute.tsx @@ -30,13 +30,13 @@ type ConfirmedRoutePropsOnyxProps = { type ConfirmedRouteProps = ConfirmedRoutePropsOnyxProps & { /** Transaction that stores the distance request data */ - transaction: Transaction; + transaction: Transaction | undefined; }; function ConfirmedRoute({mapboxAccessToken, transaction}: ConfirmedRouteProps) { const {isOffline} = useNetwork(); - const {route0: route} = transaction.routes ?? {}; - const waypoints = transaction.comment?.waypoints ?? {}; + const {route0: route} = transaction?.routes ?? {}; + const waypoints = transaction?.comment?.waypoints ?? {}; const coordinates = route?.geometry?.coordinates ?? []; const theme = useTheme(); const styles = useThemeStyles(); diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index c66a58625300..f1d042b29cad 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -1,6 +1,5 @@ import {useIsFocused} from '@react-navigation/native'; import {format} from 'date-fns'; -import {isEmpty} from 'lodash'; import React, {useCallback, useEffect, useMemo, useReducer, useState} from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; @@ -29,6 +28,7 @@ import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; +import type {PaymentType} from '@src/types/onyx/OriginalMessage'; import type {MileageRate} from '@src/types/onyx/Policy'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; import ConfirmedRoute from './ConfirmedRoute'; @@ -43,6 +43,15 @@ import Text from './Text'; import type {WithCurrentUserPersonalDetailsProps} from './withCurrentUserPersonalDetails'; import withCurrentUserPersonalDetails from './withCurrentUserPersonalDetails'; +type Option = Partial; + +type CategorySection = { + title: string | undefined; + shouldShow: boolean; + indexOffset: number; + data: Option[]; +}; + type MoneyRequestConfirmationListOnyxProps = { /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ iou: OnyxEntry; @@ -69,7 +78,7 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & onConfirm?: (selectedParticipants: Participant[]) => void; /** Callback to parent modal to send money */ - onSendMoney?: (paymentMethod: ValueOf) => void; + onSendMoney?: (paymentMethod: PaymentType) => void; /** Callback to inform a participant is selected */ onSelectParticipant?: (option: Participant) => void; @@ -155,11 +164,14 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & /** A flag for verifying that the current report is a sub-report of a workspace chat */ isPolicyExpenseChat?: boolean; + /** Whether there is smartscan failed */ hasSmartScanFailed?: boolean; + /** ID of the report action */ reportActionID?: string; - transaction: OnyxTypes.Transaction; + /** Transaction object */ + transaction?: OnyxTypes.Transaction; }; function MoneyRequestConfirmationList({ @@ -171,7 +183,7 @@ function MoneyRequestConfirmationList({ iouTag = '', iouIsBillable = false, onToggleBillable = () => {}, - payeePersonalDetails = null, + payeePersonalDetails, canModifyParticipants = false, isReadOnly = false, bankAccountRoute = '', @@ -245,7 +257,7 @@ function MoneyRequestConfirmationList({ // A flag for showing the billable field const shouldShowBillable = !policy?.disabledFields?.defaultBillable ?? true; - const hasRoute = TransactionUtils.hasRoute(transaction); + const hasRoute = TransactionUtils.hasRoute(transaction ?? null); const isDistanceRequestWithoutRoute = isDistanceRequest && !hasRoute; const formattedAmount = isDistanceRequestWithoutRoute ? translate('common.tbd') @@ -273,7 +285,7 @@ function MoneyRequestConfirmationList({ return false; } - return (!!hasSmartScanFailed && TransactionUtils.hasMissingSmartscanFields(transaction)) || (didConfirmSplit && TransactionUtils.areRequiredFieldsEmpty(transaction)); + return (!!hasSmartScanFailed && TransactionUtils.hasMissingSmartscanFields(transaction ?? null)) || (didConfirmSplit && TransactionUtils.areRequiredFieldsEmpty(transaction ?? null)); }, [isEditingSplitBill, hasSmartScanFailed, transaction, didConfirmSplit]); const isMerchantEmpty = !iouMerchant || iouMerchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT; @@ -310,7 +322,7 @@ function MoneyRequestConfirmationList({ return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( participantsList, calculatedIouAmount > 0 ? CurrencyUtils.convertToDisplayString(calculatedIouAmount, iouCurrencyCode) : '', - // TODO: Remove assertion after OptionsListUtils will be migrated + // TODO: Remove the assertion once OptionsListUtils (https://github.com/Expensify/App/issues/24921) is migrated to TypeScript. ) as Participant[]; }, [iouAmount, iouCurrencyCode], @@ -346,7 +358,7 @@ function MoneyRequestConfirmationList({ const payeePersonalDetailsMemo = useMemo(() => payeePersonalDetails ?? currentUserPersonalDetails, [payeePersonalDetails, currentUserPersonalDetails]); const canModifyParticipantsValue = !isReadOnly && canModifyParticipants && hasMultipleParticipants; - const optionSelectorSections = useMemo(() => { + const optionSelectorSections: CategorySection[] = useMemo(() => { const sections = []; const unselectedParticipants = selectedParticipants.filter((participant) => !participant.selected); if (hasMultipleParticipants) { @@ -445,17 +457,17 @@ function MoneyRequestConfirmationList({ * Navigate to report details or profile of selected user */ const navigateToReportOrUserDetail = (option: Participant | OnyxTypes.Report) => { - if ('accountID' in option) { + if ('accountID' in option && option.accountID) { const activeRoute = Navigation.getActiveRouteWithoutParams(); Navigation.navigate(ROUTES.PROFILE.getRoute(option.accountID, activeRoute)); - } else if (option.reportID) { + } else if ('reportID' in option && option.reportID) { Navigation.navigate(ROUTES.REPORT_WITH_ID_DETAILS.getRoute(option.reportID)); } }; const confirm = useCallback( - (paymentMethod: ValueOf) => { + (paymentMethod: PaymentType) => { if (selectedParticipantsMemo.length === 0) { return; } @@ -480,7 +492,7 @@ function MoneyRequestConfirmationList({ return; } - if (isEditingSplitBill && TransactionUtils.areRequiredFieldsEmpty(transaction)) { + if (isEditingSplitBill && TransactionUtils.areRequiredFieldsEmpty(transaction ?? null)) { setDidConfirmSplit(true); setFormError('iou.error.genericSmartscanFailureMessage'); return; @@ -540,7 +552,7 @@ function MoneyRequestConfirmationList({ pressOnEnter isDisabled={shouldDisableButton} // eslint-disable-next-line @typescript-eslint/naming-convention - onPress={(_event, value) => confirm(value)} + onPress={(_, value) => confirm(value)} options={splitOrRequestOptions} buttonSize={CONST.DROPDOWN_BUTTON_SIZE.LARGE} /> @@ -574,7 +586,7 @@ function MoneyRequestConfirmationList({ translate, ]); - const receiptData = ReceiptUtils.getThumbnailAndImageURIs(transaction, receiptPath, receiptFilename); + const receiptData = ReceiptUtils.getThumbnailAndImageURIs(transaction ?? null, receiptPath, receiptFilename); return ( // @ts-expect-error TODO: Remove this once OptionsSelector (https://github.com/Expensify/App/issues/25125) is migrated to TypeScript. @@ -626,11 +638,11 @@ function MoneyRequestConfirmationList({ } Navigation.navigate(ROUTES.MONEY_REQUEST_AMOUNT.getRoute(iouType, reportID)); }} - style={{...styles.moneyRequestMenuItem, ...styles.mt2}} + style={[styles.moneyRequestMenuItem, styles.mt2]} titleStyle={styles.moneyRequestConfirmationAmount} disabled={didConfirm} - brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - error={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction) ? translate('common.error.enterAmount') : ''} + brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction ?? null) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + error={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction ?? null) ? translate('common.error.enterAmount') : ''} /> )} )} {isDistanceRequest && ( @@ -707,8 +720,12 @@ function MoneyRequestConfirmationList({ }} disabled={didConfirm} interactive={!isReadOnly} - brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - error={shouldDisplayMerchantError || (shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction)) ? translate('common.error.enterMerchant') : ''} + brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction ?? null) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} + error={ + shouldDisplayMerchantError || (shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction ?? null)) + ? translate('common.error.enterMerchant') + : '' + } /> )} {shouldShowCategories && ( @@ -747,7 +764,7 @@ function MoneyRequestConfirmationList({ style={styles.moneyRequestMenuItem} disabled={didConfirm} interactive={!isReadOnly} - rightLabel={canUseViolations && Boolean(policy?.requiresTag) ? translate('common.required') : ''} + rightLabel={canUseViolations && !!policy?.requiresTag ? translate('common.required') : ''} /> )} diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 5b3347dbfa3e..ecccb451b17f 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -16,12 +16,11 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Beta, Login, PersonalDetails, PersonalDetailsList, Policy, Report, ReportAction, ReportMetadata, Session, Transaction} from '@src/types/onyx'; import type {Errors, Icon, PendingAction} from '@src/types/onyx/OnyxCommon'; -import type {IOUMessage, OriginalMessageActionName, OriginalMessageCreated} from '@src/types/onyx/OriginalMessage'; +import type {IOUMessage, OriginalMessageActionName, OriginalMessageCreated, PaymentType} from '@src/types/onyx/OriginalMessage'; import type {Status} from '@src/types/onyx/PersonalDetails'; import type {NotificationPreference} from '@src/types/onyx/Report'; import type {Message, ReportActionBase, ReportActions} from '@src/types/onyx/ReportAction'; import type {Receipt, WaypointCollection} from '@src/types/onyx/Transaction'; -import type DeepValueOf from '@src/types/utils/DeepValueOf'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject, isNotEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; @@ -2698,7 +2697,7 @@ function buildOptimisticIOUReportAction( comment: string, participants: Participant[], transactionID: string, - paymentType: DeepValueOf, + paymentType: PaymentType, iouReportID = '', isSettlingUp = false, isSendMoneyFlow = false, diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index f10696ced00f..5549b96acdb2 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -2,6 +2,7 @@ import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; +type PaymentType = DeepValueOf; type ActionName = DeepValueOf; type OriginalMessageActionName = | 'ADDCOMMENT' @@ -43,7 +44,7 @@ type IOUMessage = { lastModified?: string; participantAccountIDs?: number[]; type: ValueOf; - paymentType?: DeepValueOf; + paymentType?: PaymentType; /** Only exists when we are sending money */ IOUDetails?: IOUDetails; }; @@ -280,4 +281,5 @@ export type { OriginalMessageIOU, OriginalMessageCreated, OriginalMessageAddComment, + PaymentType, }; diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index a2182298acdf..19cecf3b9e6d 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -92,10 +92,13 @@ type Policy = { /** Whether tax tracking enabled for policy */ isTaxTrackingEnabled?: boolean; + /** List of fields which should disabled for the policy */ disabledFields?: Record; + /** Whether or not the policy requires categories */ requiresCategory?: boolean; + /** Whether or not the policy requires tags */ requiresTag?: boolean; }; diff --git a/src/types/onyx/PolicyTaxRates.ts b/src/types/onyx/PolicyTaxRates.ts index 492cf37a3181..5709ce6338ab 100644 --- a/src/types/onyx/PolicyTaxRates.ts +++ b/src/types/onyx/PolicyTaxRates.ts @@ -8,8 +8,10 @@ type PolicyTaxRate = { /** Whether the tax is disabled */ isDisabled?: boolean; + /** Default policy tax ID */ defaultExternalID: string; + /** List of tax names and values */ taxes: PolicyTaxRates; }; From fab9c8e6ed313751ec28fcd8bb15b8aeba0ccc1d Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 17 Jan 2024 15:37:20 +0100 Subject: [PATCH 016/202] fix: wip --- src/libs/actions/EmojiPickerAction.ts | 2 +- src/libs/actions/User.ts | 6 +- ...tionCompose.js => ReportActionCompose.tsx} | 153 ++++++++++-------- 3 files changed, 88 insertions(+), 73 deletions(-) rename src/pages/home/report/ReportActionCompose/{ReportActionCompose.js => ReportActionCompose.tsx} (81%) diff --git a/src/libs/actions/EmojiPickerAction.ts b/src/libs/actions/EmojiPickerAction.ts index 56a5f34c0b8e..3a4da86dcbb9 100644 --- a/src/libs/actions/EmojiPickerAction.ts +++ b/src/libs/actions/EmojiPickerAction.ts @@ -66,7 +66,7 @@ function showEmojiPicker( /** * Hide the Emoji Picker modal. */ -function hideEmojiPicker(isNavigating: boolean) { +function hideEmojiPicker(isNavigating?: boolean) { if (!emojiPickerRef.current) { return; } diff --git a/src/libs/actions/User.ts b/src/libs/actions/User.ts index 8e3bd5f2c017..e0f3003ed9e8 100644 --- a/src/libs/actions/User.ts +++ b/src/libs/actions/User.ts @@ -13,7 +13,7 @@ import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {FrequentlyUsedEmoji} from '@src/types/onyx'; +import type {BlockedFromConcierge, FrequentlyUsedEmoji} from '@src/types/onyx'; import type Login from '@src/types/onyx/Login'; import type {OnyxServerUpdate} from '@src/types/onyx/OnyxUpdatesFromServer'; import type OnyxPersonalDetails from '@src/types/onyx/PersonalDetails'; @@ -27,8 +27,6 @@ import * as PersonalDetails from './PersonalDetails'; import * as Report from './Report'; import * as Session from './Session'; -type BlockedFromConciergeNVP = {expiresAt: number}; - let currentUserAccountID = -1; let currentEmail = ''; Onyx.connect({ @@ -445,7 +443,7 @@ function validateSecondaryLogin(contactMethod: string, validateCode: string) { * and if so whether the expiresAt date of a user's ban is before right now * */ -function isBlockedFromConcierge(blockedFromConciergeNVP: OnyxEntry): boolean { +function isBlockedFromConcierge(blockedFromConciergeNVP: OnyxEntry): boolean { if (isEmptyObject(blockedFromConciergeNVP)) { return false; } diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.js b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx similarity index 81% rename from src/pages/home/report/ReportActionCompose/ReportActionCompose.js rename to src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index c072666920ae..1f0574f577cb 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.js +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -1,21 +1,23 @@ import {PortalHost} from '@gorhom/portal'; import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; +import type {SyntheticEvent} from 'react'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {View} from 'react-native'; +import {MeasureInWindowOnSuccessCallback, View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import {runOnJS, setNativeProps, useAnimatedRef} from 'react-native-reanimated'; -import _ from 'underscore'; import AttachmentModal from '@components/AttachmentModal'; import EmojiPickerButton from '@components/EmojiPicker/EmojiPickerButton'; import ExceededCommentLength from '@components/ExceededCommentLength'; import OfflineIndicator from '@components/OfflineIndicator'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import {usePersonalDetails, withNetwork} from '@components/OnyxProvider'; -import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsDefaultProps, withCurrentUserPersonalDetailsPropTypes} from '@components/withCurrentUserPersonalDetails'; +import {usePersonalDetails} from '@components/OnyxProvider'; +import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails'; +import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails'; import useDebounce from '@hooks/useDebounce'; import useHandleExceedMaxCommentLength from '@hooks/useHandleExceedMaxCommentLength'; import useLocalize from '@hooks/useLocalize'; +import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus'; @@ -26,69 +28,88 @@ import getModalState from '@libs/getModalState'; import * as ReportUtils from '@libs/ReportUtils'; import willBlurTextInputOnTapOutsideFunc from '@libs/willBlurTextInputOnTapOutside'; import ParticipantLocalTime from '@pages/home/report/ParticipantLocalTime'; -import reportActionPropTypes from '@pages/home/report/reportActionPropTypes'; import ReportDropUI from '@pages/home/report/ReportDropUI'; import ReportTypingIndicator from '@pages/home/report/ReportTypingIndicator'; -import reportPropTypes from '@pages/reportPropTypes'; import * as EmojiPickerActions from '@userActions/EmojiPickerAction'; import * as Report from '@userActions/Report'; import * as User from '@userActions/User'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import type * as OnyxTypes from '@src/types/onyx'; +import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import AttachmentPickerWithMenuItems from './AttachmentPickerWithMenuItems'; import ComposerWithSuggestions from './ComposerWithSuggestions'; import SendButton from './SendButton'; -const propTypes = { +type ComposerRef = { + blur: () => void; + focus: (shouldDelay?: boolean) => void; + replaceSelectionWithText: (text: string, shouldAddTrailSpace: boolean) => void; + prepareCommentAndResetComposer: () => string; + isFocused: () => boolean; +}; + +type SuggestionsRef = { + resetSuggestions: () => void; + onSelectionChange: (event: any) => void; + triggerHotkeyActions: (event: any) => void; + updateShouldShowSuggestionMenuToFalse: () => void; + setShouldBlockSuggestionCalc: (shouldBlock: boolean) => void; + getSuggestions: () => string[]; +}; + +type ReportActionComposeOnyxProps = { + /** The NVP describing a user's block status */ + blockedFromConcierge: OnyxEntry; + + /** Whether the composer input should be shown */ + shouldShowComposeInput: OnyxEntry; +}; + +type ReportActionComposeProps = { /** A method to call when the form is submitted */ - onSubmit: PropTypes.func.isRequired, + onSubmit: (newComment: string | undefined) => void; /** The ID of the report actions will be created for */ - reportID: PropTypes.string.isRequired, + reportID: string; /** Array of report actions for this report */ - reportActions: PropTypes.arrayOf(PropTypes.shape(reportActionPropTypes)), + reportActions?: OnyxTypes.ReportAction[]; /** The report currently being looked at */ - report: reportPropTypes, + report: OnyxEntry; /** Is composer full size */ - isComposerFullSize: PropTypes.bool, + isComposerFullSize?: boolean; /** Whether user interactions should be disabled */ - disabled: PropTypes.bool, + disabled?: boolean; /** Height of the list which the composer is part of */ - listHeight: PropTypes.number, - - // The NVP describing a user's block status - blockedFromConcierge: PropTypes.shape({ - // The date that the user will be unblocked - expiresAt: PropTypes.string, - }), + listHeight?: number; /** Whether the composer input should be shown */ - shouldShowComposeInput: PropTypes.bool, + shouldShowComposeInput?: boolean; /** The type of action that's pending */ - pendingAction: PropTypes.oneOf(['add', 'update', 'delete']), + pendingAction?: OnyxCommon.PendingAction; /** /** Whetjer the report is ready for display */ - isReportReadyForDisplay: PropTypes.bool, - ...withCurrentUserPersonalDetailsPropTypes, -}; - -const defaultProps = { - report: {}, - blockedFromConcierge: {}, - preferredSkinTone: CONST.EMOJI_DEFAULT_SKIN_TONE, - isComposerFullSize: false, - pendingAction: null, - shouldShowComposeInput: true, - listHeight: 0, - isReportReadyForDisplay: true, - ...withCurrentUserPersonalDetailsDefaultProps, -}; + isReportReadyForDisplay?: boolean; +} & ReportActionComposeOnyxProps & + WithCurrentUserPersonalDetailsProps; + +// const defaultProps = { +// report: {}, +// blockedFromConcierge: {}, +// preferredSkinTone: CONST.EMOJI_DEFAULT_SKIN_TONE, +// isComposerFullSize: false, +// pendingAction: null, +// shouldShowComposeInput: true, +// listHeight: 0, +// isReportReadyForDisplay: true, +// ...withCurrentUserPersonalDetailsDefaultProps, +// }; // We want consistent auto focus behavior on input between native and mWeb so we have some auto focus management code that will // prevent auto focus on existing chat for mobile device @@ -101,7 +122,6 @@ function ReportActionCompose({ currentUserPersonalDetails, disabled, isComposerFullSize, - network, onSubmit, pendingAction, report, @@ -110,10 +130,11 @@ function ReportActionCompose({ listHeight, shouldShowComposeInput, isReportReadyForDisplay, -}) { +}: ReportActionComposeProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const {isMediumScreenWidth, isSmallScreenWidth} = useWindowDimensions(); + const {isOffline} = useNetwork(); const animatedRef = useAnimatedRef(); const actionButtonRef = useRef(null); const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT; @@ -122,7 +143,7 @@ function ReportActionCompose({ */ const [isFocused, setIsFocused] = useState(() => { const initialModalState = getModalState(); - return shouldFocusInputOnScreenFocus && shouldShowComposeInput && !initialModalState.isVisible && !initialModalState.willAlertModalBecomeVisible; + return shouldFocusInputOnScreenFocus && shouldShowComposeInput && !initialModalState?.isVisible && !initialModalState?.willAlertModalBecomeVisible; }); const [isFullComposerAvailable, setIsFullComposerAvailable] = useState(isComposerFullSize); @@ -167,11 +188,11 @@ function ReportActionCompose({ */ const {hasExceededMaxCommentLength, validateCommentMaxLength} = useHandleExceedMaxCommentLength(); - const suggestionsRef = useRef(null); - const composerRef = useRef(null); + const suggestionsRef = useRef(null); + const composerRef = useRef(null); const reportParticipantIDs = useMemo( - () => _.without(lodashGet(report, 'participantAccountIDs', []), currentUserPersonalDetails.accountID), + () => report?.participantAccountIDs?.filter((accountID) => accountID !== currentUserPersonalDetails.accountID), [currentUserPersonalDetails.accountID, report], ); @@ -184,7 +205,7 @@ function ReportActionCompose({ // If we are on a small width device then don't show last 3 items from conciergePlaceholderOptions const conciergePlaceholderRandomIndex = useMemo( - () => _.random(translate('reportActionCompose.conciergePlaceholderOptions').length - (isSmallScreenWidth ? 4 : 1)), + () => Math.floor(Math.random() * (translate('reportActionCompose.conciergePlaceholderOptions').length - (isSmallScreenWidth ? 4 : 1) + 1)), // eslint-disable-next-line react-hooks/exhaustive-deps [], ); @@ -203,7 +224,7 @@ function ReportActionCompose({ }, [report, blockedFromConcierge, translate, conciergePlaceholderRandomIndex]); const focus = () => { - if (composerRef === null || composerRef.current === null) { + if (composerRef?.current === null) { return; } composerRef.current.focus(true); @@ -219,9 +240,9 @@ function ReportActionCompose({ isKeyboardVisibleWhenShowingModalRef.current = false; }, []); - const containerRef = useRef(null); + const containerRef = useRef(null); const measureContainer = useCallback( - (callback) => { + (callback: MeasureInWindowOnSuccessCallback) => { if (!containerRef.current) { return; } @@ -234,9 +255,9 @@ function ReportActionCompose({ const onAddActionPressed = useCallback(() => { if (!willBlurTextInputOnTapOutside) { - isKeyboardVisibleWhenShowingModalRef.current = composerRef.current.isFocused(); + isKeyboardVisibleWhenShowingModalRef.current = !!composerRef.current?.isFocused(); } - composerRef.current.blur(); + composerRef.current?.blur(); }, []); const onItemSelected = useCallback(() => { @@ -250,12 +271,9 @@ function ReportActionCompose({ suggestionsRef.current.updateShouldShowSuggestionMenuToFalse(false); }, []); - /** - * @param {Object} file - */ const addAttachment = useCallback( - (file) => { - const newComment = composerRef.current.prepareCommentAndResetComposer(); + (file: File) => { + const newComment = composerRef.current?.prepareCommentAndResetComposer(); Report.addAttachment(reportID, file, newComment); setTextInputShouldClear(false); }, @@ -273,16 +291,14 @@ function ReportActionCompose({ /** * Add a new comment to this chat - * - * @param {SyntheticEvent} [e] */ const submitForm = useCallback( - (e) => { + (e?: SyntheticEvent) => { if (e) { e.preventDefault(); } - const newComment = composerRef.current.prepareCommentAndResetComposer(); + const newComment = composerRef.current?.prepareCommentAndResetComposer(); if (!newComment) { return; } @@ -323,7 +339,7 @@ function ReportActionCompose({ // We are returning a callback here as we want to incoke the method on unmount only useEffect( () => () => { - if (!EmojiPickerActions.isActive(report.reportID)) { + if (!EmojiPickerActions.isActive(report?.reportID ?? '')) { return; } EmojiPickerActions.hideEmojiPicker(); @@ -338,7 +354,7 @@ function ReportActionCompose({ const hasReportRecipient = _.isObject(reportRecipient) && !_.isEmpty(reportRecipient); - const isSendDisabled = isCommentEmpty || isBlockedFromConcierge || disabled || hasExceededMaxCommentLength; + const isSendDisabled = isCommentEmpty || isBlockedFromConcierge || !!disabled || hasExceededMaxCommentLength; const handleSendMessage = useCallback(() => { 'worklet'; @@ -355,7 +371,7 @@ function ReportActionCompose({ }, [isSendDisabled, resetFullComposerSize, submitForm, animatedRef, isReportReadyForDisplay]); return ( - + {shouldShowReportRecipientLocalTime && hasReportRecipient && } @@ -376,12 +392,14 @@ function ReportActionCompose({ hasExceededMaxCommentLength && styles.borderColorDanger, ]} > + {/* @ts-expect-error TODO: Remove this once AttachmentModal (https://github.com/Expensify/App/issues/25130) is migrated to TypeScript. */} setIsAttachmentPreviewActive(true)} onModalHide={onAttachmentPreviewClose} > + {/* @ts-expect-error TODO: Remove this once AttachmentModal (https://github.com/Expensify/App/issues/25130) is migrated to TypeScript. */} {({displayFileInModal}) => ( <> composerRef.current.replaceSelectionWithText(...args)} - emojiPickerID={report.reportID} + // @ts-expect-error TODO: Remove this once EmojiPickerButton is migrated to TypeScript. + onEmojiSelected={(...args) => composerRef.current?.replaceSelectionWithText(...args)} + emojiPickerID={report?.reportID} /> )} {!isSmallScreenWidth && } @@ -478,12 +498,9 @@ function ReportActionCompose({ ); } -ReportActionCompose.propTypes = propTypes; -ReportActionCompose.defaultProps = defaultProps; ReportActionCompose.displayName = 'ReportActionCompose'; export default compose( - withNetwork(), withCurrentUserPersonalDetails, withOnyx({ blockedFromConcierge: { From 25f6646d0486eb0ce45714956e7118c65281ef31 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 18 Jan 2024 10:46:39 +0100 Subject: [PATCH 017/202] fix: finish working on migration --- .../ReportActionCompose.tsx | 52 +++++++------------ 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 1f0574f577cb..2cdb4e4d3602 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -1,8 +1,8 @@ import {PortalHost} from '@gorhom/portal'; -import lodashGet from 'lodash/get'; import type {SyntheticEvent} from 'react'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {MeasureInWindowOnSuccessCallback, View} from 'react-native'; +import type {MeasureInWindowOnSuccessCallback, NativeSyntheticEvent, TextInputSelectionChangeEventData} from 'react-native'; +import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import {runOnJS, setNativeProps, useAnimatedRef} from 'react-native-reanimated'; @@ -21,7 +21,6 @@ import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus'; -import compose from '@libs/compose'; import getDraftComment from '@libs/ComposerUtils/getDraftComment'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import getModalState from '@libs/getModalState'; @@ -37,6 +36,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; import AttachmentPickerWithMenuItems from './AttachmentPickerWithMenuItems'; import ComposerWithSuggestions from './ComposerWithSuggestions'; import SendButton from './SendButton'; @@ -51,9 +51,9 @@ type ComposerRef = { type SuggestionsRef = { resetSuggestions: () => void; - onSelectionChange: (event: any) => void; - triggerHotkeyActions: (event: any) => void; - updateShouldShowSuggestionMenuToFalse: () => void; + onSelectionChange: (event: NativeSyntheticEvent) => void; + triggerHotkeyActions: (event: KeyboardEvent) => void; + updateShouldShowSuggestionMenuToFalse: (shouldShowSuggestionMenu: boolean) => void; setShouldBlockSuggestionCalc: (shouldBlock: boolean) => void; getSuggestions: () => string[]; }; @@ -99,18 +99,6 @@ type ReportActionComposeProps = { } & ReportActionComposeOnyxProps & WithCurrentUserPersonalDetailsProps; -// const defaultProps = { -// report: {}, -// blockedFromConcierge: {}, -// preferredSkinTone: CONST.EMOJI_DEFAULT_SKIN_TONE, -// isComposerFullSize: false, -// pendingAction: null, -// shouldShowComposeInput: true, -// listHeight: 0, -// isReportReadyForDisplay: true, -// ...withCurrentUserPersonalDetailsDefaultProps, -// }; - // We want consistent auto focus behavior on input between native and mWeb so we have some auto focus management code that will // prevent auto focus on existing chat for mobile device const shouldFocusInputOnScreenFocus = canFocusInputOnScreenFocus(); @@ -119,17 +107,17 @@ const willBlurTextInputOnTapOutside = willBlurTextInputOnTapOutsideFunc(); function ReportActionCompose({ blockedFromConcierge, - currentUserPersonalDetails, + currentUserPersonalDetails = {}, disabled, - isComposerFullSize, + isComposerFullSize = false, onSubmit, pendingAction, report, reportID, reportActions, - listHeight, - shouldShowComposeInput, - isReportReadyForDisplay, + listHeight = 0, + shouldShowComposeInput = true, + isReportReadyForDisplay = true, }: ReportActionComposeProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -313,7 +301,7 @@ function ReportActionCompose({ isKeyboardVisibleWhenShowingModalRef.current = true; }, []); - const onBlur = useCallback((e) => { + const onBlur = useCallback((e: FocusEvent) => { setIsFocused(false); if (suggestionsRef.current) { suggestionsRef.current.resetSuggestions(); @@ -352,7 +340,7 @@ function ReportActionCompose({ const reportRecipient = personalDetails[reportRecipientAcountIDs[0]]; const shouldUseFocusedColor = !isBlockedFromConcierge && !disabled && isFocused; - const hasReportRecipient = _.isObject(reportRecipient) && !_.isEmpty(reportRecipient); + const hasReportRecipient = !isEmptyObject(reportRecipient); const isSendDisabled = isCommentEmpty || isBlockedFromConcierge || !!disabled || hasExceededMaxCommentLength; @@ -403,6 +391,7 @@ function ReportActionCompose({ {({displayFileInModal}) => ( <> { + onDrop={(e: DragEvent) => { if (isAttachmentPreviewActive) { return; } - const data = lodashGet(e, ['dataTransfer', 'items', 0]); + const data = e.dataTransfer?.items[0]; displayFileInModal(data); }} /> @@ -500,14 +489,13 @@ function ReportActionCompose({ ReportActionCompose.displayName = 'ReportActionCompose'; -export default compose( - withCurrentUserPersonalDetails, - withOnyx({ +export default withCurrentUserPersonalDetails( + withOnyx({ blockedFromConcierge: { key: ONYXKEYS.NVP_BLOCKED_FROM_CONCIERGE, }, shouldShowComposeInput: { key: ONYXKEYS.SHOULD_SHOW_COMPOSE_INPUT, }, - }), -)(ReportActionCompose); + })(ReportActionCompose), +); From 032e9e32f529ab28001a5db554460cbfd3125fa4 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 18 Jan 2024 17:01:26 +0700 Subject: [PATCH 018/202] display correct tooltip for the case subscription --- src/components/MultipleAvatars.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/components/MultipleAvatars.tsx b/src/components/MultipleAvatars.tsx index 48a9bd77c09e..5b639d832dce 100644 --- a/src/components/MultipleAvatars.tsx +++ b/src/components/MultipleAvatars.tsx @@ -107,7 +107,6 @@ function MultipleAvatars({ let avatarContainerStyles = StyleUtils.getContainerStyles(size, isInReportAction); const {singleAvatarStyle, secondAvatarStyles} = useMemo(() => avatarSizeToStylesMap[size as AvatarSizeToStyles] ?? avatarSizeToStylesMap.default, [size, avatarSizeToStylesMap]); - const tooltipTexts = useMemo(() => (shouldShowTooltip ? icons.map((icon) => icon.name) : ['']), [shouldShowTooltip, icons]); const avatarSize = useMemo(() => { if (isFocusMode) { return CONST.AVATAR_SIZE.MID_SUBSCRIPT; @@ -215,9 +214,13 @@ function MultipleAvatars({ {avatars.length > maxAvatarsInRow && ( Number(icon.id)), - )} + text={ + shouldShowTooltip + ? ReportUtils.getUserDetailsTooltipText( + icons.slice(avatarRows.length * maxAvatarsInRow - 1, avatarRows.length * maxAvatarsInRow + 9).map((icon) => Number(icon.id)), + ) + : '' + } > ) : ( - + Number(icon.id))) : ''}> Date: Thu, 18 Jan 2024 13:40:22 +0100 Subject: [PATCH 019/202] fix: typecheck --- src/components/ButtonWithDropdownMenu.tsx | 4 ++-- src/components/MoneyRequestConfirmationList.tsx | 4 ++-- src/components/PopoverMenu.tsx | 2 +- src/libs/DistanceRequestUtils.ts | 12 +++--------- src/types/onyx/IOU.ts | 2 ++ src/types/onyx/Policy.ts | 2 +- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/components/ButtonWithDropdownMenu.tsx b/src/components/ButtonWithDropdownMenu.tsx index 466c68229a32..fc33c373ad45 100644 --- a/src/components/ButtonWithDropdownMenu.tsx +++ b/src/components/ButtonWithDropdownMenu.tsx @@ -19,7 +19,7 @@ import PopoverMenu from './PopoverMenu'; type DropdownOption = { value: string; text: string; - icon: IconAsset; + icon?: IconAsset; iconWidth?: number; iconHeight?: number; iconDescription?: string; @@ -55,7 +55,7 @@ type ButtonWithDropdownMenuProps = { anchorAlignment?: AnchorAlignment; /* ref for the button */ - buttonRef: RefObject; + buttonRef?: RefObject; }; function ButtonWithDropdownMenu({ diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index f1d042b29cad..3712e928a5e1 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -20,7 +20,6 @@ import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReceiptUtils from '@libs/ReceiptUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import type {Participant} from '@libs/ReportUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; @@ -28,6 +27,7 @@ import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; +import type {Participant} from '@src/types/onyx/IOU'; import type {PaymentType} from '@src/types/onyx/OriginalMessage'; import type {MileageRate} from '@src/types/onyx/Policy'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; @@ -552,7 +552,7 @@ function MoneyRequestConfirmationList({ pressOnEnter isDisabled={shouldDisableButton} // eslint-disable-next-line @typescript-eslint/naming-convention - onPress={(_, value) => confirm(value)} + onPress={(_, value) => confirm(value as PaymentType)} options={splitOrRequestOptions} buttonSize={CONST.DROPDOWN_BUTTON_SIZE.LARGE} /> diff --git a/src/components/PopoverMenu.tsx b/src/components/PopoverMenu.tsx index 17b1a119671a..ae995c899521 100644 --- a/src/components/PopoverMenu.tsx +++ b/src/components/PopoverMenu.tsx @@ -17,7 +17,7 @@ import Text from './Text'; type PopoverMenuItem = { /** An icon element displayed on the left side */ - icon: IconAsset; + icon?: IconAsset; /** Text label */ text: string; diff --git a/src/libs/DistanceRequestUtils.ts b/src/libs/DistanceRequestUtils.ts index c92e9bfd3f67..6c7444ea12c7 100644 --- a/src/libs/DistanceRequestUtils.ts +++ b/src/libs/DistanceRequestUtils.ts @@ -1,17 +1,11 @@ import type {OnyxEntry} from 'react-native-onyx'; import type {LocaleContextProps} from '@components/LocaleContextProvider'; import CONST from '@src/CONST'; -import type {Unit} from '@src/types/onyx/Policy'; +import type {MileageRate, Unit} from '@src/types/onyx/Policy'; import type Policy from '@src/types/onyx/Policy'; import * as CurrencyUtils from './CurrencyUtils'; import * as PolicyUtils from './PolicyUtils'; -type DefaultMileageRate = { - rate?: number; - currency?: string; - unit: Unit; -}; - /** * Retrieves the default mileage rate based on a given policy. * @@ -22,7 +16,7 @@ type DefaultMileageRate = { * @returns [currency] - The currency associated with the rate. * @returns [unit] - The unit of measurement for the distance. */ -function getDefaultMileageRate(policy: OnyxEntry): DefaultMileageRate | null { +function getDefaultMileageRate(policy: OnyxEntry): MileageRate | null { if (!policy?.customUnits) { return null; } @@ -39,7 +33,7 @@ function getDefaultMileageRate(policy: OnyxEntry): DefaultMileageRate | return { rate: distanceRate.rate, - currency: distanceRate.currency, + currency: distanceRate.currency ?? 'USD', unit: distanceUnit.attributes.unit, }; } diff --git a/src/types/onyx/IOU.ts b/src/types/onyx/IOU.ts index a89b0d4530ef..220af7005c45 100644 --- a/src/types/onyx/IOU.ts +++ b/src/types/onyx/IOU.ts @@ -23,3 +23,5 @@ type IOU = { }; export default IOU; + +export type {Participant}; diff --git a/src/types/onyx/Policy.ts b/src/types/onyx/Policy.ts index ee8c69fa3f21..e5681e53dc15 100644 --- a/src/types/onyx/Policy.ts +++ b/src/types/onyx/Policy.ts @@ -19,7 +19,7 @@ type Attributes = { type MileageRate = { unit: Unit; - rate: number; + rate?: number; currency: string; }; From 5e2f31c82fda91671e4c4c1e601a7755335fb67f Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Fri, 19 Jan 2024 11:33:28 +0100 Subject: [PATCH 020/202] fix: resolve comments --- .../ReportActionCompose.tsx | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 2cdb4e4d3602..73b025c50df2 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -88,13 +88,10 @@ type ReportActionComposeProps = { /** Height of the list which the composer is part of */ listHeight?: number; - /** Whether the composer input should be shown */ - shouldShowComposeInput?: boolean; - /** The type of action that's pending */ pendingAction?: OnyxCommon.PendingAction; - /** /** Whetjer the report is ready for display */ + /** Whether the report is ready for display */ isReportReadyForDisplay?: boolean; } & ReportActionComposeOnyxProps & WithCurrentUserPersonalDetailsProps; @@ -212,7 +209,7 @@ function ReportActionCompose({ }, [report, blockedFromConcierge, translate, conciergePlaceholderRandomIndex]); const focus = () => { - if (composerRef?.current === null) { + if (composerRef.current === null) { return; } composerRef.current.focus(true); @@ -281,9 +278,9 @@ function ReportActionCompose({ * Add a new comment to this chat */ const submitForm = useCallback( - (e?: SyntheticEvent) => { - if (e) { - e.preventDefault(); + (event?: SyntheticEvent) => { + if (event) { + event.preventDefault(); } const newComment = composerRef.current?.prepareCommentAndResetComposer(); @@ -301,12 +298,12 @@ function ReportActionCompose({ isKeyboardVisibleWhenShowingModalRef.current = true; }, []); - const onBlur = useCallback((e: FocusEvent) => { + const onBlur = useCallback((event: FocusEvent) => { setIsFocused(false); if (suggestionsRef.current) { suggestionsRef.current.resetSuggestions(); } - if (e.relatedTarget && e.relatedTarget === actionButtonRef.current) { + if (event.relatedTarget && event.relatedTarget === actionButtonRef.current) { isKeyboardVisibleWhenShowingModalRef.current = true; } }, []); @@ -444,11 +441,11 @@ function ReportActionCompose({ onValueChange={validateCommentMaxLength} /> { + onDrop={(event: DragEvent) => { if (isAttachmentPreviewActive) { return; } - const data = e.dataTransfer?.items[0]; + const data = event.dataTransfer?.items[0]; displayFileInModal(data); }} /> @@ -459,7 +456,7 @@ function ReportActionCompose({ composerRef.current?.replaceSelectionWithText(...args)} emojiPickerID={report?.reportID} /> From 2a0e3e21c0b61a5f9409137e29986e4d14c93bac Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Fri, 19 Jan 2024 15:14:18 +0100 Subject: [PATCH 021/202] ref: move SuggestionMention, Suggestions to TS, fixes to MentionSuggestions and ReportActionCompose --- src/components/MentionSuggestions.tsx | 6 +- .../ReportActionCompose.tsx | 9 +- ...SuggestionEmoji.js => SuggestionEmoji.tsx} | 84 ++++------ ...estionMention.js => SuggestionMention.tsx} | 145 ++++++++---------- .../{Suggestions.js => Suggestions.tsx} | 119 +++++++------- src/types/onyx/OnyxCommon.ts | 2 +- 6 files changed, 159 insertions(+), 206 deletions(-) rename src/pages/home/report/ReportActionCompose/{SuggestionEmoji.js => SuggestionEmoji.tsx} (86%) rename src/pages/home/report/ReportActionCompose/{SuggestionMention.js => SuggestionMention.tsx} (73%) rename src/pages/home/report/ReportActionCompose/{Suggestions.js => Suggestions.tsx} (54%) diff --git a/src/components/MentionSuggestions.tsx b/src/components/MentionSuggestions.tsx index 459131ecc434..99930f995a3a 100644 --- a/src/components/MentionSuggestions.tsx +++ b/src/components/MentionSuggestions.tsx @@ -18,7 +18,7 @@ type Mention = { alternateText: string; /** Email/phone number of the user */ - login: string; + login?: string; /** Array of icons of the user. We use the first element of this array */ icons: Icon[]; @@ -32,7 +32,7 @@ type MentionSuggestionsProps = { mentions: Mention[]; /** Fired when the user selects a mention */ - onSelect: () => void; + onSelect: (highlightedMentionIndex: number) => void; /** Mention prefix that follows the @ sign */ prefix: string; @@ -142,3 +142,5 @@ function MentionSuggestions({prefix, mentions, highlightedMentionIndex = 0, onSe MentionSuggestions.displayName = 'MentionSuggestions'; export default MentionSuggestions; + +export type {Mention}; diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 73b025c50df2..025b7142df0d 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -9,6 +9,7 @@ import {runOnJS, setNativeProps, useAnimatedRef} from 'react-native-reanimated'; import AttachmentModal from '@components/AttachmentModal'; import EmojiPickerButton from '@components/EmojiPicker/EmojiPickerButton'; import ExceededCommentLength from '@components/ExceededCommentLength'; +import type {Mention} from '@components/MentionSuggestions'; import OfflineIndicator from '@components/OfflineIndicator'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import {usePersonalDetails} from '@components/OnyxProvider'; @@ -51,11 +52,11 @@ type ComposerRef = { type SuggestionsRef = { resetSuggestions: () => void; - onSelectionChange: (event: NativeSyntheticEvent) => void; + onSelectionChange?: (event: NativeSyntheticEvent) => void; triggerHotkeyActions: (event: KeyboardEvent) => void; - updateShouldShowSuggestionMenuToFalse: (shouldShowSuggestionMenu: boolean) => void; + updateShouldShowSuggestionMenuToFalse: (shouldShowSuggestionMenu?: boolean) => void; setShouldBlockSuggestionCalc: (shouldBlock: boolean) => void; - getSuggestions: () => string[]; + getSuggestions: () => Mention[]; }; type ReportActionComposeOnyxProps = { @@ -496,3 +497,5 @@ export default withCurrentUserPersonalDetails( }, })(ReportActionCompose), ); + +export type {SuggestionsRef}; diff --git a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.js b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx similarity index 86% rename from src/pages/home/report/ReportActionCompose/SuggestionEmoji.js rename to src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx index e35d1e90bd5a..06089b748554 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.js +++ b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; -import React, {useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; +import React, {ForwardedRef, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import EmojiSuggestions from '@components/EmojiSuggestions'; @@ -9,17 +10,15 @@ import * as EmojiUtils from '@libs/EmojiUtils'; import * as SuggestionsUtils from '@libs/SuggestionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import * as SuggestionProps from './suggestionProps'; +// eslint-disable-next-line import/no-cycle +import {SuggestionProps} from './Suggestions'; /** * Check if this piece of string looks like an emoji - * @param {String} str - * @param {Number} pos - * @returns {Boolean} */ -const isEmojiCode = (str, pos) => { +const isEmojiCode = (str: string, pos: number): boolean => { const leftWords = str.slice(0, pos).split(CONST.REGEX.SPECIAL_CHAR_OR_EMOJI); - const leftWord = _.last(leftWords); + const leftWord = leftWords.at(-1) ?? ''; return CONST.REGEX.HAS_COLON_ONLY_AT_THE_BEGINNING.test(leftWord) && leftWord.length > 2; }; @@ -29,38 +28,33 @@ const defaultSuggestionsValues = { shouldShowSuggestionMenu: false, }; -const propTypes = { +type SuggestionEmojiOnyxProps = { /** Preferred skin tone */ - preferredSkinTone: PropTypes.number, - - /** A ref to this component */ - forwardedRef: PropTypes.shape({current: PropTypes.shape({})}), - - /** Function to clear the input */ - resetKeyboardInput: PropTypes.func.isRequired, - - ...SuggestionProps.baseProps, + preferredSkinTone: OnyxEntry; }; -const defaultProps = { - preferredSkinTone: CONST.EMOJI_DEFAULT_SKIN_TONE, - forwardedRef: null, -}; - -function SuggestionEmoji({ - preferredSkinTone, - value, - setValue, - selection, - setSelection, - updateComment, - isComposerFullSize, - isAutoSuggestionPickerLarge, - forwardedRef, - resetKeyboardInput, - measureParentContainer, - isComposerFocused, -}) { +type SuggestionEmojiProps = { + /** Function to clear the input */ + resetKeyboardInput: () => void; +} & SuggestionEmojiOnyxProps & + SuggestionProps; + +function SuggestionEmoji( + { + preferredSkinTone = CONST.EMOJI_DEFAULT_SKIN_TONE, + value, + setValue, + selection, + setSelection, + updateComment, + isComposerFullSize, + isAutoSuggestionPickerLarge, + resetKeyboardInput, + measureParentContainer, + isComposerFocused, + }: SuggestionEmojiProps, + ref: ForwardedRef, +) { const [suggestionValues, setSuggestionValues] = useState(defaultSuggestionsValues); const isEmojiSuggestionsMenuVisible = !_.isEmpty(suggestionValues.suggestedEmojis) && suggestionValues.shouldShowSuggestionMenu; @@ -214,7 +208,7 @@ function SuggestionEmoji({ }, []); useImperativeHandle( - forwardedRef, + ref, () => ({ resetSuggestions, onSelectionChange, @@ -248,23 +242,11 @@ function SuggestionEmoji({ ); } -SuggestionEmoji.propTypes = propTypes; -SuggestionEmoji.defaultProps = defaultProps; SuggestionEmoji.displayName = 'SuggestionEmoji'; -const SuggestionEmojiWithRef = React.forwardRef((props, ref) => ( - -)); - -SuggestionEmojiWithRef.displayName = 'SuggestionEmojiWithRef'; - -export default withOnyx({ +export default withOnyx({ preferredSkinTone: { key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, selector: EmojiUtils.getPreferredSkinToneIndex, }, -})(SuggestionEmojiWithRef); +})(forwardRef(SuggestionEmoji)); diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.js b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx similarity index 73% rename from src/pages/home/report/ReportActionCompose/SuggestionMention.js rename to src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index af3074eec06d..5ce33d916a08 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.js +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -1,7 +1,7 @@ -import PropTypes from 'prop-types'; -import React, {useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; -import _ from 'underscore'; +import type {ForwardedRef} from 'react'; +import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; import * as Expensicons from '@components/Icon/Expensicons'; +import type {Mention} from '@components/MentionSuggestions'; import MentionSuggestions from '@components/MentionSuggestions'; import {usePersonalDetails} from '@components/OnyxProvider'; import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; @@ -11,52 +11,41 @@ import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as SuggestionsUtils from '@libs/SuggestionUtils'; import * as UserUtils from '@libs/UserUtils'; import CONST from '@src/CONST'; -import * as SuggestionProps from './suggestionProps'; +import type {PersonalDetailsList} from '@src/types/onyx'; +import type {SuggestionsRef} from './ReportActionCompose'; +import type {SuggestionProps} from './Suggestions'; + +type SuggestionMentionProps = {isAutoSuggestionPickerLarge: boolean} & SuggestionProps; + +type SuggestionValues = { + suggestedMentions: Mention[]; + atSignIndex: number; + shouldShowSuggestionMenu: boolean; + mentionPrefix: string; +}; /** * Check if this piece of string looks like a mention - * @param {String} str - * @returns {Boolean} */ -const isMentionCode = (str) => CONST.REGEX.HAS_AT_MOST_TWO_AT_SIGNS.test(str); +const isMentionCode = (str: string): boolean => CONST.REGEX.HAS_AT_MOST_TWO_AT_SIGNS.test(str); -const defaultSuggestionsValues = { +const defaultSuggestionsValues: SuggestionValues = { suggestedMentions: [], atSignIndex: -1, shouldShowSuggestionMenu: false, mentionPrefix: '', }; -const propTypes = { - /** A ref to this component */ - forwardedRef: PropTypes.shape({current: PropTypes.shape({})}), - - ...SuggestionProps.implementationBaseProps, -}; - -const defaultProps = { - forwardedRef: null, -}; - -function SuggestionMention({ - value, - setValue, - selection, - setSelection, - isComposerFullSize, - updateComment, - composerHeight, - forwardedRef, - isAutoSuggestionPickerLarge, - measureParentContainer, - isComposerFocused, -}) { - const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT; +function SuggestionMention( + {value, selection, setSelection, updateComment, isAutoSuggestionPickerLarge, measureParentContainer, isComposerFocused}: SuggestionMentionProps, + ref: ForwardedRef, +) { + const personalDetails = usePersonalDetails() ?? CONST.EMPTY_OBJECT; const {translate, formatPhoneNumber} = useLocalize(); const previousValue = usePrevious(value); const [suggestionValues, setSuggestionValues] = useState(defaultSuggestionsValues); - const isMentionSuggestionsMenuVisible = !_.isEmpty(suggestionValues.suggestedMentions) && suggestionValues.shouldShowSuggestionMenu; + const isMentionSuggestionsMenuVisible = !!suggestionValues.suggestedMentions.length && suggestionValues.shouldShowSuggestionMenu; const [highlightedMentionIndex, setHighlightedMentionIndex] = useArrowKeyFocusManager({ isActive: isMentionSuggestionsMenuVisible, @@ -69,10 +58,9 @@ function SuggestionMention({ /** * Replace the code of mention and update selection - * @param {Number} highlightedMentionIndex */ const insertSelectedMention = useCallback( - (highlightedMentionIndexInner) => { + (highlightedMentionIndexInner: number) => { const commentBeforeAtSign = value.slice(0, suggestionValues.atSignIndex); const mentionObject = suggestionValues.suggestedMentions[highlightedMentionIndexInner]; const mentionCode = mentionObject.text === CONST.AUTO_COMPLETE_SUGGESTER.HERE_TEXT ? CONST.AUTO_COMPLETE_SUGGESTER.HERE_TEXT : `@${mentionObject.login}`; @@ -100,23 +88,21 @@ function SuggestionMention({ /** * Listens for keyboard shortcuts and applies the action - * - * @param {Object} e */ const triggerHotkeyActions = useCallback( - (e) => { + (event: KeyboardEvent) => { const suggestionsExist = suggestionValues.suggestedMentions.length > 0; - if (((!e.shiftKey && e.key === CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey) || e.key === CONST.KEYBOARD_SHORTCUTS.TAB.shortcutKey) && suggestionsExist) { - e.preventDefault(); + if (((!event.shiftKey && event.key === CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey) || event.key === CONST.KEYBOARD_SHORTCUTS.TAB.shortcutKey) && suggestionsExist) { + event.preventDefault(); if (suggestionValues.suggestedMentions.length > 0) { insertSelectedMention(highlightedMentionIndex); return true; } } - if (e.key === CONST.KEYBOARD_SHORTCUTS.ESCAPE.shortcutKey) { - e.preventDefault(); + if (event.key === CONST.KEYBOARD_SHORTCUTS.ESCAPE.shortcutKey) { + event.preventDefault(); if (suggestionsExist) { resetSuggestions(); @@ -129,7 +115,7 @@ function SuggestionMention({ ); const getMentionOptions = useCallback( - (personalDetailsParam, searchValue = '') => { + (personalDetailsParam: PersonalDetailsList, searchValue = ''): Mention[] => { const suggestions = []; if (CONST.AUTO_COMPLETE_SUGGESTER.HERE_TEXT.includes(searchValue.toLowerCase())) { @@ -139,15 +125,15 @@ function SuggestionMention({ icons: [ { source: Expensicons.Megaphone, - type: 'avatar', + type: CONST.ICON_TYPE_AVATAR, }, ], }); } - const filteredPersonalDetails = _.filter(_.values(personalDetailsParam), (detail) => { + const filteredPersonalDetails = Object.values(personalDetailsParam ?? {}).filter((detail) => { // If we don't have user's primary login, that member is not known to the current user and hence we do not allow them to be mentioned - if (!detail.login || detail.isOptimisticPersonalDetail) { + if (!detail?.login || detail.isOptimisticPersonalDetail) { return false; } const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(detail); @@ -158,18 +144,29 @@ function SuggestionMention({ return true; }); - const sortedPersonalDetails = _.sortBy(filteredPersonalDetails, (detail) => detail.displayName || detail.login); - _.each(_.first(sortedPersonalDetails, CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS - suggestions.length), (detail) => { + const sortedPersonalDetails = filteredPersonalDetails.sort((a, b) => { + const nameA = a?.displayName ?? a?.login ?? ''; + const nameB = b?.displayName ?? b?.login ?? ''; + + if (nameA < nameB) { + return -1; + } + if (nameA > nameB) { + return 1; + } + return 0; + }); + sortedPersonalDetails.slice(0, CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS - suggestions.length).forEach((detail) => { suggestions.push({ text: PersonalDetailsUtils.getDisplayNameOrDefault(detail), - alternateText: formatPhoneNumber(detail.login), - login: detail.login, + alternateText: formatPhoneNumber(detail?.login ?? ''), + login: detail?.login, icons: [ { - name: detail.login, - source: UserUtils.getAvatar(detail.avatar, detail.accountID), - type: 'avatar', - fallbackIcon: detail.fallbackIcon, + name: detail?.login, + source: UserUtils.getAvatar(detail?.avatar, detail?.accountID), + type: CONST.ICON_TYPE_AVATAR, + fallbackIcon: detail?.fallbackIcon, }, ], }); @@ -181,7 +178,7 @@ function SuggestionMention({ ); const calculateMentionSuggestion = useCallback( - (selectionEnd) => { + (selectionEnd: number) => { if (shouldBlockCalc.current || selectionEnd < 1 || !isComposerFocused) { shouldBlockCalc.current = false; resetSuggestions(); @@ -201,11 +198,11 @@ function SuggestionMention({ const leftString = value.substring(0, suggestionEndIndex); const words = leftString.split(CONST.REGEX.SPACE_OR_EMOJI); - const lastWord = _.last(words); + const lastWord = words.at(-1) ?? ''; const secondToLastWord = words[words.length - 3]; let atSignIndex; - let suggestionWord; + let suggestionWord = ''; let prefix; // Detect if the last two words contain a mention (two words are needed to detect a mention with a space in it) @@ -223,7 +220,7 @@ function SuggestionMention({ prefix = lastWord.substring(1); } - const nextState = { + const nextState: Partial = { suggestedMentions: [], atSignIndex, mentionPrefix: prefix, @@ -235,7 +232,7 @@ function SuggestionMention({ const suggestions = getMentionOptions(personalDetails, prefix); nextState.suggestedMentions = suggestions; - nextState.shouldShowSuggestionMenu = !_.isEmpty(suggestions); + nextState.shouldShowSuggestionMenu = !!suggestions.length; } setSuggestionValues((prevState) => ({ @@ -268,20 +265,16 @@ function SuggestionMention({ }, []); const setShouldBlockSuggestionCalc = useCallback( - (shouldBlockSuggestionCalc) => { + (shouldBlockSuggestionCalc: boolean) => { shouldBlockCalc.current = shouldBlockSuggestionCalc; }, [shouldBlockCalc], ); - const onClose = useCallback(() => { - setSuggestionValues((prevState) => ({...prevState, suggestedMentions: []})); - }, []); - const getSuggestions = useCallback(() => suggestionValues.suggestedMentions, [suggestionValues]); useImperativeHandle( - forwardedRef, + ref, () => ({ resetSuggestions, triggerHotkeyActions, @@ -298,34 +291,16 @@ function SuggestionMention({ return ( ); } -SuggestionMention.propTypes = propTypes; -SuggestionMention.defaultProps = defaultProps; SuggestionMention.displayName = 'SuggestionMention'; -const SuggestionMentionWithRef = React.forwardRef((props, ref) => ( - -)); - -SuggestionMentionWithRef.displayName = 'SuggestionMentionWithRef'; - -export default SuggestionMentionWithRef; +export default forwardRef(SuggestionMention); diff --git a/src/pages/home/report/ReportActionCompose/Suggestions.js b/src/pages/home/report/ReportActionCompose/Suggestions.tsx similarity index 54% rename from src/pages/home/report/ReportActionCompose/Suggestions.js rename to src/pages/home/report/ReportActionCompose/Suggestions.tsx index 5dc71fec6419..f997637a8c4c 100644 --- a/src/pages/home/report/ReportActionCompose/Suggestions.js +++ b/src/pages/home/report/ReportActionCompose/Suggestions.tsx @@ -1,64 +1,67 @@ -import PropTypes from 'prop-types'; -import React, {useCallback, useContext, useEffect, useImperativeHandle, useRef} from 'react'; +import type {ForwardedRef} from 'react'; +import React, {forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef} from 'react'; +import type {NativeSyntheticEvent, TextInputSelectionChangeEventData} from 'react-native'; import {View} from 'react-native'; import {DragAndDropContext} from '@components/DragAndDrop/Provider'; import usePrevious from '@hooks/usePrevious'; +import type {SuggestionsRef} from './ReportActionCompose'; import SuggestionEmoji from './SuggestionEmoji'; import SuggestionMention from './SuggestionMention'; -import * as SuggestionProps from './suggestionProps'; -const propTypes = { - /** A ref to this component */ - forwardedRef: PropTypes.shape({current: PropTypes.shape({})}), - - /** Function to clear the input */ - resetKeyboardInput: PropTypes.func.isRequired, - - /** Is auto suggestion picker large */ - isAutoSuggestionPickerLarge: PropTypes.bool, - - ...SuggestionProps.baseProps, +type Selection = { + start: number; + end: number; }; -const defaultProps = { - forwardedRef: null, - isAutoSuggestionPickerLarge: true, +type SuggestionProps = { + value: string; + setValue: (newValue: string) => void; + selection: Selection; + setSelection: (newSelection: Selection) => void; + updateComment: (newComment: string, shouldDebounceSaveComment?: boolean) => void; + measureParentContainer: () => void; + isComposerFullSize: boolean; + isComposerFocused?: boolean; + resetKeyboardInput: () => void; + isAutoSuggestionPickerLarge?: boolean; + composerHeight?: number; }; /** * This component contains the individual suggestion components. * If you want to add a new suggestion type, add it here. * - * @returns {React.Component} */ -function Suggestions({ - isComposerFullSize, - value, - setValue, - selection, - setSelection, - updateComment, - composerHeight, - forwardedRef, - resetKeyboardInput, - measureParentContainer, - isAutoSuggestionPickerLarge, - isComposerFocused, -}) { - const suggestionEmojiRef = useRef(null); - const suggestionMentionRef = useRef(null); +function Suggestions( + { + isComposerFullSize, + value, + setValue, + selection, + setSelection, + updateComment, + composerHeight, + resetKeyboardInput, + measureParentContainer, + isAutoSuggestionPickerLarge = true, + isComposerFocused, + }: SuggestionProps, + ref: ForwardedRef, +) { + const suggestionEmojiRef = useRef(null); + const suggestionMentionRef = useRef(null); const {isDraggingOver} = useContext(DragAndDropContext); const prevIsDraggingOver = usePrevious(isDraggingOver); const getSuggestions = useCallback(() => { - if (suggestionEmojiRef.current && suggestionEmojiRef.current.getSuggestions) { + if (suggestionEmojiRef.current?.getSuggestions) { const emojiSuggestions = suggestionEmojiRef.current.getSuggestions(); if (emojiSuggestions.length > 0) { return emojiSuggestions; } } - if (suggestionMentionRef.current && suggestionMentionRef.current.getSuggestions) { + if (suggestionMentionRef.current?.getSuggestions) { const mentionSuggestions = suggestionMentionRef.current.getSuggestions(); if (mentionSuggestions.length > 0) { return mentionSuggestions; @@ -72,38 +75,36 @@ function Suggestions({ * Clean data related to EmojiSuggestions */ const resetSuggestions = useCallback(() => { - suggestionEmojiRef.current.resetSuggestions(); - suggestionMentionRef.current.resetSuggestions(); + suggestionEmojiRef.current?.resetSuggestions(); + suggestionMentionRef.current?.resetSuggestions(); }, []); /** * Listens for keyboard shortcuts and applies the action - * - * @param {Object} e */ - const triggerHotkeyActions = useCallback((e) => { - const emojiHandler = suggestionEmojiRef.current.triggerHotkeyActions(e); - const mentionHandler = suggestionMentionRef.current.triggerHotkeyActions(e); - return emojiHandler || mentionHandler; + const triggerHotkeyActions = useCallback((e: KeyboardEvent) => { + const emojiHandler = suggestionEmojiRef.current?.triggerHotkeyActions(e); + const mentionHandler = suggestionMentionRef.current?.triggerHotkeyActions(e); + return emojiHandler ?? mentionHandler; }, []); - const onSelectionChange = useCallback((e) => { - const emojiHandler = suggestionEmojiRef.current.onSelectionChange(e); + const onSelectionChange = useCallback((e: NativeSyntheticEvent) => { + const emojiHandler = suggestionEmojiRef.current?.onSelectionChange(e); return emojiHandler; }, []); const updateShouldShowSuggestionMenuToFalse = useCallback(() => { - suggestionEmojiRef.current.updateShouldShowSuggestionMenuToFalse(); - suggestionMentionRef.current.updateShouldShowSuggestionMenuToFalse(); + suggestionEmojiRef.current?.updateShouldShowSuggestionMenuToFalse(); + suggestionMentionRef.current?.updateShouldShowSuggestionMenuToFalse(); }, []); - const setShouldBlockSuggestionCalc = useCallback((shouldBlock) => { - suggestionEmojiRef.current.setShouldBlockSuggestionCalc(shouldBlock); - suggestionMentionRef.current.setShouldBlockSuggestionCalc(shouldBlock); + const setShouldBlockSuggestionCalc = useCallback((shouldBlock: boolean) => { + suggestionEmojiRef.current?.setShouldBlockSuggestionCalc(shouldBlock); + suggestionMentionRef.current?.setShouldBlockSuggestionCalc(shouldBlock); }, []); useImperativeHandle( - forwardedRef, + ref, () => ({ resetSuggestions, onSelectionChange, @@ -152,18 +153,8 @@ function Suggestions({ ); } -Suggestions.propTypes = propTypes; -Suggestions.defaultProps = defaultProps; Suggestions.displayName = 'Suggestions'; -const SuggestionsWithRef = React.forwardRef((props, ref) => ( - -)); - -SuggestionsWithRef.displayName = 'SuggestionsWithRef'; +export default forwardRef(Suggestions); -export default SuggestionsWithRef; +export type {SuggestionProps}; diff --git a/src/types/onyx/OnyxCommon.ts b/src/types/onyx/OnyxCommon.ts index b26dc167ed44..a4d29967be1e 100644 --- a/src/types/onyx/OnyxCommon.ts +++ b/src/types/onyx/OnyxCommon.ts @@ -20,7 +20,7 @@ type Icon = { type: AvatarType; /** Owner of the avatar. If user, displayName. If workspace, policy name */ - name: string; + name?: string; /** Avatar id */ id?: number | string; From 717a5e8d5f3229cf1611c14382adfb0ae5cd1268 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Sun, 21 Jan 2024 14:38:40 +0100 Subject: [PATCH 022/202] fix: started migrating SuggestionEmoji component --- .../ReportActionCompose/SuggestionEmoji.tsx | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx index 06089b748554..c5eb13176d44 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx @@ -1,8 +1,7 @@ -import PropTypes from 'prop-types'; -import React, {ForwardedRef, forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; +import type {ForwardedRef} from 'react'; +import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; import EmojiSuggestions from '@components/EmojiSuggestions'; import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; import useLocalize from '@hooks/useLocalize'; @@ -10,22 +9,12 @@ import * as EmojiUtils from '@libs/EmojiUtils'; import * as SuggestionsUtils from '@libs/SuggestionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -// eslint-disable-next-line import/no-cycle -import {SuggestionProps} from './Suggestions'; +import type {SuggestionProps} from './Suggestions'; -/** - * Check if this piece of string looks like an emoji - */ -const isEmojiCode = (str: string, pos: number): boolean => { - const leftWords = str.slice(0, pos).split(CONST.REGEX.SPECIAL_CHAR_OR_EMOJI); - const leftWord = leftWords.at(-1) ?? ''; - return CONST.REGEX.HAS_COLON_ONLY_AT_THE_BEGINNING.test(leftWord) && leftWord.length > 2; -}; - -const defaultSuggestionsValues = { - suggestedEmojis: [], - colonSignIndex: -1, - shouldShowSuggestionMenu: false, +type SuggestionsValue = { + suggestedEmojis: any[]; + colonIndex: number; + shouldShowSuggestionMenu: boolean; }; type SuggestionEmojiOnyxProps = { @@ -39,6 +28,21 @@ type SuggestionEmojiProps = { } & SuggestionEmojiOnyxProps & SuggestionProps; +/** + * Check if this piece of string looks like an emoji + */ +const isEmojiCode = (str: string, pos: number): boolean => { + const leftWords = str.slice(0, pos).split(CONST.REGEX.SPECIAL_CHAR_OR_EMOJI); + const leftWord = leftWords.at(-1) ?? ''; + return CONST.REGEX.HAS_COLON_ONLY_AT_THE_BEGINNING.test(leftWord) && leftWord.length > 2; +}; + +const defaultSuggestionsValues: SuggestionsValue = { + suggestedEmojis: [], + colonIndex: -1, + shouldShowSuggestionMenu: false, +}; + function SuggestionEmoji( { preferredSkinTone = CONST.EMOJI_DEFAULT_SKIN_TONE, @@ -61,7 +65,7 @@ function SuggestionEmoji( const [highlightedEmojiIndex, setHighlightedEmojiIndex] = useArrowKeyFocusManager({ isActive: isEmojiSuggestionsMenuVisible, - maxIndex: SuggestionsUtils.getMaxArrowIndex(suggestionValues.suggestedEmojis.length, isAutoSuggestionPickerLarge), + maxIndex: SuggestionsUtils.getMaxArrowIndex(suggestionValues.suggestedEmojis.length, !!isAutoSuggestionPickerLarge), shouldExcludeTextAreaNodes: false, }); @@ -75,7 +79,7 @@ function SuggestionEmoji( * @param {Number} selectedEmoji */ const insertSelectedEmoji = useCallback( - (highlightedEmojiIndexInner) => { + (highlightedEmojiIndexInner: number) => { const commentBeforeColon = value.slice(0, suggestionValues.colonIndex); const emojiObject = suggestionValues.suggestedEmojis[highlightedEmojiIndexInner]; const emojiCode = emojiObject.types && emojiObject.types[preferredSkinTone] ? emojiObject.types[preferredSkinTone] : emojiObject.code; From 1d21ded647fbd25ab4d1375133fe345a31beed02 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 22 Jan 2024 11:01:20 +0700 Subject: [PATCH 023/202] fix: Delay in updating green dot and total amount --- src/libs/actions/IOU.js | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 7ee752a1f0ef..aeff964cac6b 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -329,7 +329,7 @@ function getReceiptError(receipt, filename, isScanRequest = true) { * @param {Object} policy - May be undefined, an empty object, or an object matching the Policy type (src/types/onyx/Policy.ts) * @param {Array} policyTags * @param {Array} policyCategories - * @param {Boolean} hasOutstandingChildRequest + * @param {Array} needsToBeManuallySubmitted * @returns {Array} - An array containing the optimistic data, success data, and failure data. */ function buildOnyxDataForMoneyRequest( @@ -348,7 +348,7 @@ function buildOnyxDataForMoneyRequest( policy, policyTags, policyCategories, - hasOutstandingChildRequest = false, + needsToBeManuallySubmitted, ) { const isScanRequest = TransactionUtils.isScanRequest(transaction); const optimisticData = [ @@ -361,7 +361,7 @@ function buildOnyxDataForMoneyRequest( lastReadTime: DateUtils.getDBTime(), lastMessageTranslationKey: '', iouReportID: iouReport.reportID, - hasOutstandingChildRequest, + hasOutstandingChildRequest: needsToBeManuallySubmitted && iouReport.managerID === userAccountID && iouReport.total !== 0, ...(isNewChatReport ? {pendingFields: {createChat: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD}} : {}), }, }, @@ -687,7 +687,7 @@ function getMoneyRequestInformation( let iouReport = isNewIOUReport ? null : allReports[`${ONYXKEYS.COLLECTION.REPORT}${chatReport.iouReportID}`]; // Check if the Scheduled Submit is enabled in case of expense report - let needsToBeManuallySubmitted = false; + let needsToBeManuallySubmitted = true; let isFromPaidPolicy = false; if (isPolicyExpenseChat) { isFromPaidPolicy = PolicyUtils.isPaidGroupPolicy(policy); @@ -806,10 +806,6 @@ function getMoneyRequestInformation( } : undefined; - // The policy expense chat should have the GBR only when its a paid policy and the scheduled submit is turned off - // so the employee has to submit to their manager manually. - const hasOutstandingChildRequest = isPolicyExpenseChat && needsToBeManuallySubmitted; - // STEP 5: Build Onyx Data const [optimisticData, successData, failureData] = buildOnyxDataForMoneyRequest( chatReport, @@ -827,7 +823,7 @@ function getMoneyRequestInformation( policy, policyTags, policyCategories, - hasOutstandingChildRequest, + needsToBeManuallySubmitted, ); return { @@ -2544,7 +2540,19 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView let updatedIOUReport = {...iouReport}; const updatedReportPreviewAction = {...reportPreviewAction}; updatedReportPreviewAction.pendingAction = shouldDeleteIOUReport ? CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE : CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE; - if (ReportUtils.isExpenseReport(iouReport)) { + + const isPolicyExpenseChat = ReportUtils.isExpenseReport(iouReport); + + let needsToBeManuallySubmitted = true; + if (isPolicyExpenseChat) { + const policy = ReportUtils.getPolicy(iouReport.policyID); + const isFromPaidPolicy = PolicyUtils.isPaidGroupPolicy(policy); + + // If the scheduled submit is turned off on the policy, user needs to manually submit the report which is indicated by GBR in LHN + needsToBeManuallySubmitted = isFromPaidPolicy && !(policy.isHarvestingEnabled || false); + } + + if (isPolicyExpenseChat) { updatedIOUReport = {...iouReport}; // Because of the Expense reports are stored as negative values, we add the total from the amount @@ -2646,6 +2654,13 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView }, ] : []), + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, + value: { + hasOutstandingChildRequest: needsToBeManuallySubmitted && updatedIOUReport.managerID === userAccountID && updatedIOUReport.total !== 0, + }, + }, ]; const successData = [ From 7c7132531962d803f64392171d7c3c9d95fc9b6c Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 22 Jan 2024 13:55:47 +0100 Subject: [PATCH 024/202] fix: migrate SuggestionEmoji --- src/libs/EmojiUtils.ts | 2 +- .../ReportActionCompose.tsx | 2 +- .../ReportActionCompose/SuggestionEmoji.tsx | 51 ++++++++----------- .../ReportActionCompose/Suggestions.tsx | 2 +- 4 files changed, 25 insertions(+), 32 deletions(-) diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index e34fa0b90fc6..7971e6147c19 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -384,7 +384,7 @@ function replaceAndExtractEmojis(text: string, preferredSkinTone: number = CONST * Suggest emojis when typing emojis prefix after colon * @param [limit] - matching emojis limit */ -function suggestEmojis(text: string, lang: keyof SupportedLanguage, limit = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS): Emoji[] | undefined { +function suggestEmojis(text: string, lang: SupportedLanguage, limit: number = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS): Emoji[] | undefined { // emojisTrie is importing the emoji JSON file on the app starting and we want to avoid it const emojisTrie = require('./EmojiTrie').default; diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 025b7142df0d..9754d45be834 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -56,7 +56,7 @@ type SuggestionsRef = { triggerHotkeyActions: (event: KeyboardEvent) => void; updateShouldShowSuggestionMenuToFalse: (shouldShowSuggestionMenu?: boolean) => void; setShouldBlockSuggestionCalc: (shouldBlock: boolean) => void; - getSuggestions: () => Mention[]; + getSuggestions: () => Mention[] | Emoji[]; }; type ReportActionComposeOnyxProps = { diff --git a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx index c5eb13176d44..dac59065371d 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx @@ -1,25 +1,29 @@ import type {ForwardedRef} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; -import type {OnyxEntry} from 'react-native-onyx'; +import type {NativeSyntheticEvent, TextInputSelectionChangeEventData} from 'react-native'; import {withOnyx} from 'react-native-onyx'; +import type {Emoji} from '@assets/emojis/types'; import EmojiSuggestions from '@components/EmojiSuggestions'; import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; import useLocalize from '@hooks/useLocalize'; +import type {SupportedLanguage} from '@libs/EmojiTrie'; import * as EmojiUtils from '@libs/EmojiUtils'; import * as SuggestionsUtils from '@libs/SuggestionUtils'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import type {SuggestionsRef} from './ReportActionCompose'; import type {SuggestionProps} from './Suggestions'; type SuggestionsValue = { - suggestedEmojis: any[]; + suggestedEmojis: Emoji[]; colonIndex: number; shouldShowSuggestionMenu: boolean; }; type SuggestionEmojiOnyxProps = { /** Preferred skin tone */ - preferredSkinTone: OnyxEntry; + preferredSkinTone: number; }; type SuggestionEmojiProps = { @@ -47,21 +51,19 @@ function SuggestionEmoji( { preferredSkinTone = CONST.EMOJI_DEFAULT_SKIN_TONE, value, - setValue, selection, setSelection, updateComment, - isComposerFullSize, isAutoSuggestionPickerLarge, resetKeyboardInput, measureParentContainer, isComposerFocused, }: SuggestionEmojiProps, - ref: ForwardedRef, + ref: ForwardedRef, ) { const [suggestionValues, setSuggestionValues] = useState(defaultSuggestionsValues); - const isEmojiSuggestionsMenuVisible = !_.isEmpty(suggestionValues.suggestedEmojis) && suggestionValues.shouldShowSuggestionMenu; + const isEmojiSuggestionsMenuVisible = suggestionValues.suggestedEmojis.length > 0 && suggestionValues.shouldShowSuggestionMenu; const [highlightedEmojiIndex, setHighlightedEmojiIndex] = useArrowKeyFocusManager({ isActive: isEmojiSuggestionsMenuVisible, @@ -82,7 +84,7 @@ function SuggestionEmoji( (highlightedEmojiIndexInner: number) => { const commentBeforeColon = value.slice(0, suggestionValues.colonIndex); const emojiObject = suggestionValues.suggestedEmojis[highlightedEmojiIndexInner]; - const emojiCode = emojiObject.types && emojiObject.types[preferredSkinTone] ? emojiObject.types[preferredSkinTone] : emojiObject.code; + const emojiCode = emojiObject.types?.[preferredSkinTone] ? emojiObject.types[preferredSkinTone] : emojiObject.code; const commentAfterColonWithEmojiNameRemoved = value.slice(selection.end); updateComment(`${commentBeforeColon}${emojiCode} ${SuggestionsUtils.trimLeadingSpace(commentAfterColonWithEmojiNameRemoved)}`, true); @@ -119,11 +121,9 @@ function SuggestionEmoji( /** * Listens for keyboard shortcuts and applies the action - * - * @param {Object} e */ const triggerHotkeyActions = useCallback( - (e) => { + (e: KeyboardEvent) => { const suggestionsExist = suggestionValues.suggestedEmojis.length > 0; if (((!e.shiftKey && e.key === CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey) || e.key === CONST.KEYBOARD_SHORTCUTS.TAB.shortcutKey) && suggestionsExist) { @@ -151,7 +151,7 @@ function SuggestionEmoji( * Calculates and cares about the content of an Emoji Suggester */ const calculateEmojiSuggestion = useCallback( - (selectionEnd) => { + (selectionEnd: number) => { if (shouldBlockCalc.current || !value) { shouldBlockCalc.current = false; resetSuggestions(); @@ -161,16 +161,16 @@ function SuggestionEmoji( const colonIndex = leftString.lastIndexOf(':'); const isCurrentlyShowingEmojiSuggestion = isEmojiCode(value, selectionEnd); - const nextState = { + const nextState: SuggestionsValue = { suggestedEmojis: [], colonIndex, shouldShowSuggestionMenu: false, }; - const newSuggestedEmojis = EmojiUtils.suggestEmojis(leftString, preferredLocale); + const newSuggestedEmojis = EmojiUtils.suggestEmojis(leftString, preferredLocale as SupportedLanguage); - if (newSuggestedEmojis.length && isCurrentlyShowingEmojiSuggestion) { + if (newSuggestedEmojis?.length && isCurrentlyShowingEmojiSuggestion) { nextState.suggestedEmojis = newSuggestedEmojis; - nextState.shouldShowSuggestionMenu = !_.isEmpty(newSuggestedEmojis); + nextState.shouldShowSuggestionMenu = !isEmptyObject(newSuggestedEmojis); } setSuggestionValues((prevState) => ({...prevState, ...nextState})); @@ -187,7 +187,7 @@ function SuggestionEmoji( }, [selection, calculateEmojiSuggestion, isComposerFocused]); const onSelectionChange = useCallback( - (e) => { + (e: NativeSyntheticEvent) => { /** * we pass here e.nativeEvent.selection.end directly to calculateEmojiSuggestion * because in other case calculateEmojiSuggestion will have an old calculation value @@ -199,7 +199,7 @@ function SuggestionEmoji( ); const setShouldBlockSuggestionCalc = useCallback( - (shouldBlockSuggestionCalc) => { + (shouldBlockSuggestionCalc: boolean) => { shouldBlockCalc.current = shouldBlockSuggestionCalc; }, [shouldBlockCalc], @@ -207,10 +207,6 @@ function SuggestionEmoji( const getSuggestions = useCallback(() => suggestionValues.suggestedEmojis, [suggestionValues]); - const resetEmojiSuggestions = useCallback(() => { - setSuggestionValues((prevState) => ({...prevState, suggestedEmojis: []})); - }, []); - useImperativeHandle( ref, () => ({ @@ -230,17 +226,12 @@ function SuggestionEmoji( return ( ); @@ -248,9 +239,11 @@ function SuggestionEmoji( SuggestionEmoji.displayName = 'SuggestionEmoji'; +const SuggestionEmojiForwardedRef = forwardRef(SuggestionEmoji); + export default withOnyx({ preferredSkinTone: { key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, selector: EmojiUtils.getPreferredSkinToneIndex, }, -})(forwardRef(SuggestionEmoji)); +})(SuggestionEmojiForwardedRef); diff --git a/src/pages/home/report/ReportActionCompose/Suggestions.tsx b/src/pages/home/report/ReportActionCompose/Suggestions.tsx index f997637a8c4c..3a009728a915 100644 --- a/src/pages/home/report/ReportActionCompose/Suggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/Suggestions.tsx @@ -89,7 +89,7 @@ function Suggestions( }, []); const onSelectionChange = useCallback((e: NativeSyntheticEvent) => { - const emojiHandler = suggestionEmojiRef.current?.onSelectionChange(e); + const emojiHandler = suggestionEmojiRef.current?.onSelectionChange?.(e); return emojiHandler; }, []); From be57be30f750da1ca8a1374213907c3c8e8b8eb1 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 22 Jan 2024 14:11:08 +0100 Subject: [PATCH 025/202] fix: SuggestionEmoji and Suggestions types, migrate SendButton --- .../{SendButton.js => SendButton.tsx} | 14 +++++++------- .../report/ReportActionCompose/SuggestionEmoji.tsx | 12 +++++------- .../report/ReportActionCompose/Suggestions.tsx | 2 +- 3 files changed, 13 insertions(+), 15 deletions(-) rename src/pages/home/report/ReportActionCompose/{SendButton.js => SendButton.tsx} (90%) diff --git a/src/pages/home/report/ReportActionCompose/SendButton.js b/src/pages/home/report/ReportActionCompose/SendButton.tsx similarity index 90% rename from src/pages/home/report/ReportActionCompose/SendButton.js rename to src/pages/home/report/ReportActionCompose/SendButton.tsx index d0b0453ace2f..b6c6200fc7c0 100644 --- a/src/pages/home/report/ReportActionCompose/SendButton.js +++ b/src/pages/home/report/ReportActionCompose/SendButton.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {View} from 'react-native'; import {Gesture, GestureDetector} from 'react-native-gesture-handler'; @@ -11,21 +10,21 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -const propTypes = { +type SendButtonProps = { /** Whether the button is disabled */ - isDisabled: PropTypes.bool.isRequired, + isDisabled: boolean; /** Handle clicking on send button */ - handleSendMessage: PropTypes.func.isRequired, + handleSendMessage: () => void; }; -function SendButton({isDisabled: isDisabledProp, handleSendMessage}) { +function SendButton({isDisabled: isDisabledProp, handleSendMessage}: SendButtonProps) { const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); const Tap = Gesture.Tap() - .enabled() + .enabled(!isDisabledProp) .onEnd(() => { handleSendMessage(); }); @@ -46,6 +45,8 @@ function SendButton({isDisabled: isDisabledProp, handleSendMessage}) { ]} role={CONST.ROLE.BUTTON} accessibilityLabel={translate('common.send')} + accessible + onPress={() => {}} > {({pressed}) => ( void; + resetKeyboardInput: (() => void) | undefined; } & SuggestionEmojiOnyxProps & SuggestionProps; @@ -92,7 +92,7 @@ function SuggestionEmoji( // In some Android phones keyboard, the text to search for the emoji is not cleared // will be added after the user starts typing again on the keyboard. This package is // a workaround to reset the keyboard natively. - resetKeyboardInput(); + resetKeyboardInput?.(); setSelection({ start: suggestionValues.colonIndex + emojiCode.length + CONST.SPACE_LENGTH, @@ -239,11 +239,9 @@ function SuggestionEmoji( SuggestionEmoji.displayName = 'SuggestionEmoji'; -const SuggestionEmojiForwardedRef = forwardRef(SuggestionEmoji); - -export default withOnyx({ +export default withOnyx, SuggestionEmojiOnyxProps>({ preferredSkinTone: { key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, selector: EmojiUtils.getPreferredSkinToneIndex, }, -})(SuggestionEmojiForwardedRef); +})(forwardRef(SuggestionEmoji)); diff --git a/src/pages/home/report/ReportActionCompose/Suggestions.tsx b/src/pages/home/report/ReportActionCompose/Suggestions.tsx index 3a009728a915..2500af40c7c6 100644 --- a/src/pages/home/report/ReportActionCompose/Suggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/Suggestions.tsx @@ -22,7 +22,7 @@ type SuggestionProps = { measureParentContainer: () => void; isComposerFullSize: boolean; isComposerFocused?: boolean; - resetKeyboardInput: () => void; + resetKeyboardInput?: () => void; isAutoSuggestionPickerLarge?: boolean; composerHeight?: number; }; From 929a51a9a8be77696c674b881b7835d85147e481 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 22 Jan 2024 14:38:55 +0100 Subject: [PATCH 026/202] fix: migrate AttachmentPickerWithMenuItems --- src/components/PopoverMenu.tsx | 2 +- ...s.js => AttachmentPickerWithMenuItems.tsx} | 119 ++++++++---------- 2 files changed, 52 insertions(+), 69 deletions(-) rename src/pages/home/report/ReportActionCompose/{AttachmentPickerWithMenuItems.js => AttachmentPickerWithMenuItems.tsx} (82%) diff --git a/src/components/PopoverMenu.tsx b/src/components/PopoverMenu.tsx index 17b1a119671a..b411de1103f1 100644 --- a/src/components/PopoverMenu.tsx +++ b/src/components/PopoverMenu.tsx @@ -69,7 +69,7 @@ type PopoverMenuProps = Partial & { anchorPosition: AnchorPosition; /** Ref of the anchor */ - anchorRef: RefObject; + anchorRef: RefObject; /** Where the popover should be positioned relative to the anchor points. */ anchorAlignment?: AnchorAlignment; diff --git a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx similarity index 82% rename from src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js rename to src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index 444dd939142b..547283cc4eb0 100644 --- a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.js +++ b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -1,23 +1,23 @@ -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; +import {useIsFocused} from '@react-navigation/native'; +import type {FC} from 'react'; import React, {useCallback, useEffect, useMemo} from 'react'; import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {SvgProps} from 'react-native-svg'; +import type {ValueOf} from 'type-fest'; import AttachmentPicker from '@components/AttachmentPicker'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import PopoverMenu from '@components/PopoverMenu'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import Tooltip from '@components/Tooltip/PopoverAnchorTooltip'; -import withNavigationFocus from '@components/withNavigationFocus'; import useLocalize from '@hooks/useLocalize'; import usePrevious from '@hooks/usePrevious'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as Browser from '@libs/Browser'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; import * as IOU from '@userActions/IOU'; @@ -26,88 +26,77 @@ import * as Task from '@userActions/Task'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type * as OnyxTypes from '@src/types/onyx'; -const propTypes = { - /** The report currently being looked at */ - report: PropTypes.shape({ - /** ID of the report */ - reportID: PropTypes.string, +type MoneyRequestOption = { + icon: FC; + text: string; + onSelected: () => void; +}; - /** Whether or not the report is in the process of being created */ - loading: PropTypes.bool, - }).isRequired, +type MoneyRequestOptions = Record, MoneyRequestOption>; +type AttachmentPickerWithMenuItemsOnyxProps = { /** The policy tied to the report */ - policy: PropTypes.shape({ - /** Type of the policy */ - type: PropTypes.string, - }), + policy: OnyxEntry; +}; - /** The personal details of everyone in the report */ - reportParticipantIDs: PropTypes.arrayOf(PropTypes.number), +type AttachmentPickerWithMenuItemsProps = { + /** The report currently being looked at */ + report: OnyxTypes.Report; /** Callback to open the file in the modal */ - displayFileInModal: PropTypes.func.isRequired, + displayFileInModal: (url: string) => void; /** Whether or not the full size composer is available */ - isFullComposerAvailable: PropTypes.bool.isRequired, + isFullComposerAvailable: boolean; /** Whether or not the composer is full size */ - isComposerFullSize: PropTypes.bool.isRequired, + isComposerFullSize: boolean; /** Whether or not the user is blocked from concierge */ - isBlockedFromConcierge: PropTypes.bool.isRequired, + isBlockedFromConcierge: boolean; /** Whether or not the attachment picker is disabled */ - disabled: PropTypes.bool.isRequired, + disabled: boolean; /** Sets the menu visibility */ - setMenuVisibility: PropTypes.func.isRequired, + setMenuVisibility: (isVisible: boolean) => void; /** Whether or not the menu is visible */ - isMenuVisible: PropTypes.bool.isRequired, + isMenuVisible: boolean; /** Report ID */ - reportID: PropTypes.string.isRequired, + reportID: string; /** Called when opening the attachment picker */ - onTriggerAttachmentPicker: PropTypes.func.isRequired, + onTriggerAttachmentPicker: () => void; /** Called when cancelling the attachment picker */ - onCanceledAttachmentPicker: PropTypes.func.isRequired, + onCanceledAttachmentPicker: () => void; /** Called when the menu with the items is closed after it was open */ - onMenuClosed: PropTypes.func.isRequired, + onMenuClosed: () => void; /** Called when the add action button is pressed */ - onAddActionPressed: PropTypes.func.isRequired, + onAddActionPressed: () => void; /** Called when the menu item is selected */ - onItemSelected: PropTypes.func.isRequired, + onItemSelected: () => void; /** A ref for the add action button */ - actionButtonRef: PropTypes.shape({ - // eslint-disable-next-line react/forbid-prop-types - current: PropTypes.object, - }).isRequired, - - /** Whether or not the screen is focused */ - isFocused: PropTypes.bool.isRequired, + actionButtonRef: React.RefObject; /** A function that toggles isScrollLikelyLayoutTriggered flag for a certain period of time */ - raiseIsScrollLikelyLayoutTriggered: PropTypes.func.isRequired, -}; + raiseIsScrollLikelyLayoutTriggered: () => void; -const defaultProps = { - reportParticipantIDs: [], - policy: {}, -}; + /** The personal details of everyone in the report */ + reportParticipantIDs?: number[]; +} & AttachmentPickerWithMenuItemsOnyxProps; /** * This includes the popover of options you see when pressing the + button in the composer. * It also contains the attachment picker, as the menu items need to be able to open it. - * - * @returns {React.Component} */ function AttachmentPickerWithMenuItems({ report, @@ -127,9 +116,9 @@ function AttachmentPickerWithMenuItems({ onAddActionPressed, onItemSelected, actionButtonRef, - isFocused, raiseIsScrollLikelyLayoutTriggered, -}) { +}: AttachmentPickerWithMenuItemsProps) { + const isFocused = useIsFocused(); const theme = useTheme(); const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -137,10 +126,9 @@ function AttachmentPickerWithMenuItems({ /** * Returns the list of IOU Options - * @returns {Array} */ const moneyRequestOptions = useMemo(() => { - const options = { + const options: MoneyRequestOptions = { [CONST.IOU.TYPE.SPLIT]: { icon: Expensicons.Receipt, text: translate('iou.splitBill'), @@ -158,16 +146,15 @@ function AttachmentPickerWithMenuItems({ }, }; - return _.map(ReportUtils.getMoneyRequestOptions(report, policy, reportParticipantIDs), (option) => ({ + return ReportUtils.getMoneyRequestOptions(report, policy, reportParticipantIDs ?? []).map((option) => ({ ...options[option], })); }, [report, policy, reportParticipantIDs, translate]); /** * Determines if we can show the task option - * @returns {Boolean} */ - const taskOption = useMemo(() => { + const taskOption: MoneyRequestOption[] = useMemo(() => { if (!ReportUtils.canCreateTaskInReport(report)) { return []; } @@ -206,6 +193,7 @@ function AttachmentPickerWithMenuItems({ return ( + {/* @ts-expect-error TODO: Remove this once SettlementButton (https://github.com/Expensify/App/issues/25134) is migrated to TypeScript. */} {({openPicker}) => { const triggerAttachmentPicker = () => { onTriggerAttachmentPicker(); @@ -235,7 +223,7 @@ function AttachmentPickerWithMenuItems({ { - e.preventDefault(); + e?.preventDefault(); raiseIsScrollLikelyLayoutTriggered(); Report.setIsComposerFullSize(reportID, false); }} @@ -257,7 +245,7 @@ function AttachmentPickerWithMenuItems({ { - e.preventDefault(); + e?.preventDefault(); raiseIsScrollLikelyLayoutTriggered(); Report.setIsComposerFullSize(reportID, true); }} @@ -279,14 +267,14 @@ function AttachmentPickerWithMenuItems({ { - e.preventDefault(); + e?.preventDefault(); if (!isFocused) { return; } onAddActionPressed(); // Drop focus to avoid blue focus ring. - actionButtonRef.current.blur(); + actionButtonRef.current?.blur(); setMenuVisibility(!isMenuVisible); }} style={styles.composerSizeButton} @@ -329,15 +317,10 @@ function AttachmentPickerWithMenuItems({ ); } -AttachmentPickerWithMenuItems.propTypes = propTypes; -AttachmentPickerWithMenuItems.defaultProps = defaultProps; AttachmentPickerWithMenuItems.displayName = 'AttachmentPickerWithMenuItems'; -export default compose( - withNavigationFocus, - withOnyx({ - policy: { - key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${lodashGet(report, 'policyID')}`, - }, - }), -)(AttachmentPickerWithMenuItems); +export default withOnyx({ + policy: { + key: ({report}) => `${ONYXKEYS.COLLECTION.POLICY}${report?.policyID}`, + }, +})(AttachmentPickerWithMenuItems); From 0cc6502443d17483711b9a26bd010e878e944626 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 22 Jan 2024 15:09:18 +0100 Subject: [PATCH 027/202] fix: Migrate SilentCommentUpdater --- ...estions.js => ComposerWithSuggestions.tsx} | 0 .../{index.android.js => index.android.tsx} | 22 ++-------- .../{index.js => index.tsx} | 42 +++---------------- .../SilentCommentUpdater/types.ts | 29 +++++++++++++ 4 files changed, 38 insertions(+), 55 deletions(-) rename src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/{ComposerWithSuggestions.js => ComposerWithSuggestions.tsx} (100%) rename src/pages/home/report/ReportActionCompose/SilentCommentUpdater/{index.android.js => index.android.tsx} (69%) rename src/pages/home/report/ReportActionCompose/SilentCommentUpdater/{index.js => index.tsx} (60%) create mode 100644 src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx similarity index 100% rename from src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.js rename to src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx diff --git a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.android.js b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.android.tsx similarity index 69% rename from src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.android.js rename to src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.android.tsx index f924a7b59194..cee9cbf794bf 100644 --- a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.android.js +++ b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.android.tsx @@ -1,19 +1,7 @@ -import PropTypes from 'prop-types'; import {useEffect} from 'react'; import {withOnyx} from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; - -const propTypes = { - /** The comment of the report */ - comment: PropTypes.string, - - /** Updates the comment */ - updateComment: PropTypes.func.isRequired, -}; - -const defaultProps = { - comment: '', -}; +import type {SilentCommentUpdaterOnyxProps, SilentCommentUpdaterProps} from './types'; /** * Adding .android component to disable updating comment when prev comment is different @@ -24,9 +12,8 @@ const defaultProps = { * This component doesn't render anything. It runs a side effect to update the comment of a report under certain conditions. * It is connected to the actual draft comment in onyx. The comment in onyx might updates multiple times, and we want to avoid * re-rendering a UI component for that. That's why the side effect was moved down to a separate component. - * @returns {null} */ -function SilentCommentUpdater({comment, updateComment}) { +function SilentCommentUpdater({comment = '', updateComment}: SilentCommentUpdaterProps) { useEffect(() => { updateComment(comment); // eslint-disable-next-line react-hooks/exhaustive-deps -- We need to run this on mount @@ -35,13 +22,10 @@ function SilentCommentUpdater({comment, updateComment}) { return null; } -SilentCommentUpdater.propTypes = propTypes; -SilentCommentUpdater.defaultProps = defaultProps; SilentCommentUpdater.displayName = 'SilentCommentUpdater'; -export default withOnyx({ +export default withOnyx({ comment: { key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`, - initialValue: '', }, })(SilentCommentUpdater); diff --git a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.js b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx similarity index 60% rename from src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.js rename to src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx index 9aa997a892f4..afee06dbc8ff 100644 --- a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.js +++ b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx @@ -1,46 +1,18 @@ -import PropTypes from 'prop-types'; import {useEffect} from 'react'; import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import usePrevious from '@hooks/usePrevious'; import ONYXKEYS from '@src/ONYXKEYS'; - -const propTypes = { - /** The comment of the report */ - comment: PropTypes.string, - - /** The report associated with the comment */ - report: PropTypes.shape({ - /** The ID of the report */ - reportID: PropTypes.string, - }).isRequired, - - /** The value of the comment */ - value: PropTypes.string.isRequired, - - /** The ref of the comment */ - commentRef: PropTypes.shape({ - /** The current value of the comment */ - current: PropTypes.string, - }).isRequired, - - /** Updates the comment */ - updateComment: PropTypes.func.isRequired, -}; - -const defaultProps = { - comment: '', -}; +import type {SilentCommentUpdaterOnyxProps, SilentCommentUpdaterProps} from './types'; /** * This component doesn't render anything. It runs a side effect to update the comment of a report under certain conditions. * It is connected to the actual draft comment in onyx. The comment in onyx might updates multiple times, and we want to avoid * re-rendering a UI component for that. That's why the side effect was moved down to a separate component. - * @returns {null} */ -function SilentCommentUpdater({comment, commentRef, report, value, updateComment}) { +function SilentCommentUpdater({comment = '', commentRef, report, value, updateComment}: SilentCommentUpdaterProps) { const prevCommentProp = usePrevious(comment); - const prevReportId = usePrevious(report.reportID); + const prevReportId = usePrevious(report?.reportID); const {preferredLocale} = useLocalize(); const prevPreferredLocale = usePrevious(preferredLocale); @@ -56,21 +28,19 @@ function SilentCommentUpdater({comment, commentRef, report, value, updateComment // As the report IDs change, make sure to update the composer comment as we need to make sure // we do not show incorrect data in there (ie. draft of message from other report). - if (preferredLocale === prevPreferredLocale && report.reportID === prevReportId && !shouldSyncComment) { + if (preferredLocale === prevPreferredLocale && report?.reportID === prevReportId && !shouldSyncComment) { return; } updateComment(comment); - }, [prevCommentProp, prevPreferredLocale, prevReportId, comment, preferredLocale, report.reportID, updateComment, value, commentRef]); + }, [prevCommentProp, prevPreferredLocale, prevReportId, comment, preferredLocale, report?.reportID, updateComment, value, commentRef]); return null; } -SilentCommentUpdater.propTypes = propTypes; -SilentCommentUpdater.defaultProps = defaultProps; SilentCommentUpdater.displayName = 'SilentCommentUpdater'; -export default withOnyx({ +export default withOnyx({ comment: { key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`, initialValue: '', diff --git a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts new file mode 100644 index 000000000000..60924f24099b --- /dev/null +++ b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts @@ -0,0 +1,29 @@ +import type {OnyxEntry} from 'react-native-onyx'; +import type {Report} from '@src/types/onyx'; + +type SilentCommentUpdaterOnyxProps = { + /** The comment of the report */ + comment: OnyxEntry; +}; + +type SilentCommentUpdaterProps = { + /** Updates the comment */ + updateComment: (comment: OnyxEntry) => void; + + /** The ID of the report associated with the comment */ + reportID: string; + + /** The report associated with the comment */ + report: OnyxEntry; + + /** The value of the comment */ + value: string; + + /** The ref of the comment */ + commentRef: React.RefObject; + + /** The comment of the report */ + commnet: string; +} & SilentCommentUpdaterOnyxProps; + +export type {SilentCommentUpdaterProps, SilentCommentUpdaterOnyxProps}; From 8ed208cb62610d729bd6a7d1c9da1ec477b96c68 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 23 Jan 2024 10:49:06 +0100 Subject: [PATCH 028/202] fix: ComposerWithSuggestion migration --- .../AttachmentPickerWithMenuItems.tsx | 8 +- .../ComposerWithSuggestions.tsx | 239 ++++++++++-------- .../ReportActionCompose.tsx | 9 +- 3 files changed, 146 insertions(+), 110 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index 547283cc4eb0..0dbfbba2759d 100644 --- a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx +++ b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -43,7 +43,7 @@ type AttachmentPickerWithMenuItemsOnyxProps = { type AttachmentPickerWithMenuItemsProps = { /** The report currently being looked at */ - report: OnyxTypes.Report; + report: OnyxEntry; /** Callback to open the file in the modal */ displayFileInModal: (url: string) => void; @@ -132,17 +132,17 @@ function AttachmentPickerWithMenuItems({ [CONST.IOU.TYPE.SPLIT]: { icon: Expensicons.Receipt, text: translate('iou.splitBill'), - onSelected: () => Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE.getRoute(CONST.IOU.TYPE.SPLIT, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, report.reportID)), + onSelected: () => Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE.getRoute(CONST.IOU.TYPE.SPLIT, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, report?.reportID ?? '')), }, [CONST.IOU.TYPE.REQUEST]: { icon: Expensicons.MoneyCircle, text: translate('iou.requestMoney'), - onSelected: () => Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE.getRoute(CONST.IOU.TYPE.REQUEST, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, report.reportID)), + onSelected: () => Navigation.navigate(ROUTES.MONEY_REQUEST_CREATE.getRoute(CONST.IOU.TYPE.REQUEST, CONST.IOU.OPTIMISTIC_TRANSACTION_ID, report?.reportID ?? '')), }, [CONST.IOU.TYPE.SEND]: { icon: Expensicons.Send, text: translate('iou.sendMoney'), - onSelected: () => IOU.startMoneyRequest(CONST.IOU.TYPE.SEND, report.reportID), + onSelected: () => IOU.startMoneyRequest(CONST.IOU.TYPE.SEND, report?.reportID), }, }; diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index 413807b1f992..bce7d80121b4 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -1,11 +1,14 @@ import {useIsFocused, useNavigation} from '@react-navigation/native'; -import lodashGet from 'lodash/get'; -import React, {useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; +import lodashDebounce from 'lodash/debounce'; +import type {ForwardedRef, RefAttributes, RefObject} from 'react'; +import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; +import type {MeasureInWindowOnSuccessCallback} from 'react-native'; import {findNodeHandle, InteractionManager, NativeModules, View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {Emoji} from '@assets/emojis/types'; import Composer from '@components/Composer'; -import withKeyboardState from '@components/withKeyboardState'; +import useKeyboardState from '@hooks/useKeyboardState'; import useLocalize from '@hooks/useLocalize'; import usePrevious from '@hooks/usePrevious'; import useStyleUtils from '@hooks/useStyleUtils'; @@ -14,7 +17,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as Browser from '@libs/Browser'; import canFocusInputOnScreenFocus from '@libs/canFocusInputOnScreenFocus'; -import compose from '@libs/compose'; import * as ComposerUtils from '@libs/ComposerUtils'; import getDraftComment from '@libs/ComposerUtils/getDraftComment'; import convertToLTRForComposer from '@libs/convertToLTRForComposer'; @@ -28,6 +30,7 @@ import * as ReportUtils from '@libs/ReportUtils'; import * as SuggestionUtils from '@libs/SuggestionUtils'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import willBlurTextInputOnTapOutsideFunc from '@libs/willBlurTextInputOnTapOutside'; +import type {ComposerRef, SuggestionsRef} from '@pages/home/report/ReportActionCompose/ReportActionCompose'; import SilentCommentUpdater from '@pages/home/report/ReportActionCompose/SilentCommentUpdater'; import Suggestions from '@pages/home/report/ReportActionCompose/Suggestions'; import * as EmojiPickerActions from '@userActions/EmojiPickerAction'; @@ -36,17 +39,65 @@ import * as Report from '@userActions/Report'; import * as User from '@userActions/User'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import type * as OnyxTypes from '@src/types/onyx'; +import type ChildrenProps from '@src/types/utils/ChildrenProps'; import {defaultProps, propTypes} from './composerWithSuggestionsProps'; +type ComposerWithSuggestionsOnyxProps = { + /** The number of lines the comment should take up */ + numberOfLines: number; + + /** The parent report actions for the report */ + parentReportActions: OnyxEntry; + + /** The modal state */ + modal: OnyxEntry; + + /** The preferred skin tone of the user */ + preferredSkinTone: number; + + /** Whether the input is focused */ + editFocused: boolean; +}; +type ComposerWithSuggestionsProps = { + reportID: string; + report: OnyxEntry; + reportActions: OnyxTypes.ReportAction[] | undefined; + onFocus: () => void; + onBlur: (event: FocusEvent) => void; + onValueChange: (value: string) => void; + isComposerFullSize: boolean; + isMenuVisible: boolean; + inputPlaceholder: string; + displayFileInModal: (fileURL: string) => void; + textInputShouldClear: boolean; + setTextInputShouldClear: (shouldClear: boolean) => void; + isBlockedFromConcierge: boolean; + disabled: boolean; + isFullComposerAvailable: boolean; + setIsFullComposerAvailable: (isFullComposerAvailable: boolean) => void; + setIsCommentEmpty: (isCommentEmpty: boolean) => void; + handleSendMessage: () => void; + shouldShowComposeInput: OnyxEntry; + measureParentContainer: (callback: MeasureInWindowOnSuccessCallback) => void; + listHeight: number; + isScrollLikelyLayoutTriggered: RefObject; + raiseIsScrollLikelyLayoutTriggered: () => void; + suggestionsRef: React.RefObject; + animatedRef: RefObject; + isNextModalWillOpenRef: RefObject; + editFocused: boolean; +} & ComposerWithSuggestionsOnyxProps & + Partial; + const {RNTextInputReset} = NativeModules; const isIOSNative = getPlatform() === CONST.PLATFORM.IOS; /** * Broadcast that the user is typing. Debounced to limit how often we publish client events. - * @param {String} reportID */ -const debouncedBroadcastUserIsTyping = _.debounce((reportID) => { +const debouncedBroadcastUserIsTyping = lodashDebounce((reportID: string) => { Report.broadcastUserIsTyping(reportID); }, 100); @@ -61,61 +112,61 @@ const shouldFocusInputOnScreenFocus = canFocusInputOnScreenFocus(); * If a component really needs access to these state values it should be put here. * However, double check if the component really needs access, as it will re-render * on every key press. - * @param {Object} props - * @returns {React.Component} */ -function ComposerWithSuggestions({ - // Onyx - modal, - preferredSkinTone, - parentReportActions, - numberOfLines, - // HOCs - isKeyboardShown, - // Props: Report - reportID, - report, - reportActions, - // Focus - onFocus, - onBlur, - onValueChange, - // Composer - isComposerFullSize, - isMenuVisible, - inputPlaceholder, - displayFileInModal, - textInputShouldClear, - setTextInputShouldClear, - isBlockedFromConcierge, - disabled, - isFullComposerAvailable, - setIsFullComposerAvailable, - setIsCommentEmpty, - handleSendMessage, - shouldShowComposeInput, - measureParentContainer, - listHeight, - isScrollLikelyLayoutTriggered, - raiseIsScrollLikelyLayoutTriggered, - // Refs - suggestionsRef, - animatedRef, - forwardedRef, - isNextModalWillOpenRef, - editFocused, - // For testing - children, -}) { +function ComposerWithSuggestions( + { + // Onyx + modal, + preferredSkinTone, + parentReportActions, + numberOfLines, + + // Props: Report + reportID, + report, + reportActions, + // Focus + onFocus, + onBlur, + onValueChange, + // Composer + isComposerFullSize, + isMenuVisible, + inputPlaceholder, + displayFileInModal, + textInputShouldClear, + setTextInputShouldClear, + isBlockedFromConcierge, + disabled, + isFullComposerAvailable, + setIsFullComposerAvailable, + setIsCommentEmpty, + handleSendMessage, + shouldShowComposeInput, + measureParentContainer, + listHeight, + isScrollLikelyLayoutTriggered, + raiseIsScrollLikelyLayoutTriggered, + // Refs + suggestionsRef, + animatedRef, + isNextModalWillOpenRef, + editFocused, + // For testing + children, + }: ComposerWithSuggestionsProps, + ref: ForwardedRef, +) { + const {isKeyboardShown} = useKeyboardState(); const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {preferredLocale} = useLocalize(); const isFocused = useIsFocused(); const navigation = useNavigation(); - const emojisPresentBefore = useRef([]); + const emojisPresentBefore = useRef([]); const [value, setValue] = useState(() => { - const draft = getDraftComment(reportID) || ''; + const draft = getDraftComment(reportID) ?? ''; if (draft) { emojisPresentBefore.current = EmojiUtils.extractEmojis(draft); } @@ -126,9 +177,9 @@ function ComposerWithSuggestions({ const {isSmallScreenWidth} = useWindowDimensions(); const maxComposerLines = isSmallScreenWidth ? CONST.COMPOSER.MAX_LINES_SMALL_SCREEN : CONST.COMPOSER.MAX_LINES; - const isEmptyChat = useMemo(() => _.size(reportActions) === 1, [reportActions]); - const parentReportAction = lodashGet(parentReportActions, [report.parentReportActionID]); - const shouldAutoFocus = !modal.isVisible && (shouldFocusInputOnScreenFocus || (isEmptyChat && !ReportActionsUtils.isTransactionThread(parentReportAction))) && shouldShowComposeInput; + const isEmptyChat = useMemo(() => reportActions?.length === 1, [reportActions]); + const parentReportAction = parentReportActions?.[report?.parentReportActionID ?? '']; + const shouldAutoFocus = !modal?.isVisible && (shouldFocusInputOnScreenFocus || (isEmptyChat && !ReportActionsUtils.isTransactionThread(parentReportAction))) && shouldShowComposeInput; const valueRef = useRef(value); valueRef.current = value; @@ -138,11 +189,11 @@ function ComposerWithSuggestions({ const [composerHeight, setComposerHeight] = useState(0); const textInputRef = useRef(null); - const insertedEmojisRef = useRef([]); + const insertedEmojisRef = useRef([]); const syncSelectionWithOnChangeTextRef = useRef(null); - const suggestions = lodashGet(suggestionsRef, 'current.getSuggestions', () => [])(); + const suggestions = suggestionsRef.current?.getSuggestions(); const hasEnoughSpaceForLargeSuggestion = SuggestionUtils.hasEnoughSpaceForLargeSuggestionMenu(listHeight, composerHeight, suggestions.length); @@ -159,15 +210,12 @@ function ComposerWithSuggestions({ /** * Set the TextInput Ref - * - * @param {Element} el - * @memberof ReportActionCompose */ const setTextInputRef = useCallback( (el) => { ReportActionComposeFocusManager.composerRef.current = el; textInputRef.current = el; - if (_.isFunction(animatedRef)) { + if (typeof animatedRef === 'function') { animatedRef(el); } }, @@ -196,7 +244,7 @@ function ComposerWithSuggestions({ * @param {Boolean} shouldDebounceSaveComment */ const updateComment = useCallback( - (commentValue, shouldDebounceSaveComment) => { + (commentValue: string, shouldDebounceSaveComment: boolean) => { raiseIsScrollLikelyLayoutTriggered(); const {text: newComment, emojis, cursorPosition} = EmojiUtils.replaceAndExtractEmojis(commentValue, preferredSkinTone, preferredLocale); if (!_.isEmpty(emojis)) { @@ -514,7 +562,7 @@ function ComposerWithSuggestions({ }, []); useImperativeHandle( - forwardedRef, + ref, () => ({ blur, focus, @@ -608,39 +656,28 @@ ComposerWithSuggestions.propTypes = propTypes; ComposerWithSuggestions.defaultProps = defaultProps; ComposerWithSuggestions.displayName = 'ComposerWithSuggestions'; -const ComposerWithSuggestionsWithRef = React.forwardRef((props, ref) => ( - -)); - -ComposerWithSuggestionsWithRef.displayName = 'ComposerWithSuggestionsWithRef'; - -export default compose( - withKeyboardState, - withOnyx({ - numberOfLines: { - key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT_NUMBER_OF_LINES}${reportID}`, - // We might not have number of lines in onyx yet, for which the composer would be rendered as null - // during the first render, which we want to avoid: - initWithStoredValues: false, - }, - modal: { - key: ONYXKEYS.MODAL, - }, - preferredSkinTone: { - key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, - selector: EmojiUtils.getPreferredSkinToneIndex, - }, - editFocused: { - key: ONYXKEYS.INPUT_FOCUSED, - }, - parentReportActions: { - key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, - canEvict: false, - initWithStoredValues: false, - }, - }), -)(ComposerWithSuggestionsWithRef); +const ComposerWithSuggestionsWithRef = forwardRef(ComposerWithSuggestions); + +export default withOnyx, ComposerWithSuggestionsOnyxProps>({ + numberOfLines: { + key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT_NUMBER_OF_LINES}${reportID}`, + // We might not have number of lines in onyx yet, for which the composer would be rendered as null + // during the first render, which we want to avoid: + initWithStoredValues: false, + }, + modal: { + key: ONYXKEYS.MODAL, + }, + preferredSkinTone: { + key: ONYXKEYS.PREFERRED_EMOJI_SKIN_TONE, + selector: EmojiUtils.getPreferredSkinToneIndex, + }, + editFocused: { + key: ONYXKEYS.INPUT_FOCUSED, + }, + parentReportActions: { + key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, + canEvict: false, + initWithStoredValues: false, + }, +})(ComposerWithSuggestionsWithRef); diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 9754d45be834..b46eb145173e 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -6,6 +6,7 @@ import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import {runOnJS, setNativeProps, useAnimatedRef} from 'react-native-reanimated'; +import type {Emoji} from '@assets/emojis/types'; import AttachmentModal from '@components/AttachmentModal'; import EmojiPickerButton from '@components/EmojiPicker/EmojiPickerButton'; import ExceededCommentLength from '@components/ExceededCommentLength'; @@ -389,7 +390,6 @@ function ReportActionCompose({ {({displayFileInModal}) => ( <> Date: Wed, 24 Jan 2024 09:45:39 +0100 Subject: [PATCH 029/202] fix: keep working on ComposerWithSuggestions --- src/components/Composer/index.tsx | 5 +- src/libs/updateMultilineInputRange/types.ts | 2 +- .../ComposerWithSuggestions.tsx | 110 +++++++++--------- .../{index.e2e.js => index.e2e.tsx} | 0 .../{index.js => index.tsx} | 0 .../ReportActionCompose.tsx | 2 +- .../SilentCommentUpdater/index.tsx | 2 +- .../ReportActionCompose/Suggestions.tsx | 4 +- 8 files changed, 65 insertions(+), 60 deletions(-) rename src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/{index.e2e.js => index.e2e.tsx} (100%) rename src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/{index.js => index.tsx} (100%) diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index 3c2caf020ef7..e78e0c2a4039 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -4,9 +4,8 @@ import type {BaseSyntheticEvent, ForwardedRef} from 'react'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {flushSync} from 'react-dom'; // eslint-disable-next-line no-restricted-imports -import type {DimensionValue, NativeSyntheticEvent, Text as RNText, TextInput, TextInputKeyPressEventData, TextInputProps, TextInputSelectionChangeEventData} from 'react-native'; +import type {DimensionValue, NativeSyntheticEvent, Text as RNText, TextInput, TextInputKeyPressEventData, TextInputSelectionChangeEventData} from 'react-native'; import {StyleSheet, View} from 'react-native'; -import type {AnimatedProps} from 'react-native-reanimated'; import RNTextInput from '@components/RNTextInput'; import Text from '@components/Text'; import useIsScrollBarVisible from '@hooks/useIsScrollBarVisible'; @@ -75,7 +74,7 @@ function Composer( shouldContainScroll = false, ...props }: ComposerProps, - ref: ForwardedRef>>, + ref: ForwardedRef, ) { const theme = useTheme(); const styles = useThemeStyles(); diff --git a/src/libs/updateMultilineInputRange/types.ts b/src/libs/updateMultilineInputRange/types.ts index d1b134b09a99..ce8f553c51f8 100644 --- a/src/libs/updateMultilineInputRange/types.ts +++ b/src/libs/updateMultilineInputRange/types.ts @@ -1,5 +1,5 @@ import type {TextInput} from 'react-native'; -type UpdateMultilineInputRange = (input: HTMLInputElement | TextInput, shouldAutoFocus?: boolean) => void; +type UpdateMultilineInputRange = (input: HTMLInputElement | TextInput | null, shouldAutoFocus?: boolean) => void; export default UpdateMultilineInputRange; diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index bce7d80121b4..cb5f2b52ffbc 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -2,10 +2,11 @@ import {useIsFocused, useNavigation} from '@react-navigation/native'; import lodashDebounce from 'lodash/debounce'; import type {ForwardedRef, RefAttributes, RefObject} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; -import type {MeasureInWindowOnSuccessCallback} from 'react-native'; +import type {LayoutChangeEvent, MeasureInWindowOnSuccessCallback, NativeSyntheticEvent, TextInput, TextInputSelectionChangeEventData} from 'react-native'; import {findNodeHandle, InteractionManager, NativeModules, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; +import type {useAnimatedRef} from 'react-native-reanimated'; import type {Emoji} from '@assets/emojis/types'; import Composer from '@components/Composer'; import useKeyboardState from '@hooks/useKeyboardState'; @@ -43,9 +44,16 @@ import type * as OnyxTypes from '@src/types/onyx'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; import {defaultProps, propTypes} from './composerWithSuggestionsProps'; +type SyncSelection = { + position: number; + value: string; +}; + +type AnimatedRef = ReturnType; + type ComposerWithSuggestionsOnyxProps = { /** The number of lines the comment should take up */ - numberOfLines: number; + numberOfLines: OnyxEntry; /** The parent report actions for the report */ parentReportActions: OnyxEntry; @@ -57,8 +65,9 @@ type ComposerWithSuggestionsOnyxProps = { preferredSkinTone: number; /** Whether the input is focused */ - editFocused: boolean; + editFocused: OnyxEntry; }; + type ComposerWithSuggestionsProps = { reportID: string; report: OnyxEntry; @@ -69,7 +78,7 @@ type ComposerWithSuggestionsProps = { isComposerFullSize: boolean; isMenuVisible: boolean; inputPlaceholder: string; - displayFileInModal: (fileURL: string) => void; + displayFileInModal: (file: File | undefined) => void; textInputShouldClear: boolean; setTextInputShouldClear: (shouldClear: boolean) => void; isBlockedFromConcierge: boolean; @@ -84,8 +93,8 @@ type ComposerWithSuggestionsProps = { isScrollLikelyLayoutTriggered: RefObject; raiseIsScrollLikelyLayoutTriggered: () => void; suggestionsRef: React.RefObject; - animatedRef: RefObject; - isNextModalWillOpenRef: RefObject; + animatedRef: AnimatedRef; + isNextModalWillOpenRef: RefObject; editFocused: boolean; } & ComposerWithSuggestionsOnyxProps & Partial; @@ -178,7 +187,7 @@ function ComposerWithSuggestions( const maxComposerLines = isSmallScreenWidth ? CONST.COMPOSER.MAX_LINES_SMALL_SCREEN : CONST.COMPOSER.MAX_LINES; const isEmptyChat = useMemo(() => reportActions?.length === 1, [reportActions]); - const parentReportAction = parentReportActions?.[report?.parentReportActionID ?? '']; + const parentReportAction = parentReportActions?.[report?.parentReportActionID ?? ''] ?? null; const shouldAutoFocus = !modal?.isVisible && (shouldFocusInputOnScreenFocus || (isEmptyChat && !ReportActionsUtils.isTransactionThread(parentReportAction))) && shouldShowComposeInput; const valueRef = useRef(value); @@ -188,14 +197,14 @@ function ComposerWithSuggestions( const [composerHeight, setComposerHeight] = useState(0); - const textInputRef = useRef(null); + const textInputRef = useRef(null); const insertedEmojisRef = useRef([]); - const syncSelectionWithOnChangeTextRef = useRef(null); + const syncSelectionWithOnChangeTextRef = useRef(null); const suggestions = suggestionsRef.current?.getSuggestions(); - const hasEnoughSpaceForLargeSuggestion = SuggestionUtils.hasEnoughSpaceForLargeSuggestionMenu(listHeight, composerHeight, suggestions.length); + const hasEnoughSpaceForLargeSuggestion = SuggestionUtils.hasEnoughSpaceForLargeSuggestionMenu(listHeight, composerHeight, suggestions?.length ?? 0); const isAutoSuggestionPickerLarge = !isSmallScreenWidth || (isSmallScreenWidth && hasEnoughSpaceForLargeSuggestion); @@ -212,7 +221,7 @@ function ComposerWithSuggestions( * Set the TextInput Ref */ const setTextInputRef = useCallback( - (el) => { + (el: TextInput) => { ReportActionComposeFocusManager.composerRef.current = el; textInputRef.current = el; if (typeof animatedRef === 'function') { @@ -231,7 +240,7 @@ function ComposerWithSuggestions( const debouncedSaveReportComment = useMemo( () => - _.debounce((selectedReportID, newComment) => { + lodashDebounce((selectedReportID, newComment) => { Report.saveReportComment(selectedReportID, newComment || ''); }, 1000), [], @@ -239,17 +248,14 @@ function ComposerWithSuggestions( /** * Update the value of the comment in Onyx - * - * @param {String} comment - * @param {Boolean} shouldDebounceSaveComment */ const updateComment = useCallback( - (commentValue: string, shouldDebounceSaveComment: boolean) => { + (commentValue: string | null, shouldDebounceSaveComment?: boolean) => { raiseIsScrollLikelyLayoutTriggered(); - const {text: newComment, emojis, cursorPosition} = EmojiUtils.replaceAndExtractEmojis(commentValue, preferredSkinTone, preferredLocale); - if (!_.isEmpty(emojis)) { + const {text: newComment, emojis, cursorPosition} = EmojiUtils.replaceAndExtractEmojis(commentValue ?? '', preferredSkinTone, preferredLocale); + if (emojis.length) { const newEmojis = EmojiUtils.getAddedEmojis(emojis, emojisPresentBefore.current); - if (!_.isEmpty(newEmojis)) { + if (newEmojis.length) { // Ensure emoji suggestions are hidden after inserting emoji even when the selection is not changed if (suggestionsRef.current) { suggestionsRef.current.resetSuggestions(); @@ -269,7 +275,7 @@ function ComposerWithSuggestions( emojisPresentBefore.current = emojis; setValue(newCommentConverted); if (commentValue !== newComment) { - const position = Math.max(selection.end + (newComment.length - commentRef.current.length), cursorPosition || 0); + const position = Math.max(selection.end + (newComment.length - commentRef.current.length), cursorPosition ?? 0); if (isIOSNative) { syncSelectionWithOnChangeTextRef.current = {position, value: newComment}; @@ -316,10 +322,9 @@ function ComposerWithSuggestions( /** * Update the number of lines for a comment in Onyx - * @param {Number} numberOfLines */ const updateNumberOfLines = useCallback( - (newNumberOfLines) => { + (newNumberOfLines: number) => { if (newNumberOfLines === numberOfLines) { return; } @@ -328,9 +333,6 @@ function ComposerWithSuggestions( [reportID, numberOfLines], ); - /** - * @returns {String} - */ const prepareCommentAndResetComposer = useCallback(() => { const trimmedComment = commentRef.current.trim(); const commentLength = ReportUtils.getCommentLength(trimmedComment); @@ -356,11 +358,9 @@ function ComposerWithSuggestions( /** * Callback to add whatever text is chosen into the main input (used f.e as callback for the emoji picker) - * @param {String} text - * @param {Boolean} shouldAddTrailSpace */ const replaceSelectionWithText = useCallback( - (text, shouldAddTrailSpace = true) => { + (text: string, shouldAddTrailSpace = true) => { const updatedText = shouldAddTrailSpace ? `${text} ` : text; const selectionSpaceLength = shouldAddTrailSpace ? CONST.SPACE_LENGTH : 0; updateComment(ComposerUtils.insertText(commentRef.current, selection, updatedText)); @@ -373,12 +373,12 @@ function ComposerWithSuggestions( ); const triggerHotkeyActions = useCallback( - (e) => { + (e: KeyboardEvent) => { if (!e || ComposerUtils.canSkipTriggerHotkeys(isSmallScreenWidth, isKeyboardShown)) { return; } - if (suggestionsRef.current.triggerHotkeyActions(e)) { + if (suggestionsRef.current?.triggerHotkeyActions(e)) { return; } @@ -390,14 +390,20 @@ function ComposerWithSuggestions( // Trigger the edit box for last sent message if ArrowUp is pressed and the comment is empty and Chronos is not in the participants const valueLength = valueRef.current.length; - if (e.key === CONST.KEYBOARD_SHORTCUTS.ARROW_UP.shortcutKey && textInputRef.current.selectionStart === 0 && valueLength === 0 && !ReportUtils.chatIncludesChronos(report)) { + if ( + e.key === CONST.KEYBOARD_SHORTCUTS.ARROW_UP.shortcutKey && + textInputRef.current && + 'selectionStart' in textInputRef.current && + textInputRef.current?.selectionStart === 0 && + valueLength === 0 && + !ReportUtils.chatIncludesChronos(report) + ) { e.preventDefault(); - const lastReportAction = _.find( - [...reportActions, parentReportAction], + const lastReportAction = [...(reportActions ?? []), parentReportAction].find( (action) => ReportUtils.canEditReportAction(action) && !ReportActionsUtils.isMoneyRequestAction(action), ); if (lastReportAction) { - Report.saveReportActionDraft(reportID, lastReportAction, _.last(lastReportAction.message).html); + Report.saveReportActionDraft(reportID, lastReportAction, lastReportAction.message?.at(-1)?.html ?? ''); } } }, @@ -405,7 +411,7 @@ function ComposerWithSuggestions( ); const onChangeText = useCallback( - (commentValue) => { + (commentValue: string) => { updateComment(commentValue, true); if (isIOSNative && syncSelectionWithOnChangeTextRef.current) { @@ -416,7 +422,7 @@ function ComposerWithSuggestions( InteractionManager.runAfterInteractions(() => { // note: this implementation is only available on non-web RN, thus the wrapping // 'if' block contains a redundant (since the ref is only used on iOS) platform check - textInputRef.current.setSelection(positionSnapshot, positionSnapshot); + textInputRef.current?.setSelection(positionSnapshot, positionSnapshot); }); } }, @@ -424,8 +430,8 @@ function ComposerWithSuggestions( ); const onSelectionChange = useCallback( - (e) => { - if (textInputRef.current && textInputRef.current.isFocused() && suggestionsRef.current.onSelectionChange(e)) { + (e: NativeSyntheticEvent) => { + if (textInputRef.current?.isFocused() && suggestionsRef.current?.onSelectionChange?.(e)) { return; } @@ -451,7 +457,7 @@ function ComposerWithSuggestions( /** * Focus the composer text input - * @param {Boolean} [shouldDelay=false] Impose delay before focusing the composer + * @param [shouldDelay=false] Impose delay before focusing the composer * @memberof ReportActionCompose */ const focus = useCallback((shouldDelay = false) => { @@ -475,12 +481,12 @@ function ComposerWithSuggestions( */ const checkComposerVisibility = useCallback(() => { // Checking whether the screen is focused or not, helps avoid `modal.isVisible` false when popups are closed, even if the modal is opened. - const isComposerCoveredUp = !isFocused || EmojiPickerActions.isEmojiPickerVisible() || isMenuVisible || modal.isVisible || modal.willAlertModalBecomeVisible; + const isComposerCoveredUp = !isFocused || EmojiPickerActions.isEmojiPickerVisible() || isMenuVisible || !!modal?.isVisible || modal?.willAlertModalBecomeVisible; return !isComposerCoveredUp; }, [isMenuVisible, modal, isFocused]); const focusComposerOnKeyPress = useCallback( - (e) => { + (e: KeyboardEvent) => { const isComposerVisible = checkComposerVisibility(); if (!isComposerVisible) { return; @@ -491,7 +497,7 @@ function ComposerWithSuggestions( } // if we're typing on another input/text area, do not focus - if (['INPUT', 'TEXTAREA'].includes(e.target.nodeName)) { + if (['INPUT', 'TEXTAREA'].includes((e.target as Element)?.nodeName)) { return; } @@ -527,17 +533,17 @@ function ComposerWithSuggestions( }; }, [focusComposerOnKeyPress, navigation, setUpComposeFocusManager]); - const prevIsModalVisible = usePrevious(modal.isVisible); + const prevIsModalVisible = usePrevious(modal?.isVisible); const prevIsFocused = usePrevious(isFocused); useEffect(() => { - if (modal.isVisible && !prevIsModalVisible) { + if (modal?.isVisible && !prevIsModalVisible) { // eslint-disable-next-line no-param-reassign isNextModalWillOpenRef.current = false; } // We want to focus or refocus the input when a modal has been closed or the underlying screen is refocused. // We avoid doing this on native platforms since the software keyboard popping // open creates a jarring and broken UX. - if (!((willBlurTextInputOnTapOutside || shouldAutoFocus) && !isNextModalWillOpenRef.current && !modal.isVisible && isFocused && (prevIsModalVisible || !prevIsFocused))) { + if (!((willBlurTextInputOnTapOutside || shouldAutoFocus) && !isNextModalWillOpenRef.current && !modal?.isVisible && isFocused && (!!prevIsModalVisible || !prevIsFocused))) { return; } @@ -546,11 +552,11 @@ function ComposerWithSuggestions( return; } focus(true); - }, [focus, prevIsFocused, editFocused, prevIsModalVisible, isFocused, modal.isVisible, isNextModalWillOpenRef, shouldAutoFocus]); + }, [focus, prevIsFocused, editFocused, prevIsModalVisible, isFocused, modal?.isVisible, isNextModalWillOpenRef, shouldAutoFocus]); useEffect(() => { // Scrolls the composer to the bottom and sets the selection to the end, so that longer drafts are easier to edit - updateMultilineInputRange(textInputRef.current, shouldAutoFocus); + updateMultilineInputRange(textInputRef.current, !!shouldAutoFocus); if (value.length === 0) { return; @@ -568,7 +574,7 @@ function ComposerWithSuggestions( focus, replaceSelectionWithText, prepareCommentAndResetComposer, - isFocused: () => textInputRef.current.isFocused(), + isFocused: () => !!textInputRef.current?.isFocused(), }), [blur, focus, prepareCommentAndResetComposer, replaceSelectionWithText], ); @@ -582,7 +588,7 @@ function ComposerWithSuggestions( { + onLayout={(e: LayoutChangeEvent) => { const composerLayoutHeight = e.nativeEvent.layout.height; if (composerHeight === composerLayoutHeight) { return; @@ -625,7 +631,7 @@ function ComposerWithSuggestions( void; onSelectionChange?: (event: NativeSyntheticEvent) => void; - triggerHotkeyActions: (event: KeyboardEvent) => void; + triggerHotkeyActions: (event: KeyboardEvent) => boolean | undefined; updateShouldShowSuggestionMenuToFalse: (shouldShowSuggestionMenu?: boolean) => void; setShouldBlockSuggestionCalc: (shouldBlock: boolean) => void; getSuggestions: () => Mention[] | Emoji[]; diff --git a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx index afee06dbc8ff..3f883d46a995 100644 --- a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx +++ b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx @@ -10,7 +10,7 @@ import type {SilentCommentUpdaterOnyxProps, SilentCommentUpdaterProps} from './t * It is connected to the actual draft comment in onyx. The comment in onyx might updates multiple times, and we want to avoid * re-rendering a UI component for that. That's why the side effect was moved down to a separate component. */ -function SilentCommentUpdater({comment = '', commentRef, report, value, updateComment}: SilentCommentUpdaterProps) { +function SilentCommentUpdater({comment, commentRef, report, value, updateComment}: SilentCommentUpdaterProps) { const prevCommentProp = usePrevious(comment); const prevReportId = usePrevious(report?.reportID); const {preferredLocale} = useLocalize(); diff --git a/src/pages/home/report/ReportActionCompose/Suggestions.tsx b/src/pages/home/report/ReportActionCompose/Suggestions.tsx index 2500af40c7c6..0968a61c3abb 100644 --- a/src/pages/home/report/ReportActionCompose/Suggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/Suggestions.tsx @@ -1,6 +1,6 @@ import type {ForwardedRef} from 'react'; import React, {forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useRef} from 'react'; -import type {NativeSyntheticEvent, TextInputSelectionChangeEventData} from 'react-native'; +import type {MeasureInWindowOnSuccessCallback, NativeSyntheticEvent, TextInputSelectionChangeEventData} from 'react-native'; import {View} from 'react-native'; import {DragAndDropContext} from '@components/DragAndDrop/Provider'; import usePrevious from '@hooks/usePrevious'; @@ -19,7 +19,7 @@ type SuggestionProps = { selection: Selection; setSelection: (newSelection: Selection) => void; updateComment: (newComment: string, shouldDebounceSaveComment?: boolean) => void; - measureParentContainer: () => void; + measureParentContainer: (callback: MeasureInWindowOnSuccessCallback) => void; isComposerFullSize: boolean; isComposerFocused?: boolean; resetKeyboardInput?: () => void; From 35c7989f0a50998748982e6a4722ea2953616035 Mon Sep 17 00:00:00 2001 From: tienifr Date: Wed, 24 Jan 2024 18:41:13 +0700 Subject: [PATCH 030/202] remove cached file when delete comment --- src/ONYXKEYS.ts | 4 ++ .../AttachmentCarousel/CarouselItem.js | 1 + .../Attachments/AttachmentView/index.js | 17 +++++++- src/components/PDFView/index.native.js | 6 ++- src/libs/actions/CachedPDFPaths.ts | 39 +++++++++++++++++++ src/libs/actions/Report.ts | 2 + 6 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 src/libs/actions/CachedPDFPaths.ts diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 9693c907a5fe..e8caede964e6 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -249,6 +249,9 @@ const ONYXKEYS = { /** Indicates whether an forced upgrade is required */ UPDATE_REQUIRED: 'updateRequired', + // Paths of PDF file that has been cached during one session + CACHED_PDF_PATHS: 'cachedPDFPaths', + /** Collection Keys */ COLLECTION: { DOWNLOAD: 'download_', @@ -446,6 +449,7 @@ type OnyxValues = { [ONYXKEYS.MAX_CANVAS_HEIGHT]: number; [ONYXKEYS.MAX_CANVAS_WIDTH]: number; [ONYXKEYS.UPDATE_REQUIRED]: boolean; + [ONYXKEYS.CACHED_PDF_PATHS]: Record; // Collections [ONYXKEYS.COLLECTION.DOWNLOAD]: OnyxTypes.Download; diff --git a/src/components/Attachments/AttachmentCarousel/CarouselItem.js b/src/components/Attachments/AttachmentCarousel/CarouselItem.js index 5552f15320f3..53d72be49a47 100644 --- a/src/components/Attachments/AttachmentCarousel/CarouselItem.js +++ b/src/components/Attachments/AttachmentCarousel/CarouselItem.js @@ -110,6 +110,7 @@ function CarouselItem({item, index, activeIndex, isSingleItem, onPress}) { carouselActiveItemIndex={activeIndex} onPress={onPress} transactionID={item.transactionID} + reportActionID={item.reportActionID} /> diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index b0060afdb813..1a6f4d92c0e8 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -15,6 +15,7 @@ import useNetwork from '@hooks/useNetwork'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as CachedPDFPaths from '@libs/actions/CachedPDFPaths'; import addEncryptedAuthTokenToURL from '@libs/addEncryptedAuthTokenToURL'; import compose from '@libs/compose'; import * as TransactionUtils from '@libs/TransactionUtils'; @@ -47,6 +48,9 @@ const propTypes = { /** The id of the transaction related to the attachment */ // eslint-disable-next-line react/no-unused-prop-types transactionID: PropTypes.string, + + /** The id of the report action related to the attachment */ + reportActionID: PropTypes.string, }; const defaultProps = { @@ -57,6 +61,7 @@ const defaultProps = { containerStyles: [], isWorkspaceAvatar: false, transactionID: '', + reportActionID: '', }; function AttachmentView({ @@ -79,6 +84,7 @@ function AttachmentView({ isWorkspaceAvatar, fallbackSource, transaction, + reportActionID, }) { const theme = useTheme(); const styles = useThemeStyles(); @@ -127,6 +133,15 @@ function AttachmentView({ if ((_.isString(source) && Str.isPDF(source)) || (file && Str.isPDF(file.name || translate('attachmentView.unknownFilename')))) { const encryptedSourceUrl = isAuthTokenRequired ? addEncryptedAuthTokenToURL(source) : source; + const onPDFLoadComplete = (path) => { + if (isUsedInCarousel && reportActionID) { + CachedPDFPaths.add(reportActionID, path); + } + if (!loadComplete) { + setLoadComplete(true); + } + }; + // We need the following View component on android native // So that the event will propagate properly and // the Password protected preview will be shown for pdf attachement we are about to send. @@ -143,7 +158,7 @@ function AttachmentView({ onPress={onPress} onScaleChanged={onScaleChanged} onToggleKeyboard={onToggleKeyboard} - onLoadComplete={() => !loadComplete && setLoadComplete(true)} + onLoadComplete={onPDFLoadComplete} errorLabelStyles={isUsedInAttachmentModal ? [styles.textLabel, styles.textLarge] : [styles.cursorAuto]} style={isUsedInAttachmentModal ? styles.imageModalPDF : styles.flex1} isUsedInCarousel={isUsedInCarousel} diff --git a/src/components/PDFView/index.native.js b/src/components/PDFView/index.native.js index cbe7f0e4608e..08f2eb2c6984 100644 --- a/src/components/PDFView/index.native.js +++ b/src/components/PDFView/index.native.js @@ -118,14 +118,16 @@ class PDFView extends Component { /** * After the PDF is successfully loaded hide PDFPasswordForm and the loading * indicator. + * @param {Number} numberOfPages + * @param {Number} path - Path to cache location */ - finishPDFLoad() { + finishPDFLoad(numberOfPages, path) { this.setState({ shouldRequestPassword: false, shouldShowLoadingIndicator: false, successToLoadPDF: true, }); - this.props.onLoadComplete(); + this.props.onLoadComplete(path); } renderPDFView() { diff --git a/src/libs/actions/CachedPDFPaths.ts b/src/libs/actions/CachedPDFPaths.ts new file mode 100644 index 000000000000..28626dc34856 --- /dev/null +++ b/src/libs/actions/CachedPDFPaths.ts @@ -0,0 +1,39 @@ +import {exists, unlink} from 'react-native-fs'; +import Onyx from 'react-native-onyx'; +import ONYXKEYS from '@src/ONYXKEYS'; + +let pdfPaths: Record = {}; +Onyx.connect({ + key: ONYXKEYS.CACHED_PDF_PATHS, + callback: (val) => { + pdfPaths = val ?? {}; + }, +}); + +function add(reportActionID: string, path: string): Promise { + return Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {[reportActionID]: path}); +} + +function clear(path: string): Promise { + if (!path) { + return Promise.resolve(); + } + return new Promise((resolve) => { + exists(path).then((exist) => { + if (!exist) { + resolve(); + } + return unlink(path); + }); + }); +} + +function clearByKey(reportActionID: string) { + clear(pdfPaths[reportActionID] ?? '').then(() => Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {[reportActionID]: null})); +} + +function clearAll() { + Promise.all(Object.values(pdfPaths).map(clear)).then(() => Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {})); +} + +export {add, clearByKey, clearAll}; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 228b88d194ba..753831470c66 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -40,6 +40,7 @@ import type {Message, ReportActionBase, ReportActions} from '@src/types/onyx/Rep import type ReportAction from '@src/types/onyx/ReportAction'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import * as CachedPDFPaths from './CachedPDFPaths'; import * as Modal from './Modal'; import * as Session from './Session'; import * as Welcome from './Welcome'; @@ -1223,6 +1224,7 @@ function deleteReportComment(reportID: string, reportAction: ReportAction) { reportActionID, }; + CachedPDFPaths.clearByKey(reportActionID); API.write('DeleteComment', parameters, {optimisticData, successData, failureData}); } From 223fdd804f52f0adf9eb5891f8cd00da0dd91726 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 24 Jan 2024 12:51:51 +0100 Subject: [PATCH 031/202] fix: wip --- src/components/Composer/index.tsx | 2 +- src/components/Composer/types.ts | 2 +- .../ComposerWithSuggestions.tsx | 10 ++++++---- .../ReportActionCompose/SilentCommentUpdater/index.tsx | 7 +++---- .../ReportActionCompose/SilentCommentUpdater/types.ts | 3 --- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index e78e0c2a4039..a23a176c5bcd 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -300,7 +300,7 @@ function Composer( }, []); const handleKeyPress = useCallback( - (e: NativeSyntheticEvent) => { + (e: NativeSyntheticEvent & KeyboardEvent) => { // Prevent onKeyPress from being triggered if the Enter key is pressed while text is being composed if (!onKeyPress || isEnterWhileComposition(e as unknown as KeyboardEvent)) { return; diff --git a/src/components/Composer/types.ts b/src/components/Composer/types.ts index d8d88970ea78..6e486771c9aa 100644 --- a/src/components/Composer/types.ts +++ b/src/components/Composer/types.ts @@ -74,7 +74,7 @@ type ComposerProps = { /** Whether the sull composer is open */ isComposerFullSize?: boolean; - onKeyPress?: (event: NativeSyntheticEvent) => void; + onKeyPress?: (event: KeyboardEvent & NativeSyntheticEvent) => void; onFocus?: (event: NativeSyntheticEvent) => void; diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index cb5f2b52ffbc..034affefd747 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -2,7 +2,7 @@ import {useIsFocused, useNavigation} from '@react-navigation/native'; import lodashDebounce from 'lodash/debounce'; import type {ForwardedRef, RefAttributes, RefObject} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; -import type {LayoutChangeEvent, MeasureInWindowOnSuccessCallback, NativeSyntheticEvent, TextInput, TextInputSelectionChangeEventData} from 'react-native'; +import type {LayoutChangeEvent, MeasureInWindowOnSuccessCallback, NativeSyntheticEvent, TextInput, TextInputFocusEventData, TextInputSelectionChangeEventData} from 'react-native'; import {findNodeHandle, InteractionManager, NativeModules, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; @@ -73,7 +73,7 @@ type ComposerWithSuggestionsProps = { report: OnyxEntry; reportActions: OnyxTypes.ReportAction[] | undefined; onFocus: () => void; - onBlur: (event: FocusEvent) => void; + onBlur: (event: NativeSyntheticEvent) => void; onValueChange: (value: string) => void; isComposerFullSize: boolean; isMenuVisible: boolean; @@ -222,6 +222,7 @@ function ComposerWithSuggestions( */ const setTextInputRef = useCallback( (el: TextInput) => { + // @ts-expect-error need to reassign this ref ReportActionComposeFocusManager.composerRef.current = el; textInputRef.current = el; if (typeof animatedRef === 'function') { @@ -373,7 +374,7 @@ function ComposerWithSuggestions( ); const triggerHotkeyActions = useCallback( - (e: KeyboardEvent) => { + (e: KeyboardEvent & NativeSyntheticEvent) => { if (!e || ComposerUtils.canSkipTriggerHotkeys(isSmallScreenWidth, isKeyboardShown)) { return; } @@ -537,6 +538,7 @@ function ComposerWithSuggestions( const prevIsFocused = usePrevious(isFocused); useEffect(() => { if (modal?.isVisible && !prevIsModalVisible) { + // @ts-expect-error need to reassign this ref // eslint-disable-next-line no-param-reassign isNextModalWillOpenRef.current = false; } @@ -682,7 +684,7 @@ export default withOnyx `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, + key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.parentReportID}`, canEvict: false, initWithStoredValues: false, }, diff --git a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx index 3f883d46a995..626938c235da 100644 --- a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx +++ b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx @@ -10,14 +10,14 @@ import type {SilentCommentUpdaterOnyxProps, SilentCommentUpdaterProps} from './t * It is connected to the actual draft comment in onyx. The comment in onyx might updates multiple times, and we want to avoid * re-rendering a UI component for that. That's why the side effect was moved down to a separate component. */ -function SilentCommentUpdater({comment, commentRef, report, value, updateComment}: SilentCommentUpdaterProps) { +function SilentCommentUpdater({comment = '', commentRef, report, value, updateComment}: SilentCommentUpdaterProps) { const prevCommentProp = usePrevious(comment); const prevReportId = usePrevious(report?.reportID); const {preferredLocale} = useLocalize(); const prevPreferredLocale = usePrevious(preferredLocale); useEffect(() => { - updateComment(comment); + updateComment(comment ?? null); // eslint-disable-next-line react-hooks/exhaustive-deps -- We need to run this on mount }, []); @@ -32,7 +32,7 @@ function SilentCommentUpdater({comment, commentRef, report, value, updateComment return; } - updateComment(comment); + updateComment(comment ?? null); }, [prevCommentProp, prevPreferredLocale, prevReportId, comment, preferredLocale, report?.reportID, updateComment, value, commentRef]); return null; @@ -43,6 +43,5 @@ SilentCommentUpdater.displayName = 'SilentCommentUpdater'; export default withOnyx({ comment: { key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`, - initialValue: '', }, })(SilentCommentUpdater); diff --git a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts index 60924f24099b..591ee43ce6cd 100644 --- a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts +++ b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts @@ -21,9 +21,6 @@ type SilentCommentUpdaterProps = { /** The ref of the comment */ commentRef: React.RefObject; - - /** The comment of the report */ - commnet: string; } & SilentCommentUpdaterOnyxProps; export type {SilentCommentUpdaterProps, SilentCommentUpdaterOnyxProps}; From 05bb0a591c9401ae62f15833afd801237e6af3ee Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 24 Jan 2024 16:20:44 +0100 Subject: [PATCH 032/202] fix: finished migrating ComposerWithSuggestions, removed unused files, start migrating ReportTypeingIndicator --- src/components/Composer/index.tsx | 3 +- src/components/Composer/types.ts | 10 +- src/components/MentionSuggestions.tsx | 3 +- src/libs/E2E/client.ts | 3 + .../ComposerWithSuggestions.tsx | 37 ++--- .../composerWithSuggestionsProps.js | 126 ------------------ .../ComposerWithSuggestions/index.e2e.tsx | 18 +-- .../ReportActionCompose.tsx | 9 +- .../ReportActionCompose/suggestionProps.js | 39 ------ ...Indicator.js => ReportTypingIndicator.tsx} | 0 src/types/modules/react-native.d.ts | 5 - 11 files changed, 46 insertions(+), 207 deletions(-) delete mode 100644 src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/composerWithSuggestionsProps.js delete mode 100644 src/pages/home/report/ReportActionCompose/suggestionProps.js rename src/pages/home/report/{ReportTypingIndicator.js => ReportTypingIndicator.tsx} (100%) diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index a23a176c5bcd..493b37ff3a31 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -300,11 +300,12 @@ function Composer( }, []); const handleKeyPress = useCallback( - (e: NativeSyntheticEvent & KeyboardEvent) => { + (e: NativeSyntheticEvent) => { // Prevent onKeyPress from being triggered if the Enter key is pressed while text is being composed if (!onKeyPress || isEnterWhileComposition(e as unknown as KeyboardEvent)) { return; } + onKeyPress(e); }, [onKeyPress], diff --git a/src/components/Composer/types.ts b/src/components/Composer/types.ts index 6e486771c9aa..9565eaf6208f 100644 --- a/src/components/Composer/types.ts +++ b/src/components/Composer/types.ts @@ -1,4 +1,4 @@ -import type {NativeSyntheticEvent, StyleProp, TextInputFocusEventData, TextInputKeyPressEventData, TextInputSelectionChangeEventData, TextStyle} from 'react-native'; +import type {NativeSyntheticEvent, StyleProp, TextInputProps, TextInputSelectionChangeEventData, TextStyle} from 'react-native'; type TextSelection = { start: number; @@ -74,14 +74,8 @@ type ComposerProps = { /** Whether the sull composer is open */ isComposerFullSize?: boolean; - onKeyPress?: (event: KeyboardEvent & NativeSyntheticEvent) => void; - - onFocus?: (event: NativeSyntheticEvent) => void; - - onBlur?: (event: NativeSyntheticEvent) => void; - /** Should make the input only scroll inside the element avoid scroll out to parent */ shouldContainScroll?: boolean; -}; +} & TextInputProps; export type {TextSelection, ComposerProps}; diff --git a/src/components/MentionSuggestions.tsx b/src/components/MentionSuggestions.tsx index 99930f995a3a..23040a242807 100644 --- a/src/components/MentionSuggestions.tsx +++ b/src/components/MentionSuggestions.tsx @@ -1,4 +1,5 @@ import React, {useCallback} from 'react'; +import type {MeasureInWindowOnSuccessCallback} from 'react-native'; import {View} from 'react-native'; import useStyleUtils from '@hooks/useStyleUtils'; import useTheme from '@hooks/useTheme'; @@ -43,7 +44,7 @@ type MentionSuggestionsProps = { isMentionPickerLarge: boolean; /** Measures the parent container's position and dimensions. */ - measureParentContainer: () => void; + measureParentContainer: (callback: MeasureInWindowOnSuccessCallback) => void; }; /** diff --git a/src/libs/E2E/client.ts b/src/libs/E2E/client.ts index 472567cc6c1d..7dc3ad4073b9 100644 --- a/src/libs/E2E/client.ts +++ b/src/libs/E2E/client.ts @@ -11,6 +11,9 @@ type TestResult = { type TestConfig = { name: string; + reportScreen?: { + autoFocus?: boolean; + }; }; type NativeCommandPayload = { diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index 034affefd747..c02bda08cac7 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -2,7 +2,15 @@ import {useIsFocused, useNavigation} from '@react-navigation/native'; import lodashDebounce from 'lodash/debounce'; import type {ForwardedRef, RefAttributes, RefObject} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; -import type {LayoutChangeEvent, MeasureInWindowOnSuccessCallback, NativeSyntheticEvent, TextInput, TextInputFocusEventData, TextInputSelectionChangeEventData} from 'react-native'; +import type { + LayoutChangeEvent, + MeasureInWindowOnSuccessCallback, + NativeSyntheticEvent, + TextInput, + TextInputFocusEventData, + TextInputKeyPressEventData, + TextInputSelectionChangeEventData, +} from 'react-native'; import {findNodeHandle, InteractionManager, NativeModules, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; @@ -42,7 +50,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type * as OnyxTypes from '@src/types/onyx'; import type ChildrenProps from '@src/types/utils/ChildrenProps'; -import {defaultProps, propTypes} from './composerWithSuggestionsProps'; type SyncSelection = { position: number; @@ -126,7 +133,7 @@ function ComposerWithSuggestions( { // Onyx modal, - preferredSkinTone, + preferredSkinTone = CONST.EMOJI_DEFAULT_SKIN_TONE, parentReportActions, numberOfLines, @@ -152,7 +159,7 @@ function ComposerWithSuggestions( setIsCommentEmpty, handleSendMessage, shouldShowComposeInput, - measureParentContainer, + measureParentContainer = () => {}, listHeight, isScrollLikelyLayoutTriggered, raiseIsScrollLikelyLayoutTriggered, @@ -164,7 +171,7 @@ function ComposerWithSuggestions( // For testing children, }: ComposerWithSuggestionsProps, - ref: ForwardedRef, + ref: ForwardedRef, ) { const {isKeyboardShown} = useKeyboardState(); const theme = useTheme(); @@ -374,32 +381,33 @@ function ComposerWithSuggestions( ); const triggerHotkeyActions = useCallback( - (e: KeyboardEvent & NativeSyntheticEvent) => { - if (!e || ComposerUtils.canSkipTriggerHotkeys(isSmallScreenWidth, isKeyboardShown)) { + (event: NativeSyntheticEvent) => { + const webEvent = event as unknown as KeyboardEvent; + if (!webEvent || ComposerUtils.canSkipTriggerHotkeys(isSmallScreenWidth, isKeyboardShown)) { return; } - if (suggestionsRef.current?.triggerHotkeyActions(e)) { + if (suggestionsRef.current?.triggerHotkeyActions(webEvent)) { return; } // Submit the form when Enter is pressed - if (e.key === CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey && !e.shiftKey) { - e.preventDefault(); + if (webEvent.key === CONST.KEYBOARD_SHORTCUTS.ENTER.shortcutKey && !webEvent.shiftKey) { + webEvent.preventDefault(); handleSendMessage(); } // Trigger the edit box for last sent message if ArrowUp is pressed and the comment is empty and Chronos is not in the participants const valueLength = valueRef.current.length; if ( - e.key === CONST.KEYBOARD_SHORTCUTS.ARROW_UP.shortcutKey && + webEvent.key === CONST.KEYBOARD_SHORTCUTS.ARROW_UP.shortcutKey && textInputRef.current && 'selectionStart' in textInputRef.current && textInputRef.current?.selectionStart === 0 && valueLength === 0 && !ReportUtils.chatIncludesChronos(report) ) { - e.preventDefault(); + webEvent.preventDefault(); const lastReportAction = [...(reportActions ?? []), parentReportAction].find( (action) => ReportUtils.canEditReportAction(action) && !ReportActionsUtils.isMoneyRequestAction(action), ); @@ -568,7 +576,6 @@ function ComposerWithSuggestions( // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - useImperativeHandle( ref, () => ({ @@ -660,8 +667,6 @@ function ComposerWithSuggestions( ); } -ComposerWithSuggestions.propTypes = propTypes; -ComposerWithSuggestions.defaultProps = defaultProps; ComposerWithSuggestions.displayName = 'ComposerWithSuggestions'; const ComposerWithSuggestionsWithRef = forwardRef(ComposerWithSuggestions); @@ -689,3 +694,5 @@ export default withOnyx {}, -}; - -export {propTypes, defaultProps}; diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx index cbbd1758c9cb..87352981ba9a 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx @@ -1,6 +1,8 @@ -import _ from 'lodash'; -import React, {useEffect} from 'react'; +import type {ForwardedRef, RefObject} from 'react'; +import React, {forwardRef, useEffect} from 'react'; import E2EClient from '@libs/E2E/client'; +import type {ComposerRef} from '@pages/home/report/ReportActionCompose/ReportActionCompose'; +import type {ComposerWithSuggestionsProps} from './ComposerWithSuggestions'; import ComposerWithSuggestions from './ComposerWithSuggestions'; let rerenderCount = 0; @@ -14,20 +16,20 @@ function IncrementRenderCount() { return null; } -const ComposerWithSuggestionsE2e = React.forwardRef((props, ref) => { +function ComposerWithSuggestionsE2e(props: ComposerWithSuggestionsProps, ref: ForwardedRef) { // Eventually Auto focus on e2e tests useEffect(() => { - if (_.get(E2EClient.getCurrentActiveTestConfig(), 'reportScreen.autoFocus', false) === false) { + if ((E2EClient.getCurrentActiveTestConfig()?.reportScreen?.autoFocus ?? false) === false) { return; } // We need to wait for the component to be mounted before focusing setTimeout(() => { - if (!ref || !ref.current) { + if (!(ref as RefObject)?.current) { return; } - ref.current.focus(true); + (ref as RefObject).current?.focus(true); }, 1); }, [ref]); @@ -44,9 +46,9 @@ const ComposerWithSuggestionsE2e = React.forwardRef((props, ref) => { ); -}); +} ComposerWithSuggestionsE2e.displayName = 'ComposerWithSuggestionsE2e'; -export default ComposerWithSuggestionsE2e; +export default forwardRef(ComposerWithSuggestionsE2e); export {getRerenderCount, resetRerenderCount}; diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index d7e02fe29fcd..70c5f61d7725 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -1,7 +1,7 @@ import {PortalHost} from '@gorhom/portal'; import type {SyntheticEvent} from 'react'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import type {MeasureInWindowOnSuccessCallback, NativeSyntheticEvent, TextInputSelectionChangeEventData} from 'react-native'; +import type {MeasureInWindowOnSuccessCallback, NativeSyntheticEvent, TextInputFocusEventData, TextInputSelectionChangeEventData} from 'react-native'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; @@ -123,7 +123,7 @@ function ReportActionCompose({ const {isMediumScreenWidth, isSmallScreenWidth} = useWindowDimensions(); const {isOffline} = useNetwork(); const animatedRef = useAnimatedRef(); - const actionButtonRef = useRef(null); + const actionButtonRef = useRef(null); const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT; /** * Updates the Highlight state of the composer @@ -300,12 +300,13 @@ function ReportActionCompose({ isKeyboardVisibleWhenShowingModalRef.current = true; }, []); - const onBlur = useCallback((event: FocusEvent) => { + const onBlur = useCallback((event: NativeSyntheticEvent) => { + const webEvent = event as unknown as FocusEvent; setIsFocused(false); if (suggestionsRef.current) { suggestionsRef.current.resetSuggestions(); } - if (event.relatedTarget && event.relatedTarget === actionButtonRef.current) { + if (webEvent.relatedTarget && webEvent.relatedTarget === actionButtonRef.current) { isKeyboardVisibleWhenShowingModalRef.current = true; } }, []); diff --git a/src/pages/home/report/ReportActionCompose/suggestionProps.js b/src/pages/home/report/ReportActionCompose/suggestionProps.js deleted file mode 100644 index 62c29f3d418e..000000000000 --- a/src/pages/home/report/ReportActionCompose/suggestionProps.js +++ /dev/null @@ -1,39 +0,0 @@ -import PropTypes from 'prop-types'; - -const baseProps = { - /** The current input value */ - value: PropTypes.string.isRequired, - - /** Callback to update the current input value */ - setValue: PropTypes.func.isRequired, - - /** The current selection value */ - selection: PropTypes.shape({ - start: PropTypes.number.isRequired, - end: PropTypes.number.isRequired, - }).isRequired, - - /** Callback to update the current selection */ - setSelection: PropTypes.func.isRequired, - - /** Whether the composer is expanded */ - isComposerFullSize: PropTypes.bool.isRequired, - - /** Callback to update the comment draft */ - updateComment: PropTypes.func.isRequired, - - /** Meaures the parent container's position and dimensions. */ - measureParentContainer: PropTypes.func.isRequired, - - /** Report composer focus state */ - isComposerFocused: PropTypes.bool, -}; - -const implementationBaseProps = { - /** Whether to use the small or the big suggestion picker */ - isAutoSuggestionPickerLarge: PropTypes.bool.isRequired, - - ...baseProps, -}; - -export {baseProps, implementationBaseProps}; diff --git a/src/pages/home/report/ReportTypingIndicator.js b/src/pages/home/report/ReportTypingIndicator.tsx similarity index 100% rename from src/pages/home/report/ReportTypingIndicator.js rename to src/pages/home/report/ReportTypingIndicator.tsx diff --git a/src/types/modules/react-native.d.ts b/src/types/modules/react-native.d.ts index aaa7058737ae..7313a28984fc 100644 --- a/src/types/modules/react-native.d.ts +++ b/src/types/modules/react-native.d.ts @@ -279,14 +279,9 @@ declare module 'react-native' { * Extracted from react-native-web, packages/react-native-web/src/exports/TextInput/types.js */ interface WebTextInputProps extends WebSharedProps { - dir?: 'auto' | 'ltr' | 'rtl'; disabled?: boolean; - enterKeyHint?: 'enter' | 'done' | 'go' | 'next' | 'previous' | 'search' | 'send'; - readOnly?: boolean; } interface TextInputProps extends WebTextInputProps { - // TODO: remove once the app is updated to RN 0.73 - smartInsertDelete?: boolean; isFullComposerAvailable?: boolean; } From cf84b3b817a85d6baa5c28e2913068e2d487b260 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 24 Jan 2024 17:47:16 +0100 Subject: [PATCH 033/202] fix: move ReportTypingIndicator to TS --- .../home/report/ReportTypingIndicator.tsx | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/pages/home/report/ReportTypingIndicator.tsx b/src/pages/home/report/ReportTypingIndicator.tsx index 785f1e3f6a1e..f7f135e7374e 100755 --- a/src/pages/home/report/ReportTypingIndicator.tsx +++ b/src/pages/home/report/ReportTypingIndicator.tsx @@ -1,7 +1,6 @@ -import PropTypes from 'prop-types'; import React, {useMemo} from 'react'; +import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; import Text from '@components/Text'; import TextWithEllipsis from '@components/TextWithEllipsis'; import useLocalize from '@hooks/useLocalize'; @@ -9,28 +8,30 @@ import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ReportUtils from '@libs/ReportUtils'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {ReportUserIsTyping} from '@src/types/onyx'; -const propTypes = { +type ReportTypingIndicatorOnyxProps = { /** Key-value pairs of user accountIDs/logins and whether or not they are typing. Keys are accountIDs or logins. */ - userTypingStatuses: PropTypes.objectOf(PropTypes.bool), + userTypingStatuses: OnyxEntry; }; -const defaultProps = { - userTypingStatuses: {}, -}; +type ReportTypingIndicatorProps = { + // eslint-disable-next-line react/no-unused-prop-types + reportID: string; +} & ReportTypingIndicatorOnyxProps; -function ReportTypingIndicator({userTypingStatuses}) { +function ReportTypingIndicator({userTypingStatuses}: ReportTypingIndicatorProps) { const {translate} = useLocalize(); const {isOffline} = useNetwork(); const styles = useThemeStyles(); - const usersTyping = useMemo(() => _.filter(_.keys(userTypingStatuses), (loginOrAccountID) => userTypingStatuses[loginOrAccountID]), [userTypingStatuses]); + const usersTyping = useMemo(() => Object.keys(userTypingStatuses ?? {}).filter((loginOrAccountID) => userTypingStatuses?.[loginOrAccountID]), [userTypingStatuses]); const firstUserTyping = usersTyping[0]; const isUserTypingADisplayName = Number.isNaN(Number(firstUserTyping)); // If we are offline, the user typing statuses are not up-to-date so do not show them - if (isOffline || !firstUserTyping) { + if (!!isOffline || !firstUserTyping) { return null; } @@ -40,6 +41,7 @@ function ReportTypingIndicator({userTypingStatuses}) { if (usersTyping.length === 1) { return ( ({ userTypingStatuses: { key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_USER_IS_TYPING}${reportID}`, - initialValue: {}, }, })(ReportTypingIndicator); From 87f22f7e925b169a76d74e9a3eed6643283306c9 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 24 Jan 2024 18:26:51 +0100 Subject: [PATCH 034/202] fix: migrate ParticipanLocalTime and ReportDropUI --- ...tLocalTime.js => ParticipantLocalTime.tsx} | 35 ++++++++++--------- .../{ReportDropUI.js => ReportDropUI.tsx} | 9 ++--- .../home/report/ReportTypingIndicator.tsx | 2 +- src/types/onyx/IOU.ts | 2 ++ 4 files changed, 25 insertions(+), 23 deletions(-) rename src/pages/home/report/{ParticipantLocalTime.js => ParticipantLocalTime.tsx} (66%) rename src/pages/home/report/{ReportDropUI.js => ReportDropUI.tsx} (87%) diff --git a/src/pages/home/report/ParticipantLocalTime.js b/src/pages/home/report/ParticipantLocalTime.tsx similarity index 66% rename from src/pages/home/report/ParticipantLocalTime.js rename to src/pages/home/report/ParticipantLocalTime.tsx index 1992953c959e..c8bbaf031e32 100644 --- a/src/pages/home/report/ParticipantLocalTime.js +++ b/src/pages/home/report/ParticipantLocalTime.tsx @@ -1,36 +1,39 @@ -import lodashGet from 'lodash/get'; import React, {useEffect, useState} from 'react'; import {View} from 'react-native'; -import participantPropTypes from '@components/participantPropTypes'; import Text from '@components/Text'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import DateUtils from '@libs/DateUtils'; import Timers from '@libs/Timers'; import CONST from '@src/CONST'; +import type {PersonalDetails} from '@src/types/onyx'; +import type DeepValueOf from '@src/types/utils/DeepValueOf'; -const propTypes = { +type Locales = DeepValueOf; + +type ParticipantLocalTimeProps = { /** Personal details of the participant */ - participant: participantPropTypes.isRequired, + participant: PersonalDetails; - ...withLocalizePropTypes, + preferredLocale: Locales; }; -function getParticipantLocalTime(participant, preferredLocale) { - const reportRecipientTimezone = lodashGet(participant, 'timezone', CONST.DEFAULT_TIME_ZONE); - const reportTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale, null, reportRecipientTimezone.selected); +function getParticipantLocalTime(participant: PersonalDetails, preferredLocale: Locales) { + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const reportRecipientTimezone = participant.timezone || CONST.DEFAULT_TIME_ZONE; + const reportTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale, undefined, reportRecipientTimezone.selected); const currentTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale); - const reportRecipientDay = DateUtils.formatToDayOfWeek(reportTimezone); - const currentUserDay = DateUtils.formatToDayOfWeek(currentTimezone); + const reportRecipientDay = DateUtils.formatToDayOfWeek(reportTimezone.toDateString()); + const currentUserDay = DateUtils.formatToDayOfWeek(currentTimezone.toDateString()); if (reportRecipientDay !== currentUserDay) { return `${DateUtils.formatToLocalTime(reportTimezone)} ${reportRecipientDay}`; } return `${DateUtils.formatToLocalTime(reportTimezone)}`; } -function ParticipantLocalTime(props) { +function ParticipantLocalTime({participant, preferredLocale}: ParticipantLocalTimeProps) { + const {translate} = useLocalize(); const styles = useThemeStyles(); - const {participant, preferredLocale, translate} = props; const [localTime, setLocalTime] = useState(() => getParticipantLocalTime(participant, preferredLocale)); useEffect(() => { @@ -44,7 +47,8 @@ function ParticipantLocalTime(props) { }; }, [participant, preferredLocale]); - const reportRecipientDisplayName = lodashGet(props, 'participant.firstName') || lodashGet(props, 'participant.displayName'); + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const reportRecipientDisplayName = participant.firstName || participant.displayName; if (!reportRecipientDisplayName) { return null; @@ -65,7 +69,6 @@ function ParticipantLocalTime(props) { ); } -ParticipantLocalTime.propTypes = propTypes; ParticipantLocalTime.displayName = 'ParticipantLocalTime'; -export default withLocalize(ParticipantLocalTime); +export default ParticipantLocalTime; diff --git a/src/pages/home/report/ReportDropUI.js b/src/pages/home/report/ReportDropUI.tsx similarity index 87% rename from src/pages/home/report/ReportDropUI.js rename to src/pages/home/report/ReportDropUI.tsx index c1c3b8e506ab..d147d0c0c03d 100644 --- a/src/pages/home/report/ReportDropUI.js +++ b/src/pages/home/report/ReportDropUI.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {View} from 'react-native'; import DragAndDropConsumer from '@components/DragAndDrop/Consumer'; @@ -8,12 +7,11 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -const propTypes = { +type ReportDropUIProps = { /** Callback to execute when a file is dropped. */ - onDrop: PropTypes.func.isRequired, + onDrop: () => void; }; - -function ReportDropUI({onDrop}) { +function ReportDropUI({onDrop}: ReportDropUIProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); return ( @@ -33,6 +31,5 @@ function ReportDropUI({onDrop}) { } ReportDropUI.displayName = 'ReportDropUI'; -ReportDropUI.propTypes = propTypes; export default ReportDropUI; diff --git a/src/pages/home/report/ReportTypingIndicator.tsx b/src/pages/home/report/ReportTypingIndicator.tsx index f7f135e7374e..f62db8bf0337 100755 --- a/src/pages/home/report/ReportTypingIndicator.tsx +++ b/src/pages/home/report/ReportTypingIndicator.tsx @@ -16,7 +16,7 @@ type ReportTypingIndicatorOnyxProps = { }; type ReportTypingIndicatorProps = { - // eslint-disable-next-line react/no-unused-prop-types + // eslint-disable-next-line react/no-unused-prop-types -- This is used by withOnyx reportID: string; } & ReportTypingIndicatorOnyxProps; diff --git a/src/types/onyx/IOU.ts b/src/types/onyx/IOU.ts index a89b0d4530ef..220af7005c45 100644 --- a/src/types/onyx/IOU.ts +++ b/src/types/onyx/IOU.ts @@ -23,3 +23,5 @@ type IOU = { }; export default IOU; + +export type {Participant}; From 63a63ad6df7a87ceeb99de66e8316200d30721cf Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 25 Jan 2024 09:36:42 +0100 Subject: [PATCH 035/202] fix: typecheck --- src/components/LocaleContextProvider.tsx | 2 +- src/pages/home/report/ParticipantLocalTime.tsx | 12 +++++------- src/pages/home/report/ReportDropUI.tsx | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/components/LocaleContextProvider.tsx b/src/components/LocaleContextProvider.tsx index 7313bb4aa7bb..25b468181b87 100644 --- a/src/components/LocaleContextProvider.tsx +++ b/src/components/LocaleContextProvider.tsx @@ -132,4 +132,4 @@ Provider.displayName = 'withOnyx(LocaleContextProvider)'; export {Provider as LocaleContextProvider, LocaleContext}; -export type {LocaleContextProps}; +export type {LocaleContextProps, Locale}; diff --git a/src/pages/home/report/ParticipantLocalTime.tsx b/src/pages/home/report/ParticipantLocalTime.tsx index c8bbaf031e32..5d90659fb96a 100644 --- a/src/pages/home/report/ParticipantLocalTime.tsx +++ b/src/pages/home/report/ParticipantLocalTime.tsx @@ -5,24 +5,22 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import DateUtils from '@libs/DateUtils'; import Timers from '@libs/Timers'; +import type {Locale} from '@src/components/LocaleContextProvider'; import CONST from '@src/CONST'; import type {PersonalDetails} from '@src/types/onyx'; -import type DeepValueOf from '@src/types/utils/DeepValueOf'; - -type Locales = DeepValueOf; type ParticipantLocalTimeProps = { /** Personal details of the participant */ participant: PersonalDetails; - preferredLocale: Locales; + preferredLocale?: Locale; }; -function getParticipantLocalTime(participant: PersonalDetails, preferredLocale: Locales) { +function getParticipantLocalTime(participant: PersonalDetails, preferredLocale: Locale | undefined) { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const reportRecipientTimezone = participant.timezone || CONST.DEFAULT_TIME_ZONE; - const reportTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale, undefined, reportRecipientTimezone.selected); - const currentTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale); + const reportTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale ?? CONST.LOCALES.DEFAULT, undefined, reportRecipientTimezone.selected); + const currentTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale ?? CONST.LOCALES.DEFAULT); const reportRecipientDay = DateUtils.formatToDayOfWeek(reportTimezone.toDateString()); const currentUserDay = DateUtils.formatToDayOfWeek(currentTimezone.toDateString()); if (reportRecipientDay !== currentUserDay) { diff --git a/src/pages/home/report/ReportDropUI.tsx b/src/pages/home/report/ReportDropUI.tsx index d147d0c0c03d..fad58d60bbfa 100644 --- a/src/pages/home/report/ReportDropUI.tsx +++ b/src/pages/home/report/ReportDropUI.tsx @@ -9,7 +9,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; type ReportDropUIProps = { /** Callback to execute when a file is dropped. */ - onDrop: () => void; + onDrop: (event: DragEvent) => void; }; function ReportDropUI({onDrop}: ReportDropUIProps) { const styles = useThemeStyles(); From 1225d237f1123cb89b8e29cdc36a022042e1ad1e Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 25 Jan 2024 13:47:27 +0100 Subject: [PATCH 036/202] fix: minor fixes --- src/pages/home/report/ParticipantLocalTime.tsx | 5 +++-- .../ComposerWithSuggestions/ComposerWithSuggestions.tsx | 2 +- src/pages/home/report/ReportActionCompose/SendButton.tsx | 3 ++- .../home/report/ReportActionCompose/SuggestionMention.tsx | 6 ++++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/pages/home/report/ParticipantLocalTime.tsx b/src/pages/home/report/ParticipantLocalTime.tsx index 5d90659fb96a..e97fad8f20f0 100644 --- a/src/pages/home/report/ParticipantLocalTime.tsx +++ b/src/pages/home/report/ParticipantLocalTime.tsx @@ -13,11 +13,12 @@ type ParticipantLocalTimeProps = { /** Personal details of the participant */ participant: PersonalDetails; + /** The user's preferred locale e.g. 'en', 'es-ES' */ preferredLocale?: Locale; }; function getParticipantLocalTime(participant: PersonalDetails, preferredLocale: Locale | undefined) { - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null const reportRecipientTimezone = participant.timezone || CONST.DEFAULT_TIME_ZONE; const reportTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale ?? CONST.LOCALES.DEFAULT, undefined, reportRecipientTimezone.selected); const currentTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale ?? CONST.LOCALES.DEFAULT); @@ -45,7 +46,7 @@ function ParticipantLocalTime({participant, preferredLocale}: ParticipantLocalTi }; }, [participant, preferredLocale]); - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null const reportRecipientDisplayName = participant.firstName || participant.displayName; if (!reportRecipientDisplayName) { diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index 8c09f53d3b27..96d2e1a26f6b 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -209,7 +209,7 @@ function ComposerWithSuggestions( const syncSelectionWithOnChangeTextRef = useRef(null); - const suggestions = suggestionsRef.current?.getSuggestions(); + const suggestions = suggestionsRef.current?.getSuggestions() ?? (() => []); const hasEnoughSpaceForLargeSuggestion = SuggestionUtils.hasEnoughSpaceForLargeSuggestionMenu(listHeight, composerHeight, suggestions?.length ?? 0); diff --git a/src/pages/home/report/ReportActionCompose/SendButton.tsx b/src/pages/home/report/ReportActionCompose/SendButton.tsx index b6c6200fc7c0..453ee9310f46 100644 --- a/src/pages/home/report/ReportActionCompose/SendButton.tsx +++ b/src/pages/home/report/ReportActionCompose/SendButton.tsx @@ -24,7 +24,8 @@ function SendButton({isDisabled: isDisabledProp, handleSendMessage}: SendButtonP const {translate} = useLocalize(); const Tap = Gesture.Tap() - .enabled(!isDisabledProp) + // @ts-expect-error Enabled require argument but when passing something button is not working + .enabled() .onEnd(() => { handleSendMessage(); }); diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index d5a3a8983467..02bcd27093e7 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -145,8 +145,10 @@ function SuggestionMention( }); const sortedPersonalDetails = filteredPersonalDetails.sort((a, b) => { - const nameA = a?.displayName ?? a?.login ?? ''; - const nameB = b?.displayName ?? b?.login ?? ''; + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null + const nameA = a?.displayName || a?.login || ''; + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null + const nameB = b?.displayName || b?.login || ''; if (nameA < nameB) { return -1; From 4f907d25135d3bdc12e7a5b7971e1d71c69b558a Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 25 Jan 2024 13:55:20 +0100 Subject: [PATCH 037/202] fix: removed unused export --- src/types/onyx/IOU.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/types/onyx/IOU.ts b/src/types/onyx/IOU.ts index 220af7005c45..a89b0d4530ef 100644 --- a/src/types/onyx/IOU.ts +++ b/src/types/onyx/IOU.ts @@ -23,5 +23,3 @@ type IOU = { }; export default IOU; - -export type {Participant}; From 6981075dff4b466e784ee280878d6b39eb35a1c4 Mon Sep 17 00:00:00 2001 From: tienifr Date: Fri, 26 Jan 2024 16:07:20 +0700 Subject: [PATCH 038/202] resolve comments --- src/libs/actions/CachedPDFPaths.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libs/actions/CachedPDFPaths.ts b/src/libs/actions/CachedPDFPaths.ts index 28626dc34856..4eefb9a7982e 100644 --- a/src/libs/actions/CachedPDFPaths.ts +++ b/src/libs/actions/CachedPDFPaths.ts @@ -2,6 +2,10 @@ import {exists, unlink} from 'react-native-fs'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; +/* + * We need to save the paths of PDF files so we can delete them later. + * This is to remove the cached PDFs when an attachment is deleted or the user logs out. + */ let pdfPaths: Record = {}; Onyx.connect({ key: ONYXKEYS.CACHED_PDF_PATHS, @@ -11,6 +15,9 @@ Onyx.connect({ }); function add(reportActionID: string, path: string): Promise { + if (pdfPaths[reportActionID]) { + return Promise.resolve(); + } return Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {[reportActionID]: path}); } From 5c5b0ab9df2e4193c11e9218de31ce087c894360 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 29 Jan 2024 11:07:00 +0700 Subject: [PATCH 039/202] change params order --- src/libs/actions/IOU.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 2de0ccef71b0..4b90d5fd33d4 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -377,7 +377,7 @@ function buildOnyxDataForMoneyRequest( needsToBeManuallySubmitted = true, ) { const isScanRequest = TransactionUtils.isScanRequest(transaction); - const outstandingChildRequest = getOutstandingChildRequest(needsToBeManuallySubmitted, policy, iouReport); + const outstandingChildRequest = getOutstandingChildRequest(policy, iouReport, needsToBeManuallySubmitted); const optimisticData = [ { // Use SET for new reports because it doesn't exist yet, is faster and we need the data to be available when we navigate to the chat page From 0229c977b32f2f6b1c054098ae8cb8308ce470bd Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 30 Jan 2024 10:52:31 +0700 Subject: [PATCH 040/202] fix conflict main --- src/pages/ProfilePage.js | 47 ++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 590a4635f9e5..f20055190e3e 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -5,7 +5,6 @@ import React, {useEffect} from 'react'; import {ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; -import AttachmentModal from '@components/AttachmentModal'; import AutoUpdateTime from '@components/AutoUpdateTime'; import Avatar from '@components/Avatar'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; @@ -101,7 +100,6 @@ function ProfilePage(props) { const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(details); const avatar = lodashGet(details, 'avatar', UserUtils.getDefaultAvatar()); const fallbackIcon = lodashGet(details, 'fallbackIcon', ''); - const originalFileName = lodashGet(details, 'originalFileName', ''); const login = lodashGet(details, 'login', ''); const timezone = lodashGet(details, 'timezone', {}); @@ -122,6 +120,9 @@ function ProfilePage(props) { const hasMinimumDetails = !_.isEmpty(details.avatar); const isLoading = lodashGet(details, 'isLoading', false) || _.isEmpty(details); + // If the API returns an error for some reason there won't be any details and isLoading will get set to false, so we want to show a blocking screen + const shouldShowBlockingView = !hasMinimumDetails && !isLoading; + const statusEmojiCode = lodashGet(details, 'status.emojiCode', ''); const statusText = lodashGet(details, 'status.text', ''); const hasStatus = !!statusEmojiCode; @@ -141,7 +142,7 @@ function ProfilePage(props) { return ( - + Navigation.goBack(navigateBackTo)} @@ -150,32 +151,22 @@ function ProfilePage(props) { {hasMinimumDetails && ( - Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(String(accountID)))} + accessibilityLabel={props.translate('common.profile')} + accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON} > - {({show}) => ( - - - - - - )} - + + + + {Boolean(displayName) && ( Date: Tue, 30 Jan 2024 10:57:10 +0100 Subject: [PATCH 041/202] fix: typecheck --- .../MoneyRequestConfirmationList.tsx | 39 ++++++++++++++----- src/libs/OptionsListUtils.ts | 19 +++++++-- src/types/onyx/index.ts | 3 +- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 3712e928a5e1..3a6dd5964741 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -28,7 +28,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; -import type {PaymentType} from '@src/types/onyx/OriginalMessage'; +import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type {MileageRate} from '@src/types/onyx/Policy'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; import ConfirmedRoute from './ConfirmedRoute'; @@ -36,6 +36,7 @@ import FormHelpMessage from './FormHelpMessage'; import Image from './Image'; import MenuItemWithTopDescription from './MenuItemWithTopDescription'; import OptionsSelector from './OptionsSelector'; +import ReceiptEmptyState from './ReceiptEmptyState'; import SettlementButton from './SettlementButton'; import ShowMoreButton from './ShowMoreButton'; import Switch from './Switch'; @@ -78,7 +79,7 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & onConfirm?: (selectedParticipants: Participant[]) => void; /** Callback to parent modal to send money */ - onSendMoney?: (paymentMethod: PaymentType) => void; + onSendMoney?: (paymentMethod: PaymentMethodType) => void; /** Callback to inform a participant is selected */ onSelectParticipant?: (option: Participant) => void; @@ -232,7 +233,7 @@ function MoneyRequestConfirmationList({ const shouldCalculateDistanceAmount = isDistanceRequest && iouAmount === 0; // A flag for showing the categories field - const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories ?? {}))); + const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(policyCategories ?? {})); // A flag and a toggler for showing the rest of the form fields const [shouldExpandFields, toggleShouldExpandFields] = useReducer((state) => !state, false); @@ -249,7 +250,7 @@ function MoneyRequestConfirmationList({ const policyTagList = policyTag?.tags ?? {}; const policyTagListName = policyTag?.name ?? translate('common.tag'); // A flag for showing the tags field - const shouldShowTags = isPolicyExpenseChat && (iouTag || OptionsListUtils.hasEnabledOptions(Object.values(policyTagList))); + const shouldShowTags = isPolicyExpenseChat && (iouTag || OptionsListUtils.hasEnabledOptions(policyTagList)); // A flag for showing tax fields - tax rate and tax amount const shouldShowTax = isPolicyExpenseChat && policy?.isTaxTrackingEnabled; @@ -322,8 +323,7 @@ function MoneyRequestConfirmationList({ return OptionsListUtils.getIOUConfirmationOptionsFromParticipants( participantsList, calculatedIouAmount > 0 ? CurrencyUtils.convertToDisplayString(calculatedIouAmount, iouCurrencyCode) : '', - // TODO: Remove the assertion once OptionsListUtils (https://github.com/Expensify/App/issues/24921) is migrated to TypeScript. - ) as Participant[]; + ); }, [iouAmount, iouCurrencyCode], ); @@ -467,7 +467,7 @@ function MoneyRequestConfirmationList({ }; const confirm = useCallback( - (paymentMethod: PaymentType) => { + (paymentMethod: PaymentMethodType) => { if (selectedParticipantsMemo.length === 0) { return; } @@ -552,7 +552,7 @@ function MoneyRequestConfirmationList({ pressOnEnter isDisabled={shouldDisableButton} // eslint-disable-next-line @typescript-eslint/naming-convention - onPress={(_, value) => confirm(value as PaymentType)} + onPress={(_, value) => confirm(value as PaymentMethodType)} options={splitOrRequestOptions} buttonSize={CONST.DROPDOWN_BUTTON_SIZE.LARGE} /> @@ -612,7 +612,7 @@ function MoneyRequestConfirmationList({ )} - {(receiptData.image || receiptData.thumbnail) && ( + {receiptData.image || receiptData.thumbnail ? ( + ) : ( + // The empty receipt component should only show for IOU Requests of a paid policy ("Team" or "Corporate") + PolicyUtils.isPaidGroupPolicy(policy) && + !isDistanceRequest && + iouType === CONST.IOU.TYPE.REQUEST && ( + + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_SCAN.getRoute( + CONST.IOU.ACTION.CREATE, + iouType, + transaction?.transactionID ?? '', + reportID, + Navigation.getActiveRouteWithoutParams(), + ), + ) + } + /> + ) )} {shouldShowSmartScanFields && ( { diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 812ebb051624..a1714629c21c 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -10,7 +10,20 @@ import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Beta, Login, PersonalDetails, PersonalDetailsList, Policy, PolicyCategories, Report, ReportAction, ReportActions, Transaction, TransactionViolation} from '@src/types/onyx'; +import type { + Beta, + Login, + PersonalDetails, + PersonalDetailsList, + Policy, + PolicyCategories, + PolicyTags, + Report, + ReportAction, + ReportActions, + Transaction, + TransactionViolation, +} from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {PolicyTaxRate, PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates'; @@ -768,7 +781,7 @@ function getEnabledCategoriesCount(options: PolicyCategories): number { /** * Verifies that there is at least one enabled option */ -function hasEnabledOptions(options: PolicyCategories): boolean { +function hasEnabledOptions(options: PolicyCategories | PolicyTags): boolean { return Object.values(options).some((option) => option.enabled); } @@ -1699,7 +1712,7 @@ function getSearchOptions(reports: Record, personalDetails: Onyx /** * Build the IOUConfirmation options for showing the payee personalDetail */ -function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail: PersonalDetails, amountText: string): PayeePersonalDetails { +function getIOUConfirmationOptionsFromPayeePersonalDetail(personalDetail: PersonalDetails | EmptyObject, amountText: string): PayeePersonalDetails { const formattedLogin = LocalePhoneNumber.formatPhoneNumber(personalDetail.login ?? ''); return { text: PersonalDetailsUtils.getDisplayNameOrDefault(personalDetail, formattedLogin), diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 011242b2ba38..81bca425f78e 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -33,8 +33,7 @@ import type {PolicyMembers} from './PolicyMember'; import type PolicyMember from './PolicyMember'; import type {PolicyReportField, PolicyReportFields} from './PolicyReportField'; import type {PolicyTag, PolicyTags} from './PolicyTag'; -import type {PolicyTaxRates} from './PolicyTaxRates'; -import type PolicyTaxRate from './PolicyTaxRates'; +import type {PolicyTaxRate, PolicyTaxRates} from './PolicyTaxRates'; import type PrivatePersonalDetails from './PrivatePersonalDetails'; import type RecentlyUsedCategories from './RecentlyUsedCategories'; import type RecentlyUsedReportFields from './RecentlyUsedReportFields'; From 2c030a3d49b2fe430e61eeb4461567db56353575 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 30 Jan 2024 11:02:40 +0100 Subject: [PATCH 042/202] fix: remove unnecessary default values --- src/components/MoneyRequestConfirmationList.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 3a6dd5964741..74ac5e878395 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -187,12 +187,12 @@ function MoneyRequestConfirmationList({ payeePersonalDetails, canModifyParticipants = false, isReadOnly = false, - bankAccountRoute = '', - policyID = '', - reportID = '', - receiptPath = '', - receiptFilename = '', - transactionID = '', + bankAccountRoute, + policyID, + reportID, + receiptPath, + receiptFilename, + transactionID, mileageRate, isDistanceRequest = false, isScanRequest = false, From efa41789b32f559b5618d316be79d8b1398e53e4 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 30 Jan 2024 11:16:15 +0100 Subject: [PATCH 043/202] fix: typecheck --- src/libs/ComposerUtils/index.ts | 4 ++-- src/libs/EmojiUtils.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/ComposerUtils/index.ts b/src/libs/ComposerUtils/index.ts index 94bba5d0d00c..de937c0ba915 100644 --- a/src/libs/ComposerUtils/index.ts +++ b/src/libs/ComposerUtils/index.ts @@ -18,8 +18,8 @@ function insertText(text: string, selection: Selection, textToInsert: string): s * Insert a white space at given index of text * @param text - text that needs whitespace to be appended to */ -function insertWhiteSpaceAtIndex(text: string, index: number) { - return `${text.slice(0, index)} ${text.slice(index)}`; +function insertWhiteSpaceAtIndex(text: string | null, index: number) { + return `${text?.slice(0, index)} ${text?.slice(index)}`; } /** diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index 7971e6147c19..ecbed9c87eff 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -370,7 +370,7 @@ function replaceEmojis(text: string, preferredSkinTone: number = CONST.EMOJI_DEF /** * Find all emojis in a text and replace them with their code. */ -function replaceAndExtractEmojis(text: string, preferredSkinTone: number = CONST.EMOJI_DEFAULT_SKIN_TONE, lang: Locale = CONST.LOCALES.DEFAULT): ReplacedEmoji { +function replaceAndExtractEmojis(text: string | null, preferredSkinTone: number = CONST.EMOJI_DEFAULT_SKIN_TONE, lang: Locale = CONST.LOCALES.DEFAULT): ReplacedEmoji { const {text: convertedText = '', emojis = [], cursorPosition} = replaceEmojis(text, preferredSkinTone, lang); return { From 99a4110c3e4dde03061ee0872b51949b4caec0f8 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 30 Jan 2024 11:58:11 +0100 Subject: [PATCH 044/202] fix: typecheck --- src/libs/E2E/tests/chatOpeningTest.e2e.ts | 3 ++- src/libs/E2E/tests/reportTypingTest.e2e.ts | 3 ++- src/libs/E2E/types.ts | 2 +- src/libs/EmojiUtils.ts | 4 ++-- .../ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx | 3 ++- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/libs/E2E/tests/chatOpeningTest.e2e.ts b/src/libs/E2E/tests/chatOpeningTest.e2e.ts index ef380f847c3f..2e2ce76b348d 100644 --- a/src/libs/E2E/tests/chatOpeningTest.e2e.ts +++ b/src/libs/E2E/tests/chatOpeningTest.e2e.ts @@ -1,3 +1,4 @@ +import type {NativeConfig} from 'react-native-config'; import E2ELogin from '@libs/E2E/actions/e2eLogin'; import waitForAppLoaded from '@libs/E2E/actions/waitForAppLoaded'; import E2EClient from '@libs/E2E/client'; @@ -12,7 +13,7 @@ const test = (config: TestConfig) => { // check for login (if already logged in the action will simply resolve) console.debug('[E2E] Logging in for chat opening'); - const reportID = getConfigValueOrThrow('reportID', config); + const reportID = getConfigValueOrThrow('reportID', config as NativeConfig); E2ELogin().then((neededLogin) => { if (neededLogin) { diff --git a/src/libs/E2E/tests/reportTypingTest.e2e.ts b/src/libs/E2E/tests/reportTypingTest.e2e.ts index 4e0678aeb020..17464f7eb8d6 100644 --- a/src/libs/E2E/tests/reportTypingTest.e2e.ts +++ b/src/libs/E2E/tests/reportTypingTest.e2e.ts @@ -1,3 +1,4 @@ +import type {NativeConfig} from 'react-native-config'; import Config from 'react-native-config'; import E2ELogin from '@libs/E2E/actions/e2eLogin'; import waitForAppLoaded from '@libs/E2E/actions/waitForAppLoaded'; @@ -16,7 +17,7 @@ const test = (config: TestConfig) => { // check for login (if already logged in the action will simply resolve) console.debug('[E2E] Logging in for typing'); - const reportID = getConfigValueOrThrow('reportID', config); + const reportID = getConfigValueOrThrow('reportID', config as NativeConfig); E2ELogin().then((neededLogin) => { if (neededLogin) { diff --git a/src/libs/E2E/types.ts b/src/libs/E2E/types.ts index 2d48813fa115..93640fbb4ce8 100644 --- a/src/libs/E2E/types.ts +++ b/src/libs/E2E/types.ts @@ -20,7 +20,7 @@ type NetworkCacheMap = Record< type TestConfig = { name: string; - [key: string]: string; + [key: string]: string | {autoFocus: boolean}; }; export type {SigninParams, IsE2ETestSession, NetworkCacheMap, NetworkCacheEntry, TestConfig}; diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index ecbed9c87eff..12319e342fb8 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -371,11 +371,11 @@ function replaceEmojis(text: string, preferredSkinTone: number = CONST.EMOJI_DEF * Find all emojis in a text and replace them with their code. */ function replaceAndExtractEmojis(text: string | null, preferredSkinTone: number = CONST.EMOJI_DEFAULT_SKIN_TONE, lang: Locale = CONST.LOCALES.DEFAULT): ReplacedEmoji { - const {text: convertedText = '', emojis = [], cursorPosition} = replaceEmojis(text, preferredSkinTone, lang); + const {text: convertedText = '', emojis = [], cursorPosition} = replaceEmojis(text ?? '', preferredSkinTone, lang); return { text: convertedText, - emojis: emojis.concat(extractEmojis(text)), + emojis: emojis.concat(extractEmojis(text ?? '')), cursorPosition, }; } diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx index 87352981ba9a..94e65a48e46b 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx @@ -19,7 +19,8 @@ function IncrementRenderCount() { function ComposerWithSuggestionsE2e(props: ComposerWithSuggestionsProps, ref: ForwardedRef) { // Eventually Auto focus on e2e tests useEffect(() => { - if ((E2EClient.getCurrentActiveTestConfig()?.reportScreen?.autoFocus ?? false) === false) { + const testConfig = E2EClient.getCurrentActiveTestConfig(); + if (testConfig?.reportScreen && typeof testConfig.reportScreen !== 'string' && (testConfig?.reportScreen.autoFocus ?? false) === false) { return; } From b037ab91daadf1b1dcb610f942f7ab385d4f499e Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 30 Jan 2024 13:38:04 +0100 Subject: [PATCH 045/202] fix: typecheck --- .../MoneyRequestConfirmationList.tsx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 74ac5e878395..933d604fd3cb 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -337,7 +337,7 @@ function MoneyRequestConfirmationList({ let text; if (isSplitBill && iouAmount === 0) { text = translate('iou.split'); - } else if ((receiptPath && isTypeRequest) || isDistanceRequestWithoutRoute) { + } else if (!!(receiptPath && isTypeRequest) || isDistanceRequestWithoutRoute) { text = translate('iou.request'); if (iouAmount !== 0) { text = translate('iou.requestAmount', {amount: Number(formattedAmount)}); @@ -439,7 +439,7 @@ function MoneyRequestConfirmationList({ translate, toLocaleDigit, ); - IOU.setMoneyRequestMerchant_temporaryForRefactor(transactionID, distanceMerchant); + IOU.setMoneyRequestMerchant_temporaryForRefactor(transactionID ?? '', distanceMerchant); }, [hasRoute, distance, mileageRate?.unit, mileageRate?.rate, mileageRate?.currency, translate, toLocaleDigit, isDistanceRequest, transactionID]); const selectParticipant = useCallback( @@ -633,7 +633,7 @@ function MoneyRequestConfirmationList({ CONST.IOU.ACTION.CREATE, iouType, transaction?.transactionID ?? '', - reportID, + reportID ?? '', Navigation.getActiveRouteWithoutParams(), ), ) @@ -652,7 +652,7 @@ function MoneyRequestConfirmationList({ return; } if (isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.AMOUNT)); + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID ?? '', reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.AMOUNT)); return; } Navigation.navigate(ROUTES.MONEY_REQUEST_AMOUNT.getRoute(iouType, reportID)); @@ -671,7 +671,7 @@ function MoneyRequestConfirmationList({ description={translate('common.description')} onPress={() => { if (isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.DESCRIPTION)); + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID ?? '', reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.DESCRIPTION)); return; } Navigation.navigate(ROUTES.MONEY_REQUEST_DESCRIPTION.getRoute(iouType, reportID)); @@ -700,7 +700,7 @@ function MoneyRequestConfirmationList({ titleStyle={styles.flex1} onPress={() => { if (isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.DATE)); + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID ?? '', reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.DATE)); return; } Navigation.navigate(ROUTES.MONEY_REQUEST_DATE.getRoute(iouType, reportID)); @@ -732,7 +732,7 @@ function MoneyRequestConfirmationList({ titleStyle={styles.flex1} onPress={() => { if (isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.MERCHANT)); + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID ?? '', reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.MERCHANT)); return; } Navigation.navigate(ROUTES.MONEY_REQUEST_MERCHANT.getRoute(iouType, reportID)); @@ -755,7 +755,7 @@ function MoneyRequestConfirmationList({ numberOfLinesTitle={2} onPress={() => { if (isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.CATEGORY)); + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID ?? '', reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.CATEGORY)); return; } Navigation.navigate(ROUTES.MONEY_REQUEST_CATEGORY.getRoute(iouType, reportID)); @@ -775,7 +775,7 @@ function MoneyRequestConfirmationList({ numberOfLinesTitle={2} onPress={() => { if (isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID, reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.TAG)); + Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID ?? '', reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.TAG)); return; } Navigation.navigate(ROUTES.MONEY_REQUEST_TAG.getRoute(iouType, reportID)); @@ -796,7 +796,7 @@ function MoneyRequestConfirmationList({ titleStyle={styles.flex1} onPress={() => Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams()), + ROUTES.MONEY_REQUEST_STEP_TAX_RATE.getRoute(iouType, transaction?.transactionID ?? '', reportID ?? '', Navigation.getActiveRouteWithoutParams()), ) } disabled={didConfirm} @@ -813,7 +813,7 @@ function MoneyRequestConfirmationList({ titleStyle={styles.flex1} onPress={() => Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(iouType, transaction?.transactionID ?? '', reportID, Navigation.getActiveRouteWithoutParams()), + ROUTES.MONEY_REQUEST_STEP_TAX_AMOUNT.getRoute(iouType, transaction?.transactionID ?? '', reportID ?? '', Navigation.getActiveRouteWithoutParams()), ) } disabled={didConfirm} From 7beb521641b51f81a43fdf069cda2355c0d64aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Tue, 30 Jan 2024 15:24:27 +0100 Subject: [PATCH 046/202] added isLoadingNewOptions prop to BaseSelectionList --- src/components/SelectionList/BaseSelectionList.tsx | 2 ++ src/components/SelectionList/types.ts | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 815b80aaa50e..086ead66f820 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -58,6 +58,7 @@ function BaseSelectionList( shouldShowTooltips = true, shouldUseDynamicMaxToRenderPerBatch = false, rightHandSideComponent, + isLoadingNewOptions = false, }: BaseSelectionListProps, inputRef: ForwardedRef, ) { @@ -417,6 +418,7 @@ function BaseSelectionList( spellCheck={false} onSubmitEditing={selectFocusedOption} blurOnSubmit={!!flattenedSections.allOptions.length} + isLoading={isLoadingNewOptions} /> )} diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index a82ddef6febb..222c818dd66d 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -230,6 +230,9 @@ type BaseSelectionListProps = Partial ReactElement) | ReactElement | null; + + /** Whether to show the loading indicator for new options */ + isLoadingNewOptions?: boolean; }; type ItemLayout = { From 4c45c2ab3b4e0e5fda321427fac9d302eec41015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Tue, 30 Jan 2024 15:24:35 +0100 Subject: [PATCH 047/202] component refactor --- .../TaskShareDestinationSelectorModal.js | 181 ++++++------------ 1 file changed, 60 insertions(+), 121 deletions(-) diff --git a/src/pages/tasks/TaskShareDestinationSelectorModal.js b/src/pages/tasks/TaskShareDestinationSelectorModal.js index 64fd5f50b61f..8d3051b0669f 100644 --- a/src/pages/tasks/TaskShareDestinationSelectorModal.js +++ b/src/pages/tasks/TaskShareDestinationSelectorModal.js @@ -1,22 +1,20 @@ -/* eslint-disable es/no-optional-chaining */ +import keys from 'lodash/keys'; +import reduce from 'lodash/reduce'; import PropTypes from 'prop-types'; -import React, {useCallback, useEffect, useMemo, useState} from 'react'; +import React, {useEffect, useMemo} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import OptionsSelector from '@components/OptionsSelector'; +import {usePersonalDetails} from '@components/OnyxProvider'; import ScreenWrapper from '@components/ScreenWrapper'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; -import useAutoFocusInput from '@hooks/useAutoFocusInput'; -import useNetwork from '@hooks/useNetwork'; +import SelectionList from '@components/SelectionList'; +import useDebouncedState from '@hooks/useDebouncedState'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Report from '@libs/actions/Report'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportUtils from '@libs/ReportUtils'; -import personalDetailsPropType from '@pages/personalDetailsPropType'; import reportPropTypes from '@pages/reportPropTypes'; import * as Task from '@userActions/Task'; import CONST from '@src/CONST'; @@ -24,131 +22,82 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; const propTypes = { - /* Onyx Props */ - - /** Beta features list */ - betas: PropTypes.arrayOf(PropTypes.string), - - /** All of the personal details for everyone */ - personalDetails: PropTypes.objectOf(personalDetailsPropType), - /** All reports shared with the user */ reports: PropTypes.objectOf(reportPropTypes), - - /** Whether we are searching for reports in the server */ + /** Whether or not we are searching for reports on the server */ isSearchingForReports: PropTypes.bool, - - ...withLocalizePropTypes, }; const defaultProps = { - betas: [], - personalDetails: {}, reports: {}, isSearchingForReports: false, }; -function TaskShareDestinationSelectorModal(props) { - const styles = useThemeStyles(); - const [searchValue, setSearchValue] = useState(''); - const [headerMessage, setHeaderMessage] = useState(''); - const [filteredRecentReports, setFilteredRecentReports] = useState([]); +const selectReportHandler = (option) => { + if (!option || !option.reportID) { + return; + } - const {inputCallbackRef} = useAutoFocusInput(); - const {isSearchingForReports} = props; - const {isOffline} = useNetwork(); + Task.setShareDestinationValue(option.reportID); + Navigation.goBack(ROUTES.NEW_TASK); +}; - const filteredReports = useMemo(() => { - const reports = {}; - _.keys(props.reports).forEach((reportKey) => { - if ( - !ReportUtils.canUserPerformWriteAction(props.reports[reportKey]) || - !ReportUtils.canCreateTaskInReport(props.reports[reportKey]) || - ReportUtils.isCanceledTaskReport(props.reports[reportKey]) - ) { - return; +const reportFilter = (reports) => + reduce( + keys(reports), + (filtered, reportKey) => { + const report = reports[reportKey]; + if (ReportUtils.canUserPerformWriteAction(report) && ReportUtils.canCreateTaskInReport(report) && !ReportUtils.isCanceledTaskReport(report)) { + return {...filtered, [reportKey]: report}; } - reports[reportKey] = props.reports[reportKey]; - }); - return reports; - }, [props.reports]); - const updateOptions = useCallback(() => { - const {recentReports} = OptionsListUtils.getShareDestinationOptions(filteredReports, props.personalDetails, props.betas, searchValue.trim(), [], CONST.EXPENSIFY_EMAILS, true); - - setHeaderMessage(OptionsListUtils.getHeaderMessage(recentReports?.length !== 0, false, searchValue)); - - setFilteredRecentReports(recentReports); - }, [props, searchValue, filteredReports]); - - useEffect(() => { - const debouncedSearch = _.debounce(updateOptions, 150); - debouncedSearch(); - return () => { - debouncedSearch.cancel(); - }; - }, [updateOptions]); + return filtered; + }, + {}, + ); - const getSections = () => { - const sections = []; - let indexOffset = 0; +function TaskShareDestinationSelectorModal({reports, isSearchingForReports}) { + const styles = useThemeStyles(); + const [searchValue, debouncedSearchValue, setSearchValue] = useDebouncedState(''); + const {translate} = useLocalize(); + const personalDetails = usePersonalDetails(); - if (filteredRecentReports?.length > 0) { - sections.push({ - data: filteredRecentReports, - shouldShow: true, - indexOffset, - }); - indexOffset += filteredRecentReports?.length; - } + const options = useMemo(() => { + const filteredReports = reportFilter(reports); - return sections; - }; + const {recentReports} = OptionsListUtils.getShareDestinationOptions(filteredReports, personalDetails, [], debouncedSearchValue.trim(), [], CONST.EXPENSIFY_EMAILS, true); - const selectReport = (option) => { - if (!option) { - return; - } + const headerMessage = OptionsListUtils.getHeaderMessage(recentReports && recentReports.length !== 0, false, debouncedSearchValue); - if (option.reportID) { - Task.setShareDestinationValue(option.reportID); - Navigation.goBack(ROUTES.NEW_TASK); - } - }; + const sections = recentReports && recentReports.length > 0 ? [{data: recentReports, shouldShow: true}] : []; - // When search term updates we will fetch any reports - const setSearchTermAndSearchInServer = useCallback((text = '') => { - Report.searchInServer(text); - setSearchValue(text); - }, []); + return {sections, headerMessage}; + }, [personalDetails, reports, debouncedSearchValue]); - const sections = getSections(); + useEffect(() => { + Report.searchInServer(debouncedSearchValue); + }, [debouncedSearchValue]); return ( {({didScreenTransitionEnd, safeAreaPaddingBottomStyle}) => ( <> Navigation.goBack(ROUTES.NEW_TASK)} /> - @@ -158,25 +107,15 @@ function TaskShareDestinationSelectorModal(props) { ); } -TaskShareDestinationSelectorModal.displayName = 'TaskShareDestinationSelectorModal'; TaskShareDestinationSelectorModal.propTypes = propTypes; TaskShareDestinationSelectorModal.defaultProps = defaultProps; -export default compose( - withLocalize, - withOnyx({ - reports: { - key: ONYXKEYS.COLLECTION.REPORT, - }, - personalDetails: { - key: ONYXKEYS.PERSONAL_DETAILS_LIST, - }, - betas: { - key: ONYXKEYS.BETAS, - }, - isSearchingForReports: { - key: ONYXKEYS.IS_SEARCHING_FOR_REPORTS, - initWithStoredValues: false, - }, - }), -)(TaskShareDestinationSelectorModal); +export default withOnyx({ + reports: { + key: ONYXKEYS.COLLECTION.REPORT, + }, + isSearchingForReports: { + key: ONYXKEYS.IS_SEARCHING_FOR_REPORTS, + initWithStoredValues: false, + }, +})(TaskShareDestinationSelectorModal); From a01ada256ab16612293d94027c7d01519af183ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Wed, 31 Jan 2024 13:46:32 +0100 Subject: [PATCH 048/202] brought back displayName --- src/pages/tasks/TaskShareDestinationSelectorModal.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/tasks/TaskShareDestinationSelectorModal.js b/src/pages/tasks/TaskShareDestinationSelectorModal.js index 8d3051b0669f..b609ce02af86 100644 --- a/src/pages/tasks/TaskShareDestinationSelectorModal.js +++ b/src/pages/tasks/TaskShareDestinationSelectorModal.js @@ -107,6 +107,7 @@ function TaskShareDestinationSelectorModal({reports, isSearchingForReports}) { ); } +TaskShareDestinationSelectorModal.displayName = 'TaskShareDestinationSelectorModal'; TaskShareDestinationSelectorModal.propTypes = propTypes; TaskShareDestinationSelectorModal.defaultProps = defaultProps; From 086a705a923bbffe7e4960b7335d8aff588ce2be Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Fri, 2 Feb 2024 10:52:24 +0700 Subject: [PATCH 049/202] resolve conflict --- src/pages/ProfilePage.js | 45 ++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index f20055190e3e..16ace231eceb 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -5,6 +5,7 @@ import React, {useEffect} from 'react'; import {ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; +import AttachmentModal from '@components/AttachmentModal'; import AutoUpdateTime from '@components/AutoUpdateTime'; import Avatar from '@components/Avatar'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; @@ -103,6 +104,8 @@ function ProfilePage(props) { const login = lodashGet(details, 'login', ''); const timezone = lodashGet(details, 'timezone', {}); + const originalFileName = lodashGet(details, 'originalFileName', ''); + // If we have a reportID param this means that we // arrived here via the ParticipantsPage and should be allowed to navigate back to it const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyAccountIDs([accountID]) && !_.isEmpty(timezone); @@ -128,7 +131,7 @@ function ProfilePage(props) { const hasStatus = !!statusEmojiCode; const statusContent = `${statusEmojiCode} ${statusText}`; - const navigateBackTo = lodashGet(props.route, 'params.backTo', ROUTES.HOME); + const navigateBackTo = lodashGet(props.route, 'params.backTo'); const shouldShowNotificationPreference = !_.isEmpty(props.report) && props.report.notificationPreference !== CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN; const notificationPreference = shouldShowNotificationPreference ? props.translate(`notificationPreferencesPage.notificationPreferences.${props.report.notificationPreference}`) : ''; @@ -151,22 +154,32 @@ function ProfilePage(props) { {hasMinimumDetails && ( - Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(String(accountID)))} - accessibilityLabel={props.translate('common.profile')} - accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON} + - - - - + {({show}) => ( + + + + + + )} + {Boolean(displayName) && ( Date: Fri, 2 Feb 2024 14:35:33 +0100 Subject: [PATCH 050/202] fix: sync with main --- src/components/MoneyRequestConfirmationList.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 933d604fd3cb..30cd28541181 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -660,8 +660,14 @@ function MoneyRequestConfirmationList({ style={[styles.moneyRequestMenuItem, styles.mt2]} titleStyle={styles.moneyRequestConfirmationAmount} disabled={didConfirm} - brickRoadIndicator={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction ?? null) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - error={shouldDisplayFieldError && TransactionUtils.isAmountMissing(transaction ?? null) ? translate('common.error.enterAmount') : ''} + brickRoadIndicator={ + isPolicyExpenseChat && shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction ?? null) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined + } + error={ + shouldDisplayMerchantError || (isPolicyExpenseChat && shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction ?? null)) + ? translate('common.error.enterMerchant') + : '' + } /> )} Date: Fri, 2 Feb 2024 15:00:47 +0100 Subject: [PATCH 051/202] fix: resolve comments --- src/components/MoneyRequestConfirmationList.tsx | 7 +++++-- src/libs/ReceiptUtils.ts | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 30cd28541181..685559835897 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -423,7 +423,10 @@ function MoneyRequestConfirmationList({ return []; } const myIOUAmount = IOUUtils.calculateAmount(selectedParticipantsMemo.length, iouAmount, iouCurrencyCode ?? '', true); - return [...selectedParticipantsMemo, OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(payeePersonalDetailsMemo, String(myIOUAmount))]; + return [ + ...selectedParticipantsMemo, + OptionsListUtils.getIOUConfirmationOptionsFromPayeePersonalDetail(payeePersonalDetailsMemo, CurrencyUtils.convertToDisplayString(myIOUAmount, iouCurrencyCode)), + ]; }, [hasMultipleParticipants, selectedParticipantsMemo, iouAmount, iouCurrencyCode, payeePersonalDetailsMemo]); useEffect(() => { @@ -560,7 +563,7 @@ function MoneyRequestConfirmationList({ return ( <> - {formError && ( + {!!formError && ( , receiptPa // URI to image, i.e. blob:new.expensify.com/9ef3a018-4067-47c6-b29f-5f1bd35f213d or expensify.com/receipts/w_e616108497ef940b7210ec6beb5a462d01a878f4.jpg // If there're errors, we need to display them in preview. We can store many files in errors, but we just need to get the last one - const errors = _.findLast(transaction.errors) as ReceiptError | undefined; + const errors = _.findLast(transaction?.errors) as ReceiptError | undefined; const path = errors?.source ?? transaction?.receipt?.source ?? receiptPath ?? ''; // filename of uploaded image or last part of remote URI const filename = errors?.filename ?? transaction?.filename ?? receiptFileName ?? ''; From 45c6530265b83384f1b06b8f58725e266aa7d315 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Fri, 2 Feb 2024 16:57:35 +0100 Subject: [PATCH 052/202] fix: typecheck --- src/components/AttachmentModal.tsx | 8 ++++---- .../API/parameters/AddCommentOrAttachementParams.ts | 4 +++- src/libs/ReportUtils.ts | 5 +++-- src/libs/actions/Report.ts | 5 +++-- .../AttachmentPickerWithMenuItems.tsx | 3 ++- .../ComposerWithSuggestions.tsx | 7 +++++-- .../ReportActionCompose/ReportActionCompose.tsx | 12 +++++------- .../SilentCommentUpdater/types.ts | 4 ---- src/types/onyx/ReportAction.ts | 3 ++- 9 files changed, 27 insertions(+), 24 deletions(-) diff --git a/src/components/AttachmentModal.tsx b/src/components/AttachmentModal.tsx index 90954c63b751..f4b016b790de 100755 --- a/src/components/AttachmentModal.tsx +++ b/src/components/AttachmentModal.tsx @@ -80,7 +80,7 @@ type ImagePickerResponse = { type FileObject = File | ImagePickerResponse; type ChildrenProps = { - displayFileInModal: (data: FileObject) => void; + displayFileInModal: (data: FileObject | undefined) => void; show: () => void; }; @@ -317,8 +317,8 @@ function AttachmentModal({ }, []); const validateAndDisplayFileToUpload = useCallback( - (data: FileObject) => { - if (!isDirectoryCheck(data)) { + (data: FileObject | undefined) => { + if (!data || !isDirectoryCheck(data)) { return; } let fileObject = data; @@ -617,4 +617,4 @@ export default withOnyx({ }, })(memo(AttachmentModal)); -export type {Attachment}; +export type {Attachment, FileObject}; diff --git a/src/libs/API/parameters/AddCommentOrAttachementParams.ts b/src/libs/API/parameters/AddCommentOrAttachementParams.ts index 58faf9fdfc9c..4eab35be7dd2 100644 --- a/src/libs/API/parameters/AddCommentOrAttachementParams.ts +++ b/src/libs/API/parameters/AddCommentOrAttachementParams.ts @@ -1,9 +1,11 @@ +import type {FileObject} from '@components/AttachmentModal'; + type AddCommentOrAttachementParams = { reportID: string; reportActionID?: string; commentReportActionID?: string | null; reportComment?: string; - file?: File; + file?: Partial; timezone?: string; shouldAllowActionableMentionWhispers?: boolean; clientCreatedTime?: string; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 5f3efcbcdbb0..651cd1f6513d 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -8,6 +8,7 @@ import lodashIsEqual from 'lodash/isEqual'; import type {OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; +import type {FileObject} from '@components/AttachmentModal'; import * as Expensicons from '@components/Icon/Expensicons'; import * as defaultWorkspaceAvatars from '@components/Icon/WorkspaceDefaultAvatars'; import CONST from '@src/CONST'; @@ -1290,7 +1291,7 @@ function getRoomWelcomeMessage(report: OnyxEntry, isUserPolicyAdmin: boo /** * Returns true if Concierge is one of the chat participants (1:1 as well as group chats) */ -function chatIncludesConcierge(report: OnyxEntry): boolean { +function chatIncludesConcierge(report: Partial>): boolean { return Boolean(report?.participantAccountIDs?.length && report?.participantAccountIDs?.includes(CONST.ACCOUNT_ID.CONCIERGE)); } @@ -2591,7 +2592,7 @@ function getParsedComment(text: string): string { return text.length <= CONST.MAX_MARKUP_LENGTH ? parser.replace(text) : lodashEscape(text); } -function buildOptimisticAddCommentReportAction(text?: string, file?: File, actorAccountID?: number): OptimisticReportAction { +function buildOptimisticAddCommentReportAction(text?: string, file?: Partial, actorAccountID?: number): OptimisticReportAction { const parser = new ExpensiMark(); const commentText = getParsedComment(text ?? ''); const isAttachment = !text && file !== undefined; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 782cf2b174c2..a508325a3206 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -7,6 +7,7 @@ import type {NullishDeep, OnyxCollection, OnyxEntry, OnyxUpdate} from 'react-nat import Onyx from 'react-native-onyx'; import type {PartialDeep, ValueOf} from 'type-fest'; import type {Emoji} from '@assets/emojis/types'; +import type {FileObject} from '@components/AttachmentModal'; import * as ActiveClientManager from '@libs/ActiveClientManager'; import * as API from '@libs/API'; import type { @@ -352,7 +353,7 @@ function notifyNewAction(reportID: string, accountID?: number, reportActionID?: * - Adding one attachment * - Add both a comment and attachment simultaneously */ -function addActions(reportID: string, text = '', file?: File) { +function addActions(reportID: string, text = '', file?: Partial) { let reportCommentText = ''; let reportCommentAction: OptimisticAddCommentReportAction | undefined; let attachmentAction: OptimisticAddCommentReportAction | undefined; @@ -511,7 +512,7 @@ function addActions(reportID: string, text = '', file?: File) { } /** Add an attachment and optional comment. */ -function addAttachment(reportID: string, file: File, text = '') { +function addAttachment(reportID: string, file: Partial, text = '') { addActions(reportID, text, file); } diff --git a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index 0dbfbba2759d..9511498ea699 100644 --- a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx +++ b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -6,6 +6,7 @@ import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import type {SvgProps} from 'react-native-svg'; import type {ValueOf} from 'type-fest'; +import type {FileObject} from '@components/AttachmentModal'; import AttachmentPicker from '@components/AttachmentPicker'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; @@ -46,7 +47,7 @@ type AttachmentPickerWithMenuItemsProps = { report: OnyxEntry; /** Callback to open the file in the modal */ - displayFileInModal: (url: string) => void; + displayFileInModal: (url: FileObject | undefined) => void; /** Whether or not the full size composer is available */ isFullComposerAvailable: boolean; diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index 074383897dac..76388372dd27 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -16,6 +16,7 @@ import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import type {useAnimatedRef} from 'react-native-reanimated'; import type {Emoji} from '@assets/emojis/types'; +import type {FileObject} from '@components/AttachmentModal'; import Composer from '@components/Composer'; import useKeyboardState from '@hooks/useKeyboardState'; import useLocalize from '@hooks/useLocalize'; @@ -85,7 +86,7 @@ type ComposerWithSuggestionsProps = { isComposerFullSize: boolean; isMenuVisible: boolean; inputPlaceholder: string; - displayFileInModal: (file: File | undefined) => void; + displayFileInModal: (file: FileObject | undefined) => void; textInputShouldClear: boolean; setTextInputShouldClear: (shouldClear: boolean) => void; isBlockedFromConcierge: boolean; @@ -107,6 +108,8 @@ type ComposerWithSuggestionsProps = { lastReportAction?: OnyxTypes.ReportAction; includeChronos?: boolean; parentReportActionID?: string; + // eslint-disable-next-line react/no-unused-prop-types + parentReportID: string | undefined; } & ComposerWithSuggestionsOnyxProps & Partial; @@ -748,7 +751,7 @@ export default withOnyx `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report?.parentReportID}`, + key: ({parentReportID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${parentReportID}`, canEvict: false, initWithStoredValues: false, }, diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index a5646f9c99a3..02d4105c3500 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -76,9 +76,6 @@ type ReportActionComposeProps = { /** The ID of the report actions will be created for */ reportID: string; - /** Array of report actions for this report */ - reportActions?: OnyxTypes.ReportAction[]; - /** The report currently being looked at */ report: OnyxEntry; @@ -97,9 +94,11 @@ type ReportActionComposeProps = { /** Whether the report is ready for display */ isReportReadyForDisplay?: boolean; + /** Whether the chat is empty */ isEmptyChat?: boolean; - lastReportAction?: any; + /** The last report action */ + lastReportAction?: OnyxTypes.ReportAction; } & ReportActionComposeOnyxProps & WithCurrentUserPersonalDetailsProps; @@ -118,7 +117,6 @@ function ReportActionCompose({ pendingAction, report, reportID, - reportActions, listHeight = 0, shouldShowComposeInput = true, isReportReadyForDisplay = true, @@ -269,7 +267,7 @@ function ReportActionCompose({ }, []); const addAttachment = useCallback( - (file: FileObject) => { + (file: Partial) => { const newComment = composerRef.current?.prepareCommentAndResetComposer(); Report.addAttachment(reportID, file, newComment); setTextInputShouldClear(false); @@ -437,7 +435,7 @@ function ReportActionCompose({ reportID={reportID} parentReportID={report?.parentReportID} parentReportActionID={report?.parentReportActionID} - includesChronos={ReportUtils.chatIncludesChronos(report)} + includeChronos={ReportUtils.chatIncludesChronos(report)} isEmptyChat={isEmptyChat} lastReportAction={lastReportAction} isMenuVisible={isMenuVisible} diff --git a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts index 591ee43ce6cd..1ba1689e7d6d 100644 --- a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts +++ b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts @@ -1,5 +1,4 @@ import type {OnyxEntry} from 'react-native-onyx'; -import type {Report} from '@src/types/onyx'; type SilentCommentUpdaterOnyxProps = { /** The comment of the report */ @@ -13,9 +12,6 @@ type SilentCommentUpdaterProps = { /** The ID of the report associated with the comment */ reportID: string; - /** The report associated with the comment */ - report: OnyxEntry; - /** The value of the comment */ value: string; diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts index d2f0afad5b7a..59fb785234eb 100644 --- a/src/types/onyx/ReportAction.ts +++ b/src/types/onyx/ReportAction.ts @@ -1,4 +1,5 @@ import type {ValueOf} from 'type-fest'; +import type {FileObject} from '@components/AttachmentModal'; import type {AvatarSource} from '@libs/UserUtils'; import type CONST from '@src/CONST'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; @@ -165,7 +166,7 @@ type ReportActionBase = { isFirstItem?: boolean; /** Informations about attachments of report action */ - attachmentInfo?: File | EmptyObject; + attachmentInfo?: Partial | EmptyObject; /** Receipt tied to report action */ receipt?: Receipt; From 61ad4769e0215b48706a74615e843fb765eeab58 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Fri, 2 Feb 2024 18:51:38 +0100 Subject: [PATCH 053/202] fix: resolve comments --- src/components/Composer/types.ts | 4 +- src/components/LocaleContextProvider.tsx | 4 +- src/libs/ComposerUtils/index.ts | 2 +- src/libs/DateUtils.ts | 2 +- src/libs/E2E/tests/chatOpeningTest.e2e.ts | 5 +- src/libs/E2E/tests/reportTypingTest.e2e.ts | 5 +- src/libs/EmojiUtils.ts | 7 +- .../home/report/ParticipantLocalTime.tsx | 4 +- .../AttachmentPickerWithMenuItems.tsx | 2 +- .../ComposerWithSuggestions.tsx | 73 +++++++++++++++++-- .../ComposerWithSuggestions/index.e2e.tsx | 8 +- .../ReportActionCompose.tsx | 46 ++++++------ .../report/ReportActionCompose/SendButton.tsx | 2 - .../SilentCommentUpdater/index.android.tsx | 2 +- .../SilentCommentUpdater/index.tsx | 4 +- .../SilentCommentUpdater/types.ts | 6 +- .../ReportActionCompose/SuggestionEmoji.tsx | 13 ++-- .../ReportActionCompose/SuggestionMention.tsx | 10 +-- .../ReportActionCompose/Suggestions.tsx | 21 ++++++ .../home/report/ReportTypingIndicator.tsx | 4 +- 20 files changed, 147 insertions(+), 77 deletions(-) diff --git a/src/components/Composer/types.ts b/src/components/Composer/types.ts index 9565eaf6208f..f19feb94dd0a 100644 --- a/src/components/Composer/types.ts +++ b/src/components/Composer/types.ts @@ -5,7 +5,7 @@ type TextSelection = { end?: number; }; -type ComposerProps = { +type ComposerProps = TextInputProps & { /** identify id in the text input */ id?: string; @@ -76,6 +76,6 @@ type ComposerProps = { /** Should make the input only scroll inside the element avoid scroll out to parent */ shouldContainScroll?: boolean; -} & TextInputProps; +}; export type {TextSelection, ComposerProps}; diff --git a/src/components/LocaleContextProvider.tsx b/src/components/LocaleContextProvider.tsx index 25b468181b87..6d819f4d6eaa 100644 --- a/src/components/LocaleContextProvider.tsx +++ b/src/components/LocaleContextProvider.tsx @@ -45,7 +45,7 @@ type LocaleContextProps = { /** Returns a locally converted phone number for numbers from the same region * and an internationally converted phone number with the country code for numbers from other regions */ - formatPhoneNumber: (phoneNumber: string) => string; + formatPhoneNumber: (phoneNumber: string | undefined) => string; /** Gets the locale digit corresponding to a standard digit */ toLocaleDigit: (digit: string) => string; @@ -94,7 +94,7 @@ function LocaleContextProvider({preferredLocale, currentUserPersonalDetails = {} const updateLocale = useMemo(() => () => DateUtils.setLocale(locale), [locale]); - const formatPhoneNumber = useMemo(() => (phoneNumber) => LocalePhoneNumber.formatPhoneNumber(phoneNumber), []); + const formatPhoneNumber = useMemo(() => (phoneNumber) => LocalePhoneNumber.formatPhoneNumber(phoneNumber ?? ''), []); const toLocaleDigit = useMemo(() => (digit) => LocaleDigitUtils.toLocaleDigit(locale, digit), [locale]); diff --git a/src/libs/ComposerUtils/index.ts b/src/libs/ComposerUtils/index.ts index de937c0ba915..6018cad86e47 100644 --- a/src/libs/ComposerUtils/index.ts +++ b/src/libs/ComposerUtils/index.ts @@ -18,7 +18,7 @@ function insertText(text: string, selection: Selection, textToInsert: string): s * Insert a white space at given index of text * @param text - text that needs whitespace to be appended to */ -function insertWhiteSpaceAtIndex(text: string | null, index: number) { +function insertWhiteSpaceAtIndex(text: string, index: number) { return `${text?.slice(0, index)} ${text?.slice(index)}`; } diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 9cb08556f082..c10d6b90128b 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -265,7 +265,7 @@ function formatToLongDateWithWeekday(datetime: string | Date): string { * * @returns Sunday */ -function formatToDayOfWeek(datetime: string): string { +function formatToDayOfWeek(datetime: Date): string { return format(new Date(datetime), CONST.DATE.WEEKDAY_TIME_FORMAT); } diff --git a/src/libs/E2E/tests/chatOpeningTest.e2e.ts b/src/libs/E2E/tests/chatOpeningTest.e2e.ts index 2e2ce76b348d..17d9dfa1cb4d 100644 --- a/src/libs/E2E/tests/chatOpeningTest.e2e.ts +++ b/src/libs/E2E/tests/chatOpeningTest.e2e.ts @@ -2,18 +2,17 @@ import type {NativeConfig} from 'react-native-config'; import E2ELogin from '@libs/E2E/actions/e2eLogin'; import waitForAppLoaded from '@libs/E2E/actions/waitForAppLoaded'; import E2EClient from '@libs/E2E/client'; -import type {TestConfig} from '@libs/E2E/types'; import getConfigValueOrThrow from '@libs/E2E/utils/getConfigValueOrThrow'; import Navigation from '@libs/Navigation/Navigation'; import Performance from '@libs/Performance'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; -const test = (config: TestConfig) => { +const test = (config: NativeConfig) => { // check for login (if already logged in the action will simply resolve) console.debug('[E2E] Logging in for chat opening'); - const reportID = getConfigValueOrThrow('reportID', config as NativeConfig); + const reportID = getConfigValueOrThrow('reportID', config); E2ELogin().then((neededLogin) => { if (neededLogin) { diff --git a/src/libs/E2E/tests/reportTypingTest.e2e.ts b/src/libs/E2E/tests/reportTypingTest.e2e.ts index 17464f7eb8d6..817bda941611 100644 --- a/src/libs/E2E/tests/reportTypingTest.e2e.ts +++ b/src/libs/E2E/tests/reportTypingTest.e2e.ts @@ -4,7 +4,6 @@ import E2ELogin from '@libs/E2E/actions/e2eLogin'; import waitForAppLoaded from '@libs/E2E/actions/waitForAppLoaded'; import waitForKeyboard from '@libs/E2E/actions/waitForKeyboard'; import E2EClient from '@libs/E2E/client'; -import type {TestConfig} from '@libs/E2E/types'; import getConfigValueOrThrow from '@libs/E2E/utils/getConfigValueOrThrow'; import Navigation from '@libs/Navigation/Navigation'; import Performance from '@libs/Performance'; @@ -13,11 +12,11 @@ import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import * as NativeCommands from '../../../../tests/e2e/nativeCommands/NativeCommandsAction'; -const test = (config: TestConfig) => { +const test = (config: NativeConfig) => { // check for login (if already logged in the action will simply resolve) console.debug('[E2E] Logging in for typing'); - const reportID = getConfigValueOrThrow('reportID', config as NativeConfig); + const reportID = getConfigValueOrThrow('reportID', config); E2ELogin().then((neededLogin) => { if (neededLogin) { diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index a7063e204efe..819aecf09d43 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -10,7 +10,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {FrequentlyUsedEmoji, Locale} from '@src/types/onyx'; import type {ReportActionReaction, UsersReactions} from '@src/types/onyx/ReportActionReactions'; import type IconAsset from '@src/types/utils/IconAsset'; -import type {SupportedLanguage} from './EmojiTrie'; type HeaderIndice = {code: string; index: number; icon: IconAsset}; type EmojiSpacer = {code: string; spacer: boolean}; @@ -370,12 +369,12 @@ function replaceEmojis(text: string, preferredSkinTone: number = CONST.EMOJI_DEF /** * Find all emojis in a text and replace them with their code. */ -function replaceAndExtractEmojis(text: string | null, preferredSkinTone: number = CONST.EMOJI_DEFAULT_SKIN_TONE, lang: Locale = CONST.LOCALES.DEFAULT): ReplacedEmoji { +function replaceAndExtractEmojis(text: string, preferredSkinTone: number = CONST.EMOJI_DEFAULT_SKIN_TONE, lang: Locale = CONST.LOCALES.DEFAULT): ReplacedEmoji { const {text: convertedText = '', emojis = [], cursorPosition} = replaceEmojis(text ?? '', preferredSkinTone, lang); return { text: convertedText, - emojis: emojis.concat(extractEmojis(text ?? '')), + emojis: emojis.concat(extractEmojis(text)), cursorPosition, }; } @@ -384,7 +383,7 @@ function replaceAndExtractEmojis(text: string | null, preferredSkinTone: number * Suggest emojis when typing emojis prefix after colon * @param [limit] - matching emojis limit */ -function suggestEmojis(text: string, lang: SupportedLanguage, limit: number = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS): Emoji[] | undefined { +function suggestEmojis(text: string, lang: Locale, limit: number = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS): Emoji[] | undefined { // emojisTrie is importing the emoji JSON file on the app starting and we want to avoid it const emojisTrie = require('./EmojiTrie').default; diff --git a/src/pages/home/report/ParticipantLocalTime.tsx b/src/pages/home/report/ParticipantLocalTime.tsx index e97fad8f20f0..58d85c0662b2 100644 --- a/src/pages/home/report/ParticipantLocalTime.tsx +++ b/src/pages/home/report/ParticipantLocalTime.tsx @@ -22,8 +22,8 @@ function getParticipantLocalTime(participant: PersonalDetails, preferredLocale: const reportRecipientTimezone = participant.timezone || CONST.DEFAULT_TIME_ZONE; const reportTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale ?? CONST.LOCALES.DEFAULT, undefined, reportRecipientTimezone.selected); const currentTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale ?? CONST.LOCALES.DEFAULT); - const reportRecipientDay = DateUtils.formatToDayOfWeek(reportTimezone.toDateString()); - const currentUserDay = DateUtils.formatToDayOfWeek(currentTimezone.toDateString()); + const reportRecipientDay = DateUtils.formatToDayOfWeek(reportTimezone); + const currentUserDay = DateUtils.formatToDayOfWeek(currentTimezone); if (reportRecipientDay !== currentUserDay) { return `${DateUtils.formatToLocalTime(reportTimezone)} ${reportRecipientDay}`; } diff --git a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index 9511498ea699..e6a75e6f157b 100644 --- a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx +++ b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -194,7 +194,7 @@ function AttachmentPickerWithMenuItems({ return ( - {/* @ts-expect-error TODO: Remove this once SettlementButton (https://github.com/Expensify/App/issues/25134) is migrated to TypeScript. */} + {/* @ts-expect-error TODO: Remove this once AttachmentPicker (https://github.com/Expensify/App/issues/25134) is migrated to TypeScript. */} {({openPicker}) => { const triggerAttachmentPicker = () => { onTriggerAttachmentPicker(); diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index 76388372dd27..96989b2a647b 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -1,6 +1,6 @@ import {useIsFocused, useNavigation} from '@react-navigation/native'; import lodashDebounce from 'lodash/debounce'; -import type {ForwardedRef, RefAttributes, RefObject} from 'react'; +import type {ForwardedRef, MutableRefObject, RefAttributes, RefObject} from 'react'; import React, {forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; import type { LayoutChangeEvent, @@ -79,35 +79,94 @@ type ComposerWithSuggestionsOnyxProps = { }; type ComposerWithSuggestionsProps = { + /** Report ID */ reportID: string; + + /** Callback to focus composer */ onFocus: () => void; + + /** Callback to blur composer */ onBlur: (event: NativeSyntheticEvent) => void; + + /** Callback to update the value of the composer */ onValueChange: (value: string) => void; + + /** Whether the composer is full size */ isComposerFullSize: boolean; + + /** Whether the menu is visible */ isMenuVisible: boolean; + + /** The placeholder for the input */ inputPlaceholder: string; + + /** Function to display a file in a modal */ displayFileInModal: (file: FileObject | undefined) => void; + + /** Whether the text input should clear */ textInputShouldClear: boolean; + + /** Function to set the text input should clear */ setTextInputShouldClear: (shouldClear: boolean) => void; + + /** Whether the user is blocked from concierge */ isBlockedFromConcierge: boolean; + + /** Whether the input is disabled */ disabled: boolean; + + /** Whether the full composer is available */ isFullComposerAvailable: boolean; + + /** Function to set whether the full composer is available */ setIsFullComposerAvailable: (isFullComposerAvailable: boolean) => void; + + /** Function to set whether the comment is empty */ setIsCommentEmpty: (isCommentEmpty: boolean) => void; + + /** Function to handle sending a message */ handleSendMessage: () => void; + + /** Whether the compose input should show */ shouldShowComposeInput: OnyxEntry; + + /** Function to measure the parent container */ measureParentContainer: (callback: MeasureInWindowOnSuccessCallback) => void; + + /** The height of the list */ listHeight: number; + + /** Whether the scroll is likely to trigger a layout */ isScrollLikelyLayoutTriggered: RefObject; + + /** Function to raise the scroll is likely layout triggered */ raiseIsScrollLikelyLayoutTriggered: () => void; + + /** The ref to the suggestions */ suggestionsRef: React.RefObject; + + /** The ref to the animated input */ animatedRef: AnimatedRef; - isNextModalWillOpenRef: RefObject; + + /** The ref to the next modal will open */ + isNextModalWillOpenRef: MutableRefObject; + + /** Whether the edit is focused */ editFocused: boolean; + + /** Wheater chat is empty */ isEmptyChat?: boolean; + + /** The last report action */ lastReportAction?: OnyxTypes.ReportAction; + + /** Whether to include chronos */ includeChronos?: boolean; + + /** The parent report action ID */ parentReportActionID?: string; + + /** The parent report ID */ // eslint-disable-next-line react/no-unused-prop-types parentReportID: string | undefined; } & ComposerWithSuggestionsOnyxProps & @@ -275,13 +334,13 @@ function ComposerWithSuggestions( * @property diff - The newly added characters. */ const findNewlyAddedChars = useCallback( - (prevText: string, newText: string | null): NewlyAddedChars => { + (prevText: string, newText: string): NewlyAddedChars => { let startIndex = -1; let endIndex = -1; let currentIndex = 0; // Find the first character mismatch with newText - while (currentIndex < (newText?.length ?? 0) && prevText.charAt(currentIndex) === newText?.charAt(currentIndex) && selection.start > currentIndex) { + while (currentIndex < newText.length && prevText.charAt(currentIndex) === newText?.charAt(currentIndex) && selection.start > currentIndex) { currentIndex++; } @@ -295,7 +354,6 @@ function ComposerWithSuggestions( endIndex = currentIndex + (newText?.length ?? 0); } } - return { startIndex, endIndex, @@ -309,7 +367,7 @@ function ComposerWithSuggestions( * Update the value of the comment in Onyx */ const updateComment = useCallback( - (commentValue: string | null, shouldDebounceSaveComment?: boolean) => { + (commentValue: string, shouldDebounceSaveComment?: boolean) => { raiseIsScrollLikelyLayoutTriggered(); const {startIndex, endIndex, diff} = findNewlyAddedChars(lastTextRef.current, commentValue); const isEmojiInserted = diff.length && endIndex > startIndex && diff.trim() === diff && EmojiUtils.containsOnlyEmojis(diff); @@ -317,7 +375,7 @@ function ComposerWithSuggestions( text: newComment, emojis, cursorPosition, - } = EmojiUtils.replaceAndExtractEmojis(isEmojiInserted ? ComposerUtils.insertWhiteSpaceAtIndex(commentValue, endIndex) : commentValue, preferredSkinTone, preferredLocale); + } = EmojiUtils.replaceAndExtractEmojis(isEmojiInserted ? ComposerUtils.insertWhiteSpaceAtIndex(commentValue, endIndex) : commentValue ?? '', preferredSkinTone, preferredLocale); if (emojis.length) { const newEmojis = EmojiUtils.getAddedEmojis(emojis, emojisPresentBefore.current); if (newEmojis.length) { @@ -595,7 +653,6 @@ function ComposerWithSuggestions( const prevIsFocused = usePrevious(isFocused); useEffect(() => { if (modal?.isVisible && !prevIsModalVisible) { - // @ts-expect-error need to reassign this ref // eslint-disable-next-line no-param-reassign isNextModalWillOpenRef.current = false; } diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx index 94e65a48e46b..0fa535329d33 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx @@ -1,4 +1,4 @@ -import type {ForwardedRef, RefObject} from 'react'; +import type {ForwardedRef} from 'react'; import React, {forwardRef, useEffect} from 'react'; import E2EClient from '@libs/E2E/client'; import type {ComposerRef} from '@pages/home/report/ReportActionCompose/ReportActionCompose'; @@ -20,17 +20,17 @@ function ComposerWithSuggestionsE2e(props: ComposerWithSuggestionsProps, ref: Fo // Eventually Auto focus on e2e tests useEffect(() => { const testConfig = E2EClient.getCurrentActiveTestConfig(); - if (testConfig?.reportScreen && typeof testConfig.reportScreen !== 'string' && (testConfig?.reportScreen.autoFocus ?? false) === false) { + if (testConfig?.reportScreen && typeof testConfig.reportScreen !== 'string' && !testConfig?.reportScreen.autoFocus) { return; } // We need to wait for the component to be mounted before focusing setTimeout(() => { - if (!(ref as RefObject)?.current) { + if (!(ref && 'current' in ref)) { return; } - (ref as RefObject).current?.focus(true); + ref.current?.focus(true); }, 1); }, [ref]); diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 02d4105c3500..98630ff88b23 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -69,38 +69,38 @@ type ReportActionComposeOnyxProps = { shouldShowComposeInput: OnyxEntry; }; -type ReportActionComposeProps = { - /** A method to call when the form is submitted */ - onSubmit: (newComment: string | undefined) => void; +type ReportActionComposeProps = ReportActionComposeOnyxProps & + WithCurrentUserPersonalDetailsProps & { + /** A method to call when the form is submitted */ + onSubmit: (newComment: string | undefined) => void; - /** The ID of the report actions will be created for */ - reportID: string; + /** The ID of the report actions will be created for */ + reportID: string; - /** The report currently being looked at */ - report: OnyxEntry; + /** The report currently being looked at */ + report: OnyxEntry; - /** Is composer full size */ - isComposerFullSize?: boolean; + /** Is composer full size */ + isComposerFullSize?: boolean; - /** Whether user interactions should be disabled */ - disabled?: boolean; + /** Whether user interactions should be disabled */ + disabled?: boolean; - /** Height of the list which the composer is part of */ - listHeight?: number; + /** Height of the list which the composer is part of */ + listHeight?: number; - /** The type of action that's pending */ - pendingAction?: OnyxCommon.PendingAction; + /** The type of action that's pending */ + pendingAction?: OnyxCommon.PendingAction; - /** Whether the report is ready for display */ - isReportReadyForDisplay?: boolean; + /** Whether the report is ready for display */ + isReportReadyForDisplay?: boolean; - /** Whether the chat is empty */ - isEmptyChat?: boolean; + /** Whether the chat is empty */ + isEmptyChat?: boolean; - /** The last report action */ - lastReportAction?: OnyxTypes.ReportAction; -} & ReportActionComposeOnyxProps & - WithCurrentUserPersonalDetailsProps; + /** The last report action */ + lastReportAction?: OnyxTypes.ReportAction; + }; // We want consistent auto focus behavior on input between native and mWeb so we have some auto focus management code that will // prevent auto focus on existing chat for mobile device diff --git a/src/pages/home/report/ReportActionCompose/SendButton.tsx b/src/pages/home/report/ReportActionCompose/SendButton.tsx index feeff49ceb55..4726c1638f42 100644 --- a/src/pages/home/report/ReportActionCompose/SendButton.tsx +++ b/src/pages/home/report/ReportActionCompose/SendButton.tsx @@ -46,8 +46,6 @@ function SendButton({isDisabled: isDisabledProp, handleSendMessage}: SendButtonP ]} role={CONST.ROLE.BUTTON} accessibilityLabel={translate('common.send')} - accessible - onPress={() => {}} > {({pressed}) => ( { - updateComment(comment); + updateComment(comment ?? ''); // eslint-disable-next-line react-hooks/exhaustive-deps -- We need to run this on mount }, []); diff --git a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx index a1d591c97297..c84bd3786610 100644 --- a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx +++ b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx @@ -17,7 +17,7 @@ function SilentCommentUpdater({comment, commentRef, reportID, value, updateComme const prevPreferredLocale = usePrevious(preferredLocale); useEffect(() => { - updateComment(comment ?? null); + updateComment(comment ?? ''); // eslint-disable-next-line react-hooks/exhaustive-deps -- We need to run this on mount }, []); @@ -32,7 +32,7 @@ function SilentCommentUpdater({comment, commentRef, reportID, value, updateComme return; } - updateComment(comment); + updateComment(comment ?? ''); }, [prevCommentProp, prevPreferredLocale, prevReportId, comment, preferredLocale, reportID, updateComment, value, commentRef]); return null; diff --git a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts index 1ba1689e7d6d..dbc23b0279c3 100644 --- a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts +++ b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/types.ts @@ -5,9 +5,9 @@ type SilentCommentUpdaterOnyxProps = { comment: OnyxEntry; }; -type SilentCommentUpdaterProps = { +type SilentCommentUpdaterProps = SilentCommentUpdaterOnyxProps & { /** Updates the comment */ - updateComment: (comment: OnyxEntry) => void; + updateComment: (comment: string) => void; /** The ID of the report associated with the comment */ reportID: string; @@ -17,6 +17,6 @@ type SilentCommentUpdaterProps = { /** The ref of the comment */ commentRef: React.RefObject; -} & SilentCommentUpdaterOnyxProps; +}; export type {SilentCommentUpdaterProps, SilentCommentUpdaterOnyxProps}; diff --git a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx index d343616a206d..206c91ed9b08 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx @@ -6,7 +6,6 @@ import type {Emoji} from '@assets/emojis/types'; import EmojiSuggestions from '@components/EmojiSuggestions'; import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; import useLocalize from '@hooks/useLocalize'; -import type {SupportedLanguage} from '@libs/EmojiTrie'; import * as EmojiUtils from '@libs/EmojiUtils'; import * as SuggestionsUtils from '@libs/SuggestionUtils'; import CONST from '@src/CONST'; @@ -26,11 +25,11 @@ type SuggestionEmojiOnyxProps = { preferredSkinTone: number; }; -type SuggestionEmojiProps = { - /** Function to clear the input */ - resetKeyboardInput: (() => void) | undefined; -} & SuggestionEmojiOnyxProps & - SuggestionProps; +type SuggestionEmojiProps = SuggestionProps & + SuggestionEmojiOnyxProps & { + /** Function to clear the input */ + resetKeyboardInput: (() => void) | undefined; + }; /** * Check if this piece of string looks like an emoji @@ -166,7 +165,7 @@ function SuggestionEmoji( colonIndex, shouldShowSuggestionMenu: false, }; - const newSuggestedEmojis = EmojiUtils.suggestEmojis(leftString, preferredLocale as SupportedLanguage); + const newSuggestedEmojis = EmojiUtils.suggestEmojis(leftString, preferredLocale); if (newSuggestedEmojis?.length && isCurrentlyShowingEmojiSuggestion) { nextState.suggestedEmojis = newSuggestedEmojis; diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index 02bcd27093e7..1e3e80ad9d7e 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -15,8 +15,6 @@ import type {PersonalDetailsList} from '@src/types/onyx'; import type {SuggestionsRef} from './ReportActionCompose'; import type {SuggestionProps} from './Suggestions'; -type SuggestionMentionProps = {isAutoSuggestionPickerLarge: boolean} & SuggestionProps; - type SuggestionValues = { suggestedMentions: Mention[]; atSignIndex: number; @@ -37,7 +35,7 @@ const defaultSuggestionsValues: SuggestionValues = { }; function SuggestionMention( - {value, selection, setSelection, updateComment, isAutoSuggestionPickerLarge, measureParentContainer, isComposerFocused}: SuggestionMentionProps, + {value, selection, setSelection, updateComment, isAutoSuggestionPickerLarge, measureParentContainer, isComposerFocused}: SuggestionProps, ref: ForwardedRef, ) { const personalDetails = usePersonalDetails() ?? CONST.EMPTY_OBJECT; @@ -161,7 +159,7 @@ function SuggestionMention( sortedPersonalDetails.slice(0, CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS - suggestions.length).forEach((detail) => { suggestions.push({ text: PersonalDetailsUtils.getDisplayNameOrDefault(detail), - alternateText: formatPhoneNumber(detail?.login ?? ''), + alternateText: formatPhoneNumber(detail?.login), login: detail?.login, icons: [ { @@ -200,7 +198,7 @@ function SuggestionMention( const leftString = value.substring(0, suggestionEndIndex); const words = leftString.split(CONST.REGEX.SPACE_OR_EMOJI); - const lastWord = words.at(-1) ?? ''; + const lastWord: string = words.at(-1) ?? ''; const secondToLastWord = words[words.length - 3]; let atSignIndex; @@ -297,7 +295,7 @@ function SuggestionMention( mentions={suggestionValues.suggestedMentions} prefix={suggestionValues.mentionPrefix} onSelect={insertSelectedMention} - isMentionPickerLarge={isAutoSuggestionPickerLarge} + isMentionPickerLarge={!!isAutoSuggestionPickerLarge} measureParentContainer={measureParentContainer} /> ); diff --git a/src/pages/home/report/ReportActionCompose/Suggestions.tsx b/src/pages/home/report/ReportActionCompose/Suggestions.tsx index 0968a61c3abb..61026a792919 100644 --- a/src/pages/home/report/ReportActionCompose/Suggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/Suggestions.tsx @@ -14,16 +14,37 @@ type Selection = { }; type SuggestionProps = { + /** The current input value */ value: string; + + /** Callback to update the current input value */ setValue: (newValue: string) => void; + + /** The current selection value */ selection: Selection; + + /** Callback to update the current selection */ setSelection: (newSelection: Selection) => void; + + /** Callback to update the comment draft */ updateComment: (newComment: string, shouldDebounceSaveComment?: boolean) => void; + + /** Meaures the parent container's position and dimensions. */ measureParentContainer: (callback: MeasureInWindowOnSuccessCallback) => void; + + /** Whether the composer is expanded */ isComposerFullSize: boolean; + + /** Report composer focus state */ isComposerFocused?: boolean; + + /** Callback to reset the keyboard input */ resetKeyboardInput?: () => void; + + /** Whether the auto suggestion picker is large */ isAutoSuggestionPickerLarge?: boolean; + + /** The height of the composer */ composerHeight?: number; }; diff --git a/src/pages/home/report/ReportTypingIndicator.tsx b/src/pages/home/report/ReportTypingIndicator.tsx index 6b00a4520295..e484ce9886a7 100755 --- a/src/pages/home/report/ReportTypingIndicator.tsx +++ b/src/pages/home/report/ReportTypingIndicator.tsx @@ -15,10 +15,10 @@ type ReportTypingIndicatorOnyxProps = { userTypingStatuses: OnyxEntry; }; -type ReportTypingIndicatorProps = { +type ReportTypingIndicatorProps = ReportTypingIndicatorOnyxProps & { // eslint-disable-next-line react/no-unused-prop-types -- This is used by withOnyx reportID: string; -} & ReportTypingIndicatorOnyxProps; +}; function ReportTypingIndicator({userTypingStatuses}: ReportTypingIndicatorProps) { const {translate} = useLocalize(); From 3f10fe467b1bd17408eb8ffa1a8bb628a2429e46 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 5 Feb 2024 17:48:58 +0700 Subject: [PATCH 054/202] fix update amount --- src/libs/actions/IOU.js | 73 ++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 31 deletions(-) diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index f5167eed9afa..bd9773dcbfa2 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -312,15 +312,33 @@ function getReceiptError(receipt, filename, isScanRequest = true) { : ErrorUtils.getMicroSecondOnyxErrorObject({error: CONST.IOU.RECEIPT_ERROR, source: receipt.source, filename}); } +/** + * @param {Object} iouReport + * + * @returns {Boolean} + */ +function needsToBeManuallySubmitted(iouReport) { + const isPolicyExpenseChat = ReportUtils.isExpenseReport(iouReport); + + if (isPolicyExpenseChat) { + const policy = ReportUtils.getPolicy(iouReport.policyID); + const isFromPaidPolicy = PolicyUtils.isPaidGroupPolicy(policy); + + // If the scheduled submit is turned off on the policy, user needs to manually submit the report which is indicated by GBR in LHN + return isFromPaidPolicy && !(policy.isHarvestingEnabled || false); + } + + return true; +} + /** * Return the object to update hasOutstandingChildRequest * @param {Object} [policy] * @param {Object} iouReport - * @param {Boolean} needsToBeManuallySubmitted * @returns {Object} */ -function getOutstandingChildRequest(policy, iouReport, needsToBeManuallySubmitted) { - if (!needsToBeManuallySubmitted) { +function getOutstandingChildRequest(policy, iouReport) { + if (!needsToBeManuallySubmitted(iouReport)) { return { hasOutstandingChildRequest: false, }; @@ -355,7 +373,6 @@ function getOutstandingChildRequest(policy, iouReport, needsToBeManuallySubmitte * @param {Object} policy - May be undefined, an empty object, or an object matching the Policy type (src/types/onyx/Policy.ts) * @param {Array} policyTags * @param {Array} policyCategories - * @param {Boolean} needsToBeManuallySubmitted * @returns {Array} - An array containing the optimistic data, success data, and failure data. */ function buildOnyxDataForMoneyRequest( @@ -374,10 +391,9 @@ function buildOnyxDataForMoneyRequest( policy, policyTags, policyCategories, - needsToBeManuallySubmitted = true, ) { const isScanRequest = TransactionUtils.isScanRequest(transaction); - const outstandingChildRequest = getOutstandingChildRequest(policy, iouReport, needsToBeManuallySubmitted); + const outstandingChildRequest = getOutstandingChildRequest(policy, iouReport); const optimisticData = [ { // Use SET for new reports because it doesn't exist yet, is faster and we need the data to be available when we navigate to the chat page @@ -722,15 +738,10 @@ function getMoneyRequestInformation( iouReport = allReports[`${ONYXKEYS.COLLECTION.REPORT}${chatReport.iouReportID}`]; } - // Check if the Scheduled Submit is enabled in case of expense report - let needsToBeManuallySubmitted = true; let isFromPaidPolicy = false; if (isPolicyExpenseChat) { isFromPaidPolicy = PolicyUtils.isPaidGroupPolicy(policy); - // If the scheduled submit is turned off on the policy, user needs to manually submit the report which is indicated by GBR in LHN - needsToBeManuallySubmitted = isFromPaidPolicy && !(lodashGet(policy, 'harvesting.enabled', policy.isHarvestingEnabled) || false); - // If the linked expense report on paid policy is not draft, we need to create a new draft expense report if (iouReport && isFromPaidPolicy && !ReportUtils.isDraftExpenseReport(iouReport)) { iouReport = null; @@ -859,7 +870,6 @@ function getMoneyRequestInformation( policy, policyTags, policyCategories, - needsToBeManuallySubmitted, ); return { @@ -1033,7 +1043,7 @@ function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, t // from the server with the currency conversion let updatedMoneyRequestReport = {...iouReport}; if (updatedTransaction.currency === iouReport.currency && updatedTransaction.modifiedAmount) { - const diff = TransactionUtils.getAmount(transaction, true) - TransactionUtils.getAmount(updatedTransaction, true); + const diff = TransactionUtils.getAmount(updatedTransaction, isFromExpenseReport) - TransactionUtils.getAmount(transaction, isFromExpenseReport); if (ReportUtils.isExpenseReport(iouReport)) { updatedMoneyRequestReport.total += diff; } else { @@ -1041,11 +1051,23 @@ function getUpdateMoneyRequestParams(transactionID, transactionThreadReportID, t } updatedMoneyRequestReport.cachedTotal = CurrencyUtils.convertToDisplayString(updatedMoneyRequestReport.total, updatedTransaction.currency); - optimisticData.push({ - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, - value: updatedMoneyRequestReport, - }); + optimisticData.push( + ...[ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, + value: updatedMoneyRequestReport, + }, + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.parentReportID}`, + value: { + hasOutstandingChildRequest: + needsToBeManuallySubmitted(iouReport) && updatedMoneyRequestReport.managerID === userAccountID && updatedMoneyRequestReport.total !== 0, + }, + }, + ], + ); successData.push({ onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${iouReport.reportID}`, @@ -2653,18 +2675,7 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView const updatedReportPreviewAction = {...reportPreviewAction}; updatedReportPreviewAction.pendingAction = shouldDeleteIOUReport ? CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE : CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE; - const isPolicyExpenseChat = ReportUtils.isExpenseReport(iouReport); - - let needsToBeManuallySubmitted = true; - if (isPolicyExpenseChat) { - const policy = ReportUtils.getPolicy(iouReport.policyID); - const isFromPaidPolicy = PolicyUtils.isPaidGroupPolicy(policy); - - // If the scheduled submit is turned off on the policy, user needs to manually submit the report which is indicated by GBR in LHN - needsToBeManuallySubmitted = isFromPaidPolicy && !(policy.isHarvestingEnabled || false); - } - - if (isPolicyExpenseChat) { + if (ReportUtils.isExpenseReport(iouReport)) { updatedIOUReport = {...iouReport}; // Because of the Expense reports are stored as negative values, we add the total from the amount @@ -2770,7 +2781,7 @@ function deleteMoneyRequest(transactionID, reportAction, isSingleTransactionView onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${chatReport.reportID}`, value: { - hasOutstandingChildRequest: needsToBeManuallySubmitted && updatedIOUReport.managerID === userAccountID && updatedIOUReport.total !== 0, + hasOutstandingChildRequest: needsToBeManuallySubmitted(iouReport) && updatedIOUReport.managerID === userAccountID && updatedIOUReport.total !== 0, }, }, ]; From fad94907fbdbd62dc75a4668055132d0dec9825b Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 5 Feb 2024 12:02:47 +0100 Subject: [PATCH 055/202] fix: resolve comments --- .../ReportActionCompose/SuggestionMention.tsx | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index 1e3e80ad9d7e..2b5080e788ab 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -1,3 +1,4 @@ +import lodashSortBy from 'lodash/sortBy'; import type {ForwardedRef} from 'react'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; import * as Expensicons from '@components/Icon/Expensicons'; @@ -142,20 +143,8 @@ function SuggestionMention( return true; }); - const sortedPersonalDetails = filteredPersonalDetails.sort((a, b) => { - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null - const nameA = a?.displayName || a?.login || ''; - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null - const nameB = b?.displayName || b?.login || ''; - - if (nameA < nameB) { - return -1; - } - if (nameA > nameB) { - return 1; - } - return 0; - }); + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- nullish coalescing cannot be used if left side can be empty string + const sortedPersonalDetails = lodashSortBy(filteredPersonalDetails, (detail) => detail?.displayName || detail?.login); sortedPersonalDetails.slice(0, CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS - suggestions.length).forEach((detail) => { suggestions.push({ text: PersonalDetailsUtils.getDisplayNameOrDefault(detail), @@ -201,9 +190,9 @@ function SuggestionMention( const lastWord: string = words.at(-1) ?? ''; const secondToLastWord = words[words.length - 3]; - let atSignIndex; + let atSignIndex: number | undefined; let suggestionWord = ''; - let prefix; + let prefix: string; // Detect if the last two words contain a mention (two words are needed to detect a mention with a space in it) if (lastWord.startsWith('@')) { From 937946954bcce86a8af2b7b9eeca12336e155635 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 5 Feb 2024 22:52:12 +0700 Subject: [PATCH 056/202] seperate platform logic --- .../index.native.ts} | 0 src/libs/actions/CachedPDFPaths/index.ts | 9 +++++++++ 2 files changed, 9 insertions(+) rename src/libs/actions/{CachedPDFPaths.ts => CachedPDFPaths/index.native.ts} (100%) create mode 100644 src/libs/actions/CachedPDFPaths/index.ts diff --git a/src/libs/actions/CachedPDFPaths.ts b/src/libs/actions/CachedPDFPaths/index.native.ts similarity index 100% rename from src/libs/actions/CachedPDFPaths.ts rename to src/libs/actions/CachedPDFPaths/index.native.ts diff --git a/src/libs/actions/CachedPDFPaths/index.ts b/src/libs/actions/CachedPDFPaths/index.ts new file mode 100644 index 000000000000..8c5c71df7a49 --- /dev/null +++ b/src/libs/actions/CachedPDFPaths/index.ts @@ -0,0 +1,9 @@ +function add(reportActionID: string, path: string): Promise { + return Promise.resolve(); +} + +function clearByKey(reportActionID: string) {} + +function clearAll() {} + +export {add, clearByKey, clearAll}; From 6eb146a455a902b3c7fcad8fdd2c93362150a107 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 5 Feb 2024 23:07:20 +0700 Subject: [PATCH 057/202] add types for CachedPDFPaths --- .../Attachments/AttachmentView/index.js | 2 +- src/libs/actions/CachedPDFPaths/index.native.ts | 17 +++++++++-------- src/libs/actions/CachedPDFPaths/index.ts | 10 +++++----- src/libs/actions/CachedPDFPaths/types.ts | 6 ++++++ 4 files changed, 21 insertions(+), 14 deletions(-) create mode 100644 src/libs/actions/CachedPDFPaths/types.ts diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index 39f83820d207..cf8cc6f017d9 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -143,7 +143,7 @@ function AttachmentView({ const encryptedSourceUrl = isAuthTokenRequired ? addEncryptedAuthTokenToURL(source) : source; const onPDFLoadComplete = (path) => { - if (isUsedInCarousel && reportActionID) { + if (isUsedInCarousel && reportActionID && path) { CachedPDFPaths.add(reportActionID, path); } if (!loadComplete) { diff --git a/src/libs/actions/CachedPDFPaths/index.native.ts b/src/libs/actions/CachedPDFPaths/index.native.ts index 4eefb9a7982e..6c4456f7a528 100644 --- a/src/libs/actions/CachedPDFPaths/index.native.ts +++ b/src/libs/actions/CachedPDFPaths/index.native.ts @@ -1,6 +1,7 @@ import {exists, unlink} from 'react-native-fs'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {Add, Clear, ClearAll, ClearByKey} from './types'; /* * We need to save the paths of PDF files so we can delete them later. @@ -14,14 +15,14 @@ Onyx.connect({ }, }); -function add(reportActionID: string, path: string): Promise { +const add: Add = (reportActionID: string, path: string) => { if (pdfPaths[reportActionID]) { return Promise.resolve(); } return Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {[reportActionID]: path}); -} +}; -function clear(path: string): Promise { +const clear: Clear = (path: string) => { if (!path) { return Promise.resolve(); } @@ -33,14 +34,14 @@ function clear(path: string): Promise { return unlink(path); }); }); -} +}; -function clearByKey(reportActionID: string) { +const clearByKey: ClearByKey = (reportActionID: string) => { clear(pdfPaths[reportActionID] ?? '').then(() => Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {[reportActionID]: null})); -} +}; -function clearAll() { +const clearAll: ClearAll = () => { Promise.all(Object.values(pdfPaths).map(clear)).then(() => Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {})); -} +}; export {add, clearByKey, clearAll}; diff --git a/src/libs/actions/CachedPDFPaths/index.ts b/src/libs/actions/CachedPDFPaths/index.ts index 8c5c71df7a49..3cac21bf3c25 100644 --- a/src/libs/actions/CachedPDFPaths/index.ts +++ b/src/libs/actions/CachedPDFPaths/index.ts @@ -1,9 +1,9 @@ -function add(reportActionID: string, path: string): Promise { - return Promise.resolve(); -} +import type {Add, ClearAll, ClearByKey} from './types'; -function clearByKey(reportActionID: string) {} +const add: Add = () => Promise.resolve(); -function clearAll() {} +const clearByKey: ClearByKey = () => {}; + +const clearAll: ClearAll = () => {}; export {add, clearByKey, clearAll}; diff --git a/src/libs/actions/CachedPDFPaths/types.ts b/src/libs/actions/CachedPDFPaths/types.ts new file mode 100644 index 000000000000..8c4843aaeaec --- /dev/null +++ b/src/libs/actions/CachedPDFPaths/types.ts @@ -0,0 +1,6 @@ +type Add = (reportActionID: string, path: string) => Promise; +type Clear = (path: string) => Promise; +type ClearAll = () => void; +type ClearByKey = (reportActionID: string) => void; + +export type {Add, Clear, ClearAll, ClearByKey}; From 4d0c1b1704d30f2eee6bd85bbc8e4ddca4433e67 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 6 Feb 2024 16:26:36 +0700 Subject: [PATCH 058/202] resolve conflict --- src/pages/ProfilePage.js | 43 ++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index 16ace231eceb..426232b2f68d 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -5,7 +5,6 @@ import React, {useEffect} from 'react'; import {ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; -import AttachmentModal from '@components/AttachmentModal'; import AutoUpdateTime from '@components/AutoUpdateTime'; import Avatar from '@components/Avatar'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; @@ -104,8 +103,6 @@ function ProfilePage(props) { const login = lodashGet(details, 'login', ''); const timezone = lodashGet(details, 'timezone', {}); - const originalFileName = lodashGet(details, 'originalFileName', ''); - // If we have a reportID param this means that we // arrived here via the ParticipantsPage and should be allowed to navigate back to it const shouldShowLocalTime = !ReportUtils.hasAutomatedExpensifyAccountIDs([accountID]) && !_.isEmpty(timezone); @@ -154,32 +151,22 @@ function ProfilePage(props) { {hasMinimumDetails && ( - Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(String(accountID)))} + accessibilityLabel={props.translate('common.profile')} + accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON} > - {({show}) => ( - - - - - - )} - + + + + {Boolean(displayName) && ( Date: Tue, 6 Feb 2024 14:34:37 +0100 Subject: [PATCH 059/202] fix: typecheck --- src/components/ButtonWithDropdownMenu.tsx | 21 +++++++-------- .../MoneyRequestConfirmationList.tsx | 27 ++++++++++++------- .../API/parameters/PayMoneyRequestParams.ts | 5 ++-- src/libs/API/parameters/SendMoneyParams.ts | 5 ++-- src/libs/actions/IOU.ts | 26 +++++++++--------- src/types/onyx/OriginalMessage.ts | 3 +-- 6 files changed, 45 insertions(+), 42 deletions(-) diff --git a/src/components/ButtonWithDropdownMenu.tsx b/src/components/ButtonWithDropdownMenu.tsx index 0e41da57b409..8aa3a5f0b9f0 100644 --- a/src/components/ButtonWithDropdownMenu.tsx +++ b/src/components/ButtonWithDropdownMenu.tsx @@ -10,17 +10,14 @@ import useWindowDimensions from '@hooks/useWindowDimensions'; import type {AnchorPosition} from '@styles/index'; import CONST from '@src/CONST'; import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; -import type DeepValueOf from '@src/types/utils/DeepValueOf'; import type IconAsset from '@src/types/utils/IconAsset'; import Button from './Button'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import PopoverMenu from './PopoverMenu'; -type PaymentType = DeepValueOf; - -type DropdownOption = { - value: PaymentType; +type DropdownOption = { + value: T; text: string; icon?: IconAsset; iconWidth?: number; @@ -28,15 +25,15 @@ type DropdownOption = { iconDescription?: string; }; -type ButtonWithDropdownMenuProps = { +type ButtonWithDropdownMenuProps = { /** Text to display for the menu header */ menuHeaderText?: string; /** Callback to execute when the main button is pressed */ - onPress: (event: GestureResponderEvent | KeyboardEvent | undefined, value: PaymentType) => void; + onPress: (event: GestureResponderEvent | KeyboardEvent | undefined, value: T) => void; /** Callback to execute when a dropdown option is selected */ - onOptionSelected?: (option: DropdownOption) => void; + onOptionSelected?: (option: DropdownOption) => void; /** Call the onPress function on main button when Enter key is pressed */ pressOnEnter?: boolean; @@ -55,19 +52,19 @@ type ButtonWithDropdownMenuProps = { /** Menu options to display */ /** e.g. [{text: 'Pay with Expensify', icon: Wallet}] */ - options: DropdownOption[]; + options: Array>; /** The anchor alignment of the popover menu */ anchorAlignment?: AnchorAlignment; /* ref for the button */ - buttonRef: RefObject; + buttonRef?: RefObject; /** The priority to assign the enter key event listener to buttons. 0 is the highest priority. */ enterKeyEventListenerPriority?: number; }; -function ButtonWithDropdownMenu({ +function ButtonWithDropdownMenu({ isLoading = false, isDisabled = false, pressOnEnter = false, @@ -83,7 +80,7 @@ function ButtonWithDropdownMenu({ options, onOptionSelected, enterKeyEventListenerPriority = 0, -}: ButtonWithDropdownMenuProps) { +}: ButtonWithDropdownMenuProps) { const theme = useTheme(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index d26bdc139f69..1fd94d4a5f4b 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -25,11 +25,12 @@ import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; -import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type {MileageRate} from '@src/types/onyx/Policy'; +import type DeepValueOf from '@src/types/utils/DeepValueOf'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; import ConfirmedRoute from './ConfirmedRoute'; import FormHelpMessage from './FormHelpMessage'; @@ -44,6 +45,11 @@ import Text from './Text'; import type {WithCurrentUserPersonalDetailsProps} from './withCurrentUserPersonalDetails'; import withCurrentUserPersonalDetails from './withCurrentUserPersonalDetails'; +type DropdownOption = { + text: string; + value: DeepValueOf; +}; + type Option = Partial; type CategorySection = { @@ -79,7 +85,7 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & onConfirm?: (selectedParticipants: Participant[]) => void; /** Callback to parent modal to send money */ - onSendMoney?: (paymentMethod: PaymentMethodType) => void; + onSendMoney?: (paymentMethod: IOU.PaymentMethodType) => void; /** Callback to inform a participant is selected */ onSelectParticipant?: (option: Participant) => void; @@ -130,7 +136,7 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & isReadOnly?: boolean; /** Depending on expense report or personal IOU report, respective bank account route */ - bankAccountRoute?: string; + bankAccountRoute?: Route; /** The policyID of the request */ policyID?: string; @@ -233,7 +239,7 @@ function MoneyRequestConfirmationList({ const shouldCalculateDistanceAmount = isDistanceRequest && iouAmount === 0; // A flag for showing the categories field - const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(policyCategories ?? {})); + const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories ?? {}))); // A flag and a toggler for showing the rest of the form fields const [shouldExpandFields, toggleShouldExpandFields] = useReducer((state) => !state, false); @@ -250,7 +256,7 @@ function MoneyRequestConfirmationList({ const policyTagList = policyTag?.tags ?? {}; const policyTagListName = policyTag?.name ?? translate('common.tag'); // A flag for showing the tags field - const shouldShowTags = isPolicyExpenseChat && (iouTag || OptionsListUtils.hasEnabledOptions(policyTagList)); + const shouldShowTags = isPolicyExpenseChat && (iouTag || OptionsListUtils.hasEnabledOptions(Object.values(policyTagList ?? {}))); // A flag for showing tax fields - tax rate and tax amount const shouldShowTax = isPolicyExpenseChat && policy?.isTaxTrackingEnabled; @@ -333,7 +339,7 @@ function MoneyRequestConfirmationList({ setDidConfirm(false); } - const splitOrRequestOptions = useMemo(() => { + const splitOrRequestOptions: DropdownOption[] = useMemo(() => { let text; if (isSplitBill && iouAmount === 0) { text = translate('iou.split'); @@ -368,7 +374,7 @@ function MoneyRequestConfirmationList({ if (!canModifyParticipantsValue) { formattedParticipantsList = formattedParticipantsList.map((participant) => ({ ...participant, - isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID), + isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID ?? -1), })); } @@ -396,7 +402,7 @@ function MoneyRequestConfirmationList({ } else { const formattedSelectedParticipants = selectedParticipants.map((participant) => ({ ...participant, - isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID), + isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID ?? -1), })); sections.push({ title: translate('common.to'), @@ -470,7 +476,7 @@ function MoneyRequestConfirmationList({ }; const confirm = useCallback( - (paymentMethod: PaymentMethodType) => { + (paymentMethod: IOU.PaymentMethodType | undefined) => { if (selectedParticipantsMemo.length === 0) { return; } @@ -555,7 +561,7 @@ function MoneyRequestConfirmationList({ pressOnEnter isDisabled={shouldDisableButton} // eslint-disable-next-line @typescript-eslint/naming-convention - onPress={(_, value) => confirm(value as PaymentMethodType)} + onPress={(_, value) => confirm(value as IOU.PaymentMethodType)} options={splitOrRequestOptions} buttonSize={CONST.DROPDOWN_BUTTON_SIZE.LARGE} enterKeyEventListenerPriority={1} @@ -796,6 +802,7 @@ function MoneyRequestConfirmationList({ ); return; } + Navigation.navigate(ROUTES.MONEY_REQUEST_TAG.getRoute(iouType, reportID)); }} style={styles.moneyRequestMenuItem} diff --git a/src/libs/API/parameters/PayMoneyRequestParams.ts b/src/libs/API/parameters/PayMoneyRequestParams.ts index 94f62bcca065..93117467f630 100644 --- a/src/libs/API/parameters/PayMoneyRequestParams.ts +++ b/src/libs/API/parameters/PayMoneyRequestParams.ts @@ -1,11 +1,10 @@ -import type CONST from '@src/CONST'; -import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import type {PaymentMethodType} from '@libs/actions/IOU'; type PayMoneyRequestParams = { iouReportID: string; chatReportID: string; reportActionID: string; - paymentMethodType: DeepValueOf; + paymentMethodType: PaymentMethodType; }; export default PayMoneyRequestParams; diff --git a/src/libs/API/parameters/SendMoneyParams.ts b/src/libs/API/parameters/SendMoneyParams.ts index c32287d5b4ec..e4faa8da5b8f 100644 --- a/src/libs/API/parameters/SendMoneyParams.ts +++ b/src/libs/API/parameters/SendMoneyParams.ts @@ -1,11 +1,10 @@ -import type CONST from '@src/CONST'; -import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import type {PaymentMethodType} from '@libs/actions/IOU'; type SendMoneyParams = { iouReportID: string; chatReportID: string; reportActionID: string; - paymentMethodType: DeepValueOf; + paymentMethodType: PaymentMethodType; transactionID: string; newIOUReportDetails: string; createdReportActionID: string; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 569b6b26b728..3444030240d2 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -63,7 +63,7 @@ type MoneyRequestRoute = StackScreenProps; -type PaymentMethodType = DeepValueOf; +type PaymentMethodType = DeepValueOf | typeof CONST.IOU.REPORT_ACTION_TYPE.APPROVE; type OneOnOneIOUReport = OnyxTypes.Report | undefined | null; @@ -3255,14 +3255,14 @@ function sendMoneyWithWallet(report: OnyxTypes.Report, amount: number, currency: Report.notifyNewAction(params.chatReportID, managerID); } -function approveMoneyRequest(expenseReport: OnyxTypes.Report) { - const currentNextStep = allNextSteps[`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`] ?? null; +function approveMoneyRequest(expenseReport: OnyxEntry | EmptyObject) { + const currentNextStep = allNextSteps[`${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport?.reportID}`] ?? null; - const optimisticApprovedReportAction = ReportUtils.buildOptimisticApprovedReportAction(expenseReport.total ?? 0, expenseReport.currency ?? '', expenseReport.reportID); + const optimisticApprovedReportAction = ReportUtils.buildOptimisticApprovedReportAction(expenseReport?.total ?? 0, expenseReport?.currency ?? '', expenseReport?.reportID ?? ''); const optimisticReportActionsData: OnyxUpdate = { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport?.reportID}`, value: { [optimisticApprovedReportAction.reportActionID]: { ...(optimisticApprovedReportAction as OnyxTypes.ReportAction), @@ -3272,7 +3272,7 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report) { }; const optimisticIOUReportData: OnyxUpdate = { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT}${expenseReport?.reportID}`, value: { ...expenseReport, lastMessageText: optimisticApprovedReportAction.message?.[0].text, @@ -3286,7 +3286,7 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report) { const successData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport?.reportID}`, value: { [optimisticApprovedReportAction.reportActionID]: { pendingAction: null, @@ -3298,9 +3298,9 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report) { const failureData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${expenseReport?.reportID}`, value: { - [expenseReport.reportActionID ?? '']: { + [expenseReport?.reportActionID ?? '']: { errors: ErrorUtils.getMicroSecondOnyxError('iou.error.other'), }, }, @@ -3310,18 +3310,18 @@ function approveMoneyRequest(expenseReport: OnyxTypes.Report) { if (currentNextStep) { optimisticData.push({ onyxMethod: Onyx.METHOD.SET, - key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport?.reportID}`, value: null, }); failureData.push({ onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport.reportID}`, + key: `${ONYXKEYS.COLLECTION.NEXT_STEP}${expenseReport?.reportID}`, value: currentNextStep, }); } const parameters: ApproveMoneyRequestParams = { - reportID: expenseReport.reportID, + reportID: expenseReport?.reportID ?? '', approvedReportActionID: optimisticApprovedReportAction.reportActionID, }; @@ -3730,3 +3730,5 @@ export { navigateToStartStepIfScanFileCannotBeRead, savePreferredPaymentMethod, }; + +export type {PaymentMethodType}; diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index fd28699e7b4c..34ac84989632 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -1,9 +1,8 @@ import type {ValueOf} from 'type-fest'; +import type {PaymentMethodType} from '@libs/actions/IOU'; import type CONST from '@src/CONST'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; -type PaymentMethodType = DeepValueOf; - type ActionName = DeepValueOf; type OriginalMessageActionName = | 'ADDCOMMENT' From 1da3d098f240ba878e7d737a7e32597ca04b1ae9 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 8 Feb 2024 14:30:53 +0100 Subject: [PATCH 060/202] fix: typecheck --- src/components/MoneyRequestConfirmationList.tsx | 4 ++-- src/components/SettlementButton.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 98d177a19e67..dbfce22030a2 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -85,7 +85,7 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & onConfirm?: (selectedParticipants: Participant[]) => void; /** Callback to parent modal to send money */ - onSendMoney?: (paymentMethod: IOU.PaymentMethodType) => void; + onSendMoney?: (paymentMethod: OnyxTypes.PaymentMethodType) => void; /** Callback to inform a participant is selected */ onSelectParticipant?: (option: Participant) => void; @@ -567,7 +567,7 @@ function MoneyRequestConfirmationList({ pressOnEnter isDisabled={shouldDisableButton} // eslint-disable-next-line @typescript-eslint/naming-convention - onPress={(_, value) => confirm(value as IOU.PaymentMethodType)} + onPress={(_, value) => confirm(value as OnyxTypes.PaymentMethodType)} options={splitOrRequestOptions} buttonSize={CONST.DROPDOWN_BUTTON_SIZE.LARGE} enterKeyEventListenerPriority={1} diff --git a/src/components/SettlementButton.tsx b/src/components/SettlementButton.tsx index 058def7a34ad..4e96684a65ec 100644 --- a/src/components/SettlementButton.tsx +++ b/src/components/SettlementButton.tsx @@ -226,10 +226,10 @@ function SettlementButton({ buttonRef={buttonRef} isDisabled={isDisabled} isLoading={isLoading} - onPress={(event, iouPaymentType) => selectPaymentType(event, iouPaymentType, triggerKYCFlow)} + onPress={(event, iouPaymentType) => selectPaymentType(event, iouPaymentType as PaymentMethodType, triggerKYCFlow)} pressOnEnter={pressOnEnter} options={paymentButtonOptions} - onOptionSelected={(option) => savePreferredPaymentMethod(policyID, option.value)} + onOptionSelected={(option) => savePreferredPaymentMethod(policyID, option.value as PaymentMethodType)} style={style} buttonSize={buttonSize} anchorAlignment={paymentMethodDropdownAnchorAlignment} From 5735f6163034bff9ad5b24adfbda21caaa132b9c Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 8 Feb 2024 18:40:53 +0100 Subject: [PATCH 061/202] fix: resolve comments --- src/components/AttachmentModal.tsx | 4 +- src/components/Composer/types.ts | 2 +- src/components/LocaleContextProvider.tsx | 2 +- src/libs/ComposerUtils/index.ts | 2 +- src/libs/EmojiUtils.ts | 2 +- .../home/report/ParticipantLocalTime.tsx | 13 +- .../AttachmentPickerWithMenuItems.tsx | 21 +-- .../ComposerWithSuggestions.tsx | 146 +++++++++--------- .../ComposerWithSuggestions/index.e2e.tsx | 2 +- .../ReportActionCompose.tsx | 4 +- .../report/ReportActionCompose/SendButton.tsx | 9 +- .../SilentCommentUpdater/index.android.tsx | 2 +- .../ReportActionCompose/SuggestionEmoji.tsx | 2 +- .../home/report/ReportTypingIndicator.tsx | 2 +- 14 files changed, 99 insertions(+), 114 deletions(-) diff --git a/src/components/AttachmentModal.tsx b/src/components/AttachmentModal.tsx index adf5b7b232a2..f97da9fcd9b7 100755 --- a/src/components/AttachmentModal.tsx +++ b/src/components/AttachmentModal.tsx @@ -80,7 +80,7 @@ type ImagePickerResponse = { type FileObject = File | ImagePickerResponse; type ChildrenProps = { - displayFileInModal: (data: FileObject | undefined) => void; + displayFileInModal: (data: FileObject) => void; show: () => void; }; @@ -317,7 +317,7 @@ function AttachmentModal({ }, []); const validateAndDisplayFileToUpload = useCallback( - (data: FileObject | undefined) => { + (data: FileObject) => { if (!data || !isDirectoryCheck(data)) { return; } diff --git a/src/components/Composer/types.ts b/src/components/Composer/types.ts index f19feb94dd0a..6bc44aba69cd 100644 --- a/src/components/Composer/types.ts +++ b/src/components/Composer/types.ts @@ -31,7 +31,7 @@ type ComposerProps = TextInputProps & { onNumberOfLinesChange?: (numberOfLines: number) => void; /** Callback method to handle pasting a file */ - onPasteFile?: (file?: File) => void; + onPasteFile?: (file: File) => void; /** General styles to apply to the text input */ // eslint-disable-next-line react/forbid-prop-types diff --git a/src/components/LocaleContextProvider.tsx b/src/components/LocaleContextProvider.tsx index 6d819f4d6eaa..eca433025f71 100644 --- a/src/components/LocaleContextProvider.tsx +++ b/src/components/LocaleContextProvider.tsx @@ -94,7 +94,7 @@ function LocaleContextProvider({preferredLocale, currentUserPersonalDetails = {} const updateLocale = useMemo(() => () => DateUtils.setLocale(locale), [locale]); - const formatPhoneNumber = useMemo(() => (phoneNumber) => LocalePhoneNumber.formatPhoneNumber(phoneNumber ?? ''), []); + const formatPhoneNumber = useMemo(() => (phoneNumber) => LocalePhoneNumber.formatPhoneNumber(phoneNumber), []); const toLocaleDigit = useMemo(() => (digit) => LocaleDigitUtils.toLocaleDigit(locale, digit), [locale]); diff --git a/src/libs/ComposerUtils/index.ts b/src/libs/ComposerUtils/index.ts index 6018cad86e47..94bba5d0d00c 100644 --- a/src/libs/ComposerUtils/index.ts +++ b/src/libs/ComposerUtils/index.ts @@ -19,7 +19,7 @@ function insertText(text: string, selection: Selection, textToInsert: string): s * @param text - text that needs whitespace to be appended to */ function insertWhiteSpaceAtIndex(text: string, index: number) { - return `${text?.slice(0, index)} ${text?.slice(index)}`; + return `${text.slice(0, index)} ${text.slice(index)}`; } /** diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index 05a1cb29141b..cab0f48d75fd 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -370,7 +370,7 @@ function replaceEmojis(text: string, preferredSkinTone: number = CONST.EMOJI_DEF * Find all emojis in a text and replace them with their code. */ function replaceAndExtractEmojis(text: string, preferredSkinTone: number = CONST.EMOJI_DEFAULT_SKIN_TONE, lang: Locale = CONST.LOCALES.DEFAULT): ReplacedEmoji { - const {text: convertedText = '', emojis = [], cursorPosition} = replaceEmojis(text ?? '', preferredSkinTone, lang); + const {text: convertedText = '', emojis = [], cursorPosition} = replaceEmojis(text, preferredSkinTone, lang); return { text: convertedText, diff --git a/src/pages/home/report/ParticipantLocalTime.tsx b/src/pages/home/report/ParticipantLocalTime.tsx index 58d85c0662b2..f51032690a33 100644 --- a/src/pages/home/report/ParticipantLocalTime.tsx +++ b/src/pages/home/report/ParticipantLocalTime.tsx @@ -12,16 +12,13 @@ import type {PersonalDetails} from '@src/types/onyx'; type ParticipantLocalTimeProps = { /** Personal details of the participant */ participant: PersonalDetails; - - /** The user's preferred locale e.g. 'en', 'es-ES' */ - preferredLocale?: Locale; }; -function getParticipantLocalTime(participant: PersonalDetails, preferredLocale: Locale | undefined) { +function getParticipantLocalTime(participant: PersonalDetails, preferredLocale: Locale) { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- Disabling this line for safeness as nullish coalescing works only if the value is undefined or null const reportRecipientTimezone = participant.timezone || CONST.DEFAULT_TIME_ZONE; - const reportTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale ?? CONST.LOCALES.DEFAULT, undefined, reportRecipientTimezone.selected); - const currentTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale ?? CONST.LOCALES.DEFAULT); + const reportTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale, undefined, reportRecipientTimezone.selected); + const currentTimezone = DateUtils.getLocalDateFromDatetime(preferredLocale); const reportRecipientDay = DateUtils.formatToDayOfWeek(reportTimezone); const currentUserDay = DateUtils.formatToDayOfWeek(currentTimezone); if (reportRecipientDay !== currentUserDay) { @@ -30,8 +27,8 @@ function getParticipantLocalTime(participant: PersonalDetails, preferredLocale: return `${DateUtils.formatToLocalTime(reportTimezone)}`; } -function ParticipantLocalTime({participant, preferredLocale}: ParticipantLocalTimeProps) { - const {translate} = useLocalize(); +function ParticipantLocalTime({participant}: ParticipantLocalTimeProps) { + const {translate, preferredLocale} = useLocalize(); const styles = useThemeStyles(); const [localTime, setLocalTime] = useState(() => getParticipantLocalTime(participant, preferredLocale)); diff --git a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index e6a75e6f157b..1ae8e63bd0f1 100644 --- a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx +++ b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -1,15 +1,14 @@ import {useIsFocused} from '@react-navigation/native'; -import type {FC} from 'react'; import React, {useCallback, useEffect, useMemo} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; -import type {SvgProps} from 'react-native-svg'; import type {ValueOf} from 'type-fest'; import type {FileObject} from '@components/AttachmentModal'; import AttachmentPicker from '@components/AttachmentPicker'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; +import type {PopoverMenuItem} from '@components/PopoverMenu'; import PopoverMenu from '@components/PopoverMenu'; import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import Tooltip from '@components/Tooltip/PopoverAnchorTooltip'; @@ -29,25 +28,19 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; -type MoneyRequestOption = { - icon: FC; - text: string; - onSelected: () => void; -}; - -type MoneyRequestOptions = Record, MoneyRequestOption>; +type MoneyRequestOptions = Record, PopoverMenuItem>; type AttachmentPickerWithMenuItemsOnyxProps = { /** The policy tied to the report */ policy: OnyxEntry; }; -type AttachmentPickerWithMenuItemsProps = { +type AttachmentPickerWithMenuItemsProps = AttachmentPickerWithMenuItemsOnyxProps & { /** The report currently being looked at */ report: OnyxEntry; /** Callback to open the file in the modal */ - displayFileInModal: (url: FileObject | undefined) => void; + displayFileInModal: (url: FileObject) => void; /** Whether or not the full size composer is available */ isFullComposerAvailable: boolean; @@ -59,7 +52,7 @@ type AttachmentPickerWithMenuItemsProps = { isBlockedFromConcierge: boolean; /** Whether or not the attachment picker is disabled */ - disabled: boolean; + disabled?: boolean; /** Sets the menu visibility */ setMenuVisibility: (isVisible: boolean) => void; @@ -93,7 +86,7 @@ type AttachmentPickerWithMenuItemsProps = { /** The personal details of everyone in the report */ reportParticipantIDs?: number[]; -} & AttachmentPickerWithMenuItemsOnyxProps; +}; /** * This includes the popover of options you see when pressing the + button in the composer. @@ -155,7 +148,7 @@ function AttachmentPickerWithMenuItems({ /** * Determines if we can show the task option */ - const taskOption: MoneyRequestOption[] = useMemo(() => { + const taskOption: PopoverMenuItem[] = useMemo(() => { if (!ReportUtils.canCreateTaskInReport(report)) { return []; } diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index b54ccaf20518..6b89a591055a 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -78,99 +78,99 @@ type ComposerWithSuggestionsOnyxProps = { editFocused: OnyxEntry; }; -type ComposerWithSuggestionsProps = { - /** Report ID */ - reportID: string; +type ComposerWithSuggestionsProps = ComposerWithSuggestionsOnyxProps & + Partial & { + /** Report ID */ + reportID: string; - /** Callback to focus composer */ - onFocus: () => void; + /** Callback to focus composer */ + onFocus: () => void; - /** Callback to blur composer */ - onBlur: (event: NativeSyntheticEvent) => void; + /** Callback to blur composer */ + onBlur: (event: NativeSyntheticEvent) => void; - /** Callback to update the value of the composer */ - onValueChange: (value: string) => void; + /** Callback to update the value of the composer */ + onValueChange: (value: string) => void; - /** Whether the composer is full size */ - isComposerFullSize: boolean; + /** Whether the composer is full size */ + isComposerFullSize: boolean; - /** Whether the menu is visible */ - isMenuVisible: boolean; + /** Whether the menu is visible */ + isMenuVisible: boolean; - /** The placeholder for the input */ - inputPlaceholder: string; + /** The placeholder for the input */ + inputPlaceholder: string; - /** Function to display a file in a modal */ - displayFileInModal: (file: FileObject | undefined) => void; + /** Function to display a file in a modal */ + displayFileInModal: (file: FileObject) => void; - /** Whether the text input should clear */ - textInputShouldClear: boolean; + /** Whether the text input should clear */ + textInputShouldClear: boolean; - /** Function to set the text input should clear */ - setTextInputShouldClear: (shouldClear: boolean) => void; + /** Function to set the text input should clear */ + setTextInputShouldClear: (shouldClear: boolean) => void; - /** Whether the user is blocked from concierge */ - isBlockedFromConcierge: boolean; + /** Whether the user is blocked from concierge */ + isBlockedFromConcierge: boolean; - /** Whether the input is disabled */ - disabled: boolean; + /** Whether the input is disabled */ + disabled: boolean; - /** Whether the full composer is available */ - isFullComposerAvailable: boolean; + /** Whether the full composer is available */ + isFullComposerAvailable: boolean; - /** Function to set whether the full composer is available */ - setIsFullComposerAvailable: (isFullComposerAvailable: boolean) => void; + /** Function to set whether the full composer is available */ + setIsFullComposerAvailable: (isFullComposerAvailable: boolean) => void; - /** Function to set whether the comment is empty */ - setIsCommentEmpty: (isCommentEmpty: boolean) => void; + /** Function to set whether the comment is empty */ + setIsCommentEmpty: (isCommentEmpty: boolean) => void; - /** Function to handle sending a message */ - handleSendMessage: () => void; + /** Function to handle sending a message */ + handleSendMessage: () => void; - /** Whether the compose input should show */ - shouldShowComposeInput: OnyxEntry; + /** Whether the compose input should show */ + shouldShowComposeInput: OnyxEntry; - /** Function to measure the parent container */ - measureParentContainer: (callback: MeasureInWindowOnSuccessCallback) => void; + /** Function to measure the parent container */ + measureParentContainer: (callback: MeasureInWindowOnSuccessCallback) => void; - /** The height of the list */ - listHeight: number; + /** The height of the list */ + listHeight: number; - /** Whether the scroll is likely to trigger a layout */ - isScrollLikelyLayoutTriggered: RefObject; + /** Whether the scroll is likely to trigger a layout */ + isScrollLikelyLayoutTriggered: RefObject; - /** Function to raise the scroll is likely layout triggered */ - raiseIsScrollLikelyLayoutTriggered: () => void; + /** Function to raise the scroll is likely layout triggered */ + raiseIsScrollLikelyLayoutTriggered: () => void; - /** The ref to the suggestions */ - suggestionsRef: React.RefObject; + /** The ref to the suggestions */ + suggestionsRef: React.RefObject; - /** The ref to the animated input */ - animatedRef: AnimatedRef; + /** The ref to the animated input */ + animatedRef: AnimatedRef; - /** The ref to the next modal will open */ - isNextModalWillOpenRef: MutableRefObject; + /** The ref to the next modal will open */ + isNextModalWillOpenRef: MutableRefObject; - /** Whether the edit is focused */ - editFocused: boolean; + /** Whether the edit is focused */ + editFocused: boolean; - /** Wheater chat is empty */ - isEmptyChat?: boolean; + /** Wheater chat is empty */ + isEmptyChat?: boolean; - /** The last report action */ - lastReportAction?: OnyxTypes.ReportAction; + /** The last report action */ + lastReportAction?: OnyxTypes.ReportAction; - /** Whether to include chronos */ - includeChronos?: boolean; + /** Whether to include chronos */ + includeChronos?: boolean; - /** The parent report action ID */ - parentReportActionID?: string; + /** The parent report action ID */ + parentReportActionID?: string; - /** The parent report ID */ - // eslint-disable-next-line react/no-unused-prop-types - parentReportID: string | undefined; -} & ComposerWithSuggestionsOnyxProps & - Partial; + /** The parent report ID */ + // eslint-disable-next-line react/no-unused-prop-types -- its used in the withOnyx HOC + parentReportID: string | undefined; + }; const {RNTextInputReset} = NativeModules; @@ -240,7 +240,7 @@ function ComposerWithSuggestions( // For testing children, }: ComposerWithSuggestionsProps, - ref: ForwardedRef, + ref: ForwardedRef, ) { const {isKeyboardShown} = useKeyboardState(); const theme = useTheme(); @@ -340,24 +340,24 @@ function ComposerWithSuggestions( let currentIndex = 0; // Find the first character mismatch with newText - while (currentIndex < newText.length && prevText.charAt(currentIndex) === newText?.charAt(currentIndex) && selection.start > currentIndex) { + while (currentIndex < newText.length && prevText.charAt(currentIndex) === newText.charAt(currentIndex) && selection.start > currentIndex) { currentIndex++; } - if (currentIndex < (newText?.length ?? 0)) { + if (currentIndex < newText.length) { startIndex = currentIndex; - const commonSuffixLength = ComposerUtils.findCommonSuffixLength(prevText, newText ?? '', selection.end); + const commonSuffixLength = ComposerUtils.findCommonSuffixLength(prevText, newText, selection.end); // if text is getting pasted over find length of common suffix and subtract it from new text length if (commonSuffixLength > 0 || selection.end - selection.start > 0) { - endIndex = (newText?.length ?? 0) - commonSuffixLength; + endIndex = newText.length - commonSuffixLength; } else { - endIndex = currentIndex + (newText?.length ?? 0); + endIndex = currentIndex + newText.length; } } return { startIndex, endIndex, - diff: newText?.substring(startIndex, endIndex) ?? '', + diff: newText.substring(startIndex, endIndex), }; }, [selection.start, selection.end], @@ -375,7 +375,7 @@ function ComposerWithSuggestions( text: newComment, emojis, cursorPosition, - } = EmojiUtils.replaceAndExtractEmojis(isEmojiInserted ? ComposerUtils.insertWhiteSpaceAtIndex(commentValue, endIndex) : commentValue ?? '', preferredSkinTone, preferredLocale); + } = EmojiUtils.replaceAndExtractEmojis(isEmojiInserted ? ComposerUtils.insertWhiteSpaceAtIndex(commentValue, endIndex) : commentValue, preferredSkinTone, preferredLocale); if (emojis.length) { const newEmojis = EmojiUtils.getAddedEmojis(emojis, emojisPresentBefore.current); if (newEmojis.length) { @@ -748,7 +748,7 @@ function ComposerWithSuggestions( isComposerFullSize={isComposerFullSize} value={value} testID="composer" - numberOfLines={numberOfLines ?? 0} + numberOfLines={numberOfLines ?? undefined} onNumberOfLinesChange={updateNumberOfLines} shouldCalculateCaretPosition onLayout={onLayout} diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx index 0fa535329d33..7f169ef15918 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/index.e2e.tsx @@ -16,7 +16,7 @@ function IncrementRenderCount() { return null; } -function ComposerWithSuggestionsE2e(props: ComposerWithSuggestionsProps, ref: ForwardedRef) { +function ComposerWithSuggestionsE2e(props: ComposerWithSuggestionsProps, ref: ForwardedRef) { // Eventually Auto focus on e2e tests useEffect(() => { const testConfig = E2EClient.getCurrentActiveTestConfig(); diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 98630ff88b23..283f0dfab18f 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -289,9 +289,7 @@ function ReportActionCompose({ */ const submitForm = useCallback( (event?: SyntheticEvent) => { - if (event) { - event.preventDefault(); - } + event?.preventDefault(); const newComment = composerRef.current?.prepareCommentAndResetComposer(); if (!newComment) { diff --git a/src/pages/home/report/ReportActionCompose/SendButton.tsx b/src/pages/home/report/ReportActionCompose/SendButton.tsx index 4726c1638f42..c505eb0e32e7 100644 --- a/src/pages/home/report/ReportActionCompose/SendButton.tsx +++ b/src/pages/home/report/ReportActionCompose/SendButton.tsx @@ -23,12 +23,9 @@ function SendButton({isDisabled: isDisabledProp, handleSendMessage}: SendButtonP const styles = useThemeStyles(); const {translate} = useLocalize(); - const Tap = Gesture.Tap() - // @ts-expect-error Enabled require argument but when passing something button is not working - .enabled() - .onEnd(() => { - handleSendMessage(); - }); + const Tap = Gesture.Tap().onEnd(() => { + handleSendMessage(); + }); return ( { updateComment(comment ?? ''); // eslint-disable-next-line react-hooks/exhaustive-deps -- We need to run this on mount diff --git a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx index 206c91ed9b08..0ae45d2d705d 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionEmoji.tsx @@ -28,7 +28,7 @@ type SuggestionEmojiOnyxProps = { type SuggestionEmojiProps = SuggestionProps & SuggestionEmojiOnyxProps & { /** Function to clear the input */ - resetKeyboardInput: (() => void) | undefined; + resetKeyboardInput?: () => void; }; /** diff --git a/src/pages/home/report/ReportTypingIndicator.tsx b/src/pages/home/report/ReportTypingIndicator.tsx index e484ce9886a7..3ff8f2b0eb8e 100755 --- a/src/pages/home/report/ReportTypingIndicator.tsx +++ b/src/pages/home/report/ReportTypingIndicator.tsx @@ -41,7 +41,7 @@ function ReportTypingIndicator({userTypingStatuses}: ReportTypingIndicatorProps) if (usersTyping.length === 1) { return ( Date: Fri, 9 Feb 2024 16:32:51 +0100 Subject: [PATCH 062/202] fix: conflicts --- src/libs/NextStepUtils.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts index 3b42382b10f9..e99f2c2ef8a1 100644 --- a/src/libs/NextStepUtils.ts +++ b/src/libs/NextStepUtils.ts @@ -1,5 +1,6 @@ import {format, lastDayOfMonth, setDate} from 'date-fns'; import Str from 'expensify-common/lib/str'; +import type {OnyxEntry} from 'react-native-onyx'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; @@ -62,18 +63,21 @@ type BuildNextStepParameters = { * @param parameters.isPaidWithWallet - Whether a report has been paid with the wallet or outside of Expensify * @returns nextStep */ -function buildNextStep(report: Report | EmptyObject, predictedNextStatus: ValueOf, {isPaidWithWallet}: BuildNextStepParameters = {}): ReportNextStep | null { +function buildNextStep( + report: OnyxEntry | EmptyObject, + predictedNextStatus: ValueOf, + {isPaidWithWallet}: BuildNextStepParameters = {}, +): ReportNextStep | null { if (!ReportUtils.isExpenseReport(report)) { return null; } - const {policyID = '', ownerAccountID = -1, managerID = -1} = report; - const policy = ReportUtils.getPolicy(policyID); + const policy = ReportUtils.getPolicy(report?.policyID); const {submitsTo, harvesting, isPreventSelfApprovalEnabled, autoReportingFrequency, autoReportingOffset} = policy; - const isOwner = currentUserAccountID === ownerAccountID; - const isManager = currentUserAccountID === managerID; + const isOwner = currentUserAccountID === report?.ownerAccountID; + const isManager = currentUserAccountID === report?.managerID; const isSelfApproval = currentUserAccountID === submitsTo; - const ownerLogin = PersonalDetailsUtils.getLoginsByAccountIDs([ownerAccountID])[0] ?? ''; + const ownerLogin = PersonalDetailsUtils.getLoginsByAccountIDs([report?.ownerAccountID ?? -1])[0] ?? ''; const managerDisplayName = isSelfApproval ? 'you' : ReportUtils.getDisplayNameForParticipant(submitsTo) ?? ''; const type: ReportNextStep['type'] = 'neutral'; let optimisticNextStep: ReportNextStep | null; From 734d6d0e6e42929caa33c9b629f9555efd69f3b0 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Fri, 9 Feb 2024 17:08:30 +0100 Subject: [PATCH 063/202] migrate markdownTable --- .../{markdownTable.js => markdownTable.ts} | 349 +++++++++--------- 1 file changed, 169 insertions(+), 180 deletions(-) rename tests/e2e/compare/output/{markdownTable.js => markdownTable.ts} (54%) diff --git a/tests/e2e/compare/output/markdownTable.js b/tests/e2e/compare/output/markdownTable.ts similarity index 54% rename from tests/e2e/compare/output/markdownTable.js rename to tests/e2e/compare/output/markdownTable.ts index 3b580bcfc116..eea4297048ad 100644 --- a/tests/e2e/compare/output/markdownTable.js +++ b/tests/e2e/compare/output/markdownTable.ts @@ -1,150 +1,158 @@ /* eslint-disable */ // copied from https://raw.githubusercontent.com/wooorm/markdown-table/main/index.js, turned into cmjs -/** - * @typedef Options - * Configuration (optional). - * @property {string|null|Array} [align] - * One style for all columns, or styles for their respective columns. - * Each style is either `'l'` (left), `'r'` (right), or `'c'` (center). - * Other values are treated as `''`, which doesn’t place the colon in the - * alignment row but does align left. - * *Only the lowercased first character is used, so `Right` is fine.* - * @property {boolean} [padding=true] - * Whether to add a space of padding between delimiters and cells. - * - * When `true`, there is padding: - * - * ```markdown - * | Alpha | B | - * | ----- | ----- | - * | C | Delta | - * ``` - * - * When `false`, there is no padding: - * - * ```markdown - * |Alpha|B | - * |-----|-----| - * |C |Delta| - * ``` - * @property {boolean} [delimiterStart=true] - * Whether to begin each row with the delimiter. - * - * > 👉 **Note**: please don’t use this: it could create fragile structures - * > that aren’t understandable to some markdown parsers. - * - * When `true`, there are starting delimiters: - * - * ```markdown - * | Alpha | B | - * | ----- | ----- | - * | C | Delta | - * ``` - * - * When `false`, there are no starting delimiters: - * - * ```markdown - * Alpha | B | - * ----- | ----- | - * C | Delta | - * ``` - * @property {boolean} [delimiterEnd=true] - * Whether to end each row with the delimiter. - * - * > 👉 **Note**: please don’t use this: it could create fragile structures - * > that aren’t understandable to some markdown parsers. - * - * When `true`, there are ending delimiters: - * - * ```markdown - * | Alpha | B | - * | ----- | ----- | - * | C | Delta | - * ``` - * - * When `false`, there are no ending delimiters: - * - * ```markdown - * | Alpha | B - * | ----- | ----- - * | C | Delta - * ``` - * @property {boolean} [alignDelimiters=true] - * Whether to align the delimiters. - * By default, they are aligned: - * - * ```markdown - * | Alpha | B | - * | ----- | ----- | - * | C | Delta | - * ``` - * - * Pass `false` to make them staggered: - * - * ```markdown - * | Alpha | B | - * | - | - | - * | C | Delta | - * ``` - * @property {(value: string) => number} [stringLength] - * Function to detect the length of table cell content. - * This is used when aligning the delimiters (`|`) between table cells. - * Full-width characters and emoji mess up delimiter alignment when viewing - * the markdown source. - * To fix this, you can pass this function, which receives the cell content - * and returns its “visible” size. - * Note that what is and isn’t visible depends on where the text is displayed. - * - * Without such a function, the following: - * - * ```js - * markdownTable([ - * ['Alpha', 'Bravo'], - * ['中文', 'Charlie'], - * ['👩‍❤️‍👩', 'Delta'] - * ]) - * ``` - * - * Yields: - * - * ```markdown - * | Alpha | Bravo | - * | - | - | - * | 中文 | Charlie | - * | 👩‍❤️‍👩 | Delta | - * ``` - * - * With [`string-width`](https://github.com/sindresorhus/string-width): - * - * ```js - * import stringWidth from 'string-width' - * - * markdownTable( - * [ - * ['Alpha', 'Bravo'], - * ['中文', 'Charlie'], - * ['👩‍❤️‍👩', 'Delta'] - * ], - * {stringLength: stringWidth} - * ) - * ``` - * - * Yields: - * - * ```markdown - * | Alpha | Bravo | - * | ----- | ------- | - * | 中文 | Charlie | - * | 👩‍❤️‍👩 | Delta | - * ``` - */ - -/** - * @typedef {Options} MarkdownTableOptions - * @todo - * Remove next major. - */ +type MarkdownTableOptions = { + /** + * One style for all columns, or styles for their respective columns. + * Each style is either `'l'` (left), `'r'` (right), or `'c'` (center). + * Other values are treated as `''`, which doesn’t place the colon in the + * alignment row but does align left. + * *Only the lowercased first character is used, so `Right` is fine.* + */ + align?: string | null | Array; + + /** + * Whether to add a space of padding between delimiters and cells. + * + * When `true`, there is padding: + * + * ```markdown + * | Alpha | B | + * | ----- | ----- | + * | C | Delta | + * ``` + * + * When `false`, there is no padding: + * + * ```markdown + * |Alpha|B | + * |-----|-----| + * |C |Delta| + * ``` + */ + padding?: boolean; + + /** + * Whether to begin each row with the delimiter. + * + * > 👉 **Note**: please don’t use this: it could create fragile structures + * > that aren’t understandable to some markdown parsers. + * + * When `true`, there are starting delimiters: + * + * ```markdown + * | Alpha | B | + * | ----- | ----- | + * | C | Delta | + * ``` + * + * When `false`, there are no starting delimiters: + * + * ```markdown + * Alpha | B | + * ----- | ----- | + * C | Delta | + * ``` + */ + delimiterStart?: boolean; + /** + * Whether to end each row with the delimiter. + * + * > 👉 **Note**: please don’t use this: it could create fragile structures + * > that aren’t understandable to some markdown parsers. + * + * When `true`, there are ending delimiters: + * + * ```markdown + * | Alpha | B | + * | ----- | ----- | + * | C | Delta | + * ``` + * + * When `false`, there are no ending delimiters: + * + * ```markdown + * | Alpha | B + * | ----- | ----- + * | C | Delta + * ``` + */ + delimiterEnd?: boolean; + + /** + * Whether to align the delimiters. + * By default, they are aligned: + * + * ```markdown + * | Alpha | B | + * | ----- | ----- | + * | C | Delta | + * ``` + * + * Pass `false` to make them staggered: + * + * ```markdown + * | Alpha | B | + * | - | - | + * | C | Delta | + * ``` + */ + alignDelimiters?: boolean; + + /** + * Function to detect the length of table cell content. + * This is used when aligning the delimiters (`|`) between table cells. + * Full-width characters and emoji mess up delimiter alignment when viewing + * the markdown source. + * To fix this, you can pass this function, which receives the cell content + * and returns its “visible” size. + * Note that what is and isn’t visible depends on where the text is displayed. + * + * Without such a function, the following: + * + * ```js + * markdownTable([ + * ['Alpha', 'Bravo'], + * ['中文', 'Charlie'], + * ['👩‍❤️‍👩', 'Delta'] + * ]) + * ``` + * + * Yields: + * + * ```markdown + * | Alpha | Bravo | + * | - | - | + * | 中文 | Charlie | + * | 👩‍❤️‍👩 | Delta | + * ``` + * + * With [`string-width`](https://github.com/sindresorhus/string-width): + * + * ```js + * import stringWidth from 'string-width' + * + * markdownTable( + * [ + * ['Alpha', 'Bravo'], + * ['中文', 'Charlie'], + * ['👩‍❤️‍👩', 'Delta'] + * ], + * {stringLength: stringWidth} + * ) + * ``` + * + * Yields: + * + * ```markdown + * | Alpha | Bravo | + * | ----- | ------- | + * | 中文 | Charlie | + * | 👩‍❤️‍👩 | Delta | + * ``` + */ + stringLength?: (value: string) => number; +}; /** * Generate a markdown ([GFM](https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/organizing-information-with-tables)) table.. @@ -155,27 +163,24 @@ * Configuration (optional). * @returns {string} */ -function markdownTable(table, options = {}) { +function markdownTable(table: Array>, options: MarkdownTableOptions = {}) { const align = (options.align || []).concat(); const stringLength = options.stringLength || defaultStringLength; - /** @type {Array} Character codes as symbols for alignment per column. */ - const alignments = []; - /** @type {Array>} Cells per row. */ - const cellMatrix = []; - /** @type {Array>} Sizes of each cell per row. */ - const sizeMatrix = []; - /** @type {Array} */ - const longestCellByColumn = []; + /** Character codes as symbols for alignment per column. */ + const alignments: Array = []; + /** Cells per row. */ + const cellMatrix: Array> = []; + /** Sizes of each cell per row. */ + const sizeMatrix: Array> = []; + const longestCellByColumn: Array = []; let mostCellsPerRow = 0; let rowIndex = -1; // This is a superfluous loop if we don’t align delimiters, but otherwise we’d // do superfluous work when aligning, so optimize for aligning. while (++rowIndex < table.length) { - /** @type {Array} */ - const row = []; - /** @type {Array} */ - const sizes = []; + const row: Array = []; + const sizes: Array = []; let columnIndex = -1; if (table[rowIndex].length > mostCellsPerRow) { @@ -218,10 +223,8 @@ function markdownTable(table, options = {}) { // Inject the alignment row. columnIndex = -1; - /** @type {Array} */ - const row = []; - /** @type {Array} */ - const sizes = []; + const row: Array = []; + const sizes: Array = []; while (++columnIndex < mostCellsPerRow) { const code = alignments[columnIndex]; @@ -260,15 +263,13 @@ function markdownTable(table, options = {}) { sizeMatrix.splice(1, 0, sizes); rowIndex = -1; - /** @type {Array} */ - const lines = []; + const lines: Array = []; while (++rowIndex < cellMatrix.length) { const row = cellMatrix[rowIndex]; const sizes = sizeMatrix[rowIndex]; columnIndex = -1; - /** @type {Array} */ - const line = []; + const line: Array = []; while (++columnIndex < mostCellsPerRow) { const cell = row[columnIndex] || ''; @@ -333,27 +334,15 @@ function markdownTable(table, options = {}) { return lines.join('\n'); } -/** - * @param {string|null|undefined} [value] - * @returns {string} - */ -function serialize(value) { +function serialize(value: string | null | undefined): string { return value === null || value === undefined ? '' : String(value); } -/** - * @param {string} value - * @returns {number} - */ -function defaultStringLength(value) { +function defaultStringLength(value: string): number { return value.length; } -/** - * @param {string|null|undefined} value - * @returns {number} - */ -function toAlignment(value) { +function toAlignment(value: string | null | undefined): number { const code = typeof value === 'string' ? value.codePointAt(0) : 0; return code === 67 /* `C` */ || code === 99 /* `c` */ From 9e2f5125573999601a33e3e0abb443307dd4dde9 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Fri, 9 Feb 2024 17:39:53 +0100 Subject: [PATCH 064/202] switch from module export to export default --- tests/e2e/compare/output/markdownTable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/compare/output/markdownTable.ts b/tests/e2e/compare/output/markdownTable.ts index eea4297048ad..a22e0a5d3366 100644 --- a/tests/e2e/compare/output/markdownTable.ts +++ b/tests/e2e/compare/output/markdownTable.ts @@ -354,4 +354,4 @@ function toAlignment(value: string | null | undefined): number { : 0; } -module.exports = markdownTable; +export default markdownTable; From f69fce5038eb5366ec3ada2f96050edc13382306 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 12 Feb 2024 09:52:40 +0100 Subject: [PATCH 065/202] fix: typecheck --- src/libs/OptionsListUtils.ts | 1 + src/types/onyx/index.ts | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libs/OptionsListUtils.ts b/src/libs/OptionsListUtils.ts index 8a96c2a8705c..863970dbda30 100644 --- a/src/libs/OptionsListUtils.ts +++ b/src/libs/OptionsListUtils.ts @@ -30,6 +30,7 @@ import type {Participant} from '@src/types/onyx/IOU'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {PolicyTaxRate, PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import times from '@src/utils/times'; import Timing from './actions/Timing'; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 6343b9a1b2ec..51e772c0d173 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -50,6 +50,7 @@ import type {PolicyMembers} from './PolicyMember'; import type PolicyMember from './PolicyMember'; import type {PolicyReportField, PolicyReportFields} from './PolicyReportField'; import type {PolicyTag, PolicyTagList, PolicyTags} from './PolicyTag'; +import type {PolicyTaxRate, PolicyTaxRates} from './PolicyTaxRates'; import type PrivatePersonalDetails from './PrivatePersonalDetails'; import type RecentlyUsedCategories from './RecentlyUsedCategories'; import type RecentlyUsedReportFields from './RecentlyUsedReportFields'; @@ -169,8 +170,6 @@ export type { PolicyReportField, PolicyReportFields, RecentlyUsedReportFields, - PolicyTaxRate, - PolicyTaxRates, LastPaymentMethod, NewRoomForm, IKnowATeacherForm, @@ -180,4 +179,6 @@ export type { ReportFieldEditForm, RoomNameForm, PaymentMethodType, + PolicyTaxRate, + PolicyTaxRates, }; From a13ecf200b13e6796097a96d3d0541b9b1ea87bb Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Mon, 12 Feb 2024 10:49:44 +0100 Subject: [PATCH 066/202] fix PR comments --- tests/e2e/compare/output/markdownTable.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/e2e/compare/output/markdownTable.ts b/tests/e2e/compare/output/markdownTable.ts index a22e0a5d3366..e22325e4d8d1 100644 --- a/tests/e2e/compare/output/markdownTable.ts +++ b/tests/e2e/compare/output/markdownTable.ts @@ -167,20 +167,20 @@ function markdownTable(table: Array>, options: const align = (options.align || []).concat(); const stringLength = options.stringLength || defaultStringLength; /** Character codes as symbols for alignment per column. */ - const alignments: Array = []; + const alignments: number[] = []; /** Cells per row. */ const cellMatrix: Array> = []; /** Sizes of each cell per row. */ const sizeMatrix: Array> = []; - const longestCellByColumn: Array = []; + const longestCellByColumn: number[] = []; let mostCellsPerRow = 0; let rowIndex = -1; // This is a superfluous loop if we don’t align delimiters, but otherwise we’d // do superfluous work when aligning, so optimize for aligning. while (++rowIndex < table.length) { - const row: Array = []; - const sizes: Array = []; + const row: string[] = []; + const sizes: number[] = []; let columnIndex = -1; if (table[rowIndex].length > mostCellsPerRow) { @@ -223,8 +223,8 @@ function markdownTable(table: Array>, options: // Inject the alignment row. columnIndex = -1; - const row: Array = []; - const sizes: Array = []; + const row: string[] = []; + const sizes: number[] = []; while (++columnIndex < mostCellsPerRow) { const code = alignments[columnIndex]; @@ -263,13 +263,13 @@ function markdownTable(table: Array>, options: sizeMatrix.splice(1, 0, sizes); rowIndex = -1; - const lines: Array = []; + const lines: string[] = []; while (++rowIndex < cellMatrix.length) { const row = cellMatrix[rowIndex]; const sizes = sizeMatrix[rowIndex]; columnIndex = -1; - const line: Array = []; + const line: string[] = []; while (++columnIndex < mostCellsPerRow) { const cell = row[columnIndex] || ''; From 6a1c420f09e029ecdf7f3e0e278f9a4730a7b04e Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 13 Feb 2024 16:06:00 +0530 Subject: [PATCH 067/202] fix form default behavior --- src/components/Form/FormWrapper.tsx | 3 ++ .../SignInPageForm/index.native.tsx | 12 ----- src/components/SignInPageForm/index.tsx | 49 ------------------- src/components/SignInPageForm/types.ts | 5 -- .../usePreventFormDefault/index.native.ts | 3 ++ src/hooks/usePreventFormDefault/index.ts | 33 +++++++++++++ .../SignInPageLayout/SignInPageContent.js | 13 +++-- 7 files changed, 49 insertions(+), 69 deletions(-) delete mode 100644 src/components/SignInPageForm/index.native.tsx delete mode 100644 src/components/SignInPageForm/index.tsx delete mode 100644 src/components/SignInPageForm/types.ts create mode 100644 src/hooks/usePreventFormDefault/index.native.ts create mode 100644 src/hooks/usePreventFormDefault/index.ts diff --git a/src/components/Form/FormWrapper.tsx b/src/components/Form/FormWrapper.tsx index e8778cf25d58..2e100bb52d81 100644 --- a/src/components/Form/FormWrapper.tsx +++ b/src/components/Form/FormWrapper.tsx @@ -9,6 +9,7 @@ import FormElement from '@components/FormElement'; import SafeAreaConsumer from '@components/SafeAreaConsumer'; import type {SafeAreaChildrenProps} from '@components/SafeAreaConsumer/types'; import ScrollViewWithContext from '@components/ScrollViewWithContext'; +import usePreventFormDefault from '@hooks/usePreventFormDefault'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import type {Form} from '@src/types/onyx'; @@ -65,6 +66,8 @@ function FormWrapper({ const formContentRef = useRef(null); const errorMessage = useMemo(() => (formState ? ErrorUtils.getLatestErrorMessage(formState) : undefined), [formState]); + usePreventFormDefault(formContentRef.current); + const onFixTheErrorsLinkPressed = useCallback(() => { const errorFields = !isEmptyObject(errors) ? errors : formState?.errorFields ?? {}; const focusKey = Object.keys(inputRefs.current ?? {}).find((key) => Object.keys(errorFields).includes(key)); diff --git a/src/components/SignInPageForm/index.native.tsx b/src/components/SignInPageForm/index.native.tsx deleted file mode 100644 index 0d00c754d45a..000000000000 --- a/src/components/SignInPageForm/index.native.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import FormElement from '@components/FormElement'; -import type SignInPageFormProps from './types'; - -function SignInPageForm(props: SignInPageFormProps) { - // eslint-disable-next-line react/jsx-props-no-spreading - return ; -} - -SignInPageForm.displayName = 'SignInPageForm'; - -export default SignInPageForm; diff --git a/src/components/SignInPageForm/index.tsx b/src/components/SignInPageForm/index.tsx deleted file mode 100644 index b9f0fe202dd1..000000000000 --- a/src/components/SignInPageForm/index.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React, {useEffect, useRef} from 'react'; -import type {View} from 'react-native'; -import FormElement from '@components/FormElement'; -import type SignInPageFormProps from './types'; - -const preventFormDefault = (event: SubmitEvent) => { - // 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 SignInPageForm(props: SignInPageFormProps) { - const form = useRef(null); - - useEffect(() => { - const formCurrent = form.current; - - if (!formCurrent) { - return; - } - - // 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); - - return () => { - if (!formCurrent) { - return; - } - formCurrent.removeEventListener('submit', preventFormDefault); - }; - }, []); - - return ( - - ); -} - -SignInPageForm.displayName = 'SignInPageForm'; - -export default SignInPageForm; diff --git a/src/components/SignInPageForm/types.ts b/src/components/SignInPageForm/types.ts deleted file mode 100644 index c7f71a3f7151..000000000000 --- a/src/components/SignInPageForm/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type {ViewProps} from 'react-native'; - -type SignInPageFormProps = ViewProps; - -export default SignInPageFormProps; diff --git a/src/hooks/usePreventFormDefault/index.native.ts b/src/hooks/usePreventFormDefault/index.native.ts new file mode 100644 index 000000000000..36223555e588 --- /dev/null +++ b/src/hooks/usePreventFormDefault/index.native.ts @@ -0,0 +1,3 @@ +const usePreventFormDefault = () => {}; + +export default usePreventFormDefault; diff --git a/src/hooks/usePreventFormDefault/index.ts b/src/hooks/usePreventFormDefault/index.ts new file mode 100644 index 000000000000..6c60ca0f95c2 --- /dev/null +++ b/src/hooks/usePreventFormDefault/index.ts @@ -0,0 +1,33 @@ +import {useEffect} from 'react'; +import type {View} from 'react-native'; + +const preventFormDefault = (event: SubmitEvent) => { + // 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(); +}; + +const usePreventFormDefault = (form: View | null) => { + useEffect(() => { + if (!form) { + return; + } + + // This is a safe cast because we know that form is a HTMLFormElement. + const formElement = form as unknown as HTMLFormElement; + + // Prevent the browser from applying its own validation, which affects the email input + formElement.setAttribute('novalidate', ''); + + // Password Managers need these attributes to be able to identify the form elements properly. + formElement.setAttribute('method', 'post'); + formElement.setAttribute('action', '/'); + formElement.addEventListener('submit', preventFormDefault); + + return () => { + formElement.removeEventListener('submit', preventFormDefault); + }; + }, [form]); +}; + +export default usePreventFormDefault; diff --git a/src/pages/signin/SignInPageLayout/SignInPageContent.js b/src/pages/signin/SignInPageLayout/SignInPageContent.js index 5865c235335a..732dea9b0791 100755 --- a/src/pages/signin/SignInPageLayout/SignInPageContent.js +++ b/src/pages/signin/SignInPageLayout/SignInPageContent.js @@ -3,10 +3,11 @@ import React from 'react'; import {View} from 'react-native'; import {withSafeAreaInsets} from 'react-native-safe-area-context'; import ExpensifyWordmark from '@components/ExpensifyWordmark'; +import FormElement from '@components/FormElement'; import OfflineIndicator from '@components/OfflineIndicator'; -import SignInPageForm from '@components/SignInPageForm'; import Text from '@components/Text'; import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import usePreventFormDefault from '@hooks/usePreventFormDefault'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; @@ -42,6 +43,9 @@ function SignInPageContent(props) { const {isSmallScreenWidth} = useWindowDimensions(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); + const formRef = React.useRef(null); + + usePreventFormDefault(formRef.current); return ( @@ -49,7 +53,10 @@ function SignInPageContent(props) { {/* This empty view creates margin on the top of the sign in form which will shrink and grow depending on if the keyboard is open or not */} - + @@ -73,7 +80,7 @@ function SignInPageContent(props) { ) : null} {props.children} - + From 3380a6956c8fa2b6f48d696455f85d4bcf794c09 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 13 Feb 2024 16:16:48 +0530 Subject: [PATCH 068/202] made code dry --- src/components/Form/FormWrapper.tsx | 3 --- src/components/FormElement.tsx | 17 ++++++++++++++--- .../SignInPageLayout/SignInPageContent.js | 9 +-------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/components/Form/FormWrapper.tsx b/src/components/Form/FormWrapper.tsx index 2e100bb52d81..e8778cf25d58 100644 --- a/src/components/Form/FormWrapper.tsx +++ b/src/components/Form/FormWrapper.tsx @@ -9,7 +9,6 @@ import FormElement from '@components/FormElement'; import SafeAreaConsumer from '@components/SafeAreaConsumer'; import type {SafeAreaChildrenProps} from '@components/SafeAreaConsumer/types'; import ScrollViewWithContext from '@components/ScrollViewWithContext'; -import usePreventFormDefault from '@hooks/usePreventFormDefault'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import type {Form} from '@src/types/onyx'; @@ -66,8 +65,6 @@ function FormWrapper({ const formContentRef = useRef(null); const errorMessage = useMemo(() => (formState ? ErrorUtils.getLatestErrorMessage(formState) : undefined), [formState]); - usePreventFormDefault(formContentRef.current); - const onFixTheErrorsLinkPressed = useCallback(() => { const errorFields = !isEmptyObject(errors) ? errors : formState?.errorFields ?? {}; const focusKey = Object.keys(inputRefs.current ?? {}).find((key) => Object.keys(errorFields).includes(key)); diff --git a/src/components/FormElement.tsx b/src/components/FormElement.tsx index da98d4dc565a..535ccac2a9b9 100644 --- a/src/components/FormElement.tsx +++ b/src/components/FormElement.tsx @@ -1,14 +1,25 @@ import type {ForwardedRef} from 'react'; -import React, {forwardRef} from 'react'; +import React, {forwardRef, useRef} from 'react'; import type {ViewProps} from 'react-native'; import {View} from 'react-native'; +import usePreventFormDefault from '@hooks/usePreventFormDefault'; import * as ComponentUtils from '@libs/ComponentUtils'; -function FormElement(props: ViewProps, ref: ForwardedRef) { +function FormElement(props: ViewProps, outerRef: ForwardedRef) { + const formRef = useRef(null); + usePreventFormDefault(formRef.current); return ( { + formRef.current = ref; + if (typeof outerRef === 'function') { + outerRef(ref); + } else if (outerRef && 'current' in outerRef) { + // eslint-disable-next-line no-param-reassign + outerRef.current = ref; + } + }} // eslint-disable-next-line react/jsx-props-no-spreading {...props} /> diff --git a/src/pages/signin/SignInPageLayout/SignInPageContent.js b/src/pages/signin/SignInPageLayout/SignInPageContent.js index 732dea9b0791..2d0ed4aeb62b 100755 --- a/src/pages/signin/SignInPageLayout/SignInPageContent.js +++ b/src/pages/signin/SignInPageLayout/SignInPageContent.js @@ -7,7 +7,6 @@ import FormElement from '@components/FormElement'; import OfflineIndicator from '@components/OfflineIndicator'; import Text from '@components/Text'; import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; -import usePreventFormDefault from '@hooks/usePreventFormDefault'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; @@ -43,9 +42,6 @@ function SignInPageContent(props) { const {isSmallScreenWidth} = useWindowDimensions(); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); - const formRef = React.useRef(null); - - usePreventFormDefault(formRef.current); return ( @@ -53,10 +49,7 @@ function SignInPageContent(props) { {/* This empty view creates margin on the top of the sign in form which will shrink and grow depending on if the keyboard is open or not */} - + From 93c3a2b75257ee72c892df8c2134243ca28d8f35 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 13 Feb 2024 16:38:27 +0530 Subject: [PATCH 069/202] fixed naming to avoid confusion --- src/components/FormElement.tsx | 4 ++-- src/hooks/useFormSetup/index.native.ts | 3 +++ src/hooks/{usePreventFormDefault => useFormSetup}/index.ts | 4 ++-- src/hooks/usePreventFormDefault/index.native.ts | 3 --- 4 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 src/hooks/useFormSetup/index.native.ts rename src/hooks/{usePreventFormDefault => useFormSetup}/index.ts (92%) delete mode 100644 src/hooks/usePreventFormDefault/index.native.ts diff --git a/src/components/FormElement.tsx b/src/components/FormElement.tsx index 535ccac2a9b9..1dd7eb503621 100644 --- a/src/components/FormElement.tsx +++ b/src/components/FormElement.tsx @@ -2,12 +2,12 @@ import type {ForwardedRef} from 'react'; import React, {forwardRef, useRef} from 'react'; import type {ViewProps} from 'react-native'; import {View} from 'react-native'; -import usePreventFormDefault from '@hooks/usePreventFormDefault'; +import useFormSetup from '@hooks/useFormSetup'; import * as ComponentUtils from '@libs/ComponentUtils'; function FormElement(props: ViewProps, outerRef: ForwardedRef) { const formRef = useRef(null); - usePreventFormDefault(formRef.current); + useFormSetup(formRef.current); return ( {}; + +export default useFormSetup; diff --git a/src/hooks/usePreventFormDefault/index.ts b/src/hooks/useFormSetup/index.ts similarity index 92% rename from src/hooks/usePreventFormDefault/index.ts rename to src/hooks/useFormSetup/index.ts index 6c60ca0f95c2..935bbc2f55fb 100644 --- a/src/hooks/usePreventFormDefault/index.ts +++ b/src/hooks/useFormSetup/index.ts @@ -7,7 +7,7 @@ const preventFormDefault = (event: SubmitEvent) => { event.preventDefault(); }; -const usePreventFormDefault = (form: View | null) => { +const useFormSetup = (form: View | null) => { useEffect(() => { if (!form) { return; @@ -30,4 +30,4 @@ const usePreventFormDefault = (form: View | null) => { }, [form]); }; -export default usePreventFormDefault; +export default useFormSetup; diff --git a/src/hooks/usePreventFormDefault/index.native.ts b/src/hooks/usePreventFormDefault/index.native.ts deleted file mode 100644 index 36223555e588..000000000000 --- a/src/hooks/usePreventFormDefault/index.native.ts +++ /dev/null @@ -1,3 +0,0 @@ -const usePreventFormDefault = () => {}; - -export default usePreventFormDefault; From 7786efc13997918b27fa488be2a19d854140c5af Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Tue, 13 Feb 2024 12:27:21 +0100 Subject: [PATCH 070/202] feat: upgrade react-native-reanimated --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 11099886bfb0..cf598969e55e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -105,7 +105,7 @@ "react-native-plaid-link-sdk": "10.8.0", "react-native-qrcode-svg": "^6.2.0", "react-native-quick-sqlite": "^8.0.0-beta.2", - "react-native-reanimated": "^3.6.1", + "react-native-reanimated": "^3.7.0", "react-native-render-html": "6.3.1", "react-native-safe-area-context": "4.7.4", "react-native-screens": "3.29.0", @@ -45184,9 +45184,9 @@ } }, "node_modules/react-native-reanimated": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.6.1.tgz", - "integrity": "sha512-F4vG9Yf9PKmE3GaWtVGUpzj3SM6YY2cx1yRHCwiMd1uY7W0gU017LfcVUorboJnj0y5QZqEriEK1Usq2Y8YZqg==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.7.0.tgz", + "integrity": "sha512-KM+MKa3CJWqsF4GlOLLKBxTR2NEcrg5/HP9J2b6Dfgvll1sjZPywCOEEIh967SboEU8N9LjYZuoVm2UoXGxp2Q==", "dependencies": { "@babel/plugin-transform-object-assign": "^7.16.7", "@babel/preset-typescript": "^7.16.7", diff --git a/package.json b/package.json index 71983e0e1679..a92a633f7e15 100644 --- a/package.json +++ b/package.json @@ -153,7 +153,7 @@ "react-native-plaid-link-sdk": "10.8.0", "react-native-qrcode-svg": "^6.2.0", "react-native-quick-sqlite": "^8.0.0-beta.2", - "react-native-reanimated": "^3.6.1", + "react-native-reanimated": "^3.7.0", "react-native-render-html": "6.3.1", "react-native-safe-area-context": "4.7.4", "react-native-screens": "3.29.0", From 9bad094e91a4c7b0fd923363da2445d0440584e4 Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Tue, 13 Feb 2024 13:55:17 +0100 Subject: [PATCH 071/202] fix PR comments --- tests/e2e/compare/output/markdownTable.ts | 73 +++++++++++------------ 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/tests/e2e/compare/output/markdownTable.ts b/tests/e2e/compare/output/markdownTable.ts index e22325e4d8d1..51f0beeb6979 100644 --- a/tests/e2e/compare/output/markdownTable.ts +++ b/tests/e2e/compare/output/markdownTable.ts @@ -1,4 +1,3 @@ -/* eslint-disable */ // copied from https://raw.githubusercontent.com/wooorm/markdown-table/main/index.js, turned into cmjs type MarkdownTableOptions = { @@ -154,24 +153,42 @@ type MarkdownTableOptions = { stringLength?: (value: string) => number; }; -/** - * Generate a markdown ([GFM](https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/organizing-information-with-tables)) table.. - * - * @param {Array>} table - * Table data (matrix of strings). - * @param {Options} [options] - * Configuration (optional). - * @returns {string} - */ +function serialize(value: string | null | undefined): string { + return value === null || value === undefined ? '' : String(value); +} + +function defaultStringLength(value: string): number { + return value.length; +} + +function toAlignment(value: string | null | undefined): number { + const code = typeof value === 'string' ? value.codePointAt(0) : 0; + + if (code === 67 /* `C` */ || code === 99 /* `c` */) { + return 99; /* `c` */ + } + + if (code === 76 /* `L` */ || code === 108 /* `l` */) { + return 108; /* `l` */ + } + + if (code === 82 /* `R` */ || code === 114 /* `r` */) { + return 114; /* `r` */ + } + + return 0; +} + +/** Generate a markdown ([GFM](https://docs.github.com/en/github/writing-on-github/working-with-advanced-formatting/organizing-information-with-tables)) table.. */ function markdownTable(table: Array>, options: MarkdownTableOptions = {}) { - const align = (options.align || []).concat(); - const stringLength = options.stringLength || defaultStringLength; + const align = (options.align ?? []).concat(); + const stringLength = options.stringLength ?? defaultStringLength; /** Character codes as symbols for alignment per column. */ const alignments: number[] = []; /** Cells per row. */ - const cellMatrix: Array> = []; + const cellMatrix: string[][] = []; /** Sizes of each cell per row. */ - const sizeMatrix: Array> = []; + const sizeMatrix: number[][] = []; const longestCellByColumn: number[] = []; let mostCellsPerRow = 0; let rowIndex = -1; @@ -266,18 +283,18 @@ function markdownTable(table: Array>, options: const lines: string[] = []; while (++rowIndex < cellMatrix.length) { - const row = cellMatrix[rowIndex]; - const sizes = sizeMatrix[rowIndex]; + const matrixRow = cellMatrix[rowIndex]; + const matrixSizes = sizeMatrix[rowIndex]; columnIndex = -1; const line: string[] = []; while (++columnIndex < mostCellsPerRow) { - const cell = row[columnIndex] || ''; + const cell = matrixRow[columnIndex] || ''; let before = ''; let after = ''; if (options.alignDelimiters !== false) { - const size = longestCellByColumn[columnIndex] - (sizes[columnIndex] || 0); + const size = longestCellByColumn[columnIndex] - (matrixSizes[columnIndex] || 0); const code = alignments[columnIndex]; if (code === 114 /* `r` */) { @@ -334,24 +351,4 @@ function markdownTable(table: Array>, options: return lines.join('\n'); } -function serialize(value: string | null | undefined): string { - return value === null || value === undefined ? '' : String(value); -} - -function defaultStringLength(value: string): number { - return value.length; -} - -function toAlignment(value: string | null | undefined): number { - const code = typeof value === 'string' ? value.codePointAt(0) : 0; - - return code === 67 /* `C` */ || code === 99 /* `c` */ - ? 99 /* `c` */ - : code === 76 /* `L` */ || code === 108 /* `l` */ - ? 108 /* `l` */ - : code === 82 /* `R` */ || code === 114 /* `r` */ - ? 114 /* `r` */ - : 0; -} - export default markdownTable; From de2111c187b2cd6371a4425f1cd293b2961840ea Mon Sep 17 00:00:00 2001 From: Jakub Szymczak Date: Tue, 13 Feb 2024 16:04:15 +0100 Subject: [PATCH 072/202] fix bugs --- tests/e2e/compare/output/markdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/compare/output/markdown.js b/tests/e2e/compare/output/markdown.js index 2015d8de6cc3..112c6780d499 100644 --- a/tests/e2e/compare/output/markdown.js +++ b/tests/e2e/compare/output/markdown.js @@ -1,9 +1,9 @@ // From: https://raw.githubusercontent.com/callstack/reassure/main/packages/reassure-compare/src/output/markdown.ts +import markdownTable from './markdownTable'; const fs = require('node:fs/promises'); const path = require('path'); const _ = require('underscore'); -const markdownTable = require('./markdownTable'); const {formatDuration, formatPercent, formatDurationDiffChange} = require('./format'); const Logger = require('../../utils/logger'); From 68f4cf96945713268d8f1d34b9c4c81dd2ca2bba Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 14 Feb 2024 15:03:53 +0100 Subject: [PATCH 073/202] fix: typecheck --- src/ONYXKEYS.ts | 2 +- src/components/MoneyRequestConfirmationList.tsx | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 0735bc53e56c..944788d99cb8 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -453,7 +453,7 @@ type OnyxCollectionValuesMapping = { [ONYXKEYS.COLLECTION.SELECTED_TAB]: string; [ONYXKEYS.COLLECTION.PRIVATE_NOTES_DRAFT]: string; [ONYXKEYS.COLLECTION.NEXT_STEP]: OnyxTypes.ReportNextStep; - [ONYXKEYS.COLLECTION.POLICY_TAX_RATE]: string[]; + [ONYXKEYS.COLLECTION.POLICY_TAX_RATE]: OnyxTypes.PolicyTaxRate; }; type OnyxValuesMapping = { diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 1dd6e9b9f302..de289f1fba3b 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -77,6 +77,9 @@ type MoneyRequestConfirmationListOnyxProps = { /** The policy of root parent report */ policy: OnyxEntry; + + /** The session of the logged in user */ + session: OnyxEntry; }; type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & @@ -818,7 +821,7 @@ function MoneyRequestConfirmationList({ Navigation.navigate( ROUTES.MONEY_REQUEST_STEP_TAG.getRoute( CONST.IOU.ACTION.CREATE, - CONST.IOU.TYPE.SEND, + iouType, transaction?.transactionID ?? '', reportID ?? '', Navigation.getActiveRouteWithoutParams(), @@ -905,5 +908,8 @@ export default withCurrentUserPersonalDetails( iou: { key: ONYXKEYS.IOU, }, + session: { + key: ONYXKEYS.SESSION, + }, })(MoneyRequestConfirmationList), ); From 022db8f5be1264e9fb45a7393c84ab2d309a97af Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 14 Feb 2024 16:45:57 +0100 Subject: [PATCH 074/202] fix: resolve comments --- src/components/AttachmentModal.tsx | 4 ++-- .../AddCommentOrAttachementParams.ts | 2 +- src/libs/ReportUtils.ts | 2 +- src/libs/actions/Report.ts | 4 ++-- .../ComposerWithSuggestions.tsx | 10 ++++---- .../ReportActionCompose.tsx | 24 ++++--------------- .../SilentCommentUpdater/index.tsx | 1 + src/types/modules/pusher.d.ts | 2 +- src/types/onyx/ReportAction.ts | 2 +- 9 files changed, 19 insertions(+), 32 deletions(-) diff --git a/src/components/AttachmentModal.tsx b/src/components/AttachmentModal.tsx index 2b4afc037796..7f0178863fc9 100755 --- a/src/components/AttachmentModal.tsx +++ b/src/components/AttachmentModal.tsx @@ -89,7 +89,7 @@ type AttachmentModalProps = AttachmentModalOnyxProps & { source?: AvatarSource; /** Optional callback to fire when we want to preview an image and approve it for use. */ - onConfirm?: ((file: Partial) => void) | null; + onConfirm?: ((file: FileObject) => void) | null; /** Whether the modal should be open by default */ defaultOpen?: boolean; @@ -264,7 +264,7 @@ function AttachmentModal({ } if (onConfirm) { - onConfirm(Object.assign(file ?? {}, {source: sourceState})); + onConfirm(Object.assign(file ?? {}, {source: sourceState} as FileObject)); } setIsModalOpen(false); diff --git a/src/libs/API/parameters/AddCommentOrAttachementParams.ts b/src/libs/API/parameters/AddCommentOrAttachementParams.ts index 4eab35be7dd2..a705c92f7f27 100644 --- a/src/libs/API/parameters/AddCommentOrAttachementParams.ts +++ b/src/libs/API/parameters/AddCommentOrAttachementParams.ts @@ -5,7 +5,7 @@ type AddCommentOrAttachementParams = { reportActionID?: string; commentReportActionID?: string | null; reportComment?: string; - file?: Partial; + file?: FileObject; timezone?: string; shouldAllowActionableMentionWhispers?: boolean; clientCreatedTime?: string; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 2b073b110184..ed3dc16b56a4 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2631,7 +2631,7 @@ function getReportDescriptionText(report: Report): string { return parser.htmlToText(report.description); } -function buildOptimisticAddCommentReportAction(text?: string, file?: Partial, actorAccountID?: number): OptimisticReportAction { +function buildOptimisticAddCommentReportAction(text?: string, file?: FileObject, actorAccountID?: number): OptimisticReportAction { const parser = new ExpensiMark(); const commentText = getParsedComment(text ?? ''); const isAttachment = !text && file !== undefined; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index bfae6ece1fa1..7127178daae7 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -353,7 +353,7 @@ function notifyNewAction(reportID: string, accountID?: number, reportActionID?: * - Adding one attachment * - Add both a comment and attachment simultaneously */ -function addActions(reportID: string, text = '', file?: Partial) { +function addActions(reportID: string, text = '', file?: FileObject) { let reportCommentText = ''; let reportCommentAction: OptimisticAddCommentReportAction | undefined; let attachmentAction: OptimisticAddCommentReportAction | undefined; @@ -512,7 +512,7 @@ function addActions(reportID: string, text = '', file?: Partial) { } /** Add an attachment and optional comment. */ -function addAttachment(reportID: string, file: Partial, text = '') { +function addAttachment(reportID: string, file: FileObject, text = '') { addActions(reportID, text, file); } diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index cfe45e5a011b..a345926ad7d2 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -214,6 +214,7 @@ function ComposerWithSuggestions( onFocus, onBlur, onValueChange, + // Composer isComposerFullSize, isMenuVisible, @@ -232,11 +233,13 @@ function ComposerWithSuggestions( listHeight, isScrollLikelyLayoutTriggered, raiseIsScrollLikelyLayoutTriggered, + // Refs suggestionsRef, animatedRef, isNextModalWillOpenRef, editFocused, + // For testing children, }: ComposerWithSuggestionsProps, @@ -278,7 +281,7 @@ function ComposerWithSuggestions( const syncSelectionWithOnChangeTextRef = useRef(null); - const suggestions = suggestionsRef.current?.getSuggestions() ?? (() => []); + const suggestions = suggestionsRef.current?.getSuggestions() ?? []; const hasEnoughSpaceForLargeSuggestion = SuggestionUtils.hasEnoughSpaceForLargeSuggestionMenu(listHeight, composerHeight, suggestions?.length ?? 0); @@ -457,7 +460,7 @@ function ComposerWithSuggestions( [reportID, numberOfLines], ); - const prepareCommentAndResetComposer = useCallback(() => { + const prepareCommentAndResetComposer = useCallback((): string => { const trimmedComment = commentRef.current.trim(); const commentLength = ReportUtils.getCommentLength(trimmedComment); @@ -575,7 +578,6 @@ function ComposerWithSuggestions( /** * Focus the composer text input * @param [shouldDelay=false] Impose delay before focusing the composer - * @memberof ReportActionCompose */ const focus = useCallback((shouldDelay = false) => { focusComposerWithDelay(textInputRef.current)(shouldDelay); @@ -614,7 +616,7 @@ function ComposerWithSuggestions( } // if we're typing on another input/text area, do not focus - if (['INPUT', 'TEXTAREA'].includes((e.target as Element)?.nodeName)) { + if (['INPUT', 'TEXTAREA'].includes((e.target as Element | null)?.nodeName ?? '')) { return; } diff --git a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx index 735fb323d638..84f7600f8ef0 100644 --- a/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx +++ b/src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx @@ -43,6 +43,7 @@ import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import AttachmentPickerWithMenuItems from './AttachmentPickerWithMenuItems'; import ComposerWithSuggestions from './ComposerWithSuggestions'; +import type {ComposerWithSuggestionsProps} from './ComposerWithSuggestions/ComposerWithSuggestions'; import SendButton from './SendButton'; type ComposerRef = { @@ -71,36 +72,19 @@ type ReportActionComposeOnyxProps = { }; type ReportActionComposeProps = ReportActionComposeOnyxProps & - WithCurrentUserPersonalDetailsProps & { + WithCurrentUserPersonalDetailsProps & + Pick & { /** A method to call when the form is submitted */ onSubmit: (newComment: string | undefined) => void; - /** The ID of the report actions will be created for */ - reportID: string; - /** The report currently being looked at */ report: OnyxEntry; - /** Is composer full size */ - isComposerFullSize?: boolean; - - /** Whether user interactions should be disabled */ - disabled?: boolean; - - /** Height of the list which the composer is part of */ - listHeight?: number; - /** The type of action that's pending */ pendingAction?: OnyxCommon.PendingAction; /** Whether the report is ready for display */ isReportReadyForDisplay?: boolean; - - /** Whether the chat is empty */ - isEmptyChat?: boolean; - - /** The last report action */ - lastReportAction?: OnyxTypes.ReportAction; }; // We want consistent auto focus behavior on input between native and mWeb so we have some auto focus management code that will @@ -268,7 +252,7 @@ function ReportActionCompose({ }, []); const addAttachment = useCallback( - (file: Partial) => { + (file: FileObject) => { playSound(SOUNDS.DONE); const newComment = composerRef?.current?.prepareCommentAndResetComposer(); Report.addAttachment(reportID, file, newComment); diff --git a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx index c84bd3786610..1abc6567bc7b 100644 --- a/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx +++ b/src/pages/home/report/ReportActionCompose/SilentCommentUpdater/index.tsx @@ -43,5 +43,6 @@ SilentCommentUpdater.displayName = 'SilentCommentUpdater'; export default withOnyx({ comment: { key: ({reportID}) => `${ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT}${reportID}`, + initialValue: '', }, })(SilentCommentUpdater); diff --git a/src/types/modules/pusher.d.ts b/src/types/modules/pusher.d.ts index 676d7a7ee2fc..e9aa50085e8d 100644 --- a/src/types/modules/pusher.d.ts +++ b/src/types/modules/pusher.d.ts @@ -9,6 +9,6 @@ declare global { // eslint-disable-next-line @typescript-eslint/consistent-type-definitions interface File { source: string; - uri: string; + uri?: string; } } diff --git a/src/types/onyx/ReportAction.ts b/src/types/onyx/ReportAction.ts index 7071c211c2e9..d339d666a411 100644 --- a/src/types/onyx/ReportAction.ts +++ b/src/types/onyx/ReportAction.ts @@ -169,7 +169,7 @@ type ReportActionBase = { isFirstItem?: boolean; /** Informations about attachments of report action */ - attachmentInfo?: Partial | EmptyObject; + attachmentInfo?: FileObject | EmptyObject; /** Receipt tied to report action */ receipt?: Receipt; From fe5465074a8ab1acfbc6b207965e4cad4e093e03 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 15 Feb 2024 14:55:53 +0700 Subject: [PATCH 075/202] lint fix --- src/libs/actions/IOU.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 589bb7bff15b..f6fb82990968 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -377,7 +377,7 @@ function needsToBeManuallySubmitted(iouReport: OnyxTypes.Report) { /** * Return the object to update hasOutstandingChildRequest */ -function getOutstandingChildRequest(policy: OnyxEntry | EmptyObject, iouReport: OnyxTypes.Report) { +function getOutstandingChildRequest(policy: OnyxEntry | EmptyObject, iouReport: OnyxTypes.Report): OutstandingChildRequest { if (!needsToBeManuallySubmitted(iouReport)) { return { hasOutstandingChildRequest: false, From a33bca5d57fab862e3f432c6a0568a56435aaa4e Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Thu, 15 Feb 2024 19:02:37 +0530 Subject: [PATCH 076/202] adjust code according to recommendations --- src/components/FormElement.tsx | 15 ++++++--------- src/hooks/useFormSetup/index.ts | 20 +++++++++++--------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/components/FormElement.tsx b/src/components/FormElement.tsx index 1dd7eb503621..81242496a2cf 100644 --- a/src/components/FormElement.tsx +++ b/src/components/FormElement.tsx @@ -4,22 +4,19 @@ import type {ViewProps} from 'react-native'; import {View} from 'react-native'; import useFormSetup from '@hooks/useFormSetup'; import * as ComponentUtils from '@libs/ComponentUtils'; +import mergeRefs from '@libs/mergeRefs'; function FormElement(props: ViewProps, outerRef: ForwardedRef) { const formRef = useRef(null); + useFormSetup(formRef.current); + + const mergedRef = mergeRefs(formRef, outerRef); + return ( { - formRef.current = ref; - if (typeof outerRef === 'function') { - outerRef(ref); - } else if (outerRef && 'current' in outerRef) { - // eslint-disable-next-line no-param-reassign - outerRef.current = ref; - } - }} + ref={mergedRef} // eslint-disable-next-line react/jsx-props-no-spreading {...props} /> diff --git a/src/hooks/useFormSetup/index.ts b/src/hooks/useFormSetup/index.ts index 935bbc2f55fb..b216807abdfd 100644 --- a/src/hooks/useFormSetup/index.ts +++ b/src/hooks/useFormSetup/index.ts @@ -2,8 +2,8 @@ import {useEffect} from 'react'; import type {View} from 'react-native'; const preventFormDefault = (event: SubmitEvent) => { - // When enter is pressed form is submitted to action url (POST /). - // As we are using controlled component, we need to disable it here. + // When Enter is pressed, the form is submitted to the action URL (POST /). + // As we are using a controlled component, we need to disable this behavior here. event.preventDefault(); }; @@ -13,19 +13,21 @@ const useFormSetup = (form: View | null) => { return; } - // This is a safe cast because we know that form is a HTMLFormElement. - const formElement = form as unknown as HTMLFormElement; + // Sanity check. The form should always be an HTMLFormElement. + if (!(form instanceof HTMLFormElement)) { + return; + } // Prevent the browser from applying its own validation, which affects the email input - formElement.setAttribute('novalidate', ''); + form.setAttribute('novalidate', ''); // Password Managers need these attributes to be able to identify the form elements properly. - formElement.setAttribute('method', 'post'); - formElement.setAttribute('action', '/'); - formElement.addEventListener('submit', preventFormDefault); + form.setAttribute('method', 'post'); + form.setAttribute('action', '/'); + form.addEventListener('submit', preventFormDefault); return () => { - formElement.removeEventListener('submit', preventFormDefault); + form.removeEventListener('submit', preventFormDefault); }; }, [form]); }; From d7708c104d60b0295cb382c617646e3820d9b4e7 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 15 Feb 2024 14:33:50 +0100 Subject: [PATCH 077/202] fix: removed uncessesary condition --- .../MoneyRequestConfirmationList.tsx | 33 +++++++------------ 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index de289f1fba3b..8430dd66d3c8 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -262,7 +262,7 @@ function MoneyRequestConfirmationList({ const shouldShowTags = isPolicyExpenseChat && (iouTag || OptionsListUtils.hasEnabledOptions(Object.values(policyTagList ?? {}))); // A flag for showing tax fields - tax rate and tax amount - const shouldShowTax = isPolicyExpenseChat && policy?.isTaxTrackingEnabled; + const shouldShowTax = isPolicyExpenseChat && (policy?.tax?.trackingEnabled ?? policy?.isTaxTrackingEnabled); // A flag for showing the billable field const shouldShowBillable = !policy?.disabledFields?.defaultBillable ?? true; @@ -457,7 +457,7 @@ function MoneyRequestConfirmationList({ translate, toLocaleDigit, ); - IOU.setMoneyRequestMerchant_temporaryForRefactor(transactionID ?? '', distanceMerchant); + IOU.setMoneyRequestMerchant(transactionID ?? '', distanceMerchant, false); }, [hasRoute, distance, mileageRate?.unit, mileageRate?.rate, mileageRate?.currency, translate, toLocaleDigit, isDistanceRequest, transactionID, isDistanceRequestWithPendingRoute]); const selectParticipant = useCallback( @@ -762,11 +762,15 @@ function MoneyRequestConfirmationList({ style={styles.moneyRequestMenuItem} titleStyle={styles.flex1} onPress={() => { - if (isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID ?? '', reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.MERCHANT)); - return; - } - Navigation.navigate(ROUTES.MONEY_REQUEST_MERCHANT.getRoute(iouType, reportID)); + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_MERCHANT.getRoute( + CONST.IOU.ACTION.EDIT, + iouType, + transactionID ?? '', + reportID ?? '', + Navigation.getActiveRouteWithoutParams(), + ), + ); }} disabled={didConfirm} interactive={!isReadOnly} @@ -805,22 +809,9 @@ function MoneyRequestConfirmationList({ description={policyTagListName} numberOfLinesTitle={2} onPress={() => { - if (isEditingSplitBill) { - Navigation.navigate( - ROUTES.MONEY_REQUEST_STEP_TAG.getRoute( - CONST.IOU.ACTION.EDIT, - CONST.IOU.TYPE.SPLIT, - transaction?.transactionID ?? '', - reportID ?? '', - Navigation.getActiveRouteWithoutParams(), - ), - ); - return; - } - Navigation.navigate( ROUTES.MONEY_REQUEST_STEP_TAG.getRoute( - CONST.IOU.ACTION.CREATE, + CONST.IOU.ACTION.EDIT, iouType, transaction?.transactionID ?? '', reportID ?? '', From 1f2489345fc5b69ff95ee350a2a0a0f2f1945838 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Thu, 15 Feb 2024 19:22:45 +0530 Subject: [PATCH 078/202] trying to fix a bug --- src/components/FormElement.tsx | 28 ------------ src/components/FormElement/index.native.tsx | 18 ++++++++ src/components/FormElement/index.tsx | 50 +++++++++++++++++++++ src/hooks/useFormSetup/index.native.ts | 3 -- src/hooks/useFormSetup/index.ts | 35 --------------- src/libs/mergeRefs.ts | 1 + 6 files changed, 69 insertions(+), 66 deletions(-) delete mode 100644 src/components/FormElement.tsx create mode 100644 src/components/FormElement/index.native.tsx create mode 100644 src/components/FormElement/index.tsx delete mode 100644 src/hooks/useFormSetup/index.native.ts delete mode 100644 src/hooks/useFormSetup/index.ts diff --git a/src/components/FormElement.tsx b/src/components/FormElement.tsx deleted file mode 100644 index 81242496a2cf..000000000000 --- a/src/components/FormElement.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import type {ForwardedRef} from 'react'; -import React, {forwardRef, useRef} from 'react'; -import type {ViewProps} from 'react-native'; -import {View} from 'react-native'; -import useFormSetup from '@hooks/useFormSetup'; -import * as ComponentUtils from '@libs/ComponentUtils'; -import mergeRefs from '@libs/mergeRefs'; - -function FormElement(props: ViewProps, outerRef: ForwardedRef) { - const formRef = useRef(null); - - useFormSetup(formRef.current); - - const mergedRef = mergeRefs(formRef, outerRef); - - return ( - - ); -} - -FormElement.displayName = 'FormElement'; - -export default forwardRef(FormElement); diff --git a/src/components/FormElement/index.native.tsx b/src/components/FormElement/index.native.tsx new file mode 100644 index 000000000000..d0413c5244c1 --- /dev/null +++ b/src/components/FormElement/index.native.tsx @@ -0,0 +1,18 @@ +import type {ForwardedRef} from 'react'; +import React, {forwardRef} from 'react'; +import type {ViewProps} from 'react-native'; +import {View} from 'react-native'; + +function FormElement(props: ViewProps, ref: ForwardedRef) { + return ( + + ); +} + +FormElement.displayName = 'FormElement'; + +export default forwardRef(FormElement); diff --git a/src/components/FormElement/index.tsx b/src/components/FormElement/index.tsx new file mode 100644 index 000000000000..56b34bdba18a --- /dev/null +++ b/src/components/FormElement/index.tsx @@ -0,0 +1,50 @@ +import type {ForwardedRef} from 'react'; +import React, {forwardRef, useRef, useEffect} from 'react'; +import type {ViewProps} from 'react-native'; +import {View} from 'react-native'; +import * as ComponentUtils from '@libs/ComponentUtils'; +import mergeRefs from '@libs/mergeRefs'; + +const preventFormDefault = (event: SubmitEvent) => { + // When Enter is pressed, the form is submitted to the action URL (POST /). + // As we are using a controlled component, we need to disable this behavior here. + event.preventDefault(); +}; + +function FormElement(props: ViewProps, outerRef: ForwardedRef) { + const formRef = useRef(null); + const mergedRef = mergeRefs(formRef, outerRef); + + useEffect(() => { + const formCurrent = formRef.current; + + if (!formCurrent) { + return; + } + + // 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); + + return () => { + formCurrent.removeEventListener('submit', preventFormDefault); + }; + }, []); + + return ( + + ); +} + +FormElement.displayName = 'FormElement'; + +export default forwardRef(FormElement); diff --git a/src/hooks/useFormSetup/index.native.ts b/src/hooks/useFormSetup/index.native.ts deleted file mode 100644 index c4c37e51bc7b..000000000000 --- a/src/hooks/useFormSetup/index.native.ts +++ /dev/null @@ -1,3 +0,0 @@ -const useFormSetup = () => {}; - -export default useFormSetup; diff --git a/src/hooks/useFormSetup/index.ts b/src/hooks/useFormSetup/index.ts deleted file mode 100644 index b216807abdfd..000000000000 --- a/src/hooks/useFormSetup/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -import {useEffect} from 'react'; -import type {View} from 'react-native'; - -const preventFormDefault = (event: SubmitEvent) => { - // When Enter is pressed, the form is submitted to the action URL (POST /). - // As we are using a controlled component, we need to disable this behavior here. - event.preventDefault(); -}; - -const useFormSetup = (form: View | null) => { - useEffect(() => { - if (!form) { - return; - } - - // Sanity check. The form should always be an HTMLFormElement. - if (!(form instanceof HTMLFormElement)) { - return; - } - - // Prevent the browser from applying its own validation, which affects the email input - form.setAttribute('novalidate', ''); - - // Password Managers need these attributes to be able to identify the form elements properly. - form.setAttribute('method', 'post'); - form.setAttribute('action', '/'); - form.addEventListener('submit', preventFormDefault); - - return () => { - form.removeEventListener('submit', preventFormDefault); - }; - }, [form]); -}; - -export default useFormSetup; diff --git a/src/libs/mergeRefs.ts b/src/libs/mergeRefs.ts index d4f342d17ca4..c53a1716aee3 100644 --- a/src/libs/mergeRefs.ts +++ b/src/libs/mergeRefs.ts @@ -7,6 +7,7 @@ import type {LegacyRef, MutableRefObject, RefCallback} from 'react'; export default function mergeRefs(...refs: Array | LegacyRef | undefined | null>): RefCallback { return (value) => { refs.forEach((ref) => { + console.log('ref', ref, value); if (typeof ref === 'function') { ref(value); } else if (ref != null) { From e9c5e9ba3338163ed49a424fd080074549b22f42 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Thu, 15 Feb 2024 19:25:15 +0530 Subject: [PATCH 079/202] lint fix --- src/components/FormElement/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/FormElement/index.tsx b/src/components/FormElement/index.tsx index 56b34bdba18a..9a344eb3c39c 100644 --- a/src/components/FormElement/index.tsx +++ b/src/components/FormElement/index.tsx @@ -1,5 +1,5 @@ import type {ForwardedRef} from 'react'; -import React, {forwardRef, useRef, useEffect} from 'react'; +import React, {forwardRef, useEffect, useRef} from 'react'; import type {ViewProps} from 'react-native'; import {View} from 'react-native'; import * as ComponentUtils from '@libs/ComponentUtils'; @@ -17,7 +17,7 @@ function FormElement(props: ViewProps, outerRef: ForwardedRef) { useEffect(() => { const formCurrent = formRef.current; - + if (!formCurrent) { return; } From 970478fe8c82efa6962aac434c1adca41866cf53 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Sun, 18 Feb 2024 11:13:12 +0530 Subject: [PATCH 080/202] Fixed lint --- src/libs/mergeRefs.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/mergeRefs.ts b/src/libs/mergeRefs.ts index c53a1716aee3..d4f342d17ca4 100644 --- a/src/libs/mergeRefs.ts +++ b/src/libs/mergeRefs.ts @@ -7,7 +7,6 @@ import type {LegacyRef, MutableRefObject, RefCallback} from 'react'; export default function mergeRefs(...refs: Array | LegacyRef | undefined | null>): RefCallback { return (value) => { refs.forEach((ref) => { - console.log('ref', ref, value); if (typeof ref === 'function') { ref(value); } else if (ref != null) { From a7a74e0c4c98af97add0c978c6227c6c416250fd Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Mon, 19 Feb 2024 07:55:41 +0100 Subject: [PATCH 081/202] change file extension to .ts --- .../utils/{getCurrentBranchName.js => getCurrentBranchName.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/e2e/utils/{getCurrentBranchName.js => getCurrentBranchName.ts} (100%) diff --git a/tests/e2e/utils/getCurrentBranchName.js b/tests/e2e/utils/getCurrentBranchName.ts similarity index 100% rename from tests/e2e/utils/getCurrentBranchName.js rename to tests/e2e/utils/getCurrentBranchName.ts From 2d4d666d1317fc39cd82e28a407d4f1eb8906f55 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Mon, 19 Feb 2024 09:33:25 +0100 Subject: [PATCH 082/202] fix: add podfile --- ios/Podfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 80933065c450..e4f988173f40 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1434,7 +1434,7 @@ PODS: - React-Core - RNReactNativeHapticFeedback (2.2.0): - React-Core - - RNReanimated (3.6.1): + - RNReanimated (3.7.0): - glog - RCT-Folly (= 2022.05.16.00) - React-Core @@ -1988,7 +1988,7 @@ SPEC CHECKSUMS: rnmapbox-maps: fcf7f1cbdc8bd7569c267d07284e8a5c7bee06ed RNPermissions: 9b086c8f05b2e2faa587fdc31f4c5ab4509728aa RNReactNativeHapticFeedback: ec56a5f81c3941206fd85625fa669ffc7b4545f9 - RNReanimated: 57f436e7aa3d277fbfed05e003230b43428157c0 + RNReanimated: 7d6d32f238f914f13d9d6fb45c0aef557f7f901e RNScreens: b582cb834dc4133307562e930e8fa914b8c04ef2 RNSound: 6c156f925295bdc83e8e422e7d8b38d33bc71852 RNSVG: ba3e7232f45e34b7b47e74472386cf4e1a676d0a From 51f34ab996e756ef41e07702a37a8bf94e596b86 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Mon, 19 Feb 2024 10:34:19 +0100 Subject: [PATCH 083/202] feat: rename patches --- ... react-native-reanimated+3.7.0+001+fix-boost-dependency.patch} | 0 ...reanimated+3.6.1.patch => react-native-reanimated+3.7.0.patch} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename patches/{react-native-reanimated+3.6.1+001+fix-boost-dependency.patch => react-native-reanimated+3.7.0+001+fix-boost-dependency.patch} (100%) rename patches/{react-native-reanimated+3.6.1.patch => react-native-reanimated+3.7.0.patch} (100%) diff --git a/patches/react-native-reanimated+3.6.1+001+fix-boost-dependency.patch b/patches/react-native-reanimated+3.7.0+001+fix-boost-dependency.patch similarity index 100% rename from patches/react-native-reanimated+3.6.1+001+fix-boost-dependency.patch rename to patches/react-native-reanimated+3.7.0+001+fix-boost-dependency.patch diff --git a/patches/react-native-reanimated+3.6.1.patch b/patches/react-native-reanimated+3.7.0.patch similarity index 100% rename from patches/react-native-reanimated+3.6.1.patch rename to patches/react-native-reanimated+3.7.0.patch From d5aba808e5b9306983bf41a98ed892ffd1945227 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 20 Feb 2024 11:22:00 +0100 Subject: [PATCH 084/202] fix: displaying thumbnail --- src/components/MoneyRequestConfirmationList.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index b61e82d76538..252b0ad44384 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -73,7 +73,7 @@ type MoneyRequestConfirmationListOnyxProps = { policyCategories: OnyxEntry; /** Collection of tags attached to a policy */ - policyTags: OnyxEntry; + policyTags: OnyxEntry; /** The policy of root parent report */ policy: OnyxEntry; @@ -253,7 +253,6 @@ function MoneyRequestConfirmationList({ // In Send Money and Split Bill with Scan flow, we don't allow the Merchant or Date to be edited. For distance requests, don't show the merchant as there's already another "Distance" menu item const shouldShowDate = shouldShowAllFields && !isTypeSend && !isSplitWithScan; const shouldShowMerchant = shouldShowAllFields && !isTypeSend && !isDistanceRequest && !isSplitWithScan; - const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTags), [policyTags]); // A flag for showing the tags field const shouldShowTags = isPolicyExpenseChat && (iouTag || OptionsListUtils.hasEnabledTags(policyTagLists)); @@ -600,7 +599,7 @@ function MoneyRequestConfirmationList({ styles.mb2, ]); - const receiptData = ReceiptUtils.getThumbnailAndImageURIs(transaction ?? null, receiptPath, receiptFilename); + const receiptData = receiptPath && receiptFilename ? ReceiptUtils.getThumbnailAndImageURIs(transaction ?? null, receiptPath, receiptFilename) : null; return ( // @ts-expect-error TODO: Remove this once OptionsSelector (https://github.com/Expensify/App/issues/25125) is migrated to TypeScript. )} - {receiptData.image || receiptData.thumbnail ? ( + {receiptData?.image ?? receiptData?.thumbnail ? ( Date: Tue, 20 Feb 2024 16:29:03 +0100 Subject: [PATCH 085/202] offline text input hint --- src/pages/tasks/TaskShareDestinationSelectorModal.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/pages/tasks/TaskShareDestinationSelectorModal.js b/src/pages/tasks/TaskShareDestinationSelectorModal.js index b609ce02af86..7a5b4b764e49 100644 --- a/src/pages/tasks/TaskShareDestinationSelectorModal.js +++ b/src/pages/tasks/TaskShareDestinationSelectorModal.js @@ -10,6 +10,7 @@ import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; +import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Report from '@libs/actions/Report'; import Navigation from '@libs/Navigation/Navigation'; @@ -60,6 +61,9 @@ function TaskShareDestinationSelectorModal({reports, isSearchingForReports}) { const [searchValue, debouncedSearchValue, setSearchValue] = useDebouncedState(''); const {translate} = useLocalize(); const personalDetails = usePersonalDetails(); + const {isOffline} = useNetwork(); + + const textInputHint = useMemo(() => (isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''), [isOffline, translate]); const options = useMemo(() => { const filteredReports = reportFilter(reports); @@ -99,6 +103,7 @@ function TaskShareDestinationSelectorModal({reports, isSearchingForReports}) { safeAreaPaddingBottomStyle={safeAreaPaddingBottomStyle} showLoadingPlaceholder={!didScreenTransitionEnd} isLoadingNewOptions={isSearchingForReports} + textInputHint={textInputHint} /> From afd0f5f2abdf0f180e0b919593378dd3eab94e60 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Tue, 20 Feb 2024 17:20:08 +0100 Subject: [PATCH 086/202] add a new onyx key - initial url --- src/ONYXKEYS.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 9d35994875e1..cd56383c54ac 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -389,6 +389,11 @@ const ONYXKEYS = { PERSONAL_BANK_ACCOUNT: 'personalBankAccountForm', PERSONAL_BANK_ACCOUNT_DRAFT: 'personalBankAccountFormDraft', }, + + /** A persisted initial (deeplinked) url. Could store a previous launch value. + * It means that even after a refresh, when there is no a new value, it keeps storing an old one. + */ + INITIAL_URL: 'initialUrl', } as const; type AllOnyxKeys = DeepValueOf; @@ -557,6 +562,7 @@ type OnyxValuesMapping = { [ONYXKEYS.PLAID_CURRENT_EVENT]: string; [ONYXKEYS.LOGS]: Record; [ONYXKEYS.SHOULD_STORE_LOGS]: boolean; + [ONYXKEYS.INITIAL_URL]: string; }; type OnyxValues = OnyxValuesMapping & OnyxCollectionValuesMapping & OnyxFormValuesMapping & OnyxFormDraftValuesMapping; From fa2e3cee5e252b629a3737f6aa2fdec8e1724f88 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Tue, 20 Feb 2024 17:20:38 +0100 Subject: [PATCH 087/202] implement handling of a prev initial url --- src/libs/actions/Report.ts | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 9134f0a89e61..2ce6706c025c 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -171,11 +171,25 @@ let conciergeChatReportID: string | undefined; const typingWatchTimers: Record = {}; let reportIDDeeplinkedFromOldDot: string | undefined; -Linking.getInitialURL().then((url) => { - const params = new URLSearchParams(url ?? ''); - const exitToRoute = params.get('exitTo') ?? ''; - const {reportID} = ReportUtils.parseReportRouteParams(exitToRoute); - reportIDDeeplinkedFromOldDot = reportID; +Onyx.connect({ + key: ONYXKEYS.INITIAL_URL, + callback: (value) => { + Linking.getInitialURL().then((url) => { + const currentParams = new URLSearchParams(url ?? ''); + const currentExitToRoute = currentParams.get('exitTo') ?? ''; + const {reportID: currentReportID} = ReportUtils.parseReportRouteParams(currentExitToRoute); + + const prevParams = new URLSearchParams(value ?? ''); + const prevExitToRoute = prevParams.get('exitTo') ?? ''; + const {reportID: prevReportID} = ReportUtils.parseReportRouteParams(prevExitToRoute); + + reportIDDeeplinkedFromOldDot = currentReportID || prevReportID; + + if (currentReportID) { + Onyx.set(ONYXKEYS.INITIAL_URL, url); + } + }); + }, }); let lastVisitedPath: string | undefined; From 5bcba77195e2dda5ff0ad6209daeed71368f89af Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Wed, 21 Feb 2024 15:51:17 +0800 Subject: [PATCH 088/202] add concierge page to dismiss modal case --- src/libs/Navigation/dismissModal.ts | 1 + src/libs/Navigation/dismissModalWithReport.ts | 1 + src/pages/ConciergePage.tsx | 3 +-- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/Navigation/dismissModal.ts b/src/libs/Navigation/dismissModal.ts index 484008d2e070..1f46f5c37193 100644 --- a/src/libs/Navigation/dismissModal.ts +++ b/src/libs/Navigation/dismissModal.ts @@ -25,6 +25,7 @@ function dismissModal(navigationRef: NavigationContainerRef) case NAVIGATORS.RIGHT_MODAL_NAVIGATOR: case SCREENS.NOT_FOUND: case SCREENS.REPORT_ATTACHMENTS: + case SCREENS.CONCIERGE: navigationRef.dispatch({...StackActions.pop(), target: state.key}); break; default: { diff --git a/src/libs/Navigation/dismissModalWithReport.ts b/src/libs/Navigation/dismissModalWithReport.ts index b708819cdf9c..4fc82f76df86 100644 --- a/src/libs/Navigation/dismissModalWithReport.ts +++ b/src/libs/Navigation/dismissModalWithReport.ts @@ -38,6 +38,7 @@ function dismissModalWithReport(targetReport: Report | EmptyObject, navigationRe case NAVIGATORS.RIGHT_MODAL_NAVIGATOR: case SCREENS.NOT_FOUND: case SCREENS.REPORT_ATTACHMENTS: + case SCREENS.CONCIERGE: // If we are not in the target report, we need to navigate to it after dismissing the modal if (targetReport.reportID !== getTopmostReportId(state)) { const reportState = getStateFromPath(ROUTES.REPORT_WITH_ID.getRoute(targetReport.reportID)); diff --git a/src/pages/ConciergePage.tsx b/src/pages/ConciergePage.tsx index 251728866a54..feb1b9c54f50 100644 --- a/src/pages/ConciergePage.tsx +++ b/src/pages/ConciergePage.tsx @@ -28,8 +28,7 @@ function ConciergePage({session}: ConciergePageProps) { if (session && 'authToken' in session) { // Pop the concierge loading page before opening the concierge report. Navigation.isNavigationReady().then(() => { - Navigation.goBack(); - Report.navigateToConciergeChat(); + Report.navigateToConciergeChat(undefined, true); }); } else { Navigation.navigate(); From 67b39c13e33910a5ca59c7796203dfa229a81792 Mon Sep 17 00:00:00 2001 From: Julian Kobrynski Date: Wed, 21 Feb 2024 13:20:00 +0100 Subject: [PATCH 089/202] migrate getCurrentBranchName to TypeScript --- tests/e2e/utils/getCurrentBranchName.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/utils/getCurrentBranchName.ts b/tests/e2e/utils/getCurrentBranchName.ts index 55df11010214..7ae958b08e13 100644 --- a/tests/e2e/utils/getCurrentBranchName.ts +++ b/tests/e2e/utils/getCurrentBranchName.ts @@ -1,6 +1,6 @@ import {execSync} from 'child_process'; -const getCurrentBranchName = () => { +const getCurrentBranchName = (): string => { const stdout = execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8', }); From 2a71a34beacca8b099be1161eceb072b6aa821f0 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 21 Feb 2024 14:22:53 +0100 Subject: [PATCH 090/202] fix: typecheck --- .../ReportActionCompose/AttachmentPickerWithMenuItems.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx index 9888c5217e69..68c7f0883683 100644 --- a/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx +++ b/src/pages/home/report/ReportActionCompose/AttachmentPickerWithMenuItems.tsx @@ -18,14 +18,12 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as Browser from '@libs/Browser'; -import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; import * as IOU from '@userActions/IOU'; import * as Report from '@userActions/Report'; import * as Task from '@userActions/Task'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; type MoneyRequestOptions = Record, PopoverMenuItem>; @@ -126,12 +124,12 @@ function AttachmentPickerWithMenuItems({ [CONST.IOU.TYPE.SPLIT]: { icon: Expensicons.Receipt, text: translate('iou.splitBill'), - onSelected: () => IOU.startMoneyRequest_temporaryForRefactor(CONST.IOU.TYPE.SPLIT, report.reportID), + onSelected: () => IOU.startMoneyRequest_temporaryForRefactor(CONST.IOU.TYPE.SPLIT, report?.reportID ?? ''), }, [CONST.IOU.TYPE.REQUEST]: { icon: Expensicons.MoneyCircle, text: translate('iou.requestMoney'), - onSelected: () => IOU.startMoneyRequest_temporaryForRefactor(CONST.IOU.TYPE.REQUEST, report.reportID), + onSelected: () => IOU.startMoneyRequest_temporaryForRefactor(CONST.IOU.TYPE.REQUEST, report?.reportID ?? ''), }, [CONST.IOU.TYPE.SEND]: { icon: Expensicons.Send, From 59cb2e20b134d82b4c53736acf7809379a5bc871 Mon Sep 17 00:00:00 2001 From: ruben-rebelo Date: Wed, 21 Feb 2024 15:59:54 +0000 Subject: [PATCH 091/202] [TS migration] Migrate loginTest into Typescript --- tests/unit/{loginTest.js => loginTest.tsx} | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) rename tests/unit/{loginTest.js => loginTest.tsx} (84%) diff --git a/tests/unit/loginTest.js b/tests/unit/loginTest.tsx similarity index 84% rename from tests/unit/loginTest.js rename to tests/unit/loginTest.tsx index b63564ff2812..d5084299bb08 100644 --- a/tests/unit/loginTest.js +++ b/tests/unit/loginTest.tsx @@ -1,14 +1,12 @@ -/** - * @format - */ import React from 'react'; import 'react-native'; // Note: `react-test-renderer` renderer must be required after react-native. import renderer from 'react-test-renderer'; -import App from '../../src/App'; +import App from '@src/App'; // Needed for: https://stackoverflow.com/questions/76903168/mocking-libraries-in-jest jest.mock('react-native/Libraries/LogBox/LogBox', () => ({ + // eslint-disable-next-line @typescript-eslint/naming-convention __esModule: true, default: { ignoreLogs: jest.fn(), From 2af88861c50a9f5da5b506d25fe231bf7c806c9f Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 22 Feb 2024 16:01:31 +0700 Subject: [PATCH 092/202] update shouldShow condition correctly --- src/pages/ProfilePage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ProfilePage.js b/src/pages/ProfilePage.js index c6f3796e4c9f..2dc6b7c57251 100755 --- a/src/pages/ProfilePage.js +++ b/src/pages/ProfilePage.js @@ -142,7 +142,7 @@ function ProfilePage(props) { return ( - + Navigation.goBack(navigateBackTo)} From a1c45ee9b4e71b36e681feeced114fac6af20854 Mon Sep 17 00:00:00 2001 From: Abdullah Alsigar Date: Thu, 22 Feb 2024 14:29:37 +0300 Subject: [PATCH 093/202] fix: camera button double tap --- .../GenericPressable/BaseGenericPressable.tsx | 12 ++++++++---- .../request/step/IOURequestStepScan/index.native.js | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx b/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx index 1df56093d6a6..8a9157e5817e 100644 --- a/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx +++ b/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx @@ -109,20 +109,24 @@ function GenericPressable( if (ref && 'current' in ref) { ref.current?.blur(); } - onPress(event); - + const onPressResult = onPress(event); Accessibility.moveAccessibilityFocus(nextFocusRef); + return onPressResult; }, [shouldUseHapticsOnPress, onPress, nextFocusRef, ref, isDisabled], ); + const onKeyboardShortcutPressHandler = useCallback((event?: GestureResponderEvent | KeyboardEvent) => { + onPressHandler(event); + }, [onPressHandler]); + useEffect(() => { if (!keyboardShortcut) { return () => {}; } const {shortcutKey, descriptionKey, modifiers} = keyboardShortcut; - return KeyboardShortcut.subscribe(shortcutKey, onPressHandler, descriptionKey, modifiers, true, false, 0, false); - }, [keyboardShortcut, onPressHandler]); + return KeyboardShortcut.subscribe(shortcutKey, singleExecution(onKeyboardShortcutPressHandler), descriptionKey, modifiers, true, false, 0, false); + }, [singleExecution, keyboardShortcut, onKeyboardShortcutPressHandler]); return ( Date: Thu, 22 Feb 2024 16:49:29 +0100 Subject: [PATCH 094/202] Revert "add a new onyx key - initial url" This reverts commit afd0f5f2abdf0f180e0b919593378dd3eab94e60. --- src/ONYXKEYS.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index f818adc189de..8fcbb106268a 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -389,11 +389,6 @@ const ONYXKEYS = { PERSONAL_BANK_ACCOUNT: 'personalBankAccountForm', PERSONAL_BANK_ACCOUNT_DRAFT: 'personalBankAccountFormDraft', }, - - /** A persisted initial (deeplinked) url. Could store a previous launch value. - * It means that even after a refresh, when there is no a new value, it keeps storing an old one. - */ - INITIAL_URL: 'initialUrl', } as const; type AllOnyxKeys = DeepValueOf; @@ -562,7 +557,6 @@ type OnyxValuesMapping = { [ONYXKEYS.PLAID_CURRENT_EVENT]: string; [ONYXKEYS.LOGS]: Record; [ONYXKEYS.SHOULD_STORE_LOGS]: boolean; - [ONYXKEYS.INITIAL_URL]: string; }; type OnyxValues = OnyxValuesMapping & OnyxCollectionValuesMapping & OnyxFormValuesMapping & OnyxFormDraftValuesMapping; From 6f1b2e3851ae71905419665472d75a10144915e5 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 22 Feb 2024 16:53:39 +0100 Subject: [PATCH 095/202] add session storage key const --- src/CONST.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CONST.ts b/src/CONST.ts index 6a57738d06ec..426867c8340d 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -3303,6 +3303,10 @@ const CONST = { ADDRESS: 3, }, }, + + SESSION_STORAGE_KEYS: { + INITIAL_URL: 'INITIAL_URL', + }, } as const; type Country = keyof typeof CONST.ALL_COUNTRIES; From 7297d97548d9cb321dbd10f032ca694c4ee84d3b Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 22 Feb 2024 16:53:59 +0100 Subject: [PATCH 096/202] integrate handling of a prev initial url via session storage --- src/libs/actions/Report.ts | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 2a20764255f7..8390435a84ae 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -47,6 +47,7 @@ import DateUtils from '@libs/DateUtils'; import * as EmojiUtils from '@libs/EmojiUtils'; import * as Environment from '@libs/Environment/Environment'; import * as ErrorUtils from '@libs/ErrorUtils'; +import getPlatform from '@libs/getPlatform'; import Log from '@libs/Log'; import Navigation from '@libs/Navigation/Navigation'; import LocalNotification from '@libs/Notification/LocalNotification'; @@ -173,25 +174,28 @@ const allReports: OnyxCollection = {}; const typingWatchTimers: Record = {}; let reportIDDeeplinkedFromOldDot: string | undefined; -Onyx.connect({ - key: ONYXKEYS.INITIAL_URL, - callback: (value) => { - Linking.getInitialURL().then((url) => { - const currentParams = new URLSearchParams(url ?? ''); - const currentExitToRoute = currentParams.get('exitTo') ?? ''; - const {reportID: currentReportID} = ReportUtils.parseReportRouteParams(currentExitToRoute); +Linking.getInitialURL().then((url) => { + const isWebOrDesktop = ([CONST.PLATFORM.DESKTOP, CONST.PLATFORM.WEB] as unknown as string).includes(getPlatform()); - const prevParams = new URLSearchParams(value ?? ''); - const prevExitToRoute = prevParams.get('exitTo') ?? ''; - const {reportID: prevReportID} = ReportUtils.parseReportRouteParams(prevExitToRoute); + if (!isWebOrDesktop) { + return; + } - reportIDDeeplinkedFromOldDot = currentReportID || prevReportID; + const currentParams = new URLSearchParams(url ?? ''); + const currentExitToRoute = currentParams.get('exitTo') ?? ''; + const {reportID: currentReportID} = ReportUtils.parseReportRouteParams(currentExitToRoute); - if (currentReportID) { - Onyx.set(ONYXKEYS.INITIAL_URL, url); - } - }); - }, + const prevUrl = sessionStorage.getItem(CONST.SESSION_STORAGE_KEYS.INITIAL_URL); + + const prevParams = new URLSearchParams(prevUrl ?? ''); + const prevExitToRoute = prevParams.get('exitTo') ?? ''; + const {reportID: prevReportID} = ReportUtils.parseReportRouteParams(prevExitToRoute); + + reportIDDeeplinkedFromOldDot = currentReportID || prevReportID; + + if (currentReportID && url) { + sessionStorage.setItem(CONST.SESSION_STORAGE_KEYS.INITIAL_URL, url); + } }); let lastVisitedPath: string | undefined; @@ -517,7 +521,7 @@ function addActions(reportID: string, text = '', file?: File) { }); DateUtils.setTimezoneUpdated(); } - + return; API.write(commandName, parameters, { optimisticData, successData, From ba66ff05af6a19c564f37be03c11e22d33b00ce0 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 22 Feb 2024 16:55:27 +0100 Subject: [PATCH 097/202] remove dev. mode return --- src/libs/actions/Report.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 8390435a84ae..12b57d5bbf35 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -521,7 +521,7 @@ function addActions(reportID: string, text = '', file?: File) { }); DateUtils.setTimezoneUpdated(); } - return; + API.write(commandName, parameters, { optimisticData, successData, From 036dc298c244a29284c13b61d4783109602509cc Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 22 Feb 2024 16:57:41 +0100 Subject: [PATCH 098/202] check for web only --- src/libs/actions/Report.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 12b57d5bbf35..a8a974dc0919 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -175,9 +175,9 @@ const typingWatchTimers: Record = {}; let reportIDDeeplinkedFromOldDot: string | undefined; Linking.getInitialURL().then((url) => { - const isWebOrDesktop = ([CONST.PLATFORM.DESKTOP, CONST.PLATFORM.WEB] as unknown as string).includes(getPlatform()); + const isWeb = ([CONST.PLATFORM.WEB] as unknown as string).includes(getPlatform()); - if (!isWebOrDesktop) { + if (!isWeb) { return; } From 21be35da369fabb68de5590ebc676b5e4173b2a8 Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Thu, 22 Feb 2024 18:09:52 +0100 Subject: [PATCH 099/202] Add on begin pan gesture event --- .../VideoPlayerControls/VolumeButton/index.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js b/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js index 1c1d042d3893..4cba4506dc0e 100644 --- a/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js +++ b/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js @@ -42,15 +42,20 @@ function VolumeButton({style, small}) { setSliderHeight(e.nativeEvent.layout.height); }; + const gestureEventHandler = (event) => { + const val = Math.floor((1 - event.y / sliderHeight) * 100) / 100; + volume.value = Math.min(Math.max(val, 0), 1); + }; + const pan = Gesture.Pan() - .onBegin(() => { + .onBegin((event) => { runOnJS(setIsSliderBeingUsed)(true); + gestureEventHandler(event); }) .onChange((event) => { - const val = Math.floor((1 - event.y / sliderHeight) * 100) / 100; - volume.value = Math.min(Math.max(val, 0), 1); + gestureEventHandler(event); }) - .onEnd(() => { + .onFinished(() => { runOnJS(setIsSliderBeingUsed)(false); }); From 47264892cf3ca09bceb5e2550dc84e8673e95d3f Mon Sep 17 00:00:00 2001 From: Kamil Owczarz Date: Thu, 22 Feb 2024 18:20:46 +0100 Subject: [PATCH 100/202] Cleanup --- .../VideoPlayer/VideoPlayerControls/VolumeButton/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js b/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js index 4cba4506dc0e..b0757eb7df68 100644 --- a/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js +++ b/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js @@ -55,7 +55,7 @@ function VolumeButton({style, small}) { .onChange((event) => { gestureEventHandler(event); }) - .onFinished(() => { + .onFinalize(() => { runOnJS(setIsSliderBeingUsed)(false); }); From 95f432f162593cae937504f15ebc9f925558b3e8 Mon Sep 17 00:00:00 2001 From: codinggeek2023 Date: Fri, 23 Feb 2024 00:20:36 +0530 Subject: [PATCH 101/202] Change finish to stop to avoid confusion --- src/components/DistanceEReceipt.tsx | 2 -- src/components/DistanceRequest/DistanceRequestRenderItem.tsx | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/DistanceEReceipt.tsx b/src/components/DistanceEReceipt.tsx index 9846cfa04257..941d63c1bf94 100644 --- a/src/components/DistanceEReceipt.tsx +++ b/src/components/DistanceEReceipt.tsx @@ -75,8 +75,6 @@ function DistanceEReceipt({transaction}: DistanceEReceiptProps) { let descriptionKey: TranslationPaths = 'distance.waypointDescription.stop'; if (index === 0) { descriptionKey = 'distance.waypointDescription.start'; - } else if (index === Object.keys(waypoints).length - 1) { - descriptionKey = 'distance.waypointDescription.finish'; } return ( diff --git a/src/components/DistanceRequest/DistanceRequestRenderItem.tsx b/src/components/DistanceRequest/DistanceRequestRenderItem.tsx index a1f3efbf0291..57e4fb0b530e 100644 --- a/src/components/DistanceRequest/DistanceRequestRenderItem.tsx +++ b/src/components/DistanceRequest/DistanceRequestRenderItem.tsx @@ -42,7 +42,7 @@ function DistanceRequestRenderItem({waypoints, item = '', onSecondaryInteraction descriptionKey += 'start'; waypointIcon = Expensicons.DotIndicatorUnfilled; } else if (index === lastWaypointIndex) { - descriptionKey += 'finish'; + descriptionKey += 'stop'; waypointIcon = Expensicons.Location; } else { descriptionKey += 'stop'; From 850e9727c20d66d8f147382f0239a8b10f100e5d Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 23 Feb 2024 08:48:17 +0100 Subject: [PATCH 102/202] [TS migration] Migrate 'index.js' test --- src/libs/E2E/client.ts | 10 +++ tests/e2e/server/{index.js => index.ts} | 108 +++++++++++++----------- tests/e2e/utils/logger.js | 10 +-- 3 files changed, 70 insertions(+), 58 deletions(-) rename tests/e2e/server/{index.js => index.ts} (61%) diff --git a/src/libs/E2E/client.ts b/src/libs/E2E/client.ts index 265c55c4a230..f76bdf2ed9a5 100644 --- a/src/libs/E2E/client.ts +++ b/src/libs/E2E/client.ts @@ -3,10 +3,19 @@ import Routes from '../../../tests/e2e/server/routes'; import type {NetworkCacheMap, TestConfig} from './types'; type TestResult = { + /** Name of the test */ name: string; + + /** The branch where test were running */ branch?: string; + + /** Duration in milliseconds */ duration?: number; + + /** Optional, if set indicates that the test run failed and has no valid results. */ error?: string; + + /** Render count */ renderCount?: number; }; @@ -113,3 +122,4 @@ export default { updateNetworkCache, getNetworkCache, }; +export type {TestResult, NativeCommand}; diff --git a/tests/e2e/server/index.js b/tests/e2e/server/index.ts similarity index 61% rename from tests/e2e/server/index.js rename to tests/e2e/server/index.ts index 82152245d8e2..be3cd20c7213 100644 --- a/tests/e2e/server/index.js +++ b/tests/e2e/server/index.ts @@ -1,15 +1,42 @@ import {createServer} from 'http'; +import type {IncomingMessage, ServerResponse} from 'http'; +import type {NativeCommand, TestResult} from '@libs/E2E/client'; +import type {NetworkCacheMap, TestConfig} from '@libs/E2E/types'; import config from '../config'; import * as nativeCommands from '../nativeCommands'; import * as Logger from '../utils/logger'; import Routes from './routes'; -const PORT = process.env.PORT || config.SERVER_PORT; +type NetworkCache = { + appInstanceId: string; + cache: NetworkCacheMap; +}; + +type RequestData = TestResult | NativeCommand | NetworkCache; + +type TestStartedListener = (testConfig?: TestConfig) => void; + +type TestDoneListener = () => void; + +type TestResultListener = (testResult: TestResult) => void; + +type AddListener = (listener: TListener) => void; + +type ServerInstance = { + setTestConfig: (testConfig: TestConfig) => void; + addTestStartedListener: AddListener; + addTestResultListener: AddListener; + addTestDoneListener: AddListener; + start: () => Promise; + stop: () => Promise; +}; + +const PORT = process.env.PORT ?? config.SERVER_PORT; // Gets the request data as a string -const getReqData = (req) => { +const getReqData = (req: IncomingMessage): Promise => { let data = ''; - req.on('data', (chunk) => { + req.on('data', (chunk: string) => { data += chunk; }); @@ -21,16 +48,16 @@ const getReqData = (req) => { }; // Expects a POST request with JSON data. Returns parsed JSON data. -const getPostJSONRequestData = (req, res) => { +const getPostJSONRequestData = (req: IncomingMessage, res: ServerResponse): Promise | undefined => { if (req.method !== 'POST') { res.statusCode = 400; res.end('Unsupported method'); return; } - return getReqData(req).then((data) => { + return getReqData(req).then((data): TRequestData | undefined => { try { - return JSON.parse(data); + return JSON.parse(data) as TRequestData; } catch (e) { Logger.info('❌ Failed to parse request data', data); res.statusCode = 400; @@ -39,9 +66,9 @@ const getPostJSONRequestData = (req, res) => { }); }; -const createListenerState = () => { - const listeners = []; - const addListener = (listener) => { +const createListenerState = (): [TListener[], AddListener] => { + const listeners: TListener[] = []; + const addListener = (listener: TListener) => { listeners.push(listener); return () => { const index = listeners.indexOf(listener); @@ -54,20 +81,6 @@ const createListenerState = () => { return [listeners, addListener]; }; -/** - * The test result object that a client might submit to the server. - * @typedef TestResult - * @property {string} name - * @property {number} duration Milliseconds - * @property {string} [error] Optional, if set indicates that the test run failed and has no valid results. - */ - -/** - * @callback listener - * @param {TestResult} testResult - */ - -// eslint-disable-next-line valid-jsdoc /** * Creates a new http server. * The server just has two endpoints: @@ -78,35 +91,32 @@ const createListenerState = () => { * * It returns an instance to which you can add listeners for the test results, and test done events. */ -const createServerInstance = () => { - const [testStartedListeners, addTestStartedListener] = createListenerState(); - const [testResultListeners, addTestResultListener] = createListenerState(); - const [testDoneListeners, addTestDoneListener] = createListenerState(); - - let activeTestConfig; - const networkCache = {}; - - /** - * @param {TestConfig} testConfig - */ - const setTestConfig = (testConfig) => { +const createServerInstance = (): ServerInstance => { + const [testStartedListeners, addTestStartedListener] = createListenerState(); + const [testResultListeners, addTestResultListener] = createListenerState(); + const [testDoneListeners, addTestDoneListener] = createListenerState(); + + let activeTestConfig: TestConfig | undefined; + const networkCache: Record = {}; + + const setTestConfig = (testConfig: TestConfig) => { activeTestConfig = testConfig; }; - const server = createServer((req, res) => { + const server = createServer((req, res): ServerResponse | void => { res.statusCode = 200; switch (req.url) { case Routes.testConfig: { testStartedListeners.forEach((listener) => listener(activeTestConfig)); - if (activeTestConfig == null) { + if (!activeTestConfig) { throw new Error('No test config set'); } return res.end(JSON.stringify(activeTestConfig)); } case Routes.testResults: { - getPostJSONRequestData(req, res).then((data) => { - if (data == null) { + getPostJSONRequestData(req, res)?.then((data) => { + if (!data) { // The getPostJSONRequestData function already handled the response return; } @@ -128,9 +138,9 @@ const createServerInstance = () => { } case Routes.testNativeCommand: { - getPostJSONRequestData(req, res) - .then((data) => - nativeCommands.executeFromPayload(data.actionName, data.payload).then((status) => { + getPostJSONRequestData(req, res) + ?.then((data) => + nativeCommands.executeFromPayload(data?.actionName, data?.payload).then((status) => { if (status) { res.end('ok'); return; @@ -148,8 +158,8 @@ const createServerInstance = () => { } case Routes.testGetNetworkCache: { - getPostJSONRequestData(req, res).then((data) => { - const appInstanceId = data && data.appInstanceId; + getPostJSONRequestData(req, res)?.then((data) => { + const appInstanceId = data?.appInstanceId; if (!appInstanceId) { res.statusCode = 400; res.end('Invalid request missing appInstanceId'); @@ -164,9 +174,9 @@ const createServerInstance = () => { } case Routes.testUpdateNetworkCache: { - getPostJSONRequestData(req, res).then((data) => { - const appInstanceId = data && data.appInstanceId; - const cache = data && data.cache; + getPostJSONRequestData(req, res)?.then((data) => { + const appInstanceId = data?.appInstanceId; + const cache = data?.cache; if (!appInstanceId || !cache) { res.statusCode = 400; res.end('Invalid request missing appInstanceId or cache'); @@ -191,8 +201,8 @@ const createServerInstance = () => { addTestStartedListener, addTestResultListener, addTestDoneListener, - start: () => new Promise((resolve) => server.listen(PORT, resolve)), - stop: () => new Promise((resolve) => server.close(resolve)), + start: () => new Promise((resolve) => server.listen(PORT, resolve)), + stop: () => new Promise((resolve) => server.close(resolve)), }; }; diff --git a/tests/e2e/utils/logger.js b/tests/e2e/utils/logger.js index d0770b7aa8e4..6a39b4c10328 100644 --- a/tests/e2e/utils/logger.js +++ b/tests/e2e/utils/logger.js @@ -66,12 +66,4 @@ const error = (...args) => { log(...lines); }; -module.exports = { - log, - info, - warn, - note, - error, - success, - writeToLogFile, -}; +export {log, info, warn, note, error, success, writeToLogFile}; From 3582599e0cd2dd7f673476605619716c1642a52e Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Fri, 23 Feb 2024 14:55:20 +0530 Subject: [PATCH 103/202] submit rate page on enter --- .../workspace/reimburse/WorkspaceRateAndUnitPage/RatePage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/workspace/reimburse/WorkspaceRateAndUnitPage/RatePage.tsx b/src/pages/workspace/reimburse/WorkspaceRateAndUnitPage/RatePage.tsx index d78ccb82d704..65be798f9520 100644 --- a/src/pages/workspace/reimburse/WorkspaceRateAndUnitPage/RatePage.tsx +++ b/src/pages/workspace/reimburse/WorkspaceRateAndUnitPage/RatePage.tsx @@ -92,6 +92,7 @@ function WorkspaceRatePage(props: WorkspaceRatePageProps) { shouldHideFixErrorsAlert submitFlexEnabled={false} submitButtonStyles={[styles.mh5, styles.mt0]} + disablePressOnEnter={false} > Date: Fri, 23 Feb 2024 10:30:27 +0100 Subject: [PATCH 104/202] [TS migration] Migrate 'ReimbursementAccountLoadingIndicator.js' component --- ...=> ReimbursementAccountLoadingIndicator.tsx} | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) rename src/components/{ReimbursementAccountLoadingIndicator.js => ReimbursementAccountLoadingIndicator.tsx} (75%) diff --git a/src/components/ReimbursementAccountLoadingIndicator.js b/src/components/ReimbursementAccountLoadingIndicator.tsx similarity index 75% rename from src/components/ReimbursementAccountLoadingIndicator.js rename to src/components/ReimbursementAccountLoadingIndicator.tsx index 141e056afd93..cc9beb513002 100644 --- a/src/components/ReimbursementAccountLoadingIndicator.js +++ b/src/components/ReimbursementAccountLoadingIndicator.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {StyleSheet, View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; @@ -10,14 +9,15 @@ import LottieAnimations from './LottieAnimations'; import ScreenWrapper from './ScreenWrapper'; import Text from './Text'; -const propTypes = { +type ReimbursementAccountLoadingIndicatorProps = { /** Method to trigger when pressing back button of the header */ - onBackButtonPress: PropTypes.func.isRequired, + onBackButtonPress: () => void; }; -function ReimbursementAccountLoadingIndicator(props) { +function ReimbursementAccountLoadingIndicator({onBackButtonPress}: ReimbursementAccountLoadingIndicatorProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); + return ( - + - - {translate('reimbursementAccountLoadingAnimation.explanationLine')} + + {translate('reimbursementAccountLoadingAnimation.explanationLine')} @@ -46,7 +46,6 @@ function ReimbursementAccountLoadingIndicator(props) { ); } -ReimbursementAccountLoadingIndicator.propTypes = propTypes; ReimbursementAccountLoadingIndicator.displayName = 'ReimbursementAccountLoadingIndicator'; export default ReimbursementAccountLoadingIndicator; From 2e829a169702d72ec6a526ed432b917576baa810 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Fri, 23 Feb 2024 11:11:33 +0100 Subject: [PATCH 105/202] fix: typecheck --- src/pages/home/report/ReportActionCompose/SuggestionMention.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx index f284596040b7..54d21d637d09 100644 --- a/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx +++ b/src/pages/home/report/ReportActionCompose/SuggestionMention.tsx @@ -152,7 +152,7 @@ function SuggestionMention( sortedPersonalDetails.slice(0, CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS - suggestions.length).forEach((detail) => { suggestions.push({ text: PersonalDetailsUtils.getDisplayNameOrDefault(detail), - alternateText: formatPhoneNumber(detail?.login), + alternateText: formatPhoneNumber(detail?.login ?? ''), login: detail?.login, icons: [ { From 2e84755706a6fb6e56bcc6c5136e1573f5810d08 Mon Sep 17 00:00:00 2001 From: Cong Pham Date: Fri, 23 Feb 2024 18:33:38 +0700 Subject: [PATCH 106/202] 33546 update fix by use case --- src/components/ScreenWrapper.tsx | 6 +++++- src/pages/workspace/WorkspaceInvitePage.tsx | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/ScreenWrapper.tsx b/src/components/ScreenWrapper.tsx index 198b47cb4259..7c9219c16286 100644 --- a/src/components/ScreenWrapper.tsx +++ b/src/components/ScreenWrapper.tsx @@ -83,6 +83,9 @@ type ScreenWrapperProps = { /** Whether to avoid scroll on virtual viewport */ shouldAvoidScrollOnVirtualViewport?: boolean; + /** Whether to use cached virtual viewport height */ + shouldUseCachedViewportHeight?: boolean; + /** * The navigation prop is passed by the navigator. It is used to trigger the onEntryTransitionEnd callback * when the screen transition ends. @@ -115,6 +118,7 @@ function ScreenWrapper( navigation: navigationProp, shouldAvoidScrollOnVirtualViewport = true, shouldShowOfflineIndicatorInWideScreen = false, + shouldUseCachedViewportHeight = false, }: ScreenWrapperProps, ref: ForwardedRef, ) { @@ -127,7 +131,7 @@ function ScreenWrapper( */ const navigationFallback = useNavigation>(); const navigation = navigationProp ?? navigationFallback; - const {windowHeight, isSmallScreenWidth} = useWindowDimensions(shouldEnableMaxHeight); + const {windowHeight, isSmallScreenWidth} = useWindowDimensions(shouldUseCachedViewportHeight); const {initialHeight} = useInitialDimensions(); const styles = useThemeStyles(); const keyboardState = useKeyboardState(); diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index 8efc7d7c6a1e..1a41d0710c5d 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -285,6 +285,7 @@ function WorkspaceInvitePage({ return ( Date: Fri, 23 Feb 2024 16:17:06 +0100 Subject: [PATCH 107/202] handle if not wab as before --- src/libs/actions/Report.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index acd4fe35d110..c94b93c32a70 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -177,17 +177,17 @@ const typingWatchTimers: Record = {}; let reportIDDeeplinkedFromOldDot: string | undefined; Linking.getInitialURL().then((url) => { const isWeb = ([CONST.PLATFORM.WEB] as unknown as string).includes(getPlatform()); + const currentParams = new URLSearchParams(url ?? ''); + const currentExitToRoute = currentParams.get('exitTo') ?? ''; + const {reportID: currentReportID} = ReportUtils.parseReportRouteParams(currentExitToRoute); if (!isWeb) { + reportIDDeeplinkedFromOldDot = currentReportID; + return; } - const currentParams = new URLSearchParams(url ?? ''); - const currentExitToRoute = currentParams.get('exitTo') ?? ''; - const {reportID: currentReportID} = ReportUtils.parseReportRouteParams(currentExitToRoute); - const prevUrl = sessionStorage.getItem(CONST.SESSION_STORAGE_KEYS.INITIAL_URL); - const prevParams = new URLSearchParams(prevUrl ?? ''); const prevExitToRoute = prevParams.get('exitTo') ?? ''; const {reportID: prevReportID} = ReportUtils.parseReportRouteParams(prevExitToRoute); From 903527ff2ac49138d5248b140d43c3819c2f2500 Mon Sep 17 00:00:00 2001 From: Pavlo Tsimura Date: Fri, 23 Feb 2024 20:28:20 +0100 Subject: [PATCH 108/202] Use formula for the optimistic expense report --- src/libs/ReportUtils.ts | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index e0c474e3d8fb..6b22c48ac534 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1,3 +1,4 @@ +import {format} from 'date-fns'; import ExpensiMark from 'expensify-common/lib/ExpensiMark'; import Str from 'expensify-common/lib/str'; import {isEmpty} from 'lodash'; @@ -1996,6 +1997,13 @@ function getFormulaTypeReportField(reportFields: PolicyReportFields) { return Object.values(reportFields).find((field) => field.type === 'formula'); } +/** + * Given a set of report fields, return the field that refers to title + */ +function getTitleReportField(reportFields: PolicyReportFields) { + return Object.values(reportFields).find((field) => isReportFieldOfTypeTitle(field)); +} + /** * Get the report fields attached to the policy given policyID */ @@ -2904,6 +2912,26 @@ function buildOptimisticIOUReport(payeeAccountID: number, payerAccountID: number }; } +/** + * Populates the report field formula with the values from the report and policy. + * Currently, is supports only optimistic expense reports. + * Each formula field is either replaced with a value, or removed. + * If after all replacements the formula is empty, the original formula is returned. + */ +function populateOptimisticReportFormula(formula: string, report: OptimisticExpenseReport, policy: Policy | EmptyObject): string { + const result = formula + .replaceAll('{report:id}', report.reportID) + // We don't translate because the server response is always in English + .replaceAll('{report:type}', 'Expense Report') + .replaceAll('{report:startdate}', report.lastVisibleActionCreated ? format(new Date(report.lastVisibleActionCreated), CONST.DATE.FNS_FORMAT_STRING) : '') + .replaceAll('{report:total}', report.total?.toString() ?? '') + .replaceAll('{report:currency}', report.currency ?? '') + .replaceAll('{report:policyname}', policy.name ?? '') + .replaceAll(/\{report:(.+)}/g, ''); + + return result.trim().length ? result : formula; +} + /** * Builds an optimistic Expense report with a randomly generated reportID * @@ -2913,7 +2941,6 @@ function buildOptimisticIOUReport(payeeAccountID: number, payerAccountID: number * @param total - Amount in cents * @param currency */ - function buildOptimisticExpenseReport(chatReportID: string, policyID: string, payeeAccountID: number, total: number, currency: string): OptimisticExpenseReport { // The amount for Expense reports are stored as negative value in the database const storedTotal = total * -1; @@ -2934,7 +2961,6 @@ function buildOptimisticExpenseReport(chatReportID: string, policyID: string, pa type: CONST.REPORT.TYPE.EXPENSE, ownerAccountID: payeeAccountID, currency, - // We don't translate reportName because the server response is always in English reportName: `${policyName} owes ${formattedTotal}`, stateNum, @@ -2950,6 +2976,11 @@ function buildOptimisticExpenseReport(chatReportID: string, policyID: string, pa expenseReport.managerID = policy.submitsTo; } + const titleReportField = getTitleReportField(getReportFieldsByPolicyID(policyID) ?? {}); + if (!!titleReportField && reportFieldsEnabled(expenseReport)) { + expenseReport.reportName = populateOptimisticReportFormula(titleReportField.defaultValue, expenseReport, policy); + } + return expenseReport; } From 55884df73116a71ed4ef78645a907f5ece5c872a Mon Sep 17 00:00:00 2001 From: tienifr Date: Sat, 24 Feb 2024 06:14:50 +0700 Subject: [PATCH 109/202] fix lint --- src/components/PDFView/index.native.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/PDFView/index.native.js b/src/components/PDFView/index.native.js index f47aeafd5316..f5a74011b6cd 100644 --- a/src/components/PDFView/index.native.js +++ b/src/components/PDFView/index.native.js @@ -104,8 +104,8 @@ function PDFView({onToggleKeyboard, onLoadComplete, fileName, onPress, isFocused /** * After the PDF is successfully loaded hide PDFPasswordForm and the loading * indicator. - * @param numberOfPages - * @param path - Path to cache location + * @param {Number} numberOfPages + * @param {Number} path - Path to cache location */ const finishPDFLoad = (numberOfPages, path) => { setShouldRequestPassword(false); From aa0a8af1959fb30b92deff8e20d483e792eb49ba Mon Sep 17 00:00:00 2001 From: Abdullah Alsigar Date: Sun, 25 Feb 2024 10:24:46 +0300 Subject: [PATCH 110/202] lock capturePhoto Prevent calling the function while navigation is going on --- .../step/IOURequestStepScan/index.native.js | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.js b/src/pages/iou/request/step/IOURequestStepScan/index.native.js index 25d242db5342..84a9e419760b 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.js +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.js @@ -30,6 +30,7 @@ import reportPropTypes from '@pages/reportPropTypes'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; +import {useNavigation} from "@react-navigation/native"; import * as CameraPermission from './CameraPermission'; import NavigationAwareCamera from './NavigationAwareCamera'; @@ -61,12 +62,24 @@ function IOURequestStepScan({ const styles = useThemeStyles(); const devices = useCameraDevices('wide-angle-camera'); const device = devices.back; + const navigation = useNavigation(); const camera = useRef(null); const [flash, setFlash] = useState(false); const [cameraPermissionStatus, setCameraPermissionStatus] = useState(undefined); const askedForPermission = useRef(false); + const [didCapturePhoto, setDidCapturePhoto] = useState(false); + useEffect(() => { + const unsubscribe = navigation.addListener('focus', () => { + setDidCapturePhoto(false); + }); + + return () => { + unsubscribe(); + } + }, [navigation]); + const {translate} = useLocalize(); const askForPermissions = (showPermissionsAlert = true) => { @@ -236,6 +249,10 @@ function IOURequestStepScan({ return; } + if (didCapturePhoto) { + return; + } + return camera.current .takePhoto({ qualityPrioritization: 'speed', @@ -253,13 +270,15 @@ function IOURequestStepScan({ return; } + setDidCapturePhoto(true); navigateToConfirmationStep(); }) .catch((error) => { + setDidCapturePhoto(false); showCameraAlert(); Log.warn('Error taking photo', error); }); - }, [flash, action, translate, transactionID, updateScanAndNavigate, navigateToConfirmationStep, cameraPermissionStatus]); + }, [flash, action, translate, transactionID, updateScanAndNavigate, navigateToConfirmationStep, cameraPermissionStatus, didCapturePhoto]); // Wait for camera permission status to render if (cameraPermissionStatus == null) { From 3cc9dd5064296fc15dd76b8772cfdb776b7194d8 Mon Sep 17 00:00:00 2001 From: Bartosz Grajdek Date: Sun, 25 Feb 2024 21:35:49 +0100 Subject: [PATCH 111/202] feat: upgrade reanimated to v3.7.1 --- ios/Podfile.lock | 4 ++-- package-lock.json | 8 ++++---- package.json | 2 +- ...ative-reanimated+3.7.1+001+fix-boost-dependency.patch} | 0 ...ed+3.7.0.patch => react-native-reanimated+3.7.1.patch} | 0 5 files changed, 7 insertions(+), 7 deletions(-) rename patches/{react-native-reanimated+3.7.0+001+fix-boost-dependency.patch => react-native-reanimated+3.7.1+001+fix-boost-dependency.patch} (100%) rename patches/{react-native-reanimated+3.7.0.patch => react-native-reanimated+3.7.1.patch} (100%) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index e4f988173f40..93c4f6bbc2a9 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1434,7 +1434,7 @@ PODS: - React-Core - RNReactNativeHapticFeedback (2.2.0): - React-Core - - RNReanimated (3.7.0): + - RNReanimated (3.7.1): - glog - RCT-Folly (= 2022.05.16.00) - React-Core @@ -1988,7 +1988,7 @@ SPEC CHECKSUMS: rnmapbox-maps: fcf7f1cbdc8bd7569c267d07284e8a5c7bee06ed RNPermissions: 9b086c8f05b2e2faa587fdc31f4c5ab4509728aa RNReactNativeHapticFeedback: ec56a5f81c3941206fd85625fa669ffc7b4545f9 - RNReanimated: 7d6d32f238f914f13d9d6fb45c0aef557f7f901e + RNReanimated: beb07f7f900543928467da8107c175d1e57a1049 RNScreens: b582cb834dc4133307562e930e8fa914b8c04ef2 RNSound: 6c156f925295bdc83e8e422e7d8b38d33bc71852 RNSVG: ba3e7232f45e34b7b47e74472386cf4e1a676d0a diff --git a/package-lock.json b/package-lock.json index 3e4dfd77bccf..fc5c898f9b14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -106,7 +106,7 @@ "react-native-plaid-link-sdk": "10.8.0", "react-native-qrcode-svg": "^6.2.0", "react-native-quick-sqlite": "^8.0.0-beta.2", - "react-native-reanimated": "^3.7.0", + "react-native-reanimated": "^3.7.1", "react-native-render-html": "6.3.1", "react-native-safe-area-context": "4.8.2", "react-native-screens": "3.29.0", @@ -45270,9 +45270,9 @@ } }, "node_modules/react-native-reanimated": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.7.0.tgz", - "integrity": "sha512-KM+MKa3CJWqsF4GlOLLKBxTR2NEcrg5/HP9J2b6Dfgvll1sjZPywCOEEIh967SboEU8N9LjYZuoVm2UoXGxp2Q==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.7.1.tgz", + "integrity": "sha512-bapCxhnS58+GZynQmA/f5U8vRlmhXlI/WhYg0dqnNAGXHNIc+38ahRWcG8iK8e0R2v9M8Ky2ZWObEC6bmweofg==", "dependencies": { "@babel/plugin-transform-object-assign": "^7.16.7", "@babel/preset-typescript": "^7.16.7", diff --git a/package.json b/package.json index aac474b0f4a2..0f05b48572eb 100644 --- a/package.json +++ b/package.json @@ -154,7 +154,7 @@ "react-native-plaid-link-sdk": "10.8.0", "react-native-qrcode-svg": "^6.2.0", "react-native-quick-sqlite": "^8.0.0-beta.2", - "react-native-reanimated": "^3.7.0", + "react-native-reanimated": "^3.7.1", "react-native-render-html": "6.3.1", "react-native-safe-area-context": "4.8.2", "react-native-screens": "3.29.0", diff --git a/patches/react-native-reanimated+3.7.0+001+fix-boost-dependency.patch b/patches/react-native-reanimated+3.7.1+001+fix-boost-dependency.patch similarity index 100% rename from patches/react-native-reanimated+3.7.0+001+fix-boost-dependency.patch rename to patches/react-native-reanimated+3.7.1+001+fix-boost-dependency.patch diff --git a/patches/react-native-reanimated+3.7.0.patch b/patches/react-native-reanimated+3.7.1.patch similarity index 100% rename from patches/react-native-reanimated+3.7.0.patch rename to patches/react-native-reanimated+3.7.1.patch From 637af8a0521244a4bc5e94818701ed05677c923a Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Mon, 26 Feb 2024 13:56:16 +0800 Subject: [PATCH 112/202] remove unused param --- src/libs/actions/Report.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index f29f8a4fbaab..b1405acad98e 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -1719,7 +1719,7 @@ function updateWriteCapabilityAndNavigate(report: Report, newValue: WriteCapabil /** * Navigates to the 1:1 report with Concierge */ -function navigateToConciergeChat(shouldDismissModal = false, shouldPopCurrentScreen = false, checkIfCurrentPageActive = () => true) { +function navigateToConciergeChat(shouldDismissModal = false, checkIfCurrentPageActive = () => true) { // If conciergeChatReportID contains a concierge report ID, we navigate to the concierge chat using the stored report ID. // Otherwise, we would find the concierge chat and navigate to it. if (!conciergeChatReportID) { @@ -1730,17 +1730,11 @@ function navigateToConciergeChat(shouldDismissModal = false, shouldPopCurrentScr if (!checkIfCurrentPageActive()) { return; } - if (shouldPopCurrentScreen && !shouldDismissModal) { - Navigation.goBack(); - } navigateToAndOpenReport([CONST.EMAIL.CONCIERGE], shouldDismissModal); }); } else if (shouldDismissModal) { Navigation.dismissModal(conciergeChatReportID); } else { - if (shouldPopCurrentScreen) { - Navigation.goBack(); - } Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(conciergeChatReportID)); } } From f5a0bd4d4a892a80e7150150f790811e06ea8460 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Mon, 26 Feb 2024 13:56:21 +0800 Subject: [PATCH 113/202] fix param --- src/pages/OnboardEngagement/PurposeForUsingExpensifyPage.tsx | 2 +- .../ConnectBankAccount/ConnectBankAccount.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/OnboardEngagement/PurposeForUsingExpensifyPage.tsx b/src/pages/OnboardEngagement/PurposeForUsingExpensifyPage.tsx index 025dcafd9740..9ad19482a4a7 100644 --- a/src/pages/OnboardEngagement/PurposeForUsingExpensifyPage.tsx +++ b/src/pages/OnboardEngagement/PurposeForUsingExpensifyPage.tsx @@ -90,7 +90,7 @@ function PurposeForUsingExpensifyModal() { } Report.completeEngagementModal(message, choice); - Report.navigateToConciergeChat(false, true); + Report.navigateToConciergeChat(true); }, []); const menuItems: MenuItemProps[] = useMemo( diff --git a/src/pages/ReimbursementAccount/ConnectBankAccount/ConnectBankAccount.tsx b/src/pages/ReimbursementAccount/ConnectBankAccount/ConnectBankAccount.tsx index 1682cb66f7c8..078c216d836c 100644 --- a/src/pages/ReimbursementAccount/ConnectBankAccount/ConnectBankAccount.tsx +++ b/src/pages/ReimbursementAccount/ConnectBankAccount/ConnectBankAccount.tsx @@ -39,7 +39,7 @@ function ConnectBankAccount({reimbursementAccount, onBackButtonPress, account, p const styles = useThemeStyles(); const {translate} = useLocalize(); - const handleNavigateToConciergeChat = () => Report.navigateToConciergeChat(false, true); + const handleNavigateToConciergeChat = () => Report.navigateToConciergeChat(true); const bankAccountState = reimbursementAccount.achData?.state ?? ''; // If a user tries to navigate directly to the validate page we'll show them the EnableStep From 2db3763dc9d2119abd48ac1b93a934442f4e74a5 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Mon, 26 Feb 2024 17:24:28 +0800 Subject: [PATCH 114/202] pop the screen --- .../DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx b/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx index ed91b51a2a44..16996768eaf0 100644 --- a/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx +++ b/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx @@ -45,7 +45,7 @@ function DeeplinkRedirectLoadingIndicator({openLinkInBrowser, session}: Deeplink {translate('deeplinkWrapper.loggedInAs', {email: session?.email ?? ''})} {translate('deeplinkWrapper.doNotSeePrompt')} openLinkInBrowser(true)}>{translate('deeplinkWrapper.tryAgain')} - {translate('deeplinkWrapper.or')} Navigation.navigate(ROUTES.HOME)}>{translate('deeplinkWrapper.continueInWeb')}. + {translate('deeplinkWrapper.or')} Navigation.goBack()}>{translate('deeplinkWrapper.continueInWeb')}. From 479cf7adad63f36bf27e73effd9ce61675273656 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 26 Feb 2024 10:46:17 +0100 Subject: [PATCH 115/202] fix: typecheck --- .../MoneyRequestConfirmationList.tsx | 18 +++++++++++------- src/languages/types.ts | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 252b0ad44384..dbc94502bdd3 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -345,11 +345,11 @@ function MoneyRequestConfirmationList({ } else if (!!(receiptPath && isTypeRequest) || isDistanceRequestWithPendingRoute) { text = translate('iou.request'); if (iouAmount !== 0) { - text = translate('iou.requestAmount', {amount: Number(formattedAmount)}); + text = translate('iou.requestAmount', {amount: formattedAmount}); } } else { const translationKey = isSplitBill ? 'iou.splitAmount' : 'iou.requestAmount'; - text = translate(translationKey, {amount: Number(formattedAmount)}); + text = translate(translationKey, {amount: formattedAmount}); } return [ { @@ -785,11 +785,15 @@ function MoneyRequestConfirmationList({ description={translate('common.category')} numberOfLinesTitle={2} onPress={() => { - if (isEditingSplitBill) { - Navigation.navigate(ROUTES.EDIT_SPLIT_BILL.getRoute(reportID ?? '', reportActionID ?? '', CONST.EDIT_REQUEST_FIELD.CATEGORY)); - return; - } - Navigation.navigate(ROUTES.MONEY_REQUEST_CATEGORY.getRoute(iouType, reportID)); + Navigation.navigate( + ROUTES.MONEY_REQUEST_STEP_CATEGORY.getRoute( + CONST.IOU.ACTION.EDIT, + iouType, + transaction?.transactionID ?? '', + reportID ?? '', + Navigation.getActiveRouteWithoutParams(), + ), + ); }} style={styles.moneyRequestMenuItem} titleStyle={styles.flex1} diff --git a/src/languages/types.ts b/src/languages/types.ts index 410c8e1c2085..abfe2c3f7750 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -109,7 +109,7 @@ type RequestAmountParams = {amount: string}; type RequestedAmountMessageParams = {formattedAmount: string; comment?: string}; -type SplitAmountParams = {amount: number}; +type SplitAmountParams = {amount: string | number}; type DidSplitAmountMessageParams = {formattedAmount: string; comment: string}; From f7ed37e02855d0d3c8d3503694730b329287c974 Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 26 Feb 2024 17:15:21 +0700 Subject: [PATCH 116/202] remove redundant condition --- src/components/Attachments/AttachmentView/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index 68f41e1e51c3..e3c363c2f936 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -160,7 +160,7 @@ function AttachmentView({ const encryptedSourceUrl = isAuthTokenRequired ? addEncryptedAuthTokenToURL(source) : source; const onPDFLoadComplete = (path) => { - if (isUsedInCarousel && reportActionID && path) { + if (reportActionID && path) { CachedPDFPaths.add(reportActionID, path); } if (!loadComplete) { From abd53473a1e76f6433ee786462ec5840e4d2e57c Mon Sep 17 00:00:00 2001 From: tienifr Date: Mon, 26 Feb 2024 17:24:10 +0700 Subject: [PATCH 117/202] delete cache for transaction receipt --- src/components/Attachments/AttachmentView/index.js | 4 ++-- src/libs/actions/CachedPDFPaths/index.native.ts | 10 +++++----- src/libs/actions/CachedPDFPaths/types.ts | 4 ++-- src/libs/actions/IOU.ts | 2 ++ 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/components/Attachments/AttachmentView/index.js b/src/components/Attachments/AttachmentView/index.js index e3c363c2f936..0b402e2da4ff 100755 --- a/src/components/Attachments/AttachmentView/index.js +++ b/src/components/Attachments/AttachmentView/index.js @@ -160,8 +160,8 @@ function AttachmentView({ const encryptedSourceUrl = isAuthTokenRequired ? addEncryptedAuthTokenToURL(source) : source; const onPDFLoadComplete = (path) => { - if (reportActionID && path) { - CachedPDFPaths.add(reportActionID, path); + if (path && (transaction.transactionID || reportActionID)) { + CachedPDFPaths.add(transaction.transactionID || reportActionID, path); } if (!loadComplete) { setLoadComplete(true); diff --git a/src/libs/actions/CachedPDFPaths/index.native.ts b/src/libs/actions/CachedPDFPaths/index.native.ts index 6c4456f7a528..09203995e9a1 100644 --- a/src/libs/actions/CachedPDFPaths/index.native.ts +++ b/src/libs/actions/CachedPDFPaths/index.native.ts @@ -15,11 +15,11 @@ Onyx.connect({ }, }); -const add: Add = (reportActionID: string, path: string) => { - if (pdfPaths[reportActionID]) { +const add: Add = (id: string, path: string) => { + if (pdfPaths[id]) { return Promise.resolve(); } - return Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {[reportActionID]: path}); + return Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {[id]: path}); }; const clear: Clear = (path: string) => { @@ -36,8 +36,8 @@ const clear: Clear = (path: string) => { }); }; -const clearByKey: ClearByKey = (reportActionID: string) => { - clear(pdfPaths[reportActionID] ?? '').then(() => Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {[reportActionID]: null})); +const clearByKey: ClearByKey = (id: string) => { + clear(pdfPaths[id] ?? '').then(() => Onyx.merge(ONYXKEYS.CACHED_PDF_PATHS, {[id]: null})); }; const clearAll: ClearAll = () => { diff --git a/src/libs/actions/CachedPDFPaths/types.ts b/src/libs/actions/CachedPDFPaths/types.ts index 8c4843aaeaec..98b768c4645e 100644 --- a/src/libs/actions/CachedPDFPaths/types.ts +++ b/src/libs/actions/CachedPDFPaths/types.ts @@ -1,6 +1,6 @@ -type Add = (reportActionID: string, path: string) => Promise; +type Add = (id: string, path: string) => Promise; type Clear = (path: string) => Promise; type ClearAll = () => void; -type ClearByKey = (reportActionID: string) => void; +type ClearByKey = (id: string) => void; export type {Add, Clear, ClearAll, ClearByKey}; diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 37308c73e724..e8d1e43fb51b 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -57,6 +57,7 @@ import type {OnyxData} from '@src/types/onyx/Request'; import type {Comment, Receipt, ReceiptSource, TaxRate, TransactionChanges, WaypointCollection} from '@src/types/onyx/Transaction'; import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import * as CachedPDFPaths from './CachedPDFPaths'; import * as Policy from './Policy'; import * as Report from './Report'; @@ -3139,6 +3140,7 @@ function deleteMoneyRequest(transactionID: string, reportAction: OnyxTypes.Repor // STEP 6: Make the API request API.write(WRITE_COMMANDS.DELETE_MONEY_REQUEST, parameters, {optimisticData, successData, failureData}); + CachedPDFPaths.clearByKey(transactionID); // STEP 7: Navigate the user depending on which page they are on and which resources were deleted if (iouReport && isSingleTransactionView && shouldDeleteTransactionThread && !shouldDeleteIOUReport) { From 1e19123cf64f548463fc0ddc8d48baab4db3bc50 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 26 Feb 2024 11:30:48 +0100 Subject: [PATCH 118/202] fix: typecheck --- src/components/AvatarWithImagePicker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AvatarWithImagePicker.tsx b/src/components/AvatarWithImagePicker.tsx index fa8a6d71516f..4388ebb8f815 100644 --- a/src/components/AvatarWithImagePicker.tsx +++ b/src/components/AvatarWithImagePicker.tsx @@ -220,7 +220,7 @@ function AvatarWithImagePicker({ setError(null, {}); setIsMenuVisible(false); setImageData({ - uri: image.uri, + uri: image.uri ?? '', name: image.name, type: image.type, }); From 9112cceb6fbadcd7d1de94867dd878f32e4bc901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Mon, 26 Feb 2024 17:13:43 +0100 Subject: [PATCH 119/202] Add review changes --- .../VideoPlayerControls/VolumeButton/index.js | 26 +++++++++++-------- src/libs/NumberUtils.ts | 23 +++++++++++++++- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js b/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js index b0757eb7df68..45f47eb87c36 100644 --- a/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js +++ b/src/components/VideoPlayer/VideoPlayerControls/VolumeButton/index.js @@ -1,5 +1,5 @@ import PropTypes from 'prop-types'; -import React, {memo, useState} from 'react'; +import React, {memo, useCallback, useState} from 'react'; import {View} from 'react-native'; import {Gesture, GestureDetector} from 'react-native-gesture-handler'; import Animated, {runOnJS, useAnimatedStyle, useDerivedValue} from 'react-native-reanimated'; @@ -9,6 +9,7 @@ import IconButton from '@components/VideoPlayer/IconButton'; import {useVolumeContext} from '@components/VideoPlayerContexts/VolumeContext'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as NumberUtils from '@libs/NumberUtils'; import stylePropTypes from '@styles/stylePropTypes'; const propTypes = { @@ -38,22 +39,25 @@ function VolumeButton({style, small}) { const [volumeIcon, setVolumeIcon] = useState({icon: getVolumeIcon(volume.value)}); const [isSliderBeingUsed, setIsSliderBeingUsed] = useState(false); - const onSliderLayout = (e) => { + const onSliderLayout = useCallback((e) => { setSliderHeight(e.nativeEvent.layout.height); - }; + }, []); - const gestureEventHandler = (event) => { - const val = Math.floor((1 - event.y / sliderHeight) * 100) / 100; - volume.value = Math.min(Math.max(val, 0), 1); - }; + const changeVolumeOnPan = useCallback( + (event) => { + const val = NumberUtils.roundToTwoDecimalPlaces(1 - event.y / sliderHeight); + volume.value = NumberUtils.clamp(val, 0, 1); + }, + [sliderHeight, volume], + ); const pan = Gesture.Pan() .onBegin((event) => { runOnJS(setIsSliderBeingUsed)(true); - gestureEventHandler(event); + changeVolumeOnPan(event); }) .onChange((event) => { - gestureEventHandler(event); + changeVolumeOnPan(event); }) .onFinalize(() => { runOnJS(setIsSliderBeingUsed)(false); @@ -61,9 +65,9 @@ function VolumeButton({style, small}) { const progressBarStyle = useAnimatedStyle(() => ({height: `${volume.value * 100}%`})); - const updateIcon = (vol) => { + const updateIcon = useCallback((vol) => { setVolumeIcon({icon: getVolumeIcon(vol)}); - }; + }, []); useDerivedValue(() => { runOnJS(updateVolume)(volume.value); diff --git a/src/libs/NumberUtils.ts b/src/libs/NumberUtils.ts index d7eb87a2ed1e..b9814487bf3f 100644 --- a/src/libs/NumberUtils.ts +++ b/src/libs/NumberUtils.ts @@ -69,4 +69,25 @@ function parseFloatAnyLocale(value: string): number { return parseFloat(value ? value.replace(',', '.') : value); } -export {rand64, generateHexadecimalValue, generateRandomInt, parseFloatAnyLocale}; +/** + * Rounds a number to two decimal places. + * @param value the value to round + * @returns the rounded value + */ +function roundToTwoDecimalPlaces(value: number): number { + return Math.round(value * 100) / 100; +} + +/** + * Clamps a value between a minimum and maximum value. + * + * @param value the value to clamp + * @param min the minimum value + * @param max the maximum value + * @returns the clamped value + */ +function clamp(value: number, min: number, max: number): number { + return Math.min(Math.max(value, min), max); +} + +export {rand64, generateHexadecimalValue, generateRandomInt, parseFloatAnyLocale, roundToTwoDecimalPlaces, clamp}; From c18022ee266ef98dda7ac1382f4631533ff4d85b Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 27 Feb 2024 00:31:16 +0800 Subject: [PATCH 120/202] remove unused import --- .../DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx b/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx index 16996768eaf0..154689df4ce8 100644 --- a/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx +++ b/src/components/DeeplinkWrapper/DeeplinkRedirectLoadingIndicator.tsx @@ -12,7 +12,6 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import ONYXKEYS from '@src/ONYXKEYS'; -import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; type DeeplinkRedirectLoadingIndicatorOnyxProps = { From 0c166623f3e438f65c81cc769426152c5bf7c3d8 Mon Sep 17 00:00:00 2001 From: jeremy-croff Date: Mon, 26 Feb 2024 19:19:40 -0600 Subject: [PATCH 121/202] fix(36385): update status bar colors --- src/styles/theme/themes/dark.ts | 2 +- src/styles/theme/themes/light.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/styles/theme/themes/dark.ts b/src/styles/theme/themes/dark.ts index 3f59b08fc447..31716d75dd05 100644 --- a/src/styles/theme/themes/dark.ts +++ b/src/styles/theme/themes/dark.ts @@ -95,7 +95,7 @@ const darkTheme = { // The screen name (see SCREENS.ts) is the name of the screen as far as react-navigation is concerned, and the linkingConfig maps screen names to URLs PAGE_THEMES: { [SCREENS.HOME]: { - backgroundColor: colors.productDark200, + backgroundColor: colors.productDark100, statusBarStyle: CONST.STATUS_BAR_STYLE.LIGHT_CONTENT, }, [SCREENS.REPORT]: { diff --git a/src/styles/theme/themes/light.ts b/src/styles/theme/themes/light.ts index c0b4a5fe3182..fecd8749aebb 100644 --- a/src/styles/theme/themes/light.ts +++ b/src/styles/theme/themes/light.ts @@ -95,7 +95,7 @@ const lightTheme = { // The screen name (see SCREENS.ts) is the name of the screen as far as react-navigation is concerned, and the linkingConfig maps screen names to URLs PAGE_THEMES: { [SCREENS.HOME]: { - backgroundColor: colors.productLight200, + backgroundColor: colors.productLight100, statusBarStyle: CONST.STATUS_BAR_STYLE.DARK_CONTENT, }, [SCREENS.REPORT]: { From 131d075a12a298911e5403437a3333e370db15df Mon Sep 17 00:00:00 2001 From: dukenv0307 <129500732+dukenv0307@users.noreply.github.com> Date: Tue, 27 Feb 2024 09:41:32 +0700 Subject: [PATCH 122/202] Update src/libs/ReportUtils.ts Co-authored-by: Carlos Alvarez --- src/libs/ReportUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7c8ed1190473..98bd7d2e6f81 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -1712,7 +1712,7 @@ function getDisplayNamesWithTooltips( } /** - * Return the concatenated string of the display name of a list user + * Returns the the display names of the given user accountIDs */ function getUserDetailsTooltipText(accountIDs: number[]): string { return accountIDs.map((accountID) => getDisplayNameForParticipant(accountID)).join(', '); From 0b8d0d0fe1b1a3b6327cd57e58e5afcc1f9e90d4 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 27 Feb 2024 11:38:54 +0700 Subject: [PATCH 123/202] fix the case invite a new user to workspace --- src/components/MultipleAvatars.tsx | 12 ++++-------- .../BaseUserDetailsTooltip/index.tsx | 4 ++-- src/libs/OptionsListUtils.ts | 2 +- src/libs/ReportUtils.ts | 7 ++++--- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/components/MultipleAvatars.tsx b/src/components/MultipleAvatars.tsx index 37a27018f97f..101399230ae7 100644 --- a/src/components/MultipleAvatars.tsx +++ b/src/components/MultipleAvatars.tsx @@ -107,6 +107,8 @@ function MultipleAvatars({ let avatarContainerStyles = StyleUtils.getContainerStyles(size, isInReportAction); const {singleAvatarStyle, secondAvatarStyles} = useMemo(() => avatarSizeToStylesMap[size as AvatarSizeToStyles] ?? avatarSizeToStylesMap.default, [size, avatarSizeToStylesMap]); + const tooltipTexts = useMemo(() => (shouldShowTooltip ? icons.map((icon) => ReportUtils.getUserDetailTooltipText(Number(icon.id), icon.name)) : ['']), [shouldShowTooltip, icons]); + const avatarSize = useMemo(() => { if (isFocusMode) { return CONST.AVATAR_SIZE.MID_SUBSCRIPT; @@ -215,13 +217,7 @@ function MultipleAvatars({ {avatars.length > maxAvatarsInRow && ( Number(icon.id)), - ) - : '' - } + text={tooltipTexts.slice(avatarRows.length * maxAvatarsInRow - 1, avatarRows.length * maxAvatarsInRow + 9).join(', ')} > ) : ( - Number(icon.id))) : ''}> + getDisplayNameForParticipant(accountID)).join(', '); +function getUserDetailTooltipText(accountID: number, fallbackUserDisplayName = ''): string { + const displayNameForParticipant = getDisplayNameForParticipant(accountID); + return displayNameForParticipant || fallbackUserDisplayName; } /** @@ -5202,7 +5203,7 @@ export { buildOptimisticUnHoldReportAction, shouldDisplayThreadReplies, shouldDisableThread, - getUserDetailsTooltipText, + getUserDetailTooltipText, doesReportBelongToWorkspace, getChildReportNotificationPreference, getAllAncestorReportActions, From f17da9e0d2e4787ad153c9d6fa6e2ef9b4c9c5a9 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 27 Feb 2024 09:52:38 +0100 Subject: [PATCH 124/202] fix: typecheck --- .../MoneyRequestConfirmationList.tsx | 23 ++++++++----------- src/types/onyx/index.ts | 5 ---- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index dbc94502bdd3..21fdda1c58d2 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -29,6 +29,7 @@ import type {Route} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; +import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type {MileageRate} from '@src/types/onyx/Policy'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; @@ -63,9 +64,6 @@ type MoneyRequestConfirmationListOnyxProps = { /** Holds data related to Money Request view state, rather than the underlying Money Request data. */ iou: OnyxEntry; - /** Collection of tax rates attached to a policy */ - policyTaxRates: OnyxEntry; - /** Unit and rate used for if the money request is a distance request */ mileageRate: OnyxEntry; @@ -88,7 +86,7 @@ type MoneyRequestConfirmationListProps = MoneyRequestConfirmationListOnyxProps & onConfirm?: (selectedParticipants: Participant[]) => void; /** Callback to parent modal to send money */ - onSendMoney?: (paymentMethod: OnyxTypes.PaymentMethodType) => void; + onSendMoney?: (paymentMethod: PaymentMethodType) => void; /** Callback to inform a participant is selected */ onSelectParticipant?: (option: Participant) => void; @@ -212,7 +210,6 @@ function MoneyRequestConfirmationList({ policyTags, policyCategories, policy, - policyTaxRates, iouCurrencyCode, isEditingSplitBill, hasSmartScanFailed, @@ -240,6 +237,7 @@ function MoneyRequestConfirmationList({ const distance = transaction?.routes?.route0.distance ?? 0; const shouldCalculateDistanceAmount = isDistanceRequest && iouAmount === 0; + const taxRates = policy?.taxRates; // A flag for showing the categories field const shouldShowCategories = isPolicyExpenseChat && (iouCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories ?? {}))); @@ -275,8 +273,8 @@ function MoneyRequestConfirmationList({ ); const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction?.taxAmount, iouCurrencyCode); - const defaultTaxKey = policyTaxRates?.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${policyTaxRates.taxes[defaultTaxKey].name} (${policyTaxRates?.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) ?? ''; + const defaultTaxKey = taxRates?.defaultExternalID; + const defaultTaxName = (defaultTaxKey && `${taxRates?.taxes[defaultTaxKey].name} (${taxRates?.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const taxRateTitle = transaction?.taxRate?.text || defaultTaxName; @@ -481,7 +479,7 @@ function MoneyRequestConfirmationList({ }; const confirm = useCallback( - (paymentMethod: OnyxTypes.PaymentMethodType | undefined) => { + (paymentMethod: PaymentMethodType | undefined) => { if (selectedParticipantsMemo.length === 0) { return; } @@ -565,7 +563,7 @@ function MoneyRequestConfirmationList({ pressOnEnter isDisabled={shouldDisableButton} // eslint-disable-next-line @typescript-eslint/naming-convention - onPress={(_, value) => confirm(value as OnyxTypes.PaymentMethodType)} + onPress={(_, value) => confirm(value as PaymentMethodType)} options={splitOrRequestOptions} buttonSize={CONST.DROPDOWN_BUTTON_SIZE.LARGE} enterKeyEventListenerPriority={1} @@ -833,7 +831,7 @@ function MoneyRequestConfirmationList({ @@ -850,7 +848,7 @@ function MoneyRequestConfirmationList({ @@ -896,9 +894,6 @@ export default withCurrentUserPersonalDetails( policy: { key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, }, - policyTaxRates: { - key: ({policyID}) => `${ONYXKEYS.COLLECTION.POLICY_TAX_RATE}${policyID}`, - }, iou: { key: ONYXKEYS.IOU, }, diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index a010b5459d97..6846fc302639 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -26,7 +26,6 @@ import type MapboxAccessToken from './MapboxAccessToken'; import type Modal from './Modal'; import type Network from './Network'; import type {OnyxUpdateEvent, OnyxUpdatesFromServer} from './OnyxUpdatesFromServer'; -import type {PaymentMethodType} from './OriginalMessage'; import type PersonalBankAccount from './PersonalBankAccount'; import type {PersonalDetailsList} from './PersonalDetails'; import type PersonalDetails from './PersonalDetails'; @@ -38,7 +37,6 @@ import type {PolicyMembers} from './PolicyMember'; import type PolicyMember from './PolicyMember'; import type {PolicyReportField, PolicyReportFields} from './PolicyReportField'; import type {PolicyTag, PolicyTagList, PolicyTags} from './PolicyTag'; -import type {PolicyTaxRate, PolicyTaxRates} from './PolicyTaxRates'; import type PrivatePersonalDetails from './PrivatePersonalDetails'; import type RecentlyUsedCategories from './RecentlyUsedCategories'; import type RecentlyUsedReportFields from './RecentlyUsedReportFields'; @@ -155,8 +153,5 @@ export type { RecentlyUsedReportFields, LastPaymentMethod, InvitedEmailsToAccountIDs, - PaymentMethodType, - PolicyTaxRate, - PolicyTaxRates, Log, }; From 25359bc0aafd368f2b3a5b0b727cef9362aacd3c Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 27 Feb 2024 15:25:42 +0200 Subject: [PATCH 125/202] Profile page UI updates --- assets/images/workspace-profile-light.png | Bin 0 -> 62632 bytes assets/images/workspace-profile.png | Bin 635446 -> 70565 bytes ios/Podfile.lock | 2 +- src/pages/workspace/WorkspaceProfilePage.tsx | 15 ++++++++++++--- src/styles/index.ts | 3 +-- src/styles/utils/spacing.ts | 4 ++++ 6 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 assets/images/workspace-profile-light.png diff --git a/assets/images/workspace-profile-light.png b/assets/images/workspace-profile-light.png new file mode 100644 index 0000000000000000000000000000000000000000..7e82c98656d26beba0dd81b3f2dac772f0eb722c GIT binary patch literal 62632 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

EVKtk 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

dy`y2Z9#}ApC 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

  • q-0 z+H-^Te5}0}%D?WTDgg$+{`hUWqCagLbr31iLS~?0r=PsfY_%6kpjoG@lP@18=w|S= zJHL-^{H*iT_72ulFv|7#ABVq)?olLNwuR@w*KO3ZZMkdTKD=WIzTV!XsX@^{vcCB= z7rwXP@B29u{L=fwFv!c)f8gctK2uM1zW>_vo^w@aobrZjK(|q~gWhredUWF}Gfjpa z+-k;We1B*!`~zAx>SJBU1;I}y9RlncHIwAo_;(ps^%onH+~WfGbtR>w#Et*AHL9+T zKMt(7ySVP%sCp}+i(iS9eHR;MT2roE|1W`di5eZAbV6~3tH0U!#!#(*^i3P0P*ikN zFZ|_&)~Hb{Jhb-&6NcqX7=(Z2?1}~8aLb14s^o)j(dBY`4bJ_hZ3v<#{u^=QCsG}H zMgPYp_xQU})v|6Pm-ctF@>9!FzrXX$9_p$OVz=tu83o5WEqpw^;ZydR@#`3gL3o_dRa z+Qv_$67xFWeZA;y)cV8{o+@?C1Z^+olQ=3&#+B-aftVAVwVi9)zRW#HnKs;@ZnG2%s<}M2#WD_;NSQa{y*_= zX4?9Df*MxrH9$#HmoQBOP*+0e*ZdpbXQuw>`cLsk*2JG=H1!Yv;Fsw5^56N)As}{u z9Mf_i#d84YqOrehC9_{P>jga%AwrMsvBmULR!h z;L=F@C?*~K#6J=?M)9Y1J?1aAubcH|KTK~bHKZ%D6zK%!lK=q~YZ@aoT=(6?q zB4O$OjL-dB|10>3f8KIP0{m?J*53_v2y)_2Og{3Gf*$k8F0k$&H)_Fg6iG)w77@*w za=i&x#VCbM$5f0TB^!pbF1X7FbrqM1FFXPK)Z^JWpm{0bgn3PTNCe-D1@pHlv7h;? z;O{1DW`n?A2oJuWr%?iz6nrOF%+~ySVjTSI)_?FfzQF$}eu3}NDZ*~&W99l4ACRi9 zvVu>qw*K(n_~yU$m&?}?|2umMvk;jP|L7n5-eRo8|JbM(m~gm>NL-Bppe>A;Ld{}H z7P}8;wR_jS1+$40H}cNrhy{mEajp#Zir#y8{f7Y(>w;v5lj_a(ItL{12Q z((+HDj__tAo<5TzJaPVuCsK)Q? z8vZwW^WXYU{P4fN>#rL8)%r65Z2iq&HSy`Hl=yobe~L_1C0N;iSAX9Q)%ZUz0f!{c zx7ftNL`$GBkBvrbA$qv6ilUlOk_5poVo5cILTFqr1P>@APvc))?um8a%eh>2TlmHo zqBZ|3T{Qn{y3HSap?LTQpBtM$MD;uV&&~IUg768?| zK6I__njSl#1I{{v5XE#+D5^v6ANPKT%X8~t0|$J8U&eQTO#Etm(hK~-htK5SsQQ(^*R(P| z{4-uk;qPo?3xf|h-h+Siuka6k^Oq)m_`mBP{?2`bpsauRZ+vHm#Gg(v^%Do#Hb9o} zE*K5wY06Qu0-gdm?Gbp2E*xhTgJUxonQGA76Jv7 zJwPZp9{%*%S;6=`k$%B{>VIwh;lJ?BpS$1nKjEJmvL^nu@mpQT|CD$d8~(^jbtZ@u z1zCQy54Vtm+n-X2pyKUJ>Wo1+;WZL~Pxat;k>=8sOTpK`Crs#dZl#WHe26LdL&pV|Co_r8$%G$2V|H)$mzX!q;m)6B0Y`>i)MxzQ4O(T>Szu!h=Y;Xa5>6f)LG0mBXk=xhq`ALF z_2SwKz9zrRn$MI*`{rX1;1yr6n;%%;?wp+YKJb%iCV?s2cli3j|L~EZRE{10EGPe6 z;s4Tqy?y_QpZ-(j9-js}_`fkO<2oJ5>};Vm{%1>4L_dZ=eg=^vY_zi3+y4Yj+v1*~ zPL&#bU+~rZp^WZ=?@PW0|7*{ujN>VO?fAt1Hs1@rC;#lf)&93`FxUR;75}66-yh{O zqcR8*FYX(9ljvR+9jA8O;v+oHhfKTWejvLCj6(6%Lwtun9Xjx};A_E;-d+Cl@oVLO zsn&cw?EixQw*TAkGWt-%)*yN-Q(-i z{_BSSr}($(W+O2?yhb; literal 635446 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®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 diff --git a/ios/Podfile.lock b/ios/Podfile.lock index dc8eb94eeb3f..12663c3f238a 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2001,4 +2001,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 0ccbb4f2406893c6e9f266dc1e7470dcd72885d2 -COCOAPODS: 1.13.0 +COCOAPODS: 1.11.3 diff --git a/src/pages/workspace/WorkspaceProfilePage.tsx b/src/pages/workspace/WorkspaceProfilePage.tsx index 48dfe10a2a0e..16c4ddca4800 100644 --- a/src/pages/workspace/WorkspaceProfilePage.tsx +++ b/src/pages/workspace/WorkspaceProfilePage.tsx @@ -3,6 +3,7 @@ import type {ImageStyle, StyleProp} from 'react-native'; import {Image, ScrollView, StyleSheet, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; +import WorkspaceProfileLight from '@assets/images/workspace-profile-light.png'; import WorkspaceProfile from '@assets/images/workspace-profile.png'; import Avatar from '@components/Avatar'; import AvatarWithImagePicker from '@components/AvatarWithImagePicker'; @@ -14,6 +15,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import Section from '@components/Section'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; +import useThemePreference from '@hooks/useThemePreference'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import Navigation from '@libs/Navigation/Navigation'; @@ -42,6 +44,8 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi const styles = useThemeStyles(); const {translate} = useLocalize(); const {isSmallScreenWidth} = useWindowDimensions(); + const themePreference = useThemePreference(); + const isDarkTheme = themePreference === CONST.THEME.DARK; const outputCurrency = policy?.outputCurrency ?? ''; const currencySymbol = currencyList?.[outputCurrency]?.symbol ?? ''; @@ -55,7 +59,7 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi const policyName = policy?.name ?? ''; const policyDescription = policy?.description ?? ''; const readOnly = !PolicyUtils.isPolicyAdmin(policy); - const imageStyle: StyleProp = isSmallScreenWidth ? [styles.mhv12, styles.mhn5] : [styles.mhv8, styles.mhn8]; + const imageStyle: StyleProp = isSmallScreenWidth ? [styles.mhv12, styles.mhn5, styles.mbn5] : [styles.mhv8, styles.mhn8, styles.mbn5]; return ( Policy.updateWorkspaceAvatar(policy?.id ?? '', file as File)} onImageRemoved={() => Policy.deleteWorkspaceAvatar(policy?.id ?? '')} diff --git a/src/styles/index.ts b/src/styles/index.ts index 32392d62e5c4..f77fc008b6dc 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -4630,8 +4630,7 @@ const styles = (theme: ThemeColors) => }, workspaceTitleStyle: { - fontFamily: FontUtils.fontFamily.platform.EXP_NEUE_BOLD, - fontWeight: '500', + ...headlineFont, fontSize: variables.workspaceProfileName, }, } satisfies Styles); diff --git a/src/styles/utils/spacing.ts b/src/styles/utils/spacing.ts index 0249b3c6dfc0..b807ee2bdf24 100644 --- a/src/styles/utils/spacing.ts +++ b/src/styles/utils/spacing.ts @@ -315,6 +315,10 @@ export default { marginBottom: -4, }, + mbn5: { + marginBottom: -20, + }, + p0: { padding: 0, paddingHorizontal: 0, From ad6eff980b311b26444bcdd102fcc72e6aa9e6a4 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 27 Feb 2024 14:51:34 +0100 Subject: [PATCH 126/202] fix: linter --- src/components/MoneyRequestConfirmationList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index 21fdda1c58d2..773e98b6462e 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -274,7 +274,7 @@ function MoneyRequestConfirmationList({ const formattedTaxAmount = CurrencyUtils.convertToDisplayString(transaction?.taxAmount, iouCurrencyCode); const defaultTaxKey = taxRates?.defaultExternalID; - const defaultTaxName = (defaultTaxKey && `${taxRates?.taxes[defaultTaxKey].name} (${taxRates?.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) || ''; + const defaultTaxName = (defaultTaxKey && `${taxRates?.taxes[defaultTaxKey].name} (${taxRates?.taxes[defaultTaxKey].value}) • ${translate('common.default')}`) ?? ''; // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const taxRateTitle = transaction?.taxRate?.text || defaultTaxName; From e0ebab6fe3f2f9f47ade4763dc89b341a70c31fd Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 27 Feb 2024 15:52:45 +0200 Subject: [PATCH 127/202] rollback pod --- ios/Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 12663c3f238a..dc8eb94eeb3f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2001,4 +2001,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 0ccbb4f2406893c6e9f266dc1e7470dcd72885d2 -COCOAPODS: 1.11.3 +COCOAPODS: 1.13.0 From 63e2cf4ce94f50ebf86e7d51d627081330d845ce Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 27 Feb 2024 16:00:05 +0200 Subject: [PATCH 128/202] Remove border radius from image, fix border color around pencil icon --- src/pages/workspace/WorkspaceProfilePage.tsx | 2 +- src/styles/index.ts | 2 +- src/styles/variables.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/workspace/WorkspaceProfilePage.tsx b/src/pages/workspace/WorkspaceProfilePage.tsx index 16c4ddca4800..cb4519ad5f06 100644 --- a/src/pages/workspace/WorkspaceProfilePage.tsx +++ b/src/pages/workspace/WorkspaceProfilePage.tsx @@ -80,7 +80,7 @@ function WorkspaceProfilePage({policy, currencyList = {}, route}: WorkSpaceProfi title="" > diff --git a/src/styles/index.ts b/src/styles/index.ts index f77fc008b6dc..028bb88d6a03 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -3068,7 +3068,7 @@ const styles = (theme: ThemeColors) => smallEditIcon: { alignItems: 'center', backgroundColor: theme.buttonDefaultBG, - borderColor: theme.appBG, + borderColor: theme.buttonDefaultBG, borderRadius: 20, borderWidth: 3, color: theme.textReversed, diff --git a/src/styles/variables.ts b/src/styles/variables.ts index f7c9bd055041..c88d8f0df784 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -216,7 +216,7 @@ export default { updateAnimationH: 240, updateTextViewContainerWidth: 310, updateViewHeaderHeight: 70, - workspaceProfileName: 20, + workspaceProfileName: 22, mushroomTopHatWidth: 138, mushroomTopHatHeight: 128, From 38e88bb1a51d06b0f2aafab32fef5dfe3ecedf95 Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 27 Feb 2024 17:25:14 +0200 Subject: [PATCH 129/202] Change border --- src/styles/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index 028bb88d6a03..fa67f28b294b 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -3068,7 +3068,7 @@ const styles = (theme: ThemeColors) => smallEditIcon: { alignItems: 'center', backgroundColor: theme.buttonDefaultBG, - borderColor: theme.buttonDefaultBG, + borderColor: theme.cardBG, borderRadius: 20, borderWidth: 3, color: theme.textReversed, From 3bfd653445f65f3eafc9ad2652833d5893e85e65 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Tue, 27 Feb 2024 23:27:42 +0700 Subject: [PATCH 130/202] fix: The selection is smaller than member name row when navigating via keyboard --- src/components/SelectionList/TableListItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionList/TableListItem.tsx b/src/components/SelectionList/TableListItem.tsx index 922937c72219..76681f4823aa 100644 --- a/src/components/SelectionList/TableListItem.tsx +++ b/src/components/SelectionList/TableListItem.tsx @@ -30,7 +30,7 @@ function TableListItem({ Date: Tue, 27 Feb 2024 19:56:29 +0100 Subject: [PATCH 131/202] Fix bug with Selected bank account is not checked in bank account selection step --- src/components/AddPlaidBankAccount.js | 1 + src/components/RadioButtons.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index b6fc639546a8..1bb696d09ed1 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -301,6 +301,7 @@ function AddPlaidBankAccount({ defaultCheckedValue={defaultSelectedPlaidAccountID} onPress={handleSelectingPlaidAccount} radioButtonStyle={[styles.mb6]} + value={selectedPlaidAccountID} /> diff --git a/src/components/RadioButtons.tsx b/src/components/RadioButtons.tsx index 90c7d8580b5c..c9ebf712072e 100644 --- a/src/components/RadioButtons.tsx +++ b/src/components/RadioButtons.tsx @@ -40,10 +40,10 @@ function RadioButtons({items, onPress, defaultCheckedValue = '', radioButtonStyl const styles = useThemeStyles(); const [checkedValue, setCheckedValue] = useState(defaultCheckedValue); useEffect(() => { - if (value === checkedValue) { + if (value === checkedValue || value === undefined) { return; } - setCheckedValue(value ?? ''); + setCheckedValue(value); }, [checkedValue, value]); return ( From 87f2848b1f79f24fd56b43a88931187f1447d007 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Tue, 27 Feb 2024 20:06:29 +0100 Subject: [PATCH 132/202] Reverte passing value for RadioButtons inside AddPlaidBankAccount --- src/components/AddPlaidBankAccount.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/AddPlaidBankAccount.js b/src/components/AddPlaidBankAccount.js index 1bb696d09ed1..b6fc639546a8 100644 --- a/src/components/AddPlaidBankAccount.js +++ b/src/components/AddPlaidBankAccount.js @@ -301,7 +301,6 @@ function AddPlaidBankAccount({ defaultCheckedValue={defaultSelectedPlaidAccountID} onPress={handleSelectingPlaidAccount} radioButtonStyle={[styles.mb6]} - value={selectedPlaidAccountID} /> From b120f487f6b5e0f33301dfdf0aaf953abf6de0af Mon Sep 17 00:00:00 2001 From: Riya Shete <156463907+codinggeek2023@users.noreply.github.com> Date: Wed, 28 Feb 2024 00:56:55 +0530 Subject: [PATCH 133/202] Update en.ts --- src/languages/en.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index b6a24f33035c..a645c977a473 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2206,7 +2206,6 @@ export default { address: 'Address', waypointDescription: { start: 'Start', - finish: 'Finish', stop: 'Stop', }, mapPending: { From 56ab70862ec2a6d2c3fcd11e188d7ef6266dd421 Mon Sep 17 00:00:00 2001 From: Riya Shete <156463907+codinggeek2023@users.noreply.github.com> Date: Wed, 28 Feb 2024 00:57:58 +0530 Subject: [PATCH 134/202] Update IOURequestStepWaypoint.tsx --- src/pages/iou/request/step/IOURequestStepWaypoint.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx index eee6da9e87ef..c4e27d52e09f 100644 --- a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx +++ b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx @@ -82,8 +82,6 @@ function IOURequestStepWaypoint({ switch (parsedWaypointIndex) { case 0: return 'distance.waypointDescription.start'; - case waypointCount - 1: - return 'distance.waypointDescription.finish'; default: return 'distance.waypointDescription.stop'; } From f5963cae18f1277ed95884b4db1d673f9068360c Mon Sep 17 00:00:00 2001 From: Riya Shete <156463907+codinggeek2023@users.noreply.github.com> Date: Wed, 28 Feb 2024 01:01:36 +0530 Subject: [PATCH 135/202] Update es.ts --- src/languages/es.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/languages/es.ts b/src/languages/es.ts index c9ff087d0de7..da30eb01e84d 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2725,7 +2725,6 @@ export default { address: 'Dirección', waypointDescription: { start: 'Comienzo', - finish: 'Final', stop: 'Parada', }, mapPending: { From f92b845aff8c030b2a3fd2c76c69d9e06bf101c8 Mon Sep 17 00:00:00 2001 From: Riya Shete <156463907+codinggeek2023@users.noreply.github.com> Date: Wed, 28 Feb 2024 01:06:27 +0530 Subject: [PATCH 136/202] fix lint --- src/pages/iou/request/step/IOURequestStepWaypoint.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx index c4e27d52e09f..5a68c85546e6 100644 --- a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx +++ b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx @@ -85,7 +85,7 @@ function IOURequestStepWaypoint({ default: return 'distance.waypointDescription.stop'; } - }, [parsedWaypointIndex, waypointCount]); + }, [parsedWaypointIndex]); const locationBias = useLocationBias(allWaypoints, userLocation); const waypointAddress = currentWaypoint.address ?? ''; From d482a25fc9e9f37990c27c1d5906227eb6204cf2 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 27 Feb 2024 23:20:31 +0300 Subject: [PATCH 137/202] enable back navigation on leaving chat threads --- src/libs/actions/Report.ts | 48 ++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index f29f8a4fbaab..8712541ee1e2 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -2254,6 +2254,7 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal if (!report) { return; } + const isChatThread = ReportUtils.isChatThread(report); // Pusher's leavingStatus should be sent earlier. // Place the broadcast before calling the LeaveRoom API to prevent a race condition @@ -2262,20 +2263,22 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal // If a workspace member is leaving a workspace room, they don't actually lose the room from Onyx. // Instead, their notification preference just gets set to "hidden". + // Same applies for chat threads too const optimisticData: OnyxUpdate[] = [ { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, - value: isWorkspaceMemberLeavingWorkspaceRoom - ? { - notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, - } - : { - reportID: null, - stateNum: CONST.REPORT.STATE_NUM.APPROVED, - statusNum: CONST.REPORT.STATUS_NUM.CLOSED, - notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, - }, + value: + isWorkspaceMemberLeavingWorkspaceRoom || isChatThread + ? { + notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, + } + : { + reportID: null, + stateNum: CONST.REPORT.STATE_NUM.APPROVED, + statusNum: CONST.REPORT.STATUS_NUM.CLOSED, + notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, + }, }, ]; @@ -2283,12 +2286,13 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, - value: isWorkspaceMemberLeavingWorkspaceRoom - ? {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN} - : Object.keys(report).reduce>((acc, key) => { - acc[key] = null; - return acc; - }, {}), + value: + isWorkspaceMemberLeavingWorkspaceRoom || isChatThread + ? {notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN} + : Object.keys(report).reduce>((acc, key) => { + acc[key] = null; + return acc; + }, {}), }, ]; @@ -2344,15 +2348,19 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal const lastAccessedReportID = filteredReportsByLastRead.at(-1)?.reportID; if (lastAccessedReportID) { - // We should call Navigation.goBack to pop the current route first before navigating to Concierge. - Navigation.goBack(); + // If it is not a chat thread we should call Navigation.goBack to pop the current route first before navigating to last accessed report. + if (!isChatThread) { + Navigation.goBack(); + } Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(lastAccessedReportID)); } else { const participantAccountIDs = PersonalDetailsUtils.getAccountIDsByLogins([CONST.EMAIL.CONCIERGE]); const chat = ReportUtils.getChatByParticipants(participantAccountIDs); if (chat?.reportID) { - // We should call Navigation.goBack to pop the current route first before navigating to Concierge. - Navigation.goBack(); + // If it is not a chat thread we should call Navigation.goBack to pop the current route first before navigating to Concierge. + if (!isChatThread) { + Navigation.goBack(); + } Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(chat.reportID)); } } From ffe921337aad6287e627ed7a397b41eaadea567c Mon Sep 17 00:00:00 2001 From: Nicolay Arefyeu Date: Tue, 27 Feb 2024 22:29:40 +0200 Subject: [PATCH 138/202] Use direct fontSizeXLarge --- src/styles/index.ts | 2 +- src/styles/variables.ts | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index fa67f28b294b..304cc9e7f6bd 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -4631,7 +4631,7 @@ const styles = (theme: ThemeColors) => workspaceTitleStyle: { ...headlineFont, - fontSize: variables.workspaceProfileName, + fontSize: variables.fontSizeXLarge, }, } satisfies Styles); diff --git a/src/styles/variables.ts b/src/styles/variables.ts index c88d8f0df784..3d5115a31f54 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -216,7 +216,6 @@ export default { updateAnimationH: 240, updateTextViewContainerWidth: 310, updateViewHeaderHeight: 70, - workspaceProfileName: 22, mushroomTopHatWidth: 138, mushroomTopHatHeight: 128, From 8cf4670d37eeda785db17f8509150fc5800e61b5 Mon Sep 17 00:00:00 2001 From: Yauheni Date: Tue, 27 Feb 2024 22:16:57 +0100 Subject: [PATCH 139/202] Update code --- src/components/RadioButtons.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/RadioButtons.tsx b/src/components/RadioButtons.tsx index c9ebf712072e..2030ce8f0bfd 100644 --- a/src/components/RadioButtons.tsx +++ b/src/components/RadioButtons.tsx @@ -39,11 +39,12 @@ type RadioButtonsProps = { function RadioButtons({items, onPress, defaultCheckedValue = '', radioButtonStyle, errorText, onInputChange = () => {}, value}: RadioButtonsProps, ref: ForwardedRef) { const styles = useThemeStyles(); const [checkedValue, setCheckedValue] = useState(defaultCheckedValue); + useEffect(() => { if (value === checkedValue || value === undefined) { return; } - setCheckedValue(value); + setCheckedValue(value ?? ''); }, [checkedValue, value]); return ( From 630a17e2a97815b48e80bf7c96c9411438e6f267 Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi Date: Wed, 28 Feb 2024 06:51:24 +0530 Subject: [PATCH 140/202] Add prop isRowMultilineSupported to BaseSelectionList --- src/components/SelectionList/BaseSelectionList.tsx | 1 + src/components/SelectionList/types.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 1c69d00b3910..9ddb37695334 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -63,6 +63,7 @@ function BaseSelectionList( onLayout, customListHeader, listHeaderWrapperStyle, + isRowMultilineSupported = false, }: BaseSelectionListProps, inputRef: ForwardedRef, ) { diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 59f6b14cfb1f..370439b48835 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -258,6 +258,9 @@ type BaseSelectionListProps = Partial & { /** Styles for the list header wrapper */ listHeaderWrapperStyle?: StyleProp; + + /** Whether to wrap large text up to 2 lines */ + isRowMultilineSupported?: boolean; }; type ItemLayout = { From b7ab5736aee5e7f22f1abb5b7fa939d830deec66 Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi Date: Wed, 28 Feb 2024 06:53:24 +0530 Subject: [PATCH 141/202] Add isMultilineSupported prop to ListItem --- src/components/SelectionList/RadioListItem.tsx | 1 + src/components/SelectionList/types.ts | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/components/SelectionList/RadioListItem.tsx b/src/components/SelectionList/RadioListItem.tsx index b3340a0faf7a..b39f014a193b 100644 --- a/src/components/SelectionList/RadioListItem.tsx +++ b/src/components/SelectionList/RadioListItem.tsx @@ -16,6 +16,7 @@ function RadioListItem({ onDismissError, shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, + isMultilineSupported = false, }: RadioListItemProps) { const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 370439b48835..550276166e9e 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -37,6 +37,9 @@ type CommonListItemProps = { /** Styles for the checkbox wrapper view if select multiple option is on */ selectMultipleStyle?: StyleProp; + + /** Whether to wrap large text up to 2 lines */ + isMultilineSupported?: boolean; }; type ListItem = { @@ -83,6 +86,9 @@ type ListItem = { /** Whether this option should show subscript */ shouldShowSubscript?: boolean; + + /** Whether to wrap large text up to 2 lines */ + isMultilineSupported?: boolean; }; type ListItemProps = CommonListItemProps & { From 52a2fedc3f332edc3535885984540b4804132ecc Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi Date: Wed, 28 Feb 2024 06:55:15 +0530 Subject: [PATCH 142/202] Add numberOfLines prop type to TextWithTooltip --- src/components/TextWithTooltip/index.native.tsx | 4 ++-- src/components/TextWithTooltip/index.tsx | 4 ++-- src/components/TextWithTooltip/types.ts | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/TextWithTooltip/index.native.tsx b/src/components/TextWithTooltip/index.native.tsx index f8013ae00e4c..345f1fb770a5 100644 --- a/src/components/TextWithTooltip/index.native.tsx +++ b/src/components/TextWithTooltip/index.native.tsx @@ -2,11 +2,11 @@ import React from 'react'; import Text from '@components/Text'; import type TextWithTooltipProps from './types'; -function TextWithTooltip({text, textStyles}: TextWithTooltipProps) { +function TextWithTooltip({text, textStyles, numberOfLines}: TextWithTooltipProps) { return ( {text} diff --git a/src/components/TextWithTooltip/index.tsx b/src/components/TextWithTooltip/index.tsx index fd202db8de64..0b03c9fcc592 100644 --- a/src/components/TextWithTooltip/index.tsx +++ b/src/components/TextWithTooltip/index.tsx @@ -7,7 +7,7 @@ type LayoutChangeEvent = { target: HTMLElement; }; -function TextWithTooltip({text, shouldShowTooltip, textStyles}: TextWithTooltipProps) { +function TextWithTooltip({text, shouldShowTooltip, textStyles, numberOfLines}: TextWithTooltipProps) { const [showTooltip, setShowTooltip] = useState(false); return ( @@ -17,7 +17,7 @@ function TextWithTooltip({text, shouldShowTooltip, textStyles}: TextWithTooltipP > { const target = (e.nativeEvent as unknown as LayoutChangeEvent).target; if (!shouldShowTooltip) { diff --git a/src/components/TextWithTooltip/types.ts b/src/components/TextWithTooltip/types.ts index 80517b0b2acf..426336851ada 100644 --- a/src/components/TextWithTooltip/types.ts +++ b/src/components/TextWithTooltip/types.ts @@ -4,6 +4,9 @@ type TextWithTooltipProps = { text: string; shouldShowTooltip: boolean; textStyles?: StyleProp; + + /** Custom number of lines for Text */ + numberOfLines?: number; }; export default TextWithTooltipProps; From f585826cfe433c01e812c5fd76058cf7c6055020 Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi Date: Wed, 28 Feb 2024 06:55:58 +0530 Subject: [PATCH 143/202] Pass isRowMultilineSupported in CategoryPicker --- src/components/CategoryPicker/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/CategoryPicker/index.js b/src/components/CategoryPicker/index.js index 2374fc9e5d0c..89312a7ca614 100644 --- a/src/components/CategoryPicker/index.js +++ b/src/components/CategoryPicker/index.js @@ -70,6 +70,7 @@ function CategoryPicker({selectedCategory, policyCategories, policyRecentlyUsedC onSelectRow={onSubmit} ListItem={RadioListItem} initiallyFocusedOptionKey={selectedOptionKey} + isRowMultilineSupported /> ); } From 3a87b37183cd5e6854891b254a52e764c9c61019 Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi Date: Wed, 28 Feb 2024 06:56:17 +0530 Subject: [PATCH 144/202] Pass isMultilineSupported to ListItem --- src/components/SelectionList/BaseSelectionList.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 9ddb37695334..9db0b4102b99 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -294,6 +294,7 @@ function BaseSelectionList( shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow} rightHandSideComponent={rightHandSideComponent} keyForList={item.keyForList} + isMultilineSupported={isRowMultilineSupported} /> ); }; From b72a521c1290767455744e0e6da030f576e2da1c Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi Date: Wed, 28 Feb 2024 06:57:00 +0530 Subject: [PATCH 145/202] Pass custom numberOfLines to TextWithTooltip --- src/components/SelectionList/RadioListItem.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/SelectionList/RadioListItem.tsx b/src/components/SelectionList/RadioListItem.tsx index b39f014a193b..019cae84d156 100644 --- a/src/components/SelectionList/RadioListItem.tsx +++ b/src/components/SelectionList/RadioListItem.tsx @@ -45,9 +45,10 @@ function RadioListItem({ styles.optionDisplayName, isFocused ? styles.sidebarLinkActiveText : styles.sidebarLinkText, styles.sidebarLinkTextBold, - styles.pre, + isMultilineSupported ? styles.preWrap : styles.pre, item.alternateText ? styles.mb1 : null, ]} + numberOfLines={isMultilineSupported ? 2 : 1} /> {!!item.alternateText && ( From c140118d793b8400ca9f12f29c1cf0f92d603b99 Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi Date: Wed, 28 Feb 2024 06:57:37 +0530 Subject: [PATCH 146/202] Add the missing prop comments in TextWithTooltip Props --- src/components/TextWithTooltip/types.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/TextWithTooltip/types.ts b/src/components/TextWithTooltip/types.ts index 426336851ada..9199cc34ad5f 100644 --- a/src/components/TextWithTooltip/types.ts +++ b/src/components/TextWithTooltip/types.ts @@ -1,8 +1,13 @@ import type {StyleProp, TextStyle} from 'react-native'; type TextWithTooltipProps = { + /** The text to display */ text: string; + + /** Whether to show the toolip text */ shouldShowTooltip: boolean; + + /** Additional text styles */ textStyles?: StyleProp; /** Custom number of lines for Text */ From 261ae17cdf57596d40fdae0da86e3541029861c9 Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi Date: Wed, 28 Feb 2024 06:59:47 +0530 Subject: [PATCH 147/202] Run prettier --- src/components/TextWithTooltip/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TextWithTooltip/types.ts b/src/components/TextWithTooltip/types.ts index 9199cc34ad5f..262a1f7dba03 100644 --- a/src/components/TextWithTooltip/types.ts +++ b/src/components/TextWithTooltip/types.ts @@ -6,7 +6,7 @@ type TextWithTooltipProps = { /** Whether to show the toolip text */ shouldShowTooltip: boolean; - + /** Additional text styles */ textStyles?: StyleProp; From dd6703aacc2647341c23cf76531bb7ab471eb979 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Wed, 28 Feb 2024 11:42:34 +0700 Subject: [PATCH 148/202] Get correct default category for split scan request --- src/pages/iou/request/step/IOURequestStepCategory.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepCategory.js b/src/pages/iou/request/step/IOURequestStepCategory.js index 3e0feec02854..1945edbc24c4 100644 --- a/src/pages/iou/request/step/IOURequestStepCategory.js +++ b/src/pages/iou/request/step/IOURequestStepCategory.js @@ -1,4 +1,5 @@ import lodashGet from 'lodash/get'; +import lodashIsEmpty from 'lodash/isEmpty'; import PropTypes from 'prop-types'; import React from 'react'; import {withOnyx} from 'react-native-onyx'; @@ -72,7 +73,7 @@ function IOURequestStepCategory({ const {translate} = useLocalize(); const isEditing = action === CONST.IOU.ACTION.EDIT; const isEditingSplitBill = isEditing && iouType === CONST.IOU.TYPE.SPLIT; - const {category: transactionCategory} = ReportUtils.getTransactionDetails(isEditingSplitBill ? splitDraftTransaction : transaction); + const {category: transactionCategory} = ReportUtils.getTransactionDetails(isEditingSplitBill && !lodashIsEmpty(splitDraftTransaction) ? splitDraftTransaction : transaction); const isPolicyExpenseChat = ReportUtils.isGroupPolicy(report); // eslint-disable-next-line rulesdir/no-negated-variables From f3cdd232b6d1f1c32537030a99040d68f5df8c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ska=C5=82ka?= Date: Wed, 28 Feb 2024 09:05:13 +0100 Subject: [PATCH 149/202] Fix volume button on iOS/Safari --- src/components/VideoPlayerContexts/VolumeContext.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/VideoPlayerContexts/VolumeContext.js b/src/components/VideoPlayerContexts/VolumeContext.js index 2df463654075..a0b972d37a0d 100644 --- a/src/components/VideoPlayerContexts/VolumeContext.js +++ b/src/components/VideoPlayerContexts/VolumeContext.js @@ -14,7 +14,7 @@ function VolumeContextProvider({children}) { if (!currentVideoPlayerRef.current) { return; } - currentVideoPlayerRef.current.setStatusAsync({volume: newVolume}); + currentVideoPlayerRef.current.setStatusAsync({volume: newVolume, isMuted: newVolume === 0}); volume.value = newVolume; }, [currentVideoPlayerRef, volume], From 41be9d61016132b028ddddffce69397e28f20588 Mon Sep 17 00:00:00 2001 From: Abdullah Alsigar Date: Wed, 28 Feb 2024 11:08:04 +0300 Subject: [PATCH 150/202] revert using singleExecution on keyboard shortcut --- .../Pressable/GenericPressable/BaseGenericPressable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx b/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx index 8a9157e5817e..5ea32f3306fd 100644 --- a/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx +++ b/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx @@ -125,7 +125,7 @@ function GenericPressable( return () => {}; } const {shortcutKey, descriptionKey, modifiers} = keyboardShortcut; - return KeyboardShortcut.subscribe(shortcutKey, singleExecution(onKeyboardShortcutPressHandler), descriptionKey, modifiers, true, false, 0, false); + return KeyboardShortcut.subscribe(shortcutKey, onKeyboardShortcutPressHandler, descriptionKey, modifiers, true, false, 0, false); }, [singleExecution, keyboardShortcut, onKeyboardShortcutPressHandler]); return ( From acb167fb1f8717863720d533f27b4d603cc7d16c Mon Sep 17 00:00:00 2001 From: Abdullah Alsigar Date: Wed, 28 Feb 2024 11:10:34 +0300 Subject: [PATCH 151/202] Revert "lock capturePhoto" This reverts commit aa0a8af1959fb30b92deff8e20d483e792eb49ba. --- .../step/IOURequestStepScan/index.native.js | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.js b/src/pages/iou/request/step/IOURequestStepScan/index.native.js index 84a9e419760b..25d242db5342 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.js +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.js @@ -30,7 +30,6 @@ import reportPropTypes from '@pages/reportPropTypes'; import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; -import {useNavigation} from "@react-navigation/native"; import * as CameraPermission from './CameraPermission'; import NavigationAwareCamera from './NavigationAwareCamera'; @@ -62,24 +61,12 @@ function IOURequestStepScan({ const styles = useThemeStyles(); const devices = useCameraDevices('wide-angle-camera'); const device = devices.back; - const navigation = useNavigation(); const camera = useRef(null); const [flash, setFlash] = useState(false); const [cameraPermissionStatus, setCameraPermissionStatus] = useState(undefined); const askedForPermission = useRef(false); - const [didCapturePhoto, setDidCapturePhoto] = useState(false); - useEffect(() => { - const unsubscribe = navigation.addListener('focus', () => { - setDidCapturePhoto(false); - }); - - return () => { - unsubscribe(); - } - }, [navigation]); - const {translate} = useLocalize(); const askForPermissions = (showPermissionsAlert = true) => { @@ -249,10 +236,6 @@ function IOURequestStepScan({ return; } - if (didCapturePhoto) { - return; - } - return camera.current .takePhoto({ qualityPrioritization: 'speed', @@ -270,15 +253,13 @@ function IOURequestStepScan({ return; } - setDidCapturePhoto(true); navigateToConfirmationStep(); }) .catch((error) => { - setDidCapturePhoto(false); showCameraAlert(); Log.warn('Error taking photo', error); }); - }, [flash, action, translate, transactionID, updateScanAndNavigate, navigateToConfirmationStep, cameraPermissionStatus, didCapturePhoto]); + }, [flash, action, translate, transactionID, updateScanAndNavigate, navigateToConfirmationStep, cameraPermissionStatus]); // Wait for camera permission status to render if (cameraPermissionStatus == null) { From 64368d5784c3ad869251eb6845070fbfb5ef8f23 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 28 Feb 2024 10:49:28 +0100 Subject: [PATCH 152/202] fix: typecheck --- src/libs/EmojiUtils.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index 353ced9e1e45..cab0f48d75fd 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -10,7 +10,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {FrequentlyUsedEmoji, Locale} from '@src/types/onyx'; import type {ReportActionReaction, UsersReactions} from '@src/types/onyx/ReportActionReactions'; import type IconAsset from '@src/types/utils/IconAsset'; -import {SupportedLanguage} from './EmojiTrie'; type HeaderIndice = {code: string; index: number; icon: IconAsset}; type EmojiSpacer = {code: string; spacer: boolean}; @@ -384,7 +383,7 @@ function replaceAndExtractEmojis(text: string, preferredSkinTone: number = CONST * Suggest emojis when typing emojis prefix after colon * @param [limit] - matching emojis limit */ -function suggestEmojis(text: string, lang: SupportedLanguage, limit: number = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS): Emoji[] | undefined { +function suggestEmojis(text: string, lang: Locale, limit: number = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS): Emoji[] | undefined { // emojisTrie is importing the emoji JSON file on the app starting and we want to avoid it const emojisTrie = require('./EmojiTrie').default; From b1bf314b4c1560b14cc2f25af0e51ecf60e448fd Mon Sep 17 00:00:00 2001 From: Tomasz Misiukiewicz Date: Wed, 28 Feb 2024 11:21:14 +0100 Subject: [PATCH 153/202] preserve credentials when clearing onyx --- src/pages/settings/AboutPage/TroubleshootPage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/settings/AboutPage/TroubleshootPage.tsx b/src/pages/settings/AboutPage/TroubleshootPage.tsx index ade6932c4b2c..9bc756df03cb 100644 --- a/src/pages/settings/AboutPage/TroubleshootPage.tsx +++ b/src/pages/settings/AboutPage/TroubleshootPage.tsx @@ -40,6 +40,7 @@ const keysToPreserve: OnyxKey[] = [ ONYXKEYS.NVP_TRY_FOCUS_MODE, ONYXKEYS.PREFERRED_THEME, ONYXKEYS.NVP_PREFERRED_LOCALE, + ONYXKEYS.CREDENTIALS, ]; type BaseMenuItem = { From 66a4c0a299db42b596e6b90a1ce269161175bcb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arkadiusz=20Chrab=C4=85szczewski?= Date: Wed, 28 Feb 2024 11:34:10 +0100 Subject: [PATCH 154/202] feat: add optional checkbox press handled --- src/components/SelectionList/BaseListItem.tsx | 17 +++++++++++++++-- .../SelectionList/BaseSelectionList.tsx | 2 ++ src/components/SelectionList/TableListItem.tsx | 2 ++ src/components/SelectionList/types.ts | 6 ++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/components/SelectionList/BaseListItem.tsx b/src/components/SelectionList/BaseListItem.tsx index 2f853dc55839..824ad757cb38 100644 --- a/src/components/SelectionList/BaseListItem.tsx +++ b/src/components/SelectionList/BaseListItem.tsx @@ -19,6 +19,7 @@ function BaseListItem({ shouldPreventDefaultFocusOnSelectRow = false, canSelectMultiple = false, onSelectRow, + onCheckboxPress, onDismissError = () => {}, rightHandSideComponent, keyForList, @@ -43,6 +44,15 @@ function BaseListItem({ return rightHandSideComponent; }; + const handleCheckboxPress = () => { + if (onCheckboxPress) { + onCheckboxPress(item); + } else { + // If base list show checkbox, but there is no onCheckboxPress, then onSelectRow should be called as primary action for the entire row + onSelectRow(item); + } + }; + return ( onDismissError(item)} @@ -66,8 +76,11 @@ function BaseListItem({ <> {canSelectMultiple && ( - @@ -80,7 +93,7 @@ function BaseListItem({ /> )} - + )} {typeof children === 'function' ? children(hovered) : children} diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index 1c69d00b3910..1e75aaeac93e 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -30,6 +30,7 @@ function BaseSelectionList( ListItem, canSelectMultiple = false, onSelectRow, + onCheckboxPress, onSelectAll, onDismissError, textInputLabel = '', @@ -289,6 +290,7 @@ function BaseSelectionList( showTooltip={showTooltip} canSelectMultiple={canSelectMultiple} onSelectRow={() => selectRow(item)} + onCheckboxPress={() => onCheckboxPress?.(item)} onDismissError={() => onDismissError?.(item)} shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow} rightHandSideComponent={rightHandSideComponent} diff --git a/src/components/SelectionList/TableListItem.tsx b/src/components/SelectionList/TableListItem.tsx index 922937c72219..2acad7f40f20 100644 --- a/src/components/SelectionList/TableListItem.tsx +++ b/src/components/SelectionList/TableListItem.tsx @@ -15,6 +15,7 @@ function TableListItem({ isDisabled, canSelectMultiple, onSelectRow, + onCheckboxPress, onDismissError, shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, @@ -37,6 +38,7 @@ function TableListItem({ showTooltip={showTooltip} canSelectMultiple={canSelectMultiple} onSelectRow={onSelectRow} + onCheckboxPress={onCheckboxPress} onDismissError={onDismissError} shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow} rightHandSideComponent={rightHandSideComponent} diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 59f6b14cfb1f..b6cc0c786adb 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -23,6 +23,9 @@ type CommonListItemProps = { /** Callback to fire when the item is pressed */ onSelectRow: (item: TItem) => void; + /** Callback to fire when a checkbox is pressed */ + onCheckboxPress?: (item: TItem) => void; + /** Callback to fire when an error is dismissed */ onDismissError?: (item: TItem) => void; @@ -157,6 +160,9 @@ type BaseSelectionListProps = Partial & { /** Callback to fire when a row is pressed */ onSelectRow: (item: TItem) => void; + /** Optional callback function triggered upon pressing a checkbox. If undefined and the list displays checkboxes, checkbox interactions are managed by onSelectRow, allowing for pressing anywhere on the list. */ + onCheckboxPress?: (item: TItem) => void; + /** Callback to fire when "Select All" checkbox is pressed. Only use along with `canSelectMultiple` */ onSelectAll?: () => void; From ad6aa3811d4cf223a365a492d202bc64050014b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arkadiusz=20Chrab=C4=85szczewski?= Date: Wed, 28 Feb 2024 11:34:50 +0100 Subject: [PATCH 155/202] chore: temporary navigate to categories settings when pressing row --- src/pages/workspace/categories/WorkspaceCategoriesPage.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx index 7cd9972a6f57..721341073d72 100644 --- a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx +++ b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx @@ -129,7 +129,8 @@ function WorkspaceCategoriesPage({policyCategories, route}: WorkspaceCategoriesP Date: Wed, 28 Feb 2024 11:44:26 +0100 Subject: [PATCH 156/202] fix: pass undefined if onCheckboxPress is undefined --- src/components/SelectionList/BaseListItem.tsx | 2 -- src/components/SelectionList/BaseSelectionList.tsx | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/SelectionList/BaseListItem.tsx b/src/components/SelectionList/BaseListItem.tsx index 824ad757cb38..98b1999625ee 100644 --- a/src/components/SelectionList/BaseListItem.tsx +++ b/src/components/SelectionList/BaseListItem.tsx @@ -48,7 +48,6 @@ function BaseListItem({ if (onCheckboxPress) { onCheckboxPress(item); } else { - // If base list show checkbox, but there is no onCheckboxPress, then onSelectRow should be called as primary action for the entire row onSelectRow(item); } }; @@ -77,7 +76,6 @@ function BaseListItem({ {canSelectMultiple && ( ( showTooltip={showTooltip} canSelectMultiple={canSelectMultiple} onSelectRow={() => selectRow(item)} - onCheckboxPress={() => onCheckboxPress?.(item)} + onCheckboxPress={onCheckboxPress ? () => onCheckboxPress?.(item) : undefined} onDismissError={() => onDismissError?.(item)} shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow} rightHandSideComponent={rightHandSideComponent} From 645a1a402a9478af43a999d5404c2b4a39f9e3da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arkadiusz=20Chrab=C4=85szczewski?= Date: Wed, 28 Feb 2024 11:51:35 +0100 Subject: [PATCH 157/202] feat: add support for radio and user list item --- src/components/SelectionList/RadioListItem.tsx | 2 ++ src/components/SelectionList/UserListItem.tsx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/components/SelectionList/RadioListItem.tsx b/src/components/SelectionList/RadioListItem.tsx index b3340a0faf7a..d56e0330de32 100644 --- a/src/components/SelectionList/RadioListItem.tsx +++ b/src/components/SelectionList/RadioListItem.tsx @@ -13,6 +13,7 @@ function RadioListItem({ isDisabled, canSelectMultiple, onSelectRow, + onCheckboxPress, onDismissError, shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, @@ -30,6 +31,7 @@ function RadioListItem({ showTooltip={showTooltip} canSelectMultiple={canSelectMultiple} onSelectRow={onSelectRow} + onCheckboxPress={onCheckboxPress} onDismissError={onDismissError} shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow} rightHandSideComponent={rightHandSideComponent} diff --git a/src/components/SelectionList/UserListItem.tsx b/src/components/SelectionList/UserListItem.tsx index 06d0f6452117..fc39bb4b1259 100644 --- a/src/components/SelectionList/UserListItem.tsx +++ b/src/components/SelectionList/UserListItem.tsx @@ -18,6 +18,7 @@ function UserListItem({ isDisabled, canSelectMultiple, onSelectRow, + onCheckboxPress, onDismissError, shouldPreventDefaultFocusOnSelectRow, rightHandSideComponent, @@ -41,6 +42,7 @@ function UserListItem({ showTooltip={showTooltip} canSelectMultiple={canSelectMultiple} onSelectRow={onSelectRow} + onCheckboxPress={onCheckboxPress} onDismissError={onDismissError} shouldPreventDefaultFocusOnSelectRow={shouldPreventDefaultFocusOnSelectRow} rightHandSideComponent={rightHandSideComponent} From 43f769346cf7c1a6db91ed01752e564fa901eff6 Mon Sep 17 00:00:00 2001 From: Abdullah Alsigar Date: Wed, 28 Feb 2024 13:54:04 +0300 Subject: [PATCH 158/202] cleanup --- .../Pressable/GenericPressable/BaseGenericPressable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx b/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx index 5ea32f3306fd..647c0fcb975a 100644 --- a/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx +++ b/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx @@ -126,7 +126,7 @@ function GenericPressable( } const {shortcutKey, descriptionKey, modifiers} = keyboardShortcut; return KeyboardShortcut.subscribe(shortcutKey, onKeyboardShortcutPressHandler, descriptionKey, modifiers, true, false, 0, false); - }, [singleExecution, keyboardShortcut, onKeyboardShortcutPressHandler]); + }, [keyboardShortcut, onKeyboardShortcutPressHandler]); return ( Date: Wed, 28 Feb 2024 19:20:15 +0530 Subject: [PATCH 159/202] Add default prop value to numberOfLines Co-authored-by: Fedi Rajhi --- src/components/TextWithTooltip/index.native.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TextWithTooltip/index.native.tsx b/src/components/TextWithTooltip/index.native.tsx index 345f1fb770a5..f8f81cc7181c 100644 --- a/src/components/TextWithTooltip/index.native.tsx +++ b/src/components/TextWithTooltip/index.native.tsx @@ -2,7 +2,7 @@ import React from 'react'; import Text from '@components/Text'; import type TextWithTooltipProps from './types'; -function TextWithTooltip({text, textStyles, numberOfLines}: TextWithTooltipProps) { +function TextWithTooltip({text, textStyles, numberOfLines = 1}: TextWithTooltipProps) { return ( Date: Wed, 28 Feb 2024 19:22:08 +0530 Subject: [PATCH 160/202] Add default prop value to numberOfLines (web) Co-authored-by: Fedi Rajhi --- src/components/TextWithTooltip/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TextWithTooltip/index.tsx b/src/components/TextWithTooltip/index.tsx index 0b03c9fcc592..755959d52cfc 100644 --- a/src/components/TextWithTooltip/index.tsx +++ b/src/components/TextWithTooltip/index.tsx @@ -7,7 +7,7 @@ type LayoutChangeEvent = { target: HTMLElement; }; -function TextWithTooltip({text, shouldShowTooltip, textStyles, numberOfLines}: TextWithTooltipProps) { +function TextWithTooltip({text, shouldShowTooltip, textStyles, numberOfLines = 1}: TextWithTooltipProps) { const [showTooltip, setShowTooltip] = useState(false); return ( From 6d50cb5a8b12c514e82e267189e92641e7809f41 Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi <64629613+neonbhai@users.noreply.github.com> Date: Wed, 28 Feb 2024 19:23:41 +0530 Subject: [PATCH 161/202] Remove null coalescing operator in favor of default value Co-authored-by: Fedi Rajhi --- src/components/TextWithTooltip/index.native.tsx | 2 +- src/components/TextWithTooltip/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/TextWithTooltip/index.native.tsx b/src/components/TextWithTooltip/index.native.tsx index f8f81cc7181c..3780df6362be 100644 --- a/src/components/TextWithTooltip/index.native.tsx +++ b/src/components/TextWithTooltip/index.native.tsx @@ -6,7 +6,7 @@ function TextWithTooltip({text, textStyles, numberOfLines = 1}: TextWithTooltipP return ( {text} diff --git a/src/components/TextWithTooltip/index.tsx b/src/components/TextWithTooltip/index.tsx index 755959d52cfc..96721488c6db 100644 --- a/src/components/TextWithTooltip/index.tsx +++ b/src/components/TextWithTooltip/index.tsx @@ -17,7 +17,7 @@ function TextWithTooltip({text, shouldShowTooltip, textStyles, numberOfLines = 1 > { const target = (e.nativeEvent as unknown as LayoutChangeEvent).target; if (!shouldShowTooltip) { From 2e1472b152c8f9ea7984e17ad7f3fce4dc6f4f9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arkadiusz=20Chrab=C4=85szczewski?= Date: Wed, 28 Feb 2024 15:49:16 +0100 Subject: [PATCH 162/202] refactor: select all checkbox only in checkbox area --- .../SelectionList/BaseSelectionList.tsx | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/components/SelectionList/BaseSelectionList.tsx b/src/components/SelectionList/BaseSelectionList.tsx index f0fd096a9d95..5b5a67dc1e28 100644 --- a/src/components/SelectionList/BaseSelectionList.tsx +++ b/src/components/SelectionList/BaseSelectionList.tsx @@ -8,7 +8,6 @@ import Button from '@components/Button'; import Checkbox from '@components/Checkbox'; import FixedFooter from '@components/FixedFooter'; import OptionsListSkeletonView from '@components/OptionsListSkeletonView'; -import PressableWithFeedback from '@components/Pressable/PressableWithFeedback'; import SafeAreaConsumer from '@components/SafeAreaConsumer'; import SectionList from '@components/SectionList'; import Text from '@components/Text'; @@ -431,28 +430,19 @@ function BaseSelectionList( ) : ( <> {!headerMessage && canSelectMultiple && shouldShowSelectAll && ( - e.preventDefault() : undefined} - > + {customListHeader ?? ( {translate('workspace.people.selectAll')} )} - + )} {!headerMessage && !canSelectMultiple && customListHeader} Date: Wed, 28 Feb 2024 15:12:03 +0000 Subject: [PATCH 163/202] Update version to 1.4.44-9 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 2528e23ebfe4..cb113bd4ffce 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -98,8 +98,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001044408 - versionName "1.4.44-8" + versionCode 1001044409 + versionName "1.4.44-9" } flavorDimensions "default" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index b8cbf2e78f99..580aa09f9d03 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.44.8 + 1.4.44.9 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 48b003f4185e..156366295c82 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.4.44.8 + 1.4.44.9 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 45b77311fb36..6b3e1231eab2 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 1.4.44 CFBundleVersion - 1.4.44.8 + 1.4.44.9 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 42795645cbe4..17e705c2bc8c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.4.44-8", + "version": "1.4.44-9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.44-8", + "version": "1.4.44-9", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 7df7dcfcb93f..e6d643517a5e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.44-8", + "version": "1.4.44-9", "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 4576f782b3ba52f4aa69f33fe6e327a7ed46d033 Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi <64629613+neonbhai@users.noreply.github.com> Date: Wed, 28 Feb 2024 20:53:59 +0530 Subject: [PATCH 164/202] Update src/components/SelectionList/types.ts Co-authored-by: Puneet Lath --- src/components/SelectionList/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 550276166e9e..54728307fd41 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -38,7 +38,7 @@ type CommonListItemProps = { /** Styles for the checkbox wrapper view if select multiple option is on */ selectMultipleStyle?: StyleProp; - /** Whether to wrap large text up to 2 lines */ + /** Whether to wrap long text up to 2 lines */ isMultilineSupported?: boolean; }; From d928ea06a8bdfee4dd1068a88627d3cfdb30884f Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi <64629613+neonbhai@users.noreply.github.com> Date: Wed, 28 Feb 2024 20:54:06 +0530 Subject: [PATCH 165/202] Update src/components/SelectionList/types.ts Co-authored-by: Puneet Lath --- src/components/SelectionList/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 54728307fd41..0a550f95dbd4 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -87,7 +87,7 @@ type ListItem = { /** Whether this option should show subscript */ shouldShowSubscript?: boolean; - /** Whether to wrap large text up to 2 lines */ + /** Whether to wrap long text up to 2 lines */ isMultilineSupported?: boolean; }; From 0253712257c16b3b3a52b83a70775dc180a1a433 Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi <64629613+neonbhai@users.noreply.github.com> Date: Wed, 28 Feb 2024 20:54:13 +0530 Subject: [PATCH 166/202] Update src/components/SelectionList/types.ts Co-authored-by: Puneet Lath --- src/components/SelectionList/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SelectionList/types.ts b/src/components/SelectionList/types.ts index 0a550f95dbd4..620f1d4cb39b 100644 --- a/src/components/SelectionList/types.ts +++ b/src/components/SelectionList/types.ts @@ -265,7 +265,7 @@ type BaseSelectionListProps = Partial & { /** Styles for the list header wrapper */ listHeaderWrapperStyle?: StyleProp; - /** Whether to wrap large text up to 2 lines */ + /** Whether to wrap long text up to 2 lines */ isRowMultilineSupported?: boolean; }; From a3334e7590d6acdd4a94bd29b6cbd5f4d2ca7177 Mon Sep 17 00:00:00 2001 From: Someshwar Tripathi <64629613+neonbhai@users.noreply.github.com> Date: Wed, 28 Feb 2024 20:54:19 +0530 Subject: [PATCH 167/202] Update src/components/TextWithTooltip/types.ts Co-authored-by: Puneet Lath --- src/components/TextWithTooltip/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TextWithTooltip/types.ts b/src/components/TextWithTooltip/types.ts index 262a1f7dba03..19c0b0dca6ed 100644 --- a/src/components/TextWithTooltip/types.ts +++ b/src/components/TextWithTooltip/types.ts @@ -10,7 +10,7 @@ type TextWithTooltipProps = { /** Additional text styles */ textStyles?: StyleProp; - /** Custom number of lines for Text */ + /** Custom number of lines for text wrapping */ numberOfLines?: number; }; From 2abcf727f390493c1b65086b5c269232cedd6da8 Mon Sep 17 00:00:00 2001 From: Carlos Barros <765936+barros001@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:28:58 -0500 Subject: [PATCH 168/202] when getting the navigation subtitle, do not recursively go through parents, but rather always use the immediate parent --- src/libs/ReportUtils.ts | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 0f8656adfa51..520a76306047 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2558,19 +2558,14 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu } /** - * Recursively navigates through thread parents to get the root report and workspace name. - * The recursion stops when we find a non thread or money request report, whichever comes first. + * Get the report name and workspace name for a report based on the type of the report */ -function getRootReportAndWorkspaceName(report: OnyxEntry): ReportAndWorkspaceName { +function getReportAndWorkspaceName(report: OnyxEntry): ReportAndWorkspaceName { if (!report) { return { rootReportName: '', }; } - if (isChildReport(report) && !isMoneyRequestReport(report) && !isTaskReport(report)) { - const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID}`] ?? null; - return getRootReportAndWorkspaceName(parentReport); - } if (isIOURequest(report)) { return { @@ -2617,16 +2612,17 @@ function getChatRoomSubtitle(report: OnyxEntry): string | undefined { * Gets the parent navigation subtitle for the report */ function getParentNavigationSubtitle(report: OnyxEntry): ParentNavigationSummaryParams { - if (isThread(report)) { - const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID}`] ?? null; - const {rootReportName, workspaceName} = getRootReportAndWorkspaceName(parentReport); - if (!rootReportName) { - return {}; - } + if (!isThread(report)) { + return {}; + } - return {rootReportName, workspaceName}; + const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID}`] ?? null; + const {rootReportName, workspaceName} = getReportAndWorkspaceName(parentReport); + if (!rootReportName) { + return {}; } - return {}; + + return {rootReportName, workspaceName}; } /** From 4d9846a4f0ed0775ecdb3622f6003e5938c7c56c Mon Sep 17 00:00:00 2001 From: Carlos Barros <765936+barros001@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:35:47 -0500 Subject: [PATCH 169/202] combine getParentNavigationSubtitle and getReportAndWorkspaceName --- src/libs/ReportUtils.ts | 54 ++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 520a76306047..867e1e3f5a12 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -98,11 +98,6 @@ type SpendBreakdown = { type ParticipantDetails = [number, string, UserUtils.AvatarSource, UserUtils.AvatarSource]; -type ReportAndWorkspaceName = { - rootReportName: string; - workspaceName?: string; -}; - type OptimisticAddCommentReportAction = Pick< ReportAction, | 'reportActionID' @@ -2557,34 +2552,6 @@ function getReportName(report: OnyxEntry, policy: OnyxEntry = nu return participantsWithoutCurrentUser.map((accountID) => getDisplayNameForParticipant(accountID, isMultipleParticipantReport)).join(', '); } -/** - * Get the report name and workspace name for a report based on the type of the report - */ -function getReportAndWorkspaceName(report: OnyxEntry): ReportAndWorkspaceName { - if (!report) { - return { - rootReportName: '', - }; - } - - if (isIOURequest(report)) { - return { - rootReportName: getReportName(report), - }; - } - if (isExpenseRequest(report)) { - return { - rootReportName: getReportName(report), - workspaceName: isIOUReport(report) ? CONST.POLICY.OWNER_EMAIL_FAKE : getPolicyName(report, true), - }; - } - - return { - rootReportName: getReportName(report), - workspaceName: getPolicyName(report, true), - }; -} - /** * Get either the policyName or domainName the chat is tied to */ @@ -2617,12 +2584,27 @@ function getParentNavigationSubtitle(report: OnyxEntry): ParentNavigatio } const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID}`] ?? null; - const {rootReportName, workspaceName} = getReportAndWorkspaceName(parentReport); - if (!rootReportName) { + if (!parentReport) { return {}; } - return {rootReportName, workspaceName}; + if (isIOURequest(parentReport)) { + return { + rootReportName: getReportName(parentReport), + }; + } + + if (isExpenseRequest(parentReport)) { + return { + rootReportName: getReportName(parentReport), + workspaceName: isIOUReport(parentReport) ? CONST.POLICY.OWNER_EMAIL_FAKE : getPolicyName(parentReport, true), + }; + } + + return { + rootReportName: getReportName(parentReport), + workspaceName: getPolicyName(parentReport, true), + }; } /** From c18774fff02b3684e32a9614806ae9dc3781f0ea Mon Sep 17 00:00:00 2001 From: OSBotify Date: Wed, 28 Feb 2024 15:36:49 +0000 Subject: [PATCH 170/202] Update version to 1.4.44-10 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index cb113bd4ffce..f2bddfacf64e 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -98,8 +98,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001044409 - versionName "1.4.44-9" + versionCode 1001044410 + versionName "1.4.44-10" } flavorDimensions "default" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 580aa09f9d03..45ab7d5c9fb4 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.44.9 + 1.4.44.10 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index 156366295c82..c2859f3a9182 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.4.44.9 + 1.4.44.10 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 6b3e1231eab2..a8b93d00800d 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 1.4.44 CFBundleVersion - 1.4.44.9 + 1.4.44.10 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 17e705c2bc8c..97748111bd78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.4.44-9", + "version": "1.4.44-10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.44-9", + "version": "1.4.44-10", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index e6d643517a5e..94c89b24f1fa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.44-9", + "version": "1.4.44-10", "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 f9eb6839d410e27c69ee7c365c203c86913e3056 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Wed, 28 Feb 2024 15:38:53 +0000 Subject: [PATCH 171/202] Update version to 1.4.44-11 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index f2bddfacf64e..90eed5dcc6e1 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -98,8 +98,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001044410 - versionName "1.4.44-10" + versionCode 1001044411 + versionName "1.4.44-11" } flavorDimensions "default" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 45ab7d5c9fb4..b9fe0b79777d 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.44.10 + 1.4.44.11 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index c2859f3a9182..fc761f96dc06 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.4.44.10 + 1.4.44.11 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index a8b93d00800d..619ac43c4a02 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 1.4.44 CFBundleVersion - 1.4.44.10 + 1.4.44.11 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 97748111bd78..78dc8c8e45bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.4.44-10", + "version": "1.4.44-11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.44-10", + "version": "1.4.44-11", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 94c89b24f1fa..c8ee6c75f9dd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.44-10", + "version": "1.4.44-11", "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 610ce2667f7b4104ecb157a8c399249a15ff91cf Mon Sep 17 00:00:00 2001 From: Carlos Barros <765936+barros001@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:39:52 -0500 Subject: [PATCH 172/202] renamed rootReportName to reportNameon ParentNavigationSummaryParams type --- src/components/ParentNavigationSubtitle.tsx | 6 +++--- src/languages/en.ts | 2 +- src/languages/es.ts | 2 +- src/languages/types.ts | 2 +- src/libs/ReportUtils.ts | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/ParentNavigationSubtitle.tsx b/src/components/ParentNavigationSubtitle.tsx index 2816715dae2c..3109453ca6b0 100644 --- a/src/components/ParentNavigationSubtitle.tsx +++ b/src/components/ParentNavigationSubtitle.tsx @@ -21,7 +21,7 @@ type ParentNavigationSubtitleProps = { function ParentNavigationSubtitle({parentNavigationSubtitleData, parentReportID = '', pressableStyles}: ParentNavigationSubtitleProps) { const styles = useThemeStyles(); - const {workspaceName, rootReportName} = parentNavigationSubtitleData; + const {workspaceName, reportName} = parentNavigationSubtitleData; const {translate} = useLocalize(); @@ -30,7 +30,7 @@ function ParentNavigationSubtitle({parentNavigationSubtitleData, parentReportID onPress={() => { Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(parentReportID)); }} - accessibilityLabel={translate('threads.parentNavigationSummary', {rootReportName, workspaceName})} + accessibilityLabel={translate('threads.parentNavigationSummary', {reportName, workspaceName})} role={CONST.ROLE.LINK} style={pressableStyles} > @@ -39,7 +39,7 @@ function ParentNavigationSubtitle({parentNavigationSubtitleData, parentReportID numberOfLines={1} > {`${translate('threads.from')} `} - {rootReportName} + {reportName} {Boolean(workspaceName) && {` ${translate('threads.in')} ${workspaceName}`}} diff --git a/src/languages/en.ts b/src/languages/en.ts index cf8823f5b2be..35b9dd9a18d1 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2171,7 +2171,7 @@ export default { reply: 'Reply', from: 'From', in: 'in', - parentNavigationSummary: ({rootReportName, workspaceName}: ParentNavigationSummaryParams) => `From ${rootReportName}${workspaceName ? ` in ${workspaceName}` : ''}`, + parentNavigationSummary: ({reportName, workspaceName}: ParentNavigationSummaryParams) => `From ${reportName}${workspaceName ? ` in ${workspaceName}` : ''}`, }, qrCodes: { copy: 'Copy URL', diff --git a/src/languages/es.ts b/src/languages/es.ts index b3a8eef73d7c..398010caf656 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2659,7 +2659,7 @@ export default { reply: 'Respuesta', from: 'De', in: 'en', - parentNavigationSummary: ({rootReportName, workspaceName}: ParentNavigationSummaryParams) => `De ${rootReportName}${workspaceName ? ` en ${workspaceName}` : ''}`, + parentNavigationSummary: ({reportName, workspaceName}: ParentNavigationSummaryParams) => `De ${reportName}${workspaceName ? ` en ${workspaceName}` : ''}`, }, qrCodes: { copy: 'Copiar URL', diff --git a/src/languages/types.ts b/src/languages/types.ts index bb56d5c38cd3..ed82bcd99a92 100644 --- a/src/languages/types.ts +++ b/src/languages/types.ts @@ -195,7 +195,7 @@ type OOOEventSummaryFullDayParams = {summary: string; dayCount: number; date: st type OOOEventSummaryPartialDayParams = {summary: string; timePeriod: string; date: string}; -type ParentNavigationSummaryParams = {rootReportName?: string; workspaceName?: string}; +type ParentNavigationSummaryParams = {reportName?: string; workspaceName?: string}; type SetTheRequestParams = {valueName: string; newValueToDisplay: string}; diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 867e1e3f5a12..97b4d93790c7 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2590,19 +2590,19 @@ function getParentNavigationSubtitle(report: OnyxEntry): ParentNavigatio if (isIOURequest(parentReport)) { return { - rootReportName: getReportName(parentReport), + reportName: getReportName(parentReport), }; } if (isExpenseRequest(parentReport)) { return { - rootReportName: getReportName(parentReport), + reportName: getReportName(parentReport), workspaceName: isIOUReport(parentReport) ? CONST.POLICY.OWNER_EMAIL_FAKE : getPolicyName(parentReport, true), }; } return { - rootReportName: getReportName(parentReport), + reportName: getReportName(parentReport), workspaceName: getPolicyName(parentReport, true), }; } From b028c51344fa7816a9f29466e6d21aa444ae3733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20M=C3=B3rawski?= Date: Wed, 28 Feb 2024 16:49:18 +0100 Subject: [PATCH 173/202] crash fix --- src/pages/tasks/TaskShareDestinationSelectorModal.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/tasks/TaskShareDestinationSelectorModal.js b/src/pages/tasks/TaskShareDestinationSelectorModal.js index 7a5b4b764e49..b62440b22967 100644 --- a/src/pages/tasks/TaskShareDestinationSelectorModal.js +++ b/src/pages/tasks/TaskShareDestinationSelectorModal.js @@ -8,6 +8,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {usePersonalDetails} from '@components/OnyxProvider'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; +import UserListItem from '@components/SelectionList/UserListItem'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; @@ -94,6 +95,7 @@ function TaskShareDestinationSelectorModal({reports, isSearchingForReports}) { /> Date: Wed, 28 Feb 2024 17:08:43 +0100 Subject: [PATCH 174/202] fix autoreporting optimistic data --- src/libs/actions/Policy.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Policy.ts b/src/libs/actions/Policy.ts index b9a2e8535b62..e1da946e81d8 100644 --- a/src/libs/actions/Policy.ts +++ b/src/libs/actions/Policy.ts @@ -392,6 +392,9 @@ function setWorkspaceAutoReporting(policyID: string, enabled: boolean) { key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { autoReporting: enabled, + harvesting: { + enabled: true, + }, pendingFields: {isAutoApprovalEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}, }, }, @@ -403,7 +406,7 @@ function setWorkspaceAutoReporting(policyID: string, enabled: boolean) { key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { autoReporting: !enabled, - pendingFields: {isAutoApprovalEnabled: null}, + pendingFields: {isAutoApprovalEnabled: null, harvesting: null}, }, }, ]; @@ -413,7 +416,7 @@ function setWorkspaceAutoReporting(policyID: string, enabled: boolean) { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, value: { - pendingFields: {isAutoApprovalEnabled: null}, + pendingFields: {isAutoApprovalEnabled: null, harvesting: null}, }, }, ]; From 720a759f69d9e72f7bdd02815f99f8328742fcdb Mon Sep 17 00:00:00 2001 From: Abdullah Alsigar Date: Wed, 28 Feb 2024 19:59:39 +0300 Subject: [PATCH 175/202] lint --- .../Pressable/GenericPressable/BaseGenericPressable.tsx | 9 ++++++--- src/pages/iou/request/step/IOURequestStepParticipants.js | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx b/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx index 647c0fcb975a..907aa2f8ae01 100644 --- a/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx +++ b/src/components/Pressable/GenericPressable/BaseGenericPressable.tsx @@ -116,9 +116,12 @@ function GenericPressable( [shouldUseHapticsOnPress, onPress, nextFocusRef, ref, isDisabled], ); - const onKeyboardShortcutPressHandler = useCallback((event?: GestureResponderEvent | KeyboardEvent) => { - onPressHandler(event); - }, [onPressHandler]); + const onKeyboardShortcutPressHandler = useCallback( + (event?: GestureResponderEvent | KeyboardEvent) => { + onPressHandler(event); + }, + [onPressHandler], + ); useEffect(() => { if (!keyboardShortcut) { diff --git a/src/pages/iou/request/step/IOURequestStepParticipants.js b/src/pages/iou/request/step/IOURequestStepParticipants.js index a6f3563bd486..25fe58585478 100644 --- a/src/pages/iou/request/step/IOURequestStepParticipants.js +++ b/src/pages/iou/request/step/IOURequestStepParticipants.js @@ -1,5 +1,6 @@ import lodashGet from 'lodash/get'; import React, {useCallback, useEffect, useRef} from 'react'; +import {Text} from 'react-native'; import transactionPropTypes from '@components/transactionPropTypes'; import useLocalize from '@hooks/useLocalize'; import compose from '@libs/compose'; From 3779e7746571f746cc3919060aec30760d669f3f Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 28 Feb 2024 10:47:30 -0700 Subject: [PATCH 176/202] Remove deprecated method and pass down parentReportAction --- src/pages/home/ReportScreen.js | 1 + src/pages/home/report/ReportActionsList.js | 5 +++++ src/pages/home/report/ReportActionsListItemRenderer.js | 10 +++++++--- src/pages/home/report/ReportActionsView.js | 4 ++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/pages/home/ReportScreen.js b/src/pages/home/ReportScreen.js index 7fba188dcedd..da5a8e4aae27 100644 --- a/src/pages/home/ReportScreen.js +++ b/src/pages/home/ReportScreen.js @@ -561,6 +561,7 @@ function ReportScreen({ ( Date: Wed, 28 Feb 2024 10:59:11 -0700 Subject: [PATCH 177/202] Fix lint --- src/pages/home/report/ReportActionsList.js | 3 ++- src/pages/home/report/ReportActionsListItemRenderer.js | 1 + src/pages/home/report/ReportActionsView.js | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionsList.js b/src/pages/home/report/ReportActionsList.js index 19bad7e61634..3ace2ebeb436 100644 --- a/src/pages/home/report/ReportActionsList.js +++ b/src/pages/home/report/ReportActionsList.js @@ -82,6 +82,7 @@ const defaultProps = { isLoadingNewerReportActions: false, ...withCurrentUserPersonalDetailsDefaultProps, policy: {}, + parentReportAction: {}, }; const VERTICAL_OFFSET_THRESHOLD = 200; @@ -426,7 +427,7 @@ function ReportActionsList({ shouldDisplayNewMarker={shouldDisplayNewMarker(reportAction, index)} /> ), - [report, linkedReportActionID, sortedReportActions, mostRecentIOUReportActionID, shouldHideThreadDividerLine, shouldDisplayNewMarker], + [report, linkedReportActionID, sortedReportActions, mostRecentIOUReportActionID, shouldHideThreadDividerLine, shouldDisplayNewMarker, parentReportAction], ); // Native mobile does not render updates flatlist the changes even though component did update called. diff --git a/src/pages/home/report/ReportActionsListItemRenderer.js b/src/pages/home/report/ReportActionsListItemRenderer.js index aa8ed9e71e2e..530480f326ed 100644 --- a/src/pages/home/report/ReportActionsListItemRenderer.js +++ b/src/pages/home/report/ReportActionsListItemRenderer.js @@ -41,6 +41,7 @@ const propTypes = { const defaultProps = { mostRecentIOUReportActionID: '', linkedReportActionID: '', + parentReportAction: {}, }; function ReportActionsListItemRenderer({ diff --git a/src/pages/home/report/ReportActionsView.js b/src/pages/home/report/ReportActionsView.js index 810b752e63ff..91a8810e91ff 100755 --- a/src/pages/home/report/ReportActionsView.js +++ b/src/pages/home/report/ReportActionsView.js @@ -81,6 +81,7 @@ const defaultProps = { session: { authTokenType: '', }, + parentReportAction: {}, }; function ReportActionsView(props) { From 31ed26f141598a1ade00717425205cba787f3f00 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 29 Feb 2024 01:05:49 +0700 Subject: [PATCH 178/202] fix: Bank account icon is a green square --- src/pages/settings/Wallet/PaymentMethodList.tsx | 17 +++++++++++++++-- .../settings/Wallet/WalletPage/WalletPage.tsx | 8 ++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Wallet/PaymentMethodList.tsx b/src/pages/settings/Wallet/PaymentMethodList.tsx index 9193074f96c8..0af2748a2d76 100644 --- a/src/pages/settings/Wallet/PaymentMethodList.tsx +++ b/src/pages/settings/Wallet/PaymentMethodList.tsx @@ -236,12 +236,25 @@ function PaymentMethodList({ (paymentMethod) => paymentMethod.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || !isEmptyObject(paymentMethod.errors), ); } - combinedPaymentMethods = combinedPaymentMethods.map((paymentMethod) => { const isMethodActive = isPaymentMethodActive(actionPaymentMethodType, activePaymentMethodID, paymentMethod); return { ...paymentMethod, - onPress: (e: GestureResponderEvent) => onPress(e, paymentMethod.accountType, paymentMethod.accountData, paymentMethod.icon, paymentMethod.isDefault, paymentMethod.methodID), + onPress: (e: GestureResponderEvent) => + onPress( + e, + paymentMethod.accountType, + paymentMethod.accountData, + { + icon: paymentMethod.icon, + iconSize: paymentMethod.iconSize, + iconHeight: paymentMethod.iconHeight, + iconWidth: paymentMethod.iconWidth, + iconStyles: paymentMethod.iconStyles, + }, + paymentMethod.isDefault, + paymentMethod.methodID, + ), wrapperStyle: isMethodActive ? [StyleUtils.getButtonBackgroundColorStyle(CONST.BUTTON_STATES.PRESSED)] : null, disabled: paymentMethod.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE, isMethodActive, diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx index 13e2877d3ec7..c20a0d053998 100644 --- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx +++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx @@ -344,7 +344,6 @@ function WalletPage({bankAccountList = {}, cardList = {}, fundList = {}, isLoadi const isPopoverBottomMount = anchorPosition.anchorPositionTop === 0 || isSmallScreenWidth; const alertTextStyle = [styles.inlineSystemMessage, styles.flexShrink1]; const alertViewStyle = [styles.flexRow, styles.alignItemsCenter, styles.w100, styles.ph5]; - return ( <> {shouldShowEmptyState ? ( @@ -538,10 +537,15 @@ function WalletPage({bankAccountList = {}, cardList = {}, fundList = {}, isLoadi {isPopoverBottomMount && ( )} {shouldShowMakeDefaultButton && ( From 3d32ca3fa229788e5bf50d62c15140ba919a69b6 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 29 Feb 2024 01:14:53 +0700 Subject: [PATCH 179/202] fix ts check --- src/pages/settings/Wallet/WalletPage/WalletPage.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx index c20a0d053998..e42caa93f54c 100644 --- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx +++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx @@ -1,7 +1,7 @@ import _ from 'lodash'; import type {ForwardedRef, RefObject} from 'react'; import React, {useCallback, useEffect, useLayoutEffect, useRef, useState} from 'react'; -import type {GestureResponderEvent} from 'react-native'; +import type {GestureResponderEvent, ViewStyle} from 'react-native'; import {ActivityIndicator, Dimensions, ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu'; @@ -42,7 +42,13 @@ import type {WalletPageOnyxProps, WalletPageProps} from './types'; type FormattedSelectedPaymentMethod = { title: string; - icon?: IconAsset; + icon?: { + icon: IconAsset; + iconSize?: number; + iconHeight?: number; + iconWidth?: number; + iconStyles?: ViewStyle[]; + }; description?: string; type?: string; }; From c1737590faa50ca05e03a2f15548aa3462b5c754 Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 28 Feb 2024 11:18:19 -0700 Subject: [PATCH 180/202] Update src/pages/home/report/ReportActionsListItemRenderer.js Co-authored-by: Rajat --- src/pages/home/report/ReportActionsListItemRenderer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/home/report/ReportActionsListItemRenderer.js b/src/pages/home/report/ReportActionsListItemRenderer.js index 530480f326ed..142be03517df 100644 --- a/src/pages/home/report/ReportActionsListItemRenderer.js +++ b/src/pages/home/report/ReportActionsListItemRenderer.js @@ -123,7 +123,6 @@ function ReportActionsListItemRenderer({ ], ); - console.debug('timddd', shouldDisplayParentAction); return shouldDisplayParentAction ? ( Date: Thu, 29 Feb 2024 01:28:59 +0700 Subject: [PATCH 181/202] fix ts check --- src/pages/settings/Wallet/PaymentMethodList.tsx | 11 +++++++++-- .../settings/Wallet/WalletPage/WalletPage.tsx | 16 ++++------------ src/pages/settings/Wallet/WalletPage/types.ts | 11 ++++++++++- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/pages/settings/Wallet/PaymentMethodList.tsx b/src/pages/settings/Wallet/PaymentMethodList.tsx index 0af2748a2d76..f76ea34bc424 100644 --- a/src/pages/settings/Wallet/PaymentMethodList.tsx +++ b/src/pages/settings/Wallet/PaymentMethodList.tsx @@ -37,6 +37,7 @@ import type PaymentMethod from '@src/types/onyx/PaymentMethod'; import type {FilterMethodPaymentType} from '@src/types/onyx/WalletTransfer'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; +import {FormattedSelectedPaymentMethodIcon} from './WalletPage/types'; type PaymentMethodListOnyxProps = { /** List of bank accounts */ @@ -99,7 +100,14 @@ type PaymentMethodListProps = PaymentMethodListOnyxProps & { shouldShowEmptyListMessage?: boolean; /** What to do when a menu item is pressed */ - onPress: (event?: GestureResponderEvent | KeyboardEvent, accountType?: string, accountData?: AccountData, icon?: IconAsset, isDefault?: boolean, methodID?: number) => void; + onPress: ( + event?: GestureResponderEvent | KeyboardEvent, + accountType?: string, + accountData?: AccountData, + icon?: FormattedSelectedPaymentMethodIcon, + isDefault?: boolean, + methodID?: number, + ) => void; }; type PaymentMethodItem = PaymentMethod & { @@ -247,7 +255,6 @@ function PaymentMethodList({ paymentMethod.accountData, { icon: paymentMethod.icon, - iconSize: paymentMethod.iconSize, iconHeight: paymentMethod.iconHeight, iconWidth: paymentMethod.iconWidth, iconStyles: paymentMethod.iconStyles, diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx index e42caa93f54c..c73dcf941d26 100644 --- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx +++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx @@ -1,7 +1,7 @@ import _ from 'lodash'; import type {ForwardedRef, RefObject} from 'react'; import React, {useCallback, useEffect, useLayoutEffect, useRef, useState} from 'react'; -import type {GestureResponderEvent, ViewStyle} from 'react-native'; +import type {GestureResponderEvent} from 'react-native'; import {ActivityIndicator, Dimensions, ScrollView, View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu'; @@ -37,18 +37,11 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {AccountData} from '@src/types/onyx'; -import type IconAsset from '@src/types/utils/IconAsset'; -import type {WalletPageOnyxProps, WalletPageProps} from './types'; +import type {FormattedSelectedPaymentMethodIcon, WalletPageOnyxProps, WalletPageProps} from './types'; type FormattedSelectedPaymentMethod = { title: string; - icon?: { - icon: IconAsset; - iconSize?: number; - iconHeight?: number; - iconWidth?: number; - iconStyles?: ViewStyle[]; - }; + icon?: FormattedSelectedPaymentMethodIcon; description?: string; type?: string; }; @@ -157,7 +150,7 @@ function WalletPage({bankAccountList = {}, cardList = {}, fundList = {}, isLoadi nativeEvent?: GestureResponderEvent | KeyboardEvent, accountType?: string, account?: AccountData, - icon?: IconAsset, + icon?: FormattedSelectedPaymentMethodIcon, isDefault?: boolean, methodID?: string | number, ) => { @@ -547,7 +540,6 @@ function WalletPage({bankAccountList = {}, cardList = {}, fundList = {}, isLoadi iconHeight={paymentMethod.formattedSelectedPaymentMethod.icon?.iconHeight} iconWidth={paymentMethod.formattedSelectedPaymentMethod.icon?.iconWidth} iconStyles={paymentMethod.formattedSelectedPaymentMethod.icon?.iconStyles} - iconSize={paymentMethod.formattedSelectedPaymentMethod.icon?.iconSize} description={paymentMethod.formattedSelectedPaymentMethod.description} wrapperStyle={[styles.mb4, styles.ph5, styles.pv0]} interactive={false} diff --git a/src/pages/settings/Wallet/WalletPage/types.ts b/src/pages/settings/Wallet/WalletPage/types.ts index 0c3db1a2df65..937353b92759 100644 --- a/src/pages/settings/Wallet/WalletPage/types.ts +++ b/src/pages/settings/Wallet/WalletPage/types.ts @@ -1,5 +1,7 @@ +import {ViewStyle} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import type {BankAccountList, CardList, FundList, UserWallet, WalletTerms, WalletTransfer} from '@src/types/onyx'; +import IconAsset from '@src/types/utils/IconAsset'; type WalletPageOnyxProps = { /** Wallet balance transfer props */ @@ -28,4 +30,11 @@ type WalletPageProps = WalletPageOnyxProps & { shouldListenForResize?: boolean; }; -export type {WalletPageOnyxProps, WalletPageProps}; +type FormattedSelectedPaymentMethodIcon = { + icon: IconAsset; + iconHeight?: number; + iconWidth?: number; + iconStyles?: ViewStyle[]; +}; + +export type {WalletPageOnyxProps, WalletPageProps, FormattedSelectedPaymentMethodIcon}; From 056bc1d76a4daf3062911f0f9f22a8ff30dae1ac Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 29 Feb 2024 01:38:28 +0700 Subject: [PATCH 182/202] fix lint --- src/pages/settings/Wallet/PaymentMethodList.tsx | 3 +-- src/pages/settings/Wallet/WalletPage/types.ts | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Wallet/PaymentMethodList.tsx b/src/pages/settings/Wallet/PaymentMethodList.tsx index f76ea34bc424..ea399677898e 100644 --- a/src/pages/settings/Wallet/PaymentMethodList.tsx +++ b/src/pages/settings/Wallet/PaymentMethodList.tsx @@ -36,8 +36,7 @@ import type {Errors} from '@src/types/onyx/OnyxCommon'; import type PaymentMethod from '@src/types/onyx/PaymentMethod'; import type {FilterMethodPaymentType} from '@src/types/onyx/WalletTransfer'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import type IconAsset from '@src/types/utils/IconAsset'; -import {FormattedSelectedPaymentMethodIcon} from './WalletPage/types'; +import type {FormattedSelectedPaymentMethodIcon} from './WalletPage/types'; type PaymentMethodListOnyxProps = { /** List of bank accounts */ diff --git a/src/pages/settings/Wallet/WalletPage/types.ts b/src/pages/settings/Wallet/WalletPage/types.ts index 937353b92759..7ad46a6b348f 100644 --- a/src/pages/settings/Wallet/WalletPage/types.ts +++ b/src/pages/settings/Wallet/WalletPage/types.ts @@ -1,7 +1,7 @@ -import {ViewStyle} from 'react-native'; +import type {ViewStyle} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import type {BankAccountList, CardList, FundList, UserWallet, WalletTerms, WalletTransfer} from '@src/types/onyx'; -import IconAsset from '@src/types/utils/IconAsset'; +import type IconAsset from '@src/types/utils/IconAsset'; type WalletPageOnyxProps = { /** Wallet balance transfer props */ From 815dae1a86a9880cc3f17aafb4bdf816c15ebeeb Mon Sep 17 00:00:00 2001 From: Tim Golen Date: Wed, 28 Feb 2024 11:49:54 -0700 Subject: [PATCH 183/202] Remove extra whitespace --- src/pages/home/report/ReportActionsListItemRenderer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/home/report/ReportActionsListItemRenderer.js b/src/pages/home/report/ReportActionsListItemRenderer.js index 142be03517df..bc8e6a94359f 100644 --- a/src/pages/home/report/ReportActionsListItemRenderer.js +++ b/src/pages/home/report/ReportActionsListItemRenderer.js @@ -123,7 +123,6 @@ function ReportActionsListItemRenderer({ ], ); - return shouldDisplayParentAction ? ( Date: Wed, 28 Feb 2024 14:50:54 -0500 Subject: [PATCH 184/202] simplified getParentNavigationSubtitle logic --- src/libs/ReportUtils.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 97b4d93790c7..3eea36727ea0 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2579,12 +2579,8 @@ function getChatRoomSubtitle(report: OnyxEntry): string | undefined { * Gets the parent navigation subtitle for the report */ function getParentNavigationSubtitle(report: OnyxEntry): ParentNavigationSummaryParams { - if (!isThread(report)) { - return {}; - } - - const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${report?.parentReportID}`] ?? null; - if (!parentReport) { + const parentReport = getParentReport(report); + if (isEmptyObject(parentReport)) { return {}; } @@ -2594,13 +2590,6 @@ function getParentNavigationSubtitle(report: OnyxEntry): ParentNavigatio }; } - if (isExpenseRequest(parentReport)) { - return { - reportName: getReportName(parentReport), - workspaceName: isIOUReport(parentReport) ? CONST.POLICY.OWNER_EMAIL_FAKE : getPolicyName(parentReport, true), - }; - } - return { reportName: getReportName(parentReport), workspaceName: getPolicyName(parentReport, true), From afac4f45b5790da4af173f4a6a0d8de09465e173 Mon Sep 17 00:00:00 2001 From: dukenv0307 Date: Thu, 29 Feb 2024 03:06:37 +0700 Subject: [PATCH 185/202] fallback iconSize --- src/pages/settings/Wallet/PaymentMethodList.tsx | 7 ++++--- src/pages/settings/Wallet/WalletPage/WalletPage.tsx | 7 +++++-- src/pages/settings/Wallet/WalletPage/types.ts | 1 + 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/pages/settings/Wallet/PaymentMethodList.tsx b/src/pages/settings/Wallet/PaymentMethodList.tsx index ea399677898e..556634269f5c 100644 --- a/src/pages/settings/Wallet/PaymentMethodList.tsx +++ b/src/pages/settings/Wallet/PaymentMethodList.tsx @@ -254,9 +254,10 @@ function PaymentMethodList({ paymentMethod.accountData, { icon: paymentMethod.icon, - iconHeight: paymentMethod.iconHeight, - iconWidth: paymentMethod.iconWidth, - iconStyles: paymentMethod.iconStyles, + iconHeight: paymentMethod?.iconHeight, + iconWidth: paymentMethod?.iconWidth, + iconStyles: paymentMethod?.iconStyles, + iconSize: paymentMethod?.iconSize, }, paymentMethod.isDefault, paymentMethod.methodID, diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx index c73dcf941d26..c9e11b31c7d6 100644 --- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx +++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx @@ -154,6 +154,7 @@ function WalletPage({bankAccountList = {}, cardList = {}, fundList = {}, isLoadi isDefault?: boolean, methodID?: string | number, ) => { + console.log(icon); if (shouldShowAddPaymentMenu) { setShouldShowAddPaymentMenu(false); return; @@ -343,6 +344,8 @@ function WalletPage({bankAccountList = {}, cardList = {}, fundList = {}, isLoadi const isPopoverBottomMount = anchorPosition.anchorPositionTop === 0 || isSmallScreenWidth; const alertTextStyle = [styles.inlineSystemMessage, styles.flexShrink1]; const alertViewStyle = [styles.flexRow, styles.alignItemsCenter, styles.w100, styles.ph5]; + + console.log(paymentMethod.formattedSelectedPaymentMethod.icon); return ( <> {shouldShowEmptyState ? ( @@ -537,8 +540,8 @@ function WalletPage({bankAccountList = {}, cardList = {}, fundList = {}, isLoadi Date: Thu, 29 Feb 2024 03:13:20 +0700 Subject: [PATCH 186/202] remove console.log --- src/pages/settings/Wallet/WalletPage/WalletPage.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx index c9e11b31c7d6..b9f49049d51a 100644 --- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx +++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx @@ -154,7 +154,6 @@ function WalletPage({bankAccountList = {}, cardList = {}, fundList = {}, isLoadi isDefault?: boolean, methodID?: string | number, ) => { - console.log(icon); if (shouldShowAddPaymentMenu) { setShouldShowAddPaymentMenu(false); return; @@ -345,7 +344,6 @@ function WalletPage({bankAccountList = {}, cardList = {}, fundList = {}, isLoadi const alertTextStyle = [styles.inlineSystemMessage, styles.flexShrink1]; const alertViewStyle = [styles.flexRow, styles.alignItemsCenter, styles.w100, styles.ph5]; - console.log(paymentMethod.formattedSelectedPaymentMethod.icon); return ( <> {shouldShowEmptyState ? ( From 663eb40fe11126d083df2b858872ba848fa0a1d3 Mon Sep 17 00:00:00 2001 From: Carlos Barros <765936+barros001@users.noreply.github.com> Date: Wed, 28 Feb 2024 15:28:30 -0500 Subject: [PATCH 187/202] removed unnecessary if block that was removing the policy name from header when it was not supposed to. --- src/libs/ReportUtils.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index ee2dcf5d02d6..be75f6c28909 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2585,12 +2585,6 @@ function getParentNavigationSubtitle(report: OnyxEntry): ParentNavigatio return {}; } - if (isIOURequest(parentReport)) { - return { - reportName: getReportName(parentReport), - }; - } - return { reportName: getReportName(parentReport), workspaceName: getPolicyName(parentReport, true), From e6c5cc419d47cfc5f807fc532818b252b2302fce Mon Sep 17 00:00:00 2001 From: OSBotify Date: Wed, 28 Feb 2024 20:55:41 +0000 Subject: [PATCH 188/202] Update version to 1.4.44-12 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 90eed5dcc6e1..fb798c33d1a9 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -98,8 +98,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1001044411 - versionName "1.4.44-11" + versionCode 1001044412 + versionName "1.4.44-12" } flavorDimensions "default" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index b9fe0b79777d..f62dd79f5ce5 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -40,7 +40,7 @@ CFBundleVersion - 1.4.44.11 + 1.4.44.12 ITSAppUsesNonExemptEncryption LSApplicationQueriesSchemes diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index fc761f96dc06..ddbd21b2842a 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 1.4.44.11 + 1.4.44.12 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index 619ac43c4a02..4cffc1f6179a 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 1.4.44 CFBundleVersion - 1.4.44.11 + 1.4.44.12 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index 78dc8c8e45bc..32039aebb62f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "1.4.44-11", + "version": "1.4.44-12", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "1.4.44-11", + "version": "1.4.44-12", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index c8ee6c75f9dd..b1b5dc67327f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "1.4.44-11", + "version": "1.4.44-12", "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 aaf9d4cb8c4dad6f7fdbd7fd44e411eca0197bde Mon Sep 17 00:00:00 2001 From: Puneet Lath Date: Wed, 28 Feb 2024 16:30:59 -0500 Subject: [PATCH 189/202] Return BaseOptionsSelector.js to class component --- .../OptionsSelector/BaseOptionsSelector.js | 1087 ++++++++--------- 1 file changed, 528 insertions(+), 559 deletions(-) diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 1fa63f181dd6..3fe4711a1292 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -1,8 +1,6 @@ -import {useIsFocused} from '@react-navigation/native'; import lodashGet from 'lodash/get'; -import lodashIsEqual from 'lodash/isEqual'; import PropTypes from 'prop-types'; -import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from 'react'; +import React, {Component} from 'react'; import {ScrollView, View} from 'react-native'; import _ from 'underscore'; import ArrowKeyFocusManager from '@components/ArrowKeyFocusManager'; @@ -13,10 +11,11 @@ import OptionsList from '@components/OptionsList'; import ReferralProgramCTA from '@components/ReferralProgramCTA'; import ShowMoreButton from '@components/ShowMoreButton'; import TextInput from '@components/TextInput'; -import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; -import useLocalize from '@hooks/useLocalize'; -import usePrevious from '@hooks/usePrevious'; -import useThemeStyles from '@hooks/useThemeStyles'; +import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import withNavigationFocus from '@components/withNavigationFocus'; +import withTheme, {withThemePropTypes} from '@components/withTheme'; +import withThemeStyles, {withThemeStylesPropTypes} from '@components/withThemeStyles'; +import compose from '@libs/compose'; import getPlatform from '@libs/getPlatform'; import KeyboardShortcut from '@libs/KeyboardShortcut'; import setSelection from '@libs/setSelection'; @@ -36,6 +35,9 @@ const propTypes = { /** List styles for OptionsList */ listStyles: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]), + /** Whether navigation is focused */ + isFocused: PropTypes.bool.isRequired, + /** Whether referral CTA should be displayed */ shouldShowReferralCTA: PropTypes.bool, @@ -43,9 +45,13 @@ const propTypes = { referralContentType: PropTypes.string, ...optionsSelectorPropTypes, + ...withLocalizePropTypes, + ...withThemeStylesPropTypes, + ...withThemePropTypes, }; const defaultProps = { + shouldDelayFocus: false, shouldShowReferralCTA: false, referralContentType: CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND, safeAreaPaddingBottomStyle: {}, @@ -55,657 +61,620 @@ const defaultProps = { ...optionsSelectorDefaultProps, }; -function BaseOptionsSelector(props) { - const isFocused = useIsFocused(); - const {translate} = useLocalize(); - const themeStyles = useThemeStyles(); - - const getInitiallyFocusedIndex = useCallback( - (allOptions) => { - let defaultIndex; - if (props.shouldTextInputAppearBelowOptions) { - defaultIndex = allOptions.length; - } else if (props.focusedIndex >= 0) { - defaultIndex = props.focusedIndex; - } else { - defaultIndex = props.selectedOptions.length; +class BaseOptionsSelector extends Component { + constructor(props) { + super(props); + + this.updateFocusedIndex = this.updateFocusedIndex.bind(this); + this.scrollToIndex = this.scrollToIndex.bind(this); + this.selectRow = this.selectRow.bind(this); + this.selectFocusedOption = this.selectFocusedOption.bind(this); + this.addToSelection = this.addToSelection.bind(this); + this.updateSearchValue = this.updateSearchValue.bind(this); + this.incrementPage = this.incrementPage.bind(this); + this.sliceSections = this.sliceSections.bind(this); + this.calculateAllVisibleOptionsCount = this.calculateAllVisibleOptionsCount.bind(this); + this.handleFocusIn = this.handleFocusIn.bind(this); + this.handleFocusOut = this.handleFocusOut.bind(this); + this.debouncedUpdateSearchValue = _.debounce(this.updateSearchValue, CONST.TIMING.SEARCH_OPTION_LIST_DEBOUNCE_TIME); + this.relatedTarget = null; + this.accessibilityRoles = _.values(CONST.ROLE); + this.isWebOrDesktop = [CONST.PLATFORM.DESKTOP, CONST.PLATFORM.WEB].includes(getPlatform()); + + const allOptions = this.flattenSections(); + const sections = this.sliceSections(); + const focusedIndex = this.getInitiallyFocusedIndex(allOptions); + this.focusedOption = allOptions[focusedIndex]; + + this.state = { + sections, + allOptions, + focusedIndex, + shouldDisableRowSelection: false, + errorMessage: '', + paginationPage: 1, + disableEnterShortCut: false, + value: '', + }; + } + + componentDidMount() { + this.subscribeToEnterShortcut(); + this.subscribeToCtrlEnterShortcut(); + this.subscribeActiveElement(); + + if (this.props.isFocused && this.props.autoFocus && this.textInput) { + this.focusTimeout = setTimeout(() => { + this.textInput.focus(); + }, CONST.ANIMATED_TRANSITION); + } + + this.scrollToIndex(this.props.selectedOptions.length ? 0 : this.state.focusedIndex, false); + } + + componentDidUpdate(prevProps, prevState) { + if (prevState.disableEnterShortCut !== this.state.disableEnterShortCut) { + // Unregister the shortcut before registering a new one to avoid lingering shortcut listener + this.unsubscribeEnter(); + if (!this.state.disableEnterShortCut) { + this.subscribeToEnterShortcut(); } - if (_.isUndefined(props.initiallyFocusedOptionKey)) { - return defaultIndex; + } + + if (prevProps.isFocused !== this.props.isFocused) { + // Unregister the shortcut before registering a new one to avoid lingering shortcut listener + this.unSubscribeFromKeyboardShortcut(); + if (this.props.isFocused) { + this.subscribeToEnterShortcut(); + this.subscribeToCtrlEnterShortcut(); } + } - const indexOfInitiallyFocusedOption = _.findIndex(allOptions, (option) => option.keyForList === props.initiallyFocusedOptionKey); - - return indexOfInitiallyFocusedOption; - }, - [props.shouldTextInputAppearBelowOptions, props.initiallyFocusedOptionKey, props.selectedOptions.length, props.focusedIndex], - ); - - const isWebOrDesktop = [CONST.PLATFORM.DESKTOP, CONST.PLATFORM.WEB].includes(getPlatform()); - const accessibilityRoles = _.values(CONST.ROLE); - - const [disabledOptionsIndexes, setDisabledOptionsIndexes] = useState([]); - const [shouldDisableRowSelection, setShouldDisableRowSelection] = useState(false); - const [errorMessage, setErrorMessage] = useState(''); - const [value, setValue] = useState(''); - const [paginationPage, setPaginationPage] = useState(1); - const [disableEnterShortCut, setDisableEnterShortCut] = useState(false); - - const relatedTarget = useRef(null); - const listRef = useRef(); - const textInputRef = useRef(); - const enterSubscription = useRef(); - const CTRLEnterSubscription = useRef(); - const focusTimeout = useRef(); - const prevLocale = useRef(props.preferredLocale); - const prevPaginationPage = useRef(paginationPage); - const prevSelectedOptions = useRef(props.selectedOptions); - const prevValue = useRef(value); - const previousSections = usePrevious(props.sections); - - useImperativeHandle(props.forwardedRef, () => textInputRef.current); + // Screen coming back into focus, for example + // when doing Cmd+Shift+K, then Cmd+K, then Cmd+Shift+K. + // Only applies to platforms that support keyboard shortcuts + if (this.isWebOrDesktop && !prevProps.isFocused && this.props.isFocused && this.props.autoFocus && this.textInput) { + setTimeout(() => { + this.textInput.focus(); + }, CONST.ANIMATED_TRANSITION); + } - /** - * Flattens the sections into a single array of options. - * Each object in this array is enhanced to have: - * - * 1. A `sectionIndex`, which represents the index of the section it came from - * 2. An `index`, which represents the index of the option within the section it came from. - * - * @returns {Array} - */ - const flattenSections = useCallback(() => { - const calcAllOptions = []; - const calcDisabledOptionsIndexes = []; - let index = 0; - _.each(props.sections, (section, sectionIndex) => { - _.each(section.data, (option, optionIndex) => { - calcAllOptions.push({ - ...option, - sectionIndex, - index: optionIndex, - }); - if (section.isDisabled || option.isDisabled) { - calcDisabledOptionsIndexes.push(index); - } - index += 1; + if (prevState.paginationPage !== this.state.paginationPage) { + const newSections = this.sliceSections(); + + this.setState({ + sections: newSections, }); - }); + } - setDisabledOptionsIndexes(calcDisabledOptionsIndexes); - return calcAllOptions; - }, [props.sections]); + if (prevState.focusedIndex !== this.state.focusedIndex) { + this.focusedOption = this.state.allOptions[this.state.focusedIndex]; + } - /** - * Maps sections to render only allowed count of them per section. - * - * @returns {Object[]} - */ - const sliceSections = useCallback( - () => - _.map(props.sections, (section) => { - if (_.isEmpty(section.data)) { - return section; + if (_.isEqual(this.props.sections, prevProps.sections)) { + return; + } + + const newSections = this.sliceSections(); + const newOptions = this.flattenSections(); + + if (prevProps.preferredLocale !== this.props.preferredLocale) { + this.setState({ + sections: newSections, + allOptions: newOptions, + }); + return; + } + const newFocusedIndex = this.props.selectedOptions.length; + const isNewFocusedIndex = newFocusedIndex !== this.state.focusedIndex; + const prevFocusedOption = _.find(newOptions, (option) => this.focusedOption && option.keyForList === this.focusedOption.keyForList); + const prevFocusedOptionIndex = prevFocusedOption ? _.findIndex(newOptions, (option) => this.focusedOption && option.keyForList === this.focusedOption.keyForList) : undefined; + // eslint-disable-next-line react/no-did-update-set-state + this.setState( + { + sections: newSections, + allOptions: newOptions, + focusedIndex: prevFocusedOptionIndex || (_.isNumber(this.props.focusedIndex) ? this.props.focusedIndex : newFocusedIndex), + }, + () => { + // If we just toggled an option on a multi-selection page or cleared the search input, scroll to top + if (this.props.selectedOptions.length !== prevProps.selectedOptions.length || (!!prevState.value && !this.state.value)) { + this.scrollToIndex(0); + return; } - const pagination = paginationPage || 1; + // Otherwise, scroll to the focused index (as long as it's in range) + if (this.state.allOptions.length <= this.state.focusedIndex || !isNewFocusedIndex) { + return; + } + this.scrollToIndex(this.state.focusedIndex); + }, + ); + } - return { - ...section, - data: section.data.slice(0, CONST.MAX_OPTIONS_SELECTOR_PAGE_LENGTH * pagination), - }; - }), - [paginationPage, props.sections], - ); + componentWillUnmount() { + if (this.focusTimeout) { + clearTimeout(this.focusTimeout); + } - // eslint-disable-next-line react-hooks/exhaustive-deps - const initialAllOptions = useMemo(() => flattenSections(), []); - const [sections, setSections] = useState(sliceSections()); - const [allOptions, setAllOptions] = useState(initialAllOptions); - const [focusedIndex, setFocusedIndex] = useState(getInitiallyFocusedIndex(initialAllOptions)); - const [focusedOption, setFocusedOption] = useState(allOptions[focusedIndex]); + this.unSubscribeFromKeyboardShortcut(); + } /** - * Completes the follow-up actions after a row is selected - * - * @param {Object} option - * @param {Object} ref - * @returns {Promise} + * @param {Array} allOptions + * @returns {Number} */ - const selectRow = useCallback( - (option, ref) => - new Promise((resolve) => { - if (props.shouldShowTextInput && props.shouldPreventDefaultFocusOnSelectRow) { - if (relatedTarget.current && ref === relatedTarget.current) { - textInputRef.current.focus(); - relatedTarget.current = null; - } - if (textInputRef.current.isFocused()) { - setSelection(textInputRef.current, 0, value.length); - } - } - const selectedOption = props.onSelectRow(option); - resolve(selectedOption); - - if (!props.canSelectMultipleOptions) { - return; - } + getInitiallyFocusedIndex(allOptions) { + let defaultIndex; + if (this.props.shouldTextInputAppearBelowOptions) { + defaultIndex = allOptions.length; + } else if (this.props.focusedIndex >= 0) { + defaultIndex = this.props.focusedIndex; + } else { + defaultIndex = this.props.selectedOptions.length; + } + if (_.isUndefined(this.props.initiallyFocusedOptionKey)) { + return defaultIndex; + } - // Focus the first unselected item from the list (i.e: the best result according to the current search term) - setFocusedIndex(props.selectedOptions.length); - }), - // eslint-disable-next-line react-hooks/exhaustive-deps - [props.shouldShowTextInput, props.shouldPreventDefaultFocusOnSelectRow, value.length, props.canSelectMultipleOptions, props.selectedOptions.length], - ); + const indexOfInitiallyFocusedOption = _.findIndex(allOptions, (option) => option.keyForList === this.props.initiallyFocusedOptionKey); - const selectFocusedOption = useCallback( - (e) => { - const focusedItemKey = lodashGet(e, ['target', 'attributes', 'id', 'value']); - const localFocusedOption = focusedItemKey ? _.find(allOptions, (option) => option.keyForList === focusedItemKey) : allOptions[focusedIndex]; + return indexOfInitiallyFocusedOption; + } - if (!localFocusedOption || !isFocused) { - return; + /** + * Maps sections to render only allowed count of them per section. + * + * @returns {Objects[]} + */ + sliceSections() { + return _.map(this.props.sections, (section) => { + if (_.isEmpty(section.data)) { + return section; } - if (props.canSelectMultipleOptions) { - selectRow(localFocusedOption); - } else if (!shouldDisableRowSelection) { - setShouldDisableRowSelection(true); + return { + ...section, + data: section.data.slice(0, CONST.MAX_OPTIONS_SELECTOR_PAGE_LENGTH * lodashGet(this.state, 'paginationPage', 1)), + }; + }); + } - let result = selectRow(localFocusedOption); - if (!(result instanceof Promise)) { - result = Promise.resolve(); - } + /** + * Calculates all currently visible options based on the sections that are currently being shown + * and the number of items of those sections. + * + * @returns {Number} + */ + calculateAllVisibleOptionsCount() { + let count = 0; - setTimeout(() => { - result.finally(() => { - setShouldDisableRowSelection(false); - }); - }, 500); - } - }, - [props.canSelectMultipleOptions, focusedIndex, allOptions, isFocused, selectRow, shouldDisableRowSelection], - ); + _.forEach(this.state.sections, (section) => { + count += lodashGet(section, 'data.length', 0); + }); + + return count; + } + + updateSearchValue(value) { + this.setState({ + paginationPage: 1, + errorMessage: value.length > this.props.maxLength ? ['common.error.characterLimitExceedCounter', {length: value.length, limit: this.props.maxLength}] : '', + value, + }); + + this.props.onChangeText(value); + } - const handleFocusIn = () => { + handleFocusIn() { const activeElement = document.activeElement; - setDisableEnterShortCut(activeElement && accessibilityRoles.includes(activeElement.role) && activeElement.role !== CONST.ROLE.PRESENTATION); - }; + this.setState({ + disableEnterShortCut: activeElement && this.accessibilityRoles.includes(activeElement.role) && activeElement.role !== CONST.ROLE.PRESENTATION, + }); + } - const handleFocusOut = () => { - setDisableEnterShortCut(false); - }; + handleFocusOut() { + this.setState({ + disableEnterShortCut: false, + }); + } - const subscribeActiveElement = () => { - if (!isWebOrDesktop) { + subscribeActiveElement() { + if (!this.isWebOrDesktop) { return; } - document.addEventListener('focusin', handleFocusIn); - document.addEventListener('focusout', handleFocusOut); - }; + document.addEventListener('focusin', this.handleFocusIn); + document.addEventListener('focusout', this.handleFocusOut); + } - const subscribeToEnterShortcut = () => { + unSubscribeActiveElement() { + if (!this.isWebOrDesktop) { + return; + } + document.removeEventListener('focusin', this.handleFocusIn); + document.removeEventListener('focusout', this.handleFocusOut); + } + + subscribeToEnterShortcut() { const enterConfig = CONST.KEYBOARD_SHORTCUTS.ENTER; - enterSubscription.current = KeyboardShortcut.subscribe( + this.unsubscribeEnter = KeyboardShortcut.subscribe( enterConfig.shortcutKey, - selectFocusedOption, + this.selectFocusedOption, enterConfig.descriptionKey, enterConfig.modifiers, true, - () => !allOptions[focusedIndex], + () => !this.state.allOptions[this.state.focusedIndex], ); - }; + } - const subscribeToCtrlEnterShortcut = () => { + subscribeToCtrlEnterShortcut() { const CTRLEnterConfig = CONST.KEYBOARD_SHORTCUTS.CTRL_ENTER; - CTRLEnterSubscription.current = KeyboardShortcut.subscribe( + this.unsubscribeCTRLEnter = KeyboardShortcut.subscribe( CTRLEnterConfig.shortcutKey, () => { - if (props.canSelectMultipleOptions) { - props.onConfirmSelection(); + if (this.props.canSelectMultipleOptions) { + this.props.onConfirmSelection(); return; } - const localFocusedOption = allOptions[focusedIndex]; - if (!localFocusedOption) { + const focusedOption = this.state.allOptions[this.state.focusedIndex]; + if (!focusedOption) { return; } - selectRow(localFocusedOption); + this.selectRow(focusedOption); }, CTRLEnterConfig.descriptionKey, CTRLEnterConfig.modifiers, true, ); - }; + } - const unSubscribeFromKeyboardShortcut = () => { - if (enterSubscription.current) { - enterSubscription.current(); + unSubscribeFromKeyboardShortcut() { + if (this.unsubscribeEnter) { + this.unsubscribeEnter(); } - if (CTRLEnterSubscription.current) { - CTRLEnterSubscription.current(); + if (this.unsubscribeCTRLEnter) { + this.unsubscribeCTRLEnter(); } - }; + } - const selectOptions = useCallback(() => { - if (props.canSelectMultipleOptions) { - props.onConfirmSelection(); - return; - } + selectFocusedOption(e) { + const focusedItemKey = lodashGet(e, ['target', 'attributes', 'id', 'value']); + const focusedOption = focusedItemKey ? _.find(this.state.allOptions, (option) => option.keyForList === focusedItemKey) : this.state.allOptions[this.state.focusedIndex]; - const localFocusedOption = allOptions[focusedIndex]; - if (!localFocusedOption) { + if (!focusedOption || !this.props.isFocused) { return; } - selectRow(localFocusedOption); - // we don't need to include the whole props object as the dependency - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [allOptions, focusedIndex, props.canSelectMultipleOptions, props.onConfirmSelection, selectRow]); - - useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.ENTER, selectFocusedOption, { - shouldBubble: !allOptions[focusedIndex], - captureOnInputs: true, - }); - useKeyboardShortcut(CONST.KEYBOARD_SHORTCUTS.CTRL_ENTER, selectOptions, {captureOnInputs: true}); - - /** - * Scrolls to the focused index within the SectionList - * - * @param {Number} index - * @param {Boolean} animated - */ - const scrollToIndex = useCallback( - (index, animated = true) => { - const option = allOptions[index]; - if (!listRef.current || !option) { - return; - } - - const itemIndex = option.index; - const sectionIndex = option.sectionIndex; - - if (!lodashGet(sections, `[${sectionIndex}].data[${itemIndex}]`, null)) { - return; - } - - // Note: react-native's SectionList automatically strips out any empty sections. - // So we need to reduce the sectionIndex to remove any empty sections in front of the one we're trying to scroll to. - // Otherwise, it will cause an index-out-of-bounds error and crash the app. - let adjustedSectionIndex = sectionIndex; - for (let i = 0; i < sectionIndex; i++) { - if (_.isEmpty(lodashGet(sections, `[${i}].data`))) { - adjustedSectionIndex--; - } - } - - listRef.current.scrollToLocation({sectionIndex: adjustedSectionIndex, itemIndex, animated}); - }, - [allOptions, sections], - ); - - useEffect(() => { - subscribeToEnterShortcut(); - subscribeToCtrlEnterShortcut(); - subscribeActiveElement(); - - if (props.isFocused && props.autoFocus && textInputRef.current) { - focusTimeout.current = setTimeout(() => { - textInputRef.current.focus(); - }, CONST.ANIMATED_TRANSITION); - } - - scrollToIndex(props.selectedOptions.length ? 0 : focusedIndex, false); + if (this.props.canSelectMultipleOptions) { + this.selectRow(focusedOption); + } else if (!this.state.shouldDisableRowSelection) { + this.setState({shouldDisableRowSelection: true}); - return () => { - if (focusTimeout.current) { - clearTimeout(focusTimeout.current); + let result = this.selectRow(focusedOption); + if (!(result instanceof Promise)) { + result = Promise.resolve(); } - unSubscribeFromKeyboardShortcut(); - }; - // we want to run this effect only once, when the component is mounted - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - useEffect(() => { - // Unregister the shortcut before registering a new one to avoid lingering shortcut listener - enterSubscription.current(); - if (!disableEnterShortCut) { - subscribeToEnterShortcut(); + setTimeout(() => { + result.finally(() => { + this.setState({shouldDisableRowSelection: false}); + }); + }, 500); } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [disableEnterShortCut]); + } - useEffect(() => { - if (props.isFocused) { - subscribeToEnterShortcut(); - subscribeToCtrlEnterShortcut(); - } else { - unSubscribeFromKeyboardShortcut(); + focus() { + if (!this.textInput) { + return; } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [props.isFocused]); - - useEffect(() => { - const newSections = sliceSections(); - if (prevPaginationPage.current !== paginationPage) { - prevPaginationPage.current = paginationPage; - setSections(newSections); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [paginationPage]); + this.textInput.focus(); + } - useEffect(() => { - setFocusedOption(allOptions[focusedIndex]); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [focusedIndex]); + /** + * Flattens the sections into a single array of options. + * Each object in this array is enhanced to have: + * + * 1. A `sectionIndex`, which represents the index of the section it came from + * 2. An `index`, which represents the index of the option within the section it came from. + * + * @returns {Array} + */ + flattenSections() { + const allOptions = []; + this.disabledOptionsIndexes = []; + let index = 0; + _.each(this.props.sections, (section, sectionIndex) => { + _.each(section.data, (option, optionIndex) => { + allOptions.push({ + ...option, + sectionIndex, + index: optionIndex, + }); + if (section.isDisabled || option.isDisabled) { + this.disabledOptionsIndexes.push(index); + } + index += 1; + }); + }); + return allOptions; + } - // eslint-disable-next-line rulesdir/prefer-early-return - useEffect(() => { - // Screen coming back into focus, for example - // when doing Cmd+Shift+K, then Cmd+K, then Cmd+Shift+K. - // Only applies to platforms that support keyboard shortcuts - if (isWebOrDesktop && isFocused && props.autoFocus && textInputRef.current) { - setTimeout(() => { - textInputRef.current.focus(); - }, CONST.ANIMATED_TRANSITION); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isFocused, props.autoFocus]); + /** + * @param {Number} index + */ + updateFocusedIndex(index) { + this.setState({focusedIndex: index}, () => this.scrollToIndex(index)); + } - useEffect(() => { - if (lodashIsEqual(props.sections, previousSections)) { + /** + * Scrolls to the focused index within the SectionList + * + * @param {Number} index + * @param {Boolean} animated + */ + scrollToIndex(index, animated = true) { + const option = this.state.allOptions[index]; + if (!this.list || !option) { return; } - const newSections = sliceSections(); - const newOptions = flattenSections(); + const itemIndex = option.index; + const sectionIndex = option.sectionIndex; - if (prevLocale.current !== props.preferredLocale) { - prevLocale.current = props.preferredLocale; - setAllOptions(newOptions); - setSections(newSections); + if (!lodashGet(this.state.sections, `[${sectionIndex}].data[${itemIndex}]`, null)) { return; } - const newFocusedIndex = props.selectedOptions.length; - const prevFocusedOption = _.find(newOptions, (option) => focusedOption && option.keyForList === focusedOption.keyForList); - const prevFocusedOptionIndex = prevFocusedOption ? _.findIndex(newOptions, (option) => focusedOption && option.keyForList === focusedOption.keyForList) : undefined; - - setSections(newSections); - setAllOptions(newOptions); - setFocusedIndex(prevFocusedOptionIndex || (_.isNumber(props.focusedIndex) ? props.focusedIndex : newFocusedIndex)); - // we want to run this effect only when the sections change - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [props.sections, previousSections]); - - useEffect(() => { - // If we just toggled an option on a multi-selection page or cleared the search input, scroll to top - if (props.selectedOptions.length !== prevSelectedOptions.current.length || (!!prevValue.current && !value)) { - prevSelectedOptions.current = props.selectedOptions; - prevValue.current = value; - scrollToIndex(0); - return; - } - - // Otherwise, scroll to the focused index (as long as it's in range) - if (allOptions.length <= focusedIndex) { - return; - } - scrollToIndex(focusedIndex); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [allOptions.length, focusedIndex, props.focusedIndex, props.selectedOptions, value]); - - const updateSearchValue = useCallback( - (searchValue) => { - setValue(searchValue); - setErrorMessage( - searchValue.length > props.maxLength - ? translate('common.error.characterLimitExceedCounter', { - length: searchValue.length, - limit: props.maxLength, - }) - : '', - ); - props.onChangeText(searchValue); - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [props.onChangeText, props.maxLength, translate], - ); - - const debouncedUpdateSearchValue = _.debounce(updateSearchValue, CONST.TIMING.SEARCH_OPTION_LIST_DEBOUNCE_TIME); + this.list.scrollToLocation({sectionIndex, itemIndex, animated}); + } /** - * Calculates all currently visible options based on the sections that are currently being shown - * and the number of items of those sections. + * Completes the follow-up actions after a row is selected * - * @returns {Number} + * @param {Object} option + * @param {Object} ref + * @returns {Promise} */ - const calculateAllVisibleOptionsCount = useCallback(() => { - let count = 0; - - _.forEach(sections, (section) => { - count += lodashGet(section, 'data.length', 0); - }); + selectRow(option, ref) { + return new Promise((resolve) => { + if (this.props.shouldShowTextInput && this.props.shouldPreventDefaultFocusOnSelectRow) { + if (this.relatedTarget && ref === this.relatedTarget) { + this.textInput.focus(); + this.relatedTarget = null; + } + if (this.textInput.isFocused()) { + setSelection(this.textInput, 0, this.state.value.length); + } + } + const selectedOption = this.props.onSelectRow(option); + resolve(selectedOption); - return count; - }, [sections]); + if (!this.props.canSelectMultipleOptions) { + return; + } - /** - * @param {Number} index - */ - const updateFocusedIndex = useCallback((index) => { - setFocusedIndex(index); - }, []); + // Focus the first unselected item from the list (i.e: the best result according to the current search term) + this.setState({ + focusedIndex: this.props.selectedOptions.length, + }); + }); + } /** * Completes the follow-up action after clicking on multiple select button * @param {Object} option */ - const addToSelection = useCallback( - (option) => { - if (props.shouldShowTextInput && props.shouldPreventDefaultFocusOnSelectRow) { - textInputRef.current.focus(); - if (textInputRef.current.isFocused()) { - setSelection(textInputRef.current, 0, value.length); - } + addToSelection(option) { + if (this.props.shouldShowTextInput && this.props.shouldPreventDefaultFocusOnSelectRow) { + this.textInput.focus(); + if (this.textInput.isFocused()) { + setSelection(this.textInput, 0, this.state.value.length); } - props.onAddToSelection(option); - }, - // eslint-disable-next-line react-hooks/exhaustive-deps - [props.onAddToSelection, props.shouldShowTextInput, props.shouldPreventDefaultFocusOnSelectRow, value.length], - ); + } + this.props.onAddToSelection(option); + } /** * Increments a pagination page to show more items */ - const incrementPage = useCallback(() => { - setPaginationPage((prev) => prev + 1); - }, []); - - const shouldShowShowMoreButton = allOptions.length > CONST.MAX_OPTIONS_SELECTOR_PAGE_LENGTH * paginationPage; - const shouldShowFooter = !props.isReadOnly && (props.shouldShowConfirmButton || props.footerContent) && !(props.canSelectMultipleOptions && _.isEmpty(props.selectedOptions)); - const defaultConfirmButtonText = _.isUndefined(props.confirmButtonText) ? translate('common.confirm') : props.confirmButtonText; - const shouldShowDefaultConfirmButton = !props.footerContent && defaultConfirmButtonText; - const safeAreaPaddingBottomStyle = shouldShowFooter ? undefined : props.safeAreaPaddingBottomStyle; - const listContainerStyles = props.listContainerStyles || [themeStyles.flex1]; - const optionHoveredStyle = props.optionHoveredStyle || themeStyles.hoveredComponentBG; - - const textInput = ( - { - if (!props.shouldPreventDefaultFocusOnSelectRow) { - return; - } - relatedTarget.current = e.relatedTarget; - }} - selectTextOnFocus - blurOnSubmit={Boolean(allOptions.length)} - spellCheck={false} - shouldInterceptSwipe={props.shouldTextInputInterceptSwipe} - isLoading={props.isLoadingNewOptions} - iconLeft={props.textIconLeft} - testID="options-selector-input" - /> - ); - const optionsList = ( - { - if (props.selectedOptions.length === 0) { - scrollToIndex(focusedIndex, false); - } + incrementPage() { + this.setState((prev) => ({ + paginationPage: prev.paginationPage + 1, + })); + } + + render() { + const shouldShowShowMoreButton = this.state.allOptions.length > CONST.MAX_OPTIONS_SELECTOR_PAGE_LENGTH * this.state.paginationPage; + const shouldShowFooter = + !this.props.isReadOnly && (this.props.shouldShowConfirmButton || this.props.footerContent) && !(this.props.canSelectMultipleOptions && _.isEmpty(this.props.selectedOptions)); + const defaultConfirmButtonText = _.isUndefined(this.props.confirmButtonText) ? this.props.translate('common.confirm') : this.props.confirmButtonText; + const shouldShowDefaultConfirmButton = !this.props.footerContent && defaultConfirmButtonText; + const safeAreaPaddingBottomStyle = shouldShowFooter ? undefined : this.props.safeAreaPaddingBottomStyle; + const listContainerStyles = this.props.listContainerStyles || [this.props.themeStyles.flex1]; + const optionHoveredStyle = this.props.optionHoveredStyle || this.props.themeStyles.hoveredComponentBG; + + const textInput = ( + (this.textInput = el)} + label={this.props.textInputLabel} + accessibilityLabel={this.props.textInputLabel} + role={CONST.ROLE.PRESENTATION} + onChangeText={this.debouncedUpdateSearchValue} + errorText={this.state.errorMessage} + onSubmitEditing={this.selectFocusedOption} + placeholder={this.props.placeholderText} + maxLength={this.props.maxLength + CONST.ADDITIONAL_ALLOWED_CHARACTERS} + keyboardType={this.props.keyboardType} + onBlur={(e) => { + if (!this.props.shouldPreventDefaultFocusOnSelectRow) { + return; + } + this.relatedTarget = e.relatedTarget; + }} + selectTextOnFocus + blurOnSubmit={Boolean(this.state.allOptions.length)} + spellCheck={false} + shouldInterceptSwipe={this.props.shouldTextInputInterceptSwipe} + isLoading={this.props.isLoadingNewOptions} + iconLeft={this.props.textIconLeft} + testID="options-selector-input" + /> + ); + const optionsList = ( + (this.list = el)} + optionHoveredStyle={optionHoveredStyle} + onSelectRow={this.props.onSelectRow ? this.selectRow : undefined} + sections={this.state.sections} + focusedIndex={this.state.focusedIndex} + disableFocusOptions={this.props.disableFocusOptions} + selectedOptions={this.props.selectedOptions} + canSelectMultipleOptions={this.props.canSelectMultipleOptions} + shouldShowMultipleOptionSelectorAsButton={this.props.shouldShowMultipleOptionSelectorAsButton} + multipleOptionSelectorButtonText={this.props.multipleOptionSelectorButtonText} + onAddToSelection={this.addToSelection} + hideSectionHeaders={this.props.hideSectionHeaders} + headerMessage={this.state.errorMessage ? '' : this.props.headerMessage} + boldStyle={this.props.boldStyle} + showTitleTooltip={this.props.showTitleTooltip} + isDisabled={this.props.isDisabled} + shouldHaveOptionSeparator={this.props.shouldHaveOptionSeparator} + highlightSelectedOptions={this.props.highlightSelectedOptions} + onLayout={() => { + if (this.props.selectedOptions.length === 0) { + this.scrollToIndex(this.state.focusedIndex, false); + } - if (props.onLayout) { - props.onLayout(); + if (this.props.onLayout) { + this.props.onLayout(); + } + }} + contentContainerStyles={[safeAreaPaddingBottomStyle, ...this.props.contentContainerStyles]} + sectionHeaderStyle={this.props.sectionHeaderStyle} + listContainerStyles={listContainerStyles} + listStyles={this.props.listStyles} + isLoading={!this.props.shouldShowOptions} + showScrollIndicator={this.props.showScrollIndicator} + isRowMultilineSupported={this.props.isRowMultilineSupported} + isLoadingNewOptions={this.props.isLoadingNewOptions} + shouldPreventDefaultFocusOnSelectRow={this.props.shouldPreventDefaultFocusOnSelectRow} + nestedScrollEnabled={this.props.nestedScrollEnabled} + bounces={!this.props.shouldTextInputAppearBelowOptions || !this.props.shouldAllowScrollingChildren} + renderFooterContent={ + shouldShowShowMoreButton && ( + + ) } - }} - contentContainerStyles={[safeAreaPaddingBottomStyle, ...props.contentContainerStyles]} - sectionHeaderStyle={props.sectionHeaderStyle} - listContainerStyles={listContainerStyles} - listStyles={props.listStyles} - isLoading={!props.shouldShowOptions} - showScrollIndicator={props.showScrollIndicator} - isRowMultilineSupported={props.isRowMultilineSupported} - isLoadingNewOptions={props.isLoadingNewOptions} - shouldPreventDefaultFocusOnSelectRow={props.shouldPreventDefaultFocusOnSelectRow} - nestedScrollEnabled={props.nestedScrollEnabled} - bounces={!props.shouldTextInputAppearBelowOptions || !props.shouldAllowScrollingChildren} - renderFooterContent={() => - shouldShowShowMoreButton && ( - - ) - } - /> - ); - - const optionsAndInputsBelowThem = ( - <> - {optionsList} - - {props.children} - {props.shouldShowTextInput && textInput} - - - ); - - return ( - {} : updateFocusedIndex} - shouldResetIndexOnEndReached={false} - > - - {/* - * The OptionsList component uses a SectionList which uses a VirtualizedList internally. - * VirtualizedList cannot be directly nested within ScrollViews of the same orientation. - * To work around this, we wrap the OptionsList component with a horizontal ScrollView. - */} - {props.shouldTextInputAppearBelowOptions && props.shouldAllowScrollingChildren && ( - - - {optionsAndInputsBelowThem} + /> + ); + + const optionsAndInputsBelowThem = ( + <> + + {optionsList} + + + {this.props.children} + {this.props.shouldShowTextInput && textInput} + + + ); + + return ( + {} : this.updateFocusedIndex} + shouldResetIndexOnEndReached={false} + > + + {/* + * The OptionsList component uses a SectionList which uses a VirtualizedList internally. + * VirtualizedList cannot be directly nested within ScrollViews of the same orientation. + * To work around this, we wrap the OptionsList component with a horizontal ScrollView. + */} + {this.props.shouldTextInputAppearBelowOptions && this.props.shouldAllowScrollingChildren && ( + + + {optionsAndInputsBelowThem} + - + )} + + {this.props.shouldTextInputAppearBelowOptions && !this.props.shouldAllowScrollingChildren && optionsAndInputsBelowThem} + + {!this.props.shouldTextInputAppearBelowOptions && ( + <> + + {this.props.children} + {this.props.shouldShowTextInput && textInput} + {Boolean(this.props.textInputAlert) && ( + + )} + + {optionsList} + + )} + + {this.props.shouldShowReferralCTA && ( + + + )} - {props.shouldTextInputAppearBelowOptions && !props.shouldAllowScrollingChildren && optionsAndInputsBelowThem} - - {!props.shouldTextInputAppearBelowOptions && ( - <> - - {props.children} - {props.shouldShowTextInput && textInput} - {Boolean(props.textInputAlert) && ( - - )} - - {optionsList} - + {shouldShowFooter && ( + + {shouldShowDefaultConfirmButton && ( +

      ^UEQLRrhOK&h3#Zuf+Mep9P>1okDN-X7blO zn~VRAWi&`%%(l|bky>H47nkH;IsA^hG_s}NEOWodb0lkGrLPk_m7*|P{y4qPDhk(| zE6^EE3@mAbr{bF)qN@?YI{j@g9F@4Wz~QRBZ^b~Ot)c1;LVL3FM{_WbkMw)k4~ZtBscg z!U~kL4~rrHiE*99lQ%6l1lfw8c10q#<>9cmY4DhJg<~cZMJRDt{5+3pjrKC4?9W>c z&b>CY9&ZUIe|kA#!ho`GIdMajFX2KxL~j{6Hide?Hi9@FXN#LouzH>baRog)gIIWP z-wO{dM`>w;iTMwu56HWyjb=#o^JWhvh4%#o2^C>@?RVEMYUj_3m$=tZ+79KmjKY3} zj+b!RjmJLa@cAbViz`4$*f9XqEiRM+H)=BUINy2NkoETIWvZ2Kr@2oI!#a=8zkJNO z5vcV3`iwXld7<8ow>{1|SBHLiK>hB@f0ki-lHoFK$J^wV!cRnFtY$@s0vuvb3NzIu zC(bluLiBJ6KxnNnY}9cY-B~Bmd(Sj?Pm11Rc&C{4l)}Ri_EJtR1)7FaNvVzt{}(}) zi|H~%$epZGVOVK-`s3BDvRRyvLKTR99ClqKGD58C-Y5To<)Sz~KXeMX`mqKW^*c4cyfGpY-OKr4u!-uD6HBrOP~uaijsstJmLD zoNW7=sX+m3%5z@G=6DbB{BY$BL!_zJ3q}Iq8s)J`J{;WCZnDdSTz4qOCYhAN+LzC? zHvZ_}V;bdSY;F5SA;$gm`~kNWQ=StwqWy0Pv}s#C8VQsZoY2DxhL;!ssk*G+&c7-@ z0nb!_yFB|^79f1Ko8`TBKN~AJ^D&GCpfccDrBrA0Uo&qvD&V3><@|{oxxZXT&-oZl?qedI{eA*$1P_&1;yd?-T!Qq$Ov1+qUs{3DUN!s_j|aPz|^ zk^0mi`-a#wQ${gV)3K|3h^qBd-@++FyaV_5kzf)cLr&@bCoT>@ysA5Ov92qP;$m|3 zG6?l}oZ3mN!k-t&-(aQ25_^_48uowA%zZ=t8HIt>Z&S_u;;*pa13R!K!*VPybd`Nf z@4TYI&aHvBX1n4q@&g71{CueF2f?u76=sIu0VVO>pkyunGUnP7^_$p_AC~Tc1Baigjaik7A$%BiJB-m-HOlW zS6Qjy`d&R%cYLAzGAFcxZEmoC2i=BTHb^YSE>1R{qY?0STprRs1VdX@JOU?Z(WXBU~It|4i?a8TuhZF~_zK zpYYo}x)ZZ;1e{@n3>p1L<(Ed{Z*&_pK5*@9!6*yB7$Hl_17@(_X}#Kz+Qpfs^#Z;m(*tZu$ODlV;ofy36_LChFJ5n-;tZt%^^`_NAiA)>8>&!?IC?1 zK?!JXZf#`6m&ia6-SXd0YBENo;jrtbFVH|9KGv16=l4a{=M{V;aOzQMVe)|I5|ivrgKbU2IU;d z%Gg1|Hhctxiq_?Uy$n>7VyHkx5h^2V62v_?y zsQWyvyeT{qINgL(rRQn&FaX}6DUY;a?UR9q+8`q%-nBTaTHVJip2s1#Ir@o+WsAWz z2}%oHdxC|CQcEQjjC5@n(YIO%L_}I?d8%#hIwYw#3rS)g(%+wt1RFCq zRlEf>hn2>(6Dup&qi^Qxnb8I$cJAwQ!LJ%=p|bx^6L`#{3NF_}-(hhkQ!&Fs z@@!&c2eb`q?BZmf$p(NM#_LEjk|skU_Zj4zkDX8Hl{)_YRc^;!B9FLT&ueaRr{npz z^_<(S#8OG&(s-KPGhsO(Zzw!otbQ_h(?!hGtjykZ|8Akybgu*Nx*GQSn_bLPFMT|} z_|vs1ljFX(@8WpV72n6Oi#+0NNT<Sy3*nxm<}Mr%-MyMdEp@ByDvLP z%0AIT=8<6R5no-(Xtc>)zlI3w*u<$J{rd%xBPgb(`LFs~6Wkx;sU~~4=sKPaqV7Gg zS+2+vbbs=E!p>Attj;&R9*a%rsd#hw7sdqCW5-*(b7pWcFr7yUNW0B9Foi=3Mg`n< z>?t)oLCC!$iZ!9Iuw0jl!{mx~-|5k3Og;hDosaF``TSr)3ISZgEbcpXH4v<^!YEk$ zrv6&1K+#de48=I6Jln4w+u^aIZoBvA^$N-}9-H*s*ZtDh7Bi7j65cF^Kpzcr*N(!Cw&g zxZx@uxAY}B0J83{4U!nK9>S>_)*%U#@l=#4h25uRz3SZ6*Q6AQSyWoS+HX0a_|lyQ zIVcF4j3ZDKP(6(#9#tT^7N4`$BUFD^hIP5!#v~@UsgPG@d-)JVbNzg}h3*bV@(f`U zoS*}erT;#zXyat+B7@2Wz?yv?v2Q zJFQIIEPuyDFja?FQ^-R&^#asLYm@}xGv+B-`wh3<_Nj^ik7q1rc1ZKlPkF4JPY=h9 zMx*nG6ocPUzIRMo<^1ONra{_K@t(zzUOvRhGO>!MIlS^9yX!eXIGHr7+`<|Kim(7t zEzG{)t@3xToBgtNC1opE4!`ejcsQRF_1Q3Jo{ryZgA11Ly%{R~<(Bk{t2>7;&C|*1 zZnpaLqNRzv-S9VJMaxaTt^$cg)Gd2MiF#-k-TCArAAj@OD0xxXBTnuTJTZUTE51Ah zr21VAJL2*P4WR^UzW&%iK7v@oq z!ItqM%AGTTOYu|d9!nMor5o!8PZsZPo zH?|yj(9^Gj``=w=HlgW>-(^Oi}xoXPkhVsO&+eZ9^xyR#-gCKZ+J|VcP0;h z2yYbsiz|dE9dlR6J_+v~Y8ZLWDdt@zH;t*%*WQe4yv6)%>+M(%KyDY9$8=98>_H8J ze}<LD6lk88wMbNcQ< zB_TlgMpKBM2ZPz?)5|8i*b}_p+v(ENP9|QU@)^@a+td~~f7qnqmpF}$#9Ub0L?y1D zc6!0G>#C6W-?f>^5T!}gY~J>-|1?dO-id5pZK9-)_h(f$K;c&d3w^iOug15vUu~+~ zm%nn7MuaxB0CN>%u3SvNZZpj+6TN9#+ez6v`v0ZfW2viE$EPKF#q6lX9s+AR8$7Ri zbmaw=CxW-CneVu%*yqT48%SNX?pAs?^a5^}iLbkZQm)}kx9W{2I==KB6d_q;#JWy< z^&A>QYp~tOp@B!nC&I)F2F_>)`US=4?ezqpd9U^u7=8hn7@7*vz<`i6y z66AV$M93>bVZr+lcOYc7>wE)Tmzy^46F785!cR1#eT53yn877|$84tNqxnqWR zB>LEg!N;!MK~^@T#-t8Q_-#VRVeFD7%69bhGM6z-=f-wgBEFl-o96jds)Ue-q6N7d zH0O1!n0Q@1pPK~S79e~o(2eA8rSc5}(F`9|zG!MRy{nX3>C%;d@MkXJyN=|zc+10) zPBT|JtuJ)a3;hyuvr@Ib#H+Isvhc-HOunel^|$%RFx2dDOUEY9>f*Y$(Z6FV0=?Vp z=K`{EX%&u2s(dM093v-mu+J6GVGb%WX0 z1t*_q-Aa{i#Fd6Tl)8eXi_oM6a*FF0D2pU~m$(rG%<_qaB!v9H(!SptnDbnzXR_3yCN6>cFgAXD_O8up+X@quscP zDmbMBlBcyl+~VODeHAKJlt{TX4I~;7YCJgj%5W#bed_O8i~D#Y39>ke5PFG1F{<)D zO%~?)1xGYTq%zuE@K>2qTLIsv5eU%cJF+&ggJ=QQ-Og6z0g&Mkp=$u(4SoW8IXE`B z_-uU*8VEed*3}1W^;`RO*h;t>U-}k|>2s|vMj=m{vrqHn`OsT)(lFd*zQu#gdM$$x z)`{&SczQ-@C>Ln2?y~=E`DtN`mPudVWfUr=oL9Caux{~C;^?Zs)^La!0s03OMc@ME z^W4rj0rNr)*@)HHTI>Y+I%j_tK^fTgmcs=&N9nPb9RQ_x9DWap{MAlM$_+7NhfN7Q zXnwwk$Uz8e8+oA%u*<1YhSvAxc>MM>Tq`clpURhn((bj)BNd1zuh=! z4-#$yarsVq3JS-KGxLV*W=>$d|5hr%AULd(%}46UF! zM_dW>A@HPTgM57c%Y0^uf6%v-Fj|Rf75imrsL(>2sOES4(#_d|y#CDWz|mFh&kLTv z#cJQxJzu{hMEUb){cv#Q?0p+eUeXm;-{Bs$_dR|Q7CLetB_~3wqHSGm&bd1-N3pT0 z1d&s#EQYSf{Pw>n{ioFPDJv#^|@w_<&>(*iSRFd?N zj3~RcVb8zYMykfKfJ!!)FLqp8!AS*XJ>~P930@P7q<^7SP1JC0|8Hmdxi|8O#~dPD z=~{9vv|1S4eqa~|%xVj_d89Uso54mn*!*(huo9c(mGHiT>wefO^LoQGdyyaoDQngy*Pc{jB^>p+T#In3|(rSGm9kBlNIypL10t3-tf?fvhlJM?Vygz2Rn{r z_R$iTL)3r~LAxKA^XqB$!5X9G4XW7qXuEAa^(xm_i$wxCGe}2hB3Xj_24?3djwp;J zDEo5to(F}&csF4Rojkul(WvaUIuFjM%Lc(YWlL>^S;4!2=MP-N22KIzRaKW+SfgAy zil2z2$T=Et6oBNMm8TDHzoZyM`R=fc!e5Z(A2P6{(ID^vSaJcc)o-LU-e*L8Pdxu%QmC&3hhNhWamz-_8!O!H zxu)l4Kazb@ORYWsF=mpV`q--%2=@)odVw#&`Hyfn1Bw%T( zocrySQS?mAmqzCYSyu@-9o;mucc5_vVXh`v5rV+aox<|7jQt;&C!od!mdI>U_iZR8 z|Mn4rRjH-j7}NiyQD@E{emupSg1689gk&^E-vx9z%y3!!sIv+^Fcv-H z+!v)qk(R7J_uj|03S;o3gX^UrA`#giqGY!m4@kPBC(82y>*bl+Erd+GVcpyDzivqK zhxkR&ZPQVN*x`3&UQMQ?#7^OinUU1^fB`&>tQXmNvygoqXjJQPdTc)u;L$tyP+`=0 zcn-L;A((s`y|7`i?!78VDqIVALBY@Y+I;CrhAm%UJ=Tv}K!Is&_>NQ&ST1fVnnz7~ zn=L`3vb2;`7*ZjE`J-aLF#^u?IuZ}2X`nUyy@Kf@wVW()ERf+`?y$io0e5;ztAw#& zfJRUusZbG*#U?+Pg>~g%YCh|JY1qM26-7jxyJ%dMT!xdKX3AFxugbVdXJFGMEpxiv zP*I*cT|4i~Hx)HTv8}U(XVee$~;P46#mmJN(14a$b@u@T?p| z^u~auXPdDMTP6K85ub<-WP~1JBvzCSBfLy3230o5w@kn;wA| zb>GhIq-=gL>I7r{Kwt($833J+GOzwP?$#X%NS)563t-Z_mj+?Eb-!-$l5;jQymgN} z1oKC%8B+61_kBJiP&z@p2?13{w41~Z687MxU^S*69I!QHL;|U{w?z7izYsC*uo`VC zVpRv8J~%KOfQ-8Lc2r2Hb!X!5BQSkpOkW@Z@gpK~Rin<0g+sce*TedZ`ec=0fk$uZ z&DprlLQ)Jr5q8EsPEIP!{z3m_E-=q2t>#9g&V+-gaJu^#ifxY5`L&^ApoixZS5h}P zXX+q?7y`D&Hc_$58vJ znmb1nmZhYX)hpZ!%wBu0cR6I2r&_1Q72M31D0ETP%-{KKWYtZJyti_(wGYGZTsA0~ ze&P&kELLFlqRYe-26ZORl{^lJA&07S#m-cFFkxuqRzFE!IVbU--CNrl8fBu6BI|L} z<%&~Zmt4I)`#6Q~Rq^m&=^b}E3}&%@drkY7oVYe|iG;C~4uH05P4eKIlW7%A&^7-b z8YPIoV~?4Ls)mDuX_CzvKS)y2A{{ZE(3NfB1}GE#;6VUF@Kz=f7>UAMmo_?~)V}gk zct3!49wwkUuiTwOB?(4;5zN0kgT1$H6MgPyY1|IbnZ{DcM~#-!@Q1T73&k3phdg|P zPKP?ON}|)}%s8^H700?f>kZF-mI~Pjf-0k_527+VkfeiP*McLJB99qa7UDEyZa9(u zBlO&RYqwj)Lm+zJqZGU}0i*h>g29iJb%dJ`zsUGNGrwV(Ao7>ymHNbF0*~))4{4cd zup>`y8b`KrVLQ{IY63=J*`x-TFG?d+;{DHq+bK8b)(VlYK~i!6&>He{27UUBqg_yd zId(nO3*SRI1j2ujYaXEJ5Y>B&Y7qKGRkVgU0D6w9^db7m8*}}vwco-P`?eK}MJsV> z4z@UxNU1ibm`c!T)_>fF`aS(+R>Ut=Qq8$cN}2TLqQpU)5G{;N{Z6f1G3 zY@*1Y+&5qF4{quSM`8wSd3nzY)L$mSIIV_nwe1{M$>&o32O&xU~K`N@~JLEKp*_x zfb3KEQV$CY8NDtZ1#hv$v9C#l_(DiZA2ImAu&yAzdfibbU0u{_>J9*MEISe<;51@) zg4}`PvE^5!lxYzLgbtX*xPYckGY{!ojpG`Bq2C?5ACWO&hboB%=tZ2f&QSm+zXS43 z?QfM&uhhE6)oXs97_S0=3b~njRF0QliX_Gc9o+dp`C|lBO~AV1moo;TiGIH|e(6i3 zia7JZQ*S^E-4Ag6_9j0b&2ystt&h`r(fwL*od|fh3$oP3O`9v;WYet<{YzPZ7%t;) z_meOkwGq3~jJU*l)u%icR#Hoyrn*%JM5G1>DleUGxUSlsyYO*Chgjl1m^ zwLIuq`Ah3}Z-pE}Cwdn=A6@#ZQRJHX9{=aNj`i=n5)Wa-8Io9G&lyW=6n>*etUC9D zfeIn_W0pb0pD#G6w+}FINo#ZM!3jX*YgcA#p6Wpra(wO=&5E`F#Bqng3eAk(Z%Q=& zSsrTN7?bJqZm47408?-{OhPZkrlxJ7_sj@9*3U2zQ04Z64ES(t#Bdt)lUOP)`qwAQ zRC3}VAGls`Iw=t8!Ln;D&ZJ&tnL~Xqv-o=?Bdo0|9Etkmjvvi6cV}?w=8_S+dN2=V zKFg>)2zc788z*d`BL=8oYL%@(GI9$Xa~WW|NJEAi*MKF}$K>Cz?zB?`GII1)tO>zx zV_q6f(EV1=j<8wO1B>>-XKWA&<-E7FN+?NcEGM!sP%kRr(R)v@1{Bbi)|uLZbZkDI zW>c7)+RJCGsg|AvLHeFbM^azJ>bC7&WTIe_eVnKbuER-|DKChrf|!JV`QVz!@hyJEU&(_sMkr7v~<}EUVYYFC;gR}0hr?BAL z52|y4bj^Y)0OkrDuewYeA$x}#z4&7vmx%%+hF_)$?~z(V*9<%^q3 z*Gej1zGnG*+dC63(!a-gfyvU9GyUZ6j9U+>UIpidUQExCdnXm~WWKs{?NPz=1DsZ@ zY{BTMwy$mPE12}1Ws|e^*5Q(;hz}>MZ@CcVN z)+tjv$-q>uOE2Ges#})x<-kX!V!iv%iV81APFqlz)ab&Nt_tahba-EV%D}huHb|>O zEQPMoe_5-xP`<$Up=~Ae0oo$ZsPchGfvw7pt`SEqD%k+c-2WHHKq)kYR!qUdSATcql@x({p(&N3V+z&c^j@^HT+ z<>IH~ehSe?Vqv02IBF(vc{Ma0fxhBA5&5$tPww2OwVtiym2UmMsjtfQGP0% zleEu})xUNKG&+D>cPv%|C_brQj{32L=><+Y83@50v4Yjr@}58UQrhAc8dVsTZ0-V` z1h&qH8a{}1B4PO=Vx^&QxyTL#o*+n~h!RsE?3CSqP^vcc+GQqEi6xNJKICI;n(nv! zh0XA%{tNY@A1JsxRFAwj9iAPQVhK;hnr#-wa-kPdmkT5gZuwq$rb{m*qIHh<%EsG& zZr_U8&y1)qJ8fxHT)xQ-C!ghzkZ?tM=ge|TKqBEGU{E{A1bB9bnQO+X`K zpNFy8Nc};Ss(oQ2Hpx9{{x7cM<$!(X|5>=XJ_H$tA-VA*W&h_Ea{kSBQMwf|t^N1l zicka6gC!1}He^FQBC+P>x-&qi3A#vxkjM!SQyz8G<@1n^b;=Y(3=)NV-;w&y!i@Oq z(Cre4fSIkvIN3a*YH|^X(KKiYv`;Qh?5 zPDtLYZ3K^geVB`gph+gZz*RTH(g?^(-YHJkXRL|G3<1anM$-ySO7W zgWP9AlAaUd9lbCFmfhLv6--D7gv0BFjc)n2Lw3h9Jq(fW*o8H#T8ePb8hHxK2GC|S z@}2LVVVi+N_Iy_+DGlOH(UiWkHE2FR@E3Kkl$Gz1n7?sn!NkU>rjGN$1#%h-YA4={ zig;g}s8IZxZ@y2xhmZJbXwLXk#Wi?{o#(yOf8-`P;dh;N7Ilf|Jn#SN()7*fXm~z} zSclQm=j8c`Wl9*_nKK9N70Dv<|I#-pX!{c-D%Yl|gj@rIVrg4^c=^g6oiz=UKQvXV zYQ3?`d;m<1Z|?eRBezvBpT^gB9BpSCNeg?mKwZNJebh=&N5=+vVV%a z^!tu2T#H$ne59xB2W^wKD|kl}xx(Vp%dw|nYyFJ0M?nuS`Fm(KI7KUUrRP$2NvN#; z2rIstG=-&xvo`VJB#pfy92Mw5gbU913Ezu?>h)hu?&T46e=VaOo{h>}fE#JRRRT7q z@tT?B9V+59B8#=J77lS8NziQm{K&qYs6Y)jIdYh9!{(RLR8p}a?_?1irq*qC&QE%; zLiAqwAUFB28u!lR?kws~&`5Wb`S&d`0lYr44;_v=UH62r5d~~!)?DF@!l2Knmu)Mk zJ1SD2L7U)Y-zJEwE+~xz_u7v4UF<39o8SJu_tkdv^3&GxC>_%3HV@&&T^rWyMboyFumi};}}JIx&NN3LMR&6x)}wlpd}+2BzX zrMrcAT-g>6JYVa_z3Nxf(O?`gaYW0niN)3nRKbX|y-@)+TPjwVwBY@@lVQI1gsgZ) z4|$67Y-bP#iMv;Yl+qhLbA1Sl7{Iu`6A;*SIgeJi7T9hg^UKvPKv7@zqa5dI41%YR zm<4#pm4LRmaeYw?pYjbtgT&IUu7NcWFzt57Y(wqnQ7Sku?qOF2X(tv~U@tOs{k{0N zXQj*)^TuWI=?MV;jh1iK_0x;$$lXFI3u+UBi$VPEIsb$w5nA`=&&PXup@3pjQjxQ< zrS;w&A!k*=j_ItIfe!Uc#=j>Rs|_D0y}&v^l-kYV+NFd$TJ!u3%7)wKrB zE~X-@lh%fRm}WRXano41U$~mr8Nt(kVrhT779>pZG}Zs7U;2-G{N1elv(?08hk-Z0 znRahy=vY5N?WYlV_6(d@Ql-Ek_nu+DO~{5t$Z3joC4cNpOWPiRwwlEH<8^%C9WSjV_Xt*O7Z210a}># zk|;*{ExhCL4-#1OPOv`d%xcSiMgFZHmW1;oBSt{|-L6@bJL1UA+tYy zeWbY7df{>E1`T&7ir^#p5WXQr8TyMY;~ac=> zbgEYu(+KF*Efft9S_Hk%_Z{%)#BhZbtXU6w2so*P!3d!_nGQ2_&@F7%B|>=<%?Jpo zcf@{Xu{Ea5i>9SuYq&hV%N$XRWPLDWbh{X4h-qel-J)Jcd)*_bpIV7*tZswlxGQyv z%Ab<7Z^|v$Wqf&)LSpanjGHD%Mwc6KS!<5+c&E2lC%Fhe#+|^rkut($1*Am0#a%;9 z$UL@pGA1mh*4-WbQyRxBCbu%)r)m^rUw*D(GtQxw{#2G|-#*-}Joo2)r;?IB;yb@d zWx zc*NGRs{6J2tm+oU+^?wgUry0+mU25!^;ol5Td)Xe|BvgNRd2dZz~MS4*#HtEVt;U4 zAn5aS*(}=0|K25plHok!+{#$1VO)w&dn zBr@fo>e+5o2L)V|?Ax}w|A_dSh!q83kdg3{2AG9_v&g|Tr~h0&8E69kJFSan;i!cJ z1cG`htrhNfBK(SX*E?|74>ms}m%@a*eFg|Cx_p&@Zs-`t!irEO_AqdH0dfAQn|nxZ zSCna9G9mW^?Jb`5m<0k#lj&@-FXgZ!DISq?P6N~Q<-{WnBPjqGHm=M>_+kYFP`gh` z?4zXg?G~le;?3}o(*qPy7u{#fjDXbW7ONlUuGo-{#r1gO*&Vh`pT`UjFm_vsHUsFK3u@5uISo3rFiFgGLXp z)Kn#$nPPWn2Bm8zyzhGOw~s06y#tdLxqledH*Lw;FAD=lrs?=iINrTxOy=&T3L&tQ z6jJC;F@CkRxG-=K>-fB|TM^m>4n)hQhebiw?^f>Sn|-p}d}DSoq+BO>=1s1Sb@=ha z3_RADR)Nz~dCfO&mR^Ng_;O2hJM7y3cQjWaEJs|Venlzi>}CRo%T|vSF!TdCpKyo| zGA_eshKFrT8;>2Hf;7lzEikf0;U`KMDRxCd(>6XPl!`KrQ!z|!AMfs@n5LY&WhqgQ zP5L)!g9xTJejGa^sh^E@~ld~B5;OTYT`TpLMQJ~O@07jZ=3gKK{68W?dpgr5AP%d7hDTueC(mTfQ zLq^|ffdd|QaRBKs%}A(3N!0k4l95bZ&}zVFo1#tm`0o>7UnL10XdvkMNw0PvMOZ2f ziDEjic@Mh2MO)<^Ecd;->Y9-|O~;IbiUCTxgB0reb*XQ8} z2dE_94_RNYm^NJ%+I}pUI76F^0y!>Hakb}{3=`6=QmM=Mv8VkkKKX5RG(PUGJ99xu zaMM4ll3x3Fh)9S&e}?w>X2tR1$`T)T2wAQGn6|o@Pw8_~i=u5a6}*P&Q+hZbsWn3?9yub)XHk)b;KDb*GB?BDT56AfAD6ZM7NTvNVAM6 z&GG(Ao5E`!J9B~aoek+N$b{m-=3lneb;URN`#%TC|G|3_kF~oTpLCd&C^*$9Xl!lc zdmb6j)cv&(^f0d@(jgZo5p{3#Sqk|N0b5QKrp-ifUFeOiIK`k@YF<3zI+d6QLG{~? zWZmjRq*M2^F5CS}LT`O-BO>jzKV=-(L7u=M+26c1K!P$q;JPif1#$FDSdej8*axp% zPY}+uM-ZMF?bbWeM(mw;h(i3rjyra5A%z6ll6{cj%>fO>digK?H+Gn$E6I;U1QWUK z!Zlzq& z3e4uWxznCA7W5!Rg@s&pE1oS5AKuRr>tzrxBRXJtVFew~F=qZx=9zzR@DNb?Y;ck7 z7*32*x+N1l_*~)fe8vcgGHM&py^>x^nQ)b>grnKG|2|zZbU~5XQiAogo5I z){<%@VFbHPi%4GtIJdKhIY;_`%2SY)b>QL8-PE^*q=;Ym(lU<3U`Q%#Vqh58!RLlf zsW2+I#B=-wW+@t}1@1E`^=s#eQMz}T|A^Cx-la>|F{)cG>_2z?qWK=$~6g=;2B^Usn?k&tGq@tF zc1enchq!|zV7CJ|C>oX`WMns~i-+WI2;?YJSoV~6;3(?#iK9R;rU-X@cy>RDrE{_o zvu!>v2cOuvTr;;OIGEM&=QcRS^1g<{$O)*Z?;t6AzDQuwd)1zQ(tE~!#c!}xc-?!Z zs1g;RVd$^ezj&B%9nMj!*S(mbF;gUv>?yvP`u&M8CUiWG^QLg|@8y1D+dn5gvstjC z@vk}N#dB8r_(%CnJ+B{3dCLZ;traeY&ieo9^qvXDR7E$XB%dKg|C{u-i+L2VBrN)n zZ0L68a;|Y5{X6h}B~D!1>_^*pgC$>nfjq9f_exF9j{!TQ`k7Tl!Ll=_C9+;vBK|~% zZ}v+Y$P)3rTi3R_UVrSETOl^3==jY?z=n2z;~FtyflvXnf!n+ey=Rz+_a!JpD4)nx zR3JRxr_GO@ty#gAadB=6-$&n|W%GXkU2nJ#txfQB{S{ zK`65zW|b*9^l*+ArOGqpFqbo`^L@}FHq1e?1a4!3Lv!bAa{i(WK}j2A`uWX>PuvtL zKjxi`6g)A&q4x9Z7G_a8n|Pby^Y4~88%c0#&jl$By5`gID({1l!Z3-@@{p9d1R=vh z-2ulmdOv#+R|r>}2GKT@qA_y)ca=`Y_gac~^Ew?r*W87L7eP@YB*K_R6-0=7L=KL; zrQhtY`}xyECEO;|wX-RVN6mjFS0{EtttrL762zv#jpxZv>iRwaIa{{d&Aru$VAxB; zciutZV2eQYOM?aQnr@esP~tJkDtho?P)JsSUjqLbH>@jne;#TH(>*M-{B*$ zA?1aP#_oHF&izCB4{&Eo-S;6g;i@Sr<$x{yFeG~N(^P_waO`QiYMj|C=5t!l%VntsJZ_4ZB4 z=trLp@|b55$Gs*G>O52XQ?v8xoWbd3TNoGdsu+&#l^dks(4|y{h!EOqjBW5G)5NX!z~Cg052?v6E`xAW6Kkt zA`lJjkfj&T1jh~mexk<{*GDC~H(vhyFp$h^zdrNz_O;8phN1JvALPIp|Ee6wx%Nal ze;rS)=}^Rpz-&zkb`Fgz1aY(Ib*O&^f&7klw;T|A&ym&RPTEx70f?DFM<(l$j;py> z_oP=mbL+X8uSkq5j{pyZ0Y(UB2z@+=b>+p~q|9 zk0|Uyvv*4%6amyj*Wh|=VXs&Lk^Sy(;XdHScBCx*;tRR>|7bezaH{{XkCUvdL{>>e zvLnjMNyx}d65^CHQ_9ZzW|tANvXZ@{B-=4l6dBpFNA@}#ob&xWAHU~${_DExqKo_7 zpL@LDuX~D^CjRoq0AO{`4knbGX2X;8F7Nji1T*yHHXtXLk35}n`&)8ECg~5td}Do% zAi>%rRQC7{#qs#vaCS|bQu4V9u;iQn3ITnL#gun5AwWjBQ1-+X%)$sn4s7RTY9^1x2Mj!rZ3zP0A+#OHyIw>3d;)(VV zk+}VMn=qla7mvP_BW|u?JTDPmuT#6aP?q@pziIia5aS21{GwQ;KXCMrPDbKIWhJksDd5j9i-y* zAFTxuskL}!PQ~r7CKLnXMkG4i?9j${Uw3F_32beq#cu(d78ng;0iNb*R~q*N&q>rY z-FbA??j(Q?F_^1w$kJA9e~8YQq1B3yH@##fve${{v47CjjNATnaRU1@Hl+=T+Vg`V zCRR{t`91R3L6gli4;RJvhp(o^#^G8VF@eE#@Ip?-+w5?1ZnOv+xsh6w)CZWrgGV_b zSzHvqi5E^R=B@xmX7uU=<*OBqQ`;EIEr&PALcKMOD)osKMBhVwtiUu3YT0rFF@q$3 z)jiQc!N&jeObUm3CK)Go3LDANvcb*|l0Rz>6{3k}g*|(ZKKZEIQ%;{M`9|gQVVngC zsWqdxbP|3T52{H#GY^kl*5Ci>OLP*g*lJz&U16&)=g7dyUt>872E?&dWgJ4)4~(GG z7k(168m2=V51SP0j2HnQiktKb5q6~9gi<)ZG$->TVEkJV*DtTsmxxu8YMrE+!RP%j z`xt|EeFV&RyYz_(TMyX(fM7z1^>?Z3sL3LvvegtazoGOCGPyrxF$ggz@ayLK zXN}=dV-bJn4GERI+JuCoco#H)u{?FxF%+3m{zJ~!adTbbQQP;yALfkXrBHgI8f*1R zQemwMaugEA7{NuJ$>n{=`MUW3%U-_|7$WnZJWYxt>|TzsS%VTYG+>NAQlcz>Jqfju ziSMNcp(5{dz-yn^4J&tR$5l8;oX1CJg?Bw<3tRCn+f^D($NcgeUq6>B_rc_!Cs7G%pGaKma9%v= z-Jb#lnu*&ApXm3_+ZhjnKzpffx@kbSN<;?!QSwDiw)krsh+Lo+5Ik`)yCuLha!E<9 zM87zy>`wv5ufR7~3P@_Vb6xr5^GBm{e(TE`dL2Ak%aot>4Y4(1HQh?+=xyZE@h<$v zEzceGWkEfa@eB1{af$3gVGuDcZ6LnbafWC}WFfkx1Vkt`1TVPgHskL4nH3F5NO{bh zJ|~iE^PL%r3ANI?5mu}L5- zdMm@Ddohe(1RNy~gKBXqq7iYO>MVw>W647NZI&wdCe9Ju6VB;Sm_Ghl_>~Tc8jgK> zq5<#bij}QH>F!^!XL=#_BuGt^FbK=$&JKF!! z*b){B>Xwi6M6fJ=4r@#9J1$T~rpUir0)KnnylC8UwyP+e%-}yFHM6j-fR8ItB%)*U z^vRg8gh`$(TcMCulYNZwBxX|b`hO>N^A0EHX4gC|@2yM|yS9H?&qOC!iG zXr0(}-a(+14E}3wSGwxivaiG>RPb3xNgM9_k&C;S7k1n!Q7?pvP%p&SF7}|_sTIHW zcp6tKeJ4(Ui?i^2Lg-3Y?*ktOG`SC{Y{ZTLb{68=9Z)g?4P~6m-9`x<@4l{y-mtuz zHkPj5ysM+Qr!$T2kwxAXz@!!#n^@xHK{R7ME8x4e=x`_nb>q5n4^$UEh_ln z5(9o@x$=7Fo$mtqud1~BI-&w6%+CGD7hA1XF<1?BHOOpv+5LTirscxDzA_>MPi|Aj zx6cVlVLE3~l4J)?XuzRtO z3;yEQ9e=x-`y-rAwA9P79MNA7MTI4Sx$xZ8?pWCp;!NzNMJL`VsgWGtAa=S|#||d= zf3_;7ZO(|FZ*L9wQ}Dk0n(bYn*34C(T6X#?Cy+wf`VrZBNKWrH_$6FyN$yF>+XY=(w`Wq}lrSPC4Ee-8k_8W(V%w1noFcKK87?4L zkSk1qcO0&|8K2AD?ucWfapMa6l0P!Zx~uIq&Y}@V*vVSRopje>EcDs zdU^1CfQ1{i(wc)3bZCw3DyBMQ4vqcE(=WvFp*Z?nY(&VHxs8ldYnP{}@AF4RQtLt|G{n*_vI5sTaAo`YO(I|QgVU}~{X;6xkKD#fcm(W8 zfPR`wlg>>T!z8tpphxw8r4y{svG5`9fkfAawhpS}WeAgNQT+MV5KmM;K78cZ#7XEe z7u7nHf0L3(ozxCRg>&5 zd!A5M%!2_rKJXD(A8u<#v{PEiHhF9$*RS+mrzX+kLH=IX5FXqnCNCi#@Mhw|Tc*s$ z5~=XA6+%T->6tOhcbmvqSux{+rfcU7^)_o;5XbKFydyo2!WC|?a-rad|E$->rZ^aexgDrem!}pDb zG5VQ&kb%;@txOF#4NBeRXSe)s3~F^xath{W*7PXY{337nk#nd-Z3%Jg=Qt@iWab7D zr$Hqb4H{%1q5Ux3UXaz}lzI9a1m4-wS?3|!wKj(jHAw|!DkFRUn6y+Z*k`}7iFPGV z;1)%$pAyz`$N%g68AEGQvRm9$Lbe^| z48v~Pe!wI0JN>zZmtMqU-$VUH{!`E);)M=OVH%b4b3U9ZLRM<$9dkL>De zseTCZZ#}7VQ)k(5CVsSTydXj&{eZefh;sHrY5&!02SZkToVM!spGqBRVr3cGHu}=s z!(aKEuk%=&Xk7b(SgahQYFb*WN9o&uoK?mR(s+~ZLl^Bn-RjGenV0>RPyJ~B?(?0s zCtxI&ZozS<_?yAIk3E|wuSWz@*C%-#nPE9x*+n!zZ1W1H;F`Nl}Xym1qp}Qif1~}E8j0)Bs1%o}IG`f1NNVmF*6>nG?C9t^| z03Feh`Rf*!rm?bycAw0B-*;?8o~~=BMcbya0-RN^+4?4VJnI&c&a+jinCvSs-A zc}a<*-h{MUVd#=967^e)XxvZp0loP!S!2r%_v_X58+WZL%(=(cAZQUf!sLk|2z=$q zC4G*+w7 z;$R;LdMTI;H-yGS$zySa(4}xDQ{)RqpE$HgfX5qY?Psf> zgEq6sk}$x>KQ#*dX9>=S`>WB}5AlF55fAZl1|%FMJW)E$SpNCDrDW){v3))6uP}~Y zDZeN<%(>XW->GAuqPOxa?XPugRZ-d>AhEjHRfV3MQVRt4F}PB&#drv^h;cOI-QmII zGi~MSjskxc+Y>-%5h>M6+6CrO`g?i%ppT@N?RB0!ifMt$Tjl}M=;k}t6_xl_tH$a4 zV)<4Ms8xA zw|hVAv6xBUQn;>ICO0K<{-@gYSyQRr;i=0e8)t6xtZ-z$5_3Cq#P|BM59u18H;nQ6VT{w*7&}EC7M+&#k4HgIaX7c75sMZ zASR6`F}cyAxL@uiy&GL_Os!gYp>-Y^m)%>DXIMm=CLv;OF78M9IuilAL4HJMv-Ro* zD3-*^Gl5Y_o7o>uet}!cqN?HgUlaK$>;{qmo$|NF{KJOi_gL*`VLMJVz~}lBPK5gp zoG{P?J3flY>xZ70gJC>21T4H8dV!+_pSG03?>jyqA#SL%1qpK!I``L#1%K@!<&)jI z#LVuQ$6Ls45cGloVFeK|-biC>R|jyDymc5Ll%uHEg2N@ghfzpM*-W$d#HSOCKl^E& zm|C-j$y@h#Q>OjR%Wy4>4FVU=JdA+0YPJwtbWV!MPLXQ!2d*2ti;?KhqdyNtYK9;! z55*<`n4mkosEEem%maBKP7b^#s$cL-D+JK(O6^qbybp?av&rej@2$W83)uI5b=5$@ zg;IHO{eKZAkr7>K=Vkqnj%<+6T2W^QrTmAPI-FN@EV@lT+(PCR71TAI$q%Bh?zm`;j~ zq(79qwPHt5QS&eT#(6X#Hi^UWzI-#^onjRo2Z$0gAV{Pv{*&xJ`enU5`KrtUeL+vw z8qk)z${>(3PDRLf{XcBofSIdK5=uPQ#F~X ze|C$MP$d|*wr}63OEkXO9;*A2Q#s5Z`I2odmi%47^sS!9&r4@tgyzUivM>6`!wI7IL zch%!?(Ee|`WnUsEj~6^=BZVBQYWuR3y-T6D=I*qHPP3#B8xaeg3oVmw;-1ZVb z&!;w*YMviZG%EDQ`#s;eNE8$>(-=!Ei#mIAMPlI%RhePNi==E{hnq3S9{z}!VNL8J zy1eCaRG5DG_A&oAxgHkUFkg=xj$!guYMCRFWwSJ4b20CzlOuSo0@mNCh0Ac+eL$UB zFKpHmjEUC3$<$c|e}3Z^r)1(b7Ln6C=6YVZ)yB5;RV?i7#nJ0K0};cXDzJVM$4Pbw4A zf{;mm$7o%hkgu)zcO$MU#l@+(UHlR&fG#JZ{^U zH~~yHy801GZ*Lf6l2RxQYFOzmeW(Lh>A(Gz92L2lF6>ple%kjeO7|njGs&KU#(sn8 zbG%57u|tm{EnIA1_~Ox8lquzF?J+d0W3Oc&n=Sbk@A#=wDF|8wMV&R_#CUc?0+hZR zgCcd^zcp||gCsKCBGaA4_$@GA)dTZF>k^zxr`H`xh}KqXWlEa7RpM1 zwd&LCqP+ndH_PQEuAVDm_I;~H*@Qd&1k9~k@V>a`ZU}2NdBrq8;N*=Js`_(dE@lE8 zV0>7QOX5%TRK=|Gq`&%L{oF8j3KzR+l<H8(k zIP5p~)ON%>N_FJzKHwtG_w6IX=r8=ZSjAz+`S?onsQ@|)rBwtBEZ>UwA%~S0b;V=v zu|rX5sO^qAEWbWpi$q>+IWGe2M~*N4rKReV5WfEJZn2ce3pNNe%y}dhwlV7Dylb+K z@PduqExH4Y@i*MUrIcGBdp}L?>DfF2Kf3n$N*L@BvmXToCn4wuuEqFD)*Vn5 zl9gWH;krUZDG5dxsb?&g7o8nR9RLZY%{ExT_CqxEHlJ@cI`6uH-JbLdIf}DM+hja` z{5pIoGU#OwePjXy92bEhcv|3C`Ze1}vr7D=x0#|C+9CkWl{n&N@&Sk^3;6nXl zo2v?89ck}V<8iFuWaRe5xm4+RK#81k?^$$*I^UxC86OCML2EcJe$MUt4leE6G3HOBL zt@b9SA8b3F{N|-9XfWfCxTK%=*8KD5&M)px-G{!}I%m3HkefWRd&2uxnJ0nV>r3Yy zSKa|F-&b+eMki%78S+i?n-n7a7-&-R(tepUK6(53JlW|Jmiy)pgAyKR+vHBCDT)o) zuP&}*Y1{56<=d~0`4X3&ZjGy2u-}QF6P(~lKB64jEdMe!2u$@edYVDb^EKinVMYB* za1T*-`d|E%gLk=FplxlWNxR%m?%031GtB4SZ|_)&M=OoEXMrjT$Iz$N-*Cz&4kEli zqMMG1K6w`Gx7QCWVLgZ>zIQzVKD~uw6bCaB!hky4A3oE;`#k=2 ^XI=bf!&Pp( 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Ⓢ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