commit 44cfbeedbffe2a9612c3c7acb5144ce27580f1bd
parent f524fbb633e80675b4ab2134717b0f3a293815ea
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Mon, 1 Dec 2025 14:17:32 +0900
contacts: fix some display issues and add petnames, fixes #10607
Diffstat:
7 files changed, 56 insertions(+), 42 deletions(-)
diff --git a/packages/taler-util/src/taleruri.ts b/packages/taler-util/src/taleruri.ts
@@ -235,8 +235,8 @@ export namespace TalerUris {
};
}
export function createTalerAddContact(
- alias: string,
aliasType: string,
+ alias: string,
mailboxUri: string,
mailboxIdentity: string,
sourceBaseUrl: string,
diff --git a/packages/taler-util/src/types-taler-wallet.ts b/packages/taler-util/src/types-taler-wallet.ts
@@ -1405,6 +1405,7 @@ export const codecForContactEntry = (): Codec<ContactEntry> =>
.property("mailboxBaseUri", codecForString())
.property("mailboxAddress", codecForString())
.property("source", codecForString())
+ .property("petname", codecForString())
.build("ContactListItem");
export const codecForAddContactRequest = (): Codec<AddContactRequest> =>
@@ -1795,6 +1796,11 @@ export interface ContactEntry {
* may be a URI
*/
source: string;
+
+ /**
+ * The local petname of the contact
+ */
+ petname: string;
}
/**
diff --git a/packages/taler-wallet-core/src/contacts.ts b/packages/taler-wallet-core/src/contacts.ts
@@ -49,26 +49,14 @@ async function makeContactListItem(
r: ContactRecord,
//lastError: TalerErrorDetail | undefined,
): Promise<ContactEntry> {
- //const lastUpdateErrorInfo: OperationErrorInfo | undefined = lastError
- // ? {
- // error: lastError,
- // }
- // : undefined;
-
const listItem: ContactEntry = {
alias: r.alias,
aliasType: r.aliasType,
mailboxBaseUri: r.mailboxBaseUri,
mailboxAddress: r.mailboxAddress,
source: r.source,
+ petname: r.petname,
};
- //switch (listItem.exchangeUpdateStatus) {
- // case ExchangeUpdateStatus.UnavailableUpdate:
- // if (r.unavailableReason) {
- // listItem.unavailableReason = r.unavailableReason;
- // }
- // break;
- //}
return listItem;
}
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
@@ -2927,14 +2927,21 @@ export interface ContactRecord {
* The alias of this contact
*/
alias: string;
+
/**
* The type of the alias
*/
aliasType: string;
+
/**
* The source of this alias
*/
source: string;
+
+ /**
+ * The local petname of this alias
+ */
+ petname: string;
}
/**
diff --git a/packages/taler-wallet-webextension/src/wallet/AddContact/views.tsx b/packages/taler-wallet-webextension/src/wallet/AddContact/views.tsx
@@ -16,6 +16,7 @@
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
import { ErrorMessage } from "../../components/ErrorMessage.js";
import {
Centered,
@@ -35,6 +36,9 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { Loading } from "../../components/Loading.js";
import { useBackendContext } from "../../context/backend.js";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
+import { TextField } from "../../mui/TextField.js";
+import { TextFieldHandler } from "../../mui/handlers.js";
+import { useAlertContext } from "../../context/alert.js";
export function VerifyContactView({
alias,
@@ -149,9 +153,16 @@ export function ConfirmAddContactView({
onConfirm,
}: State.Confirm): VNode {
const { i18n } = useTranslationContext();
+ const { pushAlertOnError } = useAlertContext();
+ const [petname, setPetname] = useState<string>();
const api = useBackendContext();
-
+ const petnameHandler: TextFieldHandler = {
+ value: contact.alias,
+ onInput: pushAlertOnError(async (d: string) => {
+ setPetname(d);
+ }),
+ }
const state = useAsyncAsHook(async () => {
const b = await api.wallet.call(WalletApiOperation.GetContacts, {});
const contacts = b.contacts;
@@ -162,10 +173,11 @@ export function ConfirmAddContactView({
return <Loading />;
}
async function onAddContact(): Promise<void> {
+ contact.petname = petname ?? contact.alias;
+ console.log(contact);
await api.wallet.call(WalletApiOperation.AddContact, { contact: contact }).then();
onConfirm();
}
-
return (
<Fragment>
<section style="">
@@ -189,6 +201,15 @@ export function ConfirmAddContactView({
<b><i18n.Translate>Contact source</i18n.Translate></b>: {contact.source}
</SmallText>
)}
+ <TextField
+ label="Petname"
+ variant="filled"
+ required
+ fullWidth
+ value={petname}
+ onChange={petnameHandler.onInput}
+ error={petnameHandler.error}
+ />
</section>
<footer style={{padding: 8}}>
diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx b/packages/taler-wallet-webextension/src/wallet/Application.tsx
@@ -890,6 +890,7 @@ export function Application(): VNode {
mailboxBaseUri: tUri.mailboxBaseUri,
mailboxAddress: tUri.mailboxIdentity,
source: tUri.sourceBaseUrl,
+ petname: tUri.alias,
}
: undefined;
if (!contact) {
diff --git a/packages/taler-wallet-webextension/src/wallet/Contacts.tsx b/packages/taler-wallet-webextension/src/wallet/Contacts.tsx
@@ -15,7 +15,6 @@
*/
import {
- ScopeInfo,
ContactEntry,
NotificationType,
Transaction,
@@ -24,7 +23,6 @@ import {
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
-import { Link } from "preact-router";
import { Fragment, VNode, h } from "preact";
import { useEffect, useState } from "preact/hooks";
import { ErrorAlertView } from "../components/CurrentAlerts.js";
@@ -32,7 +30,6 @@ import { Loading } from "../components/Loading.js";
import {
BoldLight,
Centered,
- RowBorderGray,
SmallText,
SmallLightText,
} from "../components/styled/index.js";
@@ -47,15 +44,11 @@ import { TextFieldHandler } from "../mui/handlers.js";
interface Props {
tid?: string;
- scope?: ScopeInfo;
- search?: boolean;
onMessageSent?: () => Promise<void>;
}
export function ContactsPage({
tid,
- scope,
- search: showSearch,
onMessageSent
}: Props): VNode {
const transactionId = tid as TransactionIdStr; //FIXME: validate
@@ -67,6 +60,7 @@ export function ContactsPage({
const b = await api.wallet.call(WalletApiOperation.GetContacts, {});
const contacts = b.contacts;
const filteredContacts = contacts.filter(c => (!search) ? true : (
+ c.petname.toLowerCase().includes(search.toLowerCase()) ||
c.alias.toLowerCase().includes(search.toLowerCase()) ||
c.aliasType.toLowerCase().includes(search.toLowerCase()) ||
c.mailboxBaseUri.toLowerCase().includes(search.toLowerCase()) ||
@@ -105,9 +99,6 @@ export function ContactsPage({
);
}
- const onAddContact = async (c: ContactEntry) => {
- api.wallet.call(WalletApiOperation.AddContact, { contact: c }).then();
- };
const onDeleteContact = async (c: ContactEntry) => {
api.wallet.call(WalletApiOperation.DeleteContact, { contact: c }).then();
};
@@ -140,7 +131,6 @@ export function ContactsPage({
}}
contacts={state.response.contacts}
transaction={state.response.transaction}
- onAddContact={onAddContact}
onDeleteContact={onDeleteContact}
onSendUriMessage={onSendUriMessage}
/>
@@ -160,8 +150,11 @@ function ContactLayout(props: ContactProps): VNode {
return (
<Paper style={{ padding: 8 }}>
<p>
- <span>{props.contact.alias}</span>
+ <span>{props.contact.petname}</span>
<SmallText style={{ marginTop: 5 }}>
+ <i18n.Translate>Alias</i18n.Translate>: {props.contact.alias}
+ </SmallText>
+ <SmallText style={{ marginTop: 5 }}>
<i18n.Translate>Type</i18n.Translate>: {props.contact.aliasType}
</SmallText>
<SmallText style={{ marginTop: 5 }}>
@@ -194,14 +187,12 @@ export function ContactsView({
search,
contacts,
transaction,
- onAddContact,
onDeleteContact,
onSendUriMessage: onSendUriMessage,
}: {
search: TextFieldHandler;
contacts: ContactEntry[];
transaction?: Transaction;
- onAddContact: (c: ContactEntry) => Promise<void>;
onDeleteContact: (c: ContactEntry) => Promise<void>;
onSendUriMessage: (c: ContactEntry, t?: Transaction) => Promise<void>;
}): VNode {
@@ -209,27 +200,26 @@ export function ContactsView({
return (
<Fragment>
<section>
+ <TextField
+ label="Search"
+ variant="filled"
+ error={search.error}
+ required
+ fullWidth
+ value={search.value}
+ onChange={search.onInput}
+ />
{(contacts.length == 0) ? (
<Centered style={{ marginTop: 20 }}>
<BoldLight>
- <i18n.Translate>No contacts yet.</i18n.Translate>
+ <i18n.Translate>No contacts found.</i18n.Translate>
</BoldLight>
</Centered>
) :
(
- <TextField
- label="Search"
- variant="filled"
- error={search.error}
- required
- fullWidth
- value={search.value}
- onChange={search.onInput}
- />
- )}
<Grid item container columns={1} spacing={1} style={{ marginTop: 20 }}>
{
- contacts.map((c, i) => (
+ contacts.map((c, _) => (
<Grid item xs={1}>
<ContactLayout
contact={c}
@@ -241,6 +231,7 @@ export function ContactsView({
))
}
</Grid>
+ )}
</section>
</Fragment>
);