diff --git a/CHANGELOG.md b/CHANGELOG.md index b7aef4f9..abdb4e34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,26 @@ ## Release v1.3.0 (Beta) ### Improvements +- Add shortcuts + - Zoom + - Ctrl+0 (View -> Actual Size): Reset the zoom level. + - Ctrl+Plus (View -> Zoom In) + - Ctrl+Minus (View -> Zoom Out) + - Control window + - Ctrl+W (Window -> Close): On Windows and Linux, this works as minimize for the main window. + - Ctrl+M (Window -> Minimize) + - Switch teams (these shotcuts also reopen the main window) + - Ctrl+{1-9} (Window -> *Team name*): Open the *n*-th tab. + - Ctrl+Tab or Alt+Command+Right (Window -> Select Next Team): Open the right tab. + - Ctrl+Shift+Tab or Alt+Command+Left (Window -> Select Previous Team): Open the left tab. + #### Linux - Add the option to show the icon on menu bar. (requires libappindicator1 on Ubuntu) +### Known issues +- The shortcuts can't switch teams twice in a raw. +- The team pages are not correctly rendered until the window is resized when the zoom level is changed. + ## Release v1.2.0 (Beta) diff --git a/docs/setup.md b/docs/setup.md index 8745b9e5..0bd92006 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -144,6 +144,15 @@ Below lists menu options (shortcut keys are listed in brackets, `Ctrl` becomes ` - **Clear Cache and Reload** (Ctrl+Shift+R) - Clear cached content in application and reload page - **Toggle Full Screen** (F11) - Toggle application from window to full screen and back - **Toggle Developer Tools** (Ctrl+Shift+I) - Turn on and off sidebar showing developer tools + - **Actual Size** (Ctrl+0) - Reset zoom level + - **Zoom In** (Ctrl+Plus) - Enlarge the rendered contents size + - **Zoom In** (Ctrl+Minus) - Shrink the rendered contents size +- **Window** + - **Close** (Ctrl+W) - Close the window (On Window and Linux, the main window is minimized) + - **Minimize** (Ctrl+M) - Minimize the window + - ***Team Name*** (Ctrl+{1-9}) - Open the *n*-th tab + - **Select Next Team** (Ctrl+Tab, Alt+Command+Right) - Open the right tab + - **Select Previous Team** (Ctrl+Shift+Tab, Alt+Command+Left) - Open the left tab ## Notifications diff --git a/src/browser/index.jsx b/src/browser/index.jsx index 671c683b..1a252b9f 100644 --- a/src/browser/index.jsx +++ b/src/browser/index.jsx @@ -15,9 +15,7 @@ const ListGroupItem = ReactBootstrap.ListGroupItem; const LoginModal = require('./components/loginModal.jsx'); -const electron = require('electron'); -const remote = electron.remote; -const ipcRenderer = electron.ipcRenderer; +const {remote, ipcRenderer, webFrame} = require('electron'); const osLocale = require('os-locale'); const fs = require('fs'); @@ -54,6 +52,16 @@ var MainPage = React.createClass({ loginQueue: loginQueue }); }); + // can't switch tabs sequencially for some reason... + ipcRenderer.on('switch-tab', (event, key) => { + this.handleSelect(key); + }); + ipcRenderer.on('select-next-tab', (event) => { + this.handleSelect(this.state.key + 1); + }); + ipcRenderer.on('select-previous-tab', (event) => { + this.handleSelect(this.state.key - 1); + }); var focusListener = function() { var webview = document.getElementById('mattermostView' + thisObj.state.key); @@ -69,8 +77,9 @@ var MainPage = React.createClass({ }); }, handleSelect: function(key) { + const newKey = (this.props.teams.length + key) % this.props.teams.length; this.setState({ - key: key + key: newKey }); this.handleOnTeamFocused(key); }, @@ -331,6 +340,9 @@ var MattermostView = React.createClass({ webview.addEventListener("dom-ready", function() { // webview.openDevTools(); + // In order to apply the zoom level to webview. + webFrame.setZoomLevel(parseInt(localStorage.getItem('zoomLevel'))); + // Use 'Meiryo UI' and 'MS Gothic' to prevent CJK fonts on Windows(JP). if (process.platform === 'win32') { var applyCssFile = function(cssFile) { @@ -452,7 +464,7 @@ var showUnreadBadgeWindows = function(unreadCount, mentionCount) { const sendBadge = function(dataURL, description) { // window.setOverlayIcon() does't work with NativeImage across remote boundaries. // https://github.com/atom/electron/issues/4011 - electron.ipcRenderer.send('update-unread', { + ipcRenderer.send('update-unread', { overlayDataURL: dataURL, description: description, unreadCount: unreadCount, @@ -480,7 +492,7 @@ var showUnreadBadgeOSX = function(unreadCount, mentionCount) { remote.app.dock.setBadge(''); } - electron.ipcRenderer.send('update-unread', { + ipcRenderer.send('update-unread', { unreadCount: unreadCount, mentionCount: mentionCount }); @@ -495,7 +507,7 @@ var showUnreadBadgeLinux = function(unreadCount, mentionCount) { remote.app.dock.setBadge(''); }*/ - electron.ipcRenderer.send('update-unread', { + ipcRenderer.send('update-unread', { unreadCount: unreadCount, mentionCount: mentionCount }); @@ -517,6 +529,22 @@ var showUnreadBadge = function(unreadCount, mentionCount) { } } +if (!localStorage.getItem('zoomLevel')) { + localStorage.setItem('zoomLevel', 0); +} +webFrame.setZoomLevel(parseInt(localStorage.getItem('zoomLevel'))); + +ipcRenderer.on('zoom-in', (event, increment) => { + const zoomLevel = webFrame.getZoomLevel() + increment + webFrame.setZoomLevel(zoomLevel); + localStorage.setItem('zoomLevel', zoomLevel); +}); + +ipcRenderer.on('zoom-reset', (event) => { + webFrame.setZoomLevel(0); + localStorage.setItem('zoomLevel', 0); +}); + ReactDOM.render( , document.getElementById('content') diff --git a/src/browser/settings.jsx b/src/browser/settings.jsx index 74442c1d..99ec2e10 100644 --- a/src/browser/settings.jsx +++ b/src/browser/settings.jsx @@ -1,6 +1,6 @@ 'use strict'; -const remote = require('electron').remote; +const {remote, ipcRenderer} = require('electron'); const settings = require('../common/settings'); const React = require('react'); @@ -50,6 +50,7 @@ var SettingsPage = React.createClass({ currentWindow.setAutoHideMenuBar(config.hideMenuBar); currentWindow.setMenuBarVisibility(!config.hideMenuBar); } + ipcRenderer.send('update-menu', config); backToIndex(); }, handleCancel: function() { diff --git a/src/main.js b/src/main.js index bce357db..91920116 100644 --- a/src/main.js +++ b/src/main.js @@ -231,6 +231,13 @@ app.on('ready', function() { // and load the index.html of the app. mainWindow.loadURL('file://' + __dirname + '/browser/index.html'); + // Set application menu + ipc.on('update-menu', (event, config) => { + var app_menu = appMenu.createMenu(mainWindow, config); + Menu.setApplicationMenu(app_menu); + }); + ipc.emit('update-menu', true, config); + // Open the DevTools. // mainWindow.openDevTools(); @@ -274,9 +281,6 @@ app.on('ready', function() { saveWindowState(bounds_info_path, mainWindow); }); - var app_menu = appMenu.createMenu(mainWindow); - Menu.setApplicationMenu(app_menu); - // Emitted when the window is closed. mainWindow.on('closed', function() { // Dereference the window object, usually you would store windows diff --git a/src/main/menus/app.js b/src/main/menus/app.js index b4fd0e58..471de492 100644 --- a/src/main/menus/app.js +++ b/src/main/menus/app.js @@ -3,7 +3,11 @@ const electron = require('electron'); const Menu = electron.Menu; -var createTemplate = function(mainWindow) { +var createTemplate = function(mainWindow, config) { + const separatorItem = { + type: 'separator' + }; + var app_name = electron.app.getName(); var first_menu_name = (process.platform === 'darwin') ? app_name : 'File'; var template = []; @@ -133,13 +137,79 @@ var createTemplate = function(mainWindow) { focusedWindow.toggleDevTools(); } } - }, ] + }, separatorItem, { + label: 'Actual Size', + accelerator: 'CmdOrCtrl+0', + click: () => { + mainWindow.webContents.send('zoom-reset'); + } + }, { + label: 'Zoom In', + accelerator: 'CmdOrCtrl+Plus', + click: () => { + mainWindow.webContents.send('zoom-in', 1); + } + }, { + label: 'Zoom Out', + accelerator: 'CmdOrCtrl+-', + click: () => { + mainWindow.webContents.send('zoom-in', -1); + } + }] }); + + const window_menu = { + label: '&Window', + submenu: [{ + label: 'Minimize', + accelerator: 'CmdOrCtrl+M', + click: function(item, focusedWindow) { + if (focusedWindow) { + focusedWindow.minimize(); + } + } + }, { + label: 'Close', + accelerator: 'CmdOrCtrl+W', + click: function(item, focusedWindow) { + if (focusedWindow) { + focusedWindow.close(); + } + } + }, { + type: 'separator' + }, ...config.teams.slice(0, 9).map((team, i) => { + return { + label: team.name, + accelerator: `CmdOrCtrl+${i + 1}`, + click: (item, focusedWindow) => { + mainWindow.show(); // for OS X + mainWindow.webContents.send('switch-tab', i); + } + }; + }), separatorItem, { + label: 'Select Next Team', + accelerator: (process.platform === 'darwin') ? 'Alt+Cmd+Right' : 'CmdOrCtrl+Tab', + click: () => { + mainWindow.webContents.send('select-next-tab'); + }, + enabled: (config.teams.length > 1) + }, { + label: 'Select Previous Team', + accelerator: (process.platform === 'darwin') ? 'Alt+Cmd+Left' : 'CmdOrCtrl+Shift+Tab', + click: () => { + mainWindow.webContents.send('select-previous-tab'); + }, + enabled: (config.teams.length > 1) + }] + } + template.push(window_menu); + return template; }; -var createMenu = function(mainWindow) { - return Menu.buildFromTemplate(createTemplate(mainWindow)); +var createMenu = function(mainWindow, config) { + return Menu.buildFromTemplate(createTemplate(mainWindow, config)); }; module.exports = {