2021-08-03 18:29:10 +02:00
|
|
|
import type { GameScene } from "./GameScene";
|
|
|
|
import { iframeListener } from "../../Api/IframeListener";
|
|
|
|
import type { Subscription } from "rxjs";
|
|
|
|
import type { CreateEmbeddedWebsiteEvent, ModifyEmbeddedWebsiteEvent } from "../../Api/Events/EmbeddedWebsiteEvent";
|
|
|
|
import DOMElement = Phaser.GameObjects.DOMElement;
|
|
|
|
|
|
|
|
type EmbeddedWebsite = CreateEmbeddedWebsiteEvent & { iframe: HTMLIFrameElement; phaserObject: DOMElement };
|
|
|
|
|
|
|
|
export class EmbeddedWebsiteManager {
|
|
|
|
private readonly embeddedWebsites = new Map<string, EmbeddedWebsite>();
|
|
|
|
private readonly subscription: Subscription;
|
|
|
|
|
|
|
|
constructor(private gameScene: GameScene) {
|
|
|
|
iframeListener.registerAnswerer("getEmbeddedWebsite", (name: string) => {
|
|
|
|
const website = this.embeddedWebsites.get(name);
|
|
|
|
if (website === undefined) {
|
|
|
|
throw new Error('Cannot find embedded website with name "' + name + '"');
|
|
|
|
}
|
|
|
|
const rect = website.iframe.getBoundingClientRect();
|
|
|
|
return {
|
|
|
|
url: website.url,
|
|
|
|
name: website.name,
|
|
|
|
visible: website.visible,
|
|
|
|
allowApi: website.allowApi,
|
|
|
|
allow: website.allow,
|
|
|
|
position: {
|
|
|
|
x: website.phaserObject.x,
|
|
|
|
y: website.phaserObject.y,
|
|
|
|
width: rect["width"],
|
|
|
|
height: rect["height"],
|
|
|
|
},
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
iframeListener.registerAnswerer("deleteEmbeddedWebsite", (name: string) => {
|
|
|
|
const website = this.embeddedWebsites.get(name);
|
|
|
|
if (!website) {
|
|
|
|
throw new Error('Could not find website to delete with the name "' + name + '" in your map');
|
|
|
|
}
|
|
|
|
|
|
|
|
website.iframe.remove();
|
|
|
|
website.phaserObject.destroy();
|
|
|
|
this.embeddedWebsites.delete(name);
|
|
|
|
});
|
|
|
|
|
|
|
|
iframeListener.registerAnswerer(
|
|
|
|
"createEmbeddedWebsite",
|
|
|
|
(createEmbeddedWebsiteEvent: CreateEmbeddedWebsiteEvent) => {
|
|
|
|
if (this.embeddedWebsites.has(createEmbeddedWebsiteEvent.name)) {
|
|
|
|
throw new Error('An embedded website with the name "' + name + '" already exists in your map');
|
|
|
|
}
|
|
|
|
|
|
|
|
this.createEmbeddedWebsite(
|
|
|
|
createEmbeddedWebsiteEvent.name,
|
|
|
|
createEmbeddedWebsiteEvent.url,
|
|
|
|
createEmbeddedWebsiteEvent.position.x,
|
|
|
|
createEmbeddedWebsiteEvent.position.y,
|
|
|
|
createEmbeddedWebsiteEvent.position.width,
|
|
|
|
createEmbeddedWebsiteEvent.position.height,
|
|
|
|
createEmbeddedWebsiteEvent.visible ?? true,
|
|
|
|
createEmbeddedWebsiteEvent.allowApi ?? false,
|
|
|
|
createEmbeddedWebsiteEvent.allow ?? ""
|
|
|
|
);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
this.subscription = iframeListener.modifyEmbeddedWebsiteStream.subscribe(
|
|
|
|
(embeddedWebsiteEvent: ModifyEmbeddedWebsiteEvent) => {
|
|
|
|
const website = this.embeddedWebsites.get(embeddedWebsiteEvent.name);
|
|
|
|
if (!website) {
|
|
|
|
throw new Error(
|
|
|
|
'Could not find website with the name "' + embeddedWebsiteEvent.name + '" in your map'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
gameScene.markDirty();
|
|
|
|
|
|
|
|
if (embeddedWebsiteEvent.url !== undefined) {
|
|
|
|
website.url = embeddedWebsiteEvent.url;
|
|
|
|
const absoluteUrl = new URL(embeddedWebsiteEvent.url, this.gameScene.MapUrlFile).toString();
|
|
|
|
website.iframe.src = absoluteUrl;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (embeddedWebsiteEvent.visible !== undefined) {
|
|
|
|
website.visible = embeddedWebsiteEvent.visible;
|
|
|
|
website.phaserObject.visible = embeddedWebsiteEvent.visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (embeddedWebsiteEvent.allowApi !== undefined) {
|
|
|
|
website.allowApi = embeddedWebsiteEvent.allowApi;
|
|
|
|
if (embeddedWebsiteEvent.allowApi) {
|
|
|
|
iframeListener.registerIframe(website.iframe);
|
|
|
|
} else {
|
|
|
|
iframeListener.unregisterIframe(website.iframe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (embeddedWebsiteEvent.allow !== undefined) {
|
|
|
|
website.allow = embeddedWebsiteEvent.allow;
|
|
|
|
website.iframe.allow = embeddedWebsiteEvent.allow;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (embeddedWebsiteEvent?.x !== undefined) {
|
|
|
|
website.phaserObject.x = embeddedWebsiteEvent.x;
|
|
|
|
}
|
|
|
|
if (embeddedWebsiteEvent?.y !== undefined) {
|
|
|
|
website.phaserObject.y = embeddedWebsiteEvent.y;
|
|
|
|
}
|
|
|
|
if (embeddedWebsiteEvent?.width !== undefined) {
|
|
|
|
website.iframe.style.width = embeddedWebsiteEvent.width + "px";
|
|
|
|
}
|
|
|
|
if (embeddedWebsiteEvent?.height !== undefined) {
|
|
|
|
website.iframe.style.height = embeddedWebsiteEvent.height + "px";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
public createEmbeddedWebsite(
|
|
|
|
name: string,
|
|
|
|
url: string,
|
|
|
|
x: number,
|
|
|
|
y: number,
|
|
|
|
width: number,
|
|
|
|
height: number,
|
|
|
|
visible: boolean,
|
|
|
|
allowApi: boolean,
|
|
|
|
allow: string
|
|
|
|
): void {
|
|
|
|
if (this.embeddedWebsites.has(name)) {
|
|
|
|
throw new Error('An embedded website with the name "' + name + '" already exists in your map');
|
|
|
|
}
|
|
|
|
|
|
|
|
const embeddedWebsiteEvent: CreateEmbeddedWebsiteEvent = {
|
|
|
|
name,
|
|
|
|
url,
|
|
|
|
/*x,
|
|
|
|
y,
|
|
|
|
width,
|
|
|
|
height,*/
|
|
|
|
allow,
|
|
|
|
allowApi,
|
|
|
|
visible,
|
|
|
|
position: {
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const embeddedWebsite = this.doCreateEmbeddedWebsite(embeddedWebsiteEvent, visible);
|
|
|
|
|
|
|
|
this.embeddedWebsites.set(name, embeddedWebsite);
|
|
|
|
}
|
|
|
|
|
|
|
|
private doCreateEmbeddedWebsite(
|
|
|
|
embeddedWebsiteEvent: CreateEmbeddedWebsiteEvent,
|
|
|
|
visible: boolean
|
|
|
|
): EmbeddedWebsite {
|
|
|
|
const absoluteUrl = new URL(embeddedWebsiteEvent.url, this.gameScene.MapUrlFile).toString();
|
|
|
|
|
|
|
|
const iframe = document.createElement("iframe");
|
|
|
|
iframe.src = absoluteUrl;
|
2021-11-24 11:05:18 +01:00
|
|
|
iframe.tabIndex = -1;
|
2021-08-03 18:29:10 +02:00
|
|
|
iframe.style.width = embeddedWebsiteEvent.position.width + "px";
|
|
|
|
iframe.style.height = embeddedWebsiteEvent.position.height + "px";
|
|
|
|
iframe.style.margin = "0";
|
|
|
|
iframe.style.padding = "0";
|
|
|
|
iframe.style.border = "none";
|
|
|
|
|
|
|
|
const embeddedWebsite = {
|
|
|
|
...embeddedWebsiteEvent,
|
|
|
|
phaserObject: this.gameScene.add
|
|
|
|
.dom(embeddedWebsiteEvent.position.x, embeddedWebsiteEvent.position.y, iframe)
|
|
|
|
.setVisible(visible)
|
|
|
|
.setOrigin(0, 0),
|
|
|
|
iframe: iframe,
|
|
|
|
};
|
|
|
|
if (embeddedWebsiteEvent.allowApi) {
|
|
|
|
iframeListener.registerIframe(iframe);
|
|
|
|
}
|
|
|
|
|
|
|
|
return embeddedWebsite;
|
|
|
|
}
|
|
|
|
|
|
|
|
close(): void {
|
|
|
|
for (const [key, website] of this.embeddedWebsites) {
|
|
|
|
if (website.allowApi) {
|
|
|
|
iframeListener.unregisterIframe(website.iframe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
this.subscription.unsubscribe();
|
|
|
|
iframeListener.unregisterAnswerer("getEmbeddedWebsite");
|
|
|
|
iframeListener.unregisterAnswerer("deleteEmbeddedWebsite");
|
|
|
|
iframeListener.unregisterAnswerer("createEmbeddedWebsite");
|
|
|
|
}
|
|
|
|
}
|