diff options
Diffstat (limited to 'packages')
16 files changed, 293 insertions, 383 deletions
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index fe4fcc2d9..1837f0508 100644 --- a/packages/taler-wallet-webextension/src/NavigationBar.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -259,7 +259,7 @@ export function WalletNavBar({ path }: { path?: WalletNavBarOptions }): VNode { <Fragment /> )} - <EnabledBySettings name="advanceMode"> + <EnabledBySettings name="advancedMode"> <a href={Pages.dev} class={path === "dev" ? "active" : ""}> <i18n.Translate>Dev tools</i18n.Translate> </a> diff --git a/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts b/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts index 0b27c9dcf..88d97af81 100644 --- a/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts +++ b/packages/taler-wallet-webextension/src/components/TermsOfService/state.ts @@ -39,7 +39,7 @@ export function useComponentState({ showEvenIfaccepted, exchangeUrl, readOnly, c WalletApiOperation.GetExchangeTos, { exchangeBaseUrl: exchangeUrl, - acceptedFormat: ["text/html"], + acceptedFormat: ["text/xml"], acceptLanguage: acceptedLang, }, ); @@ -77,14 +77,9 @@ export function useComponentState({ showEvenIfaccepted, exchangeUrl, readOnly, c if (accepted) { await api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, { exchangeBaseUrl: exchangeUrl, - etag: state.version, }); } else { // mark as not accepted - await api.wallet.call(WalletApiOperation.SetExchangeTosAccepted, { - exchangeBaseUrl: exchangeUrl, - etag: undefined, - }); } terms?.retry() } diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx index 4ceaad010..aade67835 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx @@ -33,6 +33,7 @@ import { getAmountWithFee, } from "../../wallet/Transaction.js"; import { State } from "./index.js"; +import { EnabledBySettings } from "../../components/EnabledBySettings.js"; export function FinalStateOperation(state: State.AlreadyCompleted): VNode { const { i18n } = useTranslationContext(); @@ -77,13 +78,15 @@ export function SuccessView(state: State.Success): VNode { }} > <i18n.Translate>Exchange</i18n.Translate> - <Button onClick={state.doSelectExchange.onClick} variant="text"> - <SvgIcon - title="Edit" - dangerouslySetInnerHTML={{ __html: editIcon }} - color="black" - /> - </Button> + <EnabledBySettings name="showExchangeManagement"> + <Button onClick={state.doSelectExchange.onClick} variant="text"> + <SvgIcon + title="Edit" + dangerouslySetInnerHTML={{ __html: editIcon }} + color="black" + /> + </Button> + </EnabledBySettings> </div> } text={ diff --git a/packages/taler-wallet-webextension/src/hooks/useSettings.ts b/packages/taler-wallet-webextension/src/hooks/useSettings.ts index 29449cd59..09fe28888 100644 --- a/packages/taler-wallet-webextension/src/hooks/useSettings.ts +++ b/packages/taler-wallet-webextension/src/hooks/useSettings.ts @@ -36,13 +36,14 @@ export const codecForSettings = (): Codec<Settings> => .property("walletAllowHttp", codecForBoolean()) .property("injectTalerSupport", codecForBoolean()) .property("autoOpen", codecForBoolean()) - .property("advanceMode", codecForBoolean()) + .property("advancedMode", codecForBoolean()) .property("backup", codecForBoolean()) .property("langSelector", codecForBoolean()) .property("showJsonOnError", codecForBoolean()) .property("extendedAccountTypes", codecForBoolean()) .property("suspendIndividualTransaction", codecForBoolean()) .property("showRefeshTransactions", codecForBoolean()) + .property("showExchangeManagement", codecForBoolean()) .build("Settings"); const SETTINGS_KEY = buildStorageKey("wallet-settings", codecForSettings()); diff --git a/packages/taler-wallet-webextension/src/platform/api.ts b/packages/taler-wallet-webextension/src/platform/api.ts index 5bc7fd6c5..a16200cc5 100644 --- a/packages/taler-wallet-webextension/src/platform/api.ts +++ b/packages/taler-wallet-webextension/src/platform/api.ts @@ -113,25 +113,27 @@ type WebexWalletConfig = { export interface Settings extends WebexWalletConfig { injectTalerSupport: boolean; autoOpen: boolean; - advanceMode: boolean; + advancedMode: boolean; backup: boolean; langSelector: boolean; showJsonOnError: boolean; extendedAccountTypes: boolean; showRefeshTransactions: boolean; suspendIndividualTransaction: boolean; + showExchangeManagement: boolean; } export const defaultSettings: Settings = { injectTalerSupport: false, autoOpen: true, - advanceMode: false, + advancedMode: false, backup: false, langSelector: false, showRefeshTransactions: false, suspendIndividualTransaction: false, showJsonOnError: false, extendedAccountTypes: false, + showExchangeManagement: false, walletAllowHttp: false, }; diff --git a/packages/taler-wallet-webextension/src/wallet/AddExchange/test.ts b/packages/taler-wallet-webextension/src/wallet/AddExchange/test.ts index 60d5b274c..aa6384df2 100644 --- a/packages/taler-wallet-webextension/src/wallet/AddExchange/test.ts +++ b/packages/taler-wallet-webextension/src/wallet/AddExchange/test.ts @@ -49,6 +49,7 @@ describe("AddExchange states", () => { exchangeBaseUrl: "http://exchange.local/", ageRestrictionOptions: [], scopeInfo: undefined, + masterPub: "123qwe123", currency: "ARS", exchangeEntryStatus: ExchangeEntryStatus.Ephemeral, tosStatus: ExchangeTosStatus.Pending, diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/test.ts b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/test.ts index 3082ae7a4..0a99e6af9 100644 --- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/test.ts +++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/test.ts @@ -36,6 +36,7 @@ import { useComponentState } from "./state.js"; const exchangeArs: ExchangeListItem = { currency: "ARS", exchangeBaseUrl: "http://", + masterPub:"123qwe123", scopeInfo: undefined, tosStatus: ExchangeTosStatus.Accepted, exchangeEntryStatus: ExchangeEntryStatus.Used, diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx index f8e2c6707..c40a3a64c 100644 --- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx @@ -14,6 +14,7 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ +import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { styled } from "@linaria/react"; import { Fragment, h, VNode } from "preact"; import { AmountField } from "../../components/AmountField.js"; @@ -25,7 +26,6 @@ import { LinkPrimary, SvgIcon, } from "../../components/styled/index.js"; -import { useTranslationContext } from "@gnu-taler/web-util/browser"; import { Button } from "../../mui/Button.js"; import { Grid } from "../../mui/Grid.js"; import { Paper } from "../../mui/Paper.js"; @@ -34,8 +34,6 @@ import arrowIcon from "../../svg/chevron-down.inline.svg"; import bankIcon from "../../svg/ri-bank-line.inline.svg"; import { assertUnreachable } from "../../utils/index.js"; import { Contact, State } from "./index.js"; -import { useEffect } from "preact/hooks"; -import { Checkbox } from "../../components/Checkbox.js"; export function SelectCurrencyView({ currencies, @@ -303,7 +301,7 @@ export function ReadySendView({ required handler={amountHandler} /> - <EnabledBySettings name="advanceMode"> + <EnabledBySettings name="advancedMode"> <Button onClick={selectMax.onClick}> <i18n.Translate>Send all</i18n.Translate> </Button> diff --git a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.stories.tsx b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.stories.tsx index c2c794e89..e7c9111fd 100644 --- a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.stories.tsx @@ -21,7 +21,7 @@ import { AbsoluteTime } from "@gnu-taler/taler-util"; import * as tests from "@gnu-taler/web-util/testing"; -import { View as TestedComponent } from "./DeveloperPage.js"; +import { DeveloperPage as TestedComponent } from "./DeveloperPage.js"; export default { title: "developer", diff --git a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx index 0db7a07eb..d19fef155 100644 --- a/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DeveloperPage.tsx @@ -20,8 +20,12 @@ import { CoinDumpJson, CoinStatus, ExchangeListItem, + ExchangeTosStatus, LogLevel, NotificationType, + ScopeType, + parseWithdrawUri, + stringifyWithdrawExchange, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { useTranslationContext } from "@gnu-taler/web-util/browser"; @@ -31,7 +35,7 @@ import { useEffect, useRef, useState } from "preact/hooks"; import { Checkbox } from "../components/Checkbox.js"; import { SelectList } from "../components/SelectList.js"; import { Time } from "../components/Time.js"; -import { NotifyUpdateFadeOut } from "../components/styled/index.js"; +import { DestructiveText, LinkPrimary, NotifyUpdateFadeOut, SubTitle, SuccessText, WarningText } from "../components/styled/index.js"; import { useAlertContext } from "../context/alert.js"; import { useBackendContext } from "../context/backend.js"; import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js"; @@ -40,50 +44,8 @@ import { Button } from "../mui/Button.js"; import { Grid } from "../mui/Grid.js"; import { Paper } from "../mui/Paper.js"; import { TextField } from "../mui/TextField.js"; - -export function DeveloperPage(): VNode { - const listenAllEvents = Array.from<NotificationType>({ length: 1 }); - - const api = useBackendContext(); - - const response = useAsyncAsHook(async () => { - const op = await api.wallet.call( - WalletApiOperation.GetPendingOperations, - {}, - ); - const c = await api.wallet.call(WalletApiOperation.DumpCoins, {}); - const ex = await api.wallet.call(WalletApiOperation.ListExchanges, {}); - return { - operations: op.pendingOperations, - coins: c.coins, - exchanges: ex.exchanges, - }; - }); - - useEffect(() => { - return api.listener.onUpdateNotification(listenAllEvents, response?.retry); - }); - - const nonResponse = { operations: [], coins: [], exchanges: [] }; - const { operations, coins, exchanges } = - response === undefined - ? nonResponse - : response.hasError - ? nonResponse - : response.response; - - return ( - <View - operations={operations} - coins={coins} - exchanges={exchanges} - onDownloadDatabase={async () => { - const db = await api.wallet.call(WalletApiOperation.ExportDb, {}); - return JSON.stringify(db); - }} - /> - ); -} +import { Pages } from "../NavigationBar.js"; +import { CoinInfo } from "@gnu-taler/taler-wallet-core/dbless"; type CoinsInfo = CoinDumpJson["coins"]; type CalculatedCoinfInfo = { @@ -103,23 +65,20 @@ type SplitedCoinInfo = { export interface Props { // FIXME: Pending operations don't exist anymore. - operations: any[]; - coins: CoinsInfo; - exchanges: ExchangeListItem[]; - onDownloadDatabase: () => Promise<string>; } function hashObjectId(o: any): string { return JSON.stringify(o); } -export function View({ operations, coins, onDownloadDatabase }: Props): VNode { +export function DeveloperPage({ }: Props): VNode { const { i18n } = useTranslationContext(); const [downloadedDatabase, setDownloadedDatabase] = useState< { time: Date; content: string } | undefined >(undefined); async function onExportDatabase(): Promise<void> { - const content = await onDownloadDatabase(); + const db = await api.wallet.call(WalletApiOperation.ExportDb, {}); + const content = JSON.stringify(db); setDownloadedDatabase({ time: new Date(), content, @@ -136,10 +95,28 @@ export function View({ operations, coins, onDownloadDatabase }: Props): VNode { const [settings, updateSettings] = useSettings(); const { safely } = useAlertContext(); - const hook = useAsyncAsHook(() => - api.wallet.call(WalletApiOperation.ListExchanges, {}), - ); + // const hook = useAsyncAsHook(() => + // api.wallet.call(WalletApiOperation.ListExchanges, {}), + // ); + const listenAllEvents = Array.from<NotificationType>({ length: 1 }); + + const hook = useAsyncAsHook(async () => { + const list = await api.wallet.call(WalletApiOperation.ListExchanges, {}); + const version = await api.wallet.call(WalletApiOperation.GetVersion, {}); + const operations: any[] = await api.wallet.call( + WalletApiOperation.GetPendingOperations, + {}, + ); + const coins = await api.wallet.call(WalletApiOperation.DumpCoins, {}); + return { exchanges: list.exchanges, version, coins, operations }; + }); const exchangeList = hook && !hook.hasError ? hook.response.exchanges : []; + const coins = hook && !hook.hasError ? hook.response.coins.coins : []; + const operations = hook && !hook.hasError ? hook.response.operations : []; + + useEffect(() => { + return api.listener.onUpdateNotification(listenAllEvents, hook?.retry); + }); const currencies: { [ex: string]: string } = {}; const money_by_exchange = coins.reduce( @@ -205,30 +182,6 @@ export function View({ operations, coins, onDownloadDatabase }: Props): VNode { <Grid item> <Button variant="contained" - onClick={() => { - return api.background.call("sum", [1, 2, 3]).then((r) => { - console.log("SUM", r); - }); - }} - > - <i18n.Translate>sum 123</i18n.Translate> - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - onClick={() => { - return api.background.call("freeze", 4000).then(() => { - console.log("WAIT"); - }); - }} - > - <i18n.Translate>freeze 4000</i18n.Translate> - </Button> - </Grid> - <Grid item> - <Button - variant="contained" onClick={async () => fileRef?.current?.click()} > <i18n.Translate>import database</i18n.Translate> @@ -260,64 +213,6 @@ export function View({ operations, coins, onDownloadDatabase }: Props): VNode { <Button variant="contained" onClick={async () => { - navigator.registerProtocolHandler( - "taler", - `${window.location.origin}/static/wallet.html#/cta/withdraw?talerWithdrawUri=%s`, - ); - }} - > - <i18n.Translate>Register taler:// handler</i18n.Translate> - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - onClick={async () => { - const n = navigator as any; - if ("unregisterProtocolHandler" in n) { - n.unregisterProtocolHandler( - "taler", - `${window.location.origin}/static/wallet.html#/cta/withdraw?talerWithdrawUri=%s`, - ); - } - }} - > - <i18n.Translate>Remove taler:// handler</i18n.Translate> - </Button> - </Grid>{" "} - <Grid item> - <Button - variant="contained" - onClick={async () => { - navigator.registerProtocolHandler( - "ext+taler", - `${window.location.origin}/static/wallet.html#/cta/withdraw?talerWithdrawUri=%s`, - ); - }} - > - <i18n.Translate>Register ext+taler:// handler</i18n.Translate> - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - onClick={async () => { - const n = navigator as any; - if ("unregisterProtocolHandler" in n) { - n.unregisterProtocolHandler( - "ext+taler", - `${window.location.origin}/static/wallet.html#/cta/withdraw?talerWithdrawUri=%s`, - ); - } - }} - > - <i18n.Translate>Remove ext+taler:// handler</i18n.Translate> - </Button> - </Grid> - <Grid item> - <Button - variant="contained" - onClick={async () => { const result = await Promise.all( exchangeList.map(async (exchange) => { const url = exchange.exchangeBaseUrl; @@ -359,6 +254,201 @@ export function View({ operations, coins, onDownloadDatabase }: Props): VNode { })} /> + + <SubTitle> + <i18n.Translate>Exchange Entries</i18n.Translate> + </SubTitle> + {!exchangeList || !exchangeList.length ? ( + <div> + <i18n.Translate>No exchange yet</i18n.Translate> + </div> + ) : ( + <Fragment> + <table> + <thead> + <tr> + <th> + <i18n.Translate>Currency</i18n.Translate> + </th> + <th> + <i18n.Translate>URL</i18n.Translate> + </th> + <th> + <i18n.Translate>Status</i18n.Translate> + </th> + <th> + <i18n.Translate>Terms of Service</i18n.Translate> + </th> + <th> + <i18n.Translate>Last Update</i18n.Translate> + </th> + <th> + <i18n.Translate>Actions</i18n.Translate> + </th> + </tr> + </thead> + <tbody> + {exchangeList.map((e, idx) => { + function TosStatus(): VNode { + switch (e.tosStatus) { + case ExchangeTosStatus.Accepted: + return ( + <SuccessText> + <i18n.Translate>ok</i18n.Translate> + </SuccessText> + ); + case ExchangeTosStatus.Pending: + return ( + <WarningText> + <i18n.Translate>pending</i18n.Translate> + </WarningText> + ); + case ExchangeTosStatus.Proposed: + return <i18n.Translate>proposed</i18n.Translate>; + default: + return ( + <DestructiveText> + <i18n.Translate> + unknown (exchange status should be updated) + </i18n.Translate> + </DestructiveText> + ); + } + } + const uri = !e.masterPub ? undefined : stringifyWithdrawExchange({ + exchangeBaseUrl: e.exchangeBaseUrl, + exchangePub: e.masterPub, + }); + return ( + <tr key={idx}> + <td> + <a href={!uri? undefined: Pages.defaultCta({ uri })}> + {e.scopeInfo ? `${e.scopeInfo.currency} (${e.scopeInfo.type === ScopeType.Global ? "global" : "regional"})` : e.currency} + </a> + </td> + <td> + <a href={new URL(`/keys`, e.exchangeBaseUrl).href} target="_blank">{e.exchangeBaseUrl}</a> + </td> + <td> + {e.exchangeEntryStatus} / {e.exchangeUpdateStatus} + </td> + <td> + <TosStatus /> + </td> + <td> + {e.lastUpdateTimestamp + ? AbsoluteTime.toIsoString( + AbsoluteTime.fromPreciseTimestamp( + e.lastUpdateTimestamp, + ), + ) + : "never"} + </td> + <td> + <button + onClick={() => { + api.wallet.call( + WalletApiOperation.UpdateExchangeEntry, + { + exchangeBaseUrl: e.exchangeBaseUrl, + force: true, + }, + ); + }} + > + Reload + </button> + <button + onClick={() => { + api.wallet.call( + WalletApiOperation.DeleteExchange, + { + exchangeBaseUrl: e.exchangeBaseUrl, + }, + ); + }} + > + Delete + </button> + <button + onClick={() => { + api.wallet.call( + WalletApiOperation.DeleteExchange, + { + exchangeBaseUrl: e.exchangeBaseUrl, + purge: true, + }, + ); + }} + > + Purge + </button> + {e.scopeInfo && e.masterPub && e.currency ? + (e.scopeInfo.type === ScopeType.Global ? + <button + onClick={() => { + api.wallet.call( + WalletApiOperation.RemoveGlobalCurrencyExchange, + { + exchangeBaseUrl: e.exchangeBaseUrl, + currency: e.currency!, + exchangeMasterPub: e.masterPub!, + }, + ); + }} + > + + Make regional + </button> + : e.scopeInfo.type === ScopeType.Auditor ? + undefined + + : e.scopeInfo.type === ScopeType.Exchange ? + <button + onClick={() => { + api.wallet.call( + WalletApiOperation.AddGlobalCurrencyExchange, + { + exchangeBaseUrl: e.exchangeBaseUrl, + currency: e.currency!, + exchangeMasterPub: e.masterPub!, + }, + ); + }} + > + + Make global + </button> + : undefined) : undefined + } + <button + onClick={() => { + api.wallet.call( + WalletApiOperation.SetExchangeTosForgotten, + { + exchangeBaseUrl: e.exchangeBaseUrl, + }, + ); + }} + > + Forget ToS + </button> + </td> + </tr> + ); + })} + </tbody> + </table> + </Fragment> + )} + <div style={{ display: "flex", justifyContent: "space-between" }}> + <div /> + <LinkPrimary href={Pages.settingsExchangeAdd({})}> + <i18n.Translate>Add an exchange</i18n.Translate> + </LinkPrimary> + </div> + + <Paper style={{ padding: 10, margin: 10 }}> <h3>Logging</h3> <div> diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx index a5d6972de..cd43c4526 100644 --- a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx @@ -75,19 +75,6 @@ export const WithOneExchange = tests.createExample(TestedComponent, { autoOpenToggle: { value: false, button: {} }, langToggle: { value: false, button: {} }, setDeviceName: () => Promise.resolve(), - knownExchanges: [ - { - currency: "USD", - exchangeBaseUrl: "http://exchange.taler", - tos: { - currentVersion: "1", - acceptedVersion: "1", - content: "content of tos", - contentType: "text/plain", - }, - paytoUris: ["payto://x-taler-bank/bank.rpi.sebasjm.com/exchangeminator"], - } as any, //TODO: complete with auditors, wireInfo and denominations - ], ...version, }); @@ -99,46 +86,6 @@ export const WithExchangeInDifferentState = tests.createExample( autoOpenToggle: { value: false, button: {} }, langToggle: { value: false, button: {} }, setDeviceName: () => Promise.resolve(), - knownExchanges: [ - { - currency: "USD", - exchangeBaseUrl: "http://exchange1.taler", - tos: { - currentVersion: "1", - acceptedVersion: "1", - content: "content of tos", - contentType: "text/plain", - }, - paytoUris: [ - "payto://x-taler-bank/bank.rpi.sebasjm.com/exchangeminator", - ], - }, - { - currency: "USD", - exchangeBaseUrl: "http://exchange2.taler", - tos: { - currentVersion: "2", - acceptedVersion: "1", - content: "content of tos", - contentType: "text/plain", - }, - paytoUris: [ - "payto://x-taler-bank/bank.rpi.sebasjm.com/exchangeminator", - ], - } as any, //TODO: complete with auditors, wireInfo and denominations - { - currency: "USD", - exchangeBaseUrl: "http://exchange3.taler", - tos: { - currentVersion: "1", - content: "content of tos", - contentType: "text/plain", - }, - paytoUris: [ - "payto://x-taler-bank/bank.rpi.sebasjm.com/exchangeminator", - ], - }, - ], ...version, }, ); diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.tsx b/packages/taler-wallet-webextension/src/wallet/Settings.tsx index ec716cb87..b8fc14469 100644 --- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx @@ -16,9 +16,11 @@ import { AbsoluteTime, + ExchangeDetailedResponse, ExchangeListItem, ExchangeTosStatus, LibtoolVersion, + ScopeType, TranslatedString, WalletCoreVersion, } from "@gnu-taler/taler-util"; @@ -58,19 +60,15 @@ export function SettingsPage(): VNode { const webex = platform.getWalletWebExVersion(); const api = useBackendContext(); - const exchangesHook = useAsyncAsHook(async () => { - const list = await api.wallet.call(WalletApiOperation.ListExchanges, {}); + const hook = useAsyncAsHook(async () => { const version = await api.wallet.call(WalletApiOperation.GetVersion, {}); - return { exchanges: list.exchanges, version }; + return { version }; }); - const { exchanges, version } = - !exchangesHook || exchangesHook.hasError - ? { exchanges: [], version: undefined } - : exchangesHook.response; + + const version = hook && !hook.hasError ? hook.response.version : undefined return ( <SettingsView - knownExchanges={exchanges} deviceName={name} setDeviceName={update} autoOpenToggle={{ @@ -82,10 +80,10 @@ export function SettingsPage(): VNode { }, }} advanceToggle={{ - value: settings.advanceMode, + value: settings.advancedMode, button: { onClick: safely("update advance mode", async () => { - updateSettings("advanceMode", !settings.advanceMode); + updateSettings("advancedMode", !settings.advancedMode); }), }, }} @@ -112,7 +110,6 @@ export interface ViewProps { autoOpenToggle: ToggleHandler; advanceToggle: ToggleHandler; langToggle: ToggleHandler; - knownExchanges: Array<ExchangeListItem>; coreVersion: WalletCoreVersion | undefined; webexVersion: { version: string; @@ -121,7 +118,6 @@ export interface ViewProps { } export function SettingsView({ - knownExchanges, autoOpenToggle, advanceToggle, langToggle, @@ -136,143 +132,6 @@ export function SettingsView({ <Fragment> <section> <SubTitle> - <i18n.Translate>Exchange Entries</i18n.Translate> - </SubTitle> - {!knownExchanges || !knownExchanges.length ? ( - <div> - <i18n.Translate>No exchange yet</i18n.Translate> - </div> - ) : ( - <Fragment> - <table> - <thead> - <tr> - <th> - <i18n.Translate>Currency</i18n.Translate> - </th> - <th> - <i18n.Translate>URL</i18n.Translate> - </th> - <th> - <i18n.Translate>Status</i18n.Translate> - </th> - <th> - <i18n.Translate>Terms of Service</i18n.Translate> - </th> - <th> - <i18n.Translate>Last Update</i18n.Translate> - </th> - <th> - <i18n.Translate>Actions</i18n.Translate> - </th> - </tr> - </thead> - <tbody> - {knownExchanges.map((e, idx) => { - function TosStatus(): VNode { - switch (e.tosStatus) { - case ExchangeTosStatus.Accepted: - return ( - <SuccessText> - <i18n.Translate>ok</i18n.Translate> - </SuccessText> - ); - case ExchangeTosStatus.Pending: - return ( - <WarningText> - <i18n.Translate>pending</i18n.Translate> - </WarningText> - ); - case ExchangeTosStatus.Proposed: - return <i18n.Translate>proposed</i18n.Translate>; - default: - return ( - <DestructiveText> - <i18n.Translate> - unknown (exchange status should be updated) - </i18n.Translate> - </DestructiveText> - ); - } - } - return ( - <tr key={idx}> - <td>{e.currency}</td> - <td> - <a href={e.exchangeBaseUrl}>{e.exchangeBaseUrl}</a> - </td> - <td> - {e.exchangeEntryStatus} / {e.exchangeUpdateStatus} - </td> - <td> - <TosStatus /> - </td> - <td> - {e.lastUpdateTimestamp - ? AbsoluteTime.toIsoString( - AbsoluteTime.fromPreciseTimestamp( - e.lastUpdateTimestamp, - ), - ) - : "never"} - </td> - <td> - <button - onClick={() => { - console.log(`force-updating ${e.exchangeBaseUrl}`); - api.wallet.call( - WalletApiOperation.UpdateExchangeEntry, - { - exchangeBaseUrl: e.exchangeBaseUrl, - force: true, - }, - ); - }} - > - Reload - </button> - </td> - </tr> - ); - })} - </tbody> - </table> - </Fragment> - )} - <div style={{ display: "flex", justifyContent: "space-between" }}> - <div /> - <LinkPrimary href={Pages.settingsExchangeAdd({})}> - <i18n.Translate>Add an exchange</i18n.Translate> - </LinkPrimary> - </div> - <SubTitle> - <i18n.Translate>Advanced mode</i18n.Translate> - </SubTitle> - <Checkbox - label={i18n.str`Enable advanced mode`} - name="devMode" - description={i18n.str`Show more information and options in the UI`} - enabled={advanceToggle.value!} - onToggle={advanceToggle.button.onClick!} - /> - <EnabledBySettings name="advanceMode"> - <AdvanceSettings /> - </EnabledBySettings> - <EnabledBySettings name="langSelector"> - <SubTitle> - <i18n.Translate>Display</i18n.Translate> - </SubTitle> - <Input> - <SelectList - label={<i18n.Translate>Current Language</i18n.Translate>} - list={supportedLang} - name="lang" - value={lang} - onChange={(v) => changeLanguage(v)} - /> - </Input> - </EnabledBySettings> - <SubTitle> <i18n.Translate>Navigator</i18n.Translate> </SubTitle> <Checkbox @@ -286,6 +145,7 @@ export function SettingsView({ enabled={autoOpenToggle.value!} onToggle={autoOpenToggle.button.onClick!} /> + <SubTitle> <i18n.Translate>Version Info</i18n.Translate> </SubTitle> @@ -294,7 +154,7 @@ export function SettingsView({ text={ <span> {webexVersion.version}{" "} - <EnabledBySettings name="advanceMode"> + <EnabledBySettings name="advancedMode"> {webexVersion.hash} </EnabledBySettings> </span> @@ -313,7 +173,7 @@ export function SettingsView({ </i18n.Translate> </WarningBox> )} - <EnabledBySettings name="advanceMode"> + <EnabledBySettings name="advancedMode"> <Part title={i18n.str`Exchange compatibility`} text={<span>{coreVersion.exchange}</span>} @@ -333,6 +193,33 @@ export function SettingsView({ </EnabledBySettings> </Fragment> )} + <SubTitle> + <i18n.Translate>Settings</i18n.Translate> + </SubTitle> + <Checkbox + label={i18n.str`Enable developer mode`} + name="devMode" + description={i18n.str`Show more information and options in the UI`} + enabled={advanceToggle.value!} + onToggle={advanceToggle.button.onClick!} + /> + <EnabledBySettings name="advancedMode"> + <AdvanceSettings /> + </EnabledBySettings> + <EnabledBySettings name="langSelector"> + <SubTitle> + <i18n.Translate>Display</i18n.Translate> + </SubTitle> + <Input> + <SelectList + label={<i18n.Translate>Current Language</i18n.Translate>} + list={supportedLang} + name="lang" + value={lang} + onChange={(v) => changeLanguage(v)} + /> + </Input> + </EnabledBySettings> </section> </Fragment> ); @@ -374,6 +261,10 @@ function AdvanceSettings(): VNode { label: i18n.str`Lang selector`, description: i18n.str`Allows to manually change the language of the UI. Otherwise it will be automatically selected by your browser configuration.`, }, + showExchangeManagement: { + label: i18n.str`Edit exchange management`, + description: i18n.str`Allows to see the list of exchange, remove, add and switch before withdrawal.`, + }, }; return ( <Fragment> diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx index 65fc90f44..65ba6cc85 100644 --- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx @@ -1960,7 +1960,7 @@ function ShowWithdrawalDetailForBankIntegrated({ const raw = Amounts.parseOrThrow(transaction.amountRaw); return ( <Fragment> - <EnabledBySettings name="advanceMode"> + <EnabledBySettings name="advancedMode"> <a href="#" onClick={(e) => { diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts index d989c9662..b73b12263 100644 --- a/packages/taler-wallet-webextension/src/wxApi.ts +++ b/packages/taler-wallet-webextension/src/wxApi.ts @@ -60,14 +60,6 @@ export interface ExtendedPermissionsResponse { } export interface BackgroundOperations { - freeze: { - request: number; - response: void; - }; - sum: { - request: number[]; - response: number; - }; resetDb: { request: void; response: void; diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts index 70db60eca..051048e81 100644 --- a/packages/taler-wallet-webextension/src/wxBackend.ts +++ b/packages/taler-wallet-webextension/src/wxBackend.ts @@ -111,16 +111,6 @@ async function runGarbageCollector(): Promise<void> { logger.info("imported"); } -function freeze(time: number): Promise<void> { - return new Promise((res, rej) => { - setTimeout(res, time); - }); -} - -async function sum(ns: Array<number>): Promise<number> { - return ns.reduce((prev, cur) => prev + cur, 0); -} - const extensionHandlers: ExtensionHandlerType = { isAutoOpenEnabled, isDomainTrusted, @@ -137,8 +127,6 @@ async function isDomainTrusted(): Promise<boolean> { } const backendHandlers: BackendHandlerType = { - freeze, - sum, resetDb, runGarbageCollector, setLoggingLevel, diff --git a/packages/taler-wallet-webextension/static/wallet.html b/packages/taler-wallet-webextension/static/wallet.html index c8baa7e4d..3025901d8 100644 --- a/packages/taler-wallet-webextension/static/wallet.html +++ b/packages/taler-wallet-webextension/static/wallet.html @@ -4,6 +4,7 @@ <head> <title>GNU Taler Wallet - WebExtension</title> <meta charset="utf-8" /> + <meta name="taler-support" content="uri,api" /> <link rel="stylesheet" type="text/css" href="/dist/walletEntryPoint.css" /> <link rel="stylesheet" type="text/css" href="/static/font/import.css" /> <link rel="icon" |