Image Loading (MangaCovers) with lazy load attribute, onError instead of onLoad hook, preventing requests before sizing is complete

This commit is contained in:
2025-06-18 18:58:46 +02:00
parent 4c81c571a4
commit 84f9dc176e
3 changed files with 11 additions and 17 deletions

View File

@ -21,6 +21,9 @@ const coverSx : SxProps = {
const coverCss : CSSProperties = { const coverCss : CSSProperties = {
maxHeight: "calc("+CardHeight+"px + 2rem)", maxHeight: "calc("+CardHeight+"px + 2rem)",
maxWidth: "calc("+CardWidth+"px + 2rem)", maxWidth: "calc("+CardWidth+"px + 2rem)",
objectFit: "cover",
width: "calc("+CardHeight+"px + 2rem)",
height: "calc("+CardHeight+"px + 2rem)",
} }
export function MangaFromId({mangaId, children} : { mangaId: string, children?: ReactElement<any, any> | ReactElement<any, any>[] | undefined }){ export function MangaFromId({mangaId, children} : { mangaId: string, children?: ReactElement<any, any> | ReactElement<any, any>[] | undefined }){
@ -34,7 +37,7 @@ export function MangaFromId({mangaId, children} : { mangaId: string, children?:
<Badge sx={{margin:"8px !important"}} badgeContent={<Skeleton><Tooltip title={"Loading"}><img width={"24pt"} height={"24pt"} src={"/blahaj.png"} /></Tooltip></Skeleton>} color={ReleaseStatusToPalette(MangaReleaseStatus.Completed)} size={"lg"}> <Badge sx={{margin:"8px !important"}} badgeContent={<Skeleton><Tooltip title={"Loading"}><img width={"24pt"} height={"24pt"} src={"/blahaj.png"} /></Tooltip></Skeleton>} color={ReleaseStatusToPalette(MangaReleaseStatus.Completed)} size={"lg"}>
<Card sx={{height:"fit-content",width:"fit-content"}}> <Card sx={{height:"fit-content",width:"fit-content"}}>
<CardCover> <CardCover>
<img style={coverCss} src={"/blahaj.png"} alt="Manga Cover"/> <img loading={"lazy"} style={coverCss} src={"/blahaj.png"} alt="Manga Cover"/>
</CardCover> </CardCover>
<CardCover sx={{ <CardCover sx={{
background: background:
@ -94,9 +97,9 @@ export function Manga({manga: manga, children} : { manga: IManga, children?: Rea
setExpanded(!expanded)} setExpanded(!expanded)}
}> }>
<CardCover> <CardCover>
<img style={coverCss} src={GetMangaCoverImageUrl(apiUri, manga.mangaId, CoverRef.current)} alt="Manga Cover" <img loading={"lazy"} style={coverCss} src={GetMangaCoverImageUrl(apiUri, manga.mangaId, CoverRef.current)} alt="Manga Cover"
ref={CoverRef} ref={CoverRef}
onLoad={LoadMangaCover}/> onError={LoadMangaCover}/>
</CardCover> </CardCover>
<CardCover sx={{ <CardCover sx={{
background: background:

View File

@ -27,17 +27,12 @@ export default function MangaList({connected, setShowSearch}: {connected: boolea
StartJob(apiUri, jobId, true).finally(() => getJobList()); StartJob(apiUri, jobId, true).finally(() => getJobList());
},[apiUri]); },[apiUri]);
useEffect(() => {
getJobList();
}, [apiUri]);
useEffect(() => { useEffect(() => {
updateTimer(); updateTimer();
getJobList(); }, [connected, apiUri]);
}, [connected]);
const timerRef = React.useRef<ReturnType<typeof setInterval>>(undefined); const timerRef = React.useRef<ReturnType<typeof setInterval>>(undefined);
const updateTimer = () => { const updateTimer = useCallback(() => {
if(!connected){ if(!connected){
clearTimeout(timerRef.current); clearTimeout(timerRef.current);
return; return;
@ -45,12 +40,10 @@ export default function MangaList({connected, setShowSearch}: {connected: boolea
if(timerRef.current === undefined) { if(timerRef.current === undefined) {
console.log("Added timer!"); console.log("Added timer!");
getJobList(); getJobList();
timerRef.current = setInterval(() => { timerRef.current = setInterval(getJobList, 2000);
getJobList();
}, 2000);
} }
} }
} }, [getJobList, connected, timerRef]);
return( return(
<Stack direction="row" spacing={1} flexWrap={"wrap"} sx={{overflowX: 'hidden', overflowY: 'auto' /* Badge overflow */}} paddingTop={"6px" /* Badge overflow */}> <Stack direction="row" spacing={1} flexWrap={"wrap"} sx={{overflowX: 'hidden', overflowY: 'auto' /* Badge overflow */}} paddingTop={"6px" /* Badge overflow */}>

View File

@ -29,9 +29,7 @@ export const DeleteManga = async (apiUri: string, mangaId: string) : Promise<voi
} }
export const GetMangaCoverImageUrl = (apiUri: string, mangaId: string, ref: HTMLImageElement | undefined | null) : string => { export const GetMangaCoverImageUrl = (apiUri: string, mangaId: string, ref: HTMLImageElement | undefined | null) : string => {
if(ref == null || ref == undefined) if(ref == null || ref == undefined || mangaId === DefaultManga.mangaId)
return `${apiUri}/v2/Manga/${mangaId}/Cover?width=64&height=64`;
if(mangaId === DefaultManga.mangaId)
return "/blahaj.png"; return "/blahaj.png";
return `${apiUri}/v2/Manga/${mangaId}/Cover?width=${ref.clientWidth}&height=${ref.clientHeight}`; return `${apiUri}/v2/Manga/${mangaId}/Cover?width=${ref.clientWidth}&height=${ref.clientHeight}`;
} }