Files @ 4682f604b245
Branch filter:

Location: light9/web/ascoltami/Light9SongListing.ts

drewp@bigasterisk.com
dead code
import debug from "debug";
import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { NamedNode } from "n3";
import { getTopGraph } from "../RdfdbSyncedGraph";
import { show } from "../show_specific";
import { SyncedGraph } from "../SyncedGraph";
export { Light9TimelineAudio } from "../light9-timeline-audio";
export { Light9CursorCanvas } from "../Light9CursorCanvas";
export { RdfdbSyncedGraph } from "../RdfdbSyncedGraph";
export { ResourceDisplay } from "../ResourceDisplay";
const log = debug("songs");

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

class SongRow {
  constructor(public uri: NamedNode, public label: string) {}
}

@customElement("light9-song-listing")
export class Light9SongListing extends LitElement {
  static styles = [
    css`
      td {
        font-size: 18pt;
        white-space: nowrap;
        padding: 0 10px;
        background: #9b9b9b;
      }
      tr.current td {
        background: #dbf5e4;
      }
      tr td:first-child {
        box-shadow: initial;
      }
      tr.current td:first-child {
        box-shadow: inset 0px 2px 10px 0px black;
      }
      button {
        min-height: 30pt;
        min-width: 65pt;
      }
    `,
  ];
  graph!: SyncedGraph;
  @state() playingSong: NamedNode | null = null;
  @property() selectedSong: NamedNode | null = null;
  @state() songs: SongRow[] = [];
  @state() isPlaying = false;
  constructor() {
    super();
    getTopGraph().then((g) => {
      this.graph = g;
      this.graph.runHandler(this.getSongs.bind(this), "getsongs");
      this.graph.runHandler(this.playState.bind(this), "playstate");
    });
  }
  getSongs() {
    this.songs = [];
    const U = this.graph.U();
    try {
      const playlist: NamedNode = this.graph.uriValue(show, U(":playList"));

      (this.graph.items(playlist) as NamedNode[]).forEach((song: NamedNode) => {
        this.songs.push(new SongRow(song, this.graph.labelOrTail(song)));
      });
    } catch (e) {
      // likely it's startup- no graph yet
      log(e);
    }
  }
  playState() {
    const U = this.graph.U();
    try {
      this.isPlaying = this.graph.booleanValue(U(":ascoltami"), U(":playing"));
      this.playingSong = this.graph.uriValue(U(":ascoltami"), U(":song"));
    } catch (e) {
      log(e);
    }
  }
  render() {
    return html`
      <table>
        ${this.songs.map((song) => {
          const playing = this.playingSong && song.uri.equals(this.playingSong);
          const selected = this.selectedSong && song.uri.equals(this.selectedSong);
          // could use <resource-display .uri=${song} noclick></resource-display>
          return html`
            <tr class="song ${playing ? "current" : ""}" data-uri=${song.uri.value} @click=${this.clickSongRow}>
              <td>
                <a href=${song.uri.value}>
                  <span class="num">${song.label.slice(0, 2)}</span>
                  <span class="song-name">${song.label.slice(2).trim()}</span>
                </a>
              </td>
              <td>
                <button ?disabled=${this.isPlaying || (this.selectedSong != null && !selected)}>${selected ? "Deselect" : "Select"}</button>
              </td>
            </tr>
          `;
        })}
      </table>
    `;
  }
  clickSongRow(ev: MouseEvent) {
    ev.preventDefault();
    const row = (ev.target as HTMLElement).closest(".song") as HTMLElement;
    const song = new NamedNode(row.dataset.uri!);
    if (this.selectedSong && song.equals(this.selectedSong)) {
      this.selectedSong = null;
    } else {
      this.selectedSong = song;
    }
    this.dispatchEvent(new CustomEvent("selectsong", { detail: { song: this.selectedSong } }));
  }
}