diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 3bf00b99..e33346d0 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -199,4 +199,4 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - msg: Environment deployed at https://play-${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re + msg: "Environment deployed at https://play-${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re \nTests available at https://maps-${{ env.GITHUB_HEAD_REF_SLUG }}.test.workadventu.re/tests" diff --git a/front/src/Api/IframeListener.ts b/front/src/Api/IframeListener.ts index 9311d7b6..0adaac85 100644 --- a/front/src/Api/IframeListener.ts +++ b/front/src/Api/IframeListener.ts @@ -123,11 +123,18 @@ class IframeListener { } } + const payload = message.data; + if (foundSrc === undefined) { + if (isIframeEventWrapper(payload)) { + console.warn('It seems an iFrame is trying to communicate with WorkAdventure but was not explicitly granted the permission to do so. ' + + 'If you are looking to use the WorkAdventure Scripting API inside an iFrame, you should allow the ' + + 'iFrame to communicate with WorkAdventure by using the "openWebsiteAllowApi" property in your map (or passing "true" as a second' + + 'parameter to WA.nav.openCoWebSite())'); + } return; } - const payload = message.data; if (isIframeEventWrapper(payload)) { if (payload.type === 'showLayer' && isLayerEvent(payload.data)) { this._showLayerStream.next(payload.data); diff --git a/front/src/Api/iframe/room.ts b/front/src/Api/iframe/room.ts index aed4d983..817141f4 100644 --- a/front/src/Api/iframe/room.ts +++ b/front/src/Api/iframe/room.ts @@ -1,53 +1,51 @@ import { Subject } from "rxjs"; -import { EnterLeaveEvent, isEnterLeaveEvent } from '../Events/EnterLeaveEvent'; -import {IframeApiContribution, sendToWorkadventure} from './IframeApiContribution'; + +import { isDataLayerEvent } from "../Events/DataLayerEvent"; +import { EnterLeaveEvent, isEnterLeaveEvent } from "../Events/EnterLeaveEvent"; +import { isGameStateEvent } from "../Events/GameStateEvent"; + +import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution"; import { apiCallback } from "./registeredCallbacks"; -import type {LayerEvent} from "../Events/LayerEvent"; -import type {SetPropertyEvent} from "../Events/setPropertyEvent"; -import type {GameStateEvent} from "../Events/GameStateEvent"; -import type {ITiledMap} from "../../Phaser/Map/ITiledMap"; -import type {DataLayerEvent} from "../Events/DataLayerEvent"; -import {isGameStateEvent} from "../Events/GameStateEvent"; -import {isDataLayerEvent} from "../Events/DataLayerEvent"; + +import type { ITiledMap } from "../../Phaser/Map/ITiledMap"; +import type { DataLayerEvent } from "../Events/DataLayerEvent"; +import type { GameStateEvent } from "../Events/GameStateEvent"; const enterStreams: Map> = new Map>(); const leaveStreams: Map> = new Map>(); const dataLayerResolver = new Subject(); const stateResolvers = new Subject(); -let immutableData: GameStateEvent; +let immutableDataPromise: Promise | undefined = undefined; interface Room { - id: string, - mapUrl: string, - map: ITiledMap, - startLayer: string | null + id: string; + mapUrl: string; + map: ITiledMap; + startLayer: string | null; } interface User { - id: string | undefined, - nickName: string | null, - tags: string[] + id: string | undefined; + nickName: string | null; + tags: string[]; } - function getGameState(): Promise { - if (immutableData) { - return Promise.resolve(immutableData); - } - else { - return new Promise((resolver, thrower) => { + if (immutableDataPromise === undefined) { + immutableDataPromise = new Promise((resolver, thrower) => { stateResolvers.subscribe(resolver); - sendToWorkadventure({type: "getState", data: null}); - }) + sendToWorkadventure({ type: "getState", data: null }); + }); } + return immutableDataPromise; } function getDataLayer(): Promise { return new Promise((resolver, thrower) => { dataLayerResolver.subscribe(resolver); - sendToWorkadventure({type: "getDataLayer", data: null}) - }) + sendToWorkadventure({ type: "getDataLayer", data: null }); + }); } class WorkadventureRoomCommands extends IframeApiContribution { @@ -57,31 +55,30 @@ class WorkadventureRoomCommands extends IframeApiContribution { leaveStreams.get(payloadData.name)?.next(); - } + }, }), apiCallback({ type: "gameState", typeChecker: isGameStateEvent, callback: (payloadData) => { stateResolvers.next(payloadData); - } + }, }), apiCallback({ type: "dataLayer", typeChecker: isDataLayerEvent, callback: (payloadData) => { dataLayerResolver.next(payloadData); - } + }, }), - ] - + ]; onEnterZone(name: string, callback: () => void): void { let subject = enterStreams.get(name); @@ -90,7 +87,6 @@ class WorkadventureRoomCommands extends IframeApiContribution void): void { let subject = leaveStreams.get(name); @@ -101,35 +97,38 @@ class WorkadventureRoomCommands extends IframeApiContribution { return getGameState().then((gameState) => { - return getDataLayer().then((mapJson) => { - return {id: gameState.roomId, map: mapJson.data as ITiledMap, mapUrl: gameState.mapUrl, startLayer: gameState.startLayerName}; - }) - }) + return getDataLayer().then((mapJson) => { + return { + id: gameState.roomId, + map: mapJson.data as ITiledMap, + mapUrl: gameState.mapUrl, + startLayer: gameState.startLayerName, + }; + }); + }); } getCurrentUser(): Promise { return getGameState().then((gameState) => { - return {id: gameState.uuid, nickName: gameState.nickname, tags: gameState.tags}; - }) + return { id: gameState.uuid, nickName: gameState.nickname, tags: gameState.tags }; + }); } - } - export default new WorkadventureRoomCommands(); diff --git a/maps/tests/iframe.html b/maps/tests/iframe.html index aa8e55ec..038874b6 100644 --- a/maps/tests/iframe.html +++ b/maps/tests/iframe.html @@ -1,22 +1,30 @@ - +
diff --git a/maps/tests/index.html b/maps/tests/index.html index 0929ab83..1f5f2a0e 100644 --- a/maps/tests/index.html +++ b/maps/tests/index.html @@ -4,7 +4,7 @@ - + @@ -166,6 +166,21 @@
Result