Skip to content

Commit

Permalink
Merge pull request #4310 from LedgerHQ/feat/LIVE-8596/LLDSyncOnboardi…
Browse files Browse the repository at this point in the history
…ngPolish

feat(LLD/Sync Onboarding): Pixel polishing
  • Loading branch information
mle-gall authored Aug 28, 2023
2 parents 902f2ed + a51494c commit 4901a78
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 41 deletions.
5 changes: 5 additions & 0 deletions .changeset/khaki-hounds-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ledger-live-desktop": patch
---

Pixel polishing Sync Onboarding for Stax
1 change: 1 addition & 0 deletions apps/ledger-live-desktop/index-types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ declare module "*.svg";
declare module "*.png";
declare module "*.jpg";
declare module "*.webm";
declare module "*.mp4";

type Store = import("redux").Store;
type Device = import("@ledgerhq/live-common/hw/actions/types").Device;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,13 @@ const OnboardingAppInstallStep = ({ device, deviceToRestore, onComplete, onError
{t(`onboardingAppInstall.${deviceToRestore ? "restore" : "default"}.subtitle`)}
</Text>
<Flex pt={8} pb={2} justifyContent="space-between">
<Button flex={1} onClick={handlePressSkip} data-test-id="skip-cta-button">
<Button
variant="main"
outline
flex={1}
onClick={handlePressSkip}
data-test-id="skip-cta-button"
>
{t(`onboardingAppInstall.${deviceToRestore ? "restore" : "default"}.skipCTA`)}
</Button>
<Flex px={2} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,19 @@ import { useDispatch, useSelector } from "react-redux";
import { useHistory } from "react-router-dom";
import { DeviceModelId } from "@ledgerhq/devices";
import { useStartPostOnboardingCallback } from "@ledgerhq/live-common/postOnboarding/hooks/index";
import DeviceIllustration from "~/renderer/components/DeviceIllustration";
import { saveSettings } from "~/renderer/actions/settings";
import { getCurrentDevice } from "~/renderer/reducers/devices";
import { useTheme } from "styled-components";

const GO_TO_POSTONBOARDING_TIMEOUT = 5000;
import CompletedOnboardingDark from "./assets/completeOnboardingDark.mp4";
import CompletedOnboardingLight from "./assets/completeOnboardingLight.mp4";

const GO_TO_POSTONBOARDING_TIMEOUT = 6000;

const videos = {
dark: CompletedOnboardingDark,
light: CompletedOnboardingLight,
};

const CompletionScreen = () => {
const dispatch = useDispatch();
Expand All @@ -17,6 +25,9 @@ const CompletionScreen = () => {

const handleInitPostOnboarding = useStartPostOnboardingCallback();

const { colors } = useTheme();
const palette = colors.palette.type;

useEffect(() => {
dispatch(saveSettings({ hasCompletedOnboarding: true }));
const timeout = setTimeout(
Expand All @@ -34,7 +45,11 @@ const CompletionScreen = () => {

return (
<Flex alignItems="center" width="100%" justifyContent="center">
<DeviceIllustration deviceId={device?.modelId || DeviceModelId.nanoX} />
<Flex height={"100vh"}>
<video autoPlay loop height="100%">
<source src={videos[palette]} type="video/mp4" />
</video>
</Flex>
</Flex>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { Flex, InfiniteLoader, Text, Box } from "@ledgerhq/react-ui";
import styled, { useTheme } from "styled-components";
import { Flex, InfiniteLoader, Alert } from "@ledgerhq/react-ui";
import TrackPage from "~/renderer/analytics/TrackPage";
import { analyticsFlowName } from "./shared";

const Overlay = styled(Flex)`
background: linear-gradient(rgba(0, 0, 0, 0) 0%, ${p => p.theme.colors.constant.overlay} 25%);
`;

type Props = {
isOpen: boolean;
delay?: number;
Expand All @@ -19,7 +14,6 @@ export const DesyncOverlay = ({ isOpen, delay = 0, productName }: Props) => {
const { t } = useTranslation();

const [showContent, setShowContent] = useState<boolean>(false);
const { colors } = useTheme();

useEffect(() => {
if (isOpen) {
Expand All @@ -40,14 +34,15 @@ export const DesyncOverlay = ({ isOpen, delay = 0, productName }: Props) => {
}

return (
<Overlay
<Flex
zIndex={100}
position="absolute"
top={0}
left={0}
height="100%"
width="100%"
flexDirection="column"
backgroundColor="constant.overlay"
>
<TrackPage
category="device connection lost"
Expand All @@ -57,26 +52,21 @@ export const DesyncOverlay = ({ isOpen, delay = 0, productName }: Props) => {
refreshSource={false}
/>
<Flex alignItems="flex-end" justifyContent="center" flex={1} padding={4}>
<Flex
width="400px"
backgroundColor={colors.warning}
borderRadius="8px"
p={4}
mr={4}
mb={4}
flexDirection="row"
alignItems="center"
>
<Box flexShrink={1}>
<Text pr={3} variant="body" color={colors.constant.black}>
{t("syncOnboarding.manual.desyncOverlay.errorMessage", {
deviceName: productName,
})}
</Text>
</Box>
<InfiniteLoader color="black" size={24} />
</Flex>
<Alert
type="warning"
title={t("syncOnboarding.manual.desyncOverlay.errorMessage", {
deviceName: productName,
})}
containerProps={{
width: 480,
}}
renderRight={() => (
<Flex pl={6}>
<InfiniteLoader color="neutral.c100" size={24} />
</Flex>
)}
></Alert>
</Flex>
</Overlay>
</Flex>
);
};
Original file line number Diff line number Diff line change
@@ -1,18 +1,58 @@
import React from "react";
import { useTranslation } from "react-i18next";
import { Link, Flex } from "@ledgerhq/react-ui";
import { Link, Flex, Text } from "@ledgerhq/react-ui";
import ExitIcon from "~/renderer/icons/ExitIcon";
import { track } from "~/renderer/analytics/segment";
import { getDeviceModel } from "@ledgerhq/devices";
import { Device } from "@ledgerhq/live-common/hw/actions/types";
import styled, { useTheme } from "styled-components";

export type Props = {
onClose: () => void;
device: Device | null;
displayTitle: boolean | null;
};

const Header = ({ onClose }: Props) => {
const AnimatedText = styled.div<{ visible?: boolean | null }>`
opacity: ${props => (props.visible ? 1 : 0)};
transition: opacity 0.6s linear;
`;

const Header = ({ onClose, device, displayTitle }: Props) => {
const { t } = useTranslation();
const productName = device
? getDeviceModel(device.modelId).productName || device.modelId
: "Ledger Device";
const deviceName = device?.deviceName || productName;
const { colors } = useTheme();

const palette = colors.palette.type;

return (
<Flex justifyContent="flex-end" position="absolute" right={0}>
<Flex
width="100vw"
justifyContent="space-between"
position="sticky"
bg={palette === "dark" ? "#131415" : "#F9F9F9"} //using the hex colors that can be found in light.js and dark.js local palettes, unaccessible here as we're in v3 context, until they're replaced by the design system colors in the whole app
top={0}
left={0}
zIndex={8}
style={{
boxShadow: displayTitle
? `0px 5px 15px 5px ${
palette === "dark" ? "#131415" : "#F9F9F9" //same as above
}`
: "none",
transition: "box-shadow .6s linear",
}}
>
<Flex my={10} ml={120}>
<AnimatedText visible={displayTitle}>
<Text variant="h3Inter" fontSize="8" fontWeight="semiBold">
{t("syncOnboarding.manual.title", { deviceName })}
</Text>
</AnimatedText>
</Flex>
<Link
m={12}
size="large"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,15 +481,12 @@ const SyncOnboardingCompanion: React.FC<SyncOnboardingCompanionProps> = ({
/>
<Flex
height="100%"
overflow="hidden"
width="432px"
width="480px"
flexDirection="column"
justifyContent="flex-start"
alignSelf="center"
overflowY="scroll"
flexGrow={0}
flexShrink={1}
pt={84}
>
<Text variant="h3Inter" fontSize="8" fontWeight="semiBold" mb="8">
{t("syncOnboarding.manual.title", { deviceName })}
Expand Down
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module "*.mp4";
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,16 @@ const SyncOnboardingScreen: React.FC<SyncOnboardingScreenProps> = ({
}
}, [history, isEarlySecurityChecks]);

const [contentScroll, setContentScroll] = useState(0);

const onContentScroll = (e: React.UIEvent<HTMLDivElement>) => {
const { currentTarget } = e;
if (currentTarget instanceof HTMLDivElement) {
const scrollTop = currentTarget.scrollTop;
setContentScroll(scrollTop);
}
};

let stepContent = (
<Flex height="100%" width="100%" justifyContent="center" alignItems="center">
<InfiniteLoader />
Expand Down Expand Up @@ -302,7 +312,14 @@ const SyncOnboardingScreen: React.FC<SyncOnboardingScreenProps> = ({
}, []);

return (
<Flex width="100%" height="100%" flexDirection="column" justifyContent="flex-start">
<Flex
width="100%"
height="100%"
overflow="scroll"
flexDirection="column"
justifyContent="flex-start"
onScroll={onContentScroll}
>
{isBootloader && mustRecoverIfBootloader ? (
/**
* In case a firmware update gets interrupted and the device is in
Expand All @@ -312,8 +329,12 @@ const SyncOnboardingScreen: React.FC<SyncOnboardingScreenProps> = ({
<DeviceAction onResult={onDeviceActionResult} action={action} request={null} />
) : (
<>
<Header
device={lastSeenDevice}
onClose={handleClose}
displayTitle={currentStep === "companion" && lastSeenDevice && contentScroll > 30}
/>
{stepContent}
<Header onClose={handleClose} />
</>
)}
</Flex>
Expand Down
1 change: 1 addition & 0 deletions apps/ledger-live-desktop/tools/config/common.esbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ module.exports = {
".ttf": "file",
".otf": "file",
".webm": "file",
".mp4": "file",
".png": "dataurl",
".jpg": "dataurl",
".jpeg": "dataurl",
Expand Down

1 comment on commit 4901a78

@vercel
Copy link

@vercel vercel bot commented on 4901a78 Aug 28, 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.