Changeset - c4427fd59306
[Not reviewed]
default
0 2 1
drewp@bigasterisk.com - 3 years ago 2022-06-03 06:24:09
drewp@bigasterisk.com
port some of ascoltami into lit
3 files changed with 174 insertions and 116 deletions:
0 comments (0 inline, 0 general)
light9/ascoltami/Light9AscoltamiUi.ts
Show inline comments
 
new file 100644
 
import debug from "debug";
 
import { html, LitElement } from "lit";
 
import { customElement, property } from "lit/decorators.js";
 
import { NamedNode } from "n3";
 
import { getTopGraph } from "../web/RdfdbSyncedGraph";
 
import { SyncedGraph } from "../web/SyncedGraph";
 
export { RdfdbSyncedGraph } from "../web/RdfdbSyncedGraph";
 
export { Light9TimelineAudio } from "../web/light9-timeline-audio";
 
import { classMap } from "lit/directives/class-map.js";
 

	
 
debug.enable("*");
 
const log = debug("asco");
 

	
 
function byId(id: string): HTMLElement {
 
  return document.getElementById(id)!;
 
}
 
async function postJson(url: string, jsBody: Object) {
 
  return fetch(url, {
 
    method: "POST",
 
    headers: { "Content-Type": "applcation/json" },
 
    body: JSON.stringify(jsBody),
 
  });
 
}
 
@customElement("light9-ascoltami-ui")
 
export class Light9AscoltamiUi extends LitElement {
 
  graph!: SyncedGraph;
 
  times!: { intro: number; post: number };
 
  currentDuration: number = 0;
 
  @property() nextText: string = "";
 
  @property() isPlaying: boolean = false;
 
  render() {
 
    return html`<rdfdb-synced-graph></rdfdb-synced-graph>
 

	
 
      <link rel="stylesheet" href="./style.css" />
 

	
 
      <h1>ascoltami <a href="metrics">[metrics]</a></h1>
 

	
 
      <div class="commands">
 
        <button id="cmd-stop" @click=${this.onCmdStop} class="playMode ${classMap({ active: !this.isPlaying })}">
 
          <strong>Stop</strong>
 
          <div class="key">s</div>
 
        </button>
 
        <button id="cmd-play" @click=${this.onCmdPlay} class="playMode ${classMap({ active: this.isPlaying })}">
 
          <strong>Play</strong>
 
          <div class="key">p</div>
 
        </button>
 
        <button id="cmd-intro" @click=${this.onCmdIntro}>
 
          <strong>Skip intro</strong>
 
          <div class="key">i</div>
 
        </button>
 
        <button id="cmd-post" @click=${this.onCmdPost}>
 
          <strong>Skip to Post</strong>
 
          <div class="key">t</div>
 
        </button>
 
        <button id="cmd-go" @click=${this.onCmdGo}>
 
          <strong>Go</strong>
 
          <div class="key">g</div>
 
          <div id="next">${this.nextText}</div>
 
        </button>
 
      </div> `;
 
  }
 

	
 
  onCmdStop(ev?: MouseEvent): void {
 
    postJson("api/time", { pause: true });
 
  }
 
  onCmdPlay(ev?: MouseEvent): void {
 
    postJson("api/time", { resume: true });
 
  }
 
  onCmdIntro(ev?: MouseEvent): void {
 
    postJson("api/time", { t: this.times.intro, resume: true });
 
  }
 
  onCmdPost(ev?: MouseEvent): void {
 
    postJson("api/time", { t: this.currentDuration - this.times.post, resume: true });
 
  }
 
  onCmdGo(ev?: MouseEvent): void {
 
    postJson("api/go", {});
 
  }
 

	
 
  bindKeys() {
 
    document.addEventListener("keypress", (ev) => {
 
      if (ev.which == 115) {
 
        this.onCmdStop();
 
        return false;
 
      }
 
      if (ev.which == 112) {
 
        this.onCmdPlay();
 
        return false;
 
      }
 
      if (ev.which == 105) {
 
        this.onCmdIntro();
 
        return false;
 
      }
 
      if (ev.which == 116) {
 
        this.onCmdPost();
 
        return false;
 
      }
 

	
 
      if (ev.key == "g") {
 
        this.onCmdGo();
 
        return false;
 
      }
 
      return true;
 
    });
 
  }
 

	
 
  currentDurationChanged(newDuration: number): void {
 
    this.currentDuration = newDuration;
 
  }
 

	
 
  async musicSetup() {
 
    // shoveled over from the vanillajs version
 
    const config = await (await fetch("api/config")).json();
 
    this.times = config.times;
 
    document.title = document.title.replace("{{host}}", config.host);
 
    const h1 = document.querySelector("h1")!;
 
    h1.innerText = h1.innerText.replace("{{host}}", config.host);
 

	
 
    byId("nav").innerText = navigator.userAgent;
 
    var updateFreq = navigator.userAgent.indexOf("Linux") != -1 ? 10 : 2;
 
    if (navigator.userAgent.match(/Windows NT/)) {
 
      // helper laptop
 
      updateFreq = 10;
 
    }
 
    byId("updateReq").innerText = "" + updateFreq;
 

	
 
    (window as any).finishOldStyleSetup(
 
      this.times,
 
      updateFreq,
 
      this.currentDurationChanged.bind(this),
 
      (t: string) => {
 
        this.nextText = t;
 
      },
 
      (is: boolean) => {
 
        this.isPlaying = is;
 
      }
 
    );
 
  }
 

	
 
  constructor() {
 
    super();
 
    this.bindKeys();
 
    //   byId("cmd-stop").addEventListener("click", (ev: Event) =>
 
    // );
 

	
 
    getTopGraph().then((g) => {
 
      this.graph = g;
 
      this.musicSetup(); // async
 
    });
 
  }
 
}
light9/ascoltami/index.html
Show inline comments
 
@@ -40,33 +40,15 @@
 
        <div id="timeSlider"></div>
 
      </div>
 
    </div>
 
    <div class="commands">
 
      <button id="cmd-stop" class="playMode">
 
        <strong>Stop</strong>
 
        <div class="key">s</div>
 
      </button>
 
      <button id="cmd-play" class="playMode">
 
        <strong>Play</strong>
 
        <div class="key">p</div>
 
      </button>
 
      <button id="cmd-intro">
 
        <strong>Skip intro</strong>
 
        <div class="key">i</div>
 
      </button>
 
      <button id="cmd-post">
 
        <strong>Skip to Post</strong>
 
        <div class="key">t</div>
 
      </button>
 
      <button id="cmd-go">
 
        <strong>Go</strong>
 
        <div class="key">g</div>
 
        <div id="next"></div>
 
      </button>
 
    </div>
 

	
 
    <hr />
 
    new ui is here
 
    <light9-ascoltami-ui></light9-ascoltami-ui>
 
    <hr />
 

	
 
    <p>Running on <span id="nav"></span></p>
 
    <p><a href="">reload</a></p>
 

	
 
    <script type="module" src="main.ts"></script>
 
    <script type="module" src="../ascoltami/main.ts"></script>
 
  </body>
 
</html>
light9/ascoltami/main.ts
Show inline comments
 
@@ -2,24 +2,15 @@ function byId(id: string): HTMLElement {
 
  return document.getElementById(id)!;
 
}
 

	
 
async function onLoad() {
 
  const config = await (await fetch("api/config")).json();
 
  const times = config.times;
 
  document.title = document.title.replace("{{host}}", config.host);
 
  const h1 = document.querySelector("h1")!;
 
  h1.innerText = h1.innerText.replace("{{host}}", config.host);
 

	
 
  byId("nav").innerText = navigator.userAgent;
 
  var updateFreq = navigator.userAgent.indexOf("Linux") != -1 ? 10 : 2;
 
  if (navigator.userAgent.match(/Windows NT/)) {
 
    // helper laptop
 
    updateFreq = 10;
 
  }
 
  byId("updateReq").innerText = "" + updateFreq;
 

	
 
  let currentDuration = 0;
 
(window as any).finishOldStyleSetup = async (
 
  times: { intro: number; post: number },
 
  updateFreq: number,
 
  currentDurationChanged: (d: number) => void,
 
  setNextText: (t: string) => void,
 
  setIsPlaying: (is: boolean) => void
 
) => {
 
  let currentHighlightedSong = "";
 
  let lastPlaying = false;
 
  // let lastPlaying = false;
 

	
 
  async function updateCurrent() {
 
    const data = await (await fetch("api/time")).json();
 
@@ -29,27 +20,16 @@ async function onLoad() {
 
    }
 
    byId("currentTime").innerText = data.t.toFixed(1);
 
    byId("leftTime").innerText = (data.duration - data.t).toFixed(1);
 
    byId("leftAutoStopTime").innerText = Math.max(
 
      0,
 
      data.duration - times.post - data.t
 
    ).toFixed(1);
 
    byId("leftAutoStopTime").innerText = Math.max(0, data.duration - times.post - data.t).toFixed(1);
 
    byId("states").innerText = JSON.stringify(data.state);
 
    currentDuration = data.duration;
 
    currentDurationChanged(data.duration);
 
    //   document.querySelector("#timeSlider").slider({ value: data.t, max: data.duration });
 
    if (data.playing != lastPlaying) {
 
      document
 
        .querySelectorAll(".playMode")
 
        .forEach((e: Element) => e.classList.remove("active"));
 
      byId(data.playing ? "cmd-play" : "cmd-stop").classList.add("active");
 
      lastPlaying = data.playing;
 
    }
 
    byId("next").innerText = data.next;
 
    setIsPlaying(data.playing);
 
    setNextText(data.next);
 
  }
 

	
 
  function showCurrentSong(uri: string) {
 
    document
 
      .querySelectorAll(".songs div")
 
      .forEach((row: Element, i: number) => {
 
    document.querySelectorAll(".songs div").forEach((row: Element, i: number) => {
 
        if (row.querySelector("button")!.dataset.uri == uri) {
 
          row.classList.add("currentSong");
 
        } else {
 
@@ -60,7 +40,7 @@ async function onLoad() {
 
  }
 

	
 
  const data = await (await fetch("api/songs")).json();
 
  data.songs.forEach((song) => {
 
  data.songs.forEach((song: { uri: string; label: string }) => {
 
    const button = document.createElement("button");
 
    // link is just for dragging, not clicking
 
    const link = document.createElement("a");
 
@@ -86,58 +66,9 @@ async function onLoad() {
 
    });
 
    const dv = document.createElement("div");
 
    dv.appendChild(button);
 
    document.querySelector(".songs").appendChild(dv);
 
    document.querySelector(".songs")!.appendChild(dv);
 
  });
 

	
 
  document.addEventListener("keypress", (ev) => {
 
    if (ev.which == 115) {
 
      byId("cmd-stop").click();
 
      return false;
 
    }
 
    if (ev.which == 112) {
 
      byId("cmd-play").click();
 
      return false;
 
    }
 
    if (ev.which == 105) {
 
      byId("cmd-intro").click();
 
      return false;
 
    }
 
    if (ev.which == 116) {
 
      byId("cmd-post").click();
 
      return false;
 
    }
 

	
 
    if (ev.key == "g") {
 
      byId("cmd-go").click();
 
      return false;
 
    }
 
    return true;
 
  });
 

	
 
  async function postJson(url: string, jsBody: Object) {
 
    return fetch(url, {
 
      method: "POST",
 
      headers: { "Content-Type": "applcation/json" },
 
      body: JSON.stringify(jsBody),
 
    });
 
  }
 

	
 
  byId("cmd-stop").addEventListener("click", (ev: Event) =>
 
    postJson("api/time", { pause: true })
 
  );
 
  byId("cmd-play").addEventListener("click", (ev: Event) =>
 
    postJson("api/time", { resume: true })
 
  );
 
  byId("cmd-intro").addEventListener("click", (ev: Event) =>
 
    postJson("api/time", { t: times.intro, resume: true })
 
  );
 
  byId("cmd-post").addEventListener("click", (ev: Event) =>
 
    postJson("api/time", { t: currentDuration - times.post, resume: true })
 
  );
 
  byId("cmd-go").addEventListener("click", (ev: Event) =>
 
    postJson("api/go", {})
 
  );
 

	
 
  //   var pendingSlide = false;
 
  //   $("#timeSlider").slider({
 
  //     step: 0.01,
 
@@ -163,15 +94,11 @@ async function onLoad() {
 
    if (recentUpdates.length > 1) {
 
      if (+new Date() - recentUpdates[recentUpdates.length - 1] > 1000) {
 
        byId("updateActual").innerText = "(stalled)";
 
        document
 
          .querySelectorAll(".dimStalled")
 
          .forEach((el) => el.classList.add("stalled"));
 
        document.querySelectorAll(".dimStalled").forEach((el) => el.classList.add("stalled"));
 
        return;
 
      }
 

	
 
      var avgMs =
 
        (recentUpdates[recentUpdates.length - 1] - recentUpdates[0]) /
 
        (recentUpdates.length - 1);
 
      var avgMs = (recentUpdates[recentUpdates.length - 1] - recentUpdates[0]) / (recentUpdates.length - 1);
 
      byId("updateActual").innerText = "" + Math.round(1000 / avgMs);
 
    }
 
  }
 
@@ -188,5 +115,4 @@ async function onLoad() {
 
    whenDone();
 
  }
 
  updateLoop();
 
}
 
onLoad();
 
};
0 comments (0 inline, 0 general)