/** * Context Provider for isPlaying medias */ import { FC, useCallback, useRef, createContext, useContext, ReactNode, } from 'react'; import ReactPlayer from 'react-player'; import { StoreApi } from 'zustand'; import { useStoreWithEqualityFn } from 'zustand/traditional'; import { CorePlayerInitialState } from '../components'; import { createMediaStore, MediaStore } from '../store/media-store'; import { Highlight, MediaType, StateSelector } from '../types'; import { BlendColors } from '../utils'; import { HighlightsProvider } from './HighlightsProvider'; const MediaStoreContext = createContext | null>(null); export interface MediaProviderProps { isAudio: boolean; mediaType: MediaType; isPipEnabled: boolean; /** Highlights to be displayed in the scrub bar */ highlights?: Highlight[]; /** Blend highlights colors in the scrub bar */ getHighlightColorBlended?: BlendColors; /** Callback for media store update */ onStoreUpdate?: (store: MediaStore) => void; /** `CorePlayer` initial state */ initialState: CorePlayerInitialState; /** Trigger points (in sec) when an alert event is emitted */ alarms?: number[]; children: ReactNode; } /** Keep `MediaStore` in a context to distribute them to UI Controls * @category ContextProvider */ export const MediaProvider: FC = ({ initialState, getHighlightColorBlended, children, onStoreUpdate, highlights, alarms = [], isAudio, mediaType, isPipEnabled = true, }) => { const reactPlayerRef = useRef(null); const playPromiseRef = useRef | undefined>(undefined); const mediaContainerRef = useRef(null); const lastActivityRef = useRef(0); const lastPipActivityRef = useRef(0); const markActivity = useCallback(() => { if (lastActivityRef) { lastActivityRef.current = Date.now(); } }, []); const markPipActivity = useCallback(() => { if (lastPipActivityRef) { lastPipActivityRef.current = Date.now(); } }, []); const contextValueRef = useRef( createMediaStore({ initialState, getHighlightColorBlended, playPromiseRef, reactPlayerRef, mediaContainerRef, onStoreUpdate, alarms, lastActivityRef, markActivity, lastPipActivityRef, markPipActivity, mediaType, isAudio, isPipEnabled, }), ); return ( {children} ); }; /** * A hook to consume MediaStore. * Must be used only for components that are Consumers of MediaProvider * @category hooks * @category MediaStore */ export const useMediaStore = ( selector?: StateSelector, equalityFn = Object.is, ): StateSlice => { const context = useContext(MediaStoreContext); if (!context) { throw Error('useMediaStore cannot be used outside of the MediaProvider'); } return useStoreWithEqualityFn( context, selector as StateSelector, equalityFn, ); };