new dev environment

This commit is contained in:
Sebastian 2022-03-25 16:57:27 -03:00
parent 00fb648269
commit ddfb40e50c
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
28 changed files with 1087 additions and 529 deletions

View File

@ -0,0 +1,4 @@
/mocha.css
/mocha.js
/mocha.js.map
/manifest.json

View File

@ -0,0 +1,48 @@
<html>
<head>
<meta charset="utf-8" />
<link rel="manifest" href="./manifest.json" />
</head>
<body>
<script>
function openPopup() {
window.frames["popup"].location = "/popup.html";
}
function openWallet() {
window.frames["wallet"].location = "/wallet.html";
}
function closeWallet() {
window.frames["wallet"].location = "about:blank";
}
</script>
<input type="text" />
<button value="asd" onclick="openPopup()">open popup</button>
<button value="asd" onclick="closeWallet();openWallet()">
reload wallet page
</button>
<hr />
<iframe
id="popup-window"
name="popup"
src="about:blank"
name="popup"
width="500"
height="325"
>
</iframe>
<hr />
<iframe
id="wallet-window"
name="wallet"
src="about:blank"
name="wallet"
width="800"
height="100%"
>
</iframe>
<hr />
<iframe src="/tests.html" name="wallet" width="800" height="100%"> </iframe>
<hr />
<script src="/dist/background.dev.js"></script>
</body>
</html>

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>
html {
font-family: sans-serif; /* 1 */
}
body {
margin: 0;
}
</style>
<style>
html {
}
h1 {
font-size: 2em;
}
input {
font: inherit;
}
body {
margin: 0;
font-size: 100%;
padding: 0;
overflow: hidden;
background-color: #f8faf7;
font-family: Arial, Helvetica, sans-serif;
}
</style>
<link rel="stylesheet" type="text/css" href="/dist/popupEntryPoint.css" />
<script src="/dist/popupEntryPoint.dev.js"></script>
</head>
<body>
<taler-popup id="container" class="popup-container"></taler-popup>
</body>
</html>

View File

@ -2,19 +2,18 @@
<html>
<head>
<title>Mocha Tests</title>
<link rel="stylesheet" href="node_modules/mocha/mocha.css" />
<link rel="stylesheet" href="/mocha.css" />
</head>
<body>
<div id="mocha"></div>
<script src="node_modules/mocha/mocha.js"></script>
<script src="/mocha.js"></script>
<script>
mocha.setup("bdd");
</script>
<!-- load code you want to test here -->
<script src="dist/stories.test.js"></script>
<script src="dist/hooks/useTalerActionURL.test.js"></script>
<script src="/dist/stories.test.js"></script>
<script src="/dist/hooks/useTalerActionURL.test.js"></script>
<!-- load your test files here -->
<script>

View File

@ -0,0 +1,29 @@
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="/dist/walletEntryPoint.css" />
<style>
html {
font-family: sans-serif; /* 1 */
}
h1 {
font-size: 2em;
}
input {
font: inherit;
}
body {
margin: 0;
font-size: 100%;
padding: 0;
background-color: #f8faf7;
font-family: Arial, Helvetica, sans-serif;
}
</style>
<script src="/dist/walletEntryPoint.dev.js"></script>
</head>
<body>
<div id="container" class="wallet-container"></div>
</body>
</html>

View File

@ -1,14 +0,0 @@
<html>
<head>
<link rel="manifest" href="./manifest.json" />
</head>
<body>
<iframe src="./static/popup.html" name="popup" width="500" height="400">
algo
</iframe>
<hr />
<iframe src="./static/wallet.html" name="wallet" width="800" height="100%">
otroe
</iframe>
</body>
</html>

View File

@ -0,0 +1,22 @@
import linaria from '@linaria/esbuild'
import esbuild from 'esbuild'
import { buildConfig } from "./build-fast-with-linaria.mjs"
import fs from 'fs';
fs.writeFileSync("dev-html/manifest.json", fs.readFileSync("manifest-v2.json"))
fs.writeFileSync("dev-html/mocha.css", fs.readFileSync("node_modules/mocha/mocha.css"))
fs.writeFileSync("dev-html/mocha.js", fs.readFileSync("node_modules/mocha/mocha.js"))
fs.writeFileSync("dev-html/mocha.js.map", fs.readFileSync("node_modules/mocha/mocha.js.map"))
const server = await esbuild
.serve({
servedir: 'dev-html',
}, { ...buildConfig, outdir: 'dev-html/dist' })
.catch((e) => {
console.log(e)
process.exit(1)
});
console.log("ready!", server.port);

View File

@ -0,0 +1,43 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Entry point for the background page.
*
* @author sebasjm
*/
/**
* Imports.
*/
import { platform, setupPlatform } from "./platform/api";
import devAPI from "./platform/dev"
import { wxMain } from "./wxBackend";
console.log("Wallet setup for Dev API")
setupPlatform(devAPI)
try {
platform.registerOnInstalled(() => {
platform.openWalletPage("/welcome")
})
} catch (e) {
console.error(e);
}
platform.notifyWhenAppIsReady(() => {
wxMain();
})

View File

@ -30,8 +30,8 @@ import { wxMain } from "./wxBackend";
const isFirefox = typeof (window as any)['InstallTrigger'] !== 'undefined'
//FIXME: create different entry point for any platform instead of
//switching in runtime
// FIXME: create different entry point for any platform instead of
// switching in runtime
if (isFirefox) {
console.log("Wallet setup for Firefox API")
setupPlatform(firefoxAPI)

View File

@ -32,7 +32,7 @@ const worker: Worker = self as any as Worker;
async function handleRequest(
operation: string,
id: number,
args: string[],
req: unknown,
): Promise<void> {
const impl = nativeCrypto;
@ -42,7 +42,7 @@ async function handleRequest(
}
try {
const result = await (impl as any)[operation](...args);
const result = await (impl as any)[operation](req);
worker.postMessage({ result, id });
} catch (e) {
logger.error("error during operation", e);
@ -51,9 +51,9 @@ async function handleRequest(
}
worker.onmessage = (msg: MessageEvent) => {
const args = msg.data.args;
if (!Array.isArray(args)) {
console.error("args must be array");
const req = msg.data.req;
if (typeof req !== "object") {
console.error("request must be an object");
return;
}
const id = msg.data.id;
@ -67,7 +67,7 @@ worker.onmessage = (msg: MessageEvent) => {
return;
}
handleRequest(operation, id, args).catch((e) => {
handleRequest(operation, id, req).catch((e) => {
console.error("error in browser worker", e);
});
};

View File

@ -143,7 +143,7 @@ export const Middle = styled.div`
export const PopupBox = styled.div<{ noPadding?: boolean; devMode: boolean }>`
height: 290px;
width: 500px;
overflow-y: scroll;
overflow-y: visible;
display: flex;
flex-direction: column;
justify-content: space-between;

View File

@ -40,41 +40,18 @@ async function handleExtendedPerm(isEnabled: boolean, onChange: (value: boolean)
if (!isEnabled) {
// We set permissions here, since apparently FF wants this to be done
// as the result of an input event ...
const granted = await platform.getPermissionsApi().request(getReadRequestPermissions());
console.log("permissions granted:", granted);
const lastError = platform.getLastError();
if (lastError) {
let granted: boolean;
try {
granted = await platform.getPermissionsApi().request(getReadRequestPermissions());
} catch (lastError) {
console.error("error requesting permissions");
console.error(lastError);
onChange(false);
return;
return
}
// try {
console.log("permissions granted:", granted);
const res = await wxApi.setExtendedPermissions(granted);
onChange(res.newValue);
// } finally {
// return
// }
// return new Promise<void>((res) => {
// platform.getPermissionsApi().request(getReadRequestPermissions(), async (granted: boolean) => {
// console.log("permissions granted:", granted);
// const lastError = getLastError()
// if (lastError) {
// console.error("error requesting permissions");
// console.error(lastError);
// onChange(false);
// return;
// }
// try {
// const res = await wxApi.setExtendedPermissions(granted);
// onChange(res.newValue);
// } finally {
// res()
// }
// });
// })
}
await wxApi.setExtendedPermissions(false).then(r => onChange(r.newValue));
return

View File

@ -38,7 +38,7 @@ export interface CrossBrowserPermissionsApi {
request(p: Permissions): Promise<boolean>;
remove(p: Permissions): Promise<boolean>;
addPermissionsListener(callback: (p: Permissions) => void): void;
addPermissionsListener(callback: (p: Permissions, lastError?: string) => void): void;
}
@ -57,31 +57,132 @@ export interface WalletVersion {
*/
export interface PlatformAPI {
/**
* FIXME: should not be needed
*
* check if the platform is firefox
*/
isFirefox(): boolean;
/**
*
* Permission API for checking and add a listener
*/
getPermissionsApi(): CrossBrowserPermissionsApi;
/**
* Backend API
*
* Register a callback to be called when the wallet is ready to start
* @param callback
*/
notifyWhenAppIsReady(callback: () => void): void;
openWalletURIFromPopup(uriType: TalerUriType, talerUri: string): void;
/**
* Popup API
*
* Used when an TalerURI is found and open up from the popup UI.
* Closes the popup and open the URI into the wallet UI.
*
* @param talerUri
*/
openWalletURIFromPopup(talerUri: string): void;
/**
* Backend API
*
* Open a page into the wallet UI
* @param page
*/
openWalletPage(page: string): void;
/**
* Popup API
*
* Open a page into the wallet UI and closed the popup
* @param page
*/
openWalletPageFromPopup(page: string): void;
setMessageToWalletBackground(operation: string, payload: any): Promise<CoreApiResponse>;
listenToWalletNotifications(listener: (m: any) => void): () => void;
sendMessageToAllChannels(message: MessageFromBackend): void;
registerAllIncomingConnections(): void;
registerOnNewMessage(onNewMessage: (message: any, sender: any, callback: any) => void): void;
registerReloadOnNewVersion(): void;
/**
* Backend API
*
* When a tab has been detected to have a Taler action the background process
* can use this function to redirect the tab to the wallet UI
*
* @param tabId
* @param page
*/
redirectTabToWalletPage(tabId: number, page: string): void;
/**
* Get the wallet version from manifest
*/
getWalletVersion(): WalletVersion;
/**
* Backend API
*/
registerAllIncomingConnections(): void;
/**
* Backend API
*/
registerReloadOnNewVersion(): void;
/**
* Backend API
*/
registerTalerHeaderListener(onHeader: (tabId: number, url: string) => void): void;
/**
* Backend API
*/
registerOnInstalled(callback: () => void): void;
/**
* Backend API
*
* Check if background process run as service worker. This is used from the
* wallet use different http api and crypto worker.
*/
useServiceWorkerAsBackgroundProcess(): boolean;
getLastError(): string | undefined;
searchForTalerLinks(): string | undefined;
/**
* Popup API
*
* Read the current tab html and try to find any Taler URI or QR code present.
*
* @return Taler URI if found
*/
findTalerUriInActiveTab(): Promise<string | undefined>;
/**
* Used from the frontend to send commands to the wallet
*
* @param operation
* @param payload
*
* @return response from the backend
*/
sendMessageToWalletBackground(operation: string, payload: any): Promise<CoreApiResponse>;
/**
* Used from the frontend to receive notifications about new information
* @param listener
* @return function to unsubscribe the listener
*/
listenToWalletBackground(listener: (message: MessageFromBackend) => void): () => void;
/**
* Use by the wallet backend to receive operations from frontend (popup & wallet)
* and send a response back.
*
* @param onNewMessage
*/
listenToAllChannels(onNewMessage: (message: any, sender: any, sendResponse: (r: CoreApiResponse) => void) => void): void;
/**
* Used by the wallet backend to send notification about new information
* @param message
*/
sendMessageToAllChannels(message: MessageFromBackend): void;
}
export let platform: PlatformAPI = undefined as any;

View File

@ -14,17 +14,16 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { TalerUriType } from "@gnu-taler/taler-util";
import { classifyTalerUri, CoreApiResponse, TalerUriType } from "@gnu-taler/taler-util";
import { getReadRequestPermissions } from "../permissions";
import { CrossBrowserPermissionsApi, MessageFromBackend, Permissions, PlatformAPI } from "./api.js";
const api: PlatformAPI = {
isFirefox,
findTalerUriInActiveTab,
getLastError,
getPermissionsApi,
getWalletVersion,
listenToWalletNotifications,
listenToWalletBackground,
notifyWhenAppIsReady,
openWalletPage,
openWalletPageFromPopup,
@ -32,12 +31,11 @@ const api: PlatformAPI = {
redirectTabToWalletPage,
registerAllIncomingConnections,
registerOnInstalled,
registerOnNewMessage,
listenToAllChannels,
registerReloadOnNewVersion,
registerTalerHeaderListener,
searchForTalerLinks,
sendMessageToAllChannels,
setMessageToWalletBackground,
sendMessageToWalletBackground,
useServiceWorkerAsBackgroundProcess
}
@ -50,7 +48,7 @@ function isFirefox(): boolean {
export function contains(p: Permissions): Promise<boolean> {
return new Promise((res, rej) => {
chrome.permissions.contains(p, (resp) => {
const le = getLastError()
const le = chrome.runtime.lastError?.message
if (le) {
rej(le)
}
@ -62,7 +60,7 @@ export function contains(p: Permissions): Promise<boolean> {
export async function request(p: Permissions): Promise<boolean> {
return new Promise((res, rej) => {
chrome.permissions.request(p, (resp) => {
const le = getLastError()
const le = chrome.runtime.lastError?.message
if (le) {
rej(le)
}
@ -74,7 +72,7 @@ export async function request(p: Permissions): Promise<boolean> {
export async function remove(p: Permissions): Promise<boolean> {
return new Promise((res, rej) => {
chrome.permissions.remove(p, (resp) => {
const le = getLastError()
const le = chrome.runtime.lastError?.message
if (le) {
rej(le)
}
@ -83,9 +81,12 @@ export async function remove(p: Permissions): Promise<boolean> {
})
}
function addPermissionsListener(callback: (p: Permissions) => void): void {
function addPermissionsListener(callback: (p: Permissions, lastError?: string) => void): void {
console.log("addPermissionListener is not supported for Firefox");
chrome.permissions.onAdded.addListener(callback)
chrome.permissions.onAdded.addListener((perm: Permissions) => {
const lastError = chrome.runtime.lastError?.message;
callback(perm, lastError)
})
}
function getPermissionsApi(): CrossBrowserPermissionsApi {
@ -107,7 +108,9 @@ function notifyWhenAppIsReady(callback: () => void) {
}
function openWalletURIFromPopup(uriType: TalerUriType, talerUri: string) {
function openWalletURIFromPopup(talerUri: string) {
const uriType = classifyTalerUri(talerUri);
let url: string | undefined = undefined;
switch (uriType) {
case TalerUriType.TalerWithdraw:
@ -150,7 +153,7 @@ function openWalletPageFromPopup(page: string) {
);
}
async function setMessageToWalletBackground(operation: string, payload: any): Promise<any> {
async function sendMessageToWalletBackground(operation: string, payload: any): Promise<any> {
return new Promise<any>((resolve, reject) => {
chrome.runtime.sendMessage({ operation, payload, id: "(none)" }, (resp) => {
if (chrome.runtime.lastError) {
@ -164,7 +167,7 @@ async function setMessageToWalletBackground(operation: string, payload: any): Pr
}
let notificationPort: chrome.runtime.Port | undefined;
function listenToWalletNotifications(listener: (m: any) => void) {
function listenToWalletBackground(listener: (m: any) => void) {
if (notificationPort === undefined) {
notificationPort = chrome.runtime.connect({ name: "notifications" })
}
@ -203,7 +206,7 @@ function registerAllIncomingConnections() {
});
}
function registerOnNewMessage(cb: (message: any, sender: any, callback: any) => void) {
function listenToAllChannels(cb: (message: any, sender: any, callback: (r: CoreApiResponse) => void) => void) {
chrome.runtime.onMessage.addListener((m, s, c) => {
cb(m, s, c)
@ -311,11 +314,6 @@ function useServiceWorkerAsBackgroundProcess() {
return chrome.runtime.getManifest().manifest_version === 3
}
function getLastError() {
return chrome.runtime.lastError?.message;
}
function searchForTalerLinks(): string | undefined {
let found;
found = document.querySelector("a[href^='taler://'")

View File

@ -0,0 +1,159 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { classifyTalerUri, CoreApiResponse, TalerUriType } from "@gnu-taler/taler-util";
import { MessageFromBackend, PlatformAPI } from "./api";
const frames = ["popup", "wallet"]
const api: PlatformAPI = ({
isFirefox: () => false,
findTalerUriInActiveTab: async () => undefined,
getPermissionsApi: () => ({
addPermissionsListener: () => undefined, contains: async () => true, remove: async () => false, request: async () => false
}),
getWalletVersion: () => ({
version: 'none'
}),
notifyWhenAppIsReady: (fn: () => void) => {
let total = frames.length
function waitAndNotify() {
total--
if (total < 1) {
console.log('done')
fn()
}
}
frames.forEach(f => {
const theFrame = window.frames[f as any]
if (theFrame.location.href === 'about:blank') {
waitAndNotify()
} else {
theFrame.addEventListener("load", waitAndNotify)
}
})
},
openWalletPage: (page: string) => {
window.frames['wallet' as any].location = `/wallet.html#${page}`
},
openWalletPageFromPopup: (page: string) => {
window.parent.frames['wallet' as any].location = `/wallet.html#${page}`
window.location.href = "about:blank"
},
openWalletURIFromPopup: (page: string) => {
alert('openWalletURIFromPopup not implemented yet')
},
redirectTabToWalletPage: (tabId: number, page: string) => {
alert('redirectTabToWalletPage not implemented yet')
},
registerAllIncomingConnections: () => undefined,
registerOnInstalled: (fn: () => void) => fn(),
registerReloadOnNewVersion: () => undefined,
registerTalerHeaderListener: () => undefined,
useServiceWorkerAsBackgroundProcess: () => false,
listenToAllChannels: (fn: (m: any, s: any, c: (r: CoreApiResponse) => void) => void) => {
window.addEventListener("message", (event: MessageEvent<IframeMessageType>) => {
if (event.data.type !== 'command') return
const sender = event.data.header.replyMe
fn(event.data.body, sender, (resp: CoreApiResponse) => {
if (event.source) {
const msg: IframeMessageResponse = {
type: "response",
header: { responseId: sender },
body: resp
}
window.parent.postMessage(msg)
}
})
})
},
sendMessageToAllChannels: (message: MessageFromBackend) => {
Array.from(window.frames).forEach(w => {
try {
w.postMessage({
header: {}, body: message
});
} catch (e) {
console.error(e)
}
})
},
listenToWalletBackground: (onNewMessage: (m: MessageFromBackend) => void) => {
function listener(event: MessageEvent<IframeMessageType>) {
if (event.data.type !== 'notification') return
onNewMessage(event.data.body)
}
window.parent.addEventListener("message", listener)
return () => {
window.parent.removeEventListener("message", listener)
}
},
sendMessageToWalletBackground: async (operation: string, payload: any) => {
const replyMe = `reply-${Math.floor(Math.random() * 100000)}`
const message: IframeMessageCommand = {
type: 'command',
header: { replyMe },
body: { operation, payload, id: "(none)" }
}
window.parent.postMessage(message)
return new Promise((res, rej) => {
function listener(event: MessageEvent<IframeMessageType>) {
if (event.data.type !== "response" || event.data.header.responseId !== replyMe) {
return
}
res(event.data.body)
window.parent.removeEventListener("message", listener)
}
window.parent.addEventListener("message", listener, {
})
})
},
})
type IframeMessageType = IframeMessageNotification | IframeMessageResponse | IframeMessageCommand;
interface IframeMessageNotification {
type: "notification";
header: {
},
body: MessageFromBackend
}
interface IframeMessageResponse {
type: "response";
header: {
responseId: string;
},
body: CoreApiResponse
}
interface IframeMessageCommand {
type: "command";
header: {
replyMe: string;
},
body: {
operation: any, id: string, payload: any
}
}
export default api;

View File

@ -0,0 +1,183 @@
/*
This file is part of GNU Taler
(C) 2020 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Main entry point for extension pages.
*
* @author sebasjm
*/
import { createHashHistory } from "history";
import { Fragment, h, VNode } from "preact";
import Router, { route, Route } from "preact-router";
import { Match } from "preact-router/match";
import { useEffect, useState } from "preact/hooks";
import PendingTransactions from "../components/PendingTransactions";
import { PopupBox } from "../components/styled";
import { DevContextProvider } from "../context/devContext";
import { IoCProviderForRuntime } from "../context/iocContext";
import {
TranslationProvider,
useTranslationContext,
} from "../context/translation";
import { useTalerActionURL } from "../hooks/useTalerActionURL";
import { Pages, PopupNavBar } from "../NavigationBar";
import { platform } from "../platform/api";
import { BackupPage } from "../wallet/BackupPage";
import { ProviderDetailPage } from "../wallet/ProviderDetailPage";
import { BalancePage } from "./BalancePage";
import { TalerActionFound } from "./TalerActionFound";
function CheckTalerActionComponent(): VNode {
const [talerActionUrl] = useTalerActionURL();
useEffect(() => {
if (talerActionUrl)
route(Pages.cta.replace(":action", encodeURIComponent(talerActionUrl)));
}, [talerActionUrl]);
return <Fragment />;
}
export function Application(): VNode {
const hash_history = createHashHistory();
return (
<TranslationProvider>
<DevContextProvider>
{({ devMode }: { devMode: boolean }) => (
<IoCProviderForRuntime>
<PendingTransactions
goToTransaction={(txId: string) =>
route(Pages.balance_transaction.replace(":tid", txId))
}
/>
<Match>
{({ path }: { path: string }) => <PopupNavBar path={path} />}
</Match>
<CheckTalerActionComponent />
<PopupBox devMode={devMode}>
<Router history={hash_history}>
<Route
path={Pages.balance}
component={BalancePage}
goToWalletManualWithdraw={() =>
route(
Pages.balance_manual_withdraw.replace(":currency?", ""),
)
}
goToWalletDeposit={(currency: string) =>
route(Pages.balance_deposit.replace(":currency", currency))
}
goToWalletHistory={(currency: string) =>
route(Pages.balance_history.replace(":currency?", currency))
}
/>
<Route
path={Pages.cta}
component={function Action({ action }: { action: string }) {
const [, setDismissed] = useTalerActionURL();
return (
<TalerActionFound
url={decodeURIComponent(action)}
onDismiss={() => {
setDismissed(true);
route(Pages.balance);
}}
/>
);
}}
/>
<Route
path={Pages.backup}
component={BackupPage}
onAddProvider={() => {
route(Pages.backup_provider_add);
}}
/>
<Route
path={Pages.backup_provider_detail}
component={ProviderDetailPage}
onBack={() => {
route(Pages.backup);
}}
/>
<Route
path={Pages.balance_transaction}
component={RedirectToWalletPage}
/>
<Route
path={Pages.balance_manual_withdraw}
component={RedirectToWalletPage}
/>
<Route
path={Pages.balance_deposit}
component={RedirectToWalletPage}
/>
<Route
path={Pages.balance_history}
component={RedirectToWalletPage}
/>
<Route
path={Pages.backup_provider_add}
component={RedirectToWalletPage}
/>
<Route path={Pages.settings} component={RedirectToWalletPage} />
<Route
path={Pages.settings_exchange_add}
component={RedirectToWalletPage}
/>
<Route path={Pages.dev} component={RedirectToWalletPage} />
<Route default component={Redirect} to={Pages.balance} />
</Router>
</PopupBox>
</IoCProviderForRuntime>
)}
</DevContextProvider>
</TranslationProvider>
);
}
function RedirectToWalletPage(): VNode {
const page = (document.location.hash || "#/").replace("#", "");
const [showText, setShowText] = useState(false);
useEffect(() => {
platform.openWalletPageFromPopup(page);
setTimeout(() => {
setShowText(true);
}, 250);
});
const { i18n } = useTranslationContext();
if (!showText) return <Fragment />;
return (
<span>
<i18n.Translate>
this popup is being closed and you are being redirected to {page}
</i18n.Translate>
</span>
);
}
function Redirect({ to }: { to: string }): null {
useEffect(() => {
route(to, true);
});
return null;
}

View File

@ -34,7 +34,7 @@ export function TalerActionFound({ url, onDismiss }: Props) {
const uriType = classifyTalerUri(url);
const { i18n } = useTranslationContext();
function redirectToWallet() {
platform.openWalletURIFromPopup(uriType, url);
platform.openWalletURIFromPopup(url);
}
return (
<Fragment>

View File

@ -0,0 +1,54 @@
/*
This file is part of GNU Taler
(C) 2020 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Main entry point for extension pages.
*
* @author sebasjm
*/
import { setupI18n } from "@gnu-taler/taler-util";
import { Fragment, h, render } from "preact";
import { strings } from "./i18n/strings";
import { setupPlatform } from "./platform/api";
import devAPI from "./platform/dev";
import { Application } from "./popup/Application";
console.log("Wallet setup for Dev API");
setupPlatform(devAPI);
function main(): void {
try {
const container = document.getElementById("container");
if (!container) {
throw Error("container not found, can't mount page contents");
}
render(<Application />, container);
} catch (e) {
console.error("got error", e);
if (e instanceof Error) {
document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
}
}
}
setupI18n("en", strings);
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", main);
} else {
main();
}

View File

@ -21,29 +21,23 @@
*/
import { setupI18n } from "@gnu-taler/taler-util";
import { createHashHistory } from "history";
import { Fragment, h, render, VNode } from "preact";
import Router, { route, Route } from "preact-router";
import { Match } from "preact-router/match";
import { useEffect, useState } from "preact/hooks";
import PendingTransactions from "./components/PendingTransactions";
import { PopupBox } from "./components/styled";
import { DevContextProvider } from "./context/devContext";
import { IoCProviderForRuntime } from "./context/iocContext";
import {
TranslationProvider,
useTranslationContext,
} from "./context/translation";
import { useTalerActionURL } from "./hooks/useTalerActionURL";
import { Fragment, h, render } from "preact";
import { strings } from "./i18n/strings";
import { Pages, PopupNavBar } from "./NavigationBar";
import { platform, setupPlatform } from "./platform/api";
import { setupPlatform } from "./platform/api";
import chromeAPI from "./platform/chrome";
import firefoxAPI from "./platform/firefox";
import { BalancePage } from "./popup/BalancePage";
import { TalerActionFound } from "./popup/TalerActionFound";
import { BackupPage } from "./wallet/BackupPage";
import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
import { Application } from "./popup/Application";
//FIXME: create different entry point for any platform instead of
//switching in runtime
const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
if (isFirefox) {
console.log("Wallet setup for Firefox API");
setupPlatform(firefoxAPI);
} else {
console.log("Wallet setup for Chrome API");
setupPlatform(chromeAPI);
}
function main(): void {
try {
@ -62,160 +56,8 @@ function main(): void {
setupI18n("en", strings);
//FIXME: create different entry point for any platform instead of
//switching in runtime
const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
if (isFirefox) {
console.log("Wallet setup for Firefox API");
setupPlatform(firefoxAPI);
} else {
console.log("Wallet setup for Chrome API");
setupPlatform(chromeAPI);
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", main);
} else {
main();
}
function CheckTalerActionComponent(): VNode {
const [talerActionUrl] = useTalerActionURL();
useEffect(() => {
if (talerActionUrl)
route(Pages.cta.replace(":action", encodeURIComponent(talerActionUrl)));
}, [talerActionUrl]);
return <Fragment />;
}
function Application(): VNode {
const hash_history = createHashHistory();
return (
<TranslationProvider>
<DevContextProvider>
{({ devMode }: { devMode: boolean }) => (
<IoCProviderForRuntime>
<PendingTransactions
goToTransaction={(txId: string) =>
route(Pages.balance_transaction.replace(":tid", txId))
}
/>
<Match>
{({ path }: { path: string }) => <PopupNavBar path={path} />}
</Match>
<CheckTalerActionComponent />
<PopupBox devMode={devMode}>
<Router history={hash_history}>
<Route
path={Pages.balance}
component={BalancePage}
goToWalletManualWithdraw={() =>
route(
Pages.balance_manual_withdraw.replace(":currency?", ""),
)
}
goToWalletDeposit={(currency: string) =>
route(Pages.balance_deposit.replace(":currency", currency))
}
goToWalletHistory={(currency: string) =>
route(Pages.balance_history.replace(":currency?", currency))
}
/>
<Route
path={Pages.cta}
component={function Action({ action }: { action: string }) {
const [, setDismissed] = useTalerActionURL();
return (
<TalerActionFound
url={decodeURIComponent(action)}
onDismiss={() => {
setDismissed(true);
route(Pages.balance);
}}
/>
);
}}
/>
<Route
path={Pages.backup}
component={BackupPage}
onAddProvider={() => {
route(Pages.backup_provider_add);
}}
/>
<Route
path={Pages.backup_provider_detail}
component={ProviderDetailPage}
onBack={() => {
route(Pages.backup);
}}
/>
<Route
path={Pages.balance_transaction}
component={RedirectToWalletPage}
/>
<Route
path={Pages.balance_manual_withdraw}
component={RedirectToWalletPage}
/>
<Route
path={Pages.balance_deposit}
component={RedirectToWalletPage}
/>
<Route
path={Pages.balance_history}
component={RedirectToWalletPage}
/>
<Route
path={Pages.backup_provider_add}
component={RedirectToWalletPage}
/>
<Route path={Pages.settings} component={RedirectToWalletPage} />
<Route
path={Pages.settings_exchange_add}
component={RedirectToWalletPage}
/>
<Route path={Pages.dev} component={RedirectToWalletPage} />
<Route default component={Redirect} to={Pages.balance} />
</Router>
</PopupBox>
</IoCProviderForRuntime>
)}
</DevContextProvider>
</TranslationProvider>
);
}
function RedirectToWalletPage(): VNode {
const page = (document.location.hash || "#/").replace("#", "");
const [showText, setShowText] = useState(false);
useEffect(() => {
platform.openWalletPageFromPopup(page);
setTimeout(() => {
setShowText(true);
}, 250);
});
const { i18n } = useTranslationContext();
if (!showText) return <Fragment />;
return (
<span>
<i18n.Translate>
this popup is being closed and you are being redirected to {page}
</i18n.Translate>
</span>
);
}
function Redirect({ to }: { to: string }): null {
useEffect(() => {
route(to, true);
});
return null;
}

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="92px" height="92px" viewBox="0 0 92 92" enable-background="new 0 0 92 92" xml:space="preserve">
<path id="XMLID_467_" d="M46,63c-1.1,0-2.1-0.4-2.9-1.2l-25-26c-1.5-1.6-1.5-4.1,0.1-5.7c1.6-1.5,4.1-1.5,5.7,0.1l22.1,23l22.1-23
c1.5-1.6,4.1-1.6,5.7-0.1c1.6,1.5,1.6,4.1,0.1,5.7l-25,26C48.1,62.6,47.1,63,46,63z"/>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 92 92" enable-background="new 0 0 92 92" xml:space="preserve">
<path id="XMLID_467_" d="M46,63c-1.1,0-2.1-0.4-2.9-1.2l-25-26c-1.5-1.6-1.5-4.1,0.1-5.7c1.6-1.5,4.1-1.5,5.7,0.1l22.1,23l22.1-23
c1.5-1.6,4.1-1.6,5.7-0.1c1.6,1.5,1.6,4.1,0.1,5.7l-25,26C48.1,62.6,47.1,63,46,63z" />
</svg>

Before

Width:  |  Height:  |  Size: 584 B

After

Width:  |  Height:  |  Size: 556 B

View File

@ -15,7 +15,7 @@ export function AddNewActionView({ onCancel }: Props): VNode {
const { i18n } = useTranslationContext();
function redirectToWallet() {
platform.openWalletURIFromPopup(uriType, url);
platform.openWalletURIFromPopup(url);
}
return (

View File

@ -0,0 +1,263 @@
/*
This file is part of GNU Taler
(C) 2020 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Main entry point for extension pages.
*
* @author sebasjm
*/
import { createHashHistory } from "history";
import { Fragment, h, VNode } from "preact";
import Router, { route, Route } from "preact-router";
import Match from "preact-router/match";
import { useEffect, useState } from "preact/hooks";
import { LogoHeader } from "../components/LogoHeader";
import PendingTransactions from "../components/PendingTransactions";
import { SuccessBox, WalletBox } from "../components/styled";
import { DevContextProvider } from "../context/devContext";
import { IoCProviderForRuntime } from "../context/iocContext";
import {
TranslationProvider,
useTranslationContext,
} from "../context/translation";
import { PayPage } from "../cta/Pay";
import { RefundPage } from "../cta/Refund";
import { TipPage } from "../cta/Tip";
import { WithdrawPage } from "../cta/Withdraw";
import { Pages, WalletNavBar } from "../NavigationBar";
import { DeveloperPage } from "../popup/DeveloperPage";
import { BackupPage } from "./BackupPage";
import { DepositPage } from "./DepositPage";
import { ExchangeAddPage } from "./ExchangeAddPage";
import { HistoryPage } from "./History";
import { ManualWithdrawPage } from "./ManualWithdrawPage";
import { ProviderAddPage } from "./ProviderAddPage";
import { ProviderDetailPage } from "./ProviderDetailPage";
import { SettingsPage } from "./Settings";
import { TransactionPage } from "./Transaction";
import { WelcomePage } from "./Welcome";
export function Application(): VNode {
const [globalNotification, setGlobalNotification] = useState<
VNode | undefined
>(undefined);
const hash_history = createHashHistory();
function clearNotification(): void {
setGlobalNotification(undefined);
}
function clearNotificationWhenMovingOut(): void {
// const movingOutFromNotification =
// globalNotification && e.url !== globalNotification.to;
if (globalNotification) {
//&& movingOutFromNotification) {
setGlobalNotification(undefined);
}
}
const { i18n } = useTranslationContext();
return (
<TranslationProvider>
<DevContextProvider>
<IoCProviderForRuntime>
{/* <Match/> won't work in the first render if <Router /> is not called first */}
{/* https://github.com/preactjs/preact-router/issues/415 */}
<Router history={hash_history} />
<Match>
{({ path }: { path: string }) => {
if (path && path.startsWith("/cta")) return;
return (
<Fragment>
<LogoHeader />
<WalletNavBar path={path} />
<div
style={{
backgroundColor: "lightcyan",
display: "flex",
justifyContent: "center",
}}
>
<PendingTransactions
goToTransaction={(txId: string) =>
route(Pages.balance_transaction.replace(":tid", txId))
}
/>
</div>
</Fragment>
);
}}
</Match>
<WalletBox>
{globalNotification && (
<SuccessBox onClick={clearNotification}>
<div>{globalNotification}</div>
</SuccessBox>
)}
<Router
history={hash_history}
onChange={clearNotificationWhenMovingOut}
>
<Route path={Pages.welcome} component={WelcomePage} />
{/**
* BALANCE
*/}
<Route
path={Pages.balance_history}
component={HistoryPage}
goToWalletDeposit={(currency: string) =>
route(Pages.balance_deposit.replace(":currency", currency))
}
goToWalletManualWithdraw={(currency?: string) =>
route(
Pages.balance_manual_withdraw.replace(
":currency?",
currency || "",
),
)
}
/>
<Route
path={Pages.balance_transaction}
component={TransactionPage}
goToWalletHistory={(currency?: string) => {
route(
Pages.balance_history.replace(":currency?", currency || ""),
);
}}
/>
<Route
path={Pages.balance_manual_withdraw}
component={ManualWithdrawPage}
onCancel={() => {
route(Pages.balance);
}}
/>
<Route
path={Pages.balance_deposit}
component={DepositPage}
onCancel={(currency: string) => {
route(Pages.balance_history.replace(":currency?", currency));
}}
onSuccess={(currency: string) => {
route(Pages.balance_history.replace(":currency?", currency));
setGlobalNotification(
<i18n.Translate>
All done, your transaction is in progress
</i18n.Translate>,
);
}}
/>
{/**
* PENDING
*/}
<Route path={Pages.settings} component={SettingsPage} />
{/**
* BACKUP
*/}
<Route
path={Pages.backup}
component={BackupPage}
onAddProvider={() => {
route(Pages.backup_provider_add);
}}
/>
<Route
path={Pages.backup_provider_detail}
component={ProviderDetailPage}
onBack={() => {
route(Pages.backup);
}}
/>
<Route
path={Pages.backup_provider_add}
component={ProviderAddPage}
onBack={() => {
route(Pages.backup);
}}
/>
{/**
* SETTINGS
*/}
<Route
path={Pages.settings_exchange_add}
component={ExchangeAddPage}
onBack={() => {
route(Pages.balance);
}}
/>
{/**
* DEV
*/}
<Route path={Pages.dev} component={DeveloperPage} />
{/**
* CALL TO ACTION
*/}
<Route
path={Pages.cta_pay}
component={PayPage}
goToWalletManualWithdraw={(currency?: string) =>
route(
Pages.balance_manual_withdraw.replace(
":currency?",
currency || "",
),
)
}
goBack={() => route(Pages.balance)}
/>
<Route path={Pages.cta_refund} component={RefundPage} />
<Route path={Pages.cta_tips} component={TipPage} />
<Route path={Pages.cta_withdraw} component={WithdrawPage} />
{/**
* NOT FOUND
* all redirects should be at the end
*/}
<Route
path={Pages.balance}
component={Redirect}
to={Pages.balance_history.replace(":currency?", "")}
/>
<Route
default
component={Redirect}
to={Pages.balance_history.replace(":currency?", "")}
/>
</Router>
</WalletBox>
</IoCProviderForRuntime>
</DevContextProvider>
</TranslationProvider>
);
}
function Redirect({ to }: { to: string }): null {
useEffect(() => {
console.log("got some wrong route", to);
route(to, true);
});
return null;
}

View File

@ -253,9 +253,6 @@ export function View({
There is no known bank account to send money to
</i18n.Translate>
</p>
<ButtonBoxWarning>
<i18n.Translate>Withdraw</i18n.Translate>
</ButtonBoxWarning>
</WarningBox>
<footer>
<Button onClick={onCancel}>

View File

@ -0,0 +1,54 @@
/*
This file is part of GNU Taler
(C) 2020 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
* Main entry point for extension pages.
*
* @author sebasjm
*/
import { setupI18n } from "@gnu-taler/taler-util";
import { Fragment, h, render } from "preact";
import { strings } from "./i18n/strings";
import { setupPlatform } from "./platform/api";
import devAPI from "./platform/dev";
import { Application } from "./wallet/Application";
console.log("Wallet setup for Dev API");
setupPlatform(devAPI);
function main(): void {
try {
const container = document.getElementById("container");
if (!container) {
throw Error("container not found, can't mount page contents");
}
render(<Application />, container);
} catch (e) {
console.error("got error", e);
if (e instanceof Error) {
document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
}
}
}
setupI18n("en", strings);
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", main);
} else {
main();
}

View File

@ -21,40 +21,24 @@
*/
import { setupI18n } from "@gnu-taler/taler-util";
import { createHashHistory } from "history";
import { Fragment, h, render, VNode } from "preact";
import Router, { route, Route } from "preact-router";
import Match from "preact-router/match";
import { useEffect, useState } from "preact/hooks";
import { LogoHeader } from "./components/LogoHeader";
import PendingTransactions from "./components/PendingTransactions";
import { SuccessBox, WalletBox } from "./components/styled";
import { DevContextProvider } from "./context/devContext";
import { IoCProviderForRuntime } from "./context/iocContext";
import {
TranslationProvider,
useTranslationContext,
} from "./context/translation";
import { PayPage } from "./cta/Pay";
import { RefundPage } from "./cta/Refund";
import { TipPage } from "./cta/Tip";
import { WithdrawPage } from "./cta/Withdraw";
import { Fragment, h, render } from "preact";
import { strings } from "./i18n/strings";
import { Pages, WalletNavBar } from "./NavigationBar";
import { setupPlatform } from "./platform/api";
import chromeAPI from "./platform/chrome";
import firefoxAPI from "./platform/firefox";
import { DeveloperPage } from "./popup/DeveloperPage";
import { BackupPage } from "./wallet/BackupPage";
import { DepositPage } from "./wallet/DepositPage";
import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
import { HistoryPage } from "./wallet/History";
import { ManualWithdrawPage } from "./wallet/ManualWithdrawPage";
import { ProviderAddPage } from "./wallet/ProviderAddPage";
import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
import { SettingsPage } from "./wallet/Settings";
import { TransactionPage } from "./wallet/Transaction";
import { WelcomePage } from "./wallet/Welcome";
import { Application } from "./wallet/Application";
const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
//FIXME: create different entry point for any platform instead of
//switching in runtime
if (isFirefox) {
console.log("Wallet setup for Firefox API");
setupPlatform(firefoxAPI);
} else {
console.log("Wallet setup for Chrome API");
setupPlatform(chromeAPI);
}
function main(): void {
try {
@ -73,230 +57,8 @@ function main(): void {
setupI18n("en", strings);
const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
//FIXME: create different entry point for any platform instead of
//switching in runtime
if (isFirefox) {
console.log("Wallet setup for Firefox API");
setupPlatform(firefoxAPI);
} else {
console.log("Wallet setup for Chrome API");
setupPlatform(chromeAPI);
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", main);
} else {
main();
}
function Application(): VNode {
const [globalNotification, setGlobalNotification] = useState<
VNode | undefined
>(undefined);
const hash_history = createHashHistory();
function clearNotification(): void {
setGlobalNotification(undefined);
}
function clearNotificationWhenMovingOut(): void {
// const movingOutFromNotification =
// globalNotification && e.url !== globalNotification.to;
if (globalNotification) {
//&& movingOutFromNotification) {
setGlobalNotification(undefined);
}
}
const { i18n } = useTranslationContext();
return (
<TranslationProvider>
<DevContextProvider>
<IoCProviderForRuntime>
{/* <Match/> won't work in the first render if <Router /> is not called first */}
{/* https://github.com/preactjs/preact-router/issues/415 */}
<Router history={hash_history} />
<Match>
{({ path }: { path: string }) => {
if (path && path.startsWith("/cta")) return;
return (
<Fragment>
<LogoHeader />
<WalletNavBar path={path} />
<div
style={{
backgroundColor: "lightcyan",
display: "flex",
justifyContent: "center",
}}
>
<PendingTransactions
goToTransaction={(txId: string) =>
route(Pages.balance_transaction.replace(":tid", txId))
}
/>
</div>
</Fragment>
);
}}
</Match>
<WalletBox>
{globalNotification && (
<SuccessBox onClick={clearNotification}>
<div>{globalNotification}</div>
</SuccessBox>
)}
<Router
history={hash_history}
onChange={clearNotificationWhenMovingOut}
>
<Route path={Pages.welcome} component={WelcomePage} />
{/**
* BALANCE
*/}
<Route
path={Pages.balance_history}
component={HistoryPage}
goToWalletDeposit={(currency: string) =>
route(Pages.balance_deposit.replace(":currency", currency))
}
goToWalletManualWithdraw={(currency?: string) =>
route(
Pages.balance_manual_withdraw.replace(
":currency?",
currency || "",
),
)
}
/>
<Route
path={Pages.balance_transaction}
component={TransactionPage}
goToWalletHistory={(currency?: string) => {
route(
Pages.balance_history.replace(":currency?", currency || ""),
);
}}
/>
<Route
path={Pages.balance_manual_withdraw}
component={ManualWithdrawPage}
onCancel={() => {
route(Pages.balance);
}}
/>
<Route
path={Pages.balance_deposit}
component={DepositPage}
onCancel={(currency: string) => {
route(Pages.balance_history.replace(":currency?", currency));
}}
onSuccess={(currency: string) => {
route(Pages.balance_history.replace(":currency?", currency));
setGlobalNotification(
<i18n.Translate>
All done, your transaction is in progress
</i18n.Translate>,
);
}}
/>
{/**
* PENDING
*/}
<Route path={Pages.settings} component={SettingsPage} />
{/**
* BACKUP
*/}
<Route
path={Pages.backup}
component={BackupPage}
onAddProvider={() => {
route(Pages.backup_provider_add);
}}
/>
<Route
path={Pages.backup_provider_detail}
component={ProviderDetailPage}
onBack={() => {
route(Pages.backup);
}}
/>
<Route
path={Pages.backup_provider_add}
component={ProviderAddPage}
onBack={() => {
route(Pages.backup);
}}
/>
{/**
* SETTINGS
*/}
<Route
path={Pages.settings_exchange_add}
component={ExchangeAddPage}
onBack={() => {
route(Pages.balance);
}}
/>
{/**
* DEV
*/}
<Route path={Pages.dev} component={DeveloperPage} />
{/**
* CALL TO ACTION
*/}
<Route
path={Pages.cta_pay}
component={PayPage}
goToWalletManualWithdraw={(currency?: string) =>
route(
Pages.balance_manual_withdraw.replace(
":currency?",
currency || "",
),
)
}
goBack={() => route(Pages.balance)}
/>
<Route path={Pages.cta_refund} component={RefundPage} />
<Route path={Pages.cta_tips} component={TipPage} />
<Route path={Pages.cta_withdraw} component={WithdrawPage} />
{/**
* NOT FOUND
* all redirects should be at the end
*/}
<Route
path={Pages.balance}
component={Redirect}
to={Pages.balance_history.replace(":currency?", "")}
/>
<Route
default
component={Redirect}
to={Pages.balance_history.replace(":currency?", "")}
/>
</Router>
</WalletBox>
</IoCProviderForRuntime>
</DevContextProvider>
</TranslationProvider>
);
}
function Redirect({ to }: { to: string }): null {
useEffect(() => {
console.log("got some wrong route", to);
route(to, true);
});
return null;
}

View File

@ -97,7 +97,7 @@ export interface UpgradeResponse {
async function callBackend(operation: string, payload: any): Promise<any> {
let response: CoreApiResponse;
try {
response = await platform.setMessageToWalletBackground(operation, payload);
response = await platform.sendMessageToWalletBackground(operation, payload);
} catch (e) {
console.log("Error calling backend");
throw new Error(`Error contacting backend: ${e}`);
@ -417,11 +417,11 @@ export function onUpdateNotification(
messageTypes: Array<NotificationType>,
doCallback: () => void,
): () => void {
const listener = (message: MessageFromBackend): void => {
const onNewMessage = (message: MessageFromBackend): void => {
const shouldNotify = messageTypes.includes(message.type);
if (shouldNotify) {
doCallback();
}
};
return platform.listenToWalletNotifications(listener);
return platform.listenToWalletBackground(onNewMessage);
}

View File

@ -269,7 +269,7 @@ export async function wxMain(): Promise<void> {
// Handlers for messages coming directly from the content
// script on the page
platform.registerOnNewMessage((message, sender, callback) => {
platform.listenToAllChannels((message, sender, callback) => {
afterWalletIsInitialized.then(() => {
dispatch(message, sender, callback);
});
@ -285,8 +285,7 @@ export async function wxMain(): Promise<void> {
// On platforms that support it, also listen to external
// modification of permissions.
platform.getPermissionsApi().addPermissionsListener((perm) => {
const lastError = platform.getLastError()
platform.getPermissionsApi().addPermissionsListener((perm, lastError) => {
if (lastError) {
console.error(lastError);
return;

View File

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="/dist/popupEntryPoint.css" />
<link rel="stylesheet" type="text/css" href="/dist/walletEntryPoint.css" />
<link rel="icon" href="/static/img/icon.png" />
<script src="/dist/walletEntryPoint.js"></script>
<style>