import debug from "debug" ; import { reaction , observe } from "mobx" ; import { MeshRoom , SfuRoom , RoomStream } from "skyway-js" ; import { RoomData , RoomStat , RoomChat , RoomReaction , RoomCast , } from "../utils/types" ; import RootStore from "../stores" ; const log = debug ( "effect:room" ) ; export const joinRoom = ( store ) => { log ( "joinRoom()" ) ; const { room , ui , media , client , notification } = store ; if ( room . name === null || room . mode === null ) { throw ui . showError ( new Error ( "Room name or mode is undefined!" ) ) ; } if ( room . peer === null ) { throw ui . showError ( new Error ( "Peer is not created!" ) ) ; } const roomOptions = { mode : room . mode , stream : media . stream , videoReceiveEnabled : true , } ; if ( room . useH264 ) { Object . assign ( roomOptions , { videoCodec : "H264" } ) ; } if ( room . mode === "mesh" ) { room . room = room . peer . joinRoom < MeshRoom > ( room . name , roomOptions ) ; } else if ( room . mode === "sfu" ) { room . room = room . peer . joinRoom < SfuRoom > ( room . name , roomOptions ) ; } const confRoom = room . room ; if ( confRoom === null ) { throw ui . showError ( new Error ( "Room is null!" ) ) ; } log ( "joined room" , confRoom ) ; log ( "w/ options:" , roomOptions ) ; ui . isReEntering = false ; const disposers = [ reaction ( ( ) => ( { ... media . stat , ... client . stat } ) , ( stat ) => { log ( "reaction:send(stat)" ) ; confRoom . send ( { type : "stat" , payload : stat } ) ; } ) , reaction ( ( ) => room . myLastChat , ( chat ) => { if ( chat === null ) { return ; } log ( "reaction:send(chat)" ) ; confRoom . send ( { type : "chat" , payload : chat } ) ; } ) , reaction ( ( ) => room . myLastReaction , ( reaction ) => { if ( reaction === null ) { return ; } log ( "reaction:send(reaction)" ) ; confRoom . send ( { type : "reaction" , payload : reaction } ) ; } ) , reaction ( ( ) => room . castRequestCount , ( ) => { log ( "reaction:send(cast)" ) ; confRoom . send ( { type : "cast" , payload : { from : client . displayName } } ) ; } ) , observe ( media , "videoDeviceId" , ( change ) => { log ( "observe(media.videoDeviceId)" ) ; if ( ! room . isJoined ) { log ( "do nothing before room join" ) ; return ; } if ( change . oldValue !== null && change . newValue !== null ) { log ( "just change video by replaceStream(), no need to re-enter" ) ; confRoom . replaceStream ( media . stream ) ; return ; } log ( "need to re-enter the room to add/remove video" ) ; if ( room . room === null ) { throw ui . showError ( new Error ( "Room is null!" ) ) ; } ui . isReEntering = true ; room . room . close ( ) ; notification . showInfo ( "Re-enter the room to add/remove video" ) ; } ) , ] ; confRoom . on ( "stream" , ( stream ) => { log ( "on('stream')" , stream ) ; room . streams . set ( stream . peerId , stream ) ; confRoom . send ( { type : "stat" , payload : { ... client . stat , ... media . stat } , } ) ; } ) ; confRoom . on ( "peerLeave" , ( peerId ) => { log ( "on('peerLeave')" , peerId ) ; const stat = room . stats . get ( peerId ) ; if ( stat ) { notification . showLeave ( stat . displayName ) ; } room . removeStream ( peerId ) ; } ) ; confRoom . on ( "data" , ( { src , data } ) => { const { type , payload } = data ; switch ( type ) { case "stat" : { const stat = payload as RoomStat ; log ( "on('data/stat')" , stat ) ; if ( ! room . stats . get ( src ) ) { notification . showJoin ( stat . displayName ) ; } room . stats . set ( src , stat ) ; break ; } case "chat" : { const chat = payload as RoomChat ; log ( "on('data/chat')" , chat ) ; ui . isChatOpen || notification . showChat ( chat . from , chat . text ) ; room . addRemoteChat ( chat ) ; break ; } case "reaction" : { const reaction = payload as RoomReaction ; notification . showReaction ( reaction . from , reaction . reaction ) ; break ; } case "cast" : { const cast = payload as RoomCast ; log ( "on('data/cast')" , cast ) ; room . pinnedId = src ; notification . showInfo ( `Video was casted by ${ cast . from }` ) ; break ; } default : { log ( `on('data/unknown') discard...` ) ; } } } ) ; confRoom . once ( "close" , ( ) => { log ( "on('close')" ) ; notification . showInfo ( "room closed! trying re-connect.." ) ; disposers . forEach ( ( d ) => d ( ) ) ; try { confRoom . removeAllListeners ( ) ; room . cleanUp ( ) ; } catch ( err ) { throw ui . showError ( err ) ; } setTimeout ( ( ) => joinRoom ( store ) , 500 ) ; } ) ; } ;