diff --git a/lib/text/ui_text_displayer.js b/lib/text/ui_text_displayer.js index 3f1e8477e..d8e376543 100644 --- a/lib/text/ui_text_displayer.js +++ b/lib/text/ui_text_displayer.js @@ -79,6 +79,11 @@ shaka.text.UITextDisplayer = class { }); this.configureCaptionsTimer_(); + /** @private {shaka.util.Timer} */ + this.applyVisibilityTimer_ = new shaka.util.Timer(() => { + this.applyVisibility_(); + }); + /** * Maps cues to cue elements. Specifically points out the wrapper element of * the cue (e.g. the HTML element to put nested cues inside). @@ -165,7 +170,9 @@ shaka.text.UITextDisplayer = class { const entry = entries[entries.length - 1]; this.isContainerActuallyVisible_ = entry.isIntersecting && entry.intersectionRatio > 0; - this.applyVisibility_(); + const captionsUpdatePeriod = + this.config_?.captionsUpdatePeriod || 0.25; + this.applyVisibilityTimer_.tickAfter(captionsUpdatePeriod); } }, options); goog.asserts.assert(this.videoContainer_, @@ -174,7 +181,11 @@ shaka.text.UITextDisplayer = class { } this.eventManager_.listen(document, 'visibilitychange', (e) => { - this.applyVisibility_(); + this.applyVisibilityTimer_.tickNow(); + }); + + this.eventManager_.listen(document, 'fullscreenchange', () => { + this.applyVisibilityTimer_.tickNow(); }); this.eventManager_.listenMulti( @@ -183,18 +194,18 @@ shaka.text.UITextDisplayer = class { 'enterpictureinpicture', 'leavepictureinpicture', ], () => { - this.applyVisibility_(); + this.applyVisibilityTimer_.tickNow(); }); if ('documentPictureInPicture' in window) { this.eventManager_.listen(window.documentPictureInPicture, 'enter', (e) => { - this.applyVisibility_(); + this.applyVisibilityTimer_.tickNow(); const event = /** @type {DocumentPictureInPictureEvent} */(e); const pipWindow = event.window; this.eventManager_.listenOnce(pipWindow, 'pagehide', () => { - this.applyVisibility_(); + this.applyVisibilityTimer_.tickNow(); }); }); } @@ -202,7 +213,7 @@ shaka.text.UITextDisplayer = class { const video = /** @type {HTMLVideoElement} */(this.video_); if (video.webkitPresentationMode || video.webkitSupportsFullscreen) { this.eventManager_.listen(video, 'webkitpresentationmodechanged', () => { - this.applyVisibility_(); + this.applyVisibilityTimer_.tickNow(); }); } @@ -267,28 +278,22 @@ shaka.text.UITextDisplayer = class { this.isTextVisible_ = false; this.cues_ = []; - if (this.captionsTimer_) { - this.captionsTimer_.stop(); - this.captionsTimer_ = null; - } + this.captionsTimer_?.stop(); + this.captionsTimer_ = null; + this.applyVisibilityTimer_?.stop(); + this.applyVisibilityTimer_ = null; this.currentCuesMap_.clear(); // Tear-down the event manager to ensure messages stop moving around. - if (this.eventManager_) { - this.eventManager_.release(); - this.eventManager_ = null; - } + this.eventManager_?.release(); + this.eventManager_ = null; - if (this.resizeObserver_) { - this.resizeObserver_.disconnect(); - this.resizeObserver_ = null; - } + this.resizeObserver_?.disconnect(); + this.resizeObserver_ = null; - if (this.visibilityObserver_) { - this.visibilityObserver_.disconnect(); - this.visibilityObserver_ = null; - } + this.visibilityObserver_?.disconnect(); + this.visibilityObserver_ = null; return Promise.resolve(); } @@ -380,17 +385,37 @@ shaka.text.UITextDisplayer = class { * @private */ applyVisibility_() { - const isPiPActive = !!((window.documentPictureInPicture && - window.documentPictureInPicture.window) || - document.pictureInPictureElement); + const video = /** @type {HTMLVideoElement} */(this.video_); + let isPiPActive = false; + if (window.documentPictureInPicture && + window.documentPictureInPicture.window) { + isPiPActive = true; + } else if (document.pictureInPictureElement === video) { + isPiPActive = true; + } + let isFullscreenActive = false; + if (document.fullscreenEnabled && + document.fullscreenElement === this.videoContainer_) { + isFullscreenActive = true; + } else if (video.webkitSupportsFullscreen) { + isFullscreenActive = video.webkitDisplayingFullscreen; + } const pageVisible = document.visibilityState === 'visible'; - const actuallyVisible = - isPiPActive || (pageVisible && this.isContainerActuallyVisible_); + const actuallyVisible = isPiPActive || isFullscreenActive || + (pageVisible && this.isContainerActuallyVisible_); if (actuallyVisible) { if (this.renderSuspended_) { this.renderSuspended_ = false; this.configureCaptionsTimer_(); - this.updateCaptions_(); + requestAnimationFrame(() => { + if (!this.textContainer_) { + return; + } + + if (this.textContainer_.parentElement && this.isTextVisible_) { + this.updateCaptions_(); + } + }); } } else { if (!this.renderSuspended_) {