From f7c37df7554f2947c7aba783ca2786c1bc7c002d Mon Sep 17 00:00:00 2001 From: w33b Date: Wed, 29 Jul 2026 22:12:51 +0200 Subject: [PATCH] Show subtitles toggle & menu --- resources/js/player.js | 8 ++++ resources/js/player/player-core.js | 63 +++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/resources/js/player.js b/resources/js/player.js index a5d9bed..3b280f0 100644 --- a/resources/js/player.js +++ b/resources/js/player.js @@ -181,6 +181,9 @@ function initPlayer() { }, onLanguageChange: function (lang) { initSubtitles(lang); + if (player) { + player.setSubtitleInstance(subtitleInstance); + } }, onServerChange: function (index) { streamServerIndex = index; @@ -199,6 +202,11 @@ function initPlayer() { window.player = player; + if (player.captionsActive) { + initSubtitles(player.captionLanguage); + player.setSubtitleInstance(subtitleInstance); + } + if (!isMobile()) { player.initThumbnails(vttThumbsUrl); } diff --git a/resources/js/player/player-core.js b/resources/js/player/player-core.js index 7464d69..524d2b3 100644 --- a/resources/js/player/player-core.js +++ b/resources/js/player/player-core.js @@ -272,7 +272,7 @@ export class HStreamPlayer { mainPanel.appendChild(addItem('Quality', this._qualityLabel(this._quality), 'quality')); mainPanel.appendChild(addItem('Playback Speed', this._speedLabel(this.video.playbackRate), 'speed')); - if (this._subtitleTracks.length > 1) { + if (this._subtitleTracks.length >= 1) { mainPanel.appendChild(addItem('Subtitles', this._captionLabel(), 'captions')); } @@ -436,6 +436,7 @@ export class HStreamPlayer { } item.type = 'button'; item.setAttribute('role', 'menuitemradio'); + item.setAttribute('data-srclang', track.srclang); item.innerHTML = `${track.label}`; item.addEventListener('click', (e) => { e.stopPropagation(); @@ -953,21 +954,21 @@ export class HStreamPlayer { toggleCaptions() { this._captionsActive = !this._captionsActive; - if (this.subtitleInstance && this.subtitleInstance.canvas) { - this.subtitleInstance.canvas.style.visibility = this._captionsActive ? 'visible' : 'hidden'; - } - const libassParent = document.querySelector('.libassjs-canvas-parent'); - if (libassParent) { - libassParent.style.visibility = this._captionsActive ? 'visible' : 'hidden'; - } - if (this._captionsActive) { this._captionsBtn.classList.add('hstream-player__button--active'); } else { this._captionsBtn.classList.remove('hstream-player__button--active'); } + var libassParent = document.querySelector('.libassjs-canvas-parent'); + if (libassParent) { + libassParent.style.visibility = this._captionsActive ? 'visible' : 'hidden'; + } else if (this._captionsActive && this._onLanguageChange) { + this._onLanguageChange(this._captionLanguage); + } + localStorage.setItem('hstreamCaptions', this._captionsActive.toString()); + this._updateCaptionsPanel(); if (this._onCaptionsToggle) { this._onCaptionsToggle(this._captionsActive); } @@ -983,6 +984,7 @@ export class HStreamPlayer { if (this._onLanguageChange) { this._onLanguageChange(lang); } + this._updateCaptionsPanel(); } get captionLanguage() { @@ -1062,6 +1064,43 @@ export class HStreamPlayer { } } + _updateCaptionsPanel() { + var captionsPanel = this._menuContainer.querySelector('[data-panel="captions"]'); + if (!captionsPanel) return; + + captionsPanel.querySelectorAll('.hstream-player__menu-item').forEach(function (item) { + item.classList.remove('hstream-player__menu-item--checked'); + item.setAttribute('aria-checked', 'false'); + }); + + if (!this._captionsActive) { + var offItem = captionsPanel.querySelector('.hstream-player__menu-item:not([data-srclang])'); + if (offItem) { + offItem.classList.add('hstream-player__menu-item--checked'); + offItem.setAttribute('aria-checked', 'true'); + } + } else { + var langItem = captionsPanel.querySelector('.hstream-player__menu-item[data-srclang="' + this._captionLanguage + '"]'); + if (langItem) { + langItem.classList.add('hstream-player__menu-item--checked'); + langItem.setAttribute('aria-checked', 'true'); + } + } + + var mainPanel = this._menuContainer.querySelector('[data-panel="main"]'); + if (mainPanel) { + var items = mainPanel.querySelectorAll('.hstream-player__menu-item'); + for (var i = 0; i < items.length; i++) { + var text = items[i].textContent.trim(); + if (text.startsWith('Subtitles')) { + var valueEl = items[i].querySelector('.hstream-player__menu-value'); + if (valueEl) valueEl.textContent = this._captionLabel(); + break; + } + } + } + } + get quality() { return this._quality; } @@ -1070,6 +1109,10 @@ export class HStreamPlayer { return !!document.fullscreenElement; } + setSubtitleInstance(instance) { + this.subtitleInstance = instance; + } + toggleAmbientMode() { this._ambientMode = !this._ambientMode; localStorage.setItem('ambientMode', this._ambientMode.toString()); @@ -1202,7 +1245,7 @@ export class HStreamPlayer { if (this._captionsActive) { this._captionsBtn.classList.add('hstream-player__button--active'); } - if (this._subtitleTracks.length > 1) { + if (this._subtitleTracks.length >= 1) { this._captionsBtn.style.display = ''; }