diff --git a/scss/ionic.app.scss b/scss/ionic.app.scss index 58a9f1666b64df3aba5a6df83aa92887ce5d92f7..1ea74a0f86d1717c6226aa25ee18a6f684666817 100644 --- a/scss/ionic.app.scss +++ b/scss/ionic.app.scss @@ -1125,6 +1125,7 @@ $ionicon-var-badge-editable: $ionicon-var-edit + "\00a0"; padding: 0 15px; } + @media screen and (max-width: $screen-xxs-max) { .card > .item.item-thumbnail-left, .item-thumbnail-left, diff --git a/www/js/app.js b/www/js/app.js index 3df37b1780f860dcec8f28bc7d089b88d178eeef..79680ca7e3eadc2b9e3be0d3858a1947afe05436 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -23,7 +23,7 @@ angular.module('cesium', ['ionic', 'ionic-material', 'ngMessages', 'pascalprecht }; }) - .filter('formatDecimal', function(csConfig) { + .filter('formatDecimal', function(csConfig, $rootScope) { var minValue = 1 / Math.pow(10, csConfig.decimalCount || 4); var format = '0,0.0' + Array(csConfig.decimalCount || 4).join('0'); diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js index d94843744e92615e170d63640950a55853ead469..db2c009340b7f587b3de5a9d50dc0b486afd2879 100644 --- a/www/js/controllers/app-controllers.js +++ b/www/js/controllers/app-controllers.js @@ -99,26 +99,17 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ templateUrl :'templates/common/popover_notification.html', scope: $scope, autoremove: false, // reuse popover - afterShow: function(popover) { - if (!popover.scope.markAllAsRead) { - popover.scope.markAllAsRead = function() { - $rootScope.walletData.notifications.unreadCount = 0; - var lastNotification = $rootScope.walletData.notifications.history[0]; - $rootScope.walletData.notifications.readTime = lastNotification ? lastNotification.time : 0; - _.forEach($rootScope.walletData.notifications.history, function (item) { - if (item.onRead && typeof item.onRead == 'function') item.onRead(); - }); - }; - } - - $timeout(function() { - UIUtils.ink({selector: '.notification-popover .ink'}); - }, 100); - }, afterHidden: function() { - $rootScope.walletData.notifications.unreadCount = 0; - var lastNotification = $rootScope.walletData.notifications.history[0]; - $rootScope.walletData.notifications.readTime = lastNotification ? lastNotification.time : 0; + csWallet.data.notifications.unreadCount = 0; + if (csWallet.data.notifications && csWallet.data.notifications.history.length) { + var lastNotification = csWallet.data.notifications.history[0]; + var readTime = lastNotification ? lastNotification.time : 0; + csSettings.data.wallet = csSettings.data.wallet || {}; + if (readTime && csSettings.data.wallet.notificationReadTime != readTime) { + csSettings.data.wallet.notificationReadTime = readTime; + csSettings.store(); + } + } } }) .then(function(item) { @@ -357,9 +348,11 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $ }; // add listener on wallet event - csWallet.api.data.on.login($scope, function(walletData, resolve) { + csWallet.api.data.on.login($scope, function(walletData, deferred) { + deferred = deferred || $q.defer(); $rootScope.login = true; - if (resolve) resolve(); + deferred.resolve(); + return deferred.promise; }); csWallet.api.data.on.logout($scope, function() { $rootScope.login = false; diff --git a/www/js/controllers/notification-controllers.js b/www/js/controllers/notification-controllers.js index 2633a52d18d35c67e9253b460f56ce2b8bdfe5cf..768dadaad7308e982c073f2571a5544b3d2e4761 100644 --- a/www/js/controllers/notification-controllers.js +++ b/www/js/controllers/notification-controllers.js @@ -27,7 +27,7 @@ angular.module('cesium.notification.controllers', ['cesium.services']) ; -function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state, csWallet) { +function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state, csWallet, csSettings) { var defaultSearchLimit = 40; @@ -45,16 +45,20 @@ function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state, } }); - $scope.load = function() { + $scope.load = function(from, size) { + from = from || 0; + size = size || defaultSearchLimit; return csWallet.refreshData({ notifications: { enable: true, - from: 0, - size: $scope.search.limit + from: from, + size: size } }) - .then(function() { - $scope.search.results = csWallet.data.notifications.history; + .then(function(data) { + if (from === 0) { + $scope.search.results = data.notifications.history; + } $scope.search.loading = false; $scope.search.hasMore = ($scope.search.results && $scope.search.results.length >= $scope.search.limit); $scope.updateView(); @@ -100,7 +104,7 @@ function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state, } $scope.search.loadingMore = true; $scope.load( - $scope.search.results.length, // offset + $scope.search.results.length, // from $scope.search.limit) .then(function() { $scope.search.loadingMore = false; @@ -110,9 +114,9 @@ function NotificationsController($scope, $rootScope, $timeout, UIUtils, $state, } -function PopoverNotificationsController($scope, $rootScope, $timeout, UIUtils, $state, csWallet) { +function PopoverNotificationsController($scope, $rootScope, $timeout, UIUtils, $state, csWallet, csSettings) { - NotificationsController.call(this, $scope, $rootScope, $timeout, UIUtils, $state, csWallet); + NotificationsController.call(this, $scope, $rootScope, $timeout, UIUtils, $state, csWallet, csSettings); $scope.updateView = function() { // Set Ink @@ -121,7 +125,7 @@ function PopoverNotificationsController($scope, $rootScope, $timeout, UIUtils, $ }, 100); }; - if ($scope.search.loading) { + if ($scope.search.loading || !csWallet.data.notifications.history || !csWallet.data.notifications.history.length) { $scope.load(); } diff --git a/www/js/services/settings-services.js b/www/js/services/settings-services.js index aef205e3f40bcf94b0d52d583c4dc53a0094fc9b..88b447eb54f857f6687dfb997e8f92a3e280d7f4 100644 --- a/www/js/services/settings-services.js +++ b/www/js/services/settings-services.js @@ -41,7 +41,8 @@ angular.module('cesium.settings.services', ['ngResource', 'ngApi', 'cesium.confi }, wallet: { showPubkey: true, - alertIfUnusedWallet: true + alertIfUnusedWallet: true, + notificationReadTime: 0 }, locale: { id: fixLocale(csConfig.defaultLanguage || $translate.use()) // use config locale if set, or browser default diff --git a/www/js/services/wallet-services.js b/www/js/services/wallet-services.js index c710a22dcc3615621b6d2c1d775fedfeaff6f236..3e8c2f6e8dafb4543c027a09ff98188a480969ca 100644 --- a/www/js/services/wallet-services.js +++ b/www/js/services/wallet-services.js @@ -791,6 +791,9 @@ angular.module('cesium.wallet.services', ['ngResource', 'ngApi', 'cesium.bma.ser }) .then(function(){ return api.data.raisePromise.finishLoad(data); + }) + .then(function(){ + return data; }); }, diff --git a/www/plugins/es/i18n/locale-fr-FR.json b/www/plugins/es/i18n/locale-fr-FR.json index ffb16db4cb95eaff32f8e725a2637920873333ef..4e5fbb2d995408f235ac55af7a77d0f6b20bd746 100644 --- a/www/plugins/es/i18n/locale-fr-FR.json +++ b/www/plugins/es/i18n/locale-fr-FR.json @@ -72,7 +72,8 @@ "USER_NOT_RECIPIENT": "Vous n'etes pas le destinataire de ce message : déchiffrement impossible.", "NOT_AUTHENTICATED_MESSAGE": "L'authenticité du message est douteuse ou son contenu est corrompu.", "REMOVE_MESSAGE_FAILED": "Erreur de suppression du message", - "MESSAGE_CONTENT_TOO_LONG": "Valeur trop longue ({{maxLength}} caractères max)." + "MESSAGE_CONTENT_TOO_LONG": "Valeur trop longue ({{maxLength}} caractères max).", + "MARK_AS_READ_FAILED": "Impossible de marquer le message comme 'lu'." } }, "MARKET": { @@ -249,13 +250,15 @@ }, "EVENT": { "NODE_STARTED": "Votre noeud ES API <b>{{p0}}</b> est démarré", - "NODE_BMA_DOWN": "Noeud <b>{{p0}}:{{p1}}</b> injoignable (utilisé par votre ES API <b>{{p2}}</b>).<br/>Date de la dernière connection : {{p3|formatDate}}.", - "NODE_BMA_UP": "Noeud <b>{{p0}}:{{p1}}</b> à nouveau accessible.", + "NODE_BMA_DOWN": "Le noeud <b>{{p0}}:{{p1}}</b> (utilisé par votre noeud ES API) est <b>injoignable</b>.", + "NODE_BMA_UP": "Le noeud <b>{{p0}}:{{p1}}</b> est à nouveau accessible.", "MEMBER_JOIN": "Vous êtes maintenant <b>membre</b> de la monnaie <b>{{p0}}</b> !", "MEMBER_LEAVE": "Vous n'êtes <b>plus membre</b> de la monnaie <b>{{p0}}</b>!", "MEMBER_ACTIVE": "Votre renouvellement d'adhésion à la monnaie <b>{{p0}}</b> a été <b>pris en compte</b>.", - "TX_SENT": "Votre paiement à <b>{{p0|formatPubkey}}</b> a été effectué.", - "TX_RECEIVED": "Vous avez reçu un paiement de <b>{{p0|formatPubkey}}</b>.", + "TX_SENT": "Votre paiement à <a ui-sref=\"app.wot_view_identity({pubkey:'{{p1}}', uid:'{{p0}}'})\">{{p0}}</a> a été effectué.", + "TX_SENT_MULTI": "Votre paiement à <b>{{p0}}</b> a été effectué.", + "TX_RECEIVED": "Vous avez reçu un paiement de <a ui-sref=\"app.wot_view_identity({pubkey:'{{p1}}', uid:'{{p0}}'})\">{{p0}}</a>.", + "TX_RECEIVED_MULTI": "Vous avez reçu un paiement de <b>{{p0}}</b>.", "MARKET": { "NEW_COMMENT": "<b>{{p0}}</b> a commenté votre annonce: <b>{{p1}}</b>" }, diff --git a/www/plugins/es/js/controllers/market-controllers.js b/www/plugins/es/js/controllers/market-controllers.js index b840dfdc09560b970be6bb6463d18f04078c598d..194d129598948c0e15e74d7820689003c8c239e1 100644 --- a/www/plugins/es/js/controllers/market-controllers.js +++ b/www/plugins/es/js/controllers/market-controllers.js @@ -262,18 +262,18 @@ function ESMarketLookupController($scope, $state, $focus, $timeout, $filter, $q, return $scope.doRequest(request, more); }; - $scope.doGetLastRecord = function(offset, size) { + $scope.doGetLastRecord = function(from, size) { $scope.search.lastRecords = true; - offset = offset || 0; + from = from || 0; size = size || defaultSearchLimit; - var more = offset > 0; + var more = from > 0; var request = { sort: { "creationTime" : "desc" }, - from: offset, + from: from, size: size, _source: esMarket.record.fields.commons }; @@ -378,9 +378,7 @@ function ESMarketLookupController($scope, $state, $focus, $timeout, $filter, $q, $scope.search.results = records; } else { - _.forEach(records, function(record) { - $scope.search.results.push(record); - }); + $scope.search.results.splice($scope.search.results.length-1, 0, records); } if (records.length > 0) { @@ -397,7 +395,7 @@ function ESMarketLookupController($scope, $state, $focus, $timeout, $filter, $q, } } - $scope.search.hasMore = $scope.search.results.length === $scope.search.limit; + $scope.search.hasMore = $scope.search.results.length >= $scope.search.limit; $scope.search.loading = false; }) .catch(function(err) { diff --git a/www/plugins/es/js/controllers/message-controllers.js b/www/plugins/es/js/controllers/message-controllers.js index 684422e5f450428aaa9ba3aff7c52e29c5bd0e10..b7467097f642a6fc2106743984e6547704f7d05b 100644 --- a/www/plugins/es/js/controllers/message-controllers.js +++ b/www/plugins/es/js/controllers/message-controllers.js @@ -325,7 +325,35 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis $scope.$on('$ionicView.enter', function (e, state) { if (state.stateParams && state.stateParams.id) { // Load by id if ($scope.loading) { // prevent reload if same id - $scope.load(state.stateParams.id); + $scope.load(state.stateParams.id) + .then(function(message) { + $scope.loading = false; + UIUtils.loading.hide(); + if (!message) return; + + $scope.id = message.id; + $scope.formData = message; + $scope.canDelete = true; + $timeout(function () { + UIUtils.motion.fadeSlideIn({ + selector: '.view-message .animate-fade-slide-in .item', + startVelocity: 3000 + }); + }); + // Mark as read + if (!message.read) { + $timeout(function() { + // Message has NOT changed + if ($scope.id == message.id) { + esMessage.markAsRead(message) + .then(function() { + console.debug("[message] marked as read"); + }) + .catch(UIUtils.onError('MESSAGE.ERROR.MARK_AS_READ_FAILED')); + } + }, 2000); // 2s + } + }); } $scope.showFab('fab-view-message-reply'); @@ -337,51 +365,26 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis $scope.load = function(id) { - $scope.loadWallet() - .then(function(){ - UIUtils.loading.hide(); - - return esMessage.get({id: id}) - .then(function(message) { - - if (!message.valid) { - - return UIUtils.alert.error(!$scope.isUserPubkey(message.recipient) ? 'MESSAGE.ERROR.USER_NOT_RECIPIENT' : 'MESSAGE.ERROR.NOT_AUTHENTICATED_MESSAGE', - 'MESSAGE.ERROR.MESSAGE_NOT_READABLE') - .then(function () { - $state.go('app.user_message'); - }); - } - - $scope.formData = message; - $scope.canDelete = true; - $scope.loading = false; - - // Load avatar and name (and uid) - return esUser.profile.fillAvatars([{pubkey: $scope.formData.issuer}]) - .then(function (idties) { - return idties[0]; - }); - }) - .then(function(member) { - $scope.issuer = member; - - // Set Motion (only direct children, to exclude .lazy-load children) - $timeout(function () { - UIUtils.motion.fadeSlideIn({ - startVelocity: 3000 - }); - }, 10); - }) - .catch(UIUtils.onError('MESSAGE.ERROR.LOAD_MESSAGE_FAILED')); + return $scope.loadWallet() + .then(function() { + return esMessage.get({id: id}); }) - .catch(function(err){ - if (err === 'CANCELLED') { - $ionicHistory.nextViewOptions({ - historyRoot: true - }); - $state.go('app.user_message'); + .catch(UIUtils.onError('MESSAGE.ERROR.LOAD_MESSAGE_FAILED')) + .then(function(message) { + if (!message.valid) { + return UIUtils.alert.error(!$scope.isUserPubkey(message.recipient) ? 'MESSAGE.ERROR.USER_NOT_RECIPIENT' : 'MESSAGE.ERROR.NOT_AUTHENTICATED_MESSAGE', + 'MESSAGE.ERROR.MESSAGE_NOT_READABLE') + .then(function () { + $state.go('app.user_message'); + }); } + + // Load avatar and name (and uid) + return esUser.profile.fillAvatars([{pubkey: message.issuer}]) + .then(function (idties) { + $scope.issuer = idties[0]; + return message; + }); }); }; diff --git a/www/plugins/es/js/entities/notification.js b/www/plugins/es/js/entities/notification.js index a628e7593f10f5bcfb6569f3f468949510a25b3b..8d0636a993ede26cfca0d48b50fdb490be4a8bee 100644 --- a/www/plugins/es/js/entities/notification.js +++ b/www/plugins/es/js/entities/notification.js @@ -32,6 +32,16 @@ function Notification(json, onReadCallback) { // TX if (json.code.startsWith('TX_')) { that.icon = 'ion-card'; + var pubkeys = json.params.length > 1 ? json.params[1] : null; + if (pubkeys && pubkeys.indexOf(',') == -1) { + /*that.state = 'app.wot_view_identity'; + that.stateParams = { + pubkey: pubkeys, + uid: json.params[0] + };*/ + that.pubkey = pubkeys; + that.name = json.params[0]; + } } // member @@ -87,6 +97,6 @@ function Notification(json, onReadCallback) { } // error message else if (json.type == 'ERROR') { - that.icon = 'ion-alert'; + that.icon = 'ion-alert-circled assertive'; } } diff --git a/www/plugins/es/js/services/message-services.js b/www/plugins/es/js/services/message-services.js index 668384fc15a558d6cb8680a47f467b203efbcc88..4063c9e097c88084fca46f5265f07ede359ed2c7 100644 --- a/www/plugins/es/js/services/message-services.js +++ b/www/plugins/es/js/services/message-services.js @@ -34,7 +34,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' function onWalletInit(data) { data.messages = data.messages || {}; - data.messages.count = null; + data.messages.unreadCount = null; } function onWalletReset(data) { @@ -54,25 +54,21 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' return deferred.promise; } - var lastMessageTime = csSettings.data && csSettings.data.plugins && csSettings.data.plugins.es ? - csSettings.data.plugins.es.lastMessageTime : - undefined; - - // Count new messages - countNewMessages(data.pubkey, lastMessageTime) - .then(function(count){ + // Count unread messages + countUnreadMessages(data.pubkey) + .then(function(unreadCount){ data.messages = data.messages || {}; - data.messages.count = count; - console.debug('[ES] [message] Detecting ' + count + (lastMessageTime ? ' unread' : '') + ' messages'); + data.messages.unreadCount = unreadCount; + console.debug('[ES] [message] Detecting ' + unreadCount + ' unread messages'); deferred.resolve(data); }) .catch(function(err){ + console.error('Error chile counting message: ' + (err.message ? err.message : err)); deferred.resolve(data); }); return deferred.promise; } - function getBoxKeypair(keypair) { keypair = keypair || (csWallet.isLogin() ? csWallet.data.keypair : keypair); if (!keypair) { @@ -88,25 +84,26 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' return csWallet.data.keypair; } - function countNewMessages(pubkey, fromTime) { + function countUnreadMessages(pubkey) { pubkey = pubkey || (csWallet.isLogin() ? csWallet.data.pubkey : pubkey); if (!pubkey) { throw new Error('no pubkey, and user not connected.'); } var request = { - size: 0, - query: {constant_score: {filter: [{term: {recipient: pubkey}}]}} + query: { + bool: { + must: [ + {term: {recipient: pubkey}}, + {missing: { field : "read_signature" }} + ] + } + } }; - // Add time filter - if (fromTime) { - request.query.constant_score.filter.push({range: {time: {gt: fromTime}}}); - } - - return esHttp.post(host, port, '/message/record/_search')(request) + return esHttp.post(host, port, '/message/record/_count')(request) .then(function(res) { - return res.hits ? res.hits.total : 0; + return res.count; }); } @@ -195,6 +192,9 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' msg.id = hit._id; msg.pubkey = msg.issuer !== walletPubkey ? msg.issuer : msg.recipient; + msg.read = !!msg.read_signature; + delete msg.read_signature; + // Get uid (if member) return BMA.wot.member.get(msg.pubkey) .then(function(user) { @@ -269,6 +269,22 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' }); } + // Mark a message as read + function markMessageAsRead(message) { + if (message.read) { + var deferred = $q.defer(); + deferred.resolve(); + return deferred.promise; + } + message.read = true; + csWallet.data.messages = csWallet.data.messages || {}; + csWallet.data.messages.unreadCount = csWallet.data.messages.unreadCount ? csWallet.data.messages.unreadCount-1 : 0; + return CryptoUtils.sign(message.hash, csWallet.data.keypair) + .then(function(signature){ + return esHttp.post(host, port, '/message/record/:id/_read')(signature, {id:message.id}) + }); + } + function removeListeners() { console.debug("[ES] Disable message extension"); @@ -326,6 +342,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.services', ' get: getAndDecrypt, send: sendMessage, remove: removeMessage, + markAsRead: markMessageAsRead, fields: { commons: fields.commons } diff --git a/www/plugins/es/js/services/user-services.js b/www/plugins/es/js/services/user-services.js index 6726be9482481404c1373b3451895e9e5e307cb8..b81f8876d89c79a4e13b28daaafaba700f0a5612 100644 --- a/www/plugins/es/js/services/user-services.js +++ b/www/plugins/es/js/services/user-services.js @@ -160,7 +160,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se } // Load unread notifications count - function loadUnreadNotificationsCount(pubkey) { + function loadUnreadNotificationsCount(pubkey, readTime) { var request = { query: { bool: { @@ -172,6 +172,7 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se } }; + // Filter codes var excludesCodes = []; if (!csSettings.getByPath('plugins.es.notifications.txSent', false)) { excludesCodes.push('TX_SENT'); @@ -183,6 +184,11 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se request.query.bool.must_not = {terms: { code: excludesCodes}}; } + // Filter time + if (readTime) { + request.query.bool.must.push({range: {time: {gte: readTime}}}); + } + return esHttp.post(host, port, '/user/event/_count')(request) .then(function(res) { return res.count; @@ -204,13 +210,13 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se sort : [ { "time" : {"order" : "desc"}} ], - from:from, + from: from, size: size, _source: ["type", "code", "params", "reference", "recipient", "time", "hash", "read_signature"] }; + // Filter codes var excludesCodes = []; - if (!csSettings.getByPath('plugins.es.notifications.txSent', false)) { excludesCodes.push('TX_SENT'); } @@ -224,21 +230,14 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se return esHttp.post(host, port, '/user/event/_search')(request) .then(function(res) { if (!res.hits || !res.hits.total) return; - var unreadCount = 0; - var history = res.hits.hits.reduce(function(res, hit) { + return res.hits.hits.reduce(function(res, hit) { var item = new Notification(hit._source, markNotificationAsRead); item.id = hit._id; - unreadCount = item.read ? unreadCount : unreadCount+1; return res.concat(item) }, []); - return { - history: history, - unreadCount: unreadCount - }; }); } - // Mark a notification as read function markNotificationAsRead(notification) { return CryptoUtils.sign(notification.hash, csWallet.data.keypair) @@ -274,7 +273,6 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se } console.debug('[ES] [user] Loading user data from ES node...'); - $q.all([ // Load settings loadSettings(data.pubkey, data.keypair) @@ -290,9 +288,12 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se }), // Load unread notifications count - loadUnreadNotificationsCount(data.pubkey) + loadUnreadNotificationsCount( + data.pubkey, + csSettings.data.wallet ? csSettings.data.wallet.notificationReadTime : 0) .then(function(unreadCount) { data.notifications.unreadCount = unreadCount; + data.notifications.history = null; // remove list (usefull when settings changed) }), // Load profile avatar and name @@ -340,16 +341,24 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se } // Load user notifications - loadNotifications(data.pubkey, options.notifications.from, options.notifications.size) - .then(function(notifications) { - data.notifications.history = notifications.history; - data.notifications.unreadCount = notifications.unreadCount; - deferred.resolve(data); - }) - .catch(function(err) { - deferred.reject(err); - }) - ; + loadNotifications(data.pubkey, + options.notifications.from, + options.notifications.size) + .then(function(notifications) { + if (!notifications || !notifications.length || !options.notifications.from) { + data.notifications.history = notifications; + } + else { + // Concat (but keep original array - for data binding) + _.forEach(notifications, function(notification){ + data.notifications.history.push(notification); + }); + } + deferred.resolve(data); + }) + .catch(function(err) { + deferred.reject(err); + }); return deferred.promise; } @@ -542,6 +551,8 @@ angular.module('cesium.es.user.services', ['cesium.services', 'cesium.es.http.se .then(function() { // Change settings version csSettings.data.time = record.time; + // Force notifications reload + csWallet.data.notifications.history = []; restoringSettings = true; csSettings.store(); console.debug('[ES] [user] User settings saved in ES'); diff --git a/www/plugins/es/templates/menu_extend.html b/www/plugins/es/templates/menu_extend.html index 3dca9306de2f8a284563d59a77ab551d3d99449d..2364449407345ffa3b2e50addba9da510ac53233 100644 --- a/www/plugins/es/templates/menu_extend.html +++ b/www/plugins/es/templates/menu_extend.html @@ -9,8 +9,8 @@ active-link-path-prefix="#/app/user/message" ng-click="loginAndGo('app.user_message')"> <span - ng-if="$root.walletData.messages.count" - class="badge badge-button badge-positive">{{$root.walletData.messages.count}}</span> + ng-if="$root.walletData.messages.unreadCount" + class="badge badge-button badge-positive">{{$root.walletData.messages.unreadCount}}</span> </button> </ng-if> diff --git a/www/plugins/es/templates/message/view_message.html b/www/plugins/es/templates/message/view_message.html index 78d32205b1daddb0969c6142b019dce303f54a73..47feda00d4103d98e191c9058cf6b53ea306c5ee 100644 --- a/www/plugins/es/templates/message/view_message.html +++ b/www/plugins/es/templates/message/view_message.html @@ -1,4 +1,4 @@ -<ion-view left-buttons="leftButtons"> +<ion-view left-buttons="leftButtons" class="view-message"> <ion-nav-title> <span translate>MESSAGE.VIEW.TITLE</span> </ion-nav-title> diff --git a/www/templates/common/item_notification.html b/www/templates/common/item_notification.html index 66057637d7d20e777dc8ae3b9f85466819293fc6..51a524da251b6b1450b53be4f64b86b0b6d808fd 100644 --- a/www/templates/common/item_notification.html +++ b/www/templates/common/item_notification.html @@ -3,7 +3,7 @@ ng-class="{'unread': !notification.read}"> <img ng-src="{{::notification.thumbnail.src}}" ng-if="notification.thumbnail"></img> <i class="item-image {{::notification.icon}}" ng-if="!notification.thumbnail"></i> - <span ng-bind-html="notification.message|translate:notification.messageParams"></span> + <span trust-as-html="notification.message | translate:notification.messageParams"></span> <h4> <span class="dark"><i class="icon ion-clock"></i> {{notification.time|formatFromNow}}</span> <span class="gray">| {{notification.time|formatDate}}</span> diff --git a/www/templates/common/popover_notification.html b/www/templates/common/popover_notification.html index a41caab952bbad7bf1e56b64e589a4879ca2c7b0..87eef3b81dddf2dbefd99628d6c6782e6cd3f729 100644 --- a/www/templates/common/popover_notification.html +++ b/www/templates/common/popover_notification.html @@ -16,11 +16,11 @@ COMMON.NOTIFICATIONS.NO_RESULT </div> <ion-list> - <a ng-repeat="notification in search.results" + <div ng-repeat="notification in search.results" ng-click="closePopover(notification)"> <ng-include src="'templates/common/item_notification.html'"></ng-include> - </a> + </div> </ion-list> </ion-content> diff --git a/www/templates/common/view_notifications.html b/www/templates/common/view_notifications.html index 39d44589eacb20799ca0bf87bd5e2c67e7ae1bdb..527deffab5ad1f82883ad3a9bfd3085004c70e6c 100644 --- a/www/templates/common/view_notifications.html +++ b/www/templates/common/view_notifications.html @@ -1,4 +1,11 @@ -<ion-view view-title="{{'COMMON.NOTIFICATIONS.TITLE' | translate}}" id="notification"> +<ion-view left-buttons="leftButtons" + class="pane" + cache-view="false" + id="notification"> + <ion-nav-title> + {{'COMMON.NOTIFICATIONS.TITLE' | translate}} + </ion-nav-title> + <ion-content class="padding no-padding-xs" scroll="true"> <!-- Buttons bar--> @@ -25,10 +32,10 @@ <div class="list animate-fade-slide-in-right"> - <a ng-repeat="notification in search.results" + <div ng-repeat="notification in search.results" ng-click="onSelect(notification)"> <ng-include src="'templates/common/item_notification.html'"></ng-include> - </a> + </div> <!-- show more items --> <div class="item padding done in" ng-if="search.loadingMore"> diff --git a/www/templates/menu.html b/www/templates/menu.html index 695c4064b0bcafb4d4b12c4883f7ee27255a0254..15bfe78d00f46ee1d4708a6a063f11abadfceb85 100644 --- a/www/templates/menu.html +++ b/www/templates/menu.html @@ -17,6 +17,7 @@ <button class="button button-clear hidden-xs hidden-sm icon ion-android-notifications" ng-if="$root.login" active-link="gray" + href="#/app/notifications" ng-click="showNotificationsPopover($event)"> <span ng-if="$root.walletData.notifications.unreadCount"