diff --git a/app/Application.js b/app/Application.js
index 28a8d03e..ff810d73 100644
--- a/app/Application.js
+++ b/app/Application.js
@@ -27,6 +27,7 @@ Ext.define('Rambox.Application', {
,launch: function () {
const isOnline = require('is-online');
+ const Mousetrap = require('mousetrap');
(async () => {
await isOnline().then(res => {
var hideNoConnection = ipc.sendSync('getConfig').hideNoConnectionDialog
@@ -121,140 +122,58 @@ Ext.define('Rambox.Application', {
// Check for updates
if ( require('electron').remote.process.argv.indexOf('--without-update') === -1 ) Rambox.app.checkUpdate(true);
- // Add shortcuts to switch services using CTRL + Number
- document.keyMapping = new Ext.util.KeyMap({
- target: document
- ,binding: [
- {
- key: "\t"
- ,ctrl: true
- ,alt: false
- ,shift: false
- ,handler: function(key) {
- var tabPanel = Ext.cq1('app-main');
- var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
- var i = activeIndex + 1;
-
- // "cycle" (go to the start) when the end is reached or the end is the spacer "tbfill"
- if (i === tabPanel.items.items.length || i === tabPanel.items.items.length - 1 && tabPanel.items.items[i].id === 'tbfill') i = 0;
-
- // skip spacer
- while (tabPanel.items.items[i].id === 'tbfill') i++;
-
- tabPanel.setActiveTab(i);
- }
- }
- ,{
- key: "f"
- ,ctrl: false
- ,alt: true
- ,shift: true
- ,handler: function(key) {
- var currentTab = Ext.cq1('app-main').getActiveTab();
- if ( currentTab.getWebView ) currentTab.showSearchBox(true);
- }
- }
- ,{
- key: "\t"
- ,ctrl: true
- ,alt: false
- ,shift: true
- ,handler: function(key) {
- var tabPanel = Ext.cq1('app-main');
- var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
- var i = activeIndex - 1;
- if ( i < 0 ) i = tabPanel.items.items.length - 1;
- while ( tabPanel.items.items[i].id === 'tbfill' || i < 0 ) i--;
- tabPanel.setActiveTab( i );
- }
- }
- ,{
- key: Ext.event.Event.PAGE_DOWN
- ,ctrl: true
- ,alt: false
- ,shift: false
- ,handler: function(key) {
- var tabPanel = Ext.cq1('app-main');
- var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
- var i = activeIndex + 1;
-
- // "cycle" (go to the start) when the end is reached or the end is the spacer "tbfill"
- if (i === tabPanel.items.items.length || i === tabPanel.items.items.length - 1 && tabPanel.items.items[i].id === 'tbfill') i = 0;
-
- // skip spacer
- while (tabPanel.items.items[i].id === 'tbfill') i++;
- tabPanel.setActiveTab(i);
- }
- }
- ,{
- key: Ext.event.Event.PAGE_UP
- ,ctrl: true
- ,alt: false
- ,shift: false
- ,handler: function(key) {
- var tabPanel = Ext.cq1('app-main');
- var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
- var i = activeIndex - 1;
- if ( i < 0 ) i = tabPanel.items.items.length - 1;
- while ( tabPanel.items.items[i].id === 'tbfill' || i < 0 ) i--;
- tabPanel.setActiveTab( i );
- }
- }
- ,{
- key: [Ext.event.Event.NUM_PLUS, Ext.event.Event.NUM_MINUS, 187, 189]
- ,ctrl: true
- ,alt: false
- ,shift: false
- ,handler: function(key) {
- var tabPanel = Ext.cq1('app-main');
- if ( tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0 ) return false;
-
- key === Ext.event.Event.NUM_PLUS || key === 187 ? tabPanel.getActiveTab().zoomIn() : tabPanel.getActiveTab().zoomOut();
- }
- }
- ,{
- key: [Ext.event.Event.NUM_ZERO, '0']
- ,ctrl: true
- ,alt: false
- ,shift: false
- ,handler: function(key) {
- var tabPanel = Ext.cq1('app-main');
- if ( tabPanel.items.indexOf(tabPanel.getActiveTab()) === 0 ) return false;
-
- tabPanel.getActiveTab().resetZoom();
- }
- }
- ,{
- key: 188 // comma
- ,ctrl: true
- ,alt: false
- ,handler: function(key) {
- Ext.cq1('app-main').setActiveTab(0);
- }
- }
- ,{
- key: 'd'
- ,ctrl: false
- ,alt: true
- ,shift: true
- ,handler: function(key) {
- var btn = Ext.getCmp('disturbBtn');
- btn.toggle();
- Ext.cq1('app-main').getController().dontDisturb(btn, true);
- }
- }
- ,{
- key: 'l'
- ,ctrl: false
- ,alt: true
- ,shift: true
- ,handler: function(key) {
- var btn = Ext.getCmp('lockRamboxBtn');
- Ext.cq1('app-main').getController().lockRambox(btn);
- }
- }
- ]
+ // Shortcuts
+ const platform = require('electron').remote.process.platform;
+ // Prevents default behaviour of Mousetrap, that prevents shortcuts in textareas
+ Mousetrap.prototype.stopCallback = function(e, element, combo) {
+ return false;
+ };
+ // Add shortcuts to switch services using CTRL + Number
+ Mousetrap.bind(platform === 'darwin' ? ["command+1","command+2","command+3","command+4","command+5","command+6","command+7","command+8","command+9"] : ["ctrl+1","ctrl+2","ctrl+3","ctrl+4","ctrl+5","ctrl+6","ctrl+7","ctrl+8","ctrl+9"], function(e, combo) { // GROUPS
+ var tabPanel = Ext.cq1('app-main');
+ var arg = parseInt(e.key);
+ if ( arg >= tabPanel.items.indexOf(Ext.getCmp('tbfill')) ) arg++;
+ tabPanel.setActiveTab(arg);
+ });
+ // Add shortcut to main tab (ctrl+,)
+ Mousetrap.bind(platform === 'darwin' ? 'command+,' : 'ctrl+,', (e, combo) => {
+ Ext.cq1('app-main').setActiveTab(0);
+ });
+ // Add shortcuts to navigate through services
+ Mousetrap.bind(['ctrl+tab', 'ctrl+pagedown'], (e, combo) => {
+ var tabPanel = Ext.cq1('app-main');
+ var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
+ var i = activeIndex + 1;
+ // "cycle" (go to the start) when the end is reached or the end is the spacer "tbfill"
+ if (i === tabPanel.items.items.length || i === tabPanel.items.items.length - 1 && tabPanel.items.items[i].id === 'tbfill') i = 0;
+ // skip spacer
+ while (tabPanel.items.items[i].id === 'tbfill') i++;
+ tabPanel.setActiveTab(i);
+ });
+ Mousetrap.bind(['ctrl+shift+tab', 'ctrl+pageup'], (e, combo) => {
+ var tabPanel = Ext.cq1('app-main');
+ var activeIndex = tabPanel.items.indexOf(tabPanel.getActiveTab());
+ var i = activeIndex - 1;
+ if ( i < 0 ) i = tabPanel.items.items.length - 1;
+ while ( tabPanel.items.items[i].id === 'tbfill' || i < 0 ) i--;
+ tabPanel.setActiveTab(i);
+ });
+ // Add shortcut to search inside a service
+ Mousetrap.bind(process.platform === 'darwin' ? ['command+alt+f'] : ['shift+alt+f'], (e, combo) => {
+ var currentTab = Ext.cq1('app-main').getActiveTab();
+ if ( currentTab.getWebView ) currentTab.showSearchBox(true);
+ });
+ // Add shortcut to Do Not Disturb
+ Mousetrap.bind(platform === 'darwin' ? ["command+d"] : ["shift+alt+d"], function(e, combo) {
+ var btn = Ext.getCmp('disturbBtn');
+ btn.toggle();
+ Ext.cq1('app-main').getController().dontDisturb(btn, true);
+ });
+ // Add shortcut to Lock Rambox
+ Mousetrap.bind(platform === 'darwin' ? ['command+alt+l'] : ['shift+alt+l'], (e, combo) => {
+ var btn = Ext.getCmp('lockRamboxBtn');
+ Ext.cq1('app-main').getController().lockRambox(btn);
});
// Mouse Wheel zooming
diff --git a/app/ux/WebView.js b/app/ux/WebView.js
index 9ff96a67..42a18e75 100644
--- a/app/ux/WebView.js
+++ b/app/ux/WebView.js
@@ -504,6 +504,34 @@ Ext.define('Rambox.ux.WebView',{
webview.executeJavaScript(js_inject).then(result => {} ).catch(err => { console.log(err) })
});
+ webview.getWebContents().on('before-input-event', (event, input) => {
+ if (input.type !== 'keyDown') return;
+
+ var modifiers = [];
+ if ( input.shift ) modifiers.push('shift');
+ if ( input.control ) modifiers.push('control');
+ if ( input.alt ) modifiers.push('alt');
+ if ( input.meta ) modifiers.push('meta');
+ if ( input.isAutoRepeat ) modifiers.push('isAutoRepeat');
+
+ if ( input.key === 'Tab' && !(modifiers && modifiers.length) ) return;
+
+ // Maps special keys to fire the correct event in Mac OS
+ if ( require('electron').remote.process.platform === 'darwin' ) {
+ var keys = [];
+ keys['ƒ'] = 'f'; // Search
+
+ input.key = keys[input.key] ? keys[input.key] : input.key;
+ }
+
+ if ( input.key === 'F11' || input.key === 'F12' || input.key === 'q' || (input.key === 'F1' && modifiers.includes('control'))) return;
+
+ require('electron').remote.getCurrentWebContents().sendInputEvent({
+ type: input.type,
+ keyCode: input.key,
+ modifiers: modifiers
+ });
+ })
webview.addEventListener('ipc-message', function(event) {
var channel = event.channel;
@@ -517,30 +545,6 @@ Ext.define('Rambox.ux.WebView',{
case 'rambox.showWindowAndActivateTab':
showWindowAndActivateTab(event);
break;
- case 'keydown':
- handleKeydown(event.args[0])
- break;
- }
- /**
- * Handles 'keydown' messages.
- * Allow to handle shortcuts.
- */
- function handleKeydown(event) {
- var emulatedKeyboardEvent = new KeyboardEvent('keydown', {
- code: event.code,
- key: event.code.substring(0, 5) === 'Digit' ? event.code.substring(5, 6) : event.key,
- shiftKey: event.shiftKey,
- altKey: event.altKey,
- ctrlKey: event.ctrlKey,
- metaKey: event.metaKey,
- repeat: event.repeat,
- keyCode: event.keyCode,
- charCode: event.charCode
- });
- emulatedKeyboardEvent.getKey = function() {
- return this.keyCode || this.charCode // fake function, normally used by Ext.js, simply returning keyCode
- }
- document.keyMapping.handleTargetEvent(emulatedKeyboardEvent) // we directly trigger handleTargetEvent. That's a private method normally. We can't fire the event directly with document.dispatch, unfortunately
}
/**
* Handles 'rambox.clearUnreadCount' messages.
diff --git a/app/view/main/Main.js b/app/view/main/Main.js
index d2b3e801..656dea60 100644
--- a/app/view/main/Main.js
+++ b/app/view/main/Main.js
@@ -243,7 +243,7 @@ Ext.define('Rambox.view.main.Main', {
{
glyph: JSON.parse(localStorage.getItem('dontDisturb')) ? 'xf1f7@FontAwesome' : 'xf0f3@FontAwesome'
,text: locale['app.main[16]']+': '+(JSON.parse(localStorage.getItem('dontDisturb')) ? locale['app.window[20]'] : locale['app.window[21]'])
- ,tooltip: locale['app.main[17]']+'
'+locale['app.main[18]']+': Alt + Shift + D'
+ ,tooltip: locale['app.main[17]']+'
'+locale['app.main[18]']+(require('electron').remote.process.platform === 'darwin' ? 'Cmd + D' : ': Alt + Shift + D')
,enableToggle: true
,handler: 'dontDisturb'
,reference: 'disturbBtn'
@@ -253,7 +253,7 @@ Ext.define('Rambox.view.main.Main', {
,{
glyph: 'xf023@FontAwesome'
,text: locale['app.main[19]']
- ,tooltip: locale['app.main[20]']+'
'+locale['app.main[18]']+': Alt + Shift + L'
+ ,tooltip: locale['app.main[20]']+'
'+locale['app.main[18]']+(require('electron').remote.process.platform === 'darwin' ? 'Cmd + Alt + L' : ': Alt + Shift + L')
,handler: 'lockRambox'
,id: 'lockRamboxBtn'
},'-'
diff --git a/electron/main.js b/electron/main.js
index 4da243e4..777f5834 100644
--- a/electron/main.js
+++ b/electron/main.js
@@ -1,6 +1,6 @@
'use strict';
-const {app, protocol, BrowserWindow, dialog, shell, Menu, ipcMain, nativeImage, session, globalShortcut} = require('electron');
+const {app, protocol, BrowserWindow, dialog, shell, Menu, ipcMain, nativeImage, session} = require('electron');
// Tray
const tray = require('./tray');
// AutoLaunch
@@ -479,15 +479,6 @@ if ( config.get('disable_gpu') ) app.disableHardwareAcceleration();
// initialization and is ready to create browser windows.
app.on('ready', function() {
config.get('master_password') ? createMasterPasswordWindow() : createWindow();
- globalShortcut.register('CommandOrControl+1', () => { mainWindow.webContents.send('shortcut:tab', 1); })
- globalShortcut.register('CommandOrControl+2', () => { mainWindow.webContents.send('shortcut:tab', 2); })
- globalShortcut.register('CommandOrControl+3', () => { mainWindow.webContents.send('shortcut:tab', 3); })
- globalShortcut.register('CommandOrControl+4', () => { mainWindow.webContents.send('shortcut:tab', 4); })
- globalShortcut.register('CommandOrControl+5', () => { mainWindow.webContents.send('shortcut:tab', 5); })
- globalShortcut.register('CommandOrControl+6', () => { mainWindow.webContents.send('shortcut:tab', 6); })
- globalShortcut.register('CommandOrControl+7', () => { mainWindow.webContents.send('shortcut:tab', 7); })
- globalShortcut.register('CommandOrControl+8', () => { mainWindow.webContents.send('shortcut:tab', 8); })
- globalShortcut.register('CommandOrControl+9', () => { mainWindow.webContents.send('shortcut:tab', 9); })
});
// Quit when all windows are closed.
diff --git a/electron/menu.js b/electron/menu.js
index d5971bc3..f249d0e8 100644
--- a/electron/menu.js
+++ b/electron/menu.js
@@ -178,14 +178,17 @@ module.exports = function(config) {
},
{
label: 'Zoom In',
+ accelerator: 'Ctrl+Plus',
click(item, win) { win.webContents.send('zoomin-webview')}
},
{
label: 'Zoom Out',
+ accelerator: 'Ctrl+-',
click(item, win) { win.webContents.send('zoomout-webview')}
},
{
label: 'Reset Zoom',
+ accelerator: 'Ctrl+0',
click(item, win) { win.webContents.send('resetzoom-webview')}
}
]
diff --git a/package-lock.json b/package-lock.json
index 1cb19b48..dcaea870 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4041,6 +4041,11 @@
}
}
},
+ "mousetrap": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/mousetrap/-/mousetrap-1.6.3.tgz",
+ "integrity": "sha512-bd+nzwhhs9ifsUrC2tWaSgm24/oo2c83zaRyZQF06hYA6sANfsXHtnZ19AbbbDXCDzeH5nZBSQ4NvCjgD62tJA=="
+ },
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
diff --git a/package.json b/package.json
index e2c2a0ee..cd0f4a30 100644
--- a/package.json
+++ b/package.json
@@ -205,6 +205,7 @@
"electron-updater": "4.1.2",
"is-online": "^8.2.0",
"mime": "^2.3.1",
+ "mousetrap": "^1.6.3",
"request": "^2.88.0",
"request-promise": "^4.2.2",
"rimraf": "2.6.1",
diff --git a/resources/js/rambox-service-api.js b/resources/js/rambox-service-api.js
index a0958ef0..15e3d0ec 100644
--- a/resources/js/rambox-service-api.js
+++ b/resources/js/rambox-service-api.js
@@ -55,19 +55,3 @@ window.rambox.contextMenuBuilder = new ContextMenuBuilder();
window.rambox.contextMenuListener = new ContextMenuListener(function(event, info) {
window.rambox.contextMenuBuilder.showPopupMenu(info);
});
-
-document.addEventListener("keydown", (event) => {
- if (event.type !== 'keydown' || event.key === 'z' || event.key === 'a' ) return; // event used by default
- var msg = {
- code: event.code,
- key: event.key,
- shiftKey: event.shiftKey,
- altKey: event.altKey,
- ctrlKey: event.ctrlKey,
- metaKey: event.metaKey,
- repeat: event.repeat,
- keyCode: event.keyCode,
- charCode: event.charCode
- };
- ipcRenderer.sendToHost('keydown', msg)
-});