2021-08-04 18:07:04 +02:00
|
|
|
import { HtmlUtils } from "./HtmlUtils";
|
|
|
|
import { Subject } from "rxjs";
|
|
|
|
import { iframeListener } from "../Api/IframeListener";
|
|
|
|
import { touchScreenManager } from "../Touch/TouchScreenManager";
|
|
|
|
import { waScaleManager } from "../Phaser/Services/WaScaleManager";
|
2020-08-13 18:21:48 +02:00
|
|
|
|
2020-10-27 16:59:12 +01:00
|
|
|
enum iframeStates {
|
|
|
|
closed = 1,
|
|
|
|
loading, // loading an iframe can be slow, so we show some placeholder until it is ready
|
|
|
|
opened,
|
|
|
|
}
|
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
const cowebsiteDomId = "cowebsite"; // the id of the whole container.
|
|
|
|
const cowebsiteContainerDomId = "cowebsite-container"; // the id of the whole container.
|
|
|
|
const cowebsiteMainDomId = "cowebsite-slot-0"; // the id of the parent div of the iframe.
|
|
|
|
const cowebsiteBufferDomId = "cowebsite-buffer"; // the id of the container who contains cowebsite iframes.
|
2021-08-04 18:07:04 +02:00
|
|
|
const cowebsiteAsideDomId = "cowebsite-aside"; // the id of the parent div of the iframe.
|
2021-10-07 14:44:15 +02:00
|
|
|
const cowebsiteSubIconsDomId = "cowebsite-sub-icons";
|
2021-08-04 18:07:04 +02:00
|
|
|
export const cowebsiteCloseButtonId = "cowebsite-close";
|
|
|
|
const cowebsiteFullScreenButtonId = "cowebsite-fullscreen";
|
|
|
|
const cowebsiteOpenFullScreenImageId = "cowebsite-fullscreen-open";
|
|
|
|
const cowebsiteCloseFullScreenImageId = "cowebsite-fullscreen-close";
|
2020-10-27 16:59:12 +01:00
|
|
|
const animationTime = 500; //time used by the css transitions, in ms.
|
|
|
|
|
2021-06-07 17:48:39 +02:00
|
|
|
interface TouchMoveCoordinates {
|
|
|
|
x: number;
|
|
|
|
y: number;
|
|
|
|
}
|
|
|
|
|
2021-10-12 10:38:49 +02:00
|
|
|
export type CoWebsite = {
|
2021-10-07 14:44:15 +02:00
|
|
|
iframe: HTMLIFrameElement,
|
|
|
|
icon: HTMLDivElement,
|
|
|
|
position: number
|
|
|
|
}
|
|
|
|
|
2021-10-12 10:38:49 +02:00
|
|
|
type CoWebsiteSlot = {
|
2021-10-07 14:44:15 +02:00
|
|
|
container: HTMLElement,
|
|
|
|
position: number
|
|
|
|
}
|
|
|
|
|
2020-10-27 16:59:12 +01:00
|
|
|
class CoWebsiteManager {
|
2021-10-07 14:44:15 +02:00
|
|
|
private openedMain: iframeStates = iframeStates.closed;
|
2020-08-13 18:21:48 +02:00
|
|
|
|
2021-03-18 15:05:15 +01:00
|
|
|
private _onResize: Subject<void> = new Subject();
|
|
|
|
public onResize = this._onResize.asObservable();
|
2020-11-10 15:22:30 +01:00
|
|
|
/**
|
|
|
|
* Quickly going in and out of an iframe trigger can create conflicts between the iframe states.
|
|
|
|
* So we use this promise to queue up every cowebsite state transition
|
|
|
|
*/
|
2020-11-16 16:15:21 +01:00
|
|
|
private currentOperationPromise: Promise<void> = Promise.resolve();
|
2021-10-07 14:44:15 +02:00
|
|
|
private cowebsiteDom: HTMLDivElement;
|
|
|
|
private cowebsiteContainerDom: HTMLDivElement;
|
2021-03-15 18:43:13 +01:00
|
|
|
private resizing: boolean = false;
|
2021-03-17 11:52:41 +01:00
|
|
|
private cowebsiteMainDom: HTMLDivElement;
|
2021-10-07 14:44:15 +02:00
|
|
|
private cowebsiteBufferDom: HTMLDivElement;
|
2021-03-17 11:52:41 +01:00
|
|
|
private cowebsiteAsideDom: HTMLDivElement;
|
2021-10-07 14:44:15 +02:00
|
|
|
private cowebsiteSubIconsDom: HTMLDivElement;
|
2021-08-04 18:07:04 +02:00
|
|
|
private previousTouchMoveCoordinates: TouchMoveCoordinates | null = null; //only use on touchscreens to track touch movement
|
2021-05-12 10:35:14 +02:00
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
private coWebsites: CoWebsite[] = [];
|
|
|
|
|
|
|
|
private slots: CoWebsiteSlot[];
|
|
|
|
|
|
|
|
private resizeObserver = new ResizeObserver(entries => {
|
|
|
|
this.resizeAllIframes();
|
|
|
|
});
|
|
|
|
|
2021-03-17 11:52:41 +01:00
|
|
|
get width(): number {
|
2021-10-07 14:44:15 +02:00
|
|
|
return this.cowebsiteDom.clientWidth;
|
2021-03-17 11:52:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
set width(width: number) {
|
2021-10-07 14:44:15 +02:00
|
|
|
this.cowebsiteDom.style.width = width + "px";
|
2021-03-17 11:52:41 +01:00
|
|
|
}
|
2021-03-18 15:05:15 +01:00
|
|
|
|
2021-08-30 19:32:02 +02:00
|
|
|
set widthPercent(width: number) {
|
2021-10-07 14:44:15 +02:00
|
|
|
this.cowebsiteDom.style.width = width + "%";
|
2021-08-30 19:32:02 +02:00
|
|
|
}
|
|
|
|
|
2021-03-18 15:05:15 +01:00
|
|
|
get height(): number {
|
2021-10-07 14:44:15 +02:00
|
|
|
return this.cowebsiteDom.clientHeight;
|
2021-03-18 15:05:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
set height(height: number) {
|
2021-10-07 14:44:15 +02:00
|
|
|
this.cowebsiteDom.style.height = height + "px";
|
2021-03-18 15:05:15 +01:00
|
|
|
}
|
2021-03-28 16:53:15 +02:00
|
|
|
|
2021-03-18 15:05:15 +01:00
|
|
|
get verticalMode(): boolean {
|
|
|
|
return window.innerWidth < window.innerHeight;
|
|
|
|
}
|
2021-03-28 16:53:15 +02:00
|
|
|
|
2021-03-18 15:05:15 +01:00
|
|
|
get isFullScreen(): boolean {
|
2021-03-24 15:51:18 +01:00
|
|
|
return this.verticalMode ? this.height === window.innerHeight : this.width === window.innerWidth;
|
2021-03-18 15:05:15 +01:00
|
|
|
}
|
2021-03-06 16:00:07 +01:00
|
|
|
|
2020-11-16 16:15:21 +01:00
|
|
|
constructor() {
|
2021-10-07 14:44:15 +02:00
|
|
|
this.cowebsiteDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteDomId);
|
|
|
|
this.cowebsiteContainerDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteContainerDomId);
|
2021-03-17 11:52:41 +01:00
|
|
|
this.cowebsiteMainDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteMainDomId);
|
2021-10-07 14:44:15 +02:00
|
|
|
this.cowebsiteBufferDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteBufferDomId);
|
2021-03-17 11:52:41 +01:00
|
|
|
this.cowebsiteAsideDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteAsideDomId);
|
2021-10-07 14:44:15 +02:00
|
|
|
this.cowebsiteSubIconsDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteSubIconsDomId);
|
|
|
|
this.initResizeListeners(touchScreenManager.supportTouchScreen);
|
|
|
|
|
|
|
|
this.resizeObserver.observe(this.cowebsiteDom);
|
|
|
|
this.resizeObserver.observe(this.cowebsiteContainerDom);
|
|
|
|
|
|
|
|
this.slots = [
|
|
|
|
{
|
|
|
|
container: this.cowebsiteMainDom,
|
|
|
|
position: 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
container: HtmlUtils.getElementByIdOrFail<HTMLDivElement>('cowebsite-slot-1'),
|
|
|
|
position: 1
|
|
|
|
},
|
|
|
|
{
|
|
|
|
container: HtmlUtils.getElementByIdOrFail<HTMLDivElement>('cowebsite-slot-2'),
|
|
|
|
position: 2
|
|
|
|
},
|
|
|
|
{
|
|
|
|
container: HtmlUtils.getElementByIdOrFail<HTMLDivElement>('cowebsite-slot-3'),
|
|
|
|
position: 3
|
|
|
|
},
|
|
|
|
{
|
|
|
|
container: HtmlUtils.getElementByIdOrFail<HTMLDivElement>('cowebsite-slot-4'),
|
|
|
|
position: 4
|
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
this.slots.forEach((slot) => {
|
|
|
|
this.resizeObserver.observe(slot.container);
|
|
|
|
});
|
2021-03-17 11:52:41 +01:00
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
this.initActionsListeners();
|
2021-03-17 11:52:41 +01:00
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
const buttonCloseCoWebsites = HtmlUtils.getElementByIdOrFail(cowebsiteCloseButtonId);
|
|
|
|
buttonCloseCoWebsites.addEventListener("click", () => {
|
|
|
|
if (this.isSmallScreen() && this.coWebsites.length > 1) {
|
|
|
|
const coWebsite = this.getCoWebsiteByPosition(0);
|
|
|
|
|
|
|
|
if (coWebsite) {
|
|
|
|
this.removeCoWebsiteFromStack(coWebsite);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
buttonCloseCoWebsites.blur();
|
|
|
|
this.closeCoWebsites();
|
2021-03-17 11:52:41 +01:00
|
|
|
});
|
2021-06-03 20:05:39 +02:00
|
|
|
|
|
|
|
const buttonFullScreenFrame = HtmlUtils.getElementByIdOrFail(cowebsiteFullScreenButtonId);
|
2021-08-04 18:07:04 +02:00
|
|
|
buttonFullScreenFrame.addEventListener("click", () => {
|
2021-06-03 20:05:39 +02:00
|
|
|
buttonFullScreenFrame.blur();
|
2021-03-17 18:57:00 +01:00
|
|
|
this.fullscreen();
|
|
|
|
});
|
2021-03-17 11:52:41 +01:00
|
|
|
}
|
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
public getDevicePixelRatio(): number {
|
|
|
|
//on chrome engines, movementX and movementY return global screens coordinates while other browser return pixels
|
|
|
|
//so on chrome-based browser we need to adjust using 'devicePixelRatio'
|
|
|
|
return window.navigator.userAgent.includes("Firefox") ? 1 : window.devicePixelRatio;
|
|
|
|
}
|
|
|
|
|
|
|
|
private isSmallScreen(): boolean {
|
2021-10-29 15:23:09 +02:00
|
|
|
return window.matchMedia("(max-aspect-ratio: 1/1)").matches ||
|
|
|
|
window.matchMedia("(max-width:960px) and (max-height:768px)").matches;
|
2021-10-07 14:44:15 +02:00
|
|
|
}
|
|
|
|
|
2021-08-04 18:07:04 +02:00
|
|
|
private initResizeListeners(touchMode: boolean) {
|
|
|
|
const movecallback = (event: MouseEvent | TouchEvent) => {
|
2021-06-07 17:48:39 +02:00
|
|
|
let x, y;
|
2021-08-04 18:07:04 +02:00
|
|
|
if (event.type === "mousemove") {
|
2021-06-07 17:48:39 +02:00
|
|
|
x = (event as MouseEvent).movementX / this.getDevicePixelRatio();
|
|
|
|
y = (event as MouseEvent).movementY / this.getDevicePixelRatio();
|
|
|
|
} else {
|
|
|
|
const touchEvent = (event as TouchEvent).touches[0];
|
2021-08-04 18:07:04 +02:00
|
|
|
const last = { x: touchEvent.pageX, y: touchEvent.pageY };
|
2021-06-07 17:48:39 +02:00
|
|
|
const previous = this.previousTouchMoveCoordinates as TouchMoveCoordinates;
|
|
|
|
this.previousTouchMoveCoordinates = last;
|
|
|
|
x = last.x - previous.x;
|
|
|
|
y = last.y - previous.y;
|
|
|
|
}
|
2021-08-04 18:07:04 +02:00
|
|
|
|
|
|
|
this.verticalMode ? (this.height += y) : (this.width -= x);
|
2021-03-18 15:05:15 +01:00
|
|
|
this.fire();
|
2021-08-04 18:07:04 +02:00
|
|
|
};
|
2021-03-28 16:53:15 +02:00
|
|
|
|
2021-08-04 18:07:04 +02:00
|
|
|
this.cowebsiteAsideDom.addEventListener(touchMode ? "touchstart" : "mousedown", (event) => {
|
2021-10-12 10:38:49 +02:00
|
|
|
this.cowebsiteMainDom.style.display = "none";
|
2021-03-15 18:43:13 +01:00
|
|
|
this.resizing = true;
|
2021-06-07 17:48:39 +02:00
|
|
|
if (touchMode) {
|
|
|
|
const touchEvent = (event as TouchEvent).touches[0];
|
2021-08-04 18:07:04 +02:00
|
|
|
this.previousTouchMoveCoordinates = { x: touchEvent.pageX, y: touchEvent.pageY };
|
2021-06-07 17:48:39 +02:00
|
|
|
}
|
2021-03-17 11:52:41 +01:00
|
|
|
|
2021-08-04 18:07:04 +02:00
|
|
|
document.addEventListener(touchMode ? "touchmove" : "mousemove", movecallback);
|
2021-03-15 18:43:13 +01:00
|
|
|
});
|
|
|
|
|
2021-08-04 18:07:04 +02:00
|
|
|
document.addEventListener(touchMode ? "touchend" : "mouseup", (event) => {
|
2021-03-15 18:43:13 +01:00
|
|
|
if (!this.resizing) return;
|
2021-06-07 17:48:39 +02:00
|
|
|
if (touchMode) {
|
|
|
|
this.previousTouchMoveCoordinates = null;
|
|
|
|
}
|
2021-08-04 18:07:04 +02:00
|
|
|
document.removeEventListener(touchMode ? "touchmove" : "mousemove", movecallback);
|
2021-10-07 14:44:15 +02:00
|
|
|
this.cowebsiteMainDom.style.display = "block";
|
2021-03-15 18:43:13 +01:00
|
|
|
this.resizing = false;
|
2021-10-12 10:38:49 +02:00
|
|
|
this.cowebsiteMainDom.style.display = "flex";
|
2021-03-15 18:43:13 +01:00
|
|
|
});
|
2020-11-16 16:15:21 +01:00
|
|
|
}
|
2021-03-28 16:53:15 +02:00
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
private closeMain(): void {
|
|
|
|
this.cowebsiteDom.classList.remove("loaded"); //edit the css class to trigger the transition
|
|
|
|
this.cowebsiteDom.classList.add("hidden");
|
|
|
|
this.openedMain = iframeStates.closed;
|
|
|
|
this.resetStyleMain();
|
|
|
|
this.cowebsiteDom.style.display = "none";
|
|
|
|
}
|
|
|
|
private loadMain(): void {
|
|
|
|
this.cowebsiteDom.style.display = "flex";
|
|
|
|
this.cowebsiteDom.classList.remove("hidden"); //edit the css class to trigger the transition
|
|
|
|
this.cowebsiteDom.classList.add("loading");
|
|
|
|
this.openedMain = iframeStates.loading;
|
|
|
|
}
|
|
|
|
private openMain(): void {
|
|
|
|
this.cowebsiteDom.classList.remove("loading", "hidden"); //edit the css class to trigger the transition
|
|
|
|
this.openedMain = iframeStates.opened;
|
|
|
|
this.resetStyleMain();
|
|
|
|
}
|
|
|
|
|
|
|
|
public resetStyleMain() {
|
|
|
|
this.cowebsiteDom.style.width = "";
|
|
|
|
this.cowebsiteDom.style.height = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
private initActionsListeners() {
|
|
|
|
this.slots.forEach((slot: CoWebsiteSlot) => {
|
|
|
|
const expandButton = slot.container.querySelector('.expand');
|
|
|
|
const highlightButton = slot.container.querySelector('.hightlight');
|
|
|
|
const closeButton = slot.container.querySelector('.close');
|
|
|
|
|
|
|
|
if (expandButton) {
|
|
|
|
expandButton.addEventListener('click', (event) => {
|
|
|
|
event.preventDefault();
|
|
|
|
const coWebsite = this.getCoWebsiteByPosition(slot.position);
|
|
|
|
|
|
|
|
if (!coWebsite) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.moveRightPreviousCoWebsite(coWebsite, 0);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (highlightButton) {
|
|
|
|
highlightButton.addEventListener('click', (event) => {
|
|
|
|
event.preventDefault();
|
|
|
|
const coWebsite = this.getCoWebsiteByPosition(slot.position);
|
|
|
|
|
|
|
|
if (!coWebsite) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.moveRightPreviousCoWebsite(coWebsite, 1);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (closeButton) {
|
|
|
|
closeButton.addEventListener('click', (event) => {
|
|
|
|
event.preventDefault();
|
|
|
|
const coWebsite = this.getCoWebsiteByPosition(slot.position);
|
|
|
|
|
|
|
|
if (!coWebsite) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.removeCoWebsiteFromStack(coWebsite);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2020-11-16 16:15:21 +01:00
|
|
|
}
|
2021-03-06 16:00:07 +01:00
|
|
|
|
2021-10-12 10:38:49 +02:00
|
|
|
public getCoWebsites(): CoWebsite[] {
|
|
|
|
return this.coWebsites;
|
|
|
|
}
|
|
|
|
|
|
|
|
public getCoWebsiteById(coWebsiteId: string): CoWebsite|undefined {
|
2021-10-07 14:44:15 +02:00
|
|
|
return this.coWebsites.find((coWebsite: CoWebsite) => coWebsite.iframe.id === coWebsiteId);
|
2020-10-27 16:59:12 +01:00
|
|
|
}
|
2021-10-07 14:44:15 +02:00
|
|
|
|
|
|
|
private getSlotByPosition(position: number): CoWebsiteSlot|undefined {
|
|
|
|
return this.slots.find((slot: CoWebsiteSlot) => slot.position === position);
|
2020-10-27 16:59:12 +01:00
|
|
|
}
|
2021-10-07 14:44:15 +02:00
|
|
|
|
|
|
|
private getCoWebsiteByPosition(position: number): CoWebsite|undefined {
|
|
|
|
return this.coWebsites.find((coWebsite: CoWebsite) => coWebsite.position === position);
|
2020-10-27 16:59:12 +01:00
|
|
|
}
|
2021-03-17 11:52:41 +01:00
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
private setIframeOffset(coWebsite: CoWebsite, slot: CoWebsiteSlot) {
|
|
|
|
const bounding = slot.container.getBoundingClientRect();
|
|
|
|
|
2021-10-25 18:43:17 +02:00
|
|
|
if (coWebsite.iframe.classList.contains('thumbnail')) {
|
|
|
|
coWebsite.iframe.style.width = ((bounding.right - bounding.left) * 2) + 'px';
|
|
|
|
coWebsite.iframe.style.height = ((bounding.bottom - bounding.top) * 2) + 'px';
|
|
|
|
coWebsite.iframe.style.top = (bounding.top - (Math.floor(bounding.height * 0.5))) + 'px';
|
|
|
|
coWebsite.iframe.style.left = (bounding.left - (Math.floor(bounding.width * 0.5))) + 'px';
|
|
|
|
} else {
|
|
|
|
coWebsite.iframe.style.top = bounding.top + 'px';
|
|
|
|
coWebsite.iframe.style.left = bounding.left + 'px';
|
|
|
|
coWebsite.iframe.style.width = (bounding.right - bounding.left) + 'px';
|
|
|
|
coWebsite.iframe.style.height = (bounding.bottom - bounding.top) + 'px';
|
|
|
|
}
|
2021-03-17 11:52:41 +01:00
|
|
|
}
|
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
private resizeAllIframes() {
|
|
|
|
this.coWebsites.forEach((coWebsite: CoWebsite) => {
|
|
|
|
const slot = this.getSlotByPosition(coWebsite.position);
|
|
|
|
|
|
|
|
if (slot) {
|
|
|
|
this.setIframeOffset(coWebsite, slot);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private moveCoWebsite(coWebsite: CoWebsite, newPosition: number) {
|
|
|
|
const oldSlot = this.getSlotByPosition(coWebsite.position);
|
|
|
|
const newSlot = this.getSlotByPosition(newPosition);
|
|
|
|
|
|
|
|
if (!newSlot) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
coWebsite.iframe.scrolling = newPosition === 0 || newPosition === 1 ? "yes" : "no";
|
|
|
|
|
|
|
|
if (newPosition === 0) {
|
|
|
|
coWebsite.iframe.classList.add('main');
|
|
|
|
coWebsite.icon.style.display = "none";
|
|
|
|
} else {
|
|
|
|
coWebsite.iframe.classList.remove('main');
|
|
|
|
coWebsite.icon.style.display = "flex";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (newPosition === 1) {
|
|
|
|
coWebsite.iframe.classList.add('sub-main');
|
|
|
|
} else {
|
|
|
|
coWebsite.iframe.classList.remove('sub-main');
|
|
|
|
}
|
|
|
|
|
2021-10-25 18:43:17 +02:00
|
|
|
if (newPosition >= 2) {
|
|
|
|
coWebsite.iframe.classList.add('thumbnail');
|
|
|
|
} else {
|
|
|
|
coWebsite.iframe.classList.remove('thumbnail');
|
|
|
|
}
|
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
coWebsite.position = newPosition;
|
|
|
|
|
|
|
|
if (oldSlot && !this.getCoWebsiteByPosition(oldSlot.position)) {
|
|
|
|
oldSlot.container.style.display = 'none';
|
|
|
|
}
|
|
|
|
|
|
|
|
newSlot.container.style.display = 'block';
|
|
|
|
|
|
|
|
coWebsite.iframe.classList.remove('pixel');
|
|
|
|
|
|
|
|
this.resizeAllIframes();
|
|
|
|
}
|
|
|
|
|
|
|
|
private moveLeftPreviousCoWebsite(coWebsite: CoWebsite, newPosition: number) {
|
|
|
|
const nextCoWebsite = this.getCoWebsiteByPosition(coWebsite.position + 1);
|
|
|
|
|
|
|
|
this.moveCoWebsite(coWebsite, newPosition);
|
|
|
|
|
|
|
|
if (nextCoWebsite) {
|
|
|
|
this.moveLeftPreviousCoWebsite(nextCoWebsite, nextCoWebsite.position - 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private moveRightPreviousCoWebsite(coWebsite: CoWebsite, newPosition: number) {
|
|
|
|
if (newPosition >= 5) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const currentCoWebsite = this.getCoWebsiteByPosition(newPosition);
|
|
|
|
|
|
|
|
this.moveCoWebsite(coWebsite, newPosition);
|
|
|
|
|
|
|
|
if (newPosition === 4 ||
|
|
|
|
!currentCoWebsite ||
|
|
|
|
currentCoWebsite.iframe.id === coWebsite.iframe.id
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!currentCoWebsite) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.moveRightPreviousCoWebsite(currentCoWebsite, currentCoWebsite.position + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
private removeCoWebsiteFromStack(coWebsite: CoWebsite) {
|
|
|
|
this.coWebsites = this.coWebsites.filter(
|
|
|
|
(coWebsiteToRemove: CoWebsite) => coWebsiteToRemove.iframe.id !== coWebsite.iframe.id
|
|
|
|
);
|
|
|
|
|
|
|
|
if (this.coWebsites.length < 1) {
|
|
|
|
this.closeMain();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coWebsite.position > 0) {
|
|
|
|
const slot = this.getSlotByPosition(coWebsite.position);
|
|
|
|
if (slot) {
|
|
|
|
slot.container.style.display = 'none';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const previousCoWebsite = this.coWebsites.find((coWebsiteToCheck: CoWebsite) =>
|
|
|
|
coWebsite.position + 1 === coWebsiteToCheck.position
|
|
|
|
);
|
|
|
|
|
|
|
|
if (previousCoWebsite) {
|
|
|
|
this.moveLeftPreviousCoWebsite(previousCoWebsite, coWebsite.position);
|
|
|
|
}
|
|
|
|
|
|
|
|
coWebsite.icon.remove();
|
|
|
|
coWebsite.iframe.remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
public searchJitsi(): CoWebsite|undefined {
|
|
|
|
return this.coWebsites.find((coWebsite : CoWebsite) =>
|
|
|
|
coWebsite.iframe.id.toLowerCase().includes('jitsi')
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private generateCoWebsiteIcon(iframe: HTMLIFrameElement): HTMLDivElement {
|
|
|
|
const icon = document.createElement("div");
|
|
|
|
icon.id = "cowebsite-icon-" + iframe.id;
|
|
|
|
icon.style.display = "none";
|
|
|
|
|
|
|
|
const iconImage = document.createElement("img");
|
2021-10-26 14:16:00 +02:00
|
|
|
iconImage.src = `https://www.google.com/s2/favicons?sz=64&domain_url=${iframe.src}`;
|
2021-10-07 14:44:15 +02:00
|
|
|
const url = new URL(iframe.src);
|
|
|
|
iconImage.alt = url.hostname;
|
|
|
|
|
|
|
|
icon.appendChild(iconImage);
|
|
|
|
|
|
|
|
return icon;
|
2020-10-27 16:59:12 +01:00
|
|
|
}
|
2020-08-13 18:21:48 +02:00
|
|
|
|
2021-09-01 14:55:29 +02:00
|
|
|
public loadCoWebsite(
|
|
|
|
url: string,
|
|
|
|
base: string,
|
|
|
|
allowApi?: boolean,
|
|
|
|
allowPolicy?: string,
|
2021-10-07 14:44:15 +02:00
|
|
|
widthPercent?: number,
|
|
|
|
position?: number
|
|
|
|
): Promise<CoWebsite> {
|
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
return this.addCoWebsite((iframeBuffer) => {
|
2021-10-07 14:44:15 +02:00
|
|
|
const iframe = document.createElement("iframe");
|
|
|
|
iframe.src = new URL(url, base).toString()
|
|
|
|
|
|
|
|
if (allowPolicy) {
|
|
|
|
iframe.allow = allowPolicy;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (allowApi) {
|
|
|
|
iframeListener.registerIframe(iframe);
|
|
|
|
}
|
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
iframeBuffer.appendChild(iframe);
|
2021-10-07 14:44:15 +02:00
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
return iframe;
|
|
|
|
}, widthPercent, position);
|
2020-08-31 12:18:00 +02:00
|
|
|
}
|
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
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')
|
|
|
|
}
|
2021-10-07 14:44:15 +02:00
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
Promise.resolve(callback(this.cowebsiteBufferDom)).then(iframe =>{
|
2021-10-07 14:44:15 +02:00
|
|
|
iframe?.classList.add("pixel");
|
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
if (!iframe.id) {
|
|
|
|
do {
|
|
|
|
iframe.id = "cowebsite-iframe-" + (Math.random() + 1).toString(36).substring(7);
|
|
|
|
} while (this.getCoWebsiteById(iframe.id));
|
2021-10-07 14:44:15 +02:00
|
|
|
}
|
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
const onloadPromise = new Promise<void>((resolve) => {
|
|
|
|
iframe.onload = () => resolve();
|
|
|
|
});
|
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
const icon = this.generateCoWebsiteIcon(iframe);
|
|
|
|
|
|
|
|
const coWebsite = {
|
|
|
|
iframe,
|
|
|
|
icon,
|
2021-10-25 18:42:51 +02:00
|
|
|
position: position ?? this.coWebsites.length,
|
2021-10-07 14:44:15 +02:00
|
|
|
};
|
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
// Iframe management on mobile
|
|
|
|
icon.addEventListener("click", () => {
|
|
|
|
if (this.isSmallScreen()) {
|
|
|
|
this.moveRightPreviousCoWebsite(coWebsite, 0);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
this.coWebsites.push(coWebsite);
|
|
|
|
this.cowebsiteSubIconsDom.appendChild(icon);
|
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
const onTimeoutPromise = new Promise<void>((resolve) => {
|
|
|
|
setTimeout(() => resolve(), 2000);
|
|
|
|
});
|
2021-10-07 14:44:15 +02:00
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
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 !== 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);
|
|
|
|
}
|
2021-10-07 14:44:15 +02:00
|
|
|
|
2021-10-25 18:42:51 +02:00
|
|
|
return resolve(coWebsite);
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.error("Error loadCoWebsite => ", err);
|
|
|
|
this.removeCoWebsiteFromStack(coWebsite);
|
|
|
|
return reject();
|
|
|
|
});
|
2021-08-04 18:07:04 +02:00
|
|
|
});
|
2021-10-25 18:42:51 +02:00
|
|
|
});
|
2020-08-13 18:21:48 +02:00
|
|
|
}
|
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
public closeCoWebsite(coWebsite: CoWebsite): Promise<void> {
|
2021-08-04 18:07:04 +02:00
|
|
|
this.currentOperationPromise = this.currentOperationPromise.then(
|
|
|
|
() =>
|
2021-10-07 14:44:15 +02:00
|
|
|
new Promise((resolve) => {
|
|
|
|
if (this.coWebsites.length === 1) {
|
|
|
|
if (this.openedMain === iframeStates.closed) resolve(); //this method may be called twice, in case of iframe error for example
|
|
|
|
this.closeMain();
|
|
|
|
this.fire();
|
2021-08-04 18:07:04 +02:00
|
|
|
}
|
2021-10-07 14:44:15 +02:00
|
|
|
|
|
|
|
if (coWebsite) {
|
|
|
|
iframeListener.unregisterIframe(coWebsite.iframe);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.removeCoWebsiteFromStack(coWebsite);
|
|
|
|
resolve();
|
2021-08-04 18:07:04 +02:00
|
|
|
})
|
|
|
|
);
|
2020-11-10 15:22:30 +01:00
|
|
|
return this.currentOperationPromise;
|
2020-08-13 18:21:48 +02:00
|
|
|
}
|
|
|
|
|
2021-10-07 14:44:15 +02:00
|
|
|
public closeJitsi() {
|
|
|
|
const jitsi = this.searchJitsi();
|
|
|
|
if (jitsi) {
|
|
|
|
this.closeCoWebsite(jitsi);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public closeCoWebsites(): Promise<void> {
|
|
|
|
this.currentOperationPromise = this.currentOperationPromise
|
|
|
|
.then(() => {
|
|
|
|
this.coWebsites.forEach((coWebsite: CoWebsite) => {
|
|
|
|
this.closeCoWebsite(coWebsite);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return this.currentOperationPromise;
|
|
|
|
}
|
|
|
|
|
2021-08-04 18:07:04 +02:00
|
|
|
public getGameSize(): { width: number; height: number } {
|
2021-10-07 14:44:15 +02:00
|
|
|
if (this.openedMain !== iframeStates.opened) {
|
2020-08-13 18:21:48 +02:00
|
|
|
return {
|
|
|
|
width: window.innerWidth,
|
2021-08-04 18:07:04 +02:00
|
|
|
height: window.innerHeight,
|
|
|
|
};
|
2020-08-13 18:21:48 +02:00
|
|
|
}
|
2021-03-18 15:05:15 +01:00
|
|
|
if (!this.verticalMode) {
|
2020-08-13 18:21:48 +02:00
|
|
|
return {
|
2021-03-17 11:52:41 +01:00
|
|
|
width: window.innerWidth - this.width,
|
2021-08-04 18:07:04 +02:00
|
|
|
height: window.innerHeight,
|
|
|
|
};
|
2020-08-13 18:21:48 +02:00
|
|
|
} else {
|
|
|
|
return {
|
|
|
|
width: window.innerWidth,
|
2021-03-18 15:05:15 +01:00
|
|
|
height: window.innerHeight - this.height,
|
2021-08-04 18:07:04 +02:00
|
|
|
};
|
2020-08-13 18:21:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-27 16:59:12 +01:00
|
|
|
private fire(): void {
|
2021-03-18 15:05:15 +01:00
|
|
|
this._onResize.next();
|
2021-08-04 18:07:04 +02:00
|
|
|
waScaleManager.applyNewSize();
|
2020-08-13 18:21:48 +02:00
|
|
|
}
|
|
|
|
|
2021-03-17 18:57:00 +01:00
|
|
|
private fullscreen(): void {
|
2021-03-18 15:05:15 +01:00
|
|
|
if (this.isFullScreen) {
|
2021-10-07 14:44:15 +02:00
|
|
|
this.resetStyleMain();
|
2021-03-24 15:51:18 +01:00
|
|
|
this.fire();
|
2021-03-17 18:57:00 +01:00
|
|
|
//we don't trigger a resize of the phaser game since it won't be visible anyway.
|
2021-08-04 18:07:04 +02:00
|
|
|
HtmlUtils.getElementByIdOrFail(cowebsiteOpenFullScreenImageId).style.display = "inline";
|
|
|
|
HtmlUtils.getElementByIdOrFail(cowebsiteCloseFullScreenImageId).style.display = "none";
|
2021-03-17 18:57:00 +01:00
|
|
|
} else {
|
2021-08-04 18:07:04 +02:00
|
|
|
this.verticalMode ? (this.height = window.innerHeight) : (this.width = window.innerWidth);
|
2021-03-17 18:57:00 +01:00
|
|
|
//we don't trigger a resize of the phaser game since it won't be visible anyway.
|
2021-08-04 18:07:04 +02:00
|
|
|
HtmlUtils.getElementByIdOrFail(cowebsiteOpenFullScreenImageId).style.display = "none";
|
|
|
|
HtmlUtils.getElementByIdOrFail(cowebsiteCloseFullScreenImageId).style.display = "inline";
|
2020-08-13 18:21:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-27 16:59:12 +01:00
|
|
|
|
2021-03-06 16:00:07 +01:00
|
|
|
export const coWebsiteManager = new CoWebsiteManager();
|