Files
evilspins/app/store/favorites.ts
valere 34d22b3b17
All checks were successful
Deploy App / build (push) Successful in 43s
Deploy App / deploy (push) Successful in 41s
evilSpins v1
2025-11-04 22:41:41 +01:00

145 lines
4.6 KiB
TypeScript

import { defineStore } from 'pinia'
import type { Track, Box, BoxType, Artist } from '~/../types/types'
export const FAVORITES_BOX_ID = 'FAV'
const STORAGE_KEY = 'evilspins:favorites:v2' // Version changée pour forcer la mise à jour
export const useFavoritesStore = defineStore('favorites', {
state: () => ({
favoritesPlaylist: {
id: FAVORITES_BOX_ID,
type: 'userPlaylist' as BoxType,
name: 'Favoris',
description: 'Vos titres favoris',
color1: '#FFD700',
color2: '#FFA500',
color3: '#FF8C00',
duration: 0,
state: 'box-hidden',
tracks: [] as Track[],
isPublic: false
} as Box,
version: 1
}),
getters: {
trackIds: (state) => state.favoritesPlaylist.tracks?.map((t) => t.id) || [],
tracks: (state) => state.favoritesPlaylist.tracks || [],
isFavorite: (state) => (trackId: number) =>
state.favoritesPlaylist.tracks?.some((t) => t.id === trackId) || false
},
actions: {
load() {
if (!process.client) return
try {
const raw = localStorage.getItem(STORAGE_KEY)
if (raw) {
const data = JSON.parse(raw)
if (data.version === this.version && data.playlist) {
this.favoritesPlaylist = { ...this.favoritesPlaylist, ...data.playlist }
} else if (Array.isArray(data)) {
// Migration depuis l'ancienne version
this.favoritesPlaylist.tracks = data
.filter((x) => typeof x === 'number')
.map((id) => ({ id }) as unknown as Track) // On ne stocke que l'ID, les infos seront complétées par le dataStore
}
}
} catch (error) {
console.error('Error loading favorites:', error)
}
},
save() {
if (!process.client) return
try {
localStorage.setItem(
STORAGE_KEY,
JSON.stringify({
version: this.version,
playlist: this.favoritesPlaylist
})
)
} catch (error) {
console.error('Error saving favorites:', error)
}
},
// Crée une copie virtuelle d'une piste pour les favoris
createVirtualTrack(originalTrack: Track): Track {
// Crée une copie profonde de la piste
const virtualTrack = JSON.parse(JSON.stringify(originalTrack)) as Track
// Marque la piste comme provenant d'une playlist utilisateur
virtualTrack.source = 'userPlaylist'
virtualTrack.originalTrackId = originalTrack.id
virtualTrack.boxId = FAVORITES_BOX_ID
// Si la piste a un artiste sous forme d'objet, on le convertit en chaîne pour éviter les problèmes de référence
if (virtualTrack.artist && typeof virtualTrack.artist === 'object') {
virtualTrack.artist = (virtualTrack.artist as Artist).name
}
return virtualTrack
},
// Ajoute une piste aux favoris si elle n'y est pas déjà
add(track: Track) {
if (!this.isFavorite(track.id)) {
// Crée une copie virtuelle de la piste
const virtualTrack = this.createVirtualTrack(track)
if (!this.favoritesPlaylist.tracks) {
this.favoritesPlaylist.tracks = []
}
// Ajoute la piste virtuelle au début de la liste
this.favoritesPlaylist.tracks.unshift(virtualTrack)
this.updateDuration()
this.save()
}
},
// Supprime une piste des favoris
remove(trackId: number) {
if (this.favoritesPlaylist.tracks) {
const index = this.favoritesPlaylist.tracks.findIndex((t) => t.id === trackId)
if (index >= 0) {
this.favoritesPlaylist.tracks.splice(index, 1)
this.updateDuration()
this.save()
}
}
},
// Bascule l'état favori d'une piste
toggle(track: Track) {
if (this.isFavorite(track.id)) {
this.remove(track.id)
} else {
this.add(track)
}
},
// Met à jour la durée totale de la playlist
updateDuration() {
if (this.favoritesPlaylist.tracks) {
this.favoritesPlaylist.duration = this.favoritesPlaylist.tracks.reduce(
(total, track) => total + (track.duration || 0),
0
)
}
},
// Récupère la piste suivante dans les favoris
getNextTrack(currentTrackId: number): Track | null {
if (!this.favoritesPlaylist.tracks) return null
const currentIndex = this.favoritesPlaylist.tracks.findIndex((t) => t.id === currentTrackId)
if (currentIndex >= 0 && currentIndex < this.favoritesPlaylist.tracks.length - 1) {
const nextTrack = this.favoritesPlaylist.tracks[currentIndex + 1]
return nextTrack ? { ...nextTrack } : null
}
return null
}
}
})