diff --git a/app/model/Service.js b/app/model/Service.js
index ec4618a8..a7d4a703 100644
--- a/app/model/Service.js
+++ b/app/model/Service.js
@@ -5,14 +5,26 @@ Ext.define('Rambox.model.Service', {
,proxy: {
type: 'localstorage'
,id: 'services'
- }
-
+ }
+
,fields: [{
name: 'id'
,type: 'int'
+ },{
+ name: 'position'
+ ,type: 'int'
+ ,convert: function( value, record ) {
+ return value ? value : Ext.getStore('Services').getCount() + 1;
+ }
},{
name: 'type'
,type: 'string'
+ },{
+ name: 'logo'
+ ,type: 'string'
+ ,convert: function( value, record ) {
+ return value ? value : record.get('type') + '.png';
+ }
},{
name: 'name'
,type: 'string'
diff --git a/app/store/Services.js b/app/store/Services.js
index fc212e74..af26ecae 100644
--- a/app/store/Services.js
+++ b/app/store/Services.js
@@ -11,33 +11,44 @@ Ext.define('Rambox.store.Services', {
,autoLoad: true
,autoSync: true
+ ,sorters: [
+ {
+ property: 'position'
+ ,direction: 'ASC'
+ }
+ ]
+
,listeners: {
load: function( store, records, successful ) {
if ( Ext.isEmpty(records) ) {
Ext.get('spinner').destroy();
+ Ext.cq1('app-main').add({ tabConfig : { xtype : 'tbfill' } });
return;
}
var servicesLeft = [];
var servicesRight = [];
- Ext.each(records, function(service) {
+ store.each(function(service) {
var cfg = {
xtype: 'webview'
,id: 'tab_'+service.get('id')
,title: service.get('name')
- ,icon: 'resources/icons/'+service.get('type')+'.png'
+ ,icon: service.get('type') !== 'custom' ? 'resources/icons/'+service.get('logo') : service.get('logo')
,src: service.get('url')
,type: service.get('type')
,muted: service.get('muted')
+ ,tabConfig: {
+ service: service
+ }
};
service.get('align') === 'left' ? servicesLeft.push(cfg) : servicesRight.push(cfg);
});
Ext.cq1('app-main').add(servicesLeft);
+ Ext.cq1('app-main').add({ tabConfig : { xtype : 'tbfill' } });
if ( !Ext.isEmpty(servicesRight) ) {
- Ext.cq1('app-main').add({ tabConfig : { xtype : 'tbfill' } });
Ext.cq1('app-main').add(servicesRight);
}
}
diff --git a/app/ux/WebView.js b/app/ux/WebView.js
index a5ae2fd9..2f67a527 100644
--- a/app/ux/WebView.js
+++ b/app/ux/WebView.js
@@ -52,13 +52,20 @@ Ext.define('Rambox.ux.WebView',{
var me = this;
var webview = me.down('component').el.dom;
+ // Show and hide spinner when is loading
+ webview.addEventListener("did-start-loading", function() {
+ console.info('Start loading...', me.src);
+ me.mask('Loading...');
+ });
+ webview.addEventListener("did-stop-loading", function() {
+ me.unmask();
+ });
webview.addEventListener("did-finish-load", function(e) {
- console.info('finish load');
+ Rambox.app.setTotalServicesLoaded( Rambox.app.getTotalServicesLoaded() + 1 );
if ( Rambox.app.getTotalServicesLoaded() === Ext.getStore('Services').getCount() ) {
Ext.get('spinner').destroy();
}
- Rambox.app.setTotalServicesLoaded( Rambox.app.getTotalServicesLoaded() + 1 );
});
webview.addEventListener("dom-ready", function(e) {
diff --git a/app/view/main/Main.js b/app/view/main/Main.js
index d29fb56a..5d5dd976 100644
--- a/app/view/main/Main.js
+++ b/app/view/main/Main.js
@@ -17,14 +17,25 @@ Ext.define('Rambox.view.main.Main', {
,plugins: [
{
- ptype: 'tabreorderer'
+ ptype: 'tabreorderer'
+ ,listeners: {
+ // I put the code here because it cannot be listened into the Controller
+ Drop: function( box, tabBar, tab, startIdx, index ) {
+ var idx = 0;
+ Ext.each(tabBar.items.items, function(t) {
+ if ( idx > 0 && t.xtype !== 'tbfill' ) { // Skip first tab because is the configuration tab
+ console.log(t, idx);
+ t.service.set('position', idx);
+ } else if ( t.xtype === 'tbfill' ) {
+ idx--;
+ }
+ idx++;
+ });
+ }
+ }
}
]
- ,tabBar: {
- cls: 'allow-overflow'
- }
- ,hideMode: 'visibility'
,autoRender: true
,autoShow: true
,deferredRender: false
@@ -32,8 +43,9 @@ Ext.define('Rambox.view.main.Main', {
{
icon: 'resources/logo_32.png'
,closable: false
- ,layout: 'center'
+ ,reorderable: false
,autoScroll: true
+ ,layout: 'center'
,items: [
{
xtype: 'container'
@@ -50,9 +62,30 @@ Ext.define('Rambox.view.main.Main', {
xtype: 'templatecolumn'
,width: 50
,variableRowHeight: true
- ,tpl: ''
+ ,tpl: '
'
}
,{ text: 'Name', dataIndex: 'name', variableRowHeight: true, flex: 1 }
+ ,{
+ xtype: 'actioncolumn'
+ ,width: 60
+ ,align: 'right'
+ ,items: [
+ {
+ glyph: 0xf1f7
+ ,tooltip: 'Prevent notifications'
+ ,getClass: function( value, metaData, record, rowIndex, colIndex, store, view ){
+ if ( record.get('notifications') ) return 'x-hidden';
+ }
+ }
+ ,{
+ glyph: 0xf026
+ ,tooltip: 'Muted'
+ ,getClass: function( value, metaData, record, rowIndex, colIndex, store, view ){
+ if ( !record.get('muted') ) return 'x-hidden';
+ }
+ }
+ ]
+ }
,{
xtype: 'actioncolumn'
,width: 60
@@ -111,7 +144,8 @@ Ext.define('Rambox.view.main.Main', {
}
,{
type: 'plus'
- ,tooltip: 'Add a custom service (soon...)'
+ ,tooltip: 'Add a custom service'
+ ,handler: 'addCustomService'
}
]
,items: [
diff --git a/app/view/main/MainController.js b/app/view/main/MainController.js
index e7931e43..c1482b91 100644
--- a/app/view/main/MainController.js
+++ b/app/view/main/MainController.js
@@ -6,16 +6,17 @@ Ext.define('Rambox.view.main.MainController', {
,alias: 'controller.main'
- ,showSimpleModal: function(record) {
+ ,showSimpleModal: function(record, edit) {
var me = this;
var win = Ext.create('Ext.window.Window', {
- title: 'Add '+record.get('name')
+ 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'
@@ -25,6 +26,14 @@ Ext.define('Rambox.view.main.MainController', {
,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'
@@ -34,7 +43,7 @@ Ext.define('Rambox.view.main.MainController', {
{
xtype: 'checkbox'
,boxLabel: 'Separate'
- ,checked: false
+ ,checked: edit ? (record.get('align') === 'right' ? true : false) : false
,name: 'align'
,uncheckedValue: 'left'
,inputValue: 'right'
@@ -43,7 +52,7 @@ Ext.define('Rambox.view.main.MainController', {
xtype: 'checkbox'
,boxLabel: 'Show notifications'
,name: 'notifications'
- ,checked: true
+ ,checked: edit ? record.get('notifications') : true
,uncheckedValue: false
,inputValue: true
}
@@ -51,7 +60,7 @@ Ext.define('Rambox.view.main.MainController', {
xtype: 'checkbox'
,boxLabel: 'Mute all sounds'
,name: 'muted'
- ,checked: false
+ ,checked: edit ? record.get('muted') : false
,uncheckedValue: false
,inputValue: true
}
@@ -70,36 +79,61 @@ Ext.define('Rambox.view.main.MainController', {
}
,'->'
,{
- text: 'Add service'
+ text: edit ? 'Save' : 'Add service'
+ ,itemId: 'submit'
,handler: function() {
var formValues = win.down('form').getValues();
- var service = Ext.getStore('Services').add({
- type: record.get('id')
- ,name: formValues.serviceName
- ,url: record.get('url')
- ,align: formValues.align
- ,notifications: formValues.notifications
- ,muted: formValues.muted
- })[0];
+ if ( edit ) {
+ record.set({
+ name: formValues.serviceName
+ ,align: formValues.align
+ ,notifications: formValues.notifications
+ ,muted: formValues.muted
+ });
+ Ext.getCmp('tab_'+record.get('id')).setTitle(formValues.serviceName);
+ } else {
+ var service = Ext.create('Rambox.model.Service', {
+ type: record.get('id')
+ ,name: formValues.serviceName
+ ,url: record.get('url')
+ ,align: formValues.align
+ ,notifications: formValues.notifications
+ ,muted: formValues.muted
+ });
+ service.save();
- me.getView().add({
- xtype: 'webview'
- ,id: 'tab_'+service.get('id')
- ,title: service.get('name')
- ,icon: 'resources/icons/'+record.get('logo')
- ,src: service.get('url')
- ,type: service.get('type')
- ,align: formValues.align
- ,notifications: formValues.notifications
- ,muted: formValues.muted
- }).show();
+ var tabData = {
+ xtype: 'webview'
+ ,id: 'tab_'+service.get('id')
+ ,title: service.get('name')
+ ,icon: 'resources/icons/'+record.get('logo')
+ ,src: service.get('url')
+ ,type: service.get('type')
+ ,align: formValues.align
+ ,notifications: formValues.notifications
+ ,muted: formValues.muted
+ ,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) {
@@ -112,6 +146,7 @@ Ext.define('Rambox.view.main.MainController', {
,resizable: false
,draggable: false
,bodyPadding: 20
+ ,icon: 'resources/icons/' + record.get('logo')
,items: [
{
xtype: 'form'
@@ -121,6 +156,14 @@ Ext.define('Rambox.view.main.MainController', {
,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'
@@ -129,6 +172,14 @@ Ext.define('Rambox.view.main.MainController', {
xtype: 'textfield'
,fieldLabel: record.get('name') + ' team'
,name: 'url'
+ ,allowBlank: false
+ ,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 (/)
@@ -180,19 +231,21 @@ Ext.define('Rambox.view.main.MainController', {
,'->'
,{
text: 'Add service'
+ ,itemId: 'submit'
,handler: function() {
var formValues = win.down('form').getValues();
- var service = Ext.getStore('Services').add({
+ var service = Ext.create('Rambox.model.Service', {
type: record.get('id')
,name: formValues.serviceName
,url: record.get('url').replace('___', formValues.url)
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
- })[0];
+ });
+ service.save();
- me.getView().add({
+ var tabData = {
xtype: 'webview'
,id: 'tab_'+service.get('id')
,title: service.get('name')
@@ -202,20 +255,33 @@ Ext.define('Rambox.view.main.MainController', {
,align: formValues.align
,notifications: formValues.notifications
,muted: formValues.muted
- }).show();
+ ,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);
}
,onNewServiceSelect: function( view, record, item, index, e ) {
if ( record.get('url').indexOf('___') >= 0 ) {
this.showCustomModal(record);
} else {
- this.showSimpleModal(record);
+ this.showSimpleModal(record, false);
}
}
@@ -223,11 +289,16 @@ Ext.define('Rambox.view.main.MainController', {
Ext.Msg.confirm('Please confirm...', 'Are you sure you want to remove '+rec.get('name')+'?', function(btnId) {
if ( btnId === 'yes' ) {
gridView.getStore().remove(rec);
+ //webview.webContents.session.clearCache();
Ext.getCmp('tab_'+rec.get('id')).close();
}
});
}
+ ,configureService: function( gridView, rowIndex, colIndex, col, e, rec, rowEl ) {
+ this.showSimpleModal(rec, true);
+ }
+
,doFilter: function( cg, newValue, oldValue ) {
var values = Ext.cq1('checkboxgroup').getValue();
Ext.getStore('ServicesList').getFilters().replaceAll({
@@ -236,4 +307,151 @@ Ext.define('Rambox.view.main.MainController', {
}
});
}
+
+ ,addCustomService: function( event, toolEl, owner, tool ) {
+ var me = this;
+
+ var win = Ext.create('Ext.window.Window', {
+ title: 'Add Custom Service'
+ ,modal: true
+ ,width: 400
+ ,resizable: false
+ ,draggable: false
+ ,bodyPadding: 20
+ ,items: [
+ {
+ xtype: 'form'
+ ,items: [
+ {
+ xtype: 'textfield'
+ ,fieldLabel: '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: 'textfield'
+ ,fieldLabel: 'URL'
+ ,emptyText: 'http://service.url.com'
+ ,name: 'url'
+ ,vtype: 'url'
+ ,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'
+ ,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: 'Separate'
+ ,checked: false
+ ,name: 'align'
+ ,uncheckedValue: 'left'
+ ,inputValue: 'right'
+ }
+ ,{
+ xtype: 'checkbox'
+ ,boxLabel: 'Show notifications'
+ ,name: 'notifications'
+ ,checked: true
+ ,uncheckedValue: false
+ ,inputValue: true
+ }
+ ,{
+ xtype: 'checkbox'
+ ,boxLabel: 'Mute all sounds'
+ ,name: 'muted'
+ ,checked: false
+ ,uncheckedValue: false
+ ,inputValue: true
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ ,buttons: [
+ {
+ text: 'Cancel'
+ ,ui: 'decline'
+ ,handler: function() {
+ win.close();
+ }
+ }
+ ,'->'
+ ,{
+ text: 'Add service'
+ ,itemId: 'submit'
+ ,handler: function() {
+ var formValues = win.down('form').getValues();
+
+ 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
+ });
+ service.save();
+
+ var tabData = {
+ xtype: 'webview'
+ ,id: 'tab_'+service.get('id')
+ ,title: service.get('name')
+ ,icon: formValues.logo
+ ,src: service.get('url')
+ ,type: service.get('type')
+ ,align: formValues.align
+ ,notifications: formValues.notifications
+ ,muted: formValues.muted
+ ,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);
+ }
});
diff --git a/index.html b/index.html
index b649b85f..ce660ba0 100644
--- a/index.html
+++ b/index.html
@@ -13,6 +13,7 @@