diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json index b0ed74b54d04a1449d7385f7fa003b8749c66cce..b44274a295197c4da77e0ed641dc5d2746622aee 100644 --- a/www/i18n/locale-fr-FR.json +++ b/www/i18n/locale-fr-FR.json @@ -315,8 +315,8 @@ "SIGNED_ON_BLOCK": "Emise au bloc #{{block}}", "WRITTEN_ON_BLOCK": "Ecrite au bloc #{{block}}", "GENERAL_DIVIDER": "Informations générales", - "NOT_MEMBER_ACCOUNT": "Compte non membre", - "NOT_MEMBER_ACCOUNT_HELP": "Il s'agit d'une simple portefeuille, sans demande d'adhésion en attente.", + "NOT_MEMBER_ACCOUNT": "Compte simple (non membre)", + "NOT_MEMBER_ACCOUNT_HELP": "Il s'agit d'un simple portefeuille, sans demande d'adhésion en attente.", "TECHNICAL_DIVIDER": "Informations techniques", "BTN_CERTIFY": "Certifier", "BTN_YES_CERTIFY": "Oui, certifier", diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js index 91987bd83d28edc85c47c3d0599c8d1e6b9b8064..4c4729b7f868afa9b122fe34db35248f9e2a9ae0 100644 --- a/www/js/controllers/app-controllers.js +++ b/www/js/controllers/app-controllers.js @@ -66,7 +66,7 @@ function PluginExtensionPointController($scope, PluginService) { function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $timeout, $ionicHistory, $controller, $window, csPlatform, UIUtils, BMA, csWallet, Device, Modals, csConfig, csHttp - ) { +) { 'ngInject'; $scope.search = {}; @@ -91,26 +91,26 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ return; } Device.barcode.scan() - .then(function(uri) { - if (!uri) { - return; - } - BMA.uri.parse(uri) - .then(function(result){ - // If pubkey - if (result && result.pubkey) { - $state.go('app.wot_identity', { - pubkey: result.pubkey, - node: result.host ? result.host: null} - ); - } - else { - UIUtils.alert.error(result, 'ERROR.SCAN_UNKNOWN_FORMAT'); + .then(function(uri) { + if (!uri) { + return; } + BMA.uri.parse(uri) + .then(function(result){ + // If pubkey + if (result && result.pubkey) { + $state.go('app.wot_identity', { + pubkey: result.pubkey, + node: result.host ? result.host: null} + ); + } + else { + UIUtils.alert.error(result, 'ERROR.SCAN_UNKNOWN_FORMAT'); + } + }) + .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')); }) - .catch(UIUtils.onError('ERROR.SCAN_UNKNOWN_FORMAT')); - }) - .catch(UIUtils.onError('ERROR.SCAN_FAILED')); + .catch(UIUtils.onError('ERROR.SCAN_FAILED')); }; //////////////////////////////////////// @@ -141,13 +141,13 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ var helptipScope = $scope.createHelptipScope(true); return helptipScope.startHelpTour() - .then(function() { - helptipScope.$destroy(); - delete $rootScope.tour; - }) - .catch(function(err){ - delete $rootScope.tour; - }); + .then(function() { + helptipScope.$destroy(); + delete $rootScope.tour; + }) + .catch(function(err){ + delete $rootScope.tour; + }); }; //////////////////////////////////////// @@ -295,7 +295,10 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ UIUtils.loading.show(); return csWallet.logout() .then(function() { - $ionicSideMenuDelegate.toggleLeft(); + // Close left menu if open + if ($ionicSideMenuDelegate.isOpenLeft()) { + $ionicSideMenuDelegate.toggleLeft(); + } $ionicHistory.clearHistory(); return $ionicHistory.clearCache() @@ -425,7 +428,7 @@ function HomeController($scope, $state, $timeout, $ionicHistory, csPlatform, csC $scope.enter = function(e, state) { if (state && state.stateParams && state.stateParams.error) { // Query parameter $scope.error = state.stateParams.error; - $scope.node = csCurrency.data.node; + $scope.node = csCurrency.data.node; $scope.loading = false; $ionicHistory.nextViewOptions({ disableAnimate: true, @@ -474,6 +477,6 @@ function HomeController($scope, $state, $timeout, $ionicHistory, csPlatform, csC // For DEV ONLY /*$timeout(function() { - $scope.loginAndGo(); - }, 500);*/ + $scope.loginAndGo(); + }, 500);*/ } diff --git a/www/plugins/es/js/controllers/common-controllers.js b/www/plugins/es/js/controllers/common-controllers.js index 284ece732fe273c15293f1a53551c5ccffbb2a43..12d368f71a6d77c5312c34cf070e7687a6f2a3b2 100644 --- a/www/plugins/es/js/controllers/common-controllers.js +++ b/www/plugins/es/js/controllers/common-controllers.js @@ -330,7 +330,7 @@ function ESSocialsEditController($scope, $focus, $filter, UIUtils, SocialUtils) // Set Motion $scope.motion.show({ - selector: '#social-' + $filter('formatSlug')(url), + selector: '#social-' + $filter('formatSlug')(social.url), startVelocity: 10000 }); }; diff --git a/www/plugins/es/js/controllers/profile-controllers.js b/www/plugins/es/js/controllers/profile-controllers.js index 76b0bce0e3088a4747bd7abc96d407d469c419bd..1a572d1b09a37867eb565e45724dae371051067f 100644 --- a/www/plugins/es/js/controllers/profile-controllers.js +++ b/www/plugins/es/js/controllers/profile-controllers.js @@ -308,7 +308,7 @@ function ESViewEditProfileController($scope, $rootScope, $q, $timeout, $state, $ .catch(UIUtils.onError('ERROR.TAKE_PICTURE_FAILED')); } else { - return ModalUtils.show('plugins/es/templates/user/modal_edit_avatar.html','ESAvatarModalCtrl', + return ModalUtils.show('plugins/es/templates/common/modal_edit_avatar.html','ESAvatarModalCtrl', {}) .then(function(imageData) { if (!imageData) return; diff --git a/www/plugins/es/js/controllers/registry-controllers.js b/www/plugins/es/js/controllers/registry-controllers.js index fd644d2bfef85c4cda186ff0de3935ac3cf48cc7..55443387dd1fb5b801aae87d6523fba3777e84b4 100644 --- a/www/plugins/es/js/controllers/registry-controllers.js +++ b/www/plugins/es/js/controllers/registry-controllers.js @@ -897,7 +897,7 @@ function ESRegistryRecordEditController($scope, $timeout, $state, $q, $ionicHis .catch(UIUtils.onError('ERROR.TAKE_PICTURE_FAILED')); } else { - return ModalUtils.show('plugins/es/templates/user/modal_edit_avatar.html','ESAvatarModalCtrl', + return ModalUtils.show('plugins/es/templates/common/modal_edit_avatar.html','ESAvatarModalCtrl', {}) .then(function(imageData) { if (!imageData) return; diff --git a/www/plugins/es/js/controllers/wallet-controllers.js b/www/plugins/es/js/controllers/wallet-controllers.js index 276cbe2e784712177097ec84874d22e066245f23..2fc4ca2b4ad11547bea1c8acf78046e4f462f5b5 100644 --- a/www/plugins/es/js/controllers/wallet-controllers.js +++ b/www/plugins/es/js/controllers/wallet-controllers.js @@ -7,7 +7,7 @@ angular.module('cesium.es.wallet.controllers', ['cesium.es.services']) if (enable) { PluginServiceProvider.extendState('app.view_wallet', { points: { - 'before-technical': { + 'after-general': { templateUrl: "plugins/es/templates/wallet/view_wallet_extend.html", controller: 'ESWotIdentityViewCtrl' } diff --git a/www/plugins/es/js/controllers/wot-controllers.js b/www/plugins/es/js/controllers/wot-controllers.js index 0c959ff8bbddb67adfd1ffc640621059cd4676af..c71009ca59b19ca4915388f0058ba23098ecccf7 100644 --- a/www/plugins/es/js/controllers/wot-controllers.js +++ b/www/plugins/es/js/controllers/wot-controllers.js @@ -9,7 +9,7 @@ angular.module('cesium.es.wot.controllers', ['cesium.es.services']) .extendStates(['app.wot_identity', 'app.wot_identity_uid'], { points: { - 'general': { + 'after-general': { templateUrl: "plugins/es/templates/wot/view_identity_extend.html", controller: 'ESWotIdentityViewCtrl' }, diff --git a/www/plugins/es/js/services/message-services.js b/www/plugins/es/js/services/message-services.js index ea0b88247104758e9d6af4a31b79f0a76188662c..3469630d4b3830dee6319c2fc097328aa2c0a501 100644 --- a/www/plugins/es/js/services/message-services.js +++ b/www/plugins/es/js/services/message-services.js @@ -11,285 +11,281 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', }) -.factory('esMessage', function($q, $rootScope, $timeout, UIUtils, Api, CryptoUtils, - csPlatform, csConfig, csSettings, esHttp, csWallet, esWallet, csWot, esNotification) { - 'ngInject'; - - var - constants = { - DEFAULT_LOAD_SIZE: 10 - }, - fields = { - commons: ["issuer", "recipient", "title", "content", "time", "nonce", "read_signature"], - notifications: ["issuer", "time", "hash", "read_signature"] - }, - raw = { - postSearch: esHttp.post('/message/inbox/_search'), - getByTypeAndId : esHttp.get('/message/:type/:id'), - postReadById: esHttp.post('/message/inbox/:id/_read') - }, - listeners, - api = new Api(this, 'esMessage'); - - function onWalletInit(data) { - data.messages = data.messages || {}; - data.messages.unreadCount = null; - } - - function onWalletReset(data) { - if (data.messages) { - delete data.messages; + .factory('esMessage', function($q, $rootScope, $timeout, UIUtils, Api, CryptoUtils, + csPlatform, csConfig, csSettings, esHttp, csWallet, esWallet, csWot, esNotification) { + 'ngInject'; + + var + constants = { + DEFAULT_LOAD_SIZE: 10 + }, + fields = { + commons: ["issuer", "recipient", "title", "content", "time", "nonce", "read_signature"], + notifications: ["issuer", "time", "hash", "read_signature"] + }, + raw = { + postSearch: esHttp.post('/message/inbox/_search'), + getByTypeAndId : esHttp.get('/message/:type/:id'), + postReadById: esHttp.post('/message/inbox/:id/_read') + }, + listeners, + api = new Api(this, 'esMessage'); + + function onWalletInit(data) { + data.messages = data.messages || {}; + data.messages.unreadCount = null; } - } - function onWalletLogin(data, deferred) { - deferred = deferred || $q.defer(); - if (!data || !data.pubkey) { - deferred.resolve(); - return deferred.promise; + function onWalletReset(data) { + if (data.messages) { + delete data.messages; + } } - console.debug('[ES] [message] Loading count...'); - var now = new Date().getTime(); - - // Count unread messages - countUnreadMessages(data.pubkey) - .then(function(unreadCount){ - data.messages = data.messages || {}; - data.messages.unreadCount = unreadCount; - console.debug('[ES] [message] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); - deferred.resolve(data); - }) - .catch(function(err){ - console.error('Error chile counting message: ' + (err.message ? err.message : err)); - deferred.resolve(data); - }); - return deferred.promise; - } + function onWalletLogin(data, deferred) { + deferred = deferred || $q.defer(); + if (!data || !data.pubkey) { + deferred.resolve(); + return deferred.promise; + } - function countUnreadMessages(pubkey) { - pubkey = pubkey || (csWallet.isLogin() ? csWallet.data.pubkey : pubkey); - if (!pubkey) { - throw new Error('no pubkey, and user not connected.'); + console.debug('[ES] [message] Loading count...'); + var now = new Date().getTime(); + + // Count unread messages + countUnreadMessages(data.pubkey) + .then(function(unreadCount){ + data.messages = data.messages || {}; + data.messages.unreadCount = unreadCount; + console.debug('[ES] [message] Loaded count (' + unreadCount + ') in '+(new Date().getTime()-now)+'ms'); + deferred.resolve(data); + }) + .catch(function(err){ + console.error('Error chile counting message: ' + (err.message ? err.message : err)); + deferred.resolve(data); + }); + return deferred.promise; } - var request = { - query: { - bool: { - must: [ - {term: {recipient: pubkey}}, - {missing: { field : "read_signature" }} - ] - } + function countUnreadMessages(pubkey) { + pubkey = pubkey || (csWallet.isLogin() ? csWallet.data.pubkey : pubkey); + if (!pubkey) { + throw new Error('no pubkey, and user not connected.'); } - }; - return esHttp.post('/message/inbox/_count')(request) - .then(function(res) { - return res.count; - }); - } + var request = { + query: { + bool: { + must: [ + {term: {recipient: pubkey}}, + {missing: { field : "read_signature" }} + ] + } + } + }; - // Listen message changes - function onNewMessageEvent(event) { - console.debug("[ES] [message] detected new message (from notification service)"); + return esHttp.post('/message/inbox/_count')(request) + .then(function(res) { + return res.count; + }); + } - var notification = new Notification(event); - notification.issuer = notification.pubkey; - delete notification.pubkey; + // Listen message changes + function onNewMessageEvent(event) { + console.debug("[ES] [message] detected new message (from notification service)"); - csWot.extend(notification, 'issuer') - .then(function() { + var notification = new Notification(event); + notification.issuer = notification.pubkey; + delete notification.pubkey; - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount++; + csWot.extend(notification, 'issuer') + .then(function() { - // Raise event - api.data.raise.new(notification); - }); - } + csWallet.data.messages = csWallet.data.messages || {}; + csWallet.data.messages.unreadCount++; + + // Raise event + api.data.raise.new(notification); + }); + } - function sendMessage(message, keypair) { - return doSendMessage(message, keypair) - .then(function(res){ - var outbox = (csSettings.data.plugins.es.message && + function sendMessage(message, keypair) { + return doSendMessage(message, keypair) + .then(function(res){ + var outbox = (csSettings.data.plugins.es.message && angular.isDefined(csSettings.data.plugins.es.message.outbox)) ? - csSettings.data.plugins.es.message.outbox : true; - - if (!outbox) return res; - - // Send to outbox - return doSendMessage(message, keypair, '/message/outbox', 'issuer') - .catch(function(err) { - console.error("Failed to store message to outbox: " + err); - return res; // the first result - }); - }) - .then(function(res) { - // Raise event - api.data.raise.sent(res); - - return res; - }); - } + csSettings.data.plugins.es.message.outbox : true; + + if (!outbox) return res; + + // Send to outbox + return doSendMessage(message, keypair, '/message/outbox', 'issuer') + .catch(function(err) { + console.error("Failed to store message to outbox: " + err); + return res; // the first result + }); + }) + .then(function(res) { + // Raise event + api.data.raise.sent(res); + + return res; + }); + } - function doSendMessage(message, keypair, boxPath, recipientFieldName) { - boxPath = boxPath || '/message/inbox'; + function doSendMessage(message, keypair, boxPath, recipientFieldName) { + boxPath = boxPath || '/message/inbox'; - // Encrypt fields - return esWallet.box.record.pack(message, keypair, recipientFieldName, ['title', 'content']) + // Encrypt fields + return esWallet.box.record.pack(message, keypair, recipientFieldName, ['title', 'content']) // Send message - .then(function(message){ - return esHttp.record.post(boxPath)(message); - }); - } + .then(function(message){ + return esHttp.record.post(boxPath)(message); + }); + } - function loadMessageNotifications(options) { - if (!csWallet.isLogin()) { - return $q.when([]); // Should never happen + function loadMessageNotifications(options) { + if (!csWallet.isLogin()) { + return $q.when([]); // Should never happen + } + options = options || {}; + options.from = options.from || 0; + options.size = options.size || constants.DEFAULT_LOAD_SIZE; + var request = { + sort: { + "time" : "desc" + }, + query: {bool: {filter: {term: {recipient: csWallet.data.pubkey}}}}, + from: options.from, + size: options.size, + _source: fields.notifications + }; + + return raw.postSearch(request) + .then(function(res) { + if (!res || !res.hits || !res.hits.total) return []; + var notifications = res.hits.hits.reduce(function(result, hit) { + var msg = hit._source; + msg.id = hit._id; + msg.read = !!msg.read_signature; + delete msg.read_signature; // not need anymore + return result.concat(msg); + }, []); + return csWot.extendAll(notifications, 'issuer'); + }); } - options = options || {}; - options.from = options.from || 0; - options.size = options.size || constants.DEFAULT_LOAD_SIZE; - var request = { - sort: { - "time" : "desc" - }, - query: {bool: {filter: {term: {recipient: csWallet.data.pubkey}}}}, - from: options.from, - size: options.size, - _source: fields.notifications - }; - return raw.postSearch(request) - .then(function(res) { - if (!res || !res.hits || !res.hits.total) return []; - var notifications = res.hits.hits.reduce(function(result, hit) { - var msg = hit._source; - msg.id = hit._id; - msg.read = !!msg.read_signature; - delete msg.read_signature; // not need anymore - return result.concat(msg); - }, []); - return csWot.extendAll(notifications, 'issuer'); - }); - } + function searchMessages(pubkey, options) { + pubkey = pubkey || csWallet.data.pubkey; + + options = options || {}; + options.type = options.type || 'inbox'; + options.from = options.from || 0; + options.size = options.size || 1000; + options._source = options._source || fields.commons; + var request = { + sort: { + "time" : "desc" + }, + from: options.from, + size: options.size, + _source: options._source + }; + + if (options.type == 'inbox') { + request.query = {bool: {filter: {term: {recipient: pubkey}}}}; + } + else { + request.query = {bool: {filter: {term: {issuer: pubkey}}}}; + } - function searchMessages(pubkey, options) { - pubkey = pubkey || csWallet.data.pubkey; + return esHttp.post('/message/:type/_search')(request, {type: options.type}) + .then(function(res) { + if (!res || !res.hits || !res.hits.total) { + return []; + } + var messages = res.hits.hits.reduce(function(res, hit) { + var msg = hit._source || {}; + msg.id = hit._id; + msg.read = (options.type == 'outbox') || !!msg.read_signature; + delete msg.read_signature; // not need anymore + return res.concat(msg); + }, []); - options = options || {}; - options.type = options.type || 'inbox'; - options.from = options.from || 0; - options.size = options.size || 1000; - options._source = options._source || fields.commons; - var request = { - sort: { - "time" : "desc" - }, - from: options.from, - size: options.size, - _source: options._source - }; + console.debug('[ES] [message] Loading {0} {1} messages'.format(messages.length, options.type)); - if (options.type == 'inbox') { - request.query = {bool: {filter: {term: {recipient: pubkey}}}}; - } - else { - request.query = {bool: {filter: {term: {issuer: pubkey}}}}; + return messages; + }); } - return esHttp.post('/message/:type/_search')(request, {type: options.type}) - .then(function(res) { - if (!res || !res.hits || !res.hits.total) { - return []; - } - var messages = res.hits.hits.reduce(function(res, hit) { - var msg = hit._source || {}; - msg.id = hit._id; - msg.read = (options.type == 'outbox') || !!msg.read_signature; - delete msg.read_signature; // not need anymore - return res.concat(msg); - }, []); - - console.debug('[ES] [message] Loading {0} {1} messages'.format(messages.length, options.type)); - - return messages; - }); - } + function loadMessages(options) { + options = options || {}; + options.type = options.type || 'inbox'; + options._source = fields.commons; + options.summary = angular.isDefined(options.summary) ? options.summary : true; - function loadMessages(options) { - options = options || {}; - options.type = options.type || 'inbox'; - options._source = fields.commons; - options.summary = angular.isDefined(options.summary) ? options.summary : true; + return csWallet.auth() + .then(function(walletData) { - return csWallet.auth() - .then(function(walletData) { - - // Get encrypted message (with common fields) - return searchMessages(walletData.pubkey, options) + // Get encrypted message (with common fields) + return searchMessages(walletData.pubkey, options) // Decrypt content - .then(function(messages) { - return decryptMessages(messages, walletData.keypair, options.summary); - }); - }) - - // Add avatar - .then(function(messages){ - var avatarField = (options.type == 'inbox') ? 'issuer' : 'recipient'; - return csWot.extendAll(messages, avatarField); - }) - - // Update message count - .then(function(messages){ - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = messages.length; - - return messages; - }); - } + .then(function(messages) { + return decryptMessages(messages, walletData.keypair, options.summary); + }); + }) + + // Add avatar + .then(function(messages){ + var avatarField = (options.type == 'inbox') ? 'issuer' : 'recipient'; + return csWot.extendAll(messages, avatarField); + }) + + // Update message count + .then(function(messages){ + csWallet.data.messages = csWallet.data.messages || {}; + csWallet.data.messages.count = messages.length; - function getAndDecrypt(id, options) { + return messages; + }); + } - options = options || {}; - options.type = options.type || 'inbox'; - options.summary = angular.isDefined(options.summary) ? options.summary : false/*summary not need by default*/; + function getAndDecrypt(id, options) { + options = options || {}; + options.type = options.type || 'inbox'; + options.summary = angular.isDefined(options.summary) ? options.summary : false/*summary not need by default*/; - return csWallet.auth() - .then(function(walletData) { - return raw.getByTypeAndId({id: id, type: options.type}) - .then(function(hit) { - if (!hit.found) { - return; - } - var msg = hit._source; - msg.id = hit._id; - msg.read = (options.type == 'outbox') || !!msg.read_signature; - delete msg.read_signature; // not need anymore + return csWallet.auth() + .then(function(walletData) { + return raw.getByTypeAndId({id: id, type: options.type}) + .then(function(hit) { + if (!hit.found) return; + var msg = hit._source; + msg.id = hit._id; + msg.read = (options.type == 'outbox') || !!msg.read_signature; + delete msg.read_signature; // not need anymore - // Decrypt message - return decryptMessages([msg], walletData.keypair, options.summary) + // Decrypt message + return decryptMessages([msg], walletData.keypair, options.summary) // Add avatar - .then(function(){ - var avatarField = (options.type == 'inbox') ? 'issuer' : 'recipient'; - return csWot.extend(msg, avatarField); - }); - }); - }); - - } + .then(function(){ + var avatarField = (options.type == 'inbox') ? 'issuer' : 'recipient'; + return csWot.extend(msg, avatarField); + }); + }); + }); + } - function decryptMessages(messages, keypair, withSummary) { + function decryptMessages(messages, keypair, withSummary) { - var now = new Date().getTime(); - var issuerBoxPks = {}; // a map used as cache + var now = new Date().getTime(); + var issuerBoxPks = {}; // a map used as cache - var jobs = [esWallet.box.getKeypair(keypair)]; - return $q.all(messages.reduce(function(jobs, message) { + var jobs = [esWallet.box.getKeypair(keypair)]; + return $q.all(messages.reduce(function(jobs, message) { if (issuerBoxPks[message.issuer]) return res; return jobs.concat( CryptoUtils.box.keypair.pkFromSignPk(CryptoUtils.util.decode_base58(message.issuer)) @@ -297,267 +293,267 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform', issuerBoxPks[message.issuer] = issuerBoxPk; // fill box pk cache })); }, jobs)) - .then(function(res){ - var boxKeypair = res[0]; - return $q.all(messages.reduce(function(jobs, message) { - var issuerBoxPk = issuerBoxPks[message.issuer]; - var nonce = CryptoUtils.util.decode_base58(message.nonce); - message.valid = true; - - return jobs.concat( - // title - CryptoUtils.box.open(message.title, nonce, issuerBoxPk, boxKeypair.boxSk) - .then(function(title) { - message.title = title; - }) - .catch(function(err){ - console.error(err); - console.warn('[ES] [message] may have invalid cypher title'); - message.valid = false; - }), - - // content - CryptoUtils.box.open(message.content, nonce, issuerBoxPk, boxKeypair.boxSk) - .then(function(content) { - message.content = content; - if (withSummary) { - fillSummary(message); - } - else if (content){ - message.html = esHttp.util.parseAsHtml(content); - } - }) - .catch(function(err){ - console.error(err); - console.warn('[ES] [message] may have invalid cypher content'); - message.valid = false; - }) + .then(function(res){ + var boxKeypair = res[0]; + return $q.all(messages.reduce(function(jobs, message) { + var issuerBoxPk = issuerBoxPks[message.issuer]; + var nonce = CryptoUtils.util.decode_base58(message.nonce); + message.valid = true; + + return jobs.concat( + // title + CryptoUtils.box.open(message.title, nonce, issuerBoxPk, boxKeypair.boxSk) + .then(function(title) { + message.title = title; + }) + .catch(function(err){ + console.error(err); + console.warn('[ES] [message] may have invalid cypher title'); + message.valid = false; + }), + + // content + CryptoUtils.box.open(message.content, nonce, issuerBoxPk, boxKeypair.boxSk) + .then(function(content) { + message.content = content; + if (withSummary) { + fillSummary(message); + } + else if (content){ + message.html = esHttp.util.parseAsHtml(content); + } + }) + .catch(function(err){ + console.error(err); + console.warn('[ES] [message] may have invalid cypher content'); + message.valid = false; + }) ); }, [])); - }) - .then(function() { - console.debug('[ES] [message] All messages decrypted in ' + (new Date().getTime() - now) + 'ms'); - return messages; - }); + }) + .then(function() { + console.debug('[ES] [message] All messages decrypted in ' + (new Date().getTime() - now) + 'ms'); + return messages; + }); - } + } - // Compute a summary (truncated to 140 characters), from the message content - function fillSummary(message) { - if (message.content) { - message.summary = message.content.replace(/(^|[\n\r]+)\s*>[^\n\r]*/g, '').trim(); - if (message.summary.length > 140) { - message.summary = message.summary.substr(0, 137) + '...'; + // Compute a summary (truncated to 140 characters), from the message content + function fillSummary(message) { + if (message.content) { + message.summary = message.content.replace(/(^|[\n\r]+)\s*>[^\n\r]*/g, '').trim(); + if (message.summary.length > 140) { + message.summary = message.summary.substr(0, 137) + '...'; + } } } - } - - function removeMessage(id, type) { - type = type || 'inbox'; - return esHttp.record.remove('message', type)(id) - .then(function(res) { - // update message count - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = csWallet.data.messages.count > 0 ? csWallet.data.messages.count-1 : 0; - } - // Raise event - api.data.raise.delete(id); - return res; - }); - } - - function removeAllMessages(type) { - type = type || 'inbox'; - - return csWallet.auth() - .then(function(walletData) { - // Get all message id - return searchMessages(walletData.pubkey, {type: type, from: 0, size: 1000, _source: false}) - .then(function (res) { - if (!res || !res.length) return; - - var ids = _.pluck(res, 'id'); - - // Remove each messages - return $q.all(res.reduce(function (res, msg) { - return res.concat(esHttp.record.remove('message', type)(msg.id, walletData)); - }, [])) - .then(function() { - return ids; - }); - }) - .then(function (ids) { - // update message count - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.count = 0; - csWallet.data.messages.unreadCount = 0; - } + function removeMessage(id, type) { + type = type || 'inbox'; + return esHttp.record.remove('message', type)(id) + .then(function(res) { + // update message count + if (type == 'inbox') { + csWallet.data.messages = csWallet.data.messages || {}; + csWallet.data.messages.count = csWallet.data.messages.count > 0 ? csWallet.data.messages.count-1 : 0; + } + // Raise event + api.data.raise.delete(id); - // Raise events - _.forEach(ids, api.data.raise.delete); - }); - }); - } - - // Mark a message as read - function markMessageAsRead(message, type) { - type = type || 'inbox'; - if (message.read) { - var deferred = $q.defer(); - deferred.resolve(); - return deferred.promise; + return res; + }); } - message.read = true; - return csWallet.getKeypair() + function removeAllMessages(type) { + type = type || 'inbox'; + + return csWallet.auth() + .then(function(walletData) { + // Get all message id + return searchMessages(walletData.pubkey, {type: type, from: 0, size: 1000, _source: false}) + .then(function (res) { + if (!res || !res.length) return; + + var ids = _.pluck(res, 'id'); + + // Remove each messages + return $q.all(res.reduce(function (res, msg) { + return res.concat(esHttp.record.remove('message', type)(msg.id, walletData)); + }, [])) + .then(function() { + return ids; + }); + }) + .then(function (ids) { + // update message count + if (type == 'inbox') { + csWallet.data.messages = csWallet.data.messages || {}; + csWallet.data.messages.count = 0; + csWallet.data.messages.unreadCount = 0; + } + + // Raise events + _.forEach(ids, api.data.raise.delete); + }); + }); + } + + // Mark a message as read + function markMessageAsRead(message, type) { + type = type || 'inbox'; + if (message.read) { + var deferred = $q.defer(); + deferred.resolve(); + return deferred.promise; + } + message.read = true; + + return csWallet.getKeypair() // Prepare the read_signature to sent - .then(function(keypair) { - return CryptoUtils.sign(message.hash, keypair); - }) - - // Send read request - .then(function(signature){ - return raw.postReadById(signature, {id:message.id}); - }) - - // Update message count - .then(function() { - if (type == 'inbox') { - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount = csWallet.data.messages.unreadCount ? csWallet.data.messages.unreadCount - 1 : 0; - } - }); - } + .then(function(keypair) { + return CryptoUtils.sign(message.hash, keypair); + }) + + // Send read request + .then(function(signature){ + return raw.postReadById(signature, {id:message.id}); + }) + + // Update message count + .then(function() { + if (type == 'inbox') { + csWallet.data.messages = csWallet.data.messages || {}; + csWallet.data.messages.unreadCount = csWallet.data.messages.unreadCount ? csWallet.data.messages.unreadCount - 1 : 0; + } + }); + } - // Mark all messages as read - function markAllMessageAsRead() { - return csWallet.auth() - .then(function(walletData) { + // Mark all messages as read + function markAllMessageAsRead() { + return csWallet.auth() + .then(function(walletData) { - // Get all messages hash - return searchMessages(walletData.pubkey, { + // Get all messages hash + return searchMessages(walletData.pubkey, { type: 'inbox', from: 0, size: 1000, _source: ['hash', 'read_signature'] }) - .then(function (messages) { - if (!messages || !messages.length) return; + .then(function (messages) { + if (!messages || !messages.length) return; - // Keep only unread message - messages = _.filter(messages, {read: false}); + // Keep only unread message + messages = _.filter(messages, {read: false}); - // Remove messages - return $q.all(messages.reduce(function (res, message) { - return res.concat( - // Sign hash - CryptoUtils.sign(message.hash, walletData.keypair) + // Remove messages + return $q.all(messages.reduce(function (res, message) { + return res.concat( + // Sign hash + CryptoUtils.sign(message.hash, walletData.keypair) // then send read request - .then(function (signature) { - return raw.postReadById(signature, {id: message.id}); - })); - }, [])); - }) - .then(function () { - // update message count - csWallet.data.messages = csWallet.data.messages || {}; - csWallet.data.messages.unreadCount = 0; - }); - }); - } - - // Send message to developers - need for issue #524 - function onSendError(message) { - var developers = csConfig.developers || [{pubkey: '38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE'/*kimamila*/}]; - if(!message || !message.content || !developers || !developers.length) return; - - console.info("[ES] [message] Sending logs to developers..."); - message.issuer = csWallet.data.pubkey; - message.title = message.title || 'Sending log'; - message.time = esHttp.date.now(); - - csWallet.getKeypair() - .then(function(keypair) { - return $q.all(developers.reduce(function(res, developer){ - return !developer.pubkey ? res : - res.concat(sendMessage(angular.merge({recipient: developer.pubkey}, message), keypair)); - }, [])); - }) - .then(function(res) { - console.info("[ES] [message] Logs sent to {0} developers".format(res.length)); + .then(function (signature) { + return raw.postReadById(signature, {id: message.id}); + })); + }, [])); + }) + .then(function () { + // update message count + csWallet.data.messages = csWallet.data.messages || {}; + csWallet.data.messages.unreadCount = 0; + }); + }); + } + + // Send message to developers - need for issue #524 + function onSendError(message) { + var developers = csConfig.developers || [{pubkey: '38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE'/*kimamila*/}]; + if(!message || !message.content || !developers || !developers.length) return; + + console.info("[ES] [message] Sending logs to developers..."); + message.issuer = csWallet.data.pubkey; + message.title = message.title || 'Sending log'; + message.time = esHttp.date.now(); + + csWallet.getKeypair() + .then(function(keypair) { + return $q.all(developers.reduce(function(res, developer){ + return !developer.pubkey ? res : + res.concat(sendMessage(angular.merge({recipient: developer.pubkey}, message), keypair)); + }, [])); + }) + .then(function(res) { + console.info("[ES] [message] Logs sent to {0} developers".format(res.length)); + }); + } + + function removeListeners() { + _.forEach(listeners, function(remove){ + remove(); }); - } + listeners = []; + } - function removeListeners() { - _.forEach(listeners, function(remove){ - remove(); - }); - listeners = []; - } - - function addListeners() { - // Extend csWallet events - listeners = [ - csWallet.api.data.on.login($rootScope, onWalletLogin, this), - csWallet.api.data.on.init($rootScope, onWalletInit, this), - csWallet.api.data.on.reset($rootScope, onWalletReset, this), - esNotification.api.event.on.newMessage($rootScope, onNewMessageEvent, this), - // for issue #524 - csWallet.api.error.on.send($rootScope, onSendError, this) - ]; - } - - function refreshState() { - var enable = esHttp.alive; - if (!enable && listeners && listeners.length > 0) { - console.debug("[ES] [message] Disable"); - removeListeners(); - if (csWallet.isLogin()) { - onWalletReset(csWallet.data); - } + function addListeners() { + // Extend csWallet events + listeners = [ + csWallet.api.data.on.login($rootScope, onWalletLogin, this), + csWallet.api.data.on.init($rootScope, onWalletInit, this), + csWallet.api.data.on.reset($rootScope, onWalletReset, this), + esNotification.api.event.on.newMessage($rootScope, onNewMessageEvent, this), + // for issue #524 + csWallet.api.error.on.send($rootScope, onSendError, this) + ]; } - else if (enable && (!listeners || listeners.length === 0)) { - console.debug("[ES] [message] Enable"); - addListeners(); - if (csWallet.isLogin()) { - onWalletLogin(csWallet.data); + + function refreshState() { + var enable = esHttp.alive; + if (!enable && listeners && listeners.length > 0) { + console.debug("[ES] [message] Disable"); + removeListeners(); + if (csWallet.isLogin()) { + onWalletReset(csWallet.data); + } + } + else if (enable && (!listeners || listeners.length === 0)) { + console.debug("[ES] [message] Enable"); + addListeners(); + if (csWallet.isLogin()) { + onWalletLogin(csWallet.data); + } } } - } - - // Register extension points - api.registerEvent('data', 'new'); - api.registerEvent('data', 'delete'); - api.registerEvent('data', 'sent'); - - // Default action - csPlatform.ready().then(function() { - esHttp.api.node.on.start($rootScope, refreshState, this); - esHttp.api.node.on.stop($rootScope, refreshState, this); - return refreshState(); - }); - - return { - api: api, - search: raw.postSearch, - notifications: { - load: loadMessageNotifications - }, - load: loadMessages, - get: getAndDecrypt, - send: sendMessage, - remove: removeMessage, - removeAll: removeAllMessages, - markAsRead: markMessageAsRead, - markAllAsRead: markAllMessageAsRead, - fields: { - commons: fields.commons - } - }; -}) + + // Register extension points + api.registerEvent('data', 'new'); + api.registerEvent('data', 'delete'); + api.registerEvent('data', 'sent'); + + // Default action + csPlatform.ready().then(function() { + esHttp.api.node.on.start($rootScope, refreshState, this); + esHttp.api.node.on.stop($rootScope, refreshState, this); + return refreshState(); + }); + + return { + api: api, + search: raw.postSearch, + notifications: { + load: loadMessageNotifications + }, + load: loadMessages, + get: getAndDecrypt, + send: sendMessage, + remove: removeMessage, + removeAll: removeAllMessages, + markAsRead: markMessageAsRead, + markAllAsRead: markAllMessageAsRead, + fields: { + commons: fields.commons + } + }; + }) ; diff --git a/www/plugins/es/js/services/profile-services.js b/www/plugins/es/js/services/profile-services.js index 11d4fc538a0564b6d6ac53bb41d898fdbbfef05b..c0114c87c0896888381318c914b3581994248bbe 100644 --- a/www/plugins/es/js/services/profile-services.js +++ b/www/plugins/es/js/services/profile-services.js @@ -1,5 +1,5 @@ angular.module('cesium.es.profile.services', ['cesium.services', 'cesium.es.http.services']) -.config(function(PluginServiceProvider, csConfig) { + .config(function(PluginServiceProvider, csConfig) { 'ngInject'; var enable = csConfig.plugins && csConfig.plugins.es; @@ -10,49 +10,49 @@ angular.module('cesium.es.profile.services', ['cesium.services', 'cesium.es.http }) -.factory('esProfile', function($rootScope, $q, esHttp, SocialUtils, csWot, csWallet, csPlatform, esSettings) { - 'ngInject'; - - var - that = this, - listeners; - - that.raw = { - getFields: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content&_source=:fields'), - get: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content'), - getAll: esHttp.get('/user/profile/:id'), - search: esHttp.post('/user/profile/_search'), - mixedSearch: esHttp.post('/user,page,group/profile,record/_search') - }; - - function getAvatarAndName(pubkey) { - return that.raw.getFields({id: pubkey, fields: 'title,avatar._content_type'}) - .then(function(res) { - var profile; - if (res && res._source) { - // name - profile = {name: res._source.title}; - // avatar - profile.avatar = esHttp.image.fromHit(res, 'avatar'); - } - return profile; - }) - .catch(function(err){ - // no profile defined - if (err && err.ucode && err.ucode == 404) { - return null; - } - else { - throw err; - } - }); - } + .factory('esProfile', function($rootScope, $q, esHttp, SocialUtils, csWot, csWallet, csPlatform, esSettings) { + 'ngInject'; - function getProfile(pubkey, options) { - options = options || {}; + var + that = this, + listeners; - var get = options.raw ? that.raw.getAll : that.raw.get; - return get({id: pubkey}) + that.raw = { + getFields: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content&_source=:fields'), + get: esHttp.get('/user/profile/:id?&_source_exclude=avatar._content'), + getAll: esHttp.get('/user/profile/:id'), + search: esHttp.post('/user/profile/_search'), + mixedSearch: esHttp.post('/user,page,group/profile,record/_search') + }; + + function getAvatarAndName(pubkey) { + return that.raw.getFields({id: pubkey, fields: 'title,avatar._content_type'}) + .then(function(res) { + var profile; + if (res && res._source) { + // name + profile = {name: res._source.title}; + // avatar + profile.avatar = esHttp.image.fromHit(res, 'avatar'); + } + return profile; + }) + .catch(function(err){ + // no profile defined + if (err && err.ucode && err.ucode == 404) { + return null; + } + else { + throw err; + } + }); + } + + function getProfile(pubkey, options) { + options = options || {}; + + var get = options.raw ? that.raw.getAll : that.raw.get; + return get({id: pubkey}) .then(function(res) { if (!res || !res.found || !res._source) return undefined; @@ -81,11 +81,24 @@ angular.module('cesium.es.profile.services', ['cesium.services', 'cesium.es.http }); } - // decrypt socials, and remove duplicated url - return SocialUtils.open(profile.source.socials, csWallet.data.keypair) - .then(function(){ - return profile; + if (!csWallet.isLogin()) { + // Exclude crypted socials + profile.source.socials = _.filter(profile.source.socials, function(social) { + return social.type != 'curve25519'; }); + } + else { + // decrypt socials (if login) + return SocialUtils.open(profile.source.socials, pubkey) + .then(function(){ + //console.log(profile.source.socials); + // Exclude invalid decrypted socials + //profile.source.socials = _.where(profile.source.socials, {valid: true}); + return profile; + }); + } + + return profile; }) .catch(function(err){ // no profile defined @@ -96,329 +109,291 @@ angular.module('cesium.es.profile.services', ['cesium.services', 'cesium.es.http throw err; } }); - } - - function fillAvatars(datas, pubkeyAtributeName) { - return onWotSearch(null, datas, pubkeyAtributeName); - } - - function _fillSearchResultFromHit(data, hit, avatarFieldName) { - data.avatar = data.avatar || esHttp.image.fromHit(hit, avatarFieldName||'avatar'); - // name (basic or highlighted) - data.name = hit._source.title; - // Avoid too long name (workaround for #308) - if (data.name && data.name.length > 30) { - data.name = data.name.substr(0, 27) + '...'; - } - data.description = hit._source.description; - data.city = hit._source.city; - - if (hit.highlight) { - if (hit.highlight.title) { - data.name = hit.highlight.title[0]; - } - if (hit.highlight.tags) { - data.tags = hit.highlight.tags.reduce(function(res, tag){ - return res.concat(tag.replace('<em>', '').replace('</em>', '')); - },[]); - } - } - } - - function onWalletLogin(data, deferred) { - deferred = deferred || $q.defer(); - if (!data || !data.pubkey || !data.keypair) { - deferred.resolve(); - return deferred.promise; } - // Waiting to load crypto libs - if (!CryptoUtils.isLoaded()) { - console.debug('[ES] [wallet] Waiting crypto lib loading...'); - return $timeout(function() { - return onWalletLogin(data, deferred); - }, 50); + function fillAvatars(datas, pubkeyAtributeName) { + return onWotSearch(null, datas, pubkeyAtributeName); } - console.debug('[ES] [wallet] Loading user avatar+name...'); - var now = new Date().getTime(); + function _fillSearchResultFromHit(data, hit, avatarFieldName) { + data.avatar = data.avatar || esHttp.image.fromHit(hit, avatarFieldName||'avatar'); + // name (basic or highlighted) + data.name = hit._source.title; + // Avoid too long name (workaround for #308) + if (data.name && data.name.length > 30) { + data.name = data.name.substr(0, 27) + '...'; + } + data.description = hit._source.description || data.description; + data.city = hit._source.city || data.city; - esProfile.getAvatarAndName(data.pubkey) - .then(function(profile) { - if (profile) { - data.name = profile.name; - data.avatarStyle = profile.avatarStyle; - data.avatar = profile.avatar; - console.debug('[ES] [profile] Loaded user avatar+name in '+ (new Date().getTime()-now) +'ms'); + if (hit.highlight) { + if (hit.highlight.title) { + data.name = hit.highlight.title[0]; } - else { - console.debug('[ES] [profil] No user avatar+name found'); + if (hit.highlight.tags) { + data.tags = hit.highlight.tags.reduce(function(res, tag){ + return res.concat(tag.replace('<em>', '').replace('</em>', '')); + },[]); } - deferred.resolve(data); - }) - .catch(function(err){ - deferred.reject(err); - }); - - return deferred.promise; - } - - function onWotSearch(text, datas, pubkeyAtributeName, deferred) { - deferred = deferred || $q.defer(); - if (!text && (!datas || !datas.length)) { - deferred.resolve(datas); - return deferred.promise; + } } - pubkeyAtributeName = pubkeyAtributeName || 'pubkey'; - text = text ? text.toLowerCase().trim() : text; - var dataByPubkey; - var tags = text ? esHttp.util.parseTags(text) : undefined; - var request = { - query: {}, - highlight: {fields : {title : {}, tags: {}}}, - from: 0, - size: 100, - _source: ["title", "avatar._content_type"] - }; + function onWotSearch(text, datas, pubkeyAtributeName, deferred) { + deferred = deferred || $q.defer(); + if (!text && (!datas || !datas.length)) { + deferred.resolve(datas); + return deferred.promise; + } - // TODO: uncomment - //var mixedSearch = text && esSettings.wot.isMixedSearchEnable(); - var mixedSearch = false; - if (mixedSearch) { - request._source = request._source.concat(["description", "city", "creationTime", "membersCount", "type"]); - console.debug("[ES] [profile] Mixed search: enable"); - } + pubkeyAtributeName = pubkeyAtributeName || 'pubkey'; + text = text ? text.toLowerCase().trim() : text; + var dataByPubkey; + var tags = text ? esHttp.util.parseTags(text) : undefined; + var request = { + query: {}, + highlight: {fields : {title : {}, tags: {}}}, + from: 0, + size: 100, + _source: ["title", "avatar._content_type"] + }; - if (datas.length > 0) { - // collect pubkeys and fill values map - dataByPubkey = {}; - _.forEach(datas, function(data) { - var pubkey = data[pubkeyAtributeName]; - if (pubkey) { - var values = dataByPubkey[pubkey]; - if (!values) { - values = [data]; - dataByPubkey[pubkey] = values; - } - else { - values.push(data); + // TODO: uncomment + //var mixedSearch = text && esSettings.wot.isMixedSearchEnable(); + var mixedSearch = false; + if (mixedSearch) { + request._source = request._source.concat(["description", "city", "creationTime", "membersCount", "type"]); + console.debug("[ES] [profile] Mixed search: enable"); + } + + if (datas.length > 0) { + // collect pubkeys and fill values map + dataByPubkey = {}; + _.forEach(datas, function(data) { + var pubkey = data[pubkeyAtributeName]; + if (pubkey) { + var values = dataByPubkey[pubkey]; + if (!values) { + values = [data]; + dataByPubkey[pubkey] = values; + } + else { + values.push(data); + } } + }); + var pubkeys = _.keys(dataByPubkey); + // Make sure all results will be return + request.size = (pubkeys.length <= request.size) ? request.size : pubkeys.length; + if (!text) { + delete request.highlight; // highlight not need + request.query.constant_score = { + filter: { + terms : {_id : pubkeys} + } + }; } - }); - var pubkeys = _.keys(dataByPubkey); - // Make sure all results will be return - request.size = (pubkeys.length <= request.size) ? request.size : pubkeys.length; - if (!text) { - delete request.highlight; // highlight not need - request.query.constant_score = { - filter: { - terms : {_id : pubkeys} - } - }; - } - else { - request.query.constant_score = { - filter: {bool: {should: [ + else { + request.query.constant_score = { + filter: {bool: {should: [ {terms : {_id : pubkeys}}, {bool: { - must: [ - {match: {title: {query: text, boost: 2}}}, - {prefix: {title: text}} - ]} + must: [ + {match: {title: {query: text, boost: 2}}}, + {prefix: {title: text}} + ]} } - ]}} - }; + ]}} + }; + if (tags) { + request.query.constant_score.filter.bool.should.push({terms: {tags: tags}}); + } + } + } + else if (text){ + request.query.bool = { + should: [ + {match: {title: { + query: text, + boost: 2 + }}}, + {prefix: {title: text}} + ] + }; if (tags) { - request.query.constant_score.filter.bool.should.push({terms: {tags: tags}}); + request.query.bool.should.push({terms: {tags: tags}}); } } - } - else if (text){ - request.query.bool = { - should: [ - {match: {title: { - query: text, - boost: 2 - }}}, - {prefix: {title: text}} - ] - }; - if (tags) { - request.query.bool.should.push({terms: {tags: tags}}); + else { + // nothing to search: stop here + deferred.resolve(datas); + return deferred.promise; } - } - else { - // nothing to search: stop here - deferred.resolve(datas); - return deferred.promise; - } - if (text && mixedSearch) { - request.indices_boost = { - "user" : 100, - "page" : 1, - "group" : 0.01 - }; - } + if (text && mixedSearch) { + request.indices_boost = { + "user" : 100, + "page" : 1, + "group" : 0.01 + }; + } - var hits; - - var search = mixedSearch ? that.raw.mixedSearch : that.raw.search; - search(request) - .then(function(res) { - hits = res.hits; - if (hits.total > 0) { - var indices = {}; - var values; - _.forEach(hits.hits, function(hit) { - - var avatarFieldName = 'avatar'; - // User profile - if (hit._index == "user") { - values = dataByPubkey && dataByPubkey[hit._id]; - if (!values) { - var value = {}; - value[pubkeyAtributeName] = hit._id; - values=[value]; - datas.push(value); - } + var hits; - avatar = esHttp.image.fromHit(hit, 'avatar'); - } + var search = mixedSearch ? that.raw.mixedSearch : that.raw.search; + search(request) + .then(function(res) { + hits = res.hits; + if (hits.total > 0) { + var indices = {}; + var values; + _.forEach(hits.hits, function(hit) { + + var avatarFieldName = 'avatar'; + // User profile + if (hit._index == "user") { + values = dataByPubkey && dataByPubkey[hit._id]; + if (!values) { + var value = {}; + value[pubkeyAtributeName] = hit._id; + values=[value]; + datas.push(value); + } + + avatar = esHttp.image.fromHit(hit, 'avatar'); + } - // Page or group - else if (hit._index != "user") { - if (!indices[hit._index]) { - indices[hit._index] = true; - // add a separator - datas.push({ - id: 'divider-' + hit._index, - divider: true, - index: hit._index - }); + // Page or group + else if (hit._index != "user") { + if (!indices[hit._index]) { + indices[hit._index] = true; + // add a separator + datas.push({ + id: 'divider-' + hit._index, + divider: true, + index: hit._index + }); + } + var item = { + id: hit._index + '-' + hit._id, // unique id in list + index: hit._index, + templateUrl: 'plugins/es/templates/wot/lookup_item_{0}.html'.format(hit._index), + state: 'app.view_{0}'.format(hit._index), + stateParams: {id: hit._id, title: hit._source.title}, + creationTime: hit._source.creationTime, + memberCount: hit._source.memberCount, + type: hit._source.type + }; + values=[item]; + datas.push(item); + avatarFieldName = 'thumbnail'; } - var item = { - id: hit._index + '-' + hit._id, // unique id in list - index: hit._index, - templateUrl: 'plugins/es/templates/wot/lookup_item_{0}.html'.format(hit._index), - state: 'app.view_{0}'.format(hit._index), - stateParams: {id: hit._id, title: hit._source.title}, - creationTime: hit._source.creationTime, - memberCount: hit._source.memberCount, - type: hit._source.type - }; - values=[item]; - datas.push(item); - avatarFieldName = 'thumbnail'; - } - avatar = esHttp.image.fromHit(hit, avatarFieldName); - _.forEach(values, function(data) { - data.avatar= avatar; - _fillSearchResultFromHit(data, hit); - }); - }); - - // Add divider on top - if (_.keys(indices).length) { - datas.splice(0,0, { - id: 'divider-identities', - divider: true, - index: 'profile' + avatar = esHttp.image.fromHit(hit, avatarFieldName); + _.forEach(values, function(data) { + data.avatar= avatar; + _fillSearchResultFromHit(data, hit); + }); }); + + // Add divider on top + if (_.keys(indices).length) { + datas.splice(0,0, { + id: 'divider-identities', + divider: true, + index: 'profile' + }); + } } - } - deferred.resolve(datas); - }) - .catch(function(err){ - if (err && err.ucode && err.ucode == 404) { deferred.resolve(datas); - } - else { - deferred.reject(err); - } - }); + }) + .catch(function(err){ + if (err && err.ucode && err.ucode == 404) { + deferred.resolve(datas); + } + else { + deferred.reject(err); + } + }); - return deferred.promise; - } + return deferred.promise; + } - function onWotLoad(data, deferred) { - deferred = deferred || $q.defer(); - if (!data || !data.pubkey) { - deferred.resolve(); + function onWotLoad(data, deferred) { + deferred = deferred || $q.defer(); + if (!data || !data.pubkey) { + deferred.resolve(); + return deferred.promise; + } + + $q.all([ + // Load full profile + getProfile(data.pubkey) + .then(function(profile) { + if (profile) { + data.name = profile.name; + data.avatar = profile.avatar; + data.profile = profile.source; + data.profile.description = profile.description; + } + deferred.resolve(data); + }), + + // Load avatar on certifications + fillAvatars( + (data.received_cert||[]) + .concat(data.received_cert_pending||[]) + .concat(data.given_cert||[]) + .concat(data.given_cert_pending||[]) + ) + ]) + .catch(function(err){ + deferred.reject(err); + }); return deferred.promise; } - $q.all([ - // Load full profile - getProfile(data.pubkey) - .then(function(profile) { - if (profile) { - data.name = profile.name; - data.avatar = profile.avatar; - data.profile = profile.source; - data.profile.description = profile.description; - } - deferred.resolve(data); - }), - - // Load avatar on certifications - fillAvatars( - (data.received_cert||[]) - .concat(data.received_cert_pending||[]) - .concat(data.given_cert||[]) - .concat(data.given_cert_pending||[]) - ) - ]) - .catch(function(err){ - deferred.reject(err); - }); - return deferred.promise; - } + function removeListeners() { + _.forEach(listeners, function(remove){ + remove(); + }); + listeners = []; + } - function removeListeners() { - _.forEach(listeners, function(remove){ - remove(); - }); - listeners = []; - } - - function addListeners() { - // Extend csWot events - listeners = [ - csWot.api.data.on.load($rootScope, onWotLoad, this), - csWot.api.data.on.search($rootScope, onWotSearch, this) - ]; - } - - function refreshState() { - var enable = esHttp.alive; - if (!enable && listeners && listeners.length > 0) { - console.debug("[ES] [profile] Disable"); - removeListeners(); + function addListeners() { + // Extend csWot events + listeners = [ + csWot.api.data.on.load($rootScope, onWotLoad, this), + csWot.api.data.on.search($rootScope, onWotSearch, this) + ]; } - else if (enable && (!listeners || listeners.length === 0)) { - console.debug("[ES] [profile] Enable"); - addListeners(); + + function refreshState() { + var enable = esHttp.alive; + if (!enable && listeners && listeners.length > 0) { + console.debug("[ES] [profile] Disable"); + removeListeners(); + } + else if (enable && (!listeners || listeners.length === 0)) { + console.debug("[ES] [profile] Enable"); + addListeners(); + } } - } - - // Default actions - csPlatform.ready().then(function() { - esHttp.api.node.on.start($rootScope, refreshState, this); - esHttp.api.node.on.stop($rootScope, refreshState, this); - return refreshState(); - }); - - return { - getAvatarAndName: getAvatarAndName, - get: getProfile, - add: esHttp.record.post('/user/profile', {tagFields: ['title', 'description']}), - update: esHttp.record.post('/user/profile/:id/_update', {tagFields: ['title', 'description']}), - avatar: esHttp.get('/user/profile/:id?_source=avatar'), - fillAvatars: fillAvatars - }; -}) + + // Default actions + csPlatform.ready().then(function() { + esHttp.api.node.on.start($rootScope, refreshState, this); + esHttp.api.node.on.stop($rootScope, refreshState, this); + return refreshState(); + }); + + return { + getAvatarAndName: getAvatarAndName, + get: getProfile, + add: esHttp.record.post('/user/profile', {tagFields: ['title', 'description']}), + update: esHttp.record.post('/user/profile/:id/_update', {tagFields: ['title', 'description']}), + avatar: esHttp.get('/user/profile/:id?_source=avatar'), + fillAvatars: fillAvatars + }; + }) ; diff --git a/www/plugins/es/js/services/social-services.js b/www/plugins/es/js/services/social-services.js index de204dee445652ba3f9fac7b72316b3a0e382b89..37305a2d62ef2c2adc1acb720b669d0295c9c270 100644 --- a/www/plugins/es/js/services/social-services.js +++ b/www/plugins/es/js/services/social-services.js @@ -1,39 +1,42 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) -.factory('SocialUtils', function($filter, $q, CryptoUtils, BMA, esCrypto) { - 'ngInject'; + .factory('SocialUtils', function($filter, $q, CryptoUtils, BMA, csWallet, esCrypto) { + 'ngInject'; function SocialUtils() { var - regexp = { - URI: "([a-zA−Z0-9]+)://[ a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+", - EMAIL: "[a-zA-Z0-9-_.]+@[a-zA-Z0-9_.-]+?\\.[a-zA-Z]{2,3}", - socials: { - facebook: "https?://((fb.me)|((www.)?facebook.com))", - twitter: "https?://(www.)?twitter.com", - googleplus: "https?://plus.google.com(/u)?", - youtube: "https?://(www.)?youtube.com", - github: "https?://(www.)?github.com", - tumblr: "https?://(www.)?tumblr.com", - snapchat: "https?://(www.)?snapchat.com", - linkedin: "https?://(www.)?linkedin.com", - vimeo: "https?://(www.)?vimeo.com", - instagram: "https?://(www.)?instagram.com", - wordpress: "https?://([a-z]+)?wordpress.com", - diaspora: "https?://(www.)?((diaspora[-a-z]+)|(framasphere)).org", - duniter: "duniter://[a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+", - bitcoin: "bitcoin://[a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+", - curve25519: "curve25519://(" + BMA.constants.regexp.PUBKEY + "):([a-zA-Z0-9]+)@([a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+)" + regexp = { + URI: "([a-zA−Z0-9]+)://[ a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+", + EMAIL: "[a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$", + PHONE: "[+]?[0-9. ]{9,15}", + socials: { + facebook: "https?://((fb.me)|((www.)?facebook.com))", + twitter: "https?://(www.)?twitter.com", + googleplus: "https?://plus.google.com(/u)?", + youtube: "https?://(www.)?youtube.com", + github: "https?://(www.)?github.com", + tumblr: "https?://(www.)?tumblr.com", + snapchat: "https?://(www.)?snapchat.com", + linkedin: "https?://(www.)?linkedin.com", + vimeo: "https?://(www.)?vimeo.com", + instagram: "https?://(www.)?instagram.com", + wordpress: "https?://([a-z]+)?wordpress.com", + diaspora: "https?://(www.)?((diaspora[-a-z]+)|(framasphere)).org", + duniter: "duniter://[a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+", + bitcoin: "bitcoin://[a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+", + curve25519: "curve25519://(" + BMA.constants.regexp.PUBKEY + "):([a-zA-Z0-9]+)@([a-zA-Z0-9-_:/;*?!^\\+=@&~#|<>%.]+)" + } } - } - ; + ; function exact(regexpContent) { return new RegExp("^" + regexpContent + "$"); } + regexp.URI = exact(regexp.URI); regexp.EMAIL = exact(regexp.EMAIL); + regexp.PHONE = exact(regexp.PHONE); _.keys(regexp.socials).forEach(function(key){ regexp.socials[key] = exact(regexp.socials[key]); }); @@ -49,7 +52,7 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) urlToMatch = url.substring(0, slashPathIndex); } } - //console.debug("[social] match URI, try to match: " + urlToMatch); + //console.log("match URI, try to match: " + urlToMatch); _.keys(regexp.socials).forEach(function(key){ if (regexp.socials[key].test(urlToMatch)) { type = key; @@ -63,7 +66,12 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) else if (regexp.EMAIL.test(url)) { type = 'email'; } - //if (!type) console.debug("[social] match type: " + type); + else if (regexp.PHONE.test(url)) { + type = 'phone'; + } + if (!type) { + console.warn("[ES] [social] Unable to detect type of social URL: " + url); + } return type; } @@ -85,7 +93,16 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) if (!socials || !socials.length) return []; var map = {}; socials.forEach(function(social) { - social = social.type == 'curve25519' ? social : getFromUrl(social.url); + if (social.type == 'curve25519') { + delete social.issuer; + if (social.valid) { + angular.merge(social, getFromUrl(social.url)); + } + } + else { + // Retrieve object from URL, to get the right type (e.g. if new regexp) + social = getFromUrl(social.url); + } if (social) { var id = $filter('formatSlug')(social.url); map[id] = social; @@ -102,28 +119,33 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) }; } - function openArray(socials) { + function openArray(socials, issuer, recipient) { + + recipient = recipient || csWallet.data.pubkey; // Waiting to load crypto libs if (!CryptoUtils.isLoaded()) { console.debug('[socials] Waiting crypto lib loading...'); return $timeout(function() { - return openArray(socials); + return openArray(socials, issuer, recipient); }, 100); } - var encryptedSocials = _.filter(socials||[], function(social){ + var socialsToDecrypt = _.filter(socials||[], function(social){ var matches = social.url && social.type == 'curve25519' && regexp.socials.curve25519.exec(social.url); if (!matches) return false; social.recipient = matches[1]; social.nonce = matches[2]; social.url = matches[3]; - return true; + social.issuer = issuer; + social.valid = (social.recipient === recipient); + return social.valid; }); - if (!encryptedSocials.length) return $q.when(reduceArray(socials)); + if (!socialsToDecrypt.length) return $q.when(reduceArray(socials)); - return esCrypto.box.open(encryptedSocials, undefined/*=wallet keypair*/, 'recipient', 'url') + return esCrypto.box.open(socialsToDecrypt, undefined/*=wallet keypair*/, 'issuer', 'url') .then(function() { + // return all socials (encrypted or not) return reduceArray(socials); }); } @@ -143,20 +165,19 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) if (!socialsToEncrypt.length) return $q.when(socials); return CryptoUtils.util.random_nonce() - .then(function(nonce) { - return $q.all(socialsToEncrypt.reduce(function(res, social) { - return res.concat(esCrypto.box.pack(social, undefined/*=wallet keypair*/, 'recipient', 'url', nonce)); - }, [])); - }) - .then(function(res){ - return res.reduce(function(res, social) { - return res.concat({ - type: 'curve25519', - url: 'curve25519://{0}:{1}@{2}'.format(social.recipient, social.nonce, social.url) - }); - }, []); - }) - ; + .then(function(nonce) { + return $q.all(socialsToEncrypt.reduce(function(res, social) { + return res.concat(esCrypto.box.pack(social, undefined/*=wallet keypair*/, 'recipient', 'url', nonce)); + }, [])); + }) + .then(function(res){ + return res.reduce(function(res, social) { + return res.concat({ + type: 'curve25519', + url: 'curve25519://{0}:{1}@{2}'.format(social.recipient, social.nonce, social.url) + }); + }, []); + }); } return { @@ -172,6 +193,6 @@ angular.module('cesium.es.social.services', ['cesium.es.crypto.services']) var service = SocialUtils(); service.instance = SocialUtils; - return service; -}) + return service; + }) ; diff --git a/www/plugins/es/templates/common/edit_socials.html b/www/plugins/es/templates/common/edit_socials.html index 4ce480ec17f615eed37c5c6316ca69c9abd61c62..42e474b44514ffcd9921e944f4ef8ffd949f14b1 100644 --- a/www/plugins/es/templates/common/edit_socials.html +++ b/www/plugins/es/templates/common/edit_socials.html @@ -1,31 +1,42 @@ -<ng-controller ng-controller="ESSocialsEditCtrl"> <div class="item item-divider" translate>PROFILE.SOCIAL_NETWORKS_DIVIDER</div> <ion-item class="item-remove-animate item-icon-left " - type="no-padding item-text-wrap" - ng-if="formData.socials && formData.socials.length>0" - ng-repeat="social in formData.socials track by social.url" - id="social-{{social.url|formatSlug}}"> - <i class="icon ion-social-{{social.type}}" - ng-class="{'ion-bookmark': social.type == 'other', 'ion-link': social.type == 'web', 'ion-email': social.type == 'email'}"></i> - <p ng-if="social.type && social.type != 'web'">{{social.type}}</p> - <h2> - <a href="{{social.url}}" ng-if="social.type != 'email'" target="_blank">{{social.url}}</a> - <a href="mailto:{{social.url}}" ng-if="social.type == 'email'">{{social.url}}</a> - <a class="gray hidden-device" ng-click="formData.socials.splice($index, 1); doSave();"> - <b class="ion ion-trash-a"></b> - </a> - <a class="gray hidden-device" ng-click="editSocialNetwork($index)"> - <b class="ion ion-edit"></b> - </a> - </h2> - <ion-option-button class="button-assertive" ng-click="formData.socials.splice($index, 1); doSave();"> - {{'COMMON.BTN_DELETE'|translate}} - </ion-option-button> - <ion-option-button class="button-info" ng-click="editSocialNetwork($index)"> - {{'COMMON.BTN_EDIT'|translate}} - </ion-option-button> + type="no-padding item-text-wrap" + ng-if="formData.socials && formData.socials.length" + ng-repeat="social in formData.socials | filter:filterFn track by social.url" + id="social-{{social.url|formatSlug}}"> + <i class="icon ion-social-{{social.type}}" + ng-class="{'ion-bookmark': social.type == 'other', 'ion-link': social.type == 'web', 'ion-email': social.type == 'email', 'ion-iphone': social.type == 'phone'}"></i> + <p ng-if="social.type && social.type != 'web'"> + {{social.type}} + <i class="ion-locked" ng-if="social.recipient"></i> + </p> + <h2> + <a href="{{social.url}}" ng-if="social.type != 'email' && social.type != 'phone'" target="_blank">{{social.url}}</a> + <a href="mailto:{{social.url}}" ng-if="social.type == 'email'">{{social.url}}</a> + <a href="tel:{{social.url}}" ng-if="social.type == 'phone'">{{social.url}}</a> + <a class="gray hidden-device" + ng-if="!social.recipient" + ng-click="formData.socials.splice($index, 1); dirty = true;"> + <b class="ion ion-trash-a"></b> + </a> + <a class="gray hidden-device" + ng-if="!social.recipient" + ng-click="editSocialNetwork($index)"> + <b class="ion ion-edit"></b> + </a> + </h2> + <ion-option-button class="button-assertive" + ng-if="!social.recipient" + ng-click="formData.socials.splice($index, 1); dirty = true;"> + {{'COMMON.BTN_DELETE'|translate}} + </ion-option-button> + <ion-option-button class="button-info" + ng-if="!social.recipient" + ng-click="editSocialNetwork($index)"> + {{'COMMON.BTN_EDIT'|translate}} + </ion-option-button> </ion-item> <div class="item item-complex item-input-inset"> @@ -43,4 +54,3 @@ </button> </div> -</ng-controller> diff --git a/www/plugins/es/templates/common/item_comment.html b/www/plugins/es/templates/common/item_comment.html index f9f16578e7b6de407909906e4e2a14c9b5fc8729..be81709f1be813a3a3b1207966615c9bd31aa089 100644 --- a/www/plugins/es/templates/common/item_comment.html +++ b/www/plugins/es/templates/common/item_comment.html @@ -2,9 +2,9 @@ <a name="{{::comment.id|formatHash}}"></a> <ion-item - id="comment-{{comment.id|formatHash}}" - class="card card-comment card-avatar stable-900-bg item-text-wrap no-padding" - ng-class="{'in done': comment.isnew}"> + id="comment-{{::comment.id|formatHash}}" + class="card card-comment card-avatar stable-900-bg item-text-wrap no-padding" + ng-class="::{'in done': comment.isnew}"> <!-- Parent comment --> <div class="card-header padding-left" ng-if="comment.parent && !hideParent"> @@ -15,12 +15,12 @@ <ng-if ng-if="comment.parent.issuer"> <a ng-click="toggleExpandedParent(comment, $index)"> {{'COMMENTS.REPLY_TO_LINK'|translate}} - <ng-if ng-if="comment.parent.uid"> - {{comment.parent.name||comment.parent.uid}} + <ng-if ng-if="::comment.parent.uid"> + {{::comment.parent.name||comment.parent.uid}} </ng-if> - <ng-if ng-if="!comment.parent.uid"> + <ng-if ng-if="::!comment.parent.uid"> <i class="ion-key"></i> - {{comment.parent.issuer|formatPubkey}} + {{::comment.parent.name|| (comment.parent.issuer|formatPubkey) }} </ng-if> </a> <i ng-class="{'ion-arrow-down-b': !comment.expandedParent[$index], 'ion-arrow-up-b': comment.expandedParent[$index]}"></i> @@ -64,7 +64,7 @@ <!-- replies --> <div ng-if="comment.expandedReplies[$index]" class="padding-left card-avatar-small expanded" ng-init="hideParent=true"> <ng-include ng-repeat="comment in comment.replies track by comment.id" - src="'plugins/es/templates/common/item_comment.html'"> + src="'plugins/es/templates/common/item_comment.html'"> </ng-include> </div> diff --git a/www/plugins/es/templates/common/item_comment_content.html b/www/plugins/es/templates/common/item_comment_content.html index 4d28f29cdda8e0c4379dd62421e3d86181f62d4f..d58df1487bbafb44d7cb1a25ffb1801f601be84d 100644 --- a/www/plugins/es/templates/common/item_comment_content.html +++ b/www/plugins/es/templates/common/item_comment_content.html @@ -1,11 +1,11 @@ - <div class="item item-avatar done in"> +<div class="item item-avatar done in"> <span class="avatar" ng-if="::!comment.avatar" ng-class="::{'avatar-member': comment.uid, 'avatar-wallet': !comment.uid}"></span> - <span class="avatar" - ng-if="::comment.avatar" - style="background-image: url({{::comment.avatar.src}})"></span> + <span class="avatar" + ng-if="::comment.avatar" + style="background-image: url({{::comment.avatar.src}})"></span> <a class="pull-left" ui-sref="app.wot_identity({pubkey:comment.issuer, uid: comment.uid})"> @@ -14,8 +14,8 @@ </span> <span ng-if="::!comment.uid" class="gray"> <i class="icon ion-key gray"></i> - {{::comment.issuer|formatPubkey}} + {{::comment.name || (comment.issuer|formatPubkey)}} </span> - </a> - <span trust-as-html="comment.html"></span> - </div> + </a> + <span trust-as-html="comment.html"></span> +</div> diff --git a/www/plugins/es/templates/user/modal_edit_avatar.html b/www/plugins/es/templates/common/modal_edit_avatar.html similarity index 100% rename from www/plugins/es/templates/user/modal_edit_avatar.html rename to www/plugins/es/templates/common/modal_edit_avatar.html diff --git a/www/plugins/es/templates/common/view_comments.html b/www/plugins/es/templates/common/view_comments.html index 3c82a6affe3ecdcecb85ebef4a042dc4e3bba749..b3668a7cff15f899b1a91528980a72f14d94c2bd 100644 --- a/www/plugins/es/templates/common/view_comments.html +++ b/www/plugins/es/templates/common/view_comments.html @@ -72,7 +72,7 @@ </div> </div> - <div class="visible-xs visible-sm"> + <div class="visible-xs visible-sm" style="margin-bottom"> <div class="block"> <!-- reply to comment--> <div class="item item-input-inset done in" ng-if="formData.parent"> @@ -111,6 +111,5 @@ </div> </div> </div> - </div> </div> </div> diff --git a/www/plugins/es/templates/user/items_profile.html b/www/plugins/es/templates/user/items_profile.html index 5ef67e24d4428dc36590920c50a43e97432f060c..2354e461caf00717774b104e6dbb6f91926dedae 100644 --- a/www/plugins/es/templates/user/items_profile.html +++ b/www/plugins/es/templates/user/items_profile.html @@ -27,13 +27,16 @@ <div class="item" ng-if="formData.profile.socials && formData.profile.socials.length" ng-controller="ESSocialsViewCtrl"> <span class="gray" translate>PROFILE.SOCIAL_NETWORKS_DIVIDER</span> <div class="list no-padding"> - <ion-item ng-repeat="social in formData.profile.socials track by social.url" + <ion-item ng-repeat="social in formData.profile.socials | filter:filterFn track by social.url " id="social-{{::social.url|formatSlug}}" class="item-icon-left item-text-wrap no-padding-bottom ink" ng-click="openSocial($event, social)"> <i class="icon ion-social-{{social.type}}" - ng-class="{'ion-bookmark': social.type == 'other', 'ion-link': social.type == 'web', 'ion-email': social.type == 'email'}"></i> - <p ng-if="social.type && social.type != 'web'">{{social.type}}</p> + ng-class="{'ion-bookmark': social.type == 'other', 'ion-link': social.type == 'web', 'ion-email': social.type == 'email', 'ion-iphone': social.type == 'phone'}"></i> + <p ng-if="social.type && social.type != 'web'"> + {{social.type}} + <i class="ion-locked" ng-if="social.recipient"></i> + </p> <h4> <a>{{::social.url}}</a> </h4> diff --git a/www/plugins/es/templates/wallet/view_wallet_extend.html b/www/plugins/es/templates/wallet/view_wallet_extend.html index f148efdf402dd16a16587fefe4dca664c4968fd6..5ea67187ec3d1a8c88c47b8d1668d819c1f2bb5b 100644 --- a/www/plugins/es/templates/wallet/view_wallet_extend.html +++ b/www/plugins/es/templates/wallet/view_wallet_extend.html @@ -1,7 +1,7 @@ <ng-if ng-if="enable"> <!-- profile --> <div class="item item-divider item-divider-top-border"> - {{'PROFILE.PROFILE_DIVIDER' | translate}} + <span ng-bind-html="'PROFILE.PROFILE_DIVIDER' | translate"></span> <a class="badge button button-text button-small button-small-padding " ui-sref="app.user_edit_profile"> <i class="icon ion-edit"></i> diff --git a/www/plugins/es/templates/wot/view_identity_extend.html b/www/plugins/es/templates/wot/view_identity_extend.html index 980aa8d6da09ee9a0374f1bd1b5d6065a586ea62..d825937baa3436a8b508f3792bb72f5b0b56366b 100644 --- a/www/plugins/es/templates/wot/view_identity_extend.html +++ b/www/plugins/es/templates/wot/view_identity_extend.html @@ -7,7 +7,7 @@ </ng-if> <!-- General section --> -<ng-if ng-if="enable && extensionPoint === 'general'"> +<ng-if ng-if="enable && extensionPoint === 'after-general'"> <span class="item item-divider item-divider-top-border" translate>PROFILE.PROFILE_DIVIDER</span> diff --git a/www/templates/wallet/view_wallet.html b/www/templates/wallet/view_wallet.html index 98ef33f574de941374fd62897172d7e1fc3bd07d..fac5b093da7fdc31d09a53b971e41b1518d4c49f 100644 --- a/www/templates/wallet/view_wallet.html +++ b/www/templates/wallet/view_wallet.html @@ -142,6 +142,15 @@ <i class="gray icon ion-ios-arrow-right"></i> </a> + <!-- Account transaction --> + <a class="item item-icon-left item-icon-right ink" + ng-if="!loading" + ui-sref="app.view_wallet_tx"> + <i class="icon ion-card"></i> + <span translate>WOT.ACCOUNT_OPERATIONS</span> + <i class="gray icon ion-ios-arrow-right"></i> + </a> + <!-- Events --> <span class="item item-divider" ng-if="formData.events.length"> {{:locale:'ACCOUNT.EVENTS' | translate}} @@ -155,16 +164,10 @@ <span trust-as-html="event.message | translate:event.messageParams"></span> </div> - <!-- Account transaction --> - <a class="item item-icon-left item-icon-right ink" - ng-if="!loading" - ui-sref="app.view_wallet_tx"> - <i class="icon ion-card"></i> - <span translate>WOT.ACCOUNT_OPERATIONS</span> - <i class="gray icon ion-ios-arrow-right"></i> - </a> - <cs-extension-point name="before-technical"></cs-extension-point> + <cs-extension-point name="general"></cs-extension-point> + + <cs-extension-point name="after-general"></cs-extension-point> </div> diff --git a/www/templates/wot/view_identity.html b/www/templates/wot/view_identity.html index f257fc4e43caff33fe3ffc8734260565c10746e1..f7d5c169b6c0390af3ff49e5f0af0abc84a7201f 100644 --- a/www/templates/wot/view_identity.html +++ b/www/templates/wot/view_identity.html @@ -145,6 +145,8 @@ <cs-extension-point name="general"></cs-extension-point> + <cs-extension-point name="after-general"></cs-extension-point> + </div> <div class="col col-20 hidden-xs hidden-sm"> </div>