🔧 Refactoring the airdcpp reducer

This commit is contained in:
2021-08-26 21:47:05 -07:00
parent 2960c2dca4
commit 4ebe543f6a
5 changed files with 102 additions and 50 deletions

View File

@@ -11,8 +11,9 @@ import {
AIRDCPP_RESULT_DOWNLOAD_INITIATED, AIRDCPP_RESULT_DOWNLOAD_INITIATED,
AIRDCPP_DOWNLOAD_PROGRESS_TICK, AIRDCPP_DOWNLOAD_PROGRESS_TICK,
AIRDCPP_BUNDLES_FETCHED, AIRDCPP_BUNDLES_FETCHED,
AIRDCPP_SEARCH_IN_PROGRESS,
} from "../constants/action-types"; } from "../constants/action-types";
import { each, isNil } from "lodash"; import { each, isNil, isUndefined } from "lodash";
import axios from "axios"; import axios from "axios";
interface SearchData { interface SearchData {
@@ -26,33 +27,82 @@ function sleep(ms: number): Promise<NodeJS.Timeout> {
} }
export const search = (data: SearchData) => async (dispatch) => { export const search = (data: SearchData) => async (dispatch) => {
await SocketService.connect("admin", "password", true); try {
const instance: SearchInstance = await SocketService.post("search"); if (!SocketService.isConnected()) {
await SocketService.connect("admin", "password", true);
}
const instance: SearchInstance = await SocketService.post("search");
SocketService.addListener( // We want to get notified about every new result in order to make the user experience better
`search/${instance.id}`, await SocketService.addListener(
"search_hub_searches_sent", `search/${instance.id}`,
async (searchInfo) => { "search_result_added",
dispatch({ (groupedResult) => {
type: AIRDCPP_HUB_SEARCHES_SENT, dispatch({
searchInfo, type: AIRDCPP_SEARCH_RESULTS_RECEIVED,
instance, groupedResult: groupedResult.result,
}); });
}, // ...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)
},
);
await SocketService.post<SearchResponse>( // We also want to update the existing items in our list when new hits arrive for the previously listed files/directories
`search/${instance.id}/hub_search`, await SocketService.addListener(
data, `search/${instance.id}`,
); "search_result_updated",
async (groupedResult) => {
console.log(groupedResult);
dispatch({
type: AIRDCPP_SEARCH_RESULTS_RECEIVED,
results: groupedResult,
});
// ...update properties of the existing result in the UI
},
);
await sleep(10000); await SocketService.addListener(
const results = await SocketService.get(`search/${instance.id}/results/0/25`); `search/${instance.id}`,
dispatch({ "search_hub_searches_sent",
type: AIRDCPP_SEARCH_RESULTS_RECEIVED, async (searchInfo) => {
results, await sleep(5000);
}); // The search can now be considered to be "complete"
return results;
// 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) {
console.log("ASDASDASDASDD");
// ...nothing was received, show an informative message to the user
}
// If there's an "in progress" indicator in the UI, that could also be disabled here
dispatch({
type: AIRDCPP_HUB_SEARCHES_SENT,
searchInfo,
instance,
});
},
);
await SocketService.post<SearchResponse>(
`search/${instance.id}/hub_search`,
data,
);
// await sleep(10000);
// const results = await SocketService.get(
// `search/${instance.id}/results/0/25`,
// );
// dispatch({
// type: AIRDCPP_SEARCH_RESULTS_RECEIVED,
// results,
// });
} catch (error) {
console.log("ERO", error);
throw error;
}
}; };
export const downloadAirDCPPItem = export const downloadAirDCPPItem =
@@ -111,7 +161,7 @@ export const getDownloadProgress =
if (!SocketService.isConnected()) { if (!SocketService.isConnected()) {
await SocketService.connect("admin", "password", true); await SocketService.connect("admin", "password", true);
} }
SocketService.addListener( await SocketService.addListener(
`queue`, `queue`,
"queue_bundle_tick", "queue_bundle_tick",
async (downloadProgressData) => { async (downloadProgressData) => {

View File

@@ -16,7 +16,7 @@ export const AcquisitionPanel = (
const sanitizedVolumeName = volumeName.replace(/[^a-zA-Z0-9 ]/g, ""); const sanitizedVolumeName = volumeName.replace(/[^a-zA-Z0-9 ]/g, "");
const issueName = props.comicBookMetadata.sourcedMetadata.comicvine.name; const issueName = props.comicBookMetadata.sourcedMetadata.comicvine.name;
const airDCPPSearchResults = useSelector( const airDCPPSearchResults = useSelector(
(state: RootState) => state.airdcpp.results, (state: RootState) => { console.log(state); return state.airdcpp.results;}
); );
const isAirDCPPSearchInProgress = useSelector( const isAirDCPPSearchInProgress = useSelector(
(state: RootState) => state.airdcpp.isAirDCPPSearchInProgress, (state: RootState) => state.airdcpp.isAirDCPPSearchInProgress,
@@ -35,13 +35,15 @@ export const AcquisitionPanel = (
}, },
[dispatch], [dispatch],
); );
const dcppQuery = { const dcppQuery = {
query: { query: {
pattern: `${sanitizedVolumeName}`, pattern: `${sanitizedVolumeName.replace(/#/g, "")}`,
// pattern: "Templier T2.cbr",
extensions: ["cbz", "cbr"], extensions: ["cbz", "cbr"],
}, },
hub_urls: ["nmdcs://piter.feardc.net:411"], hub_urls: ["nmdcs://piter.feardc.net:411"],
priority: 1, priority: 5,
}; };
const downloadDCPPResult = useCallback( const downloadDCPPResult = useCallback(
@@ -102,7 +104,8 @@ export const AcquisitionPanel = (
</div> </div>
{/* AirDC++ results */} {/* AirDC++ results */}
<div> <div>
{!isNil(airDCPPSearchResults) && ( ASDASD {JSON.stringify(airDCPPSearchResults)}
{/* {!isNil(airDCPPSearchResults) && (
<table className="table is-striped"> <table className="table is-striped">
<thead> <thead>
<tr> <tr>
@@ -169,7 +172,7 @@ export const AcquisitionPanel = (
})} })}
</tbody> </tbody>
</table> </table>
)} )} */}
</div> </div>
</> </>
); );

View File

@@ -85,7 +85,7 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
name: "Volume Information", name: "Volume Information",
icon: <i className="fas fa-layer-group"></i>, icon: <i className="fas fa-layer-group"></i>,
content: isComicBookMetadataAvailable ? ( content: isComicBookMetadataAvailable ? (
<> <div key={1}>
<div className="columns"> <div className="columns">
<div className="column is-narrow"> <div className="column is-narrow">
<figure className="card-image"> <figure className="card-image">
@@ -137,26 +137,28 @@ export const ComicDetail = ({}: ComicDetailProps): ReactElement => {
)} )}
></div> ></div>
</div> </div>
</> </div>
) : null, ) : null,
}, },
{ {
id: 2, id: 2,
icon: <i className="fas fa-puzzle-piece"></i>, icon: <i className="fas fa-puzzle-piece"></i>,
name: "Other Metadata", name: "Other Metadata",
content: <div>bastard</div>, content: <div key={2}>bastard</div>,
}, },
{ {
id: 3, id: 3,
icon: <i className="fas fa-download"></i>, icon: <i className="fas fa-download"></i>,
name: "Acquisition", name: "Acquisition",
content: <AcquisitionPanel comicBookMetadata={comicBookDetailData} />, content: (
<AcquisitionPanel comicBookMetadata={comicBookDetailData} key={3} />
),
}, },
{ {
id: 4, id: 4,
icon: <i className="fas fa-cloud-download-alt"></i>, icon: <i className="fas fa-cloud-download-alt"></i>,
name: "Downloads", name: "Downloads",
content: <DownloadsPanel data={comicBookDetailData} />, content: <DownloadsPanel data={comicBookDetailData} key={4} />,
}, },
]; ];
const MetadataTabGroup = () => { const MetadataTabGroup = () => {

View File

@@ -60,11 +60,11 @@ export const DownloadsPanel = (
{!isNil(props.data) && {!isNil(props.data) &&
props.data && props.data &&
map(props.data, (bundle) => ( map(props.data, (bundle) => (
<> <span key={bundle.id}>
<dt>{bundle.name}</dt> <dt>{bundle.name}</dt>
<dd>{bundle.target}</dd> <dd>{bundle.target}</dd>
<dd>{bundle.size}</dd> <dd>{bundle.size}</dd>
</> </span>
))} ))}
</dl> </dl>
</div> </div>

View File

@@ -10,32 +10,30 @@ import { LOCATION_CHANGE } from "connected-react-router";
const initialState = { const initialState = {
isAirDCPPSearchInProgress: false, isAirDCPPSearchInProgress: false,
searchStatus: "",
searchInfo: null, searchInfo: null,
searchInstance: null, searchInstance: null,
downloadResult: null, downloadResult: null,
bundleDBImportResult: null, bundleDBImportResult: null,
searchResults: [],
}; };
function airdcppReducer(state = initialState, action) { function airdcppReducer(state = initialState, action) {
switch (action.type) { switch (action.type) {
case AIRDCPP_SEARCH_RESULTS_RECEIVED:
console.log("mad", state.searchResults);
return {
...state,
isAirDCPPSearchInProgress: true,
searchResults: [...state.searchResults, action.groupedResult],
};
case AIRDCPP_SEARCH_IN_PROGRESS: case AIRDCPP_SEARCH_IN_PROGRESS:
return { return {
...state, ...state,
isAirDCPPSearchInProgress: true, isAirDCPPSearchInProgress: true,
}; };
case AIRDCPP_SEARCH_RESULTS_RECEIVED:
return {
...state,
isAirDCPPSearchInProgress: false,
searchStatus: "Search complete",
results: action.results,
};
case AIRDCPP_HUB_SEARCHES_SENT: case AIRDCPP_HUB_SEARCHES_SENT:
return { return {
...state, ...state,
searchStatus: "Hub searches sent",
isAirDCPPSearchInProgress: true, isAirDCPPSearchInProgress: true,
searchInfo: action.searchInfo, searchInfo: action.searchInfo,
searchInstance: action.instance, searchInstance: action.instance,
@@ -52,7 +50,6 @@ function airdcppReducer(state = initialState, action) {
downloadProgressData: action.downloadProgressData, downloadProgressData: action.downloadProgressData,
}; };
case AIRDCPP_BUNDLES_FETCHED: case AIRDCPP_BUNDLES_FETCHED:
console.log(action)
return { return {
...state, ...state,
bundles: action.bundles, bundles: action.bundles,
@@ -63,7 +60,7 @@ function airdcppReducer(state = initialState, action) {
}; };
default: default:
return state; return { ...state };
} }
} }