From f470d99d0ebe8e3d14b82ef04d7b3f5372343818 Mon Sep 17 00:00:00 2001 From: Mateusz Rajski Date: Tue, 16 Sep 2025 15:37:29 +0200 Subject: [PATCH 1/8] Add custom ActivityIndicator --- src/CONST/index.ts | 1 + src/components/ActivityIndicator.tsx | 39 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/components/ActivityIndicator.tsx diff --git a/src/CONST/index.ts b/src/CONST/index.ts index c9a770a6372dd..ce10e49d77160 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -1579,6 +1579,7 @@ const CONST = { FAST_SEARCH_TREE_CREATION: 'fast_search_tree_creation', SHOW_HOVER_PREVIEW_DELAY: 270, SHOW_HOVER_PREVIEW_ANIMATION_DURATION: 250, + ACTIVITY_INDICATOR_TIMEOUT: 10000, }, PRIORITY_MODE: { GSD: 'gsd', diff --git a/src/components/ActivityIndicator.tsx b/src/components/ActivityIndicator.tsx new file mode 100644 index 0000000000000..7d3a9f2ec6671 --- /dev/null +++ b/src/components/ActivityIndicator.tsx @@ -0,0 +1,39 @@ +import {useEffect} from 'react'; +import type {ActivityIndicatorProps as RNActivityIndicatorProps} from 'react-native'; +// eslint-disable-next-line no-restricted-imports +import {ActivityIndicator as RNActivityIndicator} from 'react-native'; +import useTheme from '@hooks/useTheme'; +import Log from '@libs/Log'; +import CONST from '@src/CONST'; + +type ActivityIndicatorProps = RNActivityIndicatorProps & { + testID?: string; + timeoutMs?: number; +}; + +function ActivityIndicator({timeoutMs = CONST.TIMING.ACTIVITY_INDICATOR_TIMEOUT, ...rest}: ActivityIndicatorProps) { + const theme = useTheme(); + const timeout = timeoutMs ?? (CONST.TIMING.ACTIVITY_INDICATOR_TIMEOUT as number); + + useEffect(() => { + const timeoutId = setTimeout(() => { + Log.warn('ActivityIndicator has been shown for longer than expected', {timeoutMs: timeout, context: {/** TODO: Add context */}}); + }, timeout); + + return () => { + clearTimeout(timeoutId); + }; + }, [timeout]); + + return ( + + ); +} + +ActivityIndicator.displayName = 'ActivityIndicator'; + +export default ActivityIndicator; From 8fdd017e4d60dc9ba9490ce3282314d9978997c4 Mon Sep 17 00:00:00 2001 From: Mateusz Rajski Date: Wed, 17 Sep 2025 15:54:20 +0200 Subject: [PATCH 2/8] Cleanup ActivityIndicator --- src/components/ActivityIndicator.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/ActivityIndicator.tsx b/src/components/ActivityIndicator.tsx index 7d3a9f2ec6671..830f5571bbbf4 100644 --- a/src/components/ActivityIndicator.tsx +++ b/src/components/ActivityIndicator.tsx @@ -8,12 +8,11 @@ import CONST from '@src/CONST'; type ActivityIndicatorProps = RNActivityIndicatorProps & { testID?: string; - timeoutMs?: number; + timeout?: number; }; -function ActivityIndicator({timeoutMs = CONST.TIMING.ACTIVITY_INDICATOR_TIMEOUT, ...rest}: ActivityIndicatorProps) { +function ActivityIndicator({timeout = CONST.TIMING.ACTIVITY_INDICATOR_TIMEOUT, ...rest}: ActivityIndicatorProps) { const theme = useTheme(); - const timeout = timeoutMs ?? (CONST.TIMING.ACTIVITY_INDICATOR_TIMEOUT as number); useEffect(() => { const timeoutId = setTimeout(() => { From 70010ac1e232699586a59df3e231bcbf47ffbb4a Mon Sep 17 00:00:00 2001 From: Mateusz Rajski Date: Wed, 17 Sep 2025 17:00:24 +0200 Subject: [PATCH 3/8] Use new component in the app --- src/components/ActivityIndicator.tsx | 7 ++++++- src/components/AddPlaidBankAccount.tsx | 10 +++------- src/components/AddToWalletButton/index.native.tsx | 12 +++--------- src/components/AddressSearch/index.tsx | 10 ++++------ .../AttachmentView/DefaultAttachmentView/index.tsx | 3 ++- src/components/AvatarCropModal/AvatarCropModal.tsx | 4 ++-- src/components/Button/index.tsx | 3 ++- src/components/FullscreenLoadingIndicator.tsx | 6 ++---- src/components/HeaderWithBackButton/index.tsx | 4 ++-- src/components/Lightbox/index.tsx | 3 ++- src/components/MenuItem.tsx | 3 ++- src/components/MoneyReportHeader.tsx | 3 ++- src/components/PlaidCardFeedIcon.tsx | 10 +++------- src/components/PlaidLink/index.tsx | 10 +++------- src/components/ReportActionItem/MoneyReportView.tsx | 3 ++- .../MoneyRequestReportPreviewContent.tsx | 8 +++----- .../BaseTextInput/implementation/index.native.tsx | 3 ++- .../TransactionItemRow/ReceiptPreview/index.tsx | 6 ++---- .../NonUSD/BankInfo/subSteps/BankAccountDetails.tsx | 6 ++---- .../NonUSD/BankInfo/subSteps/Confirmation.tsx | 6 ++---- src/pages/home/report/ListBoundaryLoader.tsx | 6 ++---- .../iou/request/step/IOURequestStepCategory.tsx | 6 ++---- .../iou/request/step/IOURequestStepDestination.tsx | 6 ++---- .../request/step/IOURequestStepScan/index.native.tsx | 3 ++- .../iou/request/step/IOURequestStepScan/index.tsx | 3 ++- .../Security/TwoFactorAuth/CopyCodesPage.tsx | 7 +++---- src/pages/settings/Wallet/WalletPage/WalletPage.tsx | 4 ++-- src/pages/signin/ThirdPartySignInPage.tsx | 5 +++-- .../workspace/accounting/PolicyAccountingPage.tsx | 4 ++-- .../accounting/qbd/QuickBooksDesktopSetupPage.tsx | 6 ++---- .../workspace/categories/WorkspaceCategoriesPage.tsx | 6 ++---- .../companyCards/BankConnection/index.native.tsx | 5 +---- .../workspace/companyCards/BankConnection/index.tsx | 5 +---- .../companyCards/WorkspaceCompanyCardDetailsPage.tsx | 6 ++---- .../companyCards/WorkspaceCompanyCardsPage.tsx | 5 +---- .../companyCards/addNew/PlaidConnectionStep.tsx | 6 ++---- .../distanceRates/PolicyDistanceRatesPage.tsx | 6 ++---- .../expensifyCard/WorkspaceExpensifyCardPage.tsx | 5 +---- src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx | 6 ++---- .../receiptPartners/WorkspaceReceiptPartnersPage.tsx | 6 ++---- src/pages/workspace/reports/WorkspaceReportsPage.tsx | 6 ++---- src/pages/workspace/tags/WorkspaceTagsPage.tsx | 6 ++---- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 6 ++---- src/pages/workspace/taxes/WorkspaceTaxesPage.tsx | 6 ++---- .../workspace/workflows/WorkspaceWorkflowsPage.tsx | 7 ++----- 45 files changed, 99 insertions(+), 158 deletions(-) diff --git a/src/components/ActivityIndicator.tsx b/src/components/ActivityIndicator.tsx index 830f5571bbbf4..25bc532b76900 100644 --- a/src/components/ActivityIndicator.tsx +++ b/src/components/ActivityIndicator.tsx @@ -16,7 +16,12 @@ function ActivityIndicator({timeout = CONST.TIMING.ACTIVITY_INDICATOR_TIMEOUT, . useEffect(() => { const timeoutId = setTimeout(() => { - Log.warn('ActivityIndicator has been shown for longer than expected', {timeoutMs: timeout, context: {/** TODO: Add context */}}); + Log.warn('ActivityIndicator has been shown for longer than expected', { + timeoutMs: timeout, + context: { + /** TODO: Add context */ + }, + }); }, timeout); return () => { diff --git a/src/components/AddPlaidBankAccount.tsx b/src/components/AddPlaidBankAccount.tsx index edfdb76b7b8f9..7d1d1a6c3ad1d 100644 --- a/src/components/AddPlaidBankAccount.tsx +++ b/src/components/AddPlaidBankAccount.tsx @@ -1,10 +1,9 @@ import React, {useCallback, useEffect, useRef, useState} from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {handlePlaidError, openPlaidBankAccountSelector, openPlaidBankLogin, setPlaidEvent} from '@libs/actions/BankAccounts'; import KeyboardShortcut from '@libs/KeyboardShortcut'; @@ -14,6 +13,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {PlaidData} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import ActivityIndicator from './ActivityIndicator'; import FullPageOfflineBlockingView from './BlockingViews/FullPageOfflineBlockingView'; import FormHelpMessage from './FormHelpMessage'; import Icon from './Icon'; @@ -74,7 +74,6 @@ function AddPlaidBankAccount({ onInputChange = () => {}, isDisplayedInWalletFlow = false, }: AddPlaidBankAccountProps) { - const theme = useTheme(); const styles = useThemeStyles(); const plaidBankAccounts = plaidData?.bankAccounts ?? []; const defaultSelectedPlaidAccount = plaidBankAccounts.find((account) => account.plaidAccountID === selectedPlaidAccountID); @@ -230,10 +229,7 @@ function AddPlaidBankAccount({ if (plaidData?.isLoading) { return ( - + ); } diff --git a/src/components/AddToWalletButton/index.native.tsx b/src/components/AddToWalletButton/index.native.tsx index 6e18ec8d579ad..daf40f155690b 100644 --- a/src/components/AddToWalletButton/index.native.tsx +++ b/src/components/AddToWalletButton/index.native.tsx @@ -1,10 +1,10 @@ import {AddToWalletButton as RNAddToWalletButton} from '@expensify/react-native-wallet'; import type {TokenizationStatus} from '@expensify/react-native-wallet'; import React, {useCallback, useEffect, useState} from 'react'; -import {ActivityIndicator, Alert, View} from 'react-native'; +import {Alert, View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {openWalletPage} from '@libs/actions/PaymentMethods'; import getPlatform from '@libs/getPlatform'; @@ -19,7 +19,6 @@ function AddToWalletButton({card, cardHolderName, cardDescription, buttonStyle}: const {translate} = useLocalize(); const isCardAvailable = card.state === CONST.EXPENSIFY_CARD.STATE.OPEN; const [isLoading, setIsLoading] = useState(false); - const theme = useTheme(); const platform = getPlatform() === CONST.PLATFORM.IOS ? 'Apple' : 'Google'; const styles = useThemeStyles(); @@ -81,12 +80,7 @@ function AddToWalletButton({card, cardHolderName, cardDescription, buttonStyle}: } if (isLoading) { - return ( - - ); + return ; } if (isInWallet) { diff --git a/src/components/AddressSearch/index.tsx b/src/components/AddressSearch/index.tsx index 2b4fc3f40ce4d..a171e17a58a8c 100644 --- a/src/components/AddressSearch/index.tsx +++ b/src/components/AddressSearch/index.tsx @@ -1,9 +1,10 @@ import React, {forwardRef, useEffect, useMemo, useRef, useState} from 'react'; import type {ForwardedRef} from 'react'; -import {ActivityIndicator, Keyboard, LogBox, View} from 'react-native'; +import {Keyboard, LogBox, View} from 'react-native'; import type {LayoutChangeEvent} from 'react-native'; import {GooglePlacesAutocomplete} from 'react-native-google-places-autocomplete'; import type {GooglePlaceData, GooglePlaceDetail} from 'react-native-google-places-autocomplete'; +import ActivityIndicator from '@components/ActivityIndicator'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import LocationErrorMessage from '@components/LocationErrorMessage'; import ScrollView from '@components/ScrollView'; @@ -339,13 +340,10 @@ function AddressSearch( const listLoader = useMemo( () => ( - + ), - [styles.pv4, theme.spinner], + [styles.pv4], ); return ( diff --git a/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx b/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx index 2ec825b6ac554..34f8da7959aa7 100644 --- a/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx +++ b/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx @@ -1,6 +1,7 @@ import React from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import Text from '@components/Text'; diff --git a/src/components/AvatarCropModal/AvatarCropModal.tsx b/src/components/AvatarCropModal/AvatarCropModal.tsx index be14348ce897a..a4ec436bb2e0b 100644 --- a/src/components/AvatarCropModal/AvatarCropModal.tsx +++ b/src/components/AvatarCropModal/AvatarCropModal.tsx @@ -1,10 +1,11 @@ import React, {useCallback, useEffect, useState} from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import type {LayoutChangeEvent} from 'react-native'; import {Gesture, GestureHandlerRootView} from 'react-native-gesture-handler'; import type {GestureUpdateEvent, PanGestureChangeEventPayload, PanGestureHandlerEventPayload} from 'react-native-gesture-handler'; import ImageSize from 'react-native-image-size'; import {interpolate, runOnUI, useSharedValue} from 'react-native-reanimated'; +import ActivityIndicator from '@components/ActivityIndicator'; import Button from '@components/Button'; import HeaderGap from '@components/HeaderGap'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -375,7 +376,6 @@ function AvatarCropModal({imageUri = '', imageName = '', imageType = '', onClose {/* To avoid layout shift we should hide this component until the image container & image is initialized */} {!isImageInitialized || !isImageContainerInitialized ? ( diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx index 3677f5ca566a3..c7b8ad3ddafce 100644 --- a/src/components/Button/index.tsx +++ b/src/components/Button/index.tsx @@ -2,7 +2,8 @@ import {useIsFocused} from '@react-navigation/native'; import type {ForwardedRef} from 'react'; import React, {useCallback, useMemo, useState} from 'react'; import type {GestureResponderEvent, LayoutChangeEvent, StyleProp, TextStyle, ViewStyle} from 'react-native'; -import {ActivityIndicator, StyleSheet, View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import type {PressableRef} from '@components/Pressable/GenericPressable/types'; diff --git a/src/components/FullscreenLoadingIndicator.tsx b/src/components/FullscreenLoadingIndicator.tsx index 32ff1cd1f0793..77e2c5407ef26 100644 --- a/src/components/FullscreenLoadingIndicator.tsx +++ b/src/components/FullscreenLoadingIndicator.tsx @@ -1,8 +1,8 @@ import React from 'react'; import type {ActivityIndicatorProps, StyleProp, ViewStyle} from 'react-native'; -import {ActivityIndicator, StyleSheet, View} from 'react-native'; -import useTheme from '@hooks/useTheme'; +import {StyleSheet, View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; +import ActivityIndicator from './ActivityIndicator'; type FullScreenLoadingIndicatorIconSize = ActivityIndicatorProps['size']; @@ -13,12 +13,10 @@ type FullScreenLoadingIndicatorProps = { }; function FullScreenLoadingIndicator({style, iconSize = 'large', testID = ''}: FullScreenLoadingIndicatorProps) { - const theme = useTheme(); const styles = useThemeStyles(); return ( diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx index b3393ecd10300..8f0915ef3b847 100755 --- a/src/components/HeaderWithBackButton/index.tsx +++ b/src/components/HeaderWithBackButton/index.tsx @@ -1,6 +1,7 @@ import React, {useMemo} from 'react'; -import {ActivityIndicator, Keyboard, StyleSheet, View} from 'react-native'; +import {Keyboard, StyleSheet, View} from 'react-native'; import type {SvgProps} from 'react-native-svg'; +import ActivityIndicator from '@components/ActivityIndicator'; import Avatar from '@components/Avatar'; import AvatarWithDisplayName from '@components/AvatarWithDisplayName'; import Header from '@components/Header'; @@ -274,7 +275,6 @@ function HeaderWithBackButton({ ))} {shouldShowPinButton && !!report && } diff --git a/src/components/Lightbox/index.tsx b/src/components/Lightbox/index.tsx index e9ae48eaacda2..f67dfa0a3295b 100644 --- a/src/components/Lightbox/index.tsx +++ b/src/components/Lightbox/index.tsx @@ -1,7 +1,8 @@ import React, {useCallback, useContext, useEffect, useMemo, useState} from 'react'; import type {LayoutChangeEvent, StyleProp, ViewStyle} from 'react-native'; -import {ActivityIndicator, PixelRatio, StyleSheet, View} from 'react-native'; +import {PixelRatio, StyleSheet, View} from 'react-native'; import {useSharedValue} from 'react-native-reanimated'; +import ActivityIndicator from '@components/ActivityIndicator'; import AttachmentOfflineIndicator from '@components/AttachmentOfflineIndicator'; import AttachmentCarouselPagerContext from '@components/Attachments/AttachmentCarousel/Pager/AttachmentCarouselPagerContext'; import Image from '@components/Image'; diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index ba55883c8c75a..a6214f6ba0899 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -2,7 +2,7 @@ import type {ImageContentFit} from 'expo-image'; import type {ReactElement, ReactNode, Ref} from 'react'; import React, {useContext, useMemo, useRef} from 'react'; import type {GestureResponderEvent, StyleProp, TextStyle, ViewStyle} from 'react-native'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useStyleUtils from '@hooks/useStyleUtils'; @@ -24,6 +24,7 @@ import CONST from '@src/CONST'; import type {Icon as IconType} from '@src/types/onyx/OnyxCommon'; import type {TooltipAnchorAlignment} from '@src/types/utils/AnchorAlignment'; import type IconAsset from '@src/types/utils/IconAsset'; +import ActivityIndicator from './ActivityIndicator'; import Avatar from './Avatar'; import Badge from './Badge'; import CopyTextToClipboard from './CopyTextToClipboard'; diff --git a/src/components/MoneyReportHeader.tsx b/src/components/MoneyReportHeader.tsx index 7f18e6500e8fa..2b8fa0519d3bd 100644 --- a/src/components/MoneyReportHeader.tsx +++ b/src/components/MoneyReportHeader.tsx @@ -1,6 +1,6 @@ import {useRoute} from '@react-navigation/native'; import React, {useCallback, useContext, useEffect, useMemo, useState} from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import useDuplicateTransactionsAndViolations from '@hooks/useDuplicateTransactionsAndViolations'; @@ -103,6 +103,7 @@ import type * as OnyxTypes from '@src/types/onyx'; import type {PaymentMethodType} from '@src/types/onyx/OriginalMessage'; import type IconAsset from '@src/types/utils/IconAsset'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; +import ActivityIndicator from './ActivityIndicator'; import BrokenConnectionDescription from './BrokenConnectionDescription'; import Button from './Button'; import ButtonWithDropdownMenu from './ButtonWithDropdownMenu'; diff --git a/src/components/PlaidCardFeedIcon.tsx b/src/components/PlaidCardFeedIcon.tsx index 813cff7b44f5b..3ef12ea0e2373 100644 --- a/src/components/PlaidCardFeedIcon.tsx +++ b/src/components/PlaidCardFeedIcon.tsx @@ -1,10 +1,10 @@ import React, {useEffect, useState} from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import type {StyleProp, ViewStyle} from 'react-native'; -import useTheme from '@hooks/useTheme'; import useThemeIllustrations from '@hooks/useThemeIllustrations'; import useThemeStyles from '@hooks/useThemeStyles'; import variables from '@styles/variables'; +import ActivityIndicator from './ActivityIndicator'; import Icon from './Icon'; import * as Illustrations from './Icon/Illustrations'; import Image from './Image'; @@ -20,7 +20,6 @@ function PlaidCardFeedIcon({plaidUrl, style, isLarge, isSmall}: PlaidCardFeedIco const [isBrokenImage, setIsBrokenImage] = useState(false); const styles = useThemeStyles(); const illustrations = useThemeIllustrations(); - const theme = useTheme(); const width = isLarge ? variables.cardPreviewWidth : variables.cardIconWidth; const height = isLarge ? variables.cardPreviewHeight : variables.cardIconHeight; const [loading, setLoading] = useState(true); @@ -57,10 +56,7 @@ function PlaidCardFeedIcon({plaidUrl, style, isLarge, isSmall}: PlaidCardFeedIco /> {loading ? ( - + ) : ( {}, onError = () => {}, onExit = () => {}, onEvent, receivedRedirectURI}: PlaidLinkProps) { const [isPlaidLoaded, setIsPlaidLoaded] = useState(false); - const theme = useTheme(); const styles = useThemeStyles(); const successCallback = useCallback( (publicToken: string, metadata: PlaidLinkOnSuccessMetadata) => { @@ -55,10 +54,7 @@ function PlaidLink({token, onSuccess = () => {}, onError = () => {}, onExit = () return ( - + ); } diff --git a/src/components/ReportActionItem/MoneyReportView.tsx b/src/components/ReportActionItem/MoneyReportView.tsx index dc1d9e628bfb0..ec701b20837e8 100644 --- a/src/components/ReportActionItem/MoneyReportView.tsx +++ b/src/components/ReportActionItem/MoneyReportView.tsx @@ -1,8 +1,9 @@ import {Str} from 'expensify-common'; import React, {useMemo} from 'react'; import type {StyleProp, TextStyle} from 'react-native'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; +import ActivityIndicator from '@components/ActivityIndicator'; import Icon from '@components/Icon'; import * as Expensicons from '@components/Icon/Expensicons'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; diff --git a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx index 8a65be44a3fd0..e56dc3343c651 100644 --- a/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx +++ b/src/components/ReportActionItem/MoneyRequestReportPreview/MoneyRequestReportPreviewContent.tsx @@ -1,7 +1,8 @@ import React, {useCallback, useContext, useDeferredValue, useEffect, useMemo, useRef, useState} from 'react'; -import {ActivityIndicator, FlatList, View} from 'react-native'; +import {FlatList, View} from 'react-native'; import type {ListRenderItemInfo, ViewToken} from 'react-native'; import Animated, {useAnimatedStyle, useSharedValue, withDelay, withSpring, withTiming} from 'react-native-reanimated'; +import ActivityIndicator from '@components/ActivityIndicator'; import Button from '@components/Button'; import {getButtonRole} from '@components/Button/utils'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; @@ -722,10 +723,7 @@ function MoneyRequestReportPreviewContent({ styles.mtn1, ]} > - + ) : ( diff --git a/src/components/TextInput/BaseTextInput/implementation/index.native.tsx b/src/components/TextInput/BaseTextInput/implementation/index.native.tsx index 7aa3c74a6f63c..974d37ca748b4 100644 --- a/src/components/TextInput/BaseTextInput/implementation/index.native.tsx +++ b/src/components/TextInput/BaseTextInput/implementation/index.native.tsx @@ -1,7 +1,7 @@ import {Str} from 'expensify-common'; import React, {useCallback, useEffect, useRef, useState} from 'react'; import type {GestureResponderEvent, LayoutChangeEvent, NativeSyntheticEvent, StyleProp, TextInput, TextInputFocusEventData, ViewStyle} from 'react-native'; -import {ActivityIndicator, StyleSheet, View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import {Easing, useSharedValue, withTiming} from 'react-native-reanimated'; import Checkbox from '@components/Checkbox'; import FormHelpMessage from '@components/FormHelpMessage'; @@ -27,6 +27,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import isInputAutoFilled from '@libs/isInputAutoFilled'; import variables from '@styles/variables'; import CONST from '@src/CONST'; +import ActivityIndicator from '@components/ActivityIndicator'; function BaseTextInput({ label = '', diff --git a/src/components/TransactionItemRow/ReceiptPreview/index.tsx b/src/components/TransactionItemRow/ReceiptPreview/index.tsx index 1702c8024e012..cb1f0653f3e57 100644 --- a/src/components/TransactionItemRow/ReceiptPreview/index.tsx +++ b/src/components/TransactionItemRow/ReceiptPreview/index.tsx @@ -1,14 +1,13 @@ import React, {useCallback, useEffect, useRef, useState} from 'react'; import ReactDOM from 'react-dom'; import type {LayoutChangeEvent} from 'react-native'; -import {ActivityIndicator, StyleSheet, View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'; import DistanceEReceipt from '@components/DistanceEReceipt'; import EReceiptWithSizeCalculation from '@components/EReceiptWithSizeCalculation'; import type {ImageOnLoadEvent} from '@components/Image/types'; import useDebouncedState from '@hooks/useDebouncedState'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import {isDistanceRequest, isManualDistanceRequest} from '@libs/TransactionUtils'; @@ -16,6 +15,7 @@ import variables from '@styles/variables'; import Image from '@src/components/Image'; import CONST from '@src/CONST'; import type {Transaction} from '@src/types/onyx'; +import ActivityIndicator from '@components/ActivityIndicator'; type ReceiptPreviewProps = { /** Path to the image to be opened in the preview */ @@ -34,7 +34,6 @@ type ReceiptPreviewProps = { function ReceiptPreview({source, hovered, isEReceipt = false, transactionItem}: ReceiptPreviewProps) { const isDistanceEReceipt = isDistanceRequest(transactionItem) && !isManualDistanceRequest(transactionItem); const styles = useThemeStyles(); - const theme = useTheme(); const [eReceiptScaleFactor, setEReceiptScaleFactor] = useState(0); const [imageAspectRatio, setImageAspectRatio] = useState(undefined); const [distanceEReceiptAspectRatio, setDistanceEReceiptAspectRatio] = useState(undefined); @@ -110,7 +109,6 @@ function ReceiptPreview({source, hovered, isEReceipt = false, transactionItem}: {isLoading && ( diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx index 2e077788e6a3b..d607265bdf086 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useMemo} from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import AddressSearch from '@components/AddressSearch'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; @@ -9,7 +9,6 @@ import TextInput from '@components/TextInput'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useReimbursementAccountStepFormSubmit from '@hooks/useReimbursementAccountStepFormSubmit'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import type BankInfoSubStepProps from '@pages/ReimbursementAccount/NonUSD/BankInfo/types'; import {getBankInfoStepValues} from '@pages/ReimbursementAccount/NonUSD/utils/getBankInfoStepValues'; @@ -18,6 +17,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {ReimbursementAccountForm} from '@src/types/form'; import type {CorpayFormField} from '@src/types/onyx'; +import ActivityIndicator from '@components/ActivityIndicator'; function getInputComponent(field: CorpayFormField) { if (CONST.CORPAY_FIELDS.SPECIAL_LIST_ADDRESS_KEYS.includes(field.id)) { @@ -29,7 +29,6 @@ function getInputComponent(field: CorpayFormField) { function BankAccountDetails({onNext, isEditing, corpayFields}: BankInfoSubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); - const theme = useTheme(); const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {canBeMissing: false}); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT, {canBeMissing: true}); @@ -134,7 +133,6 @@ function BankAccountDetails({onNext, isEditing, corpayFields}: BankInfoSubStepPr diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx index dd707a480d071..84e8efbe0ad66 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx @@ -1,11 +1,10 @@ import React, {useMemo} from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import FormProvider from '@components/Form/FormProvider'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import type BankInfoSubStepProps from '@pages/ReimbursementAccount/NonUSD/BankInfo/types'; import {getBankInfoStepValues} from '@pages/ReimbursementAccount/NonUSD/utils/getBankInfoStepValues'; @@ -13,12 +12,12 @@ import getInputKeysForBankInfoStep from '@pages/ReimbursementAccount/NonUSD/util import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; +import ActivityIndicator from '@components/ActivityIndicator'; const {ACCOUNT_HOLDER_COUNTRY} = INPUT_IDS.ADDITIONAL_DATA.CORPAY; function Confirmation({onNext, onMove, corpayFields}: BankInfoSubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); - const theme = useTheme(); const [reimbursementAccount] = useOnyx(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {canBeMissing: false}); const [reimbursementAccountDraft] = useOnyx(ONYXKEYS.FORMS.REIMBURSEMENT_ACCOUNT_FORM_DRAFT, {canBeMissing: true}); @@ -67,7 +66,6 @@ function Confirmation({onNext, onMove, corpayFields}: BankInfoSubStepProps) { {corpayFields?.isLoading ? ( ) : ( diff --git a/src/pages/home/report/ListBoundaryLoader.tsx b/src/pages/home/report/ListBoundaryLoader.tsx index 8081e18bb6680..df6e2135d845b 100644 --- a/src/pages/home/report/ListBoundaryLoader.tsx +++ b/src/pages/home/report/ListBoundaryLoader.tsx @@ -1,14 +1,14 @@ import React, {useEffect} from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; import Button from '@components/Button'; import ReportActionsSkeletonView from '@components/ReportActionsSkeletonView'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; +import ActivityIndicator from '@components/ActivityIndicator'; type ListBoundaryLoaderProps = { /** type of rendered loader. Can be 'header' or 'footer' */ @@ -42,7 +42,6 @@ function ListBoundaryLoader({ hasError = false, onRetry, }: ListBoundaryLoaderProps) { - const theme = useTheme(); const styles = useThemeStyles(); const {isOffline} = useNetwork(); const {translate} = useLocalize(); @@ -102,7 +101,6 @@ function ListBoundaryLoader({ return ( diff --git a/src/pages/iou/request/step/IOURequestStepCategory.tsx b/src/pages/iou/request/step/IOURequestStepCategory.tsx index b549595aeee1b..b15d3c4a3b345 100644 --- a/src/pages/iou/request/step/IOURequestStepCategory.tsx +++ b/src/pages/iou/request/step/IOURequestStepCategory.tsx @@ -1,6 +1,6 @@ import lodashIsEmpty from 'lodash/isEmpty'; import React, {useEffect} from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import Button from '@components/Button'; import CategoryPicker from '@components/CategoryPicker'; @@ -14,7 +14,6 @@ import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; import useShowNotFoundPageInIOUStep from '@hooks/useShowNotFoundPageInIOUStep'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {getIOURequestPolicyID, setDraftSplitTransaction, setMoneyRequestCategory, updateMoneyRequestCategory} from '@libs/actions/IOU'; import {enablePolicyCategories, getPolicyCategories} from '@libs/actions/Policy/Category'; @@ -28,6 +27,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; +import ActivityIndicator from '@components/ActivityIndicator'; import StepScreenWrapper from './StepScreenWrapper'; import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; @@ -46,7 +46,6 @@ function IOURequestStepCategory({ transaction, }: IOURequestStepCategoryProps) { const styles = useThemeStyles(); - const theme = useTheme(); const {translate} = useLocalize(); const policyIdReal = getIOURequestPolicyID(transaction, reportReal); @@ -154,7 +153,6 @@ function IOURequestStepCategory({ )} {shouldShowOfflineView && {null}} diff --git a/src/pages/iou/request/step/IOURequestStepDestination.tsx b/src/pages/iou/request/step/IOURequestStepDestination.tsx index a6c6c54c03182..b8e7529365814 100644 --- a/src/pages/iou/request/step/IOURequestStepDestination.tsx +++ b/src/pages/iou/request/step/IOURequestStepDestination.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import Button from '@components/Button'; import DestinationPicker from '@components/DestinationPicker'; @@ -13,7 +13,6 @@ import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; import useSafeAreaInsets from '@hooks/useSafeAreaInsets'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@libs/Navigation/Navigation'; import {getPerDiemCustomUnit, isPolicyAdmin} from '@libs/PolicyUtils'; @@ -34,6 +33,7 @@ import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; +import ActivityIndicator from '@components/ActivityIndicator'; import StepScreenWrapper from './StepScreenWrapper'; import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; @@ -63,7 +63,6 @@ function IOURequestStepDestination({ const selectedDestination = transaction?.comment?.customUnit?.customUnitRateID; const styles = useThemeStyles(); - const theme = useTheme(); const {translate} = useLocalize(); // eslint-disable-next-line rulesdir/no-negated-variables @@ -131,7 +130,6 @@ function IOURequestStepDestination({ )} {shouldShowOfflineView && {null}} diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index b37d64cf9f70a..4efe06d3e4e5a 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -1,6 +1,6 @@ import {useFocusEffect} from '@react-navigation/core'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {ActivityIndicator, Alert, AppState, InteractionManager, StyleSheet, View} from 'react-native'; +import {Alert, AppState, InteractionManager, StyleSheet, View} from 'react-native'; import type {LayoutRectangle} from 'react-native'; import ReactNativeBlobUtil from 'react-native-blob-util'; import {Gesture, GestureDetector} from 'react-native-gesture-handler'; @@ -74,6 +74,7 @@ import type {Participant} from '@src/types/onyx/IOU'; import type Transaction from '@src/types/onyx/Transaction'; import type {Receipt} from '@src/types/onyx/Transaction'; import {getEmptyObject} from '@src/types/utils/EmptyObject'; +import ActivityIndicator from '@components/ActivityIndicator'; import CameraPermission from './CameraPermission'; import {cropImageToAspectRatio} from './cropImageToAspectRatio'; import type {ImageObject} from './cropImageToAspectRatio'; diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index b9e05dbb8b508..3ade2e357633b 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -1,7 +1,7 @@ import {useIsFocused} from '@react-navigation/native'; import React, {useCallback, useContext, useEffect, useMemo, useReducer, useRef, useState} from 'react'; import type {LayoutRectangle} from 'react-native'; -import {ActivityIndicator, InteractionManager, PanResponder, StyleSheet, View} from 'react-native'; +import {InteractionManager, PanResponder, StyleSheet, View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; import {RESULTS} from 'react-native-permissions'; import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; @@ -76,6 +76,7 @@ import type {Participant} from '@src/types/onyx/IOU'; import type Transaction from '@src/types/onyx/Transaction'; import type {Receipt} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import ActivityIndicator from '@components/ActivityIndicator'; import {cropImageToAspectRatio} from './cropImageToAspectRatio'; import type {ImageObject} from './cropImageToAspectRatio'; import {getLocationPermission} from './LocationPermission'; diff --git a/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx b/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx index fa2ae403d0268..f4f15b692f3d4 100644 --- a/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx @@ -1,5 +1,5 @@ import React, {useEffect, useMemo, useState} from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import Button from '@components/Button'; import FixedFooter from '@components/FixedFooter'; import FormHelpMessage from '@components/FormHelpMessage'; @@ -14,7 +14,6 @@ import useBeforeRemove from '@hooks/useBeforeRemove'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {READ_COMMANDS} from '@libs/API/types'; import Clipboard from '@libs/Clipboard'; @@ -29,11 +28,11 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; +import ActivityIndicator from '@components/ActivityIndicator'; import type {TwoFactorAuthPageProps} from './TwoFactorAuthPage'; import TwoFactorAuthWrapper from './TwoFactorAuthWrapper'; function CopyCodesPage({route}: TwoFactorAuthPageProps) { - const theme = useTheme(); const styles = useThemeStyles(); const {translate, formatPhoneNumber} = useLocalize(); // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout to use correct style @@ -92,7 +91,7 @@ function CopyCodesPage({route}: TwoFactorAuthPageProps) { {account?.isLoading ? ( - + ) : ( <> diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx index 562cebdab32f7..d170e113984dc 100644 --- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx +++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx @@ -3,7 +3,7 @@ import isEmpty from 'lodash/isEmpty'; import type {ForwardedRef, RefObject} from 'react'; import React, {useCallback, useContext, useEffect, useLayoutEffect, useRef, useState} from 'react'; import type {GestureResponderEvent} from 'react-native'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu'; import ConfirmModal from '@components/ConfirmModal'; import {DelegateNoAccessContext} from '@components/DelegateNoAccessModalProvider'; @@ -51,6 +51,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import {getEmptyObject} from '@src/types/utils/EmptyObject'; +import ActivityIndicator from '@components/ActivityIndicator'; type WalletPageProps = { /** Listen for window resize event on web and desktop. */ @@ -501,7 +502,6 @@ function WalletPage({shouldListenForResize = false}: WalletPageProps) { <> {shouldShowLoadingSpinner && ( diff --git a/src/pages/signin/ThirdPartySignInPage.tsx b/src/pages/signin/ThirdPartySignInPage.tsx index e8616a8754950..471c1028eedd9 100644 --- a/src/pages/signin/ThirdPartySignInPage.tsx +++ b/src/pages/signin/ThirdPartySignInPage.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import {SafeAreaView} from 'react-native-safe-area-context'; import type {ValueOf} from 'type-fest'; import AppleSignIn from '@components/SignInButtons/AppleSignIn'; @@ -13,6 +13,7 @@ import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; +import ActivityIndicator from '@components/ActivityIndicator'; import SignInPageLayout from './SignInPageLayout'; type ThirdPartySignInPageProps = { @@ -36,7 +37,7 @@ function ThirdPartySignInPage({signInProvider}: ThirdPartySignInPageProps) { {account?.isLoading ? ( - + ) : ( ) : ( ; function RequireQuickBooksDesktopModal({route}: RequireQuickBooksDesktopModalProps) { const {translate} = useLocalize(); - const theme = useTheme(); const styles = useThemeStyles(); const {environmentURL} = useEnvironment(); const policyID: string = route.params.policyID; @@ -116,7 +115,6 @@ function RequireQuickBooksDesktopModal({route}: RequireQuickBooksDesktopModalPro {!hasResultOfFetchingSetupLink ? ( ) : ( diff --git a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx index f4ecc1c4fe459..867463299c991 100644 --- a/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx +++ b/src/pages/workspace/categories/WorkspaceCategoriesPage.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import Button from '@components/Button'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types'; @@ -33,7 +33,6 @@ import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSearchBackPress from '@hooks/useSearchBackPress'; import useSearchResults from '@hooks/useSearchResults'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {isConnectionInProgress, isConnectionUnverified} from '@libs/actions/connections'; import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode'; @@ -52,6 +51,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import ActivityIndicator from '@components/ActivityIndicator'; type PolicyOption = ListItem & { /** Category name is used as a key for the selectedCategories state */ @@ -67,7 +67,6 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {shouldUseNarrowLayout, isSmallScreenWidth} = useResponsiveLayout(); const styles = useThemeStyles(); - const theme = useTheme(); const {translate, localeCompare} = useLocalize(); const [isOfflineModalVisible, setIsOfflineModalVisible] = useState(false); const [isDownloadFailureModalVisible, setIsDownloadFailureModalVisible] = useState(false); @@ -526,7 +525,6 @@ function WorkspaceCategoriesPage({route}: WorkspaceCategoriesPageProps) { )} {hasVisibleCategories && !isLoading && ( diff --git a/src/pages/workspace/companyCards/BankConnection/index.native.tsx b/src/pages/workspace/companyCards/BankConnection/index.native.tsx index 2d0119f01cdd4..e8e7459d260aa 100644 --- a/src/pages/workspace/companyCards/BankConnection/index.native.tsx +++ b/src/pages/workspace/companyCards/BankConnection/index.native.tsx @@ -1,5 +1,4 @@ import React, {useEffect, useMemo, useRef, useState} from 'react'; -import {ActivityIndicator} from 'react-native'; import type {WebViewNavigation} from 'react-native-webview'; import {WebView} from 'react-native-webview'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; @@ -12,7 +11,6 @@ import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import usePrevious from '@hooks/usePrevious'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {updateSelectedFeed} from '@libs/actions/Card'; import {setAssignCardStepAndData} from '@libs/actions/CompanyCards'; @@ -28,6 +26,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {CompanyCardFeed} from '@src/types/onyx'; +import ActivityIndicator from '@components/ActivityIndicator'; type BankConnectionProps = { /** ID of the policy */ @@ -43,7 +42,6 @@ type BankConnectionProps = { function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnectionProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); - const theme = useTheme(); const webViewRef = useRef(null); const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD, {canBeMissing: true}); @@ -169,7 +167,6 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti )} diff --git a/src/pages/workspace/companyCards/BankConnection/index.tsx b/src/pages/workspace/companyCards/BankConnection/index.tsx index 3fbeb4a0b485c..4dcb10ef36ab1 100644 --- a/src/pages/workspace/companyCards/BankConnection/index.tsx +++ b/src/pages/workspace/companyCards/BankConnection/index.tsx @@ -1,5 +1,4 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import {ActivityIndicator} from 'react-native'; import BlockingView from '@components/BlockingViews/BlockingView'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -14,7 +13,6 @@ import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import usePrevious from '@hooks/usePrevious'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {setAssignCardStepAndData} from '@libs/actions/CompanyCards'; import {checkIfNewFeedConnected, getBankName, isSelectedFeedExpired} from '@libs/CardUtils'; @@ -29,6 +27,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {CompanyCardFeed} from '@src/types/onyx'; +import ActivityIndicator from '@components/ActivityIndicator'; import openBankConnection from './openBankConnection'; let customWindow: Window | null = null; @@ -49,7 +48,6 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti const {translate} = useLocalize(); const [addNewCard] = useOnyx(ONYXKEYS.ADD_NEW_COMPANY_CARD, {canBeMissing: true}); const [assignCard] = useOnyx(ONYXKEYS.ASSIGN_CARD, {canBeMissing: true}); - const theme = useTheme(); const {bankName: bankNameFromRoute, backTo, policyID: policyIDFromRoute} = route?.params ?? {}; const policyID = policyIDFromProps ?? policyIDFromRoute; const [cardFeeds] = useCardFeeds(policyID); @@ -182,7 +180,6 @@ function BankConnection({policyID: policyIDFromProps, feed, route}: BankConnecti ) : ( ; @@ -53,7 +53,6 @@ function WorkspaceCompanyCardDetailsPage({route}: WorkspaceCompanyCardDetailsPag const [isUnassignModalVisible, setIsUnassignModalVisible] = useState(false); const {translate, getLocalDateFromDatetime} = useLocalize(); const styles = useThemeStyles(); - const theme = useTheme(); const illustrations = useThemeIllustrations(); const {isOffline} = useNetwork(); const accountingIntegrations = Object.values(CONST.POLICY.CONNECTIONS.NAME); @@ -181,7 +180,6 @@ function WorkspaceCompanyCardDetailsPage({route}: WorkspaceCompanyCardDetailsPag rightComponent={ } description={translate('workspace.moreFeatures.companyCards.lastUpdated')} diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index 94d348d6828c4..3cd4bd7c8be32 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -1,5 +1,4 @@ import React, {useCallback, useContext, useEffect, useState} from 'react'; -import {ActivityIndicator} from 'react-native'; import DecisionModal from '@components/DecisionModal'; import {DelegateNoAccessContext} from '@components/DelegateNoAccessModalProvider'; import * as Illustrations from '@components/Icon/Illustrations'; @@ -10,7 +9,6 @@ import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; import usePermissions from '@hooks/usePermissions'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import { checkIfFeedConnectionIsBroken, @@ -39,6 +37,7 @@ import type SCREENS from '@src/SCREENS'; import type {CurrencyList} from '@src/types/onyx'; import type {AssignCardData, AssignCardStep} from '@src/types/onyx/AssignCard'; import {getEmptyObject, isEmptyObject} from '@src/types/utils/EmptyObject'; +import ActivityIndicator from '@components/ActivityIndicator'; import WorkspaceCompanyCardPageEmptyState from './WorkspaceCompanyCardPageEmptyState'; import WorkspaceCompanyCardsFeedPendingPage from './WorkspaceCompanyCardsFeedPendingPage'; import WorkspaceCompanyCardsList from './WorkspaceCompanyCardsList'; @@ -49,7 +48,6 @@ type WorkspaceCompanyCardsPageProps = PlatformStackScreenProps )} {!isLoading && ( diff --git a/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx b/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx index bdfd6e5ed48f0..91912857b3c95 100644 --- a/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx +++ b/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useEffect, useRef} from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import type {LinkSuccessMetadata} from 'react-native-plaid-link-sdk'; import type {PlaidLinkOnSuccessMetadata} from 'react-plaid-link/src/types'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; @@ -10,7 +10,6 @@ import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {setAddNewCompanyCardStepAndData, setAssignCardStepAndData} from '@libs/actions/CompanyCards'; import KeyboardShortcut from '@libs/KeyboardShortcut'; @@ -24,11 +23,11 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {CompanyCardFeed} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import ActivityIndicator from '@components/ActivityIndicator'; function PlaidConnectionStep({feed, policyID}: {feed?: CompanyCardFeed; policyID?: string}) { const {translate} = useLocalize(); const styles = useThemeStyles(); - const theme = useTheme(); const [addNewCard] = useOnyx(ONYXKEYS.ADD_NEW_COMPANY_CARD, {canBeMissing: true}); const isUSCountry = addNewCard?.data?.selectedCountry === CONST.COUNTRY.US; const [isPlaidDisabled] = useOnyx(ONYXKEYS.IS_PLAID_DISABLED, {canBeMissing: true}); @@ -190,7 +189,6 @@ function PlaidConnectionStep({feed, policyID}: {feed?: CompanyCardFeed; policyID return ( diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx index 741ecb9c25dbb..af359c85dbe4a 100644 --- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx +++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import Button from '@components/Button'; import type {DropdownOption, WorkspaceDistanceRatesBulkActionType} from '@components/ButtonWithDropdownMenu/types'; import ConfirmModal from '@components/ConfirmModal'; @@ -23,7 +23,6 @@ import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSearchBackPress from '@hooks/useSearchBackPress'; import useSearchResults from '@hooks/useSearchResults'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode'; import { @@ -48,6 +47,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {Rate} from '@src/types/onyx/Policy'; +import ActivityIndicator from '@components/ActivityIndicator'; type RateForList = ListItem & {value: string; rate?: number}; @@ -60,7 +60,6 @@ function PolicyDistanceRatesPage({ }: PolicyDistanceRatesPageProps) { const {shouldUseNarrowLayout} = useResponsiveLayout(); const styles = useThemeStyles(); - const theme = useTheme(); const {translate} = useLocalize(); const [isWarningModalVisible, setIsWarningModalVisible] = useState(false); const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false); @@ -474,7 +473,6 @@ function PolicyDistanceRatesPage({ )} {Object.values(customUnitRates).length > 0 && ( diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPage.tsx index 274fba4e52cf2..469619ba3a17e 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPage.tsx @@ -1,9 +1,7 @@ import React, {useCallback, useEffect} from 'react'; -import {ActivityIndicator} from 'react-native'; import useDefaultFundID from '@hooks/useDefaultFundID'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {filterInactiveCards} from '@libs/CardUtils'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -13,6 +11,7 @@ import {openPolicyExpensifyCardsPage} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; +import ActivityIndicator from '@components/ActivityIndicator'; import WorkspaceExpensifyCardListPage from './WorkspaceExpensifyCardListPage'; import WorkspaceExpensifyCardPageEmptyState from './WorkspaceExpensifyCardPageEmptyState'; @@ -21,7 +20,6 @@ type WorkspaceExpensifyCardPageProps = PlatformStackScreenProps ); } diff --git a/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx b/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx index 242a2cc79c052..6e38dbfbaec9a 100644 --- a/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx +++ b/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx @@ -1,6 +1,6 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types'; import ConfirmModal from '@components/ConfirmModal'; @@ -28,7 +28,6 @@ import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSearchBackPress from '@hooks/useSearchBackPress'; import useSearchResults from '@hooks/useSearchResults'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {convertAmountToDisplayString} from '@libs/CurrencyUtils'; import {canUseTouchScreen} from '@libs/DeviceCapabilities'; @@ -50,6 +49,7 @@ import type SCREENS from '@src/SCREENS'; import type {PendingAction} from '@src/types/onyx/OnyxCommon'; import type {Rate} from '@src/types/onyx/Policy'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import ActivityIndicator from '@components/ActivityIndicator'; type PolicyOption = ListItem & { /** subRateID is used as a key for identification of the entry */ @@ -117,7 +117,6 @@ function WorkspacePerDiemPage({route}: WorkspacePerDiemPageProps) { // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {shouldUseNarrowLayout, isSmallScreenWidth} = useResponsiveLayout(); const styles = useThemeStyles(); - const theme = useTheme(); const {translate, localeCompare} = useLocalize(); const [isOfflineModalVisible, setIsOfflineModalVisible] = useState(false); const [selectedPerDiem, setSelectedPerDiem] = useState([]); @@ -445,7 +444,6 @@ function WorkspacePerDiemPage({route}: WorkspacePerDiemPageProps) { )} {hasVisibleSubRates && !isLoading && ( diff --git a/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx b/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx index 3eaa9e5387ab5..9edeac7696e2a 100644 --- a/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx +++ b/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; import Button from '@components/Button'; import ConfirmModal from '@components/ConfirmModal'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -16,7 +16,6 @@ import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import Navigation from '@navigation/Navigation'; import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types'; @@ -30,6 +29,7 @@ import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {AnchorPosition} from '@src/styles'; +import ActivityIndicator from '@components/ActivityIndicator'; import {getReceiptPartnersIntegrationData} from './utils'; type WorkspaceReceiptPartnersPageProps = PlatformStackScreenProps; @@ -44,7 +44,6 @@ function WorkspaceReceiptPartnersPage({route}: WorkspaceReceiptPartnersPageProps const {isOffline} = useNetwork(); const threeDotsMenuContainerRef = useRef(null); const policy = usePolicy(policyID); - const theme = useTheme(); const [selectedPartner, setSelectedPartner] = useState(null); const isLoading = policy?.isLoading; const [isDisconnectModalOpen, setIsDisconnectModalOpen] = useState(false); @@ -226,7 +225,6 @@ function WorkspaceReceiptPartnersPage({route}: WorkspaceReceiptPartnersPageProps ) : ( )} {!isLoading && ( diff --git a/src/pages/workspace/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx index 75ed76cb4d4a0..035c494fff86c 100644 --- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import Button from '@components/Button'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types'; @@ -33,7 +33,6 @@ import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSearchBackPress from '@hooks/useSearchBackPress'; import useSearchResults from '@hooks/useSearchResults'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {isConnectionInProgress, isConnectionUnverified} from '@libs/actions/connections'; import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode'; @@ -72,6 +71,7 @@ import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import type {PendingAction} from '@src/types/onyx/OnyxCommon'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import ActivityIndicator from '@components/ActivityIndicator'; import type {PolicyTag, PolicyTagList, TagListItem} from './types'; type WorkspaceTagsPageProps = @@ -83,7 +83,6 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) { // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {shouldUseNarrowLayout, isSmallScreenWidth} = useResponsiveLayout(); const styles = useThemeStyles(); - const theme = useTheme(); const {translate, localeCompare} = useLocalize(); const [isDownloadFailureModalVisible, setIsDownloadFailureModalVisible] = useState(false); const [isDeleteTagsConfirmModalVisible, setIsDeleteTagsConfirmModalVisible] = useState(false); @@ -718,7 +717,6 @@ function WorkspaceTagsPage({route}: WorkspaceTagsPageProps) { )} {hasVisibleTags && !isLoading && ( diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index 05d7191bdede4..a91ba733ca828 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -1,6 +1,6 @@ import {useIsFocused} from '@react-navigation/native'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types'; import ConfirmModal from '@components/ConfirmModal'; @@ -24,7 +24,6 @@ import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSearchBackPress from '@hooks/useSearchBackPress'; import useSearchResults from '@hooks/useSearchResults'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode'; import { @@ -52,6 +51,7 @@ import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import type {PolicyTag} from '@src/types/onyx'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; +import ActivityIndicator from '@components/ActivityIndicator'; import type {TagListItem} from './types'; type WorkspaceViewTagsProps = @@ -63,7 +63,6 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {shouldUseNarrowLayout, isSmallScreenWidth} = useResponsiveLayout(); const styles = useThemeStyles(); - const theme = useTheme(); const {translate, localeCompare} = useLocalize(); const dropdownButtonRef = useRef(null); const [isDeleteTagsConfirmModalVisible, setIsDeleteTagsConfirmModalVisible] = useState(false); @@ -402,7 +401,6 @@ function WorkspaceViewTagsPage({route}: WorkspaceViewTagsProps) { )} {tagList.length > 0 && !isLoading && ( diff --git a/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx b/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx index 7e9d0d3d1ada2..8a5b138bec756 100644 --- a/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx +++ b/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx @@ -1,5 +1,5 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import {ActivityIndicator, InteractionManager, View} from 'react-native'; +import {InteractionManager, View} from 'react-native'; import Button from '@components/Button'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import type {DropdownOption, WorkspaceTaxRatesBulkActionType} from '@components/ButtonWithDropdownMenu/types'; @@ -24,7 +24,6 @@ import useOnyx from '@hooks/useOnyx'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useSearchBackPress from '@hooks/useSearchBackPress'; import useSearchResults from '@hooks/useSearchResults'; -import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {isConnectionInProgress, isConnectionUnverified} from '@libs/actions/connections'; import {turnOffMobileSelectionMode} from '@libs/actions/MobileSelectionMode'; @@ -51,6 +50,7 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {TaxRate} from '@src/types/onyx'; +import ActivityIndicator from '@components/ActivityIndicator'; type WorkspaceTaxesPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps; @@ -63,7 +63,6 @@ function WorkspaceTaxesPage({ // eslint-disable-next-line rulesdir/prefer-shouldUseNarrowLayout-instead-of-isSmallScreenWidth const {shouldUseNarrowLayout, isSmallScreenWidth} = useResponsiveLayout(); const styles = useThemeStyles(); - const theme = useTheme(); const {translate, localeCompare} = useLocalize(); const [selectedTaxesIDs, setSelectedTaxesIDs] = useState([]); const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false); @@ -415,7 +414,6 @@ function WorkspaceTaxesPage({ )} ; function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) { const {translate, localeCompare} = useLocalize(); - const theme = useTheme(); const styles = useThemeStyles(); // We need to use isSmallScreenWidth instead of shouldUseNarrowLayout to apply a correct padding style @@ -249,7 +248,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) { !isOffline && policy?.isLoadingWorkspaceReimbursement === true ? ( ) : ( @@ -322,7 +320,6 @@ function WorkspaceWorkflowsPage({policy, route}: WorkspaceWorkflowsPageProps) { approvalWorkflows, addApprovalAction, isOffline, - theme.spinner, isPolicyAdmin, displayNameForAuthorizedPayer, route.params.policyID, From 983057d5b072aa91a4f97d3a7e0ab3308f2837c6 Mon Sep 17 00:00:00 2001 From: Mateusz Rajski Date: Thu, 18 Sep 2025 12:59:02 +0200 Subject: [PATCH 4/8] Add eslint rule to prevent usage of ActivityIndicator from react-native --- .eslintrc.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 7a2e225820c6b..0d3ef2179f305 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -13,6 +13,7 @@ const restrictedImportPaths = [ 'Pressable', 'Text', 'ScrollView', + 'ActivityIndicator', 'Animated', 'findNodeHandle', ], @@ -23,6 +24,7 @@ const restrictedImportPaths = [ "For 'StatusBar', please use '@libs/StatusBar' instead.", "For 'Text', please use '@components/Text' instead.", "For 'ScrollView', please use '@components/ScrollView' instead.", + "For 'ActivityIndicator', please use '@components/ActivityIndicator' instead.", "For 'Animated', please use 'Animated' from 'react-native-reanimated' instead.", ].join('\n'), }, From bda0a35a45339656c4cba79d3b3479372bdeea87 Mon Sep 17 00:00:00 2001 From: Mateusz Rajski Date: Thu, 18 Sep 2025 13:15:30 +0200 Subject: [PATCH 5/8] Remove default value from props --- src/components/AddressSearch/index.tsx | 2 +- .../AttachmentView/DefaultAttachmentView/index.tsx | 1 - src/components/HeaderWithBackButton/index.tsx | 5 +---- src/components/MenuItem.tsx | 5 +---- src/components/ReportActionItem/MoneyReportView.tsx | 1 - .../BaseTextInput/implementation/index.native.tsx | 3 +-- .../TextInput/BaseTextInput/implementation/index.tsx | 4 ++-- .../TransactionItemRow/ReceiptPreview/index.tsx | 6 ++---- .../NonUSD/BankInfo/subSteps/BankAccountDetails.tsx | 2 +- .../NonUSD/BankInfo/subSteps/Confirmation.tsx | 2 +- src/pages/home/report/ListBoundaryLoader.tsx | 6 ++---- src/pages/iou/request/step/IOURequestStepCategory.tsx | 2 +- src/pages/iou/request/step/IOURequestStepDestination.tsx | 2 +- .../iou/request/step/IOURequestStepScan/index.native.tsx | 2 +- src/pages/iou/request/step/IOURequestStepScan/index.tsx | 2 +- .../settings/Security/TwoFactorAuth/CopyCodesPage.tsx | 4 ++-- src/pages/settings/Wallet/WalletPage/WalletPage.tsx | 2 +- src/pages/signin/ThirdPartySignInPage.tsx | 7 +++++-- src/pages/workspace/accounting/PolicyAccountingPage.tsx | 6 ++---- .../accounting/qbd/QuickBooksDesktopSetupPage.tsx | 6 ++---- .../workspace/categories/WorkspaceCategoriesPage.tsx | 2 +- .../companyCards/BankConnection/index.native.tsx | 2 +- src/pages/workspace/companyCards/BankConnection/index.tsx | 2 +- .../companyCards/WorkspaceCompanyCardDetailsPage.tsx | 8 ++------ .../workspace/companyCards/WorkspaceCompanyCardsPage.tsx | 2 +- .../workspace/companyCards/addNew/PlaidConnectionStep.tsx | 6 ++---- .../workspace/distanceRates/PolicyDistanceRatesPage.tsx | 2 +- .../expensifyCard/WorkspaceExpensifyCardPage.tsx | 2 +- src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx | 2 +- .../receiptPartners/WorkspaceReceiptPartnersPage.tsx | 2 +- src/pages/workspace/reports/WorkspaceReportsPage.tsx | 2 +- src/pages/workspace/tags/WorkspaceTagsPage.tsx | 2 +- src/pages/workspace/tags/WorkspaceViewTagsPage.tsx | 2 +- src/pages/workspace/taxes/WorkspaceTaxesPage.tsx | 2 +- src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx | 2 +- 35 files changed, 45 insertions(+), 65 deletions(-) diff --git a/src/components/AddressSearch/index.tsx b/src/components/AddressSearch/index.tsx index a171e17a58a8c..4e0fe3d646f7b 100644 --- a/src/components/AddressSearch/index.tsx +++ b/src/components/AddressSearch/index.tsx @@ -340,7 +340,7 @@ function AddressSearch( const listLoader = useMemo( () => ( - + ), [styles.pv4], diff --git a/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx b/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx index 34f8da7959aa7..2639c618cbc89 100644 --- a/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx +++ b/src/components/Attachments/AttachmentView/DefaultAttachmentView/index.tsx @@ -62,7 +62,6 @@ function DefaultAttachmentView({fileName = '', shouldShowLoadingSpinnerIcon = fa diff --git a/src/components/HeaderWithBackButton/index.tsx b/src/components/HeaderWithBackButton/index.tsx index 8f0915ef3b847..2a1bf4220ee62 100755 --- a/src/components/HeaderWithBackButton/index.tsx +++ b/src/components/HeaderWithBackButton/index.tsx @@ -272,10 +272,7 @@ function HeaderWithBackButton({ ) : ( - + ))} {shouldShowPinButton && !!report && } diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index a6214f6ba0899..5c3b82410b9b2 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -778,10 +778,7 @@ function MenuItem({ additionalStyles={additionalIconStyles} /> ) : ( - + ))} {!!icon && iconType === CONST.ICON_TYPE_WORKSPACE && ( diff --git a/src/components/TextInput/BaseTextInput/implementation/index.native.tsx b/src/components/TextInput/BaseTextInput/implementation/index.native.tsx index 974d37ca748b4..7ee876bf55536 100644 --- a/src/components/TextInput/BaseTextInput/implementation/index.native.tsx +++ b/src/components/TextInput/BaseTextInput/implementation/index.native.tsx @@ -3,6 +3,7 @@ import React, {useCallback, useEffect, useRef, useState} from 'react'; import type {GestureResponderEvent, LayoutChangeEvent, NativeSyntheticEvent, StyleProp, TextInput, TextInputFocusEventData, ViewStyle} from 'react-native'; import {StyleSheet, View} from 'react-native'; import {Easing, useSharedValue, withTiming} from 'react-native-reanimated'; +import ActivityIndicator from '@components/ActivityIndicator'; import Checkbox from '@components/Checkbox'; import FormHelpMessage from '@components/FormHelpMessage'; import Icon from '@components/Icon'; @@ -27,7 +28,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import isInputAutoFilled from '@libs/isInputAutoFilled'; import variables from '@styles/variables'; import CONST from '@src/CONST'; -import ActivityIndicator from '@components/ActivityIndicator'; function BaseTextInput({ label = '', @@ -442,7 +442,6 @@ function BaseTextInput({ )} {inputProps.isLoading !== undefined && !shouldShowClearButton && ( {isLoading && ( - + )} diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx index d607265bdf086..cf2bc5a1465c3 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/BankAccountDetails.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import AddressSearch from '@components/AddressSearch'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; @@ -17,7 +18,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {ReimbursementAccountForm} from '@src/types/form'; import type {CorpayFormField} from '@src/types/onyx'; -import ActivityIndicator from '@components/ActivityIndicator'; function getInputComponent(field: CorpayFormField) { if (CONST.CORPAY_FIELDS.SPECIAL_LIST_ADDRESS_KEYS.includes(field.id)) { diff --git a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx index 84e8efbe0ad66..6ba0c18dae44b 100644 --- a/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx +++ b/src/pages/ReimbursementAccount/NonUSD/BankInfo/subSteps/Confirmation.tsx @@ -1,5 +1,6 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import FormProvider from '@components/Form/FormProvider'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import Text from '@components/Text'; @@ -12,7 +13,6 @@ import getInputKeysForBankInfoStep from '@pages/ReimbursementAccount/NonUSD/util import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/ReimbursementAccountForm'; -import ActivityIndicator from '@components/ActivityIndicator'; const {ACCOUNT_HOLDER_COUNTRY} = INPUT_IDS.ADDITIONAL_DATA.CORPAY; function Confirmation({onNext, onMove, corpayFields}: BankInfoSubStepProps) { diff --git a/src/pages/home/report/ListBoundaryLoader.tsx b/src/pages/home/report/ListBoundaryLoader.tsx index df6e2135d845b..38fd2446fcb16 100644 --- a/src/pages/home/report/ListBoundaryLoader.tsx +++ b/src/pages/home/report/ListBoundaryLoader.tsx @@ -1,6 +1,7 @@ import React, {useEffect} from 'react'; import {View} from 'react-native'; import type {ValueOf} from 'type-fest'; +import ActivityIndicator from '@components/ActivityIndicator'; import Button from '@components/Button'; import ReportActionsSkeletonView from '@components/ReportActionsSkeletonView'; import Text from '@components/Text'; @@ -8,7 +9,6 @@ import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import CONST from '@src/CONST'; -import ActivityIndicator from '@components/ActivityIndicator'; type ListBoundaryLoaderProps = { /** type of rendered loader. Can be 'header' or 'footer' */ @@ -100,9 +100,7 @@ function ListBoundaryLoader({ // the styles for android and the rest components are different that's why we use two different components return ( - + ); } diff --git a/src/pages/iou/request/step/IOURequestStepCategory.tsx b/src/pages/iou/request/step/IOURequestStepCategory.tsx index b15d3c4a3b345..b81ea9921aa29 100644 --- a/src/pages/iou/request/step/IOURequestStepCategory.tsx +++ b/src/pages/iou/request/step/IOURequestStepCategory.tsx @@ -1,6 +1,7 @@ import lodashIsEmpty from 'lodash/isEmpty'; import React, {useEffect} from 'react'; import {InteractionManager, View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import Button from '@components/Button'; import CategoryPicker from '@components/CategoryPicker'; @@ -27,7 +28,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import ActivityIndicator from '@components/ActivityIndicator'; import StepScreenWrapper from './StepScreenWrapper'; import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; diff --git a/src/pages/iou/request/step/IOURequestStepDestination.tsx b/src/pages/iou/request/step/IOURequestStepDestination.tsx index b8e7529365814..e294101a40b3e 100644 --- a/src/pages/iou/request/step/IOURequestStepDestination.tsx +++ b/src/pages/iou/request/step/IOURequestStepDestination.tsx @@ -1,5 +1,6 @@ import React from 'react'; import {InteractionManager, View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import Button from '@components/Button'; import DestinationPicker from '@components/DestinationPicker'; @@ -33,7 +34,6 @@ import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; -import ActivityIndicator from '@components/ActivityIndicator'; import StepScreenWrapper from './StepScreenWrapper'; import type {WithFullTransactionOrNotFoundProps} from './withFullTransactionOrNotFound'; import withFullTransactionOrNotFound from './withFullTransactionOrNotFound'; diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx index 4efe06d3e4e5a..d1140770c6183 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.native.tsx @@ -13,6 +13,7 @@ import MultiScan from '@assets/images/educational-illustration__multi-scan.svg'; import TestReceipt from '@assets/images/fake-receipt.png'; import Hand from '@assets/images/hand.svg'; import Shutter from '@assets/images/shutter.svg'; +import ActivityIndicator from '@components/ActivityIndicator'; import AttachmentPicker from '@components/AttachmentPicker'; import Button from '@components/Button'; import FeatureTrainingModal from '@components/FeatureTrainingModal'; @@ -74,7 +75,6 @@ import type {Participant} from '@src/types/onyx/IOU'; import type Transaction from '@src/types/onyx/Transaction'; import type {Receipt} from '@src/types/onyx/Transaction'; import {getEmptyObject} from '@src/types/utils/EmptyObject'; -import ActivityIndicator from '@components/ActivityIndicator'; import CameraPermission from './CameraPermission'; import {cropImageToAspectRatio} from './cropImageToAspectRatio'; import type {ImageObject} from './cropImageToAspectRatio'; diff --git a/src/pages/iou/request/step/IOURequestStepScan/index.tsx b/src/pages/iou/request/step/IOURequestStepScan/index.tsx index 3ade2e357633b..0cb6e82ec7cfe 100644 --- a/src/pages/iou/request/step/IOURequestStepScan/index.tsx +++ b/src/pages/iou/request/step/IOURequestStepScan/index.tsx @@ -11,6 +11,7 @@ import TestReceipt from '@assets/images/fake-receipt.png'; import Hand from '@assets/images/hand.svg'; import ReceiptUpload from '@assets/images/receipt-upload.svg'; import Shutter from '@assets/images/shutter.svg'; +import ActivityIndicator from '@components/ActivityIndicator'; import AttachmentPicker from '@components/AttachmentPicker'; import Button from '@components/Button'; import CopyTextToClipboard from '@components/CopyTextToClipboard'; @@ -76,7 +77,6 @@ import type {Participant} from '@src/types/onyx/IOU'; import type Transaction from '@src/types/onyx/Transaction'; import type {Receipt} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import ActivityIndicator from '@components/ActivityIndicator'; import {cropImageToAspectRatio} from './cropImageToAspectRatio'; import type {ImageObject} from './cropImageToAspectRatio'; import {getLocationPermission} from './LocationPermission'; diff --git a/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx b/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx index f4f15b692f3d4..22c1f722abd13 100644 --- a/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/CopyCodesPage.tsx @@ -1,5 +1,6 @@ import React, {useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import Button from '@components/Button'; import FixedFooter from '@components/FixedFooter'; import FormHelpMessage from '@components/FormHelpMessage'; @@ -28,7 +29,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; -import ActivityIndicator from '@components/ActivityIndicator'; import type {TwoFactorAuthPageProps} from './TwoFactorAuthPage'; import TwoFactorAuthWrapper from './TwoFactorAuthWrapper'; @@ -91,7 +91,7 @@ function CopyCodesPage({route}: TwoFactorAuthPageProps) { {account?.isLoading ? ( - + ) : ( <> diff --git a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx index d170e113984dc..a2231a5b4335e 100644 --- a/src/pages/settings/Wallet/WalletPage/WalletPage.tsx +++ b/src/pages/settings/Wallet/WalletPage/WalletPage.tsx @@ -4,6 +4,7 @@ import type {ForwardedRef, RefObject} from 'react'; import React, {useCallback, useContext, useEffect, useLayoutEffect, useRef, useState} from 'react'; import type {GestureResponderEvent} from 'react-native'; import {View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import AddPaymentMethodMenu from '@components/AddPaymentMethodMenu'; import ConfirmModal from '@components/ConfirmModal'; import {DelegateNoAccessContext} from '@components/DelegateNoAccessModalProvider'; @@ -51,7 +52,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type * as OnyxTypes from '@src/types/onyx'; import {getEmptyObject} from '@src/types/utils/EmptyObject'; -import ActivityIndicator from '@components/ActivityIndicator'; type WalletPageProps = { /** Listen for window resize event on web and desktop. */ diff --git a/src/pages/signin/ThirdPartySignInPage.tsx b/src/pages/signin/ThirdPartySignInPage.tsx index 471c1028eedd9..501da28995916 100644 --- a/src/pages/signin/ThirdPartySignInPage.tsx +++ b/src/pages/signin/ThirdPartySignInPage.tsx @@ -2,6 +2,7 @@ import React from 'react'; import {View} from 'react-native'; import {SafeAreaView} from 'react-native-safe-area-context'; import type {ValueOf} from 'type-fest'; +import ActivityIndicator from '@components/ActivityIndicator'; import AppleSignIn from '@components/SignInButtons/AppleSignIn'; import GoogleSignIn from '@components/SignInButtons/GoogleSignIn'; import Text from '@components/Text'; @@ -13,7 +14,6 @@ import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; -import ActivityIndicator from '@components/ActivityIndicator'; import SignInPageLayout from './SignInPageLayout'; type ThirdPartySignInPageProps = { @@ -37,7 +37,10 @@ function ThirdPartySignInPage({signInProvider}: ThirdPartySignInPageProps) { {account?.isLoading ? ( - + ) : ( + ) : ( ; @@ -114,9 +114,7 @@ function RequireQuickBooksDesktopModal({route}: RequireQuickBooksDesktopModalPro {translate('workspace.qbd.setupPage.body')} {!hasResultOfFetchingSetupLink ? ( - + ) : ( ; @@ -177,11 +177,7 @@ function WorkspaceCompanyCardDetailsPage({route}: WorkspaceCompanyCardDetailsPag ) : null} - } + rightComponent={} description={translate('workspace.moreFeatures.companyCards.lastUpdated')} title={card?.isLoadingLastUpdated ? translate('workspace.moreFeatures.companyCards.updating') : lastScrape} interactive={false} diff --git a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx index 3cd4bd7c8be32..d8beedb6f36c9 100644 --- a/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx +++ b/src/pages/workspace/companyCards/WorkspaceCompanyCardsPage.tsx @@ -1,4 +1,5 @@ import React, {useCallback, useContext, useEffect, useState} from 'react'; +import ActivityIndicator from '@components/ActivityIndicator'; import DecisionModal from '@components/DecisionModal'; import {DelegateNoAccessContext} from '@components/DelegateNoAccessModalProvider'; import * as Illustrations from '@components/Icon/Illustrations'; @@ -37,7 +38,6 @@ import type SCREENS from '@src/SCREENS'; import type {CurrencyList} from '@src/types/onyx'; import type {AssignCardData, AssignCardStep} from '@src/types/onyx/AssignCard'; import {getEmptyObject, isEmptyObject} from '@src/types/utils/EmptyObject'; -import ActivityIndicator from '@components/ActivityIndicator'; import WorkspaceCompanyCardPageEmptyState from './WorkspaceCompanyCardPageEmptyState'; import WorkspaceCompanyCardsFeedPendingPage from './WorkspaceCompanyCardsFeedPendingPage'; import WorkspaceCompanyCardsList from './WorkspaceCompanyCardsList'; diff --git a/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx b/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx index 91912857b3c95..23b29a4b76bc5 100644 --- a/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx +++ b/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx @@ -2,6 +2,7 @@ import React, {useCallback, useEffect, useRef} from 'react'; import {InteractionManager, View} from 'react-native'; import type {LinkSuccessMetadata} from 'react-native-plaid-link-sdk'; import type {PlaidLinkOnSuccessMetadata} from 'react-plaid-link/src/types'; +import ActivityIndicator from '@components/ActivityIndicator'; import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import PlaidLink from '@components/PlaidLink'; @@ -23,7 +24,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {CompanyCardFeed} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import ActivityIndicator from '@components/ActivityIndicator'; function PlaidConnectionStep({feed, policyID}: {feed?: CompanyCardFeed; policyID?: string}) { const {translate} = useLocalize(); @@ -188,9 +188,7 @@ function PlaidConnectionStep({feed, policyID}: {feed?: CompanyCardFeed; policyID if (plaidData?.isLoading) { return ( - + ); } diff --git a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx index af359c85dbe4a..da38da934c4ff 100644 --- a/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx +++ b/src/pages/workspace/distanceRates/PolicyDistanceRatesPage.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {InteractionManager, View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import Button from '@components/Button'; import type {DropdownOption, WorkspaceDistanceRatesBulkActionType} from '@components/ButtonWithDropdownMenu/types'; import ConfirmModal from '@components/ConfirmModal'; @@ -47,7 +48,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {Rate} from '@src/types/onyx/Policy'; -import ActivityIndicator from '@components/ActivityIndicator'; type RateForList = ListItem & {value: string; rate?: number}; diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPage.tsx index 469619ba3a17e..a9f1b3b53a70e 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardPage.tsx @@ -1,4 +1,5 @@ import React, {useCallback, useEffect} from 'react'; +import ActivityIndicator from '@components/ActivityIndicator'; import useDefaultFundID from '@hooks/useDefaultFundID'; import useNetwork from '@hooks/useNetwork'; import useOnyx from '@hooks/useOnyx'; @@ -11,7 +12,6 @@ import {openPolicyExpensifyCardsPage} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type SCREENS from '@src/SCREENS'; -import ActivityIndicator from '@components/ActivityIndicator'; import WorkspaceExpensifyCardListPage from './WorkspaceExpensifyCardListPage'; import WorkspaceExpensifyCardPageEmptyState from './WorkspaceExpensifyCardPageEmptyState'; diff --git a/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx b/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx index 6e38dbfbaec9a..30669300fdab5 100644 --- a/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx +++ b/src/pages/workspace/perDiem/WorkspacePerDiemPage.tsx @@ -1,6 +1,7 @@ import {useFocusEffect} from '@react-navigation/native'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {InteractionManager, View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types'; import ConfirmModal from '@components/ConfirmModal'; @@ -49,7 +50,6 @@ import type SCREENS from '@src/SCREENS'; import type {PendingAction} from '@src/types/onyx/OnyxCommon'; import type {Rate} from '@src/types/onyx/Policy'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; -import ActivityIndicator from '@components/ActivityIndicator'; type PolicyOption = ListItem & { /** subRateID is used as a key for identification of the entry */ diff --git a/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx b/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx index 9edeac7696e2a..5e1d65155cb9a 100644 --- a/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx +++ b/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import Button from '@components/Button'; import ConfirmModal from '@components/ConfirmModal'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -29,7 +30,6 @@ import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {AnchorPosition} from '@src/styles'; -import ActivityIndicator from '@components/ActivityIndicator'; import {getReceiptPartnersIntegrationData} from './utils'; type WorkspaceReceiptPartnersPageProps = PlatformStackScreenProps; diff --git a/src/pages/workspace/reports/WorkspaceReportsPage.tsx b/src/pages/workspace/reports/WorkspaceReportsPage.tsx index af54001a3a934..c12c79d706f22 100644 --- a/src/pages/workspace/reports/WorkspaceReportsPage.tsx +++ b/src/pages/workspace/reports/WorkspaceReportsPage.tsx @@ -3,6 +3,7 @@ import type {ListRenderItemInfo} from '@shopify/flash-list'; import {Str} from 'expensify-common'; import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import ConfirmModal from '@components/ConfirmModal'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import {Plus} from '@components/Icon/Expensicons'; @@ -39,7 +40,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -import ActivityIndicator from '@components/ActivityIndicator'; type ReportFieldForList = ListItem & { fieldID: string; diff --git a/src/pages/workspace/tags/WorkspaceTagsPage.tsx b/src/pages/workspace/tags/WorkspaceTagsPage.tsx index 035c494fff86c..2190c300c5ce1 100644 --- a/src/pages/workspace/tags/WorkspaceTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceTagsPage.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {InteractionManager, View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import Button from '@components/Button'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types'; @@ -71,7 +72,6 @@ import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import type {PendingAction} from '@src/types/onyx/OnyxCommon'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; -import ActivityIndicator from '@components/ActivityIndicator'; import type {PolicyTag, PolicyTagList, TagListItem} from './types'; type WorkspaceTagsPageProps = diff --git a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx index a91ba733ca828..017b625071918 100644 --- a/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx +++ b/src/pages/workspace/tags/WorkspaceViewTagsPage.tsx @@ -1,6 +1,7 @@ import {useIsFocused} from '@react-navigation/native'; import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {InteractionManager, View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import type {DropdownOption} from '@components/ButtonWithDropdownMenu/types'; import ConfirmModal from '@components/ConfirmModal'; @@ -51,7 +52,6 @@ import ROUTES from '@src/ROUTES'; import SCREENS from '@src/SCREENS'; import type {PolicyTag} from '@src/types/onyx'; import type DeepValueOf from '@src/types/utils/DeepValueOf'; -import ActivityIndicator from '@components/ActivityIndicator'; import type {TagListItem} from './types'; type WorkspaceViewTagsProps = diff --git a/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx b/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx index 8a5b138bec756..5f7ebdf3dc59a 100644 --- a/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx +++ b/src/pages/workspace/taxes/WorkspaceTaxesPage.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {InteractionManager, View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import Button from '@components/Button'; import ButtonWithDropdownMenu from '@components/ButtonWithDropdownMenu'; import type {DropdownOption, WorkspaceTaxRatesBulkActionType} from '@components/ButtonWithDropdownMenu/types'; @@ -50,7 +51,6 @@ import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; import type {TaxRate} from '@src/types/onyx'; -import ActivityIndicator from '@components/ActivityIndicator'; type WorkspaceTaxesPageProps = WithPolicyAndFullscreenLoadingProps & PlatformStackScreenProps; diff --git a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx index 630fbb4766656..4dbdbb88614fe 100644 --- a/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx +++ b/src/pages/workspace/workflows/WorkspaceWorkflowsPage.tsx @@ -1,6 +1,7 @@ import React, {useCallback, useContext, useEffect, useMemo, useState} from 'react'; import {InteractionManager, View} from 'react-native'; import type {TupleToUnion} from 'type-fest'; +import ActivityIndicator from '@components/ActivityIndicator'; import ApprovalWorkflowSection from '@components/ApprovalWorkflowSection'; import ConfirmModal from '@components/ConfirmModal'; import getBankIcon from '@components/Icon/BankIcons'; @@ -51,7 +52,6 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import ActivityIndicator from '@components/ActivityIndicator'; import type {ToggleSettingOptionRowProps} from './ToggleSettingsOptionRow'; import ToggleSettingOptionRow from './ToggleSettingsOptionRow'; import type {AutoReportingFrequencyKey} from './WorkspaceAutoReportingFrequencyPage'; From 20b14880b19fb0a17a43cf58c93d18250eca1484 Mon Sep 17 00:00:00 2001 From: Mateusz Rajski Date: Mon, 22 Sep 2025 14:09:05 +0200 Subject: [PATCH 6/8] Use CONST.ACTIVITY_INDICATOR_SIZE.LARGE --- src/components/AddPlaidBankAccount.tsx | 2 +- src/components/AvatarCropModal/AvatarCropModal.tsx | 2 +- src/components/FullscreenLoadingIndicator.tsx | 3 ++- src/components/Lightbox/index.tsx | 3 ++- src/components/PlaidLink/index.tsx | 3 ++- src/components/TransactionItemRow/ReceiptPreview/index.tsx | 2 +- src/pages/signin/ThirdPartySignInPage.tsx | 2 +- .../workspace/companyCards/addNew/PlaidConnectionStep.tsx | 2 +- 8 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/components/AddPlaidBankAccount.tsx b/src/components/AddPlaidBankAccount.tsx index 7d1d1a6c3ad1d..4c50576b5417a 100644 --- a/src/components/AddPlaidBankAccount.tsx +++ b/src/components/AddPlaidBankAccount.tsx @@ -229,7 +229,7 @@ function AddPlaidBankAccount({ if (plaidData?.isLoading) { return ( - + ); } diff --git a/src/components/AvatarCropModal/AvatarCropModal.tsx b/src/components/AvatarCropModal/AvatarCropModal.tsx index a4ec436bb2e0b..d7721debb3420 100644 --- a/src/components/AvatarCropModal/AvatarCropModal.tsx +++ b/src/components/AvatarCropModal/AvatarCropModal.tsx @@ -377,7 +377,7 @@ function AvatarCropModal({imageUri = '', imageName = '', imageType = '', onClose {!isImageInitialized || !isImageContainerInitialized ? ( ) : ( <> diff --git a/src/components/FullscreenLoadingIndicator.tsx b/src/components/FullscreenLoadingIndicator.tsx index 77e2c5407ef26..3f46d417c91e7 100644 --- a/src/components/FullscreenLoadingIndicator.tsx +++ b/src/components/FullscreenLoadingIndicator.tsx @@ -2,6 +2,7 @@ import React from 'react'; import type {ActivityIndicatorProps, StyleProp, ViewStyle} from 'react-native'; import {StyleSheet, View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; +import CONST from '@src/CONST'; import ActivityIndicator from './ActivityIndicator'; type FullScreenLoadingIndicatorIconSize = ActivityIndicatorProps['size']; @@ -12,7 +13,7 @@ type FullScreenLoadingIndicatorProps = { testID?: string; }; -function FullScreenLoadingIndicator({style, iconSize = 'large', testID = ''}: FullScreenLoadingIndicatorProps) { +function FullScreenLoadingIndicator({style, iconSize = CONST.ACTIVITY_INDICATOR_SIZE.LARGE, testID = ''}: FullScreenLoadingIndicatorProps) { const styles = useThemeStyles(); return ( diff --git a/src/components/Lightbox/index.tsx b/src/components/Lightbox/index.tsx index f67dfa0a3295b..bbcaf4043bece 100644 --- a/src/components/Lightbox/index.tsx +++ b/src/components/Lightbox/index.tsx @@ -14,6 +14,7 @@ import useNetwork from '@hooks/useNetwork'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import {isLocalFile} from '@libs/fileDownload/FileUtils'; +import CONST from '@src/CONST'; import NUMBER_OF_CONCURRENT_LIGHTBOXES from './numberOfConcurrentLightboxes'; const cachedImageDimensions = new Map(); @@ -270,7 +271,7 @@ function Lightbox({isAuthTokenRequired = false, uri, onScaleChanged: onScaleChan {/* Show activity indicator while the lightbox is still loading the image. */} {isLoading && (!isOffline || isALocalFile) && ( )} diff --git a/src/components/PlaidLink/index.tsx b/src/components/PlaidLink/index.tsx index 0a7c0596d4e52..a98650557f94a 100644 --- a/src/components/PlaidLink/index.tsx +++ b/src/components/PlaidLink/index.tsx @@ -5,6 +5,7 @@ import {usePlaidLink} from 'react-plaid-link'; import ActivityIndicator from '@components/ActivityIndicator'; import useThemeStyles from '@hooks/useThemeStyles'; import Log from '@libs/Log'; +import CONST from '@src/CONST'; import type PlaidLinkProps from './types'; function PlaidLink({token, onSuccess = () => {}, onError = () => {}, onExit = () => {}, onEvent, receivedRedirectURI}: PlaidLinkProps) { @@ -54,7 +55,7 @@ function PlaidLink({token, onSuccess = () => {}, onError = () => {}, onExit = () return ( - + ); } diff --git a/src/components/TransactionItemRow/ReceiptPreview/index.tsx b/src/components/TransactionItemRow/ReceiptPreview/index.tsx index e2da31ae40cb1..a1ef5c1d56343 100644 --- a/src/components/TransactionItemRow/ReceiptPreview/index.tsx +++ b/src/components/TransactionItemRow/ReceiptPreview/index.tsx @@ -108,7 +108,7 @@ function ReceiptPreview({source, hovered, isEReceipt = false, transactionItem}: {isLoading && ( - + )} diff --git a/src/pages/signin/ThirdPartySignInPage.tsx b/src/pages/signin/ThirdPartySignInPage.tsx index 501da28995916..a5935c028587d 100644 --- a/src/pages/signin/ThirdPartySignInPage.tsx +++ b/src/pages/signin/ThirdPartySignInPage.tsx @@ -38,7 +38,7 @@ function ThirdPartySignInPage({signInProvider}: ThirdPartySignInPageProps) { {account?.isLoading ? ( diff --git a/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx b/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx index 23b29a4b76bc5..33839e030d18c 100644 --- a/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx +++ b/src/pages/workspace/companyCards/addNew/PlaidConnectionStep.tsx @@ -188,7 +188,7 @@ function PlaidConnectionStep({feed, policyID}: {feed?: CompanyCardFeed; policyID if (plaidData?.isLoading) { return ( - + ); } From d764dcba724608feb1b1905c8f70ecf03ea0b8b8 Mon Sep 17 00:00:00 2001 From: Mateusz Rajski Date: Mon, 22 Sep 2025 16:27:24 +0200 Subject: [PATCH 7/8] Migrate new component to new ActivityIndicator --- .../SelectionList/Search/TransactionGroupListItem.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/SelectionList/Search/TransactionGroupListItem.tsx b/src/components/SelectionList/Search/TransactionGroupListItem.tsx index f09a9f5e73c4a..7d4dc68426083 100644 --- a/src/components/SelectionList/Search/TransactionGroupListItem.tsx +++ b/src/components/SelectionList/Search/TransactionGroupListItem.tsx @@ -1,5 +1,6 @@ import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {ActivityIndicator, View} from 'react-native'; +import {View} from 'react-native'; +import ActivityIndicator from '@components/ActivityIndicator'; import AnimatedCollapsible from '@components/AnimatedCollapsible'; import Button from '@components/Button'; import {getButtonRole} from '@components/Button/utils'; From da3f1d0e0102bfab568c2ad560ec027474fc851c Mon Sep 17 00:00:00 2001 From: Mateusz Rajski Date: Tue, 23 Sep 2025 11:07:48 +0200 Subject: [PATCH 8/8] Add JSDoc and remove TODO --- src/components/ActivityIndicator.tsx | 8 ++++---- src/components/FullscreenLoadingIndicator.tsx | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/ActivityIndicator.tsx b/src/components/ActivityIndicator.tsx index 25bc532b76900..1f0c2bea19240 100644 --- a/src/components/ActivityIndicator.tsx +++ b/src/components/ActivityIndicator.tsx @@ -1,4 +1,4 @@ -import {useEffect} from 'react'; +import React, {useEffect} from 'react'; import type {ActivityIndicatorProps as RNActivityIndicatorProps} from 'react-native'; // eslint-disable-next-line no-restricted-imports import {ActivityIndicator as RNActivityIndicator} from 'react-native'; @@ -7,7 +7,10 @@ import Log from '@libs/Log'; import CONST from '@src/CONST'; type ActivityIndicatorProps = RNActivityIndicatorProps & { + /** The ID of the test to be used for testing */ testID?: string; + + /** Timeout for the activity indicator after which we fire a log about abnormally long loading */ timeout?: number; }; @@ -18,9 +21,6 @@ function ActivityIndicator({timeout = CONST.TIMING.ACTIVITY_INDICATOR_TIMEOUT, . const timeoutId = setTimeout(() => { Log.warn('ActivityIndicator has been shown for longer than expected', { timeoutMs: timeout, - context: { - /** TODO: Add context */ - }, }); }, timeout); diff --git a/src/components/FullscreenLoadingIndicator.tsx b/src/components/FullscreenLoadingIndicator.tsx index 3f46d417c91e7..093e514c00fb3 100644 --- a/src/components/FullscreenLoadingIndicator.tsx +++ b/src/components/FullscreenLoadingIndicator.tsx @@ -8,8 +8,13 @@ import ActivityIndicator from './ActivityIndicator'; type FullScreenLoadingIndicatorIconSize = ActivityIndicatorProps['size']; type FullScreenLoadingIndicatorProps = { + /** Styles of the outer view */ style?: StyleProp; + + /** Size of the icon */ iconSize?: FullScreenLoadingIndicatorIconSize; + + /** The ID of the test to be used for testing */ testID?: string; };