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

Fix: Media controls and usability fixes for mobile #217

Merged
merged 5 commits into from
Jul 17, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions src/lib/viewers/box3d/video360/Video360.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@
display: flex;
}

.bp-video-360 canvas {
cursor: move; /* fallback if grab cursor is unsupported */
cursor: grab;
}

.bp-is-mobile {
.bp-is-mobile .bp-video-360 .bp-media-container {
.bp-media-controls-wrapper {
/* stylelint-disable declaration-no-important */
opacity: 1 !important;
visibility: visible !important;
/* stylelint-enable declaration-no-important */
}
}

.bp-video-360 canvas {
cursor: move; /* fallback if grab cursor is unsupported */
cursor: grab;
}
1 change: 1 addition & 0 deletions src/lib/viewers/media/DashViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ const MANIFEST = 'manifest.mpd';

// Make media element visible after resize
this.showMedia();
this.mediaControls.show();
this.mediaContainerEl.focus();
}

Expand Down
43 changes: 42 additions & 1 deletion src/lib/viewers/media/MediaControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { activationHandler, addActivationListener, removeActivationListener, ins
const SHOW_CONTROLS_CLASS = 'bp-media-controls-is-visible';
const PLAYING_CLASS = 'bp-media-is-playing';
const VOLUME_SCRUBBER_EXPAND_CLASS = 'bp-media-controls-volume-scrubber-expand';
const CONTROLS_AUTO_HIDE_TIMEOUT_IN_MILLIS = 1500;
const CONTROLS_AUTO_HIDE_TIMEOUT_IN_MILLIS = 2000;
const VOLUME_LEVEL_CLASS_NAMES = [
'bp-media-volume-icon-is-mute',
'bp-media-volume-icon-is-low',
Expand Down Expand Up @@ -613,6 +613,31 @@ const FILMSTRIP_FRAME_HEIGHT = 90;
}
}

/**
* Toggles the media controls
*
* @return {void}
*/
toggle() {
if (this.isVisible()) {
// Clear all controls hiding blockers to allow hiding
this.preventHiding = false;
this.settings.hide();
this.hide();
} else {
this.show();
}
}

/**
* Determines if media controls are shown
*
* @return {boolean} If the controls are visible
*/
isVisible() {
return this.wrapperEl.parentNode.classList.contains(SHOW_CONTROLS_CLASS);
}

/**
* Resizes the time scrubber
*
Expand Down Expand Up @@ -669,6 +694,11 @@ const FILMSTRIP_FRAME_HEIGHT = 90;
// aspect ratio as the original video.

this.timeScrubber.getHandleEl().addEventListener('mousedown', this.timeScrubbingStartHandler);

if (this.hasTouch) {
this.timeScrubberEl.addEventListener('touchstart', this.timeScrubbingStartHandler);
}

this.timeScrubber.getConvertedEl().addEventListener('mousemove', this.filmstripShowHandler);
this.timeScrubber.getConvertedEl().addEventListener('mouseleave', this.filmstripHideHandler);

Expand All @@ -692,16 +722,23 @@ const FILMSTRIP_FRAME_HEIGHT = 90;
timeScrubbingStartHandler() {
// Flag that we are scrubbing
this.isScrubbing = true;
this.preventHiding = true;

// Add event listener for the entire document that when mouse up happens
// anywhere, consider scrubbing has stopped. This is added on the document
// itself so that the user doesn't have to scrub in a straight line.
document.addEventListener('mouseup', this.timeScrubbingStopHandler);
if (this.hasTouch) {
document.addEventListener('touchend', this.timeScrubbingStopHandler);
}

// Likewise add a mouse move handler to the entire document so that when
// the user is scrubbing and they are randomly moving mouse anywhere on the
// document, we still continue to show the film strip
document.addEventListener('mousemove', this.filmstripShowHandler);
if (this.hasTouch) {
document.addEventListener('touchmove', this.show);
}
}

/**
Expand All @@ -714,11 +751,15 @@ const FILMSTRIP_FRAME_HEIGHT = 90;
timeScrubbingStopHandler(event) {
// Flag that scrubbing is done
this.isScrubbing = false;
this.preventHiding = false;

// Remove any even listeners that were added when scrubbing started
document.removeEventListener('mouseup', this.timeScrubbingStopHandler);
document.removeEventListener('mousemove', this.filmstripShowHandler);

document.removeEventListener('touchend', this.timeScrubbingStopHandler);
document.removeEventListener('touchmove', this.show);

if (!this.timeScrubberEl.contains(event.target)) {
// Don't hide the filmstrip if we were hovering over the scrubber when
// mouse up happened. Since we show film strip on hover. On all other cases
Expand Down
4 changes: 3 additions & 1 deletion src/lib/viewers/media/MediaControls.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
.bp-media-controls-wrapper:active,
.bp-media-controls-wrapper:focus {
opacity: 1;
visibility: visible;
}

.bp-media-controls-wrapper {
Expand All @@ -17,7 +18,8 @@
overflow: hidden;
position: absolute;
right: 0;
transition: opacity .3s;
transition: visibility .3s, opacity .3s;
visibility: hidden;
width: 100%;
}

Expand Down
29 changes: 27 additions & 2 deletions src/lib/viewers/media/VideoBaseViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const CLASS_PLAY_BUTTON = 'bp-media-play-button';
// Video element
this.mediaEl = this.mediaContainerEl.appendChild(document.createElement('video'));
this.mediaEl.setAttribute('preload', 'auto');
// Prevents native iOS UI from taking over
this.mediaEl.setAttribute('playsinline', '');

// Play button
this.playButtonEl = this.mediaContainerEl.appendChild(document.createElement('div'));
Expand All @@ -37,7 +39,8 @@ const CLASS_PLAY_BUTTON = 'bp-media-play-button';
destroy() {
if (this.mediaEl) {
this.mediaEl.removeEventListener('mousemove', this.mousemoveHandler);
this.mediaEl.removeEventListener('click', this.togglePlay);
this.mediaEl.removeEventListener('click', this.pointerHandler);
this.mediaEl.removeEventListener('touchstart', this.pointerHandler);
this.mediaEl.removeEventListener('waiting', this.waitingHandler);
}

Expand All @@ -57,6 +60,24 @@ const CLASS_PLAY_BUTTON = 'bp-media-play-button';
loadeddataHandler() {
super.loadeddataHandler();
this.showPlayButton();
this.mediaControls.show();
}

/**
* Handler for a pointer event on the media element.
*
* @param {Event} event pointer event, either touch or mouse
* @return {void}
*/
pointerHandler(event) {
if (event.type === 'touchstart') {
// Prevents 'click' event from firing which would pause the video
event.preventDefault();
event.stopPropagation();
this.mediaControls.toggle();
} else if (event.type === 'click') {
this.togglePlay();
}
}

/**
Expand Down Expand Up @@ -132,7 +153,11 @@ const CLASS_PLAY_BUTTON = 'bp-media-play-button';
}, MOUSE_MOVE_TIMEOUT_IN_MILLIS);

this.mediaEl.addEventListener('mousemove', this.mousemoveHandler);
this.mediaEl.addEventListener('click', this.togglePlay);
if (this.hasTouch) {
this.mediaEl.addEventListener('touchstart', this.pointerHandler);
}

this.mediaEl.addEventListener('click', this.pointerHandler);
this.mediaEl.addEventListener('waiting', this.waitingHandler);
this.playButtonEl.addEventListener('click', this.togglePlay);
}
Expand Down
4 changes: 3 additions & 1 deletion src/lib/viewers/media/__tests__/DashViewer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ describe('lib/viewers/media/DashViewer', () => {
initFilmstrip: () => {},
initSubtitles: () => {},
removeAllListeners: () => {},
removeListener: () => {}
removeListener: () => {},
show: sandbox.stub()
};
stubs.mockControls = sandbox.mock(dash.mediaControls);

Expand Down Expand Up @@ -430,6 +431,7 @@ describe('lib/viewers/media/DashViewer', () => {
expect(dash.emit).to.be.calledWith('load');
expect(dash.loaded).to.be.true;
expect(document.activeElement).to.equal(dash.mediaContainerEl);
expect(dash.mediaControls.show).to.be.called;
});
});

Expand Down
Loading