280 lines
8.2 KiB
TypeScript
280 lines
8.2 KiB
TypeScript
// ~/store/player.ts
|
|
import { defineStore } from 'pinia'
|
|
import type { Track, Box } from '~/../types/types'
|
|
import { useDataStore } from '~/store/data'
|
|
import { useCardStore } from '~/store/card'
|
|
import { usePlatineStore } from '~/store/platine'
|
|
|
|
export const usePlayerStore = defineStore('player', {
|
|
state: () => ({
|
|
currentTrack: null as Track | null,
|
|
position: 0,
|
|
progressionLast: 0,
|
|
isLoading: false,
|
|
history: [] as string[]
|
|
}),
|
|
|
|
actions: {
|
|
attachAudio() {
|
|
const platineStore = usePlatineStore()
|
|
|
|
// Écouter les changements de piste dans le platineStore
|
|
watch(
|
|
() => platineStore.currentTrack,
|
|
(newTrack) => {
|
|
if (newTrack) {
|
|
this.currentTrack = newTrack
|
|
// Révéler la carte quand la lecture commence
|
|
const cardStore = useCardStore()
|
|
if (!cardStore.isCardRevealed(newTrack.id)) {
|
|
requestAnimationFrame(() => {
|
|
cardStore.revealCard(newTrack.id)
|
|
})
|
|
}
|
|
} else {
|
|
this.currentTrack = null
|
|
}
|
|
}
|
|
)
|
|
|
|
// Écouter les changements d'état de lecture
|
|
watch(
|
|
() => platineStore.isPlaying,
|
|
(isPlaying) => {
|
|
if (isPlaying) {
|
|
// Gérer la logique de lecture suivante quand la lecture se termine
|
|
if (platineStore.currentTrack?.type === 'playlist') {
|
|
const dataStore = useDataStore()
|
|
const nextTrack = dataStore.getNextPlaylistTrack(platineStore.currentTrack)
|
|
if (nextTrack) {
|
|
platineStore.loadTrack(nextTrack)
|
|
platineStore.play()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
)
|
|
},
|
|
|
|
async playBox(box: Box) {
|
|
const platineStore = usePlatineStore()
|
|
|
|
// Si c'est la même box, on toggle simplement la lecture
|
|
if (this.currentTrack?.boxId === box.id && this.currentTrack?.side === box.activeSide) {
|
|
platineStore.togglePlay()
|
|
return
|
|
}
|
|
|
|
// Sinon, on charge la première piste de la box
|
|
try {
|
|
const dataStore = useDataStore()
|
|
const firstTrack = dataStore.getFirstTrackOfBox(box)
|
|
if (firstTrack) {
|
|
this.currentTrack = firstTrack
|
|
await platineStore.loadTrack(firstTrack)
|
|
await platineStore.play()
|
|
}
|
|
} catch (error) {
|
|
console.error('Error playing box:', error)
|
|
}
|
|
},
|
|
|
|
async playTrack(track: Track) {
|
|
const platineStore = usePlatineStore()
|
|
// Si c'est la même piste, on toggle simplement la lecture
|
|
if (this.currentTrack?.id === track.id) {
|
|
platineStore.togglePlay()
|
|
return
|
|
}
|
|
|
|
// Sinon, on charge et on lit la piste
|
|
this.currentTrack = track
|
|
await platineStore.loadTrack(track)
|
|
platineStore.play()
|
|
},
|
|
|
|
async playCompilationTrack(track: Track) {
|
|
const platineStore = usePlatineStore()
|
|
|
|
// Si c'est la même piste, on toggle simplement la lecture
|
|
if (this.currentTrack?.id === track.id) {
|
|
platineStore.togglePlay()
|
|
return
|
|
}
|
|
|
|
// Pour les compilations, on charge la piste avec le point de départ
|
|
this.currentTrack = track
|
|
await platineStore.loadTrack(track)
|
|
|
|
// Si c'est une compilation, on définit la position de départ
|
|
if (track.type === 'compilation' && track.start !== undefined) {
|
|
platineStore.seek(track.start)
|
|
}
|
|
|
|
platineStore.play()
|
|
},
|
|
|
|
async playPlaylistTrack(track: Track) {
|
|
const platineStore = usePlatineStore()
|
|
|
|
// Toggle simple si c'est la même piste
|
|
if (this.currentTrack?.id === track.id) {
|
|
platineStore.togglePlay()
|
|
return
|
|
}
|
|
|
|
// Sinon, on charge et on lit la piste
|
|
this.currentTrack = track
|
|
await platineStore.loadTrack(track)
|
|
platineStore.play()
|
|
},
|
|
|
|
async loadTrack(track: Track) {
|
|
const platineStore = usePlatineStore()
|
|
await platineStore.loadTrack(track)
|
|
},
|
|
|
|
async loadAndPlayTrack(track: Track) {
|
|
const platineStore = usePlatineStore()
|
|
|
|
try {
|
|
this.isLoading = true
|
|
|
|
// Charger la piste
|
|
await platineStore.loadTrack(track)
|
|
|
|
// Pour les compilations, on définit la position de départ
|
|
if (track.type === 'compilation' && track.start !== undefined) {
|
|
platineStore.seek(track.start)
|
|
}
|
|
|
|
// Lancer la lecture
|
|
await platineStore.play()
|
|
this.history.push(track.id.toString()) // S'assurer que l'ID est une chaîne
|
|
this.isLoading = false
|
|
} catch (error) {
|
|
console.error('Error loading/playing track:', error)
|
|
this.isLoading = false
|
|
}
|
|
},
|
|
|
|
togglePlay() {
|
|
const platineStore = usePlatineStore()
|
|
platineStore.togglePlay()
|
|
},
|
|
|
|
updateTime() {
|
|
const platineStore = usePlatineStore()
|
|
|
|
// Mettre à jour la position actuelle
|
|
if (platineStore.currentTrack) {
|
|
this.position = platineStore.currentTurns / 0.75 // Convertir les tours en secondes
|
|
|
|
// Calculer et mettre en cache la progression
|
|
const duration = platineStore.totalTurns / 0.75 // Durée totale en secondes
|
|
const progression = (this.position / duration) * 100
|
|
if (!isNaN(progression) && isFinite(progression)) {
|
|
this.progressionLast = progression
|
|
}
|
|
}
|
|
},
|
|
|
|
// update current track when changing time in compilation
|
|
async updateCurrentTrack() {
|
|
const platineStore = usePlatineStore()
|
|
const currentTrack = this.currentTrack
|
|
if (currentTrack && currentTrack.type === 'compilation') {
|
|
const dataStore = useDataStore()
|
|
const tracks = dataStore
|
|
.getTracksByboxId(currentTrack.boxId, currentTrack.side)
|
|
.slice()
|
|
.filter((t) => t.type === 'compilation')
|
|
.sort((a, b) => (a.start ?? 0) - (b.start ?? 0))
|
|
|
|
if (tracks.length > 0) {
|
|
const now = platineStore.currentTurns / 0.75
|
|
// find the last track whose start <= now (fallback to first track)
|
|
let nextTrack = tracks[0]
|
|
for (const t of tracks) {
|
|
const s = t.start ?? 0
|
|
if (s <= now) {
|
|
nextTrack = t
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
if (nextTrack && nextTrack.id !== currentTrack.id) {
|
|
// only update metadata reference; do not reload audio
|
|
this.currentTrack = nextTrack
|
|
|
|
// Révéler la carte avec une animation fluide
|
|
const cardStore = useCardStore()
|
|
if (nextTrack.id && !cardStore.isCardRevealed(nextTrack.id)) {
|
|
// Utiliser requestAnimationFrame pour une meilleure synchronisation avec le rendu
|
|
requestAnimationFrame(() => {
|
|
cardStore.revealCard(nextTrack.id)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
getters: {
|
|
isCurrentBox: (state) => {
|
|
return (box: Box) => {
|
|
if (box.type === 'compilation') {
|
|
return box.id === state.currentTrack?.boxId && box.activeSide === state.currentTrack?.side
|
|
} else {
|
|
return box.id === state.currentTrack?.boxId
|
|
}
|
|
}
|
|
},
|
|
|
|
isCurrentSide: (state) => {
|
|
return (side: string) => side === state.currentTrack?.side
|
|
},
|
|
|
|
isPlaylistTrack: () => {
|
|
return (track: Track) => {
|
|
return track.type === 'playlist'
|
|
}
|
|
},
|
|
|
|
isCompilationTrack: () => {
|
|
return (track: Track) => {
|
|
return track.type === 'compilation'
|
|
}
|
|
},
|
|
|
|
isPaused() {
|
|
const platineStore = usePlatineStore()
|
|
return !platineStore.isPlaying
|
|
},
|
|
|
|
getCurrentTrack: (state) => state.currentTrack,
|
|
|
|
getCurrentBox: (state) => {
|
|
return state.currentTrack ? state.currentTrack.boxId : null
|
|
},
|
|
|
|
getCurrentProgression() {
|
|
const platineStore = usePlatineStore()
|
|
if (!platineStore.currentTrack) return 0
|
|
|
|
// Calculer la progression en fonction des tours actuels et totaux
|
|
if (platineStore.totalTurns > 0) {
|
|
return (platineStore.currentTurns / platineStore.totalTurns) * 100
|
|
}
|
|
return 0
|
|
},
|
|
|
|
getCurrentCoverUrl(state) {
|
|
const id = state.currentTrack?.coverId
|
|
if (!id) return null
|
|
return id.startsWith('http') ? id : `https://f4.bcbits.com/img/${id}_4.jpg`
|
|
}
|
|
}
|
|
})
|