import { ref, computed, onMounted, onUnmounted, watchEffect } from 'vue' import type { Track } from '../types' import { formatDuration, formatTitle } from '../utils' import { useSubsonicApi } from '../subsonicApi' import { usePlayerStore } from '../store/player' import { useFavouriteStore } from '../store/favourite' import { usePlaylistStore } from '../store/playlist' import { useCacheStore } from '../store/cache' export const TrackList = ({ tracks, isPlaylistView = false, hideAlbum = false, hideArtist = false, hideDuration = false, hideCover = false, activeBy = 'id', }: { tracks: Track[], isPlaylistView?: boolean, hideAlbum?: boolean, hideArtist?: boolean, hideCover?: boolean, hideDuration?: boolean, activeBy?: 'id' | 'index', }) => { vineEmits(['remove-track']) const subsonicApi = useSubsonicApi(), playerStore = usePlayerStore(), favouriteStore = useFavouriteStore(), playlistStore = usePlaylistStore(), cacheStore = useCacheStore(), playlistSelect = ref(null), isCached = ref(tracks.map(track => false)), isFavourite = computed(() => tracks.map(track => !!favouriteStore.tracks[track.id])), isPlaying = computed(() => playerStore.isPlaying), playingTrackId = computed(() => playerStore.trackId), queueIndex = computed(() => playerStore.queueIndex), toggleFavourite = (index: number) => { if (!tracks[index]?.id) return favouriteStore.toggle('track', tracks[index].id) }, setNextInQueue = (index: number) => { if (!tracks[index]) return playerStore.setNextInQueue([ tracks[index] ]) }, addToQueue = (index: number) => { if(!tracks[index]) return playerStore.addToQueue([ tracks[index] ]) }, addToPlaylist = (playlistId: string) => { const index = playlistSelect.value if (!index || !tracks[index]) return playlistStore.addTracks(playlistId, [ tracks[index].id ]) playlistSelect.value = null }, download = (index: number) => { if (!tracks[index]) return if (subsonicApi) window.location.href = subsonicApi.getDownloadUrl(tracks[index]?.id) }, isActive = (item: Track, index: number) => ( (activeBy !== 'index') ? item.id === playerStore.trackId : index === playerStore.queueIndex ), handlePlay = (index: number) => { if (!tracks[index]) return playerStore.setShuffle(false) if (tracks[index].id === playerStore.trackId) return playerStore.playPause() return playerStore.playTrackList(tracks, index) }, cacheHandler = (index: number, e: Event) => { const cachedUrl = (e as CustomEvent).detail if (cachedUrl === tracks[index]?.url) isCached.value[index] = true }, clearHandler = async (index: number) => { isCached.value[index] = (!tracks[index]?.url) ? false : (await cacheStore.hasTrack(tracks[index]?.url)) }, dragstart = (index, event: DragEvent) => { if (!tracks[index]) return if (!tracks[index].isStream) event.dataTransfer?.setData('application/x-track-id', tracks[index].id) } onMounted(() => { tracks.forEach((track, index) => { window.addEventListener('audioCached', event => cacheHandler(index, event)) window.addEventListener('audioCacheClearedAll', event => clearHandler(index)) }) }) onUnmounted(() => { tracks.forEach((track, index) => { window.removeEventListener('audioCached', event => cacheHandler(index, event)) window.removeEventListener('audioCacheClearedAll', event => clearHandler(index)) }) }) watchEffect(async () => { tracks.forEach(async (track, index) => { if (!track.url) return (isCached.value[index] = false) isCached.value[index] = await cacheStore.hasTrack(track.url) }) }) return vine`
# Title Artist Album Time Actions
{{ (index + 1) ?? '-' }} {{ formatTitle(track.title) }} , {{ artist.name }} {{ artist.name }} {{ formatDuration(track.duration ?? 0) }} Play Next Add to Queue Add to Playlist Favourite Download Remove
{{ playlist.name }}
` }