Merge pull request #1516 from thecodingmachine/iframeManager
Display multi co-websites
This commit is contained in:
commit
60a82c5eb2
28 changed files with 2060 additions and 280 deletions
|
@ -1,5 +1,8 @@
|
||||||
## Version develop
|
## Version develop
|
||||||
|
|
||||||
|
### Updates
|
||||||
|
- Added multi Co-Website management
|
||||||
|
|
||||||
### Bugfix
|
### Bugfix
|
||||||
- Moving a discussion over a user will now add this user to the discussion
|
- Moving a discussion over a user will now add this user to the discussion
|
||||||
- Being in a silent zone new forces mediaConstraints to false (#1508)
|
- Being in a silent zone new forces mediaConstraints to false (#1508)
|
||||||
|
|
|
@ -49,19 +49,34 @@ WA.nav.goToRoom('../otherMap/map.json');
|
||||||
WA.nav.goToRoom("/_/global/<path to global map>.json#start-layer-2")
|
WA.nav.goToRoom("/_/global/<path to global map>.json#start-layer-2")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Opening/closing a web page in an iFrame
|
### Opening/closing web page in Co-Websites
|
||||||
|
|
||||||
```
|
```
|
||||||
WA.nav.openCoWebSite(url: string, allowApi: boolean = false, allowPolicy: string = ""): void
|
WA.nav.openCoWebSite(url: string, allowApi: boolean = false, allowPolicy: string = "", position: number = 0): Promise<CoWebsite>
|
||||||
WA.nav.closeCoWebSite(): void
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame. `allowApi` allows the webpage to use the "IFrame API" and execute script (it is equivalent to putting the `openWebsiteAllowApi` property in the map). `allowPolicy` grants additional access rights to the iFrame. The `allowPolicy` parameter is turned into an [`allow` feature policy in the iFrame](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-allow).
|
Opens the webpage at "url" in an iFrame (on the right side of the screen) or close that iFrame. `allowApi` allows the webpage to use the "IFrame API" and execute script (it is equivalent to putting the `openWebsiteAllowApi` property in the map). `allowPolicy` grants additional access rights to the iFrame. The `allowPolicy` parameter is turned into an [`allow` feature policy in the iFrame](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-allow), position in whitch slot the web page will be open.
|
||||||
|
You can have only 5 co-wbesites open simultaneously.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
WA.nav.openCoWebSite('https://www.wikipedia.org/');
|
const coWebsite = await WA.nav.openCoWebSite('https://www.wikipedia.org/');
|
||||||
|
const coWebsiteWorkAdventure = await WA.nav.openCoWebSite('https://workadventu.re/', true, "", 1);
|
||||||
// ...
|
// ...
|
||||||
WA.nav.closeCoWebSite();
|
coWebsite.close();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Get all Co-Websites
|
||||||
|
|
||||||
|
```
|
||||||
|
WA.nav.getCoWebSites(): Promise<CoWebsite[]>
|
||||||
|
```
|
||||||
|
|
||||||
|
Get all opened co-websites with their ids and positions.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const coWebsites = await WA.nav.getCowebSites();
|
||||||
```
|
```
|
||||||
|
|
|
@ -64,3 +64,13 @@ For instance, if you want an iFrame to be able to go in fullscreen, you will use
|
||||||
<img src="images/open_website_policy.jpg" class="figure-img img-fluid rounded" alt="" />
|
<img src="images/open_website_policy.jpg" class="figure-img img-fluid rounded" alt="" />
|
||||||
<figcaption class="figure-caption">The generated iFrame will have the allow attribute set to: <code><iframe allow="fullscreen"></code></figcaption>
|
<figcaption class="figure-caption">The generated iFrame will have the allow attribute set to: <code><iframe allow="fullscreen"></code></figcaption>
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
### Open a Jitsi with a co-website
|
||||||
|
|
||||||
|
Cowebsites allow you to have several sites open at the same time.
|
||||||
|
|
||||||
|
If you want to open a Jitsi and another page it's easy!
|
||||||
|
|
||||||
|
You have just to [add a Jitsi to the map](meeting-rooms.md) and [add a co-website](opening-a-website.md#the-openwebsite-property) on the same layer.
|
||||||
|
|
||||||
|
It's done!
|
||||||
|
|
75
front/dist/index.tmpl.html
vendored
75
front/dist/index.tmpl.html
vendored
|
@ -37,6 +37,54 @@
|
||||||
<div class="main-container" id="main-container">
|
<div class="main-container" id="main-container">
|
||||||
<!-- Create the editor container -->
|
<!-- Create the editor container -->
|
||||||
<div id="game" class="game">
|
<div id="game" class="game">
|
||||||
|
<div id="cowebsite-container">
|
||||||
|
<div id="cowebsite-container-main">
|
||||||
|
<div id="cowebsite-slot-1">
|
||||||
|
<div class="actions">
|
||||||
|
<button type="button" class="nes-btn is-primary expand">></button>
|
||||||
|
<button type="button" class="nes-btn is-error close">×</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="cowebsite-container-sub">
|
||||||
|
<div id="cowebsite-slot-2">
|
||||||
|
<div class="overlay">
|
||||||
|
<div class="actions">
|
||||||
|
<button type="button" title="Close" class="nes-btn is-error close">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="actions-move">
|
||||||
|
<button type="button" title="Expand" class="nes-btn is-primary expand">></button>
|
||||||
|
<button type="button" title="Hightlight" class="nes-btn is-secondary hightlight">Ξ</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="cowebsite-slot-3">
|
||||||
|
<div class="overlay">
|
||||||
|
<div class="actions">
|
||||||
|
<button type="button" title="Close" class="nes-btn is-error close">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="actions-move">
|
||||||
|
<button type="button" title="Expand" class="nes-btn is-primary expand">></button>
|
||||||
|
<button type="button" title="Hightlight" class="nes-btn is-secondary hightlight">Ξ</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="cowebsite-slot-4">
|
||||||
|
<div class="overlay">
|
||||||
|
<div class="actions">
|
||||||
|
<button type="button" title="Close" class="nes-btn is-error close">×</button>
|
||||||
|
</div>
|
||||||
|
<div class="actions-move">
|
||||||
|
<button type="button" title="Expand" class="nes-btn is-primary expand">></button>
|
||||||
|
<button type="button" title="Hightlight" class="nes-btn is-secondary hightlight">Ξ</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="svelte-overlay"></div>
|
<div id="svelte-overlay"></div>
|
||||||
<div id="game-overlay" class="game-overlay">
|
<div id="game-overlay" class="game-overlay">
|
||||||
<div id="main-section" class="main-section">
|
<div id="main-section" class="main-section">
|
||||||
|
@ -48,19 +96,24 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="cowebsite" class="cowebsite hidden">
|
<div id="cowebsite" class="cowebsite hidden">
|
||||||
<aside id="cowebsite-aside">
|
<aside id="cowebsite-aside" class="noselect">
|
||||||
<img src="/static/images/menu.svg" alt="hold to resize"/>
|
<div id="cowebsite-aside-buttons">
|
||||||
|
<button class="top-right-btn nes-btn is-error" id="cowebsite-close" alt="close all co-websites">
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
<button class="top-right-btn nes-btn is-primary" id="cowebsite-fullscreen" alt="fullscreen mode">
|
||||||
|
<img id="cowebsite-fullscreen-close" style="display: none;" src="resources/logos/fullscreen-exit.svg"/>
|
||||||
|
<img id="cowebsite-fullscreen-open" src="resources/logos/fullscreen.svg"/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="cowebsite-aside-holder">
|
||||||
|
<img src="/static/images/menu.svg" alt="hold to resize"/>
|
||||||
|
</div>
|
||||||
|
<div id="cowebsite-sub-icons"></div>
|
||||||
</aside>
|
</aside>
|
||||||
<main id="cowebsite-main">
|
<main id="cowebsite-slot-0"></main>
|
||||||
</main>
|
|
||||||
<button class="top-right-btn" id="cowebsite-fullscreen" alt="fullscreen mode">
|
|
||||||
<img id="cowebsite-fullscreen-open" src="resources/logos/fullscreen.svg"/>
|
|
||||||
<img id="cowebsite-fullscreen-close" style="display: none;" src="resources/logos/fullscreen-exit.svg"/>
|
|
||||||
</button>
|
|
||||||
<button class="top-right-btn" id="cowebsite-close" alt="close the iframe">
|
|
||||||
<img src="resources/logos/close.svg"/>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div id="cowebsite-buffer"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="activeScreenSharing" class="active-screen-sharing active">
|
<div id="activeScreenSharing" class="active-screen-sharing active">
|
||||||
|
|
12
front/src/Api/Events/CloseCoWebsiteEvent.ts
Normal file
12
front/src/Api/Events/CloseCoWebsiteEvent.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isCloseCoWebsite = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
id: tg.isOptional(tg.isString)
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message sent from the iFrame to the game to add a message in the chat.
|
||||||
|
*/
|
||||||
|
export type CloseCoWebsiteEvent = tg.GuardedType<typeof isCloseCoWebsite>;
|
|
@ -5,11 +5,10 @@ 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 type { OpenCoWebSiteEvent } 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";
|
||||||
import type { MapDataEvent } from "./MapDataEvent";
|
|
||||||
import type { LayerEvent } from "./LayerEvent";
|
import type { LayerEvent } from "./LayerEvent";
|
||||||
import type { SetPropertyEvent } from "./setPropertyEvent";
|
import type { SetPropertyEvent } from "./setPropertyEvent";
|
||||||
import type { LoadSoundEvent } from "./LoadSoundEvent";
|
import type { LoadSoundEvent } from "./LoadSoundEvent";
|
||||||
|
@ -27,9 +26,6 @@ import type { LoadTilesetEvent } from "./LoadTilesetEvent";
|
||||||
import { isLoadTilesetEvent } from "./LoadTilesetEvent";
|
import { isLoadTilesetEvent } from "./LoadTilesetEvent";
|
||||||
import type {
|
import type {
|
||||||
MessageReferenceEvent,
|
MessageReferenceEvent,
|
||||||
removeActionMessage,
|
|
||||||
triggerActionMessage,
|
|
||||||
TriggerActionMessageEvent,
|
|
||||||
} from "./ui/TriggerActionMessageEvent";
|
} from "./ui/TriggerActionMessageEvent";
|
||||||
import { isMessageReferenceEvent, isTriggerActionMessageEvent } from "./ui/TriggerActionMessageEvent";
|
import { isMessageReferenceEvent, isTriggerActionMessageEvent } from "./ui/TriggerActionMessageEvent";
|
||||||
import type { MenuRegisterEvent, UnregisterMenuEvent } from "./ui/MenuRegisterEvent";
|
import type { MenuRegisterEvent, UnregisterMenuEvent } from "./ui/MenuRegisterEvent";
|
||||||
|
@ -48,8 +44,6 @@ export type IframeEventMap = {
|
||||||
closePopup: ClosePopupEvent;
|
closePopup: ClosePopupEvent;
|
||||||
openTab: OpenTabEvent;
|
openTab: OpenTabEvent;
|
||||||
goToPage: GoToPageEvent;
|
goToPage: GoToPageEvent;
|
||||||
openCoWebSite: OpenCoWebSiteEvent;
|
|
||||||
closeCoWebSite: null;
|
|
||||||
disablePlayerControls: null;
|
disablePlayerControls: null;
|
||||||
restorePlayerControls: null;
|
restorePlayerControls: null;
|
||||||
displayBubble: null;
|
displayBubble: null;
|
||||||
|
@ -118,6 +112,22 @@ export const iframeQueryMapTypeGuards = {
|
||||||
query: isLoadTilesetEvent,
|
query: isLoadTilesetEvent,
|
||||||
answer: tg.isNumber,
|
answer: tg.isNumber,
|
||||||
},
|
},
|
||||||
|
openCoWebsite: {
|
||||||
|
query: isOpenCoWebsiteEvent,
|
||||||
|
answer: isCoWebsite
|
||||||
|
},
|
||||||
|
getCoWebsites: {
|
||||||
|
query: tg.isUndefined,
|
||||||
|
answer: tg.isArray(isCoWebsite)
|
||||||
|
},
|
||||||
|
closeCoWebsite: {
|
||||||
|
query: tg.isString,
|
||||||
|
answer: tg.isUndefined
|
||||||
|
},
|
||||||
|
closeCoWebsites: {
|
||||||
|
query: tg.isUndefined,
|
||||||
|
answer: tg.isUndefined
|
||||||
|
},
|
||||||
triggerActionMessage: {
|
triggerActionMessage: {
|
||||||
query: isTriggerActionMessageEvent,
|
query: isTriggerActionMessageEvent,
|
||||||
answer: tg.isUndefined,
|
answer: tg.isUndefined,
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import * as tg from "generic-type-guard";
|
|
||||||
|
|
||||||
export const isOpenCoWebsite = new tg.IsInterface()
|
|
||||||
.withProperties({
|
|
||||||
url: tg.isString,
|
|
||||||
allowApi: tg.isBoolean,
|
|
||||||
allowPolicy: tg.isString,
|
|
||||||
})
|
|
||||||
.get();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A message sent from the iFrame to the game to add a message in the chat.
|
|
||||||
*/
|
|
||||||
export type OpenCoWebSiteEvent = tg.GuardedType<typeof isOpenCoWebsite>;
|
|
22
front/src/Api/Events/OpenCoWebsiteEvent.ts
Normal file
22
front/src/Api/Events/OpenCoWebsiteEvent.ts
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const isOpenCoWebsiteEvent = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
url: tg.isString,
|
||||||
|
allowApi: tg.isOptional(tg.isBoolean),
|
||||||
|
allowPolicy: tg.isOptional(tg.isString),
|
||||||
|
position: tg.isOptional(tg.isNumber)
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
export const isCoWebsite = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
id: tg.isString,
|
||||||
|
position: tg.isNumber,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A message sent from the iFrame to the game to add a message in the chat.
|
||||||
|
*/
|
||||||
|
export type OpenCoWebsiteEvent = tg.GuardedType<typeof isOpenCoWebsiteEvent>;
|
|
@ -1,6 +1,5 @@
|
||||||
import { Subject } from "rxjs";
|
import { Subject } from "rxjs";
|
||||||
import type * as tg from "generic-type-guard";
|
import { isChatEvent } from "./Events/ChatEvent";
|
||||||
import { ChatEvent, isChatEvent } from "./Events/ChatEvent";
|
|
||||||
import { HtmlUtils } from "../WebRtc/HtmlUtils";
|
import { HtmlUtils } from "../WebRtc/HtmlUtils";
|
||||||
import type { EnterLeaveEvent } from "./Events/EnterLeaveEvent";
|
import type { EnterLeaveEvent } from "./Events/EnterLeaveEvent";
|
||||||
import { isOpenPopupEvent, OpenPopupEvent } from "./Events/OpenPopupEvent";
|
import { isOpenPopupEvent, OpenPopupEvent } from "./Events/OpenPopupEvent";
|
||||||
|
@ -8,18 +7,15 @@ import { isOpenTabEvent, OpenTabEvent } from "./Events/OpenTabEvent";
|
||||||
import type { ButtonClickedEvent } from "./Events/ButtonClickedEvent";
|
import type { ButtonClickedEvent } from "./Events/ButtonClickedEvent";
|
||||||
import { ClosePopupEvent, isClosePopupEvent } from "./Events/ClosePopupEvent";
|
import { ClosePopupEvent, isClosePopupEvent } from "./Events/ClosePopupEvent";
|
||||||
import { scriptUtils } from "./ScriptUtils";
|
import { scriptUtils } from "./ScriptUtils";
|
||||||
import { GoToPageEvent, isGoToPageEvent } from "./Events/GoToPageEvent";
|
import { isGoToPageEvent } from "./Events/GoToPageEvent";
|
||||||
import { isOpenCoWebsite, OpenCoWebSiteEvent } from "./Events/OpenCoWebSiteEvent";
|
import { isCloseCoWebsite, CloseCoWebsiteEvent } from "./Events/CloseCoWebsiteEvent";
|
||||||
import {
|
import {
|
||||||
IframeErrorAnswerEvent,
|
IframeErrorAnswerEvent,
|
||||||
IframeEvent,
|
|
||||||
IframeEventMap,
|
|
||||||
IframeQueryMap,
|
IframeQueryMap,
|
||||||
IframeResponseEvent,
|
IframeResponseEvent,
|
||||||
IframeResponseEventMap,
|
IframeResponseEventMap,
|
||||||
isIframeEventWrapper,
|
isIframeEventWrapper,
|
||||||
isIframeQueryWrapper,
|
isIframeQueryWrapper,
|
||||||
TypedMessageEvent,
|
|
||||||
} from "./Events/IframeEvent";
|
} from "./Events/IframeEvent";
|
||||||
import type { UserInputChatEvent } from "./Events/UserInputChatEvent";
|
import type { UserInputChatEvent } from "./Events/UserInputChatEvent";
|
||||||
import { isPlaySoundEvent, PlaySoundEvent } from "./Events/PlaySoundEvent";
|
import { isPlaySoundEvent, PlaySoundEvent } from "./Events/PlaySoundEvent";
|
||||||
|
@ -33,7 +29,6 @@ import { isMenuRegisterEvent, isUnregisterMenuEvent } from "./Events/ui/MenuRegi
|
||||||
import { SetTilesEvent, isSetTilesEvent } from "./Events/SetTilesEvent";
|
import { SetTilesEvent, isSetTilesEvent } from "./Events/SetTilesEvent";
|
||||||
import type { SetVariableEvent } from "./Events/SetVariableEvent";
|
import type { SetVariableEvent } from "./Events/SetVariableEvent";
|
||||||
import { ModifyEmbeddedWebsiteEvent, isEmbeddedWebsiteEvent } from "./Events/EmbeddedWebsiteEvent";
|
import { ModifyEmbeddedWebsiteEvent, isEmbeddedWebsiteEvent } from "./Events/EmbeddedWebsiteEvent";
|
||||||
import { EmbeddedWebsite } from "./iframe/Room/EmbeddedWebsite";
|
|
||||||
import { handleMenuRegistrationEvent, handleMenuUnregisterEvent } from "../Stores/MenuStore";
|
import { handleMenuRegistrationEvent, handleMenuUnregisterEvent } from "../Stores/MenuStore";
|
||||||
|
|
||||||
type AnswererCallback<T extends keyof IframeQueryMap> = (
|
type AnswererCallback<T extends keyof IframeQueryMap> = (
|
||||||
|
@ -53,10 +48,7 @@ class IframeListener {
|
||||||
public readonly openTabStream = this._openTabStream.asObservable();
|
public readonly openTabStream = this._openTabStream.asObservable();
|
||||||
|
|
||||||
private readonly _loadPageStream: Subject<string> = new Subject();
|
private readonly _loadPageStream: Subject<string> = new Subject();
|
||||||
public readonly loadPageStream = this._loadPageStream.asObservable();
|
public readonly loadPageStream = this._loadPageStream.asObservable()
|
||||||
|
|
||||||
private readonly _openCoWebSiteStream: Subject<OpenCoWebSiteEvent> = new Subject();
|
|
||||||
public readonly openCoWebSiteStream = this._openCoWebSiteStream.asObservable();
|
|
||||||
|
|
||||||
private readonly _disablePlayerControlStream: Subject<void> = new Subject();
|
private readonly _disablePlayerControlStream: Subject<void> = new Subject();
|
||||||
public readonly disablePlayerControlStream = this._disablePlayerControlStream.asObservable();
|
public readonly disablePlayerControlStream = this._disablePlayerControlStream.asObservable();
|
||||||
|
@ -138,8 +130,6 @@ class IframeListener {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foundSrc = this.getBaseUrl(foundSrc, message.source);
|
|
||||||
|
|
||||||
if (isIframeQueryWrapper(payload)) {
|
if (isIframeQueryWrapper(payload)) {
|
||||||
const queryId = payload.id;
|
const queryId = payload.id;
|
||||||
const query = payload.query;
|
const query = payload.query;
|
||||||
|
@ -224,15 +214,6 @@ class IframeListener {
|
||||||
this._stopSoundStream.next(payload.data);
|
this._stopSoundStream.next(payload.data);
|
||||||
} else if (payload.type === "loadSound" && isLoadSoundEvent(payload.data)) {
|
} else if (payload.type === "loadSound" && isLoadSoundEvent(payload.data)) {
|
||||||
this._loadSoundStream.next(payload.data);
|
this._loadSoundStream.next(payload.data);
|
||||||
} else if (payload.type === "openCoWebSite" && isOpenCoWebsite(payload.data)) {
|
|
||||||
scriptUtils.openCoWebsite(
|
|
||||||
payload.data.url,
|
|
||||||
foundSrc,
|
|
||||||
payload.data.allowApi,
|
|
||||||
payload.data.allowPolicy
|
|
||||||
);
|
|
||||||
} else if (payload.type === "closeCoWebSite") {
|
|
||||||
scriptUtils.closeCoWebSite();
|
|
||||||
} else if (payload.type === "disablePlayerControls") {
|
} else if (payload.type === "disablePlayerControls") {
|
||||||
this._disablePlayerControlStream.next();
|
this._disablePlayerControlStream.next();
|
||||||
} else if (payload.type === "restorePlayerControls") {
|
} else if (payload.type === "restorePlayerControls") {
|
||||||
|
@ -252,6 +233,9 @@ class IframeListener {
|
||||||
this.iframeCloseCallbacks.get(iframe)?.push(() => {
|
this.iframeCloseCallbacks.get(iframe)?.push(() => {
|
||||||
handleMenuUnregisterEvent(dataName);
|
handleMenuUnregisterEvent(dataName);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
foundSrc = this.getBaseUrl(foundSrc, message.source);
|
||||||
|
|
||||||
handleMenuRegistrationEvent(
|
handleMenuRegistrationEvent(
|
||||||
payload.data.name,
|
payload.data.name,
|
||||||
payload.data.iframe,
|
payload.data.iframe,
|
||||||
|
@ -354,6 +338,20 @@ class IframeListener {
|
||||||
return src;
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getBaseUrlFromSource(source: MessageEventSource): string {
|
||||||
|
let foundSrc: string | undefined;
|
||||||
|
let iframe: HTMLIFrameElement | undefined;
|
||||||
|
|
||||||
|
for (iframe of this.iframes) {
|
||||||
|
if (iframe.contentWindow === source) {
|
||||||
|
foundSrc = iframe.src;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getBaseUrl(foundSrc ?? "", source);
|
||||||
|
}
|
||||||
|
|
||||||
private static getIFrameId(scriptUrl: string): string {
|
private static getIFrameId(scriptUrl: string): string {
|
||||||
return "script" + btoa(scriptUrl);
|
return "script" + btoa(scriptUrl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { coWebsiteManager } from "../WebRtc/CoWebsiteManager";
|
import { coWebsiteManager, CoWebsite } from "../WebRtc/CoWebsiteManager";
|
||||||
import { playersStore } from "../Stores/PlayersStore";
|
import { playersStore } from "../Stores/PlayersStore";
|
||||||
import { chatMessagesStore } from "../Stores/ChatStore";
|
import { chatMessagesStore } from "../Stores/ChatStore";
|
||||||
import type { ChatEvent } from "./Events/ChatEvent";
|
import type { ChatEvent } from "./Events/ChatEvent";
|
||||||
|
@ -12,14 +12,6 @@ class ScriptUtils {
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public openCoWebsite(url: string, base: string, api: boolean, policy: string) {
|
|
||||||
coWebsiteManager.loadCoWebsite(url, base, api, policy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public closeCoWebSite() {
|
|
||||||
coWebsiteManager.closeCoWebsite();
|
|
||||||
}
|
|
||||||
|
|
||||||
public sendAnonymousChat(chatEvent: ChatEvent) {
|
public sendAnonymousChat(chatEvent: ChatEvent) {
|
||||||
const userId = playersStore.addFacticePlayer(chatEvent.author);
|
const userId = playersStore.addFacticePlayer(chatEvent.author);
|
||||||
chatMessagesStore.addExternalMessage(userId, chatEvent.message);
|
chatMessagesStore.addExternalMessage(userId, chatEvent.message);
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
import type { GoToPageEvent } from "../Events/GoToPageEvent";
|
import { IframeApiContribution, sendToWorkadventure, queryWorkadventure } from "./IframeApiContribution";
|
||||||
import type { OpenTabEvent } from "../Events/OpenTabEvent";
|
|
||||||
import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution";
|
export class CoWebsite {
|
||||||
import type { OpenCoWebSiteEvent } from "../Events/OpenCoWebSiteEvent";
|
constructor(private readonly id: string, public readonly position: number) {}
|
||||||
import type { LoadPageEvent } from "../Events/LoadPageEvent";
|
|
||||||
|
close() {
|
||||||
|
return queryWorkadventure({
|
||||||
|
type: "closeCoWebsite",
|
||||||
|
data: this.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class WorkadventureNavigationCommands extends IframeApiContribution<WorkadventureNavigationCommands> {
|
export class WorkadventureNavigationCommands extends IframeApiContribution<WorkadventureNavigationCommands> {
|
||||||
callbacks = [];
|
callbacks = [];
|
||||||
|
@ -34,21 +41,34 @@ export class WorkadventureNavigationCommands extends IframeApiContribution<Worka
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
openCoWebSite(url: string, allowApi: boolean = false, allowPolicy: string = ""): void {
|
async openCoWebSite(url: string, allowApi?: boolean, allowPolicy?: string, position?: number): Promise<CoWebsite> {
|
||||||
sendToWorkadventure({
|
const result = await queryWorkadventure({
|
||||||
type: "openCoWebSite",
|
type: "openCoWebsite",
|
||||||
data: {
|
data: {
|
||||||
url,
|
url,
|
||||||
allowApi,
|
allowApi,
|
||||||
allowPolicy,
|
allowPolicy,
|
||||||
|
position,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
return new CoWebsite(result.id, result.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
closeCoWebSite(): void {
|
async getCoWebSites(): Promise<CoWebsite[]> {
|
||||||
sendToWorkadventure({
|
const result = await queryWorkadventure({
|
||||||
type: "closeCoWebSite",
|
type: "getCoWebsites",
|
||||||
data: null,
|
data: undefined
|
||||||
|
});
|
||||||
|
return result.map((cowebsiteEvent) => new CoWebsite(cowebsiteEvent.id, cowebsiteEvent.position));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use closeCoWebsites instead to close all co-websites
|
||||||
|
*/
|
||||||
|
closeCoWebSite() {
|
||||||
|
return queryWorkadventure({
|
||||||
|
type: "closeCoWebsites",
|
||||||
|
data: undefined,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@
|
||||||
top: 10%;
|
top: 10%;
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
|
z-index: 80;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.menuIcon {
|
.menuIcon {
|
||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
|
z-index: 90;
|
||||||
|
position: relative;
|
||||||
margin: 25px;
|
margin: 25px;
|
||||||
img {
|
img {
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
|
|
|
@ -37,37 +37,44 @@ export class GameMapPropertiesListener {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => {
|
this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => {
|
||||||
if (newValue === undefined) {
|
const handler = async () => {
|
||||||
layoutManagerActionStore.removeAction("openWebsite");
|
if (newValue === undefined || newValue !== oldValue) {
|
||||||
coWebsiteManager.closeCoWebsite();
|
|
||||||
} else {
|
|
||||||
const openWebsiteFunction = () => {
|
|
||||||
coWebsiteManager.loadCoWebsite(
|
|
||||||
newValue as string,
|
|
||||||
this.scene.MapUrlFile,
|
|
||||||
allProps.get("openWebsiteAllowApi") as boolean | undefined,
|
|
||||||
allProps.get("openWebsitePolicy") as string | undefined,
|
|
||||||
allProps.get("openWebsiteWidth") as number | undefined
|
|
||||||
);
|
|
||||||
layoutManagerActionStore.removeAction("openWebsite");
|
layoutManagerActionStore.removeAction("openWebsite");
|
||||||
};
|
await coWebsiteManager.closeCoWebsites();
|
||||||
const openWebsiteTriggerValue = allProps.get(TRIGGER_WEBSITE_PROPERTIES);
|
|
||||||
if (openWebsiteTriggerValue && openWebsiteTriggerValue === ON_ACTION_TRIGGER_BUTTON) {
|
|
||||||
let message = allProps.get(WEBSITE_MESSAGE_PROPERTIES);
|
|
||||||
if (message === undefined) {
|
|
||||||
message = "Press SPACE or touch here to open web site";
|
|
||||||
}
|
|
||||||
layoutManagerActionStore.addAction({
|
|
||||||
uuid: "openWebsite",
|
|
||||||
type: "message",
|
|
||||||
message: message,
|
|
||||||
callback: () => openWebsiteFunction(),
|
|
||||||
userInputManager: this.scene.userInputManager,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
openWebsiteFunction();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if (newValue !== undefined) {
|
||||||
|
const openWebsiteFunction = () => {
|
||||||
|
coWebsiteManager.loadCoWebsite(
|
||||||
|
newValue as string,
|
||||||
|
this.scene.MapUrlFile,
|
||||||
|
allProps.get("openWebsiteAllowApi") as boolean | undefined,
|
||||||
|
allProps.get("openWebsitePolicy") as string | undefined,
|
||||||
|
allProps.get("openWebsiteWidth") as number | undefined
|
||||||
|
);
|
||||||
|
|
||||||
|
layoutManagerActionStore.removeAction("openWebsite");
|
||||||
|
};
|
||||||
|
const openWebsiteTriggerValue = allProps.get(TRIGGER_WEBSITE_PROPERTIES);
|
||||||
|
if (openWebsiteTriggerValue && openWebsiteTriggerValue === ON_ACTION_TRIGGER_BUTTON) {
|
||||||
|
let message = allProps.get(WEBSITE_MESSAGE_PROPERTIES);
|
||||||
|
if (message === undefined) {
|
||||||
|
message = "Press SPACE or touch here to open web site";
|
||||||
|
}
|
||||||
|
layoutManagerActionStore.addAction({
|
||||||
|
uuid: "openWebsite",
|
||||||
|
type: "message",
|
||||||
|
message: message,
|
||||||
|
callback: () => openWebsiteFunction(),
|
||||||
|
userInputManager: this.scene.userInputManager,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
openWebsiteFunction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handler();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {
|
||||||
TRIGGER_WEBSITE_PROPERTIES,
|
TRIGGER_WEBSITE_PROPERTIES,
|
||||||
WEBSITE_MESSAGE_PROPERTIES,
|
WEBSITE_MESSAGE_PROPERTIES,
|
||||||
} from "../../WebRtc/LayoutManager";
|
} from "../../WebRtc/LayoutManager";
|
||||||
import { coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
|
import { CoWebsite, coWebsiteManager } from "../../WebRtc/CoWebsiteManager";
|
||||||
import type { UserMovedMessage } from "../../Messages/generated/messages_pb";
|
import type { UserMovedMessage } from "../../Messages/generated/messages_pb";
|
||||||
import { ProtobufClientUtils } from "../../Network/ProtobufClientUtils";
|
import { ProtobufClientUtils } from "../../Network/ProtobufClientUtils";
|
||||||
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
import type { RoomConnection } from "../../Connexion/RoomConnection";
|
||||||
|
@ -95,7 +95,6 @@ import { EmbeddedWebsiteManager } from "./EmbeddedWebsiteManager";
|
||||||
import { GameMapPropertiesListener } from "./GameMapPropertiesListener";
|
import { GameMapPropertiesListener } from "./GameMapPropertiesListener";
|
||||||
import { analyticsClient } from "../../Administration/AnalyticsClient";
|
import { analyticsClient } from "../../Administration/AnalyticsClient";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
import type { RadialMenuItem } from "../Components/RadialMenu";
|
|
||||||
import { contactPageStore } from "../../Stores/MenuStore";
|
import { contactPageStore } from "../../Stores/MenuStore";
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
|
@ -1081,6 +1080,58 @@ ${escapedMessage}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
iframeListener.registerAnswerer("openCoWebsite", async (openCoWebsite, source) => {
|
||||||
|
if (!source) {
|
||||||
|
throw new Error("Unknown query source");
|
||||||
|
}
|
||||||
|
|
||||||
|
const coWebsite = await coWebsiteManager.loadCoWebsite(
|
||||||
|
openCoWebsite.url,
|
||||||
|
iframeListener.getBaseUrlFromSource(source),
|
||||||
|
openCoWebsite.allowApi,
|
||||||
|
openCoWebsite.allowPolicy,
|
||||||
|
openCoWebsite.position
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!coWebsite) {
|
||||||
|
throw new Error("Error on opening co-website");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: coWebsite.iframe.id,
|
||||||
|
position: coWebsite.position,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
iframeListener.registerAnswerer("getCoWebsites", () => {
|
||||||
|
const coWebsites = coWebsiteManager.getCoWebsites();
|
||||||
|
|
||||||
|
return coWebsites.map((coWebsite: CoWebsite) => {
|
||||||
|
return {
|
||||||
|
id: coWebsite.iframe.id,
|
||||||
|
position: coWebsite.position,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
iframeListener.registerAnswerer("closeCoWebsite", async (coWebsiteId) => {
|
||||||
|
const coWebsite = coWebsiteManager.getCoWebsiteById(coWebsiteId);
|
||||||
|
|
||||||
|
if (!coWebsite) {
|
||||||
|
throw new Error("Unknown co-website");
|
||||||
|
}
|
||||||
|
|
||||||
|
return coWebsiteManager.closeCoWebsite(coWebsite).catch((error) => {
|
||||||
|
throw new Error("Error on closing co-website");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
iframeListener.registerAnswerer("closeCoWebsites", async () => {
|
||||||
|
return await coWebsiteManager.closeCoWebsites().catch((error) => {
|
||||||
|
throw new Error("Error on closing all co-websites");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
iframeListener.registerAnswerer("getMapData", () => {
|
iframeListener.registerAnswerer("getMapData", () => {
|
||||||
return {
|
return {
|
||||||
data: this.gameMap.getMap(),
|
data: this.gameMap.getMap(),
|
||||||
|
@ -1284,7 +1335,7 @@ ${escapedMessage}
|
||||||
|
|
||||||
public cleanupClosingScene(): void {
|
public cleanupClosingScene(): void {
|
||||||
// stop playing audio, close any open website, stop any open Jitsi
|
// stop playing audio, close any open website, stop any open Jitsi
|
||||||
coWebsiteManager.closeCoWebsite();
|
coWebsiteManager.closeCoWebsites();
|
||||||
// Stop the script, if any
|
// Stop the script, if any
|
||||||
const scripts = this.getScriptUrls(this.mapFile);
|
const scripts = this.getScriptUrls(this.mapFile);
|
||||||
for (const script of scripts) {
|
for (const script of scripts) {
|
||||||
|
@ -1310,6 +1361,8 @@ ${escapedMessage}
|
||||||
iframeListener.unregisterAnswerer("getMapData");
|
iframeListener.unregisterAnswerer("getMapData");
|
||||||
iframeListener.unregisterAnswerer("triggerActionMessage");
|
iframeListener.unregisterAnswerer("triggerActionMessage");
|
||||||
iframeListener.unregisterAnswerer("removeActionMessage");
|
iframeListener.unregisterAnswerer("removeActionMessage");
|
||||||
|
iframeListener.unregisterAnswerer("openCoWebsite");
|
||||||
|
iframeListener.unregisterAnswerer("getCoWebsites");
|
||||||
this.sharedVariablesManager?.close();
|
this.sharedVariablesManager?.close();
|
||||||
this.embeddedWebsiteManager?.close();
|
this.embeddedWebsiteManager?.close();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store";
|
||||||
import { playersStore } from "./PlayersStore";
|
import { playersStore } from "./PlayersStore";
|
||||||
import type { PlayerInterface } from "../Phaser/Game/PlayerInterface";
|
import type { PlayerInterface } from "../Phaser/Game/PlayerInterface";
|
||||||
|
import { iframeListener } from "../Api/IframeListener";
|
||||||
|
|
||||||
export const chatVisibilityStore = writable(false);
|
export const chatVisibilityStore = writable(false);
|
||||||
export const chatInputFocusStore = writable(false);
|
export const chatInputFocusStore = writable(false);
|
||||||
|
@ -78,6 +79,8 @@ function createChatMessagesStore() {
|
||||||
date: new Date(),
|
date: new Date(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iframeListener.sendUserInputChat(text);
|
||||||
return list;
|
return list;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -99,6 +102,8 @@ function createChatMessagesStore() {
|
||||||
date: new Date(),
|
date: new Date(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iframeListener.sendUserInputChat(text);
|
||||||
return list;
|
return list;
|
||||||
});
|
});
|
||||||
chatVisibilityStore.set(true);
|
chatVisibilityStore.set(true);
|
||||||
|
|
|
@ -10,9 +10,12 @@ enum iframeStates {
|
||||||
opened,
|
opened,
|
||||||
}
|
}
|
||||||
|
|
||||||
const cowebsiteDivId = "cowebsite"; // the id of the whole container.
|
const cowebsiteDomId = "cowebsite"; // the id of the whole container.
|
||||||
const cowebsiteMainDomId = "cowebsite-main"; // the id of the parent div of the iframe.
|
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.
|
||||||
const cowebsiteAsideDomId = "cowebsite-aside"; // the id of the parent div of the iframe.
|
const cowebsiteAsideDomId = "cowebsite-aside"; // the id of the parent div of the iframe.
|
||||||
|
const cowebsiteSubIconsDomId = "cowebsite-sub-icons";
|
||||||
export const cowebsiteCloseButtonId = "cowebsite-close";
|
export const cowebsiteCloseButtonId = "cowebsite-close";
|
||||||
const cowebsiteFullScreenButtonId = "cowebsite-fullscreen";
|
const cowebsiteFullScreenButtonId = "cowebsite-fullscreen";
|
||||||
const cowebsiteOpenFullScreenImageId = "cowebsite-fullscreen-open";
|
const cowebsiteOpenFullScreenImageId = "cowebsite-fullscreen-open";
|
||||||
|
@ -24,8 +27,19 @@ interface TouchMoveCoordinates {
|
||||||
y: number;
|
y: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type CoWebsite = {
|
||||||
|
iframe: HTMLIFrameElement,
|
||||||
|
icon: HTMLDivElement,
|
||||||
|
position: number
|
||||||
|
}
|
||||||
|
|
||||||
|
type CoWebsiteSlot = {
|
||||||
|
container: HTMLElement,
|
||||||
|
position: number
|
||||||
|
}
|
||||||
|
|
||||||
class CoWebsiteManager {
|
class CoWebsiteManager {
|
||||||
private opened: iframeStates = iframeStates.closed;
|
private openedMain: iframeStates = iframeStates.closed;
|
||||||
|
|
||||||
private _onResize: Subject<void> = new Subject();
|
private _onResize: Subject<void> = new Subject();
|
||||||
public onResize = this._onResize.asObservable();
|
public onResize = this._onResize.asObservable();
|
||||||
|
@ -34,30 +48,41 @@ class CoWebsiteManager {
|
||||||
* So we use this promise to queue up every cowebsite state transition
|
* So we use this promise to queue up every cowebsite state transition
|
||||||
*/
|
*/
|
||||||
private currentOperationPromise: Promise<void> = Promise.resolve();
|
private currentOperationPromise: Promise<void> = Promise.resolve();
|
||||||
private cowebsiteDiv: HTMLDivElement;
|
private cowebsiteDom: HTMLDivElement;
|
||||||
|
private cowebsiteContainerDom: HTMLDivElement;
|
||||||
private resizing: boolean = false;
|
private resizing: boolean = false;
|
||||||
private cowebsiteMainDom: HTMLDivElement;
|
private cowebsiteMainDom: HTMLDivElement;
|
||||||
|
private cowebsiteBufferDom: HTMLDivElement;
|
||||||
private cowebsiteAsideDom: HTMLDivElement;
|
private cowebsiteAsideDom: HTMLDivElement;
|
||||||
|
private cowebsiteSubIconsDom: HTMLDivElement;
|
||||||
private previousTouchMoveCoordinates: TouchMoveCoordinates | null = null; //only use on touchscreens to track touch movement
|
private previousTouchMoveCoordinates: TouchMoveCoordinates | null = null; //only use on touchscreens to track touch movement
|
||||||
|
|
||||||
|
private coWebsites: CoWebsite[] = [];
|
||||||
|
|
||||||
|
private slots: CoWebsiteSlot[];
|
||||||
|
|
||||||
|
private resizeObserver = new ResizeObserver(entries => {
|
||||||
|
this.resizeAllIframes();
|
||||||
|
});
|
||||||
|
|
||||||
get width(): number {
|
get width(): number {
|
||||||
return this.cowebsiteDiv.clientWidth;
|
return this.cowebsiteDom.clientWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
set width(width: number) {
|
set width(width: number) {
|
||||||
this.cowebsiteDiv.style.width = width + "px";
|
this.cowebsiteDom.style.width = width + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
set widthPercent(width: number) {
|
set widthPercent(width: number) {
|
||||||
this.cowebsiteDiv.style.width = width + "%";
|
this.cowebsiteDom.style.width = width + "%";
|
||||||
}
|
}
|
||||||
|
|
||||||
get height(): number {
|
get height(): number {
|
||||||
return this.cowebsiteDiv.clientHeight;
|
return this.cowebsiteDom.clientHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
set height(height: number) {
|
set height(height: number) {
|
||||||
this.cowebsiteDiv.style.height = height + "px";
|
this.cowebsiteDom.style.height = height + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
get verticalMode(): boolean {
|
get verticalMode(): boolean {
|
||||||
|
@ -69,19 +94,59 @@ class CoWebsiteManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.cowebsiteDiv = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteDivId);
|
this.cowebsiteDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteDomId);
|
||||||
|
this.cowebsiteContainerDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteContainerDomId);
|
||||||
this.cowebsiteMainDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteMainDomId);
|
this.cowebsiteMainDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteMainDomId);
|
||||||
|
this.cowebsiteBufferDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteBufferDomId);
|
||||||
this.cowebsiteAsideDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteAsideDomId);
|
this.cowebsiteAsideDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteAsideDomId);
|
||||||
|
this.cowebsiteSubIconsDom = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteSubIconsDomId);
|
||||||
|
this.initResizeListeners(touchScreenManager.supportTouchScreen);
|
||||||
|
|
||||||
if (touchScreenManager.supportTouchScreen) {
|
this.resizeObserver.observe(this.cowebsiteDom);
|
||||||
this.initResizeListeners(true);
|
this.resizeObserver.observe(this.cowebsiteContainerDom);
|
||||||
}
|
|
||||||
this.initResizeListeners(false);
|
|
||||||
|
|
||||||
const buttonCloseFrame = HtmlUtils.getElementByIdOrFail(cowebsiteCloseButtonId);
|
this.slots = [
|
||||||
buttonCloseFrame.addEventListener("click", () => {
|
{
|
||||||
buttonCloseFrame.blur();
|
container: this.cowebsiteMainDom,
|
||||||
this.closeCoWebsite();
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.initActionsListeners();
|
||||||
|
|
||||||
|
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();
|
||||||
});
|
});
|
||||||
|
|
||||||
const buttonFullScreenFrame = HtmlUtils.getElementByIdOrFail(cowebsiteFullScreenButtonId);
|
const buttonFullScreenFrame = HtmlUtils.getElementByIdOrFail(cowebsiteFullScreenButtonId);
|
||||||
|
@ -91,6 +156,17 @@ class CoWebsiteManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
return window.matchMedia("(max-aspect-ratio: 1/1)").matches ||
|
||||||
|
window.matchMedia("(max-width:960px) and (max-height:768px)").matches;
|
||||||
|
}
|
||||||
|
|
||||||
private initResizeListeners(touchMode: boolean) {
|
private initResizeListeners(touchMode: boolean) {
|
||||||
const movecallback = (event: MouseEvent | TouchEvent) => {
|
const movecallback = (event: MouseEvent | TouchEvent) => {
|
||||||
let x, y;
|
let x, y;
|
||||||
|
@ -111,8 +187,8 @@ class CoWebsiteManager {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.cowebsiteAsideDom.addEventListener(touchMode ? "touchstart" : "mousedown", (event) => {
|
this.cowebsiteAsideDom.addEventListener(touchMode ? "touchstart" : "mousedown", (event) => {
|
||||||
|
this.cowebsiteMainDom.style.display = "none";
|
||||||
this.resizing = true;
|
this.resizing = true;
|
||||||
this.getIframeDom().style.display = "none";
|
|
||||||
if (touchMode) {
|
if (touchMode) {
|
||||||
const touchEvent = (event as TouchEvent).touches[0];
|
const touchEvent = (event as TouchEvent).touches[0];
|
||||||
this.previousTouchMoveCoordinates = { x: touchEvent.pageX, y: touchEvent.pageY };
|
this.previousTouchMoveCoordinates = { x: touchEvent.pageX, y: touchEvent.pageY };
|
||||||
|
@ -127,43 +203,249 @@ class CoWebsiteManager {
|
||||||
this.previousTouchMoveCoordinates = null;
|
this.previousTouchMoveCoordinates = null;
|
||||||
}
|
}
|
||||||
document.removeEventListener(touchMode ? "touchmove" : "mousemove", movecallback);
|
document.removeEventListener(touchMode ? "touchmove" : "mousemove", movecallback);
|
||||||
this.getIframeDom().style.display = "block";
|
this.cowebsiteMainDom.style.display = "block";
|
||||||
this.resizing = false;
|
this.resizing = false;
|
||||||
|
this.cowebsiteMainDom.style.display = "flex";
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDevicePixelRatio(): number {
|
private closeMain(): void {
|
||||||
//on chrome engines, movementX and movementY return global screens coordinates while other browser return pixels
|
this.cowebsiteDom.classList.remove("loaded"); //edit the css class to trigger the transition
|
||||||
//so on chrome-based browser we need to adjust using 'devicePixelRatio'
|
this.cowebsiteDom.classList.add("hidden");
|
||||||
return window.navigator.userAgent.includes("Firefox") ? 1 : window.devicePixelRatio;
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
private close(): void {
|
public resetStyleMain() {
|
||||||
this.cowebsiteDiv.classList.remove("loaded"); //edit the css class to trigger the transition
|
this.cowebsiteDom.style.width = "";
|
||||||
this.cowebsiteDiv.classList.add("hidden");
|
this.cowebsiteDom.style.height = "";
|
||||||
this.opened = iframeStates.closed;
|
|
||||||
this.resetStyle();
|
|
||||||
}
|
|
||||||
private load(): void {
|
|
||||||
this.cowebsiteDiv.classList.remove("hidden"); //edit the css class to trigger the transition
|
|
||||||
this.cowebsiteDiv.classList.add("loading");
|
|
||||||
this.opened = iframeStates.loading;
|
|
||||||
}
|
|
||||||
private open(): void {
|
|
||||||
this.cowebsiteDiv.classList.remove("loading", "hidden"); //edit the css class to trigger the transition
|
|
||||||
this.opened = iframeStates.opened;
|
|
||||||
this.resetStyle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public resetStyle() {
|
private initActionsListeners() {
|
||||||
this.cowebsiteDiv.style.width = "";
|
this.slots.forEach((slot: CoWebsiteSlot) => {
|
||||||
this.cowebsiteDiv.style.height = "";
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private getIframeDom(): HTMLIFrameElement {
|
public getCoWebsites(): CoWebsite[] {
|
||||||
const iframe = HtmlUtils.getElementByIdOrFail<HTMLDivElement>(cowebsiteDivId).querySelector("iframe");
|
return this.coWebsites;
|
||||||
if (!iframe) throw new Error("Could not find iframe!");
|
}
|
||||||
return iframe;
|
|
||||||
|
public getCoWebsiteById(coWebsiteId: string): CoWebsite|undefined {
|
||||||
|
return this.coWebsites.find((coWebsite: CoWebsite) => coWebsite.iframe.id === coWebsiteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSlotByPosition(position: number): CoWebsiteSlot|undefined {
|
||||||
|
return this.slots.find((slot: CoWebsiteSlot) => slot.position === position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getCoWebsiteByPosition(position: number): CoWebsite|undefined {
|
||||||
|
return this.coWebsites.find((coWebsite: CoWebsite) => coWebsite.position === position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private setIframeOffset(coWebsite: CoWebsite, slot: CoWebsiteSlot) {
|
||||||
|
const bounding = slot.container.getBoundingClientRect();
|
||||||
|
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPosition >= 2) {
|
||||||
|
coWebsite.iframe.classList.add('thumbnail');
|
||||||
|
} else {
|
||||||
|
coWebsite.iframe.classList.remove('thumbnail');
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
iconImage.src = `https://www.google.com/s2/favicons?sz=64&domain_url=${iframe.src}`;
|
||||||
|
const url = new URL(iframe.src);
|
||||||
|
iconImage.alt = url.hostname;
|
||||||
|
|
||||||
|
icon.appendChild(iconImage);
|
||||||
|
|
||||||
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
public loadCoWebsite(
|
public loadCoWebsite(
|
||||||
|
@ -171,89 +453,147 @@ class CoWebsiteManager {
|
||||||
base: string,
|
base: string,
|
||||||
allowApi?: boolean,
|
allowApi?: boolean,
|
||||||
allowPolicy?: string,
|
allowPolicy?: string,
|
||||||
widthPercent?: number
|
widthPercent?: number,
|
||||||
): void {
|
position?: number
|
||||||
this.load();
|
): Promise<CoWebsite> {
|
||||||
this.cowebsiteMainDom.innerHTML = ``;
|
|
||||||
|
|
||||||
const iframe = document.createElement("iframe");
|
return this.addCoWebsite((iframeBuffer) => {
|
||||||
iframe.id = "cowebsite-iframe";
|
const iframe = document.createElement("iframe");
|
||||||
iframe.src = new URL(url, base).toString();
|
iframe.src = new URL(url, base).toString()
|
||||||
if (allowPolicy) {
|
|
||||||
iframe.allow = allowPolicy;
|
if (allowPolicy) {
|
||||||
}
|
iframe.allow = allowPolicy;
|
||||||
const onloadPromise = new Promise<void>((resolve) => {
|
}
|
||||||
iframe.onload = () => resolve();
|
|
||||||
});
|
if (allowApi) {
|
||||||
if (allowApi) {
|
iframeListener.registerIframe(iframe);
|
||||||
iframeListener.registerIframe(iframe);
|
}
|
||||||
}
|
|
||||||
this.cowebsiteMainDom.appendChild(iframe);
|
iframeBuffer.appendChild(iframe);
|
||||||
const onTimeoutPromise = new Promise<void>((resolve) => {
|
|
||||||
setTimeout(() => resolve(), 2000);
|
return iframe;
|
||||||
});
|
}, widthPercent, position);
|
||||||
this.currentOperationPromise = this.currentOperationPromise
|
|
||||||
.then(() => Promise.race([onloadPromise, onTimeoutPromise]))
|
|
||||||
.then(() => {
|
|
||||||
this.open();
|
|
||||||
if (widthPercent) {
|
|
||||||
this.widthPercent = widthPercent;
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
|
||||||
this.fire();
|
|
||||||
}, animationTime);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error("Error loadCoWebsite => ", err);
|
|
||||||
this.closeCoWebsite();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
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: (cowebsite: HTMLDivElement) => Promise<void>, widthPercent?: number): void {
|
position?: number
|
||||||
this.load();
|
): Promise<CoWebsite> {
|
||||||
this.cowebsiteMainDom.innerHTML = ``;
|
return new Promise((resolve, reject) => {
|
||||||
this.currentOperationPromise = this.currentOperationPromise
|
if (this.coWebsites.length < 1) {
|
||||||
.then(() => callback(this.cowebsiteMainDom))
|
this.loadMain();
|
||||||
.then(() => {
|
} else if (this.coWebsites.length === 5) {
|
||||||
this.open();
|
throw new Error('Too many we')
|
||||||
if (widthPercent) {
|
}
|
||||||
this.widthPercent = widthPercent;
|
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
|
||||||
this.fire();
|
const onloadPromise = new Promise<void>((resolve) => {
|
||||||
}, animationTime);
|
iframe.onload = () => resolve();
|
||||||
})
|
});
|
||||||
.catch((err) => {
|
|
||||||
console.error("Error insertCoWebsite => ", err);
|
const icon = this.generateCoWebsiteIcon(iframe);
|
||||||
this.closeCoWebsite();
|
|
||||||
|
const coWebsite = {
|
||||||
|
iframe,
|
||||||
|
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);
|
||||||
|
|
||||||
|
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 !== 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolve(coWebsite);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error("Error loadCoWebsite => ", err);
|
||||||
|
this.removeCoWebsiteFromStack(coWebsite);
|
||||||
|
return reject();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public closeCoWebsite(): Promise<void> {
|
public closeCoWebsite(coWebsite: CoWebsite): Promise<void> {
|
||||||
this.currentOperationPromise = this.currentOperationPromise.then(
|
this.currentOperationPromise = this.currentOperationPromise.then(
|
||||||
() =>
|
() =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve) => {
|
||||||
if (this.opened === iframeStates.closed) resolve(); //this method may be called twice, in case of iframe error for example
|
if (this.coWebsites.length === 1) {
|
||||||
this.close();
|
if (this.openedMain === iframeStates.closed) resolve(); //this method may be called twice, in case of iframe error for example
|
||||||
this.fire();
|
this.closeMain();
|
||||||
const iframe = this.cowebsiteDiv.querySelector("iframe");
|
this.fire();
|
||||||
if (iframe) {
|
|
||||||
iframeListener.unregisterIframe(iframe);
|
|
||||||
}
|
}
|
||||||
setTimeout(() => {
|
|
||||||
this.cowebsiteMainDom.innerHTML = ``;
|
if (coWebsite) {
|
||||||
resolve();
|
iframeListener.unregisterIframe(coWebsite.iframe);
|
||||||
}, animationTime);
|
}
|
||||||
|
|
||||||
|
this.removeCoWebsiteFromStack(coWebsite);
|
||||||
|
resolve();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return this.currentOperationPromise;
|
return this.currentOperationPromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
public getGameSize(): { width: number; height: number } {
|
public getGameSize(): { width: number; height: number } {
|
||||||
if (this.opened !== iframeStates.opened) {
|
if (this.openedMain !== iframeStates.opened) {
|
||||||
return {
|
return {
|
||||||
width: window.innerWidth,
|
width: window.innerWidth,
|
||||||
height: window.innerHeight,
|
height: window.innerHeight,
|
||||||
|
@ -279,7 +619,7 @@ class CoWebsiteManager {
|
||||||
|
|
||||||
private fullscreen(): void {
|
private fullscreen(): void {
|
||||||
if (this.isFullScreen) {
|
if (this.isFullScreen) {
|
||||||
this.resetStyle();
|
this.resetStyleMain();
|
||||||
this.fire();
|
this.fire();
|
||||||
//we don't trigger a resize of the phaser game since it won't be visible anyway.
|
//we don't trigger a resize of the phaser game since it won't be visible anyway.
|
||||||
HtmlUtils.getElementByIdOrFail(cowebsiteOpenFullScreenImageId).style.display = "inline";
|
HtmlUtils.getElementByIdOrFail(cowebsiteOpenFullScreenImageId).style.display = "inline";
|
||||||
|
|
|
@ -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,22 +170,35 @@ 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 async stop(): Promise<void> {
|
public stop() {
|
||||||
if (!this.jitsiApi) {
|
if (!this.jitsiApi) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await coWebsiteManager.closeCoWebsite();
|
|
||||||
|
const jitsiCoWebsite = coWebsiteManager.searchJitsi();
|
||||||
|
|
||||||
|
if (jitsiCoWebsite) {
|
||||||
|
coWebsiteManager.closeJitsi();
|
||||||
|
}
|
||||||
|
|
||||||
this.jitsiApi.removeListener("audioMuteStatusChanged", this.audioCallback);
|
this.jitsiApi.removeListener("audioMuteStatusChanged", this.audioCallback);
|
||||||
this.jitsiApi.removeListener("videoMuteStatusChanged", this.videoCallback);
|
this.jitsiApi.removeListener("videoMuteStatusChanged", this.videoCallback);
|
||||||
this.jitsiApi?.dispose();
|
this.jitsiApi?.dispose();
|
||||||
|
|
|
@ -141,7 +141,7 @@ const game = new Game(config);
|
||||||
waScaleManager.setGame(game);
|
waScaleManager.setGame(game);
|
||||||
|
|
||||||
window.addEventListener("resize", function (event) {
|
window.addEventListener("resize", function (event) {
|
||||||
coWebsiteManager.resetStyle();
|
coWebsiteManager.resetStyleMain();
|
||||||
|
|
||||||
waScaleManager.applyNewSize();
|
waScaleManager.applyNewSize();
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,26 +25,112 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
aside {
|
aside {
|
||||||
height: 30px;
|
height: 50px;
|
||||||
min-height: 30px;
|
|
||||||
cursor: ns-resize;
|
cursor: ns-resize;
|
||||||
flex-direction: column;
|
flex-direction: row-reverse;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
#cowebsite-aside-holder {
|
||||||
|
pointer-events: none;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 80%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#cowebsite-sub-icons {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 0;
|
||||||
|
height: 100%;
|
||||||
|
visibility: visible;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 30px;
|
||||||
|
width: 30px;
|
||||||
|
cursor: pointer !important;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
&>div {
|
||||||
|
display: flex;
|
||||||
|
margin-left: 2px;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#cowebsite-aside-buttons {
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-bottom: 0;
|
||||||
|
justify-content: end;
|
||||||
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
cursor: ns-resize;
|
cursor: ns-resize;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.top-right-btn {
|
#cowebsite-fullscreen {
|
||||||
&#cowebsite-close {
|
padding-top: 0;
|
||||||
right: 0;
|
|
||||||
}
|
}
|
||||||
&#cowebsite-fullscreen {
|
|
||||||
left: 0;
|
.top-right-btn {
|
||||||
|
img {
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width:960px) and (max-height:768px) {
|
||||||
|
#cowebsite {
|
||||||
|
|
||||||
|
&-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
aside {
|
||||||
|
#cowebsite-sub-icons {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 0;
|
||||||
|
height: 100%;
|
||||||
|
visibility: visible;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 28px;
|
||||||
|
width: 28px;
|
||||||
|
cursor: pointer !important;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
&>div {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 2px;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
cursor: ns-resize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
#cowebsite {
|
#cowebsite {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
z-index: 200;
|
||||||
transition: transform 0.5s;
|
transition: transform 0.5s;
|
||||||
background-color: white;
|
background-color: whitesmoke;
|
||||||
|
display: none;
|
||||||
|
|
||||||
&.loading {
|
&.loading {
|
||||||
background-color: gray;
|
background-color: gray;
|
||||||
|
@ -22,30 +24,163 @@
|
||||||
background: gray;
|
background: gray;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
img {
|
#cowebsite-aside-holder {
|
||||||
margin: 3px;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#cowebsite-aside-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-bottom: auto;
|
||||||
|
flex: 1;
|
||||||
|
justify-content: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-right-btn{
|
||||||
|
transform: scale(0.5);
|
||||||
|
cursor: url('./images/cursor_pointer.png'), pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cowebsite-sub-icons {
|
||||||
|
display: flex;
|
||||||
|
margin-top: auto;
|
||||||
|
visibility: hidden;
|
||||||
|
justify-content: end;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-right-btn{
|
&-container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: none;
|
height: 100%;
|
||||||
border: none;
|
width: 100%;
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
|
||||||
|
|
||||||
img {
|
&-main {
|
||||||
height: 25px;
|
padding: 2% 5%;
|
||||||
padding: 4px;
|
height: 50%;
|
||||||
border-radius: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
img:hover {
|
&-sub {
|
||||||
background-color: rgba(0,0,0,0.4);
|
position: absolute !important;
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
bottom: 23%;
|
||||||
|
height: 20% !important;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-slot-0 {
|
||||||
|
z-index: 70 !important;
|
||||||
|
background-color: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
@for $i from 1 through 4 {
|
||||||
|
&-slot-#{$i} {
|
||||||
|
transition: transform 0.5s;
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
display: none;
|
||||||
|
background-color: #333333;
|
||||||
|
|
||||||
|
@if $i == 1 {
|
||||||
|
width: 100%;
|
||||||
|
} @else {
|
||||||
|
width: 33%;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 50;
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.actions-move {
|
||||||
|
display: none;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
gap: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba($color: #333333, $alpha: 0.6);
|
||||||
|
|
||||||
|
.actions-move {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
pointer-events: all !important;
|
||||||
|
margin: 3% 2%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: end;
|
||||||
|
position: relative;
|
||||||
|
z-index: 50;
|
||||||
|
|
||||||
|
button {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin: 8px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&-buffer {
|
||||||
|
iframe {
|
||||||
|
z-index: 45 !important;
|
||||||
|
pointer-events: none !important;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
pointer-events: all !important;
|
||||||
|
z-index: 205 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-main {
|
||||||
|
pointer-events: all !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbnail {
|
||||||
|
transform: scale(0.5, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pixel {
|
||||||
|
visibility: hidden;
|
||||||
|
height: 1px;
|
||||||
|
width: 1px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-aspect-ratio: 1/1) {
|
@media (min-aspect-ratio: 1/1) {
|
||||||
|
@ -54,7 +189,7 @@
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
display: flex;
|
display: none;
|
||||||
|
|
||||||
&.loading {
|
&.loading {
|
||||||
transform: translateX(90%);
|
transform: translateX(90%);
|
||||||
|
@ -77,15 +212,5 @@
|
||||||
transform: rotate(90deg);
|
transform: rotate(90deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-right-btn{
|
|
||||||
left: -6px;
|
|
||||||
&#cowebsite-close {
|
|
||||||
top: 0px;
|
|
||||||
}
|
|
||||||
&#cowebsite-fullscreen {
|
|
||||||
top: 25px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1111,3 +1111,18 @@ div.emoji-picker {
|
||||||
border-radius: 1em;
|
border-radius: 1em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.noselect {
|
||||||
|
-webkit-touch-callout: none; /* iOS Safari */
|
||||||
|
-webkit-user-select: none; /* Safari */
|
||||||
|
-khtml-user-select: none; /* Konqueror HTML */
|
||||||
|
-moz-user-select: none; /* Old versions of Firefox */
|
||||||
|
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||||
|
user-select: none; /* Non-prefixed version, currently
|
||||||
|
supported by Chrome, Edge, Opera and Firefox */
|
||||||
|
}
|
||||||
|
|
||||||
|
.pixel {
|
||||||
|
height: 1px !important;
|
||||||
|
width: 1px !important;
|
||||||
|
}
|
||||||
|
|
640
maps/tests/CoWebsite/cowebsite_api.json
Normal file
640
maps/tests/CoWebsite/cowebsite_api.json
Normal file
|
@ -0,0 +1,640 @@
|
||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"floor",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":2,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23],
|
||||||
|
"height":10,
|
||||||
|
"id":5,
|
||||||
|
"name":"first_cowebsite",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12],
|
||||||
|
"height":10,
|
||||||
|
"id":7,
|
||||||
|
"name":"second_cowebsite",
|
||||||
|
"opacity":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"jitsiRoom",
|
||||||
|
"type":"string",
|
||||||
|
"value":"ChillZone"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"jitsiTrigger",
|
||||||
|
"type":"string",
|
||||||
|
"value":"onaction"
|
||||||
|
}],
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":3,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[
|
||||||
|
{
|
||||||
|
"height":220.405430001517,
|
||||||
|
"id":1,
|
||||||
|
"name":"Tests",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"fontfamily":"Sans Serif",
|
||||||
|
"pixelsize":8,
|
||||||
|
"text":"Test 1:\nEnter \/cowebsite open https:\/\/wikipedia.com on the chat\nResult:\nA cowebsite must have been opened\n\nDo the first test 4 more times\n\nTest 2:\nEnter \/cowebsite close 0 on the chat\nResult:\nThe main co-website has been closed\n\nTest 3:\nEnter \/cowebsite close all on the chat\nResult:\nAll co-websites has been closed\n\nTest 4:\nGo on the white carpet to open a Jitsi & open a co-website \/cowebsite open https:\/\/wikipedia.com on the chat\nResult:\nThere are two co-websites",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":316.770833333333,
|
||||||
|
"x":1.64026713939023,
|
||||||
|
"y":97.5557662166938
|
||||||
|
}],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 27, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":8,
|
||||||
|
"name":"objects",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":9,
|
||||||
|
"nextobjectid":3,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"script",
|
||||||
|
"type":"string",
|
||||||
|
"value":"script.js"
|
||||||
|
}],
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.7.2",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"tileset1.png",
|
||||||
|
"imageheight":352,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset1",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":121,
|
||||||
|
"tileheight":32,
|
||||||
|
"tiles":[
|
||||||
|
{
|
||||||
|
"id":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":2,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":3,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":4,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":5,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":6,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":7,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":8,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":9,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":10,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":12,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":16,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":17,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":18,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":19,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":20,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":21,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":23,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":24,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":25,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":26,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":27,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":28,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":29,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":30,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":31,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":32,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":34,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":35,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":42,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":43,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":45,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":46,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":59,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":60,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":70,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":71,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":80,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":81,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":89,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":91,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":93,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":94,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":95,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":96,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":97,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":100,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":102,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":103,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":104,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":105,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":106,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":107,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":108,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":114,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":115,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"collides",
|
||||||
|
"type":"bool",
|
||||||
|
"value":true
|
||||||
|
}]
|
||||||
|
}],
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":"1.6",
|
||||||
|
"width":10
|
||||||
|
}
|
118
maps/tests/CoWebsite/cowebsite_jitsiroom.json
Normal file
118
maps/tests/CoWebsite/cowebsite_jitsiroom.json
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"floor",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":2,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23],
|
||||||
|
"height":10,
|
||||||
|
"id":5,
|
||||||
|
"name":"jitsiRoom",
|
||||||
|
"opacity":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"jitsiRoom",
|
||||||
|
"type":"string",
|
||||||
|
"value":"testJitsiRoomCoWebsite"
|
||||||
|
}],
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12],
|
||||||
|
"height":10,
|
||||||
|
"id":7,
|
||||||
|
"name":"openWebsite",
|
||||||
|
"opacity":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"openWebsite",
|
||||||
|
"type":"string",
|
||||||
|
"value":"https:\/\/workadventu.re\/"
|
||||||
|
}],
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":3,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[
|
||||||
|
{
|
||||||
|
"height":141,
|
||||||
|
"id":1,
|
||||||
|
"name":"Tests",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"fontfamily":"Sans Serif",
|
||||||
|
"pixelsize":11,
|
||||||
|
"text":"Test:\nWalk on the blue carpet, an iframe open, walk on the white carpet another one to open another one\nResult:\n2 co-websites must be opened\n\nTest:\nGo outside of carpets\nResult:\nAll co-websites must disapeared",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":316.770833333333,
|
||||||
|
"x":0.28125,
|
||||||
|
"y":187.833333333333
|
||||||
|
}],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":8,
|
||||||
|
"nextobjectid":3,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.7.2",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"tileset1.png",
|
||||||
|
"imageheight":352,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset1",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":121,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":"1.6",
|
||||||
|
"width":10
|
||||||
|
}
|
118
maps/tests/CoWebsite/cowebsite_property.json
Normal file
118
maps/tests/CoWebsite/cowebsite_property.json
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"floor",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":2,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23, 0, 0, 0, 0, 0, 23, 23, 23, 23, 23],
|
||||||
|
"height":10,
|
||||||
|
"id":5,
|
||||||
|
"name":"first_cowebsite",
|
||||||
|
"opacity":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"openWebsite",
|
||||||
|
"type":"string",
|
||||||
|
"value":"https:\/\/wikipedia.org"
|
||||||
|
}],
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12, 0, 0, 0, 0, 0, 12, 12, 12, 12, 12],
|
||||||
|
"height":10,
|
||||||
|
"id":7,
|
||||||
|
"name":"second_cowebsite",
|
||||||
|
"opacity":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"openWebsite",
|
||||||
|
"type":"string",
|
||||||
|
"value":"https:\/\/workadventu.re\/"
|
||||||
|
}],
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":3,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[
|
||||||
|
{
|
||||||
|
"height":141,
|
||||||
|
"id":1,
|
||||||
|
"name":"Tests",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"fontfamily":"Sans Serif",
|
||||||
|
"pixelsize":11,
|
||||||
|
"text":"Test:\nWalk on the blue carpet, an iframe open, walk on the white carpet another one to open another one\nResult:\n2 co-websites must be opened\n\nTest:\nGo outside of carpets\nResult:\nAll co-websites must disapeared",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":316.770833333333,
|
||||||
|
"x":0.28125,
|
||||||
|
"y":187.833333333333
|
||||||
|
}],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":8,
|
||||||
|
"nextobjectid":3,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"1.7.1",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"tileset1.png",
|
||||||
|
"imageheight":352,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset1",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":121,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":"1.6",
|
||||||
|
"width":10
|
||||||
|
}
|
108
maps/tests/CoWebsite/script.js
Normal file
108
maps/tests/CoWebsite/script.js
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
WA.onInit().then(() => {
|
||||||
|
WA.chat.onChatMessage((message) => {
|
||||||
|
|
||||||
|
if (!message.startsWith('/')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const splitedMessage = message.trim().split(' ');
|
||||||
|
const command = splitedMessage.shift().substr(1);
|
||||||
|
|
||||||
|
executeCommand(command, splitedMessage);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function wookaSendMessage(message) {
|
||||||
|
WA.chat.sendChatMessage(message, 'Wooka');
|
||||||
|
}
|
||||||
|
|
||||||
|
function unknownCommand() {
|
||||||
|
wookaSendMessage('Unknown command');
|
||||||
|
}
|
||||||
|
|
||||||
|
function executeCommand(command, args) {
|
||||||
|
switch(command) {
|
||||||
|
case 'cowebsite':
|
||||||
|
coWebsiteCommand(args);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unknownCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function coWebsiteCommand(args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
wookaSendMessage('Too few arguments');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const subCommand = args.shift();
|
||||||
|
|
||||||
|
switch(subCommand) {
|
||||||
|
case 'open':
|
||||||
|
openCoWebsite(args);
|
||||||
|
break;
|
||||||
|
case 'close':
|
||||||
|
closeCoWebsite(args);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
unknownCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openCoWebsite(args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
wookaSendMessage('Too few arguments');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const url = new URL(args[0]);
|
||||||
|
} catch (exception) {
|
||||||
|
wookaSendMessage('Parameter is not a valid URL !');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await WA.nav.openCoWebSite(args[0]).then(() => {
|
||||||
|
wookaSendMessage('Co-website has been opened !');
|
||||||
|
}).catch((error) => {
|
||||||
|
wookaSendMessage(`Something wrong happen during co-website opening: ${error.message}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function closeCoWebsite(args) {
|
||||||
|
if (args.length < 1) {
|
||||||
|
wookaSendMessage('Too few arguments');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const coWebsites = await WA.nav.getCoWebSites();
|
||||||
|
|
||||||
|
// All
|
||||||
|
if (args[0] === "all" || args[0] === "*") {
|
||||||
|
coWebsites.forEach(coWebsite => {
|
||||||
|
coWebsite.close();
|
||||||
|
});
|
||||||
|
wookaSendMessage('All co-websites has been closed !');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const position = parseInt(args[0]);
|
||||||
|
|
||||||
|
// By ID or Position
|
||||||
|
const coWebsite =
|
||||||
|
isNaN(position) ?
|
||||||
|
coWebsites.find((coWebsite) => coWebsite.id === args[0]) :
|
||||||
|
coWebsites.find((coWebsite) => coWebsite.position === position);
|
||||||
|
|
||||||
|
if (!coWebsite) {
|
||||||
|
wookaSendMessage('Unknown co-website');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await coWebsite.close().then(() => {
|
||||||
|
wookaSendMessage('This co-websites has been closed !');
|
||||||
|
}).catch((error) => {
|
||||||
|
wookaSendMessage(`Something wrong happen during co-website closing: ${error.message}`);
|
||||||
|
});
|
||||||
|
}
|
BIN
maps/tests/CoWebsite/tileset1.png
Normal file
BIN
maps/tests/CoWebsite/tileset1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 29 KiB |
|
@ -3,6 +3,7 @@
|
||||||
<head>
|
<head>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>
|
||||||
|
<title>Map Tests</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
@ -235,6 +236,33 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
<h2>CoWebsite</h2>
|
||||||
|
<table class="table">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="radio" name="test-cowebsite-property"> Success <input type="radio" name="test-cowebsite-property"> Failure <input type="radio" name="test-cowebsite-property" checked> Pending
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="#" class="testLink" data-testmap="cowebsite_property.json" target="_blank">Open co-websites by map property</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="radio" name="test-cowebsite-api"> Success <input type="radio" name="test-cowebsite-api"> Failure <input type="radio" name="test-cowebsite-api" checked> Pending
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="#" class="testLink" data-testmap="CoWebsite/cowebsite_api.json" target="_blank">Open co-websites by scripting api</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="radio" name="test-cowebsite_jitsiroom-layer-properties"> Success <input type="radio" name="test-cowebsite_jitsiroom-layer-properties"> Failure <input type="radio" name="test-cowebsite_jitsiroom-layer-properties" checked> Pending
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="#" class="testLink" data-testmap="CoWebsite/cowebsite_jitsiroom.json" target="_blank">Open co-websites and Jitsi room by layer properties</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
<h2>Mobile</h2>
|
<h2>Mobile</h2>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue