diff --git a/frontend/src/components/library/LibraryScanDrawer.jsx b/frontend/src/components/library/LibraryScanDrawer.jsx
index f5825aeb..d39835bf 100644
--- a/frontend/src/components/library/LibraryScanDrawer.jsx
+++ b/frontend/src/components/library/LibraryScanDrawer.jsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useMemo } from 'react';
+import React, { useEffect, useMemo, useState } from 'react';
import {
ActionIcon,
Badge,
@@ -55,6 +55,7 @@ const LibraryScanDrawer = ({
const scansLoading = useLibraryStore((s) => s.scansLoading);
const scans = useLibraryStore((s) => s.scans[libraryId || 'all']) ?? EMPTY_SCAN_LIST;
const fetchScans = useLibraryStore((s) => s.fetchScans);
+ const [loaderHold, setLoaderHold] = useState(false);
// Fetch once when opened (WebSockets keep it live afterward)
useEffect(() => {
@@ -77,11 +78,26 @@ const LibraryScanDrawer = ({
if (!opened) return undefined;
if (!hasRunningScan && !hasQueuedScan) return undefined;
const interval = setInterval(() => {
- void fetchScans(libraryId);
+ void fetchScans(libraryId, { background: true });
}, hasRunningScan ? 2000 : 5000);
return () => clearInterval(interval);
}, [opened, hasRunningScan, hasQueuedScan, libraryId, fetchScans]);
+ useEffect(() => {
+ if (!opened) {
+ setLoaderHold(false);
+ return undefined;
+ }
+ if (!scansLoading) {
+ return undefined;
+ }
+ setLoaderHold(true);
+ const timeout = setTimeout(() => setLoaderHold(false), 800);
+ return () => clearTimeout(timeout);
+ }, [opened, scansLoading]);
+
+ const showLoader = scansLoading || loaderHold;
+
const header = useMemo(
() => (
@@ -111,7 +127,7 @@ const LibraryScanDrawer = ({
),
- [onStartScan, onStartFullScan]
+ [onStartScan, onStartFullScan, handleRefresh]
);
return (
@@ -125,7 +141,7 @@ const LibraryScanDrawer = ({
title={header}
>
- {scansLoading ? (
+ {showLoader ? (
diff --git a/frontend/src/store/library.jsx b/frontend/src/store/library.jsx
index 21fb5ec6..a88a683b 100644
--- a/frontend/src/store/library.jsx
+++ b/frontend/src/store/library.jsx
@@ -117,10 +117,13 @@ const useLibraryStore = create(
return response;
},
- fetchScans: async (libraryId) => {
- set((state) => {
- state.scansLoading = true;
- });
+ fetchScans: async (libraryId, options = {}) => {
+ const { background = false } = options;
+ if (!background) {
+ set((state) => {
+ state.scansLoading = true;
+ });
+ }
try {
const params = new URLSearchParams();
if (libraryId) {
@@ -131,14 +134,20 @@ const useLibraryStore = create(
const payload = Array.isArray(response)
? response
: response.results || [];
- state.scans[libraryId || 'all'] = payload.map((scan) => normalizeScanEntry(scan));
- state.scansLoading = false;
+ state.scans[libraryId || 'all'] = payload.map((scan) =>
+ normalizeScanEntry(scan)
+ );
+ if (!background) {
+ state.scansLoading = false;
+ }
});
} catch (error) {
console.error('Failed to fetch scans', error);
- set((state) => {
- state.scansLoading = false;
- });
+ if (!background) {
+ set((state) => {
+ state.scansLoading = false;
+ });
+ }
}
},