aboutsummaryrefslogtreecommitdiff
path: root/popup
diff options
context:
space:
mode:
Diffstat (limited to 'popup')
-rw-r--r--popup/popup.css64
-rw-r--r--popup/popup.html20
-rw-r--r--popup/popup.tsx275
3 files changed, 359 insertions, 0 deletions
diff --git a/popup/popup.css b/popup/popup.css
new file mode 100644
index 000000000..53c9f97ed
--- /dev/null
+++ b/popup/popup.css
@@ -0,0 +1,64 @@
+body {
+ min-height: 20em;
+ width: 30em;
+ margin: 0;
+ padding: 0;
+ max-height: 800px;
+ overflow: hidden;
+}
+
+.nav {
+ background-color: #ddd;
+ padding: 0.5em 0;
+}
+
+.nav a {
+ color: black;
+ padding: 0.5em;
+ text-decoration: none;
+}
+
+.nav a.active {
+ background-color: white;
+ font-weight: bold;
+}
+
+
+.container {
+ overflow-y: scroll;
+ max-height: 400px;
+}
+
+.abbrev {
+ text-decoration-style: dotted;
+}
+
+#content {
+ padding: 1em;
+}
+
+
+#wallet-table .amount {
+ text-align: right;
+}
+
+.hidden {
+ display: none;
+}
+
+#transactions-table th,
+#transactions-table td {
+ padding: 0.2em 0.5em;
+}
+
+#reserve-create table {
+ width: 100%;
+}
+
+#reserve-create table td.label {
+ width: 5em;
+}
+
+#reserve-create table .input input[type="text"] {
+ width: 100%;
+}
diff --git a/popup/popup.html b/popup/popup.html
new file mode 100644
index 000000000..c67085c1b
--- /dev/null
+++ b/popup/popup.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="popup.css" type="text/css">
+ <script src="../lib/vendor/mithril.js"></script>
+ <script src="../lib/vendor/lodash.core.min.js"></script>
+ <script src="../lib/vendor/system-csp-production.src.js"></script>
+ <script src="../lib/vendor/jed.js"></script>
+ <script src="../lib/i18n.js"></script>
+ <script src="../lib/i18n-strings.js"></script>
+ <script src="../lib/module-trampoline.js"></script>
+</head>
+<body>
+<div id="nav"></div>
+<div id="content"></div>
+</body>
+
+
+</html>
diff --git a/popup/popup.tsx b/popup/popup.tsx
new file mode 100644
index 000000000..963556c32
--- /dev/null
+++ b/popup/popup.tsx
@@ -0,0 +1,275 @@
+/*
+ This file is part of TALER
+ (C) 2016 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
+ */
+
+
+/// <reference path="../lib/decl/mithril.d.ts" />
+/// <reference path="../lib/decl/lodash.d.ts" />
+
+"use strict";
+
+import {substituteFulfillmentUrl} from "../lib/wallet/helpers";
+
+declare var m: any;
+declare var i18n: any;
+
+
+function onUpdateNotification(f) {
+ let port = chrome.runtime.connect({name: "notifications"});
+ port.onMessage.addListener((msg, port) => {
+ f();
+ });
+}
+
+
+export function main() {
+ console.log("popup main");
+ m.route.mode = "hash";
+ m.route(document.getElementById("content"), "/balance", {
+ "/balance": WalletBalance,
+ "/history": WalletHistory,
+ "/debug": WalletDebug,
+ });
+ m.mount(document.getElementById("nav"), WalletNavBar);
+}
+
+console.log("this is popup");
+
+
+function makeTab(target, name) {
+ let cssClass = "";
+ if (target == m.route()) {
+ cssClass = "active";
+ }
+ return m("a", {config: m.route, href: target, "class": cssClass}, name);
+}
+
+namespace WalletNavBar {
+ export function view() {
+ return m("div#header.nav", [
+ makeTab("/balance", i18n`Balance`),
+ makeTab("/history", i18n`History`),
+ makeTab("/debug", i18n`Debug`),
+ ]);
+ }
+
+ export function controller() {
+ // empty
+ }
+}
+
+
+function openInExtension(element, isInitialized) {
+ element.addEventListener("click", (e) => {
+ chrome.tabs.create({
+ "url": element.href
+ });
+ e.preventDefault();
+ });
+}
+
+namespace WalletBalance {
+ export function controller() {
+ return new Controller();
+ }
+
+ class Controller {
+ myWallet;
+
+ constructor() {
+ this.updateBalance();
+
+ onUpdateNotification(() => this.updateBalance());
+ }
+
+ updateBalance() {
+ m.startComputation();
+ chrome.runtime.sendMessage({type: "balances"}, (wallet) => {
+ console.log("got wallet", wallet);
+ this.myWallet = wallet;
+ m.endComputation();
+ });
+ }
+ }
+
+ export function view(ctrl: Controller) {
+ let wallet = ctrl.myWallet;
+ if (!wallet) {
+ throw Error("Could not retrieve wallet");
+ }
+ let listing = _.map(wallet, x => m("p", formatAmount(x)));
+ if (listing.length > 0) {
+ return listing;
+ }
+ let link = m("a[href=https://demo.taler.net]",
+ {config: openInExtension},
+ i18n`free KUDOS`);
+
+ return i18n.parts`You have no balance to show. Want to get some ${link}?`;
+ }
+}
+
+
+function formatTimestamp(t) {
+ let x = new Date(t);
+ return x.toLocaleString();
+}
+
+
+function formatAmount(amount) {
+ let v = amount.value + amount.fraction / 1e6;
+ return `${v.toFixed(2)} ${amount.currency}`;
+}
+
+
+function abbrevKey(s: string) {
+ return m("span.abbrev", {title: s}, (s.slice(0, 5) + ".."))
+}
+
+
+function retryPayment(url, contractHash) {
+ return function() {
+ chrome.tabs.create({
+ "url": substituteFulfillmentUrl(url,
+ {H_contract: contractHash})
+ });
+ }
+}
+
+
+function formatHistoryItem(historyItem) {
+ const d = historyItem.detail;
+ const t = historyItem.timestamp;
+ console.log("hist item", historyItem);
+ switch (historyItem.type) {
+ case "create-reserve":
+ return m("p",
+ i18n.parts`Created reserve (${abbrevKey(d.reservePub)}) of ${formatAmount(
+ d.requestedAmount)} at ${formatTimestamp(
+ t)}`);
+ case "confirm-reserve":
+ return m("p",
+ i18n.parts`Bank confirmed reserve (${abbrevKey(d.reservePub)}) at ${formatTimestamp(
+ t)}`);
+ case "withdraw":
+ return m("p",
+ i18n`Withdraw at ${formatTimestamp(t)}`);
+ case "depleted-reserve":
+ return m("p",
+ i18n.parts`Wallet depleted reserve (${abbrevKey(d.reservePub)}) at ${formatTimestamp(t)}`);
+ case "pay":
+ let url = substituteFulfillmentUrl(d.fulfillmentUrl,
+ {H_contract: d.contractHash});
+ return m("p",
+ [
+ i18n`Payment for ${formatAmount(d.amount)} to merchant ${d.merchantName}. `,
+ m(`a`,
+ {href: url, onclick: openTab(url)},
+ "Retry")
+ ]);
+ default:
+ return m("p", i18n`Unknown event (${historyItem.type})`);
+ }
+}
+
+
+namespace WalletHistory {
+ export function controller() {
+ return new Controller();
+ }
+
+ class Controller {
+ myHistory;
+
+ constructor() {
+ this.update();
+ onUpdateNotification(() => this.update());
+ }
+
+ update() {
+ m.startComputation();
+ chrome.runtime.sendMessage({type: "get-history"}, (resp) => {
+ console.log("got history", history);
+ this.myHistory = resp;
+ m.endComputation();
+ });
+ }
+ }
+
+ export function view(ctrl: Controller) {
+ let history = ctrl.myHistory;
+ if (!history) {
+ throw Error("Could not retrieve history");
+ }
+ let listing = _.map(history, formatHistoryItem);
+ if (listing.length > 0) {
+ return m("div.container", listing);
+ }
+ return i18n`Your wallet has no events recorded.`;
+ }
+}
+
+
+function reload() {
+ try {
+ chrome.runtime.reload();
+ window.close();
+ } catch (e) {
+ // Functionality missing in firefox, ignore!
+ }
+}
+
+function confirmReset() {
+ if (confirm("Do you want to IRREVOCABLY DESTROY everything inside your" +
+ " wallet and LOSE ALL YOUR COINS?")) {
+ chrome.runtime.sendMessage({type: "reset"});
+ window.close();
+ }
+}
+
+
+var WalletDebug = {
+ view() {
+ return [
+ m("button",
+ {onclick: openExtensionPage("popup/popup.html")},
+ "wallet tab"),
+ m("button",
+ {onclick: openExtensionPage("pages/show-db.html")},
+ "show db"),
+ m("br"),
+ m("button", {onclick: confirmReset}, "reset"),
+ m("button", {onclick: reload}, "reload chrome extension"),
+ ]
+ }
+};
+
+
+function openExtensionPage(page) {
+ return function() {
+ chrome.tabs.create({
+ "url": chrome.extension.getURL(page)
+ });
+ }
+}
+
+
+function openTab(page) {
+ return function() {
+ chrome.tabs.create({
+ "url": page
+ });
+ }
+}