Skip to content

Commit

Permalink
Started working on the rotate to fullscreen
Browse files Browse the repository at this point in the history
  • Loading branch information
wassgha committed Jul 20, 2017
1 parent 88a2ca6 commit 424abc4
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 0 deletions.
7 changes: 7 additions & 0 deletions build-system/tasks/presubmit-checks.js
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,13 @@ var forbiddenTerms = {
'src/event-helper.js',
],
},
'[A-Za-z]*Full[Ss]creen\\(': {
message: 'Use fullscreenEnter() and fullscreenExit() from dom.js instead.',
whitelist: [
'ads/google/imaVideo.js',
'dist.3p/current/integration.js',
],
},
};

var ThreePTermsMessage = 'The 3p bootstrap iframe has no polyfills loaded and' +
Expand Down
35 changes: 35 additions & 0 deletions src/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -748,3 +748,38 @@ export function whenUpgradedToCustomElement(element) {

return element[UPGRADE_TO_CUSTOMELEMENT_PROMISE];
}

/**
* Replacement for `Element.requestFullscreen()` method.
* https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullscreen
* @param {Element} element
*/
export function fullscreenEnter(element) {
const requestFs = element.webkitEnterFullscreen
|| element.webkitRequestFullScreen
|| element.requestFullscreen
|| element.webkitEnterFullscreen
|| element.msRequestFullscreen
|| element.mozRequestFullscreen
|| element.mozRequestFullScreen;
if (requestFs) {
requestFs.call(element);
}
}

/**
* Replacement for `Document.exitFullscreen()` method.
* https://developer.mozilla.org/en-US/docs/Web/API/Document/exitFullscreen
* @param {Document} doc
*/
export function fullscreenExit(doc) {
const exitFs = doc.webkitCancelFullScreen
|| doc.cancelFullScreen
|| doc.webkitExitFullscreen
|| doc.exitFullscreen
|| doc.mozCancelFullScreen
|| doc.msExitFullscreen;
if (exitFs) {
exitFs.call(doc);
}
}
88 changes: 88 additions & 0 deletions src/service/video-manager-impl.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {registerServiceBuilderForDoc, getServiceForDoc} from '../service';
import {setStyles} from '../style';
import {isFiniteNumber} from '../types';
import {mapRange} from '../utils/math';
import {startsWith} from '../string.js';
import {
PlayingStates,
VideoAnalyticsEvents,
Expand All @@ -39,6 +40,8 @@ import {
} from './position-observer-impl';
import {
scopedQuerySelector,
fullscreenEnter,
fullscreenExit,
} from '../dom';
import {layoutRectLtwh, RelativePositions} from '../layout-rect';
import * as st from '../style';
Expand Down Expand Up @@ -137,6 +140,7 @@ export class VideoManager {
const entry = new VideoEntry(this, video);
this.maybeInstallVisibilityObserver_(entry);
this.maybeInstallPositionObserver_(entry);
this.maybeInstallOrientationObserver_(entry);
this.entries_.push(entry);
video.element.dispatchCustomEvent(VideoEvents.REGISTERED);
}
Expand Down Expand Up @@ -194,6 +198,47 @@ export class VideoManager {
}
}


/**
* Install the necessary listeners to be notified when the user changes
* the orientation of their device
*
* @param {VideoEntry} entry
* @private
*/
maybeInstallOrientationObserver_(entry) {
// The orientation observer is only useful for automatically putting videos
// in fullscreen.
if (!entry.video.element.hasAttribute(VideoAttributes.AUTOFULLSCREEN)) {
return;
}

// TODO(@wassgha) Check support status for orientation API and update
// this as needed.
const screen = this.ampdoc_.win.screen;
const win = this.ampdoc_.win;
const handleOrientationChange = () => {
let isLandscape;
if (screen && 'orientation' in screen) {
isLandscape = startsWith(screen.orientation.type, 'landscape');
} else {
isLandscape = win.orientation == -90 || win.orientation == 90;
}
entry.orientationChanged_(isLandscape);
};
// Chrome apparently considers 'orientationchange' to be an untrusted
// event, while 'change' on screen.orientation is considered a user
// interaction
if (screen && 'orientation' in screen) {
const orient = /** @type {!ScreenOrientation} */ (screen.orientation);
listen(orient, 'change', handleOrientationChange.bind(this));
} else {
// iOS Safari does not have screen.orientation but classifies
// 'orientationchange' as a user interaction.
listen(win, 'orientationchange', handleOrientationChange.bind(this));
}
}

/**
* Install the necessary listeners to be notified when a video scrolls in the
* viewport
Expand Down Expand Up @@ -336,6 +381,9 @@ class VideoEntry {
/** @private {boolean} */
this.isVisible_ = false;

/** @private {boolean} */
this.isFullscreenByOrientationChange_ = false;

/** @private @const {!../service/vsync-impl.Vsync} */
this.vsync_ = Services.vsyncFor(this.ampdoc_.win);

Expand Down Expand Up @@ -396,6 +444,8 @@ class VideoEntry {

this.hasAutoplay = element.hasAttribute(VideoAttributes.AUTOPLAY);

this.hasAutoFs = element.hasAttribute(VideoAttributes.AUTOFULLSCREEN);

listenOncePromise(element, VideoEvents.LOAD)
.then(() => this.videoLoaded());

Expand Down Expand Up @@ -492,6 +542,44 @@ class VideoEntry {
}
}

/**
* Called when the orientation of the device changes
* @param {boolean} isLandscape
* @private
*/
orientationChanged_(isLandscape) {
if (!viewerForDoc(this.ampdoc_).isVisible()) {
return;
}
// Put the video in/out of fullscreen depending on orientation
if (!isLandscape && this.isFullscreenByOrientationChange_) {
this.exitFullscreen_();
}
if (isLandscape
&& this.isVisible_
&& this.getPlayingState() == PlayingStates.PLAYING_MANUAL) {
this.enterFullscreen_();
}
}

/**
* Makes the video element go fullscreen and updates its status
* @private
*/
enterFullscreen_() {
fullscreenEnter(this.internalElement_);
this.isFullscreenByOrientationChange_ = true;
}

/**
* Makes the video element quit fullscreen and updates its status
* @private
*/
exitFullscreen_() {
fullscreenExit(this.ampdoc_.win.document);
this.isFullscreenByOrientationChange_ = false;
}

/**
* Only called when visibility of a loaded video changes.
* @private
Expand Down
13 changes: 13 additions & 0 deletions src/video-interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,19 @@ export const VideoAttributes = {
* to the corner when scrolled out of view and has been interacted with.
*/
DOCK: 'dock',
/**
* auto-fullscreen
*
* If enabled, this automatically expands the currently visible video and
* playing to fullscreen when the user changes the device's orientation to
* landscape if the video was started following a user interaction
* (not autoplay)
*
* Dependent upon browser support of
* http://caniuse.com/#feat=screen-orientation
* and http://caniuse.com/#feat=fullscreen
*/
AUTOFULLSCREEN: 'auto-fullscreen',
};


Expand Down
71 changes: 71 additions & 0 deletions test/manual/amp-video-auto-fullscreen.amp.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<!doctype html>
<html >
<head>
<meta charset="utf-8">
<title>AMP #0</title>
<link rel="canonical" href="amps.html" >
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<meta name="apple-mobile-web-app-title" content="AppTitle">
<meta name="apple-mobile-web-app-capable" content="yes">

<script async custom-element="amp-video" src="https://cdn.ampproject.org/v0/amp-video-0.1.js"></script>
<link href='https://fonts.googleapis.com/css?family=Questrial' rel='stylesheet' type='text/css'>
<style amp-custom>
body {
max-width: 527px;
font-family: 'Questrial', Arial;
}
[fallback] {
display: block;
/* @alternative */ display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: center;
align-items: center;
background: rgba(0, 0, 0, 0.5);
color: #fff;
}
.spacer {
height: 100vh;
}
</style>
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<script async src="https://cdn.ampproject.org/v0.js"></script>
</head>
<body>
<h1>amp-video</h1>

<amp-video
id="myVideo"
src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4"
width="720"
height="405"
layout="responsive"
auto-fullscreen
controls>
<div placeholder>
This is a placeholder
</div>
<div fallback>
This is a fallback
</div>
</amp-video>
<h3>Actions</h3>
<button on="tap:myVideo.play">Play</button>
<button on="tap:myVideo.pause">Pause</button>
<button on="tap:myVideo.mute">Mute</button>
<button on="tap:myVideo.unmute">Unmute</button>

<h2>Autoplay</h2>
<amp-video
autoplay
auto-fullscreen
src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4"
width="720"
height="405"
layout="responsive"
controls>
</amp-video>
<div class="spacer"></div>
</body>
</html>

0 comments on commit 424abc4

Please sign in to comment.