Minor layout fixes for ScanProgressPopover

This commit is contained in:
grimsi
2025-05-27 17:58:40 +02:00
parent c2c6a891b9
commit 489a6c7aed
2 changed files with 67 additions and 54 deletions
@@ -10,25 +10,42 @@ import {
Spinner Spinner
} from "@heroui/react"; } from "@heroui/react";
import {useSnapshot} from "valtio/react"; import {useSnapshot} from "valtio/react";
import {clear, scanState} from "Frontend/state/ScanState"; import {scanState} from "Frontend/state/ScanState";
import LibraryScanProgress from "Frontend/generated/de/grimsi/gameyfin/libraries/dto/LibraryScanProgress"; import LibraryScanProgress from "Frontend/generated/de/grimsi/gameyfin/libraries/dto/LibraryScanProgress";
import {libraryState} from "Frontend/state/LibraryState"; import {libraryState} from "Frontend/state/LibraryState";
import {Target} from "@phosphor-icons/react"; import {Target} from "@phosphor-icons/react";
import {timeUntil} from "Frontend/util/utils"; import {timeBetween, timeUntil} from "Frontend/util/utils";
import LibraryScanStatus from "Frontend/generated/de/grimsi/gameyfin/libraries/dto/LibraryScanStatus"; import LibraryScanStatus from "Frontend/generated/de/grimsi/gameyfin/libraries/dto/LibraryScanStatus";
import {useEffect, useState} from "react";
export default function ScanProgressPopover() { export default function ScanProgressPopover() {
const libraries = useSnapshot(libraryState).state; const libraries = useSnapshot(libraryState).state;
const scans = useSnapshot(scanState).sortedByStartTime as LibraryScanProgress[]; const scans = useSnapshot(scanState).sortedByStartTime as LibraryScanProgress[];
const scanInProgress = useSnapshot(scanState).isScanning; const scanInProgress = useSnapshot(scanState).isScanning;
// Add state to track current time and force re-renders
const [currentTime, setCurrentTime] = useState(Date.now());
// Set up an interval to update the time every second
useEffect(() => {
const intervalId = setInterval(() => {
setCurrentTime(Date.now());
}, 1000);
// Clean up the interval when component unmounts
return () => clearInterval(intervalId);
}, []);
return ( return (
<Popover placement="bottom-end" showArrow={true}> <Popover placement="bottom-end" showArrow={true}>
<PopoverTrigger> <PopoverTrigger>
<Button isIconOnly variant="light"> <Button isIconOnly variant="light">
{scanInProgress ? {scanInProgress ?
<Spinner size="sm" color="default" variant="simple"/> : <Spinner size="sm" color="default" variant="spinner"
<Target/> classNames={{
spinnerBars: "bg-foreground-500",
}}/> :
<Target className="fill-foreground-500"/>
} }
</Button> </Button>
</PopoverTrigger> </PopoverTrigger>
@@ -36,56 +53,56 @@ export default function ScanProgressPopover() {
<div className="flex flex-col gap-2 m-2 w-96"> <div className="flex flex-col gap-2 m-2 w-96">
{scans.length === 0 ? {scans.length === 0 ?
<p className="flex h-12 items-center justify-center text-sm text-default-500"> <p className="flex h-12 items-center justify-center text-sm text-default-500">
No scans in progress. No scans in progress or in history.
</p> : </p> :
<div className="flex flex-col gap-4"> <ScrollShadow hideScrollBar className="max-h-96">
<Link underline="always" size="sm" href="#" onPress={clear} className="justify-end"> {scans.map((scan, index) =>
Clear <div className="flex flex-col">
</Link> <div
<ScrollShadow hideScrollBar className="max-h-96"> className="flex flex-row justify-between items-center text-default-500 mb-1">
{scans.map((scan, index) => <p>Scan for library&nbsp;
<div className="flex flex-col"> <Link underline="always"
<div color="foreground"
className="flex flex-row justify-between items-center text-default-500 mb-1"> size="sm"
<p>Scan for library&nbsp; href={`/administration/libraries/library/${scan.libraryId}`}>
<Link underline="always" {libraries[scan.libraryId].name}
color="foreground" </Link>
size="sm" </p>
href={`/administration/libraries/library/${scan.libraryId}`}> {scan.finishedAt ?
{libraries[scan.libraryId].name} <p className="text-default-500">
</Link> Finished {timeUntil(scan.finishedAt)}
</p> </p> :
{scan.finishedAt ? <p className="text-default-500">
<p className="text-default-500">Finished {timeUntil(scan.finishedAt)}</p> : Started {timeUntil(scan.startedAt)}
<p className="text-default-500">Started {timeUntil(scan.startedAt)}</p>
}
</div>
{scan.status === LibraryScanStatus.IN_PROGRESS ?
scan.currentStep.current && scan.currentStep.total ?
<div>
<p className="text-default-500">
{`${scan.currentStep.description} (${scan.currentStep.current} / ${scan.currentStep.total})`}
</p>
<Progress
value={scan.currentStep.current / scan.currentStep.total * 100}
size="sm"/>
</div> :
<div>
<p className="text-default-500">{scan.currentStep.description}</p>
<Progress isIndeterminate size="sm"/>
</div>
:
<p>
{scan.result?.new} new /&nbsp;
{scan.result?.removed} removed /&nbsp;
{scan.result?.unmatched} unmatched
</p> </p>
} }
{scans.length > 1 && index < (scans.length - 1) && <Divider className="my-2"/>}
</div> </div>
)} {scan.status === LibraryScanStatus.IN_PROGRESS ?
</ScrollShadow> scan.currentStep.current && scan.currentStep.total ?
</div> <div className="flex flex-col gap-1">
<p className="text-default-500">
{`${scan.currentStep.description} (${scan.currentStep.current}/${scan.currentStep.total})`}
</p>
<Progress
value={scan.currentStep.current / scan.currentStep.total * 100}
size="sm"/>
</div> :
<div className="flex flex-col gap-1">
<p className="text-default-500">{scan.currentStep.description}</p>
<Progress isIndeterminate size="sm"/>
</div>
:
<p>
{scan.result?.new} new /&nbsp;
{scan.result?.removed} removed /&nbsp;
{scan.result?.unmatched} unmatched&nbsp;
(in {timeBetween(scan.startedAt, scan.finishedAt!)})
</p>
}
{scans.length > 1 && index < (scans.length - 1) && <Divider className="my-2"/>}
</div>
)}
</ScrollShadow>
} }
</div> </div>
</PopoverContent> </PopoverContent>
@@ -44,10 +44,6 @@ export function initializeScanState() {
}); });
} }
export function clear() {
scanState.state = {};
}
export function handleLibraryDeletion(libraryId: number) { export function handleLibraryDeletion(libraryId: number) {
for (const scanId in scanState.state) { for (const scanId in scanState.state) {
if (scanState.state[scanId].libraryId === libraryId) { if (scanState.state[scanId].libraryId === libraryId) {