diff --git a/src/backend/providers/gdriveplayer.ts b/src/backend/providers/gdriveplayer.ts index 492257a3..60c7ac4f 100644 --- a/src/backend/providers/gdriveplayer.ts +++ b/src/backend/providers/gdriveplayer.ts @@ -37,12 +37,14 @@ registerProvider({ rank: 69, type: [MWMediaType.MOVIE], - async scrape({ media: { imdbId } }) { + async scrape({ progress, media: { imdbId } }) { + progress(10); const streamRes = await fetch( `${ conf().CORS_PROXY_URL }https://database.gdriveplayer.us/player.php?imdb=${imdbId}` ).then((d) => d.text()); + progress(90); const page = new DOMParser().parseFromString(streamRes, "text/html"); const script: HTMLElement | undefined = Array.from( diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index 18398ace..7866066f 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -22,6 +22,7 @@ export enum Icons { COMPRESS = "compress", VOLUME = "volume", VOLUME_X = "volume_x", + X = "x", } export interface IconProps { @@ -51,6 +52,7 @@ const iconList: Record = { compress: ``, volume: ``, volume_x: ``, + x: ``, }; export const Icon = memo((props: IconProps) => { diff --git a/src/components/media/MediaCard.tsx b/src/components/media/MediaCard.tsx index f4287571..7b63bf7e 100644 --- a/src/components/media/MediaCard.tsx +++ b/src/components/media/MediaCard.tsx @@ -1,6 +1,7 @@ import { Link } from "react-router-dom"; import { DotList } from "@/components/text/DotList"; import { MWMediaMeta } from "@/backend/metadata/types"; +import { mediaTypeToJW } from "@/backend/metadata/justwatch"; export interface MediaCardProps { media: MWMediaMeta; @@ -42,9 +43,9 @@ export function MediaCard(props: MediaCardProps) { if (!props.linkable) return {content}; return ( {content} diff --git a/src/hooks/useScrape.ts b/src/hooks/useScrape.ts index 1a24eb4f..ca0004ed 100644 --- a/src/hooks/useScrape.ts +++ b/src/hooks/useScrape.ts @@ -3,7 +3,7 @@ import { MWStream } from "@/backend/helpers/streams"; import { DetailedMeta } from "@/backend/metadata/getmeta"; import { useEffect, useState } from "react"; -interface ScrapeEventLog { +export interface ScrapeEventLog { type: "provider" | "embed"; errored: boolean; percentage: number; diff --git a/src/setup/App.tsx b/src/setup/App.tsx index 629f7c04..563a8643 100644 --- a/src/setup/App.tsx +++ b/src/setup/App.tsx @@ -3,7 +3,7 @@ import { BookmarkContextProvider } from "@/state/bookmark"; import { WatchedContextProvider } from "@/state/watched"; import { NotFoundPage } from "@/views/notfound/NotFoundView"; -import { MediaView } from "@/views/MediaView"; +import { MediaView } from "@/views/media/MediaView"; import { SearchView } from "@/views/search/SearchView"; import { MWMediaType } from "@/backend/metadata/types"; diff --git a/src/views/media/MediaScrapeLog.tsx b/src/views/media/MediaScrapeLog.tsx new file mode 100644 index 00000000..20f8bb50 --- /dev/null +++ b/src/views/media/MediaScrapeLog.tsx @@ -0,0 +1,78 @@ +import { Icon, Icons } from "@/components/Icon"; +import { ScrapeEventLog } from "@/hooks/useScrape"; + +interface MediaScrapeLogProps { + events: ScrapeEventLog[]; +} + +interface MediaScrapePillProps { + event: ScrapeEventLog; +} + +function MediaScrapePillSkeleton() { + return
; +} + +function MediaScrapePill({ event }: MediaScrapePillProps) { + return ( +
+
+ {!event.errored ? ( + + + + ) : ( + + )} +
+
+

+ {event.id} +

+
+
+ ); +} + +export function MediaScrapeLog(props: MediaScrapeLogProps) { + return ( +
+
+
+
+ + {props.events.map((v) => ( + + ))} + +
+
+
+
+
+
+ ); +} diff --git a/src/views/MediaView.tsx b/src/views/media/MediaView.tsx similarity index 62% rename from src/views/MediaView.tsx rename to src/views/media/MediaView.tsx index 926f4c54..f9484c1a 100644 --- a/src/views/MediaView.tsx +++ b/src/views/media/MediaView.tsx @@ -7,9 +7,21 @@ import { VideoPlayerHeader } from "@/components/video/parts/VideoPlayerHeader"; import { DetailedMeta, getMetaFromId } from "@/backend/metadata/getmeta"; import { JWMediaToMediaType } from "@/backend/metadata/justwatch"; import { SourceControl } from "@/components/video/controls/SourceControl"; +import { Loading } from "@/components/layout/Loading"; +import { MediaScrapeLog } from "./MediaScrapeLog"; -function MediaViewLoading() { - return

Loading meta...

; +function MediaViewLoading(props: { onGoBack(): void }) { + return ( +
+
+ +
+
+ +

Finding the best video for you

+
+
+ ); } interface MediaViewScrapingProps { @@ -18,7 +30,7 @@ interface MediaViewScrapingProps { meta: DetailedMeta; } function MediaViewScraping(props: MediaViewScrapingProps) { - const { eventLog, pending, stream } = useScrape(props.meta); + const { eventLog, stream } = useScrape(props.meta); useEffect(() => { if (stream) { @@ -26,24 +38,21 @@ function MediaViewScraping(props: MediaViewScrapingProps) { } }, [stream, props]); + // TODO error screen if no streams found + return ( -
- -

pending: {pending.toString()}

-

- stream: {stream?.streamUrl} - {stream?.type} - {stream?.quality} -

-
- {eventLog.map((v) => ( -
-

- {v.percentage}% - {v.type} - {v.errored ? "ERROR" : "pending"} -

-
- ))} +
+
+ +
+
+ +

Finding the best video for you

+ +
); } @@ -70,10 +79,9 @@ export function MediaView() { }, [setMeta, params]); // TODO watched store - // TODO scrape loading state // TODO error page with video header - if (!meta) return ; + if (!meta) return ; if (!stream) return (