taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

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:
Mpackages/taler-util/src/taleruri.ts | 2+-
Mpackages/taler-util/src/types-taler-wallet.ts | 6++++++
Mpackages/taler-wallet-core/src/contacts.ts | 14+-------------
Mpackages/taler-wallet-core/src/db.ts | 7+++++++
Mpackages/taler-wallet-webextension/src/wallet/AddContact/views.tsx | 25+++++++++++++++++++++++--
Mpackages/taler-wallet-webextension/src/wallet/Application.tsx | 1+
Mpackages/taler-wallet-webextension/src/wallet/Contacts.tsx | 43+++++++++++++++++--------------------------
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> );