diff src/VideoPage.ts @ 45:df51269bcef4

fix back/fwd nav and player loading
author drewp@bigasterisk.com
date Fri, 06 Dec 2024 01:02:33 -0800
parents 1d2c65d260d1
children 882d0bb0f801
line wrap: on
line diff
--- a/src/VideoPage.ts	Fri Dec 06 01:01:05 2024 -0800
+++ b/src/VideoPage.ts	Fri Dec 06 01:02:33 2024 -0800
@@ -1,12 +1,13 @@
+import { Router } from "@lit-labs/router";
 import { LitElement, PropertyValues, TemplateResult, css, html, unsafeCSS } from "lit";
-import { customElement, property } from "lit/decorators.js";
+import { customElement, property, queryAsync } from "lit/decorators.js";
 import { PagePlayer, ShakaVideoElement } from "./PagePlayer";
 import maincss from "./main.css?inline";
 export { SlProgressBar } from "@shoelace-style/shoelace";
 export { PagePlayer } from "./PagePlayer";
+export { VBreadcrumbs } from "./VBreadcrumbs";
 export { VideoSection } from "./VideoSection";
-import { Routes, Router } from "@lit-labs/router";
-export { VBreadcrumbs } from "./VBreadcrumbs";
+
 interface VideoFile {
   webRelPath: string;
   webDataPath: string;
@@ -18,9 +19,12 @@
   path: string;
 }
 
-interface VideoListings {
+interface PageData {
+  webDirRelPath: string;
+  dirLabel: string;
   videos: VideoFile[];
   subdirs: Subdir[];
+  autoplay: VideoFile | null;
 }
 
 function subdirQuery(subdir: string): string {
@@ -29,39 +33,24 @@
 
 class route {
   path = "/video/*";
-  videoListings: VideoListings | null = null;
-  showVid: string | null = null;
-  dirName?: string;
-
-  link(wrp: string): string {
-    return "/video/" + wrp;
-  }
+  pageData: PageData | null = null;
 
   async enter(params: { [key: string]: string | undefined }): Promise<boolean> {
-    const webRelPath = "/" + params[0]!;
-    this.dirName = webRelPath.replace(/.*\/([^/]+)/, "$1");
+    const webRelPath = "/" + params[0]!; // could be /a/dir/ or /a/video
+    console.log("enter", webRelPath);
     const resp = await fetch("/video/api/videos?" + subdirQuery(webRelPath));
     if (resp.status == 404) {
       return false;
     }
-    this.videoListings = await resp.json();
-
-    if (webRelPath.endsWith("/")) {
-      this.showVid = null;
-    } else {
-      this.showVid = webRelPath;
-    }
+    this.pageData = await resp.json();
+    if (!this.pageData) return false;
 
     return true;
   }
 
   render(p: { [key: string]: string | undefined }) {
-    return html`<video-page2
-      .link=${this.link.bind(this)}
-      .showVid=${this.showVid}
-      .videoListings=${this.videoListings}
-      .dirName=${this.dirName}
-    ></video-page2>`;
+    console.log("render", this.pageData);
+    return html`<video-page2 .pageData=${this.pageData}></video-page2>`;
   }
 }
 
@@ -70,13 +59,23 @@
   static styles = [unsafeCSS(maincss)];
   private _router = new Router(this, [new route()], {});
 
+  constructor() {
+    super();
+    window.rr = this._router;
+  }
+
   render() {
-    const requestedPath = "/" + this._router.params[0];
-
+    const pd = (this._router.routes[0] as route).pageData;
+    if (!pd) {
+      console.log("no page data", this._router.routes);
+      return html`loading...`;
+      throw new Error("no page data");
+    }
+    console.log("yes page data", pd);
     return html`
       <header>
-        <img src=${this._router.link("/video/logo1.png")} title="JelloBello" />
-        <v-breadcrumbs .link=${this._router.link} dirPath=${requestedPath}></v-breadcrumbs>
+        <img src="/video/logo1.png" title="JelloBello" />
+        <v-breadcrumbs dirPath=${pd.webDirRelPath}></v-breadcrumbs>
       </header>
       <main>${this._router.outlet()}</main>
       <footer>
@@ -89,29 +88,37 @@
 
 @customElement("video-page2")
 export class VideoPage2 extends LitElement {
-  @property() showVid?: string;
-  @property() videoListings?: VideoListings;
-  @property() link!: (s: string) => string;
-  @property() dirName?: string;
+  @property() pageData?: PageData;
 
   protected firstUpdated(_changedProperties: PropertyValues): void {
     document.addEventListener("keydown", (e) => {
       if (e.key == "Escape") {
-        this.closePlayer();
+        this.gotoDirListingPage();
       }
     });
   }
 
-  protected update(changedProperties: PropertyValues<this>): void {
-    const resp = changedProperties.has("videoListings");
-    if (resp) {
-      // if (this.showVid) {
-      //   this.openPlayer();
-      // } else {
-      //   this.closePlayer();
-      // }
+  async connectedCallback() {
+    super.connectedCallback();
+    if (this.pageData?.autoplay) {
+      //this.playVideo({ detail: { manifest: this.pageData.autoplay.webDataPath } } as CustomEvent);
+      console.log("we're a player page now", this.pageData.autoplay);
+      this.startPlayer(this.pageData.autoplay);
+      // this might not autoplay
+    } else {
+      this.closePlayer();
     }
+  }
+  protected update(changedProperties: PropertyValues): void {
     super.update(changedProperties);
+    if (changedProperties.has("pageData")) {
+      if (this.pageData?.autoplay) {
+        this.startPlayer(this.pageData.autoplay);
+      } else {
+         this.closePlayer();
+      }
+    }
+    console.log("updated", this.pageData?.autoplay);
   }
 
   static styles = [
@@ -149,7 +156,7 @@
         display: inline-block;
         width: 300px;
         margin: 5px;
-        border-radius: 2px;
+        border-radius: 5px;
       }
 
       .subdir:after {
@@ -166,37 +173,38 @@
     `,
   ];
 
-  thumbSrc(v: VideoFile) {
-    return "/video/api/thumbnail?webRelPath=" + encodeURIComponent(v.webRelPath);
+  thumbSrc(vf: VideoFile) {
+    return "/video/api/thumbnail?webRelPath=" + encodeURIComponent(vf.webRelPath);
   }
 
   renderSubdir(subdir: Subdir): TemplateResult {
-    return html`<a href="${this.link(subdir.path) + "/"}"><div class="subdir">${subdir.label}</div></a>`;
+    return html`<a href="/video${subdir.path}"><div class="subdir">${subdir.label}</div></a>`;
   }
 
   renderVideoListing(video: VideoFile) {
     return html`<video-section
-      @playVideo=${this.playVideo}
+      @playVideo=${this.gotoVideoPlayerPage}
+      webRelPath=${video.webRelPath}
       thumbRelPath=${this.thumbSrc(video)}
       title="${video.label}"
-      manifest="/video/files/${video.webDataPath}"
+      manifest="/video/files${video.webDataPath}"
     ></video-section>`;
   }
 
   render() {
-    if (this.videoListings == null) {
+    if (this.pageData == null) {
       return html`<div>Loading...</div>`;
     }
     const listings = [
-      html`${this.videoListings.subdirs.map((s) => this.renderSubdir(s))}`, //
-      html`${this.videoListings.videos.map((v) => this.renderVideoListing(v))}`,
+      html`${this.pageData.subdirs.map((s) => this.renderSubdir(s))}`, //
+      html`<div>${this.pageData.videos.map((v) => this.renderVideoListing(v))}</div>`,
     ];
-    const dirTitle = this.dirName ? html`<h2>${this.dirName.slice(0, -1)}</h2>` : html``;
+    const dirTitle = this.pageData.dirLabel ? html`<h2>${this.pageData.dirLabel}</h2>` : html``;
     return html`
       ${dirTitle}
       <div class="listing">${listings}</div>
 
-      <div id="scrim" @click=${this.closePlayer}></div>
+      <div id="scrim" @click=${this.gotoDirListingPage}></div>
       <page-player manifest=""></page-player>
     `;
   }
@@ -204,11 +212,20 @@
   escapeALittle(fileUri: string): string {
     return fileUri.replace("#", encodeURIComponent("#"));
   }
+  @queryAsync("page-player") pagePlayer: Promise<PagePlayer>;
 
-  playVideo(ev: CustomEvent) {
-    const player = this.shadowRoot!.querySelector("page-player")! as PagePlayer;
-
-    player.manifest = this.escapeALittle(ev.detail.manifest);
+  async gotoVideoPlayerPage(ev: CustomEvent) {
+    const player = await this.pagePlayer;
+    console.log("playing", player, ev.detail.manifest, ev.detail.webRelPath);
+    this.goto("/video" + ev.detail.webRelPath);
+  }
+  async gotoDirListingPage() {
+    this.goto("/video" + this.pageData?.webDirRelPath);
+  }
+  
+  async startPlayer(p: VideoFile) {
+    const player = await this.pagePlayer;
+    player.manifest = this.escapeALittle("/video/files" + p.webDataPath);
     const sv = player.shadowRoot!.querySelector("shaka-video")! as ShakaVideoElement;
 
     sv.src = player.manifest;
@@ -216,8 +233,18 @@
     player.size = "big";
     this.shadowRoot!.querySelector("#scrim")!.style.display = "block";
   }
-  closePlayer() {
-    const player = this.shadowRoot!.querySelector("page-player")! as PagePlayer;
+  goto(url: string) {
+    window.rr.goto(url);
+    window.history.pushState({}, "", url);
+  }
+  async closePlayer() {
+    const player = await this.pagePlayer;
+    if (player.size === "hidden") {
+      console.log("wasn't playing", player.size);
+      return;
+    }
+    // return;
+    // this.goto("/video/" + this.pageData?.webDirRelPath);
     player.size = "hidden";
 
     this.shadowRoot!.querySelector("#scrim")!.style.display = "none";