Fix changing songs and add LRU cache
This commit is contained in:
parent
ccb905b004
commit
1be6701752
|
@ -84,7 +84,7 @@ ports:
|
|||
|
||||
vscode:
|
||||
extensions:
|
||||
- lukashass.volar
|
||||
- Vue.volar
|
||||
- ms-python.python
|
||||
- ms-toolsai.jupyter
|
||||
- ms-toolsai.jupyter-keymap
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"Vue.volar"
|
||||
]
|
||||
}
|
|
@ -36,6 +36,7 @@
|
|||
"idb-keyval": "^6.2.0",
|
||||
"js-logger": "1.6.1",
|
||||
"lodash-es": "4.17.21",
|
||||
"lru-cache": "^7.14.0",
|
||||
"moment": "2.29.4",
|
||||
"qs": "6.11.0",
|
||||
"showdown": "2.1.0",
|
||||
|
|
|
@ -8,12 +8,11 @@ import store from '~/store'
|
|||
import axios from 'axios'
|
||||
|
||||
export const isPlaying = ref(false)
|
||||
|
||||
watch(isPlaying, (playing) => {
|
||||
watchEffect(() => {
|
||||
const sound = currentSound.value
|
||||
if (!sound) return
|
||||
|
||||
if (playing) {
|
||||
if (isPlaying.value) {
|
||||
sound.play()
|
||||
return
|
||||
}
|
||||
|
|
|
@ -85,12 +85,19 @@ const createQueueTrack = async (track: Track): Promise<QueueTrack> => {
|
|||
}
|
||||
|
||||
// Adding tracks
|
||||
export const enqueue = async (...newTracks: Track[]) => {
|
||||
export const enqueueAt = async (index: number, ...newTracks: Track[]) => {
|
||||
const queueTracks = await Promise.all(newTracks.map(createQueueTrack))
|
||||
await setMany(queueTracks.map(track => [track.id, track]))
|
||||
|
||||
const ids = queueTracks.map(track => track.id)
|
||||
|
||||
if (index >= tracks.value.length) {
|
||||
// we simply push to the end
|
||||
tracks.value.push(...ids)
|
||||
} else {
|
||||
// we insert the track at given position
|
||||
tracks.value.splice(index, 0, ...ids)
|
||||
}
|
||||
|
||||
// Shuffle new tracks
|
||||
if (isShuffled.value) {
|
||||
|
@ -98,6 +105,10 @@ export const enqueue = async (...newTracks: Track[]) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const enqueue = async (...newTracks: Track[]) => {
|
||||
return enqueueAt(tracks.value.length, ...newTracks)
|
||||
}
|
||||
|
||||
// Removing tracks
|
||||
export const dequeue = async (index: number) => {
|
||||
if (currentIndex.value === index) {
|
||||
|
@ -131,7 +142,6 @@ export const playTrack = async (trackIndex: number, force = false) => {
|
|||
}
|
||||
|
||||
currentIndex.value = trackIndex
|
||||
if (isPlaying.value) currentSound.value?.play()
|
||||
}
|
||||
|
||||
// Previous track
|
||||
|
@ -198,6 +208,15 @@ export const shuffle = () => {
|
|||
shuffledIds.value = shuffleArray(tracks.value)
|
||||
}
|
||||
|
||||
export const reshuffleUpcomingTracks = () => {
|
||||
// TODO: Test if needed to add 1 to currentIndex
|
||||
const listenedTracks = shuffledIds.value.slice(0, currentIndex.value)
|
||||
const upcomingTracks = shuffledIds.value.slice(currentIndex.value)
|
||||
|
||||
listenedTracks.push(...shuffleArray(upcomingTracks))
|
||||
shuffledIds.value = listenedTracks
|
||||
}
|
||||
|
||||
// Ends in
|
||||
const now = useNow()
|
||||
export const endsIn = useTimeAgo(computed(() => {
|
||||
|
|
|
@ -2,18 +2,20 @@ import type { QueueTrack, QueueTrackSource } from '~/composables/audio/queue'
|
|||
import type { Sound } from '~/api/player'
|
||||
|
||||
import { soundImplementation } from '~/api/player'
|
||||
import { computed, shallowReactive } from 'vue'
|
||||
import { computed, watchEffect } from 'vue'
|
||||
|
||||
import { playNext, queue, currentTrack, currentIndex } from '~/composables/audio/queue'
|
||||
import { connectAudioSource } from '~/composables/audio/audio-api'
|
||||
import { isPlaying } from '~/composables/audio/player'
|
||||
|
||||
import useLRUCache from '~/composables/useLRUCache'
|
||||
import store from '~/store'
|
||||
|
||||
const ALLOWED_PLAY_TYPES: (CanPlayTypeResult | undefined)[] = ['maybe', 'probably']
|
||||
const AUDIO_ELEMENT = document.createElement('audio')
|
||||
|
||||
const soundPromises = new Map<number, Promise<Sound>>()
|
||||
const soundCache = shallowReactive(new Map<number, Sound>())
|
||||
const soundCache = useLRUCache<number, Sound>({ max: 10 })
|
||||
|
||||
const getTrackSources = (track: QueueTrack): QueueTrackSource[] => {
|
||||
const sources: QueueTrackSource[] = track.sources
|
||||
|
@ -60,7 +62,6 @@ export const createSound = async (track: QueueTrack): Promise<Sound> => {
|
|||
// NOTE: We push it to the end of the job queue
|
||||
setTimeout(playNext, 0)
|
||||
})
|
||||
|
||||
soundCache.set(track.id, sound)
|
||||
soundPromises.delete(track.id)
|
||||
return sound
|
||||
|
@ -74,7 +75,7 @@ export const createSound = async (track: QueueTrack): Promise<Sound> => {
|
|||
// Create track from queue
|
||||
export const createTrack = async (index: number) => {
|
||||
if (queue.value.length <= index || index === -1) return
|
||||
console.log('LOADING TRACK')
|
||||
console.log('LOADING TRACK', index)
|
||||
|
||||
const track = queue.value[index]
|
||||
if (!soundPromises.has(track.id) && !soundCache.has(track.id)) {
|
||||
|
@ -88,7 +89,7 @@ export const createTrack = async (index: number) => {
|
|||
sound.audioNode.disconnect()
|
||||
connectAudioSource(sound.audioNode)
|
||||
|
||||
if (isPlaying.value) {
|
||||
if (isPlaying.value && index === currentIndex.value) {
|
||||
await sound.play()
|
||||
}
|
||||
|
||||
|
@ -101,4 +102,6 @@ export const createTrack = async (index: number) => {
|
|||
}
|
||||
}
|
||||
|
||||
watchEffect(async () => createTrack(currentIndex.value))
|
||||
|
||||
export const currentSound = computed(() => soundCache.get(currentTrack.value?.id ?? -1))
|
||||
|
|
|
@ -9,7 +9,7 @@ import { useStore } from '~/store'
|
|||
import axios from 'axios'
|
||||
import jQuery from 'jquery'
|
||||
|
||||
import { enqueue as addToQueue, currentTrack } from '~/composables/audio/queue'
|
||||
import { enqueue as addToQueue, currentTrack, playNext, currentIndex, enqueueAt, queue } from '~/composables/audio/queue'
|
||||
import { isPlaying } from '~/composables/audio/player'
|
||||
|
||||
export interface PlayOptionsProps {
|
||||
|
@ -143,11 +143,11 @@ export default (props: PlayOptionsProps) => {
|
|||
|
||||
const tracks = await getPlayableTracks()
|
||||
|
||||
const wasEmpty = store.state.queue.tracks.length === 0
|
||||
await store.dispatch('queue/appendMany', { tracks, index: store.state.queue.currentIndex + 1 })
|
||||
const wasEmpty = queue.value.length === 0
|
||||
await enqueueAt(currentIndex.value + 1, ...tracks)
|
||||
|
||||
if (next && !wasEmpty) {
|
||||
await store.dispatch('queue/next')
|
||||
await playNext()
|
||||
isPlaying.value = true
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import LRU from 'lru-cache'
|
||||
import { reactive } from 'vue'
|
||||
|
||||
export default <T, K>(options: LRU.Options<T, K>) => {
|
||||
const cache = new LRU(options)
|
||||
|
||||
// @ts-expect-error keyMap is used internally so it is not defined in the types
|
||||
cache.keyMap = reactive(cache.keyMap)
|
||||
|
||||
return cache
|
||||
}
|
|
@ -4120,6 +4120,11 @@ lru-cache@^6.0.0:
|
|||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
lru-cache@^7.14.0:
|
||||
version "7.14.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.14.0.tgz#21be64954a4680e303a09e9468f880b98a0b3c7f"
|
||||
integrity sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==
|
||||
|
||||
magic-string@^0.25.0, magic-string@^0.25.7:
|
||||
version "0.25.9"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
|
||||
|
|
Loading…
Reference in New Issue