diff --git a/src/client/actions/airdcpp.actions.tsx b/src/client/actions/airdcpp.actions.tsx index 62670f0..94a8998 100644 --- a/src/client/actions/airdcpp.actions.tsx +++ b/src/client/actions/airdcpp.actions.tsx @@ -6,10 +6,9 @@ import { SearchResponse, } from "threetwo-ui-typings"; import { - AIRDCPP_SEARCH_INSTANCE_CREATED, AIRDCPP_SEARCH_RESULTS_RECEIVED, AIRDCPP_HUB_SEARCHES_SENT, - AIRDCPP_HUB_USER_CONNECTED, + AIRDCPP_RESULT_DOWNLOAD_INITIATED, } from "../constants/action-types"; interface SearchData { @@ -30,10 +29,10 @@ export const search = (data: SearchData) => async (dispatch) => { `search/${instance.id}`, "search_hub_searches_sent", async (searchInfo) => { - console.log("As", searchInfo) - // Collect the results for 5 seconds before fetching them dispatch({ type: AIRDCPP_HUB_SEARCHES_SENT, + searchInfo, + instance, }); }, ); @@ -52,3 +51,17 @@ export const search = (data: SearchData) => async (dispatch) => { SocketService.disconnect(); return results; }; + +export const downloadAirDCPPItem = + (instanceId: string, resultId: string): void => + async (dispatch) => { + await SocketService.connect("admin", "password", true); + const downloadResult = await SocketService.post( + `search/${instanceId}/results/${resultId}/download`, + ); + dispatch({ + type: AIRDCPP_RESULT_DOWNLOAD_INITIATED, + downloadResult: downloadResult, + }); + SocketService.disconnect(); + }; diff --git a/src/client/components/AcquisitionPanel.tsx b/src/client/components/AcquisitionPanel.tsx index 3a84aa7..2c9163f 100644 --- a/src/client/components/AcquisitionPanel.tsx +++ b/src/client/components/AcquisitionPanel.tsx @@ -1,7 +1,7 @@ import React, { useState, useEffect, useCallback, ReactElement } from "react"; -import { search } from "../actions/airdcpp.actions"; +import { search, downloadAirDCPPItem } from "../actions/airdcpp.actions"; import { useDispatch, useSelector } from "react-redux"; -import { RootState } from "threetwo-ui-typings"; +import { RootState, SearchInstance } from "threetwo-ui-typings"; import { each, isNil, map } from "lodash"; interface IAcquisitionPanelProps { @@ -17,8 +17,14 @@ export const AcquisitionPanel = ( const airDCPPSearchResults = useSelector( (state: RootState) => state.airdcpp.results, ); - const searchStatus = useSelector( - (state: RootState) => state.airdcpp.searchStatus, + 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 dispatch = useDispatch(); const getDCPPSearchResults = useCallback( @@ -30,75 +36,133 @@ export const AcquisitionPanel = ( const dcppQuery = { query: { pattern: `${volumeName}`, - // file_type: "compressed", extensions: ["cbz", "cbr"], }, hub_urls: ["perfection.crabdance.com:777"], priority: 1, }; + + const downloadDCPPResult = useCallback( + (searchInstanceId, resultId) => + dispatch(downloadAirDCPPItem(searchInstanceId, resultId)), + [dispatch], + ); return ( -
- -

{searchStatus}

- {/* results */} - {!isNil(airDCPPSearchResults) && ( - - - - - - - - - - {map(airDCPPSearchResults, ({ name, type, slots, users }) => { - return ( - - - - - - ); - })} - -
NameTypeSlots
-

- {type.id === "directory" ? ( - - ) : null}{" "} - {name} -

+ <> +
+
+ +
+ {!isNil(searchInfo) && !isNil(searchInstance) && ( + <> +
+
+
+
+
Query: {searchInfo.query.pattern}
-
- - {users.user.nicks} - - {users.user.flags.map((flag, idx) => ( - - {flag} - - ))} -
+ Extensions: {searchInfo.query.extensions.join(", ")}
+
File type: {searchInfo.query.file_type}
-
- - {type.id === "directory" ? "directory" : type.str} - - -
- {slots.free} free - {slots.total} -
-
- )} -
+ + + + +
+
+
+
+
+
Search Instance: {searchInstance.id}
+
Owned by {searchInstance.owner}
+
Expires in: {searchInstance.expires_in}
+
+
+
+
+
+ + )} + + {/* results */} +
+ {!isNil(airDCPPSearchResults) && ( + + + + + + + + + + + {map(airDCPPSearchResults, ({ name, type, slots, users, id }) => { + return ( + + + + + + + ); + })} + +
NameTypeSlotsActions
+

+ {type.id === "directory" ? ( + + ) : null}{" "} + {name} +

+
+
+
+ + {users.user.nicks} + + {users.user.flags.map((flag, idx) => ( + + {flag} + + ))} +
+
+
+
+ + {type.id === "directory" ? "directory" : type.str} + + +
+ + {slots.free} free + + {slots.total} +
+
+ + downloadDCPPResult(searchInstance.id, id) + } + > + + +
+ )} +
+ ); }; diff --git a/src/client/components/ComicDetail.tsx b/src/client/components/ComicDetail.tsx index efb8323..6d3cf24 100644 --- a/src/client/components/ComicDetail.tsx +++ b/src/client/components/ComicDetail.tsx @@ -151,6 +151,12 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => { name: "Acquisition", content: , }, + { + id: 4, + icon: , + name: "Downloads", + content:
Downloads
, + }, ]; const MetadataTabGroup = () => { return ( diff --git a/src/client/constants/action-types.ts b/src/client/constants/action-types.ts index 2163837..9c7eff1 100644 --- a/src/client/constants/action-types.ts +++ b/src/client/constants/action-types.ts @@ -31,11 +31,9 @@ export const IMS_COMIC_BOOK_DB_OBJECT_CALL_IN_PROGRESS = export const IMS_COMIC_BOOK_DB_OBJECT_CALL_FAILED = "IMS_COMIC_BOOK_DB_OBJECT_CALL_FAILED"; -export const AIRDCPP_SEARCH_INSTANCE_CREATED = - "AIRDCPP_SEARCH_INSTANCE_CREATED"; export const AIRDCPP_SEARCH_IN_PROGRESS = "AIRDCPP_SEARCH_IN_PROGRESS"; export const AIRDCPP_SEARCH_RESULTS_RECEIVED = "AIRDCPP_SEARCH_RESULTS_RECEIVED"; export const AIRDCPP_HUB_SEARCHES_SENT = "AIRDCPP_HUB_SEARCHES_SENT"; -export const AIRDCPP_HUB_USER_CONNECTED = "AIRDCPP_HUB_USER_CONNECTED"; +export const AIRDCPP_RESULT_DOWNLOAD_INITIATED = "AIRDCPP_RESULT_DOWNLOAD_INITIATED"; diff --git a/src/client/reducers/airdcpp.reducer.ts b/src/client/reducers/airdcpp.reducer.ts index ccaf31d..f72b1c3 100644 --- a/src/client/reducers/airdcpp.reducer.ts +++ b/src/client/reducers/airdcpp.reducer.ts @@ -1,30 +1,19 @@ import { - AIRDCPP_SEARCH_INSTANCE_CREATED, AIRDCPP_SEARCH_IN_PROGRESS, AIRDCPP_SEARCH_RESULTS_RECEIVED, AIRDCPP_HUB_SEARCHES_SENT, - AIRDCPP_HUB_USER_CONNECTED, + AIRDCPP_RESULT_DOWNLOAD_INITIATED, } from "../constants/action-types"; const initialState = { isAirDCPPSearchInProgress: false, searchStatus: "", + searchInfo: null, + searchInstance: null, }; function airdcppReducer(state = initialState, action) { switch (action.type) { - case AIRDCPP_HUB_USER_CONNECTED: - return { - ...state, - searchStatus: "Hub user connected", - } - case AIRDCPP_SEARCH_INSTANCE_CREATED: - return { - ...state, - searchInstance: action.searchInstance, - searchStatus: "Search Instance created", - }; - case AIRDCPP_SEARCH_IN_PROGRESS: return { ...state, @@ -35,6 +24,7 @@ function airdcppReducer(state = initialState, action) { return { ...state, isAirDCPPSearchInProgress: false, + searchStatus: "Search complete", results: action.results, }; case AIRDCPP_HUB_SEARCHES_SENT: @@ -42,6 +32,13 @@ function airdcppReducer(state = initialState, action) { ...state, searchStatus: "Hub searches sent", isAirDCPPSearchInProgress: true, + searchInfo: action.searchInfo, + searchInstance: action.instance, + }; + case AIRDCPP_RESULT_DOWNLOAD_INITIATED: + return { + ...state, + downloadResult: action.downloadResult, }; default: