2024-04-05 02:00:17 -04:00
|
|
|
<script lang="ts">
|
2024-04-09 00:10:23 -04:00
|
|
|
import { onMount } from 'svelte'
|
2024-04-13 00:45:35 -04:00
|
|
|
import { fade, slide } from 'svelte/transition'
|
2024-04-15 22:26:38 -04:00
|
|
|
import { queue } from '$lib/stores'
|
2024-04-13 00:45:35 -04:00
|
|
|
// import { FastAverageColor } from 'fast-average-color'
|
2024-04-09 00:10:23 -04:00
|
|
|
import Slider from '$lib/components/util/slider.svelte'
|
|
|
|
|
|
2024-04-16 10:05:11 -04:00
|
|
|
$: console.log(`Queue is now: ${$queue}`)
|
2024-04-15 22:26:38 -04:00
|
|
|
|
2024-04-13 00:45:35 -04:00
|
|
|
let paused = true,
|
2024-04-09 00:10:23 -04:00
|
|
|
shuffle = false,
|
|
|
|
|
repeat = false
|
|
|
|
|
|
2024-04-13 00:45:35 -04:00
|
|
|
let volume: number,
|
|
|
|
|
muted = false
|
2024-04-10 00:27:36 -04:00
|
|
|
|
2024-04-13 00:45:35 -04:00
|
|
|
$: if (volume) localStorage.setItem('volume', volume.toString())
|
2024-04-10 00:27:36 -04:00
|
|
|
|
2024-04-13 00:45:35 -04:00
|
|
|
const formatTime = (seconds: number): string => {
|
|
|
|
|
seconds = Math.floor(seconds)
|
|
|
|
|
const hours = Math.floor(seconds / 3600)
|
|
|
|
|
seconds = seconds - hours * 3600
|
|
|
|
|
const minutes = Math.floor(seconds / 60)
|
|
|
|
|
seconds = seconds - minutes * 60
|
|
|
|
|
return hours > 0 ? `${hours}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}` : `${minutes}:${seconds.toString().padStart(2, '0')}`
|
|
|
|
|
}
|
2024-04-10 00:27:36 -04:00
|
|
|
|
2024-04-13 00:45:35 -04:00
|
|
|
onMount(() => {
|
|
|
|
|
const storedVolume = localStorage.getItem('volume')
|
|
|
|
|
if (storedVolume) {
|
|
|
|
|
volume = Number(storedVolume)
|
|
|
|
|
} else {
|
|
|
|
|
localStorage.setItem('volume', '0.5')
|
|
|
|
|
volume = 0.5
|
2024-04-10 00:27:36 -04:00
|
|
|
}
|
2024-04-13 00:45:35 -04:00
|
|
|
})
|
2024-04-10 00:27:36 -04:00
|
|
|
|
2024-04-13 00:45:35 -04:00
|
|
|
let currentTime: number = 0
|
|
|
|
|
let duration: number = 0
|
2024-04-10 00:27:36 -04:00
|
|
|
|
2024-04-13 00:45:35 -04:00
|
|
|
let currentTimeTimestamp: HTMLSpanElement
|
|
|
|
|
let progressBar: Slider
|
|
|
|
|
let durationTimestamp: HTMLSpanElement
|
2024-04-05 02:00:17 -04:00
|
|
|
|
2024-04-13 00:45:35 -04:00
|
|
|
let seeking: boolean = false
|
|
|
|
|
$: if (!seeking && currentTimeTimestamp) currentTimeTimestamp.innerText = formatTime(currentTime)
|
|
|
|
|
$: if (!seeking && progressBar) progressBar.$set({ value: currentTime })
|
|
|
|
|
$: if (!seeking && durationTimestamp) durationTimestamp.innerText = formatTime(duration)
|
|
|
|
|
</script>
|
2024-04-05 02:00:17 -04:00
|
|
|
|
2024-04-16 10:05:11 -04:00
|
|
|
{#if $queue.queue.length > 0}
|
|
|
|
|
{@const currentlyPlaying = $queue.getCurrent()}
|
2024-04-15 09:24:28 -04:00
|
|
|
<main transition:slide class="relative m-4 grid h-20 grid-cols-[minmax(auto,_20rem)_auto_minmax(auto,_20rem)] gap-4 overflow-clip rounded-xl bg-neutral-925 text-white transition-colors duration-1000">
|
2024-04-13 00:45:35 -04:00
|
|
|
<section class="flex gap-3">
|
|
|
|
|
<div class="relative h-full w-20 min-w-20">
|
2024-04-15 22:26:38 -04:00
|
|
|
{#key currentlyPlaying}
|
|
|
|
|
<div transition:fade={{ duration: 500 }} class="absolute h-full w-full bg-cover bg-center bg-no-repeat" style="background-image: url(/api/remoteImage?url={currentlyPlaying.thumbnail});" />
|
2024-04-09 00:10:23 -04:00
|
|
|
{/key}
|
|
|
|
|
</div>
|
2024-04-13 00:45:35 -04:00
|
|
|
<section class="flex flex-col justify-center gap-1">
|
2024-04-15 22:26:38 -04:00
|
|
|
<div class="line-clamp-2 text-sm">{currentlyPlaying.name}</div>
|
|
|
|
|
<div class="text-xs">{currentlyPlaying.artists?.map((artist) => artist.name).join(', ') || currentlyPlaying.createdBy?.name}</div>
|
2024-04-13 00:45:35 -04:00
|
|
|
</section>
|
|
|
|
|
</section>
|
2024-04-15 09:24:28 -04:00
|
|
|
<section class="flex min-w-max flex-col items-center justify-center gap-1">
|
2024-04-13 00:45:35 -04:00
|
|
|
<div class="flex items-center gap-3 text-lg">
|
|
|
|
|
<button on:click={() => (shuffle = !shuffle)} class="aspect-square h-8">
|
|
|
|
|
<i class="fa-solid fa-shuffle" />
|
2024-04-09 00:10:23 -04:00
|
|
|
</button>
|
2024-04-13 00:45:35 -04:00
|
|
|
<button class="aspect-square h-8">
|
|
|
|
|
<i class="fa-solid fa-backward-step" />
|
2024-04-09 00:10:23 -04:00
|
|
|
</button>
|
2024-04-13 00:45:35 -04:00
|
|
|
<button on:click={() => (paused = !paused)} class="grid aspect-square h-8 place-items-center rounded-full bg-white">
|
|
|
|
|
<i class="fa-solid {paused ? 'fa-play' : 'fa-pause'} text-black" />
|
2024-04-09 00:10:23 -04:00
|
|
|
</button>
|
2024-04-13 00:45:35 -04:00
|
|
|
<button class="aspect-square h-8">
|
2024-04-09 00:10:23 -04:00
|
|
|
<i class="fa-solid fa-forward-step" />
|
|
|
|
|
</button>
|
2024-04-13 00:45:35 -04:00
|
|
|
<button on:click={() => (repeat = !repeat)} class="aspect-square h-8">
|
|
|
|
|
<i class="fa-solid fa-repeat" />
|
|
|
|
|
</button>
|
2024-04-09 00:10:23 -04:00
|
|
|
</div>
|
2024-04-15 09:24:28 -04:00
|
|
|
<div class="flex items-center justify-items-center gap-2">
|
2024-04-15 22:26:38 -04:00
|
|
|
<span bind:this={currentTimeTimestamp} class="w-16 text-right" />
|
2024-04-15 09:24:28 -04:00
|
|
|
<div class="w-72">
|
|
|
|
|
<Slider
|
|
|
|
|
bind:this={progressBar}
|
|
|
|
|
max={duration}
|
|
|
|
|
on:seeking={(event) => {
|
|
|
|
|
currentTimeTimestamp.innerText = formatTime(event.detail.value)
|
|
|
|
|
seeking = true
|
|
|
|
|
}}
|
|
|
|
|
on:seeked={(event) => {
|
|
|
|
|
currentTime = event.detail.value
|
|
|
|
|
seeking = false
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2024-04-15 22:26:38 -04:00
|
|
|
<span bind:this={durationTimestamp} class="w-16 text-left" />
|
2024-04-13 00:45:35 -04:00
|
|
|
</div>
|
|
|
|
|
</section>
|
2024-04-15 09:24:28 -04:00
|
|
|
<section class="flex items-center justify-end pr-2 text-lg">
|
2024-04-13 00:45:35 -04:00
|
|
|
<div id="volume-slider" class="flex h-10 w-fit flex-shrink-0 flex-row-reverse items-center gap-2">
|
|
|
|
|
<button on:click={() => (muted = !muted)} class="aspect-square h-8">
|
|
|
|
|
<i class="fa-solid {volume > 0.5 ? 'fa-volume-high' : volume > 0 ? 'fa-volume-low' : 'fa-volume-xmark'} w-full text-center text-base" />
|
|
|
|
|
</button>
|
|
|
|
|
<div id="slider-wrapper" class="w-0 transition-all duration-500">
|
|
|
|
|
<Slider bind:value={volume} max={1} />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2024-04-16 10:05:11 -04:00
|
|
|
<button class="aspect-square h-8" on:click={() => console.log('close')}>
|
2024-04-13 00:45:35 -04:00
|
|
|
<i class="fa-solid fa-xmark" />
|
|
|
|
|
</button>
|
|
|
|
|
</section>
|
2024-04-16 10:05:11 -04:00
|
|
|
<audio autoplay bind:paused bind:volume bind:currentTime bind:duration on:ended={() => console.log('next')} src="/api/audio?connection={currentlyPlaying.connection}&id={currentlyPlaying.id}" />
|
2024-04-13 00:45:35 -04:00
|
|
|
</main>
|
|
|
|
|
{/if}
|
2024-04-09 00:10:23 -04:00
|
|
|
|
2024-04-13 00:45:35 -04:00
|
|
|
<style>
|
|
|
|
|
#volume-slider:hover > #slider-wrapper {
|
|
|
|
|
width: 6rem;
|
|
|
|
|
}
|
|
|
|
|
#slider-wrapper:focus-within {
|
|
|
|
|
width: 6rem;
|
2024-04-05 02:00:17 -04:00
|
|
|
}
|
2024-04-13 00:45:35 -04:00
|
|
|
</style>
|