diff --git a/public/locales/en.json b/public/locales/en.json index 4db219b..d6bdb35 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -602,7 +602,18 @@ "columnARecord": "A Record", "columnUnpaid": "Unpaid Blocks", + "mobileOwner": "<0>Owner: <1 />", + "mobileOriginalOwner": "<0>Original owner: <1 />", + "mobileRegistered": "Registered: <1 />", + "mobileUpdated": "Updated: <1 />", + "mobileARecordTag": "A", + "mobileUnpaidTag": "{{count, number}} block", + "mobileUnpaidTag_plural": "{{count, number}} blocks", + "actions": "Actions", + "actionsViewName": "View name", + "actionsViewOwner": "View owner's address", + "actionsViewOriginalOwner": "View original owner's address", "actionsSendKrist": "Send Krist", "actionsTransferKrist": "Transfer Krist", "actionsUpdateARecord": "Update A record", @@ -1141,7 +1152,15 @@ "transactionsTo": "To", "transactionsValue": "Value", "transactionsName": "Name", - "transactionsTime": "Time" + "transactionsTime": "Time", + + "namesName": "Name", + "namesOwner": "Owner", + "namesOriginalOwner": "Original Owner", + "namesARecord": "A Record", + "namesUnpaid": "Unpaid Blocks", + "namesRegistered": "Registered Time", + "namesUpdated": "Updated Time" } } } diff --git a/src/pages/contacts/ContactMobileItem.tsx b/src/pages/contacts/ContactMobileItem.tsx index 93779cb..2382076 100644 --- a/src/pages/contacts/ContactMobileItem.tsx +++ b/src/pages/contacts/ContactMobileItem.tsx @@ -1,28 +1,17 @@ // 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 { useCallback, useMemo } from "react"; -import { Collapse, Menu } from "antd"; -import { - ProfileOutlined, SendOutlined, EditOutlined, DeleteOutlined -} from "@ant-design/icons"; - -import { useTFns } from "@utils/i18n"; - -import { useHistory } from "react-router-dom"; +import { useMemo } from "react"; +import { Collapse } from "antd"; import { Contact } from "@contacts"; -import { - useAddressPrefix, useNameSuffix, - isValidAddress, getNameParts -} from "@utils/krist"; import { ContextualAddress } from "@comp/addresses/ContextualAddress"; -import { useAuth } from "@comp/auth"; import { OpenEditContactFn } from "./ContactEditButton"; import { OpenSendTxFn } from "@comp/transactions/SendTransactionModalLink"; -import { showContactDeleteConfirmModal } from "./ContactActions"; + +import { ContactMobileItemActions } from "./ContactsMobileItemActions"; interface Props { contact: Contact; @@ -67,61 +56,3 @@ ; } - -function ContactMobileItemActions({ - contact, - openEditContact, - openSendTx -}: Props): JSX.Element { - const { t, tStr } = useTFns("addressBook."); - - const history = useHistory(); - const promptAuth = useAuth(); - - const showContactDeleteConfirm = useCallback( - () => showContactDeleteConfirmModal(t, tStr, contact), - [t, tStr, contact] - ); - - const addressPrefix = useAddressPrefix(); - const nameSuffix = useNameSuffix(); - - const isAddress = isValidAddress(addressPrefix, contact.address); - const nameParts = getNameParts(nameSuffix, contact.address); - - const contactLink = !isAddress && nameParts?.name - ? `/network/names/${encodeURIComponent(nameParts.name)}` - : `/network/addresses/${encodeURIComponent(contact.address)}`; - - return - {/* View address or name */} - } - onClick={() => history.push(contactLink)}> - {tStr(isAddress ? "actionsViewAddress" : "actionsViewName")} - - - {/* Send Krist */} - } - onClick={() => promptAuth(false, () => - openSendTx(undefined, contact.address))}> - {tStr("actionsSendTransaction")} - - - - - {/* Edit contact */} - } - onClick={() => promptAuth(false, () => - openEditContact(undefined, contact))}> - {tStr("actionsEditTooltip")} - - - - - {/* Delete wallet */} - } - onClick={showContactDeleteConfirm}> - {tStr("actionsDelete")} - - ; -} diff --git a/src/pages/contacts/ContactsMobileItemActions.tsx b/src/pages/contacts/ContactsMobileItemActions.tsx new file mode 100644 index 0000000..86d40fb --- /dev/null +++ b/src/pages/contacts/ContactsMobileItemActions.tsx @@ -0,0 +1,88 @@ +// 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 { useCallback } from "react"; +import { Menu } from "antd"; +import { + ProfileOutlined, SendOutlined, EditOutlined, DeleteOutlined +} from "@ant-design/icons"; + +import { useTFns } from "@utils/i18n"; + +import { useHistory } from "react-router-dom"; + +import { Contact } from "@contacts"; +import { + useAddressPrefix, useNameSuffix, + isValidAddress, getNameParts +} from "@utils/krist"; + +import { useAuth } from "@comp/auth"; +import { OpenEditContactFn } from "./ContactEditButton"; +import { OpenSendTxFn } from "@comp/transactions/SendTransactionModalLink"; +import { showContactDeleteConfirmModal } from "./ContactActions"; + +interface Props { + contact: Contact; + + openEditContact: OpenEditContactFn; + openSendTx: OpenSendTxFn; +} + +export function ContactMobileItemActions({ + contact, + openEditContact, + openSendTx +}: Props): JSX.Element { + const { t, tStr } = useTFns("addressBook."); + + const history = useHistory(); + const promptAuth = useAuth(); + + const showContactDeleteConfirm = useCallback( + () => showContactDeleteConfirmModal(t, tStr, contact), + [t, tStr, contact] + ); + + const addressPrefix = useAddressPrefix(); + const nameSuffix = useNameSuffix(); + + const isAddress = isValidAddress(addressPrefix, contact.address); + const nameParts = getNameParts(nameSuffix, contact.address); + + const contactLink = !isAddress && nameParts?.name + ? `/network/names/${encodeURIComponent(nameParts.name)}` + : `/network/addresses/${encodeURIComponent(contact.address)}`; + + return + {/* View address or name */} + } + onClick={() => history.push(contactLink)}> + {tStr(isAddress ? "actionsViewAddress" : "actionsViewName")} + + + {/* Send Krist */} + } + onClick={() => promptAuth(false, () => + openSendTx(undefined, contact.address))}> + {tStr("actionsSendTransaction")} + + + + + {/* Edit contact */} + } + onClick={() => promptAuth(false, () => + openEditContact(undefined, contact))}> + {tStr("actionsEditTooltip")} + + + + + {/* Delete wallet */} + } + onClick={showContactDeleteConfirm}> + {tStr("actionsDelete")} + + ; +} diff --git a/src/pages/names/NameMobileItem.tsx b/src/pages/names/NameMobileItem.tsx new file mode 100644 index 0000000..4c4a78e --- /dev/null +++ b/src/pages/names/NameMobileItem.tsx @@ -0,0 +1,114 @@ +// 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 { useMemo } from "react"; +import { Collapse, Tag } from "antd"; + +import { Trans } from "react-i18next"; +import { useTFns } from "@utils/i18n"; + +import { KristName } from "@api/types"; +import { useWallets } from "@wallets"; + +import { KristNameLink } from "@comp/names/KristNameLink"; +import { ContextualAddress } from "@comp/addresses/ContextualAddress"; +import { DateTime } from "@comp/DateTime"; + +import { OpenEditNameFn } from "./mgmt/NameEditModalLink"; +import { OpenSendTxFn } from "@comp/transactions/SendTransactionModalLink"; + +import { NameMobileItemActions } from "./NameMobileItemActions"; + +interface Props { + name: KristName; + + openNameEdit: OpenEditNameFn; + openSendTx: OpenSendTxFn; +} + +export function NameMobileItem({ + name, + openNameEdit, + openSendTx +}: Props): JSX.Element { + const { t, tStr, tKey } = useTFns("names."); + + // Used to change the actions depending on whether or not we own the name + const { walletAddressMap } = useWallets(); + const isOwn = !!walletAddressMap[name.owner]; + + const hasARecord = !!name.a; + const isUnpaid = name.unpaid > 0; + const hasTags = hasARecord || isUnpaid; + + const itemHead = useMemo(() => ( +
+ {/* Tags (A record, unpaid blocks) */} + {hasTags &&
+ {/* A record */} + {hasARecord && {tStr("mobileARecordTag")}} + + {/* Unpaid blocks */} + {isUnpaid && ( + + {t(tKey("mobileUnpaidTag"), { count: name.unpaid })} + + )} +
} + + {/* Name */} + + + {/* Owner */} +
+ + Owner: + + +
+ + {/* Original owner */} + {name.original_owner && name.owner !== name.original_owner && ( +
+ + Original owner: + + +
+ )} + + {/* Registered/updated date */} + {name.updated + ? ( +
+ + Updated: + +
+ ) + : ( +
+ + Registered: + +
+ )} +
+ ), [ + t, tStr, tKey, + hasTags, hasARecord, isUnpaid, + name.name, name.unpaid, name.owner, name.original_owner, + name.updated, name.registered + ]); + + return + + + + ; +} diff --git a/src/pages/names/NameMobileItemActions.tsx b/src/pages/names/NameMobileItemActions.tsx new file mode 100644 index 0000000..bdf72bd --- /dev/null +++ b/src/pages/names/NameMobileItemActions.tsx @@ -0,0 +1,92 @@ +// 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 { Menu } from "antd"; +import { + ProfileOutlined, SwapOutlined, SendOutlined, EditOutlined +} from "@ant-design/icons"; + +import { useTFns } from "@utils/i18n"; + +import { useHistory } from "react-router-dom"; + +import { KristName } from "@api/types"; +import { useNameSuffix } from "@utils/krist"; + +import { useAuth } from "@comp/auth"; +import { OpenEditNameFn } from "./mgmt/NameEditModalLink"; +import { OpenSendTxFn } from "@comp/transactions/SendTransactionModalLink"; + +interface Props { + name: KristName; + isOwn: boolean; + + openNameEdit: OpenEditNameFn; + openSendTx: OpenSendTxFn; +} + +export function NameMobileItemActions({ + name, isOwn, + openNameEdit, + openSendTx +}: Props): JSX.Element { + const { tStr } = useTFns("names."); + + const history = useHistory(); + const promptAuth = useAuth(); + + const nameSuffix = useNameSuffix(); + const nameWithSuffix = `${name.name}.${nameSuffix}`; + + const nameLink = `/network/names/${encodeURIComponent(name.name)}`; + const ownerLink = `/network/addresses/${encodeURIComponent(name.owner)}`; + const originalOwnerLink = name.original_owner && name.owner !== name.original_owner + ? `/network/addresses/${encodeURIComponent(name.original_owner)}` + : undefined; + + return + {/* View name */} + } + onClick={() => history.push(nameLink)}> + {tStr("actionsViewName")} + + + {/* View owner address */} + } + onClick={() => history.push(ownerLink)}> + {tStr("actionsViewOwner")} + + + {/* View original owner address */} + {originalOwnerLink && } + onClick={() => history.push(originalOwnerLink)}> + {tStr("actionsViewOriginalOwner")} + } + + {/* Send/transfer Krist */} + : } + onClick={() => promptAuth(false, () => + openSendTx(undefined, nameWithSuffix))}> + {tStr(isOwn ? "actionsTransferKrist" : "actionsSendKrist")} + + + {/* Name management actions if we own the name */} + {isOwn && <> + + + {/* Update A record */} + } + onClick={() => promptAuth(false, () => + openNameEdit("update", name.name, name.a))}> + {tStr("actionsUpdateARecord")} + + + {/* Transfer name */} + } + onClick={() => promptAuth(false, () => + openNameEdit("transfer", name.name))}> + {tStr("actionsTransferName")} + + } + ; +} diff --git a/src/pages/names/NamesPage.less b/src/pages/names/NamesPage.less index e98d96d..3f70613 100644 --- a/src/pages/names/NamesPage.less +++ b/src/pages/names/NamesPage.less @@ -2,6 +2,7 @@ // This file is part of KristWeb 2 under AGPL-3.0. // Full details: https://github.com/tmpim/KristWeb2/blob/master/LICENSE.txt @import (reference) "../../App.less"; +@import "../../style/table.less"; .names-page { // Highlight unpaid names @@ -25,6 +26,35 @@ } } + .table-mobile-list-view { + .name-mobile-item { + .name-name { + display: block; + font-size: 120%; + } + + .name-tags { + float: right; + + .ant-tag { + white-space: nowrap; + } + } + + .name-field { + font-weight: bold; + white-space: nowrap; + color: @text-color-secondary; + } + + .name-registered, .name-updated { + margin-top: @padding-xss; + color: @text-color-secondary; + font-size: @font-size-sm; + } + } + } + @media (max-width: @screen-sm) { // Make the "Purchase name" button full width on mobile .ant-page-header-heading-extra { diff --git a/src/pages/names/NamesPage.tsx b/src/pages/names/NamesPage.tsx index 532ab91..182f015 100644 --- a/src/pages/names/NamesPage.tsx +++ b/src/pages/names/NamesPage.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, useMemo } from "react"; +import { useState, useMemo, useEffect } from "react"; import { Button } from "antd"; import { TagsOutlined } from "@ant-design/icons"; @@ -23,6 +23,7 @@ import { useWallets } from "@wallets"; import { useBooleanSetting } from "@utils/settings"; +import { useTopMenuOptions } from "@layout/nav/TopMenu"; import "./NamesPage.less"; @@ -92,6 +93,9 @@ : lastNameTransactionID) : 0; + const [,, unset, setOpenSortModal] = useTopMenuOptions(); + useEffect(() => unset, [unset]); + // Memoise the table so that it only updates the props (thus triggering a // re-fetch of the names) when something relevant changes const memoTable = useMemo(() => ( @@ -103,9 +107,11 @@ openNameEdit={openNameEdit} openSendTx={openSendTx} + setOpenSortModal={setOpenSortModal} /> ), [ - usedAddresses, sortNew, usedRefreshID, setError, openSendTx, openNameEdit + usedAddresses, sortNew, usedRefreshID, setError, openSendTx, openNameEdit, + setOpenSortModal ]); const siteTitle = getSiteTitle(t, listingType, address); diff --git a/src/pages/names/NamesTable.tsx b/src/pages/names/NamesTable.tsx index 1c9be60..a8f6149 100644 --- a/src/pages/names/NamesTable.tsx +++ b/src/pages/names/NamesTable.tsx @@ -8,13 +8,19 @@ import { useTFns, TStrFn } from "@utils/i18n"; import { KristName } from "@api/types"; -import { lookupNames, LookupNamesOptions, LookupNamesResponse } from "@api/lookup"; import { - useMalleablePagination, useTableHistory, useDateColumnWidth + lookupNames, LookupNamesOptions, LookupNamesResponse, + SortableNameFields +} from "@api/lookup"; +import { + useMalleablePagination, useTableHistory, useDateColumnWidth, useMobileList, + PaginationTableProps, RenderItem, SortOptions, SetOpenSortModalFn } from "@utils/table/table"; import { useWallets, WalletAddressMap } from "@wallets"; import { NameActions } from "./mgmt/NameActions"; +import { NameMobileItem } from "./NameMobileItem"; + import { OpenEditNameFn } from "./mgmt/NameEditModalLink"; import { OpenSendTxFn } from "@comp/transactions/SendTransactionModalLink"; import { useNameTableLock } from "./tableLock"; @@ -27,21 +33,6 @@ import Debug from "debug"; const debug = Debug("kristweb:names-table"); -interface Props { - // Number used to trigger a refresh of the names listing - refreshingID?: number; - - // Whether or not to sort by newest first by default - sortNew?: boolean; - - addresses?: string[]; - setError?: Dispatch>; - setPagination?: Dispatch>; - - openNameEdit: OpenEditNameFn; - openSendTx: OpenSendTxFn; -} - function getColumns( tStr: TStrFn, dateColumnWidth: number, @@ -157,6 +148,32 @@ ]; } +const sortOptions: SortOptions = [ + { sortKey: "name", i18nKey: "namesName" }, + { sortKey: "owner", i18nKey: "namesOwner" }, + { sortKey: "original_owner", i18nKey: "namesOriginalOwner" }, + { sortKey: "a", i18nKey: "namesARecord" }, + { sortKey: "unpaid", i18nKey: "namesUnpaid" }, + { sortKey: "registered", i18nKey: "namesRegistered" }, + { sortKey: "updated", i18nKey: "namesUpdated" } +]; + +interface Props { + // Number used to trigger a refresh of the names listing + refreshingID?: number; + + // Whether or not to sort by newest first by default + sortNew?: boolean; + + addresses?: string[]; + setError?: Dispatch>; + setPagination?: Dispatch>; + + openNameEdit: OpenEditNameFn; + openSendTx: OpenSendTxFn; + setOpenSortModal?: SetOpenSortModalFn; +} + export function NamesTable({ refreshingID, @@ -165,35 +182,28 @@ addresses, setError, setPagination, + setOpenSortModal, openNameEdit, openSendTx }: Props): JSX.Element { - const { tStr, tKey } = useTFns("names."); + const { tKey } = useTFns("names."); + + const defaultOrderBy = sortNew ? "registered" : "name"; + const defaultOrder = sortNew ? "DESC" : "ASC"; const [loading, setLoading] = useState(true); const [res, setRes] = useState(); const { options, setOptions } = useTableHistory({ - orderBy: sortNew ? "registered" : "name", - order: sortNew ? "DESC" : "ASC" + orderBy: defaultOrderBy, order: defaultOrder }); - const { paginationTableProps, hotkeys } = useMalleablePagination( + const { paginationTableProps, paginationChange, hotkeys } = useMalleablePagination( res, res?.names, tKey("tableTotal"), options, setOptions, setPagination ); - const dateColumnWidth = useDateColumnWidth(); - - // Used to change the actions depending on whether or not we own the name - const { walletAddressMap, joinedAddressList } = useWallets(); - - const columns = useMemo(() => getColumns( - tStr, dateColumnWidth, sortNew, walletAddressMap, openNameEdit, openSendTx - // eslint-disable-next-line react-hooks/exhaustive-deps - ), [tStr, dateColumnWidth, sortNew, joinedAddressList, openNameEdit, openSendTx]); - // Used to pause the table lookups when performing a bulk name edit const locked = useNameTableLock(); @@ -215,10 +225,74 @@ debug("results? %b res.names.length: %d res.count: %d res.total: %d", !!res, res?.names?.length, res?.count, res?.total); + const renderMobileItem: RenderItem = useCallback(name => ( + + ), [openNameEdit, openSendTx]); + + const { isMobile, list } = useMobileList( + loading, res?.names || [], "name", + paginationTableProps.pagination, paginationChange, + sortOptions, defaultOrderBy, defaultOrder, + options, setOptions, setOpenSortModal, + renderMobileItem + ); + + return <> + {isMobile && list + ? list + : } + {hotkeys} + ; +} + +interface DesktopViewProps { + loading: boolean; + res?: LookupNamesResponse; + + sortNew: boolean | undefined; + + paginationTableProps: PaginationTableProps; + + openNameEdit: OpenEditNameFn; + openSendTx: OpenSendTxFn; +} + +function DesktopView({ + loading, res, + sortNew, + paginationTableProps, + openNameEdit, openSendTx +}: DesktopViewProps): JSX.Element { + const { tStr } = useTFns("names."); + + const dateColumnWidth = useDateColumnWidth(); + + // Used to change the actions depending on whether or not we own the name + const { walletAddressMap, joinedAddressList } = useWallets(); + + const columns = useMemo(() => getColumns( + tStr, dateColumnWidth, sortNew, walletAddressMap, openNameEdit, openSendTx + // eslint-disable-next-line react-hooks/exhaustive-deps + ), [tStr, dateColumnWidth, sortNew, joinedAddressList, openNameEdit, openSendTx]); + const getRowClasses = useCallback((name: KristName): string => name.unpaid > 0 ? "name-row-unpaid" : "", []); - const tbl = + return className="names-table" size="small" scroll={{ x: true }} @@ -233,9 +307,4 @@ columns={columns} />; - - return <> - {tbl} - {hotkeys} - ; } diff --git a/src/pages/transactions/TransactionsTable.tsx b/src/pages/transactions/TransactionsTable.tsx index 4030a25..416258b 100644 --- a/src/pages/transactions/TransactionsTable.tsx +++ b/src/pages/transactions/TransactionsTable.tsx @@ -49,23 +49,6 @@ [7]: LookupTransactionType.SEARCH, }; -interface Props { - listingType: ListingType; - - // Number used to trigger a refresh of the transactions listing - refreshingID?: number; - - addresses?: string[]; - name?: string; - query?: string; - - includeMined?: boolean; - - setError?: Dispatch>; - setPagination?: Dispatch>; - setOpenSortModal?: SetOpenSortModalFn; -} - /** Map the search listing types to their API endpoint name */ function getLookupSearchType(listingType: ListingType): "address" | "name" | "metadata" | undefined { switch (listingType) { @@ -192,6 +175,23 @@ const defaultOrderBy = "time"; // Equivalent to sorting by ID const defaultOrder = "DESC"; +interface Props { + listingType: ListingType; + + // Number used to trigger a refresh of the transactions listing + refreshingID?: number; + + addresses?: string[]; + name?: string; + query?: string; + + includeMined?: boolean; + + setError?: Dispatch>; + setPagination?: Dispatch>; + setOpenSortModal?: SetOpenSortModalFn; +} + export function TransactionsTable({ listingType, refreshingID, diff --git a/src/pages/wallets/WalletMobileItem.tsx b/src/pages/wallets/WalletMobileItem.tsx index 980a839..085b344 100644 --- a/src/pages/wallets/WalletMobileItem.tsx +++ b/src/pages/wallets/WalletMobileItem.tsx @@ -1,29 +1,23 @@ // 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 { useCallback, useMemo } from "react"; -import { Tag, Collapse, Menu } from "antd"; -import { - ProfileOutlined, SendOutlined, EditOutlined, InfoCircleOutlined, - DeleteOutlined -} from "@ant-design/icons"; +import { useMemo } from "react"; +import { Tag, Collapse } from "antd"; import { Trans } from "react-i18next"; import { useTFns } from "@utils/i18n"; -import { useHistory } from "react-router-dom"; - import { Wallet } from "@wallets"; import { ContextualAddress } from "@comp/addresses/ContextualAddress"; import { KristValue } from "@comp/krist/KristValue"; import { DateTime } from "@comp/DateTime"; -import { useAuth } from "@comp/auth"; import { OpenEditWalletFn } from "./WalletEditButton"; import { OpenSendTxFn } from "@comp/transactions/SendTransactionModalLink"; import { OpenWalletInfoFn } from "./info/WalletInfoModal"; -import { showWalletDeleteConfirmModal } from "./WalletActions"; + +import { WalletMobileItemActions } from "./WalletMobileItemActions"; interface Props { wallet: Wallet; @@ -113,59 +107,3 @@ ; } - -function WalletMobileItemActions({ - wallet, - openEditWallet, - openSendTx, - openWalletInfo -}: Props): JSX.Element { - const { t, tStr } = useTFns("myWallets."); - - const history = useHistory(); - const promptAuth = useAuth(); - - const showWalletDeleteConfirm = useCallback( - () => showWalletDeleteConfirmModal(t, tStr, wallet), - [t, tStr, wallet] - ); - - const addressLink = `/network/addresses/${encodeURIComponent(wallet.address)}`; - const addressExists = !!wallet.firstSeen; - - return - {/* View address */} - } - onClick={() => history.push(addressLink)}> - {tStr("actionsViewAddress")} - - - {/* Send Krist */} - } - onClick={() => promptAuth(false, () => openSendTx(wallet))}> - {tStr("actionsSendTransaction")} - - - - - {/* Edit wallet */} - } - onClick={() => promptAuth(false, () => openEditWallet(wallet))}> - {tStr("actionsEditTooltip")} - - - {/* Wallet info */} - } - onClick={() => openWalletInfo(wallet)}> - {tStr("actionsWalletInfo")} - - - - - {/* Delete wallet */} - } - onClick={showWalletDeleteConfirm}> - {tStr("actionsDelete")} - - ; -} diff --git a/src/pages/wallets/WalletMobileItemActions.tsx b/src/pages/wallets/WalletMobileItemActions.tsx new file mode 100644 index 0000000..e38f365 --- /dev/null +++ b/src/pages/wallets/WalletMobileItemActions.tsx @@ -0,0 +1,85 @@ +// 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 { useCallback } from "react"; +import { Menu } from "antd"; +import { + ProfileOutlined, SendOutlined, EditOutlined, InfoCircleOutlined, + DeleteOutlined +} from "@ant-design/icons"; + +import { useTFns } from "@utils/i18n"; + +import { useHistory } from "react-router-dom"; + +import { Wallet } from "@wallets"; + +import { useAuth } from "@comp/auth"; +import { OpenEditWalletFn } from "./WalletEditButton"; +import { OpenSendTxFn } from "@comp/transactions/SendTransactionModalLink"; +import { OpenWalletInfoFn } from "./info/WalletInfoModal"; +import { showWalletDeleteConfirmModal } from "./WalletActions"; + +interface Props { + wallet: Wallet; + + openEditWallet: OpenEditWalletFn; + openSendTx: OpenSendTxFn; + openWalletInfo: OpenWalletInfoFn; +} + +export function WalletMobileItemActions({ + wallet, + openEditWallet, + openSendTx, + openWalletInfo +}: Props): JSX.Element { + const { t, tStr } = useTFns("myWallets."); + + const history = useHistory(); + const promptAuth = useAuth(); + + const showWalletDeleteConfirm = useCallback( + () => showWalletDeleteConfirmModal(t, tStr, wallet), + [t, tStr, wallet] + ); + + const addressLink = `/network/addresses/${encodeURIComponent(wallet.address)}`; + const addressExists = !!wallet.firstSeen; + + return + {/* View address */} + } + onClick={() => history.push(addressLink)}> + {tStr("actionsViewAddress")} + + + {/* Send Krist */} + } + onClick={() => promptAuth(false, () => openSendTx(wallet))}> + {tStr("actionsSendTransaction")} + + + + + {/* Edit wallet */} + } + onClick={() => promptAuth(false, () => openEditWallet(wallet))}> + {tStr("actionsEditTooltip")} + + + {/* Wallet info */} + } + onClick={() => openWalletInfo(wallet)}> + {tStr("actionsWalletInfo")} + + + + + {/* Delete wallet */} + } + onClick={showWalletDeleteConfirm}> + {tStr("actionsDelete")} + + ; +}