deemix-web-frontend/app/src/App.svelte

192 lines
4.5 KiB
Svelte
Raw Normal View History

2022-02-23 18:18:13 +01:00
<script>
2022-08-18 09:28:58 +02:00
import Album from './lib/Album.svelte';
import Header from './lib/Header.svelte';
import Loading from './lib/Loading.svelte';
import Search from './lib/Search.svelte';
import ThemeSwitcher from './lib/ThemeSwitcher.svelte';
2022-08-18 23:41:37 +02:00
import { queue, saveOnDownload } from './lib/stores';
2022-08-18 09:28:58 +02:00
import { get } from 'svelte/store';
2022-08-18 23:01:08 +02:00
import { dev } from './lib/dev';
import ProgressBar from './lib/ProgressBar.svelte';
2022-08-18 23:41:37 +02:00
import { SvelteToast } from '@zerodevx/svelte-toast'
2022-02-23 18:18:13 +01:00
2022-08-18 09:28:58 +02:00
let loading = false;
2022-08-19 08:29:35 +02:00
let searchAlbums = [];
let total;
let next;
let query;
2022-08-19 10:39:49 +02:00
async function search(q) {
query = q;
2022-08-18 09:28:58 +02:00
searchAlbums = [];
loading = true;
try {
2022-08-18 23:01:08 +02:00
let url = dev ? (new URL('http://localhost:4500/api/search')) : (new URL('/api/search', window.location.origin));
2022-08-18 09:28:58 +02:00
url.searchParams.set('search', query);
const response = await fetch(url);
const data = await response.json();
loading = false;
2022-08-19 08:29:35 +02:00
searchAlbums = data.data;
total = data.total;
next = data.next;
2022-08-18 09:28:58 +02:00
} catch (error) {
console.error(error);
loading = false;
}
}
2022-08-19 08:29:35 +02:00
async function searchMore() {
loading = true;
try {
let url = dev ? (new URL('http://localhost:4500/api/search')) : (new URL('/api/search', window.location.origin));
url.searchParams.set('search', query);
url.searchParams.set('index', next);
const response = await fetch(url);
const data = await response.json();
loading = false;
searchAlbums = [...searchAlbums, ...data.data];
total = data.total;
next = data.next;
} catch (error) {
console.error(error);
loading = false;
}
}
2022-02-23 18:18:13 +01:00
</script>
2022-08-18 23:41:37 +02:00
<SvelteToast options={{
theme: {
'--toastBorderRadius': '0.75em',
'--toastBackground': 'rgba(19, 19, 19, 0.7)'
}
}}/>
2022-08-18 09:28:58 +02:00
<app>
<main>
<span class="main">
<Header/>
<Search onChange={search}/>
{#if searchAlbums.length > 0}
<div class="albums">
{#each searchAlbums as album, i}
<Album title={album.title} id={album.id} cover={album.cover} artist={album.artist}/>
{/each}
</div>
2022-08-19 08:29:35 +02:00
{#if total > searchAlbums.length}
<div style="padding: 1.5em">
<button on:click={searchMore}>Load more</button>
</div>
{/if}
{/if}
{#if loading}
<Loading/>
2022-08-18 09:28:58 +02:00
{/if}
</span>
</main>
<sidebar class:open={$queue.length > 0}>
<h1>Download Queue</h1>
<div class="queue">
{#each $queue as dl}
<div>
<Album log={dl.log} short={true} hideDownload={true} butShowThisDownloadLinkInstead={dl.downloadLink} title={dl.title} artist={dl.artist} cover={dl.cover} id={dl.id} subtitle={!dl.isAlbum && `from ${dl.album}`} />
<ProgressBar progress={dl.progress} success={dl.success}/>
</div>
{/each}
</div>
2022-08-18 23:41:37 +02:00
<form class="options">
<input type="checkbox" id="auto-save" bind:checked={$saveOnDownload}/><label for="auto-save">Save songs on download <span class="small">(Doesn't work on all browsers)</span></label>
</form>
2022-08-18 09:28:58 +02:00
</sidebar>
</app>
2022-02-23 18:18:13 +01:00
<style>
2022-08-18 09:28:58 +02:00
app {
display: flex;
flex-direction: row;
}
2022-02-23 18:18:13 +01:00
2022-08-18 09:28:58 +02:00
.main {
display: flex;
align-items: center;
flex-direction: column;
}
main {
flex: 1 1 0px;
2022-08-18 23:41:37 +02:00
min-height: 100vh;
2022-08-18 09:28:58 +02:00
}
sidebar {
2022-08-18 23:01:08 +02:00
padding: 1em;
display: flex;
flex-direction: column;
2022-08-18 09:28:58 +02:00
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
2022-08-18 23:01:08 +02:00
transition: width 0.2s ease-in-out, padding 0.2s ease-in-out, right 0.2s ease-in-out, height 0.2s ease-in-out;
2022-08-18 09:28:58 +02:00
}
2022-08-18 23:01:08 +02:00
@media (min-width: 1100px) {
sidebar {
height: calc(100vh - 2em);
overflow: auto;
overflow-x: hidden;
position: sticky;
top: 0px;
width: 0px;
right: 0px;
2022-08-18 23:45:17 +02:00
padding: 0em;
2022-08-18 23:01:08 +02:00
}
sidebar.open {
width: 450px;
right: 8px;
padding: 1em;
}
}
@media (max-width: 1099px) {
app {
flex-direction: column;
}
sidebar {
order: -1;
align-items: center;
}
sidebar:not(.open) {
height: 0px;
padding: 0em;
overflow: hidden;
}
2022-08-18 09:28:58 +02:00
}
.queue {
display: flex;
flex-direction: column;
gap: 1em;
2022-08-18 23:41:37 +02:00
max-width: 380px;
}
.options {
padding-top: 1em;
2022-08-18 09:28:58 +02:00
}
@media (prefers-color-scheme: dark) {
sidebar {
background-color: #161627;
}
}
@media (prefers-color-scheme: light) {
sidebar {
background-color: #fafafa;
}
}
.albums {
margin-top: 20px;
width: 600px;
max-width: 98%;
display: flex;
flex-direction: column;
}
</style>