cowebsite

navigation
sound
player
extraction
This commit is contained in:
jonny 2021-05-28 01:14:10 +02:00
parent ea04dd5303
commit 540e5783b6
8 changed files with 1297 additions and 113 deletions

1141
front/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
import type { OpenCoWebSiteEvent } from '../Events/OpenCoWebSiteEvent';
import { IframeApiContribution, sendToWorkadventure } from './IframeApiContribution';
class WorkadventureCoWebsiteCommands extends IframeApiContribution<WorkadventureCoWebsiteCommands> {
readonly subObjectIdentifier = "cowebsite"
readonly addMethodsAtRoot = true
callbacks = []
openCoWebSite(url: string): void {
sendToWorkadventure({
"type": 'openCoWebSite',
"data": {
url
} as OpenCoWebSiteEvent
});
}
closeCoWebSite(): void {
sendToWorkadventure({
"type": 'closeCoWebSite',
data: null
});
}
}
export default new WorkadventureCoWebsiteCommands();

View File

@ -1,8 +1,7 @@
import type { IframeEvent, IframeEventMap, IframeResponseEventMap } from '../Events/IframeEvent';
import type * as tg from "generic-type-guard"; import type * as tg from "generic-type-guard";
import type { IframeEvent, IframeEventMap, IframeResponseEventMap } from '../Events/IframeEvent';
export type PossibleSubobjects = "zone" | "chat" | "ui"
export function sendToWorkadventure(content: IframeEvent<keyof IframeEventMap>) { export function sendToWorkadventure(content: IframeEvent<keyof IframeEventMap>) {
window.parent.postMessage(content, "*") window.parent.postMessage(content, "*")
@ -21,7 +20,7 @@ export interface IframeCallbackContribution<Guard extends tg.TypeGuard<unknown>,
callback: (payloadData: T) => void callback: (payloadData: T) => void
} }
export type PossibleSubobjects = "zone" | "chat" | "ui" | "nav" | "sound" | "cowebsite" | "player"
/** /**
* !! be aware that the implemented attributes (addMethodsAtRoot and subObjectIdentifier) must be readonly * !! be aware that the implemented attributes (addMethodsAtRoot and subObjectIdentifier) must be readonly
* *

View File

@ -0,0 +1,35 @@
import type { GoToPageEvent } from '../Events/GoToPageEvent';
import type { OpenTabEvent } from '../Events/OpenTabEvent';
import { IframeApiContribution, sendToWorkadventure } from './IframeApiContribution';
class WorkadventureNavigationCommands extends IframeApiContribution<WorkadventureNavigationCommands> {
readonly subObjectIdentifier = "nav"
readonly addMethodsAtRoot = true
callbacks = []
openTab(url: string): void {
sendToWorkadventure({
"type": 'openTab',
"data": {
url
} as OpenTabEvent
});
}
goToPage(url: string): void {
sendToWorkadventure({
"type": 'goToPage',
"data": {
url
} as GoToPageEvent
});
}
}
export default new WorkadventureNavigationCommands();

View File

@ -0,0 +1,22 @@
import { IframeApiContribution, sendToWorkadventure } from './IframeApiContribution';
class WorkadventureNavigationCommands extends IframeApiContribution<WorkadventureNavigationCommands> {
readonly subObjectIdentifier = "player"
readonly addMethodsAtRoot = true
callbacks = []
disablePlayerControls(): void {
sendToWorkadventure({ 'type': 'disablePlayerControls', data: null });
}
restorePlayerControls(): void {
sendToWorkadventure({ 'type': 'restorePlayerControls', data: null });
}
}
export default new WorkadventureNavigationCommands();

View File

@ -0,0 +1,59 @@
import type { LoadSoundEvent } from '../Events/LoadSoundEvent';
import type { PlaySoundEvent } from '../Events/PlaySoundEvent';
import type { StopSoundEvent } from '../Events/StopSoundEvent';
import { IframeApiContribution, sendToWorkadventure } from './IframeApiContribution';
import SoundConfig = Phaser.Types.Sound.SoundConfig;
export class Sound {
constructor(private url: string) {
sendToWorkadventure({
"type": 'loadSound',
"data": {
url: this.url,
} as LoadSoundEvent
});
}
public play(config: SoundConfig) {
sendToWorkadventure({
"type": 'playSound',
"data": {
url: this.url,
config
} as PlaySoundEvent
});
return this.url;
}
public stop() {
sendToWorkadventure({
"type": 'stopSound',
"data": {
url: this.url,
} as StopSoundEvent
});
return this.url;
}
}
class WorkadventureSoundCommands extends IframeApiContribution<WorkadventureSoundCommands> {
readonly subObjectIdentifier = "sound"
readonly addMethodsAtRoot = true
callbacks = []
loadSound(url: string): Sound {
return new Sound(url);
}
}
export default new WorkadventureSoundCommands();

View File

@ -1,6 +1,6 @@
import { EnterLeaveEvent, isEnterLeaveEvent } from '../Events/EnterLeaveEvent'
import { apiCallback as apiCallback, IframeApiContribution } from './IframeApiContribution'
import { Subject } from "rxjs"; import { Subject } from "rxjs";
import { EnterLeaveEvent, isEnterLeaveEvent } from '../Events/EnterLeaveEvent';
import { apiCallback as apiCallback, IframeApiContribution } from './IframeApiContribution';
const enterStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>(); const enterStreams: Map<string, Subject<EnterLeaveEvent>> = new Map<string, Subject<EnterLeaveEvent>>();

View File

@ -1,13 +1,5 @@
import { Subject } from "rxjs";
import type { GoToPageEvent } from "./Api/Events/GoToPageEvent";
import { IframeResponseEventMap, isIframeResponseEventWrapper } from "./Api/Events/IframeEvent"; import { IframeResponseEventMap, isIframeResponseEventWrapper } from "./Api/Events/IframeEvent";
import type { LoadSoundEvent } from "./Api/Events/LoadSoundEvent";
import type { OpenCoWebSiteEvent } from "./Api/Events/OpenCoWebSiteEvent";
import type { OpenTabEvent } from "./Api/Events/OpenTabEvent";
import type { PlaySoundEvent } from "./Api/Events/PlaySoundEvent";
import type { StopSoundEvent } from "./Api/Events/StopSoundEvent";
import { isUserInputChatEvent, UserInputChatEvent } from "./Api/Events/UserInputChatEvent";
import SoundConfig = Phaser.Types.Sound.SoundConfig;
export const registeredCallbacks: { [K in keyof IframeResponseEventMap]?: { export const registeredCallbacks: { [K in keyof IframeResponseEventMap]?: {
typeChecker: Function typeChecker: Function
callback: Function callback: Function
@ -16,9 +8,13 @@ export const registeredCallbacks: { [K in keyof IframeResponseEventMap]?: {
const importType = Promise.all([ const importType = Promise.all([
import("./Api/iframe/popup"), import("./Api/iframe/popup"),
import("./Api/iframe/chatmessage"), import("./Api/iframe/chatmessage"),
import("./Api/iframe/zone-events") import("./Api/iframe/Sound"),
import("./Api/iframe/zone-events"),
import("./Api/iframe/Navigation"),
import("./Api/iframe/CoWebsite")
]) ])
type PromiseReturnType<P> = P extends Promise<infer T> ? T : P type PromiseReturnType<P> = P extends Promise<infer T> ? T : P
type WorkadventureCommandClasses = PromiseReturnType<typeof importType>[number]["default"]; type WorkadventureCommandClasses = PromiseReturnType<typeof importType>[number]["default"];
@ -50,20 +46,12 @@ type WorkAdventureApiFiles = {
} & SubObjectTypes } & SubObjectTypes
export interface WorkAdventureApi extends WorkAdventureApiFiles { export interface WorkAdventureApi extends WorkAdventureApiFiles {
openTab(url: string): void;
goToPage(url: string): void;
openCoWebSite(url: string): void;
closeCoWebSite(): void;
disablePlayerControls(): void; disablePlayerControls(): void;
restorePlayerControls(): void; restorePlayerControls(): void;
displayBubble(): void; displayBubble(): void;
removeBubble(): void; removeBubble(): void;
loadSound(url: string): Sound;
} }
declare global { declare global {
interface Window { interface Window {
@ -72,55 +60,9 @@ declare global {
let WA: WorkAdventureApi let WA: WorkAdventureApi
} }
const userInputChatStream: Subject<UserInputChatEvent> = new Subject();
export class Sound {
constructor(private url: string) {
window.parent.postMessage({
"type": 'loadSound',
"data": {
url: this.url,
} as LoadSoundEvent
}, '*');
}
public play(config: SoundConfig) {
window.parent.postMessage({
"type": 'playSound',
"data": {
url: this.url,
config
} as PlaySoundEvent
}, '*');
return this.url;
}
public stop() {
window.parent.postMessage({
"type": 'stopSound',
"data": {
url: this.url,
} as StopSoundEvent
}, '*');
return this.url;
}
}
window.WA = { window.WA = {
disablePlayerControls(): void {
window.parent.postMessage({ 'type': 'disablePlayerControls' }, '*');
},
restorePlayerControls(): void {
window.parent.postMessage({ 'type': 'restorePlayerControls' }, '*');
},
displayBubble(): void { displayBubble(): void {
window.parent.postMessage({ 'type': 'displayBubble' }, '*'); window.parent.postMessage({ 'type': 'displayBubble' }, '*');
@ -130,42 +72,7 @@ window.WA = {
window.parent.postMessage({ 'type': 'removeBubble' }, '*'); window.parent.postMessage({ 'type': 'removeBubble' }, '*');
}, },
openTab(url: string): void {
window.parent.postMessage({
"type": 'openTab',
"data": {
url
} as OpenTabEvent
}, '*');
},
loadSound(url: string): Sound {
return new Sound(url);
},
goToPage(url: string): void {
window.parent.postMessage({
"type": 'goToPage',
"data": {
url
} as GoToPageEvent
}, '*');
},
openCoWebSite(url: string): void {
window.parent.postMessage({
"type": 'openCoWebSite',
"data": {
url
} as OpenCoWebSiteEvent
}, '*');
},
closeCoWebSite(): void {
window.parent.postMessage({
"type": 'closeCoWebSite'
}, '*');
},
...({} as WorkAdventureApiFiles), ...({} as WorkAdventureApiFiles),
} }
@ -173,18 +80,16 @@ window.addEventListener('message', message => {
if (message.source !== window.parent) { if (message.source !== window.parent) {
return; // Skip message in this event listener return; // Skip message in this event listener
} }
const payload = message.data; const payload = message.data;
console.debug(payload); console.debug(payload);
if (isIframeResponseEventWrapper(payload)) { if (isIframeResponseEventWrapper(payload)) {
const payloadData = payload.data; const payloadData = payload.data;
if (payload.type === 'userInputChat' && isUserInputChatEvent(payloadData)) { if (registeredCallbacks[payload.type] && registeredCallbacks[payload.type]?.typeChecker(payloadData)) {
userInputChatStream.next(payloadData); registeredCallbacks[payload.type]?.callback(payloadData)
return
} }
} }
// ... // ...