diff --git a/src/components/viewSettings/viewSettings.js b/src/components/viewSettings/viewSettings.js
index c872561307..d6cbf2e92b 100644
--- a/src/components/viewSettings/viewSettings.js
+++ b/src/components/viewSettings/viewSettings.js
@@ -57,7 +57,7 @@ function showIfAllowed(context, selector, visible) {
class ViewSettings {
show(options) {
- return new Promise(function (resolve, reject) {
+ return new Promise(function (resolve) {
const dialogOptions = {
removeOnClose: true,
scrollY: false
@@ -99,8 +99,9 @@ class ViewSettings {
initEditor(dlg, options.settings);
dlg.querySelector('.selectImageType').addEventListener('change', function () {
- showIfAllowed(dlg, '.chkTitleContainer', this.value !== 'list');
- showIfAllowed(dlg, '.chkYearContainer', this.value !== 'list');
+ showIfAllowed(dlg, '.chkTitleContainer', this.value !== 'list' && this.value !== 'banner');
+ showIfAllowed(dlg, '.chkYearContainer', this.value !== 'list' && this.value !== 'banner');
+ showIfAllowed(dlg, '.chkCardLayoutContainer', this.value !== 'list' && this.value !== 'banner');
});
dlg.querySelector('.btnCancel').addEventListener('click', function () {
@@ -126,11 +127,10 @@ class ViewSettings {
if (submitted) {
saveValues(dlg, options.settings, options.settingsKey);
- resolve();
- return;
+ return resolve();
}
- reject();
+ return resolve();
});
});
}
diff --git a/src/components/viewSettings/viewSettings.template.html b/src/components/viewSettings/viewSettings.template.html
index 8aea2fac26..5989b3f83e 100644
--- a/src/components/viewSettings/viewSettings.template.html
+++ b/src/components/viewSettings/viewSettings.template.html
@@ -35,6 +35,13 @@
${GroupBySeries}
+
+
+
+
diff --git a/src/strings/en-us.json b/src/strings/en-us.json
index 7106cbceee..1487f8bf29 100644
--- a/src/strings/en-us.json
+++ b/src/strings/en-us.json
@@ -236,6 +236,7 @@
"EnableNextVideoInfoOverlayHelp": "At the end of a video, display info about the next video coming up in the current playlist.",
"EnablePhotos": "Display the photos",
"EnablePhotosHelp": "Images will be detected and displayed alongside other media files.",
+ "EnableCardLayout": "Display visual CardBox",
"EnableRewatchingNextUp": "Enable Rewatching in Next Up",
"EnableRewatchingNextUpHelp": "Enable showing already watched episodes in 'Next Up' sections.",
"EnableQuickConnect": "Enable Quick Connect on this server",
diff --git a/src/view/components/AlphaPickerContainer.tsx b/src/view/components/AlphaPickerContainer.tsx
index b85e99e0bd..57b87e0b52 100644
--- a/src/view/components/AlphaPickerContainer.tsx
+++ b/src/view/components/AlphaPickerContainer.tsx
@@ -1,33 +1,34 @@
-import React, { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react';
+import React, { FC, useCallback, useEffect, useRef, useState } from 'react';
import AlphaPicker from '../../components/alphaPicker/alphaPicker';
-import { IQuery } from './type';
+import { AlphaPickerValueI, QueryI } from './interface';
-type AlphaPickerProps = {
- query: IQuery;
- reloadItems: () => void;
-};
+interface AlphaPickerContainerI {
+ getQuery: () => QueryI
+ setAlphaPickerValue: React.Dispatch;
+ setStartIndex: React.Dispatch>;
+}
-const AlphaPickerContainer: FunctionComponent = ({ query, reloadItems }: AlphaPickerProps) => {
+const AlphaPickerContainer: FC = ({ getQuery, setAlphaPickerValue, setStartIndex }) => {
const [ alphaPicker, setAlphaPicker ] = useState();
const element = useRef(null);
+ const query = getQuery();
alphaPicker?.updateControls(query);
const onAlphaPickerChange = useCallback((e) => {
const newValue = (e as CustomEvent).detail.value;
+ let updatedValue;
if (newValue === '#') {
- query.NameLessThan = 'A';
- delete query.NameStartsWith;
+ updatedValue = {NameLessThan: 'A'};
} else {
- query.NameStartsWith = newValue;
- delete query.NameLessThan;
+ updatedValue = {NameStartsWith: newValue};
}
- query.StartIndex = 0;
- reloadItems();
- }, [query, reloadItems]);
+ setAlphaPickerValue(updatedValue);
+ setStartIndex(0);
+ }, [setStartIndex, setAlphaPickerValue]);
useEffect(() => {
- const alphaPickerElement = element.current?.querySelector('.alphaPicker');
+ const alphaPickerElement = element.current;
setAlphaPicker(new AlphaPicker({
element: alphaPickerElement,
@@ -37,12 +38,14 @@ const AlphaPickerContainer: FunctionComponent = ({ query, relo
if (alphaPickerElement) {
alphaPickerElement.addEventListener('alphavaluechanged', onAlphaPickerChange);
}
+
+ return () => {
+ alphaPickerElement?.removeEventListener('alphavaluechanged', onAlphaPickerChange);
+ };
}, [onAlphaPickerChange]);
return (
-
+
);
};
diff --git a/src/view/components/GenresItemsContainer.tsx b/src/view/components/GenresItemsContainer.tsx
index 1b90e49e70..9c8d268396 100644
--- a/src/view/components/GenresItemsContainer.tsx
+++ b/src/view/components/GenresItemsContainer.tsx
@@ -1,7 +1,7 @@
import '../../elements/emby-button/emby-button';
import '../../elements/emby-itemscontainer/emby-itemscontainer';
-import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client';
+import type { BaseItemDtoQueryResult } from '@jellyfin/sdk/lib/generated-client';
import escapeHTML from 'escape-html';
import React, { FC, useCallback, useEffect, useRef } from 'react';
diff --git a/src/view/components/ItemsContainer.tsx b/src/view/components/ItemsContainer.tsx
index 806cad279e..3deb0829bc 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, { FC, useEffect, useRef } from 'react';
+import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
+import React, { FC, useCallback, useEffect, useRef } from 'react';
import ItemsContainerElement from '../../elements/ItemsContainerElement';
import cardBuilder from '../../components/cardbuilder/cardBuilder';
@@ -7,82 +7,78 @@ import listview from '../../components/listview/listview';
import globalize from '../../scripts/globalize';
import imageLoader from '../../components/images/imageLoader';
import '../../elements/emby-itemscontainer/emby-itemscontainer';
-import { QueryI } from './interface';
+import { CardOptionsI } from './interface';
interface ItemsContainerI {
- getCurrentViewStyle: () => string;
- query: QueryI;
+ getViewSettings: () => {
+ showTitle: string | boolean;
+ cardLayout: string | boolean;
+ showYear: string | boolean;
+ imageType: string;
+ viewType: string;
+ };
getContext: () => string | null;
items?: BaseItemDto[] | null;
noItemsMessage?: string;
}
-const ItemsContainer: FC = ({ getCurrentViewStyle, query, getContext, items = [], noItemsMessage }) => {
+const ItemsContainer: FC = ({ getViewSettings, getContext, items = [], noItemsMessage }) => {
const element = useRef(null);
- const viewStyle = getCurrentViewStyle();
+ const viewsettings = getViewSettings();
- useEffect(() => {
- let html;
+ const getCardOptions = useCallback(() => {
+ let shape;
+ let preferThumb;
+ let preferDisc;
+ let preferLogo;
- if (viewStyle == 'Thumb') {
- html = cardBuilder.getCardsHtml(items, {
- items: items,
- shape: 'backdrop',
- preferThumb: true,
- context: getContext(),
- lazy: true,
- overlayPlayButton: true,
- showTitle: true,
- showYear: true,
- centerText: true
- });
- } else if (viewStyle == 'ThumbCard') {
- html = cardBuilder.getCardsHtml(items, {
- items: items,
- shape: 'backdrop',
- preferThumb: true,
- context: getContext(),
- lazy: true,
- cardLayout: true,
- showTitle: true,
- showYear: true,
- centerText: true
- });
- } else if (viewStyle == 'Banner') {
- html = cardBuilder.getCardsHtml(items, {
- items: items,
- shape: 'banner',
- preferBanner: true,
- context: getContext(),
- lazy: true
- });
- } else if (viewStyle == 'List') {
+ if (viewsettings.imageType === 'banner') {
+ shape = 'banner';
+ } else if (viewsettings.imageType === 'disc') {
+ shape = 'square';
+ preferDisc = true;
+ } else if (viewsettings.imageType === 'logo') {
+ shape = 'backdrop';
+ preferLogo = true;
+ } else if (viewsettings.imageType === 'thumb') {
+ shape = 'backdrop';
+ preferThumb = true;
+ } else {
+ shape = 'autoVertical';
+ }
+
+ const cardOptions: CardOptionsI = {
+ shape: shape,
+ showTitle: viewsettings.showTitle,
+ showYear: viewsettings.showTitle,
+ cardLayout: viewsettings.cardLayout,
+ centerText: true,
+ context: getContext(),
+ coverImage: true,
+ preferThumb: preferThumb,
+ preferDisc: preferDisc,
+ preferLogo: preferLogo,
+ overlayPlayButton: false,
+ overlayMoreButton: true,
+ overlayText: !viewsettings.showTitle
+ };
+
+ cardOptions.items = items;
+
+ return cardOptions;
+ }, [getContext, items, viewsettings.cardLayout, viewsettings.imageType, viewsettings.showTitle]);
+
+ const getItemsHtml = useCallback(() => {
+ const settings = getViewSettings();
+
+ let html = '';
+
+ if (settings.imageType === 'list') {
html = listview.getListViewHtml({
items: items,
- context: getContext(),
- sortBy: query.SortBy
- });
- } else if (viewStyle == 'PosterCard') {
- html = cardBuilder.getCardsHtml(items, {
- items: items,
- shape: 'portrait',
- context: getContext(),
- showTitle: true,
- showYear: true,
- centerText: true,
- lazy: true,
- cardLayout: true
- });
+ context: getContext()});
} else {
- html = cardBuilder.getCardsHtml(items, {
- items: items,
- shape: 'portrait',
- context: getContext(),
- overlayPlayButton: true,
- showTitle: true,
- showYear: true,
- centerText: true
- });
+ html = cardBuilder.getCardsHtml(items, getCardOptions());
}
if (!items?.length) {
@@ -94,12 +90,16 @@ const ItemsContainer: FC = ({ getCurrentViewStyle, query, getCo
html += '';
}
- const itemsContainer = element.current?.querySelector('.itemsContainer') as HTMLDivElement;
- itemsContainer.innerHTML = html;
- imageLoader.lazyChildren(itemsContainer);
- }, [query.SortBy, items, noItemsMessage, viewStyle, getContext]);
+ return html;
+ }, [getCardOptions, getContext, getViewSettings, items, noItemsMessage]);
- const cssClass = viewStyle == 'List' ? 'vertical-list' : 'vertical-wrap';
+ useEffect(() => {
+ const itemsContainer = element.current?.querySelector('.itemsContainer') as HTMLDivElement;
+ itemsContainer.innerHTML = getItemsHtml();
+ imageLoader.lazyChildren(itemsContainer);
+ }, [getItemsHtml]);
+
+ const cssClass = viewsettings.imageType == 'List' ? 'vertical-list' : 'vertical-wrap';
return (
diff --git a/src/view/components/Pagination.tsx b/src/view/components/Pagination.tsx
index 37eb168ea3..7a6da59a2a 100644
--- a/src/view/components/Pagination.tsx
+++ b/src/view/components/Pagination.tsx
@@ -1,36 +1,35 @@
-import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client';
+import type { BaseItemDtoQueryResult } from '@jellyfin/sdk/lib/generated-client';
import React, { FC, useCallback, useEffect, useRef } from 'react';
import IconButtonElement from '../../elements/IconButtonElement';
import globalize from '../../scripts/globalize';
-import { QueryI } from './interface';
+import * as userSettings from '../../scripts/settings/userSettings';
interface PaginationI {
- query: QueryI;
+ startIndex: number
+ setStartIndex: React.Dispatch
>;
itemsResult?: BaseItemDtoQueryResult;
- reloadItems: () => void;
}
-const Pagination: FC = ({ query, itemsResult = {}, reloadItems }) => {
- const startIndex = query.StartIndex;
- const limit = query.Limit;
+const Pagination: FC = ({ startIndex, setStartIndex, itemsResult = {} }) => {
+ const limit = userSettings.libraryPageSize(undefined);
const totalRecordCount = itemsResult.TotalRecordCount || 0;
const recordsEnd = Math.min(startIndex + limit, totalRecordCount);
const showControls = limit < totalRecordCount;
const element = useRef(null);
const onNextPageClick = useCallback(() => {
- if (query.Limit > 0) {
- query.StartIndex += query.Limit;
+ if (limit > 0) {
+ const newIndex = startIndex + limit;
+ setStartIndex(newIndex);
}
- reloadItems();
- }, [query, reloadItems]);
+ }, [limit, setStartIndex, startIndex]);
const onPreviousPageClick = useCallback(() => {
- if (query.Limit > 0) {
- query.StartIndex = Math.max(0, query.StartIndex - query.Limit);
+ if (limit > 0) {
+ const newIndex = Math.max(0, startIndex - limit);
+ setStartIndex(newIndex);
}
- reloadItems();
- }, [query, reloadItems]);
+ }, [limit, setStartIndex, startIndex]);
useEffect(() => {
const btnNextPage = element.current?.querySelector('.btnNextPage') as HTMLButtonElement;
@@ -52,6 +51,11 @@ const Pagination: FC = ({ query, itemsResult = {}, reloadItems }) =
}
btnPreviousPage.addEventListener('click', onPreviousPageClick);
}
+
+ return () => {
+ btnNextPage?.removeEventListener('click', onNextPageClick);
+ btnPreviousPage?.removeEventListener('click', onPreviousPageClick);
+ };
}, [totalRecordCount, onNextPageClick, onPreviousPageClick, limit, startIndex]);
return (
diff --git a/src/view/components/RecommendationContainer.tsx b/src/view/components/RecommendationContainer.tsx
index 836e2126fb..a88cf2f404 100644
--- a/src/view/components/RecommendationContainer.tsx
+++ b/src/view/components/RecommendationContainer.tsx
@@ -1,4 +1,4 @@
-import { RecommendationDto } from '@thornbill/jellyfin-sdk/dist/generated-client';
+import type { RecommendationDto } from '@jellyfin/sdk/lib/generated-client';
import React, { FC } from 'react';
import globalize from '../../scripts/globalize';
diff --git a/src/view/components/SectionContainer.tsx b/src/view/components/SectionContainer.tsx
index eb9daacb1f..b1ecff8716 100644
--- a/src/view/components/SectionContainer.tsx
+++ b/src/view/components/SectionContainer.tsx
@@ -1,6 +1,6 @@
import '../../elements/emby-itemscontainer/emby-itemscontainer';
-import { BaseItemDto } from '@thornbill/jellyfin-sdk/dist/generated-client';
+import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
import React, { FC, useEffect, useRef } from 'react';
import cardBuilder from '../../components/cardbuilder/cardBuilder';
diff --git a/src/view/components/SelectView.tsx b/src/view/components/SelectView.tsx
index 4a308c11db..6b48a86b99 100644
--- a/src/view/components/SelectView.tsx
+++ b/src/view/components/SelectView.tsx
@@ -1,32 +1,43 @@
-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 SelectViewI {
- getCurrentViewStyle: () => string;
- query: QueryI;
- getViewSettings: () => string;
+ getSettingsKey: () => string;
+ getVisibleViewSettings: () => string[];
+ getViewSettings: () => {
+ showTitle: string | boolean;
+ cardLayout: string | boolean;
+ showYear: string | boolean;
+ imageType: string;
+ viewType: string;
+ };
reloadItems: () => void;
}
-const SelectView: FC = ({ getCurrentViewStyle, getViewSettings, query, reloadItems }) => {
+const SelectView: FC = ({ getSettingsKey, getVisibleViewSettings, getViewSettings, reloadItems }) => {
const element = useRef(null);
+ const showViewSettingsMenu = useCallback(() => {
+ import('../../components/viewSettings/viewSettings').then(({default: ViewSettings}) => {
+ const viewSettings = new ViewSettings();
+ viewSettings.show({
+ settingsKey: getSettingsKey(),
+ settings: getViewSettings(),
+ visibleSettings: getVisibleViewSettings()
+ }).then(() => {
+ reloadItems();
+ });
+ });
+ }, [getSettingsKey, getViewSettings, getVisibleViewSettings, reloadItems]);
+
useEffect(() => {
const btnSelectView = element.current?.querySelector('.btnSelectView') as HTMLButtonElement;
- btnSelectView.addEventListener('click', (e) => {
- libraryBrowser.showLayoutMenu(e.target, getCurrentViewStyle(), 'Banner,List,Poster,PosterCard,Thumb,ThumbCard'.split(','));
- });
- btnSelectView.addEventListener('layoutchange', (e) => {
- const viewStyle = (e as CustomEvent).detail.viewStyle;
- userSettings.set(getViewSettings(), viewStyle, false);
- query.StartIndex = 0;
- reloadItems();
- });
- }, [getCurrentViewStyle, query, reloadItems, getViewSettings]);
+ btnSelectView?.addEventListener('click', showViewSettingsMenu);
+
+ return () => {
+ btnSelectView?.removeEventListener('click', showViewSettingsMenu);
+ };
+ }, [showViewSettingsMenu]);
return (
diff --git a/src/view/components/Shuffle.tsx b/src/view/components/Shuffle.tsx
index 35da1f7f9f..e808c7f3d8 100644
--- a/src/view/components/Shuffle.tsx
+++ b/src/view/components/Shuffle.tsx
@@ -1,4 +1,4 @@
-import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client';
+import type { BaseItemDtoQueryResult } from '@jellyfin/sdk/lib/generated-client';
import React, { FC, useCallback, useEffect, useRef } from 'react';
import { playbackManager } from '../../components/playback/playbackmanager';
diff --git a/src/view/components/ViewItemsContainer.tsx b/src/view/components/ViewItemsContainer.tsx
index 10a1046da2..cb2650a5ab 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, useRef, useState } from 'react';
+import type { BaseItemDtoQueryResult } from '@jellyfin/sdk/lib/generated-client';
+import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import loading from '../../components/loading/loading';
import * as userSettings from '../../scripts/settings/userSettings';
@@ -10,9 +10,10 @@ import Pagination from './Pagination';
import SelectView from './SelectView';
import Shuffle from './Shuffle';
import Sort from './Sort';
-import { QueryI } from './interface';
import NewCollection from './NewCollection';
import globalize from '../../scripts/globalize';
+import layoutManager from '../../components/layoutManager';
+import { AlphaPickerValueI, QueryI } from './interface';
interface ViewItemsContainerI {
topParentId: string | null;
@@ -36,15 +37,37 @@ const ViewItemsContainer: FC
= ({
getNoItemsMessage
}) => {
const [ itemsResult, setItemsResult ] = useState({});
+ const [ startIndex, setStartIndex ] = useState(0);
+ const [ alphaPickerValue, setAlphaPickerValue ] = useState({});
const element = useRef(null);
+ const queryAlphaPickerValue = useMemo(() => ({
+ ...alphaPickerValue
+ }), [alphaPickerValue]);
+
const getSettingsKey = useCallback(() => {
return `${topParentId} - ${getBasekey()}`;
}, [getBasekey, topParentId]);
+ const getVisibleViewSettings = useCallback(() => {
+ return [
+ 'showTitle',
+ 'showYear',
+ 'imageType',
+ 'cardLayout'
+ ];
+ }, []);
+
const getViewSettings = useCallback(() => {
- return `${getSettingsKey()} -view`;
+ const basekey = getSettingsKey();
+ return {
+ showTitle: userSettings.get(basekey + '-showTitle', false) !== 'false',
+ showYear: userSettings.get(basekey + '-showYear', false) !== 'false',
+ imageType: userSettings.get(basekey + '-imageType', false) || 'primary',
+ viewType: userSettings.get(basekey + '-viewType', false) || 'images',
+ cardLayout: userSettings.get(basekey + '-cardLayout', false) !== 'false'
+ };
}, [getSettingsKey]);
const getDefaultSortBy = useCallback(() => {
@@ -102,16 +125,26 @@ const ViewItemsContainer: FC = ({
}, []);
const getQuery = useCallback(() => {
+ let fields = 'BasicSyncInfo,MediaSourceCount';
+ const viewsettings = getViewSettings();
+ if (viewsettings.imageType === 'primary') {
+ fields += ',PrimaryImageAspectRatio';
+ }
+
+ if (viewsettings.showYear) {
+ fields += ',ProductionYear';
+ }
+
const query: QueryI = {
SortBy: getSortValues().sortBy,
SortOrder: getSortValues().sortOrder,
IncludeItemTypes: getItemTypes().join(','),
Recursive: true,
- Fields: 'PrimaryImageAspectRatio,MediaSourceCount,BasicSyncInfo',
+ Fields: fields,
ImageTypeLimit: 1,
- EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
+ EnableImageTypes: 'Primary,Backdrop,Banner,Thumb,Disc,Logo',
Limit: userSettings.libraryPageSize(undefined),
- StartIndex: 0,
+ StartIndex: startIndex,
ParentId: topParentId
};
@@ -119,13 +152,13 @@ const ViewItemsContainer: FC = ({
query.IsFavorite = true;
}
- userSettings.loadQuerySettings(getSettingsKey(), query);
- return query;
- }, [getSortValues, getItemTypes, topParentId, getBasekey, getSettingsKey]);
+ const queryInfo: QueryI = Object.assign(query, queryAlphaPickerValue || {});
+
+ return queryInfo;
+ }, [getViewSettings, getSortValues, getItemTypes, startIndex, topParentId, getBasekey, queryAlphaPickerValue]);
const getQueryWithFilters = useCallback(() => {
const query = getQuery();
-
const queryFilters = [];
let hasFilters;
@@ -248,10 +281,6 @@ const ViewItemsContainer: FC = ({
}];
}, []);
- const getCurrentViewStyle = useCallback(() => {
- return userSettings.get(getViewSettings(), false) || 'Poster';
- }, [getViewSettings]);
-
const getContext = useCallback(() => {
const itemType = getItemTypes().join(',');
if (itemType === 'Movie' || itemType === 'BoxSet') {
@@ -269,8 +298,8 @@ const ViewItemsContainer: FC = ({
return;
}
loading.show();
- const querywithfilters = getQueryWithFilters().query;
- window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), querywithfilters).then((result) => {
+ const query = getQueryWithFilters().query;
+ window.ApiClient.getItems(window.ApiClient.getCurrentUserId(), query).then((result) => {
setItemsResult(result);
window.scrollTo(0, 0);
@@ -289,10 +318,20 @@ const ViewItemsContainer: FC = ({
return (
-
+
{isBtnShuffleEnabled &&
}
-
+
+ {
}
= ({
- {isAlphaPickerEnabled &&
}
+ {isAlphaPickerEnabled &&
}
);
diff --git a/src/view/components/interface.ts b/src/view/components/interface.ts
index ba1e459ce0..224859e3da 100644
--- a/src/view/components/interface.ts
+++ b/src/view/components/interface.ts
@@ -1,3 +1,9 @@
+import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client';
+
+export interface AlphaPickerValueI {
+ NameLessThan?: string;
+ NameStartsWith?: string | null;
+}
export interface QueryI {
SortBy?: string;
SortOrder?: string;
@@ -7,14 +13,14 @@ export interface QueryI {
ImageTypeLimit?: number;
EnableTotalRecordCount?: boolean;
EnableImageTypes?: string;
- StartIndex: number;
+ StartIndex?: number;
ParentId?: string | null;
IsFavorite?: boolean;
IsMissing?: boolean;
Limit:number;
NameStartsWithOrGreater?: string;
NameLessThan?: string;
- NameStartsWith?: string;
+ NameStartsWith?: string | null;
VideoTypes?: string;
GenreIds?: string;
Is4K?: boolean;
@@ -48,8 +54,9 @@ export interface FiltersI {
}
export interface CardOptionsI {
- itemsContainer?: HTMLElement;
- parentContainer?: HTMLElement;
+ itemsContainer?: HTMLElement | null;
+ parentContainer?: HTMLElement | null;
+ items?: BaseItemDto[] | null;
allowBottomPadding?: boolean;
centerText?: boolean;
coverImage?: boolean;
@@ -58,17 +65,19 @@ export interface CardOptionsI {
overlayPlayButton?: boolean;
overlayText?: boolean;
preferThumb?: boolean;
+ preferDisc?: boolean;
+ preferLogo?: boolean;
scalable?: boolean;
- shape?: string;
+ shape?: string | null;
lazy?: boolean;
- cardLayout?: boolean;
+ cardLayout?: boolean | string;
showParentTitle?: boolean;
showParentTitleOrTitle?: boolean;
showAirTime?: boolean;
showAirDateTime?: boolean;
showChannelName?: boolean;
- showTitle?: boolean;
- showYear?: boolean;
+ showTitle?: boolean | string;
+ showYear?: boolean | string;
showDetailsMenu?: boolean;
missingIndicator?: boolean;
showLocationTypeIndicator?: boolean;
@@ -76,5 +85,43 @@ export interface CardOptionsI {
showUnplayedIndicator?: boolean;
showChildCountIndicator?: boolean;
lines?: number;
- context?: string;
+ context?: string | null;
+ action?: string | null;
+ defaultShape?: string;
+ indexBy?: string;
+ parentId?: string | null;
+ showMenu?: boolean;
+ cardCssClass?: string | null;
+ cardClass?: string | null;
+ centerPlayButton?: boolean;
+ overlayInfoButton?: boolean;
+ autoUpdate?: boolean;
+ cardFooterAside?: string;
+ includeParentInfoInTitle?: boolean;
+ maxLines?: number;
+ overlayMarkPlayedButton?: boolean;
+ overlayRateButton?: boolean;
+ showAirEndTime?: boolean;
+ showCurrentProgram?: boolean;
+ showCurrentProgramTime?: boolean;
+ showItemCounts?: boolean;
+ showPersonRoleOrType?: boolean;
+ showProgressBar?: boolean;
+ showPremiereDate?: boolean;
+ showRuntime?: boolean;
+ showSeriesTimerTime?: boolean;
+ showSeriesTimerChannel?: boolean;
+ showSongCount?: boolean;
+ width?: number;
+ showChannelLogo?: boolean;
+ showLogo?: boolean;
+ serverId?: string;
+ collectionId?: string | null;
+ playlistId?: string | null;
+ defaultCardImageIcon?: string;
+ disableHoverMenu?: boolean;
+ disableIndicators?: boolean;
+ showGroupCount?: boolean;
+ containerClass?: string;
+ noItemsMessage?: string;
}
diff --git a/src/view/movies/GenresView.tsx b/src/view/movies/GenresView.tsx
index b61b97b76f..4f8cb1dfaa 100644
--- a/src/view/movies/GenresView.tsx
+++ b/src/view/movies/GenresView.tsx
@@ -1,4 +1,4 @@
-import { BaseItemDtoQueryResult } from '@thornbill/jellyfin-sdk/dist/generated-client';
+import type { BaseItemDtoQueryResult } from '@jellyfin/sdk/lib/generated-client';
import React, { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import loading from '../../components/loading/loading';
diff --git a/src/view/movies/SuggestionsView.tsx b/src/view/movies/SuggestionsView.tsx
index 5bd73f0ae4..befde0e832 100644
--- a/src/view/movies/SuggestionsView.tsx
+++ b/src/view/movies/SuggestionsView.tsx
@@ -1,5 +1,5 @@
-import { BaseItemDto, BaseItemDtoQueryResult, RecommendationDto } from '@thornbill/jellyfin-sdk/dist/generated-client';
-import React, { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react';
+import type { BaseItemDto, BaseItemDtoQueryResult, RecommendationDto } from '@jellyfin/sdk/lib/generated-client';
+import React, { FC, useCallback, useEffect, useRef, useState } from 'react';
import layoutManager from '../../components/layoutManager';
import loading from '../../components/loading/loading';
@@ -12,7 +12,7 @@ interface SuggestionsViewI {
topParentId: string | null;
}
-const SuggestionsView: FunctionComponent = ({topParentId}) => {
+const SuggestionsView: FC = ({topParentId}) => {
const [ latestItems, setLatestItems ] = useState([]);
const [ resumeResult, setResumeResult ] = useState({});
const [ recommendations, setRecommendations ] = useState([]);