mirror of
https://github.com/Viren070/tmdb-addon.git
synced 2025-12-01 23:18:11 +01:00
feat(config): add 'hideInCinemaTag' and improve cast count logic
- Added support to remove 'imdb_id' from meta response when 'hideInCinemaTag' is enabled. #111 - Updated parseCast to return all cast members when count is undefined, supporting the 'Unlimited' option in configuration.
This commit is contained in:
+15
-7
@@ -51,7 +51,7 @@ const fetchMovieData = async (tmdbId, language) => {
|
||||
});
|
||||
};
|
||||
|
||||
const buildMovieResponse = async (res, type, language, tmdbId, rpdbkey) => {
|
||||
const buildMovieResponse = async (res, type, language, tmdbId, rpdbkey, config = {}) => {
|
||||
const [poster, logo, imdbRatingRaw] = await Promise.all([
|
||||
Utils.parsePoster(type, tmdbId, res.poster_path, language, rpdbkey),
|
||||
getLogo(tmdbId, language, res.original_language).catch(e => {
|
||||
@@ -62,8 +62,10 @@ const buildMovieResponse = async (res, type, language, tmdbId, rpdbkey) => {
|
||||
]);
|
||||
|
||||
const imdbRating = imdbRatingRaw || res.vote_average?.toFixed(1) || "N/A";
|
||||
const castCount = config.castCount !== undefined ? Math.max(1, Math.min(5, Number(config.castCount))) : 5;
|
||||
const hideInCinemaTag = config.hideInCinemaTag === true || config.hideInCinemaTag === "true";
|
||||
|
||||
return {
|
||||
const response = {
|
||||
imdb_id: res.imdb_id,
|
||||
country: Utils.parseCoutry(res.production_countries),
|
||||
description: res.overview,
|
||||
@@ -91,9 +93,11 @@ const buildMovieResponse = async (res, type, language, tmdbId, rpdbkey) => {
|
||||
},
|
||||
logo: processLogo(logo),
|
||||
app_extras: {
|
||||
cast: Utils.parseCast(res.credits)
|
||||
cast: Utils.parseCast(res.credits, castCount)
|
||||
}
|
||||
};
|
||||
if (hideInCinemaTag) delete response.imdb_id;
|
||||
return response;
|
||||
};
|
||||
|
||||
// TV show specific functions
|
||||
@@ -105,7 +109,7 @@ const fetchTvData = async (tmdbId, language) => {
|
||||
});
|
||||
};
|
||||
|
||||
const buildTvResponse = async (res, type, language, tmdbId, rpdbkey, config) => {
|
||||
const buildTvResponse = async (res, type, language, tmdbId, rpdbkey, config = {}) => {
|
||||
const runtime = res.episode_run_time?.[0] ?? res.last_episode_to_air?.runtime ?? res.next_episode_to_air?.runtime ?? null;
|
||||
|
||||
const [poster, logo, imdbRatingRaw, episodes] = await Promise.all([
|
||||
@@ -124,8 +128,10 @@ const buildTvResponse = async (res, type, language, tmdbId, rpdbkey, config) =>
|
||||
]);
|
||||
|
||||
const imdbRating = imdbRatingRaw || res.vote_average?.toFixed(1) || "N/A";
|
||||
const castCount = config.castCount !== undefined ? Math.max(1, Math.min(5, Number(config.castCount))) : 5;
|
||||
const hideInCinemaTag = config.hideInCinemaTag === true || config.hideInCinemaTag === "true";
|
||||
|
||||
return {
|
||||
const response = {
|
||||
country: Utils.parseCoutry(res.production_countries),
|
||||
description: res.overview,
|
||||
genre: Utils.parseGenres(res.genres),
|
||||
@@ -154,9 +160,11 @@ const buildTvResponse = async (res, type, language, tmdbId, rpdbkey, config) =>
|
||||
},
|
||||
logo: processLogo(logo),
|
||||
app_extras: {
|
||||
cast: Utils.parseCast(res.credits)
|
||||
cast: Utils.parseCast(res.credits, castCount)
|
||||
}
|
||||
};
|
||||
if (hideInCinemaTag) delete response.imdb_id;
|
||||
return response;
|
||||
};
|
||||
|
||||
// Main function
|
||||
@@ -170,7 +178,7 @@ async function getMeta(type, language, tmdbId, rpdbkey, config = {}) {
|
||||
|
||||
try {
|
||||
const meta = await (type === "movie" ?
|
||||
fetchMovieData(tmdbId, language).then(res => buildMovieResponse(res, type, language, tmdbId, rpdbkey)) :
|
||||
fetchMovieData(tmdbId, language).then(res => buildMovieResponse(res, type, language, tmdbId, rpdbkey, config)) :
|
||||
fetchTvData(tmdbId, language).then(res => buildTvResponse(res, type, language, tmdbId, rpdbkey, config))
|
||||
);
|
||||
|
||||
|
||||
@@ -6,8 +6,18 @@ function parseCertification(release_dates, language) {
|
||||
)[0].release_dates[0].certification;
|
||||
}
|
||||
|
||||
function parseCast(credits) {
|
||||
return credits.cast.slice(0, 5).map((el) => {
|
||||
function parseCast(credits, count) {
|
||||
console.log(count)
|
||||
if (count === undefined || count === null) {
|
||||
return credits.cast.map((el) => {
|
||||
return {
|
||||
name: el.name,
|
||||
character: el.character,
|
||||
photo: el.profile_path ? `https://image.tmdb.org/t/p/w276_and_h350_face${el.profile_path}` : null
|
||||
};
|
||||
});
|
||||
}
|
||||
return credits.cast.slice(0, count).map((el) => {
|
||||
return {
|
||||
name: el.name,
|
||||
character: el.character,
|
||||
|
||||
@@ -26,6 +26,8 @@ export function ConfigProvider({ children }: { children: React.ReactNode }) {
|
||||
const [catalogs, setCatalogs] = useState<CatalogConfig[]>([]);
|
||||
const [ageRating, setAgeRating] = useState<string | undefined>(undefined);
|
||||
const [searchEnabled, setSearchEnabled] = useState<boolean>(true);
|
||||
const [hideInCinemaTag, setHideInCinemaTag] = useState(false);
|
||||
const [castCount, setCastCount] = useState<number | undefined>(5);
|
||||
|
||||
const loadDefaultCatalogs = () => {
|
||||
const defaultCatalogs = baseCatalogs.map(catalog => ({
|
||||
@@ -52,6 +54,8 @@ export function ConfigProvider({ children }: { children: React.ReactNode }) {
|
||||
if (config.ageRating) setAgeRating(config.ageRating);
|
||||
if (config.includeAdult) setIncludeAdult(config.includeAdult === "true");
|
||||
if (config.language) setLanguage(config.language);
|
||||
if (config.hideInCinemaTag) setHideInCinemaTag(config.hideInCinemaTag === "true" || config.hideInCinemaTag === true);
|
||||
if (config.castCount !== undefined) setCastCount(config.castCount === "Unlimited" ? undefined : Number(config.castCount));
|
||||
|
||||
if (config.catalogs) {
|
||||
const catalogsWithNames = config.catalogs.map(catalog => {
|
||||
@@ -109,6 +113,8 @@ export function ConfigProvider({ children }: { children: React.ReactNode }) {
|
||||
catalogs,
|
||||
ageRating,
|
||||
searchEnabled,
|
||||
hideInCinemaTag,
|
||||
castCount,
|
||||
setRpdbkey,
|
||||
setGeminiKey,
|
||||
setMdblistkey,
|
||||
@@ -122,6 +128,8 @@ export function ConfigProvider({ children }: { children: React.ReactNode }) {
|
||||
setCatalogs,
|
||||
setAgeRating,
|
||||
setSearchEnabled,
|
||||
setHideInCinemaTag,
|
||||
setCastCount,
|
||||
loadConfigFromUrl
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ export type ConfigContextType = {
|
||||
catalogs: CatalogConfig[];
|
||||
ageRating: string | undefined;
|
||||
searchEnabled: boolean;
|
||||
hideInCinemaTag: boolean;
|
||||
castCount: number | undefined;
|
||||
setRpdbkey: (rpdbkey: string) => void;
|
||||
setGeminiKey: (geminikey: string) => void;
|
||||
setMdblistkey: (mdblistkey: string) => void;
|
||||
@@ -35,6 +37,8 @@ export type ConfigContextType = {
|
||||
setCatalogs: (catalogs: CatalogConfig[] | ((prev: CatalogConfig[]) => CatalogConfig[])) => void;
|
||||
setAgeRating: (ageRating: string | undefined) => void;
|
||||
setSearchEnabled: (enabled: boolean) => void;
|
||||
setHideInCinemaTag: (hide: boolean) => void;
|
||||
setCastCount: (count: number | undefined) => void;
|
||||
loadConfigFromUrl: () => void;
|
||||
};
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ interface AddonConfig {
|
||||
enabled: boolean;
|
||||
showInHome: boolean;
|
||||
}>;
|
||||
hideInCinemaTag?: boolean;
|
||||
castCount?: number;
|
||||
}
|
||||
|
||||
export function generateAddonUrl(config: AddonConfig): string {
|
||||
@@ -39,6 +41,8 @@ export function generateAddonUrl(config: AddonConfig): string {
|
||||
tmdbPrefix: config.tmdbPrefix === true ? "true" : undefined,
|
||||
hideEpisodeThumbnails: config.hideEpisodeThumbnails === true ? "true" : undefined,
|
||||
searchEnabled: config.searchEnabled === false ? "false" : undefined,
|
||||
hideInCinemaTag: config.hideInCinemaTag === true ? "true" : undefined,
|
||||
castCount: typeof config.castCount === "number" ? config.castCount : undefined,
|
||||
};
|
||||
|
||||
const cleanConfig = Object.fromEntries(
|
||||
|
||||
@@ -9,6 +9,8 @@ const Others = () => {
|
||||
const { includeAdult, setIncludeAdult } = useConfig();
|
||||
const { provideImdbId, setProvideImdbId } = useConfig();
|
||||
const { tmdbPrefix, setTmdbPrefix } = useConfig();
|
||||
const { hideInCinemaTag, setHideInCinemaTag } = useConfig();
|
||||
const { castCount, setCastCount } = useConfig();
|
||||
|
||||
return (
|
||||
<main className="md:p-12 px-2 py-12">
|
||||
@@ -59,6 +61,36 @@ const Others = () => {
|
||||
</div>
|
||||
<Switch checked={tmdbPrefix} onCheckedChange={() => setTmdbPrefix(!tmdbPrefix)} />
|
||||
</Card>
|
||||
<Card className="flex flex-row items-center justify-between p-6">
|
||||
<div className="space-y-0.5">
|
||||
<h1 className="text-sm font-semibold mb-1">Hide 'In Cinema' tag</h1>
|
||||
<p className="text-gray-500 text-sm">
|
||||
Hide the 'In Cinema' tag from posters
|
||||
</p>
|
||||
</div>
|
||||
<Switch checked={hideInCinemaTag} onCheckedChange={setHideInCinemaTag} />
|
||||
</Card>
|
||||
<Card className="flex flex-row items-center justify-between p-6">
|
||||
<div className="space-y-0.5">
|
||||
<h1 className="text-sm font-semibold mb-1">Cast count to show</h1>
|
||||
<p className="text-gray-500 text-sm">
|
||||
Number of cast members to display (minimum 5, maximum 15, or Unlimited)
|
||||
</p>
|
||||
</div>
|
||||
<select
|
||||
className="border rounded px-2 py-1 text-sm"
|
||||
value={castCount === undefined ? "Unlimited" : castCount}
|
||||
onChange={e => {
|
||||
const value = e.target.value;
|
||||
setCastCount(value === "Unlimited" ? undefined : Number(value));
|
||||
}}
|
||||
>
|
||||
<option value={5}>5</option>
|
||||
<option value={10}>10</option>
|
||||
<option value={15}>15</option>
|
||||
<option value="Unlimited">Unlimited</option>
|
||||
</select>
|
||||
</Card>
|
||||
<Card className="p-6">
|
||||
<AgeRatingSelect />
|
||||
</Card>
|
||||
|
||||
Reference in New Issue
Block a user