autoRefreshList: add status indicator

In order to clarify when the feature is watching for updates in the
current thread list or not depending in the current sort options, this
change adds an indicator which states this.

It also adds styles for a "muted" state of the indicator which might
indicate in the future that the user has disabled it manually.

Apart from this, this also changes the option text to improve it.

Fixed: twpowertools:5
Change-Id: I77a65fa9091d6c9e18f09a3798eeb5197ced8647
diff --git a/src/contentScripts/communityConsole/autoRefresh.js b/src/contentScripts/communityConsole/autoRefresh.js
index 87ca203..ea7d32f 100644
--- a/src/contentScripts/communityConsole/autoRefresh.js
+++ b/src/contentScripts/communityConsole/autoRefresh.js
@@ -20,6 +20,7 @@
     this.requestId = null;
     this.requestOrderOptions = null;
     this.snackbar = null;
+    this.statusIndicator = null;
     this.interval = null;
 
     this.setUpHandlers();
@@ -141,6 +142,41 @@
     this.snackbar = snackbar;
   }
 
+  // Create an indicator element.
+  createStatusIndicator(isSetUp) {
+    var container = document.createElement('div');
+    container.classList.add('TWPT-autorefresh-status-indicator-container');
+    var title = chrome.i18n.getMessage(
+        isSetUp ? 'inject_autorefresh_list_status_indicator_label_active' :
+                  'inject_autorefresh_list_status_indicator_label_disabled');
+    container.setAttribute('title', title);
+
+    var indicator = document.createElement('div');
+    indicator.classList.add(
+        'TWPT-autorefresh-status-indicator',
+        isSetUp ? 'TWPT-autorefresh-status-indicator--active' :
+                  'TWPT-autorefresh-status-indicator--disabled');
+    indicator.textContent =
+        isSetUp ? 'notifications_active' : 'notifications_off';
+
+    var badge = createExtBadge();
+
+    container.append(indicator, badge);
+    return container;
+  }
+
+  injectStatusIndicator(isSetUp) {
+    this.statusIndicator = this.createStatusIndicator(isSetUp);
+
+    var sortOptionsDiv = document.querySelector('ec-thread-list .sort-options');
+    if (sortOptionsDiv) {
+      sortOptionsDiv.prepend(this.statusIndicator);
+      return;
+    }
+
+    console.error('threadListAvatars: Couldn\'t inject status indicator.');
+  }
+
   checkUpdate() {
     if (location.pathname != this.path) {
       this.unregister();
@@ -226,6 +262,7 @@
   // initializes the interval to check for updates, and several other things.
   setUp() {
     if (!this.isOrderedByTimestampDescending()) {
+      this.injectStatusIndicator(false);
       console.debug(
           'autorefresh_list: refused to start up because the order is not by timestamp descending.');
       return;
@@ -236,6 +273,8 @@
     console.debug('autorefresh_list: starting set up...');
 
     if (this.snackbar === null) this.injectUpdatePrompt();
+    this.injectStatusIndicator(true);
+
     this.isLookingForUpdates = true;
     this.path = location.pathname;
 
diff --git a/src/static/_locales/ca/messages.json b/src/static/_locales/ca/messages.json
index d3774bc..564bff7 100644
--- a/src/static/_locales/ca/messages.json
+++ b/src/static/_locales/ca/messages.json
@@ -100,7 +100,7 @@
     "description": "Feature checkbox in the options page"
   },
   "options_autorefreshlist": {
-    "message": "Actualitza les llistes de fils de la Consola de la Comunitat automàticament.",
+    "message": "Mostra una notificació a la Consola de la Comunitat quan una llista de fils rep actualitzacions.",
     "description": "Feature checkbox in the options page"
   },
   "options_disableunifiedprofiles": {
@@ -242,5 +242,13 @@
   "inject_autorefresh_list_snackbar_action": {
     "message": "Actualitza",
     "description": "Button shown in a snackbar asking users to refresh/reload the list to show the new threads."
+  },
+  "inject_autorefresh_list_status_indicator_label_active": {
+    "message": "Observant canvis a la llista de fils...",
+    "description": "Helper text which appears when hovering the status indicator of the 'autorefresh list' feature to indicate that the feature is active and watching for updates in the current thread list."
+  },
+  "inject_autorefresh_list_status_indicator_label_disabled": {
+    "message": "No es poden observar canvis a la llista de fils. Sisplau canvia les opcions d'ordre a 'Ordena per: Darrera actualització' i ordre descendent.",
+    "description": "Helper text which appears when hovering the status indicator of the 'autorefresh list' feature to indicate that the feature is disabled in the current thread list because the sort options are incompatible with the feature."
   }
 }
diff --git a/src/static/_locales/en/messages.json b/src/static/_locales/en/messages.json
index 2442669..2e0c9b4 100644
--- a/src/static/_locales/en/messages.json
+++ b/src/static/_locales/en/messages.json
@@ -104,7 +104,7 @@
     "description": "Feature checkbox in the options page"
   },
   "options_autorefreshlist": {
-    "message": "Autorefresh thread lists in the Community Console.",
+    "message": "Show a notification in the Community Console when a thread list has new updates.",
     "description": "Feature checkbox in the options page"
   },
   "options_disableunifiedprofiles": {
@@ -242,5 +242,13 @@
   "inject_autorefresh_list_snackbar_action": {
     "message": "Refresh",
     "description": "Button shown in a snackbar asking users to refresh/reload the list to show the new threads."
+  },
+  "inject_autorefresh_list_status_indicator_label_active": {
+    "message": "Watching for updates to the thread list...",
+    "description": "Helper text which appears when hovering the status indicator of the 'autorefresh list' feature to indicate that the feature is active and watching for updates in the current thread list."
+  },
+  "inject_autorefresh_list_status_indicator_label_disabled": {
+    "message": "Can't watch for updates to the thread list. Please change the sort options to 'Sort by: Last updated' and descending order.",
+    "description": "Helper text which appears when hovering the status indicator of the 'autorefresh list' feature to indicate that the feature is disabled in the current thread list because the sort options are incompatible with the feature."
   }
 }
diff --git a/src/static/_locales/es/messages.json b/src/static/_locales/es/messages.json
index e4f9e02..f9b65ac 100644
--- a/src/static/_locales/es/messages.json
+++ b/src/static/_locales/es/messages.json
@@ -104,7 +104,7 @@
     "description": "Feature checkbox in the options page"
   },
   "options_autorefreshlist": {
-    "message": "Actualiza las listas de hilos de la Consola de la Comunidad automáticamente.",
+    "message": "Muestra una notificación en la Consola de la Comunidad cuando una lista de hilos recibe actualizaciones.",
     "description": "Feature checkbox in the options page"
   },
   "options_disableunifiedprofiles": {
@@ -242,5 +242,13 @@
   "inject_autorefresh_list_snackbar_action": {
     "message": "Actualizar",
     "description": "Button shown in a snackbar asking users to refresh/reload the list to show the new threads."
+  },
+  "inject_autorefresh_list_status_indicator_label_active": {
+    "message": "Observando cambios en la lista de hilos...",
+    "description": "Helper text which appears when hovering the status indicator of the 'autorefresh list' feature to indicate that the feature is active and watching for updates in the current thread list."
+  },
+  "inject_autorefresh_list_status_indicator_label_disabled": {
+    "message": "No se pueden observar cambios en la lista de hilos. Por favor cambia las opciones de orden a 'Ordenar por: Última actualización' y orden descendiente.",
+    "description": "Helper text which appears when hovering the status indicator of the 'autorefresh list' feature to indicate that the feature is disabled in the current thread list because the sort options are incompatible with the feature."
   }
 }
diff --git a/src/static/css/autorefresh_list.css b/src/static/css/autorefresh_list.css
index 56d3fda..a12540b 100644
--- a/src/static/css/autorefresh_list.css
+++ b/src/static/css/autorefresh_list.css
@@ -1,3 +1,4 @@
+/* Snackbar */
 .TWPT-pane-for-snackbar {
   height: 48px;
   position: fixed;
@@ -77,3 +78,52 @@
 .TWPT-snackbar.TWPT-hidden {
   display: none;
 }
+
+/* Status indicator */
+.TWPT-autorefresh-status-indicator-container {
+  position: relative;
+  padding: 0 8px;
+  height: 46px;
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  cursor: help;
+}
+
+.TWPT-autorefresh-status-indicator {
+  width: 24px;
+  height: 24px;
+  border-style: solid;
+  border-width: 3px;
+  border-radius: 50%;
+  font-family: 'Google Material Icons';
+  text-align: center;
+  font-size: 17px;
+  line-height: 24px;
+  user-select: none;
+}
+
+.TWPT-autorefresh-status-indicator--active {
+  color: #202124;
+  background: #e3f2fd;
+  border-color: #2389e3;
+}
+
+.TWPT-autorefresh-status-indicator--muted {
+  color: #5f6368;
+  background: #f1f3f4;
+  border-color: #757575;
+}
+
+.TWPT-autorefresh-status-indicator--disabled {
+  color: #c5221f;
+  background: #fce8e6;
+  border-color: #c5221f;
+}
+
+.TWPT-autorefresh-status-indicator-container .TWPT-badge {
+  --icon-size:  13px;
+  position: absolute;
+  bottom: 2px;
+  right: 1px;
+}