diff --git a/src/client/components/App.tsx b/src/client/components/App.tsx
index 9e46773..8e133b4 100644
--- a/src/client/components/App.tsx
+++ b/src/client/components/App.tsx
@@ -1,45 +1,9 @@
-import React, { ReactElement, useContext, useEffect } from "react";
-import Dashboard from "./Dashboard/Dashboard";
-import Import from "./Import/Import";
-import { ComicDetailContainer } from "./ComicDetail/ComicDetailContainer";
-import TabulatedContentContainer from "./Library/TabulatedContentContainer";
-import LibraryGrid from "./Library/LibraryGrid";
-import Search from "./Search/Search";
-import Settings from "./Settings/Settings";
-import VolumeDetail from "./VolumeDetail/VolumeDetail";
-import Downloads from "./Downloads/Downloads";
-
-import { Routes, Route } from "react-router-dom";
+import React, { ReactElement } from "react";
import { Outlet } from "react-router-dom";
import Navbar from "./shared/Navbar";
import "../assets/scss/App.scss";
-import { SocketIOProvider } from "../context/SocketIOContext";
-import socketIOConnectionInstance from "../shared/socket.io/instance";
-import { isEmpty, isNil, isUndefined } from "lodash";
-import {
- AIRDCPP_DOWNLOAD_PROGRESS_TICK,
- LS_SINGLE_IMPORT,
-} from "../constants/action-types";
-
export const App = (): ReactElement => {
- // useEffect(() => {
- // // Check if there is a sessionId in localStorage
- // const sessionId = localStorage.getItem("sessionId");
- // if (!isNil(sessionId)) {
- // // Resume the session
- // dispatch({
- // type: "RESUME_SESSION",
- // meta: { remote: true },
- // session: { sessionId },
- // });
- // } else {
- // // Inititalize the session and persist the sessionId to localStorage
- // socketIOConnectionInstance.on("sessionInitialized", (sessionId) => {
- // localStorage.setItem("sessionId", sessionId);
- // });
- // }
- // }, []);
return (
<>
diff --git a/src/client/components/Import/Import.tsx b/src/client/components/Import/Import.tsx
index d370e4d..be44e10 100644
--- a/src/client/components/Import/Import.tsx
+++ b/src/client/components/Import/Import.tsx
@@ -81,7 +81,13 @@ export const Import = (props: IProps): ReactElement => {
(data) => console.log(data),
);
};
-
+ /**
+ * Method to render import job queue pause/resume controls on the UI
+ *
+ * @param status The `string` status (either `"pause"` or `"resume"`)
+ * @returns ReactElement A `` that toggles queue status
+ * @remarks Sets the global `importJobQueue.status` state upon toggling
+ */
const renderQueueControls = (status: string): ReactElement | null => {
switch (status) {
case "running":
diff --git a/src/client/store/index.ts b/src/client/store/index.ts
index 210dac5..f9b4970 100644
--- a/src/client/store/index.ts
+++ b/src/client/store/index.ts
@@ -6,6 +6,11 @@ import { produce } from "immer";
import AirDCPPSocket from "../services/DcppSearchService";
import axios from "axios";
+/* Broadly, this file sets up:
+ * 1. The zustand-based global client state
+ * 2. socket.io client
+ * 3. AirDC++ websocket connection
+ */
export const useStore = create((set, get) => ({
// AirDC++ state
airDCPPSocketInstance: {},
@@ -28,24 +33,24 @@ export const useStore = create((set, get) => ({
status: undefined,
setStatus: (status: string) =>
set(
- produce((state) => {
- state.importJobQueue.status = status;
+ produce((draftState) => {
+ draftState.importJobQueue.status = status;
}),
),
setJobCount: (jobType: string, count: Number) => {
switch (jobType) {
case "successful":
set(
- produce((state) => {
- state.importJobQueue.successfulJobCount = count;
+ produce((draftState) => {
+ draftState.importJobQueue.successfulJobCount = count;
}),
);
break;
case "failed":
set(
- produce((state) => {
- state.importJobQueue.failedJobCount = count;
+ produce((draftState) => {
+ draftState.importJobQueue.failedJobCount = count;
}),
);
break;
@@ -64,20 +69,23 @@ export const useStore = create((set, get) => ({
const { getState, setState } = useStore;
-// Fetch sessionId from localStorage
+// Socket.IO initialization
+// 1. Fetch sessionId from localStorage
const sessionId = localStorage.getItem("sessionId");
-// socket.io instantiation
+// 2. socket.io instantiation
const socketIOInstance = io(SOCKET_BASE_URI, {
transports: ["websocket"],
withCredentials: true,
query: { sessionId },
});
+// 3. Set the instance in global state
setState({
socketIOInstance,
});
+// Socket.io-based session restoration
if (!isNil(sessionId)) {
- // Resume the session
+ // 1. Resume the session
socketIOInstance.emit(
"call",
"socket.resumeSession",
@@ -87,11 +95,24 @@ if (!isNil(sessionId)) {
(data) => console.log(data),
);
} else {
- // Inititalize the session and persist the sessionId to localStorage
+ // 1. Inititalize the session and persist the sessionId to localStorage
socketIOInstance.on("sessionInitialized", (sessionId) => {
localStorage.setItem("sessionId", sessionId);
});
}
+// 2. If a job is in progress, restore the job counts and persist those to global state
+socketIOInstance.on("RESTORE_JOB_COUNTS_AFTER_SESSION_RESTORATION", (data) => {
+ console.log("Active import in progress detected; restoring counts...");
+ const { completedJobCount, failedJobCount, queueStatus } = data;
+ setState((state) => ({
+ importJobQueue: {
+ ...state.importJobQueue,
+ successfulJobCount: completedJobCount,
+ failedJobCount,
+ status: queueStatus,
+ },
+ }));
+});
/**
* Method to init AirDC++ Socket with supplied settings