🏗️ Trying out react-query
This commit is contained in:
@@ -23,7 +23,11 @@ import {
|
||||
AIRDCPP_DOWNLOAD_PROGRESS_TICK,
|
||||
LS_SINGLE_IMPORT,
|
||||
} from "../constants/action-types";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||
|
||||
const queryClient = new QueryClient({});
|
||||
|
||||
/**
|
||||
* Method that initializes an AirDC++ socket connection
|
||||
@@ -32,128 +36,93 @@ import { useDispatch, useSelector } from "react-redux";
|
||||
* @returns void
|
||||
*/
|
||||
const AirDCPPSocketComponent = (): ReactElement => {
|
||||
const airDCPPConfiguration = useContext(AirDCPPSocketContext);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
const initializeAirDCPPEventListeners = async () => {
|
||||
if (
|
||||
!isUndefined(airDCPPConfiguration.airDCPPState) &&
|
||||
!isEmpty(airDCPPConfiguration.airDCPPState.settings) &&
|
||||
!isEmpty(airDCPPConfiguration.airDCPPState.socket)
|
||||
) {
|
||||
await airDCPPConfiguration.airDCPPState.socket.addListener(
|
||||
"queue",
|
||||
"queue_bundle_added",
|
||||
async (data) => {
|
||||
console.log("JEMEN:", data);
|
||||
},
|
||||
);
|
||||
// download tick listener
|
||||
await airDCPPConfiguration.airDCPPState.socket.addListener(
|
||||
`queue`,
|
||||
"queue_bundle_tick",
|
||||
async (downloadProgressData) => {
|
||||
dispatch({
|
||||
type: AIRDCPP_DOWNLOAD_PROGRESS_TICK,
|
||||
downloadProgressData,
|
||||
});
|
||||
},
|
||||
);
|
||||
// download complete listener
|
||||
await airDCPPConfiguration.airDCPPState.socket.addListener(
|
||||
`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
|
||||
if (count < 1) {
|
||||
console.log(`[AirDCPP]: Download complete.`);
|
||||
dispatch({
|
||||
type: LS_SINGLE_IMPORT,
|
||||
meta: { remote: true },
|
||||
data: bundleData,
|
||||
});
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
console.log(
|
||||
"[AirDCPP]: Listener registered - listening to queue bundle download ticks",
|
||||
);
|
||||
console.log(
|
||||
"[AirDCPP]: Listener registered - listening to queue bundle changes",
|
||||
);
|
||||
console.log(
|
||||
"[AirDCPP]: Listener registered - listening to transfer completion",
|
||||
);
|
||||
}
|
||||
};
|
||||
initializeAirDCPPEventListeners();
|
||||
}, [airDCPPConfiguration]);
|
||||
// const airDCPPConfiguration = useContext(AirDCPPSocketContext);
|
||||
// const dispatch = useDispatch();
|
||||
//
|
||||
// useEffect(() => {
|
||||
// const initializeAirDCPPEventListeners = async () => {
|
||||
// if (
|
||||
// !isUndefined(airDCPPConfiguration.airDCPPState) &&
|
||||
// !isEmpty(airDCPPConfiguration.airDCPPState.settings) &&
|
||||
// !isEmpty(airDCPPConfiguration.airDCPPState.socket)
|
||||
// ) {
|
||||
// await airDCPPConfiguration.airDCPPState.socket.addListener(
|
||||
// "queue",
|
||||
// "queue_bundle_added",
|
||||
// async (data) => {
|
||||
// console.log("JEMEN:", data);
|
||||
// },
|
||||
// );
|
||||
// // download tick listener
|
||||
// await airDCPPConfiguration.airDCPPState.socket.addListener(
|
||||
// `queue`,
|
||||
// "queue_bundle_tick",
|
||||
// async (downloadProgressData) => {
|
||||
// dispatch({
|
||||
// type: AIRDCPP_DOWNLOAD_PROGRESS_TICK,
|
||||
// downloadProgressData,
|
||||
// });
|
||||
// },
|
||||
// );
|
||||
// // download complete listener
|
||||
// await airDCPPConfiguration.airDCPPState.socket.addListener(
|
||||
// `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
|
||||
// if (count < 1) {
|
||||
// console.log(`[AirDCPP]: Download complete.`);
|
||||
// dispatch({
|
||||
// type: LS_SINGLE_IMPORT,
|
||||
// meta: { remote: true },
|
||||
// data: bundleData,
|
||||
// });
|
||||
// count += 1;
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// );
|
||||
// console.log(
|
||||
// "[AirDCPP]: Listener registered - listening to queue bundle download ticks",
|
||||
// );
|
||||
// console.log(
|
||||
// "[AirDCPP]: Listener registered - listening to queue bundle changes",
|
||||
// );
|
||||
// console.log(
|
||||
// "[AirDCPP]: Listener registered - listening to transfer completion",
|
||||
// );
|
||||
// }
|
||||
// };
|
||||
// initializeAirDCPPEventListeners();
|
||||
// }, [airDCPPConfiguration]);
|
||||
return <></>;
|
||||
};
|
||||
export const App = (): ReactElement => {
|
||||
const dispatch = useDispatch();
|
||||
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);
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
// 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 (
|
||||
<SocketIOProvider socket={socketIOConnectionInstance}>
|
||||
<AirDCPPSocketContextProvider>
|
||||
<div>
|
||||
<AirDCPPSocketComponent />
|
||||
<Routes>
|
||||
<Route path="/" element={<Dashboard />} />
|
||||
<Route path="/import" element={<Import path={"./comics"} />} />
|
||||
<Route
|
||||
path="/library"
|
||||
element={<TabulatedContentContainer category="library" />}
|
||||
/>
|
||||
<Route path="/library-grid" element={<LibraryGrid />} />
|
||||
<Route path="/downloads" element={<Downloads data={{}} />} />
|
||||
<Route path="/search" element={<Search />} />
|
||||
<Route
|
||||
path={"/comic/details/:comicObjectId"}
|
||||
element={<ComicDetailContainer />}
|
||||
/>
|
||||
<Route
|
||||
path={"/volume/details/:comicObjectId"}
|
||||
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" />}
|
||||
/>
|
||||
</Routes>
|
||||
</div>
|
||||
</AirDCPPSocketContextProvider>
|
||||
</SocketIOProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{/* The rest of your application */}
|
||||
<ReactQueryDevtools initialIsOpen={true} />
|
||||
{/* <AirDCPPSocketComponent /> */};
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@ import { isEmpty, isNil } from "lodash";
|
||||
import Header from "../shared/Header";
|
||||
|
||||
export const Dashboard = (): ReactElement => {
|
||||
const dispatch = useDispatch();
|
||||
// useEffect(() => {
|
||||
// dispatch(fetchVolumeGroups());
|
||||
// dispatch(
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import React, { ReactElement, useCallback } from "react";
|
||||
import { saveSettings } from "../../../actions/settings.actions";
|
||||
import { ConnectionForm } from "../../shared/ConnectionForm/ConnectionForm";
|
||||
import { useConnectToQBittorrentClientQuery } from "../../../services/torrents.api";
|
||||
|
||||
export const QbittorrentConnectionForm = (): ReactElement => {
|
||||
const { data, isLoading } = useConnectToQBittorrentClientQuery({});
|
||||
const onSubmit = useCallback(async (values) => {
|
||||
try {
|
||||
dispatch(saveSettings(values, "bittorrent"));
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
@@ -15,13 +12,11 @@ export const QbittorrentConnectionForm = (): ReactElement => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isLoading && (
|
||||
<ConnectionForm
|
||||
initialData={data?.bittorrent.client.host}
|
||||
submitHandler={onSubmit}
|
||||
formHeading={"Qbittorrent Configuration"}
|
||||
/>
|
||||
)}
|
||||
<ConnectionForm
|
||||
initialData={data?.bittorrent.client.host}
|
||||
submitHandler={onSubmit}
|
||||
formHeading={"Qbittorrent Configuration"}
|
||||
/>
|
||||
<pre>{JSON.stringify(data?.qbittorrentClientInfo, null, 2)}</pre>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -7,22 +7,18 @@ import { ServiceStatuses } from "../ServiceStatuses/ServiceStatuses";
|
||||
import settingsObject from "../../constants/settings/settingsMenu.json";
|
||||
import { isUndefined, map } from "lodash";
|
||||
|
||||
interface ISettingsProps { }
|
||||
interface ISettingsProps {}
|
||||
|
||||
export const Settings = (props: ISettingsProps): ReactElement => {
|
||||
const [active, setActive] = useState("gen-db");
|
||||
const settingsContent = [
|
||||
{
|
||||
id: "adc-hubs",
|
||||
content: <div key="adc-hubs">{<AirDCPPHubsForm />}</div>,
|
||||
content: <div key="adc-hubs">{/* <AirDCPPHubsForm /> */}</div>,
|
||||
},
|
||||
{
|
||||
id: "adc-connection",
|
||||
content: (
|
||||
<div key="adc-connection">
|
||||
<AirDCPPSettingsForm />
|
||||
</div>
|
||||
),
|
||||
content: <div key="adc-connection">{/* <AirDCPPSettingsForm /> */}</div>,
|
||||
},
|
||||
{
|
||||
id: "qbt-connection",
|
||||
@@ -34,15 +30,11 @@ export const Settings = (props: ISettingsProps): ReactElement => {
|
||||
},
|
||||
{
|
||||
id: "core-service",
|
||||
content: <ServiceStatuses />,
|
||||
content: <>a</>,
|
||||
},
|
||||
{
|
||||
id: "flushdb",
|
||||
content: (
|
||||
<div key="flushdb">
|
||||
<SystemSettingsForm />
|
||||
</div>
|
||||
),
|
||||
content: <div key="flushdb">{/* <SystemSettingsForm /> */}</div>,
|
||||
},
|
||||
];
|
||||
return (
|
||||
|
||||
@@ -2,46 +2,10 @@ import React, { useContext } from "react";
|
||||
import { SearchBar } from "../GlobalSearchBar/SearchBar";
|
||||
import { DownloadProgressTick } from "../ComicDetail/DownloadProgressTick";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import { isUndefined } from "lodash";
|
||||
import { format, fromUnixTime } from "date-fns";
|
||||
|
||||
const Navbar: React.FunctionComponent = (props) => {
|
||||
const downloadProgressTick = useSelector(
|
||||
(state: RootState) => state.airdcpp.downloadProgressData,
|
||||
);
|
||||
|
||||
const airDCPPSocketConnectionStatus = useSelector(
|
||||
(state: RootState) => state.airdcpp.isAirDCPPSocketConnected,
|
||||
);
|
||||
const airDCPPSessionInfo = useSelector(
|
||||
(state: RootState) => state.airdcpp.airDCPPSessionInfo,
|
||||
);
|
||||
const qBittorrentConnectionInfo = useSelector(
|
||||
(state: RootState) => state.settings.data,
|
||||
);
|
||||
const socketDisconnectionReason = useSelector(
|
||||
(state: RootState) => state.airdcpp.socketDisconnectionReason,
|
||||
);
|
||||
|
||||
// Import-related selector hooks
|
||||
const successfulImportJobCount = useSelector(
|
||||
(state: RootState) => state.fileOps.successfulJobCount,
|
||||
);
|
||||
const failedImportJobCount = useSelector(
|
||||
(state: RootState) => state.fileOps.failedJobCount,
|
||||
);
|
||||
|
||||
const lastQueueJob = useSelector(
|
||||
(state: RootState) => state.fileOps.lastQueueJob,
|
||||
);
|
||||
const libraryQueueImportStatus = useSelector(
|
||||
(state: RootState) => state.fileOps.LSQueueImportStatus,
|
||||
);
|
||||
|
||||
const allImportJobResults = useSelector(
|
||||
(state: RootState) => state.fileOps.importJobStatistics,
|
||||
);
|
||||
return (
|
||||
<nav className="navbar is-fixed-top">
|
||||
<div className="navbar-brand">
|
||||
@@ -91,8 +55,6 @@ const Navbar: React.FunctionComponent = (props) => {
|
||||
Downloads
|
||||
</Link>
|
||||
|
||||
<SearchBar />
|
||||
|
||||
<Link to="/search" className="navbar-item">
|
||||
Search ComicVine
|
||||
</Link>
|
||||
@@ -101,102 +63,7 @@ const Navbar: React.FunctionComponent = (props) => {
|
||||
<div className="navbar-end">
|
||||
<a className="navbar-item is-hidden-desktop-only"></a>
|
||||
|
||||
<div className="navbar-item has-dropdown is-hoverable">
|
||||
<a className="navbar-link is-arrowless">
|
||||
<i className="fa-solid fa-download"></i>
|
||||
{downloadProgressTick && <div className="pulsating-circle"></div>}
|
||||
</a>
|
||||
{!isUndefined(downloadProgressTick) ? (
|
||||
<div className="navbar-dropdown is-right is-boxed">
|
||||
<a className="navbar-item">
|
||||
<DownloadProgressTick data={downloadProgressTick} />
|
||||
</a>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{!isUndefined(libraryQueueImportStatus) &&
|
||||
location.hash !== "#/import" ? (
|
||||
<div className="navbar-item has-dropdown is-hoverable">
|
||||
<a className="navbar-link is-arrowless">
|
||||
<i className="fa-solid fa-file-import has-text-warning-dark"></i>
|
||||
</a>
|
||||
|
||||
<div className="navbar-dropdown is-right is-boxed">
|
||||
<a className="navbar-item">
|
||||
<ul>
|
||||
{successfulImportJobCount > 0 ? (
|
||||
<li className="mb-2">
|
||||
<span className="tag is-success mr-2">
|
||||
{successfulImportJobCount}
|
||||
</span>
|
||||
imported.
|
||||
</li>
|
||||
) : null}
|
||||
{failedImportJobCount > 0 ? (
|
||||
<li>
|
||||
<span className="tag is-danger mr-2">
|
||||
{failedImportJobCount}
|
||||
</span>
|
||||
failed to import.
|
||||
</li>
|
||||
) : null}
|
||||
</ul>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* AirDC++ socket connection status */}
|
||||
<div className="navbar-item has-dropdown is-hoverable">
|
||||
{airDCPPSocketConnectionStatus ? (
|
||||
<>
|
||||
<a className="navbar-link is-arrowless">
|
||||
<i className="fa-solid fa-tower-cell"></i>
|
||||
</a>
|
||||
<div className="navbar-dropdown pr-2 pl-2 is-right airdcpp-status is-boxed">
|
||||
{/* AirDC++ Session Information */}
|
||||
|
||||
<p>
|
||||
Last login was{" "}
|
||||
<span className="tag">
|
||||
{format(
|
||||
fromUnixTime(airDCPPSessionInfo.user.last_login),
|
||||
"dd MMMM, yyyy",
|
||||
)}
|
||||
</span>
|
||||
</p>
|
||||
<hr className="navbar-divider" />
|
||||
<p>
|
||||
<span className="tag has-text-success">
|
||||
{airDCPPSessionInfo.user.username}
|
||||
</span>
|
||||
connected to{" "}
|
||||
<span className="tag has-text-success">
|
||||
{airDCPPSessionInfo.system_info.client_version}
|
||||
</span>{" "}
|
||||
with session ID{" "}
|
||||
<span className="tag has-text-success">
|
||||
{airDCPPSessionInfo.session_id}
|
||||
</span>
|
||||
</p>
|
||||
|
||||
{/* <pre>{JSON.stringify(airDCPPSessionInfo, null, 2)}</pre> */}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<a className="navbar-link is-arrowless has-text-danger">
|
||||
<i className="fa-solid fa-bolt"></i>
|
||||
</a>
|
||||
<div className="navbar-dropdown pr-2 pl-2 is-right is-boxed">
|
||||
<pre>
|
||||
{JSON.stringify(socketDisconnectionReason, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="navbar-item has-dropdown is-hoverable is-mega">
|
||||
<div className="navbar-link flex">Blog</div>
|
||||
|
||||
Reference in New Issue
Block a user