import React, { createContext, useContext, useEffect, useCallback, type PropsWithChildren, } from 'react' import { type SessionRecorderOptions, SessionState } from '../types' import sessionRecorder from '../session-recorder' import { ScreenRecorderView } from '../components/ScreenRecorderView' import SessionRecorderWidget from '../components/SessionRecorderWidget' import { SessionType } from '@multiplayer-app/session-recorder-common' import { sessionRecorderStore, type SessionRecorderState, } from './SessionRecorderStore' import { useStoreSelector } from './useStoreSelector' interface SessionRecorderContextType { instance: typeof sessionRecorder openWidgetModal: () => void closeWidgetModal: () => void startSession: (sessionType?: SessionType) => Promise stopSession: (comment?: string) => Promise pauseSession: () => Promise resumeSession: () => Promise cancelSession: () => Promise saveSession: () => Promise } const SessionRecorderContext = createContext( null, ) export interface SessionRecorderProviderProps extends PropsWithChildren { options?: SessionRecorderOptions } export const SessionRecorderProvider: React.FC< SessionRecorderProviderProps > = ({ children, options }) => { const isInitialized = useStoreSelector( sessionRecorderStore, (s) => s.isInitialized, ) useEffect(() => { if (options) { sessionRecorder.init(options) } sessionRecorderStore.setState({ isInitialized: sessionRecorder.isInitialized, }) }, []) useEffect(() => { sessionRecorderStore.setState({ sessionState: sessionRecorder.sessionState, sessionType: sessionRecorder.sessionType, }) const onStateChange = ( sessionState: SessionState, sessionType: SessionType, ) => { sessionRecorderStore.setState({ sessionState, sessionType }) } const onInit = () => { sessionRecorderStore.setState({ isInitialized: true }) } sessionRecorder.on('state-change', onStateChange) sessionRecorder.on('init', onInit) return () => { sessionRecorder.off('state-change', onStateChange) sessionRecorder.off('init', onInit) } }, []) const startSession = useCallback( (sessionType: SessionType = SessionType.MANUAL) => { return sessionRecorder.start(sessionType) }, [], ) const stopSession = useCallback((comment?: string) => { return sessionRecorder.stop(comment) }, []) const pauseSession = useCallback(() => { return sessionRecorder.pause() }, []) const resumeSession = useCallback(() => { return sessionRecorder.resume() }, []) const cancelSession = useCallback(() => { return sessionRecorder.cancel() }, []) const saveSession = useCallback(() => { return sessionRecorder.save() }, []) const openWidgetModal = useCallback(() => { sessionRecorderStore.setState({ isWidgetModalVisible: true }) }, []) const closeWidgetModal = useCallback(() => { sessionRecorderStore.setState({ isWidgetModalVisible: false }) }, []) return ( {children} {isInitialized && !!sessionRecorder.config.widget.enabled && ( )} ) } export const useSessionRecorder = (): SessionRecorderContextType => { const context = useContext(SessionRecorderContext) if (!context) { throw new Error( 'useSessionRecorder must be used within a SessionRecorderProvider', ) } return context }