URL Search

Fix MangaConnector color
This commit is contained in:
2025-06-16 22:30:33 +02:00
parent 496e6fdde8
commit e0ec64882b

View File

@ -21,7 +21,7 @@ import {useCallback, useContext, useEffect, useState} from "react";
import {ApiUriContext} from "../api/fetchApi.tsx"; import {ApiUriContext} from "../api/fetchApi.tsx";
import {GetAllConnectors} from "../api/MangaConnector.tsx"; import {GetAllConnectors} from "../api/MangaConnector.tsx";
import IManga from "../api/types/IManga.ts"; import IManga from "../api/types/IManga.ts";
import {SearchNameOnConnector} from "../api/Search.tsx"; import {SearchNameOnConnector, SearchUrl} from "../api/Search.tsx";
import {Manga} from "./Manga.tsx"; import {Manga} from "./Manga.tsx";
import Add from "@mui/icons-material/Add"; import Add from "@mui/icons-material/Add";
import React from "react"; import React from "react";
@ -32,7 +32,7 @@ import { LibraryBooks } from "@mui/icons-material";
export default function Search({open, setOpen}:{open:boolean, setOpen:React.Dispatch<React.SetStateAction<boolean>>}){ export default function Search({open, setOpen}:{open:boolean, setOpen:React.Dispatch<React.SetStateAction<boolean>>}){
const [step, setStep] = useState<number>(1); const [step, setStep] = useState<number>(2);
const apiUri = useContext(ApiUriContext); const apiUri = useContext(ApiUriContext);
const [mangaConnectors, setMangaConnectors] = useState<IMangaConnector[]>(); const [mangaConnectors, setMangaConnectors] = useState<IMangaConnector[]>();
@ -48,14 +48,28 @@ export default function Search({open, setOpen}:{open:boolean, setOpen:React.Disp
const [resultsLoading, setResultsLoading] = useState<boolean>(false); const [resultsLoading, setResultsLoading] = useState<boolean>(false);
const StartSearch = useCallback((mangaConnector : IMangaConnector | undefined, value: string)=>{ const StartSearch = useCallback((mangaConnector : IMangaConnector | undefined, value: string)=>{
setStep(3); if(mangaConnector === undefined && !IsValidUrl(value))
if(mangaConnector === undefined)
return; return;
setResults([]); setResults(undefined);
setResultsLoading(true); setResultsLoading(true);
SearchNameOnConnector(apiUri, mangaConnector.name, value).then(setResults).finally(() => setResultsLoading(false)); setStep(3);
if (IsValidUrl(value)){
SearchUrl(apiUri, value).then((r) => setResults([r])).finally(() => setResultsLoading(false));
}else if (mangaConnector != undefined){
SearchNameOnConnector(apiUri, mangaConnector.name, value).then(setResults).finally(() => setResultsLoading(false));
}
},[apiUri]) },[apiUri])
function IsValidUrl(str : string) : boolean {
const pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
'(\\#[-a-z\\d_]*)?$','i'); // fragment locator
return !!pattern.test(str);
}
const [localLibraries, setLocalLibraries] = useState<ILocalLibrary[]>(); const [localLibraries, setLocalLibraries] = useState<ILocalLibrary[]>();
const [localLibrariesLoading, setLocalLibrariesLoading] = useState<boolean>(true); const [localLibrariesLoading, setLocalLibrariesLoading] = useState<boolean>(true);
const [selectedLibraryId, setSelectedLibraryId] = useState<string>(); const [selectedLibraryId, setSelectedLibraryId] = useState<string>();
@ -101,12 +115,12 @@ export default function Search({open, setOpen}:{open:boolean, setOpen:React.Disp
<ModalClose /> <ModalClose />
<Stepper orientation={"vertical"} sx={{ height: '100%', width: "calc(100% - 80px)", margin:"40px"}}> <Stepper orientation={"vertical"} sx={{ height: '100%', width: "calc(100% - 80px)", margin:"40px"}}>
<Step indicator={ <Step indicator={
<StepIndicator variant={step==1?"solid":"outlined"} color={mangaConnectors?.length??0 < 1 ? "danger" : "primary"}> <StepIndicator variant={step==1?"solid":"outlined"} color={(mangaConnectors?.length??0) < 1 ? "danger" : "primary"}>
1 1
</StepIndicator>}> </StepIndicator>}>
<Skeleton loading={mangaConnectorsLoading}> <Skeleton loading={mangaConnectorsLoading}>
<Select <Select
color={mangaConnectors?.length??0 < 1 ? "danger" : "neutral"} color={(mangaConnectors?.length??0) < 1 ? "danger" : "neutral"}
disabled={mangaConnectorsLoading || resultsLoading || mangaConnectors?.length == null || mangaConnectors.length < 1} disabled={mangaConnectorsLoading || resultsLoading || mangaConnectors?.length == null || mangaConnectors.length < 1}
placeholder={"Select Connector"} placeholder={"Select Connector"}
slotProps={{ slotProps={{
@ -119,8 +133,9 @@ export default function Search({open, setOpen}:{open:boolean, setOpen:React.Disp
sx={{ '--ListItemDecorator-size': '44px', minWidth: 240 }} sx={{ '--ListItemDecorator-size': '44px', minWidth: 240 }}
renderValue={renderValue} renderValue={renderValue}
onChange={(_e, newValue) => { onChange={(_e, newValue) => {
setStep(2);
setSelectedMangaConnector(mangaConnectors?.find((o) => o.name === newValue)); setSelectedMangaConnector(mangaConnectors?.find((o) => o.name === newValue));
setStep(2);
setResults(undefined);
}} }}
endDecorator={<Chip size={"sm"} color={mangaConnectors?.length??0 < 1 ? "danger" : "primary"}>{mangaConnectors?.length}</Chip>}> endDecorator={<Chip size={"sm"} color={mangaConnectors?.length??0 < 1 ? "danger" : "primary"}>{mangaConnectors?.length}</Chip>}>
{mangaConnectors?.map((connector: IMangaConnector) => ConnectorOption(connector))} {mangaConnectors?.map((connector: IMangaConnector) => ConnectorOption(connector))}
@ -131,9 +146,9 @@ export default function Search({open, setOpen}:{open:boolean, setOpen:React.Disp
<StepIndicator variant={step==2?"solid":"outlined"} color="primary"> <StepIndicator variant={step==2?"solid":"outlined"} color="primary">
2 2
</StepIndicator>}> </StepIndicator>}>
<Input disabled={step < 2 || resultsLoading} placeholder={"Name or Url " + (selectedMangaConnector ? selectedMangaConnector.baseUris[0] : "")} onKeyDown={(e) => { <Input disabled={resultsLoading} placeholder={"Name or Url " + (selectedMangaConnector ? selectedMangaConnector.baseUris[0] : "")} onKeyDown={(e) => {
setStep(2); setStep(2);
setResults([]); setResults(undefined);
if(e.key === "Enter") { if(e.key === "Enter") {
StartSearch(selectedMangaConnector, e.currentTarget.value); StartSearch(selectedMangaConnector, e.currentTarget.value);
} }
@ -143,7 +158,7 @@ export default function Search({open, setOpen}:{open:boolean, setOpen:React.Disp
<StepIndicator variant={step==3?"solid":"outlined"} color="primary"> <StepIndicator variant={step==3?"solid":"outlined"} color="primary">
3 3
</StepIndicator>}> </StepIndicator>}>
<Typography endDecorator={<Chip size={"sm"} color={"primary"}>{results?.length}</Chip>}>Results</Typography> <Typography endDecorator={<Chip size={"sm"} color={"primary"}>{results?.length??"-"}</Chip>}>Results</Typography>
<Skeleton loading={resultsLoading}> <Skeleton loading={resultsLoading}>
<Stack direction={"row"} spacing={1} flexWrap={"wrap"}> <Stack direction={"row"} spacing={1} flexWrap={"wrap"}>
{results?.map((result) => {results?.map((result) =>