diff --git a/src/components/VideoList/VideoList.tsx b/src/components/VideoList/VideoList.tsx
index c7b00ef6f..9929f451a 100644
--- a/src/components/VideoList/VideoList.tsx
+++ b/src/components/VideoList/VideoList.tsx
@@ -28,6 +28,9 @@ type Props = {
loadMore?: () => void;
};
+// eslint-disable-next-line @typescript-eslint/no-empty-function
+const defaultLoadMore = () => {};
+
function VideoList({
playlist,
header,
@@ -42,46 +45,26 @@ function VideoList({
isLoggedIn,
hasSubscription,
hasLoadMore,
- loadMore,
+ loadMore = defaultLoadMore,
}: Props) {
return (
{!!header && header}
- {loadMore ? (
- }>
- <>
- {playlist?.playlist?.map((playlistItem: PlaylistItem) => (
- onListItemClick && onListItemClick(playlistItem, playlistItem.feedid)}
- onHover={() => onListItemHover && onListItemHover(playlistItem)}
- loading={isLoading}
- isActive={activeMediaId === playlistItem.mediaid}
- activeLabel={activeLabel}
- isLocked={isLocked(accessModel, isLoggedIn, hasSubscription, playlistItem)}
- item={playlistItem}
- />
- ))}
- >
-
- ) : (
- <>
- {playlist?.playlist?.map((playlistItem: PlaylistItem) => (
- onListItemClick && onListItemClick(playlistItem, playlistItem.feedid)}
- onHover={() => onListItemHover && onListItemHover(playlistItem)}
- loading={isLoading}
- isActive={activeMediaId === playlistItem.mediaid}
- activeLabel={activeLabel}
- isLocked={isLocked(accessModel, isLoggedIn, hasSubscription, playlistItem)}
- item={playlistItem}
- />
- ))}
- >
- )}
+ }>
+ {playlist?.playlist?.map((playlistItem: PlaylistItem) => (
+ onListItemClick && onListItemClick(playlistItem, playlistItem.feedid)}
+ onHover={() => onListItemHover && onListItemHover(playlistItem)}
+ loading={isLoading}
+ isActive={activeMediaId === playlistItem.mediaid}
+ activeLabel={activeLabel}
+ isLocked={isLocked(accessModel, isLoggedIn, hasSubscription, playlistItem)}
+ item={playlistItem}
+ />
+ ))}
+
);
}
diff --git a/src/containers/AppRoutes/AppRoutes.tsx b/src/containers/AppRoutes/AppRoutes.tsx
index d0ef76fcb..abb580b1b 100644
--- a/src/containers/AppRoutes/AppRoutes.tsx
+++ b/src/containers/AppRoutes/AppRoutes.tsx
@@ -8,7 +8,7 @@ import About from '#src/pages/About/About';
import Home from '#src/pages/Home/Home';
import Search from '#src/pages/Search/Search';
import User from '#src/pages/User/User';
-import DeprecatedSeries from '#src/pages/DeprecatedSeries/DeprecatedSeries';
+import LegacySeries from '#src/pages/LegacySeries/LegacySeries';
import MediaScreenRouter from '#src/pages/ScreenRouting/MediaScreenRouter';
import PlaylistScreenRouter from '#src/pages/ScreenRouting/PlaylistScreenRouter';
import Layout from '#src/containers/Layout/Layout';
@@ -22,7 +22,7 @@ export default function AppRoutes() {
} />
} />
} />
- } />
+ } />
} />
} />
} />
diff --git a/src/hooks/series/useNextEpisode.ts b/src/hooks/series/useNextEpisode.ts
index f7468a2ae..1e58c310b 100644
--- a/src/hooks/series/useNextEpisode.ts
+++ b/src/hooks/series/useNextEpisode.ts
@@ -1,28 +1,18 @@
import { useEffect, useState } from 'react';
-import type { Playlist, PlaylistItem } from '#types/playlist';
+import type { PlaylistItem } from '#types/playlist';
import type { EpisodeMetadata, Series } from '#types/series';
import { getNextItem } from '#src/utils/series';
-export const useNextEpisode = ({
- episode,
- seriesPlaylist,
- series,
- episodeMetadata,
-}: {
- episode: PlaylistItem | undefined;
- seriesPlaylist: Playlist;
- series: Series | undefined;
- episodeMetadata: EpisodeMetadata | undefined;
-}) => {
+export const useNextEpisode = ({ series, episodeMetadata }: { series: Series | undefined; episodeMetadata: EpisodeMetadata | undefined }) => {
const [nextItem, setNextItem] = useState(undefined);
useEffect(() => {
async function fetchData() {
- const item = await getNextItem(episode, seriesPlaylist, series, episodeMetadata);
+ const item = await getNextItem(series, episodeMetadata);
setNextItem(item);
}
fetchData();
- }, [episode, seriesPlaylist, series, episodeMetadata]);
+ }, [series, episodeMetadata]);
return nextItem;
};
diff --git a/src/hooks/series/useSeriesId.ts b/src/hooks/series/useSeriesId.ts
index 382d21a84..3fd079711 100644
--- a/src/hooks/series/useSeriesId.ts
+++ b/src/hooks/series/useSeriesId.ts
@@ -2,10 +2,10 @@ import { useQuery } from 'react-query';
import type { PlaylistItem } from '#types/playlist';
import { getSeriesByMediaIds } from '#src/services/api.service';
-import { getSeriesIdFromEpisode } from '#src/utils/media';
+import { getLegacySeriesPlaylistIdFromEpisodeTags } from '#src/utils/media';
const useGetSeriesId = (item: PlaylistItem) => {
- const staticSeriesId = getSeriesIdFromEpisode(item);
+ const staticSeriesId = getLegacySeriesPlaylistIdFromEpisodeTags(item);
const { isLoading, data } = useQuery(['seriesId', item.mediaid], async () => {
// get all series for the given media id
diff --git a/src/pages/DeprecatedSeries/DeprecatedSeries.tsx b/src/pages/LegacySeries/LegacySeries.tsx
similarity index 98%
rename from src/pages/DeprecatedSeries/DeprecatedSeries.tsx
rename to src/pages/LegacySeries/LegacySeries.tsx
index 28077723d..9b244bfcc 100644
--- a/src/pages/DeprecatedSeries/DeprecatedSeries.tsx
+++ b/src/pages/LegacySeries/LegacySeries.tsx
@@ -4,9 +4,8 @@ import { Helmet } from 'react-helmet';
import { useTranslation } from 'react-i18next';
import shallow from 'zustand/shallow';
-import { filterSeries, getEpisodesInSeason, getFiltersFromSeries, getNextItem } from './utils';
+import { filterSeries, getEpisodesInSeason, getFiltersFromSeries, getNextItem, generateLegacyEpisodeJSONLD } from './utils';
-import { generateLegacyEpisodeJSONLD } from '#src/utils/structuredData';
import VideoLayout from '#components/VideoLayout/VideoLayout';
import InlinePlayer from '#src/containers/InlinePlayer/InlinePlayer';
import { isLocked } from '#src/utils/entitlements';
@@ -30,7 +29,7 @@ import useQueryParam from '#src/hooks/useQueryParam';
import Loading from '#src/pages/Loading/Loading';
import usePlaylist from '#src/hooks/usePlaylist';
-const DeprecatedSeries = () => {
+const LegacySeries = () => {
const breakpoint = useBreakpoint();
const { t } = useTranslation('video');
const [playTrailer, setPlayTrailer] = useState(false);
@@ -229,4 +228,4 @@ const DeprecatedSeries = () => {
);
};
-export default DeprecatedSeries;
+export default LegacySeries;
diff --git a/src/pages/DeprecatedSeries/utils.ts b/src/pages/LegacySeries/utils.ts
similarity index 52%
rename from src/pages/DeprecatedSeries/utils.ts
rename to src/pages/LegacySeries/utils.ts
index d0d106889..6d10c029a 100644
--- a/src/pages/DeprecatedSeries/utils.ts
+++ b/src/pages/LegacySeries/utils.ts
@@ -1,4 +1,7 @@
+import { deprecatedSeriesURL } from '#src/utils/formatting';
+import { secondsToISO8601 } from '#src/utils/datetime';
import type { Playlist, PlaylistItem } from '#types/playlist';
+import type { EpisodeMetadata } from '#types/series';
/**
* Get an array of options for a season filter
@@ -42,3 +45,45 @@ export const getEpisodesInSeason = (episode: PlaylistItem | undefined, seriesPla
return seriesPlaylist.playlist.filter((i) => i.seasonNumber === episode?.seasonNumber)?.length;
};
+
+export const generateLegacySeriesMetadata = (seriesPlaylist: Playlist, seriesId: string | undefined) => {
+ // Use playlist for old flow and media id for a new flow
+ const seriesCanonical = `${window.location.origin}/s/${seriesId}`;
+
+ return {
+ '@type': 'TVSeries',
+ '@id': seriesCanonical,
+ name: seriesPlaylist.title,
+ numberOfEpisodes: String(seriesPlaylist.playlist.length),
+ numberOfSeasons: String(
+ seriesPlaylist.playlist.reduce(function (list, playlistItem) {
+ return !playlistItem.seasonNumber || list.includes(playlistItem.seasonNumber) ? list : list.concat(playlistItem.seasonNumber);
+ }, [] as string[]).length,
+ ),
+ };
+};
+
+export const generateLegacyEpisodeJSONLD = (
+ seriesPlaylist: Playlist,
+ episode: PlaylistItem | undefined,
+ episodeMetadata: EpisodeMetadata | undefined,
+ seriesId: string,
+) => {
+ const episodeCanonical = `${window.location.origin}${deprecatedSeriesURL({ episodeId: episode?.mediaid, seriesId })}`;
+ const seriesMetadata = generateLegacySeriesMetadata(seriesPlaylist, seriesId);
+
+ if (!episode) {
+ return JSON.stringify(seriesMetadata);
+ }
+
+ return JSON.stringify({
+ '@context': 'http://schema.org/',
+ '@type': 'TVEpisode',
+ '@id': episodeCanonical,
+ episodeNumber: episodeMetadata?.episodeNumber,
+ seasonNumber: episodeMetadata?.seasonNumber,
+ name: episode.title,
+ uploadDate: secondsToISO8601(episode.pubdate),
+ partOfSeries: seriesMetadata,
+ });
+};
diff --git a/src/pages/ScreenRouting/MediaScreenRouter.tsx b/src/pages/ScreenRouting/MediaScreenRouter.tsx
index 4a664f8d6..cc8c6c4a3 100644
--- a/src/pages/ScreenRouting/MediaScreenRouter.tsx
+++ b/src/pages/ScreenRouting/MediaScreenRouter.tsx
@@ -8,7 +8,7 @@ import useMedia from '#src/hooks/useMedia';
import Loading from '#src/pages/Loading/Loading';
import ErrorPage from '#components/ErrorPage/ErrorPage';
import type { PlaylistItem } from '#types/playlist';
-import { isEpisode, isDeprecatedSeriesFlow } from '#src/utils/media';
+import { isEpisode, isLegacySeriesFlow } from '#src/utils/media';
import MediaMovie from '#src/pages/ScreenRouting/mediaScreens/MediaMovie/MediaMovie';
import MediaSeries from '#src/pages/ScreenRouting/mediaScreens/MediaSeries/MediaSeries';
import MediaLiveChannel from '#src/pages/ScreenRouting/mediaScreens/MediaLiveChannel/MediaLiveChannel';
@@ -27,7 +27,7 @@ mediaScreenMap.registerDefault(MediaMovie);
// Register legacy series and episode screens when `contentType` is missing
mediaScreenMap.register(MediaEpisode, (item) => !!item && isEpisode(item));
-mediaScreenMap.register(MediaSeries, (item) => !!item && isDeprecatedSeriesFlow(item));
+mediaScreenMap.register(MediaSeries, (item) => !!item && isLegacySeriesFlow(item));
const MediaScreenRouter = () => {
const params = useParams();
diff --git a/src/pages/ScreenRouting/mediaScreens/MediaSeries/MediaSeries.tsx b/src/pages/ScreenRouting/mediaScreens/MediaSeries/MediaSeries.tsx
index b76bb0ebd..ffaf2c145 100644
--- a/src/pages/ScreenRouting/mediaScreens/MediaSeries/MediaSeries.tsx
+++ b/src/pages/ScreenRouting/mediaScreens/MediaSeries/MediaSeries.tsx
@@ -5,13 +5,12 @@ import { useTranslation } from 'react-i18next';
import shallow from 'zustand/shallow';
import { useSearchParams } from 'react-router-dom';
-import { filterSeries, getEpisodesInSeason, getFiltersFromSeries } from './utils';
-
import { generateEpisodeJSONLD } from '#src/utils/structuredData';
import VideoLayout from '#components/VideoLayout/VideoLayout';
import InlinePlayer from '#src/containers/InlinePlayer/InlinePlayer';
import { isLocked } from '#src/utils/entitlements';
import useEntitlement from '#src/hooks/useEntitlement';
+import { getEpisodesInSeason, getFiltersFromSeries } from '#src/utils/series';
import { deprecatedSeriesURL, formatSeriesMetaString, formatVideoMetaString, mediaURL } from '#src/utils/formatting';
import useMedia from '#src/hooks/useMedia';
import { useSeriesData } from '#src/hooks/series/useSeriesData';
@@ -77,9 +76,9 @@ const MediaSeriesContent: ScreenComponent = ({ data: seriesMedia }
} = useEpisodes(seriesId, seasonFilter, { enabled: seasonFilter !== undefined && !!series });
const firstEpisode = useMemo(() => episodes?.[0]?.episodes?.[0], [episodes]);
- const filteredPlaylist = useMemo(() => filterSeries(seriesPlaylist, episodes), [seriesPlaylist, episodes]);
+ const playlist = useMemo(() => ({ ...seriesPlaylist, playlist: episodes?.flatMap((e) => e.episodes) || [] }), [seriesPlaylist, episodes]);
const episodesInSeason = getEpisodesInSeason(episodeMetadata, series);
- const nextItem = useNextEpisode({ episode, seriesPlaylist, series, episodeMetadata });
+ const nextItem = useNextEpisode({ series, episodeMetadata });
// Watch history
const watchHistoryArray = useWatchHistoryStore((state) => state.watchHistory);
@@ -226,7 +225,7 @@ const MediaSeriesContent: ScreenComponent = ({ data: seriesMedia }
accessModel={accessModel}
isLoggedIn={isLoggedIn}
hasSubscription={hasSubscription}
- playlist={filteredPlaylist}
+ playlist={playlist}
relatedTitle={inlineLayout ? seriesPlaylist.title : t('episodes')}
onItemClick={onCardClick}
setFilter={setSeasonFilter}
diff --git a/src/pages/ScreenRouting/mediaScreens/MediaSeries/utils.ts b/src/pages/ScreenRouting/mediaScreens/MediaSeries/utils.ts
deleted file mode 100644
index 2d6cd439d..000000000
--- a/src/pages/ScreenRouting/mediaScreens/MediaSeries/utils.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-import type { Playlist, PlaylistItem } from '#types/playlist';
-import type { EpisodeMetadata, EpisodesWithPagination, Series } from '#types/series';
-import { getEpisodes, getSeasonWithEpisodes } from '#src/services/api.service';
-import { mediaURL } from '#src/utils/formatting';
-import { secondsToISO8601 } from '#src/utils/datetime';
-
-/**
- * Get an array of options for a season filter
- */
-export const getFiltersFromSeries = (series: Series | undefined): string[] => {
- return series && 'seasons' in series ? series.seasons.map((season) => String(season.season_number)) : [];
-};
-
-/**
- * Get a playlist with episodes based on the selected filter
- */
-export const filterSeries = (playlist: Playlist, episodes: EpisodesWithPagination[] | undefined): Playlist => {
- // Get a flattened list of episodes and return it as part of the playlist
- return { ...playlist, playlist: episodes?.flatMap((e) => e.episodes) || [] };
-};
-
-/**
- * Retrieve a first episode of the next season
- */
-const getNextSeasonEpisode = async (seasonNumber: number, series: Series | undefined) => {
- const seasons = series?.seasons;
-
- // The seasons is the last one in case there is only one season available or it is the same as the last season in the seasons array
- const isLastSeason = seasons?.length === 1 || seasons?.[seasons?.length - 1]?.season_number === seasonNumber;
-
- if (isLastSeason) {
- return;
- } else {
- // Need to know the order of seasons to choose the next season number
- const hasAscendingOrder = (Number(seasons?.[1]?.season_number) || 0) > (Number(seasons?.[0]?.season_number) || 0);
- const nextSeasonNumber = hasAscendingOrder ? seasonNumber + 1 : seasonNumber - 1;
-
- return (await getSeasonWithEpisodes(series?.series_id, nextSeasonNumber, 0, 1))?.episodes?.[0];
- }
-};
-
-/**
- * Get a next episode of the selected season / episodes list
- */
-const getNextEpisode = async (seasonNumber: number, seriesId: string, pageWithEpisode: number) => {
- if (seasonNumber) {
- return (await getSeasonWithEpisodes(seriesId, seasonNumber, pageWithEpisode, 1))?.episodes?.[0];
- } else {
- return (await getEpisodes(seriesId, pageWithEpisode, 1))?.episodes?.[0];
- }
-};
-
-const getNewFlowNextEpisode = async (series: Series | undefined, episodeMetadata: EpisodeMetadata | undefined) => {
- if (!episodeMetadata || !series) {
- return;
- }
-
- const seasonNumber = Number(episodeMetadata.seasonNumber);
- const episodeNumber = Number(episodeMetadata.episodeNumber);
-
- // Get initial data to collect information about total number of elements
- const { episodes, pagination } =
- seasonNumber !== 0 ? await getSeasonWithEpisodes(series?.series_id, seasonNumber, 0) : await getEpisodes(series?.series_id, 0);
-
- if (episodes.length === 1 && seasonNumber) {
- return getNextSeasonEpisode(seasonNumber, series);
- }
-
- // Both episodes and seasons can be sorted by asc / desc
- const hasAscendingOrder = (Number(episodes[1].episodeNumber) || 0) > (Number(episodes[0].episodeNumber) || 0);
- const nextEpisodeNumber = hasAscendingOrder ? episodeNumber + 1 : episodeNumber - 1;
- // First page has 0 number, that is why we use Math.floor here und subtract 1
- const pageWithEpisode = Math.floor(hasAscendingOrder ? nextEpisodeNumber - 1 : pagination.total - nextEpisodeNumber - 1);
- // Consider the case when we have a next episode in the retrieved list
- const nextElementIndex = episodes.findIndex((el) => Number(el.episodeNumber) === nextEpisodeNumber);
-
- if (nextElementIndex !== -1) {
- return episodes[nextElementIndex];
- }
-
- // Fetch the next episodes of the season when there is more to fetch
- if (pageWithEpisode < pagination.total) {
- return getNextEpisode(seasonNumber, series?.series_id, pageWithEpisode);
- // Switch selected season in case the current one has nor more episodes inside
- } else if (seasonNumber) {
- return getNextSeasonEpisode(seasonNumber, series);
- }
-};
-
-export const getNextItem = async (
- episode: PlaylistItem | undefined,
- series: Series | undefined,
- episodeMetadata: EpisodeMetadata | undefined,
-): Promise => {
- if (!episode) return;
-
- const nextEpisode = await getNewFlowNextEpisode(series, episodeMetadata);
-
- return nextEpisode;
-};
-
-/** Get a total amount of episodes in a season */
-export const getEpisodesInSeason = (episodeMetadata: EpisodeMetadata | undefined, series: Series | undefined) => {
- return (series?.seasons || []).find((el) => el.season_number === Number(episodeMetadata?.seasonNumber))?.episode_count;
-};
-
-export const generateNewSeriesMetadata = (series: Series, media: PlaylistItem, seriesId: string | undefined) => {
- // Use playlist for old flow and media id for a new flow
- const seriesCanonical = `${window.location.origin}/m/${seriesId}`;
-
- return {
- '@type': 'TVSeries',
- '@id': seriesCanonical,
- name: media.title,
- numberOfEpisodes: String(series?.episode_count),
- numberOfSeasons: String(series?.season_count || 0),
- };
-};
-
-export const generateNewEpisodeJSONLD = (
- series: Series,
- media: PlaylistItem,
- episode: PlaylistItem | undefined,
- episodeMetadata: EpisodeMetadata | undefined,
- seriesId: string,
-) => {
- const episodeCanonical = `${window.location.origin}${mediaURL({ media, episodeId: episode?.mediaid })}`;
- const seriesMetadata = generateNewSeriesMetadata(series, media, seriesId);
-
- if (!episode) {
- return JSON.stringify(seriesMetadata);
- }
-
- return JSON.stringify({
- '@context': 'http://schema.org/',
- '@type': 'TVEpisode',
- '@id': episodeCanonical,
- episodeNumber: episodeMetadata?.episodeNumber,
- seasonNumber: episodeMetadata?.seasonNumber,
- name: episode.title,
- uploadDate: secondsToISO8601(episode.pubdate),
- partOfSeries: seriesMetadata,
- });
-};
diff --git a/src/utils/media.ts b/src/utils/media.ts
index be9627bdb..a4943dd90 100644
--- a/src/utils/media.ts
+++ b/src/utils/media.ts
@@ -16,21 +16,21 @@ export const getSeriesPlaylistIdFromCustomParams = (item: (PlaylistItem & Deprec
item ? item.seriesPlayListId || item.seriesPlaylistId || item.seriesId : undefined;
// For the deprecated flow we store seriesId in the media custom params
-export const isDeprecatedSeriesFlow = (item: PlaylistItem) => {
+export const isLegacySeriesFlow = (item: PlaylistItem) => {
return typeof getSeriesPlaylistIdFromCustomParams(item) !== 'undefined';
};
// For the new series flow we use contentType custom param to define media item to be series
// In this case media item and series item have the same id
-export const isNewSeriesFlow = (item: PlaylistItem) => item.contentType === CONTENT_TYPE.series;
+export const isSeriesContentType = (item: PlaylistItem) => item.contentType === CONTENT_TYPE.series;
-export const isSeries = (item: PlaylistItem) => isDeprecatedSeriesFlow(item) || isNewSeriesFlow(item);
+export const isSeries = (item: PlaylistItem) => isLegacySeriesFlow(item) || isSeriesContentType(item);
export const isEpisode = (item: PlaylistItem) => {
return typeof item?.episodeNumber !== 'undefined' || item?.contentType === CONTENT_TYPE.episode;
};
-export const getSeriesIdFromEpisode = (item: PlaylistItem | undefined) => {
+export const getLegacySeriesPlaylistIdFromEpisodeTags = (item: PlaylistItem | undefined) => {
if (!item || !isEpisode(item)) {
return;
}
@@ -44,10 +44,6 @@ export const getSeriesIdFromEpisode = (item: PlaylistItem | undefined) => {
return seriesIdTag.split('_')[1];
}
- if (item.seriesId) {
- return item.seriesId;
- }
-
return;
};
diff --git a/src/utils/series.ts b/src/utils/series.ts
index 13c44c4de..c917c122b 100644
--- a/src/utils/series.ts
+++ b/src/utils/series.ts
@@ -1,44 +1,11 @@
-import type { Playlist, PlaylistItem } from '#types/playlist';
-import type { EpisodeMetadata, EpisodesWithPagination, Series } from '#types/series';
+import type { EpisodeMetadata, Series } from '#types/series';
import { getEpisodes, getSeasonWithEpisodes } from '#src/services/api.service';
/**
* Get an array of options for a season filter
*/
-export const getFiltersFromSeries = (playlist: Playlist, series: Series | undefined): string[] => {
- const isNewFlow = !!series;
-
- // For the new series flow we already have episodes sorted correctly on the back-end side
- if (isNewFlow) {
- return 'seasons' in series ? series.seasons.map((season) => String(season.season_number)) : [];
- }
-
- // Old series doesn't have sorting supported and just aggregates all episodes in one playlist
- // So we need to sort the playlist manually based on the selected filter (season).
- return playlist.playlist
- .reduce((filters: string[], item) => (item.seasonNumber && filters.includes(item.seasonNumber) ? filters : filters.concat(item.seasonNumber || '')), [])
- .slice()
- .sort();
-};
-
-/**
- * Get a playlist with episodes based on the selected filter
- */
-export const filterSeries = (playlist: Playlist, episodes: EpisodesWithPagination[] | undefined, filter: string | undefined): Playlist => {
- const isNewFlow = !!episodes?.length;
-
- if (isNewFlow) {
- // Get a flattened list of episodes and return it as part of the playlist
- return { ...playlist, playlist: episodes.flatMap((e) => e.episodes) };
- }
-
- if (filter === '') return playlist;
-
- return {
- ...playlist,
- // Filter episodes manually for the old flow where our playlists includes all episodes with all seasons
- playlist: playlist.playlist.filter(({ seasonNumber }) => seasonNumber === filter),
- };
+export const getFiltersFromSeries = (series: Series | undefined): string[] => {
+ return series && 'seasons' in series ? series.seasons.map((season) => String(season.season_number)) : [];
};
/**
@@ -72,7 +39,7 @@ const getNextEpisode = async (seasonNumber: number, seriesId: string, pageWithEp
}
};
-const getNewFlowNextEpisode = async (series: Series | undefined, episodeMetadata: EpisodeMetadata | undefined) => {
+export const getNextItem = async (series: Series | undefined, episodeMetadata: EpisodeMetadata | undefined) => {
if (!episodeMetadata || !series) {
return;
}
@@ -109,49 +76,7 @@ const getNewFlowNextEpisode = async (series: Series | undefined, episodeMetadata
}
};
-export const getNextItem = async (
- episode: PlaylistItem | undefined,
- seriesPlaylist: Playlist,
- series: Series | undefined,
- episodeMetadata: EpisodeMetadata | undefined,
-): Promise => {
- const isNewFlow = !!series;
-
- if (!episode || !seriesPlaylist) return;
-
- // Using new flow when episodes are available
- if (isNewFlow) {
- const nextEpisode = await getNewFlowNextEpisode(series, episodeMetadata);
-
- return nextEpisode;
- }
-
- // For the old flow we already have all the episodes and seasons so we just need to find them in the array
- const index = seriesPlaylist?.playlist?.findIndex(({ mediaid }) => mediaid === episode.mediaid);
-
- return seriesPlaylist?.playlist?.[index + 1];
-};
-
/** Get a total amount of episodes in a season */
-export const getEpisodesInSeason = (
- episode: PlaylistItem | undefined,
- episodeMetadata: EpisodeMetadata | undefined,
- seriesPlaylist: Playlist,
- series: Series | undefined,
-) => {
- const isNewFlow = !!series;
-
- if (isNewFlow) {
- return (series?.seasons || []).find((el) => el.season_number === Number(episodeMetadata?.seasonNumber))?.episode_count;
- }
-
- return seriesPlaylist.playlist.filter((i) => i.seasonNumber === episode?.seasonNumber)?.length;
-};
-
-export const getFirstEpisode = (seriesPlaylist: Playlist, episodesData: EpisodesWithPagination[] | undefined) => {
- if (episodesData) {
- return episodesData?.[0]?.episodes?.[0];
- }
-
- return seriesPlaylist?.playlist?.[0];
+export const getEpisodesInSeason = (episodeMetadata: EpisodeMetadata | undefined, series: Series | undefined) => {
+ return (series?.seasons || []).find((el) => el.season_number === Number(episodeMetadata?.seasonNumber))?.episode_count;
};
diff --git a/src/utils/structuredData.ts b/src/utils/structuredData.ts
index 68f7c9c53..08340adce 100644
--- a/src/utils/structuredData.ts
+++ b/src/utils/structuredData.ts
@@ -1,7 +1,7 @@
-import { deprecatedSeriesURL, mediaURL } from './formatting';
+import { mediaURL } from './formatting';
import { secondsToISO8601 } from './datetime';
-import type { Playlist, PlaylistItem } from '#types/playlist';
+import type { PlaylistItem } from '#types/playlist';
import type { EpisodeMetadata, Series } from '#types/series';
export const generateMovieJSONLD = (item: PlaylistItem) => {
@@ -19,48 +19,6 @@ export const generateMovieJSONLD = (item: PlaylistItem) => {
});
};
-export const generateLegacySeriesMetadata = (seriesPlaylist: Playlist, seriesId: string | undefined) => {
- // Use playlist for old flow and media id for a new flow
- const seriesCanonical = `${window.location.origin}/s/${seriesId}`;
-
- return {
- '@type': 'TVSeries',
- '@id': seriesCanonical,
- name: seriesPlaylist.title,
- numberOfEpisodes: String(seriesPlaylist.playlist.length),
- numberOfSeasons: String(
- seriesPlaylist.playlist.reduce(function (list, playlistItem) {
- return !playlistItem.seasonNumber || list.includes(playlistItem.seasonNumber) ? list : list.concat(playlistItem.seasonNumber);
- }, [] as string[]).length,
- ),
- };
-};
-
-export const generateLegacyEpisodeJSONLD = (
- seriesPlaylist: Playlist,
- episode: PlaylistItem | undefined,
- episodeMetadata: EpisodeMetadata | undefined,
- seriesId: string,
-) => {
- const episodeCanonical = `${window.location.origin}${deprecatedSeriesURL({ episodeId: episode?.mediaid, seriesId })}`;
- const seriesMetadata = generateLegacySeriesMetadata(seriesPlaylist, seriesId);
-
- if (!episode) {
- return JSON.stringify(seriesMetadata);
- }
-
- return JSON.stringify({
- '@context': 'http://schema.org/',
- '@type': 'TVEpisode',
- '@id': episodeCanonical,
- episodeNumber: episodeMetadata?.episodeNumber,
- seasonNumber: episodeMetadata?.seasonNumber,
- name: episode.title,
- uploadDate: secondsToISO8601(episode.pubdate),
- partOfSeries: seriesMetadata,
- });
-};
-
export const generateSeriesMetadata = (series: Series, media: PlaylistItem, seriesId: string | undefined) => {
// Use playlist for old flow and media id for a new flow
const seriesCanonical = `${window.location.origin}/m/${seriesId}`;