diff --git a/front/src/components/Queue.vue b/front/src/components/Queue.vue
index 8a6f748b7..1f35df1d8 100644
--- a/front/src/components/Queue.vue
+++ b/front/src/components/Queue.vue
@@ -220,13 +220,11 @@ const touchProgress = (event: MouseEvent) => {
>
diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue
index 7fca3d0fe..b317dc71c 100644
--- a/front/src/components/audio/Player.vue
+++ b/front/src/components/audio/Player.vue
@@ -117,13 +117,11 @@ const switchTab = () => {
>
diff --git a/front/src/composables/audio/usePlayer.ts b/front/src/composables/audio/usePlayer.ts
index 7b3c769d7..3d5fd215c 100644
--- a/front/src/composables/audio/usePlayer.ts
+++ b/front/src/composables/audio/usePlayer.ts
@@ -2,7 +2,7 @@ import type { Track } from '~/types'
import { computed, watchEffect, ref, watch } from 'vue'
import { Howler } from 'howler'
-import { useIntervalFn, useTimeoutFn } from '@vueuse/core'
+import { useRafFn, useTimeoutFn } from '@vueuse/core'
import useQueue from '~/composables/audio/useQueue'
import useSound from '~/composables/audio/useSound'
import toLinearVolumeScale from '~/composables/audio/toLinearVolumeScale'
@@ -119,36 +119,36 @@ const progress = computed({
get: () => store.getters['player/progress'],
set: (time) => {
if (currentSound.value?.state() === 'loaded') {
+ store.state.player.currentTime = time
+
const duration = currentSound.value.duration()
-
- store.dispatch('player/updateProgress', time)
- currentSound.value._triggerSoundProgress()
-
- const toPreload = store.state.queue.tracks[currentIndex.value + 1]
- if (!nextTrackPreloaded.value && toPreload && (time > PRELOAD_DELAY || duration - time < 30)) {
- loadSound(toPreload)
- nextTrackPreloaded.value = true
- }
-
- if (time > duration / 2) {
- if (!isListeningSubmitted.value) {
- store.dispatch('player/trackListened', currentTrack.value)
- isListeningSubmitted.value = true
- }
- }
+ currentSound.value.triggerSoundProgress(time, duration)
}
}
})
const bufferProgress = computed(() => store.state.player.bufferProgress)
-onSoundProgress((node: HTMLAudioElement) => {
+onSoundProgress(({ node, time, duration }) => {
+ const toPreload = store.state.queue.tracks[currentIndex.value + 1]
+ if (!nextTrackPreloaded.value && toPreload && (time > PRELOAD_DELAY || duration - time < 30)) {
+ loadSound(toPreload)
+ nextTrackPreloaded.value = true
+ }
+
+ if (time > duration / 2) {
+ if (!isListeningSubmitted.value) {
+ store.dispatch('player/trackListened', currentTrack.value)
+ isListeningSubmitted.value = true
+ }
+ }
+
// from https://github.com/goldfire/howler.js/issues/752#issuecomment-372083163
- const { buffered, currentTime: time } = node
+ const { buffered, currentTime } = node
let range = 0
try {
- while (buffered.start(range) >= time || time >= buffered.end(range)) {
+ while (buffered.start(range) >= currentTime || currentTime >= buffered.end(range)) {
range += 1
}
} catch (IndexSizeError) {
@@ -181,11 +181,11 @@ onSoundProgress((node: HTMLAudioElement) => {
})
const observeProgress = ref(false)
-useIntervalFn(() => {
+useRafFn(() => {
if (observeProgress.value && currentSound.value?.state() === 'loaded') {
progress.value = currentSound.value.seek()
}
-}, 1000)
+})
watch(playing, async (isPlaying) => {
if (currentSound.value) {
diff --git a/front/src/composables/audio/useSound.ts b/front/src/composables/audio/useSound.ts
index 6d530a8f6..d9f824f0c 100644
--- a/front/src/composables/audio/useSound.ts
+++ b/front/src/composables/audio/useSound.ts
@@ -6,7 +6,7 @@ import useTrackSources from '~/composables/audio/useTrackSources'
import useSoundCache from '~/composables/audio/useSoundCache'
import usePlayer from '~/composables/audio/usePlayer'
import store from '~/store'
-import { createEventHook } from '@vueuse/core'
+import { createEventHook, useThrottleFn } from '@vueuse/core'
interface Sound {
id?: number
@@ -18,7 +18,7 @@ interface Sound {
seek: (time?: number) => number
duration: () => number
getSource: () => boolean
- _triggerSoundProgress: () => void
+ triggerSoundProgress: (time: number, duration: number) => void
}
const soundCache = useSoundCache()
@@ -28,7 +28,7 @@ const looping = computed(() => store.state.player.looping)
const currentSound = ref()
const soundId = ref()
-const soundProgress = createEventHook()
+const soundProgress = createEventHook<{ node: HTMLAudioElement, time: number, duration: number }>()
const createSound = (howl: Howl): Sound => ({
howl,
@@ -46,7 +46,7 @@ const createSound = (howl: Howl): Sound => ({
seek: (time?: number) => howl.seek(time),
duration: () => howl.duration(),
getSource: () => (howl as any)._sounds[0],
- _triggerSoundProgress: () => soundProgress.trigger((howl as any)._sounds[0]._node)
+ triggerSoundProgress: useThrottleFn((time: number, duration: number) => soundProgress.trigger({ node: (howl as any)._sounds[0]._node, time, duration }), 1000)
})
const loadSound = (track: Track): Sound => {
diff --git a/front/src/style/components/_player.scss b/front/src/style/components/_player.scss
index c261bb07f..2663bce49 100644
--- a/front/src/style/components/_player.scss
+++ b/front/src/style/components/_player.scss
@@ -37,7 +37,11 @@
}
.ui.progress .bar {
- transition: none;
+ transition: transform .2s linear;
+ width: 100%;
+ transform: scaleX(0);
+ transform-origin: top left;
+ will-change: transform;
}
.ui.progress .buffer.bar {
@@ -72,10 +76,9 @@
animation-timing-function: linear;
animation-iteration-count: infinite;
}
- .ui.progress:not([data-percent]):not(.indeterminate)
+ .ui.progress:not(.indeterminate)
.bar.position:not(.buffer) {
background: var(--vibrant-color);
- min-width: 0;
}
.track-controls {
diff --git a/front/src/style/components/_queue.scss b/front/src/style/components/_queue.scss
index b2bcde76b..f7fb4e7f1 100644
--- a/front/src/style/components/_queue.scss
+++ b/front/src/style/components/_queue.scss
@@ -163,15 +163,25 @@
.progress-area {
overflow: hidden;
}
+ .progress-area .progress {
+ border-radius: 0.28571429rem;
+ }
.progress-wrapper, .warning.message {
max-width: 25em;
margin: 0 auto;
}
+ .ui.progress .bar {
+ transition: transform .2s linear;
+ width: 100%;
+ transform: scaleX(0);
+ transform-origin: top left;
+ will-change: transform;
+ }
.ui.progress .buffer.bar {
position: absolute;
background-color: rgba(255, 255, 255, 0.15);
}
- .ui.progress:not([data-percent]):not(.indeterminate)
+ .ui.progress:not(.indeterminate)
.bar.position:not(.buffer) {
background: var(--vibrant-color);
}
@@ -201,9 +211,6 @@
}
.progress {
cursor: pointer;
- .bar {
- min-width: 0 !important;
- }
}
.player-controls {