view src/VideoPage.ts @ 13:b73941c4dc0a

more wip on ingest page; shared styles
author drewp@bigasterisk.com
date Sat, 15 Apr 2023 16:11:23 -0700
parents e60be5d74c07
children ff73b95fc72f
line wrap: on
line source

import { LitElement, html, css, CSSResult, unsafeCSS } from "lit";
import { customElement, property } from "lit/decorators.js";
import { PagePlayer } from "./PagePlayer";
export { VideoSection } from "./VideoSection";
export { PagePlayer } from "./PagePlayer";
import { ShakaVideoElement } from "./PagePlayer";

import maincss from "./main.css?inline";


interface VideoFile {
  webRelPath: string;
  label: string;
  thumbRelPath: string;
}
interface Subdir {
  label: string;
  path: string;
}

function subdirQuery(subdir: string): string {
  return "subdir=" + encodeURIComponent(subdir);
}

@customElement("video-page")
export class VideoPage extends LitElement {
  videos: VideoFile[];
  subdirs: Subdir[];
  @property() pathSegs: { label: string; subdir: string }[];
  constructor() {
    super();
    this.videos = [];
    this.subdirs = [];
    this.pathSegs = [];
    this.loadVideos();
  }
  updatePathSegs(subdir: string) {
    this.pathSegs = [{ label: "TOP", subdir: "/" }];
    if (subdir != "/") {
      let acc = "";
      const segs = subdir.split("/");
      segs.splice(0, 1); // the root
      for (let seg of segs) {
        acc += "/" + seg;
        this.pathSegs.push({ label: seg, subdir: acc });
      }
    }
  }
  async loadVideos() {
    const u = new URL(location.href);
    const subdir = u.searchParams.get("subdir") || "/";
    this.updatePathSegs(subdir);
    const resp = await (await fetch("api/videos?" + subdirQuery(subdir))).json();
    this.videos = resp.videos as VideoFile[];
    this.subdirs = resp.subdirs as Subdir[];
    this.requestUpdate();
  }
  static styles = [
    unsafeCSS(maincss),
    css`
   
      .listing a {
        font-size: 20px;
        text-transform: uppercase;
        text-underline-offset: 10px;
      }
      
      .subdir {
        vertical-align: top;
        color: white;
        padding: 11px;
        display: inline-block;
        width: 300px;
        background: #4ea1bd21;
        margin: 5px;
        border-bottom-right-radius: 29px;
      }
      #scrim {
        position: absolute;
        background: #000000b5;
        inset: 0;
        display: none;
      }
    `,
  ];
  render() {
    return html`
      <div id="path-segs">${this.pathSegs.map((seg) => html`<span><a href="./?${subdirQuery(seg.subdir)}">${seg.label}</a></span>`)}</div>

      <div class="listing">
      ${this.subdirs.map((s) => html`<div class="subdir"><a href="${"./?" + subdirQuery(s.path)}">${s.label}</a></div>`)}
      ${this.videos.map(
        (v) => html`<video-section @playVideo=${this.playVideo} thumbRelPath="${v.thumbRelPath}" title="${v.label}" manifest=${v.webRelPath}></video-section>`
      )}
      </div>
      <p><a href="ingest/">Add new videos...</a></p>


      <div id="scrim" @click=${this.closePlayer}></div>
      <page-player manifest=""></page-player>
    `;
  }
  playVideo(ev: CustomEvent) {
    const player = this.shadowRoot!.querySelector("page-player")! as PagePlayer;

    player.manifest = ev.detail.manifest;
    const sv = player.shadowRoot!.querySelector("shaka-video")! as ShakaVideoElement;

    sv.src = ev.detail.manifest;
    sv.load().then(() => {
      sv.play();
    });
    player.size = "big";
    this.shadowRoot!.querySelector("#scrim")!.style.display = "block";
  }
  closePlayer() {
    const player = this.shadowRoot!.querySelector("page-player")! as PagePlayer;
    player.size = "hidden";

    this.shadowRoot!.querySelector("#scrim")!.style.display = "none";
  }
}