mirror of
https://github.com/jellyfin/jellyfin-web.git
synced 2026-09-03 03:50:02 +03:00
Use query client for home screen sections
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import type { Api } from '@jellyfin/sdk/lib/api';
|
||||
import type { UserLibraryApiGetLatestMediaRequest } from '@jellyfin/sdk/lib/generated-client/api/user-library-api';
|
||||
import { getUserLibraryApi } from '@jellyfin/sdk/lib/utils/api/user-library-api';
|
||||
import { queryOptions, useQuery } from '@tanstack/react-query';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
|
||||
import { useApi } from 'hooks/useApi';
|
||||
|
||||
const fetchLatestMedia = async (
|
||||
api: Api,
|
||||
params?: UserLibraryApiGetLatestMediaRequest,
|
||||
options?: AxiosRequestConfig
|
||||
) => {
|
||||
const response = await getUserLibraryApi(api)
|
||||
.getLatestMedia(params, options);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getLatestMediaQuery = (
|
||||
api?: Api,
|
||||
params?: UserLibraryApiGetLatestMediaRequest
|
||||
) => queryOptions({
|
||||
queryKey: [ 'User', params?.userId, 'LatestMedia', params ],
|
||||
queryFn: ({ signal }) => fetchLatestMedia(api!, params, { signal }),
|
||||
enabled: !!api
|
||||
});
|
||||
|
||||
export const useLatestMedia = (
|
||||
params?: UserLibraryApiGetLatestMediaRequest
|
||||
) => {
|
||||
const { api, user } = useApi();
|
||||
return useQuery(getLatestMediaQuery(api, {
|
||||
...params,
|
||||
userId: params?.userId || user?.Id
|
||||
}));
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { Api } from '@jellyfin/sdk/lib/api';
|
||||
import type { TvShowsApiGetNextUpRequest } from '@jellyfin/sdk/lib/generated-client/api/tv-shows-api';
|
||||
import { getTvShowsApi } from '@jellyfin/sdk/lib/utils/api/tv-shows-api';
|
||||
import { queryOptions, useQuery } from '@tanstack/react-query';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
|
||||
import { useApi } from 'hooks/useApi';
|
||||
|
||||
const fetchNextUp = async (
|
||||
api: Api,
|
||||
params?: TvShowsApiGetNextUpRequest,
|
||||
options?: AxiosRequestConfig
|
||||
) => {
|
||||
const response = await getTvShowsApi(api)
|
||||
.getNextUp(params, options);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getNextUpQuery = (
|
||||
api?: Api,
|
||||
params?: TvShowsApiGetNextUpRequest
|
||||
) => queryOptions({
|
||||
queryKey: [ 'User', params?.userId, 'NextUp', params ],
|
||||
queryFn: ({ signal }) => fetchNextUp(api!, params, { signal }),
|
||||
enabled: !!api
|
||||
});
|
||||
|
||||
export const useNextUp = (
|
||||
params?: TvShowsApiGetNextUpRequest
|
||||
) => {
|
||||
const { api, user } = useApi();
|
||||
return useQuery(getNextUpQuery(api, {
|
||||
...params,
|
||||
userId: params?.userId || user?.Id
|
||||
}));
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { Api } from '@jellyfin/sdk/lib/api';
|
||||
import type { ItemsApiGetResumeItemsRequest } from '@jellyfin/sdk/lib/generated-client/api/items-api';
|
||||
import { getItemsApi } from '@jellyfin/sdk/lib/utils/api/items-api';
|
||||
import { queryOptions, useQuery } from '@tanstack/react-query';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
|
||||
import { useApi } from 'hooks/useApi';
|
||||
|
||||
const fetchResumeItems = async (
|
||||
api: Api,
|
||||
params?: ItemsApiGetResumeItemsRequest,
|
||||
options?: AxiosRequestConfig
|
||||
) => {
|
||||
const response = await getItemsApi(api)
|
||||
.getResumeItems(params, options);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getResumeItemsQuery = (
|
||||
api?: Api,
|
||||
params?: ItemsApiGetResumeItemsRequest
|
||||
) => queryOptions({
|
||||
queryKey: [ 'User', params?.userId, 'ResumeItems', params ],
|
||||
queryFn: ({ signal }) => fetchResumeItems(api!, params, { signal }),
|
||||
enabled: !!api
|
||||
});
|
||||
|
||||
export const useResumeItems = (
|
||||
params?: ItemsApiGetResumeItemsRequest
|
||||
) => {
|
||||
const { api, user } = useApi();
|
||||
return useQuery(getResumeItemsQuery(api, {
|
||||
...params,
|
||||
userId: params?.userId || user?.Id
|
||||
}));
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { Api } from '@jellyfin/sdk/lib/api';
|
||||
import type { LiveTvApiGetRecommendedProgramsRequest } from '@jellyfin/sdk/lib/generated-client/api/live-tv-api';
|
||||
import { getLiveTvApi } from '@jellyfin/sdk/lib/utils/api/live-tv-api';
|
||||
import { queryOptions, useQuery } from '@tanstack/react-query';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
|
||||
import { useApi } from 'hooks/useApi';
|
||||
|
||||
const fetchRecommendedPrograms = async (
|
||||
api: Api,
|
||||
params?: LiveTvApiGetRecommendedProgramsRequest,
|
||||
options?: AxiosRequestConfig
|
||||
) => {
|
||||
const response = await getLiveTvApi(api)
|
||||
.getRecommendedPrograms(params, options);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getRecommendedProgramsQuery = (
|
||||
api?: Api,
|
||||
params?: LiveTvApiGetRecommendedProgramsRequest
|
||||
) => queryOptions({
|
||||
queryKey: [ 'User', params?.userId, 'RecommendedPrograms', params ],
|
||||
queryFn: ({ signal }) => fetchRecommendedPrograms(api!, params, { signal }),
|
||||
enabled: !!api
|
||||
});
|
||||
|
||||
export const useRecommendedPrograms = (
|
||||
params?: LiveTvApiGetRecommendedProgramsRequest
|
||||
) => {
|
||||
const { api, user } = useApi();
|
||||
return useQuery(getRecommendedProgramsQuery(api, {
|
||||
...params,
|
||||
userId: params?.userId || user?.Id
|
||||
}));
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
import type { Api } from '@jellyfin/sdk';
|
||||
import type { LiveTvApiGetRecordingsRequest } from '@jellyfin/sdk/lib/generated-client/api/live-tv-api';
|
||||
import { getLiveTvApi } from '@jellyfin/sdk/lib/utils/api/live-tv-api';
|
||||
import { queryOptions, useQuery } from '@tanstack/react-query';
|
||||
import type { AxiosRequestConfig } from 'axios';
|
||||
|
||||
import { useApi } from 'hooks/useApi';
|
||||
|
||||
const fetchRecordings = async (
|
||||
api: Api,
|
||||
params?: LiveTvApiGetRecordingsRequest,
|
||||
options?: AxiosRequestConfig
|
||||
) => {
|
||||
const response = await getLiveTvApi(api).getRecordings(params, options);
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getRecordingsQuery = (
|
||||
api?: Api,
|
||||
params?: LiveTvApiGetRecordingsRequest
|
||||
) => queryOptions({
|
||||
queryKey: [ 'User', params?.userId, 'Recordings', params ],
|
||||
queryFn: ({ signal }) => fetchRecordings(api!, params, { signal }),
|
||||
enabled: !!api
|
||||
});
|
||||
|
||||
export const useRecordings = (
|
||||
params?: LiveTvApiGetRecordingsRequest
|
||||
) => {
|
||||
const { api, user } = useApi();
|
||||
return useQuery(getRecordingsQuery(api, {
|
||||
...params,
|
||||
userId: params?.userId || user?.Id
|
||||
}));
|
||||
};
|
||||
@@ -1,9 +1,13 @@
|
||||
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto';
|
||||
import { ItemFields } from '@jellyfin/sdk/lib/generated-client/models/item-fields';
|
||||
import type { ApiClient } from 'jellyfin-apiclient';
|
||||
|
||||
import { getRecordingsQuery } from 'apps/stable/features/liveTv/api/useRecordings';
|
||||
import cardBuilder from 'components/cardbuilder/cardBuilder';
|
||||
import globalize from 'lib/globalize';
|
||||
import { ServerConnections } from 'lib/jellyfin-apiclient';
|
||||
import { toApi } from 'utils/jellyfin-apiclient/compat';
|
||||
import { queryClient } from 'utils/query/queryClient';
|
||||
|
||||
import type { SectionContainerElement, SectionOptions } from './section';
|
||||
|
||||
@@ -14,14 +18,14 @@ function getLatestRecordingsFetchFn(
|
||||
) {
|
||||
return function () {
|
||||
const apiClient = ServerConnections.getApiClient(serverId);
|
||||
return apiClient.getLiveTvRecordings({
|
||||
return queryClient.fetchQuery(getRecordingsQuery(toApi(apiClient), {
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
Limit: enableOverflow ? 12 : 5,
|
||||
Fields: 'PrimaryImageAspectRatio',
|
||||
EnableTotalRecordCount: false,
|
||||
IsLibraryItem: activeRecordingsOnly ? null : false,
|
||||
IsInProgress: activeRecordingsOnly ? true : null
|
||||
});
|
||||
limit: enableOverflow ? 12 : 5,
|
||||
fields: [ ItemFields.PrimaryImageAspectRatio ],
|
||||
enableTotalRecordCount: false,
|
||||
isLibraryItem: activeRecordingsOnly ? undefined : false,
|
||||
isInProgress: activeRecordingsOnly ? true : undefined
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto';
|
||||
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
||||
import { ItemFields } from '@jellyfin/sdk/lib/generated-client/models/item-fields';
|
||||
import type { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto';
|
||||
import type { ApiClient } from 'jellyfin-apiclient';
|
||||
|
||||
@@ -7,24 +9,33 @@ import cardBuilder from 'components/cardbuilder/cardBuilder';
|
||||
import { getBackdropShape } from 'components/cardbuilder/utils/shape';
|
||||
import layoutManager from 'components/layoutManager';
|
||||
import globalize from 'lib/globalize';
|
||||
import { ServerConnections } from 'lib/jellyfin-apiclient';
|
||||
|
||||
import type { SectionContainerElement, SectionOptions } from './section';
|
||||
import { queryClient } from 'utils/query/queryClient';
|
||||
import { getRecommendedProgramsQuery } from 'apps/stable/features/liveTv/api/useRecommendedPrograms';
|
||||
import { toApi } from 'utils/jellyfin-apiclient/compat';
|
||||
|
||||
function getOnNowFetchFn(
|
||||
serverId: string
|
||||
apiClient: ApiClient
|
||||
) {
|
||||
return function () {
|
||||
const apiClient = ServerConnections.getApiClient(serverId);
|
||||
return apiClient.getLiveTvRecommendedPrograms({
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
IsAiring: true,
|
||||
limit: 24,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: 'Primary,Thumb,Backdrop',
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: 'ChannelInfo,PrimaryImageAspectRatio'
|
||||
});
|
||||
return queryClient
|
||||
.fetchQuery(getRecommendedProgramsQuery(toApi(apiClient), {
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
isAiring: true,
|
||||
limit: 24,
|
||||
imageTypeLimit: 1,
|
||||
enableImageTypes: [
|
||||
ImageType.Primary,
|
||||
ImageType.Thumb,
|
||||
ImageType.Backdrop
|
||||
],
|
||||
enableTotalRecordCount: false,
|
||||
fields: [
|
||||
ItemFields.ChannelInfo,
|
||||
ItemFields.PrimaryImageAspectRatio
|
||||
]
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -56,16 +67,17 @@ function getOnNowItemsHtmlFn(
|
||||
|
||||
function buildSection(
|
||||
elem: HTMLElement,
|
||||
serverId: string,
|
||||
apiClient: ApiClient,
|
||||
options: SectionOptions
|
||||
) {
|
||||
let html = '';
|
||||
const serverId = apiClient.serverId();
|
||||
|
||||
elem.classList.remove('padded-left');
|
||||
elem.classList.remove('padded-right');
|
||||
elem.classList.remove('padded-bottom');
|
||||
elem.classList.remove('verticalSection');
|
||||
|
||||
let html = '';
|
||||
html += '<div class="verticalSection">';
|
||||
html += '<div class="sectionTitleContainer sectionTitleContainer-cards padded-left">';
|
||||
html += '<h2 class="sectionTitle sectionTitle-cards">' + globalize.translate('LiveTV') + '</h2>';
|
||||
@@ -151,7 +163,7 @@ function buildSection(
|
||||
const itemsContainer: SectionContainerElement | null = elem.querySelector('.itemsContainer');
|
||||
if (!itemsContainer) return;
|
||||
itemsContainer.parentContainer = elem;
|
||||
itemsContainer.fetchData = getOnNowFetchFn(serverId);
|
||||
itemsContainer.fetchData = getOnNowFetchFn(apiClient);
|
||||
itemsContainer.getItemsHtml = getOnNowItemsHtmlFn(options);
|
||||
}
|
||||
|
||||
@@ -165,17 +177,26 @@ export function loadLiveTV(
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return apiClient.getLiveTvRecommendedPrograms({
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
IsAiring: true,
|
||||
limit: 1,
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: 'Primary,Thumb,Backdrop',
|
||||
EnableTotalRecordCount: false,
|
||||
Fields: 'ChannelInfo,PrimaryImageAspectRatio'
|
||||
}).then(function (result) {
|
||||
if (result.Items?.length) {
|
||||
buildSection(elem, apiClient.serverId(), options);
|
||||
}
|
||||
});
|
||||
return queryClient
|
||||
.fetchQuery(getRecommendedProgramsQuery(toApi(apiClient), {
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
isAiring: true,
|
||||
limit: 1,
|
||||
imageTypeLimit: 1,
|
||||
enableImageTypes: [
|
||||
ImageType.Primary,
|
||||
ImageType.Thumb,
|
||||
ImageType.Backdrop
|
||||
],
|
||||
enableTotalRecordCount: false,
|
||||
fields: [
|
||||
ItemFields.ChannelInfo,
|
||||
ItemFields.PrimaryImageAspectRatio
|
||||
]
|
||||
}))
|
||||
.then(programs => {
|
||||
if (programs.Items?.length) {
|
||||
buildSection(elem, apiClient, options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,36 +1,50 @@
|
||||
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto';
|
||||
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
||||
import { ItemFields } from '@jellyfin/sdk/lib/generated-client/models/item-fields';
|
||||
import type { ApiClient } from 'jellyfin-apiclient';
|
||||
|
||||
import { getNextUpQuery } from 'apps/stable/features/libraries/api/useNextUp';
|
||||
import cardBuilder from 'components/cardbuilder/cardBuilder';
|
||||
import { getBackdropShape } from 'components/cardbuilder/utils/shape';
|
||||
import layoutManager from 'components/layoutManager';
|
||||
import { appRouter } from 'components/router/appRouter';
|
||||
import globalize from 'lib/globalize';
|
||||
import { ServerConnections } from 'lib/jellyfin-apiclient';
|
||||
import type { UserSettings } from 'scripts/settings/userSettings';
|
||||
import { toIsoDateOnlyString } from 'utils/date';
|
||||
import { toApi } from 'utils/jellyfin-apiclient/compat';
|
||||
import { queryClient } from 'utils/query/queryClient';
|
||||
|
||||
import type { SectionContainerElement, SectionOptions } from './section';
|
||||
|
||||
function getNextUpFetchFn(
|
||||
serverId: string,
|
||||
apiClient: ApiClient,
|
||||
userSettings: UserSettings,
|
||||
{ enableOverflow }: SectionOptions
|
||||
) {
|
||||
return function () {
|
||||
const apiClient = ServerConnections.getApiClient(serverId);
|
||||
const oldestDateForNextUp = new Date();
|
||||
oldestDateForNextUp.setDate(oldestDateForNextUp.getDate() - userSettings.maxDaysForNextUp());
|
||||
return apiClient.getNextUpEpisodes({
|
||||
Limit: enableOverflow ? 24 : 15,
|
||||
Fields: 'PrimaryImageAspectRatio,DateCreated,Path,MediaSourceCount',
|
||||
UserId: apiClient.getCurrentUserId(),
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: 'Primary,Backdrop,Banner,Thumb',
|
||||
EnableTotalRecordCount: false,
|
||||
NextUpDateCutoff: oldestDateForNextUp.toISOString(),
|
||||
EnableResumable: false,
|
||||
EnableRewatching: userSettings.enableRewatchingInNextUp()
|
||||
});
|
||||
return queryClient
|
||||
.fetchQuery(getNextUpQuery(toApi(apiClient), {
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
limit: enableOverflow ? 24 : 15,
|
||||
fields: [
|
||||
ItemFields.PrimaryImageAspectRatio,
|
||||
ItemFields.DateCreated,
|
||||
ItemFields.Path,
|
||||
ItemFields.MediaSourceCount
|
||||
],
|
||||
imageTypeLimit: 1,
|
||||
enableImageTypes: [
|
||||
ImageType.Primary,
|
||||
ImageType.Backdrop,
|
||||
ImageType.Thumb
|
||||
],
|
||||
enableTotalRecordCount: false,
|
||||
nextUpDateCutoff: toIsoDateOnlyString(oldestDateForNextUp),
|
||||
enableResumable: false,
|
||||
enableRewatching: userSettings.enableRewatchingInNextUp()
|
||||
}));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -100,7 +114,7 @@ export function loadNextUp(
|
||||
|
||||
const itemsContainer: SectionContainerElement | null = elem.querySelector('.itemsContainer');
|
||||
if (!itemsContainer) return;
|
||||
itemsContainer.fetchData = getNextUpFetchFn(apiClient.serverId(), userSettings, options);
|
||||
itemsContainer.fetchData = getNextUpFetchFn(apiClient, userSettings, options);
|
||||
itemsContainer.getItemsHtml = getNextUpItemsHtmlFn(userSettings.useEpisodeImagesInNextUpAndResume(), options);
|
||||
itemsContainer.parentContainer = elem;
|
||||
}
|
||||
|
||||
@@ -1,27 +1,31 @@
|
||||
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto';
|
||||
import { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||
import type { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto';
|
||||
import { CollectionType } from '@jellyfin/sdk/lib/generated-client/models/collection-type';
|
||||
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
||||
import { ItemFields } from '@jellyfin/sdk/lib/generated-client/models/item-fields';
|
||||
import type { UserDto } from '@jellyfin/sdk/lib/generated-client/models/user-dto';
|
||||
import escapeHtml from 'escape-html';
|
||||
import type { ApiClient } from 'jellyfin-apiclient';
|
||||
|
||||
import { getLatestMediaQuery } from 'apps/stable/features/libraries/api/useLatestMedia';
|
||||
import cardBuilder from 'components/cardbuilder/cardBuilder';
|
||||
import { getBackdropShape, getPortraitShape, getSquareShape } from 'components/cardbuilder/utils/shape';
|
||||
import layoutManager from 'components/layoutManager';
|
||||
import { appRouter } from 'components/router/appRouter';
|
||||
import globalize from 'lib/globalize';
|
||||
import { ServerConnections } from 'lib/jellyfin-apiclient';
|
||||
import { toApi } from 'utils/jellyfin-apiclient/compat';
|
||||
import { queryClient } from 'utils/query/queryClient';
|
||||
|
||||
import type { SectionContainerElement, SectionOptions } from './section';
|
||||
|
||||
function getFetchLatestItemsFn(
|
||||
serverId: string,
|
||||
apiClient: ApiClient,
|
||||
user: UserDto | undefined,
|
||||
parentId: string | undefined,
|
||||
collectionType: string | null | undefined,
|
||||
{ enableOverflow }: SectionOptions
|
||||
) {
|
||||
return function () {
|
||||
const apiClient = ServerConnections.getApiClient(serverId);
|
||||
let limit = 16;
|
||||
|
||||
if (enableOverflow) {
|
||||
@@ -37,14 +41,23 @@ function getFetchLatestItemsFn(
|
||||
}
|
||||
|
||||
const options = {
|
||||
Limit: limit,
|
||||
Fields: 'PrimaryImageAspectRatio,Path',
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: 'Primary,Backdrop,Thumb',
|
||||
ParentId: parentId
|
||||
userId: user?.Id,
|
||||
limit,
|
||||
fields: [
|
||||
ItemFields.PrimaryImageAspectRatio,
|
||||
ItemFields.Path
|
||||
],
|
||||
imageTypeLimit: 1,
|
||||
enableImageTypes: [
|
||||
ImageType.Primary,
|
||||
ImageType.Backdrop,
|
||||
ImageType.Thumb
|
||||
],
|
||||
parentId
|
||||
};
|
||||
|
||||
return apiClient.getLatestItems(options);
|
||||
return queryClient
|
||||
.fetchQuery(getLatestMediaQuery(toApi(apiClient), options));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -124,7 +137,7 @@ function renderLatestSection(
|
||||
|
||||
const itemsContainer: SectionContainerElement | null = elem.querySelector('.itemsContainer');
|
||||
if (!itemsContainer) return;
|
||||
itemsContainer.fetchData = getFetchLatestItemsFn(apiClient.serverId(), parent.Id, parent.CollectionType, options);
|
||||
itemsContainer.fetchData = getFetchLatestItemsFn(apiClient, user, parent.Id, parent.CollectionType, options);
|
||||
itemsContainer.getItemsHtml = getLatestItemsHtmlFn(parent.Type, parent.CollectionType, options);
|
||||
itemsContainer.parentContainer = elem;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
import type { BaseItemDto } from '@jellyfin/sdk/lib/generated-client/models/base-item-dto';
|
||||
import type { BaseItemKind } from '@jellyfin/sdk/lib/generated-client/models/base-item-kind';
|
||||
import { ImageType } from '@jellyfin/sdk/lib/generated-client/models/image-type';
|
||||
import { ItemFields } from '@jellyfin/sdk/lib/generated-client/models/item-fields';
|
||||
import type { MediaType } from '@jellyfin/sdk/lib/generated-client/models/media-type';
|
||||
import type { ApiClient } from 'jellyfin-apiclient';
|
||||
|
||||
import { getResumeItemsQuery } from 'apps/stable/features/libraries/api/useResumeItems';
|
||||
import cardBuilder from 'components/cardbuilder/cardBuilder';
|
||||
import { getBackdropShape, getPortraitShape } from 'components/cardbuilder/utils/shape';
|
||||
import globalize from 'lib/globalize';
|
||||
import { ServerConnections } from 'lib/jellyfin-apiclient';
|
||||
import { queryClient } from 'utils/query/queryClient';
|
||||
import type { UserSettings } from 'scripts/settings/userSettings';
|
||||
import { toApi } from 'utils/jellyfin-apiclient/compat';
|
||||
|
||||
import type { SectionContainerElement, SectionOptions } from './section';
|
||||
|
||||
@@ -16,32 +20,35 @@ const dataMonitorHints: Record<string, string> = {
|
||||
};
|
||||
|
||||
function getItemsToResumeFn(
|
||||
mediaType: BaseItemKind,
|
||||
serverId: string,
|
||||
apiClient: ApiClient,
|
||||
mediaType: MediaType,
|
||||
{ enableOverflow }: SectionOptions
|
||||
) {
|
||||
return function () {
|
||||
const apiClient = ServerConnections.getApiClient(serverId);
|
||||
|
||||
const limit = enableOverflow ? 12 : 5;
|
||||
|
||||
const options = {
|
||||
Limit: limit,
|
||||
Recursive: true,
|
||||
Fields: 'PrimaryImageAspectRatio',
|
||||
ImageTypeLimit: 1,
|
||||
EnableImageTypes: 'Primary,Backdrop,Thumb',
|
||||
EnableTotalRecordCount: false,
|
||||
MediaTypes: mediaType
|
||||
userId: apiClient.getCurrentUserId(),
|
||||
limit,
|
||||
fields: [ ItemFields.PrimaryImageAspectRatio ],
|
||||
imageTypeLimit: 1,
|
||||
enableImageTypes: [
|
||||
ImageType.Primary,
|
||||
ImageType.Backdrop,
|
||||
ImageType.Thumb
|
||||
],
|
||||
enableTotalRecordCount: false,
|
||||
mediaTypes: [ mediaType ]
|
||||
};
|
||||
|
||||
return apiClient.getResumableItems(apiClient.getCurrentUserId(), options);
|
||||
return queryClient
|
||||
.fetchQuery(getResumeItemsQuery(toApi(apiClient), options));
|
||||
};
|
||||
}
|
||||
|
||||
function getItemsToResumeHtmlFn(
|
||||
useEpisodeImages: boolean,
|
||||
mediaType: BaseItemKind,
|
||||
mediaType: MediaType,
|
||||
{ enableOverflow }: SectionOptions
|
||||
) {
|
||||
return function (items: BaseItemDto[]) {
|
||||
@@ -73,7 +80,7 @@ export function loadResume(
|
||||
elem: HTMLElement,
|
||||
apiClient: ApiClient,
|
||||
titleLabel: string,
|
||||
mediaType: BaseItemKind,
|
||||
mediaType: MediaType,
|
||||
userSettings: UserSettings,
|
||||
options: SectionOptions
|
||||
) {
|
||||
@@ -99,7 +106,7 @@ export function loadResume(
|
||||
|
||||
const itemsContainer: SectionContainerElement | null = elem.querySelector('.itemsContainer');
|
||||
if (!itemsContainer) return;
|
||||
itemsContainer.fetchData = getItemsToResumeFn(mediaType, apiClient.serverId(), options);
|
||||
itemsContainer.fetchData = getItemsToResumeFn(apiClient, mediaType, options);
|
||||
itemsContainer.getItemsHtml = getItemsToResumeHtmlFn(userSettings.useEpisodeImagesInNextUpAndResume(), mediaType, options);
|
||||
itemsContainer.parentContainer = elem;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/** Converts a Date object to an ISO date string (YYYY-MM-DD). */
|
||||
export const toIsoDateOnlyString = (date: Date) => {
|
||||
return date.toISOString().split('T')[0];
|
||||
};
|
||||
Reference in New Issue
Block a user