diff --git a/.changeset/empty-mayflies-pump.md b/.changeset/empty-mayflies-pump.md new file mode 100644 index 000000000000..e6285c419f2b --- /dev/null +++ b/.changeset/empty-mayflies-pump.md @@ -0,0 +1,5 @@ +--- +"live-mobile": patch +--- + +add WS scan qr code diff --git a/apps/ledger-live-mobile/src/components/RequiresCameraPermissions/Fallback.tsx b/apps/ledger-live-mobile/src/components/RequiresCameraPermissions/Fallback.tsx index 4c46666eda75..cba184296984 100644 --- a/apps/ledger-live-mobile/src/components/RequiresCameraPermissions/Fallback.tsx +++ b/apps/ledger-live-mobile/src/components/RequiresCameraPermissions/Fallback.tsx @@ -12,6 +12,7 @@ type Props = { buttonTitle: string; onPress: () => void; event: string; + hasNoBackground?: boolean; }; const IconSettings = () => ; @@ -22,11 +23,12 @@ const FallbackCameraBody: React.FC = ({ buttonTitle, onPress, event, + hasNoBackground, }: Props) => { const { colors } = useTheme(); return ( - + diff --git a/apps/ledger-live-mobile/src/components/RequiresCameraPermissions/index.tsx b/apps/ledger-live-mobile/src/components/RequiresCameraPermissions/index.tsx index 7f1a5654c83c..50be5606d126 100644 --- a/apps/ledger-live-mobile/src/components/RequiresCameraPermissions/index.tsx +++ b/apps/ledger-live-mobile/src/components/RequiresCameraPermissions/index.tsx @@ -16,6 +16,7 @@ type Props = { * context, rather than directly showing an error screen. * */ optimisticallyMountChildren?: boolean; + fallBackHasNoBackground?: boolean; }; /** @@ -38,6 +39,7 @@ type Props = { const RequiresCameraPermissions: React.FC = ({ children, optimisticallyMountChildren = false, + fallBackHasNoBackground = false, }) => { const { t } = useTranslation(); const { @@ -59,6 +61,7 @@ const RequiresCameraPermissions: React.FC = ({ = ({ Settings <1>> <0>General <1>> <0>Ledger Sync <1>> <0>Synchronize <1>> <0>Show QR", + "step3": "Scan QR code until loader hits 100%." + } + } }, "pinCode": { "title": "Enter your code", diff --git a/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/components/StepFlow.tsx b/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/components/StepFlow.tsx index 17440e1a354e..149fba5c38ef 100644 --- a/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/components/StepFlow.tsx +++ b/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/components/StepFlow.tsx @@ -2,13 +2,13 @@ import React from "react"; import SelectAddAccountMethod from "./SelectAddAccountMethod"; import ChooseSyncMethod from "LLM/features/WalletSync/screens/Synchronize/ChooseMethod"; import QrCodeMethod from "LLM/features/WalletSync/screens/Synchronize/QrCodeMethod"; +import PinCodeInput from "LLM/features/WalletSync/screens/Synchronize/PinCodeInput"; import { TrackScreen } from "~/analytics"; import { CryptoCurrency, TokenCurrency } from "@ledgerhq/types-cryptoassets"; import { AnalyticsPage } from "LLM/features/WalletSync/hooks/useLedgerSyncAnalytics"; import { Options, Steps } from "LLM/features/WalletSync/types/Activation"; import SyncError from "LLM/features/WalletSync/screens/Synchronize/SyncError"; import PinCodeDisplay from "LLM/features/WalletSync/screens/Synchronize/PinCodeDisplay"; -import PinCodeInput from "LLM/features/WalletSync/screens/Synchronize/PinCodeInput"; type Props = { currentStep: Steps; @@ -19,6 +19,7 @@ type Props = { currentOption: Options; navigateToChooseSyncMethod: () => void; navigateToQrCodeMethod: () => void; + onQrCodeScanned: (data: string) => void; qrProcess: { url: string | null; error: Error | null; @@ -35,6 +36,7 @@ const StepFlow = ({ currentOption, navigateToChooseSyncMethod, navigateToQrCodeMethod, + onQrCodeScanned, qrProcess, }: Props) => { const getScene = () => { @@ -58,7 +60,13 @@ const StepFlow = ({ ); case Steps.QrCodeMethod: - return ; + return ( + + ); case Steps.PinDisplay: return qrProcess.pinCode ? : null; diff --git a/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/index.tsx b/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/index.tsx index 99583a1f79c8..b6eaa4cbe440 100644 --- a/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/index.tsx +++ b/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/index.tsx @@ -29,6 +29,7 @@ function View({ navigateToChooseSyncMethod, navigateToQrCodeMethod, qrProcess, + onQrCodeScanned, }: ViewProps) { const CustomDrawerHeader = () => ; @@ -51,6 +52,7 @@ function View({ navigateToChooseSyncMethod={navigateToChooseSyncMethod} navigateToQrCodeMethod={navigateToQrCodeMethod} qrProcess={qrProcess} + onQrCodeScanned={onQrCodeScanned} /> diff --git a/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/useAddAccountViewModel.ts b/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/useAddAccountViewModel.ts index 1d744d049f15..06a6c49721fe 100644 --- a/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/useAddAccountViewModel.ts +++ b/apps/ledger-live-mobile/src/newArch/features/Accounts/screens/AddAccount/useAddAccountViewModel.ts @@ -54,6 +54,12 @@ const useAddAccountViewModel = ({ isOpened, onClose }: AddAccountDrawerProps) => currentOption, }); + const onQrCodeScanned = (data: string) => { + // eslint-disable-next-line no-console + console.log(data); + //setCurrentStep(Steps.PinCodeInput); + }; + return { isAddAccountDrawerVisible: isOpened, onCloseAddAccountDrawer, @@ -64,6 +70,7 @@ const useAddAccountViewModel = ({ isOpened, onClose }: AddAccountDrawerProps) => currentOption, setCurrentStep, onGoBack, + onQrCodeScanned, qrProcess: { url, error, diff --git a/apps/ledger-live-mobile/src/newArch/features/WalletSync/__integrations__/scanQRCode.integration.test.tsx b/apps/ledger-live-mobile/src/newArch/features/WalletSync/__integrations__/scanQRCode.integration.test.tsx index aabfaacda9ad..f4c6860306b4 100644 --- a/apps/ledger-live-mobile/src/newArch/features/WalletSync/__integrations__/scanQRCode.integration.test.tsx +++ b/apps/ledger-live-mobile/src/newArch/features/WalletSync/__integrations__/scanQRCode.integration.test.tsx @@ -11,6 +11,7 @@ describe("scanQRCode", () => { await user.press(await screen.findByText(/ledger sync/i)); await user.press(await screen.findByText(/already created a key?/i)); await user.press(await screen.findByText(/scan a qr code/i)); - await expect(await screen.findByText(/show qr/i)).toBeVisible(); + await expect(screen.queryAllByText(/show qr/i)).toHaveLength(2); + await expect(screen.getByTestId("ws-scan-camera")).toBeVisible(); }); }); diff --git a/apps/ledger-live-mobile/src/newArch/features/WalletSync/__integrations__/synchronizeWithQrCode.integration.test.tsx b/apps/ledger-live-mobile/src/newArch/features/WalletSync/__integrations__/synchronizeWithQrCode.integration.test.tsx index 551ed8a4b23f..ea612db39a73 100644 --- a/apps/ledger-live-mobile/src/newArch/features/WalletSync/__integrations__/synchronizeWithQrCode.integration.test.tsx +++ b/apps/ledger-live-mobile/src/newArch/features/WalletSync/__integrations__/synchronizeWithQrCode.integration.test.tsx @@ -21,7 +21,7 @@ describe("SynchronizeWithQrCode", () => { await user.press(await screen.findByText(/ledger sync/i)); await user.press(await screen.findByText(/already created a key?/i)); await user.press(await screen.findByText(/scan a qr code/i)); - await user.press(await screen.findByText(/show qr/i)); + await user.press(await screen.queryAllByText(/show qr/i)[0]); expect(await screen.getByTestId("ws-qr-code-displayed")).toBeVisible(); //PinCode Page after scanning QRCode diff --git a/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Activation/ActivationFlow.tsx b/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Activation/ActivationFlow.tsx index 64abaaa214a4..ff01fde20e7c 100644 --- a/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Activation/ActivationFlow.tsx +++ b/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Activation/ActivationFlow.tsx @@ -19,7 +19,7 @@ type Props = { isLoading: boolean; pinCode: string | null; }; - + onQrCodeScanned: (data: string) => void; currentOption: Options; setOption: (option: Options) => void; }; @@ -31,6 +31,7 @@ const ActivationFlow = ({ qrProcess, currentOption, setOption, + onQrCodeScanned, }: Props) => { const getScene = () => { switch (currentStep) { @@ -49,7 +50,13 @@ const ActivationFlow = ({ ); case Steps.QrCodeMethod: - return ; + return ( + + ); case Steps.PinDisplay: return qrProcess.pinCode ? : null; diff --git a/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/BottomContainer.tsx b/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/BottomContainer.tsx new file mode 100644 index 000000000000..fe8c35ccad55 --- /dev/null +++ b/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/BottomContainer.tsx @@ -0,0 +1,61 @@ +import React from "react"; +import { ScrollContainer, Text, Flex } from "@ledgerhq/native-ui"; +import { useTranslation } from "react-i18next"; +import styled, { useTheme } from "styled-components/native"; + +type Props = { + steps: { + description: React.JSX.Element; + }[]; +}; + +const BulletPoint = styled(Flex)` + width: 16px; + height: 16px; + justify-content: center; + align-items: center; + background-color: ${({ theme }) => theme.colors.primary.c80}; + border-radius: 100px; +`; + +const FlexContainer = styled(Flex)` + margin-bottom: 16px; + display: flex; + flex-direction: row; + align-items: flex-start; + gap: 12px; +`; + +const BottomContainer = ({ steps }: Props) => { + const { colors } = useTheme(); + const { t } = useTranslation(); + + return ( + + + {t("walletSync.synchronize.qrCode.scan.explanation.title")} + + + {steps.map((step, index) => ( + + + + {index + 1} + + + {step.description} + + ))} + + + ); +}; + +export default BottomContainer; diff --git a/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/QrCode.tsx b/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/QrCode.tsx index c8514b2daf92..86a46ace77d3 100644 --- a/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/QrCode.tsx +++ b/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/QrCode.tsx @@ -1,9 +1,10 @@ import React from "react"; -import { Flex, Text, NumberedList, ScrollContainer } from "@ledgerhq/native-ui"; +import { Flex, Text } from "@ledgerhq/native-ui"; import styled, { useTheme } from "styled-components/native"; import QRCode from "react-native-qrcode-svg"; import getWindowDimensions from "~/logic/getWindowDimensions"; import { Trans, useTranslation } from "react-i18next"; +import BottomContainer from "./BottomContainer"; const Italic = styled(Text)` font-style: italic; @@ -31,14 +32,14 @@ const QrCode = ({ qrCodeValue }: Props) => { const steps = [ { description: ( - + {t("walletSync.synchronize.qrCode.show.explanation.steps.step1")} ), }, { description: ( - + { }, { description: ( - + {t("walletSync.synchronize.qrCode.show.explanation.steps.step3")} ), @@ -85,20 +86,7 @@ const QrCode = ({ qrCodeValue }: Props) => { size={QRCodeSize} /> - - - {t("walletSync.synchronize.qrCode.show.explanation.title")} - - - + ); }; diff --git a/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/ScanQrCode.tsx b/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/ScanQrCode.tsx new file mode 100644 index 000000000000..be65994f50db --- /dev/null +++ b/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/ScanQrCode.tsx @@ -0,0 +1,102 @@ +import React from "react"; +import { Flex, Icons, Text } from "@ledgerhq/native-ui"; +import { Trans, useTranslation } from "react-i18next"; +import styled, { useTheme } from "styled-components/native"; +import BottomContainer from "./BottomContainer"; +import { BarCodeScanningResult, Camera, CameraType } from "expo-camera"; +import { BarCodeScanner } from "expo-barcode-scanner"; +import ScanTargetSvg from "./ScanTargetSvg"; +import RequiresCameraPermissions from "~/components/RequiresCameraPermissions"; + +type Props = { + onQrCodeScanned: (data: string) => void; +}; + +const Italic = styled(Text)` + font-style: italic; +`; +// Won't work since we don't have inter italic font + +const ScanQrCode = ({ onQrCodeScanned }: Props) => { + const { t } = useTranslation(); + const { colors } = useTheme(); + + const onBarCodeScanned = ({ data }: BarCodeScanningResult) => { + onQrCodeScanned(data); + }; + + const steps = [ + { + description: ( + + {t("walletSync.synchronize.qrCode.scan.explanation.steps.step1")} + + ), + }, + { + description: ( + + , + , + ]} + /> + + ), + }, + { + description: ( + + {t("walletSync.synchronize.qrCode.scan.explanation.steps.step3")} + + ), + }, + ]; + + return ( + + + + + + + + + {t("walletSync.synchronize.qrCode.scan.description")} + + + + + + + ); +}; + +export default ScanQrCode; diff --git a/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/ScanTargetSvg.tsx b/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/ScanTargetSvg.tsx new file mode 100644 index 000000000000..d06aed24101d --- /dev/null +++ b/apps/ledger-live-mobile/src/newArch/features/WalletSync/components/Synchronize/ScanTargetSvg.tsx @@ -0,0 +1,14 @@ +import * as React from "react"; +import Svg, { SvgProps, Path } from "react-native-svg"; +const ScanTargetSvg = (props: SvgProps) => ( + + + +); +export default ScanTargetSvg; diff --git a/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Activation/ActivationDrawer.tsx b/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Activation/ActivationDrawer.tsx index c1cf7aef4c56..6bc0afbfc201 100644 --- a/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Activation/ActivationDrawer.tsx +++ b/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Activation/ActivationDrawer.tsx @@ -1,7 +1,6 @@ import React from "react"; import QueuedDrawer from "LLM/components/QueuedDrawer"; import { TrackScreen } from "~/analytics"; -import { useWindowDimensions } from "react-native"; import { Flex } from "@ledgerhq/native-ui"; import ActivationFlow from "../../components/Activation/ActivationFlow"; import { Steps } from "../../types/Activation"; @@ -23,6 +22,7 @@ function View({ canGoBack, navigateToChooseSyncMethod, navigateToQrCodeMethod, + onQrCodeScanned, goBackToPreviousStep, handleClose, onCloseDrawer, @@ -30,8 +30,6 @@ function View({ currentOption, setCurrentOption, }: ViewProps) { - const { height } = useWindowDimensions(); - const maxDrawerHeight = height - 180; const CustomDrawerHeader = () => ; return ( @@ -44,7 +42,7 @@ function View({ hasBackButton={canGoBack} onBack={goBackToPreviousStep} > - + diff --git a/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Activation/useActivationDrawerModel.ts b/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Activation/useActivationDrawerModel.ts index e9e35f6e6a93..e118245d5ed4 100644 --- a/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Activation/useActivationDrawerModel.ts +++ b/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Activation/useActivationDrawerModel.ts @@ -49,6 +49,13 @@ const useActivationDrawerModel = ({ isOpen, startingStep, handleClose }: Props) setCurrentStep(Steps.QrCodeMethod); }; + // That means the url as be stored in the store + const onQrCodeScanned = (data: string) => { + // eslint-disable-next-line no-console + console.log(data); + //setCurrentStep(Steps.PinCodeInput); + }; + const resetStep = () => setCurrentStep(startingStep); const resetOption = () => setCurrentOption(Options.SCAN); const goBackToPreviousStep = () => setCurrentStep(getPreviousStep(currentStep)); @@ -72,6 +79,7 @@ const useActivationDrawerModel = ({ isOpen, startingStep, handleClose }: Props) canGoBack, navigateToChooseSyncMethod, navigateToQrCodeMethod, + onQrCodeScanned, onCloseDrawer, handleClose, goBackToPreviousStep, diff --git a/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Synchronize/QrCodeMethod.tsx b/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Synchronize/QrCodeMethod.tsx index 9834c98a6ce6..4c76f7bf62fd 100644 --- a/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Synchronize/QrCodeMethod.tsx +++ b/apps/ledger-live-mobile/src/newArch/features/WalletSync/screens/Synchronize/QrCodeMethod.tsx @@ -1,6 +1,7 @@ import React from "react"; import { Flex, TabSelector } from "@ledgerhq/native-ui"; import QrCode from "LLM/features/WalletSync/components/Synchronize/QrCode"; +import ScanQrCode from "../../components/Synchronize/ScanQrCode"; import { Options, OptionsType } from "LLM/features/WalletSync/types/Activation"; import { useTranslation } from "react-i18next"; import { @@ -12,10 +13,11 @@ import { TrackScreen } from "~/analytics"; interface Props { setSelectedOption: (option: OptionsType) => void; + onQrCodeScanned: (data: string) => void; currentOption: Options; } -const QrCodeMethod = ({ currentOption, setSelectedOption }: Props) => { +const QrCodeMethod = ({ setSelectedOption, onQrCodeScanned, currentOption }: Props) => { const { onClickTrack } = useLedgerSyncAnalytics(); const { t } = useTranslation(); @@ -35,14 +37,7 @@ const QrCodeMethod = ({ currentOption, setSelectedOption }: Props) => { return ( <> - + ); case Options.SHOW_QR: @@ -56,7 +51,7 @@ const QrCodeMethod = ({ currentOption, setSelectedOption }: Props) => { }; return ( - +