bugfixes + added Training Stats

This commit is contained in:
Linrador 2026-05-02 13:02:48 +02:00
parent 973a07fef8
commit c905753f7a
3 changed files with 1396 additions and 676 deletions

View File

@ -2033,6 +2033,24 @@ export default function App() {
pausedByDisk: false, pausedByDisk: false,
}) })
const applyAutostartState = useCallback((data: unknown) => {
const d = (data ?? {}) as any
setAutostartState({
paused: Boolean(d?.paused),
pausedByUser: Boolean(d?.pausedByUser),
pausedByDisk: Boolean(d?.pausedByDisk),
})
}, [])
const loadAutostartState = useCallback(async () => {
const s = await apiJSON<AutostartState>('/api/autostart/state', {
cache: 'no-store' as any,
})
applyAutostartState(s)
}, [applyAutostartState])
useEffect(() => { useEffect(() => {
busyRef.current = busy busyRef.current = busy
}, [busy]) }, [busy])
@ -2714,6 +2732,7 @@ export default function App() {
if (!authed) return if (!authed) return
let es: EventSource | null = null let es: EventSource | null = null
let autostartEs: EventSource | null = null
let fallbackTimer: number | null = null let fallbackTimer: number | null = null
const stopFallbackPoll = () => { const stopFallbackPoll = () => {
@ -2758,15 +2777,6 @@ export default function App() {
} }
} }
const applyAutostartState = (data: unknown) => {
const d = (data ?? {}) as any
setAutostartState({
paused: Boolean(d?.paused),
pausedByUser: Boolean(d?.pausedByUser),
pausedByDisk: Boolean(d?.pausedByDisk),
})
}
const onDoneChanged = () => { const onDoneChanged = () => {
if (selectedTabRef.current !== 'finished') return if (selectedTabRef.current !== 'finished') return
void loadDonePage(donePageRef.current, doneSortRef.current) void loadDonePage(donePageRef.current, doneSortRef.current)
@ -2837,20 +2847,26 @@ export default function App() {
void loadDoneCount() void loadDoneCount()
void loadTaskStateOnce() void loadTaskStateOnce()
void apiJSON<AutostartState>('/api/autostart/state', { cache: 'no-store' as any }) void loadAutostartState().catch(() => {})
.then((s) => {
setAutostartState({
paused: Boolean(s?.paused),
pausedByUser: Boolean(s?.pausedByUser),
pausedByDisk: Boolean(s?.pausedByDisk),
})
})
.catch(() => {})
es = new EventSource('/api/events/stream') es = new EventSource('/api/events/stream')
eventSourceRef.current = es eventSourceRef.current = es
modelEventNamesRef.current = new Set() modelEventNamesRef.current = new Set()
autostartEs = new EventSource('/api/autostart/state/stream')
autostartEs.addEventListener('autostart', (ev) => {
try {
applyAutostartState(JSON.parse(String((ev as MessageEvent).data ?? 'null')))
} catch {
// ignore
}
})
autostartEs.onerror = () => {
// Falls der separate Stream ausfällt, wenigstens beim Fokus/Visibility wieder korrekt ziehen.
}
es.onopen = () => { es.onopen = () => {
stopFallbackPoll() stopFallbackPoll()
void loadTaskStateOnce() void loadTaskStateOnce()
@ -2867,8 +2883,10 @@ export default function App() {
const onVis = () => { const onVis = () => {
if (document.hidden) return if (document.hidden) return
void loadJobs() void loadJobs()
void loadTaskStateOnce() void loadTaskStateOnce()
void loadAutostartState().catch(() => {})
if (selectedTabRef.current === 'finished') { if (selectedTabRef.current === 'finished') {
void loadDonePage(donePageRef.current, doneSortRef.current) void loadDonePage(donePageRef.current, doneSortRef.current)
@ -2897,10 +2915,21 @@ export default function App() {
es.close() es.close()
} }
if (autostartEs) {
autostartEs.close()
}
eventSourceRef.current = null eventSourceRef.current = null
modelEventNamesRef.current = new Set() modelEventNamesRef.current = new Set()
} }
}, [authed, loadJobs, loadDoneCount, loadPendingAutoStarts]) }, [
authed,
loadJobs,
loadDoneCount,
loadPendingAutoStarts,
applyAutostartState,
loadAutostartState,
])
useEffect(() => { useEffect(() => {
const desired = new Set<string>() const desired = new Set<string>()
@ -3970,14 +3999,14 @@ export default function App() {
roomStatusByModelKey={roomStatusByModelKey} roomStatusByModelKey={roomStatusByModelKey}
pending={pendingWatchedRooms} pending={pendingWatchedRooms}
autostartState={autostartState} autostartState={autostartState}
onRefreshAutostartState={async () => { onRefreshAutostartState={async (next?: AutostartState) => {
try { try {
const s = await apiJSON<AutostartState>('/api/autostart/state', { cache: 'no-store' as any }) if (next) {
setAutostartState({ applyAutostartState(next)
paused: Boolean(s?.paused), return
pausedByUser: Boolean(s?.pausedByUser), }
pausedByDisk: Boolean(s?.pausedByDisk),
}) await loadAutostartState()
} catch { } catch {
// ignore // ignore
} }

View File

@ -32,7 +32,7 @@ type Props = {
jobs: RecordJob[] jobs: RecordJob[]
pending?: PendingWatchedRoom[] pending?: PendingWatchedRoom[]
autostartState?: AutostartState autostartState?: AutostartState
onRefreshAutostartState?: () => Promise<void> | void onRefreshAutostartState?: (next?: AutostartState) => Promise<void> | void
modelsByKey?: Record< modelsByKey?: Record<
string, string,
{ {
@ -644,9 +644,9 @@ export default function Downloads({
const [watchedBusy, setWatchedBusy] = useState(false) const [watchedBusy, setWatchedBusy] = useState(false)
const refreshWatchedState = useCallback(async () => { const refreshWatchedState = useCallback(async (next?: AutostartState) => {
try { try {
await onRefreshAutostartState?.() await onRefreshAutostartState?.(next)
} catch { } catch {
// ignore // ignore
} }
@ -678,11 +678,22 @@ export default function Downloads({
setWatchedBusy(true) setWatchedBusy(true)
try { try {
const res = await fetch('/api/autostart/pause', { method: 'POST' }) const res = await fetch('/api/autostart/pause', {
if (!res.ok) throw new Error(`HTTP ${res.status}`) method: 'POST',
await refreshWatchedState() headers: { 'Content-Type': 'application/json' },
} catch { cache: 'no-store' as any,
// ignore body: JSON.stringify({ paused: true }),
})
if (!res.ok) {
const text = await res.text().catch(() => '')
throw new Error(text || `HTTP ${res.status}`)
}
const data = await res.json().catch(() => null)
await refreshWatchedState(data ?? undefined)
} catch (e) {
console.warn('Autostart pausieren fehlgeschlagen:', e)
} finally { } finally {
setWatchedBusy(false) setWatchedBusy(false)
} }
@ -693,11 +704,20 @@ export default function Downloads({
setWatchedBusy(true) setWatchedBusy(true)
try { try {
const res = await fetch('/api/autostart/resume', { method: 'POST' }) const res = await fetch('/api/autostart/resume', {
if (!res.ok) throw new Error(`HTTP ${res.status}`) method: 'POST',
await refreshWatchedState() cache: 'no-store' as any,
} catch { })
// ignore
if (!res.ok) {
const text = await res.text().catch(() => '')
throw new Error(text || `HTTP ${res.status}`)
}
const data = await res.json().catch(() => null)
await refreshWatchedState(data ?? undefined)
} catch (e) {
console.warn('Autostart fortsetzen fehlgeschlagen:', e)
} finally { } finally {
setWatchedBusy(false) setWatchedBusy(false)
} }
@ -1578,8 +1598,8 @@ export default function Downloads({
} }
leadingIcon={ leadingIcon={
watchedPaused watchedPaused
? <PauseIcon className="size-4 shrink-0" /> ? <PlayIcon className="size-4 shrink-0" />
: <PlayIcon className="size-4 shrink-0" /> : <PauseIcon className="size-4 shrink-0" />
} }
> >
Autostart Autostart
@ -1652,8 +1672,8 @@ export default function Downloads({
} }
leadingIcon={ leadingIcon={
watchedPaused watchedPaused
? <PauseIcon className="size-4 shrink-0" /> ? <PlayIcon className="size-4 shrink-0" />
: <PlayIcon className="size-4 shrink-0" /> : <PauseIcon className="size-4 shrink-0" />
} }
> >
Autostart Autostart

File diff suppressed because it is too large Load Diff