import { Ionicons, MaterialCommunityIcons } from "@expo/vector-icons"; import { uniqBy } from "lodash"; import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { View, type ViewProps } from "react-native"; import CountryFlag from "react-native-country-flag"; import { Text } from "@/components/common/Text"; import { useJellyseerr } from "@/hooks/useJellyseerr"; import { ANIME_KEYWORD_ID } from "@/utils/jellyseerr/server/api/themoviedb/constants"; import type { TmdbRelease } from "@/utils/jellyseerr/server/api/themoviedb/interfaces"; import type { MovieDetails } from "@/utils/jellyseerr/server/models/Movie"; import type { TvDetails } from "@/utils/jellyseerr/server/models/Tv"; interface Release { certification: string; iso_639_1?: string; note?: string; release_date: string; type: number; } export const dateOpts: Intl.DateTimeFormatOptions = { year: "numeric", month: "long", day: "numeric", }; const Facts: React.FC< { title: string; facts?: string[] | React.ReactNode[] } & ViewProps > = ({ title, facts, ...props }) => facts && facts?.length > 0 && ( {title} {facts.map((f, idx) => typeof f === "string" ? {f} : f, )} ); const Fact: React.FC<{ title: string; fact?: string | null } & ViewProps> = ({ title, fact, ...props }) => fact && ; const DetailFacts: React.FC< { details?: MovieDetails | TvDetails } & ViewProps > = ({ details, className, ...props }) => { const { jellyseerrRegion: region, jellyseerrLocale: locale } = useJellyseerr(); const { t } = useTranslation(); const releases = useMemo( () => (details as MovieDetails)?.releases?.results.find( (r: TmdbRelease) => r.iso_3166_1 === region, )?.release_dates as TmdbRelease["release_dates"], [details], ); // Release date types: // 1. Premiere // 2. Theatrical (limited) // 3. Theatrical // 4. Digital // 5. Physical // 6. TV const filteredReleases = useMemo( () => uniqBy( releases?.filter((r: Release) => r.type > 2 && r.type < 6), "type", ), [releases], ); const firstAirDate = useMemo(() => { const firstAirDate = (details as TvDetails)?.firstAirDate; if (firstAirDate) { return new Date(firstAirDate).toLocaleDateString( `${locale}-${region}`, dateOpts, ); } }, [details]); const nextAirDate = useMemo(() => { const firstAirDate = (details as TvDetails)?.firstAirDate; const nextAirDate = (details as TvDetails)?.nextEpisodeToAir?.airDate; if (nextAirDate && firstAirDate !== nextAirDate) { return new Date(nextAirDate).toLocaleDateString( `${locale}-${region}`, dateOpts, ); } }, [details]); const revenue = useMemo( () => (details as MovieDetails)?.revenue?.toLocaleString?.( `${locale}-${region}`, { style: "currency", currency: "USD" }, ), [details], ); const budget = useMemo( () => (details as MovieDetails)?.budget?.toLocaleString?.( `${locale}-${region}`, { style: "currency", currency: "USD" }, ), [details], ); const streamingProviders = useMemo( () => details?.watchProviders?.find( (provider) => provider.iso_3166_1 === region, )?.flatrate, [details], ); const networks = useMemo(() => (details as TvDetails)?.networks, [details]); const spokenLanguage = useMemo( () => details?.spokenLanguages.find( (lng) => lng.iso_639_1 === details.originalLanguage, )?.name, [details], ); return ( details && ( {t("jellyseerr.details")} {details.keywords.some( (keyword) => keyword.id === ANIME_KEYWORD_ID, ) && } ( {r.type === 3 ? ( // Theatrical ) : r.type === 4 ? ( // Digital ) : ( // Physical )} {new Date(r.release_date).toLocaleDateString( `${locale}-${region}`, dateOpts, )} ))} /> ( {n.name} ))} /> n.name, )} /> n.name)} /> s.name)} /> ) ); }; export default DetailFacts;