diff options
author | Florian Dold <florian.dold@gmail.com> | 2016-02-29 18:03:02 +0100 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2016-02-29 18:03:02 +0100 |
commit | c962e9402123900c53967c14cf809ea10576cdb8 (patch) | |
tree | e7df9cfdd6fceae30fb99c8ec6be5e07c8b153a8 /popup | |
parent | 30ee3320c788129b258ed8b42f4fc63d28431e2f (diff) |
restructure
Diffstat (limited to 'popup')
-rw-r--r-- | popup/popup.css | 64 | ||||
-rw-r--r-- | popup/popup.html | 20 | ||||
-rw-r--r-- | popup/popup.tsx | 275 |
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 + }); + } +} |