mirror of
https://github.com/zoriya/react-native-omni.git
synced 2026-08-05 13:46:59 +00:00
feat(cast): allow custom cast data and custom receivers
This commit is contained in:
@@ -10,6 +10,7 @@ export type {
|
||||
Track,
|
||||
} from "./types/player";
|
||||
export type {
|
||||
CastOptions,
|
||||
Metadata,
|
||||
MixAudioMode,
|
||||
Source,
|
||||
|
||||
+2
-1
@@ -13,7 +13,7 @@ import type {
|
||||
Rendition,
|
||||
Track,
|
||||
} from "./types/player";
|
||||
import type { Source, Subtitle } from "./types/source";
|
||||
import type { CastOptions, Source, Subtitle } from "./types/source";
|
||||
|
||||
export type SubtitleFormat = "vtt" | "ass" | "pgs" | "native";
|
||||
|
||||
@@ -60,6 +60,7 @@ export class WebOmniPlayer implements OmniPlayer {
|
||||
this._store.state.toggleRemotePlayback();
|
||||
}
|
||||
|
||||
castOptions: CastOptions | null = null;
|
||||
_source: Source | null = null;
|
||||
private _showNotification = false;
|
||||
|
||||
|
||||
+3
-1
@@ -2,7 +2,7 @@ import { createContext, type ReactNode, useContext, useEffect } from "react";
|
||||
import { NitroModules } from "react-native-nitro-modules";
|
||||
import type { OmniPlayerFactory } from "./specs/omni-player.nitro";
|
||||
import type { OmniPlayer } from "./types/player";
|
||||
import type { Source } from "./types/source";
|
||||
import type { CastOptions, Source } from "./types/source";
|
||||
import { useLazyRef } from "./utils/lazy-ref";
|
||||
|
||||
const ProviderFactory =
|
||||
@@ -14,8 +14,10 @@ export const OmniProvider = ({
|
||||
children,
|
||||
source,
|
||||
showNotification = false,
|
||||
cast: _,
|
||||
}: {
|
||||
source: Source;
|
||||
cast?: CastOptions;
|
||||
children: ReactNode;
|
||||
showNotification?: boolean;
|
||||
}) => {
|
||||
|
||||
+15
-3
@@ -9,7 +9,7 @@ import {
|
||||
} from "react";
|
||||
import { WebOmniPlayer } from "./player.web";
|
||||
import type { OmniPlayer } from "./types/player";
|
||||
import type { Source } from "./types/source";
|
||||
import type { CastOptions, Source } from "./types/source";
|
||||
import { useLazyRef } from "./utils/lazy-ref";
|
||||
|
||||
export const VideoPlayer = createPlayer({ features: videoFeatures });
|
||||
@@ -19,15 +19,21 @@ const PlayerCtx = createContext<OmniPlayer>(null!);
|
||||
export const OmniProvider = ({
|
||||
children,
|
||||
source,
|
||||
cast,
|
||||
showNotification = false,
|
||||
}: {
|
||||
source: Source;
|
||||
cast?: CastOptions;
|
||||
children: ReactNode;
|
||||
showNotification?: boolean;
|
||||
}) => {
|
||||
return (
|
||||
<VideoPlayer.Provider>
|
||||
<PlayerInitializer source={source} showNotification={showNotification}>
|
||||
<PlayerInitializer
|
||||
source={source}
|
||||
cast={cast}
|
||||
showNotification={showNotification}
|
||||
>
|
||||
{children}
|
||||
</PlayerInitializer>
|
||||
</VideoPlayer.Provider>
|
||||
@@ -37,10 +43,12 @@ export const OmniProvider = ({
|
||||
const PlayerInitializer = ({
|
||||
children,
|
||||
source,
|
||||
cast,
|
||||
showNotification,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
source: Source;
|
||||
cast?: CastOptions;
|
||||
showNotification: boolean;
|
||||
}) => {
|
||||
const store = VideoPlayer.usePlayer();
|
||||
@@ -52,10 +60,14 @@ const PlayerInitializer = ({
|
||||
const uri = source.src[0]?.uri;
|
||||
if (uri !== seekedForSrc.current) {
|
||||
seekedForSrc.current = uri;
|
||||
if (source.startTime) store.seek(source.startTime)
|
||||
if (source.startTime) store.seek(source.startTime);
|
||||
}
|
||||
}, [source, store]);
|
||||
|
||||
useEffect(() => {
|
||||
player.castOptions = cast ?? null;
|
||||
}, [cast]);
|
||||
|
||||
useEffect(() => {
|
||||
player.showNotification = showNotification;
|
||||
}, [showNotification]);
|
||||
|
||||
@@ -7,6 +7,13 @@ export interface Source {
|
||||
fonts?: string[];
|
||||
metadata?: Metadata;
|
||||
mixAudio?: MixAudioMode;
|
||||
// Opaque, consumer-defined payload forwarded verbatim to the cast receiver
|
||||
// as the load request's customData. omni does not interpret it.
|
||||
castData?: unknown;
|
||||
}
|
||||
|
||||
export interface CastOptions {
|
||||
receiverApplicationId?: string;
|
||||
}
|
||||
|
||||
export interface VideoSrc {
|
||||
|
||||
+20
-20
@@ -1,6 +1,5 @@
|
||||
import type { HlsMediaConfig } from "@videojs/core/dom/media/hls-js";
|
||||
import { HlsJsVideo } from "@videojs/react/media/hlsjs-video";
|
||||
import { Video } from "@videojs/react/video";
|
||||
import {
|
||||
type CSSProperties,
|
||||
type RefObject,
|
||||
@@ -108,28 +107,29 @@ export const OmniView = ({
|
||||
const ref = useRef<HTMLVideoElement>(undefined!);
|
||||
|
||||
const src = player.source?.src[0];
|
||||
const isHls =
|
||||
src?.mimeType?.toLowerCase().includes("mpegurl") ||
|
||||
src?.uri.split(/[?#]/)[0]?.toLowerCase().endsWith(".m3u8") ||
|
||||
false;
|
||||
const Tech = isHls ? HlsJsVideo : Video;
|
||||
|
||||
const headersRef = useRef(src?.headers);
|
||||
headersRef.current = src?.headers;
|
||||
const castData = player.source?.castData;
|
||||
|
||||
const config = useMemo<HlsMediaConfig>(
|
||||
() => ({
|
||||
hlsJs: {
|
||||
xhrSetup: (xhr: XMLHttpRequest) => {
|
||||
const headers = headersRef.current;
|
||||
if (!headers) return;
|
||||
for (const [key, value] of Object.entries(headers)) {
|
||||
if (value) xhr.setRequestHeader(key, value);
|
||||
}
|
||||
() =>
|
||||
({
|
||||
hlsJs: {
|
||||
xhrSetup: (xhr: XMLHttpRequest) => {
|
||||
const headers = headersRef.current;
|
||||
if (!headers) return;
|
||||
for (const [key, value] of Object.entries(headers)) {
|
||||
if (value) xhr.setRequestHeader(key, value);
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
[],
|
||||
googleCast: {
|
||||
receiver: player.castOptions?.receiverApplicationId,
|
||||
customData: castData ?? null,
|
||||
},
|
||||
}) as HlsMediaConfig,
|
||||
[player.castOptions, castData],
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -138,10 +138,10 @@ export const OmniView = ({
|
||||
style={{ position: "relative", ...style }}
|
||||
>
|
||||
{src && (
|
||||
<Tech
|
||||
<HlsJsVideo
|
||||
ref={ref}
|
||||
src={src.uri}
|
||||
config={isHls ? config : undefined}
|
||||
config={config}
|
||||
autoPlay={autoplay}
|
||||
playsInline
|
||||
crossOrigin="anonymous"
|
||||
@@ -159,7 +159,7 @@ export const OmniView = ({
|
||||
label={subtitle.label ?? subtitle.language ?? subtitle.id}
|
||||
/>
|
||||
))}
|
||||
</Tech>
|
||||
</HlsJsVideo>
|
||||
)}
|
||||
<SubtitleOverlay
|
||||
video={ref}
|
||||
|
||||
Reference in New Issue
Block a user