import { jsxs, jsx } from "react/jsx-runtime"; import { useSearchParams, Link, useParams, useLocation, Outlet, useRoutes } from "react-router-dom"; import { m as message, ah as MenuTrigger, I as IconButton, B as Button, T as Trans, ai as Menu, h as Item, b2 as useCookie, ae as SiteConfigContext, c as createSvgIcon, i as useTrans, t as toast, b3 as FacebookIcon, b4 as TwitterIcon, aF as FormattedRelativeTime, b5 as LockIcon, o as opacityAnimation, R as FormattedDate, K as KeyboardArrowLeftIcon, ad as LinkStyle, w as IllustratedMessage, x as SvgImage, af as getBootstrapData, b as apiClient, aa as useNavigate, aO as ComboBoxForwardRef, k as SearchIcon, N as Navbar, V as Tooltip, aW as lazyLoader, u as useSettings, b6 as useAuth, b1 as Footer, aP as PageMetaTags, aD as PageStatus, e as useIsMobileMediaQuery, D as DialogTrigger, X as ButtonBase, b7 as useImageSrc, J as Form, L as FormTextField, n as showHttpErrorToast, r as ConfirmationDialog, a2 as Skeleton, d as useLocalStorage, Q as Chip, q as queryClient, M as CheckIcon, b8 as FormattedCurrency, j as TextField, b9 as useDarkThemeVariables, aN as PageErrorMessage, p as useDialogContext, l as StaticPageTitle, O as CloseIcon, G as onFormQueryError, _ as useValueLists, y as Dialog, z as DialogHeader, A as DialogBody, a7 as FileUploadProvider, Z as FormImageSelector, a4 as FormSelect, F as DialogFooter, az as isAbsoluteUrl, aX as AuthRoute, b0 as NotFoundPage } from "../server-entry.mjs"; import { b9 as useChannelQueryParams, aN as useInfiniteData, ba as channelQueryKey, bb as channelEndpoint, X as channelContentConfig, bc as Sort, aM as SortIcon, K as KeyboardArrowRightIcon, bd as GridViewIcon, ab as UserAvatar, be as BaseMediaLink, bf as getBaseMediaLink, u as useBackendFilterUrlParams, av as useTitleIndexFilters, A as AddFilterButton, w as TuneIcon, c as FilterListSkeleton, e as FilterList, _ as TITLE_MODEL, $ as MOVIE_MODEL, a0 as SERIES_MODEL, a$ as FormattedDateTimeRange, a8 as NewsArticleImage, a9 as NewsArticleLink, ae as BulletSeparatedItems, ai as TitlePoster, at as TitleLink, ad as TitleRating, aK as TitleBackdrop, bg as NEWS_ARTICLE_MODEL, aX as PERSON_MODEL, aT as PersonPoster, aV as PersonLink, aF as InfiniteScrollSentinel, bh as useChannelContent, bi as PaginationControls, R as ChevronLeftIcon, aO as MediaPlayIcon, aj as getWatchLink, aW as KnownForCompact, bj as FormattedDuration, bk as InteractableRating, bl as CHANNEL_MODEL, a_ as todoImage, bm as getPersonLink, az as getTitleLink, aA as useScrollToTop, W as useChannel, O as ImageZoomDialog, bn as ArrowForwardIcon, aH as useTitleSeasons, aI as SeasonPoster, aJ as SeasonLink, bo as useCreateReview, Q as Avatar, af as StarSelector, bp as useAuthClickCapture, ac as useDeleteReviews, M as MoreVertIcon, bq as useReviews, ah as ReviewListSortButton, br as getEpisodeLink, bs as VideoGrid, aD as useSeasonEpisodes, ak as CompactSeasonEpisode, b3 as EpisodePoster, o as ChipList, g as AddIcon, aw as useTitle, aB as useSeason, aE as EpisodeListItem, bt as getSeasonLink, aS as useEpisode, al as FormattedNumber, aa as useDeleteComments, b5 as EpisodeLink, bu as VideoGridItemSkeleton, bv as VideoGridItem, bw as EpisodeSelector, bx as MediaEpisodesIcon, ar as SiteVideoPlayer, aq as VideoPlayerSkeleton, aP as VideoThumbnail, q as Accordion, r as AccordionItem, aY as usePerson, aZ as useNewsArticle, H as Tabs, I as TabList, J as Tab, b6 as TitleLinkWithEpisodeNumber, by as StarIcon, b4 as UserProfileLink, b7 as CreateUserListPage, b8 as EditUserListPage } from "./user-profile-link-0bca566c.mjs"; import { useContext, useMemo, Fragment, memo, useRef, useState, useCallback, useEffect, useId, forwardRef, useImperativeHandle, Children } from "react"; import clsx from "clsx"; import { AnimatePresence, m } from "framer-motion"; import { L as LockOpenIcon, S as ShareIcon, E as ExpandMoreIcon, T as ThumbUpIcon, a as ThumbDownIcon, R as ReplyIcon, C as CommentIcon, F as FlagIcon, b as ListAltIcon, c as RateReviewIcon, B as BookmarkBorderIcon } from "./BookmarkBorder-2c120ae6.mjs"; import useClipboard from "react-use-clipboard"; import debounce from "just-debounce-it"; import { useLayoutEffect, getScrollParent, useObjectRef } from "@react-aria/utils"; import { C as ChevronRightIcon, O as OpenInNewIcon, E as EditIcon, B as Breadcrumb, a as BreadcrumbItem } from "./OpenInNew-3b47a656.mjs"; import { useQuery, keepPreviousData, useMutation, useQueryClient } from "@tanstack/react-query"; import dot from "dot-object"; import linkifyStr from "linkify-string"; import { useForm, useFieldArray } from "react-hook-form"; import memoize from "nano-memoize"; import "react-dom/server"; import "process"; import "http"; import "axios"; import "react-router-dom/server.mjs"; import "slugify"; import "deepmerge"; import "@internationalized/date"; import "zustand"; import "zustand/middleware/immer"; import "nanoid"; import "@react-aria/focus"; import "@floating-ui/react-dom"; import "react-merge-refs"; import "react-dom"; import "@internationalized/number"; import "@react-stately/utils"; import "@react-aria/ssr"; import "immer"; import "axios-retry"; import "tus-js-client"; import "react-use-cookie"; import "mime-match"; import "fscreen"; import "zustand/middleware"; import "zustand/traditional"; import "@react-aria/interactions"; function useInfiniteChannelContent(channel) { const queryParams = useChannelQueryParams(channel); return useInfiniteData({ willSortOrFilter: true, initialPage: channel.content, queryKey: channelQueryKey(channel.id), endpoint: channelEndpoint(channel.id), queryParams: { returnContentOnly: "true", ...queryParams } }); } function ChannelSortButton({ channel }) { var _a; const config = channelContentConfig.models[channel.config.contentModel]; const sortMethods = (config == null ? void 0 : config.sortMethods.map((method) => ({ key: method, label: channelContentConfig.sortingMethods[method].label }))) || []; if (channel.config.contentType === "manual") { sortMethods.unshift({ key: Sort.curated, label: message("Default order") }); } const [searchParams, setSearchParams] = useSearchParams(); const selectedValue = searchParams.get("order") || channel.config.contentOrder; if ((sortMethods == null ? void 0 : sortMethods.length) < 2) { return null; } const label = (_a = sortMethods == null ? void 0 : sortMethods.find( (method) => method.key === selectedValue )) == null ? void 0 : _a.label; return /* @__PURE__ */ jsxs( MenuTrigger, { selectionMode: "single", showCheckmark: true, selectedValue, onSelectionChange: (newValue) => { if (newValue === Sort.recent && channel.config.contentType === "manual") { newValue = "channelables.created_at:desc"; } setSearchParams( (prev) => { prev.set("order", newValue); return prev; }, { replace: true } ); }, children: [ /* @__PURE__ */ jsxs("span", { role: "button", "aria-label": "Toggle menu", children: [ /* @__PURE__ */ jsx(IconButton, { className: "md:hidden", role: "presentation", children: /* @__PURE__ */ jsx(SortIcon, {}) }), /* @__PURE__ */ jsx( Button, { startIcon: /* @__PURE__ */ jsx(SortIcon, {}), className: "max-md:hidden", role: "presentation", children: label ? /* @__PURE__ */ jsx(Trans, { ...label }) : /* @__PURE__ */ jsx(Trans, { message: "Popularity" }) } ) ] }), /* @__PURE__ */ jsx(Menu, { children: sortMethods == null ? void 0 : sortMethods.map((method) => /* @__PURE__ */ jsx(Item, { value: method.key, children: /* @__PURE__ */ jsx(Trans, { ...method.label }) }, method.key)) }) ] } ); } function SiteSectionHeading({ children, titleAppend, link, fontSize = "text-2xl md:text-3xl", fontWeight = "font-bold", margin = "mb-20", className: className2, headingType: HeadingType = "h2", description, descriptionFontSize = "text-base", actions, hideBorder }) { const title = link ? /* @__PURE__ */ jsx( Link, { to: link, className: "rounded outline-none transition-colors hover:underline focus-visible:ring-2 focus-visible:ring-offset-2", children } ) : children; return /* @__PURE__ */ jsxs("section", { className: clsx(className2, margin), children: [ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-44 max-md:overflow-x-auto", children: [ /* @__PURE__ */ jsx("div", { className: "flex-auto", children: /* @__PURE__ */ jsxs( "div", { className: clsx( "relative flex items-center gap-4", !hideBorder && "pl-14 before:absolute before:left-0 before:h-5/6 before:w-4 before:rounded before:bg-primary" ), children: [ /* @__PURE__ */ jsx(HeadingType, { className: clsx(fontSize, fontWeight), children: title }), titleAppend && /* @__PURE__ */ jsx("span", { className: "pt-4 text-base text-muted", children: titleAppend }), link && /* @__PURE__ */ jsx( IconButton, { elementType: Link, to: link, size: "sm", iconSize: "lg", className: "mt-4 max-md:hidden", children: /* @__PURE__ */ jsx(KeyboardArrowRightIcon, {}) } ) ] } ) }), actions && /* @__PURE__ */ jsx("div", { className: "flex flex-shrink-0 items-center gap-4", children: actions }) ] }), description && /* @__PURE__ */ jsx("div", { className: clsx("mt-6", descriptionFontSize), children: description }) ] }); } function useChannelLayouts(channel) { const config = channelContentConfig.models[channel.config.contentModel]; const availableLayouts = config == null ? void 0 : config.layoutMethods.filter((m2) => channelContentConfig.userSelectableLayouts.includes(m2)).map((method) => ({ key: method, label: channelContentConfig.layoutMethods[method].label, icon: channelContentConfig.layoutMethods[method].icon })); const [selectedLayout, setSelectedLayout] = useCookie( `channel-layout-${channel.config.contentModel}`, channel.config.selectedLayout || channel.config.layout ); return { selectedLayout, setSelectedLayout, availableLayouts }; } function ChannelLayoutButton({ channel }) { const { selectedLayout, setSelectedLayout, availableLayouts } = useChannelLayouts(channel); if ((availableLayouts == null ? void 0 : availableLayouts.length) < 2) { return null; } const layoutConfig = availableLayouts == null ? void 0 : availableLayouts.find( (method) => method.key === selectedLayout ); return /* @__PURE__ */ jsxs( MenuTrigger, { selectionMode: "single", showCheckmark: true, selectedValue: selectedLayout, onSelectionChange: (newValue) => setSelectedLayout(newValue), children: [ /* @__PURE__ */ jsxs("span", { role: "button", "aria-label": "Toggle menu", children: [ /* @__PURE__ */ jsx(IconButton, { className: "md:hidden", role: "presentation", children: (layoutConfig == null ? void 0 : layoutConfig.icon) || /* @__PURE__ */ jsx(GridViewIcon, {}) }), /* @__PURE__ */ jsx( Button, { role: "presentation", className: "max-md:hidden", startIcon: (layoutConfig == null ? void 0 : layoutConfig.icon) || /* @__PURE__ */ jsx(GridViewIcon, {}), children: (layoutConfig == null ? void 0 : layoutConfig.label) ? /* @__PURE__ */ jsx(Trans, { ...layoutConfig.label }) : /* @__PURE__ */ jsx(Trans, { message: "Popularity" }) } ) ] }), /* @__PURE__ */ jsx(Menu, { children: availableLayouts == null ? void 0 : availableLayouts.map((method) => /* @__PURE__ */ jsx(Item, { value: method.key, children: /* @__PURE__ */ jsx(Trans, { ...method.label }) }, method.key)) }) ] } ); } function UserListByline({ user }) { const { auth } = useContext(SiteConfigContext); return /* @__PURE__ */ jsxs("div", { className: "flex-shrink-0 flex items-center gap-8 mr-24", children: [ /* @__PURE__ */ jsx(UserAvatar, { user, circle: true, size: "sm" }), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx( Trans, { message: "List by :name", values: { a: () => /* @__PURE__ */ jsx( Link, { to: auth.getUserProfileLink(user), className: "font-bold hover:underline", children: user.display_name } ) } } ) }) ] }); } function shareLinkSocially(network, link, name, image) { const url = generateShareUrl(network, link, name, image); if (network === "mail") { window.location.href = url; } else { openNewWindow(url); } } function openNewWindow(url) { const width = 575, height = 400, left = (window.innerWidth - width) / 2, top = (window.innerHeight - height) / 2, opts = "status=1, scrollbars=1,width=" + width + ",height=" + height + ",top=" + top + ",left=" + left; window.open(url, "share", opts); } function generateShareUrl(type, link, name, image) { switch (type) { case "facebook": return "https://www.facebook.com/sharer/sharer.php?u=" + link; case "twitter": return `https://twitter.com/intent/tweet?text=${name}&url=${link}`; case "pinterest": return "https://pinterest.com/pin/create/button/?url=" + link + "&media=" + image; case "tumblr": const base = "https://www.tumblr.com/widgets/share/tool?shareSource=legacy&canonicalUrl=&posttype=photo&title=&caption="; return base + name + "&content=" + image + "&url=" + link; case "blogger": return "https://www.blogger.com/blog_this.pyra?t&u=" + link + "&n=" + name; case "mail": return `mailto:?subject=Check out this link.&body=${link}`; } } const CopyLinkIcon = createSvgIcon( /* @__PURE__ */ jsx("path", { d: "M 4 2 C 2.895 2 2 2.895 2 4 L 2 18 L 4 18 L 4 4 L 18 4 L 18 2 L 4 2 z M 8 6 C 6.895 6 6 6.895 6 8 L 6 20 C 6 21.105 6.895 22 8 22 L 20 22 C 21.105 22 22 21.105 22 20 L 22 8 C 22 6.895 21.105 6 20 6 L 8 6 z M 8 8 L 20 8 L 20 20 L 8 20 L 8 8 z M 16 9.0058594 C 15.230215 9.0058594 14.460443 9.2973698 13.878906 9.8789062 L 12.607422 11.150391 L 14.021484 12.564453 L 12.556641 14.029297 L 11.142578 12.615234 L 9.8789062 13.878906 C 8.7158332 15.041979 8.7158332 16.958021 9.8789062 18.121094 C 10.460397 18.702585 11.234094 19 12 19 C 12.765906 19 13.539603 18.702585 14.121094 18.121094 L 15.384766 16.857422 L 13.970703 15.443359 L 15.457031 13.957031 L 14.042969 12.542969 L 15.292969 11.292969 C 15.691896 10.894042 16.308104 10.894042 16.707031 11.292969 C 17.105958 11.691896 17.105958 12.308104 16.707031 12.707031 L 15.464844 13.949219 L 16.878906 15.363281 L 18.121094 14.121094 C 19.284167 12.958021 19.284167 11.041979 18.121094 9.8789062 C 17.539557 9.2973698 16.769785 9.0058594 16 9.0058594 z M 12.542969 14.042969 L 13.957031 15.457031 L 12.707031 16.707031 C 12.506522 16.90754 12.258094 17 12 17 C 11.741906 17 11.493478 16.90754 11.292969 16.707031 C 10.894042 16.308104 10.894042 15.691896 11.292969 15.292969 L 12.542969 14.042969 z" }) ); function ShareMenuTrigger({ link, children }) { const { trans } = useTrans(); const [, setUrlCopied] = useClipboard(link); return /* @__PURE__ */ jsxs(MenuTrigger, { children: [ children, /* @__PURE__ */ jsxs(Menu, { children: [ /* @__PURE__ */ jsx( Item, { value: "clipboard", startIcon: /* @__PURE__ */ jsx(CopyLinkIcon, {}), onSelected: () => { setUrlCopied(); toast.positive(message("Copied link to clipboard")); }, children: /* @__PURE__ */ jsx(Trans, { message: "Copy to clipboard" }) } ), /* @__PURE__ */ jsx( Item, { value: "facebook", startIcon: /* @__PURE__ */ jsx(FacebookIcon, {}), onClick: () => { shareLinkSocially( "facebook", link, trans(message("Check out this link")) ); }, children: /* @__PURE__ */ jsx(Trans, { message: "Share to facebook" }) } ), /* @__PURE__ */ jsx( Item, { value: "twitter", startIcon: /* @__PURE__ */ jsx(TwitterIcon, {}), onClick: () => { shareLinkSocially( "twitter", link, trans(message("Check out this link")) ); }, children: /* @__PURE__ */ jsx(Trans, { message: "Share to twitter" }) } ) ] }) ] }); } function UserListLink({ list, children, ...linkProps }) { const link = useMemo(() => { return getUserListLink(list); }, [list]); let content2; if (children) { content2 = children; } else if (list.internal && list.name === "watchlist") { return /* @__PURE__ */ jsx(Trans, { message: "Watchlist" }); } else { content2 = list.name; } return /* @__PURE__ */ jsx(BaseMediaLink, { ...linkProps, link, children: content2 }); } function getUserListLink(list, { absolute } = {}) { return getBaseMediaLink(`/lists/${list.id}`, { absolute }); } function UserListDetails({ list, className: className2, showShareButton, showVisibility = true }) { return /* @__PURE__ */ jsxs( "div", { className: clsx( "flex flex-shrink-0 items-center gap-4 whitespace-nowrap text-muted", className2 ), children: [ showShareButton && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(ShareButton$4, { list }), /* @__PURE__ */ jsx(Divider, { marginLeft: "ml-2" }) ] }), list.items_count ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(Trans, { message: ":count items", values: { count: list.items_count } }), /* @__PURE__ */ jsx(Divider, {}) ] }) : null, /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx( Trans, { message: "Updated :date", values: { date: /* @__PURE__ */ jsx(FormattedRelativeTime, { date: list.updated_at }) } } ) }), showVisibility && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(Divider, {}), list.public ? /* @__PURE__ */ jsx(LockOpenIcon, { size: "sm" }) : /* @__PURE__ */ jsx(LockIcon, { size: "sm" }), /* @__PURE__ */ jsx("div", { children: list.public ? /* @__PURE__ */ jsx(Trans, { message: "Public" }) : /* @__PURE__ */ jsx(Trans, { message: "Private" }) }) ] }) ] } ); } function ShareButton$4({ list }) { const link = getUserListLink(list, { absolute: true }); return /* @__PURE__ */ jsx(ShareMenuTrigger, { link, children: /* @__PURE__ */ jsx(Button, { startIcon: /* @__PURE__ */ jsx(ShareIcon, {}), sizeClassName: "px-10 py-6", children: /* @__PURE__ */ jsx(Trans, { message: "Share" }) }) }); } function Divider({ marginLeft = "ml-12" }) { return /* @__PURE__ */ jsx("div", { className: clsx("mr-10 h-20 w-1 bg-divider", marginLeft) }); } const FilterModelTypes = [TITLE_MODEL, MOVIE_MODEL, SERIES_MODEL]; function ChannelHeader({ channel, isNested, actions, margin = isNested ? "mb-16 md:mb-30" : "mb-20 md:mb-40" }) { const shouldShowFilterButton = !isNested && FilterModelTypes.includes(channel.config.contentModel) && channel.config.contentType === "listAll"; const { encodedFilters } = useBackendFilterUrlParams(); const { filters, filtersLoading } = useTitleIndexFilters({ disabled: !shouldShowFilterButton }); if (channel.config.hideTitle) { return null; } return /* @__PURE__ */ jsxs("section", { className: clsx(margin), children: [ /* @__PURE__ */ jsx( ChannelTitle, { channel, isNested, actions: /* @__PURE__ */ jsxs(Fragment, { children: [ actions, !isNested && /* @__PURE__ */ jsx(ChannelSortButton, { channel }), shouldShowFilterButton && /* @__PURE__ */ jsx( AddFilterButton, { icon: /* @__PURE__ */ jsx(TuneIcon, {}), color: null, variant: "text", disabled: filtersLoading, filters } ), !isNested && /* @__PURE__ */ jsx(ChannelLayoutButton, { channel }) ] }) } ), shouldShowFilterButton && /* @__PURE__ */ jsx("div", { className: "mt-14", children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: filtersLoading && encodedFilters ? /* @__PURE__ */ jsx(FilterListSkeleton, {}) : /* @__PURE__ */ jsx(m.div, { ...opacityAnimation, children: /* @__PURE__ */ jsx(FilterList, { filters }) }, "filter-list") }) }) ] }); } function ChannelTitle({ channel, isNested, actions }) { const { restriction: urlParam } = useParams(); if (channel.config.hideTitle) { return null; } const link = channel.config.restriction && urlParam ? `/${channel.slug}/${urlParam}` : `/${channel.slug}`; return /* @__PURE__ */ jsx( SiteSectionHeading, { className: "flex-auto", margin: "m-0", description: /* @__PURE__ */ jsx(ChannelDescription, { channel }), actions, headingType: isNested ? "h2" : "h1", descriptionFontSize: isNested ? "text-sm" : void 0, fontWeight: isNested ? "font-normal" : void 0, link: isNested ? link : void 0, children: /* @__PURE__ */ jsx(Trans, { message: channel.name }) } ); } function ChannelDescription({ channel }) { if (channel.type === "channel") { return /* @__PURE__ */ jsx(Fragment, { children: channel.description }); } return /* @__PURE__ */ jsxs("div", { className: "mt-18 items-center text-sm md:flex", children: [ channel.user && /* @__PURE__ */ jsx(UserListByline, { user: channel.user }), /* @__PURE__ */ jsx( UserListDetails, { list: channel, className: "ml-auto max-md:mt-14", showShareButton: true } ) ] }); } function ContentGridLayout({ children, className: className2, variant, gridCols = "grid-cols-[repeat(var(--nVisibleItems),minmax(0,1fr))]" }) { return /* @__PURE__ */ jsx( "div", { className: clsx( "grid gap-24", gridCols, className2, variant === "landscape" ? "content-grid-landscape" : "content-grid-portrait" ), children } ); } const PersonAge = memo(({ person, showRange }) => { if (showRange && person.birth_date && person.death_date) { return /* @__PURE__ */ jsx( FormattedDateTimeRange, { start: person.birth_date, end: person.death_date, options: { year: "numeric" } } ); } if (person.birth_date) { return /* @__PURE__ */ jsx(Fragment, { children: calculateAgeFromBirthDate(person.birth_date, person.death_date) }); } return null; }); function calculateAgeFromBirthDate(_birthDate, _deathDate) { const until = _deathDate ? new Date(_deathDate) : /* @__PURE__ */ new Date(); const birthDate = new Date(_birthDate); let age = until.getFullYear() - birthDate.getFullYear(); const m2 = until.getMonth() - birthDate.getMonth(); if (m2 < 0 || m2 === 0 && until.getDate() < birthDate.getDate()) { age--; } return age; } function NewsArticleGridItem({ article }) { return /* @__PURE__ */ jsxs("div", { className: "items-start gap-14 lg:flex", children: [ /* @__PURE__ */ jsx( NewsArticleImage, { article, className: "aspect-poster max-w-90 max-md:hidden" } ), /* @__PURE__ */ jsxs("div", { className: "min-w-0 overflow-hidden overflow-ellipsis text-base md:mt-24 lg:mt-6", children: [ /* @__PURE__ */ jsx(NewsArticleLink, { article, className: "font-medium" }), /* @__PURE__ */ jsxs(BulletSeparatedItems, { className: "mt-10 min-w-0 overflow-hidden overflow-ellipsis text-xs", children: [ /* @__PURE__ */ jsx(FormattedDate, { date: article.created_at }), /* @__PURE__ */ jsx("div", { className: "overflow-hidden overflow-ellipsis whitespace-nowrap", children: article.source }) ] }) ] }) ] }); } function TitlePortraitGridItem({ item, rating, description }) { return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx(TitlePoster, { title: item, srcSize: "md", showPlayButton: true }) }), /* @__PURE__ */ jsxs("div", { className: "mt-10 text-sm", children: [ /* @__PURE__ */ jsx(RatingOrReleaseDate, { title: item, rating, className: "mb-4" }), /* @__PURE__ */ jsx(TitleLink, { title: item, className: "block text-base font-medium" }), description ? /* @__PURE__ */ jsx("div", { className: "mt-4", children: description }) : null ] }) ] }); } function TitleLandscapeGridItem({ item }) { return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx( TitleBackdrop, { title: item, srcSize: "lg", size: "w-full", className: "rounded", wrapWithLink: true, showPlayButton: true } ), /* @__PURE__ */ jsxs("div", { className: "mt-10 text-sm", children: [ /* @__PURE__ */ jsx( TitleLink, { title: item, className: "mb-4 block text-base font-semibold" } ), /* @__PURE__ */ jsxs(BulletSeparatedItems, { className: "mb-4", children: [ item.release_date && /* @__PURE__ */ jsx(FormattedDate, { date: item.release_date }), item.certification && /* @__PURE__ */ jsx("div", { className: "uppercase", children: item.certification }) ] }), /* @__PURE__ */ jsx(TitleRating, { score: item.rating, className: "mb-4" }) ] }) ] }); } function RatingOrReleaseDate({ title, rating, className: className2 }) { if (!rating) { rating = title.rating; } if (rating) { return /* @__PURE__ */ jsx(TitleRating, { score: rating, className: className2 }); } if (title.release_date) { return /* @__PURE__ */ jsx("div", { className: className2, children: /* @__PURE__ */ jsx(FormattedDate, { date: title.release_date }) }); } return null; } function ChannelContentGridItem({ item, variant }) { switch (item.model_type) { case TITLE_MODEL: return variant === "landscape" ? /* @__PURE__ */ jsx(TitleLandscapeGridItem, { item }) : /* @__PURE__ */ jsx(TitlePortraitGridItem, { item }); case PERSON_MODEL: return /* @__PURE__ */ jsx(PersonGridItem, { item }); case NEWS_ARTICLE_MODEL: return /* @__PURE__ */ jsx(NewsArticleGridItem, { article: item }); default: return null; } } function PersonGridItem({ item }) { return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(PersonPoster, { person: item, srcSize: "md", size: "w-full", rounded: true }), /* @__PURE__ */ jsxs("div", { className: "mt-10 text-center text-sm", children: [ /* @__PURE__ */ jsx(PersonLink, { person: item, className: "block text-base font-medium" }), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(PersonAge, { person: item, showRange: true }) }) ] }) ] }); } function ChannelContentGrid(props) { const isInfiniteScroll = !props.isNested && (!props.channel.config.paginationType || props.channel.config.paginationType === "infiniteScroll"); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(ChannelHeader, { ...props }), isInfiniteScroll ? /* @__PURE__ */ jsx(InfiniteScrollGrid, { ...props }) : /* @__PURE__ */ jsx(PaginatedGrid, { ...props }) ] }); } function InfiniteScrollGrid({ channel, variant }) { const query = useInfiniteChannelContent(channel); return /* @__PURE__ */ jsxs( "div", { className: clsx("transition-opacity", query.isReloading && "opacity-70"), children: [ /* @__PURE__ */ jsx(ContentGrid, { content: query.items, variant }), /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query }) ] } ); } function PaginatedGrid({ channel, variant, isNested }) { var _a; const shouldPaginate = !isNested; const query = useChannelContent(channel, null, { paginate: shouldPaginate }); return /* @__PURE__ */ jsxs( "div", { className: clsx( "transition-opacity", query.isPlaceholderData && "opacity-70" ), children: [ shouldPaginate && /* @__PURE__ */ jsx( PaginationControls, { pagination: query.data, type: channel.config.paginationType, className: "mb-24" } ), /* @__PURE__ */ jsx(ContentGrid, { content: (_a = query.data) == null ? void 0 : _a.data, variant }), shouldPaginate && /* @__PURE__ */ jsx( PaginationControls, { pagination: query.data, type: channel.config.paginationType, className: "mt-24", scrollToTop: true } ) ] } ); } function ContentGrid({ content: content2 = [], variant }) { return /* @__PURE__ */ jsx(ContentGridLayout, { variant, children: content2.map((item) => /* @__PURE__ */ jsx( ChannelContentGridItem, { item, variant }, `${item.id}-${item.model_type}` )) }); } const containerClassName = "content-carousel content-grid relative w-full grid grid-flow-col grid-rows-[auto] overflow-x-auto overflow-y-hidden gap-24 snap-always snap-x snap-mandatory hidden-scrollbar scroll-smooth"; const itemClassName = "snap-start snap-normal"; function useCarousel({ rotate = false } = {}) { const scrollContainerRef = useRef(null); const itemWidth = useRef(0); const perPage = useRef(5); const [canScrollBackward, setCanScrollBackward] = useState(rotate); const [canScrollForward, setCanScrollForward] = useState(true); const [activePage, setActivePage] = useState(0); const updateNavStatus = useCallback(() => { const el = scrollContainerRef.current; if (el && itemWidth.current) { if (!rotate) { setCanScrollForward( el.scrollWidth - 1 > el.scrollLeft + el.clientWidth ); setCanScrollBackward(el.scrollLeft > 0); } const pageWidth = el.clientWidth; const activePage2 = Math.round(el.scrollLeft / pageWidth); setActivePage(activePage2); } }, [rotate]); useEffect(() => { const el = scrollContainerRef.current; const handleScroll = debounce(() => updateNavStatus(), 100); if (el) { el.addEventListener("scroll", handleScroll); } return () => el == null ? void 0 : el.removeEventListener("scroll", handleScroll); }, [updateNavStatus]); useLayoutEffect(() => { const el = scrollContainerRef.current; if (el) { perPage.current = Number( getComputedStyle(el).getPropertyValue("--nVisibleItems") ); const firstGridItem = el.children.item(0); const observer = new ResizeObserver((entries) => { itemWidth.current = entries[0].contentRect.width; updateNavStatus(); }); if (firstGridItem) { observer.observe(firstGridItem); } return () => observer.unobserve(el); } }, [updateNavStatus]); const scrollToIndex = useCallback((index) => { if (scrollContainerRef.current) { setActivePage(index); const amount = itemWidth.current * index; scrollContainerRef.current.scrollTo({ left: amount }); } }, []); const scrollToPreviousPage = useCallback(() => { if (scrollContainerRef.current) { const pageWidth = scrollContainerRef.current.clientWidth; const currentScroll = scrollContainerRef.current.scrollLeft; const scrollLeft = !currentScroll && rotate ? scrollContainerRef.current.scrollWidth - pageWidth : currentScroll - pageWidth; scrollContainerRef.current.scrollTo({ left: scrollLeft }); } }, [rotate]); const scrollToNextPage = useCallback(() => { if (scrollContainerRef.current) { const pageWidth = scrollContainerRef.current.clientWidth; const currentScroll = scrollContainerRef.current.scrollLeft; const scrollLeft = rotate && currentScroll + pageWidth >= scrollContainerRef.current.scrollWidth ? 0 : (activePage + 1) * pageWidth; scrollContainerRef.current.scrollTo({ left: scrollLeft }); } }, [activePage, rotate]); return { scrollContainerRef, scrollToIndex, scrollToPreviousPage, scrollToNextPage, canScrollForward, canScrollBackward, activePage, containerClassName, itemClassName }; } function ChannelContentCarousel(props) { var _a; const { channel, variant } = props; const { scrollContainerRef, canScrollForward, canScrollBackward, scrollToPreviousPage, scrollToNextPage, containerClassName: containerClassName2, itemClassName: itemClassName2 } = useCarousel(); const gridClassName = variant === "landscape" ? "content-grid-landscape" : "content-grid-portrait"; return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx( ChannelHeader, { ...props, actions: /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( IconButton, { disabled: !canScrollBackward, onClick: () => scrollToPreviousPage(), "aria-label": "Previous page", children: /* @__PURE__ */ jsx(KeyboardArrowLeftIcon, {}) } ), /* @__PURE__ */ jsx( IconButton, { disabled: !canScrollForward, onClick: () => scrollToNextPage(), "aria-label": "Next page", children: /* @__PURE__ */ jsx(KeyboardArrowRightIcon, {}) } ) ] }) } ), /* @__PURE__ */ jsx( "div", { ref: scrollContainerRef, className: clsx(containerClassName2, gridClassName), children: (_a = channel.content) == null ? void 0 : _a.data.map((item) => /* @__PURE__ */ jsx("div", { className: itemClassName2, children: /* @__PURE__ */ jsx(ChannelContentGridItem, { item, variant }) }, `${item.id}-${item.model_type}`)) } ) ] }); } function ChannelContentSlider({ channel, isNested }) { const { scrollContainerRef, activePage, canScrollBackward, canScrollForward, scrollToNextPage, scrollToPreviousPage } = useCarousel({ rotate: true }); const { data: pagination } = useChannelContent(channel); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( ChannelHeader, { channel, isNested, margin: "mb-18" } ), /* @__PURE__ */ jsxs("div", { className: "gap-24 md:flex", children: [ /* @__PURE__ */ jsxs("div", { className: "relative flex-auto", children: [ /* @__PURE__ */ jsx( "div", { ref: scrollContainerRef, className: "hidden-scrollbar flex h-full select-none snap-x snap-mandatory snap-always items-center overflow-x-auto", children: pagination == null ? void 0 : pagination.data.map((item, index) => /* @__PURE__ */ jsx(Slide, { item, index }, item.id)) } ), /* @__PURE__ */ jsxs("div", { className: "absolute top-10 z-20 w-full md:top-[170px]", children: [ /* @__PURE__ */ jsx("div", { className: "absolute left-8 hidden md:left-14 md:block", children: /* @__PURE__ */ jsx( IconButton, { variant: "outline", size: "lg", color: "white", disabled: !canScrollBackward, onClick: () => scrollToPreviousPage(), children: /* @__PURE__ */ jsx(ChevronLeftIcon, {}) } ) }), /* @__PURE__ */ jsx("div", { className: "absolute right-8 hidden md:right-14 md:block", children: /* @__PURE__ */ jsx( IconButton, { variant: "outline", size: "lg", color: "white", disabled: !canScrollForward, onClick: () => scrollToNextPage(), children: /* @__PURE__ */ jsx(ChevronRightIcon, {}) } ) }) ] }) ] }), /* @__PURE__ */ jsx(UpNext, { titles: (pagination == null ? void 0 : pagination.data) ?? [], activePage }) ] }) ] }); } function Slide({ item, index }) { return /* @__PURE__ */ jsxs("div", { className: "relative h-full w-full flex-shrink-0 snap-start snap-normal overflow-hidden rounded", children: [ /* @__PURE__ */ jsx( TitleBackdrop, { title: item, lazy: index > 0, className: "min-h-240 md:min-h-0", wrapperClassName: "h-full" } ), /* @__PURE__ */ jsxs("div", { className: "absolute inset-0 isolate flex h-full w-full items-center justify-start gap-24 rounded p-30 text-white md:items-end", children: [ /* @__PURE__ */ jsx("div", { className: "absolute left-0 h-full w-full bg-gradient-to-b from-black/40 max-md:top-0 md:bottom-0 md:h-3/4 md:bg-gradient-to-t md:from-black/100" }), /* @__PURE__ */ jsx( TitlePoster, { title: item, size: "max-h-320", srcSize: "md", className: "z-10 shadow-md max-md:hidden" } ), /* @__PURE__ */ jsxs("div", { className: "z-10 text-lg md:max-w-620", children: [ /* @__PURE__ */ jsx(TitleRating, { score: item.rating }), /* @__PURE__ */ jsx("div", { className: "my-8 text-2xl md:text-5xl", children: /* @__PURE__ */ jsx(TitleLink, { title: item }) }), item.description && /* @__PURE__ */ jsx("p", { className: "max-md:hidden", children: item.description }), item.primary_video && /* @__PURE__ */ jsx( Button, { variant: "flat", color: "primary", startIcon: /* @__PURE__ */ jsx(MediaPlayIcon, {}), radius: "rounded-full", className: "mt-24 md:min-h-42 md:min-w-144", elementType: Link, to: getWatchLink(item.primary_video), children: item.primary_video.category === "full" ? /* @__PURE__ */ jsx(Trans, { message: "Watch now" }) : /* @__PURE__ */ jsx(Trans, { message: "Play trailer" }) } ) ] }) ] }) ] }); } function UpNext({ titles, activePage }) { const itemCount = titles.length; const start = activePage + 1; const end = start + 3; const items = titles.slice(start, end); if (end > itemCount) { items.push(...titles.slice(0, end - itemCount)); } return /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: /* @__PURE__ */ jsxs("div", { className: "w-1/4 max-w-200 flex-shrink-0 max-md:hidden", children: [ /* @__PURE__ */ jsx("div", { className: "mb-12 text-lg font-semibold", children: /* @__PURE__ */ jsx(Trans, { message: "Up next" }) }), /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-24", children: items.map((item) => /* @__PURE__ */ jsxs( m.div, { className: "relative flex-auto", initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.2 }, children: [ /* @__PURE__ */ jsx( TitleBackdrop, { title: item, className: "mb-6 rounded", size: "w-full", srcSize: "md", wrapWithLink: true, showPlayButton: true } ), /* @__PURE__ */ jsx("div", { className: "mb-2 overflow-hidden overflow-ellipsis whitespace-nowrap text-sm", children: /* @__PURE__ */ jsx(TitleLink, { title: item, className: "text-base font-medium" }) }), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(TitleRating, { score: item.rating, className: "text-sm" }) }) ] }, item.id )) }) ] }) }); } function NewsArticleSourceLink({ article, className: className2 }) { return /* @__PURE__ */ jsxs("div", { className: clsx("flex items-center gap-4 text-primary", className2), children: [ /* @__PURE__ */ jsx(OpenInNewIcon, { size: "xs", className: "flex-shrink-0" }), /* @__PURE__ */ jsx( "a", { href: article.source_url, target: "_blank", rel: "noreferrer", className: clsx( LinkStyle, "whitespace-nowrap overflow-hidden overflow-ellipsis" ), children: article.source } ) ] }); } function NewsArticleByline({ article }) { return article.byline ? /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: /* @__PURE__ */ jsx(Trans, { message: "By :name", values: { name: article.byline } }) }) : null; } function ChannelContentNews({ channel, isNested }) { var _a, _b; const shouldPaginate = !isNested; const query = useChannelContent( channel, null, { paginate: shouldPaginate } ); return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(ChannelHeader, { channel, isNested }), shouldPaginate && /* @__PURE__ */ jsx( PaginationControls, { pagination: query.data, type: channel.config.paginationType, className: "mb-34" } ), /* @__PURE__ */ jsxs("div", { className: "flex gap-34", children: [ /* @__PURE__ */ jsx("div", { className: "w-240 flex-shrink-0", children: (_a = query.data) == null ? void 0 : _a.data.slice(0, 3).map((article) => /* @__PURE__ */ jsx( LeftColArticle, { article, className: "mb-14" }, article.id )) }), /* @__PURE__ */ jsx("div", { className: "flex-auto", children: (_b = query.data) == null ? void 0 : _b.data.slice(3, 12).map((article) => /* @__PURE__ */ jsxs("div", { className: "mb-12 flex items-center gap-14", children: [ /* @__PURE__ */ jsx(NewsArticleImage, { article, size: "w-84 h-84" }), /* @__PURE__ */ jsxs("div", { className: "flex-auto", children: [ /* @__PURE__ */ jsx(NewsArticleLink, { article, className: "font-semibold" }), /* @__PURE__ */ jsxs(BulletSeparatedItems, { className: "text-sm", children: [ /* @__PURE__ */ jsx(FormattedDate, { date: article.created_at }), /* @__PURE__ */ jsx(NewsArticleByline, { article }), /* @__PURE__ */ jsx(NewsArticleSourceLink, { article }) ] }) ] }) ] }, article.id)) }) ] }), shouldPaginate && /* @__PURE__ */ jsx( PaginationControls, { pagination: query.data, type: channel.config.paginationType, className: "mt-34", scrollToTop: true } ) ] }); } function LeftColArticle({ article, className: className2 }) { return /* @__PURE__ */ jsxs("div", { className: className2, children: [ /* @__PURE__ */ jsx(NewsArticleImage, { article, size: "aspect-video w-full" }), /* @__PURE__ */ jsx( NewsArticleLink, { article, className: "mt-10 block text-sm font-semibold" } ), /* @__PURE__ */ jsxs("div", { className: "mt-8 text-xs text-muted", children: [ /* @__PURE__ */ jsx(NewsArticleByline, { article }), /* @__PURE__ */ jsx(NewsArticleSourceLink, { article, className: "mt-4" }) ] }) ] }); } function ChannelContentListItem({ item }) { switch (item.model_type) { case TITLE_MODEL: return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-24 mb-24", children: [ /* @__PURE__ */ jsx(TitlePoster, { title: item, srcSize: "md", size: "w-128", showPlayButton: true }), /* @__PURE__ */ jsxs("div", { className: "flex-auto min-w-0 pt-12", children: [ /* @__PURE__ */ jsx(TitleLink, { title: item, className: "font-medium" }), /* @__PURE__ */ jsxs(BulletSeparatedItems, { className: "text-sm mt-4", children: [ item.runtime ? /* @__PURE__ */ jsx(FormattedDuration, { minutes: item.runtime, verbose: true }) : null, item.certification && /* @__PURE__ */ jsx("span", { className: "uppercase", children: item.certification }) ] }), item.rating && item.status !== "upcoming" ? /* @__PURE__ */ jsx(InteractableRating, { size: "md", title: item, className: "my-12" }) : /* @__PURE__ */ jsx("div", { className: "my-12", children: /* @__PURE__ */ jsx(FormattedDate, { date: item.release_date }) }), item.description ? /* @__PURE__ */ jsx("p", { className: "text-sm", children: item.description }) : null ] }) ] }); case PERSON_MODEL: return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-24 mb-24", children: [ /* @__PURE__ */ jsx(PersonPoster, { person: item, srcSize: "md", size: "w-128" }), /* @__PURE__ */ jsxs("div", { className: "flex-auto min-w-0 pt-12", children: [ /* @__PURE__ */ jsx(PersonLink, { person: item, className: "block font-medium text-lg" }), item.primary_credit ? /* @__PURE__ */ jsx("div", { className: "text-sm mt-4", children: /* @__PURE__ */ jsx(KnownForCompact, { person: item }) }) : null, /* @__PURE__ */ jsx("p", { className: "text-sm mt-12", children: item.description }) ] }) ] }); case NEWS_ARTICLE_MODEL: return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-14 mb-44", children: [ /* @__PURE__ */ jsx(NewsArticleImage, { article: item, className: "aspect-poster max-w-90" }), /* @__PURE__ */ jsxs("div", { className: "mt-6 text-base", children: [ /* @__PURE__ */ jsx(NewsArticleLink, { article: item, className: "font-medium" }), /* @__PURE__ */ jsx("p", { className: "text-sm mt-10", children: item.body }), /* @__PURE__ */ jsxs(BulletSeparatedItems, { className: "text-xs mt-10", children: [ /* @__PURE__ */ jsx(FormattedDate, { date: item.created_at }), /* @__PURE__ */ jsx(NewsArticleSourceLink, { article: item }) ] }) ] }) ] }); default: return null; } } function ChannelContentList(props) { const isInfiniteScroll = !props.isNested && (!props.channel.config.paginationType || props.channel.config.paginationType === "infiniteScroll"); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(ChannelHeader, { ...props }), isInfiniteScroll ? /* @__PURE__ */ jsx(InfiniteScrollList, { ...props }) : /* @__PURE__ */ jsx(PaginatedList, { ...props }) ] }); } function InfiniteScrollList({ channel }) { const query = useInfiniteChannelContent(channel); return /* @__PURE__ */ jsx( Content$1, { content: query.items, className: clsx("transition-opacity", query.isReloading && "opacity-70"), children: /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query }) } ); } function PaginatedList({ channel, isNested }) { var _a; const shouldPaginate = !isNested; const query = useChannelContent(channel, null, { paginate: shouldPaginate }); return /* @__PURE__ */ jsxs( "div", { className: clsx( "transition-opacity", query.isPlaceholderData && "opacity-70" ), children: [ shouldPaginate && /* @__PURE__ */ jsx( PaginationControls, { pagination: query.data, type: channel.config.paginationType, className: "mb-24" } ), /* @__PURE__ */ jsx(Content$1, { content: (_a = query.data) == null ? void 0 : _a.data }), shouldPaginate && /* @__PURE__ */ jsx( PaginationControls, { pagination: query.data, type: channel.config.paginationType, className: "mt-24", scrollToTop: true } ) ] } ); } function Content$1({ content: content2 = [], children, className: className2 }) { return /* @__PURE__ */ jsxs("div", { className: className2, children: [ content2.map((item) => /* @__PURE__ */ jsx( ChannelContentListItem, { item }, `${item.id}-${item.model_type}` )), children ] }); } function ChannelContent(props) { var _a; if (props.isNested && !((_a = props.channel.content) == null ? void 0 : _a.data.length)) { return null; } if (props.channel.config.contentModel === CHANNEL_MODEL) { return /* @__PURE__ */ jsx(NestedChannels, { ...props }); } else { return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(ChannelLayout, { ...props }), /* @__PURE__ */ jsx(NoResultsMessage, { channel: props.channel }) ] }); } } function NoResultsMessage({ channel }) { var _a; if (((_a = channel.content) == null ? void 0 : _a.data.length) === 0) { return /* @__PURE__ */ jsx( IllustratedMessage, { className: "mt-60", image: /* @__PURE__ */ jsx(SvgImage, { src: todoImage }), title: channel.type === "list" ? /* @__PURE__ */ jsx(Trans, { message: "This list does not have any content yet." }) : /* @__PURE__ */ jsx(Trans, { message: "This channel does not have any content yet." }) } ); } return null; } function ChannelLayout(props) { const { channel, isNested } = props; const { selectedLayout } = useChannelLayouts(channel); const layout = isNested ? channel.config.nestedLayout : selectedLayout; switch (layout) { case "grid": return /* @__PURE__ */ jsx(ChannelContentGrid, { ...props, variant: "portrait" }); case "landscapeGrid": return /* @__PURE__ */ jsx(ChannelContentGrid, { ...props, variant: "landscape" }); case "list": return /* @__PURE__ */ jsx(ChannelContentList, { ...props }); case "carousel": return /* @__PURE__ */ jsx(ChannelContentCarousel, { ...props, variant: "portrait" }); case "landscapeCarousel": return /* @__PURE__ */ jsx(ChannelContentCarousel, { ...props, variant: "landscape" }); case "slider": return /* @__PURE__ */ jsx(ChannelContentSlider, { ...props }); case "news": return /* @__PURE__ */ jsx(ChannelContentNews, { ...props }); default: return null; } } function NestedChannels({ channel, isNested }) { var _a; return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(ChannelHeader, { channel, isNested }), (_a = channel.content) == null ? void 0 : _a.data.map((nestedChannel) => /* @__PURE__ */ jsx("div", { className: "mb-40 md:mb-50", children: /* @__PURE__ */ jsx( ChannelContent, { channel: nestedChannel, isNested: true } ) }, nestedChannel.id)) ] }); } function useSearchResults(loader, query = "") { query = query.trim(); if (query === ".") { query = ""; } return useQuery({ queryKey: ["search", query, "loader"], queryFn: ({ signal }) => search(loader, query, signal), enabled: !!query, placeholderData: !!query ? keepPreviousData : void 0, initialData: () => { var _a; const data = (_a = getBootstrapData().loaders) == null ? void 0 : _a[loader]; if (query && (data == null ? void 0 : data.query) == query) { return data; } } }); } async function search(loader, query, signal) { await new Promise((resolve) => setTimeout(resolve, 300)); return apiClient.get(`search/${encodeURIComponent(query)}`, { params: { loader }, signal }).then((response) => response.data); } function SearchAutocomplete({ className: className2 }) { const { searchQuery } = useParams(); const { trans } = useTrans(); const navigate = useNavigate(); const [query, setQuery] = useState(searchQuery || ""); const [isOpen, setIsOpen] = useState(false); const { isFetching, data } = useSearchResults("searchAutocomplete", query); return /* @__PURE__ */ jsx( "form", { onSubmit: (e) => { e.preventDefault(); if (query.trim().length) { setIsOpen(false); navigate(`/search/${encodeURIComponent(query.trim())}`); } }, className: clsx( "flex max-w-580 flex-auto items-center rounded bg-chip/40 text", className2 ), children: /* @__PURE__ */ jsx( ComboBoxForwardRef, { size: "sm", startAdornment: /* @__PURE__ */ jsx("button", { type: "submit", "aria-label": trans(message("Search")), children: /* @__PURE__ */ jsx(SearchIcon, { className: "flex-shrink-0 text-muted" }) }), className: "w-full", offset: 6, inputClassName: "w-full outline-none text-sm placeholder:text-muted", isAsync: true, hideEndAdornment: true, placeholder: trans( message("Search for movies, tv shows and people...") ), isLoading: isFetching, inputValue: query, onInputValueChange: setQuery, clearInputOnItemSelection: true, blurReferenceOnItemSelection: true, selectionMode: "none", openMenuOnFocus: true, floatingMaxHeight: 670, isOpen, onOpenChange: setIsOpen, autoFocusFirstItem: false, children: data == null ? void 0 : data.results.map((result) => { switch (result.model_type) { case TITLE_MODEL: return /* @__PURE__ */ jsx( Item, { value: result.id, onSelected: () => { navigate(getTitleLink(result)); }, startIcon: /* @__PURE__ */ jsx(TitlePoster, { title: result, srcSize: "sm", size: "w-46" }), description: /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx("div", { className: "mb-4", children: result.year }), /* @__PURE__ */ jsx("div", { children: result.is_series ? /* @__PURE__ */ jsx(Trans, { message: "Tv series" }) : /* @__PURE__ */ jsx(Trans, { message: "Movie" }) }) ] }), textLabel: result.name, children: result.name }, result.id ); case PERSON_MODEL: return /* @__PURE__ */ jsx( Item, { value: result.id, onSelected: () => { navigate(getPersonLink(result)); }, startIcon: /* @__PURE__ */ jsx( PersonPoster, { person: result, srcSize: "sm", className: "w-56" } ), description: /* @__PURE__ */ jsx(KnownForCompact, { person: result }), textLabel: result.name, children: result.name }, result.id ); } }) } ) } ); } function MainNavbar({ position = "relative" }) { return /* @__PURE__ */ jsxs( Navbar, { size: "md", menuPosition: "primary", className: clsx(position, "z-40 w-full flex-shrink-0"), border: "border-none", alwaysDarkMode: true, children: [ /* @__PURE__ */ jsx(Tooltip, { label: /* @__PURE__ */ jsx(Trans, { message: "Search" }), children: /* @__PURE__ */ jsx(IconButton, { elementType: Link, to: "/search", className: "md:hidden", children: /* @__PURE__ */ jsx(SearchIcon, {}) }) }), /* @__PURE__ */ jsx(SearchAutocomplete, { className: "max-md:hidden" }) ] } ); } function AdHost({ slot, className: className2 }) { var _a; const settings = useSettings(); const { isSubscribed } = useAuth(); const adCode2 = useMemo(() => { return dot.pick(`ads.${slot}`, settings); }, [slot, settings]); if (((_a = settings.ads) == null ? void 0 : _a.disable) || isSubscribed || !adCode2) return null; return /* @__PURE__ */ jsx(InvariantAd, { className: className2, slot, adCode: adCode2 }); } const InvariantAd = memo( ({ slot, adCode: adCode2, className: className2 }) => { const ref = useRef(null); const id2 = useId(); useEffect(() => { if (ref.current) { loadAdScripts(adCode2, ref.current).then(() => { executeAdJavascript(adCode2, id2); }); } return () => { delete window["google_ad_modifications"]; }; }, [adCode2, id2]); useEffect(() => { if (ref.current) { const scrollParent = getScrollParent(ref.current); if (scrollParent) { const observer = new MutationObserver(function() { scrollParent.style.height = ""; scrollParent.style.minHeight = ""; }); observer.observe(scrollParent, { attributes: true, attributeFilter: ["style"] }); return () => observer.disconnect(); } } }, []); return /* @__PURE__ */ jsx( "div", { ref, id: id2, className: clsx( "ad-host flex max-h-[600px] min-h-90 w-full max-w-full items-center justify-center overflow-hidden", `${slot.replace(/\./g, "-")}-host`, className2 ), dangerouslySetInnerHTML: { __html: getAdHtml(adCode2) } } ); }, () => { return false; } ); function getAdHtml(adCode2) { return adCode2 == null ? void 0 : adCode2.replace(/)<[^<]*)*<\/script>/gi, "").trim(); } function loadAdScripts(adCode2, parentEl) { const promises = []; const pattern2 = /]*>([\s\S]*?)<\/script>/g; let content; while (content = pattern.exec(adCode)) { if (content[1]) { const r = `var d = document.createElement('div'); d.innerHTML = $1; document.getElementById('${id}').appendChild(d.firstChild);`; const toEval = content[1].replace(/document.write\((.+?)\);/, r); eval(toEval); } } } function SitePageLayout({ children }) { useScrollToTop(); return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [ /* @__PURE__ */ jsx(MainNavbar, {}), /* @__PURE__ */ jsxs("div", { className: "flex-auto", children: [ /* @__PURE__ */ jsx(AdHost, { slot: "general_top", className: "py-24" }), /* @__PURE__ */ jsx("div", { className: "relative min-h-[1000px] overflow-hidden", children }), /* @__PURE__ */ jsx(AdHost, { slot: "general_bottom", className: "py-24" }) ] }), /* @__PURE__ */ jsx(Footer, { className: "container mx-auto mt-48 flex-shrink-0 px-24" }) ] }); } function ChannelPage({ slugOrId, type = "channel" }) { const query = useChannel(slugOrId, "channelPage", { channelType: type }); let content2 = null; if (query.data) { content2 = /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx("div", { className: "pb-24", children: /* @__PURE__ */ jsx("div", { className: "container mx-auto p-14 @container md:p-24", children: /* @__PURE__ */ jsx( ChannelContent, { channel: query.data.channel, isNested: false }, query.data.channel.id ) }) }) ] }); } else { content2 = /* @__PURE__ */ jsx( PageStatus, { query, loaderClassName: "absolute inset-0 m-auto", loaderIsScreen: false } ); } return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function TitlePageImageGrid({ images, count, heading, srcSize }) { const isMobile = useIsMobileMediaQuery(); const { trans } = useTrans(); if (!(images == null ? void 0 : images.length)) return null; if (!count) { count = isMobile ? 6 : 5; } return /* @__PURE__ */ jsxs("div", { className: "mt-48", children: [ heading, /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-12 md:grid-cols-5 md:gap-24", children: images.slice(0, count).map((image, index) => /* @__PURE__ */ jsxs(DialogTrigger, { type: "modal", children: [ /* @__PURE__ */ jsx( ButtonBase, { "aria-label": trans(message("Image :index", { values: { index } })), children: /* @__PURE__ */ jsx(ImageItem, { image, srcSize }) } ), /* @__PURE__ */ jsx( ImageZoomDialog, { images: images.map((img) => img.url), defaultActiveIndex: index } ) ] }, image.id)) }) ] }); } function ImageItem({ image, srcSize = "md" }) { const src = useImageSrc(image.url, { size: srcSize }); return /* @__PURE__ */ jsx( "img", { className: "aspect-square w-full cursor-pointer rounded object-cover", src, alt: "" } ); } function TitleCreditsGrid({ credits, className: className2 }) { if (!credits.length) { return /* @__PURE__ */ jsx("div", { className: "text-muted italic", children: /* @__PURE__ */ jsx(Trans, { message: "We've no cast information for this title yet." }) }); } return /* @__PURE__ */ jsx( "div", { className: clsx("grid gap-14 md:gap-20 title-credits-grid", className2), children: credits.map((credit) => /* @__PURE__ */ jsxs( "div", { className: "flex items-center gap-14 md:gap-20", children: [ /* @__PURE__ */ jsx( PersonPoster, { rounded: true, person: credit, size: "w-70 md:w-96", srcSize: "md" } ), /* @__PURE__ */ jsxs("div", { className: "max-md:text-sm", children: [ /* @__PURE__ */ jsx(PersonLink, { className: "block font-bold", person: credit }), /* @__PURE__ */ jsx("div", { className: "text-muted", children: /* @__PURE__ */ jsx(Description, { credit }) }) ] }) ] }, credit.pivot.id )) } ); } function Description({ credit }) { if (credit.pivot.department === "actors") { return /* @__PURE__ */ jsx(Fragment, { children: credit.pivot.character }); } return /* @__PURE__ */ jsx("span", { className: "capitalize", children: /* @__PURE__ */ jsx(Trans, { message: credit.pivot.job }) }); } function TitlePageCast({ credits = [] }) { const cast = credits.filter((credit) => credit.pivot.department === "actors"); return /* @__PURE__ */ jsxs("div", { className: "mt-48", children: [ /* @__PURE__ */ jsx(SiteSectionHeading, { children: /* @__PURE__ */ jsx(Trans, { message: "Cast" }) }), /* @__PURE__ */ jsx(TitleCreditsGrid, { credits: cast }), /* @__PURE__ */ jsx( Button, { className: "mt-24", variant: "outline", color: "primary", elementType: Link, to: "full-credits", endIcon: /* @__PURE__ */ jsx(ArrowForwardIcon, {}), children: /* @__PURE__ */ jsx(Trans, { message: "All cast and crew" }) } ) ] }); } function useRelatedTitles(titleId) { return useQuery({ queryKey: ["titles", titleId, "related"], queryFn: () => fetchRelatedTitles(titleId) }); } function fetchRelatedTitles(titleId) { return apiClient.get(`titles/${titleId}/related`).then((response) => response.data); } function RelatedTitlesPanel({ title }) { const { data } = useRelatedTitles(title.id); if (!data || data.titles.length === 0) { return null; } return /* @__PURE__ */ jsx(RelatedTitlesCarousel, { titles: data.titles }); } function RelatedTitlesCarousel({ titles }) { const { scrollContainerRef, canScrollForward, canScrollBackward, scrollToPreviousPage, scrollToNextPage, containerClassName: containerClassName2, itemClassName: itemClassName2 } = useCarousel(); return /* @__PURE__ */ jsxs("div", { className: "mt-48", children: [ /* @__PURE__ */ jsx( SiteSectionHeading, { actions: /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( IconButton, { disabled: !canScrollBackward, onClick: () => scrollToPreviousPage(), "aria-label": "Scroll left", children: /* @__PURE__ */ jsx(KeyboardArrowLeftIcon, {}) } ), /* @__PURE__ */ jsx( IconButton, { disabled: !canScrollForward, onClick: () => scrollToNextPage(), "aria-label": "Scroll right", children: /* @__PURE__ */ jsx(KeyboardArrowRightIcon, {}) } ) ] }), children: /* @__PURE__ */ jsx(Trans, { message: "More like this" }) } ), /* @__PURE__ */ jsx( "div", { ref: scrollContainerRef, className: clsx(containerClassName2, "content-grid-portrait"), children: titles.map((item) => /* @__PURE__ */ jsx("div", { className: itemClassName2, children: /* @__PURE__ */ jsx(TitlePortraitGridItem, { item }) }, item.id)) } ) ] }); } function TitlePageSeasonGrid({ data: { title, seasons } }) { const query = useTitleSeasons(title.id, seasons); return /* @__PURE__ */ jsxs("div", { className: "mt-48", children: [ /* @__PURE__ */ jsx( SiteSectionHeading, { titleAppend: (seasons == null ? void 0 : seasons.total) ? `(${seasons.total})` : void 0, children: /* @__PURE__ */ jsx(Trans, { message: "Seasons" }) } ), /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-14 sm:grid-cols-6 lg:grid-cols-8", children: query.items.map((season) => /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx( SeasonPoster, { title, season, srcSize: "sm", className: "aspect-poster flex-shrink-0" } ), /* @__PURE__ */ jsxs("div", { className: "mt-4", children: [ /* @__PURE__ */ jsx( SeasonLink, { className: "text-sm", title, seasonNumber: season.number, color: "primary" } ), /* @__PURE__ */ jsx("div", { className: "text-xs text-muted", children: /* @__PURE__ */ jsx( FormattedDate, { date: season.release_date, options: { year: "numeric" } } ) }) ] }) ] }, season.id)) }), /* @__PURE__ */ jsx( InfiniteScrollSentinel, { query, variant: "loadMore", loaderMarginTop: "mt-14", size: "sm" } ) ] }) ] }); } const CompactCredits = memo(({ credits = {} }) => { var _a, _b, _c, _d; return /* @__PURE__ */ jsxs("div", { className: "mt-16 flex flex-col gap-14 border-t pt-16", children: [ ((_a = credits.creators) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsx(PeopleDetail, { label: /* @__PURE__ */ jsx(Trans, { message: "Created by" }), children: /* @__PURE__ */ jsx(BulletSeparatedItems, { className: "hidden-scrollbar overflow-x-auto", children: credits.creators.slice(0, 3).map((creator) => /* @__PURE__ */ jsx( PersonLink, { person: creator, color: "primary", className: "whitespace-nowrap" }, creator.id )) }) }) : null, ((_b = credits.directing) == null ? void 0 : _b.length) ? /* @__PURE__ */ jsx( PeopleDetail, { label: /* @__PURE__ */ jsx( Trans, { message: "[one Director|other Directors]", values: { count: credits.directing.length } } ), children: /* @__PURE__ */ jsx(BulletSeparatedItems, { className: "hidden-scrollbar overflow-x-auto", children: credits.directing.slice(0, 3).map((director) => /* @__PURE__ */ jsx( PersonLink, { person: director, color: "primary", className: "whitespace-nowrap" }, director.id )) }) } ) : null, ((_c = credits.writing) == null ? void 0 : _c.length) ? /* @__PURE__ */ jsx( PeopleDetail, { label: /* @__PURE__ */ jsx( Trans, { message: "[one Writer|other Writers]", values: { count: credits.writing.length } } ), children: /* @__PURE__ */ jsx(BulletSeparatedItems, { className: "hidden-scrollbar overflow-x-auto", children: credits.writing.slice(0, 3).map((writer) => /* @__PURE__ */ jsx( PersonLink, { person: writer, color: "primary", className: "whitespace-nowrap" }, writer.id )) }) } ) : null, ((_d = credits.actors) == null ? void 0 : _d.length) ? /* @__PURE__ */ jsx(PeopleDetail, { label: /* @__PURE__ */ jsx(Trans, { message: "Stars" }), children: /* @__PURE__ */ jsx(BulletSeparatedItems, { className: "hidden-scrollbar overflow-x-auto", children: credits.actors.slice(0, 3).map((actor) => /* @__PURE__ */ jsx( PersonLink, { person: actor, color: "primary", className: "whitespace-nowrap" }, actor.id )) }) }) : null ] }); }); function PeopleDetail({ label, children }) { return /* @__PURE__ */ jsxs("div", { className: "flex-shrink-0 gap-24 md:flex", children: [ /* @__PURE__ */ jsx("div", { className: "min-w-84 font-bold", children: label }), /* @__PURE__ */ jsx("div", { children }) ] }); } function getGenreLink(genre, { absolute } = {}) { return getBaseMediaLink(`/genre/${genre.name}`, { absolute }); } function useTitleNews(titleId) { return useQuery({ queryKey: ["titles", `${titleId}`, "news"], queryFn: () => fetchNews(titleId) }); } function fetchNews(titleId) { return apiClient.get(`titles/${titleId}/news`).then((response) => response.data); } function TitleNews({ title }) { const { data, isLoading } = useTitleNews(title.id); if (!isLoading && !(data == null ? void 0 : data.news_articles.length)) { return null; } return /* @__PURE__ */ jsxs("section", { className: "mt-48", children: [ /* @__PURE__ */ jsx(SiteSectionHeading, { children: /* @__PURE__ */ jsx(Trans, { message: "Related news" }) }), /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-24", children: data == null ? void 0 : data.news_articles.map((article) => /* @__PURE__ */ jsx(NewsArticleGridItem, { article }, article.id)) }) ] }); } function useLinkifiedString(text) { return useMemo(() => { if (!text) { return text; } return linkifyStr(text, { nl2br: true, attributes: { rel: "nofollow" } }); }, [text]); } function TruncatedDescription({ description, className: className2 }) { const linkifiedDescription = useLinkifiedString(description); const wrapperRef = useRef(null); const contentRef = useRef(null); const [isOverflowing, setIsOverflowing] = useState(false); const [isShowingAll, setIsShowingAll] = useState(false); useLayoutEffect(() => { var _a, _b; const wrapperHeight = ((_a = wrapperRef.current) == null ? void 0 : _a.getBoundingClientRect().height) || 0; const contentHeight = ((_b = wrapperRef.current) == null ? void 0 : _b.scrollHeight) || 0; if (contentHeight > wrapperHeight) { setIsOverflowing(true); } }, []); if (!linkifiedDescription) return null; return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( "div", { ref: wrapperRef, className: clsx( "relative", className2, !isShowingAll && "max-h-160 overflow-hidden", !isShowingAll && isOverflowing && "after:absolute after:bottom-0 after:left-0 after:h-20 after:w-full after:bg-gradient-to-b after:from-transparent after:to-background" ), children: /* @__PURE__ */ jsx( "div", { ref: contentRef, dangerouslySetInnerHTML: { __html: linkifiedDescription } } ) } ), isOverflowing && /* @__PURE__ */ jsx( Button, { size: "xs", className: "mt-20", variant: "outline", onClick: () => setIsShowingAll(!isShowingAll), children: isShowingAll ? /* @__PURE__ */ jsx(Trans, { message: "Show less" }) : /* @__PURE__ */ jsx(Trans, { message: "Show more" }) } ) ] }); } const NewReviewForm = forwardRef( ({ reviewable, currentReview, className: className2, disabled }, ref) => { const [isExpanded, setIsExpanded] = useState(false); const { user } = useAuth(); const form = useForm({ defaultValues: { score: 8 } }); useEffect(() => { if (currentReview) { form.setValue("title", currentReview.title); form.setValue("body", currentReview.body); form.setValue("score", currentReview.score); } }, [form, currentReview]); const openReviewPanel = useCallback(() => { setIsExpanded(true); }, []); useImperativeHandle( ref, () => ({ openReviewPanel }), [openReviewPanel] ); const createReview = useCreateReview(form); return /* @__PURE__ */ jsxs( Form, { className: clsx("rounded border bg-alt p-14", className2), form, onSubmit: (newValues) => { if (disabled) return; createReview.mutate( { ...newValues, reviewable }, { onSuccess: () => { toast(message("Review posted")); setIsExpanded(false); } } ); }, children: [ /* @__PURE__ */ jsxs("div", { className: "items-center gap-24 lg:flex", children: [ /* @__PURE__ */ jsx( Avatar, { size: "xl", circle: true, src: user == null ? void 0 : user.avatar, label: user == null ? void 0 : user.display_name } ), /* @__PURE__ */ jsxs("div", { className: "flex-auto", children: [ /* @__PURE__ */ jsx("div", { className: "mb-4 text-xs text-muted max-md:mt-10", children: /* @__PURE__ */ jsx( Trans, { message: "Review as :name", values: { name: /* @__PURE__ */ jsx("span", { className: "font-medium text", children: user == null ? void 0 : user.display_name }) } } ) }), /* @__PURE__ */ jsx( StarSelector, { readonly: disabled, className: "-ml-8 max-lg:mb-12", count: 10, value: disabled ? 0 : form.watch("score"), onValueChange: (newScore) => { form.setValue("score", newScore); } } ) ] }), !isExpanded && /* @__PURE__ */ jsx( Button, { variant: "flat", color: "primary", onClick: () => openReviewPanel(), disabled: !user || disabled, children: currentReview ? /* @__PURE__ */ jsx(Trans, { message: "Update review" }) : /* @__PURE__ */ jsx(Trans, { message: "Add review" }) } ) ] }), isExpanded && /* @__PURE__ */ jsxs("div", { className: "mt-24", children: [ /* @__PURE__ */ jsx( FormTextField, { name: "title", className: "mb-24", label: /* @__PURE__ */ jsx(Trans, { message: "Title" }), labelSuffix: /* @__PURE__ */ jsx(Trans, { message: "10 character minimum" }), autoFocus: true, minLength: 10, required: true } ), /* @__PURE__ */ jsx( FormTextField, { name: "body", label: /* @__PURE__ */ jsx(Trans, { message: "Review" }), labelSuffix: /* @__PURE__ */ jsx(Trans, { message: "100 character minimum" }), inputElementType: "textarea", rows: 5, minLength: 100, required: true } ), /* @__PURE__ */ jsxs("div", { className: "mt-16 flex items-center justify-end gap-8", children: [ /* @__PURE__ */ jsx( Button, { variant: "outline", className: "min-w-100", onClick: () => { setIsExpanded(false); form.reset(currentReview); }, children: /* @__PURE__ */ jsx(Trans, { message: "Cancel" }) } ), /* @__PURE__ */ jsx( Button, { type: "submit", variant: "flat", color: "primary", className: "min-w-100", disabled: createReview.isPending, children: /* @__PURE__ */ jsx(Trans, { message: "Post" }) } ) ] }) ] }) ] } ); } ); function useSubmitReviewFeedback(review) { return useMutation({ mutationFn: (payload) => submitFeedback(payload, review), onSuccess: () => { toast(message("Feedback submitted")); }, onError: (r2) => showHttpErrorToast(r2) }); } function submitFeedback(payload, review) { return apiClient.post(`reviews/${review.id}/feedback`, { is_helpful: payload.isHelpful }).then((r2) => r2.data); } function useSubmitReport(model) { return useMutation({ mutationFn: (payload) => submitReport(model, payload), onSuccess: () => { toast(message("Thanks for reporting. We will review this content.")); }, onError: (err) => showHttpErrorToast(err) }); } function submitReport(model, payload) { return apiClient.post("report", { reason: payload.reason, model_id: model.id, model_type: model.model_type }).then((r2) => r2.data); } function useDeleteReport(model) { return useMutation({ mutationFn: () => deleteReport(model), onSuccess: () => { toast(message("Report removed")); }, onError: (err) => showHttpErrorToast(err) }); } function deleteReport(reportable) { return apiClient.delete(`report/${reportable.model_type}/${reportable.id}`).then((r2) => r2.data); } function ReviewListItem$1({ review, isShared, hideShareButton, avatar }) { const isMobile = useIsMobileMediaQuery(); const ref = useRef(null); const scrolled = useRef(false); useEffect(() => { if (isShared && !scrolled.current) { setTimeout(() => { var _a; (_a = ref.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" }); scrolled.current = true; }, 50); } }, [isShared]); return /* @__PURE__ */ jsxs("div", { ref, children: [ isShared && /* @__PURE__ */ jsx("div", { className: "mb-8 mt-16 text-sm", children: /* @__PURE__ */ jsx(Trans, { message: "Shared review" }) }), /* @__PURE__ */ jsxs( "div", { className: clsx( "group flex min-h-70 items-start gap-24 rounded py-18", isShared && "mb-34 border bg-alt pl-12" ), children: [ !isMobile && (avatar || /* @__PURE__ */ jsx(UserAvatar, { user: review.user, size: "xl", circle: true })), /* @__PURE__ */ jsxs("div", { className: "flex-auto text-sm", children: [ /* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-center gap-8", children: [ review.user && /* @__PURE__ */ jsx(UserDisplayName$1, { user: review.user }), /* @__PURE__ */ jsx("time", { className: "text-xs text-muted", children: /* @__PURE__ */ jsx(FormattedRelativeTime, { date: review.created_at }) }) ] }), /* @__PURE__ */ jsx(TitleRating, { className: "mb-8 mt-10", score: review.score }), review.title && /* @__PURE__ */ jsx("div", { className: "mb-8 text-base font-medium", children: review.title }), /* @__PURE__ */ jsx("div", { className: "whitespace-break-spaces text-sm", children: review.body }), /* @__PURE__ */ jsxs("div", { className: "mt-16 items-center gap-8 md:flex", children: [ /* @__PURE__ */ jsx(Feedback, { review }), !hideShareButton && /* @__PURE__ */ jsx(ShareButton$3, { review }), /* @__PURE__ */ jsx(ReviewOptionsTrigger, { review }) ] }) ] }) ] } ) ] }); } function ShareButton$3({ review }) { const { base_url } = useSettings(); const location = useLocation(); const url = `${base_url}${location.pathname}?reviewId=${review.id}`; const [, copyLink] = useClipboard(url); return /* @__PURE__ */ jsx(Tooltip, { label: /* @__PURE__ */ jsx(Trans, { message: "Share" }), children: /* @__PURE__ */ jsx( IconButton, { className: "text-muted", onClick: () => { copyLink(); toast(message("Review link copied to clipboard")); }, children: /* @__PURE__ */ jsx(ShareIcon, {}) } ) }); } function Feedback({ review }) { const { user } = useAuth(); const authHandler = useAuthClickCapture(); const submitFeedback2 = useSubmitReviewFeedback(review); const isDisabled = submitFeedback2.isPending || user != null && user.id === review.user_id; const [helpfulCount, setHelpfulCount] = useState(review.helpful_count || 1); const [total, setTotal] = useState( review.helpful_count + review.not_helpful_count || 1 ); let initialFeedback; if (review.current_user_feedback != null) { initialFeedback = review.current_user_feedback ? "helpful" : "not_helpful"; } const [currentFeedback, setCurrentFeedback] = useState( initialFeedback ); return /* @__PURE__ */ jsxs("div", { className: "mr-auto flex flex-wrap items-center gap-6 max-md:mb-12", children: [ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted", children: /* @__PURE__ */ jsx( Trans, { message: ":helpfulCount out of :total people found this helpful. Was this review helpful?", values: { helpfulCount, total } } ) }), /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-6 pb-2", children: [ /* @__PURE__ */ jsx( Button, { variant: "link", className: clsx( "uppercase", currentFeedback === "helpful" && "pointer-events-none" ), color: currentFeedback === "helpful" ? "primary" : void 0, disabled: isDisabled, onClickCapture: authHandler, onClick: () => submitFeedback2.mutate( { isHelpful: true }, { onSuccess: () => { setHelpfulCount((count) => count + 1); setCurrentFeedback("helpful"); if (!currentFeedback) { setTotal((count) => count + 1); } } } ), children: /* @__PURE__ */ jsx(Trans, { message: "Yes" }) } ), /* @__PURE__ */ jsx("div", { className: "h-14 w-1 bg-divider" }), /* @__PURE__ */ jsx( Button, { variant: "link", className: clsx( "uppercase", currentFeedback === "not_helpful" && "pointer-events-none" ), color: currentFeedback === "not_helpful" ? "primary" : void 0, disabled: isDisabled, onClickCapture: authHandler, onClick: () => submitFeedback2.mutate( { isHelpful: false }, { onSuccess: () => { setHelpfulCount((count) => count - 1); setCurrentFeedback("not_helpful"); if (!currentFeedback) { setTotal((count) => count + 1); } } } ), children: /* @__PURE__ */ jsx(Trans, { message: "No" }) } ) ] }) ] }); } function ReviewOptionsTrigger({ review }) { const { user, hasPermission } = useAuth(); const report = useSubmitReport(review); const deleteReport2 = useDeleteReport(review); const [isReported, setIsReported] = useState(review.current_user_reported); const handleReport = () => { if (isReported) { deleteReport2.mutate(void 0, { onSuccess: () => setIsReported(false) }); } else { report.mutate({}, { onSuccess: () => setIsReported(true) }); } }; const deleteReview = useDeleteReviews(); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const showDeleteButton = user && review.user_id === user.id || hasPermission("reviews.delete"); const handleDelete = (isConfirmed) => { setIsDeleteDialogOpen(false); if (isConfirmed) { deleteReview.mutate({ reviewIds: [review.id] }); } }; return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsxs(MenuTrigger, { children: [ /* @__PURE__ */ jsx(IconButton, { className: "text-muted", "aria-label": "More options", children: /* @__PURE__ */ jsx(MoreVertIcon, {}) }), /* @__PURE__ */ jsxs(Menu, { children: [ /* @__PURE__ */ jsx(Item, { value: "report", onSelected: () => handleReport(), children: isReported ? /* @__PURE__ */ jsx(Trans, { message: "Remove report" }) : /* @__PURE__ */ jsx(Trans, { message: "Report review" }) }), showDeleteButton && /* @__PURE__ */ jsx( Item, { value: "delete", onSelected: () => setIsDeleteDialogOpen(true), children: /* @__PURE__ */ jsx(Trans, { message: "Delete" }) } ) ] }) ] }), /* @__PURE__ */ jsx( DialogTrigger, { type: "modal", isOpen: isDeleteDialogOpen, onClose: (isConfirmed) => handleDelete(isConfirmed), children: /* @__PURE__ */ jsx( ConfirmationDialog, { isDanger: true, title: /* @__PURE__ */ jsx(Trans, { message: "Delete review?" }), body: /* @__PURE__ */ jsx(Trans, { message: "Are you sure you want to delete this review?" }), confirm: /* @__PURE__ */ jsx(Trans, { message: "Delete" }) } ) } ) ] }); } function UserDisplayName$1({ user }) { const isMobile = useIsMobileMediaQuery(); const { auth } = useContext(SiteConfigContext); const sharedClassName = "flex items-center gap-8 text-base font-medium"; if (auth.getUserProfileLink) { return /* @__PURE__ */ jsxs(Fragment, { children: [ isMobile && /* @__PURE__ */ jsx(UserAvatar, { user, size: "sm", circle: true }), /* @__PURE__ */ jsx( Link, { to: auth.getUserProfileLink(user), className: clsx("hover:underline", sharedClassName), children: user.display_name } ) ] }); } return /* @__PURE__ */ jsxs("div", { className: sharedClassName, children: [ isMobile && /* @__PURE__ */ jsx(UserAvatar, { user, size: "sm", circle: true }), user.display_name ] }); } function AccountRequiredCard({ message: message2 }) { const { user } = useAuth(); if (user) return null; return /* @__PURE__ */ jsxs("div", { className: "border border-dashed py-30 px-20 my-40 mx-auto text-center max-w-850 rounded", children: [ /* @__PURE__ */ jsx("div", { className: "text-xl font-semibold mb-8", children: /* @__PURE__ */ jsx(Trans, { message: "Account required" }) }), /* @__PURE__ */ jsx("div", { className: "text-muted text-base", children: /* @__PURE__ */ jsx( Trans, { ...message2, values: { l: (parts) => /* @__PURE__ */ jsx(Link, { className: LinkStyle, to: "/login", children: parts }), r: (parts) => /* @__PURE__ */ jsx(Link, { className: LinkStyle, to: "/register", children: parts }) } } ) }) ] }); } const accountRequiredMessage$1 = message( "Please login or create account to add a review" ); function ReviewList({ reviewable, disabled, noResultsMessage, showAccountRequiredMessage }) { var _a, _b; const query = useReviews(reviewable); const actionsRef = useRef(null); const { user } = useAuth(); const currentUserReview = (_a = query.data) == null ? void 0 : _a.pages[0].current_user_review; const sharedReview = (_b = query.data) == null ? void 0 : _b.pages[0].shared_review; return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx( NewReviewForm, { className: "mb-14 md:-mx-14", reviewable, currentReview: currentUserReview, ref: actionsRef, disabled } ), /* @__PURE__ */ jsxs("div", { children: [ showAccountRequiredMessage && /* @__PURE__ */ jsx(AccountRequiredCard, { message: accountRequiredMessage$1 }), /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: query.isLoading ? /* @__PURE__ */ jsx(ReviewListSkeletons, { count: 4 }) : /* @__PURE__ */ jsx( ReviewListItems, { reviews: query.items, sharedReview, noResultsMessage } ) }), /* @__PURE__ */ jsx("div", { className: "ml-84", children: /* @__PURE__ */ jsx( InfiniteScrollSentinel, { query, variant: "loadMore", loaderMarginTop: "mt-14", loadMoreExtraContent: /* @__PURE__ */ jsx( Button, { variant: "flat", color: "primary", disabled: !user, onClick: () => { var _a2; (_a2 = actionsRef.current) == null ? void 0 : _a2.openReviewPanel(); }, children: /* @__PURE__ */ jsx(Trans, { message: "Add a review" }) } ) } ) }) ] }) ] }); } function ReviewListItems({ reviews, sharedReview, noResultsMessage }) { const { user } = useAuth(); let content2; if (!reviews.length) { content2 = user ? noResultsMessage || /* @__PURE__ */ jsx( IllustratedMessage, { className: "mt-24", size: "sm", title: /* @__PURE__ */ jsx(Trans, { message: "Seems a little quiet over here" }), description: /* @__PURE__ */ jsx(Trans, { message: "Be the first to leave a review" }) } ) : null; } else { content2 = reviews.map((review) => /* @__PURE__ */ jsx(ReviewListItem$1, { review }, review.id)); } return /* @__PURE__ */ jsxs(m.div, { ...opacityAnimation, children: [ sharedReview && /* @__PURE__ */ jsx(ReviewListItem$1, { review: sharedReview, isShared: true }), content2 ] }, "reviews"); } function ReviewListSkeletons({ count }) { return /* @__PURE__ */ jsx(m.div, { ...opacityAnimation, children: [...new Array(count).keys()].map((index) => /* @__PURE__ */ jsxs( "div", { className: "flex items-start gap-24 py-18 min-h-[212px] group", children: [ /* @__PURE__ */ jsx(Skeleton, { variant: "avatar", radius: "rounded-full", size: "w-60 h-60" }), /* @__PURE__ */ jsxs("div", { className: "flex-auto text-sm", children: [ /* @__PURE__ */ jsx( Skeleton, { className: "text-base font-medium max-w-200 mb-4", variant: "text" } ), /* @__PURE__ */ jsx(Skeleton, { variant: "text", className: "max-w-60 mb-8 mt-10 text-lg" }), /* @__PURE__ */ jsx(Skeleton, { variant: "text", className: "mb-8 text-base max-w-240" }), /* @__PURE__ */ jsx(Skeleton, { className: "text-sm", variant: "text" }), /* @__PURE__ */ jsx(Skeleton, { className: "text-sm", variant: "text" }), /* @__PURE__ */ jsx(Skeleton, { className: "text-xs mt-16", variant: "text" }) ] }) ] }, index )) }, "loading-skeleton"); } function TitlePageReviewList({ title }) { const [sort, setSort] = useLocalStorage( `reviewSort.${title.model_type}`, "created_at:desc" ); const query = useReviews(title); return /* @__PURE__ */ jsxs("div", { className: "mt-48", children: [ /* @__PURE__ */ jsx( SiteSectionHeading, { titleAppend: query.totalItems ? /* @__PURE__ */ jsxs("span", { children: [ "(", query.totalItems, ")" ] }) : null, actions: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-24", children: [ /* @__PURE__ */ jsx(TitleRating, { score: title.rating, className: "max-md:hidden" }), /* @__PURE__ */ jsx( ReviewListSortButton, { value: sort, onValueChange: (newValue) => setSort(newValue) } ) ] }), children: /* @__PURE__ */ jsx(Trans, { message: "Reviews" }) } ), /* @__PURE__ */ jsx( ReviewList, { reviewable: title, showAccountRequiredMessage: title.status !== "upcoming", noResultsMessage: title.status === "upcoming" ? /* @__PURE__ */ jsx( IllustratedMessage, { className: "mt-24", size: "sm", title: /* @__PURE__ */ jsx(Trans, { message: "This title is not released yet" }), description: /* @__PURE__ */ jsx( Trans, { message: "Come back after :date to see the reviews", values: { date: /* @__PURE__ */ jsx(FormattedDate, { date: title.release_date }) } } ) } ) : void 0 } ) ] }); } function TitlePageVideoGrid({ title, episode }) { const videos = episode ? episode.videos : title.videos; const link = episode ? `${getEpisodeLink( title, episode.season_number, episode.episode_number )}/episodes/${episode.id}/videos` : `${getTitleLink(title)}/videos`; return /* @__PURE__ */ jsx( VideoGrid, { videos, title, episode, heading: /* @__PURE__ */ jsx(SiteSectionHeading, { link, children: /* @__PURE__ */ jsx(Trans, { message: "Videos" }) }) } ); } function TitlePageEpisodeGrid({ data, label, showSeasonSelector }) { const { season } = useParams(); const [selectedSeason, setSelectedSeason] = useState( season ? parseInt(season) : 1 ); const query = useSeasonEpisodes( data.episodes, { perPage: 21, excludeDescription: "true" }, { season: selectedSeason, willSortOrFilter: true, defaultOrderBy: "episode_number", defaultOrderDir: "asc", titleId: data.title.id } ); const { isInitialLoading, items, sortDescriptor, setSortDescriptor } = query; return /* @__PURE__ */ jsxs("div", { className: "mt-48", children: [ /* @__PURE__ */ jsx( SiteSectionHeading, { actions: /* @__PURE__ */ jsxs(Fragment, { children: [ showSeasonSelector && /* @__PURE__ */ jsx( SeasonSelector, { selectedSeason, onSeasonChange: setSelectedSeason, seasonCount: data.title.seasons_count } ), /* @__PURE__ */ jsx( SortButton, { value: `${sortDescriptor.orderBy}:${sortDescriptor == null ? void 0 : sortDescriptor.orderDir}`, onValueChange: (value) => { const [orderBy, orderDir] = value.split(":"); setSortDescriptor({ orderBy, orderDir }); } } ) ] }), children: label || /* @__PURE__ */ jsx(Trans, { message: "Episodes" }) } ), /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: isInitialLoading ? /* @__PURE__ */ jsx(SkeletonGrid, {}) : /* @__PURE__ */ jsx(EpisodeGrid, { episodes: items, title: data.title, query }) }) ] }); } function GridItem({ episode, title }) { const runtime = episode.runtime || title.runtime; const name = /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(CompactSeasonEpisode, { className: "uppercase", episode }), " -", " ", episode.name ] }); return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx("div", { className: "relative", children: /* @__PURE__ */ jsx( EpisodePoster, { episode, title, srcSize: "md", showPlayButton: true, rightAction: runtime ? /* @__PURE__ */ jsx("span", { className: "rounded bg-black/50 p-4 text-xs font-medium text-white", children: /* @__PURE__ */ jsx(FormattedDuration, { minutes: runtime, verbose: true }) }) : null } ) }), /* @__PURE__ */ jsxs("div", { className: "mt-10", children: [ episode.release_date && /* @__PURE__ */ jsx("div", { className: "mb-2 text-sm text-muted", children: /* @__PURE__ */ jsx(FormattedDate, { date: episode.release_date }) }), /* @__PURE__ */ jsx("div", { className: "overflow-hidden overflow-ellipsis whitespace-nowrap text-base", children: episode.primary_video ? /* @__PURE__ */ jsx( Link, { className: "rounded outline-none hover:underline focus-visible:ring focus-visible:ring-offset-2", to: getWatchLink(episode.primary_video), children: name } ) : name }) ] }) ] }); } function EpisodeGrid({ title, episodes, query }) { return /* @__PURE__ */ jsxs(m.div, { ...opacityAnimation, children: [ /* @__PURE__ */ jsx(ContentGridLayout, { variant: "landscape", children: episodes.map((episode) => /* @__PURE__ */ jsx(GridItem, { episode, title }, episode.id)) }), /* @__PURE__ */ jsx( InfiniteScrollSentinel, { query, variant: "loadMore", size: "sm", loaderMarginTop: "mt-16" } ) ] }, "episode-grid"); } function SkeletonGrid() { return /* @__PURE__ */ jsx(m.div, { ...opacityAnimation, children: /* @__PURE__ */ jsx(ContentGridLayout, { variant: "landscape", children: [...new Array(6).keys()].map((number) => /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(Skeleton, { variant: "rect", size: "aspect-video", animation: "pulsate" }), /* @__PURE__ */ jsxs("div", { className: "mt-10 min-h-44", children: [ /* @__PURE__ */ jsx(Skeleton, { variant: "text" }), /* @__PURE__ */ jsx(Skeleton, { variant: "text" }) ] }) ] }, number)) }) }, "episode-grid"); } function SeasonSelector({ selectedSeason, onSeasonChange, seasonCount }) { return /* @__PURE__ */ jsxs( MenuTrigger, { selectedValue: selectedSeason, onSelectionChange: (newValue) => onSeasonChange(newValue), selectionMode: "single", children: [ /* @__PURE__ */ jsx(Button, { variant: "outline", startIcon: /* @__PURE__ */ jsx(ExpandMoreIcon, {}), className: "mr-4", children: /* @__PURE__ */ jsx(Trans, { message: "Season :number", values: { number: selectedSeason } }) }), /* @__PURE__ */ jsx(Menu, { children: [...new Array(seasonCount).keys()].map((number) => { const seasonNumber = number + 1; return /* @__PURE__ */ jsx(Item, { value: seasonNumber, children: /* @__PURE__ */ jsx(Trans, { message: "Season :number", values: { number: seasonNumber } }) }, seasonNumber); }) }) ] } ); } const SortOptions = [ { value: "episode_number:desc", label: message("Newest") }, { value: "episode_number:asc", label: message("Oldest") } ]; function SortButton({ value, onValueChange }) { let selectedOption = SortOptions.find((option) => option.value === value); if (!selectedOption) { selectedOption = SortOptions[0]; } return /* @__PURE__ */ jsxs( MenuTrigger, { selectedValue: value, onSelectionChange: (newValue) => onValueChange(newValue), selectionMode: "single", children: [ /* @__PURE__ */ jsx(Button, { variant: "outline", startIcon: /* @__PURE__ */ jsx(SortIcon, {}), children: /* @__PURE__ */ jsx(Trans, { ...selectedOption.label }) }), /* @__PURE__ */ jsx(Menu, { children: SortOptions.map((option) => /* @__PURE__ */ jsx(Item, { value: option.value, children: /* @__PURE__ */ jsx(Trans, { ...option.label }) }, option.value)) }) ] } ); } function TitlePageMainContent({ data, className: className2 }) { var _a, _b; const { title, credits } = data; const { title_page } = useSettings(); return /* @__PURE__ */ jsxs("main", { className: clsx(className2, "@container"), children: [ ((_a = title.genres) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsx(ChipList, { children: title.genres.map((genre) => /* @__PURE__ */ jsx( Chip, { className: "capitalize", elementType: Link, to: getGenreLink(genre), children: /* @__PURE__ */ jsx(Trans, { message: genre.display_name || genre.name }) }, genre.id )) }) : null, title.tagline && /* @__PURE__ */ jsxs("blockquote", { className: "mt-16", children: [ "“", title.tagline, "”" ] }), /* @__PURE__ */ jsx(TruncatedDescription, { className: "mt-16", description: title.description }), /* @__PURE__ */ jsx(CompactCredits, { credits }), /* @__PURE__ */ jsx(AdHost, { slot: "title_top", className: "pt-48" }), (_b = title_page == null ? void 0 : title_page.sections) == null ? void 0 : _b.map((name) => /* @__PURE__ */ jsx(TitlePageSection, { name, title, data }, name)) ] }); } function TitlePageSection({ name, title, data }) { var _a; const { titles } = useSettings(); const { hasPermission } = useAuth(); switch (name) { case "episodes": return title.is_series ? /* @__PURE__ */ jsx(TitlePageEpisodeGrid, { data, showSeasonSelector: true }) : null; case "seasons": return title.is_series ? /* @__PURE__ */ jsx(TitlePageSeasonGrid, { data }) : null; case "videos": return /* @__PURE__ */ jsx(TitlePageVideoGrid, { title }); case "images": return /* @__PURE__ */ jsx( TitlePageImageGrid, { images: title.images, heading: /* @__PURE__ */ jsx(SiteSectionHeading, { link: `${getTitleLink(title)}/images`, children: /* @__PURE__ */ jsx(Trans, { message: "Images" }) }) } ); case "reviews": return titles.enable_reviews && hasPermission("reviews.view") ? /* @__PURE__ */ jsx(TitlePageReviewList, { title }) : null; case "cast": return /* @__PURE__ */ jsx(TitlePageCast, { credits: (_a = data.credits) == null ? void 0 : _a.actors }); case "news": return /* @__PURE__ */ jsx(TitleNews, { title }); case "related": return /* @__PURE__ */ jsx(RelatedTitlesPanel, { title }); } } function TitlePageHeaderLayout({ name, description, children, right, poster }) { return /* @__PURE__ */ jsxs("div", { className: "mb-24 items-center justify-between gap-24 lg:flex", children: [ poster, /* @__PURE__ */ jsxs("div", { className: "flex-auto", children: [ children, /* @__PURE__ */ jsx("h1", { className: "mb-12 text-4xl md:mb-8 md:text-5xl", children: name }), description && /* @__PURE__ */ jsx("div", { className: "text-base font-normal", children: description }) ] }), right ] }); } function TitlePageHeader({ title, showPoster = false }) { return /* @__PURE__ */ jsx( TitlePageHeaderLayout, { name: /* @__PURE__ */ jsx(TitleLink, { title }), poster: showPoster ? /* @__PURE__ */ jsx(TitlePoster, { title, size: "w-80", srcSize: "sm" }) : null, description: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(BulletSeparatedItems, { children: [ /* @__PURE__ */ jsx(FormattedDate, { date: title.release_date }), title.certification && /* @__PURE__ */ jsx("div", { className: "uppercase", children: title.certification }), title.runtime && /* @__PURE__ */ jsx(FormattedDuration, { minutes: title.runtime, verbose: true }) ] }) }), right: /* @__PURE__ */ jsx(InteractableRating, { title }) } ); } function TitlePageHeaderImage({ title, season, episode }) { const { streaming } = useSettings(); const watchItem = episode || season || title; const backdropUrl = (episode == null ? void 0 : episode.poster) || title.backdrop; if (!backdropUrl) { return null; } const backdrop = /* @__PURE__ */ jsx( TitleBackdrop, { title, episode, size: "w-full h-full", className: "object-top", lazy: false } ); return /* @__PURE__ */ jsxs("header", { className: "relative isolate max-h-320 overflow-hidden bg-black md:max-h-400 lg:max-h-450", children: [ /* @__PURE__ */ jsx("div", { className: "container relative left-0 right-0 top-0 z-20 mx-auto h-full w-full px-24", children: backdrop }), /* @__PURE__ */ jsx("div", { className: "h-[calc(100% + 20px)] absolute left-1/2 top-1/2 z-10 w-[calc(100%+100px)] -translate-x-1/2 -translate-y-1/2 bg-black opacity-50 blur-md", children: backdrop }), /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute left-0 top-0 z-30 h-full w-full bg-gradient-to-b from-black/20 md:from-black/40" }), (streaming == null ? void 0 : streaming.show_header_play) && (watchItem == null ? void 0 : watchItem.primary_video) ? /* @__PURE__ */ jsx(PlayButton, { item: watchItem }) : null ] }); } function PlayButton({ item }) { const link = getWatchLink(item.primary_video); return /* @__PURE__ */ jsx( IconButton, { radius: "rounded-full", color: "white", variant: "raised", size: "lg", className: "absolute inset-0 z-40 m-auto", elementType: Link, to: link, children: /* @__PURE__ */ jsx(MediaPlayIcon, {}) } ); } function useCurrentUserWatchlist() { const { user } = useAuth(); return useQuery({ queryKey: ["channel", "watchlist", "compact"], queryFn: () => fetchWatchlist(), enabled: !!user }); } function useIsItemWatchlisted(item) { var _a, _b, _c; const query = useCurrentUserWatchlist(); return { isLoading: query.isLoading && query.fetchStatus !== "idle", isWatchlisted: !!((_c = (_b = (_a = query.data) == null ? void 0 : _a.watchlist) == null ? void 0 : _b.items[item.model_type]) == null ? void 0 : _c[item.id]) }; } function fetchWatchlist() { return apiClient.get(`users/me/watchlist`).then((response) => response.data); } function useAddToWatchlist() { const { data } = useCurrentUserWatchlist(); return useMutation({ mutationFn: (payload) => addToWatchlist(data.watchlist.id, payload), onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ["channel", "watchlist"] }); toast(message("Added to your watchlist")); }, onError: (r2) => showHttpErrorToast(r2) }); } function addToWatchlist(listId, payload) { return apiClient.post(`channel/${listId}/add`, { itemId: payload.id, itemType: payload.model_type }).then((r2) => r2.data); } function useRemoveFromWatchlist() { const { data } = useCurrentUserWatchlist(); return useMutation({ mutationFn: (payload) => removeFromWatchlist(data.watchlist.id, payload), onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ["channel", "watchlist"] }); toast(message("Removed from your watchlist")); }, onError: (r2) => showHttpErrorToast(r2) }); } function removeFromWatchlist(listId, payload) { return apiClient.post(`channel/${listId}/remove`, { itemId: payload.id, itemType: payload.model_type }).then((r2) => r2.data); } function WatchlistButton({ item, variant = "flat", color = "primary" }) { const { isLoading, isWatchlisted } = useIsItemWatchlisted(item); const addToWatchlist2 = useAddToWatchlist(); const removeFromWatchlist2 = useRemoveFromWatchlist(); const authHandler = useAuthClickCapture(); return /* @__PURE__ */ jsx( Button, { variant, color, startIcon: isWatchlisted ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(AddIcon, {}), className: "mt-14 min-h-40 w-full", disabled: addToWatchlist2.isPending || removeFromWatchlist2.isPending || isLoading, onClickCapture: authHandler, onClick: () => { if (isWatchlisted) { removeFromWatchlist2.mutate(item); } else { addToWatchlist2.mutate(item); } }, children: isWatchlisted ? /* @__PURE__ */ jsx(Trans, { message: "In watchlist" }) : /* @__PURE__ */ jsx(Trans, { message: "Add to watchlist" }) } ); } function TitlePageAsideLayout({ poster, children, className: className2 }) { return /* @__PURE__ */ jsxs("div", { className: clsx("top-40 flex-shrink-0 md:sticky md:w-1/4", className2), children: [ poster, /* @__PURE__ */ jsx("div", { className: "flex-auto max-md:ml-16 max-md:text-sm", children }) ] }); } function DetailItem({ label, children }) { return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx("dt", { className: "font-semibold", children: label }), /* @__PURE__ */ jsx("dl", { className: "mb-12 md:mb-24", children }) ] }); } function KeywordLink({ keyword, children, ...otherProps }) { const link = useMemo(() => getKeywordLink$1(keyword), [keyword]); return /* @__PURE__ */ jsx(BaseMediaLink, { ...otherProps, link, children: children ?? /* @__PURE__ */ jsx(Trans, { message: keyword.display_name || keyword.name }) }); } function getKeywordLink$1(keyword, { absolute } = {}) { return getBaseMediaLink(`/keyword/${keyword.name}`, { absolute }); } function ProductionCountryLink({ country, children, ...otherProps }) { const link = useMemo(() => getKeywordLink(country), [country]); return /* @__PURE__ */ jsx(BaseMediaLink, { ...otherProps, link, children: children ?? (country.display_name || country.name) }); } function getKeywordLink(country, { absolute } = {}) { return getBaseMediaLink(`/production-countries/${country.name}`, { absolute }); } function WatchNowButton({ video, variant = "outline", color = "primary", size = "w-full min-h-40 mt-14", defaultLabel }) { const label = video.episode_num && !defaultLabel ? /* @__PURE__ */ jsxs("span", { className: "inline-flex gap-4", children: [ /* @__PURE__ */ jsx(Trans, { message: "Start watching" }), /* @__PURE__ */ jsx( CompactSeasonEpisode, { seasonNum: video.season_num, episodeNum: video.episode_num } ) ] }) : /* @__PURE__ */ jsx(Trans, { message: "Watch now" }); return /* @__PURE__ */ jsx( Button, { to: getWatchLink(video), elementType: Link, startIcon: /* @__PURE__ */ jsx(MediaPlayIcon, {}), color, variant, className: size, children: label } ); } function useIsStreamingMode() { const { streaming } = useSettings(); return (streaming == null ? void 0 : streaming.prefer_full) || false; } function TitlePageAside({ data: { title, language }, className: className2 }) { var _a, _b; const isStreamingMode = useIsStreamingMode(); const { hasPermission } = useAuth(); return /* @__PURE__ */ jsxs( TitlePageAsideLayout, { className: className2, poster: /* @__PURE__ */ jsxs("div", { className: "relative", children: [ /* @__PURE__ */ jsx(TitlePoster, { title, size: "w-full", srcSize: "lg" }), hasPermission("titles.update") && /* @__PURE__ */ jsx( IconButton, { elementType: Link, to: `/admin/titles/${title.id}/edit`, className: "absolute bottom-6 right-4", color: "white", children: /* @__PURE__ */ jsx(EditIcon, {}) } ) ] }), children: [ isStreamingMode && title.primary_video && /* @__PURE__ */ jsx(WatchNowButton, { video: title.primary_video, variant: "flat" }), /* @__PURE__ */ jsx( WatchlistButton, { item: title, variant: isStreamingMode ? "outline" : "flat" } ), /* @__PURE__ */ jsx(ShareButton$2, { title }), /* @__PURE__ */ jsxs("dl", { className: "mt-14", children: [ language && /* @__PURE__ */ jsx(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Original language" }), children: /* @__PURE__ */ jsx(Trans, { message: language }) }), title.original_title !== title.name && /* @__PURE__ */ jsx(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Original title" }), children: title.original_title }), title.budget ? /* @__PURE__ */ jsx(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Budget" }), children: /* @__PURE__ */ jsx(FormattedCurrency, { value: title.budget, currency: "usd" }) }) : null, title.revenue ? /* @__PURE__ */ jsx(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Revenue" }), children: /* @__PURE__ */ jsx(FormattedCurrency, { value: title.revenue, currency: "usd" }) }) : null, ((_a = title.production_countries) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsx(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Production countries" }), children: /* @__PURE__ */ jsx("ul", { className: "mt-12 flex flex-wrap gap-8", children: title.production_countries.map((country) => /* @__PURE__ */ jsx( "li", { className: "w-max rounded-full border px-10 py-4 text-xs", children: /* @__PURE__ */ jsx(ProductionCountryLink, { country }) }, country.id )) }) }) : null, ((_b = title.keywords) == null ? void 0 : _b.length) ? /* @__PURE__ */ jsx(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Keywords" }), children: /* @__PURE__ */ jsx("ul", { className: "mt-12 flex flex-wrap gap-8", children: title.keywords.map((keyword) => /* @__PURE__ */ jsx( "li", { className: "w-max rounded-full border px-10 py-4 text-xs", children: /* @__PURE__ */ jsx(KeywordLink, { keyword }) }, keyword.id )) }) }) : null ] }) ] } ); } function ShareButton$2({ title }) { const link = getTitleLink(title, { absolute: true }); return /* @__PURE__ */ jsx(ShareMenuTrigger, { link, children: /* @__PURE__ */ jsx( Button, { variant: "outline", color: "primary", startIcon: /* @__PURE__ */ jsx(ShareIcon, {}), className: "mt-14 min-h-40 w-full", children: /* @__PURE__ */ jsx(Trans, { message: "Share" }) } ) }); } function TitlePage() { const query = useTitle("titlePage"); const content2 = query.data ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(PageContent$b, { data: query.data }) ] }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function PageContent$b({ data }) { return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(TitlePageHeaderImage, { title: data.title }), /* @__PURE__ */ jsx("div", { className: "container mx-auto mt-24 px-14 md:mt-40 md:px-24", children: /* @__PURE__ */ jsxs("div", { className: "items-start gap-54 md:flex", children: [ /* @__PURE__ */ jsx(TitlePageAside, { data, className: "max-lg:hidden" }), /* @__PURE__ */ jsxs("div", { className: "flex-auto", children: [ /* @__PURE__ */ jsx(TitlePageHeader, { title: data.title }), /* @__PURE__ */ jsx(TitlePageMainContent, { data }) ] }) ] }) }) ] }); } function SeasonPage() { const query = useSeason("seasonPage"); const content2 = query.data ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(PageContent$a, { data: query.data }) ] }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function PageContent$a({ data }) { const { title, season } = data; return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(TitlePageHeaderImage, { title, season }), /* @__PURE__ */ jsxs("div", { className: "container mx-auto mt-24 px-14 md:mt-40 md:px-24", children: [ /* @__PURE__ */ jsxs("div", { className: "mb-24 flex items-center gap-12", children: [ /* @__PURE__ */ jsx(TitlePoster, { size: "w-70", srcSize: "sm", title }), /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(TitleLink, { title, color: "primary", className: "text-xl" }), /* @__PURE__ */ jsx("div", { className: "text-lg", children: /* @__PURE__ */ jsx(Trans, { message: "Episode list" }) }) ] }) ] }), /* @__PURE__ */ jsx(SeasonList, { title }), /* @__PURE__ */ jsx(EpisodeList$1, { data }), /* @__PURE__ */ jsx(SeasonList, { title }) ] }) ] }); } function SeasonList({ title }) { const { season } = useParams(); return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsxs("div", { className: "mb-4 text-base font-semibold", children: [ /* @__PURE__ */ jsx(Trans, { message: "Seasons" }), ":" ] }), /* @__PURE__ */ jsx("div", { className: "mb-34 flex items-center gap-10", children: [...new Array(title.seasons_count).keys()].map((index) => { const number = index + 1; const isActive = season === `${number}`; return /* @__PURE__ */ jsx( SeasonLink, { title, seasonNumber: number, className: clsx( "flex h-30 w-30 flex-shrink-0 items-center justify-center rounded border text-base", isActive ? "pointer-events-none bg-primary text-white" : "text-primary" ), children: number }, number ); }) }) ] }); } function EpisodeList$1({ data: { episodes, title } }) { const query = useSeasonEpisodes(episodes); return /* @__PURE__ */ jsxs("main", { children: [ query.items.map((episode) => /* @__PURE__ */ jsx( EpisodeListItem, { episode, title, allowRating: true, showPlayButton: true, className: "mb-34" }, episode.id )), /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query }) ] }); } function EpisodePageHeader({ title, episode, showPoster }) { const navigate = useNavigate(); const runtime = episode.runtime || title.runtime; return /* @__PURE__ */ jsx( TitlePageHeaderLayout, { poster: showPoster ? /* @__PURE__ */ jsx(TitlePoster, { title, size: "w-80", srcSize: "sm" }) : void 0, name: episode.name, description: /* @__PURE__ */ jsxs(BulletSeparatedItems, { className: "my-10 md:my-0", children: [ /* @__PURE__ */ jsx( Trans, { message: "Aired :date", values: { date: /* @__PURE__ */ jsx(FormattedDate, { date: episode.release_date }) } } ), /* @__PURE__ */ jsx("span", { className: "uppercase", children: title.certification }), runtime ? /* @__PURE__ */ jsx(FormattedDuration, { minutes: runtime, verbose: true }) : null ] }), right: /* @__PURE__ */ jsx(InteractableRating, { title, episode }), children: /* @__PURE__ */ jsxs(Breadcrumb, { isNavigation: true, children: [ /* @__PURE__ */ jsx(BreadcrumbItem, { onSelected: () => navigate(getTitleLink(title)), children: title.name }), /* @__PURE__ */ jsx( BreadcrumbItem, { onSelected: () => navigate(getSeasonLink(title, episode.season_number)), children: /* @__PURE__ */ jsx( Trans, { message: "Season :number", values: { number: episode.season_number } } ) } ), /* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx( Trans, { message: "Episode :number", values: { number: episode.episode_number } } ) }) ] }) } ); } function EpisodePage() { const query = useEpisode("episodePage"); const content2 = query.data ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(PageContent$9, { data: query.data }) ] }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function PageContent$9({ data }) { const { episode, title } = data; return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(TitlePageHeaderImage, { title, episode }), /* @__PURE__ */ jsx("div", { className: "container mx-auto mt-12 px-14 md:mt-40 md:px-24", children: /* @__PURE__ */ jsxs("div", { className: "items-start gap-54 md:flex", children: [ /* @__PURE__ */ jsx(Aside, { title, episode }), /* @__PURE__ */ jsxs("div", { className: "flex-auto", children: [ /* @__PURE__ */ jsx(EpisodePageHeader, { title, episode }), /* @__PURE__ */ jsx(MainContent, { data }) ] }) ] }) }) ] }); } function MainContent({ data }) { var _a; const { episode, title, credits } = data; const { title_page } = useSettings(); return /* @__PURE__ */ jsxs("main", { className: "@container", children: [ ((_a = title.genres) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsx(ChipList, { children: title.genres.map((genre) => /* @__PURE__ */ jsx( Chip, { className: "capitalize", elementType: Link, to: getGenreLink(genre), children: genre.display_name || genre.name }, genre.id )) }) : null, /* @__PURE__ */ jsx( TruncatedDescription, { className: "mt-16", description: episode.description } ), /* @__PURE__ */ jsx(CompactCredits, { credits }), title_page == null ? void 0 : title_page.sections.map((name) => /* @__PURE__ */ jsx(EpisodePageSection, { name, data }, name)) ] }); } function EpisodePageSection({ name, data }) { var _a; switch (name) { case "videos": return /* @__PURE__ */ jsx(TitlePageVideoGrid, { title: data.title, episode: data.episode }); case "cast": return /* @__PURE__ */ jsx(TitlePageCast, { credits: (_a = data.credits) == null ? void 0 : _a.actors }); case "related": return /* @__PURE__ */ jsx(RelatedTitlesPanel, { title: data.title }); case "episodes": return /* @__PURE__ */ jsx( TitlePageEpisodeGrid, { data, label: /* @__PURE__ */ jsx(Trans, { message: "Other episodes" }) } ); default: return null; } } function Aside({ title, episode }) { const isStreamingMode = useIsStreamingMode(); return /* @__PURE__ */ jsxs( TitlePageAsideLayout, { className: "max-md:hidden", poster: /* @__PURE__ */ jsx(TitlePoster, { title, size: "w-full", srcSize: "lg" }), children: [ isStreamingMode && episode.primary_video && /* @__PURE__ */ jsx( WatchNowButton, { video: episode.primary_video, variant: "flat", defaultLabel: true } ), /* @__PURE__ */ jsx( WatchlistButton, { item: title, variant: isStreamingMode ? "outline" : "flat" } ) ] } ); } function useWatchPageVideo() { const { videoId } = useParams(); return useQuery({ queryKey: ["video", "watch-page", videoId], queryFn: () => fetchVideo(videoId), placeholderData: keepPreviousData, initialData: () => { var _a; const data = (_a = getBootstrapData().loaders) == null ? void 0 : _a.watchPage; if (data && `${data.video.id}` === videoId) { return data; } } }); } function fetchVideo(videoId) { return apiClient.get(`watch/${videoId}`).then((response) => response.data); } function commentsQueryKey(commentable, params = {}) { return ["comment", `${commentable.id}-${commentable.model_type}`, params]; } function useComments(commentable, params = {}) { return useInfiniteData({ queryKey: commentsQueryKey(commentable, params), endpoint: "commentable/comments", //paginate: 'cursor', queryParams: { commentable_type: commentable.model_type, commentable_id: commentable.id, ...params } }); } function useCreateComment() { const queryClient2 = useQueryClient(); return useMutation({ mutationFn: (props) => createComment(props), onSuccess: async (response, props) => { await queryClient2.invalidateQueries({ queryKey: [ "comment", `${props.commentable.id}-${props.commentable.model_type}` ] }); toast(message("Comment posted")); }, onError: (err) => showHttpErrorToast(err) }); } function createComment({ commentable, content: content2, inReplyTo, ...other }) { const payload = { commentable_id: commentable.id, commentable_type: commentable.model_type, content: content2, inReplyTo, ...other }; return apiClient.post("comment", payload).then((r2) => r2.data); } function NewCommentForm({ commentable, inReplyTo, onSuccess, className: className2, autoFocus, payload, ...props }) { const { trans } = useTrans(); const { user } = useAuth(); const createComment2 = useCreateComment(); const inputRef = useObjectRef(props.inputRef); const [inputIsExpanded, setInputIsExpanded] = useState(false); const [inputValue, setInputValue] = useState(""); const clearInput = () => { setInputIsExpanded(false); if (inputRef.current) { inputRef.current.blur(); setInputValue(""); } }; return /* @__PURE__ */ jsxs( "form", { className: clsx("py-6 flex gap-24", className2), onSubmit: (e) => { e.preventDefault(); if (inputValue && !createComment2.isPending) { createComment2.mutate( { ...payload, commentable, content: inputValue, inReplyTo }, { onSuccess: () => { clearInput(); onSuccess == null ? void 0 : onSuccess(); } } ); } }, children: [ /* @__PURE__ */ jsx(Avatar, { size: "xl", circle: true, src: user == null ? void 0 : user.avatar, label: user == null ? void 0 : user.display_name }), /* @__PURE__ */ jsxs("div", { className: "flex-auto", children: [ /* @__PURE__ */ jsx("div", { className: "text-xs text-muted mb-10", children: /* @__PURE__ */ jsx( Trans, { message: "Comment as :name", values: { name: /* @__PURE__ */ jsx("span", { className: "font-medium text", children: user == null ? void 0 : user.display_name }) } } ) }), /* @__PURE__ */ jsx( TextField, { inputRef, autoFocus, inputElementType: "textarea", inputClassName: "resize-none", value: inputValue, onChange: (e) => setInputValue(e.target.value), onFocus: () => setInputIsExpanded(true), onBlur: () => { if (!inputValue) { setInputIsExpanded(false); } }, minLength: 3, rows: inputIsExpanded ? 3 : 1, placeholder: inReplyTo ? trans(message("Write a reply")) : trans(message("Leave a comment")) } ), inputIsExpanded && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-12 justify-end mt-12", children: [ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => clearInput(), children: /* @__PURE__ */ jsx(Trans, { message: "Cancel" }) }), /* @__PURE__ */ jsx( Button, { variant: "outline", color: "primary", type: "submit", disabled: createComment2.isPending || inputValue.length < 3, children: /* @__PURE__ */ jsx(Trans, { message: "Comment" }) } ) ] }) ] }) ] } ); } function useStoreVote(model) { return useMutation({ mutationFn: (payload) => changeVote(model, payload), onSuccess: (response) => { }, onError: (err) => showHttpErrorToast(err) }); } function changeVote(model, payload) { return apiClient.post("vote", { vote_type: payload.voteType, model_id: model.id, model_type: model.model_type }).then((r2) => r2.data); } function ThumbButtons({ model, className: className2, showUpvotesOnly }) { const changeVote2 = useStoreVote(model); const [upvotes, setUpvotes] = useState(model.upvotes || 0); const [downvotes, setDownvotes] = useState(model.downvotes || 0); const [currentVote, setCurrentVote] = useState(model.current_vote); const syncLocalState = (model2) => { setUpvotes(model2.upvotes); setDownvotes(model2.downvotes); setCurrentVote(model2.current_vote); }; return /* @__PURE__ */ jsxs("div", { className: clsx(className2, "whitespace-nowrap"), children: [ /* @__PURE__ */ jsxs( Button, { className: "gap-6", sizeClassName: "px-8 py-4", color: currentVote === "upvote" ? "primary" : void 0, disabled: changeVote2.isPending, "aria-label": "Upvote", onClick: () => { changeVote2.mutate( { voteType: "upvote" }, { onSuccess: (response) => syncLocalState(response.model) } ); }, children: [ /* @__PURE__ */ jsx(ThumbUpIcon, {}), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(FormattedNumber, { value: upvotes }) }) ] } ), !showUpvotesOnly && /* @__PURE__ */ jsxs( Button, { className: "gap-6", sizeClassName: "px-8 py-4", color: currentVote === "downvote" ? "primary" : void 0, disabled: changeVote2.isPending, "aria-label": "Downvote", onClick: () => { changeVote2.mutate( { voteType: "downvote" }, { onSuccess: (response) => syncLocalState(response.model) } ); }, children: [ /* @__PURE__ */ jsx(ThumbDownIcon, {}), /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(FormattedNumber, { value: downvotes }) }) ] } ) ] }); } function CommentListItem$1({ comment, commentable, // user can delete comment if they have created it, or they have relevant permissions on commentable canDelete }) { const isMobile = useIsMobileMediaQuery(); const { user, hasPermission } = useAuth(); const [replyFormVisible, setReplyFormVisible] = useState(false); const showReplyButton = user != null && !comment.deleted && !isMobile && comment.depth < 5 && hasPermission("comments.create"); return /* @__PURE__ */ jsxs( "div", { style: { paddingLeft: `${comment.depth * 20}px` }, onClick: () => { if (isMobile) { setReplyFormVisible(!replyFormVisible); } }, children: [ /* @__PURE__ */ jsxs("div", { className: "group flex min-h-70 items-start gap-24 py-18", children: [ /* @__PURE__ */ jsx(UserAvatar, { user: comment.user, size: isMobile ? "lg" : "xl", circle: true }), /* @__PURE__ */ jsxs("div", { className: "flex-auto text-sm", children: [ /* @__PURE__ */ jsxs("div", { className: "mb-4 flex items-center gap-8", children: [ comment.user && /* @__PURE__ */ jsx(UserDisplayName, { user: comment.user }), /* @__PURE__ */ jsx("time", { className: "text-xs text-muted", children: /* @__PURE__ */ jsx(FormattedRelativeTime, { date: comment.created_at }) }), comment.position ? /* @__PURE__ */ jsx(Position, { commentable, position: comment.position }) : null ] }), /* @__PURE__ */ jsx("div", { className: "whitespace-pre-line", children: comment.deleted ? /* @__PURE__ */ jsx("span", { className: "italic text-muted", children: /* @__PURE__ */ jsx(Trans, { message: "[COMMENT DELETED]" }) }) : comment.content }), !comment.deleted && /* @__PURE__ */ jsxs("div", { className: "-ml-8 mt-10 flex items-center gap-8", children: [ showReplyButton && /* @__PURE__ */ jsx( Button, { sizeClassName: "text-sm px-8 py-4", startIcon: /* @__PURE__ */ jsx(ReplyIcon, {}), onClick: () => setReplyFormVisible(!replyFormVisible), children: /* @__PURE__ */ jsx(Trans, { message: "Reply" }) } ), /* @__PURE__ */ jsx(ThumbButtons, { model: comment, showUpvotesOnly: true }), /* @__PURE__ */ jsx( CommentOptionsTrigger, { comment, canDelete, user } ) ] }) ] }) ] }), replyFormVisible ? /* @__PURE__ */ jsx( NewCommentForm, { className: !(comment == null ? void 0 : comment.depth) ? "pl-20" : void 0, commentable, inReplyTo: comment, autoFocus: true, onSuccess: () => { setReplyFormVisible(false); } } ) : null ] } ); } const Position = memo(({ commentable, position }) => { if (!commentable.duration) return null; const seconds = position / 100 * (commentable.duration / 1e3); return /* @__PURE__ */ jsx("span", { className: "text-xs text-muted", children: /* @__PURE__ */ jsx( Trans, { message: "at :position", values: { position: /* @__PURE__ */ jsx(FormattedDuration, { seconds }) } } ) }); }); function CommentOptionsTrigger({ comment, canDelete, user }) { const deleteComments = useDeleteComments(); const reportComment = useSubmitReport(comment); const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); const showDeleteButton = (comment.user_id === (user == null ? void 0 : user.id) || canDelete) && !comment.deleted; const handleReport = () => { reportComment.mutate({}); }; const handleDelete = (isConfirmed) => { setIsDeleteDialogOpen(false); if (isConfirmed) { deleteComments.mutate( { commentIds: [comment.id] }, { onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["comment"] }); } } ); } }; return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsxs(MenuTrigger, { children: [ /* @__PURE__ */ jsx(Button, { startIcon: /* @__PURE__ */ jsx(MoreVertIcon, {}), sizeClassName: "text-sm px-8 py-4", children: /* @__PURE__ */ jsx(Trans, { message: "More" }) }), /* @__PURE__ */ jsxs(Menu, { children: [ /* @__PURE__ */ jsx(Item, { value: "report", onSelected: () => handleReport(), children: /* @__PURE__ */ jsx(Trans, { message: "Report comment" }) }), showDeleteButton && /* @__PURE__ */ jsx( Item, { value: "delete", onSelected: () => setIsDeleteDialogOpen(true), children: /* @__PURE__ */ jsx(Trans, { message: "Delete" }) } ) ] }) ] }), /* @__PURE__ */ jsx( DialogTrigger, { type: "modal", isOpen: isDeleteDialogOpen, onClose: (isConfirmed) => handleDelete(isConfirmed), children: /* @__PURE__ */ jsx( ConfirmationDialog, { isDanger: true, title: /* @__PURE__ */ jsx(Trans, { message: "Delete comment?" }), body: /* @__PURE__ */ jsx(Trans, { message: "Are you sure you want to delete this comment?" }), confirm: /* @__PURE__ */ jsx(Trans, { message: "Delete" }) } ) } ) ] }); } function UserDisplayName({ user }) { const { auth } = useContext(SiteConfigContext); if (auth.getUserProfileLink) { return /* @__PURE__ */ jsx( Link, { to: auth.getUserProfileLink(user), className: "text-base font-medium hover:underline", children: user.display_name } ); } return /* @__PURE__ */ jsx("div", { className: "text-base font-medium", children: user.display_name }); } const accountRequiredMessage = message( "Please login or create account to comment" ); function CommentList({ className: className2, commentable, canDeleteAllComments = false, children, perPage = 25 }) { const { items, totalItems, ...query } = useComments(commentable, { perPage }); if (query.isError) { return null; } return /* @__PURE__ */ jsxs("div", { className: className2, children: [ /* @__PURE__ */ jsxs("div", { className: "mb-8 pb-8 border-b flex items-center gap-8", children: [ /* @__PURE__ */ jsx(CommentIcon, { size: "sm", className: "text-muted" }), query.isInitialLoading ? /* @__PURE__ */ jsx(Trans, { message: "Loading comments..." }) : /* @__PURE__ */ jsx( Trans, { message: ":count comments", values: { count: /* @__PURE__ */ jsx(FormattedNumber, { value: totalItems || 0 }) } } ) ] }), children, /* @__PURE__ */ jsx(AccountRequiredCard, { message: accountRequiredMessage }), /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: query.isInitialLoading ? /* @__PURE__ */ jsx(CommentSkeletons, { count: 4 }) : /* @__PURE__ */ jsx( CommentListItems, { comments: items, canDeleteAllComments, commentable } ) }), /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query, variant: "loadMore" }) ] }); } function CommentListItems({ comments, commentable, canDeleteAllComments }) { if (!comments.length) { return /* @__PURE__ */ jsx( IllustratedMessage, { className: "mt-24", size: "sm", title: /* @__PURE__ */ jsx(Trans, { message: "Seems a little quiet over here" }), description: /* @__PURE__ */ jsx(Trans, { message: "Be the first to comment" }) } ); } return /* @__PURE__ */ jsx(m.div, { ...opacityAnimation, children: comments.map((comment) => /* @__PURE__ */ jsx( CommentListItem$1, { comment, commentable, canDelete: canDeleteAllComments }, comment.id )) }, "comments"); } function CommentSkeletons({ count }) { return /* @__PURE__ */ jsx(m.div, { ...opacityAnimation, children: [...new Array(count).keys()].map((index) => /* @__PURE__ */ jsxs( "div", { className: "flex items-start gap-24 py-18 min-h-70 group", children: [ /* @__PURE__ */ jsx(Skeleton, { variant: "avatar", radius: "rounded-full", size: "w-60 h-60" }), /* @__PURE__ */ jsxs("div", { className: "text-sm flex-auto", children: [ /* @__PURE__ */ jsx(Skeleton, { className: "text-base max-w-184 mb-4" }), /* @__PURE__ */ jsx(Skeleton, { className: "text-sm" }), /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-8 mt-10", children: [ /* @__PURE__ */ jsx(Skeleton, { className: "text-sm max-w-70" }), /* @__PURE__ */ jsx(Skeleton, { className: "text-sm max-w-40" }), /* @__PURE__ */ jsx(Skeleton, { className: "text-sm max-w-60" }) ] }) ] }) ] }, index )) }, "loading-skeleton"); } function WatchPageTitleDetails() { var _a; const { data } = useWatchPageVideo(); const isStreamingMode = useIsStreamingMode(); const content2 = !data ? /* @__PURE__ */ jsx( Layout, { poster: /* @__PURE__ */ jsx(Skeleton, { variant: "rect", size: "w-132 aspect-poster" }), titleLink: /* @__PURE__ */ jsx(Skeleton, { className: "max-w-144" }), videoName: /* @__PURE__ */ jsx(Skeleton, { className: "max-w-240" }), description: /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(Skeleton, {}), /* @__PURE__ */ jsx(Skeleton, {}) ] }), rate: /* @__PURE__ */ jsxs("div", { className: "flex h-32 items-center gap-2", children: [ /* @__PURE__ */ jsx(Skeleton, { variant: "rect", size: "w-56 h-24", className: "mr-10" }), /* @__PURE__ */ jsx(Skeleton, { variant: "rect", size: "w-56 h-24" }) ] }) }, "skeleton" ) : /* @__PURE__ */ jsx( Layout, { poster: /* @__PURE__ */ jsx( TitlePoster, { size: "w-132", srcSize: "md", title: data.title, showPlayButton: true, className: "max-md:hidden" } ), titleLink: /* @__PURE__ */ jsx(TitleLink, { title: data.title }), videoName: !isStreamingMode ? data.video.name : void 0, episodeName: data.episode ? /* @__PURE__ */ jsxs(EpisodeLink, { title: data.title, episode: data.episode, children: [ data.episode.name, " (", /* @__PURE__ */ jsx(CompactSeasonEpisode, { episode: data.episode }), ")" ] }) : void 0, description: ((_a = data.episode) == null ? void 0 : _a.description) || data.title.description, rate: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [ /* @__PURE__ */ jsx(ThumbButtons, { model: data.video, className: "mr-auto" }), /* @__PURE__ */ jsx(ReportButton, { video: data.video }), /* @__PURE__ */ jsx(ShareButton$1, { video: data.video }) ] }) }, "loaded" ); return /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: content2 }); } function ShareButton$1({ video }) { const link = getWatchLink(video, { absolute: true }); return /* @__PURE__ */ jsx(ShareMenuTrigger, { link, children: /* @__PURE__ */ jsx(Tooltip, { label: /* @__PURE__ */ jsx(Trans, { message: "Share" }), children: /* @__PURE__ */ jsx(IconButton, { children: /* @__PURE__ */ jsx(ShareIcon, {}) }) }) }); } function ReportButton({ video }) { const report = useSubmitReport(video); const deleteReport2 = useDeleteReport(video); const [isReported, setIsReported] = useState(video.current_user_reported); return /* @__PURE__ */ jsx(Tooltip, { label: /* @__PURE__ */ jsx(Trans, { message: "Report" }), children: /* @__PURE__ */ jsx( IconButton, { onClick: () => { if (isReported) { deleteReport2.mutate(); } else { report.mutate({}); } setIsReported(!isReported); }, children: /* @__PURE__ */ jsx(FlagIcon, {}) } ) }); } function Layout({ poster, titleLink, videoName, episodeName, description, rate }) { return /* @__PURE__ */ jsxs( m.div, { className: "flex items-start gap-16 overflow-hidden rounded pr-6", ...opacityAnimation, children: [ poster, /* @__PURE__ */ jsxs("div", { className: "flex-auto py-6", children: [ /* @__PURE__ */ jsx("h1", { className: "mb-6 text-2xl font-medium", children: titleLink }), episodeName && /* @__PURE__ */ jsx("div", { className: "text-base font-medium", children: episodeName }), videoName && /* @__PURE__ */ jsx("div", { className: "text-base font-medium", children: videoName }), /* @__PURE__ */ jsx("div", { className: "my-12", children: rate }), description && /* @__PURE__ */ jsx("p", { className: "max-w-780 text-sm text-muted", children: description }) ] }) ] } ); } function WatchPageAside() { const { data } = useWatchPageVideo(); const content2 = !data ? /* @__PURE__ */ jsxs(m.div, { ...opacityAnimation, children: [ /* @__PURE__ */ jsx(VideoGridItemSkeleton, { className: "mb-34" }), /* @__PURE__ */ jsx(VideoGridItemSkeleton, { className: "mb-34" }), /* @__PURE__ */ jsx(VideoGridItemSkeleton, { className: "mb-34" }) ] }, "skeleton") : /* @__PURE__ */ jsx(m.div, { ...opacityAnimation, children: data.related_videos.map((video) => /* @__PURE__ */ jsx(RelatedVideo, { video, activeVideo: data.video }, video.id)) }, "loaded"); return /* @__PURE__ */ jsxs("aside", { className: "w-350 flex-shrink-0 max-lg:mt-54", children: [ /* @__PURE__ */ jsx( SiteSectionHeading, { fontWeight: "font-medium", fontSize: "text-2xl", margin: "mb-28", children: /* @__PURE__ */ jsx(Header, { video: data == null ? void 0 : data.video }) } ), /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: content2 }) ] }); } function Header({ video }) { const isStreamingMode = useIsStreamingMode(); if (!video) { return /* @__PURE__ */ jsx("div", { className: "h-32" }); } return isStreamingMode ? /* @__PURE__ */ jsx(Trans, { message: "Related movies & series" }) : /* @__PURE__ */ jsx(Trans, { message: "Related videos" }); } function RelatedVideo({ video, activeVideo }) { const isStreamingMode = useIsStreamingMode(); let name = video.name; if (isStreamingMode) { if (video.episode) { name = /* @__PURE__ */ jsxs("span", { children: [ video.episode.name, " (", /* @__PURE__ */ jsx(CompactSeasonEpisode, { episode: video.episode }), ")" ] }); } else { name = video.title.name; } } return /* @__PURE__ */ jsx( VideoGridItem, { video, title: video.title, episode: video.episode, forceTitleBackdrop: isStreamingMode, className: clsx( "mb-24 text-sm", activeVideo.id === video.id && "text-primary" ), showCategory: !isStreamingMode, name } ); } const className = "flex items-center flex-wrap gap-14"; function WatchPageAlternativeVideos({ data }) { const navigate = useNavigate(); const { streaming } = useSettings(); const title = data == null ? void 0 : data.title; const episode = data == null ? void 0 : data.episode; const video = data == null ? void 0 : data.video; const showEpisodeSelector = title && episode && video && (video.type === "embed" || video.type === "external"); if (!showEpisodeSelector && !streaming.show_video_selector) { return null; } return /* @__PURE__ */ jsxs("div", { className: "mt-14 flex items-start justify-between gap-48", children: [ streaming.show_video_selector && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( VideoDropdown, { className: "lg:hidden", videos: (data == null ? void 0 : data.alternative_videos) || [] } ), /* @__PURE__ */ jsx("div", { className: "max-lg:hidden", children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: data ? /* @__PURE__ */ jsx(VideoList, { videos: data.alternative_videos }) : /* @__PURE__ */ jsx(Skeletons, {}) }) }) ] }), showEpisodeSelector && /* @__PURE__ */ jsx( EpisodeSelector, { title, currentEpisode: episode, onSelected: (episode2) => { navigate(getWatchLink(episode2.primary_video)); }, trigger: /* @__PURE__ */ jsx( Button, { variant: "outline", className: "min-h-40", startIcon: /* @__PURE__ */ jsx(MediaEpisodesIcon, {}), children: /* @__PURE__ */ jsx(Trans, { message: "Episodes" }) } ) } ) ] }); } function VideoDropdown({ videos, className: className2 }) { const navigate = useNavigate(); return /* @__PURE__ */ jsxs(MenuTrigger, { children: [ /* @__PURE__ */ jsx( Button, { variant: "outline", className: clsx("min-h-40", className2), startIcon: /* @__PURE__ */ jsx(MediaPlayIcon, {}), children: /* @__PURE__ */ jsx(Trans, { message: "Other sources" }) } ), /* @__PURE__ */ jsx(Menu, { children: videos.map((video) => /* @__PURE__ */ jsx( Item, { value: video.id, startIcon: /* @__PURE__ */ jsx(MediaPlayIcon, {}), endSection: /* @__PURE__ */ jsx(QualityBadge, { video }), onSelected: () => navigate(getWatchLink(video)), children: video.name }, video.id )) }) ] }); } function VideoList({ videos }) { const { videoId } = useParams(); if (videos.length < 2) { return null; } return /* @__PURE__ */ jsx( m.div, { className, ...opacityAnimation, children: videos.map((video) => /* @__PURE__ */ jsxs( Button, { elementType: Link, to: getWatchLink(video), variant: "outline", color: videoId === `${video.id}` ? "primary" : "chip", startIcon: /* @__PURE__ */ jsx(MediaPlayIcon, { "aria-hidden": true }), className: "min-h-40 gap-10", children: [ video.name, /* @__PURE__ */ jsx(QualityBadge, { video }) ] }, video.id )) }, "alternative-sources" ); } function QualityBadge({ video }) { if (!video.quality || video.quality === "default") { return null; } return /* @__PURE__ */ jsx("span", { className: "rounded border px-6 text-xs font-bold uppercase", children: video.quality }); } function Skeletons() { return /* @__PURE__ */ jsxs( m.div, { className: clsx(className, "h-40"), ...opacityAnimation, children: [ /* @__PURE__ */ jsx(Skeleton, { variant: "rect", size: "h-full w-[116px]" }), /* @__PURE__ */ jsx(Skeleton, { variant: "rect", size: "h-full w-[116px]" }), /* @__PURE__ */ jsx(Skeleton, { variant: "rect", size: "h-full w-[116px]" }), /* @__PURE__ */ jsx(Skeleton, { variant: "rect", size: "h-full w-[116px]" }), /* @__PURE__ */ jsx(Skeleton, { variant: "rect", size: "h-full w-[116px]" }) ] }, "skeletons" ); } function WatchPage() { const darkThemeVars = useDarkThemeVariables(); useScrollToTop(); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(MainNavbar, {}), /* @__PURE__ */ jsx("div", { style: darkThemeVars, className: "dark min-h-screen bg text", children: /* @__PURE__ */ jsxs("div", { className: "container mx-auto p-14 md:p-24", children: [ /* @__PURE__ */ jsx(Content, {}), /* @__PURE__ */ jsx(Footer, { className: "mt-48" }) ] }) }) ] }); } function Content() { const { titles, comments } = useSettings(); const { isLoggedIn, hasPermission } = useAuth(); const query = useWatchPageVideo(); const { data, isLoading } = query; const title = data == null ? void 0 : data.title; const episode = data == null ? void 0 : data.episode; const video = data == null ? void 0 : data.video; let commentable = video; if (!(comments == null ? void 0 : comments.per_video)) { commentable = episode || title; } const shouldShowComments = title && video && titles.enable_comments && hasPermission("comments.view"); if (data || isLoading) { return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(VideoWrapper, { data }), /* @__PURE__ */ jsx(WatchPageAlternativeVideos, { data }), /* @__PURE__ */ jsx(AdHost, { slot: "watch_top", className: "pt-48" }), /* @__PURE__ */ jsxs("section", { className: "mt-42 items-start gap-56 lg:flex", children: [ /* @__PURE__ */ jsxs("div", { className: "flex-auto", children: [ /* @__PURE__ */ jsx(WatchPageTitleDetails, {}), shouldShowComments && /* @__PURE__ */ jsx( CommentList, { commentable, className: "mt-44", perPage: 20, children: isLoggedIn && hasPermission("comments.create") && /* @__PURE__ */ jsx( NewCommentForm, { commentable, className: "mb-14 mt-24" } ) } ) ] }), /* @__PURE__ */ jsx(WatchPageAside, {}) ] }) ] }, (video == null ? void 0 : video.id) || "loading"); } return /* @__PURE__ */ jsx(PageErrorMessage, {}); } function VideoWrapper({ data }) { const isStreamingMode = useIsStreamingMode(); const { hasPermission } = useAuth(); const [isVisible, setIsVisible] = useState(false); useLayoutEffect(() => { setIsVisible(true); }, []); return /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "wait", children: (data == null ? void 0 : data.video) && isVisible ? /* @__PURE__ */ jsx(m.div, { ...opacityAnimation, children: hasPermission("videos.play") ? /* @__PURE__ */ jsx( SiteVideoPlayer, { title: data.title, episode: data.episode, video: data.video, relatedVideos: data.related_videos, autoPlay: true, logPlays: true, showEpisodeSelector: isStreamingMode } ) : /* @__PURE__ */ jsx(UpgradeMessage, { video: data.video }) }, "player") : /* @__PURE__ */ jsx(m.div, { className: "relative", ...opacityAnimation, children: /* @__PURE__ */ jsx(VideoPlayerSkeleton, { animate: true }) }, "skeleton") }); } function UpgradeMessage({ video }) { return /* @__PURE__ */ jsxs("div", { className: "relative flex aspect-video items-center justify-center bg-alt", children: [ /* @__PURE__ */ jsx("div", { className: "blur", children: /* @__PURE__ */ jsx(VideoThumbnail, { video }) }), /* @__PURE__ */ jsxs("div", { className: "absolute h-max w-max max-w-full rounded-lg bg-black/60 p-24 text-lg font-medium", children: [ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Trans, { message: "Your current plan does not allow watching videos. Upgrade to unlock this feature." }) }), /* @__PURE__ */ jsx("div", { className: "mt-14 text-center", children: /* @__PURE__ */ jsx( Button, { variant: "flat", color: "primary", elementType: Link, to: "/pricing", children: /* @__PURE__ */ jsx(Trans, { message: "Upgrade" }) } ) }) ] }) ] }); } function TitleVideosPage() { const query = useTitle("titlePage"); const content2 = query.data ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(PageContent$8, { title: query.data.title }), ";" ] }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function PageContent$8({ title }) { return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(TitlePageHeaderImage, { title }), /* @__PURE__ */ jsxs("div", { className: "container mx-auto mt-24 px-14 md:mt-40 md:px-24", children: [ /* @__PURE__ */ jsx(TitlePageHeader, { title, showPoster: true }), /* @__PURE__ */ jsx( VideoGrid, { videos: title.videos, title, count: 24, heading: /* @__PURE__ */ jsx(SiteSectionHeading, { children: /* @__PURE__ */ jsx(Trans, { message: "Video gallery" }) }) } ) ] }) ] }); } function TitleImagesPage() { const query = useTitle("titlePage"); const content2 = query.data ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(PageContent$7, { title: query.data.title }), ";" ] }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function PageContent$7({ title }) { return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(TitlePageHeaderImage, { title }), /* @__PURE__ */ jsxs("div", { className: "container mx-auto mt-24 px-14 md:mt-40 md:px-24", children: [ /* @__PURE__ */ jsx(TitlePageHeader, { title, showPoster: true }), /* @__PURE__ */ jsx( TitlePageImageGrid, { images: title.images, srcSize: "lg", count: 24, heading: /* @__PURE__ */ jsx(SiteSectionHeading, { children: /* @__PURE__ */ jsx(Trans, { message: "Image gallery" }) }) } ) ] }) ] }); } function PersonPageAside({ data: { person, total_credits_count } }) { const { hasPermission } = useAuth(); const age = /* @__PURE__ */ jsx( Trans, { message: ":count years old", values: { count: /* @__PURE__ */ jsx(PersonAge, { person }) } } ); return /* @__PURE__ */ jsx( TitlePageAsideLayout, { className: "max-md:flex", poster: /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsxs("div", { className: "relative", children: [ /* @__PURE__ */ jsx(PersonPoster, { person, size: "w-140 md:w-full", srcSize: "lg" }), hasPermission("titles.update") && /* @__PURE__ */ jsx( IconButton, { elementType: Link, to: `/admin/people/${person.id}/edit`, className: "absolute bottom-6 right-4", color: "white", children: /* @__PURE__ */ jsx(EditIcon, {}) } ) ] }), /* @__PURE__ */ jsx(ShareButton, { person }) ] }), children: /* @__PURE__ */ jsxs("dl", { className: "mt-12 md:mt-24", children: [ person.known_for && /* @__PURE__ */ jsx(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Known for" }), children: /* @__PURE__ */ jsx(Trans, { message: person.known_for }) }), person.gender && /* @__PURE__ */ jsx(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Gender" }), children: /* @__PURE__ */ jsx("span", { className: "capitalize", children: /* @__PURE__ */ jsx(Trans, { message: person.gender }) }) }), total_credits_count ? /* @__PURE__ */ jsx(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Known credits" }), children: total_credits_count }) : null, person.birth_date ? /* @__PURE__ */ jsxs(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Born" }), children: [ /* @__PURE__ */ jsx(FormattedDate, { date: person.birth_date }), " ", !person.death_date && age ] }) : null, person.birth_place ? /* @__PURE__ */ jsx(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Birthplace" }), children: person.birth_place }) : null, person.death_date ? /* @__PURE__ */ jsxs(DetailItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Died" }), children: [ /* @__PURE__ */ jsx(FormattedDate, { date: person.death_date }), " (", age, ")" ] }) : null ] }) } ); } function ShareButton({ person }) { const link = getPersonLink(person, { absolute: true }); return /* @__PURE__ */ jsx(ShareMenuTrigger, { link, children: /* @__PURE__ */ jsx( Button, { variant: "outline", color: "primary", startIcon: /* @__PURE__ */ jsx(ShareIcon, {}), className: "mt-14 md:min-h-40 md:w-full", children: /* @__PURE__ */ jsx(Trans, { message: "Share" }) } ) }); } function useFullPersonCreditsForTitle({ person, credit, department }, options) { return useQuery({ queryKey: [ "people", `${person.id}`, "full-credits", `${credit.id}`, `${department}` ], queryFn: () => fetchCredits(person.id, credit.id, department), enabled: options.enabled }); } function fetchCredits(personId, titleId, department) { return apiClient.get( `people/${personId}/full-credits/${titleId}/${department}` ).then((response) => response.data); } function CharacterOrJob({ credit, className: className2 }) { var _a, _b, _c, _d; return /* @__PURE__ */ jsx("div", { className: className2, children: ((_a = credit.pivot) == null ? void 0 : _a.department) === "actors" ? ((_b = credit.pivot) == null ? void 0 : _b.character) ?? /* @__PURE__ */ jsx(Trans, { message: "Unknown" }) : /* @__PURE__ */ jsx("span", { className: "capitalize", children: ((_c = credit.pivot) == null ? void 0 : _c.job) ? /* @__PURE__ */ jsx(Trans, { message: (_d = credit.pivot) == null ? void 0 : _d.job }) : /* @__PURE__ */ jsx(Trans, { message: "Unknown" }) }) }); } function PersonPageCredits({ data: { credits, person } }) { return /* @__PURE__ */ jsxs("div", { className: "mt-34", children: [ /* @__PURE__ */ jsx(SiteSectionHeading, { fontSize: "text-xl", children: /* @__PURE__ */ jsx(Trans, { message: "Credits" }) }), /* @__PURE__ */ jsx(Accordion, { mode: "multiple", defaultExpandedValues: [0], isLazy: true, children: Object.entries(credits).map(([department, credits2]) => /* @__PURE__ */ jsx( AccordionItem, { labelClassName: "font-semibold text-base", description: /* @__PURE__ */ jsx( Trans, { message: "(:count credits)", values: { count: credits2.length } } ), label: /* @__PURE__ */ jsx("span", { className: "capitalize", children: /* @__PURE__ */ jsx( Trans, { message: department === "actors" ? "Acting" : department } ) }), children: credits2.map((credit, index) => { var _a; const isLast = credit === credits2[credits2.length - 1]; return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsxs("div", { className: "flex items-start py-6", children: [ /* @__PURE__ */ jsx( TitlePoster, { title: credit, size: "w-40", className: "mr-12", lazy: true, srcSize: "sm" } ), /* @__PURE__ */ jsxs("div", { className: "mr-24 pt-2", children: [ /* @__PURE__ */ jsx("div", { className: "font-semibold text-base", children: /* @__PURE__ */ jsx(TitleLink, { title: credit }) }), /* @__PURE__ */ jsx( CharacterOrJob, { className: "text-sm text-muted", credit } ), credit.credited_episode_count ? /* @__PURE__ */ jsx( EpisodeList, { credit, department, person } ) : null ] }), /* @__PURE__ */ jsx("div", { className: "text-sm text-muted ml-auto", children: credit.year }) ] }), !isLast && credit.year !== ((_a = credits2[index + 1]) == null ? void 0 : _a.year) && /* @__PURE__ */ jsx("div", { className: "h-1 w-full bg-divider my-8" }) ] }, credit.id); }) }, department )) }) ] }); } function EpisodeList({ credit, department, person }) { var _a; const [loadMoreEpisodes, setLoadMoreEpisodes] = useState(false); const query = useFullPersonCreditsForTitle( { person, department, credit }, { enabled: loadMoreEpisodes } ); const allEpisodesLoaded = credit.episodes.length === credit.credited_episode_count || query.data != null; const isLoadingMore = query.isLoading && query.fetchStatus !== "idle"; const shouldShowLoadMoreBtn = isLoadingMore || !allEpisodesLoaded; const episodeCredits = ((_a = query.data) == null ? void 0 : _a.credits.length) ? query.data.credits : credit.episodes; return /* @__PURE__ */ jsxs("div", { className: "mt-4", children: [ /* @__PURE__ */ jsx("div", { children: episodeCredits.map((episodeCredit) => /* @__PURE__ */ jsx("div", { className: "text-xs pl-10 mb-4", children: /* @__PURE__ */ jsxs(BulletSeparatedItems, { children: [ /* @__PURE__ */ jsxs("span", { children: [ "-", " ", /* @__PURE__ */ jsx( EpisodeLink, { title: credit, episode: episodeCredit, seasonNumber: episodeCredit.season_number } ), " ", "(", episodeCredit.year, ")" ] }), /* @__PURE__ */ jsx(CompactSeasonEpisode, { episode: episodeCredit }), /* @__PURE__ */ jsx(CharacterOrJob, { credit: episodeCredit }) ] }) }, episodeCredit.id)) }), shouldShowLoadMoreBtn && /* @__PURE__ */ jsx("div", { className: "mt-8", children: /* @__PURE__ */ jsx( Button, { size: "xs", disabled: isLoadingMore, onClick: () => { setLoadMoreEpisodes(true); }, children: /* @__PURE__ */ jsx( Trans, { message: "Show all :count episodes", values: { count: credit.credited_episode_count } } ) } ) }) ] }); } function PersonPage() { const query = usePerson("personPage"); const content2 = query.data ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(PageContent$6, { data: query.data }) ] }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function PageContent$6({ data }) { const { person, knownFor } = data; return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx("div", { className: "container mx-auto mt-14 px-14 md:mt-40 md:px-24", children: /* @__PURE__ */ jsxs("div", { className: "items-start gap-54 md:flex", children: [ /* @__PURE__ */ jsx(PersonPageAside, { data }), /* @__PURE__ */ jsxs("main", { className: "flex-auto @container max-md:mt-34", children: [ /* @__PURE__ */ jsx(TitlePageHeaderLayout, { name: person.name }), /* @__PURE__ */ jsx(Biography, { person }), /* @__PURE__ */ jsx(AdHost, { slot: "person_top", className: "pt-48" }), /* @__PURE__ */ jsx(KnowForList, { items: knownFor }), /* @__PURE__ */ jsx(PersonPageCredits, { data }) ] }) ] }) }) }); } function Biography({ person }) { if (!person.description) return null; return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(SiteSectionHeading, { fontSize: "text-xl", children: /* @__PURE__ */ jsx(Trans, { message: "Biography" }) }), /* @__PURE__ */ jsx( TruncatedDescription, { className: "text-sm", description: person.description } ) ] }); } function KnowForList({ items }) { if (!(items == null ? void 0 : items.length)) return null; return /* @__PURE__ */ jsxs("div", { className: "mt-34", children: [ /* @__PURE__ */ jsx(SiteSectionHeading, { fontSize: "text-xl", children: /* @__PURE__ */ jsx(Trans, { message: "Known for" }) }), /* @__PURE__ */ jsx(ContentGridLayout, { variant: "portrait", children: items.slice(0, 4).map((item) => /* @__PURE__ */ jsx( TitlePortraitGridItem, { item, description: /* @__PURE__ */ jsx(CharacterOrJob, { className: "text-muted", credit: item }) }, item.id )) }) ] }); } function TitleFullCreditsPage() { const query = useTitle("titleCreditsPage"); const content2 = query.data ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(PageContent$5, { data: query.data }) ] }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function PageContent$5({ data: { title, credits: groupedCredits = {} } }) { return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(TitlePageHeaderImage, { title }), /* @__PURE__ */ jsxs("div", { className: "container mx-auto mt-24 px-14 md:mt-40 md:px-24", children: [ /* @__PURE__ */ jsx(TitlePageHeader, { title, showPoster: true }), /* @__PURE__ */ jsxs("div", { className: "mt-48 @container", children: [ /* @__PURE__ */ jsx(SiteSectionHeading, { headingType: "h2", className: "mb-40", children: /* @__PURE__ */ jsx(Trans, { message: "Full cast and crew" }) }), Object.entries(groupedCredits).map(([department, credits]) => /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx("h3", { className: "mb-16 text-2xl font-bold capitalize", children: /* @__PURE__ */ jsx(Trans, { message: department }) }), /* @__PURE__ */ jsx(TitleCreditsGrid, { credits, className: "mb-68" }) ] }, department)) ] }) ] }) ] }); } function EpisodeFullCreditsPage() { const query = useEpisode("episodeCreditsPage"); const content2 = query.data ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(PageContent$4, { data: query.data }) ] }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function PageContent$4({ data: { title, episode, credits: groupedCredits } }) { return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(TitlePageHeaderImage, { title, episode }), /* @__PURE__ */ jsxs("div", { className: "container mx-auto mt-24 px-14 md:mt-40 md:px-24", children: [ /* @__PURE__ */ jsx(EpisodePageHeader, { title, episode, showPoster: true }), /* @__PURE__ */ jsxs("div", { className: "mt-48 @container", children: [ /* @__PURE__ */ jsx(SiteSectionHeading, { headingType: "h2", className: "mb-40", children: /* @__PURE__ */ jsx(Trans, { message: "Full cast and crew" }) }), groupedCredits && Object.entries(groupedCredits).map(([department, credits]) => /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx("h3", { className: "mb-16 text-2xl font-bold capitalize", children: /* @__PURE__ */ jsx(Trans, { message: department }) }), /* @__PURE__ */ jsx(TitleCreditsGrid, { credits, className: "mb-68" }) ] }, department)) ] }) ] }) ] }); } function NewsArticlePage() { const query = useNewsArticle("newsArticlePage"); const content2 = query.data ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(PageContent$3, { data: query.data }) ] }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function PageContent$3({ data: { article, related } }) { return /* @__PURE__ */ jsxs("div", { className: "container mx-auto mt-14 items-start gap-40 px-14 md:mt-40 md:px-24 lg:flex", children: [ /* @__PURE__ */ jsxs("main", { className: "mb-24 rounded border p-16 flex-auto", children: [ /* @__PURE__ */ jsx("h1", { className: "mb-24 text-3xl md:text-4xl", children: article.title }), /* @__PURE__ */ jsxs("div", { className: "items-start gap-16 md:flex", children: [ /* @__PURE__ */ jsx( NewsArticleImage, { article, size: "w-184 h-184", className: "max-md:mb-24" } ), /* @__PURE__ */ jsx( "div", { className: "prose text dark:prose-invert", dangerouslySetInnerHTML: { __html: article.body } } ) ] }), /* @__PURE__ */ jsxs(BulletSeparatedItems, { className: "mt-24 text-sm text-muted", children: [ /* @__PURE__ */ jsx(FormattedDate, { date: article.created_at }), article.byline ? /* @__PURE__ */ jsx(NewsArticleByline, { article }) : null, article.source ? /* @__PURE__ */ jsx(NewsArticleSourceLink, { article }) : null ] }) ] }), /* @__PURE__ */ jsx(OtherNews, { articles: related }) ] }); } function OtherNews({ articles }) { return /* @__PURE__ */ jsxs("div", { className: "w-full max-w-full flex-shrink-0 lg:w-400", children: [ /* @__PURE__ */ jsx("h2", { className: "mb-14 text-2xl", children: /* @__PURE__ */ jsx(Trans, { message: "Other news" }) }), articles.map((article) => /* @__PURE__ */ jsxs( "div", { className: "mb-14 flex items-center gap-14 rounded border pr-14", children: [ /* @__PURE__ */ jsx(NewsArticleImage, { article, size: "w-80 h-80", lazy: false }), /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [ /* @__PURE__ */ jsx("h3", { className: "line-clamp-2 text-sm font-semibold", children: /* @__PURE__ */ jsx(NewsArticleLink, { article }) }), /* @__PURE__ */ jsxs(BulletSeparatedItems, { className: "mt-6 text-sm text-muted", children: [ /* @__PURE__ */ jsx(FormattedDate, { date: article.created_at }), /* @__PURE__ */ jsx(NewsArticleByline, { article }) ] }) ] }) ] }, article.id )) ] }); } function useDeleteList() { const { trans } = useTrans(); return useMutation({ mutationFn: (payload) => deleteList(payload), onSuccess: async () => { await queryClient.invalidateQueries({ queryKey: ["channel"] }); toast(trans(message("List deleted"))); }, onError: (err) => showHttpErrorToast(err) }); } function deleteList(payload) { return apiClient.delete(`channel/${payload.listId}`).then((r2) => r2.data); } function UserListIndexItem({ list, user, showVisibility = true }) { const { user: authUser } = useAuth(); const canEdit = authUser && authUser.id === user.id; return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-24 border-b py-24", children: [ /* @__PURE__ */ jsx( ItemsPreview, { className: "max-md:hidden", list } ), /* @__PURE__ */ jsxs("section", { className: "flex-auto", children: [ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-8", children: [ /* @__PURE__ */ jsx( UserListLink, { list, className: "mr-auto block text-lg font-semibold capitalize" } ), !list.config.preventDeletion && !list.internal && canEdit && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( Button, { elementType: Link, to: `${getUserListLink(list)}/edit`, variant: "outline", size: "2xs", color: "primary", children: /* @__PURE__ */ jsx(Trans, { message: "Edit" }) } ), /* @__PURE__ */ jsxs(DialogTrigger, { type: "modal", children: [ /* @__PURE__ */ jsx( Button, { color: "danger", variant: "outline", radius: "rounded", size: "2xs", children: /* @__PURE__ */ jsx(Trans, { message: "Delete" }) } ), /* @__PURE__ */ jsx(DeleteListDialog, { list }) ] }) ] }) ] }), list.description && /* @__PURE__ */ jsx("p", { className: "mt-8 whitespace-nowrap text-sm text-muted", children: list.description }), /* @__PURE__ */ jsx("div", { className: "mt-12 text-sm", children: /* @__PURE__ */ jsxs("div", { className: "items-center justify-between gap-24 md:flex", children: [ user && /* @__PURE__ */ jsx(UserListByline, { user }), /* @__PURE__ */ jsx( UserListDetails, { list, showVisibility, className: "max-md:mt-12" } ) ] }) }) ] }) ] }); } function ItemsPreview({ list, className: className2 }) { var _a, _b; if (!((_a = list.items) == null ? void 0 : _a.length)) return null; return /* @__PURE__ */ jsx( "div", { className: clsx("flex items-center overflow-hidden rounded", className2), children: (_b = list.items) == null ? void 0 : _b.map((item, index) => /* @__PURE__ */ jsxs( "div", { style: { zIndex: 100 - index }, className: clsx( "relative overflow-hidden rounded shadow-[2px_0_7px_#000]", index !== 0 && "-ml-30" ), children: [ item.model_type === "title" ? /* @__PURE__ */ jsx(TitlePoster, { title: item, size: "w-70", srcSize: "sm" }) : /* @__PURE__ */ jsx(PersonPoster, { person: item, size: "w-70", srcSize: "sm" }), /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 shadow-[inset_0_0_0_1px_rgba(221,238,255,.35)]" }) ] }, item.id )) } ); } function DeleteListDialog({ list }) { const deleteList2 = useDeleteList(); const { close } = useDialogContext(); return /* @__PURE__ */ jsx( ConfirmationDialog, { isDanger: true, title: /* @__PURE__ */ jsx(Trans, { message: "Delete list" }), body: /* @__PURE__ */ jsx(Trans, { message: "Are you sure you want to delete this list?" }), confirm: /* @__PURE__ */ jsx(Trans, { message: "Delete" }), isLoading: deleteList2.isPending, onConfirm: () => deleteList2.mutate({ listId: list.id }, { onSuccess: close }) } ); } function useProfileLists() { const { userId = "me" } = useParams(); return useInfiniteData({ endpoint: `user-profile/${userId}/lists`, queryKey: ["channel", "profile-lists", userId], paginate: "simple" }); } function UserListsIndexPage() { const query = useProfileLists(); const content2 = query.data ? /* @__PURE__ */ jsx(PageContent$2, { query }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsxs(SitePageLayout, { children: [ /* @__PURE__ */ jsx(StaticPageTitle, { children: /* @__PURE__ */ jsx(Trans, { message: "Your lists" }) }), /* @__PURE__ */ jsxs("div", { className: "container mx-auto mt-48 px-24", children: [ /* @__PURE__ */ jsx("header", { children: /* @__PURE__ */ jsx( SiteSectionHeading, { headingType: "h1", margin: "mb-34", actions: /* @__PURE__ */ jsx( Button, { variant: "flat", color: "primary", elementType: Link, to: "new", children: /* @__PURE__ */ jsx(Trans, { message: "New list" }) } ), children: /* @__PURE__ */ jsx(Trans, { message: "My lists" }) } ) }), content2 ] }) ] }); } function PageContent$2({ query }) { const { user } = useAuth(); if (query.noResults) { return /* @__PURE__ */ jsx( IllustratedMessage, { className: "mt-80", image: /* @__PURE__ */ jsx(SvgImage, { src: todoImage }), title: /* @__PURE__ */ jsx(Trans, { message: "You have not created any lists yet." }) } ); } return /* @__PURE__ */ jsxs("div", { children: [ query.items.map((list) => /* @__PURE__ */ jsx(UserListIndexItem, { list, user }, list.id)), /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query }) ] }); } const userProfileQueryKey = (userId) => [ "users", `${userId}`, "profile" ]; function useUserProfile() { const { userId } = useParams(); return useQuery({ queryKey: userProfileQueryKey(userId), queryFn: () => fetchProfile(userId) }); } function fetchProfile(userId) { return apiClient.get(`user-profile/${userId}`).then((response) => response.data); } function ProfileDescription({ profile, className: className2 }) { if (!profile) return null; return /* @__PURE__ */ jsxs("div", { className: clsx("text-sm", className2), children: [ profile.description && /* @__PURE__ */ jsx("p", { className: "rounded text-secondary whitespace-nowrap overflow-hidden overflow-ellipsis", children: profile.description }), profile.city || profile.country ? /* @__PURE__ */ jsx("div", { className: "flex items-center gap-24 justify-between mt-4", children: (profile.city || profile.country) && /* @__PURE__ */ jsxs("div", { className: "rounded text-secondary w-max", children: [ profile.city, profile.city && ",", " ", profile.country ] }) }) : null ] }); } function useFollowedUsers() { const { user } = useAuth(); return useQuery({ queryKey: ["users", "followed", "ids"], queryFn: () => fetchIds(), enabled: !!user }); } function useIsUserFollowing(user) { const { data, isLoading } = useFollowedUsers(); return { isLoading, isFollowing: !!(data == null ? void 0 : data.ids.includes(user.id)) }; } function fetchIds() { return apiClient.get(`users/me/followed-users/ids`).then((response) => response.data); } function useFollowUser() { return useMutation({ mutationFn: (payload) => followUser(payload), onSuccess: async (response, { user }) => { await queryClient.invalidateQueries({ queryKey: ["users"] }); toast(message("Following :name", { values: { name: user.display_name } })); }, onError: (r2) => showHttpErrorToast(r2) }); } function followUser({ user }) { return apiClient.post(`users/${user.id}/follow`).then((r2) => r2.data); } function useUnfollowUser() { return useMutation({ mutationFn: (payload) => unfollowUser(payload), onSuccess: async (response, { user }) => { await queryClient.invalidateQueries({ queryKey: ["users"] }); toast( message("Stopped following :name", { values: { name: user.display_name } }) ); }, onError: (r2) => showHttpErrorToast(r2) }); } function unfollowUser({ user }) { return apiClient.post(`users/${user.id}/unfollow`).then((r2) => r2.data); } function FollowButton({ user, className: className2, minWidth = "min-w-82", ...buttonProps }) { const { user: currentUser } = useAuth(); const { isFollowing, isLoading } = useIsUserFollowing(user); const followUser2 = useFollowUser(); const unfollowUser2 = useUnfollowUser(); const mergedClassName = clsx(className2, minWidth); if (isFollowing) { return /* @__PURE__ */ jsx( Button, { ...buttonProps, className: mergedClassName, onClick: () => unfollowUser2.mutate({ user }), disabled: !currentUser || (currentUser == null ? void 0 : currentUser.id) === user.id || unfollowUser2.isPending || isLoading, children: /* @__PURE__ */ jsx(Trans, { message: "Unfollow" }) } ); } return /* @__PURE__ */ jsx( Button, { ...buttonProps, className: mergedClassName, onClick: () => followUser2.mutate({ user }), disabled: !currentUser || (currentUser == null ? void 0 : currentUser.id) === user.id || followUser2.isPending || isLoading, children: /* @__PURE__ */ jsx(Trans, { message: "Follow" }) } ); } function ProfileLinksForm() { const { fields, append, remove } = useFieldArray({ name: "links" }); return /* @__PURE__ */ jsxs("div", { children: [ fields.map((field, index) => { return /* @__PURE__ */ jsxs("div", { className: "flex gap-10 mb-10 items-end", children: [ /* @__PURE__ */ jsx( FormTextField, { required: true, type: "url", label: /* @__PURE__ */ jsx(Trans, { message: "URL" }), name: `links.${index}.url`, size: "sm", className: "flex-auto" } ), /* @__PURE__ */ jsx( FormTextField, { required: true, label: /* @__PURE__ */ jsx(Trans, { message: "Short title" }), name: `links.${index}.title`, size: "sm", className: "flex-auto" } ), /* @__PURE__ */ jsx( IconButton, { size: "sm", color: "primary", className: "flex-shrink-0", onClick: () => { remove(index); }, children: /* @__PURE__ */ jsx(CloseIcon, {}) } ) ] }, field.id); }), /* @__PURE__ */ jsx( Button, { variant: "text", color: "primary", startIcon: /* @__PURE__ */ jsx(AddIcon, {}), size: "xs", onClick: () => { append({ url: "", title: "" }); }, children: /* @__PURE__ */ jsx(Trans, { message: "Add another link" }) } ) ] }); } function useUpdateUserProfile(form) { const { user } = useAuth(); const { trans } = useTrans(); return useMutation({ mutationFn: (payload) => updateProfile(payload), onSuccess: async () => { if (user) { await queryClient.invalidateQueries({ queryKey: userProfileQueryKey(user.id) }); } toast(trans(message("Profile updated"))); }, onError: (err) => onFormQueryError(err, form) }); } function updateProfile(payload) { return apiClient.put("user-profile/me", payload).then((r2) => r2.data); } function EditUserProfileDialog({ user }) { var _a, _b, _c, _d; const { close, formId } = useDialogContext(); const { data } = useValueLists(["countries"]); const form = useForm({ defaultValues: { user: { username: user.username, avatar: user.avatar, first_name: user.first_name, last_name: user.last_name }, profile: { city: (_a = user.profile) == null ? void 0 : _a.city, country: (_b = user.profile) == null ? void 0 : _b.country, description: (_c = user.profile) == null ? void 0 : _c.description }, links: user.links } }); const updateProfile2 = useUpdateUserProfile(form); return /* @__PURE__ */ jsxs(Dialog, { size: "xl", children: [ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsx(Trans, { message: "Edit your profile" }) }), /* @__PURE__ */ jsx(DialogBody, { children: /* @__PURE__ */ jsx( Form, { id: formId, form, onSubmit: (values) => updateProfile2.mutate(values, { onSuccess: () => close() }), children: /* @__PURE__ */ jsxs(FileUploadProvider, { children: [ /* @__PURE__ */ jsxs("div", { className: "md:flex items-start gap-30", children: [ /* @__PURE__ */ jsx( FormImageSelector, { label: /* @__PURE__ */ jsx(Trans, { message: "Avatar" }), name: "user.avatar", diskPrefix: "avatars", variant: "avatar", previewSize: "w-200 h-200", className: "max-md:mb-20" } ), /* @__PURE__ */ jsxs("div", { className: "flex-auto", children: [ /* @__PURE__ */ jsx( FormTextField, { name: "user.username", label: /* @__PURE__ */ jsx(Trans, { message: "Username" }), className: "mb-24" } ), /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-24", children: [ /* @__PURE__ */ jsx( FormTextField, { name: "user.first_name", label: /* @__PURE__ */ jsx(Trans, { message: "First name" }), className: "flex-1 mb-24" } ), /* @__PURE__ */ jsx( FormTextField, { name: "user.last_name", label: /* @__PURE__ */ jsx(Trans, { message: "Last name" }), className: "flex-1 mb-24" } ) ] }), /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-24", children: [ /* @__PURE__ */ jsx( FormTextField, { name: "profile.city", label: /* @__PURE__ */ jsx(Trans, { message: "City" }), className: "flex-1 mb-24" } ), /* @__PURE__ */ jsxs( FormSelect, { showSearchField: true, className: "flex-1 mb-24", selectionMode: "single", name: "profile.country", label: /* @__PURE__ */ jsx(Trans, { message: "Country" }), children: [ /* @__PURE__ */ jsx(Item, { value: void 0, children: /* @__PURE__ */ jsx(Trans, { message: "None" }) }, "none"), (_d = data == null ? void 0 : data.countries) == null ? void 0 : _d.map((country) => /* @__PURE__ */ jsx(Item, { value: country.name, children: country.name }, country.code)) ] } ) ] }), /* @__PURE__ */ jsx( FormTextField, { name: "profile.description", label: /* @__PURE__ */ jsx(Trans, { message: "Description" }), inputElementType: "textarea", rows: 4 } ) ] }) ] }), /* @__PURE__ */ jsxs("div", { className: "mt-24", children: [ /* @__PURE__ */ jsx("div", { className: "mb-16 pb-16 border-b", children: /* @__PURE__ */ jsx(Trans, { message: "Your links" }) }), /* @__PURE__ */ jsx(ProfileLinksForm, {}) ] }) ] }) } ) }), /* @__PURE__ */ jsxs(DialogFooter, { children: [ /* @__PURE__ */ jsx( Button, { type: "button", onClick: () => { close(); }, children: /* @__PURE__ */ jsx(Trans, { message: "Cancel" }) } ), /* @__PURE__ */ jsx( Button, { form: formId, type: "submit", variant: "flat", color: "primary", disabled: updateProfile2.isPending, children: /* @__PURE__ */ jsx(Trans, { message: "Save" }) } ) ] }) ] }); } function ProfileStatsList({ user }) { const { auth: { getUserProfileLink } } = useContext(SiteConfigContext); const profileLink = getUserProfileLink(user); return /* @__PURE__ */ jsxs(StatsItems, { children: [ /* @__PURE__ */ jsx( StatsItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Followers" }), value: user.followers_count || 0, link: `${profileLink}/followers` } ), /* @__PURE__ */ jsx( StatsItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Following" }), value: user.followed_users_count || 0, link: `${profileLink}/followed-users` } ), /* @__PURE__ */ jsx( StatsItem, { label: /* @__PURE__ */ jsx(Trans, { message: "Lists" }), value: user.lists_count || 0, link: `${profileLink}/lists` } ) ] }); } function StatsItems(props) { const children = Children.toArray(props.children); return /* @__PURE__ */ jsx("div", { className: "flex items-center", children: children.map((child, index) => /* @__PURE__ */ jsxs(Fragment, { children: [ child, index < children.length - 1 && /* @__PURE__ */ jsx("div", { className: "mx-10 h-34 w-1 bg-divider" }) ] }, index)) }); } function StatsItem({ label, value, link }) { return /* @__PURE__ */ jsxs(Link, { to: link, className: "group block text-center", children: [ /* @__PURE__ */ jsx("div", { className: "text-lg font-bold", children: /* @__PURE__ */ jsx(FormattedNumber, { value }) }), /* @__PURE__ */ jsx("div", { className: "text-xs uppercase text-muted transition-colors group-hover:text-primary", children: label }) ] }); } function RemoteFavicon({ url, className: className2, size = "w-16 h-16", alt }) { if (!url) { return null; } const src = getFaviconSrc(url); return /* @__PURE__ */ jsx( "img", { className: clsx(size, className2), src: getFaviconSrc(url), alt: alt || `${src} favicon` } ); } const getFaviconSrc = memoize((url) => { if (url.includes("youtube")) { return "https://www.youtube.com/s/desktop/ca54e1bd/img/favicon.ico"; } if (!isAbsoluteUrl(url)) { url = `${window.location.protocol}//${window.location.host}`; } const domain = new URL(url).origin; return "https://www.google.com/s2/favicons?domain=" + domain; }); function ProfileLinks({ links, className: className2 }) { if (!(links == null ? void 0 : links.length)) return null; if (links.length === 1) { return /* @__PURE__ */ jsxs( "a", { className: "flex items-center max-md:justify-center gap-6 mt-24 md:mt-12 hover:text-primary transition-colors", href: links[0].url, children: [ /* @__PURE__ */ jsx(OpenInNewIcon, { className: "text-muted", size: "sm" }), /* @__PURE__ */ jsx("span", { className: "capitalize", children: links[0].title }) ] } ); } return /* @__PURE__ */ jsx("div", { className: clsx("flex items-center", className2), children: links.map((link) => /* @__PURE__ */ jsx(Tooltip, { label: link.title, children: /* @__PURE__ */ jsx( ButtonBase, { elementType: "a", href: link.url, target: "_blank", rel: "noreferrer", children: /* @__PURE__ */ jsx(RemoteFavicon, { url: link.url, alt: link.title, size: "w-20 h-20" }) } ) }, link.url)) }); } function ProfilePageHeader({ user }) { const { user: currentUser } = useAuth(); return /* @__PURE__ */ jsxs("div", { className: "flex flex-col md:flex-row items-center gap-24", children: [ /* @__PURE__ */ jsx(UserAvatar, { user, circle: true, size: "w-140 h-140" }), /* @__PURE__ */ jsxs("div", { className: "flex-auto", children: [ /* @__PURE__ */ jsxs("div", { className: "flex items-center mb-8 gap-8", children: [ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: user.display_name }), user.is_pro && /* @__PURE__ */ jsx(Chip, { size: "xs", color: "primary", radius: "rounded", className: "mt-2", children: /* @__PURE__ */ jsx(Trans, { message: "PRO" }) }) ] }), /* @__PURE__ */ jsx(ProfileDescription, { profile: user.profile }), /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-14 mt-12", children: [ (currentUser == null ? void 0 : currentUser.id) !== user.id && /* @__PURE__ */ jsx( FollowButton, { variant: "outline", color: "primary", size: "xs", user } ), (currentUser == null ? void 0 : currentUser.id) === user.id && /* @__PURE__ */ jsx(EditButton, { user }) ] }) ] }), /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx(ProfileStatsList, { user }), /* @__PURE__ */ jsx( ProfileLinks, { links: user.links, className: "flex-shrink-0 ml-auto mt-12" } ) ] }) ] }); } function EditButton({ user }) { return /* @__PURE__ */ jsxs(DialogTrigger, { type: "modal", children: [ /* @__PURE__ */ jsx(Button, { variant: "outline", size: "xs", startIcon: /* @__PURE__ */ jsx(EditIcon, {}), children: /* @__PURE__ */ jsx(Trans, { message: "Edit profile" }) }), /* @__PURE__ */ jsx(EditUserProfileDialog, { user }) ] }); } const PageTabs = [ { uri: "lists", label: message("Lists") }, { uri: "ratings", label: message("Ratings") }, { uri: "reviews", label: message("Reviews") }, { uri: "comments", label: message("Comments") }, { uri: "followers", label: message("Followers") }, { uri: "followed-users", label: message("Following") } ]; function UserProfilePage() { const query = useUserProfile(); const content2 = query.data ? /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(PageContent$1, { user: query.data.user }) ] }) : /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); return /* @__PURE__ */ jsx(SitePageLayout, { children: content2 }); } function PageContent$1({ user }) { return /* @__PURE__ */ jsxs("div", { className: "container mx-auto mt-24 px-14 md:mt-40 md:px-24", children: [ /* @__PURE__ */ jsx(ProfilePageHeader, { user }), /* @__PURE__ */ jsx(ProfileTabs, { user }) ] }); } function ProfileTabs({ user }) { const { auth: { getUserProfileLink } } = useContext(SiteConfigContext); const profileLink = getUserProfileLink(user); const { pathname } = useLocation(); const tabName = pathname.split("/").pop(); let selectedTab = PageTabs.findIndex((tab) => tab.uri === tabName); if (selectedTab === -1) { selectedTab = 0; } return /* @__PURE__ */ jsxs(Tabs, { className: "mt-34", selectedTab, children: [ /* @__PURE__ */ jsx(TabList, { children: PageTabs.map((tab) => /* @__PURE__ */ jsx( Tab, { width: "min-w-132", elementType: Link, to: `${profileLink}/${tab.uri}`, replace: true, children: /* @__PURE__ */ jsx(Trans, { ...tab.label }) }, tab.uri )) }), /* @__PURE__ */ jsx("div", { className: "mt-24", children: /* @__PURE__ */ jsx(Outlet, {}) }) ] }); } function ProfileListsPanel() { const userQuery = useUserProfile(); const user = userQuery.data.user; const listsQuery = useProfileLists(); if (listsQuery.noResults) { return /* @__PURE__ */ jsx( IllustratedMessage, { imageHeight: "h-auto", imageMargin: "mb-14", image: /* @__PURE__ */ jsx(ListAltIcon, { className: "text-muted" }), size: "sm", title: /* @__PURE__ */ jsx(Trans, { message: "No lists yet" }), description: /* @__PURE__ */ jsx( Trans, { message: "Follow :user for updates on lists they create in the future.", values: { user: user.display_name } } ) } ); } if (listsQuery.data) { return /* @__PURE__ */ jsxs("div", { children: [ listsQuery.items.map((list) => /* @__PURE__ */ jsx( UserListIndexItem, { list, user, showVisibility: false }, list.id )), /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query: listsQuery }) ] }); } return /* @__PURE__ */ jsx(PageStatus, { query: listsQuery }); } function useProfileRatings() { const { userId = "me" } = useParams(); return useInfiniteData({ endpoint: `user-profile/${userId}/ratings`, queryKey: ["reviews", "profile-page-ratings", userId], paginate: "simple" }); } function EpisodePortraitGridItem({ item, title, rating }) { return /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx( EpisodePoster, { episode: item, title, srcSize: "lg", aspect: "aspect-poster", showPlayButton: true } ), /* @__PURE__ */ jsxs("div", { className: "mt-10 text-sm", children: [ /* @__PURE__ */ jsx(TitleRating, { score: rating ?? item.rating, className: "mb-4" }), /* @__PURE__ */ jsx( TitleLinkWithEpisodeNumber, { title, episode: item, className: "block font-medium text-base" } ) ] }) ] }); } function ProfileRatingsPanel() { const userQuery = useUserProfile(); const user = userQuery.data.user; const ratingsQuery = useProfileRatings(); if (ratingsQuery.noResults) { return /* @__PURE__ */ jsx( IllustratedMessage, { imageHeight: "h-auto", imageMargin: "mb-14", image: /* @__PURE__ */ jsx(StarIcon, { className: "text-muted" }), size: "sm", title: /* @__PURE__ */ jsx(Trans, { message: "No ratings yet" }), description: /* @__PURE__ */ jsx( Trans, { message: "Follow :user for updates on titles they rate in the future.", values: { user: user.display_name } } ) } ); } if (ratingsQuery.data) { return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(ContentGridLayout, { variant: "portrait", children: ratingsQuery.items.map((review) => { const reviewable = review.reviewable; if (reviewable.model_type === "episode") { return /* @__PURE__ */ jsx( EpisodePortraitGridItem, { item: reviewable, title: reviewable.title, rating: review.score }, review.id ); } return /* @__PURE__ */ jsx( TitlePortraitGridItem, { item: review.reviewable, rating: review.score }, review.id ); }) }), /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query: ratingsQuery }) ] }); } return /* @__PURE__ */ jsx(PageStatus, { query: ratingsQuery }); } function useProfileReviews() { const { userId = "me" } = useParams(); return useInfiniteData({ endpoint: `user-profile/${userId}/reviews`, queryKey: ["reviews", "profile-page-reviews", userId], paginate: "simple" }); } function ProfileReviewsPanel() { const userQuery = useUserProfile(); const user = userQuery.data.user; const reviewsQuery = useProfileReviews(); if (reviewsQuery.noResults) { return /* @__PURE__ */ jsx( IllustratedMessage, { imageHeight: "h-auto", imageMargin: "mb-14", image: /* @__PURE__ */ jsx(RateReviewIcon, { className: "text-muted" }), size: "sm", title: /* @__PURE__ */ jsx(Trans, { message: "No reviews yet" }), description: /* @__PURE__ */ jsx( Trans, { message: "Follow :user for updates on titles they review in the future.", values: { user: user.display_name } } ) } ); } if (reviewsQuery.data) { return /* @__PURE__ */ jsxs(Fragment, { children: [ reviewsQuery.items.map((review) => /* @__PURE__ */ jsx(ReviewListItem, { review }, review.id)), /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query: reviewsQuery }) ] }); } return /* @__PURE__ */ jsx(PageStatus, { query: reviewsQuery }); } function ReviewListItem({ review }) { const totalVotes = review.helpful_count + review.not_helpful_count; const reviewable = review.reviewable; const title = reviewable.model_type === "episode" ? reviewable.title : reviewable; return /* @__PURE__ */ jsxs("div", { className: "mb-24 flex items-start gap-24 border-b pb-24", children: [ /* @__PURE__ */ jsx(TitlePoster, { title, size: "w-90", srcSize: "sm" }), /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx("div", { className: "text-lg font-semibold", children: reviewable.model_type === "episode" ? /* @__PURE__ */ jsx( TitleLinkWithEpisodeNumber, { title, episode: reviewable, target: "_blank" } ) : /* @__PURE__ */ jsx(TitleLink, { title, target: "_blank" }) }), /* @__PURE__ */ jsx(TitleRating, { className: "mb-8 mt-14", score: review.score }), /* @__PURE__ */ jsx("div", { className: "text-base font-semibold", children: review.title }), /* @__PURE__ */ jsx("p", { className: "mt-10 whitespace-pre-line text-sm", children: review.body }), totalVotes ? /* @__PURE__ */ jsx("div", { className: "mt-12 text-xs text-muted", children: /* @__PURE__ */ jsx( Trans, { message: ":helpfulCount out of :total people found this helpful.", values: { helpfulCount: review.helpful_count, total: review.helpful_count + review.not_helpful_count } } ) }) : null ] }) ] }); } function useProfileComments() { const { userId = "me" } = useParams(); return useInfiniteData({ endpoint: `user-profile/${userId}/comments`, queryKey: ["comment", "profile-page-comments", userId], paginate: "simple" }); } function ProfileCommentsPanel() { const userQuery = useUserProfile(); const user = userQuery.data.user; const commentsQuery = useProfileComments(); if (commentsQuery.noResults) { return /* @__PURE__ */ jsx( IllustratedMessage, { imageHeight: "h-auto", imageMargin: "mb-14", image: /* @__PURE__ */ jsx(RateReviewIcon, { className: "text-muted" }), size: "sm", title: /* @__PURE__ */ jsx(Trans, { message: "No comments yet" }), description: /* @__PURE__ */ jsx( Trans, { message: "Follow :user for updates on comments they post in the future.", values: { user: user.display_name } } ) } ); } if (commentsQuery.data) { return /* @__PURE__ */ jsxs(Fragment, { children: [ commentsQuery.items.map((comment) => /* @__PURE__ */ jsx(CommentListItem, { comment }, comment.id)), /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query: commentsQuery }) ] }); } return /* @__PURE__ */ jsx(PageStatus, { query: commentsQuery }); } function CommentListItem({ comment }) { const commentable = comment.commentable; const title = commentable.model_type === "episode" ? commentable.title : commentable; return /* @__PURE__ */ jsxs("div", { className: "mb-24 flex items-start gap-24 border-b pb-24", children: [ /* @__PURE__ */ jsx(TitlePoster, { title, size: "w-90", srcSize: "sm" }), /* @__PURE__ */ jsxs("div", { children: [ /* @__PURE__ */ jsx("div", { className: "text-lg font-semibold", children: commentable.model_type === "episode" ? /* @__PURE__ */ jsx( TitleLinkWithEpisodeNumber, { title, episode: commentable, target: "_blank" } ) : /* @__PURE__ */ jsx(TitleLink, { title, target: "_blank" }) }), /* @__PURE__ */ jsx("time", { className: "mt-12 block text-xs text-muted", children: /* @__PURE__ */ jsx(FormattedRelativeTime, { date: comment.created_at }) }), /* @__PURE__ */ jsx("p", { className: "mt-8 whitespace-pre-line text-sm", children: comment.content }), comment.upvotes ? /* @__PURE__ */ jsxs("div", { className: "mt-12 flex items-center gap-8 text-muted", children: [ /* @__PURE__ */ jsx(ThumbUpIcon, { size: "sm" }), /* @__PURE__ */ jsx("div", { children: comment.upvotes }) ] }) : null ] }) ] }); } function useProfileFollowers() { const { userId = "me" } = useParams(); return useInfiniteData({ endpoint: `users/${userId}/followers`, queryKey: ["users", "profile-page-followers", userId], paginate: "simple" }); } function FollowerListItem({ follower }) { return /* @__PURE__ */ jsxs( "div", { className: "flex items-center gap-16 mb-16 pb-16 border-b", children: [ /* @__PURE__ */ jsx(UserAvatar, { user: follower, size: "lg" }), /* @__PURE__ */ jsxs("div", { className: "text-sm", children: [ /* @__PURE__ */ jsx(UserProfileLink, { user: follower }), follower.followers_count && follower.followers_count > 0 ? /* @__PURE__ */ jsx("div", { className: "text-xs text-muted", children: /* @__PURE__ */ jsx( Trans, { message: "[one 1 followers|other :count followers]", values: { count: follower.followers_count } } ) }) : null ] }), /* @__PURE__ */ jsx( FollowButton, { variant: "outline", size: "xs", className: "ml-auto", user: follower } ) ] }, follower.id ); } function ProfileFollowersPanel() { const userQuery = useUserProfile(); const user = userQuery.data.user; const followersQuery = useProfileFollowers(); if (followersQuery.noResults) { return /* @__PURE__ */ jsx( IllustratedMessage, { imageHeight: "h-auto", imageMargin: "mb-14", image: /* @__PURE__ */ jsx(BookmarkBorderIcon, { className: "text-muted" }), size: "sm", title: /* @__PURE__ */ jsx(Trans, { message: "No followers yet" }), description: /* @__PURE__ */ jsx( Trans, { message: "Be the first to follow :name.", values: { name: user.display_name } } ) } ); } if (followersQuery.data) { return /* @__PURE__ */ jsxs(Fragment, { children: [ followersQuery.items.map((follower) => /* @__PURE__ */ jsx(FollowerListItem, { follower }, follower.id)), /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query: followersQuery }) ] }); } return /* @__PURE__ */ jsx(PageStatus, { query: followersQuery }); } function useProfileFollowedUsers() { const { userId = "me" } = useParams(); return useInfiniteData({ endpoint: `users/${userId}/followed-users`, queryKey: ["users", "profile-page-followed-users", userId], paginate: "simple" }); } function ProfileFollowedUsersPanel() { const userQuery = useUserProfile(); const user = userQuery.data.user; const followedUsersQuery = useProfileFollowedUsers(); if (followedUsersQuery.noResults) { return /* @__PURE__ */ jsx( IllustratedMessage, { imageHeight: "h-auto", imageMargin: "mb-14", image: /* @__PURE__ */ jsx(BookmarkBorderIcon, { className: "text-muted" }), size: "sm", title: /* @__PURE__ */ jsx(Trans, { message: "Not following anyone yet" }), description: /* @__PURE__ */ jsx( Trans, { message: "Check back later to see users :user is following.", values: { user: user.display_name } } ) } ); } if (followedUsersQuery.data) { return /* @__PURE__ */ jsxs(Fragment, { children: [ followedUsersQuery.items.map((followedUser) => /* @__PURE__ */ jsx(FollowerListItem, { follower: followedUser }, followedUser.id)), /* @__PURE__ */ jsx(InfiniteScrollSentinel, { query: followedUsersQuery }) ] }); } return /* @__PURE__ */ jsx(PageStatus, { query: followedUsersQuery }); } function SearchPage() { const { query: searchTerm } = useParams(); const query = useSearchResults("searchPage", searchTerm); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(PageMetaTags, { query }), /* @__PURE__ */ jsx(SitePageLayout, { children: /* @__PURE__ */ jsx("section", { className: "container mx-auto mt-24 px-14 md:mt-40 md:px-24", children: /* @__PURE__ */ jsxs("main", { children: [ /* @__PURE__ */ jsx(MobileSearchBar, {}), /* @__PURE__ */ jsx(PageContent, { query }) ] }) }) }) ] }); } function MobileSearchBar() { const { searchQuery = "" } = useParams(); const navigate = useNavigate(); const { trans } = useTrans(); return /* @__PURE__ */ jsx( TextField, { defaultValue: searchQuery, onChange: (e) => { navigate(`/search/${e.target.value}`, { replace: true }); }, autoFocus: true, className: "w-full md:hidden", size: "lg", placeholder: trans(message("Search...")) } ); } function PageContent({ query }) { const { branding } = useSettings(); if (query.data) { return /* @__PURE__ */ jsx(SearchResults, { query }); } if (query.fetchStatus === "idle") { return /* @__PURE__ */ jsx( IllustratedMessage, { className: "mt-40", image: /* @__PURE__ */ jsx(SearchIcon, { size: "xl" }), imageHeight: "h-auto", imageMargin: "mb-12", title: /* @__PURE__ */ jsx( Trans, { message: "Search :siteName", values: { siteName: branding.site_name } } ), description: /* @__PURE__ */ jsx(Trans, { message: "Find movies, tv series, people and more." }) } ); } return /* @__PURE__ */ jsx(PageStatus, { query, loaderClassName: "absolute inset-0 m-auto" }); } function SearchResults({ query }) { const { query: searchTerm } = useParams(); const { movies, series, people } = useMemo(() => { var _a; const movies2 = []; const series2 = []; const people2 = []; (_a = query.data) == null ? void 0 : _a.results.forEach((result) => { if (result.model_type === TITLE_MODEL && result.is_series) { series2.push(result); } else if (result.model_type === TITLE_MODEL && !result.is_series) { movies2.push(result); } else if (result.model_type === PERSON_MODEL) { people2.push(result); } }); return { movies: movies2, series: series2, people: people2 }; }, [query]); return /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( SiteSectionHeading, { className: "my-24 md:mb-48", headingType: "h1", fontSize: "text-xl md:text-3xl", hideBorder: true, children: /* @__PURE__ */ jsx( Trans, { message: "Search results for: “:query“", values: { query: searchTerm } } ) } ), movies.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-48", children: [ /* @__PURE__ */ jsx(SiteSectionHeading, { fontSize: "text-2xl", children: /* @__PURE__ */ jsx(Trans, { message: "Movies" }) }), /* @__PURE__ */ jsx(ContentGrid, { content: movies, variant: "portrait" }) ] }), series.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-48", children: [ /* @__PURE__ */ jsx(SiteSectionHeading, { fontSize: "text-2xl", children: /* @__PURE__ */ jsx(Trans, { message: "Series" }) }), /* @__PURE__ */ jsx(ContentGrid, { content: series, variant: "portrait" }) ] }), people.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-48", children: [ /* @__PURE__ */ jsx(SiteSectionHeading, { fontSize: "text-2xl", children: /* @__PURE__ */ jsx(Trans, { message: "People" }) }), /* @__PURE__ */ jsx(ContentGrid, { content: people, variant: "portrait" }) ] }) ] }); } const RouteConfig = [ { index: true, element: /* @__PURE__ */ jsx(HomepageChannelPage, {}) }, { path: "search", element: /* @__PURE__ */ jsx(SearchPage, {}) }, { path: "search/:query", element: /* @__PURE__ */ jsx(SearchPage, {}) }, // Watch { path: "watch/:videoId", element: /* @__PURE__ */ jsx(WatchPage, {}) }, // Titles { path: "/titles/:titleId/:titleSlug", element: /* @__PURE__ */ jsx(TitlePage, {}) }, { path: "/titles/:titleId/:titleSlug/videos", element: /* @__PURE__ */ jsx(TitleVideosPage, {}) }, { path: "/titles/:titleId/:titleSlug/images", element: /* @__PURE__ */ jsx(TitleImagesPage, {}) }, { path: "/titles/:titleId/:titleSlug/full-credits", element: /* @__PURE__ */ jsx(TitleFullCreditsPage, {}) }, { path: "/titles/:titleId/:titleSlug/season/:season", element: /* @__PURE__ */ jsx(SeasonPage, {}) }, { path: "/titles/:titleId/:titleSlug/season/:season/episode/:episode", element: /* @__PURE__ */ jsx(EpisodePage, {}) }, { path: "/titles/:titleId/:titleSlug/season/:season/episode/:episode/full-credits", element: /* @__PURE__ */ jsx(EpisodeFullCreditsPage, {}) }, // People { path: "/people/:personId", element: /* @__PURE__ */ jsx(PersonPage, {}) }, { path: "/people/:personId/:personSlug", element: /* @__PURE__ */ jsx(PersonPage, {}) }, // News { path: "/news/:articleId", element: /* @__PURE__ */ jsx(NewsArticlePage, {}) }, // Profile page { path: "user/:userId/:slug", element: /* @__PURE__ */ jsx(UserProfilePage, {}), children: [ { index: true, element: /* @__PURE__ */ jsx(ProfileListsPanel, {}) }, { path: "lists", element: /* @__PURE__ */ jsx(ProfileListsPanel, {}) }, { path: "ratings", element: /* @__PURE__ */ jsx(ProfileRatingsPanel, {}) }, { path: "reviews", element: /* @__PURE__ */ jsx(ProfileReviewsPanel, {}) }, { path: "comments", element: /* @__PURE__ */ jsx(ProfileCommentsPanel, {}) }, { path: "followers", element: /* @__PURE__ */ jsx(ProfileFollowersPanel, {}) }, { path: "followed-users", element: /* @__PURE__ */ jsx(ProfileFollowedUsersPanel, {}) } ] }, { path: "user/:userId/:slug/:tab", element: /* @__PURE__ */ jsx(UserProfilePage, {}) }, // User Lists { path: "/lists", element: /* @__PURE__ */ jsx(AuthRoute, { children: /* @__PURE__ */ jsx(UserListsIndexPage, {}) }) }, { path: "/lists/new", element: /* @__PURE__ */ jsx(AuthRoute, { children: /* @__PURE__ */ jsx(SitePageLayout, { children: /* @__PURE__ */ jsx(CreateUserListPage, {}) }) }) }, { path: "/lists/:slugOrId", element: /* @__PURE__ */ jsx(ChannelPage, { type: "list" }) }, { path: "/lists/:slugOrId/edit", element: /* @__PURE__ */ jsx(SitePageLayout, { children: /* @__PURE__ */ jsx(EditUserListPage, {}) }) }, // Channels { path: ":slugOrId", element: /* @__PURE__ */ jsx(ChannelPage, {}) }, { path: "channel/:slugOrId", element: /* @__PURE__ */ jsx(ChannelPage, {}) }, { path: ":slugOrId/:restriction", element: /* @__PURE__ */ jsx(ChannelPage, {}) }, { path: "channel/:slugOrId/:restriction", element: /* @__PURE__ */ jsx(ChannelPage, {}) }, { path: "*", element: /* @__PURE__ */ jsx(NotFoundPage, {}) } ]; function HomepageChannelPage() { const { homepage } = useSettings(); let slugOrId = "homepage"; if ((homepage == null ? void 0 : homepage.type) === "channel" && homepage.value) { slugOrId = homepage.value; } return /* @__PURE__ */ jsx(ChannelPage, { slugOrId }); } function SiteRoutes() { return useRoutes(RouteConfig); } export { SiteRoutes as default }; //# sourceMappingURL=site-routes-cce2e301.mjs.map