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
} from "@heroui/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 {libraryState} from "Frontend/state/LibraryState";
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 {useEffect, useState} from "react";
export default function ScanProgressPopover() {
const libraries = useSnapshot(libraryState).state;
const scans = useSnapshot(scanState).sortedByStartTime as LibraryScanProgress[];
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 (
<Popover placement="bottom-end" showArrow={true}>
<PopoverTrigger>
<Button isIconOnly variant="light">
{scanInProgress ?
<Spinner size="sm" color="default" variant="simple"/> :
<Target/>
<Spinner size="sm" color="default" variant="spinner"
classNames={{
spinnerBars: "bg-foreground-500",
}}/> :
<Target className="fill-foreground-500"/>
}
</Button>
</PopoverTrigger>
@@ -36,56 +53,56 @@ export default function ScanProgressPopover() {
<div className="flex flex-col gap-2 m-2 w-96">
{scans.length === 0 ?
<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> :
<div className="flex flex-col gap-4">
<Link underline="always" size="sm" href="#" onPress={clear} className="justify-end">
Clear
</Link>
<ScrollShadow hideScrollBar className="max-h-96">
{scans.map((scan, index) =>
<div className="flex flex-col">
<div
className="flex flex-row justify-between items-center text-default-500 mb-1">
<p>Scan for library&nbsp;
<Link underline="always"
color="foreground"
size="sm"
href={`/administration/libraries/library/${scan.libraryId}`}>
{libraries[scan.libraryId].name}
</Link>
</p>
{scan.finishedAt ?
<p className="text-default-500">Finished {timeUntil(scan.finishedAt)}</p> :
<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
<ScrollShadow hideScrollBar className="max-h-96">
{scans.map((scan, index) =>
<div className="flex flex-col">
<div
className="flex flex-row justify-between items-center text-default-500 mb-1">
<p>Scan for library&nbsp;
<Link underline="always"
color="foreground"
size="sm"
href={`/administration/libraries/library/${scan.libraryId}`}>
{libraries[scan.libraryId].name}
</Link>
</p>
{scan.finishedAt ?
<p className="text-default-500">
Finished {timeUntil(scan.finishedAt)}
</p> :
<p className="text-default-500">
Started {timeUntil(scan.startedAt)}
</p>
}
{scans.length > 1 && index < (scans.length - 1) && <Divider className="my-2"/>}
</div>
)}
</ScrollShadow>
</div>
{scan.status === LibraryScanStatus.IN_PROGRESS ?
scan.currentStep.current && scan.currentStep.total ?
<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>
</PopoverContent>
@@ -44,10 +44,6 @@ export function initializeScanState() {
});
}
export function clear() {
scanState.state = {};
}
export function handleLibraryDeletion(libraryId: number) {
for (const scanId in scanState.state) {
if (scanState.state[scanId].libraryId === libraryId) {