// ~/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` } } })