Adding an API for inter-iframe communication
Adds a first version of an API to communicate between an iFrame opened by WorkAdventure and WorkAdventure itself. The first API method is a method allowing to add messages in the chat, from the iFrame. Comes with a test file.
This commit is contained in:
parent
bf8e8bf777
commit
eb93a04341
8 changed files with 184 additions and 4 deletions
3
front/dist/.gitignore
vendored
3
front/dist/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
index.html
|
||||
index.html
|
||||
/js/
|
||||
|
|
34
front/src/Api/IframeListener.ts
Normal file
34
front/src/Api/IframeListener.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
import {Subject} from "rxjs";
|
||||
|
||||
interface ChatEvent {
|
||||
message: string,
|
||||
author: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to messages from iframes and turn those messages into easy to use observables.
|
||||
*/
|
||||
class IframeListener {
|
||||
private readonly _chatStream: Subject<ChatEvent> = new Subject();
|
||||
public readonly chatStream = this._chatStream.asObservable();
|
||||
|
||||
init() {
|
||||
window.addEventListener("message", (event) => {
|
||||
// Do we trust the sender of this message?
|
||||
//if (event.origin !== "http://example.com:8080")
|
||||
// return;
|
||||
|
||||
// event.source is window.opener
|
||||
// event.data is the data sent by the iframe
|
||||
|
||||
// FIXME: this is WAAAAAAAY too sloppy as "any" let's us put anything in the message.
|
||||
|
||||
if (event.data.type === 'chat') {
|
||||
this._chatStream.next(event.data.data);
|
||||
}
|
||||
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
export const iframeListener = new IframeListener();
|
|
@ -3,6 +3,7 @@ import {mediaManager, ReportCallback, ShowReportCallBack} from "./MediaManager";
|
|||
import {UserInputManager} from "../Phaser/UserInput/UserInputManager";
|
||||
import {connectionManager} from "../Connexion/ConnectionManager";
|
||||
import {GameConnexionTypes} from "../Url/UrlManager";
|
||||
import {iframeListener} from "../Api/IframeListener";
|
||||
|
||||
export type SendMessageCallback = (message:string) => void;
|
||||
|
||||
|
@ -25,6 +26,11 @@ export class DiscussionManager {
|
|||
constructor() {
|
||||
this.mainContainer = HtmlUtils.getElementByIdOrFail<HTMLDivElement>('main-container');
|
||||
this.createDiscussPart(''); //todo: why do we always use empty string?
|
||||
|
||||
iframeListener.chatStream.subscribe((chatEvent) => {
|
||||
this.addMessage(chatEvent.author, chatEvent.message, false);
|
||||
this.showDiscussion();
|
||||
});
|
||||
}
|
||||
|
||||
private createDiscussPart(name: string) {
|
||||
|
|
21
front/src/iframe_api.ts
Normal file
21
front/src/iframe_api.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
interface WorkAdventureApi {
|
||||
sendChatMessage(message: string, author: string): void;
|
||||
}
|
||||
|
||||
declare var WA: WorkAdventureApi;
|
||||
|
||||
window.WA = {
|
||||
/**
|
||||
* Sends a message in the chat.
|
||||
* Only the local user will receive this message.
|
||||
*/
|
||||
sendChatMessage(message: string, author: string) {
|
||||
window.parent.postMessage({
|
||||
'type': 'chat',
|
||||
'data': {
|
||||
'message': message,
|
||||
'author': author
|
||||
}
|
||||
}, '*');
|
||||
}
|
||||
}
|
|
@ -14,6 +14,8 @@ import {coWebsiteManager} from "./WebRtc/CoWebsiteManager";
|
|||
import {MenuScene} from "./Phaser/Menu/MenuScene";
|
||||
import {localUserStore} from "./Connexion/LocalUserStore";
|
||||
import {ErrorScene} from "./Phaser/Reconnecting/ErrorScene";
|
||||
import {iframeListener} from "./Api/IframeListener";
|
||||
import {discussionManager} from "./WebRtc/DiscussionManager";
|
||||
|
||||
// Load Jitsi if the environment variable is set.
|
||||
if (JITSI_URL) {
|
||||
|
@ -124,3 +126,5 @@ coWebsiteManager.onStateChange(() => {
|
|||
const {width, height} = coWebsiteManager.getGameSize();
|
||||
game.scale.resize(width / RESOLUTION, height / RESOLUTION);
|
||||
});
|
||||
|
||||
iframeListener.init();
|
||||
|
|
|
@ -3,7 +3,10 @@ const webpack = require('webpack');
|
|||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.ts',
|
||||
entry: {
|
||||
'main': './src/index.ts',
|
||||
'iframe_api': './src/iframe_api.ts'
|
||||
},
|
||||
devtool: 'inline-source-map',
|
||||
devServer: {
|
||||
contentBase: './dist',
|
||||
|
@ -29,7 +32,11 @@ module.exports = {
|
|||
extensions: [ '.tsx', '.ts', '.js' ],
|
||||
},
|
||||
output: {
|
||||
filename: '[name].[contenthash].js',
|
||||
filename: (pathData) => {
|
||||
// Add a content hash only for the main bundle.
|
||||
// We want the iframe_api.js file to keep its name as it will be referenced from outside iframes.
|
||||
return pathData.chunk.name === 'main' ? 'js/[name].[contenthash].js': '[name].js';
|
||||
},
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
publicPath: '/'
|
||||
},
|
||||
|
@ -48,7 +55,8 @@ module.exports = {
|
|||
removeScriptTypeAttributes: true,
|
||||
removeStyleLinkTypeAttributes: true,
|
||||
useShortDoctype: true
|
||||
}
|
||||
},
|
||||
chunks: ['main']
|
||||
}
|
||||
),
|
||||
new webpack.ProvidePlugin({
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue