diff --git a/backupRecovery.md b/backupRecovery.md index 3865b66f2..db8f19989 100644 --- a/backupRecovery.md +++ b/backupRecovery.md @@ -19,7 +19,7 @@ Copay is a Multisig HD Wallet. Copay app holds the extended private keys for the ### Wallet Recovery Scope * Basic Recovery: Wallet access is restored. It is possible to see wallet balance and past transactions. It is possible to send and receive payments. - * Full Recovery: All the features of Partial Recovery + wallet name, copayer names are recovered, past payment proposal metadata (who signed, and notes) are recoved. + * Full Recovery: All the features of Partial Recovery + wallet name, copayer names are recovered, past payment proposal metadata (who signed, and notes) are recovered. ## Wallet Restore Scenarios diff --git a/src/js/controllers/feedback/complete.js b/src/js/controllers/feedback/complete.js index c337e14f9..80018be79 100644 --- a/src/js/controllers/feedback/complete.js +++ b/src/js/controllers/feedback/complete.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('completeController', function($scope, $stateParams, $timeout, $log, platformInfo, configService, storageService) { +angular.module('copayApp.controllers').controller('completeController', function($scope, $stateParams, $timeout, $log, $ionicHistory, $state, platformInfo, configService, storageService, lodash) { $scope.score = parseInt($stateParams.score); $scope.skipped = $stateParams.skipped == 'false' ? false : true; $scope.isCordova = platformInfo.isCordova; @@ -31,8 +31,13 @@ angular.module('copayApp.controllers').controller('completeController', function }; $scope.$on("$ionicView.beforeEnter", function(event, data) { + if(window.StatusBar){ + $log.debug('Hiding status bar...'); + StatusBar.hide(); + } + storageService.getFeedbackInfo(function(error, info) { - var feedbackInfo = JSON.parse(info); + var feedbackInfo = lodash.isString(info) ? JSON.parse(info) : null; feedbackInfo.sent = true; storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {}); }); @@ -78,4 +83,22 @@ angular.module('copayApp.controllers').controller('completeController', function } }, 100); }); + + $scope.$on("$ionicView.afterLeave", function() { + if(window.StatusBar){ + $log.debug('Showing status bar...'); + StatusBar.show(); + } + }); + + $scope.close = function() { + $ionicHistory.clearHistory(); + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $timeout(function() { + $state.go('tabs.home'); + }, 100); + }; }); diff --git a/src/js/controllers/feedback/rateApp.js b/src/js/controllers/feedback/rateApp.js index 764b79faa..6d16cfb24 100644 --- a/src/js/controllers/feedback/rateApp.js +++ b/src/js/controllers/feedback/rateApp.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('rateAppController', function($scope, $state, $stateParams, lodash, externalLinkService, configService, gettextCatalog, platformInfo, feedbackService, ongoingProcess) { +angular.module('copayApp.controllers').controller('rateAppController', function($scope, $state, $stateParams, lodash, externalLinkService, configService, gettextCatalog, platformInfo, feedbackService, ongoingProcess, popupService) { $scope.score = parseInt($stateParams.score); var isAndroid = platformInfo.isAndroid; var isIOS = platformInfo.isIOS; @@ -22,28 +22,39 @@ angular.module('copayApp.controllers').controller('rateAppController', function( popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not send feedback')); return; } - $state.go('feedback.complete', { + $state.go('tabs.rate.complete', { score: $stateParams.score, skipped: true }); }); }; + $scope.$on("$ionicView.beforeEnter", function() { + if(window.StatusBar){ + $log.debug('Hiding status bar...'); + StatusBar.hide(); + } + }); + + $scope.$on("$ionicView.afterLeave", function() { + if(window.StatusBar){ + $log.debug('Showing status bar...'); + StatusBar.show(); + } + }); + $scope.sendFeedback = function() { - $state.go('feedback.send', { + $state.go('tabs.rate.send', { score: $scope.score }); }; $scope.goAppStore = function() { + var defaults = configService.getDefaults(); var url; - if (isAndroid) url = config.rateApp.android; - if (isIOS) url = config.rateApp.ios; - // if (isWP) url = config.rateApp.ios; TODO - var title = gettextCatalog.getString('Rate the app'); - var message = gettextCatalog.getString('You must go to the official website of the app to rate it'); - var okText = gettextCatalog.getString('Go'); - var cancelText = gettextCatalog.getString('Cancel'); - externalLinkService.open(url, true, title, message, okText, cancelText); + if (isAndroid) url = defaults.rateApp.android; + if (isIOS) url = defaults.rateApp.ios; + // if (isWP) url = defaults.rateApp.windows; // TODO + externalLinkService.open(url); }; }); diff --git a/src/js/controllers/feedback/rateCard.js b/src/js/controllers/feedback/rateCard.js index 4c858b3ed..d2c92053a 100644 --- a/src/js/controllers/feedback/rateCard.js +++ b/src/js/controllers/feedback/rateCard.js @@ -6,16 +6,12 @@ angular.module('copayApp.controllers').controller('rateCardController', function $scope.score = 0; $scope.goFeedbackFlow = function() { - if ($scope.isModal) { - $scope.rateModal.hide(); - $scope.rateModal.remove(); - } if ($scope.isCordova && $scope.score == 5) { - $state.go('feedback.rateApp', { + $state.go('tabs.rate.rateApp', { score: $scope.score }); } else { - $state.go('feedback.send', { + $state.go('tabs.rate.send', { score: $scope.score }); } @@ -25,7 +21,7 @@ angular.module('copayApp.controllers').controller('rateCardController', function $scope.score = score; switch ($scope.score) { case 1: - $scope.button_title = gettextCatalog.getString("I think this app is terrible"); + $scope.button_title = gettextCatalog.getString("I think this app is terrible."); break; case 2: $scope.button_title = gettextCatalog.getString("I don't like it"); @@ -37,7 +33,7 @@ angular.module('copayApp.controllers').controller('rateCardController', function $scope.button_title = gettextCatalog.getString("I like the app"); break; case 5: - $scope.button_title = gettextCatalog.getString("This app is fantastic"); + $scope.button_title = gettextCatalog.getString("This app is fantastic!"); break; } $timeout(function() { @@ -46,21 +42,16 @@ angular.module('copayApp.controllers').controller('rateCardController', function }; $scope.hideCard = function() { - if ($scope.isModal) { - $scope.rateModal.hide(); - $scope.rateModal.remove(); - } else { - storageService.getFeedbackInfo(function(error, info) { - var feedbackInfo = JSON.parse(info); - feedbackInfo.sent = true; - storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() { - $scope.showRateCard.value = false; - }); + storageService.getFeedbackInfo(function(error, info) { + var feedbackInfo = JSON.parse(info); + feedbackInfo.sent = true; + storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() { + $scope.showRateCard.value = false; + $timeout(function() { + $scope.$apply(); + }, 100); }); - } - $timeout(function() { - $scope.$apply(); - }, 100); + }); } }); diff --git a/src/js/controllers/feedback/send.js b/src/js/controllers/feedback/send.js index fc8fa410c..e65e7cd17 100644 --- a/src/js/controllers/feedback/send.js +++ b/src/js/controllers/feedback/send.js @@ -1,29 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('sendController', function($scope, $state, $log, $stateParams, gettextCatalog, popupService, configService, lodash, feedbackService, ongoingProcess) { - $scope.score = parseInt($stateParams.score); - switch ($scope.score) { - case 1: - $scope.reaction = gettextCatalog.getString("Ouch!"); - $scope.comment = gettextCatalog.getString("There's obviously something we're doing wrong."); - break; - case 2: - $scope.reaction = gettextCatalog.getString("Oh no!"); - $scope.comment = gettextCatalog.getString("There's obviously something we're doing wrong."); - break; - case 3: - $scope.reaction = gettextCatalog.getString("Thanks!"); - $scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay wallet."); - break; - case 4: - $scope.reaction = gettextCatalog.getString("Thanks!"); - $scope.comment = gettextCatalog.getString("That's exciting to hear. We'd love to earn that fifth star from you."); - break; - case 5: - $scope.reaction = gettextCatalog.getString("Feedback!"); - $scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay wallet."); - break; - } +angular.module('copayApp.controllers').controller('sendController', function($scope, $state, $log, $timeout, $stateParams, $ionicNavBarDelegate, $ionicHistory, $ionicConfig, gettextCatalog, popupService, configService, lodash, feedbackService, ongoingProcess) { $scope.sendFeedback = function(feedback, skip) { @@ -32,7 +9,7 @@ angular.module('copayApp.controllers').controller('sendController', function($sc var dataSrc = { "Email": lodash.values(config.emailFor)[0] || ' ', "Feedback": skip ? ' ' : feedback, - "Score": $stateParams.score + "Score": $stateParams.score || ' ' }; ongoingProcess.set('sendingFeedback', true); @@ -42,11 +19,63 @@ angular.module('copayApp.controllers').controller('sendController', function($sc popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Could not send feedback')); return; } - $state.go('feedback.complete', { + if (!$stateParams.score) { + popupService.showAlert(gettextCatalog.getString('Thank you!'), gettextCatalog.getString('A member of the team will review your feedback as soon as possible.'), function() { + $scope.feedback.value = ''; + $ionicHistory.nextViewOptions({ + disableAnimate: true, + historyRoot: true + }); + $ionicHistory.clearHistory(); + $timeout(function() { + $state.go('tabs.settings'); + }); + }); + return; + } + $state.go('tabs.rate.complete', { score: $stateParams.score, skipped: skip }); }); }; + $scope.$on("$ionicView.beforeEnter", function(event, data) { + $scope.score = (data.stateParams && data.stateParams.score) ? parseInt(data.stateParams.score) : null; + $scope.feedback = {}; + + if ($scope.score) { + $ionicNavBarDelegate.showBackButton(false); + $ionicConfig.views.swipeBackEnabled(false); + } + else $ionicNavBarDelegate.showBackButton(true); + + switch ($scope.score) { + case 1: + $scope.reaction = gettextCatalog.getString("Ouch!"); + $scope.comment = gettextCatalog.getString("There's obviously something we're doing wrong.") + ' ' + gettextCatalog.getString("How could we improve your experience?"); + break; + case 2: + $scope.reaction = gettextCatalog.getString("Oh no!"); + $scope.comment = gettextCatalog.getString("There's obviously something we're doing wrong.") + ' ' + gettextCatalog.getString("How could we improve your experience?"); + break; + case 3: + $scope.reaction = gettextCatalog.getString("Hmm..."); + $scope.comment = gettextCatalog.getString("We'd love to do better.") + ' ' + gettextCatalog.getString("How could we improve your experience?"); + break; + case 4: + $scope.reaction = gettextCatalog.getString("Thanks!"); + $scope.comment = gettextCatalog.getString("That's exciting to hear. We'd love to earn that fifth star from you – how could we improve your experience?"); + break; + case 5: + $scope.reaction = gettextCatalog.getString("Thank you!"); + $scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay.") + ' ' + gettextCatalog.getString("Is there anything we could do better?"); + break; + default: + $scope.reaction = gettextCatalog.getString("Feedback!"); + $scope.comment = gettextCatalog.getString("We're always looking for ways to improve BitPay. How could we improve your experience?"); + break; + } + }); + }); diff --git a/src/js/controllers/modals/search.js b/src/js/controllers/modals/search.js index ed1861074..963e89e18 100644 --- a/src/js/controllers/modals/search.js +++ b/src/js/controllers/modals/search.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('searchController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $ionicNavBarDelegate, $state, $stateParams, $ionicScrollDelegate, bwcError, profileService, lodash, configService, gettext, gettextCatalog, platformInfo, walletService) { +angular.module('copayApp.controllers').controller('searchController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, $ionicScrollDelegate, bwcError, profileService, lodash, configService, gettext, gettextCatalog, platformInfo, walletService) { var HISTORY_SHOW_LIMIT = 10; var currentTxHistoryPage = 0; diff --git a/src/js/controllers/tab-settings.js b/src/js/controllers/tab-settings.js index 13d482102..4387685c3 100644 --- a/src/js/controllers/tab-settings.js +++ b/src/js/controllers/tab-settings.js @@ -32,15 +32,4 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct updateConfig(); }); - $scope.openRateModal = function() { - $scope.isModal = true; - $ionicModal.fromTemplateUrl('views/feedback/rateCard.html', { - scope: $scope, - backdropClickToClose: false, - hardwareBackButtonClose: false - }).then(function(modal) { - $scope.rateModal = modal; - $scope.rateModal.show(); - }); - } }); diff --git a/src/js/controllers/tx-details.js b/src/js/controllers/tx-details.js index 1b6beb58b..101df8222 100644 --- a/src/js/controllers/tx-details.js +++ b/src/js/controllers/tx-details.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('txDetailsController', function($log, $ionicHistory, $scope, walletService, lodash, gettextCatalog, profileService, configService, externalLinkService, popupService, ongoingProcess) { +angular.module('copayApp.controllers').controller('txDetailsController', function($log, $ionicHistory, $scope, $timeout, walletService, lodash, gettextCatalog, profileService, configService, externalLinkService, popupService, ongoingProcess) { $scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.title = gettextCatalog.getString('Transaction'); @@ -29,6 +29,9 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio updateMemo(); initActionList(); + $timeout(function() { + $scope.$apply(); + }); }); }); diff --git a/src/js/controllers/walletDetails.js b/src/js/controllers/walletDetails.js index 1aeb09fd1..5d3a5c22e 100644 --- a/src/js/controllers/walletDetails.js +++ b/src/js/controllers/walletDetails.js @@ -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,72 @@ 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; + $scope.wallet = profileService.getWallet($scope.walletId); $scope.requiresMultipleSignatures = $scope.wallet.credentials.m > 1; addressbookService.list(function(err, ab) { @@ -209,6 +321,7 @@ 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/directives/gravatar.js b/src/js/directives/gravatar.js index c76817b5e..2f85fe0eb 100644 --- a/src/js/directives/gravatar.js +++ b/src/js/directives/gravatar.js @@ -16,6 +16,6 @@ angular.module('copayApp.directives') scope.emailHash = md5.createHash(scope.email.toLowerCase() || ''); } }, - template: '{{ name }}' - } + template: '{{ name }}' + }; }); diff --git a/src/js/routes.js b/src/js/routes.js index a80c3e791..e424b5cb6 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -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 * */ @@ -726,43 +743,52 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr * */ - .state('feedback', { + .state('tabs.feedback', { url: '/feedback', - abstract: true, - template: '' - }) - .state('feedback.send', { - url: '/send/:score', views: { - 'feedback': { - controller: 'sendController', - templateUrl: 'views/feedback/send.html' + 'tab-settings@tabs': { + templateUrl: 'views/feedback/send.html', + controller: 'sendController' } } }) - .state('feedback.complete', { + .state('tabs.rate', { + url: '/rate', + abstract: true + }) + .state('tabs.rate.send', { + url: '/send/:score', + views: { + 'tab-home@tabs': { + templateUrl: 'views/feedback/send.html', + controller: 'sendController' + } + } + }) + .state('tabs.rate.complete', { url: '/complete/:score/:skipped', views: { - 'feedback': { + 'tab-home@tabs': { controller: 'completeController', templateUrl: 'views/feedback/complete.html' } } }) - .state('feedback.rateApp', { + .state('tabs.rate.rateApp', { url: '/rateApp/:score', views: { - 'feedback': { + 'tab-home@tabs': { controller: 'rateAppController', templateUrl: 'views/feedback/rateApp.html' } } }) - /* - * - * Buy or Sell Bitcoin - * - */ + + /* + * + * Buy or Sell Bitcoin + * + */ .state('tabs.buyandsell', { url: '/buyandsell', diff --git a/src/js/services/configService.js b/src/js/services/configService.js index a51906f82..5bd6c3cc6 100644 --- a/src/js/services/configService.js +++ b/src/js/services/configService.js @@ -20,7 +20,7 @@ angular.module('copayApp.services').factory('configService', function(storageSer }, rateApp: { - ios: 'https://itunes.apple.com/app/bitpay-secure-bitcoin-wallet/id1149581638', + ios: 'http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=1149581638&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8', android: 'https://play.google.com/store/apps/details?id=com.bitpay.wallet', wp: '' }, diff --git a/src/js/services/feeService.js b/src/js/services/feeService.js index de1caa722..5142edf66 100644 --- a/src/js/services/feeService.js +++ b/src/js/services/feeService.js @@ -30,7 +30,7 @@ angular.module('copayApp.services').factory('feeService', function($log, $stateP var feeLevelValue = lodash.find(levels, { level: feeLevel }); - if (!feeLevelValue || !feeLevelValue.feePerKB) + if (!feeLevelValue || feeLevelValue.feePerKB == null) return cb({ message: 'Could not get dynamic fee for level: ' + feeLevel }); diff --git a/src/js/services/popupService.js b/src/js/services/popupService.js index 8a78b6035..a1fc1ffe0 100644 --- a/src/js/services/popupService.js +++ b/src/js/services/popupService.js @@ -51,12 +51,12 @@ angular.module('copayApp.services').service('popupService', function($log, $ioni var _cordovaConfirm = function(title, message, okText, cancelText, cb) { var onConfirm = function(buttonIndex) { - if (buttonIndex == 1) return cb(true); + if (buttonIndex == 2) return cb(true); else return cb(false); } okText = okText || gettextCatalog.getString('OK'); cancelText = cancelText || gettextCatalog.getString('Cancel'); - navigator.notification.confirm(message, onConfirm, title, [okText, cancelText]); + navigator.notification.confirm(message, onConfirm, title, [cancelText, okText]); }; var _cordovaPrompt = function(title, message, opts, cb) { diff --git a/src/sass/views/bitpayCard.scss b/src/sass/views/bitpayCard.scss index 70bd2d762..fb796869c 100644 --- a/src/sass/views/bitpayCard.scss +++ b/src/sass/views/bitpayCard.scss @@ -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; + } + } } diff --git a/src/sass/views/confirm.scss b/src/sass/views/confirm.scss index 172f82173..6ae3d89d1 100644 --- a/src/sass/views/confirm.scss +++ b/src/sass/views/confirm.scss @@ -1,3 +1,5 @@ #view-confirm { - + .tx-details-content > .scroll { + padding-bottom: .25rem; + } } diff --git a/src/sass/views/feedback/complete.scss b/src/sass/views/feedback/complete.scss index f5e0052b9..240110ad1 100644 --- a/src/sass/views/feedback/complete.scss +++ b/src/sass/views/feedback/complete.scss @@ -19,6 +19,8 @@ } .subtitle { padding: 10px 30px 20px 40px; + text-align: center; + color: $mid-gray; } .icon-svg > img { height: 16rem; @@ -40,6 +42,7 @@ bottom: 0; width: 100%; position: absolute; + padding: 20px; background-color: $subtle-gray; .row { margin: 20px 0px 20px; diff --git a/src/sass/views/feedback/rateApp.scss b/src/sass/views/feedback/rateApp.scss index 9f44f5920..26b8841be 100644 --- a/src/sass/views/feedback/rateApp.scss +++ b/src/sass/views/feedback/rateApp.scss @@ -1,9 +1,12 @@ #rate-app { background-color: #ffffff; .skip { - margin: 10px; + margin-top: 15px; color: #667; } + .skip-rating { + margin-right: 15px; + } .icon-svg > img { width: 80px; height: 80px; @@ -13,20 +16,18 @@ font-size: 20px; font-weight: bold; color: $dark-gray; - margin: 40px 50px 10px; + margin: 80px 50px 10px; text-align: center; } .subtitle { padding: 10px 30px 20px 40px; + color: #667; } .buttons { bottom: 0; width: 100%; position: absolute; background-color: $subtle-gray; - .button { - margin-top: 40px; - margin-bottom: 30px; - } + padding: 50px 0; } } diff --git a/src/sass/views/feedback/rateCard.scss b/src/sass/views/feedback/rateCard.scss index d141ca633..9d57643d6 100644 --- a/src/sass/views/feedback/rateCard.scss +++ b/src/sass/views/feedback/rateCard.scss @@ -1,14 +1,18 @@ #rate-card { + .item-heading { + font-weight: 700; + } .row { border: none; } - .row.row-margin{ - margin: 20px 0px 20px 0px; - } .item-icon-right { margin: 0; } .feedback-flow-button { - padding: 20px; + margin-bottom: 20px; + } + .icon-svg > img { + height: 1.8rem; + margin-bottom: 5px; } } diff --git a/src/sass/views/feedback/send.scss b/src/sass/views/feedback/send.scss index 2a0f9a210..b4c383587 100644 --- a/src/sass/views/feedback/send.scss +++ b/src/sass/views/feedback/send.scss @@ -4,27 +4,34 @@ border: none; } .skip { - margin: 20px 20px 10px; - color: #667; - text-decoration: none; + color: rgba(255, 255, 255, 0.3); + } + .feedback-heading { + padding-top: 20px } .title { - padding: 20px; + padding-left: 10px; font-size: 20px; font-weight: bold; color: $dark-gray; } + .rating { + text-align: right; + padding-right: 15px; + } .comment { - padding: 20px; + padding: 0 20px 20px; font-size: 1rem; line-height: 1.5em; font-weight: 300; color: $dark-gray; } - textarea { - padding: 20px; + .user-feedback { border-top: 1px solid $subtle-gray; - padding: 20px; width: 100%; } + .send-feedback-star { + height: 1rem; + margin-left: 5px; + } } diff --git a/src/sass/views/includes/txp-details.scss b/src/sass/views/includes/txp-details.scss index 8c5e7c723..9ebb8ad67 100644 --- a/src/sass/views/includes/txp-details.scss +++ b/src/sass/views/includes/txp-details.scss @@ -23,6 +23,8 @@ img { margin-right: 1rem; + height: 35px; + width: 35px; } span { diff --git a/src/sass/views/includes/wallets.scss b/src/sass/views/includes/wallets.scss index 7bb22c807..5c73d70c7 100644 --- a/src/sass/views/includes/wallets.scss +++ b/src/sass/views/includes/wallets.scss @@ -18,16 +18,18 @@ } } .item{ - padding: calc(100vh - 99vh) calc(100vw - 93vw) calc(100vh - 97vh) calc(100vw - 95vw); - i{left:auto;} + padding: 3vh 3vw 3vh 3vw; span{ clear:both; width: 100%; display: inline-block; &.wallet-name{ - margin-top:10px; - margin-bottom:5px; - font-size:13px; + font-size:16px; + width: 70%; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + font-weight: 600; } &.wallet-number{ visibility: hidden; diff --git a/src/sass/views/tab-home.scss b/src/sass/views/tab-home.scss index ae1f52936..ca1a7bde9 100644 --- a/src/sass/views/tab-home.scss +++ b/src/sass/views/tab-home.scss @@ -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; diff --git a/src/sass/views/tab-receive.scss b/src/sass/views/tab-receive.scss index 99bc97ea5..6743b1363 100644 --- a/src/sass/views/tab-receive.scss +++ b/src/sass/views/tab-receive.scss @@ -13,14 +13,17 @@ .scroll{height:100%;} #address { background: #fff; - height: calc(100vh - 34vh); + height: 66vh; display: flex; align-items: center; justify-content: center; position: relative; flex-flow: column; @media(max-height: 600px){ - height: calc(100vh - 36vh); + height: 68vh; + } + @media(max-height: 600px) and (-webkit-device-pixel-ratio: 2){ + height: 64vh; } &-info{ height: 100%; @@ -64,15 +67,27 @@ .item { border: none; font-size: .8rem; + z-index: 0; i { font-size: 1.3rem; } } + #qr-options{ + .item{ + font-size:.7rem; + @media(min-width:350px){ + font-size:.9rem; + } + @media(min-width:450px){ + font-size:1rem; + } + } + } .bit-address { font-size: .8rem; // left:10%; position: absolute; - transition: all .4s ease; + transition: all .15s ease; width:100%; height: 100%; z-index: 0; @@ -100,16 +115,24 @@ padding-bottom: 5px; display: inline-block; font-size: .7rem; + @media(min-width:350px){ + font-size:.9rem; + } + @media(min-width:450px){ + font-size:1rem; + } + color:$light-gray; } } .qr { - padding: calc(100vh - 85vh) 0 calc(100vh - 96vh); + padding: 15vh 0 4vh; align-self: center; margin-top: auto; height: 220px; position: relative; justify-content: center; flex: 1; + z-index: 1; div{ transition: all .4s ease; &.current, &.prev, &.next{ @@ -131,7 +154,7 @@ } } @media(max-height: 700px){ - padding: calc(100vh - 90vh) 0 calc(100vh - 96vh); + padding: 10vh 0 4vh; } div{ display: flex; @@ -235,7 +258,8 @@ } .wallets{ position: relative; - height: calc(100vh - 83vh); + height: calc(27vh - 62px); + z-index: 5; .slides { .swiper-container{ position: absolute; @@ -244,15 +268,29 @@ -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); max-width: 450px; + .swiper-wrapper{ + height: auto; + top: 10%; + position:relative; + @media(max-height: 600px){padding-top:.2rem} + @media(min-height: 900px){top:30%;} + } .swiper-slide{ text-align: center; .card{ margin-top:2vh; display: inline-block; width:80%; + @media(min-height: 1000px) and (max-width: 699px){ + .item{ + padding: 2vh 3vw 2vh 3vw; + } + } + } + @media(max-width: 500px){ + &-next{left:-25%;} + &-prev{left:25%;} } - &-next{left:-25%;} - &-prev{left:25%;} } @media (max-height: 600px){ &{ @@ -267,11 +305,17 @@ .wallets{display: none;} #address{ float:left; - height:90vh; - width:65%; + height:100%; + width:calc(100% - 410px); + @media(max-width: 1000px){ + width:65%; + } &-info{ height: 100%; } + #qr-options{ + .item{font-size:1rem;} + } .qr{ height: 70%; div{ @@ -292,7 +336,14 @@ .backup, #bit-address{left:0;} #bit-address{ height: 10%; - padding: calc(100vh - 99vh); + padding: 1vh; + .bit-address{ + .item{ + top: 40%; + transform: translateY(-40%); + font-size:1rem; + } + } } } #wallets{ @@ -302,18 +353,29 @@ display: flex; flex-direction: column; overflow: visible; + max-width: 410px; + @media(max-height: 600px){ + padding-top:.55rem; + } + @media(max-width: 1000px){ + max-width: none; + } #sidebar-wallet{display: block;} .list{height: 100%;overflow: visible;} #wallet-list{ position: absolute; - width: 100%; - overflow-y: scroll; + width: 110%; + overflow-y: auto; height: 100%; left: -6%; } .wallet{ - position: relative; &.current{ + position: relative; + .card{ + opacity: 1; + transform: scale(1); + } &:before { right: 93%; top: 50%; @@ -331,24 +393,30 @@ } .card { max-width: 350px; - box-shadow:$subtle-box-shadow; + box-shadow: 0 1px 36px rgba(0, 0, 0, 0.07); padding:0; border-radius: 6px; padding:2px; width: 80%; position: relative; margin: 1.5rem auto 0; + position: relative; + opacity: .5; + transform:scale(.85); + transition:transform .2s ease; .item{ padding: 6% 10% 6% 8%; - i{left:auto;} span{ clear:both; width: 100%; display: inline-block; &.wallet-name{ - margin-top:10px; - margin-bottom:5px; - font-size:13px; + font-size:16px; + width: 70%; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + font-weight: 600; } &.wallet-number{ visibility: hidden; diff --git a/src/sass/views/walletDetails.scss b/src/sass/views/walletDetails.scss index 37438bc1d..f6220c524 100644 --- a/src/sass/views/walletDetails.scss +++ b/src/sass/views/walletDetails.scss @@ -6,7 +6,7 @@ font-weight: bold; } &--received { - color: #30af6c; + color: #09C286; } &--sent { color: $dark-gray; @@ -14,18 +14,106 @@ } &__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; + + .scroll-refresher { + z-index: 1; + margin-top: 3.5rem; + } + + .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 +127,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 +218,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; +} diff --git a/www/img/ico-star.svg b/www/img/ico-star.svg index bab3db3e5..864f2b2ba 100644 --- a/www/img/ico-star.svg +++ b/www/img/ico-star.svg @@ -2,7 +2,7 @@ + + + Group 2 + Created with Sketch. + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/www/img/icon-proposal-pending.svg b/www/img/icon-proposal-pending.svg new file mode 100644 index 000000000..6314b99ff --- /dev/null +++ b/www/img/icon-proposal-pending.svg @@ -0,0 +1,23 @@ + + + + Group + Created with Sketch. + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/www/img/icon-tx-moved-outline.svg b/www/img/icon-tx-moved-outline.svg new file mode 100644 index 000000000..1f15f2d7e --- /dev/null +++ b/www/img/icon-tx-moved-outline.svg @@ -0,0 +1,21 @@ + + + + Group 2 + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/www/img/icon-tx-received-outline.svg b/www/img/icon-tx-received-outline.svg new file mode 100644 index 000000000..fe902fab0 --- /dev/null +++ b/www/img/icon-tx-received-outline.svg @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/www/img/icon-tx-sent-outline.svg b/www/img/icon-tx-sent-outline.svg new file mode 100644 index 000000000..790099585 --- /dev/null +++ b/www/img/icon-tx-sent-outline.svg @@ -0,0 +1,21 @@ + + + + Group 2 + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/www/views/bitpayCard.html b/www/views/bitpayCard.html index bf36da1fd..e9a9a53da 100644 --- a/www/views/bitpayCard.html +++ b/www/views/bitpayCard.html @@ -16,10 +16,11 @@ Sandbox version. Only for testing purpose -
+
+
-
${{bitpayCard.bitpayCardCurrentBalance}}
+
${{bitpayCard.bitpayCardCurrentBalance}}
@@ -41,11 +42,13 @@
- +

Get started

-

Your BitPay Card is ready. Add funds to your card to start using your card at stores and ATMs worldwide.

+
+ Your BitPay Card is ready. Add funds to your card to start using your card at stores and ATMs worldwide. +
diff --git a/www/views/confirm.html b/www/views/confirm.html index 6c8dd10ac..94cd36fac 100644 --- a/www/views/confirm.html +++ b/www/views/confirm.html @@ -11,7 +11,7 @@
- + Sending
diff --git a/www/views/feedback/complete.html b/www/views/feedback/complete.html index 07f6730a8..238c82505 100644 --- a/www/views/feedback/complete.html +++ b/www/views/feedback/complete.html @@ -1,11 +1,11 @@ - + -
- +
+
-
Invite friends to BitPay Wallet!
+
Invite friends to BitPay!
@@ -53,45 +53,41 @@