Browse Source

Bugs fixed, new features and UI improvement

- Added tab reorderer functionality.
- Modify service.
- Add custom service.
- Fixed align right service (separate).
- Autofocus on service name when add a new one.
- Mask on loading webview.
- Fixed localStorage bug.
pull/3/head
saenzramiro 9 years ago
parent
commit
1047ee1c5d
  1. 14
      app/model/Service.js
  2. 17
      app/store/Services.js
  3. 11
      app/ux/WebView.js
  4. 50
      app/view/main/Main.js
  5. 278
      app/view/main/MainController.js
  6. 1
      index.html
  7. 96
      packages/local/rambox-default-theme/sass/etc/all.scss

14
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'

17
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);
}
}

11
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) {

50
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: '<img src="resources/icons/{type}.png" width="32" />'
,tpl: '<img src="{[ values.type !== \"custom\" ? \"resources/icons/\" : \"\" ]}{logo}" data-qtip="{type:capitalize}" width="32" />'
}
,{ 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: [

278
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);
}
});

1
index.html

@ -13,6 +13,7 @@
</head>
<body>
<div id="spinner">
<font>Rambox</font>
<div class="sk-folding-cube">
<div class="sk-cube1 sk-cube"></div>
<div class="sk-cube2 sk-cube"></div>

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

@ -15,15 +15,28 @@ body {
z-index: 999999;
position: absolute;
background-color: $base-color;
cursor: wait;
font {
font-family: 'Josefin Sans', sans-serif;
font-size: 150px;
top: 30%;
color: #FFF;
position: absolute;
width: 100%;
height: 120px;
line-height: 132px;
text-align: center;
}
}
.sk-folding-cube {
top: 50%;
margin: -20px auto 20px auto;
width: 80px;
height: 80px;
position: relative;
-webkit-transform: rotateZ(45deg);
transform: rotateZ(45deg);
top: 50%;
left: 50%;
width: 80px;
height: 80px;
margin-left: -40px;
position: absolute;
-webkit-transform: rotateZ(45deg);
transform: rotateZ(45deg);
}
.sk-folding-cube .sk-cube {
@ -107,57 +120,57 @@ body {
// Badge Plugin for Tabs
.x-badge {
position: relative;
overflow: visible;
position: relative;
overflow: visible;
}
.x-badge[data-badge-text]:after {
content: attr(data-badge-text);
position: absolute;
font-size: 10px;
top: -6px;
right: 2px;
width: auto;
font-weight: bold;
color: white;
text-shadow: rgba(0, 0, 0, 0.5) 0 -0.08em 0;
-webkit-border-radius: 3px;
border-radius: 3px;
padding: 0 4px;
background-image: none;
background-color: #C00;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ff1a1a), color-stop(3%, #e60000), color-stop(100%, #b30000));
background-image: -webkit-linear-gradient(top, #ff1a1a,#e60000 3%,#b30000);
background-image: linear-gradient(top, #ff1a1a,#e60000 3%,#b30000);
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 0.1em 0.1em;
box-shadow: rgba(0, 0, 0, 0.3) 0 0.1em 0.1em;
content: attr(data-badge-text);
position: absolute;
font-size: 10px;
top: 0px;
right: 2px;
width: auto;
font-weight: bold;
color: white;
text-shadow: rgba(0, 0, 0, 0.5) 0 -0.08em 0;
-webkit-border-radius: 3px;
border-radius: 3px;
padding: 0 4px;
background-image: none;
background-color: #C00;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ff1a1a), color-stop(3%, #e60000), color-stop(100%, #b30000));
background-image: -webkit-linear-gradient(top, #ff1a1a,#e60000 3%,#b30000);
background-image: linear-gradient(top, #ff1a1a,#e60000 3%,#b30000);
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 0.1em 0.1em;
box-shadow: rgba(0, 0, 0, 0.3) 0 0.1em 0.1em;
}
.x-badge.green-badge[data-badge-text]:after {
background-color: #0C0;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #1AFF1A), color-stop(3%, #00E600), color-stop(100%, #00B300));
background-image: -webkit-linear-gradient(top, #1AFF1A,#00E600 3%,#00B300);
background-image: linear-gradient(top, #1AFF1A,#00E600 3%,#00B300);
background-color: #0C0;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #1AFF1A), color-stop(3%, #00E600), color-stop(100%, #00B300));
background-image: -webkit-linear-gradient(top, #1AFF1A,#00E600 3%,#00B300);
background-image: linear-gradient(top, #1AFF1A,#00E600 3%,#00B300);
}
.x-badge.blue-badge[data-badge-text]:after {
background-color: #00C;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #1A1AFF), color-stop(3%, #0000E6), color-stop(100%, #0000B3));
background-image: -webkit-linear-gradient(top, #1A1AFF,#0000E6 3%,#0000B3);
background-image: linear-gradient(top, #1A1AFF,#0000E6 3%,#0000B3);
background-color: #00C;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #1A1AFF), color-stop(3%, #0000E6), color-stop(100%, #0000B3));
background-image: -webkit-linear-gradient(top, #1A1AFF,#0000E6 3%,#0000B3);
background-image: linear-gradient(top, #1A1AFF,#0000E6 3%,#0000B3);
}
/* Additional classes needed for tab panels */
.allow-overflow .x-box-layout-ct, .allow-overflow .x-box-inner, .allow-overflow .x-box-item {
overflow: visible;
overflow: visible;
}
.x-tab-closable.x-badge[data-badge-text]:after {
right: 16px;
right: 16px;
}
// Allow Glyphs in Action Columns
.x-action-col-glyph {font-size:20px; line-height:20px; color:#000; width:20px; margin: 0 5px;}
.x-action-col-glyph {font-size:16px; line-height:16px; color:#CFCFCF; width:16px; margin: 0 5px;}
.x-action-col-glyph:hover{color:$base-color}
.x-grid-item-over .x-hidden-display, .x-grid-item-selected .x-hidden-display{display:inline-block !important}
.x-grid-cell-inner {
@ -168,6 +181,11 @@ body {
}
}
.x-tab-icon-el-default { background-size: 24px; }
.x-title-icon { background-size: 16px; }
// Fix for scroller tab bar
.x-box-scroller-body-horizontal { width: auto !important; margin-right: 18px;}
.x-box-scroller-tab-bar { z-index: 9999; }
.service {
width:250px;

Loading…
Cancel
Save