-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add keyboard shortcuts to titles #5857
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 17 commits
fe5de7f
3134053
0d3882e
443c4af
42c3128
7c379e2
764cace
6798c3a
6f8d212
16693ea
cf263fb
d642682
348100d
dd1fffa
89b6861
fdae9b4
304fa82
532fcc7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ import shaka from 'shaka-player' | |
import { useI18n } from '../../composables/use-i18n-polyfill' | ||
|
||
import store from '../../store/index' | ||
import { IpcChannels } from '../../../constants' | ||
import { IpcChannels, KeyboardShortcuts } from '../../../constants' | ||
import { AudioTrackSelection } from './player-components/AudioTrackSelection' | ||
import { FullWindowButton } from './player-components/FullWindowButton' | ||
import { LegacyQualitySelection } from './player-components/LegacyQualitySelection' | ||
|
@@ -22,6 +22,7 @@ import { | |
translateSponsorBlockCategory | ||
} from '../../helpers/player/utils' | ||
import { | ||
addKeyboardShortcutToActionTitle, | ||
getPicturesPath, | ||
showSaveDialog, | ||
showToast | ||
|
@@ -39,6 +40,23 @@ const RequestType = shaka.net.NetworkingEngine.RequestType | |
const AdvancedRequestType = shaka.net.NetworkingEngine.AdvancedRequestType | ||
const TrackLabelFormat = shaka.ui.Overlay.TrackLabelFormat | ||
|
||
/* | ||
Mapping of Shaka localization keys for control labels to FreeTube shortcuts. | ||
See: https://github.com/shaka-project/shaka-player/blob/main/ui/locales/en.json | ||
*/ | ||
const shakaControlKeysToShortcuts = { | ||
MUTE: KeyboardShortcuts.VIDEO_PLAYER.GENERAL.MUTE, | ||
UNMUTE: KeyboardShortcuts.VIDEO_PLAYER.GENERAL.MUTE, | ||
PLAY: KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.PLAY, | ||
PAUSE: KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.PLAY, | ||
PICTURE_IN_PICTURE: KeyboardShortcuts.VIDEO_PLAYER.GENERAL.PICTURE_IN_PICTURE, | ||
ENTER_PICTURE_IN_PICTURE: KeyboardShortcuts.VIDEO_PLAYER.GENERAL.PICTURE_IN_PICTURE, | ||
EXIT_PICTURE_IN_PICTURE: KeyboardShortcuts.VIDEO_PLAYER.GENERAL.PICTURE_IN_PICTURE, | ||
CAPTIONS: KeyboardShortcuts.VIDEO_PLAYER.GENERAL.CAPTIONS, | ||
FULL_SCREEN: KeyboardShortcuts.VIDEO_PLAYER.GENERAL.FULLSCREEN, | ||
EXIT_FULL_SCREEN: KeyboardShortcuts.VIDEO_PLAYER.GENERAL.FULLSCREEN | ||
} | ||
|
||
/** @type {Map<string, string>} */ | ||
const LOCALE_MAPPINGS = new Map(process.env.SHAKA_LOCALE_MAPPINGS) | ||
|
||
|
@@ -969,7 +987,7 @@ export default defineComponent({ | |
* @param {string} locale | ||
*/ | ||
async function setLocale(locale) { | ||
// For most of FreeTube's locales their is an equivalent one in shaka-player, | ||
// For most of FreeTube's locales, there is an equivalent one in shaka-player, | ||
// however if there isn't one we should fall back to US English. | ||
// At the time of writing "et", "eu", "gl", "is" don't have any translations | ||
const shakaLocale = LOCALE_MAPPINGS.get(locale) ?? 'en' | ||
|
@@ -990,6 +1008,27 @@ export default defineComponent({ | |
|
||
localization.changeLocale([shakaLocale]) | ||
|
||
// Add the keyboard shortcut to the label for the default Shaka controls | ||
|
||
const shakaControlKeysToShortcutLocalizations = new Map() | ||
Object.entries(shakaControlKeysToShortcuts).forEach(([shakaControlKey, shortcut]) => { | ||
const originalLocalization = localization.resolve(shakaControlKey) | ||
if (originalLocalization === '') { | ||
// e.g., A Shaka localization key in shakaControlKeysToShortcuts has fallen out of date and need to be updated | ||
console.error('Mising Shaka localization key "%s"', shakaControlKey) | ||
return | ||
} | ||
|
||
const localizationWithShortcut = addKeyboardShortcutToActionTitle( | ||
originalLocalization, | ||
shortcut | ||
) | ||
|
||
shakaControlKeysToShortcutLocalizations.set(shakaControlKey, localizationWithShortcut) | ||
}) | ||
|
||
localization.insert(shakaLocale, shakaControlKeysToShortcutLocalizations) | ||
Comment on lines
+1011
to
+1030
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Non-blocking: For locales that shaka-player doesn't pre-bundle (so the ones loaded by the code above), we call |
||
|
||
events.dispatchEvent(new CustomEvent('localeChanged')) | ||
} | ||
|
||
|
@@ -1959,55 +1998,47 @@ export default defineComponent({ | |
|
||
const video_ = video.value | ||
|
||
switch (event.key) { | ||
switch (event.key.toLowerCase()) { | ||
case ' ': | ||
case 'Spacebar': // older browsers might return spacebar instead of a space character | ||
case 'K': | ||
case 'k': | ||
case 'spacebar': // older browsers might return spacebar instead of a space character | ||
case KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.PLAY: | ||
// Toggle Play/Pause | ||
event.preventDefault() | ||
video_.paused ? video_.play() : video_.pause() | ||
break | ||
case 'J': | ||
case 'j': | ||
case KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.LARGE_REWIND: | ||
// Rewind by 2x the time-skip interval (in seconds) | ||
event.preventDefault() | ||
seekBySeconds(-defaultSkipInterval.value * video_.playbackRate * 2) | ||
break | ||
case 'L': | ||
case 'l': | ||
case KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.LARGE_FAST_FORWARD: | ||
// Fast-Forward by 2x the time-skip interval (in seconds) | ||
event.preventDefault() | ||
seekBySeconds(defaultSkipInterval.value * video_.playbackRate * 2) | ||
break | ||
case 'O': | ||
case 'o': | ||
case KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.DECREASE_VIDEO_SPEED: | ||
// Decrease playback rate by user configured interval | ||
event.preventDefault() | ||
changePlayBackRate(-videoPlaybackRateInterval.value) | ||
break | ||
case 'P': | ||
case 'p': | ||
case KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.INCREASE_VIDEO_SPEED: | ||
// Increase playback rate by user configured interval | ||
event.preventDefault() | ||
changePlayBackRate(videoPlaybackRateInterval.value) | ||
break | ||
case 'F': | ||
case 'f': | ||
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.FULLSCREEN: | ||
// Toggle full screen | ||
event.preventDefault() | ||
ui.getControls().toggleFullScreen() | ||
break | ||
case 'M': | ||
case 'm': | ||
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.MUTE: | ||
// Toggle mute only if metakey is not pressed | ||
if (!event.metaKey) { | ||
event.preventDefault() | ||
video_.muted = !video_.muted | ||
} | ||
break | ||
case 'C': | ||
case 'c': | ||
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.CAPTIONS: | ||
// Toggle caption/subtitles | ||
if (player.getTextTracks().length > 0) { | ||
event.preventDefault() | ||
|
@@ -2016,17 +2047,17 @@ export default defineComponent({ | |
player.setTextTrackVisibility(!currentlyVisible) | ||
} | ||
break | ||
case 'ArrowUp': | ||
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.VOLUME_UP: | ||
// Increase volume | ||
event.preventDefault() | ||
changeVolume(0.05) | ||
break | ||
case 'ArrowDown': | ||
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.VOLUME_DOWN: | ||
// Decrease Volume | ||
event.preventDefault() | ||
changeVolume(-0.05) | ||
break | ||
case 'ArrowLeft': | ||
case KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.SMALL_REWIND: | ||
event.preventDefault() | ||
if (canChapterJump(event, 'previous')) { | ||
// Jump to the previous chapter | ||
|
@@ -2036,7 +2067,7 @@ export default defineComponent({ | |
seekBySeconds(-defaultSkipInterval.value * video_.playbackRate) | ||
} | ||
break | ||
case 'ArrowRight': | ||
case KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.SMALL_FAST_FORWARD: | ||
event.preventDefault() | ||
if (canChapterJump(event, 'next')) { | ||
// Jump to the next chapter | ||
|
@@ -2046,8 +2077,7 @@ export default defineComponent({ | |
seekBySeconds(defaultSkipInterval.value * video_.playbackRate) | ||
} | ||
break | ||
case 'I': | ||
case 'i': | ||
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.PICTURE_IN_PICTURE: | ||
// Toggle picture in picture | ||
if (props.format !== 'audio') { | ||
const controls = ui.getControls() | ||
|
@@ -2080,29 +2110,28 @@ export default defineComponent({ | |
} | ||
break | ||
} | ||
case ',': | ||
case KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.LAST_FRAME: | ||
// `⌘+,` is for settings in MacOS | ||
if (!event.metaKey) { | ||
event.preventDefault() | ||
// Return to previous frame | ||
frameByFrame(-1) | ||
} | ||
break | ||
case '.': | ||
case KeyboardShortcuts.VIDEO_PLAYER.PLAYBACK.NEXT_FRAME: | ||
event.preventDefault() | ||
// Advance to next frame | ||
frameByFrame(1) | ||
break | ||
case 'D': | ||
case 'd': | ||
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.STATS: | ||
// Toggle stats display | ||
event.preventDefault() | ||
|
||
events.dispatchEvent(new CustomEvent('setStatsVisibility', { | ||
detail: !showStats.value | ||
})) | ||
break | ||
case 'Escape': | ||
case 'escape': | ||
// Exit full window | ||
if (fullWindowEnabled.value) { | ||
event.preventDefault() | ||
|
@@ -2112,16 +2141,14 @@ export default defineComponent({ | |
})) | ||
} | ||
break | ||
case 'S': | ||
case 's': | ||
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.FULLWINDOW: | ||
// Toggle full window mode | ||
event.preventDefault() | ||
events.dispatchEvent(new CustomEvent('setFullWindow', { | ||
detail: !fullWindowEnabled.value | ||
})) | ||
break | ||
case 'T': | ||
case 't': | ||
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.THEATRE_MODE: | ||
// Toggle theatre mode | ||
if (props.theatrePossible) { | ||
event.preventDefault() | ||
|
@@ -2131,8 +2158,7 @@ export default defineComponent({ | |
})) | ||
} | ||
break | ||
case 'U': | ||
case 'u': | ||
case KeyboardShortcuts.VIDEO_PLAYER.GENERAL.TAKE_SCREENSHOT: | ||
if (process.env.IS_ELECTRON && enableScreenshot.value && props.format !== 'audio') { | ||
event.preventDefault() | ||
// Take screenshot | ||
|
Uh oh!
There was an error while loading. Please reload this page.