Browse Source

Merge pull request #862 from saenzramiro/v0.5.8

v0.5.8
pull/297/merge
Ramiro Saenz 8 years ago committed by GitHub
parent
commit
3d7ae58fa9
  1. 1
      .gitignore
  2. 7
      app.js
  3. 31
      app/Application.js
  4. 8
      app/model/Service.js
  5. 1
      app/model/ServiceList.js
  6. 4
      app/package.json
  7. 3
      app/store/Services.js
  8. 189
      app/store/ServicesList.js
  9. 2
      app/util/Notifier.js
  10. 69
      app/ux/Auth0.js
  11. 121
      app/ux/WebView.js
  12. 168
      app/view/add/Add.js
  13. 10
      app/view/add/AddController.js
  14. 14
      app/view/main/About.js
  15. 46
      app/view/main/Main.js
  16. 113
      app/view/main/MainController.js
  17. 132
      app/view/preferences/Preferences.js
  18. 9
      app/view/preferences/PreferencesController.js
  19. 2
      appveyor.yml
  20. 78
      electron/main.js
  21. 524
      electron/menu.js
  22. 37
      electron/tray.js
  23. 44
      index.html
  24. 50
      languages.js
  25. 15
      package.json
  26. BIN
      resources/icons/actor.png
  27. BIN
      resources/icons/clocktweets.png
  28. BIN
      resources/icons/fastmail.png
  29. BIN
      resources/icons/hibox.png
  30. BIN
      resources/icons/intercom.png
  31. BIN
      resources/icons/jandi.png
  32. BIN
      resources/icons/mastodon.png
  33. BIN
      resources/icons/messengerpages.png
  34. BIN
      resources/icons/teamworkchat.png
  35. BIN
      resources/icons/threema.png
  36. BIN
      resources/icons/vk.png
  37. BIN
      resources/icons/xing.png
  38. 1
      resources/languages/af.js
  39. 1
      resources/languages/ar.js
  40. 1
      resources/languages/ca.js
  41. 1
      resources/languages/cs.js
  42. 1
      resources/languages/da.js
  43. 1
      resources/languages/de.js
  44. 1
      resources/languages/el.js
  45. 1
      resources/languages/en.js
  46. 1
      resources/languages/es-ES.js
  47. 1
      resources/languages/fa.js
  48. 1
      resources/languages/fi.js
  49. 1
      resources/languages/fr.js
  50. 1
      resources/languages/he.js
  51. 1
      resources/languages/hu.js
  52. 1
      resources/languages/id.js
  53. 1
      resources/languages/it.js
  54. 1
      resources/languages/ja.js
  55. 1
      resources/languages/ko.js
  56. 1
      resources/languages/nl.js
  57. 1
      resources/languages/no.js
  58. 1
      resources/languages/pl.js
  59. 1
      resources/languages/pt-BR.js
  60. 1
      resources/languages/pt-PT.js
  61. 1
      resources/languages/ro.js
  62. 1
      resources/languages/ru.js
  63. 1
      resources/languages/sr.js
  64. 1
      resources/languages/sv-SE.js
  65. 1
      resources/languages/tr.js
  66. 1
      resources/languages/uk.js
  67. 1
      resources/languages/vi.js
  68. 1
      resources/languages/zh-CN.js
  69. 1
      resources/languages/zh-TW.js

1
.gitignore vendored

@ -34,3 +34,4 @@ npm-debug.log
/.vagrant
env.js
rambox_cfg.json
languages.js

7
app.js

@ -15,6 +15,9 @@ const ipc = require('electron').ipcRenderer;
ipc.on('showAbout', function(event, message) {
!Ext.cq1('about') ? Ext.create('Rambox.view.main.About') : '';
});
ipc.on('showPreferences', function(event, message) {
!Ext.cq1('preferences') ? Ext.create('Rambox.view.preferences.Preferences').show() : '';
});
ipc.on('autoUpdater:check-update', function() {
Rambox.app.checkUpdate();
});
@ -121,3 +124,7 @@ ipc.on('reloadCurrentService', function(e) {
var tab = Ext.cq1('app-main').getActiveTab();
if ( tab.id !== 'ramboxTab' ) tab.reloadService();
});
// Focus the current service when Alt + Tab or click in webviews textfields
window.addEventListener('focus', function() {
if(Ext.cq1("app-main")) Ext.cq1("app-main").getActiveTab().down('component').el.dom.focus();
});

31
app/Application.js

@ -34,7 +34,7 @@ Ext.define('Rambox.Application', {
Rambox.ux.Auth0.init();
// Check for updates
Rambox.app.checkUpdate(true);
if ( require('electron').remote.process.argv.indexOf('--without-update') === -1 && process.platform !== 'win32' ) Rambox.app.checkUpdate(true);
// Add shortcuts to switch services using CTRL + Number
var map = new Ext.util.KeyMap({
@ -82,9 +82,14 @@ Ext.define('Rambox.Application', {
var tabPanel = Ext.cq1('app-main');
var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
var i = activeIndex + 1;
if ( i >= tabPanel.items.items.length - 1 ) i = 0;
while ( tabPanel.items.items[i].id === 'tbfill' ) i++;
tabPanel.setActiveTab( i );
// "cycle" (go to the start) when the end is reached or the end is the spacer "tbfill"
if (i === tabPanel.items.items.length || i === tabPanel.items.items.length - 1 && tabPanel.items.items[i].id === 'tbfill') i = 0;
// skip spacer
while (tabPanel.items.items[i].id === 'tbfill') i++;
tabPanel.setActiveTab(i);
}
}
,{
@ -97,7 +102,7 @@ Ext.define('Rambox.Application', {
var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
var i = activeIndex - 1;
if ( i < 0 ) i = tabPanel.items.items.length - 1;
while ( tabPanel.items.items[i].id === 'tbfill' ) i--;
while ( tabPanel.items.items[i].id === 'tbfill' || i < 0 ) i--;
tabPanel.setActiveTab( i );
}
}
@ -183,10 +188,6 @@ Ext.define('Rambox.Application', {
}
});
if ( process.platform !== 'win32' ) {
this.checkUpdate(true);
}
// Define default value
if ( localStorage.getItem('dontDisturb') === null ) localStorage.setItem('dontDisturb', false);
@ -226,17 +227,17 @@ Ext.define('Rambox.Application', {
'->'
,{
xtype: 'label'
,html: '<b>New version is available!</b> ('+json.version+')' + ( process.platform === 'win32' ? ' Is downloading in the background and you will notify when is ready to install it.' : '' )
,html: '<b>'+locale['app.update[0]']+'</b> ('+json.version+')' + ( process.platform === 'win32' ? ' Is downloading in the background and you will notify when is ready to install it.' : '' )
}
,{
xtype: 'button'
,text: 'Download'
,href: 'https://getrambox.herokuapp.com/download/'+process.platform+'_'+process.arch
,text: locale['app.update[1]']
,href: process.platform === 'darwin' ? 'https://getrambox.herokuapp.com/download/'+process.platform+'_'+process.arch : 'https://github.com/saenzramiro/rambox/releases/latest'
,hidden: process.platform === 'win32'
}
,{
xtype: 'button'
,text: 'Changelog'
,text: locale['app.update[2]']
,ui: 'decline'
,tooltip: 'Click here to see more information about the new version.'
,href: 'https://github.com/saenzramiro/rambox/releases/tag/'+json.version
@ -254,8 +255,8 @@ Ext.define('Rambox.Application', {
return;
} else if ( !silence ) {
Ext.Msg.show({
title: 'You are up to date!'
,message: 'You have the latest version of Rambox.'
title: locale['app.update[3]']
,message: locale['app.update[4]']
,icon: Ext.Msg.INFO
,buttons: Ext.Msg.OK
});

8
app/model/Service.js

@ -37,6 +37,14 @@ Ext.define('Rambox.model.Service', {
name: 'muted'
,type: 'boolean'
,defaultValue: false
},{
name: 'tabname'
,type: 'boolean'
,defaultValue: true
},{
name: 'statusbar'
,type: 'boolean'
,defaultValue: true
},{
name: 'displayTabUnreadCounter'
,type: 'boolean'

1
app/model/ServiceList.js

@ -13,6 +13,7 @@ Ext.define('Rambox.model.ServiceList', {
},{
name: 'description'
,type: 'string'
,defaultValue: locale['services[27]']
},{
name: 'url'
,type: 'string'

4
app/package.json

@ -1,7 +1,7 @@
{
"name": "Rambox",
"productName": "Rambox",
"version": "0.5.7",
"version": "0.5.8",
"description": "Rambox",
"main": "electron/main.js",
"private": true,
@ -29,7 +29,7 @@
"author": "Ramiro Saenz <[email protected]>",
"license": "GPL-3.0",
"dependencies": {
"auto-launch": "4.0.0",
"auto-launch-patched": "5.0.2",
"tmp": "0.0.28",
"mime": "^1.3.4",
"electron-is-dev": "^0.1.1",

3
app/store/Services.js

@ -39,6 +39,9 @@ Ext.define('Rambox.store.Services', {
break;
}
// If the service is disabled, we dont add it to tab bar
if ( !service.get('enabled') ) return;
var cfg = {
xtype: 'webview'
,id: 'tab_'+service.get('id')

189
app/store/ServicesList.js

@ -25,17 +25,17 @@ Ext.define('Rambox.store.ServicesList', {
id: 'whatsapp'
,logo: 'whatsapp.png'
,name: 'WhatsApp'
,description: 'WhatsApp is a cross-platform mobile messaging app for iPhone, BlackBerry, Android, Windows Phone and Nokia. Send text, video, images, audio for free.'
,description: locale['services[0]']
,url: 'https://web.whatsapp.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("infinite-list-item"),b=0;for(i=0;i<a.length;i++)if(!(a[i].getElementsByClassName("icon-muted").length>0||0===a[i].getElementsByClassName("unread-count").length)){var c=parseInt(a[i].getElementsByClassName("unread-count")[0].innerHTML.trim());b+=isNaN(c)?0:c}updateBadge(b)}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}var originalTitle=document.title;setInterval(checkUnread,1e3);'
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("infinite-list-item"),b=0;for(i=0;i<a.length;i++)if(!(a[i].getElementsByClassName("icon-muted").length>0||0===a[i].getElementsByClassName("unread-count").length)){var c=parseInt(a[i].getElementsByClassName("unread-count")[0].innerHTML.trim());b+=isNaN(c)?0:c}updateBadge(b)}function updateBadge(count) { if (count && count >= 1) { rambox.setUnreadCount(count); } else { rambox.clearUnreadCount(); } }setInterval(checkUnread,1e3);'
,dont_update_unread_from_title: true
},
{
id: 'slack'
,logo: 'slack.png'
,name: 'Slack'
,description: 'Slack brings all your communication together in one place. It’s real-time messaging, archiving and search for modern teams.'
,description: locale['services[1]']
,url: 'https://___.slack.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var a=0,b=0;$(".unread_msgs").each(function(){a+=isNaN(parseInt($(this).html())) ? 0 : parseInt($(this).html())}),$(".unread_highlights").each(function(){b+=isNaN(parseInt($(this).html())) ? 0 : parseInt($(this).html())}),updateBadge(a,b)}function updateBadge(a,b){var c=b>0?"("+b+") ":a>0?"(•) ":"";document.title=c+originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
@ -44,7 +44,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'noysi'
,logo: 'noysi.png'
,name: 'Noysi'
,description: 'Noysi is a communication tool for teams where privacy is guaranteed. With Noysi you can access all your conversations and files in seconds from anywhere and unlimited.'
,description: locale['services[2]']
,url: 'https://noysi.com/#/identity/sign-in'
,type: 'messaging'
},
@ -52,7 +52,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'messenger'
,logo: 'messenger.png'
,name: 'Messenger'
,description: 'Instantly reach the people in your life for free. Messenger is just like texting, but you don\'t have to pay for every message.'
,description: locale['services[3]']
,url: 'https://www.messenger.com/login/'
,type: 'messaging'
,titleBlink: true
@ -62,7 +62,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'skype'
,logo: 'skype.png'
,name: 'Skype'
,description: 'Stay in touch with family and friends for free. Get international calling, free online calls and Skype for Business on desktop and mobile.'
,description: locale['services[4]']
,url: 'https://web.skype.com/'
,type: 'messaging'
,userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Safari/537.36 Edge/13.10586'
@ -72,7 +72,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'hangouts'
,logo: 'hangouts.png'
,name: 'Hangouts'
,description: 'Hangouts bring conversations to life with photos, emoji, and even group video calls for free. Connect with friends across computers, Android, and Apple devices.'
,description: locale['services[5]']
,url: 'https://hangouts.google.com/'
,type: 'messaging'
,titleBlink: true
@ -84,7 +84,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'hipchat'
,logo: 'hipchat.png'
,name: 'HipChat'
,description: 'HipChat is hosted group chat and video chat built for teams. Supercharge real-time collaboration with persistent chat rooms, file sharing, and screen sharing.'
,description: locale['services[6]']
,url: 'https://___.hipchat.com/chat'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("hc-badge"),t=0;for(i=0;i<e.length;i++)t+=parseInt(e[i].innerHTML.trim());updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
@ -94,7 +94,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'telegram'
,logo: 'telegram.png'
,name: 'Telegram'
,description: 'Telegram is a messaging app with a focus on speed and security. It’s super-fast, simple, secure and free.'
,description: locale['services[7]']
,url: 'https://web.telegram.org/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("im_dialog_badge badge"),t=0;for(i=0;i<e.length;i++)if(!e[i].classList.contains("im_dialog_badge_muted")){t+=parseInt(e[i].innerHTML.trim())}updateBadge(t)}function updateBadge(e){e>=1?rambox.setUnreadCount(e):rambox.clearUnreadCount()}setInterval(checkUnread,3000);'
@ -104,7 +104,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'wechat'
,logo: 'wechat.png'
,name: 'WeChat'
,description: 'WeChat is a free messaging calling app that allows you to easily connect with family; friends across countries. It’s the all-in-one communications app for free text (SMS/MMS), voice; video calls, moments, photo sharing, and games.'
,description: locale['services[8]']
,url: 'https://web.wechat.com/'
,type: 'messaging'
},
@ -112,7 +112,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'gmail'
,logo: 'gmail.png'
,name: 'Gmail'
,description: 'Gmail, Google\'s free email service, is one of the world\'s most popular email programs.'
,description: locale['services[9]']
,url: 'https://mail.google.com/mail/'
,type: 'email'
,allow_popups: true
@ -123,17 +123,18 @@ Ext.define('Rambox.store.ServicesList', {
id: 'inbox'
,logo: 'inbox.png'
,name: 'Inbox'
,description: 'Inbox by Gmail is a new app from the Gmail team. Inbox is an organized place to get things done and get back to what matters. Bundles keep emails organized.'
,description: locale['services[10]']
,url: 'http://inbox.google.com/?cid=imp'
,type: 'email'
,manual_notifications: true
,js_unread: 'function checkUnread(){updateBadge(document.getElementsByClassName("ss").length)}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3e3);'
,note: 'Please be sure to sign out to Hangouts inside Inbox because cause problems. <a href="https://github.com/saenzramiro/rambox/wiki/Inbox" target="_blank">Read more...</a>'
},
{
id: 'chatwork'
,logo: 'chatwork.png'
,name: 'ChatWork'
,description: 'ChatWork is a group chat app for business. Secure messaging, video chat, task management and file sharing. Real-time communication and increase productivity for teams.'
,description: locale['services[11]']
,url: 'https://www.chatwork.com/login.php'
,type: 'messaging'
,note: 'To enable desktop notifications, you have to go to Options inside ChatWork.'
@ -142,7 +143,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'groupme'
,logo: 'groupme.png'
,name: 'GroupMe'
,description: 'GroupMe brings group text messaging to every phone. Group message with the people in your life that are important to you.'
,description: locale['services[12]']
,url: 'https://web.groupme.com/signin'
,type: 'messaging'
,note: 'To enable desktop notifications, you have to go to Options inside GroupMe. To count unread messages, be sure to be in Chats.'
@ -153,7 +154,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'grape'
,logo: 'grape.png'
,name: 'Grape'
,description: 'The world\'s most advanced team chat meets enterprise search'
,description: locale['services[13]']
,url: 'https://chatgrape.com/accounts/login/'
,type: 'messaging'
},
@ -161,7 +162,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'gitter'
,logo: 'gitter.png'
,name: 'Gitter'
,description: 'Gitter is built on top of GitHub and is tightly integrated with your organisations, repositories, issues and activity.'
,description: locale['services[14]']
,url: 'https://gitter.im/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("room-item__unread-indicator"),t=0;for(i=0;i<e.length;i++)t+=isNaN(parseInt(e[i].innerHTML.trim())) ? 0 : parseInt(e[i].innerHTML.trim());updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
@ -170,7 +171,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'steam'
,logo: 'steam.png'
,name: 'Steam Chat'
,description: 'Steam is a digital distribution platform developed by Valve Corporation offering digital rights management (DRM), multiplayer gaming and social networking services.'
,description: locale['services[15]']
,url: 'https://steamcommunity.com/chat'
,type: 'messaging'
,note: 'To enable desktop notifications, you have to go to Options inside Steam Chat.'
@ -180,7 +181,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'discord'
,logo: 'discord.png'
,name: 'Discord'
,description: 'Step up your game with a modern voice & text chat app. Crystal clear voice, multiple server and channel support, mobile apps, and more.'
,description: locale['services[16]']
,url: 'https://discordapp.com/login'
,type: 'messaging'
,titleBlink: true
@ -191,7 +192,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'outlook'
,logo: 'outlook.png'
,name: 'Outlook'
,description: 'Take control. Do more. Outlook is the free email and calendar service that helps you stay on top of what matters and get things done.'
,description: locale['services[17]']
,url: 'https://mail.live.com/'
,type: 'email'
,manual_notifications: true
@ -201,7 +202,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'outlook365'
,logo: 'outlook365.png'
,name: 'Outlook 365'
,description: 'Outlook for Business'
,description: locale['services[18]']
,url: 'https://outlook.office.com/owa/'
,type: 'email'
,manual_notifications: true
@ -211,7 +212,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'yahoo'
,logo: 'yahoo.png'
,name: 'Yahoo! Mail'
,description: 'Web-based email service offered by the American company Yahoo!. The service is free for personal use, and paid-for business email plans are available.'
,description: locale['services[19]']
,url: 'https://mail.yahoo.com/'
,type: 'email'
,note: 'To enable desktop notifications, you have to go to Options inside Yahoo! Mail.'
@ -220,15 +221,24 @@ Ext.define('Rambox.store.ServicesList', {
id: 'protonmail'
,logo: 'protonmail.png'
,name: 'ProtonMail'
,description: 'Free and web-based encrypted email service founded in 2013 at the CERN research facility. ProtonMail is designed as a zero-knowledge system,[note 1] using client-side encryption to protect emails and user data before they are sent to ProtonMail servers, in contrast to other common webmail services such as Gmail and Hotmail.'
,description: locale['services[20]']
,url: 'https://mail.protonmail.com/inbox'
,type: 'email'
},
{
id: 'protonmailch'
,logo: 'protonmail.png'
,name: 'ProtonMail CH'
,description: locale['services[20]']
,url: 'https://app.protonmail.ch/inbox'
,type: 'email'
,note: 'Read <a href="https://protonmail.com/support/knowledge-base/what-is-the-difference-between-protonmail-com-and-protonmail-ch/" target="_blank">HERE</a> to see the differences between protonmail.com and protonmail.ch.'
},
{
id: 'tutanota'
,logo: 'tutanota.png'
,name: 'Tutanota'
,description: 'Tutanota is an open-source end-to-end encrypted email software and freemium hosted secure email service based on this software'
,description: locale['services[21]']
,url: 'https://app.tutanota.de/'
,type: 'email'
},
@ -236,7 +246,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'hushmail'
,logo: 'hushmail.png'
,name: 'Hushmail'
,description: 'Web-based email service offering PGP-encrypted e-mail and vanity domain service. Hushmail offers "free" and "paid" versions of service. Hushmail uses OpenPGP standards and the source is available for download.'
,description: locale['services[22]']
,url: 'https://www.hushmail.com/hushmail/index.php'
,type: 'email'
},
@ -244,7 +254,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'missive'
,logo: 'missive.png'
,name: 'Missive'
,description: 'Collaborative email and threaded group chat for productive teams. A single app for all your internal and external communication.'
,description: locale['services[23]']
,url: 'https://mail.missiveapp.com/login'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("unseen-count"),t=0;for(i=0;i<e.length;i++)t+=parseInt(e[i].innerHTML.trim());updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
@ -253,7 +263,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'rocketchat'
,logo: 'rocketchat.png'
,name: 'Rocket Chat'
,description: 'From group messages and video calls all the way to helpdesk killer features our goal is to become the number one cross-platform open source chat solution.'
,description: locale['services[24]']
,url: '___'
,type: 'messaging'
,note: 'You have to use this service by signing in with your email or username (No SSO allowed yet).'
@ -262,7 +272,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'wire'
,logo: 'wire.png'
,name: 'Wire'
,description: 'HD quality calls, private and group chats with inline photos, music and video. Also available for your phone or tablet.'
,description: locale['services[25]']
,url: 'https://app.wire.com/'
,type: 'messaging'
},
@ -270,7 +280,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'sync'
,logo: 'sync.png'
,name: 'Sync'
,description: 'Sync is a business chat tool that will boost productivity for your team.'
,description: locale['services[26]']
,url: 'https://m.wantedly.com/login'
,type: 'messaging'
},
@ -285,7 +295,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'yahoomessenger'
,logo: 'yahoomessenger.png'
,name: 'Yahoo! Messenger'
,description: 'Allows you to instant message with anyone on the Yahoo server. Tells you when you get mail, and gives stock quotes.'
,description: locale['services[28]']
,url: 'https://messenger.yahoo.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){updateBadge(document.getElementsByClassName("list-item-unread-indicator").length)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
@ -294,7 +304,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'voxer'
,logo: 'voxer.png'
,name: 'Voxer'
,description: 'Voxer is a messaging app for your smartphone with live voice (like a PTT walkie talkie), text, photo and location sharing.'
,description: locale['services[29]']
,url: 'https://web.voxer.com/'
,type: 'messaging'
},
@ -302,7 +312,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'dasher'
,logo: 'dasher.png'
,name: 'Dasher'
,description: 'Dasher lets you say what you really want with pics, GIFs, links and more. Take a poll to find out what your friends really think of your new boo.'
,description: locale['services[30]']
,url: 'https://dasher.im/'
,type: 'messaging'
},
@ -310,7 +320,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'flowdock'
,logo: 'flowdock.png'
,name: 'Flowdock'
,description: 'Flowdock is your team\'s chat with a shared inbox. Teams using Flowdock stay up-to-date, react in seconds instead of days, and never forget anything'
,description: locale['services[31]']
,url: 'https://www.flowdock.com/login'
,type: 'messaging'
},
@ -318,7 +328,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'mattermost'
,logo: 'mattermost.png'
,name: 'Mattermost'
,description: 'Mattermost is an open source, self-hosted Slack-alternative. As an alternative to proprietary SaaS messaging, Mattermost brings all your team communication into one place, making it searchable and accessible anywhere.'
,description: locale['services[32]']
,url: '___'
,type: 'messaging'
,js_unread: 'Object.defineProperty(document,"title",{configurable:!0,set:function(a){document.getElementsByTagName("title")[0].innerHTML=a[0]==="*"?"(•) Mattermost":a},get:function(){return document.getElementsByTagName("title")[0].innerHTML}});'
@ -327,7 +337,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'dingtalk'
,logo: 'dingtalk.png'
,name: 'DingTalk'
,description: 'DingTalk is a multi-sided platform empowers small and medium-sized business to communicate effectively.'
,description: locale['services[33]']
,url: 'https://im.dingtalk.com/'
,type: 'messaging'
},
@ -335,7 +345,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'mysms'
,logo: 'mysms.png'
,name: 'mysms'
,description: 'The mysms family of applications helps you text anywhere and enhances your messaging experience on your smartphone, tablet and computer.'
,description: locale['services[34]']
,url: 'https://app.mysms.com/#login'
,type: 'messaging'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("unread"),t=0;for(i=0;i<e.length;i++)t+=parseInt(e[i].firstChild.innerHTML.trim());updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}"https://app.mysms.com/#login"===document.baseURI&&(document.getElementsByClassName("innerPanel")[0].rows[0].style.display="none",document.getElementsByClassName("innerPanel")[0].rows[1].cells[0].firstElementChild.style.display="none",document.getElementsByClassName("msisdnLoginPanel")[0].style.display="inline");var originalTitle=document.title;setInterval(checkUnread,3000);'
@ -345,7 +355,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'icq'
,logo: 'icq.png'
,name: 'ICQ'
,description: 'ICQ is an open source instant messaging computer program that was first developed and popularized.'
,description: locale['services[35]']
,url: 'https://web.icq.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){updateBadge(parseInt(document.getElementsByClassName("nwa-msg-counter")[0].style.display==="block"?document.getElementsByClassName("nwa-msg-counter")[0].innerHTML.trim():0))}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
@ -354,7 +364,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'tweetdeck'
,logo: 'tweetdeck.png'
,name: 'TweetDeck'
,description: 'TweetDeck is a social media dashboard application for management of Twitter accounts.'
,description: locale['services[36]']
,url: 'https://tweetdeck.twitter.com/'
,type: 'messaging'
},
@ -362,7 +372,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'custom'
,logo: 'custom.png'
,name: '_Custom Service'
,description: 'Add a custom service if is not listed above.'
,description: locale['services[38]']
,url: '___'
,type: 'custom'
,allow_popups: true
@ -371,7 +381,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'zinc'
,logo: 'zinc.png'
,name: 'Zinc'
,description: 'Zinc is a secure communication app for mobile workers, with text, voice, video, file sharing and more.'
,description: locale['services[39]']
,url: 'https://zinc-app.com/'
,type: 'messaging'
},
@ -379,7 +389,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'freenode'
,logo: 'freenode.png'
,name: 'FreeNode'
,description: 'Freenode, formerly known as Open Projects Network, is an IRC network used to discuss peer-directed projects.'
,description: locale['services[40]']
,url: 'https://webchat.freenode.net/'
,type: 'messaging'
},
@ -387,7 +397,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'mightytext'
,logo: 'mightytext.png'
,name: 'Mighty Text'
,description: 'Text from your computer, sync\'d with your Android phone & number.'
,description: locale['services[41]']
,url: 'https://mightytext.net/web/'
,type: 'messaging'
},
@ -395,7 +405,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'roundcube'
,logo: 'roundcube.png'
,name: 'Roundcube'
,description: 'Free and open source webmail software for the masses, written in PHP.'
,description: locale['services[42]']
,url: '___'
,type: 'email'
},
@ -403,7 +413,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'horde'
,logo: 'horde.png'
,name: 'Horde'
,description: 'Horde is a free and open source web-based groupware.'
,description: locale['services[43]']
,url: '___'
,type: 'email'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("count"),t=0;for(i=0;i<e.length;i++)t+=parseInt(e[i].innerHTML.match(/\d+/g));updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
@ -413,7 +423,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'squirrelmail'
,logo: 'squirrelmail.png'
,name: 'SquirrelMail'
,description: 'SquirrelMail is a standards-based webmail package written in PHP.'
,description: locale['services[44]']
,url: '___'
,type: 'email'
,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("leftunseen"),t=0;for(i=0;i<e.length;i++)t+=parseInt(e[i].innerHTML);updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
@ -422,7 +432,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'zohoemail'
,logo: 'zohoemail.png'
,name: 'Zoho Email'
,description: 'Ad-free business Email Hosting with a clean, minimalist interface. Integrated Calendar, Contacts, Notes, Tasks apps.'
,description: locale['services[45]']
,url: 'https://mail.zoho.com/'
,type: 'email'
,js_unread: 'zmail.aInfo[zmail.accId].mailId = "a";'
@ -432,7 +442,7 @@ Ext.define('Rambox.store.ServicesList', {
id: 'zohochat'
,logo: 'zohochat.png'
,name: 'Zoho Chat'
,description: 'Zoho chat is a secure and scalable real-time communication and collaboration platform for teams to improve their productivity.'
,description: locale['services[46]']
,url: 'https://chat.zoho.com/'
,type: 'messaging'
,js_unread: 'NotifyByTitle.show = function(){};NotifyByTitle.start = function(){};NotifyByTitle.stop = function(){};function checkUnread(){var t=0;$(".msgnotify").each(function() { t += isNaN(parseInt($(this).html())) ? 0 : parseInt(parseInt($(this).html())) });updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
@ -480,6 +490,7 @@ Ext.define('Rambox.store.ServicesList', {
,description: 'Ryver is a team communication tool that organizes team collaboration, chats, files, and even emails into a single location, for any size team, for FREE.'
,url: 'https://___.ryver.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){updateBadge(parseInt(document.getElementsByClassName("scene-space-tab-button--flash").length))}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
},
{
id: 'aim'
@ -506,7 +517,8 @@ Ext.define('Rambox.store.ServicesList', {
,description: 'iCloud makes sure you always have the latest versions of your most important things — documents, photos, notes, contacts, and more — on all your devices. It can even help you locate a missing iPhone, iPad, iPod touch or Mac.'
,url: 'https://www.icloud.com/#mail'
,type: 'email'
,js_unread: 'Object.defineProperty(document,"title",{configurable:!0,set:function(a){var t = document.getElementsByName("mail")[0].contentWindow.document.body.getElementsByClassName("count digit");t = t.length===1?t[0].innerHTML:0;document.getElementsByTagName("title")[0].innerHTML="("+t+") iCloud Mail"},get:function(){return document.getElementsByTagName("title")[0].innerHTML}});'
,js_unread: 'function checkUnread(){updateBadge(document.querySelector(".current-app").querySelector(".sb-badge").style.display==="none"?0:parseInt(document.querySelector(".current-app").querySelector(".text").innerHTML.trim()))}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
,dont_update_unread_from_title: true
},
{
id: 'rainloop'
@ -579,14 +591,6 @@ Ext.define('Rambox.store.ServicesList', {
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("mx_RoomTile_nameContainer"),b=0;for(i=0;i<a.length;i++){var c=a[i].getElementsByClassName("mx_RoomTile_badge");for(ii=0;ii<c.length;ii++)parseInt(c[ii].textContent.trim())%1===0&&(b+=parseInt(c[ii].textContent.trim()))}updateBadge(b)}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,1e3);'
,custom_domain: true
},
{
id: 'actor'
,logo: 'actor.png'
,name: 'Actor'
,description: 'Free and Secure text, photo and voice messages over 2G/3G or Wi-Fi.'
,url: 'https://app.actor.im/'
,type: 'messaging'
},
{
id: 'socialcast'
,logo: 'socialcast.png'
@ -651,6 +655,9 @@ Ext.define('Rambox.store.ServicesList', {
,description: 'Flock is a free enterprise tool for business communication. Packed with tons of productivity features, Flock drives efficiency and boosts speed of execution.'
,url: 'https://web.flock.co/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("unreadMessages no-unread-mentions has-unread"),b=0;for(i=0;i<a.length;i++)b+=parseInt(a[i].innerHTML.trim());updateBadge(b)}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
,dont_update_unread_from_title: true
},
{
id: 'crisp'
@ -703,6 +710,7 @@ Ext.define('Rambox.store.ServicesList', {
,description: 'Microsoft Teams is the chat-based workspace in Office 365 that integrates all the people, content, and tools your team needs to be more engaged and effective.'
,url: 'https://teams.microsoft.com'
,type: 'messaging'
,userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'
},
{
id: 'kezmo'
@ -728,6 +736,7 @@ Ext.define('Rambox.store.ServicesList', {
,description: 'Manage your professional identity. Build and engage with your professional network. Access knowledge, insights and opportunities.'
,url: 'https://www.linkedin.com/messaging'
,type: 'messaging'
,css: 'nav, .ad-banner-container, .right-rail { display: none !important; } .neptune-grid { width: 100% !important; padding:0!important; } .authentication-outlet { margin: 0 !important; }.neptune-grid.two-column .core-rail{width:100%!important;}.msg-messaging-container{height:calc(100%)!important;}.msg-conversations-container{flex:1!important;}.msg-thread{flex:3!important;max-width:none!important;min-width:none!important;}#messaging{height:calc(100vh)!important;}#msg-overlay{display:none!important;}body{overflow-y:hidden!important;}'
},
{
id: 'zyptonite'
@ -744,24 +753,80 @@ Ext.define('Rambox.store.ServicesList', {
,logo: 'fastmail.png'
,name: 'FastMail'
,description: 'Secure, reliable email hosting for businesses, families and professionals. Premium email with no ads, excellent spam protection and rapid personal support.'
,url: 'https://www.fastmail.com/login/'
,url: 'https://www.fastmail.com/mail/'
,type: 'mail'
,js_unread: 'setTimeout(function(){O.WindowController.openExternal=function(a){var b=document.createElement("a");b.href=a,b.setAttribute("target","_blank"),b.click()};},3000);'
},
{
id: 'hibox'
{
id: 'hibox'
,logo: 'hibox.png'
,name: 'Hibox'
,description: 'Hibox is a secure and private messaging platform for your business.'
,url: 'https://app.hibox.co/'
,type: 'messaging'
},
{
id: 'jandi'
{
id: 'jandi'
,logo: 'jandi.png'
,name: 'Jandi'
,description: 'Jandi is a group-oriented enterprise messaging platform with an integrated suite of collaboration tools for workplace.'
,url: 'https://___.jandi.com/'
,type: 'messaging'
}
]
},
{
id: 'messengerpages'
,logo: 'messengerpages.png'
,name: 'Messenger for Pages'
,description: 'Chat with the people of your Facebook Page.'
,url: 'https://facebook.com/___/messages/'
,type: 'messaging'
,css: '#pagelet_bluebar{display:none;}#pages_manager_top_bar_container{display:none;}#pagelet_sidebar{display:none;}#pagelet_dock{display:none;}#pages_manager_top_bar_container + div{margin:0;width:100%;}#pages_manager_top_bar_container + div > div > div{padding:0;}#pages_manager_top_bar_container + div > div > div div div:last-child{top:0!important;}'
},
{
id: 'vk'
,logo: 'vk.png'
,name: 'VK Messenger'
,description: 'Simple and Easy App for Messaging on VK.'
,url: 'https://vk.com/im'
,type: 'messaging'
,js_unread: 'function checkUnread(){updateBadge(parseInt(document.getElementById("l_msg").innerText.replace(/\D+/g,"")))}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
,css: '#page_header_cont{display:none;}#side_bar{display:none;}#page_body{width:100%!important;margin-top:0;}.im-page_classic.im-page{width:700px!important;}.im-right-menu.ui_rmenu{margin-left:715px!important;}.im-page{padding-top:0!important;}.im-page_classic.im-page .im-page--header{border-top:0!important;width:700px!important;max-width:700px!important;top:0!important;margin-top:0!important;}.im-page_classic.im-page .im-page--dialogs-footer{width:700px!important;max-width:700px!important;}.im-page .im-page--dialogs{padding-top:6px!important;}.im-page_classic .im-page--chat-header{top:0!important;width:700px!important;}.im-page_classic.im-page .im-page--chat-input{width:700px!important;border-bottom:0!important;}.im-chat-input.im-chat-input_classic .im-chat-input--textarea{width:588px!important;}.im-right-menu.ui_rmenu{top:0!important;}'
},
{
id: 'mastodon'
,logo: 'mastodon.png'
,name: 'Mastodon'
,description: 'Mastodon is a free, open-source social network server. A decentralized solution to commercial platforms, it avoids the risks of a single company monopolizing your communication. Anyone can run Mastodon and participate in the social network seamlessly.'
,url: 'https://mastodon.social/auth/sign_in'
,type: 'messaging'
,custom_domain: true
,note: '<a href="https://instances.mastodon.xyz/" target="_blank">List of instances</a>'
},
{
id: 'teamworkchat'
,logo: 'teamworkchat.png'
,name: 'Teamwork Chat'
,description: 'Say goodbye to email. Take your online collaboration to the next level with Teamwork Chat and keep all team discussions in one place. Chat to your team in a fun and informal way with Teamwork Chat.'
,url: 'https://___.teamwork.com/chat'
,type: 'messaging'
,js_unread: 'function checkUnread(){updateBadge(parseInt(document.getElementsByClassName("sidebar-notification-indicator").length > 0 ? document.getElementsByClassName("sidebar-notification-indicator")[0].innerHTML : 0))}function updateBadge(a){a>=1?rambox.setUnreadCount(a):rambox.clearUnreadCount()}setInterval(checkUnread,3e3);'
,dont_update_unread_from_title: true
},
{
id: 'clocktweets'
,logo: 'clocktweets.png'
,name: 'ClockTweets'
,description: 'Schedule your Tweets with love. Save time and manage your social media strategy easily.'
,url: 'https://clocktweets.com/dashboard/'
,type: 'messaging'
},
{
id: 'intercom'
,logo: 'intercom.png'
,name: 'Intercom'
,description: 'Intercom makes it easy to communicate with your customers personally, at scale. Designed to feel like the messaging apps you use every day, Intercom lets you talk to consumers almost anywhere: inside your app, on your website, across social media and via email.'
,url: 'https://app.intercom.io'
,type: 'messaging'
}
]
});

2
app/util/Notifier.js

@ -49,7 +49,7 @@ Ext.define('Rambox.util.Notifier', {
});
notification.onclick = function() {
require('electron').remote.getCurrentWindow().show();
ipc.send('toggleWin', true);
Ext.cq1('app-main').setActiveTab(view);
};
}

69
app/ux/Auth0.js

@ -13,7 +13,8 @@ Ext.define('Rambox.ux.Auth0', {
autoclose: true
,autofocus: true
,auth: {
redirect: false
redirect: false
,params: {scope: 'openid offline_access'}
}
,theme: {
logo: 'resources/Icon.png'
@ -25,7 +26,7 @@ Ext.define('Rambox.ux.Auth0', {
,popupOptions: {
nodeIntegration: 'no'
}
//,language: 'en'
,language: localStorage.getItem('locale-auth0') === null ? 'en' : localStorage.getItem('locale-auth0')
});
me.auth0 = new Auth0({ clientID: auth0Cfg.clientID, domain : auth0Cfg.domain });
@ -45,7 +46,7 @@ Ext.define('Rambox.ux.Auth0', {
}
// Display a spinner while waiting
Ext.Msg.wait('Please wait until we get your configuration.', 'Connecting...');
Ext.Msg.wait(locale['app.window[29]'], locale['app.window[28]']);
// Google Analytics Event
ga_storage._trackEvent('Users', 'loggedIn');
@ -54,6 +55,7 @@ Ext.define('Rambox.ux.Auth0', {
// Save the profile and JWT.
localStorage.setItem('profile', JSON.stringify(profile));
localStorage.setItem('id_token', authResult.idToken);
localStorage.setItem('refresh_token', authResult.refreshToken);
if ( !Ext.isEmpty(profile.user_metadata) && !Ext.isEmpty(profile.user_metadata.services) ) {
Ext.each(profile.user_metadata.services, function(s) {
@ -81,9 +83,10 @@ Ext.define('Rambox.ux.Auth0', {
var lastupdate = (new Date()).toJSON();
var services = [];
Ext.getStore('Services').each(function(service) {
delete service.data.id;
delete service.data.zoomLevel;
services.push(service.data);
var s = Ext.clone(service);
delete s.data.id;
delete s.data.zoomLevel;
services.push(s.data);
});
Ext.Ajax.request({
@ -95,6 +98,7 @@ Ext.define('Rambox.ux.Auth0', {
Ext.Msg.hide();
// Save the last update in localStorage
var profile = Ext.decode(localStorage.getItem('profile'));
if ( !profile.user_metadata ) profile.user_metadata = {};
profile.user_metadata.services_lastupdate = lastupdate;
localStorage.setItem('profile', Ext.encode(profile));
Ext.cq1('app-main').getViewModel().set('last_sync', new Date(lastupdate).toUTCString());
@ -108,6 +112,8 @@ Ext.define('Rambox.ux.Auth0', {
});
}
,failure: function(response) {
if ( response.status === 401 ) return me.renewToken(me.backupConfiguration);
Ext.Msg.hide();
Ext.toast({
html: '<i class="fa fa-times fa-3x fa-pull-left" aria-hidden="true"></i> Error occurred when trying to backup your configuration.'
@ -124,10 +130,14 @@ Ext.define('Rambox.ux.Auth0', {
,restoreConfiguration: function() {
var me = this;
Ext.cq1('app-main').getController().removeAllServices(false, function() {
me.lock.getProfile(localStorage.getItem('id_token'), function (err, profile) {
if (err) return alert('There was an error getting the profile: ' + err.message);
me.lock.getProfile(localStorage.getItem('id_token'), function (err, profile) {
if ( err ) {
if ( err.error === 401 ) return me.renewToken(me.restoreConfiguration);
return alert('There was an error getting the profile: ' + err.message);
}
// First we remove all current services
Ext.cq1('app-main').getController().removeAllServices(false, function() {
Ext.each(profile.user_metadata.services, function(s) {
var service = Ext.create('Rambox.model.Service', s);
service.save();
@ -143,7 +153,21 @@ Ext.define('Rambox.ux.Auth0', {
var me = this;
me.lock.getProfile(localStorage.getItem('id_token'), function (err, profile) {
if (err) return alert('There was an error getting the profile: ' + err.message);
if ( err ) {
if ( err.error === 401 ) return me.renewToken(me.checkConfiguration);
return alert('There was an error getting the profile: ' + err.message);
}
if ( !profile.user_metadata ) {
Ext.toast({
html: 'You don\'t have any backup yet.'
,title: 'Synchronize Configuration'
,width: 300
,align: 't'
,closable: false
});
return;
}
if ( Math.floor(new Date(profile.user_metadata.services_lastupdate) / 1000) > Math.floor(new Date(Ext.decode(localStorage.getItem('profile')).user_metadata.services_lastupdate) / 1000) ) {
Ext.toast({
@ -165,6 +189,30 @@ Ext.define('Rambox.ux.Auth0', {
});
}
,renewToken: function(callback) {
var me = this;
Ext.Ajax.request({
url: 'https://rambox.auth0.com/delegation'
,method: 'POST'
,jsonData: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer'
,client_id: auth0Cfg.clientID
,refresh_token: localStorage.getItem('refresh_token')
,api_type: 'app'
}
,success: function(response) {
var json = Ext.decode(response.responseText);
localStorage.setItem('id_token', json.id_token);
if ( Ext.isFunction(callback) ) callback.bind(me)();
}
,failure: function(response) {
console.error(response);
}
});
}
,login: function() {
var me = this;
@ -176,5 +224,6 @@ Ext.define('Rambox.ux.Auth0', {
localStorage.removeItem('profile');
localStorage.removeItem('id_token');
localStorage.removeItem('refresh_token');
}
});

121
app/ux/WebView.js

@ -38,7 +38,7 @@ Ext.define('Rambox.ux.WebView',{
Ext.apply(me, {
items: me.webViewConstructor()
,title: me.record.get('name')
,title: me.record.get('tabname') ? me.record.get('name') : ''
,icon: me.record.get('type') === 'custom' ? (me.record.get('logo') === '' ? 'resources/icons/custom.png' : me.record.get('logo')) : 'resources/icons/'+me.record.get('logo')
,src: me.record.get('url')
,type: me.record.get('type')
@ -108,14 +108,14 @@ Ext.define('Rambox.ux.WebView',{
}
,'-'
,{
text: 'Reload'
text: locale['app.webview[0]']
,glyph: 'xf021@FontAwesome'
,scope: me
,handler: me.reloadService
}
,'-'
,{
text: 'Toggle Developer Tools'
text: locale['app.webview[3]']
,glyph: 'xf121@FontAwesome'
,scope: me
,handler: me.toggleDevTools
@ -123,26 +123,29 @@ Ext.define('Rambox.ux.WebView',{
]
}
}
,bbar: {
xtype: 'statusbar'
,defaultText: '<i class="fa fa-check fa-fw" aria-hidden="true"></i> Ready'
,busyIconCls : ''
,busyText: '<i class="fa fa-circle-o-notch fa-spin fa-fw"></i> Loading...'
,items: [
,{
xtype: 'tbtext'
,itemId: 'url'
}
]
}
,listeners: {
afterrender: me.onAfterRender
,beforedestroy: me.onBeforeDestroy
}
});
if ( me.record.get('statusbar') ) {
Ext.apply(me, {
bbar: me.statusBarConstructor(false)
});
} else {
me.items.push(me.statusBarConstructor(true));
}
me.callParent(config);
}
,onBeforeDestroy: function() {
var me = this;
me.setUnreadCount(0);
}
,webViewConstructor: function( enabled ) {
var me = this;
@ -157,7 +160,7 @@ Ext.define('Rambox.ux.WebView',{
,padding: 100
};
} else {
cfg = {
cfg = [{
xtype: 'component'
,hideMode: 'offsets'
,autoRender: true
@ -165,7 +168,7 @@ Ext.define('Rambox.ux.WebView',{
,autoEl: {
tag: 'webview'
,src: me.record.get('url')
,style: 'width:100%;height:100%;'
,style: 'width:100%;height:100%;visibility:visible;'
,partition: 'persist:' + me.record.get('type') + '_' + me.id.replace('tab_', '') + (localStorage.getItem('id_token') ? '_' + Ext.decode(localStorage.getItem('profile')).user_id : '')
,plugins: 'true'
,allowtransparency: 'on'
@ -175,14 +178,50 @@ Ext.define('Rambox.ux.WebView',{
,useragent: Ext.getStore('ServicesList').getById(me.record.get('type')).get('userAgent')
,preload: './resources/js/rambox-service-api.js'
}
};
}];
if ( Ext.getStore('ServicesList').getById(me.record.get('type')).get('allow_popups') ) cfg.autoEl.allowpopups = 'on';
if ( Ext.getStore('ServicesList').getById(me.record.get('type')).get('allow_popups') ) cfg[0].autoEl.allowpopups = 'on';
}
return cfg;
}
,statusBarConstructor: function(floating) {
var me = this;
return {
xtype: 'statusbar'
,hidden: !me.record.get('statusbar')
,keep: me.record.get('statusbar')
,y: floating ? '-18px' : 'auto'
,height: 19
,dock: 'bottom'
,defaultText: '<i class="fa fa-check fa-fw" aria-hidden="true"></i> Ready'
,busyIconCls : ''
,busyText: '<i class="fa fa-circle-o-notch fa-spin fa-fw"></i> '+locale['app.webview[4]']
,items: [
{
xtype: 'tbtext'
,itemId: 'url'
}
,{
xtype: 'button'
,glyph: 'xf00d@FontAwesome'
,scale: 'small'
,ui: 'decline'
,padding: 0
,scope: me
,hidden: floating
,handler: me.closeStatusBar
,tooltip: {
text: 'Close statusbar until next time'
,mouseOffset: [0,-60]
}
}
]
};
}
,onAfterRender: function() {
var me = this;
@ -199,10 +238,12 @@ Ext.define('Rambox.ux.WebView',{
// Show and hide spinner when is loading
webview.addEventListener("did-start-loading", function() {
console.info('Start loading...', me.src);
if ( !me.down('statusbar').closed || !me.down('statusbar').keep ) me.down('statusbar').show();
me.down('statusbar').showBusy();
});
webview.addEventListener("did-stop-loading", function() {
me.down('statusbar').clearStatus({useDefaults: true});
if ( !me.down('statusbar').keep ) me.down('statusbar').hide();
});
webview.addEventListener("did-finish-load", function(e) {
@ -238,7 +279,9 @@ Ext.define('Rambox.ux.WebView',{
,width: '80%'
,height: '80%'
,maximizable: true
,modal: true
,resizable: true
,draggable: true
,collapsible: true
,items: {
xtype: 'component'
,hideMode: 'offsets'
@ -264,7 +307,9 @@ Ext.define('Rambox.ux.WebView',{
,width: e.options.width
,height: e.options.height
,maximizable: true
,modal: true
,resizable: true
,draggable: true
,collapsible: true
,items: {
xtype: 'component'
,hideMode: 'offsets'
@ -334,9 +379,13 @@ Ext.define('Rambox.ux.WebView',{
} else {
callback(false);
}
me.down('statusbar').keep = true;
me.down('statusbar').show();
me.down('statusbar').setStatus({
text: '<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> Certification Warning'
});
me.down('statusbar').down('button').show();
});
});
@ -361,6 +410,7 @@ Ext.define('Rambox.ux.WebView',{
function handleClearUnreadCount() {
me.tab.setBadgeText('');
me.currentUnreadCount = 0;
me.setUnreadCount(0);
}
/**
@ -373,9 +423,7 @@ Ext.define('Rambox.ux.WebView',{
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));
me.doManualNotification(count);
me.setUnreadCount(count);
}
}
}
@ -401,7 +449,7 @@ Ext.define('Rambox.ux.WebView',{
}
webview.addEventListener('did-get-redirect-request', function( e ) {
if ( e.isMainFrame ) Ext.defer(function() { webview.loadURL(e.newURL); }, 1000); // Applied a defer because sometimes is not redirecting. TweetDeck 2FA is an example.
if ( e.isMainFrame && me.record.get('type') === 'tweetdeck' ) Ext.defer(function() { webview.loadURL(e.newURL); }, 1000); // Applied a defer because sometimes is not redirecting. TweetDeck 2FA is an example.
});
webview.addEventListener('update-target-url', function( url ) {
@ -412,7 +460,7 @@ Ext.define('Rambox.ux.WebView',{
,setUnreadCount: function(newUnreadCount) {
var me = this;
if (newUnreadCount === parseInt(newUnreadCount,10) && me.record.get('includeInGlobalUnreadCounter') === true) {
if ( !isNaN(newUnreadCount) && (function(x) { return (x | 0) === x; })(parseFloat(newUnreadCount)) && me.record.get('includeInGlobalUnreadCounter') === true) {
Rambox.util.UnreadCounter.setUnreadCountForService(me.record.get('id'), newUnreadCount);
} else {
Rambox.util.UnreadCounter.clearUnreadCountForService(me.record.get('id'));
@ -511,6 +559,27 @@ Ext.define('Rambox.ux.WebView',{
if ( me.record.get('enabled') ) webview.setAudioMuted(muted);
}
,closeStatusBar: function() {
var me = this;
me.down('statusbar').hide();
me.down('statusbar').closed = true;
me.down('statusbar').keep = me.record.get('statusbar');
}
,setStatusBar: function(keep) {
var me = this;
me.down('statusbar').destroy();
if ( keep ) {
me.addDocked(me.statusBarConstructor(false));
} else {
me.add(me.statusBarConstructor(true));
}
me.down('statusbar').keep = keep;
}
,setNotifications: function(notification, calledFromDisturb) {
var me = this;
var webview = me.down('component').el.dom;

168
app/view/add/Add.js

@ -27,7 +27,7 @@ Ext.define('Rambox.view.add.Add',{
,initComponent: function() {
var me = this;
me.title = (!me.edit ? 'Add ' : 'Edit ') + me.record.get('name');
me.title = (!me.edit ? locale['app.window[0]'] : locale['app.window[1]']) + ' ' + me.record.get('name');
me.icon = me.record.get('type') === 'custom' ? (!me.edit ? 'resources/icons/custom.png' : (me.record.get('logo') === '' ? 'resources/icons/custom.png' : me.record.get('logo'))) : 'resources/icons/'+me.record.get('logo');
me.items = [
{
@ -35,7 +35,8 @@ Ext.define('Rambox.view.add.Add',{
,items: [
{
xtype: 'textfield'
,fieldLabel: 'Name'
,fieldLabel: locale['app.window[2]']
,labelWidth: 40
,value: me.record.get('type') === 'custom' ? (me.edit ? me.record.get('name') : '') : me.record.get('name')
,name: 'serviceName'
,allowBlank: true
@ -43,12 +44,22 @@ Ext.define('Rambox.view.add.Add',{
}
,{
xtype: 'container'
,layout: 'column'
,layout: 'hbox'
,hidden: me.edit ? me.service.get('url').indexOf('___') === -1 && !me.service.get('custom_domain') : me.record.get('url').indexOf('___') === -1 && !me.record.get('custom_domain')
,items: [
{
xtype: 'label'
,text: locale['app.window[17]']+':'
,width: 45
}
,{
xtype: 'button'
,text: me.edit ? me.service.get('url').split('___')[0] : me.record.get('url').split('___')[0]
,style: 'border-top-right-radius:0;border-bottom-right-radius:0;'
,hidden: me.edit ? me.service.get('url').indexOf('___') === -1 ? true : me.service.get('type') === 'custom' || me.service.get('url') === '___' : me.record.get('url').indexOf('___') === -1 ? true : me.record.get('type') === 'custom' || me.record.get('url') === '___'
}
,{
xtype: 'textfield'
,fieldLabel: 'URL'
,name: 'url'
,value: me.edit && me.service.get('url').indexOf('___') >= 0 ? me.record.get('url').replace(me.service.get('url').split('___')[0], '').replace(me.service.get('url').split('___')[1], '') : (me.record.get('url').indexOf('___') === -1 ? me.record.get('url') : '')
,readOnly: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? true : me.service.get('url').indexOf('___') === -1 && !me.service.get('custom_domain')) : me.record.get('url').indexOf('___') === -1 && me.record.get('custom_domain')
@ -56,8 +67,8 @@ Ext.define('Rambox.view.add.Add',{
,submitEmptyText: false
,emptyText: me.record.get('url') === '___' ? 'http://' : ''
,vtype: me.record.get('url') === '___' ? 'url' : ''
,width: 275
,listeners: { specialkey: 'onEnter' }
,flex: 1
}
,{
xtype: 'cycle'
@ -100,6 +111,8 @@ Ext.define('Rambox.view.add.Add',{
activeItem.custom ? cycleBtn.previousSibling().setValue('') : cycleBtn.previousSibling().reset();
}
cycleBtn.previousSibling().previousSibling().setHidden(activeItem.custom ? true : me.edit ? me.service.get('url').indexOf('___') === -1 ? true : me.service.get('type') === 'custom' || me.service.get('url') === '___' : me.record.get('url').indexOf('___') === -1 ? true : me.record.get('type') === 'custom' || me.record.get('url') === '___');
cycleBtn.previousSibling().setReadOnly( activeItem.custom ? false : (me.edit ? me.service.get('url').indexOf('___') === -1 : me.record.get('url').indexOf('___') === -1) );
cycleBtn.nextSibling().setValue( activeItem.custom ? 2 : 1 );
}
@ -113,89 +126,118 @@ Ext.define('Rambox.view.add.Add',{
}
,{
xtype: 'textfield'
,fieldLabel: 'Logo'
,fieldLabel: locale['app.window[18]']
,emptyText: 'http://url.com/image.png'
,name: 'logo'
,vtype: me.record.get('type') === 'custom' ? 'url' : ''
,value: me.record.get('type') === 'custom' ? (me.edit ? me.record.get('logo') : '') : me.record.get('logo')
,allowBlank: true
,hidden: me.record.get('type') !== 'custom'
,labelWidth: 40
,margin: '5 0 0 0'
,listeners: { specialkey: 'onEnter' }
}
,{
xtype: 'fieldset'
,title: 'Options'
,title: locale['app.window[3]']
,margin: '10 0 0 0'
,items: [
{
xtype: 'checkbox'
,boxLabel: 'Align to Right'
,checked: me.edit ? (me.record.get('align') === 'right' ? true : false) : false
,name: 'align'
,uncheckedValue: 'left'
,inputValue: 'right'
}
,{
xtype: 'checkbox'
,boxLabel: 'Show notifications'
,name: 'notifications'
,checked: me.edit ? me.record.get('notifications') : true
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: 'Mute all sounds'
,name: 'muted'
,checked: me.edit ? me.record.get('muted') : false
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: 'Trust invalid authority certificates'
,name: 'trust'
,hidden: me.record.get('type') !== 'custom'
,checked: me.edit ? me.record.get('trust') : true
,uncheckedValue: false
,inputValue: true
xtype: 'checkboxgroup'
,columns: 2
,items: [
{
xtype: 'checkbox'
,boxLabel: locale['app.window[4]']
,checked: me.edit ? (me.record.get('align') === 'right' ? true : false) : false
,name: 'align'
,uncheckedValue: 'left'
,inputValue: 'right'
}
,{
xtype: 'checkbox'
,boxLabel: locale['app.window[6]']
,name: 'muted'
,checked: me.edit ? me.record.get('muted') : false
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: 'Show service name in Tab'
,name: 'tabname'
,checked: me.edit ? me.record.get('tabname') : true
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: locale['app.window[5]']
,name: 'notifications'
,checked: me.edit ? me.record.get('notifications') : true
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: 'Always display Status Bar'
,name: 'statusbar'
,checked: me.edit ? me.record.get('statusbar') : true
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: locale['app.window[19]']
,name: 'trust'
,hidden: me.record.get('type') !== 'custom'
,checked: me.edit ? me.record.get('trust') : true
,uncheckedValue: false
,inputValue: true
}
]
}
]
},
{
xtype: 'fieldset',
title: 'Unread counter',
margin: '10 0 0 0',
items: [
{
xtype: 'checkbox',
boxLabel: 'Display tab unread counter',
name: 'displayTabUnreadCounter',
checked: me.edit ? me.record.get('displayTabUnreadCounter') : true,
uncheckedValue: false,
inputValue: true
},
}
,{
xtype: 'fieldset'
,title: 'Unread counter'
,margin: '10 0 0 0'
,items: [
{
xtype: 'checkbox',
boxLabel: 'Include in global unread counter',
name: 'includeInGlobalUnreadCounter',
checked: me.edit ? me.record.get('includeInGlobalUnreadCounter') : true,
uncheckedValue: false,
inputValue: true
xtype: 'checkboxgroup'
,columns: 2
,items: [
{
xtype: 'checkbox',
boxLabel: 'Display tab unread counter',
name: 'displayTabUnreadCounter',
checked: me.edit ? me.record.get('displayTabUnreadCounter') : true,
uncheckedValue: false,
inputValue: true
},
{
xtype: 'checkbox',
boxLabel: 'Include in global unread counter',
name: 'includeInGlobalUnreadCounter',
checked: me.edit ? me.record.get('includeInGlobalUnreadCounter') : true,
uncheckedValue: false,
inputValue: true
}
]
}
]
},
{
}
,{
xtype: 'fieldset'
,title: 'Advanced'
,title: locale['app.window[7]']
,margin: '10 0 0 0'
,collapsible: true
,collapsed: true
,items: [
{
xtype: 'textarea'
,fieldLabel: 'Custom Code (<a href="https://github.com/saenzramiro/rambox/wiki/Inject-JavaScript-Code" target="_blank">read more</a>)'
,fieldLabel: locale['app.window[8]']+' (<a href="https://github.com/saenzramiro/rambox/wiki/Inject-JavaScript-Code" target="_blank">'+locale['app.window[9]']+'</a>)'
,allowBlank: true
,name: 'js_unread'
,value: me.edit ? me.record.get('js_unread') : ''
@ -221,7 +263,7 @@ Ext.define('Rambox.view.add.Add',{
me.buttons = [
{
text: 'Cancel'
text: locale['button[1]']
,ui: 'decline'
,handler: 'doCancel'
}

10
app/view/add/AddController.js

@ -34,6 +34,8 @@ Ext.define('Rambox.view.add.AddController', {
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,statusbar: formValues.statusbar
,tabname: formValues.tabname
,displayTabUnreadCounter: formValues.displayTabUnreadCounter
,includeInGlobalUnreadCounter: formValues.includeInGlobalUnreadCounter
,trust: formValues.trust
@ -43,9 +45,11 @@ Ext.define('Rambox.view.add.AddController', {
var view = Ext.getCmp('tab_'+win.record.get('id'));
// Change the title of the Tab
view.setTitle(formValues.serviceName);
view.setTitle( formValues.tabname ? formValues.serviceName : '' );
// Change sound of the Tab
view.setAudioMuted(formValues.muted);
// Change statusbar of the Tab
view.setStatusBar(formValues.statusbar);
// Change notifications of the Tab
view.setNotifications(formValues.notifications);
// Change the icon of the Tab
@ -62,7 +66,7 @@ Ext.define('Rambox.view.add.AddController', {
}
// Apply the JS Code of the Tab
if ( win.down('textarea').isDirty() ) {
Ext.Msg.confirm('CUSTOM CODE', 'Rambox needs to reload the service to execute the new JavaScript code. Do you want to do it now?', function( btnId ) {
Ext.Msg.confirm(locale['app.window[8]'].toUpperCase(), 'Rambox needs to reload the service to execute the new JavaScript code. Do you want to do it now?', function( btnId ) {
if ( btnId === 'yes' ) view.reloadService();
});
}
@ -85,6 +89,8 @@ Ext.define('Rambox.view.add.AddController', {
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,tabname: formValues.tabname
,statusbar: formValues.statusbar
,displayTabUnreadCounter: formValues.displayTabUnreadCounter
,includeInGlobalUnreadCounter: formValues.includeInGlobalUnreadCounter
,trust: formValues.trust

14
app/view/main/About.js

@ -1,13 +1,13 @@
Ext.define('Rambox.view.main.About', {
extend: 'Ext.window.Window'
,xtype: 'about'
,title: 'About Rambox'
,title: locale['app.about[0]']
,autoShow: true
,modal: true
,resizable: false
,constrain: true
,width: 300
,height: 385
,height: 450
,bodyPadding: 10
,data: {
version: require('electron').remote.app.getVersion()
@ -19,15 +19,15 @@ Ext.define('Rambox.view.main.About', {
}
,tpl: [
'<div style="text-align:center;"><img src="resources/Icon.png" width="100" /></div>'
,'<h3>Free, Open Source and Cross Platform messaging and emailing app that combines common web applications into one.</h3>'
,'<div><b>Version:</b> {version}</div>'
,'<div><b>Platform:</b> {platform} ({arch})</div>'
,'<h3>'+locale['app.about[1]']+'</h3>'
,'<div><b>'+locale['app.about[2]']+':</b> {version}</div>'
,'<div><b>'+locale['app.about[3]']+':</b> {platform} ({arch})</div>'
,'<div><b>Electron:</b> {electron}</div>'
,'<div><b>Chromium:</b> {chromium}</div>'
,'<div><b>Node:</b> {node}</div>'
,'<br />'
,'<div style="text-align:center;"><a href="https://github.com/saenzramiro/rambox" target="_blank">GitHub</a> - <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU75QWS7LH2CA" target="_blank">Donate</a> - <a href="http://rambox.pro" target="_blank">rambox.pro</a></div>'
,'<div style="text-align:center;"><a href="https://github.com/saenzramiro/rambox" target="_blank">GitHub</a> - <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU75QWS7LH2CA" target="_blank">'+locale['app.main[25]']+'</a> - <a href="http://rambox.pro" target="_blank">rambox.pro</a></div>'
,'<br />'
,'<div style="text-align:center;"><i>Developed by Ramiro Saenz</i></div>'
,'<div style="text-align:center;"><i>'+locale['app.about[4]']+' Ramiro Saenz</i></div>'
]
});

46
app/view/main/Main.js

@ -37,7 +37,7 @@ Ext.define('Rambox.view.main.Main', {
,items: [
{
xtype: 'panel'
,title: 'Add a new Service'
,title: locale['app.main[0]']
,margin: '0 5 0 0'
,flex: 1
,header: { height: 50 }
@ -47,7 +47,7 @@ Ext.define('Rambox.view.main.Main', {
,items: [
{
xtype: 'checkbox'
,boxLabel: 'Messaging'
,boxLabel: locale['app.main[1]']
,name: 'messaging'
,checked: true
,uncheckedValue: false
@ -55,7 +55,7 @@ Ext.define('Rambox.view.main.Main', {
}
,{
xtype: 'checkbox'
,boxLabel: 'Email'
,boxLabel: locale['app.main[2]']
,margin: '0 10 0 10'
,name: 'email'
,checked: true
@ -104,7 +104,7 @@ Ext.define('Rambox.view.main.Main', {
,'</div>'
,'</tpl>'
]
,emptyText: '<div style="padding: 20px;">No services found... Try another search.</div>'
,emptyText: '<div style="padding: 20px;">'+locale['app.main[3]']+'</div>'
,listeners: {
itemclick: 'onNewServiceSelect'
}
@ -113,7 +113,7 @@ Ext.define('Rambox.view.main.Main', {
}
,{
xtype: 'grid'
,title: 'Enabled Services'
,title: locale['app.main[4]']
,store: 'Services'
,hideHeaders: true
,margin: '0 0 0 5'
@ -123,7 +123,7 @@ Ext.define('Rambox.view.main.Main', {
{
ftype:'grouping'
,collapsible: false
,groupHeaderTpl: '{columnName:uppercase}: {name:capitalize} ({rows.length} Item{[values.rows.length > 1 ? "s" : ""]})'
,groupHeaderTpl: '{columnName:uppercase}: {name:capitalize} ({rows.length} {[values.rows.length > 1 ? "'+locale['app.main[9]']+'" : "'+locale['app.main[8]']+'"]})'
}
]
,plugins: {
@ -135,7 +135,7 @@ Ext.define('Rambox.view.main.Main', {
xtype: 'button'
,glyph: 'xf1f8@FontAwesome'
,baseCls: ''
,tooltip: 'Remove all Services'
,tooltip: locale['app.main[10]']
,handler: 'removeAllServices'
}
]
@ -144,7 +144,7 @@ Ext.define('Rambox.view.main.Main', {
xtype: 'templatecolumn'
,width: 50
,variableRowHeight: true
,tpl: '<img src="{[ values.type !== \"custom\" ? \"resources/icons/\"+values.logo : (values.logo == \"\" ? \"resources/icons/custom.png\" : values.logo) ]}" data-qtip="{type:capitalize}" width="32" />'
,tpl: '<img src="{[ values.type !== \"custom\" ? \"resources/icons/\"+values.logo : (values.logo == \"\" ? \"resources/icons/custom.png\" : values.logo) ]}" data-qtip="{type:capitalize}" width="32" style="{[ values.enabled ? \"-webkit-filter: grayscale(0)\" : \"-webkit-filter: grayscale(1)\" ]}" />'
}
,{
dataIndex: 'name'
@ -162,14 +162,14 @@ Ext.define('Rambox.view.main.Main', {
,items: [
{
glyph: 0xf1f7
,tooltip: 'Prevent notifications'
,tooltip: locale['app.main[11]']
,getClass: function( value, metaData, record, rowIndex, colIndex, store, view ){
if ( record.get('notifications') ) return 'x-hidden';
}
}
,{
glyph: 0xf026
,tooltip: 'Muted'
,tooltip: locale['app.main[12]']
,getClass: function( value, metaData, record, rowIndex, colIndex, store, view ){
if ( !record.get('muted') ) return 'x-hidden';
}
@ -183,13 +183,13 @@ Ext.define('Rambox.view.main.Main', {
,items: [
{
glyph: 0xf013
,tooltip: 'Configure'
,tooltip: locale['app.main[13]']
,handler: 'configureService'
,getClass: function(){ return 'x-hidden-display'; }
}
,{
glyph: 0xf1f8
,tooltip: 'Remove'
,tooltip: locale['app.main[14]']
,handler: 'removeService'
,getClass: function(){ return 'x-hidden-display'; }
}
@ -209,7 +209,7 @@ Ext.define('Rambox.view.main.Main', {
}
]
,viewConfig: {
emptyText: 'No services added...'
emptyText: locale['app.main[15]']
,forceFit: true
,stripeRows: true
}
@ -228,8 +228,8 @@ Ext.define('Rambox.view.main.Main', {
,items: [
{
glyph: 'xf1f7@FontAwesome'
,text: 'Don\'t Disturb: '+(JSON.parse(localStorage.getItem('dontDisturb')) ? 'ON' : 'OFF')
,tooltip: 'Disable notifications and sounds in all services. Perfect to be concentrated and focused.<br/><b>Shortcut key: F1</b>'
,text: locale['app.main[16]']+': '+(JSON.parse(localStorage.getItem('dontDisturb')) ? locale['app.window[20]'] : locale['app.window[21]'])
,tooltip: locale['app.main[17]']+'<br/><b>'+locale['app.main[18]']+': F1</b>'
,enableToggle: true
,handler: 'dontDisturb'
,reference: 'disturbBtn'
@ -238,8 +238,8 @@ Ext.define('Rambox.view.main.Main', {
}
,{
glyph: 'xf023@FontAwesome'
,text: 'Lock Rambox'
,tooltip: 'Lock this app if you will be away for a period of time.<br/><b>Shortcut key: F2</b>'
,text: locale['app.main[19]']
,tooltip: locale['app.main[20]']+'<br/><b>'+locale['app.main[18]']+': F2</b>'
,handler: 'lockRambox'
,id: 'lockRamboxBtn'
}
@ -294,24 +294,24 @@ Ext.define('Rambox.view.main.Main', {
}
,'-'
,{
text: 'Logout'
text: locale['app.main[21]']
,glyph: 'xf08b@FontAwesome'
,handler: 'logout'
}
]
}
,{
text: 'Login'
text: locale['app.main[22]']
,icon: 'resources/auth0.png'
,id: 'loginBtn'
,tooltip: 'Login to save your configuration (no credentials stored) to sync with all your computers.<br /><br /><i>Powered by Auth0 (http://auth0.com)</i>'
,tooltip: locale['app.main[23]']+'<br /><br /><i>'+locale['app.main[24]']+' Auth0 (http://auth0.com)</i>'
,bind: {
hidden: '{username}'
}
,handler: 'login'
}
,{
tooltip: 'Preferences'
tooltip: locale['preferences[0]']
,glyph: 'xf013@FontAwesome'
,handler: 'openPreferences'
}
@ -327,7 +327,7 @@ Ext.define('Rambox.view.main.Main', {
,pressed: true
}
,{
text: 'Donation'
text: locale['app.main[25]']
,glyph: 'xf21e@FontAwesome'
,handler: 'showDonate'
}
@ -341,7 +341,7 @@ Ext.define('Rambox.view.main.Main', {
,'->'
,{
xtype: 'label'
,html: '<span class="fa fa-code" style="color:black;"></span> with <span class="fa fa-heart" style="color:red;"></span> from <img src="resources/flag.png" alt="Argentina" data-qtip="Argentina" /> as an Open Source project.'
,html: '<span class="fa fa-code" style="color:black;"></span> '+locale['app.main[26]']+' <span class="fa fa-heart" style="color:red;"></span> '+locale['app.main[27]'].replace('Argentina', '<img src="resources/flag.png" alt="Argentina" data-qtip="Argentina" />')
}
,'->'
,{

113
app/view/main/MainController.js

@ -24,7 +24,7 @@ Ext.define('Rambox.view.main.MainController', {
var store = Ext.getStore('Services');
store.suspendEvent('remove');
Ext.each(tabPanel.items.items, function(t, i) {
if ( t.id !== 'ramboxTab' && t.id !== 'tbfill' ) {
if ( t.id !== 'ramboxTab' && t.id !== 'tbfill' && t.record.get('enabled') ) {
var rec = store.getById(t.record.get('id'));
if ( rec.get('align') === 'right' ) i--;
rec.set('position', i);
@ -54,7 +54,26 @@ Ext.define('Rambox.view.main.MainController', {
,onEnableDisableService: function(cc, rowIndex, checked) {
var rec = Ext.getStore('Services').getAt(rowIndex);
Ext.getCmp('tab_'+rec.get('id')).setEnabled(checked);
if ( !checked ) {
Ext.getCmp('tab_'+rec.get('id')).destroy();
} else {
Ext.cq1('app-main').insert(rec.get('align') === 'left' ? rec.get('position') : rec.get('position')+1, {
xtype: 'webview'
,id: 'tab_'+rec.get('id')
,title: rec.get('name')
,icon: rec.get('type') !== 'custom' ? 'resources/icons/'+rec.get('logo') : ( rec.get('logo') === '' ? 'resources/icons/custom.png' : rec.get('logo'))
,src: rec.get('url')
,type: rec.get('type')
,muted: rec.get('muted')
,includeInGlobalUnreadCounter: rec.get('includeInGlobalUnreadCounter')
,displayTabUnreadCounter: rec.get('displayTabUnreadCounter')
,enabled: rec.get('enabled')
,record: rec
,tabConfig: {
service: rec
}
});
}
}
,onNewServiceSelect: function( view, record, item, index, e ) {
@ -87,7 +106,7 @@ Ext.define('Rambox.view.main.MainController', {
,removeService: function( gridView, rowIndex, colIndex, col, e, rec, rowEl ) {
var me = this;
Ext.Msg.confirm('Please confirm...', 'Are you sure you want to remove <b>'+rec.get('name')+'</b>?', function(btnId) {
Ext.Msg.confirm(locale['app.window[12]'], locale['app.window[13]']+' <b>'+rec.get('name')+'</b>?', function(btnId) {
if ( btnId === 'yes' ) me.removeServiceFn(rec.get('id'));
});
}
@ -99,13 +118,13 @@ Ext.define('Rambox.view.main.MainController', {
document.title = 'Rambox';
if ( btn ) {
Ext.Msg.confirm('Please confirm...', 'Are you sure you want to remove all services?', function(btnId) {
Ext.Msg.confirm(locale['app.window[12]'], locale['app.window[14]'], function(btnId) {
if ( btnId === 'yes' ) {
Ext.cq1('app-main').suspendEvent('remove');
Ext.getStore('Services').load();
Ext.Array.each(Ext.getStore('Services').collect('id'), function(serviceId) {
me.removeServiceFn(serviceId);
});
Ext.getStore('Services').load();
if ( Ext.isFunction(callback) ) callback();
Ext.cq1('app-main').resumeEvent('remove');
document.title = 'Rambox';
@ -113,10 +132,10 @@ Ext.define('Rambox.view.main.MainController', {
});
} else {
Ext.cq1('app-main').suspendEvent('remove');
Ext.getStore('Services').load();
Ext.Array.each(Ext.getStore('Services').collect('id'), function(serviceId) {
me.removeServiceFn(serviceId);
});
Ext.getStore('Services').load();
if ( Ext.isFunction(callback) ) callback();
Ext.cq1('app-main').resumeEvent('remove');
document.title = 'Rambox';
@ -208,7 +227,7 @@ Ext.define('Rambox.view.main.MainController', {
localStorage.setItem('dontDisturb', btn.pressed);
btn.setText('Don\'t Disturb: ' + ( btn.pressed ? 'ON' : 'OFF' ));
btn.setText(locale['app.main[16]']+': ' + ( btn.pressed ? locale['app.window[20]'] : locale['app.window[21]'] ));
// If this method is called from Lock method, prevent showing toast
if ( !e ) return;
@ -224,39 +243,57 @@ Ext.define('Rambox.view.main.MainController', {
,lockRambox: function(btn) {
var me = this;
var msgbox = Ext.Msg.prompt('Lock Rambox', 'Enter a temporal password to unlock it later', function(btnId, text) {
if ( btnId === 'ok' ) {
var msgbox2 = Ext.Msg.prompt('Lock Rambox', 'Repeat the temporal password', function(btnId, text2) {
if ( btnId === 'ok' ) {
if ( text !== text2 ) {
Ext.Msg.show({
title: 'Warning'
,message: 'Passwords are not the same. Please try again...'
,icon: Ext.Msg.WARNING
,buttons: Ext.Msg.OK
,fn: me.lockRambox
});
return false;
if ( ipc.sendSync('getConfig').master_password ) {
Ext.Msg.confirm(locale['app.main[19]'], 'Do you want to use the Master Password as your temporal password?', function(btnId) {
if ( btnId === 'yes' ) {
setLock(ipc.sendSync('getConfig').master_password);
} else {
showTempPass();
}
});
} else {
showTempPass();
}
function showTempPass() {
var msgbox = Ext.Msg.prompt(locale['app.main[19]'], locale['app.window[22]'], function(btnId, text) {
if ( btnId === 'ok' ) {
var msgbox2 = Ext.Msg.prompt(locale['app.main[19]'], locale['app.window[23]'], function(btnId, text2) {
if ( btnId === 'ok' ) {
if ( text !== text2 ) {
Ext.Msg.show({
title: locale['app.window[24]']
,message: locale['app.window[25]']
,icon: Ext.Msg.WARNING
,buttons: Ext.Msg.OK
,fn: me.lockRambox
});
return false;
}
setLock(Rambox.util.MD5.encypt(text));
}
});
msgbox2.textField.inputEl.dom.type = 'password';
}
});
msgbox.textField.inputEl.dom.type = 'password';
}
console.info('Lock Rambox:', 'Enabled');
function setLock(text) {
console.info('Lock Rambox:', 'Enabled');
// Save encrypted password in localStorage to show locked when app is reopen
localStorage.setItem('locked', Rambox.util.MD5.encypt(text));
// Save encrypted password in localStorage to show locked when app is reopen
localStorage.setItem('locked', text);
// Google Analytics Event
ga_storage._trackEvent('Usability', 'locked');
// Google Analytics Event
ga_storage._trackEvent('Usability', 'locked');
me.lookupReference('disturbBtn').setPressed(true);
me.dontDisturb(me.lookupReference('disturbBtn'), false, true);
me.lookupReference('disturbBtn').setPressed(true);
me.dontDisturb(me.lookupReference('disturbBtn'), false, true);
me.showLockWindow();
}
});
msgbox2.textField.inputEl.dom.type = 'password';
}
});
msgbox.textField.inputEl.dom.type = 'password';
me.showLockWindow();
}
}
,showLockWindow: function() {
@ -300,7 +337,7 @@ Ext.define('Rambox.view.main.MainController', {
xtype: 'component'
,autoEl: {
tag: 'h1'
,html: 'Rambox is locked'
,html: locale['app.window[26]']
,style: 'text-align:center;width:256px;'
}
}
@ -318,7 +355,7 @@ Ext.define('Rambox.view.main.MainController', {
}
,{
xtype: 'button'
,text: 'UNLOCK'
,text: locale['app.window[27]']
,glyph: 'xf13e@FontAwesome'
,width: 256
,scale: 'large'
@ -347,7 +384,7 @@ Ext.define('Rambox.view.main.MainController', {
var me = this;
var logoutFn = function(callback) {
Ext.Msg.wait('Closing you session...', 'Logout');
Ext.Msg.wait(locale['app.window[37]'], locale['app.main[21]']);
// Google Analytics Event
ga_storage._trackEvent('Users', 'loggedOut');
@ -364,7 +401,7 @@ Ext.define('Rambox.view.main.MainController', {
}
if ( btn ) {
Ext.Msg.confirm('Logout', 'Are you sure you want to logout?', function(btnId) {
Ext.Msg.confirm(locale['app.main[21]'], locale['app.window[38]'], function(btnId) {
if ( btnId === 'yes' ) {
logoutFn(function() {
me.removeAllServices();

132
app/view/preferences/Preferences.js

@ -14,22 +14,23 @@ Ext.define('Rambox.view.preferences.Preferences',{
type: 'preferences-preferences'
}
,title: 'Preferences'
,width: 400
,title: locale['preferences[0]']
,width: 420
,modal: true
,closable: true
,minimizable: false
,maximizable: false
,draggable: true
,resizable: false
,buttons: [
{
text: 'Cancel'
text: locale['button[1]']
,ui: 'decline'
,handler: 'cancel'
}
,'->'
,{
text: 'Save'
text: locale['button[4]']
,handler: 'save'
}
]
@ -43,52 +44,119 @@ Ext.define('Rambox.view.preferences.Preferences',{
,bodyPadding: 20
,items: [
{
xtype: 'container'
,layout: 'hbox'
,items: [
{
xtype: 'combo'
,name: 'locale'
,fieldLabel: 'Language'
,labelAlign: 'left'
,flex: 1
,labelWidth: 80
,value: config.locale
,displayField: 'label'
,valueField: 'value'
,editable: false
,store: Ext.create('Ext.data.Store', {
fields: ['value', 'label']
,data: [
{ 'value': 'ar', 'auth0': 'en', 'label': 'Arabic' }
,{ 'value': 'cs', 'auth0': 'cs', 'label': 'Czech' }
,{ 'value': 'nl', 'auth0': 'nl', 'label': 'Dutch' }
,{ 'value': 'en', 'auth0': 'en', 'label': 'English' }
,{ 'value': 'fr', 'auth0': 'fr', 'label': 'French' }
,{ 'value': 'de', 'auth0': 'de', 'label': 'German' }
,{ 'value': 'el', 'auth0': 'en', 'label': 'Greek' }
,{ 'value': 'id', 'auth0': 'en', 'label': 'Indonesian' }
,{ 'value': 'it', 'auth0': 'it', 'label': 'Italian' }
,{ 'value': 'ko', 'auth0': 'en', 'label': 'Korean' }
,{ 'value': 'fa', 'auth0': 'fa', 'label': 'Persian' }
,{ 'value': 'pl', 'auth0': 'pl', 'label': 'Polish' }
,{ 'value': 'pt-PT', 'auth0': 'pt-br', 'label': 'Portuguese' }
,{ 'value': 'pt-BR', 'auth0': 'pt-br', 'label': 'Portuguese (Brazilian)' }
,{ 'value': 'ru', 'auth0': 'ru', 'label': 'Russian' }
,{ 'value': 'es-ES', 'auth0': 'es', 'label': 'Spanish' }
,{ 'value': 'tr', 'auth0': 'tr', 'label': 'Turkish' }
]
})
}
,{
xtype: 'button'
,text: 'Help us Translate'
,style: 'border-top-left-radius:0;border-bottom-left-radius:0;'
,href: 'https://crowdin.com/project/rambox/invite'
}
]
}
,{
xtype: 'label'
,text: 'English is the only language that has full translation. We are working with all the others, help us!'
,style: 'display:block;font-size:10px;line-height:15px;'
,margin: '0 0 10 0'
}
,{
xtype: 'checkbox'
,name: 'auto_launch'
,boxLabel: 'Start automatically on system startup'
,boxLabel: locale['preferences[5]']
,value: config.auto_launch
}
,{
xtype: 'checkbox'
,name: 'start_minimized'
,boxLabel: 'Start minimized'
,boxLabel: locale['preferences[4]']
,value: config.start_minimized
}
,{
xtype: 'checkbox'
,name: 'hide_menu_bar'
,boxLabel: 'Auto-hide Menu bar (<code>Alt</code> key to display)'
,boxLabel: locale['preferences[1]']+' (<code>Alt</code> key to display)'
,value: config.hide_menu_bar
,hidden: process.platform !== 'win32'
}
,{
xtype: 'checkbox'
,name: 'skip_taskbar'
,boxLabel: 'Show in Taskbar'
,value: config.skip_taskbar
,reference: 'skipTaskbar'
xtype: 'combo'
,name: 'window_display_behavior'
,fieldLabel: 'Display behaviour'
,labelAlign: 'left'
,width: 380
,labelWidth: 105
,value: config.window_display_behavior
,displayField: 'label'
,valueField: 'value'
,editable: false
,store: Ext.create('Ext.data.Store', {
fields: ['value', 'label']
,data: [
{ 'value': 'show_taskbar', 'label': 'Show in Taskbar' }
,{ 'value': 'show_trayIcon', 'label': 'Show Tray Icon' }
,{ 'value': 'taskbar_tray', 'label': 'Show in Taskbar and Tray Icon' }
]
})
,hidden: process.platform === 'darwin'
},
{
xtype: 'combo',
name: 'window_close_behavior',
fieldLabel: 'When closing the main window',
labelAlign: 'top',
value: config.window_close_behavior,
displayField: 'label',
valueField: 'value',
editable: false,
store: Ext.create('Ext.data.Store', {
fields: ['value', 'label'],
data : [
{ 'value': 'keep_in_tray', 'label': 'Keep in tray' },
{ 'value': 'keep_in_tray_and_taskbar', 'label': 'Keep in tray and taskbar' },
{ 'value': 'quit', 'label': 'Quit' }
}
,{
xtype: 'combo'
,name: 'window_close_behavior'
,fieldLabel: 'When closing the main window'
,labelAlign: 'left'
,width: 380
,labelWidth: 180
,value: config.window_close_behavior
,displayField: 'label'
,valueField: 'value'
,editable: false
,store: Ext.create('Ext.data.Store', {
fields: ['value', 'label']
,data: [
{ 'value': 'keep_in_tray', 'label': 'Keep in tray' }
,{ 'value': 'keep_in_tray_and_taskbar', 'label': 'Keep in tray and taskbar' }
,{ 'value': 'quit', 'label': 'Quit' }
]
}),
hidden: process.platform === 'darwin'
},
{
})
,hidden: process.platform === 'darwin'
}
,{
xtype: 'checkbox'
,name: 'always_on_top'
,boxLabel: 'Always on top'

9
app/view/preferences/PreferencesController.js

@ -39,6 +39,15 @@ Ext.define('Rambox.view.preferences.PreferencesController', {
// Proxy
if ( values.proxy && (Ext.isEmpty(values.proxyHost) || Ext.isEmpty(values.proxyPort)) ) return;
// Locale
if ( values.locale !== ipc.sendSync('getConfig').locale ) {
localStorage.setItem('locale', values.locale);
localStorage.setItem('locale-auth0', me.getView().down('form').down('combo[name="locale"]').getSelection().get('auth0'));
Ext.Msg.confirm('Action required', 'To change the language of Rambox, you need to reload the app. Do you want to do it now?', function(btnId) {
if ( btnId === 'yes' ) ipc.send('relaunchApp');
});
}
ipc.send('setConfig', values);
me.getView().close();
}

2
appveyor.yml

@ -1,4 +1,4 @@
version: 0.5.7
version: 0.5.8
pull_requests:
do_not_increment_build_number: true
branches:

78
electron/main.js

@ -1,12 +1,10 @@
'use strict';
const {app, protocol, BrowserWindow, dialog, shell, Menu, ipcMain, nativeImage, session} = require('electron');
// Menu
const appMenu = require('./menu');
// Tray
const tray = require('./tray');
// AutoLaunch
var AutoLaunch = require('auto-launch');
var AutoLaunch = require('auto-launch-patched');
// Configuration
const Config = require('electron-config');
// Development
@ -22,7 +20,7 @@ const config = new Config({
defaults: {
always_on_top: false
,hide_menu_bar: false
,skip_taskbar: true
,window_display_behavior: 'taskbar_tray'
,auto_launch: !isDev
,window_close_behavior: 'keep_in_tray'
,start_minimized: false
@ -32,6 +30,7 @@ const config = new Config({
,proxy: false
,proxyHost: ''
,proxyPort: ''
,locale: 'en'
,x: undefined
,y: undefined
@ -41,10 +40,13 @@ const config = new Config({
}
});
// Menu
const appMenu = require('./menu')(config);
// Configure AutoLaunch
const appLauncher = new AutoLaunch({
name: process.platform === 'darwin' ? 'Rambox.app' : 'Rambox'
,isHiddenOnLaunch: config.get('start_minimized')
name: 'Rambox'
,isHidden: config.get('start_minimized')
});
config.get('auto_launch') && !isDev ? appLauncher.enable() : appLauncher.disable();
@ -132,7 +134,7 @@ function createWindow () {
,height: config.get('height')
,alwaysOnTop: config.get('always_on_top')
,autoHideMenuBar: config.get('hide_menu_bar')
,skipTaskbar: !config.get('skip_taskbar')
,skipTaskbar: config.get('window_display_behavior') === 'show_trayIcon'
,show: !config.get('start_minimized')
,webPreferences: {
webSecurity: false
@ -156,7 +158,7 @@ function createWindow () {
tray.create(mainWindow, config);
if ( fs.existsSync(path.resolve(path.dirname(process.execPath), '..', 'Update.exe')) ) updater.initialize(mainWindow);
if ( fs.existsSync(path.resolve(path.dirname(process.execPath), '..', 'Update.exe')) && process.argv.indexOf('--without-update') === -1 ) updater.initialize(mainWindow);
// Open links in default browser
mainWindow.webContents.on('new-window', function(e, url, frameName, disposition, options) {
@ -184,10 +186,7 @@ function createWindow () {
// Navigate the window forward when the user hits their mouse forward button
if ( cmd === 'browser-forward' ) mainWindow.webContents.executeJavaScript('if(Ext.cq1("app-main")) Ext.cq1("app-main").getActiveTab().goForward();');
});
mainWindow.on('focus', (e) => {
// Make focus on current service when user use Alt + Tab to activate Rambox
mainWindow.webContents.executeJavaScript('if(Ext.cq1("app-main")) Ext.cq1("app-main").fireEvent("tabchange", Ext.cq1("app-main"), Ext.cq1("app-main").getActiveTab());');
});
// Emitted when the window is closed.
mainWindow.on('close', function(e) {
if ( !isQuitting ) {
@ -218,6 +217,7 @@ function createWindow () {
mainWindow.on('closed', function(e) {
mainWindow = null;
});
mainWindow.once('focus', () => mainWindow.flashFrame(false));
}
let mainMasterPasswordWindow;
@ -245,9 +245,11 @@ function updateBadge(title) {
}
mainWindow.webContents.send('setBadge', messageCount);
} else { // macOS
} else { // macOS & Linux
app.setBadgeCount(messageCount);
}
if ( messageCount > 0 && !mainWindow.isFocused() ) mainWindow.flashFrame(true);
}
ipcMain.on('setBadge', function(event, messageCount, value) {
@ -265,14 +267,29 @@ ipcMain.on('setConfig', function(event, values) {
// hide_menu_bar
mainWindow.setAutoHideMenuBar(values.hide_menu_bar);
if ( !values.hide_menu_bar ) mainWindow.setMenuBarVisibility(true);
// skip_taskbar
mainWindow.setSkipTaskbar(!values.skip_taskbar);
// always_on_top
mainWindow.setAlwaysOnTop(values.always_on_top);
// auto_launch
values.auto_launch ? appLauncher.enable() : appLauncher.disable();
// systemtray_indicator
updateBadge(mainWindow.getTitle());
switch ( values.window_display_behavior ) {
case 'show_taskbar':
mainWindow.setSkipTaskbar(false);
tray.destroy();
break;
case 'show_trayIcon':
mainWindow.setSkipTaskbar(true);
tray.create(mainWindow, config);
break;
case 'taskbar_tray':
mainWindow.setSkipTaskbar(false);
tray.create(mainWindow, config);
break;
default:
break;
}
});
ipcMain.on('validateMasterPassword', function(event, pass) {
@ -292,6 +309,17 @@ ipcMain.on('setServiceNotifications', function(event, partition, op) {
});
});
// Reload app
ipcMain.on('reloadApp', function(event) {
mainWindow.reload();
});
// Relaunch app
ipcMain.on('relaunchApp', function(event) {
app.relaunch();
app.exit(0);
});
const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => {
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
@ -366,6 +394,26 @@ ipcMain.on('image:popup', function(event, url, partition) {
tmpWindow.loadURL(url);
});
ipcMain.on('toggleWin', function(event, allwaysShow) {
if ( !mainWindow.isMinimized() && mainWindow.isMaximized() && mainWindow.isVisible() ) { // Maximized
!allwaysShow ? mainWindow.close() : mainWindow.show();
} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Minimized
mainWindow.restore();
} else if ( !mainWindow.isMinimized() && !mainWindow.isMaximized() && mainWindow.isVisible() ) { // Windowed mode
!allwaysShow ? mainWindow.close() : mainWindow.show();
} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && mainWindow.isVisible() ) { // Closed to taskbar
mainWindow.restore();
} else if ( !mainWindow.isMinimized() && mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Closed maximized to tray
mainWindow.show();
} else if ( !mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Closed windowed to tray
mainWindow.show();
} else if ( mainWindow.isMinimized() && !mainWindow.isMaximized() && !mainWindow.isVisible() ) { // Closed minimized to tray
mainWindow.restore();
} else {
mainWindow.show();
}
});
// Proxy
if ( config.get('proxy') ) app.commandLine.appendSwitch('proxy-server', config.get('proxyHost')+':'+config.get('proxyPort'));

524
electron/menu.js

@ -16,270 +16,296 @@ function sendAction(action) {
win.webContents.send(action);
}
const helpSubmenu = [
{
label: `&Visit ${appName} Website`,
click() {
shell.openExternal('http://rambox.pro');
}
},
{
label: `&Facebook`,
click() {
shell.openExternal('https://www.facebook.com/ramboxapp');
}
},
{
label: `&Twitter`,
click() {
shell.openExternal('https://www.twitter.com/ramboxapp');
}
},
{
label: `&GitHub`,
click() {
shell.openExternal('https://www.github.com/saenzramiro/rambox');
}
},
{
type: 'separator'
},
{
label: '&Report an Issue...',
click() {
const body = `
<!-- Please describe here your issue and steps to reproduce it. -->
module.exports = function(config) {
const locale = require('../resources/languages/'+config.get('locale'));
const helpSubmenu = [
{
label: `&`+locale['menu.help[0]'],
click() {
shell.openExternal('http://rambox.pro');
}
},
{
label: `&Facebook`,
click() {
shell.openExternal('https://www.facebook.com/ramboxapp');
}
},
{
label: `&Twitter`,
click() {
shell.openExternal('https://www.twitter.com/ramboxapp');
}
},
{
label: `&GitHub`,
click() {
shell.openExternal('https://www.github.com/saenzramiro/rambox');
}
},
{
type: 'separator'
},
{
label: '&'+locale['menu.help[1]'],
click() {
const body = `
<!-- Please describe here your issue and steps to reproduce it. -->
<!-- DON'T REMOVE THE FOLLOWING LINES -->
-
> ${app.getName()} ${app.getVersion()}
> Electron ${process.versions.electron}
> ${process.platform} ${process.arch} ${os.release()}`;
<!-- DON'T REMOVE THE FOLLOWING LINES -->
-
> ${app.getName()} ${app.getVersion()}
> Electron ${process.versions.electron}
> ${process.platform} ${process.arch} ${os.release()}`;
shell.openExternal(`https://github.com/saenzramiro/rambox/issues/new?body=${encodeURIComponent(body)}`);
}
},
{
label: `&Ask for Help`,
click() {
shell.openExternal('https://gitter.im/saenzramiro/rambox');
}
},
{
label: `&Tools`,
submenu: [
{
label: `&Clear Cache`,
click(item, win) {
win.webContents.session.clearCache(function() {
win.reload();
});
}
},
{
label: `&Clear Local Storage`,
click(item, win) {
win.webContents.session.clearStorageData({
storages: ['localstorage']
}, function() {
win.reload();
});
shell.openExternal(`https://github.com/saenzramiro/rambox/issues/new?body=${encodeURIComponent(body)}`);
}
},
{
label: `&`+locale['menu.help[2]'],
click() {
shell.openExternal('https://gitter.im/saenzramiro/rambox');
}
},
{
label: `&Tools`,
submenu: [
{
label: `&Clear Cache`,
click(item, win) {
win.webContents.session.clearCache(function() {
win.reload();
});
}
},
{
label: `&Clear Local Storage`,
click(item, win) {
win.webContents.session.clearStorageData({
storages: ['localstorage']
}, function() {
win.reload();
});
}
}
]
},
{
type: 'separator'
},
{
label: `&`+locale['menu.help[3]'],
click() {
shell.openExternal('https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU75QWS7LH2CA');
}
]
},
{
type: 'separator'
},
{
label: `&Donate`,
click() {
shell.openExternal('https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU75QWS7LH2CA');
}
}
];
];
let tpl = [
{
label: '&Edit',
submenu: [
{
role: 'undo'
},
{
role: 'redo'
},
{
type: 'separator'
},
{
role: 'cut'
},
{
role: 'copy'
},
{
role: 'paste'
},
{
role: 'pasteandmatchstyle'
},
{
role: 'selectall'
},
{
role: 'delete'
}
]
},
{
label: '&View',
submenu: [
{
label: '&Reload',
accelerator: 'CmdOrCtrl+R',
click(item, focusedWindow) {
if (focusedWindow) focusedWindow.reload();
let tpl = [
{
label: '&'+locale['menu.edit[0]'],
submenu: [
{
role: 'undo'
,label: locale['menu.edit[1]']
},
{
role: 'redo'
,label: locale['menu.edit[2]']
},
{
type: 'separator'
},
{
role: 'cut'
,label: locale['menu.edit[3]']
},
{
role: 'copy'
,label: locale['menu.edit[4]']
},
{
role: 'paste'
,label: locale['menu.edit[5]']
},
{
role: 'pasteandmatchstyle'
},
{
role: 'selectall'
,label: locale['menu.edit[6]']
},
{
role: 'delete'
}
},
{
label: '&Reload current Service',
accelerator: 'CmdOrCtrl+Shift+R',
click() {
sendAction('reloadCurrentService');
]
},
{
label: '&'+locale['menu.view[0]'],
submenu: [
{
label: '&'+locale['menu.view[1]'],
accelerator: 'CmdOrCtrl+R',
click(item, focusedWindow) {
if (focusedWindow) focusedWindow.reload();
}
},
{
label: '&Reload current Service',
accelerator: 'CmdOrCtrl+Shift+R',
click() {
sendAction('reloadCurrentService');
}
},
{
type: 'separator'
},
{
role: 'zoomin'
},
{
role: 'zoomout'
},
{
role: 'resetzoom'
}
},
{
type: 'separator'
},
{
role: 'zoomin'
},
{
role: 'zoomout'
},
{
role: 'resetzoom'
}
]
},
{
label: '&Window',
role: 'window',
submenu: [
{
label: '&Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: '&Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
{
type: 'separator'
},
{
role: 'togglefullscreen'
},
{
label: '&Toggle Developer Tools',
accelerator: process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',
click(item, focusedWindow) {
if (focusedWindow) focusedWindow.webContents.toggleDevTools();
]
},
{
label: '&'+locale['menu.window[0]'],
role: 'window',
submenu: [
{
label: '&'+locale['menu.window[1]'],
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: '&'+locale['menu.window[2]'],
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
{
type: 'separator'
},
{
role: 'togglefullscreen'
,label: locale['menu.view[2]']
},
{
label: '&'+locale['menu.view[3]'],
accelerator: process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',
click(item, focusedWindow) {
if (focusedWindow) focusedWindow.webContents.toggleDevTools();
}
}
}
]
},
{
label: '&Help',
role: 'help'
}
];
]
},
{
label: '&'+locale['menu.help[4]'],
role: 'help'
}
];
if (process.platform === 'darwin') {
tpl.unshift({
label: appName,
submenu: [
{
label: `Check for updates...`,
click(item, win) {
const webContents = win.webContents;
const send = webContents.send.bind(win.webContents);
send('autoUpdater:check-update');
if (process.platform === 'darwin') {
tpl.unshift({
label: appName,
submenu: [
{
label: locale['preferences[0]'],
click() {
sendAction('showPreferences')
}
},
{
label: locale['menu.help[5]'],
click(item, win) {
const webContents = win.webContents;
const send = webContents.send.bind(win.webContents);
send('autoUpdater:check-update');
}
},
{
label: locale['menu.help[6]'],
click() {
sendAction('showAbout')
}
},
{
type: 'separator'
},
{
label: locale['menu.osx[0]'],
role: 'services',
submenu: []
},
{
type: 'separator'
},
{
label: locale['menu.osx[1]'],
accelerator: 'Command+H',
role: 'hide'
},
{
label: locale['menu.osx[2]'],
accelerator: 'Command+Alt+H',
role: 'hideothers'
},
{
label: locale['menu.osx[3]'],
role: 'unhide'
},
{
type: 'separator'
},
{
role: 'quit',
label: locale['tray[1]']
}
},
{
label: `About ${appName}`,
click() {
sendAction('showAbout')
]
});
} else {
tpl.unshift({
label: '&'+locale['menu.file[0]'],
submenu: [
{
label: locale['preferences[0]'],
click() {
sendAction('showPreferences')
}
},
{
type: 'separator'
},
{
role: 'quit',
label: locale['menu.file[1]']
}
},
{
type: 'separator'
},
{
label: 'Services',
role: 'services',
submenu: []
},
{
type: 'separator'
},
{
label: `Hide ${appName}`,
accelerator: 'Command+H',
role: 'hide'
},
{
label: 'Hide Others',
accelerator: 'Command+Alt+H',
role: 'hideothers'
},
{
label: 'Show All',
role: 'unhide'
},
{
type: 'separator'
},
{
role: 'quit'
]
});
helpSubmenu.push({
type: 'separator'
});
helpSubmenu.push({
label: `&`+locale['menu.help[5]'],
click(item, win) {
const webContents = win.webContents;
const send = webContents.send.bind(win.webContents);
send('autoUpdater:check-update');
}
]
});
} else {
tpl.unshift({
label: '&File',
submenu: [
{
role: 'quit'
});
helpSubmenu.push({
label: `&`+locale['menu.help[6]'],
click() {
sendAction('showAbout')
}
]
});
helpSubmenu.push({
type: 'separator'
});
helpSubmenu.push({
label: `&Check for updates...`,
click(item, win) {
const webContents = win.webContents;
const send = webContents.send.bind(win.webContents);
send('autoUpdater:check-update');
}
});
helpSubmenu.push({
label: `&About ${appName}`,
click() {
sendAction('showAbout')
}
});
}
});
}
tpl[tpl.length - 1].submenu = helpSubmenu;
tpl[tpl.length - 1].submenu = helpSubmenu;
var menu = electron.Menu.buildFromTemplate(tpl);
module.exports = menu;
return electron.Menu.buildFromTemplate(tpl);
};

37
electron/tray.js

@ -8,33 +8,17 @@ const MenuItem = electron.MenuItem;
var appIcon = null;
exports.create = function(win, config) {
if (process.platform === 'darwin' || appIcon) {
return;
}
if (process.platform === 'darwin' || appIcon || config.get('window_display_behavior') === 'show_taskbar' ) return;
const icon = process.platform === 'linux' || process.platform === 'darwin' ? 'IconTray.png' : 'Icon.ico';
const iconPath = path.join(__dirname, `../resources/${icon}`);
const toggleWin = () => {
if ( !config.get('keep_in_taskbar_on_close') ) {
if ( win.isVisible() ) {
win.hide();
} else {
config.get('maximized') ? win.maximize() : win.show();
}
} else {
if ( win.isVisible() && !win.isMinimized() ) {
win.minimize();
} else {
config.get('maximized') ? win.maximize() : win.show();
}
}
};
const contextMenu = electron.Menu.buildFromTemplate([
{
label: 'Show/Hide Window'
,click: toggleWin
,click() {
win.webContents.executeJavaScript('ipc.send("toggleWin", false);');
}
},
{
type: 'separator'
@ -50,15 +34,16 @@ exports.create = function(win, config) {
appIcon = new Tray(iconPath);
appIcon.setToolTip('Rambox');
appIcon.setContextMenu(contextMenu);
appIcon.on('click', () => {
if ( !win.isVisible() ) {
win.isVisible() ? win.hide() : win.show();
} else {
win.focus();
}
appIcon.on('double-click', function() {
win.webContents.executeJavaScript('ipc.send("toggleWin", true);');
});
};
exports.destroy = function() {
appIcon.destroy();
appIcon = null;
};
exports.setBadge = function(messageCount, showUnreadTray) {
if (process.platform === 'darwin' || !appIcon) return;

44
index.html

@ -7,16 +7,50 @@
<title>Rambox</title>
<script type='text/javascript'>
var xhr = new XMLHttpRequest();
var file = "http://rambox.pro/api/latestversion.json";
var randomNum = Math.round(Math.random() * 10000);
xhr.open('HEAD', file + "?rand=" + randomNum, true);
xhr.send();
xhr.addEventListener("readystatechange", processRequest, false);
function processRequest(e) {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 304) {
console.info('Internet Connection', true);
} else {
console.info('Internet Connection', false);
alert('No Internet Connection. Please, check your internet connection and open Rambox again.');
require('electron').remote.app.quit();
}
}
}
</script>
<!-- The line below must be kept intact for Sencha Cmd to build your application -->
<script id="microloader" type="text/javascript" src="bootstrap.js"></script>
<!--- Localization -->
<script type='text/javascript'>
(function(d, s){
var t = d.createElement(s), e = d.getElementsByTagName(s)[0];
t.type = "text/javascript"; e.parentNode.insertBefore(t, e);
t.src = "resources/languages/"+require('electron').ipcRenderer.sendSync('getConfig').locale+".js";
})(document, "script");
</script>
<!--- Localization -->
<!--- Tooltip player -->
<script type='text/javascript'>
(function(d, s){
var t = d.createElement(s), e = d.getElementsByTagName(s)[0];
t.type = "text/javascript"; e.parentNode.insertBefore(t, e);
t.async = "async";
t.src = "https://cdn.tooltip.io/static/player.js?apiKey=sEF8shc4KSuqtHMx0ztmTFdcrQO0cAVpszZ9Y8hLfQ2";
})(document, "script");
var t = d.createElement(s), e = d.getElementsByTagName(s)[0];
t.type = "text/javascript"; e.parentNode.insertBefore(t, e);
t.async = "async";
t.src = "https://cdn.tooltip.io/static/player.js?apiKey=sEF8shc4KSuqtHMx0ztmTFdcrQO0cAVpszZ9Y8hLfQ2";
})(document, "script");
</script>
<!--- Tooltip player -->
</head>

50
languages.js

@ -0,0 +1,50 @@
const fs = require('fs');
const path = require('path');
const csvjson = require('csvjson');
const Crowdin = require('crowdin');
var deleteFolderRecursive = function(path) {
if( fs.existsSync(path) ) {
fs.readdirSync(path).forEach(function(file,index){
var curPath = path + "/" + file;
if(fs.lstatSync(curPath).isDirectory()) { // recurse
deleteFolderRecursive(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
};
var crowdin = new Crowdin({
apiKey: '',
endpointUrl: 'https://api.crowdin.net/api/project/rambox'
});
var args = process.argv.slice(2);
if ( args.indexOf('download') >= 0 ) crowdin.downloadToPath('resources/languages').then(function() { console.info('Download finished!') });
if ( args.indexOf('generate') >= 0 ) {
fs.readdirSync(__dirname+'/resources/languages').filter(file => fs.lstatSync(path.join(__dirname+'/resources/languages', file)).isDirectory()).forEach(function(locale) {
var result = 'var locale=[];';
var path = __dirname+'/resources/languages/'+locale;
fs.readdirSync(path).forEach(function(file) {
var data = fs.readFileSync(path+'/'+file, { encoding : 'utf8'});
csvjson.toObject(data, {
headers: 'prop,text'
,delimiter: ','
,quote: '"'
}).forEach(function(obj) {
result += 'locale["'+obj.prop+'"]="'+obj.text+'";';
});
});
result += 'module.exports = locale;';
fs.writeFileSync(path+'/../'+locale+'.js', result);
console.log(locale, "File was generated!");
deleteFolderRecursive(path);
});
}
if ( args.length === 0 ) console.error('No arguments passed');

15
package.json

@ -68,6 +68,11 @@
},
"linux": {
"category": "Office",
"desktop": {
"Terminal": "false",
"Type": "Application",
"Categories": "GTK;GNOME;Utility;Office;Email;Chat;InstantMessaging;"
},
"target": [
"AppImage",
"deb",
@ -84,16 +89,18 @@
},
"devDependencies": {
"asar": "^0.12.1",
"electron": "^1.6.1",
"electron-builder": "^14.5.3",
"electron": "1.7.1",
"electron-builder": "^17.8.0",
"electron-builder-squirrel-windows": "15.0.0",
"electron-squirrel-startup": "^1.0.0",
"chai": "3.5.0",
"mocha": "3.2.0",
"spectron": "3.4.0"
"spectron": "3.4.0",
"csvjson": "4.3.3",
"crowdin": "1.0.0"
},
"dependencies": {
"auto-launch": "4.0.0",
"auto-launch-patched": "5.0.2",
"tmp": "0.0.28",
"mime": "^1.3.4",
"electron-is-dev": "^0.1.1",

BIN
resources/icons/actor.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

BIN
resources/icons/clocktweets.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
resources/icons/fastmail.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 53 KiB

BIN
resources/icons/hibox.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 64 KiB

BIN
resources/icons/intercom.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
resources/icons/jandi.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 52 KiB

BIN
resources/icons/mastodon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
resources/icons/messengerpages.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
resources/icons/teamworkchat.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
resources/icons/threema.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 61 KiB

BIN
resources/icons/vk.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
resources/icons/xing.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 47 KiB

1
resources/languages/af.js

File diff suppressed because one or more lines are too long

1
resources/languages/ar.js

File diff suppressed because one or more lines are too long

1
resources/languages/ca.js

File diff suppressed because one or more lines are too long

1
resources/languages/cs.js

File diff suppressed because one or more lines are too long

1
resources/languages/da.js

File diff suppressed because one or more lines are too long

1
resources/languages/de.js

File diff suppressed because one or more lines are too long

1
resources/languages/el.js

File diff suppressed because one or more lines are too long

1
resources/languages/en.js

File diff suppressed because one or more lines are too long

1
resources/languages/es-ES.js

File diff suppressed because one or more lines are too long

1
resources/languages/fa.js

File diff suppressed because one or more lines are too long

1
resources/languages/fi.js

File diff suppressed because one or more lines are too long

1
resources/languages/fr.js

File diff suppressed because one or more lines are too long

1
resources/languages/he.js

File diff suppressed because one or more lines are too long

1
resources/languages/hu.js

File diff suppressed because one or more lines are too long

1
resources/languages/id.js

File diff suppressed because one or more lines are too long

1
resources/languages/it.js

File diff suppressed because one or more lines are too long

1
resources/languages/ja.js

File diff suppressed because one or more lines are too long

1
resources/languages/ko.js

File diff suppressed because one or more lines are too long

1
resources/languages/nl.js

File diff suppressed because one or more lines are too long

1
resources/languages/no.js

File diff suppressed because one or more lines are too long

1
resources/languages/pl.js

File diff suppressed because one or more lines are too long

1
resources/languages/pt-BR.js

File diff suppressed because one or more lines are too long

1
resources/languages/pt-PT.js

File diff suppressed because one or more lines are too long

1
resources/languages/ro.js

File diff suppressed because one or more lines are too long

1
resources/languages/ru.js

File diff suppressed because one or more lines are too long

1
resources/languages/sr.js

File diff suppressed because one or more lines are too long

1
resources/languages/sv-SE.js

File diff suppressed because one or more lines are too long

1
resources/languages/tr.js

File diff suppressed because one or more lines are too long

1
resources/languages/uk.js

File diff suppressed because one or more lines are too long

1
resources/languages/vi.js

File diff suppressed because one or more lines are too long

1
resources/languages/zh-CN.js

File diff suppressed because one or more lines are too long

1
resources/languages/zh-TW.js

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save