167 lines
4.6 KiB
Svelte
167 lines
4.6 KiB
Svelte
<script lang="ts">
|
|
import LL from "$i18n/i18n-svelte";
|
|
import {
|
|
mdiPlay,
|
|
mdiSkipPrevious,
|
|
mdiSkipNext,
|
|
mdiShuffle,
|
|
mdiRepeat,
|
|
mdiDotsVertical,
|
|
mdiFullscreen,
|
|
mdiRepeatOnce,
|
|
mdiPause,
|
|
mdiPlaylistPlay,
|
|
} from "@mdi/js";
|
|
import { createDropdownMenu } from "@melt-ui/svelte";
|
|
|
|
import IconButton from "$lib/components/ui/IconButton.svelte";
|
|
import Slider from "$lib/components/ui/Slider.svelte";
|
|
import CurrentCover from "./CurrentCover.svelte";
|
|
import TrackName from "./TrackName.svelte";
|
|
import VolumeControl from "./VolumeControl.svelte";
|
|
import LikeButton from "$lib/components/ui/LikeButton.svelte";
|
|
import IconToggle from "$lib/components/ui/IconToggle.svelte";
|
|
import IconToggleMulti from "$lib/components/ui/IconToggleMulti.svelte";
|
|
import IconButtonTrigger from "$lib/components/ui/IconButtonTrigger.svelte";
|
|
import TrackMenu from "$lib/components/contextmenu/TrackMenu.svelte";
|
|
|
|
import { clientState, toggleShowQueue } from "$lib/stores/clientState";
|
|
import { formatDuration } from "$lib/util/functions";
|
|
import { testTrack } from "$lib/util/testdata";
|
|
import { POSITIONING_DROPDOWN } from "$lib/util/constants";
|
|
|
|
let position = 81;
|
|
let displayPosition = position;
|
|
let length = 195;
|
|
let track = testTrack;
|
|
|
|
const {
|
|
elements: { trigger, menu, item },
|
|
builders: { createSubmenu },
|
|
states: { open: ddnOpen },
|
|
} = createDropdownMenu({ positioning: POSITIONING_DROPDOWN });
|
|
</script>
|
|
|
|
<div id="playerbar">
|
|
<div class="px-4" class:pl-4={!$clientState.currentCoverLarge}>
|
|
<!-- current track -->
|
|
<div class="track">
|
|
<div
|
|
class="flex items-center justify-start"
|
|
aria-label={$LL.now_playing({
|
|
title: track.name,
|
|
artist: track.artists[0].name,
|
|
})}
|
|
>
|
|
<CurrentCover />
|
|
<TrackName {track} />
|
|
<LikeButton />
|
|
</div>
|
|
</div>
|
|
<!-- controls -->
|
|
<div class="control">
|
|
<div class="flex flex-col justify-center items-center space-y-1">
|
|
<div class="flex w-full space-x-2 justify-center items-center">
|
|
<IconToggle
|
|
iconOn={mdiShuffle}
|
|
ariaLabelOn={$LL.shuffle_enable()}
|
|
ariaLabelOff={$LL.shuffle_disable()}
|
|
/>
|
|
<IconButton path={mdiSkipPrevious} size="md" ariaLabel={$LL.previous()} />
|
|
<IconToggle
|
|
iconOn={mdiPause}
|
|
iconOff={mdiPlay}
|
|
size="md"
|
|
color="primary"
|
|
iColorOn=""
|
|
ariaLabelOn={$LL.play()}
|
|
ariaLabelOff={$LL.pause()}
|
|
/>
|
|
<IconButton path={mdiSkipNext} size="md" ariaLabel={$LL.next()} />
|
|
<IconToggleMulti
|
|
icons={[mdiRepeat, mdiRepeat, mdiRepeatOnce]}
|
|
ariaLabels={[$LL.repeat_disable(), $LL.repeat_queue(), $LL.repeat_track()]}
|
|
/>
|
|
</div>
|
|
<div
|
|
class="flex items-center justify-between w-full text-sm text-base-content text-opacity-70"
|
|
>
|
|
<span class="w-12 text-right"
|
|
>{formatDuration(Math.round(displayPosition))}</span
|
|
>
|
|
<Slider
|
|
min={0}
|
|
max={length}
|
|
bind:value={position}
|
|
bind:displayValue={displayPosition}
|
|
ariaLabel={$LL.seek_bar()}
|
|
/>
|
|
<span class="w-12">{formatDuration(length)}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- options -->
|
|
<div class="options">
|
|
<div class="flex justify-end items-center flex-grow space-x-1">
|
|
<IconToggle
|
|
iconOn={mdiPlaylistPlay}
|
|
value={$clientState.showQueue}
|
|
ariaLabelOn={$LL.queue_show()}
|
|
ariaLabelOff={$LL.queue_hide()}
|
|
on:change={toggleShowQueue}
|
|
/>
|
|
<VolumeControl />
|
|
<IconButton path={mdiFullscreen} ariaLabel={$LL.fullscreen_player()} />
|
|
<IconButtonTrigger
|
|
path={mdiDotsVertical}
|
|
ariaLabel={$LL.track_options()}
|
|
trigger={$trigger}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<TrackMenu
|
|
menu={$menu}
|
|
item={$item}
|
|
open={$ddnOpen}
|
|
{createSubmenu}
|
|
tracks={[testTrack]}
|
|
/>
|
|
|
|
<style lang="postcss">
|
|
#playerbar {
|
|
@apply bg-base-200;
|
|
|
|
grid-area: player / player / player / player;
|
|
|
|
width: 100%;
|
|
min-width: 768px;
|
|
|
|
& > div {
|
|
min-width: 620px;
|
|
height: 90px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
}
|
|
|
|
.track {
|
|
min-width: 180px;
|
|
width: 30%;
|
|
}
|
|
|
|
.control {
|
|
max-width: 722px;
|
|
width: 40%;
|
|
}
|
|
|
|
.options {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
min-width: 180px;
|
|
width: 30%;
|
|
}
|
|
</style>
|