import React, { useCallback, useContext, ReactElement, useEffect } from "react"; import { search, downloadAirDCPPItem, getBundlesForComic, } from "../actions/airdcpp.actions"; import { useDispatch, useSelector } from "react-redux"; import { RootState, SearchInstance } from "threetwo-ui-typings"; import ellipsize from "ellipsize"; import { isEmpty, isNil, isUndefined, map, pick } from "lodash"; import { AirDCPPSocketContext } from "../context/AirDCPPSocket"; interface IAcquisitionPanelProps { comicBookMetadata: any; } export const AcquisitionPanel = ( props: IAcquisitionPanelProps, ): ReactElement => { const volumeName = props.comicBookMetadata.sourcedMetadata.comicvine.volumeInformation.name; const sanitizedVolumeName = volumeName.replace(/[^a-zA-Z0-9 ]/g, ""); const issueName = props.comicBookMetadata.sourcedMetadata.comicvine.name; // Selectors for picking state const airDCPPSearchResults = useSelector((state: RootState) => { return state.airdcpp.searchResults; }); const isAirDCPPSearchInProgress = useSelector( (state: RootState) => state.airdcpp.isAirDCPPSearchInProgress, ); const searchInfo = useSelector( (state: RootState) => state.airdcpp.searchInfo, ); const searchInstance: SearchInstance = useSelector( (state: RootState) => state.airdcpp.searchInstance, ); const userSettings = useSelector((state: RootState) => state.settings.data); const { ADCPPSocket } = useContext(AirDCPPSocketContext); const dispatch = useDispatch(); const getDCPPSearchResults = useCallback( async (searchQuery) => { dispatch( search(searchQuery, ADCPPSocket, { username: `${userSettings.directConnect.client.host.username}`, password: `${userSettings.directConnect.client.host.password}`, }), ); }, [dispatch, ADCPPSocket], ); // AirDC++ search query const dcppQuery = { query: { pattern: `${sanitizedVolumeName.replace(/#/g, "")}`, // pattern: "Templier T2.cbr", extensions: ["cbz", "cbr"], }, // "comic-scans.no-ip.biz:24674", hub_urls: map(userSettings.directConnect.client.hubs, (item) => item.value), priority: 5, }; // download via AirDC++ const downloadDCPPResult = useCallback( (searchInstanceId, resultId, comicBookObjectId) => { dispatch( downloadAirDCPPItem( searchInstanceId, resultId, comicBookObjectId, ADCPPSocket, { username: `${userSettings.directConnect.client.host.username}`, password: `${userSettings.directConnect.client.host.password}`, }, ), ); // this is to update the download count badge on the downloads tab dispatch( getBundlesForComic(comicBookObjectId, ADCPPSocket, { username: `${userSettings.directConnect.client.host.username}`, password: `${userSettings.directConnect.client.host.password}`, }), ); }, [dispatch], ); return ( <>
{!isEmpty(ADCPPSocket) ? (
) : (
AirDC++ is not configured. Please configure it in{" "} Settings.
)} {/* AirDC++ search instance details */} {!isNil(searchInfo) && !isNil(searchInstance) && ( <>
{userSettings.directConnect.client.hubs.map( ({ value }) => ( {value} ), )}
Query: {searchInfo.query.pattern}
Extensions: {searchInfo.query.extensions.join(", ")}
File type: {searchInfo.query.file_type}
Search Instance: {searchInstance.id}
Owned by {searchInstance.owner}
Expires in: {searchInstance.expires_in}
)}
{/* AirDC++ results */}
{!isNil(airDCPPSearchResults) && !isEmpty(airDCPPSearchResults) ? ( {map(airDCPPSearchResults, ({ result }, idx) => { return ( ); })}
Name Type Slots Actions

{result.type.id === "directory" ? ( ) : null}{" "} {ellipsize(result.name, 70)}

{!isNil(result.dupe) ? ( Dupe ) : null} {result.users.user.nicks} {result.users.user.flags.map((flag, idx) => ( {flag} ))}
{result.type.id === "directory" ? "directory" : result.type.str}
{result.slots.free} free {result.slots.total}
downloadDCPPResult( searchInstance.id, result.id, props.comicBookMetadata._id, ) } >
) : (
Searching via AirDC++ is still in{" "} alpha. Some searches may take arbitrarily long, or may not work at all. Searches from ADCS hubs are more reliable than NMDCS ones.
)}
); }; export default AcquisitionPanel;