Skip to content

Commit

Permalink
[FEAT] : LLM revamp recover service manager (#4818)
Browse files Browse the repository at this point in the history
* Revamp Service in Manager

* Add changeset

* Fix Banner New Ledger Issue

* Fix typecheck

* Review

* remove unused file
  • Loading branch information
mcayuelas-ledger authored Sep 27, 2023
1 parent 948d3ba commit e00647b
Show file tree
Hide file tree
Showing 9 changed files with 197 additions and 170 deletions.
5 changes: 5 additions & 0 deletions .changeset/strong-flowers-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"live-mobile": patch
---

Update UI in Manager for Services Recover
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function BluetoothEmpty({ onPairNewDevice, hideAnimation }: Props) {
</Text>
</Box>
</Flex>
<Button mb={8} event="PairDevice" type="main" onPress={onPairNewDevice} testID="pair-device">
<Button mb={5} event="PairDevice" type="main" onPress={onPairNewDevice} testID="pair-device">
<Trans i18nKey="SelectDevice.deviceNotFoundPairNewDevice" />
</Button>
</>
Expand Down
101 changes: 57 additions & 44 deletions apps/ledger-live-mobile/src/components/SelectDevice2/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -354,53 +354,66 @@ export default function SelectDevice({
</Touchable>
)}
</Flex>
<ScrollContainer my={4}>
{deviceList.length > 0 ? (
deviceList.map(device => (
<Item key={device.deviceId} device={device as Device} onPress={handleOnSelect} />
))
) : (
<Touchable
onPress={isChoiceDrawerDisplayedOnAddDevice ? onAddNewPress : openBlePairingFlow}
{...addNewButtonEventProps}
>
<Flex
p={5}
mb={4}
borderRadius={5}
flexDirection="row"
alignItems="center"
borderColor="neutral.c40"
borderStyle="dashed"
borderWidth="1px"
<ScrollContainer
my={4}
contentContainerStyle={{
flexGrow: 1,
justifyContent: "space-between",
flexDirection: "column",
}}
>
<Flex>
{deviceList.length > 0 ? (
deviceList.map(device => (
<Item key={device.deviceId} device={device as Device} onPress={handleOnSelect} />
))
) : (
<Touchable
onPress={isChoiceDrawerDisplayedOnAddDevice ? onAddNewPress : openBlePairingFlow}
{...addNewButtonEventProps}
>
<IconsLegacy.PlusMedium color="neutral.c90" size={20} />
<Text variant="large" fontWeight="semiBold" ml={5}>
{t(
`manager.selectDevice.${
Platform.OS === "android" ? "addWithBluetooth" : "addALedger"
}`,
)}
<Flex
p={5}
mb={4}
borderRadius={5}
flexDirection="row"
alignItems="center"
borderColor="neutral.c40"
borderStyle="dashed"
borderWidth="1px"
>
<IconsLegacy.PlusMedium color="neutral.c90" size={20} />
<Text variant="large" fontWeight="semiBold" ml={5}>
{t(
`manager.selectDevice.${
Platform.OS === "android" ? "addWithBluetooth" : "addALedger"
}`,
)}
</Text>
</Flex>
</Touchable>
)}
{Platform.OS === "android" &&
USBDevice === undefined &&
ProxyDevice === undefined && (
<Text
color="neutral.c100"
variant="large"
fontWeight="semiBold"
fontSize={4}
lineHeight="21px"
>
<Trans i18nKey="manager.selectDevice.otgBanner" />
</Text>
</Flex>
</Touchable>
)}
{Platform.OS === "android" && USBDevice === undefined && ProxyDevice === undefined && (
<Text
color="neutral.c100"
variant="large"
fontWeight="semiBold"
fontSize={4}
lineHeight="21px"
>
<Trans i18nKey="manager.selectDevice.otgBanner" />
</Text>
)}
{displayServicesWidget && <ServicesWidget />}
)}
{displayServicesWidget && <ServicesWidget />}
</Flex>

<Flex alignItems="center" mt={10}>
<BuyDeviceCTA />
</Flex>
</ScrollContainer>
<Flex alignItems="center" mt={5}>
<BuyDeviceCTA />
</Flex>

<QueuedDrawer
isRequestingToBeOpened={isAddNewDrawerOpen}
onClose={() => setIsAddNewDrawerOpen(false)}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { useFeature } from "@ledgerhq/live-common/featureFlags/index";
import {
useLearnMoreURI,
useAlreadySubscribedURI,
} from "@ledgerhq/live-common/hooks/recoverFeatureFlag";
import { useMemo } from "react";
import { Linking } from "react-native";
import { track } from "../../../analytics";
import { urls } from "../../../config/urls";

export function useProtect() {
const servicesConfig = useFeature("protectServicesMobile");

const learnMoreURI = useLearnMoreURI(servicesConfig);
const alreadySubscribedURI = useAlreadySubscribedURI(servicesConfig);

const onLearnMore = () => {
const url = `${learnMoreURI}&source=${urls.recoverSources.myLedger}`;
Linking.canOpenURL(url).then(() => Linking.openURL(url));
};

const onAlreadySubscribe = () => {
const url = `${alreadySubscribedURI}&source=${urls.recoverSources.myLedger}`;
Linking.canOpenURL(url).then(() => Linking.openURL(url));
};

const onClickCard = () => {
onLearnMore();
trackEvent("card_clicked", "Recover Card");
};

const onClickSignIn = () => {
onAlreadySubscribe();
trackEvent("button_clicked", "Sign In Recover");
};
const onClickFreeTrial = () => {
onLearnMore();
trackEvent("button_clicked", "Try for Free Recover");
};

const trackEvent = (eventName: "button_clicked" | "card_clicked", name: string) => {
track(eventName, {
...(eventName === "button_clicked" && { button: name }),
...(eventName === "card_clicked" && { card: name }),
});
};

const displayService = useMemo(
() => servicesConfig?.enabled && learnMoreURI && alreadySubscribedURI,
[alreadySubscribedURI, learnMoreURI, servicesConfig?.enabled],
);

return {
displayService,
onClickCard,
onClickSignIn,
onClickFreeTrial,
};
}
118 changes: 68 additions & 50 deletions apps/ledger-live-mobile/src/components/ServicesWidget/index.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,84 @@
import { Flex, Text } from "@ledgerhq/native-ui";
import React, { memo, useCallback } from "react";
import { Linking, Image } from "react-native";
import { Button, Flex, Text } from "@ledgerhq/native-ui";
import React, { memo } from "react";
import { Image, ImageBackground } from "react-native";
import { useTranslation } from "react-i18next";
import { useTheme } from "styled-components/native";
import { useFeature } from "@ledgerhq/live-common/featureFlags/index";
import {
useAlreadySubscribedURI,
useLearnMoreURI,
} from "@ledgerhq/live-common/hooks/recoverFeatureFlag";
import NewProtectState from "./Protect/NewProtectState";
import styled, { useTheme } from "styled-components/native";

import Touchable from "../Touchable";

import LedgerRecoverLogoLight from "../../images/ledger_recover_light.png";
import LedgerRecoverLogoDark from "../../images/ledger_recover_dark.png";

import LedgerRecoverCardTopImage from "../../images/ledger_recover_card_top.png";
import LedgerRecoverBackground from "../../images/ledger_recover_card_background.png";
import { useProtect } from "./Protect/useProtect";

function ServicesWidget() {
const { t } = useTranslation();
const servicesConfig = useFeature("protectServicesMobile");
const theme = useTheme();
const { displayService, onClickFreeTrial, onClickCard, onClickSignIn } = useProtect();

const learnMoreURI = useLearnMoreURI(servicesConfig);
const alreadySubscribedURI = useAlreadySubscribedURI(servicesConfig);
return displayService ? (
<Flex>
<Flex flexDirection="row" justifyContent="space-between" alignItems="center" mb={6} mt={8}>
<Text variant="h5" fontWeight="semiBold">
{t("servicesWidget.title")}
</Text>

const onCardPress = useCallback(() => {
if (alreadySubscribedURI) {
Linking.canOpenURL(alreadySubscribedURI).then(() => Linking.openURL(alreadySubscribedURI));
}
}, [alreadySubscribedURI]);
<Touchable onPress={onClickSignIn}>
<Text color="primary.c90" mr={3} variant="body">
{t("servicesWidget.signIn")}
</Text>
</Touchable>
</Flex>
<StyledTouchable onPress={onClickCard}>
<ImageBackground
source={LedgerRecoverBackground}
style={{
width: "100%",
height: "100%",
position: "relative",
display: "flex",
justifyContent: "center",
alignItems: "center",
borderRadius: 30,
}}
imageStyle={{
borderRadius: theme.space[4],
}}
>
<TagComponent bg="opacityReverse.c50" borderRadius={1} px={2} py={1}>
<Text variant="small" fontWeight="semiBold" color="neutral.c100" numberOfLines={1}>
{t("servicesWidget.recover.tag")}
</Text>
</TagComponent>

return servicesConfig?.enabled && learnMoreURI && alreadySubscribedURI ? (
<>
<Text mt={10} fontWeight="semiBold" variant="h5" mb={6}>
{t("servicesWidget.title")}
<ImageComponent>
<Image source={LedgerRecoverLogoLight} style={{ width: 90, height: 26 }} />
</ImageComponent>
</ImageBackground>
</StyledTouchable>

<Text color="neutral.c80" fontWeight="semiBold" my={4}>
{t("servicesWidget.recover.desc")}
</Text>
<Touchable onPress={onCardPress}>
<Flex bg="neutral.c30" borderRadius={8} mb={13} overflow="hidden">
<Image
source={LedgerRecoverCardTopImage}
resizeMode={"stretch"}
style={{ width: "100%", height: 8 }}
/>
<Flex p={7}>
<Flex flexDirection="row" justifyContent="space-between" alignItems="center" mb={6}>
<Image
source={
theme.colors.type === "light" ? LedgerRecoverLogoLight : LedgerRecoverLogoDark
}
style={{ width: 90, height: 26 }}
/>
<NewProtectState.StatusTag />
</Flex>
<Text variant="body" color="neutral.c80" mb={7}>
{t(`servicesWidget.protect.status.new.desc`)}
</Text>
<NewProtectState params={{ learnMoreURI, alreadySubscribedURI }} />
</Flex>
</Flex>
</Touchable>
</>

<Button type="main" onPress={onClickFreeTrial} style={{ alignSelf: "flex-start" }}>
<Text variant="body" fontWeight="semiBold" color="neutral.c00">
{t("servicesWidget.recover.cta")}
</Text>
</Button>
</Flex>
) : null;
}

const StyledTouchable = styled(Touchable)`
height: 110px;
`;

const TagComponent = styled(Flex)`
position: absolute;
right: 9px;
top: 9px;
`;

const ImageComponent = styled(Flex)``;

export default memo(ServicesWidget);
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

1 comment on commit e00647b

@vercel
Copy link

@vercel vercel bot commented on e00647b Sep 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.