diff --git a/public/views/activity.html b/public/views/activity.html new file mode 100644 index 000000000..2885b2fb5 --- /dev/null +++ b/public/views/activity.html @@ -0,0 +1,32 @@ + + + + Recent Activity + + + +
+
+ +
+
+
Updating activity. Please stand by.
+
+
+ + +
+
+
    +
  • + +
  • + +
  • + No recent activity +
  • +
+
+
+
+
diff --git a/public/views/includes/walletActivity.html b/public/views/includes/walletActivity.html new file mode 100644 index 000000000..408e78c1c --- /dev/null +++ b/public/views/includes/walletActivity.html @@ -0,0 +1,38 @@ + + + + + {{x.amountStr}} + + + + + + Proposal Deleted + + + + + Proposal Rejected + + + + + + {{x.message}} + + + + Proposal Accepted + + + + +
+ + · + + {{ x.creatorName}}@{{x.wallet.name}} + · +
+ diff --git a/public/views/tab-home.html b/public/views/tab-home.html index 322a2e0f3..a4d5b572f 100644 --- a/public/views/tab-home.html +++ b/public/views/tab-home.html @@ -6,30 +6,36 @@ -
-

Activity

-
+

Activity

+
+
+ +
+
+
Updating activity. Please stand by.
+
+
+
+ +
+
    -
  • - - bla bla - -
    - blo blo · -
    +
  • +
  • -
  • +
  • +
  • + No recent activity +
- -

Wallets

diff --git a/src/js/controllers/activity.js b/src/js/controllers/activity.js new file mode 100644 index 000000000..ccbfc215e --- /dev/null +++ b/src/js/controllers/activity.js @@ -0,0 +1,47 @@ +'use strict'; + +angular.module('copayApp.controllers').controller('activityController', + function($rootScope, $timeout, $scope, $state, lodash, profileService, walletService, configService, txFormatService, $ionicModal, $log, platformInfo) { + var self = this; + + var setNotifications = function(notifications) { + var n = walletService.processNotifications(notifications); + + $scope.notifications = n; + $timeout(function() { + $scope.$apply(); + }, 1); + }; + + + + + $scope.init = function() { + $scope.wallets = profileService.getWallets(); + + var i = $scope.wallets.length, + j = 0; + // var timeSpan = 60 * 60 * 24 * 7; TODO + var timeSpan = 60 * 60 * 6; + var notifications = []; + + $scope.fetchingNotifications = true; + + lodash.each($scope.wallets, function(wallet) { + + walletService.getNotifications(wallet, { + timeSpan: timeSpan + }, function(err, n) { + if (err) { + console.log('[tab-home.js.35:err:]', $log.error(err)); //TODO + return; + } + notifications.push(n); + if (++j == i) { + $scope.fetchingNotifications = false; + setNotifications(lodash.compact(lodash.flatten(notifications))); + }; + }); + }); + } + }); diff --git a/src/js/controllers/tab-home.js b/src/js/controllers/tab-home.js index cee57243b..614b5976b 100644 --- a/src/js/controllers/tab-home.js +++ b/src/js/controllers/tab-home.js @@ -4,27 +4,58 @@ angular.module('copayApp.controllers').controller('tabHomeController', function($rootScope, $timeout, $scope, $state, lodash, profileService, walletService, configService, txFormatService, $ionicModal, $log, platformInfo) { var self = this; - self.setWallets = function() { - $scope.wallets = profileService.getWallets(); + var setNotifications = function(notifications) { + + var n = walletService.processNotifications(notifications, 5); + + $scope.notifications = n; + $scope.notificationsMore = notifications.length > 5 ? notifications.length - 5 : null; + $timeout(function() { + $scope.$apply(); + }, 1); + }; + + self.updateAllWallets = function() { $scope.wallets = profileService.getWallets(); - var i = $scope.wallets.length; + var i = $scope.wallets.length, j =0; +// var timeSpan = 60 * 60 * 24 * 7; + var timeSpan = 60 * 60 * 24 * 1; + var notifications = []; + + $scope.fetchingNotifications = true; + lodash.each($scope.wallets, function(wallet) { + walletService.getStatus(wallet, {}, function(err, status) { if (err) { console.log('[tab-home.js.35:err:]', $log.error(err)); //TODO return; - } + } wallet.status = status; }); + + walletService.getNotifications(wallet, { + timeSpan: timeSpan + }, function(err, n) { + if (err) { + console.log('[tab-home.js.35:err:]', $log.error(err)); //TODO + return; + } + notifications.push(n); + if (++j == i) { + $scope.fetchingNotifications = false; + setNotifications(lodash.compact(lodash.flatten(notifications))); + }; + }); + }); } self.updateWallet = function(wallet) { - $log.debug('Updating wallet:' + wallet.name) walletService.getStatus(wallet, {}, function(err, status) { if (err) { @@ -32,7 +63,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', return; } wallet.status = status; - $timeout(function(){ + $timeout(function() { $scope.$apply(); }, 1); }); @@ -55,7 +86,7 @@ angular.module('copayApp.controllers').controller('tabHomeController', ]; $scope.$on('$destroy', function() { - lodash.each(listeners, function(x){ + lodash.each(listeners, function(x) { x(); }); }); diff --git a/src/js/controllers/walletDetails.js b/src/js/controllers/walletDetails.js index 459d4a224..1d4e42b4c 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, $ionicNavBarDelegate, $state, $stateParams, bwcError, profileService, lodash, configService, gettext, gettextCatalog, platformInfo, walletService, storageService) { +angular.module('copayApp.controllers').controller('walletDetailsController', function($scope, $rootScope, $interval, $timeout, $filter, $log, $ionicModal, $ionicPopover, $ionicNavBarDelegate, $state, $stateParams, bwcError, profileService, lodash, configService, gettext, gettextCatalog, platformInfo, walletService, storageService, $ionicPopup) { var isCordova = platformInfo.isCordova; var isWP = platformInfo.isWP; @@ -39,10 +39,10 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun setPendingTxps(status.pendingTxps); $scope.status = status; - $timeout(function(){ + $timeout(function() { $scope.$apply(); }, 1); - + }); }; @@ -80,7 +80,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun ]; $scope.$on('$destroy', function() { - lodash.each(listeners, function(x){ + lodash.each(listeners, function(x) { x(); }); }); @@ -117,7 +117,7 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun walletService.recreate(); }; - $scope.updateTxHistory = function() { + $scope.updateTxHistory = function(cb) { if ($scope.updatingTxHistory) return; @@ -129,10 +129,10 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun $scope.updatingTxHistoryProgress = txs ? txs.length : 0; $scope.completeTxHistory = txs; $scope.showHistory(); - $timeout(function(){ + $timeout(function() { $scope.$apply(); }, 1); - + }; $timeout(function() { @@ -148,9 +148,11 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun $scope.completeTxHistory = txHistory; $scope.showHistory(); - $timeout(function(){ + + $timeout(function() { $scope.$apply(); }, 1); + return cb(); }); }); }; @@ -168,9 +170,9 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun $scope.$broadcast('scroll.infiniteScrollComplete'); }; - $scope.updateAll = function()  { + $scope.updateAll = function(cb)  { $scope.updateStatus(false); - $scope.updateTxHistory(); + $scope.updateTxHistory(cb); } var hideBalance = function() { @@ -200,7 +202,30 @@ angular.module('copayApp.controllers').controller('walletDetailsController', fun hideBalance(); $ionicNavBarDelegate.title(wallet.name); - $scope.updateAll(); - }; - + $scope.updateAll(function() { + if ($stateParams.txid) { + var txp = lodash.find($scope.completeTxHistory, { + txid: $stateParams.txid + }); + if (txp) { + $scope.openTxModal(tx); + } else { + $ionicPopup.alert({ + title: gettext('TX not available'), + }); + } + } else if ($stateParams.txpId) { + var txp = lodash.find($scope.txps, { + id: $stateParams.txpId + }); + if (txp) { + $scope.openTxpModal(txp); + } else { + $ionicPopup.alert({ + title: gettext('Proposal not longer available'), + }); + } + } + }); + } }); diff --git a/src/js/routes.js b/src/js/routes.js index 5c1e95d18..14cff17a8 100644 --- a/src/js/routes.js +++ b/src/js/routes.js @@ -121,7 +121,10 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr }, needProfile: true }) - + .state('activity', { + url: '/activity', + templateUrl: 'views/activity.html' + }) /* * @@ -140,7 +143,11 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr 'wallet': { templateUrl: 'views/walletDetails.html' } - } + }, + params: { + txid: null, + txpId: null, + }, }) .state('wallet.preferences', { url: '/preferences', @@ -274,6 +281,8 @@ angular.module('copayApp').config(function(historicLogProvider, $provide, $logPr } }) + + /* * * Tabs diff --git a/src/js/services/walletService.js b/src/js/services/walletService.js index 284b3eaca..3165a89d8 100644 --- a/src/js/services/walletService.js +++ b/src/js/services/walletService.js @@ -1,6 +1,6 @@ 'use strict'; -angular.module('copayApp.services').factory('walletService', function($log, $timeout, lodash, trezor, ledger, storageService, configService, rateService, uxLanguage, $filter, gettextCatalog, bwcError, $ionicPopup, fingerprintService, ongoingProcess, gettext, $rootScope, txStatus, txFormatService, $ionicModal, $state) { +angular.module('copayApp.services').factory('walletService', function($log, $timeout, lodash, trezor, ledger, storageService, configService, rateService, uxLanguage, $filter, gettextCatalog, bwcError, $ionicPopup, fingerprintService, ongoingProcess, gettext, $rootScope, txStatus, txFormatService, $ionicModal, $state, bwcService) { // `wallet` is a decorated version of client. var root = {}; @@ -765,10 +765,10 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim includeCopayerBranches: true, }, function(err) { - if (err && wallet.walletId == walletId) { - wallet.updating = false; - handleError(err); - } + if (err && wallet.walletId == walletId) { + wallet.updating = false; + handleError(err); + } }); }; @@ -998,33 +998,61 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim }); }); }; - root.getEncodedWalletInfo = function(wallet,cb){ + + root.getNotifications = function(wallet, opts, cb) { + + wallet.getNotifications(opts, function(err, notifications) { + if (err) return cb(err); + + notifications = lodash.filter(notifications, function(x) { + return x.type != 'NewBlock' && x.type != 'BalanceUpdated'; + }); + + var idToName = {}; + if (wallet.cachedStatus) { + lodash.each(wallet.cachedStatus.wallet.copayers, function(c) { + idToName[c.id] = c.name; + }); + } + + lodash.each(notifications, function(x) { + x.wallet = wallet; + if (x.creatorId && wallet.cachedStatus) { + x.creatorName = idToName[x.creatorId]; + }; + }); + + return cb(null, notifications); + }); + }; + + root.getEncodedWalletInfo = function(wallet, cb) { var getCode = function() { - var derivationPath = wallet.credentials.getBaseAddressDerivationPath(); - var encodingType = { - mnemonic: 1, - xpriv: 2, - xpub: 3 - }; - var info; + var derivationPath = wallet.credentials.getBaseAddressDerivationPath(); + var encodingType = { + mnemonic: 1, + xpriv: 2, + xpub: 3 + }; + var info; - // not supported yet - if (wallet.credentials.derivationStrategy != 'BIP44' || !wallet.canSign()) - return null; + // not supported yet + if (wallet.credentials.derivationStrategy != 'BIP44' || !wallet.canSign()) + return null; - if (wallet.credentials.mnemonic) { - info = { - type: encodingType.mnemonic, - data: wallet.credentials.mnemonic, - } - } else { - info = { - type: encodingType.xpriv, - data: wallet.credentials.xPrivKey - } + if (wallet.credentials.mnemonic) { + info = { + type: encodingType.mnemonic, + data: wallet.credentials.mnemonic, } - return info.type + '|' + info.data + '|' + wallet.credentials.network.toLowerCase() + '|' + derivationPath + '|' + (wallet.credentials.mnemonicHasPassphrase); + } else { + info = { + type: encodingType.xpriv, + data: wallet.credentials.xPrivKey + } + } + return info.type + '|' + info.data + '|' + wallet.credentials.network.toLowerCase() + '|' + derivationPath + '|' + (wallet.credentials.mnemonicHasPassphrase); }; fingerprintService.check(wallet, function(err) { @@ -1034,11 +1062,66 @@ angular.module('copayApp.services').factory('walletService', function($log, $tim if (err) return cb(err); var code = getCode(); -console.log('[walletService.js.948:code:]',code); //TODO + console.log('[walletService.js.948:code:]', code); //TODO return cb(null, code); }); }); }; + root.processNotifications = function(notifications, limit) { + if (!notifications) return []; + + var shown = lodash.sortBy(notifications, 'createdOn').reverse(); + + if (limit) + shown = shown.splice(0, limit); + + lodash.each(shown, function(x) { + x.txpId = x.data ? x.data.txProposalId : null; + x.txid = x.data ? x.data.txid : null; + x.types = [x.type]; + + if (x.data && x.data.amount) + x.amountStr = txFormatService.formatAmountStr(x.data.amount); + + x.action = function() { + // TODO? + $state.go('wallet.details', { + walletId: x.walletId, + txpId: x.txpId, + txid: x.txid, + }); + }; + }); + + // condense + var finale = [], + prev; + + + lodash.each(shown, function(x) { + if (prev && prev.walletId === x.walletId && prev.txpId && prev.txpId === x.txpId) { + prev.types.push(x.type); + prev.data = lodash.assign(prev.data, x.data); + prev.txid = prev.txid || x.txid; + } else { + finale.push(x); + prev = x; + } + }); + + // messsages... + + var u = bwcService.getUtils(); + lodash.each(finale, function(x) { + if (x.data && x.data.message && x.wallet && x.wallet.credentials.sharedEncryptingKey) { + // TODO TODO TODO => BWC + x.message = u.decryptMessage(x.data.message, x.wallet.credentials.sharedEncryptingKey); + } + }); + + return finale; + }; + return root; });