-
Notifications
You must be signed in to change notification settings - Fork 327
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🥅(lld): rework ui of node erros on send flow (#8075)
- Loading branch information
1 parent
17732b4
commit 77846a0
Showing
11 changed files
with
388 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"ledger-live-desktop": patch | ||
--- | ||
|
||
Change node errors UI on send flow when a tx failed |
19 changes: 19 additions & 0 deletions
19
apps/ledger-live-desktop/src/newArch/hooks/useCopyToClipboard.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { useCallback, useRef } from "react"; | ||
|
||
export function useCopyToClipboard(callback?: (text: string) => void) { | ||
const textRef = useRef<string>(); | ||
|
||
const copy = useCallback(() => { | ||
const text = textRef.current ?? ""; | ||
navigator.clipboard.writeText(text).then(() => { | ||
if (callback) { | ||
callback(text); | ||
} | ||
}); | ||
}, [callback]); | ||
|
||
return (text: string) => { | ||
textRef.current = text; | ||
copy(); | ||
}; | ||
} |
61 changes: 61 additions & 0 deletions
61
apps/ledger-live-desktop/src/newArch/hooks/useExportLogs.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import getUser from "~/helpers/user"; | ||
import { getAllEnvs } from "@ledgerhq/live-env"; | ||
import { webFrame, ipcRenderer } from "electron"; | ||
import { useCallback, useState } from "react"; | ||
import { useTechnicalDateTimeFn } from "~/renderer/hooks/useDateFormatter"; | ||
import logger, { memoryLogger } from "~/renderer/logger"; | ||
import { useSelector } from "react-redux"; | ||
import { accountsSelector } from "~/renderer/reducers/accounts"; | ||
|
||
export function useExportLogs() { | ||
const getDateTxt = useTechnicalDateTimeFn(); | ||
const accounts = useSelector(accountsSelector); | ||
const [exporting, setExporting] = useState(false); | ||
|
||
const saveLogs = useCallback(async (path: Electron.SaveDialogReturnValue) => { | ||
try { | ||
const memoryLogsStr = JSON.stringify(memoryLogger.getMemoryLogs(), null, 2); | ||
await ipcRenderer.invoke("save-logs", path, memoryLogsStr); | ||
} catch (error) { | ||
console.error("Error while requesting to save logs from the renderer process", error); | ||
} | ||
}, []); | ||
|
||
const exportLogs = useCallback(async () => { | ||
try { | ||
const resourceUsage = webFrame.getResourceUsage(); | ||
const user = await getUser(); | ||
logger.log("exportLogsMeta", { | ||
resourceUsage, | ||
release: __APP_VERSION__, | ||
git_commit: __GIT_REVISION__, | ||
environment: __DEV__ ? "development" : "production", | ||
userAgent: window.navigator.userAgent, | ||
userAnonymousId: user.id, | ||
env: getAllEnvs(), | ||
accountsIds: accounts.map(a => a.id), | ||
}); | ||
|
||
const path = await ipcRenderer.invoke("show-save-dialog", { | ||
title: "Export logs", | ||
defaultPath: `ledgerlive-logs-${getDateTxt()}-${__GIT_REVISION__ || "unversioned"}.json`, | ||
filters: [{ name: "All Files", extensions: ["json"] }], | ||
}); | ||
|
||
if (path) { | ||
await saveLogs(path); | ||
} | ||
} catch (error) { | ||
logger.critical(error as Error); | ||
} | ||
}, [accounts, getDateTxt, saveLogs]); | ||
|
||
const handleExportLogs = useCallback(async () => { | ||
if (exporting) return; | ||
setExporting(true); | ||
await exportLogs(); | ||
setExporting(false); | ||
}, [exporting, exportLogs]); | ||
|
||
return { handleExportLogs }; | ||
} |
58 changes: 58 additions & 0 deletions
58
...ledger-live-desktop/src/renderer/modals/Send/steps/Confirmation/NodeError/HelpSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import React from "react"; | ||
import { Flex, Text, Icons } from "@ledgerhq/react-ui"; | ||
import { useTranslation } from "react-i18next"; | ||
import styled from "styled-components"; | ||
|
||
type Props = { | ||
onGetHelp: () => void; | ||
}; | ||
|
||
const InteractFlex = styled(Flex)` | ||
&:hover { | ||
cursor: pointer; | ||
background-color: ${({ theme }) => theme.colors.palette.opacityDefault.c10}; | ||
} | ||
padding: 8px; | ||
background-color: ${({ theme }) => theme.colors.palette.opacityDefault.c05}; | ||
border-radius: 8px; | ||
column-gap: 8px; | ||
align-items: center; | ||
&:active { | ||
background-color: ${({ theme }) => theme.colors.palette.opacityDefault.c20}; | ||
} | ||
`; | ||
|
||
const StyledText = styled(Text)` | ||
word-break: break-all; | ||
`; | ||
|
||
const HelpSection = ({ onGetHelp }: Props) => { | ||
const { t } = useTranslation(); | ||
return ( | ||
<Flex | ||
alignItems="start" | ||
flexDirection="column" | ||
rowGap={2} | ||
bg="opacityDefault.c05" | ||
borderRadius={8} | ||
justifyContent="space-between" | ||
p={2} | ||
minHeight="128px" | ||
flex={1} | ||
> | ||
<Text variant="bodyLineHeight" fontSize={13}> | ||
{t("errors.TransactionBroadcastError.helpCenterTitle")} | ||
<Text color="neutral.c70">{t("errors.TransactionBroadcastError.helpCenterDesc")}</Text> | ||
</Text> | ||
<InteractFlex onClick={onGetHelp}> | ||
<Icons.Support color="neutral.c100" size="S" /> | ||
<StyledText variant="bodyLineHeight" fontSize={13}> | ||
{t("errors.TransactionBroadcastError.getHelp")} | ||
</StyledText> | ||
</InteractFlex> | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default HelpSection; |
77 changes: 77 additions & 0 deletions
77
...e-desktop/src/renderer/modals/Send/steps/Confirmation/NodeError/TechnicalErrorSection.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import React, { useState } from "react"; | ||
import { Flex, Text, Icons } from "@ledgerhq/react-ui"; | ||
import { useTranslation } from "react-i18next"; | ||
import styled from "styled-components"; | ||
import { useCopyToClipboard } from "~/newArch/hooks/useCopyToClipboard"; | ||
|
||
type Props = { | ||
error: Error; | ||
onSaveLogs: () => void; | ||
}; | ||
|
||
const InteractFlex = styled(Flex)` | ||
&:hover { | ||
cursor: pointer; | ||
background-color: ${({ theme }) => theme.colors.palette.opacityDefault.c10}; | ||
} | ||
padding: 8px; | ||
background-color: ${({ theme }) => theme.colors.palette.opacityDefault.c05}; | ||
border-radius: 8px; | ||
column-gap: 8px; | ||
align-items: center; | ||
&:active { | ||
background-color: ${({ theme }) => theme.colors.palette.opacityDefault.c20}; | ||
} | ||
`; | ||
|
||
const StyledText = styled(Text)` | ||
word-break: break-all; | ||
display: -webkit-box; | ||
-webkit-line-clamp: 3; | ||
-webkit-box-orient: vertical; | ||
overflow: hidden; | ||
`; | ||
|
||
const TechnicalErrorSection = ({ error, onSaveLogs }: Props) => { | ||
const { t } = useTranslation(); | ||
const [icon, setIcon] = useState(<Icons.Copy color="neutral.c100" size="S" />); | ||
|
||
const copyToClipboard = useCopyToClipboard(_text => { | ||
setIcon(<Icons.Check color="success.c50" size="S" />); | ||
setTimeout(() => { | ||
setIcon(<Icons.Copy color="neutral.c100" size="S" />); | ||
}, 5000); | ||
}); | ||
|
||
const handleCopyError = () => { | ||
copyToClipboard(error.message); | ||
}; | ||
|
||
return ( | ||
<Flex | ||
alignItems="flex-start" | ||
flexDirection="column" | ||
bg="opacityDefault.c05" | ||
borderRadius={8} | ||
justifyContent="space-between" | ||
p={2} | ||
> | ||
<StyledText variant="bodyLineHeight" fontSize={13} width="100%"> | ||
{t("errors.TransactionBroadcastError.technicalErrorTitle")} | ||
<Text color="neutral.c70">{error.message}</Text> | ||
</StyledText> | ||
<Flex columnGap={2}> | ||
<InteractFlex onClick={onSaveLogs}> | ||
<Icons.Download color="neutral.c100" size="S" /> | ||
<Text variant="bodyLineHeight" fontSize={13}> | ||
{t("errors.TransactionBroadcastError.saveLogs")} | ||
</Text> | ||
</InteractFlex> | ||
<InteractFlex onClick={handleCopyError}>{icon}</InteractFlex> | ||
</Flex> | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default TechnicalErrorSection; |
98 changes: 98 additions & 0 deletions
98
apps/ledger-live-desktop/src/renderer/modals/Send/steps/Confirmation/NodeError/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import React, { useState } from "react"; | ||
import { Flex, Grid, Icons, Text } from "@ledgerhq/react-ui"; | ||
import styled, { useTheme } from "styled-components"; | ||
import { CircleWrapper } from "~/renderer/components/CryptoCurrencyIcon"; | ||
import { useExportLogs } from "LLD/hooks/useExportLogs"; | ||
import { TransactionBroadcastError } from "@ledgerhq/live-common/errors/transactionBroadcastErrors"; | ||
import { urls } from "~/config/urls"; | ||
import { openURL } from "~/renderer/linking"; | ||
import { useLocalizedUrl } from "~/renderer/hooks/useLocalizedUrls"; | ||
import { useTranslation } from "react-i18next"; | ||
import TechnicalErrorSection from "./TechnicalErrorSection"; | ||
import HelpSection from "./HelpSection"; | ||
import TranslatedError from "~/renderer/components/TranslatedError"; | ||
import { ErrorBody } from "~/renderer/components/ErrorBody"; | ||
|
||
type Props = { | ||
error: TransactionBroadcastError; | ||
}; | ||
|
||
const InteractFlex = styled(Flex)` | ||
&:hover { | ||
cursor: pointer; | ||
} | ||
`; | ||
|
||
const NodeError: React.FC<Props> = ({ error }) => { | ||
const theme = useTheme(); | ||
const { t } = useTranslation(); | ||
const { handleExportLogs } = useExportLogs(); | ||
|
||
const { coin: currencyName, network: networkName, url } = error; | ||
const supportUrl = url ?? urls.contactSupport; | ||
const localizedSupportUrl = useLocalizedUrl(supportUrl); | ||
|
||
const [isShowMore, setIsShowMore] = useState(true); | ||
|
||
const color = theme.colors.palette.opacityDefault.c05; | ||
|
||
const onSaveLogs = () => handleExportLogs(); | ||
|
||
const onGetHelp = () => openURL(localizedSupportUrl); | ||
|
||
const onShowMore = () => setIsShowMore(!isShowMore); | ||
|
||
return ( | ||
<Flex | ||
justifyContent="center" | ||
alignItems="center" | ||
width={"90%"} | ||
rowGap={32} | ||
flexDirection="column" | ||
> | ||
<Flex justifyContent="center" flexDirection="column"> | ||
<ErrorBody | ||
title={ | ||
<Text variant="h3Inter" fontSize={24} textAlign="center"> | ||
<TranslatedError error={error} /> | ||
</Text> | ||
} | ||
description={ | ||
<Text variant="bodyLineHeight" fontSize={14} textAlign="center" color="neutral.c70"> | ||
{t("errors.TransactionBroadcastError.description", { | ||
networkName, | ||
currencyName, | ||
})} | ||
</Text> | ||
} | ||
top={ | ||
<CircleWrapper size={72} color={color}> | ||
<Icons.DeleteCircleFill size="L" color="error.c50" /> | ||
</CircleWrapper> | ||
} | ||
/> | ||
</Flex> | ||
<Flex flexDirection="column" rowGap={16} width="100%" alignItems="flex-start"> | ||
<InteractFlex alignItems="center" onClick={onShowMore}> | ||
<Text variant="bodyLineHeight" fontSize={13}> | ||
{t("errors.TransactionBroadcastError.needHelp")} | ||
</Text> | ||
|
||
{isShowMore ? ( | ||
<Icons.ChevronDown color="neutral.c100" size="S" /> | ||
) : ( | ||
<Icons.ChevronRight color="neutral.c100" size="S" /> | ||
)} | ||
</InteractFlex> | ||
{isShowMore && ( | ||
<Grid columns={2} columnGap="8px" width="100%"> | ||
<HelpSection onGetHelp={onGetHelp} /> | ||
<TechnicalErrorSection error={error} onSaveLogs={onSaveLogs} /> | ||
</Grid> | ||
)} | ||
</Flex> | ||
</Flex> | ||
); | ||
}; | ||
|
||
export default NodeError; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.