import { ColDef, RowDoubleClickedEvent } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; import { Box, Group } from '@mantine/core'; import { closeAllModals, openModal } from '@mantine/modals'; import { MutableRefObject, useMemo, useRef } from 'react'; import { RiMoreFill } from 'react-icons/ri'; import { generatePath, useNavigate, useParams } from 'react-router'; import { Link } from 'react-router-dom'; import styled from 'styled-components'; import { LibraryItem, QueueSong } from '/@/renderer/api/types'; import { Button, ConfirmModal, DropdownMenu, MotionGroup, toast } from '/@/renderer/components'; import { getColumnDefs, useFixedTableHeader, VirtualTable, } from '/@/renderer/components/virtual-table'; import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; import { useHandleTableContextMenu } from '/@/renderer/features/context-menu'; import { PLAYLIST_SONG_CONTEXT_MENU_ITEMS, SMART_PLAYLIST_SONG_CONTEXT_MENU_ITEMS, } from '/@/renderer/features/context-menu/context-menu-items'; import { usePlayQueueAdd } from '/@/renderer/features/player'; import { openUpdatePlaylistModal } from '/@/renderer/features/playlists/components/update-playlist-form'; import { useDeletePlaylist } from '/@/renderer/features/playlists/mutations/delete-playlist-mutation'; import { usePlaylistDetail } from '/@/renderer/features/playlists/queries/playlist-detail-query'; import { usePlaylistSongListInfinite } from '/@/renderer/features/playlists/queries/playlist-song-list-query'; import { PlayButton, PLAY_TYPES } from '/@/renderer/features/shared'; import { AppRoute } from '/@/renderer/router/routes'; import { useCurrentServer, useSongListStore } from '/@/renderer/store'; import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; import { Play } from '/@/renderer/types'; const ContentContainer = styled.div` position: relative; display: flex; flex-direction: column; padding: 1rem 2rem 5rem; overflow: hidden; .ag-theme-alpine-dark { --ag-header-background-color: rgba(0, 0, 0, 0%) !important; } .ag-header { margin-bottom: 0.5rem; } `; interface PlaylistDetailContentProps { tableRef: MutableRefObject; } export const PlaylistDetailContent = ({ tableRef }: PlaylistDetailContentProps) => { const navigate = useNavigate(); const { playlistId } = useParams() as { playlistId: string }; const page = useSongListStore(); const handlePlayQueueAdd = usePlayQueueAdd(); const server = useCurrentServer(); const detailQuery = usePlaylistDetail({ query: { id: playlistId }, serverId: server?.id }); const playButtonBehavior = usePlayButtonBehavior(); const playlistSongsQueryInfinite = usePlaylistSongListInfinite({ options: { cacheTime: 0, keepPreviousData: false, }, query: { id: playlistId, limit: 50, startIndex: 0, }, serverId: server?.id, }); const handleLoadMore = () => { playlistSongsQueryInfinite.fetchNextPage(); }; const columnDefs: ColDef[] = useMemo( () => getColumnDefs(page.table.columns).filter( (c) => c.colId !== 'album' && c.colId !== 'artist', ), [page.table.columns], ); const contextMenuItems = useMemo(() => { if (detailQuery?.data?.rules) { return SMART_PLAYLIST_SONG_CONTEXT_MENU_ITEMS; } return PLAYLIST_SONG_CONTEXT_MENU_ITEMS; }, [detailQuery?.data?.rules]); const handleContextMenu = useHandleTableContextMenu(LibraryItem.SONG, contextMenuItems, { playlistId, }); const playlistSongData = useMemo( () => playlistSongsQueryInfinite.data?.pages.flatMap((p) => p?.items), [playlistSongsQueryInfinite.data?.pages], ); const { intersectRef, tableContainerRef } = useFixedTableHeader(); const deletePlaylistMutation = useDeletePlaylist({}); const handleDeletePlaylist = () => { deletePlaylistMutation.mutate( { query: { id: playlistId }, serverId: server?.id }, { onError: (err) => { toast.error({ message: err.message, title: 'Error deleting playlist', }); }, onSuccess: () => { toast.success({ message: `Playlist has been deleted`, }); closeAllModals(); navigate(AppRoute.PLAYLISTS); }, }, ); }; const openDeletePlaylist = () => { openModal({ children: ( Are you sure you want to delete this playlist? ), title: 'Delete playlist', }); }; const handlePlay = (playType?: Play) => { handlePlayQueueAdd?.({ byItemType: { id: [playlistId], type: LibraryItem.PLAYLIST, }, playType: playType || playButtonBehavior, }); }; const handleRowDoubleClick = (e: RowDoubleClickedEvent) => { if (!e.data) return; handlePlayQueueAdd?.({ byItemType: { id: [playlistId], type: LibraryItem.PLAYLIST, }, initialSongId: e.data.id, playType: playButtonBehavior, }); }; const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); const loadMoreRef = useRef(null); return ( handlePlay()} /> {PLAY_TYPES.filter((type) => type.play !== playButtonBehavior).map( (type) => ( handlePlay(type.play)} > {type.label} ), )} { if (!detailQuery.data || !server) return; openUpdatePlaylistModal({ playlist: detailQuery.data, server }); }} > Edit playlist Delete playlist { // It's possible that there are duplicate song ids in a playlist return `${data.data.id}-${data.data.pageIndex}`; }} rowClassRules={rowClassRules} rowData={playlistSongData} rowHeight={60} rowSelection="multiple" onCellContextMenu={handleContextMenu} onRowDoubleClicked={handleRowDoubleClick} /> ); };