import { Box, Group, Stack } from '@mantine/core'; import { useForm } from '@mantine/form'; import { closeModal, ContextModalProps } from '@mantine/modals'; import { useMemo, useState } from 'react'; import { api } from '/@/renderer/api'; import { queryKeys } from '/@/renderer/api/query-keys'; import { PlaylistListSort, SongListQuery, SongListSort, SortOrder } from '/@/renderer/api/types'; import { Button, MultiSelect, Switch, toast } from '/@/renderer/components'; import { useAddToPlaylist } from '/@/renderer/features/playlists/mutations/add-to-playlist-mutation'; import { usePlaylistList } from '/@/renderer/features/playlists/queries/playlist-list-query'; import { queryClient } from '/@/renderer/lib/react-query'; import { useCurrentServer } from '/@/renderer/store'; export const AddToPlaylistContextModal = ({ id, innerProps, }: ContextModalProps<{ albumId?: string[]; artistId?: string[]; songId?: string[]; }>) => { const { albumId, artistId, songId } = innerProps; const server = useCurrentServer(); const [isLoading, setIsLoading] = useState(false); const addToPlaylistMutation = useAddToPlaylist({}); const playlistList = usePlaylistList({ query: { _custom: { navidrome: { smart: false, }, }, sortBy: PlaylistListSort.NAME, sortOrder: SortOrder.ASC, startIndex: 0, }, serverId: server?.id, }); const playlistSelect = useMemo(() => { return ( playlistList.data?.items?.map((playlist) => ({ label: playlist.name, value: playlist.id, })) || [] ); }, [playlistList.data]); const form = useForm({ initialValues: { playlistId: [], skipDuplicates: true, }, }); const getSongsByAlbum = async (albumId: string) => { const query: SongListQuery = { albumIds: [albumId], sortBy: SongListSort.ALBUM, sortOrder: SortOrder.ASC, startIndex: 0, }; const queryKey = queryKeys.songs.list(server?.id || '', query); const songsRes = await queryClient.fetchQuery(queryKey, ({ signal }) => { if (!server) throw new Error('No server'); return api.controller.getSongList({ apiClientProps: { server, signal }, query }); }); return songsRes; }; const getSongsByArtist = async (artistId: string) => { const query: SongListQuery = { artistIds: [artistId], sortBy: SongListSort.ARTIST, sortOrder: SortOrder.ASC, startIndex: 0, }; const queryKey = queryKeys.songs.list(server?.id || '', query); const songsRes = await queryClient.fetchQuery(queryKey, ({ signal }) => { if (!server) throw new Error('No server'); return api.controller.getSongList({ apiClientProps: { server, signal }, query }); }); return songsRes; }; const isSubmitDisabled = form.values.playlistId.length === 0 || addToPlaylistMutation.isLoading; const handleSubmit = form.onSubmit(async (values) => { setIsLoading(true); const allSongIds: string[] = []; const uniqueSongIds: string[] = []; if (albumId && albumId.length > 0) { for (const id of albumId) { const songs = await getSongsByAlbum(id); allSongIds.push(...(songs?.items?.map((song) => song.id) || [])); } } if (artistId && artistId.length > 0) { for (const id of artistId) { const songs = await getSongsByArtist(id); allSongIds.push(...(songs?.items?.map((song) => song.id) || [])); } } if (songId && songId.length > 0) { allSongIds.push(...songId); } for (const playlistId of values.playlistId) { if (values.skipDuplicates) { const query = { id: playlistId, startIndex: 0, }; const queryKey = queryKeys.playlists.songList(server?.id || '', playlistId, query); const playlistSongsRes = await queryClient.fetchQuery(queryKey, ({ signal }) => { if (!server) throw new Error('No server'); return api.controller.getPlaylistSongList({ apiClientProps: { server, signal, }, query: { id: playlistId, startIndex: 0 }, }); }); const playlistSongIds = playlistSongsRes?.items?.map((song) => song.id); for (const songId of allSongIds) { if (!playlistSongIds?.includes(songId)) { uniqueSongIds.push(songId); } } } if (values.skipDuplicates ? uniqueSongIds.length > 0 : allSongIds.length > 0) { if (!server) return null; addToPlaylistMutation.mutate( { body: { songId: values.skipDuplicates ? uniqueSongIds : allSongIds }, query: { id: playlistId }, serverId: server?.id, }, { onError: (err) => { toast.error({ message: `[${ playlistSelect.find((playlist) => playlist.value === playlistId) ?.label }] ${err.message}`, title: 'Failed to add songs to playlist', }); }, }, ); } } setIsLoading(false); toast.success({ message: `Added ${ values.skipDuplicates ? uniqueSongIds.length : allSongIds.length } songs to ${values.playlistId.length} playlist(s)`, }); closeModal(id); return null; }); return (
); };