Skip to content
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

Automatic fullscreen videos on device roation #10108

Merged
merged 5 commits into from
Jul 27, 2017

Conversation

wassgha
Copy link
Contributor

@wassgha wassgha commented Jun 23, 2017

Switching to landscape when watching a video is a strong indicator that the user wants to expand the video to fullscreen. This feature allows AMP pages to automatically put videos into fullscreen mode when an orientation change is detected.

Changes

  • Added auto-fullscreen attribute to the video interface
  • Implemented an orientation change listener
  • Implemented in/out of fullscreen on manually playing videos when the device rotation changes to landscape
  • Added fullscreenEnter and fullscreenExit to the video interface and implemented it for all players (amp-video and amp-dailymotion have full support on iOS, other video players don't for now). Opened Implement iOS-compatible fullscreenEnter and fullscreenExit on video players that support it #10561 to check compatibility and implement any internal fullscreen API.

Closes #5380 , Checks-off an item on #4154 , Related-to #10561 , #10660

Copy link
Contributor

@aghassemi aghassemi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall I think we can move ahead with this feature. I suggest:
1- Run through the requested changed in this PR
2- Add integration tests and do some manual testing specially to make sure:
A) orientation change when AMP doc is invisible (i.e. not the current item in the Viewer) is side-effect free.
B) ensure if video was already made fullscreen by user, this code is side-effect free.
C) ensure when we take the video to fullscreen automatically (specially iframed ones), the fullscreen UI control works as expected (e.g. user can exit fullscreen manually and that does not mess up the code logic here)
3- Validator and documentation PR when we are happy with the feature.

/**
* auto-fullscreen
*
* NOTE: experimental
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't think we need to keep this experimental.

* auto-fullscreen
*
* NOTE: experimental
* If enabled, this automatically expands the currently visible video to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

currently visible and playing.

Let's discuss with @spacedino on whether we need to exclude autoplaying from this behaviour or not (I don't see a reason to exclude autoplay from this feature)

* @private
*/
maybeInstallOrientationObserver_(entry) {
// TODO(@wassgha): Remove this later. For now, the orientation observer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's replace the TODO with a comment that we only needs this when auto-fullscreen is enabled. Can't think of any other cases we may need this observer.

// Chrome apparently considers 'orientationchange' to be an untrusted
// event, while 'change' on screen.orientation is considered a user
// interaction
if (screen.orientation !== undefined) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note sue if screen is available in all browsers (e.g. IE11) also we want to get the screen from the current win not the global screen so let's do:

const screen = this.ampdoc_.win.screen;
if (screen && screen.orientation) 

*/
orientationChanged_() {

const vidElement = this.video.element.querySelector('iframe, video');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add TODO to refactor since video docking is using this as well.

const angle = this.ampdoc_.win.orientation !== undefined ?
this.ampdoc_.win.orientation : screen.orientation.angle;

if (this.isVisible_
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reverse and return early (before the angel calculation). Also make sure you bail out if !viewerForDoc(this.ampdoc_).isVisible()

&& (Math.abs(angle) == 270 || Math.abs(angle) == 90)) {

// Determine which implementation of requestFullScreen to use
const requestFullScreen = vidElement.webkitEnterFullscreen
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's refactor to two new methods on entry: enterFullscreen_() and exitFullscreen_()

|| vidElement.webkitEnterFullscreen || vidElement.msRequestFullscreen
|| vidElement.mozRequestFullScreen;

requestFullScreen.call(vidElement);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try catch these calls since we don't wanna log when request is denied, if it fails, we should not set this.isFullscreen_ = true;


if (this.isVisible_
&& this.getPlayingState() == PlayingStates.PLAYING_MANUAL
&& (Math.abs(angle) == 270 || Math.abs(angle) == 90)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if user manually goes to fullscreen and then rotates in the following cases?
1- Chrome amp-video
2- Chrome amp-youtube
3- iOS amp-video
4- iOS amp-youtube

I am assuming (hoping) fullscreen request will be denied.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Behaves correctly (manually tested)

requestFullScreen.call(vidElement);
this.isFullscreen_ = true;

} else if (this.isFullscreen_) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.isFullscreen_ is misleading, it is more like this.isFullscreenWithAutoFullscreen_

@wassgha
Copy link
Contributor Author

wassgha commented Jun 30, 2017

@aghassemi There's an issue i'm not sure how to fix: When you're in portrait and the video is in view then you rotate the video sometimes gets out of view and therefore doesn't go to fullscreen (since we only measure whether it is visible or not after the orientation change...)

@wassgha wassgha force-pushed the landscape-fullscreen branch 2 times, most recently from 60f7370 to 03791d2 Compare July 5, 2017 07:18
@wassgha wassgha force-pushed the landscape-fullscreen branch 7 times, most recently from 4ea6e7f to 26ceeb4 Compare July 15, 2017 06:37
@wassgha
Copy link
Contributor Author

wassgha commented Jul 18, 2017

@aghassemi Would we want to add a enterFullscreen() method to the video interface to get this working on iOS with iframe based video players?

@aghassemi
Copy link
Contributor

@wassgha definitely, not hopeful that any 3P has support for this (including YT) but at minimum we can make it work for IMA

@wassgha
Copy link
Contributor Author

wassgha commented Jul 20, 2017

Ready for review :)

@wassgha wassgha force-pushed the landscape-fullscreen branch 2 times, most recently from a87213d to 212b88c Compare July 21, 2017 17:31
Copy link
Contributor

@aghassemi aghassemi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, few nits

* @override
*/
fullscreenEnter() {
// TODO(@aghassemi) Make internal <video> element go fullscreen instead
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do TODO(aghassemi, #10597)

src/dom.js Outdated
/**
* Replacement for `Element.requestFullscreen()` method.
* https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullscreen
* @param {Element} element
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{!Element} (same below)

* http://caniuse.com/#feat=screen-orientation
* and http://caniuse.com/#feat=fullscreen
*/
AUTOFULLSCREEN: 'auto-fullscreen',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what was the conclusion from design review? fullscreen-on-landscape or auto-fullscreen? (I am fine with either)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the consensus was to launch as default and add no-fullscreen-on-landscape but i'm not sure about that..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a big fan of binary attributes. Let's do:
fullscreen-on-landscape=(never|always).
If fullscreen-on-landscape is specified without a value, then it equals always
If no fullscreen-on-landscape is specified, for initial launch, it means never, we will have to do an experiment and ramp up slowly where not having fullscreen-on-landscape starts meaning always

* @private
*/
orientationChanged_(isLandscape) {
// Put the video in/out of fullscreen depending on orientation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return early if !viewerForDoc(this.ampdoc_).isVisible()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually from what I've seen, when the video is fullscreen, viewerForDoc(this.ampdoc_).isVisible() always returns false. Is that the normal behavior or is it a bug?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting, it is technically correct. Can we ensure at least we don't go to fullscreen on rotation if viewerForDoc(this.ampdoc_).isVisible() is false?

* http://caniuse.com/#feat=screen-orientation
* and http://caniuse.com/#feat=fullscreen
*/
AUTOFULLSCREEN: 'auto-fullscreen',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's also add the validation rules and documentation for all the components that now support this in a separate PR (which would effectively be the launch PR, so let's CC Eric and Rudy on that one)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to switch to attribute lists on that PR or leave that for later?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah would be a good time to do attribute list for video-interface

@wassgha wassgha force-pushed the landscape-fullscreen branch 7 times, most recently from 94f885f to 03b3c1e Compare July 26, 2017 02:46
Copy link
Contributor

@aghassemi aghassemi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple more requests and then good to merge!

@@ -218,6 +227,9 @@ class AmpDailymotion extends AMP.BaseElement {
case DailymotionEvents.STARTED_BUFFERING:
this.startedBufferingResolver_(true);
break;
case DailymotionEvents.FULLSCREEN_CHANGE:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice! they thought of everything.

* @private
*/
orientationChanged_(isLandscape) {
// Put the video in/out of fullscreen depending on screen orientation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return early if this.loaded_ is false. What can happen is orientation change occurring before the layoutCallback of a video player is called in which case their iframe is null. Now at the moment we can't get to that case because of the this.getPlayingState() == PlayingStates.PLAYING_MANUAL check but I like to keep the code safe since later supporting AUTOPLAY can surface the race condition.

<body>
<h1>amp-video</h1>

<amp-video
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just add the sample to the end of the existing amp-video.amp.html (and youtube, brid, ima, daily motion)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs validation though...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right.. then let's move this to test/manual and create an issue to add examples + ABE samples when launched.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VideoAttributes.FULLSCREEN_ON_LANDSCAPE
);

this.hasFullscreenOnLandscape = fsOnLandscapeAttr !== undefined
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undefined check not needed (getAttribute actually returns null). Also inconsistent == and === (just use == compiler takes care of it).

Copy link
Contributor

@aghassemi aghassemi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants