From 42d27215809a0a542426b82f859c0f62eafc534a Mon Sep 17 00:00:00 2001 From: Benoit Lavenier <benoit.lavenier@e-is.pro> Date: Fri, 20 Dec 2019 19:31:01 +0100 Subject: [PATCH] [enh] Allow to switch between secondary wallets more easily [enh] Allow to see message of secondary wallets [fix] Fix crypto error for use of js-nacl [fix] Wot identity: Adapt hero header when QRcode is zoom --- www/js/config.js | 56 +- www/js/controllers/blockchain-controllers.js | 4 +- www/js/controllers/currency-controllers.js | 2 +- www/js/controllers/network-controllers.js | 12 +- www/js/controllers/wallet-controllers.js | 27 +- www/js/controllers/wallets-controllers.js | 696 +++++++++--------- www/js/controllers/wot-controllers.js | 4 +- www/js/services/crypto-services.js | 94 ++- www/js/services/modal-services.js | 49 +- www/js/services/utils-services.js | 7 +- www/js/services/wallet-services.js | 2 +- .../es/js/controllers/app-controllers.js | 2 +- .../es/js/controllers/document-controllers.js | 2 +- .../es/js/controllers/message-controllers.js | 275 ++++--- .../es/js/controllers/profile-controllers.js | 6 +- .../es/js/controllers/registry-controllers.js | 4 +- .../controllers/subscription-controllers.js | 18 +- .../es/js/controllers/wot-controllers.js | 2 +- .../es/js/services/comment-services.js | 7 +- .../es/js/services/document-services.js | 14 +- www/plugins/es/js/services/http-services.js | 30 +- .../es/js/services/invitation-services.js | 51 +- .../es/js/services/message-services.js | 103 ++- .../es/js/services/subscription-services.js | 8 +- www/plugins/es/templates/message/list.html | 4 +- .../es/templates/message/lookup_by_id.html | 17 + .../es/templates/message/lookup_lg.html | 34 +- .../es/templates/message/popover_message.html | 2 +- .../wallet/list/item_wallet_light.html | 2 +- .../wallet/list/popover_wallets.html | 32 +- www/templates/wallet/list/view_wallets.html | 3 + www/templates/wallet/view_wallet.html | 21 +- www/templates/wot/view_identity.html | 2 +- 33 files changed, 912 insertions(+), 680 deletions(-) create mode 100644 www/plugins/es/templates/message/lookup_by_id.html diff --git a/www/js/config.js b/www/js/config.js index de9aeab2e..166c63d8e 100644 --- a/www/js/config.js +++ b/www/js/config.js @@ -12,78 +12,38 @@ angular.module("cesium.config", []) "cacheTimeMs": 300000, "fallbackLanguage": "en", "rememberMe": true, - "showUDHistory": true, - "timeout": 40000, + "timeout": 300000, "timeWarningExpireMembership": 5184000, "timeWarningExpire": 7776000, - "keepAuthIdle": 600, "useLocalStorage": true, "useRelative": false, - "expertMode": false, + "expertMode": true, "decimalCount": 2, - "httpsMode": false, "shareBaseUrl": "https://g1.duniter.fr", "helptip": { - "enable": true, + "enable": false, "installDocUrl": { "fr-FR": "https://duniter.org/fr/wiki/duniter/installer/", - "en": "https://duniter.org/en/wiki/duniter/install/" + "en": "https://github.com/duniter/duniter/blob/master/doc/install-a-node.md" } }, - "license": { - "en": "license/license_g1-en", - "fr-FR": "license/license_g1-fr-FR", - "es-ES": "license/license_g1-es-ES" - }, "node": { - "host": "g1.duniter.org", + "host": "g1-test.duniter.org", "port": 443 }, "fallbackNodes": [ { - "host": "g1.nordstrom.duniter.org", - "port": 443 - }, - { - "host": "g1.cgeek.fr", - "port": 443 - }, - { - "host": "g1.monnaielibreoccitanie.org", - "port": 443 - }, - { - "host": "g1.le-sou.org", - "port": 443 - }, - { - "host": "g1.duniter.fr", + "host": "g1-test.cgeek.fr", "port": 443 } ], - "developers": [ - { - "name": "Benoit Lavenier", - "pubkey": "38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE" - } - ], "plugins": { "es": { "enable": true, "askEnable": true, "useRemoteStorage": true, - "host": "g1.data.duniter.fr", + "host": "g1-test.data.duniter.fr", "port": 443, - "fallbackNodes": [ - { - "host": "g1.data.le-sou.org", - "port": 443 - }, - { - "host": "g1.data.duniter.fr", - "port": 443 - } - ], "notifications": { "txSent": true, "txReceived": true, @@ -94,7 +54,7 @@ angular.module("cesium.config", []) } }, "version": "1.4.12", - "build": "2019-11-16T13:39:37.358Z", + "build": "2019-12-19T14:53:37.759Z", "newIssueUrl": "https://git.duniter.org/clients/cesium-grp/cesium/issues/new" }) diff --git a/www/js/controllers/blockchain-controllers.js b/www/js/controllers/blockchain-controllers.js index 983f762ca..efd8e141c 100644 --- a/www/js/controllers/blockchain-controllers.js +++ b/www/js/controllers/blockchain-controllers.js @@ -331,12 +331,12 @@ function BlockLookupController($scope, $timeout, $focus, $filter, $state, $ancho $scope.smallscreen = UIUtils.screen.isSmall(); + $scope.$broadcast('$$rebind::rebind'); // notify binder + // Set Motion if (res && res.length) { $scope.motion.show({selector: '.list-blocks .item-block'}); } - - $scope.$broadcast('$$rebind::rebind'); // notify binder }; $scope.showMore = function() { diff --git a/www/js/controllers/currency-controllers.js b/www/js/controllers/currency-controllers.js index 30467cb70..985276bed 100644 --- a/www/js/controllers/currency-controllers.js +++ b/www/js/controllers/currency-controllers.js @@ -235,7 +235,7 @@ function CurrencyViewController($scope, $q, $timeout, $ionicPopover, Modals, BMA console.debug("[currency] Parameters loaded in " + (Date.now() - now) + 'ms' ); $scope.loading = false; - $scope.$broadcast('$$rebind::' + 'rebind'); // force bind of currency name + $scope.$broadcast('$$rebind::rebind'); // force bind of currency name // Set Ink UIUtils.ink(); diff --git a/www/js/controllers/network-controllers.js b/www/js/controllers/network-controllers.js index bfeb74bbf..0fdbb64ea 100644 --- a/www/js/controllers/network-controllers.js +++ b/www/js/controllers/network-controllers.js @@ -179,17 +179,17 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.updateView = function(data) { console.debug("[peers] Updating UI"); - $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding + $scope.$broadcast('$$rebind::rebind'); // force data binding $scope.search.results = data.peers; $scope.search.memberPeersCount = data.memberPeersCount; // Always tru if network not started (e.g. after leave+renter the view) $scope.search.loading = !$scope.networkStarted || csNetwork.isBusy(); + if (!$scope.loading) { + $scope.$broadcast('$$rebind::rebind'); // force data binding + } if ($scope.motion && $scope.search.results && $scope.search.results.length > 0) { $scope.motion.show({selector: '.item-peer'}); } - if (!$scope.loading) { - $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding - } }; $scope.refresh = function() { @@ -248,7 +248,7 @@ function NetworkLookupController($scope, $state, $location, $ionicPopover, $win $scope.toggleCompactMode = function() { $scope.compactMode = !$scope.compactMode; - $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding + $scope.$broadcast('$$rebind::rebind'); // force data binding }; $scope.selectPeer = function(peer) { @@ -506,7 +506,7 @@ function PeerInfoPopoverController($scope, $q, csSettings, csCurrency, csHttp, B $scope.formData.hasNewRelease = false; } $scope.loading = false; - $scope.$broadcast('$$rebind::' + 'rebind'); // force data binding + $scope.$broadcast('$$rebind::rebind'); // force data binding }); }; diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js index 5fe49a977..920a25f9f 100644 --- a/www/js/controllers/wallet-controllers.js +++ b/www/js/controllers/wallet-controllers.js @@ -114,7 +114,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $scope.updateView = function() { $scope.motion.show({selector: '#wallet .item'}); - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::rebind'); // force rebind }; @@ -558,7 +558,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, .then(function(done){ if (done) { UIUtils.toast.show('INFO.TRANSFER_SENT'); - $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance + $scope.$broadcast('$$rebind::balance'); // force rebind balance $scope.motion.show({selector: '.item-pending'}); } }); @@ -645,11 +645,13 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, }; $scope.showSelectWalletPopover = function(event) { + return csPopovers.showSelectWallet(event, { - scope: $scope - }) + parameters: { + excludedWalletId: $scope.walletId + }}) .then(function(newWallet) { - if (!newWallet || newWallet.id === wallet.id) return; + if (!newWallet || newWallet.id === $scope.walletId) return; // nothing changed if (newWallet.isDefault()) { return $state.go('app.view_wallet'); } @@ -692,6 +694,8 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, return $scope.showHome(); } + $scope.walletId = wallet.id; + $scope.cleanLocationHref(state); return $scope.load(); @@ -754,8 +758,8 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, // Update view $scope.updateView = function() { if (!$scope.formData || $scope.loading) return; - $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::balance'); // force rebind balance + $scope.$broadcast('$$rebind::rebind'); // force rebind $scope.motion.show({selector: '.view-wallet-tx .item', ink: false}); }; @@ -841,7 +845,7 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, .then(function(done){ if (done) { UIUtils.toast.show('INFO.TRANSFER_SENT'); - $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance + $scope.$broadcast('$$rebind::balance'); // force rebind balance $scope.motion.show({selector: '.item-pending'}); } }); @@ -887,8 +891,11 @@ function WalletTxController($scope, $ionicPopover, $state, $timeout, $location, if (!csWallet.children.count()) return; return Modals.showSelectWallet({ - showDefault: true, - showBalance: false + parameters: { + showDefault: true, + showBalance: false, + excludedWalletId: $scope.walletId + } }) .then(function(newWallet) { if (!newWallet || wallet && newWallet.id === wallet.id) return; diff --git a/www/js/controllers/wallets-controllers.js b/www/js/controllers/wallets-controllers.js index 5d399f787..2731fcfa5 100644 --- a/www/js/controllers/wallets-controllers.js +++ b/www/js/controllers/wallets-controllers.js @@ -9,7 +9,7 @@ angular.module('cesium.wallets.controllers', ['cesium.services', 'cesium.currenc views: { 'menuContent': { templateUrl: "templates/wallet/list/view_wallets.html", - controller: 'WalletListCtrl' + controller: 'WalletListViewCtrl' } }, data: { @@ -59,119 +59,220 @@ angular.module('cesium.wallets.controllers', ['cesium.services', 'cesium.currenc }) ; }) + .controller('WalletListAbstractCtrl', WalletListAbstractController) - - .controller('WalletListCtrl', WalletListController) + .controller('WalletListViewCtrl', WalletListViewController) .controller('WalletSelectModalCtrl', WalletSelectModalController) .controller('WalletListImportModalCtrl', WalletListImportModalController) - .controller('PopoverWalletSelectModalCtrl', PopoverWalletSelectModalController) + .controller('WalletSelectPopoverCtrl', WalletSelectPopoverController) ; -function WalletListController($scope, $controller, $state, $timeout, $q, $translate, $ionicPopover, $ionicPopup, - ModalUtils, UIUtils, Modals, csCurrency, csSettings, csWallet){ + +function WalletListAbstractController($scope, $q, $timeout, UIUtils, filterTranslations, csSettings, csCurrency, csWallet) { 'ngInject'; - $scope.settings = csSettings.data; - $scope.listeners = []; + $scope.loading = true; + $scope.wallets = null; + $scope.formData = { + useRelative: csSettings.data.useRelative, + showDefault: true, + showBalance: false, + balance: undefined, + updatingWalletId: undefined, + stopped: false, + minData: true + }; + $scope.motion = null; // no animation - // Initialize the super class and extend it. - angular.extend(this, $controller('WalletSelectModalCtrl', {$scope: $scope, parameters: {}})); + $scope.setParameters = function(parameters) { + parameters = parameters || {}; - // Override defaults - $scope.formData.name = undefined; - $scope.motion = UIUtils.motion.default; - $scope.entered = false; + $scope.formData.useRelative = angular.isDefined(parameters.useRelative) ? parameters.useRelative : $scope.formData.useRelative; + $scope.formData.showBalance = angular.isDefined(parameters.showBalance) ? parameters.showBalance : $scope.formData.showBalance; + $scope.formData.minData = angular.isDefined(parameters.minData) ? parameters.minData : $scope.formData.minData; + $scope.formData.excludedWalletId = parameters.excludedWalletId; + $scope.formData.showDefault = (angular.isDefined(parameters.showDefault) ? parameters.showDefault : $scope.formData.showDefault) + && ($scope.formData.excludedWalletId !== 'default'); - $scope.enter = function(e, state) { - // First enter - if (!$scope.entered) { - $scope.entered = true; - $scope.setParameters({ - showDefault: true, - showBalance: true, - minData: false - }); + }; - return $scope.load() - .then(function() { - UIUtils.loading.hide(); - if (!$scope.wallets) return; // user cancel, or error - $scope.addListeners(); - $scope.showFab('fab-add-wallet'); - }); + $scope.load = function(options) { + + options = options || {}; + $scope.loading = (options.silent !== false); + $scope.formData.balance = undefined; + $scope.formData.updatingWalletId = undefined; + $scope.formData.stopped = false; + + // Load currency, and filter translations (need by 'formatAmount' filter) + var jobs = []; + + jobs.push(csCurrency.name() + .then(function(currency) { + $scope.currency = currency; + return filterTranslations.ready(); + })); + + // Get children wallets + $scope.defaultWallet = $scope.formData.showDefault ? csWallet : undefined; + if (!$scope.wallets) { + jobs.push( + csWallet.children.all() + .then(function(children) { + $scope.wallets=children; + UIUtils.loading.hide(); + }) + ); } - // If already enter - else { - // Re-add listeners - $scope.addListeners(); - if ($scope.formData.stopped) { - $scope.loading = false; - $scope.formData.stopped = false; + + // Prepare load options + var walletLoadOptions = { + silent: true, + minData: $scope.formData.minData, + sources: $scope.formData.showBalance, + tx: { + enable: false + }, + api: true + }; + var hasLoadError = false; + var loadCounter = 0; + var now = Date.now(); + var balance = 0; + return (jobs.length ? $q.all(jobs) : $q.when()) + // Load wallet data (apply a timeout between each wallet) + .then(function() { + var wallets = $scope.formData.showDefault ? [csWallet].concat($scope.wallets) : $scope.wallets; + if (!wallets.length) return; + console.debug("[wallets] Loading {0} wallets...".format(wallets.length)); + return wallets.reduce(function(res, wallet) { + var skip= !options.refresh && wallet.isDataLoaded(walletLoadOptions); + if (skip) { + console.debug("[wallets] Wallet #{0} already loaded. Skipping".format(wallet.id)); + return res.then(function(){ + balance += wallet.data.balance; + $scope.updateWalletView(wallet.id); + }); + } + loadCounter++; + return res.then(function() { + if ($scope.formData.stopped) return; // skip if stopped + // Loading next wallet, after waiting some time + $scope.formData.updatingWalletId = wallet.id; + var loadPromise; + if (options.refresh && wallet.data.loaded) { + var refreshOptions = angular.merge({ + // Refresh requirements if member account + requirements: (!wallet.data.requirements.loaded || wallet.data.requirements.isMember || wallet.data.requirements.wasMember || wallet.data.requirements.pendingMembership) + }, walletLoadOptions); + loadPromise = wallet.refreshData(refreshOptions); + } + else { + loadPromise = wallet.loadData(walletLoadOptions); + } + + loadPromise.then(function(walletData) { + balance += walletData.balance; + $scope.updateWalletView(wallet.id); + }) + .catch(function(err) { + console.error("[wallets] Error while loading data of wallet #{0}".format(wallet.id), err); + hasLoadError = true; + }); + return loadPromise; + }); + }, $q.when()); + }) + .then(function() { + if (hasLoadError) { + return UIUtils.alert.error('ERROR.LOAD_WALLET_LIST_FAILED') + .then(function() { + $scope.resetData(); + $scope.cancel(); + }); + } + // Stop + if ($scope.formData.stopped) return; + if (loadCounter) { + console.debug("[wallets] Loaded data of {0} wallet(s) in {1}ms".format(loadCounter, (Date.now() - now))); + } + $scope.formData.balance = balance; $scope.formData.updatingWalletId = undefined; + $scope.loading = false; + UIUtils.loading.hide(); $scope.updateView(); - } + }) + .catch(function(err) { + $scope.resetData(); + if (err && err === 'CANCELLED') { + $scope.cancel(); + throw err; + } + return UIUtils.onError('ERROR.LOAD_WALLET_LIST_FAILED')(err); + }); + }; + + $scope.filterFn = function(parameters) { + return function(wallet) { + return !parameters ||Â wallet.id !== parameters.excludedWalletId; } }; - $scope.$on('$ionicView.enter', $scope.enter); - $scope.leave = function() { - $scope.formData.stopped = true; + + // Clean controller data + $scope.resetData = function() { + console.debug("[wallets] Cleaning wallet list"); + $scope.wallets = null; + $scope.loading = true; + $scope.entered = false; + $scope.formData.balance = undefined; $scope.formData.updatingWalletId = undefined; - $scope.loading = false; - $scope.removeListeners(); }; - $scope.$on('$ionicView.leave', $scope.leave); - $scope.cancel = function() { - $scope.showHome(); - }; + $scope.updateView = function(walletId) { + if (!$scope.wallets || !$scope.wallets.length) return; - $scope.select = function(event, wallet) { - if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; - if (wallet.isDefault()) { - $state.go('app.view_wallet'); + var selectorSuffix = walletId && (' #wallet-' + walletId) || ''; + + if ($scope.motion) { + $scope.motion.show({selector: '.list .item.item-wallet' + selectorSuffix, ink: true}); } else { - $state.go('app.view_wallet_by_id', {id: wallet.id}); + UIUtils.ink({selector: '.list .item.item-wallet' + selectorSuffix}); } - event.preventDefault(); }; - $scope.editWallet = function(event, wallet) { - - event.preventDefault(); + $scope.updateWalletView = function(walletId) { + if ($scope.motion) { + $scope.motion.show({selector: '.list #wallet-' + walletId, ink: true}); + } + else { + UIUtils.ink({selector: '.list #wallet-' + walletId}); + } + }; - return $scope.showEditPopup(wallet) - .then(function(newName) { - if (!newName) return; + $scope.doUpdate = function(silent) { + if ($scope.loading || !$scope.wallets || !$scope.wallets.length || $scope.formData.updatingWalletId) return $q.when(); - // Auth (if encryption is need) - return (csSettings.data.useLocalStorageEncryption ? csWallet.auth({minData: true}) : $q.when()) + $scope.selectPrevented = true; + $timeout(function() { + $scope.selectPrevented = false; + }, 1000); - // Save changes - .then(function() { - wallet.data.localName = newName; - csWallet.storeData(); - UIUtils.loading.hide(); - $scope.updateView(); - }) - .catch(function(err) { - if (err === 'CANCELLED') { - return UIUtils.loading.hide(); - } - UIUtils.onError('ERROR.SAVE_WALLET_LIST_FAILED')(err); - }); + return $scope.load({silent: silent, refresh: true}) + .then(function() { + $scope.loading = false; + $scope.selectPrevented = false; + if (silent) { + $scope.$broadcast('$$rebind::rebind'); // force rebind + } + $scope.updateView(); }); }; - $scope.downloadAsFile = function() { - if (!$scope.wallets) return; // user cancel - return csWallet.children.downloadFile(); - }; - $scope.addNewWallet = function(wallet) { if (!wallet) return $q.reject("Missing 'wallet' argument"); @@ -222,43 +323,188 @@ function WalletListController($scope, $controller, $state, $timeout, $q, $transl return; } - // Avoid to add main wallet again - if (csWallet.isUserPubkey(walletData.pubkey)) { - UIUtils.loading.hide(); - UIUtils.alert.error('ERROR.COULD_NOT_ADD_MAIN_WALLET'); - return; - } + // Avoid to add main wallet again + if (csWallet.isUserPubkey(walletData.pubkey)) { + UIUtils.loading.hide(); + UIUtils.alert.error('ERROR.COULD_NOT_ADD_MAIN_WALLET'); + return; + } + + // Avoid to add exists wallet again + if (csWallet.children.hasPubkey(walletData.pubkey)) { + UIUtils.loading.hide(); + UIUtils.alert.error('ERROR.COULD_NOT_ADD_EXISTING_WALLET'); + return; + } + + console.debug("[wallet] Adding secondary wallet {"+walletData.pubkey.substring(0,8)+"}"); + + // Add the child wallet + return $scope.addNewWallet(wallet) + .then(function() { + UIUtils.loading.hide(); + $scope.updateView(); + }); + }) + .catch(function(err) { + if (err === 'CANCELLED') { + // Silent + UIUtils.loading.hide(); + } + }); + }; + + /* -- Method to override by subclasses-- */ + + $scope.addListenersOnWallet = function(wallet) { + // Can be override by subclass + }; + + $scope.cancel = function() { + console.warn("cancel() must be implement by subclass") + }; + + $scope.select = function(event, wallet) { + console.warn("select() must be implement by subclass") + }; +} + +function WalletSelectModalController($scope, $controller, parameters) { + 'ngInject'; + + // Initialize the super class and extend it. + angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope})); + + $scope.$on('modal.shown', function() { + $scope.setParameters(parameters); + $scope.load(); + }); + + $scope.cancel = function() { + $scope.closeModal(); + }; + + $scope.select = function(event, wallet) { + if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; + $scope.closeModal(wallet); + }; + + // Default actions + if (parameters) { + $scope.setParameters(parameters); + } +} + +function WalletListViewController($scope, $controller, $state, $timeout, $q, $translate, $ionicPopover, $ionicPopup, + ModalUtils, UIUtils, Modals, csCurrency, csSettings, csWallet){ + 'ngInject'; + + $scope.settings = csSettings.data; + $scope.listeners = []; + + // Initialize the super class and extend it. + angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope, parameters: {}})); + + // Override defaults + $scope.formData.name = undefined; + $scope.motion = UIUtils.motion.default; + $scope.entered = false; + + $scope.enter = function(e, state) { + // First enter + if (!$scope.entered) { + $scope.entered = true; + $scope.setParameters({ + showDefault: true, + showBalance: true, + minData: false + }); + + return $scope.load() + .then(function() { + UIUtils.loading.hide(); + if (!$scope.wallets) return; // user cancel, or error + $scope.addListeners(); + $scope.showFab('fab-add-wallet'); + }); + } + // If already enter + else { + // Re-add listeners + $scope.addListeners(); + if ($scope.formData.stopped) { + $scope.loading = false; + $scope.formData.stopped = false; + $scope.formData.updatingWalletId = undefined; + $scope.updateView(); + } + } + }; + $scope.$on('$ionicView.enter', $scope.enter); + + $scope.leave = function() { + $scope.formData.stopped = true; + $scope.formData.updatingWalletId = undefined; + $scope.loading = false; + $scope.removeListeners(); + }; + $scope.$on('$ionicView.leave', $scope.leave); + + $scope.cancel = function() { + $scope.showHome(); + }; + + $scope.select = function(event, wallet) { + if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; + if (wallet.isDefault()) { + $state.go('app.view_wallet'); + } + else { + $state.go('app.view_wallet_by_id', {id: wallet.id}); + } + event.preventDefault(); + }; + + $scope.editWallet = function(event, wallet) { + + event.preventDefault(); - // Avoid to add exists wallet again - if (csWallet.children.hasPubkey(walletData.pubkey)) { - UIUtils.loading.hide(); - UIUtils.alert.error('ERROR.COULD_NOT_ADD_EXISTING_WALLET'); - return; - } + return $scope.showEditPopup(wallet) + .then(function(newName) { + if (!newName) return; - console.debug("[wallet] Adding secondary wallet {"+walletData.pubkey.substring(0,8)+"}"); + // Auth (if encryption is need) + return (csSettings.data.useLocalStorageEncryption ? csWallet.auth({minData: true}) : $q.when()) - // Add the child wallet - return $scope.addNewWallet(wallet) + // Save changes .then(function() { + wallet.data.localName = newName; + csWallet.storeData(); UIUtils.loading.hide(); $scope.updateView(); + }) + .catch(function(err) { + if (err === 'CANCELLED') { + return UIUtils.loading.hide(); + } + UIUtils.onError('ERROR.SAVE_WALLET_LIST_FAILED')(err); }); - }) - .catch(function(err) { - if (err === 'CANCELLED') { - // Silent - UIUtils.loading.hide(); - } }); }; + $scope.downloadAsFile = function() { + if (!$scope.wallets) return; // user cancel + return csWallet.children.downloadFile(); + }; + + + $scope.selectAndRemoveWallet = function() { $scope.hideActionsPopover(); return Modals.showSelectWallet({ - wallets: $scope.wallets, - showDefault: false - }) + wallets: $scope.wallets, + showDefault: false + }) .then(function(wallet) { if (!wallet || !wallet.id) return; @@ -287,13 +533,13 @@ function WalletListController($scope, $controller, $state, $timeout, $q, $transl console.debug("[wallet] Adding secondary wallet {"+authData.pubkey.substring(0,8)+"}"); var wallet = csWallet.children.instance(); return wallet.login({ - authData: authData, - // Load data options : - minData: true, - sources: true, - api: false, - success: UIUtils.loading.show - }) + authData: authData, + // Load data options : + minData: true, + sources: true, + api: false, + success: UIUtils.loading.show + }) .then(function(walletData) { walletData.localName = authData.localName; return $scope.addNewWallet(wallet); @@ -301,8 +547,8 @@ function WalletListController($scope, $controller, $state, $timeout, $q, $transl }; return ModalUtils.show( - 'templates/wallet/list/modal_import_file.html', - 'WalletListImportModalCtrl' + 'templates/wallet/list/modal_import_file.html', + 'WalletListImportModalCtrl' ) .then(function(items){ if (!items || !items.length) return; // User cancel @@ -451,13 +697,13 @@ function WalletListController($scope, $controller, $state, $timeout, $q, $transl var inheritedUpdateView = $scope.updateView; $scope.updateView = function() { inheritedUpdateView(); - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::rebind'); // force rebind }; var inheritedUpdateWalletView = $scope.updateWalletView; $scope.updateWalletView = function(walletId) { inheritedUpdateWalletView(walletId); - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::rebind'); // force rebind }; // Detect changes in settings useRelative @@ -468,233 +714,19 @@ function WalletListController($scope, $controller, $state, $timeout, $q, $transl }, true); } -function WalletSelectModalController($scope, $q, $timeout, UIUtils, filterTranslations, csSettings, csCurrency, csWallet, parameters){ - 'ngInject'; - - $scope.loading = true; - $scope.wallets = null; - $scope.formData = { - useRelative: csSettings.data.useRelative, - showDefault: true, - showBalance: false, - balance: undefined, - updatingWalletId: undefined, - stopped: false, - minData: true - }; - $scope.motion = null; // no animation - - $scope.setParameters = function(parameters) { - parameters = parameters || {}; - - $scope.formData.useRelative = angular.isDefined(parameters.useRelative) ? parameters.useRelative : $scope.formData.useRelative; - - $scope.formData.showDefault = angular.isDefined(parameters.showDefault) ? parameters.showDefault : $scope.formData.showDefault; - - $scope.formData.showBalance = angular.isDefined(parameters.showBalance) ? parameters.showBalance : $scope.formData.showBalance; - - $scope.formData.minData = angular.isDefined(parameters.minData) ? parameters.minData : $scope.formData.minData; - }; - - $scope.load = function(options) { - - options = options || {}; - $scope.loading = angular.isUndefined(options.silent) || !options.silent; - $scope.formData.balance = undefined; - $scope.formData.updatingWalletId = undefined; - $scope.formData.stopped = false; - - // Load currency, and filter translations (need by 'formatAmount' filter) - var jobs = []; - - jobs.push(csCurrency.name() - .then(function(currency) { - $scope.currency = currency; - return filterTranslations.ready(); - })); - - // Get children wallets - $scope.defaultWallet = $scope.formData.showDefault ? csWallet : undefined; - if (!$scope.wallets) { - jobs.push( - csWallet.children.all() - .then(function(children) { - $scope.wallets=children; - UIUtils.loading.hide(); - }) - ); - } - - // Prepare load options - var walletLoadOptions = { - silent: true, - minData: $scope.formData.minData, - sources: $scope.formData.showBalance, - tx: { - enable: false - }, - api: true - }; - var hasLoadError = false; - var loadCounter = 0; - var now = Date.now(); - var balance = 0; - return (jobs.length ? $q.all(jobs) : $q.when()) - // Load wallet data (apply a timeout between each wallet) - .then(function() { - var wallets = $scope.formData.showDefault ? [csWallet].concat($scope.wallets) : $scope.wallets; - if (!wallets.length) return; - console.debug("[wallets] Loading {0} wallets...".format(wallets.length)); - return wallets.reduce(function(res, wallet) { - var skip= !options.refresh && wallet.isDataLoaded(walletLoadOptions); - if (skip) { - console.debug("[wallets] Wallet #{0} already loaded. Skipping".format(wallet.id)); - return res.then(function(){ - balance += wallet.data.balance; - $scope.updateWalletView(wallet.id); - }); - } - loadCounter++; - return res.then(function() { - if ($scope.formData.stopped) return; // skip if stopped - // Loading next wallet, after waiting some time - $scope.formData.updatingWalletId = wallet.id; - var loadPromise; - if (options.refresh && wallet.data.loaded) { - var refreshOptions = angular.merge({ - // Refresh requirements if member account - requirements: (!wallet.data.requirements.loaded || wallet.data.requirements.isMember || wallet.data.requirements.wasMember || wallet.data.requirements.pendingMembership) - }, walletLoadOptions); - loadPromise = wallet.refreshData(refreshOptions); - } - else { - loadPromise = wallet.loadData(walletLoadOptions); - } - - loadPromise.then(function(walletData) { - balance += walletData.balance; - $scope.updateWalletView(wallet.id); - }) - .catch(function(err) { - console.error("[wallets] Error while loading data of wallet #{0}".format(wallet.id), err); - hasLoadError = true; - }); - return loadPromise; - }); - }, $q.when()); - }) - .then(function() { - if (hasLoadError) { - return UIUtils.alert.error('ERROR.LOAD_WALLET_LIST_FAILED') - .then(function() { - $scope.resetData(); - $scope.cancel(); - }); - } - // Stop - if ($scope.formData.stopped) return; - if (loadCounter) { - console.debug("[wallets] Loaded data of {0} wallet(s) in {1}ms".format(loadCounter, (Date.now() - now))); - } - $scope.formData.balance = balance; - $scope.formData.updatingWalletId = undefined; - $scope.loading = false; - UIUtils.loading.hide(); - $scope.updateView(); - }) - .catch(function(err) { - $scope.resetData(); - if (err && err === 'CANCELLED') { - $scope.cancel(); - throw err; - } - return UIUtils.onError('ERROR.LOAD_WALLET_LIST_FAILED')(err); - }); - }; - - $scope.$on('modal.shown', function() { - $scope.load(); - }); - - $scope.cancel = function() { - $scope.closeModal(); - }; - - $scope.select = function(event, wallet) { - if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; - $scope.closeModal(wallet); - }; - - // Clean controller data - $scope.resetData = function() { - console.debug("[wallets] Cleaning wallet list"); - $scope.wallets = null; - $scope.loading = true; - $scope.entered = false; - $scope.formData.balance = undefined; - $scope.formData.updatingWalletId = undefined; - }; - - $scope.updateView = function(walletId) { - if (!$scope.wallets || !$scope.wallets.length) return; - - var selectorSuffix = walletId && (' #wallet-' + walletId) || ''; - - if ($scope.motion) { - $scope.motion.show({selector: '.list .item.item-wallet' + selectorSuffix, ink: true}); - } - else { - UIUtils.ink({selector: '.list .item.item-wallet' + selectorSuffix}); - } - }; - - $scope.updateWalletView = function(walletId) { - if ($scope.motion) { - $scope.motion.show({selector: '.list #wallet-' + walletId, ink: true}); - } - else { - UIUtils.ink({selector: '.list #wallet-' + walletId}); - } - }; - - $scope.doUpdate = function(silent, event) { - if ($scope.loading || !$scope.wallets || !$scope.wallets.length || $scope.formData.updatingWalletId) return $q.when(); - - $scope.selectPrevented = true; - $timeout(function() { - $scope.selectPrevented = false; - }, 1000); - - return $scope.load({silent: silent, refresh: true}) - .then(function() { - $scope.loading = false; - $scope.selectPrevented = false; - if (silent) { - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind - } - $scope.updateView(); - }); - }; - - // Default actions - $scope.setParameters(parameters); - -} -function PopoverWalletSelectModalController($scope, $controller, UIUtils) { +function WalletSelectPopoverController($scope, $controller, UIUtils, parameters) { 'ngInject'; // Initialize the super class and extend it. - angular.extend(this, $controller('WalletSelectModalCtrl', {$scope: $scope, parameters: { - showDefault: true, - showBalance: false - }})); + angular.extend(this, $controller('WalletListAbstractCtrl', {$scope: $scope})); // Disable list motion $scope.motion = null; $scope.$on('popover.shown', function() { if ($scope.loading) { + $scope.setParameters(parameters); $scope.load(); } }); @@ -703,12 +735,14 @@ function PopoverWalletSelectModalController($scope, $controller, UIUtils) { if (!$scope.wallets || !$scope.wallets.length) return; UIUtils.ink({selector: '.popover-wallets .list .item'}); + $scope.$broadcast('$$rebind::rebind'); // force rebind }; $scope.select = function(event, wallet) { if (event.isDefaultPrevented() || !wallet || $scope.selectPrevented) return; // no selection $scope.closePopover(wallet); }; + } function WalletListImportModalController($scope, $timeout, BMA, csWallet) { diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js index db0194e04..6344a296d 100644 --- a/www/js/controllers/wot-controllers.js +++ b/www/js/controllers/wot-controllers.js @@ -1209,8 +1209,8 @@ function WotIdentityTxViewController($scope, $timeout, $q, BMA, csSettings, csWo // Update view $scope.updateView = function() { - $scope.$broadcast('$$rebind::' + 'balance'); // force rebind balance - $scope.$broadcast('$$rebind::' + 'rebind'); // force rebind + $scope.$broadcast('$$rebind::balance'); // force rebind balance + $scope.$broadcast('$$rebind::rebind'); // force rebind $scope.motion.show(); }; diff --git a/www/js/services/crypto-services.js b/www/js/services/crypto-services.js index 75ebb37b1..8201a3134 100644 --- a/www/js/services/crypto-services.js +++ b/www/js/services/crypto-services.js @@ -217,40 +217,47 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) */ this.box_keypair_from_sign = function (signKeyPair) { if (signKeyPair.boxSk && signKeyPair.boxPk) return $q.when(signKeyPair); - return $q.when(that.nacl.crypto_box_keypair_from_sign_sk(signKeyPair.signSk)); + return $q(function (resolve, reject) { + try { + // TODO: waiting for a new version of js-nacl, with missing functions expose + //resolve(that.nacl.crypto_box_keypair_from_sign_sk(signPk); + + resolve(crypto_box_keypair_from_sign_sk(signPk)); + } + catch(err) { + reject(err); + } + }); }; /** * Compute the box public key, from a sign public key */ this.box_pk_from_sign = function (signPk) { - return $q(function (resolve, reject) { + return $q(function(resolve, reject) { try { - var pka = check_injectBytes("box_pk_from_sign", "signPk", signPk, that.nacl.nacl_raw._crypto_sign_publickeybytes()); - var pk = new Target(that.nacl.nacl_raw._crypto_box_publickeybytes()); - check("_crypto_sign_ed25519_pk_to_curve25519", that.nacl.nacl_raw._crypto_sign_ed25519_pk_to_curve25519(pk.address, pka)); - FREE(pka); - resolve(pk.extractBytes()); + // TODO: waiting for a new version of js-nacl, with missing functions expose + //resolve(that.nacl.crypto_box_pk_from_sign_pk(signPk)); + + resolve(crypto_box_pk_from_sign_pk(signPk)); } - catch (err) { + catch(err) { reject(err); } }); }; this.box_sk_from_sign = function (signSk) { - return $q(function (resolve, reject) { + return $q(function(resolve, reject) { try { - var ska = check_injectBytes("box_sk_from_sign", "signSk", signSk, that.nacl.nacl_raw._crypto_sign_secretkeybytes()); - var sk = new Target(that.nacl.nacl_raw._crypto_box_secretkeybytes()); - that.nacl.nacl_raw._crypto_sign_ed25519_sk_to_curve25519(sk.address, ska); - FREE(ska); - resolve(sk.extractBytes()); + // TODO: waiting for a new version of js-nacl, with missing functions expose + //resolve(that.nacl.crypto_box_sk_from_sign_sk(signSk)); + resolve(crypto_box_sk_from_sign_sk(signSk)); } - catch (err) { + catch(err) { reject(err); } - }); + }) }; /** @@ -294,7 +301,7 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) } try { - var message = crypto_box_open(ciphertextBin, nonce, senderPk, recipientSk); + var message = that.nacl.crypto_box_open(ciphertextBin, nonce, senderPk, recipientSk); resolve(that.nacl.decode_utf8(message)); } catch (err) { @@ -447,6 +454,40 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) open: that.box_open }; + /*-- + start WORKAROUND - Publish missing functions (see PR js-nacl: https://github.com/tonyg/js-nacl/pull/54) + -- */ + + function crypto_box_keypair_from_sign_sk(sk) { + var ska = check_injectBytes("crypto_box_keypair_from_sign_sk", "sk", sk, + that.nacl.nacl_raw._crypto_sign_secretkeybytes()); + var skb = new Target(that.nacl.nacl_raw._crypto_box_secretkeybytes()); + check("_crypto_sign_ed25519_sk_to_curve25519", + that.nacl.nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska)); + FREE(ska); + return that.nacl.crypto_box_keypair_from_raw_sk(skb.extractBytes()); + } + + function crypto_box_pk_from_sign_pk(pk) { + var pka = check_injectBytes("crypto_box_pk_from_sign_pk", "pk", pk, + that.nacl.nacl_raw._crypto_sign_publickeybytes()); + var pkb = new Target(that.nacl.nacl_raw._crypto_box_publickeybytes()); + check("_crypto_sign_ed25519_pk_to_curve25519", + that.nacl.nacl_raw._crypto_sign_ed25519_pk_to_curve25519(pkb.address, pka)); + FREE(pka); + return pkb.extractBytes(); + } + + function crypto_box_sk_from_sign_sk(sk) { + var ska = check_injectBytes("crypto_box_sk_from_sign_sk", "sk", sk, + that.nacl.nacl_raw._crypto_sign_secretkeybytes()); + var skb = new Target(that.nacl.nacl_raw._crypto_box_secretkeybytes()); + check("_crypto_sign_ed25519_sk_to_curve25519", + that.nacl.nacl_raw._crypto_sign_ed25519_sk_to_curve25519(skb.address, ska)); + FREE(ska); + return skb.extractBytes(); + } + function check_length(function_name, what, thing, expected_length) { if (thing.length !== expected_length) { throw {message: "nacl." + function_name + " expected " + @@ -454,20 +495,6 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) } } - function crypto_box_open(ciphertext, nonce, pk, sk) { - var c = injectBytes(ciphertext, that.nacl.nacl_raw._crypto_box_boxzerobytes()); - var na = check_injectBytes("crypto_box_open", - "nonce", nonce, that.nacl.nacl_raw._crypto_box_noncebytes()); - var pka = check_injectBytes("crypto_box_open", - "pk", pk, that.nacl.nacl_raw._crypto_box_publickeybytes()); - var ska = check_injectBytes("crypto_box_open", - "sk", sk, that.nacl.nacl_raw._crypto_box_secretkeybytes()); - var m = new Target(ciphertext.length + that.nacl.nacl_raw._crypto_box_boxzerobytes()); - check("_crypto_box_open", that.nacl.nacl_raw._crypto_box_open(m.address, c, m.length, 0, na, pka, ska)); - free_all([c, na, pka, ska]); - return m.extractBytes(that.nacl.nacl_raw._crypto_box_zerobytes()); - } - function check(function_name, result) { if (result !== 0) { throw {message: "nacl_raw." + function_name + " signalled an error"}; @@ -524,6 +551,11 @@ angular.module('cesium.crypto.services', ['cesium.utils.services']) this.address = null; return result; }; + + /*-- + end of WORKAROUND + -- */ + } FullJSServiceFactory.prototype = new CryptoAbstractService(); diff --git a/www/js/services/modal-services.js b/www/js/services/modal-services.js index e1d792480..fd024fff9 100644 --- a/www/js/services/modal-services.js +++ b/www/js/services/modal-services.js @@ -111,11 +111,11 @@ angular.module('cesium.modal.services', ['cesium.utils.services']) options = options ? options : {} ; options.animation = options.animation || 'slide-in-up'; - // var focusFirstInput = false; - // // removeIf(device) - // focusFirstInput = angular.isDefined(options.focusFirstInput) ? options.focusFirstInput : false; - // // endRemoveIf(device) - // options.focusFirstInput = focusFirstInput; + var focusFirstInput = false; + // removeIf(device) + focusFirstInput = angular.isDefined(options.focusFirstInput) ? options.focusFirstInput : false; + // endRemoveIf(device) + options.focusFirstInput = focusFirstInput; // If modal has a controller if (controller) { @@ -298,18 +298,41 @@ angular.module('cesium.modal.services', ['cesium.utils.services']) }) -.factory('csPopovers', function($rootScope, $translate, $ionicPopup, $timeout, UIUtils) { +.factory('csPopovers', function($rootScope, $translate, $ionicPopup, $timeout, UIUtils, $controller) { 'ngInject'; function showSelectWallet(event, options) { - options = options || {}; + options = options ||Â {}; + + var parameters = options.parameters ||Â {}; + delete options.parameters; + var scope = options.scope && options.scope.$new() || $rootScope.$new(true); - scope.parameters = options; - delete options.scope; - return UIUtils.popover.show(event, angular.merge({ - templateUrl :'templates/wallet/list/popover_wallets.html', - autoremove: true - }, options)); + options.scope = scope; + options.templateUrl = 'templates/wallet/list/popover_wallets.html'; + options.autoremove = true; + + // Initialize the popover controller, with parameters + angular.extend(this, $controller('WalletSelectPopoverCtrl', {$scope: options.scope, parameters: parameters})); + + var afterShowSaved = options.afterShow; + options.afterShow = function(popover) { + + // Add a missing method, to close the popover + scope.closePopover = function(res) { + popover.scope.closePopover(res); + }; + + // Execute default afterShow fn, if any + if (afterShowSaved) afterShowSaved(popover); + }; + // Show the popover + return UIUtils.popover.show(event, options) + .then(function(res) { + // Then destroy the scope + scope.$destroy(); + return res; + }); } return { diff --git a/www/js/services/utils-services.js b/www/js/services/utils-services.js index 9c9b84107..3c18ed4f9 100644 --- a/www/js/services/utils-services.js +++ b/www/js/services/utils-services.js @@ -412,10 +412,9 @@ angular.module('cesium.utils.services', []) options = options || {}; options.templateUrl = options.templateUrl ? options.templateUrl : 'templates/common/popover_copy.html'; - options.scope = options.scope && options.scope || $rootScope; + options.scope = options.scope || $rootScope; options.scope.popovers = options.scope.popovers || {}; options.autoselect = options.autoselect || false; - options.bindings = options.bindings || {}; options.autoremove = angular.isDefined(options.autoremove) ? options.autoremove : true; options.backdropClickToClose = angular.isDefined(options.backdropClickToClose) ? options.backdropClickToClose : true; options.focusFirstInput = angular.isDefined(options.focusFirstInput) ? options.focusFirstInput : false; @@ -426,7 +425,9 @@ angular.module('cesium.utils.services', []) popover.deferred=deferred; popover.options=options; // Fill the popover scope - angular.merge(popover.scope, options.bindings); + if (options.bindings) { + angular.merge(popover.scope, options.bindings); + } $timeout(function() { // This is need for Firefox popover.show(event) .then(function() { diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index 97b4a431b..b787c38b8 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -1997,7 +1997,7 @@ angular.module('cesium.wallet.services', ['ngApi', 'ngFileSaver', 'cesium.bma.se }, getChildWalletById = function(id) { - return _.find(data.children|| [], function(child) {return child.id == id;}); + return (id !== 'default') && _.find(data.children|| [], function(child) {return child.id == id;}) || undefined; }, getChildWalletByPubkey = function(pubkey) { diff --git a/www/plugins/es/js/controllers/app-controllers.js b/www/plugins/es/js/controllers/app-controllers.js index f595e7930..c324806e7 100644 --- a/www/plugins/es/js/controllers/app-controllers.js +++ b/www/plugins/es/js/controllers/app-controllers.js @@ -67,7 +67,7 @@ function ESMenuExtendController($scope, $state, $controller, UIUtils, csWallet) angular.extend(this, $controller('ESExtensionCtrl', {$scope: $scope})); $scope.showRegistryLookupView = function() { - $state.go(UIUtils.screen.isSmall() ? 'app.registry_lookup': 'app.registry_lookup_lg'); + $state.go(UIUtils.screen.isSmall() ? 'app.wot_lookup.tab_registry': 'app.registry_lookup_lg'); }; $scope.showNotificationsPopover = function(event) { diff --git a/www/plugins/es/js/controllers/document-controllers.js b/www/plugins/es/js/controllers/document-controllers.js index f6e11c46f..3e9f52126 100644 --- a/www/plugins/es/js/controllers/document-controllers.js +++ b/www/plugins/es/js/controllers/document-controllers.js @@ -147,7 +147,7 @@ function ESDocumentLookupController($scope, $ionicPopover, $location, $timeout, }); }; - $scope.remove = function(index) { + $scope.remove = function(index, options) { var doc = $scope.search.results[index]; if (!doc) return; diff --git a/www/plugins/es/js/controllers/message-controllers.js b/www/plugins/es/js/controllers/message-controllers.js index b4b49d291..283e5252b 100644 --- a/www/plugins/es/js/controllers/message-controllers.js +++ b/www/plugins/es/js/controllers/message-controllers.js @@ -62,7 +62,7 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services']) url: "/wallets/:id/message", views: { 'menuContent': { - templateUrl: "plugins/es/templates/message/lookup.html" + templateUrl: "plugins/es/templates/message/lookup_by_id.html" } } }) @@ -104,7 +104,7 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services']) }) .state('app.user_messages_lg_outbox', { - url: "/wallets/:id/message/lg/outbox", + url: "/user/message/lg/outbox", views: { 'menuContent': { templateUrl: "plugins/es/templates/message/lookup_lg.html", @@ -118,7 +118,7 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services']) }) .state('app.user_messages_lg_outbox_by_id', { - url: "/user/message/lg/outbox", + url: "/wallets/:id/message/lg/outbox", views: { 'menuContent': { templateUrl: "plugins/es/templates/message/lookup_lg.html", @@ -189,6 +189,7 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto var defaultSearchLimit = 40; var wallet; + var selectPrevented = false; $scope.search = { loading: true, @@ -205,43 +206,45 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto $scope.fabButtonNewMessageId = undefined; $scope.enter = function(s, state) { - wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; - if (!wallet) { - UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); - return $scope.showHome(); - } + // First enter + if ($scope.search.loading) { + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } - $scope.isDefaultWallet = wallet.isDefault(); - $scope.walletId = wallet.id; + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; - wallet.auth({minData: true}) - .then(function() { - if (!$scope.entered) { - $scope.entered = true; - $scope.type = $scope.type || state.stateParams && state.stateParams.type || 'inbox'; - $scope.load(); - } + wallet.auth({minData: true}) + .then(function() { + if (!$scope.entered) { + $scope.entered = true; + $scope.type = $scope.type || state.stateParams && state.stateParams.type || 'inbox'; + $scope.load(); + } - if ($scope.fabButtonNewMessageId) { - $scope.showFab($scope.fabButtonNewMessageId); - } - }) - .catch(function(err) { - if ('CANCELLED' === err) { - $ionicHistory.nextViewOptions({ - historyRoot: true - }); - $state.go('app.home'); - } - }); + if ($scope.fabButtonNewMessageId) { + $scope.showFab($scope.fabButtonNewMessageId); + } + }) + .catch(function(err) { + if ('CANCELLED' === err) { + $ionicHistory.nextViewOptions({ + historyRoot: true + }); + $scope.showHome(); + } + }); + } + // Not first entering: refresh the view + else { + $scope.updateView(); + } }; $scope.$on('$ionicView.enter', $scope.enter); - - $scope.refresh = function(silent) { - return $scope.load(undefined, undefined, silent); - }; - $scope.load = function(from, size, silent) { var options = angular.copy($scope.search.options); @@ -279,15 +282,11 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto }); }; - $scope.setType = function(type) { - $scope.type = type; - $scope.load(); - }; - $scope.updateView = function() { if ($scope.motion && $scope.motion.ionListClass && $scope.search.results.length) { $scope.motion.show({selector: '.view-messages .list .item'}); } + $scope.$broadcast('$$rebind::rebind'); // notifier binder }; $scope.showMore = function() { @@ -332,9 +331,10 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE') .then(function(confirm) { if (confirm) { - esMessage.remove(message.id, $scope.type) + esMessage.remove(message.id, $scope.type, {walletId: $scope.walletId}) .then(function () { $scope.search.results.splice(index,1); // remove from messages array + $scope.updateView(); UIUtils.toast.show('MESSAGE.INFO.MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_MESSAGE_FAILED')); @@ -349,9 +349,10 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE_ALL') .then(function(confirm) { if (confirm) { - esMessage.removeAll($scope.type) + esMessage.removeAll($scope.type, {walletId: $scope.walletId}) .then(function () { $scope.search.results.splice(0,$scope.search.results.length); // reset array + $scope.updateView(); UIUtils.toast.show('MESSAGE.INFO.All_MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_All_MESSAGES_FAILED')); @@ -379,13 +380,33 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto return $scope.load(); }; - $scope.select = function(message) { - if (!wallet || wallet.isDefault()) { - $state.go('app.user_view_message', {type: $scope.type, messageId:message.id}); - } - else { - $state.go('app.user_view_message_by_id', {type: $scope.type, messageId:message.id, id: $scope.walletId}); - } + + $scope.refresh = function(silent) { + selectPrevented = true; // Will disable select() to open the message + return $scope.load(undefined, undefined, silent) + .then(function() { + selectPrevented = false; + }) + .catch(function() { + selectPrevented = false; + }); + }; + + $scope.select = function(message, event) { + if (event.isDefaultPrevented() || $scope.search.loading || selectPrevented) return; // skip + + // Add a timeout, to be sure the refres action was not called before + return $timeout(function() { + if (selectPrevented || event.isDefaultPrevented()) return; // skip + event.preventDefault(); + + if ($scope.walletId === 'default') { + return $state.go('app.user_view_message', {type: $scope.type, messageId:message.id}); + } + else { + return $state.go('app.user_view_message_by_id', {type: $scope.type, messageId:message.id, id: $scope.walletId}); + } + }, 200); }; /* -- Modals -- */ @@ -458,22 +479,23 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto if (index) { $scope.search.results.splice(index,1); // remove from messages array } + $scope.updateView(); }; esMessage.api.data.on.delete($scope, $scope.onMessageDelete); // Watch user sent message $scope.onNewOutboxMessage = function(id) { - if ($scope.type != 'outbox') return; + if ($scope.type !== 'outbox') return; // Add message sent to list - $scope.loading = true; + $scope.search.loading = true; return $timeout(function() { // Load the message sent - return esMessage.get(id, {type: $scope.type, summary: true}); + return esMessage.get(id, $scope.type, {summary: true, wallet: wallet}); }, 500 /*waiting ES propagation*/) .then(function(msg) { $scope.search.results.splice(0,0,msg); - $scope.loading = false; - $scope.motion.show({selector: '.view-messages .list .item'}); + $scope.search.loading = false; + $scope.updateView(); }) .catch(function() { $scope.loading = false; @@ -483,15 +505,15 @@ function ESMessageAbstractListController($scope, $state, $translate, $ionicHisto // Watch received message $scope.onNewInboxMessage = function(notification) { - if ($scope.type != 'inbox' || !$scope.entered) return; + if ($scope.type !== 'inbox' || !$scope.entered || !wallet.isUserPubkey(notification.issuer)) return; // Add message sent to list - $scope.loading = true; + $scope.search.loading = true; // Load the the message - return esMessage.get(notification.id, {type: $scope.type, summary: true}) + return esMessage.get(notification.id, $scope.type, {summary: true, wallet: wallet}) .then(function(msg) { $scope.search.results.splice(0,0,msg); $scope.search.loading = false; - $scope.motion.show({selector: '.view-messages .list .item'}); + $scope.updateView(); }) .catch(function() { $scope.search.loading = false; @@ -764,65 +786,67 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis }); $scope.enter = function(e, state) { - if (!$scope.loading) return; // prevent reload if same id + // First enter + if ($scope.loading) { - wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; - if (!wallet) { - UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); - return $scope.showHome(); - } + wallet = (state.stateParams && state.stateParams.id) ? csWallet.children.get(state.stateParams.id) : csWallet; + if (!wallet) { + UIUtils.alert.error('ERROR.UNKNOWN_WALLET_ID'); + return $scope.showHome(); + } - $scope.isDefaultWallet = wallet.isDefault(); - $scope.walletId = wallet.id; + $scope.isDefaultWallet = wallet.isDefault(); + $scope.walletId = wallet.id; - var messageId = state.stateParams && state.stateParams.messageId; - $scope.type = state.stateParams.type || 'inbox'; + var messageId = state.stateParams && state.stateParams.messageId; + $scope.type = state.stateParams.type || 'inbox'; - // No message id: redirect - if (angular.isUndefined(messageId)) { - $state.go('app.user_message'); - return; - } + // No message id: redirect + if (angular.isUndefined(messageId)) { + $scope.goBack(); + return; + } - wallet.auth({minData: true}) - .then(function () { - return $scope.load(messageId, $scope.type); - }) - .then(function(message) { + wallet.auth({minData: true}) + .then(function () { + return $scope.load(messageId, $scope.type); + }) + .then(function(message) { - UIUtils.loading.hide(); - if (!message) return; // SKip - - $scope.updateView(message); - $scope.showFab('fab-view-message-reply'); - - // Mark as read - if (!message.read) { - $timeout(function() { - // Message has NOT changed - if ($scope.id === message.id) { - esMessage.markAsRead(message, {type: $scope.type, wallet: wallet}) - .then(function() { - console.debug("[message] marked as read"); - }) - .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED')); - } - }, 2000); // 2s - } - }); + UIUtils.loading.hide(); + if (!message) return; // SKip + + $scope.updateView(message); + $scope.showFab('fab-view-message-reply'); + + // Mark as read + if (!message.read) { + $timeout(function() { + // Message has NOT changed + if ($scope.id === message.id) { + esMessage.markAsRead(message, {type: $scope.type, wallet: wallet}) + .then(function() { + console.debug("[message] marked as read"); + }) + .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED')); + } + }, 2000); // 2s + } + }); + } }; $scope.$on('$ionicView.enter', $scope.enter); $scope.load = function(id, type) { type = type || 'inbox'; - return esMessage.get(id, {type: type, wallet: wallet}) + return esMessage.get(id, type, {wallet: wallet}) .catch(UIUtils.onError('MESSAGE.ERROR.LOAD_MESSAGE_FAILED')) .then(function(message) { if (!message.valid) { return UIUtils.alert.error(!$scope.isUserPubkey(message.recipient) ? 'MESSAGE.ERROR.USER_NOT_RECIPIENT' : 'MESSAGE.ERROR.NOT_AUTHENTICATED_MESSAGE', 'MESSAGE.ERROR.MESSAGE_NOT_READABLE') .then(function () { - $state.go('app.user_message', {type: type}); + $scope.goBack(true/*clear cache*/); }); } return message; @@ -845,14 +869,9 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis UIUtils.alert.confirm('MESSAGE.CONFIRM.REMOVE') .then(function(confirm) { if (confirm) { - return esMessage.remove($scope.id, $scope.type) + return esMessage.remove($scope.id, $scope.type, {wallet: wallet}) .then(function () { - $ionicHistory.nextViewOptions({ - historyRoot: true - }); - $state.go($scope.type == 'inbox' ? 'app.user_message.tab_inbox' : 'app.user_message.tab_outbox', - {type: $scope.type} - ); + $scope.goBack(true/*clear page cache*/); UIUtils.toast.show('MESSAGE.INFO.MESSAGE_REMOVED'); }) .catch(UIUtils.onError('MESSAGE.ERROR.REMOVE_MESSAGE_FAILED')); @@ -860,6 +879,23 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis }); }; + $scope.goBack = function(clearPageCache) { + if (clearPageCache) { + $ionicHistory.clearCache($ionicHistory.currentView().stateId); // clear current view + } + $ionicHistory.nextViewOptions({historyRoot: true}); + if ($scope.isDefaultWallet) { + if ($scope.type) { + $state.go('app.user_message.tab_' + $scope.type, {type: $scope.type}); + } + } + else { + if ($scope.type) { + $state.go('app.user_messages_by_id.tab_' + $scope.type, {type: $scope.type, id: $scope.walletId}); + } + } + }; + /* -- Popover -- */ $scope.showActionsPopover = function(event) { @@ -895,7 +931,7 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis title: prefix + $scope.formData.title, content: content, isReply: true, - wallet: $scope.walletId + walletId: wallet.id }); }) .then(function(sent) { @@ -914,6 +950,7 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM 'ngInject'; var defaultSearchLimit = 40; + var wallet; $scope.search = { loading : true, @@ -925,6 +962,15 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM $scope.$on('popover.shown', function() { if ($scope.search.loading) { + // TODO manage secondary wallets + wallet = $scope.walletId && csWallet.children.get($scope.walletId) ||Â csWallet; + + /* -- wallet listeners -- */ + if (wallet.isDefault()) { + wallet.api.data.on.logout($scope, $scope.resetData); + esMessage.api.data.on.new($scope, $scope.onNewMessageNotification); + } + $scope.load(); } }); @@ -980,13 +1026,22 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM // Listen notifications changes $scope.onNewMessageNotification = function(notification) { if ($scope.search.loading || $scope.search.loadingMore) return; + + if (!wallet.isUserPubkey(notification.issuer)) return; // skip + + // Prepend to list $scope.search.results.splice(0,0,notification); $scope.updateView(); }; $scope.select = function(notification) { if (!notification.read) notification.read = true; - $state.go('app.user_view_message', {messageId: notification.id}); + if ($scope.walletId === 'default') { + $state.go('app.user_view_message', {messageId: notification.id}); + } + else { + $state.go('app.user_view_message_by_id', {messageId: notification.id, id: $scope.walletId}); + } $scope.closePopover(notification); }; @@ -1008,7 +1063,7 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM $timeout(function() { parameters = parameters ||Â {}; - parameters.wallet = $scope.walletId; + parameters.walletId = wallet.id; esModals.showMessageCompose(parameters) .then(function(id) { @@ -1019,9 +1074,7 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM /* -- listeners -- */ - csWallet.api.data.on.logout($scope, $scope.resetData); esHttp.api.node.on.stop($scope, $scope.resetData); esHttp.api.node.on.start($scope, $scope.load); - esMessage.api.data.on.new($scope, $scope.onNewMessageNotification); } diff --git a/www/plugins/es/js/controllers/profile-controllers.js b/www/plugins/es/js/controllers/profile-controllers.js index abf8be04b..82a612301 100644 --- a/www/plugins/es/js/controllers/profile-controllers.js +++ b/www/plugins/es/js/controllers/profile-controllers.js @@ -72,6 +72,8 @@ function ESViewEditProfileController($scope, $q, $timeout, $state, $focus, $tran return $scope.showHome(); } + $scope.walletId = wallet.id; + return wallet.auth({ minData: true }) @@ -395,9 +397,7 @@ function ESViewEditProfileController($scope, $q, $timeout, $state, $focus, $tran // removeIf(no-device) UIUtils.loading.show(); // endRemoveIf(no-device) - return esProfile.remove(walletData.pubkey, { - wallet: wallet - }) + return esProfile.remove(walletData.pubkey, {wallet: wallet}) .then(function () { if (wallet.isDefault()) { walletData.name=null; // keep local name, on children wallets diff --git a/www/plugins/es/js/controllers/registry-controllers.js b/www/plugins/es/js/controllers/registry-controllers.js index 339df0a7b..04b3c29fb 100644 --- a/www/plugins/es/js/controllers/registry-controllers.js +++ b/www/plugins/es/js/controllers/registry-controllers.js @@ -801,7 +801,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.$broadcast('$recordView.enter', state); } else { - $state.go('app.registry_lookup'); + $state.go('app.wot_lookup.tab_registry'); } }); @@ -843,7 +843,7 @@ function ESRegistryRecordViewController($scope, $rootScope, $state, $q, $timeout $scope.loading = false; if (err && err.ucode === 404) { UIUtils.toast.show('REGISTRY.ERROR.RECORD_NOT_EXISTS'); - $state.go('app.registry_lookup'); + $state.go('app.wot_lookup.tab_registry'); } else { UIUtils.onError('REGISTRY.ERROR.LOAD_RECORD_FAILED')(err); diff --git a/www/plugins/es/js/controllers/subscription-controllers.js b/www/plugins/es/js/controllers/subscription-controllers.js index 397bf94c6..d73f77361 100644 --- a/www/plugins/es/js/controllers/subscription-controllers.js +++ b/www/plugins/es/js/controllers/subscription-controllers.js @@ -68,11 +68,7 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, return $scope.showHome(); } - $scope.loadWallet({ - wallet: wallet, - auth: true, - minData: true - }) + wallet.auth({minData: true}) .then(function() { UIUtils.loading.hide(); return $scope.load(); @@ -81,7 +77,7 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, $scope.showFab('fab-add-subscription-record'); }) .catch(function(err){ - if (err == 'CANCELLED') { + if (err === 'CANCELLED') { UIUtils.loading.hide(10); $scope.loading=true; // reset for force reload next time $ionicHistory.goBack(); @@ -146,7 +142,7 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, if (!cat) return; type = cat.id; // get subscription parameters - if (type == 'email') { + if (type === 'email') { return $scope.showEmailModal(); } else { @@ -156,7 +152,7 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, .then(function(record) { if (!record) return; UIUtils.loading.show(); - esSubscription.record.add(record, wallet) + esSubscription.record.add(record, {wallet: wallet}) .then($scope.addToUI) .then(function() { wallet.data.subscriptions = wallet.data.subscriptions || {count: 0}; @@ -173,7 +169,7 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, // get subscription parameters var promise; var oldRecord = angular.copy(record); - if (record.type == 'email') { + if (record.type === 'email') { promise = $scope.showEmailModal(record); } if (!promise) return; @@ -185,8 +181,8 @@ function ViewSubscriptionsController($scope, $q, $ionicHistory, csWot, csWallet, return esSubscription.record.update(record, wallet) .then(function() { // If recipient change, update in results - if (oldRecord.type != record.type || - oldRecord.recipient != record.recipient) { + if (oldRecord.type !== record.type || + oldRecord.recipient !== record.recipient) { $scope.removeFromUI(oldRecord); return $scope.addToUI(record); } diff --git a/www/plugins/es/js/controllers/wot-controllers.js b/www/plugins/es/js/controllers/wot-controllers.js index 2adfdfff5..4ac6d8ed6 100644 --- a/www/plugins/es/js/controllers/wot-controllers.js +++ b/www/plugins/es/js/controllers/wot-controllers.js @@ -83,7 +83,7 @@ function ESWotLookupExtendController($scope, $controller, $state) { location: location.length ? location : undefined }; - $state.go('app.registry_lookup', stateParams); + $state.go('app.wot_lookup.tab_registry', stateParams); }; } diff --git a/www/plugins/es/js/services/comment-services.js b/www/plugins/es/js/services/comment-services.js index 339b3b752..374752bbe 100644 --- a/www/plugins/es/js/services/comment-services.js +++ b/www/plugins/es/js/services/comment-services.js @@ -167,8 +167,11 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', if (index === -1) return; data.result.splice(index, 1); delete data.mapById[comment.id]; + + var wallet = !csWallet.isUserPubkey(comment.issuer) ? csWallet.children.getByPubkey(comment.issuer) : csWallet; + // Send deletion request - if (csWallet.isUserPubkey(comment.issuer)) { + if (wallet) { return exports.raw.remove(comment.id) .catch(function(err){ console.error(err); @@ -176,7 +179,7 @@ angular.module('cesium.es.comment.services', ['ngResource', 'cesium.services', }); } else { - return $q.reject("User is not the comment issuer"); + return $q.reject("No wallet found corresponding to the comment issuer"); } }; }; diff --git a/www/plugins/es/js/services/document-services.js b/www/plugins/es/js/services/document-services.js index fc58393ba..41567a054 100644 --- a/www/plugins/es/js/services/document-services.js +++ b/www/plugins/es/js/services/document-services.js @@ -164,19 +164,21 @@ angular.module('cesium.es.document.services', ['ngResource', 'cesium.platform', }); } - function remove(document) { + function remove(document, options) { if (!document || !document.index || !document.type || !document.id) return $q.reject('Could not remove document: missing mandatory fields'); - return esHttp.record.remove(document.index, document.type)(document.id); + return esHttp.record.remove(document.index, document.type)(document.id, options); } - function removeAll(documents) { + function removeAll(documents, options) { if (!documents || !documents.length) return; - return csWallet.auth() - .then(function(walletData) { + var wallet = options && options.walletId && csWallet.children.get(options.walletId) ||Â csWallet; + + return wallet.auth() // Auth once + .then(function() { // Remove each doc return $q.all(documents.reduce(function (res, doc) { - return res.concat(esHttp.record.remove(doc.index, doc.type)(doc.id, walletData)); + return res.concat(esHttp.record.remove(doc.index, doc.type)(doc.id, {wallet: wallet})); }, [])); }); } diff --git a/www/plugins/es/js/services/http-services.js b/www/plugins/es/js/services/http-services.js index 9b0990a28..110e688d0 100644 --- a/www/plugins/es/js/services/http-services.js +++ b/www/plugins/es/js/services/http-services.js @@ -436,17 +436,26 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function postRecord(path, options) { options = options || {}; var postRequest = that.post(path); - return function(record, params) { + return function(record, options) { + options = options || {}; + var wallet = options.wallet || (options.walletId && csWallet.children.get(options.walletId)) + ||Â ((!options.pubkey ||Â csWallet.isUserPubkey(options.pubkey)) && csWallet) + ||Â (options.pubkey && csWallet.children.getByPubkey(options.pubkey)); - var wallet = (params && params.wallet || csWallet); - params = params || {}; - params.pubkey = params.pubkey || wallet.data.pubkey; - var keypair = params.keypair || wallet.data.keypair; - // make sure to hide some params - if (params) { - delete params.wallet; - delete params.keypair; + var keypair = options.keypair || wallet && wallet.data && wallet.data.keypair; + + if (!keypair && !wallet) { + throw new Error('Missing wallet or keypair, to sign record') } + + // Create the POSt request params, + // but BEFORE, remove protected options + delete options.wallet; + delete options.walletId; + delete options.keypair; + var params = angular.copy(options); + params.pubkey = params.pubkey || wallet.data.pubkey; + return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true})) .then(function() { if (options.creationTime && !record.creationTime) { @@ -499,8 +508,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic function removeRecord(index, type) { return function(id, options) { options = options || {}; - var wallet = (options && options.wallet || csWallet); - delete options.wallet; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) ||Â csWallet; return (wallet.isAuth() ? $q.when(wallet.data) : wallet.auth({silent: true, minData: true})) .then(function(walletData) { diff --git a/www/plugins/es/js/services/invitation-services.js b/www/plugins/es/js/services/invitation-services.js index f10946c8f..e10117276 100644 --- a/www/plugins/es/js/services/invitation-services.js +++ b/www/plugins/es/js/services/invitation-services.js @@ -275,42 +275,47 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }); } - function deleteInvitation(invitation) { + function deleteInvitation(invitation, options) { if (!invitation || !invitation.id) throw 'Invalid invitation (empty or without id). Could not delete.'; var type = invitation.type || 'certification'; - return that.raw[type].remove(invitation.id) + var wallet = options && options.walletId && csWallet.children.get(options.walletId) || csWallet; + return that.raw[type].remove(invitation.id, {wallet: wallet}) .then(function() { // Always reset unread count - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; - if (!csWallet.data.invitations || !csWallet.data.invitations.list) return; + if (!wallet.data.invitations || !wallet.data.invitations.list) return; // Remove form list - csWallet.data.invitations.list.splice(csWallet.data.invitations.list.indexOf(invitation), 1); + wallet.data.invitations.list.splice(wallet.data.invitations.list.indexOf(invitation), 1); }); } - function deleteInvitationsByIds(ids, type) { + function deleteInvitationsByIds(ids, type, options) { if (!ids || !ids.length) return $q.when(); type = type || 'certification'; return $q.all( ids.reduce(function(res, id) { - return res.concat(that.raw[type].remove(id)); + return res.concat(that.raw[type].remove(id, options)); }, []) ); } - function deleteAllInvitations(pubkey, type) { - pubkey = pubkey || csWallet.data.pubkey; + function deleteAllInvitationsByPubkey(type, options) { + type = type || 'certification'; - console.debug('[ES] [invitation] Deleting all invitations...'); var now = Date.now(); - var countBeforeDeletion = (csWallet.data.invitations && csWallet.data.invitations.count) || 0; - var unreadCountBeforeDeletion = (csWallet.data.invitations && csWallet.data.invitations.unreadCount) || 0; + console.debug('[ES] [invitation] Deleting all {0} invitations...'.format(type)); + + var wallet = (options && options.pubkey && csWallet.children.getByPubkey(options.pubkey)) + (options && options.walletId && csWallet.children.getByPubkey(options.walletId)) + || csWallet; + var countBeforeDeletion = (wallet.data.invitations && wallet.data.invitations.count) || 0; + var unreadCountBeforeDeletion = (wallet.data.invitations && wallet.data.invitations.unreadCount) || 0; // Get invitation ids - return that.raw[type].getIds({pubkey: pubkey}) + return that.raw[type].getIds({pubkey: wallet.data.pubkey}) .then(function(res) { if (!res || !res.hits || !res.hits.total) return; var ids = res.hits.hits.reduce(function (res, hit) { @@ -318,26 +323,26 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', }, []); // Do deletion by ids - return deleteInvitationsByIds(ids, type) + return deleteInvitationsByIds(ids, type, {walletId: wallet.id}) .then(function() { // Update wallet count - csWallet.data.invitations = csWallet.data.invitations || {}; + wallet.data.invitations = wallet.data.invitations || {}; // Decrement count (warning: could have received new invitations during deletion execution) - if (csWallet.data.invitations.count >= countBeforeDeletion) { - csWallet.data.invitations.count -= countBeforeDeletion || 0; + if (wallet.data.invitations.count >= countBeforeDeletion) { + wallet.data.invitations.count -= countBeforeDeletion || 0; } else { - csWallet.data.invitations.count = 0; + wallet.data.invitations.count = 0; } // Decrement count (warning: could have received new invitations during deletion execution) - if (csWallet.data.invitations.unreadCount >= unreadCountBeforeDeletion) { - csWallet.data.invitations.unreadCount -= unreadCountBeforeDeletion || 0; + if (wallet.data.invitations.unreadCount >= unreadCountBeforeDeletion) { + wallet.data.invitations.unreadCount -= unreadCountBeforeDeletion || 0; } else { - csWallet.data.invitations.unreadCount = 0; + wallet.data.invitations.unreadCount = 0; } - console.debug('[ES] [invitation] All invitations deleted in {0}ms'.format(Date.now()-now)); + console.debug('[ES] [invitation] All {0} invitations deleted in {1}ms'.format(type, Date.now()-now)); }); }); } @@ -397,7 +402,7 @@ angular.module('cesium.es.invitation.services', ['cesium.platform', that.send = sendInvitation; that.delete = deleteInvitation; that.deleteByIds = deleteInvitationsByIds; - that.deleteAll = deleteAllInvitations; + that.deleteAll = deleteAllInvitationsByPubkey; that.constants = constants; diff --git a/www/plugins/es/js/services/message-services.js b/www/plugins/es/js/services/message-services.js index 192bb5059..c0bded686 100644 --- a/www/plugins/es/js/services/message-services.js +++ b/www/plugins/es/js/services/message-services.js @@ -66,8 +66,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', console.debug('[ES] [message] Loading count...'); // Count unread messages - countUnreadMessages(data.pubkey, csWallet) - .then(function(unreadCount){ + countUnreadMessages({pubkey: data.pubkey}) + .then(function(unreadCount) { data.messages = data.messages || {}; data.messages.unreadCount = unreadCount; data.messages.time = time; @@ -81,11 +81,13 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', return deferred.promise; } - function countUnreadMessages(pubkey, wallet) { - wallet = wallet ||Â csWallet; - pubkey = pubkey || (wallet.isLogin() ? wallet.data.pubkey : pubkey); + function countUnreadMessages(options) { + options = options ||Â {}; + var wallet = options.wallet + ||Â (options.walletId && csWallet.children.get(options.walletId)) || csWallet; + var pubkey = options.pubkey || (wallet && wallet.data && wallet.data.pubkey); if (!pubkey) { - throw new Error('no pubkey, and user not connected.'); + throw new Error('no pubkey or wallet found in options, and user not connected.'); } var request = { @@ -107,13 +109,22 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Listen message changes function onNewMessageEvent(event, wallet) { - wallet = wallet ||Â csWallet; console.debug("[ES] [message] detected new message (from notification service)"); var notification = new EsNotification(event); notification.issuer = notification.pubkey; delete notification.pubkey; + if (!notification.issuer) return; // Skip if invalid + + // Get the wallet + wallet = wallet ||Â (notification.issuer && csWallet.isUserPubkey(notification.issuer) && csWallet) + || (notification.issuer && csWallet.children.getByPubkey(notification.issuer)); + + if (!wallet) { + throw new Error("No wallet for pubkey: {0}".format(notification.issuer.substring(0, 6))) + } + csWot.extend(notification, 'issuer') .then(function() { @@ -127,7 +138,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', function sendMessage(message, options) { options = options || {}; - var wallet = options.wallet || csWallet; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; message.issuer = message.issuer || wallet.data.pubkey; return wallet.getKeypair() .then(function(keypair) { @@ -173,7 +185,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', options = options || {}; options.from = options.from || 0; options.size = options.size || constants.DEFAULT_LOAD_SIZE; - var wallet = options.wallet ||Â csWallet; + var wallet = options.wallet ||Â options.walletId && csWallet.children.get(options.walletId) || csWallet; + delete options.wallet; if (!wallet.isLogin()) { return $q.when([]); // Should never happen @@ -254,7 +267,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', options.filter = angular.isDefined(options.filter) ? options.filter : undefined; options.from = options.from || 0; - var wallet = options.wallet || csWallet; + var wallet = options.wallet ||Â options.walletId && csWallet.children.get(options.walletId) ||Â csWallet; + delete options.wallet; // avoid error in angular.copy() var promise = wallet.auth() .then(function(walletData) { @@ -279,12 +293,15 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', if (messages.length && options.filter){ var filteredMessages = filterMessages(messages, options.filter); - // Recursive loop, if need more + // Need more messages: iterate again if (filteredMessages.length < messages.length) { options = angular.copy(options); options.from += options.size; options.size = messages.length - filteredMessages.length; - return loadMessages(options) + // put the wallet again, because it has been removed before the angular.copy() + // To avoid an error + options.wallet = wallet; + return loadMessages(options) // Loop .then(function(messages) { return filteredMessages.concat(messages); }); @@ -307,20 +324,20 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', return promise; } - function getAndDecrypt(id, options) { + function getAndDecrypt(id, type, options) { + var type = type || 'inbox'; options = options || {}; - options.type = options.type || 'inbox'; options.summary = angular.isDefined(options.summary) ? options.summary : false/*summary not need by default*/; - var wallet = options.wallet || csWallet; + var wallet = options.wallet ||Â (options.walletId && csWallet.children.get(options.walletId)) ||Â csWallet; return wallet.auth() .then(function(walletData) { - return raw.getByTypeAndId({id: id, type: options.type}) + return raw.getByTypeAndId({id: id, type: type}) .then(function(hit) { if (!hit.found) return; var msg = hit._source; msg.id = hit._id; - msg.read = (options.type == 'outbox') || !!msg.read_signature; + msg.read = (type == 'outbox') || !!msg.read_signature; delete msg.read_signature; // not need anymore // Decrypt message @@ -328,7 +345,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Add avatar .then(function(){ - var avatarField = (options.type == 'inbox') ? 'issuer' : 'recipient'; + var avatarField = (type == 'inbox') ? 'issuer' : 'recipient'; return csWot.extend(msg, avatarField); }); }); @@ -404,26 +421,32 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', } } - function removeMessage(id, type) { + function removeMessage(id, type, options) { type = type || 'inbox'; - return esHttp.record.remove('message', type)(id) + + var wallet = options.wallet ||Â (options.walletId && csWallet.children.get(options.walletId)) ||Â csWallet; + + return esHttp.record.remove('message', type)(id, {wallet: wallet}) .then(function(res) { - // update message count - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = csWallet.data.messages.count > 0 ? csWallet.data.messages.count-1 : 0; + // Update message count + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = wallet.data.messages.count > 0 ? wallet.data.messages.count-1 : 0; } + // Raise event - api.data.raise.delete(id); + if (wallet.isDefault()) { + api.data.raise.delete(id); + } return res; }); } - function removeAllMessages(type) { + function removeAllMessages(type, options) { type = type || 'inbox'; - - return csWallet.auth() + var wallet = options && options.walletId && csWallet.children.get(options.walletId) ||Â csWallet; + return wallet.auth() .then(function(walletData) { // Get all message id return searchMessages(walletData.pubkey, {type: type, from: 0, size: 1000, _source: false}) @@ -434,7 +457,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Remove each messages return $q.all(res.reduce(function (res, msg) { - return res.concat(esHttp.record.remove('message', type)(msg.id, walletData)); + return res.concat(esHttp.record.remove('message', type)(msg.id, {wallet: wallet})); }, [])) .then(function() { return ids; @@ -442,22 +465,25 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }) .then(function (ids) { // update message count - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = 0; - csWallet.data.messages.unreadCount = 0; + if (type === 'inbox') { + wallet.data.messages = wallet.data.messages || {}; + wallet.data.messages.count = 0; + wallet.data.messages.unreadCount = 0; } // Raise events - _.forEach(ids, api.data.raise.delete); + if (wallet.isDefault()) { + _.forEach(ids, api.data.raise.delete); + } }); }); } // Mark a message as read function markMessageAsRead(message, options) { - var type = options && options.type || 'inbox'; - var wallet = options && options.wallet || csWallet; + options = options ||Â {}; + var wallet = options.wallet || options.walletId && csWallet.children.get(options.walletId) || csWallet; + var type = options && options.type || (!wallet.isUserPubkey(message.recipient) ? 'outbox' : 'inbox'); if (message.read) { var deferred = $q.defer(); deferred.resolve(); @@ -479,7 +505,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Update message count .then(function() { - if (type == 'inbox') { + if (type === 'inbox') { wallet.data.messages = wallet.data.messages || {}; wallet.data.messages.unreadCount = wallet.data.messages.unreadCount ? wallet.data.messages.unreadCount - 1 : 0; } @@ -488,7 +514,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', // Mark all messages as read function markAllMessageAsRead(options) { - var wallet = options && options.wallet || csWallet; + options = options ||Â {}; + var wallet = options.wallet ||Â options.walletId && csWallet.children.get(options.walletId) || csWallet; return wallet.auth() .then(function(walletData) { diff --git a/www/plugins/es/js/services/subscription-services.js b/www/plugins/es/js/services/subscription-services.js index a8924bd67..34b72c1e2 100644 --- a/www/plugins/es/js/services/subscription-services.js +++ b/www/plugins/es/js/services/subscription-services.js @@ -81,12 +81,12 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es }); } - function addRecord(record, wallet) { + function addRecord(record, options) { if (!record || !record.type || !record.content || !record.recipient) { return $q.reject("Missing arguments 'record' or 'record.type' or 'record.content' or 'record.recipient'"); } - wallet = wallet || csWallet; + var wallet = options && options.wallet || (options && options.walletId && csWallet.children.get(options.walletId)) || csWallet; var issuer = wallet.data.pubkey; var contentStr = JSON.stringify(record.content); @@ -115,12 +115,12 @@ angular.module('cesium.es.subscription.services', ['cesium.platform', 'cesium.es ; } - function updateRecord(record, wallet) { + function updateRecord(record, options) { if (!record || !record.content || !record.recipient) { return $q.reject("Missing arguments 'record' or 'record.content', or 'record.recipient'"); } - wallet = wallet || csWallet; + var wallet = options && options.wallet || (options && options.walletId && csWallet.children.get(options.walletId)) || csWallet; var issuer = wallet.data.pubkey; var contentStr = JSON.stringify(record.content); diff --git a/www/plugins/es/templates/message/list.html b/www/plugins/es/templates/message/list.html index a352f5d4c..c564a6e49 100644 --- a/www/plugins/es/templates/message/list.html +++ b/www/plugins/es/templates/message/list.html @@ -8,8 +8,8 @@ <ion-item class="item item-border-large item-avatar item-icon-right ink" - ng-repeat="msg in search.results" - ng-click="select(msg)"> + ng-repeat="msg in :rebind:search.results track by msg.id" + ng-click="select(msg, $event)"> <i ng-if="::!msg.avatar" class="item-image icon" ng-class="{'ion-person': msg.uid, 'ion-email': !msg.uid}"></i> <i ng-if="::msg.avatar" class="item-image avatar" style="background-image: url({{::msg.avatar.src}})"></i> diff --git a/www/plugins/es/templates/message/lookup_by_id.html b/www/plugins/es/templates/message/lookup_by_id.html new file mode 100644 index 000000000..cdf3578f4 --- /dev/null +++ b/www/plugins/es/templates/message/lookup_by_id.html @@ -0,0 +1,17 @@ +<ion-view left-buttons="leftButtons" class="view-messages"> + + <ion-tabs class="tabs-positive tabs-icon-top"> + + <ion-tab title="{{'MESSAGE.LIST.INBOX'|translate}}" icon="ion-archive" + ui-sref="app.user_messages_by_id.tab_inbox"> + <ion-nav-view name="tab_inbox"></ion-nav-view> + </ion-tab> + + <ion-tab title="{{'MESSAGE.LIST.OUTBOX'|translate}}" icon="ion-paper-airplane" + ui-sref="app.user_messages_by_id.tab_outbox"> + <ion-nav-view name="tab_outbox"></ion-nav-view> + </ion-tab> + + </ion-tabs> + +</ion-view> diff --git a/www/plugins/es/templates/message/lookup_lg.html b/www/plugins/es/templates/message/lookup_lg.html index 70db4c64b..66349decf 100644 --- a/www/plugins/es/templates/message/lookup_lg.html +++ b/www/plugins/es/templates/message/lookup_lg.html @@ -12,7 +12,7 @@ <ion-content class="padding no-padding-xs no-padding-sm"> <ion-refresher pulling-text="{{'COMMON.BTN_REFRESH' | translate}}" - on-refresh="refresh(true)"> + on-refresh="refresh(true, $event)"> </ion-refresher> <!-- Buttons bar--> @@ -37,16 +37,32 @@ <!-- button tabs --> <div class="buttons-tabs border-bottom hidden-sm hidden-xs"> <div class="pull-right"> - <div - class="button button-tab dark" + + <!-- inbox tab --> + <a + ng-hide="!isDefaultWallet" + class="button button-tab ink dark" title="{{'MESSAGE.LIST.INBOX' | translate}}" nav-transition="none" ng-class="{'active': type=='inbox'}" ui-sref="app.user_messages_lg_inbox"> <i class="icon ion-archive"></i> {{'MESSAGE.LIST.INBOX' | translate}} - </div> + </a> + <a + ng-hide="isDefaultWallet" + class="button button-tab ink dark" + title="{{'MESSAGE.LIST.INBOX' | translate}}" + nav-transition="none" + ng-class="{'active': type=='inbox'}" + ui-sref="app.user_messages_lg_inbox_by_id({id: walletId})"> + <i class="icon ion-archive"></i> + {{'MESSAGE.LIST.INBOX' | translate}} + </a> + + <!-- outbox tab --> <a + ng-hide="!isDefaultWallet" class="button button-tab ink dark" title="{{'MESSAGE.LIST.OUTBOX' | translate}}" nav-transition="none" @@ -55,6 +71,16 @@ <i class="icon ion-paper-airplane"></i> {{'MESSAGE.LIST.OUTBOX' | translate}} </a> + <a + ng-hide="isDefaultWallet" + class="button button-tab ink dark" + title="{{'MESSAGE.LIST.OUTBOX' | translate}}" + nav-transition="none" + ng-class="{'active': type=='outbox'}" + ui-sref="app.user_messages_lg_outbox_by_id({id: walletId})"> + <i class="icon ion-paper-airplane"></i> + {{'MESSAGE.LIST.OUTBOX' | translate}} + </a> </div> </div> diff --git a/www/plugins/es/templates/message/popover_message.html b/www/plugins/es/templates/message/popover_message.html index 31ed03406..2155e2031 100644 --- a/www/plugins/es/templates/message/popover_message.html +++ b/www/plugins/es/templates/message/popover_message.html @@ -1,4 +1,4 @@ -<ion-popover-view class="fit hidden-xs hidden-sm popover-notification" +<ion-popover-view class="fit hidden-xs hidden-sm popover-light" ng-controller="PopoverMessageCtrl"> <ion-header-bar class="stable-bg block"> <div class="title" translate>MESSAGE.NOTIFICATIONS.TITLE</div> diff --git a/www/templates/wallet/list/item_wallet_light.html b/www/templates/wallet/list/item_wallet_light.html index b8882d564..610ca609a 100644 --- a/www/templates/wallet/list/item_wallet_light.html +++ b/www/templates/wallet/list/item_wallet_light.html @@ -4,7 +4,7 @@ ng-init="walletData=wallet.data;"> <i ng-if="::!walletData.avatar" class="item-image icon" - ng-class=":rebind:{'ion-card': !walletData.isMember, 'ion-persion': walletData.isMember}"></i> + ng-class="::{'ion-card': !walletData.isMember, 'ion-person': walletData.isMember}"></i> <i ng-if="::walletData.avatar" class="item-image avatar" style="background-image: url({{::walletData.avatar.src}})"></i> <div class="badge badge-button badge-avatar badge-assertive ion-locked " ng-hide="::wallet.isAuth()"> </div> diff --git a/www/templates/wallet/list/popover_wallets.html b/www/templates/wallet/list/popover_wallets.html index 080071a94..458d603b4 100644 --- a/www/templates/wallet/list/popover_wallets.html +++ b/www/templates/wallet/list/popover_wallets.html @@ -1,7 +1,12 @@ -<ion-popover-view class="fit popover-wallets" - ng-controller="PopoverWalletSelectModalCtrl"> - <ion-header-bar> - <h1 class="title" translate>ACCOUNT.SELECT_WALLET_MODAL.TITLE</h1> +<ion-popover-view class="fit popover-wallets popover-light"> + <ion-header-bar class="stable-bg block"> + <div class="title" translate>ACCOUNT.SELECT_WALLET_MODAL.TITLE</div> + + <div class="pull-right"> + <a class="positive" + ng-click="showNewWalletModal()" + translate>ACCOUNT.WALLET_LIST.BTN_NEW</a> + </div> </ion-header-bar> <ion-content scroll="true"> @@ -9,15 +14,30 @@ <ion-spinner icon="android"></ion-spinner> </div> - <div class="center padding gray" ng-if="!loading && !wallets.length"> + <div class="center padding gray" ng-if="!loading && !wallets.length && !defaultWallet"> {{:locale:'ACCOUNT.WALLET_LIST.NO_WALLET'|translate}} </div> <ion-list ng-if="!loading"> - <ng-repeat ng-repeat="wallet in wallets track by wallet.id" + + <ng-include ng-if="defaultWallet" ng-init="wallet = defaultWallet" src="'templates/wallet/list/item_wallet_light.html'"> + </ng-include> + + <ng-repeat ng-repeat="wallet in :rebind:wallets | filter:filterFn(formData) track by wallet.id" ng-include="'templates/wallet/list/item_wallet_light.html'"> </ng-repeat> </ion-list> </ion-content> + + <ion-footer-bar class="stable-bg block"> + + <!-- show all --> + <div class="pull-right"> + <a class="positive" + ui-sref="app.view_wallets" + ng-click="closePopover()" + translate>COMMON.NOTIFICATIONS.SHOW_ALL</a> + </div> + </ion-footer-bar> </ion-popover-view> diff --git a/www/templates/wallet/list/view_wallets.html b/www/templates/wallet/list/view_wallets.html index e0eb1e166..b92075b1e 100644 --- a/www/templates/wallet/list/view_wallets.html +++ b/www/templates/wallet/list/view_wallets.html @@ -62,9 +62,12 @@ </div> <ion-list class="{{::motion.ionListClass}}"> + + <!-- default wallet --> <ng-include ng-if="defaultWallet" ng-init="wallet = defaultWallet" src="'templates/wallet/list/item_wallet.html'"> </ng-include> + <!-- children wallets --> <ng-include ng-repeat="wallet in wallets track by wallet.id" src="'templates/wallet/list/item_wallet.html'"> </ng-include> diff --git a/www/templates/wallet/view_wallet.html b/www/templates/wallet/view_wallet.html index abdd5b998..6825e9292 100644 --- a/www/templates/wallet/view_wallet.html +++ b/www/templates/wallet/view_wallet.html @@ -25,16 +25,31 @@ ng-class="{'hero-qrcode-active': toggleQRCode}"> <div class="content" ng-if="!loading"> + <i class="avatar" ng-if=":rebind:!formData.avatar" ng-class=":rebind:{'avatar-wallet': !formData.isMember, 'avatar-member': formData.isMember}"></i> <i class="avatar" ng-if=":rebind:formData.avatar" style="background-image: url({{:rebind:formData.avatar.src}})"></i> + <h3 class="light"> - <ng-if ng-if=":rebind:formData.name">{{:rebind:formData.name}}</ng-if> - <ng-if ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</ng-if> - <ng-if ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</ng-if> + <ng-if ng-if=":rebind:!enableSelectWallet"> + <span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span> + <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span> + <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span> + </ng-if> + <!-- select wallet button --> + <a ng-if=":rebind:enableSelectWallet" + class="hidden-xs hidden-sm" + style="color: lightgray;" + title="{{:locale:'ACCOUNT.SELECT_WALLET_MODAL.TITLE'|translate}}" + ng-click="showSelectWalletPopover($event)"> + <span ng-if=":rebind:formData.name">{{:rebind:formData.name}}</span> + <span ng-if=":rebind:!formData.name && formData.uid">{{:rebind:formData.uid}}</span> + <span ng-if=":rebind:!formData.name && !formData.uid"><i class="ion-key"></i> {{:rebind:formData.pubkey | formatPubkey}}</span> + <i class="ion-arrow-down-b"></i> + </a> </h3> <h4 class="assertive"><ng-if ng-if=":rebind:(formData.name || formData.uid) && !formData.isMember" translate>WOT.NOT_MEMBER_PARENTHESIS</ng-if></h4> diff --git a/www/templates/wot/view_identity.html b/www/templates/wot/view_identity.html index 8e820bc95..4147fbb3b 100644 --- a/www/templates/wot/view_identity.html +++ b/www/templates/wot/view_identity.html @@ -10,7 +10,7 @@ on-refresh="doUpdate(true)"> </ion-refresher> - <div class="hero"> + <div class="hero" ng-class="{'hero-qrcode-active': toggleQRCode}"> <div class="content" ng-if="!loading"> <i class="avatar" ng-if=":rebind:!formData.avatar" -- GitLab