From 3be80255fb20a9c3eeb03082bba140b5835b07bc Mon Sep 17 00:00:00 2001
From: Benoit Lavenier <benoit.lavenier@e-is.pro>
Date: Wed, 4 Mar 2020 19:04:18 +0100
Subject: [PATCH] [enh] Home: add a json feed reader, to be able to publish
 news [fix] Home: fix layout (vertical scroll) [fix] Like: fix access to
 constants KINDS

---
 app/config.json                               |  76 +-----
 scss/ionic.app.scss                           |  53 ++++
 www/css/style.css                             |  16 +-
 www/feed.json                                 |  35 +++
 www/i18n/locale-en-GB.json                    |   7 +-
 www/i18n/locale-en.json                       |   7 +-
 www/i18n/locale-fr-FR.json                    |   5 +-
 www/js/config.js                              |  62 +++--
 www/js/controllers/app-controllers.js         |  65 ++++-
 www/js/services/settings-services.js          |   7 +
 www/js/services/wot-services.js               |   2 +-
 .../es/js/controllers/like-controllers.js     |   2 +-
 .../es/js/controllers/wot-controllers.js      |   4 +-
 .../es/templates/network/view_es_peer.html    |   2 +-
 www/templates/api/home.html                   |   2 +-
 www/templates/api/transfer.html               |   2 +-
 www/templates/home/home.html                  | 230 +++++++++++-------
 www/templates/network/view_peer.html          |   2 +-
 .../wot/tabs/tab_received_certifications.html |   2 +-
 19 files changed, 373 insertions(+), 208 deletions(-)
 create mode 100644 www/feed.json

diff --git a/app/config.json b/app/config.json
index 545c4299c..a64d8caf2 100644
--- a/app/config.json
+++ b/app/config.json
@@ -27,6 +27,13 @@
       "es-ES": "license/license_g1-es-ES",
       "eo-EO": "license/license_g1-eo-EO"
     },
+    "feed": {
+      "jsonFeed": {
+        "fr-FR": "feed.json",
+        "en": "feed.json"
+      },
+      "maxContentLength": 650
+    },
     "node": {
       "host": "g1.duniter.org",
       "port": 443
@@ -162,75 +169,6 @@
     }
   },
 
-  "le-sou": {
-    "cacheTimeMs": 300000,
-    "fallbackLanguage": "fr-FR",
-    "defaultLanguage": "fr-FR",
-    "rememberMe": true,
-    "timeout": 30000,
-    "timeWarningExpireMembership": 5184000,
-    "timeWarningExpire": 7776000,
-    "keepAuthIdle": 600,
-    "useLocalStorage": true,
-    "useRelative": false,
-    "expertMode": false,
-    "decimalCount": 2,
-    "httpsMode": false,
-    "shareBaseUrl": "https://g1.le-sou.org",
-    "helptip": {
-      "enable": true,
-      "installDocUrl": {
-        "fr-FR": "https://www.le-sou.org/devenir-noeud/",
-        "en": "https://duniter.org/en/wiki/duniter/install/"
-      }
-    },
-    "license": {
-      "fr-FR": "license/license_g1-fr-FR",
-      "en": "license/license_g1-en"
-    },
-    "node": {
-      "host": "g1.le-sou.org",
-      "port": 443
-    },
-    "fallbackNodes": [
-      {
-        "host": "g1.duniter.org",
-        "port": 443
-      },
-      {
-        "host": "g1.duniter.fr",
-        "port": 443
-      }
-    ],
-    "plugins":{
-      "es": {
-        "enable": true,
-        "askEnable": true,
-        "useRemoteStorage": true,
-        "host": "g1.data.le-sou.org",
-        "port": 443,
-        "fallbackNodes": [
-          {
-            "host": "g1.data.le-sou.org",
-            "port": 443
-          },
-          {
-            "host": "g1.data.duniter.fr",
-            "port": 443
-          }
-        ],
-        "notifications": {
-          "txSent": true,
-          "txReceived": true,
-          "certSent": true,
-          "certReceived": true
-        },
-        "defaultCountry": "France"
-      }
-    }
-  },
-
-
   "g1-test": {
     "cacheTimeMs": 300000,
     "fallbackLanguage": "en",
diff --git a/scss/ionic.app.scss b/scss/ionic.app.scss
index 868ee51ba..b4146080f 100644
--- a/scss/ionic.app.scss
+++ b/scss/ionic.app.scss
@@ -2549,3 +2549,56 @@ div[dropzone]:hover {
   user-select: none !important;
   pointer-events: none;
 }
+
+/* -- feed (home page) -- */
+.feed {
+  .card {
+    background-color: rgba(0,0,0,0.3);
+    color: lightgrey;
+  }
+
+  h1, h2, h3, h4, h5 {
+    color: white !important;
+  }
+
+  ul {
+    list-style: unset;
+    padding-left: 40px;
+  }
+
+  .feed_header,
+  .card .header {
+    height: 25px;
+    color: grey !important;
+    a  {
+      color: inherit;
+    }
+    .avatar {
+      margin-top: -6px;
+      margin-left: -6px;
+      height: 30px;
+      width: 30px;
+      border: 1px solid $positive;
+    }
+    .avatar-left-padding {
+      padding-left: 30px;
+    }
+  }
+
+  .feed-title,
+  .card .title {
+    margin-top: 5px;
+    font-size: 18pt;
+    a {
+      color: white !important;;
+    }
+  }
+
+  .feed-content,
+  .card .content {
+    text-align: start;
+    color: lightgrey !important;
+  }
+
+}
+
diff --git a/www/css/style.css b/www/css/style.css
index 3cb65f89e..7f6bd56b2 100644
--- a/www/css/style.css
+++ b/www/css/style.css
@@ -10,24 +10,14 @@
     line-height: inherit;
 }
 
-#home h1 {
+#home .main-container h1 {
     padding-top: 15px;
     text-align: center;
 }
-
-#home h2 {
-    font-size: 22px;
-    padding-top: 15px;
-    padding-bottom: 15px;
-    text-align: center;
+#home .main-container h4 {
     color: #fff;
 }
-
-#home h4 {
-    color: #fff;
-}
-
-#home h4 a {
+#home .main-container h4 a {
   color: inherit;
 }
 
diff --git a/www/feed.json b/www/feed.json
new file mode 100644
index 000000000..9c71e6821
--- /dev/null
+++ b/www/feed.json
@@ -0,0 +1,35 @@
+{
+  "version": "https://jsonfeed.org/version/1",
+  "user_comment": "This feed allows you to read the posts from this site in any feed reader that supports the JSON Feed format. To add this feed to your reader, copy the following URL — https://jsonfeed.org/feed.json — and add it your reader.",
+  "title": "Actualités",
+  "description": "Cesium News",
+  "home_page_url": "https://forum.monnaie-libre.fr/tag/cesium",
+  "feed_url": "/feed.json",
+  "author": {
+    "name": "Benoit Lavenier",
+    "url": "@BenoitLavenier",
+    "avatar": "http://localhost:9200/user/profile/38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE/_image/avatar.png"
+  },
+  "items": [
+    {
+      "title": "Fermeture prochaine de Cesium-web",
+      "author": {
+        "name": "Moul",
+        "url": "@moul",
+        "avatar": "https://forum.monnaie-libre.fr/user_avatar/forum.monnaie-libre.fr/moul/45/1246_2.png"
+      },
+      "date_published": "2020-02-07T09:42:00+01:00",
+      "id": "https://forum.monnaie-libre.fr/t/fermeture-prochaine-de-cesium-web-1er-mai/9474",
+      "url": "https://forum.monnaie-libre.fr/t/fermeture-prochaine-de-cesium-web-1er-mai/9474",
+      "content_html": "<p>Au <b>1er mai 2020</b>, il ne sera <b>plus possible de vous connecter à Ğ1 via la version web de Cesium</b> (Cesium-web), pour faire des transactions et certifier de nouveaux membres. Cesium-web restera cependant disponible en lecture, pour consulter vos comptes et vos certifications. Cette décision a été prise par les développeurs, en raison de potentielles failles de sécurité, qui pourraient affecter l’évolution de cette monnaie.</p><p>Le présent article a pour objectif : <ul><li>de vous présenter les causes et conséquences de cette décision,</li>\n<li>de détailler les procédures d’installation sur les différentes plateformes.</li></ul></p><p><h4>Pourquoi fermer Cesium-Web ?</h2></p><h5>Rappels concernant la Ğ1</h5><p>La monnaie libre Ğ1 est une monnaie cryptographique, c’est-à-dire qu’elle utilise des procédés de chiffrement pour garantir la légitimité de chaque transaction.</p>\n"
+    },
+    {
+      "title": "Un site officiel simple pour Cesium !",
+      "date_published": "2019-02-21T22:55:00+01:00",
+      "id": "https://cesium.app",
+      "url": "https://cesium.app",
+      "image": "https://cesium.app/i18n/fr_FR/contents/accueil/Cesium-G1-maquette.png",
+      "content_html": "<p><ul><li>Vous aimeriez vous inscrire à la Ğ1 (<i>June</i>), mais vous ne savez pas comment vous y prendre ?</li><li>Vous voulez savoir <b>comment utiliser</b> Cesium depuis votre smartphone ou ordinateur ?</li><li>On vous a dit que Cesium faisait aussi le café (en plus de gérer votre portefeuille en monnaie libre), mais vous n'en êtes pas sûr ? :-)</li></ul></p><p>Tutos, téléchargements, documentation: tout est désormais accessible depuis le <b>site officiel</b> : <b>https://cesium.app</b> !</p>"
+    }
+  ]
+}
diff --git a/www/i18n/locale-en-GB.json b/www/i18n/locale-en-GB.json
index 9aabaca37..a9e6b89b3 100644
--- a/www/i18n/locale-en-GB.json
+++ b/www/i18n/locale-en-GB.json
@@ -120,14 +120,17 @@
   "HOME": {
     "TITLE": "Cesium",
     "WELCOME": "Welcome to the Cesium Application!",
-    "MESSAGE": "Follow your {{currency|abbreviate}} wallets easily",
+    "MESSAGE": "Receive and send libre currency {{currency|abbreviate}}",
     "BTN_CURRENCY": "Explore currency",
     "BTN_ABOUT": "about",
     "BTN_HELP": "Help",
     "REPORT_ISSUE": "Report an issue",
     "NOT_YOUR_ACCOUNT_QUESTION" : "You do not own the account <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b>?",
     "BTN_CHANGE_ACCOUNT": "Disconnect this account",
-    "CONNECTION_ERROR": "Peer <b>{{server}}</b> unreachable or invalid address.<br/><br/>Check your Internet connection, or change node <a class=\"positive\" ng-click=\"doQuickFix('settings')\">in the settings</a>."
+    "CONNECTION_ERROR": "Peer <b>{{server}}</b> unreachable or invalid address.<br/><br/>Check your Internet connection, or change node <a class=\"positive\" ng-click=\"doQuickFix('settings')\">in the settings</a>.",
+    "SHOW_ALL_FEED": "Show all",
+    "READ_MORE": "Read more",
+    "FEED_SOURCE": "Source"
   },
   "SETTINGS": {
     "TITLE": "Settings",
diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json
index 7213317ac..bfca95881 100644
--- a/www/i18n/locale-en.json
+++ b/www/i18n/locale-en.json
@@ -120,14 +120,17 @@
   "HOME": {
     "TITLE": "Cesium",
     "WELCOME": "Welcome to the Cesium Application!",
-    "MESSAGE": "Follow your {{currency|abbreviate}} wallets easily",
+    "MESSAGE": "Receive and send libre currency {{currency|abbreviate}}",
     "BTN_CURRENCY": "Explore currency",
     "BTN_ABOUT": "about",
     "BTN_HELP": "Help",
     "REPORT_ISSUE": "Report an issue",
     "NOT_YOUR_ACCOUNT_QUESTION" : "You do not own the account <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b>?",
     "BTN_CHANGE_ACCOUNT": "Disconnect this account",
-    "CONNECTION_ERROR": "Peer <b>{{server}}</b> unreachable or invalid address.<br/><br/>Check your Internet connection, or change node <a class=\"positive\" ng-click=\"doQuickFix('settings')\">in the settings</a>."
+    "CONNECTION_ERROR": "Peer <b>{{server}}</b> unreachable or invalid address.<br/><br/>Check your Internet connection, or change node <a class=\"positive\" ng-click=\"doQuickFix('settings')\">in the settings</a>.",
+    "SHOW_ALL_FEED": "Show all",
+    "READ_MORE": "Read more",
+    "FEED_SOURCE": "Source"
   },
   "SETTINGS": {
     "TITLE": "Settings",
diff --git a/www/i18n/locale-fr-FR.json b/www/i18n/locale-fr-FR.json
index bded45dd5..1f472e583 100644
--- a/www/i18n/locale-fr-FR.json
+++ b/www/i18n/locale-fr-FR.json
@@ -127,7 +127,10 @@
     "REPORT_ISSUE": "anomalie",
     "NOT_YOUR_ACCOUNT_QUESTION" : "Vous n'êtes pas propriétaire du compte <b><i class=\"ion-key\"></i> {{pubkey|formatPubkey}}</b> ?",
     "BTN_CHANGE_ACCOUNT": "Déconnecter ce compte",
-    "CONNECTION_ERROR": "Nœud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifiez votre connexion Internet, ou changer de nœud <a class=\"positive\" ng-click=\"doQuickFix('settings')\">dans les paramètres</a>."
+    "CONNECTION_ERROR": "Nœud <b>{{server}}</b> injoignable ou adresse invalide.<br/><br/>Vérifiez votre connexion Internet, ou changer de nœud <a class=\"positive\" ng-click=\"doQuickFix('settings')\">dans les paramètres</a>.",
+    "SHOW_ALL_FEED": "Voir tout",
+    "READ_MORE": "Lire la suite",
+    "FEED_SOURCE": "Source"
   },
   "SETTINGS": {
     "TITLE": "Paramètres",
diff --git a/www/js/config.js b/www/js/config.js
index 9aae1c638..7cc4a6838 100644
--- a/www/js/config.js
+++ b/www/js/config.js
@@ -10,37 +10,54 @@ angular.module("cesium.config", [])
 
 .constant("csConfig", {
 	"cacheTimeMs": 300000,
-	"fallbackLanguage": "fr-FR",
-	"defaultLanguage": "fr-FR",
+	"fallbackLanguage": "en",
 	"rememberMe": true,
 	"showUDHistory": true,
-	"timeout": 300000,
+	"timeout": 40000,
 	"timeWarningExpireMembership": 5184000,
 	"timeWarningExpire": 7776000,
+	"keepAuthIdle": 600,
 	"useLocalStorage": true,
-	"useRelative": true,
-	"expertMode": true,
+	"useRelative": false,
+	"expertMode": false,
 	"decimalCount": 2,
+	"httpsMode": false,
+	"shareBaseUrl": "https://g1.duniter.fr",
 	"helptip": {
-		"enable": false,
+		"enable": true,
 		"installDocUrl": {
 			"fr-FR": "https://duniter.org/fr/wiki/duniter/installer/",
 			"en": "https://duniter.org/en/wiki/duniter/install/"
 		}
 	},
 	"license": {
-		"fr-FR": "license/license_g1-fr-FR",
 		"en": "license/license_g1-en",
+		"fr-FR": "license/license_g1-fr-FR",
 		"es-ES": "license/license_g1-es-ES",
 		"eo-EO": "license/license_g1-eo-EO"
 	},
+	"feed": {
+		"jsonFeed": {
+			"fr-FR": "feed.json",
+			"en": "feed.json"
+		},
+		"maxContentLength": 650
+	},
 	"node": {
-		"host": "g1.duniter.fr",
+		"host": "g1.duniter.org",
 		"port": 443
 	},
 	"fallbackNodes": [
 		{
-			"host": "g1.duniter.org",
+			"host": "g1.cgeek.fr",
+			"port": 443
+		},
+		{
+			"host": "g1.monnaielibreoccitanie.org",
+			"port": 443
+		},
+		{
+			"host": "g1.le-sou.org",
 			"port": 443
 		},
 		{
@@ -48,13 +65,19 @@ angular.module("cesium.config", [])
 			"port": 443
 		}
 	],
+	"developers": [
+		{
+			"name": "Benoit Lavenier",
+			"pubkey": "38MEAZN68Pz1DTvT3tqgxx4yQP6snJCQhPqEFxbDk4aE"
+		}
+	],
 	"plugins": {
 		"es": {
-			"enable": false,
-			"askEnable": false,
-			"host": "localhost",
-			"port": 9200,
-			"wsPort": 9400,
+			"enable": true,
+			"askEnable": true,
+			"useRemoteStorage": true,
+			"host": "g1.data.duniter.fr",
+			"port": 443,
 			"fallbackNodes": [
 				{
 					"host": "g1.data.le-sou.org",
@@ -72,19 +95,10 @@ angular.module("cesium.config", [])
 				"certReceived": true
 			},
 			"defaultCountry": "France"
-		},
-		"graph": {
-			"enable": true
-		},
-		"neo4j": {
-			"enable": true
-		},
-		"rml9": {
-			"enable": true
 		}
 	},
 	"version": "1.5.3",
-	"build": "2020-03-02T09:05:39.852Z",
+	"build": "2020-03-04T18:00:55.476Z",
 	"newIssueUrl": "https://git.duniter.org/clients/cesium-grp/cesium/issues/new"
 })
 
diff --git a/www/js/controllers/app-controllers.js b/www/js/controllers/app-controllers.js
index 806047b97..f0e6a97cc 100644
--- a/www/js/controllers/app-controllers.js
+++ b/www/js/controllers/app-controllers.js
@@ -443,6 +443,15 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $
     $event.stopPropagation();
     $event.preventDefault();
 
+    // Read URL like '@UID' (Used by home page, in feed's author url)
+    if (uri && uri.startsWith('@')) {
+      var uid = uri.substr(1);
+      if (BMA.regexp.USER_ID.test(uid)) {
+        $state.go('app.wot_identity_uid', {uid: uid});
+        return false;
+      }
+    }
+
     options = options || {};
 
     // If unable to open, just copy value
@@ -502,11 +511,12 @@ function AppController($scope, $rootScope, $state, $ionicSideMenuDelegate, $q, $
 }
 
 
-function HomeController($scope, $state, $timeout, $ionicHistory, $translate, UIUtils, csPlatform, csCurrency, csSettings) {
+function HomeController($scope, $state, $timeout, $ionicHistory, $translate, $http, UIUtils, csConfig, csPlatform, csCurrency, csSettings) {
   'ngInject';
 
   $scope.loading = true;
   $scope.locales = angular.copy(csSettings.locales);
+  $scope.smallscreen = UIUtils.screen.isSmall();
 
   $scope.enter = function(e, state) {
     if (ionic.Platform.isIOS()) {
@@ -533,10 +543,11 @@ function HomeController($scope, $state, $timeout, $ionicHistory, $translate, UIU
         notify: false});
     }
     else {
-      // Start platform
+      // Wait platform to be ready
       csPlatform.ready()
         .then(function() {
           $scope.loading = false;
+          $scope.loadFeeds();
         })
         .catch(function(err) {
           $scope.node =  csCurrency.data.node;
@@ -554,6 +565,55 @@ function HomeController($scope, $state, $timeout, $ionicHistory, $translate, UIU
     $timeout($scope.enter, 200);
   };
 
+  $scope.loadFeeds = function() {
+    var feedUrl = csSettings.getFeedUrl();
+    if (!feedUrl || typeof feedUrl !== 'string') return; // Skip
+
+    var maxContentLength = (csConfig.feed && csConfig.feed.maxContentLength) || 650;
+
+    var now = Date.now();
+    console.debug("[home] Loading feeds from {0}...".format(feedUrl));
+
+    $http.get(feedUrl, {responseType: 'json'})
+      .success(function(feed) {
+        console.debug('[home] Feeds loaded in {0}ms'.format(Date.now()-now));
+        if (!feed || !feed.items || !feed.items.length) return // skip if empty
+
+        feed.items = feed.items.reduce(function(res, item) {
+          if (!item || (!item.title && !item.content_text && !item.content_html)) return res; // Skip
+
+          // Convert UTC time
+          if (item.date_published) {
+            item.time = moment.utc(item.date_published).unix();
+          }
+          // Convert content to HTML
+          if (item.content_html) {
+            item.content = item.content_html;
+          }
+          else {
+            item.content = (item.content_text||'').replace(/\n/g, '<br/>');
+          }
+
+          // Trunc content, if need
+          if (maxContentLength !== -1 && item.content && item.content.length > maxContentLength) {
+            var endIndex = Math.max(item.content.lastIndexOf(" ", maxContentLength), item.content.lastIndexOf("<", maxContentLength));
+            item.content = item.content.substr(0, endIndex) + ' (...)';
+            item.truncated = true;
+          }
+
+          // If author is missing, copy the main author
+          item.author = item.author || feed.author;
+
+          return res.concat(item);
+        }, []);
+        $scope.feed = feed;
+      })
+      .error(function(data, status) {
+        console.error('[home] Failed to load feeds.');
+        $scope.feed = null;
+      });
+  }
+
   /**
    * Catch click for quick fix
    * @param event
@@ -571,6 +631,7 @@ function HomeController($scope, $state, $timeout, $ionicHistory, $translate, UIU
     $translate.use(langKey);
     $scope.hideLocalesPopover();
     csSettings.data.locale = _.findWhere($scope.locales, {id: langKey});
+    $scope.loadFeeds();
   };
 
   /* -- show/hide locales popup -- */
diff --git a/www/js/services/settings-services.js b/www/js/services/settings-services.js
index c4d03f909..d279f3799 100644
--- a/www/js/services/settings-services.js
+++ b/www/js/services/settings-services.js
@@ -257,6 +257,12 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config'])
       (csConfig.license[locale] ? csConfig.license[locale] : defaultSettings.license[csConfig.defaultLanguage || 'en'] || csConfig.license) : undefined;
   },
 
+  getFeedUrl = function() {
+    var locale = data.locale && data.locale.id || csConfig.defaultLanguage || 'en';
+    return (csConfig.feed && csConfig.feed.jsonFeed) ?
+      (csConfig.feed.jsonFeed[locale] ? csConfig.feed.jsonFeed[locale] : defaultSettings.feed.jsonFeed[csConfig.defaultLanguage || 'en'] || csConfig.feed) : undefined;
+  },
+
   // Detect locale successful changes, then apply to vendor libs
   onLocaleChange = function() {
     var locale = $translate.use();
@@ -344,6 +350,7 @@ angular.module('cesium.settings.services', ['ngApi', 'cesium.config'])
     store: store,
     restore: restore,
     getLicenseUrl: getLicenseUrl,
+    getFeedUrl: getFeedUrl,
     defaultSettings: defaultSettings,
     // api extension
     api: api,
diff --git a/www/js/services/wot-services.js b/www/js/services/wot-services.js
index 2bc6e8d42..94b656df3 100644
--- a/www/js/services/wot-services.js
+++ b/www/js/services/wot-services.js
@@ -190,7 +190,7 @@ angular.module('cesium.wot.services', ['ngApi', 'cesium.bma.services', 'cesium.c
 
       // Alert user, when request is too long (> 2s)
       $timeout(function() {
-        if (!data.requirements.loaded) UIUtils.loading.update({template: "COMMON.LOADING_WAIT"});
+        if (!data.requirements || !data.requirements.loaded) UIUtils.loading.update({template: "COMMON.LOADING_WAIT"});
       }, 2000);
 
       var now = Date.now();
diff --git a/www/plugins/es/js/controllers/like-controllers.js b/www/plugins/es/js/controllers/like-controllers.js
index dec175e3e..a29609136 100644
--- a/www/plugins/es/js/controllers/like-controllers.js
+++ b/www/plugins/es/js/controllers/like-controllers.js
@@ -61,7 +61,7 @@ function ESLikesController($scope, $q, $timeout, $translate, $ionicPopup, UIUtil
   };
 
   $scope.loadLikes = function(id) {
-    if ($scope.likeData.loading) return;// Skip
+    if (!$scope.likeData || $scope.likeData.loading) return;// Skip
 
     id = id || $scope.likeData.id;
     $scope.initLikes();
diff --git a/www/plugins/es/js/controllers/wot-controllers.js b/www/plugins/es/js/controllers/wot-controllers.js
index fd7c9fd9d..fe5ac90c9 100644
--- a/www/plugins/es/js/controllers/wot-controllers.js
+++ b/www/plugins/es/js/controllers/wot-controllers.js
@@ -98,12 +98,12 @@ function ESWotLookupExtendController($scope, $controller, $state) {
 }
 
 function ESWotIdentityViewController($scope, $ionicPopover, $q, $controller, UIUtils, Modals, csWallet,
-                                     esHttp, esModals, esWallet, esProfile, esInvitation) {
+                                     esHttp, esLike, esModals, esWallet, esProfile, esInvitation) {
   'ngInject';
 
   $scope.options = $scope.options || {};
   $scope.options.like = $scope.options.like || {
-    kinds: esHttp.constants.like.KINDS,
+    kinds: esLike.constants.KINDS,
     index: 'user',
     type: 'profile',
     service: esProfile.like
diff --git a/www/plugins/es/templates/network/view_es_peer.html b/www/plugins/es/templates/network/view_es_peer.html
index 64bc49fa0..882ff8550 100644
--- a/www/plugins/es/templates/network/view_es_peer.html
+++ b/www/plugins/es/templates/network/view_es_peer.html
@@ -4,7 +4,7 @@
     <span translate>ES_SETTINGS.PLUGIN_NAME</span>
   </ion-nav-title>
 
-  <ion-content class="has-header" scroll="true">
+  <ion-content>
 
     <div class="row no-padding">
       <div class="col col-20 hidden-xs hidden-sm">&nbsp;
diff --git a/www/templates/api/home.html b/www/templates/api/home.html
index d669e13ec..852bbf795 100644
--- a/www/templates/api/home.html
+++ b/www/templates/api/home.html
@@ -14,7 +14,7 @@
     </button>
   </ion-nav-buttons>
 
-  <ion-content class="has-header no-padding-xs no-padding-sm positive-900-bg">
+  <ion-content class="no-padding-xs no-padding-sm positive-900-bg">
 
     <br class="hidden-xs"/>
 
diff --git a/www/templates/api/transfer.html b/www/templates/api/transfer.html
index efb9ced6d..f0520fcff 100644
--- a/www/templates/api/transfer.html
+++ b/www/templates/api/transfer.html
@@ -24,7 +24,7 @@
     </button>
   </ion-nav-buttons>
 
-  <ion-content class=" has-header no-padding-xs positive-900-bg">
+  <ion-content class="no-padding-xs positive-900-bg">
 
     <br class="hidden-xs"/>
 
diff --git a/www/templates/home/home.html b/www/templates/home/home.html
index 664545733..946ed0ff6 100644
--- a/www/templates/home/home.html
+++ b/www/templates/home/home.html
@@ -13,98 +13,156 @@
     </button>
   </ion-nav-buttons>
 
-  <ion-content
-    class="has-header text-center no-padding-xs positive-900-bg circle-bg-dark">
+  <ion-content class="positive-900-bg circle-bg-dark">
+
+    <div class="row no-padding-xs responsive-lg">
+      <div class="col col-30 hidden-xs hidden-sm">&nbsp;</div>
+      <div class="col text-center no-padding-xs main-container">
+
+        <div id="helptip-home-logo" class="logo"></div>
+
+        <h4>
+          <span class="hidden-xs" translate>HOME.WELCOME</span>
+          <b ng-show="!loading" translate-values=":currency:{currency: $root.currency.name}" translate>HOME.MESSAGE</b>
+        </h4>
+
+        <div class="center padding" ng-if="loading">
+          <ion-spinner icon="android" ></ion-spinner>
+        </div>
+
+        <div class="center padding animate-fade-in animate-show-hide ng-hide" ng-show="!loading && error">
+          <div class="card card-item padding">
+            <p class="item-content item-text-wrap">
+                <span class="dark" trust-as-html="'HOME.CONNECTION_ERROR'|translate:node"></span>
+            </p>
+
+            <!-- Retry -->
+            <button type="button"
+                    class="button button-positive icon icon-left ion-refresh ink"
+                    ng-click="reload()">{{'COMMON.BTN_REFRESH'|translate}}</button>
+          </div>
+        </div>
+
+        <div class="center animate-fade-in animate-show-hide ng-hide" ng-show="!loading && !error">
+
+          <!-- Help tour (NOT ready yet for small device) -->
+          <button type="button"
+                  class="button button-block button-stable button-raised icon-left icon ion-easel ink-dark hidden-xs"
+                  ng-show="login"
+                  ng-click="startHelpTour()" >
+            {{'COMMON.BTN_HELP_TOUR'|translate}}
+          </button>
+
+          <button type="button"
+                  class="button button-block button-positive button-raised ink-dark"
+                  ng-click="showJoinModal()" ng-if="!login" translate>LOGIN.CREATE_FREE_ACCOUNT</button>
+
+          <button type="button"
+                  class="item button button-block button-positive button-raised icon icon-left ion-person ink-dark"
+                  ui-sref="app.view_wallet" ng-show="login" translate>MENU.ACCOUNT</button>
+
+          <button type="button"
+                  class="item button button-block button-positive button-raised icon icon-left ion-card ink-dark visible-xs"
+                  ui-sref="app.view_wallet_tx" ng-if="login" translate>MENU.TRANSACTIONS</button>
+
+          <br class="visible-xs visible-sm"/>
+
+          <!-- join link -->
+          <div class="text-center no-padding" ng-show="!login">
+            <br class="visible-xs visible-sm"/>
+            {{'LOGIN.HAVE_ACCOUNT_QUESTION'|translate}}
+            <b>
+              <a class="assertive hidden-xs hidden-sm" ui-sref="app.view_wallet" translate>
+                COMMON.BTN_LOGIN
+              </a>
+            </b>
+          </div>
+
+          <!-- disconnect link -->
+          <div class="text-center no-padding" ng-show="login">
+            <br class="visible-xs visible-sm"/>
+            <span ng-bind-html="'HOME.NOT_YOUR_ACCOUNT_QUESTION'|translate:{pubkey: walletData.pubkey}"></span>
+            <br/>
+            <b>
+              <a class="assertive hidden-xs hidden-sm" ng-click="logout()" translate>
+                HOME.BTN_CHANGE_ACCOUNT
+              </a>
+            </b>
+          </div>
+
+          <button type="button"
+                  class="button button-block button-stable button-raised ink visible-xs visible-sm"
+                  ui-sref="app.view_wallet" ng-if="!login" translate>COMMON.BTN_LOGIN</button>
+          <button type="button"
+                  class="button button-block button-assertive button-raised icon icon-left ion-log-out ink-dark visible-xs visible-sm"
+                  ng-click="logout()" ng-if="login" translate>COMMON.BTN_LOGOUT</button>
+
+
+          <div class="text-center no-padding visible-xs stable">
+            <br/>
+            <!-- version -->
+            {{'COMMON.APP_VERSION'|translate:{version: config.version} }}
+            |
+            <!-- about -->
+            <a href="#" ng-click="showAboutModal()" translate>HOME.BTN_ABOUT</a>
+          </div>
+
+        </div>
 
-    <div id="helptip-home-logo" class="logo"></div>
 
-    <h4>
-      <span class="hidden-xs" translate>HOME.WELCOME</span>
-      <b ng-show="!loading" translate-values=":currency:{currency: $root.currency.name}" translate>HOME.MESSAGE</b>
-    </h4>
-
-    <div class="center padding" ng-if="loading">
-      <ion-spinner icon="android" ></ion-spinner>
-    </div>
-
-    <div class="center padding animate-fade-in animate-show-hide ng-hide" ng-show="!loading && error">
-      <div class="card card-item padding">
-        <p class="item-content item-text-wrap">
-            <span class="dark" trust-as-html="'HOME.CONNECTION_ERROR'|translate:node"></span>
-        </p>
-
-        <!-- Retry -->
-        <button type="button"
-                class="button button-positive icon icon-left ion-refresh ink"
-                ng-click="reload()">{{'COMMON.BTN_REFRESH'|translate}}</button>
       </div>
-    </div>
-
-    <div class="center animate-fade-in animate-show-hide ng-hide" ng-show="!loading && !error">
-
-      <!-- Help tour (NOT ready yet for small device) -->
-      <button type="button"
-              class="button button-block button-stable button-raised icon-left icon ion-easel ink-dark hidden-xs"
-              ng-show="login"
-              ng-click="startHelpTour()" >
-        {{'COMMON.BTN_HELP_TOUR'|translate}}
-      </button>
-
-      <button type="button"
-              class="button button-block button-positive button-raised ink-dark"
-              ng-click="showJoinModal()" ng-if="!login" translate>LOGIN.CREATE_FREE_ACCOUNT</button>
-
-      <button type="button"
-              class="item button button-block button-positive button-raised icon icon-left ion-person ink-dark"
-              ui-sref="app.view_wallet" ng-show="login" translate>MENU.ACCOUNT</button>
-
-      <button type="button"
-              class="item button button-block button-positive button-raised icon icon-left ion-card ink-dark visible-xs"
-              ui-sref="app.view_wallet_tx" ng-if="login" translate>MENU.TRANSACTIONS</button>
-
-      <br class="visible-xs visible-sm"/>
-
-      <!-- join link -->
-      <div class="text-center no-padding" ng-show="!login">
-        <br class="visible-xs visible-sm"/>
-        {{'LOGIN.HAVE_ACCOUNT_QUESTION'|translate}}
-        <b>
-          <a class="assertive hidden-xs hidden-sm" ui-sref="app.view_wallet" translate>
-            COMMON.BTN_LOGIN
-          </a>
-        </b>
+      <div class="col col-30 no-padding">
+
+        <!-- feed -->
+        <div ng-if="feed" class="feed padding padding-top">
+          <h3 class="padding-left">
+            <i class="icon ion-speakerphone"></i>
+            {{feed.title}}
+            <small><a ng-click="openLink($event, feed.home_page_url)" class="gray">
+              <span translate>HOME.SHOW_ALL_FEED</span>
+              <i class="icon ion-chevron-right"></i>
+            </a></small>
+          </h3>
+
+          <!-- feed items -->
+          <div ng-repeat="item in feed.items"
+             class="card padding">
+
+            <div class="header ">
+              <!-- author -->
+              <i ng-if="item.author.avatar" class="avatar" style="background-image: url({{item.author.avatar}});"></i>
+              <a ng-class="{'avatar-left-padding': item.author.avatar}" class="author"
+                 ng-click="item.author.url && openLink($event, item.author.url)">
+                {{item.author.name}}
+              </a>
+
+              <!-- time -->
+              <a ng-if="item.time"
+                 title="{{item.time|formatDate}}"
+                 ng-click="openLink($event, item.url)"
+                 class="item-note">
+                <small><i class="icon ion-clock"></i>&nbsp;{{item.time|formatFromNow}}</small>
+              </a>
+            </div>
+            <!-- title -->
+            <h2 class="title feed-title">
+              <a ng-click="openLink($event, item.url)">{{item.title}}</a></h2>
+            <div ng-if="item.content"
+                 class="content feed-content"
+                 trust-as-html="item.content"></div>
+            <h4 class="card-footer feed-footer text-right positive-100">
+              <a ng-click="openLink($event, item.url)">
+                <span ng-if="item.truncated" translate>HOME.READ_MORE</span>
+                <span ng-if="!item.truncated" translate>COMMON.BTN_SHOW</span>
+                <i class="icon ion-chevron-right"></i>
+              </a>
+            </h4>
+          </div>
+        </div>
       </div>
+    </div>
 
-      <!-- disconnect link -->
-      <div class="text-center no-padding" ng-show="login">
-        <br class="visible-xs visible-sm"/>
-        <span ng-bind-html="'HOME.NOT_YOUR_ACCOUNT_QUESTION'|translate:{pubkey: walletData.pubkey}"></span>
-        <br/>
-        <b>
-          <a class="assertive hidden-xs hidden-sm" ng-click="logout()" translate>
-            HOME.BTN_CHANGE_ACCOUNT
-          </a>
-        </b>
-      </div>
 
-      <button type="button"
-              class="button button-block button-stable button-raised ink visible-xs visible-sm"
-              ui-sref="app.view_wallet" ng-if="!login" translate>COMMON.BTN_LOGIN</button>
-      <button type="button"
-              class="button button-block button-assertive button-raised icon icon-left ion-log-out ink-dark visible-xs visible-sm"
-              ng-click="logout()" ng-if="login" translate>COMMON.BTN_LOGOUT</button>
-
-
-      <div class="text-center no-padding visible-xs stable">
-        <br/>
-        <!-- version -->
-        {{'COMMON.APP_VERSION'|translate:{version: config.version} }}
-        |
-        <!-- about -->
-        <a href="#" ng-click="showAboutModal()" translate>HOME.BTN_ABOUT</a>
-      </div>
-
-    </div>
   </ion-content>
 
 </ion-view>
diff --git a/www/templates/network/view_peer.html b/www/templates/network/view_peer.html
index c90092d4e..b081f7593 100644
--- a/www/templates/network/view_peer.html
+++ b/www/templates/network/view_peer.html
@@ -3,7 +3,7 @@
     <span translate>PEER.VIEW.TITLE</span>
   </ion-nav-title>
 
-  <ion-content class="has-header" scroll="true">
+  <ion-content>
 
     <div class="row no-padding">
       <div class="col col-20 hidden-xs hidden-sm">&nbsp;
diff --git a/www/templates/wot/tabs/tab_received_certifications.html b/www/templates/wot/tabs/tab_received_certifications.html
index d553b658d..98ee69959 100644
--- a/www/templates/wot/tabs/tab_received_certifications.html
+++ b/www/templates/wot/tabs/tab_received_certifications.html
@@ -4,7 +4,7 @@
     </button>
   </ion-nav-buttons>
 
-  <ion-content ng-init="motions.givenCertifications=false; motions.avatar=false;" class="has-header">
+  <ion-content ng-init="motions.givenCertifications=false; motions.avatar=false;">
     <div class="center padding" ng-if="loading">
       <ion-spinner icon="android"></ion-spinner>
     </div>
-- 
GitLab