Merge pull request #5363 from matiu/chrome-app

Chrome app for Copay
This commit is contained in:
Javier Donadío 2017-01-05 17:34:56 -03:00 committed by GitHub
commit 481d9ba457
19 changed files with 75 additions and 50 deletions

View file

@ -15,6 +15,7 @@ var templates = {
'.desktop': 'webkitbuilds/', '.desktop': 'webkitbuilds/',
'setup-win.iss': 'webkitbuilds/', 'setup-win.iss': 'webkitbuilds/',
'build-macos.sh': 'webkitbuilds/', 'build-macos.sh': 'webkitbuilds/',
'manifest.json': 'chrome-app/',
// 'bower.json': '/', // 'bower.json': '/',
}; };
var configDir = process.argv[2] || 'copay'; var configDir = process.argv[2] || 'copay';

View file

@ -1,7 +1,7 @@
{ {
"manifest_version": 2, "manifest_version": 2,
"name": "*PACKAGENAME*", "name": "*PACKAGENAME*",
"description": "*PACKAGEDESCRIPTION*", "description": "*DESCRIPTION*",
"version": "*VERSION*", "version": "*VERSION*",
"permissions": [ "permissions": [
"storage", "storage",

View file

@ -1,8 +1,9 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('addressbookListController', function($scope, $log, $timeout, addressbookService, lodash, popupService, gettextCatalog) { angular.module('copayApp.controllers').controller('addressbookListController', function($scope, $log, $timeout, addressbookService, lodash, popupService, gettextCatalog, platformInfo) {
var contacts; var contacts;
$scope.isChromeApp = platformInfo.isChromeApp;
var initAddressbook = function() { var initAddressbook = function() {
addressbookService.list(function(err, ab) { addressbookService.list(function(err, ab) {

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('addressbookViewController', function($scope, $state, $timeout, $stateParams, lodash, addressbookService, popupService, $ionicHistory) { angular.module('copayApp.controllers').controller('addressbookViewController', function($scope, $state, $timeout, $stateParams, lodash, addressbookService, popupService, $ionicHistory, platformInfo) {
$scope.isChromeApp = platformInfo.isChromeApp;
$scope.addressbookEntry = {}; $scope.addressbookEntry = {};
$scope.addressbookEntry.name = $stateParams.name; $scope.addressbookEntry.name = $stateParams.name;
$scope.addressbookEntry.email = $stateParams.email; $scope.addressbookEntry.email = $stateParams.email;

View file

@ -7,6 +7,7 @@ angular.module('copayApp.controllers').controller('amountController', function($
var satToBtc; var satToBtc;
var SMALL_FONT_SIZE_LIMIT = 10; var SMALL_FONT_SIZE_LIMIT = 10;
var LENGTH_EXPRESSION_LIMIT = 19; var LENGTH_EXPRESSION_LIMIT = 19;
$scope.isChromeApp = platformInfo.isChromeApp;
$scope.$on('$ionicView.leave', function() { $scope.$on('$ionicView.leave', function() {
angular.element($window).off('keydown'); angular.element($window).off('keydown');

View file

@ -36,7 +36,7 @@ angular.module('copayApp.controllers').controller('importController',
id: 'trezor', id: 'trezor',
label: 'Trezor Hardware Wallet', label: 'Trezor Hardware Wallet',
}); });
$scope.seedSource = $scope.seedOptions[0]; $scope.formData.seedSource = $scope.seedOptions[0];
} }
}; };
@ -281,16 +281,16 @@ angular.module('copayApp.controllers').controller('importController',
}; };
$scope.importHW = function(form) { $scope.importHW = function(form) {
if (form.$invalid || $scope.formData.ccount < 0) { if (form.$invalid || $scope.formData.account < 0) {
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('There is an error in the form')); popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('There is an error in the form'));
return; return;
} }
$scope.importErr = false; $scope.importErr = false;
var account = $scope.formData.ccount; var account = $scope.formData.account;
if ($scope.seedSource.id == 'trezor') { if ($scope.formData.seedSource.id == 'trezor') {
if (account < 1) { if (account < 1) {
popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number')); popupService.showAlert(gettextCatalog.getString('Error'), gettextCatalog.getString('Invalid account number'));
return; return;
@ -298,7 +298,7 @@ angular.module('copayApp.controllers').controller('importController',
account = account - 1; account = account - 1;
} }
switch ($scope.seedSource.id) { switch ($scope.formData.seedSource.id) {
case ('ledger'): case ('ledger'):
ongoingProcess.set('connectingledger', true); ongoingProcess.set('connectingledger', true);
$scope.importLedger(account); $scope.importLedger(account);

View file

@ -1,11 +1,11 @@
'use strict'; 'use strict';
angular.module('copayApp.controllers').controller('tabSendController', function($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, addressbookService, profileService, lodash, $state, walletService, incomingData, popupService) { angular.module('copayApp.controllers').controller('tabSendController', function($scope, $rootScope, $log, $timeout, $ionicScrollDelegate, addressbookService, profileService, lodash, $state, walletService, incomingData, popupService, platformInfo) {
var originalList; var originalList;
var CONTACTS_SHOW_LIMIT; var CONTACTS_SHOW_LIMIT;
var currentContactsPage; var currentContactsPage;
$scope.isChromeApp = platformInfo.isChromeApp;
var updateList = function() { var updateList = function() {
CONTACTS_SHOW_LIMIT = 10; CONTACTS_SHOW_LIMIT = 10;

View file

@ -1,7 +1,7 @@
'use strict'; 'use strict';
angular.module('copayApp.services') angular.module('copayApp.services')
.factory('hwWallet', function($log, bwcService) { .factory('hwWallet', function($log, bwcService) {
var root = {}; var root = {};
// Ledger magic number to get xPub without user confirmation // Ledger magic number to get xPub without user confirmation
@ -11,8 +11,7 @@ angular.module('copayApp.services')
root.LIVENET_PATH = 0; root.LIVENET_PATH = 0;
root._err = function(data) { root._err = function(data) {
var msg = 'Hardware Wallet Error: ' + (data.error || data.message || 'unknown'); var msg = data.error || data.message || 'unknown';
$log.warn(msg);
return msg; return msg;
}; };
@ -21,13 +20,13 @@ angular.module('copayApp.services')
if (!isMultisig) return root.UNISIG_ROOTPATH; if (!isMultisig) return root.UNISIG_ROOTPATH;
// Compat // Compat
if (device == 'ledger' && account ==0) return root.UNISIG_ROOTPATH; if (device == 'ledger' && account == 0) return root.UNISIG_ROOTPATH;
return root.MULTISIG_ROOTPATH; return root.MULTISIG_ROOTPATH;
}; };
root.getAddressPath = function(device, isMultisig, account) { root.getAddressPath = function(device, isMultisig, account) {
return root.getRootPath(device,isMultisig,account) + "'/" + root.LIVENET_PATH + "'/" + account + "'"; return root.getRootPath(device, isMultisig, account) + "'/" + root.LIVENET_PATH + "'/" + account + "'";
} }
root.getEntropyPath = function(device, isMultisig, account) { root.getEntropyPath = function(device, isMultisig, account) {
@ -35,9 +34,9 @@ angular.module('copayApp.services')
// Old ledger wallet compat // Old ledger wallet compat
if (device == 'ledger' && account == 0) if (device == 'ledger' && account == 0)
return root.ENTROPY_INDEX_PATH + "0'"; return root.ENTROPY_INDEX_PATH + "0'";
return root.ENTROPY_INDEX_PATH + root.getRootPath(device,isMultisig,account) + "'/" + account + "'"; return root.ENTROPY_INDEX_PATH + root.getRootPath(device, isMultisig, account) + "'/" + account + "'";
}; };
root.pubKeyToEntropySource = function(xPubKey) { root.pubKeyToEntropySource = function(xPubKey) {

View file

@ -17,7 +17,7 @@ angular.module('copayApp.services')
if (!data.success) if (!data.success)
return callback(hwWallet._err(data)); return callback(hwWallet._err(data));
return callback(null, hwWallet.pubKeyToEntropySource(data.xpubkey)); return callback(null, hwWallet.pubKeyToEntropySource(data.xpubkey));
}); });
}; };
@ -27,21 +27,18 @@ angular.module('copayApp.services')
root._messageAfterSession({ root._messageAfterSession({
command: "get_xpubkey", command: "get_xpubkey",
path: path path: path
}) });
}; };
root.getInfoForNewWallet = function(isMultisig, account, callback) { root.getInfoForNewWallet = function(isMultisig, account, callback) {
var opts = {};
root.getEntropySource(isMultisig, account, function(err, entropySource) { root.getEntropySource(isMultisig, account, function(err, entropySource) {
if (err) return callback(err); if (err) return callback(err);
opts.entropySource = entropySource;
root.getXPubKey(hwWallet.getAddressPath('ledger', isMultisig, account), function(data) { root.getXPubKey(hwWallet.getAddressPath('ledger', isMultisig, account), function(data) {
if (!data.success) { if (!data.success) return callback(data);
$log.warn(data.message);
return callback(data); var opts = {};
} opts.entropySource = entropySource;
opts.extendedPublicKey = data.xpubkey; opts.extendedPublicKey = data.xpubkey;
opts.externalSource = 'ledger'; opts.externalSource = 'ledger';
opts.account = account; opts.account = account;
@ -130,7 +127,7 @@ angular.module('copayApp.services')
root._should_poll_session = false; root._should_poll_session = false;
} else if (typeof root.callbacks[data.command] == "function") { } else if (typeof root.callbacks[data.command] == "function") {
root.callbacks[data.command](data); root.callbacks[data.command](data);
} } else {}
} else { } else {
root._should_poll_session = false; root._should_poll_session = false;
Object.keys(root.callbacks).forEach(function(key) { Object.keys(root.callbacks).forEach(function(key) {

View file

@ -636,6 +636,7 @@ angular.module('copayApp.services')
}; };
root._normalizeMnemonic = function(words) { root._normalizeMnemonic = function(words) {
if (!words || !words.indexOf) return words;
var isJA = words.indexOf('\u3000') > -1; var isJA = words.indexOf('\u3000') > -1;
var wordList = words.split(/[\u3000\s]+/); var wordList = words.split(/[\u3000\s]+/);

View file

@ -19,7 +19,11 @@ angular.module('copayApp.services')
root.getXPubKey = function(path, callback) { root.getXPubKey = function(path, callback) {
$log.debug('TREZOR deriving xPub path:', path); $log.debug('TREZOR deriving xPub path:', path);
TrezorConnect.getXPubKey(path, callback); try {
TrezorConnect.getXPubKey(path, callback);
} catch (e) {
callback('Error connecting Trezor');
}
}; };

View file

@ -130,4 +130,20 @@
display: block; display: block;
color: $mid-gray; color: $mid-gray;
} }
.big-icon-svg {
padding: 0 7px;
> .bg {
background-color: #f2f2f2;
border-radius: 50%;
width: 70px;
height: 70px;
box-shadow: 0px 1px 5px rgba($mid-gray, .1);
background-repeat: no-repeat;
background-clip: padding-box;
background-size: 103%;
&.green {
background: rgb(1, 209, 162);
}
}
}
} }

BIN
www/img/icon-chrome-128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -37,7 +37,8 @@
<ion-item ng-repeat="addrEntry in addressbook" <ion-item ng-repeat="addrEntry in addressbook"
class="item-icon-right item-avatar" class="item-icon-right item-avatar"
ui-sref="tabs.addressbook.view({address:addrEntry.address, email: addrEntry.email, name: addrEntry.name})"> ui-sref="tabs.addressbook.view({address:addrEntry.address, email: addrEntry.email, name: addrEntry.name})">
<gravatar name="{{addrEntry.name}}" width="50" email="{{addrEntry.email}}"></gravatar> <img src="img/contact-placeholder.svg" class="bg"/ ng-if="isChromeApp">
<gravatar name="{{addrEntry.name}}" width="50" email="{{addrEntry.email}}" ng-if="!isChromeApp"></gravatar>
<h2>{{addrEntry.name}}</h2> <h2>{{addrEntry.name}}</h2>
<p>{{addrEntry.address}}</p> <p>{{addrEntry.address}}</p>
<i class="icon bp-arrow-right"></i> <i class="icon bp-arrow-right"></i>

View file

@ -8,7 +8,10 @@
</ion-nav-bar> </ion-nav-bar>
<ion-content scroll="false"> <ion-content scroll="false">
<div class="gravatar-content"> <div class="gravatar-content">
<gravatar name="{{addressbookEntry.name}}" width="80" email="{{addressbookEntry.email}}"></gravatar> <i class="icon big-icon-svg" ng-if="isChromeApp">
<img src="img/contact-placeholder.svg" class="bg"/>
</i>
<gravatar name="{{addressbookEntry.name}}" width="80" email="{{addressbookEntry.email}}" ng-if="!isChromeApp"></gravatar>
</div> </div>
<div class="list"> <div class="list">
<div class="item item-text-wrap"> <div class="item item-text-wrap">

View file

@ -22,7 +22,10 @@
<img src="img/icon-wallet.svg" ng-style="{'background-color': toColor}" class="bg"/> <img src="img/icon-wallet.svg" ng-style="{'background-color': toColor}" class="bg"/>
</i> </i>
<span ng-if="!isWallet && !isGiftCard && !isGlidera"> <span ng-if="!isWallet && !isGiftCard && !isGlidera">
<gravatar ng-if="!cardId" class="send-gravatar" name="{{toName}}" height="30" width="30" email="{{toEmail}}"></gravatar> <i class="icon big-icon-svg" ng-if="isChromeApp">
<img src="img/contact-placeholder.svg" class="bg"/>
</i>
<gravatar ng-if="!cardId && !isChromeApp" class="send-gravatar" name="{{toName}}" height="30" width="30" email="{{toEmail}}"></gravatar>
<i ng-if="cardId" class="icon big-icon-svg"> <i ng-if="cardId" class="icon big-icon-svg">
<div class="bg icon-bitpay-card"></div> <div class="bg icon-bitpay-card"></div>
</i> </i>

View file

@ -1,19 +1,16 @@
<span ng-show="wallet.isShared" class="size-12"><span translate>{{wallet.m}}-of-{{wallet.n}}</span></span> <span ng-show="wallet.status.wallet.singleAddress" class="size-12"><span translate>Auditable</span></span>
<span ng-show="wallet.isSingleAddress" class="size-12"><span translate>Auditable</span></span> <img style="height:0.6em; margin-right: 1px;" ng-show="wallet.network != 'livenet'" src="img/icon-testnet-white.svg">
<img style="height:0.6em; margin-right: 1px;" ng-show="wallet.network != 'livenet'" src="img/icon-testnet-white.svg"> <img style="height:0.6em; margin-right: 1px;" ng-show="!wallet.canSign() && !wallet.isPrivKeyExternal()" src="img/icon-read-only-white.svg">
<img style="height:0.6em; margin-right: 1px;" ng-show="!wallet.canSign() && !wallet.isPrivKeyExternal()"
src="img/icon-read-only-white.svg">
<img style="height:0.6em; margin-right: 1px;" ng-show="wallet.getPrivKeyExternalSourceName() == 'trezor'" <img style="height:0.6em; margin-right: 1px;" ng-show="wallet.getPrivKeyExternalSourceName() == 'trezor'" src="img/icon-trezor-white.svg">
src="img/icon-trezor-white.svg"> <img style="height:0.6em; margin-right: 1px;" ng-show="wallet.getPrivKeyExternalSourceName() == 'ledger'" src="img/icon-ledger-white.svg">
<img style="height:0.6em; margin-right: 1px;" ng-show="wallet.getPrivKeyExternalSourceName() == 'ledger'" <span ng-show="wallet.credentials.n > 1" class="size-12"><span translate>{{wallet.m}}-of-{{wallet.n}}</span></span>
src="img/icon-ledger-white.svg"> <span class="size-12 dib" style="height:0.6em; margin-right: 1px;" ng-show="wallet.credentials.account">#{{wallet.credentials.account || 0}} </span>
<span class="size-12 dib" style="height:0.6em; margin-right: 1px;" ng-show="wallet.account">#{{wallet.account || 0}} </span>
<img style="height:0.6em; margin-right: 1px;" ng-show="wallet.isPrivKeyEncrypted()" src="img/icon-lock-white.svg"> <img style="height:0.6em; margin-right: 1px;" ng-show="wallet.isPrivKeyEncrypted()" src="img/icon-lock-white.svg">
<!-- <img style="height:1em" ng&#45;show="wallet.preferences.email" src="img/icon&#45;email.svg"> --> <!-- <img style="height:1em" ng&#45;show="wallet.preferences.email" src="img/icon&#45;email.svg"> -->
<img style="height:0.6em; margin-right: 1px;" ng-show="wallet.usingCustomBWS" src="img/icon-bws-white.svg"> <img style="height:0.6em; margin-right: 1px;" ng-show="wallet.usingCustomBWS" src="img/icon-bws-white.svg">
<img style="height:0.6em" ng-show="updatingTxHistory" src="img/icon-sync-white.svg"> <img style="height:0.6em" ng-show="updatingTxHistory" src="img/icon-sync-white.svg">

View file

@ -12,15 +12,15 @@
Wallet Type Wallet Type
</div> </div>
<select ng-model="seedSource" ng-options="seed as seed.label for seed in seedOptions"></select> <select ng-model="formData.seedSource" ng-options="seed as seed.label for seed in seedOptions"></select>
</label> </label>
<label class="item item-input item-stacked-label" ng-show="seedSource.id == 'trezor' || seedSource.id == 'ledger'"> <label class="item item-input item-stacked-label" ng-show="formData.seedSource.id == 'trezor' || formData.seedSource.id == 'ledger'">
<span class="input-label" translate>Account Number</span> <span class="input-label" translate>Account Number</span>
<input type="number" ng-model="formData.account" ignore-mouse-wheel> <input type="number" ng-model="formData.account" ignore-mouse-wheel>
</label> </label>
<ion-toggle ng-show="seedSource.id == 'trezor'" ng-model="formData.isMultisig" toggle-class="toggle-positive"> <ion-toggle ng-show="formData.seedSource.id == 'trezor'" ng-model="formData.isMultisig" toggle-class="toggle-positive">
<span translate>Shared Wallet</span> <span translate>Shared Wallet</span>
</ion-toggle> </ion-toggle>

View file

@ -44,7 +44,8 @@
</a> </a>
<a class="item item-icon-left item-icon-right" ng-repeat="item in list" ng-if="hasContacts && !item.isWallet" ng-click="goToAmount(item)"> <a class="item item-icon-left item-icon-right" ng-repeat="item in list" ng-if="hasContacts && !item.isWallet" ng-click="goToAmount(item)">
<i class="icon big-icon-svg"> <i class="icon big-icon-svg">
<gravatar class="send-gravatar" name="{{item.name}}" width="30" email="{{item.email}}"></gravatar> <img src="img/contact-placeholder.svg" class="bg"/ ng-if="isChromeApp">
<gravatar class="send-gravatar" name="{{item.name}}" width="30" email="{{item.email}}" ng-if="!isChromeApp"></gravatar>
</i> </i>
{{item.name}} {{item.name}}
<i class="icon bp-arrow-right"></i> <i class="icon bp-arrow-right"></i>