ref(TS) Convert some files to TS (#13223)

This commit is contained in:
Robert Pintilii
2023-04-20 12:06:45 +03:00
committed by GitHub
parent 91e9005f08
commit bf1dde7cd1
33 changed files with 225 additions and 185 deletions

View File

@@ -197,6 +197,8 @@
"lint-fix": "eslint --ext .js,.ts,.tsx --max-warnings 0 --fix .",
"postinstall": "patch-package --error-on-fail && jetify",
"validate": "npm ls",
"tsc-test:web": "tsc --project tsconfig.web.json --listFilesOnly | grep -v node_modules | grep native",
"tsc-test:native": "tsc --project tsconfig.native.json --listFilesOnly | grep -v node_modules | grep web",
"start": "make dev"
},
"resolutions": {

View File

@@ -1,6 +1,5 @@
// @flow
import { AnyAction } from 'redux';
import { readyToClose } from '../../../features/mobile/external-api/actions';
import {
ACTION_PINNED,
ACTION_UNPINNED,
@@ -9,8 +8,10 @@ import {
} from '../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../analytics/functions';
import { reloadNow } from '../../app/actions';
import { IReduxState, IStore } from '../../app/types';
import { removeLobbyChatParticipant } from '../../chat/actions.any';
import { openDisplayNamePrompt } from '../../display-name/actions';
import { readyToClose } from '../../mobile/external-api/actions';
import { showErrorNotification, showWarningNotification } from '../../notifications/actions';
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
import { setIAmVisitor } from '../../visitors/actions';
@@ -62,12 +63,10 @@ import {
} from './functions';
import logger from './logger';
declare var APP: Object;
/**
* Handler for before unload event.
*/
let beforeUnloadHandler;
let beforeUnloadHandler: Function | undefined;
/**
* Implements the middleware of the feature base/conference.
@@ -129,7 +128,7 @@ MiddlewareRegistry.register(store => next => action => {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _conferenceFailed({ dispatch, getState }, next, action) {
function _conferenceFailed({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
const { conference, error } = action;
if (error.name === JitsiConferenceErrors.REDIRECTED) {
@@ -191,7 +190,7 @@ function _conferenceFailed({ dispatch, getState }, next, action) {
const newConfig = restoreConferenceOptions(getState);
if (newConfig) {
dispatch(overwriteConfig(newConfig))
dispatch(overwriteConfig(newConfig)) // @ts-ignore
.then(dispatch(conferenceWillLeave(conference)))
.then(conference.leave())
.then(dispatch(disconnect()))
@@ -217,7 +216,7 @@ function _conferenceFailed({ dispatch, getState }, next, action) {
const [ vnode ] = error.params;
dispatch(overwriteConfig(newConfig))
dispatch(overwriteConfig(newConfig)) // @ts-ignore
.then(dispatch(conferenceWillLeave(conference)))
.then(conference.leave())
.then(dispatch(disconnect()))
@@ -234,7 +233,7 @@ function _conferenceFailed({ dispatch, getState }, next, action) {
if (typeof APP === 'undefined') {
!error.recoverable
&& conference
&& conference.leave(CONFERENCE_LEAVE_REASONS.UNRECOVERABLE_ERROR).catch(reason => {
&& conference.leave(CONFERENCE_LEAVE_REASONS.UNRECOVERABLE_ERROR).catch((reason: Error) => {
// Even though we don't care too much about the failure, it may be
// good to know that it happen, so log it (on the info level).
logger.info('JitsiConference.leave() rejected with:', reason);
@@ -267,7 +266,7 @@ function _conferenceFailed({ dispatch, getState }, next, action) {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _conferenceJoined({ dispatch, getState }, next, action) {
function _conferenceJoined({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
const result = next(action);
const { conference } = action;
const { pendingSubjectChange } = getState()['features/base/conference'];
@@ -288,6 +287,8 @@ function _conferenceJoined({ dispatch, getState }, next, action) {
beforeUnloadHandler = () => {
dispatch(conferenceWillLeave(conference));
};
// @ts-ignore
window.addEventListener(disableBeforeUnloadHandlers ? 'unload' : 'beforeunload', beforeUnloadHandler);
if (requireDisplayName
@@ -313,7 +314,7 @@ function _conferenceJoined({ dispatch, getState }, next, action) {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _connectionEstablished({ dispatch }, next, action) {
function _connectionEstablished({ dispatch }: IStore, next: Function, action: AnyAction) {
const result = next(action);
// FIXME: Workaround for the web version. Currently, the creation of the
@@ -330,7 +331,7 @@ function _connectionEstablished({ dispatch }, next, action) {
* @param {Object} state - The redux state.
* @returns {void}
*/
function _logJwtErrors(message, state) {
function _logJwtErrors(message: string, state: IReduxState) {
const { jwt } = state['features/base/jwt'];
if (!jwt) {
@@ -357,7 +358,7 @@ function _logJwtErrors(message, state) {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _connectionFailed({ dispatch, getState }, next, action) {
function _connectionFailed({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
_logJwtErrors(action.error.message, getState());
const result = next(action);
@@ -417,7 +418,7 @@ function _connectionFailed({ dispatch, getState }, next, action) {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _conferenceSubjectChanged({ dispatch, getState }, next, action) {
function _conferenceSubjectChanged({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
const result = next(action);
const { subject } = getState()['features/base/conference'];
@@ -442,7 +443,7 @@ function _conferenceSubjectChanged({ dispatch, getState }, next, action) {
* @param {Object} store - The redux store.
* @returns {void}
*/
function _conferenceWillLeave({ getState }: { getState: Function }) {
function _conferenceWillLeave({ getState }: IStore) {
_removeUnloadHandler(getState);
}
@@ -460,7 +461,7 @@ function _conferenceWillLeave({ getState }: { getState: Function }) {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _pinParticipant({ getState }, next, action) {
function _pinParticipant({ getState }: IStore, next: Function, action: AnyAction) {
const state = getState();
const { conference } = state['features/base/conference'];
@@ -473,7 +474,7 @@ function _pinParticipant({ getState }, next, action) {
const pinnedParticipant = getPinnedParticipant(state);
const actionName = id ? ACTION_PINNED : ACTION_UNPINNED;
const local
= (participantById && participantById.local)
= participantById?.local
|| (!id && pinnedParticipant && pinnedParticipant.local);
let participantIdForEvent;
@@ -481,7 +482,7 @@ function _pinParticipant({ getState }, next, action) {
participantIdForEvent = local;
} else {
participantIdForEvent
= actionName === ACTION_PINNED ? id : pinnedParticipant && pinnedParticipant.id;
= actionName === ACTION_PINNED ? id : pinnedParticipant?.id;
}
sendAnalytics(createPinnedEvent(
@@ -501,10 +502,11 @@ function _pinParticipant({ getState }, next, action) {
* @param {Function} getState - The redux getState function.
* @returns {void}
*/
function _removeUnloadHandler(getState) {
function _removeUnloadHandler(getState: IStore['getState']) {
if (typeof beforeUnloadHandler !== 'undefined') {
const { disableBeforeUnloadHandlers = false } = getState()['features/base/config'];
// @ts-ignore
window.removeEventListener(disableBeforeUnloadHandlers ? 'unload' : 'beforeunload', beforeUnloadHandler);
beforeUnloadHandler = undefined;
}
@@ -522,7 +524,7 @@ function _removeUnloadHandler(getState) {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _sendTones({ getState }, next, action) {
function _sendTones({ getState }: IStore, next: Function, action: AnyAction) {
const state = getState();
const { conference } = state['features/base/conference'];
@@ -549,15 +551,15 @@ function _sendTones({ getState }, next, action) {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _setRoom({ dispatch, getState }, next, action) {
function _setRoom({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
const state = getState();
const { localSubject, subject } = state['features/base/config'];
const { room } = action;
if (room) {
// Set the stored subject.
dispatch(setLocalSubject(localSubject));
dispatch(setSubject(subject));
dispatch(setLocalSubject(localSubject ?? ''));
dispatch(setSubject(subject ?? ''));
}
return next(action);
@@ -572,7 +574,7 @@ function _setRoom({ dispatch, getState }, next, action) {
* @private
* @returns {Promise}
*/
function _syncConferenceLocalTracksWithState({ getState }, action) {
function _syncConferenceLocalTracksWithState({ getState }: IStore, action: AnyAction) {
const conference = getCurrentConference(getState);
let promise;
@@ -603,7 +605,7 @@ function _syncConferenceLocalTracksWithState({ getState }, action) {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _trackAddedOrRemoved(store, next, action) {
function _trackAddedOrRemoved(store: IStore, next: Function, action: AnyAction) {
const track = action.track;
// TODO All track swapping should happen here instead of conference.js.
@@ -628,7 +630,7 @@ function _trackAddedOrRemoved(store, next, action) {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _updateLocalParticipantInConference({ dispatch, getState }, next, action) {
function _updateLocalParticipantInConference({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
const { conference } = getState()['features/base/conference'];
const { participant } = action;
const result = next(action);

View File

@@ -1,4 +1,3 @@
import {
setPrejoinPageVisibility,
setSkipPrejoinOnReload

View File

@@ -60,6 +60,7 @@ export interface IJitsiConference {
getMetadataHandler: Function;
getName: Function;
getParticipantById: Function;
getParticipantCount: Function;
getParticipants: Function;
getRole: Function;
getSpeakerStats: () => ISpeakerStats;
@@ -101,6 +102,7 @@ export interface IJitsiConference {
sendMessage: Function;
sendPrivateTextMessage: Function;
sendTextMessage: Function;
sendTones: Function;
sessionId: string;
setDesktopSharingFrameRate: Function;
setDisplayName: Function;

View File

@@ -7,6 +7,7 @@ import _ from 'lodash';
import { IReduxState } from '../../app/types';
import { browser } from '../lib-jitsi-meet';
import { IMediaState } from '../media/reducer';
import { parseURLParams } from '../util/parseURLParams';
import { IConfig } from './configType';
@@ -65,7 +66,7 @@ export function getMeetingRegion(state: IReduxState) {
* @param {Object} _state - The global state.
* @returns {boolean}
*/
export function getMultipleVideoSendingSupportFeatureFlag(_state: IReduxState) {
export function getMultipleVideoSendingSupportFeatureFlag(_state: IReduxState | IMediaState) {
return browser.supportsUnifiedPlan();
}

View File

@@ -72,7 +72,7 @@ export type ConnectionFailedError = {
* connection: JitsiConnection
* }}
*/
export function connectionDisconnected(connection: Object) {
export function connectionDisconnected(connection?: Object) {
return {
type: CONNECTION_DISCONNECTED,
connection

View File

@@ -1,5 +1,3 @@
// @flow
import { getLogger } from '../logging/functions';
export default getLogger('features/base/jitsi-local-storage');

View File

@@ -1,6 +1,7 @@
// @flow
// @ts-ignore
import Bourne from '@hapi/bourne';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import { jitsiLocalStorage } from '@jitsi/js-utils/jitsi-local-storage';
import { browser } from '../lib-jitsi-meet';
@@ -9,9 +10,6 @@ import { parseURLParams } from '../util/parseURLParams';
import logger from './logger';
declare var APP: Object;
declare var config: Object;
/**
* Handles changes of the fake local storage.
@@ -29,7 +27,7 @@ function onFakeLocalStorageChanged() {
* @returns {boolean} - True if the local storage of the host page needs to be used instead jitsi-meet's local storage
* and false otherwise.
*/
function shouldUseHostPageLocalStorage(urlParams) {
function shouldUseHostPageLocalStorage(urlParams: { 'config.useHostPageLocalStorage'?: boolean; }) {
// NOTE: normally the url params and the config will be merged into the redux store. But we want to setup the local
// storage as soon as possible, the store is not created yet and the merging of the URL params and the config
// haven't been executed yet. That's why we need to manually parse the URL params and also access the config through
@@ -58,6 +56,7 @@ function shouldUseHostPageLocalStorage(urlParams) {
* @returns {void}
*/
function setupJitsiLocalStorage() {
// @ts-ignore
const urlParams = parseURLParams(window.location);
if (shouldUseHostPageLocalStorage(urlParams)) {

View File

@@ -2,5 +2,6 @@
// of) the project jitsi-meet.
//
// @ts-ignore
import JitsiMeetJS from 'lib-jitsi-meet';
export { JitsiMeetJS as default };

View File

@@ -1,5 +0,0 @@
// @flow
declare var JitsiMeetJS: Object;
export default JitsiMeetJS;

View File

@@ -0,0 +1,3 @@
declare let JitsiMeetJS: any;
export default JitsiMeetJS;

View File

@@ -157,7 +157,7 @@ export function setVideoAvailable(available: boolean) {
* @returns {Function}
*/
export function setVideoMuted(
muted: boolean,
muted: boolean | number,
authority: number = VIDEO_MUTISM_AUTHORITY.USER,
ensureTrack = false) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {

View File

@@ -1,4 +1,4 @@
// @flow
import { AnyAction } from 'redux';
import {
createStartAudioOnlyEvent,
@@ -7,6 +7,7 @@ import {
createTrackMutedEvent
} from '../../analytics/AnalyticsEvents';
import { sendAnalytics } from '../../analytics/functions';
import { IStore } from '../../app/types';
import { APP_STATE_CHANGED } from '../../mobile/background/actionTypes';
import { showWarningNotification } from '../../notifications/actions';
import { NOTIFICATION_TIMEOUT_TYPE } from '../../notifications/constants';
@@ -23,6 +24,7 @@ import { getPropertyValue } from '../settings/functions.any';
import { TRACK_ADDED } from '../tracks/actionTypes';
import { destroyLocalTracks } from '../tracks/actions.any';
import { isLocalTrackMuted, isLocalVideoTrackDesktop, setTrackMuted } from '../tracks/functions.any';
import { ITrack } from '../tracks/types';
import {
SET_AUDIO_MUTED,
@@ -155,7 +157,7 @@ MiddlewareRegistry.register(store => next => action => {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _appStateChanged({ dispatch, getState }, next, action) {
function _appStateChanged({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
if (navigator.product === 'ReactNative') {
const { appState } = action;
const mute = appState !== 'active' && !isLocalVideoTrackDesktop(getState());
@@ -180,7 +182,7 @@ function _appStateChanged({ dispatch, getState }, next, action) {
* @private
* @returns {Object} The value returned by {@code next(action)}.
*/
function _setAudioOnly({ dispatch, getState }, next, action) {
function _setAudioOnly({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
const { audioOnly } = action;
const state = getState();
@@ -209,7 +211,7 @@ function _setAudioOnly({ dispatch, getState }, next, action) {
* @returns {Object} The new state that is the result of the reduction of the
* specified {@code action}.
*/
function _setRoom({ dispatch, getState }, next, action) {
function _setRoom({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
// Figure out the desires/intents i.e. the state of base/media. There are
// multiple desires/intents ordered by precedence such as server-side
// config, config overrides in the user-supplied URL, user's own app
@@ -222,7 +224,7 @@ function _setRoom({ dispatch, getState }, next, action) {
const videoMuted = roomIsValid ? getStartWithVideoMuted(state) : _VIDEO_INITIAL_MEDIA_STATE.muted;
sendAnalytics(
createStartMutedConfigurationEvent('local', audioMuted, videoMuted));
createStartMutedConfigurationEvent('local', audioMuted, Boolean(videoMuted)));
logger.log(
`Start muted: ${audioMuted ? 'audio, ' : ''}${
videoMuted ? 'video' : ''}`);
@@ -295,7 +297,7 @@ function _setRoom({ dispatch, getState }, next, action) {
* @private
* @returns {void}
*/
function _syncTrackMutedState({ getState }, track) {
function _syncTrackMutedState({ getState }: IStore, track: ITrack) {
const state = getState()['features/base/media'];
const mediaType = track.mediaType;
const muted = Boolean(state[mediaType].muted);

View File

@@ -1 +1 @@
import './middleware.any.js';
import './middleware.any';

View File

@@ -1,4 +1,4 @@
import './middleware.any.js';
import './middleware.any';
import { IStore } from '../../app/types';
import { showNotification } from '../../notifications/actions';

View File

@@ -4,6 +4,7 @@ import {
} from '../config/functions.any';
import { JitsiTrackErrors, browser } from '../lib-jitsi-meet';
import { MEDIA_TYPE, MediaType, VIDEO_TYPE } from '../media/constants';
import { IMediaState } from '../media/reducer';
import {
getVirtualScreenshareParticipantOwnerId,
isScreenShareParticipant
@@ -359,7 +360,7 @@ export function isUserInteractionRequiredForUnmute(state: IReduxState) {
* @param {Object} state - The redux state.
* @returns {Promise}
*/
export function setTrackMuted(track: any, muted: boolean, state: IReduxState) {
export function setTrackMuted(track: any, muted: boolean, state: IReduxState | IMediaState) {
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

View File

@@ -283,6 +283,7 @@ export function updateProfile(calendarType: string) {
return Promise.reject('No integration found');
}
// @ts-ignore
return dispatch(integration.getCurrentEmail())
.then((email: string) => {
dispatch(setCalendarProfileEmail(email));

View File

@@ -1,6 +1,6 @@
import { ColorPalette } from '../../base/styles/components/styles/ColorPalette';
import { createStyleSheet } from '../../base/styles/functions.any';
import BaseTheme from '../../base/ui/components/BaseTheme.native';
import BaseTheme from '../../base/ui/components/BaseTheme';
const NOTIFICATION_SIZE = 55;

View File

@@ -39,7 +39,7 @@ export interface ICalendarSyncState {
integrationReady: boolean;
integrationType?: string;
isLoadingEvents?: boolean;
msAuthState?: Object;
msAuthState?: any;
profileEmail?: string;
}

View File

@@ -1,14 +1,11 @@
// @flow
import type { Dispatch } from 'redux';
import { IStore } from '../../app/types';
import {
getCalendarEntries,
loadGoogleAPI,
signIn,
updateCalendarEvent,
updateProfile
} from '../../google-api/actions';
} from '../../google-api/actions'; // @ts-ignore
import googleApi from '../../google-api/googleApi.web';
/**
@@ -43,7 +40,7 @@ export const googleCalendarApi = {
* @returns {function(Dispatch<any>, Function): Promise<void>}
*/
load() {
return (dispatch: Dispatch<any>) => dispatch(loadGoogleAPI());
return (dispatch: IStore['dispatch']) => dispatch(loadGoogleAPI());
},
/**

View File

@@ -1,16 +1,18 @@
// @flow
import { Client } from '@microsoft/microsoft-graph-client';
// eslint-disable-next-line lines-around-comment
// @ts-ignore
import base64js from 'base64-js';
import type { Dispatch } from 'redux';
import { v4 as uuidV4 } from 'uuid';
import { findWindows } from 'windows-iana';
import { IanaName } from 'windows-iana/dist/enums';
// @ts-expect-error
import { createDeferred } from '../../../../modules/util/helpers';
import { IStore } from '../../app/types';
import { parseURLParams } from '../../base/util/parseURLParams';
import { parseStandardURIString } from '../../base/util/uri';
import { getShareInfoText } from '../../invite/functions';
import { setCalendarAPIAuthState } from '../actions';
import { setCalendarAPIAuthState } from '../actions.web';
/**
@@ -63,7 +65,7 @@ const MS_API_CONFIGURATION = {
* @private
* @type {Object|null}
*/
let popupAuthWindow = null;
let popupAuthWindow: Window | null = null;
/**
* A stateless collection of action creators that implements the expected
@@ -81,10 +83,10 @@ export const microsoftCalendarApi = {
* @param {number} fetchEndDays - The number of days to fetch.
* @returns {function(Dispatch<any>, Function): Promise<CalendarEntries>}
*/
getCalendarEntries(fetchStartDays: ?number, fetchEndDays: ?number) {
return (dispatch: Dispatch<any>, getState: Function): Promise<*> => {
getCalendarEntries(fetchStartDays?: number, fetchEndDays?: number) {
return (dispatch: IStore['dispatch'], getState: IStore['getState']): Promise<any> => {
const state = getState()['features/calendar-sync'] || {};
const token = state.msAuthState && state.msAuthState.accessToken;
const token = state.msAuthState?.accessToken;
if (!token) {
return Promise.reject('Not authorized, please sign in!');
@@ -98,8 +100,8 @@ export const microsoftCalendarApi = {
.api(MS_API_CONFIGURATION.CALENDAR_ENDPOINT)
.get()
.then(response => {
const calendarIds = response.value.map(en => en.id);
const getEventsPromises = calendarIds.map(id =>
const calendarIds = response.value.map((en: any) => en.id);
const getEventsPromises = calendarIds.map((id: string) =>
requestCalendarEvents(
client, id, fetchStartDays, fetchEndDays));
@@ -120,7 +122,7 @@ export const microsoftCalendarApi = {
* @returns {function(Dispatch<*, Function>): Promise<string>}
*/
getCurrentEmail(): Function {
return (dispatch: Dispatch<any>, getState: Function) => {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
const { msAuthState = {} }
= getState()['features/calendar-sync'] || {};
const email = msAuthState.userSigninName || '';
@@ -134,7 +136,7 @@ export const microsoftCalendarApi = {
*
* @returns {function(): Promise<void>}
*/
load(): Function {
load() {
return () => Promise.resolve();
},
@@ -143,8 +145,8 @@ export const microsoftCalendarApi = {
*
* @returns {function(Dispatch<any>, Function): Promise<void>}
*/
signIn(): Function {
return (dispatch: Dispatch<any>, getState: Function) => {
signIn() {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
// Ensure only one popup window at a time.
if (popupAuthWindow) {
popupAuthWindow.focus();
@@ -164,7 +166,7 @@ export const microsoftCalendarApi = {
const { microsoftApiApplicationClientID }
= getState()['features/base/config'];
const authUrl = getAuthUrl(
microsoftApiApplicationClientID,
microsoftApiApplicationClientID ?? '',
guids.authState,
guids.authNonce);
const h = 600;
@@ -178,7 +180,7 @@ export const microsoftCalendarApi = {
(screen.width / 2) - (w / 2)}`);
const windowCloseCheck = setInterval(() => {
if (popupAuthWindow && popupAuthWindow.closed) {
if (popupAuthWindow?.closed) {
signInDeferred.reject(
'Popup closed before completing auth.');
popupAuthWindow = null;
@@ -199,19 +201,19 @@ export const microsoftCalendarApi = {
* @private
* @returns {void}
*/
function handleAuth({ data }) {
function handleAuth({ data }: any) {
if (!data || data.type !== 'ms-login') {
return;
}
window.removeEventListener('message', handleAuth);
popupAuthWindow && popupAuthWindow.close();
popupAuthWindow?.close();
popupAuthWindow = null;
const params = getParamsFromHash(data.url);
const tokenParts = getValidatedTokenParts(
params, guids, microsoftApiApplicationClientID);
params, guids, microsoftApiApplicationClientID ?? '');
if (!tokenParts) {
signInDeferred.reject('Invalid token received');
@@ -242,8 +244,8 @@ export const microsoftCalendarApi = {
*
* @returns {function(Dispatch<any>, Function): Promise<boolean>}
*/
_isSignedIn(): Function {
return (dispatch: Dispatch<any>, getState: Function) => {
_isSignedIn() {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
const now = new Date().getTime();
const state
= getState()['features/calendar-sync'].msAuthState || {};
@@ -271,9 +273,9 @@ export const microsoftCalendarApi = {
* @returns {function(Dispatch<any>): Promise<string|never>}
*/
updateCalendarEvent(id: string, calendarId: string, location: string) {
return (dispatch: Dispatch<any>, getState: Function): Promise<*> => {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
const state = getState()['features/calendar-sync'] || {};
const token = state.msAuthState && state.msAuthState.accessToken;
const token = state.msAuthState?.accessToken;
if (!token) {
return Promise.reject('Not authorized, please sign in!');
@@ -329,7 +331,7 @@ export const microsoftCalendarApi = {
* title: string
* }}
*/
function formatCalendarEntry(entry) {
function formatCalendarEntry(entry: any) {
return {
calendarId: entry.calendarId,
description: entry.body.content,
@@ -352,7 +354,7 @@ function formatCalendarEntry(entry) {
* @private
* @returns {string} - The auth URL.
*/
function getAuthRefreshUrl(appId, userDomainType, userSigninName) {
function getAuthRefreshUrl(appId: string, userDomainType: string, userSigninName: string) {
return [
getAuthUrl(appId, 'undefined', 'undefined'),
'prompt=none',
@@ -370,7 +372,7 @@ function getAuthRefreshUrl(appId, userDomainType, userSigninName) {
* @private
* @returns {string} - The auth URL.
*/
function getAuthUrl(appId, authState, authNonce) {
function getAuthUrl(appId: string, authState: string, authNonce: string) {
const authParams = [
'response_type=id_token+token',
`client_id=${appId}`,
@@ -392,7 +394,8 @@ function getAuthUrl(appId, authState, authNonce) {
* @private
* @returns {Object}
*/
function getParamsFromHash(url) {
function getParamsFromHash(url: string) {
// @ts-ignore
const params = parseURLParams(parseStandardURIString(url), true, 'hash');
// Get the number of seconds the token is valid for, subtract 5 minutes
@@ -418,7 +421,7 @@ function getParamsFromHash(url) {
* @private
* @returns {Object|null}
*/
function getValidatedTokenParts(tokenInfo, guids, appId) {
function getValidatedTokenParts(tokenInfo: any, guids: any, appId: string) {
// Make sure the token matches the request source by matching the GUID.
if (tokenInfo.state !== guids.authState) {
return null;
@@ -479,15 +482,15 @@ function getValidatedTokenParts(tokenInfo, guids, appId) {
* @private
* @returns {function(Dispatch<any>, Function): Promise<void>}
*/
function refreshAuthToken(): Function {
return (dispatch: Dispatch<any>, getState: Function) => {
function refreshAuthToken() {
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
const { microsoftApiApplicationClientID }
= getState()['features/base/config'];
const { msAuthState = {} }
= getState()['features/calendar-sync'] || {};
const refreshAuthUrl = getAuthRefreshUrl(
microsoftApiApplicationClientID,
microsoftApiApplicationClientID ?? '',
msAuthState.userDomainType,
msAuthState.userSigninName);
@@ -500,7 +503,7 @@ function refreshAuthToken(): Function {
const signInPromise = new Promise(resolve => {
iframe.onload = () => {
resolve(iframe.contentWindow.location.hash);
resolve(iframe.contentWindow?.location.hash);
};
});
@@ -514,7 +517,7 @@ function refreshAuthToken(): Function {
document.body.appendChild(iframe);
return signInPromise.then(hash => {
const params = getParamsFromHash(hash);
const params = getParamsFromHash(hash as string);
dispatch(setCalendarAPIAuthState({
accessToken: params.access_token,
@@ -537,22 +540,22 @@ function refreshAuthToken(): Function {
* @private
*/
function requestCalendarEvents( // eslint-disable-line max-params
client,
calendarId,
fetchStartDays,
fetchEndDays): Promise<*> {
client: any,
calendarId: string,
fetchStartDays?: number,
fetchEndDays?: number): Promise<any> {
const startDate = new Date();
const endDate = new Date();
startDate.setDate(startDate.getDate() + fetchStartDays);
endDate.setDate(endDate.getDate() + fetchEndDays);
startDate.setDate(startDate.getDate() + Number(fetchStartDays));
endDate.setDate(endDate.getDate() + Number(fetchEndDays));
const filter = `Start/DateTime ge '${
startDate.toISOString()}' and End/DateTime lt '${
endDate.toISOString()}'`;
const ianaTimeZone = new Intl.DateTimeFormat().resolvedOptions().timeZone;
const windowsTimeZone = findWindows(ianaTimeZone);
const windowsTimeZone = findWindows(ianaTimeZone as IanaName);
return client
.api(`/me/calendars/${calendarId}/events`)
@@ -561,7 +564,7 @@ function requestCalendarEvents( // eslint-disable-line max-params
.select('id,subject,start,end,location,body')
.orderby('createdDateTime DESC')
.get()
.then(result => result.value.map(item => {
.then((result: any) => result.value.map((item: Object) => {
return {
...item,
calendarId
@@ -576,7 +579,7 @@ function requestCalendarEvents( // eslint-disable-line max-params
* @private
* @returns {string} - The converted string.
*/
function b64utoutf8(str) {
function b64utoutf8(str: string) {
let s = str;
// Convert from Base64URL to Base64.
@@ -595,7 +598,7 @@ function b64utoutf8(str) {
// Convert bytes to hex.
s = bytes.reduce((str_, byte) => str_ + byte.toString(16).padStart(2, '0'), '');
s = bytes.reduce((str_: any, byte: any) => str_ + byte.toString(16).padStart(2, '0'), '');
// Convert a hexadecimal string to a URLComponent string

View File

@@ -1,5 +1,3 @@
// @flow
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { OPEN_DESKTOP_APP } from './actionTypes';

View File

@@ -9,12 +9,12 @@ import {
getParticipantPresenceStatus,
getRemoteParticipants
} from '../../../base/participants/functions';
import { Container, Text } from '../../../base/react/components/index.web';
import { Container, Text } from '../../../base/react/components/index';
import { isLocalTrackMuted } from '../../../base/tracks/functions.any';
import PresenceLabel from '../../../presence-status/components/PresenceLabel';
import { CALLING } from '../../../presence-status/constants';
import styles from './styles.web';
import styles from './styles';
/**
* The type of the React {@code Component} props of {@link CalleeInfo}.

View File

@@ -1,8 +1,7 @@
// @flow
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { IReduxState } from '../../app/types';
import { shouldDisplayTileView } from '../../video-layout/functions.web';
/**
@@ -22,7 +21,7 @@ export const ORIENTATION = {
* The type of the React {@code Component} props of
* {@link LargeVideoBackgroundCanvas}.
*/
type Props = {
interface IProps {
/**
* Whether or not the layout should change to support tile view mode.
@@ -30,35 +29,35 @@ type Props = {
* @protected
* @type {boolean}
*/
_shouldDisplayTileView: boolean,
_shouldDisplayTileView: boolean;
/**
* Additional CSS class names to add to the root of the component.
*/
className: String,
className: String;
/**
* Whether or not the background should have its visibility hidden.
*/
hidden: boolean,
hidden: boolean;
/**
* Whether or not the video should display flipped horizontally, so left
* becomes right and right becomes left.
*/
mirror: boolean,
mirror: boolean;
/**
* Whether the component should ensure full width of the video is displayed
* (landscape) or full height (portrait).
*/
orientationFit: string,
orientationFit: string;
/**
* The video stream to display.
*/
videoElement: Object
};
videoElement: HTMLVideoElement;
}
/**
@@ -67,10 +66,10 @@ type Props = {
*
* @augments Component
*/
export class LargeVideoBackground extends Component<Props> {
_canvasEl: Object;
export class LargeVideoBackground extends Component<IProps> {
_canvasEl: HTMLCanvasElement;
_updateCanvasInterval: *;
_updateCanvasInterval: number | undefined;
/**
* Initializes new {@code LargeVideoBackground} instance.
@@ -78,7 +77,7 @@ export class LargeVideoBackground extends Component<Props> {
* @param {*} props - The read-only properties with which the new instance
* is to be initialized.
*/
constructor(props: Props) {
constructor(props: IProps) {
super(props);
// Bind event handlers so they are only bound once per instance.
@@ -107,7 +106,7 @@ export class LargeVideoBackground extends Component<Props> {
*
* @inheritdoc
*/
componentDidUpdate(prevProps: Props) {
componentDidUpdate(prevProps: IProps) {
const wasCanvasUpdating = !prevProps.hidden && !prevProps._shouldDisplayTileView && prevProps.videoElement;
const shouldCanvasUpdating
= !this.props.hidden && !this.props._shouldDisplayTileView && this.props.videoElement;
@@ -163,7 +162,7 @@ export class LargeVideoBackground extends Component<Props> {
_clearCanvas() {
const cavnasContext = this._canvasEl.getContext('2d');
cavnasContext.clearRect(
cavnasContext?.clearRect(
0, 0, this._canvasEl.width, this._canvasEl.height);
}
@@ -177,8 +176,6 @@ export class LargeVideoBackground extends Component<Props> {
clearInterval(this._updateCanvasInterval);
}
_setCanvasEl: () => void;
/**
* Sets the instance variable for the component's canvas element so it can
* be accessed directly for drawing on.
@@ -187,7 +184,7 @@ export class LargeVideoBackground extends Component<Props> {
* @private
* @returns {void}
*/
_setCanvasEl(element) {
_setCanvasEl(element: HTMLCanvasElement) {
this._canvasEl = element;
}
@@ -199,11 +196,9 @@ export class LargeVideoBackground extends Component<Props> {
*/
_setUpdateCanvasInterval() {
this._clearUpdateCanvasInterval();
this._updateCanvasInterval = setInterval(this._updateCanvas, 200);
this._updateCanvasInterval = window.setInterval(this._updateCanvas, 200);
}
_updateCanvas: () => void;
/**
* Draws the current frame of the passed in video element onto the canvas.
*
@@ -235,13 +230,13 @@ export class LargeVideoBackground extends Component<Props> {
if (this.props.orientationFit === ORIENTATION.LANDSCAPE) {
const heightScaledToFit = (canvasWidth / videoWidth) * videoHeight;
canvasContext.drawImage(
videoElement, 0, 0, canvasWidth, heightScaledToFit);
canvasContext?.drawImage(
videoElement as any, 0, 0, canvasWidth, heightScaledToFit);
} else {
const widthScaledToFit = (canvasHeight / videoHeight) * videoWidth;
canvasContext.drawImage(
videoElement, 0, 0, widthScaledToFit, canvasHeight);
canvasContext?.drawImage(
videoElement as any, 0, 0, widthScaledToFit, canvasHeight);
}
}
}
@@ -255,7 +250,7 @@ export class LargeVideoBackground extends Component<Props> {
* _shouldDisplayTileView: boolean
* }}
*/
function _mapStateToProps(state) {
function _mapStateToProps(state: IReduxState) {
return {
_shouldDisplayTileView: shouldDisplayTileView(state)
};

View File

@@ -7,6 +7,7 @@ import { createSharedVideoEvent as createEvent } from '../../../analytics/Analyt
import { sendAnalytics } from '../../../analytics/functions';
import { IReduxState } from '../../../app/types';
import { getCurrentConference } from '../../../base/conference/functions';
import { IJitsiConference } from '../../../base/conference/reducer';
import { MEDIA_TYPE } from '../../../base/media/constants';
import { getLocalParticipant } from '../../../base/participants/functions';
import { isLocalTrackMuted } from '../../../base/tracks/functions';
@@ -39,7 +40,7 @@ export interface IProps {
/**
* The current conference.
*/
_conference: Object;
_conference?: IJitsiConference;
/**
* Warning that indicates an incorrect video url.
@@ -71,12 +72,12 @@ export interface IProps {
/**
* Store flag for muted state.
*/
_muted: boolean;
_muted?: boolean;
/**
* The shared video owner id.
*/
_ownerId: string;
_ownerId?: string;
/**
* Updates the shared video status.
@@ -86,7 +87,7 @@ export interface IProps {
/**
* The shared video status.
*/
_status: string;
_status?: string;
/**
* Action to stop video sharing.
@@ -97,12 +98,12 @@ export interface IProps {
* Seek time in seconds.
*
*/
_time: number;
_time?: number;
/**
* The video url.
*/
_videoUrl: string;
_videoUrl?: string;
/**
* The video id.
@@ -185,8 +186,8 @@ class AbstractVideoManager extends PureComponent<IProps> {
const playerTime = this.getTime();
if (shouldSeekToPosition(_time, playerTime)) {
this.seek(_time);
if (shouldSeekToPosition(Number(_time), Number(playerTime))) {
this.seek(Number(_time));
}
if (this.getPlaybackStatus() !== _status) {
@@ -214,7 +215,7 @@ class AbstractVideoManager extends PureComponent<IProps> {
* @param {Object|undefined} e - The error returned by the API or none.
* @returns {void}
*/
onError(e: any) {
onError(e?: any) {
logger.error('Error in the video player', e?.data,
e?.data ? 'Check error code at https://developers.google.com/youtube/iframe_api_reference#onError' : '');
this.props._stopSharedVideo();
@@ -251,7 +252,7 @@ class AbstractVideoManager extends PureComponent<IProps> {
const volume = this.getVolume();
const muted = this.isMuted();
if (volume > 0 && !muted) {
if (Number(volume) > 0 && !muted) {
this.smartAudioMute();
}
@@ -290,7 +291,7 @@ class AbstractVideoManager extends PureComponent<IProps> {
const status = this.getPlaybackStatus();
if (!Object.values(PLAYBACK_STATUSES).includes(status)) {
if (!Object.values(PLAYBACK_STATUSES).includes(status ?? '')) {
return;
}
@@ -320,7 +321,7 @@ class AbstractVideoManager extends PureComponent<IProps> {
isSharedVideoVolumeOn() {
return this.getPlaybackStatus() === PLAYBACK_STATUSES.PLAYING
&& !this.isMuted()
&& this.getVolume() > 0;
&& Number(this.getVolume()) > 0;
}
/**
@@ -342,54 +343,93 @@ class AbstractVideoManager extends PureComponent<IProps> {
/**
* Seeks video to provided time.
*
* @param {number} time
* @param {number} _time - Time to seek to.
* @returns {void}
*/
seek: (time: number) => void;
seek(_time: number) {
// to be implemented by subclass
}
/**
* Indicates the playback state of the video.
*
* @returns {string}
*/
getPlaybackStatus: () => string;
getPlaybackStatus(): string | undefined {
return;
}
/**
* Indicates whether the video is muted.
*
* @returns {boolean}
*/
isMuted: () => boolean;
isMuted(): boolean | undefined {
return;
}
/**
* Retrieves current volume.
*
* @returns {number}
*/
getVolume: () => number;
getVolume() {
return 1;
}
/**
* Plays video.
*
* @returns {void}
*/
play: () => void;
play() {
// to be implemented by subclass
}
/**
* Pauses video.
*
* @returns {void}
*/
pause: () => void;
pause() {
// to be implemented by subclass
}
/**
* Mutes video.
*
* @returns {void}
*/
mute: () => void;
mute() {
// to be implemented by subclass
}
/**
* Unmutes video.
*
* @returns {void}
*/
unMute: () => void;
unMute() {
// to be implemented by subclass
}
/**
* Retrieves current time.
*
* @returns {number}
*/
getTime: () => number;
getTime() {
return 0;
}
/**
* Disposes current video player.
*
* @returns {void}
*/
dispose: () => void;
dispose() {
// to be implemented by subclass
}
}

View File

@@ -4,7 +4,7 @@ import { connect } from 'react-redux';
import { PLAYBACK_STATUSES } from '../../constants';
import AbstractVideoManager, {
Props,
IProps,
_mapDispatchToProps,
_mapStateToProps
} from './AbstractVideoManager';
@@ -13,7 +13,9 @@ import AbstractVideoManager, {
/**
* Manager of shared video.
*/
class VideoManager extends AbstractVideoManager<Props> {
class VideoManager extends AbstractVideoManager {
playerRef: React.RefObject<HTMLVideoElement>;
/**
* Initializes a new VideoManager instance.
*
@@ -21,7 +23,7 @@ class VideoManager extends AbstractVideoManager<Props> {
*
* @returns {void}
*/
constructor(props) {
constructor(props: IProps) {
super(props);
this.playerRef = React.createRef();
@@ -70,7 +72,7 @@ class VideoManager extends AbstractVideoManager<Props> {
* @returns {number}
*/
getVolume() {
return this.player?.volume;
return Number(this.player?.volume);
}
/**
@@ -79,7 +81,7 @@ class VideoManager extends AbstractVideoManager<Props> {
* @returns {number}
*/
getTime() {
return this.player?.currentTime;
return Number(this.player?.currentTime);
}
/**
@@ -89,7 +91,7 @@ class VideoManager extends AbstractVideoManager<Props> {
*
* @returns {void}
*/
seek(time) {
seek(time: number) {
if (this.player) {
this.player.currentTime = time;
}
@@ -143,7 +145,7 @@ class VideoManager extends AbstractVideoManager<Props> {
getPlayerOptions() {
const { _isOwner, videoId } = this.props;
let options = {
let options: any = {
autoPlay: true,
src: videoId,
controls: _isOwner,

View File

@@ -6,6 +6,7 @@ import YouTube from 'react-youtube';
import { PLAYBACK_STATUSES } from '../../constants';
import AbstractVideoManager, {
IProps,
_mapDispatchToProps,
_mapStateToProps
} from './AbstractVideoManager';
@@ -16,6 +17,9 @@ import AbstractVideoManager, {
* @returns {void}
*/
class YoutubeVideoManager extends AbstractVideoManager {
isPlayerAPILoaded: boolean;
player?: any;
/**
* Initializes a new YoutubeVideoManager instance.
*
@@ -23,7 +27,7 @@ class YoutubeVideoManager extends AbstractVideoManager {
*
* @returns {void}
*/
constructor(props) {
constructor(props: IProps) {
super(props);
this.isPlayerAPILoaded = false;
@@ -88,7 +92,7 @@ class YoutubeVideoManager extends AbstractVideoManager {
*
* @returns {void}
*/
seek(time) {
seek(time: number) {
return this.player?.seekTo(time);
}
@@ -147,7 +151,7 @@ class YoutubeVideoManager extends AbstractVideoManager {
*
* @returns {void}
*/
onPlayerStateChange = event => {
onPlayerStateChange = (event: any) => {
if (event.data === YouTube.PlayerState.PLAYING) {
this.onPlay();
} else if (event.data === YouTube.PlayerState.PAUSED) {
@@ -162,7 +166,7 @@ class YoutubeVideoManager extends AbstractVideoManager {
*
* @returns {void}
*/
onPlayerReady = event => {
onPlayerReady = (event: any) => {
const { _isOwner } = this.props;
this.player = event.target;
@@ -201,7 +205,7 @@ class YoutubeVideoManager extends AbstractVideoManager {
'rel': 0
}
},
onError: e => this.onError(e),
onError: (e: any) => this.onError(e),
onReady: this.onPlayerReady,
onStateChange: this.onPlayerStateChange,
videoId

View File

@@ -1,5 +1,3 @@
// @flow
import JitsiMeetJS from '../../base/lib-jitsi-meet';
import { MEDIA_TYPE } from '../../base/media/constants';
@@ -12,12 +10,12 @@ export class AudioMixerEffect {
/**
* JitsiLocalTrack that is going to be mixed into the track that uses this effect.
*/
_mixAudio: Object;
_mixAudio: any;
/**
* MediaStream resulted from mixing.
*/
_mixedMediaStream: Object;
_mixedMediaStream: any;
/**
* MediaStreamTrack obtained from mixed stream.
@@ -32,19 +30,19 @@ export class AudioMixerEffect {
/**
* MediaStreamTrack obtained from the original MediaStream.
*/
_originalTrack: Object;
_originalTrack: any;
/**
* Lib-jitsi-meet AudioMixer.
*/
_audioMixer: Object;
_audioMixer: any;
/**
* Creates AudioMixerEffect.
*
* @param {JitsiLocalTrack} mixAudio - JitsiLocalTrack which will be mixed with the original track.
*/
constructor(mixAudio: Object) {
constructor(mixAudio: any) {
if (mixAudio.getType() !== MEDIA_TYPE.AUDIO) {
throw new Error('AudioMixerEffect only supports audio JitsiLocalTracks; effect will not work!');
}
@@ -58,7 +56,7 @@ export class AudioMixerEffect {
* @param {JitsiLocalTrack} sourceLocalTrack - Track to which the effect will be applied.
* @returns {boolean} - Returns true if this effect can run on the specified track, false otherwise.
*/
isEnabled(sourceLocalTrack: Object) {
isEnabled(sourceLocalTrack: any) {
// Both JitsiLocalTracks need to be audio i.e. contain an audio MediaStreamTrack
return sourceLocalTrack.isAudioTrack() && this._mixAudio.isAudioTrack();
}

View File

@@ -1,7 +1,6 @@
// @flow
// Script expects to find rnnoise webassembly binary in the same public path root, otherwise it won't load
// During the build phase this needs to be taken care of manually
// @ts-ignore
import { createRNNWasmModule } from '@jitsi/rnnoise-wasm';
import RnnoiseProcessor from './RnnoiseProcessor';
@@ -9,7 +8,7 @@ import RnnoiseProcessor from './RnnoiseProcessor';
export { RNNOISE_SAMPLE_LENGTH } from './RnnoiseProcessor';
export type { RnnoiseProcessor };
let rnnoiseModule;
let rnnoiseModule: Promise<any> | undefined;
/**
* Creates a new instance of RnnoiseProcessor.
@@ -21,5 +20,5 @@ export function createRnnoiseProcessor() {
rnnoiseModule = createRNNWasmModule();
}
return rnnoiseModule.then(mod => new RnnoiseProcessor(mod));
return rnnoiseModule?.then(mod => new RnnoiseProcessor(mod));
}

View File

@@ -29,7 +29,7 @@ import {
AbstractWelcomePage,
_mapStateToProps as _abstractMapStateToProps
} from './AbstractWelcomePage';
import styles from './styles';
import styles from './styles.native';
interface IProps extends AbstractProps {

View File

@@ -31,9 +31,7 @@
"react/features/remote-control",
"react/features/screen-share",
"react/features/screenshot-capture",
"react/features/stream-effects/noise-suppression",
"react/features/stream-effects/rnnoise",
"react/features/stream-effects/virtual-background",
"react/features/stream-effects",
"react/features/virtual-background",
"react/features/web-hid",
"react/features/whiteboard",