Skip to content
Snippets Groups Projects
Verified Commit 39b473f1 authored by Eliot Berriot's avatar Eliot Berriot
Browse files

Fixed #310: current track restart/hiccup when shuffling queue, deleting track...

Fixed #310: current track restart/hiccup when shuffling queue, deleting track from queue or reordering
parent b2a876b4
No related branches found
No related tags found
No related merge requests found
Fixed current track restart/hiccup when shuffling queue, deleting track from queue or reordering (#310)
......@@ -116,8 +116,8 @@
</div>
<div class="ui bottom attached tab" data-tab="queue">
<table class="ui compact inverted very basic fixed single line unstackable table">
<draggable v-model="queue.tracks" element="tbody" @update="reorder">
<tr @click="$store.dispatch('queue/currentIndex', index)" v-for="(track, index) in queue.tracks" :key="index" :class="[{'active': index === queue.currentIndex}]">
<draggable v-model="tracks" element="tbody" @update="reorder">
<tr @click="$store.dispatch('queue/currentIndex', index)" v-for="(track, index) in tracks" :key="index" :class="[{'active': index === queue.currentIndex}]">
<td class="right aligned">{{ index + 1}}</td>
<td class="center aligned">
<img class="ui mini image" v-if="track.album.cover" :src="$store.getters['instance/absoluteUrl'](track.album.cover)">
......@@ -176,6 +176,7 @@ export default {
return {
selectedTab: 'library',
backend: backend,
tracksChangeBuffer: null,
isCollapsed: true,
fetchInterval: null
}
......@@ -207,6 +208,14 @@ export default {
return adminPermissions.filter(e => {
return e
}).length > 0
},
tracks: {
get () {
return this.$store.state.queue.tracks
},
set (value) {
this.tracksChangeBuffer = value
}
}
},
methods: {
......@@ -219,7 +228,7 @@ export default {
},
reorder: function (event) {
this.$store.commit('queue/reorder', {
oldIndex: event.oldIndex, newIndex: event.newIndex})
tracks: this.tracksChangeBuffer, oldIndex: event.oldIndex, newIndex: event.newIndex})
},
scrollToCurrent () {
let current = $(this.$el).find('[data-tab="queue"] .active')[0]
......
<template>
<div class="ui inverted segment player-wrapper" :style="style">
<div class="player">
<audio-track
ref="currentAudio"
v-if="renderAudio && currentTrack"
:key="currentTrack.id"
:is-current="true"
:start-time="$store.state.player.currentTime"
:autoplay="$store.state.player.playing"
:track="currentTrack">
</audio-track>
<keep-alive>
<audio-track
ref="currentAudio"
v-if="renderAudio && currentTrack"
:is-current="true"
:start-time="$store.state.player.currentTime"
:autoplay="$store.state.player.playing"
:track="currentTrack">
</audio-track>
</keep-alive>
<div v-if="currentTrack" class="track-area ui unstackable items">
<div class="ui inverted item">
<div class="ui tiny image">
......
......@@ -4,7 +4,7 @@
@error="errored"
@loadeddata="loaded"
@durationchange="updateDuration"
@timeupdate="updateProgress"
@timeupdate="updateProgressThrottled"
@ended="ended"
preload>
<source
......@@ -30,6 +30,7 @@ export default {
},
data () {
return {
realTrack: this.track,
sourceErrors: 0,
isUpdatingTime: false
}
......@@ -43,7 +44,7 @@ export default {
looping: state => state.player.looping
}),
srcs: function () {
let file = this.track.files[0]
let file = this.realTrack.files[0]
if (!file) {
this.$store.dispatch('player/trackErrored')
return []
......@@ -61,6 +62,9 @@ export default {
})
}
return sources
},
updateProgressThrottled () {
return _.throttle(this.updateProgress, 250)
}
},
methods: {
......@@ -100,30 +104,40 @@ export default {
}
}
},
updateProgress: _.throttle(function () {
updateProgress: function () {
this.isUpdatingTime = true
if (this.$refs.audio) {
this.$store.dispatch('player/updateProgress', this.$refs.audio.currentTime)
}
}, 250),
},
ended: function () {
let onlyTrack = this.$store.state.queue.tracks.length === 1
if (this.looping === 1 || (onlyTrack && this.looping === 2)) {
this.setCurrentTime(0)
this.$refs.audio.play()
} else {
this.$store.dispatch('player/trackEnded', this.track)
this.$store.dispatch('player/trackEnded', this.realTrack)
}
},
setCurrentTime (t) {
if (t < 0 | t > this.duration) {
return
}
this.updateProgress(t)
if (t === this.$refs.audio.currentTime) {
return
}
if (t === 0) {
this.updateProgressThrottled.cancel()
}
this.$refs.audio.currentTime = t
}
},
watch: {
track: _.debounce(function (newValue) {
this.realTrack = newValue
this.setCurrentTime(0)
this.$refs.audio.load()
}, 1000, {leading: true, trailing: true}),
playing: function (newValue) {
if (newValue === true) {
this.$refs.audio.play()
......@@ -131,6 +145,11 @@ export default {
this.$refs.audio.pause()
}
},
'$store.state.queue.currentIndex' () {
if (this.$store.state.player.playing) {
this.$refs.audio.play()
}
},
volume: function (newValue) {
this.$refs.audio.volume = newValue
},
......
......@@ -31,9 +31,10 @@ export default {
insert (state, {track, index}) {
state.tracks.splice(index, 0, track)
},
reorder (state, {oldIndex, newIndex}) {
reorder (state, {tracks, oldIndex, newIndex}) {
// called when the user uses drag / drop to reorder
// tracks in queue
state.tracks = tracks
if (oldIndex === state.currentIndex) {
state.currentIndex = newIndex
return
......@@ -102,7 +103,7 @@ export default {
}
if (current) {
// we play next track, which now have the same index
dispatch('currentIndex', index)
commit('currentIndex', index)
}
if (state.currentIndex + 1 === state.tracks.length) {
dispatch('radios/populateQueue', null, {root: true})
......@@ -156,7 +157,6 @@ export default {
let toKeep = state.tracks.slice(0, state.currentIndex + 1)
let toShuffle = state.tracks.slice(state.currentIndex + 1)
let shuffled = toKeep.concat(_.shuffle(toShuffle))
commit('player/currentTime', 0, {root: true})
commit('tracks', [])
let params = {tracks: shuffled}
if (callback) {
......
......@@ -169,11 +169,11 @@ describe('store/queue', () => {
payload: 2,
params: {state: {currentIndex: 2}},
expectedMutations: [
{ type: 'splice', payload: {start: 2, size: 1} }
{ type: 'splice', payload: {start: 2, size: 1} },
{ type: 'currentIndex', payload: 2 }
],
expectedActions: [
{ type: 'player/stop', payload: null, options: {root: true} },
{ type: 'currentIndex', payload: 2 }
{ type: 'player/stop', payload: null, options: {root: true} }
]
}, done)
})
......@@ -324,7 +324,6 @@ describe('store/queue', () => {
action: store.actions.shuffle,
params: {state: {currentIndex: 1, tracks: tracks}},
expectedMutations: [
{ type: 'player/currentTime', payload: 0, options: {root: true} },
{ type: 'tracks', payload: [] }
],
expectedActions: [
......
import store from '@/store/ui'
import { testAction } from '../../utils'
describe('store/ui', () => {
describe('mutations', () => {
it('addMessage', () => {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment