mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-13 16:40:01 +00:00
8d8dca32d8
* chore: bump version to v2.3.0-preview * Customize start page (#803) * Update ConfigService to support complex Objects Implemented tests for ConfigService * Added DB migration for config table * Fixed version in banner.txt not being displayed * Implement Library ordering Implement "Show recently added games on homepage" * Fix build.gradle.kts * FIx bug when creating libraries * Fix TypeScript errors Fix library sorting * Bump actions/checkout from 5 to 6 (#811) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Added automatic scanning using file system watchers (#813) * Implement collections (#814) * Backend implementation for collections * Fix database schema and migration script * Refactor some config values Fix ArrayInput not being deactivatable * Remove "AutoRegisterNewUsers" config option * Fix bug when removing ignored paths * Add UI for collections (WIP) * Fix table actions not synced with state Fix tests * Finish implementation of collection feature * Fix tests * Bump actions/checkout from 5 to 6 (#815) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Fix "allow guests to create game requests" not being enabled when guest access is activated * Fix: Disable loading of EditGameMetadataModal and MatchGameModal in GameView when user is not admin * WIP: Update start page layout * Performance improvements (lazy loading and virtualized grids/lists) Fix various smaller issues * Implement use of blurhash for all images in backend and covers in frontend * Fix bugs and test * Fix code analysis issues * Remove "UI settings" since they have been made obsolete --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
118 lines
6.2 KiB
TypeScript
118 lines
6.2 KiB
TypeScript
import {
|
|
Button,
|
|
Divider,
|
|
Link,
|
|
Popover,
|
|
PopoverContent,
|
|
PopoverTrigger,
|
|
Progress,
|
|
ScrollShadow,
|
|
Spinner
|
|
} from "@heroui/react";
|
|
import {useSnapshot} from "valtio/react";
|
|
import {scanState} from "Frontend/state/ScanState";
|
|
import {libraryState} from "Frontend/state/LibraryState";
|
|
import {TargetIcon, WarningIcon} from "@phosphor-icons/react";
|
|
import {timeBetween, timeUntil, toTitleCase} from "Frontend/util/utils";
|
|
import LibraryScanStatus from "Frontend/generated/org/gameyfin/app/libraries/dto/LibraryScanStatus";
|
|
import {useEffect, useState} from "react";
|
|
|
|
export default function ScanProgressPopover() {
|
|
const libraries = useSnapshot(libraryState).state;
|
|
const scans = useSnapshot(scanState).sortedByStartTime;
|
|
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="spinner"
|
|
classNames={{
|
|
spinnerBars: "bg-foreground-500",
|
|
}}/> :
|
|
<TargetIcon className="fill-foreground-500"/>
|
|
}
|
|
</Button>
|
|
</PopoverTrigger>
|
|
<PopoverContent>
|
|
<div className="flex flex-col gap-2 m-2 min-w-md">
|
|
{scans.length === 0 ?
|
|
<p className="flex h-12 items-center justify-center text-sm text-default-500">
|
|
No scans in progress or in history.
|
|
</p> :
|
|
<ScrollShadow hideScrollBar className="max-h-96">
|
|
{scans.map((scan, index) =>
|
|
<div className="flex flex-col" key={scan.scanId}>
|
|
<div
|
|
className="flex flex-row gap-4 justify-between items-center text-default-500 mb-1">
|
|
<p>{toTitleCase(scan.type)} scan for library
|
|
<Link underline="always"
|
|
color="foreground"
|
|
size="sm"
|
|
href={`/administration/games/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 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>
|
|
)
|
|
}
|
|
{scan.status === LibraryScanStatus.COMPLETED &&
|
|
<p>
|
|
{scan.result?.new} new /
|
|
{(scan as any).result?.updated != null && `${(scan as any).result.updated} updated / `}
|
|
{scan.result?.removed} removed /
|
|
{scan.result?.unmatched} unmatched
|
|
(in {timeBetween(scan.startedAt, scan.finishedAt!)})
|
|
</p>
|
|
}
|
|
{scan.status === LibraryScanStatus.FAILED &&
|
|
<p className="text-danger flex flex-row gap-1"><WarningIcon weight="fill"/>
|
|
Scan failed (check logs for details)
|
|
</p>
|
|
}
|
|
{scans.length > 1 && index < (scans.length - 1) && <Divider className="my-2"/>}
|
|
</div>
|
|
)}
|
|
</ScrollShadow>
|
|
}
|
|
</div>
|
|
</PopoverContent>
|
|
</Popover>
|
|
);
|
|
} |