🏗️ Refactor to support DC++ and socket.io integration

This refactor covers the following workflows:

1. Adding a comic from LOCG or ComicVine adds it to the wanted list
2. Downloading that comic from DC++ correctly adds download metadata to the corresponding comic object in mongo
3. Successful download triggers automatic import to library and cover extraction, metadata application
This commit is contained in:
2022-12-21 21:07:22 -08:00
parent bf6f18c5d5
commit 0d41b57d18
10 changed files with 96 additions and 70 deletions

View File

@@ -18,18 +18,22 @@ import {
AirDCPPSocketContext,
} from "../context/AirDCPPSocket";
import { isEmpty, isUndefined } from "lodash";
import { AIRDCPP_DOWNLOAD_PROGRESS_TICK } from "../constants/action-types";
import { useDispatch } from "react-redux";
import {
AIRDCPP_DOWNLOAD_PROGRESS_TICK,
LS_SINGLE_IMPORT,
} from "../constants/action-types";
import { useDispatch, useSelector } from "react-redux";
/**
* Method that initializes an AirDC++ socket connection
* 1. Initializes event listeners for download init, tick and complete events
* 2. Handles errors in case the connection to AirDC++ is not established or terminated
* @returns void
* 2. Handles errors in case the connection to AirDC++ is not established or terminated
* @returns void
*/
const AirDCPPSocketComponent = (): ReactElement => {
const airDCPPConfiguration = useContext(AirDCPPSocketContext);
const dispatch = useDispatch();
useEffect(() => {
const initializeAirDCPPEventListeners = async () => {
if (
@@ -42,9 +46,7 @@ const AirDCPPSocketComponent = (): ReactElement => {
"queue_bundle_added",
async (data) => {
console.log("JEMEN:", data);
}
},
);
// download tick listener
await airDCPPConfiguration.airDCPPState.socket.addListener(
@@ -62,9 +64,18 @@ const AirDCPPSocketComponent = (): ReactElement => {
`queue`,
"queue_bundle_status",
async (bundleData) => {
let count = 0;
if (bundleData.status.completed && bundleData.status.downloaded) {
// dispatch the action for raw import, with the metadata
console.log("IM THE MAN UP IN THIS")
if (count < 1) {
console.log(`[AirDCPP]: Download complete.`);
dispatch({
type: LS_SINGLE_IMPORT,
meta: { remote: true },
data: bundleData,
});
count += 1;
}
}
},
);
@@ -92,7 +103,10 @@ export const App = (): ReactElement => {
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/import" element={<Import path={"./comics"} />} />
<Route path="/library" element={<TabulatedContentContainer category="library" />} />
<Route
path="/library"
element={<TabulatedContentContainer category="library" />}
/>
<Route path="/library-grid" element={<LibraryGrid />} />
<Route path="/downloads" element={<Downloads data={{}} />} />
<Route path="/search" element={<Search />} />
@@ -105,9 +119,18 @@ export const App = (): ReactElement => {
element={<VolumeDetail />}
/>
<Route path="/settings" element={<Settings />} />
<Route path="/pull-list/all" element={<TabulatedContentContainer category="pullList" />} />
<Route path="/wanted/all" element={<TabulatedContentContainer category="wanted" />} />
<Route path="/volumes/all" element={<TabulatedContentContainer category="volumes" />} />
<Route
path="/pull-list/all"
element={<TabulatedContentContainer category="pullList" />}
/>
<Route
path="/wanted/all"
element={<TabulatedContentContainer category="wanted" />}
/>
<Route
path="/volumes/all"
element={<TabulatedContentContainer category="volumes" />}
/>
</Routes>
</div>
</AirDCPPSocketContextProvider>

View File

@@ -16,6 +16,7 @@ import ellipsize from "ellipsize";
import { Form, Field } from "react-final-form";
import { isEmpty, isNil, map } from "lodash";
import { AirDCPPSocketContext } from "../../context/AirDCPPSocket";
interface IAcquisitionPanelProps {
query: any;
comicObjectId: any;
@@ -96,9 +97,12 @@ export const AcquisitionPanel = (
(searchInstanceId, resultId, name, size, type) => {
dispatch(
downloadAirDCPPItem(
searchInstanceId, resultId,
searchInstanceId,
resultId,
props.comicObjectId,
name, size, type,
name,
size,
type,
airDCPPConfiguration.airDCPPState.socket,
{
username: `${airDCPPConfiguration.airDCPPState.settings.directConnect.client.host.username}`,

View File

@@ -38,7 +38,7 @@ export const RawFileDetails = (props): ReactElement => {
</dd>
</dl>
</div>
<div className="content comic-detail raw-file-details mt-3 column is-one-third">
<div className="content comic-detail raw-file-details mt-3 column is-three-fifths">
<dl>
{/* inferred metadata */}
<dt>Inferred Issue Metadata</dt>

View File

@@ -11,7 +11,7 @@ import {
getComicBooks,
} from "../../actions/fileops.actions";
import { getLibraryStatistics } from "../../actions/comicinfo.actions";
import { isEmpty } from "lodash";
import { isEmpty, isNil } from "lodash";
export const Dashboard = (): ReactElement => {
const dispatch = useDispatch();
@@ -43,7 +43,7 @@ export const Dashboard = (): ReactElement => {
}, []);
const recentComics = useSelector(
(state: RootState) => state.fileOps.recentComics,
(state: RootState) => state.fileOps.recentComics
);
const wantedComics = useSelector(
(state: RootState) => state.fileOps.wantedComics,
@@ -60,7 +60,7 @@ export const Dashboard = (): ReactElement => {
<section className="section">
<h1 className="title">Dashboard</h1>
{!isEmpty(recentComics) && !isEmpty(recentComics.docs) ? (
{!isEmpty(recentComics) ? (
<>
{/* Pull List */}
<PullList issues={recentComics} />
@@ -74,9 +74,8 @@ export const Dashboard = (): ReactElement => {
<WantedComicsList comics={wantedComics} />
)}
{/* Recent imports */}
{!isEmpty(recentComics) && (
<RecentlyImported comicBookCovers={recentComics} />
)}
{/* Volumes */}
{!isEmpty(volumeGroups) && (
<VolumeGroups volumeGroups={volumeGroups} />

View File

@@ -20,7 +20,7 @@ export const PullList = ({ issues }: PullListProps): ReactElement => {
useEffect(() => {
dispatch(
getWeeklyPullList({
startDate: "2022-11-15",
startDate: "2022-12-25",
pageSize: "15",
currentPage: "1",
}),

View File

@@ -24,7 +24,6 @@ export const RecentlyImported = ({
700: 2,
600: 2,
};
return (
<>
<div className="content mt-5">
@@ -41,7 +40,7 @@ export const RecentlyImported = ({
columnClassName="recent-comics-column"
>
{map(
comicBookCovers.docs,
comicBookCovers,
(
{
_id,
@@ -53,6 +52,7 @@ export const RecentlyImported = ({
},
idx,
) => {
console.log(comicvine);
const { issueName, url } = determineCoverFile({
rawFileDetails,
comicvine,
@@ -64,7 +64,7 @@ export const RecentlyImported = ({
comicInfo,
locg,
});
console.log(name);
const isComicBookMetadataAvailable =
!isUndefined(comicvine) &&
!isUndefined(comicvine.volumeInformation);
@@ -123,7 +123,7 @@ export const RecentlyImported = ({
</div>
</Card>
{/* metadata card */}
{!isNil(name) ? (
{!isNil(name) && (
<Card orientation="horizontal" hasDetails imageUrl={coverURL}>
<dd className="is-size-9">
<dl>
@@ -138,7 +138,7 @@ export const RecentlyImported = ({
</dl>
</dd>
</Card>
) : null}
)}
</React.Fragment>
);
},