forked from Mastodon/mastoradio-la-radio-di-mastodon
refact store again
This commit is contained in:
parent
9b87708077
commit
dacc31ce77
|
@ -2,4 +2,5 @@ node_modules
|
|||
dist
|
||||
public
|
||||
.cache
|
||||
.env
|
||||
.env
|
||||
.now
|
|
@ -21,11 +21,65 @@
|
|||
|
||||
|
||||
<script>
|
||||
import { onMount, onDestroy } from 'svelte'
|
||||
import { get } from 'svelte/store'
|
||||
|
||||
import Controls from '/components/Controls.svelte'
|
||||
import Queue from '/components/Queue.svelte'
|
||||
import Viewer from '/components/Viewer.svelte'
|
||||
import { hashtagIterator } from '/services/mastodon.js'
|
||||
import { mkTracksIterator } from '/services/misc.js'
|
||||
|
||||
import { current } from '/store.js'
|
||||
import { domain, hashtags, queue, next, current, enqueueing, select } from '/store.js'
|
||||
|
||||
let nextUnsubcribe = null
|
||||
let currentUnsubcribe = null
|
||||
|
||||
onMount(async () => {
|
||||
const iterator = mkTracksIterator(hashtagIterator(get(domain), get(hashtags)[0]))
|
||||
|
||||
const { value: first } = await iterator.next()
|
||||
|
||||
queue.set([first])
|
||||
select(first)
|
||||
|
||||
nextUnsubcribe = next.subscribe(async nextValue => {
|
||||
if (nextValue === null) {
|
||||
if (!get(enqueueing)) {
|
||||
enqueueing.set(true)
|
||||
|
||||
const { value: newTrack } = await iterator.next()
|
||||
|
||||
if (newTrack) {
|
||||
queue.update(queueValue => [...queueValue, newTrack])
|
||||
next.set(newTrack)
|
||||
}
|
||||
|
||||
enqueueing.set(false)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
currentUnsubcribe = current.subscribe(currentValue => {
|
||||
if (currentValue !== null) {
|
||||
next.update(nextValue => {
|
||||
if (nextValue === currentValue) {
|
||||
return null
|
||||
} else {
|
||||
return nextValue
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
for (const unsubcribe of [nextUnsubcribe, currentUnsubcribe]) {
|
||||
if (unsubcribe) {
|
||||
unsubcribe()
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<button class:cant={!$canPrevious} on:click={() => selectPrevious()}>⏮️</button>
|
||||
|
||||
<button on:click={() => $paused = !$paused}>
|
||||
{#if $index === null}
|
||||
{#if $current === null}
|
||||
▶️
|
||||
{:else if $loading}
|
||||
🕒
|
||||
|
@ -44,7 +44,7 @@
|
|||
paused,
|
||||
muted,
|
||||
volume,
|
||||
index,
|
||||
current,
|
||||
queue,
|
||||
canPrevious,
|
||||
canNext,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
<div>
|
||||
<h6>PLAY NEXT</h6>
|
||||
|
||||
{#if $next}
|
||||
<div class="entry">
|
||||
<div class="entry" on:click={() => select($next)}>
|
||||
<div class="title">{$next.metadata.title}</div>
|
||||
<div class="user">by {$next.status.account.acct}</div>
|
||||
</div>
|
||||
|
@ -13,54 +14,32 @@
|
|||
|
||||
|
||||
<h6>HISTORY</h6>
|
||||
{#each $queue as track, i (track.status.id)}
|
||||
<div class="entry" class:active={i === $index}>
|
||||
<div>
|
||||
<button on:click={() => toggle(i)}>
|
||||
{#if i != $index}
|
||||
▶️
|
||||
{:else if $loading}
|
||||
🕒
|
||||
{:else if $paused}
|
||||
▶️
|
||||
{:else}
|
||||
⏸️
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="title">{track.metadata.title}</div>
|
||||
<div class="user">by {track.status.account.acct}</div>
|
||||
{#each history as track (track.status.id)}
|
||||
<div class="entry" class:active={track === $current} on:click={() => select(track)}>
|
||||
<div class>{track.metadata.title}</div>
|
||||
<div class>shared by {track.status.account.acct}</div>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import { next, enqueueing, queue, index, paused, loading, canNext, selectNext } from '/store.js'
|
||||
import { queue, next, current, enqueueing, select } from '/store.js'
|
||||
|
||||
const toggle = i => {
|
||||
if (i === $index) {
|
||||
$paused = !$paused
|
||||
} else {
|
||||
$index = i
|
||||
$paused = false
|
||||
}
|
||||
}
|
||||
|
||||
$: if ($queue.length === 0 && $index === null && $next !== null) {
|
||||
$queue = [$next]
|
||||
$next = null
|
||||
$index = 0
|
||||
}
|
||||
$: history = $queue.filter(x => x !== $next).reverse()
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.entry {
|
||||
padding: 1em 2em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.entry.active {
|
||||
background-color: plum;
|
||||
}
|
||||
|
||||
.entry.active::before {
|
||||
content: "▶️";
|
||||
}
|
||||
</style>
|
|
@ -20,20 +20,22 @@
|
|||
LOADING TRACK
|
||||
{/if}
|
||||
|
||||
{#if duration}
|
||||
<div>
|
||||
{currentTimeText}
|
||||
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max={duration}
|
||||
value="0"
|
||||
value="{currentTime}"
|
||||
on:input={event => updateCurrentTime(event.target.value, false)}
|
||||
on:change={event => updateCurrentTime(event.target.value, true)}
|
||||
disabled={currentTime === null || duration === null}
|
||||
>
|
||||
|
||||
{durationText}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
@ -49,8 +51,8 @@
|
|||
let duration = null
|
||||
let seek = null
|
||||
|
||||
$: currentTimeText = currentTime !== null ? secondsToElapsedTime(currentTime) : null
|
||||
$: durationText = duration !== null ? secondsToElapsedTime(duration) : null
|
||||
$: currentTimeText = currentTime !== null ? secondsToElapsedTime(currentTime) : '--:--'
|
||||
$: durationText = duration !== null ? secondsToElapsedTime(duration) : '--:--'
|
||||
|
||||
$: if (ended || error) {
|
||||
selectNext()
|
||||
|
|
62
src/store.js
62
src/store.js
|
@ -1,7 +1,5 @@
|
|||
import { writable, derived, get } from 'svelte/store'
|
||||
import { writableLocalStorage } from '/services/svelte.js'
|
||||
import { hashtagIterator } from '/services/mastodon.js'
|
||||
import { mkTracksIterator } from '/services/misc.js'
|
||||
|
||||
export const domain = writableLocalStorage('domain', 'eldritch.cafe')
|
||||
|
||||
|
@ -12,63 +10,43 @@ export const hashtags = writableLocalStorage('hashtags', [
|
|||
'pouetradio'
|
||||
])
|
||||
|
||||
|
||||
|
||||
const tracksIterator = mkTracksIterator(hashtagIterator(get(domain), get(hashtags)[0]))
|
||||
|
||||
|
||||
|
||||
export const paused = writable(true)
|
||||
export const muted = writableLocalStorage('muted', false)
|
||||
export const volume = writableLocalStorage('volume', 100)
|
||||
|
||||
export const next = writable(null)
|
||||
export const enqueueing = writable(false)
|
||||
|
||||
export const queue = writable([])
|
||||
export const index = writable(null)
|
||||
export const current = derived([queue, index], ([$queue, $index]) => $queue[$index])
|
||||
|
||||
export const canPrevious = derived([index, queue], ([$index, $queue]) => $index !== null && $index < $queue.length - 1)
|
||||
export const canNext = derived([index, next], ([$index, $next]) => $index !== null && ($index > 0 || $next !== null))
|
||||
export const next = writable(null)
|
||||
export const current = writable(null)
|
||||
export const enqueueing = writable(false)
|
||||
|
||||
export const loading = writable(false)
|
||||
|
||||
next.subscribe(async $next => {
|
||||
if ($next === null) {
|
||||
if (!get(enqueueing)) {
|
||||
enqueueing.set(true)
|
||||
|
||||
const { value: newTrack } = await tracksIterator.next()
|
||||
|
||||
if (newTrack) {
|
||||
next.set(newTrack)
|
||||
}
|
||||
|
||||
enqueueing.set(false)
|
||||
}
|
||||
}
|
||||
const index = derived([queue, current], ([$queue, $current]) => {
|
||||
const i = $queue.indexOf($current)
|
||||
return i === -1 ? null : i
|
||||
})
|
||||
|
||||
export const canPrevious = derived([queue, index], ([$queue, $index]) => $index !== null && $index > 0)
|
||||
export const canNext = derived([queue, index], ([$queue, $index]) => $index !== null && $index < $queue.length - 1)
|
||||
|
||||
|
||||
export const select = track => {
|
||||
console.log(`Select ${track.metadata.title}`)
|
||||
current.set(track)
|
||||
}
|
||||
|
||||
export const selectPrevious = () => {
|
||||
if (get(canPrevious)) {
|
||||
index.update($index => $index + 1)
|
||||
const $queue = get(queue)
|
||||
const $index = get(index)
|
||||
select($queue[$index - 1])
|
||||
}
|
||||
}
|
||||
|
||||
export const selectNext = () => {
|
||||
if (get(canNext)) {
|
||||
const $queue = get(queue)
|
||||
const $index = get(index)
|
||||
|
||||
if ($index === 0) {
|
||||
queue.update($queue => {
|
||||
const $next = get(next)
|
||||
next.set(null)
|
||||
|
||||
return [$next, ...$queue]
|
||||
})
|
||||
} else {
|
||||
index.update($index => $index - 1)
|
||||
}
|
||||
select($queue[$index + 1])
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue