Merge pull request #6710 from Gamboster/v4

Feat: Basic Amount page
This commit is contained in:
Gustavo Maximiliano Cortez 2017-09-07 12:22:59 -03:00 committed by GitHub
commit 9a6e6849bd
14 changed files with 407 additions and 9 deletions

View File

@ -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,

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 35 35" style="enable-background:new 0 0 35 35;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.1;}
</style>
<path class="st0" d="M17.5,0C7.9,0,0,7.9,0,17.5s7.9,17.5,17.5,17.5S35,27.1,35,17.5S27.1,0,17.5,0L17.5,0z M28.6,26.9
c-1-2.3-3.2-3.3-5.4-4.1c-1-0.3-1.6-1.3-1.8-2.2c1.9-1.2,3.4-3.5,3.4-6.1v-1.5c0-4.1-3.2-7.3-7.3-7.3s-7.3,3.2-7.3,7.3v1.5
c0,2.6,1.5,4.9,3.5,6.3C13.4,21.7,13,22.5,12,23c-2.2,0.7-4.4,1.7-5.4,4.1c-2.3-2.6-3.6-6-3.6-9.6c0-8,6.6-14.5,14.6-14.5
s14.6,6.5,14.6,14.5C32.1,21.1,30.8,24.4,28.6,26.9L28.6,26.9z"/>
</svg>

After

Width:  |  Height:  |  Size: 812 B

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 20.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Bitcoin_Symbol" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 12 16" style="enable-background:new 0 0 12 16;" xml:space="preserve">
<style type="text/css">
.st0{fill:#5D5D5D;}
</style>
<path class="st0" d="M7.4,2.5l0-2.4L6,0.2l0,2.3c-0.4,0-0.8,0-1.2,0l0-2.3l-1.5,0l0,2.4c-0.3,0-0.6,0-0.9,0l-2,0l0,1.5
c0,0,1.1,0,1,0c0.6,0,0.8,0.3,0.8,0.6l0,6.5c0,0.2-0.2,0.5-0.6,0.5c0,0-1.1,0-1.1,0l-0.3,1.7l1.9,0c0.4,0,0.7,0,1,0l0,2.4l1.5,0
l0-2.4c0.4,0,0.8,0,1.2,0l0,2.3l1.5,0l0-2.4c2.5-0.1,4.2-0.7,4.4-3c0.2-1.8-0.7-2.6-2.1-3C10.5,7,11,6.2,10.9,5
C10.7,3.3,9.3,2.7,7.4,2.5z M8.8,10.1c0,1.8-3.1,1.6-4.1,1.6l0-3.2C5.7,8.5,8.8,8.2,8.8,10.1L8.8,10.1z M8.2,5.6
c0,1.6-2.6,1.4-3.4,1.4l0-2.9C5.6,4.2,8.2,3.9,8.2,5.6L8.2,5.6z"/>
</svg>

After

Width:  |  Height:  |  Size: 939 B

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="25px" height="15px" viewBox="0 0 25 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 41 (35326) - http://www.bohemiancoding.com/sketch -->
<title>scan-ico</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" opacity="0.5">
<g id="Send---initial" transform="translate(-326.000000, -139.000000)" stroke-width="1.5" stroke="#4A4A4A">
<g id="Send-to-(Field)" transform="translate(0.000000, 70.000000)">
<g id="scan-ico" transform="translate(326.000000, 68.000000)">
<g id="Icons/Tabs/Scan" transform="translate(0.233333, 0.551724)">
<g id="Scan">
<path d="M8.01713862,1.23032704 L4.65481836,1.23032704 M4.40485821,1.23032704 L4.40485821,4.48620728" id="Line-Copy-2" stroke-linejoin="round"></path>
<path d="M16.3666389,1.23032704 L19.7289592,1.23032704 M19.9789194,1.23032704 L19.9789194,4.48620728" id="Line-Copy-3" stroke-linejoin="round"></path>
<path d="M8.01713862,14.3286527 L4.65481836,14.3286527 M4.40485821,14.3286527 L4.40485821,11.0727724" id="Line-Copy-5" stroke-linejoin="round"></path>
<path d="M16.3666389,14.3286527 L19.7289592,14.3286527 M19.9789194,14.3286527 L19.9789194,11.0727724" id="Line-Copy-4" stroke-linejoin="round"></path>
<path d="M0.559999983,7.67196401 L23.8933334,7.67196401" id="Line"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -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);

View File

@ -0,0 +1,66 @@
<ion-header>
<ion-navbar>
<ion-title>Amount</ion-title>
</ion-navbar>
</ion-header>
<ion-content>
<ion-list>
<ion-label padding>Recipient</ion-label>
<ion-item>
<ion-icon name="contact" item-left></ion-icon>
<span>{{ address }}</span>
</ion-item>
</ion-list>
<div>
<div padding>
<div>
<span>Amount</span>
</div>
<div>
<span>{{ amount || "0.00" }}</span>
</div>
<div [hidden]="!globalResult">
= {{globalResult|| "0.00" }}
</div>
</div>
<div class="keypad">
<div class="operator-row">
<div class="col operator-send"
[hidden]="!allowSend" (click)="finish()">
<ion-icon name="arrow-round-forward"></ion-icon>
</div>
</div>
<div class="row">
<div class="col digit" (click)="pushDigit('7')">7</div>
<div class="col digit" (click)="pushDigit('8')">8</div>
<div class="col digit" (click)="pushDigit('9')">9</div>
<div class="col operator" (click)="pushOperator('/')">&#247;</div>
</div>
<div class="row">
<div class="col digit" (click)="pushDigit('4')">4</div>
<div class="col digit" (click)="pushDigit('5')">5</div>
<div class="col digit" (click)="pushDigit('6')">6</div>
<div class="col operator" (click)="pushOperator('x')">&#215;</div>
</div>
<div class="row">
<div class="col digit" (click)="pushDigit('1')">1</div>
<div class="col digit" (click)="pushDigit('2')">2</div>
<div class="col digit" (click)="pushDigit('3')">3</div>
<div class="col operator" (click)="pushOperator('+')">&#43;</div>
</div>
<div class="row">
<div class="col digit" (click)="pushDigit('.')">.</div>
<div class="col digit" (click)="pushDigit('0')">0</div>
<div class="col digit" (click)="removeDigit()"><ion-icon name="backspace"></ion-icon></div>
<div class="col operator" (click)="pushOperator('-')">&#45;</div>
</div>
</div>
</div>
</ion-content>

View File

@ -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;
}
}
}

View File

@ -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<any> = [];
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});
}
}

View File

@ -0,0 +1,13 @@
<ion-header>
<ion-navbar>
<ion-title>Confirm</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<div>To: {{address}}</div>
<div>Amount: {{amount}}</div>
</ion-content>

View File

@ -0,0 +1,3 @@
page-confirm {
}

View File

@ -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;
}
}

View File

@ -1,9 +1,3 @@
<!--
Generated template for the SendPage page.
See http://ionicframework.com/docs/components/#navigation for more info on
Ionic pages and navigation.
-->
<ion-header>
<ion-navbar>
@ -14,5 +8,14 @@
<ion-content padding>
<ion-list>
<ion-label>Recipient</ion-label>
<ion-item>
<ion-icon name="logo-bitcoin" item-left></ion-icon>
<ion-input type="text" placeholder="Search or enter bitcoin address" [(ngModel)]="search" (ngModelChange)="findContact(search)"></ion-input>
<ion-icon class="scanner-icon" name="md-qr-scanner" item-right (click)="openScanner()"></ion-icon>
</ion-item>
</ion-list>
</ion-content>

View File

@ -1,3 +1,8 @@
page-send {
.item-md ion-icon[item-left] + .item-inner {
margin: 0px;
}
.scanner-icon {
z-index: 99;
}
}

View File

@ -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});
}
}
}