player use icons
This commit is contained in:
@@ -35,6 +35,21 @@
|
||||
} from "$lib/player/player.svelte";
|
||||
import { createMediaSessionBindings } from "$lib/player/media-session";
|
||||
|
||||
import {
|
||||
ChevronsUpDown,
|
||||
ListX,
|
||||
Pause as PauseIcon,
|
||||
PanelRightClose,
|
||||
PanelRightOpen,
|
||||
Play as PlayIcon,
|
||||
Repeat,
|
||||
Shuffle,
|
||||
SkipBack,
|
||||
SkipForward,
|
||||
Volume2,
|
||||
X,
|
||||
} from "@lucide/svelte";
|
||||
|
||||
let audioEl: HTMLAudioElement | null = null;
|
||||
|
||||
// Best-effort preload of the upcoming track's URL
|
||||
@@ -439,12 +454,17 @@
|
||||
>
|
||||
<div class="mx-auto flex max-w-4xl items-center gap-2 px-3 py-2">
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
onclick={() => toggleUiOpen()}
|
||||
aria-label={snap.uiOpen ? "Close player" : "Open player"}
|
||||
title={snap.uiOpen ? "Close player" : "Open player"}
|
||||
>
|
||||
{snap.uiOpen ? "Close" : "Player"}
|
||||
{#if snap.uiOpen}
|
||||
<X class="h-4 w-4" />
|
||||
{:else}
|
||||
<ChevronsUpDown class="h-4 w-4" />
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<div
|
||||
@@ -502,20 +522,24 @@
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
disabled={!canPrev}
|
||||
aria-label="Previous"
|
||||
title="Previous"
|
||||
onclick={() => {
|
||||
prev(currentTime);
|
||||
void syncAndAutoplay();
|
||||
}}
|
||||
>
|
||||
Prev
|
||||
<SkipBack class="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
aria-label={isPlaying ? "Pause" : "Play"}
|
||||
title={isPlaying ? "Pause" : "Play"}
|
||||
onclick={() => {
|
||||
if (!audioEl) return;
|
||||
if (audioEl.paused) void audioEl.play();
|
||||
@@ -523,19 +547,25 @@
|
||||
}}
|
||||
disabled={!snap.currentTrack}
|
||||
>
|
||||
{isPlaying ? "Pause" : "Play"}
|
||||
{#if isPlaying}
|
||||
<PauseIcon class="h-4 w-4" />
|
||||
{:else}
|
||||
<PlayIcon class="h-4 w-4" />
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
disabled={!canNext}
|
||||
aria-label="Next"
|
||||
title="Next"
|
||||
onclick={() => {
|
||||
next();
|
||||
void syncAndAutoplay();
|
||||
}}
|
||||
>
|
||||
Next
|
||||
<SkipForward class="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -544,22 +574,29 @@
|
||||
<div class="mx-auto max-w-4xl space-y-3">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
onclick={() => toggleShuffle()}
|
||||
aria-label={snap.shuffleEnabled ? "Shuffle on" : "Shuffle off"}
|
||||
title={snap.shuffleEnabled ? "Shuffle on" : "Shuffle off"}
|
||||
>
|
||||
Shuffle: {snap.shuffleEnabled ? "On" : "Off"}
|
||||
<Shuffle class="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
onclick={() => toggleWrap()}
|
||||
aria-label={snap.wrapEnabled ? "Wrap on" : "Wrap off"}
|
||||
title={snap.wrapEnabled ? "Wrap on" : "Wrap off"}
|
||||
>
|
||||
Wrap: {snap.wrapEnabled ? "On" : "Off"}
|
||||
<Repeat class="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
<label class="ml-auto flex items-center gap-2 text-sm">
|
||||
<span class="text-muted-foreground">Vol</span>
|
||||
<span class="text-muted-foreground" aria-hidden="true">
|
||||
<Volume2 class="h-4 w-4" />
|
||||
</span>
|
||||
<span class="sr-only">Volume</span>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
@@ -623,11 +660,13 @@
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-xs"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
onclick={() => removeTrack(item.track.id)}
|
||||
aria-label="Remove from queue"
|
||||
title="Remove from queue"
|
||||
>
|
||||
Remove
|
||||
<ListX class="h-4 w-4" />
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
@@ -679,12 +718,17 @@
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
onclick={() => toggleUiOpen()}
|
||||
aria-label={snap.uiOpen ? "Hide player sidebar" : "Show player sidebar"}
|
||||
title={snap.uiOpen ? "Hide player sidebar" : "Show player sidebar"}
|
||||
>
|
||||
{snap.uiOpen ? "Hide" : "Show"}
|
||||
{#if snap.uiOpen}
|
||||
<PanelRightClose class="h-4 w-4" />
|
||||
{:else}
|
||||
<PanelRightOpen class="h-4 w-4" />
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -697,38 +741,46 @@
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
onclick={() => toggleShuffle()}
|
||||
aria-label={snap.shuffleEnabled ? "Shuffle on" : "Shuffle off"}
|
||||
title={snap.shuffleEnabled ? "Shuffle on" : "Shuffle off"}
|
||||
>
|
||||
Shuffle: {snap.shuffleEnabled ? "On" : "Off"}
|
||||
<Shuffle class="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
onclick={() => toggleWrap()}
|
||||
aria-label={snap.wrapEnabled ? "Wrap on" : "Wrap off"}
|
||||
title={snap.wrapEnabled ? "Wrap on" : "Wrap off"}
|
||||
>
|
||||
Wrap: {snap.wrapEnabled ? "On" : "Off"}
|
||||
<Repeat class="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
disabled={!canPrev}
|
||||
aria-label="Previous"
|
||||
title="Previous"
|
||||
onclick={() => {
|
||||
prev(currentTime);
|
||||
void syncAndAutoplay();
|
||||
}}
|
||||
>
|
||||
Prev
|
||||
<SkipBack class="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
aria-label={isPlaying ? "Pause" : "Play"}
|
||||
title={isPlaying ? "Pause" : "Play"}
|
||||
onclick={() => {
|
||||
if (!audioEl) return;
|
||||
if (audioEl.paused) void audioEl.play();
|
||||
@@ -736,23 +788,32 @@
|
||||
}}
|
||||
disabled={!snap.currentTrack}
|
||||
>
|
||||
{isPlaying ? "Pause" : "Play"}
|
||||
{#if isPlaying}
|
||||
<PauseIcon class="h-4 w-4" />
|
||||
{:else}
|
||||
<PlayIcon class="h-4 w-4" />
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
disabled={!canNext}
|
||||
aria-label="Next"
|
||||
title="Next"
|
||||
onclick={() => {
|
||||
next();
|
||||
void syncAndAutoplay();
|
||||
}}
|
||||
>
|
||||
Next
|
||||
<SkipForward class="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
<label class="ml-auto flex items-center gap-2 text-sm">
|
||||
<span class="text-muted-foreground">Vol</span>
|
||||
<span class="text-muted-foreground" aria-hidden="true">
|
||||
<Volume2 class="h-4 w-4" />
|
||||
</span>
|
||||
<span class="sr-only">Volume</span>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
@@ -819,11 +880,13 @@
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="rounded border px-2 py-1 text-xs"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
type="button"
|
||||
onclick={() => removeTrack(item.track.id)}
|
||||
aria-label="Remove from queue"
|
||||
title="Remove from queue"
|
||||
>
|
||||
Remove
|
||||
<ListX class="h-4 w-4" />
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
<script lang="ts">
|
||||
import {
|
||||
ListPlus,
|
||||
Play as PlayIcon,
|
||||
SkipForward,
|
||||
Trash2,
|
||||
} from "@lucide/svelte";
|
||||
import {
|
||||
addToQueue,
|
||||
hasTrack,
|
||||
@@ -77,49 +83,57 @@
|
||||
<div class="mt-2 flex flex-wrap items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
disabled={!track}
|
||||
title="Play"
|
||||
aria-label="Play"
|
||||
onclick={() => {
|
||||
if (!track) return;
|
||||
play(track);
|
||||
requestGlobalAutoplay();
|
||||
}}
|
||||
>
|
||||
Play
|
||||
<PlayIcon class="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
disabled={!track}
|
||||
title="Play next"
|
||||
aria-label="Play next"
|
||||
onclick={() => {
|
||||
if (!track) return;
|
||||
playNext(track);
|
||||
requestGlobalAutoplay();
|
||||
}}
|
||||
>
|
||||
Play next
|
||||
<SkipForward class="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
disabled={!track}
|
||||
title="Add to queue"
|
||||
aria-label="Add to queue"
|
||||
onclick={() => {
|
||||
if (!track) return;
|
||||
addToQueue(track);
|
||||
}}
|
||||
>
|
||||
Add to queue
|
||||
<ListPlus class="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
{#if isQueued}
|
||||
<button
|
||||
type="button"
|
||||
class="rounded border px-2 py-1 text-sm"
|
||||
class="inline-flex h-8 w-8 items-center justify-center rounded border"
|
||||
title="Remove from queue"
|
||||
aria-label="Remove from queue"
|
||||
onclick={() => removeTrack(annSongId)}
|
||||
>
|
||||
Remove
|
||||
<Trash2 class="h-4 w-4" />
|
||||
</button>
|
||||
|
||||
<span class="text-xs text-muted-foreground">Queued</span>
|
||||
|
||||
Reference in New Issue
Block a user