From d05f47d15a7109acf1641614d6e2ae14649da629 Mon Sep 17 00:00:00 2001 From: Gabriel Masclef Date: Thu, 7 Sep 2017 12:18:44 -0300 Subject: [PATCH] Feat: Basic Amount page --- src/app/app.module.ts | 12 +- src/assets/img/contact-placeholder.svg | 12 ++ src/assets/img/icon-bitcoin-symbol.svg | 13 +++ src/assets/img/scan-ico.svg | 24 ++++ src/pages/scan/scan.ts | 4 + src/pages/send/amount/amount.html | 66 +++++++++++ src/pages/send/amount/amount.scss | 63 +++++++++++ src/pages/send/amount/amount.ts | 148 +++++++++++++++++++++++++ src/pages/send/confirm/confirm.html | 13 +++ src/pages/send/confirm/confirm.scss | 3 + src/pages/send/confirm/confirm.ts | 22 ++++ src/pages/send/send.html | 15 ++- src/pages/send/send.scss | 7 +- src/pages/send/send.ts | 14 +++ 14 files changed, 407 insertions(+), 9 deletions(-) create mode 100644 src/assets/img/contact-placeholder.svg create mode 100644 src/assets/img/icon-bitcoin-symbol.svg create mode 100644 src/assets/img/scan-ico.svg create mode 100644 src/pages/send/amount/amount.html create mode 100644 src/pages/send/amount/amount.scss create mode 100644 src/pages/send/amount/amount.ts create mode 100644 src/pages/send/confirm/confirm.html create mode 100644 src/pages/send/confirm/confirm.scss create mode 100644 src/pages/send/confirm/confirm.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 70607b355..6b0debc83 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -37,6 +37,10 @@ import { SettingsPage } from '../pages/settings/settings'; import { AboutPage } from '../pages/settings/about/about'; import { TermsOfUsePage } from '../pages/settings/about/terms-of-use/terms-of-use'; +/* Send */ +import { AmountPage } from '../pages/send/amount/amount'; +import { ConfirmPage } from '../pages/send/confirm/confirm'; + /* Providers */ import { WalletProvider } from '../providers/wallet/wallet'; import { PersistenceProvider, persistenceProviderFactory } from '../providers/persistence/persistence'; @@ -66,7 +70,9 @@ export function createTranslateLoader(http: Http) { EmailPage, BackupRequestPage, DisclaimerPage, - TabsPage + TabsPage, + AmountPage, + ConfirmPage ], imports: [ BrowserModule, @@ -97,7 +103,9 @@ export function createTranslateLoader(http: Http) { EmailPage, BackupRequestPage, DisclaimerPage, - TabsPage + TabsPage, + AmountPage, + ConfirmPage ], providers: [ StatusBar, diff --git a/src/assets/img/contact-placeholder.svg b/src/assets/img/contact-placeholder.svg new file mode 100644 index 000000000..f730da86b --- /dev/null +++ b/src/assets/img/contact-placeholder.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/src/assets/img/icon-bitcoin-symbol.svg b/src/assets/img/icon-bitcoin-symbol.svg new file mode 100644 index 000000000..39d4cc30b --- /dev/null +++ b/src/assets/img/icon-bitcoin-symbol.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/src/assets/img/scan-ico.svg b/src/assets/img/scan-ico.svg new file mode 100644 index 000000000..5d13c91fe --- /dev/null +++ b/src/assets/img/scan-ico.svg @@ -0,0 +1,24 @@ + + + + scan-ico + Created with Sketch. + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pages/scan/scan.ts b/src/pages/scan/scan.ts index 538e697ab..07648bea5 100644 --- a/src/pages/scan/scan.ts +++ b/src/pages/scan/scan.ts @@ -3,6 +3,8 @@ import { NavController, NavParams } from 'ionic-angular'; import { QRScanner, QRScannerStatus } from '@ionic-native/qr-scanner'; import { PlatformProvider } from '../../providers/platform/platform'; import { ScanProvider } from '../../providers/scan/scan'; +import { AmountPage } from '../send/amount/amount'; + //import { QRScanner as QRScannerBrowser } from 'cordova-plugin-qrscanner/src/browser/src/library' @Component({ @@ -37,6 +39,8 @@ export class ScanPage { this.scanProvider.activate() .then(resp => { this.text = resp; + // TODO: implement incomingData + this.navCtrl.push(AmountPage, {address: this.text}); }) .catch(error => { console.log("error: " + error); diff --git a/src/pages/send/amount/amount.html b/src/pages/send/amount/amount.html new file mode 100644 index 000000000..cf949817e --- /dev/null +++ b/src/pages/send/amount/amount.html @@ -0,0 +1,66 @@ + + + + Amount + + + + + + + + Recipient + + + {{ address }} + + +
+
+
+ Amount +
+
+ {{ amount || "0.00" }} +
+
+ = {{globalResult|| "0.00" }} +
+
+
+
+
+ +
+
+
+
7
+
8
+
9
+
÷
+
+ +
+
4
+
5
+
6
+
×
+
+ +
+
1
+
2
+
3
+
+
+
+ +
+
.
+
0
+
+
-
+
+
+
+
diff --git a/src/pages/send/amount/amount.scss b/src/pages/send/amount/amount.scss new file mode 100644 index 000000000..bf38b2e41 --- /dev/null +++ b/src/pages/send/amount/amount.scss @@ -0,0 +1,63 @@ +page-amount { + .item-md ion-icon[item-left] + .item-inner { + margin: 0px; + } + .keypad { + text-align: center; + font-size: 24px; + font-weight: lighter; + position: absolute; + bottom: 0; + width: 100%; + color: $v-mid-gray; + + .row { + padding: 0 !important; + margin: 0 !important; + } + + .col { + line-height: 45px; + } + + .operator { + background-color: $v-subtle-gray; + font-weight: normal; + cursor: pointer; + + &:active { + background-color: $v-light-gray; + } + } + + .operator-row { + width: 25%; + margin-left: 75%; + .operator-send { + font-weight: bolder; + color: #fff; + background-color: #647ce8; + font-size: 36px; + cursor: pointer; + + &:active { + background-color: #eaeaea; + } + } + } + + .digit{ + cursor: pointer; + border-top: 1px solid $v-subtle-gray; + border-left: 1px solid $v-subtle-gray; + &:active { + background-color: $v-subtle-gray; + } + } + + @media(max-height: 480px) { + font-size: 12px; + + } + } +} diff --git a/src/pages/send/amount/amount.ts b/src/pages/send/amount/amount.ts new file mode 100644 index 000000000..79cea846d --- /dev/null +++ b/src/pages/send/amount/amount.ts @@ -0,0 +1,148 @@ +import { Component } from '@angular/core'; +import { NavController, NavParams } from 'ionic-angular'; +import * as _ from 'lodash'; +import { ConfirmPage } from '../confirm/confirm'; + +@Component({ + selector: 'page-amount', + templateUrl: 'amount.html', +}) +export class AmountPage { + + public address: string; + public amount: string; + public smallFont: boolean; + public allowSend: boolean; + public globalResult: string; + + private LENGTH_EXPRESSION_LIMIT = 19; + private SMALL_FONT_SIZE_LIMIT = 10; + private availableUnits: Array = []; + private unitIndex: number = 0; + + constructor(public navCtrl: NavController, public navParams: NavParams) { + this.amount = ""; + this.allowSend = false; + } + + ionViewDidLoad() { + console.log('ionViewDidLoad AmountPage'); + console.log("this.navParams.data", this.navParams.data); + this.address = this.navParams.data.address; + } + + pushDigit(digit: string) { + if (this.amount && this.amount.length >= this.LENGTH_EXPRESSION_LIMIT) return; + if (this.amount.indexOf('.') > -1 && digit == '.') return; + // TODO: next line - Need: isFiat + //if (this.availableUnits[this.unitIndex].isFiat && this.amount.indexOf('.') > -1 && this.amount[this.amount.indexOf('.') + 2]) return; + + this.amount = (this.amount + digit).replace('..', '.'); + console.log("this.amount", this.amount); + this.checkFontSize(); + this.processAmount(); + }; + + removeDigit() { + this.amount = (this.amount).toString().slice(0, -1); + this.processAmount(); + this.checkFontSize(); + }; + + pushOperator(operator: string) { + if (!this.amount || this.amount.length == 0) return; + this.amount = this._pushOperator(this.amount, operator); + }; + + _pushOperator(val: string, operator: string) { + if (!this.isOperator(_.last(val))) { + return val + operator; + } else { + return val.slice(0, -1) + operator; + } + }; + + isOperator(val: string) { + var regex = /[\/\-\+\x\*]/; + return regex.test(val); + }; + + isExpression(val: string) { + var regex = /^\.?\d+(\.?\d+)?([\/\-\+\*x]\d?\.?\d+)+$/; + return regex.test(val); + }; + + checkFontSize() { + if (this.amount && this.amount.length >= this.SMALL_FONT_SIZE_LIMIT) this.smallFont = true; + else this.smallFont = false; + }; + + processAmount() { + var formatedValue = this.format(this.amount); + var result = this.evaluate(formatedValue); + this.allowSend = _.isNumber(result) && +result > 0; + if (_.isNumber(result)) { + this.globalResult = this.isExpression(this.amount) ? '= ' + this.processResult(result) : ''; + + // TODO this.globalResult is always undefinded - Need: processResult() + /* if (this.availableUnits[this.unitIndex].isFiat) { + + var a = this.fromFiat(result); + if (a) { + this.alternativeAmount = txFormatService.formatAmount(a * unitToSatoshi, true); + } else { + this.alternativeAmount = 'N/A'; //TODO + this.allowSend = false; + } + } else { + this.alternativeAmount = $filter('formatFiatAmount')(toFiat(result)); + } */ + this.globalResult = result.toString(); + } + }; + + format(val: string) { + if (!val) return; + + var result = val.toString(); + + if (this.isOperator(_.last(val))) result = result.slice(0, -1); + + return result.replace('x', '*'); + }; + + evaluate(val: string) { + var result; + try { + result = eval(val); + } catch (e) { + return 0; + } + if (!_.isFinite(result)) return 0; + console.log("evaluate result: ", result); + return result; + }; + + processResult(val: number) { + // TODO: implement this function correctly - Need: txFormatService, isFiat, $filter + console.log("processResult TODO"); + /*if (this.availableUnits[this.unitIndex].isFiat) return $filter('formatFiatAmount')(val); + else return txFormatService.formatAmount(val.toFixed(unitDecimals) * unitToSatoshi, true);*/ + }; + + fromFiat(val: number) { + // TODO: implement next line correctly - Need: rateService + //return parseFloat((rateService.fromFiat(val, fiatCode, availableUnits[altUnitIndex].id) * satToUnit).toFixed(unitDecimals)); + }; + + toFiat(val) { + // TODO: implement next line correctly - Need: rateService + /*if (!rateService.getRate(fiatCode)) return; + return parseFloat((rateService.toFiat(val * unitToSatoshi, fiatCode, availableUnits[unitIndex].id)).toFixed(2));*/ + }; + + finish() { + this.navCtrl.push(ConfirmPage, {address: this.address, amount: this.globalResult}); + } + +} diff --git a/src/pages/send/confirm/confirm.html b/src/pages/send/confirm/confirm.html new file mode 100644 index 000000000..7d1b077e1 --- /dev/null +++ b/src/pages/send/confirm/confirm.html @@ -0,0 +1,13 @@ + + + + Confirm + + + + + + +
To: {{address}}
+
Amount: {{amount}}
+
diff --git a/src/pages/send/confirm/confirm.scss b/src/pages/send/confirm/confirm.scss new file mode 100644 index 000000000..f586a4372 --- /dev/null +++ b/src/pages/send/confirm/confirm.scss @@ -0,0 +1,3 @@ +page-confirm { + +} diff --git a/src/pages/send/confirm/confirm.ts b/src/pages/send/confirm/confirm.ts new file mode 100644 index 000000000..ab2008bcb --- /dev/null +++ b/src/pages/send/confirm/confirm.ts @@ -0,0 +1,22 @@ +import { Component } from '@angular/core'; +import { NavController, NavParams } from 'ionic-angular'; + +@Component({ + selector: 'page-confirm', + templateUrl: 'confirm.html', +}) +export class ConfirmPage { + + public address: string; + public amount: string; + + constructor(public navCtrl: NavController, public navParams: NavParams) { + } + + ionViewDidLoad() { + console.log('ionViewDidLoad ConfirmPage'); + this.address = this.navParams.data.address; + this.amount = this.navParams.data.amount; + } + +} diff --git a/src/pages/send/send.html b/src/pages/send/send.html index 59abb950b..ec9a881c8 100644 --- a/src/pages/send/send.html +++ b/src/pages/send/send.html @@ -1,9 +1,3 @@ - @@ -14,5 +8,14 @@ + + Recipient + + + + + + + diff --git a/src/pages/send/send.scss b/src/pages/send/send.scss index 947b207b3..f86c8eda5 100644 --- a/src/pages/send/send.scss +++ b/src/pages/send/send.scss @@ -1,3 +1,8 @@ page-send { - + .item-md ion-icon[item-left] + .item-inner { + margin: 0px; + } + .scanner-icon { + z-index: 99; + } } diff --git a/src/pages/send/send.ts b/src/pages/send/send.ts index 8050cf4b9..1c6dee640 100644 --- a/src/pages/send/send.ts +++ b/src/pages/send/send.ts @@ -1,5 +1,7 @@ import { Component } from '@angular/core'; import { NavController, NavParams } from 'ionic-angular'; +import * as _ from 'lodash'; +import { AmountPage } from './amount/amount'; @Component({ selector: 'page-send', @@ -14,4 +16,16 @@ export class SendPage { console.log('ionViewDidLoad SendPage'); } + openScanner() { + this.navCtrl.parent.select(2); + } + + findContact(search: string) { + // TODO: Improve this function + console.log("Send search string", search); + if (search.length === 34 && _.startsWith(search, '1')) { + this.navCtrl.push(AmountPage, {address: search}); + } + } + }