big store uwu

This commit is contained in:
wryk 2020-01-09 02:26:13 +01:00
parent 3e9ac5f2e8
commit 408099ac29
5 changed files with 102 additions and 64 deletions

View File

@ -15,23 +15,29 @@
</section> </section>
<section class="queue"> <section class="queue">
{#await entriesPromise} {#if $entries}
Loading radio please wait {#await $entries}
{:then entries} Loading radio please wait
<ul> {:then entries}
{#each entries as entry} <ul>
<li class="entry" class:active={entry === selectedEntry} on:click={selectEntry(entry)}> {#each entries as entry}
<b>{entry.status.account.acct}</b> <li class="entry" class:active={entry === selectedEntry} on:click={selectEntry(entry)}>
<small>{entry.tags}</small> <b>{entry.status.account.acct}</b>
</li> <small>{entry.tags}</small>
{/each} </li>
</ul> {/each}
{:catch error} </ul>
Oops, something went wrong : {error} {:catch error}
{/await} Oops, something went wrong : {error}
{/await}
{:else}
Your queue
{/if}
<header> <header>
<a href="https://{domain}/">{domain}</a> - {@html hashtags.map(hashtag => `<a href="https://${domain}/tags/${hashtag}">#${hashtag}</a>`)} <a href="https://{$domain}/">{$domain}</a> - {@html $hashtags.map(hashtag => `<a href="https://${$domain}/tags/${hashtag}">#${hashtag}</a>`)}
<button on:click={() => entries.load()}>LOAD MOAR</button>
</header> </header>
</section> </section>
</main> </main>
@ -39,13 +45,9 @@
<script> <script>
import { onMount } from 'svelte' import { onMount } from 'svelte'
import { fetchEntries } from './util.js'
import YoutubeViewer from './YoutubeViewer.svelte' import YoutubeViewer from './YoutubeViewer.svelte'
import { domain, hashtags, entries } from './store.js'
export let domain
export let hashtags
let entriesPromise = new Promise(() => {})
let selectedEntry = null let selectedEntry = null
const selectEntry = entry => { const selectEntry = entry => {
@ -53,11 +55,7 @@
} }
onMount(() => { onMount(() => {
entriesPromise = fetchEntries(domain, hashtags) entries.load()
entriesPromise.then(entries => {
[selectedEntry] = entries
})
}) })
</script> </script>

View File

@ -1,5 +1,7 @@
<div> <div>
<div bind:this={element}></div> <div bind:this={element}></div>
<button on:click={player.play()}>PLAY UWU</button>
</div> </div>
<script> <script>
@ -12,16 +14,13 @@
let player let player
$: if (player && videoId) { $: if (player && videoId) {
console.log(`loada ${videoId}`)
player.load(videoId, true) player.load(videoId, true)
} }
onMount(() => { onMount(() => {
player = new YoutubePlayer(element, { player = new YoutubePlayer(element, {
width: 200,
height: 200,
autoplay: true, autoplay: true,
controls: false, // debug only controls: true, // debug only
keyboard: false, keyboard: false,
fullscreen: false, fullscreen: false,
modestBranding: true, modestBranding: true,

View File

@ -1,16 +1,7 @@
import App from './App.svelte' import App from './App.svelte'
const app = new App({ const app = new App({
target: document.body, target: document.body
props: {
domain: 'eldritch.cafe',
hashtags: [
'np',
'nowplaying',
'tootradio',
'pouetradio'
]
}
}) })
export default app export default app

71
src/store.js Normal file
View File

@ -0,0 +1,71 @@
import { writable, get } from 'svelte/store'
import { getUrls, getYoutubeId, isSupportedUrl, intersection } from './util.js'
export const domain = writable('eldritch.cafe')
export const hashtags = writable([
'np',
'nowplaying',
'tootradio',
'pouetradio'
])
export const entries = entriesStore()
function entriesStore() {
let loading = false
let next = `https://eldritch.cafe/api/v1/timelines/tag/np`
const store = writable(null)
const { set, subscribe } = store
const load = async () => {
if (loading) {
return
}
loading = true
const responseP = fetch(next)
responseP.then(response => {
next = Array.from(getUrls(response.headers.get('link')))[0] // need to better parse that
})
const entriesP = responseP
.then(response => response.json())
.then(statuses => {
return statuses
.map(status => {
const [url] = Array.from(getUrls(status.content)).filter(isSupportedUrl)
return { status, url }
})
.filter(entry => entry.url != null)
.map(({ status, url }) => {
const id = getYoutubeId(url)
const tags = intersection(status.tags.map(tag => tag.name), [
'np',
'nowplaying',
'tootradio',
'pouetradio'
])
return { status, url, id, tags }
})
})
const previousEntriesP = get(store)
if (previousEntriesP) {
const [previousEntries, entries] = await Promise.all([previousEntriesP, entriesP])
set(Promise.resolve([...previousEntries, ...entries]))
} else {
set(entriesP)
}
loading = false
}
return { subscribe, load }
}

View File

@ -1,31 +1,10 @@
import getUrls from 'get-urls' export { default as getUrls } from 'get-urls'
import getYoutubeId from 'get-youtube-id' export { default as getYoutubeId } from 'get-youtube-id'
export async function fetchEntries(domain, hashtags) { export function isSupportedUrl(url) {
const response = await fetch(`https://${domain}/api/v1/timelines/tag/${hashtags[0]}`)
const statuses = await response.json()
const entries = statuses
.map(status => {
const [url] = Array.from(getUrls(status.content)).filter(isSupportedUrl)
return { status, url }
})
.filter(entry => entry.url != null)
.map(({ status, url }) => {
const id = getYoutubeId(url)
const tags = intersection(status.tags.map(tag => tag.name), hashtags)
return { status, url, id, tags }
})
return entries
}
function isSupportedUrl(url) {
return (new URL(url)).hostname === 'youtube.com' return (new URL(url)).hostname === 'youtube.com'
} }
function intersection(xs, ys) { export function intersection(xs, ys) {
return xs.filter(x => ys.includes(x)); return xs.filter(x => ys.includes(x));
} }