Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import {
import Routes from '../../../../../constants/navigation/Routes';
import { mapCaipChainIdToChainName } from '../../util/mapCaipChainIdToChainName';

interface AddFundsModalNavigationDetails {
export interface AddFundsModalNavigationDetails {
priorityToken?: CardFundingToken;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
import { useCardHomeData } from '../../hooks/useCardHomeData';
import MoneyBalanceIcon from '../../../../../images/money-balance.svg';

interface AssetSelectionModalNavigationDetails {
export interface AssetSelectionModalNavigationDetails {
navigateToCardHomeOnPriorityToken?: boolean;
selectionOnly?: boolean;
onTokenSelect?: (token: CardFundingToken) => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { ModalAction } from '../../../Rewards/components/RewardsBottomSheetModal
import { strings } from '../../../../../../locales/i18n';
import { useParams } from '../../../../../util/navigation/navUtils';

interface ConfirmModalParams {
export interface ConfirmModalParams {
title: string;
description: string;
icon: IconName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const clearOnValueChange = () => {
onValueChangeCallback = null;
};

interface RegionSelectorModalParams {
export interface RegionSelectorModalParams {
regions: Region[];
renderAreaCode?: boolean;
selectedRegionKey?: string | null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import useAuthentication from '../../../../../core/Authentication/hooks/useAuthe
import { useTailwind } from '@metamask/design-system-twrnc-preset';
import { CardHomeSelectors } from '../../Views/CardHome/CardHome.testIds';

interface PasswordBottomSheetParams {
export interface PasswordBottomSheetParams {
onSuccess: () => void;
description?: string;
}
Expand Down
52 changes: 33 additions & 19 deletions app/components/UI/Card/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,15 @@
clearNativeStackNavigatorOptions,
transparentModalScreenOptions,
} from '../../../../constants/navigation/clearStackNavigatorOptions';
import type {
CardModalsNavigationParamList,
CardRootParamList,
CardScreensStackParamList,
} from '../types/navigation';

const Stack = createNativeStackNavigator();
const ModalsStack = createNativeStackNavigator();
const ScreensStack = createNativeStackNavigator<CardScreensStackParamList>();
const RootStack = createNativeStackNavigator<CardRootParamList>();
const ModalsStack = createNativeStackNavigator<CardModalsNavigationParamList>();

// All Card main screens render their own header via HeaderStandard, so hide
// the navigator chrome by default.
Expand All @@ -51,7 +57,9 @@
const spendingLimitScreenOptions = ({
route,
}: {
route: { params?: { flow?: 'manage' | 'enable' | 'onboarding' } };
route: {
params?: CardScreensStackParamList['CardSpendingLimit'];

Check warning on line 61 in app/components/UI/Card/routes/index.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Consider removing 'undefined' type or '?' specifier, one of them is redundant.

See more on https://sonarcloud.io/project/issues?id=MetaMask_metamask-mobile&issues=AZ9iLUYpyGaQetiPJHhj&open=AZ9iLUYpyGaQetiPJHhj&pullRequest=33283
};
}): NativeStackNavigationOptions => ({
headerShown: false,
gestureEnabled: route.params?.flow !== 'onboarding',
Expand All @@ -68,37 +76,43 @@
);

return (
<Stack.Navigator
<ScreensStack.Navigator
initialRouteName={initialRouteName}
screenOptions={mainScreenOptions}
>
<Stack.Screen name={Routes.CARD.HOME} component={CardHome} />
<Stack.Screen name={Routes.CARD.WELCOME} component={CardWelcome} />
<Stack.Screen
<ScreensStack.Screen name={Routes.CARD.HOME} component={CardHome} />
<ScreensStack.Screen name={Routes.CARD.WELCOME} component={CardWelcome} />
<ScreensStack.Screen
name={Routes.CARD.CHOOSE_YOUR_CARD}
component={ChooseYourCard}
/>
<Stack.Screen name={Routes.CARD.REVIEW_ORDER} component={ReviewOrder} />
<Stack.Screen
<ScreensStack.Screen
name={Routes.CARD.REVIEW_ORDER}
component={ReviewOrder}
/>
<ScreensStack.Screen
name={Routes.CARD.ORDER_COMPLETED}
component={OrderCompleted}
/>
<Stack.Screen name={Routes.CARD.CASHBACK} component={Cashback} />
<Stack.Screen name={Routes.CARD.CREDIT_REDEEM} component={CreditRedeem} />
<Stack.Screen
<ScreensStack.Screen name={Routes.CARD.CASHBACK} component={Cashback} />
<ScreensStack.Screen
name={Routes.CARD.CREDIT_REDEEM}
component={CreditRedeem}
/>
<ScreensStack.Screen
name={Routes.CARD.AUTHENTICATION}
component={CardAuthentication}
/>
<Stack.Screen
<ScreensStack.Screen
name={Routes.CARD.SPENDING_LIMIT}
component={SpendingLimit}
options={spendingLimitScreenOptions}
/>
<Stack.Screen
<ScreensStack.Screen
name={Routes.CARD.ONBOARDING.ROOT}
component={OnboardingNavigator}
/>
</Stack.Navigator>
</ScreensStack.Navigator>
);
};

Expand Down Expand Up @@ -169,20 +183,20 @@
);

const CardRoutes = () => (
<Stack.Navigator
<RootStack.Navigator
initialRouteName={Routes.CARD.HOME}
screenOptions={{ headerShown: false }}
>
<Stack.Screen name={Routes.CARD.HOME} component={MainRoutes} />
<Stack.Screen
<RootStack.Screen name={Routes.CARD.HOME} component={MainRoutes} />
<RootStack.Screen
name={Routes.CARD.MODALS.ID}
component={CardModalsRoutes}
options={{
...clearNativeStackNavigatorOptions,
...transparentModalScreenOptions,
}}
/>
</Stack.Navigator>
</RootStack.Navigator>
);

export default withCardSDK(CardRoutes);
104 changes: 104 additions & 0 deletions app/components/UI/Card/types/navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import type { NavigatorScreenParams } from '@react-navigation/native';
import type { AddFundsModalNavigationDetails } from '../components/AddFundsBottomSheet/AddFundsBottomSheet';
import type { AssetSelectionModalNavigationDetails } from '../components/AssetSelectionBottomSheet/AssetSelectionBottomSheet';
import type { RegionSelectorModalParams } from '../components/Onboarding/RegionSelectorModal';
import type { ConfirmModalParams } from '../components/Onboarding/ConfirmModal';
import type { PasswordBottomSheetParams } from '../components/PasswordBottomSheet/PasswordBottomSheet';
import type { DaimoPayModalParams } from '../components/DaimoPayModal/DaimoPayModal';
import type { CreditBalanceTooltipParams } from '../components/CreditBalanceTooltipSheet/CreditBalanceTooltipSheet';
import type { MoneyUnlinkCardSheetRouteParams } from '../components/MoneyUnlinkCardSheet/MoneyUnlinkCardSheet';
import type { ChooseYourCardParams } from '../Views/ChooseYourCard/ChooseYourCard';
import type { ReviewOrderParams } from '../Views/ReviewOrder/ReviewOrder';
import type { OrderCompletedParams } from '../Views/OrderCompleted/OrderCompleted';
import type { CardFundingToken, CardUserPhase } from '../types';

/**
* Nested-navigation params for Card container screens navigated via
* `navigate(container, { screen, params })`.
*
* Kept local to avoid a circular import with NavigationService/types.
*/
interface CardNestedNavigationParams {
screen?: string;
params?: object;
}

/**
* Param list for screens inside the Card main stack (`MainRoutes`).
*/
// ParamListBase requires `type`; `interface` cannot satisfy it.
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type CardScreensStackParamList = {
CardHome: undefined;
CardWelcome: undefined;
ChooseYourCard: ChooseYourCardParams | undefined;
ReviewOrder: ReviewOrderParams | undefined;
OrderCompleted: OrderCompletedParams | undefined;
CardCashback: undefined;
CardCreditRedeem: undefined;
CardAuthentication:
| {
showAuthPrompt?: boolean;
postAuthRedirect?: { screen: string; params?: object };
}
| undefined;
CardSpendingLimit:
| {
flow?: 'manage' | 'enable' | 'onboarding' | 'enable_card';
selectedToken?: CardFundingToken;
}
| undefined;
CardOnboarding:
| (CardNestedNavigationParams & { cardUserPhase?: CardUserPhase })
| undefined;
};

/**
* Param list for screens inside the Card modal stack (`CardModalsRoutes`).
*/
// ParamListBase requires `type`; `interface` cannot satisfy it.
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type CardModalsNavigationParamList = {
CardAddFundsModal: AddFundsModalNavigationDetails | undefined;
CardAssetSelectionModal: AssetSelectionModalNavigationDetails | undefined;
CardRegionSelectionModal: RegionSelectorModalParams;
CardConfirmModal: ConfirmModalParams;
CardPasswordModal: PasswordBottomSheetParams;
CardRecurringFeeModal: undefined;
CardDaimoPayModal: DaimoPayModalParams;
CardViewPinModal: { imageUrl: string };
CardSpendingLimitOptionsModal: {
currentLimitType: 'full' | 'restricted';
currentCustomLimit: string;
callerRoute: string;
callerParams?: Record<string, unknown>;
};
CardWaitlistFormModal: { url: string };
CardForgotPasswordModal: { location?: 'us' | 'international' } | undefined;
CardCreditBalanceTooltipModal: CreditBalanceTooltipParams | undefined;
CardCreditRefundTooltipModal: { isMoneyAccount?: boolean } | undefined;
CardUnlinkMoneyAccountSheet: MoneyUnlinkCardSheetRouteParams | undefined;
};

/**
* Param list for the outer Card root stack (`CardRoutes`): main screens + modals.
*/
// ParamListBase requires `type`; `interface` cannot satisfy it.
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type CardRootParamList = {
CardHome: NavigatorScreenParams<CardScreensStackParamList> | undefined;
CardModals: NavigatorScreenParams<CardModalsNavigationParamList> | undefined;
};

/**
* Feature-level Card navigation params for nested `CardScreens` / `CardModals` entry.
*/
// Intersection (`&`) requires `type`; `interface` cannot express this.
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
export type CardNavigationParamList = CardScreensStackParamList &
CardModalsNavigationParamList & {
CardScreens: NavigatorScreenParams<CardRootParamList> | undefined;
CardModals:
| NavigatorScreenParams<CardModalsNavigationParamList>
| undefined;
};
75 changes: 31 additions & 44 deletions app/core/NavigationService/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,18 @@ import type {
PerpsStackParamList,
} from '../../components/UI/Perps/types/navigation';
import type { MoneyNavigationParamList } from '../../components/UI/Money/types/navigation';
import type {
CardModalsNavigationParamList,
CardRootParamList,
CardScreensStackParamList,
} from '../../components/UI/Card/types/navigation';
import type { TrendingTokensFullViewParams } from '../../components/UI/Trending/Views/TrendingTokensFullView/TrendingTokensFullView';
import type { MarketInsightsRouteParams } from '../../components/UI/MarketInsights/Views/MarketInsightsView/MarketInsightsView';
import type { MoreTokenActionsMenuParams } from '../../components/UI/TokenDetails/components/MoreTokenActionsMenu';
import type { SecurityBadgeBottomSheetParams } from '../../components/UI/TokenDetails/components/SecurityBadgeBottomSheet';
import type { MAPickerSheetParams } from '../../components/UI/Charts/AdvancedChart/MAPickerSheet';
import type { AgenticCliApprovalParams } from '../../components/Views/AgenticCliApproval/types';
import type { AgenticCliDashboardWebviewParams } from '../../components/Views/AgenticCliDashboardWebview/types';
import type { CreditBalanceTooltipParams } from '../../components/UI/Card/components/CreditBalanceTooltipSheet/CreditBalanceTooltipSheet';
import type { MoneyUnlinkCardSheetRouteParams } from '../../components/UI/Card/components/MoneyUnlinkCardSheet/MoneyUnlinkCardSheet';
import type { MoneyDeeplinkModalParams } from '../../components/UI/Money/components/MoneyDeeplinkModal/MoneyDeeplinkModal';
import type { TradingSignalsSetupParams } from '../../components/Views/SocialLeaderboard/components/TradingSignalsSetupBottomSheet/TradingSignalsSetupBottomSheet';
import type { ExploreFeedRouteParams } from '../../components/Views/TrendingView/TrendingView';
Expand Down Expand Up @@ -198,9 +201,6 @@ import type {
} from '../../components/Views/RevealPrivateCredential/RevealPrivateCredential.types';

// Card params
import type { CardConfirmModalParams } from '../../components/UI/Card/Card.types';
import type { ShippingAddress } from '../../components/UI/Card/util/buildUserAddress';

// Account actions params
import type {
AccountActionsParams,
Expand Down Expand Up @@ -927,25 +927,17 @@ export type RootStackParamList = {
///: END:ONLY_INCLUDE_IF

// Card routes
CardScreens: undefined;
CardHome: undefined;
CardWelcome: undefined;
CardAuthentication: { showAuthPrompt?: boolean } | undefined;
CardSpendingLimit: { flow: string } | undefined;
ChooseYourCard:
| { flow: string; shippingAddress?: ShippingAddress }
| undefined;
CardCashback: undefined;
CardCreditRedeem: undefined;
ReviewOrder: undefined;
OrderCompleted:
| {
paymentMethod?: string;
transactionHash?: string;
fromUpgrade?: boolean;
}
| undefined;
CardOnboarding: undefined;
CardScreens: NavigatorScreenParams<CardRootParamList> | undefined;
CardHome: CardScreensStackParamList['CardHome'];
CardWelcome: CardScreensStackParamList['CardWelcome'];
CardAuthentication: CardScreensStackParamList['CardAuthentication'];
CardSpendingLimit: CardScreensStackParamList['CardSpendingLimit'];
ChooseYourCard: CardScreensStackParamList['ChooseYourCard'];
CardCashback: CardScreensStackParamList['CardCashback'];
CardCreditRedeem: CardScreensStackParamList['CardCreditRedeem'];
ReviewOrder: CardScreensStackParamList['ReviewOrder'];
OrderCompleted: CardScreensStackParamList['OrderCompleted'];
CardOnboarding: CardScreensStackParamList['CardOnboarding'];
CardOnboardingSignUp: undefined;
CardOnboardingConfirmEmail: undefined;
CardOnboardingSetPhoneNumber: undefined;
Expand All @@ -957,26 +949,21 @@ export type RootStackParamList = {
CardOnboardingComplete: undefined;
CardOnboardingKYCFailed: undefined;
CardOnboardingKYCPending: undefined;
CardModals: NestedNavigationParams | undefined;
CardAddFundsModal: undefined;
CardAssetSelectionModal: undefined;
CardRegionSelectionModal: undefined;
CardConfirmModal: CardConfirmModalParams | undefined;
CardPasswordModal: undefined;
CardRecurringFeeModal: undefined;
CardDaimoPayModal: undefined;
CardViewPinModal: { imageUrl: string };
CardSpendingLimitOptionsModal: {
currentLimitType: 'full' | 'restricted';
currentCustomLimit: string;
callerRoute: string;
callerParams?: Record<string, unknown>;
};
CardWaitlistFormModal: { url: string };
CardForgotPasswordModal: { location?: 'us' | 'international' } | undefined;
CardCreditBalanceTooltipModal: CreditBalanceTooltipParams | undefined;
CardCreditRefundTooltipModal: { isMoneyAccount?: boolean } | undefined;
CardUnlinkMoneyAccountSheet: MoneyUnlinkCardSheetRouteParams | undefined;
CardModals: NavigatorScreenParams<CardModalsNavigationParamList> | undefined;
CardAddFundsModal: CardModalsNavigationParamList['CardAddFundsModal'];
CardAssetSelectionModal: CardModalsNavigationParamList['CardAssetSelectionModal'];
CardRegionSelectionModal: CardModalsNavigationParamList['CardRegionSelectionModal'];
CardConfirmModal: CardModalsNavigationParamList['CardConfirmModal'];
CardPasswordModal: CardModalsNavigationParamList['CardPasswordModal'];
CardRecurringFeeModal: CardModalsNavigationParamList['CardRecurringFeeModal'];
CardDaimoPayModal: CardModalsNavigationParamList['CardDaimoPayModal'];
CardViewPinModal: CardModalsNavigationParamList['CardViewPinModal'];
CardSpendingLimitOptionsModal: CardModalsNavigationParamList['CardSpendingLimitOptionsModal'];
CardWaitlistFormModal: CardModalsNavigationParamList['CardWaitlistFormModal'];
CardForgotPasswordModal: CardModalsNavigationParamList['CardForgotPasswordModal'];
CardCreditBalanceTooltipModal: CardModalsNavigationParamList['CardCreditBalanceTooltipModal'];
CardCreditRefundTooltipModal: CardModalsNavigationParamList['CardCreditRefundTooltipModal'];
CardUnlinkMoneyAccountSheet: CardModalsNavigationParamList['CardUnlinkMoneyAccountSheet'];

// Send routes
Recipient: SendRecipientParams | undefined;
Expand Down
Loading