ref(TS) Convert some base features to TS (#12138)
This commit is contained in:
parent
5502601fb3
commit
95084e1004
|
@ -121,7 +121,7 @@
|
|||
"react-window": "1.8.6",
|
||||
"react-youtube": "7.13.1",
|
||||
"redux": "4.0.4",
|
||||
"redux-thunk": "2.2.0",
|
||||
"redux-thunk": "2.4.1",
|
||||
"resemblejs": "4.0.0",
|
||||
"seamless-scroll-polyfill": "2.1.8",
|
||||
"styled-components": "3.4.9",
|
||||
|
@ -16941,9 +16941,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/redux-thunk": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.2.0.tgz",
|
||||
"integrity": "sha1-5hWhbha0ehmlFXZhM9Hj6Zt4UuU="
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
|
||||
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==",
|
||||
"peerDependencies": {
|
||||
"redux": "^4"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerate": {
|
||||
"version": "1.4.2",
|
||||
|
@ -33153,9 +33156,9 @@
|
|||
}
|
||||
},
|
||||
"redux-thunk": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.2.0.tgz",
|
||||
"integrity": "sha1-5hWhbha0ehmlFXZhM9Hj6Zt4UuU="
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
|
||||
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q=="
|
||||
},
|
||||
"regenerate": {
|
||||
"version": "1.4.2",
|
||||
|
|
|
@ -126,7 +126,7 @@
|
|||
"react-window": "1.8.6",
|
||||
"react-youtube": "7.13.1",
|
||||
"redux": "4.0.4",
|
||||
"redux-thunk": "2.2.0",
|
||||
"redux-thunk": "2.4.1",
|
||||
"resemblejs": "4.0.0",
|
||||
"seamless-scroll-polyfill": "2.1.8",
|
||||
"styled-components": "3.4.9",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { AnyAction, Dispatch } from 'redux';
|
||||
import { AnyAction } from 'redux';
|
||||
import { ThunkDispatch } from 'redux-thunk';
|
||||
|
||||
import { IAnalyticsState } from '../analytics/reducer';
|
||||
import { IAuthenticationState } from '../authentication/reducer';
|
||||
|
@ -75,7 +76,7 @@ import { IVideoSipGW } from '../videosipgw/reducer';
|
|||
import { IVirtualBackground } from '../virtual-background/reducer';
|
||||
|
||||
export interface IStore {
|
||||
dispatch: Dispatch<AnyAction>;
|
||||
dispatch: ThunkDispatch<IState, void, AnyAction>;
|
||||
getState: () => IState;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,10 @@ class LoginDialog extends Component<Props, State> {
|
|||
dispatch
|
||||
} = this.props;
|
||||
const { password, username } = this.state;
|
||||
const jid = toJid(username, configHosts);
|
||||
const jid = toJid(username, configHosts ?? {
|
||||
authdomain: '',
|
||||
domain: ''
|
||||
});
|
||||
|
||||
if (conference) {
|
||||
dispatch(authenticateAndUpgradeRole(jid, password, conference));
|
||||
|
@ -217,7 +220,8 @@ class LoginDialog extends Component<Props, State> {
|
|||
const { credentials } = error;
|
||||
|
||||
if (credentials
|
||||
&& credentials.jid === toJid(username, configHosts)
|
||||
&& credentials.jid === toJid(username, configHosts ?? { authdomain: '',
|
||||
domain: '' })
|
||||
&& credentials.password === password) {
|
||||
messageKey = t('dialog.incorrectPassword');
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ export interface IConferenceState {
|
|||
password?: string;
|
||||
passwordRequired?: Object;
|
||||
pendingSubjectChange?: string;
|
||||
room?: Object;
|
||||
room?: string;
|
||||
startAudioMutedPolicy?: boolean;
|
||||
startReactionsMuted?: boolean;
|
||||
startVideoMutedPolicy?: boolean;
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
// @flow
|
||||
|
||||
// @ts-ignore
|
||||
import { jitsiLocalStorage } from '@jitsi/js-utils';
|
||||
import type { Dispatch } from 'redux';
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
import { addKnownDomains } from '../known-domains';
|
||||
import { parseURIString } from '../util';
|
||||
import { addKnownDomains } from '../known-domains/actions';
|
||||
import { parseURIString } from '../util/uri';
|
||||
|
||||
import {
|
||||
CONFIG_WILL_LOAD,
|
||||
|
@ -13,8 +12,9 @@ import {
|
|||
UPDATE_CONFIG,
|
||||
OVERWRITE_CONFIG
|
||||
} from './actionTypes';
|
||||
import { IConfig } from './configType';
|
||||
import { _CONFIG_STORE_PREFIX } from './constants';
|
||||
import { setConfigFromURLParams } from './functions';
|
||||
import { setConfigFromURLParams } from './functions.any';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,7 @@ import { setConfigFromURLParams } from './functions';
|
|||
* @param {Object} config - The new options (to add).
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function updateConfig(config: Object) {
|
||||
export function updateConfig(config: IConfig) {
|
||||
return {
|
||||
type: UPDATE_CONFIG,
|
||||
config
|
||||
|
@ -116,6 +116,8 @@ export function setConfig(config: Object = {}) {
|
|||
// On Web the config also comes from the window.config global,
|
||||
// but it is resolved in the loadConfig procedure.
|
||||
config,
|
||||
|
||||
// @ts-ignore
|
||||
window.interfaceConfig,
|
||||
locationURL);
|
||||
|
||||
|
@ -142,6 +144,7 @@ export function storeConfig(baseURL: string, config: Object) {
|
|||
let b = false;
|
||||
|
||||
try {
|
||||
// @ts-ignore
|
||||
if (typeof window.config === 'undefined' || window.config !== config) {
|
||||
jitsiLocalStorage.setItem(`${_CONFIG_STORE_PREFIX}/${baseURL}`, JSON.stringify(config));
|
||||
b = true;
|
||||
|
@ -153,7 +156,7 @@ export function storeConfig(baseURL: string, config: Object) {
|
|||
// If base/config knows a domain, then the app knows it.
|
||||
if (b) {
|
||||
try {
|
||||
dispatch(addKnownDomains(parseURIString(baseURL).host));
|
||||
dispatch(addKnownDomains(parseURIString(baseURL)?.host));
|
||||
} catch (e) {
|
||||
// Ignore the error because the fiddling with "known domains" is
|
||||
// a side effect here.
|
|
@ -105,6 +105,7 @@ export interface IConfig {
|
|||
scriptURLs?: Array<string>;
|
||||
};
|
||||
apiLogLevels?: Array<'warn' | 'log' | 'error' | 'info' | 'debug'>;
|
||||
appId?: string;
|
||||
audioLevelsInterval?: number;
|
||||
audioQuality?: {
|
||||
opusMaxAverageBitrate?: number | null;
|
||||
|
@ -316,6 +317,8 @@ export interface IConfig {
|
|||
disabled?: boolean;
|
||||
};
|
||||
gravatarBaseURL?: string;
|
||||
guestDialOutStatusUrl?: string;
|
||||
guestDialOutUrl?: string;
|
||||
helpCentreURL?: string;
|
||||
hiddenPremeetingButtons?: Array<'microphone' | 'camera' | 'select-background' | 'invite' | 'settings'>;
|
||||
hideAddRoomButton?: boolean;
|
||||
|
@ -354,7 +357,7 @@ export interface IConfig {
|
|||
notifyAllParticipants?: boolean;
|
||||
};
|
||||
localSubject?: string;
|
||||
locationURL?: string;
|
||||
locationURL?: URL;
|
||||
maxFullResolutionParticipants?: number;
|
||||
moderatedRoomServiceUrl?: string;
|
||||
mouseMoveCallbackInterval?: number;
|
||||
|
@ -403,12 +406,14 @@ export interface IConfig {
|
|||
hideStorageWarning?: boolean;
|
||||
sharingEnabled?: boolean;
|
||||
};
|
||||
recordingSharingUrl?: string;
|
||||
remoteVideoMenu?: {
|
||||
disableGrantModerator?: boolean;
|
||||
disableKick?: boolean;
|
||||
disablePrivateChat?: boolean;
|
||||
disabled?: boolean;
|
||||
};
|
||||
replaceParticipant?: string;
|
||||
requireDisplayName?: boolean;
|
||||
resolution?: number;
|
||||
roomPasswordNumberOfDigits?: number;
|
||||
|
@ -417,6 +422,7 @@ export interface IConfig {
|
|||
enabled?: boolean;
|
||||
mode?: 'always' | 'recording';
|
||||
};
|
||||
serviceUrl?: string;
|
||||
speakerStatsOrder?: Array<'role' | 'name' | 'hasLeft'>;
|
||||
startAudioMuted?: boolean;
|
||||
startAudioOnly?: boolean;
|
||||
|
@ -481,4 +487,5 @@ export interface IConfig {
|
|||
webrtcIceTcpDisable?: boolean;
|
||||
webrtcIceUdpDisable?: boolean;
|
||||
websocket?: string;
|
||||
websocketKeepAliveUrl?: string;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
// @ts-ignore
|
||||
import Bourne from '@hapi/bourne';
|
||||
// @ts-ignore
|
||||
import { jitsiLocalStorage } from '@jitsi/js-utils';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { IState } from '../../app/types';
|
||||
import { browser } from '../lib-jitsi-meet';
|
||||
import { parseURLParams } from '../util';
|
||||
import { parseURLParams } from '../util/parseURLParams';
|
||||
|
||||
import { IConfig } from './configType';
|
||||
import CONFIG_WHITELIST from './configWhitelist';
|
||||
import { _CONFIG_STORE_PREFIX, FEATURE_FLAGS } from './constants';
|
||||
import INTERFACE_CONFIG_WHITELIST from './interfaceConfigWhitelist';
|
||||
|
@ -46,7 +49,7 @@ export function createFakeConfig(baseURL: string) {
|
|||
* @param {Object} state - The global state.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getMeetingRegion(state: Object) {
|
||||
export function getMeetingRegion(state: IState) {
|
||||
return state['features/base/config']?.deploymentInfo?.region || '';
|
||||
}
|
||||
|
||||
|
@ -56,7 +59,7 @@ export function getMeetingRegion(state: Object) {
|
|||
* @param {Object} state - The global state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function getMultipleVideoSupportFeatureFlag(state: Object) {
|
||||
export function getMultipleVideoSupportFeatureFlag(state: IState) {
|
||||
return getFeatureFlag(state, FEATURE_FLAGS.MULTIPLE_VIDEO_STREAMS_SUPPORT)
|
||||
&& getSourceNameSignalingFeatureFlag(state);
|
||||
}
|
||||
|
@ -67,7 +70,7 @@ export function getMultipleVideoSupportFeatureFlag(state: Object) {
|
|||
* @param {Object} state - The global state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function getMultipleVideoSendingSupportFeatureFlag(state: Object) {
|
||||
export function getMultipleVideoSendingSupportFeatureFlag(state: IState) {
|
||||
return navigator.product !== 'ReactNative'
|
||||
&& getMultipleVideoSupportFeatureFlag(state) && isUnifiedPlanEnabled(state);
|
||||
}
|
||||
|
@ -78,7 +81,7 @@ export function getMultipleVideoSendingSupportFeatureFlag(state: Object) {
|
|||
* @param {Object} state - The global state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function getSourceNameSignalingFeatureFlag(state: Object) {
|
||||
export function getSourceNameSignalingFeatureFlag(state: IState) {
|
||||
return getFeatureFlag(state, FEATURE_FLAGS.SOURCE_NAME_SIGNALING);
|
||||
}
|
||||
|
||||
|
@ -89,10 +92,10 @@ export function getSourceNameSignalingFeatureFlag(state: Object) {
|
|||
* @param {string} featureFlag - The name of the feature flag.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function getFeatureFlag(state: Object, featureFlag: string) {
|
||||
export function getFeatureFlag(state: IState, featureFlag: string) {
|
||||
const featureFlags = state['features/base/config']?.flags || {};
|
||||
|
||||
return Boolean(featureFlags[featureFlag]);
|
||||
return Boolean(featureFlags[featureFlag as keyof typeof featureFlags]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,7 +104,7 @@ export function getFeatureFlag(state: Object, featureFlag: string) {
|
|||
* @param {Object} state - The global state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function getDisableRemoveRaisedHandOnFocus(state: Object) {
|
||||
export function getDisableRemoveRaisedHandOnFocus(state: IState) {
|
||||
return state['features/base/config']?.disableRemoveRaisedHandOnFocus || false;
|
||||
}
|
||||
|
||||
|
@ -111,7 +114,7 @@ export function getDisableRemoveRaisedHandOnFocus(state: Object) {
|
|||
* @param {Object} state - The global state.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getRecordingSharingUrl(state: Object) {
|
||||
export function getRecordingSharingUrl(state: IState) {
|
||||
return state['features/base/config'].recordingSharingUrl;
|
||||
}
|
||||
|
||||
|
@ -136,7 +139,7 @@ export function getRecordingSharingUrl(state: Object) {
|
|||
* }.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function overrideConfigJSON(config: ?Object, interfaceConfig: ?Object, json: Object) {
|
||||
export function overrideConfigJSON(config: IConfig, interfaceConfig: any, json: any) {
|
||||
for (const configName of Object.keys(json)) {
|
||||
let configObj;
|
||||
|
||||
|
@ -147,7 +150,7 @@ export function overrideConfigJSON(config: ?Object, interfaceConfig: ?Object, js
|
|||
}
|
||||
if (configObj) {
|
||||
const configJSON
|
||||
= getWhitelistedJSON(configName, json[configName]);
|
||||
= getWhitelistedJSON(configName as 'interfaceConfig' | 'config', json[configName]);
|
||||
|
||||
if (!_.isEmpty(configJSON)) {
|
||||
logger.info(
|
||||
|
@ -177,7 +180,7 @@ export function overrideConfigJSON(config: ?Object, interfaceConfig: ?Object, js
|
|||
* @returns {Object} - The result object only with the keys
|
||||
* that are whitelisted.
|
||||
*/
|
||||
export function getWhitelistedJSON(configName: string, configJSON: Object): Object {
|
||||
export function getWhitelistedJSON(configName: 'interfaceConfig' | 'config', configJSON: any): Object {
|
||||
if (configName === 'interfaceConfig') {
|
||||
return _.pick(configJSON, INTERFACE_CONFIG_WHITELIST);
|
||||
} else if (configName === 'config') {
|
||||
|
@ -193,9 +196,9 @@ export function getWhitelistedJSON(configName: string, configJSON: Object): Obje
|
|||
* @param {Object} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isNameReadOnly(state: Object): boolean {
|
||||
return state['features/base/config'].disableProfile
|
||||
|| state['features/base/config'].readOnlyName;
|
||||
export function isNameReadOnly(state: IState): boolean {
|
||||
return Boolean(state['features/base/config'].disableProfile
|
||||
|| state['features/base/config'].readOnlyName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -204,7 +207,7 @@ export function isNameReadOnly(state: Object): boolean {
|
|||
* @param {Object} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isDisplayNameVisible(state: Object): boolean {
|
||||
export function isDisplayNameVisible(state: IState): boolean {
|
||||
return !state['features/base/config'].hideDisplayName;
|
||||
}
|
||||
|
||||
|
@ -214,7 +217,7 @@ export function isDisplayNameVisible(state: Object): boolean {
|
|||
* @param {Object} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isUnifiedPlanEnabled(state: Object): boolean {
|
||||
export function isUnifiedPlanEnabled(state: IState): boolean {
|
||||
const { enableUnifiedOnChrome = true } = state['features/base/config'];
|
||||
|
||||
return browser.supportsUnifiedPlan()
|
||||
|
@ -232,7 +235,7 @@ export function isUnifiedPlanEnabled(state: Object): boolean {
|
|||
* from {@code baseURL} and stored with {@code storeConfig} if it was restored;
|
||||
* otherwise, {@code undefined}.
|
||||
*/
|
||||
export function restoreConfig(baseURL: string): ?Object {
|
||||
export function restoreConfig(baseURL: string) {
|
||||
const key = `${_CONFIG_STORE_PREFIX}/${baseURL}`;
|
||||
const config = jitsiLocalStorage.getItem(key);
|
||||
|
||||
|
@ -266,9 +269,9 @@ export function restoreConfig(baseURL: string): ?Object {
|
|||
* @returns {void}
|
||||
*/
|
||||
export function setConfigFromURLParams(
|
||||
config: ?Object, interfaceConfig: ?Object, location: Object) {
|
||||
config: IConfig, interfaceConfig: any, location: string | URL) {
|
||||
const params = parseURLParams(location);
|
||||
const json = {};
|
||||
const json: any = {};
|
||||
|
||||
// At this point we have:
|
||||
// params = {
|
||||
|
@ -292,7 +295,7 @@ export function setConfigFromURLParams(
|
|||
for (const param of Object.keys(params)) {
|
||||
let base = json;
|
||||
const names = param.split('.');
|
||||
const last = names.pop();
|
||||
const last = names.pop() ?? '';
|
||||
|
||||
for (const name of names) {
|
||||
base = base[name] = base[name] || {};
|
|
@ -1,8 +1,10 @@
|
|||
// @flow
|
||||
|
||||
import { NativeModules } from 'react-native';
|
||||
|
||||
import { getFeatureFlag, REPLACE_PARTICIPANT } from '../flags';
|
||||
import { IState } from '../../app/types';
|
||||
import { REPLACE_PARTICIPANT } from '../flags/constants';
|
||||
import { getFeatureFlag } from '../flags/functions';
|
||||
|
||||
import { IConfig } from './configType';
|
||||
|
||||
export * from './functions.any';
|
||||
|
||||
|
@ -12,7 +14,8 @@ export * from './functions.any';
|
|||
* @param {*} config - The configuration which needs to be cleaned up.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function _cleanupConfig(config: Object) {
|
||||
export function _cleanupConfig(config: IConfig) {
|
||||
config.analytics ??= {};
|
||||
config.analytics.scriptURLs = [];
|
||||
if (NativeModules.AppInfo.LIBRE_BUILD) {
|
||||
delete config.analytics?.amplitudeAPPKey;
|
||||
|
@ -29,6 +32,6 @@ export function _cleanupConfig(config: Object) {
|
|||
* @param {Object} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function getReplaceParticipant(state: Object): string {
|
||||
export function getReplaceParticipant(state: IState): string {
|
||||
return getFeatureFlag(state, REPLACE_PARTICIPANT, false);
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
// @flow
|
||||
import { IState } from '../../app/types';
|
||||
|
||||
import { IConfig } from './configType';
|
||||
import { TOOLBAR_BUTTONS } from './constants';
|
||||
|
||||
export * from './functions.any';
|
||||
|
@ -10,7 +11,7 @@ export * from './functions.any';
|
|||
* @param {*} config - The configuration which needs to be cleaned up.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function _cleanupConfig(config: Object) { // eslint-disable-line no-unused-vars
|
||||
export function _cleanupConfig(config: IConfig) { // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -19,7 +20,7 @@ export function _cleanupConfig(config: Object) { // eslint-disable-line no-unuse
|
|||
* @param {Object} state - The state of the app.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getDialOutStatusUrl(state: Object): string {
|
||||
export function getDialOutStatusUrl(state: IState): string | undefined {
|
||||
return state['features/base/config'].guestDialOutStatusUrl;
|
||||
}
|
||||
|
||||
|
@ -29,7 +30,7 @@ export function getDialOutStatusUrl(state: Object): string {
|
|||
* @param {Object} state - The state of the app.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getDialOutUrl(state: Object): string {
|
||||
export function getDialOutUrl(state: IState): string | undefined {
|
||||
return state['features/base/config'].guestDialOutUrl;
|
||||
}
|
||||
|
||||
|
@ -39,7 +40,7 @@ export function getDialOutUrl(state: Object): string {
|
|||
* @param {Object} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function getReplaceParticipant(state: Object): string {
|
||||
export function getReplaceParticipant(state: IState): string | undefined {
|
||||
return state['features/base/config'].replaceParticipant;
|
||||
}
|
||||
|
||||
|
@ -49,7 +50,7 @@ export function getReplaceParticipant(state: Object): string {
|
|||
* @param {Object} state - The redux state.
|
||||
* @returns {Array<string>} - The list of enabled toolbar buttons.
|
||||
*/
|
||||
export function getToolbarButtons(state: Object): Array<string> {
|
||||
export function getToolbarButtons(state: IState): Array<string> {
|
||||
const { toolbarButtons } = state['features/base/config'];
|
||||
|
||||
return Array.isArray(toolbarButtons) ? toolbarButtons : TOOLBAR_BUTTONS;
|
||||
|
@ -63,7 +64,7 @@ export function getToolbarButtons(state: Object): Array<string> {
|
|||
* @param {Object|Array<string>} state - The redux state or the array with the enabled buttons.
|
||||
* @returns {boolean} - True if the button is enabled and false otherwise.
|
||||
*/
|
||||
export function isToolbarButtonEnabled(buttonName: string, state: Object | Array<string>) {
|
||||
export function isToolbarButtonEnabled(buttonName: string, state: IState | Array<string>) {
|
||||
const buttons = Array.isArray(state) ? state : getToolbarButtons(state);
|
||||
|
||||
return buttons.includes(buttonName);
|
||||
|
@ -75,7 +76,7 @@ export function isToolbarButtonEnabled(buttonName: string, state: Object | Array
|
|||
* @param {Object} state - The state of the app.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function areAudioLevelsEnabled(state: Object): boolean {
|
||||
export function areAudioLevelsEnabled(state: IState): boolean {
|
||||
// Default to false for React Native as audio levels are of no interest to the mobile app.
|
||||
return navigator.product !== 'ReactNative' && !state['features/base/config'].disableAudioLevels;
|
||||
}
|
|
@ -1,13 +1,11 @@
|
|||
// @flow
|
||||
|
||||
import { getBackendSafeRoomName } from '../util';
|
||||
import { getBackendSafeRoomName } from '../util/uri';
|
||||
|
||||
/**
|
||||
* Builds and returns the room name.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
export default function getRoomName(): ?string {
|
||||
export default function getRoomName(): string | undefined {
|
||||
const path = window.location.pathname;
|
||||
|
||||
// The last non-directory component of the path (name) is the room.
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import { getLogger } from '../logging/functions';
|
||||
|
||||
export default getLogger('features/base/config');
|
|
@ -1,9 +1,13 @@
|
|||
import { AnyAction } from 'redux';
|
||||
|
||||
import { IStore } from '../../app/types';
|
||||
import { getFeatureFlag } from '../flags/functions';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
import { updateSettings } from '../settings';
|
||||
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
|
||||
import { updateSettings } from '../settings/actions';
|
||||
|
||||
import { SET_CONFIG, OVERWRITE_CONFIG } from './actionTypes';
|
||||
import { updateConfig } from './actions';
|
||||
import { IConfig } from './configType';
|
||||
|
||||
/**
|
||||
* The middleware of the feature {@code base/config}.
|
||||
|
@ -37,7 +41,7 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
* @private
|
||||
* @returns {*} The return value of {@code next(action)}.
|
||||
*/
|
||||
function _setConfig({ dispatch, getState }, next, action) {
|
||||
function _setConfig({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
|
||||
// The reducer is doing some alterations to the config passed in the action,
|
||||
// so make sure it's the final state by waiting for the action to be
|
||||
// reduced.
|
||||
|
@ -46,7 +50,7 @@ function _setConfig({ dispatch, getState }, next, action) {
|
|||
|
||||
// Update the config with user defined settings.
|
||||
const settings = state['features/base/settings'];
|
||||
const config = {};
|
||||
const config: IConfig = {};
|
||||
|
||||
if (typeof settings.disableP2P !== 'undefined') {
|
||||
config.p2p = { enabled: !settings.disableP2P };
|
||||
|
@ -77,7 +81,9 @@ function _setConfig({ dispatch, getState }, next, action) {
|
|||
// not be the global variable which is being modified anymore due to
|
||||
// different merge methods being used along the way. The global variable
|
||||
// must be synchronized with the final state resolved by the reducer.
|
||||
// @ts-ignore
|
||||
if (typeof window.config !== 'undefined') {
|
||||
// @ts-ignore
|
||||
window.config = state['features/base/config'];
|
||||
}
|
||||
|
||||
|
@ -96,7 +102,7 @@ function _setConfig({ dispatch, getState }, next, action) {
|
|||
* @private
|
||||
* @returns {*} The return value of {@code next(action)}.
|
||||
*/
|
||||
function _updateSettings({ dispatch }, next, action) {
|
||||
function _updateSettings({ dispatch }: IStore, next: Function, action: AnyAction) {
|
||||
const { config: { doNotFlipLocalVideo } } = action;
|
||||
|
||||
if (doNotFlipLocalVideo === true) {
|
|
@ -1,10 +1,11 @@
|
|||
import _ from 'lodash';
|
||||
|
||||
import { IState } from '../../app/types';
|
||||
import {
|
||||
appendURLParam,
|
||||
getBackendSafeRoomName,
|
||||
parseURIString
|
||||
} from '../util';
|
||||
} from '../util/uri';
|
||||
|
||||
import logger from './logger';
|
||||
|
||||
|
@ -16,7 +17,7 @@ import logger from './logger';
|
|||
* @returns {Object} The options to be passed to the constructor of
|
||||
* {@code JitsiConnection}.
|
||||
*/
|
||||
export function constructOptions(state) {
|
||||
export function constructOptions(state: IState) {
|
||||
// Deep clone the options to make sure we don't modify the object in the
|
||||
// redux store.
|
||||
const options = _.cloneDeep(state['features/base/config']);
|
||||
|
@ -36,14 +37,14 @@ export function constructOptions(state) {
|
|||
|
||||
if (bosh.startsWith('//')) {
|
||||
// By default our config.js doesn't include the protocol.
|
||||
bosh = `${locationURL.protocol}${bosh}`;
|
||||
bosh = `${locationURL?.protocol}${bosh}`;
|
||||
} else if (bosh.startsWith('/')) {
|
||||
// Handle relative URLs, which won't work on mobile.
|
||||
const {
|
||||
protocol,
|
||||
host,
|
||||
contextRoot
|
||||
} = parseURIString(locationURL.href);
|
||||
} = parseURIString(locationURL?.href);
|
||||
|
||||
bosh = `${protocol}//${host}${contextRoot || '/'}${bosh.substr(1)}`;
|
||||
}
|
||||
|
@ -60,10 +61,10 @@ export function constructOptions(state) {
|
|||
if (serviceUrl && room) {
|
||||
const roomName = getBackendSafeRoomName(room);
|
||||
|
||||
options.serviceUrl = appendURLParam(serviceUrl, 'room', roomName);
|
||||
options.serviceUrl = appendURLParam(serviceUrl, 'room', roomName ?? '');
|
||||
|
||||
if (options.websocketKeepAliveUrl) {
|
||||
options.websocketKeepAliveUrl = appendURLParam(options.websocketKeepAliveUrl, 'room', roomName);
|
||||
options.websocketKeepAliveUrl = appendURLParam(options.websocketKeepAliveUrl, 'room', roomName ?? '');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
// @flow
|
||||
|
||||
import type { Dispatch } from 'redux';
|
||||
/* eslint-disable lines-around-comment */
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
// @ts-ignore
|
||||
import { conferenceLeft, conferenceWillLeave } from '../conference/actions';
|
||||
// @ts-ignore
|
||||
import { getCurrentConference } from '../conference/functions';
|
||||
import JitsiMeetJS, { JitsiConnectionEvents } from '../lib-jitsi-meet';
|
||||
|
||||
|
@ -36,34 +37,34 @@ export type ConnectionFailedError = {
|
|||
/**
|
||||
* The XMPP user's ID.
|
||||
*/
|
||||
jid: string,
|
||||
jid: string;
|
||||
|
||||
/**
|
||||
* The XMPP user's password.
|
||||
*/
|
||||
password: string
|
||||
},
|
||||
password: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* The details about the connection failed event.
|
||||
*/
|
||||
details?: Object,
|
||||
details?: Object;
|
||||
|
||||
/**
|
||||
* Error message.
|
||||
*/
|
||||
message?: string,
|
||||
message?: string;
|
||||
|
||||
/**
|
||||
* One of {@link JitsiConnectionError} constants (defined in
|
||||
* lib-jitsi-meet).
|
||||
*/
|
||||
name: string,
|
||||
name: string;
|
||||
|
||||
/**
|
||||
* Indicates whether this event is recoverable or not.
|
||||
*/
|
||||
recoverable?: boolean
|
||||
recoverable?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -73,7 +74,7 @@ export type ConnectionFailedError = {
|
|||
* @param {string} [password] - The XMPP user's password.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function connect(id: ?string, password: ?string) {
|
||||
export function connect(id?: string, password?: string) {
|
||||
return (dispatch: Dispatch<any>, getState: Function) => {
|
||||
const state = getState();
|
||||
const options = constructOptions(state);
|
||||
|
@ -141,7 +142,7 @@ export function connect(id: ?string, password: ?string) {
|
|||
function _onConnectionFailed( // eslint-disable-line max-params
|
||||
err: string,
|
||||
msg: string,
|
||||
credentials: Object,
|
||||
credentials: any,
|
||||
details: Object) {
|
||||
unsubscribe();
|
||||
dispatch(
|
||||
|
@ -253,7 +254,7 @@ export function connectionFailed(
|
|||
* connection: JitsiConnection
|
||||
* }}
|
||||
*/
|
||||
function _connectionWillConnect(connection) {
|
||||
function _connectionWillConnect(connection: Object) {
|
||||
return {
|
||||
type: CONNECTION_WILL_CONNECT,
|
||||
connection
|
||||
|
@ -286,7 +287,7 @@ export function disconnect() {
|
|||
|
||||
promise
|
||||
= conference_.leave()
|
||||
.catch(error => {
|
||||
.catch((error: Error) => {
|
||||
logger.warn(
|
||||
'JitsiConference.leave() rejected with:',
|
||||
error);
|
||||
|
@ -328,7 +329,7 @@ export function disconnect() {
|
|||
* locationURL: URL
|
||||
* }}
|
||||
*/
|
||||
export function setLocationURL(locationURL: ?URL) {
|
||||
export function setLocationURL(locationURL?: URL) {
|
||||
return {
|
||||
type: SET_LOCATION_URL,
|
||||
locationURL
|
|
@ -1,12 +1,8 @@
|
|||
// @flow
|
||||
import { IStore } from '../../app/types';
|
||||
import { configureInitialDevices } from '../devices/actions';
|
||||
import { getBackendSafeRoomName } from '../util/uri';
|
||||
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
declare var APP: Object;
|
||||
declare var config: Object;
|
||||
|
||||
import { configureInitialDevices } from '../devices';
|
||||
import { getBackendSafeRoomName } from '../util';
|
||||
declare const APP: any;
|
||||
|
||||
export {
|
||||
connectionDisconnected,
|
||||
|
@ -24,7 +20,7 @@ export * from './actions.any';
|
|||
* @returns {Promise<JitsiConnection>}
|
||||
*/
|
||||
export function connect() {
|
||||
return (dispatch: Dispatch<any>, getState: Function) => {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const room = getBackendSafeRoomName(getState()['features/base/conference'].room);
|
||||
|
||||
// XXX For web based version we use conference initialization logic
|
||||
|
@ -32,7 +28,7 @@ export function connect() {
|
|||
return dispatch(configureInitialDevices()).then(
|
||||
() => APP.conference.init({
|
||||
roomName: room
|
||||
}).catch(error => {
|
||||
}).catch((error: Error) => {
|
||||
APP.API.notifyConferenceLeft(APP.conference.roomName);
|
||||
logger.error(error);
|
||||
}));
|
||||
|
@ -46,7 +42,7 @@ export function connect() {
|
|||
* request for call feedback.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function disconnect(requestFeedback: boolean = false) {
|
||||
export function disconnect(requestFeedback = false) {
|
||||
// XXX For web based version we use conference hanging up logic from the old
|
||||
// app.
|
||||
return () => APP.conference.hangup(requestFeedback);
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
/**
|
||||
* The name of the {@code JitsiConnection} property which identifies the {@code JitsiConference} currently associated
|
||||
* with it.
|
|
@ -1,7 +1,6 @@
|
|||
/* @flow */
|
||||
|
||||
import { toState } from '../redux';
|
||||
import { toURLString } from '../util';
|
||||
import { IStateful } from '../app/types';
|
||||
import { toState } from '../redux/functions';
|
||||
import { toURLString } from '../util/uri';
|
||||
|
||||
import { getURLWithoutParams } from './utils';
|
||||
|
||||
|
@ -13,7 +12,7 @@ import { getURLWithoutParams } from './utils';
|
|||
* @returns {string|undefined}
|
||||
* @private
|
||||
*/
|
||||
export function getCurrentConferenceUrl(stateful: Function | Object) {
|
||||
export function getCurrentConferenceUrl(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
let currentUrl;
|
||||
|
||||
|
@ -40,7 +39,7 @@ export function getCurrentConferenceUrl(stateful: Function | Object) {
|
|||
* to be stripped.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getInviteURL(stateOrGetState: Function | Object): string {
|
||||
export function getInviteURL(stateOrGetState: IStateful): string {
|
||||
const state = toState(stateOrGetState);
|
||||
let locationURL
|
||||
= state instanceof URL
|
||||
|
@ -75,7 +74,7 @@ export function getInviteURL(stateOrGetState: Function | Object): string {
|
|||
* @param {Function|Object} stateOrGetState - The redux state or redux's {@code getState} function.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isInviteURLReady(stateOrGetState: Function | Object): boolean {
|
||||
export function isInviteURLReady(stateOrGetState: IStateful): boolean {
|
||||
const state = toState(stateOrGetState);
|
||||
|
||||
return Boolean(state['features/base/connection'].locationURL || state['features/base/config'].locationURL);
|
||||
|
@ -90,6 +89,6 @@ export function isInviteURLReady(stateOrGetState: Function | Object): boolean {
|
|||
* @returns {string} A string in the form of a JID (i.e.
|
||||
* {@code user@server.com}).
|
||||
*/
|
||||
export function toJid(id: string, { authdomain, domain }: Object): string {
|
||||
export function toJid(id: string, { authdomain, domain }: { authdomain?: string; domain?: string; }): string {
|
||||
return id.indexOf('@') >= 0 ? id : `${id}@${authdomain || domain}`;
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import { getLogger } from '../logging/functions';
|
||||
|
||||
export default getLogger('features/base/connection');
|
|
@ -1,8 +1,7 @@
|
|||
import { IStore } from '../../app/types';
|
||||
import JitsiMeetJS from '../lib-jitsi-meet';
|
||||
import {
|
||||
getUserSelectedOutputDeviceId,
|
||||
updateSettings
|
||||
} from '../settings';
|
||||
import { updateSettings } from '../settings/actions';
|
||||
import { getUserSelectedOutputDeviceId } from '../settings/functions.any';
|
||||
|
||||
import {
|
||||
ADD_PENDING_DEVICE_REQUEST,
|
||||
|
@ -55,7 +54,7 @@ const DEVICE_TYPE_TO_SETTINGS_KEYS = {
|
|||
* request: Object
|
||||
* }}
|
||||
*/
|
||||
export function addPendingDeviceRequest(request) {
|
||||
export function addPendingDeviceRequest(request: Object) {
|
||||
return {
|
||||
type: ADD_PENDING_DEVICE_REQUEST,
|
||||
request
|
||||
|
@ -68,7 +67,7 @@ export function addPendingDeviceRequest(request) {
|
|||
* @returns {Function}
|
||||
*/
|
||||
export function configureInitialDevices() {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const deviceLabels = getDevicesFromURL(getState());
|
||||
let updateSettingsPromise;
|
||||
|
||||
|
@ -86,9 +85,9 @@ export function configureInitialDevices() {
|
|||
name: 'setDevice',
|
||||
device: {
|
||||
kind: key.toLowerCase(),
|
||||
label: deviceLabels[key]
|
||||
label: deviceLabels[key as keyof typeof deviceLabels]
|
||||
},
|
||||
// eslint-disable-next-line no-empty-function
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
responseCallback() {}
|
||||
}));
|
||||
});
|
||||
|
@ -96,14 +95,17 @@ export function configureInitialDevices() {
|
|||
return;
|
||||
}
|
||||
|
||||
const newSettings = {};
|
||||
const newSettings: any = {};
|
||||
|
||||
Object.keys(deviceLabels).forEach(key => {
|
||||
const label = deviceLabels[key];
|
||||
const label = deviceLabels[key as keyof typeof deviceLabels];
|
||||
|
||||
// @ts-ignore
|
||||
const deviceId = getDeviceIdByLabel(state, label, key);
|
||||
|
||||
if (deviceId) {
|
||||
const settingsTranslationMap = DEVICE_TYPE_TO_SETTINGS_KEYS[key];
|
||||
const settingsTranslationMap = DEVICE_TYPE_TO_SETTINGS_KEYS[
|
||||
key as keyof typeof DEVICE_TYPE_TO_SETTINGS_KEYS];
|
||||
|
||||
newSettings[settingsTranslationMap.currentDeviceId] = deviceId;
|
||||
newSettings[settingsTranslationMap.userSelectedDeviceId] = deviceId;
|
||||
|
@ -135,12 +137,12 @@ export function configureInitialDevices() {
|
|||
* @returns {Function}
|
||||
*/
|
||||
export function getAvailableDevices() {
|
||||
return dispatch => new Promise(resolve => {
|
||||
return (dispatch: IStore['dispatch']) => new Promise(resolve => {
|
||||
const { mediaDevices } = JitsiMeetJS;
|
||||
|
||||
if (mediaDevices.isDeviceListAvailable()
|
||||
&& mediaDevices.isDeviceChangeAvailable()) {
|
||||
mediaDevices.enumerateDevices(devices => {
|
||||
mediaDevices.enumerateDevices((devices: any) => {
|
||||
dispatch(updateDeviceList(devices));
|
||||
|
||||
resolve(devices);
|
||||
|
@ -163,7 +165,7 @@ export function getAvailableDevices() {
|
|||
* error: Object
|
||||
* }}
|
||||
*/
|
||||
export function notifyCameraError(error) {
|
||||
export function notifyCameraError(error: Error) {
|
||||
return {
|
||||
type: NOTIFY_CAMERA_ERROR,
|
||||
error
|
||||
|
@ -182,7 +184,7 @@ export function notifyCameraError(error) {
|
|||
* error: Object
|
||||
* }}
|
||||
*/
|
||||
export function notifyMicError(error) {
|
||||
export function notifyMicError(error: Error) {
|
||||
return {
|
||||
type: NOTIFY_MIC_ERROR,
|
||||
error
|
||||
|
@ -211,7 +213,7 @@ export function removePendingDeviceRequests() {
|
|||
* deviceId: string
|
||||
* }}
|
||||
*/
|
||||
export function setAudioInputDevice(deviceId) {
|
||||
export function setAudioInputDevice(deviceId: string) {
|
||||
return {
|
||||
type: SET_AUDIO_INPUT_DEVICE,
|
||||
deviceId
|
||||
|
@ -225,8 +227,8 @@ export function setAudioInputDevice(deviceId) {
|
|||
* @param {string} deviceId - The id of the new audio input device.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function setAudioInputDeviceAndUpdateSettings(deviceId) {
|
||||
return function(dispatch, getState) {
|
||||
export function setAudioInputDeviceAndUpdateSettings(deviceId: string) {
|
||||
return function(dispatch: IStore['dispatch'], getState: IStore['getState']) {
|
||||
const deviceLabel = getDeviceLabelById(getState(), deviceId, 'audioInput');
|
||||
|
||||
dispatch(setAudioInputDevice(deviceId));
|
||||
|
@ -243,8 +245,8 @@ export function setAudioInputDeviceAndUpdateSettings(deviceId) {
|
|||
* @param {string} deviceId - The id of the new output device.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function setAudioOutputDevice(deviceId) {
|
||||
return function(dispatch, getState) {
|
||||
export function setAudioOutputDevice(deviceId: string) {
|
||||
return function(dispatch: IStore['dispatch'], getState: IStore['getState']) {
|
||||
const deviceLabel = getDeviceLabelById(getState(), deviceId, 'audioOutput');
|
||||
|
||||
return setAudioOutputDeviceId(deviceId, dispatch, true, deviceLabel);
|
||||
|
@ -260,7 +262,7 @@ export function setAudioOutputDevice(deviceId) {
|
|||
* deviceId: string
|
||||
* }}
|
||||
*/
|
||||
export function setVideoInputDevice(deviceId) {
|
||||
export function setVideoInputDevice(deviceId: string) {
|
||||
return {
|
||||
type: SET_VIDEO_INPUT_DEVICE,
|
||||
deviceId
|
||||
|
@ -274,8 +276,8 @@ export function setVideoInputDevice(deviceId) {
|
|||
* @param {string} deviceId - The id of the new video input device.
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function setVideoInputDeviceAndUpdateSettings(deviceId) {
|
||||
return function(dispatch, getState) {
|
||||
export function setVideoInputDeviceAndUpdateSettings(deviceId: string) {
|
||||
return function(dispatch: IStore['dispatch'], getState: IStore['getState']) {
|
||||
const deviceLabel = getDeviceLabelById(getState(), deviceId, 'videoInput');
|
||||
|
||||
dispatch(setVideoInputDevice(deviceId));
|
||||
|
@ -296,7 +298,7 @@ export function setVideoInputDeviceAndUpdateSettings(deviceId) {
|
|||
* devices: Array<MediaDeviceInfo>
|
||||
* }}
|
||||
*/
|
||||
export function updateDeviceList(devices) {
|
||||
export function updateDeviceList(devices: MediaDeviceInfo[]) {
|
||||
return {
|
||||
type: UPDATE_DEVICE_LIST,
|
||||
devices
|
||||
|
@ -314,7 +316,7 @@ export function updateDeviceList(devices) {
|
|||
* oldDevices: Array<MediaDeviceInfo>
|
||||
* }}
|
||||
*/
|
||||
export function checkAndNotifyForNewDevice(newDevices, oldDevices) {
|
||||
export function checkAndNotifyForNewDevice(newDevices: MediaDeviceInfo[], oldDevices: MediaDeviceInfo[]) {
|
||||
return {
|
||||
type: CHECK_AND_NOTIFY_FOR_NEW_DEVICE,
|
||||
newDevices,
|
||||
|
@ -331,7 +333,7 @@ export function checkAndNotifyForNewDevice(newDevices, oldDevices) {
|
|||
* permissions: Object
|
||||
* }}
|
||||
*/
|
||||
export function devicePermissionsChanged(permissions) {
|
||||
export function devicePermissionsChanged(permissions: Object) {
|
||||
return {
|
||||
type: DEVICE_PERMISSIONS_CHANGED,
|
||||
permissions
|
|
@ -1,12 +1,14 @@
|
|||
// @flow
|
||||
|
||||
import { IState } from '../../app/types';
|
||||
import JitsiMeetJS from '../lib-jitsi-meet';
|
||||
import { updateSettings } from '../settings';
|
||||
import { parseURLParams } from '../util';
|
||||
import { updateSettings } from '../settings/actions';
|
||||
import { ISettingsState } from '../settings/reducer';
|
||||
import { parseURLParams } from '../util/parseURLParams';
|
||||
|
||||
import logger from './logger';
|
||||
import { IDevicesState } from './reducer';
|
||||
|
||||
declare var APP: Object;
|
||||
|
||||
declare const APP: any;
|
||||
|
||||
const webrtcKindToJitsiKindTranslator = {
|
||||
audioinput: 'audioInput',
|
||||
|
@ -22,14 +24,16 @@ const webrtcKindToJitsiKindTranslator = {
|
|||
* @returns {boolean} - True if the labels are already initialized and false
|
||||
* otherwise.
|
||||
*/
|
||||
export function areDeviceLabelsInitialized(state: Object) {
|
||||
export function areDeviceLabelsInitialized(state: IState) {
|
||||
// TODO: Replace with something that doesn't use APP when the conference.js logic is reactified.
|
||||
if (APP.conference._localTracksInitialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const type of [ 'audioInput', 'audioOutput', 'videoInput' ]) {
|
||||
if ((state['features/base/devices'].availableDevices[type] || []).find(d => Boolean(d.label))) {
|
||||
const availableDevices = state['features/base/devices'].availableDevices;
|
||||
|
||||
if ((availableDevices[type as keyof typeof availableDevices] || []).find(d => Boolean(d.label))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -56,14 +60,15 @@ export function getAudioOutputDeviceId() {
|
|||
* of the preceding types.
|
||||
* @returns {string|undefined}
|
||||
*/
|
||||
export function getDefaultDeviceId(state: Object, kind: string) {
|
||||
const kindToSearch = webrtcKindToJitsiKindTranslator[kind] || kind;
|
||||
const defaultDevice = (state['features/base/devices'].availableDevices[kindToSearch] || [])
|
||||
export function getDefaultDeviceId(state: IState, kind: string) {
|
||||
const kindToSearch = webrtcKindToJitsiKindTranslator[kind as keyof typeof webrtcKindToJitsiKindTranslator] || kind;
|
||||
const availableDevices = state['features/base/devices'].availableDevices;
|
||||
const defaultDevice = (availableDevices[kindToSearch as keyof typeof availableDevices] || [])
|
||||
.find(d => d.deviceId === 'default');
|
||||
|
||||
// Find the device with a matching group id.
|
||||
const matchingDevice = (state['features/base/devices'].availableDevices[kindToSearch] || [])
|
||||
.find(d => d.deviceId !== 'default' && d.groupId === defaultDevice.groupId);
|
||||
const matchingDevice = (availableDevices[kindToSearch as keyof typeof availableDevices] || [])
|
||||
.find(d => d.deviceId !== 'default' && d.groupId === defaultDevice?.groupId);
|
||||
|
||||
if (matchingDevice) {
|
||||
return matchingDevice.deviceId;
|
||||
|
@ -80,11 +85,12 @@ export function getDefaultDeviceId(state: Object, kind: string) {
|
|||
* of the preceding types.
|
||||
* @returns {string|undefined}
|
||||
*/
|
||||
export function getDeviceIdByLabel(state: Object, label: string, kind: string) {
|
||||
const kindToSearch = webrtcKindToJitsiKindTranslator[kind] || kind;
|
||||
export function getDeviceIdByLabel(state: IState, label: string, kind: string) {
|
||||
const kindToSearch = webrtcKindToJitsiKindTranslator[kind as keyof typeof webrtcKindToJitsiKindTranslator] || kind;
|
||||
|
||||
const availableDevices = state['features/base/devices'].availableDevices;
|
||||
const device
|
||||
= (state['features/base/devices'].availableDevices[kindToSearch] || [])
|
||||
= (availableDevices[kindToSearch as keyof typeof availableDevices] || [])
|
||||
.find(d => d.label === label);
|
||||
|
||||
if (device) {
|
||||
|
@ -102,11 +108,12 @@ export function getDeviceIdByLabel(state: Object, label: string, kind: string) {
|
|||
* of the preceding types.
|
||||
* @returns {string|undefined}
|
||||
*/
|
||||
export function getDeviceLabelById(state: Object, id: string, kind: string) {
|
||||
const kindToSearch = webrtcKindToJitsiKindTranslator[kind] || kind;
|
||||
export function getDeviceLabelById(state: IState, id: string, kind: string) {
|
||||
const kindToSearch = webrtcKindToJitsiKindTranslator[kind as keyof typeof webrtcKindToJitsiKindTranslator] || kind;
|
||||
|
||||
const availableDevices = state['features/base/devices'].availableDevices;
|
||||
const device
|
||||
= (state['features/base/devices'].availableDevices[kindToSearch] || [])
|
||||
= (availableDevices[kindToSearch as keyof typeof availableDevices] || [])
|
||||
.find(d => d.deviceId === id);
|
||||
|
||||
if (device) {
|
||||
|
@ -120,9 +127,9 @@ export function getDeviceLabelById(state: Object, id: string, kind: string) {
|
|||
* @param {Object} state - The redux state.
|
||||
* @returns {Object|undefined}
|
||||
*/
|
||||
export function getDevicesFromURL(state: Object) {
|
||||
export function getDevicesFromURL(state: IState) {
|
||||
const urlParams
|
||||
= parseURLParams(state['features/base/connection'].locationURL);
|
||||
= parseURLParams(state['features/base/connection'].locationURL ?? '');
|
||||
|
||||
const audioOutput = urlParams['devices.audioOutput'];
|
||||
const videoInput = urlParams['devices.videoInput'];
|
||||
|
@ -132,7 +139,7 @@ export function getDevicesFromURL(state: Object) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const devices = {};
|
||||
const devices: IDevicesState['availableDevices'] = {};
|
||||
|
||||
audioOutput && (devices.audioOutput = audioOutput);
|
||||
videoInput && (devices.videoInput = videoInput);
|
||||
|
@ -150,7 +157,7 @@ export function getDevicesFromURL(state: Object) {
|
|||
* are device type and the values are arrays with devices matching the device
|
||||
* type.
|
||||
*/
|
||||
export function groupDevicesByKind(devices: Object[]): Object {
|
||||
export function groupDevicesByKind(devices: MediaDeviceInfo[]): IDevicesState['availableDevices'] {
|
||||
return {
|
||||
audioInput: devices.filter(device => device.kind === 'audioinput'),
|
||||
audioOutput: devices.filter(device => device.kind === 'audiooutput'),
|
||||
|
@ -165,7 +172,7 @@ export function groupDevicesByKind(devices: Object[]): Object {
|
|||
* @private
|
||||
* @returns {Array<MediaDeviceInfo>} Filtered audio devices.
|
||||
*/
|
||||
export function filterAudioDevices(devices: Object[]): Object {
|
||||
export function filterAudioDevices(devices: MediaDeviceInfo[]) {
|
||||
return devices.filter(device => device.kind === 'audioinput');
|
||||
}
|
||||
|
||||
|
@ -197,8 +204,8 @@ export function formatDeviceLabel(label: string) {
|
|||
* @param {Object} state - The state of the application.
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
export function getAudioInputDeviceData(state: Object) {
|
||||
return state['features/base/devices'].availableDevices.audioInput.map(
|
||||
export function getAudioInputDeviceData(state: IState) {
|
||||
return state['features/base/devices'].availableDevices.audioInput?.map(
|
||||
({ deviceId, label }) => {
|
||||
return {
|
||||
deviceId,
|
||||
|
@ -213,8 +220,8 @@ export function getAudioInputDeviceData(state: Object) {
|
|||
* @param {Object} state - The state of the application.
|
||||
* @returns {Object[]}
|
||||
*/
|
||||
export function getAudioOutputDeviceData(state: Object) {
|
||||
return state['features/base/devices'].availableDevices.audioOutput.map(
|
||||
export function getAudioOutputDeviceData(state: IState) {
|
||||
return state['features/base/devices'].availableDevices.audioOutput?.map(
|
||||
({ deviceId, label }) => {
|
||||
return {
|
||||
deviceId,
|
||||
|
@ -229,8 +236,8 @@ export function getAudioOutputDeviceData(state: Object) {
|
|||
* @param {Object} state - The state of the application.
|
||||
* @returns {string[]}
|
||||
*/
|
||||
export function getVideoDeviceIds(state: Object) {
|
||||
return state['features/base/devices'].availableDevices.videoInput.map(({ deviceId }) => deviceId);
|
||||
export function getVideoDeviceIds(state: IState) {
|
||||
return state['features/base/devices'].availableDevices.videoInput?.map(({ deviceId }) => deviceId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,12 +248,14 @@ export function getVideoDeviceIds(state: Object) {
|
|||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function hasAvailableDevices(state: Object, type: string) {
|
||||
export function hasAvailableDevices(state: IState, type: string) {
|
||||
if (state['features/base/devices'] === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return state['features/base/devices'].availableDevices[type].length > 0;
|
||||
const availableDevices = state['features/base/devices'].availableDevices;
|
||||
|
||||
return Number(availableDevices[type as keyof typeof availableDevices]?.length) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,10 +269,10 @@ export function hasAvailableDevices(state: Object, type: string) {
|
|||
* @returns {Promise}
|
||||
*/
|
||||
export function setAudioOutputDeviceId(
|
||||
newId: string = 'default',
|
||||
newId = 'default',
|
||||
dispatch: Function,
|
||||
userSelection: boolean = false,
|
||||
newLabel: ?string): Promise<*> {
|
||||
userSelection = false,
|
||||
newLabel?: string): Promise<any> {
|
||||
|
||||
logger.debug(`setAudioOutputDevice: ${String(newLabel)}[${newId}]`);
|
||||
|
||||
|
@ -275,7 +284,7 @@ export function setAudioOutputDeviceId(
|
|||
|
||||
return JitsiMeetJS.mediaDevices.setAudioOutputDevice(newId)
|
||||
.then(() => {
|
||||
const newSettings = {
|
||||
const newSettings: Partial<ISettingsState> = {
|
||||
audioOutputDeviceId: newId,
|
||||
userSelectedAudioOutputDeviceId: undefined,
|
||||
userSelectedAudioOutputDeviceLabel: undefined
|
|
@ -29,9 +29,9 @@ const DEFAULT_STATE: IDevicesState = {
|
|||
|
||||
export interface IDevicesState {
|
||||
availableDevices: {
|
||||
audioInput: MediaDeviceInfo[];
|
||||
audioOutput: MediaDeviceInfo[];
|
||||
videoInput: MediaDeviceInfo[];
|
||||
audioInput?: MediaDeviceInfo[];
|
||||
audioOutput?: MediaDeviceInfo[];
|
||||
videoInput?: MediaDeviceInfo[];
|
||||
};
|
||||
pendingRequests: Object[];
|
||||
permissions: {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import { UPDATE_FLAGS } from './actionTypes';
|
||||
|
||||
/**
|
|
@ -1,7 +1,7 @@
|
|||
// @flow
|
||||
|
||||
// @ts-ignore
|
||||
import { getAppProp } from '../app';
|
||||
import { toState } from '../redux';
|
||||
import { IStateful } from '../app/types';
|
||||
import { toState } from '../redux/functions';
|
||||
|
||||
/**
|
||||
* Gets the value of a specific feature flag.
|
||||
|
@ -14,11 +14,11 @@ import { toState } from '../redux';
|
|||
* @returns {*} The value of the specified React {@code Component} prop of the
|
||||
* currently mounted {@code App}.
|
||||
*/
|
||||
export function getFeatureFlag(stateful: Function | Object, flag: string, defaultValue: any) {
|
||||
export function getFeatureFlag(stateful: IStateful, flag: string, defaultValue?: any) {
|
||||
const state = toState(stateful)['features/base/flags'];
|
||||
|
||||
if (state) {
|
||||
const value = state[flag];
|
||||
const value = state[flag as keyof typeof state];
|
||||
|
||||
if (typeof value !== 'undefined') {
|
||||
return value;
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import { ADD_KNOWN_DOMAINS } from './actionTypes';
|
||||
|
||||
/**
|
|
@ -1,10 +1,10 @@
|
|||
// @flow
|
||||
|
||||
// @ts-ignore
|
||||
import { getDefaultURL } from '../../app/functions';
|
||||
import { APP_WILL_MOUNT } from '../app';
|
||||
import { SET_ROOM } from '../conference';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
import { parseURIString } from '../util';
|
||||
import { IStore } from '../../app/types';
|
||||
import { APP_WILL_MOUNT } from '../app/actionTypes';
|
||||
import { SET_ROOM } from '../conference/actionTypes';
|
||||
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
|
||||
import { parseURIString } from '../util/uri';
|
||||
|
||||
import { addKnownDomains } from './actions';
|
||||
|
||||
|
@ -32,10 +32,10 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
* @private
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function _appWillMount({ dispatch, getState }) {
|
||||
function _appWillMount({ dispatch, getState }: IStore) {
|
||||
const defaultURL = parseURIString(getDefaultURL(getState));
|
||||
|
||||
dispatch(addKnownDomains(defaultURL.host));
|
||||
dispatch(addKnownDomains(defaultURL?.host));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,7 +46,7 @@ function _appWillMount({ dispatch, getState }) {
|
|||
* @private
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function _setRoom({ dispatch, getState }) {
|
||||
function _setRoom({ dispatch, getState }: IStore) {
|
||||
const { locationURL } = getState()['features/base/connection'];
|
||||
let host;
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
/* @flow */
|
||||
|
||||
import { toState } from '../redux';
|
||||
import { getPropertyValue } from '../settings';
|
||||
import { IStateful } from '../app/types';
|
||||
import { toState } from '../redux/functions';
|
||||
import { getPropertyValue } from '../settings/functions.any';
|
||||
|
||||
import { VIDEO_MUTISM_AUTHORITY } from './constants';
|
||||
|
||||
|
@ -32,7 +31,7 @@ const START_WITH_AUDIO_VIDEO_MUTED_SOURCES = {
|
|||
* {@code getState} function.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isAudioMuted(stateful: Function | Object) {
|
||||
export function isAudioMuted(stateful: IStateful) {
|
||||
return Boolean(toState(stateful)['features/base/media'].audio.muted);
|
||||
}
|
||||
|
||||
|
@ -43,7 +42,7 @@ export function isAudioMuted(stateful: Function | Object) {
|
|||
* {@code getState} function.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isVideoMutedByAudioOnly(stateful: Function | Object) {
|
||||
export function isVideoMutedByAudioOnly(stateful: IStateful) {
|
||||
return (
|
||||
_isVideoMutedByAuthority(stateful, VIDEO_MUTISM_AUTHORITY.AUDIO_ONLY));
|
||||
}
|
||||
|
@ -60,7 +59,7 @@ export function isVideoMutedByAudioOnly(stateful: Function | Object) {
|
|||
* {@code videoMutismAuthority}, then {@code true}; otherwise, {@code false}.
|
||||
*/
|
||||
function _isVideoMutedByAuthority(
|
||||
stateful: Function | Object,
|
||||
stateful: IStateful,
|
||||
videoMutismAuthority: number) {
|
||||
const { muted } = toState(stateful)['features/base/media'].video;
|
||||
|
||||
|
@ -74,7 +73,7 @@ function _isVideoMutedByAuthority(
|
|||
* @param {Object|Function} stateful - The redux state object or {@code getState} function.
|
||||
* @returns {boolean} - The computed startWithAudioMuted value that will be used.
|
||||
*/
|
||||
export function getStartWithAudioMuted(stateful: Object | Function) {
|
||||
export function getStartWithAudioMuted(stateful: IStateful) {
|
||||
return Boolean(getPropertyValue(stateful, 'startWithAudioMuted', START_WITH_AUDIO_VIDEO_MUTED_SOURCES));
|
||||
}
|
||||
|
||||
|
@ -84,7 +83,7 @@ export function getStartWithAudioMuted(stateful: Object | Function) {
|
|||
* @param {Object|Function} stateful - The redux state object or {@code getState} function.
|
||||
* @returns {boolean} - The computed startWithVideoMuted value that will be used.
|
||||
*/
|
||||
export function getStartWithVideoMuted(stateful: Object | Function) {
|
||||
export function getStartWithVideoMuted(stateful: IStateful) {
|
||||
return Boolean(getPropertyValue(stateful, 'startWithVideoMuted', START_WITH_AUDIO_VIDEO_MUTED_SOURCES));
|
||||
}
|
||||
|
||||
|
@ -94,7 +93,7 @@ export function getStartWithVideoMuted(stateful: Object | Function) {
|
|||
* @param {Function|Object} stateful - The redux store, state, or {@code getState} function.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isVideoMuted(stateful: Function | Object) {
|
||||
export function isVideoMuted(stateful: IStateful) {
|
||||
return Boolean(toState(stateful)['features/base/media'].video.muted);
|
||||
}
|
||||
|
||||
|
@ -105,7 +104,7 @@ export function isVideoMuted(stateful: Function | Object) {
|
|||
* {@code getState} function.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isVideoMutedByUser(stateful: Function | Object) {
|
||||
export function isVideoMutedByUser(stateful: IStateful) {
|
||||
return _isVideoMutedByAuthority(stateful, VIDEO_MUTISM_AUTHORITY.USER);
|
||||
}
|
||||
|
||||
|
@ -120,7 +119,7 @@ export function isVideoMutedByUser(stateful: Function | Object) {
|
|||
* otherwise, false.
|
||||
*/
|
||||
export function shouldRenderVideoTrack(
|
||||
videoTrack: ?{ muted: boolean, videoStarted: boolean },
|
||||
videoTrack: { muted: boolean; videoStarted: boolean; },
|
||||
waitForVideoStarted: boolean) {
|
||||
return (
|
||||
videoTrack
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import { getLogger } from '../logging/functions';
|
||||
|
||||
export default getLogger('features/base/media');
|
|
@ -80,16 +80,16 @@ export function getActiveSpeakersToBeDisplayed(stateful: IStateful) {
|
|||
}
|
||||
let availableSlotsForActiveSpeakers = visibleRemoteParticipants.size;
|
||||
|
||||
if (activeSpeakers.has(dominantSpeaker)) {
|
||||
activeSpeakers.delete(dominantSpeaker);
|
||||
if (activeSpeakers.has(dominantSpeaker ?? '')) {
|
||||
activeSpeakers.delete(dominantSpeaker ?? '');
|
||||
}
|
||||
|
||||
// Add dominant speaker to the beginning of the list (not including self) since the active speaker list is always
|
||||
// alphabetically sorted.
|
||||
if (dominantSpeaker && dominantSpeaker !== getLocalParticipant(state).id) {
|
||||
if (dominantSpeaker && dominantSpeaker !== getLocalParticipant(state)?.id) {
|
||||
const updatedSpeakers = Array.from(activeSpeakers);
|
||||
|
||||
updatedSpeakers.splice(0, 0, [ dominantSpeaker, getParticipantById(state, dominantSpeaker)?.name ]);
|
||||
updatedSpeakers.splice(0, 0, [ dominantSpeaker, getParticipantById(state, dominantSpeaker)?.name ?? '' ]);
|
||||
activeSpeakers = new Map(updatedSpeakers);
|
||||
}
|
||||
|
||||
|
@ -359,11 +359,11 @@ export function getParticipantDisplayName(stateful: IStateful, id: string): stri
|
|||
}
|
||||
|
||||
if (participant.local) {
|
||||
return defaultLocalDisplayName;
|
||||
return defaultLocalDisplayName ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
return defaultRemoteDisplayName;
|
||||
return defaultRemoteDisplayName ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -439,7 +439,7 @@ export function getPinnedParticipant(stateful: IStateful) {
|
|||
|
||||
if (stageFilmstrip) {
|
||||
const { activeParticipants } = state['features/filmstrip'];
|
||||
const id = activeParticipants.find((p: Participant) => p.pinned)?.participantId;
|
||||
const id = activeParticipants.find(p => p.pinned)?.participantId;
|
||||
|
||||
return id ? getParticipantById(stateful, id) : undefined;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ export interface Participant {
|
|||
export interface LocalParticipant extends Participant {
|
||||
audioOutputDeviceId?: string;
|
||||
cameraDeviceId?: string;
|
||||
jwtId?: string;
|
||||
micDeviceId?: string;
|
||||
startWithAudioMuted?: boolean;
|
||||
startWithVideoMuted?: boolean;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import _ from 'lodash';
|
||||
import { connect as reduxConnect } from 'react-redux';
|
||||
|
||||
import { IState } from '../../app/types';
|
||||
import { IStateful } from '../app/types';
|
||||
|
||||
/**
|
||||
|
@ -135,7 +136,7 @@ function _set<T extends Object>(
|
|||
* returned.
|
||||
* @returns {Object} The redux state.
|
||||
*/
|
||||
export function toState(stateful: IStateful) {
|
||||
export function toState(stateful: IStateful): IState {
|
||||
if (stateful) {
|
||||
if (typeof stateful === 'function') {
|
||||
return stateful();
|
||||
|
@ -149,5 +150,6 @@ export function toState(stateful: IStateful) {
|
|||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
return stateful;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import _ from 'lodash';
|
||||
|
||||
import MiddlewareRegistry from './MiddlewareRegistry';
|
|
@ -1,4 +1,5 @@
|
|||
import { SETTINGS_UPDATED } from './actionTypes';
|
||||
import { ISettingsState } from './reducer';
|
||||
|
||||
/**
|
||||
* Create an action for when the settings are updated.
|
||||
|
@ -23,7 +24,7 @@ import { SETTINGS_UPDATED } from './actionTypes';
|
|||
* }
|
||||
* }}
|
||||
*/
|
||||
export function updateSettings(settings) {
|
||||
export function updateSettings(settings: Partial<ISettingsState>) {
|
||||
return {
|
||||
type: SETTINGS_UPDATED,
|
||||
settings
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
/**
|
||||
* The default server URL to open if no other was specified.
|
||||
*/
|
|
@ -1,10 +1,14 @@
|
|||
// @flow
|
||||
import { CONFIG_WHITELIST } from '../config';
|
||||
import { getParticipantCount } from '../participants';
|
||||
import { toState } from '../redux';
|
||||
import { parseURLParams } from '../util';
|
||||
import { IState } from '../../app/types';
|
||||
import { IStateful } from '../app/types';
|
||||
import CONFIG_WHITELIST from '../config/configWhitelist';
|
||||
import { IConfigState } from '../config/reducer';
|
||||
import { IJwtState } from '../jwt/reducer';
|
||||
import { getParticipantCount } from '../participants/functions';
|
||||
import { toState } from '../redux/functions';
|
||||
import { parseURLParams } from '../util/parseURLParams';
|
||||
|
||||
import { DEFAULT_SERVER_URL } from './constants';
|
||||
import { ISettingsState } from './reducer';
|
||||
|
||||
/**
|
||||
* Returns the effective value of a configuration/preference/setting by applying
|
||||
|
@ -23,9 +27,9 @@ import { DEFAULT_SERVER_URL } from './constants';
|
|||
* @returns {any}
|
||||
*/
|
||||
export function getPropertyValue(
|
||||
stateful: Object | Function,
|
||||
stateful: IStateful,
|
||||
propertyName: string,
|
||||
sources?: Object
|
||||
sources?: any
|
||||
) {
|
||||
// Default values don't play nicely with partial objects and we want to make
|
||||
// the function easy to use without exhaustively defining all flags:
|
||||
|
@ -45,10 +49,10 @@ export function getPropertyValue(
|
|||
|
||||
// jwt
|
||||
if (sources.jwt) {
|
||||
const value = state['features/base/jwt'][propertyName];
|
||||
const value = state['features/base/jwt'][propertyName as keyof IJwtState];
|
||||
|
||||
if (typeof value !== 'undefined') {
|
||||
return value[propertyName];
|
||||
return value[propertyName as keyof typeof value];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +60,7 @@ export function getPropertyValue(
|
|||
if (sources.urlParams) {
|
||||
if (CONFIG_WHITELIST.indexOf(propertyName) !== -1) {
|
||||
const urlParams
|
||||
= parseURLParams(state['features/base/connection'].locationURL);
|
||||
= parseURLParams(state['features/base/connection'].locationURL ?? '');
|
||||
const value = urlParams[`config.${propertyName}`];
|
||||
|
||||
if (typeof value !== 'undefined') {
|
||||
|
@ -67,7 +71,7 @@ export function getPropertyValue(
|
|||
|
||||
// settings
|
||||
if (sources.settings) {
|
||||
const value = state['features/base/settings'][propertyName];
|
||||
const value = state['features/base/settings'][propertyName as keyof ISettingsState];
|
||||
|
||||
if (typeof value !== 'undefined') {
|
||||
return value;
|
||||
|
@ -76,7 +80,7 @@ export function getPropertyValue(
|
|||
|
||||
// config
|
||||
if (sources.config) {
|
||||
const value = state['features/base/config'][propertyName];
|
||||
const value = state['features/base/config'][propertyName as keyof IConfigState];
|
||||
|
||||
if (typeof value !== 'undefined') {
|
||||
return value;
|
||||
|
@ -93,7 +97,7 @@ export function getPropertyValue(
|
|||
* {@code getState} function.
|
||||
* @returns {string} - The currently configured server URL.
|
||||
*/
|
||||
export function getServerURL(stateful: Object | Function) {
|
||||
export function getServerURL(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
|
||||
return state['features/base/settings'].serverURL || DEFAULT_SERVER_URL;
|
||||
|
@ -107,7 +111,7 @@ export function getServerURL(stateful: Object | Function) {
|
|||
* {@code getState} function.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getUserSelectedCameraDeviceId(stateful: Object | Function) {
|
||||
export function getUserSelectedCameraDeviceId(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
const {
|
||||
userSelectedCameraDeviceId,
|
||||
|
@ -135,7 +139,7 @@ export function getUserSelectedCameraDeviceId(stateful: Object | Function) {
|
|||
* {@code getState} function.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getUserSelectedMicDeviceId(stateful: Object | Function) {
|
||||
export function getUserSelectedMicDeviceId(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
const {
|
||||
userSelectedMicDeviceId,
|
||||
|
@ -163,7 +167,7 @@ export function getUserSelectedMicDeviceId(stateful: Object | Function) {
|
|||
* {@code getState} function.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getUserSelectedOutputDeviceId(stateful: Object | Function) {
|
||||
export function getUserSelectedOutputDeviceId(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
const {
|
||||
userSelectedAudioOutputDeviceId,
|
||||
|
@ -202,13 +206,19 @@ export function getUserSelectedOutputDeviceId(stateful: Object | Function) {
|
|||
* @private
|
||||
* @returns {string} The preferred device ID to use for media.
|
||||
*/
|
||||
function _getUserSelectedDeviceId(options) {
|
||||
function _getUserSelectedDeviceId(options: {
|
||||
availableDevices: MediaDeviceInfo[] | undefined;
|
||||
matchRegex?: RegExp;
|
||||
replacement?: string;
|
||||
userSelectedDeviceId?: string;
|
||||
userSelectedDeviceLabel?: string;
|
||||
}) {
|
||||
const {
|
||||
availableDevices,
|
||||
matchRegex,
|
||||
matchRegex = '',
|
||||
userSelectedDeviceId,
|
||||
userSelectedDeviceLabel,
|
||||
replacement
|
||||
replacement = ''
|
||||
} = options;
|
||||
|
||||
// If there is no label at all, there is no need to fall back to checking
|
||||
|
@ -217,7 +227,7 @@ function _getUserSelectedDeviceId(options) {
|
|||
return userSelectedDeviceId;
|
||||
}
|
||||
|
||||
const foundMatchingBasedonDeviceId = availableDevices.find(
|
||||
const foundMatchingBasedonDeviceId = availableDevices?.find(
|
||||
candidate => candidate.deviceId === userSelectedDeviceId);
|
||||
|
||||
// Prioritize matching the deviceId
|
||||
|
@ -228,7 +238,7 @@ function _getUserSelectedDeviceId(options) {
|
|||
const strippedDeviceLabel
|
||||
= matchRegex ? userSelectedDeviceLabel.replace(matchRegex, replacement)
|
||||
: userSelectedDeviceLabel;
|
||||
const foundMatchBasedOnLabel = availableDevices.find(candidate => {
|
||||
const foundMatchBasedOnLabel = availableDevices?.find(candidate => {
|
||||
const { label } = candidate;
|
||||
|
||||
if (!label) {
|
||||
|
@ -253,7 +263,7 @@ function _getUserSelectedDeviceId(options) {
|
|||
* @param {Object} state - The state of the application.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function shouldHideShareAudioHelper(state: Object): boolean {
|
||||
export function shouldHideShareAudioHelper(state: IState): boolean | undefined {
|
||||
|
||||
return state['features/base/settings'].hideShareAudioHelper;
|
||||
}
|
||||
|
@ -264,7 +274,7 @@ export function shouldHideShareAudioHelper(state: Object): boolean {
|
|||
* @param {Object} state - Redux state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function shouldHideSelfView(state: Object) {
|
||||
export function shouldHideSelfView(state: IState) {
|
||||
return getParticipantCount(state) === 1 ? false : getHideSelfView(state);
|
||||
}
|
||||
|
||||
|
@ -274,6 +284,6 @@ export function shouldHideSelfView(state: Object) {
|
|||
* @param {Object} state - Redux state.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function getHideSelfView(state: Object) {
|
||||
export function getHideSelfView(state: IState) {
|
||||
return state['features/base/config'].disableSelfView || state['features/base/settings'].disableSelfView;
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import { NativeModules } from 'react-native';
|
||||
import DefaultPreference from 'react-native-default-preference';
|
||||
|
||||
|
@ -31,6 +29,6 @@ export function handleCallIntegrationChange(disabled: boolean) {
|
|||
* @returns {void}
|
||||
*/
|
||||
export function handleCrashReportingChange(disabled: boolean) {
|
||||
DefaultPreference.setName('jitsi-default-preferences').then(
|
||||
DefaultPreference.setName('jitsi-default-preferences').then( // @ts-ignore
|
||||
DefaultPreference.set('isCrashReportingDisabled', disabled.toString()));
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
// @flow
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { IState } from '../../app/types';
|
||||
|
||||
export * from './functions.any';
|
||||
|
||||
|
@ -8,7 +9,7 @@ export * from './functions.any';
|
|||
* @param {Object} state - The state of the application.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function getCurrentCameraDeviceId(state: Object) {
|
||||
export function getCurrentCameraDeviceId(state: IState) {
|
||||
return getDeviceIdByType(state, 'isVideoTrack');
|
||||
}
|
||||
|
||||
|
@ -18,7 +19,7 @@ export function getCurrentCameraDeviceId(state: Object) {
|
|||
* @param {Object} state - The state of the application.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function getCurrentMicDeviceId(state: Object) {
|
||||
export function getCurrentMicDeviceId(state: IState) {
|
||||
return getDeviceIdByType(state, 'isAudioTrack');
|
||||
}
|
||||
|
||||
|
@ -28,7 +29,7 @@ export function getCurrentMicDeviceId(state: Object) {
|
|||
* @param {Object} state - The state of the application.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function getCurrentOutputDeviceId(state: Object) {
|
||||
export function getCurrentOutputDeviceId(state: IState) {
|
||||
return state['features/base/settings'].audioOutputDeviceId;
|
||||
}
|
||||
|
||||
|
@ -39,11 +40,11 @@ export function getCurrentOutputDeviceId(state: Object) {
|
|||
* @param {string} isType - Can be 'isVideoTrack' | 'isAudioTrack'.
|
||||
* @returns {string}
|
||||
*/
|
||||
function getDeviceIdByType(state: Object, isType: string) {
|
||||
function getDeviceIdByType(state: IState, isType: string) {
|
||||
const [ deviceId ] = state['features/base/tracks']
|
||||
.map(t => t.jitsiTrack)
|
||||
.filter(t => t && t.isLocal() && t[isType]())
|
||||
.map(t => t.getDeviceId());
|
||||
.map(t => t.jitsiTrack)
|
||||
.filter(t => t?.isLocal() && t[isType as keyof typeof t]())
|
||||
.map(t => t.getDeviceId());
|
||||
|
||||
return deviceId || '';
|
||||
}
|
||||
|
@ -54,7 +55,7 @@ function getDeviceIdByType(state: Object, isType: string) {
|
|||
* @param {Object} state - The state of the application.
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getDisplayName(state: Object): string {
|
||||
export function getDisplayName(state: IState): string {
|
||||
return state['features/base/settings'].displayName || '';
|
||||
}
|
||||
|
||||
|
@ -66,8 +67,8 @@ export function getDisplayName(state: Object): string {
|
|||
* @param {boolean} disabled - Whether call integration is disabled or not.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function handleCallIntegrationChange(disabled: boolean) { // eslint-disable-line no-unused-vars
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function, require-jsdoc
|
||||
export function handleCallIntegrationChange(disabled: boolean) { }
|
||||
|
||||
/**
|
||||
* Handles changes to the `disableCrashReporting` setting.
|
||||
|
@ -76,5 +77,5 @@ export function handleCallIntegrationChange(disabled: boolean) { // eslint-disab
|
|||
* @param {boolean} disabled - Whether crash reporting is disabled or not.
|
||||
* @returns {void}
|
||||
*/
|
||||
export function handleCrashReportingChange(disabled: boolean) { // eslint-disable-line no-unused-vars
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function, require-jsdoc
|
||||
export function handleCrashReportingChange(disabled: boolean) { }
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import { getLogger } from '../logging/functions';
|
||||
|
||||
export default getLogger('features/base/settings');
|
|
@ -1,19 +1,26 @@
|
|||
// @flow
|
||||
/* eslint-disable lines-around-comment */
|
||||
import _ from 'lodash';
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
import { IStore } from '../../app/types';
|
||||
import { PREJOIN_INITIALIZED } from '../../prejoin/actionTypes';
|
||||
// @ts-ignore
|
||||
import { setPrejoinPageVisibility } from '../../prejoin/actions';
|
||||
import { APP_WILL_MOUNT } from '../app';
|
||||
import { setAudioOnly } from '../audio-only';
|
||||
import { APP_WILL_MOUNT } from '../app/actionTypes';
|
||||
import { setAudioOnly } from '../audio-only/actions';
|
||||
import { SET_LOCATION_URL } from '../connection/actionTypes'; // minimize imports to avoid circular imports
|
||||
// @ts-ignore
|
||||
import { getJwtName } from '../jwt/functions';
|
||||
import { getLocalParticipant, participantUpdated } from '../participants';
|
||||
import { MiddlewareRegistry } from '../redux';
|
||||
import { parseURLParams } from '../util';
|
||||
import { participantUpdated } from '../participants/actions';
|
||||
import { getLocalParticipant } from '../participants/functions';
|
||||
import MiddlewareRegistry from '../redux/MiddlewareRegistry';
|
||||
import { parseURLParams } from '../util/parseURLParams';
|
||||
|
||||
import { SETTINGS_UPDATED } from './actionTypes';
|
||||
import { updateSettings } from './actions';
|
||||
// @ts-ignore
|
||||
import { handleCallIntegrationChange, handleCrashReportingChange } from './functions';
|
||||
import { ISettingsState } from './reducer';
|
||||
|
||||
|
||||
/**
|
||||
|
@ -57,7 +64,7 @@ MiddlewareRegistry.register(store => next => action => {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _initializeShowPrejoin({ dispatch, getState }) {
|
||||
function _initializeShowPrejoin({ dispatch, getState }: IStore) {
|
||||
const { userSelectedSkipPrejoin } = getState()['features/base/settings'];
|
||||
|
||||
if (userSelectedSkipPrejoin) {
|
||||
|
@ -72,7 +79,7 @@ function _initializeShowPrejoin({ dispatch, getState }) {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _initializeCallIntegration({ getState }) {
|
||||
function _initializeCallIntegration({ getState }: IStore) {
|
||||
const { disableCallIntegration } = getState()['features/base/settings'];
|
||||
|
||||
if (typeof disableCallIntegration === 'boolean') {
|
||||
|
@ -88,7 +95,7 @@ function _initializeCallIntegration({ getState }) {
|
|||
* @param {string} settingsField - The name of the settings field to map.
|
||||
* @returns {string}
|
||||
*/
|
||||
function _mapSettingsFieldToParticipant(settingsField) {
|
||||
function _mapSettingsFieldToParticipant(settingsField: string) {
|
||||
switch (settingsField) {
|
||||
case 'displayName':
|
||||
return 'name';
|
||||
|
@ -104,7 +111,9 @@ function _mapSettingsFieldToParticipant(settingsField) {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _maybeHandleCallIntegrationChange({ settings: { disableCallIntegration } }) {
|
||||
function _maybeHandleCallIntegrationChange({ settings: { disableCallIntegration } }: {
|
||||
settings: Partial<ISettingsState>;
|
||||
}) {
|
||||
if (typeof disableCallIntegration === 'boolean') {
|
||||
handleCallIntegrationChange(disableCallIntegration);
|
||||
}
|
||||
|
@ -117,7 +126,9 @@ function _maybeHandleCallIntegrationChange({ settings: { disableCallIntegration
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _maybeCrashReportingChange({ settings: { disableCrashReporting } }) {
|
||||
function _maybeCrashReportingChange({ settings: { disableCrashReporting } }: {
|
||||
settings: Partial<ISettingsState>;
|
||||
}) {
|
||||
if (typeof disableCrashReporting === 'boolean') {
|
||||
handleCrashReportingChange(disableCrashReporting);
|
||||
}
|
||||
|
@ -132,8 +143,8 @@ function _maybeCrashReportingChange({ settings: { disableCrashReporting } }) {
|
|||
* @returns {void}
|
||||
*/
|
||||
function _maybeSetAudioOnly(
|
||||
{ dispatch },
|
||||
{ settings: { startAudioOnly } }) {
|
||||
{ dispatch }: IStore,
|
||||
{ settings: { startAudioOnly } }: { settings: Partial<ISettingsState>; }) {
|
||||
if (typeof startAudioOnly === 'boolean') {
|
||||
dispatch(setAudioOnly(startAudioOnly));
|
||||
}
|
||||
|
@ -146,7 +157,7 @@ function _maybeSetAudioOnly(
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _maybeUpdateDisplayName({ dispatch, getState }) {
|
||||
function _maybeUpdateDisplayName({ dispatch, getState }: IStore) {
|
||||
const state = getState();
|
||||
const hasJwt = Boolean(state['features/base/jwt'].jwt);
|
||||
|
||||
|
@ -169,7 +180,7 @@ function _maybeUpdateDisplayName({ dispatch, getState }) {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _updateLocalParticipant({ dispatch, getState }, action) {
|
||||
function _updateLocalParticipant({ dispatch, getState }: IStore, action: AnyAction) {
|
||||
const { settings } = action;
|
||||
const localParticipant = getLocalParticipant(getState());
|
||||
const newLocalParticipant = {
|
||||
|
@ -178,12 +189,15 @@ function _updateLocalParticipant({ dispatch, getState }, action) {
|
|||
|
||||
for (const key in settings) {
|
||||
if (settings.hasOwnProperty(key)) {
|
||||
newLocalParticipant[_mapSettingsFieldToParticipant(key)]
|
||||
newLocalParticipant[_mapSettingsFieldToParticipant(key) as keyof typeof newLocalParticipant]
|
||||
= settings[key];
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(participantUpdated(newLocalParticipant));
|
||||
dispatch(participantUpdated({
|
||||
...newLocalParticipant,
|
||||
id: newLocalParticipant.id ?? ''
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,9 +208,9 @@ function _updateLocalParticipant({ dispatch, getState }, action) {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _updateLocalParticipantFromUrl({ dispatch, getState }) {
|
||||
function _updateLocalParticipantFromUrl({ dispatch, getState }: IStore) {
|
||||
const urlParams
|
||||
= parseURLParams(getState()['features/base/connection'].locationURL);
|
||||
= parseURLParams(getState()['features/base/connection'].locationURL ?? '');
|
||||
const urlEmail = urlParams['userInfo.email'];
|
||||
const urlDisplayName = urlParams['userInfo.displayName'];
|
||||
|
|
@ -52,18 +52,18 @@ const DEFAULT_STATE: ISettingsState = {
|
|||
|
||||
export interface ISettingsState {
|
||||
audioOutputDeviceId?: string | boolean;
|
||||
avatarURL?: string | boolean;
|
||||
avatarURL?: string;
|
||||
cameraDeviceId?: string | boolean;
|
||||
disableCallIntegration?: boolean;
|
||||
disableCrashReporting?: boolean;
|
||||
disableP2P?: boolean;
|
||||
disableSelfView?: boolean;
|
||||
displayName?: string | boolean;
|
||||
email?: string | boolean;
|
||||
displayName?: string;
|
||||
email?: string;
|
||||
hideShareAudioHelper?: boolean;
|
||||
localFlipX?: boolean;
|
||||
micDeviceId?: string | boolean;
|
||||
serverURL?: string | boolean;
|
||||
serverURL?: string;
|
||||
soundsIncomingMessage?: boolean;
|
||||
soundsParticipantJoined?: boolean;
|
||||
soundsParticipantKnocking?: boolean;
|
||||
|
@ -73,12 +73,12 @@ export interface ISettingsState {
|
|||
startAudioOnly?: boolean;
|
||||
startWithAudioMuted?: boolean;
|
||||
startWithVideoMuted?: boolean;
|
||||
userSelectedAudioOutputDeviceId?: string | boolean;
|
||||
userSelectedAudioOutputDeviceLabel?: string | boolean;
|
||||
userSelectedCameraDeviceId?: string | boolean;
|
||||
userSelectedCameraDeviceLabel?: string | boolean;
|
||||
userSelectedMicDeviceId?: string | boolean;
|
||||
userSelectedMicDeviceLabel?: string | boolean;
|
||||
userSelectedAudioOutputDeviceId?: string;
|
||||
userSelectedAudioOutputDeviceLabel?: string;
|
||||
userSelectedCameraDeviceId?: string;
|
||||
userSelectedCameraDeviceLabel?: string;
|
||||
userSelectedMicDeviceId?: string;
|
||||
userSelectedMicDeviceLabel?: string;
|
||||
userSelectedNotifications?: {
|
||||
[key: string]: boolean;
|
||||
} | boolean;
|
||||
|
@ -97,6 +97,7 @@ const filterSubtree: ISettingsState = {};
|
|||
Object.keys(DEFAULT_STATE).forEach(key => {
|
||||
const key1 = key as keyof typeof filterSubtree;
|
||||
|
||||
// @ts-ignore
|
||||
filterSubtree[key1] = true;
|
||||
});
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import {
|
|||
|
||||
interface ITrack {
|
||||
isReceivingData: boolean;
|
||||
jitsiTrack: Object;
|
||||
jitsiTrack: any;
|
||||
lastMediaEvent?: string;
|
||||
local: boolean;
|
||||
mediaType: string;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// @flow
|
||||
|
||||
import { getLogger } from '../logging/functions';
|
||||
|
||||
export default getLogger('features/base/util');
|
|
@ -24,7 +24,7 @@ const blacklist = [ '__proto__', 'constructor', 'prototype' ];
|
|||
export function parseURLParams(
|
||||
url: URL | string,
|
||||
dontParse = false,
|
||||
source = 'hash'): Object {
|
||||
source = 'hash') {
|
||||
if (typeof url === 'string') {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
url = new URL(url);
|
||||
|
|
|
@ -330,7 +330,7 @@ export function parseStandardURIString(str: string) {
|
|||
* search: string
|
||||
* }}
|
||||
*/
|
||||
export function parseURIString(uri?: string) {
|
||||
export function parseURIString(uri?: string): any {
|
||||
if (typeof uri !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
|
|
|
@ -1276,7 +1276,7 @@ function _mapStateToProps(state: IState, ownProps: any): Object {
|
|||
|
||||
const { gifUrl: gifSrc } = getGifForParticipant(state, id);
|
||||
const mode = getGifDisplayMode(state);
|
||||
const participantId = isLocal ? getLocalParticipant(state).id : participantID;
|
||||
const participantId = isLocal ? getLocalParticipant(state)?.id : participantID;
|
||||
|
||||
return {
|
||||
_audioTrack,
|
||||
|
|
|
@ -50,7 +50,7 @@ const AbstractPollAnswer = (Component: ComponentType<AbstractProps>) => (props:
|
|||
|
||||
const poll: Poll = useSelector((state: IState) => state['features/polls'].polls[pollId]);
|
||||
|
||||
const { id: localId } = useSelector(getLocalParticipant);
|
||||
const { id: localId } = useSelector(getLocalParticipant) ?? { id: '' };
|
||||
|
||||
const [ checkBoxStates, setCheckBoxState ] = useState(() => {
|
||||
if (poll.lastVote !== null) {
|
||||
|
|
|
@ -33,7 +33,7 @@ const PollAnswer = (props: AbstractProps) => {
|
|||
<>
|
||||
<Text style = { dialogStyles.questionText } >{ poll.question }</Text>
|
||||
<Text style = { dialogStyles.questionOwnerText } >{
|
||||
t('polls.by', { name: localParticipant.name })
|
||||
t('polls.by', { name: localParticipant?.name })
|
||||
}
|
||||
</Text>
|
||||
<View style = { chatStyles.answerContent }>
|
||||
|
|
|
@ -5,7 +5,6 @@ import clsx from 'clsx';
|
|||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
|
||||
import { createReactionMenuEvent, createToolbarEvent } from '../../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../../analytics/functions';
|
||||
|
@ -53,7 +52,7 @@ interface Props extends WithTranslation {
|
|||
/**
|
||||
* The ID of the local participant.
|
||||
*/
|
||||
_localParticipantID: String;
|
||||
_localParticipantID?: string;
|
||||
|
||||
/**
|
||||
* Whether or not the local participant's hand is raised.
|
||||
|
@ -241,7 +240,7 @@ function mapStateToProps(state: IState) {
|
|||
const localParticipant = getLocalParticipant(state);
|
||||
|
||||
return {
|
||||
_localParticipantID: localParticipant.id,
|
||||
_localParticipantID: localParticipant?.id,
|
||||
_isMobile: isMobileBrowser(),
|
||||
_isGifEnabled: isGifEnabled(state),
|
||||
_isGifMenuVisible: isGifsMenuOpen(state),
|
||||
|
@ -258,10 +257,7 @@ function mapStateToProps(state: IState) {
|
|||
function mapDispatchToProps(dispatch: IStore['dispatch']) {
|
||||
return {
|
||||
dispatch,
|
||||
...bindActionCreators(
|
||||
{
|
||||
_dockToolbox: dockToolbox
|
||||
}, dispatch)
|
||||
_dockToolbox: (dock: boolean) => dispatch(dockToolbox(dock))
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -72,8 +72,8 @@ export async function sendReactionsWebhook(state: IState, reactions: Array<strin
|
|||
sessionId: conference.sessionId,
|
||||
submitted: Date.now(),
|
||||
reactions,
|
||||
participantId: localParticipant.jwtId,
|
||||
participantName: localParticipant.name,
|
||||
participantId: localParticipant?.jwtId,
|
||||
participantName: localParticipant?.name,
|
||||
participantJid: jid
|
||||
};
|
||||
|
||||
|
|
|
@ -204,7 +204,7 @@ MiddlewareRegistry.register((store: IStore) => (next: Function) => (action: any)
|
|||
const { disableReactionsModeration } = state['features/base/config'];
|
||||
|
||||
const customActions = [ 'notify.reactionSounds' ];
|
||||
const customFunctions = [ () => dispatch(updateSettings({
|
||||
const customFunctions: Function[] = [ () => dispatch(updateSettings({
|
||||
soundsReactions: false
|
||||
})) ];
|
||||
|
||||
|
|
|
@ -303,7 +303,7 @@ function _mapStateToProps(state: IState, ownProps: Partial<Props>) {
|
|||
_showLocalVideoFlipButton: !disableLocalVideoFlip && videoTrack?.videoType !== 'desktop',
|
||||
_showHideSelfViewButton: showHideSelfViewButton,
|
||||
_overflowDrawer: overflowDrawer,
|
||||
_localParticipantId: localParticipant.id,
|
||||
_localParticipantId: localParticipant?.id,
|
||||
_showConnectionInfo: showConnectionInfo,
|
||||
_showPinToStage: isStageFilmstripAvailable(state)
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue