🏗️ 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:
@@ -63,7 +63,7 @@
|
|||||||
"pretty-bytes": "^5.6.0",
|
"pretty-bytes": "^5.6.0",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"qs": "^6.10.5",
|
"qs": "^6.10.5",
|
||||||
"react": "^18.1.0",
|
"react": "^18.2.0",
|
||||||
"react-collapsible": "^2.9.0",
|
"react-collapsible": "^2.9.0",
|
||||||
"react-comic-viewer": "^0.4.0",
|
"react-comic-viewer": "^0.4.0",
|
||||||
"react-day-picker": "^8.0.6",
|
"react-day-picker": "^8.0.6",
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import {
|
|||||||
CV_WEEKLY_PULLLIST_FETCHED,
|
CV_WEEKLY_PULLLIST_FETCHED,
|
||||||
} from "../constants/action-types";
|
} from "../constants/action-types";
|
||||||
import { success } from "react-notification-system-redux";
|
import { success } from "react-notification-system-redux";
|
||||||
import { removeLeadingPeriod } from "../shared/utils/formatting.utils";
|
|
||||||
import { isNil, map } from "lodash";
|
import { isNil, map } from "lodash";
|
||||||
|
|
||||||
export async function walkFolder(path: string): Promise<Array<IFolderData>> {
|
export async function walkFolder(path: string): Promise<Array<IFolderData>> {
|
||||||
@@ -60,15 +60,6 @@ export async function walkFolder(path: string): Promise<Array<IFolderData>> {
|
|||||||
* @return the comic book metadata
|
* @return the comic book metadata
|
||||||
*/
|
*/
|
||||||
export const fetchComicBookMetadata = () => async (dispatch) => {
|
export const fetchComicBookMetadata = () => async (dispatch) => {
|
||||||
const extractionOptions = {
|
|
||||||
extractTarget: "cover",
|
|
||||||
targetExtractionFolder: "./userdata/covers",
|
|
||||||
extractionMode: "bulk",
|
|
||||||
paginationOptions: {
|
|
||||||
pageLimit: 25,
|
|
||||||
page: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: LS_IMPORT_CALL_IN_PROGRESS,
|
type: LS_IMPORT_CALL_IN_PROGRESS,
|
||||||
});
|
});
|
||||||
@@ -86,7 +77,7 @@ export const fetchComicBookMetadata = () => async (dispatch) => {
|
|||||||
dispatch({
|
dispatch({
|
||||||
type: LS_IMPORT,
|
type: LS_IMPORT,
|
||||||
meta: { remote: true },
|
meta: { remote: true },
|
||||||
data: { extractionOptions },
|
data: {},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
export const toggleImportQueueStatus = (options) => async (dispatch) => {
|
export const toggleImportQueueStatus = (options) => async (dispatch) => {
|
||||||
@@ -136,21 +127,24 @@ export const getComicBooks = (options) => async (dispatch) => {
|
|||||||
* @returns Nothing.
|
* @returns Nothing.
|
||||||
* @param payload
|
* @param payload
|
||||||
*/
|
*/
|
||||||
export const importToDB = (sourceName: string, payload?: any) => (dispatch) => {
|
export const importToDB = (sourceName: string, metadata?: any) => (dispatch) => {
|
||||||
try {
|
try {
|
||||||
const comicBookMetadata = {
|
const comicBookMetadata = {
|
||||||
rawFileDetails: {
|
importType: "new",
|
||||||
name: "",
|
payload: {
|
||||||
},
|
rawFileDetails: {
|
||||||
importStatus: {
|
name: "",
|
||||||
isImported: true,
|
|
||||||
tagged: false,
|
|
||||||
matchedResult: {
|
|
||||||
score: "0",
|
|
||||||
},
|
},
|
||||||
},
|
importStatus: {
|
||||||
sourcedMetadata: payload || null,
|
isImported: true,
|
||||||
acquisition: { source: { wanted: true, name: sourceName } },
|
tagged: false,
|
||||||
|
matchedResult: {
|
||||||
|
score: "0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sourcedMetadata: metadata || null,
|
||||||
|
acquisition: { source: { wanted: true, name: sourceName } },
|
||||||
|
}
|
||||||
};
|
};
|
||||||
dispatch({
|
dispatch({
|
||||||
type: IMS_CV_METADATA_IMPORT_CALL_IN_PROGRESS,
|
type: IMS_CV_METADATA_IMPORT_CALL_IN_PROGRESS,
|
||||||
@@ -260,34 +254,31 @@ export const fetchComicVineMatches =
|
|||||||
* @returns {any}
|
* @returns {any}
|
||||||
*/
|
*/
|
||||||
export const extractComicArchive =
|
export const extractComicArchive =
|
||||||
(path: string, options: any): any => async (dispatch) => {
|
|
||||||
const comicBookPages: string[] = [];
|
|
||||||
console.log(options);
|
|
||||||
dispatch({
|
|
||||||
type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS,
|
|
||||||
});
|
|
||||||
const extractedComicBookArchive = await axios({
|
|
||||||
method: "POST",
|
|
||||||
url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`,
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json; charset=utf-8",
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
filePath: path,
|
|
||||||
options,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
map(extractedComicBookArchive.data, (page) => {
|
|
||||||
const pageFilePath = removeLeadingPeriod(page);
|
|
||||||
const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`);
|
|
||||||
comicBookPages.push(imagePath);
|
|
||||||
});
|
|
||||||
dispatch({
|
|
||||||
type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS,
|
|
||||||
extractedComicBookArchive: comicBookPages,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
(path: string, options: any): any =>
|
||||||
|
async (dispatch) => {
|
||||||
|
dispatch({
|
||||||
|
type: IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS,
|
||||||
|
});
|
||||||
|
await axios({
|
||||||
|
method: "POST",
|
||||||
|
url: `${LIBRARY_SERVICE_BASE_URI}/uncompressFullArchive`,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
filePath: path,
|
||||||
|
options,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description
|
||||||
|
* @param {any} query
|
||||||
|
* @param {any} options
|
||||||
|
* @returns {any}
|
||||||
|
*/
|
||||||
export const searchIssue = (query, options) => async (dispatch) => {
|
export const searchIssue = (query, options) => async (dispatch) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: SS_SEARCH_IN_PROGRESS,
|
type: SS_SEARCH_IN_PROGRESS,
|
||||||
|
|||||||
@@ -18,18 +18,22 @@ import {
|
|||||||
AirDCPPSocketContext,
|
AirDCPPSocketContext,
|
||||||
} from "../context/AirDCPPSocket";
|
} from "../context/AirDCPPSocket";
|
||||||
import { isEmpty, isUndefined } from "lodash";
|
import { isEmpty, isUndefined } from "lodash";
|
||||||
import { AIRDCPP_DOWNLOAD_PROGRESS_TICK } from "../constants/action-types";
|
import {
|
||||||
import { useDispatch } from "react-redux";
|
AIRDCPP_DOWNLOAD_PROGRESS_TICK,
|
||||||
|
LS_SINGLE_IMPORT,
|
||||||
|
} from "../constants/action-types";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method that initializes an AirDC++ socket connection
|
* Method that initializes an AirDC++ socket connection
|
||||||
* 1. Initializes event listeners for download init, tick and complete events
|
* 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
|
* 2. Handles errors in case the connection to AirDC++ is not established or terminated
|
||||||
* @returns void
|
* @returns void
|
||||||
*/
|
*/
|
||||||
const AirDCPPSocketComponent = (): ReactElement => {
|
const AirDCPPSocketComponent = (): ReactElement => {
|
||||||
const airDCPPConfiguration = useContext(AirDCPPSocketContext);
|
const airDCPPConfiguration = useContext(AirDCPPSocketContext);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initializeAirDCPPEventListeners = async () => {
|
const initializeAirDCPPEventListeners = async () => {
|
||||||
if (
|
if (
|
||||||
@@ -42,9 +46,7 @@ const AirDCPPSocketComponent = (): ReactElement => {
|
|||||||
"queue_bundle_added",
|
"queue_bundle_added",
|
||||||
async (data) => {
|
async (data) => {
|
||||||
console.log("JEMEN:", data);
|
console.log("JEMEN:", data);
|
||||||
|
},
|
||||||
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
// download tick listener
|
// download tick listener
|
||||||
await airDCPPConfiguration.airDCPPState.socket.addListener(
|
await airDCPPConfiguration.airDCPPState.socket.addListener(
|
||||||
@@ -62,9 +64,18 @@ const AirDCPPSocketComponent = (): ReactElement => {
|
|||||||
`queue`,
|
`queue`,
|
||||||
"queue_bundle_status",
|
"queue_bundle_status",
|
||||||
async (bundleData) => {
|
async (bundleData) => {
|
||||||
|
let count = 0;
|
||||||
if (bundleData.status.completed && bundleData.status.downloaded) {
|
if (bundleData.status.completed && bundleData.status.downloaded) {
|
||||||
// dispatch the action for raw import, with the metadata
|
// 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>
|
<Routes>
|
||||||
<Route path="/" element={<Dashboard />} />
|
<Route path="/" element={<Dashboard />} />
|
||||||
<Route path="/import" element={<Import path={"./comics"} />} />
|
<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="/library-grid" element={<LibraryGrid />} />
|
||||||
<Route path="/downloads" element={<Downloads data={{}} />} />
|
<Route path="/downloads" element={<Downloads data={{}} />} />
|
||||||
<Route path="/search" element={<Search />} />
|
<Route path="/search" element={<Search />} />
|
||||||
@@ -105,9 +119,18 @@ export const App = (): ReactElement => {
|
|||||||
element={<VolumeDetail />}
|
element={<VolumeDetail />}
|
||||||
/>
|
/>
|
||||||
<Route path="/settings" element={<Settings />} />
|
<Route path="/settings" element={<Settings />} />
|
||||||
<Route path="/pull-list/all" element={<TabulatedContentContainer category="pullList" />} />
|
<Route
|
||||||
<Route path="/wanted/all" element={<TabulatedContentContainer category="wanted" />} />
|
path="/pull-list/all"
|
||||||
<Route path="/volumes/all" element={<TabulatedContentContainer category="volumes" />} />
|
element={<TabulatedContentContainer category="pullList" />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/wanted/all"
|
||||||
|
element={<TabulatedContentContainer category="wanted" />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/volumes/all"
|
||||||
|
element={<TabulatedContentContainer category="volumes" />}
|
||||||
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
</AirDCPPSocketContextProvider>
|
</AirDCPPSocketContextProvider>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import ellipsize from "ellipsize";
|
|||||||
import { Form, Field } from "react-final-form";
|
import { Form, Field } from "react-final-form";
|
||||||
import { isEmpty, isNil, map } from "lodash";
|
import { isEmpty, isNil, map } from "lodash";
|
||||||
import { AirDCPPSocketContext } from "../../context/AirDCPPSocket";
|
import { AirDCPPSocketContext } from "../../context/AirDCPPSocket";
|
||||||
|
|
||||||
interface IAcquisitionPanelProps {
|
interface IAcquisitionPanelProps {
|
||||||
query: any;
|
query: any;
|
||||||
comicObjectId: any;
|
comicObjectId: any;
|
||||||
@@ -96,9 +97,12 @@ export const AcquisitionPanel = (
|
|||||||
(searchInstanceId, resultId, name, size, type) => {
|
(searchInstanceId, resultId, name, size, type) => {
|
||||||
dispatch(
|
dispatch(
|
||||||
downloadAirDCPPItem(
|
downloadAirDCPPItem(
|
||||||
searchInstanceId, resultId,
|
searchInstanceId,
|
||||||
|
resultId,
|
||||||
props.comicObjectId,
|
props.comicObjectId,
|
||||||
name, size, type,
|
name,
|
||||||
|
size,
|
||||||
|
type,
|
||||||
airDCPPConfiguration.airDCPPState.socket,
|
airDCPPConfiguration.airDCPPState.socket,
|
||||||
{
|
{
|
||||||
username: `${airDCPPConfiguration.airDCPPState.settings.directConnect.client.host.username}`,
|
username: `${airDCPPConfiguration.airDCPPState.settings.directConnect.client.host.username}`,
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const extractedComicBook = useSelector(
|
const extractedComicBook = useSelector(
|
||||||
(state: RootState) => state.fileOps.extractedComicBookArchive,
|
(state: RootState) => state.fileOps.extractedComicBookArchive.reading,
|
||||||
);
|
);
|
||||||
const { comicObjectId } = useParams<{ comicObjectId: string }>();
|
const { comicObjectId } = useParams<{ comicObjectId: string }>();
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ export const ComicDetail = (data: ComicDetailProps): ReactElement => {
|
|||||||
dispatch(
|
dispatch(
|
||||||
extractComicArchive(filePath, {
|
extractComicArchive(filePath, {
|
||||||
type: "full",
|
type: "full",
|
||||||
purpose: "readComicBook",
|
purpose: "reading",
|
||||||
imageResizeOptions: {
|
imageResizeOptions: {
|
||||||
baseWidth: 1024,
|
baseWidth: 1024,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ export const RawFileDetails = (props): ReactElement => {
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</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>
|
<dl>
|
||||||
{/* inferred metadata */}
|
{/* inferred metadata */}
|
||||||
<dt>Inferred Issue Metadata</dt>
|
<dt>Inferred Issue Metadata</dt>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ export const ArchiveOperations = (props): ReactElement => {
|
|||||||
(state: RootState) => state.fileOps.comicBookExtractionInProgress,
|
(state: RootState) => state.fileOps.comicBookExtractionInProgress,
|
||||||
);
|
);
|
||||||
const extractedComicBookArchive = useSelector(
|
const extractedComicBookArchive = useSelector(
|
||||||
(state: RootState) => state.fileOps.extractedComicBookArchive,
|
(state: RootState) => state.fileOps.extractedComicBookArchive.analysis,
|
||||||
);
|
);
|
||||||
|
|
||||||
const imageAnalysisResult = useSelector((state: RootState) => {
|
const imageAnalysisResult = useSelector((state: RootState) => {
|
||||||
@@ -23,7 +23,15 @@ export const ArchiveOperations = (props): ReactElement => {
|
|||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const unpackComicArchive = useCallback(() => {
|
const unpackComicArchive = useCallback(() => {
|
||||||
dispatch(extractComicArchive(data.rawFileDetails.filePath));
|
dispatch(
|
||||||
|
extractComicArchive(data.rawFileDetails.filePath, {
|
||||||
|
type: "full",
|
||||||
|
purpose: "analysis",
|
||||||
|
imageResizeOptions: {
|
||||||
|
baseWidth: 275,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// sliding panel config
|
// sliding panel config
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
getComicBooks,
|
getComicBooks,
|
||||||
} from "../../actions/fileops.actions";
|
} from "../../actions/fileops.actions";
|
||||||
import { getLibraryStatistics } from "../../actions/comicinfo.actions";
|
import { getLibraryStatistics } from "../../actions/comicinfo.actions";
|
||||||
import { isEmpty } from "lodash";
|
import { isEmpty, isNil } from "lodash";
|
||||||
|
|
||||||
export const Dashboard = (): ReactElement => {
|
export const Dashboard = (): ReactElement => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -43,7 +43,7 @@ export const Dashboard = (): ReactElement => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const recentComics = useSelector(
|
const recentComics = useSelector(
|
||||||
(state: RootState) => state.fileOps.recentComics,
|
(state: RootState) => state.fileOps.recentComics
|
||||||
);
|
);
|
||||||
const wantedComics = useSelector(
|
const wantedComics = useSelector(
|
||||||
(state: RootState) => state.fileOps.wantedComics,
|
(state: RootState) => state.fileOps.wantedComics,
|
||||||
@@ -60,7 +60,7 @@ export const Dashboard = (): ReactElement => {
|
|||||||
<section className="section">
|
<section className="section">
|
||||||
<h1 className="title">Dashboard</h1>
|
<h1 className="title">Dashboard</h1>
|
||||||
|
|
||||||
{!isEmpty(recentComics) && !isEmpty(recentComics.docs) ? (
|
{!isEmpty(recentComics) ? (
|
||||||
<>
|
<>
|
||||||
{/* Pull List */}
|
{/* Pull List */}
|
||||||
<PullList issues={recentComics} />
|
<PullList issues={recentComics} />
|
||||||
@@ -74,9 +74,8 @@ export const Dashboard = (): ReactElement => {
|
|||||||
<WantedComicsList comics={wantedComics} />
|
<WantedComicsList comics={wantedComics} />
|
||||||
)}
|
)}
|
||||||
{/* Recent imports */}
|
{/* Recent imports */}
|
||||||
{!isEmpty(recentComics) && (
|
|
||||||
<RecentlyImported comicBookCovers={recentComics} />
|
<RecentlyImported comicBookCovers={recentComics} />
|
||||||
)}
|
|
||||||
{/* Volumes */}
|
{/* Volumes */}
|
||||||
{!isEmpty(volumeGroups) && (
|
{!isEmpty(volumeGroups) && (
|
||||||
<VolumeGroups volumeGroups={volumeGroups} />
|
<VolumeGroups volumeGroups={volumeGroups} />
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ export const PullList = ({ issues }: PullListProps): ReactElement => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(
|
dispatch(
|
||||||
getWeeklyPullList({
|
getWeeklyPullList({
|
||||||
startDate: "2022-11-15",
|
startDate: "2022-12-25",
|
||||||
pageSize: "15",
|
pageSize: "15",
|
||||||
currentPage: "1",
|
currentPage: "1",
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ export const RecentlyImported = ({
|
|||||||
700: 2,
|
700: 2,
|
||||||
600: 2,
|
600: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="content mt-5">
|
<div className="content mt-5">
|
||||||
@@ -41,7 +40,7 @@ export const RecentlyImported = ({
|
|||||||
columnClassName="recent-comics-column"
|
columnClassName="recent-comics-column"
|
||||||
>
|
>
|
||||||
{map(
|
{map(
|
||||||
comicBookCovers.docs,
|
comicBookCovers,
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
_id,
|
_id,
|
||||||
@@ -53,6 +52,7 @@ export const RecentlyImported = ({
|
|||||||
},
|
},
|
||||||
idx,
|
idx,
|
||||||
) => {
|
) => {
|
||||||
|
console.log(comicvine);
|
||||||
const { issueName, url } = determineCoverFile({
|
const { issueName, url } = determineCoverFile({
|
||||||
rawFileDetails,
|
rawFileDetails,
|
||||||
comicvine,
|
comicvine,
|
||||||
@@ -64,7 +64,7 @@ export const RecentlyImported = ({
|
|||||||
comicInfo,
|
comicInfo,
|
||||||
locg,
|
locg,
|
||||||
});
|
});
|
||||||
|
console.log(name);
|
||||||
const isComicBookMetadataAvailable =
|
const isComicBookMetadataAvailable =
|
||||||
!isUndefined(comicvine) &&
|
!isUndefined(comicvine) &&
|
||||||
!isUndefined(comicvine.volumeInformation);
|
!isUndefined(comicvine.volumeInformation);
|
||||||
@@ -123,7 +123,7 @@ export const RecentlyImported = ({
|
|||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
{/* metadata card */}
|
{/* metadata card */}
|
||||||
{!isNil(name) ? (
|
{!isNil(name) && (
|
||||||
<Card orientation="horizontal" hasDetails imageUrl={coverURL}>
|
<Card orientation="horizontal" hasDetails imageUrl={coverURL}>
|
||||||
<dd className="is-size-9">
|
<dd className="is-size-9">
|
||||||
<dl>
|
<dl>
|
||||||
@@ -138,7 +138,7 @@ export const RecentlyImported = ({
|
|||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
</Card>
|
</Card>
|
||||||
) : null}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_IN_PROGRESS =
|
|||||||
export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_FAILED =
|
export const IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_FAILED =
|
||||||
"IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_FAILED";
|
"IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_CALL_FAILED";
|
||||||
|
|
||||||
|
export const COMICBOOK_EXTRACTION_SUCCESS = "COMICBOOK_EXTRACTION_SUCCESS";
|
||||||
|
|
||||||
// Image file stats
|
// Image file stats
|
||||||
export const IMG_ANALYSIS_CALL_IN_PROGRESS = "IMG_ANALYSIS_CALL_IN_PROGRESS";
|
export const IMG_ANALYSIS_CALL_IN_PROGRESS = "IMG_ANALYSIS_CALL_IN_PROGRESS";
|
||||||
export const IMG_ANALYSIS_DATA_FETCH_SUCCESS =
|
export const IMG_ANALYSIS_DATA_FETCH_SUCCESS =
|
||||||
|
|||||||
@@ -29,7 +29,11 @@ import {
|
|||||||
SS_SEARCH_FAILED,
|
SS_SEARCH_FAILED,
|
||||||
SS_SEARCH_RESULTS_FETCHED_SPECIAL,
|
SS_SEARCH_RESULTS_FETCHED_SPECIAL,
|
||||||
VOLUMES_FETCHED,
|
VOLUMES_FETCHED,
|
||||||
|
COMICBOOK_EXTRACTION_SUCCESS,
|
||||||
} from "../constants/action-types";
|
} from "../constants/action-types";
|
||||||
|
import { removeLeadingPeriod } from "../shared/utils/formatting.utils";
|
||||||
|
import { LIBRARY_SERVICE_HOST } from "../constants/endpoints";
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
IMSCallInProgress: false,
|
IMSCallInProgress: false,
|
||||||
IMGCallInProgress: false,
|
IMGCallInProgress: false,
|
||||||
@@ -42,7 +46,10 @@ const initialState = {
|
|||||||
isComicVineMetadataImportInProgress: false,
|
isComicVineMetadataImportInProgress: false,
|
||||||
comicVineMetadataImportError: {},
|
comicVineMetadataImportError: {},
|
||||||
rawImportError: {},
|
rawImportError: {},
|
||||||
extractedComicBookArchive: [],
|
extractedComicBookArchive: {
|
||||||
|
reading: [],
|
||||||
|
analysis: [],
|
||||||
|
},
|
||||||
recentComics: [],
|
recentComics: [],
|
||||||
wantedComics: [],
|
wantedComics: [],
|
||||||
libraryComics: [],
|
libraryComics: [],
|
||||||
@@ -81,7 +88,7 @@ function fileOpsReducer(state = initialState, action) {
|
|||||||
case IMS_RECENT_COMICS_FETCHED:
|
case IMS_RECENT_COMICS_FETCHED:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
recentComics: action.data,
|
recentComics: action.data.docs,
|
||||||
};
|
};
|
||||||
case IMS_WANTED_COMICS_FETCHED:
|
case IMS_WANTED_COMICS_FETCHED:
|
||||||
return {
|
return {
|
||||||
@@ -131,13 +138,7 @@ function fileOpsReducer(state = initialState, action) {
|
|||||||
comicBookExtractionInProgress: true,
|
comicBookExtractionInProgress: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case IMS_COMIC_BOOK_ARCHIVE_EXTRACTION_SUCCESS: {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
extractedComicBookArchive: action.extractedComicBookArchive,
|
|
||||||
comicBookExtractionInProgress: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case LOCATION_CHANGE: {
|
case LOCATION_CHANGE: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@@ -152,11 +153,44 @@ function fileOpsReducer(state = initialState, action) {
|
|||||||
}
|
}
|
||||||
case LS_COVER_EXTRACTED: {
|
case LS_COVER_EXTRACTED: {
|
||||||
console.log("BASH", action);
|
console.log("BASH", action);
|
||||||
|
if(state.recentComics.length === 5) {
|
||||||
|
state.recentComics.pop();
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
librarySearchResultCount: state.librarySearchResultCount + 1,
|
librarySearchResultCount: state.librarySearchResultCount + 1,
|
||||||
|
recentComics: [...state.recentComics, action.result.data.importResult]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case COMICBOOK_EXTRACTION_SUCCESS: {
|
||||||
|
const comicBookPages: string[] = [];
|
||||||
|
map(action.result.files, (page) => {
|
||||||
|
const pageFilePath = removeLeadingPeriod(page);
|
||||||
|
const imagePath = encodeURI(`${LIBRARY_SERVICE_HOST}${pageFilePath}`);
|
||||||
|
comicBookPages.push(imagePath);
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (action.result.purpose) {
|
||||||
|
case "reading":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
extractedComicBookArchive: {
|
||||||
|
reading: comicBookPages,
|
||||||
|
},
|
||||||
|
comicBookExtractionInProgress: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
case "analysis":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
extractedComicBookArchive: {
|
||||||
|
analysis: comicBookPages,
|
||||||
|
},
|
||||||
|
comicBookExtractionInProgress: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
case LS_QUEUE_DRAINED: {
|
case LS_QUEUE_DRAINED: {
|
||||||
console.log("drained", action);
|
console.log("drained", action);
|
||||||
return {
|
return {
|
||||||
@@ -229,7 +263,7 @@ function fileOpsReducer(state = initialState, action) {
|
|||||||
volumes: action.data,
|
volumes: action.data,
|
||||||
SSCallInProgress: false,
|
SSCallInProgress: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
case SS_SEARCH_FAILED: {
|
case SS_SEARCH_FAILED: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|||||||
@@ -67,7 +67,10 @@ export const determineCoverFile = (data) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const determineExternalMetadata = (metadataSource, source) => {
|
export const determineExternalMetadata = (
|
||||||
|
metadataSource: string,
|
||||||
|
source: any
|
||||||
|
) => {
|
||||||
switch (metadataSource) {
|
switch (metadataSource) {
|
||||||
case "comicvine":
|
case "comicvine":
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -15607,7 +15607,7 @@ react-transition-group@4.4.2, react-transition-group@^4.3.0:
|
|||||||
loose-envify "^1.4.0"
|
loose-envify "^1.4.0"
|
||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
|
|
||||||
react@^18.1.0:
|
react@^18.2.0:
|
||||||
version "18.2.0"
|
version "18.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||||
|
|||||||
Reference in New Issue
Block a user