diff --git a/src/client/actions/airdcpp.actions.tsx b/src/client/actions/airdcpp.actions.tsx index f5cfeea..e02b009 100644 --- a/src/client/actions/airdcpp.actions.tsx +++ b/src/client/actions/airdcpp.actions.tsx @@ -29,90 +29,97 @@ function sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } -export const search = (data: SearchData) => async (dispatch) => { - try { - if (!SocketService.isConnected()) { - await SocketService.connect("admin", "password", true); +export const search = + (data: SearchData, ADCPPSocket: any) => async (dispatch) => { + try { + if (!ADCPPSocket.isConnected()) { + await ADCPPSocket.connect("admin", "password", true); + } + const instance: SearchInstance = await ADCPPSocket.post("search"); + dispatch({ + type: AIRDCPP_SEARCH_IN_PROGRESS, + }); + + // We want to get notified about every new result in order to make the user experience better + await ADCPPSocket.addListener( + `search`, + "search_result_added", + async (groupedResult) => { + // ...add the received result in the UI + // (it's probably a good idea to have some kind of throttling for the UI updates as there can be thousands of results) + + dispatch({ + type: AIRDCPP_SEARCH_RESULTS_ADDED, + groupedResult, + }); + }, + instance.id, + ); + + // We also want to update the existing items in our list when new hits arrive for the previously listed files/directories + await ADCPPSocket.addListener( + `search`, + "search_result_updated", + async (groupedResult) => { + // ...update properties of the existing result in the UI + dispatch({ + type: AIRDCPP_SEARCH_RESULTS_UPDATED, + groupedResult, + }); + }, + instance.id, + ); + + // We need to show something to the user in case the search won't yield any results so that he won't be waiting forever) + // Wait for 5 seconds for any results to arrive after the searches were sent to the hubs + await ADCPPSocket.addListener( + `search`, + "search_hub_searches_sent", + async (searchInfo) => { + await sleep(5000); + + // Check the number of received results (in real use cases we should know that even without calling the API) + const currentInstance = await ADCPPSocket.get( + `search/${instance.id}`, + ); + if (currentInstance.result_count === 0) { + // ...nothing was received, show an informative message to the user + console.log("No more search results."); + } + + // The search can now be considered to be "complete" + // If there's an "in progress" indicator in the UI, that could also be disabled here + dispatch({ + type: AIRDCPP_HUB_SEARCHES_SENT, + searchInfo, + instance, + }); + }, + instance.id, + ); + + // Finally, perform the actual search + await ADCPPSocket.post(`search/${instance.id}/hub_search`, data); + } catch (error) { + console.log(error); + throw error; } - const instance: SearchInstance = await SocketService.post("search"); - dispatch({ - type: AIRDCPP_SEARCH_IN_PROGRESS, - }); - - // We want to get notified about every new result in order to make the user experience better - await SocketService.addListener( - `search`, - "search_result_added", - async (groupedResult) => { - // ...add the received result in the UI - // (it's probably a good idea to have some kind of throttling for the UI updates as there can be thousands of results) - - dispatch({ - type: AIRDCPP_SEARCH_RESULTS_ADDED, - groupedResult, - }); - }, - instance.id, - ); - - // We also want to update the existing items in our list when new hits arrive for the previously listed files/directories - await SocketService.addListener( - `search`, - "search_result_updated", - async (groupedResult) => { - // ...update properties of the existing result in the UI - dispatch({ - type: AIRDCPP_SEARCH_RESULTS_UPDATED, - groupedResult, - }); - }, - instance.id, - ); - - // We need to show something to the user in case the search won't yield any results so that he won't be waiting forever) - // Wait for 5 seconds for any results to arrive after the searches were sent to the hubs - await SocketService.addListener( - `search`, - "search_hub_searches_sent", - async (searchInfo) => { - await sleep(5000); - - // Check the number of received results (in real use cases we should know that even without calling the API) - const currentInstance = await SocketService.get( - `search/${instance.id}`, - ); - if (currentInstance.result_count === 0) { - // ...nothing was received, show an informative message to the user - } - - // The search can now be considered to be "complete" - // If there's an "in progress" indicator in the UI, that could also be disabled here - dispatch({ - type: AIRDCPP_HUB_SEARCHES_SENT, - searchInfo, - instance, - }); - }, - instance.id, - ); - - // Finally, perform the actual search - await SocketService.post(`search/${instance.id}/hub_search`, data); - } catch (error) { - console.log(error); - throw error; - } -}; + }; export const downloadAirDCPPItem = - (instanceId: string, resultId: string, comicObjectId: string): void => + ( + instanceId: string, + resultId: string, + comicObjectId: string, + ADCPPSocket: any, + ): void => async (dispatch) => { try { - if (!SocketService.isConnected()) { - await SocketService.connect("admin", "password", true); + if (!ADCPPSocket.isConnected()) { + await ADCPPSocket.connect("admin", "password", true); } let bundleDBImportResult = {}; - const downloadResult = await SocketService.post( + const downloadResult = await ADCPPSocket.post( `search/${instanceId}/results/${resultId}/download`, ); @@ -159,13 +166,13 @@ export const downloadAirDCPPItem = }; export const getDownloadProgress = - (comicObjectId: string): void => + (comicObjectId: string, ADCPPSocket: any): void => async (dispatch) => { try { - if (!SocketService.isConnected()) { - await SocketService.connect("admin", "password", true); + if (!ADCPPSocket.isConnected()) { + await ADCPPSocket.connect("admin", "password", true); } - await SocketService.addListener( + await ADCPPSocket.addListener( `queue`, "queue_bundle_tick", async (downloadProgressData) => { @@ -181,10 +188,10 @@ export const getDownloadProgress = }; export const getBundlesForComic = - (comicObjectId: string) => async (dispatch) => { + (comicObjectId: string, ADCPPSocket: any) => async (dispatch) => { try { - if (!SocketService.isConnected()) { - await SocketService.connect("admin", "password", true); + if (!ADCPPSocket.isConnected()) { + await ADCPPSocket.connect("admin", "password", true); } const comicObject = await axios({ method: "POST", @@ -199,7 +206,7 @@ export const getBundlesForComic = // get only the bundles applicable for the comic const filteredBundles = comicObject.data.acquisition.directconnect.map( async ({ bundleId }) => { - return await SocketService.get(`queue/bundles/${bundleId}`); + return await ADCPPSocket.get(`queue/bundles/${bundleId}`); }, ); dispatch({ diff --git a/src/client/components/AcquisitionPanel.tsx b/src/client/components/AcquisitionPanel.tsx index d9a0e9e..c6e197c 100644 --- a/src/client/components/AcquisitionPanel.tsx +++ b/src/client/components/AcquisitionPanel.tsx @@ -1,15 +1,14 @@ -import React, { useCallback, useEffect, useState, ReactElement } from "react"; +import React, { useCallback, useContext, ReactElement } from "react"; import { search, downloadAirDCPPItem, getBundlesForComic, } from "../actions/airdcpp.actions"; +import { SocketContext } from "../context/AirDCPPSocket"; import { useDispatch, useSelector } from "react-redux"; import { RootState, SearchInstance } from "threetwo-ui-typings"; import ellipsize from "ellipsize"; import { isEmpty, isNil, isUndefined, map } from "lodash"; -import { getSettings } from "../actions/settings.actions"; -import AirDCPPSocket from "../services/DcppSearchService"; interface IAcquisitionPanelProps { comicBookMetadata: any; } @@ -23,7 +22,6 @@ export const AcquisitionPanel = ( const issueName = props.comicBookMetadata.sourcedMetadata.comicvine.name; // local state - const [ADCPPSocket, setADCPPSocket] = useState({}); // Selectors for picking state const airDCPPSearchResults = useSelector((state: RootState) => { return state.airdcpp.searchResults; @@ -42,23 +40,17 @@ export const AcquisitionPanel = ( ); const dispatch = useDispatch(); - useEffect(() => { - dispatch(getSettings()); - if (!isEmpty(airDCPPClientSettings)) { - const dcppSocket = new AirDCPPSocket({ - hostname: `${airDCPPClientSettings.directConnect.client.hostname}`, - }); - setADCPPSocket(dcppSocket); - } - }, [dispatch]); + + const ADCPPSocket = useContext(SocketContext); const getDCPPSearchResults = useCallback( (searchQuery) => { - dispatch(search(searchQuery)); + console.log(ADCPPSocket); + dispatch(search(searchQuery, ADCPPSocket)); }, - [dispatch], + [dispatch, ADCPPSocket], ); - console.log(airDCPPClientSettings); + const dcppQuery = { query: { pattern: `${sanitizedVolumeName.replace(/#/g, "")}`, @@ -73,18 +65,23 @@ export const AcquisitionPanel = ( const downloadDCPPResult = useCallback( (searchInstanceId, resultId, comicBookObjectId) => { dispatch( - downloadAirDCPPItem(searchInstanceId, resultId, comicBookObjectId), + downloadAirDCPPItem( + searchInstanceId, + resultId, + comicBookObjectId, + ADCPPSocket, + ), ); // this is to update the download count badge on the downloads tab - dispatch(getBundlesForComic(comicBookObjectId)); + dispatch(getBundlesForComic(comicBookObjectId, ADCPPSocket)); }, [dispatch], ); + return ( <>
- {!isEmpty(airDCPPClientSettings) && - !isUndefined(airDCPPClientSettings) ? ( + {!isEmpty(ADCPPSocket) && !isUndefined(ADCPPSocket) ? (