diff --git a/web/ascoltami/Light9AscoltamiUi.ts b/web/ascoltami/Light9AscoltamiUi.ts --- a/web/ascoltami/Light9AscoltamiUi.ts +++ b/web/ascoltami/Light9AscoltamiUi.ts @@ -1,27 +1,19 @@ import debug from "debug"; -import { css, html, LitElement } from "lit"; +import { css, html, LitElement, PropertyValues } from "lit"; import { customElement, property } from "lit/decorators.js"; -import { classMap } from "lit/directives/class-map.js"; import { NamedNode } from "n3"; -import Sylvester from "sylvester"; -import { Zoom } from "../light9-timeline-audio"; import { PlainViewState } from "../Light9CursorCanvas"; import { getTopGraph } from "../RdfdbSyncedGraph"; import { SyncedGraph } from "../SyncedGraph"; -import { TimingUpdate } from "./main"; -import { showRoot } from "../show_specific"; -export { Light9TimelineAudio } from "../light9-timeline-audio"; -export { Light9CursorCanvas } from "../Light9CursorCanvas"; +import { PlayerState } from "./PlayerState"; export { RdfdbSyncedGraph } from "../RdfdbSyncedGraph"; export { ResourceDisplay } from "../ResourceDisplay"; -const $V = Sylvester.Vector.create; +export { Light9AscoltamiTimeline } from "./Light9AscoltamiTimeline"; +export { Light9SongListing } from "./Light9SongListing"; 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", @@ -29,157 +21,154 @@ async function postJson(url: string, jsB body: JSON.stringify(jsBody), }); } + @customElement("light9-ascoltami-ui") export class Light9AscoltamiUi extends LitElement { graph!: SyncedGraph; - times!: { intro: number; post: number }; - @property() nextText: string = ""; - @property() isPlaying: boolean = false; @property() show: NamedNode | null = null; @property() song: NamedNode | null = null; @property() selectedSong: NamedNode | null = null; - @property() currentDuration: number = 0; - @property() zoom: Zoom; - @property() overviewZoom: Zoom; @property() viewState: PlainViewState | null = null; + @property() host: any; + @property() playerState: PlayerState = { duration: null, endOfSong: null, pausedSongTime: null, playing: null, song: null, wallStartTime: null }; + @property() playerTime: number = 0; static styles = [ css` :host { display: flex; flex-direction: column; } - .timeRow { - margin: 14px; - position: relative; - } - #overview { - height: 60px; - } - #zoomed { - margin-top: 40px; - height: 80px; - } - #cursor { - position: absolute; - left: 0; - top: 0; - width: 100%; - height: 100%; - } - #grow { - flex: 1 1 auto; - display: flex; - } - #grow > span { - display: flex; - position: relative; - width: 50%; + + .keyCap { + color: #ccc; + background: #525252; + display: inline-block; + border: 1px outset #b3b3b3; + padding: 2px 3px; + margin: 3px 0; + margin-left: 0.4em; + font-size: 16px; + box-shadow: 0.9px 0.9px 0px 2px #565656; + border-radius: 2px; } - #playSelected { - height: 100px; - } - #songList { - overflow-y: scroll; - position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; + + button { + min-height: 48pt; + min-width: 65pt; } - #songList .row { - width: 60%; - min-height: 40px; - text-align: left; - position: relative; - } - #songList .row:nth-child(even) { - background: #333; + + #mainRow { + display: flex; + flex-direction: row; } - #songList .row:nth-child(odd) { - background: #444; + + light9-song-listing { + flex-grow: 1; } - #songList button { - min-height: 40px; - margin-bottom: 10px; - } - #songList .row.playing { - box-shadow: 0 0 30px red; - background-color: #de5050; + + th { + text-align: right; } `, ]; - render() { - return html` + + constructor() { + super(); + getTopGraph().then((g) => { + this.graph = g; + this.graph.runHandler(this.updatePlayState.bind(this), "playstate-ui"); + }); + setInterval(this.updateT.bind(this), 100); + } + + protected async firstUpdated(_changedProperties: PropertyValues) { + this.bindKeys(); + const config = await (await fetch("/service/ascoltami/config")).json(); + document.title = document.title.replace("{{host}}", config.host); + this.host = config.host; + } - + updatePlayState() { + const U = this.graph.U(); + const asco = U(":ascoltami"); + this.playerState = { + duration: this.graph.optionalFloatValue(asco, U(":duration")), + endOfSong: this.graph.optionalBooleanValue(asco, U(":endOfSong")), + pausedSongTime: this.graph.optionalFloatValue(asco, U(":pausedSongTime")), + wallStartTime: this.graph.optionalFloatValue(asco, U(":wallStartTime")), + playing: this.graph.optionalBooleanValue(asco, U(":playing")), + song: this.graph.optionalUriValue(asco, U(":song")), + }; + this.updateT(); + } - + updateT() { + if (this.playerState.wallStartTime !== null) { + this.playerTime = Date.now() / 1000 - this.playerState.wallStartTime; + } else if (this.playerState.pausedSongTime !== null) { + this.playerTime = this.playerState.pausedSongTime; + } else { + this.playerTime = 0; + } + } + + render() { + return html` +

ascoltami on ${this.host}

-
- -
- - ${this.songList.map( - (song) => html` - - - - - ` - )} -
- -
-
-