Refacto insert cowebsite

This commit is contained in:
Alexis Faizeau 2021-10-25 18:42:51 +02:00
parent 251d14a470
commit f84c4b3276
6 changed files with 98 additions and 110 deletions

View File

@ -5,7 +5,7 @@ import type { ClosePopupEvent } from "./ClosePopupEvent";
import type { EnterLeaveEvent } from "./EnterLeaveEvent"; import type { EnterLeaveEvent } from "./EnterLeaveEvent";
import type { GoToPageEvent } from "./GoToPageEvent"; import type { GoToPageEvent } from "./GoToPageEvent";
import type { LoadPageEvent } from "./LoadPageEvent"; import type { LoadPageEvent } from "./LoadPageEvent";
import { coWebsite, isOpenCoWebsiteEvent } from "./OpenCoWebsiteEvent"; import { isCoWebsite, isOpenCoWebsiteEvent } from "./OpenCoWebsiteEvent";
import type { OpenPopupEvent } from "./OpenPopupEvent"; import type { OpenPopupEvent } from "./OpenPopupEvent";
import type { OpenTabEvent } from "./OpenTabEvent"; import type { OpenTabEvent } from "./OpenTabEvent";
import type { UserInputChatEvent } from "./UserInputChatEvent"; import type { UserInputChatEvent } from "./UserInputChatEvent";
@ -114,11 +114,11 @@ export const iframeQueryMapTypeGuards = {
}, },
openCoWebsite: { openCoWebsite: {
query: isOpenCoWebsiteEvent, query: isOpenCoWebsiteEvent,
answer: coWebsite answer: isCoWebsite
}, },
getCoWebsites: { getCoWebsites: {
query: tg.isUndefined, query: tg.isUndefined,
answer: tg.isArray(coWebsite) answer: tg.isArray(isCoWebsite)
}, },
closeCoWebsite: { closeCoWebsite: {
query: tg.isString, query: tg.isString,

View File

@ -9,7 +9,7 @@ export const isOpenCoWebsiteEvent = new tg.IsInterface()
}) })
.get(); .get();
export const coWebsite = new tg.IsInterface() export const isCoWebsite = new tg.IsInterface()
.withProperties({ .withProperties({
id: tg.isString, id: tg.isString,
position: tg.isNumber, position: tg.isNumber,

View File

@ -1,5 +1,16 @@
import { IframeApiContribution, sendToWorkadventure, queryWorkadventure } from "./IframeApiContribution"; import { IframeApiContribution, sendToWorkadventure, queryWorkadventure } from "./IframeApiContribution";
export class CoWebsite {
constructor(private readonly id: string, public readonly position: number) {}
close() {
return queryWorkadventure({
type: "closeCoWebsite",
data: this.id,
});
}
}
export class WorkadventureNavigationCommands extends IframeApiContribution<WorkadventureNavigationCommands> { export class WorkadventureNavigationCommands extends IframeApiContribution<WorkadventureNavigationCommands> {
callbacks = []; callbacks = [];
@ -45,8 +56,8 @@ export class WorkadventureNavigationCommands extends IframeApiContribution<Worka
}); });
} }
openCoWebsite(url: string, allowApi?: boolean, allowPolicy?: string, position?: number) { async openCoWebsite(url: string, allowApi?: boolean, allowPolicy?: string, position?: number): Promise<CoWebsite> {
return queryWorkadventure({ const result = await queryWorkadventure({
type: "openCoWebsite", type: "openCoWebsite",
data: { data: {
url, url,
@ -55,13 +66,15 @@ export class WorkadventureNavigationCommands extends IframeApiContribution<Worka
position, position,
}, },
}); });
return new CoWebsite(result.id, result.position);
} }
getCoWebsites() { async getCoWebsites(): Promise<CoWebsite[]> {
return queryWorkadventure({ const result = await queryWorkadventure({
type: "getCoWebsites", type: "getCoWebsites",
data: undefined data: undefined
}); });
return result.map((cowebsiteEvent) => new CoWebsite(cowebsiteEvent.id, cowebsiteEvent.position));
} }
/** /**

View File

@ -442,35 +442,50 @@ class CoWebsiteManager {
widthPercent?: number, widthPercent?: number,
position?: number position?: number
): Promise<CoWebsite> { ): Promise<CoWebsite> {
return new Promise((resolve, reject) => {
if (this.coWebsites.length < 1) {
this.loadMain();
} else if (this.coWebsites.length === 5) {
return reject();
}
return this.addCoWebsite((iframeBuffer) => {
const iframe = document.createElement("iframe"); const iframe = document.createElement("iframe");
iframe?.classList.add("pixel");
do {
iframe.id = "cowebsite-iframe-" + (Math.random() + 1).toString(36).substring(7);
} while (iframe.id.toLowerCase().includes('jitsi') || this.getCoWebsiteById(iframe.id));
iframe.src = new URL(url, base).toString() iframe.src = new URL(url, base).toString()
if (allowPolicy) { if (allowPolicy) {
iframe.allow = allowPolicy; iframe.allow = allowPolicy;
} }
const onloadPromise = new Promise<void>((resolve) => {
iframe.onload = () => resolve();
});
if (allowApi) { if (allowApi) {
iframeListener.registerIframe(iframe); iframeListener.registerIframe(iframe);
} }
iframeBuffer.appendChild(iframe);
return iframe;
}, widthPercent, position);
}
public async addCoWebsite(
callback: (iframeBuffer: HTMLDivElement) => PromiseLike<HTMLIFrameElement>|HTMLIFrameElement,
widthPercent?: number,
position?: number
): Promise<CoWebsite> {
return new Promise((resolve, reject) => {
if (this.coWebsites.length < 1) {
this.loadMain();
} else if (this.coWebsites.length === 5) {
throw new Error('Too many we')
}
Promise.resolve(callback(this.cowebsiteBufferDom)).then(iframe =>{
iframe?.classList.add("pixel");
if (!iframe.id) {
do {
iframe.id = "cowebsite-iframe-" + (Math.random() + 1).toString(36).substring(7);
} while (this.getCoWebsiteById(iframe.id));
}
const onloadPromise = new Promise<void>((resolve) => {
iframe.onload = () => resolve();
});
const icon = this.generateCoWebsiteIcon(iframe); const icon = this.generateCoWebsiteIcon(iframe);
const coWebsite = { const coWebsite = {
@ -488,7 +503,6 @@ class CoWebsiteManager {
this.coWebsites.push(coWebsite); this.coWebsites.push(coWebsite);
this.cowebsiteSubIconsDom.appendChild(icon); this.cowebsiteSubIconsDom.appendChild(icon);
this.cowebsiteBufferDom.appendChild(coWebsite.iframe);
const onTimeoutPromise = new Promise<void>((resolve) => { const onTimeoutPromise = new Promise<void>((resolve) => {
setTimeout(() => resolve(), 2000); setTimeout(() => resolve(), 2000);
@ -505,12 +519,12 @@ class CoWebsiteManager {
setTimeout(() => { setTimeout(() => {
this.fire(); this.fire();
position ? position !== undefined ?
this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) : this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) :
this.moveCoWebsite(coWebsite, coWebsite.position); this.moveCoWebsite(coWebsite, coWebsite.position);
}, animationTime); }, animationTime);
} else { } else {
position ? position !== undefined ?
this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) : this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) :
this.moveCoWebsite(coWebsite, coWebsite.position); this.moveCoWebsite(coWebsite, coWebsite.position);
} }
@ -523,56 +537,6 @@ class CoWebsiteManager {
return reject(); return reject();
}); });
}); });
}
/**
* Just like loadCoWebsite but the div can be filled by the user.
*/
public insertCoWebsite(callback: (jitsiBuffer: HTMLDivElement) => Promise<void>, widthPercent?: number): void {
if (this.coWebsites.length < 1) {
this.loadMain();
} else if (this.coWebsites.length === 5) {
return;
}
this.currentOperationPromise = this.currentOperationPromise
.then(() => callback(this.cowebsiteBufferDom))
.then(() => {
const iframe = this.cowebsiteBufferDom.querySelector<HTMLIFrameElement>('[id*="jitsi" i]');
iframe?.classList.add("pixel");
if (!iframe) {
console.error("Error insertCoWebsite => Cannot find Iframe Element on Jitsi DOM");
return;
}
const icon = this.generateCoWebsiteIcon(iframe);
const coWebsite = {
iframe,
icon,
position: 0,
};
this.coWebsites.push(coWebsite);
this.cowebsiteSubIconsDom.appendChild(icon);
if (coWebsite.position === 0) {
this.openMain();
if (widthPercent) {
this.widthPercent = widthPercent;
}
setTimeout(() => {
this.fire();
}, animationTime);
}
this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position);
})
.catch((err) => {
console.error("Error insertCoWebsite => ", err);
}); });
} }

View File

@ -141,7 +141,7 @@ class JitsiFactory {
jitsiUrl?: string, jitsiUrl?: string,
jitsiWidth?: number jitsiWidth?: number
): void { ): void {
coWebsiteManager.insertCoWebsite(async (cowebsiteDiv) => { coWebsiteManager.addCoWebsite(async (cowebsiteDiv) => {
// Jitsi meet external API maintains some data in local storage // Jitsi meet external API maintains some data in local storage
// which is sent via the appData URL parameter when joining a // which is sent via the appData URL parameter when joining a
// conference. Problem is that this data grows indefinitely. Thus // conference. Problem is that this data grows indefinitely. Thus
@ -170,15 +170,22 @@ class JitsiFactory {
} }
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
options.onload = () => resolve(); //we want for the iframe to be loaded before triggering animations. const doResolve = (): void => {
setTimeout(() => resolve(), 2000); //failsafe in case the iframe is deleted before loading or too long to load const iframe = cowebsiteDiv.querySelector<HTMLIFrameElement>('[id*="jitsi" i]');
if (iframe === null) {
throw new Error("Could not find Jitsi Iframe");
}
resolve(iframe);
}
options.onload = () => doResolve(); //we want for the iframe to be loaded before triggering animations.
setTimeout(() => doResolve(), 2000); //failsafe in case the iframe is deleted before loading or too long to load
this.jitsiApi = new window.JitsiMeetExternalAPI(domain, options); this.jitsiApi = new window.JitsiMeetExternalAPI(domain, options);
this.jitsiApi.executeCommand("displayName", playerName); this.jitsiApi.executeCommand("displayName", playerName);
this.jitsiApi.addListener("audioMuteStatusChanged", this.audioCallback); this.jitsiApi.addListener("audioMuteStatusChanged", this.audioCallback);
this.jitsiApi.addListener("videoMuteStatusChanged", this.videoCallback); this.jitsiApi.addListener("videoMuteStatusChanged", this.videoCallback);
}); });
}, jitsiWidth); }, jitsiWidth, 0);
} }
public stop() { public stop() {

View File

@ -170,6 +170,10 @@
.sub-main { .sub-main {
pointer-events: all !important; pointer-events: all !important;
} }
.thumbnail {
transform: scale(0.5, 0.5);
}
} }
.pixel { .pixel {