diff --git a/frontend/src/tools/media.jsx b/frontend/src/tools/media.jsx index dddae24..5cb1166 100644 --- a/frontend/src/tools/media.jsx +++ b/frontend/src/tools/media.jsx @@ -256,31 +256,35 @@ function KinoGrid({ onOpenModal }) { const [xrelIds, setXrelIds] = useState(new Set()); const [favIds, toggleFav] = useFavIds(); + // Filme laden useEffect(() => { setLoading(true); setError(''); api('/tools/media/now-playing') - .then(list => { - setMovies(list); - // xREL-Badge: sequentielle 5er-Batches (Rate-Limit-sicher) - const moviesMeta = list.map(m => ({ id: m.id, title: m.title, original_title: m.original_title })); - (async () => { - for (let i = 0; i < moviesMeta.length; i += 5) { - try { - const chunk = moviesMeta.slice(i, i + 5); - const result = await api('/tools/media/xrel-check', { method:'POST', body:{ movies: chunk } }); - setXrelIds(prev => { - const next = new Set(prev); - Object.entries(result).forEach(([k,v]) => { if (v) next.add(Number(k)); }); - return next; - }); - } catch (_) {} - } - })(); - }) + .then(setMovies) .catch(e => setError(e.message)) .finally(() => setLoading(false)); }, []); + // xREL-Badges: eigener Effect, startet wenn movies gefüllt sind + useEffect(() => { + if (!movies.length) return; + let cancelled = false; + const moviesMeta = movies.map(m => ({ id: m.id, title: m.title, original_title: m.original_title })); + (async () => { + for (let i = 0; i < moviesMeta.length; i += 5) { + if (cancelled) break; + try { + const chunk = moviesMeta.slice(i, i + 5); + const result = await api('/tools/media/xrel-check', { method:'POST', body:{ movies: chunk } }); + if (cancelled) break; + const hits = Object.entries(result).filter(([,v]) => v).map(([k]) => Number(k)); + if (hits.length > 0) setXrelIds(prev => new Set([...prev, ...hits])); + } catch (_) {} + } + })(); + return () => { cancelled = true; }; + }, [movies]); + const onToggle = async (movie, isFav) => { try { await toggleFav(movie, isFav); } catch (e) { alert(e.message); } }; @@ -325,28 +329,31 @@ function DemnächstGrid({ onOpenModal }) { useEffect(() => { setLoading(true); setError(''); api('/tools/media/upcoming') - .then(grps => { - setGroups(grps); - const allMovies = Object.values(grps).flat(); - const moviesMeta = allMovies.map(m => ({ id: m.id, title: m.title, original_title: m.original_title })); - (async () => { - for (let i = 0; i < moviesMeta.length; i += 5) { - try { - const chunk = moviesMeta.slice(i, i + 5); - const result = await api('/tools/media/xrel-check', { method:'POST', body:{ movies: chunk } }); - setXrelIds(prev => { - const next = new Set(prev); - Object.entries(result).forEach(([k,v]) => { if (v) next.add(Number(k)); }); - return next; - }); - } catch (_) {} - } - })(); - }) + .then(setGroups) .catch(e => setError(e.message)) .finally(() => setLoading(false)); }, []); + useEffect(() => { + const allMovies = Object.values(groups).flat(); + if (!allMovies.length) return; + let cancelled = false; + const moviesMeta = allMovies.map(m => ({ id: m.id, title: m.title, original_title: m.original_title })); + (async () => { + for (let i = 0; i < moviesMeta.length; i += 5) { + if (cancelled) break; + try { + const chunk = moviesMeta.slice(i, i + 5); + const result = await api('/tools/media/xrel-check', { method:'POST', body:{ movies: chunk } }); + if (cancelled) break; + const hits = Object.entries(result).filter(([,v]) => v).map(([k]) => Number(k)); + if (hits.length > 0) setXrelIds(prev => new Set([...prev, ...hits])); + } catch (_) {} + } + })(); + return () => { cancelled = true; }; + }, [groups]); + const onToggle = async (movie, isFav) => { try { await toggleFav(movie, isFav); } catch (e) { alert(e.message); } };