UNPKG

@fctv/js

Version:

Call SDK for JavaScript

262 lines (229 loc) 6.62 kB
import { UserSession, UserSessionEvent, CallState } from '@fctv/js'; import { ConnectionStatus, UserStatus } from './constants'; import { LOGIN, LOGOUT, UPDATE_CONNECTION_STATUS, UPDATE_USER_STATUS, NEW_CALL, TIME_ELAPSED, REMOTE_STREAM, LOCAL_STREAM, UPDATE_CALL_STATE } from './actions/actionTypes' import store from '../store'; let _fcTVServiceInstance = null; const _savedLoggedInUserKey = '_savedLoggedInUserKey'; export default class FCTVService { _timer = null; static getInstance = () => { if (!_fcTVServiceInstance) { _fcTVServiceInstance = new FCTVService(); } return _fcTVServiceInstance; }; get isLoggedIn() { return this.client && this.client.isLoggedIn; } constructor() { this.activeCall = null; this._setActiveCall = this._setActiveCall.bind(this); this._startTimer = this._startTimer.bind(this); this._stopTimer = this._stopTimer.bind(this); // Get logged user from local storage const savedLoggedInUser = localStorage.getItem(_savedLoggedInUserKey); if (savedLoggedInUser) { this.user = JSON.parse(savedLoggedInUser); } } login(options) { this.logout(true); // Close the old if existing, but keep the session this.client = new UserSession(options); this.user = options; this._subscribeEvents(); this.client.connect(); store.dispatch({ type: UPDATE_CONNECTION_STATUS, payload: { connectionStatus: ConnectionStatus.CONNECTING } }) } logout(keepSession = false) { this.client && this.client.close(keepSession); // Remove saved user from localStorage localStorage.removeItem(_savedLoggedInUserKey); this.user = null; this._stopTimer(); } _subscribeEvents() { this.client.on(UserSessionEvent.ON_READY, () => { console.log('[FCTVService] Ready'); store.dispatch({ type: UPDATE_CONNECTION_STATUS, payload: { connectionStatus: ConnectionStatus.READY } }) }); this.client.on(UserSessionEvent.ON_CLOSED, () => { console.log('[FCTVService] Closed'); store.dispatch({ type: LOGOUT }); }); this.client.on(UserSessionEvent.ON_ERROR, (err, data) => { console.log('[FCTVService] Error', err); store.dispatch({ type: UPDATE_CONNECTION_STATUS, payload: { connectionStatus: ConnectionStatus.ERROR } }) }); this.client.on(UserSessionEvent.ON_RETRYING, (err, data) => { console.log('[FCTVService] Retrying'); store.dispatch({ type: UPDATE_CONNECTION_STATUS, payload: { connectionStatus: ConnectionStatus.RETRYING } }) }); this.client.on(UserSessionEvent.ON_LOGIN_ERROR, (err, data) => { console.log('[FCTVService] Login Error'); store.dispatch({ type: UPDATE_USER_STATUS, payload: { userStatus: UserStatus.LOGIN_FAILED } }) }); this.client.on(UserSessionEvent.ON_LOGIN_SUCCESS, (err, data) => { console.log('[FCTVService] Login Success', data); // Save to localStorage localStorage.setItem(_savedLoggedInUserKey, JSON.stringify(this.user)); store.dispatch({ type: LOGIN, payload: { user: this.user } }) }); this.client.on(UserSessionEvent.ON_SPEED_CHANGE, (err, data) => { console.log('[FCTVService] Speed change', data); }); this.client.on(UserSessionEvent.ON_USER_MEDIA_ERROR, (err) => { console.error('[FCTVService] User Media', err); }); this.client.on(UserSessionEvent.ON_USER_PEER_ERROR, (err) => { console.error('[FCTVService] User Peer', err); }); this.client.on(UserSessionEvent.ON_INCOMING_CALL, (err, call) => { console.log('[FCTVService] Incoming call', call); let t = setTimeout(() => { this.answerCall(call); clearTimeout(t); }, 5000); }); this.client.on(UserSessionEvent.ON_RECOVERY_CALL, (err, call) => { console.debug('[FCTVService] Call need recovery', call); let t = setTimeout(() => { this.answerCall(call); clearTimeout(t); }, 5000); }); this.client.on(UserSessionEvent.ON_CALL_LOCAL_STREAM, (err, call) => { console.debug('[FCTVService] Call local stream', call); store.dispatch({ type: LOCAL_STREAM, payload: { localStream: call.localStream } }) }); this.client.on(UserSessionEvent.ON_CALL_REMOTE_STREAM, (err, call) => { console.debug('[FCTVService] Call remote stream', call); store.dispatch({ type: REMOTE_STREAM, payload: { remoteStream: call.remoteStream } }) }); this.client.on(UserSessionEvent.ON_CALL_STATE_UPDATE, (err, call) => { console.debug('[App] Call state', call.state); if (this.activeCall && this.activeCall.id === call.id) { store.dispatch({ type: UPDATE_CALL_STATE, payload: { callState: call.state } }) } switch (call.state) { case CallState.TRYING: this._setActiveCall(call); break; case CallState.RINGING: break; case CallState.ACTIVE: this._setActiveCall(call); this._startTimer(); break; case CallState.DESTROYED: if (this.activeCall && this.activeCall.id === call.id) { this._setActiveCall(null); this._stopTimer(); } break; default: break; } }); } _setActiveCall(call) { this.activeCall = call; store.dispatch({ type: NEW_CALL, payload: { call: call } }) } makeCall(destinationNumber) { const data = { destinationNumber }; this.hangupCall(); this.activeCall = this.client.newCall(data); } hangupCall() { if (this.activeCall) { this.activeCall.hangup() } } answerCall(call) { // Hangup the old call if (this.activeCall && call.id !== this.activeCall.id) { this.hangupCall(); } call.answer(); } _startTimer() { this._timer = setInterval(()=> { if (this.activeCall) { const elapsedSeconds = Math.round((Date.now() - this.activeCall.activeTime)/1000); store.dispatch({ type: TIME_ELAPSED, payload: { timeElapsed: elapsedSeconds } }) } }, 1000); } _stopTimer() { this._timer && clearInterval(this._timer); } }