diff --git a/README.md b/README.md index 37509ba1..83278210 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ Gmail Inbox HipChat + ChatWork GroupMe Grape @@ -57,6 +58,7 @@ Outlook Outlook 365 TutaNota + Hushmail BearyChat Aol @@ -67,6 +69,7 @@ Missive Yahoo! Mail Ryver + Yandex Mail Dasher DingTalk @@ -77,6 +80,7 @@ Yahoo! Messenger mysms ICQ + TweetDeck Zinc FreeNode @@ -87,6 +91,7 @@ Horde SquirrelMail Zimbra + Hootsuite Amium RainLoop @@ -97,6 +102,7 @@ Crisp Flock Openmailbox + Typetalk Drift mmmelon @@ -107,7 +113,9 @@ Riot Pushbullet Movim + Kaiwa +XING































@@ -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'); +}