From d6409f185d332f6ade298f143cdb7803391f4b0b Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Wed, 18 Nov 2020 12:44:06 +0100 Subject: re-enable tipping support in the WebExtension UI --- packages/taler-wallet-core/src/operations/tip.ts | 1 + .../taler-wallet-core/src/types/walletTypes.ts | 25 ++++++++ .../src/pageEntryPoint.ts | 4 ++ .../taler-wallet-webextension/src/pages/tip.tsx | 75 ++++++++++++++++++++-- packages/taler-wallet-webextension/src/wxApi.ts | 11 ++++ packages/taler-wallet-webextension/static/tip.html | 8 +-- 6 files changed, 116 insertions(+), 8 deletions(-) diff --git a/packages/taler-wallet-core/src/operations/tip.ts b/packages/taler-wallet-core/src/operations/tip.ts index 1d19a72ed..119695de6 100644 --- a/packages/taler-wallet-core/src/operations/tip.ts +++ b/packages/taler-wallet-core/src/operations/tip.ts @@ -121,6 +121,7 @@ export async function prepareTip( accepted: !!tipRecord && !!tipRecord.acceptedTimestamp, tipAmountRaw: Amounts.stringify(tipRecord.tipAmountRaw), exchangeBaseUrl: tipRecord.exchangeBaseUrl, + merchantBaseUrl: tipRecord.merchantBaseUrl, expirationTimestamp: tipRecord.tipExpiration, tipAmountEffective: Amounts.stringify(tipRecord.tipAmountEffective), walletTipId: tipRecord.walletTipId, diff --git a/packages/taler-wallet-core/src/types/walletTypes.ts b/packages/taler-wallet-core/src/types/walletTypes.ts index 1b20d7b47..7940497a3 100644 --- a/packages/taler-wallet-core/src/types/walletTypes.ts +++ b/packages/taler-wallet-core/src/types/walletTypes.ts @@ -360,9 +360,33 @@ export interface PrepareTipResult { * Has the tip already been accepted? */ accepted: boolean; + + /** + * Amount that the merchant gave. + */ tipAmountRaw: AmountString; + + /** + * Amount that arrived at the wallet. + * Might be lower than the raw amount due to fees. + */ tipAmountEffective: AmountString; + + /** + * Base URL of the merchant backend giving then tip. + */ + merchantBaseUrl: string; + + /** + * Base URL of the exchange that is used to withdraw the tip. + * Determined by the merchant, the wallet/user has no choice here. + */ exchangeBaseUrl: string; + + /** + * Time when the tip will expire. After it expired, it can't be picked + * up anymore. + */ expirationTimestamp: Timestamp; } @@ -372,6 +396,7 @@ export const codecForPrepareTipResult = (): Codec => .property("tipAmountRaw", codecForAmountString()) .property("tipAmountEffective", codecForAmountString()) .property("exchangeBaseUrl", codecForString()) + .property("merchantBaseUrl", codecForString()) .property("expirationTimestamp", codecForTimestamp) .property("walletTipId", codecForString()) .build("PrepareTipResult"); diff --git a/packages/taler-wallet-webextension/src/pageEntryPoint.ts b/packages/taler-wallet-webextension/src/pageEntryPoint.ts index 216cb83c3..0e2b67b5d 100644 --- a/packages/taler-wallet-webextension/src/pageEntryPoint.ts +++ b/packages/taler-wallet-webextension/src/pageEntryPoint.ts @@ -27,6 +27,7 @@ import { createWelcomePage } from "./pages/welcome"; import { createPayPage } from "./pages/pay"; import { createRefundPage } from "./pages/refund"; import { setupI18n } from "taler-wallet-core"; +import { createTipPage } from './pages/tip'; function main(): void { try { @@ -52,6 +53,9 @@ function main(): void { case "refund.html": mainElement = createRefundPage(); break; + case "tip.html": + mainElement = createTipPage(); + break; default: throw Error(`page '${page}' not implemented`); } diff --git a/packages/taler-wallet-webextension/src/pages/tip.tsx b/packages/taler-wallet-webextension/src/pages/tip.tsx index 1290037e7..6f57854d2 100644 --- a/packages/taler-wallet-webextension/src/pages/tip.tsx +++ b/packages/taler-wallet-webextension/src/pages/tip.tsx @@ -15,14 +15,81 @@ */ /** - * Page shown to the user to confirm creation - * of a reserve, usually requested by the bank. + * Page shown to the user to accept or ignore a tip from a merchant. * - * @author Florian Dold + * @author Florian Dold */ import * as React from "react"; +import { useEffect, useState } from "react"; +import { PrepareTipResult } from "taler-wallet-core"; +import { AmountView } from "../renderHtml"; +import * as wxApi from "../wxApi"; + +function TalerTipDialog({ talerTipUri }: { talerTipUri: string }): JSX.Element { + const [updateCounter, setUpdateCounter] = useState(0); + const [prepareTipResult, setPrepareTipResult] = useState< + PrepareTipResult | undefined + >(); + + const [tipIgnored, setTipIgnored] = useState(false); + + useEffect(() => { + const doFetch = async (): Promise => { + const p = await wxApi.prepareTip({ talerTipUri }); + setPrepareTipResult(p); + }; + doFetch(); + }, [talerTipUri, updateCounter]); + + const doAccept = async () => { + if (!prepareTipResult) { + return; + } + await wxApi.acceptTip({ walletTipId: prepareTipResult?.walletTipId }); + setUpdateCounter(updateCounter + 1); + }; + + const doIgnore = () => { + setTipIgnored(true); + }; + + if (tipIgnored) { + return You've ignored the tip.; + } + + if (!prepareTipResult) { + return Loading ...; + } + + if (prepareTipResult.accepted) { + return ( + + Tip from {prepareTipResult.merchantBaseUrl} accepted. + Check your transactions list for more details. + + ); + } else { + return ( +
+

+ The merchant {prepareTipResult.merchantBaseUrl} is + offering you a tip of{" "} + via the + exchange {prepareTipResult.exchangeBaseUrl} +

+ + +
+ ); + } +} export function createTipPage(): JSX.Element { - return not implemented; + const url = new URL(document.location.href); + const talerTipUri = url.searchParams.get("talerTipUri"); + if (!talerTipUri) { + throw Error("invalid parameter"); + } + return ; } diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts index 9b7697c99..0434bb6d3 100644 --- a/packages/taler-wallet-webextension/src/wxApi.ts +++ b/packages/taler-wallet-webextension/src/wxApi.ts @@ -33,6 +33,9 @@ import { WithdrawUriInfoResponse, TransactionsResponse, ApplyRefundResponse, + PrepareTipRequest, + PrepareTipResult, + AcceptTipRequest, } from "taler-wallet-core"; export interface ExtendedPermissionsResponse { @@ -188,6 +191,14 @@ export function getWithdrawalDetailsForUri( return callBackend("getWithdrawalDetailsForUri", req); } +export function prepareTip(req: PrepareTipRequest): Promise { + return callBackend("prepareTip", req); +} + +export function acceptTip(req: AcceptTipRequest): Promise { + return callBackend("acceptTip", req); +} + export function onUpdateNotification(f: () => void): () => void { const port = chrome.runtime.connect({ name: "notifications" }); const listener = (): void => { diff --git a/packages/taler-wallet-webextension/static/tip.html b/packages/taler-wallet-webextension/static/tip.html index 00ed4d248..9c074e129 100644 --- a/packages/taler-wallet-webextension/static/tip.html +++ b/packages/taler-wallet-webextension/static/tip.html @@ -4,10 +4,10 @@ Taler Wallet: Received Tip - - - - + + + + -- cgit v1.2.3