diff --git a/src/js/controllers/walletDetails.js b/src/js/controllers/walletDetails.js index 9e915deed..710bf3545 100644 --- a/src/js/controllers/walletDetails.js +++ b/src/js/controllers/walletDetails.js @@ -67,6 +67,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun setPendingTxps(status.pendingTxps); $scope.status = status; } + refreshAmountSection(); $timeout(function() { $scope.$apply(); }); @@ -107,6 +108,19 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun }); }; + $scope.openBalanceModal = function() { + $ionicModal.fromTemplateUrl('views/modals/wallet-balance.html', { + scope: $scope + }).then(function(modal) { + $scope.walletBalanceModal = modal; + $scope.walletBalanceModal.show(); + }); + + $scope.close = function() { + $scope.walletBalanceModal.hide(); + }; + }; + $scope.recreate = function() { walletService.recreate($scope.wallet, function(err) { if (err) return; @@ -234,11 +248,10 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun }; var prevPos; - var screenInactive = true; function getScrollPosition() { var scrollPosition = $ionicScrollDelegate.getScrollPosition(); - if (!scrollPosition || screenInactive) { + if (!scrollPosition) { $window.requestAnimationFrame(function() { getScrollPosition(); }); @@ -252,16 +265,21 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun return; } prevPos = pos; - var amountHeight = 180 - pos; + refreshAmountSection(pos); + }; + + function refreshAmountSection(scrollPos) { + scrollPos = scrollPos || 0; + var amountHeight = 210 - scrollPos; if (amountHeight < 80) { amountHeight = 80; } var contentMargin = amountHeight; - if (contentMargin > 180) { - contentMargin = 180; + if (contentMargin > 210) { + contentMargin = 210; } - var amountScale = (amountHeight / 180); + var amountScale = (amountHeight / 210); if (amountScale < 0.5) { amountScale = 0.5; } @@ -271,11 +289,31 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun var s = amountScale; + // Make space for the balance button when it needs to display. + var TOP_NO_BALANCE_BUTTON = 45; + var TOP_BALANCE_BUTTON = 10; + var top = TOP_NO_BALANCE_BUTTON; + $scope.showBalanceButton = ($scope.wallet.status.totalBalanceSat != $scope.wallet.status.spendableAmount); + if ($scope.showBalanceButton) { + top = TOP_BALANCE_BUTTON; + $scope.showBalanceButton = true; + } + + var amountTop = ((amountScale - 0.5) / 0.5) * top; + if (amountTop < 5) { + amountTop = 5; + } + if (amountTop > top) { + amountTop = top; + } + + var t = amountTop; + $scope.altAmountOpacity = (amountHeight - 100) / 80; $window.requestAnimationFrame(function() { $scope.amountHeight = amountHeight + 'px'; $scope.contentMargin = contentMargin + 'px'; - $scope.amountScale = 'scale3d(' + s + ',' + s + ',' + s + ')'; + $scope.amountScale = 'scale3d(' + s + ',' + s + ',' + s + ') translateY(' + t + 'px)'; $scope.$digest(); getScrollPosition(); }); @@ -285,16 +323,10 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun $scope.$on("$ionicView.enter", function(event, data) { if ($scope.isCordova && $scope.isAndroid) setAndroidStatusBarColor(); - $timeout(function() { - screenInactive = false; - }, 200); if (scrollWatcherInitialized || !$scope.amountIsCollapsible) { return; } scrollWatcherInitialized = true; - $timeout(function() { - getScrollPosition(); - }, 100); }); $scope.$on("$ionicView.beforeEnter", function(event, data) { @@ -308,6 +340,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun }); $scope.updateAll(); + refreshAmountSection(); listeners = [ $rootScope.$on('bwsEvent', function(e, walletId) { @@ -328,7 +361,6 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun }); $scope.$on("$ionicView.leave", function(event, data) { - screenInactive = true; lodash.each(listeners, function(x) { x(); }); diff --git a/src/js/services/walletService.js b/src/js/services/walletService.js index c84c438df..844db435e 100644 --- a/src/js/services/walletService.js +++ b/src/js/services/walletService.js @@ -160,19 +160,22 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim // Address with Balance cache.balanceByAddress = balance.byAddress; + // Total wallet balance is same regardless of 'spend unconfirmed funds' setting. + cache.totalBalanceSat = balance.totalAmount; + // Spend unconfirmed funds if (config.spendUnconfirmed) { - cache.totalBalanceSat = balance.totalAmount; cache.lockedBalanceSat = balance.lockedAmount; cache.availableBalanceSat = balance.availableAmount; cache.totalBytesToSendMax = balance.totalBytesToSendMax; - cache.pendingAmount = null; + cache.pendingAmount = 0; + cache.spendableAmount = balance.totalAmount - balance.lockedAmount; } else { - cache.totalBalanceSat = balance.totalConfirmedAmount; cache.lockedBalanceSat = balance.lockedConfirmedAmount; cache.availableBalanceSat = balance.availableConfirmedAmount; cache.totalBytesToSendMax = balance.totalBytesToSendConfirmedMax; cache.pendingAmount = balance.totalAmount - balance.totalConfirmedAmount; + cache.spendableAmount = balance.totalConfirmedAmount - balance.lockedAmount; } // Selected unit @@ -184,13 +187,8 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim cache.totalBalanceStr = txFormatService.formatAmount(cache.totalBalanceSat) + ' ' + cache.unitName; cache.lockedBalanceStr = txFormatService.formatAmount(cache.lockedBalanceSat) + ' ' + cache.unitName; cache.availableBalanceStr = txFormatService.formatAmount(cache.availableBalanceSat) + ' ' + cache.unitName; - cache.pendingBalanceStr = txFormatService.formatAmount(cache.totalBalanceSat + (cache.pendingAmount === null ? 0 : cache.pendingAmount)) + ' ' + cache.unitName; - - if (cache.pendingAmount !== null && cache.pendingAmount !== 0) { - cache.pendingAmountStr = txFormatService.formatAmount(cache.pendingAmount) + ' ' + cache.unitName; - } else { - cache.pendingAmountStr = null; - } + cache.spendableBalanceStr = txFormatService.formatAmount(cache.spendableAmount) + ' ' + cache.unitName; + cache.pendingBalanceStr = txFormatService.formatAmount(cache.pendingAmount) + ' ' + cache.unitName; cache.alternativeName = config.settings.alternativeName; cache.alternativeIsoCode = config.settings.alternativeIsoCode; @@ -209,11 +207,15 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim rateService.whenAvailable(function() { var totalBalanceAlternative = rateService.toFiat(cache.totalBalanceSat, cache.alternativeIsoCode); + var pendingBalanceAlternative = rateService.toFiat(cache.pendingAmount, cache.alternativeIsoCode); var lockedBalanceAlternative = rateService.toFiat(cache.lockedBalanceSat, cache.alternativeIsoCode); + var spendableBalanceAlternative = rateService.toFiat(cache.spendableAmount, cache.alternativeIsoCode); var alternativeConversionRate = rateService.toFiat(100000000, cache.alternativeIsoCode); cache.totalBalanceAlternative = $filter('formatFiatAmount')(totalBalanceAlternative); + cache.pendingBalanceAlternative = $filter('formatFiatAmount')(pendingBalanceAlternative); cache.lockedBalanceAlternative = $filter('formatFiatAmount')(lockedBalanceAlternative); + cache.spendableBalanceAlternative = $filter('formatFiatAmount')(spendableBalanceAlternative); cache.alternativeConversionRate = $filter('formatFiatAmount')(alternativeConversionRate); cache.alternativeBalanceAvailable = true; diff --git a/src/sass/views/tab-home.scss b/src/sass/views/tab-home.scss index 80ed81634..692224cf2 100644 --- a/src/sass/views/tab-home.scss +++ b/src/sass/views/tab-home.scss @@ -111,6 +111,13 @@ font-weight: 300; color: $light-gray; } + &__status-icon { + font-size: 18px; + margin-left: 5px; + position: relative; + top: 1px; + color: $light-gray; + } } } .release { diff --git a/src/sass/views/views.scss b/src/sass/views/views.scss index 1e88f8af0..8e241aba7 100644 --- a/src/sass/views/views.scss +++ b/src/sass/views/views.scss @@ -9,6 +9,7 @@ @import "tab-scan"; @import "tab-send"; @import "tab-settings"; +@import "walletBalance"; @import "walletDetails"; @import "advancedSettings"; @import "bitpayCard"; diff --git a/src/sass/views/walletBalance.scss b/src/sass/views/walletBalance.scss new file mode 100644 index 000000000..84ec41109 --- /dev/null +++ b/src/sass/views/walletBalance.scss @@ -0,0 +1,113 @@ +.wallet-balance { + + &__amount { + + font-size: 16px; + + &--total { + color: $mid-gray; + } + + &--available { + color: #09C286;; + } + + &--confirming { + color: #FF9900; + } + + &--locked { + color: #FF9900; + } + + &--alternative { + color: $light-gray; + font-size: 14px; + } + + } + + &__title { + flex-grow: 1; + color: $dark-gray; + overflow: hidden; + } + + &__icon { + float: left; + margin-right: 1rem; + color: $light-gray; + font-size: 24px; + } + + &__list { + background: #f5f5f5; + } + + .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; + } + + &__content { + display: flex; + align-items: center; + flex-grow: 1; + padding: 0.6rem 0; + padding-right: 1rem; + border-bottom: 1px solid rgb(245, 245, 245); + overflow: hidden; + + &.no-border { + border: 0; + } + } + + &__amount { + white-space: nowrap; + } + + &__heading { + font-size: 17px; + color: #445; + margin: 1rem 1rem 1rem 1rem; + } + + &__description { + font-size: 12.5px; + color: #667; + margin: 0.7rem; + line-height: 16px; + } + +} + +#wallet-balance { + .bar-header { + border: 0; + background: none; + .title, .button { + color: #fff; + } + .button { + background-color: transparent; + } + } + + ion-content { + background: #F5F5F5; + } + +} diff --git a/src/sass/views/walletDetails.scss b/src/sass/views/walletDetails.scss index f6220c524..52dd836bc 100644 --- a/src/sass/views/walletDetails.scss +++ b/src/sass/views/walletDetails.scss @@ -130,7 +130,7 @@ ion-content { &.collapsible { - margin-top: 180px; + margin-top: 210px; } padding-top: 0; @@ -168,9 +168,9 @@ width: 100%; text-align: center; color: #fff; - height: 180px; + height: 210px; padding-top: 40px; - display: flex; + display: block; align-items: center; justify-content: center; @@ -179,8 +179,7 @@ } &__balance { - transform: scale3d(1, 1, 1); - margin-top: 5px; + transform: scale3d(1, 1, 1) translateY(45px); } &__updating { @@ -192,9 +191,11 @@ line-height: 36px; } - strong { - line-height: 100%; + &__button-balance { + background-color: transparent; + border: 1px solid rgba(255,255,255,0.25); } + } .item.item-footer { font-weight: lighter; @@ -214,7 +215,7 @@ position: absolute; top: inherit; left: 10px; - bottom: 15px; + bottom: 5px; font-size: 20px; color: #fff; } diff --git a/www/img/icon-confirming-clear.svg b/www/img/icon-confirming-clear.svg new file mode 100644 index 000000000..e7cf58529 --- /dev/null +++ b/www/img/icon-confirming-clear.svg @@ -0,0 +1,18 @@ + + + + +Group 2 +Created with Sketch. + + + + + + + + + diff --git a/www/img/icon-important.svg b/www/img/icon-important.svg new file mode 100644 index 000000000..4f113aaf2 --- /dev/null +++ b/www/img/icon-important.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/www/img/icon-sigma.svg b/www/img/icon-sigma.svg new file mode 100644 index 000000000..0baf24a13 --- /dev/null +++ b/www/img/icon-sigma.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/www/views/modals/wallet-balance.html b/www/views/modals/wallet-balance.html new file mode 100644 index 000000000..d68109fa3 --- /dev/null +++ b/www/views/modals/wallet-balance.html @@ -0,0 +1,96 @@ + + + +
+ {{wallet.name}} +
+
+ + + +
+
+ +
All of your bitcoin wallet balance may not be available for immediate spending.
+
+
+ +
+
Total
+ + + {{status.totalBalanceStr}} + +
+ + {{status.totalBalanceAlternative}} {{status.alternativeIsoCode}} + +
+
+
+
+
The total amount of bitcoin stored in this wallet.
+
+
+
+ +
+
Available
+ + + {{status.spendableBalanceStr}} + +
+ + {{status.spendableBalanceAlternative}} {{status.alternativeIsoCode}} + +
+
+
+
+
The amount of bitcoin immediately spendable from this wallet.
+
+
+
+ +
+
Confirming
+ + + {{status.pendingBalanceStr}} + +
+ + {{status.pendingBalanceAlternative}} {{status.alternativeIsoCode}} + +
+
+
+
+
The amount of bitcoin stored in this wallet with less than 1 blockchain confirmation.
+
+
+
+ +
+
Locked
+ + + {{status.lockedBalanceStr}} + +
+ + {{status.lockedBalanceAlternative}} {{status.alternativeIsoCode}} + +
+
+
+
+
The amount of bitcoin stored in this wallet that is allocated as inputs to your pending transaction proposals. The amount is determined using unspent transaction outputs associated with this wallet and may be more than the actual amounts associated with your pending transaction proposals.
+
+
+
diff --git a/www/views/tab-home.html b/www/views/tab-home.html index 391f35636..2cb7387dd 100644 --- a/www/views/tab-home.html +++ b/www/views/tab-home.html @@ -80,11 +80,12 @@ Incomplete - {{wallet.status.pendingBalanceStr}} + {{wallet.status.totalBalanceStr}} [Balance Hidden] {{wallet.m}}-of-{{wallet.n}} + {{wallet.error}}   diff --git a/www/views/walletDetails.html b/www/views/walletDetails.html index 46a89a93e..d89023f4e 100644 --- a/www/views/walletDetails.html +++ b/www/views/walletDetails.html @@ -27,11 +27,12 @@
+ {{updateStatusError}} Tap to retry
- This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information. + This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information. Recreate
@@ -45,21 +46,15 @@ ng-show="!updateStatusError && wallet.walletScanStatus != 'error' && !wallet.balanceHidden" on-hold="hideToggle()" ng-style="{'transform': amountScale}" - class="amount__balance" - > - {{status.totalBalanceStr}} + class="amount__balance"> + {{status.totalBalanceStr}}
{{status.totalBalanceAlternative}} {{status.alternativeIsoCode}}
-
-
Available: {{status.totalBalanceStr}}
-
Confirming: {{status.pendingAmountStr}}
-
+ +
+ +
+
@@ -78,7 +87,6 @@
-
@@ -105,24 +113,14 @@
- {{updateStatusError}} + {{updateStatusError}} Tap to retry
- This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information. + This wallet is not registered at the given Bitcore Wallet Service (BWS). You can recreate it from the local information. Recreate
- -
- {{status.totalBalanceStr}} -
{{status.totalBalanceAlternative}} {{status.alternativeIsoCode}}
-
-
Available: {{status.totalBalanceStr}}
-
Confirming: {{status.pendingAmountStr}}
-
-
-
[Balance Hidden]