Merge branch 'master' of https://github.com/bitpay/copay into feat/app-identity

This commit is contained in:
Andy Phillipson 2017-01-03 14:08:41 -05:00
commit 189117433a
85 changed files with 1252 additions and 1224 deletions

View file

@ -61,10 +61,10 @@ module.exports = function(grunt) {
stdin: true, stdin: true,
}, },
desktopsign: { desktopsign: {
cmd: 'gpg -u 1112CFA1 --output webkitbuilds/<%= pkg.title %>-linux.zip.sig --detach-sig webkitbuilds/<%= pkg.title %>-linux.zip && gpg -u 1112CFA1 --output webkitbuilds/<%= pkg.title %>-win.exe.sig --detach-sig webkitbuilds/<%= pkg.title %>-win.exe' cmd: 'gpg -u 1112CFA1 --output webkitbuilds/<%= pkg.title %>-linux.zip.sig --detach-sig webkitbuilds/<%= pkg.title %>-linux.zip && gpg -u 1112CFA1 --output webkitbuilds/<%= pkg.title %>.dmg.sig --detach-sig webkitbuilds/<%= pkg.title %>.dmg ; gpg -u 1112CFA1 --output webkitbuilds/<%= pkg.title %>-win.exe.sig --detach-sig webkitbuilds/<%= pkg.title %>-win.exe'
}, },
desktopverify: { desktopverify: {
cmd: 'gpg --verify webkitbuilds/<%= pkg.title %>-linux.zip.sig webkitbuilds/<%= pkg.title %>-linux.zip && gpg --verify webkitbuilds/<%= pkg.title %>-win.exe.sig webkitbuilds/<%= pkg.title %>-win.exe' cmd: 'gpg --verify webkitbuilds/<%= pkg.title %>-linux.zip.sig webkitbuilds/<%= pkg.title %>-linux.zip && gpg --verify webkitbuilds/<%= pkg.title %>.dmg.sig webkitbuilds/<%= pkg.title %>.dmg ; gpg --verify webkitbuilds/<%= pkg.title %>-win.exe.sig webkitbuilds/<%= pkg.title %>-win.exe'
}, },
}, },
watch: { watch: {
@ -74,13 +74,9 @@ module.exports = function(grunt) {
grunt.log.writeln('Waiting for more changes...'); grunt.log.writeln('Waiting for more changes...');
}, },
}, },
css: {
files: ['src/css/*.css'],
tasks: ['concat:css']
},
sass: { sass: {
files: ['src/sass/**/**/*.scss'], files: ['src/sass/**/**/*.scss'],
tasks: ['sass', 'concat:css'] tasks: ['sass']
}, },
main: { main: {
files: [ files: [
@ -104,8 +100,9 @@ module.exports = function(grunt) {
}, },
files: [{ files: [{
expand: true, expand: true,
flatten: true,
src: ['src/sass/main.scss'], src: ['src/sass/main.scss'],
dest: './', dest: 'www/css/',
ext: '.css' ext: '.css'
}] }]
} }
@ -118,6 +115,7 @@ module.exports = function(grunt) {
angular: { angular: {
src: [ src: [
'bower_components/qrcode-generator/js/qrcode.js', 'bower_components/qrcode-generator/js/qrcode.js',
'bower_components/qrcode-generator/js/qrcode_UTF8.js',
'bower_components/moment/min/moment-with-locales.js', 'bower_components/moment/min/moment-with-locales.js',
'bower_components/angular-moment/angular-moment.js', 'bower_components/angular-moment/angular-moment.js',
'bower_components/ng-lodash/build/ng-lodash.js', 'bower_components/ng-lodash/build/ng-lodash.js',
@ -132,7 +130,7 @@ module.exports = function(grunt) {
'angular-bitauth/angular-bitauth.js', 'angular-bitauth/angular-bitauth.js',
'angular-bitcore-wallet-client/angular-bitcore-wallet-client.js' 'angular-bitcore-wallet-client/angular-bitcore-wallet-client.js'
], ],
dest: 'www/lib/angular.js' dest: 'www/lib/angular-components.js'
}, },
js: { js: {
src: [ src: [
@ -152,11 +150,7 @@ module.exports = function(grunt) {
'node_modules/bezier-easing/dist/bezier-easing.min.js', 'node_modules/bezier-easing/dist/bezier-easing.min.js',
'node_modules/cordova-plugin-qrscanner/dist/cordova-plugin-qrscanner-lib.min.js' 'node_modules/cordova-plugin-qrscanner/dist/cordova-plugin-qrscanner-lib.min.js'
], ],
dest: 'www/js/copay.js' dest: 'www/js/app.js'
},
css: {
src: ['src/sass/*.css', 'src/css/*.css'],
dest: 'www/css/copay.css'
} }
}, },
uglify: { uglify: {
@ -165,8 +159,8 @@ module.exports = function(grunt) {
}, },
prod: { prod: {
files: { files: {
'www/js/copay.js': ['www/js/copay.js'], 'www/js/app.js': ['www/js/app.js'],
'www/lib/angular.js': ['www/lib/angular.js'] 'www/lib/angular-components.js': ['www/lib/angular-components.js']
} }
} }
}, },
@ -228,8 +222,8 @@ module.exports = function(grunt) {
macPlist: { macPlist: {
'CFBundleURLTypes': [ 'CFBundleURLTypes': [
{ {
'CFBundleURLName' : 'URI Handler', 'CFBundleURLName': 'URI Handler',
'CFBundleURLSchemes' : ['bitcoin', '<%= pkg.name %>'] 'CFBundleURLSchemes': ['bitcoin', '<%= pkg.name %>']
} }
] ]
} }

View file

@ -22,7 +22,7 @@
"pushSenderId": "1036948132229", "pushSenderId": "1036948132229",
"description": "Secure Bitcoin Wallet", "description": "Secure Bitcoin Wallet",
"version": "1.2.1", "version": "1.2.1",
"androidVersion": "12100", "androidVersion": "121000",
"_extraCSS": null, "_extraCSS": null,
"_enabledExtensions": { "_enabledExtensions": {
"coinbase": true, "coinbase": true,

View file

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-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="msapplication-tap-highlight" content="no">
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">
<link rel="stylesheet" type="text/css" href="css/copay.css"> <link rel="stylesheet" type="text/css" href="css/main.css">
<title>*USERVISIBLENAME* - *PURPOSELINE*</title> <title>*USERVISIBLENAME* - *PURPOSELINE*</title>
<link rel="shortcut icon" href="img/app/favicon.ico"> <link rel="shortcut icon" href="img/app/favicon.ico">
</head> </head>
@ -25,11 +25,11 @@
</ion-nav-view> </ion-nav-view>
<script src="lib/ionic.bundle.min.js"></script> <script src="lib/ionic.bundle.min.js"></script>
<script src="lib/angular.js"></script> <script src="lib/angular-components.js"></script>
<script type="text/javascript" charset="utf-8" src="cordova.js"></script> <script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script src="js/copay.js"></script> <script src="js/app.js"></script>
</body> </body>
</html> </html>

View file

@ -42,15 +42,15 @@ Copay is a Multisig HD Wallet. Copay app holds the extended private keys for the
- Go to 'Create Wallet', and enter the WS at 'Advanced Options'. Select a new name for the restored wallet. Total and required number of copayers should be set to 1. - Go to 'Create Wallet', and enter the WS at 'Advanced Options'. Select a new name for the restored wallet. Total and required number of copayers should be set to 1.
- Wallet should be recreated and access to funds should be restored. - Wallet should be recreated and access to funds should be restored.
(Using WD) (Using WB)
- Enter the WD at 'Import Wallet' - Enter the WB at 'Import Wallet'
- Wallet should be recreated and access to funds should be restored. - Wallet should be recreated and access to funds should be restored.
### Multisig wallets ### Multisig wallets
Case 1: From both WS and WD, full recovery is possible. Case 1: From both WS and WB, full recovery is possible.
- Enter WS or WD at 'Import wallet' in a new device. - Enter WS or WB at 'Import wallet' in a new device.
- Wallet access should be restored. - Wallet access should be restored.
Case 2: Basic recovery is possible using the device where the wallet is installed, pointing the the new server (Recreate Wallet feature). Case 2: Basic recovery is possible using the device where the wallet is installed, pointing the the new server (Recreate Wallet feature).
@ -66,12 +66,12 @@ Copay is a Multisig HD Wallet. Copay app holds the extended private keys for the
- Ask other copayers to join the wallet using the given invitation code. All copayers need to enter their WS at Join (at -> Advanced Options -> Wallet Seed). - Ask other copayers to join the wallet using the given invitation code. All copayers need to enter their WS at Join (at -> Advanced Options -> Wallet Seed).
- Wallet should be recreated and access to funds should be restored. - Wallet should be recreated and access to funds should be restored.
B) One WD and a quorum of WS of the other members. B) One WB and a quorum of WS of the other members.
- Using the WD, import the wallet. - Using the WB, import the wallet.
- Ask other copayers to import the wallet using their WS. - Ask other copayers to import the wallet using their WS.
- Wallet should be recreated and funds should be accesable - Wallet should be recreated and funds should be accesable
In this case, Copayers will not be able to decrypt the 'notes' field on the new Spend Proposals, because the shared secret stored at the WD is not longer known by other copayers. In this case, Copayers will not be able to decrypt the 'notes' field on the new Spend Proposals, because the shared secret stored at the WB is not longer known by other copayers.
### Hardware wallets ### Hardware wallets

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@ angular.module('copayApp.controllers').controller('addressbookAddController', fu
'email': '' 'email': ''
}; };
$scope.onQrCodeScanned = function(data, addressbookForm) { $scope.onQrCodeScannedAddressBook = function(data, addressbookForm) {
$timeout(function() { $timeout(function() {
var form = addressbookForm; var form = addressbookForm;
if (data && form) { if (data && form) {

View file

@ -1,9 +1,8 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('addressesController', function($scope, $stateParams, $state, $timeout, $ionicHistory, $ionicPopover, $ionicScrollDelegate, configService, popupService, gettextCatalog, ongoingProcess, lodash, profileService, walletService, platformInfo) { angular.module('copayApp.controllers').controller('addressesController', function($scope, $stateParams, $state, $timeout, $ionicHistory, $ionicScrollDelegate, configService, popupService, gettextCatalog, ongoingProcess, lodash, profileService, walletService, platformInfo) {
var UNUSED_ADDRESS_LIMIT = 5; var UNUSED_ADDRESS_LIMIT = 5;
var BALANCE_ADDRESS_LIMIT = 5; var BALANCE_ADDRESS_LIMIT = 5;
var MENU_ITEM_HEIGHT = 55;
var config; var config;
var unitName; var unitName;
var unitToSatoshi; var unitToSatoshi;
@ -100,6 +99,13 @@ angular.module('copayApp.controllers').controller('addressesController', functio
}); });
}; };
$scope.requestSpecificAmount = function() {
$state.go('tabs.receive.amount', {
customAmount: true,
toAddress: $stateParams.toAddress
});
}
$scope.showInformation = function() { $scope.showInformation = function() {
$timeout(function() { $timeout(function() {
$scope.showInfo = !$scope.showInfo; $scope.showInfo = !$scope.showInfo;
@ -114,36 +120,13 @@ angular.module('copayApp.controllers').controller('addressesController', functio
}, 10); }, 10);
}; };
$scope.showMenu = function(allAddresses, $event) { $scope.scan = function() {
var scanObj = {
text: gettextCatalog.getString('Scan addresses for funds'),
action: scan,
};
var sendAddressesObj = {
text: gettextCatalog.getString('Send addresses by email'),
action: sendByEmail,
}
$scope.items = allAddresses ? [sendAddressesObj] : [scanObj];
$scope.height = $scope.items.length * MENU_ITEM_HEIGHT;
$ionicPopover.fromTemplateUrl('views/includes/menu-popover.html', {
scope: $scope
}).then(function(popover) {
$scope.menu = popover;
$scope.menu.show($event);
});
};
var scan = function() {
walletService.startScan($scope.wallet); walletService.startScan($scope.wallet);
$scope.menu.hide();
$ionicHistory.clearHistory(); $ionicHistory.clearHistory();
$state.go('tabs.home'); $state.go('tabs.home');
}; };
var sendByEmail = function() { $scope.sendByEmail = function() {
function formatDate(ts) { function formatDate(ts) {
var dateObj = new Date(ts * 1000); var dateObj = new Date(ts * 1000);
if (!dateObj) { if (!dateObj) {

View file

@ -29,50 +29,6 @@ angular.module('copayApp.controllers').controller('advancedSettingsController',
}; };
}; };
$scope.global = $rootScope;
if (!$scope.global.developmentUtilitiesEnabled) {
$scope.global.developmentUtilitiesEnabled = {
value: false
};
}
$scope.toggledDevelopmentUtils = function() {
if ($scope.global.developmentUtilitiesEnabled.value) {
$log.debug('User enabled development utilities.');
$timeout(function() {
$ionicScrollDelegate.resize();
}, 10);
} else {
$log.debug('User disabled development utilities.');
}
}
$scope.activateFeedbackCard = function() {
$scope.feedbackCardActivating = true;
storageService.getFeedbackInfo(function(error, info) {
var feedbackInfo = JSON.parse(info);
// hardcoding so we can distinguish from normal operation
feedbackInfo.time = 1231006505; // genesis block time
feedbackInfo.version = window.version;
feedbackInfo.sent = false;
storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {
$log.debug('Activated feedback card with: ' + JSON.stringify(feedbackInfo));
$ionicHistory.clearCache();
$timeout(function() {
$scope.feedbackCardActivating = false;
$scope.feedbackCardActivated = true;
$timeout(function() {
$scope.feedbackCardActivated = false;
}, 10000);
}, 500);
});
});
}
$scope.resetActivateFeedbackCard = function() {
$scope.feedbackCardActivated = false;
}
$scope.spendUnconfirmedChange = function() { $scope.spendUnconfirmedChange = function() {
var opts = { var opts = {
wallet: { wallet: {

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('amazonController', angular.module('copayApp.controllers').controller('amazonController',
function($scope, $timeout, $ionicModal, $log, lodash, amazonService, platformInfo, externalLinkService, popupService, gettextCatalog) { function($scope, $timeout, $ionicModal, $log, $ionicScrollDelegate, lodash, amazonService, platformInfo, externalLinkService, popupService, ongoingProcess) {
$scope.network = amazonService.getEnvironment(); $scope.network = amazonService.getEnvironment();
@ -12,7 +12,7 @@ angular.module('copayApp.controllers').controller('amazonController',
var initAmazon = function() { var initAmazon = function() {
amazonService.getPendingGiftCards(function(err, gcds) { amazonService.getPendingGiftCards(function(err, gcds) {
if (err) { if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), err); popupService.showAlert('Error', err);
return; return;
} }
$scope.giftCards = lodash.isEmpty(gcds) ? null : gcds; $scope.giftCards = lodash.isEmpty(gcds) ? null : gcds;
@ -24,7 +24,7 @@ angular.module('copayApp.controllers').controller('amazonController',
claimCode: $scope.cardClaimCode claimCode: $scope.cardClaimCode
}); });
if (lodash.isEmpty(card)) { if (lodash.isEmpty(card)) {
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Card not found')); popupService.showAlert('Error', 'Card not found');
return; return;
} }
$scope.openCardModal(card); $scope.openCardModal(card);
@ -34,18 +34,29 @@ angular.module('copayApp.controllers').controller('amazonController',
}; };
$scope.updatePendingGiftCards = lodash.debounce(function() { $scope.updatePendingGiftCards = lodash.debounce(function() {
ongoingProcess.set('updatingGiftCards', true);
amazonService.getPendingGiftCards(function(err, gcds) { amazonService.getPendingGiftCards(function(err, gcds) {
if (lodash.isEmpty(gcds)) {
$timeout(function() {
ongoingProcess.set('updatingGiftCards', false);
}, 1000);
}
$timeout(function() { $timeout(function() {
$scope.giftCards = gcds; $scope.giftCards = lodash.isEmpty(gcds) ? null : gcds;
$scope.$digest(); $scope.$digest();
}); });
var index = 0;
lodash.forEach(gcds, function(dataFromStorage) { lodash.forEach(gcds, function(dataFromStorage) {
if (++index == Object.keys(gcds).length) {
$timeout(function() {
ongoingProcess.set('updatingGiftCards', false);
}, 1000);
}
if (dataFromStorage.status == 'PENDING') { if (dataFromStorage.status == 'PENDING') {
$log.debug("creating gift card"); $log.debug("creating gift card");
amazonService.createGiftCard(dataFromStorage, function(err, giftCard) { amazonService.createGiftCard(dataFromStorage, function(err, giftCard) {
if (err) { if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), err); popupService.showAlert('Error', err);
return; return;
} }
if (giftCard.status != 'PENDING') { if (giftCard.status != 'PENDING') {
@ -65,13 +76,14 @@ angular.module('copayApp.controllers').controller('amazonController',
$log.debug("Saving new gift card"); $log.debug("Saving new gift card");
amazonService.getPendingGiftCards(function(err, gcds) { amazonService.getPendingGiftCards(function(err, gcds) {
if (err) { if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), err); popupService.showAlert('Error', err);
return; return;
} }
$scope.giftCards = gcds; $scope.giftCards = lodash.isEmpty(gcds) ? null : gcds;
$timeout(function() { $timeout(function() {
$scope.$digest(); $scope.$digest();
}); $ionicScrollDelegate.resize();
}, 10);
}); });
}); });
} else $log.debug("pending gift card not available yet"); } else $log.debug("pending gift card not available yet");
@ -80,7 +92,9 @@ angular.module('copayApp.controllers').controller('amazonController',
}); });
}); });
}, 1000); }, 1000, {
'leading': true
});
$scope.openCardModal = function(card) { $scope.openCardModal = function(card) {
$scope.card = card; $scope.card = card;
@ -92,8 +106,8 @@ angular.module('copayApp.controllers').controller('amazonController',
$scope.amazonCardDetailsModal.show(); $scope.amazonCardDetailsModal.show();
}); });
$scope.$on('UpdateAmazonList', function(event) { $scope.$on('modal.hidden', function() {
initAmazon(); $scope.updatePendingGiftCards();
}); });
}; };

View file

@ -1,13 +1,12 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('amountController', function($scope, $filter, $timeout, $ionicScrollDelegate, $ionicHistory, $ionicPopover, gettextCatalog, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, txFormatService, ongoingProcess, bitpayCardService, popupService, bwcError, payproService, profileService, bitcore, amazonService, glideraService) { angular.module('copayApp.controllers').controller('amountController', function($scope, $filter, $timeout, $ionicScrollDelegate, $ionicHistory, gettextCatalog, platformInfo, lodash, configService, rateService, $stateParams, $window, $state, $log, txFormatService, ongoingProcess, bitpayCardService, popupService, bwcError, payproService, profileService, bitcore, amazonService, glideraService) {
var unitToSatoshi; var unitToSatoshi;
var satToUnit; var satToUnit;
var unitDecimals; var unitDecimals;
var satToBtc; var satToBtc;
var SMALL_FONT_SIZE_LIMIT = 10; var SMALL_FONT_SIZE_LIMIT = 10;
var LENGTH_EXPRESSION_LIMIT = 19; var LENGTH_EXPRESSION_LIMIT = 19;
var MENU_ITEM_HEIGHT = 55;
$scope.$on('$ionicView.leave', function() { $scope.$on('$ionicView.leave', function() {
angular.element($window).off('keydown'); angular.element($window).off('keydown');
@ -21,7 +20,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.glideraAccessToken = data.stateParams.glideraAccessToken; $scope.glideraAccessToken = data.stateParams.glideraAccessToken;
$scope.cardId = data.stateParams.cardId; $scope.cardId = data.stateParams.cardId;
$scope.showMenu = $ionicHistory.backView().stateName == 'tabs.send'; $scope.showMenu = $ionicHistory.backView() && $ionicHistory.backView().stateName == 'tabs.send';
var isWallet = data.stateParams.isWallet || 'false'; var isWallet = data.stateParams.isWallet || 'false';
$scope.isWallet = (isWallet.toString().trim().toLowerCase() == 'true' ? true : false); $scope.isWallet = (isWallet.toString().trim().toLowerCase() == 'true' ? true : false);
$scope.toAddress = data.stateParams.toAddress; $scope.toAddress = data.stateParams.toAddress;
@ -29,6 +28,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.toEmail = data.stateParams.toEmail; $scope.toEmail = data.stateParams.toEmail;
$scope.showAlternativeAmount = !!$scope.cardId || !!$scope.isGiftCard || !!$scope.isGlidera; $scope.showAlternativeAmount = !!$scope.cardId || !!$scope.isGiftCard || !!$scope.isGlidera;
$scope.toColor = data.stateParams.toColor; $scope.toColor = data.stateParams.toColor;
$scope.showSendMax = false;
$scope.customAmount = data.stateParams.customAmount; $scope.customAmount = data.stateParams.customAmount;
@ -71,7 +71,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
var config = configService.getSync().wallet.settings; var config = configService.getSync().wallet.settings;
$scope.unitName = config.unitName; $scope.unitName = config.unitName;
$scope.alternativeIsoCode = config.alternativeIsoCode; $scope.alternativeIsoCode = !!$scope.cardId || !!$scope.isGiftCard ? 'USD' : config.alternativeIsoCode;
$scope.specificAmount = $scope.specificAlternativeAmount = ''; $scope.specificAmount = $scope.specificAlternativeAmount = '';
$scope.isCordova = platformInfo.isCordova; $scope.isCordova = platformInfo.isCordova;
unitToSatoshi = config.unitToSatoshi; unitToSatoshi = config.unitToSatoshi;
@ -93,25 +93,12 @@ angular.module('copayApp.controllers').controller('amountController', function($
}, 10); }, 10);
}); });
$scope.showSendMaxMenu = function($event) { $scope.showSendMaxMenu = function() {
var sendMaxObj = { $scope.showSendMax = true;
text: gettextCatalog.getString('Send max amount'),
action: setSendMax,
};
$scope.items = [sendMaxObj];
$scope.height = $scope.items.length * MENU_ITEM_HEIGHT;
$ionicPopover.fromTemplateUrl('views/includes/menu-popover.html', {
scope: $scope
}).then(function(popover) {
$scope.menu = popover;
$scope.menu.show($event);
});
}; };
function setSendMax() { $scope.sendMax = function() {
$scope.menu.hide(); $scope.showSendMax = false;
$state.transitionTo('tabs.send.confirm', { $state.transitionTo('tabs.send.confirm', {
isWallet: $scope.isWallet, isWallet: $scope.isWallet,
toAmount: null, toAmount: null,
@ -205,11 +192,11 @@ angular.module('copayApp.controllers').controller('amountController', function($
}; };
function fromFiat(val) { function fromFiat(val) {
return parseFloat((rateService.fromFiat(val, $scope.alternativeIsoCode) * satToUnit).toFixed(unitDecimals), 10); return parseFloat((rateService.fromFiat(val, $scope.alternativeIsoCode) * satToUnit).toFixed(unitDecimals));
}; };
function toFiat(val) { function toFiat(val) {
return parseFloat((rateService.toFiat(val * unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2), 10); return parseFloat((rateService.toFiat(val * unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2));
}; };
function evaluate(val) { function evaluate(val) {
@ -283,6 +270,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
} }
var stateParams = { var stateParams = {
cardId: $scope.cardId, cardId: $scope.cardId,
cardAmountUSD: amountUSD,
toName: $scope.toName, toName: $scope.toName,
toAmount: payProDetails.amount, toAmount: payProDetails.amount,
toAddress: payProDetails.toAddress, toAddress: payProDetails.toAddress,
@ -303,7 +291,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
try { try {
uuid = profileService.getWallets({ uuid = profileService.getWallets({
onlyComplete: true, onlyComplete: true,
network: 'livenet', network: amazonService.getEnvironment(),
})[0].id; })[0].id;
} catch (err) { } catch (err) {
ongoingProcess.set('Preparing transaction...', false); ongoingProcess.set('Preparing transaction...', false);

View file

@ -31,6 +31,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
var isWallet = data.stateParams.isWallet || 'false'; var isWallet = data.stateParams.isWallet || 'false';
$scope.isWallet = (isWallet.toString().trim().toLowerCase() == 'true' ? true : false); $scope.isWallet = (isWallet.toString().trim().toLowerCase() == 'true' ? true : false);
$scope.cardId = data.stateParams.cardId; $scope.cardId = data.stateParams.cardId;
$scope.cardAmountUSD = data.stateParams.cardAmountUSD;
$scope.toAddress = data.stateParams.toAddress; $scope.toAddress = data.stateParams.toAddress;
$scope.toName = data.stateParams.toName; $scope.toName = data.stateParams.toName;
$scope.toEmail = data.stateParams.toEmail; $scope.toEmail = data.stateParams.toEmail;
@ -62,9 +63,8 @@ angular.module('copayApp.controllers').controller('confirmController', function(
if (!$scope.wallets || !$scope.wallets.length) { if (!$scope.wallets || !$scope.wallets.length) {
$scope.noMatchingWallet = true; $scope.noMatchingWallet = true;
if ($scope.paypro) { displayValues();
displayValues(); $log.warn('No ' + $scope.network + ' wallets to make the payment');
}
$timeout(function() { $timeout(function() {
$scope.$apply(); $scope.$apply();
}); });
@ -106,6 +106,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
} else initConfirm(); } else initConfirm();
} else { } else {
if (!enoughFunds) $scope.insufficientFunds = true; if (!enoughFunds) $scope.insufficientFunds = true;
displayValues();
$log.warn('No wallet available to make the payment'); $log.warn('No wallet available to make the payment');
} }
$timeout(function() { $timeout(function() {
@ -132,9 +133,15 @@ angular.module('copayApp.controllers').controller('confirmController', function(
$scope.amountStr = txFormatService.formatAmountStr(toAmount); $scope.amountStr = txFormatService.formatAmountStr(toAmount);
$scope.displayAmount = getDisplayAmount($scope.amountStr); $scope.displayAmount = getDisplayAmount($scope.amountStr);
$scope.displayUnit = getDisplayUnit($scope.amountStr); $scope.displayUnit = getDisplayUnit($scope.amountStr);
txFormatService.formatAlternativeStr(toAmount, function(v) { if ($scope.cardAmountUSD) {
$scope.alternativeAmountStr = v; $scope.alternativeAmountStr = $filter('formatFiatAmount')($scope.cardAmountUSD) + ' USD';
}); } else if ($scope.giftCardAmountUSD) {
$scope.alternativeAmountStr = $filter('formatFiatAmount')($scope.giftCardAmountUSD) + ' USD';
} else {
txFormatService.formatAlternativeStr(toAmount, function(v) {
$scope.alternativeAmountStr = v;
});
}
if ($scope.isGlidera == 'buy') $scope.getBuyPrice(); if ($scope.isGlidera == 'buy') $scope.getBuyPrice();
if ($scope.isGlidera == 'sell') $scope.getSellPrice(); if ($scope.isGlidera == 'sell') $scope.getSellPrice();
}; };
@ -428,6 +435,10 @@ angular.module('copayApp.controllers').controller('confirmController', function(
}); });
}; };
$scope.cancel = function() {
$scope.payproModal.hide();
};
$scope.approve = function(onSendStatusChange) { $scope.approve = function(onSendStatusChange) {
var wallet = $scope.wallet; var wallet = $scope.wallet;
@ -783,6 +794,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
invoiceUrl: $scope.paypro.url, invoiceUrl: $scope.paypro.url,
invoiceTime: giftCardInvoiceTime invoiceTime: giftCardInvoiceTime
}; };
ongoingProcess.set('creatingGiftCard', true);
debounceCreate(count, dataSrc, onSendStatusChange); debounceCreate(count, dataSrc, onSendStatusChange);
} }
}, onSendStatusChange); }, onSendStatusChange);
@ -795,7 +807,6 @@ angular.module('copayApp.controllers').controller('confirmController', function(
}); });
var debounceCreateGiftCard = function(count, dataSrc, onSendStatusChange) { var debounceCreateGiftCard = function(count, dataSrc, onSendStatusChange) {
amazonService.createGiftCard(dataSrc, function(err, giftCard) { amazonService.createGiftCard(dataSrc, function(err, giftCard) {
$log.debug("creating gift card " + count); $log.debug("creating gift card " + count);
if (err) { if (err) {
@ -830,6 +841,7 @@ angular.module('copayApp.controllers').controller('confirmController', function(
} }
amazonService.savePendingGiftCard(newData, null, function(err) { amazonService.savePendingGiftCard(newData, null, function(err) {
ongoingProcess.set('creatingGiftCard', false);
$log.debug("Saving new gift card with status: " + newData.status); $log.debug("Saving new gift card with status: " + newData.status);
$scope.amazonGiftCard = newData; $scope.amazonGiftCard = newData;
}); });

View file

@ -1,10 +1,10 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('copayersController', angular.module('copayApp.controllers').controller('copayersController',
function($scope, $log, $timeout, $stateParams, $state, $rootScope, $ionicHistory, $window, lodash, profileService, walletService, popupService, platformInfo, gettextCatalog, ongoingProcess) { function($scope, $log, $timeout, $stateParams, $state, $rootScope, $ionicHistory, appConfigService, lodash, profileService, walletService, popupService, platformInfo, gettextCatalog, ongoingProcess) {
var appName = $window.appConfig.userVisibleName; var appName = appConfigService.userVisibleName;
var appUrl = $window.appConfig.url; var appUrl = appConfigService.url;
$scope.isCordova = platformInfo.isCordova; $scope.isCordova = platformInfo.isCordova;
$scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.$on("$ionicView.beforeEnter", function(event, data) {

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('createController', angular.module('copayApp.controllers').controller('createController',
function($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, platformInfo, derivationPathHelper, ongoingProcess, walletService, storageService, popupService, $window) { function($scope, $rootScope, $timeout, $log, lodash, $state, $ionicScrollDelegate, $ionicHistory, profileService, configService, gettextCatalog, ledger, trezor, platformInfo, derivationPathHelper, ongoingProcess, walletService, storageService, popupService, appConfigService) {
var isChromeApp = platformInfo.isChromeApp; var isChromeApp = platformInfo.isChromeApp;
var isCordova = platformInfo.isCordova; var isCordova = platformInfo.isCordova;
@ -80,7 +80,7 @@ angular.module('copayApp.controllers').controller('createController',
*/ */
if ($window.appConfig.name == 'copay') { if (appConfigService.name == 'copay') {
if (n > 1 && isChromeApp) { if (n > 1 && isChromeApp) {
seedOptions.push({ seedOptions.push({
id: 'ledger', id: 'ledger',

View file

@ -18,8 +18,7 @@ angular.module('copayApp.controllers').controller('customAmountController', func
$scope.finish = function() { $scope.finish = function() {
$ionicHistory.nextViewOptions({ $ionicHistory.nextViewOptions({
disableAnimate: false, disableAnimate: false
historyRoot: true
}); });
$ionicHistory.goBack(-2); $ionicHistory.goBack(-2);
}; };

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('exportController', angular.module('copayApp.controllers').controller('exportController',
function($scope, $timeout, $log, $ionicHistory, $ionicScrollDelegate, backupService, walletService, storageService, profileService, platformInfo, gettextCatalog, $state, $stateParams, popupService, $window) { function($scope, $timeout, $log, $ionicHistory, $ionicScrollDelegate, backupService, walletService, storageService, profileService, platformInfo, gettextCatalog, $state, $stateParams, popupService, appConfigService) {
var wallet = profileService.getWallet($stateParams.walletId); var wallet = profileService.getWallet($stateParams.walletId);
$scope.showAdvChange = function() { $scope.showAdvChange = function() {
@ -191,7 +191,7 @@ angular.module('copayApp.controllers').controller('exportController',
if ($scope.formData.noSignEnabled) if ($scope.formData.noSignEnabled)
name = name + '(No Private Key)'; name = name + '(No Private Key)';
var subject = $window.appConfig.nameCase + ' Wallet Backup: ' + name; var subject = appConfigService.nameCase + ' Wallet Backup: ' + name;
var body = 'Here is the encrypted backup of the wallet ' + name + ': \n\n' + ew + '\n\n To import this backup, copy all text between {...}, including the symbols {}'; var body = 'Here is the encrypted backup of the wallet ' + name + ': \n\n' + ew + '\n\n To import this backup, copy all text between {...}, including the symbols {}';
window.plugins.socialsharing.shareViaEmail( window.plugins.socialsharing.shareViaEmail(
body, body,

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('sendController', function($scope, $state, $log, $timeout, $stateParams, $ionicNavBarDelegate, $ionicHistory, $ionicConfig, $window, gettextCatalog, popupService, configService, lodash, feedbackService, ongoingProcess) { angular.module('copayApp.controllers').controller('sendController', function($scope, $state, $log, $timeout, $stateParams, $ionicNavBarDelegate, $ionicHistory, $ionicConfig, $window, gettextCatalog, popupService, configService, lodash, feedbackService, ongoingProcess, platformInfo) {
$scope.sendFeedback = function(feedback, goHome) { $scope.sendFeedback = function(feedback, goHome) {
@ -42,6 +42,7 @@ angular.module('copayApp.controllers').controller('sendController', function($sc
}; };
$scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isCordova = platformInfo.isCordova;
$scope.score = (data.stateParams && data.stateParams.score) ? parseInt(data.stateParams.score) : null; $scope.score = (data.stateParams && data.stateParams.score) ? parseInt(data.stateParams.score) : null;
$scope.feedback = {}; $scope.feedback = {};

View file

@ -1,7 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('headController', angular.module('copayApp.controllers').controller('headController', function($scope, appConfigService, $log) {
function($scope, $window, $log) { $scope.appConfig = appConfigService;
$scope.appConfig = $window.appConfig; $log.info('Running head controller:' + appConfigService.nameCase)
$log.info('Running head controller:' + $window.appConfig.nameCase) });
});

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('importController', angular.module('copayApp.controllers').controller('importController',
function($scope, $timeout, $log, $state, $stateParams, $ionicHistory, $ionicScrollDelegate, profileService, configService, sjcl, ledger, trezor, derivationPathHelper, platformInfo, bwcService, ongoingProcess, walletService, popupService, gettextCatalog, $window) { function($scope, $timeout, $log, $state, $stateParams, $ionicHistory, $ionicScrollDelegate, profileService, configService, sjcl, ledger, trezor, derivationPathHelper, platformInfo, bwcService, ongoingProcess, walletService, popupService, gettextCatalog, appConfigService) {
var isChromeApp = platformInfo.isChromeApp; var isChromeApp = platformInfo.isChromeApp;
var isDevel = platformInfo.isDevel; var isDevel = platformInfo.isDevel;
@ -17,7 +17,7 @@ angular.module('copayApp.controllers').controller('importController',
$scope.formData.derivationPath = derivationPathHelper.default; $scope.formData.derivationPath = derivationPathHelper.default;
$scope.formData.account = 1; $scope.formData.account = 1;
$scope.importErr = false; $scope.importErr = false;
$scope.showHardwareWallet = $window.appConfig.name == 'copay'; $scope.showHardwareWallet = appConfigService.name == 'copay';
if ($stateParams.code) if ($stateParams.code)
$scope.processWalletInfo($stateParams.code); $scope.processWalletInfo($stateParams.code);
@ -238,6 +238,7 @@ angular.module('copayApp.controllers').controller('importController',
if (!words) { if (!words) {
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Please enter the recovery phrase')); popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Please enter the recovery phrase'));
return;
} else if (words.indexOf('xprv') == 0 || words.indexOf('tprv') == 0) { } else if (words.indexOf('xprv') == 0 || words.indexOf('tprv') == 0) {
return _importExtendedPrivateKey(words, opts); return _importExtendedPrivateKey(words, opts);
} else if (words.indexOf('xpub') == 0 || words.indexOf('tpuv') == 0) { } else if (words.indexOf('xpub') == 0 || words.indexOf('tpuv') == 0) {

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('joinController', angular.module('copayApp.controllers').controller('joinController',
function($scope, $rootScope, $timeout, $state, $ionicHistory, $ionicScrollDelegate, profileService, configService, storageService, applicationService, gettextCatalog, lodash, ledger, trezor, platformInfo, derivationPathHelper, ongoingProcess, walletService, $log, $stateParams, popupService, $window) { function($scope, $rootScope, $timeout, $state, $ionicHistory, $ionicScrollDelegate, profileService, configService, storageService, applicationService, gettextCatalog, lodash, ledger, trezor, platformInfo, derivationPathHelper, ongoingProcess, walletService, $log, $stateParams, popupService, appConfigService) {
var isChromeApp = platformInfo.isChromeApp; var isChromeApp = platformInfo.isChromeApp;
var isDevel = platformInfo.isDevel; var isDevel = platformInfo.isDevel;
@ -33,7 +33,7 @@ angular.module('copayApp.controllers').controller('joinController',
} }
}; };
this.onQrCodeScanned = function(data) { this.onQrCodeScannedJoin = function(data) {
$scope.secret = data; $scope.secret = data;
if ($scope.joinForm) { if ($scope.joinForm) {
$scope.joinForm.secret.$setViewValue(data); $scope.joinForm.secret.$setViewValue(data);
@ -44,7 +44,7 @@ angular.module('copayApp.controllers').controller('joinController',
if ($stateParams.url) { if ($stateParams.url) {
var data = $stateParams.url; var data = $stateParams.url;
data = data.replace('copay:', ''); data = data.replace('copay:', '');
this.onQrCodeScanned(data); this.onQrCodeScannedJoin(data);
} }
var updateSeedSourceSelect = function() { var updateSeedSourceSelect = function() {
@ -63,7 +63,7 @@ angular.module('copayApp.controllers').controller('joinController',
*/ */
if ($window.appConfig.name == 'copay') { if (appConfigService.name == 'copay') {
if (isChromeApp) { if (isChromeApp) {
self.seedOptions.push({ self.seedOptions.push({
id: 'ledger', id: 'ledger',

View file

@ -1,18 +1,22 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('amazonCardDetailsController', function($scope, $log, $timeout, bwcError, amazonService, lodash, ongoingProcess, popupService, gettextCatalog, externalLinkService) { angular.module('copayApp.controllers').controller('amazonCardDetailsController', function($scope, $log, $timeout, $ionicScrollDelegate, bwcError, amazonService, lodash, ongoingProcess, popupService, externalLinkService) {
$scope.cancelGiftCard = function() { $scope.cancelGiftCard = function() {
ongoingProcess.set('Canceling gift card...', true); ongoingProcess.set('cancelingGiftCard', true);
amazonService.cancelGiftCard($scope.card, function(err, data) { amazonService.cancelGiftCard($scope.card, function(err, data) {
ongoingProcess.set('Canceling gift card...', false); ongoingProcess.set('cancelingGiftCard', false);
if (err) { if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err)); popupService.showAlert('Error', bwcError.msg(err));
return; return;
} }
$scope.card.cardStatus = data.cardStatus; $scope.card.cardStatus = data.cardStatus;
$timeout(function() {
$ionicScrollDelegate.resize();
$ionicScrollDelegate.scrollTop();
}, 10);
amazonService.savePendingGiftCard($scope.card, null, function(err) { amazonService.savePendingGiftCard($scope.card, null, function(err) {
$scope.$emit('UpdateAmazonList'); $scope.refreshGiftCard();
}); });
}); });
}; };
@ -21,23 +25,34 @@ angular.module('copayApp.controllers').controller('amazonCardDetailsController',
amazonService.savePendingGiftCard($scope.card, { amazonService.savePendingGiftCard($scope.card, {
remove: true remove: true
}, function(err) { }, function(err) {
$scope.$emit('UpdateAmazonList');
$scope.cancel(); $scope.cancel();
}); });
}; };
$scope.refreshGiftCard = function() { $scope.refreshGiftCard = function() {
ongoingProcess.set('updatingGiftCard', true);
amazonService.getPendingGiftCards(function(err, gcds) { amazonService.getPendingGiftCards(function(err, gcds) {
if (lodash.isEmpty(gcds)) {
$timeout(function() {
ongoingProcess.set('updatingGiftCard', false);
}, 1000);
}
if (err) { if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), err); popupService.showAlert('Error', err);
return; return;
} }
var index = 0;
lodash.forEach(gcds, function(dataFromStorage) { lodash.forEach(gcds, function(dataFromStorage) {
if (++index == Object.keys(gcds).length) {
$timeout(function() {
ongoingProcess.set('updatingGiftCard', false);
}, 1000);
}
if (dataFromStorage.status == 'PENDING' && dataFromStorage.invoiceId == $scope.card.invoiceId) { if (dataFromStorage.status == 'PENDING' && dataFromStorage.invoiceId == $scope.card.invoiceId) {
$log.debug("creating gift card"); $log.debug("creating gift card");
amazonService.createGiftCard(dataFromStorage, function(err, giftCard) { amazonService.createGiftCard(dataFromStorage, function(err, giftCard) {
if (err) { if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err)); popupService.showAlert('Error', bwcError.msg(err));
return; return;
} }
if (!lodash.isEmpty(giftCard)) { if (!lodash.isEmpty(giftCard)) {
@ -46,7 +61,6 @@ angular.module('copayApp.controllers').controller('amazonCardDetailsController',
amazonService.savePendingGiftCard(newData, null, function(err) { amazonService.savePendingGiftCard(newData, null, function(err) {
$log.debug("Saving new gift card"); $log.debug("Saving new gift card");
$scope.card = newData; $scope.card = newData;
$scope.$emit('UpdateAmazonList');
$timeout(function() { $timeout(function() {
$scope.$digest(); $scope.$digest();
}); });

View file

@ -1,9 +0,0 @@
'use strict';
angular.module('copayApp.controllers').controller('payproController', function($scope) {
var self = $scope.self;
$scope.cancel = function() {
$scope.payproModal.hide();
};
});

View file

@ -7,15 +7,15 @@ angular.module('copayApp.controllers').controller('backupRequestController', fun
$scope.openPopup = function() { $scope.openPopup = function() {
var title = gettextCatalog.getString('Without a backup, you could lose money.'); var title = gettextCatalog.getString('Watch out!');
var message = gettextCatalog.getString('If this device is replaced or this app is deleted, neither you nor BitPay can recover your funds without a backup.'); var message = gettextCatalog.getString('If this device is replaced or this app is deleted, neither you nor BitPay can recover your funds without a backup.');
var okText = gettextCatalog.getString('I understand'); var okText = gettextCatalog.getString('I understand');
var cancelText = gettextCatalog.getString('Go back'); var cancelText = gettextCatalog.getString('Go back');
popupService.showConfirm(title, message, okText, cancelText, function(val) { popupService.showConfirm(title, message, okText, cancelText, function(val) {
if (val) { if (val) {
var title = gettextCatalog.getString('Are you sure you want to skip the backup?'); var title = gettextCatalog.getString('Are you sure you want to skip it?');
var message = gettextCatalog.getString('You can create a backup later from your wallet settings.'); var message = gettextCatalog.getString('You can create a backup later from your wallet settings.');
var okText = gettextCatalog.getString('Yes, skip backup'); var okText = gettextCatalog.getString('Yes, skip');
var cancelText = gettextCatalog.getString('Go back'); var cancelText = gettextCatalog.getString('Go back');
popupService.showConfirm(title, message, okText, cancelText, function(val) { popupService.showConfirm(title, message, okText, cancelText, function(val) {
if (val) { if (val) {

View file

@ -5,7 +5,8 @@ angular.module('copayApp.controllers').controller('disclaimerController', functi
$scope.$on("$ionicView.afterEnter", function() { $scope.$on("$ionicView.afterEnter", function() {
startupService.ready(); startupService.ready();
}); });
$scope.init = function() {
$scope.$on("$ionicView.beforeEnter", function() {
$scope.lang = uxLanguage.currentLanguage; $scope.lang = uxLanguage.currentLanguage;
$scope.terms = {}; $scope.terms = {};
$scope.accepted = {}; $scope.accepted = {};
@ -13,10 +14,7 @@ angular.module('copayApp.controllers').controller('disclaimerController', functi
$scope.backedUp = $stateParams.backedUp; $scope.backedUp = $stateParams.backedUp;
$scope.resume = $stateParams.resume; $scope.resume = $stateParams.resume;
$scope.shrinkView = false; $scope.shrinkView = false;
$timeout(function() { });
$scope.$apply();
}, 1);
};
$scope.confirm = function() { $scope.confirm = function() {
profileService.setDisclaimerAccepted(function(err) { profileService.setDisclaimerAccepted(function(err) {

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('termsController', function($scope, $log, $state, $window, uxLanguage, profileService, externalLinkService, gettextCatalog) { angular.module('copayApp.controllers').controller('termsController', function($scope, $log, $state, appConfigService, uxLanguage, profileService, externalLinkService, gettextCatalog) {
$scope.lang = uxLanguage.currentLanguage; $scope.lang = uxLanguage.currentLanguage;
$scope.confirm = function() { $scope.confirm = function() {
@ -15,10 +15,10 @@ angular.module('copayApp.controllers').controller('termsController', function($s
}; };
$scope.openExternalLink = function() { $scope.openExternalLink = function() {
var url = $window.appConfig.disclaimerUrl; var url = appConfigService.disclaimerUrl;
var optIn = true; var optIn = true;
var title = gettextCatalog.getString('View Terms of Service'); var title = gettextCatalog.getString('View Terms of Service');
var message = gettextCatalog.getString('The official English Terms of Service are available on the BitPay website. Would you like to view them?'); var message = gettextCatalog.getString('The official English Terms of Service are available on the BitPay website.');
var okText = gettextCatalog.getString('Open Website'); var okText = gettextCatalog.getString('Open Website');
var cancelText = gettextCatalog.getString('Go Back'); var cancelText = gettextCatalog.getString('Go Back');
externalLinkService.open(url, optIn, title, message, okText, cancelText); externalLinkService.open(url, optIn, title, message, okText, cancelText);

View file

@ -8,13 +8,6 @@ angular.module('copayApp.controllers').controller('welcomeController', function(
startupService.ready(); startupService.ready();
}); });
$scope.goImport = function(code) {
$state.go('onboarding.import', {
fromOnboarding: true,
code: code
});
};
$scope.createProfile = function() { $scope.createProfile = function() {
$log.debug('Creating profile'); $log.debug('Creating profile');
profileService.createProfile(function(err) { profileService.createProfile(function(err) {

View file

@ -1,14 +1,14 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('preferencesAbout', angular.module('copayApp.controllers').controller('preferencesAbout',
function($scope, $window, gettextCatalog, externalLinkService) { function($scope, $window, appConfigService, gettextCatalog, externalLinkService) {
$scope.title = gettextCatalog.getString('About') + ' ' + $window.appConfig.nameCase; $scope.title = gettextCatalog.getString('About') + ' ' + appConfigService.nameCase;
$scope.version = $window.version; $scope.version = $window.version;
$scope.commitHash = $window.commitHash; $scope.commitHash = $window.commitHash;
$scope.openExternalLink = function() { $scope.openExternalLink = function() {
var url = 'https://github.com/bitpay/' + $window.appConfig.gitHubRepoName + '/tree/' + $window.commitHash + ''; var url = 'https://github.com/bitpay/' + appConfigService.gitHubRepoName + '/tree/' + $window.commitHash + '';
var optIn = true; var optIn = true;
var title = gettextCatalog.getString('Open GitHub Project'); var title = gettextCatalog.getString('Open GitHub Project');
var message = gettextCatalog.getString('You can see the latest developments and contribute to this open source app by visiting our project on GitHub.'); var message = gettextCatalog.getString('You can see the latest developments and contribute to this open source app by visiting our project on GitHub.');

View file

@ -1,14 +1,14 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('preferencesBwsUrlController', angular.module('copayApp.controllers').controller('preferencesBwsUrlController',
function($scope, $log, $stateParams, configService, applicationService, profileService, storageService, $window) { function($scope, $log, $stateParams, configService, applicationService, profileService, storageService, appConfigService) {
$scope.success = null; $scope.success = null;
var wallet = profileService.getWallet($stateParams.walletId); var wallet = profileService.getWallet($stateParams.walletId);
var walletId = wallet.credentials.walletId; var walletId = wallet.credentials.walletId;
var defaults = configService.getDefaults(); var defaults = configService.getDefaults();
var config = configService.getSync(); var config = configService.getSync();
$scope.appName = $window.appConfig.nameCase; $scope.appName = appConfigService.nameCase;
$scope.bwsurl = { $scope.bwsurl = {
value: (config.bwsFor && config.bwsFor[walletId]) || defaults.bws.url value: (config.bwsFor && config.bwsFor[walletId]) || defaults.bws.url
}; };

View file

@ -1,11 +1,11 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('preferencesHistory', angular.module('copayApp.controllers').controller('preferencesHistory',
function($scope, $log, $stateParams, $timeout, $state, $ionicHistory, storageService, platformInfo, profileService, lodash, $window) { function($scope, $log, $stateParams, $timeout, $state, $ionicHistory, storageService, platformInfo, profileService, lodash, appConfigService) {
$scope.wallet = profileService.getWallet($stateParams.walletId); $scope.wallet = profileService.getWallet($stateParams.walletId);
$scope.csvReady = false; $scope.csvReady = false;
$scope.isCordova = platformInfo.isCordova; $scope.isCordova = platformInfo.isCordova;
$scope.appName = $window.appConfig.nameCase; $scope.appName = appConfigService.nameCase;
$scope.csvHistory = function(cb) { $scope.csvHistory = function(cb) {
var allTxs = []; var allTxs = [];

View file

@ -1,9 +1,9 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('preferencesNotificationsController', function($scope, $log, $timeout, $window, lodash, configService, platformInfo, pushNotificationsService, profileService, emailService) { angular.module('copayApp.controllers').controller('preferencesNotificationsController', function($scope, $log, $timeout, appConfigService, lodash, configService, platformInfo, pushNotificationsService, profileService, emailService) {
var updateConfig = function() { var updateConfig = function() {
var config = configService.getSync(); var config = configService.getSync();
$scope.appName = $window.appConfig.nameCase; $scope.appName = appConfigService.nameCase;
$scope.PNEnabledByUser = true; $scope.PNEnabledByUser = true;
$scope.usePushNotifications = platformInfo.isCordova && !platformInfo.isWP; $scope.usePushNotifications = platformInfo.isCordova && !platformInfo.isWP;
$scope.isIOSApp = platformInfo.isIOS && platformInfo.isCordova; $scope.isIOSApp = platformInfo.isIOS && platformInfo.isCordova;

View file

@ -1,14 +1,14 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('tabHomeController', angular.module('copayApp.controllers').controller('tabHomeController',
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, $window, bitpayCardService, startupService, addressbookService, feedbackService) { function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, bitpayCardService, startupService, addressbookService, feedbackService) {
var wallet; var wallet;
var listeners = []; var listeners = [];
var notifications = []; var notifications = [];
$scope.externalServices = {}; $scope.externalServices = {};
$scope.openTxpModal = txpModalService.open; $scope.openTxpModal = txpModalService.open;
$scope.version = $window.version; $scope.version = $window.version;
$scope.name = $window.appConfig.nameCase; $scope.name = appConfigService.nameCase;
$scope.homeTip = $stateParams.fromOnboarding; $scope.homeTip = $stateParams.fromOnboarding;
$scope.isCordova = platformInfo.isCordova; $scope.isCordova = platformInfo.isCordova;
$scope.isAndroid = platformInfo.isAndroid; $scope.isAndroid = platformInfo.isAndroid;
@ -43,7 +43,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
} else { } else {
var feedbackInfo = JSON.parse(info); var feedbackInfo = JSON.parse(info);
//Check if current version is greater than saved version //Check if current version is greater than saved version
var currentVersion = window.version; var currentVersion = $scope.version;
var savedVersion = feedbackInfo.version; var savedVersion = feedbackInfo.version;
var isVersionUpdated = feedbackService.isVersionUpdated(currentVersion, savedVersion); var isVersionUpdated = feedbackService.isVersionUpdated(currentVersion, savedVersion);
if (!isVersionUpdated) { if (!isVersionUpdated) {
@ -62,7 +62,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
function initFeedBackInfo() { function initFeedBackInfo() {
var feedbackInfo = {}; var feedbackInfo = {};
feedbackInfo.time = moment().unix(); feedbackInfo.time = moment().unix();
feedbackInfo.version = window.version; feedbackInfo.version = $scope.version;
feedbackInfo.sent = false; feedbackInfo.sent = false;
storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() { storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {
$scope.showRateCard.value = false; $scope.showRateCard.value = false;

View file

@ -3,7 +3,6 @@
angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError) { angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError) {
var listeners = []; var listeners = [];
var MENU_ITEM_HEIGHT = 55;
$scope.isCordova = platformInfo.isCordova; $scope.isCordova = platformInfo.isCordova;
$scope.isNW = platformInfo.isNW; $scope.isNW = platformInfo.isNW;
$scope.walletAddrs = {}; $scope.walletAddrs = {};
@ -50,8 +49,9 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
}; };
$scope.showAddresses = function() { $scope.showAddresses = function() {
$state.transitionTo('tabs.receive.addresses', { $state.go('tabs.receive.addresses', {
walletId: $scope.wallet.credentials.walletId walletId: $scope.wallet.credentials.walletId,
toAddress: $scope.addr
}); });
}; };
@ -140,31 +140,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
}); });
}; };
var goRequestAmount = function() {
$scope.menu.hide();
$state.go('tabs.receive.amount', {
customAmount: true,
toAddress: $scope.addr
});
}
$scope.showMenu = function(allAddresses, $event) {
var requestAmountObj = {
text: gettextCatalog.getString('Request Specific amount'),
action: goRequestAmount,
};
$scope.items = [requestAmountObj];
$scope.height = $scope.items.length * MENU_ITEM_HEIGHT;
$ionicPopover.fromTemplateUrl('views/includes/menu-popover.html', {
scope: $scope
}).then(function(popover) {
$scope.menu = popover;
$scope.menu.show($event);
});
};
$scope.$on("$ionicView.beforeEnter", function(event, data) { $scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.wallets = profileService.getWallets(); $scope.wallets = profileService.getWallets();

View file

@ -133,13 +133,9 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
lodash.each(wallets, function(w) { lodash.each(wallets, function(w) {
walletService.getStatus(w, {}, function(err, status) { walletService.getStatus(w, {}, function(err, status) {
++index; ++index;
if (index == wallets.length) $scope.checkingBalance = false; if (err && !status) {
if (err || !status) {
$log.error(err); $log.error(err);
return; } else if (status.availableBalanceSat > 0) {
}
if (status.availableBalanceSat > 0) {
$scope.hasFunds = true; $scope.hasFunds = true;
$rootScope.everHasFunds = true; $rootScope.everHasFunds = true;
} }
@ -148,6 +144,7 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
if ($scope.hasFunds != true) { if ($scope.hasFunds != true) {
$ionicScrollDelegate.freezeScroll(true); $ionicScrollDelegate.freezeScroll(true);
} }
$scope.checkingBalance = false;
$timeout(function() { $timeout(function() {
$scope.$apply(); $scope.$apply();
}); });

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('tabSettingsController', function($scope, $window, $ionicModal, $log, lodash, uxLanguage, platformInfo, profileService, feeService, configService, externalLinkService, bitpayCardService, storageService, glideraService, gettextCatalog) { angular.module('copayApp.controllers').controller('tabSettingsController', function($scope, appConfigService, $ionicModal, $log, lodash, uxLanguage, platformInfo, profileService, feeService, configService, externalLinkService, bitpayCardService, storageService, glideraService, gettextCatalog) {
var updateConfig = function() { var updateConfig = function() {
var isCordova = platformInfo.isCordova; var isCordova = platformInfo.isCordova;
@ -10,13 +10,13 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
$scope.usePushNotifications = isCordova && !isWP; $scope.usePushNotifications = isCordova && !isWP;
$scope.isCordova = isCordova; $scope.isCordova = isCordova;
$scope.appName = $window.appConfig.nameCase; $scope.appName = appConfigService.nameCase;
$scope.currentLanguageName = uxLanguage.getCurrentLanguageName(); $scope.currentLanguageName = uxLanguage.getCurrentLanguageName();
$scope.feeOpts = feeService.feeOpts; $scope.feeOpts = feeService.feeOpts;
$scope.currentFeeLevel = feeService.getCurrentFeeLevel(); $scope.currentFeeLevel = feeService.getCurrentFeeLevel();
$scope.wallets = profileService.getWallets(); $scope.wallets = profileService.getWallets();
configService.whenAvailable(function(config) { configService.whenAvailable(function(config) {
$scope.unitName = config.wallet.settings.unitName; $scope.unitName = config.wallet.settings.unitName;
$scope.selectedAlternative = { $scope.selectedAlternative = {
@ -33,7 +33,7 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
if (!lodash.isEmpty(data)) { if (!lodash.isEmpty(data)) {
$scope.bitpayCards = true; $scope.bitpayCards = true;
} }
}); });
} }
if ($scope.glideraEnabled) { if ($scope.glideraEnabled) {
@ -50,7 +50,7 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
var url = 'https://help.bitpay.com/bitpay-app'; var url = 'https://help.bitpay.com/bitpay-app';
var optIn = true; var optIn = true;
var title = gettextCatalog.getString('BitPay Help Center'); var title = gettextCatalog.getString('BitPay Help Center');
var message = gettextCatalog.getString('Help and support information is available at the BitPay Help Center website. Would you like to go there now?'); var message = gettextCatalog.getString('Help and support information is available at the BitPay Help Center website.');
var okText = gettextCatalog.getString('Open Help Center'); var okText = gettextCatalog.getString('Open Help Center');
var cancelText = gettextCatalog.getString('Go Back'); var cancelText = gettextCatalog.getString('Go Back');
externalLinkService.open(url, optIn, title, message, okText, cancelText); externalLinkService.open(url, optIn, title, message, okText, cancelText);

View file

@ -1,9 +1,9 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('termOfUseController', angular.module('copayApp.controllers').controller('termOfUseController',
function($scope, $window, uxLanguage, externalLinkService) { function($scope, appConfigService, uxLanguage, externalLinkService) {
$scope.lang = uxLanguage.currentLanguage; $scope.lang = uxLanguage.currentLanguage;
$scope.disclaimerUrl = $window.appConfig.disclaimerUrl; $scope.disclaimerUrl = appConfigService.disclaimerUrl;
$scope.openExternalLink = function(url, target) { $scope.openExternalLink = function(url, target) {
externalLinkService.open(url, target); externalLinkService.open(url, target);

View file

@ -122,8 +122,8 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio
var btx = $scope.btx; var btx = $scope.btx;
var url = 'https://' + ($scope.getShortNetworkName() == 'test' ? 'test-' : '') + 'insight.bitpay.com/tx/' + btx.txid; var url = 'https://' + ($scope.getShortNetworkName() == 'test' ? 'test-' : '') + 'insight.bitpay.com/tx/' + btx.txid;
var optIn = true; var optIn = true;
var title = gettextCatalog.getString('View Transaction on Insight'); var title = null;
var message = gettextCatalog.getString('Would you like to view this transaction on the Insight blockchain explorer?'); var message = gettextCatalog.getString('View Transaction on Insight');
var okText = gettextCatalog.getString('Open Insight'); var okText = gettextCatalog.getString('Open Insight');
var cancelText = gettextCatalog.getString('Go Back'); var cancelText = gettextCatalog.getString('Go Back');
externalLinkService.open(url, optIn, title, message, okText, cancelText); externalLinkService.open(url, optIn, title, message, okText, cancelText);

View file

@ -8,7 +8,9 @@ angular.module('copayApp.directives')
transclude: true, transclude: true,
scope: { scope: {
sendStatus: '=clickSendStatus', sendStatus: '=clickSendStatus',
wallet: '=hasWalletChosen' hasWalletChosen: '=hasWalletChosen',
insufficientFunds: '=insufficientFunds',
noMatchingWallet: '=noMatchingWallet'
}, },
link: function(scope, element, attrs) { link: function(scope, element, attrs) {
scope.$watch('sendStatus', function() { scope.$watch('sendStatus', function() {

View file

@ -0,0 +1,25 @@
'use strict';
angular.module('copayApp.directives')
.directive('itemSelector', function($timeout) {
return {
restrict: 'E',
templateUrl: 'views/includes/itemSelector.html',
transclude: true,
scope: {
show: '=itemSelectorShow',
onSelect: '=itemSelectorOnSelect'
},
link: function(scope, element, attrs) {
scope.hide = function() {
scope.show = false;
};
scope.sendMax = function() {
$timeout(function() {
scope.hide();
}, 100);
scope.onSelect();
};
}
};
});

View file

@ -614,7 +614,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
*/ */
.state('tabs.receive.addresses', { .state('tabs.receive.addresses', {
url: '/addresses/:walletId', url: '/addresses/:walletId/:toAddress',
views: { views: {
'tab-receive@tabs': { 'tab-receive@tabs': {
controller: 'addressesController', controller: 'addressesController',
@ -1031,7 +1031,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
} }
}) })
.state('tabs.bitpayCard.confirm', { .state('tabs.bitpayCard.confirm', {
url: '/confirm/:cardId/:toAddress/:toName/:toAmount/:toEmail/:description', url: '/confirm/:cardId/:cardAmountUSD/:toAddress/:toName/:toAmount/:toEmail/:description',
views: { views: {
'tab-home@tabs': { 'tab-home@tabs': {
controller: 'confirmController', controller: 'confirmController',
@ -1052,7 +1052,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
} }
}); });
}) })
.run(function($rootScope, $state, $location, $log, $timeout, $ionicHistory, $ionicPlatform, $window, lodash, platformInfo, profileService, uxLanguage, gettextCatalog, openURLService, storageService, scannerService) { .run(function($rootScope, $state, $location, $log, $timeout, $ionicHistory, $ionicPlatform, $window, appConfigService, lodash, platformInfo, profileService, uxLanguage, gettextCatalog, openURLService, storageService, scannerService) {
uxLanguage.init(); uxLanguage.init();
@ -1171,7 +1171,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
type: "menubar" type: "menubar"
}); });
try { try {
nativeMenuBar.createMacBuiltin($window.appConfig.nameCase); nativeMenuBar.createMacBuiltin(appConfigService.nameCase);
} catch (e) { } catch (e) {
$log.debug('This is not OSX'); $log.debug('This is not OSX');
} }

View file

@ -0,0 +1,5 @@
'use strict';
angular.module('copayApp.services').factory('appConfigService', function($window) {
return $window.appConfig;
});

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.services') angular.module('copayApp.services')
.factory('backupService', function backupServiceFactory($log, $timeout, $stateParams, profileService, sjcl, $window) { .factory('backupService', function backupServiceFactory($log, $timeout, $stateParams, profileService, sjcl, appConfigService) {
var root = {}; var root = {};
@ -80,7 +80,7 @@ angular.module('copayApp.services')
var walletName = (wallet.alias || '') + (wallet.alias ? '-' : '') + wallet.credentials.walletName; var walletName = (wallet.alias || '') + (wallet.alias ? '-' : '') + wallet.credentials.walletName;
if (opts.noSign) walletName = walletName + '-noSign' if (opts.noSign) walletName = walletName + '-noSign'
var filename = walletName + '-' + $window.appConfig.nameCase + 'backup.aes.json'; var filename = walletName + '-' + appConfigService.nameCase + 'backup.aes.json';
_download(ew, filename, cb) _download(ew, filename, cb)
}; };
return root; return root;

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.services').factory('incomingData', function($log, $state, $window, $timeout, bitcore, $rootScope, payproService, scannerService) { angular.module('copayApp.services').factory('incomingData', function($log, $state, $timeout, bitcore, $rootScope, payproService, scannerService, appConfigService) {
var root = {}; var root = {};
@ -121,17 +121,17 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
} else { } else {
goToAmountPage(data); goToAmountPage(data);
} }
} else if (data && data.indexOf($window.appConfig.name + '://glidera') === 0) { } else if (data && data.indexOf(appConfigService.name + '://glidera') === 0) {
return $state.go('uriglidera', { return $state.go('uriglidera', {
url: data url: data
}); });
} else if (data && data.indexOf($window.appConfig.name + '://coinbase') === 0) { } else if (data && data.indexOf(appConfigService.name + '://coinbase') === 0) {
return $state.go('uricoinbase', { return $state.go('uricoinbase', {
url: data url: data
}); });
// BitPay Authentication // BitPayCard Authentication
} else if (data && data.indexOf($window.appConfig.name + '://') === 0) { } else if (data && data.indexOf(appConfigService.name + '://') === 0) {
var secret = getParameterByName('secret', data); var secret = getParameterByName('secret', data);
var email = getParameterByName('email', data); var email = getParameterByName('email', data);
var otp = getParameterByName('otp', data); var otp = getParameterByName('otp', data);

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copayApp.services') angular.module('copayApp.services')
.factory('logHeader', function($window, $log, platformInfo) { .factory('logHeader', function($window, appConfigService, $log, platformInfo) {
$log.info($window.appConfig.nameCase + ' v' + window.version + ' #' + window.commitHash); $log.info(appConfigService.nameCase + ' v' + $window.version + ' #' + $window.commitHash);
$log.info('Client: '+ JSON.stringify(platformInfo) ); $log.info('Client: ' + JSON.stringify(platformInfo));
return {}; return {};
}); });

View file

@ -39,7 +39,11 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
'sendingByEmail': gettext('Preparing addresses...'), 'sendingByEmail': gettext('Preparing addresses...'),
'sending2faCode': gettext('Sending 2FA code...'), 'sending2faCode': gettext('Sending 2FA code...'),
'buyingBitcoin': gettext('Buying Bitcoin...'), 'buyingBitcoin': gettext('Buying Bitcoin...'),
'sellingBitcoin': gettext('Selling Bitcoin...') 'sellingBitcoin': gettext('Selling Bitcoin...'),
'updatingGiftCards': 'Updating Gift Cards...',
'updatingGiftCard': 'Updating Gift Card...',
'cancelingGiftCard': 'Canceling Gift Card...',
'creatingGiftCard': 'Creating Gift Card...'
}; };
root.clear = function() { root.clear = function() {

View file

@ -712,7 +712,7 @@ angular.module('copayApp.services')
var opts = {}; var opts = {};
opts.m = 1; opts.m = 1;
opts.n = 1; opts.n = 1;
opts.network = 'livenet'; opts.networkName = 'livenet';
root.createWallet(opts, cb); root.createWallet(opts, cb);
}; };

View file

@ -1,6 +1,6 @@
'use strict'; 'use strict';
angular.module('copayApp.services').factory('txFormatService', function(bwcService, rateService, configService, lodash) { angular.module('copayApp.services').factory('txFormatService', function($filter, bwcService, rateService, configService, lodash) {
var root = {}; var root = {};
root.Utils = bwcService.getUtils(); root.Utils = bwcService.getUtils();
@ -48,10 +48,11 @@ angular.module('copayApp.services').factory('txFormatService', function(bwcServi
var config = configService.getSync().wallet.settings; var config = configService.getSync().wallet.settings;
var val = function() { var val = function() {
var v1 = rateService.toFiat(satoshis, config.alternativeIsoCode); var v1 = parseFloat((rateService.toFiat(satoshis, config.alternativeIsoCode)).toFixed(2));
v1 = $filter('formatFiatAmount')(v1);
if (!v1) return null; if (!v1) return null;
return v1.toFixed(2) + ' ' + config.alternativeIsoCode; return v1 + ' ' + config.alternativeIsoCode;
}; };
// Async version // Async version

View file

@ -12,23 +12,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
var errors = bwcService.getErrors(); var errors = bwcService.getErrors();
// UI Related
root.openStatusModal = function(type, txp, cb) {
var scope = $rootScope.$new(true);
scope.type = type;
scope.tx = txFormatService.processTx(txp);
scope.color = txp.color;
scope.cb = cb;
$ionicModal.fromTemplateUrl('views/modals/tx-status.html', {
scope: scope,
animation: 'slide-in-up'
}).then(function(modal) {
scope.txStatusModal = modal;
scope.txStatusModal.show();
});
};
var _signWithLedger = function(wallet, txp, cb) { var _signWithLedger = function(wallet, txp, cb) {
$log.info('Requesting Ledger Chrome app to sign the transaction'); $log.info('Requesting Ledger Chrome app to sign the transaction');
@ -961,23 +944,10 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
if (err) return cb(bwcError.msg(err)); if (err) return cb(bwcError.msg(err));
$rootScope.$emit('Local/TxAction', wallet.id); $rootScope.$emit('Local/TxAction', wallet.id);
var type = root.getViewStatus(wallet, broadcastedTxp);
if (!customStatusHandler) {
root.openStatusModal(type, broadcastedTxp, function() {});
}
return cb(null, broadcastedTxp); return cb(null, broadcastedTxp);
}); });
} else { } else {
$rootScope.$emit('Local/TxAction', wallet.id); $rootScope.$emit('Local/TxAction', wallet.id);
var type = root.getViewStatus(wallet, signedTxp);
if (!customStatusHandler) {
root.openStatusModal(type, signedTxp, function() {});
}
return cb(null, signedTxp); return cb(null, signedTxp);
} }
}); });
@ -1053,38 +1023,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
} catch (e) {} } catch (e) {}
} }
root.getViewStatus = function(wallet, txp) {
var status = txp.status;
var type;
var INMEDIATE_SECS = 10;
if (status == 'broadcasted') {
type = 'broadcasted';
} else {
var n = txp.actions.length;
var action = lodash.find(txp.actions, {
copayerId: wallet.credentials.copayerId
});
if (!action) {
type = 'created';
} else if (action.type == 'accept') {
// created and accepted at the same time?
if (n == 1 && action.createdOn - txp.createdOn < INMEDIATE_SECS) {
type = 'created';
} else {
type = 'accepted';
}
} else if (action.type == 'reject') {
type = 'rejected';
} else {
throw new Error('Unknown type:' + type);
}
}
return type;
};
root.getSendMaxInfo = function(wallet, opts, cb) { root.getSendMaxInfo = function(wallet, opts, cb) {
opts = opts || {}; opts = opts || {};
wallet.getSendMaxInfo(opts, function(err, res) { wallet.getSendMaxInfo(opts, function(err, res) {

View file

@ -12,6 +12,8 @@ ion-tabs.ion-tabs-transparent {
background: none transparent; background: none transparent;
} }
ion-nav-bar.hide { display: block !important; }
// .placeholder-icon padding cannot be modified by a variable // .placeholder-icon padding cannot be modified by a variable
$placeholder-icon-padding: 10px; $placeholder-icon-padding: 10px;
.placeholder-icon { .placeholder-icon {

View file

@ -165,7 +165,7 @@ input[type=number] {
.input-notification { .input-notification {
float: right; float: right;
margin-right: 10px; margin-right: 25px;
} }
.pr { .pr {

View file

@ -14,9 +14,43 @@
padding: 0 10px; padding: 0 10px;
font-size: 24px; font-size: 24px;
cursor: pointer; cursor: pointer;
line-height: 155px;
} }
.qr-icon { .icon {
line-height: 45px; &.valid {
padding-top: 3px;
color: #13E5B6;
}
&.invalid {
padding-top: 3px;
color: #DF2121;
}
}
.add-address-input-group {
background-color: #fff;
.item-stacked-label {
padding: 1rem;
}
.input-label {
text-transform: uppercase;
font-size: 12px;
font-weight: bold;
}
}
.add-address-list {
.item {
color: $dark-gray;
padding-top: 1.3rem;
padding-bottom: 1.3rem;
&.item-divider {
color: $mid-gray;
padding-bottom: .5rem;
font-size: .9rem;
}
}
.item-note {
color: $light-gray;
}
} }
} }
#view-address-book { #view-address-book {

View file

@ -47,7 +47,6 @@
font-size: .9rem; font-size: .9rem;
} }
&.view-all { &.view-all {
margin: 20px 0px 20px 0px;
cursor: pointer; cursor: pointer;
cursor: hand; cursor: hand;
i { i {

View file

@ -1,4 +1,5 @@
#view-confirm { #view-confirm {
background-color: #ffffff;
@extend .deflash-blue; @extend .deflash-blue;
.icon-amazon { .icon-amazon {
background-image: url("../img/icon-amazon.svg"); background-image: url("../img/icon-amazon.svg");

View file

@ -0,0 +1,61 @@
item-selector {
$border-color: #EFEFEF;
.bp-action-sheet__sheet {
padding-left: 2rem;
padding-right: .75rem;
}
.item-selector {
.option {
border: 0;
padding-right: 0;
padding-top: 0;
padding-bottom: 0;
margin-bottom: 1px;
overflow: visible;
> i {
color: #647ce8;
padding: 0 0 5px 0;
margin-left: -5px;
> img {
height: 39px;
width: 39px;
padding: 4px;
}
}
}
.item-selector-inner {
display: flex;
position: relative;
padding-top: 16px;
padding-bottom: 16px;
&::after {
display: block;
position: absolute;
width: 100%;
height: 1px;
background: $border-color;
bottom: 0;
right: 0;
content: '';
}
.check {
padding: 0 1.2rem;
}
}
.item-selector-details {
flex-grow: 1;
.item-selector-name {
padding-bottom: 5px;
}
}
}
}

View file

@ -8,8 +8,20 @@
padding: 0 10px; padding: 0 10px;
font-size: 24px; font-size: 24px;
cursor: pointer; cursor: pointer;
}
.qr-icon {
line-height: 45px; line-height: 45px;
} }
.item-stacked-label .icon {
padding: 0px;
margin: 0px;
}
.icon {
&.valid {
padding-top: 3px;
color: #13E5B6;
}
&.invalid {
padding-top: 3px;
color: #DF2121;
}
}
} }

View file

@ -62,7 +62,7 @@
} }
.checkbox input:before, .checkbox input:before,
.checkbox .checkbox-icon:before { .checkbox .checkbox-icon:before {
padding: 1.1rem; padding: 1.2rem;
position: relative; position: relative;
background:url("../img/onboarding-checkbox-unchecked.svg") top center no-repeat; background:url("../img/onboarding-checkbox-unchecked.svg") top center no-repeat;
} }

View file

@ -117,6 +117,7 @@
transform: translate(-150%, -40%); transform: translate(-150%, -40%);
} }
.item { .item {
white-space: nowrap;
padding-top: 5px; padding-top: 5px;
padding-bottom: 5px; padding-bottom: 5px;
font-size: .7rem; font-size: .7rem;

View file

@ -39,6 +39,7 @@
@import "includes/tx-details"; @import "includes/tx-details";
@import "includes/txp-details"; @import "includes/txp-details";
@import "includes/tx-status"; @import "includes/tx-status";
@import "includes/itemSelector";
@import "includes/walletSelector"; @import "includes/walletSelector";
@import "integrations/coinbase"; @import "integrations/coinbase";
@import "integrations/glidera"; @import "integrations/glidera";

View file

@ -16,8 +16,8 @@
<form name="addressbookForm" no-validate> <form name="addressbookForm" no-validate>
<div class="list"> <div class="list add-address-list add-address-input-group">
<label class="item item-input item-stacked-label"> <label class="item item-input item-stacked-label no-border">
<span class="input-label" translate>Name</span> <span class="input-label" translate>Name</span>
<input type="text" <input type="text"
id="name" id="name"
@ -37,10 +37,8 @@
<label class="item item-input item-stacked-label"> <label class="item item-input item-stacked-label">
<span class="input-label" translate>Bitcoin Address</span> <span class="input-label" translate>Bitcoin Address</span>
<div class="input-notification"> <div class="input-notification">
<i class="icon ion-checkmark-circled balanced" <i ng-show="!addressbookForm.address.$invalid" class="icon ion-checkmark-circled valid"></i>
ng-show="!addressbookForm.address.$invalid"></i> <i ng-show="addressbookForm.address.$invalid && addressbookEntry.address" class="icon ion-close-circled invalid"></i>
<i class="icon ion-close-circled assertive"
ng-show="addressbookForm.address.$invalid && addressbookEntry.address"></i>
</div> </div>
<input type="text" <input type="text"
id="address" id="address"
@ -49,7 +47,7 @@
valid-address required> valid-address required>
</label> </label>
<div class="qr-scan-icon"> <div class="qr-scan-icon">
<qr-scanner on-scan="onQrCodeScanned(data, addressbookForm)"></qr-scanner> <qr-scanner on-scan="onQrCodeScannedAddressBook(data, addressbookForm)"></qr-scanner>
</div> </div>
</div> </div>
</div> </div>

View file

@ -17,7 +17,7 @@
<img src="img/address-book-add.svg"/> <img src="img/address-book-add.svg"/>
</i> </i>
<div class="zero-state-heading" translate>No contacts yet</div> <div class="zero-state-heading" translate>No contacts yet</div>
<div class="zero-state-description" translate>You havent added any contacts to your address book yet. Get started by adding your first one.</div> <div class="zero-state-description" translate>Get started by adding your first one.</div>
<div class="zero-state-cta"> <div class="zero-state-cta">
<button class="button button-standard button-primary" ui-sref="tabs.addressbook.add" translate>Add Contact</button> <button class="button button-standard button-primary" ui-sref="tabs.addressbook.add" translate>Add Contact</button>
</div> </div>

View file

@ -3,11 +3,6 @@
<ion-nav-title>{{'Wallet Addresses' | translate}}</ion-nav-title> <ion-nav-title>{{'Wallet Addresses' | translate}}</ion-nav-title>
<ion-nav-back-button> <ion-nav-back-button>
</ion-nav-back-button> </ion-nav-back-button>
<ion-nav-buttons side="secondary">
<button class="button back-button" ng-click="showMenu(false, $event)">
<i class="icon ion-ios-more"></i>
</button>
</ion-nav-buttons>
</ion-nav-bar> </ion-nav-bar>
<ion-content> <ion-content>
@ -26,11 +21,22 @@
<div class="addr-explanation" ng-if="showInfo"> <div class="addr-explanation" ng-if="showInfo">
<div class="addr-description"> <div class="addr-description">
<span translate>It's a good idea to avoid reusing addresses-this both protects your privacy and keeps your bitcoins secure against hypothetical attacks by quantum computers.</span>&nbsp<a ng-click="showInformation()" translate>Hide</a> <span translate>It's a good idea to avoid reusing addresses - this both protects your privacy and keeps your bitcoins secure against hypothetical attacks by quantum computers.</span>&nbsp<a ng-click="showInformation()" translate>Hide</a>
</div> </div>
</div> </div>
<div class="list"> <div class="list">
<div class="item item-icon-right view-all" ng-click="requestSpecificAmount()">
<span translate>Request Specific amount</span>
<i class="icon ion-ios-arrow-thin-right"></i>
</div>
<div class="item item-icon-right view-all" ng-show="viewAll.value" ng-click="viewAllAddresses()">
<span translate>View All Addresses</span>
<i class="icon ion-ios-arrow-thin-right"></i>
</div>
<div class="item view-all" ng-show="latestWithBalance[0]" ng-click="scan()">
<span translate>Scan addresses for funds</span>
</div>
<div class="item item-divider item-icon-right" ng-click="newAddress()"> <div class="item item-divider item-icon-right" ng-click="newAddress()">
<span translate>Unused Addresses</span> <span translate>Unused Addresses</span>
<i class="icon ion-ios-plus-empty"></i> <i class="icon ion-ios-plus-empty"></i>
@ -61,11 +67,6 @@
<div class="addr-balance">{{w.balanceStr}}</div> <div class="addr-balance">{{w.balanceStr}}</div>
</div> </div>
</div> </div>
<div class="item item-icon-right view-all" ng-show="viewAll.value" ng-click="viewAllAddresses()">
<span translate>View All Addresses</span>
<i class="icon ion-ios-arrow-thin-right"></i>
</div>
</div> </div>
</div> </div>
</ion-content> </ion-content>

View file

@ -67,31 +67,6 @@
<span transaction>If enabled, the Frequently Used card - a list of the most commonly chosen recipients - will appear in the Send tab.</span> <span transaction>If enabled, the Frequently Used card - a list of the most commonly chosen recipients - will appear in the Send tab.</span>
</div> --> </div> -->
<div ng-show="global.developmentUtilitiesEnabled.value">
<div class="item item-divider" translate>Development Utilities</div>
<div class="settings-explanation">
<div class="settings-description" translate>
These utilities may be unstable. Proceed at your own risk.
</div>
</div>
<div class="item has-comment item-button-right">
Feedback Card
<button class="button button-secondary" ng-click="activateFeedbackCard()" ng-show="!feedbackCardActivating && !feedbackCardActivated">
Activate
</button>
<button class="button button-secondary button-clear" disabled ng-show="feedbackCardActivating">
<ion-spinner></ion-spinner>
</button>
<button class="button button-secondary button-clear" ng-show="feedbackCardActivated" ng-click="resetActivateFeedbackCard()">
Activated
</button>
</div>
<div class="comment">
<span transaction>The feedback card is displayed on the Home tab at certain times. You can activate it immediately here.</span>
</div>
</div>
</div> </div>
</ion-content> </ion-content>
</ion-view> </ion-view>

View file

@ -3,17 +3,20 @@
<ion-nav-title>{{'All Addresses' | translate}}</ion-nav-title> <ion-nav-title>{{'All Addresses' | translate}}</ion-nav-title>
<ion-nav-back-button> <ion-nav-back-button>
</ion-nav-back-button> </ion-nav-back-button>
<ion-nav-buttons side="secondary">
<button class="button back-button" ng-click="showMenu(true, $event)" ng-hide="!isCordova && allAddressesView">
<i class="icon ion-ios-more"></i>
</button>
</ion-nav-buttons>
</ion-nav-bar> </ion-nav-bar>
<ion-content> <ion-content>
<div class="addr-list list"> <div class="addr-list list">
<div class="item item-divider"></div> <div class="item item-divider"></div>
<div ng-show="isCordova && allAddresses[0]">
<div class="item view-all" ng-click="sendByEmail()">
<span translate>Send addresses by email</span>
</div>
<div class="item item-divider"></div>
</div>
<div class="item" ng-repeat="a in allAddresses track by $index" copy-to-clipboard="a.address"> <div class="item" ng-repeat="a in allAddresses track by $index" copy-to-clipboard="a.address">
{{a.address}} {{a.address}}
<div class="addr-path" ng-if="!a.balanceStr"> <div class="addr-path" ng-if="!a.balanceStr">

View file

@ -6,7 +6,7 @@
<ion-nav-back-button> <ion-nav-back-button>
</ion-nav-back-button> </ion-nav-back-button>
<ion-nav-buttons side="secondary"> <ion-nav-buttons side="secondary">
<button class="button back-button" ng-click="showSendMaxMenu($event)" ng-if="showMenu"> <button class="button back-button" ng-click="showSendMaxMenu()" ng-if="showMenu">
<i class="icon ion-ios-more"></i> <i class="icon ion-ios-more"></i>
</button> </button>
</ion-nav-buttons> </ion-nav-buttons>
@ -120,4 +120,8 @@
</div> </div>
</div> </div>
</ion-content> </ion-content>
<item-selector
item-selector-show="showSendMax"
item-selector-on-select="sendMax">
</item-selector>
</ion-view> </ion-view>

View file

@ -12,7 +12,7 @@
<div class="onboarding-illustration-backup-warning"></div> <div class="onboarding-illustration-backup-warning"></div>
<div id="cta-buttons"> <div id="cta-buttons">
<div class="onboarding-tldr" translate>Anyone with your backup phrase can access or spend your bitcoin.</div> <div class="onboarding-tldr" translate>Anyone with your backup phrase can access or spend your bitcoin.</div>
<button class="button button-standard button-primary" ng-click="openPopup()" translate>All clear, let's do this</button> <button class="button button-standard button-primary" ng-click="openPopup()" translate>Got it</button>
</div> </div>
</ion-content> </ion-content>
</ion-view> </ion-view>

View file

@ -60,12 +60,18 @@
<span class="label" ng-if="!isGlidera" translate>From</span> <span class="label" ng-if="!isGlidera" translate>From</span>
<span class="label" ng-if="isGlidera == 'buy'">To</span> <span class="label" ng-if="isGlidera == 'buy'">To</span>
<span class="label" ng-if="isGlidera == 'sell'">From</span> <span class="label" ng-if="isGlidera == 'sell'">From</span>
<div class="wallet"> <div class="wallet" ng-if="wallet">
<i class="icon big-icon-svg"> <i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-style="{'background-color': wallet.color}" class="bg"/> <img src="img/icon-wallet.svg" ng-style="{'background-color': wallet.color}" class="bg"/>
</i> </i>
<div>{{wallet.name}}</div> <div>{{wallet.name}}</div>
</div> </div>
<div class="wallet" ng-if="!wallet">
<i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" ng-style="{'background-color': 'grey'}" class="bg"/>
</i>
<div>...</div>
</div>
<i class="icon bp-arrow-right"></i> <i class="icon bp-arrow-right"></i>
</a> </a>
<a class="item single-line item-icon-right" ng-if="!insufficientFunds && !noMatchingWallet && !isGlidera" ng-click="showDescriptionPopup()"> <a class="item single-line item-icon-right" ng-if="!insufficientFunds && !noMatchingWallet && !isGlidera" ng-click="showDescriptionPopup()">
@ -120,17 +126,21 @@
</ion-content> </ion-content>
<click-to-accept <click-to-accept
ng-click="approve(statusChangeHandler)" ng-click="approve(statusChangeHandler)"
ng-if="!isCordova && wallets[0] && !insufficientFunds && !noMatchingWallet" ng-if="!isCordova"
click-send-status="sendStatus" click-send-status="sendStatus"
has-wallet-chosen="wallet"> has-wallet-chosen="wallet"
insufficient-funds="insufficientFunds"
no-matching-wallet="noMatchingWallet">
{{'Accept' | translate}} {{'Accept' | translate}}
</click-to-accept> </click-to-accept>
<slide-to-accept <slide-to-accept
ng-disabled="!wallet" ng-disabled="!wallet"
ng-if="isCordova && wallets[0] && !insufficientFunds && !noMatchingWallet" ng-if="isCordova"
slide-on-confirm="onConfirm()" slide-on-confirm="onConfirm()"
slide-send-status="sendStatus" slide-send-status="sendStatus"
has-wallet-chosen="wallet"> has-wallet-chosen="wallet"
insufficient-funds="insufficientFunds"
no-matching-wallet="noMatchingWallet">
{{'Accept' | translate}} {{'Accept' | translate}}
</slide-to-accept> </slide-to-accept>
<slide-to-accept-success <slide-to-accept-success

View file

@ -10,7 +10,7 @@
</button> </button>
</ion-nav-buttons> </ion-nav-buttons>
<ion-nav-buttons side="secondary"> <ion-nav-buttons side="secondary">
<button ng-disabled="!feedback.value" class="button no-border" type="submit" ng-click="sendFeedback(feedback.value)" translate> <button ng-show="isCordova" ng-disabled="!feedback.value" class="button no-border" type="submit" ng-click="sendFeedback(feedback.value)" translate>
Send Send
</button> </button>
</ion-nav-buttons> </ion-nav-buttons>
@ -40,7 +40,7 @@
</div> </div>
<div ng-if="showForm" class="form-fade-in"> <div ng-if="showForm" class="form-fade-in">
<textarea class="user-feedback" ng-model="feedback.value" rows="5" placeholder="{{'Your ideas, feedback, or comments' | translate}}" autofocus></textarea> <textarea class="user-feedback" ng-model="feedback.value" rows="5" placeholder="{{'Your ideas, feedback, or comments' | translate}}" autofocus></textarea>
<button ng-disabled="!feedback.value" type="submit" class="button button-standard button-primary" ng-click="sendFeedback(feedback.value)" translate> <button ng-show="!isCordova" ng-disabled="!feedback.value" type="submit" class="button button-standard button-primary" ng-click="sendFeedback(feedback.value)" translate>
Send Send
</button> </button>
</div> </div>

View file

@ -1,9 +0,0 @@
<div class="columns m20t">
<div class="m20t size-14 text-center">
<i class="fi-alert"></i>
{{msg|translate}}
</div>
<div class="text-center m20t" ng-click="close()">
<a class="button outline light-gray round tiny small-4">OK</a>
</div>
</div>

View file

@ -1,10 +0,0 @@
<div>
<h1 translate>Without a backup, you could lose money</h1>
<span translate>If something happens to this device, this app is deleted, or your password forgotten, neither you nor Bitpay can recover your funds.</span>
<button ng-click="goBack()" class="button button-block button-light" translate>
Go back
</button>
<button ng-click="continue()" class="button button-block button-light" translate>
I understand
</button>
</div>

View file

@ -7,7 +7,7 @@
<div class="popup-modal-heading" translate>Backup Needed</div> <div class="popup-modal-heading" translate>Backup Needed</div>
<div class="popup-modal-message" translate>Now is a good time to backup your wallet. If this device is lost, it is impossible to access your funds without a backup.</div> <div class="popup-modal-message" translate>Now is a good time to backup your wallet. If this device is lost, it is impossible to access your funds without a backup.</div>
<button class="button button-clear" ng-click="doBackup()" translate>Backup now</button> <button class="button button-clear" ng-click="doBackup()" translate>Backup now</button>
<button class="button button-secondary button-clear" ng-click="close()" translate>I'll do it later</button> <button class="button button-secondary button-clear" ng-click="close()" translate>Do it later</button>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,7 +0,0 @@
<div>
<h1 translate>Screenshots are not secure</h1>
<span translate>if you take a screenshot, your backup may be viewed by others apps. You can make a safe backup with paper and a pen.</span>
<button ng-click="close()" class="button button-block button-clear" translate>
Got it
</button>
</div>

View file

@ -1,4 +1,4 @@
<button ng-disabled="!wallet" class="click-to-accept__button button button-standard button-primary" ng-class="{disable: sendStatus}"> <button ng-disabled="!hasWalletChosen || insufficientFunds || noMatchingWallet" class="click-to-accept__button button button-standard button-primary" ng-class="{disable: sendStatus}">
<span ng-if="!sendStatus"> <span ng-if="!sendStatus">
<ng-transclude></ng-transclude> <ng-transclude></ng-transclude>
</span> </span>

View file

@ -0,0 +1,12 @@
<action-sheet action-sheet-show="show" class="item-selector">
<img class="back-arrow" src="img/icon-back-arrow.svg" ng-click="hide()">
<div class="header">{{title}}</div>
<a class="item item-icon-left option no-border" ng-click="onSelect()">
<i class="icon ion-ios-speedometer-outline"></i>
<div class="item-selector-inner">
<div class="item-selector-details">
<div class="item-selector-name" translate>Send max amount</div>
</div>
</div>
</a>
</action-sheet>

View file

@ -1,9 +0,0 @@
<ion-popover-view ng-style="{'height': height + 'px'}" id="menu-popover">
<ion-content>
<div class="list">
<div class="item" ng-repeat="i in items track by $index" ng-click="i.action()">
{{i.text}}
</div>
</div>
</ion-content>
</ion-popover-view>

View file

@ -1,42 +0,0 @@
<div class="columns m20t">
<label class="size-14 text-center" for="password" ng-if="isSetup">
<span ng-show="!isVerification" translate>Set up a spending password</span>
<span ng-show="isVerification" translate>Repeat the spending password</span>
</label>
<label class="size-14 text-center" for="password" ng-if="!isSetup">
<span translate>Enter your spending password</span>
</label>
<div class="input m20t">
<input type="password" placeholder="{{'Your spending password'|translate}}"
id="passwordInput" name="password" ng-model="data.password" ng-keypress="keyPress($event)" autofocus>
</div>
</div>
<div class="row">
<div class="small-6 columns">
<button
class="round small-6 columns outline dark-gray expand"
ng-click="cancel()"
ng-disabled="loading">
<span class="size-12" translate>Cancel</span>
</button>
</div>
<div class="small-6 columns">
<button class="round expand"
ng-click="set()"
ng-disabled="!data.password || loading"
ng-style="{'background-color':index.backgroundColor}">
<span ng-if="isSetup" class="size-12" translate>SET</span>
<span ng-if="!isSetup" class="size-12">OK</span>
</button>
</div>
</div>
<p class="text-warning size-12 columns m20t text-center" ng-show="isSetup">
<i class="fi-alert"></i>
<span ng-show="!error" translate> Your wallet key will be encrypted. The Spending Password cannot be recovered. Be sure to write it down</span>
<span ng-show="error">{{error|translate}}</span>
</p>

View file

@ -25,10 +25,8 @@
<label class="item item-input item-stacked-label no-border"> <label class="item item-input item-stacked-label no-border">
<span class="input-label" translate>Wallet Invitation</span> <span class="input-label" translate>Wallet Invitation</span>
<div class="input-notification"> <div class="input-notification">
<i class="icon ion-checkmark-circled balanced" <i ng-show="!joinForm.secret.$invalid" class="icon ion-checkmark-circled valid"></i>
ng-show="!joinForm.secret.$invalid"></i> <i ng-show="joinForm.secret.$invalid && secret" class="icon ion-close-circled invalid"></i>
<i class="icon ion-close-circled assertive"
ng-show="joinForm.secret.$invalid && secret"></i>
</div> </div>
<input id="secret" <input id="secret"
type="text" type="text"
@ -38,7 +36,7 @@
wallet-secret required> wallet-secret required>
</label> </label>
<div class="qr-scan-icon"> <div class="qr-scan-icon">
<qr-scanner class="qr-icon size-24" on-scan="join.onQrCodeScanned(data)"></qr-scanner> <qr-scanner class="qr-icon size-24" on-scan="join.onQrCodeScannedJoin(data)"></qr-scanner>
</div> </div>
</div> </div>
<div class="item item-divider"></div> <div class="item item-divider"></div>
@ -91,14 +89,14 @@
</div> </div>
<div class="item item-input" ng-show="encrypt"> <div class="item item-input" ng-show="encrypt">
<input ng-show="join.seedSourceId == 'new'" <input ng-show="join.seedSourceId == 'new'"
placeholder="{{'Password'|translate}}" placeholder="{{'Password'|translate}}"
type="password" type="password"
autocapitalize="off" autocapitalize="off"
name="createPassphrase" name="createPassphrase"
ng-model="createPassphrase"> ng-model="createPassphrase">
<input ng-show="join.seedSourceId == 'set'" <input ng-show="join.seedSourceId == 'set'"
placeholder="{{'Password'|translate}}" placeholder="{{'Password'|translate}}"
type="password" type="password"
autocapitalize="off" autocapitalize="off"

View file

@ -1,56 +1,61 @@
<ion-modal-view ng-controller="payproController"> <ion-modal-view id="view-confirm">
<ion-header-bar align-title="center" class="bar-royal" ng-style="{'background-color': color, 'border-color': color}"> <ion-header-bar align-title="center" class="bar-royal">
<button class="button button-clear" ng-click="cancel()"> <button class="button button-back button-clear" ng-click="cancel()">
{{'Close' | translate}} {{'Close' | translate}}
</button> </button>
<div class="title" translate> <h1 class="title" translate>Payment request</h1>
Payment request
</div>
</ion-header-bar> </ion-header-bar>
<ion-content> <ion-content>
<div class="header-modal text-center size-42">
{{amountStr}}
</div>
<div class="list"> <div class="list">
<div class="item item-divider" translate> <div class="item head">
Details <div class="amount-label">
<div class="amount">{{displayAmount || '...'}} <span class="unit">{{displayUnit}}</span></div>
<div class="alternative">{{alternativeAmountStr || '...'}}</div>
</div>
</div> </div>
<div class="item"> <div class="info">
{{'Pay To'|translate}} <div class="item single-line" ng-if="paypro.domain">
<span class="item-note">{{paypro.domain}}</span> <span class="label">{{'Pay To'|translate}}</span>
</div> <span class="item-note">
<div class="item" ng-if="paypro.toAddress"> {{paypro.domain}}
{{'Address'|translate}}
<span class="item-note">{{paypro.toAddress}}</span>
</div>
<div class="item">
{{'Certified by'|translate}}
<span class="item-note">
<span ng-show="paypro.caTrusted">
<i class="ion-locked" style="color:green"></i>
{{paypro.caName}}<br>
<span translate>(Trusted)</span>
</span> </span>
<span ng-show="!paypro.caTrusted"> </div>
<span ng-show="paypro.selfSigned"> <div class="item single-line" ng-if="paypro.toAddress">
<i class="ion-unlocked" style="color:red"></i> <span translate>Self-signed Certificate</span> <span class="label">{{'Address'|translate}}</span>
<span class="item-note m10l ellipsis">
{{paypro.toAddress}}
</span>
</div>
<div class="item">
<span class="label">{{'Certified by'|translate}}</span>
<span class="item-note w100p">
<span ng-show="paypro.caTrusted">
<i class="ion-locked" style="color:green"></i>
{{paypro.caName}} {{'(Trusted)' | translate}}</span>
</span> </span>
<span ng-show="!paypro.selfSigned"> <span ng-show="!paypro.caTrusted">
<i class="ion-locked" style="color:yellow"></i>{{paypro.caName}}<br> <span ng-show="paypro.selfSigned">
<span translate>WARNING: UNTRUSTED CERTIFICATE</span> <i class="ion-unlocked" style="color:red"></i> <span translate>Self-signed Certificate</span>
</span>
<span ng-show="!paypro.selfSigned">
<i class="ion-locked" style="color:yellow"></i>{{paypro.caName}}<br>
<span translate>WARNING: UNTRUSTED CERTIFICATE</span>
</span>
</span> </span>
</span> </span>
</span> </div>
</div> <div class="item" ng-if="paypro.memo">
<div class="item" ng-if="paypro.memo"> <span class="label">{{'Memo'|translate}}</span>
{{'Memo'|translate}} <span class="item-note w100p">
<span class="item-note wrapword">{{paypro.memo}}</span> {{paypro.memo}}
</div> </span>
<div class="item" ng-if="paypro.expires"> </div>
{{'Expires'|translate}} <div class="item single-line" ng-if="paypro.expires">
<span class="item-note">{{paypro.expires * 1000 | amTimeAgo }}</span> <span class="label">{{'Expires'|translate}}</span>
<span class="item-note">
{{paypro.expires * 1000 | amTimeAgo }}
</span>
</div>
</div> </div>
</div> </div>
</ion-content> </ion-content>

View file

@ -9,7 +9,7 @@
<i class="ion-ios-arrow-thin-down" id="arrow-down"></i> <i class="ion-ios-arrow-thin-down" id="arrow-down"></i>
<div class="onboarding-tldr" id="backup-tldr" translate>Your wallet is never saved to cloud storage or standard device backups.</div> <div class="onboarding-tldr" id="backup-tldr" translate>Your wallet is never saved to cloud storage or standard device backups.</div>
<button class="button button-standard button-primary" ui-sref="onboarding.backupWarning({from: 'onboarding', walletId: walletId})" translate>Backup wallet</button> <button class="button button-standard button-primary" ui-sref="onboarding.backupWarning({from: 'onboarding', walletId: walletId})" translate>Backup wallet</button>
<button class="button button-standard button-secondary button-clear" ng-click="openPopup()" translate>I'll backup my wallet later</button> <button class="button button-standard button-secondary" ng-click="openPopup()" translate>Do it later</button>
</div> </div>
</ion-content> </ion-content>
</ion-view> </ion-view>

View file

@ -1,5 +1,5 @@
<ion-pane class="pane-onboarding"> <ion-pane class="pane-onboarding">
<ion-view id="onboarding-disclaimer" class="onboarding" ng-class="{'shrink': shrinkView}" ng-init=init()> <ion-view id="onboarding-disclaimer" class="onboarding" ng-class="{'shrink': shrinkView}">
<ion-nav-bar class="bar-stable" ng-if="backedUp == 'false'"> <ion-nav-bar class="bar-stable" ng-if="backedUp == 'false'">
<ion-nav-title></ion-nav-title> <ion-nav-title></ion-nav-title>
<ion-nav-buttons side="primary"> <ion-nav-buttons side="primary">

View file

@ -1,6 +1,5 @@
<ion-view id="onboard-welcome" class="onboarding"> <ion-view id="onboard-welcome" class="onboarding">
<ion-content ng-controller="welcomeController" ng-init="createProfile()" scroll="false"> <ion-content ng-controller="welcomeController" ng-init="createProfile()" scroll="false">
<!-- <qr-scanner id="qrcode" on-scan="goImport(data)"></qr-scanner> -->
<div id="logo-tagline"> <div id="logo-tagline">
<img src='img/bitpay-logo.svg' id="logo" /> <img src='img/bitpay-logo.svg' id="logo" />
<p id="lead" translate>Take control of your money,<br />get started with bitcoin.</p> <p id="lead" translate>Take control of your money,<br />get started with bitcoin.</p>

View file

@ -31,7 +31,7 @@
slide-success-show="sendStatus === 'success'" slide-success-show="sendStatus === 'success'"
slide-success-on-confirm="onSuccessConfirm()" slide-success-on-confirm="onSuccessConfirm()"
slide-success-hide-on-confirm="true"> slide-success-hide-on-confirm="true">
<span translate>Founds transferred</span> <span translate>Funds transferred</span>
</slide-to-accept-success> </slide-to-accept-success>
</ion-content> </ion-content>
</ion-view> </ion-view>

View file

@ -17,8 +17,7 @@
</div> </div>
<div class="settings-explanation"> <div class="settings-explanation">
<div class="settings-description" translate> <div class="settings-description" translate>
{{appName}} depends on Bitcore Wallet Service (BWS) for blockchain information, networking and Copayer synchronization. {{appName}} depends on Bitcore Wallet Service (BWS) for blockchain information, networking and Copayer synchronization. The default configuration points to https://bws.bitpay.com (BitPay's public BWS instance).
The default configuration points to https://bws.bitpay.com (BitPay's public BWS instance).
</div> </div>
</div> </div>
<button class="button button-standard button-primary" ng-click="save()" translate>Save</button> <button class="button button-standard button-primary" ng-click="save()" translate>Save</button>

View file

@ -63,7 +63,7 @@
<i class="icon big-icon-svg"> <i class="icon big-icon-svg">
<img src="img/icon-wallet.svg" class="bg wallet icon-create-wallet"/> <img src="img/icon-wallet.svg" class="bg wallet icon-create-wallet"/>
</i> </i>
<span translate>Create a bitcoin wallet</span> <span translate>Create bitcoin wallet</span>
<i class="icon bp-arrow-right"></i> <i class="icon bp-arrow-right"></i>
</a> </a>
<a ng-repeat="wallet in wallets track by $index" <a ng-repeat="wallet in wallets track by $index"

View file

@ -1,11 +1,6 @@
<ion-view id="tab-receive"> <ion-view id="tab-receive">
<ion-nav-bar class="bar-royal"> <ion-nav-bar class="bar-royal">
<ion-nav-title>{{'Receive' | translate}}</ion-nav-title> <ion-nav-title>{{'Receive' | translate}}</ion-nav-title>
<ion-nav-buttons side="secondary">
<button ng-disabled="generatingAddress" class="button back-button" ng-click="showMenu(false, $event)">
<i class="icon ion-ios-more"></i>
</button>
</ion-nav-buttons>
</ion-nav-bar> </ion-nav-bar>
<ion-content scroll="false"> <ion-content scroll="false">
<article class="list card padding text-center" ng-if="!wallets[0]"> <article class="list card padding text-center" ng-if="!wallets[0]">

View file

@ -1,4 +1,4 @@
<ion-view id="view-confirm" hide-tabs> <ion-view id="txp-details" hide-tabs>
<ion-nav-bar class="bar-royal"> <ion-nav-bar class="bar-royal">
<ion-nav-title> <ion-nav-title>
{{title}} {{title}}

View file

@ -140,7 +140,7 @@
</button> </button>
</div> </div>
<div ng-show="!updateStatusError && wallet.balanceHidden" on-hold="hideToggle()"> <div ng-show="!updateStatusError && wallet.balanceHidden" ng-style="{'transform': amountScale}" on-hold="hideToggle()">
<strong class="size-24" translate>[Balance Hidden]</strong> <strong class="size-24" translate>[Balance Hidden]</strong>
<div class="size-14" translate> <div class="size-14" translate>
Tap and hold to show Tap and hold to show
@ -273,7 +273,7 @@
<div> <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 | amTimeAgo}}</time>
<time class="wallet-details__tx-time" ng-if="btx.time && !createdWithinPastDay(btx.time)"> <time class="wallet-details__tx-time" ng-if="btx.time && !createdWithinPastDay(btx.time)">
{{btx.time * 1000 | amDateFormat:'MMM d, YYYY'}} {{btx.time * 1000 | amDateFormat:'MMM D, YYYY'}}
</time> </time>
</div> </div>
</span> </span>