feat(stats): delete episode from library detail view

Add Delete Episode button to MediaDetailView/MediaHeader; extract
buildDeleteEpisodeHandler for testability. Add refresh() to
useMediaLibrary (version-bump pattern) and call it in LibraryTab's
onBack so the list reloads after a delete.
This commit is contained in:
2026-04-09 01:01:13 -07:00
parent 20976d63f0
commit 8e25e19cac
6 changed files with 160 additions and 10 deletions

View File

@@ -55,3 +55,11 @@ test('shouldRefreshMediaLibraryRows ignores non-youtube rows', () => {
false,
);
});
test('useMediaLibrary is a function export', async () => {
// Verify the hook is exported as a function. The `refresh` return value
// is exercised at the component level; reactive re-fetch via version bump
// cannot be tested without a full React test environment (no @testing-library).
const mod = await import('./useMediaLibrary');
assert.equal(typeof mod.useMediaLibrary, 'function');
});

View File

@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react';
import { useState, useEffect, useCallback } from 'react';
import { getStatsClient } from './useStatsApi';
import type { MediaLibraryItem } from '../types/stats';
@@ -18,6 +18,9 @@ export function useMediaLibrary() {
const [media, setMedia] = useState<MediaLibraryItem[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [version, setVersion] = useState(0);
const refresh = useCallback(() => setVersion((v) => v + 1), []);
useEffect(() => {
let cancelled = false;
@@ -59,7 +62,7 @@ export function useMediaLibrary() {
clearTimeout(retryTimer);
}
};
}, []);
}, [version]);
return { media, loading, error };
return { media, loading, error, refresh };
}