fix(player): volume slider jumps / flickers
This commit is contained in:
@@ -13,7 +13,6 @@
|
||||
import { Progress } from '$lib/components/ui/progress';
|
||||
import dayjs from 'dayjs';
|
||||
import duration from 'dayjs/plugin/duration';
|
||||
import { Slider } from '$lib/components/ui/slider';
|
||||
import * as Popover from '$lib/components/ui/popover';
|
||||
import { Separator } from '$lib/components/ui/separator';
|
||||
import { getPlayerState } from '$lib/player.svelte';
|
||||
@@ -77,19 +76,24 @@
|
||||
};
|
||||
};
|
||||
|
||||
const submitVolumeForm: SubmitFunction = async ({ formData }) => {
|
||||
formData.set('volume', player.volume.toString());
|
||||
|
||||
return async ({ update, result }) => {
|
||||
await update({
|
||||
invalidateAll: false
|
||||
});
|
||||
|
||||
if (result.type === 'success' && result.data && 'volume' in result.data) {
|
||||
player.volume = result.data.volume;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function onMouseMove(e: MouseEvent) {
|
||||
mouse.offsetX = e.offsetX;
|
||||
mouse.offsetY = e.offsetY;
|
||||
}
|
||||
|
||||
let volume = $state({
|
||||
get value() {
|
||||
return [player.volume];
|
||||
},
|
||||
set value(v: number[]) {
|
||||
player.volume = v[0];
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<footer class="border border-x-0 border-t border-border/40 bg-background/95 px-4">
|
||||
@@ -189,20 +193,23 @@
|
||||
class="flex-1"
|
||||
method="POST"
|
||||
action="/player?/volume"
|
||||
use:enhance
|
||||
use:enhance={submitVolumeForm}
|
||||
>
|
||||
<input type="hidden" name="volume" value={volume.value[0]} />
|
||||
<Slider
|
||||
class="w-full"
|
||||
min={0}
|
||||
max={1}
|
||||
<input
|
||||
class="volume-slider"
|
||||
type="range"
|
||||
min={0.0}
|
||||
max={1.0}
|
||||
step={0.01}
|
||||
bind:value={volume.value}
|
||||
onValueChange={() => {
|
||||
bind:value={player.volume}
|
||||
oninput={() => {
|
||||
volumeForm?.requestSubmit();
|
||||
}}
|
||||
onValueCommit={() => {
|
||||
volumeForm?.requestSubmit();
|
||||
onmousedown={() => {
|
||||
player.adjustingVolume = true;
|
||||
}}
|
||||
onmouseup={() => {
|
||||
player.adjustingVolume = false;
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
@@ -240,3 +247,30 @@
|
||||
</footer>
|
||||
|
||||
<svelte:window onmousemove={onMouseMove} />
|
||||
|
||||
<style>
|
||||
.volume-slider {
|
||||
-webkit-appearance: none !important; /* Override default CSS styles */
|
||||
appearance: none !important;
|
||||
width: 100%; /* Full-width */
|
||||
height: 8px; /* Specified height */
|
||||
border-radius: 0.5rem;
|
||||
background: hsl(var(--secondary));
|
||||
outline: none; /* Remove outline */
|
||||
opacity: 0.7; /* Set transparency (for mouse-over effects on hover) */
|
||||
-webkit-transition: 0.2s; /* 0.2 seconds transition on hover */
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.volume-slider::-webkit-slider-thumb {
|
||||
@apply size-4 bg-background ring ring-secondary ring-offset-0 ring-offset-transparent transition-colors;
|
||||
|
||||
appearance: none;
|
||||
background-color: hsl(var(--primary));
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.volume-slider::-webkit-slider-thumb:active {
|
||||
@apply ring-offset-2 ring-offset-background;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
if (result.type === 'success' && result.data) {
|
||||
player.currentlyPlaying = result.data.track ?? null;
|
||||
player.progress = result.data.position;
|
||||
player.isPaused = false;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -5,10 +5,11 @@ import { PlayerClient } from './proto/player.client';
|
||||
import { protoTransport } from '../hooks.client';
|
||||
|
||||
class PlayerState {
|
||||
volume = $state(0);
|
||||
volume = $state(0.0);
|
||||
currentlyPlaying = $state<Track | null>(null);
|
||||
progress = $state<bigint>(0n);
|
||||
isPaused = $state(false);
|
||||
adjustingVolume = $state(false);
|
||||
#abortContoller: AbortController | null = null;
|
||||
|
||||
constructor() {
|
||||
@@ -26,7 +27,10 @@ class PlayerState {
|
||||
}
|
||||
|
||||
applyStatus(status: PlayerStatus) {
|
||||
if (!this.adjustingVolume) {
|
||||
this.volume = status.volume;
|
||||
}
|
||||
|
||||
this.progress = status.progress;
|
||||
this.currentlyPlaying = status.currentlyPlaying ?? null;
|
||||
this.isPaused = status.isPaused;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { PlayerClient } from '$lib/proto/player.client';
|
||||
import { protoTransport } from '../hooks.server';
|
||||
import type { LayoutServerLoad } from './$types';
|
||||
|
||||
export const load: LayoutServerLoad = async () => {
|
||||
|
||||
Reference in New Issue
Block a user