mirror of
https://github.com/storytold/storyteller-bevy.git
synced 2026-10-09 00:09:55 +00:00
Communication bridge to storyteller-frontend (#74)
This PR establishes a rudimentary communication protocol between Storyteller Studio and the parent application (at fakeyou.com / storyteller.ai) via the `Window.postMessage` API. An example of how this protocol can be used from the parent application is here: https://github.com/storytold/storyteller-frontend/commit/d36e2a9e5c162233d7bd194fdbaa26199bbf6f7a
This commit is contained in:
@@ -24,6 +24,7 @@ import "@storyteller/studio-ui/toolbar";
|
||||
import "@storyteller/studio-ui/tree";
|
||||
import "@storyteller/studio-web/canvas-provider";
|
||||
import "@storyteller/studio-web/entity-inspector";
|
||||
import "@storyteller/studio-web/iframe-messaging-bridge";
|
||||
import "@storyteller/studio-web/loading";
|
||||
import "@storyteller/studio-web/scene-hierarchy";
|
||||
import "@storyteller/studio-web/studio";
|
||||
@@ -71,7 +72,21 @@ export class AppElement extends LitElement {
|
||||
headers: { "Accept": "text/plain" },
|
||||
body: formData,
|
||||
});
|
||||
console.log(response);
|
||||
|
||||
if (response.ok) {
|
||||
const resultJson: {
|
||||
success: boolean;
|
||||
media_file_token: string;
|
||||
} = await response.json();
|
||||
|
||||
if (resultJson.success) {
|
||||
this.dispatchEvent(new CustomEvent("scene-uploaded", {
|
||||
detail: resultJson.media_file_token,
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
console.error(err);
|
||||
@@ -132,6 +147,8 @@ export class AppElement extends LitElement {
|
||||
protected override render = () => html`
|
||||
<sts-canvas-provider class="app-root">
|
||||
<sts-scene-data-provider>
|
||||
<sts-iframe-messaging-bridge></sts-iframe-messaging-bridge>
|
||||
|
||||
<!-- Scene view -->
|
||||
<sts-studio
|
||||
class=${classMap({
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export * from "./lib/canvas-provider.element";
|
||||
export * from "./lib/iframe-messaging-bridge.element";
|
||||
export * from "./lib/inspector/entity-inspector.element";
|
||||
export * from "./lib/inspector/inspector.types";
|
||||
export * from "./lib/loading.element";
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
import { on } from "@storyteller/framework";
|
||||
import * as studio from "@storyteller/studio";
|
||||
import { SceneState, type SceneStateEvent } from "@storyteller/studio";
|
||||
import { LitElement, nothing } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
|
||||
const PARENT_ORIGIN_WHITELIST: readonly string[] = [
|
||||
"https://fakeyou.com",
|
||||
"https://storyteller.ai",
|
||||
"https://staging.fakeyou.com",
|
||||
"https://staging.storyteller.ai",
|
||||
"https://feature-mvp--fakeyou.netlify.app",
|
||||
"https://feature-mvp--storyteller.netlify.app",
|
||||
"http://dev.fakeyou.com:7000",
|
||||
"http://dev.fakeyou.com:7001",
|
||||
"http://dev.fakeyou.com:7002",
|
||||
"http://dev.storyteller.com:7000",
|
||||
"http://dev.storyteller.com:7001",
|
||||
"http://dev.storyteller.com:7002",
|
||||
"http://localhost:7000",
|
||||
"http://localhost:7001",
|
||||
"http://localhost:7002",
|
||||
];
|
||||
|
||||
@customElement("sts-iframe-messaging-bridge")
|
||||
export class IframeMessagingBridgeElement extends LitElement {
|
||||
#parentWindow?: Window;
|
||||
#parentOrigin?: string;
|
||||
|
||||
override connectedCallback(): void {
|
||||
if (
|
||||
window.parent
|
||||
&& window.parent !== window
|
||||
&& PARENT_ORIGIN_WHITELIST.includes(window.parent.origin)
|
||||
) {
|
||||
this.#parentWindow = window.parent;
|
||||
this.#parentOrigin = window.parent.origin;
|
||||
}
|
||||
|
||||
super.connectedCallback();
|
||||
}
|
||||
|
||||
@on("window:message")
|
||||
onParentMessage(event: MessageEvent<string>): void {
|
||||
if (!this.#parentOrigin || event.origin !== this.#parentOrigin)
|
||||
return;
|
||||
|
||||
if (event.data === "save-scene")
|
||||
studio.saveScene();
|
||||
}
|
||||
|
||||
@on("window:scene-uploaded")
|
||||
onSceneUploaded(event: CustomEvent<string>): void {
|
||||
if (!this.#parentWindow || !this.#parentOrigin)
|
||||
return;
|
||||
|
||||
this.#parentWindow.postMessage(`scene-saved:${event.detail}`, this.#parentOrigin);
|
||||
}
|
||||
|
||||
@on("window:scene-state")
|
||||
onSceneStateChange({ detail: state }: SceneStateEvent): void {
|
||||
if (!this.#parentWindow || !this.#parentOrigin)
|
||||
return;
|
||||
|
||||
if (state === SceneState.Active)
|
||||
this.#parentWindow.postMessage("studio-ready", this.#parentOrigin);
|
||||
}
|
||||
|
||||
protected override render = () => nothing;
|
||||
}
|
||||
@@ -27,6 +27,7 @@
|
||||
"@storyteller/studio-web": ["studio-web/src/index.ts"],
|
||||
"@storyteller/studio-web/canvas-provider": ["studio-web/src/lib/canvas-provider.element.ts"],
|
||||
"@storyteller/studio-web/entity-inspector": ["studio-web/src/lib/inspector/entity-inspector.element.ts"],
|
||||
"@storyteller/studio-web/iframe-messaging-bridge": ["studio-web/src/lib/iframe-messaging-bridge.element.ts"],
|
||||
"@storyteller/studio-web/loading": ["studio-web/src/lib/loading.element.ts"],
|
||||
"@storyteller/studio-web/scene-data-provider": ["studio-web/src/lib/scene-data-provider.element.ts"],
|
||||
"@storyteller/studio-web/scene-hierarchy": ["studio-web/src/lib/scene-hierarchy.element.ts"],
|
||||
|
||||
Reference in New Issue
Block a user