mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2025-12-30 03:12:29 +00:00
ref(TS) Convert some native components to TS (#13307)
This commit is contained in:
19
package-lock.json
generated
19
package-lock.json
generated
@@ -135,6 +135,7 @@
|
||||
"@types/react-dom": "17.0.14",
|
||||
"@types/react-linkify": "1.0.1",
|
||||
"@types/react-native": "0.68.9",
|
||||
"@types/react-native-keep-awake": "2.0.3",
|
||||
"@types/react-native-video": "5.0.14",
|
||||
"@types/react-redux": "7.1.24",
|
||||
"@types/react-window": "1.8.5",
|
||||
@@ -5826,6 +5827,15 @@
|
||||
"@types/react": "^17"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-native-keep-awake": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native-keep-awake/-/react-native-keep-awake-2.0.3.tgz",
|
||||
"integrity": "sha512-0C4bUlGPHRpplbn+YnX2UO0/2joa0dhCPumas2fielGNJkS1FTJOrw9jFo4B0+LOtmsepXiy/ANTF/on0b2Ddw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react-native-video": {
|
||||
"version": "5.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native-video/-/react-native-video-5.0.14.tgz",
|
||||
@@ -23883,6 +23893,15 @@
|
||||
"@types/react": "^17"
|
||||
}
|
||||
},
|
||||
"@types/react-native-keep-awake": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native-keep-awake/-/react-native-keep-awake-2.0.3.tgz",
|
||||
"integrity": "sha512-0C4bUlGPHRpplbn+YnX2UO0/2joa0dhCPumas2fielGNJkS1FTJOrw9jFo4B0+LOtmsepXiy/ANTF/on0b2Ddw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-native-video": {
|
||||
"version": "5.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-native-video/-/react-native-video-5.0.14.tgz",
|
||||
|
||||
@@ -140,6 +140,7 @@
|
||||
"@types/react-dom": "17.0.14",
|
||||
"@types/react-linkify": "1.0.1",
|
||||
"@types/react-native": "0.68.9",
|
||||
"@types/react-native-keep-awake": "2.0.3",
|
||||
"@types/react-native-video": "5.0.14",
|
||||
"@types/react-redux": "7.1.24",
|
||||
"@types/react-window": "1.8.5",
|
||||
|
||||
@@ -46,6 +46,7 @@ export interface IJitsiConference {
|
||||
authenticateAndUpgradeRole: Function;
|
||||
avModerationApprove: Function;
|
||||
avModerationReject: Function;
|
||||
callUUID?: string;
|
||||
createVideoSIPGWSession: Function;
|
||||
dial: Function;
|
||||
disableAVModeration: Function;
|
||||
|
||||
@@ -170,6 +170,7 @@ export interface IConfig {
|
||||
}>;
|
||||
callDisplayName?: string;
|
||||
callFlowsEnabled?: boolean;
|
||||
callHandle?: string;
|
||||
callStatsConfigParams?: {
|
||||
additionalIDs?: {
|
||||
customerID?: string;
|
||||
@@ -191,6 +192,7 @@ export interface IConfig {
|
||||
};
|
||||
callStatsID?: string;
|
||||
callStatsSecret?: string;
|
||||
callUUID?: string;
|
||||
channelLastN?: number;
|
||||
chromeExtensionBanner?: {
|
||||
chromeExtensionsInfo?: Array<{ id: string; path: string; }>;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import statsEmitter from '../../../connection-indicator/statsEmitter';
|
||||
import { getLocalParticipant } from '../../participants/functions';
|
||||
import { isTestModeEnabled } from '../functions';
|
||||
@@ -10,7 +11,7 @@ import TestHint from './TestHint';
|
||||
/**
|
||||
* Defines the TestConnectionInfo's properties.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* The JitsiConference's connection state. It's the lib-jitsi-meet's event
|
||||
@@ -20,30 +21,30 @@ type Props = {
|
||||
* 'conference.connectionInterrupted'
|
||||
* 'conference.connectionRestored'.
|
||||
*/
|
||||
_conferenceConnectionState: string,
|
||||
_conferenceConnectionState: string;
|
||||
|
||||
/**
|
||||
* This will be a boolean converted to a string. The value will be 'true'
|
||||
* once the conference is joined (the XMPP MUC room to be specific).
|
||||
*/
|
||||
_conferenceJoinedState: string,
|
||||
_conferenceJoinedState: string;
|
||||
|
||||
/**
|
||||
* The local participant's ID. Required to be able to observe the local RTP
|
||||
* stats.
|
||||
*/
|
||||
_localUserId: string,
|
||||
_localUserId: string;
|
||||
|
||||
/**
|
||||
* The local participant's role.
|
||||
*/
|
||||
_localUserRole: string,
|
||||
_localUserRole: string;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the test mode is currently on. Otherwise the
|
||||
* TestConnectionInfo component will not render.
|
||||
*/
|
||||
_testMode: boolean
|
||||
_testMode: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,15 +65,15 @@ type State = {
|
||||
/**
|
||||
* The local download RTP bitrate.
|
||||
*/
|
||||
download: number,
|
||||
download: number;
|
||||
|
||||
/**
|
||||
* The local upload RTP bitrate.
|
||||
*/
|
||||
upload: number
|
||||
}
|
||||
}
|
||||
}
|
||||
upload: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* The component will expose some of the app state to the jitsi-meet-torture
|
||||
@@ -81,8 +82,7 @@ type State = {
|
||||
* this information, but there's no such option on React Native(maybe that's
|
||||
* a good thing).
|
||||
*/
|
||||
class TestConnectionInfo extends Component<Props, State> {
|
||||
_onStatsUpdated: Object => void;
|
||||
class TestConnectionInfo extends Component<IProps, State> {
|
||||
|
||||
/**
|
||||
* Initializes new <tt>TestConnectionInfo</tt> instance.
|
||||
@@ -90,7 +90,7 @@ class TestConnectionInfo extends Component<Props, State> {
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this._onStatsUpdated = this._onStatsUpdated.bind(this);
|
||||
@@ -114,7 +114,8 @@ class TestConnectionInfo extends Component<Props, State> {
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
_onStatsUpdated(stats = {}) {
|
||||
_onStatsUpdated(stats = { bitrate: { download: undefined,
|
||||
upload: undefined } }) {
|
||||
this.setState({
|
||||
stats: {
|
||||
bitrate: {
|
||||
@@ -143,7 +144,7 @@ class TestConnectionInfo extends Component<Props, State> {
|
||||
* @inheritdoc
|
||||
* returns {void}
|
||||
*/
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
componentDidUpdate(prevProps: IProps) {
|
||||
if (prevProps._localUserId !== this.props._localUserId) {
|
||||
statsEmitter.unsubscribeToClientStats(
|
||||
prevProps._localUserId, this._onStatsUpdated);
|
||||
@@ -175,7 +176,7 @@ class TestConnectionInfo extends Component<Props, State> {
|
||||
}
|
||||
|
||||
return (
|
||||
<Fragment accessible = { false } >
|
||||
<Fragment>
|
||||
<TestHint
|
||||
id = 'org.jitsi.meet.conference.connectionState'
|
||||
value = { this.props._conferenceConnectionState } />
|
||||
@@ -184,7 +185,7 @@ class TestConnectionInfo extends Component<Props, State> {
|
||||
value = { this.props._conferenceJoinedState } />
|
||||
<TestHint
|
||||
id = 'org.jitsi.meet.conference.grantModeratorAvailable'
|
||||
value = { true } />
|
||||
value = { 'true' } />
|
||||
<TestHint
|
||||
id = 'org.jitsi.meet.conference.localParticipantRole'
|
||||
value = { this.props._localUserRole } />
|
||||
@@ -202,9 +203,9 @@ class TestConnectionInfo extends Component<Props, State> {
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @private
|
||||
* @returns {Props}
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
const conferenceJoined
|
||||
= Boolean(state['features/base/conference'].conference);
|
||||
const localParticipant = getLocalParticipant(state);
|
||||
@@ -212,8 +213,8 @@ function _mapStateToProps(state) {
|
||||
return {
|
||||
_conferenceConnectionState: state['features/testing'].connectionState,
|
||||
_conferenceJoinedState: conferenceJoined.toString(),
|
||||
_localUserId: localParticipant?.id,
|
||||
_localUserRole: localParticipant?.role,
|
||||
_localUserId: localParticipant?.id ?? '',
|
||||
_localUserRole: localParticipant?.role ?? '',
|
||||
_testMode: isTestModeEnabled(state)
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import { Component } from 'react';
|
||||
|
||||
export default Component;
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { IReduxState } from '../../app/types';
|
||||
import isInsecureRoomName from '../../base/util/isInsecureRoomName';
|
||||
|
||||
interface IProps {
|
||||
interface IProps extends WithTranslation {
|
||||
|
||||
/**
|
||||
* True of the label should be visible.
|
||||
*/
|
||||
_visible: boolean;
|
||||
|
||||
/**
|
||||
* Function to be used to translate i18n labels.
|
||||
*/
|
||||
t: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import React, { useCallback } from 'react';
|
||||
import { TouchableOpacity } from 'react-native';
|
||||
import { useDispatch } from 'react-redux';
|
||||
@@ -19,16 +17,16 @@ import {
|
||||
LabelHitSlop
|
||||
} from './constants';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Creates a function to be invoked when the onPress of the touchables are
|
||||
* triggered.
|
||||
*/
|
||||
createOnPress: Function
|
||||
createOnPress: Function;
|
||||
}
|
||||
|
||||
const AlwaysOnLabels = ({ createOnPress }: Props) => {
|
||||
const AlwaysOnLabels = ({ createOnPress }: IProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const openHighlightDialogCallback = useCallback(() => dispatch(openHighlightDialog()), [ dispatch ]);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { useIsFocused } from '@react-navigation/native';
|
||||
import React, { useEffect } from 'react';
|
||||
import {
|
||||
@@ -8,12 +6,14 @@ import {
|
||||
Platform,
|
||||
SafeAreaView,
|
||||
StatusBar,
|
||||
View
|
||||
View,
|
||||
ViewStyle
|
||||
} from 'react-native';
|
||||
import { withSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { EdgeInsets, withSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { appNavigate } from '../../../app/actions';
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { FULLSCREEN_ENABLED, PIP_ENABLED } from '../../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../../base/flags/functions';
|
||||
import { getParticipantCount } from '../../../base/participants/functions';
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
ASPECT_RATIO_NARROW,
|
||||
ASPECT_RATIO_WIDE
|
||||
} from '../../../base/responsive-ui/constants';
|
||||
import { StyleType } from '../../../base/styles/functions.any';
|
||||
import TestConnectionInfo from '../../../base/testing/components/TestConnectionInfo';
|
||||
import { isCalendarEnabled } from '../../../calendar-sync/functions.native';
|
||||
import DisplayNameLabel from '../../../display-name/components/native/DisplayNameLabel';
|
||||
@@ -63,27 +64,27 @@ import styles from './styles';
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link Conference}.
|
||||
*/
|
||||
type Props = AbstractProps & {
|
||||
interface IProps extends AbstractProps {
|
||||
|
||||
/**
|
||||
* Application's aspect ratio.
|
||||
*/
|
||||
_aspectRatio: Symbol,
|
||||
_aspectRatio: Symbol;
|
||||
|
||||
/**
|
||||
* Whether the audio only is enabled or not.
|
||||
*/
|
||||
_audioOnlyEnabled: boolean,
|
||||
_audioOnlyEnabled: boolean;
|
||||
|
||||
/**
|
||||
* Branding styles for conference.
|
||||
*/
|
||||
_brandingStyles: Object,
|
||||
_brandingStyles: StyleType;
|
||||
|
||||
/**
|
||||
* Whether the calendar feature is enabled or not.
|
||||
*/
|
||||
_calendarEnabled: boolean,
|
||||
_calendarEnabled: boolean;
|
||||
|
||||
/**
|
||||
* The indicator which determines that we are still connecting to the
|
||||
@@ -91,101 +92,101 @@ type Props = AbstractProps & {
|
||||
* joining the room. If truthy, then an activity/loading indicator will be
|
||||
* rendered.
|
||||
*/
|
||||
_connecting: boolean,
|
||||
_connecting: boolean;
|
||||
|
||||
/**
|
||||
* Set to {@code true} when the filmstrip is currently visible.
|
||||
*/
|
||||
_filmstripVisible: boolean,
|
||||
_filmstripVisible: boolean;
|
||||
|
||||
/**
|
||||
* The indicator which determines whether fullscreen (immersive) mode is enabled.
|
||||
*/
|
||||
_fullscreenEnabled: boolean,
|
||||
_fullscreenEnabled: boolean;
|
||||
|
||||
/**
|
||||
* The indicator which determines if the conference type is one to one.
|
||||
*/
|
||||
_isOneToOneConference: boolean,
|
||||
_isOneToOneConference: boolean;
|
||||
|
||||
/**
|
||||
* The indicator which determines if the participants pane is open.
|
||||
*/
|
||||
_isParticipantsPaneOpen: boolean,
|
||||
_isParticipantsPaneOpen: boolean;
|
||||
|
||||
/**
|
||||
* The ID of the participant currently on stage (if any).
|
||||
*/
|
||||
_largeVideoParticipantId: string,
|
||||
_largeVideoParticipantId: string;
|
||||
|
||||
/**
|
||||
* Local participant's display name.
|
||||
*/
|
||||
_localParticipantDisplayName: string,
|
||||
_localParticipantDisplayName: string;
|
||||
|
||||
/**
|
||||
* Whether Picture-in-Picture is enabled.
|
||||
*/
|
||||
_pictureInPictureEnabled: boolean,
|
||||
_pictureInPictureEnabled: boolean;
|
||||
|
||||
/**
|
||||
* The indicator which determines whether the UI is reduced (to accommodate
|
||||
* smaller display areas).
|
||||
*/
|
||||
_reducedUI: boolean,
|
||||
|
||||
/**
|
||||
* The indicator which determines whether the Toolbox is visible.
|
||||
*/
|
||||
_toolboxVisible: boolean,
|
||||
_reducedUI: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if we should auto-knock.
|
||||
*/
|
||||
_shouldEnableAutoKnock: boolean,
|
||||
_shouldEnableAutoKnock: boolean;
|
||||
|
||||
/**
|
||||
* Indicates whether the lobby screen should be visible.
|
||||
*/
|
||||
_showLobby: boolean,
|
||||
_showLobby: boolean;
|
||||
|
||||
/**
|
||||
* Indicates whether the car mode is enabled.
|
||||
*/
|
||||
_startCarMode: boolean,
|
||||
_startCarMode: boolean;
|
||||
|
||||
/**
|
||||
* The indicator which determines whether the Toolbox is visible.
|
||||
*/
|
||||
_toolboxVisible: boolean;
|
||||
|
||||
/**
|
||||
* The redux {@code dispatch} function.
|
||||
*/
|
||||
dispatch: Function,
|
||||
dispatch: Function;
|
||||
|
||||
/**
|
||||
* Object containing the safe area insets.
|
||||
*/
|
||||
insets: Object,
|
||||
insets: EdgeInsets;
|
||||
|
||||
/**
|
||||
* Default prop for navigating between screen components(React Navigation).
|
||||
*/
|
||||
navigation: Object
|
||||
};
|
||||
navigation: any;
|
||||
}
|
||||
|
||||
type State = {
|
||||
|
||||
/**
|
||||
* The label that is currently expanded.
|
||||
*/
|
||||
visibleExpandedLabel: ?string
|
||||
}
|
||||
visibleExpandedLabel?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* The conference page of the mobile (i.e. React Native) application.
|
||||
*/
|
||||
class Conference extends AbstractConference<Props, State> {
|
||||
class Conference extends AbstractConference<IProps, State> {
|
||||
/**
|
||||
* Timeout ref.
|
||||
*/
|
||||
_expandedLabelTimeout: Object;
|
||||
_expandedLabelTimeout: any;
|
||||
|
||||
/**
|
||||
* Initializes a new Conference instance.
|
||||
@@ -193,14 +194,14 @@ class Conference extends AbstractConference<Props, State> {
|
||||
* @param {Object} props - The read-only properties with which the new
|
||||
* instance is to be initialized.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
visibleExpandedLabel: undefined
|
||||
};
|
||||
|
||||
this._expandedLabelTimeout = React.createRef();
|
||||
this._expandedLabelTimeout = React.createRef<number>();
|
||||
|
||||
// Bind event handlers so they are only bound once per instance.
|
||||
this._onClick = this._onClick.bind(this);
|
||||
@@ -235,7 +236,7 @@ class Conference extends AbstractConference<Props, State> {
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
componentDidUpdate(prevProps) {
|
||||
componentDidUpdate(prevProps: IProps) {
|
||||
const {
|
||||
_shouldEnableAutoKnock,
|
||||
_showLobby,
|
||||
@@ -267,7 +268,7 @@ class Conference extends AbstractConference<Props, State> {
|
||||
// Tear handling any hardware button presses for back navigation down.
|
||||
BackHandler.removeEventListener('hardwareBackPress', this._onHardwareBackPress);
|
||||
|
||||
clearTimeout(this._expandedLabelTimeout.current);
|
||||
clearTimeout(this._expandedLabelTimeout.current ?? 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -301,8 +302,6 @@ class Conference extends AbstractConference<Props, State> {
|
||||
);
|
||||
}
|
||||
|
||||
_onClick: () => void;
|
||||
|
||||
/**
|
||||
* Changes the value of the toolboxVisible state, thus allowing us to switch
|
||||
* between Toolbox and Filmstrip and change their visibility.
|
||||
@@ -314,8 +313,6 @@ class Conference extends AbstractConference<Props, State> {
|
||||
this._setToolboxVisible(!this.props._toolboxVisible);
|
||||
}
|
||||
|
||||
_onHardwareBackPress: () => boolean;
|
||||
|
||||
/**
|
||||
* Handles a hardware button press for back navigation. Enters Picture-in-Picture mode
|
||||
* (if supported) or leaves the associated {@code Conference} otherwise.
|
||||
@@ -340,8 +337,6 @@ class Conference extends AbstractConference<Props, State> {
|
||||
return true;
|
||||
}
|
||||
|
||||
_createOnPress: (string) => void;
|
||||
|
||||
/**
|
||||
* Creates a function to be invoked when the onPress of the touchables are
|
||||
* triggered.
|
||||
@@ -350,7 +345,7 @@ class Conference extends AbstractConference<Props, State> {
|
||||
* triggered.
|
||||
* @returns {Function}
|
||||
*/
|
||||
_createOnPress(label) {
|
||||
_createOnPress(label: string) {
|
||||
return () => {
|
||||
const { visibleExpandedLabel } = this.state;
|
||||
|
||||
@@ -434,7 +429,7 @@ class Conference extends AbstractConference<Props, State> {
|
||||
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { styles.toolboxAndFilmstripContainer }>
|
||||
style = { styles.toolboxAndFilmstripContainer as ViewStyle }>
|
||||
|
||||
<Captions onPress = { this._onClick } />
|
||||
|
||||
@@ -463,17 +458,17 @@ class Conference extends AbstractConference<Props, State> {
|
||||
<SafeAreaView
|
||||
pointerEvents = 'box-none'
|
||||
style = {
|
||||
_toolboxVisible
|
||||
(_toolboxVisible
|
||||
? styles.titleBarSafeViewColor
|
||||
: styles.titleBarSafeViewTransparent }>
|
||||
: styles.titleBarSafeViewTransparent) as ViewStyle }>
|
||||
<TitleBar _createOnPress = { this._createOnPress } />
|
||||
</SafeAreaView>
|
||||
<SafeAreaView
|
||||
pointerEvents = 'box-none'
|
||||
style = {
|
||||
_toolboxVisible
|
||||
(_toolboxVisible
|
||||
? [ styles.titleBarSafeViewTransparent, { top: this.props.insets.top + 50 } ]
|
||||
: styles.titleBarSafeViewTransparent
|
||||
: styles.titleBarSafeViewTransparent) as ViewStyle
|
||||
}>
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
@@ -482,7 +477,7 @@ class Conference extends AbstractConference<Props, State> {
|
||||
</View>
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { alwaysOnTitleBarStyles }>
|
||||
style = { alwaysOnTitleBarStyles as ViewStyle }>
|
||||
{/* eslint-disable-next-line react/jsx-no-bind */}
|
||||
<AlwaysOnLabels createOnPress = { this._createOnPress } />
|
||||
</View>
|
||||
@@ -532,7 +527,7 @@ class Conference extends AbstractConference<Props, State> {
|
||||
* @returns {React$Element}
|
||||
*/
|
||||
_renderNotificationsContainer() {
|
||||
const notificationsStyle = {};
|
||||
const notificationsStyle: ViewStyle = {};
|
||||
|
||||
// In the landscape mode (wide) there's problem with notifications being
|
||||
// shadowed by the filmstrip rendered on the right. This makes the "x"
|
||||
@@ -559,8 +554,6 @@ class Conference extends AbstractConference<Props, State> {
|
||||
);
|
||||
}
|
||||
|
||||
_setToolboxVisible: (boolean) => void;
|
||||
|
||||
/**
|
||||
* Dispatches an action changing the visibility of the {@link Toolbox}.
|
||||
*
|
||||
@@ -569,7 +562,7 @@ class Conference extends AbstractConference<Props, State> {
|
||||
* {@code Toolbox} or {@code false} to hide it.
|
||||
* @returns {void}
|
||||
*/
|
||||
_setToolboxVisible(visible) {
|
||||
_setToolboxVisible(visible: boolean) {
|
||||
this.props.dispatch(setToolboxVisible(visible));
|
||||
}
|
||||
}
|
||||
@@ -578,10 +571,11 @@ class Conference extends AbstractConference<Props, State> {
|
||||
* Maps (parts of) the redux state to the associated {@code Conference}'s props.
|
||||
*
|
||||
* @param {Object} state - The redux state.
|
||||
* @param {any} _ownProps - Component's own props.
|
||||
* @private
|
||||
* @returns {Props}
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
function _mapStateToProps(state: IReduxState, _ownProps: any) {
|
||||
const { isOpen } = state['features/participants-pane'];
|
||||
const { aspectRatio, reducedUI } = state['features/base/responsive-ui'];
|
||||
const { backgroundColor } = state['features/dynamic-branding'];
|
||||
@@ -627,7 +621,7 @@ export default withSafeAreaInsets(connect(_mapStateToProps)(props => {
|
||||
return () => setPictureInPictureEnabled(false);
|
||||
}, [ isFocused ]);
|
||||
|
||||
return (
|
||||
return ( // @ts-ignore
|
||||
<Conference { ...props } />
|
||||
);
|
||||
}));
|
||||
@@ -1,26 +1,25 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme';
|
||||
|
||||
import { EXPANDED_LABELS } from './constants';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* The selected label to show details.
|
||||
*/
|
||||
visibleExpandedLabel: ?string
|
||||
visibleExpandedLabel?: string;
|
||||
}
|
||||
|
||||
const ExpandedLabelPopup = ({ visibleExpandedLabel }: Props) => {
|
||||
const ExpandedLabelPopup = ({ visibleExpandedLabel }: IProps) => {
|
||||
if (visibleExpandedLabel) {
|
||||
const expandedLabel = EXPANDED_LABELS[visibleExpandedLabel];
|
||||
const expandedLabel = EXPANDED_LABELS[visibleExpandedLabel as keyof typeof EXPANDED_LABELS];
|
||||
|
||||
if (expandedLabel) {
|
||||
const LabelComponent = expandedLabel.component || expandedLabel;
|
||||
const { props, alwaysOn } = expandedLabel || {};
|
||||
const LabelComponent = expandedLabel.component;
|
||||
|
||||
const { props, alwaysOn } = expandedLabel;
|
||||
const style = {
|
||||
top: alwaysOn ? BaseTheme.spacing[6] : BaseTheme.spacing[1]
|
||||
};
|
||||
@@ -1,13 +1,11 @@
|
||||
// @flow
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import ExpandedLabel, { Props as AbstractProps } from '../../../base/label/components/native/ExpandedLabel';
|
||||
import ExpandedLabel, { IProps as AbstractProps } from '../../../base/label/components/native/ExpandedLabel';
|
||||
|
||||
import { INSECURE_ROOM_NAME_LABEL_COLOR } from './styles';
|
||||
|
||||
type Props = AbstractProps & {
|
||||
t: Function
|
||||
}
|
||||
type Props = AbstractProps & WithTranslation;
|
||||
|
||||
/**
|
||||
* A react {@code Component} that implements an expanded label as tooltip-like
|
||||
@@ -1,8 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import { IconWarning } from '../../../base/icons/svg';
|
||||
import Label from '../../../base/label/components/native/Label';
|
||||
import AbstractInsecureRoomNameLabel, { _mapStateToProps } from '../AbstractInsecureRoomNameLabel';
|
||||
@@ -27,4 +26,4 @@ class InsecureRoomNameLabel extends AbstractInsecureRoomNameLabel {
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(_mapStateToProps)(InsecureRoomNameLabel);
|
||||
export default translate(connect(_mapStateToProps)(InsecureRoomNameLabel));
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
import { TouchableOpacity, View } from 'react-native';
|
||||
import { TouchableOpacity, View, ViewStyle } from 'react-native';
|
||||
|
||||
import TranscribingLabel from '../../../transcribing/components/TranscribingLabel.native';
|
||||
import VideoQualityLabel from '../../../video-quality/components/VideoQualityLabel.native';
|
||||
@@ -8,19 +8,19 @@ import InsecureRoomNameLabel from './InsecureRoomNameLabel';
|
||||
import { LABEL_ID_INSECURE_ROOM_NAME, LABEL_ID_QUALITY, LABEL_ID_TRANSCRIBING, LabelHitSlop } from './constants';
|
||||
import styles from './styles';
|
||||
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Creates a function to be invoked when the onPress of the touchables are
|
||||
* triggered.
|
||||
*/
|
||||
createOnPress: Function
|
||||
createOnPress: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* A container that renders the conference indicators, if any.
|
||||
*/
|
||||
class Labels extends Component<Props> {
|
||||
class Labels extends Component<IProps> {
|
||||
|
||||
/**
|
||||
* Implements React {@code Component}'s render.
|
||||
@@ -32,7 +32,7 @@ class Labels extends Component<Props> {
|
||||
<View pointerEvents = 'box-none'>
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { styles.indicatorContainer }>
|
||||
style = { styles.indicatorContainer as ViewStyle }>
|
||||
<TouchableOpacity
|
||||
hitSlop = { LabelHitSlop }
|
||||
onPress = {
|
||||
@@ -1,11 +1,9 @@
|
||||
// @flow
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import ExpandedLabel, { Props as AbstractProps } from '../../../base/label/components/native/ExpandedLabel';
|
||||
import ExpandedLabel, { IProps as AbstractProps } from '../../../base/label/components/native/ExpandedLabel';
|
||||
|
||||
type Props = AbstractProps & {
|
||||
t: Function
|
||||
}
|
||||
type Props = AbstractProps & WithTranslation;
|
||||
|
||||
/**
|
||||
* A react {@code Component} that implements an expanded label as tooltip-like
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { IconRaiseHand } from '../../../base/icons/svg';
|
||||
import Label from '../../../base/label/components/native/Label';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
|
||||
@@ -8,17 +9,17 @@ import BaseTheme from '../../../base/ui/components/BaseTheme.native';
|
||||
import styles from './styles';
|
||||
|
||||
const RaisedHandsCountLabel = () => {
|
||||
const raisedHandsCount = useSelector(state =>
|
||||
const raisedHandsCount = useSelector((state: IReduxState) =>
|
||||
(state['features/base/participants'].raisedHandsQueue || []).length);
|
||||
|
||||
return raisedHandsCount > 0 && (
|
||||
return raisedHandsCount > 0 ? (
|
||||
<Label
|
||||
icon = { IconRaiseHand }
|
||||
iconColor = { BaseTheme.palette.uiBackground }
|
||||
style = { styles.raisedHandsCountLabel }
|
||||
text = { raisedHandsCount }
|
||||
text = { `${raisedHandsCount}` }
|
||||
textStyle = { styles.raisedHandsCountLabelText } />
|
||||
);
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default RaisedHandsCountLabel;
|
||||
@@ -1,9 +1,8 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import { Text, View } from 'react-native';
|
||||
import { Text, View, ViewStyle } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { getConferenceName, getConferenceTimestamp } from '../../../base/conference/functions';
|
||||
import { CONFERENCE_TIMER_ENABLED, MEETING_NAME_ENABLED } from '../../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../../base/flags/functions';
|
||||
@@ -17,44 +16,43 @@ import ConferenceTimer from '../ConferenceTimer';
|
||||
import Labels from './Labels';
|
||||
import styles from './styles';
|
||||
|
||||
interface IProps {
|
||||
|
||||
type Props = {
|
||||
/**
|
||||
* Whether displaying the current conference timer is enabled or not.
|
||||
*/
|
||||
_conferenceTimerEnabled: boolean;
|
||||
|
||||
/**
|
||||
* Creates a function to be invoked when the onPress of the touchables are
|
||||
* triggered.
|
||||
*/
|
||||
_createOnPress: Function,
|
||||
|
||||
/**
|
||||
* Whether displaying the current conference timer is enabled or not.
|
||||
*/
|
||||
_conferenceTimerEnabled: boolean,
|
||||
_createOnPress: Function;
|
||||
|
||||
/**
|
||||
* Name of the meeting we're currently in.
|
||||
*/
|
||||
_meetingName: string,
|
||||
_meetingName: string;
|
||||
|
||||
/**
|
||||
* Whether displaying the current meeting name is enabled or not.
|
||||
*/
|
||||
_meetingNameEnabled: boolean,
|
||||
_meetingNameEnabled: boolean;
|
||||
|
||||
/**
|
||||
* True if the navigation bar should be visible.
|
||||
*/
|
||||
_visible: boolean
|
||||
};
|
||||
_visible: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements a navigation bar component that is rendered on top of the
|
||||
* conference screen.
|
||||
*
|
||||
* @param {Props} props - The React props passed to this component.
|
||||
* @param {IProps} props - The React props passed to this component.
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
const TitleBar = (props: Props) => {
|
||||
const TitleBar = (props: IProps) => {
|
||||
const { _visible } = props;
|
||||
|
||||
if (!_visible) {
|
||||
@@ -63,22 +61,22 @@ const TitleBar = (props: Props) => {
|
||||
|
||||
return (
|
||||
<View
|
||||
style = { styles.titleBarWrapper }>
|
||||
<View style = { styles.pipButtonContainer }>
|
||||
style = { styles.titleBarWrapper as ViewStyle }>
|
||||
<View style = { styles.pipButtonContainer as ViewStyle }>
|
||||
<PictureInPictureButton styles = { styles.pipButton } />
|
||||
</View>
|
||||
<View
|
||||
pointerEvents = 'box-none'
|
||||
style = { styles.roomNameWrapper }>
|
||||
style = { styles.roomNameWrapper as ViewStyle }>
|
||||
{
|
||||
props._conferenceTimerEnabled
|
||||
&& <View style = { styles.roomTimerView }>
|
||||
&& <View style = { styles.roomTimerView as ViewStyle }>
|
||||
<ConferenceTimer textStyle = { styles.roomTimer } />
|
||||
</View>
|
||||
}
|
||||
{
|
||||
props._meetingNameEnabled
|
||||
&& <View style = { styles.roomNameView }>
|
||||
&& <View style = { styles.roomNameView as ViewStyle }>
|
||||
<Text
|
||||
numberOfLines = { 1 }
|
||||
style = { styles.roomName }>
|
||||
@@ -106,9 +104,9 @@ const TitleBar = (props: Props) => {
|
||||
* Maps part of the Redux store to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @returns {Props}
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
const { hideConferenceTimer, hideConferenceSubject } = state['features/base/config'];
|
||||
const startTimestamp = getConferenceTimestamp(state);
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable lines-around-comment */
|
||||
import React, { useEffect } from 'react';
|
||||
import { View, ViewStyle } from 'react-native';
|
||||
import Orientation from 'react-native-orientation-locker';
|
||||
|
||||
@@ -4,8 +4,6 @@ import { useDispatch } from 'react-redux';
|
||||
import { openSheet } from '../../../../base/dialog/actions';
|
||||
import Button from '../../../../base/ui/components/native/Button';
|
||||
import { BUTTON_TYPES } from '../../../../base/ui/constants.native';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import AudioRoutePickerDialog from '../../../../mobile/audio-mode/components/AudioRoutePickerDialog';
|
||||
|
||||
import AudioIcon from './AudioIcon';
|
||||
|
||||
@@ -10,8 +10,6 @@ import { JitsiRecordingConstants } from '../../../../base/lib-jitsi-meet';
|
||||
import { getLocalParticipant } from '../../../../base/participants/functions';
|
||||
import ConnectionIndicator from '../../../../connection-indicator/components/native/ConnectionIndicator';
|
||||
import RecordingLabel from '../../../../recording/components/native/RecordingLabel';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import VideoQualityLabel from '../../../../video-quality/components/VideoQualityLabel.native';
|
||||
|
||||
import styles from './styles';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// @flow
|
||||
import React from 'react';
|
||||
|
||||
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
|
||||
import RecordingExpandedLabel from '../../../recording/components/native/RecordingExpandedLabel';
|
||||
@@ -28,12 +28,22 @@ export const LABEL_ID_INSECURE_ROOM_NAME = 'insecure-room-name';
|
||||
export const LABEL_ID_RAISED_HANDS_COUNT = 'raised-hands-count';
|
||||
export const LABEL_ID_VISITORS_COUNT = 'visitors-count';
|
||||
|
||||
interface IExpandedLabel {
|
||||
alwaysOn?: boolean;
|
||||
component: React.ComponentType<any>;
|
||||
props?: any;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@code ExpandedLabel} components to be rendered for the individual
|
||||
* {@code Label}s.
|
||||
*/
|
||||
export const EXPANDED_LABELS = {
|
||||
[LABEL_ID_QUALITY]: VideoQualityExpandedLabel,
|
||||
export const EXPANDED_LABELS: {
|
||||
[key: string]: IExpandedLabel;
|
||||
} = {
|
||||
[LABEL_ID_QUALITY]: {
|
||||
component: VideoQualityExpandedLabel
|
||||
},
|
||||
[LABEL_ID_RECORDING]: {
|
||||
component: RecordingExpandedLabel,
|
||||
props: {
|
||||
@@ -48,8 +58,12 @@ export const EXPANDED_LABELS = {
|
||||
},
|
||||
alwaysOn: true
|
||||
},
|
||||
[LABEL_ID_TRANSCRIBING]: TranscribingExpandedLabel,
|
||||
[LABEL_ID_INSECURE_ROOM_NAME]: InsecureRoomNameExpandedLabel,
|
||||
[LABEL_ID_TRANSCRIBING]: {
|
||||
component: TranscribingExpandedLabel
|
||||
},
|
||||
[LABEL_ID_INSECURE_ROOM_NAME]: {
|
||||
component: InsecureRoomNameExpandedLabel
|
||||
},
|
||||
[LABEL_ID_RAISED_HANDS_COUNT]: {
|
||||
component: RaisedHandsCountExpandedLabel,
|
||||
alwaysOn: true
|
||||
@@ -69,7 +69,7 @@ interface IProps {
|
||||
/**
|
||||
* Object containing the safe area insets.
|
||||
*/
|
||||
insets: Object;
|
||||
insets?: Object;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -219,7 +219,7 @@ export function getFilmstripDimensions({
|
||||
aspectRatio: Symbol;
|
||||
clientHeight: number;
|
||||
clientWidth: number;
|
||||
insets: {
|
||||
insets?: {
|
||||
bottom?: number;
|
||||
left?: number;
|
||||
right?: number;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { connect } from 'react-redux';
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
import { openSheet } from '../../../base/dialog/actions';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
@@ -8,18 +7,10 @@ import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/too
|
||||
|
||||
import AudioRoutePickerDialog from './AudioRoutePickerDialog';
|
||||
|
||||
type Props = AbstractButtonProps & {
|
||||
|
||||
/**
|
||||
* The Redux dispatch function.
|
||||
*/
|
||||
dispatch: Dispatch<any>
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements an {@link AbstractButton} to open the audio device list.
|
||||
*/
|
||||
class AudioDeviceToggleButton extends AbstractButton<Props, *> {
|
||||
class AudioDeviceToggleButton extends AbstractButton<AbstractButtonProps> {
|
||||
accessibilityLabel = 'toolbar.accessibilityLabel.audioRoute';
|
||||
icon = IconVolumeUp;
|
||||
label = 'toolbar.accessibilityLabel.audioRoute';
|
||||
@@ -1,8 +1,9 @@
|
||||
import _ from 'lodash';
|
||||
import React, { Component } from 'react';
|
||||
import { NativeModules, Text, TouchableHighlight, View } from 'react-native';
|
||||
import { NativeModules, Text, TextStyle, TouchableHighlight, View, ViewStyle } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { hideSheet } from '../../../base/dialog/actions';
|
||||
import BottomSheet from '../../../base/dialog/components/native/BottomSheet';
|
||||
import { bottomSheetStyles } from '../../../base/dialog/components/native/styles';
|
||||
@@ -15,6 +16,7 @@ import {
|
||||
IconPhoneRinging,
|
||||
IconVolumeUp
|
||||
} from '../../../base/icons/svg';
|
||||
import { StyleType } from '../../../base/styles/functions.any';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
|
||||
|
||||
import styles from './styles';
|
||||
@@ -24,92 +26,92 @@ const { AudioMode } = NativeModules;
|
||||
/**
|
||||
* Type definition for a single entry in the device list.
|
||||
*/
|
||||
type Device = {
|
||||
interface IDevice {
|
||||
|
||||
/**
|
||||
* Name of the icon which will be rendered on the right.
|
||||
*/
|
||||
icon: Object,
|
||||
icon: Function;
|
||||
|
||||
/**
|
||||
* True if the element is selected (will be highlighted in blue),
|
||||
* false otherwise.
|
||||
*/
|
||||
selected: boolean,
|
||||
selected: boolean;
|
||||
|
||||
/**
|
||||
* Text which will be rendered in the row.
|
||||
*/
|
||||
text: string,
|
||||
text: string;
|
||||
|
||||
/**
|
||||
* Device type.
|
||||
*/
|
||||
type: string,
|
||||
type: string;
|
||||
|
||||
/**
|
||||
* Unique device ID.
|
||||
*/
|
||||
uid: ?string
|
||||
};
|
||||
uid?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* "Raw" device, as returned by native.
|
||||
*/
|
||||
type RawDevice = {
|
||||
export interface IRawDevice {
|
||||
|
||||
/**
|
||||
* Display name for the device.
|
||||
*/
|
||||
name: ?string,
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* Is this device selected?
|
||||
*/
|
||||
selected: boolean,
|
||||
selected: boolean;
|
||||
|
||||
/**
|
||||
* Device type.
|
||||
*/
|
||||
type: string,
|
||||
type: string;
|
||||
|
||||
/**
|
||||
* Unique device ID.
|
||||
*/
|
||||
uid: ?string
|
||||
};
|
||||
uid?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code AudioRoutePickerDialog}'s React {@code Component} prop types.
|
||||
*/
|
||||
type Props = {
|
||||
interface IProps {
|
||||
|
||||
/**
|
||||
* Object describing available devices.
|
||||
*/
|
||||
_devices: Array<RawDevice>,
|
||||
_devices: Array<IRawDevice>;
|
||||
|
||||
/**
|
||||
* Used for hiding the dialog when the selection was completed.
|
||||
*/
|
||||
dispatch: Function,
|
||||
dispatch: Function;
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
t: Function;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code AudioRoutePickerDialog}'s React {@code Component} state types.
|
||||
*/
|
||||
type State = {
|
||||
interface IState {
|
||||
|
||||
/**
|
||||
* Array of available devices.
|
||||
*/
|
||||
devices: Array<Device>
|
||||
};
|
||||
devices: Array<IDevice>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps each device type to a display name and icon.
|
||||
@@ -146,7 +148,7 @@ const deviceInfoMap = {
|
||||
* Implements a React {@code Component} which prompts the user when a password
|
||||
* is required to join a conference.
|
||||
*/
|
||||
class AudioRoutePickerDialog extends Component<Props, State> {
|
||||
class AudioRoutePickerDialog extends Component<IProps, IState> {
|
||||
state = {
|
||||
/**
|
||||
* Available audio devices, it will be set in
|
||||
@@ -160,7 +162,7 @@ class AudioRoutePickerDialog extends Component<Props, State> {
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
static getDerivedStateFromProps(props: Props) {
|
||||
static getDerivedStateFromProps(props: IProps) {
|
||||
const { _devices: devices, t } = props;
|
||||
|
||||
if (!devices) {
|
||||
@@ -170,7 +172,7 @@ class AudioRoutePickerDialog extends Component<Props, State> {
|
||||
const audioDevices = [];
|
||||
|
||||
for (const device of devices) {
|
||||
const infoMap = deviceInfoMap[device.type];
|
||||
const infoMap = deviceInfoMap[device.type as keyof typeof deviceInfoMap];
|
||||
|
||||
// Skip devices with unknown type.
|
||||
if (!infoMap) {
|
||||
@@ -206,25 +208,25 @@ class AudioRoutePickerDialog extends Component<Props, State> {
|
||||
/**
|
||||
* Initializes a new {@code PasswordRequiredPrompt} instance.
|
||||
*
|
||||
* @param {Props} props - The read-only React {@code Component} props with
|
||||
* @param {IProps} props - The read-only React {@code Component} props with
|
||||
* which the new instance is to be initialized.
|
||||
*/
|
||||
constructor(props: Props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
// Trigger an initial update.
|
||||
AudioMode.updateDeviceList && AudioMode.updateDeviceList();
|
||||
AudioMode.updateDeviceList?.();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns a function which handles the selection of a device
|
||||
* on the sheet. The selected device will be used by {@code AudioMode}.
|
||||
*
|
||||
* @param {Device} device - Object representing the selected device.
|
||||
* @param {IDevice} device - Object representing the selected device.
|
||||
* @private
|
||||
* @returns {Function}
|
||||
*/
|
||||
_onSelectDeviceFn(device: Device) {
|
||||
_onSelectDeviceFn(device: IDevice) {
|
||||
return () => {
|
||||
this.props.dispatch(hideSheet());
|
||||
AudioMode.setAudioDevice(device.uid || device.type);
|
||||
@@ -234,11 +236,11 @@ class AudioRoutePickerDialog extends Component<Props, State> {
|
||||
/**
|
||||
* Renders a single device.
|
||||
*
|
||||
* @param {Device} device - Object representing a single device.
|
||||
* @param {IDevice} device - Object representing a single device.
|
||||
* @private
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderDevice(device: Device) {
|
||||
_renderDevice(device: IDevice) {
|
||||
const { icon, selected, text } = device;
|
||||
const selectedStyle = selected ? styles.selectedText : {};
|
||||
const borderRadiusHighlightStyles = {
|
||||
@@ -253,11 +255,14 @@ class AudioRoutePickerDialog extends Component<Props, State> {
|
||||
onPress = { this._onSelectDeviceFn(device) }
|
||||
style = { speakerDeviceIsNotSelected && borderRadiusHighlightStyles }
|
||||
underlayColor = { BaseTheme.palette.ui04 } >
|
||||
<View style = { styles.deviceRow } >
|
||||
<View style = { styles.deviceRow as ViewStyle } >
|
||||
<Icon
|
||||
src = { icon }
|
||||
style = { [ styles.deviceIcon, bottomSheetStyles.buttons.iconStyle, selectedStyle ] } />
|
||||
<Text style = { [ styles.deviceText, bottomSheetStyles.buttons.labelStyle, selectedStyle ] } >
|
||||
style = { [ styles.deviceIcon, bottomSheetStyles.buttons.iconStyle, selectedStyle
|
||||
] as StyleType[] } />
|
||||
<Text
|
||||
style = { [ styles.deviceText, bottomSheetStyles.buttons.labelStyle, selectedStyle
|
||||
] as TextStyle[] } >
|
||||
{ text }
|
||||
</Text>
|
||||
</View>
|
||||
@@ -275,11 +280,11 @@ class AudioRoutePickerDialog extends Component<Props, State> {
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<View style = { styles.deviceRow } >
|
||||
<View style = { styles.deviceRow as ViewStyle } >
|
||||
<Icon
|
||||
src = { deviceInfoMap.SPEAKER.icon }
|
||||
style = { [ styles.deviceIcon, bottomSheetStyles.buttons.iconStyle ] } />
|
||||
<Text style = { [ styles.deviceText, bottomSheetStyles.buttons.labelStyle ] } >
|
||||
style = { [ styles.deviceIcon, bottomSheetStyles.buttons.iconStyle ] as StyleType[] } />
|
||||
<Text style = { [ styles.deviceText, bottomSheetStyles.buttons.labelStyle ] as TextStyle[] } >
|
||||
{ t('audioDevices.none') }
|
||||
</Text>
|
||||
</View>
|
||||
@@ -316,7 +321,7 @@ class AudioRoutePickerDialog extends Component<Props, State> {
|
||||
* @param {Object} state - The Redux state.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
return {
|
||||
_devices: state['features/mobile/audio-mode'].devices
|
||||
};
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { MD_ITEM_HEIGHT } from '../../../base/dialog/components/native/styles';
|
||||
import { createStyleSheet } from '../../../base/styles/functions.any';
|
||||
import BaseTheme from '../../../base/ui/components/BaseTheme.native';
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { getLogger } from '../../base/logging/functions';
|
||||
|
||||
export default getLogger('features/mobile/audio-mode');
|
||||
@@ -1,6 +1,7 @@
|
||||
// @flow
|
||||
import { NativeEventEmitter, NativeModules } from 'react-native';
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
import { IStore } from '../../app/types';
|
||||
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app/actionTypes';
|
||||
import { SET_AUDIO_ONLY } from '../../base/audio-only/actionTypes';
|
||||
import {
|
||||
@@ -75,7 +76,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _appWillMount(store) {
|
||||
function _appWillMount(store: IStore) {
|
||||
const subscriptions = [
|
||||
AudioModeEmitter.addListener(AudioMode.DEVICE_CHANGE_EVENT, _onDevicesUpdate, store)
|
||||
];
|
||||
@@ -93,8 +94,9 @@ function _appWillMount(store) {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _onDevicesUpdate(devices) {
|
||||
const { dispatch } = this; // eslint-disable-line no-invalid-this
|
||||
function _onDevicesUpdate(devices: any) {
|
||||
// @ts-ignore
|
||||
const { dispatch } = this; // eslint-disable-line @typescript-eslint/no-invalid-this
|
||||
|
||||
dispatch({
|
||||
type: _SET_AUDIOMODE_DEVICES,
|
||||
@@ -112,7 +114,7 @@ function _onDevicesUpdate(devices) {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _setSubscriptions({ getState }) {
|
||||
function _setSubscriptions({ getState }: IStore) {
|
||||
const { subscriptions } = getState()['features/mobile/audio-mode'];
|
||||
|
||||
if (subscriptions) {
|
||||
@@ -134,12 +136,12 @@ function _setSubscriptions({ getState }) {
|
||||
* @private
|
||||
* @returns {*} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _updateAudioMode({ getState }, next, action) {
|
||||
function _updateAudioMode({ getState }: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
const state = getState();
|
||||
const conference = getCurrentConference(state);
|
||||
const { enabled: audioOnly } = state['features/base/audio-only'];
|
||||
let mode;
|
||||
let mode: string;
|
||||
|
||||
if (getFeatureFlag(state, AUDIO_FOCUS_DISABLED, false)) {
|
||||
return result;
|
||||
@@ -149,7 +151,7 @@ function _updateAudioMode({ getState }, next, action) {
|
||||
mode = AudioMode.DEFAULT;
|
||||
}
|
||||
|
||||
AudioMode.setMode(mode).catch(err => logger.error(`Failed to set audio mode ${String(mode)}: ${err}`));
|
||||
AudioMode.setMode(mode).catch((err: any) => logger.error(`Failed to set audio mode ${String(mode)}: ${err}`));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -2,10 +2,13 @@ import ReducerRegistry from '../../base/redux/ReducerRegistry';
|
||||
import { equals, set } from '../../base/redux/functions';
|
||||
|
||||
import { _SET_AUDIOMODE_DEVICES, _SET_AUDIOMODE_SUBSCRIPTIONS } from './actionTypes';
|
||||
import { IRawDevice } from './components/AudioRoutePickerDialog';
|
||||
|
||||
export interface IMobileAudioModeState {
|
||||
devices: Object[];
|
||||
subscriptions: Object[];
|
||||
devices: IRawDevice[];
|
||||
subscriptions: {
|
||||
remove: Function;
|
||||
}[];
|
||||
}
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { APP_STATE_CHANGED, _SET_APP_STATE_LISTENER } from './actionTypes';
|
||||
|
||||
/**
|
||||
@@ -12,7 +10,7 @@ import { APP_STATE_CHANGED, _SET_APP_STATE_LISTENER } from './actionTypes';
|
||||
* listener: Function
|
||||
* }}
|
||||
*/
|
||||
export function _setAppStateListener(listener: ?Function) {
|
||||
export function _setAppStateListener(listener?: Function) {
|
||||
return {
|
||||
type: _SET_APP_STATE_LISTENER,
|
||||
listener
|
||||
@@ -1,8 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import { AppState } from 'react-native';
|
||||
import type { Dispatch } from 'redux';
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
import { IStore } from '../../app/types';
|
||||
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app/actionTypes';
|
||||
import MiddlewareRegistry from '../../base/redux/MiddlewareRegistry';
|
||||
|
||||
@@ -51,7 +50,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _onAppStateChange(dispatch: Dispatch<any>, appState: string) {
|
||||
function _onAppStateChange(dispatch: IStore['dispatch'], appState: string) {
|
||||
dispatch(appStateChanged(appState));
|
||||
}
|
||||
|
||||
@@ -69,7 +68,7 @@ function _onAppStateChange(dispatch: Dispatch<any>, appState: string) {
|
||||
* @private
|
||||
* @returns {Object} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _setAppStateListenerF({ getState }, next, action) {
|
||||
function _setAppStateListenerF({ getState }: IStore, next: Function, action: AnyAction) {
|
||||
// Remove the old AppState listener and add the new one.
|
||||
const { appStateListener: oldListener } = getState()['features/background'];
|
||||
const result = next(action);
|
||||
@@ -1,3 +1,5 @@
|
||||
import { AppStateStatus } from 'react-native';
|
||||
|
||||
import ReducerRegistry from '../../base/redux/ReducerRegistry';
|
||||
|
||||
import {
|
||||
@@ -7,7 +9,7 @@ import {
|
||||
|
||||
export interface IBackgroundState {
|
||||
appState: string;
|
||||
appStateListener?: Function;
|
||||
appStateListener?: (state: AppStateStatus) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NativeEventEmitter, NativeModules } from 'react-native';
|
||||
|
||||
import { getName } from '../../app/functions';
|
||||
import { getName } from '../../app/functions.native';
|
||||
|
||||
/**
|
||||
* Thin wrapper around Apple's CallKit functionality.
|
||||
@@ -35,7 +35,7 @@ if (CallKit) {
|
||||
CallKit = {
|
||||
...CallKit,
|
||||
addListener: eventEmitter.addListener.bind(eventEmitter),
|
||||
registerSubscriptions(context, delegate) {
|
||||
registerSubscriptions(context: any, delegate: any) {
|
||||
CallKit.setProviderConfiguration({
|
||||
iconTemplateImageName: 'CallKitIcon',
|
||||
localizedName: getName()
|
||||
@@ -11,7 +11,7 @@ if (ConnectionService) {
|
||||
ConnectionService = {
|
||||
...ConnectionService,
|
||||
addListener: eventEmitter.addListener.bind(eventEmitter),
|
||||
registerSubscriptions(context, delegate) {
|
||||
registerSubscriptions(context: any, delegate: any) {
|
||||
return [
|
||||
ConnectionService.addListener(
|
||||
'org.jitsi.meet:features/connection_service#disconnect',
|
||||
@@ -1,5 +1,4 @@
|
||||
// @flow
|
||||
|
||||
import { IStateful } from '../../base/app/types';
|
||||
import { CALL_INTEGRATION_ENABLED } from '../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../base/flags/functions';
|
||||
import { toState } from '../../base/redux/functions';
|
||||
@@ -11,7 +10,7 @@ import { toState } from '../../base/redux/functions';
|
||||
* function.
|
||||
* @returns {string} - Default URL for the app.
|
||||
*/
|
||||
export function isCallIntegrationEnabled(stateful: Function | Object) {
|
||||
export function isCallIntegrationEnabled(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
const { disableCallIntegration } = state['features/base/settings'];
|
||||
const flag = getFeatureFlag(state, CALL_INTEGRATION_ENABLED);
|
||||
@@ -1,11 +1,11 @@
|
||||
// @flow
|
||||
|
||||
import { Alert, NativeModules, Platform } from 'react-native';
|
||||
import { AnyAction } from 'redux';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { createTrackMutedEvent } from '../../analytics/AnalyticsEvents';
|
||||
import { sendAnalytics } from '../../analytics/functions';
|
||||
import { appNavigate } from '../../app/actions';
|
||||
import { IReduxState, IStore } from '../../app/types';
|
||||
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app/actionTypes';
|
||||
import { SET_AUDIO_ONLY } from '../../base/audio-only/actionTypes';
|
||||
import {
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
getConferenceName,
|
||||
getCurrentConference
|
||||
} from '../../base/conference/functions';
|
||||
import { IJitsiConference } from '../../base/conference/reducer';
|
||||
import { getInviteURL } from '../../base/connection/functions';
|
||||
import { setAudioMuted } from '../../base/media/actions';
|
||||
import { MEDIA_TYPE } from '../../base/media/constants';
|
||||
@@ -104,7 +105,7 @@ CallIntegration && MiddlewareRegistry.register(store => next => action => {
|
||||
* @private
|
||||
* @returns {*} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _appWillMount({ dispatch, getState }, next, action) {
|
||||
function _appWillMount({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
|
||||
const context = {
|
||||
@@ -142,7 +143,7 @@ function _appWillMount({ dispatch, getState }, next, action) {
|
||||
* @private
|
||||
* @returns {*} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _conferenceFailed({ getState }, next, action) {
|
||||
function _conferenceFailed({ getState }: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
|
||||
if (!isCallIntegrationEnabled(getState)) {
|
||||
@@ -177,7 +178,7 @@ function _conferenceFailed({ getState }, next, action) {
|
||||
* @private
|
||||
* @returns {*} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _conferenceJoined({ getState }, next, action) {
|
||||
function _conferenceJoined({ getState }: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
|
||||
if (!isCallIntegrationEnabled(getState)) {
|
||||
@@ -222,7 +223,7 @@ function _conferenceJoined({ getState }, next, action) {
|
||||
* @private
|
||||
* @returns {*} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _conferenceLeft({ getState }, next, action) {
|
||||
function _conferenceLeft({ getState }: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
|
||||
if (!isCallIntegrationEnabled(getState)) {
|
||||
@@ -252,7 +253,7 @@ function _conferenceLeft({ getState }, next, action) {
|
||||
* @private
|
||||
* @returns {*} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _conferenceWillJoin({ dispatch, getState }, next, action) {
|
||||
function _conferenceWillJoin({ dispatch, getState }: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
|
||||
if (!isCallIntegrationEnabled(getState)) {
|
||||
@@ -292,7 +293,7 @@ function _conferenceWillJoin({ dispatch, getState }, next, action) {
|
||||
_updateCallIntegrationMuted(conference, state);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error: any) => {
|
||||
// Currently this error codes are emitted only by Android.
|
||||
//
|
||||
if (error.code === 'CREATE_OUTGOING_CALL_FAILED') {
|
||||
@@ -327,7 +328,7 @@ function _conferenceWillJoin({ dispatch, getState }, next, action) {
|
||||
* @param {Object} state - Redux store.
|
||||
* @returns {void}
|
||||
*/
|
||||
function _handleConnectionServiceFailure(state: Object) {
|
||||
function _handleConnectionServiceFailure(state: IReduxState) {
|
||||
const conference = getCurrentConference(state);
|
||||
|
||||
if (conference) {
|
||||
@@ -356,8 +357,9 @@ function _handleConnectionServiceFailure(state: Object) {
|
||||
* {@code performEndCallAction}.
|
||||
* @returns {void}
|
||||
*/
|
||||
function _onPerformEndCallAction({ callUUID }) {
|
||||
const { dispatch, getState } = this; // eslint-disable-line no-invalid-this
|
||||
function _onPerformEndCallAction({ callUUID }: { callUUID: string; }) {
|
||||
// @ts-ignore
|
||||
const { dispatch, getState } = this; // eslint-disable-line @typescript-eslint/no-invalid-this
|
||||
const conference = getCurrentConference(getState);
|
||||
|
||||
if (conference && conference.callUUID === callUUID) {
|
||||
@@ -376,8 +378,9 @@ function _onPerformEndCallAction({ callUUID }) {
|
||||
* {@code performSetMutedCallAction}.
|
||||
* @returns {void}
|
||||
*/
|
||||
function _onPerformSetMutedCallAction({ callUUID, muted }) {
|
||||
const { dispatch, getState } = this; // eslint-disable-line no-invalid-this
|
||||
function _onPerformSetMutedCallAction({ callUUID, muted }: { callUUID: string; muted: boolean; }) {
|
||||
// @ts-ignore
|
||||
const { dispatch, getState } = this; // eslint-disable-line @typescript-eslint/no-invalid-this
|
||||
const conference = getCurrentConference(getState);
|
||||
|
||||
if (conference && conference.callUUID === callUUID) {
|
||||
@@ -408,7 +411,7 @@ function _onPerformSetMutedCallAction({ callUUID, muted }) {
|
||||
* @private
|
||||
* @returns {*} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _setAudioOnly({ getState }, next, action) {
|
||||
function _setAudioOnly({ getState }: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
const state = getState();
|
||||
|
||||
@@ -418,7 +421,7 @@ function _setAudioOnly({ getState }, next, action) {
|
||||
|
||||
const conference = getCurrentConference(state);
|
||||
|
||||
if (conference && conference.callUUID) {
|
||||
if (conference?.callUUID) {
|
||||
CallIntegration.updateCall(
|
||||
conference.callUUID,
|
||||
{ hasVideo: !action.audioOnly });
|
||||
@@ -442,7 +445,7 @@ function _setAudioOnly({ getState }, next, action) {
|
||||
* @private
|
||||
* @returns {*} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _setCallKitSubscriptions({ getState }, next, action) {
|
||||
function _setCallKitSubscriptions({ getState }: IStore, next: Function, action: AnyAction) {
|
||||
const { subscriptions } = getState()['features/call-integration'];
|
||||
|
||||
if (subscriptions) {
|
||||
@@ -466,7 +469,7 @@ function _setCallKitSubscriptions({ getState }, next, action) {
|
||||
* @private
|
||||
* @returns {*} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _syncTrackState({ getState }, next, action) {
|
||||
function _syncTrackState({ getState }: IStore, next: Function, action: AnyAction) {
|
||||
const result = next(action);
|
||||
|
||||
if (!isCallIntegrationEnabled(getState)) {
|
||||
@@ -504,7 +507,7 @@ function _syncTrackState({ getState }, next, action) {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _updateCallIntegrationMuted(conference, state) {
|
||||
function _updateCallIntegrationMuted(conference: IJitsiConference, state: IReduxState) {
|
||||
const muted = isLocalTrackMuted(state['features/base/tracks'], MEDIA_TYPE.AUDIO);
|
||||
|
||||
CallIntegration.setMuted(conference.callUUID, muted);
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { getLogger } from '../../base/logging/functions';
|
||||
|
||||
export default getLogger('features/mobile/external-api');
|
||||
@@ -1,10 +1,11 @@
|
||||
// @flow
|
||||
|
||||
import debounce from 'lodash/debounce';
|
||||
import { NativeEventEmitter, NativeModules } from 'react-native';
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
// @ts-expect-error
|
||||
import { ENDPOINT_TEXT_MESSAGE_NAME } from '../../../../modules/API/constants';
|
||||
import { appNavigate } from '../../app/actions';
|
||||
import { IStore } from '../../app/types';
|
||||
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app/actionTypes';
|
||||
import {
|
||||
CONFERENCE_FAILED,
|
||||
@@ -19,6 +20,7 @@ import {
|
||||
getCurrentConference,
|
||||
isRoomValid
|
||||
} from '../../base/conference/functions';
|
||||
import { IJitsiConference } from '../../base/conference/reducer';
|
||||
import { CONNECTION_DISCONNECTED } from '../../base/connection/actionTypes';
|
||||
import {
|
||||
JITSI_CONNECTION_CONFERENCE_KEY,
|
||||
@@ -36,10 +38,12 @@ import {
|
||||
getRemoteParticipants,
|
||||
isScreenShareParticipant
|
||||
} from '../../base/participants/functions';
|
||||
import { IParticipant } from '../../base/participants/types';
|
||||
import MiddlewareRegistry from '../../base/redux/MiddlewareRegistry';
|
||||
import StateListenerRegistry from '../../base/redux/StateListenerRegistry';
|
||||
import { toggleScreensharing } from '../../base/tracks/actions.native';
|
||||
import { getLocalTracks, isLocalTrackMuted } from '../../base/tracks/functions.native';
|
||||
import { ITrack } from '../../base/tracks/types';
|
||||
import { CLOSE_CHAT, OPEN_CHAT } from '../../chat/actionTypes';
|
||||
import { openChat } from '../../chat/actions';
|
||||
import { closeChat, sendMessage, setPrivateMessageRecipient } from '../../chat/actions.any';
|
||||
@@ -237,7 +241,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
*/
|
||||
StateListenerRegistry.register(
|
||||
/* selector */ state => state['features/base/tracks'],
|
||||
/* listener */ debounce((tracks, store) => {
|
||||
/* listener */ debounce((tracks: ITrack[], store: IStore) => {
|
||||
const oldScreenShares = store.getState()['features/mobile/external-api'].screenShares || [];
|
||||
const newScreenShares = tracks
|
||||
.filter(track => track.mediaType === 'video' && track.videoType === 'desktop')
|
||||
@@ -277,7 +281,7 @@ StateListenerRegistry.register(
|
||||
* @param {Participant} participant - The participant object from the redux store.
|
||||
* @returns {Object} - The participant info object.
|
||||
*/
|
||||
function _participantToParticipantInfo(participant) {
|
||||
function _participantToParticipantInfo(participant: IParticipant) {
|
||||
return {
|
||||
isLocal: participant.local,
|
||||
email: participant.email,
|
||||
@@ -296,7 +300,7 @@ function _participantToParticipantInfo(participant) {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _registerForNativeEvents(store) {
|
||||
function _registerForNativeEvents(store: IStore) {
|
||||
const { getState, dispatch } = store;
|
||||
|
||||
eventEmitter.addListener(ExternalAPI.HANG_UP, () => {
|
||||
@@ -315,7 +319,7 @@ function _registerForNativeEvents(store) {
|
||||
const conference = getCurrentConference(getState());
|
||||
|
||||
try {
|
||||
conference && conference.sendEndpointMessage(to, {
|
||||
conference?.sendEndpointMessage(to, {
|
||||
name: ENDPOINT_TEXT_MESSAGE_NAME,
|
||||
text: message
|
||||
});
|
||||
@@ -334,7 +338,7 @@ function _registerForNativeEvents(store) {
|
||||
const remoteParticipants = getRemoteParticipants(store);
|
||||
const localParticipant = getLocalParticipant(store);
|
||||
|
||||
participantsInfo.push(_participantToParticipantInfo(localParticipant));
|
||||
localParticipant && participantsInfo.push(_participantToParticipantInfo(localParticipant));
|
||||
remoteParticipants.forEach(participant => {
|
||||
if (!participant.fakeParticipant) {
|
||||
participantsInfo.push(_participantToParticipantInfo(participant));
|
||||
@@ -401,12 +405,12 @@ function _unregisterForNativeEvents() {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _registerForEndpointTextMessages(store) {
|
||||
function _registerForEndpointTextMessages(store: IStore) {
|
||||
const conference = getCurrentConference(store.getState());
|
||||
|
||||
conference && conference.on(
|
||||
conference?.on(
|
||||
JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
|
||||
(...args) => {
|
||||
(...args: any[]) => {
|
||||
if (args && args.length >= 2) {
|
||||
const [ sender, eventData ] = args;
|
||||
|
||||
@@ -422,9 +426,9 @@ function _registerForEndpointTextMessages(store) {
|
||||
}
|
||||
});
|
||||
|
||||
conference.on(
|
||||
conference?.on(
|
||||
JitsiConferenceEvents.MESSAGE_RECEIVED,
|
||||
(id, message, timestamp) => {
|
||||
(id: string, message: string, timestamp: number) => {
|
||||
sendEvent(
|
||||
store,
|
||||
CHAT_MESSAGE_RECEIVED,
|
||||
@@ -437,10 +441,10 @@ function _registerForEndpointTextMessages(store) {
|
||||
}
|
||||
);
|
||||
|
||||
conference.on(
|
||||
conference?.on(
|
||||
JitsiConferenceEvents.PRIVATE_MESSAGE_RECEIVED,
|
||||
(id, message, timestamp) => {
|
||||
sendEvent(
|
||||
(id: string, message: string, timestamp: number) => {
|
||||
sendEvent(
|
||||
store,
|
||||
CHAT_MESSAGE_RECEIVED,
|
||||
/* data */ {
|
||||
@@ -449,7 +453,7 @@ function _registerForEndpointTextMessages(store) {
|
||||
isPrivate: true,
|
||||
timestamp
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -462,7 +466,7 @@ function _registerForEndpointTextMessages(store) {
|
||||
* {@code error}.
|
||||
*/
|
||||
function _toErrorString(
|
||||
error: Error | { message: ?string, name: ?string } | string) {
|
||||
error: Error | { message?: string; name?: string; } | string) {
|
||||
// XXX In lib-jitsi-meet and jitsi-meet we utilize errors in the form of
|
||||
// strings, Error instances, and plain objects which resemble Error.
|
||||
return (
|
||||
@@ -487,7 +491,7 @@ function _toErrorString(
|
||||
* @param {Action} action - The redux action.
|
||||
* @returns {void}
|
||||
*/
|
||||
function _maybeTriggerEarlyConferenceWillJoin(store, action) {
|
||||
function _maybeTriggerEarlyConferenceWillJoin(store: IStore, action: AnyAction) {
|
||||
const { locationURL } = store.getState()['features/base/connection'];
|
||||
const { room } = action;
|
||||
|
||||
@@ -518,18 +522,19 @@ function _normalizeUrl(url: URL) {
|
||||
* @returns {void}
|
||||
*/
|
||||
function _sendConferenceEvent(
|
||||
store: Object,
|
||||
store: IStore,
|
||||
action: {
|
||||
conference: Object,
|
||||
type: string,
|
||||
url: ?string
|
||||
conference: IJitsiConference;
|
||||
isAudioMuted?: boolean;
|
||||
type: string;
|
||||
url?: string;
|
||||
}) {
|
||||
const { conference, type, ...data } = action;
|
||||
|
||||
// For these (redux) actions, conference identifies a JitsiConference
|
||||
// instance. The external API cannot transport such an object so we have to
|
||||
// transport an "equivalent".
|
||||
if (conference) {
|
||||
if (conference) { // @ts-ignore
|
||||
data.url = _normalizeUrl(conference[JITSI_CONFERENCE_URL_KEY]);
|
||||
|
||||
const localTracks = getLocalTracks(store.getState()['features/base/tracks']);
|
||||
@@ -569,7 +574,7 @@ function _sendConferenceEvent(
|
||||
* @returns {boolean} If the specified event is to not be sent, {@code true};
|
||||
* otherwise, {@code false}.
|
||||
*/
|
||||
function _swallowConferenceLeft({ getState }, action, { url }) {
|
||||
function _swallowConferenceLeft({ getState }: IStore, action: AnyAction, { url }: { url: string; }) {
|
||||
// XXX Internally, we work with JitsiConference instances. Externally
|
||||
// though, we deal with URL strings. The relation between the two is many to
|
||||
// one so it's technically and practically possible (by externally loading
|
||||
@@ -602,7 +607,7 @@ function _swallowConferenceLeft({ getState }, action, { url }) {
|
||||
* @returns {boolean} If the specified event is to not be sent, {@code true};
|
||||
* otherwise, {@code false}.
|
||||
*/
|
||||
function _swallowEvent(store, action, data) {
|
||||
function _swallowEvent(store: IStore, action: AnyAction, data: any) {
|
||||
switch (action.type) {
|
||||
case CONFERENCE_LEFT:
|
||||
return _swallowConferenceLeft(store, action, data);
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { _SET_IMMERSIVE_LISTENER } from './actionTypes';
|
||||
|
||||
/**
|
||||
@@ -13,7 +11,7 @@ import { _SET_IMMERSIVE_LISTENER } from './actionTypes';
|
||||
* listener: ?Function
|
||||
* }}
|
||||
*/
|
||||
export function _setImmersiveListener(listener: ?Function) {
|
||||
export function _setImmersiveListener(listener?: Function) {
|
||||
return {
|
||||
type: _SET_IMMERSIVE_LISTENER,
|
||||
listener
|
||||
@@ -1,7 +1,8 @@
|
||||
// @flow
|
||||
|
||||
// @ts-expect-error
|
||||
import { Immersive } from 'react-native-immersive';
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
import { IStore } from '../../app/types';
|
||||
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../../base/app/actionTypes';
|
||||
import { getCurrentConference } from '../../base/conference/functions';
|
||||
import { isAnyDialogOpen } from '../../base/dialog/functions';
|
||||
@@ -69,7 +70,7 @@ StateListenerRegistry.register(
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _onImmersiveChange({ getState }) {
|
||||
function _onImmersiveChange({ getState }: IStore) {
|
||||
const state = getState();
|
||||
const { appState } = state['features/background'];
|
||||
|
||||
@@ -115,7 +116,7 @@ function _setFullScreen(fullScreen: boolean) {
|
||||
* @private
|
||||
* @returns {Object} The value returned by {@code next(action)}.
|
||||
*/
|
||||
function _setImmersiveListenerF({ getState }, next, action) {
|
||||
function _setImmersiveListenerF({ getState }: IStore, next: Function, action: AnyAction) {
|
||||
// XXX The React Native module Immersive is only implemented on Android and
|
||||
// throws on other platforms.
|
||||
if (Platform.OS === 'android') {
|
||||
@@ -3,6 +3,7 @@ import { createStackNavigator } from '@react-navigation/stack';
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../../../app/types';
|
||||
import LobbyChatScreen from '../../../../../lobby/components/native/LobbyChatScreen';
|
||||
import LobbyScreen from '../../../../../lobby/components/native/LobbyScreen';
|
||||
import { screen } from '../../../routes';
|
||||
@@ -18,12 +19,14 @@ const LobbyStack = createStackNavigator();
|
||||
|
||||
const LobbyNavigationContainer = () => {
|
||||
const { isLobbyChatActive }
|
||||
= useSelector(state => state['features/chat']);
|
||||
= useSelector((state: IReduxState) => state['features/chat']);
|
||||
|
||||
return (
|
||||
<NavigationContainer
|
||||
independent = { true }
|
||||
ref = { lobbyNavigationContainerRef }
|
||||
|
||||
// @ts-ignore
|
||||
theme = { navigationContainerTheme }>
|
||||
<LobbyStack.Navigator
|
||||
screenOptions = {{
|
||||
@@ -1,12 +1,10 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import { GestureResponderEvent } from 'react-native';
|
||||
|
||||
import { IconArrowBack } from '../../../../base/icons/svg';
|
||||
import HeaderNavigationButton
|
||||
from '../HeaderNavigationButton';
|
||||
|
||||
|
||||
/**
|
||||
* Render header arrow back button for navigation.
|
||||
*
|
||||
@@ -14,7 +12,7 @@ import HeaderNavigationButton
|
||||
* function.
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
export function renderArrowBackButton(onPress: Function) {
|
||||
export function renderArrowBackButton(onPress: (e?: GestureResponderEvent | MouseEvent) => void) {
|
||||
return (
|
||||
<HeaderNavigationButton
|
||||
onPress = { onPress }
|
||||
@@ -1,9 +1,11 @@
|
||||
import { appNavigate } from '../../app/actions';
|
||||
import { AnyAction } from 'redux';
|
||||
|
||||
import { appNavigate } from '../../app/actions.native';
|
||||
import { IStore } from '../../app/types';
|
||||
import { CONFERENCE_FAILED } from '../../base/conference/actionTypes';
|
||||
import { JitsiConferenceErrors } from '../../base/lib-jitsi-meet';
|
||||
import MiddlewareRegistry from '../../base/redux/MiddlewareRegistry';
|
||||
|
||||
|
||||
MiddlewareRegistry.register(store => next => action => {
|
||||
switch (action.type) {
|
||||
|
||||
@@ -23,7 +25,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
* @param {Object} action - The Redux action.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function _conferenceFailed({ dispatch }, next, action) {
|
||||
function _conferenceFailed({ dispatch }: IStore, next: Function, action: AnyAction) {
|
||||
const { error } = action;
|
||||
|
||||
// We need to cover the case where knocking participant
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @flow */
|
||||
|
||||
import { Alert } from 'react-native';
|
||||
|
||||
import { isRoomValid } from '../../base/conference/functions';
|
||||
@@ -47,7 +45,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _alertPermissionErrorWithSettings(trackType) {
|
||||
function _alertPermissionErrorWithSettings(trackType: string) {
|
||||
/* eslint-disable indent */
|
||||
const message = trackType === 'video'
|
||||
? i18next.t('dialog.permissionCameraRequiredError')
|
||||
@@ -1,8 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import { NativeModules } from 'react-native';
|
||||
import type { Dispatch } from 'redux';
|
||||
|
||||
import { IStore } from '../../app/types';
|
||||
import { PIP_ENABLED } from '../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../base/flags/functions';
|
||||
import Platform from '../../base/react/Platform.native';
|
||||
@@ -21,7 +19,7 @@ import logger from './logger';
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function enterPictureInPicture() {
|
||||
return (dispatch: Dispatch<any>, getState: Function) => {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
// XXX At the time of this writing this action can only be dispatched by
|
||||
// the button which is on the conference view, which means that it's
|
||||
// fine to enter PiP mode.
|
||||
@@ -37,7 +35,7 @@ export function enterPictureInPicture() {
|
||||
|
||||
p.then(
|
||||
() => dispatch({ type: ENTER_PICTURE_IN_PICTURE }),
|
||||
e => logger.warn(`Error entering PiP mode: ${e}`));
|
||||
(e: string) => logger.warn(`Error entering PiP mode: ${e}`));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,33 +1,27 @@
|
||||
// @flow
|
||||
|
||||
import { NativeModules, Platform } from 'react-native';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { PIP_ENABLED, PIP_WHILE_SCREEN_SHARING_ENABLED } from '../../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../../base/flags/functions';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
import { IconArrowDown } from '../../../base/icons/svg';
|
||||
import AbstractButton, { IProps as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton';
|
||||
import { isLocalVideoTrackDesktop } from '../../../base/tracks/functions';
|
||||
import { isLocalVideoTrackDesktop } from '../../../base/tracks/functions.native';
|
||||
import { enterPictureInPicture } from '../actions';
|
||||
|
||||
type Props = AbstractButtonProps & {
|
||||
interface IProps extends AbstractButtonProps {
|
||||
|
||||
/**
|
||||
* Whether Picture-in-Picture is enabled or not.
|
||||
*/
|
||||
_enabled: boolean,
|
||||
|
||||
/**
|
||||
* The redux {@code dispatch} function.
|
||||
*/
|
||||
dispatch: Function
|
||||
};
|
||||
_enabled: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* An implementation of a button for entering Picture-in-Picture mode.
|
||||
*/
|
||||
class PictureInPictureButton extends AbstractButton<Props, *> {
|
||||
class PictureInPictureButton extends AbstractButton<IProps> {
|
||||
accessibilityLabel = 'toolbar.accessibilityLabel.pip';
|
||||
icon = IconArrowDown;
|
||||
label = 'toolbar.pip';
|
||||
@@ -63,7 +57,7 @@ class PictureInPictureButton extends AbstractButton<Props, *> {
|
||||
* _enabled: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
const pipEnabled = Boolean(getFeatureFlag(state, PIP_ENABLED));
|
||||
const pipWhileScreenSharingEnabled = getFeatureFlag(state, PIP_WHILE_SCREEN_SHARING_ENABLED, false);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { getLogger } from '../../base/logging/functions';
|
||||
|
||||
export default getLogger('features/mobile/pip');
|
||||
@@ -29,6 +29,6 @@ StateListenerRegistry.register(
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _setProximityEnabled(enabled) {
|
||||
function _setProximityEnabled(enabled: boolean) {
|
||||
NativeModules.Proximity.setEnabled(Boolean(enabled));
|
||||
}
|
||||
@@ -26,7 +26,7 @@ StateListenerRegistry.register(
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _setWakeLock(wakeLock) {
|
||||
function _setWakeLock(wakeLock: boolean) {
|
||||
if (wakeLock) {
|
||||
KeepAwake.activate();
|
||||
} else {
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { SET_CONFERENCE_TIMESTAMP, SET_SESSION_ID, SET_WATCH_REACHABLE } from './actionTypes';
|
||||
|
||||
/**
|
||||
@@ -1,5 +1,3 @@
|
||||
// @flow
|
||||
|
||||
import { getLogger } from '../../base/logging/functions';
|
||||
|
||||
export default getLogger('features/mobile/watchos');
|
||||
@@ -1,10 +1,10 @@
|
||||
// @flow
|
||||
|
||||
import { NativeModules, Platform } from 'react-native';
|
||||
import { updateApplicationContext, watchEvents } from 'react-native-watch-connectivity';
|
||||
|
||||
import { appNavigate } from '../../app/actions';
|
||||
import { IStore } from '../../app/types';
|
||||
import { APP_WILL_MOUNT } from '../../base/app/actionTypes';
|
||||
import { IStateful } from '../../base/app/types';
|
||||
import { CONFERENCE_JOINED } from '../../base/conference/actionTypes';
|
||||
import { getCurrentConferenceUrl } from '../../base/connection/functions';
|
||||
import { setAudioMuted } from '../../base/media/actions';
|
||||
@@ -68,7 +68,7 @@ watchOSEnabled && MiddlewareRegistry.register(store => next => action => {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _appWillMount({ dispatch, getState }) {
|
||||
function _appWillMount({ dispatch, getState }: IStore) {
|
||||
watchEvents.addListener('reachability', reachable => {
|
||||
dispatch(setWatchReachable(reachable));
|
||||
_updateApplicationContext(getState);
|
||||
@@ -96,7 +96,7 @@ function _appWillMount({ dispatch, getState }) {
|
||||
}
|
||||
break;
|
||||
case CMD_JOIN_CONFERENCE: {
|
||||
const newConferenceURL = message.data;
|
||||
const newConferenceURL: any = message.data;
|
||||
const oldConferenceURL = getCurrentConferenceUrl(getState());
|
||||
|
||||
if (oldConferenceURL !== newConferenceURL) {
|
||||
@@ -122,7 +122,7 @@ function _appWillMount({ dispatch, getState }) {
|
||||
* @returns {number}
|
||||
* @private
|
||||
*/
|
||||
function _getSessionId(stateful) {
|
||||
function _getSessionId(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
|
||||
return state['features/mobile/watchos'].sessionID;
|
||||
@@ -135,7 +135,7 @@ function _getSessionId(stateful) {
|
||||
* @returns {Array<Object>}
|
||||
* @private
|
||||
*/
|
||||
function _getRecentUrls(stateful) {
|
||||
function _getRecentUrls(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
const recentURLs = state['features/recent-list'];
|
||||
|
||||
@@ -154,7 +154,7 @@ function _getRecentUrls(stateful) {
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
function _isAudioMuted(stateful) {
|
||||
function _isAudioMuted(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
const { audio } = state['features/base/media'];
|
||||
|
||||
@@ -169,7 +169,7 @@ function _isAudioMuted(stateful) {
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function _updateApplicationContext(stateful) {
|
||||
function _updateApplicationContext(stateful: IStateful) {
|
||||
const state = toState(stateful);
|
||||
const { conferenceTimestamp, sessionID, watchReachable } = state['features/mobile/watchos'];
|
||||
|
||||
@@ -7,7 +7,6 @@ import { IStore } from '../../app/types';
|
||||
import AbstractPage from '../../base/react/components/AbstractPage';
|
||||
import { Container, Text } from '../../base/react/components/index';
|
||||
|
||||
// @ts-ignore
|
||||
import styles from './styles';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export default {};
|
||||
4
react/features/recent-list/components/styles.web.ts
Normal file
4
react/features/recent-list/components/styles.web.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export default {
|
||||
emptyListContainer: {},
|
||||
emptyListText: {}
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { ANDROID_SCREENSHARING_ENABLED } from '../../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../../base/flags/functions';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
@@ -13,28 +12,23 @@ import { isLocalVideoTrackDesktop } from '../../../base/tracks/functions.native'
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link ScreenSharingAndroidButton}.
|
||||
*/
|
||||
type Props = AbstractButtonProps & {
|
||||
interface IProps extends AbstractButtonProps {
|
||||
|
||||
/**
|
||||
* True if the button needs to be disabled.
|
||||
*/
|
||||
_disabled: boolean,
|
||||
_disabled: boolean;
|
||||
|
||||
/**
|
||||
* Whether video is currently muted or not.
|
||||
*/
|
||||
_screensharing: boolean,
|
||||
|
||||
/**
|
||||
* The redux {@code dispatch} function.
|
||||
*/
|
||||
dispatch: Function
|
||||
};
|
||||
_screensharing: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* An implementation of a button for toggling screen sharing.
|
||||
*/
|
||||
class ScreenSharingAndroidButton extends AbstractButton<Props, *> {
|
||||
class ScreenSharingAndroidButton extends AbstractButton<IProps> {
|
||||
accessibilityLabel = 'toolbar.accessibilityLabel.shareYourScreen';
|
||||
icon = IconScreenshare;
|
||||
label = 'toolbar.startScreenSharing';
|
||||
@@ -85,7 +79,7 @@ class ScreenSharingAndroidButton extends AbstractButton<Props, *> {
|
||||
* _screensharing: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state): Object {
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
const enabled = getFeatureFlag(state, ANDROID_SCREENSHARING_ENABLED, true);
|
||||
|
||||
return {
|
||||
@@ -5,11 +5,8 @@ import { connect } from 'react-redux';
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { isDesktopShareButtonDisabled } from '../../functions.native';
|
||||
|
||||
// @ts-ignore
|
||||
import ScreenSharingAndroidButton from './ScreenSharingAndroidButton.js';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import ScreenSharingIosButton from './ScreenSharingIosButton.js';
|
||||
import ScreenSharingAndroidButton from './ScreenSharingAndroidButton';
|
||||
import ScreenSharingIosButton from './ScreenSharingIosButton';
|
||||
|
||||
const ScreenSharingButton = (props: any) => (
|
||||
<>
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// @flow
|
||||
|
||||
import React from 'react';
|
||||
import { NativeModules, Platform, findNodeHandle } from 'react-native';
|
||||
import { ScreenCapturePickerView } from 'react-native-webrtc';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../../app/types';
|
||||
import { IOS_SCREENSHARING_ENABLED } from '../../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../../base/flags/functions';
|
||||
import { translate } from '../../../base/i18n/functions';
|
||||
@@ -15,23 +14,18 @@ import { isLocalVideoTrackDesktop } from '../../../base/tracks/functions.native'
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link ScreenSharingIosButton}.
|
||||
*/
|
||||
type Props = AbstractButtonProps & {
|
||||
interface IProps extends AbstractButtonProps {
|
||||
|
||||
/**
|
||||
* True if the button needs to be disabled.
|
||||
*/
|
||||
_disabled: boolean,
|
||||
_disabled: boolean;
|
||||
|
||||
/**
|
||||
* Whether video is currently muted or not.
|
||||
*/
|
||||
_screensharing: boolean,
|
||||
|
||||
/**
|
||||
* The redux {@code dispatch} function.
|
||||
*/
|
||||
dispatch: Function
|
||||
};
|
||||
_screensharing: boolean;
|
||||
}
|
||||
|
||||
const styles = {
|
||||
screenCapturePickerView: {
|
||||
@@ -42,9 +36,8 @@ const styles = {
|
||||
/**
|
||||
* An implementation of a button for toggling screen sharing on iOS.
|
||||
*/
|
||||
class ScreenSharingIosButton extends AbstractButton<Props, *> {
|
||||
_nativeComponent: ?Object;
|
||||
_setNativeComponent: Function;
|
||||
class ScreenSharingIosButton extends AbstractButton<IProps> {
|
||||
_nativeComponent: React.Component<any, any> | null;
|
||||
|
||||
accessibilityLabel = 'toolbar.accessibilityLabel.shareYourScreen';
|
||||
icon = IconScreenshare;
|
||||
@@ -57,7 +50,7 @@ class ScreenSharingIosButton extends AbstractButton<Props, *> {
|
||||
* @param {Object} props - The React {@code Component} props to initialize
|
||||
* the new {@code ScreenSharingIosButton} instance with.
|
||||
*/
|
||||
constructor(props) {
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
|
||||
this._nativeComponent = null;
|
||||
@@ -77,7 +70,7 @@ class ScreenSharingIosButton extends AbstractButton<Props, *> {
|
||||
<>
|
||||
{ super.render() }
|
||||
<ScreenCapturePickerView
|
||||
ref = { this._setNativeComponent }
|
||||
ref = { this._setNativeComponent } // @ts-ignore
|
||||
style = { styles.screenCapturePickerView } />
|
||||
</>
|
||||
);
|
||||
@@ -90,7 +83,7 @@ class ScreenSharingIosButton extends AbstractButton<Props, *> {
|
||||
* @param {ReactComponent} component - React Component.
|
||||
* @returns {void}
|
||||
*/
|
||||
_setNativeComponent(component) {
|
||||
_setNativeComponent(component: React.Component<any, any> | null) {
|
||||
this._nativeComponent = component;
|
||||
}
|
||||
|
||||
@@ -139,7 +132,7 @@ class ScreenSharingIosButton extends AbstractButton<Props, *> {
|
||||
* _disabled: boolean,
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state): Object {
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
const enabled = getFeatureFlag(state, IOS_SCREENSHARING_ENABLED, false);
|
||||
|
||||
return {
|
||||
@@ -28,14 +28,14 @@ const VisitorsCountLabel = () => {
|
||||
const visitorsCount = useSelector((state: IReduxState) =>
|
||||
state['features/visitors'].count || 0);
|
||||
|
||||
return !visitorsMode && visitorsCount > 0 && (
|
||||
return !visitorsMode && visitorsCount > 0 ? (
|
||||
<Label
|
||||
icon = { IconUsers }
|
||||
iconColor = { BaseTheme.palette.uiBackground }
|
||||
style = { styles.raisedHandsCountLabel }
|
||||
text = { `${getVisitorsShortText(visitorsCount)}` }
|
||||
textStyle = { styles.raisedHandsCountLabelText } />
|
||||
);
|
||||
) : null;
|
||||
};
|
||||
|
||||
export default VisitorsCountLabel;
|
||||
|
||||
Reference in New Issue
Block a user