Merge sprint 19.
# Conflicts: # src/js/controllers/tab-home.js
This commit is contained in:
commit
0bb4de9bd1
49 changed files with 4115 additions and 3815 deletions
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification, externalLinkService, firebaseEventsService) {
|
||||
angular.module('copayApp.controllers').controller('confirmController', function($rootScope, $scope, $interval, $filter, $timeout, $ionicScrollDelegate, gettextCatalog, walletService, platformInfo, lodash, configService, $stateParams, $window, $state, $log, profileService, bitcore, bitcoreCash, txFormatService, ongoingProcess, $ionicModal, popupService, $ionicHistory, $ionicConfig, payproService, feeService, bwcError, txConfirmNotification, externalLinkService, firebaseEventsService, soundService) {
|
||||
|
||||
var countDown = null;
|
||||
var FEE_TOO_HIGH_LIMIT_PER = 15;
|
||||
|
|
@ -287,7 +287,10 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
tx.amountValueStr = tx.amountStr.split(' ')[0];
|
||||
tx.amountUnitStr = tx.amountStr.split(' ')[1];
|
||||
txFormatService.formatAlternativeStr(wallet.coin, tx.toAmount, function(v) {
|
||||
var parts = v.split(' ');
|
||||
tx.alternativeAmountStr = v;
|
||||
tx.alternativeAmountValueStr = parts[0];
|
||||
tx.alternativeAmountUnitStr = (parts.length > 0) ? parts[1] : '';
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -426,6 +429,8 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
|
||||
|
||||
function showSendMaxWarning(wallet, sendMaxInfo) {
|
||||
var feeAlternative = '',
|
||||
msg = '';
|
||||
|
||||
function verifyExcludedUtxos() {
|
||||
var warningMsg = [];
|
||||
|
|
@ -443,9 +448,18 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
return warningMsg.join('\n');
|
||||
};
|
||||
|
||||
var msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees.", {
|
||||
fee: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.fee)
|
||||
});
|
||||
feeAlternative = txFormatService.formatAlternativeStr(wallet.coin, sendMaxInfo.fee);
|
||||
if (feeAlternative) {
|
||||
msg = gettextCatalog.getString("{{feeAlternative}} will be deducted for bitcoin networking fees ({{fee}}).", {
|
||||
fee: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.fee),
|
||||
feeAlternative: feeAlternative
|
||||
});
|
||||
} else {
|
||||
msg = gettextCatalog.getString("{{fee}} will be deducted for bitcoin networking fees).", {
|
||||
fee: txFormatService.formatAmountStr(wallet.coin, sendMaxInfo.fee)
|
||||
});
|
||||
}
|
||||
|
||||
var warningMsg = verifyExcludedUtxos();
|
||||
|
||||
if (!lodash.isEmpty(warningMsg))
|
||||
|
|
@ -624,10 +638,11 @@ angular.module('copayApp.controllers').controller('confirmController', function(
|
|||
(processName == 'sendingTx' && !$scope.wallet.canSign() && !$scope.wallet.isPrivKeyExternal())
|
||||
) && !isOn) {
|
||||
$scope.sendStatus = 'success';
|
||||
if (config.soundsEnabled && $scope.wallet.coin == 'bch') {
|
||||
var audio = new Audio('misc/bch_sent.mp3');
|
||||
audio.play();
|
||||
|
||||
if ($state.current.name === "tabs.send.confirm") { // XX SP: Otherwise all open wallets on other devices play this sound if you have been in a send flow before on that device.
|
||||
soundService.play('misc/payment_sent.mp3');
|
||||
}
|
||||
|
||||
firebaseEventsService.logEvent('sent_bitcoin', { coin: $scope.wallet.coin });
|
||||
$timeout(function() {
|
||||
$scope.$digest();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('tabHomeController',
|
||||
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, startupService, addressbookService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService, pushNotificationsService, timeService, bitcoincomService, pricechartService, firebaseEventsService, servicesService, shapeshiftService, $ionicNavBarDelegate, signVerifyMessageService) {
|
||||
function($rootScope, $timeout, $scope, $state, $stateParams, $ionicModal, $ionicScrollDelegate, $window, gettextCatalog, lodash, popupService, ongoingProcess, bannerService, externalLinkService, latestReleaseService, profileService, walletService, configService, $log, platformInfo, storageService, txpModalService, appConfigService, startupService, addressbookService, feedbackService, bwcError, nextStepsService, buyAndSellService, homeIntegrationsService, bitpayCardService, pushNotificationsService, timeService, bitcoincomService, pricechartService, firebaseEventsService, servicesService, shapeshiftService, $ionicNavBarDelegate, signVerifyMessageService) {
|
||||
var wallet;
|
||||
var listeners = [];
|
||||
var notifications = [];
|
||||
|
|
@ -15,9 +15,19 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
$scope.isWindowsPhoneApp = platformInfo.isCordova && platformInfo.isWP;
|
||||
$scope.isNW = platformInfo.isNW;
|
||||
$scope.showServices = false;
|
||||
$scope.bannerIsLoading = true;
|
||||
$scope.bannerImageUrl = '';
|
||||
$scope.bannerUrl = '';
|
||||
|
||||
|
||||
$scope.$on("$ionicView.afterEnter", function() {
|
||||
startupService.ready();
|
||||
|
||||
bannerService.getBanner(function (banner) {
|
||||
$scope.bannerImageUrl = banner.imageURL;
|
||||
$scope.bannerUrl = banner.url;
|
||||
$scope.bannerIsLoading = false;
|
||||
});
|
||||
});
|
||||
|
||||
$scope.$on("$ionicView.beforeEnter", function(event, data) {
|
||||
|
|
@ -117,8 +127,8 @@ angular.module('copayApp.controllers').controller('tabHomeController',
|
|||
externalLinkService.open(url, optIn, title, message, okText, cancelText);
|
||||
};
|
||||
|
||||
$scope.openStore = function() {
|
||||
externalLinkService.open('https://store.bitcoin.com/', false);
|
||||
$scope.openBannerUrl = function() {
|
||||
externalLinkService.open($scope.bannerUrl, false);
|
||||
};
|
||||
|
||||
$scope.openNotificationModal = function(n) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, txFormatService) {
|
||||
angular.module('copayApp.controllers').controller('tabReceiveController', function($rootScope, $scope, $timeout, $log, $ionicModal, $state, $ionicHistory, $ionicPopover, storageService, platformInfo, walletService, profileService, configService, lodash, gettextCatalog, popupService, bwcError, bitcoinCashJsService, $ionicNavBarDelegate, txFormatService, soundService, clipboardService) {
|
||||
|
||||
var listeners = [];
|
||||
$scope.bchAddressType = { type: 'cashaddr' };
|
||||
|
|
@ -15,22 +15,6 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
|||
|
||||
var config;
|
||||
|
||||
var soundLoaded = false;
|
||||
var nativeAudioAvailable = (window.plugins && window.plugins.NativeAudio);
|
||||
|
||||
if (nativeAudioAvailable) {
|
||||
window.plugins.NativeAudio.preloadSimple('received', 'misc/coin_received.mp3', function (msg) {
|
||||
$log.debug('Receive sound loaded.');
|
||||
soundLoaded = true;
|
||||
}, function (error) {
|
||||
$log.debug('Error loading receive sound.');
|
||||
$log.debug(error);
|
||||
});
|
||||
} else {
|
||||
$log.debug('isNW: Using HTML5-Audio instead of native audio');
|
||||
soundLoaded = true;
|
||||
}
|
||||
|
||||
$scope.displayBalanceAsFiat = true;
|
||||
|
||||
$scope.requestSpecificAmount = function() {
|
||||
|
|
@ -74,6 +58,12 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
|||
paymentSubscriptionObj.addr = $scope.addr
|
||||
}
|
||||
|
||||
try {
|
||||
clipboardService.copyToClipboard($scope.wallet.coin == 'bch' && $scope.bchAddressType.type == 'cashaddr' ? 'bitcoincash:' + $scope.addr : $scope.addr);
|
||||
} catch (error) {
|
||||
$log.debug("Error copying to clipboard:");
|
||||
$log.debug(error);
|
||||
}
|
||||
// create subscription
|
||||
var msg = JSON.stringify(paymentSubscriptionObj);
|
||||
currentAddressSocket.onopen = function (event) {
|
||||
|
|
@ -143,21 +133,21 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
|
|||
for (var i = 0; i < data.x.out.length; i++) {
|
||||
if (data.x.out[i].addr == watchAddress) {
|
||||
$scope.paymentReceivedAmount = txFormatService.formatAmount(data.x.out[i].value, 'full');
|
||||
$scope.paymentReceivedAlternativeAmount = ''; // For when a subsequent payment is received.
|
||||
txFormatService.formatAlternativeStr($scope.wallet.coin, data.x.out[i].value, function(alternativeStr){
|
||||
if (alternativeStr) {
|
||||
$scope.paymentReceivedAlternativeAmount = alternativeStr;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
$scope.paymentReceivedCoin = $scope.wallet.coin;
|
||||
$scope.$apply(function () {
|
||||
|
||||
if (config.soundsEnabled && soundLoaded) {
|
||||
$log.debug('Play sound.');
|
||||
if (nativeAudioAvailable) {
|
||||
window.plugins.NativeAudio.play('received');
|
||||
} else {
|
||||
new Audio('misc/coin_received.ogg').play(); // NW.js has no mp3 support
|
||||
}
|
||||
} else {
|
||||
$log.debug('Sound is disabled.');
|
||||
}
|
||||
if ($state.current.name === "tabs.receive") {
|
||||
soundService.play('misc/payment_received.mp3');
|
||||
}
|
||||
|
||||
$scope.$apply(function () {
|
||||
$scope.showingPaymentReceived = true;
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,8 +122,11 @@ angular.module('copayApp.controllers').controller('tabScanController', function(
|
|||
scannerService.openSettings();
|
||||
};
|
||||
|
||||
$scope.reactivationCount = 0;
|
||||
$scope.attemptToReactivate = function(){
|
||||
scannerService.reinitialize();
|
||||
scannerService.reinitialize(function(){
|
||||
$scope.reactivationCount++;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.toggleLight = function(){
|
||||
|
|
|
|||
|
|
@ -76,8 +76,11 @@ angular.module('copayApp.controllers').controller('tabSendController', function(
|
|||
var walletList = [];
|
||||
lodash.each(walletsToTransfer, function(v) {
|
||||
var displayBalanceAsFiat =
|
||||
v.status.alternativeBalanceAvailable &&
|
||||
config.wallet.settings.priceDisplay === 'fiat';
|
||||
// BD got v.status as undefined here once during development, just
|
||||
// after creating a new wallet.
|
||||
v.status &&
|
||||
v.status.alternativeBalanceAvailable &&
|
||||
config.wallet.settings.priceDisplay === 'fiat';
|
||||
|
||||
walletList.push({
|
||||
color: v.color,
|
||||
|
|
|
|||
15
src/js/decorators/displayLogDebug.js
Normal file
15
src/js/decorators/displayLogDebug.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
angular.module('copayApp')
|
||||
.config(['$provide', '$logProvider', function($provide, $logProvider) {
|
||||
// expose a provider to reach debugEnabled in $log
|
||||
$provide.value('$logProvider', $logProvider);
|
||||
}])
|
||||
.decorator('$log', ['$logProvider', '$delegate', function($logProvider, $delegate) {
|
||||
// override $log.debug to display in Chrome
|
||||
$delegate.debug = function () {
|
||||
if ($logProvider.debugEnabled()) {
|
||||
$delegate.info.apply($delegate, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
return $delegate;
|
||||
}]);
|
||||
|
|
@ -1,38 +1,26 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.directives')
|
||||
.directive('copyToClipboard', function(platformInfo, nodeWebkitService, gettextCatalog, ionicToast, clipboard) {
|
||||
.directive('copyToClipboard', function(clipboardService, ionicToast, gettextCatalog) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
copyToClipboard: '=copyToClipboard'
|
||||
},
|
||||
link: function(scope, elem, attrs, ctrl) {
|
||||
var isCordova = platformInfo.isCordova;
|
||||
var isChromeApp = platformInfo.isChromeApp;
|
||||
var isNW = platformInfo.isNW;
|
||||
elem.bind('mouseover', function() {
|
||||
elem.css('cursor', 'pointer');
|
||||
});
|
||||
|
||||
var msg = gettextCatalog.getString('Copied to clipboard');
|
||||
elem.bind('click', function() {
|
||||
var data = scope.copyToClipboard;
|
||||
if (!data) return;
|
||||
clipboardService.copyToClipboard(data);
|
||||
|
||||
if (isCordova) {
|
||||
cordova.plugins.clipboard.copy(data);
|
||||
} else if (isNW) {
|
||||
nodeWebkitService.writeToClipboard(data);
|
||||
} else if (clipboard.supported) {
|
||||
clipboard.copyText(data);
|
||||
} else {
|
||||
// No supported
|
||||
return;
|
||||
}
|
||||
scope.$apply(function() {
|
||||
var msg = gettextCatalog.getString('Copied to clipboard');
|
||||
scope.$apply(function () {
|
||||
ionicToast.show(msg, 'bottom', false, 1000);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
78
src/js/services/bannerService.js
Normal file
78
src/js/services/bannerService.js
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services').factory('bannerService', function ($http, $log) {
|
||||
// Export
|
||||
var root = {};
|
||||
|
||||
// Constant
|
||||
var API_URL = 'https://bwscash.bitcoin.com/bws/api/v1/marketing';
|
||||
|
||||
// Variable
|
||||
var hasFetched = false;
|
||||
var banners = [];
|
||||
var defaultBanner = {
|
||||
id: 'default-banner',
|
||||
imageURL: 'img/banner-store.png',
|
||||
url: 'https://store.bitcoin.com/',
|
||||
isLocal: true
|
||||
};
|
||||
|
||||
// Private methods
|
||||
var fetchSettings = function (cb) {
|
||||
var req = {
|
||||
method: 'GET',
|
||||
url: API_URL+'/settings',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
};
|
||||
$http(req).then(function (response) {
|
||||
$log.info('Get banner settings: SUCCESS');
|
||||
banners = response.data;
|
||||
return cb(true);
|
||||
}, function (error) {
|
||||
$log.error('Get banner settings: ERROR ' + error.statusText);
|
||||
return cb(false);
|
||||
});
|
||||
};
|
||||
|
||||
root.getBanner = function (cb) {
|
||||
|
||||
// If not fetch get the banner
|
||||
if (!hasFetched) {
|
||||
hasFetched = true;
|
||||
|
||||
// If never fetch, lets fetch
|
||||
fetchSettings(function (isSuccess) {
|
||||
root.getBanner(cb);
|
||||
});
|
||||
|
||||
// If fetch, and got banners, lets have a look
|
||||
} else if (banners.length > 0) {
|
||||
var selectedBanners = [];
|
||||
for(var i in banners) {
|
||||
var banner = banners[i];
|
||||
|
||||
// Generate the URL for the banner
|
||||
var fileName = banner.image.substring(0, banner.image.lastIndexOf('.'));
|
||||
var extension = banner.image.substring(banner.image.lastIndexOf('.')+1);
|
||||
banner.imageURL = API_URL +'/banners/'+fileName+"/"+extension;
|
||||
|
||||
// Add the banner
|
||||
selectedBanners.push(banners[i]);
|
||||
}
|
||||
|
||||
// If no banner activated, return the default one
|
||||
if (selectedBanners.length == 0) {
|
||||
return cb(defaultBanner);
|
||||
} else {
|
||||
return cb(selectedBanners[Math.floor(Math.random()*banners.length)]);
|
||||
}
|
||||
|
||||
} else {
|
||||
return cb(defaultBanner);
|
||||
}
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
24
src/js/services/clipboardService.js
Normal file
24
src/js/services/clipboardService.js
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services').factory('clipboardService', function ($http, $log, platformInfo, nodeWebkitService, gettextCatalog, ionicToast, clipboard) {
|
||||
var root = {};
|
||||
|
||||
root.copyToClipboard = function (data) {
|
||||
if (!data) return;
|
||||
|
||||
$log.debug("Copy '"+data+"' to clipboard");
|
||||
if (platformInfo.isCordova) {
|
||||
cordova.plugins.clipboard.copy(data);
|
||||
} else if (platformInfo.isNW) {
|
||||
nodeWebkitService.writeToClipboard(data);
|
||||
} else if (clipboard.supported) {
|
||||
clipboard.copyText(data);
|
||||
} else {
|
||||
// No supported
|
||||
return;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
|
|
@ -103,6 +103,7 @@ angular.module('copayApp.services').service('scannerService', function($log, $ti
|
|||
_completeInitialization(status, callback);
|
||||
});
|
||||
} else {
|
||||
isAvailable = true; // XX SP: Availability can change after permissions are granted after being denied.
|
||||
_completeInitialization(status, callback);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
44
src/js/services/soundService.js
Normal file
44
src/js/services/soundService.js
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
'use strict';
|
||||
|
||||
angular.module('copayApp.services').service('soundService', function($log, $timeout, platformInfo, configService) {
|
||||
|
||||
var root = {};
|
||||
|
||||
/**
|
||||
* Play a sound (when enabled in the configuration) using the Cordova Media-plugin (on Mobile) or html5-audio (on Desktop) relative to the www-root
|
||||
* Make sure there is a .ogg file as well for NW.js (desktop) implementation
|
||||
* @param soundFile
|
||||
*/
|
||||
root.play = function(soundFile) {
|
||||
configService.whenAvailable(function(config) {
|
||||
if (config.soundsEnabled) {
|
||||
if (platformInfo.isCordova) {
|
||||
|
||||
if (platformInfo.isAndroid) {
|
||||
var p = window.location.pathname;
|
||||
var device_path = p.substring(0, p.lastIndexOf('/'));
|
||||
soundFile = device_path + '/' + soundFile;
|
||||
}
|
||||
|
||||
var audio = new Media(soundFile,
|
||||
function () {
|
||||
$log.debug("playAudio(bch_sent):Audio Success");
|
||||
},
|
||||
function (err) {
|
||||
$log.debug("playAudio():Audio Error: " + err);
|
||||
}
|
||||
);
|
||||
audio.play({playAudioWhenScreenIsLocked: false}); // XX SP: "Locked" is also the mute switch in iOS
|
||||
} else {
|
||||
if (platformInfo.isNW) {
|
||||
soundFile = soundFile.substring(0, soundFile.lastIndexOf('.')) + ".ogg";
|
||||
$log.debug("Playing .ogg file ("+soundFile+"), as NW.js has no mp3 support");
|
||||
}
|
||||
new Audio(soundFile).play();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return root;
|
||||
});
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict';
|
||||
angular.module('copayApp.services')
|
||||
.factory('storageService', function(appConfigService, logHeader, fileStorageService, localStorageService, sjcl, $log, lodash, platformInfo, secureStorageService, $timeout) {
|
||||
.factory('storageService', function(appConfigService, logHeader, fileStorageService, localStorageService, sjcl, $log, lodash, platformInfo, $timeout) {
|
||||
|
||||
var root = {};
|
||||
var storage;
|
||||
|
|
@ -121,11 +121,7 @@ angular.module('copayApp.services')
|
|||
|
||||
root.storeProfile = function(profile, cb) {
|
||||
var profileString = profile.toObj();
|
||||
if (platformInfo.isNW) {
|
||||
storage.set('profile', profileString, cb);
|
||||
} else {
|
||||
secureStorageService.set('profile', profileString, cb);
|
||||
}
|
||||
storage.set('profile', profileString, cb);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -205,48 +201,19 @@ angular.module('copayApp.services')
|
|||
* @param {getProfileCallback} cb
|
||||
*/
|
||||
root.getProfile = function(cb) {
|
||||
if (platformInfo.isNW) {
|
||||
storage.get('profile', function(getErr, getStr) {
|
||||
_onOldProfileRetrieved(getErr, getStr, cb);
|
||||
});
|
||||
return
|
||||
}
|
||||
|
||||
secureStorageService.get('profile', function(secureErr, secureStr) {
|
||||
var secureProfile;
|
||||
var oldProfile;
|
||||
|
||||
if (secureErr) {
|
||||
return cb(secureErr, null);
|
||||
storage.get('profile', function(getErr, getStr) {
|
||||
if (getErr) {
|
||||
cb(getErr, null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (secureStr) {
|
||||
try {
|
||||
secureProfile = Profile.fromString(secureStr);
|
||||
$log.debug('profile: ' + JSON.stringify(secureProfile));
|
||||
} catch (e) {
|
||||
$log.error(e);
|
||||
return cb(e, null);
|
||||
}
|
||||
if (!getStr) {
|
||||
cb(null, null);
|
||||
return;
|
||||
}
|
||||
|
||||
storage.get('profile', function(getErr, getStr) {
|
||||
_onOldProfileRetrieved(getErr, getStr, function(oldErr, oldProfile){
|
||||
if (oldErr) {
|
||||
return cb(oldErr, null);
|
||||
}
|
||||
|
||||
if (!oldProfile) {
|
||||
if (secureProfile) {
|
||||
return cb(null, secureProfile);
|
||||
} else {
|
||||
// No profiles found. No errors either.
|
||||
return cb(null, null);
|
||||
}
|
||||
}
|
||||
_migrateProfiles(oldProfile, secureProfile, cb);
|
||||
});
|
||||
});
|
||||
|
||||
var profile = Profile.fromString(getStr);
|
||||
cb(null, profile);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -72,11 +72,19 @@ angular.module('copayApp.services').factory('txFormatService', function($filter,
|
|||
var config = configService.getSync().wallet.settings;
|
||||
|
||||
var val = function() {
|
||||
var v1 = parseFloat((rateService.toFiat(satoshis, config.alternativeIsoCode, coin)).toFixed(2));
|
||||
v1 = $filter('formatFiatAmount')(v1);
|
||||
var fiatAmount = rateService.toFiat(satoshis, config.alternativeIsoCode, coin);
|
||||
var roundedStr = fiatAmount.toFixed(2);
|
||||
var roundedNum = parseFloat(roundedStr);
|
||||
var subcent = roundedNum === 0 && fiatAmount > 0;
|
||||
var lessThanPrefix = '';
|
||||
if (subcent) {
|
||||
roundedNum = 0.01;
|
||||
lessThanPrefix = '< ';
|
||||
}
|
||||
var v1 = $filter('formatFiatAmount')(roundedNum);
|
||||
if (!v1) return null;
|
||||
|
||||
return v1 + ' ' + config.alternativeIsoCode;
|
||||
return lessThanPrefix + v1 + ' ' + config.alternativeIsoCode;
|
||||
};
|
||||
|
||||
// Async version
|
||||
|
|
|
|||
68
src/js/services/txFormatService.spec.js
Normal file
68
src/js/services/txFormatService.spec.js
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
describe('txFormatService', function(){
|
||||
var configServiceMock,
|
||||
rateServiceMock,
|
||||
txFormatService;
|
||||
|
||||
beforeEach(function(){
|
||||
module('ngLodash');
|
||||
module('bwcModule');
|
||||
module('copayApp.filters');
|
||||
module('copayApp.services');
|
||||
|
||||
configServiceMock = {
|
||||
getSync: jasmine.createSpy()
|
||||
};
|
||||
|
||||
rateServiceMock = {
|
||||
isAvailable: jasmine.createSpy(),
|
||||
toFiat: jasmine.createSpy()
|
||||
};
|
||||
|
||||
module(function($provide) {
|
||||
$provide.value('configService', configServiceMock);
|
||||
$provide.value('rateService', rateServiceMock);
|
||||
});
|
||||
|
||||
inject(function($injector){
|
||||
txFormatService = $injector.get('txFormatService');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('formatAlternativeStr 0.49 cents.', function() {
|
||||
|
||||
configServiceMock.getSync.and.returnValue({
|
||||
wallet: {
|
||||
settings: {
|
||||
alternativeIsoCode: 'USD'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
rateServiceMock.isAvailable.and.returnValue(true);
|
||||
rateServiceMock.toFiat.and.returnValue(0.00499);
|
||||
|
||||
var formatted = txFormatService.formatAlternativeStr('bch', 123);
|
||||
|
||||
expect(formatted).toBe('< 0.01 USD');
|
||||
});
|
||||
|
||||
it('formatAlternativeStr 0.5 cents.', function() {
|
||||
|
||||
configServiceMock.getSync.and.returnValue({
|
||||
wallet: {
|
||||
settings: {
|
||||
alternativeIsoCode: 'USD'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
rateServiceMock.isAvailable.and.returnValue(true);
|
||||
rateServiceMock.toFiat.and.returnValue(0.005);
|
||||
|
||||
var formatted = txFormatService.formatAlternativeStr('bch', 123);
|
||||
|
||||
expect(formatted).toBe('0.01 USD');
|
||||
});
|
||||
|
||||
});
|
||||
|
|
@ -1,14 +1,15 @@
|
|||
qrcode {
|
||||
&.qr-icon {
|
||||
position: relative;
|
||||
&.qr-overlay {
|
||||
&::before {
|
||||
content: "";
|
||||
background-size: 100% 100%;
|
||||
display: block;
|
||||
margin-left: calc(50% - 22px);
|
||||
left: 88px;
|
||||
margin-top: 88px;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
position: absolute;
|
||||
position:absolute;
|
||||
}
|
||||
&--bch::before {
|
||||
background-image: url('../img/qr-overlay-bch.png');
|
||||
|
|
|
|||
|
|
@ -36,6 +36,11 @@
|
|||
.amount-label{
|
||||
line-height: 30px;
|
||||
.amount{
|
||||
font-size: 16px;
|
||||
color: #9B9B9B;
|
||||
font-family: "Roboto-Light";
|
||||
}
|
||||
.alternative {
|
||||
font-size: 38px;
|
||||
margin-bottom: .5rem;
|
||||
|
||||
|
|
@ -43,11 +48,6 @@
|
|||
font-family: "Roboto-Light";
|
||||
}
|
||||
}
|
||||
.alternative {
|
||||
font-size: 16px;
|
||||
font-family: "Roboto-Light";
|
||||
color: #9B9B9B;
|
||||
}
|
||||
}
|
||||
}
|
||||
.item {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@
|
|||
}
|
||||
}
|
||||
&-banner {
|
||||
svg {
|
||||
margin: 40px auto 40px;
|
||||
}
|
||||
padding: 0;
|
||||
&__img {
|
||||
width: 100%;
|
||||
|
|
|
|||
11
src/shim/shim.js
Normal file
11
src/shim/shim.js
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
//---------------------------------------------------------------------
|
||||
//
|
||||
// Add components what are missing in old JavaScript Engine
|
||||
//
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
if (!ArrayBuffer['isView']) {
|
||||
ArrayBuffer.isView = function(a) {
|
||||
return a !== null && typeof(a) === "object" && a['buffer'] instanceof ArrayBuffer;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue