diff --git a/apps/expo/src/app/loading.tsx b/apps/expo/src/app/loading.tsx index 9b76086..88be6ea 100644 --- a/apps/expo/src/app/loading.tsx +++ b/apps/expo/src/app/loading.tsx @@ -1,108 +1,113 @@ -import { getVideoStream, transformSearchResultToScrapeMedia } from "@movie-web/provider-utils"; -import { fetchMediaDetails } from "@movie-web/tmdb"; -import { useLocalSearchParams, useRouter } from "expo-router"; import { useEffect, useState } from "react"; -import { Text } from 'react-native'; +import { Text } from "react-native"; +import { useLocalSearchParams, useRouter } from "expo-router"; + +import { + getVideoStream, + transformSearchResultToScrapeMedia, +} from "@movie-web/provider-utils"; +import { fetchMediaDetails } from "@movie-web/tmdb"; + +import type { VideoPlayerData } from "./videoPlayer"; import type { ItemData } from "~/components/item/item"; import ScreenLayout from "~/components/layout/ScreenLayout"; -import type { VideoPlayerData } from "./videoPlayer"; export default function LoadingScreenWrapper() { - const params = useLocalSearchParams(); - const data = params.data - ? (JSON.parse(params.data as string) as ItemData) - : null; - return ; + const params = useLocalSearchParams(); + const data = params.data + ? (JSON.parse(params.data as string) as ItemData) + : null; + return ; } function LoadingScreen({ data }: { data: ItemData | null }) { - const router = useRouter(); - const [eventLog, setEventLog] = useState([]); + const router = useRouter(); + const [eventLog, setEventLog] = useState([]); - const handleEvent = (event: unknown) => { - const formattedEvent = formatEvent(event); - setEventLog((prevLog) => [...prevLog, formattedEvent]); - }; + const handleEvent = (event: unknown) => { + const formattedEvent = formatEvent(event); + setEventLog((prevLog) => [...prevLog, formattedEvent]); + }; - useEffect(() => { - const fetchVideo = async () => { - if (!data) return null; - const { id, type } = data; - const media = await fetchMediaDetails(id, type).catch(() => null); - if (!media) return null; + useEffect(() => { + const fetchVideo = async () => { + if (!data) return null; + const { id, type } = data; + const media = await fetchMediaDetails(id, type).catch(() => null); + if (!media) return null; - const { result } = media; - let season: number | undefined; // defaults to 1 when undefined - let episode: number | undefined; + const { result } = media; + let season: number | undefined; // defaults to 1 when undefined + let episode: number | undefined; - if (type === "tv") { - // season = ?? undefined; - // episode = ?? undefined; - } + if (type === "tv") { + // season = ?? undefined; + // episode = ?? undefined; + } - const scrapeMedia = transformSearchResultToScrapeMedia( - type, - result, - season, - episode, - ); + const scrapeMedia = transformSearchResultToScrapeMedia( + type, + result, + season, + episode, + ); - const stream = await getVideoStream({ - media: scrapeMedia, - onEvent: handleEvent, - }).catch(() => null); - if (!stream) return null; + const stream = await getVideoStream({ + media: scrapeMedia, + onEvent: handleEvent, + }).catch(() => null); + if (!stream) return null; - return { stream, scrapeMedia } - }; + return { stream, scrapeMedia }; + }; - const initialize = async () => { - const video = await fetchVideo(); - if (!video || !data) { - return router.push({ pathname: "/(tabs)" }); - } + const initialize = async () => { + const video = await fetchVideo(); + if (!video || !data) { + return router.push({ pathname: "/(tabs)" }); + } - const videoPlayerData: VideoPlayerData = { - item: data, - stream: video.stream, - media: video.scrapeMedia - }; + const videoPlayerData: VideoPlayerData = { + item: data, + stream: video.stream, + media: video.scrapeMedia, + }; - router.replace({ - pathname: "/videoPlayer", - params: { data: JSON.stringify(videoPlayerData) }, - }); - }; + router.replace({ + pathname: "/videoPlayer", + params: { data: JSON.stringify(videoPlayerData) }, + }); + }; - void initialize(); - }, [data, router]); - - return ( - - {eventLog.map((event, index) => ( - - {event} - - ))} - - ); - } + void initialize(); + }, [data, router]); + + return ( + + {eventLog.map((event, index) => ( + + {event} + + ))} + + ); +} function formatEvent(event: unknown): string { - if (typeof event === 'string') { - return `Start: ID - ${event}`; - } else if (typeof event === 'object' && event !== null) { - const evt = event as Record; - if ('percentage' in evt) { - return `Update: ${String(evt.percentage)}% - Status: ${String(evt.status)}`; - } else if ('sourceIds' in evt) { - return `Initialization: Source IDs - ${String(evt.sourceIds)}`; - } else if ('sourceId' in evt) { - return `Discovered Embeds: Source ID - ${String(evt.sourceId)}`; - } - } - return JSON.stringify(event); - } \ No newline at end of file + if (typeof event === "string") { + return `Start: ID - ${event}`; + } else if (typeof event === "object" && event !== null) { + const evt = event as Record; + if ("percentage" in evt) { + return `Update: ${String(evt.percentage)}% - Status: ${String(evt.status)}`; + } else if ("sourceIds" in evt) { + return `Initialization: Source IDs - ${String(evt.sourceIds)}`; + } else if ("sourceId" in evt) { + return `Discovered Embeds: Source ID - ${String(evt.sourceId)}`; + } + } + return JSON.stringify(event); +} diff --git a/apps/expo/src/app/videoPlayer.tsx b/apps/expo/src/app/videoPlayer.tsx index 22272fc..03c3d3b 100644 --- a/apps/expo/src/app/videoPlayer.tsx +++ b/apps/expo/src/app/videoPlayer.tsx @@ -6,12 +6,8 @@ import * as NavigationBar from "expo-navigation-bar"; import { useLocalSearchParams, useRouter } from "expo-router"; import * as StatusBar from "expo-status-bar"; -import type { - ScrapeMedia, - Stream} from "@movie-web/provider-utils"; -import { - findHighestQuality, -} from "@movie-web/provider-utils"; +import type { ScrapeMedia, Stream } from "@movie-web/provider-utils"; +import { findHighestQuality } from "@movie-web/provider-utils"; import type { ItemData } from "~/components/item/item"; import type { HeaderData } from "~/components/player/Header"; @@ -28,9 +24,9 @@ export default function VideoPlayerWrapper() { } export interface VideoPlayerData { - item: ItemData; - stream: Stream; - media: ScrapeMedia; + item: ItemData; + stream: Stream; + media: ScrapeMedia; } interface VideoPlayerProps { @@ -54,56 +50,52 @@ const VideoPlayer: React.FC = ({ data }) => { useEffect(() => { const initializePlayer = async () => { - StatusBar.setStatusBarHidden(true); + StatusBar.setStatusBarHidden(true); await NavigationBar.setVisibilityAsync("hidden"); setIsLoading(true); - - if (!data) { - await dismissFullscreenPlayer(); - return router.push("/(tabs)"); - } - const { item, stream, media } = data; + if (!data) { + await dismissFullscreenPlayer(); + return router.push("/(tabs)"); + } - setHeaderData({ - title: item.title, - year: item.year, - season: - media.type === "show" ? media.season.number : undefined, - episode: - media.type === "show" - ? media.episode.number - : undefined, - }); + const { item, stream, media } = data; - let highestQuality; - let url; + setHeaderData({ + title: item.title, + year: item.year, + season: media.type === "show" ? media.season.number : undefined, + episode: media.type === "show" ? media.episode.number : undefined, + }); - switch (stream.type) { - case "file": - highestQuality = findHighestQuality(stream); - url = highestQuality ? stream.qualities[highestQuality]?.url : null; - return url ?? null; - case "hls": - url = stream.playlist; - } + let highestQuality; + let url; - // setTextTracks( - // stream.captions && stream.captions.length > 0 - // ? convertCaptionsToTextTracks(stream.captions) - // : [], - // ); + switch (stream.type) { + case "file": + highestQuality = findHighestQuality(stream); + url = highestQuality ? stream.qualities[highestQuality]?.url : null; + return url ?? null; + case "hls": + url = stream.playlist; + } - setVideoSrc({ - uri: url, - headers: { - ...stream.preferredHeaders, - ...stream.headers, - }, - }); + // setTextTracks( + // stream.captions && stream.captions.length > 0 + // ? convertCaptionsToTextTracks(stream.captions) + // : [], + // ); - setIsLoading(false); - }; + setVideoSrc({ + uri: url, + headers: { + ...stream.preferredHeaders, + ...stream.headers, + }, + }); + + setIsLoading(false); + }; setIsLoading(true); void presentFullscreenPlayer(); diff --git a/packages/provider-utils/src/index.ts b/packages/provider-utils/src/index.ts index ad1b133..5550a8a 100644 --- a/packages/provider-utils/src/index.ts +++ b/packages/provider-utils/src/index.ts @@ -1,6 +1,7 @@ +import type { ScrapeMedia, Stream } from "@movie-web/providers"; + export const name = "provider-utils"; export * from "./video"; export * from "./util"; -import type { Stream, ScrapeMedia } from "@movie-web/providers"; export type { Stream, ScrapeMedia }; diff --git a/packages/provider-utils/src/video.ts b/packages/provider-utils/src/video.ts index 383a6b9..135edd3 100644 --- a/packages/provider-utils/src/video.ts +++ b/packages/provider-utils/src/video.ts @@ -28,16 +28,16 @@ export async function getVideoStream({ consistentIpForRequests: true, }); - const options: RunnerOptions = { - media, - events: { - init: onEvent, - update: onEvent, - discoverEmbeds: onEvent, - start: onEvent, - } - }; - + const options: RunnerOptions = { + media, + events: { + init: onEvent, + update: onEvent, + discoverEmbeds: onEvent, + start: onEvent, + }, + }; + const result = await providers.runAll(options); if (!result) return null;