diff --git a/src/view/components/ItemsContainer.tsx b/src/view/components/ItemsContainer.tsx index 84354aafc4..806cad279e 100644 --- a/src/view/components/ItemsContainer.tsx +++ b/src/view/components/ItemsContainer.tsx @@ -1,5 +1,5 @@ import { BaseItemDto } from '@thornbill/jellyfin-sdk/dist/generated-client'; -import React, { FunctionComponent, useEffect, useRef } from 'react'; +import React, { FC, useEffect, useRef } from 'react'; import ItemsContainerElement from '../../elements/ItemsContainerElement'; import cardBuilder from '../../components/cardbuilder/cardBuilder'; @@ -9,7 +9,7 @@ import imageLoader from '../../components/images/imageLoader'; import '../../elements/emby-itemscontainer/emby-itemscontainer'; import { QueryI } from './interface'; -type ItemsContainerProps = { +interface ItemsContainerI { getCurrentViewStyle: () => string; query: QueryI; getContext: () => string | null; @@ -17,7 +17,7 @@ type ItemsContainerProps = { noItemsMessage?: string; } -const ItemsContainer: FunctionComponent = ({ getCurrentViewStyle, query, getContext, items = [], noItemsMessage }: ItemsContainerProps) => { +const ItemsContainer: FC = ({ getCurrentViewStyle, query, getContext, items = [], noItemsMessage }) => { const element = useRef(null); const viewStyle = getCurrentViewStyle(); diff --git a/src/view/components/Sort.tsx b/src/view/components/Sort.tsx index 770b466dfe..43c5125f1d 100644 --- a/src/view/components/Sort.tsx +++ b/src/view/components/Sort.tsx @@ -1,40 +1,44 @@ -import React, { FC, useEffect, useRef } from 'react'; +import React, { FC, useCallback, useEffect, useRef } from 'react'; import IconButtonElement from '../../elements/IconButtonElement'; -import libraryBrowser from '../../scripts/libraryBrowser'; -import * as userSettings from '../../scripts/settings/userSettings'; -import { QueryI } from './interface'; interface SortI { getSortMenuOptions: () => { name: string; - id: string; - }[]; - query: QueryI; + value: string; + }[] + getSortValues: () => { + sortBy: string; + sortOrder: string; + } getSettingsKey: () => string; reloadItems: () => void; } -const Sort: FC = ({ getSortMenuOptions, query, getSettingsKey, reloadItems }) => { +const Sort: FC = ({ getSortMenuOptions, getSortValues, getSettingsKey, reloadItems }) => { const element = useRef(null); + const showSortMenu = useCallback(() => { + import('../../components/sortmenu/sortmenu').then(({default: SortMenu}) => { + const sortMenu = new SortMenu(); + sortMenu.show({ + settingsKey: getSettingsKey(), + settings: getSortValues(), + sortOptions: getSortMenuOptions() + }).then(() => { + reloadItems(); + }); + }); + }, [getSettingsKey, getSortMenuOptions, getSortValues, reloadItems]); + useEffect(() => { const btnSort = element.current?.querySelector('.btnSort'); - if (btnSort) { - btnSort.addEventListener('click', (e) => { - libraryBrowser.showSortMenu({ - items: getSortMenuOptions(), - callback: () => { - query.StartIndex = 0; - userSettings.saveQuerySettings(getSettingsKey(), query); - reloadItems(); - }, - query: query, - button: e.target - }); - }); - } - }, [getSortMenuOptions, query, reloadItems, getSettingsKey]); + btnSort?.addEventListener('click', showSortMenu); + + return () => { + btnSort?.removeEventListener('click', showSortMenu); + }; + }, [showSortMenu]); return (
diff --git a/src/view/components/ViewItemsContainer.tsx b/src/view/components/ViewItemsContainer.tsx index 50c97c30ea..909da7be78 100644 --- a/src/view/components/ViewItemsContainer.tsx +++ b/src/view/components/ViewItemsContainer.tsx @@ -1,5 +1,5 @@ import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client'; -import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { FC, useCallback, useEffect, useRef, useState } from 'react'; import loading from '../../components/loading/loading'; import * as userSettings from '../../scripts/settings/userSettings'; @@ -12,6 +12,7 @@ import Shuffle from './Shuffle'; import Sort from './Sort'; import { QueryI } from './interface'; import NewCollection from './NewCollection'; +import globalize from '../../scripts/globalize'; interface ViewItemsContainerI { topParentId: string | null; @@ -22,10 +23,6 @@ interface ViewItemsContainerI { getBasekey: () => string; getFilterMode: () => string; getItemTypes: () => string; - getSortMenuOptions: () => { - name: string; - id: string; - }[]; getNoItemsMessage: () => string; } @@ -38,7 +35,6 @@ const ViewItemsContainer: FC = ({ getBasekey, getFilterMode, getItemTypes, - getSortMenuOptions, getNoItemsMessage }) => { const [ itemsResult, setItemsResult ] = useState({}); @@ -53,24 +49,74 @@ const ViewItemsContainer: FC = ({ return `${getSettingsKey()} -view`; }, [getSettingsKey]); - let query = useMemo(() => ({ - SortBy: 'SortName,ProductionYear', - SortOrder: 'Ascending', - IncludeItemTypes: getItemTypes(), - Recursive: true, - Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo', - ImageTypeLimit: 1, - EnableImageTypes: 'Primary,Backdrop,Banner,Thumb', - Limit: userSettings.libraryPageSize(undefined), - StartIndex: 0, - ParentId: topParentId - }), [getItemTypes, topParentId]); + const getDefaultSortBy = useCallback(() => { + return 'SortName'; + }, []); - if (getBasekey() === 'favorites') { - query.IsFavorite = true; - } + const getSortValues = useCallback(() => { + const basekey = getSettingsKey(); - query = userSettings.loadQuerySettings(getSettingsKey(), query); + return { + sortBy: userSettings.getFilter(basekey + '-sortby') || getDefaultSortBy(), + sortOrder: userSettings.getFilter(basekey + '-sortorder') === 'Descending' ? 'Descending' : 'Ascending' + }; + }, [getDefaultSortBy, getSettingsKey]); + + const getQuery = useCallback(() => { + const query: QueryI = { + SortBy: getSortValues().sortBy, + SortOrder: getSortValues().sortOrder, + IncludeItemTypes: getItemTypes(), + Recursive: true, + Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo', + ImageTypeLimit: 1, + EnableImageTypes: 'Primary,Backdrop,Banner,Thumb', + Limit: userSettings.libraryPageSize(undefined), + StartIndex: 0, + ParentId: topParentId + }; + + if (getBasekey() === 'favorites') { + query.IsFavorite = true; + } + + userSettings.loadQuerySettings(getSettingsKey(), query); + return query; + }, [getSortValues, getItemTypes, topParentId, getBasekey, getSettingsKey]); + + const getSortMenuOptions = useCallback(() => { + return [{ + name: globalize.translate('Name'), + value: 'SortName,ProductionYear' + }, { + name: globalize.translate('OptionRandom'), + value: 'Random' + }, { + name: globalize.translate('OptionImdbRating'), + value: 'CommunityRating,SortName,ProductionYear' + }, { + name: globalize.translate('OptionCriticRating'), + value: 'CriticRating,SortName,ProductionYear' + }, { + name: globalize.translate('OptionDateAdded'), + value: 'DateCreated,SortName,ProductionYear' + }, { + name: globalize.translate('OptionDatePlayed'), + value: 'DatePlayed,SortName,ProductionYear' + }, { + name: globalize.translate('OptionParentalRating'), + value: 'OfficialRating,SortName,ProductionYear' + }, { + name: globalize.translate('OptionPlayCount'), + value: 'PlayCount,SortName,ProductionYear' + }, { + name: globalize.translate('OptionReleaseDate'), + value: 'PremiereDate,SortName,ProductionYear' + }, { + name: globalize.translate('Runtime'), + value: 'Runtime,SortName,ProductionYear' + }]; + }, []); const getCurrentViewStyle = useCallback(() => { return userSettings.get(getViewSettings(), false) || 'Poster'; @@ -93,6 +139,7 @@ const ViewItemsContainer: FC = ({ return; } loading.show(); + const query = getQuery(); window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), query).then((result) => { setItemsResult(result); window.scrollTo(0, 0); @@ -103,7 +150,7 @@ const ViewItemsContainer: FC = ({ autoFocuser.autoFocus(page); }); }); - }, [query]); + }, [getQuery]); useEffect(() => { reloadItems(); @@ -112,30 +159,36 @@ const ViewItemsContainer: FC = ({ return (
- + {isBtnShuffleEnabled && } - - + - {isBtnFilterEnabled && } + + + {isBtnFilterEnabled && } {isBtnNewCollectionEnabled && }
- {isAlphaPickerEnabled && } + {isAlphaPickerEnabled && }
- +
); diff --git a/src/view/movies/CollectionsView.tsx b/src/view/movies/CollectionsView.tsx index dd4000c056..059f6b0526 100644 --- a/src/view/movies/CollectionsView.tsx +++ b/src/view/movies/CollectionsView.tsx @@ -1,6 +1,5 @@ import React, { FC, useCallback } from 'react'; -import globalize from '../../scripts/globalize'; import ViewItemsContainer from '../components/ViewItemsContainer'; interface CollectionsViewI { @@ -24,16 +23,6 @@ const CollectionsView: FC = ({ topParentId }) => { return 'MessageNoCollectionsAvailable'; }, []); - const getSortMenuOptions = useCallback(() => { - return [{ - name: globalize.translate('Name'), - id: 'SortName' - }, { - name: globalize.translate('OptionDateAdded'), - id: 'DateCreated,SortName' - }]; - }, []); - return ( = ({ topParentId }) => { getBasekey={getBasekey} getFilterMode={getFilterMode} getItemTypes={getItemTypes} - getSortMenuOptions={getSortMenuOptions} getNoItemsMessage={getNoItemsMessage} /> ); diff --git a/src/view/movies/FavoritesView.tsx b/src/view/movies/FavoritesView.tsx index 3e203a5444..4254578b70 100644 --- a/src/view/movies/FavoritesView.tsx +++ b/src/view/movies/FavoritesView.tsx @@ -1,6 +1,5 @@ import React, { FC, useCallback } from 'react'; -import globalize from '../../scripts/globalize'; import ViewItemsContainer from '../components/ViewItemsContainer'; interface FavoritesViewI { @@ -24,47 +23,12 @@ const FavoritesView: FC = ({ topParentId }) => { return 'MessageNoFavoritesAvailable'; }, []); - const getSortMenuOptions = useCallback(() => { - return [{ - name: globalize.translate('Name'), - id: 'SortName,ProductionYear' - }, { - name: globalize.translate('OptionRandom'), - id: 'Random' - }, { - name: globalize.translate('OptionImdbRating'), - id: 'CommunityRating,SortName,ProductionYear' - }, { - name: globalize.translate('OptionCriticRating'), - id: 'CriticRating,SortName,ProductionYear' - }, { - name: globalize.translate('OptionDateAdded'), - id: 'DateCreated,SortName,ProductionYear' - }, { - name: globalize.translate('OptionDatePlayed'), - id: 'DatePlayed,SortName,ProductionYear' - }, { - name: globalize.translate('OptionParentalRating'), - id: 'OfficialRating,SortName,ProductionYear' - }, { - name: globalize.translate('OptionPlayCount'), - id: 'PlayCount,SortName,ProductionYear' - }, { - name: globalize.translate('OptionReleaseDate'), - id: 'PremiereDate,SortName,ProductionYear' - }, { - name: globalize.translate('Runtime'), - id: 'Runtime,SortName,ProductionYear' - }]; - }, []); - return ( ); diff --git a/src/view/movies/MoviesView.tsx b/src/view/movies/MoviesView.tsx index bd92b9d627..a5f2c69e25 100644 --- a/src/view/movies/MoviesView.tsx +++ b/src/view/movies/MoviesView.tsx @@ -1,5 +1,4 @@ import React, { FC, useCallback } from 'react'; -import globalize from '../../scripts/globalize'; import ViewItemsContainer from '../components/ViewItemsContainer'; @@ -24,40 +23,6 @@ const MoviesView: FC = ({ topParentId }) => { return 'MessageNoItemsAvailable'; }, []); - const getSortMenuOptions = useCallback(() => { - return [{ - name: globalize.translate('Name'), - id: 'SortName,ProductionYear' - }, { - name: globalize.translate('OptionRandom'), - id: 'Random' - }, { - name: globalize.translate('OptionImdbRating'), - id: 'CommunityRating,SortName,ProductionYear' - }, { - name: globalize.translate('OptionCriticRating'), - id: 'CriticRating,SortName,ProductionYear' - }, { - name: globalize.translate('OptionDateAdded'), - id: 'DateCreated,SortName,ProductionYear' - }, { - name: globalize.translate('OptionDatePlayed'), - id: 'DatePlayed,SortName,ProductionYear' - }, { - name: globalize.translate('OptionParentalRating'), - id: 'OfficialRating,SortName,ProductionYear' - }, { - name: globalize.translate('OptionPlayCount'), - id: 'PlayCount,SortName,ProductionYear' - }, { - name: globalize.translate('OptionReleaseDate'), - id: 'PremiereDate,SortName,ProductionYear' - }, { - name: globalize.translate('Runtime'), - id: 'Runtime,SortName,ProductionYear' - }]; - }, []); - return ( = ({ topParentId }) => { getBasekey={getBasekey} getFilterMode={getFilterMode} getItemTypes={getItemTypes} - getSortMenuOptions={getSortMenuOptions} getNoItemsMessage={getNoItemsMessage} /> ); diff --git a/src/view/movies/TrailersView.tsx b/src/view/movies/TrailersView.tsx index 8ed076e987..4896e6e778 100644 --- a/src/view/movies/TrailersView.tsx +++ b/src/view/movies/TrailersView.tsx @@ -1,7 +1,6 @@ import React, { FC, useCallback } from 'react'; -import globalize from '../../scripts/globalize'; import ViewItemsContainer from '../components/ViewItemsContainer'; interface TrailersViewI { @@ -25,38 +24,12 @@ const TrailersView: FC = ({ topParentId }) => { return 'MessageNoTrailersFound'; }, []); - const getSortMenuOptions = useCallback(() => { - return [{ - name: globalize.translate('Name'), - id: 'SortName' - }, { - name: globalize.translate('OptionImdbRating'), - id: 'CommunityRating,SortName' - }, { - name: globalize.translate('OptionDateAdded'), - id: 'DateCreated,SortName' - }, { - name: globalize.translate('OptionDatePlayed'), - id: 'DatePlayed,SortName' - }, { - name: globalize.translate('OptionParentalRating'), - id: 'OfficialRating,SortName' - }, { - name: globalize.translate('OptionPlayCount'), - id: 'PlayCount,SortName' - }, { - name: globalize.translate('OptionReleaseDate'), - id: 'PremiereDate,SortName' - }]; - }, []); - return ( );