summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/video-app.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-26 16:45:43 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-26 16:45:43 +0200
commitf2b90449841373d9b0fdd70449f3e94c9dd0116d (patch)
tree3a7e47d3994249fcc6282a00fd773d2a8635d669 /packages/meshbay-hub/src/meshbay_hub/static/video-app.js
parentbc94dc672d142e989fa4f483f643d4b43f66b02f (diff)
downloadmeshbay-f2b90449841373d9b0fdd70449f3e94c9dd0116d.tar.gz
feat(video): add an All/Movies/Series filter to the toolbar
A segmented control to the left of the search box, defaulting to "All". Applied before the text filter — a title match within a type nobody asked to see still isn't shown. Resets to "All" on group change, matching the text filter's own reset.
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/video-app.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/video-app.js28
1 files changed, 23 insertions, 5 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/video-app.js b/packages/meshbay-hub/src/meshbay_hub/static/video-app.js
index ce38b0e..dd120da 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/video-app.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/video-app.js
@@ -758,10 +758,14 @@ function VideoApp({
}) {
const [mode, setMode] = useState(loadViewMode);
const [filter, setFilter] = useState('');
+ // Which of movies/shows to show at all — independent of the text filter
+ // below, and applied first: a title match within a type nobody asked to
+ // see is still not what "Movies only" means.
+ const [typeFilter, setTypeFilter] = useState('all');
const tmdbEnabled = tmdbConfig ? tmdbConfig.enabled : true;
useEffect(() => { setMode(loadViewMode()); }, [groupId]);
- useEffect(() => { setFilter(''); }, [groupId]);
+ useEffect(() => { setFilter(''); setTypeFilter('all'); }, [groupId]);
const setModeAndSave = (m) => { setMode(m); saveViewMode(m); };
@@ -769,10 +773,10 @@ function VideoApp({
() => groupVideoEntries(entries, videoRoot), [entries, videoRoot]);
const needle = filter.trim().toLowerCase();
- const filteredMovies = useMemo(() => (!needle ? movies : movies.filter(
- (e) => (e.display_title || e.name).toLowerCase().includes(needle))), [movies, needle]);
- const filteredShows = useMemo(() => (!needle ? shows : shows.filter(
- (s) => s.title.toLowerCase().includes(needle))), [shows, needle]);
+ const filteredMovies = useMemo(() => (typeFilter === 'series' ? [] : !needle ? movies : movies.filter(
+ (e) => (e.display_title || e.name).toLowerCase().includes(needle))), [movies, needle, typeFilter]);
+ const filteredShows = useMemo(() => (typeFilter === 'movies' ? [] : !needle ? shows : shows.filter(
+ (s) => s.title.toLowerCase().includes(needle))), [shows, needle, typeFilter]);
return html`
${(status === 'discovering' || status === 'connecting' || status === 'fetching') && html`
@@ -794,6 +798,20 @@ function VideoApp({
onClick=${() => setModeAndSave('flat')}>
${t('video.mode_flat')}
</button>
+ <div class="tb-typefilter">
+ <button class=${typeFilter === 'all' ? 'active' : ''}
+ onClick=${() => setTypeFilter('all')}>
+ ${t('video.filter_all')}
+ </button>
+ <button class=${typeFilter === 'movies' ? 'active' : ''}
+ onClick=${() => setTypeFilter('movies')}>
+ ${t('video.filter_movies')}
+ </button>
+ <button class=${typeFilter === 'series' ? 'active' : ''}
+ onClick=${() => setTypeFilter('series')}>
+ ${t('video.filter_series')}
+ </button>
+ </div>
<div class="tb-search">
<${Icon} name="search" />
<input type="text" placeholder="${t('group.filter')}"