import { AnyAction , Dispatch , MiddlewareAPI } from 'redux' ; import { CommsNode , CommsStyle , CommsNodeOptions , SendToOptions } from '../util/commsNode' ; import { PeerNode } from '../util/peerNode' ; import { McastNode } from '../util/mcastNode' ; import { setMyPeerIdAction } from './myPeerIdReducer' ; import { removeAllConnectedUsersAction } from './connectedUserReducer' ; interface PeerToPeerMiddlewareOptions < T > { getCommsChannel : ( state : T ) => { commsChannelId : string | null ; commsStyle : CommsStyle ; userId ? : string ; } ; commsNodeOptions : CommsNodeOptions ; getSendToOptions : ( commsNode : CommsNode , action : AnyAction ) => undefined | Partial < SendToOptions > ; shouldDispatchLocally ? : ( action : AnyAction , state : T ) => boolean ; } const peerToPeerMiddleware = < Store > ( { getCommsChannel , commsNodeOptions = { } , getSendToOptions } ) => { let currentCommsStyle ; let commsNode ; window . addEventListener ( 'beforeunload' , ( ) => { commsNode && commsNode . destroy ( ) ; } ) ; return ( api ) => ( next ) => ( action ) => { let result ; if ( ! commsNodeOptions . shouldDispatchLocally || commsNodeOptions . shouldDispatchLocally ( action , api . getState ( ) , commsNode ) ) { result = next ( action ) ; } const newState = api . getState ( ) ; const { commsChannelId , commsStyle , userId } = getCommsChannel ( newState ) ; if ( ! commsNode && commsChannelId && userId ) { currentCommsStyle = commsStyle ; switch ( commsStyle ) { case CommsStyle . PeerToPeer : commsNode = new PeerNode ( commsChannelId , userId , commsNodeOptions ) ; break ; case CommsStyle . MultiCast : commsNode = new McastNode ( commsChannelId , userId , commsNodeOptions ) ; break ; default : return result ; } commsNode . init ( ) ; next ( setMyPeerIdAction ( commsNode . peerId ) ) ; } if ( commsNode && ! action . fromPeerId && typeof ( action ) === 'object' ) { const sendToOptions = getSendToOptions ( commsNode , action ) ; if ( sendToOptions ) { commsNode . sendTo ( action , sendToOptions ) ; } } if ( commsNode && ( ! commsChannelId || commsStyle !== currentCommsStyle ) ) { commsNode . destroy ( ) ; commsNode = null ; next ( removeAllConnectedUsersAction ( ) ) ; next ( setMyPeerIdAction ( null ) ) ; } return result ; } ; } ; export default peerToPeerMiddleware ;