From e8f948f68656e68853e5522a8b4df732e05e6e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Thu, 19 Oct 2023 14:24:41 +0200 Subject: [PATCH 001/793] install native-stack --- package-lock.json | 45 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + 2 files changed, 46 insertions(+) diff --git a/package-lock.json b/package-lock.json index 95c25f602e30..75d3e9fe0ed0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,6 +37,7 @@ "@react-native-picker/picker": "^2.4.3", "@react-navigation/material-top-tabs": "^6.6.3", "@react-navigation/native": "6.1.6", + "@react-navigation/native-stack": "^6.9.14", "@react-navigation/stack": "6.3.16", "@react-ng/bounds-observer": "^0.2.1", "@rnmapbox/maps": "^10.0.11", @@ -8961,6 +8962,33 @@ "react-native": "*" } }, + "node_modules/@react-navigation/native-stack": { + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.14.tgz", + "integrity": "sha512-7RiZkvMFN6f0kmANc63B/0m9ttQ2JpDIPWQwPU93FP698s19KTOyu7uxgl7Oi3bvsqHFO5JfiR7B+4h8lh9dxw==", + "dependencies": { + "@react-navigation/elements": "^1.3.19", + "warn-once": "^0.1.0" + }, + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-safe-area-context": ">= 3.0.0", + "react-native-screens": ">= 3.0.0" + } + }, + "node_modules/@react-navigation/native-stack/node_modules/@react-navigation/elements": { + "version": "1.3.19", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.19.tgz", + "integrity": "sha512-7hLvSYKPuDS070pza5gd43WDX7QgfuEmuTWNbCJhKdWlLudYmq3qzxGCBwCfO2dEI6+p8tla5wruaWiGKAbTYw==", + "peerDependencies": { + "@react-navigation/native": "^6.0.0", + "react": "*", + "react-native": "*", + "react-native-safe-area-context": ">= 3.0.0" + } + }, "node_modules/@react-navigation/routers": { "version": "6.1.8", "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.8.tgz", @@ -59320,6 +59348,23 @@ "nanoid": "^3.1.23" } }, + "@react-navigation/native-stack": { + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/@react-navigation/native-stack/-/native-stack-6.9.14.tgz", + "integrity": "sha512-7RiZkvMFN6f0kmANc63B/0m9ttQ2JpDIPWQwPU93FP698s19KTOyu7uxgl7Oi3bvsqHFO5JfiR7B+4h8lh9dxw==", + "requires": { + "@react-navigation/elements": "^1.3.19", + "warn-once": "^0.1.0" + }, + "dependencies": { + "@react-navigation/elements": { + "version": "1.3.19", + "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.19.tgz", + "integrity": "sha512-7hLvSYKPuDS070pza5gd43WDX7QgfuEmuTWNbCJhKdWlLudYmq3qzxGCBwCfO2dEI6+p8tla5wruaWiGKAbTYw==", + "requires": {} + } + } + }, "@react-navigation/routers": { "version": "6.1.8", "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.8.tgz", diff --git a/package.json b/package.json index 1db859827c41..665951328bd1 100644 --- a/package.json +++ b/package.json @@ -82,6 +82,7 @@ "@react-native-picker/picker": "^2.4.3", "@react-navigation/material-top-tabs": "^6.6.3", "@react-navigation/native": "6.1.6", + "@react-navigation/native-stack": "^6.9.14", "@react-navigation/stack": "6.3.16", "@react-ng/bounds-observer": "^0.2.1", "@rnmapbox/maps": "^10.0.11", From b180872b639ceb3e4aa399645c9c85ec87b0b0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Thu, 19 Oct 2023 15:14:37 +0200 Subject: [PATCH 002/793] create PlatformStackNavigator with different impls for web & native --- src/libs/Navigation/AppNavigator/ModalStackNavigators.js | 7 +++++-- .../AppNavigator/Navigators/CentralPaneNavigator.js | 4 ++-- src/libs/Navigation/AppNavigator/Navigators/Overlay.js | 1 + .../AppNavigator/Navigators/RightModalNavigator.js | 4 ++-- src/libs/Navigation/AppNavigator/PublicScreens.js | 4 ++-- .../AppNavigator/createCustomStackNavigator/index.js | 4 ++-- src/libs/Navigation/PlatformStackNavigator/index.native.ts | 7 +++++++ src/libs/Navigation/PlatformStackNavigator/index.ts | 7 +++++++ 8 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 src/libs/Navigation/PlatformStackNavigator/index.native.ts create mode 100644 src/libs/Navigation/PlatformStackNavigator/index.ts diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js index cfc8f815e4fe..2e5950e1b094 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js @@ -1,9 +1,12 @@ import _ from 'underscore'; import React from 'react'; -import {createStackNavigator, CardStyleInterpolators} from '@react-navigation/stack'; +import {CardStyleInterpolators} from '@react-navigation/stack'; +import * as PlatformStackNavigator from '../PlatformStackNavigator'; + import styles from '../../../styles/styles'; import SCREENS from '../../../SCREENS'; +// TODO: migrate options const defaultSubRouteOptions = { cardStyle: styles.navigationScreenCardStyle, headerShown: false, @@ -17,7 +20,7 @@ const defaultSubRouteOptions = { * @returns {Function} */ function createModalStackNavigator(screens) { - const ModalStackNavigator = createStackNavigator(); + const ModalStackNavigator = PlatformStackNavigator.createPlatformStackNavigator(); return () => ( {_.map(screens, (getComponent, name) => ( diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js index 64eadcbe06c3..b5fa76a48b90 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js @@ -1,12 +1,12 @@ import React from 'react'; -import {createStackNavigator} from '@react-navigation/stack'; +import * as PlatformStackNavigator from '../../PlatformStackNavigator'; import SCREENS from '../../../../SCREENS'; import ReportScreenWrapper from '../ReportScreenWrapper'; import getCurrentUrl from '../../currentUrl'; import styles from '../../../../styles/styles'; import FreezeWrapper from '../../FreezeWrapper'; -const Stack = createStackNavigator(); +const Stack = PlatformStackNavigator.createPlatformStackNavigator(); const url = getCurrentUrl(); const openOnAdminRoom = url ? new URL(url).searchParams.get('openOnAdminRoom') : undefined; diff --git a/src/libs/Navigation/AppNavigator/Navigators/Overlay.js b/src/libs/Navigation/AppNavigator/Navigators/Overlay.js index 1b2faff8c5e3..ed3c27aed673 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/Overlay.js +++ b/src/libs/Navigation/AppNavigator/Navigators/Overlay.js @@ -1,5 +1,6 @@ import React from 'react'; import {Animated, View} from 'react-native'; +// TODO: migrate import {useCardAnimation} from '@react-navigation/stack'; import PropTypes from 'prop-types'; diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js index 5f24ec159828..822a1c6ead55 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js @@ -1,6 +1,6 @@ import React from 'react'; import {View} from 'react-native'; -import {createStackNavigator} from '@react-navigation/stack'; +import * as PlatformStackNavigator from '../../PlatformStackNavigator'; import * as ModalStackNavigators from '../ModalStackNavigators'; import RHPScreenOptions from '../RHPScreenOptions'; @@ -10,7 +10,7 @@ import styles from '../../../../styles/styles'; import Overlay from './Overlay'; import NoDropZone from '../../../../components/DragAndDrop/NoDropZone'; -const Stack = createStackNavigator(); +const Stack = PlatformStackNavigator.createPlatformStackNavigator(); const propTypes = { ...withNavigationPropTypes, diff --git a/src/libs/Navigation/AppNavigator/PublicScreens.js b/src/libs/Navigation/AppNavigator/PublicScreens.js index 7b0afb787278..6a2ad51cab6b 100644 --- a/src/libs/Navigation/AppNavigator/PublicScreens.js +++ b/src/libs/Navigation/AppNavigator/PublicScreens.js @@ -1,5 +1,5 @@ import React from 'react'; -import {createStackNavigator} from '@react-navigation/stack'; +import * as PlatformStackNavigator from '../PlatformStackNavigator'; import SignInPage from '../../../pages/signin/SignInPage'; import ValidateLoginPage from '../../../pages/ValidateLoginPage'; import LogInWithShortLivedAuthTokenPage from '../../../pages/LogInWithShortLivedAuthTokenPage'; @@ -10,7 +10,7 @@ import AppleSignInDesktopPage from '../../../pages/signin/AppleSignInDesktopPage import GoogleSignInDesktopPage from '../../../pages/signin/GoogleSignInDesktopPage'; import SAMLSignInPage from '../../../pages/signin/SAMLSignInPage'; -const RootStack = createStackNavigator(); +const RootStack = PlatformStackNavigator.createPlatformStackNavigator(); function PublicScreens() { return ( diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js index 58be3d2af3da..5b9679426a4f 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js @@ -1,7 +1,7 @@ import React, {useRef} from 'react'; import PropTypes from 'prop-types'; import {useNavigationBuilder, createNavigatorFactory} from '@react-navigation/native'; -import {StackView} from '@react-navigation/stack'; +import * as PlatformStackNavigator from '../../PlatformStackNavigator'; import CustomRouter from './CustomRouter'; import useWindowDimensions from '../../../../hooks/useWindowDimensions'; @@ -42,7 +42,7 @@ function ResponsiveStackNavigator(props) { return ( - Date: Thu, 19 Oct 2023 15:22:14 +0200 Subject: [PATCH 003/793] create separate functions --- src/libs/Navigation/AppNavigator/ModalStackNavigators.js | 4 ++-- .../AppNavigator/Navigators/CentralPaneNavigator.js | 4 ++-- .../AppNavigator/Navigators/RightModalNavigator.js | 4 ++-- src/libs/Navigation/AppNavigator/PublicScreens.js | 4 ++-- .../AppNavigator/createCustomStackNavigator/index.js | 4 ++-- .../Navigation/PlatformStackNavigation/StackView.native.ts | 3 +++ src/libs/Navigation/PlatformStackNavigation/StackView.ts | 3 +++ .../createPlatformStackNavigator.native.ts | 7 +++++++ .../createPlatformStackNavigator.ts | 7 +++++++ src/libs/Navigation/PlatformStackNavigator/index.native.ts | 7 ------- src/libs/Navigation/PlatformStackNavigator/index.ts | 7 ------- 11 files changed, 30 insertions(+), 24 deletions(-) create mode 100644 src/libs/Navigation/PlatformStackNavigation/StackView.native.ts create mode 100644 src/libs/Navigation/PlatformStackNavigation/StackView.ts create mode 100644 src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator.native.ts create mode 100644 src/libs/Navigation/PlatformStackNavigation/createPlatformStackNavigator.ts delete mode 100644 src/libs/Navigation/PlatformStackNavigator/index.native.ts delete mode 100644 src/libs/Navigation/PlatformStackNavigator/index.ts diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js index 2e5950e1b094..985aacc9da96 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js @@ -1,7 +1,7 @@ import _ from 'underscore'; import React from 'react'; import {CardStyleInterpolators} from '@react-navigation/stack'; -import * as PlatformStackNavigator from '../PlatformStackNavigator'; +import createPlatformStackNavigator from '../PlatformStackNavigation/createPlatformStackNavigator'; import styles from '../../../styles/styles'; import SCREENS from '../../../SCREENS'; @@ -20,7 +20,7 @@ const defaultSubRouteOptions = { * @returns {Function} */ function createModalStackNavigator(screens) { - const ModalStackNavigator = PlatformStackNavigator.createPlatformStackNavigator(); + const ModalStackNavigator = createPlatformStackNavigator(); return () => ( {_.map(screens, (getComponent, name) => ( diff --git a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js index b5fa76a48b90..754a25694785 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/CentralPaneNavigator.js @@ -1,12 +1,12 @@ import React from 'react'; -import * as PlatformStackNavigator from '../../PlatformStackNavigator'; +import createPlatformStackNavigator from '../../PlatformStackNavigation/createPlatformStackNavigator'; import SCREENS from '../../../../SCREENS'; import ReportScreenWrapper from '../ReportScreenWrapper'; import getCurrentUrl from '../../currentUrl'; import styles from '../../../../styles/styles'; import FreezeWrapper from '../../FreezeWrapper'; -const Stack = PlatformStackNavigator.createPlatformStackNavigator(); +const Stack = createPlatformStackNavigator(); const url = getCurrentUrl(); const openOnAdminRoom = url ? new URL(url).searchParams.get('openOnAdminRoom') : undefined; diff --git a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js index 822a1c6ead55..2086490c597f 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js +++ b/src/libs/Navigation/AppNavigator/Navigators/RightModalNavigator.js @@ -1,6 +1,6 @@ import React from 'react'; import {View} from 'react-native'; -import * as PlatformStackNavigator from '../../PlatformStackNavigator'; +import createPlatformStackNavigator from '../../PlatformStackNavigation/createPlatformStackNavigator'; import * as ModalStackNavigators from '../ModalStackNavigators'; import RHPScreenOptions from '../RHPScreenOptions'; @@ -10,7 +10,7 @@ import styles from '../../../../styles/styles'; import Overlay from './Overlay'; import NoDropZone from '../../../../components/DragAndDrop/NoDropZone'; -const Stack = PlatformStackNavigator.createPlatformStackNavigator(); +const Stack = createPlatformStackNavigator(); const propTypes = { ...withNavigationPropTypes, diff --git a/src/libs/Navigation/AppNavigator/PublicScreens.js b/src/libs/Navigation/AppNavigator/PublicScreens.js index 6a2ad51cab6b..720784f97ec1 100644 --- a/src/libs/Navigation/AppNavigator/PublicScreens.js +++ b/src/libs/Navigation/AppNavigator/PublicScreens.js @@ -1,5 +1,5 @@ import React from 'react'; -import * as PlatformStackNavigator from '../PlatformStackNavigator'; +import createPlatformStackNavigator from '../PlatformStackNavigation/createPlatformStackNavigator'; import SignInPage from '../../../pages/signin/SignInPage'; import ValidateLoginPage from '../../../pages/ValidateLoginPage'; import LogInWithShortLivedAuthTokenPage from '../../../pages/LogInWithShortLivedAuthTokenPage'; @@ -10,7 +10,7 @@ import AppleSignInDesktopPage from '../../../pages/signin/AppleSignInDesktopPage import GoogleSignInDesktopPage from '../../../pages/signin/GoogleSignInDesktopPage'; import SAMLSignInPage from '../../../pages/signin/SAMLSignInPage'; -const RootStack = PlatformStackNavigator.createPlatformStackNavigator(); +const RootStack = createPlatformStackNavigator(); function PublicScreens() { return ( diff --git a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js index 5b9679426a4f..60894018ffd3 100644 --- a/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js +++ b/src/libs/Navigation/AppNavigator/createCustomStackNavigator/index.js @@ -1,7 +1,7 @@ import React, {useRef} from 'react'; import PropTypes from 'prop-types'; import {useNavigationBuilder, createNavigatorFactory} from '@react-navigation/native'; -import * as PlatformStackNavigator from '../../PlatformStackNavigator'; +import StackView from '../../PlatformStackNavigation/StackView'; import CustomRouter from './CustomRouter'; import useWindowDimensions from '../../../../hooks/useWindowDimensions'; @@ -42,7 +42,7 @@ function ResponsiveStackNavigator(props) { return ( - Date: Thu, 19 Oct 2023 17:06:52 +0200 Subject: [PATCH 004/793] fix right modal options --- .../defaultScreenOptions/index.native.ts | 10 +++++++++ .../index.ts} | 0 .../index.native.ts | 7 +++++++ .../getRightModalNavigatorOptions/index.ts | 21 +++++++++++++++++++ .../getRootNavigatorScreenOptions.js | 15 ++----------- .../getNavigationModalCardStyles/types.ts | 4 +--- 6 files changed, 41 insertions(+), 16 deletions(-) create mode 100644 src/libs/Navigation/AppNavigator/defaultScreenOptions/index.native.ts rename src/libs/Navigation/AppNavigator/{defaultScreenOptions.js => defaultScreenOptions/index.ts} (100%) create mode 100644 src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.native.ts create mode 100644 src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.ts diff --git a/src/libs/Navigation/AppNavigator/defaultScreenOptions/index.native.ts b/src/libs/Navigation/AppNavigator/defaultScreenOptions/index.native.ts new file mode 100644 index 000000000000..12ba580c41d8 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/defaultScreenOptions/index.native.ts @@ -0,0 +1,10 @@ +const defaultScreenOptions = { + contentStyle: { + overflow: 'visible', + flex: 1, + }, + headerShown: false, + animationTypeForReplace: 'push', +}; + +export default defaultScreenOptions; diff --git a/src/libs/Navigation/AppNavigator/defaultScreenOptions.js b/src/libs/Navigation/AppNavigator/defaultScreenOptions/index.ts similarity index 100% rename from src/libs/Navigation/AppNavigator/defaultScreenOptions.js rename to src/libs/Navigation/AppNavigator/defaultScreenOptions/index.ts diff --git a/src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.native.ts b/src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.native.ts new file mode 100644 index 000000000000..35d4605a2e5c --- /dev/null +++ b/src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.native.ts @@ -0,0 +1,7 @@ +import {NativeStackNavigationOptions} from '@react-navigation/native-stack'; + +const rightModalNavigatorOptions = (): NativeStackNavigationOptions => ({ + presentation: 'card', +}); + +export default rightModalNavigatorOptions; diff --git a/src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.ts b/src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.ts new file mode 100644 index 000000000000..ccab8ecd9fa5 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.ts @@ -0,0 +1,21 @@ +import {StackNavigationOptions} from '@react-navigation/stack'; +import getNavigationModalCardStyle from '../../../../styles/getNavigationModalCardStyles'; +import modalCardStyleInterpolator from '../modalCardStyleInterpolator'; + +const rightModalNavigatorOptions = (isSmallScreenWidth: boolean): StackNavigationOptions => ({ + cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, false, props), + presentation: 'transparentModal', + + // We want pop in RHP since there are some flows that would work weird otherwise + animationTypeForReplace: 'pop', + cardStyle: { + ...getNavigationModalCardStyle(), + + // This is necessary to cover translated sidebar with overlay. + width: isSmallScreenWidth ? '100%' : '200%', + // Excess space should be on the left so we need to position from right. + right: 0, + }, +}); + +export default rightModalNavigatorOptions; diff --git a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js index a7456fb071b4..ef879e269242 100644 --- a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js +++ b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js @@ -3,6 +3,7 @@ import styles from '../../../styles/styles'; import variables from '../../../styles/variables'; import getNavigationModalCardStyle from '../../../styles/getNavigationModalCardStyles'; import CONFIG from '../../../CONFIG'; +import getRightModalNavigatorOptions from './getRightModalNavigatorOptions'; const commonScreenOptions = { headerShown: false, @@ -15,19 +16,7 @@ const commonScreenOptions = { export default (isSmallScreenWidth) => ({ rightModalNavigator: { ...commonScreenOptions, - cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, false, props), - presentation: 'transparentModal', - - // We want pop in RHP since there are some flows that would work weird otherwise - animationTypeForReplace: 'pop', - cardStyle: { - ...getNavigationModalCardStyle(), - - // This is necessary to cover translated sidebar with overlay. - width: isSmallScreenWidth ? '100%' : '200%', - // Excess space should be on the left so we need to position from right. - right: 0, - }, + ...getRightModalNavigatorOptions(isSmallScreenWidth), }, homeScreen: { diff --git a/src/styles/getNavigationModalCardStyles/types.ts b/src/styles/getNavigationModalCardStyles/types.ts index 877981dd4dd2..e0dba07dc908 100644 --- a/src/styles/getNavigationModalCardStyles/types.ts +++ b/src/styles/getNavigationModalCardStyles/types.ts @@ -1,7 +1,5 @@ import {ViewStyle} from 'react-native'; -type GetNavigationModalCardStylesParams = {isSmallScreenWidth: number}; - -type GetNavigationModalCardStyles = (params: GetNavigationModalCardStylesParams) => ViewStyle; +type GetNavigationModalCardStyles = () => ViewStyle; export default GetNavigationModalCardStyles; From 27b2a131ccc8d7a9652adc127f67752f6911b447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Thu, 19 Oct 2023 17:09:36 +0200 Subject: [PATCH 005/793] add note about card* property usage --- .../Navigation/AppNavigator/getRootNavigatorScreenOptions.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js index ef879e269242..578ed1881b97 100644 --- a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js +++ b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js @@ -22,8 +22,8 @@ export default (isSmallScreenWidth) => ({ homeScreen: { title: CONFIG.SITE_TITLE, ...commonScreenOptions, + // Note: The card* properties won't be applied on mobile platforms, as they use the native defaults. cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, false, props), - cardStyle: { ...getNavigationModalCardStyle(), width: isSmallScreenWidth ? '100%' : variables.sideBarWidth, @@ -36,6 +36,7 @@ export default (isSmallScreenWidth) => ({ // eslint-disable-next-line rulesdir/no-negated-variables fullScreen: { ...commonScreenOptions, + cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, true, props), cardStyle: { ...getNavigationModalCardStyle(), @@ -49,8 +50,8 @@ export default (isSmallScreenWidth) => ({ title: CONFIG.SITE_TITLE, ...commonScreenOptions, animationEnabled: isSmallScreenWidth, - cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, true, props), + cardStyleInterpolator: (props) => modalCardStyleInterpolator(isSmallScreenWidth, true, props), cardStyle: { ...getNavigationModalCardStyle(), paddingRight: isSmallScreenWidth ? 0 : variables.sideBarWidth, From 5e5deb49b113133448114eff68fb05c8547b822d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Thu, 19 Oct 2023 17:40:19 +0200 Subject: [PATCH 006/793] migrate defaultSubRouteOptions --- .../Navigation/AppNavigator/ModalStackNavigators.js | 11 +---------- .../modalStackNavigatorOptions/index.native.ts | 9 +++++++++ .../AppNavigator/modalStackNavigatorOptions/index.ts | 10 ++++++++++ 3 files changed, 20 insertions(+), 10 deletions(-) create mode 100644 src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.native.ts create mode 100644 src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.ts diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js index 985aacc9da96..7f5e8fbc3579 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators.js +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators.js @@ -1,17 +1,8 @@ import _ from 'underscore'; import React from 'react'; -import {CardStyleInterpolators} from '@react-navigation/stack'; import createPlatformStackNavigator from '../PlatformStackNavigation/createPlatformStackNavigator'; - -import styles from '../../../styles/styles'; import SCREENS from '../../../SCREENS'; - -// TODO: migrate options -const defaultSubRouteOptions = { - cardStyle: styles.navigationScreenCardStyle, - headerShown: false, - cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, -}; +import defaultSubRouteOptions from './modalStackNavigatorOptions'; /** * Create a modal stack navigator with an array of sub-screens. diff --git a/src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.native.ts b/src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.native.ts new file mode 100644 index 000000000000..c54b1d653aca --- /dev/null +++ b/src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.native.ts @@ -0,0 +1,9 @@ +import {NativeStackNavigationOptions} from '@react-navigation/native-stack'; +import styles from '../../../../styles/styles'; + +const defaultSubRouteOptions: NativeStackNavigationOptions = { + contentStyle: styles.navigationScreenCardStyle, + headerShown: false, +}; + +export default defaultSubRouteOptions; diff --git a/src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.ts b/src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.ts new file mode 100644 index 000000000000..ea241e6f441b --- /dev/null +++ b/src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.ts @@ -0,0 +1,10 @@ +import {CardStyleInterpolators, StackNavigationOptions} from '@react-navigation/stack'; +import styles from '../../../../styles/styles'; + +const defaultSubRouteOptions: StackNavigationOptions = { + cardStyle: styles.navigationScreenCardStyle, + headerShown: false, + cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS, +}; + +export default defaultSubRouteOptions; From 6e49ccf73e6aa9907a24debc676696bdb9c83c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Fri, 20 Oct 2023 08:08:20 +0200 Subject: [PATCH 007/793] change default animation for android --- .../Navigation/AppNavigator/defaultScreenOptions/index.native.ts | 1 + .../AppNavigator/getRightModalNavigatorOptions/index.native.ts | 1 + .../Navigation/AppNavigator/getRootNavigatorScreenOptions.js | 1 + .../AppNavigator/modalStackNavigatorOptions/index.native.ts | 1 + 4 files changed, 4 insertions(+) diff --git a/src/libs/Navigation/AppNavigator/defaultScreenOptions/index.native.ts b/src/libs/Navigation/AppNavigator/defaultScreenOptions/index.native.ts index 12ba580c41d8..17100bc71bda 100644 --- a/src/libs/Navigation/AppNavigator/defaultScreenOptions/index.native.ts +++ b/src/libs/Navigation/AppNavigator/defaultScreenOptions/index.native.ts @@ -5,6 +5,7 @@ const defaultScreenOptions = { }, headerShown: false, animationTypeForReplace: 'push', + animation: 'slide_from_right', }; export default defaultScreenOptions; diff --git a/src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.native.ts b/src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.native.ts index 35d4605a2e5c..9c0d1fe3abff 100644 --- a/src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.native.ts +++ b/src/libs/Navigation/AppNavigator/getRightModalNavigatorOptions/index.native.ts @@ -2,6 +2,7 @@ import {NativeStackNavigationOptions} from '@react-navigation/native-stack'; const rightModalNavigatorOptions = (): NativeStackNavigationOptions => ({ presentation: 'card', + animation: 'slide_from_right', }); export default rightModalNavigatorOptions; diff --git a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js index 578ed1881b97..9d485f239fe6 100644 --- a/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js +++ b/src/libs/Navigation/AppNavigator/getRootNavigatorScreenOptions.js @@ -11,6 +11,7 @@ const commonScreenOptions = { animationEnabled: true, cardOverlayEnabled: true, animationTypeForReplace: 'push', + animation: 'slide_from_right', }; export default (isSmallScreenWidth) => ({ diff --git a/src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.native.ts b/src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.native.ts index c54b1d653aca..96ee4c4b26d2 100644 --- a/src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.native.ts +++ b/src/libs/Navigation/AppNavigator/modalStackNavigatorOptions/index.native.ts @@ -4,6 +4,7 @@ import styles from '../../../../styles/styles'; const defaultSubRouteOptions: NativeStackNavigationOptions = { contentStyle: styles.navigationScreenCardStyle, headerShown: false, + animation: 'slide_from_right', }; export default defaultSubRouteOptions; From 08c6181183ac2f092e739985a75fed309d8b65c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hanno=20J=2E=20G=C3=B6decke?= Date: Fri, 20 Oct 2023 08:59:45 +0200 Subject: [PATCH 008/793] migrate overlay --- .../Navigators/{Overlay.js => Overlay/index.js} | 9 ++++----- .../AppNavigator/Navigators/Overlay/index.native.js | 7 +++++++ 2 files changed, 11 insertions(+), 5 deletions(-) rename src/libs/Navigation/AppNavigator/Navigators/{Overlay.js => Overlay/index.js} (86%) create mode 100644 src/libs/Navigation/AppNavigator/Navigators/Overlay/index.native.js diff --git a/src/libs/Navigation/AppNavigator/Navigators/Overlay.js b/src/libs/Navigation/AppNavigator/Navigators/Overlay/index.js similarity index 86% rename from src/libs/Navigation/AppNavigator/Navigators/Overlay.js rename to src/libs/Navigation/AppNavigator/Navigators/Overlay/index.js index ed3c27aed673..ad35484d21d8 100644 --- a/src/libs/Navigation/AppNavigator/Navigators/Overlay.js +++ b/src/libs/Navigation/AppNavigator/Navigators/Overlay/index.js @@ -1,14 +1,13 @@ import React from 'react'; import {Animated, View} from 'react-native'; -// TODO: migrate import {useCardAnimation} from '@react-navigation/stack'; import PropTypes from 'prop-types'; -import styles from '../../../../styles/styles'; +import styles from '../../../../../styles/styles'; -import PressableWithoutFeedback from '../../../../components/Pressable/PressableWithoutFeedback'; -import useLocalize from '../../../../hooks/useLocalize'; -import CONST from '../../../../CONST'; +import PressableWithoutFeedback from '../../../../../components/Pressable/PressableWithoutFeedback'; +import useLocalize from '../../../../../hooks/useLocalize'; +import CONST from '../../../../../CONST'; const propTypes = { /* Callback to close the modal */ diff --git a/src/libs/Navigation/AppNavigator/Navigators/Overlay/index.native.js b/src/libs/Navigation/AppNavigator/Navigators/Overlay/index.native.js new file mode 100644 index 000000000000..30651e32cbd6 --- /dev/null +++ b/src/libs/Navigation/AppNavigator/Navigators/Overlay/index.native.js @@ -0,0 +1,7 @@ +function Overlay() { + return null; +} + +Overlay.displayName = 'Overlay'; + +export default Overlay; From dde6aca441a7aa3f99ddcea54826f1de16a8e26a Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 18 Dec 2023 17:11:25 +0100 Subject: [PATCH 009/793] chore: move IOUWaypoint Pages to TS --- src/ROUTES.ts | 2 +- src/libs/Navigation/types.ts | 4 +- src/libs/actions/Transaction.ts | 20 ++- src/pages/iou/MoneyRequestEditWaypointPage.js | 32 ----- .../iou/MoneyRequestEditWaypointPage.tsx | 15 ++ .../NewDistanceRequestWaypointEditorPage.js | 55 -------- .../NewDistanceRequestWaypointEditorPage.tsx | 38 +++++ .../{WaypointEditor.js => WaypointEditor.tsx} | 132 ++++++++---------- src/types/onyx/Transaction.ts | 20 ++- 9 files changed, 145 insertions(+), 173 deletions(-) delete mode 100644 src/pages/iou/MoneyRequestEditWaypointPage.js create mode 100644 src/pages/iou/MoneyRequestEditWaypointPage.tsx delete mode 100644 src/pages/iou/NewDistanceRequestWaypointEditorPage.js create mode 100644 src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx rename src/pages/iou/{WaypointEditor.js => WaypointEditor.tsx} (73%) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index ca1fe9f0e81a..1a205c7827b1 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -300,7 +300,7 @@ const ROUTES = { }, MONEY_REQUEST_EDIT_WAYPOINT: { route: 'r/:threadReportID/edit/distance/:transactionID/waypoint/:waypointIndex', - getRoute: (threadReportID: number, transactionID: string, waypointIndex: number) => `r/${threadReportID}/edit/distance/${transactionID}/waypoint/${waypointIndex}` as const, + getRoute: (threadReportID: string, transactionID: string, waypointIndex: number) => `r/${threadReportID}/edit/distance/${transactionID}/waypoint/${waypointIndex}` as const, }, MONEY_REQUEST_DISTANCE_TAB: { route: ':iouType/new/:reportID?/distance', diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 94a07ddc6b73..bae2ccaf1cc0 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -227,13 +227,13 @@ type MoneyRequestNavigatorParamList = { iouType: string; transactionID: string; waypointIndex: string; - threadReportID: number; + threadReportID: string; }; [SCREENS.MONEY_REQUEST.EDIT_WAYPOINT]: { iouType: string; transactionID: string; waypointIndex: string; - threadReportID: number; + threadReportID: string; }; [SCREENS.MONEY_REQUEST.DISTANCE]: { iouType: ValueOf; diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts index 86bd1b31714d..75a202b59986 100644 --- a/src/libs/actions/Transaction.ts +++ b/src/libs/actions/Transaction.ts @@ -1,7 +1,7 @@ import {isEqual} from 'lodash'; import lodashClone from 'lodash/clone'; import lodashHas from 'lodash/has'; -import Onyx from 'react-native-onyx'; +import Onyx, {OnyxEntry} from 'react-native-onyx'; import * as API from '@libs/API'; import * as CollectionUtils from '@libs/CollectionUtils'; import * as TransactionUtils from '@libs/TransactionUtils'; @@ -102,7 +102,7 @@ function saveWaypoint(transactionID: string, index: string, waypoint: RecentWayp } } -function removeWaypoint(transaction: Transaction, currentIndex: string, isDraft: boolean) { +function removeWaypoint(transaction: OnyxEntry, currentIndex: string, isDraft?: boolean) { // Index comes from the route params and is a string const index = Number(currentIndex); const existingWaypoints = transaction?.comment?.waypoints ?? {}; @@ -131,8 +131,18 @@ function removeWaypoint(transaction: Transaction, currentIndex: string, isDraft: // Doing a deep clone of the transaction to avoid mutating the original object and running into a cache issue when using Onyx.set let newTransaction: Transaction = { ...transaction, + amount: transaction?.amount ?? 0, + billable: transaction?.billable ?? false, + category: transaction?.category ?? '', + created: transaction?.created ?? '', + currency: transaction?.currency ?? '', + pendingAction: transaction?.pendingAction ?? null, + merchant: transaction?.merchant ?? '', + reportID: transaction?.reportID ?? '', + transactionID: transaction?.transactionID ?? '', + tag: transaction?.tag ?? '', comment: { - ...transaction.comment, + ...transaction?.comment, waypoints: reIndexedWaypoints, }, }; @@ -156,10 +166,10 @@ function removeWaypoint(transaction: Transaction, currentIndex: string, isDraft: }; } if (isDraft) { - Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction.transactionID}`, newTransaction); + Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transaction?.transactionID}`, newTransaction); return; } - Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction.transactionID}`, newTransaction); + Onyx.set(`${ONYXKEYS.COLLECTION.TRANSACTION}${transaction?.transactionID}`, newTransaction); } function getOnyxDataForRouteRequest(transactionID: string, isDraft = false): OnyxData { diff --git a/src/pages/iou/MoneyRequestEditWaypointPage.js b/src/pages/iou/MoneyRequestEditWaypointPage.js deleted file mode 100644 index fc777891109e..000000000000 --- a/src/pages/iou/MoneyRequestEditWaypointPage.js +++ /dev/null @@ -1,32 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import WaypointEditor from './WaypointEditor'; - -const propTypes = { - /** Route params */ - route: PropTypes.shape({ - params: PropTypes.shape({ - /** Thread reportID */ - threadReportID: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - - /** ID of the transaction being edited */ - transactionID: PropTypes.string, - - /** Index of the waypoint being edited */ - waypointIndex: PropTypes.string, - }), - }), -}; - -const defaultProps = { - route: {}, -}; - -function MoneyRequestEditWaypointPage({route}) { - return ; -} - -MoneyRequestEditWaypointPage.displayName = 'MoneyRequestEditWaypointPage'; -MoneyRequestEditWaypointPage.propTypes = propTypes; -MoneyRequestEditWaypointPage.defaultProps = defaultProps; -export default MoneyRequestEditWaypointPage; diff --git a/src/pages/iou/MoneyRequestEditWaypointPage.tsx b/src/pages/iou/MoneyRequestEditWaypointPage.tsx new file mode 100644 index 000000000000..49319b2c0e3e --- /dev/null +++ b/src/pages/iou/MoneyRequestEditWaypointPage.tsx @@ -0,0 +1,15 @@ +import {StackScreenProps} from '@react-navigation/stack'; +import React from 'react'; +import {MoneyRequestNavigatorParamList} from '@libs/Navigation/types'; +import SCREENS from '@src/SCREENS'; +import WaypointEditor from './WaypointEditor'; + +type MoneyRequestEditWaypointPageProps = StackScreenProps; + +function MoneyRequestEditWaypointPage({route}: MoneyRequestEditWaypointPageProps) { + return ; +} + +MoneyRequestEditWaypointPage.displayName = 'MoneyRequestEditWaypointPage'; + +export default MoneyRequestEditWaypointPage; diff --git a/src/pages/iou/NewDistanceRequestWaypointEditorPage.js b/src/pages/iou/NewDistanceRequestWaypointEditorPage.js deleted file mode 100644 index 269cde577040..000000000000 --- a/src/pages/iou/NewDistanceRequestWaypointEditorPage.js +++ /dev/null @@ -1,55 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import {withOnyx} from 'react-native-onyx'; -import ONYXKEYS from '@src/ONYXKEYS'; -import WaypointEditor from './WaypointEditor'; - -const propTypes = { - /** The transactionID of this request */ - transactionID: PropTypes.string, - - /** Route params */ - route: PropTypes.shape({ - params: PropTypes.shape({ - /** IOU type */ - iouType: PropTypes.string, - - /** Index of the waypoint being edited */ - waypointIndex: PropTypes.string, - }), - }), -}; - -const defaultProps = { - transactionID: '', - route: { - params: { - iouType: '', - waypointIndex: '', - }, - }, -}; - -// This component is responsible for grabbing the transactionID from the IOU key -// You can't use Onyx props in the withOnyx mapping, so we need to set up and access the transactionID here, and then pass it down so that WaypointEditor can subscribe to the transaction. -function NewDistanceRequestWaypointEditorPage({transactionID, route}) { - return ( - - ); -} - -NewDistanceRequestWaypointEditorPage.displayName = 'NewDistanceRequestWaypointEditorPage'; -NewDistanceRequestWaypointEditorPage.propTypes = propTypes; -NewDistanceRequestWaypointEditorPage.defaultProps = defaultProps; -export default withOnyx({ - transactionID: {key: ONYXKEYS.IOU, selector: (iou) => iou && iou.transactionID}, -})(NewDistanceRequestWaypointEditorPage); diff --git a/src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx b/src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx new file mode 100644 index 000000000000..2480c8cc097c --- /dev/null +++ b/src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx @@ -0,0 +1,38 @@ +import {RouteProp} from '@react-navigation/native'; +import {StackScreenProps} from '@react-navigation/stack'; +import React from 'react'; +import {withOnyx} from 'react-native-onyx'; +import {MoneyRequestNavigatorParamList} from '@libs/Navigation/types'; +import ONYXKEYS from '@src/ONYXKEYS'; +import SCREENS from '@src/SCREENS'; +import WaypointEditor from './WaypointEditor'; + +type NewDistanceRequestWaypointEditorPageOnyxProps = { + transactionID: string | undefined; +}; +type NewDistanceRequestWaypointEditorPageProps = StackScreenProps & NewDistanceRequestWaypointEditorPageOnyxProps; + +// This component is responsible for grabbing the transactionID from the IOU key +// You can't use Onyx props in the withOnyx mapping, so we need to set up and access the transactionID here, and then pass it down so that WaypointEditor can subscribe to the transaction. +function NewDistanceRequestWaypointEditorPage({transactionID, route}: NewDistanceRequestWaypointEditorPageProps) { + return ( + + } + /> + ); +} + +NewDistanceRequestWaypointEditorPage.displayName = 'NewDistanceRequestWaypointEditorPage'; + +export default withOnyx({ + transactionID: {key: ONYXKEYS.IOU, selector: (iou) => iou?.transactionID}, +})(NewDistanceRequestWaypointEditorPage); diff --git a/src/pages/iou/WaypointEditor.js b/src/pages/iou/WaypointEditor.tsx similarity index 73% rename from src/pages/iou/WaypointEditor.js rename to src/pages/iou/WaypointEditor.tsx index e8d3c8520ca8..d72a3001094f 100644 --- a/src/pages/iou/WaypointEditor.js +++ b/src/pages/iou/WaypointEditor.tsx @@ -1,9 +1,7 @@ -import {useNavigation} from '@react-navigation/native'; -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; +import {RouteProp, useNavigation} from '@react-navigation/native'; +import {StackScreenProps} from '@react-navigation/stack'; import React, {useMemo, useRef, useState} from 'react'; -import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import AddressSearch from '@components/AddressSearch'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import ConfirmModal from '@components/ConfirmModal'; @@ -12,71 +10,51 @@ import InputWrapper from '@components/Form/InputWrapper'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; import ScreenWrapper from '@components/ScreenWrapper'; -import transactionPropTypes from '@components/transactionPropTypes'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; +import {MoneyRequestNavigatorParamList} from '@libs/Navigation/types'; import * as ValidationUtils from '@libs/ValidationUtils'; import * as Transaction from '@userActions/Transaction'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; +import * as OnyxTypes from '@src/types/onyx'; +import {Waypoint} from '@src/types/onyx/Transaction'; +import {isNotEmptyObject} from '@src/types/utils/EmptyObject'; + +type MappedWaypoint = { + name: string | undefined; + description: string; + geometry: { + location: { + lat: number; + lng: number; + }; + }; +}; -const propTypes = { - /** Route params */ - route: PropTypes.shape({ - params: PropTypes.shape({ - /** IOU type */ - iouType: PropTypes.string, - - /** Thread reportID */ - threadReportID: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), - - /** ID of the transaction being edited */ - transactionID: PropTypes.string, - - /** Index of the waypoint being edited */ - waypointIndex: PropTypes.string, - }), - }), - - recentWaypoints: PropTypes.arrayOf( - PropTypes.shape({ - /** The name of the location */ - name: PropTypes.string, - - /** A description of the location (usually the address) */ - description: PropTypes.string, - - /** Data required by the google auto complete plugin to know where to put the markers on the map */ - geometry: PropTypes.shape({ - /** Data about the location */ - location: PropTypes.shape({ - /** Latitude of the location */ - lat: PropTypes.number, - - /** Longitude of the location */ - lng: PropTypes.number, - }), - }), - }), - ), - - /* Onyx props */ +type WaypointEditorOnyxProps = { /** The optimistic transaction for this request */ - transaction: transactionPropTypes, -}; + transaction: OnyxEntry; -const defaultProps = { - route: {}, - recentWaypoints: [], - transaction: {}, + /** List of recent waypoints */ + recentWaypoints: OnyxEntry; }; -function WaypointEditor({route: {params: {iouType = '', transactionID = '', waypointIndex = '', threadReportID = 0}} = {}, transaction, recentWaypoints}) { +type WaypointEditorProps = {route: RouteProp} & WaypointEditorOnyxProps; + +function WaypointEditor({ + route: { + params: {iouType = '', transactionID = '', waypointIndex = '', threadReportID = ''}, + }, + transaction, + recentWaypoints = [], +}: WaypointEditorProps) { const styles = useThemeStyles(); const {windowWidth} = useWindowDimensions(); const [isDeleteStopModalOpen, setIsDeleteStopModalOpen] = useState(false); @@ -86,11 +64,11 @@ function WaypointEditor({route: {params: {iouType = '', transactionID = '', wayp const {isOffline} = useNetwork(); const textInput = useRef(null); const parsedWaypointIndex = parseInt(waypointIndex, 10); - const allWaypoints = lodashGet(transaction, 'comment.waypoints', {}); - const currentWaypoint = lodashGet(allWaypoints, `waypoint${waypointIndex}`, {}); + const allWaypoints = transaction?.comment.waypoints ?? {}; + const currentWaypoint = allWaypoints[`waypoint${waypointIndex}`] ?? {}; - const waypointCount = _.size(allWaypoints); - const filledWaypointCount = _.size(_.filter(allWaypoints, (waypoint) => !_.isEmpty(waypoint))); + const waypointCount = Object.keys(allWaypoints).length; + const filledWaypointCount = Object.values(allWaypoints).filter((waypoint) => isNotEmptyObject(waypoint)).length; const waypointDescriptionKey = useMemo(() => { switch (parsedWaypointIndex) { @@ -103,15 +81,15 @@ function WaypointEditor({route: {params: {iouType = '', transactionID = '', wayp } }, [parsedWaypointIndex, waypointCount]); - const waypointAddress = lodashGet(currentWaypoint, 'address', ''); - const isEditingWaypoint = Boolean(threadReportID); + const waypointAddress = currentWaypoint.address ?? ''; + const isEditingWaypoint = !!threadReportID; // Hide the menu when there is only start and finish waypoint const shouldShowThreeDotsButton = waypointCount > 2; const shouldDisableEditor = isFocused && (Number.isNaN(parsedWaypointIndex) || parsedWaypointIndex < 0 || parsedWaypointIndex > waypointCount || (filledWaypointCount < 2 && parsedWaypointIndex >= waypointCount)); - const validate = (values) => { + const validate = (values: Record) => { const errors = {}; const waypointValue = values[`waypoint${waypointIndex}`] || ''; if (isOffline && waypointValue !== '' && !ValidationUtils.isValidAddress(waypointValue)) { @@ -127,9 +105,9 @@ function WaypointEditor({route: {params: {iouType = '', transactionID = '', wayp return errors; }; - const saveWaypoint = (waypoint) => Transaction.saveWaypoint(transactionID, waypointIndex, waypoint, isEditingWaypoint); + const saveWaypoint = (waypoint: OnyxTypes.RecentWaypoint) => Transaction.saveWaypoint(transactionID, waypointIndex, waypoint, isEditingWaypoint); - const submit = (values) => { + const submit = (values: Record) => { const waypointValue = values[`waypoint${waypointIndex}`] || ''; // Allows letting you set a waypoint to an empty value @@ -141,10 +119,10 @@ function WaypointEditor({route: {params: {iouType = '', transactionID = '', wayp // Therefore, we're going to save the waypoint as just the address, and the lat/long will be filled in on the backend if (isOffline && waypointValue) { const waypoint = { - lat: null, - lng: null, + lat: -1, + lng: -1, address: waypointValue, - name: null, + name: undefined, }; saveWaypoint(waypoint); } @@ -159,12 +137,13 @@ function WaypointEditor({route: {params: {iouType = '', transactionID = '', wayp Navigation.goBack(ROUTES.MONEY_REQUEST_DISTANCE_TAB.getRoute(iouType)); }; - const selectWaypoint = (values) => { + const selectWaypoint = (values: Waypoint) => { const waypoint = { - lat: values.lat, - lng: values.lng, - address: values.address, - name: values.name || null, + lat: values.lat ?? 0, + lng: values.lng ?? 0, + address: values.address ?? '', + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + name: values.name, }; saveWaypoint(waypoint); @@ -178,7 +157,7 @@ function WaypointEditor({route: {params: {iouType = '', transactionID = '', wayp return ( textInput.current && textInput.current.focus()} + onEntryTransitionEnd={() => textInput.current?.focus()} shouldEnableMaxHeight testID={WaypointEditor.displayName} > @@ -251,11 +230,10 @@ function WaypointEditor({route: {params: {iouType = '', transactionID = '', wayp } WaypointEditor.displayName = 'WaypointEditor'; -WaypointEditor.propTypes = propTypes; -WaypointEditor.defaultProps = defaultProps; -export default withOnyx({ + +export default withOnyx({ transaction: { - key: ({route}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${lodashGet(route, 'params.transactionID')}`, + key: ({route}) => `${ONYXKEYS.COLLECTION.TRANSACTION}${route.params.transactionID}`, }, recentWaypoints: { key: ONYXKEYS.NVP_RECENT_WAYPOINTS, @@ -263,7 +241,7 @@ export default withOnyx({ // Only grab the most recent 5 waypoints because that's all that is shown in the UI. This also puts them into the format of data // that the google autocomplete component expects for it's "predefined places" feature. selector: (waypoints) => - _.map(waypoints ? waypoints.slice(0, 5) : [], (waypoint) => ({ + (waypoints ? waypoints.slice(0, 5) : []).map((waypoint) => ({ name: waypoint.name, description: waypoint.address, geometry: { diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 53bfc36a4e47..5ca701cf1f8e 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -15,6 +15,24 @@ type Waypoint = { /** The longitude of the waypoint */ lng?: number; + + /** Address city */ + city?: string; + + /** Address state */ + state?: string; + + /** Address zip code */ + zipCode?: string; + + /** Address country */ + country?: string; + + /** Address street line 1 */ + street?: string; + + /** Address street line 2 */ + street2?: string; }; type WaypointCollection = Record; @@ -70,7 +88,7 @@ type Transaction = { modifiedWaypoints?: WaypointCollection; // Used during the creation flow before the transaction is saved to the server and helps dictate where the user is navigated to when pressing the back button on the confirmation step participantsAutoAssigned?: boolean; - pendingAction: OnyxCommon.PendingAction; + pendingAction: OnyxCommon.PendingAction | null; receipt?: Receipt; reportID: string; routes?: Routes; From 36c73edf7f23439187fdf5de45800ff036a62d28 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 18 Dec 2023 17:27:00 +0100 Subject: [PATCH 010/793] ref: seperate types --- src/pages/iou/WaypointEditor.tsx | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/pages/iou/WaypointEditor.tsx b/src/pages/iou/WaypointEditor.tsx index d72a3001094f..2d7fd5b3abcd 100644 --- a/src/pages/iou/WaypointEditor.tsx +++ b/src/pages/iou/WaypointEditor.tsx @@ -1,5 +1,4 @@ import {RouteProp, useNavigation} from '@react-navigation/native'; -import {StackScreenProps} from '@react-navigation/stack'; import React, {useMemo, useRef, useState} from 'react'; import {OnyxEntry, withOnyx} from 'react-native-onyx'; import AddressSearch from '@components/AddressSearch'; @@ -27,15 +26,19 @@ import * as OnyxTypes from '@src/types/onyx'; import {Waypoint} from '@src/types/onyx/Transaction'; import {isNotEmptyObject} from '@src/types/utils/EmptyObject'; +type Location = { + lat: number; + lng: number; +}; + +type Geometry = { + location: Location; +}; + type MappedWaypoint = { name: string | undefined; description: string; - geometry: { - location: { - lat: number; - lng: number; - }; - }; + geometry: Geometry; }; type WaypointEditorOnyxProps = { From dded6349ee50d371ed5c920a4c3334700ad1d537 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 19 Dec 2023 21:55:13 +0530 Subject: [PATCH 011/793] test map when image is not loaded in request view --- .../ReportActionItem/MoneyRequestPreview.js | 10 +++++++++- src/components/ReportActionItem/MoneyRequestView.js | 13 ++++++++++++- src/libs/actions/IOU.js | 3 +++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestPreview.js b/src/components/ReportActionItem/MoneyRequestPreview.js index 12c6d0629370..1d798130dfd5 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview.js +++ b/src/components/ReportActionItem/MoneyRequestPreview.js @@ -38,6 +38,7 @@ import CONST from '@src/CONST'; import * as Localize from '@src/libs/Localize'; import ONYXKEYS from '@src/ONYXKEYS'; import ReportActionItemImages from './ReportActionItemImages'; +import ConfirmedRoute from '@components/ConfirmedRoute'; const propTypes = { /** The active IOUReport, used for Onyx subscription */ @@ -169,6 +170,8 @@ function MoneyRequestPreview(props) { const hasPendingWaypoints = lodashGet(props.transaction, 'pendingFields.waypoints', null); + const showMapAsImage = isDistanceRequest && hasPendingWaypoints; + const getSettledMessage = () => { if (isExpensifyCardTransaction) { return translate('common.done'); @@ -257,7 +260,12 @@ function MoneyRequestPreview(props) { !props.onPreviewPressed ? [styles.moneyRequestPreviewBox, ...props.containerStyles] : {}, ]} > - {hasReceipt && ( + {showMapAsImage && ( + + + + )} + {!showMapAsImage && hasReceipt && ( - {hasReceipt && ( + {showMapAsImage && ( + + + + + + )} + {!showMapAsImage && hasReceipt && ( Date: Wed, 20 Dec 2023 08:32:45 +0100 Subject: [PATCH 012/793] chore: added todos --- src/pages/iou/WaypointEditor.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/WaypointEditor.tsx b/src/pages/iou/WaypointEditor.tsx index 2d7fd5b3abcd..43ade2c0b559 100644 --- a/src/pages/iou/WaypointEditor.tsx +++ b/src/pages/iou/WaypointEditor.tsx @@ -1,5 +1,6 @@ import {RouteProp, useNavigation} from '@react-navigation/native'; import React, {useMemo, useRef, useState} from 'react'; +import {TextInput} from 'react-native'; import {OnyxEntry, withOnyx} from 'react-native-onyx'; import AddressSearch from '@components/AddressSearch'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; @@ -65,7 +66,7 @@ function WaypointEditor({ const isFocused = navigation.isFocused(); const {translate} = useLocalize(); const {isOffline} = useNetwork(); - const textInput = useRef(null); + const textInput = useRef(null); const parsedWaypointIndex = parseInt(waypointIndex, 10); const allWaypoints = transaction?.comment.waypoints ?? {}; const currentWaypoint = allWaypoints[`waypoint${waypointIndex}`] ?? {}; @@ -158,9 +159,12 @@ function WaypointEditor({ }; return ( + /* @ts-expect-error TODO: Remove this once ScreenWrapper (https://github.com/Expensify/App/issues/25109) is migrated to TypeScript. */ textInput.current?.focus()} + onEntryTransitionEnd={() => { + textInput.current?.focus(); + }} shouldEnableMaxHeight testID={WaypointEditor.displayName} > @@ -191,6 +195,7 @@ function WaypointEditor({ cancelText={translate('common.cancel')} danger /> + {/* @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/25109) is migrated to TypeScript. */} (textInput.current = e)} + ref={(e) => { + textInput.current = e; + }} hint={!isOffline ? 'distance.errors.selectSuggestedAddress' : ''} containerStyles={[styles.mt3]} label={translate('distance.address')} From 049e7adb17efdbbede6f908ea39acbd64223f91f Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 20 Dec 2023 11:45:09 +0100 Subject: [PATCH 013/793] fix: address comments --- src/libs/actions/Transaction.ts | 1 - src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx | 4 ++-- src/pages/iou/WaypointEditor.tsx | 6 +++--- src/types/onyx/Transaction.ts | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts index cdb4fad6c14f..ee749b4fab03 100644 --- a/src/libs/actions/Transaction.ts +++ b/src/libs/actions/Transaction.ts @@ -133,7 +133,6 @@ function removeWaypoint(transaction: OnyxEntry, currentIndex: strin category: transaction?.category ?? '', created: transaction?.created ?? '', currency: transaction?.currency ?? '', - pendingAction: transaction?.pendingAction ?? null, merchant: transaction?.merchant ?? '', reportID: transaction?.reportID ?? '', transactionID: transaction?.transactionID ?? '', diff --git a/src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx b/src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx index 2480c8cc097c..de811c5ad9b5 100644 --- a/src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx +++ b/src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx @@ -14,7 +14,7 @@ type NewDistanceRequestWaypointEditorPageProps = StackScreenProps } diff --git a/src/pages/iou/WaypointEditor.tsx b/src/pages/iou/WaypointEditor.tsx index 43ade2c0b559..d2d175624905 100644 --- a/src/pages/iou/WaypointEditor.tsx +++ b/src/pages/iou/WaypointEditor.tsx @@ -37,7 +37,7 @@ type Geometry = { }; type MappedWaypoint = { - name: string | undefined; + name?: string; description: string; geometry: Geometry; }; @@ -143,8 +143,8 @@ function WaypointEditor({ const selectWaypoint = (values: Waypoint) => { const waypoint = { - lat: values.lat ?? 0, - lng: values.lng ?? 0, + lat: values.lat ?? -1, + lng: values.lng ?? -1, address: values.address ?? '', // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing name: values.name, diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 5ca701cf1f8e..f3fec51bf362 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -88,7 +88,7 @@ type Transaction = { modifiedWaypoints?: WaypointCollection; // Used during the creation flow before the transaction is saved to the server and helps dictate where the user is navigated to when pressing the back button on the confirmation step participantsAutoAssigned?: boolean; - pendingAction: OnyxCommon.PendingAction | null; + pendingAction?: OnyxCommon.PendingAction; receipt?: Receipt; reportID: string; routes?: Routes; From 2a751759ef8e01ee5c8d60fffcbeebb3f2151063 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Thu, 21 Dec 2023 15:11:14 +0100 Subject: [PATCH 014/793] fix: adjust recentwaypoint type --- src/pages/iou/WaypointEditor.tsx | 11 ++++------- src/types/onyx/RecentWaypoint.ts | 4 ++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/pages/iou/WaypointEditor.tsx b/src/pages/iou/WaypointEditor.tsx index d2d175624905..c28b1b8f86dc 100644 --- a/src/pages/iou/WaypointEditor.tsx +++ b/src/pages/iou/WaypointEditor.tsx @@ -28,8 +28,8 @@ import {Waypoint} from '@src/types/onyx/Transaction'; import {isNotEmptyObject} from '@src/types/utils/EmptyObject'; type Location = { - lat: number; - lng: number; + lat?: number; + lng?: number; }; type Geometry = { @@ -123,10 +123,7 @@ function WaypointEditor({ // Therefore, we're going to save the waypoint as just the address, and the lat/long will be filled in on the backend if (isOffline && waypointValue) { const waypoint = { - lat: -1, - lng: -1, address: waypointValue, - name: undefined, }; saveWaypoint(waypoint); } @@ -143,8 +140,8 @@ function WaypointEditor({ const selectWaypoint = (values: Waypoint) => { const waypoint = { - lat: values.lat ?? -1, - lng: values.lng ?? -1, + lat: values.lat, + lng: values.lng, address: values.address ?? '', // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing name: values.name, diff --git a/src/types/onyx/RecentWaypoint.ts b/src/types/onyx/RecentWaypoint.ts index 097aed3be916..4028e59846ce 100644 --- a/src/types/onyx/RecentWaypoint.ts +++ b/src/types/onyx/RecentWaypoint.ts @@ -6,10 +6,10 @@ type RecentWaypoint = { address: string; /** The lattitude of the waypoint */ - lat: number; + lat?: number; /** The longitude of the waypoint */ - lng: number; + lng?: number; }; export default RecentWaypoint; From 9b36c85dfd9639ace0b6f8ffa2df6150eb2d5daa Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Tue, 2 Jan 2024 14:41:39 +0100 Subject: [PATCH 015/793] fix: type problems --- .../BlockingViews/FullPageNotFoundView.tsx | 4 ++-- src/libs/ErrorUtils.ts | 1 + src/libs/actions/Transaction.ts | 12 ++---------- src/pages/iou/WaypointEditor.tsx | 12 +++++++++--- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/components/BlockingViews/FullPageNotFoundView.tsx b/src/components/BlockingViews/FullPageNotFoundView.tsx index 6d7f838bf6c2..0427b75aa036 100644 --- a/src/components/BlockingViews/FullPageNotFoundView.tsx +++ b/src/components/BlockingViews/FullPageNotFoundView.tsx @@ -33,10 +33,10 @@ type FullPageNotFoundViewProps = { linkKey?: TranslationPaths; /** Method to trigger when pressing the back button of the header */ - onBackButtonPress: () => void; + onBackButtonPress?: () => void; /** Function to call when pressing the navigation link */ - onLinkPress: () => void; + onLinkPress?: () => void; }; // eslint-disable-next-line rulesdir/no-negated-variables diff --git a/src/libs/ErrorUtils.ts b/src/libs/ErrorUtils.ts index 46bdd510f5c4..ab589ea73fbf 100644 --- a/src/libs/ErrorUtils.ts +++ b/src/libs/ErrorUtils.ts @@ -120,3 +120,4 @@ function addErrorMessage(errors: ErrorsList, inpu } export {getAuthenticateErrorMessage, getMicroSecondOnyxError, getMicroSecondOnyxErrorObject, getLatestErrorMessage, getLatestErrorField, getEarliestErrorField, addErrorMessage}; +export type {ErrorsList}; diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts index ee749b4fab03..ee09fa6966e4 100644 --- a/src/libs/actions/Transaction.ts +++ b/src/libs/actions/Transaction.ts @@ -127,16 +127,8 @@ function removeWaypoint(transaction: OnyxEntry, currentIndex: strin // to remove nested keys while also preserving other object keys // Doing a deep clone of the transaction to avoid mutating the original object and running into a cache issue when using Onyx.set let newTransaction: Transaction = { - ...transaction, - amount: transaction?.amount ?? 0, - billable: transaction?.billable ?? false, - category: transaction?.category ?? '', - created: transaction?.created ?? '', - currency: transaction?.currency ?? '', - merchant: transaction?.merchant ?? '', - reportID: transaction?.reportID ?? '', - transactionID: transaction?.transactionID ?? '', - tag: transaction?.tag ?? '', + // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style + ...(transaction as Transaction), comment: { ...transaction?.comment, waypoints: reIndexedWaypoints, diff --git a/src/pages/iou/WaypointEditor.tsx b/src/pages/iou/WaypointEditor.tsx index c28b1b8f86dc..80491b3b4a91 100644 --- a/src/pages/iou/WaypointEditor.tsx +++ b/src/pages/iou/WaypointEditor.tsx @@ -36,9 +36,16 @@ type Geometry = { location: Location; }; +type Values = Record; + type MappedWaypoint = { + /* Waypoint name */ name?: string; + + /* Waypoint description */ description: string; + + /* Waypoint geometry object cointaing coordinates */ geometry: Geometry; }; @@ -93,7 +100,7 @@ function WaypointEditor({ isFocused && (Number.isNaN(parsedWaypointIndex) || parsedWaypointIndex < 0 || parsedWaypointIndex > waypointCount || (filledWaypointCount < 2 && parsedWaypointIndex >= waypointCount)); - const validate = (values: Record) => { + const validate = (values: Values): ErrorUtils.ErrorsList => { const errors = {}; const waypointValue = values[`waypoint${waypointIndex}`] || ''; if (isOffline && waypointValue !== '' && !ValidationUtils.isValidAddress(waypointValue)) { @@ -111,7 +118,7 @@ function WaypointEditor({ const saveWaypoint = (waypoint: OnyxTypes.RecentWaypoint) => Transaction.saveWaypoint(transactionID, waypointIndex, waypoint, isEditingWaypoint); - const submit = (values: Record) => { + const submit = (values: Values) => { const waypointValue = values[`waypoint${waypointIndex}`] || ''; // Allows letting you set a waypoint to an empty value @@ -143,7 +150,6 @@ function WaypointEditor({ lat: values.lat, lng: values.lng, address: values.address ?? '', - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing name: values.name, }; saveWaypoint(waypoint); From b14c40dfd3a5161b4d1828a040ae6c5e57888e45 Mon Sep 17 00:00:00 2001 From: Antony Kithinzi Date: Tue, 2 Jan 2024 21:31:37 +0100 Subject: [PATCH 016/793] fix: adding backTo param to ReportParticipantsPage.js --- src/pages/ReportParticipantsPage.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js index e04ffbb352fc..1e84bd3dcbbb 100755 --- a/src/pages/ReportParticipantsPage.js +++ b/src/pages/ReportParticipantsPage.js @@ -121,7 +121,12 @@ function ReportParticipantsPage(props) { }, ]} onSelectRow={(option) => { - Navigation.navigate(ROUTES.PROFILE.getRoute(option.accountID)); + Navigation.navigate( + ROUTES.PROFILE.getRoute( + option.accountID, + ROUTES.REPORT_PARTICIPANTS.getRoute(props.report.reportID) + ) + ); }} hideSectionHeaders showTitleTooltip From 7f463df300e29633d97ab2756736fc030e4b5b1a Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Wed, 3 Jan 2024 14:20:47 +0100 Subject: [PATCH 017/793] fix: resolve comments --- src/pages/iou/WaypointEditor.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pages/iou/WaypointEditor.tsx b/src/pages/iou/WaypointEditor.tsx index 80491b3b4a91..e2367502652e 100644 --- a/src/pages/iou/WaypointEditor.tsx +++ b/src/pages/iou/WaypointEditor.tsx @@ -36,16 +36,16 @@ type Geometry = { location: Location; }; -type Values = Record; +type WaypointValues = Record; type MappedWaypoint = { - /* Waypoint name */ + /** Waypoint name */ name?: string; - /* Waypoint description */ + /** Waypoint description */ description: string; - /* Waypoint geometry object cointaing coordinates */ + /** Waypoint geometry object cointaing coordinates */ geometry: Geometry; }; @@ -100,7 +100,7 @@ function WaypointEditor({ isFocused && (Number.isNaN(parsedWaypointIndex) || parsedWaypointIndex < 0 || parsedWaypointIndex > waypointCount || (filledWaypointCount < 2 && parsedWaypointIndex >= waypointCount)); - const validate = (values: Values): ErrorUtils.ErrorsList => { + const validate = (values: WaypointValues): ErrorUtils.ErrorsList => { const errors = {}; const waypointValue = values[`waypoint${waypointIndex}`] || ''; if (isOffline && waypointValue !== '' && !ValidationUtils.isValidAddress(waypointValue)) { @@ -118,7 +118,7 @@ function WaypointEditor({ const saveWaypoint = (waypoint: OnyxTypes.RecentWaypoint) => Transaction.saveWaypoint(transactionID, waypointIndex, waypoint, isEditingWaypoint); - const submit = (values: Values) => { + const submit = (values: WaypointValues) => { const waypointValue = values[`waypoint${waypointIndex}`] || ''; // Allows letting you set a waypoint to an empty value From ef26aaa1d61d8b25ae43ed2deb9cbc0c589d74b5 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 9 Jan 2024 17:49:16 +0530 Subject: [PATCH 018/793] test changes --- src/components/ReportActionItem/MoneyRequestPreview.js | 2 +- src/components/ReportActionItem/MoneyRequestView.js | 2 +- src/libs/TransactionUtils.ts | 7 +++++-- src/libs/actions/IOU.js | 4 +++- src/types/onyx/Transaction.ts | 6 ++++-- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestPreview.js b/src/components/ReportActionItem/MoneyRequestPreview.js index 0663441c3834..9bba3aed205a 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview.js +++ b/src/components/ReportActionItem/MoneyRequestPreview.js @@ -38,8 +38,8 @@ import * as Report from '@userActions/Report'; import CONST from '@src/CONST'; import * as Localize from '@src/libs/Localize'; import ONYXKEYS from '@src/ONYXKEYS'; -import ReportActionItemImages from './ReportActionItemImages'; import ConfirmedRoute from '@components/ConfirmedRoute'; +import ReportActionItemImages from './ReportActionItemImages'; const propTypes = { /** The active IOUReport, used for Onyx subscription */ diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index eb658a7f8a1b..fc70b47d7101 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -42,8 +42,8 @@ import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import ReportActionItemImage from './ReportActionItemImage'; import ConfirmedRoute from '@components/ConfirmedRoute'; +import ReportActionItemImage from './ReportActionItemImage'; const violationNames = lodashValues(CONST.VIOLATIONS); diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index c34a6753c1d5..b8fad803d957 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -1,5 +1,6 @@ import lodashHas from 'lodash/has'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; +import type {EmptyObject} from '@src/types/utils/EmptyObject'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; @@ -7,8 +8,8 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {RecentWaypoint, Report, ReportAction, Transaction} from '@src/types/onyx'; import type {PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates'; import type PolicyTaxRate from '@src/types/onyx/PolicyTaxRates'; -import type {Comment, Receipt, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; +import type {Comment, PendingFieldsCollection, Receipt, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; +import {isNotEmptyObject} from '@src/types/utils/EmptyObject'; import {isCorporateCard, isExpensifyCard} from './CardUtils'; import DateUtils from './DateUtils'; import * as NumberUtils from './NumberUtils'; @@ -98,6 +99,7 @@ function buildOptimisticTransaction( category = '', tag = '', billable = false, + pendingFields: PendingFieldsCollection | null = null, ): Transaction { // transactionIDs are random, positive, 64-bit numeric strings. // Because JS can only handle 53-bit numbers, transactionIDs are strings in the front-end (just like reportActionID) @@ -112,6 +114,7 @@ function buildOptimisticTransaction( } return { + ...(isNotEmptyObject(pendingFields) ? {pendingFields} : {}), transactionID, amount, currency, diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index 4e1a45101732..f4ff83e995c8 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -721,6 +721,8 @@ function getMoneyRequestInformation( receiptObject.state = receipt.state || CONST.IOU.RECEIPT_STATE.SCANREADY; filename = receipt.name; } + const existingTransaction = allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`]; + const isDistanceRequest = existingTransaction && existingTransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE let optimisticTransaction = TransactionUtils.buildOptimisticTransaction( ReportUtils.isExpenseReport(iouReport) ? -amount : amount, currency, @@ -736,6 +738,7 @@ function getMoneyRequestInformation( category, tag, billable, + isDistanceRequest ? {waypoints: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD} : null, ); const optimisticPolicyRecentlyUsedCategories = Policy.buildOptimisticPolicyRecentlyUsedCategories(iouReport.policyID, category); @@ -747,7 +750,6 @@ function getMoneyRequestInformation( // data. This is a big can of worms to change it to `Onyx.merge()` as explored in https://expensify.slack.com/archives/C05DWUDHVK7/p1692139468252109. // I want to clean this up at some point, but it's possible this will live in the code for a while so I've created https://github.com/Expensify/App/issues/25417 // to remind me to do this. - const existingTransaction = allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`]; if (existingTransaction && existingTransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) { optimisticTransaction = OnyxUtils.fastMerge(existingTransaction, optimisticTransaction); // pendingFields: { diff --git a/src/types/onyx/Transaction.ts b/src/types/onyx/Transaction.ts index 8b7e26280305..a6b65f7cba38 100644 --- a/src/types/onyx/Transaction.ts +++ b/src/types/onyx/Transaction.ts @@ -49,6 +49,8 @@ type Route = { type Routes = Record; +type PendingFieldsCollection = Partial<{[K in keyof Transaction | keyof Comment]: ValueOf}>; + type Transaction = { amount: number; billable: boolean; @@ -76,7 +78,7 @@ type Transaction = { routes?: Routes; transactionID: string; tag: string; - pendingFields?: Partial<{[K in keyof Transaction | keyof Comment]: ValueOf}>; + pendingFields?: PendingFieldsCollection; /** Card Transactions */ @@ -97,4 +99,4 @@ type Transaction = { }; export default Transaction; -export type {WaypointCollection, Comment, Receipt, Waypoint}; +export type {WaypointCollection, Comment, Receipt, Waypoint, PendingFieldsCollection}; From 54a63d643b9ad602ace915090c3c18cae28af5b0 Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 9 Jan 2024 18:07:40 +0530 Subject: [PATCH 019/793] fix lint --- src/components/ReportActionItem/MoneyRequestPreview.js | 2 +- src/components/ReportActionItem/MoneyRequestView.js | 2 +- src/libs/TransactionUtils.ts | 2 +- src/libs/actions/IOU.js | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/ReportActionItem/MoneyRequestPreview.js b/src/components/ReportActionItem/MoneyRequestPreview.js index 9bba3aed205a..84ed317be294 100644 --- a/src/components/ReportActionItem/MoneyRequestPreview.js +++ b/src/components/ReportActionItem/MoneyRequestPreview.js @@ -5,6 +5,7 @@ import React from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; +import ConfirmedRoute from '@components/ConfirmedRoute'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import MoneyRequestSkeletonView from '@components/MoneyRequestSkeletonView'; @@ -38,7 +39,6 @@ import * as Report from '@userActions/Report'; import CONST from '@src/CONST'; import * as Localize from '@src/libs/Localize'; import ONYXKEYS from '@src/ONYXKEYS'; -import ConfirmedRoute from '@components/ConfirmedRoute'; import ReportActionItemImages from './ReportActionItemImages'; const propTypes = { diff --git a/src/components/ReportActionItem/MoneyRequestView.js b/src/components/ReportActionItem/MoneyRequestView.js index fc70b47d7101..04b8d35e3448 100644 --- a/src/components/ReportActionItem/MoneyRequestView.js +++ b/src/components/ReportActionItem/MoneyRequestView.js @@ -5,6 +5,7 @@ import React, {useCallback} from 'react'; import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import categoryPropTypes from '@components/categoryPropTypes'; +import ConfirmedRoute from '@components/ConfirmedRoute'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -42,7 +43,6 @@ import * as IOU from '@userActions/IOU'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import ConfirmedRoute from '@components/ConfirmedRoute'; import ReportActionItemImage from './ReportActionItemImage'; const violationNames = lodashValues(CONST.VIOLATIONS); diff --git a/src/libs/TransactionUtils.ts b/src/libs/TransactionUtils.ts index b8fad803d957..4155fe426f5a 100644 --- a/src/libs/TransactionUtils.ts +++ b/src/libs/TransactionUtils.ts @@ -1,6 +1,5 @@ import lodashHas from 'lodash/has'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; -import type {EmptyObject} from '@src/types/utils/EmptyObject'; import Onyx from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import CONST from '@src/CONST'; @@ -9,6 +8,7 @@ import type {RecentWaypoint, Report, ReportAction, Transaction} from '@src/types import type {PolicyTaxRates} from '@src/types/onyx/PolicyTaxRates'; import type PolicyTaxRate from '@src/types/onyx/PolicyTaxRates'; import type {Comment, PendingFieldsCollection, Receipt, Waypoint, WaypointCollection} from '@src/types/onyx/Transaction'; +import type {EmptyObject} from '@src/types/utils/EmptyObject'; import {isNotEmptyObject} from '@src/types/utils/EmptyObject'; import {isCorporateCard, isExpensifyCard} from './CardUtils'; import DateUtils from './DateUtils'; diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index f4ff83e995c8..f004b44feca2 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -722,7 +722,7 @@ function getMoneyRequestInformation( filename = receipt.name; } const existingTransaction = allTransactionDrafts[`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${CONST.IOU.OPTIMISTIC_TRANSACTION_ID}`]; - const isDistanceRequest = existingTransaction && existingTransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE + const isDistanceRequest = existingTransaction && existingTransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE; let optimisticTransaction = TransactionUtils.buildOptimisticTransaction( ReportUtils.isExpenseReport(iouReport) ? -amount : amount, currency, @@ -752,9 +752,9 @@ function getMoneyRequestInformation( // to remind me to do this. if (existingTransaction && existingTransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) { optimisticTransaction = OnyxUtils.fastMerge(existingTransaction, optimisticTransaction); -// pendingFields: { -// waypoints: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, -// } + // pendingFields: { + // waypoints: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, + // } } // STEP 4: Build optimistic reportActions. We need: From 46141e379c495127f8287f3ca15a771c4eba63df Mon Sep 17 00:00:00 2001 From: Shubham Agrawal Date: Tue, 9 Jan 2024 18:09:37 +0530 Subject: [PATCH 020/793] fix lint --- src/libs/actions/IOU.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libs/actions/IOU.js b/src/libs/actions/IOU.js index f004b44feca2..d68b33e6b5ef 100644 --- a/src/libs/actions/IOU.js +++ b/src/libs/actions/IOU.js @@ -750,11 +750,8 @@ function getMoneyRequestInformation( // data. This is a big can of worms to change it to `Onyx.merge()` as explored in https://expensify.slack.com/archives/C05DWUDHVK7/p1692139468252109. // I want to clean this up at some point, but it's possible this will live in the code for a while so I've created https://github.com/Expensify/App/issues/25417 // to remind me to do this. - if (existingTransaction && existingTransaction.iouRequestType === CONST.IOU.REQUEST_TYPE.DISTANCE) { + if (isDistanceRequest) { optimisticTransaction = OnyxUtils.fastMerge(existingTransaction, optimisticTransaction); - // pendingFields: { - // waypoints: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, - // } } // STEP 4: Build optimistic reportActions. We need: From b7045ec7091f7aba9d94939ea654c3ba5cc59b06 Mon Sep 17 00:00:00 2001 From: Antony Kithinzi Date: Fri, 12 Jan 2024 16:05:21 -0500 Subject: [PATCH 021/793] fix: adding backTo param to ReportParticipantsPage.js --- src/pages/ReportParticipantsPage.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js index 7dbc1c7036c4..9e480d2f0516 100755 --- a/src/pages/ReportParticipantsPage.js +++ b/src/pages/ReportParticipantsPage.js @@ -121,7 +121,12 @@ function ReportParticipantsPage(props) { }, ]} onSelectRow={(option) => { - Navigation.navigate(ROUTES.PROFILE.getRoute(option.accountID)); + Navigation.navigate( + ROUTES.PROFILE.getRoute( + option.accountID, + ROUTES.REPORT_PARTICIPANTS.getRoute(props.report.reportID) + ) + ); }} hideSectionHeaders showTitleTooltip From e7b85131efe677ac38f177262f3c51b512643b82 Mon Sep 17 00:00:00 2001 From: Antony Kithinzi Date: Sat, 13 Jan 2024 04:50:32 +0100 Subject: [PATCH 022/793] fmt: prettier --- src/pages/ReportParticipantsPage.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/pages/ReportParticipantsPage.js b/src/pages/ReportParticipantsPage.js index 9e480d2f0516..3bc2783db981 100755 --- a/src/pages/ReportParticipantsPage.js +++ b/src/pages/ReportParticipantsPage.js @@ -121,12 +121,7 @@ function ReportParticipantsPage(props) { }, ]} onSelectRow={(option) => { - Navigation.navigate( - ROUTES.PROFILE.getRoute( - option.accountID, - ROUTES.REPORT_PARTICIPANTS.getRoute(props.report.reportID) - ) - ); + Navigation.navigate(ROUTES.PROFILE.getRoute(option.accountID, ROUTES.REPORT_PARTICIPANTS.getRoute(props.report.reportID))); }} hideSectionHeaders showTitleTooltip From 02dbc360a4068ba132d3f2af9bd6badd594c0105 Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 15 Jan 2024 13:08:51 +0100 Subject: [PATCH 023/793] fix: move changes to new file --- src/ROUTES.ts | 2 +- src/libs/Navigation/types.ts | 8 + src/pages/iou/MoneyRequestWaypointPage.tsx | 36 ++++ .../NewDistanceRequestWaypointEditorPage.tsx | 52 ----- ...Waypoint.js => IOURequestStepWaypoint.tsx} | 181 +++++++++--------- 5 files changed, 132 insertions(+), 147 deletions(-) create mode 100644 src/pages/iou/MoneyRequestWaypointPage.tsx delete mode 100644 src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx rename src/pages/iou/request/step/{IOURequestStepWaypoint.js => IOURequestStepWaypoint.tsx} (67%) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 37003a09a0cd..4fda2e3ef3da 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -494,4 +494,4 @@ type RouteIsPlainString = IsEqual; */ type Route = RouteIsPlainString extends true ? never : AllRoutes; -export type {Route}; +export type {Route, AllRoutes}; diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 8563db7db172..e044f0b16f33 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -3,6 +3,7 @@ import type {CommonActions, NavigationContainerRefWithCurrent, NavigationHelpers import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; import type NAVIGATORS from '@src/NAVIGATORS'; +import {AllRoutes} from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; type NavigationRef = NavigationContainerRefWithCurrent; @@ -226,6 +227,13 @@ type MoneyRequestNavigatorParamList = { reportID: string; backTo: string; }; + [SCREENS.MONEY_REQUEST.STEP_WAYPOINT]: { + iouType: ValueOf; + reportID: string; + backTo: AllRoutes | undefined; + action: ValueOf; + pageIndex: string; + }; [SCREENS.MONEY_REQUEST.MERCHANT]: { iouType: string; reportID: string; diff --git a/src/pages/iou/MoneyRequestWaypointPage.tsx b/src/pages/iou/MoneyRequestWaypointPage.tsx new file mode 100644 index 000000000000..ce31e58514f5 --- /dev/null +++ b/src/pages/iou/MoneyRequestWaypointPage.tsx @@ -0,0 +1,36 @@ +import type {StackScreenProps} from '@react-navigation/stack'; +import React from 'react'; +import {withOnyx} from 'react-native-onyx'; +import type {MoneyRequestNavigatorParamList} from '@libs/Navigation/types'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type SCREENS from '@src/SCREENS'; +import IOURequestStepWaypoint from './request/step/IOURequestStepWaypoint'; + +type MoneyRequestWaypointPageOnyxProps = { + transactionID: string | undefined; +}; +type MoneyRequestWaypointPageProps = StackScreenProps & MoneyRequestWaypointPageOnyxProps; + +// This component is responsible for grabbing the transactionID from the IOU key +// You can't use Onyx props in the withOnyx mapping, so we need to set up and access the transactionID here, and then pass it down so that WaypointEditor can subscribe to the transaction. +function MoneyRequestWaypointPage({transactionID = '', route}: MoneyRequestWaypointPageProps) { + return ( + // @ts-expect-error TODO: Remove this once withFullTransactionOrNotFound is migrated to TypeScript. + + ); +} + +MoneyRequestWaypointPage.displayName = 'MoneyRequestWaypointPage'; + +export default withOnyx({ + transactionID: {key: ONYXKEYS.IOU, selector: (iou) => iou?.transactionID}, +})(MoneyRequestWaypointPage); diff --git a/src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx b/src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx deleted file mode 100644 index 8456135c6101..000000000000 --- a/src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import type {StackScreenProps} from '@react-navigation/stack'; -import React from 'react'; -import {withOnyx} from 'react-native-onyx'; -import type {MoneyRequestNavigatorParamList} from '@libs/Navigation/types'; -import ONYXKEYS from '@src/ONYXKEYS'; -<<<<<<<< HEAD:src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx -import type SCREENS from '@src/SCREENS'; -import WaypointEditor from './WaypointEditor'; -======== -import IOURequestStepWaypoint from './request/step/IOURequestStepWaypoint'; ->>>>>>>> f268c39c331305c49dbb80a0d0e59984289ecb25:src/pages/iou/MoneyRequestWaypointPage.js - -type NewDistanceRequestWaypointEditorPageOnyxProps = { - transactionID: string | undefined; -}; -type NewDistanceRequestWaypointEditorPageProps = StackScreenProps & NewDistanceRequestWaypointEditorPageOnyxProps; - -// This component is responsible for grabbing the transactionID from the IOU key -// You can't use Onyx props in the withOnyx mapping, so we need to set up and access the transactionID here, and then pass it down so that WaypointEditor can subscribe to the transaction. -<<<<<<<< HEAD:src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx -function NewDistanceRequestWaypointEditorPage({transactionID = '', route}: NewDistanceRequestWaypointEditorPageProps) { -======== -function MoneyRequestWaypointPage({transactionID, route}) { ->>>>>>>> f268c39c331305c49dbb80a0d0e59984289ecb25:src/pages/iou/MoneyRequestWaypointPage.js - return ( - - ); -} - -<<<<<<<< HEAD:src/pages/iou/NewDistanceRequestWaypointEditorPage.tsx -NewDistanceRequestWaypointEditorPage.displayName = 'NewDistanceRequestWaypointEditorPage'; - -export default withOnyx({ - transactionID: {key: ONYXKEYS.IOU, selector: (iou) => iou?.transactionID}, -})(NewDistanceRequestWaypointEditorPage); -======== -MoneyRequestWaypointPage.displayName = 'MoneyRequestWaypointPage'; -MoneyRequestWaypointPage.propTypes = propTypes; -MoneyRequestWaypointPage.defaultProps = defaultProps; -export default withOnyx({ - transactionID: {key: ONYXKEYS.IOU, selector: (iou) => iou && iou.transactionID}, -})(MoneyRequestWaypointPage); ->>>>>>>> f268c39c331305c49dbb80a0d0e59984289ecb25:src/pages/iou/MoneyRequestWaypointPage.js diff --git a/src/pages/iou/request/step/IOURequestStepWaypoint.js b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx similarity index 67% rename from src/pages/iou/request/step/IOURequestStepWaypoint.js rename to src/pages/iou/request/step/IOURequestStepWaypoint.tsx index 1087018eeed9..f03d6299b873 100644 --- a/src/pages/iou/request/step/IOURequestStepWaypoint.js +++ b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx @@ -1,10 +1,10 @@ import {useNavigation} from '@react-navigation/native'; -import lodashGet from 'lodash/get'; -import PropTypes from 'prop-types'; import React, {useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; +import type {TextInput} from 'react-native'; import {withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {OnyxEntry} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; import AddressSearch from '@components/AddressSearch'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import ConfirmModal from '@components/ConfirmModal'; @@ -13,79 +13,76 @@ import InputWrapperWithRef from '@components/Form/InputWrapper'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; import ScreenWrapper from '@components/ScreenWrapper'; -import transactionPropTypes from '@components/transactionPropTypes'; import useLocalize from '@hooks/useLocalize'; import useLocationBias from '@hooks/useLocationBias'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; -import compose from '@libs/compose'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as ValidationUtils from '@libs/ValidationUtils'; import * as Transaction from '@userActions/Transaction'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import type {AllRoutes} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; -import IOURequestStepRoutePropTypes from './IOURequestStepRoutePropTypes'; +import type * as OnyxTypes from '@src/types/onyx'; +import type {Waypoint} from '@src/types/onyx/Transaction'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; -const propTypes = { - /** Navigation route context info provided by react navigation */ - route: IOURequestStepRoutePropTypes.isRequired, +type Location = { + lat?: number; + lng?: number; +}; - /* Onyx props */ - /** The optimistic transaction for this request */ - transaction: transactionPropTypes, +type Geometry = { + location: Location; +}; - /* Current location coordinates of the user */ - userLocation: PropTypes.shape({ - /** Latitude of the location */ - latitude: PropTypes.number, +type WaypointValues = Record; - /** Longitude of the location */ - longitude: PropTypes.number, - }), +type MappedWaypoint = { + /** Waypoint name */ + name?: string; - /** Recent waypoints that the user has selected */ - recentWaypoints: PropTypes.arrayOf( - PropTypes.shape({ - /** The name of the location */ - name: PropTypes.string, + /** Waypoint description */ + description: string; - /** A description of the location (usually the address) */ - description: PropTypes.string, + /** Waypoint geometry object cointaing coordinates */ + geometry: Geometry; +}; - /** Data required by the google auto complete plugin to know where to put the markers on the map */ - geometry: PropTypes.shape({ - /** Data about the location */ - location: PropTypes.shape({ - /** Latitude of the location */ - lat: PropTypes.number, +type IOURequestStepWaypointOnyxProps = { + /** List of recent waypoints */ + recentWaypoints: OnyxEntry; - /** Longitude of the location */ - lng: PropTypes.number, - }), - }), - }), - ), + userLocation: OnyxEntry; }; -const defaultProps = { - recentWaypoints: [], - transaction: {}, - userLocation: undefined, -}; +type IOURequestStepWaypointProps = { + route: { + params: { + iouType: ValueOf; + transactionID: string; + reportID: string; + backTo: AllRoutes | undefined; + action: ValueOf; + pageIndex: string; + }; + }; + transaction: OnyxEntry; +} & IOURequestStepWaypointOnyxProps; function IOURequestStepWaypoint({ - recentWaypoints, route: { params: {action, backTo, iouType, pageIndex, reportID, transactionID}, }, transaction, + recentWaypoints = [], userLocation, -}) { +}: IOURequestStepWaypointProps) { const styles = useThemeStyles(); const {windowWidth} = useWindowDimensions(); const [isDeleteStopModalOpen, setIsDeleteStopModalOpen] = useState(false); @@ -93,12 +90,12 @@ function IOURequestStepWaypoint({ const isFocused = navigation.isFocused(); const {translate} = useLocalize(); const {isOffline} = useNetwork(); - const textInput = useRef(null); + const textInput = useRef(null); const parsedWaypointIndex = parseInt(pageIndex, 10); - const allWaypoints = lodashGet(transaction, 'comment.waypoints', {}); - const currentWaypoint = lodashGet(allWaypoints, `waypoint${pageIndex}`, {}); - const waypointCount = _.size(allWaypoints); - const filledWaypointCount = _.size(_.filter(allWaypoints, (waypoint) => !_.isEmpty(waypoint))); + const allWaypoints = transaction?.comment.waypoints ?? {}; + const currentWaypoint = allWaypoints[`waypoint${pageIndex}`] ?? {}; + const waypointCount = Object.keys(allWaypoints).length; + const filledWaypointCount = Object.values(allWaypoints).filter((waypoint) => !isEmptyObject(waypoint)).length; const waypointDescriptionKey = useMemo(() => { switch (parsedWaypointIndex) { @@ -112,14 +109,14 @@ function IOURequestStepWaypoint({ }, [parsedWaypointIndex, waypointCount]); const locationBias = useLocationBias(allWaypoints, userLocation); - const waypointAddress = lodashGet(currentWaypoint, 'address', ''); + const waypointAddress = currentWaypoint.address ?? ''; // Hide the menu when there is only start and finish waypoint const shouldShowThreeDotsButton = waypointCount > 2; const shouldDisableEditor = isFocused && (Number.isNaN(parsedWaypointIndex) || parsedWaypointIndex < 0 || parsedWaypointIndex > waypointCount || (filledWaypointCount < 2 && parsedWaypointIndex >= waypointCount)); - const validate = (values) => { + const validate = (values: WaypointValues): ErrorUtils.ErrorsList => { const errors = {}; const waypointValue = values[`waypoint${pageIndex}`] || ''; if (isOffline && waypointValue !== '' && !ValidationUtils.isValidAddress(waypointValue)) { @@ -135,9 +132,9 @@ function IOURequestStepWaypoint({ return errors; }; - const saveWaypoint = (waypoint) => Transaction.saveWaypoint(transactionID, pageIndex, waypoint, action === CONST.IOU.ACTION.CREATE); + const saveWaypoint = (waypoint: OnyxTypes.RecentWaypoint) => Transaction.saveWaypoint(transactionID, pageIndex, waypoint, action === CONST.IOU.ACTION.CREATE); - const submit = (values) => { + const submit = (values: WaypointValues) => { const waypointValue = values[`waypoint${pageIndex}`] || ''; // Allows letting you set a waypoint to an empty value @@ -149,10 +146,8 @@ function IOURequestStepWaypoint({ // Therefore, we're going to save the waypoint as just the address, and the lat/long will be filled in on the backend if (isOffline && waypointValue) { const waypoint = { - lat: null, - lng: null, address: waypointValue, - name: values.name || null, + name: values.name, }; saveWaypoint(waypoint); } @@ -167,18 +162,12 @@ function IOURequestStepWaypoint({ Navigation.goBack(ROUTES.MONEY_REQUEST_DISTANCE_TAB.getRoute(iouType)); }; - /** - * @param {Object} values - * @param {String} values.lat - * @param {String} values.lng - * @param {String} values.address - */ - const selectWaypoint = (values) => { + const selectWaypoint = (values: Waypoint) => { const waypoint = { lat: values.lat, lng: values.lng, - address: values.address, - name: values.name || null, + address: values.address ?? '', + name: values.name, }; Transaction.saveWaypoint(transactionID, pageIndex, waypoint, action === CONST.IOU.ACTION.CREATE); if (backTo) { @@ -191,7 +180,7 @@ function IOURequestStepWaypoint({ return ( textInput.current && textInput.current.focus()} + onEntryTransitionEnd={() => textInput.current?.focus()} shouldEnableMaxHeight testID={IOURequestStepWaypoint.displayName} > @@ -222,6 +211,7 @@ function IOURequestStepWaypoint({ cancelText={translate('common.cancel')} danger /> + {/* @ts-expect-error TODO: Remove this once Form (https://github.com/Expensify/App/issues/25109) is migrated to TypeScript. */} (textInput.current = e)} + ref={(e) => { + textInput.current = e; + }} hint={!isOffline ? 'distance.errors.selectSuggestedAddress' : ''} containerStyles={[styles.mt4]} label={translate('distance.address')} @@ -267,32 +260,32 @@ function IOURequestStepWaypoint({ } IOURequestStepWaypoint.displayName = 'IOURequestStepWaypoint'; -IOURequestStepWaypoint.propTypes = propTypes; -IOURequestStepWaypoint.defaultProps = defaultProps; -export default compose( - withWritableReportOrNotFound, - withFullTransactionOrNotFound, - withOnyx({ - userLocation: { - key: ONYXKEYS.USER_LOCATION, - }, - recentWaypoints: { - key: ONYXKEYS.NVP_RECENT_WAYPOINTS, +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepWaypointWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepWaypoint); +// eslint-disable-next-line rulesdir/no-negated-variables +const IOURequestStepWaypointWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepWaypointWithWritableReportOrNotFound); - // Only grab the most recent 5 waypoints because that's all that is shown in the UI. This also puts them into the format of data - // that the google autocomplete component expects for it's "predefined places" feature. - selector: (waypoints) => - _.map(waypoints ? waypoints.slice(0, 5) : [], (waypoint) => ({ - name: waypoint.name, - description: waypoint.address, - geometry: { - location: { - lat: waypoint.lat, - lng: waypoint.lng, - }, +export default withOnyx({ + userLocation: { + key: ONYXKEYS.USER_LOCATION, + }, + recentWaypoints: { + key: ONYXKEYS.NVP_RECENT_WAYPOINTS, + + // Only grab the most recent 5 waypoints because that's all that is shown in the UI. This also puts them into the format of data + // that the google autocomplete component expects for it's "predefined places" feature. + selector: (waypoints) => + (waypoints ? waypoints.slice(0, 5) : []).map((waypoint) => ({ + name: waypoint.name, + description: waypoint.address, + geometry: { + location: { + lat: waypoint.lat, + lng: waypoint.lng, }, - })), - }, - }), -)(IOURequestStepWaypoint); + }, + })), + }, + // @ts-expect-error TODO: Remove this once withFullTransactionOrNotFound and IOURequestStepWaypointWithWritableReportOrNotFound is migrated to TypeScript. +})(IOURequestStepWaypointWithFullTransactionOrNotFound); From e6164a2c0561f9cd1497289e558a3cc13acc56ce Mon Sep 17 00:00:00 2001 From: Jakub Butkiewicz Date: Mon, 15 Jan 2024 13:30:46 +0100 Subject: [PATCH 024/793] fix: type errors --- src/hooks/useLocationBias.ts | 2 +- src/libs/Navigation/types.ts | 2 +- src/libs/actions/Transaction.ts | 5 ++++- src/pages/iou/MoneyRequestEditWaypointPage.tsx | 15 --------------- .../iou/request/step/IOURequestStepWaypoint.tsx | 2 ++ 5 files changed, 8 insertions(+), 18 deletions(-) delete mode 100644 src/pages/iou/MoneyRequestEditWaypointPage.tsx diff --git a/src/hooks/useLocationBias.ts b/src/hooks/useLocationBias.ts index 607b1bfbc0d2..9efd13298bbb 100644 --- a/src/hooks/useLocationBias.ts +++ b/src/hooks/useLocationBias.ts @@ -1,6 +1,6 @@ import {useMemo} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import type {Location} from '@pages/iou/WaypointEditor'; +import type {Location} from '@pages/iou/request/step/IOURequestStepWaypoint'; import type {UserLocation} from '@src/types/onyx'; /** diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index e044f0b16f33..24cf74562047 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -3,7 +3,7 @@ import type {CommonActions, NavigationContainerRefWithCurrent, NavigationHelpers import type {ValueOf} from 'type-fest'; import type CONST from '@src/CONST'; import type NAVIGATORS from '@src/NAVIGATORS'; -import {AllRoutes} from '@src/ROUTES'; +import type {AllRoutes} from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; type NavigationRef = NavigationContainerRefWithCurrent; diff --git a/src/libs/actions/Transaction.ts b/src/libs/actions/Transaction.ts index 5f2e1186ec32..90d557188238 100644 --- a/src/libs/actions/Transaction.ts +++ b/src/libs/actions/Transaction.ts @@ -102,6 +102,9 @@ function saveWaypoint(transactionID: string, index: string, waypoint: RecentWayp } function removeWaypoint(transaction: OnyxEntry, currentIndex: string, isDraft?: boolean) { + if (!transaction) { + return; + } // Index comes from the route params and is a string const index = Number(currentIndex); const existingWaypoints = transaction?.comment?.waypoints ?? {}; @@ -130,7 +133,7 @@ function removeWaypoint(transaction: OnyxEntry, currentIndex: strin // Doing a deep clone of the transaction to avoid mutating the original object and running into a cache issue when using Onyx.set let newTransaction: Transaction = { // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style - ...(transaction as Transaction), + ...transaction, comment: { ...transaction?.comment, waypoints: reIndexedWaypoints, diff --git a/src/pages/iou/MoneyRequestEditWaypointPage.tsx b/src/pages/iou/MoneyRequestEditWaypointPage.tsx deleted file mode 100644 index 478b076e1991..000000000000 --- a/src/pages/iou/MoneyRequestEditWaypointPage.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import type {StackScreenProps} from '@react-navigation/stack'; -import React from 'react'; -import type {MoneyRequestNavigatorParamList} from '@libs/Navigation/types'; -import type SCREENS from '@src/SCREENS'; -import WaypointEditor from './WaypointEditor'; - -type MoneyRequestEditWaypointPageProps = StackScreenProps; - -function MoneyRequestEditWaypointPage({route}: MoneyRequestEditWaypointPageProps) { - return ; -} - -MoneyRequestEditWaypointPage.displayName = 'MoneyRequestEditWaypointPage'; - -export default MoneyRequestEditWaypointPage; diff --git a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx index f03d6299b873..ff6ec5d5f25c 100644 --- a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx +++ b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx @@ -289,3 +289,5 @@ export default withOnyx Date: Mon, 15 Jan 2024 17:41:10 +0100 Subject: [PATCH 025/793] fix: types --- src/pages/iou/request/step/IOURequestStepWaypoint.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx index ff6ec5d5f25c..675b2f0b2c68 100644 --- a/src/pages/iou/request/step/IOURequestStepWaypoint.tsx +++ b/src/pages/iou/request/step/IOURequestStepWaypoint.tsx @@ -24,7 +24,7 @@ import * as ValidationUtils from '@libs/ValidationUtils'; import * as Transaction from '@userActions/Transaction'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {AllRoutes} from '@src/ROUTES'; +import type {Route as Routes} from '@src/ROUTES'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import type {Waypoint} from '@src/types/onyx/Transaction'; @@ -67,7 +67,7 @@ type IOURequestStepWaypointProps = { iouType: ValueOf; transactionID: string; reportID: string; - backTo: AllRoutes | undefined; + backTo: Routes | undefined; action: ValueOf; pageIndex: string; }; From a7fbd9777e99eed5b7c32262fa72dde8f9964c7c Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 18 Jan 2024 16:47:56 +0700 Subject: [PATCH 026/793] TS migration SettingsWallet --- src/components/BigNumberPad.tsx | 2 +- ...tPage.js => ChooseTransferAccountPage.tsx} | 63 ++++++++---------- ...otCardSection.js => RedDotCardSection.tsx} | 12 ++-- ...Page.js => ReportVirtualCardFraudPage.tsx} | 65 +++++++++---------- .../Wallet/walletTransferPropTypes.js | 16 ----- src/types/onyx/Fund.ts | 2 +- 6 files changed, 63 insertions(+), 97 deletions(-) rename src/pages/settings/Wallet/{ChooseTransferAccountPage.js => ChooseTransferAccountPage.tsx} (51%) rename src/pages/settings/Wallet/{RedDotCardSection.js => RedDotCardSection.tsx} (76%) rename src/pages/settings/Wallet/{ReportVirtualCardFraudPage.js => ReportVirtualCardFraudPage.tsx} (60%) delete mode 100644 src/pages/settings/Wallet/walletTransferPropTypes.js diff --git a/src/components/BigNumberPad.tsx b/src/components/BigNumberPad.tsx index 8b840f9d1b57..adefb78a66c7 100644 --- a/src/components/BigNumberPad.tsx +++ b/src/components/BigNumberPad.tsx @@ -17,7 +17,7 @@ type BigNumberPadProps = { id?: string; /** Whether long press is disabled */ - isLongPressDisabled: boolean; + isLongPressDisabled?: boolean; }; const padNumbers = [ diff --git a/src/pages/settings/Wallet/ChooseTransferAccountPage.js b/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx similarity index 51% rename from src/pages/settings/Wallet/ChooseTransferAccountPage.js rename to src/pages/settings/Wallet/ChooseTransferAccountPage.tsx index 815d2e883cf0..d938ca78117c 100644 --- a/src/pages/settings/Wallet/ChooseTransferAccountPage.js +++ b/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx @@ -1,43 +1,39 @@ import React from 'react'; -import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; +import {GestureResponderEvent, View} from 'react-native'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItem from '@components/MenuItem'; import ScreenWrapper from '@components/ScreenWrapper'; -import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; +import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import compose from '@libs/compose'; import Navigation from '@libs/Navigation/Navigation'; import * as BankAccounts from '@userActions/BankAccounts'; import * as PaymentMethods from '@userActions/PaymentMethods'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import type {AccountData as BankAccountData, WalletTransfer} from '@src/types/onyx'; +import type {AccountData as FundAccountData} from '@src/types/onyx/Fund'; import PaymentMethodList from './PaymentMethodList'; -import walletTransferPropTypes from './walletTransferPropTypes'; -const propTypes = { - /** Wallet transfer propTypes */ - walletTransfer: walletTransferPropTypes, - - ...withLocalizePropTypes, +type ChooseTransferAccountPageOnyxProps = { + walletTransfer: OnyxEntry; }; -const defaultProps = { - walletTransfer: {}, -}; +type ChooseTransferAccountPageProps = ChooseTransferAccountPageOnyxProps & {}; -function ChooseTransferAccountPage(props) { +function ChooseTransferAccountPage({walletTransfer = {}}: ChooseTransferAccountPageProps) { const styles = useThemeStyles(); + const {translate} = useLocalize(); /** * Go back to transfer balance screen with the selected bank account set - * @param {Object} event Click event object - * @param {String} accountType of the selected account type - * @param {Object} account of the selected account data */ - const selectAccountAndNavigateBack = (event, accountType, account) => { - PaymentMethods.saveWalletTransferAccountTypeAndID(accountType, accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT ? account.bankAccountID : account.fundID); + const selectAccountAndNavigateBack = (event: GestureResponderEvent | KeyboardEvent, accountType: string, account: BankAccountData | FundAccountData) => { + PaymentMethods.saveWalletTransferAccountTypeAndID( + accountType, + (accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT ? (account as BankAccountData)?.bankAccountID?.toString() : (account as FundAccountData)?.fundID?.toString()) ?? '', + ); Navigation.goBack(ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE); }; @@ -45,7 +41,7 @@ function ChooseTransferAccountPage(props) { * @param {String} paymentType */ const navigateToAddPaymentMethodPage = () => { - if (props.walletTransfer.filterPaymentMethodType === CONST.PAYMENT_METHODS.DEBIT_CARD) { + if (walletTransfer?.filterPaymentMethodType === CONST.PAYMENT_METHODS.DEBIT_CARD) { Navigation.navigate(ROUTES.SETTINGS_ADD_DEBIT_CARD); return; } @@ -55,24 +51,24 @@ function ChooseTransferAccountPage(props) { return ( Navigation.goBack(ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE)} /> @@ -80,15 +76,10 @@ function ChooseTransferAccountPage(props) { ); } -ChooseTransferAccountPage.propTypes = propTypes; -ChooseTransferAccountPage.defaultProps = defaultProps; ChooseTransferAccountPage.displayName = 'ChooseTransferAccountPage'; -export default compose( - withLocalize, - withOnyx({ - walletTransfer: { - key: ONYXKEYS.WALLET_TRANSFER, - }, - }), -)(ChooseTransferAccountPage); +export default withOnyx({ + walletTransfer: { + key: ONYXKEYS.WALLET_TRANSFER, + }, +})(ChooseTransferAccountPage); diff --git a/src/pages/settings/Wallet/RedDotCardSection.js b/src/pages/settings/Wallet/RedDotCardSection.tsx similarity index 76% rename from src/pages/settings/Wallet/RedDotCardSection.js rename to src/pages/settings/Wallet/RedDotCardSection.tsx index 7025cf7bf1a2..29acf7489fc7 100644 --- a/src/pages/settings/Wallet/RedDotCardSection.js +++ b/src/pages/settings/Wallet/RedDotCardSection.tsx @@ -1,4 +1,3 @@ -import PropTypes from 'prop-types'; import React from 'react'; import {View} from 'react-native'; import Icon from '@components/Icon'; @@ -7,12 +6,12 @@ import Text from '@components/Text'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -const propTypes = { - title: PropTypes.string.isRequired, - description: PropTypes.string.isRequired, +type RedDotCardSectionProps = { + title: string; + description: string; }; -function RedDotCardSection({title, description}) { +function RedDotCardSection({title, description}: RedDotCardSectionProps) { const theme = useTheme(); const styles = useThemeStyles(); @@ -27,14 +26,13 @@ function RedDotCardSection({title, description}) { {title} - {description} + {description} ); } -RedDotCardSection.propTypes = propTypes; RedDotCardSection.displayName = 'RedDotCardSection'; export default RedDotCardSection; diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.js b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx similarity index 60% rename from src/pages/settings/Wallet/ReportVirtualCardFraudPage.js rename to src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx index fa88e01d8b41..6570fe804927 100644 --- a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.js +++ b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx @@ -1,7 +1,8 @@ -import PropTypes from 'prop-types'; +import type {RouteProp} from '@react-navigation/native'; +import isEmpty from 'lodash/isEmpty'; import React, {useEffect} from 'react'; import {View} from 'react-native'; -import {withOnyx} from 'react-native-onyx'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -17,57 +18,51 @@ import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import * as Card from '@userActions/Card'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import assignedCardPropTypes from './assignedCardPropTypes'; +import type {Route} from '@src/ROUTES'; +import type {Form, Card as OnyxCard} from '@src/types/onyx'; -const propTypes = { - /* Onyx Props */ - formData: PropTypes.shape({ - isLoading: PropTypes.bool, - }), - cardList: PropTypes.objectOf(assignedCardPropTypes), - /** The parameters needed to authenticate with a short-lived token are in the URL */ - route: PropTypes.shape({ - /** Each parameter passed via the URL */ - params: PropTypes.shape({ - /** Domain string */ - domain: PropTypes.string, - }), - }).isRequired, +type ReportVirtualCardFraudPageOnyxProps = { + formData: OnyxEntry
; + cardList: OnyxEntry>; }; -const defaultProps = { - cardList: {}, - formData: {}, +type ReportVirtualCardFraudPageProps = ReportVirtualCardFraudPageOnyxProps & { + /** + * The parameters needed to authenticate with a short-lived token are in the URL + * Each parameter passed via the URL + * Domain string + */ + route: RouteProp<{params: {domain: Route}}>; }; function ReportVirtualCardFraudPage({ route: { params: {domain}, }, - cardList, - formData, -}) { + cardList = {}, + formData = {}, +}: ReportVirtualCardFraudPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const domainCards = CardUtils.getDomainCards(cardList)[domain]; - const virtualCard = _.find(domainCards, (card) => card.isVirtual) || {}; - const virtualCardError = ErrorUtils.getLatestErrorMessage(virtualCard) || ''; + const domainCards = CardUtils.getDomainCards(cardList ?? {})[domain]; + const virtualCard = domainCards.find((card) => card.isVirtual); + const virtualCardError = ErrorUtils.getLatestErrorMessage(virtualCard?.errors ?? {}) || ''; - const prevIsLoading = usePrevious(formData.isLoading); + const prevIsLoading = usePrevious(formData?.isLoading); useEffect(() => { - if (!prevIsLoading || formData.isLoading) { + if (!prevIsLoading || formData?.isLoading) { return; } - if (!_.isEmpty(virtualCard.errors)) { + if (!isEmpty(virtualCard?.errors)) { return; } Navigation.navigate(ROUTES.SETTINGS_WALLET_DOMAINCARD.getRoute(domain)); - }, [domain, formData.isLoading, prevIsLoading, virtualCard.errors]); + }, [domain, formData?.isLoading, prevIsLoading, virtualCard?.errors]); - if (_.isEmpty(virtualCard)) { + if (isEmpty(virtualCard)) { return ; } @@ -78,12 +73,12 @@ function ReportVirtualCardFraudPage({ onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_WALLET_DOMAINCARD.getRoute(domain))} /> - {translate('reportFraudPage.description')} + {translate('reportFraudPage.description')} Card.reportVirtualExpensifyCardFraud(virtualCard.cardID)} message={virtualCardError} - isLoading={formData.isLoading} + isLoading={formData?.isLoading} buttonText={translate('reportFraudPage.deactivateCard')} /> @@ -91,11 +86,9 @@ function ReportVirtualCardFraudPage({ ); } -ReportVirtualCardFraudPage.propTypes = propTypes; -ReportVirtualCardFraudPage.defaultProps = defaultProps; ReportVirtualCardFraudPage.displayName = 'ReportVirtualCardFraudPage'; -export default withOnyx({ +export default withOnyx({ cardList: { key: ONYXKEYS.CARD_LIST, }, diff --git a/src/pages/settings/Wallet/walletTransferPropTypes.js b/src/pages/settings/Wallet/walletTransferPropTypes.js deleted file mode 100644 index 9e25213382e9..000000000000 --- a/src/pages/settings/Wallet/walletTransferPropTypes.js +++ /dev/null @@ -1,16 +0,0 @@ -import PropTypes from 'prop-types'; -import CONST from '@src/CONST'; - -/** Wallet balance transfer props */ -const walletTransferPropTypes = PropTypes.shape({ - /** Selected accountID for transfer */ - selectedAccountID: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - - /** Type to filter the payment Method list */ - filterPaymentMethodType: PropTypes.oneOf([CONST.PAYMENT_METHODS.DEBIT_CARD, CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT, '']), - - /** Whether the success screen is shown to user. */ - shouldShowSuccess: PropTypes.bool, -}); - -export default walletTransferPropTypes; diff --git a/src/types/onyx/Fund.ts b/src/types/onyx/Fund.ts index 842a882ff23f..3073172a5eec 100644 --- a/src/types/onyx/Fund.ts +++ b/src/types/onyx/Fund.ts @@ -40,4 +40,4 @@ type Fund = { type FundList = Record; export default Fund; -export type {FundList}; +export type {AccountData, FundList}; From 47ea3acf32da429e1aad1d193effffe614fd4ace Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 18 Jan 2024 17:59:08 +0700 Subject: [PATCH 027/793] use StackScreenProps type --- src/libs/Navigation/types.ts | 1 + .../Wallet/ReportVirtualCardFraudPage.tsx | 25 ++++++++----------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 8d227fa6f697..a3c963729adf 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -384,6 +384,7 @@ type PublicScreensParamList = { shortLivedAuthToken?: string; shortLivedToken?: string; exitTo?: Routes; + domain?: Routes; }; [SCREENS.VALIDATE_LOGIN]: { accountID: string; diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx index 6570fe804927..d72f6c5ac35e 100644 --- a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx +++ b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx @@ -1,5 +1,4 @@ -import type {RouteProp} from '@react-navigation/native'; -import isEmpty from 'lodash/isEmpty'; +import type {StackScreenProps} from '@react-navigation/stack'; import React, {useEffect} from 'react'; import {View} from 'react-native'; import {OnyxEntry, withOnyx} from 'react-native-onyx'; @@ -14,30 +13,28 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as CardUtils from '@libs/CardUtils'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; +import type {PublicScreensParamList} from '@libs/Navigation/types'; import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import * as Card from '@userActions/Card'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import type {Route} from '@src/ROUTES'; +import type SCREENS from '@src/SCREENS'; import type {Form, Card as OnyxCard} from '@src/types/onyx'; +import {isEmptyObject} from '@src/types/utils/EmptyObject'; type ReportVirtualCardFraudPageOnyxProps = { + /** Form data propTypes */ formData: OnyxEntry; + + /** Card list propTypes */ cardList: OnyxEntry>; }; -type ReportVirtualCardFraudPageProps = ReportVirtualCardFraudPageOnyxProps & { - /** - * The parameters needed to authenticate with a short-lived token are in the URL - * Each parameter passed via the URL - * Domain string - */ - route: RouteProp<{params: {domain: Route}}>; -}; +type ReportVirtualCardFraudPageProps = ReportVirtualCardFraudPageOnyxProps & StackScreenProps; function ReportVirtualCardFraudPage({ route: { - params: {domain}, + params: {domain = ''}, }, cardList = {}, formData = {}, @@ -55,14 +52,14 @@ function ReportVirtualCardFraudPage({ if (!prevIsLoading || formData?.isLoading) { return; } - if (!isEmpty(virtualCard?.errors)) { + if (!isEmptyObject(virtualCard?.errors)) { return; } Navigation.navigate(ROUTES.SETTINGS_WALLET_DOMAINCARD.getRoute(domain)); }, [domain, formData?.isLoading, prevIsLoading, virtualCard?.errors]); - if (isEmpty(virtualCard)) { + if (isEmptyObject(virtualCard)) { return ; } From 9506d82a6a9e9a74db2b59ff20a851c7241171fe Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 18 Jan 2024 17:59:50 +0700 Subject: [PATCH 028/793] add commen --- src/pages/settings/Wallet/ChooseTransferAccountPage.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx b/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx index d938ca78117c..fd06bf13302d 100644 --- a/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx +++ b/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx @@ -18,10 +18,11 @@ import type {AccountData as FundAccountData} from '@src/types/onyx/Fund'; import PaymentMethodList from './PaymentMethodList'; type ChooseTransferAccountPageOnyxProps = { + /** Wallet transfer propTypes */ walletTransfer: OnyxEntry; }; -type ChooseTransferAccountPageProps = ChooseTransferAccountPageOnyxProps & {}; +type ChooseTransferAccountPageProps = ChooseTransferAccountPageOnyxProps; function ChooseTransferAccountPage({walletTransfer = {}}: ChooseTransferAccountPageProps) { const styles = useThemeStyles(); @@ -37,9 +38,6 @@ function ChooseTransferAccountPage({walletTransfer = {}}: ChooseTransferAccountP Navigation.goBack(ROUTES.SETTINGS_WALLET_TRANSFER_BALANCE); }; - /** - * @param {String} paymentType - */ const navigateToAddPaymentMethodPage = () => { if (walletTransfer?.filterPaymentMethodType === CONST.PAYMENT_METHODS.DEBIT_CARD) { Navigation.navigate(ROUTES.SETTINGS_ADD_DEBIT_CARD); From a15c596e8d2eb2895c2c08e1855e5354a64b38e5 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 18 Jan 2024 18:16:04 +0700 Subject: [PATCH 029/793] fix lint --- src/pages/settings/Wallet/ChooseTransferAccountPage.tsx | 6 ++++-- src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx b/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx index fd06bf13302d..ff45ca4be548 100644 --- a/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx +++ b/src/pages/settings/Wallet/ChooseTransferAccountPage.tsx @@ -1,6 +1,8 @@ import React from 'react'; -import {GestureResponderEvent, View} from 'react-native'; -import {OnyxEntry, withOnyx} from 'react-native-onyx'; +import type {GestureResponderEvent} from 'react-native'; +import {View} from 'react-native'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItem from '@components/MenuItem'; diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx index d72f6c5ac35e..9b18dfacf8c2 100644 --- a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx +++ b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx @@ -1,8 +1,8 @@ import type {StackScreenProps} from '@react-navigation/stack'; import React, {useEffect} from 'react'; import {View} from 'react-native'; -import {OnyxEntry, withOnyx} from 'react-native-onyx'; -import _ from 'underscore'; +import type {OnyxEntry} from 'react-native-onyx'; +import {withOnyx} from 'react-native-onyx'; import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; From b8485107464dd76efa0ab34a0d5f7c59b105e422 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 18 Jan 2024 18:17:43 +0700 Subject: [PATCH 030/793] TS migrate ActivatePhysicalCardPage --- .../Wallet/ActivatePhysicalCardPage.tsx | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx diff --git a/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx new file mode 100644 index 000000000000..85111b606d55 --- /dev/null +++ b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx @@ -0,0 +1,166 @@ +import type {StackScreenProps} from '@react-navigation/stack'; +import React, {useCallback, useEffect, useRef, useState} from 'react'; +import {View} from 'react-native'; +import {OnyxEntry, withOnyx} from 'react-native-onyx'; +import BigNumberPad from '@components/BigNumberPad'; +import Button from '@components/Button'; +import IllustratedHeaderPageLayout from '@components/IllustratedHeaderPageLayout'; +import LottieAnimations from '@components/LottieAnimations'; +import MagicCodeInput from '@components/MagicCodeInput'; +import Text from '@components/Text'; +import useLocalize from '@hooks/useLocalize'; +import useNetwork from '@hooks/useNetwork'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import useWindowDimensions from '@hooks/useWindowDimensions'; +import * as CardUtils from '@libs/CardUtils'; +import * as DeviceCapabilities from '@libs/DeviceCapabilities'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import Navigation from '@libs/Navigation/Navigation'; +import type {PublicScreensParamList} from '@libs/Navigation/types'; +import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; +import * as CardSettings from '@userActions/Card'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; +import SCREENS from '@src/SCREENS'; +import type {Card} from '@src/types/onyx'; +import { isEmptyObject } from '@src/types/utils/EmptyObject'; + +type ActivatePhysicalCardPageOnyxProps = { + /** Card list propTypes */ + cardList: OnyxEntry>; +}; + +type ActivatePhysicalCardPageProps = ActivatePhysicalCardPageOnyxProps & StackScreenProps; + +const LAST_FOUR_DIGITS_LENGTH = 4; +const MAGIC_INPUT_MIN_HEIGHT = 86; + +function ActivatePhysicalCardPage({ + cardList = {}, + route: { + params: {domain = ''}, + }, +}: ActivatePhysicalCardPageProps) { + const theme = useTheme(); + const styles = useThemeStyles(); + const {isExtraSmallScreenHeight} = useWindowDimensions(); + const {translate} = useLocalize(); + const {isOffline} = useNetwork(); + + const [formError, setFormError] = useState(''); + const [lastFourDigits, setLastFourDigits] = useState(''); + const [lastPressedDigit, setLastPressedDigit] = useState(''); + + const domainCards = CardUtils.getDomainCards(cardList ?? {})[domain]; + const physicalCard = domainCards.find((card) => card.isVirtual); + const cardID = physicalCard?.cardID ?? 0; + const cardError = ErrorUtils.getLatestErrorMessage(physicalCard ?? {}); + + const activateCardCodeInputRef = useRef(null); + + /** + * If state of the card is CONST.EXPENSIFY_CARD.STATE.OPEN, navigate to card details screen. + */ + useEffect(() => { + if (physicalCard?.isLoading || (cardList && cardList[cardID]?.state !== CONST.EXPENSIFY_CARD.STATE.OPEN)) { + return; + } + + Navigation.navigate(ROUTES.SETTINGS_WALLET_DOMAINCARD.getRoute(domain)); + }, [cardID, cardList, domain, physicalCard?.isLoading]); + + useEffect( + () => () => { + CardSettings.clearCardListErrors(cardID); + }, + [cardID], + ); + + /** + * Update lastPressedDigit with value that was pressed on BigNumberPad. + * + * NOTE: If the same digit is pressed twice in a row, append it to the end of the string + * so that useEffect inside MagicCodeInput will be triggered by artificial change of the value. + */ + const updateLastPressedDigit = useCallback((key: string) => setLastPressedDigit(lastPressedDigit === key ? lastPressedDigit + key : key), [lastPressedDigit]); + + /** + * Handle card activation code input + */ + const onCodeInput = (text: string) => { + setFormError(''); + + if (cardError) { + CardSettings.clearCardListErrors(cardID); + } + + setLastFourDigits(text); + }; + + const submitAndNavigateToNextPage = useCallback(() => { + // @ts-expect-error TODO: Remove this once MagicCodeInput (https://github.com/Expensify/App/issues/25078) is migrated to TypeScript. + activateCardCodeInputRef.current?.blur(); + + if (lastFourDigits.replace(CONST.MAGIC_CODE_EMPTY_CHAR, '').length !== LAST_FOUR_DIGITS_LENGTH) { + setFormError(translate('activateCardPage.error.thatDidntMatch')); + return; + } + + CardSettings.activatePhysicalExpensifyCard(lastFourDigits, cardID); + }, [lastFourDigits, cardID, translate]); + + if (isEmptyObject(physicalCard)) { + return ; + } + + return ( + Navigation.navigate(ROUTES.SETTINGS_WALLET_DOMAINCARD.getRoute(domain))} + backgroundColor={theme.PAGE_THEMES[SCREENS.SETTINGS.PREFERENCES.ROOT].backgroundColor} + illustration={LottieAnimations.Magician} + scrollViewContainerStyles={[styles.mnh100]} + childrenContainerStyles={[styles.flex1]} + > + {translate('activateCardPage.pleaseEnterLastFour')} + + + + + {DeviceCapabilities.canUseTouchScreen() && } + +