import { createContext, useRef, useState } from "react"; import { BSVersion } from "shared/bs-version.interface"; import { LocalMapsListPanel, LocalMapsListPanelRef } from "./maps/local-maps-list-panel.component"; import { BsmDropdownButton, DropDownItem } from "../shared/bsm-dropdown-button.component"; import { FilterPanel } from "./maps/filter-panel.component"; import { MapFilter } from "shared/models/maps/beat-saver.model"; import { MapsManagerService } from "renderer/services/maps-manager.service"; import { MapsDownloaderService } from "renderer/services/maps-downloader.service"; import { useTranslation } from "renderer/hooks/use-translation.hook"; import { FolderLinkState } from "renderer/services/version-folder-linker.service"; import { useService } from "renderer/hooks/use-service.hook"; import { BsContentTabPanel } from "../shared/bs-content-tab-panel/bs-content-tab-panel.component"; import { BsmButton } from "../shared/bsm-button.component"; import { MapIcon } from "../svgs/icons/map-icon.component"; import { PlaylistIcon } from "../svgs/icons/playlist-icon.component"; import { useObservable } from "renderer/hooks/use-observable.hook"; import { BehaviorSubject, of } from "rxjs"; import { LocalPlaylistsListPanel, LocalPlaylistsListRef } from "./playlists/local-playlists-list-panel.component"; import { PlaylistsManagerService } from "renderer/services/playlists-manager.service"; import { BsmLocalMap } from "shared/models/maps/bsm-local-map.interface"; import { useConstant } from "renderer/hooks/use-constant.hook"; import { LocalBPListsDetails } from "shared/models/playlists/local-playlist.models"; import { PlaylistDownloaderService } from "renderer/services/playlist-downloader.service"; import { LocalPlaylistFilter, LocalPlaylistFilterPanel } from "./playlists/local-playlist-filter-panel.component"; import { noop } from "shared/helpers/function.helpers"; type Props = { readonly version?: BSVersion; readonly isActive?: boolean; }; export const InstalledMapsContext = createContext<{ maps$: BehaviorSubject; setMaps: (maps: BsmLocalMap[]) => void; playlists$: BehaviorSubject; setPlaylists: (playlist: LocalBPListsDetails[]) => void; }>(null); export function MapsPlaylistsPanel({ version, isActive }: Props) { const mapsManager = useService(MapsManagerService); const mapsDownloader = useService(MapsDownloaderService); const playlistsManager = useService(PlaylistsManagerService); const playlistsDownloader = useService(PlaylistDownloaderService); const t = useTranslation(); const [tabIndex, setTabIndex] = useState(0); const maps$ = useConstant(() => new BehaviorSubject(undefined)); const playlists$ = useConstant(() => new BehaviorSubject(undefined)); const mapsContextValue = useConstant(() => ({ maps$, setMaps: maps$.next.bind(maps$), playlists$, setPlaylists: playlists$.next.bind(playlists$), })); const mapsRef = useRef(); const playlistsRef = useRef(); const [mapFilter, setMapFilter] = useState({}); const [playlistFilter, setPlaylistFilter] = useState({}); const [search, setSearch] = useState(""); const mapsLinkedState = useObservable(() => { if(!version) return of(FolderLinkState.Unlinked); return mapsManager.$mapsFolderLinkState(version); }, FolderLinkState.Unlinked, [version]); const playlistLinkedState = useObservable(() => { if(!version) return of(FolderLinkState.Unlinked); return playlistsManager.$playlistsFolderLinkState(version); }, FolderLinkState.Unlinked, [version]); const handleAddClick = () => { switch (tabIndex) { case 0: return mapsDownloader.openDownloadMapModal(version, maps$.value); case 1: return playlistsDownloader.openDownloadPlaylistModal(version, playlists$, maps$); default: return noop(); } } const handleMapsLinkClick = () => { if(mapsLinkedState === FolderLinkState.Pending || mapsLinkedState === FolderLinkState.Processing){ return Promise.resolve(false); } if (mapsLinkedState === FolderLinkState.Unlinked) { return mapsManager.linkVersion(version); } return mapsManager.unlinkVersion(version); }; const handlePlaylistLinkClick = () => { if(playlistLinkedState === FolderLinkState.Pending || playlistLinkedState === FolderLinkState.Processing){ return Promise.resolve(false); } if (playlistLinkedState === FolderLinkState.Unlinked) { return playlistsManager.linkVersion(version); } return playlistsManager.unlinkVersion(version); } const dropDownItems = ((): DropDownItem[] => { if (tabIndex === 0) { return [ { icon: "export", text: "pages.version-viewer.maps.search-bar.dropdown.export-maps", onClick: () => mapsRef.current.exportMaps?.() }, { icon: "trash", text: "pages.version-viewer.maps.search-bar.dropdown.delete-maps", onClick: () => mapsRef.current.deleteMaps?.() }, { icon: "clean", text: "pages.version-viewer.maps.search-bar.dropdown.delete-duplicate-maps", onClick: () => mapsRef.current.removeDuplicates?.() }, ]; } return [ { icon: "add", text: t("playlist.create-a-playlist"), onClick: () => playlistsRef?.current?.createPlaylist?.() }, { icon: "sync", text: t("playlist.synchronize-playlists"), onClick: () => playlistsRef?.current?.syncPlaylists?.() }, { icon: "export", text: t("playlist.export-playlists"), onClick: () => playlistsRef?.current?.exportPlaylists?.() }, { icon: "trash", text: t("playlist.delete-playlists"), onClick: () => playlistsRef?.current?.deletePlaylists?.() }, ]; })(); return ( <> setTabIndex(index)} tabs={[ { text: "misc.maps", icon: MapIcon, onClick: () => setTabIndex(0), linkProps: version ? { state: mapsLinkedState, onClick: handleMapsLinkClick, } : null, }, { text: "misc.playlists", icon: PlaylistIcon, onClick: () => setTabIndex(1), linkProps: version ? { state: playlistLinkedState, onClick: handlePlaylistLinkClick, } : null, }, ]} > ); }