diff --git a/.changeset/fresh-dragons-smile.md b/.changeset/fresh-dragons-smile.md new file mode 100644 index 000000000000..5e12dc401fb7 --- /dev/null +++ b/.changeset/fresh-dragons-smile.md @@ -0,0 +1,5 @@ +--- +"live-mobile": patch +--- + +Re-use account-specific stake flow actions directly in the Earn Navigator to avoid empty stake flow navigation that was causing empty modals to appear. diff --git a/apps/ledger-live-mobile/src/components/RootNavigator/BaseNavigator.tsx b/apps/ledger-live-mobile/src/components/RootNavigator/BaseNavigator.tsx index 722ca1f5a597..dfb0b3564ebd 100644 --- a/apps/ledger-live-mobile/src/components/RootNavigator/BaseNavigator.tsx +++ b/apps/ledger-live-mobile/src/components/RootNavigator/BaseNavigator.tsx @@ -289,11 +289,6 @@ export default function BaseNavigator() { options={{ headerShown: false }} {...noNanoBuyNanoWallScreenOptions} /> - + (); @@ -29,6 +30,12 @@ const Earn = (props: NavigationProps) => { const accounts = useSelector(accountsSelector); const route = useRoute(); + const openStakingDrawer = useStakingDrawer({ + navigation, + parentRoute: route, + alwaysShowNoFunds: false, + }); + useEffect(() => { if (!ptxEarn?.enabled) { return navigation.pop(); @@ -63,13 +70,7 @@ const Earn = (props: NavigationProps) => { const accountId = getAccountIdFromWalletAccountId(walletId); const account = accounts.find(acc => acc.id === accountId); if (account) { - navigation.navigate(NavigatorName.StakeFlow, { - screen: ScreenName.Stake, - params: { - account, - parentRoute: route, - }, - }); + openStakingDrawer(account); } else { // eslint-disable-next-line no-console console.log("no matching account found for given id."); @@ -88,7 +89,7 @@ const Earn = (props: NavigationProps) => { params: { currencies: [currencyId], parentRoute: route, - // Stake flow will get CryptoCurrency and Account, and navigate to NoFunds flow: + // Stake flow will skip step 1 (select CryptoCurrency) and step 2 (select Account), and navigate straight to NoFunds flow: alwaysShowNoFunds: true, // Navigate to NoFunds even if some funds available. }, }); @@ -105,7 +106,15 @@ const Earn = (props: NavigationProps) => { deeplinkRouting(); return clearDeepLink(); - }, [paramAction, ptxEarn?.enabled, props.route.params, accounts, navigation, route]); + }, [ + paramAction, + ptxEarn?.enabled, + props.route.params, + accounts, + navigation, + route, + openStakingDrawer, + ]); return ( <> diff --git a/apps/ledger-live-mobile/src/components/Stake/index.tsx b/apps/ledger-live-mobile/src/components/Stake/index.tsx index 93a4872b1398..eeb2d25b44e4 100644 --- a/apps/ledger-live-mobile/src/components/Stake/index.tsx +++ b/apps/ledger-live-mobile/src/components/Stake/index.tsx @@ -2,14 +2,14 @@ import { useMemo, useLayoutEffect, useCallback } from "react"; import { StackNavigationProp } from "@react-navigation/stack"; import { useNavigation } from "@react-navigation/native"; -import { Account } from "@ledgerhq/types-live"; import { listCurrencies, filterCurrencies } from "@ledgerhq/live-common/currencies/helpers"; import { useFeature } from "@ledgerhq/live-common/featureFlags/index"; import { NavigatorName, ScreenName } from "../../const"; -import perFamilyAccountActions from "../../generated/accountActions"; import type { StackNavigatorProps, BaseComposite } from "../RootNavigator/types/helpers"; import type { StakeNavigatorParamList } from "../RootNavigator/types/StakeNavigator"; +import { useStakingDrawer } from "./useStakingDrawer"; + type Props = BaseComposite>; const StakeFlow = ({ route }: Props) => { @@ -26,57 +26,7 @@ const StakeFlow = ({ route }: Props) => { }); }, [currencies]); - const goToAccount = useCallback( - (account: Account, parentAccount?: Account) => { - if (alwaysShowNoFunds) { - navigation.navigate(NavigatorName.Base, { - screen: NavigatorName.NoFundsFlow, - drawer: undefined, - params: { - screen: ScreenName.NoFunds, - params: { - account, - parentAccount, - }, - }, - }); - return; - } - - // @ts-expect-error issue in typing - const decorators = perFamilyAccountActions[account?.currency?.family]; - const familySpecificMainActions = - (decorators && - decorators.getMainActions && - decorators.getMainActions({ - account, - parentAccount, - colors: {}, - parentRoute, - })) || - []; - const stakeFlow = familySpecificMainActions.find( - (action: { id: string }) => action.id === "stake", - )?.navigationParams; - if (!stakeFlow) return null; - - const [name, options] = stakeFlow; - - navigation.navigate(NavigatorName.Base, { - screen: name, - drawer: options?.drawer, - params: { - screen: options.screen, - params: { - ...(options?.params || {}), - account, - parentAccount, - }, - }, - }); - }, - [navigation, parentRoute, alwaysShowNoFunds], - ); + const goToAccountStakeFlow = useStakingDrawer({ navigation, parentRoute, alwaysShowNoFunds }); const requestAccount = useCallback(() => { if (cryptoCurrencies.length === 1) { @@ -85,7 +35,7 @@ const StakeFlow = ({ route }: Props) => { screen: ScreenName.RequestAccountsSelectAccount, params: { currency: cryptoCurrencies[0], - onSuccess: goToAccount, + onSuccess: goToAccountStakeFlow, allowAddAccount: true, // if no account, need to be able to add one to get funds. }, }); @@ -95,19 +45,19 @@ const StakeFlow = ({ route }: Props) => { params: { currencies: cryptoCurrencies, allowAddAccount: true, - onSuccess: goToAccount, + onSuccess: goToAccountStakeFlow, }, }); } - }, [cryptoCurrencies, navigation, goToAccount]); + }, [cryptoCurrencies, navigation, goToAccountStakeFlow]); useLayoutEffect(() => { if (account) { - goToAccount(account); + goToAccountStakeFlow(account); } else { requestAccount(); } - }, [requestAccount, goToAccount, account]); + }, [requestAccount, goToAccountStakeFlow, account]); return null; }; diff --git a/apps/ledger-live-mobile/src/components/Stake/useStakingDrawer.tsx b/apps/ledger-live-mobile/src/components/Stake/useStakingDrawer.tsx new file mode 100644 index 000000000000..1527da2da36c --- /dev/null +++ b/apps/ledger-live-mobile/src/components/Stake/useStakingDrawer.tsx @@ -0,0 +1,68 @@ +import { StackNavigationProp } from "@react-navigation/stack"; +import { ParamListBase, RouteProp } from "@react-navigation/native"; +import { Account } from "@ledgerhq/types-live"; +import { NavigatorName, ScreenName } from "../../const"; +import perFamilyAccountActions from "../../generated/accountActions"; + +/** Open the stake flow for a given account from any navigator. Returns to parent route on completion. */ +export function useStakingDrawer({ + navigation, + parentRoute, + alwaysShowNoFunds, +}: { + navigation: StackNavigationProp<{ [key: string]: object | undefined }>; + parentRoute: RouteProp | undefined; + alwaysShowNoFunds?: boolean | undefined; +}) { + return (account: Account, parentAccount?: Account) => { + if (alwaysShowNoFunds) { + // get funds to stake with + navigation.navigate(NavigatorName.Base, { + screen: NavigatorName.NoFundsFlow, + drawer: undefined, + params: { + screen: ScreenName.NoFunds, + params: { + account, + parentAccount, + }, + }, + }); + return; + } + + // @ts-expect-error issue in typing + const decorators = perFamilyAccountActions[account?.currency?.family]; + // get the stake flow for the specific currency + const familySpecificMainActions = + (decorators && + decorators.getMainActions && + decorators.getMainActions({ + account, + parentAccount, + colors: {}, + parentRoute, + })) || + []; + const stakeFlow = familySpecificMainActions.find( + (action: { id: string }) => action.id === "stake", + )?.navigationParams; + if (!stakeFlow) return null; + + const [name, options] = stakeFlow; + + // open staking drawer (or stake flow screens) for the specific currency, inside the current navigator + navigation.navigate(NavigatorName.Base, { + screen: name, + drawer: options?.drawer, + params: { + screen: options.screen, + params: { + ...(options?.params || {}), + account, + parentAccount, + }, + }, + }); + }; +} diff --git a/apps/ledger-live-mobile/src/components/TabBar/TransferDrawer.tsx b/apps/ledger-live-mobile/src/components/TabBar/TransferDrawer.tsx index 2ed5a3a02a79..105ae7e2a260 100644 --- a/apps/ledger-live-mobile/src/components/TabBar/TransferDrawer.tsx +++ b/apps/ledger-live-mobile/src/components/TabBar/TransferDrawer.tsx @@ -111,10 +111,12 @@ export default function TransferDrawer({ onClose }: Omit onNavigate(NavigatorName.Exchange, { screen: ScreenName.ExchangeBuy }), [onNavigate], ); + const onSell = useCallback( () => onNavigate(NavigatorName.Exchange, { screen: ScreenName.ExchangeSell }), [onNavigate],