fix(player): volume slider jumps / flickers

This commit is contained in:
2024-11-26 00:27:12 +01:00
parent 48c92f6b00
commit 9fc59cfd61
4 changed files with 61 additions and 24 deletions

View File

@@ -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>

View File

@@ -25,6 +25,7 @@
if (result.type === 'success' && result.data) {
player.currentlyPlaying = result.data.track ?? null;
player.progress = result.data.position;
player.isPaused = false;
}
};
};

View File

@@ -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;

View File

@@ -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 () => {