Merge pull request #5007 from msalcala11/improveWalletDetails

Improve wallet details
This commit is contained in:
Jason Dreyzehner 2016-11-15 13:55:21 -05:00 committed by GitHub
commit 8191701fb3
22 changed files with 691 additions and 113 deletions

View File

@ -1,6 +1,6 @@
'use strict';
angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, $ionicHistory, profileService, lodash, configService, gettextCatalog, platformInfo, walletService, txpModalService, externalLinkService, popupService, addressbookService) {
angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, $ionicHistory, profileService, lodash, configService, gettextCatalog, platformInfo, walletService, txpModalService, externalLinkService, popupService, addressbookService, storageService, $ionicScrollDelegate, $window) {
var HISTORY_SHOW_LIMIT = 10;
var currentTxHistoryPage = 0;
@ -10,6 +10,9 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
$scope.openTxpModal = txpModalService.open;
$scope.isCordova = platformInfo.isCordova;
$scope.isAndroid = platformInfo.isAndroid;
$scope.isIOS = platformInfo.isIOS;
$scope.amountIsCollapsible = !$scope.isAndroid;
$scope.openExternalLink = function(url, target) {
externalLinkService.open(url, target);
@ -158,6 +161,52 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
}
};
$scope.getDate = function(txCreated) {
var date = new Date(txCreated * 1000);
return date;
};
$scope.isFirstInGroup = function(index) {
if (index === 0) {
return true;
}
var curTx = $scope.txHistory[index];
var prevTx = $scope.txHistory[index - 1];
return !createdDuringSameMonth(curTx, prevTx);
};
$scope.isLastInGroup = function(index) {
if (index === $scope.txHistory.length - 1) {
return true;
}
return $scope.isFirstInGroup(index + 1);
};
function createdDuringSameMonth(tx1, tx2) {
var date1 = new Date(tx1.time * 1000);
var date2 = new Date(tx2.time * 1000);
return getMonthYear(date1) === getMonthYear(date2);
}
$scope.createdWithinPastDay = function(time) {
var now = new Date();
var date = new Date(time * 1000);
return (now.getTime() - date.getTime()) < (1000 * 60 * 60 * 24);
};
$scope.isDateInCurrentMonth = function(date) {
var now = new Date();
return getMonthYear(now) === getMonthYear(date);
};
function getMonthYear(date) {
return date.getMonth() + date.getFullYear();
}
$scope.isUnconfirmed = function(tx) {
return !tx.confirmations || tx.confirmations === 0;
};
$scope.showMore = function() {
$timeout(function() {
currentTxHistoryPage++;
@ -184,9 +233,75 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
});
};
$scope.$on("$ionicView.beforeEnter", function(event, data) {
var prevPos;
var screenInactive = true;
$scope.wallet = profileService.getWallet(data.stateParams.walletId);
function getScrollPosition() {
var scrollPosition = $ionicScrollDelegate.getScrollPosition();
if (!scrollPosition || screenInactive) {
$window.requestAnimationFrame(function() {
getScrollPosition();
});
return;
}
var pos = scrollPosition.top;
if (pos === prevPos) {
$window.requestAnimationFrame(function() {
getScrollPosition();
});
return;
}
prevPos = pos;
var amountHeight = 180 - pos;
if (amountHeight < 80) {
amountHeight = 80;
}
var contentMargin = amountHeight;
if (contentMargin > 180) {
contentMargin = 180;
}
var amountScale = (amountHeight / 180);
if (amountScale < 0.5) {
amountScale = 0.5;
}
if (amountScale > 1.1) {
amountScale = 1.1;
}
var s = amountScale;
$scope.altAmountOpacity = (amountHeight - 100) / 80;
$window.requestAnimationFrame(function() {
$scope.amountHeight = amountHeight + 'px';
$scope.contentMargin = contentMargin + 'px';
$scope.amountScale = 'scale3d(' + s + ',' + s + ',' + s + ')';
$scope.$digest();
getScrollPosition();
});
}
var scrollWatcherInitialized;
$scope.$on("$ionicView.enter", function(event, data) {
$timeout(function() {
screenInactive = false;
}, 200);
if (scrollWatcherInitialized || !$scope.amountIsCollapsible) {
return;
}
scrollWatcherInitialized = true;
$timeout(function() {
getScrollPosition();
}, 100);
});
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.walletId = data.stateParams.walletId;
storageService.getBackupFlag($scope.walletId, function(err, flag) {
$scope.isBackedUp = flag ? true : false;
});
$scope.wallet = profileService.getWallet($scope.walletId);
$scope.requiresMultipleSignatures = $scope.wallet.credentials.m > 1;
addressbookService.list(function(err, ab) {
@ -208,7 +323,12 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun
];
});
// $scope.$on("$ionicView.beforeLeave", function(event, data) {
// $interval.cancel(scrollInterval);
// });
$scope.$on("$ionicView.leave", function(event, data) {
screenInactive = true;
lodash.each(listeners, function(x) {
x();
});

View File

@ -16,6 +16,6 @@ angular.module('copayApp.directives')
scope.emailHash = md5.createHash(scope.email.toLowerCase() || '');
}
},
template: '<img class="gravatar" alt="{{ name }}" height="{{ height }}" width="{{ width }}" src="https://secure.gravatar.com/avatar/{{ emailHash }}.jpg?s={{ width }}&d=mm">'
}
template: '<img class="gravatar" alt="{{ name }}" height="{{ height }}" width="{{ width }}" src="https://secure.gravatar.com/avatar/{{ emailHash }}.jpg?s={{ width }}&d=identicon">'
};
});

View File

@ -151,7 +151,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
*/
.state('tabs.wallet', {
url: '/wallet/{walletId}/{fromOnboarding}',
url: '/wallet/:walletId/:fromOnboarding',
views: {
'tab-home@tabs': {
controller: 'walletDetailsController',
@ -186,6 +186,23 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
}
}
})
.state('tabs.wallet.backupWarning', {
url: '/backupWarning/:from/:walletId',
views: {
'tab-home@tabs': {
templateUrl: 'views/backupWarning.html'
}
}
})
.state('tabs.wallet.backup', {
url: '/backup/:walletId',
views: {
'tab-home@tabs': {
templateUrl: 'views/backup.html',
controller: 'backupController'
}
}
})
/*
*
@ -601,7 +618,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
/*
*
* Back flow from receive
* Init backup flow
*
*/

View File

@ -1,4 +1,5 @@
#bitpayCard {
background: white;
.bar-header {
border: 0;
background: #1e3186;
@ -9,15 +10,35 @@
background-color: transparent;
}
}
.amount-wrapper {
position: relative;
overflow: visible;
.amount-bg {
content: '';
top: -1000px;
left: 0;
position: absolute;
height: 1000px;
width: 100%;
background-color: #1e3186;
}
}
.amount {
width: 100%;
text-align: center;
padding: 2rem 1rem 1.5rem 1rem;
height: 140px;
height: 160px;
border-color: #172565;
background-color: #1e3186;
background-image: linear-gradient(0deg, #172565, #172565 0%, transparent 0%);
color: #fff;
&__balance {
margin-bottom: 25px;
font-weight: 600;
font-size: 34px;
}
}
.wallet-details-wallet-info {
bottom: 5px;
@ -37,4 +58,26 @@
.item-select select {
color: #667;
}
.get-started {
margin-top: 20px;
&__arrow {
font-size: 56px;
opacity: .2;
}
h1 {
font-size: 28px;
color: #4A4A4A;
}
&__text {
font-weight: 300;
color: #8e8e8e;
max-width: 300px;
margin: 0 auto;
}
}
}

View File

@ -1,3 +1,5 @@
#view-confirm {
.tx-details-content > .scroll {
padding-bottom: .25rem;
}
}

View File

@ -23,6 +23,8 @@
img {
margin-right: 1rem;
height: 35px;
width: 35px;
}
span {

View File

@ -52,6 +52,15 @@
}
}
}
.wallet-details__item.item {
padding-top: 0;
padding-bottom: 0;
.wallet-details__tx-icon {
background: #fff;
border-radius: 50px;
}
}
.next-step.item {
padding-top: 27px;
padding-bottom: 27px;

View File

@ -6,7 +6,7 @@
font-weight: bold;
}
&--received {
color: #30af6c;
color: #09C286;
}
&--sent {
color: $dark-gray;
@ -14,18 +14,101 @@
}
&__tx-time {
color: $light-gray;
font-size: 12.5px;
}
&__tx-title {
padding-top: 10px;
flex-grow: 1;
color: $dark-gray;
overflow: hidden;
}
&__tx-icon {
float: left;
margin-right: 10px;
margin-right: 25px;
}
&__tx-message {
margin-right: 1rem;
}
&__list {
}
.item {
display: flex;
align-items: center;
background: #fff;
padding-left: 1rem;
}
&__item {
display: flex;
align-items: center;
background: #fff;
padding: 0;
margin: 0;
border: 0;
padding-left: 1rem;
&.proposal {
position: relative;
}
&__marker {
position: absolute;
height: 100%;
width: 3px;
background: #F5A623;
left: 0;
}
}
&__tx-content {
display: flex;
align-items: center;
flex-grow: 1;
padding: 1rem 0;
padding-right: 1rem;
border-bottom: 1px solid rgb(245, 245, 245);
overflow: hidden;
&.no-border {
border: 0;
}
}
&__tx-amount {
white-space: nowrap;
}
&__group-label {
font-size: 14px;
font-weight: 300;
color: #727272;
padding: 2px 1rem;
background: #f8f8f9;
}
}
#walletDetails {
background: #F8F8F9;
.ionic-refresher-content {
color: white !important;
}
.spinner svg {
stroke: white;
fill: white;
}
.bp-content {
position: relative;
height: 100%;
&.status-bar {
margin-top: 20px;
}
}
.bar-header {
border: 0;
background: none;
@ -39,13 +122,66 @@
.nav-bar-block, .bar {
background-color: inherit !important;
}
ion-content {
&.collapsible {
margin-top: 180px;
}
padding-top: 0;
top: 0;
.scroll {
background: rgb(248, 248, 249);
min-height: 300px;
}
}
.amount-wrapper {
position: relative;
overflow: visible;
.amount-bg {
content: '';
top: 0;
left: 0;
position: absolute;
width: 100%;
height: 500px;
transform: translateY(-499px);
&.collapsible {
top: initial;
bottom: 0;
left: 0;
position: absolute;
width: 100%;
height: 200px;
transform: translateY(100px);
}
}
}
.amount {
width: 100%;
text-align: center;
padding: 2rem 1rem 1.5rem 1rem;
color: #fff;
height: 140px;
margin-bottom: 10px;
height: 180px;
padding-top: 40px;
display: flex;
align-items: center;
justify-content: center;
&.collapsible {
margin-bottom: 10px;
}
&__balance {
transform: scale3d(1, 1, 1);
margin-top: 5px;
}
&__updating {
z-index: 999;
margin-top: -2.1rem;
}
&-alternative {
line-height: 36px;
@ -77,3 +213,18 @@
font-size: 20px;
color: #fff;
}
.wallet-not-backed-up-warning {
background: orange;
text-align: center;
color: white;
font-size: 14px;
display: block;
text-decoration: none;
z-index: 9999;
position: relative;
}
a.item {
cursor: pointer;
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="33px" height="33px" viewBox="0 0 33 33" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.1 (33804) - http://www.bohemiancoding.com/sketch -->
<title>Group 2</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons/Transaction/Processing" transform="translate(-8.000000, -8.000000)">
<g id="Icons/Send">
<g id="Group-2" transform="translate(8.000000, 8.000000)">
<path d="M16.5,33 C25.6126984,33 33,25.6126984 33,16.5 C33,7.38730163 25.6126984,0 16.5,0 C7.38730163,0 0,7.38730163 0,16.5 C0,25.6126984 7.38730163,33 16.5,33 Z" id="Oval-204" fill="#F2F2F2" opacity="0.8"></path>
<g id="Group" transform="translate(8.000000, 7.500000)" stroke="#BDBDBD">
<path d="M0,9 C0,4.05 3.80952381,0 8.46560847,0 C11.7671958,0 14.6455026,1.98 16,4.95" id="Shape"></path>
<path d="M17,9 C17,13.95 13.1904762,18 8.53439153,18 C5.23280423,18 2.35449735,16.02 1,13.05" id="Shape"></path>
<polyline id="Shape" points="17 0 16.2941176 5 11 4.3220339"></polyline>
<polyline id="Shape" points="0 18 0.705882353 13 6 13.6779661"></polyline>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="33px" height="33px" viewBox="0 0 33 33" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.1 (33804) - http://www.bohemiancoding.com/sketch -->
<title>Group</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons/Transaction/Pending" transform="translate(-8.000000, -8.000000)">
<g id="Icons/Send">
<g id="icons/received">
<g id="users-24px-outline-2_a-check" transform="translate(8.000000, 8.000000)">
<g id="Group">
<path d="M16.5,33 C25.6126984,33 33,25.6126984 33,16.5 C33,7.38730163 25.6126984,0 16.5,0 C7.38730163,0 0,7.38730163 0,16.5 C0,25.6126984 7.38730163,33 16.5,33 Z" id="Oval-204" fill="#FFF6EF"></path>
<path d="M15.7275949,17.3034598 C13.3028473,17.3034598 11.1520001,17.8512604 9.73870884,18.3277955 C8.69548354,18.680689 8,19.6638107 8,20.7654223 L8,24.172433 L14.8689732,24.172433" id="Shape" stroke="#F6A623"></path>
<path d="M15.7275949,17.3034598 L15.7275949,17.3034598 C13.3569405,17.3034598 11.4344866,14.5223843 11.4344866,12.1517299 L11.4344866,11.2931083 C11.4344866,8.92245388 13.3569405,7 15.7275949,7 L15.7275949,7 C18.0982492,7 20.0207031,8.92245388 20.0207031,11.2931083 L20.0207031,12.1517299 C20.0207031,14.5223843 18.0982492,17.3034598 15.7275949,17.3034598 L15.7275949,17.3034598 Z" id="Shape" stroke="#F6A623"></path>
<polyline id="Shape" stroke="#F6A623" points="19.1620815 23.3138114 20.8793248 25.0310547 25.172433 20.7379464"></polyline>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.1 (33804) - http://www.bohemiancoding.com/sketch -->
<title>Group 2</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons/Transaction/Send" transform="translate(-6.000000, -6.000000)">
<g id="Group-2" transform="translate(24.500000, 24.500000) rotate(90.000000) translate(-24.500000, -24.500000) translate(7.000000, 7.000000)">
<g id="Icons/Send">
<g id="icons/received">
<g id="Received" transform="translate(17.244258, 17.883990) scale(-1, 1) translate(-17.244258, -17.883990) translate(0.244258, 0.883990)">
<path d="M17.3272285,33.991292 C26.4399269,33.991292 33.8272285,26.6039904 33.8272285,17.491292 C33.8272285,8.37859367 26.4399269,0.991292046 17.3272285,0.991292046 C8.21453012,0.991292046 0.82722849,8.37859367 0.82722849,17.491292 C0.82722849,26.6039904 8.21453012,33.991292 17.3272285,33.991292 Z" id="Oval-204" stroke="#BDBDBD" opacity="0.8"></path>
<path d="M11.0503675,17.6759465 L24.0056239,17.6759465 M15.816934,23.6130491 L10,17.7604241 L15.614688,12" id="Line" stroke="#BEBEBE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="translate(17.002812, 17.806525) scale(1, -1) rotate(-90.000000) translate(-17.002812, -17.806525) "></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,15 @@
<?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{fill:#0EC286;}
</style>
<g>
<path class="st0" d="M17.5,34.5c-9.4,0-17-7.6-17-17s7.6-17,17-17s17,7.6,17,17S26.9,34.5,17.5,34.5z M17.5,1.5
c-8.8,0-16,7.2-16,16s7.2,16,16,16s16-7.2,16-16S26.3,1.5,17.5,1.5z"/>
</g>
<path class="st0" d="M23.8,18.2c-0.3-0.3-0.8-0.3-1.1,0l-4.7,4.6V10.5c0-0.4-0.3-0.8-0.8-0.8s-0.8,0.3-0.8,0.8v12.1l-4.4-4.3
c-0.3-0.3-0.8-0.3-1.1,0c-0.3,0.3-0.3,0.8,0,1.1l5.8,5.6c0.1,0.1,0.3,0.2,0.5,0.2c0.2,0,0.4-0.1,0.5-0.2l5.9-5.8
C24.1,18.9,24.1,18.5,23.8,18.2z"/>
</svg>

After

Width:  |  Height:  |  Size: 851 B

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="35px" height="35px" viewBox="0 0 35 35" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 40.1 (33804) - http://www.bohemiancoding.com/sketch -->
<title>Group 2</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Symbols" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Icons/Transaction/Send" transform="translate(-6.000000, -8.000000)">
<g id="Group-2" transform="translate(7.000000, 7.000000)">
<g id="Icons/Send">
<g id="icons/received">
<g id="Received" transform="translate(17.244258, 17.883990) scale(-1, 1) translate(-17.244258, -17.883990) translate(0.244258, 0.883990)">
<path d="M17.3272285,33.991292 C26.4399269,33.991292 33.8272285,26.6039904 33.8272285,17.491292 C33.8272285,8.37859367 26.4399269,0.991292046 17.3272285,0.991292046 C8.21453012,0.991292046 0.82722849,8.37859367 0.82722849,17.491292 C0.82722849,26.6039904 8.21453012,33.991292 17.3272285,33.991292 Z" id="Oval-204" stroke="#BDBDBD" opacity="0.8"></path>
<path d="M11.0503675,17.6759465 L24.0056239,17.6759465 M15.816934,23.6130491 L10,17.7604241 L15.614688,12" id="Line" stroke="#BEBEBE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" transform="translate(17.002812, 17.806525) scale(1, -1) rotate(-90.000000) translate(-17.002812, -17.806525) "></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -16,10 +16,11 @@
Sandbox version. Only for testing purpose
</div>
<div class="oh pr" ng-show="!error">
<div class="amount-wrapper" ng-show="!error">
<div class="amount-bg"></div>
<div class="amount">
<div ng-if="bitpayCard.bitpayCardCurrentBalance" ng-click="bitpayCard.update()">
<div class="size-36 m20b">${{bitpayCard.bitpayCardCurrentBalance}}</div>
<div class="amount__balance">${{bitpayCard.bitpayCardCurrentBalance}}</div>
<a class="button button-primary button-small m5t size-14"
style="padding: 0.5em 1em;"
ui-sref="tabs.bitpayCard.amount({'cardId': cardId, 'toName': 'BitPay Card'})">
@ -41,11 +42,13 @@
</div>
<div
class="m10t text-center padding ng-hide"
class="text-center padding get-started"
ng-show="bitpayCard.getStarted">
<i class="icon ion-ios-arrow-thin-up size-24"></i>
<i class="icon ion-ios-arrow-thin-up get-started__arrow"></i>
<h1>Get started</h1>
<h4>Your BitPay Card is ready. Add funds to your card to start using your card at stores and ATMs worldwide.</h4>
<div class="get-started__text">
Your BitPay Card is ready. Add funds to your card to start using your card at stores and ATMs worldwide.
</div>
</div>
<div class="list" ng-show="!bitpayCard.getStarted">

View File

@ -11,7 +11,7 @@
<div class="list">
<div class="item head">
<div class="sending-label">
<img src="img/sending-icon.svg">
<img src="img/icon-tx-sent-outline.svg">
<span translate>Sending</span>
</div>
<div class="amount-label">

View File

@ -1,27 +1,39 @@
<div class="wallet-details__item__marker"></div>
<img class="wallet-details__tx-icon" src="img/icon-proposal-pending.svg" width="40">
<div class="wallet-activity" ng-class="{'wallet-activity-not-pending':!tx.pendingForUs}">
<div class="wallet-activity-amount">
{{tx.amountStr}}
<div class="wallet-details__tx-content" ng-class="{'no-border': $last}">
<div class="wallet-details__tx-title">
<span ng-show="!tx.merchant">
<span ng-show="addressbook[tx.toAddress] && !tx.message">
{{addressbook[tx.toAddress].name || addressbook[tx.toAddress]}}
</span>
<span class="ellipsis" ng-show="!addressbook[tx.toAddress] && tx.message">
{{tx.message}}
</span>
<span ng-show="!addressbook[tx.toAddress] && !tx.message" translate>
Sending
</span>
</span>
<span ng-show="tx.merchant">
<span ng-show="tx.merchant.pr.ca"><i class="fi-lock"></i> {{tx.merchant.domain}}</span>
<span ng-show="!tx.merchant.pr.ca"><i class="fi-unlock"></i> {{tx.merchant.domain}}</span>
</span>
</div>
<span ng-show="!tx.merchant">
<span ng-show="addressbook[tx.toAddress] && !tx.message">
{{addressbook[tx.toAddress].name || addressbook[tx.toAddress]}}
</span>
<span class="ellipsis" ng-show="!addressbook[tx.toAddress] && tx.message">
{{tx.message}}
</span>
<span ng-show="!addressbook[tx.toAddress] && !tx.message" translate>
Sending
</span>
</span>
<span ng-show="tx.merchant">
<span ng-show="tx.merchant.pr.ca"><i class="fi-lock"></i> {{tx.merchant.domain}}</span>
<span ng-show="!tx.merchant.pr.ca"><i class="fi-unlock"></i> {{tx.merchant.domain}}</span>
</span>
<p class="wallet-activity-note">
<i class="icon ion-record wallet-activity-note-child" ng-style="{'color':tx.wallet.color}"></i>
<span class="wallet-activity-note-child">{{tx.wallet.name}}</span>
<time class="wallet-activity-note-child">{{tx.createdOn * 1000 | amTimeAgo}}</time>
</p>
<span class="item-note text-right wallet-details__tx-amount">
<span class="wallet-details__tx-amount wallet-details__tx-amount--sent">
<span ng-if="tx.action == 'sent'"></span>
<span class="size-12" ng-if="tx.action == 'invalid'" translate>
(possible double spend)
</span>
<span ng-if="tx.action != 'invalid'">
{{tx.amountStr}}
</span>
</span>
<div>
<time class="wallet-details__tx-time" ng-if="tx.createdOn && createdWithinPastDay(tx.createdOn)">{{tx.createdOn * 1000 | amTimeAgo}}</time>
<time class="wallet-details__tx-time" ng-if="tx.createdOn && !createdWithinPastDay(tx.createdOn)">{{tx.createdOn * 1000 | date:'MMMM d, y'}}</time>
</div>
</span>
</div>

View File

@ -40,9 +40,9 @@
</p>
</span>
<img class="left m10r" src="img/icon-receive-history.svg" alt="sync" width="40" ng-if="btx.action == 'received'">
<img class="left m10r" src="img/icon-sent-history.svg" alt="sync" width="40" ng-if="btx.action == 'sent'">
<img class="left m10r" src="img/icon-moved.svg" alt="sync" width="40" ng-if="btx.action == 'moved'">
<img class="left m10r" src="img/icon-tx-received-outline.svg" alt="sync" width="40" ng-if="btx.action == 'received'">
<img class="left m10r" src="img/icon-tx-sent-outline.svg" alt="sync" width="40" ng-if="btx.action == 'sent'">
<img class="left m10r" src="img/icon-tx-moved-outline.svg" alt="sync" width="40" ng-if="btx.action == 'moved'">
<h2>
<div class="padding" ng-if="btx.action == 'received'">

View File

@ -15,7 +15,7 @@
<div class="list">
<div class="item head">
<div class="sending-label">
<img src="img/sending-icon.svg">
<img src="img/icon-tx-sent-outline.svg">
<span translate>Sending</span>
</div>
<div class="amount-label">

View File

@ -16,10 +16,8 @@
</div>
</div>
<div class="list card" ng-show="txps[0] && !fetchingProposals">
<a ng-repeat="tx in txps" class="item" ng-click="openTxpModal(tx)">
<span ng-include="'views/includes/txp.html'"></span>
</a>
<div class="list card" ng-show="txps[0] && !fetchingProposals" style="padding: 0;">
<a ng-repeat="tx in txps" ng-click="openTxpModal(tx)" class="wallet-details__item item item-sub" ng-include="'views/includes/txp.html'"></a>
</div>
<div class="list card" ng-show="!txps[0] && !fetchingProposals">

View File

@ -40,9 +40,9 @@
<span class="badge badge-assertive m5t m10r" ng-show="txpsN>3"> {{txpsN}}</span>
</a>
<a ng-repeat="tx in txps" class="item item-sub" ng-click="openTxpModal(tx)">
<span ng-include="'views/includes/txp.html'"></span>
</a>
<div ng-repeat="tx in txps" ng-click="openTxpModal(tx)">
<a class="wallet-details__item item item-sub" ng-include="'views/includes/txp.html'"></a>
</div>
</div>
<div class="list card" ng-if="notifications[0] && recentTransactionsEnabled">

View File

@ -7,13 +7,20 @@
</ion-nav-back-button>
</ion-nav-bar>
<ion-content>
<ion-content class="tx-details-content">
<div class="list">
<div class="item head">
<div class="sending-label">
<img src="img/icon-check-circled.svg">
<div class="sending-label" ng-if="btx.confirmations > 0">
<img src="img/icon-tx-sent-outline.svg" ng-if="btx.action === 'sent'">
<img src="img/icon-tx-received-outline.svg" ng-if="btx.action === 'received'">
<img src="img/icon-tx-moved-outline.svg" ng-if="btx.action === 'moved'">
<span translate>{{btx.action | translate}}</span>
</div>
<div class="sending-label" ng-if="btx.confirmations === 0">
<img src="img/icon-confirming.svg">
<span ng-if="btx.action == 'sent' || btx.action == 'moved'">Sending</span>
<span ng-if="btx.action == 'received'">Receiving</span>
</div>
<div class="amount-label">
<div class="amount">{{displayAmount}} <span class="unit">{{displayUnit}}</span></div>
<div class="alternative" ng-click="getFiatRate(); showRate = !showRate">
@ -53,11 +60,11 @@
{{btx.creatorName}} <time>{{ (btx.ts || btx.createdOn ) * 1000 | amDateFormat:'MM/DD/YYYY hh:mm a'}}</time>
</span>
</div>
<a class="item single-line item-icon-right" ng-click="showCommentPopup()">
<a class="item item-icon-right" ng-class="{'single-line': !btx.note.body && !btx.message}" ng-click="showCommentPopup()">
<span class="label" translate>Memo</span>
<span class="item-note m10l">
<div class="item-note" style="display: block; float: none; margin-bottom: .25rem;">
{{btx.note.body || btx.message}}
</span>
</div>
<i class="icon bp-arrow-right"></i>
</a>
<div class="item single-line">
@ -69,7 +76,7 @@
<div class="item single-line">
<span class="label" translate>Confirmations</span>
<span class="item-note">
<span class="assertive" ng-show="!btx.confirmations || btx.confirmations == 0" translate>
<span ng-show="!btx.confirmations || btx.confirmations == 0" translate>
Unconfirmed
</span>
<span ng-show="btx.confirmations>0 && !btx.safeConfirmed">

View File

@ -1,4 +1,5 @@
<ion-view id="walletDetails">
<ion-nav-bar ng-style="{'background-color': wallet.color}">
<ion-nav-title>{{wallet.name}}</ion-nav-title>
<ion-nav-back-button>
@ -10,15 +11,94 @@
</ion-nav-buttons>
</ion-nav-bar>
<ion-content has-bouncing="false">
<div class="bp-content" ng-class="{'status-bar': isCordova && isIOS}">
<div class="amount-wrapper" ng-show="wallet && wallet.isComplete() && amountIsCollapsible" ng-style="{'background-color':wallet.color}">
<div
class="amount-bg"
ng-style="{'background-color':wallet.color}"
ng-class="{collapsible: amountIsCollapsible}"
></div>
<div
ng-style="{'background-color':wallet.color, 'height': amountHeight}"
class="amount"
ng-class="{collapsible: amountIsCollapsible}"
>
<div ng-if="!notAuthorized && !updatingStatus">
<div ng-show="updateStatusError">
<a class="button button-outline button-light button-small" ng-click='update()' translate>Tap to retry</a>
</div>
<div ng-show="walletNotRegistered">
<span class="size-12 db m10b" translate>This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information.</span>
<a class="button button-outline button-light button-small" ng-click='recreate()' translate>Recreate</a>
</div>
<div ng-show="wallet.walletScanStatus == 'error'" ng-click='retryScan()'>
<span translate>Scan status finished with error</span>
<br><span translate>Tap to retry</span>
</div>
<div
ng-click='updateAll(true)'
ng-show="!updateStatusError && wallet.walletScanStatus != 'error' && !wallet.balanceHidden"
on-hold="hideToggle()"
ng-style="{'transform': amountScale}"
class="amount__balance"
>
<strong ng-if="!status.pendingAmount" class="size-36">{{status.totalBalanceStr}}</strong>
<div
ng-if="!status.pendingAmount"
class="size-14 amount-alternative"
ng-if="status.totalBalanceAlternative"
ng-style="{opacity: altAmountOpacity}"
>
{{status.totalBalanceAlternative}} {{status.alternativeIsoCode}}
</div>
<div class="size-20" ng-if="status.pendingAmount">
<div style="margin-bottom:.5rem"><span translate>Available</span>: {{status.totalBalanceStr}}</div>
<div><span translate>Confirming</span>: {{status.pendingAmountStr}}</div>
</div>
</div>
<div ng-show="!updateStatusError && wallet.walletScanStatus != 'error' && wallet.balanceHidden" on-hold="hideToggle()">
<strong class="size-24" translate>[Balance Hidden]</strong>
<div class="size-14" translate>
Tap and hold to show
</div>
</div>
</div>
<div ng-if="updatingStatus" class="amount__updating">
<div class="size-36">
<strong>...</strong>
</div>
</div>
</div>
<div class="wallet-details-wallet-info" ng-style="{opacity: altAmountOpacity}">
<span ng-include="'views/includes/walletInfo.html'"></span>
</div>
</div>
<ion-content ng-style="{'margin-top': contentMargin}" ng-class="{collapsible: amountIsCollapsible}">
<ion-refresher
ng-if="isAndroid"
pulling-icon="ion-ios-refresh"
spinner="ios-small"
on-refresh="onRefresh()">
</ion-refresher>
<div class="oh pr" ng-show="wallet && wallet.isComplete()">
<div ng-style="{'background-color':wallet.color}" class="amount">
<div class="amount-wrapper" ng-if="wallet && wallet.isComplete() && !amountIsCollapsible">
<div
class="amount-bg"
ng-style="{'background-color':wallet.color}"
></div>
<div
ng-style="{'background-color':wallet.color}"
class="amount"
ng-class="{'collapsible': amountIsCollapsible}"
>
<div ng-if="!updatingStatus">
<div ng-show="updateStatusError">
@ -59,7 +139,11 @@
</div>
</div> <!-- oh -->
<div class="p60b" ng-show="wallet && wallet.isComplete() && !walletNotRegistered">
<a class="wallet-not-backed-up-warning" ng-if="!isBackedUp" ui-sref="tabs.wallet.backupWarning({from: 'tabs.wallet'})">
Wallet not backed up
</a>
<div class="p60b" ng-if="wallet && wallet.isComplete() && !walletNotRegistered" style="padding-top: 1rem;">
<div class="oh pr m20t" ng-show="wallet.incorrectDerivation">
<div class="text-center text-warning">
<i class="fi-alert"></i>
@ -69,14 +153,18 @@
</div>
</div>
<div class="list" ng-if="txps[0]">
<div class="item item-heading" translate>
<!-- <div class="item item-heading" translate>
<span ng-show="requiresMultipleSignatures" translate>Payment Proposals</span>
<span ng-show="!requiresMultipleSignatures" translate>Unsent transactions</span>
</div> -->
<div class="wallet-details__group-label" style="padding-bottom: 8px;">
<span ng-show="requiresMultipleSignatures" translate>Proposals</span>
<span ng-show="!requiresMultipleSignatures" translate>Unsent transactions</span>
</div>
<div ng-repeat="tx in txps" class="item item-icon-left" ng-click="openTxpModal(tx)">
<span ng-include="'views/includes/txp.html'"></span>
<div ng-repeat="tx in txps" ng-click="openTxpModal(tx)">
<a class="wallet-details__item proposal item" ng-include="'views/includes/txp.html'"></a>
</div>
<div class="item item-footer description" ng-show="status.lockedBalanceSat">
<div class="item item-footer description" ng-show="status.lockedBalanceSat" style="background: white;">
<span translate>Total Locked Balance</span>:
<b>{{status.lockedBalanceStr}} </b>
<span> {{status.lockedBalanceAlternative}} {{status.alternativeIsoCode}} </span>
@ -102,51 +190,74 @@
</div>
</div>
<div class="list" ng-show="txHistory[0]">
<div class="item" ng-repeat="btx in txHistory track by $index" ng-click="openTxModal(btx)">
<span class="item-note text-right">
<span class="wallet-details__tx-amount" ng-class="{'wallet-details__tx-amount--recent': btx.recent, 'wallet-details__tx-amount--received': btx.action == 'received', 'wallet-details__tx-amount--sent': btx.action == 'sent'}">
<span ng-if="btx.action == 'sent'"></span>
<span class="size-12" ng-if="btx.action == 'invalid'" translate>
(possible double spend)
</span>
<span ng-if="btx.action != 'invalid'">
{{btx.amountStr}}
</span>
<div class="wallet-details__list" ng-show="txHistory[0]">
<div ng-repeat="btx in txHistory track by $index" ng-click="openTxModal(btx)">
<div class="wallet-details__group-label" ng-if="isFirstInGroup($index)">
<span ng-if="isDateInCurrentMonth(getDate(btx.time))">
Recent
</span>
<span ng-if="!isDateInCurrentMonth(getDate(btx.time))">
{{getDate(btx.time) | date:'MMMM'}}
</span>
<p>
<time class="wallet-details__tx-time" ng-if="btx.time">{{btx.time * 1000 | amTimeAgo}}</time>
<span translate class="text-warning"
ng-show="!btx.time && (!btx.confirmations || btx.confirmations == 0)">
Unconfirmed
</span>
</p>
</span>
<img class="wallet-details__tx-icon" src="img/icon-tx-received.svg" width="40" ng-if="btx.action == 'received'">
<img class="wallet-details__tx-icon" src="img/icon-tx-sent.svg" width="40" ng-if="btx.action == 'sent'">
<img class="wallet-details__tx-icon" src="img/icon-tx-moved.svg" width="40" ng-if="btx.action == 'moved'">
<div class="wallet-details__tx-title">
<div ng-show="btx.action == 'received'" class="ellipsis">
<div ng-if="btx.note.body">{{btx.note.body}}</div>
<div ng-if="!btx.note.body" translate> Received</div>
</div>
<div ng-show="btx.action == 'sent'" class="ellipsis">
<div ng-if="btx.message">{{btx.message}}</div>
<div ng-if="!btx.message && btx.note.body">{{btx.note.body}}</div>
<div ng-if="!btx.message && !btx.note.body && addressbook[btx.addressTo]">
{{addressbook[btx.addressTo].name || addressbook[btx.addressTo]}}
</div>
<div ng-if="!btx.message && !btx.note.body && !addressbook[btx.addressTo]" translate>Sent</div>
</div>
<div ng-show="btx.action == 'moved'" class="ellipsis">
<div ng-if="btx.note.body">{{btx.note.body}}</div>
<div ng-if="!btx.note.body" translate>Moved</div>
</div>
<span class="label tu warning radius" ng-if="btx.action == 'invalid'" translate>Invalid</span>
</div>
<a class="wallet-details__item item">
<img class="wallet-details__tx-icon" src="img/icon-confirming.svg" width="40" ng-if="isUnconfirmed(btx)">
<span ng-if="!isUnconfirmed(btx)">
<img class="wallet-details__tx-icon" src="img/icon-tx-received-outline.svg" width="40" ng-if="btx.action == 'received'">
<img class="wallet-details__tx-icon" src="img/icon-tx-sent-outline.svg" width="40" ng-if="btx.action == 'sent'">
<img class="wallet-details__tx-icon" src="img/icon-tx-moved-outline.svg" width="40" ng-if="btx.action == 'moved'">
</span>
<div class="wallet-details__tx-content" ng-class="{'no-border': isLastInGroup($index)}">
<div class="wallet-details__tx-title" ng-if="!isUnconfirmed(btx)">
<div ng-show="btx.action == 'received'" class="ellipsis">
<div ng-if="btx.note.body" class="wallet-details__tx-message ellipsis">{{btx.note.body}}</div>
<div ng-if="!btx.note.body" class="wallet-details__tx-message ellipsis" translate> Received</div>
</div>
<div ng-show="btx.action == 'sent'" class="ellipsis">
<div ng-if="btx.message" class="wallet-details__tx-message ellipsis">{{btx.message}}</div>
<div ng-if="!btx.message && btx.note.body" class="wallet-details__tx-message ellipsis">{{btx.note.body}}</div>
<div ng-if="!btx.message && !btx.note.body && addressbook[btx.addressTo]" class="wallet-details__tx-message ellipsis">
{{addressbook[btx.addressTo].name || addressbook[btx.addressTo]}}
</div>
<div ng-if="!btx.message && !btx.note.body && !addressbook[btx.addressTo]" translate>Sent</div>
</div>
<div ng-show="btx.action == 'moved'" class="ellipsis">
<div ng-if="btx.note.body" class="wallet-details__tx-message ellipsis">{{btx.note.body}}</div>
<div ng-if="!btx.note.body" class="wallet-details__tx-message ellipsis" translate>Moved</div>
</div>
<span class="label tu warning radius" ng-if="btx.action == 'invalid'" translate>Invalid</span>
</div>
<div class="wallet-details__tx-title" ng-if="isUnconfirmed(btx)">
<div class="ellipsis" style="color: #B4B4B4;">
<span ng-if="btx.action == 'sent' || btx.action == 'moved'">Sending</span>
<span ng-if="btx.action == 'received'">Receiving</span>
</div>
</div>
<span class="item-note text-right wallet-details__tx-amount">
<span class="wallet-details__tx-amount" ng-class="{'wallet-details__tx-amount--recent': btx.recent, 'wallet-details__tx-amount--received': btx.action == 'received', 'wallet-details__tx-amount--sent': btx.action == 'sent'}">
<span ng-if="btx.action == 'sent'"></span>
<span class="size-12" ng-if="btx.action == 'invalid'" translate>
(possible double spend)
</span>
<span ng-if="btx.action != 'invalid'">
{{btx.amountStr}}
</span>
</span>
<div>
<time class="wallet-details__tx-time" ng-if="btx.time && createdWithinPastDay(btx.time)">{{btx.time * 1000 | amTimeAgo}}</time>
<time class="wallet-details__tx-time" ng-if="btx.time && !createdWithinPastDay(btx.time)">{{btx.time * 1000 | date:'MMMM d, y'}}</time>
</div>
</span>
</div>
</a>
</div>
</div>
<ion-infinite-scroll
@ -156,4 +267,5 @@
</ion-infinite-scroll>
</div>
</ion-content>
</div>
</ion-view>