import Skylink from '../index';
import logger from '../logger';
import MESSAGES from '../messages';
import mediaStreamHelpers from '../media-stream/helpers/index';
import SkylinkSignalingServer from '../server-communication/signaling-server/index';
import { BROWSER_AGENT } from '../constants';
/**
* @namespace UtilHelpers
* @description Util helper functions
* @private
*/
/**
* Function that tests if an object is empty.
* @param {Object} obj
* @return {boolean}
* @memberOf UtilHelpers
*/
export const isEmptyObj = (obj) => {
const keys = Object.keys(obj);
return keys.length === 0;
};
/**
* Function that tests if an array is empty.
* @param {Array} array
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isEmptyArray = array => array.length === 0;
/**
* Function that tests if a string is an empty string.
* @param string
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isEmptyString = string => string === '';
/**
* Function that tests if type is 'Object'.
* @param {*} param
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isAObj = param => typeof param === 'object' && param !== null;
/**
* Function that tests if type is 'Null'.
* @param {*} param
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isNull = param => typeof param === 'object' && param == null;
/**
* Function that tests if type is 'Number'.
* @param {*} param
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isANumber = param => typeof param === 'number';
/**
* Function that tests if type is 'Function'.
* @param {*} param
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isAFunction = param => typeof param === 'function';
/**
* Function that tests if type is 'Boolean'.
* @param {Object|boolean}
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isABoolean = obj => typeof obj !== 'undefined' && typeof obj === 'boolean';
/**
* Function that tests if type is 'String'.
* @param {*} param
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isAString = param => typeof param === 'string';
/**
* Function that tests if a param is null, undefined or a string.
* @param param
* @param paramName
* @param methodName
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const getParamValidity = (param, paramName, methodName) => {
let proceed = true;
if (param === null || typeof param === 'undefined' || !isAString(param)) {
logger.log.ERROR(`${methodName}: ${paramName} is null, undefined or not a string.`);
proceed = false;
}
return proceed;
};
/**
* Function that returns the Skylink state.
* @param {SkylinkRoom.id} rid
* @returns {SkylinkState|null} state
* @memberOf UtilHelpers
*/
export const getStateByRid = (rid) => {
const proceed = getParamValidity(rid, 'roomId', 'getStateByRid');
if (proceed) {
const states = Skylink.getSkylinkState();
const roomKeys = Object.keys(states);
let roomState = null;
for (let i = 0; i < roomKeys.length; i += 1) {
const key = roomKeys[i];
if (key === rid) {
roomState = states[key];
break;
}
}
return roomState;
}
logger.log.ERROR(`getRoomStateByRid: ${MESSAGES.ROOM_STATE.NOT_FOUND} - ${rid}`);
return null;
};
/**
* Function that returns the Skylink state.
* @param {String} roomkey - The room key.
* @returns {SkylinkState}
* @memberOf UtilHelpers
*/
export const getStateByKey = roomkey => getStateByRid(roomkey);
/**
* Function that returns the room state.
* @param {String} roomName - The room name.
* @returns {SkylinkState|null} - The room state.
* @memberOf UtilHelpers
*/
export const getRoomStateByName = (roomName) => {
const proceed = getParamValidity(roomName, 'roomName', 'getRoomStateByName');
let matchedRoomState = null;
if (proceed) {
const state = Skylink.getSkylinkState();
const roomKeys = Object.keys(state);
for (let i = 0; i < roomKeys.length; i += 1) {
const roomState = state[roomKeys[i]];
if (roomState.room.roomName.toLowerCase() === roomName.toLowerCase()) {
matchedRoomState = roomState;
break;
}
}
}
if (!matchedRoomState) {
logger.log.ERROR(`getRoomStateByName: ${MESSAGES.ROOM_STATE.NOT_FOUND} - ${roomName}`);
}
return matchedRoomState;
};
/**
* Function that checks the agent version compatibility.
* @param {String} agentVer
* @param {String} requiredVer
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isLowerThanVersion = (agentVer, requiredVer) => {
const partsA = (agentVer || '').split('.');
const partsB = (requiredVer || '').split('.');
for (let i = 0; i < partsB.length; i += 1) {
if ((partsA[i] || '0') < (partsB[i] || '0')) {
return true;
}
}
return false;
};
/**
* Disconnects from the signaling server.
* @memberOf UtilHelpers
*/
export const disconnect = () => {
try {
new SkylinkSignalingServer().socket.disconnect();
} catch (error) {
logger.log.ERROR(error);
}
};
/**
* Function that generates an <a href="https://en.wikipedia.org/wiki/Universally_unique_identifier">UUID</a> (Unique ID).
* @returns {String} Returns a generated UUID (Unique ID).
* @memberOf UtilHelpers
*/
export const generateUUID = () => {
/* eslint-disable no-bitwise */
let d = new Date().getTime();
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (d + Math.random() * 16) % 16 | 0;
d = Math.floor(d / 16);
return (c === 'x' ? r : (r && 0x7 | 0x8)).toString(16);
});
return uuid;
};
/**
* Function that returns the getUserMedia stream when the user had not joined a room (is stateless)
* @param {Object} options
* @returns {Promise}
* @memberOf UtilHelpers
*/
export const statelessGetUserMedia = options => new Promise((resolve, reject) => {
const { navigator } = window;
if (!options || !isAObj(options)) {
reject(new Error(`${MESSAGES.MEDIA_STREAM.ERRORS.INVALID_GUM_OPTIONS} ${options}`));
}
navigator.mediaDevices.getUserMedia(options).then((stream) => {
const streams = mediaStreamHelpers.splitAudioAndVideoStream(stream);
resolve(streams);
}).catch((error) => {
reject(error);
});
});
/**
* Function that always returns are rejected Promise.
* @param {String} errorMsg
* @returns {Promise}
* @memberOf UtilHelpers
*/
export const rejectPromise = errorMsg => new Promise((resolve, reject) => {
reject(new Error(errorMsg));
});
/**
* Function that updates the replaced state of the streams
* @param {MediaStream} replacedStream
* @param {MediaStream} newStream
* @param {SkylinkState} state
* @param {boolean} isReplaced
* @memberOf UtilHelpers
*/
export const updateReplacedStreamInState = (replacedStream, newStream, state, isReplaced) => {
const { streams, room } = state;
const streamObjs = Object.values(streams.userMedia);
for (let i = 0; i < streamObjs.length; i += 1) {
if (streamObjs[i].id === replacedStream.id) {
streamObjs[i].isReplaced = isReplaced;
streamObjs[i].newStream = newStream;
}
}
Skylink.setSkylinkState(state, room.id);
};
/**
* Function that checks if the peerId exists on the peerConnection
* @param {SkylinkRoom} room
* @param {String} peerId
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isValidPeerId = (room, peerId) => {
const state = Skylink.getSkylinkState(room.id);
const { peerConnections } = state;
const peerIds = Object.keys(peerConnections);
let isValid = false;
peerIds.forEach((validPeerId) => {
if (validPeerId === peerId) {
isValid = true;
}
});
return isValid;
};
/**
* Function that checks if a media stream has an audio track.
* @param {MediaStream} stream
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const hasAudioTrack = stream => stream.getAudioTracks().length > 0;
/**
* Function that checks if a media stream has a video track.
* @param {MediaStream} stream
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const hasVideoTrack = stream => stream.getVideoTracks().length > 0;
/**
* Function that checks the browser agent.
* @param {String} agent
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isAgent = (agent) => {
const { AdapterJS } = window;
switch (agent) {
case BROWSER_AGENT.CHROME:
return AdapterJS.webrtcDetectedBrowser === BROWSER_AGENT.CHROME;
case BROWSER_AGENT.SAFARI:
return AdapterJS.webrtcDetectedBrowser === BROWSER_AGENT.SAFARI;
case BROWSER_AGENT.FIREFOX:
return AdapterJS.webrtcDetectedBrowser === BROWSER_AGENT.FIREFOX;
default:
logger.log.DEBUG(MESSAGES.UTILS.INVALID_BROWSER_AGENT);
return false;
}
};
/**
* Function that checks the browser version.
* @param {number} version
* @returns {boolean}
* @memberOf UtilHelpers
*/
export const isVersion = (version) => {
const { AdapterJS } = window;
return AdapterJS.webrtcDetectedVersion === version;
};
/**
* Function that generates a timestamp in UNIX format.
* @returns {number}
* @memberOf UtilHelpers
*/
export const generateUNIXTimeStamp = () => Math.round(new Date().getTime() / 1000);
/**
* Function that parses UNIX timestamp and returns timestamp in ISO string.
* @param timestamp
* @returns {string}
* @memberOf UtilHelpers
*/
export const parseUNIXTimeStamp = timestamp => new Date(timestamp).toISOString();
/**
* Function that generates a timestamp in ISO string format.
* @returns {string}
* @memberOf UtilHelpers
*/
export const generateISOStringTimesStamp = () => new Date().toISOString();