WIP Media Library dialog

This commit is contained in:
Danny McGee
2024-03-08 17:40:11 -05:00
parent 0642c1c370
commit f347ac783f
4 changed files with 160 additions and 34 deletions
+12 -34
View File
@@ -8,17 +8,17 @@ import {
} from "@storyteller/studio";
import { ButtonElement } from "@storyteller/studio-ui/button";
import {
MediaFileType,
SceneHierarchyElement,
StorytellerApi,
StudioURLParams,
} from "@storyteller/studio-web";
import { assert, match } from "@storyteller/utility";
import { match } from "@storyteller/utility";
import { LitElement, html, nothing } from "lit";
import { customElement, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { createRef, ref } from "lit/directives/ref.js";
import { styleMap } from "lit/directives/style-map.js";
import { MediaLibraryElement } from "./media-library.element";
import "@storyteller/studio-ui/button";
import "@storyteller/studio-ui/icon";
@@ -37,6 +37,7 @@ import "./anim-editor.element";
import "./help.element";
import "./blocking.element";
import "./media-library.element";
import "./app.element.scss";
@@ -58,6 +59,7 @@ export class AppElement extends LitElement {
#enableAnimTimeline = false; // TODO
#addToSceneButtonRef = createRef<ButtonElement>();
#mediaLibraryRef = createRef<MediaLibraryElement>();
#inspectorRef = createRef<HTMLDivElement>();
#hierarchyRef = createRef<SceneHierarchyElement>();
@@ -67,37 +69,6 @@ export class AppElement extends LitElement {
return this;
}
// TODO
override async connectedCallback(): Promise<void> {
super.connectedCallback();
try {
const session = await this.api.session();
console.log("session:", session);
if (!session.logged_in)
return; // TODO: Prompt for login?
assert(session.user?.username != null);
const mediaFilesResult = await this.api.listMediaFiles({
username: session.user.username,
filterMediaType: [
MediaFileType.Bvh,
MediaFileType.Fbx,
MediaFileType.Glb,
MediaFileType.Gltf,
MediaFileType.Mocap,
MediaFileType.ScnRon,
],
});
console.log(mediaFilesResult);
}
catch (err) {
console.error(err);
}
}
@on("scene-saved")
async onSceneSaved({ detail: scene }: SceneSavedEvent): Promise<void> {
try {
@@ -220,7 +191,14 @@ export class AppElement extends LitElement {
<!-- Studio-mode-only elements -->
${this.#params.mode === StudioMode.Editor ? html`
<sts-add-to-scene-menu .trigger=${this.#addToSceneButtonRef}></sts-add-to-scene-menu>
<sts-add-to-scene-menu
.trigger=${this.#addToSceneButtonRef}
@open-media-library=${() => {
this.#mediaLibraryRef.value?.open();
}}
></sts-add-to-scene-menu>
<sts-media-library ${ref(this.#mediaLibraryRef)}></sts-media-library>
<sts-transform-toolbar class="v-start h-center"></sts-transform-toolbar>
${this.showInspector ? html`
@@ -0,0 +1,14 @@
:host {
display: block;
min-width: 512px;
min-height: 256px;
max-width: 80%;
max-height: 80%;
padding: 1rem;
overflow: auto;
background: #0006;
color: #FFFC;
backdrop-filter: blur(16px);
border-radius: 0.5rem;
}
@@ -0,0 +1,131 @@
import { inject, on } from "@storyteller/framework";
import {
OVERLAY_PROVIDER,
type OverlayHandle,
type OverlayProvider,
} from "@storyteller/studio-ui/overlay-provider";
import {
type MediaFile,
MediaFileType,
StorytellerApi,
} from "@storyteller/studio-web";
import { LitElement, unsafeCSS, type PropertyValues, html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { createRef, ref } from "lit/directives/ref.js";
import { until } from "lit/directives/until.js";
import dialogStyles from "./media-library.element.scss?inline";
@customElement("sts-media-library")
export class MediaLibraryElement extends LitElement {
@property({ attribute: false })
trigger = createRef<HTMLElement>();
@inject(OVERLAY_PROVIDER)
overlay!: OverlayProvider;
#overlayHandle?: WeakRef<OverlayHandle>;
#dialogRef = createRef<MediaLibraryDialogElement>();
open(): void {
this.#overlayHandle = this.overlay.attach(this, html`
<sts-media-library-dialog
${ref(this.#dialogRef)}
@close=${() => this.close()}
></sts-media-library-dialog>
`, {
containerStyles: {
display: "flex",
alignItems: "center",
justifyContent: "center",
},
});
}
close(): void {
if (this.#overlayHandle)
this.overlay.detach(this.#overlayHandle);
}
protected override updated(changes: PropertyValues<this>): void {
if (changes.has("trigger")) {
const prevTrigger = changes.get("trigger");
if (prevTrigger?.value) {
prevTrigger.value.removeEventListener("click", this.onTriggerClick);
}
const trigger = this.trigger.value;
if (!trigger) return;
trigger.addEventListener("click", this.onTriggerClick);
}
super.updated(changes);
}
override disconnectedCallback(): void {
this.trigger.value?.removeEventListener("click", this.onTriggerClick);
super.disconnectedCallback();
}
onTriggerClick = (): void => {
this.open();
}
}
@customElement("sts-media-library-dialog")
export class MediaLibraryDialogElement extends LitElement {
static override styles = unsafeCSS(dialogStyles);
@property({ reflect: true })
override role = "dialog";
@state()
mediaFiles?: Promise<MediaFile[]>;
@inject(StorytellerApi)
_api!: StorytellerApi;
override async connectedCallback(): Promise<void> {
this.mediaFiles = this._api
.session()
.then(session => {
if (!session.logged_in || !session.user?.username)
return Promise.reject(new Error("Not logged in"));
return this._api.listMediaFiles({
username: session.user.username,
filterMediaType: [
MediaFileType.Bvh,
MediaFileType.Glb,
MediaFileType.Gltf,
MediaFileType.ScnRon,
],
});
})
.then(result => Promise.all(
result.results.map(({ token }) => this._api.mediaFile(token))
))
.catch(err => {
console.error(err);
return [];
});
super.connectedCallback();
}
@on("window:click")
onWindowClick(event: PointerEvent): void {
if (!event.composedPath().includes(this))
this.dispatchEvent(new CustomEvent("close"));
}
protected override render = () => html`
${until(
this.mediaFiles?.then(files => html`
<pre>${JSON.stringify(files, null, " ")}</pre>
`),
html`<span>Loading...</span>`
)}
`;
}
@@ -60,6 +60,9 @@ export class AddToSceneMenuElement extends LitElement {
<sts-button
role="menuitem"
icon="photo-film-music"
@click=${() => {
this.dispatchEvent(new CustomEvent("open-media-library"));
}}
>
Media library...
</sts-button>