diff --git a/docs/maps/api-nav.md b/docs/maps/api-nav.md index f5721063..386edf9e 100644 --- a/docs/maps/api-nav.md +++ b/docs/maps/api-nav.md @@ -49,19 +49,36 @@ WA.nav.goToRoom('../otherMap/map.json'); WA.nav.goToRoom("/_/global/.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.closeCoWebSite(): void +WA.nav.openCoWebsite(url: string, allowApi: boolean = false, allowPolicy: string = "", position: number = 0): Promise +WA.nav.closeCoWebsite(coWebsiteId: string): Promise +WA.nav.closeCoWebsites(): Promise ``` -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. Example: ```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(); +WA.nav.closeCoWebsite(coWebsite.id); +WA.nav.closeCoWebsites(); +``` + +### Opening/closing web page in Co-Websites + +``` +WA.nav.getCoWebsites(): Promise +``` + +Get all opened co-websites withe their ids and positions. + +Example: + +```javascript +const coWebsites = await WA.nav.getCowebsites(); ``` diff --git a/front/dist/index.tmpl.html b/front/dist/index.tmpl.html index dc21765b..3b43a5ef 100644 --- a/front/dist/index.tmpl.html +++ b/front/dist/index.tmpl.html @@ -111,8 +111,7 @@
-
-
+
diff --git a/front/src/Api/Events/CloseCoWebsiteEvent.ts b/front/src/Api/Events/CloseCoWebsiteEvent.ts new file mode 100644 index 00000000..94167d5e --- /dev/null +++ b/front/src/Api/Events/CloseCoWebsiteEvent.ts @@ -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; diff --git a/front/src/Api/Events/IframeEvent.ts b/front/src/Api/Events/IframeEvent.ts index 861acc22..554e4545 100644 --- a/front/src/Api/Events/IframeEvent.ts +++ b/front/src/Api/Events/IframeEvent.ts @@ -5,11 +5,10 @@ import type { ClosePopupEvent } from "./ClosePopupEvent"; import type { EnterLeaveEvent } from "./EnterLeaveEvent"; import type { GoToPageEvent } from "./GoToPageEvent"; import type { LoadPageEvent } from "./LoadPageEvent"; -import type { OpenCoWebSiteEvent } from "./OpenCoWebSiteEvent"; +import { coWebsite, isOpenCoWebsiteEvent } from "./OpenCoWebsiteEvent"; import type { OpenPopupEvent } from "./OpenPopupEvent"; import type { OpenTabEvent } from "./OpenTabEvent"; import type { UserInputChatEvent } from "./UserInputChatEvent"; -import type { MapDataEvent } from "./MapDataEvent"; import type { LayerEvent } from "./LayerEvent"; import type { SetPropertyEvent } from "./setPropertyEvent"; import type { LoadSoundEvent } from "./LoadSoundEvent"; @@ -27,9 +26,6 @@ import type { LoadTilesetEvent } from "./LoadTilesetEvent"; import { isLoadTilesetEvent } from "./LoadTilesetEvent"; import type { MessageReferenceEvent, - removeActionMessage, - triggerActionMessage, - TriggerActionMessageEvent, } from "./ui/TriggerActionMessageEvent"; import { isMessageReferenceEvent, isTriggerActionMessageEvent } from "./ui/TriggerActionMessageEvent"; import type { MenuRegisterEvent, UnregisterMenuEvent } from "./ui/MenuRegisterEvent"; @@ -48,8 +44,6 @@ export type IframeEventMap = { closePopup: ClosePopupEvent; openTab: OpenTabEvent; goToPage: GoToPageEvent; - openCoWebSite: OpenCoWebSiteEvent; - closeCoWebSite: null; disablePlayerControls: null; restorePlayerControls: null; displayBubble: null; @@ -118,6 +112,22 @@ export const iframeQueryMapTypeGuards = { query: isLoadTilesetEvent, answer: tg.isNumber, }, + openCoWebsite: { + query: isOpenCoWebsiteEvent, + answer: coWebsite + }, + getCoWebsites: { + query: tg.isUndefined, + answer: tg.isArray(coWebsite) + }, + closeCoWebsite: { + query: tg.isString, + answer: tg.isUndefined + }, + closeCoWebsites: { + query: tg.isUndefined, + answer: tg.isUndefined + }, triggerActionMessage: { query: isTriggerActionMessageEvent, answer: tg.isUndefined, diff --git a/front/src/Api/Events/OpenCoWebSiteEvent.ts b/front/src/Api/Events/OpenCoWebSiteEvent.ts deleted file mode 100644 index 7b5e6070..00000000 --- a/front/src/Api/Events/OpenCoWebSiteEvent.ts +++ /dev/null @@ -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; diff --git a/front/src/Api/Events/OpenCoWebsiteEvent.ts b/front/src/Api/Events/OpenCoWebsiteEvent.ts new file mode 100644 index 00000000..cc70b2e5 --- /dev/null +++ b/front/src/Api/Events/OpenCoWebsiteEvent.ts @@ -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 coWebsite = 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; diff --git a/front/src/Api/IframeListener.ts b/front/src/Api/IframeListener.ts index 5a9aca85..caa59420 100644 --- a/front/src/Api/IframeListener.ts +++ b/front/src/Api/IframeListener.ts @@ -1,6 +1,5 @@ import { Subject } from "rxjs"; -import type * as tg from "generic-type-guard"; -import { ChatEvent, isChatEvent } from "./Events/ChatEvent"; +import { isChatEvent } from "./Events/ChatEvent"; import { HtmlUtils } from "../WebRtc/HtmlUtils"; import type { EnterLeaveEvent } from "./Events/EnterLeaveEvent"; import { isOpenPopupEvent, OpenPopupEvent } from "./Events/OpenPopupEvent"; @@ -8,18 +7,15 @@ import { isOpenTabEvent, OpenTabEvent } from "./Events/OpenTabEvent"; import type { ButtonClickedEvent } from "./Events/ButtonClickedEvent"; import { ClosePopupEvent, isClosePopupEvent } from "./Events/ClosePopupEvent"; import { scriptUtils } from "./ScriptUtils"; -import { GoToPageEvent, isGoToPageEvent } from "./Events/GoToPageEvent"; -import { isOpenCoWebsite, OpenCoWebSiteEvent } from "./Events/OpenCoWebSiteEvent"; +import { isGoToPageEvent } from "./Events/GoToPageEvent"; +import { isCloseCoWebsite, CloseCoWebsiteEvent } from "./Events/CloseCoWebsiteEvent"; import { IframeErrorAnswerEvent, - IframeEvent, - IframeEventMap, IframeQueryMap, IframeResponseEvent, IframeResponseEventMap, isIframeEventWrapper, isIframeQueryWrapper, - TypedMessageEvent, } from "./Events/IframeEvent"; import type { UserInputChatEvent } from "./Events/UserInputChatEvent"; import { isPlaySoundEvent, PlaySoundEvent } from "./Events/PlaySoundEvent"; @@ -33,7 +29,6 @@ import { isMenuRegisterEvent, isUnregisterMenuEvent } from "./Events/ui/MenuRegi import { SetTilesEvent, isSetTilesEvent } from "./Events/SetTilesEvent"; import type { SetVariableEvent } from "./Events/SetVariableEvent"; import { ModifyEmbeddedWebsiteEvent, isEmbeddedWebsiteEvent } from "./Events/EmbeddedWebsiteEvent"; -import { EmbeddedWebsite } from "./iframe/Room/EmbeddedWebsite"; import { handleMenuRegistrationEvent, handleMenuUnregisterEvent } from "../Stores/MenuStore"; type AnswererCallback = ( @@ -53,10 +48,7 @@ class IframeListener { public readonly openTabStream = this._openTabStream.asObservable(); private readonly _loadPageStream: Subject = new Subject(); - public readonly loadPageStream = this._loadPageStream.asObservable(); - - private readonly _openCoWebSiteStream: Subject = new Subject(); - public readonly openCoWebSiteStream = this._openCoWebSiteStream.asObservable(); + public readonly loadPageStream = this._loadPageStream.asObservable() private readonly _disablePlayerControlStream: Subject = new Subject(); public readonly disablePlayerControlStream = this._disablePlayerControlStream.asObservable(); @@ -138,8 +130,6 @@ class IframeListener { return; } - foundSrc = this.getBaseUrl(foundSrc, message.source); - if (isIframeQueryWrapper(payload)) { const queryId = payload.id; const query = payload.query; @@ -224,15 +214,6 @@ class IframeListener { this._stopSoundStream.next(payload.data); } else if (payload.type === "loadSound" && isLoadSoundEvent(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") { this._disablePlayerControlStream.next(); } else if (payload.type === "restorePlayerControls") { @@ -252,6 +233,9 @@ class IframeListener { this.iframeCloseCallbacks.get(iframe)?.push(() => { handleMenuUnregisterEvent(dataName); }); + + foundSrc = this.getBaseUrl(foundSrc, message.source); + handleMenuRegistrationEvent( payload.data.name, payload.data.iframe, @@ -354,6 +338,20 @@ class IframeListener { 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 { return "script" + btoa(scriptUrl); } diff --git a/front/src/Api/ScriptUtils.ts b/front/src/Api/ScriptUtils.ts index ad6dcc0f..10a80c92 100644 --- a/front/src/Api/ScriptUtils.ts +++ b/front/src/Api/ScriptUtils.ts @@ -1,4 +1,4 @@ -import { coWebsiteManager } from "../WebRtc/CoWebsiteManager"; +import { coWebsiteManager, CoWebsite } from "../WebRtc/CoWebsiteManager"; import { playersStore } from "../Stores/PlayersStore"; import { chatMessagesStore } from "../Stores/ChatStore"; import type { ChatEvent } from "./Events/ChatEvent"; @@ -12,14 +12,6 @@ class ScriptUtils { 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) { const userId = playersStore.addFacticePlayer(chatEvent.author); chatMessagesStore.addExternalMessage(userId, chatEvent.message); diff --git a/front/src/Api/iframe/nav.ts b/front/src/Api/iframe/nav.ts index f051a7c0..24b04e62 100644 --- a/front/src/Api/iframe/nav.ts +++ b/front/src/Api/iframe/nav.ts @@ -1,8 +1,4 @@ -import type { GoToPageEvent } from "../Events/GoToPageEvent"; -import type { OpenTabEvent } from "../Events/OpenTabEvent"; -import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution"; -import type { OpenCoWebSiteEvent } from "../Events/OpenCoWebSiteEvent"; -import type { LoadPageEvent } from "../Events/LoadPageEvent"; +import { IframeApiContribution, sendToWorkadventure, queryWorkadventure } from "./IframeApiContribution"; export class WorkadventureNavigationCommands extends IframeApiContribution { callbacks = []; @@ -34,21 +30,61 @@ export class WorkadventureNavigationCommands extends IframeApiContribution { + 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", () => { return { data: this.gameMap.getMap(), @@ -1310,6 +1361,8 @@ ${escapedMessage} iframeListener.unregisterAnswerer("getMapData"); iframeListener.unregisterAnswerer("triggerActionMessage"); iframeListener.unregisterAnswerer("removeActionMessage"); + iframeListener.unregisterAnswerer("openCoWebsite"); + iframeListener.unregisterAnswerer("getCoWebsites"); this.sharedVariablesManager?.close(); this.embeddedWebsiteManager?.close(); diff --git a/front/src/WebRtc/CoWebsiteManager.ts b/front/src/WebRtc/CoWebsiteManager.ts index b60578df..06b29d18 100644 --- a/front/src/WebRtc/CoWebsiteManager.ts +++ b/front/src/WebRtc/CoWebsiteManager.ts @@ -27,13 +27,13 @@ interface TouchMoveCoordinates { y: number; } -export interface CoWebsite { +export type CoWebsite = { iframe: HTMLIFrameElement, icon: HTMLDivElement, position: number } -interface CoWebsiteSlot { +type CoWebsiteSlot = { container: HTMLElement, position: number } @@ -186,6 +186,7 @@ class CoWebsiteManager { }; this.cowebsiteAsideDom.addEventListener(touchMode ? "touchstart" : "mousedown", (event) => { + this.cowebsiteMainDom.style.display = "none"; this.resizing = true; if (touchMode) { const touchEvent = (event as TouchEvent).touches[0]; @@ -203,6 +204,7 @@ class CoWebsiteManager { document.removeEventListener(touchMode ? "touchmove" : "mousemove", movecallback); this.cowebsiteMainDom.style.display = "block"; this.resizing = false; + this.cowebsiteMainDom.style.display = "flex"; }); } @@ -277,7 +279,11 @@ class CoWebsiteManager { }); } - private searchCoWebsiteById(coWebsiteId: string): CoWebsite|undefined { + public getCoWebsites(): CoWebsite[] { + return this.coWebsites; + } + + public getCoWebsiteById(coWebsiteId: string): CoWebsite|undefined { return this.coWebsites.find((coWebsite: CoWebsite) => coWebsite.iframe.id === coWebsiteId); } @@ -449,7 +455,7 @@ class CoWebsiteManager { do { iframe.id = "cowebsite-iframe-" + (Math.random() + 1).toString(36).substring(7); - } while (iframe.id.toLowerCase().includes('jitsi') || this.searchCoWebsiteById(iframe.id)); + } while (iframe.id.toLowerCase().includes('jitsi') || this.getCoWebsiteById(iframe.id)); iframe.src = new URL(url, base).toString() diff --git a/front/style/cowebsite-mobile.scss b/front/style/cowebsite-mobile.scss index b336a29a..3a3482a9 100644 --- a/front/style/cowebsite-mobile.scss +++ b/front/style/cowebsite-mobile.scss @@ -31,8 +31,7 @@ aside { - height: 30px; - min-height: 30px; + height: 50px; cursor: ns-resize; flex-direction: row-reverse; align-items: center; @@ -58,8 +57,8 @@ visibility: visible; img { - height: 20px; - width: 20px; + height: 30px; + width: 30px; cursor: pointer !important; border-radius: 50%; background-color: whitesmoke; diff --git a/front/style/cowebsite.scss b/front/style/cowebsite.scss index c2e0b2d2..223ed85a 100644 --- a/front/style/cowebsite.scss +++ b/front/style/cowebsite.scss @@ -4,7 +4,7 @@ position: fixed; z-index: 200; transition: transform 0.5s; - background-color: white; + background-color: whitesmoke; display: none; &.loading { diff --git a/maps/tests/CoWebsite/cowebsite_api.json b/maps/tests/CoWebsite/cowebsite_api.json new file mode 100644 index 00000000..7f5537ff --- /dev/null +++ b/maps/tests/CoWebsite/cowebsite_api.json @@ -0,0 +1,629 @@ +{ "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, + "type":"tilelayer", + "visible":true, + "width":10, + "x":0, + "y":0 + }, + { + "draworder":"topdown", + "id":3, + "name":"floorLayer", + "objects":[ + { + "height":157.696496283938, + "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", + "wrap":true + }, + "type":"", + "visible":true, + "width":316.770833333333, + "x":1.64026713939023, + "y":160.264699934273 + }], + "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 +} \ No newline at end of file diff --git a/maps/tests/CoWebsite/cowebsite_property.json b/maps/tests/CoWebsite/cowebsite_property.json new file mode 100644 index 00000000..d01c1753 --- /dev/null +++ b/maps/tests/CoWebsite/cowebsite_property.json @@ -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 +} \ No newline at end of file diff --git a/maps/tests/CoWebsite/script.js b/maps/tests/CoWebsite/script.js new file mode 100644 index 00000000..ae1f94d2 --- /dev/null +++ b/maps/tests/CoWebsite/script.js @@ -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; + } + + // All + if (args[0] === "all" || args[0] === "*") { + WA.nav.closeCoWebsites().then(() => { + wookaSendMessage('All co-websites has been closed !'); + }).catch((error) => { + wookaSendMessage(`Something wrong happen during co-websites closing: ${error.message}`); + }); + return; + } + + const coWebsites = await WA.nav.getCoWebsites(); + 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 WA.nav.closeCoWebsite(coWebsite.id).then(() => { + wookaSendMessage('This co-websites has been closed !'); + }).catch((error) => { + wookaSendMessage(`Something wrong happen during co-website closing: ${error.message}`); + }); +} diff --git a/maps/tests/CoWebsite/tileset1.png b/maps/tests/CoWebsite/tileset1.png new file mode 100644 index 00000000..6e7dafb4 Binary files /dev/null and b/maps/tests/CoWebsite/tileset1.png differ diff --git a/maps/tests/index.html b/maps/tests/index.html index c30b54a5..692783af 100644 --- a/maps/tests/index.html +++ b/maps/tests/index.html @@ -3,6 +3,7 @@ + Map Tests
@@ -235,6 +236,25 @@ +

CoWebsite

+ + + + + + + + + +
+ Success Failure Pending + + Open co-websites by map property +
+ Success Failure Pending + + Open co-websites by scripting api +

Mobile