diff --git a/index.html b/index.html index 21d1f3a..7ae7be9 100644 --- a/index.html +++ b/index.html @@ -1,16 +1,14 @@ - - - - - - + + + + + Three Two! - + - +
- - - \ No newline at end of file + + diff --git a/package.json b/package.json index e0acf9a..390dbd6 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "axios-cache-interceptor": "^1.0.1", "axios-rate-limit": "^1.3.0", "babel-plugin-styled-components": "^2.1.4", + "bulma-prefers-dark": "^0.1.0-beta.1", "date-fns": "^2.28.0", "dayjs": "^1.10.6", "ellipsize": "^0.5.1", diff --git a/src/client/assets/scss/App.scss b/src/client/assets/scss/App.scss index 0833103..5f3aeab 100644 --- a/src/client/assets/scss/App.scss +++ b/src/client/assets/scss/App.scss @@ -1,4 +1,5 @@ @import "/node_modules/bulma/bulma.sass"; +@import "/node_modules/bulma-prefers-dark/bulma-prefers-dark.sass"; $fa-font-path: "/node_modules/@fortawesome/fontawesome-free/webfonts"; @import "/node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss"; @import "/node_modules/@fortawesome/fontawesome-free/scss/regular.scss"; @@ -14,8 +15,9 @@ $flexSize: 4em; $boxSpacing: 1em; $colorText: #404646; body { - background: #fffcc; + background: #20292f; } + .is-size-8 { font-size: $size-8; } @@ -72,10 +74,6 @@ pre { background: #454a59; } - body { - background: #454a59; - } - .pulsating-circle { position: relative; left: -120%; @@ -244,12 +242,16 @@ pre { .generic-card { display: inline-block; - background-color: #fff; + background-color: hsl(232, 11%, 15%); border-top-left-radius: 0.4rem; border-top-right-radius: 0.4rem; border-bottom-left-radius: 0.4rem; border-bottom-right-radius: 0.4rem; - box-shadow: 1px 8px 23px 7px rgba(0, 0, 0, 0.12); + box-shadow: inset 0 0 0.5px 1px hsla(0, 0%, 100%, 0.1), + /* 2. shadow ring 👇 */ 0 0 0 1px hsla(230, 13%, 9%, 0.075), + /* 3. multiple soft shadows 👇 */ 0 0.3px 0.4px hsla(230, 13%, 9%, 0.02), + 0 0.9px 1.5px hsla(230, 13%, 9%, 0.045), + 0 3.5px 6px hsla(230, 13%, 9%, 0.09); .green-border { border: 1px dotted #168b64; @@ -358,7 +360,7 @@ pre { // raw file details .raw-file-details { padding: 1rem; - background-color: beige; + background: #30475e; border-radius: 0.5rem; } @@ -368,23 +370,23 @@ pre { // comicvine metadata .comicvine-metadata { - background-color: #f2f1f9; + background-color: #d6cc99; padding: 0.8rem; border-radius: 0.5rem; } .issue-metadata { - background-color: #fbffee; + background-color: #57615c; padding: 0.8em; border-radius: 0.5rem; .name { font-size: 0.95rem; - color: #4a4f50; } } .comicInfo-metadata { - background-color: #f7ebdd; + background-color: #d6cc99; + color: #000; padding: 0.8rem; border-radius: 0.5rem; } @@ -421,17 +423,17 @@ pre { } // Library .header-area { + background: #20292f; width: 100%; padding: 25px 0 15px 0; position: sticky; - z-index: 9999; - background: #fffffc; - top: 50px; + z-index: 9; + top: 57px; } .library { .table-controls { - background: #fffffc; + background: #20292f; justify-content: space-between; position: sticky; top: 126px; @@ -439,17 +441,17 @@ pre { } .pagination { margin: 0; - background: #fffffc; } table { + background: #20292f; border-collapse: separate; width: 100%; thead { + background: #20292f; position: sticky; top: 250px; z-index: 1; - background: #fffffc; min-height: 130px; } tr { diff --git a/src/client/components/ComicDetail/AcquisitionPanel.tsx b/src/client/components/ComicDetail/AcquisitionPanel.tsx index 2b25188..bc851cb 100644 --- a/src/client/components/ComicDetail/AcquisitionPanel.tsx +++ b/src/client/components/ComicDetail/AcquisitionPanel.tsx @@ -1,9 +1,5 @@ import React, { useCallback, ReactElement, useEffect, useState } from "react"; -import { - downloadAirDCPPItem, - getBundlesForComic, - sleep, -} from "../../actions/airdcpp.actions"; +import { getBundlesForComic, sleep } from "../../actions/airdcpp.actions"; import { SearchQuery, PriorityEnum, SearchResponse } from "threetwo-ui-typings"; import { RootState, SearchInstance } from "threetwo-ui-typings"; import ellipsize from "ellipsize"; @@ -13,6 +9,7 @@ import { isEmpty, isNil, map } from "lodash"; import { useStore } from "../../store"; import { useShallow } from "zustand/react/shallow"; import { useQuery } from "@tanstack/react-query"; +import axios from "axios"; interface IAcquisitionPanelProps { query: any; @@ -28,14 +25,22 @@ export const AcquisitionPanel = ( airDCPPSocketInstance, airDCPPClientConfiguration, airDCPPSessionInformation, + airDCPPDownloadTick, } = useStore( useShallow((state) => ({ airDCPPSocketInstance: state.airDCPPSocketInstance, airDCPPClientConfiguration: state.airDCPPClientConfiguration, airDCPPSessionInformation: state.airDCPPSessionInformation, + airDCPPDownloadTick: state.airDCPPDownloadTick, })), ); + interface SearchData { + query: Pick & Partial>; + hub_urls: string[] | undefined | null; + priority: PriorityEnum; + } + /** * Get the hubs list from an AirDCPP Socket */ @@ -43,34 +48,15 @@ export const AcquisitionPanel = ( queryKey: ["hubs"], queryFn: async () => await airDCPPSocketInstance.get(`hubs`), }); - + const { comicObjectId } = props; const issueName = props.query.issue.name || ""; - // const { settings } = props; const sanitizedIssueName = issueName.replace(/[^a-zA-Z0-9 ]/g, " "); - // Selectors for picking state - // const airDCPPSearchResults = useSelector((state: RootState) => { - // return state.airdcpp.searchResults; - // }); - // const isAirDCPPSearchInProgress = useSelector( - // (state: RootState) => state.airdcpp.isAirDCPPSearchInProgress, - // ); - // const searchInfo = useSelector( - // (state: RootState) => state.airdcpp.searchInfo, - // ); - // const searchInstance: SearchInstance = useSelector( - // (state: RootState) => state.airdcpp.searchInstance, - // ); - - // const settings = useSelector((state: RootState) => state.settings.data); - // const airDCPPConfiguration = useContext(AirDCPPSocketContext); - interface SearchData { - query: Pick & Partial>; - hub_urls: string[] | undefined | null; - priority: PriorityEnum; - } const [dcppQuery, setDcppQuery] = useState({}); const [airDCPPSearchResults, setAirDCPPSearchResults] = useState([]); + const [airDCPPSearchStatus, setAirDCPPSearchStatus] = useState(false); + const [airDCPPSearchInstance, setAirDCPPSearchInstance] = useState({}); + const [airDCPPSearchInfo, setAirDCPPSearchInfo] = useState({}); // Construct a AirDC++ query based on metadata inferred, upon component mount // Pre-populate the search input with the search string, so that @@ -88,15 +74,18 @@ export const AcquisitionPanel = ( setDcppQuery(dcppSearchQuery); }, []); + /** + * Method to perform a search via an AirDC++ websocket + * @param {SearchData} data - a SearchData query + * @param {any} ADCPPSocket - an intialized AirDC++ socket instance + */ const search = async (data: SearchData, ADCPPSocket: any) => { try { if (!ADCPPSocket.isConnected()) { await ADCPPSocket(); } const instance: SearchInstance = await ADCPPSocket.post("search"); - // dispatch({ - // type: AIRDCPP_SEARCH_IN_PROGRESS, - // }); + setAirDCPPSearchStatus(true); // We want to get notified about every new result in order to make the user experience better await ADCPPSocket.addListener( @@ -142,6 +131,9 @@ export const AcquisitionPanel = ( const currentInstance = await ADCPPSocket.get( `search/${instance.id}`, ); + setAirDCPPSearchInstance(currentInstance); + setAirDCPPSearchInfo(searchInfo); + console.log("Asdas", airDCPPSearchInfo); if (currentInstance.result_count === 0) { // ...nothing was received, show an informative message to the user console.log("No more search results."); @@ -149,11 +141,8 @@ export const AcquisitionPanel = ( // The search can now be considered to be "complete" // If there's an "in progress" indicator in the UI, that could also be disabled here - // dispatch({ - // type: AIRDCPP_HUB_SEARCHES_SENT, - // searchInfo, - // instance, - // }); + setAirDCPPSearchInstance(instance); + setAirDCPPSearchStatus(false); }, instance.id, ); @@ -164,6 +153,68 @@ export const AcquisitionPanel = ( throw error; } }; + + /** + * Method to download a bundle associated with a search result from AirDC++ + * @param {Number} searchInstanceId - description + * @param {String} resultId - description + * @param {String} comicObjectId - description + * @param {String} name - description + * @param {Number} size - description + * @param {any} type - description + * @param {any} ADCPPSocket - description + * @returns {void} - description + */ + const download = async ( + searchInstanceId: Number, + resultId: String, + comicObjectId: String, + name: String, + size: Number, + type: any, + ADCPPSocket: any, + ): void => { + try { + if (!ADCPPSocket.isConnected()) { + await ADCPPSocket.connect(); + } + let bundleDBImportResult = {}; + const downloadResult = await ADCPPSocket.post( + `search/${searchInstanceId}/results/${resultId}/download`, + ); + + if (!isNil(downloadResult)) { + bundleDBImportResult = await axios({ + method: "POST", + url: `http://localhost:3000/api/library/applyAirDCPPDownloadMetadata`, + headers: { + "Content-Type": "application/json; charset=utf-8", + }, + data: { + bundleId: downloadResult.bundle_info.id, + comicObjectId, + name, + size, + type, + }, + }); + + // dispatch({ + // type: AIRDCPP_RESULT_DOWNLOAD_INITIATED, + // downloadResult, + // bundleDBImportResult, + // }); + // + // dispatch({ + // type: IMS_COMIC_BOOK_DB_OBJECT_FETCHED, + // comicBookDetail: bundleDBImportResult.data, + // IMS_inProgress: false, + // }); + } + } catch (error) { + throw error; + } + }; const getDCPPSearchResults = async (searchQuery) => { const manualQuery = { query: { @@ -209,7 +260,6 @@ export const AcquisitionPanel = ( }, [], ); - console.log("yaman", airDCPPSearchResults); return ( <>
@@ -245,7 +295,7 @@ export const AcquisitionPanel = (