MOBILE-4072 h5p: Use workaround for H5P fullscreen in iOS

main
Aldo Saia 2022-10-12 17:14:44 -03:00 committed by Dani Palou
parent cd8f81d332
commit 16e137bf57
3 changed files with 79 additions and 15 deletions

View File

@ -47,7 +47,7 @@
<preference name="iosPersistentFileLocation" value="Compatibility" /> <preference name="iosPersistentFileLocation" value="Compatibility" />
<preference name="iosScheme" value="moodleappfs" /> <preference name="iosScheme" value="moodleappfs" />
<preference name="WKWebViewOnly" value="true" /> <preference name="WKWebViewOnly" value="true" />
<preference name="WKFullScreenEnabled" value="true" /> <preference name="WKFullScreenEnabled" value="false" />
<preference name="AndroidXEnabled" value="true" /> <preference name="AndroidXEnabled" value="true" />
<preference name="GradlePluginGoogleServicesEnabled" value="true" /> <preference name="GradlePluginGoogleServicesEnabled" value="true" />
<preference name="GradlePluginGoogleServicesVersion" value="4.3.10" /> <preference name="GradlePluginGoogleServicesVersion" value="4.3.10" />

View File

@ -57,9 +57,13 @@ export class CoreIframeComponent implements OnChanges, OnDestroy {
protected style?: HTMLStyleElement; protected style?: HTMLStyleElement;
protected orientationObs?: CoreEventObserver; protected orientationObs?: CoreEventObserver;
protected navSubscription?: Subscription; protected navSubscription?: Subscription;
protected messageListenerFunction: (event: MessageEvent) => Promise<void>;
constructor(protected elementRef: ElementRef<HTMLElement>) { constructor(protected elementRef: ElementRef<HTMLElement>) {
this.loaded = new EventEmitter<HTMLIFrameElement>(); this.loaded = new EventEmitter<HTMLIFrameElement>();
// Listen for messages from the iframe.
window.addEventListener('message', this.messageListenerFunction = (event) => this.onIframeMessage(event));
} }
/** /**
@ -177,12 +181,13 @@ export class CoreIframeComponent implements OnChanges, OnDestroy {
ngOnDestroy(): void { ngOnDestroy(): void {
this.orientationObs?.off(); this.orientationObs?.off();
this.navSubscription?.unsubscribe(); this.navSubscription?.unsubscribe();
window.removeEventListener('message', this.messageListenerFunction);
} }
/** /**
* Toggle fullscreen mode. * Toggle fullscreen mode.
*/ */
toggleFullscreen(enable?: boolean): void { toggleFullscreen(enable?: boolean, notifyIframe = true): void {
if (enable !== undefined) { if (enable !== undefined) {
this.fullscreen = enable; this.fullscreen = enable;
} else { } else {
@ -200,6 +205,27 @@ export class CoreIframeComponent implements OnChanges, OnDestroy {
} }
document.body.classList.toggle('core-iframe-fullscreen', this.fullscreen); document.body.classList.toggle('core-iframe-fullscreen', this.fullscreen);
if (notifyIframe && this.iframe?.nativeElement) {
(<HTMLIFrameElement> this.iframe.nativeElement).contentWindow?.postMessage(
this.fullscreen ? 'enterFullScreen' : 'exitFullScreen',
'*',
);
}
}
/**
* Treat an iframe message event.
*
* @param event Event.
* @return Promise resolved when done.
*/
protected async onIframeMessage(event: MessageEvent): Promise<void> {
if (event.data == 'enterFullScreen' && this.showFullscreenOnToolbar && !this.fullscreen) {
this.toggleFullscreen(true, false);
} else if (event.data == 'exitFullScreen' && this.fullscreen) {
this.toggleFullscreen(false, false);
}
} }
} }

View File

@ -22,6 +22,11 @@ H5P.$window = H5P.jQuery(window);
*/ */
H5P.instances = []; H5P.instances = [];
function isIOS() {
return ['iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod'].includes(navigator.platform)
|| (navigator.userAgent.includes("Mac") && "ontouchend" in document);
}
// Detect if we support fullscreen, and what prefix to use. // Detect if we support fullscreen, and what prefix to use.
if (document.documentElement.requestFullScreen) { if (document.documentElement.requestFullScreen) {
/** /**
@ -32,23 +37,23 @@ if (document.documentElement.requestFullScreen) {
H5P.fullScreenBrowserPrefix = ''; H5P.fullScreenBrowserPrefix = '';
} }
else if (document.documentElement.webkitRequestFullScreen) { else if (document.documentElement.webkitRequestFullScreen) {
// This code has been changed to allow full screen in Moodle app. H5P.safariBrowser = navigator.userAgent.match(/version\/([.\d]+)/i);
H5P.fullScreenBrowserPrefix = 'webkit'; H5P.safariBrowser = (H5P.safariBrowser === null ? 0 : parseInt(H5P.safariBrowser[1]));
H5P.safariBrowser = 0;
// H5P.safariBrowser = navigator.userAgent.match(/version\/([.\d]+)/i); // Do not allow fullscreen for safari < 7.
// H5P.safariBrowser = (H5P.safariBrowser === null ? 0 : parseInt(H5P.safariBrowser[1])); if (H5P.safariBrowser === 0 || H5P.safariBrowser > 6) {
H5P.fullScreenBrowserPrefix = 'webkit';
// // Do not allow fullscreen for safari < 7. }
// if (H5P.safariBrowser === 0 || H5P.safariBrowser > 6) {
// H5P.fullScreenBrowserPrefix = 'webkit';
// }
} }
else if (document.documentElement.mozRequestFullScreen) { else if (document.documentElement.mozRequestFullScreen) {
H5P.fullScreenBrowserPrefix = 'moz'; H5P.fullScreenBrowserPrefix = 'moz';
} }
else if (document.documentElement.msRequestFullscreen) { else if (document.documentElement.msRequestFullscreen) {
H5P.fullScreenBrowserPrefix = 'ms'; H5P.fullScreenBrowserPrefix = 'ms';
} else if (isIOS()) {
// This code has been added to allow a "fake" full screen in Moodle app.
H5P.fullScreenBrowserPrefix = 'webkit';
H5P.safariBrowser = 0;
} }
/** /**
@ -165,6 +170,17 @@ H5P.init = function (target) {
} }
}) })
; ;
if (isIOS()) {
// Register message listener to enter fullscreen.
window.addEventListener('message', function receiveMessage(event) {
if (event.data == 'enterFullScreen') {
H5P.fullScreen($container, instance);
} else if (event.data == 'exitFullScreen') {
H5P.exitFullScreen();
}
}, false);
}
} }
/** /**
@ -587,7 +603,7 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
}; };
H5P.isFullscreen = true; H5P.isFullscreen = true;
if (H5P.fullScreenBrowserPrefix === undefined || forceSemiFullScreen === true) { if (forceSemiFullScreen === true) {
// Create semi fullscreen. // Create semi fullscreen.
if (H5P.isFramed) { if (H5P.isFramed) {
@ -666,7 +682,13 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
else { else {
var method = (H5P.fullScreenBrowserPrefix === 'ms' ? 'msRequestFullscreen' : H5P.fullScreenBrowserPrefix + 'RequestFullScreen'); var method = (H5P.fullScreenBrowserPrefix === 'ms' ? 'msRequestFullscreen' : H5P.fullScreenBrowserPrefix + 'RequestFullScreen');
var params = (H5P.fullScreenBrowserPrefix === 'webkit' && H5P.safariBrowser === 0 ? Element.ALLOW_KEYBOARD_INPUT : undefined); var params = (H5P.fullScreenBrowserPrefix === 'webkit' && H5P.safariBrowser === 0 ? Element.ALLOW_KEYBOARD_INPUT : undefined);
$element[0][method](params);
if (isIOS()) {
before('h5p-fullscreen-ios');
window.parent.postMessage('enterFullScreen', '*');
} else {
$element[0][method](params);
}
} }
// Allows everone to exit // Allows everone to exit
@ -678,12 +700,28 @@ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFull
document.mozCancelFullScreen(); document.mozCancelFullScreen();
} }
else { else {
document[H5P.fullScreenBrowserPrefix + 'ExitFullscreen'](); done('h5p-fullscreen');
document[H5P.fullScreenBrowserPrefix + 'ExitFullscreen'] && document[H5P.fullScreenBrowserPrefix + 'ExitFullscreen']();
if (isIOS()) {
done('h5p-fullscreen-ios');
window.parent.postMessage('exitFullScreen', '*');
}
} }
}; };
} }
}; };
if (isIOS()) {
// Pass fullscreen messages to child iframes.
window.addEventListener('message', function receiveMessage(event) {
if (event.data === 'enterFullScreen' || event.data === 'exitFullScreen') {
Array.from(document.querySelectorAll('iframe')).forEach(function (iframe) {
iframe.contentWindow && iframe.contentWindow.postMessage(event.data, '*');
});
}
}, false);
}
(function () { (function () {
/** /**
* Helper for adding a query parameter to an existing path that may already * Helper for adding a query parameter to an existing path that may already