forked from Mastodon/mastoradio-la-radio-di-mastodon
~ d e s i g n ~
This commit is contained in:
commit
8633b8534b
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
["@babel/plugin-transform-runtime", {
|
||||||
|
"corejs": 3
|
||||||
|
}]
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.cache
|
||||||
|
.env
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"name": "eldritch-cafe-radio",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "parcel src/index.html",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.7.7",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||||
|
"parcel": "^1.12.4",
|
||||||
|
"parcel-plugin-svelte": "^4.0.5",
|
||||||
|
"svelte": "^3.16.7"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime-corejs3": "^7.7.7",
|
||||||
|
"get-urls": "^9.2.0"
|
||||||
|
},
|
||||||
|
"browserslist": [
|
||||||
|
"last 1 chrome versions"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
<main class="app">
|
||||||
|
<header class="header">
|
||||||
|
<h1>
|
||||||
|
Eldritch Radio
|
||||||
|
</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="player">
|
||||||
|
{#if selectedEntry}
|
||||||
|
Playing <a href={selectedEntry.url}>{selectedEntry.url}</a>
|
||||||
|
{:else}
|
||||||
|
Loading ...
|
||||||
|
{/if}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="queue">
|
||||||
|
{#await entriesPromise}
|
||||||
|
Loading radio please wait
|
||||||
|
{:then entries}
|
||||||
|
<ul>
|
||||||
|
{#each entries as entry}
|
||||||
|
<li>
|
||||||
|
<a href={entry.url}>{entry.url}</a>
|
||||||
|
<small>{entry.tags}</small>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
{:catch error}
|
||||||
|
Oops, something went wrong : {error}
|
||||||
|
{/await}
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<a href="https://{domain}/">{domain}</a> - {@html hashtags.map(hashtag => `<a href="https://${domain}/tags/${hashtag}">#${hashtag}</a>`)}
|
||||||
|
</header>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import { fetchEntries } from './util.js'
|
||||||
|
|
||||||
|
export let domain
|
||||||
|
export let hashtags
|
||||||
|
|
||||||
|
let entriesPromise = new Promise(() => {})
|
||||||
|
let selectedEntry = null
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
entriesPromise = fetchEntries(domain, hashtags)
|
||||||
|
|
||||||
|
entriesPromise.then(entries => {
|
||||||
|
[selectedEntry] = entries
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.app {
|
||||||
|
display: grid;
|
||||||
|
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
|
||||||
|
grid-template-areas:
|
||||||
|
"header"
|
||||||
|
"player"
|
||||||
|
"queue";
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
grid-area: header;
|
||||||
|
}
|
||||||
|
|
||||||
|
.player {
|
||||||
|
grid-area: player;
|
||||||
|
}
|
||||||
|
|
||||||
|
.queue {
|
||||||
|
grid-area: queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.app {
|
||||||
|
grid-template-columns: 2fr 3fr;
|
||||||
|
grid-template-rows: auto 1fr;
|
||||||
|
|
||||||
|
grid-template-areas:
|
||||||
|
"header queue"
|
||||||
|
"player queue"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<title>Document</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script src="main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,16 @@
|
||||||
|
import App from './App.svelte'
|
||||||
|
|
||||||
|
const app = new App({
|
||||||
|
target: document.body,
|
||||||
|
props: {
|
||||||
|
domain: 'eldritch.cafe',
|
||||||
|
hashtags: [
|
||||||
|
'np',
|
||||||
|
'nowplaying',
|
||||||
|
'tootradio',
|
||||||
|
'pouetradio'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default app
|
|
@ -0,0 +1,25 @@
|
||||||
|
import getUrls from 'get-urls'
|
||||||
|
|
||||||
|
export async function fetchEntries(domain, hashtags) {
|
||||||
|
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)
|
||||||
|
const tags = intersection(status.tags.map(tag => tag.name), hashtags)
|
||||||
|
|
||||||
|
return { status, url, tags }
|
||||||
|
})
|
||||||
|
.filter(entry => entry.url != null)
|
||||||
|
|
||||||
|
return entries
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSupportedUrl(url) {
|
||||||
|
return (new URL(url)).hostname === 'youtube.com'
|
||||||
|
}
|
||||||
|
|
||||||
|
function intersection(xs, ys) {
|
||||||
|
return xs.filter(x => ys.includes(x));
|
||||||
|
}
|
Loading…
Reference in New Issue