From 3881c58088877a3b666e86468fa21181f416279e Mon Sep 17 00:00:00 2001 From: truph01 Date: Wed, 14 Jan 2026 17:58:06 +0700 Subject: [PATCH 01/22] fix: refactor modals --- .../settings/Security/CloseAccountPage.tsx | 51 +++-- .../Security/SecuritySettingsPage.tsx | 52 ++--- .../Subscription/CardSection/CardSection.tsx | 185 +++++++++--------- .../Troubleshoot/TroubleshootPage.tsx | 50 +++-- 4 files changed, 172 insertions(+), 166 deletions(-) diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index db99fe85ccba6..b1cea2e81b866 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -1,15 +1,16 @@ import {Str} from 'expensify-common'; -import React, {useEffect, useState} from 'react'; +import React, {useCallback, useEffect, useState} from 'react'; import {View} from 'react-native'; -import ConfirmModal from '@components/ConfirmModal'; import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import {ModalActions} from '@components/Modal/Global/ModalContext'; import ScreenWrapper from '@components/ScreenWrapper'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; +import useConfirmModal from '@hooks/useConfirmModal'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -32,27 +33,35 @@ function CloseAccountPage() { const styles = useThemeStyles(); const {translate, formatPhoneNumber} = useLocalize(); - const [isConfirmModalVisible, setConfirmModalVisibility] = useState(false); const [reasonForLeaving, setReasonForLeaving] = useState(''); + const {showConfirmModal} = useConfirmModal(); + const showCloseAccountWarningModal = useCallback(() => { + return showConfirmModal({ + title: translate('closeAccountPage.closeAccountWarning'), + prompt: translate('closeAccountPage.closeAccountPermanentlyDeleteData'), + confirmText: translate('common.yesContinue'), + cancelText: translate('common.cancel'), + shouldShowCancelButton: true, + danger: true, + shouldDisableConfirmButtonWhenOffline: true, + }); + }, [showConfirmModal, translate]); + // If you are new to hooks this might look weird but basically it is something that only runs when the component unmounts // nothing runs on mount and we pass empty dependencies to prevent this from running on every re-render. // TODO: We should refactor this so that the data in instead passed directly as a prop instead of "side loading" the data // here, we left this as is during refactor to limit the breaking changes. useEffect(() => () => clearError(), []); - const hideConfirmModal = () => { - setConfirmModalVisibility(false); - }; - - const onConfirm = () => { - closeAccount(reasonForLeaving); - hideConfirmModal(); - }; - - const showConfirmModal = (values: FormOnyxValues) => { - setConfirmModalVisibility(true); + const onSubmit = (values: FormOnyxValues) => { setReasonForLeaving(values.reasonForLeaving); + showCloseAccountWarningModal().then((result) => { + if (result.action !== ModalActions.CONFIRM) { + return; + } + closeAccount(reasonForLeaving); + }); }; const userEmailOrPhone = session?.email ? formatPhoneNumber(session.email) : null; @@ -105,7 +114,7 @@ function CloseAccountPage() { - diff --git a/src/pages/settings/Security/SecuritySettingsPage.tsx b/src/pages/settings/Security/SecuritySettingsPage.tsx index c90b07039067e..62b1821e3f317 100644 --- a/src/pages/settings/Security/SecuritySettingsPage.tsx +++ b/src/pages/settings/Security/SecuritySettingsPage.tsx @@ -3,7 +3,6 @@ import React, {useCallback, useContext, useEffect, useLayoutEffect, useMemo, use import type {RefObject} from 'react'; import {Dimensions, View} from 'react-native'; import type {GestureResponderEvent, StyleProp, ViewStyle} from 'react-native'; -import ConfirmModal from '@components/ConfirmModal'; import {DelegateNoAccessContext} from '@components/DelegateNoAccessModalProvider'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; // eslint-disable-next-line no-restricted-imports @@ -12,6 +11,7 @@ import {LockedAccountContext} from '@components/LockedAccountModalProvider'; import MenuItem from '@components/MenuItem'; import type {MenuItemProps} from '@components/MenuItem'; import MenuItemList from '@components/MenuItemList'; +import {ModalActions} from '@components/Modal/Global/ModalContext'; import {usePersonalDetails} from '@components/OnyxListItemProvider'; import PopoverMenu from '@components/PopoverMenu'; import type {PopoverMenuItem} from '@components/PopoverMenu'; @@ -20,6 +20,7 @@ import ScrollView from '@components/ScrollView'; import Section from '@components/Section'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; +import useConfirmModal from '@hooks/useConfirmModal'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; @@ -72,10 +73,21 @@ function SecuritySettingsPage() { const delegateButtonRef = useRef(null); const [shouldShowDelegatePopoverMenu, setShouldShowDelegatePopoverMenu] = useState(false); - const [shouldShowRemoveDelegateModal, setShouldShowRemoveDelegateModal] = useState(false); const [selectedDelegate, setSelectedDelegate] = useState(); const [selectedEmail, setSelectedEmail] = useState(); + const {showConfirmModal} = useConfirmModal(); + const showRemoveCopilotModal = useCallback(() => { + return showConfirmModal({ + title: translate('delegate.removeCopilot'), + prompt: translate('delegate.removeCopilotConfirmation'), + confirmText: translate('delegate.removeCopilot'), + cancelText: translate('common.cancel'), + shouldShowCancelButton: true, + danger: true, + }); + }, [showConfirmModal, translate]); + const errorFields = account?.delegatedAccess?.errorFields ?? {}; const [anchorPosition, setAnchorPosition] = useState({ @@ -329,7 +341,18 @@ function SecuritySettingsPage() { } modalClose(() => { setShouldShowDelegatePopoverMenu(false); - setShouldShowRemoveDelegateModal(true); + showRemoveCopilotModal().then((result) => { + if (result.action === ModalActions.CLOSE) { + setSelectedDelegate(undefined); + } else { + if (isActingAsDelegate) { + showDelegateNoAccessModal(); + return; + } + removeDelegate({email: selectedDelegate?.email ?? '', delegatedAccess: account?.delegatedAccess}); + setSelectedDelegate(undefined); + } + }); setSelectedEmail(undefined); }); }, @@ -446,29 +469,6 @@ function SecuritySettingsPage() { setSelectedEmail(undefined); }} /> - { - if (isActingAsDelegate) { - setShouldShowRemoveDelegateModal(false); - showDelegateNoAccessModal(); - return; - } - removeDelegate({email: selectedDelegate?.email ?? '', delegatedAccess: account?.delegatedAccess}); - setShouldShowRemoveDelegateModal(false); - setSelectedDelegate(undefined); - }} - onCancel={() => { - setShouldShowRemoveDelegateModal(false); - setSelectedDelegate(undefined); - }} - confirmText={translate('delegate.removeCopilot')} - cancelText={translate('common.cancel')} - shouldShowCancelButton - /> diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx index 34d9b55c84b4a..8ae427bff0bf6 100644 --- a/src/pages/settings/Subscription/CardSection/CardSection.tsx +++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx @@ -1,11 +1,12 @@ import React, {useCallback, useEffect, useMemo, useState} from 'react'; import {View} from 'react-native'; -import ConfirmModal from '@components/ConfirmModal'; import Icon from '@components/Icon'; import MenuItem from '@components/MenuItem'; +import {ModalActions} from '@components/Modal/Global/ModalContext'; import RenderHTML from '@components/RenderHTML'; import Section from '@components/Section'; import Text from '@components/Text'; +import useConfirmModal from '@hooks/useConfirmModal'; import useHasTeam2025Pricing from '@hooks/useHasTeam2025Pricing'; import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; @@ -41,7 +42,6 @@ import type {BillingStatusResult} from './utils'; import CardSectionUtils from './utils'; function CardSection() { - const [isRequestRefundModalVisible, setIsRequestRefundModalVisible] = useState(false); const {translate} = useLocalize(); const styles = useThemeStyles(); const theme = useTheme(); @@ -74,10 +74,20 @@ function CardSection() { const [billingStatusOnyx] = useOnyx(ONYXKEYS.NVP_PRIVATE_BILLING_STATUS, {canBeMissing: true}); const requestRefund = useCallback(() => { requestRefundByUser(); - setIsRequestRefundModalVisible(false); Navigation.goBackToHome(); }, []); + const {showConfirmModal} = useConfirmModal(); + const showRequestRefundModal = useCallback(() => { + return showConfirmModal({ + title: translate('subscription.cardSection.requestRefund'), + prompt: , + confirmText: translate('subscription.cardSection.requestRefundModal.confirm'), + cancelText: translate('common.cancel'), + shouldShowCancelButton: true, + }); + }, [showConfirmModal, translate]); + const viewPurchases = useCallback(() => { const query = buildQueryStringFromFilterFormValues({ type: CONST.SEARCH.DATA_TYPES.EXPENSE, @@ -185,105 +195,92 @@ function CardSection() { } return ( - <> -
- - {!isEmptyObject(defaultCard?.accountData) && ( - - - - {getPaymentMethodDescription(defaultCard?.accountType, defaultCard?.accountData, translate)} - - {translate( - 'subscription.cardSection.cardInfo', - defaultCard?.accountData?.addressName ?? '', - `${cardMonth} ${defaultCard?.accountData?.cardYear}`, - defaultCard?.accountData?.currency ?? '', - )} - - - +
+ + {!isEmptyObject(defaultCard?.accountData) && ( + + + + {getPaymentMethodDescription(defaultCard?.accountType, defaultCard?.accountData, translate)} + + {translate( + 'subscription.cardSection.cardInfo', + defaultCard?.accountData?.addressName ?? '', + `${cardMonth} ${defaultCard?.accountData?.cardYear}`, + defaultCard?.accountData?.currency ?? '', + )} + - )} - - - {isEmptyObject(defaultCard?.accountData) && } - {billingStatus?.isRetryAvailable !== undefined && ( - - )} - {hasCardAuthenticatedError(privateStripeCustomerID) && ( - + + )} + - {!!account?.hasPurchases && ( - - )} - - {!!(subscriptionPlan && account?.isEligibleForRefund) && ( - setIsRequestRefundModalVisible(true)} - /> - )} + {isEmptyObject(defaultCard?.accountData) && } + {billingStatus?.isRetryAvailable !== undefined && ( + + )} + {hasCardAuthenticatedError(privateStripeCustomerID) && ( + + )} - {!!(privateSubscription?.type === CONST.SUBSCRIPTION.TYPE.ANNUAL && account?.hasPurchases) && } -
+ {!!account?.hasPurchases && ( + + )} - {!!account?.isEligibleForRefund && ( - setIsRequestRefundModalVisible(false)} - prompt={ - - - - } - confirmText={translate('subscription.cardSection.requestRefundModal.confirm')} - cancelText={translate('common.cancel')} - danger + titleStyle={styles.textStrong} + disabled={isOffline} + onPress={async () => { + const result = await showRequestRefundModal(); + if (result.action !== ModalActions.CONFIRM) { + return; + } + requestRefund(); + }} /> )} - + + {!!(privateSubscription?.type === CONST.SUBSCRIPTION.TYPE.ANNUAL && account?.hasPurchases) && } +
); } diff --git a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx index c6ddcea9e2db3..40fe23df47cf6 100644 --- a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx +++ b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx @@ -1,11 +1,11 @@ import {differenceInDays} from 'date-fns'; import React, {useCallback, useMemo, useState} from 'react'; import {View} from 'react-native'; -import ConfirmModal from '@components/ConfirmModal'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ImportOnyxState from '@components/ImportOnyxState'; import MenuItemList from '@components/MenuItemList'; +import {ModalActions} from '@components/Modal/Global/ModalContext'; import {useOptionsList} from '@components/OptionListContextProvider'; import RecordTroubleshootDataToolMenu from '@components/RecordTroubleshootDataToolMenu'; import RenderHTML from '@components/RenderHTML'; @@ -17,6 +17,7 @@ import SentryDebugToolMenu from '@components/SentryDebugToolMenu'; import Switch from '@components/Switch'; import TestToolMenu from '@components/TestToolMenu'; import TestToolRow from '@components/TestToolRow'; +import useConfirmModal from '@hooks/useConfirmModal'; import useEnvironment from '@hooks/useEnvironment'; import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; @@ -53,7 +54,6 @@ function TroubleshootPage() { const {translate} = useLocalize(); const styles = useThemeStyles(); const {isProduction, isDevelopment} = useEnvironment(); - const [isConfirmationModalVisible, setIsConfirmationModalVisible] = useState(false); const waitForNavigate = useWaitForNavigation(); const {shouldUseNarrowLayout} = useResponsiveLayout(); const [isLoading, setIsLoading] = useState(false); @@ -61,8 +61,24 @@ function TroubleshootPage() { const [shouldMaskOnyxState = true] = useOnyx(ONYXKEYS.SHOULD_MASK_ONYX_STATE, {canBeMissing: true}); const {resetOptions} = useOptionsList({shouldInitialize: false}); const [tryNewDot] = useOnyx(ONYXKEYS.NVP_TRY_NEW_DOT, {canBeMissing: true}); + const {showConfirmModal} = useConfirmModal(); const shouldOpenSurveyReasonPage = tryNewDot?.classicRedirect?.dismissed === false; const {setShouldResetSearchQuery} = useSearchContext(); + const showResetAndRefreshModal = useCallback(async () => { + const result = await showConfirmModal({ + title: translate('common.areYouSure'), + prompt: translate('initialSettingsPage.troubleshoot.confirmResetDescription'), + confirmText: translate('initialSettingsPage.troubleshoot.resetAndRefresh'), + cancelText: translate('common.cancel'), + shouldShowCancelButton: true, + }); + if (result.action !== ModalActions.CONFIRM) { + return; + } + resetOptions(); + setShouldResetSearchQuery(true); + clearOnyxAndResetApp(); + }, [showConfirmModal, translate, resetOptions, setShouldResetSearchQuery]); const exportOnyxState = useCallback(() => { ExportOnyxState.readFromOnyxDatabase().then((value: Record) => { const dataToShare = ExportOnyxState.maskOnyxState(value, shouldMaskOnyxState); @@ -137,7 +153,7 @@ function TroubleshootPage() { { translationKey: 'initialSettingsPage.troubleshoot.clearCacheAndRestart', icon: icons.RotateLeft, - action: () => setIsConfirmationModalVisible(true), + action: showResetAndRefreshModal, }, { translationKey: 'initialSettingsPage.troubleshoot.exportOnyxState', @@ -161,7 +177,18 @@ function TroubleshootPage() { wrapperStyle: [styles.sectionMenuItemTopDescription], })) .reverse(); - }, [icons.Bug, icons.RotateLeft, icons.Download, waitForNavigate, exportOnyxState, shouldStoreLogs, classicRedirectMenuItem, translate, styles.sectionMenuItemTopDescription]); + }, [ + icons.Bug, + icons.RotateLeft, + icons.Download, + waitForNavigate, + exportOnyxState, + shouldStoreLogs, + classicRedirectMenuItem, + translate, + styles.sectionMenuItemTopDescription, + showResetAndRefreshModal, + ]); return ( )} - - { - setIsConfirmationModalVisible(false); - resetOptions(); - setShouldResetSearchQuery(true); - clearOnyxAndResetApp(); - }} - onCancel={() => setIsConfirmationModalVisible(false)} - prompt={translate('initialSettingsPage.troubleshoot.confirmResetDescription')} - confirmText={translate('initialSettingsPage.troubleshoot.resetAndRefresh')} - cancelText={translate('common.cancel')} - /> From 750397e3fc10af26418f09b9f76f7bcb2460c10b Mon Sep 17 00:00:00 2001 From: truph01 Date: Thu, 15 Jan 2026 17:34:10 +0700 Subject: [PATCH 02/22] fix: use async await --- .../settings/Security/CloseAccountPage.tsx | 13 +++++----- .../Security/SecuritySettingsPage.tsx | 25 +++++++++---------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index 6dccd91178d2d..755c22ed44e67 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -54,14 +54,13 @@ function CloseAccountPage() { // here, we left this as is during refactor to limit the breaking changes. useEffect(() => () => clearError(), []); - const onSubmit = (values: FormOnyxValues) => { + const onSubmit = async (values: FormOnyxValues) => { setReasonForLeaving(values.reasonForLeaving); - showCloseAccountWarningModal().then((result) => { - if (result.action !== ModalActions.CONFIRM) { - return; - } - closeAccount(reasonForLeaving); - }); + const result = await showCloseAccountWarningModal(); + if (result.action !== ModalActions.CONFIRM) { + return; + } + closeAccount(reasonForLeaving); }; const userEmailOrPhone = session?.email ? formatPhoneNumber(session.email) : null; diff --git a/src/pages/settings/Security/SecuritySettingsPage.tsx b/src/pages/settings/Security/SecuritySettingsPage.tsx index 62b1821e3f317..efb430f3b6fdc 100644 --- a/src/pages/settings/Security/SecuritySettingsPage.tsx +++ b/src/pages/settings/Security/SecuritySettingsPage.tsx @@ -339,21 +339,20 @@ function SecuritySettingsPage() { modalClose(() => showLockedAccountModal()); return; } - modalClose(() => { + modalClose(async () => { setShouldShowDelegatePopoverMenu(false); - showRemoveCopilotModal().then((result) => { - if (result.action === ModalActions.CLOSE) { - setSelectedDelegate(undefined); - } else { - if (isActingAsDelegate) { - showDelegateNoAccessModal(); - return; - } - removeDelegate({email: selectedDelegate?.email ?? '', delegatedAccess: account?.delegatedAccess}); - setSelectedDelegate(undefined); - } - }); setSelectedEmail(undefined); + const result = await showRemoveCopilotModal(); + if (result.action === ModalActions.CLOSE) { + setSelectedDelegate(undefined); + } else { + if (isActingAsDelegate) { + showDelegateNoAccessModal(); + return; + } + removeDelegate({email: selectedDelegate?.email ?? '', delegatedAccess: account?.delegatedAccess}); + setSelectedDelegate(undefined); + } }); }, }, From 427848131752ce60fd9fde1859b5f09dca76d1c7 Mon Sep 17 00:00:00 2001 From: truph01 Date: Thu, 15 Jan 2026 17:40:19 +0700 Subject: [PATCH 03/22] fix: lint --- .../settings/Security/CloseAccountPage.tsx | 14 ++++++----- .../Security/SecuritySettingsPage.tsx | 24 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index 755c22ed44e67..6d3ec2a530894 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -54,13 +54,15 @@ function CloseAccountPage() { // here, we left this as is during refactor to limit the breaking changes. useEffect(() => () => clearError(), []); - const onSubmit = async (values: FormOnyxValues) => { + const onSubmit = (values: FormOnyxValues) => { setReasonForLeaving(values.reasonForLeaving); - const result = await showCloseAccountWarningModal(); - if (result.action !== ModalActions.CONFIRM) { - return; - } - closeAccount(reasonForLeaving); + void (async () => { + const result = await showCloseAccountWarningModal(); + if (result.action !== ModalActions.CONFIRM) { + return; + } + closeAccount(values.reasonForLeaving); + })(); }; const userEmailOrPhone = session?.email ? formatPhoneNumber(session.email) : null; diff --git a/src/pages/settings/Security/SecuritySettingsPage.tsx b/src/pages/settings/Security/SecuritySettingsPage.tsx index efb430f3b6fdc..3b122eb508abd 100644 --- a/src/pages/settings/Security/SecuritySettingsPage.tsx +++ b/src/pages/settings/Security/SecuritySettingsPage.tsx @@ -339,20 +339,22 @@ function SecuritySettingsPage() { modalClose(() => showLockedAccountModal()); return; } - modalClose(async () => { + modalClose(() => { setShouldShowDelegatePopoverMenu(false); setSelectedEmail(undefined); - const result = await showRemoveCopilotModal(); - if (result.action === ModalActions.CLOSE) { - setSelectedDelegate(undefined); - } else { - if (isActingAsDelegate) { - showDelegateNoAccessModal(); - return; + void (async () => { + const result = await showRemoveCopilotModal(); + if (result.action === ModalActions.CLOSE) { + setSelectedDelegate(undefined); + } else { + if (isActingAsDelegate) { + showDelegateNoAccessModal(); + return; + } + removeDelegate({email: selectedDelegate?.email ?? '', delegatedAccess: account?.delegatedAccess}); + setSelectedDelegate(undefined); } - removeDelegate({email: selectedDelegate?.email ?? '', delegatedAccess: account?.delegatedAccess}); - setSelectedDelegate(undefined); - } + })(); }); }, }, From 40fcf95759d9164e5602e97808c0f5544c068ac1 Mon Sep 17 00:00:00 2001 From: truph01 Date: Thu, 15 Jan 2026 17:48:40 +0700 Subject: [PATCH 04/22] fix: lint --- src/pages/settings/Security/CloseAccountPage.tsx | 5 +---- src/pages/settings/Security/SecuritySettingsPage.tsx | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index 6d3ec2a530894..4dc32add49935 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -33,8 +33,6 @@ function CloseAccountPage() { const styles = useThemeStyles(); const {translate, formatPhoneNumber} = useLocalize(); - const [reasonForLeaving, setReasonForLeaving] = useState(''); - const {showConfirmModal} = useConfirmModal(); const showCloseAccountWarningModal = useCallback(() => { return showConfirmModal({ @@ -55,8 +53,7 @@ function CloseAccountPage() { useEffect(() => () => clearError(), []); const onSubmit = (values: FormOnyxValues) => { - setReasonForLeaving(values.reasonForLeaving); - void (async () => { + (async () => { const result = await showCloseAccountWarningModal(); if (result.action !== ModalActions.CONFIRM) { return; diff --git a/src/pages/settings/Security/SecuritySettingsPage.tsx b/src/pages/settings/Security/SecuritySettingsPage.tsx index 3b122eb508abd..acbbd08e42c33 100644 --- a/src/pages/settings/Security/SecuritySettingsPage.tsx +++ b/src/pages/settings/Security/SecuritySettingsPage.tsx @@ -342,7 +342,7 @@ function SecuritySettingsPage() { modalClose(() => { setShouldShowDelegatePopoverMenu(false); setSelectedEmail(undefined); - void (async () => { + (async () => { const result = await showRemoveCopilotModal(); if (result.action === ModalActions.CLOSE) { setSelectedDelegate(undefined); From 898820749029525e63f22677f532a8741823fecf Mon Sep 17 00:00:00 2001 From: truph01 Date: Thu, 15 Jan 2026 17:51:39 +0700 Subject: [PATCH 05/22] fix: lint --- src/pages/settings/Security/CloseAccountPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index 4dc32add49935..bc6fca711a777 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -1,5 +1,5 @@ import {Str} from 'expensify-common'; -import React, {useCallback, useEffect, useState} from 'react'; +import React, {useCallback, useEffect} from 'react'; import {View} from 'react-native'; import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper'; import FormProvider from '@components/Form/FormProvider'; From ae4f550286104cb873184ac368499832dfc20995 Mon Sep 17 00:00:00 2001 From: truph01 Date: Thu, 22 Jan 2026 08:09:27 +0700 Subject: [PATCH 06/22] fix: refactor CardSection --- src/pages/settings/Subscription/CardSection/CardSection.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx index 5539eb28eee91..a68a55d58ed41 100644 --- a/src/pages/settings/Subscription/CardSection/CardSection.tsx +++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx @@ -78,15 +78,17 @@ function CardSection() { }, []); const {showConfirmModal} = useConfirmModal(); + const refundPrompt = useMemo(() => , [translate]); + const showRequestRefundModal = useCallback(() => { return showConfirmModal({ title: translate('subscription.cardSection.requestRefund'), - prompt: , + prompt: refundPrompt, confirmText: translate('subscription.cardSection.requestRefundModal.confirm'), cancelText: translate('common.cancel'), shouldShowCancelButton: true, }); - }, [showConfirmModal, translate]); + }, [showConfirmModal, translate, refundPrompt]); const viewPurchases = useCallback(() => { const query = buildQueryStringFromFilterFormValues({ From aff60e65d648a929eb267ccb4006a1710c300ce4 Mon Sep 17 00:00:00 2001 From: truph01 Date: Thu, 22 Jan 2026 08:09:55 +0700 Subject: [PATCH 07/22] fix: lint --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index ad7cbdcc99ec4..1e7de7f2db5b6 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit ad7cbdcc99ec46cf94f8c830e90136565a566484 +Subproject commit 1e7de7f2db5b65847fa9f5090b784298c1974b54 From 5825911007aceae78ed9465fc6a1df91b6c44134 Mon Sep 17 00:00:00 2001 From: truph01 Date: Thu, 22 Jan 2026 08:12:39 +0700 Subject: [PATCH 08/22] fix: conflicts --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 1e7de7f2db5b6..056474e9aae44 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 1e7de7f2db5b65847fa9f5090b784298c1974b54 +Subproject commit 056474e9aae4453a822e51aab49bc7f3391e1a42 From 1b80676f3d3e2eecf7a41aac1e1d1a90bcdb7e4c Mon Sep 17 00:00:00 2001 From: truph01 Date: Tue, 27 Jan 2026 02:31:03 +0700 Subject: [PATCH 09/22] fix: remove IIFE --- src/pages/settings/Security/CloseAccountPage.tsx | 5 ++--- src/pages/settings/Security/SecuritySettingsPage.tsx | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index bc6fca711a777..f311e370e3281 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -53,13 +53,12 @@ function CloseAccountPage() { useEffect(() => () => clearError(), []); const onSubmit = (values: FormOnyxValues) => { - (async () => { - const result = await showCloseAccountWarningModal(); + showCloseAccountWarningModal().then((result) => { if (result.action !== ModalActions.CONFIRM) { return; } closeAccount(values.reasonForLeaving); - })(); + }); }; const userEmailOrPhone = session?.email ? formatPhoneNumber(session.email) : null; diff --git a/src/pages/settings/Security/SecuritySettingsPage.tsx b/src/pages/settings/Security/SecuritySettingsPage.tsx index cb5117de809f2..8bffc7305709b 100644 --- a/src/pages/settings/Security/SecuritySettingsPage.tsx +++ b/src/pages/settings/Security/SecuritySettingsPage.tsx @@ -342,8 +342,7 @@ function SecuritySettingsPage() { modalClose(() => { setShouldShowDelegatePopoverMenu(false); setSelectedEmail(undefined); - (async () => { - const result = await showRemoveCopilotModal(); + showRemoveCopilotModal().then((result) => { if (result.action === ModalActions.CLOSE) { setSelectedDelegate(undefined); } else { @@ -354,7 +353,7 @@ function SecuritySettingsPage() { removeDelegate({email: selectedDelegate?.email ?? '', delegatedAccess: account?.delegatedAccess}); setSelectedDelegate(undefined); } - })(); + }); }); }, }, From 041139888532eedf56a94f7f95f7036d6a70f975 Mon Sep 17 00:00:00 2001 From: truph01 Date: Tue, 27 Jan 2026 03:32:43 +0700 Subject: [PATCH 10/22] fix: remove manual memoization --- .../settings/Security/CloseAccountPage.tsx | 6 ++-- .../Subscription/CardSection/CardSection.tsx | 26 +++++++------- .../Troubleshoot/TroubleshootPage.tsx | 36 ++++++++----------- 3 files changed, 29 insertions(+), 39 deletions(-) diff --git a/src/pages/settings/Security/CloseAccountPage.tsx b/src/pages/settings/Security/CloseAccountPage.tsx index f311e370e3281..1b7eec3b55105 100644 --- a/src/pages/settings/Security/CloseAccountPage.tsx +++ b/src/pages/settings/Security/CloseAccountPage.tsx @@ -1,5 +1,5 @@ import {Str} from 'expensify-common'; -import React, {useCallback, useEffect} from 'react'; +import React, {useEffect} from 'react'; import {View} from 'react-native'; import DelegateNoAccessWrapper from '@components/DelegateNoAccessWrapper'; import FormProvider from '@components/Form/FormProvider'; @@ -34,7 +34,7 @@ function CloseAccountPage() { const {translate, formatPhoneNumber} = useLocalize(); const {showConfirmModal} = useConfirmModal(); - const showCloseAccountWarningModal = useCallback(() => { + const showCloseAccountWarningModal = () => { return showConfirmModal({ title: translate('closeAccountPage.closeAccountWarning'), prompt: translate('closeAccountPage.closeAccountPermanentlyDeleteData'), @@ -44,7 +44,7 @@ function CloseAccountPage() { danger: true, shouldDisableConfirmButtonWhenOffline: true, }); - }, [showConfirmModal, translate]); + }; // If you are new to hooks this might look weird but basically it is something that only runs when the component unmounts // nothing runs on mount and we pass empty dependencies to prevent this from running on every re-render. diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx index e561d2c82203b..905d9ce387e3f 100644 --- a/src/pages/settings/Subscription/CardSection/CardSection.tsx +++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx @@ -1,4 +1,4 @@ -import React, {useCallback, useEffect, useMemo, useState} from 'react'; +import React, {useEffect, useState} from 'react'; import {View} from 'react-native'; import Icon from '@components/Icon'; import MenuItem from '@components/MenuItem'; @@ -61,26 +61,24 @@ function CardSection() { const [subscriptionRetryBillingStatusSuccessful] = useOnyx(ONYXKEYS.SUBSCRIPTION_RETRY_BILLING_STATUS_SUCCESSFUL, {canBeMissing: true}); const [subscriptionRetryBillingStatusFailed] = useOnyx(ONYXKEYS.SUBSCRIPTION_RETRY_BILLING_STATUS_FAILED, {canBeMissing: true}); const {isOffline} = useNetwork(); - const defaultCard = useMemo(() => Object.values(fundList ?? {}).find((card) => card.accountData?.additionalData?.isBillingCard), [fundList]); - const cardMonth = useMemo(() => DateUtils.getMonthNames()[(defaultCard?.accountData?.cardMonth ?? 1) - 1], [defaultCard?.accountData?.cardMonth]); - const hasFailedLastBilling = useMemo( - () => purchaseList?.[0]?.message.billingType === CONST.BILLING.TYPE_STRIPE_FAILED_AUTHENTICATION || purchaseList?.[0]?.message.billingType === CONST.BILLING.TYPE_FAILED_2018, - [purchaseList], - ); + const defaultCard = Object.values(fundList ?? {}).find((card) => card.accountData?.additionalData?.isBillingCard); + const cardMonth = DateUtils.getMonthNames()[(defaultCard?.accountData?.cardMonth ?? 1) - 1]; + const hasFailedLastBilling = + purchaseList?.[0]?.message.billingType === CONST.BILLING.TYPE_STRIPE_FAILED_AUTHENTICATION || purchaseList?.[0]?.message.billingType === CONST.BILLING.TYPE_FAILED_2018; const [firstDayFreeTrial] = useOnyx(ONYXKEYS.NVP_FIRST_DAY_FREE_TRIAL, {canBeMissing: true}); const [lastDayFreeTrial] = useOnyx(ONYXKEYS.NVP_LAST_DAY_FREE_TRIAL, {canBeMissing: true}); const [billingDisputePending] = useOnyx(ONYXKEYS.NVP_PRIVATE_BILLING_DISPUTE_PENDING, {canBeMissing: true}); const [userBillingFundID] = useOnyx(ONYXKEYS.NVP_BILLING_FUND_ID, {canBeMissing: true}); const [billingStatusOnyx] = useOnyx(ONYXKEYS.NVP_PRIVATE_BILLING_STATUS, {canBeMissing: true}); - const requestRefund = useCallback(() => { + const requestRefund = () => { requestRefundByUser(); Navigation.goBackToHome(); - }, []); + }; const {showConfirmModal} = useConfirmModal(); - const refundPrompt = useMemo(() => , [translate]); + const refundPrompt = ; - const showRequestRefundModal = useCallback(() => { + const showRequestRefundModal = () => { return showConfirmModal({ title: translate('subscription.cardSection.requestRefund'), prompt: refundPrompt, @@ -88,9 +86,9 @@ function CardSection() { cancelText: translate('common.cancel'), shouldShowCancelButton: true, }); - }, [showConfirmModal, translate, refundPrompt]); + }; - const viewPurchases = useCallback(() => { + const viewPurchases = () => { const query = buildQueryStringFromFilterFormValues({ type: CONST.SEARCH.DATA_TYPES.EXPENSE, status: CONST.SEARCH.STATUS.EXPENSE.ALL, @@ -99,7 +97,7 @@ function CardSection() { // rawQuery is needed to populate rawFilterList, which prevents useSuggestedSearchDefaultNavigation from auto-redirecting to actionable searches. Navigation.navigate(ROUTES.SEARCH_ROOT.getRoute({query, rawQuery: query})); - }, []); + }; const [billingStatus, setBillingStatus] = useState(() => CardSectionUtils.getBillingStatus({ diff --git a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx index 40fe23df47cf6..21ea97bdc6704 100644 --- a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx +++ b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx @@ -1,5 +1,5 @@ import {differenceInDays} from 'date-fns'; -import React, {useCallback, useMemo, useState} from 'react'; +import React, {useState} from 'react'; import {View} from 'react-native'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; @@ -64,7 +64,7 @@ function TroubleshootPage() { const {showConfirmModal} = useConfirmModal(); const shouldOpenSurveyReasonPage = tryNewDot?.classicRedirect?.dismissed === false; const {setShouldResetSearchQuery} = useSearchContext(); - const showResetAndRefreshModal = useCallback(async () => { + const showResetAndRefreshModal = async () => { const result = await showConfirmModal({ title: translate('common.areYouSure'), prompt: translate('initialSettingsPage.troubleshoot.confirmResetDescription'), @@ -78,15 +78,15 @@ function TroubleshootPage() { resetOptions(); setShouldResetSearchQuery(true); clearOnyxAndResetApp(); - }, [showConfirmModal, translate, resetOptions, setShouldResetSearchQuery]); - const exportOnyxState = useCallback(() => { + }; + const exportOnyxState = () => { ExportOnyxState.readFromOnyxDatabase().then((value: Record) => { const dataToShare = ExportOnyxState.maskOnyxState(value, shouldMaskOnyxState); ExportOnyxState.shareAsFile(JSON.stringify(dataToShare)); }); - }, [shouldMaskOnyxState]); + }; - const surveyCompletedWithinLastMonth = useMemo(() => { + const getSurveyCompletedWithinLastMonth = () => { const surveyThresholdInDays = 30; const {dismissedReasons} = tryNewDot?.classicRedirect ?? {}; if (dismissedReasons?.length === 0) { @@ -109,9 +109,10 @@ function TroubleshootPage() { const daysSinceLastSurvey = differenceInDays(new Date(), timestampToCheck); return daysSinceLastSurvey < surveyThresholdInDays; - }, [tryNewDot?.classicRedirect]); + }; + const surveyCompletedWithinLastMonth = getSurveyCompletedWithinLastMonth(); - const classicRedirectMenuItem: BaseMenuItem | null = useMemo(() => { + const getClassicRedirectMenuItem = (): BaseMenuItem | null => { if (tryNewDot?.classicRedirect?.isLockedToNewDot) { return null; } @@ -140,9 +141,10 @@ function TroubleshootPage() { }, }), }; - }, [tryNewDot?.classicRedirect?.isLockedToNewDot, icons.ExpensifyLogoNew, surveyCompletedWithinLastMonth, shouldOpenSurveyReasonPage]); + }; + const classicRedirectMenuItem = getClassicRedirectMenuItem(); - const menuItems = useMemo(() => { + const getMenuItems = () => { const debugConsoleItem: BaseMenuItem = { translationKey: 'initialSettingsPage.troubleshoot.viewConsole', icon: icons.Bug, @@ -177,18 +179,8 @@ function TroubleshootPage() { wrapperStyle: [styles.sectionMenuItemTopDescription], })) .reverse(); - }, [ - icons.Bug, - icons.RotateLeft, - icons.Download, - waitForNavigate, - exportOnyxState, - shouldStoreLogs, - classicRedirectMenuItem, - translate, - styles.sectionMenuItemTopDescription, - showResetAndRefreshModal, - ]); + }; + const menuItems = getMenuItems(); return ( Date: Thu, 29 Jan 2026 16:37:49 +0700 Subject: [PATCH 11/22] fix: wrong button color --- src/pages/settings/Subscription/CardSection/CardSection.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx index 905d9ce387e3f..0f7f06ab40e0c 100644 --- a/src/pages/settings/Subscription/CardSection/CardSection.tsx +++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx @@ -85,6 +85,7 @@ function CardSection() { confirmText: translate('subscription.cardSection.requestRefundModal.confirm'), cancelText: translate('common.cancel'), shouldShowCancelButton: true, + danger: true, }); }; From 1babb55db3468c75a33a7212b938d633a73924a8 Mon Sep 17 00:00:00 2001 From: truph01 Date: Sun, 1 Feb 2026 17:27:49 +0700 Subject: [PATCH 12/22] fix: navigation issue when hiding modal in CardSection --- src/pages/settings/Subscription/CardSection/CardSection.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx index 0f7f06ab40e0c..49e2cbeb45a50 100644 --- a/src/pages/settings/Subscription/CardSection/CardSection.tsx +++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx @@ -86,6 +86,7 @@ function CardSection() { cancelText: translate('common.cancel'), shouldShowCancelButton: true, danger: true, + shouldHandleNavigationBack: false, }); }; @@ -262,7 +263,7 @@ function CardSection() { /> )} - {!!(subscriptionPlan && account?.isEligibleForRefund) && ( + { ( Date: Sun, 1 Feb 2026 17:30:16 +0700 Subject: [PATCH 13/22] fix: revert un-related change --- src/pages/settings/Subscription/CardSection/CardSection.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx index 49e2cbeb45a50..24698a4df1bbc 100644 --- a/src/pages/settings/Subscription/CardSection/CardSection.tsx +++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx @@ -263,7 +263,7 @@ function CardSection() { /> )} - { ( + {!!(subscriptionPlan && account?.isEligibleForRefund) && ( Date: Mon, 9 Feb 2026 15:07:26 +0700 Subject: [PATCH 14/22] fix: conflict --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index a4663a30d7b94..68c675aff235a 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit a4663a30d7b948ea34c90f381773c60b8c3ebd0a +Subproject commit 68c675aff235ac3c81f04a20a1e8fe019502bebd From 55726671a55e73df2b102c22e78db332b19d3ccb Mon Sep 17 00:00:00 2001 From: truph01 Date: Mon, 9 Feb 2026 15:09:55 +0700 Subject: [PATCH 15/22] fix: lint --- src/pages/settings/Troubleshoot/TroubleshootPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx index 4f4e2fa4f4dcc..6d92f41f3df1f 100644 --- a/src/pages/settings/Troubleshoot/TroubleshootPage.tsx +++ b/src/pages/settings/Troubleshoot/TroubleshootPage.tsx @@ -1,5 +1,5 @@ import {differenceInDays} from 'date-fns'; -import React, {useCallback, useEffect, useMemo, useState} from 'react'; +import React, {useEffect, useState} from 'react'; import {View} from 'react-native'; import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; From bc2a2ab375ae876bd227bf02442213ce42d1741e Mon Sep 17 00:00:00 2001 From: truph01 Date: Mon, 9 Feb 2026 15:14:09 +0700 Subject: [PATCH 16/22] fix: lint --- src/pages/settings/Subscription/CardSection/CardSection.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx index 24698a4df1bbc..b58c611ba1429 100644 --- a/src/pages/settings/Subscription/CardSection/CardSection.tsx +++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx @@ -125,6 +125,7 @@ function CardSection() { }); useEffect(() => { + // eslint-disable-next-line react-hooks/set-state-in-effect setBillingStatus( CardSectionUtils.getBillingStatus({ translate, From 7d6f658130f258c6f15a2d202df6c2287c90cedd Mon Sep 17 00:00:00 2001 From: truph01 Date: Tue, 17 Feb 2026 08:37:39 +0700 Subject: [PATCH 17/22] fix: conflicts --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 68c675aff235a..db0883a40063c 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 68c675aff235ac3c81f04a20a1e8fe019502bebd +Subproject commit db0883a40063c1097b8fc5da68b6305e14dee223 From 23a0636931a183b6e7333d9611cf6d5bf060c723 Mon Sep 17 00:00:00 2001 From: truph01 Date: Sun, 22 Feb 2026 23:21:52 +0700 Subject: [PATCH 18/22] fix: conflicts --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index db0883a40063c..08338ebdf8069 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit db0883a40063c1097b8fc5da68b6305e14dee223 +Subproject commit 08338ebdf8069ec3da78de81de7541a8058202a3 From 81a75c8edfdf7a632052d9375e68d7fdb7b4f249 Mon Sep 17 00:00:00 2001 From: truph01 Date: Mon, 2 Mar 2026 18:40:44 +0700 Subject: [PATCH 19/22] fix: conflicts --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 08338ebdf8069..39f6ce249b8a3 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 08338ebdf8069ec3da78de81de7541a8058202a3 +Subproject commit 39f6ce249b8a30d74112b772996198e49b8bb162 From f6aced93e8071f3c97f3079da9ce5d2451ef6a30 Mon Sep 17 00:00:00 2001 From: truph01 Date: Mon, 2 Mar 2026 22:37:43 +0700 Subject: [PATCH 20/22] fix: conflicts --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 39f6ce249b8a3..a62e2157d72bf 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 39f6ce249b8a30d74112b772996198e49b8bb162 +Subproject commit a62e2157d72bf49ef8bc0e7ee9f341454ebf7afe From 426c3a66e1439b3527b43bdfe4a2a4726c959a0f Mon Sep 17 00:00:00 2001 From: truph01 Date: Tue, 3 Mar 2026 00:13:45 +0700 Subject: [PATCH 21/22] fix: conflicts --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index a62e2157d72bf..81ea07906616e 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit a62e2157d72bf49ef8bc0e7ee9f341454ebf7afe +Subproject commit 81ea07906616e83338e6cbad9296c784e55ea41e From d7a52782d6d853d87185f0006c4382ff81c2fa36 Mon Sep 17 00:00:00 2001 From: truph01 Date: Tue, 3 Mar 2026 00:40:53 +0700 Subject: [PATCH 22/22] fix: merge main --- Mobile-Expensify | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mobile-Expensify b/Mobile-Expensify index 81ea07906616e..1c9ede1736f89 160000 --- a/Mobile-Expensify +++ b/Mobile-Expensify @@ -1 +1 @@ -Subproject commit 81ea07906616e83338e6cbad9296c784e55ea41e +Subproject commit 1c9ede1736f893ab474ee40c94f6d66ea539ffac