(null)
+ return
+
+
+
+}
+
+export interface ViewProps {
+ currency: string;
+ info?: ProviderInfo;
+ onDelete: () => void;
+ onSync: () => void;
+ onBack: () => void;
+ onAddProvider: () => void;
+}
+
+export function ProviderView({ currency, info, onDelete, onSync, onBack, onAddProvider }: ViewProps): VNode {
+ function Footer() {
+ return
+ }
+ function Error() {
+ if (info?.lastError) {
+ return
+
{info.lastError.hint}
+
+ }
+ if (info?.backupProblem) {
+ switch (info.backupProblem.type) {
+ case "backup-conflicting-device":
+ return
+
There is another backup from {info.backupProblem.otherDeviceId}
+
+ case "backup-unreadable":
+ return
+
Backup is not readable
+
+ default:
+ return
+
Unkown backup problem: {JSON.stringify(info.backupProblem)}
+
+ }
+ }
+ return null
+ }
+ function colorByStatus(status: ProviderPaymentType | undefined) {
+ switch (status) {
+ case ProviderPaymentType.InsufficientBalance:
+ return 'rgb(223, 117, 20)'
+ case ProviderPaymentType.Unpaid:
+ return 'rgb(202, 60, 60)'
+ case ProviderPaymentType.Paid:
+ return 'rgb(28, 184, 65)'
+ case ProviderPaymentType.Pending:
+ return 'gray'
+ case ProviderPaymentType.InsufficientBalance:
+ return 'rgb(202, 60, 60)'
+ case ProviderPaymentType.TermsChanged:
+ return 'rgb(202, 60, 60)'
+ default:
+ break;
+ }
+ return undefined
+ }
+
+ return (
+
+
+
+
+ {info?.paymentStatus.type}
+ {info &&
+ From {info.syncProviderBaseUrl}
+ }
+
+
+
+
+
{currency}
+ {info &&
{info.terms?.annualFee} / year
}
+
+
+ {daysSince(info?.lastSuccessfulBackupTimestamp)}
+
+
+
+
+ )
+}
+
+function daysSince(d?: Timestamp) {
+ if (!d || d.t_ms === 'never') return 'never synced'
+ const duration = intervalToDuration({
+ start: d.t_ms,
+ end: new Date(),
+ })
+ const str = formatDuration(duration, {
+ delimiter: ', ',
+ format: [
+ duration?.years ? 'years' : (
+ duration?.months ? 'months' : (
+ duration?.days ? 'days' : (
+ duration?.hours ? 'hours' : (
+ duration?.minutes ? 'minutes' : 'seconds'
+ )
+ )
+ )
+ )
+ ]
+ })
+ return `synced ${str} ago`
+}
diff --git a/packages/taler-wallet-webextension/src/popup/Transaction.tsx b/packages/taler-wallet-webextension/src/popup/Transaction.tsx
index 7a66d7a0e..d6a85d64d 100644
--- a/packages/taler-wallet-webextension/src/popup/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/popup/Transaction.tsx
@@ -97,7 +97,7 @@ export function TransactionView({ transaction, onDelete, onRetry, onBack }: Wall
return (
- {transaction.timestamp.t_ms === "never" ? "never" : format(transaction.timestamp.t_ms, 'dd/MM/yyyy HH:mm:ss')}
+ {transaction.timestamp.t_ms === "never" ? "never" : format(transaction.timestamp.t_ms, 'dd/MM/yyyy HH:mm:ss')}
From {transaction.exchangeBaseUrl}
diff --git a/packages/taler-wallet-webextension/src/popup/popup.tsx b/packages/taler-wallet-webextension/src/popup/popup.tsx
index 288e04477..6b8f110e1 100644
--- a/packages/taler-wallet-webextension/src/popup/popup.tsx
+++ b/packages/taler-wallet-webextension/src/popup/popup.tsx
@@ -36,6 +36,7 @@ export enum Pages {
backup = '/backup',
history = '/history',
transaction = '/transaction/:tid',
+ provider = '/provider/:currency',
}
interface TabProps {
diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
index c777e01de..8fb5121e5 100644
--- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
+++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
@@ -38,6 +38,7 @@ import { useTalerActionURL } from "./hooks/useTalerActionURL";
import { createHashHistory } from "history";
import { DevContextProvider } from "./context/useDevContext";
import { BackupPage } from "./popup/BackupPage";
+import { ProviderPage } from "./popup/ProviderPage.js";
function main(): void {
try {
@@ -99,6 +100,7 @@ function Application() {
+
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts
index 81f418d40..393c41102 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -38,8 +38,8 @@ import {
DeleteTransactionRequest,
RetryTransactionRequest,
} from "@gnu-taler/taler-util";
-import { BackupProviderState, OperationFailedError } from "@gnu-taler/taler-wallet-core";
-import { BackupInfo } from "@gnu-taler/taler-wallet-core/src/operations/backup";
+import { AddBackupProviderRequest, BackupProviderState, OperationFailedError } from "@gnu-taler/taler-wallet-core";
+import { BackupInfo } from "@gnu-taler/taler-wallet-core";
export interface ExtendedPermissionsResponse {
newValue: boolean;
@@ -166,9 +166,26 @@ export function listKnownCurrencies(): Promise {
/**
* Get information about the current state of wallet backups.
*/
- export function getBackupInfo(): Promise {
+export function getBackupInfo(): Promise {
return callBackend("getBackupInfo", {})
}
+
+/**
+ * Add a backup provider and activate it
+ */
+export function addBackupProvider(backupProviderBaseUrl: string): Promise {
+ return callBackend("addBackupProvider", {
+ backupProviderBaseUrl, activate: true
+ } as AddBackupProviderRequest)
+}
+
+export function syncAllProviders(): Promise {
+ return callBackend("runBackupCycle", {})
+}
+
+
+
+
/**
* Retry a transaction
* @param transactionId