From c33693b4e61418800f664d682b58f92fbd6accf5 Mon Sep 17 00:00:00 2001 From: apoorvlathey Date: Thu, 15 Jun 2023 03:38:10 +0530 Subject: [PATCH] add address book --- package.json | 8 +- src/components/Body/AddressInput.tsx | 83 --------- .../Body/AddressInput/AddressBook/index.tsx | 160 ++++++++++++++++++ src/components/Body/AddressInput/index.tsx | 106 ++++++++++++ src/components/Body/TransactionRequests.tsx | 2 +- yarn.lock | 8 +- 6 files changed, 278 insertions(+), 89 deletions(-) delete mode 100644 src/components/Body/AddressInput.tsx create mode 100644 src/components/Body/AddressInput/AddressBook/index.tsx create mode 100644 src/components/Body/AddressInput/index.tsx diff --git a/package.json b/package.json index 00f12cd..e97fe03 100644 --- a/package.json +++ b/package.json @@ -58,5 +58,11 @@ ">0.2%", "not dead", "not op_mini all" - ] + ], + "resolutions": { + "react-error-overlay": "6.0.9" + }, + "devDependencies": { + "react-error-overlay": "6.0.9" + } } diff --git a/src/components/Body/AddressInput.tsx b/src/components/Body/AddressInput.tsx deleted file mode 100644 index 2e34ec6..0000000 --- a/src/components/Body/AddressInput.tsx +++ /dev/null @@ -1,83 +0,0 @@ -import { - FormControl, - FormLabel, - InputGroup, - Input, - InputRightElement, - Button, -} from "@chakra-ui/react"; -import { DeleteIcon } from "@chakra-ui/icons"; - -interface AddressInputParams { - showAddress: string; - setShowAddress: (value: string) => void; - setAddress: (value: string) => void; - setIsAddressValid: (value: boolean) => void; - bg: string; - isAddressValid: boolean; - selectedTabIndex: number; - isConnected: boolean; - appUrl: string | undefined; - isIFrameLoading: boolean; - updateAddress: () => void; -} - -function AddressInput({ - showAddress, - setShowAddress, - setAddress, - setIsAddressValid, - bg, - isAddressValid, - selectedTabIndex, - isConnected, - appUrl, - isIFrameLoading, - updateAddress, -}: AddressInputParams) { - return ( - - Enter Address or ENS to Impersonate - - { - const _showAddress = e.target.value; - setShowAddress(_showAddress); - setAddress(_showAddress); - setIsAddressValid(true); // remove inValid warning when user types again - }} - bg={bg} - isInvalid={!isAddressValid} - /> - {(selectedTabIndex === 0 && isConnected) || - (selectedTabIndex === 1 && appUrl && !isIFrameLoading) ? ( - - - - ) : ( - showAddress && ( - - - - ) - )} - - - ); -} - -export default AddressInput; diff --git a/src/components/Body/AddressInput/AddressBook/index.tsx b/src/components/Body/AddressInput/AddressBook/index.tsx new file mode 100644 index 0000000..2a4e587 --- /dev/null +++ b/src/components/Body/AddressInput/AddressBook/index.tsx @@ -0,0 +1,160 @@ +import { useState, useEffect } from "react"; +import { + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + HStack, + ModalCloseButton, + ModalBody, + Text, + Input, + Center, + Button, + Box, +} from "@chakra-ui/react"; +import { DeleteIcon } from "@chakra-ui/icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faSave } from "@fortawesome/free-solid-svg-icons"; +import { slicedText } from "../../TransactionRequests"; + +const STORAGE_KEY = "address-book"; + +interface SavedAddressInfo { + address: string; + label: string; +} + +interface AddressBookParams { + isAddressBookOpen: boolean; + closeAddressBook: () => void; + showAddress: string; + setShowAddress: (value: string) => void; + setAddress: (value: string) => void; +} + +function AddressBook({ + isAddressBookOpen, + closeAddressBook, + showAddress, + setShowAddress, + setAddress, +}: AddressBookParams) { + const [newAddressInput, setNewAddressInput] = useState(""); + const [newLableInput, setNewLabelInput] = useState(""); + const [savedAddresses, setSavedAddresses] = useState([]); + + useEffect(() => { + setSavedAddresses(JSON.parse(localStorage.getItem(STORAGE_KEY) ?? "[]")); + }, []); + + useEffect(() => { + setNewAddressInput(showAddress); + }, [showAddress]); + + useEffect(() => { + localStorage.setItem(STORAGE_KEY, JSON.stringify(savedAddresses)); + }, [savedAddresses]); + + // reset label when modal is reopened + useEffect(() => { + setNewLabelInput(""); + }, [isAddressBookOpen]); + + return ( + + + + Address Book + + + + setNewAddressInput(e.target.value)} + /> + setNewLabelInput(e.target.value)} + /> + +
+ +
+ {savedAddresses.length > 0 && ( + + Select from saved addresses: + + {savedAddresses.map(({ address, label }, i) => ( + + + + + ))} + + + )} +
+
+
+ ); +} + +export default AddressBook; diff --git a/src/components/Body/AddressInput/index.tsx b/src/components/Body/AddressInput/index.tsx new file mode 100644 index 0000000..3142624 --- /dev/null +++ b/src/components/Body/AddressInput/index.tsx @@ -0,0 +1,106 @@ +import { + FormControl, + FormLabel, + InputGroup, + Input, + InputRightElement, + Button, + HStack, + useDisclosure, +} from "@chakra-ui/react"; +import { DeleteIcon } from "@chakra-ui/icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faBook } from "@fortawesome/free-solid-svg-icons"; +import AddressBook from "./AddressBook"; + +interface AddressInputParams { + showAddress: string; + setShowAddress: (value: string) => void; + setAddress: (value: string) => void; + setIsAddressValid: (value: boolean) => void; + bg: string; + isAddressValid: boolean; + selectedTabIndex: number; + isConnected: boolean; + appUrl: string | undefined; + isIFrameLoading: boolean; + updateAddress: () => void; +} + +function AddressInput({ + showAddress, + setShowAddress, + setAddress, + setIsAddressValid, + bg, + isAddressValid, + selectedTabIndex, + isConnected, + appUrl, + isIFrameLoading, + updateAddress, +}: AddressInputParams) { + const { + isOpen: isAddressBookOpen, + onOpen: openAddressBook, + onClose: closeAddressBook, + } = useDisclosure(); + + return ( + + Enter Address or ENS to Impersonate + + + { + const _showAddress = e.target.value; + setShowAddress(_showAddress); + setAddress(_showAddress); + setIsAddressValid(true); // remove inValid warning when user types again + }} + bg={bg} + isInvalid={!isAddressValid} + /> + {(selectedTabIndex === 0 && isConnected) || + (selectedTabIndex === 1 && appUrl && !isIFrameLoading) ? ( + + + + ) : ( + showAddress && ( + + + + ) + )} + + + + + + ); +} + +export default AddressInput; diff --git a/src/components/Body/TransactionRequests.tsx b/src/components/Body/TransactionRequests.tsx index a58225f..65131e5 100644 --- a/src/components/Body/TransactionRequests.tsx +++ b/src/components/Body/TransactionRequests.tsx @@ -26,7 +26,7 @@ import { import CopyToClipboard from "./CopyToClipboard"; import { TxnDataType } from "../../types"; -const slicedText = (txt: string) => { +export const slicedText = (txt: string) => { return txt.length > 6 ? `${txt.slice(0, 4)}...${txt.slice(txt.length - 2, txt.length)}` : txt; diff --git a/yarn.lock b/yarn.lock index bf08ef0..a8b75a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11492,10 +11492,10 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" -react-error-overlay@^6.0.9: - version "6.0.11" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" - integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== +react-error-overlay@6.0.9, react-error-overlay@^6.0.9: + version "6.0.9" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" + integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== react-fast-compare@3.2.0: version "3.2.0"