🏗️ Refactored AirDC++ session status indicator

This commit is contained in:
2023-11-07 20:06:32 -06:00
parent 936945138f
commit 18d2624d6c
6 changed files with 70 additions and 96 deletions

View File

@@ -10,6 +10,7 @@ import VolumeDetail from "./VolumeDetail/VolumeDetail";
import Downloads from "./Downloads/Downloads"; import Downloads from "./Downloads/Downloads";
import { Routes, Route } from "react-router-dom"; import { Routes, Route } 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";
@@ -46,7 +47,12 @@ export const App = (): ReactElement => {
// }); // });
// } // }
// }, []); // }, []);
return <>{/* <Navbar /> */}</>; return (
<>
<Navbar />
<Outlet />
</>
);
}; };
export default App; export default App;

View File

@@ -12,7 +12,7 @@ export const AirDCPPSettingsForm = (): ReactElement => {
const { const {
airDCPPSocketConnected, airDCPPSocketConnected,
airDCPPDisconnectionInfo, airDCPPDisconnectionInfo,
airDCPPSocketConnectionInformation, airDCPPSessionInformation,
airDCPPClientConfiguration, airDCPPClientConfiguration,
airDCPPSocketInstance, airDCPPSocketInstance,
} = useStore( } = useStore(
@@ -20,8 +20,7 @@ export const AirDCPPSettingsForm = (): ReactElement => {
airDCPPSocketConnected: state.airDCPPSocketConnected, airDCPPSocketConnected: state.airDCPPSocketConnected,
airDCPPDisconnectionInfo: state.airDCPPDisconnectionInfo, airDCPPDisconnectionInfo: state.airDCPPDisconnectionInfo,
airDCPPClientConfiguration: state.airDCPPClientConfiguration, airDCPPClientConfiguration: state.airDCPPClientConfiguration,
airDCPPSocketConnectionInformation: airDCPPSessionInformation: state.airDCPPSessionInformation,
state.airDCPPSocketConnectionInformation,
airDCPPSocketInstance: state.airDCPPSocketInstance, airDCPPSocketInstance: state.airDCPPSocketInstance,
})), })),
); );
@@ -48,10 +47,8 @@ export const AirDCPPSettingsForm = (): ReactElement => {
formHeading={"Configure AirDC++"} formHeading={"Configure AirDC++"}
/> />
{!isEmpty(airDCPPSocketConnectionInformation) ? ( {!isEmpty(airDCPPSessionInformation) ? (
<AirDCPPSettingsConfirmation <AirDCPPSettingsConfirmation settings={airDCPPSessionInformation} />
settings={airDCPPSocketConnectionInformation}
/>
) : null} ) : null}
{!isEmpty(airDCPPClientConfiguration) ? ( {!isEmpty(airDCPPClientConfiguration) ? (

View File

@@ -0,0 +1,5 @@
import React from "react";
export const ErrorPage = () => {
return <>Error has been encountered.</>;
};

View File

@@ -1,9 +1,8 @@
import React, { useContext } from "react"; import React from "react";
import { SearchBar } from "../GlobalSearchBar/SearchBar"; import { SearchBar } from "../GlobalSearchBar/SearchBar";
import { DownloadProgressTick } from "../ComicDetail/DownloadProgressTick"; import { DownloadProgressTick } from "../ComicDetail/DownloadProgressTick";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useSelector } from "react-redux"; import { isEmpty, isUndefined } from "lodash";
import { isUndefined } from "lodash";
import { format, fromUnixTime } from "date-fns"; import { format, fromUnixTime } from "date-fns";
import { useStore } from "../../store/index"; import { useStore } from "../../store/index";
import { useShallow } from "zustand/react/shallow"; import { useShallow } from "zustand/react/shallow";
@@ -12,7 +11,8 @@ const Navbar: React.FunctionComponent = (props) => {
const { const {
airDCPPSocketConnected, airDCPPSocketConnected,
airDCPPDisconnectionInfo, airDCPPDisconnectionInfo,
airDCPPSocketConnectionInformation, airDCPPSessionInformation,
airDCPPDownloadTick,
airDCPPClientConfiguration, airDCPPClientConfiguration,
airDCPPSocketInstance, airDCPPSocketInstance,
} = useStore( } = useStore(
@@ -20,43 +20,43 @@ const Navbar: React.FunctionComponent = (props) => {
airDCPPSocketConnected: state.airDCPPSocketConnected, airDCPPSocketConnected: state.airDCPPSocketConnected,
airDCPPDisconnectionInfo: state.airDCPPDisconnectionInfo, airDCPPDisconnectionInfo: state.airDCPPDisconnectionInfo,
airDCPPClientConfiguration: state.airDCPPClientConfiguration, airDCPPClientConfiguration: state.airDCPPClientConfiguration,
airDCPPSocketConnectionInformation: airDCPPSessionInformation: state.airDCPPSessionInformation,
state.airDCPPSocketConnectionInformation,
airDCPPSocketInstance: state.airDCPPSocketInstance, airDCPPSocketInstance: state.airDCPPSocketInstance,
airDCPPDownloadTick: state.airDCPPDownloadTick,
})), })),
); );
const downloadProgressTick = useSelector( // const downloadProgressTick = useSelector(
(state: RootState) => state.airdcpp.downloadProgressData, // (state: RootState) => state.airdcpp.downloadProgressData,
); // );
//
const airDCPPSocketConnectionStatus = useSelector( // const airDCPPSocketConnectionStatus = useSelector(
(state: RootState) => state.airdcpp.isAirDCPPSocketConnected, // (state: RootState) => state.airdcpp.isAirDCPPSocketConnected,
); // );
const airDCPPSessionInfo = useSelector( // const airDCPPSessionInfo = useSelector(
(state: RootState) => state.airdcpp.airDCPPSessionInfo, // (state: RootState) => state.airdcpp.airDCPPSessionInfo,
); // );
const socketDisconnectionReason = useSelector( // const socketDisconnectionReason = useSelector(
(state: RootState) => state.airdcpp.socketDisconnectionReason, // (state: RootState) => state.airdcpp.socketDisconnectionReason,
); // );
// Import-related selector hooks // Import-related selector hooks
const successfulImportJobCount = useSelector( // const successfulImportJobCount = useSelector(
(state: RootState) => state.fileOps.successfulJobCount, // (state: RootState) => state.fileOps.successfulJobCount,
); // );
const failedImportJobCount = useSelector( // const failedImportJobCount = useSelector(
(state: RootState) => state.fileOps.failedJobCount, // (state: RootState) => state.fileOps.failedJobCount,
); // );
//
const lastQueueJob = useSelector( // const lastQueueJob = useSelector(
(state: RootState) => state.fileOps.lastQueueJob, // (state: RootState) => state.fileOps.lastQueueJob,
); // );
const libraryQueueImportStatus = useSelector( // const libraryQueueImportStatus = useSelector(
(state: RootState) => state.fileOps.LSQueueImportStatus, // (state: RootState) => state.fileOps.LSQueueImportStatus,
); // );
//
const allImportJobResults = useSelector( // const allImportJobResults = useSelector(
(state: RootState) => state.fileOps.importJobStatistics, // (state: RootState) => state.fileOps.importJobStatistics,
); // );
return ( return (
<nav className="navbar is-fixed-top"> <nav className="navbar is-fixed-top">
<div className="navbar-brand"> <div className="navbar-brand">
@@ -106,7 +106,7 @@ const Navbar: React.FunctionComponent = (props) => {
Downloads Downloads
</Link> </Link>
<SearchBar /> {/* <SearchBar /> */}
<Link to="/search" className="navbar-item"> <Link to="/search" className="navbar-item">
Search ComicVine Search ComicVine
@@ -119,52 +119,22 @@ const Navbar: React.FunctionComponent = (props) => {
<div className="navbar-item has-dropdown is-hoverable"> <div className="navbar-item has-dropdown is-hoverable">
<a className="navbar-link is-arrowless"> <a className="navbar-link is-arrowless">
<i className="fa-solid fa-download"></i> <i className="fa-solid fa-download"></i>
{downloadProgressTick && <div className="pulsating-circle"></div>} {!isEmpty(airDCPPDownloadTick) && (
<div className="pulsating-circle"></div>
)}
</a> </a>
{!isUndefined(downloadProgressTick) ? ( {!isEmpty(airDCPPDownloadTick) ? (
<div className="navbar-dropdown is-right is-boxed"> <div className="navbar-dropdown is-right is-boxed">
<a className="navbar-item"> <a className="navbar-item">
<DownloadProgressTick data={downloadProgressTick} /> <DownloadProgressTick data={airDCPPDownloadTick} />
</a> </a>
</div> </div>
) : null} ) : null}
</div> </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 */} {/* AirDC++ socket connection status */}
<div className="navbar-item has-dropdown is-hoverable"> <div className="navbar-item has-dropdown is-hoverable">
{airDCPPSocketConnectionStatus ? ( {airDCPPSocketConnected ? (
<> <>
<a className="navbar-link is-arrowless has-text-success"> <a className="navbar-link is-arrowless has-text-success">
<i className="fa-solid fa-bolt"></i> <i className="fa-solid fa-bolt"></i>
@@ -176,7 +146,7 @@ const Navbar: React.FunctionComponent = (props) => {
Last login was{" "} Last login was{" "}
<span className="tag"> <span className="tag">
{format( {format(
fromUnixTime(airDCPPSessionInfo.user.last_login), fromUnixTime(airDCPPSessionInformation.user.last_login),
"dd MMMM, yyyy", "dd MMMM, yyyy",
)} )}
</span> </span>
@@ -184,15 +154,15 @@ const Navbar: React.FunctionComponent = (props) => {
<hr className="navbar-divider" /> <hr className="navbar-divider" />
<p> <p>
<span className="tag has-text-success"> <span className="tag has-text-success">
{airDCPPSessionInfo.user.username} {airDCPPSessionInformation.user.username}
</span> </span>
connected to{" "} connected to{" "}
<span className="tag has-text-success"> <span className="tag has-text-success">
{airDCPPSessionInfo.system_info.client_version} {airDCPPSessionInformation.system_info.client_version}
</span>{" "} </span>{" "}
with session ID{" "} with session ID{" "}
<span className="tag has-text-success"> <span className="tag has-text-success">
{airDCPPSessionInfo.session_id} {airDCPPSessionInformation.session_id}
</span> </span>
</p> </p>
@@ -205,9 +175,7 @@ const Navbar: React.FunctionComponent = (props) => {
<i className="fa-solid fa-bolt"></i> <i className="fa-solid fa-bolt"></i>
</a> </a>
<div className="navbar-dropdown pr-2 pl-2 is-right is-boxed"> <div className="navbar-dropdown pr-2 pl-2 is-right is-boxed">
<pre> <pre>{JSON.stringify(airDCPPDisconnectionInfo, null, 2)}</pre>
{JSON.stringify(socketDisconnectionReason, null, 2)}
</pre>
</div> </div>
</> </>
)} )}

View File

@@ -4,6 +4,7 @@ import { createRoot } from "react-dom/client";
import App from "./components/App"; import App from "./components/App";
import { createBrowserRouter, RouterProvider } from "react-router-dom"; import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Settings from "./components/Settings/Settings"; import Settings from "./components/Settings/Settings";
import { ErrorPage } from "./components/shared/ErrorPage";
const rootEl = document.getElementById("root"); const rootEl = document.getElementById("root");
const root = createRoot(rootEl); const root = createRoot(rootEl);
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
@@ -15,10 +16,8 @@ const router = createBrowserRouter([
{ {
path: "/", path: "/",
element: <App />, element: <App />,
}, errorElement: <ErrorPage />,
{ children: [{ path: "settings", element: <Settings /> }],
path: "/settings",
element: <Settings />,
}, },
]); ]);

View File

@@ -9,7 +9,7 @@ export const useStore = create((set, get) => ({
airDCPPSocketConnected: false, airDCPPSocketConnected: false,
airDCPPDisconnectionInfo: {}, airDCPPDisconnectionInfo: {},
airDCPPClientConfiguration: {}, airDCPPClientConfiguration: {},
airDCPPSocketConnectionInformation: {}, airDCPPSessionInformation: {},
setAirDCPPSocketConnectionStatus: () => setAirDCPPSocketConnectionStatus: () =>
set((value) => ({ set((value) => ({
airDCPPSocketConnected: value, airDCPPSocketConnected: value,
@@ -54,10 +54,9 @@ const initializeAirDCPPSocket = async (configuration): Promise<any> => {
}; };
// AirDC++ Socket-related connection and post-connection // AirDC++ Socket-related connection and post-connection
// Attempt connection // Attempt connection
const airDCPPSocketConnectionInformation = const airDCPPSessionInformation = await initializedAirDCPPSocket.connect();
await initializedAirDCPPSocket.connect();
setState({ setState({
airDCPPSocketConnectionInformation, airDCPPSessionInformation,
}); });
// Set up event listeners // Set up event listeners