chatview: improve timestamp display.

Timestamps are displayed as group likes "just now", "1 hour ago", etc.

Change-Id: I39c3482615c0e3fa4cef01ef29b355785c203626
Reviewed-by: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
diff --git a/web/chatview.html b/web/chatview.html
index b66764a..6490020 100644
--- a/web/chatview.html
+++ b/web/chatview.html
@@ -58,24 +58,62 @@
     }
 }
 
+/*
+ * Update timestamps messages
+ */
+function updateView() {
+    if (ring.chatview) ring.chatview.updateTimestamps();
+}
+setInterval(updateView, 60000);
+
 var ring = {}; // ring namespace
 
 ring.chatview = (function(){
+    const avatar_size = 35;
     var dev = {}; // ring.chatview.dev namespace
     var raf = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
     var messages = document.querySelector("#messages");
 
     /**
+     * Transform a date to a string group likes 1 hour ago.
+     */
+    function formatDate(date) {
+        const seconds = Math.floor((new Date() - date) / 1000);
+        var interval = Math.floor(seconds / (3600 * 24));
+        if (interval > 5) {
+            return date.toLocaleString();
+        }
+        if (interval > 1) {
+            return interval + ' days ago';
+        }
+        if (interval === 1) {
+            return interval + ' day ago';
+        }
+        interval = Math.floor(seconds / 3600);
+        if (interval > 1) {
+            return interval + ' hours ago';
+        }
+        if (interval === 1) {
+            return interval + ' hour ago';
+        }
+        interval = Math.floor(seconds / 60);
+        if (interval > 1) {
+            return interval + ' minutes ago';
+        }
+        return 'just now';
+    }
+
+    /**
      * Send #sendMessage #message value
      */
      function sendMessage()
      {
-       var input = document.querySelector("#sendMessage #message");
-       var message = input.value;
-       if (message.length > 0) {
-         input.value = '';
-         window.prompt(message);
-       }
+         var input = document.querySelector("#sendMessage #message");
+         var message = input.value;
+         if (message.length > 0) {
+             input.value = '';
+             window.prompt(message);
+         }
      }
 
     /**
@@ -143,9 +181,72 @@
     /**
      * Returns the message date, formatted for display
      */
-    function getMessageTimestampText(message_timestamp)
+    function getMessageTimestampText(message_timestamp, custom_format)
     {
-        return new Date(1000 * message_timestamp).toLocaleString();
+      const date = new Date(1000 * message_timestamp);
+      if(custom_format) {
+          return formatDate(date);
+      } else {
+          return date.toLocaleString();
+      }
+    }
+
+    /**
+     * Merge timestamps if they are from the same group (likes: "1 hour ago")
+     */
+    function cleanPreviousTimestamps (baseNode, endIndex) {
+        // Remove previous elements with the same formatted timestamp
+        for (var c = endIndex - 1 ; c >= 0 ; --c) {
+            const child = messages.children[c];
+            if (child.className.indexOf('timestamp') !== -1) {
+                if (child.className === baseNode.className &&
+                child.innerHTML === baseNode.innerHTML) {
+                    messages.removeChild(child);
+                } else {
+                    break; // A different timestamp is met, we can stop here.
+                }
+            }
+        }
+    }
+
+    /**
+     * Update padding if the sender image is displayed
+     */
+    function updateTimestampPadding (timestampNode, senderImage, direction) {
+        var new_padding = 20;
+        if (timestampNode.className.indexOf(`timestamp_${direction}`) &&
+          senderImage &&
+          senderImage.offsetHeight === avatar_size) {
+            new_padding += avatar_size;
+        }
+
+        if (direction == 'out')
+            timestampNode.style.paddingRight = new_padding;
+        else
+            timestampNode.style.paddingLeft = new_padding;
+    }
+
+    /**
+     * Update timestamps
+     */
+    function updateTimestamps() {
+        const timestamps = messages.querySelectorAll('.timestamp');
+        const image_out = messages.querySelector('.message_out .sender_image')
+        const image_in = messages.querySelector('.message_in .sender_image')
+        if (timestamps) {
+            for ( var c = 0 ; c < messages.children.length ; ++c) {
+              const child = messages.children[c];
+              if (child.className.indexOf('timestamp') !== -1) {
+                    // Update timestamp
+                    child.innerHTML = getMessageTimestampText(child.getAttribute('message_timestamp'), true)
+                    // Update padding
+                    updateTimestampPadding (child, image_out, 'out');
+                    updateTimestampPadding (child, image_in, 'in');
+                    // Remove previous elements with the same formatted timestamp
+                    cleanPreviousTimestamps(child, c);
+                }
+            }
+        }
     }
 
    /**
@@ -220,6 +321,28 @@
             chatview_message_div.appendChild(chatview_message_delivery_status);
             messages.appendChild(chatview_message_div);
 
+            // Get last message
+            const items = messages.querySelectorAll(".message");
+
+            // Add message
+            messages.appendChild(chatview_message_div);
+            // Get timestamp to add
+            const formattedTimestamp = getMessageTimestampText(message_timestamp, true);
+            // Create the timestamp object
+            const date_elt = document.createElement('div');
+            date_elt.innerHTML = formattedTimestamp;
+            timestamp_div_classes = [
+                "timestamp",
+                "timestamp_" + message_direction
+            ];
+            date_elt.setAttribute("class", timestamp_div_classes.join(" "));
+            date_elt.setAttribute("message_timestamp", message_timestamp);
+            // Remove last timestamp if it's the same
+            if (messages.querySelectorAll(".timestamp"))
+                cleanPreviousTimestamps(date_elt, messages.children.length);
+            // Add the new timestamp
+            messages.appendChild(date_elt);
+
         } else {
 
             chatview_message_div = document.querySelector("#message_" + message_id);
@@ -245,12 +368,12 @@
         chatview_message_timestamp.textContent = getMessageTimestampText(message_timestamp);
 
         if (new_message) {
-            chatview_message_div.querySelector(".message_wrapper").appendChild(chatview_message_timestamp);
-
             if (message_direction === "out") {
                 chatview_sentCheckmark.innerHTML = sentAnimation;
                 chatview_message_div.querySelector(".message_wrapper").appendChild(chatview_sentCheckmark);
             }
+
+            chatview_message_div.querySelector(".message_wrapper").appendChild(chatview_message_timestamp);
         }
 
         if (message_direction === "out") {
@@ -258,6 +381,8 @@
                 chatview_message_div.classList.add("message--sent");
             }
         }
+
+        updateTimestamps();
     }
 
     /**