From f752ba2b857b61ad756c999b59dd1e3ea5d6fbc8 Mon Sep 17 00:00:00 2001 From: 4gray Date: Fri, 13 Feb 2026 00:45:42 +0100 Subject: [PATCH] feat(xtream): add category search functionality and update selection state --- .../stores/features/with-selection.feature.ts | 43 +++++++++++++++++-- .../xtream-main-container.component.html | 43 +++++++++++++++---- .../xtream-main-container.component.scss | 11 +++++ .../xtream-main-container.component.ts | 15 +++++++ 4 files changed, 101 insertions(+), 11 deletions(-) diff --git a/apps/web/src/app/xtream-tauri/stores/features/with-selection.feature.ts b/apps/web/src/app/xtream-tauri/stores/features/with-selection.feature.ts index bbdbda9f6..0c50b19d9 100644 --- a/apps/web/src/app/xtream-tauri/stores/features/with-selection.feature.ts +++ b/apps/web/src/app/xtream-tauri/stores/features/with-selection.feature.ts @@ -24,6 +24,7 @@ export interface SelectionState { page: number; limit: number; contentSortMode: XtreamCategorySortMode; + categorySearchTerm: string; isLoadingDetails: boolean; detailsError: string | null; } @@ -38,6 +39,7 @@ const initialSelectionState: SelectionState = { page: 0, limit: Number(localStorage.getItem('xtream-page-size') ?? 25), contentSortMode: 'date-desc', + categorySearchTerm: '', isLoadingDetails: false, detailsError: null, }; @@ -88,6 +90,18 @@ export function withSelection() { }); }; + const filterBySearchTerm = (items: any[], searchTerm: string): any[] => { + const normalized = searchTerm.trim().toLocaleLowerCase(); + if (!normalized) { + return items; + } + + return items.filter((item: any) => { + const title = (item.title ?? item.name ?? '').toString(); + return title.toLocaleLowerCase().includes(normalized); + }); + }; + // Memoized sorted content - only recalculates when content/type changes const sortedContent = computed(() => { const categoryType = store.selectedContentType(); @@ -166,6 +180,7 @@ export function withSelection() { const categoryId = store.selectedCategoryId(); const categoryType = store.selectedContentType(); const sortMode = store.contentSortMode(); + const searchTerm = store.categorySearchTerm(); // Access parent store content (from withContent) const storeAny = store as any; @@ -183,6 +198,10 @@ export function withSelection() { Number(item.category_id) === categoryId ); if (categoryType === 'vod' || categoryType === 'series') { + filteredContent = filterBySearchTerm( + filteredContent, + searchTerm + ); filteredContent = sortByMode( filteredContent, sortMode, @@ -203,6 +222,7 @@ export function withSelection() { const categoryId = store.selectedCategoryId(); const categoryType = store.selectedContentType(); const sortMode = store.contentSortMode(); + const searchTerm = store.categorySearchTerm(); // Access parent store content (from withContent) const storeAny = store as any; @@ -222,7 +242,7 @@ export function withSelection() { ); if (categoryType === 'vod' || categoryType === 'series') { return sortByMode( - filteredContent, + filterBySearchTerm(filteredContent, searchTerm), sortMode, categoryType ); @@ -237,6 +257,7 @@ export function withSelection() { getTotalPages: computed(() => { const categoryId = store.selectedCategoryId(); const categoryType = store.selectedContentType(); + const searchTerm = store.categorySearchTerm(); // Access parent store content (from withContent) const storeAny = store as any; @@ -249,10 +270,14 @@ export function withSelection() { let totalItems = 0; if (categoryId) { - totalItems = content.filter( + let filtered = content.filter( (item: any) => Number(item.category_id) === categoryId - ).length; + ); + if (categoryType === 'vod' || categoryType === 'series') { + filtered = filterBySearchTerm(filtered, searchTerm); + } + totalItems = filtered.length; } else { totalItems = content.length; } @@ -320,6 +345,7 @@ export function withSelection() { selectedContentType: type, selectedCategoryId: null, page: 0, + categorySearchTerm: '', }); }, @@ -337,6 +363,7 @@ export function withSelection() { patchState(store, { selectedCategoryId: newCategoryId, page: 0, + categorySearchTerm: '', }); } }, @@ -387,6 +414,16 @@ export function withSelection() { }); }, + /** + * Set selected category search term + */ + setCategorySearchTerm(term: string): void { + patchState(store, { + categorySearchTerm: term, + page: 0, + }); + }, + /** * Reset selection state */ diff --git a/apps/web/src/app/xtream-tauri/xtream-main-container.component.html b/apps/web/src/app/xtream-tauri/xtream-main-container.component.html index f04fd3d63..621363de1 100644 --- a/apps/web/src/app/xtream-tauri/xtream-main-container.component.html +++ b/apps/web/src/app/xtream-tauri/xtream-main-container.component.html @@ -42,14 +42,41 @@ @if (canShowSortMenu()) { - +
+ + search + + @if (categorySearchTerm()) { + + } + + +