diff --git a/app/package.json b/app/package.json index 839a79ef..7d96bec2 100644 --- a/app/package.json +++ b/app/package.json @@ -29,12 +29,12 @@ "author": "Ramiro Saenz ", "license": "MIT", "dependencies": { - "auto-launch": "^2.1.0", - "electron-window-state": "^3.0.3", + "auto-launch": "4.0.0", "firebase": "^3.0.5", "firebase-token-generator": "^2.0.0", "tmp": "0.0.28", "mime": "^1.3.4", - "electron-is-dev": "^0.1.1" + "electron-is-dev": "^0.1.1", + "electron-config": "0.2.1" } } diff --git a/app/view/main/Main.js b/app/view/main/Main.js index d5924c88..c86e1e4d 100644 --- a/app/view/main/Main.js +++ b/app/view/main/Main.js @@ -264,6 +264,11 @@ Ext.define('Rambox.view.main.Main', { } ,handler: 'login' } + ,{ + tooltip: 'Preferences' + ,glyph: 'xf013@FontAwesome' + ,handler: 'openPreferences' + } ] } ,bbar: [ diff --git a/app/view/main/MainController.js b/app/view/main/MainController.js index 84876a42..a6df1d09 100644 --- a/app/view/main/MainController.js +++ b/app/view/main/MainController.js @@ -927,6 +927,12 @@ Ext.define('Rambox.view.main.MainController', { winLock.down('textfield').focus(1000); } + ,openPreferences: function( btn ) { + var me = this; + + Ext.create('Rambox.view.preferences.Preferences').show(); + } + ,login: function(btn) { var me = this; diff --git a/app/view/preferences/Preferences.js b/app/view/preferences/Preferences.js new file mode 100644 index 00000000..1786c402 --- /dev/null +++ b/app/view/preferences/Preferences.js @@ -0,0 +1,92 @@ +Ext.define('Rambox.view.preferences.Preferences',{ + extend: 'Ext.window.Window' + ,xtype: 'preferences' + + ,requires: [ + 'Rambox.view.preferences.PreferencesController' + ,'Rambox.view.preferences.PreferencesModel' + ,'Ext.form.field.ComboBox' + ,'Ext.form.field.Checkbox' + ] + + ,controller: 'preferences-preferences' + ,viewModel: { + type: 'preferences-preferences' + } + + ,title: 'Preferences' + ,width: 400 + ,modal: true + ,closable: true + ,minimizable: false + ,maximizable: false + ,draggable: true + ,buttons: [ + { + text: 'Cancel' + ,ui: 'decline' + ,handler: 'cancel' + } + ,'->' + ,{ + text: 'Save' + ,handler: 'save' + } + ] + + ,initComponent: function() { + var config = ipc.sendSync('getConfig'); + + this.items = [ + { + xtype: 'form' + ,bodyPadding: 20 + ,items: [ + { + xtype: 'checkbox' + ,name: 'hide_menu_bar' + ,boxLabel: 'Auto-hide Menu bar (Alt key to display)' + ,value: config.hide_menu_bar + ,hidden: Ext.os.is.MacOS + } + ,{ + xtype: 'checkbox' + ,name: 'skip_taskbar' + ,boxLabel: 'Show in Taskbar' + ,value: config.skip_taskbar + ,reference: 'skipTaskbar' + ,hidden: Ext.os.is.MacOS + } + ,{ + xtype: 'checkbox' + ,name: 'keep_in_taskbar_on_close' + ,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 + } + ,{ + xtype: 'checkbox' + ,name: 'always_on_top' + ,boxLabel: 'Always on top' + ,value: config.always_on_top + } + ,{ + xtype: 'checkbox' + ,name: 'start_minimized' + ,boxLabel: 'Start minimized' + ,value: config.start_minimized + } + ,{ + xtype: 'checkbox' + ,name: 'auto_launch' + ,boxLabel: 'Start automatically on system startup' + ,value: config.auto_launch + } + ] + } + ]; + + this.callParent(); + } +}); diff --git a/app/view/preferences/PreferencesController.js b/app/view/preferences/PreferencesController.js new file mode 100644 index 00000000..aae878b3 --- /dev/null +++ b/app/view/preferences/PreferencesController.js @@ -0,0 +1,17 @@ +Ext.define('Rambox.view.preferences.PreferencesController', { + extend: 'Ext.app.ViewController' + ,alias: 'controller.preferences-preferences' + + ,cancel: function( btn ) { + var me = this; + + me.getView().close(); + } + + ,save: function( btn ) { + var me = this; + + ipc.send('setConfig', me.getView().down('form').getForm().getFieldValues()); + me.getView().close(); + } +}); diff --git a/app/view/preferences/PreferencesModel.js b/app/view/preferences/PreferencesModel.js new file mode 100644 index 00000000..e9ae12b9 --- /dev/null +++ b/app/view/preferences/PreferencesModel.js @@ -0,0 +1,6 @@ +Ext.define('Rambox.view.preferences.PreferencesModel', { + extend: 'Ext.app.ViewModel' + ,alias: 'viewmodel.preferences-preferences' + + ,data: {} +}); diff --git a/electron/global_settings.js b/electron/global_settings.js deleted file mode 100644 index 94c04c18..00000000 --- a/electron/global_settings.js +++ /dev/null @@ -1,37 +0,0 @@ -const fs = require('fs'); -const settingsPathname = 'rambox_cfg.json'; - -var globalSettings = { - settings: { - always_on_top: 0, - hide_menu_bar: 0, - skip_taskbar: 0, - auto_launch: 1, - keep_in_taskbar_on_close: 1, - start_minimized: 0 - }, - init: function(settings) { - this.settings = settings; - }, - set: function(name, value) { - this.settings[name] = value; - }, - get: function(name) { - return this.settings[name]; - }, - save: function() { - try { - fs.writeFileSync(settingsPathname, JSON.stringify(this.settings)); - } catch (err) {} - } -}; - -try { - //test to see if settings exist - fs.openSync(settingsPathname, 'r+'); //throws error if file doesn't exist - globalSettings.init(JSON.parse(fs.readFileSync(settingsPathname))); -} catch (err) { - globalSettings.save(); -} - -module.exports = globalSettings; diff --git a/electron/main.js b/electron/main.js index 49ab6239..c27663d9 100644 --- a/electron/main.js +++ b/electron/main.js @@ -5,14 +5,40 @@ const {app, protocol, BrowserWindow, dialog, shell, Menu, ipcMain, nativeImage} const appMenu = require('./menu'); // Tray const tray = require('./tray'); -// Window State Plugin -const windowStateKeeper = require('electron-window-state'); -// Global Settings -var globalSettings = require('./global_settings.js'); - +// AutoLaunch +var AutoLaunch = require('auto-launch'); +// Configuration +const Config = require('electron-config'); +// Development const isDev = require('electron-is-dev'); +// Updater const updater = require('./updater'); +// Initial Config +const config = new Config({ + defaults: { + always_on_top: false + ,hide_menu_bar: false + ,skip_taskbar: true + ,auto_launch: !isDev + ,keep_in_taskbar_on_close: true + ,start_minimized: false + + ,x: undefined + ,y: undefined + ,width: 1000 + ,height: 800 + ,maximized: false + } +}); + +// Configure AutoLaunch +const appLauncher = new AutoLaunch({ + name: 'Rambox' + ,isHiddenOnLaunch: config.get('start_minimized') +}); +config.get('auto_launch') && !isDev ? appLauncher.enable() : appLauncher.disable(); + // this should be placed at top of main.js to handle setup events quickly if (handleSquirrelEvent()) { // squirrel event handled and app will exit in 1000ms, so don't do anything else @@ -87,27 +113,19 @@ let mainWindow; let isQuitting = false; function createWindow () { - // Load the previous state with fallback to defaults - - let mainWindowState = windowStateKeeper({ - defaultWidth: 1000 - ,defaultHeight: 800 - ,maximize: false - }); - // Create the browser window using the state information mainWindow = new BrowserWindow({ title: 'Rambox' ,icon: __dirname + '/../resources/Icon.ico' - ,x: mainWindowState.x - ,y: mainWindowState.y - ,width: mainWindowState.width - ,height: mainWindowState.height - ,backgroundColor: '#2E658E' - ,alwaysOnTop: parseInt(globalSettings.get('always_on_top')) ? true : false - ,autoHideMenuBar: parseInt(globalSettings.get('hide_menu_bar')) ? true : false - ,skipTaskbar: parseInt(globalSettings.get('skip_taskbar')) ? true : false - ,show: parseInt(globalSettings.get('start_minimized')) ? false : true + ,backgroundColor: '#FFF' + ,x: config.get('x') + ,y: config.get('y') + ,width: config.get('width') + ,height: config.get('height') + ,alwaysOnTop: config.get('always_on_top') + ,autoHideMenuBar: config.get('hide_menu_bar') + ,skipTaskbar: !config.get('skip_taskbar') + ,show: !config.get('start_minimized') ,webPreferences: { webSecurity: false ,nodeIntegration: true @@ -116,26 +134,22 @@ function createWindow () { } }); - if ( !parseInt(globalSettings.get('start_minimized')) && mainWindowState.isMaximized ) mainWindow.maximize(); - - // Let us register listeners on the window, so we can update the state - // automatically (the listeners will be removed when the window is closed) - // and restore the maximized or full screen state - mainWindowState.manage(mainWindow); + if ( !config.get('start_minimized') && config.get('maximized') ) mainWindow.maximize(); process.setMaxListeners(10000); + // Open the DevTools. + if ( isDev ) mainWindow.webContents.openDevTools(); + // and load the index.html of the app. mainWindow.loadURL('file://' + __dirname + '/../index.html'); Menu.setApplicationMenu(appMenu); - tray.create(mainWindow, mainWindowState); + tray.create(mainWindow, config); if ( !isDev && process.platform === 'win32' ) updater.initialize(mainWindow); - mainWindow.on('page-title-updated', (e, title) => updateBadge(title)); - // Open links in default browser mainWindow.webContents.on('new-window', function(e, url, frameName, disposition, options) { if ( disposition !== 'foreground-tab' ) return; @@ -150,18 +164,22 @@ function createWindow () { event.preventDefault(); }); + // BrowserWindow events + mainWindow.on('page-title-updated', (e, title) => updateBadge(title)); + mainWindow.on('maximize', function(e) { config.set('maximized', true); }); + mainWindow.on('unmaximize', function(e) { config.set('maximized', false); }); + mainWindow.on('resize', function(e) { if (!mainWindow.isMaximized()) config.set(mainWindow.getBounds()); }); + mainWindow.on('move', function(e) { if (!mainWindow.isMaximized()) config.set(mainWindow.getBounds()); }); mainWindow.on('app-command', (e, cmd) => { // Navigate the window back when the user hits their mouse back button if ( cmd === 'browser-backward' ) mainWindow.webContents.executeJavaScript('Ext.cq1("app-main").getActiveTab().goBack();'); // Navigate the window forward when the user hits their mouse forward button if ( cmd === 'browser-forward' ) mainWindow.webContents.executeJavaScript('Ext.cq1("app-main").getActiveTab().goForward();'); }); - mainWindow.on('focus', (e) => { // Make focus on current service when user use Alt + Tab to activate Rambox mainWindow.webContents.executeJavaScript('Ext.cq1("app-main").fireEvent("tabchange", Ext.cq1("app-main"), Ext.cq1("app-main").getActiveTab());'); }); - // Emitted when the window is closed. mainWindow.on('close', function(e) { if ( !isQuitting ) { @@ -170,11 +188,10 @@ function createWindow () { if (process.platform === 'darwin') { app.hide(); } else { - parseInt(globalSettings.get('keep_in_taskbar_on_close')) ? mainWindow.minimize() : mainWindow.hide(); + config.get('keep_in_taskbar_on_close') ? mainWindow.minimize() : mainWindow.hide(); } } }); - mainWindow.on('closed', function(e) { mainWindow = null; }); @@ -202,6 +219,24 @@ ipcMain.on('setBadge', function(event, messageCount, value) { mainWindow.setOverlayIcon(img, messageCount.toString()); }); +ipcMain.on('getConfig', function(event, arg) { + event.returnValue = config.store; +}); + +ipcMain.on('setConfig', function(event, values) { + config.set(values); + + // hide_menu_bar + mainWindow.setAutoHideMenuBar(values.hide_menu_bar); + if ( !values.hide_menu_bar ) mainWindow.setMenuBarVisibility(true); + // skip_taskbar + mainWindow.setSkipTaskbar(!values.skip_taskbar); + // always_on_top + mainWindow.setAlwaysOnTop(values.always_on_top); + // auto_launch + values.auto_launch ? appLauncher.enable() : appLauncher.disable(); +}); + const shouldQuit = app.makeSingleInstance((commandLine, workingDirectory) => { // Someone tried to run a second instance, we should focus our window. if (mainWindow) { diff --git a/electron/menu.js b/electron/menu.js index 5e6a754e..8d6847b3 100644 --- a/electron/menu.js +++ b/electron/menu.js @@ -5,21 +5,6 @@ const app = electron.app; const BrowserWindow = electron.BrowserWindow; const shell = electron.shell; const appName = app.getName(); -// AutoLaunch -var AutoLaunch = require('auto-launch'); -// Global Settings -var globalSettings = require('./global_settings.js'); - -// Configure AutoLaunch -const appLauncher = new AutoLaunch({ - name: 'Rambox' -}); -appLauncher.isEnabled().then(function(enabled){ - if(enabled) return; - return appLauncher.enable(); -}).then(function(err){ - -}); function sendAction(action) { const win = BrowserWindow.getAllWindows()[0]; @@ -185,111 +170,6 @@ let tpl = [ } ]; -let preferences = [ - { - label: 'Auto-hide Menu bar', - visible: process.platform === 'win32', - type: 'checkbox', - checked: parseInt(globalSettings.get('hide_menu_bar')) ? true : false, - click: function(item, mainWindow) { - if ( item.checked ) { - electron.dialog.showMessageBox(mainWindow, { - title: 'Don\'t need to see the menu bar all the time?' - ,message: 'To temporarily show the menu bar, just press the Alt key.' - ,buttons: ['OK'] - ,type: 'info' - }, function() { - mainWindow.focus(); - }); - globalSettings.set('hide_menu_bar', 1); - if (mainWindow) mainWindow.setAutoHideMenuBar(true); - } else { - globalSettings.set('hide_menu_bar', 0); - mainWindow.setAutoHideMenuBar(false); - } - globalSettings.save(); - } - }, - { - label: 'Show in Taskbar', - type: 'checkbox', - checked: parseInt(globalSettings.get('skip_taskbar')) ? false : true, - click: function(item, mainWindow) { - if ( item.checked ) { - globalSettings.set('skip_taskbar', 0); - globalSettings.set('keep_in_taskbar_on_close', 1); - menu.items[0].submenu.items[process.platform === 'darwin' ? 2 : 0].submenu.items[2].enabled = true; - menu.items[0].submenu.items[process.platform === 'darwin' ? 2 : 0].submenu.items[2].checked = true; - if (mainWindow) mainWindow.setSkipTaskbar(false); - } else { - globalSettings.set('skip_taskbar', 1); - globalSettings.set('keep_in_taskbar_on_close', 0); - menu.items[0].submenu.items[process.platform === 'darwin' ? 2 : 0].submenu.items[2].enabled = false; - menu.items[0].submenu.items[process.platform === 'darwin' ? 2 : 0].submenu.items[2].checked = false; - mainWindow.setSkipTaskbar(true); - } - globalSettings.save(); - } - }, - { - label: 'Keep Rambox in the taskbar when close it', - type: 'checkbox', - enabled: parseInt(globalSettings.get('skip_taskbar')) ? false : true, - checked: parseInt(globalSettings.get('keep_in_taskbar_on_close')) ? true : false, - click: function(item) { - if ( item.checked ) { - globalSettings.set('keep_in_taskbar_on_close', 1); - } else { - globalSettings.set('keep_in_taskbar_on_close', 0); - } - globalSettings.save(); - } - }, - { - label: 'Always on top', - type: 'checkbox', - checked: parseInt(globalSettings.get('always_on_top')) ? true : false, - click: function(item, mainWindow) { - if ( item.checked ) { - globalSettings.set('always_on_top', 1); - if (mainWindow) mainWindow.setAlwaysOnTop(true); - } else { - globalSettings.set('always_on_top', 0); - mainWindow.setAlwaysOnTop(false); - } - globalSettings.save(); - } - }, - { - label: 'Start minimized', - type: 'checkbox', - checked: parseInt(globalSettings.get('start_minimized')) ? true : false, - click: function(item) { - if ( item.checked ) { - globalSettings.set('start_minimized', 1); - } else { - globalSettings.set('start_minimized', 0); - } - globalSettings.save(); - } - }, - { - label: 'Start automatically on system startup', - type: 'checkbox', - checked: parseInt(globalSettings.get('auto_launch')) ? true : false, - click: function(item) { - if ( item.checked ) { - appLauncher.enable(); - globalSettings.set('auto_launch', 1); - } else { - appLauncher.disable(); - globalSettings.set('auto_launch', 0); - } - globalSettings.save(); - } - } -]; - if (process.platform === 'darwin') { tpl.unshift({ label: appName, @@ -311,13 +191,6 @@ if (process.platform === 'darwin') { { type: 'separator' }, - { - label: 'Preferences', - submenu: preferences - }, - { - type: 'separator' - }, { label: 'Services', role: 'services', @@ -352,13 +225,6 @@ if (process.platform === 'darwin') { tpl.unshift({ label: 'File', submenu: [ - { - label: 'Preferences', - submenu: preferences - }, - { - type: 'separator' - }, { role: 'quit' } diff --git a/electron/tray.js b/electron/tray.js index 682e22af..fdafe084 100644 --- a/electron/tray.js +++ b/electron/tray.js @@ -7,7 +7,7 @@ const Tray = electron.Tray; const MenuItem = electron.MenuItem; var appIcon = null; -exports.create = function(win, mainWindowState) { +exports.create = function(win, config) { if (process.platform === 'darwin' || appIcon) { return; } @@ -16,19 +16,25 @@ exports.create = function(win, mainWindowState) { const iconPath = path.join(__dirname, `../resources/${icon}`); const toggleWin = () => { - if (win.isVisible()) { - win.hide(); + if ( !config.get('keep_in_taskbar_on_close') ) { + if ( win.isVisible() ) { + win.hide(); + } else { + config.get('maximized') ? win.maximize() : win.show(); + } } else { - win.show(); + if ( win.isVisible() && !win.isMinimized() ) { + win.minimize(); + } else { + config.get('maximized') ? win.maximize() : win.show(); + } } }; const contextMenu = electron.Menu.buildFromTemplate([ { label: 'Show/Hide Window' - ,click() { - toggleWin(); - } + ,click: toggleWin }, { type: 'separator' diff --git a/package.json b/package.json index 3ca4fd42..6bcdd47f 100644 --- a/package.json +++ b/package.json @@ -129,12 +129,12 @@ } }, "dependencies": { - "auto-launch": "^2.1.0", - "electron-window-state": "^3.0.3", + "auto-launch": "4.0.0", "firebase": "^3.0.5", "firebase-token-generator": "^2.0.0", "tmp": "0.0.28", "mime": "^1.3.4", - "electron-is-dev": "^0.1.1" + "electron-is-dev": "^0.1.1", + "electron-config": "0.2.1" } }