feat: show mining frame toast on OSD and speed up stats session deletes

- Flash mined-frame screenshot as in-overlay image toast for OSD card notifications
- Batch cover art from stored DB blobs via POST /api/stats/covers (no extra AniList fetches)
- Show delete progress toast on stats home and sessions pages
- Refresh only affected rollups on session delete instead of full rebuild
- Rebuild lifetime summaries with aggregate SQL CTEs instead of per-session loop
This commit is contained in:
2026-06-04 22:00:51 -07:00
parent ea79e331fa
commit b343f1cf5c
45 changed files with 1199 additions and 209 deletions
+2 -24
View File
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { RetryingCoverImage } from '../common/RetryingCoverImage';
import { resolveMediaCoverApiUrl } from '../../lib/media-library-grouping';
interface CoverImageProps {
@@ -9,31 +9,9 @@ interface CoverImageProps {
}
export function CoverImage({ videoId, title, src = null, className = '' }: CoverImageProps) {
const [failed, setFailed] = useState(false);
const fallbackChar = title.charAt(0) || '?';
const resolvedSrc = src?.trim() || resolveMediaCoverApiUrl(videoId);
useEffect(() => {
setFailed(false);
}, [resolvedSrc]);
if (failed) {
return (
<div
className={`bg-ctp-surface2 flex items-center justify-center text-ctp-overlay2 text-2xl font-bold ${className}`}
>
{fallbackChar}
</div>
);
}
return (
<img
src={resolvedSrc}
alt={title}
loading="lazy"
className={`object-cover bg-ctp-surface2 ${className}`}
onError={() => setFailed(true)}
/>
<RetryingCoverImage src={resolvedSrc} alt={title} fallbackLabel={title} className={className} />
);
}