Fetch only new queue tracks from indexedDB

environments/review-docs-renov-b1i8ag/deployments/15025
wvffle 2022-10-28 12:29:58 +00:00 zatwierdzone przez Georg Krause
rodzic 9f36c4b3a8
commit f51007b807
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 2970D504B2183D22
4 zmienionych plików z 74 dodań i 34 usunięć

Wyświetl plik

@ -1,6 +1,6 @@
import { createGlobalState, tryOnMounted, useIntervalFn, useRafFn, useStorage, useTimeoutFn, whenever } from '@vueuse/core'
import { computed, nextTick, ref, watch, watchEffect, type Ref } from 'vue'
import { useTracks } from '~/composables/audio/tracks'
import { computed, ref, watch, watchEffect, type Ref } from 'vue'
import { setGain } from './audio-api'
import { useQueue, currentIndex, currentTrack } from './queue'
@ -43,6 +43,12 @@ export const usePlayer = createGlobalState(() => {
sound.pause()
})
const stop = async () => {
isPlaying.value = false
seekTo(0)
return nextTick()
}
// Create first track when we initalize the page
// NOTE: We want to have it called only once, hence we're using createGlobalState
const initializeFirstTrack = createGlobalState(() => tryOnMounted(() => {
@ -195,13 +201,14 @@ export const usePlayer = createGlobalState(() => {
return sound.isErrored.value
})
const { start, stop } = useTimeoutFn(() => playNext(), 3000, { immediate: false })
watch(currentIndex, stop)
whenever(errored, start)
const { start: startErrorTimeout, stop: stopErrorTimeout } = useTimeoutFn(() => playNext(), 3000, { immediate: false })
watch(currentIndex, stopErrorTimeout)
whenever(errored, startErrorTimeout)
return {
initializeFirstTrack,
isPlaying,
stop,
volume,
mute,
looping,

Wyświetl plik

@ -1,12 +1,12 @@
import type { Track, Upload } from '~/types'
import { computedAsync, createGlobalState, useNow, useStorage, useTimeAgo } from '@vueuse/core'
import { shuffle as shuffleArray, sum, uniq } from 'lodash-es'
import { createGlobalState, useNow, useStorage, useTimeAgo, whenever } from '@vueuse/core'
import { shuffle as shuffleArray, sum } from 'lodash-es'
import { computed, ref, shallowReactive, watchEffect } from 'vue'
import { getMany, setMany } from 'idb-keyval'
import { computed, watchEffect } from 'vue'
import { useClamp } from '@vueuse/math'
import { looping, LoopingMode, isPlaying } from '~/composables/audio/player'
import { looping, LoopingMode, isPlaying, usePlayer } from '~/composables/audio/player'
import { useStore } from '~/store'
import axios from 'axios'
@ -44,22 +44,45 @@ const shuffledIds = useStorage('queue:tracks:shuffled', [] as number[])
const isShuffled = computed(() => shuffledIds.value.length !== 0)
const tracksById = computedAsync(async () => {
const trackObjects = await getMany(uniq(tracks.value))
return trackObjects.reduce((acc, track) => {
acc[track.id] = track
return acc
}, {}) as Record<number, QueueTrack>
}, {})
const tracksById = shallowReactive(new Map<number, QueueTrack>())
const fetchingTracks = ref(false)
watchEffect(async () => {
if (fetchingTracks.value) return
const queue = computed(() => {
const indexedTracks = tracksById.value
const allTracks = new Set(tracks.value)
const addedIds = new Set(allTracks)
if (isShuffled.value) {
return shuffledIds.value.map(id => indexedTracks[id]).filter(i => i)
for (const id of tracksById.keys()) {
if (allTracks.has(id)) {
// Track in queue, so remove it from the new ids set
addedIds.delete(id)
} else {
// Track removed from queue, so remove it from the object
tracksById.delete(id)
}
}
return tracks.value.map(id => indexedTracks[id]).filter(i => i)
if (addedIds.size > 0) {
fetchingTracks.value = true
try {
const trackInfos: QueueTrack[] = await getMany([...addedIds])
for (const track of trackInfos) {
tracksById.set(track.id, track)
}
} catch (error) {
console.error(error)
} finally {
fetchingTracks.value = false
}
}
})
const queue = computed<QueueTrack[]>(() => {
const ids = isShuffled.value
? shuffledIds.value
: tracks.value
return ids.map(id => tracksById.get(id)).filter((i): i is QueueTrack => !!i)
})
// Current Index
@ -235,7 +258,11 @@ export const useQueue = createGlobalState(() => {
}))
// Clear
const clearRadio = ref(false)
const clear = async () => {
const { stop } = usePlayer()
await stop()
clearRadio.value = true
tracks.value.length = 0
}
@ -249,8 +276,9 @@ export const useQueue = createGlobalState(() => {
}
})
watchEffect(() => {
if (tracks.value.length === 0) {
whenever(clearRadio, () => {
clearRadio.value = false
if (store.state.radios.running) {
return store.dispatch('radios/stop')
}
})

Wyświetl plik

@ -1,13 +1,13 @@
import type { QueueTrack, QueueTrackSource } from '~/composables/audio/queue'
import type { Sound } from '~/api/player'
import { soundImplementation } from '~/api/player'
import { createGlobalState, syncRef } from '@vueuse/core'
import { computed, ref, watch } from 'vue'
import { createGlobalState, syncRef, whenever } from '@vueuse/core'
import { computed, ref } from 'vue'
import { useQueue } from '~/composables/audio/queue'
import { connectAudioSource } from '~/composables/audio/audio-api'
import { usePlayer } from '~/composables/audio/player'
import { useQueue } from '~/composables/audio/queue'
import { soundImplementation } from '~/api/player'
import useLRUCache from '~/composables/useLRUCache'
import store from '~/store'
@ -112,8 +112,9 @@ export const useTracks = createGlobalState(() => {
// NOTE: We want to have it called only once, hence we're using createGlobalState
const initialize = createGlobalState(() => {
const { currentTrack: track, currentIndex } = useQueue()
watch(currentIndex, (index) => createTrack(index))
const { currentIndex, currentTrack: track } = useQueue()
whenever(track, () => createTrack(currentIndex.value))
syncRef(track, currentTrack, {
direction: 'ltr'
})

Wyświetl plik

@ -164,21 +164,25 @@ export default (props: PlayOptionsProps) => {
const tracksToPlay = await getPlayableTracks()
await addToQueue(...tracksToPlay)
const trackIndex = props.tracks?.findIndex(track => track.id === props.track?.id && track.position === props.track?.position) ?? 0
await playTrack(trackIndex)
if (props.track && props.tracks?.length) {
const trackIndex = props.tracks?.findIndex(track => track.id === props.track?.id && track.position === props.track?.position) ?? 0
await playTrack(trackIndex)
isPlaying.value = true
} else {
await playTrack(0, true)
isPlaying.value = true
}
isPlaying.value = true
playTrack(0, true)
addMessage(tracksToPlay)
}
const activateTrack = (track: Track, index: number) => {
const activateTrack = async (track: Track, index: number) => {
// TODO (wvffle): Check if position checking did not break anything
if (track.id === currentTrack.value?.id && track.position === currentTrack.value?.position) {
isPlaying.value = true
}
replacePlay()
return replacePlay()
}
return {