Merge pull request #2638 from matiu/feat/gen-addr-anim

Feat/gen addr anim
This commit is contained in:
Gustavo Maximiliano Cortez 2015-04-27 02:09:08 -03:00
commit 5bf0b93089
8 changed files with 40 additions and 516 deletions

BIN
public/img/qr.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -185,16 +185,36 @@
</div>
</div>
<div ng-show="!index.needsBackup || home.skipBackup">
<div class="row" ng-if="home.addr">
<div class="row">
<!-- Address-->
<div class="large-12 columns">
<h2 class="text-center m10t" translate>My Bitcoin address</h2>
<div ng-show="!home.generatingAddress">
<div class="text-center" ng-click="home.copyAddress(home.addr)">
<qrcode size="220" data="bitcoin:{{home.addr}}"></qrcode>
<div class="m10t">
<h4 ng-class="{'enable_text_select': !index.isCordova}" class="size-12">{{home.addr}}</h4>
</div>
</div>
</div>
<div ng-show="home.generatingAddress">
<div class="text-center" style="margin-bottom:14px;">
<div style="height:220px; width:220px; margin:auto; background: url(img/qr.png) white">
<div class="spinner" style="margin-top:80px">
<div class="rect1"></div>
<div class="rect2"></div>
<div class="rect3"></div>
<div class="rect4"></div>
<div class="rect5"></div>
</div>
</div>
<div class="m10t">
<h4 class="size-12">...</h4>
</div>
</div>
</div>
<div class="m10t text-center" ng-show="index.isCordova">
<span class="button outline dark-gray tiny"
ng-click="home.shareAddress(home.addr)">
@ -207,10 +227,10 @@
</div>
</div>
</div>
<div class="row m20t" ng-if="home.addr">
<div class="row m20t">
<div class="large-12 columns">
<button class="button black expand radius" ng-click="home.newAddress()"
ng-style="{'background-color':index.backgroundColor}" ng-disabled="home.blockUx || index.isOffline" translate>
ng-style="{'background-color':index.backgroundColor}" ng-disabled="home.blockUx || index.isOffline ||home.generatingAddress" translate>
Generate new address
</button>
</div>

View file

@ -1145,11 +1145,13 @@ input.ng-invalid-match, input.ng-invalid-match:focus {
/*/////////////////// SPINNER ////////////////////*/
#history .spinner {
#history .spinner, #receive .spinner {
height: 46px;
}
#history .spinner > div {
#history .spinner > div,
#receive .spinner > div
{
background-color: #7A8C9E;
}

View file

@ -95,8 +95,8 @@ angular.module('copayApp.controllers').controller('copayersController',
if (isMobile.Android() || isMobile.Windows()) {
window.ignoreMobilePause = true;
}
var message = 'Join my Copay wallet. Here is the invitation code ' + secret + ' You can download Copay for your phone or desktop at https://copay.io';
window.plugins.socialsharing.share(message, null, null, null);
var message = 'Join my Copay wallet. Here is the invitation code: ' + secret + ' You can download Copay for your phone or desktop at https://copay.io';
window.plugins.socialsharing.share(message, 'Invitation to share a Copay Wallet', null, null);
}
};

View file

@ -1,6 +0,0 @@
'use strict';
angular.module('copayApp.controllers').controller('historyController',
function($scope, $rootScope, $filter, $timeout, $modal, $log, profileService, notification, go, configService, rateService, lodash) {
});

View file

@ -1,63 +0,0 @@
'use strict';
angular.module('copayApp.controllers').controller('receiveController',
function($rootScope, $scope, $timeout, $modal, $log, isCordova, isMobile, profileService, storageService) {
var self = this;
this.isCordova = isCordova;
self.addresses = [];
var newAddrListener = $rootScope.$on('Local/NeedNewAddress', function() {
self.getAddress();
});
$scope.$on('$destroy', newAddrListener);
this.newAddress = function() {
var fc = profileService.focusedClient;
self.generatingAddress = true;
self.error = null;
fc.createAddress(function(err, addr) {
self.generatingAddress = false;
if (err) {
$log.debug('Creating address ERROR:', err);
$scope.$emit('Local/ClientError', err);
self.error='Could not generate address';
} else {
self.addr = addr.address;
storageService.storeLastAddress(fc.credentials.walletId, addr.address, function() {});
}
$scope.$digest();
});
};
this.getAddress = function() {
var fc = profileService.focusedClient;
$timeout(function() {
storageService.getLastAddress(fc.credentials.walletId, function(err, addr) {
if (addr) {
self.addr = addr;
} else {
self.newAddress();
}
});
});
};
this.copyAddress = function(addr) {
if (isCordova) {
window.cordova.plugins.clipboard.copy('bitcoin:' + addr);
window.plugins.toast.showShortCenter('Copied to clipboard');
}
};
this.shareAddress = function(addr) {
if (isCordova) {
if (isMobile.Android() || isMobile.Windows()) {
window.ignoreMobilePause = true;
}
window.plugins.socialsharing.share('bitcoin:' + addr, null, null, null);
}
};
}
);

View file

@ -1,433 +0,0 @@
'use strict';
angular.module('copayApp.controllers').controller('sendController',
function($rootScope, $scope, $window, $timeout, $modal, $filter, $log, notification, isMobile, txStatus, isCordova, bitcore, profileService, configService, rateService, isChromeApp, lodash) {
var fc = profileService.focusedClient;
var self = this;
this.resetError = function() {
this.error = this.success = null;
};
this.init = function() {
this.isMobile = isMobile.any();
this.isWindowsPhoneApp = isMobile.Windows() && isCordova;
$rootScope.wpInputFocused = false;
$rootScope.title = fc.credentials.m > 1 ? 'Send Proposal' : 'Send';
this.blockUx = false;
this.resetError();
this.isRateAvailable = false;
this.showScanner = false;
this.isMobile = isMobile.any();
var paymentUri = $rootScope.$on('paymentUri', function(event, uri) {
$timeout(function() {
self.setForm(uri);
}, 100);
});
var config = configService.getSync().wallet.settings;
this.alternativeName = config.alternativeName;
this.alternativeAmount = 0;
this.alternativeIsoCode = config.alternativeIsoCode;
this.unitToSatoshi = config.unitToSatoshi;
this.unitDecimals = config.unitDecimals;
this.unitName = config.unitName;
rateService.whenAvailable(function() {
self.isRateAvailable = true;
$rootScope.$digest();
});
var openScannerCordova = $rootScope.$on('dataScanned', function(event, data) {
self.setForm(data);
});
$scope.$on('$destroy', function() {
$rootScope.hideMenuBar = false;
openScannerCordova();
paymentUri();
});
this.setInputs();
};
var hideMenuBar = lodash.debounce(function(hide) {
if (hide) {
$rootScope.hideMenuBar = true;
} else {
$rootScope.hideMenuBar = false;
}
$rootScope.$digest();
}, 100);
this.formFocus = function(what) {
if (isCordova) {
hideMenuBar(what);
}
if (!this.isWindowsPhoneApp) return
if (!what) {
this.hideAddress = false;
this.hideAmount = false;
} else {
if (what == 'amount') {
this.hideAddress = true;
} else if (what == 'msg') {
this.hideAddress = true;
this.hideAmount = true;
}
}
$timeout(function() {
$rootScope.$digest();
}, 1);
};
this.setInputs = function() {
var unitToSat = this.unitToSatoshi;
var satToUnit = 1 / unitToSat;
/**
* Setting the two related amounts as properties prevents an infinite
* recursion for watches while preserving the original angular updates
*
*/
Object.defineProperty($scope,
"_alternative", {
get: function() {
return $scope.__alternative;
},
set: function(newValue) {
$scope.__alternative = newValue;
if (typeof(newValue) === 'number' && self.isRateAvailable) {
$scope._amount = parseFloat((rateService.fromFiat(newValue, self.alternativeIsoCode) * satToUnit).toFixed(self.unitDecimals), 10);
}
},
enumerable: true,
configurable: true
});
Object.defineProperty($scope,
"_amount", {
get: function() {
return $scope.__amount;
},
set: function(newValue) {
$scope.__amount = newValue;
if (typeof(newValue) === 'number' && self.isRateAvailable) {
$scope.__alternative = parseFloat((rateService.toFiat(newValue * self.unitToSatoshi, self.alternativeIsoCode)).toFixed(2), 10);
} else {
$scope.__alternative = 0;
}
self.alternativeAmount = $scope.__alternative;
self.resetError();
},
enumerable: true,
configurable: true
});
Object.defineProperty($scope,
"_address", {
get: function() {
return $scope.__address;
},
set: function(newValue) {
$scope.__address = self.onAddressChange(newValue);
},
enumerable: true,
configurable: true
});
};
this.setError = function(err) {
$log.warn(err);
var errMessage = 'The transaction' + (fc.credentials.m > 1 ? ' proposal' : '') +
' could not be created: ' + (err.message ? err.message : err);
this.error = errMessage;
$timeout(function() {
$scope.$digest();
}, 1);
};
this.setOngoingProcess = function(name) {
var self = this;
$timeout(function() {
self.onGoingProcess = name;
$rootScope.$apply();
})
};
this.submitForm = function(form) {
var unitToSat = this.unitToSatoshi;
if (form.$invalid) {
this.error = 'Unable to send transaction proposal';
return;
}
if (fc.isPrivKeyEncrypted()) {
profileService.unlockFC(function(err) {
if (err) return self.setError(err);
return self.submitForm(form);
});
return;
};
self.blockUx = true;
self.setOngoingProcess('Sending');
if (isCordova) {
window.plugins.spinnerDialog.show(null, 'Creating transaction...', true);
}
$timeout(function() {
var comment = form.comment.$modelValue;
var paypro = self._paypro;
var address, amount;
address = form.address.$modelValue;
amount = parseInt((form.amount.$modelValue * unitToSat).toFixed(0));
fc.sendTxProposal({
toAddress: address,
amount: amount,
message: comment,
payProUrl: paypro ? paypro.url : null,
}, function(err, txp) {
self.setOngoingProcess();
if (err) {
profileService.lockFC();
if (isCordova) {
window.plugins.spinnerDialog.hide();
}
self.blockUx = false;
return self.setError(err);
}
self.signAndBroadcast(txp, function(err) {
self.setOngoingProcess();
if (isCordova) {
window.plugins.spinnerDialog.hide();
}
self.blockUx = false;
if (err) {
profileService.lockFC();
return self.setError(err);
}
self.resetForm(form);
});
});
}, 100);
};
this.signAndBroadcast = function(txp, cb) {
self.setOngoingProcess('Signing');
fc.signTxProposal(txp, function(err, signedTx) {
profileService.lockFC();
self.setOngoingProcess();
if (err) return cb(err);
if (signedTx.status == 'accepted') {
self.setOngoingProcess('Broadcasting');
fc.broadcastTxProposal(signedTx, function(err, btx) {
self.setOngoingProcess();
if (err) {
$scope.error = 'Transaction not broadcasted. Please try again.';
$scope.$digest();
} else {
txStatus.notify(btx);
$scope.$emit('Local/TxProposalAction');
}
return cb();
});
} else {
txStatus.notify(signedTx);
$scope.$emit('Local/TxProposalAction');
return cb();
}
});
};
this.setTopAmount = function() {
throw new Error('todo: setTopAmount');
var form = $scope.sendForm;
if (form) {
form.amount.$setViewValue(w.balanceInfo.topAmount);
form.amount.$render();
form.amount.$isValid = true;
}
};
this.setForm = function(to, amount, comment) {
var form = $scope.sendForm;
if (to) {
form.address.$setViewValue(to);
form.address.$isValid = true;
form.address.$render();
this.lockAddress = true;
}
if (amount) {
form.amount.$setViewValue("" + amount);
form.amount.$isValid = true;
form.amount.$render();
this.lockAmount = true;
}
if (comment) {
form.comment.$setViewValue(comment);
form.comment.$isValid = true;
form.comment.$render();
}
};
this.resetForm = function(form) {
this.resetError();
this.fetchingURL = null;
this._paypro = null;
this.lockAddress = false;
this.lockAmount = false;
this._amount = this._address = null;
if (form && form.amount) {
form.amount.$pristine = true;
form.amount.$setViewValue('');
form.amount.$render();
form.comment.$setViewValue('');
form.comment.$render();
form.$setPristine();
if (form.address) {
form.address.$pristine = true;
form.address.$setViewValue('');
form.address.$render();
}
}
$timeout(function() {
$rootScope.$digest();
}, 1);
};
this.openPPModal = function(paypro) {
var ModalInstanceCtrl = function($scope, $modalInstance) {
var satToUnit = 1 / self.unitToSatoshi;
$scope.paypro = paypro;
$scope.alternative = self.alternativeAmount;
$scope.alternativeIsoCode = self.alternativeIsoCode;
$scope.isRateAvailable = self.isRateAvailable;
$scope.unitTotal = (paypro.amount * satToUnit).toFixed(self.unitDecimals);
$scope.unitName = self.unitName;
$scope.color = fc.backgroundColor;
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
};
$modal.open({
templateUrl: 'views/modals/paypro.html',
windowClass: 'full',
controller: ModalInstanceCtrl,
});
};
this.setFromPayPro = function(uri, form) {
if (isChromeApp) {
this.error = 'Payment Protocol not supported on Chrome App';
return;
}
var satToUnit = 1 / this.unitToSatoshi;
this.fetchingURL = uri;
this.blockUx = true;
var self = this;
$log.debug('Fetch PayPro Request...', uri);
$timeout(function() {
fc.fetchPayPro({
payProUrl: uri,
}, function(err, paypro) {
$log.debug(paypro);
self.blockUx = false;
self.fetchingURL = null;
if (err) {
$log.warn(err);
self.resetForm(form);
var msg = err.toString();
if (msg.match('HTTP')) {
msg = 'Could not fetch payment information';
}
self.error = msg;
} else {
self._paypro = paypro;
self.setForm(paypro.toAddress, (paypro.amount * satToUnit).toFixed(self.unitDecimals),
paypro.memo);
}
});
}, 1);
};
this.setFromUri = function(uri) {
function sanitizeUri(uri) {
// Fixes when a region uses comma to separate decimals
var regex = /[\?\&]amount=(\d+([\,\.]\d+)?)/i;
var match = regex.exec(uri);
if (!match || match.length === 0) {
return uri;
}
var value = match[0].replace(',', '.');
var newUri = uri.replace(regex, value);
return newUri;
};
var satToUnit = 1 / this.unitToSatoshi;
uri = sanitizeUri(uri);
if (!bitcore.URI.isValid(uri)) {
return uri;
}
var parsed = new bitcore.URI(uri);
var addr = parsed.address.toString();
var message = parsed.message;
if (parsed.r)
return this.setFromPayPro(parsed.r);
var amount = parsed.amount ?
(parsed.amount.toFixed(0) * satToUnit).toFixed(this.unitDecimals) : 0;
this.setForm(addr, amount, message);
return addr;
};
this.onAddressChange = function(value) {
this.resetError();
if (!value) return '';
if (this._paypro)
return value;
if (value.indexOf('bitcoin:') === 0) {
return this.setFromUri(value);
} else if (/^https?:\/\//.test(value)) {
return this.setFromPayPro(value);
} else {
return value;
}
};
});

View file

@ -272,17 +272,21 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
this.newAddress = function() {
var fc = profileService.focusedClient;
self.setOngoingProcess('Generating Address');
self.generatingAddress = true;
fc.createAddress(function(err, addr) {
self.setOngoingProcess();
if (err) {
$log.debug('Creating address ERROR:', err);
$scope.$emit('Local/ClientError', err);
} else {
self.addr = addr.address;
storageService.storeLastAddress(fc.credentials.walletId, addr.address, function() {});
self.generatingAddress = false;
$scope.$digest();
return;
}
$scope.$digest();
self.addr = addr.address;
storageService.storeLastAddress(fc.credentials.walletId, addr.address, function() {
self.generatingAddress = false;
$scope.$digest();
});
});
};
@ -500,7 +504,7 @@ angular.module('copayApp.controllers').controller('walletHomeController', functi
profileService.lockFC();
self.setOngoingProcess();
if (err) {
if (err) {
return cb(err);
}