182 lines
4.3 KiB
JavaScript
182 lines
4.3 KiB
JavaScript
import { LitElement, css, html } from 'lit'
|
|
import { Task } from '@lit-labs/task'
|
|
|
|
// components
|
|
import '../components/Loading.js'
|
|
import '../components/AudioCard.js'
|
|
import '../components/ModularPlayer.js'
|
|
|
|
import Router from '../api/Router.js'
|
|
|
|
class AudioView extends LitElement {
|
|
static properties = {
|
|
tracks: { type: Array },
|
|
selected: { state: true }
|
|
}
|
|
|
|
constructor() {
|
|
super()
|
|
this.tracks = []
|
|
this.selected = null
|
|
}
|
|
|
|
firstUpdated() {
|
|
this.addEventListener('select-audio', ({ detail }) => {
|
|
const div = this.shadowRoot.querySelector('mm-audio-player')
|
|
|
|
div.addEventListener('transitionend', () => {
|
|
this.selected = {
|
|
...detail
|
|
}
|
|
div.classList.remove('unloading')
|
|
})
|
|
|
|
div.classList.add('unloading')
|
|
})
|
|
|
|
this.addEventListener('next-track', () => {
|
|
this._skipTrack(1)
|
|
})
|
|
|
|
this.addEventListener('prev-track', () => {
|
|
this._skipTrack(-1)
|
|
})
|
|
}
|
|
|
|
_getAudio = new Task(
|
|
this,
|
|
async () => {
|
|
const res = await fetch(`/data${Router.route.path}.json`)
|
|
const json = await res.json()
|
|
|
|
this.tracks = json.map(i => {
|
|
i.media = `/media${Router.route.path}/${i.media}`
|
|
i.image = i.image ? `/media${Router.route.path}/${i.image}` : ''
|
|
|
|
return i
|
|
})
|
|
|
|
if (this.tracks.length > 0) {
|
|
const idx = 0
|
|
this.selected = {
|
|
...this.tracks[idx], idx,
|
|
}
|
|
}
|
|
},
|
|
() => []
|
|
)
|
|
|
|
_skipTrack(direction) {
|
|
const idx = (this.selected.idx + direction) % this.tracks.length
|
|
const detail = { ...this.tracks[idx], idx }
|
|
|
|
this.selected = { ...detail, media: `${Router.route.path}/${detail.media}` }
|
|
}
|
|
|
|
render() {
|
|
return html`
|
|
<nav class="tracks">
|
|
<div class="scroll-items">
|
|
${this._getAudio.render({
|
|
pending: () => html`<mm-loading style="--fill-color: grey"></mm-loading>`,
|
|
complete: () => html`${this.tracks.length > 0 ? this.tracks.map((t, i) => html`
|
|
<mm-acard
|
|
idx=${i}
|
|
icon=${t.album ? 'album' : 'play-circle'}
|
|
?selected=${t.title == this.selected.title && t.details == this.selected.details}
|
|
.details=${t}
|
|
></mm-acard>`) : 'No tracks added for this category' }`,
|
|
error: (err) => html`Error: ${err}`
|
|
})}
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="player ${this.selected.tracks ? '' : 'single'}">
|
|
<div>
|
|
<mm-audio-player .details=${this.selected}></mm-audio-player>
|
|
</div>
|
|
</div>
|
|
`
|
|
}
|
|
|
|
static styles = css`
|
|
:host {
|
|
flex-grow: 1;
|
|
display: grid;
|
|
grid-template-columns: 0.7fr 1fr;
|
|
gap: 0.5em;
|
|
height: 100%;
|
|
}
|
|
|
|
.tracks {
|
|
--border-radius: 0.75em;
|
|
--padding: 0.5em;
|
|
position: relative;
|
|
background: var(--neutral-400, lightgrey);
|
|
border-radius: 0 var(--border-radius) 0 0;
|
|
}
|
|
|
|
.scroll-items {
|
|
position: absolute;
|
|
inset: 0;
|
|
padding-block: 0.75em;
|
|
padding-inline-start: 0.5em;
|
|
padding-inline-end: 0.75em;
|
|
border-radius: 0 calc(var(--border-radius) * 0.5) 0 0;
|
|
display: grid;
|
|
grid-auto-flow: rows;
|
|
align-content: start;
|
|
gap: 0.75em;
|
|
overflow-x: hidden;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.player {
|
|
position: relative;
|
|
|
|
&.single > div {
|
|
background-image: url('/images/Meredith Monk (1974) Photo Lauretta Harris.jpg'), var(--green-gradient-400);
|
|
background-position: center;
|
|
background-size: 110%, 110%, cover;
|
|
background-blend-mode: soft-light, screen;
|
|
}
|
|
|
|
> div {
|
|
position: absolute;
|
|
inset: 0;
|
|
border-radius: 0.75em 0 0 0.75em;
|
|
background: var(--green-gradient-400, lightgrey);
|
|
margin-block-end: 1em;
|
|
overflow: hidden;
|
|
|
|
.bg-img {
|
|
position: absolute;
|
|
inset: 0;
|
|
object-fit: cover;
|
|
object-position: center 25%;
|
|
opacity: 0.2;
|
|
scale: 1.1;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
}
|
|
|
|
mm-audio-player {
|
|
transition: opacity 0.125s 0.125s ease-in-out;
|
|
}
|
|
|
|
.unloading {
|
|
opacity: 0;
|
|
transition: opacity 0.125s ease-in-out;
|
|
}
|
|
|
|
mm-footer {
|
|
z-index: 1;
|
|
}
|
|
`
|
|
}
|
|
|
|
|
|
customElements.define('mm-audio', AudioView)
|