Changed currentlyPlaying to queue
This commit is contained in:
@@ -3,15 +3,9 @@
|
|||||||
|
|
||||||
import IconButton from '$lib/components/util/iconButton.svelte'
|
import IconButton from '$lib/components/util/iconButton.svelte'
|
||||||
import { goto } from '$app/navigation'
|
import { goto } from '$app/navigation'
|
||||||
import { currentlyPlaying } from '$lib/stores'
|
import { queue } from '$lib/stores'
|
||||||
|
|
||||||
let image: HTMLImageElement, captionText: HTMLDivElement
|
let image: HTMLImageElement, captionText: HTMLDivElement
|
||||||
|
|
||||||
const setCurrentlyPlaying = () => {
|
|
||||||
if (mediaItem.type === 'song') {
|
|
||||||
$currentlyPlaying = mediaItem
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="card-wrapper" class="flex-shrink-0">
|
<div id="card-wrapper" class="flex-shrink-0">
|
||||||
@@ -31,7 +25,12 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<span id="play-button" class="absolute left-1/2 top-1/2 h-12 -translate-x-1/2 -translate-y-1/2 opacity-0 transition-opacity duration-200 ease-out">
|
<span id="play-button" class="absolute left-1/2 top-1/2 h-12 -translate-x-1/2 -translate-y-1/2 opacity-0 transition-opacity duration-200 ease-out">
|
||||||
<IconButton halo={true} on:click={setCurrentlyPlaying}>
|
<IconButton
|
||||||
|
halo={true}
|
||||||
|
on:click={() => {
|
||||||
|
if (mediaItem.type === 'song') $queue.push(mediaItem)
|
||||||
|
}}
|
||||||
|
>
|
||||||
<i slot="icon" class="fa-solid fa-play text-xl" />
|
<i slot="icon" class="fa-solid fa-play text-xl" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte'
|
import { onMount } from 'svelte'
|
||||||
import { fade, slide } from 'svelte/transition'
|
import { fade, slide } from 'svelte/transition'
|
||||||
import { currentlyPlaying } from '$lib/stores'
|
import { queue } from '$lib/stores'
|
||||||
// import { FastAverageColor } from 'fast-average-color'
|
// import { FastAverageColor } from 'fast-average-color'
|
||||||
import Slider from '$lib/components/util/slider.svelte'
|
import Slider from '$lib/components/util/slider.svelte'
|
||||||
|
|
||||||
|
let queuePosition = 0
|
||||||
|
$: currentlyPlaying = $queue[queuePosition]
|
||||||
|
|
||||||
let paused = true,
|
let paused = true,
|
||||||
shuffle = false,
|
shuffle = false,
|
||||||
repeat = false
|
repeat = false
|
||||||
@@ -46,17 +49,17 @@
|
|||||||
$: if (!seeking && durationTimestamp) durationTimestamp.innerText = formatTime(duration)
|
$: if (!seeking && durationTimestamp) durationTimestamp.innerText = formatTime(duration)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $currentlyPlaying}
|
{#if currentlyPlaying}
|
||||||
<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">
|
<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">
|
||||||
<section class="flex gap-3">
|
<section class="flex gap-3">
|
||||||
<div class="relative h-full w-20 min-w-20">
|
<div class="relative h-full w-20 min-w-20">
|
||||||
{#key $currentlyPlaying}
|
{#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});" />
|
<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});" />
|
||||||
{/key}
|
{/key}
|
||||||
</div>
|
</div>
|
||||||
<section class="flex flex-col justify-center gap-1">
|
<section class="flex flex-col justify-center gap-1">
|
||||||
<div class="line-clamp-2 text-sm">{$currentlyPlaying.name}</div>
|
<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>
|
<div class="text-xs">{currentlyPlaying.artists?.map((artist) => artist.name).join(', ') || currentlyPlaying.createdBy?.name}</div>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
<section class="flex min-w-max flex-col items-center justify-center gap-1">
|
<section class="flex min-w-max flex-col items-center justify-center gap-1">
|
||||||
@@ -78,7 +81,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-items-center gap-2">
|
<div class="flex items-center justify-items-center gap-2">
|
||||||
<span bind:this={currentTimeTimestamp} class="w-8 text-right" />
|
<span bind:this={currentTimeTimestamp} class="w-16 text-right" />
|
||||||
<div class="w-72">
|
<div class="w-72">
|
||||||
<Slider
|
<Slider
|
||||||
bind:this={progressBar}
|
bind:this={progressBar}
|
||||||
@@ -93,7 +96,7 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span bind:this={durationTimestamp} class="w-8 text-left" />
|
<span bind:this={durationTimestamp} class="w-16 text-left" />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="flex items-center justify-end pr-2 text-lg">
|
<section class="flex items-center justify-end pr-2 text-lg">
|
||||||
@@ -105,11 +108,11 @@
|
|||||||
<Slider bind:value={volume} max={1} />
|
<Slider bind:value={volume} max={1} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button class="aspect-square h-8" on:click={() => ($currentlyPlaying = null)}>
|
<button class="aspect-square h-8" on:click={() => ($queue = [])}>
|
||||||
<i class="fa-solid fa-xmark" />
|
<i class="fa-solid fa-xmark" />
|
||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
<audio bind:paused bind:volume bind:currentTime bind:duration on:ended={() => ($currentlyPlaying = null)} src="/api/audio?connection={$currentlyPlaying.connection}&id={$currentlyPlaying.id}" />
|
<audio bind:paused bind:volume bind:currentTime bind:duration on:ended={() => queuePosition++} src="/api/audio?connection={currentlyPlaying.connection}&id={currentlyPlaying.id}" />
|
||||||
</main>
|
</main>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export const pageWidth: Writable<number> = writable()
|
|||||||
|
|
||||||
export const newestAlert: Writable<[AlertType, string]> = writable()
|
export const newestAlert: Writable<[AlertType, string]> = writable()
|
||||||
|
|
||||||
export const currentlyPlaying: Writable<Song | null> = writable()
|
export const queue: Writable<Song[]> = writable()
|
||||||
|
|
||||||
const youtubeMusicBackground: string = 'https://www.gstatic.com/youtube/media/ytm/images/sbg/wsbg@4000x2250.png' // Default Youtube music background
|
const youtubeMusicBackground: string = 'https://www.gstatic.com/youtube/media/ytm/images/sbg/wsbg@4000x2250.png' // Default Youtube music background
|
||||||
export const backgroundImage: Writable<string> = writable(youtubeMusicBackground)
|
export const backgroundImage: Writable<string> = writable(youtubeMusicBackground)
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { currentlyPlaying } from '$lib/stores'
|
import { queue } from '$lib/stores'
|
||||||
import type { PageServerData } from './$types'
|
import type { PageServerData } from './$types'
|
||||||
|
|
||||||
export let data: PageServerData
|
export let data: PageServerData
|
||||||
|
|
||||||
|
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')}`
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if data.searchResults}
|
{#if data.searchResults}
|
||||||
@@ -13,7 +22,7 @@
|
|||||||
<button
|
<button
|
||||||
id="searchResult"
|
id="searchResult"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (searchResult.type === 'song') $currentlyPlaying = searchResult
|
if (searchResult.type === 'song') $queue.push(searchResult)
|
||||||
}}
|
}}
|
||||||
class="grid aspect-square h-full place-items-center bg-cover bg-center bg-no-repeat"
|
class="grid aspect-square h-full place-items-center bg-cover bg-center bg-no-repeat"
|
||||||
style="--thumbnail: url('/api/remoteImage?url={searchResult.thumbnail}')"
|
style="--thumbnail: url('/api/remoteImage?url={searchResult.thumbnail}')"
|
||||||
@@ -28,6 +37,9 @@
|
|||||||
<div>{searchResult.createdBy?.name}</div>
|
<div>{searchResult.createdBy?.name}</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
{#if 'duration' in searchResult && searchResult.duration}
|
||||||
|
<span class="justify-self-end">{formatTime(searchResult.duration)}</span>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
Reference in New Issue
Block a user