🏗️ Refactored the Import page

This commit is contained in:
2023-11-15 15:13:49 -06:00
parent 794fd9b3a0
commit 7e304b2b96
3 changed files with 39 additions and 48 deletions

View File

@@ -1,45 +1,9 @@
import React, { ReactElement, useContext, useEffect } from "react"; import React, { ReactElement } 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 { Outlet } from "react-router-dom"; import { Outlet } from "react-router-dom";
import Navbar from "./shared/Navbar"; import Navbar from "./shared/Navbar";
import "../assets/scss/App.scss"; 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 => { 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 ( return (
<> <>
<Navbar /> <Navbar />

View File

@@ -81,7 +81,13 @@ export const Import = (props: IProps): ReactElement => {
(data) => console.log(data), (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 `<button/>` that toggles queue status
* @remarks Sets the global `importJobQueue.status` state upon toggling
*/
const renderQueueControls = (status: string): ReactElement | null => { const renderQueueControls = (status: string): ReactElement | null => {
switch (status) { switch (status) {
case "running": case "running":

View File

@@ -6,6 +6,11 @@ import { produce } from "immer";
import AirDCPPSocket from "../services/DcppSearchService"; import AirDCPPSocket from "../services/DcppSearchService";
import axios from "axios"; 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) => ({ export const useStore = create((set, get) => ({
// AirDC++ state // AirDC++ state
airDCPPSocketInstance: {}, airDCPPSocketInstance: {},
@@ -28,24 +33,24 @@ export const useStore = create((set, get) => ({
status: undefined, status: undefined,
setStatus: (status: string) => setStatus: (status: string) =>
set( set(
produce((state) => { produce((draftState) => {
state.importJobQueue.status = status; draftState.importJobQueue.status = status;
}), }),
), ),
setJobCount: (jobType: string, count: Number) => { setJobCount: (jobType: string, count: Number) => {
switch (jobType) { switch (jobType) {
case "successful": case "successful":
set( set(
produce((state) => { produce((draftState) => {
state.importJobQueue.successfulJobCount = count; draftState.importJobQueue.successfulJobCount = count;
}), }),
); );
break; break;
case "failed": case "failed":
set( set(
produce((state) => { produce((draftState) => {
state.importJobQueue.failedJobCount = count; draftState.importJobQueue.failedJobCount = count;
}), }),
); );
break; break;
@@ -64,20 +69,23 @@ export const useStore = create((set, get) => ({
const { getState, setState } = useStore; const { getState, setState } = useStore;
// Fetch sessionId from localStorage // Socket.IO initialization
// 1. Fetch sessionId from localStorage
const sessionId = localStorage.getItem("sessionId"); const sessionId = localStorage.getItem("sessionId");
// socket.io instantiation // 2. socket.io instantiation
const socketIOInstance = io(SOCKET_BASE_URI, { const socketIOInstance = io(SOCKET_BASE_URI, {
transports: ["websocket"], transports: ["websocket"],
withCredentials: true, withCredentials: true,
query: { sessionId }, query: { sessionId },
}); });
// 3. Set the instance in global state
setState({ setState({
socketIOInstance, socketIOInstance,
}); });
// Socket.io-based session restoration
if (!isNil(sessionId)) { if (!isNil(sessionId)) {
// Resume the session // 1. Resume the session
socketIOInstance.emit( socketIOInstance.emit(
"call", "call",
"socket.resumeSession", "socket.resumeSession",
@@ -87,11 +95,24 @@ if (!isNil(sessionId)) {
(data) => console.log(data), (data) => console.log(data),
); );
} else { } else {
// Inititalize the session and persist the sessionId to localStorage // 1. Inititalize the session and persist the sessionId to localStorage
socketIOInstance.on("sessionInitialized", (sessionId) => { socketIOInstance.on("sessionInitialized", (sessionId) => {
localStorage.setItem("sessionId", 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 * Method to init AirDC++ Socket with supplied settings