Revert "Delete duplicate code and unify source selecting views"

This reverts commit 28d03a06a5.
This commit is contained in:
Pas 2025-10-19 18:32:58 -06:00
parent 28d03a06a5
commit 40eb846a68
2 changed files with 162 additions and 14 deletions

View file

@ -21,7 +21,6 @@ export interface SourceSelectionViewProps {
export interface EmbedSelectionViewProps {
id: string;
sourceId: string | null;
onBack?: () => void;
}
export function EmbedOption(props: {
@ -61,11 +60,7 @@ export function EmbedOption(props: {
);
}
export function EmbedSelectionView({
sourceId,
id,
onBack,
}: EmbedSelectionViewProps) {
export function EmbedSelectionView({ sourceId, id }: EmbedSelectionViewProps) {
const { t } = useTranslation();
const router = useOverlayRouter(id);
const { run, watching, notfound, loading, items, errored } =
@ -131,7 +126,7 @@ export function EmbedSelectionView({
return (
<>
<Menu.BackLink onClick={onBack || (() => router.navigate("/source"))}>
<Menu.BackLink onClick={() => router.navigate("/source")}>
{sourceName}
</Menu.BackLink>
<Menu.Section>{content}</Menu.Section>

View file

@ -1,20 +1,164 @@
import { ScrapeMedia } from "@p-stream/providers";
import React from "react";
import React, { ReactNode, useEffect, useMemo, useRef } from "react";
import { useTranslation } from "react-i18next";
import { getCachedMetadata } from "@/backend/helpers/providerApi";
import { Loading } from "@/components/layout/Loading";
import {
EmbedSelectionView,
SourceSelectionView,
} from "@/components/player/atoms/settings/SourceSelectingView";
useEmbedScraping,
useSourceScraping,
} from "@/components/player/hooks/useSourceSelection";
import { Menu } from "@/components/player/internals/ContextMenu";
import { SelectableLink } from "@/components/player/internals/ContextMenu/Links";
import { usePreferencesStore } from "@/stores/preferences";
// Embed option component
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 (
<SelectableLink loading={loading} error={errored} onClick={run}>
<span className="flex flex-col">
<span>{embedName}</span>
</span>
</SelectableLink>
);
}
// Embed selection view (when a source is selected)
function EmbedSelectionView(props: {
sourceId: string;
routerId: string;
onBack: () => void;
}) {
const { t } = useTranslation();
const { run, notfound, loading, items, errored } = useSourceScraping(
props.sourceId,
props.routerId,
);
const sourceName = useMemo(() => {
if (!props.sourceId) return "...";
const sourceMeta = getCachedMetadata().find((s) => s.id === props.sourceId);
return sourceMeta?.name ?? "...";
}, [props.sourceId]);
const lastSourceId = useRef<string | null>(null);
useEffect(() => {
if (lastSourceId.current === props.sourceId) return;
lastSourceId.current = props.sourceId;
if (!props.sourceId) return;
run();
}, [run, props.sourceId]);
let content: ReactNode = null;
if (loading)
content = (
<Menu.TextDisplay noIcon>
<Loading />
</Menu.TextDisplay>
);
else if (notfound)
content = (
<Menu.TextDisplay
title={t("player.menus.sources.noStream.title") ?? undefined}
>
{t("player.menus.sources.noStream.text")}
</Menu.TextDisplay>
);
else if (items?.length === 0)
content = (
<Menu.TextDisplay
title={t("player.menus.sources.noEmbeds.title") ?? undefined}
>
{t("player.menus.sources.noEmbeds.text")}
</Menu.TextDisplay>
);
else if (errored)
content = (
<Menu.TextDisplay
title={t("player.menus.sources.failed.title") ?? undefined}
>
{t("player.menus.sources.failed.text")}
</Menu.TextDisplay>
);
else if (items && props.sourceId)
content = items.map((v) => (
<EmbedOption
key={`${v.embedId}-${v.url}`}
embedId={v.embedId}
url={v.url}
routerId={props.routerId}
sourceId={props.sourceId}
/>
));
return (
<>
<Menu.BackLink onClick={props.onBack}>{sourceName}</Menu.BackLink>
<Menu.Section>{content}</Menu.Section>
</>
);
}
// Main source selection view
export function SourceSelectPart(_props: { media: ScrapeMedia }) {
export function SourceSelectPart(props: { media: ScrapeMedia }) {
const { t } = useTranslation();
const [selectedSourceId, setSelectedSourceId] = React.useState<string | null>(
null,
);
const routerId = "manualSourceSelect";
const preferredSourceOrder = usePreferencesStore((s) => s.sourceOrder);
const enableSourceOrder = usePreferencesStore((s) => s.enableSourceOrder);
const sources = useMemo(() => {
const metaType = props.media.type;
if (!metaType) return [];
const allSources = getCachedMetadata()
.filter((v) => v.type === "source")
.filter((v) => v.mediaTypes?.includes(metaType));
if (!enableSourceOrder || preferredSourceOrder.length === 0) {
return allSources;
}
// Sort sources according to preferred order
const orderedSources = [];
const remainingSources = [...allSources];
// Add sources in preferred order
for (const sourceId of preferredSourceOrder) {
const sourceIndex = remainingSources.findIndex((s) => s.id === sourceId);
if (sourceIndex !== -1) {
orderedSources.push(remainingSources[sourceIndex]);
remainingSources.splice(sourceIndex, 1);
}
}
// Add remaining sources that weren't in the preferred order
orderedSources.push(...remainingSources);
return orderedSources;
}, [props.media.type, preferredSourceOrder, enableSourceOrder]);
if (selectedSourceId) {
return (
@ -23,7 +167,7 @@ export function SourceSelectPart(_props: { media: ScrapeMedia }) {
<Menu.CardWithScrollable>
<EmbedSelectionView
sourceId={selectedSourceId}
id={routerId}
routerId={routerId}
onBack={() => setSelectedSourceId(null)}
/>
</Menu.CardWithScrollable>
@ -37,7 +181,16 @@ export function SourceSelectPart(_props: { media: ScrapeMedia }) {
<div className="w-full max-w-md h-[50vh] flex flex-col">
<Menu.CardWithScrollable>
<Menu.Title>{t("player.menus.sources.title")}</Menu.Title>
<SourceSelectionView id={routerId} onChoose={setSelectedSourceId} />
<Menu.Section className="pb-4">
{sources.map((v) => (
<SelectableLink
key={v.id}
onClick={() => setSelectedSourceId(v.id)}
>
{v.name}
</SelectableLink>
))}
</Menu.Section>
</Menu.CardWithScrollable>
</div>
</div>