Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
|
4c665b5705 | ||
|
21372037b4 |
1 changed files with 61 additions and 35 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue