From da37fab1308117eba062693d6b5c400a10be54d3 Mon Sep 17 00:00:00 2001 From: Gary Katsevman Date: Thu, 26 Mar 2020 17:26:26 -0400 Subject: [PATCH] feat(fs): return a promise from requestFullscreen and exitFullscreen when we can (#6424) --- src/js/player.js | 75 ++++++++++++++++++++++++++++++++++++++++++++ src/js/tech/html5.js | 20 ++++++++++-- 2 files changed, 92 insertions(+), 3 deletions(-) diff --git a/src/js/player.js b/src/js/player.js index d03e7195e2..f4ed3f7ccc 100644 --- a/src/js/player.js +++ b/src/js/player.js @@ -1157,6 +1157,7 @@ class Player extends Component { this.on(this.tech_, 'pause', this.handleTechPause_); this.on(this.tech_, 'durationchange', this.handleTechDurationChange_); this.on(this.tech_, 'fullscreenchange', this.handleTechFullscreenChange_); + this.on(this.tech_, 'fullscreenerror', this.handleTechFullscreenError_); this.on(this.tech_, 'enterpictureinpicture', this.handleTechEnterPictureInPicture_); this.on(this.tech_, 'leavepictureinpicture', this.handleTechLeavePictureInPicture_); this.on(this.tech_, 'error', this.handleTechError_); @@ -2047,6 +2048,10 @@ class Player extends Component { } } + handleTechFullscreenError_(event, err) { + this.trigger('fullscreenerror', err); + } + /** * @private */ @@ -2745,6 +2750,41 @@ class Player extends Component { * @fires Player#fullscreenchange */ requestFullscreen(fullscreenOptions) { + const PromiseClass = this.options_.Promise || window.Promise; + + if (PromiseClass) { + const self = this; + + return new PromiseClass((resolve, reject) => { + function offHandler() { + self.off(self.fsApi_.fullscreenerror, errorHandler); + self.off(self.fsApi_.fullscreenchange, changeHandler); + } + function changeHandler() { + offHandler(); + resolve(); + } + function errorHandler(e, err) { + offHandler(); + reject(err); + } + + self.one('fullscreenchange', changeHandler); + self.one('fullscreenerror', errorHandler); + + const promise = self.requestFullscreenHelper_(fullscreenOptions); + + if (promise) { + promise.then(offHandler, offHandler); + return promise; + } + }); + } + + return this.requestFullscreenHelper_(); + } + + requestFullscreenHelper_(fullscreenOptions) { let fsOptions; // Only pass fullscreen options to requestFullscreen in spec-compliant browsers. @@ -2788,6 +2828,41 @@ class Player extends Component { * @fires Player#fullscreenchange */ exitFullscreen() { + const PromiseClass = this.options_.Promise || window.Promise; + + if (PromiseClass) { + const self = this; + + return new PromiseClass((resolve, reject) => { + function offHandler() { + self.off(self.fsApi_.fullscreenerror, errorHandler); + self.off(self.fsApi_.fullscreenchange, changeHandler); + } + function changeHandler() { + offHandler(); + resolve(); + } + function errorHandler(e, err) { + offHandler(); + reject(err); + } + + self.one('fullscreenchange', changeHandler); + self.one('fullscreenerror', errorHandler); + + const promise = self.exitFullscreenHelper_(); + + if (promise) { + promise.then(offHandler, offHandler); + return promise; + } + }); + } + + return this.exitFullscreenHelper_(); + } + + exitFullscreenHelper_() { if (this.fsApi_.requestFullscreen) { const promise = document[this.fsApi_.exitFullscreen](); diff --git a/src/js/tech/html5.js b/src/js/tech/html5.js index eac24a09e6..bb3bed832c 100644 --- a/src/js/tech/html5.js +++ b/src/js/tech/html5.js @@ -14,6 +14,7 @@ import {toTitleCase} from '../utils/string-cases.js'; import {NORMAL as TRACK_TYPES, REMOTE} from '../tracks/track-types'; import setupSourceset from './setup-sourceset'; import defineLazyProperty from '../utils/define-lazy-property.js'; +import {silencePromise} from '../utils/promise'; /** * HTML5 Media Controller - Wrapper for HTML5 Media API @@ -652,16 +653,24 @@ class Html5 extends Tech { if (video.paused && video.networkState <= video.HAVE_METADATA) { // attempt to prime the video element for programmatic access // this isn't necessary on the desktop but shouldn't hurt - this.el_.play(); + silencePromise(this.el_.play()); // playing and pausing synchronously during the transition to fullscreen // can get iOS ~6.1 devices into a play/pause loop this.setTimeout(function() { video.pause(); - video.webkitEnterFullScreen(); + try { + video.webkitEnterFullScreen(); + } catch (e) { + this.trigger('fullscreenerror', e); + } }, 0); } else { - video.webkitEnterFullScreen(); + try { + video.webkitEnterFullScreen(); + } catch (e) { + this.trigger('fullscreenerror', e); + } } } @@ -669,6 +678,11 @@ class Html5 extends Tech { * Request that the `HTML5` Tech exit fullscreen. */ exitFullScreen() { + if (!this.el_.webkitDisplayingFullscreen) { + this.trigger('fullscreenerror', new Error('The video is not fullscreen')); + return; + } + this.el_.webkitExitFullScreen(); }