Improvement open TX modal

This commit is contained in:
Gustavo Maximiliano Cortez 2016-02-09 16:48:53 -05:00
parent 41ea294b80
commit b405510db3
11 changed files with 341 additions and 18 deletions

View File

@ -46,7 +46,6 @@ module.exports = function(grunt) {
},
angular: {
src: [
'bower_components/fastclick/lib/fastclick.js',
'bower_components/qrcode-generator/js/qrcode.js',
'bower_components/qrcode-decoder-js/lib/qrcode-decoder.js',
'bower_components/moment/min/moment-with-locales.js',

View File

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
<meta name="msapplication-tap-highlight" content="no">
<meta name="format-detection" content="telephone=no">
<link rel="stylesheet" type="text/css" href="css/foundation.css">
@ -14,20 +14,19 @@
</head>
<body ng-cloak class="ng-cloak">
<div class="page"
ng-controller="indexController as index"
ng-swipe-disable-mouse
ng-swipe-left="index.closeMenu()"
ng-swipe-right="index.openMenu()">
<div class="off-canvas-wrap" id="off-canvas-wrap">
<div class="page" ng-controller="indexController as index">
<div notifications="right top"></div>
<div ng-include="'views/includes/tx-details.html'" ng-if="index.showTx"></div>
<div ng-include="'views/includes/password.html'" ng-if="index.askPassword"></div>
<div ng-include="'views/includes/alert.html'" ng-if="index.showAlert"></div>
<div ng-include="'views/includes/confirm-tx.html'" ng-if="index.confirmTx"></div>
<div class="off-canvas-wrap" id="off-canvas-wrap"
ng-swipe-disable-mouse
ng-swipe-left="index.closeMenu()"
ng-swipe-right="index.openMenu()">
<div class="inner-wrap">
<div ng-include="'views/includes/sidebar.html'" ng-if="index.hasProfile"></div>
<div notifications="right top"></div>
<div ng-include="'views/includes/password.html'" ng-if="index.askPassword"></div>
<div ng-include="'views/includes/alert.html'" ng-if="index.showAlert"></div>
<div ng-include="'views/includes/confirm-tx.html'" ng-if="index.confirmTx"></div>
<div id="sectionContainer">
<div id="mainSection">
<section ui-view="main"

View File

@ -0,0 +1,158 @@
<div
ng-controller="txController as txc"
class="txModal fix-modals-touch"
ng-class="{'animated': index.isCordova, 'slideInRight': modalOpening, 'slideOutRight': modalClosing}"
ng-swipe-disable-mouse
ng-swipe-right="txc.cancel()">
<nav class="tab-bar" ng-style="{'background-color':txc.color}">
<section class="left-small">
<a ng-click="txc.cancel()">
<i class="icon-arrow-left3 icon-back"></i>
<span class="text-back" translate>Back</span>
</a>
</section>
<section class="middle tab-bar-section">
<h1 class="title ellipsis" translate>
Transaction
</h1>
</section>
</nav>
<div class="header-modal text-center" ng-init="txc.getAlternativeAmount(index.showTx)">
<div ng-show="index.showTx.action != 'invalid'">
<div ng-show="index.showTx.action == 'received'">
<img src="img/icon-receive-history.svg" alt="sync" width="50">
<p class="m0 text-gray size-14" translate>Received</p>
</div>
<div ng-show="index.showTx.action == 'sent'">
<img src="img/icon-sent-history.svg" alt="sync" width="50">
<p class="m0 text-gray size-14" translate>Sent</p>
</div>
<div ng-show="index.showTx.action == 'moved'">
<img src="img/icon-moved.svg" alt="sync" width="50">
<p class="m0 text-gray size-14" translate>Moved</p>
</div>
<div class="size-36">
<span ng-if="index.showTx.action == 'received'">+</span><span ng-if="index.showTx.action == 'sent'">-</span>{{index.showTx.amountStr}}
</div>
<div class="alternative-amount" ng-click="showRate=!showRate" ng-init="showRate = false">
<span class="label gray radius" ng-show="!showRate && alternativeAmountStr">
{{alternativeAmountStr}}
</span>
<span class="size-12" ng-show="showRate && alternativeAmountStr">
{{rateStr}} ({{rateDate | amDateFormat:'MM/DD/YYYY HH:mm a'}})
</span>
</div>
</div>
<div ng-show="index.showTx.action == 'invalid'">
-
</div>
</div>
<h4 class="title m0" translate>Details</h4>
<ul class="no-bullet size-14 m0">
<li ng-if="!index.showTx.hasMultiplesOutputs && index.showTx.addressTo && index.showTx.addressTo != 'N/A'" class="line-b p10 oh"
ng-click="copyAddress(index.showTx.addressTo)">
<span class="text-gray" translate>To</span>
<span class="right">
<span ng-if="index.showTx.merchant">
<span ng-show="index.showTx.merchant.pr.ca"><i class="fi-lock color-greeni"></i> {{index.showTx.merchant.domain}}</span>
<span ng-show="!index.showTx.merchant.pr.ca"><i class="fi-unlock color-yellowi"></i> {{index.showTx.merchant.domain}}</span>
</span>
<span ng-if="!index.showTx.merchant">
<span ng-show="index.showTx.labelTo">{{index.showTx.labelTo}}</span>
<contact ng-show="!index.showTx.labelTo" class="enable_text_select" address="{{index.showTx.addressTo}}"></contact>
</span>
</span>
</li>
<li ng-show="index.showTx.hasMultiplesOutputs" class="line-b p10 oh"
ng-click="showMultiplesOutputs = !showMultiplesOutputs">
<span class="text-gray" translate>Recipients</span>
<span class="right">{{index.showTx.recipientCount}}
<i ng-show="showMultiplesOutputs" class="icon-arrow-up3 size-24"></i>
<i ng-show="!showMultiplesOutputs" class="icon-arrow-down3 size-24"></i>
</span>
</li>
<div class="line-b" ng-show="index.showTx.hasMultiplesOutputs && showMultiplesOutputs"
ng-repeat="output in index.showTx.outputs"
ng-include="'views/includes/output.html'">
</div>
<li ng-show="btc.message" class="line-b p10 oh">
<span class="text-gray" translate>Note</span>
<span class="right">{{index.showTx.message}}</span>
</li>
<li ng-if="index.showTx.action == 'invalid'" class="line-b p10 oh">
<span class="right" translate>
This transaction has become invalid; possibly due to a double spend attempt.
</span>
<li ng-if="index.showTx.time" class="line-b p10 oh">
<span class="text-gray" translate>Date</span>
<span class="right">
<time>{{ index.showTx.time * 1000 | amDateFormat:'MM/DD/YYYY HH:mm a'}}</time>
<time>({{ index.showTx.time * 1000 | amTimeAgo}})</time>
</span>
</li>
<li class="line-b p10" ng-show="index.showTx.action != 'received'">
<span class="text-gray" translate>Fee</span>
<span class="right">{{index.showTx.feeStr}}</span>
</li>
<li class="line-b p10 oh" ng-if="index.showTx.message && index.showTx.action != 'received'">
<span class="text-gray" translate>Note</span>
<span class="right">{{index.showTx.message}}</span>
</li>
<li ng-if="index.showTx.merchant" class="line-b p10 oh">
<span class="text-gray" translate>Merchant message</span>
<span class="right">
{{index.showTx.merchant.pr.pd.memo}}
</span>
</li>
<li ng-if="index.showTx.time" class="line-b p10 oh">
<span class="text-gray" translate>Confirmations</span>
<span class="right" >
<span class="text-warning" ng-show="!index.showTx.confirmations || index.showTx.confirmations == 0" translate>
Unconfirmed
</span>
<span class="label gray radius" ng-show="index.showTx.confirmations>0 && !index.showTx.safeConfirmed">
{{index.showTx.confirmations}}
</span>
<span class="label gray radius" ng-show="index.showTx.safeConfirmed">
{{index.showTx.safeConfirmed}}
</span>
</span>
</li>
</ul>
<div ng-if="index.showTx.actions[0] && txc.isShared">
<h4 class="title m0" translate>Participants</h4>
<ul class="no-bullet size-14 m0">
<li class="line-b p10 text-gray" ng-repeat="c in index.showTx.actions">
<i class="icon-contact size-24"></i>
<span class="right">
<i ng-if="c.type == 'reject'" class="fi-x icon-sign x db"></i>
<i ng-if="c.type == 'accept'" class="fi-check icon-sign check db"></i>
</span>
{{c.copayerName}} <span ng-if="c.copayerId == txc.copayerId">({{'Me'|translate}})</span>
</li>
</ul>
</div>
<div ng-show="index.showTx.txid" class="tx-details-blockchain">
<div class="text-center m20t">
<button class="button outline round dark-gray tiny" ng-click="$root.openExternalLink('https://' +
(txc.getShortNetworkName() == 'test' ? 'test-' : '') + 'insight.bitpay.com/tx/' + index.showTx.txid)">
<span class="text-gray" translate>See it on the blockchain</span>
</button>
</div>
</div>
<div class="extra-margin-bottom"></div>
</div>

View File

@ -199,7 +199,21 @@
</div>
<div ng-repeat="btx in index.txHistory"
ng-click="home.openTxModal(btx)"
fast-click callback-fn="home.openNewTxModal({
txid: btx.txid,
action: btx.action,
hasMultiplesOutputs: btx.hasMultiplesOutputs,
addressTo: btx.addressTo,
merchant: btx.merchant,
labelTo: btx.labelTo,
recipientCount: btx.recipientCount,
outputs: btx.outputs,
message: btx.message,
time: btx.time,
confirmations: btx.confirmations,
safeConfirmed: btx.safeConfirmed,
amountStr: btx.amountStr
})"
class="row collapse last-transactions-content">
<div class="large-6 medium-6 small-6 columns size-14">
<div class="m10r left">

View File

@ -1399,7 +1399,14 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
border-top-right-radius: 5px;
}
/*******************/
.txModal {
background: #FFFFFF;
border-radius: 5px;
position: absolute;
width: 100%;
height: 100%;
z-index: 1100;
}
.alertModal {
background: #FFFFFF;

View File

@ -644,6 +644,8 @@ body.modal-open {
.reveal-modal.animated.slideInRight,
.reveal-modal.animated.slideOutRight,
.txModal.animated.slideInRight,
.txModal.animated.slideOutRight,
.reveal-modal.animated.fadeOutUp,
.reveal-modal.animated.slideInUp,
.reveal-modal.animated.slideInDown {

View File

@ -1344,6 +1344,13 @@ angular.module('copayApp.controllers').controller('indexController', function($r
});
});
$rootScope.$on('Local/TxModal', function(event, tx) {
self.showTx = tx;
$timeout(function() {
$rootScope.$apply();
});
});
$rootScope.$on('NewIncomingTx', function() {
self.newTx = true;
self.updateAll({

67
src/js/controllers/tx.js Normal file
View File

@ -0,0 +1,67 @@
'use strict';
angular.module('copayApp.controllers').controller('txController',
function($rootScope, $scope, $timeout, profileService, notification, go, gettext, isCordova, nodeWebkit) {
var fc = profileService.focusedClient;
this.color = fc.backgroundColor;
this.copayerId = fc.credentials.copayerId;
this.isShared = fc.credentials.n > 1;
if (isCordova) {
$scope.modalOpening = true;
$timeout(function() {
$scope.modalOpening = false;
}, 300);
}
this.getAlternativeAmount = function(btx) {
console.log('[tx.js:18]',btx); //TODO
var satToBtc = 1 / 100000000;
fc.getFiatRate({
code: self.alternativeIsoCode,
ts: btx.time * 1000
}, function(err, res) {
console.log('[tx.js:24]',res); //TODO
if (err) {
$log.debug('Could not get historic rate');
return;
}
if (res && res.rate) {
var alternativeAmountBtc = (btx.amount * satToBtc).toFixed(8);
$scope.rateDate = res.fetchedOn;
$scope.rateStr = res.rate + ' ' + self.alternativeIsoCode;
$scope.alternativeAmountStr = $filter('noFractionNumber')(alternativeAmountBtc * res.rate, 2) + ' ' + self.alternativeIsoCode;
$scope.$apply();
}
});
};
this.getShortNetworkName = function() {
var n = fc.credentials.network;
return n.substring(0, 4);
};
this.copyAddress = function(addr) {
if (!addr) return;
if (isCordova) {
window.cordova.plugins.clipboard.copy(addr);
window.plugins.toast.showShortCenter(gettextCatalog.getString('Copied to clipboard'));
} else if (nodeWebkit.isDefined()) {
nodeWebkit.writeToClipboard(addr);
}
};
this.cancel = function() {
if (isCordova) {
$scope.modalClosing = true;
$timeout(function() {
$scope.modalClosing = false;
$rootScope.$emit('Local/TxModal', null);
}, 300);
} else {
$rootScope.$emit('Local/TxModal', null);
}
};
});

View File

@ -1149,6 +1149,10 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
return this.alternativeIsoCode;
};
this.openNewTxModal = function(tx) {
$rootScope.$emit('Local/TxModal', tx);
};
this.openTxModal = function(btx) {
$rootScope.modalOpened = true;
var self = this;

View File

@ -317,4 +317,71 @@ angular.module('copayApp.directives')
replace: true,
templateUrl: 'views/includes/available-balance.html'
}
});
})
.directive('fastClick', [ 'isCordova', '$timeout', function(isCordova, $timeout) {
return {
scope: { someCtrlFn: '&callbackFn'},
link: function(scope, element, attrs) {
if (!isCordova) {
element.on('click', function(){
scope.someCtrlFn();
console.log('click real');
});
} else {
var trackingClick = false;
var targetElement = null;
var touchStartX = 0;
var touchStartY = 0;
var touchBoundary = 10;
element.on('touchstart', function(event) {
trackingClick = true;
targetElement = event.target;
touchStartX = event.targetTouches[0].pageX;
touchStartY = event.targetTouches[0].pageY;
console.log('PRIMER CLICKKKKKK!!');
return true;
});
element.on('touchend', function(event) {
if (trackingClick) {
scope.someCtrlFn();
event.preventDefault();
}
trackingClick = false;
console.log('SOLTANDO EL CLICKKKKKK!!');
return false;
});
element.on('touchmove', function(event) {
console.log('[directives.js:357] MOVING 1', trackingClick); //TODO
if (!trackingClick) {
return true;
}
console.log('[directives.js:361] MOVING 2', trackingClick); //TODO
// If the touch has moved, cancel the click tracking
if (targetElement !== event.target
|| (Math.abs(event.changedTouches[0].pageX - touchStartX) > touchBoundary
|| (Math.abs(event.changedTouches[0].pageY - touchStartY) > touchBoundary))) {
trackingClick = false;
targetElement = null;
}
return true;
});
element.on('touchcancel', function() {
trackingClick = false;
targetElement = null;
});
}
}
}
}]);
;

View File

@ -511,7 +511,6 @@ angular
});
})
.run(function($rootScope, $state, $log, uriHandler, isCordova, profileService, $timeout, nodeWebkit, uxLanguage, animationService) {
FastClick.attach(document.body);
uxLanguage.init();