From f55c6e4f9027e8277553af44334026a70ee3bdaa Mon Sep 17 00:00:00 2001 From: ofreyssinet-ledger <91890529+ofreyssinet-ledger@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:45:11 +0200 Subject: [PATCH] Feat/live 8375 fw update redesign (#4471) * feat(llm/fwupdatebanner): new design * fix(llm/fwupdatebanner): loading state * chore: changeset * chore(llm): remove unimported code * chore(llm): cleanup comments * fix(llm/fwupdatebanner): loader color --- .changeset/eighty-hornets-suffer.md | 5 + .../src/components/FirmwareUpdateBanner.tsx | 105 +++++++++--------- .../src/components/theme/InvertTheme.tsx | 14 --- .../src/locales/en/common.json | 5 + .../src/screens/Manager/AppsScreen.tsx | 13 ++- .../src/screens/Manager/Device/index.tsx | 18 ++- 6 files changed, 84 insertions(+), 76 deletions(-) create mode 100644 .changeset/eighty-hornets-suffer.md delete mode 100644 apps/ledger-live-mobile/src/components/theme/InvertTheme.tsx diff --git a/.changeset/eighty-hornets-suffer.md b/.changeset/eighty-hornets-suffer.md new file mode 100644 index 000000000000..9e30ce618d8c --- /dev/null +++ b/.changeset/eighty-hornets-suffer.md @@ -0,0 +1,5 @@ +--- +"live-mobile": patch +--- + +New firmware update flow: redesign of fw update available banner diff --git a/apps/ledger-live-mobile/src/components/FirmwareUpdateBanner.tsx b/apps/ledger-live-mobile/src/components/FirmwareUpdateBanner.tsx index 503f26aad231..58f84acd4097 100644 --- a/apps/ledger-live-mobile/src/components/FirmwareUpdateBanner.tsx +++ b/apps/ledger-live-mobile/src/components/FirmwareUpdateBanner.tsx @@ -1,10 +1,18 @@ import React, { useState, useCallback, useEffect } from "react"; -import { Platform, Linking } from "react-native"; +import { Platform, Pressable } from "react-native"; import { useNavigation, useRoute, useTheme } from "@react-navigation/native"; import { DeviceModelInfo } from "@ledgerhq/types-live"; import { useTranslation } from "react-i18next"; import { useSelector } from "react-redux"; -import { Alert, Text, Flex, IconsLegacy, IconBadge, ProgressLoader } from "@ledgerhq/native-ui"; +import { + Alert, + Text, + Flex, + IconsLegacy, + IconBadge, + Icons, + InfiniteLoader, +} from "@ledgerhq/native-ui"; import { DownloadMedium, UsbMedium } from "@ledgerhq/native-ui/assets/icons"; import { DeviceModelId, getDeviceModel } from "@ledgerhq/devices"; import { useFeature } from "@ledgerhq/live-common/featureFlags/index"; @@ -24,8 +32,6 @@ import { import { hasConnectedDeviceSelector } from "../reducers/appstate"; import Button from "./Button"; import QueuedDrawer from "./QueuedDrawer"; -import InvertTheme from "./theme/InvertTheme"; -import { urls } from "../config/urls"; import { renderConnectYourDevice } from "./DeviceAction/rendering"; import { DeviceActionError } from "./DeviceAction/common"; import { UpdateStep } from "../screens/FirmwareUpdate"; @@ -48,7 +54,7 @@ const FirmwareUpdateBanner = ({ onBackFromUpdate }: FirmwareUpdateBannerProps) = const { dark } = useTheme(); const theme: "dark" | "light" = dark ? "dark" : "light"; - const [disableUpdateButton, setDisableUpdateButton] = useState(false); + const [loading, setLoading] = useState(false); const [showBatteryWarningDrawer, setShowBatteryWarningDrawer] = useState(false); const [showUnsupportedUpdateDrawer, setShowUnsupportedUpdateDrawer] = useState(false); @@ -124,7 +130,7 @@ const FirmwareUpdateBanner = ({ onBackFromUpdate }: FirmwareUpdateBannerProps) = ? setShowBatteryWarningDrawer(true) : onExperimentalFirmwareUpdate(); - setDisableUpdateButton(false); + setLoading(false); } }, [ batteryRequestCompleted, @@ -140,12 +146,6 @@ const FirmwareUpdateBanner = ({ onBackFromUpdate }: FirmwareUpdateBannerProps) = setShowUnsupportedUpdateDrawer(false); }, []); - const onOpenReleaseNotes = useCallback(() => { - if (lastConnectedDevice) { - Linking.openURL(urls.fwUpdateReleaseNotes[lastConnectedDevice?.modelId]); - } - }, [lastConnectedDevice]); - const isUsbFwVersionUpdateSupported = lastSeenDevice && isFirmwareUpdateVersionSupported(lastSeenDevice.deviceInfo, lastSeenDevice.modelId); @@ -161,7 +161,7 @@ const FirmwareUpdateBanner = ({ onBackFromUpdate }: FirmwareUpdateBannerProps) = if (lastConnectedDevice?.modelId === DeviceModelId.stax && newFwUpdateUxFeatureFlag?.enabled) { // This leads to a check on the battery before triggering update, it is only necessary for Stax and on the new UX // (because it's the only type of update that can happen via BLE) - setDisableUpdateButton(true); + setLoading(true); triggerBatteryCheck(); } // Path with any device model, wired and on android @@ -179,50 +179,51 @@ const FirmwareUpdateBanner = ({ onBackFromUpdate }: FirmwareUpdateBannerProps) = onExperimentalFirmwareUpdate, ]); - const deviceName = lastConnectedDevice + const productName = lastConnectedDevice ? getDeviceModel(lastConnectedDevice.modelId).productName - : ""; + : undefined; + + const deviceName = lastConnectedDevice?.deviceName; return showBanner && hasCompletedOnboarding && hasConnectedDevice ? ( <> {newFwUpdateUxFeatureFlag?.enabled ? ( - - - - - {t("FirmwareUpdate.newVersion", { - version, - deviceName, - })} - - - - - + + + + {loading ? ( + + ) : lastConnectedDevice?.modelId === DeviceModelId.stax ? ( + + ) : ( + + )} - - + + + {t("FirmwareUpdate.banner.title")} + + + {deviceName + ? t("FirmwareUpdate.banner.descriptionDeviceName", { + deviceName, + firmwareVersion: version, + }) + : t("FirmwareUpdate.banner.descriptionProductName", { + productName, + firmwareVersion: version, + })} + + + + ) : ( @@ -294,7 +295,7 @@ const FirmwareUpdateBanner = ({ onBackFromUpdate }: FirmwareUpdateBannerProps) = } onClose={() => { cancelBatteryCheck(); - setDisableUpdateButton(false); + setLoading(false); }} > {lastConnectedDevice && ( diff --git a/apps/ledger-live-mobile/src/components/theme/InvertTheme.tsx b/apps/ledger-live-mobile/src/components/theme/InvertTheme.tsx deleted file mode 100644 index 3b1ceb3f0192..000000000000 --- a/apps/ledger-live-mobile/src/components/theme/InvertTheme.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from "react"; -import { useTheme } from "styled-components/native"; -import StyleProvider from "../../StyleProvider"; - -export default function InvertTheme({ - children, -}: { - children?: React.ReactNode; -}): React.ReactElement { - const { theme } = useTheme(); - const revertTheme = theme === "light" ? "dark" : "light"; - - return {children}; -} diff --git a/apps/ledger-live-mobile/src/locales/en/common.json b/apps/ledger-live-mobile/src/locales/en/common.json index e39bd622e07a..adda5b30df08 100644 --- a/apps/ledger-live-mobile/src/locales/en/common.json +++ b/apps/ledger-live-mobile/src/locales/en/common.json @@ -4116,6 +4116,11 @@ "action": "Update" }, "FirmwareUpdate": { + "banner": { + "title": "OS update available", + "descriptionDeviceName": "Tap to update “{{deviceName}}” to OS version {{firmwareVersion}}.", + "descriptionProductName": "Tap to update your {{productName}} to OS version {{firmwareVersion}}." + }, "title": "Update firmware", "beginUpdate": "Begin update", "updateDevice": "{{deviceName}} OS Update", diff --git a/apps/ledger-live-mobile/src/screens/Manager/AppsScreen.tsx b/apps/ledger-live-mobile/src/screens/Manager/AppsScreen.tsx index b25d7c01b8ea..4b3ea3c4fce4 100644 --- a/apps/ledger-live-mobile/src/screens/Manager/AppsScreen.tsx +++ b/apps/ledger-live-mobile/src/screens/Manager/AppsScreen.tsx @@ -259,11 +259,6 @@ const AppsScreen = ({ data={items} ListHeaderComponent={ - {showFwUpdateBanner && newFwUpdateUxFeatureFlag?.enabled ? ( - - - - ) : null} + > + {showFwUpdateBanner && newFwUpdateUxFeatureFlag?.enabled ? ( + + + + ) : null} + {showFwUpdateBanner && !newFwUpdateUxFeatureFlag?.enabled ? ( diff --git a/apps/ledger-live-mobile/src/screens/Manager/Device/index.tsx b/apps/ledger-live-mobile/src/screens/Manager/Device/index.tsx index 2c199186a065..19c0310a489a 100644 --- a/apps/ledger-live-mobile/src/screens/Manager/Device/index.tsx +++ b/apps/ledger-live-mobile/src/screens/Manager/Device/index.tsx @@ -1,4 +1,12 @@ -import React, { useRef, useEffect, memo, useCallback, useMemo, useState } from "react"; +import React, { + useRef, + useEffect, + memo, + useCallback, + useMemo, + useState, + PropsWithChildren, +} from "react"; import { useSelector } from "react-redux"; import { Trans } from "react-i18next"; @@ -33,7 +41,7 @@ const illustrations = { stax: Stax, }; -type Props = { +type Props = PropsWithChildren<{ distribution: AppsDistribution; state: State; result: ListAppsResult; @@ -46,12 +54,12 @@ type Props = { dispatch: (action: Action) => void; appList: App[]; onLanguageChange: () => void; -}; +}>; const BorderCard = styled.View` flex-direction: column; border: 1px solid ${p => p.theme.colors.neutral.c40}; - border-radius: 4px; + border-radius: 8px; `; const DeviceCard = ({ @@ -65,6 +73,7 @@ const DeviceCard = ({ dispatch, appList, onLanguageChange, + children, }: Props) => { const { colors, theme } = useTheme(); const lastSeenCustomImage = useSelector(lastSeenCustomImageSelector); @@ -110,6 +119,7 @@ const DeviceCard = ({ return ( + {children} {illustration}