Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ofreyssinet-ledger committed Oct 28, 2024
1 parent b9ce7cd commit 4beb5bd
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 58 deletions.
128 changes: 89 additions & 39 deletions apps/ledger-live-mobile/src/screens/Portfolio/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import {
} from "@ledgerhq/live-common/hooks/recoverFeatureFlag";
import { useRefreshAccountsOrdering } from "~/actions/general";
import {
// TODO: discreetMode is never used 😱 is it safe to remove
// discreetModeSelector,
hasBeenUpsoldProtectSelector,
lastConnectedDeviceSelector,
onboardingTypeSelector,
Expand Down Expand Up @@ -54,6 +52,8 @@ import ContentCardsLocation from "~/dynamicContent/ContentCardsLocation";
import { ContentCardLocation } from "~/dynamicContent/types";
import usePortfolioAnalyticsOptInPrompt from "~/hooks/analyticsOptInPrompt/usePorfolioAnalyticsOptInPrompt";
import AddAccountDrawer from "LLM/features/Accounts/screens/AddAccount";
import { DeviceModelId } from "@ledgerhq/types-devices";
import { useStartPostOnboardingCallback } from "@ledgerhq/live-common/postOnboarding/hooks";

export { default as PortfolioTabIcon } from "./TabIcon";

Expand All @@ -65,22 +65,98 @@ const RefreshableCollapsibleHeaderFlatList = globalSyncRefreshControl(Collapsibl
progressViewOffset: Platform.OS === "android" ? 64 : 0,
});

function PortfolioScreen({ navigation }: NavigationProps) {
const hideEmptyTokenAccount = useEnv("HIDE_EMPTY_TOKEN_ACCOUNTS");
const { t } = useTranslation();
// TODO: discreetMode is never used 😱 is it safe to remove
// const discreetMode = useSelector(discreetModeSelector);
const hasBeenUpsoldProtect = useSelector(hasBeenUpsoldProtectSelector);
const lastConnectedDevice = useSelector(lastConnectedDeviceSelector);
const [isAddModalOpened, setAddModalOpened] = useState(false);
const { colors } = useTheme();
const { isAWalletCardDisplayed } = useDynamicContent();
const hasRedirectedToPostOnboardingSelector = () => true;

const setHasRedirectedToPostOnboarding = () => {};

function useOpenProtectUpsellCallback() {
const onboardingType = useSelector(onboardingTypeSelector);
const protectFeature = useFeature("protectServicesMobile");
const recoverAlreadyOnboardedURI = useAlreadyOnboardedURI(protectFeature);
const recoverPostOnboardingURI = usePostOnboardingURI(protectFeature);
const recoverHomeURI = useHomeURI(protectFeature);
const dispatch = useDispatch();
return useCallback(async () => {
const internetConnected = await internetReachable();
if (internetConnected && protectFeature?.enabled) {
if (recoverPostOnboardingURI && onboardingType === OnboardingType.restore) {
Linking.openURL(recoverPostOnboardingURI);
dispatch(setHasBeenUpsoldProtect(true));
} else if (recoverHomeURI && onboardingType === OnboardingType.setupNew) {
Linking.openURL(recoverHomeURI);
dispatch(setHasBeenUpsoldProtect(true));
} else if (recoverAlreadyOnboardedURI) {
Linking.openURL(recoverAlreadyOnboardedURI);
dispatch(setHasBeenUpsoldProtect(true));
}
}
}, [
dispatch,
onboardingType,
protectFeature?.enabled,
recoverAlreadyOnboardedURI,
recoverHomeURI,
recoverPostOnboardingURI,
]);
}

function useOpenPostOnboardingCallback(deviceModelId?: DeviceModelId) {
const dispatch = useDispatch();
const startPostOnboarding = useStartPostOnboardingCallback();
return useCallback(() => {
startPostOnboarding({
deviceModelId: deviceModelId,
resetNavigationStack: false,
fallbackIfNoAction: () => {},
});
dispatch(setHasRedirectedToPostOnboarding(true));
}, [deviceModelId, dispatch, startPostOnboarding]);
}

/**
* Redirects the user to the post onboarding or the protect upsell if needed
* */
function useAutoRedirectToPostOnboarding() {
const hasBeenUpsoldProtect = useSelector(hasBeenUpsoldProtectSelector);
const hasRedirectedToPostOnboarding = useSelector(hasRedirectedToPostOnboardingSelector);
const recoverUpsellRedirection = useFeature("recoverUpsellRedirection");
const lastConnectedDevice = useSelector(lastConnectedDeviceSelector);

const eligibleDevicesForUpsell = recoverUpsellRedirection?.enabled
? [DeviceModelId.stax, DeviceModelId.europa]
: [DeviceModelId.nanoX];

const eligibleForUpsell =
lastConnectedDevice?.modelId && eligibleDevicesForUpsell.includes(lastConnectedDevice.modelId);

const shouldRedirectToProtectUpsell = !hasBeenUpsoldProtect && eligibleForUpsell;

const shouldRedirectToPostOnboarding =
!hasRedirectedToPostOnboarding && (eligibleForUpsell ? hasBeenUpsoldProtect : true);

const openProtectUpsell = useOpenProtectUpsellCallback();
const openPostOnboarding = useOpenPostOnboardingCallback(lastConnectedDevice?.modelId);

useEffect(() => {
if (shouldRedirectToProtectUpsell) {
openProtectUpsell();
} else if (shouldRedirectToPostOnboarding) {
openPostOnboarding();
}
}, [
openPostOnboarding,
openProtectUpsell,
shouldRedirectToPostOnboarding,
shouldRedirectToProtectUpsell,
]);
}

function PortfolioScreen({ navigation }: NavigationProps) {
const hideEmptyTokenAccount = useEnv("HIDE_EMPTY_TOKEN_ACCOUNTS");
const { t } = useTranslation();
const [isAddModalOpened, setAddModalOpened] = useState(false);
const { colors } = useTheme();
const { isAWalletCardDisplayed } = useDynamicContent();

const onBackFromUpdate = useCallback(
(_updateState: UpdateStep) => {
Expand All @@ -89,33 +165,7 @@ function PortfolioScreen({ navigation }: NavigationProps) {
[navigation],
);

useEffect(() => {
const openProtectUpsell = async () => {
const internetConnected = await internetReachable();
if (internetConnected && protectFeature?.enabled) {
if (recoverPostOnboardingURI && onboardingType === OnboardingType.restore) {
Linking.openURL(recoverPostOnboardingURI);
} else if (recoverHomeURI && onboardingType === OnboardingType.setupNew) {
Linking.openURL(recoverHomeURI);
} else if (recoverAlreadyOnboardedURI) {
Linking.openURL(recoverAlreadyOnboardedURI);
}
}
};
if (!hasBeenUpsoldProtect && lastConnectedDevice?.modelId === "nanoX") {
openProtectUpsell();
dispatch(setHasBeenUpsoldProtect(true));
}
}, [
onboardingType,
hasBeenUpsoldProtect,
lastConnectedDevice,
recoverPostOnboardingURI,
recoverAlreadyOnboardedURI,
recoverHomeURI,
dispatch,
protectFeature?.enabled,
]);
useAutoRedirectToPostOnboarding();

usePortfolioAnalyticsOptInPrompt();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,59 @@ import { BaseComposite, RootNavigation } from "~/components/RootNavigator/types/
import { DeviceModelId } from "@ledgerhq/devices";
import EuropaCompletionView from "./EuropaCompletionView";
import StaxCompletionView from "./StaxCompletionView";
import { useFeature } from "@ledgerhq/live-common/featureFlags";

type Props = BaseComposite<
StackScreenProps<SyncOnboardingStackParamList, ScreenName.SyncOnboardingCompletion>
>;

const CompletionScreen = ({ navigation, route }: Props) => {
const { device } = route.params;

const recoverUpsellRedirection = useFeature("recoverUpsellRedirection");

const startPostOnboarding = useStartPostOnboardingCallback();

const redirectToMainScreen = useCallback(() => {
(navigation as unknown as RootNavigation).reset({
index: 0,
routes: [
{
name: NavigatorName.Base,
state: {
routes: [
{
name: NavigatorName.Main,
},
],
},
},
],
});
}, [navigation]);

const redirectToPostOnboarding = useCallback(() => {
startPostOnboarding({
deviceModelId: device.modelId,
resetNavigationStack: true,
fallbackIfNoAction: () =>
// Resets the navigation stack to avoid allowing to go back to the onboarding welcome screen
// FIXME: bindings to react-navigation seem to have issues with composites
(navigation as unknown as RootNavigation).reset({
index: 0,
routes: [
{
name: NavigatorName.Base,
state: {
routes: [
{
name: NavigatorName.Main,
},
],
},
},
],
}),
redirectToMainScreen(),
});
}, [device.modelId, navigation, startPostOnboarding]);
}, [device.modelId, redirectToMainScreen, startPostOnboarding]);

const redirectToNextScreen = recoverUpsellRedirection?.enabled
? redirectToMainScreen // The main screen will handle the redirection to the upsell screen
: redirectToPostOnboarding;

return (
<TouchableWithoutFeedback onPress={redirectToPostOnboarding}>
<TouchableWithoutFeedback onPress={redirectToNextScreen}>
<Flex width="100%" height="100%" alignItems="center" justifyContent="center">
{device.modelId === DeviceModelId.europa ? (
<EuropaCompletionView device={device} onAnimationFinish={redirectToPostOnboarding} />
<EuropaCompletionView device={device} onAnimationFinish={redirectToNextScreen} />
) : (
<StaxCompletionView onAnimationFinish={redirectToPostOnboarding} />
<StaxCompletionView onAnimationFinish={redirectToNextScreen} />
)}
</Flex>
</TouchableWithoutFeedback>
Expand Down

0 comments on commit 4beb5bd

Please sign in to comment.