From f7baac5ff460687951443965c2a38323c42bd2c9 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 10 Sep 2024 16:20:14 +0300 Subject: [PATCH 01/73] change manager id optimistically for advanced approval --- src/libs/actions/IOU.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 32e3575f6686..a1b0a660c0a2 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -42,6 +42,7 @@ import Navigation from '@libs/Navigation/Navigation'; import * as NextStepUtils from '@libs/NextStepUtils'; import {rand64} from '@libs/NumberUtils'; import * as OptionsListUtils from '@libs/OptionsListUtils'; +import {getAccountIDsByLogins} from '@libs/PersonalDetailsUtils'; import * as PhoneNumber from '@libs/PhoneNumber'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; @@ -6926,6 +6927,8 @@ function approveMoneyRequest(expenseReport: OnyxEntry, full?: const predictedNextStatus = isLastApprover(approvalChain) ? CONST.REPORT.STATUS_NUM.APPROVED : CONST.REPORT.STATUS_NUM.SUBMITTED; const predictedNextState = isLastApprover(approvalChain) ? CONST.REPORT.STATE_NUM.APPROVED : CONST.REPORT.STATE_NUM.SUBMITTED; + const currentUserApprovalIndex = approvalChain.indexOf(currentUserEmail); + const managerID = isLastApprover(approvalChain) || currentUserApprovalIndex === -1 ? expenseReport?.managerID : getAccountIDsByLogins([approvalChain[currentUserApprovalIndex + 1]])[0]; const optimisticNextStep = NextStepUtils.buildNextStep(expenseReport, predictedNextStatus); const chatReport = ReportUtils.getReportOrDraftReport(expenseReport?.chatReportID); @@ -6949,6 +6952,7 @@ function approveMoneyRequest(expenseReport: OnyxEntry, full?: lastMessageHtml: ReportActionsUtils.getReportActionHtml(optimisticApprovedReportAction), stateNum: predictedNextState, statusNum: predictedNextStatus, + managerID, pendingFields: { partial: full ? null : CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, }, From 021d61eff89b0231ee8c0cd0a04245fdea373879 Mon Sep 17 00:00:00 2001 From: Anusha Date: Fri, 13 Sep 2024 02:22:02 +0500 Subject: [PATCH 02/73] fix invoice category --- src/libs/ReportUtils.ts | 1 + src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 0e7418a306af..5245d96378b4 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -458,6 +458,7 @@ type OptionData = { tabIndex?: 0 | -1; isConciergeChat?: boolean; isBold?: boolean; + isSender?: boolean; } & Report; type OnyxDataTaskAssigneeChat = { diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 6c1457abef62..5db903a2d905 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -168,6 +168,10 @@ function IOURequestStepConfirmation({ if (policyExpenseChat?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { openDraftWorkspaceRequest(policyExpenseChat.policyID); } + const isSender = participants?.find((participant) => participant.isSender); + if (isSender?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { + openDraftWorkspaceRequest(isSender.policyID); + } }, [isOffline, participants, transaction?.billable, policy, transactionID]); const defaultBillable = !!policy?.defaultBillable; From 43746db86e679fb257546468bc018b9b49ec7e1c Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Fri, 13 Sep 2024 22:52:03 +0530 Subject: [PATCH 03/73] chore: migrate withOnyx to useOnyx --- .../Navigation/AppNavigator/AuthScreens.tsx | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index f2461f400678..0c0d68c4e6dc 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -1,7 +1,7 @@ import React, {memo, useEffect, useMemo, useRef} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import Onyx, {withOnyx} from 'react-native-onyx'; +import Onyx, {useOnyx} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import ComposeProviders from '@components/ComposeProviders'; import OptionsListContextProvider from '@components/OptionListContextProvider'; @@ -61,17 +61,6 @@ import OnboardingModalNavigator from './Navigators/OnboardingModalNavigator'; import RightModalNavigator from './Navigators/RightModalNavigator'; import WelcomeVideoModalNavigator from './Navigators/WelcomeVideoModalNavigator'; -type AuthScreensProps = { - /** Session of currently logged in user */ - session: OnyxEntry; - - /** The report ID of the last opened public room as anonymous user */ - lastOpenedPublicRoomID: OnyxEntry; - - /** The last Onyx update ID was applied to the client */ - initialLastUpdateIDAppliedToClient: OnyxEntry; -}; - const loadReportAttachments = () => require('../../../pages/home/report/ReportAttachments').default; const loadValidateLoginPage = () => require('../../../pages/ValidateLoginPage').default; const loadLogOutPreviousUserPage = () => require('../../../pages/LogOutPreviousUserPage').default; @@ -211,7 +200,10 @@ const modalScreenListenersWithCancelSearch = { }, }; -function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDAppliedToClient}: AuthScreensProps) { +function AuthScreens() { + const [session] = useOnyx(ONYXKEYS.SESSION) + const [lastOpenedPublicRoomID] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID) + const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT) const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout(); @@ -567,14 +559,4 @@ AuthScreens.displayName = 'AuthScreens'; const AuthScreensMemoized = memo(AuthScreens, () => true); -export default withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, - lastOpenedPublicRoomID: { - key: ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID, - }, - initialLastUpdateIDAppliedToClient: { - key: ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT, - }, -})(AuthScreensMemoized); +export default AuthScreensMemoized; From 4df69bb5e73576b1a4f1c6412795c859f6e7e0a6 Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Fri, 13 Sep 2024 23:59:00 +0530 Subject: [PATCH 04/73] lint fix --- ios/Podfile.lock | 24 +++++++++---------- .../Navigation/AppNavigator/AuthScreens.tsx | 6 ++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index bff8e0799f40..45534889fffa 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -28,17 +28,17 @@ PODS: - AppAuth/Core - boost (1.84.0) - DoubleConversion (1.1.6) - - EXAV (14.0.7): + - EXAV (14.0.6): - ExpoModulesCore - ReactCommon/turbomodule/core - EXImageLoader (4.7.0): - ExpoModulesCore - React-Core - - Expo (51.0.31): + - Expo (51.0.17): - ExpoModulesCore - ExpoAsset (10.0.10): - ExpoModulesCore - - ExpoImage (1.12.15): + - ExpoImage (1.12.12): - ExpoModulesCore - libavif/libdav1d - SDWebImage (~> 5.19.1) @@ -49,7 +49,7 @@ PODS: - EXImageLoader - ExpoModulesCore - SDWebImageWebPCoder - - ExpoModulesCore (1.12.23): + - ExpoModulesCore (1.12.18): - DoubleConversion - glog - hermes-engine @@ -2405,13 +2405,13 @@ PODS: - Yoga - RNLocalize (2.2.6): - React-Core - - rnmapbox-maps (10.1.30): + - rnmapbox-maps (10.1.26): - MapboxMaps (~> 10.18.2) - React - React-Core - - rnmapbox-maps/DynamicLibrary (= 10.1.30) + - rnmapbox-maps/DynamicLibrary (= 10.1.26) - Turf - - rnmapbox-maps/DynamicLibrary (10.1.30): + - rnmapbox-maps/DynamicLibrary (10.1.26): - DoubleConversion - hermes-engine - MapboxMaps (~> 10.18.2) @@ -3098,13 +3098,13 @@ SPEC CHECKSUMS: AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa boost: 26992d1adf73c1c7676360643e687aee6dda994b DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 - EXAV: afa491e598334bbbb92a92a2f4dd33d7149ad37f + EXAV: 62e66b067185d630fe4cb4aa6eb0e48f72e67e0f EXImageLoader: ab589d67d6c5f2c33572afea9917304418566334 - Expo: 4773e11951abd0f666f67023f0cb1d48c3e8a32b + Expo: 675a5642b5860771507237259da50b921c03a9f3 ExpoAsset: 323700f291684f110fb55f0d4022a3362ea9f875 - ExpoImage: f77df382153d716f332f974438a803c4527f60b0 + ExpoImage: 2ccccff1219ebc765e344f3338f2430af2df4824 ExpoImageManipulator: aea99205c66043a00a0af90e345395637b9902fa - ExpoModulesCore: 335282d855cc34fb5540e170204e729a51464bbb + ExpoModulesCore: 606b7ca7c74186324975750c8a6f97b643f54ec9 FBLazyVector: 38bb611218305c3bc61803e287b8a81c6f63b619 Firebase: 629510f1a9ddb235f3a7c5c8ceb23ba887f0f814 FirebaseABTesting: 10cbce8db9985ae2e3847ea44e9947dd18f94e10 @@ -3231,7 +3231,7 @@ SPEC CHECKSUMS: RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0 RNLiveMarkdown: cfc927fc0b1182e364237c72692e079107c6f5f1 RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 - rnmapbox-maps: 460d6ff97ae49c7d5708c3212c6521697c36a0c4 + rnmapbox-maps: 5ab6bfd249cd67262615153c648f8d809aab781c RNPermissions: 0b1429b55af59d1d08b75a8be2459f65a8ac3f28 RNReactNativeHapticFeedback: a15b431d2903bc2eb3474ff8d9a05d3e67a70199 RNReanimated: 76901886830e1032f16bbf820153f7dc3f02d51d diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 0c0d68c4e6dc..a76886a7e0ce 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -201,9 +201,9 @@ const modalScreenListenersWithCancelSearch = { }; function AuthScreens() { - const [session] = useOnyx(ONYXKEYS.SESSION) - const [lastOpenedPublicRoomID] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID) - const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT) + const [session] = useOnyx(ONYXKEYS.SESSION); + const [lastOpenedPublicRoomID] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID); + const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout(); From 94b1edd0fa622f2d621c67a7d963fd1a42973253 Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Sat, 14 Sep 2024 00:01:05 +0530 Subject: [PATCH 05/73] revert podfile changes --- ios/Podfile.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 81167b6b529b..e6a521ead8b5 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -28,17 +28,17 @@ PODS: - AppAuth/Core - boost (1.84.0) - DoubleConversion (1.1.6) - - EXAV (14.0.6): + - EXAV (14.0.7): - ExpoModulesCore - ReactCommon/turbomodule/core - EXImageLoader (4.7.0): - ExpoModulesCore - React-Core - - Expo (51.0.17): + - Expo (51.0.31): - ExpoModulesCore - ExpoAsset (10.0.10): - ExpoModulesCore - - ExpoImage (1.12.12): + - ExpoImage (1.12.15): - ExpoModulesCore - libavif/libdav1d - SDWebImage (~> 5.19.1) @@ -49,7 +49,7 @@ PODS: - EXImageLoader - ExpoModulesCore - SDWebImageWebPCoder - - ExpoModulesCore (1.12.18): + - ExpoModulesCore (1.12.23): - DoubleConversion - glog - hermes-engine @@ -2405,13 +2405,13 @@ PODS: - Yoga - RNLocalize (2.2.6): - React-Core - - rnmapbox-maps (10.1.26): + - rnmapbox-maps (10.1.30): - MapboxMaps (~> 10.18.2) - React - React-Core - - rnmapbox-maps/DynamicLibrary (= 10.1.26) + - rnmapbox-maps/DynamicLibrary (= 10.1.30) - Turf - - rnmapbox-maps/DynamicLibrary (10.1.26): + - rnmapbox-maps/DynamicLibrary (10.1.30): - DoubleConversion - hermes-engine - MapboxMaps (~> 10.18.2) @@ -3098,13 +3098,13 @@ SPEC CHECKSUMS: AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa boost: 26992d1adf73c1c7676360643e687aee6dda994b DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 - EXAV: 62e66b067185d630fe4cb4aa6eb0e48f72e67e0f + EXAV: afa491e598334bbbb92a92a2f4dd33d7149ad37f EXImageLoader: ab589d67d6c5f2c33572afea9917304418566334 - Expo: 675a5642b5860771507237259da50b921c03a9f3 + Expo: 4773e11951abd0f666f67023f0cb1d48c3e8a32b ExpoAsset: 323700f291684f110fb55f0d4022a3362ea9f875 - ExpoImage: 2ccccff1219ebc765e344f3338f2430af2df4824 + ExpoImage: f77df382153d716f332f974438a803c4527f60b0 ExpoImageManipulator: aea99205c66043a00a0af90e345395637b9902fa - ExpoModulesCore: 606b7ca7c74186324975750c8a6f97b643f54ec9 + ExpoModulesCore: 335282d855cc34fb5540e170204e729a51464bbb FBLazyVector: 38bb611218305c3bc61803e287b8a81c6f63b619 Firebase: 629510f1a9ddb235f3a7c5c8ceb23ba887f0f814 FirebaseABTesting: 10cbce8db9985ae2e3847ea44e9947dd18f94e10 @@ -3231,7 +3231,7 @@ SPEC CHECKSUMS: RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0 RNLiveMarkdown: e44918843c2638692348f39eafc275698baf0444 RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 - rnmapbox-maps: 5ab6bfd249cd67262615153c648f8d809aab781c + rnmapbox-maps: 460d6ff97ae49c7d5708c3212c6521697c36a0c4 RNPermissions: 0b1429b55af59d1d08b75a8be2459f65a8ac3f28 RNReactNativeHapticFeedback: a15b431d2903bc2eb3474ff8d9a05d3e67a70199 RNReanimated: 76901886830e1032f16bbf820153f7dc3f02d51d @@ -3250,4 +3250,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: e479ec84cb53e5fd463486d71dfee91708d3fd9a -COCOAPODS: 1.15.2 +COCOAPODS: 1.15.2 \ No newline at end of file From b727cc4fac3cda1c4d913dcffc96378fd45b3021 Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Sat, 14 Sep 2024 00:01:33 +0530 Subject: [PATCH 06/73] revert podfile changes --- ios/Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index e6a521ead8b5..7176ecd8453e 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -3250,4 +3250,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: e479ec84cb53e5fd463486d71dfee91708d3fd9a -COCOAPODS: 1.15.2 \ No newline at end of file +COCOAPODS: 1.15.2 From 8beb8b0525f25906dec09d0995f1187e807db616 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Fri, 13 Sep 2024 22:23:16 +0300 Subject: [PATCH 07/73] implemented getNextApproverAccountID --- src/libs/actions/IOU.ts | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index 1f1d56a4d027..ff522e4abac5 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -42,7 +42,7 @@ import Navigation from '@libs/Navigation/Navigation'; import * as NextStepUtils from '@libs/NextStepUtils'; import {rand64} from '@libs/NumberUtils'; import * as OptionsListUtils from '@libs/OptionsListUtils'; -import {getAccountIDsByLogins} from '@libs/PersonalDetailsUtils'; +import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import * as PhoneNumber from '@libs/PhoneNumber'; import * as PolicyUtils from '@libs/PolicyUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; @@ -7009,6 +7009,24 @@ function isLastApprover(approvalChain: string[]): boolean { return approvalChain[approvalChain.length - 1] === currentUserEmail; } +function getNextApproverAccountID(report: OnyxEntry) { + const ownerAccountID = report?.ownerAccountID ?? -1; + const policy = PolicyUtils.getPolicy(report?.policyID); + const approvalChain = ReportUtils.getApprovalChain(policy, ownerAccountID, report?.total ?? 0); + const submitToAccountID = PolicyUtils.getSubmitToAccountID(policy, ownerAccountID); + + if (approvalChain.length === 0) { + return submitToAccountID; + } + + const nextApproverEmail = approvalChain.length === 1 ? approvalChain[0] : approvalChain[approvalChain.indexOf(currentUserEmail) + 1]; + if (!nextApproverEmail) { + return submitToAccountID; + } + + return PersonalDetailsUtils.getAccountIDsByLogins([nextApproverEmail])[0] ?? submitToAccountID; +} + function approveMoneyRequest(expenseReport: OnyxEntry, full?: boolean) { if (expenseReport?.policyID && SubscriptionUtils.shouldRestrictUserBillableActions(expenseReport.policyID)) { Navigation.navigate(ROUTES.RESTRICTED_ACTION.getRoute(expenseReport.policyID)); @@ -7027,8 +7045,7 @@ function approveMoneyRequest(expenseReport: OnyxEntry, full?: const predictedNextStatus = isLastApprover(approvalChain) ? CONST.REPORT.STATUS_NUM.APPROVED : CONST.REPORT.STATUS_NUM.SUBMITTED; const predictedNextState = isLastApprover(approvalChain) ? CONST.REPORT.STATE_NUM.APPROVED : CONST.REPORT.STATE_NUM.SUBMITTED; - const currentUserApprovalIndex = approvalChain.indexOf(currentUserEmail); - const managerID = isLastApprover(approvalChain) || currentUserApprovalIndex === -1 ? expenseReport?.managerID : getAccountIDsByLogins([approvalChain[currentUserApprovalIndex + 1]])[0]; + const managerID = isLastApprover(approvalChain) ? expenseReport?.managerID : getNextApproverAccountID(expenseReport); const optimisticNextStep = NextStepUtils.buildNextStep(expenseReport, predictedNextStatus); const chatReport = ReportUtils.getReportOrDraftReport(expenseReport?.chatReportID); From fc706e9c6c082137fdc0c9bf80f9de445efec5b2 Mon Sep 17 00:00:00 2001 From: Anusha <93134676+Nodebrute@users.noreply.github.com> Date: Mon, 16 Sep 2024 02:57:19 +0500 Subject: [PATCH 08/73] Update src/pages/iou/request/step/IOURequestStepConfirmation.tsx Co-authored-by: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> --- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 5db903a2d905..c91a897e66b0 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -168,7 +168,7 @@ function IOURequestStepConfirmation({ if (policyExpenseChat?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { openDraftWorkspaceRequest(policyExpenseChat.policyID); } - const isSender = participants?.find((participant) => participant.isSender); + const senderPolicyParticipant = participants?.find((participant) => participant.isSender); if (isSender?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { openDraftWorkspaceRequest(isSender.policyID); } From d4007d43d6eea41f7ec6bb9da85a33bcbff7fcd7 Mon Sep 17 00:00:00 2001 From: Anusha <93134676+Nodebrute@users.noreply.github.com> Date: Mon, 16 Sep 2024 02:57:26 +0500 Subject: [PATCH 09/73] Update src/pages/iou/request/step/IOURequestStepConfirmation.tsx Co-authored-by: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> --- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index c91a897e66b0..7e31e9bfe29b 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -169,7 +169,7 @@ function IOURequestStepConfirmation({ openDraftWorkspaceRequest(policyExpenseChat.policyID); } const senderPolicyParticipant = participants?.find((participant) => participant.isSender); - if (isSender?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { + if (senderPolicyParticipant?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { openDraftWorkspaceRequest(isSender.policyID); } }, [isOffline, participants, transaction?.billable, policy, transactionID]); From 6d9836a677720a9e8839b4aaa3474aa12abde7c5 Mon Sep 17 00:00:00 2001 From: Anusha <93134676+Nodebrute@users.noreply.github.com> Date: Mon, 16 Sep 2024 02:57:41 +0500 Subject: [PATCH 10/73] Update src/pages/iou/request/step/IOURequestStepConfirmation.tsx Co-authored-by: rayane-djouah <77965000+rayane-djouah@users.noreply.github.com> --- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 7e31e9bfe29b..e852a980473b 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -170,7 +170,7 @@ function IOURequestStepConfirmation({ } const senderPolicyParticipant = participants?.find((participant) => participant.isSender); if (senderPolicyParticipant?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { - openDraftWorkspaceRequest(isSender.policyID); + openDraftWorkspaceRequest(senderPolicyParticipant.policyID); } }, [isOffline, participants, transaction?.billable, policy, transactionID]); From 63f8dc37b9bff91704a5280e73c13ab6b2506722 Mon Sep 17 00:00:00 2001 From: Anusha Date: Mon, 16 Sep 2024 05:19:07 +0500 Subject: [PATCH 11/73] fix dependancy --- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index e852a980473b..d3899f828d41 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -172,7 +172,7 @@ function IOURequestStepConfirmation({ if (senderPolicyParticipant?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { openDraftWorkspaceRequest(senderPolicyParticipant.policyID); } - }, [isOffline, participants, transaction?.billable, policy, transactionID]); + }, [isOffline, participants, policy?.pendingAction]); const defaultBillable = !!policy?.defaultBillable; useEffect(() => { From 88b3289ff361630e1af4a640f4f779c93791d8cb Mon Sep 17 00:00:00 2001 From: Anusha Date: Mon, 16 Sep 2024 05:36:42 +0500 Subject: [PATCH 12/73] add transaction?.billable --- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index d3899f828d41..5d9f090c9071 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -172,7 +172,7 @@ function IOURequestStepConfirmation({ if (senderPolicyParticipant?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { openDraftWorkspaceRequest(senderPolicyParticipant.policyID); } - }, [isOffline, participants, policy?.pendingAction]); + }, [isOffline, participants, policy?.pendingAction, transaction?.billable]); const defaultBillable = !!policy?.defaultBillable; useEffect(() => { From 7cd4281e699b923685377b2d4addb7231a58fd8d Mon Sep 17 00:00:00 2001 From: Anusha Date: Mon, 16 Sep 2024 05:40:48 +0500 Subject: [PATCH 13/73] fix useeffect dependancy --- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 5d9f090c9071..d3899f828d41 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -172,7 +172,7 @@ function IOURequestStepConfirmation({ if (senderPolicyParticipant?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { openDraftWorkspaceRequest(senderPolicyParticipant.policyID); } - }, [isOffline, participants, policy?.pendingAction, transaction?.billable]); + }, [isOffline, participants, policy?.pendingAction]); const defaultBillable = !!policy?.defaultBillable; useEffect(() => { From 250275bd8dc0a66a466c32d5ccb97b34ad5476f2 Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Mon, 16 Sep 2024 08:35:36 +0530 Subject: [PATCH 14/73] fix showing indicator --- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index a76886a7e0ce..6d37a5568b2c 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -47,6 +47,7 @@ import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails'; +import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import type ReactComponentModule from '@src/types/utils/ReactComponentModule'; import CENTRAL_PANE_SCREENS from './CENTRAL_PANE_SCREENS'; import createCustomStackNavigator from './createCustomStackNavigator'; @@ -201,9 +202,10 @@ const modalScreenListenersWithCancelSearch = { }; function AuthScreens() { - const [session] = useOnyx(ONYXKEYS.SESSION); - const [lastOpenedPublicRoomID] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID); - const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT); + const [session, sessionStatus] = useOnyx(ONYXKEYS.SESSION); + const [lastOpenedPublicRoomID, lastOpenedPublicRoomIDStatus] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID); + const [initialLastUpdateIDAppliedToClient, initialLastUpdateIDAppliedToClientStatus] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT); + const isSessionLoading = isLoadingOnyxValue(sessionStatus, lastOpenedPublicRoomIDStatus, initialLastUpdateIDAppliedToClientStatus); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout(); @@ -382,6 +384,9 @@ function AuthScreens() { // Prevent unnecessary scrolling cardStyle: styles.cardStyleNavigator, }; + if (isSessionLoading) { + return; + } return ( From e605f5107e2ce4c319d5437b4984e69ca4299d97 Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Wed, 18 Sep 2024 08:05:54 +0530 Subject: [PATCH 15/73] refactoring --- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 0567964ebc78..38265cdca5c8 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -47,8 +47,8 @@ import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails'; -import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import type ReactComponentModule from '@src/types/utils/ReactComponentModule'; import CENTRAL_PANE_SCREENS from './CENTRAL_PANE_SCREENS'; import createCustomStackNavigator from './createCustomStackNavigator'; @@ -206,7 +206,6 @@ function AuthScreens() { const [session, sessionStatus] = useOnyx(ONYXKEYS.SESSION); const [lastOpenedPublicRoomID, lastOpenedPublicRoomIDStatus] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID); const [initialLastUpdateIDAppliedToClient, initialLastUpdateIDAppliedToClientStatus] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT); - const isSessionLoading = isLoadingOnyxValue(sessionStatus, lastOpenedPublicRoomIDStatus, initialLastUpdateIDAppliedToClientStatus); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout(); @@ -385,7 +384,7 @@ function AuthScreens() { // Prevent unnecessary scrolling cardStyle: styles.cardStyleNavigator, }; - if (isSessionLoading) { + if (isLoadingOnyxValue(sessionStatus, lastOpenedPublicRoomIDStatus, initialLastUpdateIDAppliedToClientStatus)) { return; } @@ -563,6 +562,4 @@ function AuthScreens() { AuthScreens.displayName = 'AuthScreens'; -const AuthScreensMemoized = memo(AuthScreens, () => true); - -export default AuthScreensMemoized; +export default memo(AuthScreens, () => true); From 5b890e4166b4322ddcc060ae1a3290c5fb155646 Mon Sep 17 00:00:00 2001 From: Muaaz Arshad Date: Wed, 18 Sep 2024 20:40:11 +0500 Subject: [PATCH 16/73] Error spacing inconsistency fixed --- .../ExitSurvey/ExitSurveyResponsePage.tsx | 43 ++----------------- 1 file changed, 3 insertions(+), 40 deletions(-) diff --git a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx index c14c20ffc992..85620c607645 100644 --- a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx +++ b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx @@ -14,12 +14,9 @@ import useKeyboardState from '@hooks/useKeyboardState'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useSafeAreaInsets from '@hooks/useSafeAreaInsets'; -import useSafePaddingBottomStyle from '@hooks/useSafePaddingBottomStyle'; -import useStyledSafeAreaInsets from '@hooks/useStyledSafeAreaInsets'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; -import * as NumberUtils from '@libs/NumberUtils'; import StatusBar from '@libs/StatusBar'; import updateMultilineInputRange from '@libs/updateMultilineInputRange'; import Navigation from '@navigation/Navigation'; @@ -47,18 +44,10 @@ function ExitSurveyResponsePage({draftResponse, route, navigation}: ExitSurveyRe const {keyboardHeight} = useKeyboardState(); const {windowHeight} = useWindowDimensions(); const {inputCallbackRef, inputRef} = useAutoFocusInput(); - const [headerTitleHeight, setHeaderTitleHeight] = useState(0); // Device safe area top and bottom insets. // When the keyboard is shown, the bottom inset doesn't affect the height, so we take it out from the calculation. - const {top: safeAreaInsetsTop, bottom: safeAreaInsetsBottom} = useSafeAreaInsets(); - const safeAreaInsetsBottomValue = !keyboardHeight ? safeAreaInsetsBottom : 0; - // FormWrapper bottom padding - const {paddingBottom: formPaddingBottom} = useStyledSafeAreaInsets(); - const formPaddingBottomValue = formPaddingBottom || styles.pb5.paddingBottom; - // Extra bottom padding in FormAlertWithSubmitButton - const safePaddingBottomStyle = useSafePaddingBottomStyle(); - const safePaddingBottomStyleValue = 'paddingBottom' in safePaddingBottomStyle ? (safePaddingBottomStyle.paddingBottom as number) : 0; + const {top: safeAreaInsetsTop} = useSafeAreaInsets(); const {reason, backTo} = route.params; const {isOffline} = useNetwork({ @@ -96,27 +85,6 @@ function ExitSurveyResponsePage({draftResponse, route, navigation}: ExitSurveyRe // Minus the top margins on the form formTopMarginsStyle.marginTop, ); - const responseInputMaxHeight = NumberUtils.roundDownToLargestMultiple( - formMaxHeight - - safeAreaInsetsBottomValue - - safePaddingBottomStyleValue - - formPaddingBottomValue - - // Minus the height of the text component - headerTitleHeight - - // Minus the response input margins (multiplied by 2 to create the effect of margins on top and bottom). - // marginBottom does not work in this case because the TextInput is in a ScrollView and will push the button beneath it out of view, - // so it's maxHeight is what dictates space between it and the button. - baseResponseInputContainerStyle.marginTop * 2 - - // Minus the approximate size of a default button - variables.componentSizeLarge - - // Minus the height above the button for the form error text, accounting for 2 lines max. - variables.lineHeightNormal * 2 - - // Minus the margin between the button and the form error text - styles.mb3.marginBottom, - - // Round down to the largest number of full lines - styles.baseTextInput.lineHeight, - ); return ( @@ -142,12 +110,7 @@ function ExitSurveyResponsePage({draftResponse, route, navigation}: ExitSurveyRe {isOffline && } {!isOffline && ( <> - setHeaderTitleHeight(e.nativeEvent.layout.height)} - > - {translate(`exitSurvey.prompts.${reason}`)} - + {translate(`exitSurvey.prompts.${reason}`)} { if (!el) { From e059a866014a51a16229de5ee4df86187c438187 Mon Sep 17 00:00:00 2001 From: Muaaz Arshad Date: Wed, 18 Sep 2024 20:45:26 +0500 Subject: [PATCH 17/73] Error spacing inconsistency fixed --- src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx index 85620c607645..b1675c18fe73 100644 --- a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx +++ b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx @@ -1,5 +1,5 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import React, {useCallback, useEffect, useState} from 'react'; +import React, {useCallback, useEffect} from 'react'; import {withOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; From e00d4c65c9599bfea1375a52907cdbf8a7023576 Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Fri, 13 Sep 2024 22:52:03 +0530 Subject: [PATCH 18/73] chore: migrate withOnyx to useOnyx --- .../Navigation/AppNavigator/AuthScreens.tsx | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index b68b9441c38c..54d07e12b3a4 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -1,7 +1,7 @@ import React, {memo, useEffect, useMemo, useRef} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import Onyx, {withOnyx} from 'react-native-onyx'; +import Onyx, {useOnyx} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import ComposeProviders from '@components/ComposeProviders'; import OptionsListContextProvider from '@components/OptionListContextProvider'; @@ -63,17 +63,6 @@ import OnboardingModalNavigator from './Navigators/OnboardingModalNavigator'; import RightModalNavigator from './Navigators/RightModalNavigator'; import WelcomeVideoModalNavigator from './Navigators/WelcomeVideoModalNavigator'; -type AuthScreensProps = { - /** Session of currently logged in user */ - session: OnyxEntry; - - /** The report ID of the last opened public room as anonymous user */ - lastOpenedPublicRoomID: OnyxEntry; - - /** The last Onyx update ID was applied to the client */ - initialLastUpdateIDAppliedToClient: OnyxEntry; -}; - const loadReportAttachments = () => require('../../../pages/home/report/ReportAttachments').default; const loadValidateLoginPage = () => require('../../../pages/ValidateLoginPage').default; const loadLogOutPreviousUserPage = () => require('../../../pages/LogOutPreviousUserPage').default; @@ -213,7 +202,10 @@ const modalScreenListenersWithCancelSearch = { }, }; -function AuthScreens({session, lastOpenedPublicRoomID, initialLastUpdateIDAppliedToClient}: AuthScreensProps) { +function AuthScreens() { + const [session] = useOnyx(ONYXKEYS.SESSION) + const [lastOpenedPublicRoomID] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID) + const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT) const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout(); @@ -570,14 +562,4 @@ AuthScreens.displayName = 'AuthScreens'; const AuthScreensMemoized = memo(AuthScreens, () => true); -export default withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, - lastOpenedPublicRoomID: { - key: ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID, - }, - initialLastUpdateIDAppliedToClient: { - key: ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT, - }, -})(AuthScreensMemoized); +export default AuthScreensMemoized; From ba4e4ca8640edd73fc4622ae36862ef40dfddd43 Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Fri, 13 Sep 2024 23:59:00 +0530 Subject: [PATCH 19/73] lint fix --- ios/Podfile.lock | 24 +++++++++---------- .../Navigation/AppNavigator/AuthScreens.tsx | 6 ++--- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 0f1a42791d1e..229b13ea3fc2 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -28,17 +28,17 @@ PODS: - AppAuth/Core - boost (1.84.0) - DoubleConversion (1.1.6) - - EXAV (14.0.7): + - EXAV (14.0.6): - ExpoModulesCore - ReactCommon/turbomodule/core - EXImageLoader (4.7.0): - ExpoModulesCore - React-Core - - Expo (51.0.31): + - Expo (51.0.17): - ExpoModulesCore - ExpoAsset (10.0.10): - ExpoModulesCore - - ExpoImage (1.12.15): + - ExpoImage (1.12.12): - ExpoModulesCore - libavif/libdav1d - SDWebImage (~> 5.19.1) @@ -49,7 +49,7 @@ PODS: - EXImageLoader - ExpoModulesCore - SDWebImageWebPCoder - - ExpoModulesCore (1.12.23): + - ExpoModulesCore (1.12.18): - DoubleConversion - glog - hermes-engine @@ -2405,13 +2405,13 @@ PODS: - Yoga - RNLocalize (2.2.6): - React-Core - - rnmapbox-maps (10.1.30): + - rnmapbox-maps (10.1.26): - MapboxMaps (~> 10.18.2) - React - React-Core - - rnmapbox-maps/DynamicLibrary (= 10.1.30) + - rnmapbox-maps/DynamicLibrary (= 10.1.26) - Turf - - rnmapbox-maps/DynamicLibrary (10.1.30): + - rnmapbox-maps/DynamicLibrary (10.1.26): - DoubleConversion - hermes-engine - MapboxMaps (~> 10.18.2) @@ -3098,13 +3098,13 @@ SPEC CHECKSUMS: AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa boost: 26992d1adf73c1c7676360643e687aee6dda994b DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 - EXAV: afa491e598334bbbb92a92a2f4dd33d7149ad37f + EXAV: 62e66b067185d630fe4cb4aa6eb0e48f72e67e0f EXImageLoader: ab589d67d6c5f2c33572afea9917304418566334 - Expo: 4773e11951abd0f666f67023f0cb1d48c3e8a32b + Expo: 675a5642b5860771507237259da50b921c03a9f3 ExpoAsset: 323700f291684f110fb55f0d4022a3362ea9f875 - ExpoImage: f77df382153d716f332f974438a803c4527f60b0 + ExpoImage: 2ccccff1219ebc765e344f3338f2430af2df4824 ExpoImageManipulator: aea99205c66043a00a0af90e345395637b9902fa - ExpoModulesCore: 335282d855cc34fb5540e170204e729a51464bbb + ExpoModulesCore: 606b7ca7c74186324975750c8a6f97b643f54ec9 FBLazyVector: 38bb611218305c3bc61803e287b8a81c6f63b619 Firebase: 629510f1a9ddb235f3a7c5c8ceb23ba887f0f814 FirebaseABTesting: 10cbce8db9985ae2e3847ea44e9947dd18f94e10 @@ -3231,7 +3231,7 @@ SPEC CHECKSUMS: RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0 RNLiveMarkdown: e44918843c2638692348f39eafc275698baf0444 RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 - rnmapbox-maps: 460d6ff97ae49c7d5708c3212c6521697c36a0c4 + rnmapbox-maps: 5ab6bfd249cd67262615153c648f8d809aab781c RNPermissions: 0b1429b55af59d1d08b75a8be2459f65a8ac3f28 RNReactNativeHapticFeedback: 31833c3ef341d716dbbd9d64e940f0c230db46f6 RNReanimated: 76901886830e1032f16bbf820153f7dc3f02d51d diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 54d07e12b3a4..33367cdf2f37 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -203,9 +203,9 @@ const modalScreenListenersWithCancelSearch = { }; function AuthScreens() { - const [session] = useOnyx(ONYXKEYS.SESSION) - const [lastOpenedPublicRoomID] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID) - const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT) + const [session] = useOnyx(ONYXKEYS.SESSION); + const [lastOpenedPublicRoomID] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID); + const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout(); From 61afdeea9b31f86c5561aa178b768485e7f66157 Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Sat, 14 Sep 2024 00:01:05 +0530 Subject: [PATCH 20/73] revert podfile changes --- ios/Podfile.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 229b13ea3fc2..447a54da46ea 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -28,17 +28,17 @@ PODS: - AppAuth/Core - boost (1.84.0) - DoubleConversion (1.1.6) - - EXAV (14.0.6): + - EXAV (14.0.7): - ExpoModulesCore - ReactCommon/turbomodule/core - EXImageLoader (4.7.0): - ExpoModulesCore - React-Core - - Expo (51.0.17): + - Expo (51.0.31): - ExpoModulesCore - ExpoAsset (10.0.10): - ExpoModulesCore - - ExpoImage (1.12.12): + - ExpoImage (1.12.15): - ExpoModulesCore - libavif/libdav1d - SDWebImage (~> 5.19.1) @@ -49,7 +49,7 @@ PODS: - EXImageLoader - ExpoModulesCore - SDWebImageWebPCoder - - ExpoModulesCore (1.12.18): + - ExpoModulesCore (1.12.23): - DoubleConversion - glog - hermes-engine @@ -2405,13 +2405,13 @@ PODS: - Yoga - RNLocalize (2.2.6): - React-Core - - rnmapbox-maps (10.1.26): + - rnmapbox-maps (10.1.30): - MapboxMaps (~> 10.18.2) - React - React-Core - - rnmapbox-maps/DynamicLibrary (= 10.1.26) + - rnmapbox-maps/DynamicLibrary (= 10.1.30) - Turf - - rnmapbox-maps/DynamicLibrary (10.1.26): + - rnmapbox-maps/DynamicLibrary (10.1.30): - DoubleConversion - hermes-engine - MapboxMaps (~> 10.18.2) @@ -3098,13 +3098,13 @@ SPEC CHECKSUMS: AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa boost: 26992d1adf73c1c7676360643e687aee6dda994b DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5 - EXAV: 62e66b067185d630fe4cb4aa6eb0e48f72e67e0f + EXAV: afa491e598334bbbb92a92a2f4dd33d7149ad37f EXImageLoader: ab589d67d6c5f2c33572afea9917304418566334 - Expo: 675a5642b5860771507237259da50b921c03a9f3 + Expo: 4773e11951abd0f666f67023f0cb1d48c3e8a32b ExpoAsset: 323700f291684f110fb55f0d4022a3362ea9f875 - ExpoImage: 2ccccff1219ebc765e344f3338f2430af2df4824 + ExpoImage: f77df382153d716f332f974438a803c4527f60b0 ExpoImageManipulator: aea99205c66043a00a0af90e345395637b9902fa - ExpoModulesCore: 606b7ca7c74186324975750c8a6f97b643f54ec9 + ExpoModulesCore: 335282d855cc34fb5540e170204e729a51464bbb FBLazyVector: 38bb611218305c3bc61803e287b8a81c6f63b619 Firebase: 629510f1a9ddb235f3a7c5c8ceb23ba887f0f814 FirebaseABTesting: 10cbce8db9985ae2e3847ea44e9947dd18f94e10 @@ -3231,7 +3231,7 @@ SPEC CHECKSUMS: RNGoogleSignin: ccaa4a81582cf713eea562c5dd9dc1961a715fd0 RNLiveMarkdown: e44918843c2638692348f39eafc275698baf0444 RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 - rnmapbox-maps: 5ab6bfd249cd67262615153c648f8d809aab781c + rnmapbox-maps: 460d6ff97ae49c7d5708c3212c6521697c36a0c4 RNPermissions: 0b1429b55af59d1d08b75a8be2459f65a8ac3f28 RNReactNativeHapticFeedback: 31833c3ef341d716dbbd9d64e940f0c230db46f6 RNReanimated: 76901886830e1032f16bbf820153f7dc3f02d51d @@ -3250,4 +3250,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: e479ec84cb53e5fd463486d71dfee91708d3fd9a -COCOAPODS: 1.15.2 +COCOAPODS: 1.15.2 \ No newline at end of file From 003585e5216dfd2ce0c1b2e23504c22dd833c617 Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Sat, 14 Sep 2024 00:01:33 +0530 Subject: [PATCH 21/73] revert podfile changes --- ios/Podfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 447a54da46ea..0f1a42791d1e 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -3250,4 +3250,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: e479ec84cb53e5fd463486d71dfee91708d3fd9a -COCOAPODS: 1.15.2 \ No newline at end of file +COCOAPODS: 1.15.2 From 34dd64dced356b6faede45fe49c158625f95c0bb Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Wed, 18 Sep 2024 21:36:48 +0530 Subject: [PATCH 22/73] modify --- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 33367cdf2f37..58207d129546 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -49,6 +49,7 @@ import SCREENS from '@src/SCREENS'; import type * as OnyxTypes from '@src/types/onyx'; import type {SelectedTimezone, Timezone} from '@src/types/onyx/PersonalDetails'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import type ReactComponentModule from '@src/types/utils/ReactComponentModule'; import CENTRAL_PANE_SCREENS from './CENTRAL_PANE_SCREENS'; import createCustomStackNavigator from './createCustomStackNavigator'; @@ -203,9 +204,9 @@ const modalScreenListenersWithCancelSearch = { }; function AuthScreens() { - const [session] = useOnyx(ONYXKEYS.SESSION); - const [lastOpenedPublicRoomID] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID); - const [initialLastUpdateIDAppliedToClient] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT); + const [session, sessionStatus] = useOnyx(ONYXKEYS.SESSION); + const [lastOpenedPublicRoomID, lastOpenedPublicRoomIDStatus] = useOnyx(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID); + const [initialLastUpdateIDAppliedToClient, initialLastUpdateIDAppliedToClientStatus] = useOnyx(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {shouldUseNarrowLayout, onboardingIsMediumOrLargerScreenWidth, isSmallScreenWidth} = useResponsiveLayout(); @@ -384,6 +385,9 @@ function AuthScreens() { // Prevent unnecessary scrolling cardStyle: styles.cardStyleNavigator, }; + if (isLoadingOnyxValue(sessionStatus, lastOpenedPublicRoomIDStatus, initialLastUpdateIDAppliedToClientStatus)) { + return; + } return ( From 4f3af391658e30c70c5077135309162ab0b5785c Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Wed, 18 Sep 2024 08:05:54 +0530 Subject: [PATCH 23/73] refactoring --- src/libs/Navigation/AppNavigator/AuthScreens.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.tsx b/src/libs/Navigation/AppNavigator/AuthScreens.tsx index 58207d129546..defe1cee1aa3 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.tsx +++ b/src/libs/Navigation/AppNavigator/AuthScreens.tsx @@ -564,6 +564,4 @@ function AuthScreens() { AuthScreens.displayName = 'AuthScreens'; -const AuthScreensMemoized = memo(AuthScreens, () => true); - -export default AuthScreensMemoized; +export default memo(AuthScreens, () => true); From 8616749fec22d7f9e6a1042c05262d36267e7313 Mon Sep 17 00:00:00 2001 From: Anusha Date: Thu, 19 Sep 2024 07:04:35 +0500 Subject: [PATCH 24/73] fix isSender type --- src/libs/ReportUtils.ts | 1 - src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 607f48ce715f..79948d51bcdc 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -458,7 +458,6 @@ type OptionData = { tabIndex?: 0 | -1; isConciergeChat?: boolean; isBold?: boolean; - isSender?: boolean; } & Report; type OnyxDataTaskAssigneeChat = { diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index d3899f828d41..31c3fc69996f 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -168,7 +168,7 @@ function IOURequestStepConfirmation({ if (policyExpenseChat?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { openDraftWorkspaceRequest(policyExpenseChat.policyID); } - const senderPolicyParticipant = participants?.find((participant) => participant.isSender); + const senderPolicyParticipant = participants?.find((participant) => !!participant && 'isSender' in participant && participant.isSender); if (senderPolicyParticipant?.policyID && policy?.pendingAction !== CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD) { openDraftWorkspaceRequest(senderPolicyParticipant.policyID); } From 90968b84d4ba097693308493c37782877bb741ec Mon Sep 17 00:00:00 2001 From: Abhinay Bathina Date: Sat, 14 Sep 2024 11:10:01 +0530 Subject: [PATCH 25/73] chore: migrate withWritableReportOrNotFound from withOnyx to useOnyx --- .../step/withWritableReportOrNotFound.tsx | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx index 8df530f3c81c..be45b173f5ff 100644 --- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx +++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx @@ -2,7 +2,7 @@ import type {RouteProp} from '@react-navigation/core'; import type {ComponentType, ForwardedRef, RefAttributes} from 'react'; import React, {forwardRef, useEffect} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import getComponentDisplayName from '@libs/getComponentDisplayName'; @@ -52,14 +52,21 @@ type WithWritableReportOrNotFoundProps = WithWr export default function , TRef>( WrappedComponent: ComponentType>, shouldIncludeDeprecatedIOUType = false, -): React.ComponentType, keyof WithWritableReportOrNotFoundOnyxProps>> { +): React.ComponentType> & RefAttributes> { // eslint-disable-next-line rulesdir/no-negated-variables - function WithWritableReportOrNotFound(props: TProps, ref: ForwardedRef) { - const {report = {reportID: ''}, route, isLoadingApp = true, reportDraft} = props; + function WithWritableReportOrNotFound(props: Omit>, ref: ForwardedRef) { + const {route} = props as TProps; const iouTypeParamIsInvalid = !Object.values(CONST.IOU.TYPE) .filter((type) => shouldIncludeDeprecatedIOUType || (type !== CONST.IOU.TYPE.REQUEST && type !== CONST.IOU.TYPE.SEND)) .includes(route.params?.iouType); const isEditing = 'action' in route.params && route.params?.action === CONST.IOU.ACTION.EDIT; + + const reportID = route.params.reportID; + + const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${reportID ?? -1}`); + const [isLoadingApp = true] = useOnyx(ONYXKEYS.IS_LOADING_APP); + const [reportDraft] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_DRAFT}${reportID ?? -1}`); + const canUserPerformWriteAction = ReportUtils.canUserPerformWriteAction(report); useEffect(() => { @@ -81,7 +88,10 @@ export default function ); @@ -89,17 +99,7 @@ export default function , WithWritableReportOrNotFoundOnyxProps>({ - report: { - key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID ?? '-1'}`, - }, - isLoadingApp: { - key: ONYXKEYS.IS_LOADING_APP, - }, - reportDraft: { - key: ({route}) => `${ONYXKEYS.COLLECTION.REPORT_DRAFT}${route.params.reportID ?? '-1'}`, - }, - })(forwardRef(WithWritableReportOrNotFound)); + return forwardRef(WithWritableReportOrNotFound); } export type {WithWritableReportOrNotFoundProps}; From bd4712ae3107f53dff67ecbd6618f29bbc804633 Mon Sep 17 00:00:00 2001 From: Abhinay Bathina Date: Fri, 20 Sep 2024 00:01:36 +0530 Subject: [PATCH 26/73] chore: update TypeScript types --- src/pages/iou/request/step/withWritableReportOrNotFound.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx index be45b173f5ff..6a045e6289f8 100644 --- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx +++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx @@ -52,10 +52,10 @@ type WithWritableReportOrNotFoundProps = WithWr export default function , TRef>( WrappedComponent: ComponentType>, shouldIncludeDeprecatedIOUType = false, -): React.ComponentType> & RefAttributes> { +): React.ComponentType & RefAttributes> { // eslint-disable-next-line rulesdir/no-negated-variables - function WithWritableReportOrNotFound(props: Omit>, ref: ForwardedRef) { - const {route} = props as TProps; + function WithWritableReportOrNotFound(props: Omit, ref: ForwardedRef) { + const {route} = props; const iouTypeParamIsInvalid = !Object.values(CONST.IOU.TYPE) .filter((type) => shouldIncludeDeprecatedIOUType || (type !== CONST.IOU.TYPE.REQUEST && type !== CONST.IOU.TYPE.SEND)) .includes(route.params?.iouType); From 0415fe326dc8c71dc1af9be74b34a75474654d81 Mon Sep 17 00:00:00 2001 From: Abhinay Bathina Date: Fri, 20 Sep 2024 00:13:49 +0530 Subject: [PATCH 27/73] minor: refactor --- src/pages/iou/request/step/withWritableReportOrNotFound.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx index 6a045e6289f8..69172bde748e 100644 --- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx +++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx @@ -52,7 +52,7 @@ type WithWritableReportOrNotFoundProps = WithWr export default function , TRef>( WrappedComponent: ComponentType>, shouldIncludeDeprecatedIOUType = false, -): React.ComponentType & RefAttributes> { +): React.ComponentType, keyof WithWritableReportOrNotFoundOnyxProps>> { // eslint-disable-next-line rulesdir/no-negated-variables function WithWritableReportOrNotFound(props: Omit, ref: ForwardedRef) { const {route} = props; From ed9659daa784d85703595af457b8789a2c499e03 Mon Sep 17 00:00:00 2001 From: Abhinay Bathina Date: Fri, 20 Sep 2024 00:22:45 +0530 Subject: [PATCH 28/73] chore: code review changes --- src/pages/iou/request/step/withWritableReportOrNotFound.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx index 69172bde748e..7bad2de23660 100644 --- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx +++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx @@ -61,11 +61,9 @@ export default function Date: Fri, 20 Sep 2024 01:17:55 +0530 Subject: [PATCH 29/73] chore: move useOnyx calls to top for readability and use '-1' instead of 1 for missing reportID --- .../iou/request/step/withWritableReportOrNotFound.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx index 7bad2de23660..dab24427aaf7 100644 --- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx +++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx @@ -56,15 +56,15 @@ export default function , ref: ForwardedRef) { const {route} = props; + const [report = {reportID: ''}] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID ?? '-1'}`); + const [isLoadingApp = true] = useOnyx(ONYXKEYS.IS_LOADING_APP); + const [reportDraft] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_DRAFT}${route.params.reportID ?? '-1'}`); + const iouTypeParamIsInvalid = !Object.values(CONST.IOU.TYPE) .filter((type) => shouldIncludeDeprecatedIOUType || (type !== CONST.IOU.TYPE.REQUEST && type !== CONST.IOU.TYPE.SEND)) .includes(route.params?.iouType); const isEditing = 'action' in route.params && route.params?.action === CONST.IOU.ACTION.EDIT; - const [report = {reportID: ''}] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID ?? -1}`); - const [isLoadingApp = true] = useOnyx(ONYXKEYS.IS_LOADING_APP); - const [reportDraft] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_DRAFT}${route.params.reportID ?? -1}`); - const canUserPerformWriteAction = ReportUtils.canUserPerformWriteAction(report); useEffect(() => { From 69aba443834f8fae1aaa6f2304a494037ed6c0ef Mon Sep 17 00:00:00 2001 From: Abhinay Bathina Date: Fri, 20 Sep 2024 18:06:18 +0530 Subject: [PATCH 30/73] fix: create a variable for reportOrDefault to pass report as it is to child component --- .../iou/request/step/withWritableReportOrNotFound.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx index dab24427aaf7..115d9f503b9c 100644 --- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx +++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx @@ -56,19 +56,21 @@ export default function , ref: ForwardedRef) { const {route} = props; - const [report = {reportID: ''}] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID ?? '-1'}`); + const [report] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${route.params.reportID ?? '-1'}`); const [isLoadingApp = true] = useOnyx(ONYXKEYS.IS_LOADING_APP); const [reportDraft] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_DRAFT}${route.params.reportID ?? '-1'}`); + const reportOrDefault = report ?? {reportID: ''}; + const iouTypeParamIsInvalid = !Object.values(CONST.IOU.TYPE) .filter((type) => shouldIncludeDeprecatedIOUType || (type !== CONST.IOU.TYPE.REQUEST && type !== CONST.IOU.TYPE.SEND)) .includes(route.params?.iouType); const isEditing = 'action' in route.params && route.params?.action === CONST.IOU.ACTION.EDIT; - const canUserPerformWriteAction = ReportUtils.canUserPerformWriteAction(report); + const canUserPerformWriteAction = ReportUtils.canUserPerformWriteAction(reportOrDefault); useEffect(() => { - if (!!report?.reportID || !route.params.reportID || !!reportDraft || !isEditing) { + if (!!reportOrDefault?.reportID || !route.params.reportID || !!reportDraft || !isEditing) { return; } ReportActions.openReport(route.params.reportID); From 7db6f638c90b4b6834c7e2f4b992dabc2d4b9894 Mon Sep 17 00:00:00 2001 From: Alex Beaman Date: Fri, 20 Sep 2024 14:39:40 -0600 Subject: [PATCH 31/73] Remove manager condition --- src/libs/ReportUtils.ts | 6 +++--- src/libs/SidebarUtils.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 8746490ecd30..b793d9809b2f 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -7817,8 +7817,8 @@ function hasMissingInvoiceBankAccount(iouReportID: string): boolean { return invoiceReport?.ownerAccountID === currentUserAccountID && isEmptyObject(getPolicy(invoiceReport?.policyID)?.invoice?.bankAccount ?? {}) && isSettled(iouReportID); } -function isExpenseReportManagerWithoutParentAccess(report: OnyxEntry) { - return isExpenseReport(report) && report?.hasParentAccess === false && report?.managerID === currentUserAccountID; +function isExpenseReportWithoutParentAccess(report: OnyxEntry) { + return isExpenseReport(report) && report?.hasParentAccess === false; } export { @@ -8016,7 +8016,7 @@ export { isEmptyReport, isRootGroupChat, isExpenseReport, - isExpenseReportManagerWithoutParentAccess, + isExpenseReportWithoutParentAccess, isExpenseRequest, isExpensifyOnlyParticipantInReport, isGroupChat, diff --git a/src/libs/SidebarUtils.ts b/src/libs/SidebarUtils.ts index d056f111695e..e120f7026fce 100644 --- a/src/libs/SidebarUtils.ts +++ b/src/libs/SidebarUtils.ts @@ -129,10 +129,10 @@ function getOrderedReportIDs( return; } const isSystemChat = ReportUtils.isSystemChat(report); - const isExpenseReportManagerWithoutParentAccess = ReportUtils.isExpenseReportManagerWithoutParentAccess(report); + const isExpenseReportWithoutParentAccess = ReportUtils.isExpenseReportWithoutParentAccess(report); const shouldOverrideHidden = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - hasValidDraftComment(report.reportID) || hasErrorsOtherThanFailedReceipt || isFocused || isSystemChat || report.isPinned || isExpenseReportManagerWithoutParentAccess; + hasValidDraftComment(report.reportID) || hasErrorsOtherThanFailedReceipt || isFocused || isSystemChat || report.isPinned || isExpenseReportWithoutParentAccess; if (isHidden && !shouldOverrideHidden) { return; } From 28a76097f6eb277241e1714abc334a9cfac5359d Mon Sep 17 00:00:00 2001 From: daledah Date: Sat, 21 Sep 2024 10:55:29 +0700 Subject: [PATCH 32/73] fix: page not found on emoji report field --- src/ROUTES.ts | 2 +- src/libs/Navigation/linkingConfig/config.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ROUTES.ts b/src/ROUTES.ts index 146d35611a72..1a6cf17e0199 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -287,7 +287,7 @@ const ROUTES = { }, EDIT_REPORT_FIELD_REQUEST: { route: 'r/:reportID/edit/policyField/:policyID/:fieldID', - getRoute: (reportID: string, policyID: string, fieldID: string) => `r/${reportID}/edit/policyField/${policyID}/${fieldID}` as const, + getRoute: (reportID: string, policyID: string, fieldID: string) => `r/${reportID}/edit/policyField/${policyID}/${encodeURIComponent(fieldID)}` as const, }, REPORT_WITH_ID_DETAILS_SHARE_CODE: { route: 'r/:reportID/details/shareCode', diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts index 09ed50a57395..a97e2ddae327 100644 --- a/src/libs/Navigation/linkingConfig/config.ts +++ b/src/libs/Navigation/linkingConfig/config.ts @@ -1116,7 +1116,12 @@ const config: LinkingOptions['config'] = { }, [SCREENS.RIGHT_MODAL.EDIT_REQUEST]: { screens: { - [SCREENS.EDIT_REQUEST.REPORT_FIELD]: ROUTES.EDIT_REPORT_FIELD_REQUEST.route, + [SCREENS.EDIT_REQUEST.REPORT_FIELD]: { + path: ROUTES.EDIT_REPORT_FIELD_REQUEST.route, + parse: { + fieldID: (fieldID: string) => decodeURIComponent(fieldID), + }, + }, }, }, [SCREENS.RIGHT_MODAL.SIGN_IN]: { From f616babdc79f4cebc20e12d536b2c6057774fbd3 Mon Sep 17 00:00:00 2001 From: Abhinay Bathina Date: Sat, 21 Sep 2024 09:40:16 +0530 Subject: [PATCH 33/73] chore: don't pass isLoadingApp into the wrapped component --- src/pages/iou/request/step/withWritableReportOrNotFound.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx index 115d9f503b9c..cd4dd4f93ba4 100644 --- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx +++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx @@ -18,9 +18,6 @@ type WithWritableReportOrNotFoundOnyxProps = { /** The report corresponding to the reportID in the route params */ report: OnyxEntry; - /** Whether the reports are loading. When false it means they are ready to be used. */ - isLoadingApp: OnyxEntry; - /** The draft report corresponding to the reportID in the route params */ reportDraft: OnyxEntry; }; @@ -90,7 +87,6 @@ export default function From 299040a5fa609d126ed0fc877faed317c714dc48 Mon Sep 17 00:00:00 2001 From: mkzie2 Date: Mon, 23 Sep 2024 13:34:11 +0700 Subject: [PATCH 34/73] Remove viewing search query in the list and add bookmark icon for mobile --- src/pages/Search/SearchTypeMenuNarrow.tsx | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/pages/Search/SearchTypeMenuNarrow.tsx b/src/pages/Search/SearchTypeMenuNarrow.tsx index 0158a15bfc41..c8aaa2e125e4 100644 --- a/src/pages/Search/SearchTypeMenuNarrow.tsx +++ b/src/pages/Search/SearchTypeMenuNarrow.tsx @@ -84,20 +84,6 @@ function SearchTypeMenuNarrow({typeMenuItems, activeItemIndex, queryJSON, title, }; }); - if (title) { - items.push({ - text: title, - onSelected: closeMenu, - isSelected: !currentSavedSearch, - icon: Expensicons.Filters, - iconFill: theme.iconSuccessFill, - success: true, - containerStyle: undefined, - iconRight: Expensicons.Checkmark, - shouldShowRightIcon: false, - }); - } - return items; }, [typeMenuItems, activeItemIndex, title, theme, singleExecution, closeMenu, currentSavedSearch]); @@ -109,6 +95,7 @@ function SearchTypeMenuNarrow({typeMenuItems, activeItemIndex, queryJSON, title, text: item.title ?? '', styles: [styles.textSupporting], onSelected: item.onPress, + icon: Expensicons.Bookmark, shouldShowRightComponent: true, rightComponent: ( Date: Mon, 23 Sep 2024 13:46:51 +0700 Subject: [PATCH 35/73] fix lint --- src/pages/Search/SearchTypeMenuNarrow.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Search/SearchTypeMenuNarrow.tsx b/src/pages/Search/SearchTypeMenuNarrow.tsx index c8aaa2e125e4..3ba9857892d2 100644 --- a/src/pages/Search/SearchTypeMenuNarrow.tsx +++ b/src/pages/Search/SearchTypeMenuNarrow.tsx @@ -85,7 +85,7 @@ function SearchTypeMenuNarrow({typeMenuItems, activeItemIndex, queryJSON, title, }); return items; - }, [typeMenuItems, activeItemIndex, title, theme, singleExecution, closeMenu, currentSavedSearch]); + }, [typeMenuItems, activeItemIndex, title, theme, singleExecution]); const menuIcon = useMemo(() => (title ? Expensicons.Filters : popoverMenuItems[activeItemIndex]?.icon ?? Expensicons.Receipt), [activeItemIndex, popoverMenuItems, title]); const menuTitle = useMemo(() => title ?? popoverMenuItems[activeItemIndex]?.text, [activeItemIndex, popoverMenuItems, title]); From 5791e4aef6cc1376680f9e5741d0a6b7013c5fc8 Mon Sep 17 00:00:00 2001 From: mkzie2 Date: Mon, 23 Sep 2024 16:11:02 +0700 Subject: [PATCH 36/73] only remove viewing search if it's saved search --- src/pages/Search/SearchTypeMenuNarrow.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/pages/Search/SearchTypeMenuNarrow.tsx b/src/pages/Search/SearchTypeMenuNarrow.tsx index 3ba9857892d2..d0053f45be74 100644 --- a/src/pages/Search/SearchTypeMenuNarrow.tsx +++ b/src/pages/Search/SearchTypeMenuNarrow.tsx @@ -84,8 +84,22 @@ function SearchTypeMenuNarrow({typeMenuItems, activeItemIndex, queryJSON, title, }; }); + if (title && !currentSavedSearch) { + items.push({ + text: title, + onSelected: closeMenu, + isSelected: !currentSavedSearch, + icon: Expensicons.Filters, + iconFill: theme.iconSuccessFill, + success: true, + containerStyle: undefined, + iconRight: Expensicons.Checkmark, + shouldShowRightIcon: false, + }); + } + return items; - }, [typeMenuItems, activeItemIndex, title, theme, singleExecution]); + }, [typeMenuItems, activeItemIndex, title, theme, singleExecution, closeMenu, currentSavedSearch]); const menuIcon = useMemo(() => (title ? Expensicons.Filters : popoverMenuItems[activeItemIndex]?.icon ?? Expensicons.Receipt), [activeItemIndex, popoverMenuItems, title]); const menuTitle = useMemo(() => title ?? popoverMenuItems[activeItemIndex]?.text, [activeItemIndex, popoverMenuItems, title]); From edf4ee7e478cdf04a10912ba58d5cf2a4e2ce360 Mon Sep 17 00:00:00 2001 From: Abhinay Bathina Date: Tue, 24 Sep 2024 01:00:51 +0530 Subject: [PATCH 37/73] refactor: remove reportOrDraft variable and pass default value to canUserPerformWriteAction function only --- src/pages/iou/request/step/withWritableReportOrNotFound.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx index cd4dd4f93ba4..2361d58dc2be 100644 --- a/src/pages/iou/request/step/withWritableReportOrNotFound.tsx +++ b/src/pages/iou/request/step/withWritableReportOrNotFound.tsx @@ -57,17 +57,15 @@ export default function shouldIncludeDeprecatedIOUType || (type !== CONST.IOU.TYPE.REQUEST && type !== CONST.IOU.TYPE.SEND)) .includes(route.params?.iouType); const isEditing = 'action' in route.params && route.params?.action === CONST.IOU.ACTION.EDIT; - const canUserPerformWriteAction = ReportUtils.canUserPerformWriteAction(reportOrDefault); + const canUserPerformWriteAction = ReportUtils.canUserPerformWriteAction(report ?? {reportID: ''}); useEffect(() => { - if (!!reportOrDefault?.reportID || !route.params.reportID || !!reportDraft || !isEditing) { + if (!!report?.reportID || !route.params.reportID || !!reportDraft || !isEditing) { return; } ReportActions.openReport(route.params.reportID); From 841ca52a8d5250981103f6b6972558d2643741ee Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Mon, 23 Sep 2024 23:34:20 +0300 Subject: [PATCH 38/73] remove pending delete members name from default group chat name --- src/libs/ReportUtils.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index d38d3f8b950e..7bd57bd63efd 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2143,7 +2143,14 @@ function getGroupChatName(participants?: SelectedParticipant[], shouldApplyLimit return report.reportName; } - let participantAccountIDs = participants?.map((participant) => participant.accountID) ?? Object.keys(report?.participants ?? {}).map(Number); + let participantAccountIDs = + participants?.map((participant) => participant.accountID) ?? + Object.keys(report?.participants ?? {}) + .map(Number) + .filter((accountID) => { + const pendingMember = report?.pendingChatMembers?.find((member) => member.accountID === accountID.toString()); + return !(pendingMember && pendingMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); + }); if (shouldApplyLimit) { participantAccountIDs = participantAccountIDs.slice(0, 5); } From 2e7abce2aecc5b8e035e4f9a7655942b2124e808 Mon Sep 17 00:00:00 2001 From: Anusha Date: Tue, 24 Sep 2024 04:54:51 +0500 Subject: [PATCH 39/73] fix pressing tab --- src/pages/WorkspaceSwitcherPage/WorkspacesSectionHeader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/WorkspaceSwitcherPage/WorkspacesSectionHeader.tsx b/src/pages/WorkspaceSwitcherPage/WorkspacesSectionHeader.tsx index 18c3be9678c4..a550d5471072 100644 --- a/src/pages/WorkspaceSwitcherPage/WorkspacesSectionHeader.tsx +++ b/src/pages/WorkspaceSwitcherPage/WorkspacesSectionHeader.tsx @@ -30,7 +30,7 @@ function WorkspacesSectionHeader() { { const activeRoute = Navigation.getActiveRouteWithoutParams(); From aa9da686c8e4a45902fa7bbb37dd4b1009b364eb Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 24 Sep 2024 10:51:59 +0700 Subject: [PATCH 40/73] fix: 1:1 user receipt placeholder flickers --- src/pages/home/report/ReportActionsView.tsx | 52 ++++----------------- 1 file changed, 8 insertions(+), 44 deletions(-) diff --git a/src/pages/home/report/ReportActionsView.tsx b/src/pages/home/report/ReportActionsView.tsx index 1460942931fc..ff01997535c1 100755 --- a/src/pages/home/report/ReportActionsView.tsx +++ b/src/pages/home/report/ReportActionsView.tsx @@ -4,7 +4,7 @@ import lodashIsEqual from 'lodash/isEqual'; import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react'; import {InteractionManager} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx, withOnyx} from 'react-native-onyx'; import useCopySelectionHelper from '@hooks/useCopySelectionHelper'; import useInitialValue from '@hooks/useInitialValue'; import useNetwork from '@hooks/useNetwork'; @@ -34,18 +34,7 @@ import PopoverReactionList from './ReactionList/PopoverReactionList'; import ReportActionsList from './ReportActionsList'; import UserTypingEventListener from './UserTypingEventListener'; -type ReportActionsViewOnyxProps = { - /** Session info for the currently logged in user. */ - session: OnyxEntry; - - /** Array of report actions for the transaction thread report associated with the current report */ - transactionThreadReportActions: OnyxTypes.ReportAction[]; - - /** The transaction thread report associated with the current report, if any */ - transactionThreadReport: OnyxEntry; -}; - -type ReportActionsViewProps = ReportActionsViewOnyxProps & { +type ReportActionsViewProps = { /** The report currently being looked at */ report: OnyxTypes.Report; @@ -79,11 +68,8 @@ let listOldID = Math.round(Math.random() * 100); function ReportActionsView({ report, - transactionThreadReport, - session, parentReportAction, reportActions: allReportActions = [], - transactionThreadReportActions = [], isLoadingInitialReportActions = false, isLoadingOlderReportActions = false, hasLoadingOlderReportActionsError = false, @@ -94,6 +80,11 @@ function ReportActionsView({ useCopySelectionHelper(); const reactionListRef = useContext(ReactionListContext); const route = useRoute>(); + const [session] = useOnyx(ONYXKEYS.SESSION); + const [transactionThreadReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID || -1}`, { + selector: (reportActions: OnyxEntry) => ReportActionsUtils.getSortedReportActionsForDisplay(reportActions, true), + }); + const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID || -1}`); const reportActionID = route?.params?.reportActionID; const prevReportActionID = usePrevious(reportActionID); const didLayout = useRef(false); @@ -503,26 +494,14 @@ ReportActionsView.displayName = 'ReportActionsView'; ReportActionsView.initMeasured = false; function arePropsEqual(oldProps: ReportActionsViewProps, newProps: ReportActionsViewProps): boolean { - if (!lodashIsEqual(oldProps.transactionThreadReport, newProps.transactionThreadReport)) { - return false; - } - if (!lodashIsEqual(oldProps.reportActions, newProps.reportActions)) { return false; } - if (!lodashIsEqual(oldProps.transactionThreadReportActions, newProps.transactionThreadReportActions)) { - return false; - } - if (!lodashIsEqual(oldProps.parentReportAction, newProps.parentReportAction)) { return false; } - if (oldProps.session?.authTokenType !== newProps.session?.authTokenType) { - return false; - } - if (oldProps.isLoadingInitialReportActions !== newProps.isLoadingInitialReportActions) { return false; } @@ -548,19 +527,4 @@ function arePropsEqual(oldProps: ReportActionsViewProps, newProps: ReportActions const MemoizedReportActionsView = React.memo(ReportActionsView, arePropsEqual); -export default Performance.withRenderTrace({id: ' rendering'})( - withOnyx({ - session: { - key: ONYXKEYS.SESSION, - }, - transactionThreadReportActions: { - key: ({transactionThreadReportID}) => `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID ?? -1}`, - canEvict: false, - selector: (reportActions: OnyxEntry) => ReportActionsUtils.getSortedReportActionsForDisplay(reportActions, true), - }, - transactionThreadReport: { - key: ({transactionThreadReportID}) => `${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID ?? -1}`, - initialValue: {} as OnyxTypes.Report, - }, - })(MemoizedReportActionsView), -); +export default Performance.withRenderTrace({id: ' rendering'})(MemoizedReportActionsView); From 5e306c8cec4a846da90ab76ee72d9e3d0d801c6d Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 24 Sep 2024 10:54:49 +0700 Subject: [PATCH 41/73] fix: Unable to create a new line in description field with SHIFT+Enter --- src/components/Button/validateSubmitShortcut/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Button/validateSubmitShortcut/index.ts b/src/components/Button/validateSubmitShortcut/index.ts index f8cea44f73d6..29ba071c25f2 100644 --- a/src/components/Button/validateSubmitShortcut/index.ts +++ b/src/components/Button/validateSubmitShortcut/index.ts @@ -11,7 +11,7 @@ import type ValidateSubmitShortcut from './types'; const validateSubmitShortcut: ValidateSubmitShortcut = (isDisabled, isLoading, event) => { const eventTarget = event?.target as HTMLElement; - if (isDisabled || isLoading || eventTarget.nodeName === 'TEXTAREA') { + if (isDisabled || isLoading || eventTarget.nodeName === 'TEXTAREA' || (eventTarget?.contentEditable === 'true' && eventTarget.ariaMultiLine)) { return false; } From 2332436f4b6913f3f6f4895db799bc17768a834f Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Tue, 24 Sep 2024 14:36:16 +0800 Subject: [PATCH 42/73] fix text blinking --- src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx index f23b136c76d0..6b803b42302b 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx @@ -345,10 +345,10 @@ function BaseValidateCodeForm( )} {hasError && } Date: Tue, 24 Sep 2024 14:59:04 +0800 Subject: [PATCH 43/73] migrate to useOnyx --- .../ValidateCodeForm/BaseValidateCodeForm.tsx | 34 ++++--------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx index 6b803b42302b..f73c0a1602fb 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx @@ -2,8 +2,7 @@ import {useIsFocused} from '@react-navigation/native'; import React, {forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState} from 'react'; import type {ForwardedRef} from 'react'; import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import Button from '@components/Button'; import SafariFormWrapper from '@components/Form/SafariFormWrapper'; import FormHelpMessage from '@components/FormHelpMessage'; @@ -30,24 +29,11 @@ import * as User from '@userActions/User'; import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; -import type {Account, Credentials, Session} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type ValidateCodeFormProps from './types'; -type BaseValidateCodeFormOnyxProps = { - /** The details about the account that the user is signing in with */ - account: OnyxEntry; - - /** The credentials of the person logging in */ - credentials: OnyxEntry; - - /** Session info for the currently logged in user. */ - session: OnyxEntry; -}; - type BaseValidateCodeFormProps = WithToggleVisibilityViewProps & - ValidateCodeFormProps & - BaseValidateCodeFormOnyxProps & { + ValidateCodeFormProps & { /** Specifies autocomplete hints for the system, so it can provide autofill */ autoComplete: 'sms-otp' | 'one-time-code'; }; @@ -60,10 +46,10 @@ type ValidateCodeFormVariant = 'validateCode' | 'twoFactorAuthCode' | 'recoveryC type FormError = Partial>; -function BaseValidateCodeForm( - {account, credentials, session, autoComplete, isUsingRecoveryCode, setIsUsingRecoveryCode, isVisible}: BaseValidateCodeFormProps, - forwardedRef: ForwardedRef, -) { +function BaseValidateCodeForm({autoComplete, isUsingRecoveryCode, setIsUsingRecoveryCode, isVisible}: BaseValidateCodeFormProps, forwardedRef: ForwardedRef) { + const [account] = useOnyx(ONYXKEYS.ACCOUNT); + const [credentials] = useOnyx(ONYXKEYS.CREDENTIALS); + const [session] = useOnyx(ONYXKEYS.SESSION); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); const {translate} = useLocalize(); @@ -422,12 +408,6 @@ function BaseValidateCodeForm( BaseValidateCodeForm.displayName = 'BaseValidateCodeForm'; -export default withToggleVisibilityView( - withOnyx({ - account: {key: ONYXKEYS.ACCOUNT}, - credentials: {key: ONYXKEYS.CREDENTIALS}, - session: {key: ONYXKEYS.SESSION}, - })(forwardRef(BaseValidateCodeForm)), -); +export default withToggleVisibilityView(forwardRef(BaseValidateCodeForm)); export type {BaseValidateCodeFormRef}; From 3ca7e4c7367a06e6329bee416cbf13af54c762f2 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Tue, 24 Sep 2024 15:43:59 +0700 Subject: [PATCH 44/73] fix lint --- src/pages/home/report/ReportActionsView.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/home/report/ReportActionsView.tsx b/src/pages/home/report/ReportActionsView.tsx index ff01997535c1..9337cbc2196d 100755 --- a/src/pages/home/report/ReportActionsView.tsx +++ b/src/pages/home/report/ReportActionsView.tsx @@ -4,7 +4,7 @@ import lodashIsEqual from 'lodash/isEqual'; import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react'; import {InteractionManager} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {useOnyx, withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import useCopySelectionHelper from '@hooks/useCopySelectionHelper'; import useInitialValue from '@hooks/useInitialValue'; import useNetwork from '@hooks/useNetwork'; @@ -81,10 +81,10 @@ function ReportActionsView({ const reactionListRef = useContext(ReactionListContext); const route = useRoute>(); const [session] = useOnyx(ONYXKEYS.SESSION); - const [transactionThreadReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID || -1}`, { + const [transactionThreadReportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${transactionThreadReportID ?? -1}`, { selector: (reportActions: OnyxEntry) => ReportActionsUtils.getSortedReportActionsForDisplay(reportActions, true), }); - const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID || -1}`); + const [transactionThreadReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${transactionThreadReportID ?? -1}`); const reportActionID = route?.params?.reportActionID; const prevReportActionID = usePrevious(reportActionID); const didLayout = useRef(false); @@ -202,7 +202,7 @@ function ReportActionsView({ // Get a sorted array of reportActions for both the current report and the transaction thread report associated with this report (if there is one) // so that we display transaction-level and report-level report actions in order in the one-transaction view const combinedReportActions = useMemo( - () => ReportActionsUtils.getCombinedReportActions(reportActionsToDisplay, transactionThreadReportID ?? null, transactionThreadReportActions), + () => ReportActionsUtils.getCombinedReportActions(reportActionsToDisplay, transactionThreadReportID ?? null, transactionThreadReportActions as OnyxTypes.ReportAction[]), [reportActionsToDisplay, transactionThreadReportActions, transactionThreadReportID], ); From ca6f5a018adbb791be0cda3da255821c337c32ea Mon Sep 17 00:00:00 2001 From: mkzie2 Date: Tue, 24 Sep 2024 16:19:17 +0700 Subject: [PATCH 45/73] fix icon fill --- src/pages/Search/SearchTypeMenuNarrow.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/Search/SearchTypeMenuNarrow.tsx b/src/pages/Search/SearchTypeMenuNarrow.tsx index d0053f45be74..4d51044c47dd 100644 --- a/src/pages/Search/SearchTypeMenuNarrow.tsx +++ b/src/pages/Search/SearchTypeMenuNarrow.tsx @@ -110,6 +110,7 @@ function SearchTypeMenuNarrow({typeMenuItems, activeItemIndex, queryJSON, title, styles: [styles.textSupporting], onSelected: item.onPress, icon: Expensicons.Bookmark, + iconFill: currentSavedSearch?.hash === item.hash ? theme.iconSuccessFill : theme.icon, shouldShowRightComponent: true, rightComponent: ( Date: Tue, 24 Sep 2024 17:01:28 +0700 Subject: [PATCH 46/73] fix lint --- src/pages/home/report/ReportActionsView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionsView.tsx b/src/pages/home/report/ReportActionsView.tsx index 9337cbc2196d..578c06c6dc9f 100755 --- a/src/pages/home/report/ReportActionsView.tsx +++ b/src/pages/home/report/ReportActionsView.tsx @@ -202,7 +202,7 @@ function ReportActionsView({ // Get a sorted array of reportActions for both the current report and the transaction thread report associated with this report (if there is one) // so that we display transaction-level and report-level report actions in order in the one-transaction view const combinedReportActions = useMemo( - () => ReportActionsUtils.getCombinedReportActions(reportActionsToDisplay, transactionThreadReportID ?? null, transactionThreadReportActions as OnyxTypes.ReportAction[]), + () => ReportActionsUtils.getCombinedReportActions(reportActionsToDisplay, transactionThreadReportID ?? null, transactionThreadReportActions! as OnyxTypes.ReportAction[]), [reportActionsToDisplay, transactionThreadReportActions, transactionThreadReportID], ); From 008b5541f9891af535ff99d49f149d41c6894197 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 24 Sep 2024 15:44:41 +0300 Subject: [PATCH 47/73] refactored code --- src/libs/ReportUtils.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/ReportUtils.ts b/src/libs/ReportUtils.ts index 7bd57bd63efd..bfd8c93be89f 100644 --- a/src/libs/ReportUtils.ts +++ b/src/libs/ReportUtils.ts @@ -2143,14 +2143,14 @@ function getGroupChatName(participants?: SelectedParticipant[], shouldApplyLimit return report.reportName; } + const pendingMemberAccountIDs = new Set( + report?.pendingChatMembers?.filter((member) => member.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE).map((member) => member.accountID), + ); let participantAccountIDs = participants?.map((participant) => participant.accountID) ?? Object.keys(report?.participants ?? {}) .map(Number) - .filter((accountID) => { - const pendingMember = report?.pendingChatMembers?.find((member) => member.accountID === accountID.toString()); - return !(pendingMember && pendingMember.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE); - }); + .filter((accountID) => !pendingMemberAccountIDs.has(accountID.toString())); if (shouldApplyLimit) { participantAccountIDs = participantAccountIDs.slice(0, 5); } From 74c357d8c22f8473acb30499e92a31875b37fa00 Mon Sep 17 00:00:00 2001 From: Muaaz Arshad <111155000+MuaazArshad@users.noreply.github.com> Date: Tue, 24 Sep 2024 19:56:03 +0500 Subject: [PATCH 48/73] fix lint --- src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx index f6b8746c591e..1fb7cfbc94ab 100644 --- a/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx +++ b/src/pages/settings/ExitSurvey/ExitSurveyResponsePage.tsx @@ -1,5 +1,5 @@ import type {StackScreenProps} from '@react-navigation/stack'; -import React, {useCallback, useEffect, useState} from 'react'; +import React, {useCallback, useEffect} from 'react'; import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; From 2b210c705b12ccbdbaf81d61f11eeaa1dede200e Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Tue, 24 Sep 2024 17:28:03 +0200 Subject: [PATCH 49/73] feat: bump react-native-haptic-feedback to newest version and remove unnecessary patch --- ios/Podfile.lock | 8 +-- package-lock.json | 8 +-- package.json | 2 +- .../react-native-haptic-feedback+2.3.1.patch | 56 ------------------- 4 files changed, 9 insertions(+), 65 deletions(-) delete mode 100644 patches/react-native-haptic-feedback+2.3.1.patch diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 0f1a42791d1e..8bcfe1515ca5 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -144,7 +144,7 @@ PODS: - "GoogleUtilities/NSData+zlib (~> 7.7)" - fmt (9.1.0) - FullStory (1.49.0) - - fullstory_react-native (1.4.2): + - fullstory_react-native (1.7.1): - DoubleConversion - FullStory (~> 1.14) - glog @@ -2451,7 +2451,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - RNReactNativeHapticFeedback (2.3.1): + - RNReactNativeHapticFeedback (2.3.3): - DoubleConversion - glog - hermes-engine @@ -3117,7 +3117,7 @@ SPEC CHECKSUMS: FirebaseRemoteConfig: 2d6e2cfdb49af79535c8af8a80a4a5009038ec2b fmt: 4c2741a687cc09f0634a2e2c72a838b99f1ff120 FullStory: c95f74445f871bc344cdc4a4e4ece61b5554e55d - fullstory_react-native: 1818ee93dc38801665f26869f7ad68abb698a89a + fullstory_react-native: 44dc2c85a6316df2713e6cb0048ce5719c3b0bab glog: 69ef571f3de08433d766d614c73a9838a06bf7eb GoogleAppMeasurement: 5ba1164e3c844ba84272555e916d0a6d3d977e91 GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a @@ -3233,7 +3233,7 @@ SPEC CHECKSUMS: RNLocalize: d4b8af4e442d4bcca54e68fc687a2129b4d71a81 rnmapbox-maps: 460d6ff97ae49c7d5708c3212c6521697c36a0c4 RNPermissions: 0b1429b55af59d1d08b75a8be2459f65a8ac3f28 - RNReactNativeHapticFeedback: 31833c3ef341d716dbbd9d64e940f0c230db46f6 + RNReactNativeHapticFeedback: 73756a3477a5a622fa16862a3ab0d0fc5e5edff5 RNReanimated: 76901886830e1032f16bbf820153f7dc3f02d51d RNScreens: de6e57426ba0e6cbc3fb5b4f496e7f08cb2773c2 RNShare: bd4fe9b95d1ee89a200778cc0753ebe650154bb0 diff --git a/package-lock.json b/package-lock.json index 3c27c44a3bd7..bcc38ef02134 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,7 +85,7 @@ "react-native-fs": "^2.20.0", "react-native-gesture-handler": "2.18.0", "react-native-google-places-autocomplete": "2.5.6", - "react-native-haptic-feedback": "^2.3.1", + "react-native-haptic-feedback": "^2.3.3", "react-native-image-picker": "^7.0.3", "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#cb392140db4953a283590d7cf93b4d0461baa2a9", "react-native-key-command": "^1.0.8", @@ -34543,9 +34543,9 @@ } }, "node_modules/react-native-haptic-feedback": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/react-native-haptic-feedback/-/react-native-haptic-feedback-2.3.1.tgz", - "integrity": "sha512-dPfjV4iVHfhVyfG+nRd88ygjahbdup7KFZDM5L2aNIAzqbNtKxHZn5O1pHegwSj1t15VJliu0GyTX7XpBDeXUw==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/react-native-haptic-feedback/-/react-native-haptic-feedback-2.3.3.tgz", + "integrity": "sha512-svS4D5PxfNv8o68m9ahWfwje5NqukM3qLS48+WTdhbDkNUkOhP9rDfDSRHzlhk4zq+ISjyw95EhLeh8NkKX5vQ==", "workspaces": [ "example" ], diff --git a/package.json b/package.json index 6f4980f04ee0..cc0ca056cc1c 100644 --- a/package.json +++ b/package.json @@ -142,7 +142,7 @@ "react-native-fs": "^2.20.0", "react-native-gesture-handler": "2.18.0", "react-native-google-places-autocomplete": "2.5.6", - "react-native-haptic-feedback": "^2.3.1", + "react-native-haptic-feedback": "^2.3.3", "react-native-image-picker": "^7.0.3", "react-native-image-size": "git+https://github.com/Expensify/react-native-image-size#cb392140db4953a283590d7cf93b4d0461baa2a9", "react-native-key-command": "^1.0.8", diff --git a/patches/react-native-haptic-feedback+2.3.1.patch b/patches/react-native-haptic-feedback+2.3.1.patch deleted file mode 100644 index 799bdaf7e53e..000000000000 --- a/patches/react-native-haptic-feedback+2.3.1.patch +++ /dev/null @@ -1,56 +0,0 @@ -diff --git a/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedback.h b/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedback.h -index c1498b9..250df1f 100644 ---- a/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedback.h -+++ b/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedback.h -@@ -1,5 +1,5 @@ - #ifdef RCT_NEW_ARCH_ENABLED --#import "RNHapticFeedbackSpec.h" -+#import - - @interface RNHapticFeedback : NSObject - #else -diff --git a/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedbackSpec.h b/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedbackSpec.h -deleted file mode 100644 -index 6f0f81d..0000000 ---- a/node_modules/react-native-haptic-feedback/ios/RNHapticFeedback/RNHapticFeedbackSpec.h -+++ /dev/null -@@ -1,15 +0,0 @@ --// --// RNHapticFeedbackSpec.h --// RNHapticFeedback --// --// Created by Michael Kuczera on 05.08.24. --// Copyright © 2024 Facebook. All rights reserved. --// --#import -- --@protocol NativeHapticFeedbackSpec -- --// Indicates whether the device supports haptic feedback --- (Boolean)supportsHaptic; -- --@end -diff --git a/node_modules/react-native-haptic-feedback/package.json b/node_modules/react-native-haptic-feedback/package.json -index 86dfaa4..9cec8e4 100644 ---- a/node_modules/react-native-haptic-feedback/package.json -+++ b/node_modules/react-native-haptic-feedback/package.json -@@ -6,18 +6,7 @@ - "source": "src/index.ts", - "main": "./lib/commonjs/index.js", - "module": "./lib/module/index.js", -- "exports": { -- ".": { -- "import": { -- "types": "./lib/typescript/module/src/index.d.ts", -- "default": "./lib/module/index.js" -- }, -- "require": { -- "types": "./lib/typescript/commonjs/src/index.d.ts", -- "default": "./lib/commonjs/index.js" -- } -- } -- }, -+ "types": "./lib/typescript/module/src/index.d.ts", - "scripts": { - "typecheck": "tsc --noEmit --project tsconfig.test.json", - "test": "jest", From 010fcb0f516317010737c3d58dbe70ad891d90d2 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Tue, 24 Sep 2024 18:32:44 +0300 Subject: [PATCH 50/73] fixed similar problem in header view --- src/pages/home/HeaderView.tsx | 2 +- src/pages/home/ReportScreen.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/home/HeaderView.tsx b/src/pages/home/HeaderView.tsx index 14ed4b583baf..51582f0b2092 100644 --- a/src/pages/home/HeaderView.tsx +++ b/src/pages/home/HeaderView.tsx @@ -65,7 +65,7 @@ function HeaderView({report, parentReportAction, reportID, onNavigationMenuButto const isSelfDM = ReportUtils.isSelfDM(report); const isGroupChat = ReportUtils.isGroupChat(report) || ReportUtils.isDeprecatedGroupDM(report); - const participants = ReportUtils.getParticipantsAccountIDsForDisplay(report).slice(0, 5); + const participants = ReportUtils.getParticipantsAccountIDsForDisplay(report, false, true).slice(0, 5); const isMultipleParticipant = participants.length > 1; const participantPersonalDetails = OptionsListUtils.getPersonalDetailsForAccountIDs(participants, personalDetails); diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index b8b551a345ca..baf48775011f 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -211,6 +211,7 @@ function ReportScreen({route, currentReportID = '', navigation}: ReportScreenPro permissions, invoiceReceiver: reportOnyx.invoiceReceiver, policyAvatar: reportOnyx.policyAvatar, + pendingChatMembers: reportOnyx.pendingChatMembers, }, [reportOnyx, permissions], ); From 68e75a0031280953121dbebd2a3126aa6f863a00 Mon Sep 17 00:00:00 2001 From: Anusha Date: Tue, 24 Sep 2024 22:16:11 +0500 Subject: [PATCH 51/73] migrate to useOnyx --- .../step/IOURequestStepConfirmation.tsx | 52 ++++--------------- 1 file changed, 9 insertions(+), 43 deletions(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index 31c3fc69996f..bf618aa87421 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -1,7 +1,7 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Expensicons from '@components/Icon/Expensicons'; @@ -41,33 +41,10 @@ import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; import type {WithWritableReportOrNotFoundProps} from './withWritableReportOrNotFound'; import withWritableReportOrNotFound from './withWritableReportOrNotFound'; -type IOURequestStepConfirmationOnyxProps = { - /** The policy of the report */ - policy: OnyxEntry; - - /** The draft policy of the report */ - policyDraft: OnyxEntry; - - /** The category configuration of the report's policy */ - policyCategories: OnyxEntry; - - /** The draft category configuration of the report's policy */ - policyCategoriesDraft: OnyxEntry; - - /** The tag configuration of the report's policy */ - policyTags: OnyxEntry; -}; - -type IOURequestStepConfirmationProps = IOURequestStepConfirmationOnyxProps & - WithWritableReportOrNotFoundProps & +type IOURequestStepConfirmationProps = WithWritableReportOrNotFoundProps & WithFullTransactionOrNotFoundProps; function IOURequestStepConfirmation({ - policy: policyReal, - policyDraft, - policyTags, - policyCategories: policyCategoriesReal, - policyCategoriesDraft, report: reportReal, reportDraft, route: { @@ -78,6 +55,12 @@ function IOURequestStepConfirmation({ const currentUserPersonalDetails = useCurrentUserPersonalDetails(); const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT; + const [policyDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${IOU.getIOURequestPolicyID(transaction, reportDraft)}`); + const [policyReal] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${IOU.getIOURequestPolicyID(transaction, reportReal)}`); + const [policyCategoriesReal] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${IOU.getIOURequestPolicyID(transaction, reportReal)}`); + const [policyCategoriesDraft] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${IOU.getIOURequestPolicyID(transaction, reportDraft)}`); + const [policyTags] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_TAGS}${IOU.getIOURequestPolicyID(transaction, reportReal)}`); + const report = reportReal ?? reportDraft; const policy = policyReal ?? policyDraft; const policyCategories = policyCategoriesReal ?? policyCategoriesDraft; @@ -664,25 +647,8 @@ function IOURequestStepConfirmation({ IOURequestStepConfirmation.displayName = 'IOURequestStepConfirmation'; -const IOURequestStepConfirmationWithOnyx = withOnyx({ - policy: { - key: ({report, transaction}) => `${ONYXKEYS.COLLECTION.POLICY}${IOU.getIOURequestPolicyID(transaction, report)}`, - }, - policyDraft: { - key: ({reportDraft, transaction}) => `${ONYXKEYS.COLLECTION.POLICY_DRAFTS}${IOU.getIOURequestPolicyID(transaction, reportDraft)}`, - }, - policyCategories: { - key: ({report, transaction}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${IOU.getIOURequestPolicyID(transaction, report)}`, - }, - policyCategoriesDraft: { - key: ({reportDraft, transaction}) => `${ONYXKEYS.COLLECTION.POLICY_CATEGORIES_DRAFT}${IOU.getIOURequestPolicyID(transaction, reportDraft)}`, - }, - policyTags: { - key: ({report, transaction}) => `${ONYXKEYS.COLLECTION.POLICY_TAGS}${IOU.getIOURequestPolicyID(transaction, report)}`, - }, -})(IOURequestStepConfirmation); /* eslint-disable rulesdir/no-negated-variables */ -const IOURequestStepConfirmationWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepConfirmationWithOnyx); +const IOURequestStepConfirmationWithFullTransactionOrNotFound = withFullTransactionOrNotFound(IOURequestStepConfirmation); /* eslint-disable rulesdir/no-negated-variables */ const IOURequestStepConfirmationWithWritableReportOrNotFound = withWritableReportOrNotFound(IOURequestStepConfirmationWithFullTransactionOrNotFound); export default IOURequestStepConfirmationWithWritableReportOrNotFound; From cffd880df2d8d545675b9ea46f116704510c9e91 Mon Sep 17 00:00:00 2001 From: Anusha Date: Tue, 24 Sep 2024 22:22:56 +0500 Subject: [PATCH 52/73] fix lint errors --- src/pages/iou/request/step/IOURequestStepConfirmation.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index bf618aa87421..b08f9a6ced5f 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -32,7 +32,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {Policy, PolicyCategories, PolicyTagLists} from '@src/types/onyx'; import type {Participant} from '@src/types/onyx/IOU'; import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type {Receipt} from '@src/types/onyx/Transaction'; From b5a4e3aa81febcff2285442470a617f54843360f Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Wed, 25 Sep 2024 07:35:40 +0530 Subject: [PATCH 53/73] fix tests --- tests/ui/PaginationTest.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/ui/PaginationTest.tsx b/tests/ui/PaginationTest.tsx index 9d120433daa1..d27b95f36ed5 100644 --- a/tests/ui/PaginationTest.tsx +++ b/tests/ui/PaginationTest.tsx @@ -238,6 +238,9 @@ async function signInAndGetApp(): Promise { }, }); + await Onyx.set(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT, 1) + await Onyx.set(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID, "1") + // We manually setting the sidebar as loaded since the onLayout event does not fire in tests AppActions.setSidebarLoaded(); }); From 99b3b90db3f7bb1719afa0d01269cf364db82cc3 Mon Sep 17 00:00:00 2001 From: truph01 Date: Wed, 25 Sep 2024 09:12:42 +0700 Subject: [PATCH 54/73] feat: move intro text to ScrollView --- src/pages/workspace/WorkspaceMoreFeaturesPage.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx index 0182f1ea8827..a743140278f7 100644 --- a/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx +++ b/src/pages/workspace/WorkspaceMoreFeaturesPage.tsx @@ -409,11 +409,13 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro title={translate('workspace.common.moreFeatures')} shouldShowBackButton={shouldUseNarrowLayout} /> - - {translate('workspace.moreFeatures.subtitle')} - - {sections.map(renderSection)} + + + {translate('workspace.moreFeatures.subtitle')} + + {sections.map(renderSection)} + Date: Wed, 25 Sep 2024 07:45:25 +0530 Subject: [PATCH 55/73] fix lint --- tests/ui/PaginationTest.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/ui/PaginationTest.tsx b/tests/ui/PaginationTest.tsx index d27b95f36ed5..290f0d28fb9b 100644 --- a/tests/ui/PaginationTest.tsx +++ b/tests/ui/PaginationTest.tsx @@ -238,8 +238,9 @@ async function signInAndGetApp(): Promise { }, }); - await Onyx.set(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT, 1) - await Onyx.set(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID, "1") + await Onyx.set(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT, 1); + + await Onyx.set(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID, '1'); // We manually setting the sidebar as loaded since the onLayout event does not fire in tests AppActions.setSidebarLoaded(); From 99edd392902500abf2fec6dd9e32f3e3c7daebbf Mon Sep 17 00:00:00 2001 From: BhuvaneshPatil Date: Wed, 25 Sep 2024 07:50:43 +0530 Subject: [PATCH 56/73] fix test --- tests/ui/UnreadIndicatorsTest.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/ui/UnreadIndicatorsTest.tsx b/tests/ui/UnreadIndicatorsTest.tsx index c9cdd81cf9ba..c133e000a51f 100644 --- a/tests/ui/UnreadIndicatorsTest.tsx +++ b/tests/ui/UnreadIndicatorsTest.tsx @@ -181,6 +181,10 @@ function signInAndGetAppWithUnreadChat(): Promise { [USER_B_ACCOUNT_ID]: TestHelper.buildPersonalDetails(USER_B_EMAIL, USER_B_ACCOUNT_ID, 'B'), }); + await Onyx.set(ONYXKEYS.ONYX_UPDATES_LAST_UPDATE_ID_APPLIED_TO_CLIENT, 1); + + await Onyx.set(ONYXKEYS.LAST_OPENED_PUBLIC_ROOM_ID, '1'); + // We manually setting the sidebar as loaded since the onLayout event does not fire in tests AppActions.setSidebarLoaded(); return waitForBatchedUpdatesWithAct(); From bf5dc7d4837e2c779bd5e9617fb67c5a5e7a42ab Mon Sep 17 00:00:00 2001 From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:17:22 -1000 Subject: [PATCH 57/73] Create Add-approvals.md Create new helpdot page for workspace Add approvals feature --- .../new-expensify/workspaces/Add-approvals.md | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 docs/articles/new-expensify/workspaces/Add-approvals.md diff --git a/docs/articles/new-expensify/workspaces/Add-approvals.md b/docs/articles/new-expensify/workspaces/Add-approvals.md new file mode 100644 index 000000000000..d66eaca23c37 --- /dev/null +++ b/docs/articles/new-expensify/workspaces/Add-approvals.md @@ -0,0 +1,73 @@ +--- +title: Add approvals +description: Add approvals to your workspace to require additional approval before authorizing payments. +--- +
+ +# Add approvals + +Each Expensify workspace can be configured to require additional approvals before payments are authorized. Once approvals are enabled on a workspace, admins will be able to set a default approval workflow to apply to all members of the workspace, as well as set custom approval workflows for specific members. + +When workspace members submit expenses, the expenses will require approval from each approver in the approval workflow before payment is authorized. + +## Add approvals on a workspace + +**To enable Add approvals on a workspace you are an admin on:** + +1. Click your profile image or icon in the bottom left menu +2. Click *Workspaces* in the left menu +3. Select the workspace where you want to add approvals +4. Click *Workflows* in the left menu +5. Click the toggle next to *Add approvals* + +Toggling on **Add approvals** will reveal an option to set a default approval workflow. + +## Configure approval workflows + +**To configure the default approval workflow for the workspace:** + +1. Click your profile image or icon in the bottom left menu +2. Click **Workspaces** in the left menu +3. Select the workspace where you want to set the approval workflow +4. Click **Workflows** in the left menu +5. Under **Expenses from Everyone**, click on **First approver** +6. Select the workspace member who should be the first approver in the approval workflow +7. Under **Additional approver**, continue selecting workspace members until all the desired approvers are listed +8. Click **Save** + +Note: When Add approvals is enabled, the workspace must have a default approval workflow. + +**To set an approval workflow that applies only to specific workspace members:** + +1. Click your profile image or icon in the bottom left menu +2. Click **Workspaces** in the left menu +3. Select the workspace where you want to add approvals +4. Click **Workflows** in the left menu +5. Under **Add approvals**, click on **Add approval workflow** +6. Choose the workspace member whose expenses should go through the custom approval workfow +7. Click **Next** +8. Choose the workspace member who should be the first approver on submitted expenses in the approval workflow +9. Click **Next** +10. Click **Additional approver** to continue selecting workspace members until all the desired approvers are listed +11. Click **Add workflow** to save it + +## Edit or delete approval workflows + +**To edit an approval workflow:** + +1. On the **Workflows** page, click the approval workflow that should be edited +2. Click on the Approver field for the approval level where the edit should be made +3. Choose the workspace member who should be set as the approver for that level, or deselect them to remove the approval level from the workflow +4. Click **Save** + +**To delete an approval workflow:** + +1. On the **Workflows** page, click the approval workflow that shoudld be deleted +2. Click **Delete** +3. In the window that appears,click **Delete** again + +# FAQ + +## Can an employee have more than one approval workflow? +No, each employee can have only one approval workflow + From 9b49655b6a5e961a9d9e47f575bc768daee021ab Mon Sep 17 00:00:00 2001 From: Stephanie Elliott <31225194+stephanieelliott@users.noreply.github.com> Date: Tue, 24 Sep 2024 17:27:18 -1000 Subject: [PATCH 58/73] Update Add-approvals.md --- docs/articles/new-expensify/workspaces/Add-approvals.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/articles/new-expensify/workspaces/Add-approvals.md b/docs/articles/new-expensify/workspaces/Add-approvals.md index d66eaca23c37..5d8c1f733287 100644 --- a/docs/articles/new-expensify/workspaces/Add-approvals.md +++ b/docs/articles/new-expensify/workspaces/Add-approvals.md @@ -8,17 +8,17 @@ description: Add approvals to your workspace to require additional approval befo Each Expensify workspace can be configured to require additional approvals before payments are authorized. Once approvals are enabled on a workspace, admins will be able to set a default approval workflow to apply to all members of the workspace, as well as set custom approval workflows for specific members. -When workspace members submit expenses, the expenses will require approval from each approver in the approval workflow before payment is authorized. +When workspace members submit expenses, the expenses will require approval from each approver in their approval workflow before payment is authorized. ## Add approvals on a workspace **To enable Add approvals on a workspace you are an admin on:** 1. Click your profile image or icon in the bottom left menu -2. Click *Workspaces* in the left menu +2. Click **Workspaces** in the left menu 3. Select the workspace where you want to add approvals -4. Click *Workflows* in the left menu -5. Click the toggle next to *Add approvals* +4. Click **Workflows** in the left menu +5. Click the toggle next to **Add approvals** Toggling on **Add approvals** will reveal an option to set a default approval workflow. From 41079724bd426c4c1d614c3f259e09d35e821fe2 Mon Sep 17 00:00:00 2001 From: daledah Date: Wed, 25 Sep 2024 10:30:22 +0700 Subject: [PATCH 59/73] fix: tooltip show over dialog --- .../BaseEducationalTooltip.tsx | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx index d0ff254324ae..463a69acf0d8 100644 --- a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx +++ b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx @@ -1,7 +1,9 @@ import React, {memo, useEffect, useRef, useState} from 'react'; import type {LayoutRectangle, NativeSyntheticEvent} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; import GenericTooltip from '@components/Tooltip/GenericTooltip'; import type {EducationalTooltipProps} from '@components/Tooltip/types'; +import ONYXKEYS from '@src/ONYXKEYS'; import measureTooltipCoordinate from './measureTooltipCoordinate'; type LayoutChangeEventWithTarget = NativeSyntheticEvent<{layout: LayoutRectangle; target: HTMLElement}>; @@ -15,6 +17,10 @@ function BaseEducationalTooltip({children, shouldAutoDismiss = false, shouldRend const [shouldMeasure, setShouldMeasure] = useState(false); const show = useRef<() => void>(); + const [modal] = useOnyx(ONYXKEYS.MODAL); + + const shouldShow = !modal?.willAlertModalBecomeVisible && !modal?.isVisible; + const didShowRef = useRef(false); useEffect( () => () => { @@ -33,21 +39,29 @@ function BaseEducationalTooltip({children, shouldAutoDismiss = false, shouldRend return; } + // If the modal is open, hide the tooltip immediately and clear the timeout + if (!shouldShow) { + hideTooltipRef.current(); + return; + } + + // Automatically hide tooltip after 5 seconds if shouldAutoDismiss is true const timerID = setTimeout(hideTooltipRef.current, 5000); return () => { clearTimeout(timerID); }; - }, [shouldAutoDismiss]); + }, [shouldAutoDismiss, shouldShow]); useEffect(() => { - if (!shouldRender || !shouldMeasure) { + if (!shouldRender || !shouldMeasure || !shouldShow || didShowRef.current) { return; } // When tooltip is used inside an animated view (e.g. popover), we need to wait for the animation to finish before measuring content. setTimeout(() => { + didShowRef.current = true; show.current?.(); }, 500); - }, [shouldMeasure, shouldRender]); + }, [shouldMeasure, shouldRender, shouldShow]); return ( Date: Tue, 24 Sep 2024 17:37:58 -1000 Subject: [PATCH 60/73] Create Set-distance-rates.md Create new helpdot page for setting distance rates on workspaces --- .../workspaces/Set-distance-rates.md | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 docs/articles/new-expensify/workspaces/Set-distance-rates.md diff --git a/docs/articles/new-expensify/workspaces/Set-distance-rates.md b/docs/articles/new-expensify/workspaces/Set-distance-rates.md new file mode 100644 index 000000000000..c434f34d2cef --- /dev/null +++ b/docs/articles/new-expensify/workspaces/Set-distance-rates.md @@ -0,0 +1,50 @@ +--- +title: Set Distance Rates +description: Set distance rates on your Expensify workspace +--- +
+ +# Set Distance eates + +Each Expensify workspace can be configured with one or more distance rates. Once distance rates are enabled on your workspace, employees will be able to choose between the available rates to create distance expenses. + +## Enable distance rates on a workspace + +**To enable distance rates on a workspace you are an admin on:** + +1. Click your profile image or icon in the bottom left menu +2. Click **Workspaces** in the left menu +3. Select the workspace where you want to enable distance rates +4. Click **More features** in the left menu +5. Click the toggle next to **Distance rates** + +After toggling on distance rates, you will see a new **Distance rates** option in the left menu. + +## Add, delete, or edit distance rates + +**To add a distance rate:** + +1. Click your profile image or icon in the bottom left menu +2. Click **Workspaces** in the left menu +3. Select the workspace where you want to add distance rates +4. Click **Distance rates** in the left menu +5. Click **Add rate** in the top right +6. Enter a value, then click **Save** + +**To enable, disable, edit or delete a single distance rate:** + +1. Click the distance rate on the **Distance rates** settings page +2. To enable or disable the distance rate, click the toggle next to **Enable rate**, then click **Save** +3. To edit the rate amount, click on the amount field, enter the new value, then click **Save** +4. To permanently delete the distance rate, click **Delete** + +Note: When Distance rates is enabled, the workspace must have at least one enabled distance rate. + +**To enable, disable, edit or delete distance rates in bulk:** + +1. On the **Distance rates** settings page, click the checkboxes next to the distance rates that should me modified +2. Click “x selected” at the top right +3. To enable or disable all the selected distance rates, click **Enable rates** or **Disable rates** +4. To permanently delete the distance rates, click **Delete rates** + +Note: When Distance rates are enabled, the workspace must have at least one enabled distance rate. From fa3c9b54c30fae44f6a9a494410fcbd8d8f726bb Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Wed, 25 Sep 2024 12:21:30 +0800 Subject: [PATCH 61/73] fix wrong avatar x position --- src/components/AccountSwitcherSkeletonView/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AccountSwitcherSkeletonView/index.tsx b/src/components/AccountSwitcherSkeletonView/index.tsx index 3faf7e563f3c..379a4094e032 100644 --- a/src/components/AccountSwitcherSkeletonView/index.tsx +++ b/src/components/AccountSwitcherSkeletonView/index.tsx @@ -22,7 +22,7 @@ function AccountSwitcherSkeletonView({shouldAnimate = true, avatarSize = CONST.A const StyleUtils = useStyleUtils(); const avatarPlaceholderSize = StyleUtils.getAvatarSize(avatarSize); const avatarPlaceholderRadius = avatarPlaceholderSize / 2; - const startPositionX = 30; + const startPositionX = avatarPlaceholderRadius; return ( From a11d004f5f4f1f34be68fd7d69d491f187f66268 Mon Sep 17 00:00:00 2001 From: nkdengineer Date: Wed, 25 Sep 2024 15:44:46 +0700 Subject: [PATCH 62/73] fix lint --- src/pages/home/report/ReportActionsView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionsView.tsx b/src/pages/home/report/ReportActionsView.tsx index 578c06c6dc9f..270a241778e1 100755 --- a/src/pages/home/report/ReportActionsView.tsx +++ b/src/pages/home/report/ReportActionsView.tsx @@ -202,7 +202,7 @@ function ReportActionsView({ // Get a sorted array of reportActions for both the current report and the transaction thread report associated with this report (if there is one) // so that we display transaction-level and report-level report actions in order in the one-transaction view const combinedReportActions = useMemo( - () => ReportActionsUtils.getCombinedReportActions(reportActionsToDisplay, transactionThreadReportID ?? null, transactionThreadReportActions! as OnyxTypes.ReportAction[]), + () => ReportActionsUtils.getCombinedReportActions(reportActionsToDisplay, transactionThreadReportID ?? null, transactionThreadReportActions ?? []), [reportActionsToDisplay, transactionThreadReportActions, transactionThreadReportID], ); From b7842cbb6bcfebd097df027c1490771057f378f8 Mon Sep 17 00:00:00 2001 From: daledah Date: Wed, 25 Sep 2024 17:28:52 +0700 Subject: [PATCH 63/73] fix: performance test --- src/components/LHNOptionsList/OptionRowLHN.tsx | 2 +- src/components/MenuItem.tsx | 5 +++++ .../Tooltip/BaseGenericTooltip/index.native.tsx | 4 ++-- .../Tooltip/BaseGenericTooltip/index.tsx | 4 ++-- .../Tooltip/BaseGenericTooltip/types.ts | 5 ++++- .../BaseEducationalTooltip.tsx | 16 +++++++++------- .../Tooltip/EducationalTooltip/index.tsx | 6 +++++- src/components/Tooltip/GenericTooltip.tsx | 8 ++++---- src/components/Tooltip/types.ts | 4 ++-- src/pages/Search/SearchTypeMenu.tsx | 2 +- .../ReportActionCompose/ReportActionCompose.tsx | 2 +- 11 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index 353bacdc0a25..322f28aa246d 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -187,7 +187,7 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti shiftHorizontal={variables.gbrTooltipShiftHorizontal} shiftVertical={variables.composerTooltipShiftVertical} wrapperStyle={styles.quickActionTooltipWrapper} - onPressOverlay={() => User.dismissGBRTooltip()} + onHideTooltip={() => User.dismissGBRTooltip()} > diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index 2524658d6ffc..a0fd8511eb3a 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -330,6 +330,9 @@ type MenuItemBaseProps = { /** Should selected item be marked with checkmark */ shouldShowSelectedItemCheck?: boolean; + + /** Handles what to do when hiding the tooltip */ + onHideTooltip?: () => void; }; type MenuItemProps = (IconProps | AvatarProps | NoIcon) & MenuItemBaseProps; @@ -428,6 +431,7 @@ function MenuItem( tooltipShiftVertical = 0, renderTooltipContent, shouldShowSelectedItemCheck = false, + onHideTooltip, }: MenuItemProps, ref: PressableRef, ) { @@ -559,6 +563,7 @@ function MenuItem( shiftHorizontal={tooltipShiftHorizontal} shiftVertical={tooltipShiftVertical} shouldAutoDismiss + onHideTooltip={onHideTooltip} > diff --git a/src/components/Tooltip/BaseGenericTooltip/index.native.tsx b/src/components/Tooltip/BaseGenericTooltip/index.native.tsx index e42f95874b42..f586c20cba49 100644 --- a/src/components/Tooltip/BaseGenericTooltip/index.native.tsx +++ b/src/components/Tooltip/BaseGenericTooltip/index.native.tsx @@ -34,7 +34,7 @@ function BaseGenericTooltip({ }, wrapperStyle = {}, shouldUseOverlay = false, - onPressOverlay = () => {}, + onHideTooltip = () => {}, }: BaseGenericTooltipProps) { // The width of tooltip's inner content. Has to be undefined in the beginning // as a width of 0 will cause the content to be rendered of a width of 0, @@ -102,7 +102,7 @@ function BaseGenericTooltip({ return ( - {shouldUseOverlay && } + {shouldUseOverlay && } {}, + onHideTooltip = () => {}, }: BaseGenericTooltipProps) { // The width of tooltip's inner content. Has to be undefined in the beginning // as a width of 0 will cause the content to be rendered of a width of 0, @@ -119,7 +119,7 @@ function BaseGenericTooltip({ return ReactDOM.createPortal( <> - {shouldUseOverlay && } + {shouldUseOverlay && } void; } & Pick< SharedTooltipProps, - 'renderTooltipContent' | 'maxWidth' | 'numberOfLines' | 'text' | 'shouldForceRenderingBelow' | 'wrapperStyle' | 'anchorAlignment' | 'shouldUseOverlay' | 'onPressOverlay' + 'renderTooltipContent' | 'maxWidth' | 'numberOfLines' | 'text' | 'shouldForceRenderingBelow' | 'wrapperStyle' | 'anchorAlignment' | 'shouldUseOverlay' | 'onHideTooltip' >; // eslint-disable-next-line import/prefer-default-export diff --git a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx index 463a69acf0d8..ef5327feba31 100644 --- a/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx +++ b/src/components/Tooltip/EducationalTooltip/BaseEducationalTooltip.tsx @@ -12,7 +12,7 @@ type LayoutChangeEventWithTarget = NativeSyntheticEvent<{layout: LayoutRectangle * A component used to wrap an element intended for displaying a tooltip. * This tooltip would show immediately without user's interaction and hide after 5 seconds. */ -function BaseEducationalTooltip({children, shouldAutoDismiss = false, shouldRender = false, ...props}: EducationalTooltipProps) { +function BaseEducationalTooltip({children, onHideTooltip, shouldAutoDismiss = false, ...props}: EducationalTooltipProps) { const hideTooltipRef = useRef<() => void>(); const [shouldMeasure, setShouldMeasure] = useState(false); @@ -20,7 +20,6 @@ function BaseEducationalTooltip({children, shouldAutoDismiss = false, shouldRend const [modal] = useOnyx(ONYXKEYS.MODAL); const shouldShow = !modal?.willAlertModalBecomeVisible && !modal?.isVisible; - const didShowRef = useRef(false); useEffect( () => () => { @@ -46,28 +45,31 @@ function BaseEducationalTooltip({children, shouldAutoDismiss = false, shouldRend } // Automatically hide tooltip after 5 seconds if shouldAutoDismiss is true - const timerID = setTimeout(hideTooltipRef.current, 5000); + const timerID = setTimeout(() => { + hideTooltipRef.current?.(); + onHideTooltip?.(); + }, 5000); return () => { clearTimeout(timerID); }; - }, [shouldAutoDismiss, shouldShow]); + }, [shouldAutoDismiss, shouldShow, onHideTooltip]); useEffect(() => { - if (!shouldRender || !shouldMeasure || !shouldShow || didShowRef.current) { + if (!shouldMeasure || !shouldShow) { return; } // When tooltip is used inside an animated view (e.g. popover), we need to wait for the animation to finish before measuring content. setTimeout(() => { - didShowRef.current = true; show.current?.(); }, 500); - }, [shouldMeasure, shouldRender, shouldShow]); + }, [shouldMeasure, shouldShow]); return ( {({showTooltip, hideTooltip, updateTargetBounds}) => { // eslint-disable-next-line react-compiler/react-compiler diff --git a/src/components/Tooltip/EducationalTooltip/index.tsx b/src/components/Tooltip/EducationalTooltip/index.tsx index 03500f768dd9..a97e36a5904c 100644 --- a/src/components/Tooltip/EducationalTooltip/index.tsx +++ b/src/components/Tooltip/EducationalTooltip/index.tsx @@ -2,7 +2,11 @@ import React from 'react'; import type {TooltipExtendedProps} from '@components/Tooltip/types'; import BaseEducationalTooltip from './BaseEducationalTooltip'; -function EducationalTooltip({children, ...props}: TooltipExtendedProps) { +function EducationalTooltip({children, shouldRender = false, ...props}: TooltipExtendedProps) { + if (!shouldRender) { + return children; + } + return ( {}, + onHideTooltip = () => {}, }: GenericTooltipProps) { const {preferredLocale} = useLocalize(); const {windowWidth} = useWindowDimensions(); @@ -150,8 +150,8 @@ function GenericTooltip({ } setShouldUseOverlay(false); hideTooltip(); - onPressOverlayProp(); - }, [shouldUseOverlay, onPressOverlayProp, hideTooltip]); + onHideTooltip(); + }, [shouldUseOverlay, onHideTooltip, hideTooltip]); useImperativeHandle(TooltipRefManager.ref, () => ({hideTooltip}), [hideTooltip]); @@ -183,7 +183,7 @@ function GenericTooltip({ wrapperStyle={wrapperStyle} anchorAlignment={anchorAlignment} shouldUseOverlay={shouldUseOverlay} - onPressOverlay={onPressOverlay} + onHideTooltip={onPressOverlay} /> )} diff --git a/src/components/Tooltip/types.ts b/src/components/Tooltip/types.ts index 0462b36fa524..0924f5d46a28 100644 --- a/src/components/Tooltip/types.ts +++ b/src/components/Tooltip/types.ts @@ -40,8 +40,8 @@ type SharedTooltipProps = { /** Should render a fullscreen transparent overlay */ shouldUseOverlay?: boolean; - /** Callback to fire when the transparent overlay is pressed */ - onPressOverlay?: () => void; + /** Handles what to do when hiding the tooltip */ + onHideTooltip?: () => void; }; type GenericTooltipState = { diff --git a/src/pages/Search/SearchTypeMenu.tsx b/src/pages/Search/SearchTypeMenu.tsx index 311168dc5d61..17531b60cce6 100644 --- a/src/pages/Search/SearchTypeMenu.tsx +++ b/src/pages/Search/SearchTypeMenu.tsx @@ -132,8 +132,8 @@ function SearchTypeMenu({queryJSON}: SearchTypeMenuProps) { tooltipShiftHorizontal: -32, tooltipShiftVertical: 15, tooltipWrapperStyle: [styles.bgPaleGreen, styles.mh4, styles.pv2], + onHideTooltip: () => SearchActions.dismissSavedSearchRenameTooltip(), renderTooltipContent: () => { - SearchActions.dismissSavedSearchRenameTooltip(); return ( User.dismissWorkspaceTooltip()} + onHideTooltip={() => User.dismissWorkspaceTooltip()} anchorAlignment={{ horizontal: CONST.MODAL.ANCHOR_ORIGIN_HORIZONTAL.LEFT, vertical: CONST.MODAL.ANCHOR_ORIGIN_VERTICAL.BOTTOM, From 4bf4032d6e422064618d367b7e844bef23e17723 Mon Sep 17 00:00:00 2001 From: FitseTLT Date: Wed, 25 Sep 2024 13:52:46 +0300 Subject: [PATCH 64/73] refactored code to make it DRY --- src/libs/NextStepUtils.ts | 19 +++++-------------- src/libs/actions/IOU.ts | 3 ++- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts index 7f13e1297b6f..ba435cc57b8f 100644 --- a/src/libs/NextStepUtils.ts +++ b/src/libs/NextStepUtils.ts @@ -8,9 +8,9 @@ import ONYXKEYS from '@src/ONYXKEYS'; import type {Policy, Report, ReportNextStep} from '@src/types/onyx'; import type {Message} from '@src/types/onyx/ReportNextStep'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import {getNextApproverAccountID} from './actions/IOU'; import DateUtils from './DateUtils'; import EmailUtils from './EmailUtils'; -import * as PersonalDetailsUtils from './PersonalDetailsUtils'; import * as PolicyUtils from './PolicyUtils'; import * as ReportUtils from './ReportUtils'; @@ -67,18 +67,10 @@ function parseMessage(messages: Message[] | undefined) { return `${formattedHtml}`; } -function getNextApproverDisplayName(policy: Policy, ownerAccountID: number, submitToAccountID: number, report: OnyxEntry) { - const approvalChain = ReportUtils.getApprovalChain(policy, ownerAccountID, report?.total ?? 0); - if (approvalChain.length === 0) { - return ReportUtils.getDisplayNameForParticipant(submitToAccountID); - } - - const nextApproverEmail = approvalChain.length === 1 ? approvalChain[0] : approvalChain[approvalChain.indexOf(currentUserEmail) + 1]; - if (!nextApproverEmail) { - return ReportUtils.getDisplayNameForParticipant(submitToAccountID); - } +function getNextApproverDisplayName(report: OnyxEntry) { + const approverAccountID = getNextApproverAccountID(report); - return PersonalDetailsUtils.getPersonalDetailByEmail(nextApproverEmail)?.displayName ?? nextApproverEmail; + return ReportUtils.getDisplayNameForParticipant(approverAccountID) ?? ReportUtils.getPersonalDetailsForAccountID(approverAccountID).login; } /** @@ -98,9 +90,8 @@ function buildNextStep(report: OnyxEntry, predictedNextStatus: ValueOf) { return submitToAccountID; } - return PersonalDetailsUtils.getAccountIDsByLogins([nextApproverEmail])[0] ?? submitToAccountID; + return PersonalDetailsUtils.getAccountIDsByLogins([nextApproverEmail])[0]; } function approveMoneyRequest(expenseReport: OnyxEntry, full?: boolean) { @@ -8190,6 +8190,7 @@ function mergeDuplicates(params: TransactionMergeParams) { export { adjustRemainingSplitShares, + getNextApproverAccountID, approveMoneyRequest, canApproveIOU, cancelPayment, From 2329240a9c80086daa3d2c7997592506fe3b65b0 Mon Sep 17 00:00:00 2001 From: Wojciech Lewicki Date: Wed, 25 Sep 2024 15:11:41 +0200 Subject: [PATCH 65/73] fix: mock for jest --- __mocks__/react-native-haptic-feedback.ts | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 __mocks__/react-native-haptic-feedback.ts diff --git a/__mocks__/react-native-haptic-feedback.ts b/__mocks__/react-native-haptic-feedback.ts new file mode 100644 index 000000000000..6d20b410d835 --- /dev/null +++ b/__mocks__/react-native-haptic-feedback.ts @@ -0,0 +1,5 @@ +import type HapticFeedback from 'react-native-haptic-feedback'; + +const RNHapticFeedback: typeof HapticFeedback = {trigger: jest.fn()}; + +export default RNHapticFeedback; From cbb6e5c7d429f4fcf989ab48e7706a245595d4f8 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 25 Sep 2024 08:56:27 -0700 Subject: [PATCH 66/73] Add parallel gradle flag to speed up Android builds --- android/gradle.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/android/gradle.properties b/android/gradle.properties index 87333d20f743..46cd98554d29 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -55,3 +55,5 @@ MYAPP_UPLOAD_KEY_ALIAS=ReactNativeChat-Key-Alias disableFrameProcessors=true android.nonTransitiveRClass=false + +org.gradle.parallel=true From ecf7e7e73dfd625ed7669560125a41307b960f09 Mon Sep 17 00:00:00 2001 From: Monil Bhavsar Date: Wed, 25 Sep 2024 11:14:07 -0700 Subject: [PATCH 67/73] Persist undefined value for proper promise resolution check --- src/libs/actions/PriorityMode.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/PriorityMode.ts b/src/libs/actions/PriorityMode.ts index beec327a2e40..2aca5d9f9de8 100644 --- a/src/libs/actions/PriorityMode.ts +++ b/src/libs/actions/PriorityMode.ts @@ -57,11 +57,11 @@ Onyx.connect({ }, }); -let hasTriedFocusMode: boolean | null | undefined; +let hasTriedFocusMode: boolean | undefined; Onyx.connect({ key: ONYXKEYS.NVP_TRY_FOCUS_MODE, callback: (val) => { - hasTriedFocusMode = val ?? null; + hasTriedFocusMode = val; // eslint-disable-next-line @typescript-eslint/no-use-before-define checkRequiredData(); From 57a2a65db4d3f60d9161b3b51b9c25668785d0a9 Mon Sep 17 00:00:00 2001 From: Anusha Date: Wed, 25 Sep 2024 23:28:23 +0500 Subject: [PATCH 68/73] add accessibilityLabel --- src/pages/WorkspaceSwitcherPage/WorkspacesSectionHeader.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/WorkspaceSwitcherPage/WorkspacesSectionHeader.tsx b/src/pages/WorkspaceSwitcherPage/WorkspacesSectionHeader.tsx index a550d5471072..9c714e54704c 100644 --- a/src/pages/WorkspaceSwitcherPage/WorkspacesSectionHeader.tsx +++ b/src/pages/WorkspaceSwitcherPage/WorkspacesSectionHeader.tsx @@ -30,7 +30,7 @@ function WorkspacesSectionHeader() { { const activeRoute = Navigation.getActiveRouteWithoutParams(); From a4a344b7cedd0ab9cafb4857db15de8eea409689 Mon Sep 17 00:00:00 2001 From: OSBotify Date: Wed, 25 Sep 2024 20:12:39 +0000 Subject: [PATCH 69/73] Update version to 9.0.40-1 --- android/app/build.gradle | 4 ++-- ios/NewExpensify/Info.plist | 2 +- ios/NewExpensifyTests/Info.plist | 2 +- ios/NotificationServiceExtension/Info.plist | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index fffbd66aefae..833f8290e5e6 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -110,8 +110,8 @@ android { minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled rootProject.ext.multiDexEnabled - versionCode 1009004000 - versionName "9.0.40-0" + versionCode 1009004001 + versionName "9.0.40-1" // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index 7d3f7bba95fa..4eeb658f3347 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -40,7 +40,7 @@ CFBundleVersion - 9.0.40.0 + 9.0.40.1 FullStory OrgId diff --git a/ios/NewExpensifyTests/Info.plist b/ios/NewExpensifyTests/Info.plist index aa39f6fba8a7..7dc1b1416139 100644 --- a/ios/NewExpensifyTests/Info.plist +++ b/ios/NewExpensifyTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 9.0.40.0 + 9.0.40.1 diff --git a/ios/NotificationServiceExtension/Info.plist b/ios/NotificationServiceExtension/Info.plist index f6a276489738..83fa9ece1deb 100644 --- a/ios/NotificationServiceExtension/Info.plist +++ b/ios/NotificationServiceExtension/Info.plist @@ -13,7 +13,7 @@ CFBundleShortVersionString 9.0.40 CFBundleVersion - 9.0.40.0 + 9.0.40.1 NSExtension NSExtensionPointIdentifier diff --git a/package-lock.json b/package-lock.json index c40f3f92a66f..6af9c1981bc8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "new.expensify", - "version": "9.0.40-0", + "version": "9.0.40-1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "new.expensify", - "version": "9.0.40-0", + "version": "9.0.40-1", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index b0162b06073a..deff4054ce01 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "new.expensify", - "version": "9.0.40-0", + "version": "9.0.40-1", "author": "Expensify, Inc.", "homepage": "https://new.expensify.com", "description": "New Expensify is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.", From 01568ff87406db627ac52b9072bd5bc5a1d7d58d Mon Sep 17 00:00:00 2001 From: Marc Glasser Date: Wed, 25 Sep 2024 10:52:13 -1000 Subject: [PATCH 70/73] Update NewApp_AdHoc.mobileprovision --- ios/NewApp_AdHoc.mobileprovision.gpg | Bin 11894 -> 11923 bytes ...c_Notification_Service.mobileprovision.gpg | Bin 11546 -> 11571 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/ios/NewApp_AdHoc.mobileprovision.gpg b/ios/NewApp_AdHoc.mobileprovision.gpg index 78fb5d53d9e9c71023c076b5d50740256bcb5415..d2f181f6b7f4c91ab4773ef6b082ddd8b266ac7c 100644 GIT binary patch literal 11923 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 Z@4ZTtTckN%HkSIq6L^Xn3G`dA3v%h!L0|v? literal 11894 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 z Date: Wed, 25 Sep 2024 16:07:17 -0700 Subject: [PATCH 71/73] Revert style change --- src/pages/workspace/WorkspaceMembersPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index 5593881354a3..d79670785524 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -537,7 +537,7 @@ function WorkspaceMembersPage({personalDetails, route, policy, currentUserPerson return null; } return ( - + {(shouldUseNarrowLayout ? canSelectMultiple : selectedEmployees.length > 0) ? ( shouldAlwaysShowDropdownMenu From 0a6fc5236f1748b6ad085acd397e37523bb115ff Mon Sep 17 00:00:00 2001 From: Aldo Canepa Date: Wed, 25 Sep 2024 16:23:48 -0700 Subject: [PATCH 72/73] Remove View --- src/pages/workspace/WorkspaceMembersPage.tsx | 46 +++++++++----------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index d79670785524..54c9ced5d6d8 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -536,31 +536,27 @@ function WorkspaceMembersPage({personalDetails, route, policy, currentUserPerson if (!isPolicyAdmin) { return null; } - return ( - - {(shouldUseNarrowLayout ? canSelectMultiple : selectedEmployees.length > 0) ? ( - - shouldAlwaysShowDropdownMenu - pressOnEnter - customText={translate('workspace.common.selected', {selectedNumber: selectedEmployees.length})} - buttonSize={CONST.DROPDOWN_BUTTON_SIZE.MEDIUM} - onPress={() => null} - options={getBulkActionsButtonOptions()} - isSplitButton={false} - style={[shouldUseNarrowLayout && styles.flexGrow1, shouldUseNarrowLayout && styles.mb3]} - isDisabled={!selectedEmployees.length} - /> - ) : ( -