import { MouseEvent, useMemo } from 'react'; import { Box, Center, Divider, Group, Stack } from '@mantine/core'; import { closeAllModals, openModal } from '@mantine/modals'; import { AnimatePresence, motion } from 'framer-motion'; import { IconType } from 'react-icons'; import { RiAddFill, RiAlbumFill, RiAlbumLine, RiArrowDownSLine, RiDiscLine, RiFlag2Fill, RiFlagLine, RiFolder3Fill, RiFolder3Line, RiHome6Fill, RiHome6Line, RiListUnordered, RiMusic2Fill, RiMusic2Line, RiPlayLine, RiSearchFill, RiUserVoiceFill, RiUserVoiceLine, RiSearchLine, RiPlayFill, RiSettings2Line, RiSettings2Fill, RiPlayListLine, RiPlayListFill, } from 'react-icons/ri'; import { generatePath, Link, useLocation } from 'react-router-dom'; import styled from 'styled-components'; import { SidebarItemType, useGeneralSettings, useWindowSettings, } from '../../../store/settings.store'; import { LibraryItem, PlaylistListSort, ServerType, SortOrder } from '/@/renderer/api/types'; import { Button, MotionStack, Spinner, Tooltip } from '/@/renderer/components'; import { CreatePlaylistForm, usePlaylistList } from '/@/renderer/features/playlists'; import { ActionBar } from '/@/renderer/features/sidebar/components/action-bar'; import { SidebarItem } from '/@/renderer/features/sidebar/components/sidebar-item'; import { SidebarPlaylistList } from '/@/renderer/features/sidebar/components/sidebar-playlist-list'; import { useContainerQuery } from '/@/renderer/hooks'; import { AppRoute } from '/@/renderer/router/routes'; import { useAppStoreActions, useCurrentServer, useCurrentSong, useFullScreenPlayerStore, useSetFullScreenPlayerStore, useSidebarStore, } from '/@/renderer/store'; import { fadeIn } from '/@/renderer/styles'; import { Platform } from '/@/renderer/types'; const SidebarContainer = styled.div<{ windowBarStyle: Platform }>` height: 100%; max-height: ${(props) => props.windowBarStyle === Platform.WEB || props.windowBarStyle === Platform.LINUX ? 'calc(100vh - 149px)' : 'calc(100vh - 179px)'}; // Playerbar (90px), titlebar (65px), windowbar (30px) user-select: none; `; const ImageContainer = styled(motion.div)<{ height: string }>` position: relative; height: ${(props) => props.height}; cursor: pointer; ${fadeIn}; animation: fadein 0.2s ease-in-out; button { display: none; } &:hover button { display: block; } `; const SidebarImage = styled.img` width: 100%; height: 100%; object-fit: cover; background: var(--placeholder-bg); `; const sidebarItemMap = { [AppRoute.HOME]: { activeIcon: RiHome6Fill, icon: RiHome6Line, }, [AppRoute.LIBRARY_ALBUMS]: { activeIcon: RiAlbumFill, icon: RiAlbumLine, }, [AppRoute.LIBRARY_ALBUM_ARTISTS]: { activeIcon: RiUserVoiceFill, icon: RiUserVoiceLine, }, [AppRoute.PLAYLISTS]: { activeIcon: RiPlayListFill, icon: RiPlayListLine, }, [AppRoute.LIBRARY_SONGS]: { activeIcon: RiMusic2Fill, icon: RiMusic2Line, }, [AppRoute.LIBRARY_FOLDERS]: { activeIcon: RiFolder3Fill, icon: RiFolder3Line, }, [AppRoute.LIBRARY_GENRES]: { activeIcon: RiFlag2Fill, icon: RiFlagLine, }, [generatePath(AppRoute.SEARCH, { itemType: LibraryItem.SONG })]: { activeIcon: RiSearchFill, icon: RiSearchLine, }, [AppRoute.SETTINGS]: { activeIcon: RiSettings2Fill, icon: RiSettings2Line, }, [AppRoute.NOW_PLAYING]: { activeIcon: RiPlayFill, icon: RiPlayLine, }, }; export const Sidebar = () => { const location = useLocation(); const sidebar = useSidebarStore(); const { setSideBar } = useAppStoreActions(); const { windowBarStyle } = useWindowSettings(); const { sidebarPlaylistList } = useGeneralSettings(); const imageUrl = useCurrentSong()?.imageUrl; const server = useCurrentServer(); const upsizedImageUrl = imageUrl ?.replace(/size=\d+/, 'size=300') .replace(/width=\d+/, 'width=300') .replace(/height=\d+/, 'height=300'); const showImage = sidebar.image; const handleCreatePlaylistModal = (e: MouseEvent) => { e.stopPropagation(); openModal({ children: closeAllModals()} />, size: server?.type === ServerType?.NAVIDROME ? 'xl' : 'sm', title: 'Create Playlist', }); }; const playlistsQuery = usePlaylistList({ query: { sortBy: PlaylistListSort.NAME, sortOrder: SortOrder.ASC, startIndex: 0, }, serverId: server?.id, }); const setFullScreenPlayerStore = useSetFullScreenPlayerStore(); const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore(); const expandFullScreenPlayer = () => { setFullScreenPlayerStore({ expanded: !isFullScreenPlayerExpanded }); }; const cq = useContainerQuery({ sm: 300 }); const { sidebarItems } = useGeneralSettings(); const sidebarItemsWithRoute: (SidebarItemType & { activeIcon: IconType; icon: IconType; })[] = useMemo(() => { if (!sidebarItems) return []; const items = sidebarItems .filter((item) => !item.disabled) .map((item) => ({ ...item, ...sidebarItemMap[item.route as keyof typeof sidebarItemMap], })); return items; }, [sidebarItems]); return ( {sidebarItemsWithRoute.map((item) => ( {location.pathname === item.route ? ( ) : ( )} {item.label} ))} {sidebarPlaylistList && ( <> Playlists {playlistsQuery.isLoading && } )} {showImage && ( {upsizedImageUrl ? ( ) : (
)}
)}
); };