From 7ccadb2c75d7e176f8326df45a11677344044334 Mon Sep 17 00:00:00 2001 From: Sibtain Ali Date: Tue, 2 Apr 2024 15:02:27 +0500 Subject: [PATCH 001/545] temp feature --- assets/images/receipt-location-marker.svg | 134 ++++++++++++++++++ src/components/LocationPermissionModal.tsx | 48 +++++++ ...oraryForRefactorRequestConfirmationList.js | 2 + 3 files changed, 184 insertions(+) create mode 100644 assets/images/receipt-location-marker.svg create mode 100644 src/components/LocationPermissionModal.tsx diff --git a/assets/images/receipt-location-marker.svg b/assets/images/receipt-location-marker.svg new file mode 100644 index 000000000000..674db76464f7 --- /dev/null +++ b/assets/images/receipt-location-marker.svg @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/LocationPermissionModal.tsx b/src/components/LocationPermissionModal.tsx new file mode 100644 index 000000000000..f73289a22aee --- /dev/null +++ b/src/components/LocationPermissionModal.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import LocationMarker from '@assets/images/receipt-location-marker.svg'; +import ConfirmModal from './ConfirmModal'; + +type LocationPermissionModalProps = { + /** A callback to call when the form has been submitted */ + onConfirm: () => void; + + /** A callback to call when the form has been closed */ + onCancel?: () => void; + + /** Modal visibility */ + isVisible: boolean; + + /** Callback method fired when the modal is hidden */ + onModalHide?: () => void; + + /** Should we announce the Modal visibility changes? */ + shouldSetModalVisibility?: boolean; +}; + +function LocationPermissionModal({ + shouldSetModalVisibility = true, + onModalHide = () => {}, + isVisible, + onConfirm, + onCancel, +}: LocationPermissionModalProps) { + + return ( + + ); +} + +LocationPermissionModal.displayName = 'LocationPermissionModal'; + +export default LocationPermissionModal; diff --git a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js index 3fd76eea657b..fed91f87677e 100755 --- a/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js +++ b/src/components/MoneyTemporaryForRefactorRequestConfirmationList.js @@ -31,6 +31,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import Button from './Button'; +import LocationPermissionModal from './LocationPermissionModal'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; import categoryPropTypes from './categoryPropTypes'; import ConfirmedRoute from './ConfirmedRoute'; @@ -978,6 +979,7 @@ function MoneyTemporaryForRefactorRequestConfirmationList({ )} {shouldShowAllFields && supplementaryFields} + {}} isVisible /> Date: Tue, 9 Apr 2024 01:06:06 +0500 Subject: [PATCH 002/545] design ready --- src/components/ConfirmContent.tsx | 63 +++++++++++++++++-- src/components/ConfirmModal.tsx | 30 +++++++++ src/components/LocationPermissionModal.tsx | 29 +++++---- ...oraryForRefactorRequestConfirmationList.js | 7 ++- src/languages/en.ts | 5 ++ src/languages/es.ts | 5 ++ 6 files changed, 119 insertions(+), 20 deletions(-) diff --git a/src/components/ConfirmContent.tsx b/src/components/ConfirmContent.tsx index 26331f92401c..adade9fc09c5 100644 --- a/src/components/ConfirmContent.tsx +++ b/src/components/ConfirmContent.tsx @@ -14,8 +14,11 @@ import type IconAsset from '@src/types/utils/IconAsset'; import Button from './Button'; import Header from './Header'; import Icon from './Icon'; +import {Close} from './Icon/Expensicons'; import ImageSVG from './ImageSVG'; +import {PressableWithoutFeedback} from './Pressable'; import Text from './Text'; +import Tooltip from './Tooltip'; type ConfirmContentProps = { /** Title of the modal */ @@ -51,15 +54,33 @@ type ConfirmContentProps = { /** Icon to display above the title */ iconSource?: IconAsset; + /** Icon width */ + iconWidth?: number; + + /** Icon height */ + iconHeight?: number; + + /** Should the icon be centered? */ + shouldCenterIcon?: boolean; + /** Whether to center the icon / text content */ shouldCenterContent?: boolean; + /** Whether to show the dismiss icon */ + shouldShowDismissIcon?: boolean; + /** Whether to stack the buttons */ shouldStackButtons?: boolean; + /** Whether to reverse the order of the stacked buttons */ + shouldReverseStackedButtons?: boolean; + /** Styles for title */ titleStyles?: StyleProp; + /** Styles for title container */ + titleContainerStyles?: StyleProp; + /** Styles for prompt */ promptStyles?: StyleProp; @@ -91,7 +112,13 @@ function ConfirmContent({ promptStyles, contentStyles, iconAdditionalStyles, + iconWidth = variables.appModalAppIconSize, + iconHeight = variables.appModalAppIconSize, + shouldCenterIcon = false, + shouldShowDismissIcon = false, image, + titleContainerStyles, + shouldReverseStackedButtons = false, }: ConfirmContentProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -116,19 +143,35 @@ function ConfirmContent({ )} + {shouldShowDismissIcon && ( + + + + + + + + )} {typeof iconSource === 'function' && ( - + )} - +
+ {shouldShowCancelButton && shouldReverseStackedButtons && ( + + + + + + ); +} + +export default EmptyStateComponent; diff --git a/src/components/EmptyStateComponent/types.ts b/src/components/EmptyStateComponent/types.ts new file mode 100644 index 000000000000..7a7cc9b4ff57 --- /dev/null +++ b/src/components/EmptyStateComponent/types.ts @@ -0,0 +1,29 @@ +import type DotLottieAnimation from '@components/LottieAnimations/types'; +import type SearchRowSkeleton from '@components/Skeletons/SearchRowSkeleton'; +import type TableRowSkeleton from '@components/Skeletons/TableRowSkeleton'; +import type IconAsset from '@src/types/utils/IconAsset'; + +type ValidSkeletons = typeof SearchRowSkeleton | typeof TableRowSkeleton; +type MediaTypes = 'video' | 'illustration' | 'animation'; + +type SharedProps = { + SkeletonComponent: ValidSkeletons; + titleText: string; + subtitleText: string; + buttonText?: string; + buttonAction?: () => void; + headerMediaType: T; +}; + +type MediaType = SharedProps & { + headerMedia: HeaderMedia; +}; + +type VideoProps = MediaType; +type IllustrationProps = MediaType; +type AnimationProps = MediaType; + +type EmptyStateComponentProps = VideoProps | IllustrationProps | AnimationProps; + +// eslint-disable-next-line import/prefer-default-export +export type {EmptyStateComponentProps}; diff --git a/src/components/Icon/index.tsx b/src/components/Icon/index.tsx index b4da5c0b0fa2..f49f74a6724a 100644 --- a/src/components/Icon/index.tsx +++ b/src/components/Icon/index.tsx @@ -1,4 +1,4 @@ -import type {ImageContentFit} from 'expo-image'; +import type {ImageContentFit, ImageStyle} from 'expo-image'; import React from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; diff --git a/src/components/OptionsListSkeletonView.tsx b/src/components/OptionsListSkeletonView.tsx index 1f09876b18d3..8b2a53b5c59e 100644 --- a/src/components/OptionsListSkeletonView.tsx +++ b/src/components/OptionsListSkeletonView.tsx @@ -17,12 +17,14 @@ function getLinedWidth(index: number): string { type OptionsListSkeletonViewProps = { shouldAnimate?: boolean; + gradientOpacity?: boolean; }; -function OptionsListSkeletonView({shouldAnimate = true}: OptionsListSkeletonViewProps) { +function OptionsListSkeletonView({shouldAnimate = true, gradientOpacity = false}: OptionsListSkeletonViewProps) { return ( { const lineWidth = getLinedWidth(itemIndex); diff --git a/src/components/Search.tsx b/src/components/Search.tsx index e4faa15bfb94..442bc5937b76 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -14,7 +14,6 @@ import * as SearchUtils from '@libs/SearchUtils'; import type {SearchColumnType, SortOrder} from '@libs/SearchUtils'; import Navigation from '@navigation/Navigation'; import type {CentralPaneNavigatorParamList} from '@navigation/types'; -import EmptySearchView from '@pages/Search/EmptySearchView'; import variables from '@styles/variables'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; @@ -23,10 +22,12 @@ import type {SearchQuery} from '@src/types/onyx/SearchResults'; import type SearchResults from '@src/types/onyx/SearchResults'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; +import EmptyStateComponent from './EmptyStateComponent'; import SelectionList from './SelectionList'; import SearchTableHeader from './SelectionList/SearchTableHeader'; import type {ReportListItemType, TransactionListItemType} from './SelectionList/types'; -import TableListItemSkeleton from './Skeletons/TableListItemSkeleton'; +import SearchRowSkeleton from './Skeletons/SearchRowSkeleton'; +import TableRowSkeleton from './Skeletons/TableRowSkeleton'; type SearchProps = { query: SearchQuery; @@ -97,11 +98,21 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { const shouldShowEmptyState = !isLoadingItems && isEmptyObject(searchResults?.data); if (isLoadingItems) { - return ; + return ; } if (shouldShowEmptyState) { - return ; + return ( + Navigation.navigate(ROUTES.CONCIERGE)} + buttonText="Go to Workspaces" + /> + ); } const openReport = (item: TransactionListItemType | ReportListItemType) => { @@ -188,7 +199,7 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { onEndReached={fetchMoreResults} listFooterContent={ isLoadingMoreItems ? ( - diff --git a/src/components/Skeletons/ItemListSkeletonView.tsx b/src/components/Skeletons/ItemListSkeletonView.tsx index 5c46dbdddbfc..62e1e5afad13 100644 --- a/src/components/Skeletons/ItemListSkeletonView.tsx +++ b/src/components/Skeletons/ItemListSkeletonView.tsx @@ -1,5 +1,6 @@ import React, {useMemo, useState} from 'react'; import {View} from 'react-native'; +import type {StyleProp, ViewStyle} from 'react-native'; import SkeletonViewContentLoader from '@components/SkeletonViewContentLoader'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -9,9 +10,19 @@ type ListItemSkeletonProps = { shouldAnimate?: boolean; renderSkeletonItem: (args: {itemIndex: number}) => React.ReactNode; fixedNumItems?: number; + gradientOpacity?: boolean; + itemViewStyle?: StyleProp; + itemViewHeight?: number; }; -function ItemListSkeletonView({shouldAnimate = true, renderSkeletonItem, fixedNumItems}: ListItemSkeletonProps) { +function ItemListSkeletonView({ + shouldAnimate = true, + renderSkeletonItem, + fixedNumItems, + gradientOpacity = false, + itemViewStyle = {}, + itemViewHeight = CONST.LHN_SKELETON_VIEW_ITEM_HEIGHT, +}: ListItemSkeletonProps) { const theme = useTheme(); const themeStyles = useThemeStyles(); @@ -19,22 +30,25 @@ function ItemListSkeletonView({shouldAnimate = true, renderSkeletonItem, fixedNu const skeletonViewItems = useMemo(() => { const items = []; for (let i = 0; i < numItems; i++) { + const opacity = gradientOpacity ? 1 - i / numItems : 1; items.push( - - {renderSkeletonItem({itemIndex: i})} - , + + + + {renderSkeletonItem({itemIndex: i})} + + + , ); } return items; - }, [numItems, shouldAnimate, theme, themeStyles, renderSkeletonItem]); - + }, [numItems, shouldAnimate, theme, themeStyles, renderSkeletonItem, gradientOpacity, itemViewHeight, itemViewStyle]); return ( ( <> ( + <> + + + + + )} + /> + ); +} + +TableListItemSkeleton.displayName = 'TableListItemSkeleton'; + +export default TableListItemSkeleton; diff --git a/src/styles/index.ts b/src/styles/index.ts index b031e665594f..a12090ff275f 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1663,6 +1663,7 @@ const styles = (theme: ThemeColors) => welcomeVideoNarrowLayout: { width: variables.onboardingModalWidth, + height: 500, }, onlyEmojisText: { @@ -5033,6 +5034,28 @@ const styles = (theme: ThemeColors) => fontSize: variables.fontSizeNormal, fontWeight: FontUtils.fontWeight.bold, }, + + skeletonBackground: { + flex: 1, + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + }, + + emptyStateForeground: (isSmallScreenWidth: boolean) => ({ + justifyContent: 'center', + alignItems: 'center', + height: '100%', + padding: isSmallScreenWidth ? 24 : 0, + }), + + emptyStateContent: (isSmallScreenWidth: boolean) => ({ + width: isSmallScreenWidth ? '100%' : 400, + backgroundColor: theme.cardBG, + borderRadius: variables.componentBorderRadiusLarge, + }), } satisfies Styles); type ThemeStyles = ReturnType; From 6d91057bf954ea8979b7da97de69a35382b3526c Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 20 Jun 2024 17:08:26 +0700 Subject: [PATCH 110/545] check active route approach --- src/components/ReportActionItem/TaskView.tsx | 6 ++++++ src/components/TaskHeaderActionButton.tsx | 13 ++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/components/ReportActionItem/TaskView.tsx b/src/components/ReportActionItem/TaskView.tsx index 43e896fe6578..ebe442dd8d75 100644 --- a/src/components/ReportActionItem/TaskView.tsx +++ b/src/components/ReportActionItem/TaskView.tsx @@ -96,6 +96,12 @@ function TaskView({report, ...props}: TaskViewProps) { { + if ( + Navigation.isActiveRoute(ROUTES.TASK_ASSIGNEE.getRoute(report.reportID)) || + Navigation.isActiveRoute(ROUTES.REPORT_DESCRIPTION.getRoute(report.reportID)) + ) { + return; + } if (isCompleted) { Task.reopenTask(report); } else { diff --git a/src/components/TaskHeaderActionButton.tsx b/src/components/TaskHeaderActionButton.tsx index 0c7e603a4aa2..ccf3e22ecc5f 100644 --- a/src/components/TaskHeaderActionButton.tsx +++ b/src/components/TaskHeaderActionButton.tsx @@ -4,10 +4,12 @@ import type {OnyxEntry} from 'react-native-onyx'; import {withOnyx} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@libs/Navigation/Navigation'; import * as ReportUtils from '@libs/ReportUtils'; import * as Session from '@userActions/Session'; import * as Task from '@userActions/Task'; import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import Button from './Button'; @@ -36,7 +38,16 @@ function TaskHeaderActionButton({report, session}: TaskHeaderActionButtonProps) isDisabled={!Task.canModifyTask(report, session?.accountID ?? -1)} medium text={translate(ReportUtils.isCompletedTaskReport(report) ? 'task.markAsIncomplete' : 'task.markAsComplete')} - onPress={Session.checkIfActionIsAllowed(() => (ReportUtils.isCompletedTaskReport(report) ? Task.reopenTask(report) : Task.completeTask(report)))} + onPress={Session.checkIfActionIsAllowed(() => { + if (Navigation.isActiveRoute(ROUTES.TASK_ASSIGNEE.getRoute(report.reportID)) || Navigation.isActiveRoute(ROUTES.REPORT_DESCRIPTION.getRoute(report.reportID))) { + return; + } + if (ReportUtils.isCompletedTaskReport(report)) { + Task.reopenTask(report); + } else { + Task.completeTask(report); + } + })} style={styles.flex1} /> From 0308f12e27abcd6e6486ebf1d37ebec5a79bcd16 Mon Sep 17 00:00:00 2001 From: tienifr Date: Thu, 20 Jun 2024 17:19:06 +0700 Subject: [PATCH 111/545] remove redundant changes --- src/components/MenuItem.tsx | 10 +- src/pages/home/ReportScreen.tsx | 4 +- src/pages/settings/Profile/ProfilePage.tsx | 101 +++++++++++---------- 3 files changed, 61 insertions(+), 54 deletions(-) diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index fad11c8e3a79..c1fe4270d4e1 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -394,7 +394,7 @@ function MenuItem( const StyleUtils = useStyleUtils(); const combinedStyle = [styles.popoverMenuItem, style]; const {shouldUseNarrowLayout} = useResponsiveLayout(); - const {isExecuting, singleExecution} = useContext(MenuItemGroupContext) ?? {}; + const {isExecuting, singleExecution, waitForNavigate} = useContext(MenuItemGroupContext) ?? {}; const isDeleted = style && Array.isArray(style) ? style.includes(styles.offlineFeedback.deleted) : false; const descriptionVerticalMargin = shouldShowDescriptionOnTop ? styles.mb1 : styles.mt1; @@ -469,11 +469,15 @@ function MenuItem( } if (onPress && event) { - if (!singleExecution) { + if (!singleExecution || !waitForNavigate) { onPress(event); return; } - singleExecution(onPress)(event); + singleExecution( + waitForNavigate(() => { + onPress(event); + }), + )(); } }; diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 20d4f1fa175e..ade50c0e2c9b 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -719,8 +719,8 @@ function ReportScreen({ )} {/* Note: The ReportActionsSkeletonView should be allowed to mount even if the initial report actions are not loaded. - If we prevent rendering the report while they are loading then - we'll unnecessarily unmount the ReportActionsView which will clear the new marker lines initial state. */} + If we prevent rendering the report while they are loading then + we'll unnecessarily unmount the ReportActionsView which will clear the new marker lines initial state. */} {shouldShowSkeleton && } {isCurrentReportLoadedFromOnyx ? ( diff --git a/src/pages/settings/Profile/ProfilePage.tsx b/src/pages/settings/Profile/ProfilePage.tsx index 011d5956be58..4c5ed88e6898 100755 --- a/src/pages/settings/Profile/ProfilePage.tsx +++ b/src/pages/settings/Profile/ProfilePage.tsx @@ -5,6 +5,7 @@ import {withOnyx} from 'react-native-onyx'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Illustrations from '@components/Icon/Illustrations'; +import MenuItemGroup from '@components/MenuItemGroup'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; @@ -135,55 +136,57 @@ function ProfilePage({ icon={Illustrations.Profile} /> - -
- {publicOptions.map((detail, index) => ( - Navigation.navigate(detail.pageRoute)} - brickRoadIndicator={detail.brickRoadIndicator} - /> - ))} -
-
- {isLoadingApp ? ( - - ) : ( - <> - {privateOptions.map((detail, index) => ( - Navigation.navigate(detail.pageRoute)} - /> - ))} - - )} -
-
+ + +
+ {publicOptions.map((detail, index) => ( + Navigation.navigate(detail.pageRoute)} + brickRoadIndicator={detail.brickRoadIndicator} + /> + ))} +
+
+ {isLoadingApp ? ( + + ) : ( + <> + {privateOptions.map((detail, index) => ( + Navigation.navigate(detail.pageRoute)} + /> + ))} + + )} +
+
+
); From a99586158513d3f9bba965256477bb83039c57e1 Mon Sep 17 00:00:00 2001 From: Filip Solecki Date: Fri, 21 Jun 2024 13:50:26 +0200 Subject: [PATCH 112/545] Remove backgroundColor --- src/components/EmptyStateComponent/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/EmptyStateComponent/index.tsx b/src/components/EmptyStateComponent/index.tsx index 496930d05208..1933df015b55 100644 --- a/src/components/EmptyStateComponent/index.tsx +++ b/src/components/EmptyStateComponent/index.tsx @@ -62,7 +62,7 @@ function EmptyStateComponent({SkeletonComponent, headerMediaType, headerMedia, b default: HeaderComponent = ( Date: Mon, 24 Jun 2024 07:44:52 +0300 Subject: [PATCH 113/545] rename to update gl code --- src/libs/actions/Policy/Category.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Policy/Category.ts b/src/libs/actions/Policy/Category.ts index 1f8ba0880ce6..c668e4a6127b 100644 --- a/src/libs/actions/Policy/Category.ts +++ b/src/libs/actions/Policy/Category.ts @@ -331,7 +331,7 @@ function renamePolicyCategory(policyID: string, policyCategory: {oldName: string API.write(WRITE_COMMANDS.RENAME_WORKSPACE_CATEGORY, parameters, onyxData); } -function setPolicyCategoryGLCode(policyID: string, categoryName: string, glCode: string) { +function updatePolicyCategoryGLCode(policyID: string, categoryName: string, glCode: string) { const policyCategoryToUpdate = allPolicyCategories?.[`${ONYXKEYS.COLLECTION.POLICY_CATEGORIES}${policyID}`]?.[categoryName] ?? {}; const onyxData: OnyxData = { @@ -650,7 +650,7 @@ export { setWorkspaceRequiresCategory, createPolicyCategory, renamePolicyCategory, - setPolicyCategoryGLCode, + updatePolicyCategoryGLCode, clearCategoryErrors, enablePolicyCategories, setPolicyDistanceRatesDefaultCategory, From e1a58a0db031f6c398c7701d05837e28de5e7bbe Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 24 Jun 2024 07:45:27 +0300 Subject: [PATCH 114/545] rename to update gl code --- src/pages/workspace/categories/CategoryGLCodePage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/workspace/categories/CategoryGLCodePage.tsx b/src/pages/workspace/categories/CategoryGLCodePage.tsx index c16550fcdd88..1547be5bb42d 100644 --- a/src/pages/workspace/categories/CategoryGLCodePage.tsx +++ b/src/pages/workspace/categories/CategoryGLCodePage.tsx @@ -40,7 +40,7 @@ function CategoryGLCodePage({route, policyCategories}: EditCategoryPageProps) { (values: FormOnyxValues) => { const newGLCode = values.glCode.trim(); if (newGLCode !== glCode) { - Category.setPolicyCategoryGLCode(route.params.policyID, categoryName, newGLCode); + Category.updatePolicyCategoryGLCode(route.params.policyID, categoryName, newGLCode); } Navigation.goBack(); }, From e02ceaecd9430bd3929ffafc01b6248f65986366 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 24 Jun 2024 07:55:12 +0300 Subject: [PATCH 115/545] fix err --- src/libs/actions/Policy/Category.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/Policy/Category.ts b/src/libs/actions/Policy/Category.ts index c668e4a6127b..819bd334ea06 100644 --- a/src/libs/actions/Policy/Category.ts +++ b/src/libs/actions/Policy/Category.ts @@ -374,7 +374,7 @@ function updatePolicyCategoryGLCode(policyID: string, categoryName: string, glCo value: { [categoryName]: { ...policyCategoryToUpdate, - errors: ErrorUtils.getMicroSecondOnyxError('workspace.categories.updateGLCodeFailureMessage'), + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('workspace.categories.updateGLCodeFailureMessage'), pendingAction: null, }, }, From 4ca6c616063052cca5c44676a895fac5a60f2c76 Mon Sep 17 00:00:00 2001 From: Rushat Gabhane Date: Mon, 24 Jun 2024 08:02:17 +0300 Subject: [PATCH 116/545] fix err --- src/libs/API/parameters/index.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index c4f64a4512af..c8636973c13a 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -165,7 +165,6 @@ export type {default as CreateWorkspaceCategoriesParams} from './CreateWorkspace export type {default as RenameWorkspaceCategoriesParams} from './RenameWorkspaceCategoriesParams'; export type {default as SetWorkspaceRequiresCategoryParams} from './SetWorkspaceRequiresCategoryParams'; export type {default as DeleteWorkspaceCategoriesParams} from './DeleteWorkspaceCategoriesParams'; -export type {default as SetWorkspaceAutoReportingParams} from './SetWorkspaceAutoReportingParams'; export type {default as UpdatePolicyCategoryGLCodeParams} from './UpdatePolicyCategoryGLCodeParams'; export type {default as SetWorkspaceAutoReportingFrequencyParams} from './SetWorkspaceAutoReportingFrequencyParams'; export type {default as SetWorkspaceAutoReportingMonthlyOffsetParams} from './SetWorkspaceAutoReportingMonthlyOffsetParams'; From 9f3a62c398f4b320e29342aa051269d9836716aa Mon Sep 17 00:00:00 2001 From: Filip Solecki Date: Mon, 24 Jun 2024 09:39:07 +0200 Subject: [PATCH 117/545] Animation case --- src/components/EmptyStateComponent/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/EmptyStateComponent/index.tsx b/src/components/EmptyStateComponent/index.tsx index 1933df015b55..18277565b780 100644 --- a/src/components/EmptyStateComponent/index.tsx +++ b/src/components/EmptyStateComponent/index.tsx @@ -56,7 +56,7 @@ function EmptyStateComponent({SkeletonComponent, headerMediaType, headerMedia, b break; case 'animation': - 123 + Animation ; break; default: From 01333bcbc61a3c7c42e587c8ca149cc0d448e587 Mon Sep 17 00:00:00 2001 From: Filip Solecki Date: Mon, 24 Jun 2024 15:16:50 +0200 Subject: [PATCH 118/545] Add animation and implement on Search page --- src/components/EmptyStateComponent/index.tsx | 41 +++++++------- src/components/EmptyStateComponent/types.ts | 2 + src/components/Icon/Expensicons.ts | 2 + src/components/ImageSVG/index.tsx | 2 +- src/components/Search.tsx | 15 +++--- .../Skeletons/ItemListSkeletonView.tsx | 54 +++++++++++++------ src/languages/en.ts | 4 ++ src/languages/es.ts | 4 ++ src/styles/index.ts | 5 ++ 9 files changed, 87 insertions(+), 42 deletions(-) diff --git a/src/components/EmptyStateComponent/index.tsx b/src/components/EmptyStateComponent/index.tsx index 18277565b780..a6bd07b94550 100644 --- a/src/components/EmptyStateComponent/index.tsx +++ b/src/components/EmptyStateComponent/index.tsx @@ -3,6 +3,7 @@ import React, {useState} from 'react'; import {View} from 'react-native'; import Button from '@components/Button'; import ImageSVG from '@components/ImageSVG'; +import Lottie from '@components/Lottie'; import Text from '@components/Text'; import VideoPlayer from '@components/VideoPlayer'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -19,7 +20,7 @@ type VideoLoadedEventType = { }; }; -function EmptyStateComponent({SkeletonComponent, headerMediaType, headerMedia, buttonText, buttonAction, titleText, subtitleText}: EmptyStateComponentProps) { +function EmptyStateComponent({SkeletonComponent, headerMediaType, headerMedia, buttonText, buttonAction, titleText, subtitleText, headerStyles}: EmptyStateComponentProps) { const styles = useThemeStyles(); const isSmallScreenWidth = getIsSmallScreenWidth(); @@ -55,19 +56,21 @@ function EmptyStateComponent({SkeletonComponent, headerMediaType, headerMedia, b ); break; case 'animation': - - Animation - ; - break; - default: HeaderComponent = ( - ); + break; + case 'illustration': + HeaderComponent = ; + break; + default: + HeaderComponent = null; + break; } return ( @@ -80,16 +83,18 @@ function EmptyStateComponent({SkeletonComponent, headerMediaType, headerMedia, b
- {HeaderComponent} + {HeaderComponent} {titleText} {subtitleText} - + {buttonText && buttonAction && ( + + )} diff --git a/src/components/EmptyStateComponent/types.ts b/src/components/EmptyStateComponent/types.ts index 7a7cc9b4ff57..a3ef4ad75f59 100644 --- a/src/components/EmptyStateComponent/types.ts +++ b/src/components/EmptyStateComponent/types.ts @@ -1,3 +1,4 @@ +import type {StyleProp, ViewStyle} from 'react-native'; import type DotLottieAnimation from '@components/LottieAnimations/types'; import type SearchRowSkeleton from '@components/Skeletons/SearchRowSkeleton'; import type TableRowSkeleton from '@components/Skeletons/TableRowSkeleton'; @@ -12,6 +13,7 @@ type SharedProps = { subtitleText: string; buttonText?: string; buttonAction?: () => void; + headerStyles?: StyleProp; headerMediaType: T; }; diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts index c3e50cff3178..3ac4e346ccb5 100644 --- a/src/components/Icon/Expensicons.ts +++ b/src/components/Icon/Expensicons.ts @@ -118,6 +118,7 @@ import Meter from '@assets/images/meter.svg'; import MoneyBag from '@assets/images/money-bag.svg'; import MoneyCircle from '@assets/images/money-circle.svg'; import MoneySearch from '@assets/images/money-search.svg'; +import MoneyStack from '@assets/images/money-stack.svg'; import MoneyWaving from '@assets/images/money-waving.svg'; import Monitor from '@assets/images/monitor.svg'; import Mute from '@assets/images/mute.svg'; @@ -366,4 +367,5 @@ export { Clear, CheckCircle, CheckmarkCircle, + MoneyStack, }; diff --git a/src/components/ImageSVG/index.tsx b/src/components/ImageSVG/index.tsx index 3ce04a1a190a..cf58aa873584 100644 --- a/src/components/ImageSVG/index.tsx +++ b/src/components/ImageSVG/index.tsx @@ -2,7 +2,7 @@ import React from 'react'; import type {SvgProps} from 'react-native-svg'; import type ImageSVGProps from './types'; -function ImageSVG({src, width = '100%', height = '100%', fill, hovered = false, pressed = false, style, pointerEvents, preserveAspectRatio}: ImageSVGProps) { +function ImageSVG({src, width, height = '100%', fill, hovered = false, pressed = false, style, pointerEvents, preserveAspectRatio}: ImageSVGProps) { const ImageSvgComponent = src as React.FC; const additionalProps: Pick = {}; diff --git a/src/components/Search.tsx b/src/components/Search.tsx index 442bc5937b76..449dfb4dfe9f 100644 --- a/src/components/Search.tsx +++ b/src/components/Search.tsx @@ -3,6 +3,7 @@ import type {StackNavigationProp} from '@react-navigation/stack'; import React, {useCallback, useEffect, useRef} from 'react'; import type {OnyxEntry} from 'react-native-onyx'; import {useOnyx} from 'react-native-onyx'; +import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; @@ -23,11 +24,11 @@ import type SearchResults from '@src/types/onyx/SearchResults'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; import EmptyStateComponent from './EmptyStateComponent'; +import LottieAnimations from './LottieAnimations'; import SelectionList from './SelectionList'; import SearchTableHeader from './SelectionList/SearchTableHeader'; import type {ReportListItemType, TransactionListItemType} from './SelectionList/types'; import SearchRowSkeleton from './Skeletons/SearchRowSkeleton'; -import TableRowSkeleton from './Skeletons/TableRowSkeleton'; type SearchProps = { query: SearchQuery; @@ -50,6 +51,7 @@ function isTransactionListItemType(item: TransactionListItemType | ReportListIte function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { const {isOffline} = useNetwork(); const styles = useThemeStyles(); + const {translate} = useLocalize(); const {isLargeScreenWidth} = useWindowDimensions(); const navigation = useNavigation>(); const lastSearchResultsRef = useRef>(); @@ -105,12 +107,11 @@ function Search({query, policyIDs, sortBy, sortOrder}: SearchProps) { return ( Navigation.navigate(ROUTES.CONCIERGE)} - buttonText="Go to Workspaces" + headerMediaType="animation" + headerMedia={LottieAnimations.Coin} + headerStyles={styles.activeComponentBG} + titleText={translate('search.searchResults.emptyState.title')} + subtitleText={translate('search.searchResults.emptyState.subtitle')} /> ); } diff --git a/src/components/Skeletons/ItemListSkeletonView.tsx b/src/components/Skeletons/ItemListSkeletonView.tsx index 62e1e5afad13..79b8dec1c183 100644 --- a/src/components/Skeletons/ItemListSkeletonView.tsx +++ b/src/components/Skeletons/ItemListSkeletonView.tsx @@ -1,6 +1,6 @@ -import React, {useMemo, useState} from 'react'; +import React, {useCallback, useMemo, useState} from 'react'; +import type {LayoutChangeEvent, StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; -import type {StyleProp, ViewStyle} from 'react-native'; import SkeletonViewContentLoader from '@components/SkeletonViewContentLoader'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -15,6 +15,14 @@ type ListItemSkeletonProps = { itemViewHeight?: number; }; +const getVerticalMargin = (style: StyleProp): number => { + if (!style) { + return 0; + } + const flattenStyle = style instanceof Array ? Object.assign({}, ...style) : style; + return Number((flattenStyle.marginVertical || 0) + (flattenStyle.marginTop || 0) + (flattenStyle.marginBottom || 0)); +}; + function ItemListSkeletonView({ shouldAnimate = true, renderSkeletonItem, @@ -27,13 +35,36 @@ function ItemListSkeletonView({ const themeStyles = useThemeStyles(); const [numItems, setNumItems] = useState(fixedNumItems ?? 0); + + const totalItemHeight = itemViewHeight + getVerticalMargin(itemViewStyle); + + const handleLayout = useCallback( + (event: LayoutChangeEvent) => { + if (fixedNumItems) { + return; + } + + const totalHeight = event.nativeEvent.layout.height; + + const newNumItems = Math.ceil(totalHeight / totalItemHeight); + + if (newNumItems !== numItems) { + setNumItems(newNumItems); + } + }, + [fixedNumItems, numItems, totalItemHeight], + ); + const skeletonViewItems = useMemo(() => { const items = []; for (let i = 0; i < numItems; i++) { const opacity = gradientOpacity ? 1 - i / numItems : 1; items.push( - - + + { - if (fixedNumItems) { - return; - } - - const newNumItems = Math.ceil(event.nativeEvent.layout.height / itemViewHeight); - if (newNumItems === numItems) { - return; - } - setNumItems(newNumItems); - }} + onLayout={handleLayout} > {skeletonViewItems} diff --git a/src/languages/en.ts b/src/languages/en.ts index 3a569801bb6a..3f0ca3299185 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2804,6 +2804,10 @@ export default { title: 'Nothing to show', subtitle: 'Try creating something using the green + button.', }, + emptyState: { + title: 'No expenses to display', + subtitle: 'Try creating something using the green + button.', + }, }, groupedExpenses: 'grouped expenses', }, diff --git a/src/languages/es.ts b/src/languages/es.ts index a2118d55e43c..ad4c3973a6fd 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2843,6 +2843,10 @@ export default { title: 'No hay nada que ver aquí', subtitle: 'Por favor intenta crear algo usando el botón verde.', }, + emptyState: { + title: 'Sin gastos de exposición', + subtitle: 'Intenta crear algo utilizando el botón verde.', + }, }, groupedExpenses: 'gastos agrupados', }, diff --git a/src/styles/index.ts b/src/styles/index.ts index a12090ff275f..5bf96be3d3c1 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -5056,6 +5056,11 @@ const styles = (theme: ThemeColors) => backgroundColor: theme.cardBG, borderRadius: variables.componentBorderRadiusLarge, }), + + emptyStateHeader: { + borderTopLeftRadius: variables.componentBorderRadiusLarge, + borderTopRightRadius: variables.componentBorderRadiusLarge, + }, } satisfies Styles); type ThemeStyles = ReturnType; From 364708b1fdaac03ee37c216e2d30b62363b4d828 Mon Sep 17 00:00:00 2001 From: Kaushik Kapadiya Date: Mon, 24 Jun 2024 18:57:11 +0530 Subject: [PATCH 119/545] Reset amount on reset button click --- src/components/MoneyRequestAmountInput.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/MoneyRequestAmountInput.tsx b/src/components/MoneyRequestAmountInput.tsx index ec38c04ec8e2..5a8d3742b5f8 100644 --- a/src/components/MoneyRequestAmountInput.tsx +++ b/src/components/MoneyRequestAmountInput.tsx @@ -9,7 +9,6 @@ import getOperatingSystem from '@libs/getOperatingSystem'; import * as MoneyRequestUtils from '@libs/MoneyRequestUtils'; import shouldIgnoreSelectionWhenUpdatedManually from '@libs/shouldIgnoreSelectionWhenUpdatedManually'; import CONST from '@src/CONST'; -import isTextInputFocused from './TextInput/BaseTextInput/isTextInputFocused'; import type {BaseTextInputRef} from './TextInput/BaseTextInput/types'; import TextInputWithCurrencySymbol from './TextInputWithCurrencySymbol'; @@ -107,7 +106,7 @@ const getNewSelection = (oldSelection: Selection, prevLength: number, newLength: return {start: cursorPosition, end: cursorPosition}; }; -const defaultOnFormatAmount = (amount: number) => CurrencyUtils.convertToFrontendAmountAsString(amount); +const defaultOnFormatAmount = (amount: number, currency?: string): string => CurrencyUtils.convertToFrontendAmountAsString(amount); function MoneyRequestAmountInput( { From b454ac27ae3a971f0b9033ca9863cad34be3051d Mon Sep 17 00:00:00 2001 From: Kaushik Kapadiya Date: Mon, 24 Jun 2024 19:16:09 +0530 Subject: [PATCH 120/545] Reset amount on reset button click --- src/components/MoneyRequestAmountInput.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/MoneyRequestAmountInput.tsx b/src/components/MoneyRequestAmountInput.tsx index 5a8d3742b5f8..80b86afc9e06 100644 --- a/src/components/MoneyRequestAmountInput.tsx +++ b/src/components/MoneyRequestAmountInput.tsx @@ -106,7 +106,7 @@ const getNewSelection = (oldSelection: Selection, prevLength: number, newLength: return {start: cursorPosition, end: cursorPosition}; }; -const defaultOnFormatAmount = (amount: number, currency?: string): string => CurrencyUtils.convertToFrontendAmountAsString(amount); +const defaultOnFormatAmount = (amount: number) => CurrencyUtils.convertToFrontendAmountAsString(amount); function MoneyRequestAmountInput( { @@ -208,7 +208,7 @@ function MoneyRequestAmountInput( useEffect(() => { const shouldExitEarly = !currency || typeof amount !== 'number' || (formatAmountOnBlur && textInput.current?.isFocused()) || shouldKeepUserInput; - const frontendAmount = onFormatAmount(amount, currency); + const frontendAmount = onFormatAmount ? onFormatAmount(amount, currency) : defaultOnFormatAmount(amount, currency); if (shouldResetAmount) { setCurrentAmount(frontendAmount); From 7fe8f3e78f66078d253a107d4ec9b5a7ed5250a9 Mon Sep 17 00:00:00 2001 From: Taras Perun Date: Mon, 24 Jun 2024 15:47:07 +0200 Subject: [PATCH 121/545] preloaded linking --- src/libs/E2E/reactNativeLaunchingTest.ts | 1 + .../E2E/tests/preloadedLinkingTest.e2e.ts | 77 +++++++++++++++++++ tests/e2e/config.ts | 10 +++ 3 files changed, 88 insertions(+) create mode 100644 src/libs/E2E/tests/preloadedLinkingTest.e2e.ts diff --git a/src/libs/E2E/reactNativeLaunchingTest.ts b/src/libs/E2E/reactNativeLaunchingTest.ts index f23508987268..26b250ce3814 100644 --- a/src/libs/E2E/reactNativeLaunchingTest.ts +++ b/src/libs/E2E/reactNativeLaunchingTest.ts @@ -39,6 +39,7 @@ const tests: Tests = { [E2EConfig.TEST_NAMES.ChatOpening]: require('./tests/chatOpeningTest.e2e').default, [E2EConfig.TEST_NAMES.ReportTyping]: require('./tests/reportTypingTest.e2e').default, [E2EConfig.TEST_NAMES.Linking]: require('./tests/linkingTest.e2e').default, + [E2EConfig.TEST_NAMES.PreloadedLinking]: require('./tests/preloadedLinkingTest.e2e').default, }; // Once we receive the TII measurement we know that the app is initialized and ready to be used: diff --git a/src/libs/E2E/tests/preloadedLinkingTest.e2e.ts b/src/libs/E2E/tests/preloadedLinkingTest.e2e.ts new file mode 100644 index 000000000000..e718ef0ecdfc --- /dev/null +++ b/src/libs/E2E/tests/preloadedLinkingTest.e2e.ts @@ -0,0 +1,77 @@ +import {DeviceEventEmitter} from 'react-native'; +import type {NativeConfig} from 'react-native-config'; +import Config from 'react-native-config'; +import Timing from '@libs/actions/Timing'; +import E2ELogin from '@libs/E2E/actions/e2eLogin'; +import waitForAppLoaded from '@libs/E2E/actions/waitForAppLoaded'; +import E2EClient from '@libs/E2E/client'; +import getConfigValueOrThrow from '@libs/E2E/utils/getConfigValueOrThrow'; +import getPromiseWithResolve from '@libs/E2E/utils/getPromiseWithResolve'; +import Navigation from '@libs/Navigation/Navigation'; +import Performance from '@libs/Performance'; +import CONST from '@src/CONST'; +import ROUTES from '@src/ROUTES'; + +const test = (config: NativeConfig) => { + console.debug('[E2E] Logging in for comment linking'); + + const reportID = getConfigValueOrThrow('reportID', config); + const linkedReportActionID = getConfigValueOrThrow('linkedReportActionID', config); + + E2ELogin().then((neededLogin) => { + if (neededLogin) { + return waitForAppLoaded().then(() => E2EClient.submitTestDone()); + } + + const [appearMessagePromise, appearMessageResolve] = getPromiseWithResolve(); + const [switchReportPromise, switchReportResolve] = getPromiseWithResolve(); + + Promise.all([appearMessagePromise, switchReportPromise]) + .then(() => { + console.debug('[E2E] Test completed successfully, exiting…'); + E2EClient.submitTestDone(); + }) + .catch((err) => { + console.debug('[E2E] Error while submitting test results:', err); + }); + + const subscription = DeviceEventEmitter.addListener('onViewableItemsChanged', (res) => { + console.debug('[E2E] Viewable items retrieved, verifying correct message…', res); + if (!!res && res[0]?.item?.reportActionID === linkedReportActionID) { + appearMessageResolve(); + subscription.remove(); + } else { + console.debug(`[E2E] Provided message id '${res?.[0]?.item?.reportActionID}' doesn't match to an expected '${linkedReportActionID}'. Waiting for a next one…`); + } + }); + + Performance.subscribeToMeasurements((entry) => { + if (entry.name === CONST.TIMING.SIDEBAR_LOADED) { + console.debug('[E2E] Sidebar loaded, navigating to a report…'); + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID)); + return; + } + + if (entry.name === CONST.TIMING.REPORT_INITIAL_RENDER) { + console.debug('[E2E] Navigating to linked report action…'); + Timing.start(CONST.TIMING.SWITCH_REPORT); + Performance.markStart(CONST.TIMING.SWITCH_REPORT); + + Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, linkedReportActionID)); + return; + } + + if (entry.name === CONST.TIMING.CHAT_RENDER) { + E2EClient.submitTestResults({ + branch: Config.E2E_BRANCH, + name: 'Comment linking', + duration: entry.duration, + }); + + switchReportResolve(); + } + }); + }); +}; + +export default test; diff --git a/tests/e2e/config.ts b/tests/e2e/config.ts index 6eb6bb839ae2..5bd72913c87c 100644 --- a/tests/e2e/config.ts +++ b/tests/e2e/config.ts @@ -8,6 +8,7 @@ const TEST_NAMES = { ReportTyping: 'Report typing', ChatOpening: 'Chat opening', Linking: 'Linking', + PreloadedLinking: 'Preloaded linking', }; /** @@ -96,6 +97,15 @@ export default { linkedReportID: '5421294415618529', linkedReportActionID: '2845024374735019929', }, + [TEST_NAMES.PreloadedLinking]: { + name: TEST_NAMES.PreloadedLinking, + reportScreen: { + autoFocus: true, + }, + // Crowded Policy (Do Not Delete) Report, has a input bar available: + reportID: '5421294415618529', + linkedReportActionID: '8984197495983183608', // Message 4897 + }, }, }; From bc1069262f87cdd9eac9f6b7c37f4318bf6af8a8 Mon Sep 17 00:00:00 2001 From: Kaushik Kapadiya Date: Mon, 24 Jun 2024 19:22:30 +0530 Subject: [PATCH 122/545] Reset amount on reset button click --- src/components/MoneyRequestAmountInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MoneyRequestAmountInput.tsx b/src/components/MoneyRequestAmountInput.tsx index 80b86afc9e06..05b733c85fff 100644 --- a/src/components/MoneyRequestAmountInput.tsx +++ b/src/components/MoneyRequestAmountInput.tsx @@ -208,7 +208,7 @@ function MoneyRequestAmountInput( useEffect(() => { const shouldExitEarly = !currency || typeof amount !== 'number' || (formatAmountOnBlur && textInput.current?.isFocused()) || shouldKeepUserInput; - const frontendAmount = onFormatAmount ? onFormatAmount(amount, currency) : defaultOnFormatAmount(amount, currency); + const frontendAmount = onFormatAmount(amount, currency); if (shouldResetAmount) { setCurrentAmount(frontendAmount); From 4db9a0afc2cdd53daec37ccfbd0d61f407303570 Mon Sep 17 00:00:00 2001 From: Kaushik Kapadiya Date: Mon, 24 Jun 2024 19:45:59 +0530 Subject: [PATCH 123/545] Reset amount on reset button click --- src/components/MoneyRequestAmountInput.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/MoneyRequestAmountInput.tsx b/src/components/MoneyRequestAmountInput.tsx index 05b733c85fff..a63622eb4434 100644 --- a/src/components/MoneyRequestAmountInput.tsx +++ b/src/components/MoneyRequestAmountInput.tsx @@ -9,6 +9,7 @@ import getOperatingSystem from '@libs/getOperatingSystem'; import * as MoneyRequestUtils from '@libs/MoneyRequestUtils'; import shouldIgnoreSelectionWhenUpdatedManually from '@libs/shouldIgnoreSelectionWhenUpdatedManually'; import CONST from '@src/CONST'; +import isTextInputFocused from './TextInput/BaseTextInput/isTextInputFocused'; import type {BaseTextInputRef} from './TextInput/BaseTextInput/types'; import TextInputWithCurrencySymbol from './TextInputWithCurrencySymbol'; @@ -207,7 +208,7 @@ function MoneyRequestAmountInput( })); useEffect(() => { - const shouldExitEarly = !currency || typeof amount !== 'number' || (formatAmountOnBlur && textInput.current?.isFocused()) || shouldKeepUserInput; + const shouldExitEarly = (!currency || typeof amount !== 'number' || (formatAmountOnBlur && isTextInputFocused(textInput))) || shouldKeepUserInput; const frontendAmount = onFormatAmount(amount, currency); if (shouldResetAmount) { From b3087ed1561f1f2661de3574275621adeac5849f Mon Sep 17 00:00:00 2001 From: Kaushik Kapadiya Date: Mon, 24 Jun 2024 19:56:21 +0530 Subject: [PATCH 124/545] Reset amount on reset button click --- src/components/MoneyRequestAmountInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/MoneyRequestAmountInput.tsx b/src/components/MoneyRequestAmountInput.tsx index a63622eb4434..6569e1fbdd8e 100644 --- a/src/components/MoneyRequestAmountInput.tsx +++ b/src/components/MoneyRequestAmountInput.tsx @@ -208,7 +208,7 @@ function MoneyRequestAmountInput( })); useEffect(() => { - const shouldExitEarly = (!currency || typeof amount !== 'number' || (formatAmountOnBlur && isTextInputFocused(textInput))) || shouldKeepUserInput; + const shouldExitEarly = (!currency || typeof amount !== 'number' || (formatAmountOnBlur && isTextInputFocused(textInput))) ?? shouldKeepUserInput; const frontendAmount = onFormatAmount(amount, currency); if (shouldResetAmount) { From d10afcbc59b5d5ecbda2870000b6836266c107eb Mon Sep 17 00:00:00 2001 From: dominictb Date: Tue, 25 Jun 2024 10:02:38 +0700 Subject: [PATCH 125/545] fix: do not refresh draft txn after redirect --- src/libs/actions/IOU.ts | 15 +++++++++++++++ src/pages/iou/request/IOURequestStartPage.tsx | 10 +++++++++- .../request/step/IOURequestStepConfirmation.tsx | 3 ++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/IOU.ts b/src/libs/actions/IOU.ts index bc4569bf4603..77c4378c325f 100644 --- a/src/libs/actions/IOU.ts +++ b/src/libs/actions/IOU.ts @@ -364,6 +364,20 @@ function initMoneyRequest(reportID: string, policy: OnyxEntry, }); } +/** + * + * @param transactionID + * @param reportID + */ +function resetMoneyRequest(transactionID: string, reportID: string, isFromGlobalCreate: boolean) { + Onyx.merge(`${ONYXKEYS.COLLECTION.TRANSACTION_DRAFT}${transactionID}`, { + reportID, + participants: [], + participantsAutoAssigned: false, + isFromGlobalCreate, + }); +} + function createDraftTransaction(transaction: OnyxTypes.Transaction) { if (!transaction) { return; @@ -6998,6 +7012,7 @@ export { detachReceipt, editMoneyRequest, initMoneyRequest, + resetMoneyRequest, navigateToStartStepIfScanFileCannotBeRead, payMoneyRequest, payInvoice, diff --git a/src/pages/iou/request/IOURequestStartPage.tsx b/src/pages/iou/request/IOURequestStartPage.tsx index 44f3c1b6a1bc..d576f0b5546c 100644 --- a/src/pages/iou/request/IOURequestStartPage.tsx +++ b/src/pages/iou/request/IOURequestStartPage.tsx @@ -96,6 +96,11 @@ function IOURequestStartPage({ if (transaction?.reportID === reportID) { return; } + // if transaction is from global create, reset the reportID & participant + if (transaction?.isFromGlobalCreate && transaction.transactionID) { + IOU.resetMoneyRequest(transaction.transactionID, reportID, isFromGlobalCreate); + return; + } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, transactionRequestType.current); }, [transaction, policy, reportID, iouType, isFromGlobalCreate]); @@ -109,9 +114,12 @@ function IOURequestStartPage({ const resetIOUTypeIfChanged = useCallback( (newIOUType: IOURequestType) => { + if (transaction?.iouRequestType === newIOUType) { + return; + } IOU.initMoneyRequest(reportID, policy, isFromGlobalCreate, newIOUType); }, - [policy, reportID, isFromGlobalCreate], + [policy, reportID, isFromGlobalCreate, transaction?.iouRequestType], ); if (!transaction?.transactionID) { diff --git a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx index ea03c9ae3b06..00f43f0c8a63 100644 --- a/src/pages/iou/request/step/IOURequestStepConfirmation.tsx +++ b/src/pages/iou/request/step/IOURequestStepConfirmation.tsx @@ -189,7 +189,8 @@ function IOURequestStepConfirmation({ // If there is not a report attached to the IOU with a reportID, then the participants were manually selected and the user needs taken // back to the participants step if (!transaction?.participantsAutoAssigned) { - Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, reportID, undefined, action)); + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + Navigation.goBack(ROUTES.MONEY_REQUEST_STEP_PARTICIPANTS.getRoute(iouType, transactionID, transaction?.reportID || reportID, undefined, action)); return; } IOUUtils.navigateToStartMoneyRequestStep(requestType, iouType, transactionID, reportID, action); From 9c096648ad8ab8e0572cba385c74114a90740f00 Mon Sep 17 00:00:00 2001 From: Filip Solecki Date: Tue, 25 Jun 2024 08:25:13 +0200 Subject: [PATCH 126/545] Small fixes on search empty page, add new empty component on tags and category pages --- src/components/EmptyStateComponent/index.tsx | 6 +++--- src/components/EmptyStateComponent/types.ts | 4 ++-- src/components/Search.tsx | 16 ++-------------- .../Skeletons/ItemListSkeletonView.tsx | 2 +- src/components/Skeletons/SearchRowSkeleton.tsx | 1 + src/languages/en.ts | 4 ---- src/languages/es.ts | 4 ---- src/pages/Search/EmptySearchView.tsx | 14 ++++++++++---- .../categories/WorkspaceCategoriesPage.tsx | 11 ++++++++--- src/pages/workspace/tags/WorkspaceTagsPage.tsx | 11 ++++++++--- 10 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/components/EmptyStateComponent/index.tsx b/src/components/EmptyStateComponent/index.tsx index a6bd07b94550..24f75fa832f5 100644 --- a/src/components/EmptyStateComponent/index.tsx +++ b/src/components/EmptyStateComponent/index.tsx @@ -20,7 +20,7 @@ type VideoLoadedEventType = { }; }; -function EmptyStateComponent({SkeletonComponent, headerMediaType, headerMedia, buttonText, buttonAction, titleText, subtitleText, headerStyles}: EmptyStateComponentProps) { +function EmptyStateComponent({SkeletonComponent, headerMediaType, headerMedia, buttonText, buttonAction, title, subtitle, headerStyles}: EmptyStateComponentProps) { const styles = useThemeStyles(); const isSmallScreenWidth = getIsSmallScreenWidth(); @@ -85,8 +85,8 @@ function EmptyStateComponent({SkeletonComponent, headerMediaType, headerMedia, b {HeaderComponent} - {titleText} - {subtitleText} + {title} + {subtitle} {buttonText && buttonAction && (