pagination

This commit is contained in:
Jill 2022-08-19 09:29:35 +03:00
parent 79eb457248
commit f5a413cd99
5 changed files with 77 additions and 16 deletions

View File

@ -12,8 +12,13 @@
let loading = false; let loading = false;
let searchAlbums = [];
let total;
let next;
let query;
async function search(event) { async function search(event) {
const query = event.target.value; query = event.target.value;
searchAlbums = []; searchAlbums = [];
loading = true; loading = true;
@ -24,14 +29,33 @@
const response = await fetch(url); const response = await fetch(url);
const data = await response.json(); const data = await response.json();
loading = false; loading = false;
searchAlbums = data; searchAlbums = data.data;
total = data.total;
next = data.next;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
loading = false; loading = false;
} }
} }
let searchAlbums = []; 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;
}
}
</script> </script>
<SvelteToast options={{ <SvelteToast options={{
@ -45,15 +69,21 @@
<span class="main"> <span class="main">
<Header/> <Header/>
<Search onChange={search}/> <Search onChange={search}/>
{#if loading}
<Loading/>
{/if}
{#if searchAlbums.length > 0} {#if searchAlbums.length > 0}
<div class="albums"> <div class="albums">
{#each searchAlbums as album, i} {#each searchAlbums as album, i}
<Album title={album.title} id={album.id} cover={album.cover} artist={album.artist}/> <Album title={album.title} id={album.id} cover={album.cover} artist={album.artist}/>
{/each} {/each}
</div> </div>
{#if total > searchAlbums.length}
<div style="padding: 1.5em">
<button on:click={searchMore}>Load more</button>
</div>
{/if}
{/if}
{#if loading}
<Loading/>
{/if} {/if}
</span> </span>
</main> </main>

View File

@ -23,6 +23,14 @@ body {
color: rgb(151, 151, 255); color: rgb(151, 151, 255);
filter: drop-shadow( 0px 0px 2px #8383F3); filter: drop-shadow( 0px 0px 2px #8383F3);
} }
button {
background-color: #161627;
color: #fff;
border-color: #161627;
}
button:hover {
border-color: rgb(131, 131, 243);
}
} }
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
body { body {
@ -40,6 +48,14 @@ body {
color: #f484b6; color: #f484b6;
filter: drop-shadow( 0px 0px 2px #f484b6); filter: drop-shadow( 0px 0px 2px #f484b6);
} }
button {
background-color: #ffffff;
color: #1e1e2d;
border-color: #ffffff;
}
button:hover {
border-color: #ea74ac;
}
} }
body { body {
@ -57,4 +73,14 @@ body {
.link { .link {
cursor: pointer; cursor: pointer;
transition: 0.1s color ease-out; transition: 0.1s color ease-out;
}
button {
cursor: pointer;
border-width: 2px;
border-radius: 8px;
border-style: solid;
font-size: large;
padding: 0.25em;
transition: 0.1s border-color ease-out;
} }

View File

@ -24,13 +24,15 @@ router.get('/api/album', async (req, res) => {
id: album.id, id: album.id,
title: album.title, title: album.title,
link: album.link, link: album.link,
releaseDate: album.release_date,
explicitCover: album.explicit_content_cover,
tracks: album.tracks.data.map(t => { tracks: album.tracks.data.map(t => {
return { return {
id: t.id, id: t.id,
title: t.title, title: t.title,
duration: t.duration, duration: t.duration,
link: t.link, link: t.link,
artist: t.artist.name, artist: t.artist.name
}; };
}) })
}); });

View File

@ -12,19 +12,22 @@ router.get('/api/search', async (req, res) => {
if (Array.isArray(req.query.search)) req.query.search = req.query.search.join(''); if (Array.isArray(req.query.search)) req.query.search = req.query.search.join('');
req.query.search = req.query.search as string; req.query.search = req.query.search as string;
let s: [Album]; let s: DeezerResponse<[Album]>;
try { try {
s = searchcache[req.query.search] || (await deezerInstance.api.search_album(req.query.search, { s = searchcache[req.query.search+'/'+req.query.index] || (await deezerInstance.api.search_album(req.query.search, {
limit: config.limits.searchLimit || 15, limit: config.limits.searchLimit || 15,
})).data; index: parseInt(req.query.index as string) || undefined
}));
} catch(err) { } catch(err) {
logger.error((err as Error).toString()); logger.error((err as Error).toString());
return res.sendStatus(500); return res.sendStatus(500);
} }
if (!searchcache[req.query.search]) searchcache[req.query.search] = s; searchcache[req.query.search+'/'+req.query.index] = s;
let format = s.map(s => { let format = {
return { next: s.next && s.next.split('=').pop(), // dumb workaround of having to use regexes because i hate regexes
total: s.total,
data: s.data.map(s => ({
id: s.id, id: s.id,
title: s.title, title: s.title,
cover: s.md5_image, cover: s.md5_image,
@ -32,8 +35,8 @@ router.get('/api/search', async (req, res) => {
id: s.artist.id, id: s.artist.id,
name: s.artist.name name: s.artist.name
}, },
}; }))
}); };
res.send(format); res.send(format);
}); });

View File

@ -10,7 +10,7 @@ import { deezerInstance } from './deemix';
export const port = config.server.port || 4500; export const port = config.server.port || 4500;
export let searchcache: Record<string, [Album]> = {}; export let searchcache: Record<string, DeezerResponse<[Album]>> = {};
export let albumcache: Record<string, Album> = {}; export let albumcache: Record<string, Album> = {};
export let trackcache: Record<string, Track> = {}; export let trackcache: Record<string, Track> = {};