import clsx from 'clsx'; import { AnimatePresence, motion } from 'motion/react'; import { MouseEvent, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import styles from './sidebar.module.css'; import { useItemImageUrl } from '/@/renderer/components/item-image/item-image'; import { ContextMenuController } from '/@/renderer/features/context-menu/context-menu-controller'; import { useIsRadioActive, useRadioPlayer, } from '/@/renderer/features/radio/hooks/use-radio-player'; import { ActionBar } from '/@/renderer/features/sidebar/components/action-bar'; import { SidebarCollectionList } from '/@/renderer/features/sidebar/components/sidebar-collection-list'; import { SidebarIcon } from '/@/renderer/features/sidebar/components/sidebar-icon'; import { SidebarItem } from '/@/renderer/features/sidebar/components/sidebar-item'; import { SidebarPlaylistAddDragContext, SidebarPlaylistList, SidebarSharedPlaylistList, useSidebarPlaylistAddDragMonitor, } from '/@/renderer/features/sidebar/components/sidebar-playlist-list'; import { useAppStore, useAppStoreActions, useFullScreenPlayerStore, useGeneralSettings, usePlayerSong, useSetFullScreenPlayerStore, } from '/@/renderer/store'; import { SidebarItemType, useSidebarItems, useSidebarPlaylistList, useWindowSettings, } from '/@/renderer/store/settings.store'; import { Accordion } from '/@/shared/components/accordion/accordion'; import { ActionIcon } from '/@/shared/components/action-icon/action-icon'; import { Center } from '/@/shared/components/center/center'; import { Group } from '/@/shared/components/group/group'; import { Icon } from '/@/shared/components/icon/icon'; import { ImageUnloader } from '/@/shared/components/image/image'; import { ScrollArea } from '/@/shared/components/scroll-area/scroll-area'; import { Text } from '/@/shared/components/text/text'; import { Tooltip } from '/@/shared/components/tooltip/tooltip'; import { ExplicitStatus, LibraryItem } from '/@/shared/types/domain-types'; import { Platform } from '/@/shared/types/types'; const SidebarPlaylistSection = () => { const isAddDragActive = useSidebarPlaylistAddDragMonitor(); return ( ); }; export const Sidebar = () => { const { t } = useTranslation(); const sidebarPlaylistList = useSidebarPlaylistList(); const translatedSidebarItemMap = useMemo( () => ({ Albums: t('page.sidebar.albums'), Artists: t('page.sidebar.albumArtists'), 'Artists-all': t('page.sidebar.artists'), Collections: t('page.sidebar.collections'), Favorites: t('page.sidebar.favorites'), Folders: t('page.sidebar.folders'), Genres: t('page.sidebar.genres'), Home: t('page.sidebar.home'), 'Now Playing': t('page.sidebar.nowPlaying'), Playlists: t('page.sidebar.playlists'), Radio: t('page.sidebar.radio'), Search: t('page.sidebar.search'), Settings: t('page.sidebar.settings'), Tracks: t('page.sidebar.tracks'), }), [t], ); const sidebarItems = useSidebarItems(); const { windowBarStyle } = useWindowSettings(); const sidebarImageEnabled = useAppStore((state) => state.sidebar.image); const showImage = sidebarImageEnabled; const sidebarItemsWithRoute: SidebarItemType[] = useMemo(() => { if (!sidebarItems) return []; const items = sidebarItems .filter((item) => !item.disabled) .map((item) => ({ ...item, label: translatedSidebarItemMap[item.id as keyof typeof translatedSidebarItemMap] ?? item.label, })); return items; }, [sidebarItems, translatedSidebarItemMap]); /* Library accordion: only items with a route (exclude Collections section) */ const libraryItemsWithRoute = useMemo( () => sidebarItemsWithRoute.filter((item) => item.id !== 'Collections' && item.route), [sidebarItemsWithRoute], ); const isCustomWindowBar = windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS; return ( ); }; const SidebarImage = () => { const { t } = useTranslation(); const { setSideBar } = useAppStoreActions(); const currentSong = usePlayerSong(); const isRadioActive = useIsRadioActive(); const { currentStationArt, isPlaying: isRadioPlaying } = useRadioPlayer(); const { blurExplicitImages } = useGeneralSettings(); const imageUrl = useItemImageUrl({ id: currentSong?.imageId || undefined, itemType: LibraryItem.SONG, serverId: currentSong?._serverId, type: 'sidebar', }); const radioImageUrl = useItemImageUrl({ id: isRadioActive ? currentStationArt?.imageId || undefined : undefined, imageUrl: isRadioActive ? currentStationArt?.imageUrl || undefined : undefined, itemType: LibraryItem.RADIO_STATION, serverId: isRadioActive ? currentStationArt?.serverId : undefined, type: 'sidebar', }); const isPlayingRadio = isRadioActive && isRadioPlaying; const isSongDefined = Boolean(currentSong?.id); const setFullScreenPlayerStore = useSetFullScreenPlayerStore(); const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore(); const expandFullScreenPlayer = () => { setFullScreenPlayerStore({ expanded: !isFullScreenPlayerExpanded }); }; const handleToggleContextMenu = (e: MouseEvent) => { e.preventDefault(); e.stopPropagation(); if (!currentSong || isPlayingRadio) { return; } if (isSongDefined && !isFullScreenPlayerExpanded) { ContextMenuController.call({ cmd: { items: [currentSong!], type: LibraryItem.SONG }, event: e, }); } }; return ( {isRadioActive && radioImageUrl ? ( ) : isRadioActive ? (
) : imageUrl ? ( ) : ( )}
{ e.stopPropagation(); setSideBar({ image: false }); }} opacity={0.8} radius="md" style={{ cursor: 'default', position: 'absolute', right: '1rem', top: '1rem', }} tooltip={{ label: t('common.collapse'), openDelay: 500, }} />
); };