From 1a12ef181a5ae592a3a71b7a9ba382d0e04d0cf0 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Thu, 3 Nov 2016 13:39:03 -0300 Subject: [PATCH 1/8] Fix error if backView does not exist --- src/js/controllers/copayers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/controllers/copayers.js b/src/js/controllers/copayers.js index d5ae4c41e..cc4a97c69 100644 --- a/src/js/controllers/copayers.js +++ b/src/js/controllers/copayers.js @@ -79,8 +79,8 @@ angular.module('copayApp.controllers').controller('copayersController', }; $scope.goHome = function() { - $ionicHistory.removeBackView(); $state.go('tabs.home'); + $ionicHistory.clearHistory(); }; }); From 691600e1161a59dfc034d6a41d7d0dad5c6c2f25 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Thu, 3 Nov 2016 13:40:45 -0300 Subject: [PATCH 2/8] Updates info when a copayer accept/reject --- src/js/controllers/modals/txpDetails.js | 172 +++++++++++++----------- 1 file changed, 90 insertions(+), 82 deletions(-) diff --git a/src/js/controllers/modals/txpDetails.js b/src/js/controllers/modals/txpDetails.js index d67c2f7a4..7d8918e18 100644 --- a/src/js/controllers/modals/txpDetails.js +++ b/src/js/controllers/modals/txpDetails.js @@ -1,13 +1,11 @@ 'use strict'; -angular.module('copayApp.controllers').controller('txpDetailsController', function($scope, $rootScope, $timeout, $interval, $ionicModal, $log, ongoingProcess, platformInfo, $ionicScrollDelegate, txFormatService, fingerprintService, bwcError, gettextCatalog, lodash, walletService, popupService, $state, $ionicHistory) { - var self = $scope.self; - var tx = $scope.tx; - var copayers = $scope.copayers; +angular.module('copayApp.controllers').controller('txpDetailsController', function($scope, $rootScope, $timeout, $interval, $log, ongoingProcess, platformInfo, $ionicScrollDelegate, txFormatService, bwcError, gettextCatalog, lodash, walletService, popupService, $ionicHistory) { var isGlidera = $scope.isGlidera; var GLIDERA_LOCK_TIME = 6 * 60 * 60; var now = Math.floor(Date.now() / 1000); var countDown; + var listeners = []; $scope.init = function() { $scope.loading = null; @@ -18,8 +16,8 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi $scope.color = $scope.wallet.color; $scope.data = {}; $scope.hasClick = platformInfo.hasClick; - $scope.displayAmount = getDisplayAmount(tx.amountStr); - $scope.displayUnit = getDisplayUnit(tx.amountStr); + $scope.displayAmount = getDisplayAmount($scope.tx.amountStr); + $scope.displayUnit = getDisplayUnit($scope.tx.amountStr); initActionList(); checkPaypro(); } @@ -46,12 +44,12 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi $scope.actionList.push({ type: 'created', - time: tx.createdOn, + time: $scope.tx.createdOn, description: actionDescriptions['created'], - by: tx.creatorName + by: $scope.tx.creatorName }); - lodash.each(tx.actions, function(action) { + lodash.each($scope.tx.actions, function(action) { $scope.actionList.push({ type: action.type, time: action.createdOn, @@ -61,38 +59,70 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi }); }; + function checkPaypro() { + if ($scope.tx.payProUrl && !platformInfo.isChromeApp) { + $scope.wallet.fetchPayPro({ + payProUrl: $scope.tx.payProUrl, + }, function(err, paypro) { + if (err) return; + $scope.tx.paypro = paypro; + paymentTimeControl($scope.tx.paypro.expires); + $timeout(function() { + $ionicScrollDelegate.resize(); + }, 10); + }); + } + }; + + function paymentTimeControl(expirationTime) { + $scope.paymentExpired = false; + setExpirationTime(); + + countDown = $interval(function() { + setExpirationTime(); + }, 1000); + + function setExpirationTime() { + var now = Math.floor(Date.now() / 1000); + if (now > expirationTime) { + $scope.paymentExpired = true; + if (countDown) $interval.cancel(countDown); + return; + } + var totalSecs = expirationTime - now; + var m = Math.floor(totalSecs / 60); + var s = totalSecs % 60; + $scope.expires = ('0' + m).slice(-2) + ":" + ('0' + s).slice(-2); + }; + }; + $scope.$on('accepted', function(event) { $scope.sign(); }); // ToDo: use tx.customData instead of tx.message - if (tx.message === 'Glidera transaction' && isGlidera) { - tx.isGlidera = true; - if (tx.canBeRemoved) { - tx.canBeRemoved = (Date.now() / 1000 - (tx.ts || tx.createdOn)) > GLIDERA_LOCK_TIME; + if ($scope.tx.message === 'Glidera transaction' && isGlidera) { + $scope.tx.isGlidera = true; + if ($scope.tx.canBeRemoved) { + $scope.tx.canBeRemoved = (Date.now() / 1000 - ($scope.tx.ts || $scope.tx.createdOn)) > GLIDERA_LOCK_TIME; } } - var setSendError = function(msg) { + var setError = function (err, prefix) { $scope.sendStatus = ''; - var error = msg || gettextCatalog.getString('Could not send payment'); - popupService.showAlert(gettextCatalog.getString('Error'), error); - } + $scope.loading = false; + popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err, prefix)); + }; $scope.sign = function(onSendStatusChange) { $scope.loading = true; walletService.publishAndSign($scope.wallet, $scope.tx, function(err, txp) { $scope.$emit('UpdateTx'); - if (err) return setSendError(err); + if (err) return setError(err, gettextCatalog.getString('Could not send payment')); success(); }, onSendStatusChange); }; - function setError(err, prefix) { - $scope.loading = false; - popupService.showAlert(gettextCatalog.getString('Error'), bwcError.msg(err, prefix)); - }; - $scope.reject = function(txp) { var title = gettextCatalog.getString('Warning!'); var msg = gettextCatalog.getString('Are you sure you want to reject this transaction?'); @@ -150,69 +180,46 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi return $scope.wallet.credentials.networkName.substring(0, 4); }; - function checkPaypro() { - if (tx.payProUrl && !platformInfo.isChromeApp) { - $scope.wallet.fetchPayPro({ - payProUrl: tx.payProUrl, - }, function(err, paypro) { - if (err) return; - tx.paypro = paypro; - paymentTimeControl(tx.paypro.expires); - $timeout(function() { - $ionicScrollDelegate.resize(); - }, 10); - }); - } - }; - - function paymentTimeControl(expirationTime) { - $scope.paymentExpired = false; - setExpirationTime(); - - countDown = $interval(function() { - setExpirationTime(); - }, 1000); - - function setExpirationTime() { - var now = Math.floor(Date.now() / 1000); - if (now > expirationTime) { - $scope.paymentExpired = true; - if (countDown) $interval.cancel(countDown); + var updateTxInfo = function(eventName) { + $scope.wallet.getTx($scope.tx.id, function(err, tx) { + if (err) { + if (err.message && err.message == 'TX_NOT_FOUND' && + (eventName == 'transactionProposalRemoved' || eventName == 'TxProposalRemoved')) { + $scope.tx.removed = true; + $scope.tx.canBeRemoved = false; + $scope.tx.pendingForUs = false; + $scope.$apply(); + } return; } - var totalSecs = expirationTime - now; - var m = Math.floor(totalSecs / 60); - var s = totalSecs % 60; - $scope.expires = ('0' + m).slice(-2) + ":" + ('0' + s).slice(-2); - }; + + var action = lodash.find(tx.actions, { + copayerId: $scope.wallet.credentials.copayerId + }); + + $scope.tx = txFormatService.processTx(tx); + + if (!action && tx.status == 'pending') + $scope.tx.pendingForUs = true; + + $scope.updateCopayerList(); + initActionList(); + $scope.$apply(); + }); }; - lodash.each(['TxProposalRejectedBy', 'TxProposalAcceptedBy', 'transactionProposalRemoved', 'TxProposalRemoved', 'NewOutgoingTx', 'UpdateTx'], function(eventName) { - $rootScope.$on(eventName, function() { - $scope.wallet.getTx($scope.tx.id, function(err, tx) { - if (err) { - if (err.message && err.message == 'TX_NOT_FOUND' && - (eventName == 'transactionProposalRemoved' || eventName == 'TxProposalRemoved')) { - $scope.tx.removed = true; - $scope.tx.canBeRemoved = false; - $scope.tx.pendingForUs = false; - $scope.$apply(); - } - return; - } - - var action = lodash.find(tx.actions, { - copayerId: $scope.wallet.credentials.copayerId - }); - - $scope.tx = txFormatService.processTx(tx); - - if (!action && tx.status == 'pending') - $scope.tx.pendingForUs = true; - - $scope.updateCopayerList(); - $scope.$apply(); - }); + var bwsEvent = $rootScope.$on('bwsEvent', function(e, walletId, type, n) { + lodash.each([ + 'TxProposalRejectedBy', + 'TxProposalAcceptedBy', + 'transactionProposalRemoved', + 'TxProposalRemoved', + 'NewOutgoingTx', + 'UpdateTx' + ], function(eventName) { + if (walletId == $scope.wallet.id && type == eventName) { + updateTxInfo(eventName); + } }); }); @@ -252,6 +259,7 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi }; $scope.close = function() { + bwsEvent(); $scope.loading = null; $scope.txpDetailsModal.hide(); }; From cc88ddf295a908ca3119704ac5688acddc744d3e Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Thu, 3 Nov 2016 13:49:37 -0300 Subject: [PATCH 3/8] Adds confirmation before delete transaction. Fix delete transaction --- src/js/controllers/modals/txpDetails.js | 32 +++++++++++++------------ 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/js/controllers/modals/txpDetails.js b/src/js/controllers/modals/txpDetails.js index 7d8918e18..975132f42 100644 --- a/src/js/controllers/modals/txpDetails.js +++ b/src/js/controllers/modals/txpDetails.js @@ -141,22 +141,24 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi }; $scope.remove = function() { - $scope.loading = true; + var title = gettextCatalog.getString('Warning!'); + var msg = gettextCatalog.getString('Are you sure you want to remove this transaction?'); + popupService.showConfirm(title, msg, null, null, function(res) { + if (res) { + ongoingProcess.set('removeTx', true); + walletService.removeTx($scope.wallet, $scope.tx, function(err) { + ongoingProcess.set('removeTx', false); - $timeout(function() { - ongoingProcess.set('removeTx', true); - walletService.removeTx($scope.wallet, $scope.tx, function(err) { - ongoingProcess.set('removeTx', false); + // Hacky: request tries to parse an empty response + if (err && !(err.message && err.message.match(/Unexpected/))) { + $scope.$emit('UpdateTx'); + return setError(err, gettextCatalog.getString('Could not delete payment proposal')); + } - // Hacky: request tries to parse an empty response - if (err && !(err.message && err.message.match(/Unexpected/))) { - $scope.$emit('UpdateTx'); - return setError(err, gettextCatalog.getString('Could not delete payment proposal')); - } - - $scope.close(); - }); - }, 10); + $scope.close(); + }); + } + }); }; $scope.broadcast = function(txp) { @@ -183,7 +185,7 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi var updateTxInfo = function(eventName) { $scope.wallet.getTx($scope.tx.id, function(err, tx) { if (err) { - if (err.message && err.message == 'TX_NOT_FOUND' && + if (err.message && err.message == 'Transaction proposal not found' && (eventName == 'transactionProposalRemoved' || eventName == 'TxProposalRemoved')) { $scope.tx.removed = true; $scope.tx.canBeRemoved = false; From ff4041b5e5801c11a8e3b6777b7f8a43afb20d1a Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Thu, 3 Nov 2016 16:02:47 -0300 Subject: [PATCH 4/8] Removes unused variable --- src/js/controllers/modals/txpDetails.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/js/controllers/modals/txpDetails.js b/src/js/controllers/modals/txpDetails.js index 975132f42..eb88b5d02 100644 --- a/src/js/controllers/modals/txpDetails.js +++ b/src/js/controllers/modals/txpDetails.js @@ -5,7 +5,6 @@ angular.module('copayApp.controllers').controller('txpDetailsController', functi var GLIDERA_LOCK_TIME = 6 * 60 * 60; var now = Math.floor(Date.now() / 1000); var countDown; - var listeners = []; $scope.init = function() { $scope.loading = null; From 91f8dccc1b0a1e5a3ce7304c422b912961886eac Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Fri, 4 Nov 2016 17:03:20 -0300 Subject: [PATCH 5/8] Updates tx-detail --- .../{modals/txDetails.js => tx-details.js} | 54 ++++++------------- src/js/routes.js | 2 +- www/views/{modals => }/tx-details.html | 4 +- 3 files changed, 18 insertions(+), 42 deletions(-) rename src/js/controllers/{modals/txDetails.js => tx-details.js} (67%) rename www/views/{modals => }/tx-details.html (96%) diff --git a/src/js/controllers/modals/txDetails.js b/src/js/controllers/tx-details.js similarity index 67% rename from src/js/controllers/modals/txDetails.js rename to src/js/controllers/tx-details.js index ea2cb431a..680e83af2 100644 --- a/src/js/controllers/modals/txDetails.js +++ b/src/js/controllers/tx-details.js @@ -1,27 +1,21 @@ 'use strict'; -angular.module('copayApp.controllers').controller('txDetailsController', function($log, $timeout, $ionicHistory, $scope, $filter, $stateParams, ongoingProcess, walletService, lodash, gettextCatalog, profileService, configService, txFormatService, externalLinkService, popupService) { - var config = configService.getSync(); - var configWallet = config.wallet; - var walletSettings = configWallet.settings; - var wallet = profileService.getWallet($stateParams.walletId); +angular.module('copayApp.controllers').controller('txDetailsController', function($log, $timeout, $ionicHistory, $scope, $stateParams, walletService, lodash, gettextCatalog, profileService, configService, externalLinkService, popupService) { - $scope.wallet = wallet; - $scope.title = gettextCatalog.getString('Transaction'); + $scope.$on("$ionicView.beforeEnter", function(event, data) { + $scope.title = gettextCatalog.getString('Transaction'); + $scope.wallet = profileService.getWallet(data.stateParams.walletId); + $scope.color = $scope.wallet.color; + $scope.copayerId = $scope.wallet.credentials.copayerId; + $scope.isShared = $scope.wallet.credentials.n > 1; - $scope.init = function() { - $scope.alternativeIsoCode = walletSettings.alternativeIsoCode; - $scope.color = wallet.color; - $scope.copayerId = wallet.credentials.copayerId; - $scope.isShared = wallet.credentials.n > 1; - walletService.getTx(wallet, $stateParams.txid, function(err, tx) { + walletService.getTx($scope.wallet, $stateParams.txid, function(err, tx) { if (err) { $log.warn('Could not get tx'); $ionicHistory.goBack(); return; } $scope.btx = tx; - $scope.btx.feeLevel = walletSettings.feeLevel; if ($scope.btx.action != 'invalid') { if ($scope.btx.action == 'sent') $scope.title = gettextCatalog.getString('Sent Funds'); if ($scope.btx.action == 'received') $scope.title = gettextCatalog.getString('Received Funds'); @@ -34,7 +28,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio updateMemo(); initActionList(); }); - }; + }); function getDisplayAmount(amountStr) { return amountStr.split(' ')[0]; @@ -45,7 +39,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio } function updateMemo() { - walletService.getTxNote(wallet, $scope.btx.txid, function(err, note) { + walletService.getTxNote($scope.wallet, $scope.btx.txid, function(err, note) { if (err) { $log.warn('Could not fetch transaction note: ' + err); return; @@ -53,18 +47,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio if (!note) return; $scope.btx.note = note; - - walletService.getTx(wallet, $scope.btx.txid, function(err, tx) { - if (err) { - $log.error(err); - return; - } - - tx.note = note; - $timeout(function() { - $scope.$apply(); - }); - }); + $scope.$apply(); }); } @@ -109,9 +92,10 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio } if ($scope.btx.note && $scope.btx.note.body) opts.defaultText = $scope.btx.note.body; - popupService.showPrompt(wallet.name, gettextCatalog.getString('Memo'), opts, function(text) { + popupService.showPrompt($scope.wallet.name, gettextCatalog.getString('Memo'), opts, function(text) { if (typeof text == "undefined") return; + $scope.btx.note.body = text; $log.debug('Saving memo'); var args = { @@ -119,17 +103,10 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio body: text }; - walletService.editTxNote(wallet, args, function(err, res) { + walletService.editTxNote($scope.wallet, args, function(err, res) { if (err) { $log.debug('Could not save tx comment ' + err); - return; } - // This is only to refresh the current screen data - updateMemo(); - $scope.btx.searcheableString = null; - $timeout(function() { - $scope.$apply(); - }); }); }); }; @@ -147,7 +124,7 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio }; $scope.getShortNetworkName = function() { - var n = wallet.credentials.network; + var n = $scope.wallet.credentials.network; return n.substring(0, 4); }; @@ -155,5 +132,4 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio $scope.txDetailsModal.hide(); }; - $scope.init(); }); diff --git a/src/js/routes.js b/src/js/routes.js index f9d36f2c9..2b92f5af2 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -182,7 +182,7 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr views: { 'tab-home@tabs': { controller: 'txDetailsController', - templateUrl: 'views/modals/tx-details.html' + templateUrl: 'views/tx-details.html' } } }) diff --git a/www/views/modals/tx-details.html b/www/views/tx-details.html similarity index 96% rename from www/views/modals/tx-details.html rename to www/views/tx-details.html index 6297683d2..790a34c50 100644 --- a/www/views/modals/tx-details.html +++ b/www/views/tx-details.html @@ -47,14 +47,14 @@ {{btx.creatorName}} - + Memo {{btx.note.body || btx.message}} -
+
Fee {{btx.feeStr}} From 5771b22c68467d139cd7e95c1aaeafdff65dc887 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Fri, 4 Nov 2016 17:15:18 -0300 Subject: [PATCH 6/8] Fix Search: open tx detail --- src/js/controllers/walletDetails.js | 10 +++++++++- www/views/modals/search.html | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/js/controllers/walletDetails.js b/src/js/controllers/walletDetails.js index 6fd7a8b30..f90361ec2 100644 --- a/src/js/controllers/walletDetails.js +++ b/src/js/controllers/walletDetails.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, profileService, lodash, configService, gettextCatalog, platformInfo, walletService, txpModalService, externalLinkService, popupService, addressbookService) { +angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $state, $stateParams, $ionicHistory, profileService, lodash, configService, gettextCatalog, platformInfo, walletService, txpModalService, externalLinkService, popupService, addressbookService) { var HISTORY_SHOW_LIMIT = 10; var currentTxHistoryPage = 0; @@ -87,6 +87,14 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun $scope.close = function() { $scope.searchModal.hide(); }; + + $scope.openTx = function(tx) { + $ionicHistory.nextViewOptions({ + disableAnimate: true + }); + $scope.searchModal.hide(); + $scope.openTxModal(tx); + }; }; $scope.openTxModal = function(btx) { diff --git a/www/views/modals/search.html b/www/views/modals/search.html index ec2f0cd82..ed507f76f 100644 --- a/www/views/modals/search.html +++ b/www/views/modals/search.html @@ -18,7 +18,7 @@
-
+
From b3fdec3d782691f546ca316766eecbae59f65500 Mon Sep 17 00:00:00 2001 From: Gustavo Maximiliano Cortez Date: Tue, 8 Nov 2016 09:58:48 -0300 Subject: [PATCH 7/8] Fix error for empty notes --- src/js/controllers/tx-details.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/js/controllers/tx-details.js b/src/js/controllers/tx-details.js index 680e83af2..e41cca9c2 100644 --- a/src/js/controllers/tx-details.js +++ b/src/js/controllers/tx-details.js @@ -95,7 +95,9 @@ angular.module('copayApp.controllers').controller('txDetailsController', functio popupService.showPrompt($scope.wallet.name, gettextCatalog.getString('Memo'), opts, function(text) { if (typeof text == "undefined") return; - $scope.btx.note.body = text; + $scope.btx.note = { + body: text + }; $log.debug('Saving memo'); var args = { From 2e19bee5fc0d6dc8a40770bf5d879f70583fbb95 Mon Sep 17 00:00:00 2001 From: Jason Dreyzehner Date: Wed, 9 Nov 2016 12:11:40 -0500 Subject: [PATCH 8/8] chore(scripts): add placeholder start:desktop package script --- app-template/package-template.json | 1 + 1 file changed, 1 insertion(+) diff --git a/app-template/package-template.json b/app-template/package-template.json index a1d87faf0..a52f16e90 100644 --- a/app-template/package-template.json +++ b/app-template/package-template.json @@ -87,6 +87,7 @@ "start": "npm run build:www && ionic serve --nolivereload --nogulp -s", "start:ios": "npm run build:www && npm run build:ios && npm run open:ios", "start:android": "npm run build:www && npm run build:android && npm run run:android", + "start:desktop": "npm start", "watch": "grunt watch", "build:www": "grunt", "build:www-release": "grunt prod",