2023-10-05 22:12:25 +02:00
|
|
|
import { ProviderControls, ScrapeMedia } from "@movie-web/providers";
|
2023-10-06 00:20:19 +02:00
|
|
|
import classNames from "classnames";
|
|
|
|
import { useEffect, useRef } from "react";
|
2023-10-05 22:12:25 +02:00
|
|
|
import type { AsyncReturnType } from "type-fest";
|
2023-10-01 21:08:26 +02:00
|
|
|
|
2023-11-10 22:14:41 +01:00
|
|
|
import {
|
2023-11-11 16:17:13 +01:00
|
|
|
scrapePartsToProviderMetric,
|
2023-11-10 22:14:41 +01:00
|
|
|
useReportProviders,
|
|
|
|
} from "@/backend/helpers/report";
|
2023-10-02 21:04:40 +02:00
|
|
|
import { usePlayer } from "@/components/player/hooks/usePlayer";
|
2023-10-06 00:01:35 +02:00
|
|
|
import {
|
|
|
|
ScrapeCard,
|
|
|
|
ScrapeItem,
|
|
|
|
} from "@/components/player/internals/ScrapeCard";
|
2023-10-23 23:06:24 +02:00
|
|
|
import {
|
|
|
|
ScrapingItems,
|
|
|
|
ScrapingSegment,
|
|
|
|
useListCenter,
|
|
|
|
useScrape,
|
|
|
|
} from "@/hooks/useProviderScrape";
|
2023-10-01 21:08:26 +02:00
|
|
|
|
|
|
|
export interface ScrapingProps {
|
|
|
|
media: ScrapeMedia;
|
2023-10-05 22:12:25 +02:00
|
|
|
onGetStream?: (stream: AsyncReturnType<ProviderControls["runAll"]>) => void;
|
2023-10-23 23:06:24 +02:00
|
|
|
onResult?: (
|
|
|
|
sources: Record<string, ScrapingSegment>,
|
|
|
|
sourceOrder: ScrapingItems[]
|
|
|
|
) => void;
|
2023-10-01 21:08:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export function ScrapingPart(props: ScrapingProps) {
|
2023-10-02 21:04:40 +02:00
|
|
|
const { playMedia } = usePlayer();
|
2023-11-10 22:14:41 +01:00
|
|
|
const { report } = useReportProviders();
|
2023-10-06 00:01:35 +02:00
|
|
|
const { startScraping, sourceOrder, sources, currentSource } = useScrape();
|
|
|
|
|
|
|
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
|
|
const listRef = useRef<HTMLDivElement | null>(null);
|
2023-10-06 00:20:19 +02:00
|
|
|
const renderedOnce = useListCenter(
|
|
|
|
containerRef,
|
|
|
|
listRef,
|
|
|
|
sourceOrder,
|
|
|
|
currentSource
|
|
|
|
);
|
2023-10-01 21:08:26 +02:00
|
|
|
|
2023-10-23 23:06:24 +02:00
|
|
|
const resultRef = useRef({
|
|
|
|
sourceOrder,
|
|
|
|
sources,
|
|
|
|
});
|
|
|
|
useEffect(() => {
|
|
|
|
resultRef.current = {
|
|
|
|
sourceOrder,
|
|
|
|
sources,
|
|
|
|
};
|
|
|
|
}, [sourceOrder, sources]);
|
|
|
|
|
2023-10-02 21:04:40 +02:00
|
|
|
const started = useRef(false);
|
|
|
|
useEffect(() => {
|
|
|
|
if (started.current) return;
|
|
|
|
started.current = true;
|
|
|
|
(async () => {
|
|
|
|
const output = await startScraping(props.media);
|
2023-10-23 23:06:24 +02:00
|
|
|
props.onResult?.(
|
|
|
|
resultRef.current.sources,
|
|
|
|
resultRef.current.sourceOrder
|
|
|
|
);
|
2023-11-10 22:14:41 +01:00
|
|
|
report(
|
2023-11-11 16:17:13 +01:00
|
|
|
scrapePartsToProviderMetric(
|
|
|
|
props.media,
|
|
|
|
resultRef.current.sourceOrder,
|
|
|
|
resultRef.current.sources
|
2023-11-10 22:14:41 +01:00
|
|
|
)
|
|
|
|
);
|
2023-10-05 22:12:25 +02:00
|
|
|
props.onGetStream?.(output);
|
2023-10-02 21:04:40 +02:00
|
|
|
})();
|
2023-11-10 22:14:41 +01:00
|
|
|
}, [startScraping, props, playMedia, report]);
|
2023-10-02 21:04:40 +02:00
|
|
|
|
2023-10-08 19:35:11 +02:00
|
|
|
const currentProvider = sourceOrder.find(
|
|
|
|
(s) => sources[s.id].status === "pending"
|
|
|
|
);
|
2023-10-23 21:03:50 +02:00
|
|
|
let currentProviderIndex = sourceOrder.findIndex(
|
|
|
|
(provider) => currentProvider?.id === provider.id
|
|
|
|
);
|
|
|
|
if (currentProviderIndex === -1)
|
|
|
|
currentProviderIndex = sourceOrder.length - 1;
|
2023-10-08 19:35:11 +02:00
|
|
|
|
2023-10-01 21:08:26 +02:00
|
|
|
return (
|
2023-10-06 00:01:35 +02:00
|
|
|
<div className="h-full w-full relative" ref={containerRef}>
|
2023-10-06 00:20:19 +02:00
|
|
|
<div
|
|
|
|
className={classNames({
|
|
|
|
"absolute transition-[transform,opacity] opacity-0": true,
|
|
|
|
"!opacity-100": renderedOnce,
|
|
|
|
})}
|
|
|
|
ref={listRef}
|
|
|
|
>
|
2023-10-06 00:01:35 +02:00
|
|
|
{sourceOrder.map((order) => {
|
|
|
|
const source = sources[order.id];
|
2023-10-08 19:35:11 +02:00
|
|
|
const distance = Math.abs(
|
|
|
|
sourceOrder.findIndex((t) => t.id === order.id) -
|
|
|
|
currentProviderIndex
|
|
|
|
);
|
2023-10-06 00:01:35 +02:00
|
|
|
return (
|
2023-10-08 19:35:11 +02:00
|
|
|
<div
|
|
|
|
className="transition-opacity duration-100"
|
|
|
|
style={{ opacity: Math.max(0, 1 - distance * 0.3) }}
|
2023-10-06 00:01:35 +02:00
|
|
|
key={order.id}
|
|
|
|
>
|
2023-10-08 19:35:11 +02:00
|
|
|
<ScrapeCard
|
|
|
|
id={order.id}
|
|
|
|
name={source.name}
|
|
|
|
status={source.status}
|
|
|
|
hasChildren={order.children.length > 0}
|
|
|
|
percentage={source.percentage}
|
|
|
|
>
|
|
|
|
<div
|
|
|
|
className={classNames({
|
|
|
|
"space-y-6 mt-8": order.children.length > 0,
|
|
|
|
})}
|
|
|
|
>
|
|
|
|
{order.children.map((embedId) => {
|
|
|
|
const embed = sources[embedId];
|
|
|
|
return (
|
|
|
|
<ScrapeItem
|
|
|
|
id={embedId}
|
|
|
|
name={embed.name}
|
|
|
|
status={embed.status}
|
|
|
|
percentage={embed.percentage}
|
|
|
|
key={embedId}
|
|
|
|
/>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
</ScrapeCard>
|
|
|
|
</div>
|
2023-10-03 20:24:09 +02:00
|
|
|
);
|
2023-10-06 00:01:35 +02:00
|
|
|
})}
|
|
|
|
</div>
|
2023-10-01 21:08:26 +02:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|