From b8c6a40a3626c26bd8e10e54b09bd9c9855e5fe3 Mon Sep 17 00:00:00 2001 From: Jason Henriquez Date: Sat, 19 Oct 2024 21:20:40 -0500 Subject: [PATCH 01/15] MHave fullscreen persist when videos autoplay --- .../ft-shaka-video-player/ft-shaka-video-player.js | 9 +++++++-- src/renderer/views/Watch/Watch.js | 4 +++- src/renderer/views/Watch/Watch.vue | 3 +++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js index 4c3c10f96..9424026ee 100644 --- a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js +++ b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js @@ -106,6 +106,10 @@ export default defineComponent({ vrProjection: { type: String, default: null + }, + startInFullwindow: { + type: Boolean, + default: false } }, emits: [ @@ -139,7 +143,7 @@ export default defineComponent({ const isLive = ref(false) const useOverFlowMenu = ref(false) - const fullWindowEnabled = ref(false) + const fullWindowEnabled = ref(props.startInFullwindow) const forceAspectRatio = ref(false) const activeLegacyFormat = shallowRef(null) @@ -1042,7 +1046,7 @@ export default defineComponent({ navigator.mediaSession.playbackState = 'none' } - emit('ended') + emit('ended', fullWindowEnabled.value) } function updateVolume() { @@ -2350,6 +2354,7 @@ export default defineComponent({ registerLegacyQualitySelection() registerStatsButton() + if (ui.isMobile()) { useOverFlowMenu.value = true } else { diff --git a/src/renderer/views/Watch/Watch.js b/src/renderer/views/Watch/Watch.js index 71f0c454c..7a2c1c1d8 100644 --- a/src/renderer/views/Watch/Watch.js +++ b/src/renderer/views/Watch/Watch.js @@ -66,6 +66,7 @@ export default defineComponent({ }, data: function () { return { + isInFullwindow: false, isLoading: true, firstLoad: true, useTheatreMode: false, @@ -1181,7 +1182,8 @@ export default defineComponent({ this.activeFormat = 'audio' }, - handleVideoEnded: function () { + handleVideoEnded: function (isInFullwindow = false) { + this.isInFullwindow = isInFullwindow if ((!this.watchingPlaylist || !this.autoplayPlaylists) && !this.playNextVideo) { return } diff --git a/src/renderer/views/Watch/Watch.vue b/src/renderer/views/Watch/Watch.vue index e9c60192c..e51c8cb43 100644 --- a/src/renderer/views/Watch/Watch.vue +++ b/src/renderer/views/Watch/Watch.vue @@ -34,11 +34,14 @@ :theatre-possible="theatrePossible" :use-theatre-mode="useTheatreMode" :vr-projection="vrProjection" + :start-in-fullwindow="isInFullwindow" class="videoPlayer" @error="handlePlayerError" @loaded="handleVideoLoaded" @timeupdate="updateCurrentChapter" @ended="handleVideoEnded" + @set-fullscreen="e => isInFullscreen = e" + @set-fullwindow="e => isInFullwindow = e" @toggle-theatre-mode="useTheatreMode = !useTheatreMode" />
Date: Sun, 20 Oct 2024 10:40:19 -0500 Subject: [PATCH 02/15] Have fullscreen and PiP be re-requested on autoplay when they are open --- src/constants.js | 3 ++ src/main/index.js | 8 ++++ .../ft-shaka-video-player.js | 37 +++++++++++++++++-- .../ft-shaka-video-player.vue | 2 + src/renderer/views/Watch/Watch.js | 17 +++++++-- src/renderer/views/Watch/Watch.vue | 7 ++-- 6 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/constants.js b/src/constants.js index f45e30fb8..38e1e7a1e 100644 --- a/src/constants.js +++ b/src/constants.js @@ -15,6 +15,9 @@ const IpcChannels = { APP_READY: 'app-ready', RELAUNCH_REQUEST: 'relaunch-request', + REQUEST_FULLSCREEN: 'request-fullscreen', + REQUEST_PIP: 'request_pip', + SEARCH_INPUT_HANDLING_READY: 'search-input-handling-ready', UPDATE_SEARCH_INPUT_TEXT: 'update-search-input-text', diff --git a/src/main/index.js b/src/main/index.js index 10ca46343..e98a9a331 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -927,6 +927,14 @@ function runApp() { return app.getPath('pictures') }) + ipcMain.on(IpcChannels.REQUEST_FULLSCREEN, ({ sender }) => { + sender.executeJavaScript('document.getElementById("video").requestFullscreen({navigationUI: "hide"})', true) + }) + + ipcMain.on(IpcChannels.REQUEST_PIP, ({ sender }) => { + sender.executeJavaScript('document.getElementById("video").requestPictureInPicture()', true) + }) + ipcMain.handle(IpcChannels.SHOW_OPEN_DIALOG, async ({ sender }, options) => { const senderWindow = findSenderWindow(sender) if (senderWindow) { diff --git a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js index 9424026ee..c7d55ef74 100644 --- a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js +++ b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.js @@ -107,15 +107,24 @@ export default defineComponent({ type: String, default: null }, + startInFullscreen: { + type: Boolean, + default: false + }, startInFullwindow: { type: Boolean, default: false + }, + startInPip: { + type: Boolean, + default: false } }, emits: [ 'error', 'loaded', 'ended', + 'reset-start-in-viewing-mode', 'timeupdate', 'toggle-theatre-mode' ], @@ -143,11 +152,16 @@ export default defineComponent({ const isLive = ref(false) const useOverFlowMenu = ref(false) - const fullWindowEnabled = ref(props.startInFullwindow) const forceAspectRatio = ref(false) const activeLegacyFormat = shallowRef(null) + const fullWindowEnabled = ref(props.startInFullwindow) + let startInFullscreen = props.startInFullscreen + let startInPip = props.startInPip + + emit('reset-start-in-viewing-mode') + /** * @type {{ * url: string, @@ -1046,7 +1060,17 @@ export default defineComponent({ navigator.mediaSession.playbackState = 'none' } - emit('ended', fullWindowEnabled.value) + const controls = ui.getControls() + emit('ended', controls.isFullScreenEnabled(), fullWindowEnabled.value, controls.isPiPEnabled()) + } + + function handleCanPlay() { + // PiP can only be activated once the video's readState and video track are populated + if (startInPip && ui.getControls().isPiPAllowed() && process.env.IS_ELECTRON) { + startInPip = false + const { ipcRenderer } = require('electron') + ipcRenderer.send(IpcChannels.REQUEST_PIP) + } } function updateVolume() { @@ -1754,7 +1778,7 @@ export default defineComponent({ /** * As shaka-player doesn't let you unregister custom control factories, * overwrite them with `null` instead so the referenced objects - * (e.g. {@linkcode events}, {@linkcode fullWindowEnabled}) can get gargabe collected + * (e.g. {@linkcode events}, {@linkcode fullWindowEnabled}) can get garbage collected */ function cleanUpCustomPlayerControls() { shakaControls.registerElement('ft_audio_tracks', null) @@ -2543,6 +2567,12 @@ export default defineComponent({ if (props.chapters.length > 0) { createChapterMarkers() } + + if (startInFullscreen && process.env.IS_ELECTRON) { + startInFullscreen = false + const { ipcRenderer } = require('electron') + ipcRenderer.send(IpcChannels.REQUEST_FULLSCREEN) + } } watch( @@ -2781,6 +2811,7 @@ export default defineComponent({ handlePlay, handlePause, + handleCanPlay, handleEnded, updateVolume, handleTimeupdate, diff --git a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue index 4b9519c77..208a656fa 100644 --- a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue +++ b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue @@ -9,6 +9,7 @@ >
+ + + + + + - - - - -
Date: Sun, 20 Oct 2024 12:16:45 -0500 Subject: [PATCH 04/15] Implement external player default viewing mode Current limitations: does not work for the search bar, randomly encountered YT video links (e.g., in descriptions), or the video thumbnail link in the playlist list view. --- .../distraction-settings.js | 1 - .../ft-list-playlist/ft-list-playlist.js | 4 ++++ .../components/ft-list-video/ft-list-video.js | 13 +++++++++++++ .../components/ft-list-video/ft-list-video.vue | 18 ++++++++++++------ src/renderer/views/Watch/Watch.js | 1 - 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/renderer/components/distraction-settings/distraction-settings.js b/src/renderer/components/distraction-settings/distraction-settings.js index eb584eaff..002631739 100644 --- a/src/renderer/components/distraction-settings/distraction-settings.js +++ b/src/renderer/components/distraction-settings/distraction-settings.js @@ -203,7 +203,6 @@ export default defineComponent({ 'updateHideLiveChat', 'updateHideActiveSubscriptions', 'updatePlayNextVideo', - 'updateDefaultViewingMode', 'updateHideVideoDescription', 'updateHideComments', 'updateHideCommentPhotos', diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.js b/src/renderer/components/ft-list-playlist/ft-list-playlist.js index 98747cef3..1642292fa 100644 --- a/src/renderer/components/ft-list-playlist/ft-list-playlist.js +++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.js @@ -60,6 +60,10 @@ export default defineComponent({ return this.$store.getters.getExternalPlayer }, + externalPlayerIsDefaultViewingMode: function () { + return this.$store.getters.getDefaultViewingMode === 'external_player' + }, + defaultPlayback: function () { return this.$store.getters.getDefaultPlayback }, diff --git a/src/renderer/components/ft-list-video/ft-list-video.js b/src/renderer/components/ft-list-video/ft-list-video.js index 67acb17bb..0963c6fd5 100644 --- a/src/renderer/components/ft-list-video/ft-list-video.js +++ b/src/renderer/components/ft-list-video/ft-list-video.js @@ -376,6 +376,10 @@ export default defineComponent({ return this.$store.getters.getExternalPlayer }, + externalPlayerIsDefaultViewingMode: function () { + return this.$store.getters.getDefaultViewingMode === 'external_player' + }, + defaultPlayback: function () { return this.$store.getters.getDefaultPlayback }, @@ -478,6 +482,10 @@ export default defineComponent({ return this.isInQuickBookmarkPlaylist ? 'base favorite' : 'base' }, + watchPageLinkType() { + return this.externalPlayerIsDefaultViewingMode ? 'a' : 'router-link' + }, + watchPageLinkTo() { // For `router-link` attribute `to` return { @@ -530,6 +538,11 @@ export default defineComponent({ } }, methods: { + handleWatchPageLinkClick: function() { + if (this.externalPlayerIsDefaultViewingMode) { + this.handleExternalPlayer() + } + }, fetchDeArrowThumbnail: async function() { if (this.thumbnailPreference === 'hidden') { return } const videoId = this.id diff --git a/src/renderer/components/ft-list-video/ft-list-video.vue b/src/renderer/components/ft-list-video/ft-list-video.vue index 7d63dcf98..a4a4adf6a 100644 --- a/src/renderer/components/ft-list-video/ft-list-video.vue +++ b/src/renderer/components/ft-list-video/ft-list-video.vue @@ -10,11 +10,14 @@ >
- + - +
-

{{ displayTitle }}

-
+
Date: Sun, 20 Oct 2024 12:39:51 -0500 Subject: [PATCH 05/15] Disable & hide 'External Player' default viewing mode when no external player is set This will prevent issues with users who accidentally change this setting and report that clicking on videos results in errors. --- .../ft-list-playlist/ft-list-playlist.js | 4 --- .../components/ft-list-video/ft-list-video.js | 2 +- .../player-settings/player-settings.js | 36 +++++++++++++------ static/locales/en-US.yaml | 1 + 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/renderer/components/ft-list-playlist/ft-list-playlist.js b/src/renderer/components/ft-list-playlist/ft-list-playlist.js index 1642292fa..98747cef3 100644 --- a/src/renderer/components/ft-list-playlist/ft-list-playlist.js +++ b/src/renderer/components/ft-list-playlist/ft-list-playlist.js @@ -60,10 +60,6 @@ export default defineComponent({ return this.$store.getters.getExternalPlayer }, - externalPlayerIsDefaultViewingMode: function () { - return this.$store.getters.getDefaultViewingMode === 'external_player' - }, - defaultPlayback: function () { return this.$store.getters.getDefaultPlayback }, diff --git a/src/renderer/components/ft-list-video/ft-list-video.js b/src/renderer/components/ft-list-video/ft-list-video.js index 0963c6fd5..579fd0647 100644 --- a/src/renderer/components/ft-list-video/ft-list-video.js +++ b/src/renderer/components/ft-list-video/ft-list-video.js @@ -377,7 +377,7 @@ export default defineComponent({ }, externalPlayerIsDefaultViewingMode: function () { - return this.$store.getters.getDefaultViewingMode === 'external_player' + return this.externalPlayer !== '' && this.$store.getters.getDefaultViewingMode === 'external_player' }, defaultPlayback: function () { diff --git a/src/renderer/components/player-settings/player-settings.js b/src/renderer/components/player-settings/player-settings.js index 6428fb264..118d34987 100644 --- a/src/renderer/components/player-settings/player-settings.js +++ b/src/renderer/components/player-settings/player-settings.js @@ -49,14 +49,6 @@ export default defineComponent({ 0.5, 1 ], - viewingModeValues: [ - 'default', - 'theatre', - 'fullscreen', - 'fullwindow', - 'pip', - 'external_player' - ], screenshotFormatNames: [ 'PNG', 'JPEG' @@ -68,6 +60,14 @@ export default defineComponent({ screenshotFolderPlaceholder: '', screenshotFilenameExample: '', screenshotDefaultPattern: '%Y%M%D-%H%N%S', + viewingModeValues: [ + 'default', + 'theatre', + 'fullscreen', + 'fullwindow', + 'pip', + 'external_player' + ] } }, computed: { @@ -128,9 +128,18 @@ export default defineComponent({ }, defaultViewingMode: function () { + const defaultViewingMode = this.$store.getters.getDefaultViewingMode + if (defaultViewingMode === 'external_player' && this.externalPlayer === '') { + return 'default' + } + return this.$store.getters.getDefaultViewingMode }, + externalPlayer: function () { + return this.$store.getters.getExternalPlayer + }, + hideRecommendedVideos: function () { return this.$store.getters.getHideRecommendedVideos }, @@ -186,14 +195,21 @@ export default defineComponent({ }, viewingModeNames: function () { - return [ + const viewingModeNames = [ this.$t('Settings.General Settings.Thumbnail Preference.Default'), this.$t('Video.Player.Theatre Mode'), this.$t('Settings.Player Settings.Default Viewing Mode.Fullscreen'), this.$t('Video.Player.Full Window'), this.$t('Settings.Player Settings.Default Viewing Mode.Picture in Picture'), - this.$t('Settings.External Player Settings.External Player'), ] + + if (this.externalPlayer !== '') { + viewingModeNames.push( + this.$t('Settings.Player Settings.Default Viewing Mode.External Player', { externalPlayerName: this.externalPlayer }) + ) + } + + return viewingModeNames }, enableScreenshot: function() { diff --git a/static/locales/en-US.yaml b/static/locales/en-US.yaml index b975201bd..11794b3c3 100644 --- a/static/locales/en-US.yaml +++ b/static/locales/en-US.yaml @@ -406,6 +406,7 @@ Settings: Default Viewing Mode: Default Viewing Mode Fullscreen: Fullscreen Picture in Picture: Picture in Picture + External Player: External Player ({externalPlayerName}) Scroll Volume Over Video Player: Scroll Volume Over Video Player Scroll Playback Rate Over Video Player: Scroll Playback Rate Over Video Player Skip by Scrolling Over Video Player: Skip by Scrolling Over Video Player From 034733664773ee81cce0304d670a6ec6e1bb0663 Mon Sep 17 00:00:00 2001 From: Jason Henriquez Date: Sun, 20 Oct 2024 17:44:35 -0500 Subject: [PATCH 06/15] Fix fullscreen issue with icons by calling requestFullscreen on videoContainer element --- src/main/index.js | 2 +- .../components/ft-shaka-video-player/ft-shaka-video-player.vue | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/index.js b/src/main/index.js index e98a9a331..9b233e429 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -928,7 +928,7 @@ function runApp() { }) ipcMain.on(IpcChannels.REQUEST_FULLSCREEN, ({ sender }) => { - sender.executeJavaScript('document.getElementById("video").requestFullscreen({navigationUI: "hide"})', true) + sender.executeJavaScript('document.getElementById("videoContainer").requestFullscreen({navigationUI: "hide"})', true) }) ipcMain.on(IpcChannels.REQUEST_PIP, ({ sender }) => { diff --git a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue index 208a656fa..5a40c070a 100644 --- a/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue +++ b/src/renderer/components/ft-shaka-video-player/ft-shaka-video-player.vue @@ -1,5 +1,6 @@