Compare commits

...

2 commits

Author SHA1 Message Date
saltrafael
4c665b5705
Add Numbered Steps video key events 2021-08-31 10:19:21 -03:00
saltrafael
21372037b4
Fix inital display of control bar text 2021-08-31 09:52:15 -03:00

View file

@ -103,6 +103,19 @@ const SMALL_J_KEYCODE = 74;
const SMALL_K_KEYCODE = 75; const SMALL_K_KEYCODE = 75;
const SMALL_L_KEYCODE = 76; const SMALL_L_KEYCODE = 76;
const numberCodes = {
'48': 0,
'49': 1,
'50': 2,
'51': 3,
'52': 4,
'53': 5,
'54': 6,
'55': 7,
'56': 8,
'57': 9,
};
const FULLSCREEN_KEYCODE = SMALL_F_KEYCODE; const FULLSCREEN_KEYCODE = SMALL_F_KEYCODE;
const MUTE_KEYCODE = SMALL_M_KEYCODE; const MUTE_KEYCODE = SMALL_M_KEYCODE;
const THEATER_MODE_KEYCODE = SMALL_T_KEYCODE; const THEATER_MODE_KEYCODE = SMALL_T_KEYCODE;
@ -282,27 +295,42 @@ export default React.memo<Props>(function VideoJs(props: Props) {
} }
} }
function resolveCtrlText(e) { // Override the player's control text. We override to:
// Override the player's control text. We override to: // 1. Add keyboard shortcut to the tool-tip.
// 1. Add keyboard shortcut to the tool-tip. // 2. Override videojs' i18n and use our own (don't want to have 2 systems).
// 2. Override videojs' i18n and use our own (don't want to have 2 systems). //
// // Notes:
// Notes: // - For dynamic controls (e.g. play/pause), those unfortunately need to be
// - For dynamic controls (e.g. play/pause), those unfortunately need to be // updated again at their event-listener level (that's just the way videojs
// updated again at their event-listener level (that's just the way videojs // updates the text), hence the need to listen to 'play', 'pause' and 'volumechange'
// updates the text), hence the need to listen to 'play', 'pause' and 'volumechange' // on top of just 'loadstart'.
// on top of just 'loadstart'. // - videojs changes the MuteToggle text at 'loadstart', so this was chosen
// - videojs changes the MuteToggle text at 'loadstart', so this was chosen // as the listener to update static texts.
// as the listener to update static texts. function resolveCtrlText(e, initialPlay) {
const player = playerRef.current; const player = playerRef.current;
if (player) { if (player) {
const controlBar = player.getChild('controlBar'); const controlBar = player.getChild('controlBar');
switch (e.type) { switch (e.type) {
case 'play': case 'play':
controlBar.getChild('PlayToggle').controlText(__('Pause (space)')); controlBar.getChild('PlayToggle').controlText(__('Pause (space/k)'));
if (initialPlay) {
controlBar.getChild('PlaybackRateMenuButton').controlText(__('Playback Rate (<, >)'));
controlBar.getChild('QualityButton').controlText(__('Quality'));
resolveCtrlText({ type: 'fullscreenchange' });
resolveCtrlText({ type: 'volumechange' });
resolveCtrlText({ type: 'fullscreenchange' });
// --- Do everything ---
// (1) The 'Theater mode' button should probably be changed to a class
// so that we can use getChild() with a specific name. There might be
// clashes if we add a new button in the future.
// (2) We'll have to get 'makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)'
// as a prop here so we can say "Theater mode|Default mode" instead of
// "Toggle Theater mode".
controlBar.getChild('Button').controlText(__('Toggle Theater mode (t)'));
}
break; break;
case 'pause': case 'pause':
controlBar.getChild('PlayToggle').controlText(__('Play (space)')); controlBar.getChild('PlayToggle').controlText(__('Play (space/k)'));
break; break;
case 'volumechange': case 'volumechange':
controlBar controlBar
@ -316,20 +344,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
.controlText(player.isFullscreen() ? __('Exit Fullscreen (f)') : __('Fullscreen (f)')); .controlText(player.isFullscreen() ? __('Exit Fullscreen (f)') : __('Fullscreen (f)'));
break; break;
case 'loadstart': case 'loadstart':
// --- Do everything --- resolveCtrlText({ type: 'play' }, true);
controlBar.getChild('PlaybackRateMenuButton').controlText(__('Playback Rate (<, >)'));
controlBar.getChild('QualityButton').controlText(__('Quality'));
resolveCtrlText({ type: 'play' });
resolveCtrlText({ type: 'pause' });
resolveCtrlText({ type: 'volumechange' });
resolveCtrlText({ type: 'fullscreenchange' });
// (1) The 'Theater mode' button should probably be changed to a class
// so that we can use getChild() with a specific name. There might be
// clashes if we add a new button in the future.
// (2) We'll have to get 'makeSelectClientSetting(SETTINGS.VIDEO_THEATER_MODE)'
// as a prop here so we can say "Theater mode|Default mode" instead of
// "Toggle Theater mode".
controlBar.getChild('Button').controlText(__('Toggle Theater mode (t)'));
break; break;
default: default:
if (isDev) throw Error('Unexpected: ' + e.type); if (isDev) throw Error('Unexpected: ' + e.type);
@ -347,6 +362,7 @@ export default React.memo<Props>(function VideoJs(props: Props) {
} else { } else {
showTapButton(TAP.NONE); showTapButton(TAP.NONE);
} }
resolveCtrlText({ type: 'play' }, true);
} }
function onVolumeChange() { function onVolumeChange() {
@ -397,19 +413,28 @@ export default React.memo<Props>(function VideoJs(props: Props) {
if (e.keyCode === VOLUME_UP_KEYCODE) volumeUp(); if (e.keyCode === VOLUME_UP_KEYCODE) volumeUp();
if (e.keyCode === VOLUME_DOWN_KEYCODE) volumeDown(); if (e.keyCode === VOLUME_DOWN_KEYCODE) volumeDown();
if (e.keyCode === THEATER_MODE_KEYCODE) toggleTheaterMode(); if (e.keyCode === THEATER_MODE_KEYCODE) toggleTheaterMode();
if (e.keyCode === SEEK_FORWARD_KEYCODE) seekVideo(SEEK_STEP); if (e.keyCode === SEEK_FORWARD_KEYCODE) seekVideo(SEEK_STEP, false);
if (e.keyCode === SEEK_BACKWARD_KEYCODE) seekVideo(-SEEK_STEP); if (e.keyCode === SEEK_BACKWARD_KEYCODE) seekVideo(-SEEK_STEP, false);
if (e.keyCode === SEEK_FORWARD_KEYCODE_5) seekVideo(SEEK_STEP_5); if (e.keyCode === SEEK_FORWARD_KEYCODE_5) seekVideo(SEEK_STEP_5, false);
if (e.keyCode === SEEK_BACKWARD_KEYCODE_5) seekVideo(-SEEK_STEP_5); if (e.keyCode === SEEK_BACKWARD_KEYCODE_5) seekVideo(-SEEK_STEP_5, false);
if (String(e.keyCode) in numberCodes) seekVideo(numberCodes[String(e.keyCode)], true);
} }
function seekVideo(stepSize: number) { function seekVideo(stepSize: number, numberedStep: boolean) {
const player = playerRef.current; const player = playerRef.current;
const videoNode = containerRef.current && containerRef.current.querySelector('video, audio'); const videoNode = containerRef.current && containerRef.current.querySelector('video, audio');
if (!videoNode || !player) return; if (!videoNode || !player) return;
const duration = videoNode.duration; const duration = videoNode.duration;
const numberedStepSize = duration / 10;
const currentTime = videoNode.currentTime; const currentTime = videoNode.currentTime;
const newDuration = currentTime + stepSize;
let newDuration;
if (numberedStep) {
newDuration = numberedStepSize * stepSize;
} else {
newDuration = currentTime + stepSize;
}
if (newDuration < 0) { if (newDuration < 0) {
videoNode.currentTime = 0; videoNode.currentTime = 0;
} else if (newDuration > duration) { } else if (newDuration > duration) {
@ -417,7 +442,8 @@ export default React.memo<Props>(function VideoJs(props: Props) {
} else { } else {
videoNode.currentTime = newDuration; videoNode.currentTime = newDuration;
} }
OVERLAY.showSeekedOverlay(player, Math.abs(stepSize), stepSize > 0);
if (!numberedStep) OVERLAY.showSeekedOverlay(player, Math.abs(stepSize), stepSize > 0);
player.userActive(true); player.userActive(true);
} }