Refacto insert cowebsite
This commit is contained in:
parent
251d14a470
commit
f84c4b3276
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -442,138 +442,102 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
const icon = this.generateCoWebsiteIcon(iframe);
|
iframeBuffer.appendChild(iframe);
|
||||||
|
|
||||||
const coWebsite = {
|
return iframe;
|
||||||
iframe,
|
}, widthPercent, position);
|
||||||
icon,
|
|
||||||
position: position ?? this.coWebsites.length,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Iframe management on mobile
|
|
||||||
icon.addEventListener("click", () => {
|
|
||||||
if (this.isSmallScreen()) {
|
|
||||||
this.moveRightPreviousCoWebsite(coWebsite, 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.coWebsites.push(coWebsite);
|
|
||||||
this.cowebsiteSubIconsDom.appendChild(icon);
|
|
||||||
this.cowebsiteBufferDom.appendChild(coWebsite.iframe);
|
|
||||||
|
|
||||||
const onTimeoutPromise = new Promise<void>((resolve) => {
|
|
||||||
setTimeout(() => resolve(), 2000);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.currentOperationPromise = this.currentOperationPromise
|
|
||||||
.then(() => Promise.race([onloadPromise, onTimeoutPromise]))
|
|
||||||
.then(() => {
|
|
||||||
if (coWebsite.position === 0) {
|
|
||||||
this.openMain();
|
|
||||||
if (widthPercent) {
|
|
||||||
this.widthPercent = widthPercent;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
this.fire();
|
|
||||||
position ?
|
|
||||||
this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) :
|
|
||||||
this.moveCoWebsite(coWebsite, coWebsite.position);
|
|
||||||
}, animationTime);
|
|
||||||
} else {
|
|
||||||
position ?
|
|
||||||
this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) :
|
|
||||||
this.moveCoWebsite(coWebsite, coWebsite.position);
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolve(coWebsite);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error("Error loadCoWebsite => ", err);
|
|
||||||
this.removeCoWebsiteFromStack(coWebsite);
|
|
||||||
return reject();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public async addCoWebsite(
|
||||||
* Just like loadCoWebsite but the div can be filled by the user.
|
callback: (iframeBuffer: HTMLDivElement) => PromiseLike<HTMLIFrameElement>|HTMLIFrameElement,
|
||||||
*/
|
widthPercent?: number,
|
||||||
public insertCoWebsite(callback: (jitsiBuffer: HTMLDivElement) => Promise<void>, widthPercent?: number): void {
|
position?: number
|
||||||
if (this.coWebsites.length < 1) {
|
): Promise<CoWebsite> {
|
||||||
this.loadMain();
|
return new Promise((resolve, reject) => {
|
||||||
} else if (this.coWebsites.length === 5) {
|
if (this.coWebsites.length < 1) {
|
||||||
return;
|
this.loadMain();
|
||||||
}
|
} else if (this.coWebsites.length === 5) {
|
||||||
|
throw new Error('Too many we')
|
||||||
|
}
|
||||||
|
|
||||||
this.currentOperationPromise = this.currentOperationPromise
|
Promise.resolve(callback(this.cowebsiteBufferDom)).then(iframe =>{
|
||||||
.then(() => callback(this.cowebsiteBufferDom))
|
|
||||||
.then(() => {
|
|
||||||
const iframe = this.cowebsiteBufferDom.querySelector<HTMLIFrameElement>('[id*="jitsi" i]');
|
|
||||||
iframe?.classList.add("pixel");
|
iframe?.classList.add("pixel");
|
||||||
|
|
||||||
if (!iframe) {
|
if (!iframe.id) {
|
||||||
console.error("Error insertCoWebsite => Cannot find Iframe Element on Jitsi DOM");
|
do {
|
||||||
return;
|
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 = {
|
||||||
iframe,
|
iframe,
|
||||||
icon,
|
icon,
|
||||||
position: 0,
|
position: position ?? this.coWebsites.length,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Iframe management on mobile
|
||||||
|
icon.addEventListener("click", () => {
|
||||||
|
if (this.isSmallScreen()) {
|
||||||
|
this.moveRightPreviousCoWebsite(coWebsite, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.coWebsites.push(coWebsite);
|
this.coWebsites.push(coWebsite);
|
||||||
this.cowebsiteSubIconsDom.appendChild(icon);
|
this.cowebsiteSubIconsDom.appendChild(icon);
|
||||||
|
|
||||||
if (coWebsite.position === 0) {
|
const onTimeoutPromise = new Promise<void>((resolve) => {
|
||||||
this.openMain();
|
setTimeout(() => resolve(), 2000);
|
||||||
|
});
|
||||||
|
|
||||||
if (widthPercent) {
|
this.currentOperationPromise = this.currentOperationPromise
|
||||||
this.widthPercent = widthPercent;
|
.then(() => Promise.race([onloadPromise, onTimeoutPromise]))
|
||||||
}
|
.then(() => {
|
||||||
|
if (coWebsite.position === 0) {
|
||||||
|
this.openMain();
|
||||||
|
if (widthPercent) {
|
||||||
|
this.widthPercent = widthPercent;
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.fire();
|
this.fire();
|
||||||
}, animationTime);
|
position !== undefined ?
|
||||||
}
|
this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) :
|
||||||
|
this.moveCoWebsite(coWebsite, coWebsite.position);
|
||||||
|
}, animationTime);
|
||||||
|
} else {
|
||||||
|
position !== undefined ?
|
||||||
|
this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position) :
|
||||||
|
this.moveCoWebsite(coWebsite, coWebsite.position);
|
||||||
|
}
|
||||||
|
|
||||||
this.moveRightPreviousCoWebsite(coWebsite, coWebsite.position);
|
return resolve(coWebsite);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("Error insertCoWebsite => ", err);
|
console.error("Error loadCoWebsite => ", err);
|
||||||
|
this.removeCoWebsiteFromStack(coWebsite);
|
||||||
|
return reject();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeCoWebsite(coWebsite: CoWebsite): Promise<void> {
|
public closeCoWebsite(coWebsite: CoWebsite): Promise<void> {
|
||||||
|
@ -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() {
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user