diff --git a/react/features/base/conference/reducer.ts b/react/features/base/conference/reducer.ts index a96885c8b..3079949e2 100644 --- a/react/features/base/conference/reducer.ts +++ b/react/features/base/conference/reducer.ts @@ -50,6 +50,7 @@ export interface IJitsiConference { getBreakoutRooms: Function; getLocalParticipantProperty: Function; getLocalTracks: Function; + getParticipantById: Function; grantOwner: Function; isAVModerationSupported: Function; isCallstatsEnabled: Function; @@ -74,6 +75,8 @@ export interface IJitsiConference { setDesktopSharingFrameRate: Function; setDisplayName: Function; setLocalParticipantProperty: Function; + setReceiverConstraints: Function; + setSenderVideoConstraint: Function; setSubject: Function; } diff --git a/react/features/base/config/configType.ts b/react/features/base/config/configType.ts index 419d2354f..8a8a406bd 100644 --- a/react/features/base/config/configType.ts +++ b/react/features/base/config/configType.ts @@ -433,7 +433,7 @@ export interface IConfig { disableSearch?: boolean; disabled?: boolean; order?: Array<'role' | 'name' | 'hasLeft'>; - }; + }; speakerStatsOrder?: Array<'role' | 'name' | 'hasLeft'>; startAudioMuted?: number; startAudioOnly?: boolean; @@ -492,6 +492,7 @@ export interface IConfig { minHeightForQualityLvl?: { [key: number]: string; }; + persist?: boolean; preferredCodec?: string; resizeDesktopForPresenter?: boolean; }; diff --git a/react/features/base/tracks/functions.ts b/react/features/base/tracks/functions.ts index ba054067a..54083ab37 100644 --- a/react/features/base/tracks/functions.ts +++ b/react/features/base/tracks/functions.ts @@ -496,7 +496,7 @@ export function getVirtualScreenshareParticipantTrack(tracks: ITrack[], virtualS * @param {string[]} screenShareParticipantIds - Participant ID. * @returns {(string[])} */ -export function getRemoteScreenSharesSourceNames(state: IReduxState, screenShareParticipantIds = []) { +export function getRemoteScreenSharesSourceNames(state: IReduxState, screenShareParticipantIds: string[] = []) { const tracks = state['features/base/tracks']; return getMultipleVideoSupportFeatureFlag(state) diff --git a/react/features/follow-me/actions.js b/react/features/follow-me/actions.ts similarity index 84% rename from react/features/follow-me/actions.js rename to react/features/follow-me/actions.ts index ac64cbdb8..c6acbef46 100644 --- a/react/features/follow-me/actions.js +++ b/react/features/follow-me/actions.ts @@ -1,5 +1,3 @@ -// @flow - import { SET_FOLLOW_ME_MODERATOR, SET_FOLLOW_ME_STATE @@ -14,7 +12,7 @@ import { * id, string * }} */ -export function setFollowMeModerator(id: ?string) { +export function setFollowMeModerator(id?: string) { return { type: SET_FOLLOW_ME_MODERATOR, id @@ -30,7 +28,7 @@ export function setFollowMeModerator(id: ?string) { * state: Object * }} */ -export function setFollowMeState(state: ?Object) { +export function setFollowMeState(state?: Object) { return { type: SET_FOLLOW_ME_STATE, state diff --git a/react/features/follow-me/functions.js b/react/features/follow-me/functions.ts similarity index 69% rename from react/features/follow-me/functions.js rename to react/features/follow-me/functions.ts index ca23a87e3..25c22f871 100644 --- a/react/features/follow-me/functions.js +++ b/react/features/follow-me/functions.ts @@ -1,6 +1,5 @@ -// @flow - -import { toState } from '../base/redux'; +import { IStateful } from '../base/app/types'; +import { toState } from '../base/redux/functions'; /** * Returns true if follow me is active and false otherwise. @@ -9,7 +8,7 @@ import { toState } from '../base/redux'; * to the Redux state. * @returns {boolean} - True if follow me is active and false otherwise. */ -export function isFollowMeActive(stateful: Object | Function) { +export function isFollowMeActive(stateful: IStateful) { const state = toState(stateful); return Boolean(state['features/follow-me'].moderator); diff --git a/react/features/follow-me/logger.js b/react/features/follow-me/logger.ts similarity index 91% rename from react/features/follow-me/logger.js rename to react/features/follow-me/logger.ts index 0853fd3de..5ead2a375 100644 --- a/react/features/follow-me/logger.js +++ b/react/features/follow-me/logger.ts @@ -1,5 +1,3 @@ -// @flow - import { getLogger } from '../base/logging/functions'; export default getLogger('features/follow-me'); diff --git a/react/features/follow-me/middleware.js b/react/features/follow-me/middleware.ts similarity index 85% rename from react/features/follow-me/middleware.js rename to react/features/follow-me/middleware.ts index 778740cb6..44294d2bf 100644 --- a/react/features/follow-me/middleware.js +++ b/react/features/follow-me/middleware.ts @@ -1,19 +1,16 @@ -// @flow - import _ from 'lodash'; +import { IStore } from '../app/types'; import { CONFERENCE_JOIN_IN_PROGRESS } from '../base/conference/actionTypes'; -import { - PARTICIPANT_LEFT, - getParticipantById, - getPinnedParticipant, - pinParticipant -} from '../base/participants'; -import { MiddlewareRegistry } from '../base/redux'; -import { updateSettings } from '../base/settings'; -import { setFilmstripVisible } from '../filmstrip'; -import { addStageParticipant } from '../filmstrip/actions.web'; -import { setTileView } from '../video-layout'; +import { PARTICIPANT_LEFT } from '../base/participants/actionTypes'; +import { pinParticipant } from '../base/participants/actions'; +import { getParticipantById, getPinnedParticipant } from '../base/participants/functions'; +import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; +import { updateSettings } from '../base/settings/actions'; +// eslint-disable-next-line lines-around-comment +// @ts-ignore +import { addStageParticipant, setFilmstripVisible } from '../filmstrip/actions'; +import { setTileView } from '../video-layout/actions.any'; import { setFollowMeModerator, @@ -25,8 +22,6 @@ import logger from './logger'; import './subscriber'; -declare var APP: Object; - /** * The timeout after which a follow-me command that has been received will be * ignored if not consumed. @@ -43,7 +38,7 @@ const _FOLLOW_ME_RECEIVED_TIMEOUT = 30; * * @type {TimeoutID} */ -let nextOnStageTimeout; +let nextOnStageTimeout: number; /** * A count of how many seconds the nextOnStageTimeout has ticked while waiting @@ -66,7 +61,7 @@ MiddlewareRegistry.register(store => next => action => { const { conference } = action; conference.addCommandListener( - FOLLOW_ME_COMMAND, ({ attributes }, id) => { + FOLLOW_ME_COMMAND, ({ attributes }: any, id: string) => { _onFollowMeCommand(attributes, id, store); }); break; @@ -94,7 +89,7 @@ MiddlewareRegistry.register(store => next => action => { * @private * @returns {void} */ -function _onFollowMeCommand(attributes = {}, id, store) { +function _onFollowMeCommand(attributes: any = {}, id: string, store: IStore) { const state = store.getState(); // We require to know who issued the command because (1) only a @@ -124,7 +119,7 @@ function _onFollowMeCommand(attributes = {}, id, store) { const { conference } = state['features/base/conference']; // As this participant is not stored in redux store we do the checks on the JitsiParticipant from lib-jitsi-meet - const participant = conference.getParticipantById(id); + const participant = conference?.getParticipantById(id); if (!iAmRecorder || !participant || participant.getRole() !== 'moderator' || !participant.isHiddenFromRecorder()) { @@ -187,7 +182,8 @@ function _onFollowMeCommand(attributes = {}, id, store) { const stageParticipants = JSON.parse(attributes.pinnedStageParticipants); if (!_.isEqual(stageParticipants, oldState.pinnedStageParticipants)) { - stageParticipants.forEach(p => store.dispatch(addStageParticipant(p.participantId, true))); + stageParticipants.forEach((p: { participantId: string; }) => + store.dispatch(addStageParticipant(p.participantId, true))); } } @@ -207,14 +203,14 @@ function _onFollowMeCommand(attributes = {}, id, store) { * @private * @returns {void} */ -function _pinVideoThumbnailById(store, clickId) { +function _pinVideoThumbnailById(store: IStore, clickId: string) { if (getParticipantById(store.getState(), clickId)) { clearTimeout(nextOnStageTimeout); nextOnStageTimer = 0; store.dispatch(pinParticipant(clickId)); } else { - nextOnStageTimeout = setTimeout(() => { + nextOnStageTimeout = window.setTimeout(() => { if (nextOnStageTimer > _FOLLOW_ME_RECEIVED_TIMEOUT) { nextOnStageTimer = 0; diff --git a/react/features/follow-me/subscriber.js b/react/features/follow-me/subscriber.ts similarity index 91% rename from react/features/follow-me/subscriber.js rename to react/features/follow-me/subscriber.ts index 82a4db8ef..71af651da 100644 --- a/react/features/follow-me/subscriber.js +++ b/react/features/follow-me/subscriber.ts @@ -1,11 +1,12 @@ -// @flow - -import { getCurrentConference } from '../base/conference'; +import { IReduxState, IStore } from '../app/types'; +import { getCurrentConference } from '../base/conference/functions'; import { getPinnedParticipant, isLocalParticipantModerator -} from '../base/participants'; -import { StateListenerRegistry } from '../base/redux'; +} from '../base/participants/functions'; +import StateListenerRegistry from '../base/redux/StateListenerRegistry'; +// eslint-disable-next-line lines-around-comment +// @ts-ignore import { getPinnedActiveParticipants, isStageFilmstripEnabled } from '../filmstrip/functions.web'; import { shouldDisplayTileView } from '../video-layout/functions'; @@ -84,14 +85,14 @@ StateListenerRegistry.register( * @param {Object} state - The redux state. * @returns {Object} */ -function _getFollowMeState(state) { +function _getFollowMeState(state: IReduxState) { const pinnedParticipant = getPinnedParticipant(state); const stageFilmstrip = isStageFilmstripEnabled(state); return { filmstripVisible: state['features/filmstrip'].visible, maxStageParticipants: stageFilmstrip ? state['features/base/settings'].maxStageParticipants : undefined, - nextOnStage: stageFilmstrip ? undefined : pinnedParticipant && pinnedParticipant.id, + nextOnStage: stageFilmstrip ? undefined : pinnedParticipant?.id, pinnedStageParticipants: stageFilmstrip ? JSON.stringify(getPinnedActiveParticipants(state)) : undefined, sharedDocumentVisible: state['features/etherpad'].editing, tileViewEnabled: shouldDisplayTileView(state) @@ -107,7 +108,7 @@ function _getFollowMeState(state) { * @returns {void} */ function _sendFollowMeCommand( - newSelectedValue, store) { // eslint-disable-line no-unused-vars + newSelectedValue: any, store: IStore) { const state = store.getState(); const conference = getCurrentConference(state); diff --git a/react/features/shared-video/functions.js b/react/features/shared-video/functions.ts similarity index 89% rename from react/features/shared-video/functions.js rename to react/features/shared-video/functions.ts index efbc7c97d..a41c1ffcc 100644 --- a/react/features/shared-video/functions.js +++ b/react/features/shared-video/functions.ts @@ -1,6 +1,5 @@ -// @flow - -import { getFakeParticipants } from '../base/participants'; +import { IStateful } from '../base/app/types'; +import { getFakeParticipants } from '../base/participants/functions'; import { VIDEO_PLAYER_PARTICIPANT_NAME, YOUTUBE_PLAYER_PARTICIPANT_NAME } from './constants'; @@ -40,10 +39,10 @@ export function isSharingStatus(status: string) { * @param {Object | Function} stateful - The Redux state or a function that gets resolved to the Redux state. * @returns {boolean} */ -export function isVideoPlaying(stateful: Object | Function): boolean { +export function isVideoPlaying(stateful: IStateful): boolean { let videoPlaying = false; - // eslint-disable-next-line no-unused-vars + // eslint-disable-next-line @typescript-eslint/no-unused-vars for (const [ id, p ] of getFakeParticipants(stateful)) { if (p.name === VIDEO_PLAYER_PARTICIPANT_NAME || p.name === YOUTUBE_PLAYER_PARTICIPANT_NAME) { videoPlaying = true; diff --git a/react/features/video-layout/actions.any.js b/react/features/video-layout/actions.any.ts similarity index 92% rename from react/features/video-layout/actions.any.js rename to react/features/video-layout/actions.any.ts index ef645fe27..5e5201085 100644 --- a/react/features/video-layout/actions.any.js +++ b/react/features/video-layout/actions.any.ts @@ -1,6 +1,4 @@ -// @flow - -import type { Dispatch } from 'redux'; +import { IStore } from '../app/types'; import { SCREEN_SHARE_REMOTE_PARTICIPANTS_UPDATED, @@ -54,7 +52,7 @@ export function virtualScreenshareParticipantsUpdated(participantIds: Array, getState: Function) => { + return (dispatch: IStore['dispatch'], getState: IStore['getState']) => { const tileViewActive = shouldDisplayTileView(getState()); dispatch(setTileView(!tileViewActive)); diff --git a/react/features/video-layout/actions.native.js b/react/features/video-layout/actions.native.ts similarity index 100% rename from react/features/video-layout/actions.native.js rename to react/features/video-layout/actions.native.ts diff --git a/react/features/video-layout/actions.web.js b/react/features/video-layout/actions.web.ts similarity index 100% rename from react/features/video-layout/actions.web.js rename to react/features/video-layout/actions.web.ts diff --git a/react/features/video-layout/functions.any.js b/react/features/video-layout/functions.any.ts similarity index 87% rename from react/features/video-layout/functions.any.js rename to react/features/video-layout/functions.any.ts index 5ae950af9..14ece6141 100644 --- a/react/features/video-layout/functions.any.js +++ b/react/features/video-layout/functions.any.ts @@ -1,13 +1,11 @@ -// @flow -import type { Dispatch } from 'redux'; - -import { TILE_VIEW_ENABLED, getFeatureFlag } from '../base/flags'; -import { - getParticipantCount, - getPinnedParticipant, - pinParticipant -} from '../base/participants'; +import { IReduxState, IStore } from '../app/types'; +import { TILE_VIEW_ENABLED } from '../base/flags/constants'; +import { getFeatureFlag } from '../base/flags/functions'; +import { pinParticipant } from '../base/participants/actions'; +import { getParticipantCount, getPinnedParticipant } from '../base/participants/functions'; import { FakeParticipant } from '../base/participants/types'; +// eslint-disable-next-line lines-around-comment +// @ts-ignore import { isStageFilmstripAvailable } from '../filmstrip/functions'; import { isVideoPlaying } from '../shared-video/functions'; import { VIDEO_QUALITY_LEVELS } from '../video-quality/constants'; @@ -16,8 +14,6 @@ import { getMinHeightForQualityLvlMap } from '../video-quality/selector'; import { LAYOUTS } from './constants'; -declare var interfaceConfig: Object; - /** * A selector for retrieving the current automatic pinning setting. * @@ -40,7 +36,7 @@ export function getAutoPinSetting() { * @param {Object} state - The redux state. * @returns {string} */ -export function getCurrentLayout(state: Object) { +export function getCurrentLayout(state: IReduxState) { if (navigator.product === 'ReactNative') { // FIXME: what should this return? return undefined; @@ -65,8 +61,8 @@ export function getCurrentLayout(state: Object) { * @param {Object} state - The redux state. * @returns {boolean} True if tile view should be displayed. */ -export function shouldDisplayTileView(state: Object = {}) { - const { tileViewEnabled } = state['features/video-layout']; +export function shouldDisplayTileView(state: IReduxState) { + const { tileViewEnabled } = state['features/video-layout'] ?? {}; if (tileViewEnabled !== undefined) { // If the user explicitly requested a view mode, we @@ -119,7 +115,7 @@ export function shouldDisplayTileView(state: Object = {}) { * @returns {void} */ export function updateAutoPinnedParticipant( - screenShares: Array, { dispatch, getState }: { dispatch: Dispatch, getState: Function }) { + screenShares: Array, { dispatch, getState }: IStore) { const state = getState(); const remoteScreenShares = state['features/video-layout'].remoteScreenShares; const pinned = getPinnedParticipant(getState); @@ -155,7 +151,7 @@ export function updateAutoPinnedParticipant( * @param {Object} state - The redux state. * @returns {boolean} */ -export function isLayoutTileView(state: Object) { +export function isLayoutTileView(state: IReduxState) { return getCurrentLayout(state) === LAYOUTS.TILE_VIEW; } @@ -189,7 +185,7 @@ function getVideoQualityForHeight(height: number) { * @param {Object} state - Redux state. * @returns {number} */ -export function getVideoQualityForResizableFilmstripThumbnails(height, state) { +export function getVideoQualityForResizableFilmstripThumbnails(height: number, state: IReduxState) { if (!height) { return VIDEO_QUALITY_LEVELS.LOW; } @@ -204,7 +200,7 @@ export function getVideoQualityForResizableFilmstripThumbnails(height, state) { * @param {Object} state - Redux state. * @returns {number} */ -export function getVideoQualityForScreenSharingFilmstrip(height, state) { +export function getVideoQualityForScreenSharingFilmstrip(height: number, state: IReduxState) { if (!height) { return VIDEO_QUALITY_LEVELS.LOW; } @@ -218,7 +214,7 @@ export function getVideoQualityForScreenSharingFilmstrip(height, state) { * @param {number} largeVideoHeight - The height of the large video. * @returns {number} - The video quality for the large video. */ -export function getVideoQualityForLargeVideo(largeVideoHeight) { +export function getVideoQualityForLargeVideo(largeVideoHeight: number) { return getVideoQualityForHeight(largeVideoHeight); } @@ -229,7 +225,7 @@ export function getVideoQualityForLargeVideo(largeVideoHeight) { * @param {Object} state - Redux state. * @returns {number} */ -export function getVideoQualityForStageThumbnails(height, state) { +export function getVideoQualityForStageThumbnails(height: number, state: IReduxState) { if (!height) { return VIDEO_QUALITY_LEVELS.LOW; } diff --git a/react/features/video-layout/functions.native.js b/react/features/video-layout/functions.native.ts similarity index 100% rename from react/features/video-layout/functions.native.js rename to react/features/video-layout/functions.native.ts diff --git a/react/features/video-layout/functions.web.js b/react/features/video-layout/functions.web.ts similarity index 89% rename from react/features/video-layout/functions.web.js rename to react/features/video-layout/functions.web.ts index 349814d07..9703466e6 100644 --- a/react/features/video-layout/functions.web.js +++ b/react/features/video-layout/functions.web.ts @@ -1,3 +1,4 @@ +import { IReduxState } from '../app/types'; import { ABSOLUTE_MAX_COLUMNS, DEFAULT_MAX_COLUMNS, @@ -7,12 +8,12 @@ import { getNumberOfPartipantsForTileView, getThumbnailMinHeight, getTileDefaultAspectRatio -} from '../filmstrip/functions'; + + // @ts-ignore +} from '../filmstrip/functions.web'; export * from './functions.any'; -declare var interfaceConfig: Object; - /** * Returns how many columns should be displayed in tile view. The number * returned will be between 1 and 7, inclusive. @@ -24,7 +25,8 @@ declare var interfaceConfig: Object; * @param {boolean} options.disableTileEnlargement - Custom value to be used instead of config.disableTileEnlargement. * @returns {number} */ -export function getMaxColumnCount(state, options = {}) { +export function getMaxColumnCount(state: IReduxState, options: { + disableResponsiveTiles?: boolean; disableTileEnlargement?: boolean; width?: number; } = {}) { if (typeof interfaceConfig === 'undefined') { return DEFAULT_MAX_COLUMNS; } @@ -69,7 +71,7 @@ export function getMaxColumnCount(state, options = {}) { * @returns {Object} An object is return with the desired number of columns, * rows, and visible rows (the rest should overflow) for the tile view layout. */ -export function getNotResponsiveTileViewGridDimensions(state: Object, stageFilmstrip: boolean = false) { +export function getNotResponsiveTileViewGridDimensions(state: IReduxState, stageFilmstrip = false) { const maxColumns = getMaxColumnCount(state); const { activeParticipants } = state['features/filmstrip']; const numberOfParticipants = stageFilmstrip ? activeParticipants.length : getNumberOfPartipantsForTileView(state); diff --git a/react/features/video-layout/logger.js b/react/features/video-layout/logger.ts similarity index 91% rename from react/features/video-layout/logger.js rename to react/features/video-layout/logger.ts index d03405939..d2f3a8dc4 100644 --- a/react/features/video-layout/logger.js +++ b/react/features/video-layout/logger.ts @@ -1,5 +1,3 @@ -// @flow - import { getLogger } from '../base/logging/functions'; export default getLogger('features/video-layout'); diff --git a/react/features/video-layout/middleware.any.js b/react/features/video-layout/middleware.any.ts similarity index 80% rename from react/features/video-layout/middleware.any.js rename to react/features/video-layout/middleware.any.ts index 416049bbb..288265a92 100644 --- a/react/features/video-layout/middleware.any.js +++ b/react/features/video-layout/middleware.any.ts @@ -1,19 +1,17 @@ -// @flow - -import { getCurrentConference } from '../base/conference'; -import { VIDEO_TYPE } from '../base/media'; -import { - PARTICIPANT_LEFT, - PIN_PARTICIPANT, - getParticipantById, - getPinnedParticipant, - pinParticipant -} from '../base/participants'; -import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux'; -import { TRACK_REMOVED } from '../base/tracks'; -import { SET_DOCUMENT_EDITING_STATUS } from '../etherpad'; +import { IStore } from '../app/types'; +import { getCurrentConference } from '../base/conference/functions'; +import { VIDEO_TYPE } from '../base/media/constants'; +import { PARTICIPANT_LEFT, PIN_PARTICIPANT } from '../base/participants/actionTypes'; +import { pinParticipant } from '../base/participants/actions'; +import { getParticipantById, getPinnedParticipant } from '../base/participants/functions'; +import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; +import StateListenerRegistry from '../base/redux/StateListenerRegistry'; +import { TRACK_REMOVED } from '../base/tracks/actionTypes'; +import { SET_DOCUMENT_EDITING_STATUS } from '../etherpad/actionTypes'; +// eslint-disable-next-line lines-around-comment +// @ts-ignore import { isStageFilmstripEnabled } from '../filmstrip/functions'; -import { isFollowMeActive } from '../follow-me'; +import { isFollowMeActive } from '../follow-me/functions'; import { SET_TILE_VIEW } from './actionTypes'; import { setRemoteParticipantsWithScreenShare, setTileView } from './actions'; @@ -21,7 +19,7 @@ import { getAutoPinSetting, updateAutoPinnedParticipant } from './functions'; import './subscriber'; -let previousTileViewEnabled; +let previousTileViewEnabled: boolean | undefined; /** * Middleware which intercepts actions and updates tile view related state. @@ -88,7 +86,7 @@ MiddlewareRegistry.register(store => next => action => { case TRACK_REMOVED: { const { jitsiTrack } = action.track; - if (jitsiTrack && jitsiTrack.isVideoTrack() && jitsiTrack.getVideoType() === VIDEO_TYPE.DESKTOP) { + if (jitsiTrack?.isVideoTrack() && jitsiTrack?.getVideoType() === VIDEO_TYPE.DESKTOP) { const participantId = jitsiTrack.getParticipantId(); const oldScreenShares = store.getState()['features/video-layout'].remoteScreenShares || []; const newScreenShares = oldScreenShares.filter(id => id !== participantId); @@ -134,7 +132,7 @@ StateListenerRegistry.register( * @param {Object} store - The Redux Store. * @returns {void} */ -function _restoreTileViewState({ dispatch, getState }) { +function _restoreTileViewState({ dispatch, getState }: IStore) { const { tileViewEnabled } = getState()['features/video-layout']; if (tileViewEnabled === undefined && previousTileViewEnabled !== undefined) { @@ -150,7 +148,7 @@ function _restoreTileViewState({ dispatch, getState }) { * @param {Object} store - The Redux Store. * @returns {void} */ -function _storeTileViewStateAndClear({ dispatch, getState }) { +function _storeTileViewStateAndClear({ dispatch, getState }: IStore) { const { tileViewEnabled } = getState()['features/video-layout']; if (tileViewEnabled !== undefined) { diff --git a/react/features/video-layout/middleware.native.js b/react/features/video-layout/middleware.native.ts similarity index 73% rename from react/features/video-layout/middleware.native.js rename to react/features/video-layout/middleware.native.ts index ba2760493..8329a8020 100644 --- a/react/features/video-layout/middleware.native.js +++ b/react/features/video-layout/middleware.native.ts @@ -1,6 +1,9 @@ -import { MEDIA_TYPE, VIDEO_MUTISM_AUTHORITY, setVideoMuted } from '../base/media'; -import { MiddlewareRegistry } from '../base/redux'; -import { CLIENT_RESIZED } from '../base/responsive-ui'; +import { setVideoMuted } from '../base/media/actions'; +import { MEDIA_TYPE, VIDEO_MUTISM_AUTHORITY } from '../base/media/constants'; +import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; +import { CLIENT_RESIZED } from '../base/responsive-ui/actionTypes'; +// eslint-disable-next-line lines-around-comment +// @ts-ignore import { setLargeVideoDimensions } from '../large-video/actions.any'; import { SET_CAR_MODE } from './actionTypes'; diff --git a/react/features/video-layout/middleware.web.js b/react/features/video-layout/middleware.web.ts similarity index 85% rename from react/features/video-layout/middleware.web.js rename to react/features/video-layout/middleware.web.ts index 7862ee3c8..a7919bbf8 100644 --- a/react/features/video-layout/middleware.web.js +++ b/react/features/video-layout/middleware.web.ts @@ -1,15 +1,11 @@ -// @flow - +// @ts-expect-error import VideoLayout from '../../../modules/UI/videolayout/VideoLayout.js'; -import { CONFERENCE_WILL_LEAVE } from '../base/conference'; -import { MEDIA_TYPE } from '../base/media'; -import { - PARTICIPANT_JOINED, - PARTICIPANT_UPDATED, - getLocalParticipant -} from '../base/participants'; -import { MiddlewareRegistry } from '../base/redux'; -import { TRACK_ADDED, TRACK_REMOVED, TRACK_STOPPED } from '../base/tracks'; +import { CONFERENCE_WILL_LEAVE } from '../base/conference/actionTypes'; +import { MEDIA_TYPE } from '../base/media/constants'; +import { PARTICIPANT_JOINED, PARTICIPANT_UPDATED } from '../base/participants/actionTypes'; +import { getLocalParticipant } from '../base/participants/functions'; +import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; +import { TRACK_ADDED, TRACK_REMOVED, TRACK_STOPPED } from '../base/tracks/actionTypes'; import { PARTICIPANTS_PANE_CLOSE, PARTICIPANTS_PANE_OPEN } from '../participants-pane/actionTypes'; import './middleware.any'; diff --git a/react/features/video-layout/subscriber.js b/react/features/video-layout/subscriber.ts similarity index 87% rename from react/features/video-layout/subscriber.js rename to react/features/video-layout/subscriber.ts index 063824ab5..c52cc9813 100644 --- a/react/features/video-layout/subscriber.js +++ b/react/features/video-layout/subscriber.ts @@ -1,13 +1,13 @@ -// @flow - import debounce from 'lodash/debounce'; -import { getMultipleVideoSupportFeatureFlag } from '../base/config'; -import { StateListenerRegistry, equals } from '../base/redux'; -import { isFollowMeActive } from '../follow-me'; +import { getMultipleVideoSupportFeatureFlag } from '../base/config/functions'; +import StateListenerRegistry from '../base/redux/StateListenerRegistry'; +import { equals } from '../base/redux/functions'; +import { ITrack } from '../base/tracks/reducer'; +import { isFollowMeActive } from '../follow-me/functions'; -import { setRemoteParticipantsWithScreenShare, virtualScreenshareParticipantsUpdated } from './actions'; -import { getAutoPinSetting, updateAutoPinnedParticipant } from './functions'; +import { setRemoteParticipantsWithScreenShare, virtualScreenshareParticipantsUpdated } from './actions.web'; +import { getAutoPinSetting, updateAutoPinnedParticipant } from './functions.web'; StateListenerRegistry.register( /* selector */ state => state['features/base/participants'].sortedRemoteVirtualScreenshareParticipants, @@ -60,7 +60,7 @@ StateListenerRegistry.register( } const oldScreenSharesOrder = store.getState()['features/video-layout'].remoteScreenShares || []; - const knownSharingParticipantIds = tracks.reduce((acc, track) => { + const knownSharingParticipantIds = tracks.reduce((acc: string[], track: ITrack) => { if (track.mediaType === 'video' && track.videoType === 'desktop') { const skipTrack = getAutoPinSetting() === 'remote-only' && track.local; @@ -76,11 +76,11 @@ StateListenerRegistry.register( // by looping through the known sharing participants and removing any // participant IDs which are no longer sharing. const newScreenSharesOrder = oldScreenSharesOrder.filter( - participantId => knownSharingParticipantIds.includes(participantId)); + (participantId: string) => knownSharingParticipantIds.includes(participantId)); // Make sure all new sharing participant get added to the end of the // known screen shares. - knownSharingParticipantIds.forEach(participantId => { + knownSharingParticipantIds.forEach((participantId: string) => { if (!newScreenSharesOrder.includes(participantId)) { newScreenSharesOrder.push(participantId); } diff --git a/react/features/video-quality/actions.js b/react/features/video-quality/actions.ts similarity index 97% rename from react/features/video-quality/actions.js rename to react/features/video-quality/actions.ts index 3eda4373e..ec422d6cc 100644 --- a/react/features/video-quality/actions.js +++ b/react/features/video-quality/actions.ts @@ -1,6 +1,4 @@ -// @flow - -import type { Dispatch } from 'redux'; +import { IStore } from '../app/types'; import { SET_MAX_RECEIVER_VIDEO_QUALITY_FOR_LARGE_VIDEO, @@ -125,7 +123,7 @@ export function setPreferredVideoQuality(preferredVideoQuality: number) { * @returns {void} */ export function setVideoQuality(frameHeight: number) { - return (dispatch: Dispatch) => { + return (dispatch: IStore['dispatch']) => { if (frameHeight < VIDEO_QUALITY_LEVELS.LOW) { logger.error(`Invalid frame height for video quality - ${frameHeight}`); diff --git a/react/features/video-quality/functions.js b/react/features/video-quality/functions.ts similarity index 96% rename from react/features/video-quality/functions.js rename to react/features/video-quality/functions.ts index bd321afed..17a2ce18a 100644 --- a/react/features/video-quality/functions.js +++ b/react/features/video-quality/functions.ts @@ -29,7 +29,7 @@ export function getReceiverVideoQualityLevel(availableHeight: number, heightToLe * @returns {Map|undefined} - A mapping of minimal thumbnail height required for given quality level or * {@code undefined} if the map contains invalid values. */ -export function validateMinHeightForQualityLvl(minHeightForQualityLvl) { +export function validateMinHeightForQualityLvl(minHeightForQualityLvl?: { [key: number]: string; }) { if (typeof minHeightForQualityLvl !== 'object' || Object.keys(minHeightForQualityLvl).map(lvl => Number(lvl)) .find(lvl => lvl === null || isNaN(lvl) || lvl < 0)) { @@ -51,7 +51,7 @@ export function validateMinHeightForQualityLvl(minHeightForQualityLvl) { for (const level of levelsSorted) { const configQuality = minHeightForQualityLvl[level]; - const appQuality = CFG_LVL_TO_APP_QUALITY_LVL[configQuality]; + const appQuality = CFG_LVL_TO_APP_QUALITY_LVL[configQuality as keyof typeof CFG_LVL_TO_APP_QUALITY_LVL]; if (!appQuality) { return undefined; diff --git a/react/features/video-quality/middleware.js b/react/features/video-quality/middleware.ts similarity index 85% rename from react/features/video-quality/middleware.js rename to react/features/video-quality/middleware.ts index 60ae11e19..ac20832cb 100644 --- a/react/features/video-quality/middleware.js +++ b/react/features/video-quality/middleware.ts @@ -1,8 +1,6 @@ -// @flow - -import { CONFERENCE_JOINED } from '../base/conference'; -import { SET_CONFIG } from '../base/config'; -import { MiddlewareRegistry } from '../base/redux'; +import { CONFERENCE_JOINED } from '../base/conference/actionTypes'; +import { SET_CONFIG } from '../base/config/actionTypes'; +import MiddlewareRegistry from '../base/redux/MiddlewareRegistry'; import { setPreferredVideoQuality } from './actions'; import logger from './logger'; @@ -24,7 +22,7 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => { const { resolution } = getState()['features/base/config']; if (typeof resolution !== 'undefined') { - dispatch(setPreferredVideoQuality(Number.parseInt(resolution, 10))); + dispatch(setPreferredVideoQuality(Number.parseInt(`${resolution}`, 10))); logger.info(`Configured preferred receiver video frame height to: ${resolution}`); } } diff --git a/react/features/video-quality/selector.js b/react/features/video-quality/selector.ts similarity index 64% rename from react/features/video-quality/selector.js rename to react/features/video-quality/selector.ts index d873092d5..95647acf8 100644 --- a/react/features/video-quality/selector.js +++ b/react/features/video-quality/selector.ts @@ -1,4 +1,4 @@ -// @flow +import { IReduxState } from '../app/types'; /** * Selects the thumbnail height to the quality level mapping from the config. @@ -6,6 +6,6 @@ * @param {Object} state - The redux state. * @returns {Map} */ -export function getMinHeightForQualityLvlMap(state: Object): Map { +export function getMinHeightForQualityLvlMap(state: IReduxState): Map { return state['features/video-quality'].minHeightForQualityLvl; } diff --git a/react/features/video-quality/subscriber.js b/react/features/video-quality/subscriber.ts similarity index 94% rename from react/features/video-quality/subscriber.js rename to react/features/video-quality/subscriber.ts index 2b70029fc..5560f2062 100644 --- a/react/features/video-quality/subscriber.js +++ b/react/features/video-quality/subscriber.ts @@ -1,26 +1,30 @@ -/* global APP */ - import debounce from 'lodash/debounce'; -import { _handleParticipantError } from '../base/conference'; -import { getSourceNameSignalingFeatureFlag } from '../base/config'; -import { MEDIA_TYPE } from '../base/media'; -import { getLocalParticipant } from '../base/participants'; -import { StateListenerRegistry } from '../base/redux'; -import { getRemoteScreenSharesSourceNames, getTrackSourceNameByMediaTypeAndParticipant } from '../base/tracks'; -import { reportError } from '../base/util'; +import { IStore } from '../app/types'; +import { _handleParticipantError } from '../base/conference/functions'; +import { getSourceNameSignalingFeatureFlag } from '../base/config/functions'; +import { MEDIA_TYPE } from '../base/media/constants'; +import { getLocalParticipant } from '../base/participants/functions'; +import StateListenerRegistry from '../base/redux/StateListenerRegistry'; +import { + getRemoteScreenSharesSourceNames, + getTrackSourceNameByMediaTypeAndParticipant +} from '../base/tracks/functions'; +import { reportError } from '../base/util/helpers'; import { getActiveParticipantsIds, getScreenshareFilmstripParticipantId, isTopPanelEnabled + + // @ts-ignore } from '../filmstrip/functions'; +import { LAYOUTS } from '../video-layout/constants'; import { - LAYOUTS, getVideoQualityForLargeVideo, getVideoQualityForResizableFilmstripThumbnails, getVideoQualityForStageThumbnails, shouldDisplayTileView -} from '../video-layout'; +} from '../video-layout/functions'; import { getCurrentLayout, getVideoQualityForScreenSharingFilmstrip } from '../video-layout/functions.any'; import { @@ -301,7 +305,7 @@ StateListenerRegistry.register( * @param {number} preferred - The user preferred max frame height. * @returns {void} */ -function _setSenderVideoConstraint(preferred, { getState }) { +function _setSenderVideoConstraint(preferred: number, { getState }: IStore) { const state = getState(); const { conference } = state['features/base/conference']; @@ -311,7 +315,7 @@ function _setSenderVideoConstraint(preferred, { getState }) { logger.info(`Setting sender resolution to ${preferred}`); conference.setSenderVideoConstraint(preferred) - .catch(error => { + .catch((error: any) => { _handleParticipantError(error); reportError(error, `Changing sender resolution to ${preferred} failed.`); }); @@ -323,7 +327,7 @@ function _setSenderVideoConstraint(preferred, { getState }) { * @param {*} store - The redux store. * @returns {void} */ -function _updateReceiverVideoConstraints({ getState }) { +function _updateReceiverVideoConstraints({ getState }: IStore) { const state = getState(); const { conference } = state['features/base/conference']; @@ -339,7 +343,7 @@ function _updateReceiverVideoConstraints({ getState }) { maxReceiverVideoQualityForScreenSharingFilmstrip, preferredVideoQuality } = state['features/video-quality']; - const { participantId: largeVideoParticipantId } = state['features/large-video']; + const { participantId: largeVideoParticipantId = '' } = state['features/large-video']; const maxFrameHeightForTileView = Math.min(maxReceiverVideoQualityForTileView, preferredVideoQuality); const maxFrameHeightForStageFilmstrip = Math.min(maxReceiverVideoQualityForStageFilmstrip, preferredVideoQuality); const maxFrameHeightForVerticalFilmstrip @@ -352,20 +356,20 @@ function _updateReceiverVideoConstraints({ getState }) { const { visibleRemoteParticipants } = state['features/filmstrip']; const tracks = state['features/base/tracks']; const sourceNameSignaling = getSourceNameSignalingFeatureFlag(state); - const localParticipantId = getLocalParticipant(state).id; + const localParticipantId = getLocalParticipant(state)?.id; const activeParticipantsIds = getActiveParticipantsIds(state); const screenshareFilmstripParticipantId = isTopPanelEnabled(state) && getScreenshareFilmstripParticipantId(state); - const receiverConstraints = { + const receiverConstraints: any = { constraints: {}, defaultConstraints: { 'maxHeight': VIDEO_QUALITY_LEVELS.NONE }, lastN }; - let remoteScreenSharesSourceNames; - let visibleRemoteTrackSourceNames = []; - let largeVideoSourceName; - let activeParticipantsSources = []; + let remoteScreenSharesSourceNames: string[]; + let visibleRemoteTrackSourceNames: string[] = []; + let largeVideoSourceName: string | undefined; + let activeParticipantsSources: string[] = []; if (sourceNameSignaling) { receiverConstraints.onStageSources = []; @@ -390,7 +394,7 @@ function _updateReceiverVideoConstraints({ getState }) { } if (activeParticipantsIds?.length > 0) { - activeParticipantsIds.forEach(participantId => { + activeParticipantsIds.forEach((participantId: string) => { let sourceName; if (remoteScreenSharesSourceNames.includes(participantId)) { @@ -491,7 +495,7 @@ function _updateReceiverVideoConstraints({ getState }) { try { conference.setReceiverConstraints(receiverConstraints); - } catch (error) { + } catch (error: any) { _handleParticipantError(error); reportError(error, `Failed to set receiver video constraints ${JSON.stringify(receiverConstraints)}`); }