add shuffle and repeat toggle
This commit is contained in:
parent
554d58f04b
commit
c751194c16
@ -44,10 +44,21 @@
|
|||||||
</b-button>
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Time --->
|
<!-- Controls right --->
|
||||||
<div class="col p-0 d-none d-sm-block" style="min-width: 0; width: 0;">
|
<div class="col p-0 d-none d-sm-block " style="min-width: 0; width: 0;">
|
||||||
<div v-if="track" class="pr-3 text-right text-truncate">
|
<div class="d-flex justify-content-end pr-3">
|
||||||
{{ $formatDuration(currentTime) }} / {{ $formatDuration(duration) }}
|
<b-button variant="link"
|
||||||
|
class="m-0 d-none d-sm-inline-block"
|
||||||
|
:class="{ 'text-primary': shuffleActive }"
|
||||||
|
@click="toggleShuffle">
|
||||||
|
<Icon icon="shuffle" />
|
||||||
|
</b-button>
|
||||||
|
<b-button variant="link"
|
||||||
|
class="m-0 d-none d-sm-inline-block "
|
||||||
|
:class="{ 'text-primary': repeatActive }"
|
||||||
|
@click="toggleRepeat">
|
||||||
|
<Icon icon="arrow-repeat" />
|
||||||
|
</b-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -81,7 +92,8 @@
|
|||||||
...mapState('player', {
|
...mapState('player', {
|
||||||
isPlaying: (state: any) => state.isPlaying,
|
isPlaying: (state: any) => state.isPlaying,
|
||||||
currentTime: (state: any) => state.currentTime,
|
currentTime: (state: any) => state.currentTime,
|
||||||
duration: (state: any) => state.duration,
|
repeatActive: (state: any) => state.repeat,
|
||||||
|
shuffleActive: (state: any) => state.shuffle,
|
||||||
visible: (state: any) => state.queue.length > 0,
|
visible: (state: any) => state.queue.length > 0,
|
||||||
}),
|
}),
|
||||||
...mapGetters('player', [
|
...mapGetters('player', [
|
||||||
@ -94,6 +106,8 @@
|
|||||||
'playPause',
|
'playPause',
|
||||||
'next',
|
'next',
|
||||||
'previous',
|
'previous',
|
||||||
|
'toggleRepeat',
|
||||||
|
'toggleShuffle',
|
||||||
]),
|
]),
|
||||||
seek(event: any) {
|
seek(event: any) {
|
||||||
if (event.target) {
|
if (event.target) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Store, Module } from 'vuex'
|
import { Store, Module } from 'vuex'
|
||||||
import { trackListEquals } from '@/shared/utils'
|
import { shuffle, trackListEquals } from '@/shared/utils'
|
||||||
|
|
||||||
const audio = new Audio()
|
const audio = new Audio()
|
||||||
const storedQueue = JSON.parse(localStorage.getItem('queue') || '[]')
|
const storedQueue = JSON.parse(localStorage.getItem('queue') || '[]')
|
||||||
@ -15,6 +15,8 @@ interface State {
|
|||||||
isPlaying: boolean;
|
isPlaying: boolean;
|
||||||
duration: number; // duration of current track in seconds
|
duration: number; // duration of current track in seconds
|
||||||
currentTime: number; // position of current track in seconds
|
currentTime: number; // position of current track in seconds
|
||||||
|
repeat: boolean;
|
||||||
|
shuffle: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const playerModule: Module<State, any> = {
|
export const playerModule: Module<State, any> = {
|
||||||
@ -25,6 +27,8 @@ export const playerModule: Module<State, any> = {
|
|||||||
isPlaying: false,
|
isPlaying: false,
|
||||||
duration: 0,
|
duration: 0,
|
||||||
currentTime: 0,
|
currentTime: 0,
|
||||||
|
repeat: localStorage.getItem('player.repeat') !== 'false',
|
||||||
|
shuffle: localStorage.getItem('player.shuffle') === 'true',
|
||||||
},
|
},
|
||||||
|
|
||||||
mutations: {
|
mutations: {
|
||||||
@ -43,6 +47,14 @@ export const playerModule: Module<State, any> = {
|
|||||||
setPosition(state, time: number) {
|
setPosition(state, time: number) {
|
||||||
audio.currentTime = time
|
audio.currentTime = time
|
||||||
},
|
},
|
||||||
|
setRepeat(state, enable) {
|
||||||
|
state.repeat = enable
|
||||||
|
localStorage.setItem('player.repeat', enable)
|
||||||
|
},
|
||||||
|
setShuffle(state, enable) {
|
||||||
|
state.shuffle = enable
|
||||||
|
localStorage.setItem('player.shuffle', enable)
|
||||||
|
},
|
||||||
setQueue(state, queue) {
|
setQueue(state, queue) {
|
||||||
state.queue = queue
|
state.queue = queue
|
||||||
state.queueIndex = -1
|
state.queueIndex = -1
|
||||||
@ -89,12 +101,25 @@ export const playerModule: Module<State, any> = {
|
|||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
async playTrackList({ commit, state }, { tracks, index }) {
|
async playTrackList({ commit, state }, { tracks, index }) {
|
||||||
if (!trackListEquals(state.queue, tracks)) {
|
if (trackListEquals(state.queue, tracks)) {
|
||||||
commit('setQueue', [...tracks])
|
|
||||||
}
|
|
||||||
commit('setQueueIndex', index)
|
commit('setQueueIndex', index)
|
||||||
commit('setPlaying')
|
commit('setPlaying')
|
||||||
await audio.play()
|
await audio.play()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tracks = [...tracks]
|
||||||
|
if (state.shuffle) {
|
||||||
|
const selected = tracks[index]
|
||||||
|
tracks.splice(index, 1)
|
||||||
|
tracks = [selected, ...shuffle(tracks)]
|
||||||
|
commit('setQueue', tracks)
|
||||||
|
commit('setQueueIndex', 0)
|
||||||
|
} else {
|
||||||
|
commit('setQueue', tracks)
|
||||||
|
commit('setQueueIndex', index)
|
||||||
|
}
|
||||||
|
commit('setPlaying')
|
||||||
|
await audio.play()
|
||||||
},
|
},
|
||||||
async resume({ commit }) {
|
async resume({ commit }) {
|
||||||
commit('setPlaying')
|
commit('setPlaying')
|
||||||
@ -125,6 +150,16 @@ export const playerModule: Module<State, any> = {
|
|||||||
commit('setPosition', state.duration * value)
|
commit('setPosition', state.duration * value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
resetQueue({ commit }) {
|
||||||
|
audio.pause()
|
||||||
|
commit('setQueueIndex', 0)
|
||||||
|
commit('setPaused')
|
||||||
|
},
|
||||||
|
toggleRepeat({ commit, state }) {
|
||||||
|
commit('setRepeat', !state.repeat)
|
||||||
|
},
|
||||||
|
toggleShuffle({ commit, state }) {
|
||||||
|
commit('setShuffle', !state.shuffle)
|
||||||
},
|
},
|
||||||
addToQueue({ commit }, track) {
|
addToQueue({ commit }, track) {
|
||||||
commit('addToQueue', track)
|
commit('addToQueue', track)
|
||||||
@ -167,7 +202,11 @@ export function setupAudio(store: Store<any>) {
|
|||||||
store.commit('player/setDuration', audio.duration)
|
store.commit('player/setDuration', audio.duration)
|
||||||
}
|
}
|
||||||
audio.onended = () => {
|
audio.onended = () => {
|
||||||
|
if (store.state.repeat) {
|
||||||
store.dispatch('player/next')
|
store.dispatch('player/next')
|
||||||
|
} else {
|
||||||
|
store.dispatch('player/resetQueue')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
audio.onerror = () => {
|
audio.onerror = () => {
|
||||||
store.commit('player/setPaused')
|
store.commit('player/setPaused')
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import {
|
import {
|
||||||
BIcon,
|
BIcon,
|
||||||
|
BIconArrowRepeat,
|
||||||
BIconBoxArrowUpRight,
|
BIconBoxArrowUpRight,
|
||||||
BIconBroadcast,
|
BIconBroadcast,
|
||||||
BIconCardText,
|
BIconCardText,
|
||||||
@ -17,6 +18,7 @@
|
|||||||
BIconList,
|
BIconList,
|
||||||
BIconPlayFill,
|
BIconPlayFill,
|
||||||
BIconPauseFill,
|
BIconPauseFill,
|
||||||
|
BIconShuffle,
|
||||||
BIconSkipStartFill,
|
BIconSkipStartFill,
|
||||||
BIconSkipEndFill,
|
BIconSkipEndFill,
|
||||||
BIconPlus,
|
BIconPlus,
|
||||||
@ -30,6 +32,7 @@
|
|||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
components: {
|
components: {
|
||||||
BIcon,
|
BIcon,
|
||||||
|
BIconArrowRepeat,
|
||||||
BIconBoxArrowUpRight,
|
BIconBoxArrowUpRight,
|
||||||
BIconBroadcast,
|
BIconBroadcast,
|
||||||
BIconCardText,
|
BIconCardText,
|
||||||
@ -42,6 +45,7 @@
|
|||||||
BIconList,
|
BIconList,
|
||||||
BIconPlayFill,
|
BIconPlayFill,
|
||||||
BIconPauseFill,
|
BIconPauseFill,
|
||||||
|
BIconShuffle,
|
||||||
BIconSkipStartFill,
|
BIconSkipStartFill,
|
||||||
BIconSkipEndFill,
|
BIconSkipEndFill,
|
||||||
BIconPlus,
|
BIconPlus,
|
||||||
|
@ -9,6 +9,14 @@ export function randomString(): string {
|
|||||||
return String.fromCharCode.apply(null, Array.from(arr))
|
return String.fromCharCode.apply(null, Array.from(arr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shuffle(a: any[]) {
|
||||||
|
for (let i = a.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[a[i], a[j]] = [a[j], a[i]]
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
export function md5(str: string): string {
|
export function md5(str: string): string {
|
||||||
return MD5.hash(str)
|
return MD5.hash(str)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user