From 40eb846a685d05505c9fa6f3cd407efca01d8234 Mon Sep 17 00:00:00 2001 From: Pas <74743263+Pasithea0@users.noreply.github.com> Date: Sun, 19 Oct 2025 18:32:58 -0600 Subject: [PATCH] Revert "Delete duplicate code and unify source selecting views" This reverts commit 28d03a06a584824295b87a2e7162e50aa828d7fc. --- .../atoms/settings/SourceSelectingView.tsx | 9 +- src/pages/parts/player/SourceSelectPart.tsx | 167 +++++++++++++++++- 2 files changed, 162 insertions(+), 14 deletions(-) diff --git a/src/components/player/atoms/settings/SourceSelectingView.tsx b/src/components/player/atoms/settings/SourceSelectingView.tsx index 33381010..6b058ee1 100644 --- a/src/components/player/atoms/settings/SourceSelectingView.tsx +++ b/src/components/player/atoms/settings/SourceSelectingView.tsx @@ -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 ( <> - router.navigate("/source"))}> + router.navigate("/source")}> {sourceName} {content} diff --git a/src/pages/parts/player/SourceSelectPart.tsx b/src/pages/parts/player/SourceSelectPart.tsx index c5efdbae..cd371b7d 100644 --- a/src/pages/parts/player/SourceSelectPart.tsx +++ b/src/pages/parts/player/SourceSelectPart.tsx @@ -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 ( + + + {embedName} + + + ); +} + +// 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(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 = ( + + + + ); + 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 (items && props.sourceId) + content = items.map((v) => ( + + )); + + return ( + <> + {sourceName} + {content} + + ); +} // Main source selection view -export function SourceSelectPart(_props: { media: ScrapeMedia }) { +export function SourceSelectPart(props: { media: ScrapeMedia }) { const { t } = useTranslation(); const [selectedSourceId, setSelectedSourceId] = React.useState( 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 }) { setSelectedSourceId(null)} /> @@ -37,7 +181,16 @@ export function SourceSelectPart(_props: { media: ScrapeMedia }) {
{t("player.menus.sources.title")} - + + {sources.map((v) => ( + setSelectedSourceId(v.id)} + > + {v.name} + + ))} +