diff --git a/src-tauri/src/music/commands.rs b/src-tauri/src/music/commands.rs index 9e213bf..cd3d008 100644 --- a/src-tauri/src/music/commands.rs +++ b/src-tauri/src/music/commands.rs @@ -74,6 +74,8 @@ pub fn seek_to( state: State<'_, AppData>, ) -> Result<(), String> { core::seek_to(&state, position)?; + // Emit the new position immediately so the UI updates without waiting for the next periodic update + app.emit("PLAYBACK_POSITION_UPDATE", state.sink.get_pos()).unwrap(); app.emit("SERVER_SYNC_EVENT", "").unwrap(); Ok(()) } diff --git a/src/app/views/currently-playing.component.ts b/src/app/views/currently-playing.component.ts index ab63747..2bcf8d2 100644 --- a/src/app/views/currently-playing.component.ts +++ b/src/app/views/currently-playing.component.ts @@ -170,13 +170,16 @@ export class AlbumArt {

{{ totalTimeFormatted() }}

- - + [value]="currentSecs() ?? 0" + [max]="totalSecs() ?? 0" + min="0" + step="1" + [style.--progress]="progressPercent() + '%'" + (input)="seekFromInput($event)" + />
@@ -289,22 +292,26 @@ export class AlbumArt { background-blend-mode: plus-darker; height: 0.5rem; appearance: none; + background: rgba(0, 0, 0, 0.12); + cursor: pointer; } - .progressBar::-webkit-progress-bar { - height: 100%; - background: rgba(0, 0, 0, 0.12); - padding: 0; - margin: 0; + .progressBar::-webkit-slider-thumb { + appearance: none; + width: 0; + height: 0; } - .progressBar::-webkit-progress-value { - border-radius: 1.25rem; - background: rgba(255, 255, 255, 0.8); - mix-blend-mode: plus-lighter; - height: 100%; - padding: 0; - margin: 0; + .progressBar::-webkit-slider-runnable-track { + height: 0.5rem; + border-radius: 1.5rem; + background: linear-gradient( + to right, + rgba(255, 255, 255, 0.8) 0%, + rgba(255, 255, 255, 0.8) var(--progress, 0%), + transparent var(--progress, 0%), + transparent 100% + ); } `, ], @@ -335,6 +342,13 @@ export class CurrentlyPlaying { return this.playingMetadata().position?.secs; }); + progressPercent = computed(() => { + const current = this.currentSecs() ?? 0; + const total = this.totalSecs() ?? 0; + if (total === 0) return 0; + return (current / total) * 100; + }); + totalTime = computed(() => { // Format as `hh:mm:ss` but only show minutes and hours if they are non-zero const duration = this.playingMetadata().duration?.secs; @@ -380,11 +394,9 @@ export class CurrentlyPlaying { resume = resume; pause = pause; - seekFromProgressBar(event: MouseEvent) { - const progressBar = event.target as HTMLProgressElement; - const value = - (event.offsetX / progressBar.offsetWidth) * - parseInt(progressBar.getAttribute("max") || "0"); + seekFromInput(event: Event) { + const input = event.target as HTMLInputElement; + const value = parseFloat(input.value); seek(value); } }