diff light9/ascoltami/Light9AscoltamiUi.ts @ 2135:197a4ec877a7

acso relayout so only the song list scrolls
author drewp@bigasterisk.com
date Mon, 06 Jun 2022 01:15:17 +0000
parents 1dbbf0db3036
children b39f6c363163
line wrap: on
line diff
--- a/light9/ascoltami/Light9AscoltamiUi.ts	Sun Jun 05 22:55:06 2022 +0000
+++ b/light9/ascoltami/Light9AscoltamiUi.ts	Mon Jun 06 01:15:17 2022 +0000
@@ -9,7 +9,6 @@
 import { getTopGraph } from "../web/RdfdbSyncedGraph";
 import { SyncedGraph } from "../web/SyncedGraph";
 import { TimingUpdate } from "./main";
-import { ResourceDisplay } from '../web/ResourceDisplay';
 export { Light9TimelineAudio } from "../web/light9-timeline-audio";
 export { Light9CursorCanvas } from "../web/Light9CursorCanvas";
 export { RdfdbSyncedGraph } from "../web/RdfdbSyncedGraph";
@@ -37,13 +36,17 @@
   @property() isPlaying: boolean = false;
   @property() show: NamedNode | null = null;
   @property() song: NamedNode | null = null;
-  @property() requestedSong: NamedNode | null = null;
+  @property() selectedSong: NamedNode | null = null;
   @property() currentDuration: number = 0;
   @property() zoom: Zoom;
   @property() overviewZoom: Zoom;
   @property() viewState: PlainViewState | null = null;
   static styles = [
     css`
+      :host {
+        display: flex;
+        flex-direction: column;
+      }
       .timeRow {
         margin: 14px;
         position: relative;
@@ -62,52 +65,158 @@
         width: 100%;
         height: 100%;
       }
+      #grow {
+
+        flex: 1 1 auto;
+        display: flex;
+
+      }
+      #grow > span {
+        display: flex;
+        position: relative;
+        width:50%;
+      }
+      #playSelected {
+        height:100px;
+      }
+      #songList {
+        overflow-y: scroll;
+        position: absolute;
+        left:0;top:0;right:0;bottom:0;
+      }
+      #songList .row {
+        width: 60%;
+        min-height: 40px;
+        text-align: left;
+        position: relative;
+      }
+      #songList .row:nth-child(even) {background: #333;}
+      #songList .row:nth-child(odd) {background: #444;}
+      #songList button {
+        min-height: 40px;
+        margin-bottom: 10px;
+      }
+      #songList .row.playing {
+        box-shadow: 0 0 30px red;
+        background-color: #de5050;
+      }
     `,
   ];
   render() {
     return html`<rdfdb-synced-graph></rdfdb-synced-graph>
 
-<link rel="stylesheet" href="./style.css" />
-
-<!-- <h1>ascoltami <a href="metrics">[metrics]</a></h1> -->
-<!-- <div>
-  songlist:
-  ${this.songList.map((song) => html`
-  <div>song: <resource-display .uri=${song}></resource-display>
-  </div>
-  `)}
-</div> -->
-<div class="timeRow">
-  <div id="timeSlider"></div>
-  <light9-timeline-audio id="overview" .show=${this.show} .song=${this.song} .zoom=${this.overviewZoom}>
-  </light9-timeline-audio>
-  <light9-timeline-audio id="zoomed" .show=${this.show} .song=${this.song} .zoom=${this.zoom}></light9-timeline-audio>
-  <light9-cursor-canvas id="cursor" .viewState=${this.viewState}></light9-cursor-canvas>
-</div>
+      <link rel="stylesheet" href="./style.css" />
 
-<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>`;
+      <!-- <h1>ascoltami <a href="metrics">[metrics]</a></h1> -->
+      
+      <div id="grow">
+        <span>
+                <div id="songList">
+                <table>
+                  ${this.songList.map(
+                    (song) => html`
+                      <tr
+                        class="row ${classMap({
+                          playing: !!(this.song && song.equals(this.song)),
+                        })}"
+                      >
+                        <td><resource-display .uri=${song}></resource-display></td>
+                        <td>
+                          <button @click=${this.onSelectSong.bind(this, song)}>
+                            <span>Select</span>
+                          </button>
+                        </td>
+                      </tr>
+                    `
+                  )}
+                </table>
+              </div>    
+        </span><span>
+      
+        <div id="right">
+      <div>
+        Selected:
+        <resource-display .uri=${this.selectedSong}></resource-display>
+      </div>
+      <div>
+        <button id="playSelected"
+          ?disabled=${this.selectedSong === null}
+          @click=${this.onPlaySelected}
+        >
+          Play selected from start
+        </button>
+      </div>
+      </div>    
+        </span>
+      </div>
+      
+      
+      <div class="timeRow">
+        <div id="timeSlider"></div>
+        <light9-timeline-audio
+          id="overview"
+          .show=${this.show}
+          .song=${this.song}
+          .zoom=${this.overviewZoom}
+        >
+        </light9-timeline-audio>
+        <light9-timeline-audio
+          id="zoomed"
+          .show=${this.show}
+          .song=${this.song}
+          .zoom=${this.zoom}
+        ></light9-timeline-audio>
+        <light9-cursor-canvas
+          id="cursor"
+          .viewState=${this.viewState}
+        ></light9-cursor-canvas>
+      </div>
+
+      <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>`;
+  }
+
+  onSelectSong(song: NamedNode, ev: MouseEvent) {
+    if (this.selectedSong && song.equals(this.selectedSong)) {
+      this.selectedSong = null;
+    } else {
+      this.selectedSong = song;
+    }
+  }
+  async onPlaySelected(ev: Event) {
+    if (!this.selectedSong) {
+      return;
+    }
+    await fetch("api/song", { method: "POST", body: this.selectedSong.value });
   }
 
   onCmdStop(ev?: MouseEvent): void {
@@ -120,7 +229,10 @@
     postJson("api/time", { t: this.times.intro, resume: true });
   }
   onCmdPost(ev?: MouseEvent): void {
-    postJson("api/time", { t: this.currentDuration - this.times.post, resume: true });
+    postJson("api/time", {
+      t: this.currentDuration - this.times.post,
+      resume: true,
+    });
   }
   onCmdGo(ev?: MouseEvent): void {
     postJson("api/go", {});
@@ -162,9 +274,7 @@
     try {
       const h1 = document.querySelector("h1")!;
       h1.innerText = h1.innerText.replace("{{host}}", config.host);
-    } catch (e) {
-
-    }
+    } catch (e) {}
     byId("nav").innerText = navigator.userAgent;
     var updateFreq = navigator.userAgent.indexOf("Linux") != -1 ? 10 : 2;
     if (navigator.userAgent.match(/Windows NT/)) {
@@ -173,31 +283,40 @@
     }
     byId("updateReq").innerText = "" + updateFreq;
 
-    (window as any).finishOldStyleSetup(this.times, updateFreq, (data: TimingUpdate) => {
-      this.nextText = data.next;
-      this.isPlaying = data.playing;
-      this.currentDuration = data.duration;
-      this.song = new NamedNode(data.song);
-      this.overviewZoom = { duration: data.duration, t1: 0, t2: data.duration };
-      const t1 = data.t - 2,
-        t2 = data.t + 20;
-      this.zoom = { duration: data.duration, t1, t2 };
-      const timeRow = this.shadowRoot!.querySelector(".timeRow") as HTMLDivElement;
-      const w = timeRow.offsetWidth;
-      this.viewState = {
-        zoomSpec: { t1: () => t1, t2: () => t2 },
-        cursor: { t: () => data.t },
-        audioY: () => 0,
-        audioH: () => 60,
-        zoomedTimeY: () => 60,
-        zoomedTimeH: () => 40,
-        fullZoomX: (sec: number) => (sec / data.duration) * w,
-        zoomInX: (sec: number) => ((sec - t1) / (t2 - t1)) * w,
-        mouse: { pos: () => $V([0, 0]) },
-      };
-    });
+    (window as any).finishOldStyleSetup(
+      this.times,
+      updateFreq,
+      this.onOldStyleUpdate.bind(this)
+    );
   }
-  @property() songList: NamedNode[] = []
+
+  onOldStyleUpdate(data: TimingUpdate) {
+    this.nextText = data.next;
+    this.isPlaying = data.playing;
+    this.currentDuration = data.duration;
+    this.song = new NamedNode(data.song);
+    this.overviewZoom = { duration: data.duration, t1: 0, t2: data.duration };
+    const t1 = data.t - 2,
+      t2 = data.t + 20;
+    this.zoom = { duration: data.duration, t1, t2 };
+    const timeRow = this.shadowRoot!.querySelector(
+      ".timeRow"
+    ) as HTMLDivElement;
+    const w = timeRow.offsetWidth;
+    this.viewState = {
+      zoomSpec: { t1: () => t1, t2: () => t2 },
+      cursor: { t: () => data.t },
+      audioY: () => 0,
+      audioH: () => 60,
+      zoomedTimeY: () => 60,
+      zoomedTimeH: () => 40,
+      fullZoomX: (sec: number) => (sec / data.duration) * w,
+      zoomInX: (sec: number) => ((sec - t1) / (t2 - t1)) * w,
+      mouse: { pos: () => $V([0, 0]) },
+    };
+  }
+
+  @property() songList: NamedNode[] = [];
   constructor() {
     super();
     this.bindKeys();
@@ -206,21 +325,22 @@
     getTopGraph().then((g) => {
       this.graph = g;
       this.musicSetup(); // async
-      this.graph.runHandler(this.graphChanged.bind(this), 'loadsongs');
+      this.graph.runHandler(this.graphChanged.bind(this), "loadsongs");
     });
   }
   graphChanged() {
-    this.songList = []
+    this.songList = [];
     try {
-      const playList = this.graph.uriValue(//
-        this.graph.Uri('http://light9.bigasterisk.com/show/dance2022'),
-        this.graph.Uri(':playList'));
-      log(playList)
+      const playList = this.graph.uriValue(
+        //
+        this.graph.Uri("http://light9.bigasterisk.com/show/dance2022"),
+        this.graph.Uri(":playList")
+      );
+      log(playList);
       this.songList = this.graph.items(playList) as NamedNode[];
     } catch (e) {
-      log('no playlist yet')
+      log("no playlist yet");
     }
     log(this.songList.length);
-
   }
 }