From 744fcf61cf9f2febaabf460cf7898ca6571030ee Mon Sep 17 00:00:00 2001
From: blavenie <benoit.lavenier@e-is.pro>
Date: Tue, 19 Sep 2017 18:46:35 +0200
Subject: [PATCH] [enh] Parse URL in description or message - fix #551 [fix]
 Update message list when delete/sent/received message - fix #562

---
 www/js/config.js                              | 53 ++++++------
 www/js/controllers/app-controllers.js         |  1 +
 .../es/js/controllers/message-controllers.js  | 65 ++++++++++++--
 www/plugins/es/js/services/http-services.js   | 23 +++--
 .../es/js/services/message-services.js        | 85 ++++++++++++-------
 .../es/templates/message/view_message.html    |  3 +-
 6 files changed, 157 insertions(+), 73 deletions(-)

diff --git a/www/js/config.js b/www/js/config.js
index 626523b1c..c60394490 100644
--- a/www/js/config.js
+++ b/www/js/config.js
@@ -10,53 +10,49 @@ angular.module("cesium.config", [])
 
 .constant("csConfig", {
 	"cacheTimeMs": 300000,
-	"fallbackLanguage": "en",
+	"fallbackLanguage": "fr-FR",
+	"defaultLanguage": "fr-FR",
 	"rememberMe": true,
 	"showUDHistory": false,
 	"timeout": 300000,
 	"timeWarningExpireMembership": 5184000,
 	"timeWarningExpire": 7776000,
-	"keepAuthIlde": 600,
 	"useLocalStorage": true,
-	"useRelative": false,
-	"expertMode": false,
+	"useRelative": true,
+	"expertMode": true,
 	"decimalCount": 2,
-	"httpsMode": false,
-	"shareBaseUrl": "https://g1.duniter.fr",
 	"helptip": {
-		"enable": true,
-		"installDocUrl": "https://github.com/duniter/duniter/blob/master/doc/install-a-node.md"
+		"enable": false,
+		"installDocUrl": {
+			"fr-FR": "http://www.le-sou.org/devenir-noeud/",
+			"en": "https://github.com/duniter/duniter/blob/master/doc/install-a-node.md"
+		}
 	},
 	"license": {
-		"fr-FR": "license/license_g1-fr-FR",
-		"en": "license/license_g1-en"
+		"fr-FR": "license/license_g1-fr-FR.txt",
+		"en": "license/license_g1-en.txt"
 	},
 	"node": {
-		"host": "g1.duniter.org",
-		"port": "443"
+		"host": "localhost",
+		"port": 9600
 	},
 	"fallbackNodes": [
 		{
-			"host": "g1.duniter.fr",
+			"host": "g1.duniter.org",
 			"port": "443"
 		},
 		{
-			"host": "g1.duniter.org",
+			"host": "g1.duniter.fr",
 			"port": "443"
 		}
 	],
-	"developers": [
-		{
-			"name": "Benoit Lavenier",
-			"pubkey": "38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE"
-		}
-	],
 	"plugins": {
 		"es": {
-			"enable": true,
+			"enable": false,
 			"askEnable": false,
-			"host": "g1.data.duniter.fr",
-			"port": "443",
+			"host": "localhost",
+			"port": 9200,
+			"wsPort": 9400,
 			"notifications": {
 				"txSent": true,
 				"txReceived": true,
@@ -64,10 +60,19 @@ angular.module("cesium.config", [])
 				"certReceived": true
 			},
 			"defaultCountry": "France"
+		},
+		"graph": {
+			"enable": true
+		},
+		"neo4j": {
+			"enable": true
+		},
+		"rml9": {
+			"enable": true
 		}
 	},
 	"version": "0.17.2",
-	"build": "2017-08-23T14:48:40.900Z",
+	"build": "2017-09-11T08:35:12.484Z",
 	"newIssueUrl": "https://github.com/duniter/cesium/issues/new?labels=bug"
 })
 
diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js
index 9689b00ba..a0a96b6db 100644
--- a/www/js/controllers/app-controllers.js
+++ b/www/js/controllers/app-controllers.js
@@ -71,6 +71,7 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $
 
   $scope.search = {};
   $scope.login = csWallet.isLogin();
+  $scope.auth = csWallet.isAuth();
   $scope.motion = UIUtils.motion.default;
 
   $scope.showHome = function() {
diff --git a/www/plugins/es/js/controllers/message-controllers.js b/www/plugins/es/js/controllers/message-controllers.js
index 741804a65..afcf229d9 100644
--- a/www/plugins/es/js/controllers/message-controllers.js
+++ b/www/plugins/es/js/controllers/message-controllers.js
@@ -60,7 +60,7 @@ angular.module('cesium.es.message.controllers', ['cesium.es.services'])
 
 ;
 
-function ESMessageListController($scope, $state, $translate, $ionicHistory, $ionicPopover,
+function ESMessageListController($scope, $state, $translate, $ionicHistory, $ionicPopover, $timeout,
                                  esModals, UIUtils, esMessage) {
   'ngInject';
 
@@ -178,8 +178,8 @@ function ESMessageListController($scope, $state, $translate, $ionicHistory, $ion
       .then(function() {
         UIUtils.loading.hide();
         return esModals.showMessageCompose(parameters)
-          .then(function(sent) {
-            if (sent) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT');
+          .then(function(id) {
+            if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT');
           });
       });
   };
@@ -232,6 +232,57 @@ function ESMessageListController($scope, $state, $translate, $ionicHistory, $ion
     }
   };
 
+  /* -- watch events (delete, received, sent) -- */
+
+  // Message deletion
+  $scope.onMessageDelete = function(id) {
+    var index = _.findIndex($scope.messages, function(msg) {
+      return msg.id == id;
+    });
+    if (index) {
+      $scope.messages.splice(index,1); // remove from messages array
+    }
+  };
+  esMessage.api.data.on.delete($scope, $scope.onMessageDelete);
+
+  // Watch user sent message
+  $scope.onNewOutboxMessage = function(id) {
+    if ($scope.type != 'outbox') return;
+    // Add message sent to list
+    $scope.loading = true;
+    return $timeout(function() {
+       // Load the message sent
+        return esMessage.get(id, {type: $scope.type, summary: true});
+      }, 500 /*waiting ES propagation*/)
+      .then(function(msg) {
+        $scope.messages.splice(0,0,msg);
+        $scope.loading = false;
+        $scope.motion.show({selector: '.view-messages .list .item'});
+      })
+      .catch(function() {
+        $scope.loading = false;
+      });
+  };
+  esMessage.api.data.on.sent($scope, $scope.onNewOutboxMessage);
+
+  // Watch received message
+  $scope.onNewInboxMessage = function(notification) {
+    if ($scope.type != 'inbox') return;
+    // Add message sent to list
+    $scope.loading = true;
+    console.log(notification);
+    // Load the the message
+    return esMessage.get(notification.id, {type: $scope.type, summary: true})
+      .then(function(msg) {
+        $scope.messages.splice(0,0,msg);
+        $scope.loading = false;
+        $scope.motion.show({selector: '.view-messages .list .item'});
+      })
+      .catch(function() {
+        $scope.loading = false;
+      });
+  };
+  esMessage.api.data.on.new($scope, $scope.onNewInboxMessage);
 
   // for DEV only
   /*$timeout(function() {
@@ -336,7 +387,7 @@ function ESMessageComposeModalController($scope, Modals, UIUtils, csWallet, esHt
       .then(function(id) {
         $scope.id=id;
         UIUtils.loading.hide();
-        $scope.closeModal(true);
+        $scope.closeModal(id);
       })
       .catch(UIUtils.onError('MESSAGE.ERROR.SEND_MSG_FAILED'));
   };
@@ -432,7 +483,7 @@ function ESMessageViewController($scope, $state, $timeout, $translate, $ionicHis
 
     return $scope.loadWallet({minData: true})
       .then(function() {
-        return esMessage.get({type: type, id: id});
+        return esMessage.get(id, {type: type});
       })
       .catch(UIUtils.onError('MESSAGE.ERROR.LOAD_MESSAGE_FAILED'))
       .then(function(message) {
@@ -592,8 +643,8 @@ function PopoverMessageController($scope, UIUtils, $state, csWallet, esHttp, esM
   $scope.showNewMessageModal = function(parameters) {
     $scope.closePopover();
     return esModals.showMessageCompose(parameters)
-      .then(function(sent) {
-        if (sent) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT');
+      .then(function(id) {
+        if (id) UIUtils.toast.show('MESSAGE.INFO.MESSAGE_SENT');
       });
   };
 
diff --git a/www/plugins/es/js/services/http-services.js b/www/plugins/es/js/services/http-services.js
index 101aacade..0d48358ea 100644
--- a/www/plugins/es/js/services/http-services.js
+++ b/www/plugins/es/js/services/http-services.js
@@ -168,7 +168,7 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic
           tags.push(tag);
         }
         value = value.substr(matches.index + matches[1].length + 1);
-        matches = value && reg.exec(value);
+        matches = value.length > 0 && reg.exec(value);
       }
       return tags;
     }
@@ -194,10 +194,22 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic
     }
 
     function trustAsHtml(text, options) {
-      var content = text ? escape(text.trim()).replace(/\n/g,'<br>') : undefined;
+
+
+      var content = text ? escape(text.trim()) : undefined;
       if (content) {
         options = options || {};
         options.tagState = options.tagState || 'app.wot_lookup';
+        if (options.newLine || !angular.isDefined(options.newLine)) {
+          content = content.replace(/\n/g, '<br>\n');
+        }
+
+        // Replace URL in description
+        var urls = parseUrlsFromText(content);
+        _.forEach(urls, function(url){
+          var link = '<a href=\"{0}\" target=\"_system\">{1}</a>'.format(url, url);
+          content = content.replace(url, link);
+        });
 
         // Replace hashtags
         var hashTags = parseTagsFromText(content);
@@ -217,13 +229,6 @@ angular.module('cesium.es.http.services', ['ngResource', 'ngApi', 'cesium.servic
           content = content.replace('@'+tag, link);
         });
 
-        // Replace user tags in description
-        var urls = parseUrlsFromText(content);
-        _.forEach(urls, function(url){
-          var link = '<a href=\"{0}\" target=\"_system\">{1}</a>'.format(url, url);
-          content = content.replace(url, link);
-        });
-
         $sce.trustAsHtml(content);
       }
       return content;
diff --git a/www/plugins/es/js/services/message-services.js b/www/plugins/es/js/services/message-services.js
index b35485590..fd2f24bc4 100644
--- a/www/plugins/es/js/services/message-services.js
+++ b/www/plugins/es/js/services/message-services.js
@@ -111,21 +111,25 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
 
   function sendMessage(message, keypair) {
     return doSendMessage(message, keypair)
-      .then(function(sendResult){
+      .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 sendResult;
+        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);
-          })
-          .then(function() {
-            return sendResult;
+            return res; // the first result
           });
+      })
+      .then(function(res) {
+        // Raise event
+        api.data.raise.sent(res);
+
+        return res;
       });
   }
 
@@ -235,8 +239,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
 
       // Add avatar
       .then(function(messages){
-        var senderPkField = (options.type == 'inbox') ? 'issuer' : 'recipient';
-        return csWot.extendAll(messages, senderPkField);
+        var avatarField = (options.type == 'inbox') ? 'issuer' : 'recipient';
+        return csWot.extendAll(messages, avatarField);
       })
 
       // Update message count
@@ -248,29 +252,35 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
       });
   }
 
-  function getAndDecrypt(params, keypair) {
-    params.type = params.type || 'inbox';
-    var avatarField = (params.type == 'inbox') ? 'issuer' : 'recipient';
-    return raw.getByTypeAndId(params)
-      .then(function(hit) {
-        if (!hit.found) {
-          return;
-        }
-        var msg = hit._source;
-        msg.id = hit._id;
-        msg.read = (params.type == 'outbox') || !!msg.read_signature;
-        delete msg.read_signature; // not need anymore
-
-        // Decrypt message
-        return decryptMessages([msg], keypair, false/*summary not need*/)
-          .then(function(){
-            // Fill avatar
-            return csWot.extendAll([msg], avatarField);
-          })
-          .then(function() {
-            return msg;
+  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
+
+            // 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);
+              });
           });
       });
+
   }
 
   function decryptMessages(messages, keypair, withSummary) {
@@ -314,7 +324,7 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
                   fillSummary(message);
                 }
                 else if (content){
-                  message.content = esHttp.util.trustAsHtml(content);
+                  message.html = esHttp.util.trustAsHtml(content);
                 }
               })
               .catch(function(err){
@@ -351,6 +361,9 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
           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;
       });
   }
@@ -365,18 +378,26 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
           .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 () {
+          .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);
           });
       });
   }
@@ -511,6 +532,8 @@ angular.module('cesium.es.message.services', ['ngResource', 'cesium.platform',
 
   // Register extension points
   api.registerEvent('data', 'new');
+  api.registerEvent('data', 'delete');
+  api.registerEvent('data', 'sent');
 
   // Default action
   csPlatform.ready().then(function() {
diff --git a/www/plugins/es/templates/message/view_message.html b/www/plugins/es/templates/message/view_message.html
index afb4ef5e4..9b4eca760 100644
--- a/www/plugins/es/templates/message/view_message.html
+++ b/www/plugins/es/templates/message/view_message.html
@@ -80,8 +80,7 @@
 
           <!-- content -->
           <ion-item>
-            <p>
-              <span class="text-keep-lines" ng-bind-html="formData.content"></span>
+            <p ng-bind-html="formData.html">
             </p>
 
             <div class="padding gray" ng-if="!formData.content" translate>
-- 
GitLab