🏗️ Refactoring archive uncompression for "Read Comic" and "Analysis" user flows (#46)
* 🔧 Refactoring uncompression methods on client-side * ✏️ Refactoring * 👁️ Updates to the comic viewer * 🖼️ Added screenshots from December 2022 * ✏️ Fixed typo in README * 🏗️ Massive refactor around archive uncompression for reading/analysis * 🔧 Tweaked state vars for reading and analysis * 🏗️ 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 was merged in pull request #46.
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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}`,
|
||||
|
||||
@@ -66,7 +66,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
||||
);
|
||||
|
||||
const extractedComicBook = useSelector(
|
||||
(state: RootState) => state.fileOps.extractedComicBookArchive,
|
||||
(state: RootState) => state.fileOps.extractedComicBookArchive.reading,
|
||||
);
|
||||
const { comicObjectId } = useParams<{ comicObjectId: string }>();
|
||||
|
||||
@@ -77,7 +77,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
||||
dispatch(
|
||||
extractComicArchive(filePath, {
|
||||
type: "full",
|
||||
purpose: "readComicBook",
|
||||
purpose: "reading",
|
||||
imageResizeOptions: {
|
||||
baseWidth: 1024,
|
||||
},
|
||||
|
||||
@@ -38,7 +38,8 @@ 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>
|
||||
|
||||
@@ -14,7 +14,7 @@ export const ArchiveOperations = (props): ReactElement => {
|
||||
(state: RootState) => state.fileOps.comicBookExtractionInProgress,
|
||||
);
|
||||
const extractedComicBookArchive = useSelector(
|
||||
(state: RootState) => state.fileOps.extractedComicBookArchive,
|
||||
(state: RootState) => state.fileOps.extractedComicBookArchive.analysis,
|
||||
);
|
||||
|
||||
const imageAnalysisResult = useSelector((state: RootState) => {
|
||||
@@ -23,7 +23,15 @@ export const ArchiveOperations = (props): ReactElement => {
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const unpackComicArchive = useCallback(() => {
|
||||
dispatch(extractComicArchive(data.rawFileDetails.filePath));
|
||||
dispatch(
|
||||
extractComicArchive(data.rawFileDetails.filePath, {
|
||||
type: "full",
|
||||
purpose: "analysis",
|
||||
imageResizeOptions: {
|
||||
baseWidth: 275,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}, []);
|
||||
|
||||
// sliding panel config
|
||||
|
||||
@@ -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} />
|
||||
|
||||
@@ -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",
|
||||
}),
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user