diff --git a/app/model/Service.js b/app/model/Service.js index a7d4a703..ad5db198 100644 --- a/app/model/Service.js +++ b/app/model/Service.js @@ -43,5 +43,9 @@ Ext.define('Rambox.model.Service', { name: 'muted' ,type: 'boolean' ,defaultValue: false + },{ + name: 'js_unread' + ,type: 'string' + ,defaultValue: '' }] }); diff --git a/app/model/ServiceList.js b/app/model/ServiceList.js index a53a5d93..ce1efdd5 100644 --- a/app/model/ServiceList.js +++ b/app/model/ServiceList.js @@ -16,5 +16,9 @@ Ext.define('Rambox.model.ServiceList', { },{ name: 'type' ,type: 'string' + },{ + name: 'js_unread' + ,type: 'string' + ,defaultValue: '' }] }); diff --git a/app/store/Services.js b/app/store/Services.js index af26ecae..9d1f1972 100644 --- a/app/store/Services.js +++ b/app/store/Services.js @@ -37,6 +37,7 @@ Ext.define('Rambox.store.Services', { ,src: service.get('url') ,type: service.get('type') ,muted: service.get('muted') + ,record: service ,tabConfig: { service: service } diff --git a/app/store/ServicesList.js b/app/store/ServicesList.js index 9b5b52e9..dfddd0f7 100644 --- a/app/store/ServicesList.js +++ b/app/store/ServicesList.js @@ -29,6 +29,7 @@ Ext.define('Rambox.store.ServicesList', { ,name: 'Slack' ,url: 'https://___.slack.com/' ,type: 'messaging' + ,js_unread: 'function checkUnread(){var e=document.getElementsByClassName("unread_highlight"),t=0;for(i=0;i=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);' }, { id: 'noysi' @@ -57,6 +58,7 @@ Ext.define('Rambox.store.ServicesList', { ,name: 'Hangouts' ,url: 'https://hangouts.google.com/' ,type: 'messaging' + ,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);' }, { id: 'hipchat' @@ -92,6 +94,7 @@ Ext.define('Rambox.store.ServicesList', { ,name: 'Inbox' ,url: 'http://inbox.google.com/?cid=imp' ,type: 'email' + ,js_unread: 'function checkUnread(){updateBadge(document.getElementsByClassName("qG").length)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);' }, { id: 'chatwork' diff --git a/app/ux/WebView.js b/app/ux/WebView.js index 8287550c..5a568cc3 100644 --- a/app/ux/WebView.js +++ b/app/ux/WebView.js @@ -74,7 +74,7 @@ Ext.define('Rambox.ux.WebView',{ webview.addEventListener("did-finish-load", function(e) { Rambox.app.setTotalServicesLoaded( Rambox.app.getTotalServicesLoaded() + 1 ); - if ( Rambox.app.getTotalServicesLoaded() === Ext.getStore('Services').getCount() ) { + if ( Rambox.app.getTotalServicesLoaded() === Ext.getStore('Services').getCount() && Ext.get('spinner') !== null ) { Ext.get('spinner').destroy(); } }); @@ -89,20 +89,17 @@ Ext.define('Rambox.ux.WebView',{ }); // Injected code to detect new messages - switch ( me.type ) { - case 'inbox': - webview.executeJavaScript('function checkUnread(){updateBadge(document.getElementsByClassName("qG").length)}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);'); - break; - case 'hangouts': - webview.executeJavaScript('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);'); - break; - default: - break; + if ( me.record && me.record.get('js_unread') !== '' ) { + console.info('JS Injected', me.src); + console.log(me.record.get('js_unread')); + webview.executeJavaScript(me.record.get('js_unread')); } + + // Scroll always to top (bug) + webview.executeJavaScript('document.body.scrollTop=0;'); }); webview.addEventListener("page-title-updated", function(e) { - var ipc = require('electron').ipcRenderer; var count = e.title.match(/\((\d+)\)/); count = count ? parseInt(count[1]) : 0; @@ -125,15 +122,6 @@ Ext.define('Rambox.ux.WebView',{ } if ( e.title === 'Google Hangouts' ) me.notifications = 0; break; - case 'slack': - if ( e.title.indexOf('! ') >= 0 ) { - me.tab.setBadgeText(1); - me.notifications = 1; - } else { - me.tab.setBadgeText(0); - me.notifications = 0; - } - break; default: me.tab.setBadgeText(count); me.notifications = count; diff --git a/app/view/main/Main.js b/app/view/main/Main.js index c70249b9..f1f7c686 100644 --- a/app/view/main/Main.js +++ b/app/view/main/Main.js @@ -45,145 +45,168 @@ Ext.define('Rambox.view.main.Main', { ,closable: false ,reorderable: false ,autoScroll: true - ,layout: 'center' + ,layout: 'hbox' ,items: [ { - xtype: 'container' - ,items: [ + xtype: 'panel' + ,title: 'Add a new Service' + ,margin: '0 5 0 0' + ,flex: 1 + ,header: { height: 50 } + ,tools: [ { - xtype: 'grid' - ,title: 'Enabled Services' - ,store: 'Services' - ,margin: '50 0 0 0' - ,hideHeaders: true - ,width: 500 - ,columns: [ + xtype: 'checkboxgroup' + ,items: [ { - xtype: 'templatecolumn' - ,width: 50 - ,variableRowHeight: true - ,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: 'checkbox' + ,boxLabel: 'Messaging' + ,name: 'messaging' + ,checked: true + ,uncheckedValue: false + ,inputValue: true } ,{ - xtype: 'actioncolumn' - ,width: 60 - ,align: 'center' - ,items: [ - { - glyph: 0xf1f8 - ,tooltip: 'Remove' - ,handler: 'removeService' - ,getClass: function(){ return 'x-hidden-display'; } - } - ,{ - glyph: 0xf013 - ,tooltip: 'Configure' - ,handler: 'configureService' - ,getClass: function(){ return 'x-hidden-display'; } - } - ] + xtype: 'checkbox' + ,boxLabel: 'Email' + ,margin: '0 10 0 10' + ,name: 'email' + ,checked: true + ,uncheckedValue: false + ,inputValue: true } ] - ,viewConfig: { - emptyText: 'No services added...' - ,forceFit: true + ,listeners: { + change: 'doTypeFilter' } } ,{ - xtype: 'panel' - ,title: 'Add a new Service' - ,width: 500 - ,margin: '50 0 0 0' - ,tools: [ - { - xtype: 'checkboxgroup' - ,items: [ - { - xtype: 'checkbox' - ,boxLabel: 'Messaging' - ,name: 'messaging' - ,checked: true - ,uncheckedValue: false - ,inputValue: true - } - ,{ - xtype: 'checkbox' - ,boxLabel: 'Email' - ,margin: '0 10 0 10' - ,name: 'email' - ,checked: true - ,uncheckedValue: false - ,inputValue: true - } - ] - ,listeners: { - change: 'doFilter' - } + xtype: 'textfield' + ,grow: true + ,growMin: 120 + ,growMax: 170 + ,triggers: { + clear: { + weight: 0 + ,cls: Ext.baseCSSPrefix + 'form-clear-trigger' + ,hidden: true + ,handler: 'onClearClick' } - ,{ - type: 'plus' - ,tooltip: 'Add a custom service' - ,handler: 'addCustomService' + ,search: { + weight: 1 + ,cls: Ext.baseCSSPrefix + 'form-search-trigger search-trigger' } + } + ,listeners: { + change: 'onSearchServiceChange' + ,afterrender: 'onSearchRender' + ,specialkey: 'onSearchEnter' + } + } + ,{ + type: 'plus' + ,tooltip: 'Add a custom service' + ,handler: 'addCustomService' + } + ] + ,items: [ + { + xtype: 'dataview' + ,store: 'ServicesList' + ,itemSelector: 'div.service' + ,tpl: [ + '' + ,'
' + ,'' + ,'{name}' + ,'
' + ,'
' ] + ,emptyText: '
No services found... Try another search.
' + ,listeners: { + itemclick: 'onNewServiceSelect' + } + } + ] + } + ,{ + xtype: 'grid' + ,title: 'Enabled Services' + ,store: 'Services' + ,hideHeaders: true + ,margin: '0 0 0 5' + ,flex: 1 + ,header: { height: 50 } + ,columns: [ + { + xtype: 'templatecolumn' + ,width: 50 + ,variableRowHeight: true + ,tpl: '' + } + ,{ text: 'Name', dataIndex: 'name', variableRowHeight: true, flex: 1 } + ,{ + xtype: 'actioncolumn' + ,width: 60 + ,align: 'right' ,items: [ { - xtype: 'dataview' - ,store: 'ServicesList' - ,itemSelector: 'div.service' - ,tpl: [ - '' - ,'
' - ,'' - ,'{name}' - ,'
' - ,'
' - ] - ,listeners: { - itemclick: 'onNewServiceSelect' + 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: 'toolbar' - ,margin: '50 0 0 0' + xtype: 'actioncolumn' + ,width: 60 + ,align: 'center' ,items: [ { - xtype: 'label' - ,html: ' with from Argentina as an Open Source project.' + glyph: 0xf1f8 + ,tooltip: 'Remove' + ,handler: 'removeService' + ,getClass: function(){ return 'x-hidden-display'; } } ,{ - text: 'www.rambox.io' - ,href: 'http://www.rambox.io' + glyph: 0xf013 + ,tooltip: 'Configure' + ,handler: 'configureService' + ,getClass: function(){ return 'x-hidden-display'; } } ] } ] + ,viewConfig: { + emptyText: 'No services added...' + ,forceFit: true + } } ] + ,bbar: [ + '->' + ,{ + xtype: 'label' + ,html: ' with from Argentina as an Open Source project.' + } + ,{ + text: 'www.rambox.io' + ,href: 'http://www.rambox.io' + } + ,'->' + ] } ] + + ,listeners: { + tabchange: 'onTabChange' + } }); diff --git a/app/view/main/MainController.js b/app/view/main/MainController.js index c1482b91..817a6195 100644 --- a/app/view/main/MainController.js +++ b/app/view/main/MainController.js @@ -6,6 +6,14 @@ Ext.define('Rambox.view.main.MainController', { ,alias: 'controller.main' + // Make focus on webview every time the user change tabs, to enable the autofocus in websites + ,onTabChange: function( tabPanel, newTab, oldTab ) { + var me = this; + var webview = newTab.down('component').el.dom; + + if ( webview ) webview.focus(); + } + ,showSimpleModal: function(record, edit) { var me = this; @@ -100,8 +108,10 @@ Ext.define('Rambox.view.main.MainController', { ,align: formValues.align ,notifications: formValues.notifications ,muted: formValues.muted + ,js_unread: record.get('js_unread') }); service.save(); + Ext.getStore('Services').add(service); var tabData = { xtype: 'webview' @@ -113,6 +123,7 @@ Ext.define('Rambox.view.main.MainController', { ,align: formValues.align ,notifications: formValues.notifications ,muted: formValues.muted + ,record: service ,tabConfig: { service: service } @@ -242,8 +253,10 @@ Ext.define('Rambox.view.main.MainController', { ,align: formValues.align ,notifications: formValues.notifications ,muted: formValues.muted + ,js_unread: record.get('js_unread') }); service.save(); + Ext.getStore('Services').add(service); var tabData = { xtype: 'webview' @@ -255,6 +268,7 @@ Ext.define('Rambox.view.main.MainController', { ,align: formValues.align ,notifications: formValues.notifications ,muted: formValues.muted + ,record: service ,tabConfig: { service: service } @@ -286,11 +300,19 @@ Ext.define('Rambox.view.main.MainController', { } ,removeService: function( gridView, rowIndex, colIndex, col, e, rec, rowEl ) { - Ext.Msg.confirm('Please confirm...', 'Are you sure you want to remove '+rec.get('name')+'?', function(btnId) { + Ext.Msg.confirm('Please confirm...', 'Are you sure you want to remove '+rec.get('name')+'?', function(btnId) { if ( btnId === 'yes' ) { + var tab = Ext.getCmp('tab_'+rec.get('id')); + + // Remove record from localStorage gridView.getStore().remove(rec); - //webview.webContents.session.clearCache(); - Ext.getCmp('tab_'+rec.get('id')).close(); + + // Clear all trash data + tab.down('component').el.dom.getWebContents().session.clearCache(Ext.emptyFn); + tab.down('component').el.dom.getWebContents().session.clearStorageData({}, Ext.emptyFn); + + // Close tab + tab.close(); } }); } @@ -299,15 +321,6 @@ Ext.define('Rambox.view.main.MainController', { this.showSimpleModal(rec, true); } - ,doFilter: function( cg, newValue, oldValue ) { - var values = Ext.cq1('checkboxgroup').getValue(); - Ext.getStore('ServicesList').getFilters().replaceAll({ - fn: function(record) { - return Ext.Array.contains(Ext.Object.getKeys(values), record.get('type')); - } - }); - } - ,addCustomService: function( event, toolEl, owner, tool ) { var me = this; @@ -341,6 +354,7 @@ Ext.define('Rambox.view.main.MainController', { ,emptyText: 'http://service.url.com' ,name: 'url' ,vtype: 'url' + ,allowBlank: false ,listeners: { specialkey: function(field, e) { if(e.getKey() == e.ENTER && field.up('form').isValid()) { @@ -355,6 +369,7 @@ Ext.define('Rambox.view.main.MainController', { ,emptyText: 'http://image.url.com/image.png' ,name: 'logo' ,vtype: 'url' + ,allowBlank: true ,listeners: { specialkey: function(field, e) { if(e.getKey() == e.ENTER && field.up('form').isValid()) { @@ -394,6 +409,24 @@ Ext.define('Rambox.view.main.MainController', { } ] } + ,{ + xtype: 'fieldset' + ,title: 'Advanced' + ,margin: '10 0 0 0' + ,collapsible: true + ,collapsed: true + ,items: [ + { + xtype: 'textarea' + ,fieldLabel: 'Unread Code' + ,allowBlank: true + ,name: 'js_unread' + ,anchor: '100%' + ,emptyText: 'Write code here if the service don\'t update the page title when have new activity. The code needs to return an integer, for example: document.body.getElementsByClassName("ee").length;' + ,height: 120 + } + ] + } ] } ] @@ -420,8 +453,10 @@ Ext.define('Rambox.view.main.MainController', { ,align: formValues.align ,notifications: formValues.notifications ,muted: formValues.muted + ,js_unread: 'function checkUnread(){updateBadge(' + formValues.js_unread + ')}function updateBadge(e){e>=1?document.title="("+e+") "+originalTitle:document.title=originalTitle}var originalTitle=document.title;setInterval(checkUnread,3000);' }); service.save(); + Ext.getStore('Services').add(service); var tabData = { xtype: 'webview' @@ -433,6 +468,7 @@ Ext.define('Rambox.view.main.MainController', { ,align: formValues.align ,notifications: formValues.notifications ,muted: formValues.muted + ,record: service ,tabConfig: { service: service } @@ -454,4 +490,61 @@ Ext.define('Rambox.view.main.MainController', { // Make focus to the name field win.down('textfield[name="serviceName"]').focus(true, 100); } + + ,onSearchRender: function( field ) { + field.focus(false, 1000); + } + + ,onSearchEnter: function( field, e ) { + var me = this; + + if ( e.getKey() == e.ENTER && Ext.getStore('ServicesList').getCount() === 1 ) { + me.onNewServiceSelect(field.up().down('dataview'), Ext.getStore('ServicesList').getAt(0)); + me.onClearClick(field); + } + } + + ,doTypeFilter: function( cg, newValue, oldValue ) { + var me = this; + + Ext.getStore('ServicesList').getFilters().replaceAll({ + fn: function(record) { + return Ext.Array.contains(Ext.Object.getKeys(cg.getValue()), record.get('type')); + } + }); + } + + ,onSearchServiceChange: function(field, newValue, oldValue) { + var me = this; + + var cg = field.up().down('checkboxgroup'); + if ( !Ext.isEmpty(newValue) && newValue.length > 0 ) { + field.getTrigger('clear').show(); + + Ext.getStore('ServicesList').getFilters().replaceAll({ + fn: function(record) { + if ( !Ext.Array.contains(Ext.Object.getKeys(cg.getValue()), record.get('type')) ) return false; + return record.get('name').toLowerCase().indexOf(newValue.toLowerCase()) > -1 ? true : false; + } + }); + } else { + field.getTrigger('clear').hide(); + Ext.getStore('ServicesList').getFilters().removeAll(); + me.doTypeFilter(cg); + } + field.updateLayout(); + } + + ,onClearClick: function(field, trigger, e) { + var me = this; + + var cg = field.up().down('checkboxgroup'); + + field.reset(); + field.getTrigger('clear').hide(); + field.updateLayout(); + + Ext.getStore('ServicesList').getFilters().removeAll(); + me.doTypeFilter(cg); + } }); diff --git a/packages/local/rambox-default-theme/sass/etc/all.scss b/packages/local/rambox-default-theme/sass/etc/all.scss index 0a2ea3ef..0431e8ed 100644 --- a/packages/local/rambox-default-theme/sass/etc/all.scss +++ b/packages/local/rambox-default-theme/sass/etc/all.scss @@ -184,19 +184,22 @@ body { .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; } +//.x-box-scroller-body-horizontal { width: auto !important; margin-right: 18px; padding-right: 18px; } +//.x-box-scroller-tab-bar { z-index: 9999; } .service { - width:250px; - display:inline-block; - padding:10px; - cursor:pointer; + width: 230px; + display: inline-block; + padding: 10px; + cursor: pointer; img { float: left; } span { - margin-left:10px; - line-height:48px; + margin-left: 10px; + line-height: 48px; + } + &:hover { + background-color: lighten($base-color, 55%); } }