diff --git a/src/pages/addresses/AddressButtonRow.tsx b/src/pages/addresses/AddressButtonRow.tsx index 638914e..b97744b 100644 --- a/src/pages/addresses/AddressButtonRow.tsx +++ b/src/pages/addresses/AddressButtonRow.tsx @@ -1,73 +1,161 @@ // Copyright (c) 2020-2021 Drew Lemmy // This file is part of KristWeb 2 under AGPL-3.0. // Full details: https://github.com/tmpim/KristWeb2/blob/master/LICENSE.txt -import { Button, Tooltip } from "antd"; +import { useEffect } from "react"; +import { Button, Tooltip, Menu } from "antd"; import { SendOutlined, SwapOutlined, UserAddOutlined, EditOutlined } from "@ant-design/icons"; -import { useTranslation } from "react-i18next"; +import { useTFns } from "@utils/i18n"; import { isV1Address } from "@utils/currency"; -import { KristAddressWithNames } from "@api/lookup"; import { Wallet } from "@wallets"; import { Contact } from "@contacts"; -import { WalletEditButton } from "../wallets/WalletEditButton"; -import { ContactEditButton } from "../contacts/ContactEditButton"; -import { SendTransactionModalLink } from "@comp/transactions/SendTransactionModalLink"; + +import { useTopMenuOptions } from "@layout/nav/TopMenu"; +import { useAuth } from "@comp/auth"; +import { OpenEditWalletFn } from "@pages/wallets/WalletEditButton"; +import { OpenEditContactFn } from "@pages/contacts/ContactEditButton"; +import { OpenSendTxFn } from "@comp/transactions/SendTransactionModalLink"; interface Props { - address: KristAddressWithNames; + address: string; myWallet?: Wallet; myContact?: Contact; + + openEditWallet: OpenEditWalletFn; + openEditContact: OpenEditContactFn; + openSendTx: OpenSendTxFn; } export function AddressButtonRow({ address, myWallet, - myContact -}: Props): JSX.Element { - const { t } = useTranslation(); + myContact, - const isV1 = address && isV1Address(address.address); + openEditWallet, + openEditContact, + openSendTx +}: Props): JSX.Element { + const { t, tStr, tKey } = useTFns("address."); + + const isV1 = isV1Address(address); + + const promptAuth = useAuth(); + + const [usingTopMenu, set, unset] = useTopMenuOptions(); + useEffect(() => { + set(<> + {/* Send/transfer Krist */} + : } + disabled={isV1} + onClick={() => promptAuth(false, () => + openSendTx(undefined, address))} + > + {t( + tKey(myWallet ? "buttonTransferKrist" : "buttonSendKrist"), + { address } + )} + + + {/* Add contact/edit wallet */} + {myWallet + ? ( + } + onClick={() => promptAuth(true, () => openEditWallet(myWallet))} + > + {tStr("buttonEditWallet")} + + ) + : ( + : } + onClick={() => openEditContact(address, myContact)} + > + {tStr(myContact ? "buttonEditContact" : "buttonAddContact")} + + ) + } + ); + return unset; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + t, tStr, tKey, set, unset, address, openSendTx, openEditWallet, + openEditContact, isV1, promptAuth, myContact?.id, myWallet?.id + ]); + + return <> + {/* Only display the buttons on desktop */} + {!usingTopMenu && } + ; +} + +function Buttons({ + address, + myWallet, + myContact, + isV1, + + openEditWallet, + openEditContact, + openSendTx +}: Props & { isV1: boolean }): JSX.Element { + const { t, tStr, tKey } = useTFns("address."); + + const promptAuth = useAuth(); const sendButton = ; return <> {/* Send/transfer Krist button */} {isV1 ? ( // Disable the button and show a tooltip for V1 addresses - + {sendButton} ) - : ( // Otherwise, enable the button - - {sendButton} - - )} + : sendButton // Otherwise, enable the button + } {/* Add contact/edit wallet button */} {myWallet ? ( - - - + ) : ( - - - + )} ; } diff --git a/src/pages/addresses/AddressPage.tsx b/src/pages/addresses/AddressPage.tsx index b08e932..ea2f716 100644 --- a/src/pages/addresses/AddressPage.tsx +++ b/src/pages/addresses/AddressPage.tsx @@ -27,6 +27,10 @@ import { getVerified, VerifiedDescription } from "@comp/addresses/VerifiedAddress"; +import { useEditWalletModal } from "@pages/wallets/WalletEditButton"; +import { useEditContactModal } from "@pages/contacts/ContactEditButton"; +import { useSendTransactionModal } from "@comp/transactions/SendTransactionModalLink"; + import "./AddressPage.less"; const { Text } = Typography; @@ -54,6 +58,10 @@ const showVerifiedDesc = verified?.description || verified?.website || verified?.isActive === false; + const [openEditWallet, editWalletModal] = useEditWalletModal(); + const [openEditContact, editContactModal] = useEditContactModal(); + const [openSendTx, sendTxModal] = useSendTransactionModal(); + return <> {/* Address and buttons */} @@ -64,9 +72,13 @@ {/* Buttons (e.g. Send Krist, Add contact) */} @@ -150,6 +162,10 @@ + + {sendTxModal} + {editWalletModal} + {editContactModal} ; } diff --git a/src/pages/contacts/AddContactModal.tsx b/src/pages/contacts/AddContactModal.tsx index 6786816..090389a 100644 --- a/src/pages/contacts/AddContactModal.tsx +++ b/src/pages/contacts/AddContactModal.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2020-2021 Drew Lemmy // This file is part of KristWeb 2 under AGPL-3.0. // Full details: https://github.com/tmpim/KristWeb2/blob/master/LICENSE.txt -import { useState } from "react"; +import { useState, useEffect, useMemo } from "react"; import { Modal, Form, Input, message, notification } from "antd"; import { useTFns } from "@utils/i18n"; @@ -104,6 +104,20 @@ setAddress(values.address || ""); } + const initialValues = useMemo(() => ({ + label: editing?.label ?? undefined, + address: editing?.address ?? initialAddress + }), [ + initialAddress, editing?.label, editing?.address + ]); + + // Refresh the form if the initial values have changed + useEffect(() => { + if (!form || (!initialAddress && !editing?.address)) return; + form.setFieldsValue(initialValues); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [form, initialAddress, editing?.label, editing?.address]); + return promptAuth(true, () => openEditContact(contact))} + onClick={() => promptAuth(true, () => openEditContact(undefined, contact))} trigger={["click"]} overlay={() => ( diff --git a/src/pages/contacts/ContactEditButton.tsx b/src/pages/contacts/ContactEditButton.tsx index 1683998..0bdf71f 100644 --- a/src/pages/contacts/ContactEditButton.tsx +++ b/src/pages/contacts/ContactEditButton.tsx @@ -36,7 +36,7 @@ ; }; -export type OpenEditContactFn = (contact: Contact) => void; +export type OpenEditContactFn = (address?: string, contact?: Contact) => void; export type ContactEditHookRes = [ OpenEditContactFn, JSX.Element | null, @@ -46,16 +46,23 @@ export function useEditContactModal(): ContactEditHookRes { const [opened, setOpened] = useState(false); const [visible, setVisible] = useState(false); + const [address, setAddress] = useState(); const [contact, setContact] = useState(); - const open = useCallback((contact: Contact) => { + const open = useCallback((address?: string, contact?: Contact) => { + setAddress(address); setContact(contact); setVisible(true); setOpened(true); }, []); const modal = opened - ? + ? : null; return [open, modal, setVisible]; diff --git a/src/pages/names/NameButtonRow.tsx b/src/pages/names/NameButtonRow.tsx index df25b52..9817d36 100644 --- a/src/pages/names/NameButtonRow.tsx +++ b/src/pages/names/NameButtonRow.tsx @@ -1,67 +1,148 @@ // Copyright (c) 2020-2021 Drew Lemmy // This file is part of KristWeb 2 under AGPL-3.0. // Full details: https://github.com/tmpim/KristWeb2/blob/master/LICENSE.txt -import { Button } from "antd"; +import { useEffect } from "react"; +import { Button, Menu, Space } from "antd"; import { SendOutlined, SwapOutlined, EditOutlined } from "@ant-design/icons"; -import { useTranslation } from "react-i18next"; +import { useTFns } from "@utils/i18n"; import { KristName } from "@api/types"; -import { Wallet } from "@wallets"; -import { SendTransactionModalLink } from "@comp/transactions/SendTransactionModalLink"; -import { NameEditModalLink } from "./mgmt/NameEditModalLink"; + +import { useTopMenuOptions } from "@layout/nav/TopMenu"; +import { useAuth } from "@comp/auth"; +import { OpenEditNameFn } from "./mgmt/NameEditModalLink"; +import { OpenSendTxFn } from "@comp/transactions/SendTransactionModalLink"; interface Props { name: KristName; nameWithSuffix: string; - myWallet?: Wallet; + myWallet: boolean; + + openNameEdit: OpenEditNameFn; + openSendTx: OpenSendTxFn; } -export function NameButtonRow({ name, nameWithSuffix, myWallet }: Props): JSX.Element { - const { t } = useTranslation(); +export function NameButtonRow({ + name, + nameWithSuffix, + myWallet, - return <> - {/* Send/transfer Krist button */} - - - + + + {myWallet && } + + {/* Update A record */} + {myWallet && ( + } + onClick={() => promptAuth(false, () => + openNameEdit("update", name.name, name.a))} + > + {tStr("buttonARecord")} + + )} + + {/* Transfer name record */} + {myWallet && ( + } + danger + onClick={() => promptAuth(false, () => + openNameEdit("transfer", name.name))} + > + {tStr("buttonTransferName")} + + )} + ); + return unset; + }, [ + t, tStr, tKey, set, unset, nameWithSuffix, openSendTx, openNameEdit, + name.name, name.a, myWallet, promptAuth + ]); + + return <> + {/* Only display the buttons on desktop */} + {!usingTopMenu && } + ; +} + +function Buttons({ + name, + nameWithSuffix, + myWallet, + + openNameEdit, + openSendTx +}: Props): JSX.Element { + const { t, tStr, tKey } = useTFns("name."); + + const promptAuth = useAuth(); + + return + {/* Send/transfer Krist button */} + {/* If we're the name owner, show the management buttons */} {/* Update A record button */} {myWallet && ( - } + onClick={() => promptAuth(false, () => + openNameEdit("update", name.name, name.a))} > - - + {tStr("buttonARecord")} + )} {/* Transfer name button */} {myWallet && ( - promptAuth(false, () => + openNameEdit("transfer", name.name))} > - - + {tStr("buttonTransferName")} + )} - ; + ; } diff --git a/src/pages/names/NamePage.tsx b/src/pages/names/NamePage.tsx index 17ad543..d1a90d7 100644 --- a/src/pages/names/NamePage.tsx +++ b/src/pages/names/NamePage.tsx @@ -27,7 +27,10 @@ import { NameButtonRow } from "./NameButtonRow"; import { NameTransactionsCard } from "./NameTransactionsCard"; -import { NameEditModalLink } from "./mgmt/NameEditModalLink"; + +import { useAuth } from "@comp/auth"; +import { useNameEditModal } from "./mgmt/NameEditModalLink"; +import { useSendTransactionModal } from "@comp/transactions/SendTransactionModalLink"; import "./NamePage.less"; @@ -57,6 +60,10 @@ const nameCopyText = copyNameSuffixes ? nameWithSuffix : name.name; + const promptAuth = useAuth(); + const [openNameEdit, nameEditModal] = useNameEditModal(); + const [openSendTx, sendTxModal] = useSendTransactionModal(); + return <> {/* Name and buttons */} @@ -69,7 +76,10 @@ @@ -131,15 +141,12 @@ titleKey="name.aRecord" titleExtra={myWallet && <> - - - - - + promptAuth(false, () => + openNameEdit("update", name.name, name.a))}> + + } value={} @@ -168,6 +175,9 @@ /> + + {nameEditModal} + {sendTxModal} ; }