Browse Source

Merge tag '0.4.4' of https://github.com/saenzramiro/rambox into feature/add-context-menu

pull/297/head
Nils Hesse 9 years ago
parent
commit
cdf228ebf9
  1. 10
      .editorconfig
  2. 26
      README.md
  3. 5
      app.js
  4. 5
      app.json
  5. 51
      app/Application.js
  6. 8
      app/model/ServiceList.js
  7. 2
      app/package.json
  8. 146
      app/store/ServicesList.js
  9. 10
      app/ux/Auth0.js
  10. 44
      app/ux/Firebase.js
  11. 71
      app/ux/WebView.js
  12. 219
      app/view/add/Add.js
  13. 125
      app/view/add/AddController.js
  14. 4
      app/view/add/AddModel.js
  15. 48
      app/view/main/Main.js
  16. 638
      app/view/main/MainController.js
  17. 14
      app/view/preferences/Preferences.js
  18. 5
      appveyor.yml
  19. 32
      electron/main.js
  20. 30
      electron/menu.js
  21. 2
      electron/tray.js
  22. 10
      index.html
  23. 23
      masterpassword.html
  24. 2
      package.json
  25. BIN
      packages/local/rambox-default-theme/resources/fonts/icomoon/icomoon.eot
  26. 21
      packages/local/rambox-default-theme/resources/fonts/icomoon/icomoon.svg
  27. BIN
      packages/local/rambox-default-theme/resources/fonts/icomoon/icomoon.ttf
  28. BIN
      packages/local/rambox-default-theme/resources/fonts/icomoon/icomoon.woff
  29. 229
      packages/local/rambox-default-theme/sass/etc/_loadscreen.scss
  30. 1
      packages/local/rambox-default-theme/sass/etc/all.scss
  31. 3
      packages/local/rambox-default-theme/sass/src/grid/column/Action.scss
  32. BIN
      resources/icons/actor.png
  33. BIN
      resources/icons/crisp.png
  34. BIN
      resources/icons/drift.png
  35. BIN
      resources/icons/fleep.png
  36. BIN
      resources/icons/flock.png
  37. BIN
      resources/icons/kaiwa.png
  38. BIN
      resources/icons/mmmelon.png
  39. BIN
      resources/icons/movim.png
  40. BIN
      resources/icons/openmailbox.png
  41. BIN
      resources/icons/pushbullet.png
  42. BIN
      resources/icons/riot.png
  43. BIN
      resources/icons/smooch.png
  44. BIN
      resources/icons/socialcast.png
  45. BIN
      resources/icons/spark.png
  46. BIN
      resources/icons/typetalk.png
  47. BIN
      resources/installer/Icon.icns
  48. 263
      resources/js/loadscreen.js

10
.editorconfig

@ -0,0 +1,10 @@
# EditorConfig is awesome: http://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
indent_style = tab

26
README.md

@ -35,7 +35,7 @@
![Rambox](https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/screenshots/mac.png)
## Services available - 57
## Services available - 72
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/whatsapp.png" alt="WhatsApp" title="WhatsApp">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/messenger.png" alt="Messenger" title="Messenger">
@ -68,7 +68,6 @@
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/yahoo.png" alt="Yahoo! Mail" title="Yahoo! Mail">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/ryver.png" alt="Ryver" title="Ryver">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/yandex.png" alt="Yandex Mail" title="Yandex Mail">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/office365.png" alt="OFfice 365" title="Office 365">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/dasher.png" alt="Dasher" title="Dasher">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/dingtalk.png" alt="DingTalk" title="DingTalk">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/flowdock.png" alt="FlowDock" title="FlowDock">
@ -94,8 +93,23 @@
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/icloud.png" alt="iCloud Mail" title="iCloud Mail">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/irccloud.png" alt="IRC Cloud" title="IRC Cloud">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/kiwi.png" alt="Kiwi IRC" title="Kiwi IRC">
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/smooch.png" alt="Smooch" title="Smooch">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/crisp.png" alt="Crisp" title="Crisp">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/flock.png" alt="Flock" title="Flock">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/openmailbox.png" alt="Openmailbox" title="Openmailbox">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/typetalk.png" alt="Typetalk" title="Typetalk">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/drift.png" alt="Drift" title="Drift">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/mmmelon.png" alt="mmmelon" title="mmmelon">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/spark.png" alt="Cisco Spark" title="Cisco Spark">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/fleep.png" alt="Fleep" title="Fleep">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/socialcast.png" alt="Socialcast" title="Socialcast">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/actor.png" alt="Actor" title="Actor">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/riot.png" alt="Riot" title="Riot">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/pushbullet.png" alt="Pushbullet" title="Pushbullet">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/movim.png" alt="Movim" title="Movim">
<img width="80" align="left" src="https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/kaiwa.png" alt="Kaiwa" title="Kaiwa">
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
## Features
@ -122,6 +136,10 @@ Sessions will persist using the [partition:persist](http://electron.atom.io/docs
Sync feature use Auth0 for Single Sign On & Token Based Authentication with the integration with Firebase to store the services that user is using (and the configuration for each service). You are always welcome to check the code! ;)
## Translations
Help us translate Rambox on https://crowdin.com/project/rambox/invite.
## [Install on Linux - Steps](https://github.com/saenzramiro/rambox/wiki/Install-on-Linux)
## [To Do](https://github.com/saenzramiro/rambox/blob/master/TODO.md)

5
app.js

@ -130,3 +130,8 @@ ipc.on('setBadge', function(event, messageCount) {
ipc.send('setBadge', messageCount, canvas.toDataURL());
});
// Reload Current Service
ipc.on('reloadCurrentService', function(e) {
var tab = Ext.cq1('app-main').getActiveTab();
if ( tab.id !== 'ramboxTab' ) tab.reloadService();
});

5
app.json

@ -113,7 +113,10 @@
{
"path": "resources/js/GALocalStorage.js"
},
{
{
"path": "resources/js/loadscreen.js"
},
{
"path": "env.js"
},
{

51
app/Application.js

@ -29,9 +29,7 @@ Ext.define('Rambox.Application', {
// Set Google Analytics events
ga_storage._setAccount('UA-80680424-1');
ga_storage._trackPageview('/index.html', 'main');
// Initialize Auth0
Rambox.ux.Auth0.init();
ga_storage._trackEvent('Versions', require('electron').remote.app.getVersion());
// Add shortcuts to switch services using CTRL + Number
var map = new Ext.util.KeyMap({
@ -45,9 +43,10 @@ Ext.define('Rambox.Application', {
,handler: function(key) {
var tabPanel = Ext.cq1('app-main');
var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
if ( tabPanel.items.items[activeIndex + 1] && tabPanel.items.items[activeIndex + 1].id === 'tbfill' ) activeIndex++;
if ( !tabPanel.items.items[activeIndex + 1] ) activeIndex = -1;
tabPanel.setActiveTab( activeIndex + 1 );
var i = activeIndex + 1;
if ( i >= tabPanel.items.items.length - 1 ) i = 0;
while ( tabPanel.items.items[i].id === 'tbfill' ) i++;
tabPanel.setActiveTab( i );
}
}
,{
@ -58,10 +57,38 @@ Ext.define('Rambox.Application', {
,handler: function(key) {
var tabPanel = Ext.cq1('app-main');
var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
if ( tabPanel.items.items[activeIndex - 1] && tabPanel.items.items[activeIndex - 1].id === 'tbfill' ) activeIndex--;
if ( !tabPanel.items.items[activeIndex - 1] && tabPanel.items.items.length !== 2 ) activeIndex = tabPanel.items.items.length;
if ( tabPanel.items.items.length === 2 ) activeIndex = 1;
tabPanel.setActiveTab( activeIndex - 1 );
var i = activeIndex - 1;
if ( i < 0 ) i = tabPanel.items.items.length - 1;
while ( tabPanel.items.items[i].id === 'tbfill' || i < 0 ) i--;
tabPanel.setActiveTab( i );
}
}
,{
key: Ext.event.Event.PAGE_DOWN
,ctrl: true
,alt: false
,shift: false
,handler: function(key) {
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 );
}
}
,{
key: Ext.event.Event.PAGE_UP
,ctrl: true
,alt: false
,shift: false
,handler: function(key) {
var tabPanel = Ext.cq1('app-main');
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--;
tabPanel.setActiveTab( i );
}
}
,{
@ -93,7 +120,9 @@ Ext.define('Rambox.Application', {
,ctrl: true
,alt: false
,handler: function(key) {
Ext.cq1('app-main').setActiveTab(key - 48);
key = key - 48;
if ( key >= Ext.cq1('app-main').items.indexOf(Ext.getCmp('tbfill')) ) key++;
Ext.cq1('app-main').setActiveTab(key);
}
}
,{

8
app/model/ServiceList.js

@ -31,6 +31,10 @@ Ext.define('Rambox.model.ServiceList', {
name: 'allow_popups'
,type: 'boolean'
,defaultValue: false
},{
name: 'manual_notifications'
,type: 'boolean'
,defaultValue: false
},{
name: 'userAgent'
,type: 'string'
@ -39,5 +43,9 @@ Ext.define('Rambox.model.ServiceList', {
name: 'note'
,type: 'string'
,defaultValue: ''
},{
name: 'custom_domain'
,type: 'boolean'
,defaultValue: false
}]
});

2
app/package.json

@ -1,7 +1,7 @@
{
"name": "Rambox",
"productName": "Rambox",
"version": "0.4.2",
"version": "0.4.4",
"description": "Rambox",
"main": "electron/main.js",
"private": true,

146
app/store/ServicesList.js

@ -74,6 +74,7 @@ Ext.define('Rambox.store.ServicesList', {
,url: 'https://hangouts.google.com/'
,type: 'messaging'
,titleBlink: true
,manual_notifications: true
,js_unread: 'function checkUnread(){updateBadge(document.getElementById("hangout-landing-chat").lastChild.contentWindow.document.body.getElementsByClassName("ee").length)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
},
{
@ -84,6 +85,7 @@ Ext.define('Rambox.store.ServicesList', {
,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);'
,custom_domain: true
},
{
id: 'telegram'
@ -121,7 +123,8 @@ Ext.define('Rambox.store.ServicesList', {
,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.'
,url: 'http://inbox.google.com/?cid=imp'
,type: 'email'
,js_unread: 'function checkUnread(){updateBadge(document.getElementsByClassName("ss").length)}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle,checked&&a>oldUnread&&new Notification("Inbox",{body:"You have a new email",icon:"https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/inbox.png"}),checked=!0,oldUnread=a}var checked=!1,oldUnread,originalTitle=document.title;setInterval(checkUnread,3e3);'
,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);'
},
{
id: 'chatwork'
@ -186,7 +189,8 @@ Ext.define('Rambox.store.ServicesList', {
,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.'
,url: 'https://mail.live.com/'
,type: 'email'
,js_unread: 'function checkUnread(){var a=$(".subfolders [role=treeitem]:first .treeNodeRowElement").siblings().last().text();updateBadge(""===a?0:parseInt(a))}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle,checked&&a>oldUnread&&new Notification("Outlook",{body:"You have a new email",icon:"https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/outlook.png"}),checked=!0,oldUnread=a}var checked=!1,oldUnread,originalTitle=document.title;setInterval(checkUnread,3e3);'
,manual_notifications: true
,js_unread: 'function checkUnread(){var a=$(".subfolders [role=treeitem]:first .treeNodeRowElement").siblings().last().text();updateBadge(""===a?0:parseInt(a))}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3e3);'
},
{
id: 'outlook365'
@ -195,7 +199,8 @@ Ext.define('Rambox.store.ServicesList', {
,description: 'Outlook for Business'
,url: 'https://outlook.office.com/owa/'
,type: 'email'
,js_unread: 'function checkUnread(){var a=$(".subfolders [role=treeitem]:first .treeNodeRowElement").siblings().last().text();updateBadge(""===a?0:parseInt(a))}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle,checked&&a>oldUnread&&new Notification("Outlook 365",{body:"You have a new email",icon:"https://raw.githubusercontent.com/saenzramiro/rambox/master/resources/icons/outlook365.png"}),checked=!0,oldUnread=a}var checked=!1,oldUnread,originalTitle=document.title;setInterval(checkUnread,3e3);'
,manual_notifications: true
,js_unread: 'function checkUnread(){var a=$(".subfolders [role=treeitem]:first .treeNodeRowElement").siblings().last().text();updateBadge(""===a?0:parseInt(a))}function updateBadge(a){a>=1?document.title="("+a+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3e3);'
},
{
id: 'yahoo'
@ -204,6 +209,7 @@ Ext.define('Rambox.store.ServicesList', {
,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.'
,url: 'https://mail.yahoo.com/'
,type: 'email'
,note: 'To enable desktop notifications, you have to go to Options inside Yahoo! Mail.'
},
{
id: 'protonmail'
@ -311,6 +317,7 @@ Ext.define('Rambox.store.ServicesList', {
,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.'
,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}});'
},
{
id: 'dingtalk'
@ -352,6 +359,7 @@ Ext.define('Rambox.store.ServicesList', {
,logo: 'custom.png'
,name: '_Custom Service'
,description: 'Add a custom service if is not listed above.'
,url: '___'
,type: 'custom'
,allow_popups: true
},
@ -413,6 +421,8 @@ Ext.define('Rambox.store.ServicesList', {
,description: 'Ad-free business Email Hosting with a clean, minimalist interface. Integrated Calendar, Contacts, Notes, Tasks apps.'
,url: 'https://mail.zoho.com/'
,type: 'email'
,js_unread: 'zmail.aInfo[zmail.accId].mailId = "a";'
,note: 'To enable desktop notifications, you have to go to Settings inside Zoho Email.'
},
{
id: 'zohochat'
@ -449,13 +459,14 @@ Ext.define('Rambox.store.ServicesList', {
,type: 'email'
},
{
id:' irccloud'
id: ' irccloud'
,logo: 'irccloud.png'
,name: 'IRCCloud'
,description: 'IRCCloud is a modern IRC client that keeps you connected, with none of the baggage.'
,url: 'https://www.irccloud.com/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var t=0;[].map.call(document.querySelectorAll(".bufferBadges > .badge"),n=>n.textContent?parseInt(n.textContent,10):0).reduce((x,y)=>x+y,0);updateBadge(t)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'
,custom_domain: true
},
{
id: 'ryver'
@ -481,6 +492,7 @@ Ext.define('Rambox.store.ServicesList', {
,url: 'https://kiwiirc.com/client'
,type: 'messaging'
,js_unread: 'function getUnreadCount(){var a=0;$(".activity").each(function(){a+=parseInt($(this).html())});var b=!1;return $(".panel[style*=display: block] .msg").each(function(){b?a++:$(this).hasClass("last_seen")&&(b=!0)}),a}function updateTitle(a){count=getUnreadCount(),cleanTitle=a.match(re),null!==cleanTitle&&cleanTitle.length>1?cleanTitle=cleanTitle[1]:cleanTitle=a,a=count>0?"("+getUnreadCount()+") "+cleanTitle:cleanTitle,$("title").text(a)}var re=/\(\d+\)[ ](.*)/;Object.defineProperty(document,"title",{configurable:!0,set:function(a){updateTitle(a)},get:function(){return $("title").text()}}),setInterval(function(){updateTitle(document.title)},3e3);'
,custom_domain: true
},
{
id: 'icloud'
@ -524,6 +536,130 @@ Ext.define('Rambox.store.ServicesList', {
,url: '___'
,type: 'email'
,js_unread: 'function check_unread(){update_badge(appCtxt.getById(ZmFolder.ID_INBOX).numUnread)}function update_badge(a){document.title=a>0?"("+a+") "+original_title:original_title}const original_title=document.title;setInterval(check_unread,3e3);'
},
{
id: 'kaiwa'
,logo: 'kaiwa.png'
,name: 'Kaiwa'
,description: 'A modern and Open Source Web client for XMPP.'
,url: '___'
,type: 'messaging'
,js_unread: 'function check_unread() { let count=0; for (let node of document.getElementsByClassName("unread")){ if (node.innerHTML){ count += parseInt(node.innerHTML); } } update_badge(count);}function update_badge(a) { document.title = a > 0 ? "(" + a + ") " + original_title : original_title}const original_title = document.title;setInterval(check_unread, 3e3);'
},
{
id: 'movim'
,logo: 'movim.png'
,name: 'Movim'
,description: 'Movim is a decentralized social network, written in PHP and HTML5 and based on the XMPP standard protocol.'
,url: 'https://___.movim.eu/'
,type: 'messaging'
,js_unread: 'function checkUnread(){var a=document.getElementsByClassName("color dark"),b=0;for(i=0;i<a.length;i++){var c=a[i].getElementsByClassName("counter");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,3e3);'
,custom_domain: true
},
{
id: 'pushbullet'
,logo: 'pushbullet.png'
,name: 'Pushbullet'
,description: 'Pushbullet connects your devices, making them feel like one.'
,url: 'https://www.pushbullet.com/'
,type: 'messaging'
},
{
id: 'riot'
,logo: 'riot.png'
,name: 'Riot'
,description: 'Riot is a simple and elegant collaboration environment that gathers all of your different conversations and app integrations into one single app.'
,url: 'https://riot.im/app/'
,type: 'messaging'
},
{
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'
,name: 'Socialcast'
,description: 'Socialcast is the premier enterprise social networking platform that connects people to the knowledge, ideas and resources they need to work more effectively.'
,url: 'https://___.socialcast.com/'
,type: 'messaging'
},
{
id: 'fleep'
,logo: 'fleep.png'
,name: 'Fleep'
,description: 'Fleep enables communication within and across organizations - be it your team chats, project communication or 1:1 conversations.'
,url: 'https://fleep.io/chat'
,type: 'messaging'
,js_unread: 'document.getElementsByClassName("google-login-area")[0].remove();document.getElementsByClassName("microsoft-login-area")[0].remove();'
},
{
id: 'spark'
,logo: 'spark.png'
,name: 'Cisco Spark'
,description: 'Cisco Spark is for group chat, video calling, and sharing documents with your team. It’s all backed by Cisco security and reliability.'
,url: 'https://web.ciscospark.com/'
,type: 'messaging'
},
{
id: 'mmmelon'
,logo: 'mmmelon.png'
,name: 'mmmelon'
,description: 'The ultimate tool for daily management of projects and teams. Cloud-based, web and mobile.'
,url: '___'
,type: 'messaging'
},
{
id: 'drift'
,logo: 'drift.png'
,name: 'Drift'
,description: 'Drift is a messaging app that makes it easy for businesses to talk to their website visitors and customers in real-time, from anywhere.'
,url: 'https://app.drift.com/'
,type: 'messaging'
},
{
id: 'typetalk'
,logo: 'typetalk.png'
,name: 'Typetalk'
,description: 'Typetalk brings fun and ease to team discussions through instant messaging on desktop and mobile devices.'
,url: 'https://typetalk.in/signin'
,type: 'messaging'
},
{
id: 'openmailbox'
,logo: 'openmailbox.png'
,name: 'Openmailbox'
,description: 'Free mail hosting. Respect your rights and your privacy.'
,url: 'https://www.openmailbox.org/webmail/'
,type: 'email'
},
{
id: 'flock'
,logo: 'flock.png'
,name: 'Flock'
,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'
},
{
id: 'crisp'
,logo: 'crisp.png'
,name: 'Crisp'
,description: 'Connect your customers to your team.'
,url: 'https://app.crisp.im/inbox'
,type: 'messaging'
},
{
id: 'smooch'
,logo: 'smooch.png'
,name: 'Smooch'
,description: 'Unified multi-channel messaging for businesses, bots and software makers.'
,url: 'https://app.smooch.io/'
,type: 'messaging'
}
]
]
});

10
app/ux/Auth0.js

@ -113,7 +113,7 @@ Ext.define('Rambox.ux.Auth0', {
} else {
Ext.Msg.confirm('Clear services', 'Do you want to remove all your current services to start over?<br /><br />If <b>NO</b>, you will be logged out.', function(btnId) {
if ( btnId === 'yes' ) {
me.removeAllServices(false);
Ext.cq1('app-main').getController().removeAllServices(false);
} else {
me.logout();
}
@ -124,7 +124,7 @@ Ext.define('Rambox.ux.Auth0', {
} else if ( snapshot2.hasChildren() && Ext.getStore('Services').getCount() > 0 ) {
Ext.Msg.confirm('Confirm', 'To import your configuration, I need to remove all your current services. Do you want to continue?<br /><br />If <b>NO</b>, you will be logged out.', function(btnId) {
if ( btnId === 'yes' ) {
me.removeAllServices(false, function() {
Ext.cq1('app-main').getController().removeAllServices(false, function() {
importServices(snapshot2);
});
} else {
@ -140,10 +140,10 @@ Ext.define('Rambox.ux.Auth0', {
localStorage.setItem('id_token', authResult.idToken);
}
});
}).catch(function(error) {
})['catch'](function(error) {
Ext.Msg.hide();
Ext.Msg.show({
title: 'Firebug Error'
title: 'Firebase Error'
,message: error.message+'<br><br>Code: '+error.code+'<br><br>Sorry, try again later.'
,icon: Ext.Msg.ERROR
,buttons: Ext.Msg.OK
@ -164,6 +164,8 @@ Ext.define('Rambox.ux.Auth0', {
,login: function() {
var me = this;
if ( !me.auth0 ) Rambox.ux.Auth0.init();
me.lock.show();
}

44
app/ux/Firebase.js

@ -14,14 +14,43 @@ Ext.define('Rambox.ux.Firebase', {
// Attach an asynchronous callback to read the data at our posts reference
ref.on("child_changed", function(snapshot, prevChildKey) {
// Disable duplicate actions when user edit a service
var rec = Ext.getStore('Services').findRecord('firebase_key', snapshot.key);
var recData = Ext.clone(rec.data);
delete recData.id;
delete recData.firebase_key;
if ( Ext.Object.equals(recData, snapshot.val()) ) return;
console.info('Firebase - Child Changed', snapshot.val(), snapshot.key, prevChildKey);
// Suspend events
Ext.getStore('Services').suspendEvent('update');
var rec = Ext.getStore('Services').findRecord('firebase_key', snapshot.key);
// Change the title of the Tab
Ext.getCmp('tab_'+rec.get('id')).setTitle(snapshot.val().name);
// Change sound of the Tab
Ext.getCmp('tab_'+rec.get('id')).setAudioMuted(snapshot.val().muted);
// Change notifications of the Tab
Ext.getCmp('tab_'+rec.get('id')).setNotifications(snapshot.val().notifications);
// Change the icon of the Tab
if ( rec.get('type') === 'custom' && rec.get('logo') !== snapshot.val().logo ) Ext.getCmp('tab_'+rec.get('id')).setConfig('icon', snapshot.val().logo === '' ? 'resources/icons/custom.png' : snapshot.val().logo);
// Change the URL of the Tab
if ( rec.get('url') !== snapshot.val().url ) Ext.getCmp('tab_'+rec.get('id')).setURL(snapshot.val().url);
// Change the align of the Tab
if ( rec.get('align') !== snapshot.val().align ) {
if ( rec.get('align') === 'left' ) {
Ext.cq1('app-main').moveBefore(Ext.getCmp('tab_'+rec.get('id')), Ext.getCmp('tbfill'));
} else {
Ext.cq1('app-main').moveAfter(Ext.getCmp('tab_'+rec.get('id')), Ext.getCmp('tbfill'));
}
}
// Apply the JS Code of the Tab
if ( rec.get('js_unread') !== snapshot.val().js_unread ) {
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 ) {
if ( btnId === 'yes' ) Ext.getCmp('tab_'+rec.get('id')).reloadService();
});
}
// Position
if ( rec.get('position') !== snapshot.val().position ) {
var pos = parseInt(snapshot.val().position);
@ -29,11 +58,14 @@ Ext.define('Rambox.ux.Firebase', {
Ext.cq1('app-main').move(Ext.getCmp('tab_'+rec.get('id')), pos);
}
// Enable/Disable
if ( rec.get('enable') !== snapshot.val().enable ) Ext.getCmp('tab_'+rec.get('id')).setEnabled(snapshot.val().enabled);
rec.set(snapshot.val());
rec.save();
Ext.getCmp('tab_'+rec.get('id')).record = rec;
Ext.getCmp('tab_'+rec.get('id')).tabConfig.service = rec;
// Enable/Disable
if ( recData.enabled !== snapshot.val().enabled ) Ext.getCmp('tab_'+rec.get('id')).setEnabled(snapshot.val().enabled);
Ext.getStore('Services').resumeEvent('update');
Ext.getStore('Services').load();
}, function (errorObject) {

71
app/ux/WebView.js

@ -34,7 +34,14 @@ Ext.define('Rambox.ux.WebView',{
if ( me.record.get('trust') ) ipc.send('allowCertificate', me.src);
Ext.apply(me, {
items: me.webViewConstructor(me.record.get('enabled'))
items: me.webViewConstructor()
,title: 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')
,align: me.record.get('align')
,notifications: me.record.get('notifications')
,muted: me.record.get('muted')
,tabConfig: {
listeners: {
badgetextchange: me.onBadgeTextChange
@ -44,6 +51,7 @@ Ext.define('Rambox.ux.WebView',{
e.stopEvent();
});
}
,scope: me
}
,clickEvent: ''
,style: !me.record.get('enabled') ? '-webkit-filter: grayscale(1)' : ''
@ -121,10 +129,12 @@ Ext.define('Rambox.ux.WebView',{
me.callParent(config);
}
,webViewConstructor: function(enabled) {
,webViewConstructor: function( enabled ) {
var me = this;
var cfg;
enabled = enabled || me.record.get('enabled');
if ( !enabled ) {
cfg = {
xtype: 'container'
@ -140,25 +150,26 @@ Ext.define('Rambox.ux.WebView',{
,autoShow: true
,autoEl: {
tag: 'webview'
,src: me.src
,src: me.record.get('url')
,style: 'width:100%;height:100%;'
,partition: 'persist:' + me.type + '_' + me.id.replace('tab_', '') + (localStorage.getItem('id_token') ? '_' + Ext.decode(localStorage.getItem('profile')).user_id : '')
,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'
,autosize: 'on'
,disablewebsecurity: 'on'
,blinkfeatures: 'ApplicationCache,GlobalCacheStorage'
,useragent: Ext.getStore('ServicesList').getById(me.type).get('userAgent')
,useragent: Ext.getStore('ServicesList').getById(me.record.get('type')).get('userAgent')
}
};
if ( Ext.getStore('ServicesList').getById(me.type).get('allow_popups') ) cfg.autoEl.allowpopups = 'on';
if ( Ext.getStore('ServicesList').getById(me.record.get('type')).get('allow_popups') ) cfg.autoEl.allowpopups = 'on';
}
return cfg;
}
,onBadgeTextChange: function( tab, badgeText, oldBadgeText ) {
var me = this;
if ( oldBadgeText === null ) oldBadgeText = 0;
var actualNotifications = Rambox.app.getTotalNotifications();
@ -166,6 +177,31 @@ Ext.define('Rambox.ux.WebView',{
badgeText = Rambox.util.Format.stripNumber(badgeText);
Rambox.app.setTotalNotifications(actualNotifications - oldBadgeText + badgeText);
// Some services dont have Desktop Notifications, so we add that functionality =)
if ( Ext.getStore('ServicesList').getById(me.type).get('manual_notifications') && oldBadgeText < badgeText && me.record.get('notifications') && !JSON.parse(localStorage.getItem('dontDisturb')) ) {
var text;
switch ( Ext.getStore('ServicesList').getById(me.type).get('type') ) {
case 'messaging':
text = 'You have ' + Ext.util.Format.plural(badgeText, 'new message', 'new messages') + '.';
break;
case 'email':
text = 'You have ' + Ext.util.Format.plural(badgeText, 'new email', 'new emails') + '.';
break;
default:
text = 'You have ' + Ext.util.Format.plural(badgeText, 'new activity', 'new activities') + '.';
break;
}
var not = new Notification(me.record.get('name'), {
body: text
,icon: tab.icon
,silent: me.record.get('muted')
});
not.onclick = function() {
require('electron').remote.getCurrentWindow().show();
Ext.cq1('app-main').setActiveTab(me);
};
}
}
,onAfterRender: function() {
@ -198,7 +234,6 @@ Ext.define('Rambox.ux.WebView',{
// Open links in default browser
webview.addEventListener('new-window', function(e) {
console.log('new-window', e);
switch ( me.type ) {
case 'skype':
// hack to fix multiple browser tabs on Skype link click, re #11
@ -271,7 +306,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);
if ( e.isMainFrame ) webview.loadURL(e.newURL);
});
}
@ -279,7 +314,10 @@ Ext.define('Rambox.ux.WebView',{
var me = this;
var webview = me.down('component').el.dom;
if ( me.record.get('enabled') ) webview.loadURL(me.src);
if ( me.record.get('enabled') ) {
me.tab.setBadgeText('');
webview.loadURL(me.src);
}
}
,toggleDevTools: function(btn) {
@ -289,10 +327,21 @@ Ext.define('Rambox.ux.WebView',{
if ( me.record.get('enabled') ) webview.isDevToolsOpened() ? webview.closeDevTools() : webview.openDevTools();
}
,setURL: function(url) {
var me = this;
var webview = me.down('component').el.dom;
me.src = url;
if ( me.record.get('enabled') ) webview.loadURL(url);
}
,setAudioMuted: function(muted, calledFromDisturb) {
var me = this;
var webview = me.down('component').el.dom;
me.muted = muted;
if ( !muted && !calledFromDisturb && JSON.parse(localStorage.getItem('dontDisturb')) ) return;
if ( me.record.get('enabled') ) webview.setAudioMuted(muted);
@ -302,6 +351,8 @@ Ext.define('Rambox.ux.WebView',{
var me = this;
var webview = me.down('component').el.dom;
me.notifications = notification;
if ( notification && !calledFromDisturb && JSON.parse(localStorage.getItem('dontDisturb')) ) return;
if ( me.record.get('enabled') ) ipc.send('setServiceNotifications', webview.partition, notification);
@ -310,12 +361,14 @@ Ext.define('Rambox.ux.WebView',{
,setEnabled: function(enabled) {
var me = this;
me.tab.setBadgeText('');
me.removeAll();
me.add(me.webViewConstructor(enabled));
if ( enabled ) {
me.resumeEvent('afterrender');
me.show();
me.tab.setStyle('-webkit-filter', 'grayscale(0)');
me.onAfterRender();
} else {
me.suspendEvent('afterrender');
me.tab.setStyle('-webkit-filter', 'grayscale(1)');

219
app/view/add/Add.js

@ -0,0 +1,219 @@
Ext.define('Rambox.view.add.Add',{
extend: 'Ext.window.Window'
,requires: [
'Rambox.view.add.AddController'
,'Rambox.view.add.AddModel'
]
,controller: 'add-add'
,viewModel: {
type: 'add-add'
}
// private
,record: null
,service: null
,edit: false
// defaults
,modal: true
,width: 500
,autoShow: true
,resizable: false
,draggable: false
,bodyPadding: 20
,initComponent: function() {
var me = this;
me.title = (!me.edit ? 'Add ' : 'Edit ') + 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 = [
{
xtype: 'form'
,items: [
{
xtype: 'textfield'
,fieldLabel: 'Name'
,value: me.record.get('type') === 'custom' ? (me.edit ? me.record.get('name') : '') : me.record.get('name')
,name: 'serviceName'
,allowBlank: true
,listeners: { specialkey: 'onEnter' }
}
,{
xtype: 'container'
,layout: 'column'
,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: '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')
,allowBlank: false
,submitEmptyText: false
,emptyText: me.record.get('url') === '___' ? 'http://' : ''
,vtype: me.record.get('url') === '___' ? 'url' : ''
,width: 275
,listeners: { specialkey: 'onEnter' }
}
,{
xtype: 'cycle'
,showText: true
,style: 'border-top-left-radius:0;border-bottom-left-radius:0;'
,hidden: me.edit ? me.service.get('type') === 'custom' || me.service.get('url') === '___' : me.record.get('type') === 'custom' || me.record.get('url') === '___'
,arrowVisible: me.edit ? (me.service.get('url').indexOf('___') >= 0 && !me.service.get('custom_domain') ? false : me.service.get('custom_domain')) : (me.record.get('url').indexOf('___') >= 0 && !me.record.get('custom_domain') ? false : me.record.get('custom_domain'))
,menu: {
items: [
{
text: me.edit ? (me.service.get('url').indexOf('___') === -1 ? 'Official Server' : Ext.String.endsWith(me.service.get('url'), '/') ? me.service.get('url').split('___')[1].slice(0, -1) : me.service.get('url').split('___')[1]) : (me.record.get('url').indexOf('___') === -1 ? 'Official Server' : Ext.String.endsWith(me.record.get('url'), '/') ? me.record.get('url').split('___')[1].slice(0, -1) : me.record.get('url').split('___')[1])
,checked: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? true : Ext.String.endsWith(me.record.get('url'), me.service.get('url').split('___')[1])) : true
,disabled: me.edit ? me.service.get('url') === '___' : me.record.get('url') === '___'
}
,{
text: 'Custom Server'
,checked: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? false : !Ext.String.endsWith(me.record.get('url'), me.service.get('url').split('___')[1])) : false
,custom: true
,disabled: me.edit ? !me.service.get('custom_domain') : !me.record.get('custom_domain')
}
]
}
// Fixes bug EXTJS-20094 for version Ext JS 5
,arrowHandler: function(cycleBtn, e) {
if ( !cycleBtn.arrowVisible ) cycleBtn.hideMenu();
}
,changeHandler: function(cycleBtn, activeItem) {
Ext.apply(cycleBtn.previousSibling(), {
emptyText: activeItem.custom ? 'http://' : ' '
,vtype: activeItem.custom ? 'url' : ''
});
cycleBtn.previousSibling().applyEmptyText();
cycleBtn.previousSibling().reset();
if ( me.edit && cycleBtn.nextSibling().originalValue !== '2' ) {
me.service.get('custom_domain') && !activeItem.custom ? cycleBtn.previousSibling().reset() : cycleBtn.previousSibling().setValue('');
} else if ( me.edit && cycleBtn.nextSibling().originalValue === '2' ) {
me.service.get('custom_domain') && !activeItem.custom ? cycleBtn.previousSibling().setValue( me.service.get('url').indexOf('___') === -1 && me.service.get('custom_domain') ? me.service.get('url') : '') : cycleBtn.previousSibling().reset();
} else if ( !me.edit && cycleBtn.nextSibling().originalValue === '1' ) {
activeItem.custom ? cycleBtn.previousSibling().setValue('') : cycleBtn.previousSibling().reset();
}
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 );
}
}
,{
xtype: 'hiddenfield'
,name: 'cycleValue'
,value: me.edit ? (me.service.get('custom_domain') && me.service.get('url') === me.record.get('url') ? 1 : (!Ext.String.endsWith(me.record.get('url'), me.service.get('url').split('___')[1]) ? 2 : 1)) : 1
}
]
}
,{
xtype: 'textfield'
,fieldLabel: 'Logo'
,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'
,margin: '5 0 0 0'
,listeners: { specialkey: 'onEnter' }
}
,{
xtype: 'fieldset'
,title: 'Options'
,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') : false
,uncheckedValue: false
,inputValue: true
}
]
}
,{
xtype: 'fieldset'
,title: 'Advanced'
,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>)'
,allowBlank: true
,name: 'js_unread'
,value: me.edit ? me.record.get('js_unread') : ''
,anchor: '100%'
,height: 120
}
]
}
,{
xtype: 'container'
,hidden: (me.edit ? Ext.getStore('ServicesList').getById(me.record.get('type')).get('note') === '' : me.record.get('note') === '')
,data: { note: (me.edit ? Ext.getStore('ServicesList').getById(me.record.get('type')).get('note') : me.record.get('note')) }
,margin: '10 0 0 0'
,style: 'background-color:#93CFE0;color:#053767;border-radius:6px;'
,tpl: [
'<i class="fa fa-info-circle" aria-hidden="true" style="font-size:40px;margin:20px;"></i>'
,'<span style="font-size: 15px;position: absolute;padding: 10px 10px 10px 0;">{note}</span>'
]
}
]
}
];
me.buttons = [
{
text: 'Cancel'
,ui: 'decline'
,handler: 'doCancel'
}
,'->'
,{
text: me.title
,itemId: 'submit'
,handler: 'doSave'
}
];
this.callParent(this);
}
,listeners: {
show: 'onShow'
}
});

125
app/view/add/AddController.js

@ -0,0 +1,125 @@
Ext.define('Rambox.view.add.AddController', {
extend: 'Ext.app.ViewController'
,alias: 'controller.add-add'
,doCancel: function( btn ) {
var me = this;
me.getView().close();
}
,doSave: function( btn ) {
var me = this;
var win = me.getView();
if ( !win.down('form').isValid() ) return false;
var formValues = win.down('form').getValues();
if ( win.edit ) {
// Format data
if ( win.service.get('url').indexOf('___') >= 0 ) {
formValues.url = formValues.cycleValue === '1' ? win.service.get('url').replace('___', formValues.url) : formValues.url;
}
var oldData = win.record.getData();
win.record.set({
logo: formValues.logo
,name: formValues.serviceName
,url: formValues.url
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,trust: formValues.trust
,js_unread: formValues.js_unread
});
// Change the title of the Tab
Ext.getCmp('tab_'+win.record.get('id')).setTitle(formValues.serviceName);
// Change sound of the Tab
Ext.getCmp('tab_'+win.record.get('id')).setAudioMuted(formValues.muted);
// Change notifications of the Tab
Ext.getCmp('tab_'+win.record.get('id')).setNotifications(formValues.notifications);
// Change the icon of the Tab
if ( win.record.get('type') === 'custom' && oldData.logo !== formValues.logo ) Ext.getCmp('tab_'+win.record.get('id')).setConfig('icon', formValues.logo === '' ? 'resources/icons/custom.png' : formValues.logo);
// Change the URL of the Tab
if ( oldData.url !== formValues.url ) Ext.getCmp('tab_'+win.record.get('id')).setURL(formValues.url);
// Change the align of the Tab
if ( oldData.align !== formValues.align ) {
if ( formValues.align === 'left' ) {
Ext.cq1('app-main').moveBefore(Ext.getCmp('tab_'+win.record.get('id')), Ext.getCmp('tbfill'));
} else {
Ext.cq1('app-main').moveAfter(Ext.getCmp('tab_'+win.record.get('id')), Ext.getCmp('tbfill'));
}
}
// 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 ) {
if ( btnId === 'yes' ) Ext.getCmp('tab_'+win.record.get('id')).reloadService();
});
}
Ext.getCmp('tab_'+win.record.get('id')).record = win.record;
Ext.getCmp('tab_'+win.record.get('id')).tabConfig.service = win.record;
} else {
// Format data
if ( win.record.get('url').indexOf('___') >= 0 ) {
formValues.url = formValues.cycleValue === '1' ? win.record.get('url').replace('___', formValues.url) : formValues.url;
}
var service = Ext.create('Rambox.model.Service', {
type: win.record.get('id')
,logo: formValues.logo
,name: formValues.serviceName
,url: formValues.url
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,trust: formValues.trust
,js_unread: formValues.js_unread
});
service.save();
Ext.getStore('Services').add(service);
var tabData = {
xtype: 'webview'
,id: 'tab_'+service.get('id')
/*
,title: service.get('name')
,icon: service.get('logo')
,src: service.get('url')
,type: service.get('type')
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
*/
,record: service
,tabConfig: {
service: service
}
};
if ( formValues.align === 'left' ) {
var tbfill = Ext.cq1('app-main').getTabBar().down('tbfill');
Ext.cq1('app-main').insert(Ext.cq1('app-main').getTabBar().items.indexOf(tbfill), tabData).show();
} else {
Ext.cq1('app-main').add(tabData).show();
}
}
win.close();
}
,onEnter: function(field, e) {
var me = this;
if ( e.getKey() == e.ENTER && field.up('form').isValid() ) me.doSave();
}
,onShow: function(win) {
var me = this;
// Make focus to the name field
win.down('textfield[name="serviceName"]').focus(true, 100);
}
});

4
app/view/add/AddModel.js

@ -0,0 +1,4 @@
Ext.define('Rambox.view.add.AddModel', {
extend: 'Ext.app.ViewModel'
,alias: 'viewmodel.add-add'
});

48
app/view/main/Main.js

@ -5,6 +5,7 @@ Ext.define('Rambox.view.main.Main', {
,'Rambox.view.main.MainModel'
,'Rambox.ux.WebView'
,'Rambox.ux.mixin.Badge'
,'Rambox.view.add.Add'
,'Ext.ux.TabReorderer'
]
@ -290,16 +291,18 @@ Ext.define('Rambox.view.main.Main', {
,allowToggle: false
,items: [
{
text: '<b>Donate</b> with'
,overCls: ''
text: '<b>Help us</b> with'
,pressed: true
}
,{
glyph: 'xf1ed@FontAwesome'
,href: 'https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WU75QWS7LH2CA'
text: 'Donation'
,glyph: 'xf21e@FontAwesome'
,handler: 'showDonate'
}
,{
glyph: 'xf15a@FontAwesome'
,href: 'https://www.coinbase.com/saenzramiro'
text: 'Translation'
,glyph: 'xf0ac@FontAwesome'
,href: 'https://crowdin.com/project/rambox/invite'
}
]
}
@ -310,19 +313,26 @@ Ext.define('Rambox.view.main.Main', {
}
,'->'
,{
glyph: 'xf082@FontAwesome'
,tooltip: 'Facebook'
,href: 'https://www.facebook.com/ramboxapp'
}
,{
glyph: 'xf099@FontAwesome'
,tooltip: 'Twitter'
,href: 'https://www.twitter.com/ramboxapp'
}
,{
glyph: 'xf09b@FontAwesome'
,tooltip: 'GitHub'
,href: 'https://www.github.com/saenzramiro/rambox'
xtype: 'segmentedbutton'
,allowToggle: false
,items: [
{
text: '<b>Follow us</b>'
,pressed: true
}
,{
glyph: 'xf082@FontAwesome'
,href: 'https://www.facebook.com/ramboxapp'
}
,{
glyph: 'xf099@FontAwesome'
,href: 'https://www.twitter.com/ramboxapp'
}
,{
glyph: 'xf09b@FontAwesome'
,href: 'https://www.github.com/saenzramiro/rambox'
}
]
}
]
}

638
app/view/main/MainController.js

@ -45,395 +45,6 @@ Ext.define('Rambox.view.main.MainController', {
Ext.getCmp('tab_'+e.record.get('id')).setTitle(e.record.get('name'));
}
,showSimpleModal: function(record, edit) {
var me = this;
var win = Ext.create('Ext.window.Window', {
title: (edit ? 'Edit ' : 'Add ') + record.get('name')
,modal: true
,width: 400
,resizable: false
,draggable: false
,bodyPadding: 20
,icon: 'resources/icons/' + record.get('logo')
,items: [
{
xtype: 'form'
,items: [
{
xtype: 'textfield'
,fieldLabel: 'Name'
,value: record.get('name')
,name: 'serviceName'
,allowBlank: true
,listeners: {
specialkey: function(field, e) {
if(e.getKey() == e.ENTER && field.up('form').isValid()) {
field.up('window').down('#submit').handler();
}
}
}
}
,{
xtype: 'fieldset'
,title: 'Options'
,margin: '10 0 0 0'
,items: [
{
xtype: 'checkbox'
,boxLabel: 'Align to Right'
,checked: edit ? (record.get('align') === 'right' ? true : false) : false
,name: 'align'
,uncheckedValue: 'left'
,inputValue: 'right'
}
,{
xtype: 'checkbox'
,boxLabel: 'Show notifications'
,name: 'notifications'
,checked: edit ? record.get('notifications') : true
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: 'Mute all sounds'
,name: 'muted'
,checked: edit ? record.get('muted') : false
,uncheckedValue: false
,inputValue: true
}
]
}
,{
xtype: 'fieldset'
,title: 'Advanced'
,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>)'
,allowBlank: true
,name: 'js_unread'
,value: edit ? record.get('js_unread') : ''
,anchor: '100%'
,height: 120
}
]
}
,{
xtype: 'container'
,hidden: (edit ? Ext.getStore('ServicesList').getById(record.get('type')).get('note') === '' : record.get('note') === '')
,data: { note: (edit ? Ext.getStore('ServicesList').getById(record.get('type')).get('note') : record.get('note')) }
,margin: '10 0 0 0'
,style: 'background-color:#93CFE0;color:#053767;border-radius:6px;'
,tpl: [
'<i class="fa fa-info-circle" aria-hidden="true" style="font-size:40px;margin:20px;"></i>'
,'<span style="font-size: 15px;position: absolute;padding: 10px 10px 10px 0;">{note}</span>'
]
}
]
}
]
,buttons: [
{
text: 'Cancel'
,ui: 'decline'
,handler: function() {
win.close();
}
}
,'->'
,{
text: edit ? 'Save' : 'Add service'
,itemId: 'submit'
,handler: function() {
if ( !win.down('form').isValid() ) return false;
var formValues = win.down('form').getValues();
if ( edit ) {
var oldData = record.getData();
record.set({
name: formValues.serviceName
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,js_unread: formValues.js_unread
});
// Change the title of the Tab
Ext.getCmp('tab_'+record.get('id')).setTitle(formValues.serviceName);
// Change sound of the Tab
Ext.getCmp('tab_'+record.get('id')).setAudioMuted(formValues.muted);
// Change notifications of the Tab
Ext.getCmp('tab_'+record.get('id')).setNotifications(formValues.notifications);
// Change the align of the Tab
if ( oldData.align !== formValues.align ) {
if ( formValues.align === 'left' ) {
me.getView().moveBefore(Ext.getCmp('tab_'+record.get('id')), Ext.getCmp('tbfill'));
} else {
me.getView().moveAfter(Ext.getCmp('tab_'+record.get('id')), Ext.getCmp('tbfill'));
}
}
Ext.getCmp('tab_'+record.get('id')).record = record;
} else {
var service = Ext.create('Rambox.model.Service', {
type: record.get('id')
,logo: record.get('logo')
,name: formValues.serviceName
,url: record.get('url')
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,js_unread: formValues.js_unread
});
service.save();
Ext.getStore('Services').add(service);
var tabData = {
xtype: 'webview'
,id: 'tab_'+service.get('id')
,title: service.get('name')
,icon: 'resources/icons/'+service.get('logo')
,src: service.get('url')
,type: service.get('type')
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,record: service
,tabConfig: {
service: service
}
};
if ( formValues.align === 'left' ) {
var tbfill = me.getView().getTabBar().down('tbfill');
me.getView().insert(me.getView().getTabBar().items.indexOf(tbfill), tabData).show();
} else {
me.getView().add(tabData).show();
}
}
win.close();
}
}
]
}).show();
// Make focus to the name field
win.down('textfield[name="serviceName"]').focus(true, 100);
}
,showCustomModal: function(record, edit) {
var me = this;
var win = Ext.create('Ext.window.Window', {
title: (edit ? 'Edit ' : 'Add ') + record.get('name')
,modal: true
,width: 400
,resizable: false
,draggable: false
,bodyPadding: 20
,icon: 'resources/icons/' + record.get('logo')
,items: [
{
xtype: 'form'
,items: [
{
xtype: 'textfield'
,fieldLabel: 'Name'
,value: record.get('name')
,name: 'serviceName'
,allowBlank: true
,listeners: {
specialkey: function(field, e) {
if(e.getKey() == e.ENTER && field.up('form').isValid()) {
field.up('window').down('#submit').handler();
}
}
}
}
,{
xtype: 'container'
,layout: 'column'
,items: [{
xtype: 'textfield'
,fieldLabel: record.get('name') + ' team'
,name: 'url'
,allowBlank: false
,submitEmptyText: false
,emptyText: record.get('url') === '___' ? 'http://' : ''
,vtype: record.get('url') === '___' ? 'url' : ''
,width: 220
,listeners: {
specialkey: function(field, e) {
if(e.getKey() == e.ENTER && field.up('form').isValid()) {
field.up('window').down('#submit').handler();
}
}
}
},{
xtype: 'displayfield'
,value: record.get('url').split('___')[1].slice(0, -1) // Get the URL and remove the final slash (/)
,submitValue: false // Prevent being submitted
}]
}
,{
xtype: 'fieldset'
,title: 'Options'
,margin: '10 0 0 0'
,items: [
{
xtype: 'checkbox'
,boxLabel: 'Align to Right'
,checked: edit ? (record.get('align') === 'right' ? true : false) : false
,name: 'align'
,uncheckedValue: 'left'
,inputValue: 'right'
}
,{
xtype: 'checkbox'
,boxLabel: 'Show notifications'
,name: 'notifications'
,checked: edit ? record.get('notifications') : true
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: 'Mute all sounds'
,name: 'muted'
,checked: edit ? record.get('muted') : false
,uncheckedValue: false
,inputValue: true
}
]
}
,{
xtype: 'fieldset'
,title: 'Advanced'
,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>)'
,allowBlank: true
,name: 'js_unread'
,value: edit ? record.get('js_unread') : ''
,anchor: '100%'
,height: 120
}
]
}
,{
xtype: 'container'
,hidden: (edit ? Ext.getStore('ServicesList').getById(record.get('type')).get('note') === '' : record.get('note') === '')
,data: { note: (edit ? Ext.getStore('ServicesList').getById(record.get('type')).get('note') : record.get('note')) }
,margin: '10 0 0 0'
,style: 'background-color:#93CFE0;color:#053767;border-radius:6px;'
,tpl: [
'<i class="fa fa-info-circle" aria-hidden="true" style="font-size:40px;margin:20px;"></i>'
,'<span style="font-size: 15px;position: absolute;padding: 10px 10px 10px 0;">{note}</span>'
]
}
]
}
]
,buttons: [
{
text: 'Cancel'
,ui: 'decline'
,handler: function() {
win.close();
}
}
,'->'
,{
text: edit ? 'Save' : 'Add service'
,itemId: 'submit'
,handler: function() {
if ( !win.down('form').isValid() ) return false;
var formValues = win.down('form').getValues();
if ( edit ) {
var oldData = record.getData();
record.set({
name: formValues.serviceName
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,js_unread: formValues.js_unread
});
// Change the title of the Tab
Ext.getCmp('tab_'+record.get('id')).setTitle(formValues.serviceName);
// Change sound of the Tab
Ext.getCmp('tab_'+record.get('id')).setAudioMuted(formValues.muted);
// Change notifications of the Tab
Ext.getCmp('tab_'+record.get('id')).setNotifications(formValues.notifications);
// Change the align of the Tab
if ( oldData.align !== formValues.align ) {
if ( formValues.align === 'left' ) {
me.getView().moveBefore(Ext.getCmp('tab_'+record.get('id')), Ext.getCmp('tbfill'));
} else {
me.getView().moveAfter(Ext.getCmp('tab_'+record.get('id')), Ext.getCmp('tbfill'));
}
}
Ext.getCmp('tab_'+record.get('id')).record = record;
} else {
var service = Ext.create('Rambox.model.Service', {
type: record.get('id')
,logo: record.get('logo')
,name: formValues.serviceName
,url: record.get('url').replace('___', formValues.url)
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,js_unread: formValues.js_unread
});
service.save();
Ext.getStore('Services').add(service);
var tabData = {
xtype: 'webview'
,id: 'tab_'+service.get('id')
,title: service.get('name')
,icon: 'resources/icons/'+service.get('logo')
,src: service.get('url')
,type: service.get('type')
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,record: service
,tabConfig: {
service: service
}
};
if ( formValues.align === 'left' ) {
var tbfill = me.getView().getTabBar().down('tbfill');
me.getView().insert(me.getView().getTabBar().items.indexOf(tbfill), tabData).show();
} else {
me.getView().add(tabData).show();
}
}
win.close();
}
}
]
}).show();
// Make focus to the name field
win.down('textfield[name="serviceName"]').focus(true, 100);
}
,onEnableDisableService: function(cc, rowIndex, checked) {
var rec = Ext.getStore('Services').getAt(rowIndex);
@ -441,13 +52,9 @@ Ext.define('Rambox.view.main.MainController', {
}
,onNewServiceSelect: function( view, record, item, index, e ) {
if ( record.get('url').indexOf('___') >= 0 ) {
this.showCustomModal(record);
} else if ( record.get('type') === 'custom' ) {
this.addCustomService(record, false);
} else {
this.showSimpleModal(record, false);
}
Ext.create('Rambox.view.add.Add', {
record: record
});
}
,removeServiceFn: function(serviceId) {
@ -459,7 +66,7 @@ Ext.define('Rambox.view.main.MainController', {
var rec = Ext.getStore('Services').getById(serviceId);
// Clear all trash data
if ( rec.get('enabled') ) {
if ( rec.get('enabled') && tab.down('component').el ) {
tab.down('component').el.dom.getWebContents().session.clearCache(Ext.emptyFn);
tab.down('component').el.dom.getWebContents().session.clearStorageData({}, Ext.emptyFn);
}
@ -495,6 +102,7 @@ Ext.define('Rambox.view.main.MainController', {
Ext.getStore('Services').load();
if ( Ext.isFunction(callback) ) callback();
Ext.cq1('app-main').resumeEvent('remove');
document.title = 'Rambox';
}
});
} else {
@ -505,236 +113,16 @@ Ext.define('Rambox.view.main.MainController', {
Ext.getStore('Services').load();
if ( Ext.isFunction(callback) ) callback();
Ext.cq1('app-main').resumeEvent('remove');
document.title = 'Rambox';
}
}
,configureService: function( gridView, rowIndex, colIndex, col, e, rec, rowEl ) {
if ( rec.get('type') === 'custom' ) {
this.addCustomService(rec, true);
} else {
this.showSimpleModal(rec, true);
}
}
,addCustomService: function( record, edit ) {
var me = this;
var win = Ext.create('Ext.window.Window', {
title: (edit ? 'Edit ' : 'Add ') + 'Custom Service'
,modal: true
,width: 400
,resizable: false
,draggable: false
,bodyPadding: 20
,items: [
{
xtype: 'form'
,items: [
{
xtype: 'textfield'
,fieldLabel: 'Name'
,name: 'serviceName'
,value: (edit ? record.get('name') : '')
,allowBlank: true
,listeners: {
specialkey: function(field, e) {
if(e.getKey() == e.ENTER && field.up('form').isValid()) {
field.up('window').down('#submit').handler();
}
}
}
}
,{
xtype: 'textfield'
,fieldLabel: 'URL'
,emptyText: 'http://service.url.com'
,name: 'url'
,vtype: 'url'
,value: (edit ? record.get('url') : '')
,allowBlank: false
,listeners: {
specialkey: function(field, e) {
if(e.getKey() == e.ENTER && field.up('form').isValid()) {
field.up('window').down('#submit').handler();
}
}
}
}
,{
xtype: 'textfield'
,fieldLabel: 'Logo'
,emptyText: 'http://image.url.com/image.png'
,name: 'logo'
,vtype: 'url'
,value: (edit ? record.get('logo') : '')
,allowBlank: true
,listeners: {
specialkey: function(field, e) {
if(e.getKey() == e.ENTER && field.up('form').isValid()) {
field.up('window').down('#submit').handler();
}
}
}
}
,{
xtype: 'fieldset'
,title: 'Options'
,margin: '10 0 0 0'
,items: [
{
xtype: 'checkbox'
,boxLabel: 'Align to Right'
,checked: edit ? (record.get('align') === 'right' ? true : false) : false
,name: 'align'
,uncheckedValue: 'left'
,inputValue: 'right'
}
,{
xtype: 'checkbox'
,boxLabel: 'Show notifications'
,name: 'notifications'
,checked: edit ? record.get('notifications') : true
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: 'Mute all sounds'
,name: 'muted'
,checked: edit ? record.get('muted') : false
,uncheckedValue: false
,inputValue: true
}
,{
xtype: 'checkbox'
,boxLabel: 'Trust invalid authority certificates'
,name: 'trust'
,checked: edit ? record.get('trust') : false
,uncheckedValue: false
,inputValue: true
}
]
}
,{
xtype: 'fieldset'
,title: 'Advanced'
,margin: '10 0 0 0'
,collapsible: true
,collapsed: true
,items: [
{
xtype: 'textarea'
,fieldLabel: 'Custom Code (<a href="https://github.com/saenzramiro/rambox/wiki/Add-a-Custom-Service" target="_blank">read more</a>)'
,allowBlank: true
,name: 'js_unread'
,value: (edit ? record.get('js_unread') : '')
,anchor: '100%'
,height: 120
}
]
}
]
}
]
,buttons: [
{
text: 'Cancel'
,ui: 'decline'
,handler: function() {
win.close();
}
}
,'->'
,{
text: (edit ? 'Edit ' : 'Add ') + ' Service'
,itemId: 'submit'
,handler: function() {
if ( !win.down('form').isValid() ) return false;
var formValues = win.down('form').getValues();
if ( edit ) {
var oldData = record.getData();
// If users change the URL, we change the URL of the Webview
if ( record.get('url') !== formValues.url ) Ext.getCmp('tab_'+record.get('id')).down('component').el.dom.loadURL(formValues.url);
// Save the service
record.set({
name: formValues.serviceName
,url: formValues.url
,logo: formValues.logo
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,trust: formValues.trust
,js_unread: formValues.js_unread
});
// Change the title of the Tab
Ext.getCmp('tab_'+record.get('id')).setTitle(formValues.serviceName);
// Change sound of the Tab
Ext.getCmp('tab_'+record.get('id')).setAudioMuted(formValues.muted);
// Change notifications of the Tab
Ext.getCmp('tab_'+record.get('id')).setNotifications(formValues.notifications);
// Change the icon of the Tab
Ext.getCmp('tab_'+record.get('id')).setIcon(record.get('logo') === '' ? 'resources/icons/custom.png' : record.get('logo'));
// Change the align of the Tab
if ( oldData.align !== formValues.align ) {
if ( formValues.align === 'left' ) {
me.getView().moveBefore(Ext.getCmp('tab_'+record.get('id')), Ext.getCmp('tbfill'));
} else {
me.getView().moveAfter(Ext.getCmp('tab_'+record.get('id')), Ext.getCmp('tbfill'));
}
}
Ext.getCmp('tab_'+record.get('id')).record = record;
} else {
var service = Ext.create('Rambox.model.Service', {
type: 'custom'
,logo: formValues.logo
,name: formValues.serviceName
,url: formValues.url
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,trust: formValues.trust
,js_unread: formValues.js_unread
});
service.save();
Ext.getStore('Services').add(service);
var tabData = {
xtype: 'webview'
,id: 'tab_'+service.get('id')
,title: service.get('name')
,icon: service.get('logo') === '' ? 'resources/icons/custom.png' : service.get('logo')
,src: service.get('url')
,type: service.get('type')
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
,record: service
,tabConfig: {
service: service
}
};
if ( formValues.align === 'left' ) {
var tbfill = me.getView().getTabBar().down('tbfill');
me.getView().insert(me.getView().getTabBar().items.indexOf(tbfill), tabData).show();
} else {
me.getView().add(tabData).show();
}
}
win.close();
}
}
]
}).show();
// Make focus to the name field
win.down('textfield[name="serviceName"]').focus(true, 100);
Ext.create('Rambox.view.add.Add', {
record: rec
,service: Ext.getStore('ServicesList').getById(rec.get('type'))
,edit: true
});
}
,onSearchRender: function( field ) {
@ -988,4 +376,8 @@ Ext.define('Rambox.view.main.MainController', {
logoutFn();
}
}
,showDonate: function( btn ) {
Tooltip.API.show('zxzKWZfcmgRtHXgth');
}
});

14
app/view/preferences/Preferences.js

@ -59,7 +59,7 @@ Ext.define('Rambox.view.preferences.Preferences',{
,name: 'hide_menu_bar'
,boxLabel: 'Auto-hide Menu bar (<code>Alt</code> key to display)'
,value: config.hide_menu_bar
,hidden: Ext.os.is.MacOS
,hidden: process.platform !== 'win32'
}
,{
xtype: 'checkbox'
@ -67,7 +67,7 @@ Ext.define('Rambox.view.preferences.Preferences',{
,boxLabel: 'Show in Taskbar'
,value: config.skip_taskbar
,reference: 'skipTaskbar'
,hidden: Ext.os.is.MacOS
,hidden: process.platform !== 'win32'
}
,{
xtype: 'checkbox'
@ -75,7 +75,7 @@ Ext.define('Rambox.view.preferences.Preferences',{
,boxLabel: 'Keep Rambox in the Taskbar when close it'
,value: config.keep_in_taskbar_on_close
,bind: { disabled: '{!skipTaskbar.checked}' }
,hidden: Ext.os.is.MacOS
,hidden: process.platform !== 'win32'
}
,{
xtype: 'checkbox'
@ -88,7 +88,13 @@ Ext.define('Rambox.view.preferences.Preferences',{
,name: 'systemtray_indicator'
,boxLabel: 'Show System Tray indicator on unread messages'
,value: config.systemtray_indicator
,hidden: Ext.os.is.MacOS
,hidden: process.platform === 'darwin'
}
,{
xtype: 'checkbox'
,name: 'disable_gpu'
,boxLabel: 'Disable Hardware Acceleration (needs to relaunch)'
,value: config.disable_gpu
}
,{
xtype: 'fieldset'

5
appveyor.yml

@ -1,4 +1,4 @@
version: 0.4.2
version: 0.4.4
pull_requests:
do_not_increment_build_number: true
branches:
@ -33,12 +33,13 @@ build_script:
npm --version
node_modules/.bin/build --win --x64
node_modules/.bin/build --win --ia32 --x64
test: off
artifacts:
- path: dist\win\*.exe
- path: dist\win\*.nupkg
- path: dist\win\RELEASES
- path: dist\win-ia32\*.exe
- path: dist\*.zip
deploy:
- provider: GitHub

32
electron/main.js

@ -24,10 +24,12 @@ const config = new Config({
,hide_menu_bar: false
,skip_taskbar: true
,auto_launch: !isDev
,keep_in_taskbar_on_close: getDefaultValueForkeep_in_taskbar_on_close()
// On Linux false because it's uncommon for apps on linux to stay in the taskbar on close
,keep_in_taskbar_on_close: process.platform !== 'linux'
,start_minimized: false
,systemtray_indicator: true
,master_password: false
,disable_gpu: process.platform === 'linux'
,proxy: false
,proxyHost: ''
,proxyPort: ''
@ -40,15 +42,6 @@ const config = new Config({
}
});
/**
* Returns the default value for "keep_in_taskbar_on_close".
* On all platforms except linux: true
* On linux: false (because it's uncommon for apps on linux to stay in the taskbar on close)
*/
function getDefaultValueForkeep_in_taskbar_on_close() {
return process.platform !== 'linux';
}
// Configure AutoLaunch
const appLauncher = new AutoLaunch({
name: 'Rambox'
@ -232,6 +225,9 @@ function createMasterPasswordWindow() {
backgroundColor: '#0675A0'
,frame: false
});
// Open the DevTools.
if ( isDev ) mainMasterPasswordWindow.webContents.openDevTools();
mainMasterPasswordWindow.loadURL('file://' + __dirname + '/../masterpassword.html');
mainMasterPasswordWindow.on('close', function() { mainMasterPasswordWindow = null });
}
@ -319,10 +315,10 @@ app.on('certificate-error', function(event, webContents, url, error, certificate
} else {
callback(false);
dialog.showMessageBox(mainWindow, {
title: 'Certification Error'
title: 'Certification Warning'
,message: 'The service with the following URL has an invalid authority certification.\n\n'+url+'\n\nIf is a Custom Service, you have to remove it and add it again, enabling the "Trust invalid authority certificates" in the Options.'
,buttons: ['OK']
,type: 'error'
,type: 'warning'
}, function() {
});
@ -394,6 +390,12 @@ ipcMain.on('image:popup', function(event, url, partition) {
// Proxy
if ( config.get('proxy') ) app.commandLine.appendSwitch('proxy-server', config.get('proxyHost')+':'+config.get('proxyPort'));
// Disable GPU Acceleration for Linux
// to prevent White Page bug
// https://github.com/electron/electron/issues/6139
// https://github.com/saenzramiro/rambox/issues/181
if ( config.get('disable_gpu') ) app.disableHardwareAcceleration();
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
@ -409,12 +411,14 @@ app.on('window-all-closed', function () {
}
});
// Only macOS: On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null && mainMasterPasswordWindow === null ) {
config.get('master_password') ? createMasterPasswordWindow() : createWindow();
}
if ( mainWindow !== null ) mainWindow.show();
});
app.on('before-quit', function () {

30
electron/menu.js

@ -67,6 +67,29 @@ const helpSubmenu = [
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'
},
@ -121,6 +144,13 @@ let tpl = [
if (focusedWindow) focusedWindow.reload();
}
},
{
label: 'Reload current Service',
accelerator: 'CmdOrCtrl+Shift+R',
click() {
sendAction('reloadCurrentService');
}
},
{
type: 'separator'
},

2
electron/tray.js

@ -51,7 +51,7 @@ exports.create = function(win, config) {
appIcon.setToolTip('Rambox');
appIcon.setContextMenu(contextMenu);
appIcon.on('double-click', () => {
win.isVisible() && config.get('maximized') ? win.maximize() : win.show();
if ( !win.isVisible() || win.isMinimized() ) config.get('maximized') ? win.maximize() : win.show();
});
};

10
index.html

@ -21,6 +21,14 @@
<!--- Tooltip player -->
</head>
<body>
<div id="spinner" class='uil-ring-css' style='transform:scale(1);'><div></div></div>
<div id="spinner" class="component" data-path-start="M280,466c0,0.13-0.001,0.26-0.003,0.39c-0.002,0.134-0.004,0.266-0.007,0.396
C279.572,482.992,266.307,496,250,496h-2.125H51.625H50c-16.316,0-29.592-13.029-29.99-29.249c-0.003-0.13-0.006-0.261-0.007-0.393
C20.001,466.239,20,466.119,20,466l0,0c0-0.141,0.001-0.281,0.003-0.422C20.228,449.206,33.573,436,50,436h1.625h196.25H250
c16.438,0,29.787,13.222,29.997,29.608C279.999,465.738,280,465.869,280,466L280,466z" data-path-listen="M181,466c0,0.13-0.001,0.26-0.003,0.39c-0.002,0.134-0.004,0.266-0.007,0.396
C180.572,482.992,167.307,496,151,496h-2.125h2.75H150c-16.316,0-29.592-13.029-29.99-29.249c-0.003-0.13-0.006-0.261-0.007-0.393
C120.001,466.239,120,466.119,120,466l0,0c0-0.141,0.001-0.281,0.003-0.422C120.228,449.206,133.573,436,150,436h1.625h-2.75H151
c16.438,0,29.787,13.222,29.997,29.608C180.999,465.738,181,465.869,181,466L181,466z" data-path-player="M290,40c0,0.13-0.001,380.26-0.003,380.39c-0.002,0.134,0.006,24.479,0.003,24.609 c0,3.095-2.562,5.001-5,5.001h-27.125H41.625H15c-1.875,0-5-1.25-5-5.001c-0.003-0.13,0.004-24.509,0.003-24.641 C10.001,420.239,10,40.119,10,40l0,0c0-0.141-0.002-24.859,0-25c0,0,0-5,5-5h26.625h216.25H285c2.438,0,5,1.906,5,5 C290.002,15.13,290,39.869,290,40L290,40z">
<div class="button button--start uil-ring-css" style="transform:scale(1);"><div></div></div>
</div>
</body>
</html>

23
masterpassword.html

@ -9,19 +9,22 @@
<body>
<div style="background-image: url(resources/Icon.png);background-size:200px;width:200px;height:200px;position:relative;left:50%;margin-left:-100px;margin-top:100px;"></div>
<div style="color:#FFF;text-align:center;font-size:20px;font-family:Verdana;margin:30px 0;">Master Password</div>
<div style="text-align:center;margin:30px 0;"><input type="password" autofocus placeholder="Enter your password..." onkeyup="doValidate(this.value)" style="text-align:center;font-size:20px;font-family:Verdana;padding:10px;" /></div>
<div style="text-align:center;margin:30px 0;"><input type="password" autofocus placeholder="Enter your password..." onkeyup="doValidate(event, this.value)" style="text-align:center;font-size:20px;font-family:Verdana;padding:10px;border: 0;" /><button onclick="onButtonClick()" style="height:44px;border:0;width:44px;position:relative;top:2px;font-size:30px;background-color:#053767;color:white;">&raquo;</button></div>
<div style="text-align:center;margin-top:60px;"><a href="#" onclick="exit()" style="text-decoration:none;color:#4e9dbb;font-family:Arial;">Exit Rambox</a></div>
<script>
var to;
function doValidate(value) {
clearTimeout(to);
to = setTimeout(function() {
const {ipcRenderer} = require('electron');
if ( ipcRenderer.sendSync('validateMasterPassword', value) ) {
//require('electron').remote.
} else {
function doValidate(e, value) {
if (e.keyCode == 13) {
const { ipcRenderer } = require('electron');
if ( !ipcRenderer.sendSync('validateMasterPassword', value) ) {
alert('The password is incorrect. Try again...');
}
}, 3000);
}
}
function onButtonClick() {
return doValidate({ keyCode: 13 }, document.getElementsByTagName('input')[0].value);
}
function exit() {
require('electron').remote.app.quit();
}
</script>
</body>

2
package.json

@ -95,7 +95,7 @@
"asar": "^0.12.1",
"bestzip": "^1.1.3",
"electron-builder": "6.5.2",
"electron-prebuilt": "1.3.5",
"electron-prebuilt": "1.4.1",
"electron-squirrel-startup": "^1.0.0"
},
"dependencies": {

BIN
packages/local/rambox-default-theme/resources/fonts/icomoon/icomoon.eot

Binary file not shown.

21
packages/local/rambox-default-theme/resources/fonts/icomoon/icomoon.svg

@ -0,0 +1,21 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="icomoon" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xea83;" glyph-name="mail" d="M853.31 960h-682.62c-93.88 0-170.69-76.784-170.69-170.658v-682.656c0-93.876 76.81-170.686 170.69-170.686h682.622c93.938 0 170.688 76.81 170.688 170.686v682.656c0 93.874-76.75 170.658-170.69 170.658zM256 704h512c9.138 0 18.004-1.962 26.144-5.662l-282.144-329.168-282.144 329.17c8.14 3.696 17.006 5.66 26.144 5.66zM192 256v384c0 1.34 0.056 2.672 0.14 4l187.664-218.94-185.598-185.6c-1.444 5.338-2.206 10.886-2.206 16.54zM768 192h-512c-5.654 0-11.202 0.762-16.54 2.206l182.118 182.118 90.422-105.496 90.424 105.494 182.116-182.118c-5.34-1.442-10.886-2.204-16.54-2.204zM832 256c0-5.654-0.762-11.2-2.206-16.54l-185.598 185.598 187.664 218.942c0.084-1.328 0.14-2.66 0.14-4v-384z" />
<glyph unicode="&#xea8e;" glyph-name="hangouts" d="M511.8 960c-244.2 0-442.2-198-442.2-442.2 0-231.4 210.8-419 442.2-419v-162.8c268.6 136.2 442.6 355.6 442.6 581.8 0 244.2-198.4 442.2-442.6 442.2zM448 448c0-53-28.6-96-64-96v96h-128v192h192v-192zM768 448c0-53-28.6-96-64-96v96h-128v192h192v-192z" />
<glyph unicode="&#xea91;" glyph-name="facebook2" d="M928 960h-832c-52.8 0-96-43.2-96-96v-832c0-52.8 43.2-96 96-96h416v448h-128v128h128v64c0 105.8 86.2 192 192 192h128v-128h-128c-35.2 0-64-28.8-64-64v-64h192l-32-128h-160v-448h288c52.8 0 96 43.2 96 96v832c0 52.8-43.2 96-96 96z" />
<glyph unicode="&#xea93;" glyph-name="whatsapp" d="M873 811.2c-95.8 96-223.2 148.8-359 148.8-279.6 0-507.2-227.6-507.2-507.4 0-89.4 23.4-176.8 67.8-253.6l-72-263 269 70.6c74.2-40.4 157.6-61.8 242.4-61.8h0.2c0 0 0 0 0 0 279.6 0 507.4 227.6 507.4 507.4 0 135.6-52.8 263-148.6 359zM514.2 30.4v0c-75.8 0-150 20.4-214.8 58.8l-15.4 9.2-159.6-41.8 42.6 155.6-10 16c-42.4 67-64.6 144.6-64.6 224.4 0 232.6 189.2 421.8 422 421.8 112.6 0 218.6-44 298.2-123.6 79.6-79.8 123.4-185.6 123.4-298.4-0.2-232.8-189.4-422-421.8-422zM745.4 346.4c-12.6 6.4-75 37-86.6 41.2s-20 6.4-28.6-6.4c-8.4-12.6-32.8-41.2-40.2-49.8-7.4-8.4-14.8-9.6-27.4-3.2s-53.6 19.8-102 63c-37.6 33.6-63.2 75.2-70.6 87.8s-0.8 19.6 5.6 25.8c5.8 5.6 12.6 14.8 19 22.2s8.4 12.6 12.6 21.2c4.2 8.4 2.2 15.8-1 22.2s-28.6 68.8-39 94.2c-10.2 24.8-20.8 21.4-28.6 21.8-7.4 0.4-15.8 0.4-24.2 0.4s-22.2-3.2-33.8-15.8c-11.6-12.6-44.4-43.4-44.4-105.8s45.4-122.6 51.8-131.2c6.4-8.4 89.4-136.6 216.6-191.4 30.2-13 53.8-20.8 72.2-26.8 30.4-9.6 58-8.2 79.8-5 24.4 3.6 75 30.6 85.6 60.2s10.6 55 7.4 60.2c-3 5.6-11.4 8.8-24.2 15.2z" />
<glyph unicode="&#xea95;" glyph-name="telegram" d="M512 960c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM763.6 609l-84-395.8c-5.8-28.2-22.8-34.8-46.4-21.8l-128 94.6-61.4-59.8c-7.2-7-12.8-12.8-25.6-12.8-16.6 0-13.8 6.2-19.4 22l-43.6 143.2-126.6 39.4c-27.4 8.4-27.6 27.2 6.2 40.6l493.2 190.4c22.4 10.2 44.2-5.4 35.6-40z" />
<glyph unicode="&#xea96;" glyph-name="twitter" d="M1024 733.6c-37.6-16.8-78.2-28-120.6-33 43.4 26 76.6 67.2 92.4 116.2-40.6-24-85.6-41.6-133.4-51-38.4 40.8-93 66.2-153.4 66.2-116 0-210-94-210-210 0-16.4 1.8-32.4 5.4-47.8-174.6 8.8-329.4 92.4-433 219.6-18-31-28.4-67.2-28.4-105.6 0-72.8 37-137.2 93.4-174.8-34.4 1-66.8 10.6-95.2 26.2 0-0.8 0-1.8 0-2.6 0-101.8 72.4-186.8 168.6-206-17.6-4.8-36.2-7.4-55.4-7.4-13.6 0-26.6 1.4-39.6 3.8 26.8-83.4 104.4-144.2 196.2-146-72-56.4-162.4-90-261-90-17 0-33.6 1-50.2 3 93.2-59.8 203.6-94.4 322.2-94.4 386.4 0 597.8 320.2 597.8 597.8 0 9.2-0.2 18.2-0.6 27.2 41 29.4 76.6 66.4 104.8 108.6z" />
<glyph unicode="&#xea98;" glyph-name="vk" d="M928 960h-832c-52.8 0-96-43.2-96-96v-832c0-52.8 43.2-96 96-96h832c52.8 0 96 43.2 96 96v832c0 52.8-43.2 96-96 96zM829.4 243.2l-93.6-1.4c0 0-20.2-4-46.6 14.2-35 24-68 86.6-93.8 78.4-26-8.2-25.2-64.4-25.2-64.4s0.2-12-5.8-18.4c-6.4-7-19.2-8.4-19.2-8.4h-41.8c0 0-92.4-5.6-173.8 79.2-88.8 92.4-167.2 275.8-167.2 275.8s-4.6 12 0.4 17.8c5.6 6.6 20.6 7 20.6 7l100.2 0.6c0 0 9.4-1.6 16.2-6.6 5.6-4 8.6-11.8 8.6-11.8s16.2-41 37.6-78c41.8-72.2 61.4-88 75.6-80.4 20.6 11.2 14.4 102.2 14.4 102.2s0.4 33-10.4 47.6c-8.4 11.4-24.2 14.8-31 15.6-5.6 0.8 3.6 13.8 15.6 19.8 18 8.8 49.8 9.4 87.4 9 29.2-0.2 37.8-2.2 49.2-4.8 34.6-8.4 22.8-40.6 22.8-117.8 0-24.8-4.4-59.6 13.4-71 7.6-5 26.4-0.8 73.4 79 22.2 37.8 39 82.2 39 82.2s3.6 8 9.2 11.4c5.8 3.4 13.6 2.4 13.6 2.4l105.4 0.6c0 0 31.6 3.8 36.8-10.6 5.4-15-11.8-50-54.8-107.4-70.6-94.2-78.6-85.4-19.8-139.8 56-52 67.6-77.4 69.6-80.6 22.8-38.4-26-41.4-26-41.4z" />
<glyph unicode="&#xea9f;" glyph-name="twitch" d="M96 960l-96-160v-736h256v-128h128l128 128h160l288 288v608h-864zM832 416l-160-160h-160l-128-128v128h-192v576h640v-416zM608 704h96v-256h-96v256zM416 704h96v-256h-96v256z" />
<glyph unicode="&#xeaad;" glyph-name="steam2" d="M303.922 123.99c27.144 0 53.786 13.136 69.972 37.416 25.734 38.602 15.302 90.754-23.298 116.488l-66.074 44.048c11.308 3.080 23.194 4.756 35.478 4.756 74.392 0 134.696-60.304 134.696-134.698s-60.306-134.698-134.698-134.698c-72.404 0-131.444 57.132-134.548 128.774l71.954-47.968c14.322-9.548 30.506-14.118 46.518-14.118zM853.34 960c93.876 0 170.66-76.812 170.66-170.688v-682.628c0-93.936-76.784-170.684-170.66-170.684h-682.652c-93.876 0-170.688 76.75-170.688 170.682v203.028l121.334-80.888c-11.652-63.174 6.938-130.83 55.798-179.69 78.904-78.904 206.83-78.904 285.736 0 48.468 48.466 67.15 115.43 56.076 178.166l249.056 222.988c46.248 6.638 90.816 27.744 126.394 63.322 87.476 87.476 87.476 229.306 0 316.784-87.48 87.478-229.308 87.478-316.786 0-35.578-35.578-56.684-80.146-63.322-126.392v0l-204.694-310.23c-31.848-1.632-63.378-10.764-91.726-27.392l-217.866 145.244v277.69c0 93.876 76.81 170.688 170.686 170.688h682.654zM896 672c0 88.366-71.634 160-160 160s-160-71.634-160-160 71.634-160 160-160 160 71.634 160 160zM640 672c0 53.020 42.98 96 96 96s96-42.98 96-96-42.98-96-96-96-96 42.98-96 96z" />
<glyph unicode="&#xeac5;" glyph-name="skype" d="M425.6 922.6c-1.6 1-3.4 1.8-5 2.6-1.8-0.4-3.4-0.6-5.2-1l10.2-1.6zM36.8 539c-0.4-1.8-0.6-3.6-0.8-5.2 1-1.6 1.6-3.2 2.6-4.8l-1.8 10zM986.8 357.4c0.4 1.8 0.6 3.6 1 5.4-1 1.6-1.6 3.2-2.6 4.8l1.6-10.2zM592-23c1.6-1 3.4-1.8 5-2.6 1.8 0.4 3.6 0.6 5.4 0.8l-10.4 1.8zM987.8 362.8c-0.4-1.8-0.6-3.6-1-5.4l-1.8 10.4c1-1.8 1.8-3.4 2.8-5 5.2 28.8 8 58.2 8 87.6 0 65.2-12.8 128.6-38 188.2-24.4 57.6-59.2 109.4-103.6 153.8s-96.2 79.2-153.6 103.6c-59.6 25.2-123 38-188.2 38-30.8 0-61.6-2.8-91.6-8.6 0 0-0.2 0-0.2 0 1.6-0.8 3.4-1.6 5-2.6l-10.2 1.6c1.8 0.4 3.4 0.6 5.2 1-41.2 21.8-87.4 33.6-134.2 33.6-76.4 0-148.4-29.8-202.4-83.8s-83.8-126-83.8-202.4c0-48.6 12.6-96.6 36-138.8 0.4 1.8 0.6 3.6 0.8 5.2l1.8-10.2c-1 1.6-1.8 3.2-2.6 4.8-4.8-27.4-7.2-55.4-7.2-83.4 0-65.2 12.8-128.6 38-188.2 24.4-57.6 59.2-109.2 103.6-153.6s96.2-79.2 153.8-103.6c59.6-25.2 123-38 188.2-38 28.4 0 56.8 2.6 84.6 7.6-1.6 1-3.2 1.8-5 2.6l10.4-1.8c-1.8-0.4-3.6-0.6-5.4-0.8 42.8-24.2 91.4-37.2 140.8-37.2 76.4 0 148.4 29.8 202.4 83.8s83.8 126 83.8 202.4c-0.2 48.6-12.8 96.6-36.4 139.2zM514.2 154.2c-171.8 0-248.6 84.4-248.6 147.8 0 32.4 24 55.2 57 55.2 73.6 0 54.4-105.6 191.6-105.6 70.2 0 109 38.2 109 77.2 0 23.4-11.6 49.4-57.8 60.8l-152.8 38.2c-123 30.8-145.4 97.4-145.4 160 0 129.8 122.2 178.6 237 178.6 105.8 0 230.4-58.4 230.4-136.4 0-33.4-29-52.8-62-52.8-62.8 0-51.2 86.8-177.6 86.8-62.8 0-97.4-28.4-97.4-69s49.6-53.6 92.6-63.4l113.2-25.2c123.8-27.6 155.2-100 155.2-168 0-105.4-81-184.2-244.4-184.2z" />
<glyph unicode="&#xeac7;" glyph-name="hackernews" d="M0 960v-1024h1024v1024h-1024zM544 376v-216h-64v216l-175 328h72.6l134.4-252 134.4 252h72.6l-175-328z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
packages/local/rambox-default-theme/resources/fonts/icomoon/icomoon.ttf

Binary file not shown.

BIN
packages/local/rambox-default-theme/resources/fonts/icomoon/icomoon.woff

Binary file not shown.

229
packages/local/rambox-default-theme/sass/etc/_loadscreen.scss

@ -0,0 +1,229 @@
/* Main component wrapper */
body {
overflow: hidden;
}
.component {
position: absolute;;
z-index: 1;
width: 200px;
height: 200px;
margin: -100px 0 0 -100px;
top: 50%;
left: 50%;
}
/* Actual buttons (laid over shapes) */
.button {
font-weight: bold;
position: absolute;
bottom: 4px;
top: 50%;
left: 50%;
width: 200px;
height: 200px;
margin: -100px 0 0 -100px;
padding: 0;
text-align: center;
color: #00a7e7;
border: none;
background: none;
-webkit-transition: opacity 0.3s;
transition: opacity 0.3s;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.button:hover,
.button:focus {
outline: none;
color: #048abd;
}
.button--listen {
pointer-events: none;
}
.button--close {
z-index: 10;
top: 0px;
right: 0px;
left: auto;
width: 40px;
height: 40px;
padding: 10px;
color: #fff;
}
.button--close:hover,
.button--close:focus {
color: #ddd;
}
.button--hidden {
pointer-events: none;
opacity: 0;
}
/* Inner content of the start/*/
.button__content {
position: absolute;
opacity: 0;
-webkit-transition: -webkit-transform 0.4s, opacity 0.4s;
transition: transform 0.4s, opacity 0.4s;
}
.button__content--listen {
font-size: 1.75em;
line-height: 64px;
bottom: 0;
left: 50%;
width: 60px;
height: 60px;
margin: 0 0 0 -30px;
border-radius: 50%;
-webkit-transform: translate3d(0, 25px, 0);
transform: translate3d(0, 25px, 0);
-webkit-transition-timing-function: cubic-bezier(0.8, 0, 0.2, 1);
transition-timing-function: cubic-bezier(0.8, 0, 0.2, 1);
}
.button__content--listen::before,
.button__content--listen::after {
content: '';
position: absolute;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
opacity: 0;
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 50%;
}
.button--animate .button__content--listen::before,
.button--animate .button__content--listen::after {
-webkit-animation: anim-ripple 1.2s ease-out infinite forwards;
animation: anim-ripple 1.2s ease-out infinite forwards;
}
.button--animate .button__content--listen::after {
-webkit-animation-delay: 0.6s;
animation-delay: 0.6s;
}
@-webkit-keyframes anim-ripple {
0% {
opacity: 0;
-webkit-transform: scale3d(3, 3, 1);
transform: scale3d(3, 3, 1);
}
50% {
opacity: 1;
}
100% {
opacity: 0;
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
@keyframes anim-ripple {
0% {
opacity: 0;
-webkit-transform: scale3d(3, 3, 1);
transform: scale3d(3, 3, 1);
}
50% {
opacity: 1;
}
100% {
opacity: 0;
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1);
}
}
.notes {
position: absolute;
z-index: -1;
bottom: 0;
left: 50%;
width: 200px;
height: 100px;
margin: 0 0 0 -100px;
}
.note {
font-size: 2.8em;
position: absolute;
left: 50%;
width: 1em;
margin: 0 0 0 -0.5em;
opacity: 0;
color: rgba(255, 255, 255, 0.75);
}
.note:nth-child(odd) {
color: rgba(0, 0, 0, 0.1);
}
.note:nth-child(4n) {
font-size: 2em;
}
.note:nth-child(6n) {
color: rgba(255, 255, 255, 0.3);
}
/* ICONS */
@font-face {
font-family: 'icomoon';
src:url('../resources/fonts/icomoon/icomoon.eot?4djz1y');
src:url('../resources/fonts/icomoon/icomoon.eot?4djz1y#iefix') format('embedded-opentype'),
url('../resources/fonts/icomoon/icomoon.ttf?4djz1y') format('truetype'),
url('../resources/fonts/icomoon/icomoon.woff?4djz1y') format('woff'),
url('../resources/fonts/icomoon/icomoon.svg?4djz1y#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
.icon {
font-family: 'icomoon';
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon--microphone:before {
content: "\ea95";
}
.icon--cross:before {
content: "\e90c";
}
.icon--note1:before {
content: "\ea83";
}
.icon--note2:before {
content: "\eaad";
}
.icon--note3:before {
content: "\eac5";
}
.icon--note4:before {
content: "\ea93";
}
.icon--note5:before {
content: "\ea95";
}
.icon--note6:before {
content: "\ea96";
}

1
packages/local/rambox-default-theme/sass/etc/all.scss

@ -1,6 +1,7 @@
@import url(../resources/fonts/font-awesome/css/font-awesome.min.css);
@import url(https://fonts.googleapis.com/css?family=Josefin+Sans:400,700,600);
@import url(https://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,700italic,700,500italic,500,400italic);
@import 'loadscreen';
$base-color: #2E658E;
$font-family: 'Roboto', sans-serif;

3
packages/local/rambox-default-theme/sass/src/grid/column/Action.scss

@ -0,0 +1,3 @@
.x-action-col-glyph {
color: lighten($base-color, 20%);
}

BIN
resources/icons/actor.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
resources/icons/crisp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
resources/icons/drift.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
resources/icons/fleep.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
resources/icons/flock.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
resources/icons/kaiwa.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
resources/icons/mmmelon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

BIN
resources/icons/movim.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
resources/icons/openmailbox.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
resources/icons/pushbullet.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
resources/icons/riot.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
resources/icons/smooch.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
resources/icons/socialcast.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
resources/icons/spark.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
resources/icons/typetalk.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
resources/installer/Icon.icns

Binary file not shown.

263
resources/js/loadscreen.js

@ -0,0 +1,263 @@
/*! modernizr 3.2.0 (Custom Build) | MIT *
* http://modernizr.com/download/?-csstransitions-prefixedcss !*/
!function(e,n,t){function r(e,n){return typeof e===n}function o(){var e,n,t,o,i,s,a;for(var f in C)if(C.hasOwnProperty(f)){if(e=[],n=C[f],n.name&&(e.push(n.name.toLowerCase()),n.options&&n.options.aliases&&n.options.aliases.length))for(t=0;t<n.options.aliases.length;t++)e.push(n.options.aliases[t].toLowerCase());for(o=r(n.fn,"function")?n.fn():n.fn,i=0;i<e.length;i++)s=e[i],a=s.split("."),1===a.length?Modernizr[a[0]]=o:(!Modernizr[a[0]]||Modernizr[a[0]]instanceof Boolean||(Modernizr[a[0]]=new Boolean(Modernizr[a[0]])),Modernizr[a[0]][a[1]]=o),g.push((o?"":"no-")+a.join("-"))}}function i(e){var n=_.className,t=Modernizr._config.classPrefix||"";if(w&&(n=n.baseVal),Modernizr._config.enableJSClass){var r=new RegExp("(^|\\s)"+t+"no-js(\\s|$)");n=n.replace(r,"$1"+t+"js$2")}Modernizr._config.enableClasses&&(n+=" "+t+e.join(" "+t),w?_.className.baseVal=n:_.className=n)}function s(e){return e.replace(/([A-Z])/g,function(e,n){return"-"+n.toLowerCase()}).replace(/^ms-/,"-ms-")}function a(e){return e.replace(/([a-z])-([a-z])/g,function(e,n,t){return n+t.toUpperCase()}).replace(/^-/,"")}function f(e,n){return!!~(""+e).indexOf(n)}function l(){return"function"!=typeof n.createElement?n.createElement(arguments[0]):w?n.createElementNS.call(n,"http://www.w3.org/2000/svg",arguments[0]):n.createElement.apply(n,arguments)}function u(e,n){return function(){return e.apply(n,arguments)}}function p(e,n,t){var o;for(var i in e)if(e[i]in n)return t===!1?e[i]:(o=n[e[i]],r(o,"function")?u(o,t||n):o);return!1}function d(){var e=n.body;return e||(e=l(w?"svg":"body"),e.fake=!0),e}function c(e,t,r,o){var i,s,a,f,u="modernizr",p=l("div"),c=d();if(parseInt(r,10))for(;r--;)a=l("div"),a.id=o?o[r]:u+(r+1),p.appendChild(a);return i=l("style"),i.type="text/css",i.id="s"+u,(c.fake?c:p).appendChild(i),c.appendChild(p),i.styleSheet?i.styleSheet.cssText=e:i.appendChild(n.createTextNode(e)),p.id=u,c.fake&&(c.style.background="",c.style.overflow="hidden",f=_.style.overflow,_.style.overflow="hidden",_.appendChild(c)),s=t(p,e),c.fake?(c.parentNode.removeChild(c),_.style.overflow=f,_.offsetHeight):p.parentNode.removeChild(p),!!s}function m(n,r){var o=n.length;if("CSS"in e&&"supports"in e.CSS){for(;o--;)if(e.CSS.supports(s(n[o]),r))return!0;return!1}if("CSSSupportsRule"in e){for(var i=[];o--;)i.push("("+s(n[o])+":"+r+")");return i=i.join(" or "),c("@supports ("+i+") { #modernizr { position: absolute; } }",function(e){return"absolute"==getComputedStyle(e,null).position})}return t}function v(e,n,o,i){function s(){p&&(delete N.style,delete N.modElem)}if(i=r(i,"undefined")?!1:i,!r(o,"undefined")){var u=m(e,o);if(!r(u,"undefined"))return u}for(var p,d,c,v,h,y=["modernizr","tspan"];!N.style;)p=!0,N.modElem=l(y.shift()),N.style=N.modElem.style;for(c=e.length,d=0;c>d;d++)if(v=e[d],h=N.style[v],f(v,"-")&&(v=a(v)),N.style[v]!==t){if(i||r(o,"undefined"))return s(),"pfx"==n?v:!0;try{N.style[v]=o}catch(g){}if(N.style[v]!=h)return s(),"pfx"==n?v:!0}return s(),!1}function h(e,n,t,o,i){var s=e.charAt(0).toUpperCase()+e.slice(1),a=(e+" "+b.join(s+" ")+s).split(" ");return r(n,"string")||r(n,"undefined")?v(a,n,o,i):(a=(e+" "+P.join(s+" ")+s).split(" "),p(a,n,t))}function y(e,n,r){return h(e,t,t,n,r)}var g=[],C=[],x={_version:"3.2.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,n){var t=this;setTimeout(function(){n(t[e])},0)},addTest:function(e,n,t){C.push({name:e,fn:n,options:t})},addAsyncTest:function(e){C.push({name:null,fn:e})}},Modernizr=function(){};Modernizr.prototype=x,Modernizr=new Modernizr;var _=n.documentElement,w="svg"===_.nodeName.toLowerCase(),S="Moz O ms Webkit",b=x._config.usePrefixes?S.split(" "):[];x._cssomPrefixes=b;var E=function(n){var r,o=prefixes.length,i=e.CSSRule;if("undefined"==typeof i)return t;if(!n)return!1;if(n=n.replace(/^@/,""),r=n.replace(/-/g,"_").toUpperCase()+"_RULE",r in i)return"@"+n;for(var s=0;o>s;s++){var a=prefixes[s],f=a.toUpperCase()+"_"+r;if(f in i)return"@-"+a.toLowerCase()+"-"+n}return!1};x.atRule=E;var P=x._config.usePrefixes?S.toLowerCase().split(" "):[];x._domPrefixes=P;var z={elem:l("modernizr")};Modernizr._q.push(function(){delete z.elem});var N={style:z.elem.style};Modernizr._q.unshift(function(){delete N.style}),x.testAllProps=h;var T=x.prefixed=function(e,n,t){return 0===e.indexOf("@")?E(e):(-1!=e.indexOf("-")&&(e=a(e)),n?h(e,n,t):h(e,"pfx"))};x.prefixedCSS=function(e){var n=T(e);return n&&s(n)};x.testAllProps=y,Modernizr.addTest("csstransitions",y("transition","all",!0)),o(),i(g),delete x.addTest,delete x.addAsyncTest;for(var j=0;j<Modernizr._q.length;j++)Modernizr._q[j]();e.Modernizr=Modernizr}(window,document);
/**
* main.js
* http://www.codrops.com
*
* Licensed under the MIT license.
* http://www.opensource.org/licenses/mit-license.php
*
* Copyright 2015, Codrops
* http://www.codrops.com
*/
;(function(window) {
'use strict';
/**
* some helper functions
*/
// from http://stackoverflow.com/a/25273333
var bezier = function(x1, y1, x2, y2, epsilon) {
var curveX = function(t){
var v = 1 - t;
return 3 * v * v * t * x1 + 3 * v * t * t * x2 + t * t * t;
};
var curveY = function(t){
var v = 1 - t;
return 3 * v * v * t * y1 + 3 * v * t * t * y2 + t * t * t;
};
var derivativeCurveX = function(t){
var v = 1 - t;
return 3 * (2 * (t - 1) * t + v * v) * x1 + 3 * (- t * t * t + 2 * v * t) * x2;
};
return function(t){
var x = t, t0, t1, t2, x2, d2, i;
// First try a few iterations of Newton's method -- normally very fast.
for (t2 = x, i = 0; i < 8; i++){
x2 = curveX(t2) - x;
if (Math.abs(x2) < epsilon) return curveY(t2);
d2 = derivativeCurveX(t2);
if (Math.abs(d2) < 1e-6) break;
t2 = t2 - x2 / d2;
}
t0 = 0, t1 = 1, t2 = x;
if (t2 < t0) return curveY(t0);
if (t2 > t1) return curveY(t1);
// Fallback to the bisection method for reliability.
while (t0 < t1){
x2 = curveX(t2);
if (Math.abs(x2 - x) < epsilon) return curveY(t2);
if (x > x2) t0 = t2;
else t1 = t2;
t2 = (t1 - t0) * .5 + t0;
}
// Failure
return curveY(t2);
};
},
getRandomNumber = function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
throttle = function(fn, delay) {
var allowSample = true;
return function(e) {
if (allowSample) {
allowSample = false;
setTimeout(function() { allowSample = true; }, delay);
fn(e);
}
};
},
// from https://davidwalsh.name/vendor-prefix
prefix = (function () {
var styles = window.getComputedStyle(document.documentElement, ''),
pre = (Array.prototype.slice.call(styles).join('').match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o']))[1],
dom = ('WebKit|Moz|MS|O').match(new RegExp('(' + pre + ')', 'i'))[1];
return {
dom: dom,
lowercase: pre,
css: '-' + pre + '-',
js: pre[0].toUpperCase() + pre.substr(1)
};
})();
var support = {transitions : Modernizr.csstransitions},
transEndEventNames = { 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd', 'msTransition': 'MSTransitionEnd', 'transition': 'transitionend' },
transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],
onEndTransition = function( el, callback, propTest ) {
var onEndCallbackFn = function( ev ) {
if( support.transitions ) {
if( ev.target != this || propTest && ev.propertyName !== propTest && ev.propertyName !== prefix.css + propTest ) return;
this.removeEventListener( transEndEventName, onEndCallbackFn );
}
if( callback && typeof callback === 'function' ) { callback.call(this); }
};
if( support.transitions ) {
el.addEventListener( transEndEventName, onEndCallbackFn );
}
else {
onEndCallbackFn();
}
},
// the main component element/wrapper
shzEl = document.querySelector('.component'),
// the initial button
shzCtrl = shzEl.querySelector('div.button--start'),
// total number of notes/symbols moving towards the listen button
totalNotes = 50,
// the notes elements
notes,
// the note´s speed factor relative to the distance from the note element to the button.
// if notesSpeedFactor = 1, then the speed equals the distance (in ms)
notesSpeedFactor = 4.5,
// window sizes
winsize = {width: window.innerWidth, height: window.innerHeight},
// button offset
shzCtrlOffset = shzCtrl.getBoundingClientRect(),
// button sizes
shzCtrlSize = {width: shzCtrl.offsetWidth, height: shzCtrl.offsetHeight},
// tells us if the listening animation is taking place
isListening = false,
// audio player element
playerEl = shzEl.querySelector('.player');
// close player control
//playerCloseCtrl = playerEl.querySelector('.button--close');
function init() {
// create the music notes elements - the musical symbols that will animate/move towards the listen button
createNotes();
// star animation
listen();
}
/**
* creates [totalNotes] note elements (the musical symbols that will animate/move towards the listen button)
*/
function createNotes() {
var notesEl = document.createElement('div'), notesElContent = '';
notesEl.className = 'notes';
for(var i = 0; i < totalNotes; ++i) {
// we have 6 different types of symbols (icon--note1, icon--note2 ... icon--note6)
var j = (i + 1) - 6 * Math.floor(i/6);
notesElContent += '<div class="note icon icon--note' + j + '"></div>';
}
notesEl.innerHTML = notesElContent;
shzEl.insertBefore(notesEl, shzEl.firstChild)
// reference to the notes elements
notes = [].slice.call(notesEl.querySelectorAll('.note'));
}
/**
* transform the initial button into a circle shaped one that "listens" to the current song..
*/
function listen() {
isListening = true;
showNotes();
}
/**
* stop the ripples and notes animations
*/
function stopListening() {
isListening = false;
// music notes animation stops...
hideNotes();
}
/**
* show the notes elements: first set a random position and then animate them towards the button
*/
function showNotes() {
notes.forEach(function(note) {
// first position the notes randomly on the page
positionNote(note);
// now, animate the notes torwards the button
animateNote(note);
});
}
/**
* fade out the notes elements
*/
function hideNotes() {
notes.forEach(function(note) {
note.style.opacity = 0;
});
}
/**
* positions a note/symbol randomly on the page. The area is restricted to be somewhere outside of the viewport.
* @param {Element Node} note - the note element
*/
function positionNote(note) {
// we want to position the notes randomly (translation and rotation) outside of the viewport
var x = getRandomNumber(-2*(shzCtrlOffset.left + shzCtrlSize.width/2), 2*(winsize.width - (shzCtrlOffset.left + shzCtrlSize.width/2))), y,
rotation = getRandomNumber(-30, 30);
if( x > -1*(shzCtrlOffset.top + shzCtrlSize.height/2) && x < shzCtrlOffset.top + shzCtrlSize.height/2 ) {
y = getRandomNumber(0,1) > 0 ? getRandomNumber(-2*(shzCtrlOffset.top + shzCtrlSize.height/2), -1*(shzCtrlOffset.top + shzCtrlSize.height/2)) : getRandomNumber(winsize.height - (shzCtrlOffset.top + shzCtrlSize.height/2), winsize.height + winsize.height - (shzCtrlOffset.top + shzCtrlSize.height/2));
}
else {
y = getRandomNumber(-2*(shzCtrlOffset.top + shzCtrlSize.height/2), winsize.height + winsize.height - (shzCtrlOffset.top + shzCtrlSize.height/2));
}
// first reset transition if any
note.style.WebkitTransition = note.style.transition = 'none';
// apply the random transforms
note.style.WebkitTransform = note.style.transform = 'translate3d(' + x + 'px,' + y + 'px,0) rotate3d(0,0,1,' + rotation + 'deg)';
// save the translation values for later
note.setAttribute('data-tx', Math.abs(x));
note.setAttribute('data-ty', Math.abs(y));
}
/**
* animates a note torwards the button. Once that's done, it repositions the note and animates it again until the component is no longer listening.
* @param {Element Node} note - the note element
*/
function animateNote(note) {
setTimeout(function() {
if(!isListening) return;
// the transition speed of each note will be proportional to the its distance to the button
// speed = notesSpeedFactor * distance
var noteSpeed = notesSpeedFactor * Math.sqrt(Math.pow(note.getAttribute('data-tx'),2) + Math.pow(note.getAttribute('data-ty'),2));
// apply the transition
note.style.WebkitTransition = '-webkit-transform ' + noteSpeed + 'ms ease, opacity 0.8s';
note.style.transition = 'transform ' + noteSpeed + 'ms ease-in, opacity 0.8s';
// now apply the transform (reset the transform so the note moves to its original position) and fade in the note
note.style.WebkitTransform = note.style.transform = 'translate3d(0,0,0)';
note.style.opacity = 1;
// after the animation is finished,
var onEndTransitionCallback = function() {
// reset transitions and styles
note.style.WebkitTransition = note.style.transition = 'none';
note.style.opacity = 0;
if(!isListening) return;
positionNote(note);
animateNote(note);
};
onEndTransition(note, onEndTransitionCallback, 'transform');
}, 60);
}
init();
})(window);
Loading…
Cancel
Save