Merge branch 'wallet/sprint/18' into wallet/task/399

This commit is contained in:
Jean-Baptiste Dominguez 2018-07-03 12:17:56 +09:00 committed by GitHub
commit 1d9efcca06
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 808 additions and 157 deletions

View file

@ -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))

View file

@ -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, soundService) {
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' };
@ -58,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) {
@ -127,6 +133,12 @@ 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;
@ -229,6 +241,7 @@ angular.module('copayApp.controllers').controller('tabReceiveController', functi
});
$scope.$on("$ionicView.enter", function(event, data) {
$scope.showingPaymentReceived = false;
$ionicNavBarDelegate.showBar(true);
});

View file

@ -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(){

View file

@ -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,

View 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;
}]);

View file

@ -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);
});
});
}
}

View 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;
});

View file

@ -107,7 +107,7 @@ angular.module('copayApp.services').factory('configService', function(storageSer
enabled: false,
},
soundsEnabled: false,
soundsEnabled: true,
log: {
filter: 'debug',

View file

@ -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);
}
});

View file

@ -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);
});
};

View file

@ -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

View 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');
});
});

View file

@ -5,6 +5,7 @@
@import "icons";
@import "buttons";
@import "forms";
@import "qr";
@import "mixins/mixins";
@import "views/views";
@import "directives/directives";

20
src/sass/qr.scss Normal file
View file

@ -0,0 +1,20 @@
qrcode {
&.qr-icon {
&::before {
content: "";
background-size: 100% 100%;
display: block;
margin-left: calc(50% - 22px);
margin-top: 88px;
width: 44px;
height: 44px;
position: absolute;
}
&--bch::before {
background-image: url('../img/qr-overlay-bch.png');
}
&--btc::before {
background-image: url('../img/qr-overlay-btc.png');
}
}
}

View file

@ -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 {

11
src/shim/shim.js Normal file
View 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;
};
}