2017-10-10 23:43:22 +00:00
|
|
|
/* global APP, $, interfaceConfig */
|
2016-06-20 21:13:17 +00:00
|
|
|
|
2017-05-26 22:11:33 +00:00
|
|
|
import { toggleDialog } from '../../react/features/base/dialog';
|
2017-12-11 18:48:32 +00:00
|
|
|
import {
|
2018-01-03 21:24:07 +00:00
|
|
|
ACTION_SHORTCUT_PRESSED as PRESSED,
|
|
|
|
ACTION_SHORTCUT_RELEASED as RELEASED,
|
|
|
|
createShortcutEvent,
|
|
|
|
sendAnalytics
|
2017-12-11 18:48:32 +00:00
|
|
|
} from '../../react/features/analytics';
|
2017-11-13 22:58:00 +00:00
|
|
|
import { KeyboardShortcutsDialog }
|
|
|
|
from '../../react/features/keyboard-shortcuts';
|
2017-02-17 00:59:30 +00:00
|
|
|
import { SpeakerStats } from '../../react/features/speaker-stats';
|
|
|
|
|
2017-10-09 21:40:38 +00:00
|
|
|
const logger = require('jitsi-meet-logger').getLogger(__filename);
|
|
|
|
|
2016-08-29 03:59:09 +00:00
|
|
|
/**
|
|
|
|
* Map of shortcuts. When a shortcut is registered it enters the mapping.
|
2018-04-06 15:11:21 +00:00
|
|
|
* @type {Map}
|
2016-08-29 03:59:09 +00:00
|
|
|
*/
|
2018-04-06 15:11:21 +00:00
|
|
|
const _shortcuts = new Map();
|
2016-08-29 03:59:09 +00:00
|
|
|
|
2017-11-13 22:58:00 +00:00
|
|
|
/**
|
|
|
|
* Map of registered keyboard keys and translation keys describing the
|
|
|
|
* action performed by the key.
|
|
|
|
* @type {Map}
|
|
|
|
*/
|
|
|
|
const _shortcutsHelp = new Map();
|
|
|
|
|
2017-01-06 22:03:54 +00:00
|
|
|
/**
|
|
|
|
* True if the keyboard shortcuts are enabled and false if not.
|
|
|
|
* @type {boolean}
|
|
|
|
*/
|
|
|
|
let enabled = true;
|
|
|
|
|
2016-08-29 03:59:09 +00:00
|
|
|
/**
|
|
|
|
* Maps keycode to character, id of popover for given function and function.
|
|
|
|
*/
|
2017-06-14 18:13:41 +00:00
|
|
|
const KeyboardShortcut = {
|
2017-10-12 23:02:29 +00:00
|
|
|
init() {
|
|
|
|
this._initGlobalShortcuts();
|
2016-08-29 03:59:09 +00:00
|
|
|
|
2017-10-12 23:02:29 +00:00
|
|
|
window.onkeyup = e => {
|
|
|
|
if (!enabled) {
|
2017-01-06 22:03:54 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-10-12 23:02:29 +00:00
|
|
|
const key = this._getKeyboardKey(e).toUpperCase();
|
|
|
|
const num = parseInt(key, 10);
|
|
|
|
|
|
|
|
if (!($(':focus').is('input[type=text]')
|
|
|
|
|| $(':focus').is('input[type=password]')
|
|
|
|
|| $(':focus').is('textarea'))) {
|
2018-04-06 15:11:21 +00:00
|
|
|
if (_shortcuts.has(key)) {
|
|
|
|
_shortcuts.get(key).function(e);
|
2017-10-12 23:02:29 +00:00
|
|
|
} else if (!isNaN(num) && num >= 0 && num <= 9) {
|
2016-11-01 10:30:43 +00:00
|
|
|
APP.UI.clickOnVideo(num);
|
2015-01-22 16:26:05 +00:00
|
|
|
}
|
2017-10-12 23:02:29 +00:00
|
|
|
|
2015-01-22 16:26:05 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-10-12 23:02:29 +00:00
|
|
|
window.onkeydown = e => {
|
|
|
|
if (!enabled) {
|
2017-01-06 22:03:54 +00:00
|
|
|
return;
|
|
|
|
}
|
2017-10-12 23:02:29 +00:00
|
|
|
if (!($(':focus').is('input[type=text]')
|
|
|
|
|| $(':focus').is('input[type=password]')
|
|
|
|
|| $(':focus').is('textarea'))) {
|
|
|
|
if (this._getKeyboardKey(e).toUpperCase() === ' ') {
|
|
|
|
if (APP.conference.isLocalAudioMuted()) {
|
2018-01-03 21:24:07 +00:00
|
|
|
sendAnalytics(createShortcutEvent(
|
|
|
|
'push.to.talk',
|
|
|
|
PRESSED));
|
|
|
|
logger.log('Talk shortcut pressed');
|
2016-02-09 16:29:50 +00:00
|
|
|
APP.conference.muteAudio(false);
|
2017-10-09 21:40:38 +00:00
|
|
|
}
|
2015-01-22 16:26:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
},
|
2016-08-29 03:59:09 +00:00
|
|
|
|
2017-01-06 22:03:54 +00:00
|
|
|
/**
|
|
|
|
* Enables/Disables the keyboard shortcuts.
|
|
|
|
* @param {boolean} value - the new value.
|
|
|
|
*/
|
2017-10-12 23:02:29 +00:00
|
|
|
enable(value) {
|
2017-01-06 22:03:54 +00:00
|
|
|
enabled = value;
|
|
|
|
},
|
|
|
|
|
2018-03-07 00:28:19 +00:00
|
|
|
/**
|
|
|
|
* Opens the {@KeyboardShortcutsDialog} dialog.
|
|
|
|
*
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
openDialog() {
|
|
|
|
APP.store.dispatch(toggleDialog(KeyboardShortcutsDialog, {
|
|
|
|
shortcutDescriptions: _shortcutsHelp
|
|
|
|
}));
|
|
|
|
},
|
|
|
|
|
2016-08-29 03:59:09 +00:00
|
|
|
/**
|
|
|
|
* Registers a new shortcut.
|
|
|
|
*
|
|
|
|
* @param shortcutChar the shortcut character triggering the action
|
2018-01-03 21:24:07 +00:00
|
|
|
* @param shortcutAttr the "shortcut" html element attribute mapping an
|
2016-08-29 03:59:09 +00:00
|
|
|
* element to this shortcut and used to show the shortcut character on the
|
|
|
|
* element tooltip
|
|
|
|
* @param exec the function to be executed when the shortcut is pressed
|
|
|
|
* @param helpDescription the description of the shortcut that would appear
|
|
|
|
* in the help menu
|
|
|
|
*/
|
2017-10-12 23:02:29 +00:00
|
|
|
registerShortcut(// eslint-disable-line max-params
|
2017-10-02 23:08:07 +00:00
|
|
|
shortcutChar,
|
|
|
|
shortcutAttr,
|
|
|
|
exec,
|
|
|
|
helpDescription) {
|
2018-04-06 15:11:21 +00:00
|
|
|
_shortcuts.set(shortcutChar, {
|
2016-08-29 03:59:09 +00:00
|
|
|
character: shortcutChar,
|
2018-04-06 15:11:21 +00:00
|
|
|
function: exec,
|
|
|
|
shortcutAttr
|
|
|
|
});
|
2016-08-29 03:59:09 +00:00
|
|
|
|
2017-10-12 23:02:29 +00:00
|
|
|
if (helpDescription) {
|
2016-08-29 03:59:09 +00:00
|
|
|
this._addShortcutToHelp(shortcutChar, helpDescription);
|
2017-10-12 23:02:29 +00:00
|
|
|
}
|
2016-08-29 03:59:09 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Unregisters a shortcut.
|
|
|
|
*
|
|
|
|
* @param shortcutChar unregisters the given shortcut, which means it will
|
|
|
|
* no longer be usable
|
|
|
|
*/
|
2017-10-12 23:02:29 +00:00
|
|
|
unregisterShortcut(shortcutChar) {
|
2018-04-06 15:11:21 +00:00
|
|
|
_shortcuts.delete(shortcutChar);
|
2017-11-13 22:58:00 +00:00
|
|
|
_shortcutsHelp.delete(shortcutChar);
|
Improve keyboard shortcut handling
Use KeyboardEvent.key if available,
match both lower and upper case letters to keep previous behaviour
KeyboardEvent is a mess.
KeyboardEvent.which gives you, in theory, a decimal representation of the key pressed.
"r" or "R" gives you 82, which is "R", you can look at KeyboardEvent.shiftKey,
but you don't have access to capslock...
Maybe you want to use numbers, but of course NumPad will not give you the same than
"normal" numbers ...
Now if you use something else than letter, for exemple "?",
on a QWERTY keyboard "/" and "?" gives you 191,
on a AZERTY keyboard "," and "?" gives you 188, so we have to stick to letters.
This was for keydown and keyup events, keypressed event return the real char
(lower "a", "/", "?", ...) but it fails in some cases
The only non broken property is KeyboardEvent.key,
but it's only supported since Chrome 51, Opera 38, and not supported by Safari
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
A good reference & test:
http://unixpapa.com/js/testkey.html
http://unixpapa.com/js/key.html
Signed-off-by: Etienne CHAMPETIER <champetier.etienne@gmail.com>
2016-07-13 12:22:57 +00:00
|
|
|
},
|
2017-10-12 23:02:29 +00:00
|
|
|
|
Improve keyboard shortcut handling
Use KeyboardEvent.key if available,
match both lower and upper case letters to keep previous behaviour
KeyboardEvent is a mess.
KeyboardEvent.which gives you, in theory, a decimal representation of the key pressed.
"r" or "R" gives you 82, which is "R", you can look at KeyboardEvent.shiftKey,
but you don't have access to capslock...
Maybe you want to use numbers, but of course NumPad will not give you the same than
"normal" numbers ...
Now if you use something else than letter, for exemple "?",
on a QWERTY keyboard "/" and "?" gives you 191,
on a AZERTY keyboard "," and "?" gives you 188, so we have to stick to letters.
This was for keydown and keyup events, keypressed event return the real char
(lower "a", "/", "?", ...) but it fails in some cases
The only non broken property is KeyboardEvent.key,
but it's only supported since Chrome 51, Opera 38, and not supported by Safari
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
A good reference & test:
http://unixpapa.com/js/testkey.html
http://unixpapa.com/js/key.html
Signed-off-by: Etienne CHAMPETIER <champetier.etienne@gmail.com>
2016-07-13 12:22:57 +00:00
|
|
|
/**
|
|
|
|
* @param e a KeyboardEvent
|
|
|
|
* @returns {string} e.key or something close if not supported
|
|
|
|
*/
|
2017-10-12 23:02:29 +00:00
|
|
|
_getKeyboardKey(e) {
|
2018-04-16 21:33:26 +00:00
|
|
|
// If e.key is a string, then it is assumed it already plainly states
|
|
|
|
// the key pressed. This may not be true in all cases, such as with Edge
|
|
|
|
// and "?", when the browser cannot properly map a key press event to a
|
|
|
|
// keyboard key. To be safe, when a key is "Unidentified" it must be
|
|
|
|
// further analyzed by jitsi to a key using e.which.
|
|
|
|
if (typeof e.key === 'string' && e.key !== 'Unidentified') {
|
Improve keyboard shortcut handling
Use KeyboardEvent.key if available,
match both lower and upper case letters to keep previous behaviour
KeyboardEvent is a mess.
KeyboardEvent.which gives you, in theory, a decimal representation of the key pressed.
"r" or "R" gives you 82, which is "R", you can look at KeyboardEvent.shiftKey,
but you don't have access to capslock...
Maybe you want to use numbers, but of course NumPad will not give you the same than
"normal" numbers ...
Now if you use something else than letter, for exemple "?",
on a QWERTY keyboard "/" and "?" gives you 191,
on a AZERTY keyboard "," and "?" gives you 188, so we have to stick to letters.
This was for keydown and keyup events, keypressed event return the real char
(lower "a", "/", "?", ...) but it fails in some cases
The only non broken property is KeyboardEvent.key,
but it's only supported since Chrome 51, Opera 38, and not supported by Safari
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
A good reference & test:
http://unixpapa.com/js/testkey.html
http://unixpapa.com/js/key.html
Signed-off-by: Etienne CHAMPETIER <champetier.etienne@gmail.com>
2016-07-13 12:22:57 +00:00
|
|
|
return e.key;
|
|
|
|
}
|
2017-10-12 23:02:29 +00:00
|
|
|
if (e.type === 'keypress'
|
2017-10-02 23:08:07 +00:00
|
|
|
&& ((e.which >= 32 && e.which <= 126)
|
2017-10-12 23:02:29 +00:00
|
|
|
|| (e.which >= 160 && e.which <= 255))) {
|
Improve keyboard shortcut handling
Use KeyboardEvent.key if available,
match both lower and upper case letters to keep previous behaviour
KeyboardEvent is a mess.
KeyboardEvent.which gives you, in theory, a decimal representation of the key pressed.
"r" or "R" gives you 82, which is "R", you can look at KeyboardEvent.shiftKey,
but you don't have access to capslock...
Maybe you want to use numbers, but of course NumPad will not give you the same than
"normal" numbers ...
Now if you use something else than letter, for exemple "?",
on a QWERTY keyboard "/" and "?" gives you 191,
on a AZERTY keyboard "," and "?" gives you 188, so we have to stick to letters.
This was for keydown and keyup events, keypressed event return the real char
(lower "a", "/", "?", ...) but it fails in some cases
The only non broken property is KeyboardEvent.key,
but it's only supported since Chrome 51, Opera 38, and not supported by Safari
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
A good reference & test:
http://unixpapa.com/js/testkey.html
http://unixpapa.com/js/key.html
Signed-off-by: Etienne CHAMPETIER <champetier.etienne@gmail.com>
2016-07-13 12:22:57 +00:00
|
|
|
return String.fromCharCode(e.which);
|
|
|
|
}
|
2017-10-12 23:02:29 +00:00
|
|
|
|
Improve keyboard shortcut handling
Use KeyboardEvent.key if available,
match both lower and upper case letters to keep previous behaviour
KeyboardEvent is a mess.
KeyboardEvent.which gives you, in theory, a decimal representation of the key pressed.
"r" or "R" gives you 82, which is "R", you can look at KeyboardEvent.shiftKey,
but you don't have access to capslock...
Maybe you want to use numbers, but of course NumPad will not give you the same than
"normal" numbers ...
Now if you use something else than letter, for exemple "?",
on a QWERTY keyboard "/" and "?" gives you 191,
on a AZERTY keyboard "," and "?" gives you 188, so we have to stick to letters.
This was for keydown and keyup events, keypressed event return the real char
(lower "a", "/", "?", ...) but it fails in some cases
The only non broken property is KeyboardEvent.key,
but it's only supported since Chrome 51, Opera 38, and not supported by Safari
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
A good reference & test:
http://unixpapa.com/js/testkey.html
http://unixpapa.com/js/key.html
Signed-off-by: Etienne CHAMPETIER <champetier.etienne@gmail.com>
2016-07-13 12:22:57 +00:00
|
|
|
// try to fallback (0-9A-Za-z and QWERTY keyboard)
|
|
|
|
switch (e.which) {
|
|
|
|
case 27:
|
2017-10-12 23:02:29 +00:00
|
|
|
return 'Escape';
|
Improve keyboard shortcut handling
Use KeyboardEvent.key if available,
match both lower and upper case letters to keep previous behaviour
KeyboardEvent is a mess.
KeyboardEvent.which gives you, in theory, a decimal representation of the key pressed.
"r" or "R" gives you 82, which is "R", you can look at KeyboardEvent.shiftKey,
but you don't have access to capslock...
Maybe you want to use numbers, but of course NumPad will not give you the same than
"normal" numbers ...
Now if you use something else than letter, for exemple "?",
on a QWERTY keyboard "/" and "?" gives you 191,
on a AZERTY keyboard "," and "?" gives you 188, so we have to stick to letters.
This was for keydown and keyup events, keypressed event return the real char
(lower "a", "/", "?", ...) but it fails in some cases
The only non broken property is KeyboardEvent.key,
but it's only supported since Chrome 51, Opera 38, and not supported by Safari
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
A good reference & test:
http://unixpapa.com/js/testkey.html
http://unixpapa.com/js/key.html
Signed-off-by: Etienne CHAMPETIER <champetier.etienne@gmail.com>
2016-07-13 12:22:57 +00:00
|
|
|
case 191:
|
2017-10-12 23:02:29 +00:00
|
|
|
return e.shiftKey ? '?' : '/';
|
Improve keyboard shortcut handling
Use KeyboardEvent.key if available,
match both lower and upper case letters to keep previous behaviour
KeyboardEvent is a mess.
KeyboardEvent.which gives you, in theory, a decimal representation of the key pressed.
"r" or "R" gives you 82, which is "R", you can look at KeyboardEvent.shiftKey,
but you don't have access to capslock...
Maybe you want to use numbers, but of course NumPad will not give you the same than
"normal" numbers ...
Now if you use something else than letter, for exemple "?",
on a QWERTY keyboard "/" and "?" gives you 191,
on a AZERTY keyboard "," and "?" gives you 188, so we have to stick to letters.
This was for keydown and keyup events, keypressed event return the real char
(lower "a", "/", "?", ...) but it fails in some cases
The only non broken property is KeyboardEvent.key,
but it's only supported since Chrome 51, Opera 38, and not supported by Safari
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
A good reference & test:
http://unixpapa.com/js/testkey.html
http://unixpapa.com/js/key.html
Signed-off-by: Etienne CHAMPETIER <champetier.etienne@gmail.com>
2016-07-13 12:22:57 +00:00
|
|
|
}
|
2017-10-12 23:02:29 +00:00
|
|
|
if (e.shiftKey || e.type === 'keypress') {
|
Improve keyboard shortcut handling
Use KeyboardEvent.key if available,
match both lower and upper case letters to keep previous behaviour
KeyboardEvent is a mess.
KeyboardEvent.which gives you, in theory, a decimal representation of the key pressed.
"r" or "R" gives you 82, which is "R", you can look at KeyboardEvent.shiftKey,
but you don't have access to capslock...
Maybe you want to use numbers, but of course NumPad will not give you the same than
"normal" numbers ...
Now if you use something else than letter, for exemple "?",
on a QWERTY keyboard "/" and "?" gives you 191,
on a AZERTY keyboard "," and "?" gives you 188, so we have to stick to letters.
This was for keydown and keyup events, keypressed event return the real char
(lower "a", "/", "?", ...) but it fails in some cases
The only non broken property is KeyboardEvent.key,
but it's only supported since Chrome 51, Opera 38, and not supported by Safari
https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
A good reference & test:
http://unixpapa.com/js/testkey.html
http://unixpapa.com/js/key.html
Signed-off-by: Etienne CHAMPETIER <champetier.etienne@gmail.com>
2016-07-13 12:22:57 +00:00
|
|
|
return String.fromCharCode(e.which);
|
|
|
|
}
|
2017-10-12 23:02:29 +00:00
|
|
|
|
|
|
|
return String.fromCharCode(e.which).toLowerCase();
|
|
|
|
|
2016-08-29 03:59:09 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Adds the given shortcut to the help dialog.
|
|
|
|
*
|
|
|
|
* @param shortcutChar the shortcut character
|
|
|
|
* @param shortcutDescriptionKey the description of the shortcut
|
|
|
|
* @private
|
|
|
|
*/
|
2017-10-12 23:02:29 +00:00
|
|
|
_addShortcutToHelp(shortcutChar, shortcutDescriptionKey) {
|
2017-11-13 22:58:00 +00:00
|
|
|
_shortcutsHelp.set(shortcutChar, shortcutDescriptionKey);
|
2017-10-12 23:02:29 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialise global shortcuts.
|
|
|
|
* Global shortcuts are shortcuts for features that don't have a button or
|
|
|
|
* link associated with the action. In other words they represent actions
|
|
|
|
* triggered _only_ with a shortcut.
|
|
|
|
*/
|
|
|
|
_initGlobalShortcuts() {
|
|
|
|
this.registerShortcut('?', null, () => {
|
2018-01-03 21:24:07 +00:00
|
|
|
sendAnalytics(createShortcutEvent('help'));
|
2018-03-07 00:28:19 +00:00
|
|
|
this.openDialog();
|
2017-10-12 23:02:29 +00:00
|
|
|
}, 'keyboardShortcuts.toggleShortcuts');
|
|
|
|
|
|
|
|
// register SPACE shortcut in two steps to insure visibility of help
|
|
|
|
// message
|
|
|
|
this.registerShortcut(' ', null, () => {
|
2018-01-03 21:24:07 +00:00
|
|
|
sendAnalytics(createShortcutEvent('push.to.talk', RELEASED));
|
|
|
|
logger.log('Talk shortcut released');
|
2017-10-12 23:02:29 +00:00
|
|
|
APP.conference.muteAudio(true);
|
|
|
|
});
|
|
|
|
this._addShortcutToHelp('SPACE', 'keyboardShortcuts.pushToTalk');
|
|
|
|
|
|
|
|
if (!interfaceConfig.filmStripOnly) {
|
|
|
|
this.registerShortcut('T', null, () => {
|
2018-01-03 21:24:07 +00:00
|
|
|
sendAnalytics(createShortcutEvent('speaker.stats'));
|
2017-10-12 23:02:29 +00:00
|
|
|
APP.store.dispatch(toggleDialog(SpeakerStats, {
|
|
|
|
conference: APP.conference
|
|
|
|
}));
|
|
|
|
}, 'keyboardShortcuts.showSpeakerStats');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* FIXME: Currently focus keys are directly implemented below in
|
|
|
|
* onkeyup. They should be moved to the SmallVideo instead.
|
|
|
|
*/
|
|
|
|
this._addShortcutToHelp('0', 'keyboardShortcuts.focusLocal');
|
|
|
|
this._addShortcutToHelp('1-9', 'keyboardShortcuts.focusRemote');
|
2015-01-22 16:26:05 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-06-14 18:13:41 +00:00
|
|
|
export default KeyboardShortcut;
|