import { ReactNode, useEffect, useMemo, useRef } from "react";
import { useTranslation } from "react-i18next";
import { getCachedMetadata } from "@/backend/helpers/providerApi";
import { Loading } from "@/components/layout/Loading";
import {
useEmbedScraping,
useSourceScraping,
} from "@/components/player/hooks/useSourceSelection";
import { Menu } from "@/components/player/internals/ContextMenu";
import { SelectableLink } from "@/components/player/internals/ContextMenu/Links";
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
import { usePlayerStore } from "@/stores/player/store";
export interface SourceSelectionViewProps {
id: string;
onChoose?: (id: string) => void;
}
export interface EmbedSelectionViewProps {
id: string;
sourceId: string | null;
}
export function EmbedOption(props: {
embedId: string;
url: string;
sourceId: string;
routerId: string;
}) {
const { t } = useTranslation();
const unknownEmbedName = t("player.menus.sources.unknownOption");
const embedName = useMemo(() => {
if (!props.embedId) return unknownEmbedName;
const sourceMeta = getCachedMetadata().find((s) => s.id === props.embedId);
return sourceMeta?.name ?? unknownEmbedName;
}, [props.embedId, unknownEmbedName]);
const { run, errored, loading } = useEmbedScraping(
props.routerId,
props.sourceId,
props.url,
props.embedId
);
return (
{embedName}
);
}
export function EmbedSelectionView({ sourceId, id }: EmbedSelectionViewProps) {
const { t } = useTranslation();
const router = useOverlayRouter(id);
const { run, watching, notfound, loading, items, errored } =
useSourceScraping(sourceId, id);
const sourceName = useMemo(() => {
if (!sourceId) return "...";
const sourceMeta = getCachedMetadata().find((s) => s.id === sourceId);
return sourceMeta?.name ?? "...";
}, [sourceId]);
const lastSourceId = useRef(null);
useEffect(() => {
if (lastSourceId.current === sourceId) return;
lastSourceId.current = sourceId;
if (!sourceId) return;
run();
}, [run, sourceId]);
let content: ReactNode = null;
if (loading)
content = (
);
else if (notfound)
content = (
{t("player.menus.sources.noStream.text")}
);
else if (items?.length === 0)
content = (
{t("player.menus.sources.noEmbeds.text")}
);
else if (errored)
content = (
{t("player.menus.sources.failed.text")}
);
else if (watching)
content = null; // when it starts watching, empty the display
else if (items && sourceId)
content = items.map((v) => (
));
return (
<>
router.navigate("/source")}>
{sourceName}
{content}
>
);
}
export function SourceSelectionView({
id,
onChoose,
}: SourceSelectionViewProps) {
const { t } = useTranslation();
const router = useOverlayRouter(id);
const metaType = usePlayerStore((s) => s.meta?.type);
const currentSourceId = usePlayerStore((s) => s.sourceId);
const sources = useMemo(() => {
if (!metaType) return [];
return getCachedMetadata()
.filter((v) => v.type === "source")
.filter((v) => v.mediaTypes?.includes(metaType));
}, [metaType]);
return (
<>
router.navigate("/")}>
{t("player.menus.sources.title")}
{sources.map((v) => (
{
onChoose?.(v.id);
router.navigate("/source/embeds");
}}
selected={v.id === currentSourceId}
>
{v.name}
))}
>
);
}