Refactor based on code review. Improved typing of useCookie hook. Added duration/delay to control length of toast.

This commit is contained in:
Dan Ditomaso
2025-01-14 21:51:06 -05:00
parent 07d4204e86
commit 7884991ac6
6 changed files with 221 additions and 143 deletions
+54 -31
View File
@@ -1,3 +1,5 @@
import { useDevice } from "@app/core/stores/deviceStore";
import { Button } from "@components/UI/Button";
import {
Dialog,
DialogContent,
@@ -6,11 +8,9 @@ import {
DialogHeader,
DialogTitle,
} from "@components/UI/Dialog.tsx";
import { Button } from "@components/UI/Button";
import { fromByteArray } from "base64-js";
import { DownloadIcon, PrinterIcon } from "lucide-react";
import React from "react";
import { useDevice } from "@app/core/stores/deviceStore";
import { fromByteArray } from "base64-js";
export interface PkiBackupDialogProps {
open: boolean;
@@ -22,26 +22,30 @@ export const PkiBackupDialog = ({
onOpenChange,
}: PkiBackupDialogProps) => {
const { config, setDialogOpen } = useDevice();
const privateKeyData = config.security?.privateKey
const privateKey = config.security?.privateKey;
const publicKey = config.security?.publicKey;
// If the private data doesn't exist return null
if (!privateKeyData) {
return null
}
const getPrivateKey = React.useMemo(() => fromByteArray(config.security?.privateKey ?? new Uint8Array(0)), [config.security?.privateKey]);
const decodeKeyData = React.useCallback(
(key: Uint8Array<ArrayBufferLike>) => {
if (!key) return "";
return fromByteArray(key ?? new Uint8Array(0));
},
[],
);
const closeDialog = React.useCallback(() => {
setDialogOpen("pkiBackup", false)
}, [setDialogOpen])
setDialogOpen("pkiBackup", false);
}, [setDialogOpen]);
const renderPrintWindow = React.useCallback(() => {
if (!privateKey || !publicKey) return;
const printWindow = window.open("", "_blank");
if (printWindow) {
printWindow.document.write(`
<html>
<head>
<title>Your Private Key</title>
<title>=== MESHTASTIC KEYS ===</title>
<style>
body { font-family: Arial, sans-serif; padding: 20px; }
h1 { font-size: 18px; }
@@ -49,58 +53,77 @@ export const PkiBackupDialog = ({
</style>
</head>
<body>
<h1>Your Private Key</h1>
<p>${getPrivateKey}</p>
<h1>=== MESHTASTIC KEYS ===</h1>
<br>
<h2>Public Key:</h2>
<p>${decodeKeyData(publicKey)}</p>
<h2>Private Key:</h2>
<p>${decodeKeyData(privateKey)}</p>
<br>
<p>=== END OF KEYS ===</p>
</body>
</html>
`);
printWindow.document.close();
printWindow.print();
closeDialog()
closeDialog();
}
}, [getPrivateKey, closeDialog]);
}, [decodeKeyData, privateKey, publicKey, closeDialog]);
const createDownloadKeyFile = React.useCallback(() => {
const blob = new Blob([getPrivateKey], { type: "text/plain" });
if (!privateKey || !publicKey) return;
const decodedPrivateKey = decodeKeyData(privateKey);
const decodedPublicKey = decodeKeyData(publicKey);
const formattedContent = [
"=== MESHTASTIC KEYS ===\n\n",
"Private Key:\n",
decodedPrivateKey,
"\n\nPublic Key:\n",
decodedPublicKey,
"\n\n=== END OF KEYS ===",
].join("");
const blob = new Blob([formattedContent], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = "meshtastic_private_key.txt";
link.download = "meshtastic_keys.txt";
link.style.display = "none";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
closeDialog()
closeDialog();
URL.revokeObjectURL(url);
}, [getPrivateKey, closeDialog]);
}, [decodeKeyData, privateKey, publicKey, closeDialog]);
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent>
<DialogHeader>
<DialogTitle>Backup Key</DialogTitle>
<DialogTitle>Backup Keys</DialogTitle>
<DialogDescription>
Its important to backup your private key and store your backup securely!
Its important to backup your public and private keys and store your
backup securely!
</DialogDescription>
<DialogDescription>
<span className="font-bold break-before-auto">If you lose your private key, you will need to reset your device.</span>
<span className="font-bold break-before-auto">
If you lose your keys, you will need to reset your device.
</span>
</DialogDescription>
</DialogHeader>
<DialogFooter className="mt-6">
<Button
variant={'default'}
variant={"default"}
onClick={() => createDownloadKeyFile()}
className=""
>
<DownloadIcon size={20} className="mr-2" />
Download
</Button>
<Button
variant={'default'}
onClick={() => renderPrintWindow()}
>
<Button variant={"default"} onClick={() => renderPrintWindow()}>
<PrinterIcon size={20} className="mr-2" />
Print
</Button>