diff --git a/scss/ionic.app.scss b/scss/ionic.app.scss index fc658014a1d50288d450890bc806da9722695f34..12e8b4d6aae00043aba50438fd949ba9ba9bb108 100644 --- a/scss/ionic.app.scss +++ b/scss/ionic.app.scss @@ -831,7 +831,6 @@ $screen-menu: 845px; text-align: right !important; } - .lookupForm .list .item-avatar { min-height: 80px !important; diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json index e138a02279face8e5a815053f11c77d142513d44..559838b0eab34f6b5abe5562cc98cede4928f103 100644 --- a/www/i18n/locale-en.json +++ b/www/i18n/locale-en.json @@ -42,6 +42,7 @@ "UNIVERSAL_DIVIDEND": "Universal dividend", "UD": "UD", "DATE_PATTERN": "MM/DD/YYYY HH:mm", + "DATE_SHORT_PATTERN": "MM/DD/YYYY", "EMPTY_PARENTHESIS": "(empty)", "UID": "Pseudonym", "ENABLE": "Enable", @@ -112,7 +113,7 @@ "REMEMBER_ME": "Remember me", "PLUGINS_SETTINGS": "Extensions", "BTN_RESET": "Restore default values", - "EXPERT_MODE": "Enable expert mode<span class=\"hidden-xs\"> (Display more details on peers)</span>", + "EXPERT_MODE": "Enable expert mode<span class=\"hidden-xs\">(display more details)</span>", "POPUP_NODE": { "TITLE" : "Duniter Node", "HELP" : "Set the address of the node to use:" @@ -157,9 +158,12 @@ "SEARCH_HELP": "Search (member or public key)", "REGISTERED_SINCE": "Registered since ", "REGISTERED_SINCE_BLOCK": "Registered since block #", - "NO_CERTIFICATIONS": "No certification", + "NO_CERTIFICATION": "No received certification", + "NO_GIVEN_CERTIFICATION": "No given certification", "NOT_MEMBER_PARENTHESIS": "(not member)", "EXPIRE_IN": "Expires", + "NOT_WRITTEN_EXPIRE_IN": "Deadline<br/>treatment", + "EXPIRED": "Expired", "PSEUDO": "Pseudonym", "SIGNED_ON_BLOCK": "Certify on block #{{block}}", "WRITTEN_ON_BLOCK": "Written on block #{{block}}", @@ -197,6 +201,7 @@ "TITLE": "{{uid}} - Certifications sent", "SUMMARY": "Sent certifications", "LIST": "Détails of sent certifications", + "PENDING_LIST": "Pending certifications", "SENT": "Sent certifications", "SENT_BY": "Certifications sent by {{uid}}" } @@ -331,7 +336,10 @@ "IDENTITY_INVALID_BLOCK_HASH": "This membership application is no longer valid (because it references a block that network nodes are cancelled): the person must renew its application for membership <b>before</b> being certified.", "IDENTITY_SANDBOX_FULL": "Could not register, because node's sandbox is full.<br/><br/>Please retry later or choose another Duniter node (in <b>Settings</b>).", "WOT_PENDING_INVALID_BLOCK_HASH": "Membership not valid.", - "WALLET_INVALID_BLOCK_HASH": "Your membership application is no longer valid (because it references a block that network nodes are cancelled).<br/>You must <a ng-click=\"doQuickFix('renew')\">renew your application for membership</a> to fix this issue." + "WALLET_INVALID_BLOCK_HASH": "Your membership application is no longer valid (because it references a block that network nodes are cancelled).<br/>You must <a ng-click=\"doQuickFix('renew')\">renew your application for membership</a> to fix this issue.", + "IDENTITY_ALREADY_CERTIFY": "You have <b>already certified</b> that identity.<br/><br/>Your certificate is still valid (expires {{expiresIn|formatDuration}}).", + "IDENTITY_ALREADY_CERTIFY_PENDING": "You have <b>already certified</b> that identity.<br/><br/>Your certification is still pending (Deadline for treatment {{expiresIn|formatDuration}}).", + "UNABLE_TO_CERTIFY_TITLE": "Unable to certify" }, "INFO": { "POPUP_TITLE": "Information", diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json index 10520b5d6eebb1271a5f6f23e1c00f730c894264..480f437449319162ea990540ecc695a763eed597 100644 --- a/www/i18n/locale-fr-FR.json +++ b/www/i18n/locale-fr-FR.json @@ -42,6 +42,7 @@ "UNIVERSAL_DIVIDEND": "Dividende universel", "UD": "DU", "DATE_PATTERN": "DD/MM/YYYY HH:mm", + "DATE_SHORT_PATTERN": "DD/MM/YYYY", "EMPTY_PARENTHESIS": "(vide)", "UID": "Pseudonyme", "ENABLE": "Activé", @@ -112,7 +113,7 @@ "REMEMBER_ME": "Se souvenir de moi", "PLUGINS_SETTINGS": "Extensions", "BTN_RESET": "Restaurer les valeurs par défaut", - "EXPERT_MODE": "Activer le mode expert<span class=\"hidden-xs\"> (Informations détaillées sur les noeuds)</span>", + "EXPERT_MODE": "Activer le mode expert<span class=\"hidden-xs\">(affichage plus détaillé)</span>", "POPUP_NODE": { "TITLE" : "Noeud Duniter", "HELP" : "Saisissez l'adresse du noeud que vous voulez utiliser :" @@ -157,12 +158,15 @@ "SEARCH_HELP": "Recherche (pseudo ou clé publique)", "REGISTERED_SINCE": "Inscription", "REGISTERED_SINCE_BLOCK": "Inscrit au block #", - "NO_CERTIFICATIONS": "Aucune certification", + "NO_CERTIFICATION": "Aucune certification validée", + "NO_GIVEN_CERTIFICATION": "Aucune certification émise", "NOT_MEMBER_PARENTHESIS": "(non membre)", "EXPIRE_IN": "Expiration", + "NOT_WRITTEN_EXPIRE_IN": "Date limite<br/>de traitement", + "EXPIRED": "Expiré", "PSEUDO": "Pseudonyme", - "SIGNED_ON_BLOCK": "Certifié au bloc #{{block}}", - "WRITTEN_ON_BLOCK": "Ecrit au bloc #{{block}}", + "SIGNED_ON_BLOCK": "Emise au bloc #{{block}}", + "WRITTEN_ON_BLOCK": "Ecrite au bloc #{{block}}", "GENERAL_DIVIDER": "Informations générales", "TECHNICAL_DIVIDER": "Informations techniques", "BTN_CERTIFY": "Certifier", @@ -197,6 +201,7 @@ "TITLE": "{{uid}} - Certifications émises", "SUMMARY": "Certifications émises", "LIST": "Détail des certifications émises", + "PENDING_LIST": "Certifications en attente de traitement", "SENT": "Certifications émises", "SENT_BY": "Certifications émises par {{uid}}" } @@ -331,7 +336,10 @@ "IDENTITY_INVALID_BLOCK_HASH": "Cette demande d'adhésion n'est plus valide (car elle référence un bloc que les noeuds du réseau ont annulé) : cette personne doit renouveller sa demande d'adhésion <b>avant</b> d'être certifiée.", "IDENTITY_SANDBOX_FULL": "Le noeud Duniter utilisé par Cesium ne peut plus recevoir de nouvelles identités, car sa file d'attente est pleine.<br/><br/>Veuillez réessayer ultérieurement ou changer de noeud (via le menu <b>Paramètres</b>).", "WOT_PENDING_INVALID_BLOCK_HASH": "Adhésion non valide.", - "WALLET_INVALID_BLOCK_HASH": "Votre demande d'adhésion n'est plus valide (car elle référence un bloc que les noeuds du réseau ont annulé).<br/>Vous devez <a ng-click=\"doQuickFix('renew')\">envoyer une nouvelle demande</a> pour résoudre ce problème." + "WALLET_INVALID_BLOCK_HASH": "Votre demande d'adhésion n'est plus valide (car elle référence un bloc que les noeuds du réseau ont annulé).<br/>Vous devez <a ng-click=\"doQuickFix('renew')\">envoyer une nouvelle demande</a> pour résoudre ce problème.", + "IDENTITY_ALREADY_CERTIFY": "Vous avez <b>déjà certifié</b> cette identité.<br/><br/>Cette certification est encore valide (expiration {{expiresIn|formatDuration}}).", + "IDENTITY_ALREADY_CERTIFY_PENDING": "Vous avez <b>déjà certifié</b> cette identité.<br/><br/>Cette certification est en attente de traitement (date limite de traitement {{expiresIn|formatDuration}}).", + "UNABLE_TO_CERTIFY_TITLE": "Certification impossible" }, "INFO": { "POPUP_TITLE": "Information", diff --git a/www/index.html b/www/index.html index 88c4c89b44a8a9a72b02b7f7bfcb618d86303dd1..93f33d393f7fc22c4abcb4fe7ca02a11c6967aee 100644 --- a/www/index.html +++ b/www/index.html @@ -56,6 +56,7 @@ <script src="dist/dist_js/app/services/network-services.js"></script> <script src="dist/dist_js/app/services/crypto-services.js"></script> <script src="dist/dist_js/app/services/utils-services.js"></script> + <script src="dist/dist_js/app/services/cache-services.js"></script> <script src="dist/dist_js/app/services/modal-services.js"></script> <script src="dist/dist_js/app/services/http-services.js"></script> <script src="dist/dist_js/app/services/storage-services.js"></script> diff --git a/www/js/app.js b/www/js/app.js index f837e916c3e8f258a38156d69372454d412c6a7c..9ecd29621760c13863b32bee71a54642c25b702d 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -53,6 +53,12 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht }; }) + .filter('formatDateShort', function($rootScope) { + return function(input) { + return input ? moment(parseInt(input)*1000).local().format($rootScope.dateShortPattern || 'YYYY-MM-DD') : ''; + }; + }) + .filter('formatFromNow', function() { return function(input) { return input ? moment(parseInt(input)*1000).startOf('minute').fromNow() : ''; @@ -261,9 +267,16 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht } // Set date pattern (see 'formatDate' filter) - $translate('COMMON.DATE_PATTERN') - .then(function(datePattern) { - $rootScope.datePattern = datePattern || 'YYYY-MM-DD HH:mm'; + $translate(['COMMON.DATE_PATTERN', 'COMMON.DATE_SHORT_PATTERN']) + .then(function(translations) { + $rootScope.datePattern = translations['COMMON.DATE_PATTERN']; + if ($rootScope.datePattern == 'COMMON.DATE_PATTERN') { + $rootScope.datePattern = 'YYYY-MM-DD HH:mm'; + } + $rootScope.dateShortPattern = translations['COMMON.DATE_SHORT_PATTERN']; + if ($rootScope.dateShortPattern == 'COMMON.DATE_SHORT_PATTERN') { + $rootScope.dateShortPattern = 'YYYY-MM-DD'; + } }); }; diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js index 6ec64b209f04a1c0f959e2cc8a006621ffd7a618..d55e8000b7014e97a9f9cec8f771df758ae898f8 100644 --- a/www/js/controllers/app-controllers.js +++ b/www/js/controllers/app-controllers.js @@ -71,16 +71,16 @@ function PluginExtensionPointController($scope, PluginService) { * Abstract controller (inherited by other controllers) */ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $timeout, $ionicHistory, $controller, - UIUtils, BMA, Wallet, Device, Modals, csSettings, csConfig + UIUtils, BMA, csWallet, Device, Modals, csSettings, csConfig ) { 'ngInject'; $scope.search = {}; - $rootScope.walletData = Wallet.data; + $rootScope.walletData = csWallet.data; $rootScope.settings = csSettings.data; $rootScope.config = csConfig; $rootScope.device = Device; - $rootScope.login = Wallet.isLogin(); + $rootScope.login = csWallet.isLogin(); //////////////////////////////////////// // Show view @@ -131,7 +131,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ $scope.createHelptipScope = function(isTour) { if (!isTour && ($rootScope.tour || !$rootScope.settings.helptip.enable)) { - return; // avoid other helptip to be launched (e.g. wallet) + return; // avoid other helptip to be launched (e.g. csWallet) } // Create a new scope for the tour controller var helptipScope = $scope.$new(); @@ -140,7 +140,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }; $scope.startHelpTour = function() { - $rootScope.tour = true; // to avoid other helptip to be launched (e.g. wallet) + $rootScope.tour = true; // to avoid other helptip to be launched (e.g. csWallet) var helptipScope = $scope.createHelptipScope(true); return helptipScope.startHelpTour() .then(function() { @@ -185,7 +185,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ // Warn if wallet has been never used - see #167 var _showConfirmIfUnused = function() { - var showAlert = !csConfig.initPhase && Wallet.isNeverUsed() && (!csSettings.data.wallet || csSettings.data.wallet.alertIfUnusedWallet); + var showAlert = !csConfig.initPhase && csWallet.isNeverUsed() && (!csSettings.data.wallet || csSettings.data.wallet.alertIfUnusedWallet); if (!showAlert) return; UIUtils.alert.confirm('CONFIRM.LOGIN_UNUSED_WALLET', 'CONFIRM.LOGIN_UNUSED_WALLET_TITLE', { @@ -204,12 +204,12 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }; return $q(function(resolve, reject){ - if (!Wallet.isLogin()) { + if (!csWallet.isLogin()) { return $scope.showLoginModal() .then(function(walletData) { if (walletData) { $rootScope.viewFirstEnter = false; - Wallet.loadData() + csWallet.loadData() .then(function(walletData){ _showConfirmIfUnused(); $rootScope.walletData = walletData; @@ -229,8 +229,8 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ } }); } - else if (!Wallet.data.loaded) { - return Wallet.loadData() + else if (!csWallet.data.loaded) { + return csWallet.loadData() .then(function(walletData){ _showConfirmIfUnused(); $rootScope.walletData = walletData; @@ -246,7 +246,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }); } else { - resolve(Wallet.data); + resolve(csWallet.data); } }); }; @@ -260,7 +260,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ $scope.loginAndGo = function(state) { $scope.closeProfilePopover(); - if (!Wallet.isLogin()) { + if (!csWallet.isLogin()) { return $scope.showLoginModal() .then(function(walletData){ UIUtils.loading.hide(10); @@ -285,7 +285,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ csSettings.data.useLocalStorage = csSettings.data.rememberMe ? true : csSettings.data.useLocalStorage; csSettings.store(); } - return Wallet.login(formData.username, formData.password); + return csWallet.login(formData.username, formData.password); }) .then(function(walletData){ if (walletData) { @@ -307,7 +307,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ return; } UIUtils.loading.show(); - return Wallet.logout() + return csWallet.logout() .then(function() { $ionicSideMenuDelegate.toggleLeft(); $ionicHistory.clearHistory(); @@ -321,17 +321,17 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }; // add listener on wallet event - Wallet.api.data.on.login($scope, function(walletData, resolve) { + csWallet.api.data.on.login($scope, function(walletData, resolve) { $rootScope.login = true; if (resolve) resolve(); }); - Wallet.api.data.on.logout($scope, function() { + csWallet.api.data.on.logout($scope, function() { $rootScope.login = false; }); // If connected and same pubkey $scope.isUserPubkey = function(pubkey) { - return Wallet.isUserPubkey(pubkey); + return csWallet.isUserPubkey(pubkey); }; //////////////////////////////////////// diff --git a/www/js/controllers/help-controllers.js b/www/js/controllers/help-controllers.js index e672919a14e77b9a7bc3a8ed131da3c809bc66cc..9bda73f6e3211b869b16fe42d0f2720a695385ff 100644 --- a/www/js/controllers/help-controllers.js +++ b/www/js/controllers/help-controllers.js @@ -79,8 +79,8 @@ function HelpModalController($scope, $timeout, $anchorScroll, csSettings, parame /* ---------------------------- * Help Tip * ---------------------------- */ -function HelpTipController($scope, $rootScope, $state, $window, $ionicSideMenuDelegate, $timeout, $q, $translate, $sce, - UIUtils, csConfig, csSettings, csCurrency, Device, Wallet) { +function HelpTipController($scope, $rootScope, $state, $window, $ionicSideMenuDelegate, $timeout, $q, + UIUtils, csConfig, csSettings, csCurrency, Device, csWallet) { $scope.tour = false; // Is a tour or a helptip ? @@ -183,7 +183,7 @@ function HelpTipController($scope, $rootScope, $state, $window, $ionicSideMenuDe // Wallet tour (if login) .then(function(next){ if (!next) return false; - if (!Wallet.isLogin()) return true; // not login: continue + if (!csWallet.isLogin()) return true; // not login: continue return $scope.startWalletTour(0, true) .then(function(endIndex){ if (!endIndex) return false; @@ -196,7 +196,7 @@ function HelpTipController($scope, $rootScope, $state, $window, $ionicSideMenuDe // Wallet certifications tour .then(function(next){ if (!next) return false; - if (!Wallet.isLogin()) return true; // not login: continue + if (!csWallet.isLogin()) return true; // not login: continue return $scope.startWalletCertTour(0, true) .then(function(endIndex){ if (!endIndex) return false; @@ -562,7 +562,7 @@ function HelpTipController($scope, $rootScope, $state, $window, $ionicSideMenuDe * @returns {*} */ $scope.startWalletNoLoginTour = function(startIndex, hasNext) { - if (Wallet.isLogin()) return $scope.emptyPromise(true); // skip if login + if (csWallet.isLogin()) return $scope.emptyPromise(true); // skip if login var steps = [ function () { @@ -587,7 +587,7 @@ function HelpTipController($scope, $rootScope, $state, $window, $ionicSideMenuDe * @returns {*} */ $scope.startWalletTour = function(startIndex, hasNext) { - if (!Wallet.isLogin()) return $scope.emptyPromise(true); // skip if not login + if (!csWallet.isLogin()) return $scope.emptyPromise(true); // skip if not login var contentParams; @@ -678,7 +678,7 @@ function HelpTipController($scope, $rootScope, $state, $window, $ionicSideMenuDe * @returns {*} */ $scope.startWalletCertTour = function(startIndex, hasNext) { - if (!Wallet.isLogin()) return $scope.emptyPromise(true); + if (!csWallet.isLogin()) return $scope.emptyPromise(true); var contentParams; var skipAll = false; @@ -900,7 +900,7 @@ function HelpTipController($scope, $rootScope, $state, $window, $ionicSideMenuDe } // If login: redirect to wallet - if (Wallet.isLogin()) { + if (csWallet.isLogin()) { return $state.go('app.view_wallet') .then(function(){ return $scope.showHelpTip('helptip-wallet-balance', { diff --git a/www/js/controllers/join-controllers.js b/www/js/controllers/join-controllers.js index ed5227d21733848c45018eebaeb7a74bae060dfd..0529a73b0f9b30e65ec07dd1cf16f81de0f77ff4 100644 --- a/www/js/controllers/join-controllers.js +++ b/www/js/controllers/join-controllers.js @@ -36,7 +36,7 @@ function JoinController($timeout, Modals) { } -function JoinModalController($scope, $state, $timeout, UIUtils, CryptoUtils, Modals, Wallet, csCurrency, PluginService) { +function JoinModalController($scope, $state, UIUtils, CryptoUtils, Modals, csWallet, csCurrency) { 'ngInject'; $scope.formData = { @@ -150,7 +150,7 @@ function JoinModalController($scope, $state, $timeout, UIUtils, CryptoUtils, Mod var onErrorLogout = function(message) { return function(err) { - Wallet.logout() + csWallet.logout() .then(function(){ UIUtils.onError(message)(err); }); @@ -159,7 +159,7 @@ function JoinModalController($scope, $state, $timeout, UIUtils, CryptoUtils, Mod UIUtils.loading.show(); - Wallet.login($scope.formData.username, $scope.formData.password) + csWallet.login($scope.formData.username, $scope.formData.password) .then(function() { if (!$scope.formData.isMember) { // Redirect to wallet @@ -168,10 +168,10 @@ function JoinModalController($scope, $state, $timeout, UIUtils, CryptoUtils, Mod } // Send self - Wallet.self($scope.formData.pseudo, false/*do NOT load membership here*/) + csWallet.self($scope.formData.pseudo, false/*do NOT load membership here*/) .then(function() { // Send membership IN - Wallet.membership.inside() + csWallet.membership.inside() .then(function() { $scope.closeModal(); diff --git a/www/js/controllers/settings-controllers.js b/www/js/controllers/settings-controllers.js index b5b632778d9df8d52c48cb36c6760620a7f92ec1..c0a070d3c57d73429f7d7c81eda2a0686b0ede2e 100644 --- a/www/js/controllers/settings-controllers.js +++ b/www/js/controllers/settings-controllers.js @@ -36,7 +36,7 @@ function SettingsController($scope, $q, $ionicPopup, $timeout, $translate, csHtt }; $scope.load = function() { - $scope.loading = true; // to avoid the call of Wallet.store() + $scope.loading = true; // to avoid the call of csWallet.store() // Fill locales $scope.locales = angular.copy(UIUtils.locales); diff --git a/www/js/controllers/transfer-controllers.js b/www/js/controllers/transfer-controllers.js index 58164acad7df21952093be34a6b64e21f3f753ba..f119975afae7e0b197a00cef302b28c0f2f7b53a 100644 --- a/www/js/controllers/transfer-controllers.js +++ b/www/js/controllers/transfer-controllers.js @@ -44,10 +44,10 @@ angular.module('cesium.transfer.controllers', ['cesium.services', 'cesium.curren .controller('TransferModalCtrl', TransferModalController) ; -function TransferController($scope, $rootScope, $state, BMA, Wallet, UIUtils, $timeout, Device, $ionicPopover, $translate, $filter, $q, Modals, $ionicHistory) { +function TransferController($scope, $rootScope, $state, BMA, csWallet, UIUtils, $timeout, Device, $ionicPopover, $translate, $filter, $q, Modals, $ionicHistory) { 'ngInject'; - TransferModalController.call(this, $scope, $rootScope, $state, BMA, Wallet, UIUtils, $timeout, Device, $ionicPopover, $translate, $filter, $q, Modals, csSettings); + TransferModalController.call(this, $scope, $rootScope, $state, BMA, csWallet, UIUtils, $timeout, Device, $ionicPopover, $translate, $filter, $q, Modals, csSettings); $scope.$on('$ionicView.enter', function(e, state) { if (!!state.stateParams && !!state.stateParams.pubkey) { @@ -80,7 +80,7 @@ function TransferController($scope, $rootScope, $state, BMA, Wallet, UIUtils, $t }; } -function TransferModalController($scope, $rootScope, $ionicPopover, $translate, $filter, $q, BMA, Wallet, UIUtils, Modals, +function TransferModalController($scope, $rootScope, $ionicPopover, $translate, $filter, $q, BMA, csWallet, UIUtils, Modals, csSettings, parameters) { 'ngInject'; @@ -181,7 +181,7 @@ function TransferModalController($scope, $rootScope, $ionicPopover, $translate, amount.replace(new RegExp('[.,]'), '.'); } - Wallet.transfer($scope.formData.destPub, amount, $scope.formData.comment, $scope.formData.useRelative) + csWallet.transfer($scope.formData.destPub, amount, $scope.formData.comment, $scope.formData.useRelative) .then(function() { UIUtils.loading.hide(); $scope.closeModal(true); diff --git a/www/js/controllers/wallet-controllers.js b/www/js/controllers/wallet-controllers.js index 5c496867df65bd0538b7ea92e25a07dac374f58f..6f0aa4b69abca9025801b7d6d8598dfdf59d7e30 100644 --- a/www/js/controllers/wallet-controllers.js +++ b/www/js/controllers/wallet-controllers.js @@ -33,7 +33,7 @@ angular.module('cesium.wallet.controllers', ['cesium.services', 'cesium.currency ; function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, $ionicHistory, - UIUtils, Wallet, $translate, $ionicPopover, Modals, csSettings, BMA) { + UIUtils, csWallet, $translate, $ionicPopover, Modals, csSettings, BMA) { 'ngInject'; $scope.convertedBalance = null; @@ -159,7 +159,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, .then(function(uid) { UIUtils.loading.show(); - return Wallet.self(uid) + return csWallet.self(uid) .then(function() { $scope.updateView(); UIUtils.loading.hide(); @@ -174,7 +174,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, }; $scope.doMembershipIn = function(retryCount) { - return Wallet.membership.inside() + return csWallet.membership.inside() .then(function() { $scope.updateView(); UIUtils.loading.hide(); @@ -206,7 +206,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, if (!$rootScope.walletData.blockUid || uid != $rootScope.walletData.uid) { $rootScope.walletData.blockUid = null; $rootScope.walletData.uid = uid; - Wallet.self(uid, false/*do NOT load membership here*/) + csWallet.self(uid, false/*do NOT load membership here*/) .then(function() { $scope.doMembershipIn(); }) @@ -241,7 +241,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, } UIUtils.loading.show(); - return Wallet.membership.out() + return csWallet.membership.out() .then(function() { UIUtils.loading.hide(); UIUtils.toast.show('INFO.MEMBERSHIP_OUT_SENT'); @@ -252,7 +252,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, // Updating wallet data $scope.doUpdate = function() { UIUtils.loading.show(); - return Wallet.refreshData() + return csWallet.refreshData() .then(function() { $scope.updateView(); UIUtils.loading.hide(); @@ -316,6 +316,15 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, /* -- popup / UI -- */ + $scope.toggleShowDetails = function() { + // Update user settings + csSettings.data.wallet = csSettings.data.wallet || {}; + csSettings.data.wallet.showPubkey = !$scope.showDetails; + csSettings.store(); + + $scope.setShowDetails(csSettings.data.wallet.showPubkey); + }; + $scope.setShowDetails = function(show) { $scope.showDetails = show; $scope.hideActionsPopover(); @@ -332,11 +341,6 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, pubkeyElement.classList.toggle('in', true); }, 500); } - - // Update user settings - csSettings.data.wallet = csSettings.data.wallet || {}; - csSettings.data.wallet.showPubkey = show; - csSettings.store(); }; // Transfer @@ -462,7 +466,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, (Math.trunc(new Date().getTime() / 1000) - 2 * csSettings.data.walletHistoryTimeSecond); UIUtils.loading.show(); - return Wallet.refreshData({tx: {enable: true,fromTime: fromTime}}) + return csWallet.refreshData({tx: {enable: true,fromTime: fromTime}}) .then(function() { $scope.updateView(); UIUtils.loading.hide(); @@ -483,7 +487,7 @@ function WalletController($scope, $rootScope, $q, $ionicPopup, $timeout, $state, } -function WalletTxErrorController($scope, $timeout, UIUtils, Wallet) { +function WalletTxErrorController($scope, $timeout, UIUtils, csWallet) { 'ngInject'; $scope.$on('$ionicView.enter', function(e) { @@ -508,7 +512,7 @@ function WalletTxErrorController($scope, $timeout, UIUtils, Wallet) { // Updating wallet data $scope.doUpdate = function() { UIUtils.loading.show(); - Wallet.refreshData() + csWallet.refreshData() .then(function() { $scope.updateView(); UIUtils.loading.hide(); diff --git a/www/js/controllers/wot-controllers.js b/www/js/controllers/wot-controllers.js index 16425d02a373a4352f8f9c5bf87bb60010a4e6c8..74089bd8ca8e4492829f43b4554263b8e4f91588 100644 --- a/www/js/controllers/wot-controllers.js +++ b/www/js/controllers/wot-controllers.js @@ -84,7 +84,7 @@ angular.module('cesium.wot.controllers', ['cesium.services']) ; -function WotLookupController($scope, BMA, $state, UIUtils, $timeout, csConfig, csSettings, Device, Wallet, WotService, $focus, $ionicPopover) { +function WotLookupController($scope, BMA, $state, UIUtils, $timeout, csConfig, csSettings, Device, csWallet, csWot, $focus, $ionicPopover) { 'ngInject'; var defaultSearchLimit = 20; @@ -143,7 +143,7 @@ function WotLookupController($scope, BMA, $state, UIUtils, $timeout, csConfig, c } else { $scope.search.type = 'text'; - WotService.search(text) + csWot.search(text) .then(function(idties){ if ($scope.search.type != 'text') return; // could have change if ($scope.search.text.trim() !== text) return; // search text has changed before received response @@ -165,8 +165,8 @@ function WotLookupController($scope, BMA, $state, UIUtils, $timeout, csConfig, c $scope.search.type = 'newcomers'; $scope.search.limit = (limit && limit > 0) ? limit : defaultSearchLimit; var searchFunction = csConfig.initPhase ? - WotService.all : - WotService.newcomers; + csWot.all : + csWot.newcomers; return searchFunction($scope.search.limit).then(function(idties){ if ($scope.search.type != 'newcomers') return; // could have change $scope.doDisplayResult(idties); @@ -178,7 +178,7 @@ function WotLookupController($scope, BMA, $state, UIUtils, $timeout, csConfig, c $scope.search.loading = more ? false : true; $scope.search.type = 'pending'; $scope.search.limit = (limit && limit > 0) ? limit : defaultSearchLimit; - return WotService.pending($scope.search.limit).then(function(idties){ + return csWot.pending($scope.search.limit).then(function(idties){ if ($scope.search.type != 'pending') return; // could have change $scope.doDisplayResult(idties); }); @@ -206,7 +206,7 @@ function WotLookupController($scope, BMA, $state, UIUtils, $timeout, csConfig, c $scope.select = function(identity) { // identity = self -> open the user wallet - if (Wallet.isUserPubkey(identity.pubkey)) { + if (csWallet.isUserPubkey(identity.pubkey)) { $state.go('app.view_wallet'); } // Open identity view @@ -313,10 +313,10 @@ function WotLookupController($scope, BMA, $state, UIUtils, $timeout, csConfig, c } -function WotLookupModalController($scope, BMA, $state, UIUtils, $timeout, csConfig, csSettings, Device, Wallet, WotService, $focus, $ionicPopover){ +function WotLookupModalController($scope, BMA, $state, UIUtils, $timeout, csConfig, csSettings, Device, csWallet, csWot, $focus, $ionicPopover){ 'ngInject'; - WotLookupController.call(this, $scope, BMA, $state, UIUtils, $timeout, csConfig, csSettings, Device, Wallet, WotService, $focus, $ionicPopover); + WotLookupController.call(this, $scope, BMA, $state, UIUtils, $timeout, csConfig, csSettings, Device, csWallet, csWot, $focus, $ionicPopover); $scope.search.loading = false; $scope.enableFilter = false; @@ -343,7 +343,7 @@ function WotLookupModalController($scope, BMA, $state, UIUtils, $timeout, csConf // endRemoveIf(device) } -function WotIdentityViewController($scope, $state, $timeout, UIUtils, WotService) { +function WotIdentityViewController($scope, $state, $timeout, UIUtils, csWot) { 'ngInject'; $scope.formData = {}; @@ -353,11 +353,9 @@ function WotIdentityViewController($scope, $state, $timeout, UIUtils, WotService if (state.stateParams && state.stateParams.pubkey && state.stateParams.pubkey.trim().length > 0) { - if ($scope.loading) { - $scope.load( - state.stateParams.pubkey.trim(), - state.stateParams.uid ? state.stateParams.uid.trim() : null - ); + if ($scope.loading) { // load once + $scope.load(state.stateParams.pubkey.trim(), + true /*withCache*/); } } else { @@ -366,8 +364,8 @@ function WotIdentityViewController($scope, $state, $timeout, UIUtils, WotService } }); - $scope.load = function(pubkey) { - WotService.load(pubkey) + $scope.load = function(pubkey, withCache) { + csWot.load(pubkey, withCache) .then(function(identity){ $scope.formData = identity; $scope.loading = false; @@ -391,7 +389,7 @@ function WotIdentityViewController($scope, $state, $timeout, UIUtils, WotService $scope.showSharePopover = function(event) { var title = $scope.formData.name || $scope.formData.uid || $scope.formData.pubkey; - var url = $state.href('app.wot_view_identity', {pubkey: $scope.formData.pubkey, uid: $scope.formData.name || $scope.formData.uid}, {absolute: true}); + var url = $state.href('app.wot_view_identity', {pubkey: $scope.formData.pubkey, uid: $scope.formData.uid}, {absolute: true}); UIUtils.popover.share(event, { bindings: { url: url, @@ -413,13 +411,13 @@ function WotIdentityViewController($scope, $state, $timeout, UIUtils, WotService * @param $timeout * @param $translate * @param csSettings - * @param Wallet + * @param csWallet * @param UIUtils - * @param WotService + * @param csWot * @param Modals * @constructor */ -function WotCertificationsViewController($scope, $rootScope, $state, $timeout, $translate, csConfig, csSettings, Wallet, UIUtils, WotService, Modals) { +function WotCertificationsViewController($scope, $rootScope, $state, $timeout, $translate, csConfig, csSettings, csWallet, UIUtils, csWot, Modals) { 'ngInject'; $scope.loading = true; @@ -432,14 +430,14 @@ function WotCertificationsViewController($scope, $rootScope, $state, $timeout, $ if (state.stateParams && state.stateParams.pubkey && state.stateParams.pubkey.trim().length > 0) { if ($scope.loading) { - $scope.load(state.stateParams.pubkey.trim()); + $scope.load(state.stateParams.pubkey.trim(), true /*withCache*/); } } // Load from wallet pubkey - else if (Wallet.isLogin()){ + else if (csWallet.isLogin()){ if ($scope.loading) { - $scope.load(Wallet.data.pubkey); + $scope.load(csWallet.data.pubkey, true /*withCache*/); } } @@ -451,13 +449,13 @@ function WotCertificationsViewController($scope, $rootScope, $state, $timeout, $ } }); - $scope.load = function(pubkey) { - return WotService.load(pubkey) + $scope.load = function(pubkey, withCache) { + return csWot.load(pubkey, withCache) .then(function(identity){ $scope.formData = identity; - $scope.canCertify = $scope.formData.hasSelf && (!Wallet.isLogin() || (!Wallet.isUserPubkey(pubkey))); - $scope.canSelectAndCertify = $scope.formData.hasSelf && Wallet.isUserPubkey(pubkey); - $scope.alreadyCertified = $scope.canCertify ? !!_.findWhere(identity.certifications, { uid: Wallet.data.uid, valid: true }) : false; + $scope.canCertify = $scope.formData.hasSelf && (!csWallet.isLogin() || (!csWallet.isUserPubkey(pubkey))); + $scope.canSelectAndCertify = $scope.formData.hasSelf && csWallet.isUserPubkey(pubkey); + $scope.alreadyCertified = $scope.canCertify ? !!_.findWhere(identity.certifications, { uid: csWallet.data.uid, valid: true }) : false; $scope.loading = false; @@ -467,7 +465,7 @@ function WotCertificationsViewController($scope, $rootScope, $state, $timeout, $ $scope.motionGivenCertifications(900); // Show help tip - var isWallet = Wallet.isUserPubkey(pubkey); + var isWallet = csWallet.isUserPubkey(pubkey); $scope.showHelpTip(isWallet); }); }; @@ -488,7 +486,7 @@ function WotCertificationsViewController($scope, $rootScope, $state, $timeout, $ return; } UIUtils.loading.show(); - Wallet.certify($scope.formData.uid, + csWallet.certify($scope.formData.uid, $scope.formData.pubkey, $scope.formData.timestamp, $scope.formData.sig) @@ -527,7 +525,7 @@ function WotCertificationsViewController($scope, $rootScope, $state, $timeout, $ UIUtils.loading.show(); // load selected identity - return WotService.load(idty.pubkey); + return csWot.load(idty.pubkey, false /*no cache*/); }) .then(function(identity) { if (!identity) return; // cancelled @@ -537,6 +535,26 @@ function WotCertificationsViewController($scope, $rootScope, $state, $timeout, $ return; } + // Check not already certified + var previousCert = _.findWhere(identity.certifications, { uid: csWallet.data.uid, pending: false, valid: true}); + if (previousCert) { + $translate('ERROR.IDENTITY_ALREADY_CERTIFY', previousCert) + .then(function(message) { + UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + }); + return; + } + + // Check not pending certification + previousCert = _.findWhere(identity.certifications, { uid: csWallet.data.uid, pending: true, valid: true}); + if (previousCert) { + $translate('ERROR.IDENTITY_ALREADY_CERTIFY_PENDING', previousCert) + .then(function(message) { + UIUtils.alert.error(message, 'ERROR.UNABLE_TO_CERTIFY_TITLE'); + }); + return; + } + // Ask confirmation $translate('CONFIRM.CERTIFY_RULES_TITLE_UID', {uid: identity.uid}) .then(function(confirmTitle) { @@ -549,7 +567,7 @@ function WotCertificationsViewController($scope, $rootScope, $state, $timeout, $ UIUtils.loading.show(); // Send certification - Wallet.certify(identity.uid, + csWallet.certify(identity.uid, identity.pubkey, identity.timestamp, identity.sig) @@ -566,7 +584,7 @@ function WotCertificationsViewController($scope, $rootScope, $state, $timeout, $ // Updating wallet data $scope.doUpdate = function() { - $scope.load($scope.formData.pubkey); + $scope.load($scope.formData.pubkey, false /*no cache*/); }; // Show received certifcations diff --git a/www/js/services/bma-services.js b/www/js/services/bma-services.js index 422d3fdfc2944eff35f3ff577576d46ad25d248b..7ab8d6db4e5b2afc4b0181b9fee370e4e2d3af60 100644 --- a/www/js/services/bma-services.js +++ b/www/js/services/bma-services.js @@ -2,7 +2,7 @@ angular.module('cesium.bma.services', ['ngResource', 'cesium.http.services', 'cesium.settings.services']) -.factory('BMA', function($q, csSettings, csHttp, $rootScope, $timeout) { +.factory('BMA', function($q, csSettings, csHttp, csCache, $rootScope, $timeout) { 'ngInject'; function factory(host, port, cacheEnable) { @@ -42,7 +42,7 @@ angular.module('cesium.bma.services', ['ngResource', 'cesium.http.services', 'ce function copy(otherNode) { if (!!this.instance) { // if main service impl var instance = this.instance; // keep factory - csHttp.cache.clearAll(); // clean cache for old node + csCache.clearAll(); // clean all caches angular.copy(otherNode, this); this.instance = instance; } diff --git a/www/js/services/cache-services.js b/www/js/services/cache-services.js new file mode 100644 index 0000000000000000000000000000000000000000..503a12dc320861ab2eca7711006c5552a1c1ed27 --- /dev/null +++ b/www/js/services/cache-services.js @@ -0,0 +1,91 @@ +angular.module('cesium.cache.services', ['ngResource', 'angular-cache']) + +.factory('csCache', function($http, csSettings, CacheFactory) { + 'ngInject'; + + function factory() { + + var + constants = { + LONG: 1 * 60 * 60 * 1000 /*5 min*/, + SHORT: csSettings.data.cacheTimeMs + }, + cacheNames = []; + ; + + function getOrCreateCache(prefix, maxAge, onExpire){ + prefix = prefix || 'csCache-'; + maxAge = maxAge || constants.cache.SHORT; + var cacheName = prefix + maxAge; + if (!onExpire) { + if (!cacheNames[cacheName]) { + cacheNames[cacheName] = true; + } + return CacheFactory.get(cacheName) || + CacheFactory.createCache(cacheName, { + maxAge: maxAge, + deleteOnExpire: 'aggressive', + //cacheFlushInterval: 60 * 60 * 1000, // clear itself every hour + recycleFreq: Math.max(maxAge - 1000, 5 * 60 * 1000 /*5min*/), + storageMode: 'memory' + // FIXME : enable this when cache is cleaning on rollback + //csSettings.data.useLocalStorage ? 'localStorage' : 'memory' + }); + } + else { + var counter = 1; + while(CacheFactory.get(cacheName + counter)) { + counter++; + } + cacheName = cacheName + counter; + if (!cacheNames[cacheName]) { + cacheNames[cacheName] = true; + } + return CacheFactory.createCache(cacheName, { + maxAge: maxAge, + deleteOnExpire: 'aggressive', + //cacheFlushInterval: 60 * 60 * 1000, // This cache will clear itself every hour + recycleFreq: maxAge, + onExpire: onExpire, + storageMode: 'memory' + // FIXME : enable this when cache is cleaning on rollback + //csSettings.data.useLocalStorage ? 'localStorage' : 'memory' + }); + } + } + + function clearAllCaches() { + console.debug("[http] cleaning all caches"); + _.forEach(_.keys(cacheNames), function(cacheName) { + var cache = CacheFactory.get(cacheName); + if (cache) { + cache.removeAll(); + } + }); + } + + function clearFromPrefix(cachePrefix) { + _.forEach(_.keys(cacheNames), function(cacheName) { + if (cacheName.startsWith(cachePrefix)) { + var cache = CacheFactory.get(cacheNames); + if (cache) { + cache.removeAll(); + } + } + }); + } + + return { + get: getOrCreateCache, + clear: clearFromPrefix, + clearAll: clearAllCaches, + constants: { + LONG : constants.LONG, + SHORT: constants.SHORT + } + }; + } + + return factory(); +}) +; diff --git a/www/js/services/http-services.js b/www/js/services/http-services.js index dd84f83155a2dbd182e8888302e120eff9a0c078..abd3fde6d67aff86bbaa5f6193aa07f1d02ec090 100644 --- a/www/js/services/http-services.js +++ b/www/js/services/http-services.js @@ -1,18 +1,13 @@ -angular.module('cesium.http.services', ['ngResource', 'angular-cache']) +angular.module('cesium.http.services', ['ngResource', 'cesium.cache.services']) -.factory('csHttp', function($http, $q, csSettings, CacheFactory) { +.factory('csHttp', function($http, $q, csSettings, csCache, CacheFactory) { 'ngInject'; function factory(timeout) { var sockets = [], - constants = { - cache: { - LONG: 1 * 60 * 60 * 1000 /*5 min*/, - SHORT: csSettings.data.cacheTimeMs - } - } + cachePrefix = 'csHttp' ; if (!timeout) { @@ -84,41 +79,9 @@ angular.module('cesium.http.services', ['ngResource', 'angular-cache']) }; } - function getOrCreateCache(maxAge, onExpire){ - var cacheName = 'csHttp-' + maxAge; - if (!onExpire) { - return CacheFactory.get(cacheName) || - CacheFactory.createCache(cacheName, { - maxAge: maxAge, - deleteOnExpire: 'aggressive', - //cacheFlushInterval: 60 * 60 * 1000, // clear itself every hour - recycleFreq: Math.max(maxAge - 1000, 5 * 60 * 1000 /*5min*/), - storageMode: 'memory' - // FIXME : enable this when cache is cleaning on rollback - //csSettings.data.useLocalStorage ? 'localStorage' : 'memory' - }); - } - else { - var counter = 1; - while(CacheFactory.get(cacheName + counter)) { - counter++; - } - return CacheFactory.createCache(cacheName + counter, { - maxAge: maxAge, - deleteOnExpire: 'aggressive', - //cacheFlushInterval: 60 * 60 * 1000, // This cache will clear itself every hour - recycleFreq: maxAge, - onExpire: onExpire, - storageMode: 'memory' - // FIXME : enable this when cache is cleaning on rollback - //csSettings.data.useLocalStorage ? 'localStorage' : 'memory' - }); - } - } - function getResourceWithCache(host, port, path, maxAge, autoRefresh) { var url = getUrl(host, port, path); - maxAge = maxAge || constants.cache.LONG; + maxAge = maxAge || csCache.constants.LONG; console.debug('[http] will cache ['+url+'] ' + maxAge + 'ms' + (autoRefresh ? ' with auto-refresh' : '')); return function(params) { @@ -127,7 +90,7 @@ angular.module('cesium.http.services', ['ngResource', 'angular-cache']) timeout: timeout }; if (autoRefresh) { // redo the request if need - config.cache = getOrCreateCache(maxAge, function (key, value) { + config.cache = csCache.get(cachePrefix, maxAge, function (key, value) { console.debug('[http] Refreshing cache for ['+key+'] '); $http.get(key, config) .success(function (data) { @@ -136,7 +99,7 @@ angular.module('cesium.http.services', ['ngResource', 'angular-cache']) }); } else { - config.cache = getOrCreateCache(maxAge); + config.cache = csCache.get(cachePrefix, maxAge); } prepare(url, params, config, function(url, config) { @@ -152,18 +115,6 @@ angular.module('cesium.http.services', ['ngResource', 'angular-cache']) }; } - function clearAllCache() { - console.debug("[http] cleaning all caches"); - var cache = CacheFactory.get('csHttp-' + constants.cache.SHORT); - if (cache) { - cache.removeAll(); - } - cache = CacheFactory.get('csHttp-' + constants.cache.LONG); - if (cache) { - cache.removeAll(); - } - } - function postResource(host, port, path) { var url = getUrl(host, port, path); return function(data, params) { @@ -258,11 +209,7 @@ angular.module('cesium.http.services', ['ngResource', 'angular-cache']) uri: { parse: parseUri }, - cache: { - LONG : constants.LONG, - SHORT: constants.SHORT, - clearAll: clearAllCache - } + cache: csCache.constants }; } diff --git a/www/js/services/network-services.js b/www/js/services/network-services.js index e602fc93cbe11211cc6a966b1e04b03a1007a833..3461062d6215a61c32d1a1144bdb1bea25c76ba1 100644 --- a/www/js/services/network-services.js +++ b/www/js/services/network-services.js @@ -75,7 +75,7 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se $interval.cancel(interval); console.debug('[network] Finish : all peers found. Stopping new peers check.'); // The peer lookup end, we can make a clean final report - sortPeers(); + sortPeers(true/*update main buid*/); } }, 1000); @@ -167,12 +167,12 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se newPeers = newPeers || data.newPeers; if (newPeers.length) { data.peers = data.peers.concat(newPeers.splice(0)); - console.debug('[network] New peers found: sort and add them to result...'); + console.debug('[network] New peers found: add them to result and sort...'); sortPeers(); } }, - sortPeers = function() { + sortPeers = function(updateMainBuid) { // Count peer by current block uid var currents = {}; _.forEach(data.peers, function(peer){ @@ -187,9 +187,8 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se var mainBlock = _.max(buids, function(obj) { return obj.count; }); - data.mainBuid = mainBlock.buid; _.forEach(data.peers, function(peer){ - peer.hasMainConsensusBlock = peer.buid == data.mainBuid; + peer.hasMainConsensusBlock = peer.buid == mainBlock.buid; peer.hasConsensusBlock = !peer.hasMainConsensusBlock && currents[peer.buid] > 1; }); data.peers = _.uniq(data.peers, false, function(peer) { @@ -203,6 +202,11 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se score += (-1 * (peer.uid ? peer.uid.charCodeAt(0) : 999)); // alphabetical order return -score; }); + if (updateMainBuid) { + // TODO: raise a special event if changed ? + data.mainBuid = mainBlock.buid; + //api.data.raise.changed(data); // raise event + } api.data.raise.changed(data); // raise event }, @@ -311,6 +315,7 @@ angular.module('cesium.network.services', ['ngResource', 'ngApi', 'cesium.bma.se // Register extension points api.registerEvent('data', 'changed'); + api.registerEvent('data', 'rollback'); return { id: id, diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index dde9d87031dc258d812fe58f2cd1dd33b09743ee..2a33c7358e1abafaf63b963b9333d60820e4a667 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -3,10 +3,10 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser 'cesium.settings.services']) -.factory('Wallet', function($q, $rootScope, $timeout, $translate, $filter, Api, localStorage, CryptoUtils, BMA, csSettings, csNetwork, Device) { +.factory('csWallet', function($q, $rootScope, $timeout, $translate, $filter, Api, localStorage, CryptoUtils, BMA, csSettings) { 'ngInject'; - Wallet = function(id) { + factory = function(id) { var constants = { @@ -483,7 +483,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser data.tx.pendings = txPendings; data.tx.fromTime = fromTime; data.tx.toTime = data.tx.history.length ? data.tx.history[0].time /*=max(tx.time)*/: fromTime; - console.log('[wallet] TX history loaded in '+ (new Date().getTime()-now) +'ms'); + console.debug('[wallet] TX history loaded in '+ (new Date().getTime()-now) +'ms'); resolve(); }) .catch(function(err) { @@ -1412,7 +1412,7 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser }; }; - var service = Wallet('default'); + var service = factory('default'); // try to restore wallet csSettings.api.data.on.ready($rootScope, function() { @@ -1422,6 +1422,6 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser }); }); - service.instance = Wallet; + service.instance = factory; return service; }); diff --git a/www/js/services/wot-services.js b/www/js/services/wot-services.js index 0da07c5e4902880fdcf5d69cd318696de022c032..606d3d1bcdc519e5074b56a48ad0c451fec9ea20 100644 --- a/www/js/services/wot-services.js +++ b/www/js/services/wot-services.js @@ -2,138 +2,188 @@ angular.module('cesium.wot.services', ['ngResource', 'ngApi', 'cesium.bma.services', 'cesium.crypto.services', 'cesium.utils.services', 'cesium.settings.services']) -.factory('WotService', function($q, $timeout, BMA, Api, csSettings) { +.factory('csWot', function($q, $timeout, BMA, Api, CacheFactory, csSettings, csCache) { 'ngInject'; - WotService = function(id) { + factory = function(id) { var - api = new Api(this, "WotService-" + id), - - _sortAndLimitIdentities = function(idties, size) { - idties = _.sortBy(idties, function(idty){ - var score = 1; - score += (1000000 * (idty.block)); - score += (10 * (900 - idty.uid.toLowerCase().charCodeAt(0))); - return -score; - }); - if (angular.isDefined(size) && idties.length > size) { - idties = idties.slice(0, size); // limit if more than expected size - } - return idties; - }, - - loadRequirements = function(pubkey, uid) { - return $q(function(resolve, reject) { - // Get requirements - BMA.wot.requirements({pubkey: pubkey}) - .then(function(res){ - if (!res.identities || res.identities.length === 0) { - resolve(); - return; - } - if (res.identities.length > 1) { - res.identities = _.sortBy(res.identities, function(idty) { - var score = 1; - score += (100000000000 * ((uid && idty.uid === uid) ? 1 : 0)); - score += (1000000 * idty.membershipExpiresIn); - score += (10 * idty.membershipPendingExpiresIn); - return -score; - }); - } - var requirements = res.identities[0]; - // Add useful custom fields - requirements.hasSelf = true; - requirements.needMembership = (requirements.membershipExpiresIn === 0 && - requirements.membershipPendingExpiresIn <= 0 ); - requirements.needRenew = !requirements.needMembership && (requirements.membershipExpiresIn <= csSettings.data.timeWarningExpire && - requirements.membershipPendingExpiresIn <= 0 ); - requirements.canMembershipOut = (requirements.membershipExpiresIn > 0); - requirements.pendingMembership = (requirements.membershipPendingExpiresIn > 0); - requirements.certificationCount = (requirements.certifications) ? requirements.certifications.length : 0; - requirements.willExpireCertificationCount = requirements.certifications ? requirements.certifications.reduce(function(count, cert){ - if (cert.expiresIn <= csSettings.data.timeWarningExpire) { - return count + 1; - } - return count; - }, 0) : 0; - requirements.isMember = !requirements.needMembership && !requirements.pendingMembership; - resolve(requirements); - }) - .catch(function(err) { - // If not a member: continue - if (!!err && - (err.ucode == BMA.errorCodes.NO_MATCHING_MEMBER || - err.ucode == BMA.errorCodes.NO_IDTY_MATCHING_PUB_OR_UID)) { - resolve({ - hasSelf: false, - needMembership: true, - canMembershipOut: false, - needRenew: false, - pendingMembership: false, - certificationCount: 0, - certifications: [], - needCertifications: false, - needCertificationCount: 0, - willNeedCertificationCount: 0 - }); - } - else { - reject(err); - } + api = new Api(this, "csWot-" + id), + identityCache = csCache.get('csWot-idty-', csCache.constants.SHORT), + + _sortAndLimitIdentities = function(idties, size) { + idties = _.sortBy(idties, function(idty){ + var score = 1; + score += (1000000 * (idty.block)); + score += (10 * (900 - idty.uid.toLowerCase().charCodeAt(0))); + return -score; }); - }); - }, - - loadIdentity = function(pubkey, requirements, parameters) { - return $q(function(resolve, reject) { - BMA.wot.lookup({ search: pubkey }) - .then(function(res){ - var identities = res.results.reduce(function(idties, res) { - return idties.concat(res.uids.reduce(function(uids, idty) { - var blockUid = idty.meta.timestamp.split('-', 2); - return uids.concat({ - uid: idty.uid, - pubkey: res.pubkey, - timestamp: idty.meta.timestamp, - number: parseInt(blockUid[0]), - hash: blockUid[1], - revoked: idty.revoked, - revokedSig: idty.revocation_sig, - sig: idty.self + if (angular.isDefined(size) && idties.length > size) { + idties = idties.slice(0, size); // limit if more than expected size + } + return idties; + }, + + loadRequirements = function(pubkey, uid) { + return $q(function(resolve, reject) { + // Get requirements + BMA.wot.requirements({pubkey: pubkey}) + .then(function(res){ + if (!res.identities || res.identities.length === 0) { + resolve(); + return; + } + if (res.identities.length > 1) { + res.identities = _.sortBy(res.identities, function(idty) { + var score = 1; + score += (100000000000 * ((uid && idty.uid === uid) ? 1 : 0)); + score += (1000000 * idty.membershipExpiresIn); + score += (10 * idty.membershipPendingExpiresIn); + return -score; + }); + } + var requirements = res.identities[0]; + // Add useful custom fields + requirements.hasSelf = true; + requirements.needMembership = (requirements.membershipExpiresIn === 0 && + requirements.membershipPendingExpiresIn <= 0 ); + requirements.needRenew = !requirements.needMembership && (requirements.membershipExpiresIn <= csSettings.data.timeWarningExpire && + requirements.membershipPendingExpiresIn <= 0 ); + requirements.canMembershipOut = (requirements.membershipExpiresIn > 0); + requirements.pendingMembership = (requirements.membershipPendingExpiresIn > 0); + requirements.certificationCount = (requirements.certifications) ? requirements.certifications.length : 0; + requirements.willExpireCertificationCount = requirements.certifications ? requirements.certifications.reduce(function(count, cert){ + if (cert.expiresIn <= csSettings.data.timeWarningExpire) { + return count + 1; + } + return count; + }, 0) : 0; + requirements.isMember = !requirements.needMembership && !requirements.pendingMembership; + resolve(requirements); + }) + .catch(function(err) { + // If not a member: continue + if (!!err && + (err.ucode == BMA.errorCodes.NO_MATCHING_MEMBER || + err.ucode == BMA.errorCodes.NO_IDTY_MATCHING_PUB_OR_UID)) { + resolve({ + hasSelf: false, + needMembership: true, + canMembershipOut: false, + needRenew: false, + pendingMembership: false, + certificationCount: 0, + certifications: [], + needCertifications: false, + needCertificationCount: 0, + willNeedCertificationCount: 0 }); - }, [])); - }, []); - // Choose the more updated identity - var identity = identities.length == 1 ? - identities[0] : - _.sortBy(identities, 'number')[identities.length-1]; - - identity.hasSelf = !!(identity.uid && identity.timestamp && identity.sig); - - // Retrieve certifications - var expiresInByPub = requirements.certifications.reduce(function(map, cert){ - map[cert.from]=cert.expiresIn; - return map; - }, {}); - var certPubkeys = []; - identity.hasPendingCertifications = false; - var certifications = !res.results ? [] : res.results.reduce(function(certs, res) { - return certs.concat(res.uids.reduce(function(certs, idty) { - return certs.concat(idty.others.reduce(function(certs, cert) { - var expiresIn = cert.isMember ? expiresInByPub[cert.pubkey] : null; + } + else { + reject(err); + } + }); + }); + }, + + loadIdentity = function(pubkey, requirements, parameters, medianTime) { + return $q(function(resolve, reject) { + BMA.wot.lookup({ search: pubkey }) + .then(function(res){ + var identities = res.results.reduce(function(idties, res) { + return idties.concat(res.uids.reduce(function(uids, idty) { + var blockUid = idty.meta.timestamp.split('-', 2); + return uids.concat({ + uid: idty.uid, + pubkey: res.pubkey, + timestamp: idty.meta.timestamp, + number: parseInt(blockUid[0]), + hash: blockUid[1], + revoked: idty.revoked, + revokedSig: idty.revocation_sig, + sig: idty.self + }); + }, [])); + }, []); + // Choose the more updated identity + var identity = identities.length == 1 ? + identities[0] : + _.sortBy(identities, 'number')[identities.length-1]; + + identity.hasSelf = !!(identity.uid && identity.timestamp && identity.sig); + + // Retrieve certifications + var expiresInByPub = requirements.certifications.reduce(function(map, cert){ + map[cert.from]=cert.expiresIn; + return map; + }, {}); + var certPubkeys = []; + var pendingCertBlocks = {}; + identity.hasPendingCertifications = false; + var certifications = !res.results ? [] : res.results.reduce(function(certs, res) { + return certs.concat(res.uids.reduce(function(certs, idty) { + return certs.concat(idty.others.reduce(function(certs, cert) { + var expiresIn = cert.isMember ? expiresInByPub[cert.pubkey] : null; + var certTime = expiresIn ? (medianTime - parameters.sigValidity + expiresIn) : null; + var result = { + pubkey: cert.pubkey, + uid: cert.uids[0], + time: certTime, + block: (cert.meta && cert.meta.block_number) ? cert.meta.block_number : 0, + expiresIn: expiresIn, + willExpire: (expiresIn && expiresIn <= csSettings.data.timeWarningExpire), + pending: !expiresIn, + isMember: cert.isMember + }; + if (result.pending) { + identity.hasPendingCertifications = true; + if (!pendingCertBlocks[result.block]) { + pendingCertBlocks[result.block] = [result]; + } + else { + pendingCertBlocks[result.block].push(result); + } + } + if (!certPubkeys[cert.pubkey]) { + certPubkeys[cert.pubkey] = result; + } + else { // if duplicated cert: keep the most recent + if (result.block > certPubkeys[cert.pubkey].block) { + certPubkeys[cert.pubkey] = result; + } + else { + return certs; // skip this result + } + } + return certs.concat(result); + }, certs)); + }, certs)); + }, []); + identity.certifications = _.sortBy(certifications, function(cert){ + var score = 1; + score += (1000000000000 * (cert.expiresIn ? cert.expiresIn : 0)); + score += (10000000 * (cert.isMember ? 1 : 0)); + score += (10 * (cert.block ? cert.block : 0)); + return -score; + }); + identity.certificationCount = requirements.certificationCount; + identity.isMember = requirements.isMember; + delete requirements.certifications; + delete requirements.certificationCount; + + // Store given certs + certPubkeys = []; + var givenCertifications = !res.results ? [] : res.results.reduce(function(certs, res) { + return certs.concat(res.signed.reduce(function(certs, cert) { + var blockUid = cert.meta ? cert.meta.timestamp.split('-', 2) : [null, null]; var result = { pubkey: cert.pubkey, - uid: cert.uids[0], - block: (cert.meta && cert.meta.block_number) ? cert.meta.block_number : 0, - expiresIn: expiresIn, - willExpire: (expiresIn && expiresIn <= csSettings.data.timeWarningExpire), - pending: !expiresIn, - isMember: cert.isMember + uid: cert.uid, + block: blockUid[0], + hash: blockUid[1], + isMember: cert.isMember, + wasMember: cert.wasMember }; - if (result.pending && !identity.hasPendingCertifications) { - identity.hasPendingCertifications = true; - } if (!certPubkeys[cert.pubkey]) { certPubkeys[cert.pubkey] = result; } @@ -147,120 +197,113 @@ angular.module('cesium.wot.services', ['ngResource', 'ngApi', 'cesium.bma.servic } return certs.concat(result); }, certs)); - }, certs)); - }, []); - identity.certifications = _.sortBy(certifications, function(cert){ - var score = 1; - score += (1000000000000 * (cert.expiresIn ? cert.expiresIn : 0)); - score += (10000000 * (cert.isMember ? 1 : 0)); - score += (10 * (cert.block ? cert.block : 0)); - return -score; - }); - identity.certificationCount = requirements.certificationCount; - identity.isMember = requirements.isMember; - delete requirements.certifications; - delete requirements.certificationCount; - - // Store given certs - certPubkeys = []; - var givenCertifications = !res.results ? [] : res.results.reduce(function(certs, res) { - return certs.concat(res.signed.reduce(function(certs, cert) { - if (!certPubkeys[cert.pubkey]) { // skip duplicated certs - certPubkeys[cert.pubkey] = true; - var blockUid = cert.meta ? cert.meta.timestamp.split('-', 2) : [null, null]; - return certs.concat({ - pubkey: cert.pubkey, - uid: cert.uid, - block: blockUid[0], - hash: blockUid[1], - isMember: cert.isMember, - wasMember: cert.wasMember + }, []); + identity.temp = { + givenCertifications: givenCertifications // will be used in loadGivenCertifications() + }; + identity.sigQty = parameters.sigQty; + identity.sigStock = parameters.sigStock; + + var blocks = [identity.number].concat(_.keys(pendingCertBlocks)); + + // Retrieve block time, from number + return BMA.blockchain.blocks(_.uniq(blocks)).then(function(blocks){ + _.forEach(blocks, function(block){ + // Retrieve self time + if (identity.number && block.number === identity.number) { + identity.sigDate = block.time; + + // Check if self has been done on a valid block + if (!identity.isMember && identity.number !== 0 && identity.hash !== block.hash) { + addEvent(identity, {type: 'error', message: 'ERROR.IDENTITY_INVALID_BLOCK_HASH'}); + console.debug("Invalid membership for uid={0}: block hash not match a real block (block cancelled)".format(identity.uid)); + } + } + + // Set time of pending certs + _.forEach(pendingCertBlocks[block.number], function(cert) { + cert.time = block.medianTime; + cert.expiresIn = Math.max(0, cert.time + parameters.sigWindow - medianTime); + cert.valid = (cert.expiresIn > 0); }); + }); + + resolve(identity); + }) + .catch(function(err){ + // Special case for currency init (root block not exists): use now + if (err && err.ucode == BMA.errorCodes.BLOCK_NOT_FOUND && identity.number === '0') { + identity.sigDate = Math.trunc(new Date().getTime() / 1000); + resolve(identity); } - return certs; - }, certs)); - }, []); - identity.temp = { - givenCertifications: givenCertifications - }; - identity.sigQty = parameters.sigQty; - identity.sigStockMax = parameters.sigStock; - - // Retrieve registration date - return BMA.blockchain.block({block: identity.number}) - .then(function(block) { - identity.sigDate = block.time; - - // Check if self has been done on a valid block - if (!identity.isMember && identity.number !== 0 && identity.hash !== block.hash) { - addEvent(identity, {type: 'error', message: 'ERROR.IDENTITY_INVALID_BLOCK_HASH'}); - console.debug("Invalid membership for uid={0}: block hash not match a real block (block cancelled)".format(identity.uid)); - } - resolve(identity); + else { + reject(err); + } + }); }) - .catch(function(err){ - // Special case for currency init (root block not exists): use now - if (err && err.ucode == BMA.errorCodes.BLOCK_NOT_FOUND && identity.number === '0') { - identity.sigDate = Math.trunc(new Date().getTime() / 1000); + .catch(function(err) { + if (!!err && err.ucode == BMA.errorCodes.NO_MATCHING_IDENTITY) { // Identity not found (if no self) + var identity = { + uid: null, + pubkey: pubkey, + hasSelf: false + }; resolve(identity); } else { reject(err); } }); - }) - .catch(function(err) { - if (!!err && err.ucode == BMA.errorCodes.NO_MATCHING_IDENTITY) { // Identity not found (if no self) - var identity = { - uid: null, - pubkey: pubkey, - hasSelf: false - }; - resolve(identity); - } - else { - reject(err); - } }); - }); - }, + }, loadGivenCertifications = function(pubkey, lookupGivenCertifications, parameters, medianTime) { return $q(function(resolve, reject) { - var lookupCertsMap = !lookupGivenCertifications ? {} : lookupGivenCertifications.reduce(function(map, cert){ - map[cert.pubkey] = cert; - return map; + var lookupCertsMap = !lookupGivenCertifications ? {} : lookupGivenCertifications.reduce(function(res, cert){ + res[cert.pubkey] = cert; + return res; }, {}); BMA.wot.certifiedBy({ pubkey: pubkey }) .then(function(res){ - var sigStock = 0; + var givenCertificationCount = 0; + var certifications = res.certifications.reduce(function(res, cert) { var certTime = cert.cert_time ? cert.cert_time.medianTime : null; - var expiresIn = (cert.written === null || certTime === null) ? 0 : (certTime + parameters.sigValidity - medianTime); + var expiresIn = (!cert.written || !certTime) ? 0 : (certTime + parameters.sigValidity - medianTime); expiresIn = (expiresIn < 0) ? 0 : expiresIn; - sigStock = (expiresIn > 0) ? sigStock+1 : sigStock; + givenCertificationCount = (expiresIn > 0) ? givenCertificationCount+1 : givenCertificationCount; delete lookupCertsMap[cert.pubkey]; - return res.concat({ - isMember: cert.isMember, - wasMember: cert.wasMember, - uid: cert.uid, + var result = { pubkey: cert.pubkey, + uid: cert.uid, time: certTime, + isMember: cert.isMember, + wasMember: cert.wasMember, expiresIn: expiresIn, - valid: (expiresIn > 0), + willExpire: (expiresIn && expiresIn <= csSettings.data.timeWarningExpire), + pending: false, block: (cert.written !== null) ? cert.written.number : (cert.cert_time ? cert.cert_time.block : null) - }); + }; + return res.concat(result); }, []); - // Add missing certs found in lookup (e.g. not written certs) - certifications = _.keys(lookupCertsMap).reduce(function(res, pubkey){ - var cert = lookupCertsMap[pubkey]; - cert.valid = false; - return res.concat(cert); - }, certifications); + // Add pending certs (found in lookup - see loadIdentity()) + var pendingCertBlocks = {}; + var pendingCertifications = _.forEach(_.values(lookupCertsMap), function(cert){ + cert.pending = true; + if (!pendingCertBlocks[cert.block]) { + pendingCertBlocks[cert.block] = [cert]; + } + else { + pendingCertBlocks[cert.block].push(cert); + } + }); + + var hasPendingGivenCertifications = pendingCertifications.length > 0; + certifications = certifications.concat(pendingCertifications); certifications = _.sortBy(certifications, function(cert){ var score = 1; @@ -270,15 +313,35 @@ angular.module('cesium.wot.services', ['ngResource', 'ngApi', 'cesium.bma.servic return -score; }); - resolve({ - sigStock: sigStock, + var result = { + givenCertificationCount: givenCertificationCount, + hasPendingGivenCertifications: hasPendingGivenCertifications, givenCertifications: certifications - }); + }; + var pendingCertBlockNumbers = _.keys(pendingCertBlocks); + if (!pendingCertBlockNumbers.length) { + resolve(result); + } + else { + // Add time to pending cert + BMA.blockchain.blocks(_.uniq(pendingCertBlockNumbers)).then(function(blocks){ + _.forEach(blocks, function(block){ + _.forEach(pendingCertBlocks[block.number], function(cert) { + cert.time = block.medianTime; + cert.expiresIn = Math.max(0, cert.time + parameters.sigWindow - medianTime); + cert.valid = (cert.expiresIn > 0); + }); + }); + + resolve(result); + }); + } }) .catch(function(err) { if (!!err && err.ucode == BMA.errorCodes.NO_MATCHING_MEMBER) { // member not found resolve({ - sigStock: 0, + givenCertificationCount: 0, + hasPendingGivenCertifications: false, givenCertifications: [] }); } @@ -289,40 +352,47 @@ angular.module('cesium.wot.services', ['ngResource', 'ngApi', 'cesium.bma.servic }); }, - loadSources = function(pubkey) { - return $q(function(resolve, reject) { - // Get transactions - BMA.tx.sources({pubkey: pubkey}) - .then(function(res){ - var sources = []; - var sourcesIndexByKey = []; - var balance = 0; - if (!!res.sources && res.sources.length > 0) { - _.forEach(res.sources, function(src) { - var srcKey = src.type+':'+src.identifier+':'+src.noffset; - src.consumed = false; - balance += (src.base > 0) ? (src.amount * Math.pow(10, src.base)) : src.amount; - sources.push(src); - sourcesIndexByKey[srcKey] = sources.length -1 ; + loadSources = function(pubkey) { + return $q(function(resolve, reject) { + // Get transactions + BMA.tx.sources({pubkey: pubkey}) + .then(function(res){ + var sources = []; + var sourcesIndexByKey = []; + var balance = 0; + if (!!res.sources && res.sources.length > 0) { + _.forEach(res.sources, function(src) { + var srcKey = src.type+':'+src.identifier+':'+src.noffset; + src.consumed = false; + balance += (src.base > 0) ? (src.amount * Math.pow(10, src.base)) : src.amount; + sources.push(src); + sourcesIndexByKey[srcKey] = sources.length -1 ; + }); + } + resolve({ + sources: sources, + sourcesIndexByKey: sourcesIndexByKey, + balance: balance }); - } - resolve({ - sources: sources, - sourcesIndexByKey: sourcesIndexByKey, - balance: balance + }) + .catch(function(err) { + reject(err); }); - }) - .catch(function(err) { - reject(err); }); - }); - }, + }, - loadData = function(pubkey, uid) { + loadData = function(pubkey, withCache, uid) { return $q(function(resolve, reject){ - var data = { - pubkey: pubkey - }; + // Check cached data + var data = withCache ? identityCache.get(pubkey) : null; + if (data) { + console.debug("[wot] Found cached identity " + pubkey.substring(0, 8)); + resolve(data); + return; + } + console.debug("[wot] Loading identity " + pubkey.substring(0, 8)); + var now = new Date().getTime(); + data = {pubkey: pubkey}; var parameters; var medianTime; @@ -355,7 +425,7 @@ angular.module('cesium.wot.services', ['ngResource', 'ngApi', 'cesium.bma.servic data.requirements = requirements; // Get identity - return loadIdentity(pubkey, requirements, parameters) + return loadIdentity(pubkey, requirements, parameters, medianTime) .then(function (identity) { angular.merge(data, identity); @@ -378,282 +448,284 @@ angular.module('cesium.wot.services', ['ngResource', 'ngApi', 'cesium.bma.servic ]); }) .then(function() { + identityCache.put(pubkey, data); // add to cache + console.debug('[wallet] Identity '+ pubkey.substring(0, 8) +' loaded in '+ (new Date().getTime()-now) +'ms'); resolve(data); }) .catch(function(err) { reject(err); }); }); - }, + }, - search = function(text) { - return $q(function(resolve, reject) { - if (!text || text.trim() !== text) { - resolve(); - } - return BMA.wot.lookup({ search: text }) - .then(function(res){ - var idtyKeys = []; - var idties = res.results.reduce(function(idties, res) { - return idties.concat(res.uids.reduce(function(uids, idty) { - var blocUid = idty.meta.timestamp.split('-', 2); - var idtyKey = idty.uid + '-' + res.pubkey; - if (!idtyKeys[idtyKey] && !idty.revoked) { - idtyKeys[idtyKey] = true; - return uids.concat({ - uid: idty.uid, - pubkey: res.pubkey, - number: blocUid[0], - hash: blocUid[1] - }); - } - return uids; - }, [])); - }, []); + search = function(text) { + return $q(function(resolve, reject) { + if (!text || text.trim() !== text) { + resolve(); + } + return BMA.wot.lookup({ search: text }) + .then(function(res){ + var idtyKeys = []; + var idties = res.results.reduce(function(idties, res) { + return idties.concat(res.uids.reduce(function(uids, idty) { + var blocUid = idty.meta.timestamp.split('-', 2); + var idtyKey = idty.uid + '-' + res.pubkey; + if (!idtyKeys[idtyKey] && !idty.revoked) { + idtyKeys[idtyKey] = true; + return uids.concat({ + uid: idty.uid, + pubkey: res.pubkey, + number: blocUid[0], + hash: blocUid[1] + }); + } + return uids; + }, [])); + }, []); - api.data.raisePromise.search(text, idties) - .then(function() { - resolve(idties); - }); - }) - .catch(function(err) { - if (err && err.ucode == BMA.errorCodes.NO_MATCHING_IDENTITY) { - var idties = []; api.data.raisePromise.search(text, idties) .then(function() { resolve(idties); }); - } - else { - reject(err); - } - }); - }); - }, - - getNewcomers = function(size) { - size = size || 20; - return BMA.blockchain.stats.newcomers() - .then(function(res) { - if (!res.result.blocks || !res.result.blocks.length) { - return null; - } - var blocks = _.sortBy(res.result.blocks, function(n){ return -n; }); - return getNewcomersRecursive(blocks, 0, 5, size) - .then(function(idties){ - if (!idties || !idties.length) { - return null; + }) + .catch(function(err) { + if (err && err.ucode == BMA.errorCodes.NO_MATCHING_IDENTITY) { + var idties = []; + api.data.raisePromise.search(text, idties) + .then(function() { + resolve(idties); + }); + } + else { + reject(err); } - idties = _sortAndLimitIdentities(idties, size); - return $q(function(resolve, reject) { - api.data.raisePromise.search(null, idties) - .then(function () { - resolve(idties); - }) - .catch(function(err){ - reject(err); - }); - }); }); }); - }, - - - getNewcomersRecursive = function(blocks, offset, size, maxResultSize) { - return $q(function(resolve, reject) { - var result = []; - var jobs = []; - _.each(blocks.slice(offset, offset+size), function(number) { - jobs.push( - BMA.blockchain.block({block: number}) - .then(function(block){ - if (!block || !block.joiners) return; - _.each(block.joiners, function(joiner){ - var parts = joiner.split(':'); - result.push({ - pubkey:parts[0], - uid: parts[parts.length-1], - memberDate: block.medianTime, - block: block.number - }); + }, + + getNewcomers = function(size) { + size = size || 20; + return BMA.blockchain.stats.newcomers() + .then(function(res) { + if (!res.result.blocks || !res.result.blocks.length) { + return null; + } + var blocks = _.sortBy(res.result.blocks, function(n){ return -n; }); + return getNewcomersRecursive(blocks, 0, 5, size) + .then(function(idties){ + if (!idties || !idties.length) { + return null; + } + idties = _sortAndLimitIdentities(idties, size); + return $q(function(resolve, reject) { + api.data.raisePromise.search(null, idties) + .then(function () { + resolve(idties); + }) + .catch(function(err){ + reject(err); + }); }); - }) - ); - }); + }); + }); + }, - $q.all(jobs) - .then(function() { - if (result.length < maxResultSize && offset < blocks.length - 1) { - $timeout(function() { - getNewcomersRecursive(blocks, offset+size, size, maxResultSize - result.length) - .then(function(res) { - resolve(result.concat(res)); - }) - .catch(function(err) { - reject(err); + + getNewcomersRecursive = function(blocks, offset, size, maxResultSize) { + return $q(function(resolve, reject) { + var result = []; + var jobs = []; + _.each(blocks.slice(offset, offset+size), function(number) { + jobs.push( + BMA.blockchain.block({block: number}) + .then(function(block){ + if (!block || !block.joiners) return; + _.each(block.joiners, function(joiner){ + var parts = joiner.split(':'); + result.push({ + pubkey:parts[0], + uid: parts[parts.length-1], + memberDate: block.medianTime, + block: block.number + }); }); - }, 1000); - } - else { - resolve(result); - } - }) - .catch(function(err){ - if (err && err.ucode === BMA.errorCodes.HTTP_LIMITATION) { - resolve(result); - } - else { - reject(err); - } + }) + ); }); - }); - }, - - getPending = function(size) { - size = size || 20; - return BMA.wot.member.pending() - .then(function(res) { - if (!res.memberships || !res.memberships.length) { - return null; - } - var idtiesByBlock = {}; - var idtiesByPubkey = {}; - var idties = []; - _.forEach(res.memberships, function(ms){ - if (ms.membership == 'IN') { - var idty = { - uid: ms.uid, - pubkey: ms.pubkey, - block: ms.blockNumber, - blockHash: ms.blockHash - }; - var otherIdtySamePubkey = idtiesByPubkey[ms.pubkey]; - if (otherIdtySamePubkey && idty.block > otherIdtySamePubkey.block) { - return; // skip - } - idtiesByPubkey[idty.pubkey] = idty; - if (!idtiesByBlock[idty.block]) { - idtiesByBlock[idty.block] = [idty]; + + $q.all(jobs) + .then(function() { + if (result.length < maxResultSize && offset < blocks.length - 1) { + $timeout(function() { + getNewcomersRecursive(blocks, offset+size, size, maxResultSize - result.length) + .then(function(res) { + resolve(result.concat(res)); + }) + .catch(function(err) { + reject(err); + }); + }, 1000); } else { - idtiesByBlock[idty.block].push(idty); + resolve(result); } - - // Remove previous idty from maps - if (otherIdtySamePubkey) { - idtiesByBlock[otherIdtySamePubkey.block] = idtiesByBlock[otherIdtySamePubkey.block].reduce(function(res, aidty){ - if (aidty.pubkey == otherIdtySamePubkey.pubkey) return res; // if match idty to remove, to NOT add - return (res||[]).concat(aidty); - }, null); - if (idtiesByBlock[otherIdtySamePubkey.block] === null) { - delete idtiesByBlock[otherIdtySamePubkey.block]; - } - return; + }) + .catch(function(err){ + if (err && err.ucode === BMA.errorCodes.HTTP_LIMITATION) { + resolve(result); } else { - idties.push(idty); + reject(err); } - } - }); - idties = _sortAndLimitIdentities(idtiesByPubkey, size); + }); + }); + }, - return BMA.blockchain.blocks(_.keys(idtiesByBlock)) - .then(function(blocks) { + getPending = function(size) { + size = size || 20; + return BMA.wot.member.pending() + .then(function(res) { + if (!res.memberships || !res.memberships.length) { + return null; + } + var idtiesByBlock = {}; + var idtiesByPubkey = {}; + var idties = []; + _.forEach(res.memberships, function(ms){ + if (ms.membership == 'IN') { + var idty = { + uid: ms.uid, + pubkey: ms.pubkey, + block: ms.blockNumber, + blockHash: ms.blockHash + }; + var otherIdtySamePubkey = idtiesByPubkey[ms.pubkey]; + if (otherIdtySamePubkey && idty.block > otherIdtySamePubkey.block) { + return; // skip + } + idtiesByPubkey[idty.pubkey] = idty; + if (!idtiesByBlock[idty.block]) { + idtiesByBlock[idty.block] = [idty]; + } + else { + idtiesByBlock[idty.block].push(idty); + } - _.forEach(blocks, function(block){ - _.forEach(idtiesByBlock[block.number], function(idty) { - idty.sigDate = block.medianTime; - if (block.number !== 0 && idty.blockHash !== block.hash) { - addEvent(idty, {type:'error', message: 'ERROR.WOT_PENDING_INVALID_BLOCK_HASH'}); - console.debug("Invalid membership for uid={0}: block hash not match a real block (block cancelled)".format(idty.uid)); + // Remove previous idty from maps + if (otherIdtySamePubkey) { + idtiesByBlock[otherIdtySamePubkey.block] = idtiesByBlock[otherIdtySamePubkey.block].reduce(function(res, aidty){ + if (aidty.pubkey == otherIdtySamePubkey.pubkey) return res; // if match idty to remove, to NOT add + return (res||[]).concat(aidty); + }, null); + if (idtiesByBlock[otherIdtySamePubkey.block] === null) { + delete idtiesByBlock[otherIdtySamePubkey.block]; } - }); - }); - return $q(function(resolve, reject) { - api.data.raisePromise.search(null, idties) - .then(function () { - resolve(idties); - }) - .catch(function(err){ - reject(err); - }); - }); + return; + } + else { + idties.push(idty); + } + } }); - }); - }, - - getAll = function() { - var letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','u','v','w','x','y','z']; - return getAllRecursive(letters, 0, BMA.constants.LIMIT_REQUEST_COUNT); - }, - - getAllRecursive = function(letters, offset, size) { - return $q(function(resolve, reject) { - var result = []; - var pubkeys = {}; - var jobs = []; - _.each(letters.slice(offset, offset+size), function(letter) { - jobs.push( - search(letter) - .then(function(idties){ - if (!idties || !idties.length) return; - result = idties.reduce(function(res, idty) { - if (!pubkeys[idty.pubkey]) { - pubkeys[idty.pubkey] = true; - return res.concat(idty); - } - return res; - }, result); - }) - ); - }); + idties = _sortAndLimitIdentities(idtiesByPubkey, size); - $q.all(jobs) - .then(function() { - if (offset < letters.length - 1) { - $timeout(function() { - getAllRecursive(letters, offset+size, size) - .then(function(idties) { - if (!idties || !idties.length) { - resolve(result); - return; + return BMA.blockchain.blocks(_.keys(idtiesByBlock)) + .then(function(blocks) { + + _.forEach(blocks, function(block){ + _.forEach(idtiesByBlock[block.number], function(idty) { + idty.sigDate = block.medianTime; + if (block.number !== 0 && idty.blockHash !== block.hash) { + addEvent(idty, {type:'error', message: 'ERROR.WOT_PENDING_INVALID_BLOCK_HASH'}); + console.debug("Invalid membership for uid={0}: block hash not match a real block (block cancelled)".format(idty.uid)); } - resolve(idties.reduce(function(res, idty) { - if (!pubkeys[idty.pubkey]) { - pubkeys[idty.pubkey] = true; - return res.concat(idty); - } - return res; - }, result)); - }) - .catch(function(err) { - reject(err); }); - }, BMA.constants.LIMIT_REQUEST_DELAY); - } - else { - resolve(result); - } - }) - .catch(function(err){ - if (err && err.ucode === BMA.errorCodes.HTTP_LIMITATION) { - resolve(result); - } - else { - reject(err); - } + }); + return $q(function(resolve, reject) { + api.data.raisePromise.search(null, idties) + .then(function () { + resolve(idties); + }) + .catch(function(err){ + reject(err); + }); + }); + }); }); - }); - }, - - addEvent = function(data, event) { - event = event || {}; - event.type = event.type || 'info'; - event.message = event.message || ''; - event.messageParams = event.messageParams || {}; - data.events = data.events || []; - data.events.push(event); - } + }, + + getAll = function() { + var letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','u','v','w','x','y','z']; + return getAllRecursive(letters, 0, BMA.constants.LIMIT_REQUEST_COUNT); + }, + + getAllRecursive = function(letters, offset, size) { + return $q(function(resolve, reject) { + var result = []; + var pubkeys = {}; + var jobs = []; + _.each(letters.slice(offset, offset+size), function(letter) { + jobs.push( + search(letter) + .then(function(idties){ + if (!idties || !idties.length) return; + result = idties.reduce(function(res, idty) { + if (!pubkeys[idty.pubkey]) { + pubkeys[idty.pubkey] = true; + return res.concat(idty); + } + return res; + }, result); + }) + ); + }); + + $q.all(jobs) + .then(function() { + if (offset < letters.length - 1) { + $timeout(function() { + getAllRecursive(letters, offset+size, size) + .then(function(idties) { + if (!idties || !idties.length) { + resolve(result); + return; + } + resolve(idties.reduce(function(res, idty) { + if (!pubkeys[idty.pubkey]) { + pubkeys[idty.pubkey] = true; + return res.concat(idty); + } + return res; + }, result)); + }) + .catch(function(err) { + reject(err); + }); + }, BMA.constants.LIMIT_REQUEST_DELAY); + } + else { + resolve(result); + } + }) + .catch(function(err){ + if (err && err.ucode === BMA.errorCodes.HTTP_LIMITATION) { + resolve(result); + } + else { + reject(err); + } + }); + }); + }, + + addEvent = function(data, event) { + event = event || {}; + event.type = event.type || 'info'; + event.message = event.message || ''; + event.messageParams = event.messageParams || {}; + data.events = data.events || []; + data.events.push(event); + } ; // Register extension points @@ -672,8 +744,8 @@ angular.module('cesium.wot.services', ['ngResource', 'ngApi', 'cesium.bma.servic }; }; - var service = WotService('default'); + var service = factory('default'); - service.instance = WotService; + service.instance = factory; return service; }); diff --git a/www/plugins/es/i18n/locale-fr-FR.json b/www/plugins/es/i18n/locale-fr-FR.json index a53b4702326fbae807327bec83de62dea3b976ed..bef80391654b276d33a7c0b7ba57793c9c0f8d1b 100644 --- a/www/plugins/es/i18n/locale-fr-FR.json +++ b/www/plugins/es/i18n/locale-fr-FR.json @@ -197,8 +197,8 @@ }, "PROFILE": { "UID": "Pseudonyme", - "TITLE": "Nom", - "TITLE_HELP": "Nom", + "TITLE": "Nom, Prénom", + "TITLE_HELP": "Nom, Prénom", "DESCRIPTION": "A propos de moi", "DESCRIPTION_HELP": "A propos de moi...", "ADDRESS": "Rue", diff --git a/www/plugins/es/js/controllers/app-controllers.js b/www/plugins/es/js/controllers/app-controllers.js index 8ae31e16f6bd0bbca50cd6f2dd469ccf0554405a..7e533b8c746c6eb7945660b8e96938cee4cf9cc0 100644 --- a/www/plugins/es/js/controllers/app-controllers.js +++ b/www/plugins/es/js/controllers/app-controllers.js @@ -113,11 +113,11 @@ function ESMenuExtendController($scope, $state, PluginService, csSettings,UIUtil /** * Control profile popover extension */ -function ESProfilePopoverExtendController($scope, $state, csSettings, Wallet) { +function ESProfilePopoverExtendController($scope, $state, csSettings, csWallet) { 'ngInject'; $scope.updateView = function() { - $scope.enable = Wallet.isLogin() && ( + $scope.enable = csWallet.isLogin() && ( (csSettings.data.plugins && csSettings.data.plugins.es) ? csSettings.data.plugins.es.enable : !!csSettings.data.plugins.host); @@ -127,12 +127,12 @@ function ESProfilePopoverExtendController($scope, $state, csSettings, Wallet) { $scope.updateView(); }); - Wallet.api.data.on.login($scope, function(walletData, resolve){ + csWallet.api.data.on.login($scope, function(walletData, resolve){ $scope.updateView(); if (resolve) resolve(); }); - Wallet.api.data.on.logout($scope, function(){ + csWallet.api.data.on.logout($scope, function(){ $scope.updateView(); }); diff --git a/www/plugins/es/js/controllers/common-controllers.js b/www/plugins/es/js/controllers/common-controllers.js index 3b34327e317117527eef99b3e505675555750b08..05f7c8a27f05799cbd5b8c31d9ec977db021c4b3 100644 --- a/www/plugins/es/js/controllers/common-controllers.js +++ b/www/plugins/es/js/controllers/common-controllers.js @@ -114,7 +114,7 @@ function ESCategoryModalController($scope, UIUtils, $timeout, parameters) { -function ESCommentsController($scope, $timeout, $filter, $state, Wallet, UIUtils, esHttp, DataService) { +function ESCommentsController($scope, $timeout, $filter, $state, csWallet, UIUtils, esHttp, DataService) { 'ngInject'; $scope.maxCommentSize = 10; @@ -219,7 +219,7 @@ function ESCommentsController($scope, $timeout, $filter, $state, Wallet, UIUtils if (!comment || !comment.id) {return;} $scope.comments.splice(index, 1); - DataService.record.comment.remove(comment.id, Wallet.data.keypair) + DataService.record.comment.remove(comment.id, csWallet.data.keypair) .catch(UIUtils.onError('esMarket.ERROR.FAILED_REMOVE_COMMENT')); }; } diff --git a/www/plugins/es/js/controllers/market-controllers.js b/www/plugins/es/js/controllers/market-controllers.js index f95b0419b10cdae5f9ec6a9ef8dd2ae8454f09d9..35d26e586f91813ec4f40750fa46ed629264088f 100644 --- a/www/plugins/es/js/controllers/market-controllers.js +++ b/www/plugins/es/js/controllers/market-controllers.js @@ -417,7 +417,7 @@ function ESMarketLookupController($scope, $state, $focus, $timeout, $filter, $q, function ESMarketRecordViewController($scope, $anchorScroll, $ionicPopover, $state, $translate, $ionicHistory, $q, $timeout, $filter, - Wallet, esMarket, UIUtils, esHttp, esUser, BMA, csSettings) { + csWallet, esMarket, UIUtils, esHttp, esUser, BMA, csSettings) { 'ngInject'; $scope.formData = {}; @@ -428,7 +428,7 @@ function ESMarketRecordViewController($scope, $anchorScroll, $ionicPopover, $sta $scope.maxCommentSize = 10; $scope.loading = true; - ESCommentsController.call(this, $scope, $timeout, $filter, $state, Wallet, UIUtils, esHttp, esMarket); + ESCommentsController.call(this, $scope, $timeout, $filter, $state, csWallet, UIUtils, esHttp, esMarket); $scope.$on('$ionicView.enter', function (e, state) { if (state.stateParams && state.stateParams.id) { // Load by id @@ -467,7 +467,7 @@ function ESMarketRecordViewController($scope, $anchorScroll, $ionicPopover, $sta if (hit._source.thumbnail) { $scope.thumbnail = UIUtils.image.fromAttachment(hit._source.thumbnail); } - $scope.canEdit = $scope.formData && Wallet.isUserPubkey($scope.formData.issuer); + $scope.canEdit = $scope.formData && csWallet.isUserPubkey($scope.formData.issuer); return esUser.profile.fillAvatars([{pubkey: $scope.formData.issuer}]) .then(function(idties) { return idties[0]; diff --git a/www/plugins/es/js/controllers/message-controllers.js b/www/plugins/es/js/controllers/message-controllers.js index 073571ea7539d20a9e1830728f3fc82886b39c1c..684422e5f450428aaa9ba3aff7c52e29c5bd0e10 100644 --- a/www/plugins/es/js/controllers/message-controllers.js +++ b/www/plugins/es/js/controllers/message-controllers.js @@ -185,10 +185,10 @@ function ESMessageInboxController($scope, $rootScope, $state, $timeout, $transla } -function ESMessageComposeController($scope, $ionicHistory, Modals, UIUtils, CryptoUtils, Wallet, esHttp, esMessage) { +function ESMessageComposeController($scope, $ionicHistory, Modals, UIUtils, CryptoUtils, csWallet, esHttp, esMessage) { 'ngInject'; - ESMessageComposeModalController.call(this, $scope, Modals, UIUtils, CryptoUtils, Wallet, esHttp, esMessage); + ESMessageComposeModalController.call(this, $scope, Modals, UIUtils, CryptoUtils, csWallet, esHttp, esMessage); $scope.$on('$ionicView.enter', function(e, state) { if (!!state.stateParams && !!state.stateParams.pubkey) { @@ -227,7 +227,7 @@ function ESMessageComposeController($scope, $ionicHistory, Modals, UIUtils, Cry } -function ESMessageComposeModalController($scope, Modals, UIUtils, CryptoUtils, Wallet, esHttp, esMessage, parameters) { +function ESMessageComposeModalController($scope, Modals, UIUtils, CryptoUtils, csWallet, esHttp, esMessage, parameters) { 'ngInject'; $scope.formData = { @@ -257,7 +257,7 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, CryptoUtils, W UIUtils.loading.show(); var data = { - issuer: Wallet.data.pubkey, + issuer: csWallet.data.pubkey, recipient: $scope.formData.destPub, title: $scope.formData.title, content: $scope.formData.content, @@ -265,7 +265,7 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, CryptoUtils, W nonce: CryptoUtils.util.random_nonce() }; - esMessage.send(data, Wallet.data.keypair) + esMessage.send(data, csWallet.data.keypair) .then(function(id) { $scope.id=id; UIUtils.loading.hide(); diff --git a/www/plugins/es/js/controllers/registry-controllers.js b/www/plugins/es/js/controllers/registry-controllers.js index 52062db575f635955c19747b10a5774675b0dc3b..c458d3845bc91ccabe4c32f059e3fa80d5899b76 100644 --- a/www/plugins/es/js/controllers/registry-controllers.js +++ b/www/plugins/es/js/controllers/registry-controllers.js @@ -376,7 +376,7 @@ function ESRegistryLookupController($scope, $state, $focus, $timeout, esRegistry function ESRegistryRecordViewController($scope, $state, $q, $timeout, $ionicPopover, $ionicHistory, $translate, $anchorScroll, $filter, - Wallet, esRegistry, esUser, UIUtils, BMA, esHttp) { + csWallet, esRegistry, esUser, UIUtils, esHttp) { 'ngInject'; $scope.formData = {}; @@ -386,7 +386,7 @@ function ESRegistryRecordViewController($scope, $state, $q, $timeout, $ionicPopo $scope.canEdit = false; $scope.loading = true; - ESCommentsController.call(this, $scope, $timeout, $filter, $state, Wallet, UIUtils, esHttp, esRegistry); + ESCommentsController.call(this, $scope, $timeout, $filter, $state, csWallet, UIUtils, esHttp, esRegistry); $scope.$on('$ionicView.enter', function(e, state) { if (state.stateParams && state.stateParams.id) { // Load by id @@ -416,7 +416,7 @@ function ESRegistryRecordViewController($scope, $state, $q, $timeout, $ionicPopo else { delete $scope.thumbnail; } - $scope.canEdit = Wallet.isUserPubkey($scope.formData.issuer); + $scope.canEdit = csWallet.isUserPubkey($scope.formData.issuer); // Load avatar and name (and uid) return esUser.profile.fillAvatars([{pubkey: $scope.formData.issuer}]) diff --git a/www/plugins/es/js/services/http-services.js b/www/plugins/es/js/services/http-services.js index 9e82e99f53782a2627f759cddaaf36f513e0fb64..1a4a2ed46c1708e22ea6e4d3d6a5de4ed488a234 100644 --- a/www/plugins/es/js/services/http-services.js +++ b/www/plugins/es/js/services/http-services.js @@ -3,7 +3,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'cesium.services', 'ces /** * Elastic Search Http */ -.factory('esHttp', function($q, CryptoUtils, csHttp, $rootScope, csConfig, csSettings, Wallet) { +.factory('esHttp', function($q, CryptoUtils, csHttp, $rootScope, csConfig, csSettings, csWallet) { 'ngInject'; function factory() { @@ -27,7 +27,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'cesium.services', 'ces return function(record, params) { return $q(function(resolve, reject) { - if (!Wallet.isLogin()) { + if (!csWallet.isLogin()) { reject('Wallet must be login before sending record to ES node'); return; } var errorFct = function(err) { @@ -67,7 +67,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'cesium.services', 'ces var postHistoryDelete = csHttp.post(host, node, '/history/delete'); return function(id) { return $q(function(resolve, reject) { - if (!Wallet.isLogin()) { + if (!csWallet.isLogin()) { reject('Wallet must be login before sending record to ES node'); return; } var errorFct = function(err) { diff --git a/www/plugins/es/js/services/message-services.js b/www/plugins/es/js/services/message-services.js index 5a7238f7fd74a3a646adf1932fc70e7d5eb28331..2351bb89135c1ce4d92c0a5bbc3107dfead27aa2 100644 --- a/www/plugins/es/js/services/message-services.js +++ b/www/plugins/es/js/services/message-services.js @@ -10,7 +10,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' }) -.factory('esMessage', function($q, $rootScope, csSettings, esHttp, CryptoUtils, esUser, Wallet, BMA) { +.factory('esMessage', function($q, $rootScope, csSettings, esHttp, CryptoUtils, esUser, csWallet, BMA) { 'ngInject'; function factory(host, port) { @@ -79,7 +79,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' function getBoxKeypair(keypair) { - keypair = keypair || (Wallet.isLogin() ? Wallet.data.keypair : keypair); + keypair = keypair || (csWallet.isLogin() ? csWallet.data.keypair : keypair); if (!keypair) { throw new Error('no keypair, and user not connected.'); } @@ -87,14 +87,14 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' return keypair; } var boxKeypair = CryptoUtils.box.keypair.fromSignKeypair(keypair); - Wallet.data.keypair.boxSk = boxKeypair.boxSk; - Wallet.data.keypair.boxPk = boxKeypair.boxPk; + csWallet.data.keypair.boxSk = boxKeypair.boxSk; + csWallet.data.keypair.boxPk = boxKeypair.boxPk; console.debug("[ES] Secret box keypair successfully computed"); - return Wallet.data.keypair; + return csWallet.data.keypair; } function countNewMessages(pubkey, fromTime) { - pubkey = pubkey || (Wallet.isLogin() ? Wallet.data.pubkey : pubkey); + pubkey = pubkey || (csWallet.isLogin() ? csWallet.data.pubkey : pubkey); if (!pubkey) { throw new Error('no pubkey, and user not connected.'); } @@ -165,7 +165,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' return []; } else { - var walletPubkey = Wallet.isLogin() ? Wallet.data.pubkey : null; + var walletPubkey = csWallet.isLogin() ? csWallet.data.pubkey : null; var messages = res.hits.hits.reduce(function(result, hit) { var msg = hit._source; msg.id = hit._id; @@ -177,8 +177,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' console.debug('[ES] [message] Loading ' + messages.length + ' messages'); // Update message count - Wallet.data.messages = Wallet.data.messages || {}; - Wallet.data.messages.count = messages.length; + csWallet.data.messages = csWallet.data.messages || {}; + csWallet.data.messages.count = messages.length; return decryptMessages(messages, keypair) .then(function(){ @@ -195,7 +195,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' return; } else { - var walletPubkey = Wallet.isLogin() ? Wallet.data.pubkey : null; + var walletPubkey = csWallet.isLogin() ? csWallet.data.pubkey : null; var msg = hit._source; msg.id = hit._id; msg.pubkey = msg.issuer !== walletPubkey ? msg.issuer : msg.recipient; @@ -268,8 +268,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' return esHttp.record.remove(host, port, 'message', 'record')(id) .then(function(res) { // update message count - Wallet.data.messages = Wallet.data.messages || {}; - Wallet.data.messages.count = Wallet.data.messages.count > 0 ? Wallet.data.messages.count-1 : 0; + csWallet.data.messages = csWallet.data.messages || {}; + csWallet.data.messages.count = csWallet.data.messages.count > 0 ? csWallet.data.messages.count-1 : 0; return res; }); } @@ -286,12 +286,12 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' function addListeners() { console.debug("[ES] Enable message extension"); - // Extend Wallet.loadData() and WotService.loadData() + // Extend csWallet.loadData() listeners = [ - Wallet.api.data.on.login($rootScope, onWalletLoad, this), - //Wallet.api.data.on.load($rootScope, onWalletLoad, this), - Wallet.api.data.on.init($rootScope, onWalletInit, this), - Wallet.api.data.on.reset($rootScope, onWalletReset, this), + csWallet.api.data.on.login($rootScope, onWalletLoad, this), + //csWallet.api.data.on.load($rootScope, onWalletLoad, this), + csWallet.api.data.on.init($rootScope, onWalletInit, this), + csWallet.api.data.on.reset($rootScope, onWalletReset, this), ]; } @@ -314,8 +314,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' // Listen for settings changed csSettings.api.data.on.changed($rootScope, function(){ refreshListeners(); - if (isEnable() && !Wallet.data.messages) { - onWalletLoad(Wallet.data); + if (isEnable() && !csWallet.data.messages) { + onWalletLoad(csWallet.data); } }); diff --git a/www/plugins/es/js/services/user-services.js b/www/plugins/es/js/services/user-services.js index 7d44d48194e3c1a60b70f558c90750566ab80084..bdcb48d43ed01bfdeb77a797398c427bc51c17dd 100644 --- a/www/plugins/es/js/services/user-services.js +++ b/www/plugins/es/js/services/user-services.js @@ -10,7 +10,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se }) -.factory('esUser', function($rootScope, $q, $timeout, esHttp, csConfig, csSettings, Wallet, WotService, UIUtils, BMA, CryptoUtils, Device) { +.factory('esUser', function($rootScope, $q, $timeout, esHttp, csConfig, csSettings, csWallet, csWot, UIUtils, BMA, CryptoUtils, Device) { 'ngInject'; function factory(host, port) { @@ -242,14 +242,14 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se // Waiting to load crypto libs if (!CryptoUtils.isLoaded()) { - console.debug('[esUser] Waiting crypto lib loading...'); + console.debug('[ES] [user] Waiting crypto lib loading...'); $timeout(function() { onWalletLogin(data, resolve, reject); }, 200); return; } - console.debug('[esUser] Loading user settings from ES node...'); + console.debug('[ES] [user] Loading user settings from ES node...'); // Load settings esHttp.get(host, port, '/user/settings/:id')({id: data.pubkey}) @@ -261,7 +261,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se var record = res._source; // Do not apply if same version if (record.time === csSettings.data.time) { - console.debug('[esUser] Local settings already up to date'); + console.debug('[ES] [user] Local settings already up to date'); resolve(data); return; } @@ -275,13 +275,13 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se angular.merge(csSettings.data, settings); restoringSettings = true; csSettings.store(); - console.debug('[esUser] Successfully loaded user settings from ES node'); + console.debug('[ES] [user] Successfully loaded user settings from ES node'); resolve(data); }); }) .catch(function(err){ if (err && err.ucode && err.ucode == 404) { - console.debug('[esUser] No user settings found in ES node...'); + console.debug('[ES] [user] No user settings found in ES node...'); resolve(data); // not found } else { @@ -291,24 +291,24 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se } function onSettingsChanged(data) { - if (!Wallet.isLogin()) return; + if (!csWallet.isLogin()) return; // Waiting to load crypto libs if (!CryptoUtils.isLoaded()) { - console.debug('[esUser] Waiting crypto lib loading...'); + console.debug('[ES] [user] Waiting crypto lib loading...'); $timeout(function() { onSettingsChanged(data); }, 200); return; } - console.debug('[esUser] Saving user settings to ES...'); + console.debug('[ES] [user] Saving user settings to ES...'); - var boxKeypair = CryptoUtils.box.keypair.fromSignKeypair(Wallet.data.keypair); + var boxKeypair = CryptoUtils.box.keypair.fromSignKeypair(csWallet.data.keypair); var nonce = CryptoUtils.util.random_nonce(); var formData = { - issuer: Wallet.data.pubkey, + issuer: csWallet.data.pubkey, nonce: CryptoUtils.util.encode_base58(nonce), time: Math.trunc(new Date().getTime() / 1000) }; @@ -330,7 +330,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se csSettings.data.time = formData.time; restoringSettings = true; csSettings.store(); - console.debug('[esUser] User settings saved in ES'); + console.debug('[ES] [user] User settings saved in ES'); }) .catch(function(err) { console.error(err); @@ -340,7 +340,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se } function removeListeners() { - console.debug("[esUser] Disable user extension"); + console.debug("[ES] [user] Disable"); _.forEach(listeners, function(remove){ remove(); @@ -349,16 +349,16 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se } function addListeners() { - console.debug("[ES] Enable user extension"); + console.debug("[ES] [user] Enable"); - // Extend Wallet.loadData() and WotService.loadData() + // Extend csWallet.loadData() and csWot.loadData() listeners = [ - Wallet.api.data.on.load($rootScope, onWalletLoad, this), - Wallet.api.data.on.finishLoad($rootScope, onWalletFinishLoad, this), - Wallet.api.data.on.reset($rootScope, onWalletReset, this), - Wallet.api.data.on.login($rootScope, onWalletLogin, this), - WotService.api.data.on.load($rootScope, onWotLoad, this), - WotService.api.data.on.search($rootScope, onWotSearch, this), + csWallet.api.data.on.load($rootScope, onWalletLoad, this), + csWallet.api.data.on.finishLoad($rootScope, onWalletFinishLoad, this), + csWallet.api.data.on.reset($rootScope, onWalletReset, this), + csWallet.api.data.on.login($rootScope, onWalletLogin, this), + csWot.api.data.on.load($rootScope, onWotLoad, this), + csWot.api.data.on.search($rootScope, onWotSearch, this), ]; } @@ -391,7 +391,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se if (!wasEnable && isEnable()) { return $q(function(resolve, reject){ - onWalletLogin(Wallet.data, resolve, reject); + onWalletLogin(csWallet.data, resolve, reject); }); } else { diff --git a/www/templates/settings/settings.html b/www/templates/settings/settings.html index 29a99a253a11ec12c5496be5b910c46db218e694..18273401f813a8fc1064d4f18d644fa58825a320 100644 --- a/www/templates/settings/settings.html +++ b/www/templates/settings/settings.html @@ -115,7 +115,7 @@ </div> <span class="item-note dark">{{getServer()}}</ng-if></span> </div> - <div class="item item-toggle dark hidden-sm hidden-xs hidden-md"> + <div class="item item-toggle dark hidden-xs hidden-sm"> <div class="input-label" ng-bind-html="'SETTINGS.EXPERT_MODE' | translate"></div> <label class="toggle toggle-royal"> <input type="checkbox" ng-model="formData.expertMode" > diff --git a/www/templates/wallet/popover_actions.html b/www/templates/wallet/popover_actions.html index ca3ea7eb7cd226b5e7ab2bac84a068b501a7df76..4818d68c007ab39784a0f55b432959c8cf05b912 100644 --- a/www/templates/wallet/popover_actions.html +++ b/www/templates/wallet/popover_actions.html @@ -6,7 +6,7 @@ <div class="list item-text-wrap"> <a class="item item-icon-left item-icon-right ink" - ng-click="setShowDetails(!showDetails)"> + ng-click="toggleShowDetails()"> <i class="icon ion-key"></i> {{'ACCOUNT.BTN_SHOW_DETAILS' | translate}} <i class="icon" diff --git a/www/templates/wot/tabs/view_certifications.html b/www/templates/wot/tabs/view_certifications.html index e1fd7a38c3530873d536095d24a0e21596e6d895..c61a8e87f2284b7f9670969de17baeb5ada017fd 100644 --- a/www/templates/wot/tabs/view_certifications.html +++ b/www/templates/wot/tabs/view_certifications.html @@ -11,8 +11,10 @@ <span class="badge" ng-class="{'badge-balanced': formData.certificationCount >= formData.sigQty, 'badge-assertive': formData.certificationCount < formData.sigQty}">{{formData.certificationCount}}</span> </div> + <!-- pending certifications --> <span class="item item-divider" ng-if="formData.hasPendingCertifications"> <span translate>WOT.CERTIFICATIONS.PENDING_LIST</span> + <div class="badge item-note" style="text-align: right !important;" translate>WOT.NOT_WRITTEN_EXPIRE_IN</div> </span> <a class="item ink" @@ -30,7 +32,8 @@ <h4 class="gray"> <i class="ion-key"></i> {{::cert.pubkey | formatPubkey}} - <span class="gray"> | {{::'WOT.SIGNED_ON_BLOCK' | translate:cert}}</span> + <span class="gray"> | {{::cert.time|formatDate}}</span> + <span class="gray" ng-if="$root.settings.expertMode"> | {{::'WOT.SIGNED_ON_BLOCK' | translate:cert}}</span> </h4> </span> <span ng-if="!cert.isMember"> @@ -42,19 +45,31 @@ </span> </h3> <h5 class="assertive">{{'WOT.NOT_MEMBER_PARENTHESIS'|translate}}</h5> - <h4 class="gray"><i class="ion-key"></i> - {{::cert.pubkey | formatPubkey}} | {{'WOT.SIGNED_ON_BLOCK' | translate}} #{{::cert.block}}</h4> + <h4 class="gray"> + <span ng-if="cert.uid"> + <i class="ion-key"></i> + {{::cert.pubkey | formatPubkey}} + </span> + <span class="gray"> | {{::cert.time|formatDate}}</span> + <span class="gray" ng-if="$root.settings.expertMode"> | {{::'WOT.SIGNED_ON_BLOCK' | translate:cert}}</span> + </h4> </span> + <div class="badge badge-stable" ng-if="cert.expiresIn"> + {{::cert.expiresIn | formatDuration}} + </div> + <div class="badge badge-assertive" ng-if="!cert.expiresIn"> + {{::'WOT.EXPIRED' | translate}} + </div> </a> + <!-- valid certifications --> <span class="item item-divider"> <span translate>WOT.CERTIFICATIONS.LIST</span> <div class="badge item-note" translate>WOT.EXPIRE_IN</div> </span> - <span class="item" ng-if="!loading && formData.certifications.length == 0"> - <h3 translate>WOT.NO_CERTIFICATIONS</h3> - </span> + <span class="item gray" ng-if="!formData.certificationCount" + translate>WOT.NO_CERTIFICATION</span> <a class="item ink" ng-repeat="cert in formData.certifications | filter: {pending: false}" @@ -69,7 +84,8 @@ <h4 class="gray"> <i class="ion-key"></i> {{::cert.pubkey | formatPubkey}} - <span class="gray"> | {{::'WOT.WRITTEN_ON_BLOCK' | translate:cert}}</span> + <span class="gray"> | {{cert.time|formatDate}}</span> + <span class="gray" ng-if="$root.settings.expertMode"> | {{::'WOT.WRITTEN_ON_BLOCK' | translate:cert}}</span> </h4> </span> <span ng-if="!cert.isMember"> @@ -82,11 +98,21 @@ {{::cert.pubkey | formatPubkey}} </h3> <h5 class="assertive">{{'WOT.NOT_MEMBER_PARENTHESIS'|translate}}</h5> - <h4 ng-if="!cert.isMember" class="gray">{{'WOT.SIGNED_ON_BLOCK' | translate}} #{{::cert.block}}</h4> + <h4 class="gray"> + <span ng-if="cert.uid"> + <i class="ion-key"></i> + {{::cert.pubkey | formatPubkey}} + </span> + <span class="gray"> | {{cert.time|formatDate}}</span> + <span class="gray" ng-if="$root.settings.expertMode"> | {{'WOT.SIGNED_ON_BLOCK' | translate:cert}}</span> + </h4> </span> - <div class="badge item-note" + <div class="badge" ng-if="cert.expiresIn" ng-class="{'badge-balanced': !cert.willExpire, 'badge-energized': cert.willExpire}"> {{::cert.expiresIn | formatDuration}} </div> + <div class="badge badge-assertive" ng-if="!cert.expiresIn"> + {{::'WOT.EXPIRED' | translate}} + </div> </a> </div> diff --git a/www/templates/wot/tabs/view_given_certifications.html b/www/templates/wot/tabs/view_given_certifications.html index 864edc42cf2d7d01dbc861e68933017efbccee95..bfd69948574ba776c6f79c3a1b3ee31a66f0e13d 100644 --- a/www/templates/wot/tabs/view_given_certifications.html +++ b/www/templates/wot/tabs/view_given_certifications.html @@ -10,24 +10,21 @@ <i class="icon ion-ribbon-a"></i> <span translate>WOT.GIVEN_CERTIFICATIONS.SENT</span> <span class="badge" - ng-class="{'badge-balanced': formData.sigStock < formData.sigStockMax, 'badge-assertive': formData.sigStock >= formData.sigStockMax}">{{formData.sigStock}} / {{formData.sigStockMax}}</span> + ng-class="{'badge-balanced': formData.givenCertificationCount < formData.sigStock, 'badge-assertive': formData.givenCertificationCount >= formData.sigStock}">{{formData.givenCertificationCount}} / {{formData.sigStock}}</span> </div> - <span class="item item-divider"> - <span translate>WOT.GIVEN_CERTIFICATIONS.LIST</span> - <div class="badge item-note" translate>WOT.EXPIRE_IN</div> - </span> - - <span class="item" ng-if="!loading && formData.givenCertifications.length == 0"> - <h3 translate>WOT.NO_CERTIFICATIONS</h3> + <!-- pending given certifications --> + <span class="item item-divider" ng-if="formData.hasPendingGivenCertifications"> + <span translate>WOT.GIVEN_CERTIFICATIONS.PENDING_LIST</span> + <div class="badge item-note" style="text-align: right !important;" translate>WOT.NOT_WRITTEN_EXPIRE_IN</div> </span> <a class="item ink" - ng-repeat="cert in formData.givenCertifications" - ui-sref="app.wot_view_identity({pubkey:cert.pubkey, uid:cert.uid})"> + ng-repeat="cert in formData.givenCertifications | filter:{pending:true}" + ui-sref="app.wot_view_identity({pubkey:cert.pubkey, uid:cert.uid})"> <span ng-if="cert.isMember"> <h3> - <i ng-if="!cert.valid" class="icon ion-clock"> </i> + <i class="icon ion-clock"> </i> <span class="positive"> <i class="icon ion-person"> </i> {{::cert.uid}} @@ -36,8 +33,8 @@ <h4 class="gray"> <i class="icon ion-key"></i> {{::cert.pubkey | formatPubkey}} - <span class="gray" ng-if="cert.valid"> | {{'WOT.WRITTEN_ON_BLOCK' | translate}} #{{::cert.block}}</span> - <span class="gray" ng-if="!cert.valid"> | {{'WOT.SIGNED_ON_BLOCK' | translate}} #{{::cert.block}}</span> + <span class="gray"> | {{cert.time|formatDate}}</span> + <span class="gray" ng-if="$root.settings.expertMode"> | {{'WOT.SIGNED_ON_BLOCK' | translate:cert}}</span> </h4> </span> <span ng-if="!cert.isMember"> @@ -46,16 +43,81 @@ <i class="ion-person"> </i> {{::cert.uid}} </span> - <i class="ion-key"></i> + <span ng-if="!cert.uid"> + <i class="ion-key"> </i> + {{::cert.pubkey | formatPubkey}} + </span> + </h3> + <h5 class="assertive">{{::'WOT.NOT_MEMBER_PARENTHESIS'|translate}}</h5> + <h4 class="gray"> + <span ng-if="cert.uid"> + <i class="ion-key"> </i> + {{::cert.pubkey | formatPubkey}} + </span> + <span class="gray"> | {{::cert.time|formatDate}}</span> + <span class="gray" ng-if="$root.settings.expertMode"> | {{::'WOT.SIGNED_ON_BLOCK' | translate:cert}}</span> + </h4> + </span> + <div class="badge badge-stable" ng-if="cert.expiresIn"> + {{::cert.expiresIn | formatDuration}} + </div> + <div class="badge badge-assertive" ng-if="!cert.expiresIn"> + {{::'WOT.EXPIRED' | translate}} + </div> + </a> + + <!-- validated given certifications --> + <span class="item item-divider"> + <span translate>WOT.GIVEN_CERTIFICATIONS.LIST</span> + <div class="badge item-note" translate>WOT.EXPIRE_IN</div> + </span> + + <span class="item gray" ng-if="!formData.givenCertificationCount" translate> + WOT.NO_GIVEN_CERTIFICATION + </span> + + <a class="item ink" + ng-repeat="cert in formData.givenCertifications | filter:{pending:false}" + ui-sref="app.wot_view_identity({pubkey:cert.pubkey, uid:cert.uid})"> + <span ng-if="cert.isMember"> + <h3 class="positive"> + <i class="icon ion-person"> </i> + {{::cert.uid}} + </h3> + <h4 class="gray"> + <i class="icon ion-key"></i> {{::cert.pubkey | formatPubkey}} + <span class="gray"> | {{::cert.time|formatDate}}</span> + <span class="gray" ng-if="$root.settings.expertMode"> | {{::'WOT.WRITTEN_ON_BLOCK' | translate:cert}}</span> + </h4> + </span> + <span ng-if="!cert.isMember"> + <h3 class="gray"> + <span ng-if="cert.uid"> + <i class="ion-person"> </i> + {{::cert.uid}} + </span> + <span ng-if="!cert.uid"> + <i class="ion-key"></i> + {{::cert.pubkey | formatPubkey}} + </span> </h3> - <h5 class="assertive">{{'WOT.NOT_MEMBER_PARENTHESIS'|translate}}</h5> - <h4 ng-if="!cert.isMember" class="gray">{{'WOT.SIGNED_ON_BLOCK' | translate}} #{{::cert.block}}</h4> + <h5 class="assertive">{{::'WOT.NOT_MEMBER_PARENTHESIS'|translate}}</h5> + <h4 class="gray"> + <span ng-if="cert.uid"> + <i class="ion-key"></i> + {{::cert.pubkey | formatPubkey}} + </span> + <span class="gray"> | {{::cert.time|formatDate}}</span> + <span class="gray" ng-if="$root.settings.expertMode"> | {{::'WOT.WRITTEN_ON_BLOCK' | translate:cert}}</span> + </h4> </span> - <div class="badge item-note" - ng-if="cert.valid" + <div class="badge" ng-if="cert.expiresIn" ng-class="{'badge-balanced': !cert.willExpire, 'badge-energized': cert.willExpire}"> {{::cert.expiresIn | formatDuration}} </div> + <div class="badge badge-assertive" ng-if="!cert.expiresIn"> + {{::'WOT.EXPIRED' | translate}} + </div> </a> </div>