funkwhale/front/src/composables/audio/useQueue.ts

113 lines
2.5 KiB
TypeScript

import type { Track } from "~/types"
import { useTimeoutFn, useThrottleFn, useTimeAgo, useNow, whenever } from '@vueuse/core'
import { Howler } from 'howler'
import { gettext } from '~/init/locale'
import { ref, computed } from "vue"
import { sum } from 'lodash-es'
import store from "~/store"
const { $pgettext } = gettext
const currentTrack = computed(() => store.getters['queue/currentTrack'])
const currentIndex = computed(() => store.state.queue.currentIndex)
const hasNext = computed(() => store.getters['queue/hasNext'])
const hasPrevious = computed(() => store.getters['queue/hasPrevious'])
const isEmpty = computed(() => store.getters['queue/isEmpty'])
whenever(isEmpty, () => Howler.unload())
const removeTrack = (index: number) => store.dispatch('queue/cleanTrack', index)
const clear = () => store.dispatch('queue/clean')
const next = () => store.dispatch('queue/next')
const previous = () => store.dispatch('queue/previous')
const focused = computed(() => store.state.ui.queueFocused === 'queue')
//
// Track list
//
const tracksChangeBuffer = ref<Track[] | null>(null)
const tracks = computed<Track[]>({
get: () => store.state.queue.tracks,
set: (value) => (tracksChangeBuffer.value = value)
})
const reorder = (oldIndex: number, newIndex: number) => {
store.commit('queue/reorder', {
tracks: tracksChangeBuffer.value ?? tracks.value,
oldIndex,
newIndex
})
tracksChangeBuffer.value = null
}
//
// Shuffle
//
const isShuffling = ref(false)
const forceShuffle = useThrottleFn(() => {
isShuffling.value = true
useTimeoutFn(async () => {
await store.dispatch('queue/shuffle')
store.commit('ui/addMessage', {
content: $pgettext('Content/Queue/Message', 'Queue shuffled!'),
date: new Date()
})
isShuffling.value = false
}, 100)
})
const shuffle = useThrottleFn(() => {
if (isShuffling.value || isEmpty.value) {
return
}
return forceShuffle()
}, 101, false)
//
// Time left
//
const now = useNow()
const endsIn = useTimeAgo(computed(() => {
const seconds = sum(
tracks.value
.slice(currentIndex.value)
.map((track) => track.uploads?.[0]?.duration ?? 0)
)
const date = new Date(now.value)
date.setSeconds(date.getSeconds() + seconds)
return date
}))
export default () => {
return {
currentTrack,
currentIndex,
hasNext,
hasPrevious,
isEmpty,
isShuffling,
removeTrack,
clear,
next,
previous,
tracks,
reorder,
shuffle,
forceShuffle,
endsIn,
focused
}
}