From 144f3e26c52906fee3beb05a1d48e78acc57136f Mon Sep 17 00:00:00 2001 From: PhilReact Date: Tue, 19 Nov 2024 08:25:25 +0200 Subject: [PATCH] added wallets page --- src/App.tsx | 40 +++- src/ExtStates/NotAuthenticated.tsx | 19 +- src/Wallets.tsx | 344 +++++++++++++++++++++++++++++ src/background.ts | 17 ++ 4 files changed, 404 insertions(+), 16 deletions(-) create mode 100644 src/Wallets.tsx diff --git a/src/App.tsx b/src/App.tsx index 3f555f4..87f63b0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -122,6 +122,7 @@ import { import { fileToBase64 } from "./utils/fileReading"; import { handleGetFileFromIndexedDB } from "./utils/indexedDB"; import { CoreSyncStatus } from "./components/CoreSyncStatus"; +import { Wallets } from "./Wallets"; type extStates = | "not-authenticated" @@ -137,6 +138,7 @@ type extStates = | "wallet-dropped" | "web-app-request-buy-order" | "buy-order-submitted" + | "wallets" | "group"; interface MyContextInterface { @@ -238,6 +240,8 @@ export const resumeAllQueues = () => { }); }; + + export const MyContext = createContext(defaultValues); export let globalApiKey: string | null = null; @@ -2184,9 +2188,9 @@ function App() { )} - {rawWallet && extState === "wallet-dropped" && ( + {extState === "wallets" && ( <> - + + + + + )} + {rawWallet && extState === "wallet-dropped" && ( + <> + + + { + setRawWallet(null); + setExtstate("wallets"); + logoutFunc(); + }} + src={Return} + /> +
+ {rawWallet?.name ? rawWallet?.name : rawWallet?.address0} + - - - Authenticate + setExtstate('wallets')}> + {/* */} + Wallets - + {/* - + */} @@ -288,7 +287,6 @@ export const NotAuthenticated = ({ display: "flex", gap: "10px", alignItems: "center", - marginLeft: "28px", }} > - + diff --git a/src/Wallets.tsx b/src/Wallets.tsx new file mode 100644 index 0000000..1de70d6 --- /dev/null +++ b/src/Wallets.tsx @@ -0,0 +1,344 @@ +import React, { useEffect, useRef, useState } from "react"; +import List from "@mui/material/List"; +import ListItem from "@mui/material/ListItem"; +import Divider from "@mui/material/Divider"; +import ListItemText from "@mui/material/ListItemText"; +import ListItemAvatar from "@mui/material/ListItemAvatar"; +import Avatar from "@mui/material/Avatar"; +import Typography from "@mui/material/Typography"; +import { Box, Button, ButtonBase, IconButton, Input } from "@mui/material"; +import { CustomButton } from "./App-styles"; +import { useDropzone } from "react-dropzone"; +import EditIcon from "@mui/icons-material/Edit"; +import { Label } from "./components/Group/AddGroup"; +import { Spacer } from "./common/Spacer"; +import { getWallets, storeWallets } from "./background"; + +const parsefilenameQortal = (filename)=> { + return filename.startsWith("qortal_backup_") ? filename.slice(14) : filename; + } + +export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => { + const [wallets, setWallets] = useState([]); + const [isLoading, setIsLoading] = useState(false); + + const hasFetchedWalletsRef = useRef(false) + const { getRootProps, getInputProps } = useDropzone({ + accept: { + "application/json": [".json"], // Only accept JSON files + }, + onDrop: async (acceptedFiles) => { + const files: any = acceptedFiles; + let importedWallets: any = []; + + for (const file of files) { + try { + const fileContents = await new Promise((resolve, reject) => { + const reader = new FileReader(); + + reader.onabort = () => reject("File reading was aborted"); + reader.onerror = () => reject("File reading has failed"); + reader.onload = () => { + // Resolve the promise with the reader result when reading completes + resolve(reader.result); + }; + + // Read the file as text + reader.readAsText(file); + }); + if (typeof fileContents !== "string") continue; + const parsedData = JSON.parse(fileContents) + importedWallets.push({...parsedData, filename: file?.name}); + } catch (error) { + console.error(error); + } + } + + let error: any = null; + let uniqueInitialMap = new Map(); + + // Only add a message if it doesn't already exist in the Map + importedWallets.forEach((wallet) => { + if (!wallet?.address0) return; + if (!uniqueInitialMap.has(wallet?.address0)) { + uniqueInitialMap.set(wallet?.address0, wallet); + } + }); + const data = Array.from(uniqueInitialMap.values()); + if (data && data?.length > 0) { + const uniqueNewWallets = data.filter( + (newWallet) => + !wallets.some( + (existingWallet) => + existingWallet?.address0 === newWallet?.address0 + ) + ); + setWallets([...wallets, ...uniqueNewWallets]); + } + }, + }); + + const updateWalletItem = (idx, wallet) => { + setWallets((prev) => { + let copyPrev = [...prev]; + if (wallet === null) { + console.log("entered"); + copyPrev.splice(idx, 1); // Use splice to remove the item + return copyPrev; + } else { + copyPrev[idx] = wallet; // Update the wallet at the specified index + return copyPrev; + } + }); + }; + + const selectedWalletFunc = (wallet) => { + setRawWallet(wallet); + setExtState("wallet-dropped"); + }; + + useEffect(()=> { + setIsLoading(true) + getWallets().then((res)=> { + hasFetchedWalletsRef.current = true + if(res && Array.isArray(res)){ + setWallets(res) + } + setIsLoading(false) + }).catch((error)=> { + console.error(error) + setIsLoading(false) + }) + }, []) + + useEffect(()=> { + if(hasFetchedWalletsRef.current && wallets && Array.isArray(wallets)){ + storeWallets(wallets) + } + }, [wallets]) + + if(isLoading) return null + + return ( +
+ {(wallets?.length === 0 || + !wallets) ? ( + <> + No wallets saved + + + ): ( + <> + Your saved wallets + + + )} + + {rawWallet && ( + + Selected Wallet: + {rawWallet?.name && {rawWallet.name}} + {rawWallet?.address0 && ( + {rawWallet?.address0} + )} + + )} + {wallets?.length > 0 && ( + + {wallets?.map((wallet, idx) => { + return ( + <> + + + + ); + })} + + )} + + + + + Add wallets + + +
+ ); +}; + +const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => { + const [name, setName] = useState(""); + const [note, setNote] = useState(""); + const [isEdit, setIsEdit] = useState(false); + + useEffect(() => { + if (wallet?.name) { + setName(wallet.name); + } + if (wallet?.note) { + setNote(wallet.note); + } + }, [wallet]); + return ( + <> + { + setSelectedWallet(wallet); + }} + sx={{ + width: '100%' + }} + > + { + e.stopPropagation(); + setIsEdit(true); + }} + edge="end" + aria-label="edit" + > + + + } + alignItems="flex-start" + > + + + + + + {wallet?.address0} + + {wallet?.note} + + } + /> + + + {isEdit && ( + + + setName(e.target.value)} + sx={{ + width: "100%", + }} + /> + + + setNote(e.target.value)} + inputProps={{ + maxLength: 100, + }} + sx={{ + width: "100%", + }} + /> + + + + + + + + )} + + ); +}; diff --git a/src/background.ts b/src/background.ts index 0997354..75951f7 100644 --- a/src/background.ts +++ b/src/background.ts @@ -851,6 +851,23 @@ export async function getSaveWallet() { } } +export async function getWallets() { + const res = await getData("wallets").catch(() => null); + if (res) { + return res; + } else { + throw new Error("No wallet saved"); + } +} + +export async function storeWallets(wallets) { + storeData("wallets", wallets) + .catch((error) => { + reject(new Error(error.message || "Error saving data")); + }); +} + + export async function clearAllNotifications() { // const notifications = await chrome.notifications.getAll(); // for (const notificationId of Object.keys(notifications)) {