Files
react-native-omni/src/provider.tsx
T

72 lines
1.7 KiB
TypeScript
Executable File

import {
createContext,
type ReactNode,
useContext,
useEffect,
useEffectEvent,
useRef,
useState,
} from "react";
import { NitroModules } from "react-native-nitro-modules";
import type {
OmniPlayer as NativeOmniPlayer,
OmniPlayerFactory,
} from "./specs/omni-player.nitro";
import type { AndroidBackend, OmniPlayer, PlayerBackend } from "./types/player";
import type { CastOptions, Source } from "./types/source";
const ProviderFactory =
NitroModules.createHybridObject<OmniPlayerFactory>("OmniPlayerFactory");
const PlayerCtx = createContext<OmniPlayer>(null!);
export const OmniProvider = ({
children,
source,
backend = { android: "vlc" },
showNotification = false,
cast,
}: {
source?: Source;
cast?: CastOptions;
backend?: PlayerBackend;
children: ReactNode;
showNotification?: boolean;
}) => {
const [player, setPlayer] = useState<NativeOmniPlayer | null>(null);
const createPlayer = useEffectEvent((aBackend: AndroidBackend) =>
ProviderFactory.createPlayer({ android: aBackend }, cast),
);
useEffect(() => {
setPlayer(createPlayer(backend.android ?? "vlc"));
}, [backend.android]);
useEffect(() => {
if (!player) return;
return () => player.abandon();
}, [player]);
const inited = useRef<NativeOmniPlayer | null>(null);
useEffect(() => {
if (!player) return;
if (inited.current !== player) {
inited.current = player;
if (source == null) return;
}
player.source = source;
}, [player, source]);
useEffect(() => {
if (player) player.showNotification = showNotification;
}, [player, showNotification]);
if (!player) return null;
return <PlayerCtx.Provider value={player}>{children}</PlayerCtx.Provider>;
};
export const usePlayer = () => {
return useContext(PlayerCtx);
};