diff --git a/public/locales/en.json b/public/locales/en.json
index d1aaf39..4db219b 100644
--- a/public/locales/en.json
+++ b/public/locales/en.json
@@ -212,6 +212,8 @@
"columnLabel": "Label",
"columnAddress": "Address",
+ "actionsViewAddress": "View address",
+ "actionsViewName": "View name",
"actionsEditTooltip": "Edit contact",
"actionsSendTransaction": "Send Krist",
"actionsDelete": "Delete contact",
diff --git a/src/pages/contacts/ContactActions.tsx b/src/pages/contacts/ContactActions.tsx
index 126f5c6..497695f 100644
--- a/src/pages/contacts/ContactActions.tsx
+++ b/src/pages/contacts/ContactActions.tsx
@@ -7,7 +7,8 @@
EditOutlined, DeleteOutlined, ExclamationCircleOutlined, SendOutlined
} from "@ant-design/icons";
-import { useTFns } from "@utils/i18n";
+import { TFunction } from "react-i18next";
+import { useTFns, TStrFn } from "@utils/i18n";
import { useAuth } from "@comp/auth";
import { OpenEditContactFn } from "./ContactEditButton";
@@ -29,18 +30,10 @@
const { t, tStr } = useTFns("addressBook.");
const promptAuth = useAuth();
- const showContactDeleteConfirm = useCallback((): void => {
- Modal.confirm({
- icon: ,
-
- title: tStr("actionsDeleteConfirm"),
-
- onOk: () => deleteContact(contact),
- okText: t("dialog.yes"),
- okType: "danger",
- cancelText: t("dialog.no")
- });
- }, [t, tStr, contact]);
+ const showContactDeleteConfirm = useCallback(
+ () => showContactDeleteConfirmModal(t, tStr, contact),
+ [t, tStr, contact]
+ );
const memoDropdown = useMemo(() => ,
+
+ title: tStr("actionsDeleteConfirm"),
+
+ onOk: () => deleteContact(contact),
+ okText: t("dialog.yes"),
+ okType: "danger",
+ cancelText: t("dialog.no")
+ });
+}
diff --git a/src/pages/contacts/ContactMobileItem.tsx b/src/pages/contacts/ContactMobileItem.tsx
new file mode 100644
index 0000000..93779cb
--- /dev/null
+++ b/src/pages/contacts/ContactMobileItem.tsx
@@ -0,0 +1,127 @@
+// 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 { 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";
+
+interface Props {
+ contact: Contact;
+
+ openEditContact: OpenEditContactFn;
+ openSendTx: OpenSendTxFn;
+}
+
+export function ContactMobileItem({
+ contact,
+ openEditContact,
+ openSendTx
+}: Props): JSX.Element {
+ const itemHead = useMemo(() => (
+
+ {/* Label, if possible */}
+ {contact.label &&
+ {contact.label}
+ }
+
+ {/* Address */}
+
+ {/* Address */}
+
+
+
+ ), [contact.address, contact.label]);
+
+ return
+
+
+
+ ;
+}
+
+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 ;
+}
diff --git a/src/pages/contacts/ContactsPage.less b/src/pages/contacts/ContactsPage.less
new file mode 100644
index 0000000..ae8fa9d
--- /dev/null
+++ b/src/pages/contacts/ContactsPage.less
@@ -0,0 +1,14 @@
+// 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 (reference) "../../App.less";
+@import "../../style/table.less";
+
+.contacts-page .table-mobile-list-view {
+ .contact-mobile-item {
+ .contact-label {
+ display: block;
+ font-size: 120%;
+ }
+ }
+}
diff --git a/src/pages/contacts/ContactsPage.tsx b/src/pages/contacts/ContactsPage.tsx
index 3827c10..b566df3 100644
--- a/src/pages/contacts/ContactsPage.tsx
+++ b/src/pages/contacts/ContactsPage.tsx
@@ -13,6 +13,8 @@
import { useEditContactModal } from "./ContactEditButton";
import { useSendTransactionModal } from "@comp/transactions/SendTransactionModalLink";
+import "./ContactsPage.less";
+
/** Contact count subtitle */
function ContactsPageSubtitle(): JSX.Element {
const { t, tStr, tKey } = useTFns("addressBook.");
@@ -36,6 +38,7 @@
siteTitleKey="addressBook.title" titleKey="addressBook.title"
subTitle={}
extra={extra}
+ className="contacts-page"
>
= useCallback(contact => (
+
+ ), [openEditContact, openSendTx]);
+
+ const { isMobile, list } = useSimpleMobileList(
+ false, contactValues, "id", "address", false, renderMobileItem
+ );
+
+ return isMobile && list
+ ? list
+ : ;
+}
+
+interface DesktopViewProps extends Props {
+ contacts: Contact[];
+}
+function DesktopView({
+ contacts,
+ openEditContact,
+ openSendTx
+}: DesktopViewProps): JSX.Element {
+ const { tStr } = useTFns("addressBook.");
const columns = useMemo(() => getColumns(
tStr, openEditContact, openSendTx
@@ -80,7 +114,7 @@
size="small"
scroll={{ x: true }}
- dataSource={Object.values(contacts)}
+ dataSource={contacts}
rowKey="id"
pagination={{
@@ -91,3 +125,4 @@
/>;
}
+
diff --git a/src/pages/wallets/WalletMobileItem.tsx b/src/pages/wallets/WalletMobileItem.tsx
index f3174b5..aa378b8 100644
--- a/src/pages/wallets/WalletMobileItem.tsx
+++ b/src/pages/wallets/WalletMobileItem.tsx
@@ -102,7 +102,7 @@
wallet.firstSeen, wallet.balance, wallet.names
]);
- return
+ return
.ant-collapse-content-box {
+ // Make the actions menu flush
+ padding: 0;
+
+ .ant-menu {
+ .ant-menu-item {
+ margin-bottom: 0;
+ }
+ }
+ }
+ }
+
.ant-list-pagination {
display: grid;
justify-content: center;