diff --git a/changes/changelog.d/586.enhancement b/changes/changelog.d/586.enhancement new file mode 100644 index 000000000..bee8c1c96 --- /dev/null +++ b/changes/changelog.d/586.enhancement @@ -0,0 +1 @@ +The progress bar in the player now display loading state / buffer loading (#586) diff --git a/front/src/components/audio/Player.vue b/front/src/components/audio/Player.vue index 5387d02b7..1d622f330 100644 --- a/front/src/components/audio/Player.vue +++ b/front/src/components/audio/Player.vue @@ -51,7 +51,11 @@

{{durationFormatted}}

-
+
+
@@ -301,9 +305,11 @@ export default { ...mapState({ currentIndex: state => state.queue.currentIndex, playing: state => state.player.playing, + isLoadingAudio: state => state.player.isLoadingAudio, volume: state => state.player.volume, looping: state => state.player.looping, duration: state => state.player.duration, + bufferProgress: state => state.player.bufferProgress, queue: state => state.queue }), ...mapGetters({ @@ -522,4 +528,43 @@ export default { margin: 0; } + +@keyframes MOVE-BG { + from { + transform: translateX(0px); + } + to { + transform: translateX(46px); + } +} + +.indicating.progress { + overflow: hidden; +} + +.ui.progress .bar { + transition: none; +} + +.ui.inverted.progress .buffer.bar { + position: absolute; + background-color:rgba(255, 255, 255, 0.15); +} +.indicating.progress .bar { + left: -46px; + width: 200% !important; + color: grey; + background: repeating-linear-gradient( + -55deg, + grey 1px, + grey 10px, + transparent 10px, + transparent 20px, + ) !important; + + animation-name: MOVE-BG; + animation-duration: 2s; + animation-timing-function: linear; + animation-iteration-count: infinite; +} diff --git a/front/src/components/audio/Track.vue b/front/src/components/audio/Track.vue index 5626dd4d8..32eb62722 100644 --- a/front/src/components/audio/Track.vue +++ b/front/src/components/audio/Track.vue @@ -44,11 +44,17 @@ export default { } }, onload: function () { + self.$store.commit('player/isLoadingAudio', false) self.$store.commit('player/resetErrorCount') self.$store.commit('player/duration', self.sound.duration()) + let node = self.sound._sounds[0]._node; + node.addEventListener('progress', () => { + self.updateBuffer(node) + }) } }) if (this.autoplay) { + self.$store.commit('player/isLoadingAudio', true) this.sound.play() this.$store.commit('player/playing', true) this.observeProgress(true) @@ -91,10 +97,40 @@ export default { } }, methods: { + updateBuffer (node) { + // from https://github.com/goldfire/howler.js/issues/752#issuecomment-372083163 + let range = 0; + let bf = node.buffered; + let time = node.currentTime; + try { + while(!(bf.start(range) <= time && time <= bf.end(range))) { + range += 1; + } + } catch (IndexSizeError) { + return + } + let loadPercentage + let start = bf.start(range) + let end = bf.end(range) + if (range === 0) { + // easy case, no user-seek + let loadStartPercentage = start / node.duration; + let loadEndPercentage = end / node.duration; + loadPercentage = loadEndPercentage - loadStartPercentage; + } else { + let loaded = end - start + let remainingToLoad = node.duration - start + // user seeked a specific position in the audio, our progress must be + // computed based on the remaining portion of the track + loadPercentage = loaded / remainingToLoad; + } + this.$store.commit('player/bufferProgress', loadPercentage * 100) + }, updateProgress: function () { this.isUpdatingTime = true if (this.sound && this.sound.state() === 'loaded') { this.$store.dispatch('player/updateProgress', this.sound.seek()) + this.updateBuffer(this.sound._sounds[0]._node) } }, observeProgress: function (enable) { diff --git a/front/src/store/player.js b/front/src/store/player.js index dc01f368b..08492541e 100644 --- a/front/src/store/player.js +++ b/front/src/store/player.js @@ -8,11 +8,13 @@ export default { maxConsecutiveErrors: 5, errorCount: 0, playing: false, + isLoadingAudio: false, volume: 0.5, tempVolume: 0.5, duration: 0, currentTime: 0, errored: false, + bufferProgress: 0, looping: 0 // 0 -> no, 1 -> on track, 2 -> on queue }, mutations: { @@ -59,12 +61,18 @@ export default { playing (state, value) { state.playing = value }, + bufferProgress (state, value) { + state.bufferProgress = value + }, toggleLooping (state) { if (state.looping > 1) { state.looping = 0 } else { state.looping += 1 } + }, + isLoadingAudio (state, value) { + state.isLoadingAudio = value } }, getters: {