🏗️ Refactored Import page to read from global state
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
"final-form-arrays": "^3.0.2",
|
"final-form-arrays": "^3.0.2",
|
||||||
"history": "^5.3.0",
|
"history": "^5.3.0",
|
||||||
"html-to-text": "^8.1.0",
|
"html-to-text": "^8.1.0",
|
||||||
|
"immer": "^10.0.3",
|
||||||
"jsdoc": "^3.6.10",
|
"jsdoc": "^3.6.10",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"pretty-bytes": "^5.6.0",
|
"pretty-bytes": "^5.6.0",
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React, { ReactElement, useCallback, useEffect } from "react";
|
import React, { ReactElement, useCallback, useEffect } from "react";
|
||||||
import { useSelector, useDispatch } from "react-redux";
|
|
||||||
import {
|
import {
|
||||||
fetchComicBookMetadata,
|
fetchComicBookMetadata,
|
||||||
getImportJobResultStatistics,
|
getImportJobResultStatistics,
|
||||||
@@ -9,6 +8,10 @@ import "react-loader-spinner/dist/loader/css/react-spinner-loader.css";
|
|||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import Loader from "react-loader-spinner";
|
import Loader from "react-loader-spinner";
|
||||||
import { isEmpty, isNil, isUndefined } from "lodash";
|
import { isEmpty, isNil, isUndefined } from "lodash";
|
||||||
|
import { useQuery, useMutation } from "@tanstack/react-query";
|
||||||
|
import { useStore } from "../../store";
|
||||||
|
import { useShallow } from "zustand/react/shallow";
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
matches?: unknown;
|
matches?: unknown;
|
||||||
@@ -31,41 +34,62 @@ interface IProps {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export const Import = (props: IProps): ReactElement => {
|
export const Import = (props: IProps): ReactElement => {
|
||||||
const dispatch = useDispatch();
|
const { importJobQueue, socketIOInstance } = useStore(
|
||||||
const successfulImportJobCount = useSelector(
|
useShallow((state) => ({
|
||||||
(state: RootState) => state.fileOps.successfulJobCount,
|
importJobQueue: state.importJobQueue,
|
||||||
);
|
socketIOInstance: state.socketIOInstance,
|
||||||
const failedImportJobCount = useSelector(
|
})),
|
||||||
(state: RootState) => state.fileOps.failedJobCount,
|
|
||||||
);
|
);
|
||||||
|
// 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,
|
||||||
|
// );
|
||||||
|
|
||||||
const lastQueueJob = useSelector(
|
const sessionId = localStorage.getItem("sessionId");
|
||||||
(state: RootState) => state.fileOps.lastQueueJob,
|
const { mutate: initiateImport } = useMutation({
|
||||||
);
|
mutationFn: async () =>
|
||||||
const libraryQueueImportStatus = useSelector(
|
await axios.request({
|
||||||
(state: RootState) => state.fileOps.LSQueueImportStatus,
|
url: `http://localhost:3000/api/library/newImport`,
|
||||||
);
|
method: "POST",
|
||||||
|
data: { sessionId },
|
||||||
const allImportJobResults = useSelector(
|
}),
|
||||||
(state: RootState) => state.fileOps.importJobStatistics,
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const initiateImport = useCallback(() => {
|
|
||||||
if (typeof props.path !== "undefined") {
|
|
||||||
dispatch(fetchComicBookMetadata(props.path));
|
|
||||||
}
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
|
// Act on each comic issue successfully imported, as indicated
|
||||||
|
// by the LS_COVER_EXTRACTED event
|
||||||
|
socketIOInstance.on("LS_COVER_EXTRACTED", (data) => {
|
||||||
|
const { completedJobCount } = data;
|
||||||
|
importJobQueue.setJobCount("successful", completedJobCount);
|
||||||
|
});
|
||||||
|
socketIOInstance.on("LS_COVER_EXTRACTION_FAILED", (data) => {
|
||||||
|
console.log(data);
|
||||||
|
const { failedJobCount } = data;
|
||||||
|
importJobQueue.setJobCount("failed", failedJobCount);
|
||||||
|
});
|
||||||
const toggleQueue = useCallback(
|
const toggleQueue = useCallback(
|
||||||
(queueAction: string, queueStatus: string) => {
|
(queueAction: string, queueStatus: string) => {
|
||||||
dispatch(setQueueControl(queueAction, queueStatus));
|
// dispatch(setQueueControl(queueAction, queueStatus));
|
||||||
},
|
},
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch(getImportJobResultStatistics());
|
// dispatch(getImportJobResultStatistics());
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const libraryQueueImportStatus = undefined;
|
||||||
const renderQueueControls = (status: string): ReactElement | null => {
|
const renderQueueControls = (status: string): ReactElement | null => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case "running":
|
case "running":
|
||||||
@@ -128,7 +152,7 @@ export const Import = (props: IProps): ReactElement => {
|
|||||||
? "button is-medium"
|
? "button is-medium"
|
||||||
: "button is-loading is-medium"
|
: "button is-loading is-medium"
|
||||||
}
|
}
|
||||||
onClick={initiateImport}
|
onClick={() => initiateImport()}
|
||||||
>
|
>
|
||||||
<span className="icon">
|
<span className="icon">
|
||||||
<i className="fas fa-file-import"></i>
|
<i className="fas fa-file-import"></i>
|
||||||
@@ -136,60 +160,58 @@ export const Import = (props: IProps): ReactElement => {
|
|||||||
<span>Start Import</span>
|
<span>Start Import</span>
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
{libraryQueueImportStatus !== "drained" &&
|
|
||||||
!isUndefined(libraryQueueImportStatus) && (
|
|
||||||
<>
|
|
||||||
<table className="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Completed Jobs</th>
|
|
||||||
<th>Failed Jobs</th>
|
|
||||||
<th>Queue Controls</th>
|
|
||||||
<th>Queue Status</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
<>
|
||||||
<tr>
|
<table className="table">
|
||||||
<th>
|
<thead>
|
||||||
{successfulImportJobCount > 0 && (
|
<tr>
|
||||||
<div className="box has-background-success-light has-text-centered">
|
<th>Completed Jobs</th>
|
||||||
<span className="is-size-2 has-text-weight-bold">
|
<th>Failed Jobs</th>
|
||||||
{successfulImportJobCount}
|
<th>Queue Controls</th>
|
||||||
</span>
|
<th>Queue Status</th>
|
||||||
</div>
|
</tr>
|
||||||
)}
|
</thead>
|
||||||
</th>
|
|
||||||
<td>
|
|
||||||
{failedImportJobCount > 0 && (
|
|
||||||
<div className="box has-background-danger has-text-centered">
|
|
||||||
<span className="is-size-2 has-text-weight-bold">
|
|
||||||
{failedImportJobCount}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td>{renderQueueControls(libraryQueueImportStatus)}</td>
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
{importJobQueue.successfulJobCount > 0 && (
|
||||||
|
<div className="box has-background-success-light has-text-centered">
|
||||||
|
<span className="is-size-2 has-text-weight-bold">
|
||||||
|
{importJobQueue.successfulJobCount}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
{importJobQueue.failedJobCount > 0 && (
|
||||||
|
<div className="box has-background-danger has-text-centered">
|
||||||
|
<span className="is-size-2 has-text-weight-bold">
|
||||||
|
{importJobQueue.failedJobCount}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{/* <td>{renderQueueControls(libraryQueueImportStatus)}</td>
|
||||||
<td>
|
<td>
|
||||||
{libraryQueueImportStatus !== undefined ? (
|
{libraryQueueImportStatus !== undefined ? (
|
||||||
<span className="tag is-warning">
|
<span className="tag is-warning">
|
||||||
{libraryQueueImportStatus}
|
{libraryQueueImportStatus}
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
</td>
|
</td> */}
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
Imported{" "}
|
Imported{" "}
|
||||||
<span className="has-text-weight-bold">{lastQueueJob}</span>
|
{/* <span className="has-text-weight-bold">{lastQueueJob}</span> */}
|
||||||
</>
|
</>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Past imports */}
|
{/* Past imports */}
|
||||||
|
|
||||||
<h3 className="subtitle is-4 mt-5">Past Imports</h3>
|
<h3 className="subtitle is-4 mt-5">Past Imports</h3>
|
||||||
<table className="table">
|
{/* <table className="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Time Started</th>
|
<th>Time Started</th>
|
||||||
@@ -228,7 +250,7 @@ export const Import = (props: IProps): ReactElement => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table> */}
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -38,7 +38,11 @@ export const Settings = (props: ISettingsProps): ReactElement => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "flushdb",
|
id: "flushdb",
|
||||||
content: <div key="flushdb">{/* <SystemSettingsForm /> */}</div>,
|
content: (
|
||||||
|
<div key="flushdb">
|
||||||
|
<SystemSettingsForm />
|
||||||
|
</div>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import React, { ReactElement, useCallback } from "react";
|
import React, { ReactElement } from "react";
|
||||||
import { flushDb } from "../../../actions/settings.actions";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import axios from "axios";
|
||||||
|
|
||||||
export const SystemSettingsForm = (): ReactElement => {
|
export const SystemSettingsForm = (): ReactElement => {
|
||||||
const dispatch = useDispatch();
|
const { mutate: flushDb, isLoading } = useMutation({
|
||||||
const isSettingsCallInProgress = useSelector(
|
mutationFn: async () => {
|
||||||
(state: RootState) => state.settings.inProgress,
|
await axios({
|
||||||
);
|
url: `http://localhost:3000/api/library/flushDb`,
|
||||||
const flushDatabase = useCallback(() => {
|
method: "POST",
|
||||||
dispatch(flushDb());
|
});
|
||||||
}, []);
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="is-clearfix">
|
<div className="is-clearfix">
|
||||||
@@ -48,11 +49,9 @@ export const SystemSettingsForm = (): ReactElement => {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
className={
|
className={
|
||||||
isSettingsCallInProgress
|
isLoading ? "button is-danger is-loading" : "button is-danger"
|
||||||
? "button is-danger is-loading"
|
|
||||||
: "button is-danger"
|
|
||||||
}
|
}
|
||||||
onClick={flushDatabase}
|
onClick={() => flushDb()}
|
||||||
>
|
>
|
||||||
<span className="icon">
|
<span className="icon">
|
||||||
<i className="fas fa-eraser"></i>
|
<i className="fas fa-eraser"></i>
|
||||||
|
|||||||
@@ -13,15 +13,11 @@ const Navbar: React.FunctionComponent = (props) => {
|
|||||||
airDCPPDisconnectionInfo,
|
airDCPPDisconnectionInfo,
|
||||||
airDCPPSessionInformation,
|
airDCPPSessionInformation,
|
||||||
airDCPPDownloadTick,
|
airDCPPDownloadTick,
|
||||||
airDCPPClientConfiguration,
|
|
||||||
airDCPPSocketInstance,
|
|
||||||
} = useStore(
|
} = useStore(
|
||||||
useShallow((state) => ({
|
useShallow((state) => ({
|
||||||
airDCPPSocketConnected: state.airDCPPSocketConnected,
|
airDCPPSocketConnected: state.airDCPPSocketConnected,
|
||||||
airDCPPDisconnectionInfo: state.airDCPPDisconnectionInfo,
|
airDCPPDisconnectionInfo: state.airDCPPDisconnectionInfo,
|
||||||
airDCPPClientConfiguration: state.airDCPPClientConfiguration,
|
|
||||||
airDCPPSessionInformation: state.airDCPPSessionInformation,
|
airDCPPSessionInformation: state.airDCPPSessionInformation,
|
||||||
airDCPPSocketInstance: state.airDCPPSocketInstance,
|
|
||||||
airDCPPDownloadTick: state.airDCPPDownloadTick,
|
airDCPPDownloadTick: state.airDCPPDownloadTick,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
import { isEmpty, isUndefined } from "lodash";
|
|
||||||
import React, { createContext, useEffect, useState } from "react";
|
|
||||||
import { useQuery, useMutation } from "@tanstack/react-query";
|
|
||||||
import { useStore } from "../store/index";
|
|
||||||
import AirDCPPSocket from "../services/DcppSearchService";
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
const AirDCPPSocketContextProvider = ({ children }) => {
|
|
||||||
const { getState, setState } = useStore;
|
|
||||||
// setter for settings for use in the context consumer
|
|
||||||
const setSettings = (settingsObject) => {
|
|
||||||
persistSettings({
|
|
||||||
...airDCPPState,
|
|
||||||
airDCPPState: {
|
|
||||||
settings: settingsObject,
|
|
||||||
socket: {},
|
|
||||||
socketConnectionInformation: {},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// Initial state for AirDC++ configuration
|
|
||||||
const initState = {
|
|
||||||
airDCPPState: {
|
|
||||||
settings: {},
|
|
||||||
socket: {},
|
|
||||||
socketConnectionInformation: {},
|
|
||||||
},
|
|
||||||
setSettings: setSettings,
|
|
||||||
};
|
|
||||||
const [airDCPPState, persistSettings] = useState(initState);
|
|
||||||
|
|
||||||
// 1. get settings from mongo
|
|
||||||
const { data, isLoading, isError } = useQuery({
|
|
||||||
queryKey: ["settings"],
|
|
||||||
queryFn: async () =>
|
|
||||||
await axios({
|
|
||||||
url: "http://localhost:3000/api/settings/getAllSettings",
|
|
||||||
method: "GET",
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const directConnectConfiguration = data?.data.directConnect.client.host;
|
|
||||||
|
|
||||||
// 2. If available, init AirDC++ Socket with those settings
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isEmpty(directConnectConfiguration)) {
|
|
||||||
initializeAirDCPPSocket(directConnectConfiguration);
|
|
||||||
}
|
|
||||||
}, [directConnectConfiguration]);
|
|
||||||
|
|
||||||
// Method to init AirDC++ Socket with supplied settings
|
|
||||||
const initializeAirDCPPSocket = async (configuration) => {
|
|
||||||
console.log("[AirDCPP]: Initializing socket...");
|
|
||||||
|
|
||||||
const initializedAirDCPPSocket = new AirDCPPSocket({
|
|
||||||
protocol: `${configuration.protocol}`,
|
|
||||||
hostname: `${configuration.hostname}:${configuration.port}`,
|
|
||||||
username: `${configuration.username}`,
|
|
||||||
password: `${configuration.password}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set up connect and disconnect handlers
|
|
||||||
initializedAirDCPPSocket.onConnected = (sessionInfo) => {
|
|
||||||
// update global state with socket connection status
|
|
||||||
setState({
|
|
||||||
airDCPPSocketConnected: true,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
initializedAirDCPPSocket.onDisconnected = async (
|
|
||||||
reason,
|
|
||||||
code,
|
|
||||||
wasClean,
|
|
||||||
) => {
|
|
||||||
// update global state with socket connection status
|
|
||||||
setState({
|
|
||||||
disconnectionInfo: { reason, code, wasClean },
|
|
||||||
airDCPPSocketConnected: false,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// Attempt connection
|
|
||||||
const socketConnectionInformation =
|
|
||||||
await initializedAirDCPPSocket.connect();
|
|
||||||
|
|
||||||
// update the state with the new socket connection information
|
|
||||||
persistSettings({
|
|
||||||
...airDCPPState,
|
|
||||||
airDCPPState: {
|
|
||||||
settings: configuration,
|
|
||||||
socket: initializedAirDCPPSocket,
|
|
||||||
socketConnectionInformation,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log("connected?", getState());
|
|
||||||
// the Provider gives access to the context to its children
|
|
||||||
return (
|
|
||||||
<AirDCPPSocketContext.Provider value={airDCPPState}>
|
|
||||||
{children}
|
|
||||||
</AirDCPPSocketContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
const AirDCPPSocketContext = createContext({
|
|
||||||
airDCPPState: {},
|
|
||||||
saveSettings: () => {},
|
|
||||||
});
|
|
||||||
|
|
||||||
export { AirDCPPSocketContext, AirDCPPSocketContextProvider };
|
|
||||||
@@ -9,6 +9,7 @@ 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";
|
||||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
||||||
|
import Import from "./components/Import/Import";
|
||||||
|
|
||||||
const queryClient = new QueryClient();
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
@@ -17,7 +18,10 @@ const router = createBrowserRouter([
|
|||||||
path: "/",
|
path: "/",
|
||||||
element: <App />,
|
element: <App />,
|
||||||
errorElement: <ErrorPage />,
|
errorElement: <ErrorPage />,
|
||||||
children: [{ path: "settings", element: <Settings /> }],
|
children: [
|
||||||
|
{ path: "settings", element: <Settings /> },
|
||||||
|
{ path: "import", element: <Import path={"./comics"} /> },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { create } from "zustand";
|
import { create } from "zustand";
|
||||||
import { isEmpty } from "lodash";
|
import { isEmpty } from "lodash";
|
||||||
|
import io from "socket.io-client";
|
||||||
|
import { SOCKET_BASE_URI } from "../constants/endpoints";
|
||||||
|
import { produce } from "immer";
|
||||||
import AirDCPPSocket from "../services/DcppSearchService";
|
import AirDCPPSocket from "../services/DcppSearchService";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
@@ -14,15 +17,49 @@ export const useStore = create((set, get) => ({
|
|||||||
set((value) => ({
|
set((value) => ({
|
||||||
airDCPPSocketConnected: value,
|
airDCPPSocketConnected: value,
|
||||||
})),
|
})),
|
||||||
getAirDCPPConnectionStatus: () => {
|
|
||||||
const airDCPPSocketConnectionStatus = get().airDCPPSocketConnected;
|
|
||||||
},
|
|
||||||
airDCPPDownloadTick: {},
|
airDCPPDownloadTick: {},
|
||||||
// Socket.io state
|
// Socket.io state
|
||||||
|
socketIOInstance: {},
|
||||||
|
|
||||||
|
// Import job results
|
||||||
|
importJobQueue: {
|
||||||
|
successfulJobCount: 0,
|
||||||
|
failedJobCount: 0,
|
||||||
|
setJobCount: (jobType: string, count: Number) => {
|
||||||
|
switch (jobType) {
|
||||||
|
case "successful":
|
||||||
|
set(
|
||||||
|
produce((state) => {
|
||||||
|
state.importJobQueue.successfulJobCount = count;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "failed":
|
||||||
|
set(
|
||||||
|
produce((state) => {
|
||||||
|
state.importJobQueue.failedJobCount = count;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const { getState, setState } = useStore;
|
const { getState, setState } = useStore;
|
||||||
|
|
||||||
|
// socket.io instantiation
|
||||||
|
const sessionId = localStorage.getItem("sessionId");
|
||||||
|
const socketIOInstance = io(SOCKET_BASE_URI, {
|
||||||
|
transports: ["websocket"],
|
||||||
|
withCredentials: true,
|
||||||
|
query: { sessionId },
|
||||||
|
});
|
||||||
|
setState({
|
||||||
|
socketIOInstance,
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to init AirDC++ Socket with supplied settings
|
* Method to init AirDC++ Socket with supplied settings
|
||||||
* @param configuration - credentials, and hostname details to init AirDC++ connection
|
* @param configuration - credentials, and hostname details to init AirDC++ connection
|
||||||
|
|||||||
@@ -6345,6 +6345,11 @@ ignore@^5.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
|
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
|
||||||
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
|
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
|
||||||
|
|
||||||
|
immer@^10.0.3:
|
||||||
|
version "10.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/immer/-/immer-10.0.3.tgz#a8de42065e964aa3edf6afc282dfc7f7f34ae3c9"
|
||||||
|
integrity sha512-pwupu3eWfouuaowscykeckFmVTpqbzW+rXFCX8rQLkZzM9ftBmU/++Ra+o+L27mz03zJTlyV4UUr+fdKNffo4A==
|
||||||
|
|
||||||
immutable@^4.0.0, immutable@^4.3.4:
|
immutable@^4.0.0, immutable@^4.3.4:
|
||||||
version "4.3.4"
|
version "4.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f"
|
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f"
|
||||||
@@ -9501,6 +9506,7 @@ string-length@^4.0.1:
|
|||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||||
|
name string-width-cjs
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||||
@@ -9575,6 +9581,7 @@ string_decoder@~1.1.1:
|
|||||||
safe-buffer "~5.1.0"
|
safe-buffer "~5.1.0"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||||
|
name strip-ansi-cjs
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||||
@@ -10388,6 +10395,7 @@ wordwrap@^1.0.0:
|
|||||||
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
|
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==
|
||||||
|
|
||||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
|
||||||
|
name wrap-ansi-cjs
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||||
|
|||||||
Reference in New Issue
Block a user