From 7fb527b0009a29605c32e663ab9e6a812a8cc5a8 Mon Sep 17 00:00:00 2001
From: Florian Dold <florian.dold@gmail.com>
Date: Wed, 5 Oct 2016 17:04:57 +0200
Subject: refactor confirm-contract rendering

---
 pages/confirm-contract.tsx | 187 +++++++++++++++++++++++++++++----------------
 1 file changed, 120 insertions(+), 67 deletions(-)

(limited to 'pages/confirm-contract.tsx')

diff --git a/pages/confirm-contract.tsx b/pages/confirm-contract.tsx
index f162dca85..8e553b05b 100644
--- a/pages/confirm-contract.tsx
+++ b/pages/confirm-contract.tsx
@@ -22,113 +22,166 @@
  */
 
 
-/// <reference path="../lib/decl/handlebars/handlebars.d.ts" />
-import MithrilComponent = _mithril.MithrilComponent;
+/// <reference path="../lib/decl/preact.d.ts" />
 import {substituteFulfillmentUrl} from "../lib/wallet/helpers";
 import m from "mithril";
 import {Contract, AmountJson} from "../lib/wallet/types";
 import {renderContract, prettyAmount} from "../lib/wallet/renderHtml";
 "use strict";
 
-const Details = {
-  controller() {
-    return {collapsed: m.prop(true)};
-  },
-  view(ctrl: any, contract: Contract) {
-    if (ctrl.collapsed()) {
-      return m("div", [
-        m("button.linky", {
-          onclick: () => {
-            ctrl.collapsed(false);
-          }
-        }, "show more details")
-      ]);
+
+interface DetailState {
+  collapsed: boolean;
+}
+
+interface DetailProps {
+  contract: Contract;
+}
+
+let h = preact.h;
+
+
+class Details extends preact.Component<DetailProps, DetailState> {
+  constructor() {
+    super();
+    this.state = {
+      collapsed: true
+    };
+  }
+
+  render(props: DetailProps, state: DetailState) {
+    if (state.collapsed) {
+      return h("div", {},
+               h("button", {
+                 className: "linky",
+                 onClick: () => {
+                   this.setState({collapsed: false});
+                 }
+               }, "show more details"));
     } else {
-      return m("div", [
-        m("button.linky", {
-          onclick: () => {
-            ctrl.collapsed(true);
-          }
-        }, "show less details"),
-        m("div", [
-          "Accepted exchanges:",
-          m("ul",
-            contract.exchanges.map(e => m("li", `${e.url}: ${e.master_pub}`)))
-        ])
-      ]);
+      return h("div", {},
+               h("button", {
+                 className: "linky",
+                 onClick: () => {
+                   this.setState({collapsed: true});
+                 }
+               }, "show less details"),
+               h("div", {},
+                 "Accepted exchanges:",
+                 h("ul", {},
+                   ...props.contract.exchanges.map(
+                     e => h("li", {}, `${e.url}: ${e.master_pub}`)))));
     }
   }
-};
+}
 
-export function main() {
-  let url = URI(document.location.href);
-  let query: any = URI.parseQuery(url.query());
-  let offer = JSON.parse(query.offer);
-  console.dir(offer);
-  let contract = offer.contract;
-  let error: string|null = null;
-  let payDisabled = true;
-
-  var Contract = {
-    view(ctrl: any) {
-      return [
-        renderContract(contract),
-        m("button.accept",
-          {onclick: doPayment, disabled: payDisabled},
-          i18n`Confirm Payment`),
-        (error ? m("p.errorbox", error) : []),
-        m(Details, contract)
-      ];
+interface ContractPromptProps {
+  offer: any;
+}
+
+interface ContractPromptState {
+  error: string|null;
+  payDisabled: boolean;
+}
+
+class ContractPrompt extends preact.Component<ContractPromptProps, ContractPromptState> {
+  constructor() {
+    super();
+    this.state = {
+      error: null,
+      payDisabled: true,
     }
-  };
+  }
 
-  m.mount(document.getElementById("contract")!, Contract);
+  componentWillMount() {
+    this.checkPayment();
+  }
+
+  componentWillUnmount() {
+    // FIXME: abort running ops
+  }
 
-  function checkPayment() {
-    chrome.runtime.sendMessage({type: 'check-pay', detail: {offer}}, (resp) => {
+  checkPayment() {
+    let msg = {
+      type: 'check-pay',
+      detail: {
+        offer: this.props.offer
+      }
+    };
+    chrome.runtime.sendMessage(msg, (resp) => {
       if (resp.error) {
         console.log("check-pay error", JSON.stringify(resp));
         switch (resp.error) {
           case "coins-insufficient":
-            error = i18n`You have insufficient funds of the requested currency in your wallet.`;
+            this.state.error = i18n`You have insufficient funds of the requested currency in your wallet.`;
             break;
           default:
-            error = `Error: ${resp.error}`;
+            this.state.error = `Error: ${resp.error}`;
             break;
         }
-        payDisabled = true;
+        this.state.payDisabled = true;
       } else {
-        payDisabled = false;
-        error = null;
+        this.state.payDisabled = false;
+        this.state.error = null;
       }
-      m.redraw();
-      window.setTimeout(checkPayment, 300);
+      this.forceUpdate();
+      window.setTimeout(() => this.checkPayment(), 300);
     });
   }
 
-  checkPayment();
-
-
-  function doPayment() {
-    let d = {offer};
+  doPayment() {
+    let d = {offer: this.props.offer};
     chrome.runtime.sendMessage({type: 'confirm-pay', detail: d}, (resp) => {
       if (resp.error) {
         console.log("confirm-pay error", JSON.stringify(resp));
         switch (resp.error) {
           case "coins-insufficient":
-            error = "You do not have enough coins of the requested currency.";
+            this.state.error = "You do not have enough coins of the" +
+              " requested currency.";
             break;
           default:
-            error = `Error: ${resp.error}`;
+            this.state.error = `Error: ${resp.error}`;
             break;
         }
-        m.redraw();
+        preact.rerender();
         return;
       }
       let c = d.offer.contract;
       console.log("contract", c);
       document.location.href = substituteFulfillmentUrl(c.fulfillment_url,
-                                                        offer);
+                                                        this.props.offer);
     });
   }
+
+
+  render(props: ContractPromptProps, state: ContractPromptState) {
+    let c = props.offer.contract;
+    return h("div", {},
+             renderContract(c),
+             h("button",
+               {
+                 onClick: () => this.doPayment(),
+                 disabled: state.payDisabled,
+                 "className": "accept"
+               },
+               i18n`Confirm Payment`),
+             (state.error ? h("p",
+                              {className: "errorbox"},
+                              state.error) : h("p",  "")),
+             h(Details, {contract: c})
+    );
+  }
+}
+
+
+export function main() {
+  let url = URI(document.location.href);
+  let query: any = URI.parseQuery(url.query());
+  let offer = JSON.parse(query.offer);
+  console.dir(offer);
+  let contract = offer.contract;
+
+
+  let prompt = h(ContractPrompt, {offer});
+  preact.render(prompt, document.getElementById("contract")!);
 }
-- 
cgit v1.2.3

