ref(TS) Convert base/tracks to TS (#12219)
This commit is contained in:
parent
fb2cfaa204
commit
3426960d5a
|
@ -1,6 +1,13 @@
|
|||
import { IStore } from "./react/features/app/types";
|
||||
|
||||
export {};
|
||||
|
||||
declare global {
|
||||
const APP: any;
|
||||
const APP: {
|
||||
store: IStore;
|
||||
UI: any;
|
||||
API: any;
|
||||
conference: any;
|
||||
};
|
||||
const interfaceConfig: any;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ export interface IJitsiConference {
|
|||
muteParticipant: Function;
|
||||
on: Function;
|
||||
removeTrack: Function;
|
||||
replaceTrack: Function;
|
||||
sendCommand: Function;
|
||||
sendEndpointMessage: Function;
|
||||
sessionId: string;
|
||||
|
|
|
@ -54,7 +54,9 @@ export const VIDEO_MUTISM_AUTHORITY = {
|
|||
*
|
||||
* @enum {string}
|
||||
*/
|
||||
export const VIDEO_TYPE = {
|
||||
export const VIDEO_TYPE: { [key: string]: VideoType; } = {
|
||||
CAMERA: 'camera',
|
||||
DESKTOP: 'desktop'
|
||||
};
|
||||
|
||||
export type VideoType = 'camera' | 'desktop';
|
||||
|
|
|
@ -1,25 +1,26 @@
|
|||
/* global APP */
|
||||
|
||||
import {
|
||||
createTrackMutedEvent,
|
||||
sendAnalytics
|
||||
} from '../../analytics';
|
||||
import { NOTIFICATION_TIMEOUT_TYPE, showErrorNotification, showNotification } from '../../notifications';
|
||||
import { getCurrentConference } from '../conference';
|
||||
import { getMultipleVideoSendingSupportFeatureFlag } from '../config';
|
||||
import { createTrackMutedEvent } from '../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../analytics/functions';
|
||||
import { IStore } from '../../app/types';
|
||||
import { showErrorNotification, showNotification } from '../../notifications/actions';
|
||||
import { NOTIFICATION_TIMEOUT, NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
|
||||
import { getCurrentConference } from '../conference/functions';
|
||||
import { IJitsiConference } from '../conference/reducer';
|
||||
import { getMultipleVideoSendingSupportFeatureFlag } from '../config/functions.any';
|
||||
import { JitsiTrackErrors, JitsiTrackEvents } from '../lib-jitsi-meet';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import { createLocalTrack } from '../lib-jitsi-meet/functions';
|
||||
import { setAudioMuted, setScreenshareMuted, setVideoMuted } from '../media/actions';
|
||||
import {
|
||||
CAMERA_FACING_MODE,
|
||||
MediaType,
|
||||
MEDIA_TYPE,
|
||||
setAudioMuted,
|
||||
setScreenshareMuted,
|
||||
setVideoMuted,
|
||||
VideoType,
|
||||
VIDEO_MUTISM_AUTHORITY,
|
||||
VIDEO_TYPE
|
||||
} from '../media';
|
||||
import { getLocalParticipant } from '../participants';
|
||||
import { updateSettings } from '../settings';
|
||||
} from '../media/constants';
|
||||
import { getLocalParticipant } from '../participants/functions';
|
||||
import { updateSettings } from '../settings/actions';
|
||||
|
||||
import {
|
||||
SET_NO_SRC_DATA_NOTIFICATION_UID,
|
||||
|
@ -43,6 +44,7 @@ import {
|
|||
getTrackByJitsiTrack
|
||||
} from './functions';
|
||||
import logger from './logger';
|
||||
import { TrackOptions } from './types';
|
||||
|
||||
/**
|
||||
* Add a given local track to the conference.
|
||||
|
@ -50,8 +52,8 @@ import logger from './logger';
|
|||
* @param {JitsiLocalTrack} newTrack - The local track to be added to the conference.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function addLocalTrack(newTrack) {
|
||||
return async (dispatch, getState) => {
|
||||
export function addLocalTrack(newTrack: any) {
|
||||
return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const conference = getCurrentConference(getState());
|
||||
|
||||
if (conference) {
|
||||
|
@ -82,8 +84,8 @@ export function addLocalTrack(newTrack) {
|
|||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function createDesiredLocalTracks(...desiredTypes) {
|
||||
return (dispatch, getState) => {
|
||||
export function createDesiredLocalTracks(...desiredTypes: any) {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const state = getState();
|
||||
|
||||
dispatch(destroyLocalDesktopTrackIfExists());
|
||||
|
@ -118,7 +120,7 @@ export function createDesiredLocalTracks(...desiredTypes) {
|
|||
|
||||
// We need to create the desired tracks which are not already available.
|
||||
const createTypes
|
||||
= desiredTypes.filter(type => availableTypes.indexOf(type) === -1);
|
||||
= desiredTypes.filter((type: MediaType) => availableTypes.indexOf(type) === -1);
|
||||
|
||||
createTypes.length
|
||||
&& dispatch(createLocalTracksA({ devices: createTypes }));
|
||||
|
@ -132,8 +134,8 @@ export function createDesiredLocalTracks(...desiredTypes) {
|
|||
* @param {Object} [options] - For info @see JitsiMeetJS.createLocalTracks.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function createLocalTracksA(options = {}) {
|
||||
return (dispatch, getState) => {
|
||||
export function createLocalTracksA(options: TrackOptions = {}) {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const devices
|
||||
= options.devices || [ MEDIA_TYPE.AUDIO, MEDIA_TYPE.VIDEO ];
|
||||
const store = {
|
||||
|
@ -154,7 +156,7 @@ export function createLocalTracksA(options = {}) {
|
|||
for (const device of devices) {
|
||||
if (getLocalTrack(
|
||||
getState()['features/base/tracks'],
|
||||
device,
|
||||
device as MediaType,
|
||||
/* includePending */ true)) {
|
||||
throw new Error(`Local track for ${device} already exists`);
|
||||
}
|
||||
|
@ -170,7 +172,7 @@ export function createLocalTracksA(options = {}) {
|
|||
},
|
||||
store)
|
||||
.then(
|
||||
localTracks => {
|
||||
(localTracks: any[]) => {
|
||||
// Because GUM is called for 1 device (which is actually
|
||||
// a media type 'audio', 'video', 'screen', etc.) we
|
||||
// should not get more than one JitsiTrack.
|
||||
|
@ -184,15 +186,15 @@ export function createLocalTracksA(options = {}) {
|
|||
if (gumProcess.canceled) {
|
||||
return _disposeTracks(localTracks)
|
||||
.then(() =>
|
||||
dispatch(_trackCreateCanceled(device)));
|
||||
dispatch(_trackCreateCanceled(device as MediaType)));
|
||||
}
|
||||
|
||||
return dispatch(trackAdded(localTracks[0]));
|
||||
},
|
||||
reason =>
|
||||
(reason: Error) =>
|
||||
dispatch(
|
||||
gumProcess.canceled
|
||||
? _trackCreateCanceled(device)
|
||||
? _trackCreateCanceled(device as MediaType)
|
||||
: _onCreateLocalTracksRejected(
|
||||
reason,
|
||||
device)));
|
||||
|
@ -230,12 +232,12 @@ export function createLocalTracksA(options = {}) {
|
|||
*/
|
||||
export function destroyLocalTracks(track = null) {
|
||||
if (track) {
|
||||
return dispatch => {
|
||||
return (dispatch: IStore['dispatch']) => {
|
||||
dispatch(_disposeAndRemoveTracks([ track ]));
|
||||
};
|
||||
}
|
||||
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
// First wait until any getUserMedia in progress is settled and then get
|
||||
// rid of all local tracks.
|
||||
_cancelGUMProcesses(getState)
|
||||
|
@ -257,7 +259,7 @@ export function destroyLocalTracks(track = null) {
|
|||
* track: Track
|
||||
* }}
|
||||
*/
|
||||
export function noDataFromSource(track) {
|
||||
export function noDataFromSource(track: any) {
|
||||
return {
|
||||
type: TRACK_NO_DATA_FROM_SOURCE,
|
||||
track
|
||||
|
@ -270,8 +272,8 @@ export function noDataFromSource(track) {
|
|||
* @param {JitsiLocalTrack} jitsiTrack - The track.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function showNoDataFromSourceVideoError(jitsiTrack) {
|
||||
return async (dispatch, getState) => {
|
||||
export function showNoDataFromSourceVideoError(jitsiTrack: any) {
|
||||
return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
let notificationInfo;
|
||||
|
||||
const track = getTrackByJitsiTrack(getState()['features/base/tracks'], jitsiTrack);
|
||||
|
@ -289,7 +291,7 @@ export function showNoDataFromSourceVideoError(jitsiTrack) {
|
|||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
|
||||
notificationInfo = {
|
||||
uid: notificationAction.uid
|
||||
uid: notificationAction?.uid
|
||||
};
|
||||
}
|
||||
dispatch(trackNoDataFromSourceNotificationInfoChanged(jitsiTrack, notificationInfo));
|
||||
|
@ -311,7 +313,8 @@ export function showNoDataFromSourceVideoError(jitsiTrack) {
|
|||
* shareOptions: Object
|
||||
* }}
|
||||
*/
|
||||
export function toggleScreensharing(enabled, audioOnly = false, ignoreDidHaveVideo = false, shareOptions = {}) {
|
||||
export function toggleScreensharing(enabled: boolean, audioOnly = false,
|
||||
ignoreDidHaveVideo = false, shareOptions = {}) {
|
||||
return {
|
||||
type: TOGGLE_SCREENSHARING,
|
||||
enabled,
|
||||
|
@ -333,8 +336,8 @@ export function toggleScreensharing(enabled, audioOnly = false, ignoreDidHaveVid
|
|||
* will be used.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function replaceLocalTrack(oldTrack, newTrack, conference) {
|
||||
return async (dispatch, getState) => {
|
||||
export function replaceLocalTrack(oldTrack: any, newTrack: any, conference?: IJitsiConference) {
|
||||
return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
conference
|
||||
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
|
@ -355,8 +358,8 @@ export function replaceLocalTrack(oldTrack, newTrack, conference) {
|
|||
* @param {JitsiLocalTrack|null} newTrack - The track to use instead.
|
||||
* @returns {Function}
|
||||
*/
|
||||
function replaceStoredTracks(oldTrack, newTrack) {
|
||||
return async (dispatch, getState) => {
|
||||
function replaceStoredTracks(oldTrack: any, newTrack: any) {
|
||||
return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
// We call dispose after doing the replace because dispose will
|
||||
// try and do a new o/a after the track removes itself. Doing it
|
||||
// after means the JitsiLocalTrack.conference is already
|
||||
|
@ -395,14 +398,14 @@ function replaceStoredTracks(oldTrack, newTrack) {
|
|||
* @param {(JitsiLocalTrack|JitsiRemoteTrack)} track - JitsiTrack instance.
|
||||
* @returns {{ type: TRACK_ADDED, track: Track }}
|
||||
*/
|
||||
export function trackAdded(track) {
|
||||
return async (dispatch, getState) => {
|
||||
export function trackAdded(track: any) {
|
||||
return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
track.on(
|
||||
JitsiTrackEvents.TRACK_MUTE_CHANGED,
|
||||
() => dispatch(trackMutedChanged(track)));
|
||||
track.on(
|
||||
JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED,
|
||||
type => dispatch(trackVideoTypeChanged(track, type)));
|
||||
(type: VideoType) => dispatch(trackVideoTypeChanged(track, type)));
|
||||
|
||||
// participantId
|
||||
const local = track.isLocal();
|
||||
|
@ -434,13 +437,13 @@ export function trackAdded(track) {
|
|||
// Set the notification ID so that other parts of the application know that this was
|
||||
// displayed in the context of the current device.
|
||||
// I.E. The no-audio-signal notification shouldn't be displayed if this was already shown.
|
||||
dispatch(setNoSrcDataNotificationUid(notificationAction.uid));
|
||||
dispatch(setNoSrcDataNotificationUid(notificationAction?.uid));
|
||||
|
||||
noDataFromSourceNotificationInfo = { uid: notificationAction.uid };
|
||||
noDataFromSourceNotificationInfo = { uid: notificationAction?.uid };
|
||||
} else {
|
||||
const timeout = setTimeout(() => dispatch(
|
||||
showNoDataFromSourceVideoError(track)),
|
||||
NOTIFICATION_TIMEOUT_TYPE.MEDIUM);
|
||||
NOTIFICATION_TIMEOUT.MEDIUM);
|
||||
|
||||
noDataFromSourceNotificationInfo = { timeout };
|
||||
}
|
||||
|
@ -486,7 +489,7 @@ export function trackAdded(track) {
|
|||
* track: Track
|
||||
* }}
|
||||
*/
|
||||
export function trackMutedChanged(track) {
|
||||
export function trackMutedChanged(track: any) {
|
||||
return {
|
||||
type: TRACK_UPDATED,
|
||||
track: {
|
||||
|
@ -507,7 +510,7 @@ export function trackMutedChanged(track) {
|
|||
* track: Track
|
||||
* }}
|
||||
*/
|
||||
export function trackMuteUnmuteFailed(track, wasMuting) {
|
||||
export function trackMuteUnmuteFailed(track: any, wasMuting: boolean) {
|
||||
return {
|
||||
type: TRACK_MUTE_UNMUTE_FAILED,
|
||||
track,
|
||||
|
@ -525,7 +528,7 @@ export function trackMuteUnmuteFailed(track, wasMuting) {
|
|||
* track: Track
|
||||
* }}
|
||||
*/
|
||||
export function trackNoDataFromSourceNotificationInfoChanged(track, noDataFromSourceNotificationInfo) {
|
||||
export function trackNoDataFromSourceNotificationInfoChanged(track: any, noDataFromSourceNotificationInfo?: Object) {
|
||||
return {
|
||||
type: TRACK_UPDATED,
|
||||
track: {
|
||||
|
@ -545,7 +548,7 @@ export function trackNoDataFromSourceNotificationInfoChanged(track, noDataFromSo
|
|||
* track: Track
|
||||
* }}
|
||||
*/
|
||||
export function trackRemoved(track) {
|
||||
export function trackRemoved(track: any) {
|
||||
track.removeAllListeners(JitsiTrackEvents.TRACK_MUTE_CHANGED);
|
||||
track.removeAllListeners(JitsiTrackEvents.TRACK_VIDEOTYPE_CHANGED);
|
||||
track.removeAllListeners(JitsiTrackEvents.NO_DATA_FROM_SOURCE);
|
||||
|
@ -567,7 +570,7 @@ export function trackRemoved(track) {
|
|||
* track: Track
|
||||
* }}
|
||||
*/
|
||||
export function trackVideoStarted(track) {
|
||||
export function trackVideoStarted(track: any) {
|
||||
return {
|
||||
type: TRACK_UPDATED,
|
||||
track: {
|
||||
|
@ -587,7 +590,7 @@ export function trackVideoStarted(track) {
|
|||
* track: Track
|
||||
* }}
|
||||
*/
|
||||
export function trackVideoTypeChanged(track, videoType) {
|
||||
export function trackVideoTypeChanged(track: any, videoType: VideoType) {
|
||||
return {
|
||||
type: TRACK_UPDATED,
|
||||
track: {
|
||||
|
@ -607,7 +610,7 @@ export function trackVideoTypeChanged(track, videoType) {
|
|||
* track: Track
|
||||
* }}
|
||||
*/
|
||||
export function trackStreamingStatusChanged(track, streamingStatus) {
|
||||
export function trackStreamingStatusChanged(track: any, streamingStatus: string) {
|
||||
return {
|
||||
type: TRACK_UPDATED,
|
||||
track: {
|
||||
|
@ -624,8 +627,8 @@ export function trackStreamingStatusChanged(track, streamingStatus) {
|
|||
* @private
|
||||
* @returns {Function}
|
||||
*/
|
||||
function _addTracks(tracks) {
|
||||
return dispatch => Promise.all(tracks.map(t => dispatch(trackAdded(t))));
|
||||
function _addTracks(tracks: any[]) {
|
||||
return (dispatch: IStore['dispatch']) => Promise.all(tracks.map(t => dispatch(trackAdded(t))));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -640,16 +643,16 @@ function _addTracks(tracks) {
|
|||
* about here is to be sure that the {@code getUserMedia} callbacks have
|
||||
* completed (i.e. Returned from the native side).
|
||||
*/
|
||||
function _cancelGUMProcesses(getState) {
|
||||
function _cancelGUMProcesses(getState: IStore['getState']) {
|
||||
const logError
|
||||
= error =>
|
||||
= (error: Error) =>
|
||||
logger.error('gumProcess.cancel failed', JSON.stringify(error));
|
||||
|
||||
return Promise.all(
|
||||
getState()['features/base/tracks']
|
||||
.filter(t => t.local)
|
||||
.map(({ gumProcess }) =>
|
||||
gumProcess && gumProcess.cancel().catch(logError)));
|
||||
.map(({ gumProcess }: any) =>
|
||||
gumProcess?.cancel().catch(logError)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -659,8 +662,8 @@ function _cancelGUMProcesses(getState) {
|
|||
* @protected
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function _disposeAndRemoveTracks(tracks) {
|
||||
return dispatch =>
|
||||
export function _disposeAndRemoveTracks(tracks: any[]) {
|
||||
return (dispatch: IStore['dispatch']) =>
|
||||
_disposeTracks(tracks)
|
||||
.then(() =>
|
||||
Promise.all(tracks.map(t => dispatch(trackRemoved(t)))));
|
||||
|
@ -674,11 +677,11 @@ export function _disposeAndRemoveTracks(tracks) {
|
|||
* @returns {Promise} - A Promise resolved once {@link JitsiTrack.dispose()} is
|
||||
* done for every track from the list.
|
||||
*/
|
||||
function _disposeTracks(tracks) {
|
||||
function _disposeTracks(tracks: any) {
|
||||
return Promise.all(
|
||||
tracks.map(t =>
|
||||
tracks.map((t: any) =>
|
||||
t.dispose()
|
||||
.catch(err => {
|
||||
.catch((err: Error) => {
|
||||
// Track might be already disposed so ignore such an error.
|
||||
// Of course, re-throw any other error(s).
|
||||
if (err.name !== JitsiTrackErrors.TRACK_IS_DISPOSED) {
|
||||
|
@ -697,8 +700,8 @@ function _disposeTracks(tracks) {
|
|||
* @private
|
||||
* @returns {Function}
|
||||
*/
|
||||
function _onCreateLocalTracksRejected(error, device) {
|
||||
return dispatch => {
|
||||
function _onCreateLocalTracksRejected(error: Error, device: string) {
|
||||
return (dispatch: IStore['dispatch']) => {
|
||||
// If permissions are not allowed, alert the user.
|
||||
dispatch({
|
||||
type: TRACK_CREATE_ERROR,
|
||||
|
@ -724,11 +727,10 @@ function _onCreateLocalTracksRejected(error, device) {
|
|||
* @private
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function _shouldMirror(track) {
|
||||
function _shouldMirror(track: any) {
|
||||
return (
|
||||
track
|
||||
&& track.isLocal()
|
||||
&& track.isVideoTrack()
|
||||
track?.isLocal()
|
||||
&& track?.isVideoTrack()
|
||||
|
||||
// XXX The type of the return value of JitsiLocalTrack's
|
||||
// getCameraFacingMode happens to be named CAMERA_FACING_MODE as
|
||||
|
@ -736,7 +738,7 @@ function _shouldMirror(track) {
|
|||
// of the value on the right side of the equality check is defined
|
||||
// by jitsi-meet. The type definitions are surely compatible today
|
||||
// but that may not be the case tomorrow.
|
||||
&& track.getCameraFacingMode() === CAMERA_FACING_MODE.USER);
|
||||
&& track?.getCameraFacingMode() === CAMERA_FACING_MODE.USER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -752,7 +754,7 @@ function _shouldMirror(track) {
|
|||
* trackType: MEDIA_TYPE
|
||||
* }}
|
||||
*/
|
||||
function _trackCreateCanceled(mediaType) {
|
||||
function _trackCreateCanceled(mediaType: MediaType) {
|
||||
return {
|
||||
type: TRACK_CREATE_CANCELED,
|
||||
trackType: mediaType
|
||||
|
@ -765,7 +767,7 @@ function _trackCreateCanceled(mediaType) {
|
|||
* @returns {Function}
|
||||
*/
|
||||
export function destroyLocalDesktopTrackIfExists() {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const videoTrack = getLocalVideoTrack(getState()['features/base/tracks']);
|
||||
const isDesktopTrack = videoTrack && videoTrack.videoType === VIDEO_TYPE.DESKTOP;
|
||||
|
||||
|
@ -782,10 +784,10 @@ export function destroyLocalDesktopTrackIfExists() {
|
|||
* @param {number} uid - Notification UID.
|
||||
* @returns {{
|
||||
* type: SET_NO_AUDIO_SIGNAL_UID,
|
||||
* uid: number
|
||||
* uid: string
|
||||
* }}
|
||||
*/
|
||||
export function setNoSrcDataNotificationUid(uid) {
|
||||
export function setNoSrcDataNotificationUid(uid?: string) {
|
||||
return {
|
||||
type: SET_NO_SRC_DATA_NOTIFICATION_UID,
|
||||
uid
|
||||
|
@ -803,7 +805,7 @@ export function setNoSrcDataNotificationUid(uid) {
|
|||
* name: string
|
||||
* }}
|
||||
*/
|
||||
export function updateLastTrackVideoMediaEvent(track, name) {
|
||||
export function updateLastTrackVideoMediaEvent(track: any, name: string) {
|
||||
return {
|
||||
type: TRACK_UPDATE_LAST_VIDEO_MEDIA_EVENT,
|
||||
track,
|
||||
|
@ -817,10 +819,10 @@ export function updateLastTrackVideoMediaEvent(track, name) {
|
|||
* @returns {Function}
|
||||
*/
|
||||
export function toggleCamera() {
|
||||
return async (dispatch, getState) => {
|
||||
return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const state = getState();
|
||||
const tracks = state['features/base/tracks'];
|
||||
const localVideoTrack = getLocalVideoTrack(tracks).jitsiTrack;
|
||||
const localVideoTrack = getLocalVideoTrack(tracks)?.jitsiTrack;
|
||||
const currentFacingMode = localVideoTrack.getCameraFacingMode();
|
||||
|
||||
/**
|
|
@ -1,39 +1,44 @@
|
|||
/* global APP */
|
||||
|
||||
import { IState, IStore } from '../../app/types';
|
||||
import { IStateful } from '../app/types';
|
||||
import {
|
||||
getMultipleVideoSendingSupportFeatureFlag,
|
||||
getMultipleVideoSupportFeatureFlag
|
||||
} from '../config/functions.any';
|
||||
import { isMobileBrowser } from '../environment/utils';
|
||||
import JitsiMeetJS, { JitsiTrackErrors, browser } from '../lib-jitsi-meet';
|
||||
import { MEDIA_TYPE, VIDEO_TYPE, setAudioMuted } from '../media';
|
||||
import { getParticipantByIdOrUndefined, getVirtualScreenshareParticipantOwnerId } from '../participants';
|
||||
import { toState } from '../redux';
|
||||
import { setAudioMuted } from '../media/actions';
|
||||
import { MediaType, MEDIA_TYPE, VIDEO_TYPE } from '../media/constants';
|
||||
import { getParticipantByIdOrUndefined, getVirtualScreenshareParticipantOwnerId } from '../participants/functions';
|
||||
import { Participant } from '../participants/types';
|
||||
import { toState } from '../redux/functions';
|
||||
import {
|
||||
getUserSelectedCameraDeviceId,
|
||||
getUserSelectedMicDeviceId
|
||||
} from '../settings';
|
||||
} from '../settings/functions.any';
|
||||
|
||||
// @ts-ignore
|
||||
import loadEffects from './loadEffects';
|
||||
import logger from './logger';
|
||||
import { ITrack } from './reducer';
|
||||
import { TrackOptions } from './types';
|
||||
|
||||
/**
|
||||
* Returns root tracks state.
|
||||
*
|
||||
* @param {Object} state - Global state.
|
||||
* @param {IState} state - Global state.
|
||||
* @returns {Object} Tracks state.
|
||||
*/
|
||||
export const getTrackState = state => state['features/base/tracks'];
|
||||
export const getTrackState = (state: IState) => state['features/base/tracks'];
|
||||
|
||||
/**
|
||||
* Checks if the passed media type is muted for the participant.
|
||||
*
|
||||
* @param {Object} participant - Participant reference.
|
||||
* @param {MEDIA_TYPE} mediaType - Media type.
|
||||
* @param {Object} state - Global state.
|
||||
* @param {Participant} participant - Participant reference.
|
||||
* @param {MediaType} mediaType - Media type.
|
||||
* @param {IState} state - Global state.
|
||||
* @returns {boolean} - Is the media type muted for the participant.
|
||||
*/
|
||||
export function isParticipantMediaMuted(participant, mediaType, state) {
|
||||
export function isParticipantMediaMuted(participant: Participant, mediaType: MediaType, state: IState) {
|
||||
if (!participant) {
|
||||
return false;
|
||||
}
|
||||
|
@ -52,22 +57,22 @@ export function isParticipantMediaMuted(participant, mediaType, state) {
|
|||
/**
|
||||
* Checks if the participant is audio muted.
|
||||
*
|
||||
* @param {Object} participant - Participant reference.
|
||||
* @param {Object} state - Global state.
|
||||
* @param {Participant} participant - Participant reference.
|
||||
* @param {IState} state - Global state.
|
||||
* @returns {boolean} - Is audio muted for the participant.
|
||||
*/
|
||||
export function isParticipantAudioMuted(participant, state) {
|
||||
export function isParticipantAudioMuted(participant: Participant, state: IState) {
|
||||
return isParticipantMediaMuted(participant, MEDIA_TYPE.AUDIO, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the participant is video muted.
|
||||
*
|
||||
* @param {Object} participant - Participant reference.
|
||||
* @param {Object} state - Global state.
|
||||
* @param {Participant} participant - Participant reference.
|
||||
* @param {IState} state - Global state.
|
||||
* @returns {boolean} - Is video muted for the participant.
|
||||
*/
|
||||
export function isParticipantVideoMuted(participant, state) {
|
||||
export function isParticipantVideoMuted(participant: Participant, state: IState) {
|
||||
return isParticipantMediaMuted(participant, MEDIA_TYPE.VIDEO, state);
|
||||
}
|
||||
|
||||
|
@ -83,7 +88,7 @@ export function isParticipantVideoMuted(participant, state) {
|
|||
* shared.
|
||||
* @returns {Promise<JitsiLocalTrack>}
|
||||
*/
|
||||
export async function createLocalPresenterTrack(options, desktopHeight) {
|
||||
export async function createLocalPresenterTrack(options: TrackOptions, desktopHeight: number) {
|
||||
const { cameraDeviceId } = options;
|
||||
|
||||
// compute the constraints of the camera track based on the resolution
|
||||
|
@ -130,11 +135,11 @@ export async function createLocalPresenterTrack(options, desktopHeight) {
|
|||
* @param {boolean} [options.fireSlowPromiseEvent] - Whether lib-jitsi-meet
|
||||
* should check for a slow {@code getUserMedia} request and fire a
|
||||
* corresponding event.
|
||||
* @param {Object} store - The redux store in the context of which the function
|
||||
* @param {IStore} store - The redux store in the context of which the function
|
||||
* is to execute and from which state such as {@code config} is to be retrieved.
|
||||
* @returns {Promise<JitsiLocalTrack[]>}
|
||||
*/
|
||||
export function createLocalTracksF(options = {}, store) {
|
||||
export function createLocalTracksF(options: TrackOptions = {}, store?: IStore) {
|
||||
let { cameraDeviceId, micDeviceId } = options;
|
||||
const {
|
||||
desktopSharingSourceDevice,
|
||||
|
@ -147,7 +152,9 @@ export function createLocalTracksF(options = {}, store) {
|
|||
if (typeof APP !== 'undefined') {
|
||||
// TODO The app's settings should go in the redux store and then the
|
||||
// reliance on the global variable APP will go away.
|
||||
store || (store = APP.store); // eslint-disable-line no-param-reassign
|
||||
if (!store) {
|
||||
store = APP.store; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
const state = store.getState();
|
||||
|
||||
|
@ -159,6 +166,7 @@ export function createLocalTracksF(options = {}, store) {
|
|||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const state = store.getState();
|
||||
const {
|
||||
desktopSharingFrameRate,
|
||||
|
@ -168,7 +176,7 @@ export function createLocalTracksF(options = {}, store) {
|
|||
const constraints = options.constraints ?? state['features/base/config'].constraints;
|
||||
|
||||
return (
|
||||
loadEffects(store).then(effectsArray => {
|
||||
loadEffects(store).then((effectsArray: Object[]) => {
|
||||
// Filter any undefined values returned by Promise.resolve().
|
||||
const effects = effectsArray.filter(effect => Boolean(effect));
|
||||
|
||||
|
@ -181,7 +189,7 @@ export function createLocalTracksF(options = {}, store) {
|
|||
desktopSharingSources,
|
||||
|
||||
// Copy array to avoid mutations inside library.
|
||||
devices: options.devices.slice(0),
|
||||
devices: options.devices?.slice(0),
|
||||
effects,
|
||||
firefox_fake_device, // eslint-disable-line camelcase
|
||||
firePermissionPromptIsShownEvent,
|
||||
|
@ -190,7 +198,7 @@ export function createLocalTracksF(options = {}, store) {
|
|||
resolution,
|
||||
timeout
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err: Error) => {
|
||||
logger.error('Failed to create local tracks', options.devices, err);
|
||||
|
||||
return Promise.reject(err);
|
||||
|
@ -207,7 +215,7 @@ export function createLocalTracksF(options = {}, store) {
|
|||
* @todo Refactor to not use APP.
|
||||
*/
|
||||
export function createPrejoinTracks() {
|
||||
const errors = {};
|
||||
const errors: any = {};
|
||||
const initialDevices = [ 'audio' ];
|
||||
const requestedAudio = true;
|
||||
let requestedVideo = false;
|
||||
|
@ -235,8 +243,8 @@ export function createPrejoinTracks() {
|
|||
tryCreateLocalTracks = createLocalTracksF({
|
||||
devices: initialDevices,
|
||||
firePermissionPromptIsShownEvent: true
|
||||
})
|
||||
.catch(err => {
|
||||
}, APP.store)
|
||||
.catch((err: Error) => {
|
||||
if (requestedAudio && requestedVideo) {
|
||||
|
||||
// Try audio only...
|
||||
|
@ -258,7 +266,7 @@ export function createPrejoinTracks() {
|
|||
}
|
||||
logger.error('Should never happen');
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err: Error) => {
|
||||
// Log this just in case...
|
||||
if (!requestedAudio) {
|
||||
logger.error('The impossible just happened', err);
|
||||
|
@ -273,7 +281,7 @@ export function createPrejoinTracks() {
|
|||
})
|
||||
: [];
|
||||
})
|
||||
.catch(err => {
|
||||
.catch((err: Error) => {
|
||||
// Log this just in case...
|
||||
if (!requestedVideo) {
|
||||
logger.error('The impossible just happened', err);
|
||||
|
@ -293,10 +301,10 @@ export function createPrejoinTracks() {
|
|||
/**
|
||||
* Returns local audio track.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @returns {(Track|undefined)}
|
||||
*/
|
||||
export function getLocalAudioTrack(tracks) {
|
||||
export function getLocalAudioTrack(tracks: ITrack[]) {
|
||||
return getLocalTrack(tracks, MEDIA_TYPE.AUDIO);
|
||||
}
|
||||
|
||||
|
@ -309,7 +317,7 @@ export function getLocalAudioTrack(tracks) {
|
|||
* {@code jitsiTrack} property is {@code undefined}. By default a pending local track is not returned.
|
||||
* @returns {(Track|undefined)}
|
||||
*/
|
||||
export function getLocalDesktopTrack(tracks, includePending = false) {
|
||||
export function getLocalDesktopTrack(tracks: ITrack[], includePending = false) {
|
||||
return (
|
||||
getLocalTracks(tracks, includePending)
|
||||
.find(t => t.mediaType === MEDIA_TYPE.SCREENSHARE || t.videoType === VIDEO_TYPE.DESKTOP));
|
||||
|
@ -318,10 +326,10 @@ export function getLocalDesktopTrack(tracks, includePending = false) {
|
|||
/**
|
||||
* Returns the stored local desktop jitsiLocalTrack.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @param {IState} state - The redux state.
|
||||
* @returns {JitsiLocalTrack|undefined}
|
||||
*/
|
||||
export function getLocalJitsiDesktopTrack(state) {
|
||||
export function getLocalJitsiDesktopTrack(state: IState) {
|
||||
const track = getLocalDesktopTrack(getTrackState(state));
|
||||
|
||||
return track?.jitsiTrack;
|
||||
|
@ -330,8 +338,8 @@ export function getLocalJitsiDesktopTrack(state) {
|
|||
/**
|
||||
* Returns local track by media type.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {MEDIA_TYPE} mediaType - Media type.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @param {MediaType} mediaType - Media type.
|
||||
* @param {boolean} [includePending] - Indicates whether a local track is to be
|
||||
* returned if it is still pending. A local track is pending if
|
||||
* {@code getUserMedia} is still executing to create it and, consequently, its
|
||||
|
@ -339,7 +347,7 @@ export function getLocalJitsiDesktopTrack(state) {
|
|||
* track is not returned.
|
||||
* @returns {(Track|undefined)}
|
||||
*/
|
||||
export function getLocalTrack(tracks, mediaType, includePending = false) {
|
||||
export function getLocalTrack(tracks: ITrack[], mediaType: MediaType, includePending = false) {
|
||||
return (
|
||||
getLocalTracks(tracks, includePending)
|
||||
.find(t => t.mediaType === mediaType));
|
||||
|
@ -349,7 +357,7 @@ export function getLocalTrack(tracks, mediaType, includePending = false) {
|
|||
* Returns an array containing the local tracks with or without a (valid)
|
||||
* {@code JitsiTrack}.
|
||||
*
|
||||
* @param {Track[]} tracks - An array containing all local tracks.
|
||||
* @param {ITrack[]} tracks - An array containing all local tracks.
|
||||
* @param {boolean} [includePending] - Indicates whether a local track is to be
|
||||
* returned if it is still pending. A local track is pending if
|
||||
* {@code getUserMedia} is still executing to create it and, consequently, its
|
||||
|
@ -357,7 +365,7 @@ export function getLocalTrack(tracks, mediaType, includePending = false) {
|
|||
* track is not returned.
|
||||
* @returns {Track[]}
|
||||
*/
|
||||
export function getLocalTracks(tracks, includePending = false) {
|
||||
export function getLocalTracks(tracks: ITrack[], includePending = false) {
|
||||
// XXX A local track is considered ready only once it has its `jitsiTrack`
|
||||
// property set by the `TRACK_ADDED` action. Until then there is a stub
|
||||
// added just before the `getUserMedia` call with a cancellable
|
||||
|
@ -371,20 +379,20 @@ export function getLocalTracks(tracks, includePending = false) {
|
|||
/**
|
||||
* Returns local video track.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @returns {(Track|undefined)}
|
||||
*/
|
||||
export function getLocalVideoTrack(tracks) {
|
||||
export function getLocalVideoTrack(tracks: ITrack[]) {
|
||||
return getLocalTrack(tracks, MEDIA_TYPE.VIDEO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the media type of the local video, presenter or video.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @returns {MEDIA_TYPE}
|
||||
*/
|
||||
export function getLocalVideoType(tracks) {
|
||||
export function getLocalVideoType(tracks: ITrack[]) {
|
||||
const presenterTrack = getLocalTrack(tracks, MEDIA_TYPE.PRESENTER);
|
||||
|
||||
return presenterTrack ? MEDIA_TYPE.PRESENTER : MEDIA_TYPE.VIDEO;
|
||||
|
@ -393,10 +401,10 @@ export function getLocalVideoType(tracks) {
|
|||
/**
|
||||
* Returns the stored local video track.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @param {IState} state - The redux state.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function getLocalJitsiVideoTrack(state) {
|
||||
export function getLocalJitsiVideoTrack(state: IState) {
|
||||
const track = getLocalVideoTrack(getTrackState(state));
|
||||
|
||||
return track?.jitsiTrack;
|
||||
|
@ -405,10 +413,10 @@ export function getLocalJitsiVideoTrack(state) {
|
|||
/**
|
||||
* Returns the stored local audio track.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @param {IState} state - The redux state.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function getLocalJitsiAudioTrack(state) {
|
||||
export function getLocalJitsiAudioTrack(state: IState) {
|
||||
const track = getLocalAudioTrack(getTrackState(state));
|
||||
|
||||
return track?.jitsiTrack;
|
||||
|
@ -417,13 +425,13 @@ export function getLocalJitsiAudioTrack(state) {
|
|||
/**
|
||||
* Returns track of specified media type for specified participant.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {Object} participant - Participant Object.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @param {Participant} participant - Participant Object.
|
||||
* @returns {(Track|undefined)}
|
||||
*/
|
||||
export function getVideoTrackByParticipant(
|
||||
tracks,
|
||||
participant) {
|
||||
tracks: ITrack[],
|
||||
participant?: Participant) {
|
||||
|
||||
if (!participant) {
|
||||
return;
|
||||
|
@ -439,11 +447,11 @@ export function getVideoTrackByParticipant(
|
|||
/**
|
||||
* Returns source name for specified participant id.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @param {IState} state - The Redux state.
|
||||
* @param {string} participantId - Participant ID.
|
||||
* @returns {string | undefined}
|
||||
*/
|
||||
export function getSourceNameByParticipantId(state, participantId) {
|
||||
export function getSourceNameByParticipantId(state: IState, participantId: string) {
|
||||
const participant = getParticipantByIdOrUndefined(state, participantId);
|
||||
const tracks = state['features/base/tracks'];
|
||||
const track = getVideoTrackByParticipant(tracks, participant);
|
||||
|
@ -454,15 +462,15 @@ export function getSourceNameByParticipantId(state, participantId) {
|
|||
/**
|
||||
* Returns track of specified media type for specified participant id.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {MEDIA_TYPE} mediaType - Media type.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @param {MediaType} mediaType - Media type.
|
||||
* @param {string} participantId - Participant ID.
|
||||
* @returns {(Track|undefined)}
|
||||
*/
|
||||
export function getTrackByMediaTypeAndParticipant(
|
||||
tracks,
|
||||
mediaType,
|
||||
participantId) {
|
||||
tracks: ITrack[],
|
||||
mediaType: MediaType,
|
||||
participantId: string) {
|
||||
return tracks.find(
|
||||
t => Boolean(t.jitsiTrack) && t.participantId === participantId && t.mediaType === mediaType
|
||||
);
|
||||
|
@ -471,11 +479,11 @@ export function getTrackByMediaTypeAndParticipant(
|
|||
/**
|
||||
* Returns screenshare track of given virtualScreenshareParticipantId.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @param {string} virtualScreenshareParticipantId - Virtual Screenshare Participant ID.
|
||||
* @returns {(Track|undefined)}
|
||||
*/
|
||||
export function getVirtualScreenshareParticipantTrack(tracks, virtualScreenshareParticipantId) {
|
||||
export function getVirtualScreenshareParticipantTrack(tracks: ITrack[], virtualScreenshareParticipantId: string) {
|
||||
const ownderId = getVirtualScreenshareParticipantOwnerId(virtualScreenshareParticipantId);
|
||||
|
||||
return getScreenShareTrack(tracks, ownderId);
|
||||
|
@ -484,16 +492,16 @@ export function getVirtualScreenshareParticipantTrack(tracks, virtualScreenshare
|
|||
/**
|
||||
* Returns track source names of given screen share participant ids.
|
||||
*
|
||||
* @param {Object} state - The entire redux state.
|
||||
* @param {IState} state - The entire redux state.
|
||||
* @param {string[]} screenShareParticipantIds - Participant ID.
|
||||
* @returns {(string[])}
|
||||
*/
|
||||
export function getRemoteScreenSharesSourceNames(state, screenShareParticipantIds = []) {
|
||||
export function getRemoteScreenSharesSourceNames(state: IState, screenShareParticipantIds = []) {
|
||||
const tracks = state['features/base/tracks'];
|
||||
|
||||
return getMultipleVideoSupportFeatureFlag(state)
|
||||
? screenShareParticipantIds
|
||||
: screenShareParticipantIds.reduce((acc, id) => {
|
||||
: screenShareParticipantIds.reduce((acc: string[], id) => {
|
||||
const sourceName = getScreenShareTrack(tracks, id)?.jitsiTrack.getSourceName();
|
||||
|
||||
if (sourceName) {
|
||||
|
@ -511,7 +519,7 @@ export function getRemoteScreenSharesSourceNames(state, screenShareParticipantId
|
|||
* @param {string} ownerId - Screenshare track owner ID.
|
||||
* @returns {(Track|undefined)}
|
||||
*/
|
||||
export function getScreenShareTrack(tracks, ownerId) {
|
||||
export function getScreenShareTrack(tracks: ITrack[], ownerId: string) {
|
||||
return tracks.find(
|
||||
t => Boolean(t.jitsiTrack)
|
||||
&& t.participantId === ownerId
|
||||
|
@ -522,15 +530,15 @@ export function getScreenShareTrack(tracks, ownerId) {
|
|||
/**
|
||||
* Returns track source name of specified media type for specified participant id.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {MEDIA_TYPE} mediaType - Media type.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @param {MediaType} mediaType - Media type.
|
||||
* @param {string} participantId - Participant ID.
|
||||
* @returns {(string|undefined)}
|
||||
*/
|
||||
export function getTrackSourceNameByMediaTypeAndParticipant(
|
||||
tracks,
|
||||
mediaType,
|
||||
participantId) {
|
||||
tracks: ITrack[],
|
||||
mediaType: MediaType,
|
||||
participantId: string) {
|
||||
const track = getTrackByMediaTypeAndParticipant(
|
||||
tracks,
|
||||
mediaType,
|
||||
|
@ -543,32 +551,32 @@ export function getTrackSourceNameByMediaTypeAndParticipant(
|
|||
* Returns the track if any which corresponds to a specific instance
|
||||
* of JitsiLocalTrack or JitsiRemoteTrack.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @param {(JitsiLocalTrack|JitsiRemoteTrack)} jitsiTrack - JitsiTrack instance.
|
||||
* @returns {(Track|undefined)}
|
||||
*/
|
||||
export function getTrackByJitsiTrack(tracks, jitsiTrack) {
|
||||
export function getTrackByJitsiTrack(tracks: ITrack[], jitsiTrack: any) {
|
||||
return tracks.find(t => t.jitsiTrack === jitsiTrack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns tracks of specified media type.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {MEDIA_TYPE} mediaType - Media type.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @param {MediaType} mediaType - Media type.
|
||||
* @returns {Track[]}
|
||||
*/
|
||||
export function getTracksByMediaType(tracks, mediaType) {
|
||||
export function getTracksByMediaType(tracks: ITrack[], mediaType: MediaType) {
|
||||
return tracks.filter(t => t.mediaType === mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the local video camera track in the given set of tracks is muted.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @returns {Track[]}
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @returns {ITrack[]}
|
||||
*/
|
||||
export function isLocalCameraTrackMuted(tracks) {
|
||||
export function isLocalCameraTrackMuted(tracks: ITrack[]) {
|
||||
const presenterTrack = getLocalTrack(tracks, MEDIA_TYPE.PRESENTER);
|
||||
const videoTrack = getLocalTrack(tracks, MEDIA_TYPE.VIDEO);
|
||||
|
||||
|
@ -588,13 +596,13 @@ export function isLocalCameraTrackMuted(tracks) {
|
|||
/**
|
||||
* Checks if the first local track in the given tracks set is muted.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {MEDIA_TYPE} mediaType - The media type of tracks to be checked.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @param {MediaType} mediaType - The media type of tracks to be checked.
|
||||
* @returns {boolean} True if local track is muted or false if the track is
|
||||
* unmuted or if there are no local tracks of the given media type in the given
|
||||
* set of tracks.
|
||||
*/
|
||||
export function isLocalTrackMuted(tracks, mediaType) {
|
||||
export function isLocalTrackMuted(tracks: ITrack[], mediaType: MediaType) {
|
||||
const track = getLocalTrack(tracks, mediaType);
|
||||
|
||||
return !track || track.muted;
|
||||
|
@ -603,10 +611,10 @@ export function isLocalTrackMuted(tracks, mediaType) {
|
|||
/**
|
||||
* Checks if the local video track is of type DESKtOP.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @param {IState} state - The redux state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isLocalVideoTrackDesktop(state) {
|
||||
export function isLocalVideoTrackDesktop(state: IState) {
|
||||
const videoTrack = getLocalVideoTrack(getTrackState(state));
|
||||
|
||||
return videoTrack && videoTrack.videoType === VIDEO_TYPE.DESKTOP;
|
||||
|
@ -617,12 +625,12 @@ export function isLocalVideoTrackDesktop(state) {
|
|||
* Returns true if the remote track of the given media type and the given
|
||||
* participant is muted, false otherwise.
|
||||
*
|
||||
* @param {Track[]} tracks - List of all tracks.
|
||||
* @param {MEDIA_TYPE} mediaType - The media type of tracks to be checked.
|
||||
* @param {*} participantId - Participant ID.
|
||||
* @param {ITrack[]} tracks - List of all tracks.
|
||||
* @param {MediaType} mediaType - The media type of tracks to be checked.
|
||||
* @param {string} participantId - Participant ID.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isRemoteTrackMuted(tracks, mediaType, participantId) {
|
||||
export function isRemoteTrackMuted(tracks: ITrack[], mediaType: MediaType, participantId: string) {
|
||||
const track = getTrackByMediaTypeAndParticipant(
|
||||
tracks, mediaType, participantId);
|
||||
|
||||
|
@ -633,10 +641,10 @@ export function isRemoteTrackMuted(tracks, mediaType, participantId) {
|
|||
* Returns whether or not the current environment needs a user interaction with
|
||||
* the page before any unmute can occur.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @param {IState} state - The redux state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isUserInteractionRequiredForUnmute(state) {
|
||||
export function isUserInteractionRequiredForUnmute(state: IState) {
|
||||
return browser.isUserInteractionRequiredForUnmute()
|
||||
&& window
|
||||
&& window.self !== window.top
|
||||
|
@ -652,7 +660,7 @@ export function isUserInteractionRequiredForUnmute(state) {
|
|||
* @param {Object} state - The redux state.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function setTrackMuted(track, muted, state) {
|
||||
export function setTrackMuted(track: any, muted: boolean, state: IState) {
|
||||
muted = Boolean(muted); // eslint-disable-line no-param-reassign
|
||||
|
||||
// Ignore the check for desktop track muted operation. When the screenshare is terminated by clicking on the
|
||||
|
@ -665,7 +673,7 @@ export function setTrackMuted(track, muted, state) {
|
|||
|
||||
const f = muted ? 'mute' : 'unmute';
|
||||
|
||||
return track[f]().catch(error => {
|
||||
return track[f]().catch((error: Error) => {
|
||||
// Track might be already disposed so ignore such an error.
|
||||
if (error.name !== JitsiTrackErrors.TRACK_IS_DISPOSED) {
|
||||
logger.error(`set track ${f} failed`, error);
|
||||
|
@ -681,9 +689,9 @@ export function setTrackMuted(track, muted, state) {
|
|||
* @param {Function|Object} stateful - The redux store or {@code getState} function.
|
||||
* @returns {boolean} - Whether toggle camera should be enabled.
|
||||
*/
|
||||
export function isToggleCameraEnabled(stateful) {
|
||||
export function isToggleCameraEnabled(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
const { videoInput } = state['features/base/devices'].availableDevices;
|
||||
|
||||
return isMobileBrowser() && videoInput.length > 1;
|
||||
return isMobileBrowser() && Number(videoInput?.length) > 1;
|
||||
}
|
|
@ -1,28 +1,30 @@
|
|||
// @flow
|
||||
|
||||
import { batch } from 'react-redux';
|
||||
|
||||
import { IStore } from '../../app/types';
|
||||
import { _RESET_BREAKOUT_ROOMS } from '../../breakout-rooms/actionTypes';
|
||||
import { hideNotification } from '../../notifications';
|
||||
import { hideNotification } from '../../notifications/actions';
|
||||
import { isPrejoinPageVisible } from '../../prejoin/functions';
|
||||
import { getCurrentConference } from '../conference/functions';
|
||||
import { getMultipleVideoSendingSupportFeatureFlag } from '../config';
|
||||
import { getMultipleVideoSendingSupportFeatureFlag } from '../config/functions.any';
|
||||
import { getAvailableDevices } from '../devices/actions';
|
||||
import {
|
||||
CAMERA_FACING_MODE,
|
||||
MEDIA_TYPE,
|
||||
SET_AUDIO_MUTED,
|
||||
SET_CAMERA_FACING_MODE,
|
||||
SET_VIDEO_MUTED,
|
||||
VIDEO_MUTISM_AUTHORITY,
|
||||
TOGGLE_CAMERA_FACING_MODE,
|
||||
toggleCameraFacingMode,
|
||||
SET_SCREENSHARE_MUTED,
|
||||
SET_SCREENSHARE_MUTED
|
||||
} from '../media/actionTypes';
|
||||
import { toggleCameraFacingMode, setScreenshareMuted } from '../media/actions';
|
||||
import {
|
||||
CAMERA_FACING_MODE,
|
||||
MEDIA_TYPE,
|
||||
VIDEO_MUTISM_AUTHORITY,
|
||||
VIDEO_TYPE,
|
||||
setScreenshareMuted,
|
||||
SCREENSHARE_MUTISM_AUTHORITY
|
||||
} from '../media';
|
||||
import { MiddlewareRegistry, StateListenerRegistry } from '../redux';
|
||||
SCREENSHARE_MUTISM_AUTHORITY,
|
||||
MediaType
|
||||
} from '../media/constants';
|
||||
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
|
||||
import StateListenerRegistry from '../redux/StateListenerRegistry';
|
||||
|
||||
import {
|
||||
TRACK_ADDED,
|
||||
|
@ -47,11 +49,10 @@ import {
|
|||
isUserInteractionRequiredForUnmute,
|
||||
setTrackMuted
|
||||
} from './functions';
|
||||
import { ITrack } from './reducer';
|
||||
|
||||
import './subscriber';
|
||||
|
||||
declare var APP: Object;
|
||||
|
||||
/**
|
||||
* Middleware that captures LIB_DID_DISPOSE and LIB_DID_INIT actions and,
|
||||
* respectively, creates/destroys local media tracks. Also listens to
|
||||
|
@ -267,7 +268,7 @@ StateListenerRegistry.register(
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _handleNoDataFromSourceErrors(store, action) {
|
||||
function _handleNoDataFromSourceErrors(store: IStore, action: any) {
|
||||
const { getState, dispatch } = store;
|
||||
|
||||
const track = getTrackByJitsiTrack(getState()['features/base/tracks'], action.track.jitsiTrack);
|
||||
|
@ -323,9 +324,9 @@ function _handleNoDataFromSourceErrors(store, action) {
|
|||
* {@code mediaType} in the specified {@code store}.
|
||||
*/
|
||||
function _getLocalTrack(
|
||||
{ getState }: { getState: Function },
|
||||
mediaType: MEDIA_TYPE,
|
||||
includePending: boolean = false) {
|
||||
{ getState }: { getState: Function; },
|
||||
mediaType: MediaType,
|
||||
includePending = false) {
|
||||
return (
|
||||
getLocalTrack(
|
||||
getState()['features/base/tracks'],
|
||||
|
@ -340,11 +341,11 @@ function _getLocalTrack(
|
|||
* @param {Track} track - The redux action dispatched in the specified store.
|
||||
* @returns {void}
|
||||
*/
|
||||
function _removeNoDataFromSourceNotification({ getState, dispatch }, track) {
|
||||
function _removeNoDataFromSourceNotification({ getState, dispatch }: IStore, track: ITrack) {
|
||||
const t = getTrackByJitsiTrack(getState()['features/base/tracks'], track.jitsiTrack);
|
||||
const { jitsiTrack, noDataFromSourceNotificationInfo = {} } = t || {};
|
||||
|
||||
if (noDataFromSourceNotificationInfo && noDataFromSourceNotificationInfo.uid) {
|
||||
if (noDataFromSourceNotificationInfo?.uid) {
|
||||
dispatch(hideNotification(noDataFromSourceNotificationInfo.uid));
|
||||
dispatch(trackNoDataFromSourceNotificationInfoChanged(jitsiTrack, undefined));
|
||||
}
|
||||
|
@ -361,7 +362,8 @@ function _removeNoDataFromSourceNotification({ getState, dispatch }, track) {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
async function _setMuted(store, { ensureTrack, authority, muted }, mediaType: MEDIA_TYPE) {
|
||||
async function _setMuted(store: IStore, { ensureTrack, authority, muted }: {
|
||||
authority: number; ensureTrack: boolean; muted: boolean; }, mediaType: MediaType) {
|
||||
const { dispatch, getState } = store;
|
||||
const localTrack = _getLocalTrack(store, mediaType, /* includePending */ true);
|
||||
const state = getState();
|
|
@ -1,3 +1,4 @@
|
|||
import { MediaType } from '../media/constants';
|
||||
import { PARTICIPANT_ID_CHANGED } from '../participants/actionTypes';
|
||||
import ReducerRegistry from '../redux/ReducerRegistry';
|
||||
import { set } from '../redux/functions';
|
||||
|
@ -14,14 +15,18 @@ import {
|
|||
TRACK_WILL_CREATE
|
||||
} from './actionTypes';
|
||||
|
||||
interface ITrack {
|
||||
export interface ITrack {
|
||||
isReceivingData: boolean;
|
||||
jitsiTrack: any;
|
||||
lastMediaEvent?: string;
|
||||
local: boolean;
|
||||
mediaType: string;
|
||||
mediaType: MediaType;
|
||||
mirror: boolean;
|
||||
muted: boolean;
|
||||
noDataFromSourceNotificationInfo?: {
|
||||
timeout?: number;
|
||||
uid?: string;
|
||||
};
|
||||
participantId: string;
|
||||
streamingStatus?: string;
|
||||
videoStarted: boolean;
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
// @flow
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
import { StateListenerRegistry } from '../../base/redux';
|
||||
import StateListenerRegistry from '../redux/StateListenerRegistry';
|
||||
|
||||
import { isLocalCameraTrackMuted } from './functions';
|
||||
|
||||
declare var APP: Object;
|
||||
|
||||
/**
|
||||
* Notifies when the list of currently sharing participants changes.
|
||||
*/
|
|
@ -0,0 +1,20 @@
|
|||
export interface TrackOptions {
|
||||
cameraDeviceId?: string | null;
|
||||
constraints?: {
|
||||
video?: {
|
||||
height?: {
|
||||
ideal?: number;
|
||||
max?: number;
|
||||
min?: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
desktopSharingSourceDevice?: string;
|
||||
desktopSharingSources?: string[];
|
||||
devices?: string[];
|
||||
facingMode?: string;
|
||||
firePermissionPromptIsShownEvent?: boolean;
|
||||
fireSlowPromiseEvent?: boolean;
|
||||
micDeviceId?: string | null;
|
||||
timeout?: number;
|
||||
}
|
|
@ -64,7 +64,7 @@ const Prejoin: React.FC<PrejoinProps> = ({ navigation }: PrejoinProps) => {
|
|||
(state: IState) => state['features/base/responsive-ui']?.aspectRatio
|
||||
);
|
||||
const localParticipant = useSelector((state: IState) => getLocalParticipant(state));
|
||||
const isDisplayNameMandatory = useSelector(state => isDisplayNameRequired(state));
|
||||
const isDisplayNameMandatory = useSelector((state: IState) => isDisplayNameRequired(state));
|
||||
const roomName = useSelector((state: IState) => getConferenceName(state));
|
||||
const participantName = localParticipant?.name;
|
||||
const [ displayName, setDisplayName ]
|
||||
|
|
|
@ -1,26 +1,25 @@
|
|||
// @flow
|
||||
|
||||
import { getRoomName } from '../base/conference';
|
||||
import { getDialOutStatusUrl, getDialOutUrl } from '../base/config/functions';
|
||||
import { isAudioMuted, isVideoMutedByUser } from '../base/media';
|
||||
import { IState } from '../app/types';
|
||||
import { getRoomName } from '../base/conference/functions';
|
||||
import { getDialOutStatusUrl, getDialOutUrl } from '../base/config/functions.web';
|
||||
import { isAudioMuted, isVideoMutedByUser } from '../base/media/functions';
|
||||
|
||||
/**
|
||||
* Selector for the visibility of the 'join by phone' button.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isJoinByPhoneButtonVisible(state: Object): boolean {
|
||||
export function isJoinByPhoneButtonVisible(state: IState): boolean {
|
||||
return Boolean(getDialOutUrl(state) && getDialOutStatusUrl(state));
|
||||
}
|
||||
|
||||
/**
|
||||
* Selector for determining if the device status strip is visible or not.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isDeviceStatusVisible(state: Object): boolean {
|
||||
export function isDeviceStatusVisible(state: IState): boolean {
|
||||
return !(isAudioMuted(state) && isVideoMutedByUser(state))
|
||||
&& !state['features/base/config'].startSilent;
|
||||
}
|
||||
|
@ -28,91 +27,91 @@ export function isDeviceStatusVisible(state: Object): boolean {
|
|||
/**
|
||||
* Selector for determining if the display name is mandatory.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isDisplayNameRequired(state: Object): boolean {
|
||||
return state['features/prejoin']?.isDisplayNameRequired
|
||||
|| state['features/base/config']?.requireDisplayName;
|
||||
export function isDisplayNameRequired(state: IState): boolean {
|
||||
return Boolean(state['features/prejoin']?.isDisplayNameRequired
|
||||
|| state['features/base/config']?.requireDisplayName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Selector for determining if the prejoin display name field is visible.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPrejoinDisplayNameVisible(state: Object): boolean {
|
||||
export function isPrejoinDisplayNameVisible(state: IState): boolean {
|
||||
return !state['features/base/config'].prejoinConfig?.hideDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text for the prejoin status bar.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getDeviceStatusText(state: Object): string {
|
||||
export function getDeviceStatusText(state: IState): string {
|
||||
return state['features/prejoin']?.deviceStatusText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the prejoin status bar: 'ok'|'warning'.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getDeviceStatusType(state: Object): string {
|
||||
export function getDeviceStatusType(state: IState): string {
|
||||
return state['features/prejoin']?.deviceStatusType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the 'conferenceUrl' used for dialing out.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getDialOutConferenceUrl(state: Object): string {
|
||||
return `${getRoomName(state)}@${state['features/base/config'].hosts.muc}`;
|
||||
export function getDialOutConferenceUrl(state: IState): string {
|
||||
return `${getRoomName(state)}@${state['features/base/config'].hosts?.muc}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selector for getting the dial out country.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {Object}
|
||||
*/
|
||||
export function getDialOutCountry(state: Object): Object {
|
||||
export function getDialOutCountry(state: IState) {
|
||||
return state['features/prejoin'].dialOutCountry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selector for getting the dial out number (without prefix).
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getDialOutNumber(state: Object): string {
|
||||
export function getDialOutNumber(state: IState): string {
|
||||
return state['features/prejoin'].dialOutNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selector for getting the dial out status while calling.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getDialOutStatus(state: Object): string {
|
||||
export function getDialOutStatus(state: IState): string {
|
||||
return state['features/prejoin'].dialOutStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full dial out number (containing country code and +).
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getFullDialOutNumber(state: Object): string {
|
||||
export function getFullDialOutNumber(state: IState): string {
|
||||
const dialOutNumber = getDialOutNumber(state);
|
||||
const country = getDialOutCountry(state);
|
||||
|
||||
|
@ -122,20 +121,20 @@ export function getFullDialOutNumber(state: Object): string {
|
|||
/**
|
||||
* Selector for getting the error if any while creating streams.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getRawError(state: Object): string {
|
||||
export function getRawError(state: IState): string {
|
||||
return state['features/prejoin']?.rawError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selector for getting the visibility state for the 'JoinByPhoneDialog'.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isJoinByPhoneDialogVisible(state: Object): boolean {
|
||||
export function isJoinByPhoneDialogVisible(state: IState): boolean {
|
||||
return state['features/prejoin']?.showJoinByPhoneDialog;
|
||||
}
|
||||
|
||||
|
@ -143,28 +142,28 @@ export function isJoinByPhoneDialogVisible(state: Object): boolean {
|
|||
* Returns true if the prejoin page is enabled and no flag
|
||||
* to bypass showing the page is present.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isPrejoinPageVisible(state: Object): boolean {
|
||||
return navigator.product !== 'ReactNative'
|
||||
export function isPrejoinPageVisible(state: IState): boolean {
|
||||
return Boolean(navigator.product !== 'ReactNative'
|
||||
&& state['features/base/config'].prejoinConfig?.enabled
|
||||
&& state['features/prejoin']?.showPrejoin
|
||||
&& !(state['features/base/config'].enableForcedReload && state['features/prejoin'].skipPrejoinOnReload);
|
||||
&& !(state['features/base/config'].enableForcedReload && state['features/prejoin'].skipPrejoinOnReload));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we should auto-knock in case lobby is enabled for the room.
|
||||
*
|
||||
* @param {Object} state - The state of the app.
|
||||
* @param {IState} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function shouldAutoKnock(state: Object): boolean {
|
||||
export function shouldAutoKnock(state: IState): boolean {
|
||||
const { iAmRecorder, iAmSipGateway, autoKnockLobby, prejoinConfig } = state['features/base/config'];
|
||||
const { userSelectedSkipPrejoin } = state['features/base/settings'];
|
||||
const isPrejoinEnabled = prejoinConfig?.enabled;
|
||||
|
||||
return ((isPrejoinEnabled && !userSelectedSkipPrejoin)
|
||||
return Boolean(((isPrejoinEnabled && !userSelectedSkipPrejoin)
|
||||
|| autoKnockLobby || (iAmRecorder && iAmSipGateway))
|
||||
&& !state['features/lobby'].knocking;
|
||||
&& !state['features/lobby'].knocking);
|
||||
}
|
Loading…
Reference in New Issue