mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
use filtermenu
This commit is contained in:
parent
0acac1b52d
commit
0dc9ad8904
7 changed files with 215 additions and 51 deletions
|
@ -1,38 +1,53 @@
|
|||
import React, { FC, useCallback, useEffect, useRef } from 'react';
|
||||
import { Events } from 'jellyfin-apiclient';
|
||||
import IconButtonElement from '../../elements/IconButtonElement';
|
||||
import { QueryI } from './interface';
|
||||
import { FiltersI } from './interface';
|
||||
|
||||
interface FilterI {
|
||||
query: QueryI;
|
||||
getFilterMode: () => string | null;
|
||||
topParentId?: string | null;
|
||||
getItemTypes: () => string[];
|
||||
getFilters: () => FiltersI;
|
||||
getSettingsKey: () => string;
|
||||
getFilterMenuOptions: () => Record<string, never>;
|
||||
getVisibleFilters: () => string[];
|
||||
reloadItems: () => void;
|
||||
}
|
||||
|
||||
const Filter: FC<FilterI> = ({ query, getFilterMode, reloadItems }) => {
|
||||
const Filter: FC<FilterI> = ({
|
||||
topParentId,
|
||||
getItemTypes,
|
||||
getSettingsKey,
|
||||
getFilters,
|
||||
getVisibleFilters,
|
||||
getFilterMenuOptions,
|
||||
reloadItems
|
||||
}) => {
|
||||
const element = useRef<HTMLDivElement>(null);
|
||||
|
||||
const showFilterMenu = useCallback(() => {
|
||||
import('../../components/filterdialog/filterdialog').then(({default: filterDialogFactory}) => {
|
||||
const filterDialog = new filterDialogFactory({
|
||||
query: query,
|
||||
mode: getFilterMode(),
|
||||
serverId: window.ApiClient.serverId()
|
||||
});
|
||||
Events.on(filterDialog, 'filterchange', () => {
|
||||
query.StartIndex = 0;
|
||||
import('../../components/filtermenu/filtermenu').then(({default: FilterMenu}) => {
|
||||
const filterMenu = new FilterMenu();
|
||||
filterMenu.show({
|
||||
settingsKey: getSettingsKey(),
|
||||
settings: getFilters(),
|
||||
visibleSettings: getVisibleFilters(),
|
||||
parentId: topParentId,
|
||||
itemTypes: getItemTypes(),
|
||||
serverId: window.ApiClient.serverId(),
|
||||
filterMenuOptions: getFilterMenuOptions()
|
||||
}).then(() => {
|
||||
reloadItems();
|
||||
});
|
||||
filterDialog.show();
|
||||
});
|
||||
}, [getFilterMode, query, reloadItems]);
|
||||
}, [getSettingsKey, getFilters, getVisibleFilters, topParentId, getItemTypes, getFilterMenuOptions, reloadItems]);
|
||||
|
||||
useEffect(() => {
|
||||
const btnFilter = element.current?.querySelector('.btnFilter');
|
||||
|
||||
if (btnFilter) {
|
||||
btnFilter.addEventListener('click', showFilterMenu);
|
||||
}
|
||||
btnFilter?.addEventListener('click', showFilterMenu);
|
||||
|
||||
return () => {
|
||||
btnFilter?.removeEventListener('click', showFilterMenu);
|
||||
};
|
||||
}, [showFilterMenu]);
|
||||
|
||||
return (
|
||||
|
|
|
@ -21,8 +21,7 @@ interface ViewItemsContainerI {
|
|||
isBtnNewCollectionEnabled?: boolean;
|
||||
isAlphaPickerEnabled?: boolean;
|
||||
getBasekey: () => string;
|
||||
getFilterMode: () => string;
|
||||
getItemTypes: () => string;
|
||||
getItemTypes: () => string[];
|
||||
getNoItemsMessage: () => string;
|
||||
}
|
||||
|
||||
|
@ -33,7 +32,6 @@ const ViewItemsContainer: FC<ViewItemsContainerI> = ({
|
|||
isBtnNewCollectionEnabled = false,
|
||||
isAlphaPickerEnabled = true,
|
||||
getBasekey,
|
||||
getFilterMode,
|
||||
getItemTypes,
|
||||
getNoItemsMessage
|
||||
}) => {
|
||||
|
@ -62,11 +60,52 @@ const ViewItemsContainer: FC<ViewItemsContainerI> = ({
|
|||
};
|
||||
}, [getDefaultSortBy, getSettingsKey]);
|
||||
|
||||
const getFilters = useCallback(() => {
|
||||
const basekey = getSettingsKey();
|
||||
return {
|
||||
IsPlayed: userSettings.getFilter(basekey + '-filter-IsPlayed') === 'true',
|
||||
IsUnplayed: userSettings.getFilter(basekey + '-filter-IsUnplayed') === 'true',
|
||||
IsFavorite: userSettings.getFilter(basekey + '-filter-IsFavorite') === 'true',
|
||||
IsResumable: userSettings.getFilter(basekey + '-filter-IsResumable') === 'true',
|
||||
Is4K: userSettings.getFilter(basekey + '-filter-Is4K') === 'true',
|
||||
IsHD: userSettings.getFilter(basekey + '-filter-IsHD') === 'true',
|
||||
IsSD: userSettings.getFilter(basekey + '-filter-IsSD') === 'true',
|
||||
Is3D: userSettings.getFilter(basekey + '-filter-Is3D') === 'true',
|
||||
VideoTypes: userSettings.getFilter(basekey + '-filter-VideoTypes'),
|
||||
SeriesStatus: userSettings.getFilter(basekey + '-filter-SeriesStatus'),
|
||||
HasSubtitles: userSettings.getFilter(basekey + '-filter-HasSubtitles'),
|
||||
HasTrailer: userSettings.getFilter(basekey + '-filter-HasTrailer'),
|
||||
HasSpecialFeature: userSettings.getFilter(basekey + '-filter-HasSpecialFeature'),
|
||||
HasThemeSong: userSettings.getFilter(basekey + '-filter-HasThemeSong'),
|
||||
HasThemeVideo: userSettings.getFilter(basekey + '-filter-HasThemeVideo'),
|
||||
GenreIds: userSettings.getFilter(basekey + '-filter-GenreIds')
|
||||
};
|
||||
}, [getSettingsKey]);
|
||||
|
||||
const getFilterMenuOptions = useCallback(() => {
|
||||
return {};
|
||||
}, []);
|
||||
|
||||
const getVisibleFilters = useCallback(() => {
|
||||
return [
|
||||
'IsUnplayed',
|
||||
'IsPlayed',
|
||||
'IsFavorite',
|
||||
'IsResumable',
|
||||
'VideoType',
|
||||
'HasSubtitles',
|
||||
'HasTrailer',
|
||||
'HasSpecialFeature',
|
||||
'HasThemeSong',
|
||||
'HasThemeVideo'
|
||||
];
|
||||
}, []);
|
||||
|
||||
const getQuery = useCallback(() => {
|
||||
const query: QueryI = {
|
||||
SortBy: getSortValues().sortBy,
|
||||
SortOrder: getSortValues().sortOrder,
|
||||
IncludeItemTypes: getItemTypes(),
|
||||
IncludeItemTypes: getItemTypes().join(','),
|
||||
Recursive: true,
|
||||
Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo',
|
||||
ImageTypeLimit: 1,
|
||||
|
@ -84,6 +123,97 @@ const ViewItemsContainer: FC<ViewItemsContainerI> = ({
|
|||
return query;
|
||||
}, [getSortValues, getItemTypes, topParentId, getBasekey, getSettingsKey]);
|
||||
|
||||
const getQueryWithFilters = useCallback(() => {
|
||||
const query = getQuery();
|
||||
|
||||
const queryFilters = [];
|
||||
let hasFilters;
|
||||
|
||||
const filters = getFilters();
|
||||
|
||||
if (filters.IsPlayed) {
|
||||
queryFilters.push('IsPlayed');
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.IsUnplayed) {
|
||||
queryFilters.push('IsUnplayed');
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.IsFavorite) {
|
||||
queryFilters.push('IsFavorite');
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.IsResumable) {
|
||||
queryFilters.push('IsResumable');
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.VideoTypes) {
|
||||
hasFilters = true;
|
||||
query.VideoTypes = filters.VideoTypes;
|
||||
}
|
||||
|
||||
if (filters.GenreIds) {
|
||||
hasFilters = true;
|
||||
query.GenreIds = filters.GenreIds;
|
||||
}
|
||||
|
||||
if (filters.Is4K) {
|
||||
query.Is4K = true;
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.IsHD) {
|
||||
query.IsHD = true;
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.IsSD) {
|
||||
query.IsHD = false;
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.Is3D) {
|
||||
query.Is3D = true;
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.HasSubtitles) {
|
||||
query.HasSubtitles = true;
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.HasTrailer) {
|
||||
query.HasTrailer = true;
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.HasSpecialFeature) {
|
||||
query.HasSpecialFeature = true;
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.HasThemeSong) {
|
||||
query.HasThemeSong = true;
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
if (filters.HasThemeVideo) {
|
||||
query.HasThemeVideo = true;
|
||||
hasFilters = true;
|
||||
}
|
||||
|
||||
query.Filters = queryFilters.length ? queryFilters.join(',') : null;
|
||||
|
||||
return {
|
||||
query: query,
|
||||
hasFilters: hasFilters
|
||||
};
|
||||
}, [getQuery, getFilters]);
|
||||
|
||||
const getSortMenuOptions = useCallback(() => {
|
||||
return [{
|
||||
name: globalize.translate('Name'),
|
||||
|
@ -123,7 +253,7 @@ const ViewItemsContainer: FC<ViewItemsContainerI> = ({
|
|||
}, [getViewSettings]);
|
||||
|
||||
const getContext = useCallback(() => {
|
||||
const itemType = getItemTypes();
|
||||
const itemType = getItemTypes().join(',');
|
||||
if (itemType === 'Movie' || itemType === 'BoxSet') {
|
||||
return 'movies';
|
||||
}
|
||||
|
@ -139,8 +269,8 @@ const ViewItemsContainer: FC<ViewItemsContainerI> = ({
|
|||
return;
|
||||
}
|
||||
loading.show();
|
||||
const query = getQuery();
|
||||
window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), query).then((result) => {
|
||||
const querywithfilters = getQueryWithFilters().query;
|
||||
window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), querywithfilters).then((result) => {
|
||||
setItemsResult(result);
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
|
@ -150,7 +280,7 @@ const ViewItemsContainer: FC<ViewItemsContainerI> = ({
|
|||
autoFocuser.autoFocus(page);
|
||||
});
|
||||
});
|
||||
}, [getQuery]);
|
||||
}, [getQueryWithFilters]);
|
||||
|
||||
useEffect(() => {
|
||||
reloadItems();
|
||||
|
@ -171,7 +301,15 @@ const ViewItemsContainer: FC<ViewItemsContainerI> = ({
|
|||
reloadItems={reloadItems}
|
||||
/>
|
||||
|
||||
{isBtnFilterEnabled && <Filter query={getQuery()} getFilterMode={getFilterMode} reloadItems={reloadItems} />}
|
||||
{isBtnFilterEnabled && <Filter
|
||||
topParentId={topParentId}
|
||||
getFilters={getFilters}
|
||||
getSettingsKey={getSettingsKey}
|
||||
getItemTypes={getItemTypes}
|
||||
getVisibleFilters={getVisibleFilters}
|
||||
getFilterMenuOptions={getFilterMenuOptions}
|
||||
reloadItems={reloadItems}
|
||||
/>}
|
||||
|
||||
{isBtnNewCollectionEnabled && <NewCollection />}
|
||||
|
||||
|
|
|
@ -12,8 +12,39 @@ export interface QueryI {
|
|||
IsFavorite?: boolean;
|
||||
IsMissing?: boolean;
|
||||
Limit:number;
|
||||
NameStartsWithOrGreater?: string;
|
||||
NameLessThan?: string;
|
||||
NameStartsWith?: string;
|
||||
VideoTypes?: string;
|
||||
GenreIds?: string;
|
||||
Is4K?: boolean;
|
||||
IsHD?: boolean;
|
||||
Is3D?: boolean;
|
||||
HasSubtitles?: boolean;
|
||||
HasTrailer?: boolean;
|
||||
HasSpecialFeature?: boolean;
|
||||
HasThemeSong?: boolean;
|
||||
HasThemeVideo?: boolean;
|
||||
Filters?: string | null;
|
||||
}
|
||||
|
||||
export interface FiltersI {
|
||||
IsPlayed: boolean;
|
||||
IsUnplayed: boolean;
|
||||
IsFavorite: boolean;
|
||||
IsResumable: boolean;
|
||||
Is4K: boolean;
|
||||
IsHD: boolean;
|
||||
IsSD: boolean;
|
||||
Is3D: boolean;
|
||||
VideoTypes: string;
|
||||
SeriesStatus: string;
|
||||
HasSubtitles: string;
|
||||
HasTrailer: string;
|
||||
HasSpecialFeature: string;
|
||||
HasThemeSong: string;
|
||||
HasThemeVideo: string;
|
||||
GenreIds: string;
|
||||
}
|
||||
|
||||
export interface CardOptionsI {
|
||||
|
|
|
@ -11,12 +11,8 @@ const CollectionsView: FC<CollectionsViewI> = ({ topParentId }) => {
|
|||
return 'collections';
|
||||
}, []);
|
||||
|
||||
const getFilterMode = useCallback(() => {
|
||||
return 'movies';
|
||||
}, []);
|
||||
|
||||
const getItemTypes = useCallback(() => {
|
||||
return 'BoxSet';
|
||||
return ['BoxSet'];
|
||||
}, []);
|
||||
|
||||
const getNoItemsMessage = useCallback(() => {
|
||||
|
@ -30,7 +26,6 @@ const CollectionsView: FC<CollectionsViewI> = ({ topParentId }) => {
|
|||
isBtnNewCollectionEnabled={true}
|
||||
isAlphaPickerEnabled={false}
|
||||
getBasekey={getBasekey}
|
||||
getFilterMode={getFilterMode}
|
||||
getItemTypes={getItemTypes}
|
||||
getNoItemsMessage={getNoItemsMessage}
|
||||
/>
|
||||
|
|
|
@ -11,12 +11,8 @@ const FavoritesView: FC<FavoritesViewI> = ({ topParentId }) => {
|
|||
return 'favorites';
|
||||
}, []);
|
||||
|
||||
const getFilterMode = useCallback(() => {
|
||||
return 'movies';
|
||||
}, []);
|
||||
|
||||
const getItemTypes = useCallback(() => {
|
||||
return 'Movie';
|
||||
return ['Movie'];
|
||||
}, []);
|
||||
|
||||
const getNoItemsMessage = useCallback(() => {
|
||||
|
@ -27,7 +23,6 @@ const FavoritesView: FC<FavoritesViewI> = ({ topParentId }) => {
|
|||
<ViewItemsContainer
|
||||
topParentId={topParentId}
|
||||
getBasekey={getBasekey}
|
||||
getFilterMode={getFilterMode}
|
||||
getItemTypes={getItemTypes}
|
||||
getNoItemsMessage={getNoItemsMessage}
|
||||
/>
|
||||
|
|
|
@ -11,12 +11,8 @@ const MoviesView: FC<MoviesViewI> = ({ topParentId }) => {
|
|||
return 'movies';
|
||||
}, []);
|
||||
|
||||
const getFilterMode = useCallback(() => {
|
||||
return 'movies';
|
||||
}, []);
|
||||
|
||||
const getItemTypes = useCallback(() => {
|
||||
return 'Movie';
|
||||
return ['Movie'];
|
||||
}, []);
|
||||
|
||||
const getNoItemsMessage = useCallback(() => {
|
||||
|
@ -28,7 +24,6 @@ const MoviesView: FC<MoviesViewI> = ({ topParentId }) => {
|
|||
topParentId={topParentId}
|
||||
isBtnShuffleEnabled={true}
|
||||
getBasekey={getBasekey}
|
||||
getFilterMode={getFilterMode}
|
||||
getItemTypes={getItemTypes}
|
||||
getNoItemsMessage={getNoItemsMessage}
|
||||
/>
|
||||
|
|
|
@ -12,12 +12,8 @@ const TrailersView: FC<TrailersViewI> = ({ topParentId }) => {
|
|||
return 'trailers';
|
||||
}, []);
|
||||
|
||||
const getFilterMode = useCallback(() => {
|
||||
return 'movies';
|
||||
}, []);
|
||||
|
||||
const getItemTypes = useCallback(() => {
|
||||
return 'Trailer';
|
||||
return ['Trailer'];
|
||||
}, []);
|
||||
|
||||
const getNoItemsMessage = useCallback(() => {
|
||||
|
@ -28,7 +24,6 @@ const TrailersView: FC<TrailersViewI> = ({ topParentId }) => {
|
|||
<ViewItemsContainer
|
||||
topParentId={topParentId}
|
||||
getBasekey={getBasekey}
|
||||
getFilterMode={getFilterMode}
|
||||
getItemTypes={getItemTypes}
|
||||
getNoItemsMessage={getNoItemsMessage}
|
||||
/>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue