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: Default seek, event.target, import await, forward scrubbing, fullscreen inview #311

Merged
merged 3 commits into from
Jan 13, 2025
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
44 changes: 10 additions & 34 deletions js/mediaLibrariesOverrides.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import Adapt from 'core/js/adapt';
import device from 'core/js/device';
import 'libraries/mediaelement-and-player';

/**
Expand Down Expand Up @@ -61,40 +60,17 @@ Adapt.on('app:dataReady', () => {
* and switch it back on again after exiting full screen mode
*/
const mepPrototype = Object.assign({}, window.mejs.MediaElementPlayer.prototype);

Object.assign(window.mejs.MediaElementPlayer.prototype, {
detectFullscreenMode() {
const vendorPrefix = this.getVendorPrefix();
const fsEventName = 'on' + vendorPrefix + 'fullscreenchange';

if (document[fsEventName] === null) {
document[fsEventName] = function fullScreenEventHandler() {

const elementName = (vendorPrefix === '' ? 'fullscreenElement' : vendorPrefix + 'FullscreenElement');

if (document[elementName] !== null) {
$.inview.lock('mediaelement');
Adapt.trigger('media:fullscreen:enter');
} else {
$.inview.unlock('mediaelement');
Adapt.trigger('media:fullscreen:exit');
}
};
}
return mepPrototype.detectFullscreenMode.apply(this, arguments);
enterFullScreen(...args) {
$.inview.lock('mediaelement');
Adapt.trigger('media:fullscreen:enter');
return mepPrototype.enterFullScreen.call(this, ...args);
},

/**
* Fullscreen events and properties are still vendor-prefixed in some browsers.
* https://developer.mozilla.org/en-US/docs/Web/API/Document/fullscreenchange_event#browser_compatibility
*/
getVendorPrefix() {
const browser = device.browser;

if (browser === 'safari') {
return 'webkit';
}

return '';
exitFullScreen(...args) {
setTimeout(() => {
$.inview.unlock('mediaelement');
Adapt.trigger('media:fullscreen:exit');
}, 250);
return mepPrototype.exitFullScreen.call(this, ...args);
}
});
52 changes: 35 additions & 17 deletions js/mediaView.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import './mediaLibrariesOverrides';
// instruct adapt to wait whilst loading client-side libraries
wait.for(async done => {
// load plugins
import('libraries/plugins/speed');
import('libraries/plugins/speed-i18n');
import('libraries/plugins/jump-forward');
import('libraries/plugins/jump-forward-i18n');
import('libraries/plugins/skip-back');
import('libraries/plugins/skip-back-i18n');
await import('libraries/plugins/speed');
await import('libraries/plugins/speed-i18n');
await import('libraries/plugins/jump-forward');
await import('libraries/plugins/jump-forward-i18n');
await import('libraries/plugins/skip-back');
await import('libraries/plugins/skip-back-i18n');
done();
});

Expand Down Expand Up @@ -49,7 +49,10 @@ class MediaView extends ComponentView {
'media:stop': this.onMediaStop
});

_.bindAll(this, 'onMediaElementPlay', 'onMediaElementPause', 'onMediaElementEnded', 'onMediaVolumeChange', 'onMediaElementTimeUpdate', 'onMediaElementSeeking', 'onOverlayClick', 'onMediaElementClick', 'onWidgetInview');
// android, force timeupdate handler to call after seeking handler in order to prevent forward scrubbing
this.onMediaElementTimeUpdate = _.debounce(this.onMediaElementTimeUpdate.bind(this), 0);

_.bindAll(this, 'onMediaElementPlay', 'onMediaElementPause', 'onMediaElementEnded', 'onMediaVolumeChange', 'onMediaElementSeeking', 'onOverlayClick', 'onMediaElementClick', 'onWidgetInview');

// set initial player state attributes
this.model.set({
Expand Down Expand Up @@ -114,12 +117,12 @@ class MediaView extends ComponentView {
}
}

/*
Unless we are on Android/iOS and using native controls, when MediaElementJS initializes the player
it will invoke the success callback prior to performing one last call to setPlayerSize.
This call to setPlayerSize is deferred by 50ms so we add a delay of 100ms here to ensure that
we don't invoke setReadyStatus until the player is definitely finished rendering.
*/
/**
* Unless we are on Android/iOS and using native controls, when MediaElementJS initializes the player
* it will invoke the success callback prior to performing one last call to setPlayerSize.
* This call to setPlayerSize is deferred by 50ms so we add a delay of 100ms here to ensure that
* we don't invoke setReadyStatus until the player is definitely finished rendering.
*/
modelOptions.success = _.debounce(this.onPlayerReady.bind(this), 100);

if (this.model.get('_useClosedCaptions')) {
Expand Down Expand Up @@ -149,6 +152,19 @@ class MediaView extends ComponentView {
*/
modelOptions.keyActions = [];

/**
* Convert string seek functions into compiled functions
*/
if (typeof modelOptions.defaultSeekBackwardInterval === 'string') {
// eslint-disable-next-line no-new-func
modelOptions.defaultSeekBackwardInterval = new Function('media', `return ${modelOptions.defaultSeekBackwardInterval}`);
}

if (typeof modelOptions.defaultSeekForwardInterval === 'string') {
// eslint-disable-next-line no-new-func
modelOptions.defaultSeekForwardInterval = new Function('media', `return ${modelOptions.defaultSeekBackwardInterval}`);
}

return modelOptions;
}

Expand Down Expand Up @@ -330,17 +346,19 @@ class MediaView extends ComponentView {
if (!maxViewed) {
maxViewed = 0;
}
if (event.target.currentTime <= maxViewed) return;
event.target.currentTime = maxViewed;
const target = event.currentTarget;
if (target.currentTime <= maxViewed) return;
target.currentTime = maxViewed;
}

onMediaElementTimeUpdate(event) {
let maxViewed = this.model.get('_maxViewed');
if (!maxViewed) {
maxViewed = 0;
}
if (event.target.currentTime <= maxViewed) return;
this.model.set('_maxViewed', event.target.currentTime);
const target = event.currentTarget;
if (target.currentTime <= maxViewed) return;
this.model.set('_maxViewed', target.currentTime);
}

onMediaStop(view) {
Expand Down