diff --git a/front/src/Api/Events/IframeEvent.ts b/front/src/Api/Events/IframeEvent.ts index 99222e58..c3e2f6c9 100644 --- a/front/src/Api/Events/IframeEvent.ts +++ b/front/src/Api/Events/IframeEvent.ts @@ -15,6 +15,8 @@ import type { LayerEvent } from './LayerEvent'; import type { SetPropertyEvent } from "./setPropertyEvent"; import type { LoadSoundEvent } from "./LoadSoundEvent"; import type { PlaySoundEvent } from "./PlaySoundEvent"; +import type { MenuItemClickedEvent } from "./MenuItemClickedEvent"; +import type { HasPlayerMovedEvent } from "./HasPlayerMovedEvent"; export interface TypedMessageEvent extends MessageEvent { @@ -44,6 +46,8 @@ export type IframeEventMap = { loadSound: LoadSoundEvent playSound: PlaySoundEvent stopSound: null, + getState: undefined, + registerMenuCommand: undefined } export interface IframeEvent { type: T; diff --git a/front/src/Api/Events/LoadPageEvent.ts b/front/src/Api/Events/LoadPageEvent.ts new file mode 100644 index 00000000..9bc7f32a --- /dev/null +++ b/front/src/Api/Events/LoadPageEvent.ts @@ -0,0 +1,13 @@ +import * as tg from "generic-type-guard"; + + + +export const isLoadPageEvent = + new tg.IsInterface().withProperties({ + url: tg.isString, + }).get(); + +/** + * A message sent from the iFrame to the game to add a message in the chat. + */ +export type LoadPageEvent = tg.GuardedType; \ No newline at end of file diff --git a/front/src/Api/IframeListener.ts b/front/src/Api/IframeListener.ts index e7638d04..a495d92b 100644 --- a/front/src/Api/IframeListener.ts +++ b/front/src/Api/IframeListener.ts @@ -1,21 +1,36 @@ - -import { Subject } from "rxjs"; -import { ChatEvent, isChatEvent } from "./Events/ChatEvent"; -import { HtmlUtils } from "../WebRtc/HtmlUtils"; -import type { EnterLeaveEvent } from "./Events/EnterLeaveEvent"; -import { isOpenPopupEvent, OpenPopupEvent } from "./Events/OpenPopupEvent"; -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 { IframeEventMap, IframeEvent, IframeResponseEvent, IframeResponseEventMap, isIframeEventWrapper, TypedMessageEvent } from "./Events/IframeEvent"; -import type { UserInputChatEvent } from "./Events/UserInputChatEvent"; -import { isLoadPageEvent } from './Events/LoadPageEvent'; +import {Subject} from "rxjs"; +import {ChatEvent, isChatEvent} from "./Events/ChatEvent"; +import {HtmlUtils} from "../WebRtc/HtmlUtils"; +import type {EnterLeaveEvent} from "./Events/EnterLeaveEvent"; +import {isOpenPopupEvent, OpenPopupEvent} from "./Events/OpenPopupEvent"; +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 { + IframeEvent, + IframeEventMap, + IframeResponseEvent, + IframeResponseEventMap, + isIframeEventWrapper, + TypedMessageEvent +} from "./Events/IframeEvent"; +import type {UserInputChatEvent} from "./Events/UserInputChatEvent"; +//import { isLoadPageEvent } from './Events/LoadPageEvent'; import {isPlaySoundEvent, PlaySoundEvent} from "./Events/PlaySoundEvent"; import {isStopSoundEvent, StopSoundEvent} from "./Events/StopSoundEvent"; import {isLoadSoundEvent, LoadSoundEvent} from "./Events/LoadSoundEvent"; +import {isSetPropertyEvent, SetPropertyEvent} from "./Events/setPropertyEvent"; +import {isLayerEvent, LayerEvent} from "./Events/LayerEvent"; +import {isMenuItemRegisterEvent} from "./Events/MenuItemRegisterEvent"; +import type {DataLayerEvent} from "./Events/DataLayerEvent"; +import type {GameStateEvent} from "./Events/GameStateEvent"; +import type {MenuItemClickedEvent} from "./Events/MenuItemClickedEvent"; +import type {HasPlayerMovedEvent} from "./Events/HasPlayerMovedEvent"; +import {isLoadPageEvent} from "./Events/LoadPageEvent"; + /** * Listens to messages from iframes and turn those messages into easy to use observables. * Also allows to send messages to those iframes. @@ -34,6 +49,9 @@ class IframeListener { private readonly _goToPageStream: Subject = new Subject(); public readonly goToPageStream = this._goToPageStream.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(); @@ -135,6 +153,9 @@ class IframeListener { else if (payload.type === 'goToPage' && isGoToPageEvent(payload.data)) { scriptUtils.goToPage(payload.data.url); } + else if (payload.type === 'loadPage' && isLoadPageEvent(payload.data)) { + this._loadPageStream.next(payload.data.url); + } else if (payload.type === 'playSound' && isPlaySoundEvent(payload.data)) { this._playSoundStream.next(payload.data); } @@ -216,7 +237,7 @@ class IframeListener { if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') { // Using external iframe mode ( const iframe = document.createElement('iframe'); - iframe.id = this.getIFrameId(scriptUrl); + iframe.id = IframeListener.getIFrameId(scriptUrl); iframe.style.display = 'none'; iframe.src = '/iframe.html?script=' + encodeURIComponent(scriptUrl); @@ -231,25 +252,24 @@ class IframeListener { } else { // production code const iframe = document.createElement('iframe'); - iframe.id = this.getIFrameId(scriptUrl); + iframe.id = IframeListener.getIFrameId(scriptUrl); iframe.style.display = 'none'; // We are putting a sandbox on this script because it will run in the same domain as the main website. iframe.sandbox.add('allow-scripts'); iframe.sandbox.add('allow-top-navigation-by-user-activation'); - const html = '\n' + + //iframe.src = "data:text/html;charset=utf-8," + escape(html); + iframe.srcdoc = '\n' + '\n' + '\n' + '\n' + '\n' + '\n' + + '\n' + '\n' + '\n'; - //iframe.src = "data:text/html;charset=utf-8," + escape(html); - iframe.srcdoc = html; - document.body.prepend(iframe); this.scripts.set(scriptUrl, iframe); @@ -259,12 +279,12 @@ class IframeListener { } - private getIFrameId(scriptUrl: string): string { + private static getIFrameId(scriptUrl: string): string { return 'script' + btoa(scriptUrl); } unregisterScript(scriptUrl: string): void { - const iFrameId = this.getIFrameId(scriptUrl); + const iFrameId = IframeListener.getIFrameId(scriptUrl); const iframe = HtmlUtils.getElementByIdOrFail(iFrameId); if (!iframe) { throw new Error('Unknown iframe for script "' + scriptUrl + '"'); diff --git a/front/src/Api/iframe/nav.ts b/front/src/Api/iframe/nav.ts index b6798330..f6add88e 100644 --- a/front/src/Api/iframe/nav.ts +++ b/front/src/Api/iframe/nav.ts @@ -2,6 +2,7 @@ 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"; class WorkadventureNavigationCommands extends IframeApiContribution { @@ -31,7 +32,7 @@ class WorkadventureNavigationCommands extends IframeApiContribution void> = new Map() const wa = { ui, nav, @@ -100,7 +103,8 @@ const wa = { /** * @deprecated Use WA.nav.openCoWebSite instead - */openCoWebSite(url: string): void { + */ + openCoWebSite(url: string): void { console.warn('Method WA.openCoWebSite is deprecated. Please use WA.nav.openCoWebSite instead'); nav.openCoWebSite(url); }, diff --git a/front/yarn.lock b/front/yarn.lock index e64a76c1..a96be8aa 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -1417,6 +1417,13 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -1428,7 +1435,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==