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,
},
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: {
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: {
@ -74,13 +74,9 @@ module.exports = function(grunt) {
grunt.log.writeln('Waiting for more changes...');
},
},
css: {
files: ['src/css/*.css'],
tasks: ['concat:css']
},
sass: {
files: ['src/sass/**/**/*.scss'],
tasks: ['sass', 'concat:css']
tasks: ['sass']
},
main: {
files: [
@ -104,8 +100,9 @@ module.exports = function(grunt) {
},
files: [{
expand: true,
flatten: true,
src: ['src/sass/main.scss'],
dest: './',
dest: 'www/css/',
ext: '.css'
}]
}
@ -118,6 +115,7 @@ module.exports = function(grunt) {
angular: {
src: [
'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/angular-moment/angular-moment.js',
'bower_components/ng-lodash/build/ng-lodash.js',
@ -132,7 +130,7 @@ module.exports = function(grunt) {
'angular-bitauth/angular-bitauth.js',
'angular-bitcore-wallet-client/angular-bitcore-wallet-client.js'
],
dest: 'www/lib/angular.js'
dest: 'www/lib/angular-components.js'
},
js: {
src: [
@ -152,11 +150,7 @@ module.exports = function(grunt) {
'node_modules/bezier-easing/dist/bezier-easing.min.js',
'node_modules/cordova-plugin-qrscanner/dist/cordova-plugin-qrscanner-lib.min.js'
],
dest: 'www/js/copay.js'
},
css: {
src: ['src/sass/*.css', 'src/css/*.css'],
dest: 'www/css/copay.css'
dest: 'www/js/app.js'
}
},
uglify: {
@ -165,8 +159,8 @@ module.exports = function(grunt) {
},
prod: {
files: {
'www/js/copay.js': ['www/js/copay.js'],
'www/lib/angular.js': ['www/lib/angular.js']
'www/js/app.js': ['www/js/app.js'],
'www/lib/angular-components.js': ['www/lib/angular-components.js']
}
}
},

View File

@ -22,7 +22,7 @@
"pushSenderId": "1036948132229",
"description": "Secure Bitcoin Wallet",
"version": "1.2.1",
"androidVersion": "12100",
"androidVersion": "121000",
"_extraCSS": null,
"_enabledExtensions": {
"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="msapplication-tap-highlight" content="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>
<link rel="shortcut icon" href="img/app/favicon.ico">
</head>
@ -25,11 +25,11 @@
</ion-nav-view>
<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 src="js/copay.js"></script>
<script src="js/app.js"></script>
</body>
</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.
- Wallet should be recreated and access to funds should be restored.
(Using WD)
- Enter the WD at 'Import Wallet'
(Using WB)
- Enter the WB at 'Import Wallet'
- Wallet should be recreated and access to funds should be restored.
### Multisig wallets
Case 1: From both WS and WD, full recovery is possible.
- Enter WS or WD at 'Import wallet' in a new device.
Case 1: From both WS and WB, full recovery is possible.
- Enter WS or WB at 'Import wallet' in a new device.
- 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).
@ -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).
- Wallet should be recreated and access to funds should be restored.
B) One WD and a quorum of WS of the other members.
- Using the WD, import the wallet.
B) One WB and a quorum of WS of the other members.
- Using the WB, import the wallet.
- Ask other copayers to import the wallet using their WS.
- 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

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': ''
};
$scope.onQrCodeScanned = function(data, addressbookForm) {
$scope.onQrCodeScannedAddressBook = function(data, addressbookForm) {
$timeout(function() {
var form = addressbookForm;
if (data && form) {

View File

@ -1,9 +1,8 @@
'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 BALANCE_ADDRESS_LIMIT = 5;
var MENU_ITEM_HEIGHT = 55;
var config;
var unitName;
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() {
$timeout(function() {
$scope.showInfo = !$scope.showInfo;
@ -114,36 +120,13 @@ angular.module('copayApp.controllers').controller('addressesController', functio
}, 10);
};
$scope.showMenu = function(allAddresses, $event) {
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() {
$scope.scan = function() {
walletService.startScan($scope.wallet);
$scope.menu.hide();
$ionicHistory.clearHistory();
$state.go('tabs.home');
};
var sendByEmail = function() {
$scope.sendByEmail = function() {
function formatDate(ts) {
var dateObj = new Date(ts * 1000);
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() {
var opts = {
wallet: {

View File

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

View File

@ -1,13 +1,12 @@
'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 satToUnit;
var unitDecimals;
var satToBtc;
var SMALL_FONT_SIZE_LIMIT = 10;
var LENGTH_EXPRESSION_LIMIT = 19;
var MENU_ITEM_HEIGHT = 55;
$scope.$on('$ionicView.leave', function() {
angular.element($window).off('keydown');
@ -21,7 +20,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.glideraAccessToken = data.stateParams.glideraAccessToken;
$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';
$scope.isWallet = (isWallet.toString().trim().toLowerCase() == 'true' ? true : false);
$scope.toAddress = data.stateParams.toAddress;
@ -29,6 +28,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
$scope.toEmail = data.stateParams.toEmail;
$scope.showAlternativeAmount = !!$scope.cardId || !!$scope.isGiftCard || !!$scope.isGlidera;
$scope.toColor = data.stateParams.toColor;
$scope.showSendMax = false;
$scope.customAmount = data.stateParams.customAmount;
@ -71,7 +71,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
var config = configService.getSync().wallet.settings;
$scope.unitName = config.unitName;
$scope.alternativeIsoCode = config.alternativeIsoCode;
$scope.alternativeIsoCode = !!$scope.cardId || !!$scope.isGiftCard ? 'USD' : config.alternativeIsoCode;
$scope.specificAmount = $scope.specificAlternativeAmount = '';
$scope.isCordova = platformInfo.isCordova;
unitToSatoshi = config.unitToSatoshi;
@ -93,25 +93,12 @@ angular.module('copayApp.controllers').controller('amountController', function($
}, 10);
});
$scope.showSendMaxMenu = function($event) {
var sendMaxObj = {
text: gettextCatalog.getString('Send max amount'),
action: setSendMax,
$scope.showSendMaxMenu = function() {
$scope.showSendMax = true;
};
$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.menu.hide();
$scope.sendMax = function() {
$scope.showSendMax = false;
$state.transitionTo('tabs.send.confirm', {
isWallet: $scope.isWallet,
toAmount: null,
@ -205,11 +192,11 @@ angular.module('copayApp.controllers').controller('amountController', function($
};
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) {
return parseFloat((rateService.toFiat(val * unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2), 10);
return parseFloat((rateService.toFiat(val * unitToSatoshi, $scope.alternativeIsoCode)).toFixed(2));
};
function evaluate(val) {
@ -283,6 +270,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
}
var stateParams = {
cardId: $scope.cardId,
cardAmountUSD: amountUSD,
toName: $scope.toName,
toAmount: payProDetails.amount,
toAddress: payProDetails.toAddress,
@ -303,7 +291,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
try {
uuid = profileService.getWallets({
onlyComplete: true,
network: 'livenet',
network: amazonService.getEnvironment(),
})[0].id;
} catch (err) {
ongoingProcess.set('Preparing transaction...', false);

View File

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

View File

@ -1,10 +1,10 @@
'use strict';
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 appUrl = $window.appConfig.url;
var appName = appConfigService.userVisibleName;
var appUrl = appConfigService.url;
$scope.isCordova = platformInfo.isCordova;
$scope.$on("$ionicView.beforeEnter", function(event, data) {

View File

@ -1,7 +1,7 @@
'use strict';
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 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) {
seedOptions.push({
id: 'ledger',

View File

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

View File

@ -1,7 +1,7 @@
'use strict';
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);
$scope.showAdvChange = function() {
@ -191,7 +191,7 @@ angular.module('copayApp.controllers').controller('exportController',
if ($scope.formData.noSignEnabled)
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 {}';
window.plugins.socialsharing.shareViaEmail(
body,

View File

@ -1,6 +1,6 @@
'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) {
@ -42,6 +42,7 @@ angular.module('copayApp.controllers').controller('sendController', function($sc
};
$scope.$on("$ionicView.beforeEnter", function(event, data) {
$scope.isCordova = platformInfo.isCordova;
$scope.score = (data.stateParams && data.stateParams.score) ? parseInt(data.stateParams.score) : null;
$scope.feedback = {};

View File

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

View File

@ -1,7 +1,7 @@
'use strict';
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 isDevel = platformInfo.isDevel;
@ -17,7 +17,7 @@ angular.module('copayApp.controllers').controller('importController',
$scope.formData.derivationPath = derivationPathHelper.default;
$scope.formData.account = 1;
$scope.importErr = false;
$scope.showHardwareWallet = $window.appConfig.name == 'copay';
$scope.showHardwareWallet = appConfigService.name == 'copay';
if ($stateParams.code)
$scope.processWalletInfo($stateParams.code);
@ -238,6 +238,7 @@ angular.module('copayApp.controllers').controller('importController',
if (!words) {
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Please enter the recovery phrase'));
return;
} else if (words.indexOf('xprv') == 0 || words.indexOf('tprv') == 0) {
return _importExtendedPrivateKey(words, opts);
} else if (words.indexOf('xpub') == 0 || words.indexOf('tpuv') == 0) {

View File

@ -1,7 +1,7 @@
'use strict';
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 isDevel = platformInfo.isDevel;
@ -33,7 +33,7 @@ angular.module('copayApp.controllers').controller('joinController',
}
};
this.onQrCodeScanned = function(data) {
this.onQrCodeScannedJoin = function(data) {
$scope.secret = data;
if ($scope.joinForm) {
$scope.joinForm.secret.$setViewValue(data);
@ -44,7 +44,7 @@ angular.module('copayApp.controllers').controller('joinController',
if ($stateParams.url) {
var data = $stateParams.url;
data = data.replace('copay:', '');
this.onQrCodeScanned(data);
this.onQrCodeScannedJoin(data);
}
var updateSeedSourceSelect = function() {
@ -63,7 +63,7 @@ angular.module('copayApp.controllers').controller('joinController',
*/
if ($window.appConfig.name == 'copay') {
if (appConfigService.name == 'copay') {
if (isChromeApp) {
self.seedOptions.push({
id: 'ledger',

View File

@ -1,18 +1,22 @@
'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() {
ongoingProcess.set('Canceling gift card...', true);
ongoingProcess.set('cancelingGiftCard', true);
amazonService.cancelGiftCard($scope.card, function(err, data) {
ongoingProcess.set('Canceling gift card...', false);
ongoingProcess.set('cancelingGiftCard', false);
if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
popupService.showAlert('Error', bwcError.msg(err));
return;
}
$scope.card.cardStatus = data.cardStatus;
$timeout(function() {
$ionicScrollDelegate.resize();
$ionicScrollDelegate.scrollTop();
}, 10);
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, {
remove: true
}, function(err) {
$scope.$emit('UpdateAmazonList');
$scope.cancel();
});
};
$scope.refreshGiftCard = function() {
ongoingProcess.set('updatingGiftCard', true);
amazonService.getPendingGiftCards(function(err, gcds) {
if (lodash.isEmpty(gcds)) {
$timeout(function() {
ongoingProcess.set('updatingGiftCard', false);
}, 1000);
}
if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), err);
popupService.showAlert('Error', err);
return;
}
var index = 0;
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) {
$log.debug("creating gift card");
amazonService.createGiftCard(dataFromStorage, function(err, giftCard) {
if (err) {
popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err));
popupService.showAlert('Error', bwcError.msg(err));
return;
}
if (!lodash.isEmpty(giftCard)) {
@ -46,7 +61,6 @@ angular.module('copayApp.controllers').controller('amazonCardDetailsController',
amazonService.savePendingGiftCard(newData, null, function(err) {
$log.debug("Saving new gift card");
$scope.card = newData;
$scope.$emit('UpdateAmazonList');
$timeout(function() {
$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() {
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 okText = gettextCatalog.getString('I understand');
var cancelText = gettextCatalog.getString('Go back');
popupService.showConfirm(title, message, okText, cancelText, function(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 okText = gettextCatalog.getString('Yes, skip backup');
var okText = gettextCatalog.getString('Yes, skip');
var cancelText = gettextCatalog.getString('Go back');
popupService.showConfirm(title, message, okText, cancelText, function(val) {
if (val) {

View File

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

View File

@ -1,6 +1,6 @@
'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.confirm = function() {
@ -15,10 +15,10 @@ angular.module('copayApp.controllers').controller('termsController', function($s
};
$scope.openExternalLink = function() {
var url = $window.appConfig.disclaimerUrl;
var url = appConfigService.disclaimerUrl;
var optIn = true;
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 cancelText = gettextCatalog.getString('Go Back');
externalLinkService.open(url, optIn, title, message, okText, cancelText);

View File

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

View File

@ -1,14 +1,14 @@
'use strict';
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.commitHash = $window.commitHash;
$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 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.');

View File

@ -1,14 +1,14 @@
'use strict';
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;
var wallet = profileService.getWallet($stateParams.walletId);
var walletId = wallet.credentials.walletId;
var defaults = configService.getDefaults();
var config = configService.getSync();
$scope.appName = $window.appConfig.nameCase;
$scope.appName = appConfigService.nameCase;
$scope.bwsurl = {
value: (config.bwsFor && config.bwsFor[walletId]) || defaults.bws.url
};

View File

@ -1,11 +1,11 @@
'use strict';
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.csvReady = false;
$scope.isCordova = platformInfo.isCordova;
$scope.appName = $window.appConfig.nameCase;
$scope.appName = appConfigService.nameCase;
$scope.csvHistory = function(cb) {
var allTxs = [];

View File

@ -1,9 +1,9 @@
'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 config = configService.getSync();
$scope.appName = $window.appConfig.nameCase;
$scope.appName = appConfigService.nameCase;
$scope.PNEnabledByUser = true;
$scope.usePushNotifications = platformInfo.isCordova && !platformInfo.isWP;
$scope.isIOSApp = platformInfo.isIOS && platformInfo.isCordova;

View File

@ -1,14 +1,14 @@
'use strict';
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 listeners = [];
var notifications = [];
$scope.externalServices = {};
$scope.openTxpModal = txpModalService.open;
$scope.version = $window.version;
$scope.name = $window.appConfig.nameCase;
$scope.name = appConfigService.nameCase;
$scope.homeTip = $stateParams.fromOnboarding;
$scope.isCordova = platformInfo.isCordova;
$scope.isAndroid = platformInfo.isAndroid;
@ -43,7 +43,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
} else {
var feedbackInfo = JSON.parse(info);
//Check if current version is greater than saved version
var currentVersion = window.version;
var currentVersion = $scope.version;
var savedVersion = feedbackInfo.version;
var isVersionUpdated = feedbackService.isVersionUpdated(currentVersion, savedVersion);
if (!isVersionUpdated) {
@ -62,7 +62,7 @@ angular.module('copayApp.controllers').controller('tabHomeController',
function initFeedBackInfo() {
var feedbackInfo = {};
feedbackInfo.time = moment().unix();
feedbackInfo.version = window.version;
feedbackInfo.version = $scope.version;
feedbackInfo.sent = false;
storageService.setFeedbackInfo(JSON.stringify(feedbackInfo), function() {
$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) {
var listeners = [];
var MENU_ITEM_HEIGHT = 55;
$scope.isCordova = platformInfo.isCordova;
$scope.isNW = platformInfo.isNW;
$scope.walletAddrs = {};
@ -50,8 +49,9 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
};
$scope.showAddresses = function() {
$state.transitionTo('tabs.receive.addresses', {
walletId: $scope.wallet.credentials.walletId
$state.go('tabs.receive.addresses', {
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.wallets = profileService.getWallets();

View File

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

View File

@ -1,6 +1,6 @@
'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 isCordova = platformInfo.isCordova;
@ -10,7 +10,7 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
$scope.usePushNotifications = isCordova && !isWP;
$scope.isCordova = isCordova;
$scope.appName = $window.appConfig.nameCase;
$scope.appName = appConfigService.nameCase;
$scope.currentLanguageName = uxLanguage.getCurrentLanguageName();
$scope.feeOpts = feeService.feeOpts;
$scope.currentFeeLevel = feeService.getCurrentFeeLevel();
@ -50,7 +50,7 @@ angular.module('copayApp.controllers').controller('tabSettingsController', funct
var url = 'https://help.bitpay.com/bitpay-app';
var optIn = true;
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 cancelText = gettextCatalog.getString('Go Back');
externalLinkService.open(url, optIn, title, message, okText, cancelText);

View File

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

View File

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

View File

@ -8,7 +8,9 @@ angular.module('copayApp.directives')
transclude: true,
scope: {
sendStatus: '=clickSendStatus',
wallet: '=hasWalletChosen'
hasWalletChosen: '=hasWalletChosen',
insufficientFunds: '=insufficientFunds',
noMatchingWallet: '=noMatchingWallet'
},
link: function(scope, element, attrs) {
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', {
url: '/addresses/:walletId',
url: '/addresses/:walletId/:toAddress',
views: {
'tab-receive@tabs': {
controller: 'addressesController',
@ -1031,7 +1031,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
}
})
.state('tabs.bitpayCard.confirm', {
url: '/confirm/:cardId/:toAddress/:toName/:toAmount/:toEmail/:description',
url: '/confirm/:cardId/:cardAmountUSD/:toAddress/:toName/:toAmount/:toEmail/:description',
views: {
'tab-home@tabs': {
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();
@ -1171,7 +1171,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr
type: "menubar"
});
try {
nativeMenuBar.createMacBuiltin($window.appConfig.nameCase);
nativeMenuBar.createMacBuiltin(appConfigService.nameCase);
} catch (e) {
$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';
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 = {};
@ -80,7 +80,7 @@ angular.module('copayApp.services')
var walletName = (wallet.alias || '') + (wallet.alias ? '-' : '') + wallet.credentials.walletName;
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)
};
return root;

View File

@ -1,6 +1,6 @@
'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 = {};
@ -121,17 +121,17 @@ angular.module('copayApp.services').factory('incomingData', function($log, $stat
} else {
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', {
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', {
url: data
});
// BitPay Authentication
} else if (data && data.indexOf($window.appConfig.name + '://') === 0) {
// BitPayCard Authentication
} else if (data && data.indexOf(appConfigService.name + '://') === 0) {
var secret = getParameterByName('secret', data);
var email = getParameterByName('email', data);
var otp = getParameterByName('otp', data);

View File

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

View File

@ -39,7 +39,11 @@ angular.module('copayApp.services').factory('ongoingProcess', function($log, $ti
'sendingByEmail': gettext('Preparing addresses...'),
'sending2faCode': gettext('Sending 2FA code...'),
'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() {

View File

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

View File

@ -1,6 +1,6 @@
'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 = {};
root.Utils = bwcService.getUtils();
@ -48,10 +48,11 @@ angular.module('copayApp.services').factory('txFormatService', function(bwcServi
var config = configService.getSync().wallet.settings;
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;
return v1.toFixed(2) + ' ' + config.alternativeIsoCode;
return v1 + ' ' + config.alternativeIsoCode;
};
// Async version

View File

@ -12,23 +12,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
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) {
$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));
$rootScope.$emit('Local/TxAction', wallet.id);
var type = root.getViewStatus(wallet, broadcastedTxp);
if (!customStatusHandler) {
root.openStatusModal(type, broadcastedTxp, function() {});
}
return cb(null, broadcastedTxp);
});
} else {
$rootScope.$emit('Local/TxAction', wallet.id);
var type = root.getViewStatus(wallet, signedTxp);
if (!customStatusHandler) {
root.openStatusModal(type, signedTxp, function() {});
}
return cb(null, signedTxp);
}
});
@ -1053,38 +1023,6 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim
} 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) {
opts = opts || {};
wallet.getSendMaxInfo(opts, function(err, res) {

View File

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

View File

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

View File

@ -14,9 +14,43 @@
padding: 0 10px;
font-size: 24px;
cursor: pointer;
line-height: 155px;
}
.icon {
&.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;
}
.qr-icon {
line-height: 45px;
}
}
#view-address-book {

View File

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

View File

@ -1,4 +1,5 @@
#view-confirm {
background-color: #ffffff;
@extend .deflash-blue;
.icon-amazon {
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;
font-size: 24px;
cursor: pointer;
}
.qr-icon {
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 .checkbox-icon:before {
padding: 1.1rem;
padding: 1.2rem;
position: relative;
background:url("../img/onboarding-checkbox-unchecked.svg") top center no-repeat;
}

View File

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

View File

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

View File

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

View File

@ -17,7 +17,7 @@
<img src="img/address-book-add.svg"/>
</i>
<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">
<button class="button button-standard button-primary" ui-sref="tabs.addressbook.add" translate>Add Contact</button>
</div>

View File

@ -3,11 +3,6 @@
<ion-nav-title>{{'Wallet Addresses' | translate}}</ion-nav-title>
<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-content>
@ -31,6 +26,17 @@
</div>
<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()">
<span translate>Unused Addresses</span>
<i class="icon ion-ios-plus-empty"></i>
@ -61,11 +67,6 @@
<div class="addr-balance">{{w.balanceStr}}</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>
</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>
</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>
</ion-content>
</ion-view>

View File

@ -3,17 +3,20 @@
<ion-nav-title>{{'All Addresses' | translate}}</ion-nav-title>
<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-content>
<div class="addr-list list">
<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">
{{a.address}}
<div class="addr-path" ng-if="!a.balanceStr">

View File

@ -6,7 +6,7 @@
<ion-nav-back-button>
</ion-nav-back-button>
<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>
</button>
</ion-nav-buttons>
@ -120,4 +120,8 @@
</div>
</div>
</ion-content>
<item-selector
item-selector-show="showSendMax"
item-selector-on-select="sendMax">
</item-selector>
</ion-view>

View File

@ -12,7 +12,7 @@
<div class="onboarding-illustration-backup-warning"></div>
<div id="cta-buttons">
<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>
</ion-content>
</ion-view>

View File

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

View File

@ -10,7 +10,7 @@
</button>
</ion-nav-buttons>
<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
</button>
</ion-nav-buttons>
@ -40,7 +40,7 @@
</div>
<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>
<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
</button>
</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-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-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>

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">
<ng-transclude></ng-transclude>
</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">
<span class="input-label" translate>Wallet Invitation</span>
<div class="input-notification">
<i class="icon ion-checkmark-circled balanced"
ng-show="!joinForm.secret.$invalid"></i>
<i class="icon ion-close-circled assertive"
ng-show="joinForm.secret.$invalid && secret"></i>
<i ng-show="!joinForm.secret.$invalid" class="icon ion-checkmark-circled valid"></i>
<i ng-show="joinForm.secret.$invalid && secret" class="icon ion-close-circled invalid"></i>
</div>
<input id="secret"
type="text"
@ -38,7 +36,7 @@
wallet-secret required>
</label>
<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 class="item item-divider"></div>

View File

@ -1,37 +1,37 @@
<ion-modal-view ng-controller="payproController">
<ion-header-bar align-title="center" class="bar-royal" ng-style="{'background-color': color, 'border-color': color}">
<button class="button button-clear" ng-click="cancel()">
<ion-modal-view id="view-confirm">
<ion-header-bar align-title="center" class="bar-royal">
<button class="button button-back button-clear" ng-click="cancel()">
{{'Close' | translate}}
</button>
<div class="title" translate>
Payment request
</div>
<h1 class="title" translate>Payment request</h1>
</ion-header-bar>
<ion-content>
<div class="header-modal text-center size-42">
{{amountStr}}
</div>
<div class="list">
<div class="item item-divider" translate>
Details
<div class="item head">
<div class="amount-label">
<div class="amount">{{displayAmount || '...'}} <span class="unit">{{displayUnit}}</span></div>
<div class="alternative">{{alternativeAmountStr || '...'}}</div>
</div>
<div class="item">
{{'Pay To'|translate}}
<span class="item-note">{{paypro.domain}}</span>
</div>
<div class="item" ng-if="paypro.toAddress">
{{'Address'|translate}}
<span class="item-note">{{paypro.toAddress}}</span>
</div>
<div class="item">
{{'Certified by'|translate}}
<div class="info">
<div class="item single-line" ng-if="paypro.domain">
<span class="label">{{'Pay To'|translate}}</span>
<span class="item-note">
{{paypro.domain}}
</span>
</div>
<div class="item single-line" ng-if="paypro.toAddress">
<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}}<br>
<span translate>(Trusted)</span>
{{paypro.caName}} {{'(Trusted)' | translate}}</span>
</span>
<span ng-show="!paypro.caTrusted">
<span ng-show="paypro.selfSigned">
@ -45,12 +45,17 @@
</span>
</div>
<div class="item" ng-if="paypro.memo">
{{'Memo'|translate}}
<span class="item-note wrapword">{{paypro.memo}}</span>
<span class="label">{{'Memo'|translate}}</span>
<span class="item-note w100p">
{{paypro.memo}}
</span>
</div>
<div class="item single-line" ng-if="paypro.expires">
<span class="label">{{'Expires'|translate}}</span>
<span class="item-note">
{{paypro.expires * 1000 | amTimeAgo }}
</span>
</div>
<div class="item" ng-if="paypro.expires">
{{'Expires'|translate}}
<span class="item-note">{{paypro.expires * 1000 | amTimeAgo }}</span>
</div>
</div>
</ion-content>

View File

@ -9,7 +9,7 @@
<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>
<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>
</ion-content>
</ion-view>

View File

@ -1,5 +1,5 @@
<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-title></ion-nav-title>
<ion-nav-buttons side="primary">

View File

@ -1,6 +1,5 @@
<ion-view id="onboard-welcome" class="onboarding">
<ion-content ng-controller="welcomeController" ng-init="createProfile()" scroll="false">
<!-- <qr-scanner id="qrcode" on-scan="goImport(data)"></qr-scanner> -->
<div id="logo-tagline">
<img src='img/bitpay-logo.svg' id="logo" />
<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-on-confirm="onSuccessConfirm()"
slide-success-hide-on-confirm="true">
<span translate>Founds transferred</span>
<span translate>Funds transferred</span>
</slide-to-accept-success>
</ion-content>
</ion-view>

View File

@ -17,8 +17,7 @@
</div>
<div class="settings-explanation">
<div class="settings-description" translate>
{{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).
{{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).
</div>
</div>
<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">
<img src="img/icon-wallet.svg" class="bg wallet icon-create-wallet"/>
</i>
<span translate>Create a bitcoin wallet</span>
<span translate>Create bitcoin wallet</span>
<i class="icon bp-arrow-right"></i>
</a>
<a ng-repeat="wallet in wallets track by $index"

View File

@ -1,11 +1,6 @@
<ion-view id="tab-receive">
<ion-nav-bar class="bar-royal">
<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-content scroll="false">
<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-title>
{{title}}

View File

@ -140,7 +140,7 @@
</button>
</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>
<div class="size-14" translate>
Tap and hold to show
@ -273,7 +273,7 @@
<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 | amDateFormat:'MMM d, YYYY'}}
{{btx.time * 1000 | amDateFormat:'MMM D, YYYY'}}
</time>
</div>
</span>