diff --git a/src-gui/src/renderer/components/alert/SwapStatusAlert.tsx b/src-gui/src/renderer/components/alert/SwapStatusAlert.tsx index 1fa17491..502fb35d 100644 --- a/src-gui/src/renderer/components/alert/SwapStatusAlert.tsx +++ b/src-gui/src/renderer/components/alert/SwapStatusAlert.tsx @@ -216,7 +216,7 @@ export default function SwapStatusAlert({ } + action={Resume Swap} variant="filled" > diff --git a/src-gui/src/renderer/components/modal/swap/DepositAddressInfoBox.tsx b/src-gui/src/renderer/components/modal/swap/DepositAddressInfoBox.tsx index 6e96d186..c228e33f 100644 --- a/src-gui/src/renderer/components/modal/swap/DepositAddressInfoBox.tsx +++ b/src-gui/src/renderer/components/modal/swap/DepositAddressInfoBox.tsx @@ -1,7 +1,6 @@ import { Box } from "@material-ui/core"; import { ReactNode } from "react"; -import CopyableMonospaceTextBox from "renderer/components/other/CopyableMonospaceTextBox"; -import BitcoinQrCode from "./BitcoinQrCode"; +import ActionableMonospaceTextBox from "renderer/components/other/ActionableMonospaceTextBox"; import InfoBox from "./InfoBox"; type Props = { @@ -20,7 +19,7 @@ export default function DepositAddressInfoBox({ return ( } + mainContent={} additionalContent={ {additionalContent} - } icon={icon} diff --git a/src-gui/src/renderer/components/other/ActionableMonospaceTextBox.tsx b/src-gui/src/renderer/components/other/ActionableMonospaceTextBox.tsx new file mode 100644 index 00000000..2cb228fa --- /dev/null +++ b/src-gui/src/renderer/components/other/ActionableMonospaceTextBox.tsx @@ -0,0 +1,120 @@ +import { Box, Button, IconButton, Tooltip, makeStyles } from "@material-ui/core"; +import { FileCopyOutlined, CropFree as CropFreeIcon } from "@material-ui/icons"; +import { writeText } from "@tauri-apps/plugin-clipboard-manager"; +import { useState } from "react"; +import MonospaceTextBox from "./MonospaceTextBox"; +import { Modal } from "@material-ui/core"; +import QRCode from "react-qr-code"; + +type ModalProps = { + open: boolean; + onClose: () => void; + content: string; +}; + +type Props = { + content: string; + displayCopyIcon?: boolean; + enableQrCode?: boolean; +}; + +const useStyles = makeStyles((theme) => ({ + container: { + display: "flex", + alignItems: "center", + cursor: "pointer", + }, + textBoxWrapper: { + flexGrow: 1, + }, + iconButton: { + marginLeft: theme.spacing(1), + }, + modalContent: { + display: "flex", + flexDirection: "column", + gap: theme.spacing(2), + justifyContent: "center", + alignItems: "center", + height: "100%", + }, + qrCode: { + maxWidth: "90%", + maxHeight: "90%", + }, +})); + +function QRCodeModal({ open, onClose, content }: ModalProps) { + const classes = useStyles(); + return ( + + + + + + + ); +} + +export default function ActionableMonospaceTextBox({ + content, + displayCopyIcon = true, + enableQrCode = true, +}: Props) { + const classes = useStyles(); + const [copied, setCopied] = useState(false); + const [qrCodeOpen, setQrCodeOpen] = useState(false); + const [isQrCodeButtonHovered, setIsQrCodeButtonHovered] = useState(false); + + const handleCopy = async () => { + await writeText(content); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + }; + + return ( + <> + + + + + {content} + {displayCopyIcon && ( + + + + )} + {enableQrCode && ( + + setQrCodeOpen(true)} + onMouseEnter={() => setIsQrCodeButtonHovered(true)} + onMouseLeave={() => setIsQrCodeButtonHovered(false)} + size="small" + className={classes.iconButton} + > + + + + )} + + + + + {enableQrCode && ( + setQrCodeOpen(false)} + content={content} + /> + )} + + ); +} \ No newline at end of file diff --git a/src-gui/src/renderer/components/other/CopyableMonospaceTextBox.tsx b/src-gui/src/renderer/components/other/CopyableMonospaceTextBox.tsx deleted file mode 100644 index 81f7f97a..00000000 --- a/src-gui/src/renderer/components/other/CopyableMonospaceTextBox.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { Box, Tooltip } from "@material-ui/core"; -import { FileCopyOutlined } from "@material-ui/icons"; -import { writeText } from "@tauri-apps/plugin-clipboard-manager"; -import { useState } from "react"; -import MonospaceTextBox from "./MonospaceTextBox"; - -type Props = { - address: string; - noIcon?: boolean; -}; - -/** Display addresses monospaced and clickable such that a click copies the address to the clipboard. */ -export default function CopyableMonospaceTextBox({ - address, - noIcon = false, -}: Props) { - // Signal that the address was copied - const [copied, setCopied] = useState(false); - const tooltip = copied ? "Copied to clipboard" : "Click to copy"; - - // Copy address to clipboard on-click - const handleClick = async () => { - // Copy to clipboard - await writeText(address); - // Change tooltip to show that we copied the address - setCopied(true); - // After a delay, show default tooltip again (2sec) - setTimeout(() => setCopied(false), 2_000); - }; - - // Apply icon unless specified otherwise - const icon = noIcon ? null : ; - - return ( - - {/* Div is necessary to make the tooltip work */} - - - - - ); -} diff --git a/src-gui/src/renderer/components/other/MonospaceTextBox.tsx b/src-gui/src/renderer/components/other/MonospaceTextBox.tsx index 3775c117..96a518a8 100644 --- a/src-gui/src/renderer/components/other/MonospaceTextBox.tsx +++ b/src-gui/src/renderer/components/other/MonospaceTextBox.tsx @@ -1,10 +1,7 @@ import { Box, Typography, makeStyles } from "@material-ui/core"; -import { ReactNode } from "react"; type Props = { - content: string; - onClick?: (content: string) => void; - endIcon?: ReactNode; + children: React.ReactNode; }; const useStyles = makeStyles((theme) => ({ @@ -14,31 +11,25 @@ const useStyles = makeStyles((theme) => ({ backgroundColor: theme.palette.grey[900], borderRadius: theme.shape.borderRadius, padding: theme.spacing(1), - gap: theme.spacing(1), }, content: { wordBreak: "break-word", whiteSpace: "pre-wrap", fontFamily: "monospace", - lineHeight: "1.5em", + lineHeight: 1.5, + display: "flex", + alignItems: "center", }, })); -export default function MonospaceTextBox({ content, endIcon, onClick }: Props) { +export default function MonospaceTextBox({ children }: Props) { const classes = useStyles(); - const handleClick = () => onClick?.(content); - return ( - - - {content} + + + {children} - {endIcon} ); -} +} \ No newline at end of file diff --git a/src-gui/src/renderer/components/pages/history/table/HistoryRowExpanded.tsx b/src-gui/src/renderer/components/pages/history/table/HistoryRowExpanded.tsx index 3af1f78a..d3a3892f 100644 --- a/src-gui/src/renderer/components/pages/history/table/HistoryRowExpanded.tsx +++ b/src-gui/src/renderer/components/pages/history/table/HistoryRowExpanded.tsx @@ -10,7 +10,7 @@ import { } from "@material-ui/core"; import { OpenInNew } from "@material-ui/icons"; import { GetSwapInfoResponse } from "models/tauriModel"; -import CopyableMonospaceTextBox from "renderer/components/other/CopyableMonospaceTextBox"; +import ActionableMonospaceTextBox from "renderer/components/other/ActionableMonospaceTextBox"; import MonospaceTextBox from "renderer/components/other/MonospaceTextBox"; import { MoneroBitcoinExchangeRate, @@ -90,7 +90,7 @@ export default function HistoryRowExpanded({ {swap.seller.addresses.map((addr) => ( - + ))}