fix: modal X-Button fixed, xREL parallel (Scene+P2P), Badge sequential batches

This commit is contained in:
2026-06-10 19:19:28 +02:00
parent e53e8e4331
commit 102ab274c7
2 changed files with 84 additions and 100 deletions

View File

@@ -261,19 +261,21 @@ function KinoGrid({ onOpenModal }) {
api('/tools/media/now-playing')
.then(list => {
setMovies(list);
// xREL-Badge: progressive 5er-Batches
// xREL-Badge: sequentielle 5er-Batches (Rate-Limit-sicher)
const moviesMeta = list.map(m => ({ id: m.id, title: m.title, original_title: m.original_title }));
for (let i = 0; i < moviesMeta.length; i += 5) {
const chunk = moviesMeta.slice(i, i + 5);
api('/tools/media/xrel-check', { method:'POST', body:{ movies: chunk } })
.then(result => {
(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(() => {});
}
} catch (_) {}
}
})();
})
.catch(e => setError(e.message))
.finally(() => setLoading(false));
@@ -327,17 +329,19 @@ function DemnächstGrid({ onOpenModal }) {
setGroups(grps);
const allMovies = Object.values(grps).flat();
const moviesMeta = allMovies.map(m => ({ id: m.id, title: m.title, original_title: m.original_title }));
for (let i = 0; i < moviesMeta.length; i += 5) {
const chunk = moviesMeta.slice(i, i + 5);
api('/tools/media/xrel-check', { method:'POST', body:{ movies: chunk } })
.then(result => {
(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(() => {});
}
} catch (_) {}
}
})();
})
.catch(e => setError(e.message))
.finally(() => setLoading(false));
@@ -461,14 +465,21 @@ function FavoritenKalender({ onOpenModal }) {
// ── Film-Detail-Modal (via Portal) ────────────────────────────────────────────
function MovieModal({ tmdbId, onClose, mobile }) {
const [detail, setDetail] = useState(null);
const [xrel, setXrel] = useState(null); // null=lädt, []+=fertig
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
useEffect(() => {
setLoading(true); setError('');
setLoading(true); setDetail(null); setXrel(null); setError('');
api(`/tools/media/movie/${tmdbId}`)
.then(setDetail).catch(e => setError(e.message)).finally(() => setLoading(false));
.then(d => {
// TMDb-Daten sofort anzeigen
setDetail(d);
setLoading(false);
// xREL ist bereits im response enthalten (Backend lädt parallel)
setXrel(Array.isArray(d.xrel) ? d.xrel : []);
})
.catch(e => { setError(e.message); setLoading(false); });
// Body-Scroll sperren
const prev = document.body.style.overflow;
document.body.style.overflow = 'hidden';
@@ -608,11 +619,15 @@ function MovieModal({ tmdbId, onClose, mobile }) {
</div>
{/* xREL Releases */}
{detail.xrel?.length > 0 && (
{xrel === null && (
<div style={{ marginTop:16, fontSize:11, color:'rgba(255,255,255,0.3)',
fontFamily:'monospace', fontStyle:'italic' }}> Suche deutsche Releases</div>
)}
{xrel !== null && xrel.length > 0 && (
<div style={{ marginTop:18 }}>
<div style={{ ...S.head, marginBottom:8 }}>RELEASES (XREL.TO)</div>
<div style={{ display:'flex', flexDirection:'column', gap:4 }}>
{detail.xrel.map((r, i) => (
{xrel.map((r, i) => (
<a key={i} href={r.url} target="_blank" rel="noopener noreferrer" style={{
display:'flex', alignItems:'flex-start', gap:8,
background:'rgba(255,255,255,0.03)', border:'1px solid rgba(255,255,255,0.07)',