diff --git a/README.md b/README.md
index 37509ba1..83278210 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,7 @@
+
@@ -57,6 +58,7 @@
+
@@ -67,6 +69,7 @@
+
@@ -77,6 +80,7 @@
+
@@ -87,6 +91,7 @@
+
@@ -97,6 +102,7 @@
+
@@ -107,7 +113,9 @@
+
+
@@ -152,6 +160,35 @@ Want to report a bug, request a feature, contribute to or translate Rambox? We n
If you're comfortable getting up and running from a `git clone`, this method is for you.
+## Adding a service
+
+The available services are stored in the [ServiceList.js](app/store/ServicesList.js).
+Structure of a service entry:
+
+|Name|Description|Required|
+|---|---|---|
+|id|Unique identifier for the service, e.g. "slack"|yes|
+|logo|File name of the service logo located in "/resources/icons/", e.g. "slack.png"|yes|
+|name|Visible name for the service, e.g. "Slack"|yes|
+|description|A short description of the service, e.g. "Slack brings all your communication together..."|yes|
+|url|URL of the service, e.g. "https://\_\_\_.slack.com/". "\_\_\_" may be used as a placeholder, that can be configured when adding a service.|yes|
+|type|Defines the type of the service. Must be one of `email` or `messaging`.|yes|
+|allow_popups|Set to `true` to allow popup windows for the service.|no|
+|note|Additional info to display when adding the service.|no|
+|manual_notifications|Set to `true` to let Rambox trigger notifications. Can be used for services that doesn't support browser notifications.|no|
+|js_unread|JavaScript code for setting the unread count (see below).|no|
+|dont_update_unread_from_title|Set to `true` to prevent updating the unread count from the window title (see below).|no|
+
+### Setting the unread count
+
+While there is also a way to set the unread count by adding ` (COUNT)` to the window title, this describes the preferred way of doing it:
+
+First set `dont_update_unread_from_title` in the service config to `true`.
+
+Code provided by `js_unread` will be injected into the service website.
+You can retrieve the unread count in this JavaScript code e.g. by parsing elements.
+Set the unread count by calling `rambox.setUnreadCount(COUNT)` or clear it by calling `rambox.clearUnreadCount()`.
+
#### Technologies:
* Sencha Ext JS 5.1.1.451
diff --git a/app/store/ServicesList.js b/app/store/ServicesList.js
index 078ddc8f..4499a500 100644
--- a/app/store/ServicesList.js
+++ b/app/store/ServicesList.js
@@ -662,6 +662,16 @@ Ext.define('Rambox.store.ServicesList', {
,type: 'messaging'
},
{
+ id: 'xing'
+ ,logo: 'xing.png'
+ ,name: 'XING'
+ ,description: 'Career-oriented social networking'
+ ,url: 'https://www.xing.com/messages/conversations'
+ ,type: 'messaging'
+ ,js_unread: '(function() { let originalTitle = document.title; function checkUnread() { let count = null; let notificationElement = document.querySelector(\'[data-update="unread_conversations"]\'); if (notificationElement && notificationElement.style.display !== \'none\') { count = parseInt(notificationElement.textContent.trim(), 10); } updateBadge(count); } function updateBadge(count) { if (count && count >= 1) { rambox.setUnreadCount(count); } else { rambox.clearUnreadCount(); } } setInterval(checkUnread, 3000); checkUnread(); })();'
+ ,dont_update_unread_from_title: true
+ },
+ {
id: 'Workplace'
,logo: 'workplace.png'
,name: 'Workplace by Facebook'
@@ -669,5 +679,5 @@ Ext.define('Rambox.store.ServicesList', {
,url: 'https://___.facebook.com/'
,type: 'messaging'
}
- ]
+ ]
});
diff --git a/app/ux/WebView.js b/app/ux/WebView.js
index 053b8bc1..6583a01b 100644
--- a/app/ux/WebView.js
+++ b/app/ux/WebView.js
@@ -160,7 +160,8 @@ Ext.define('Rambox.ux.WebView',{
,autosize: 'on'
,disablewebsecurity: 'on'
,blinkfeatures: 'ApplicationCache,GlobalCacheStorage'
- ,useragent: Ext.getStore('ServicesList').getById(me.record.get('type')).get('userAgent')
+ ,useragent: Ext.getStore('ServicesList').getById(me.record.get('type')).get('userAgent'),
+ preload: './resources/js/rambox-service-api.js'
}
};
@@ -262,14 +263,54 @@ Ext.define('Rambox.ux.WebView',{
webview.executeJavaScript('document.body.scrollTop=0;');
});
- webview.addEventListener("page-title-updated", function(e) {
- var count = e.title.match(/\(([^)]+)\)/); // Get text between (...)
+ webview.addEventListener('ipc-message', function(event) {
+ var channel = event.channel;
+ switch (channel) {
+ case 'rambox.setUnreadCount':
+ handleSetUnreadCount(event);
+ break;
+ case 'rambox.clearUnreadCount':
+ handleClearUnreadCount(event);
+ break;
+ }
+
+ /**
+ * Handles 'rambox.clearUnreadCount' messages.
+ * Clears the unread count.
+ */
+ function handleClearUnreadCount() {
+ me.tab.setBadgeText('');
+ }
+
+ /**
+ * Handles 'rambox.setUnreadCount' messages.
+ * Sets the badge text if the event contains an integer as first argument.
+ *
+ * @param event
+ */
+ function handleSetUnreadCount(event) {
+ if (Array.isArray(event.args) === true && event.args.length > 0) {
+ var count = event.args[0];
+ if (count === parseInt(count, 10)) {
+ me.tab.setBadgeText(Rambox.util.Format.formatNumber(count));
+ }
+ }
+ }
+ });
+
+ /**
+ * Register page title update event listener only for services that don't prevent it by setting 'dont_update_unread_from_title' to true.
+ */
+ if (Ext.getStore('ServicesList').getById(me.record.get('type')).get('dont_update_unread_from_title') !== true) {
+ webview.addEventListener("page-title-updated", function(e) {
+ var count = e.title.match(/\(([^)]+)\)/); // Get text between (...)
count = count ? count[1] : '0';
count = count === '•' ? count : Ext.isArray(count.match(/\d+/g)) ? count.match(/\d+/g).join("") : count.match(/\d+/g); // Some services have special characters. Example: (•)
count = count === null ? '0' : count;
- me.setUnreadCount(count);
- });
+ me.setUnreadCount(count);
+ });
+ }
webview.addEventListener('did-get-redirect-request', function( e ) {
if ( e.isMainFrame ) webview.loadURL(e.newURL);
diff --git a/resources/icons/xing.png b/resources/icons/xing.png
new file mode 100644
index 00000000..070b8eb0
Binary files /dev/null and b/resources/icons/xing.png differ
diff --git a/resources/js/rambox-service-api.js b/resources/js/rambox-service-api.js
new file mode 100644
index 00000000..c37517dd
--- /dev/null
+++ b/resources/js/rambox-service-api.js
@@ -0,0 +1,28 @@
+/**
+ * This file is loaded in the service web views to provide a Rambox API.
+ */
+
+const { ipcRenderer } = require('electron');
+
+/**
+ * Make the Rambox API available via a global "rambox" variable.
+ *
+ * @type {{}}
+ */
+window.rambox = {};
+
+/**
+ * Sets the unraed count of the tab.
+ *
+ * @param {*} count The unread count
+ */
+window.rambox.setUnreadCount = function(count) {
+ ipcRenderer.sendToHost('rambox.setUnreadCount', count);
+};
+
+/**
+ * Clears the unread count.
+ */
+window.rambox.clearUnreadCount = function() {
+ ipcRenderer.sendToHost('rambox.clearUnreadCount');
+}