From 8b8565bf601f6a77dd2f5377a43710b14fe6f6eb Mon Sep 17 00:00:00 2001 From: Robert Pintilii Date: Mon, 24 Apr 2023 20:14:02 +0300 Subject: [PATCH] ref(TS) Convert some native components to TS (#13259) --- .../react/components/AbstractContainer.ts | 2 +- .../features/base/styles/functions.native.ts | 2 +- react/features/base/styles/functions.web.ts | 2 +- .../components/native/ConnectionIndicator.tsx | 17 +--- .../components/AbstractRaisedHandIndicator.ts | 4 +- ...edIndicator.js => AudioMutedIndicator.tsx} | 2 - .../native/{Filmstrip.js => Filmstrip.tsx} | 75 +++++++------- .../{LocalThumbnail.js => LocalThumbnail.tsx} | 6 +- ...PinnedIndicator.js => PinnedIndicator.tsx} | 2 - ...ndIndicator.js => RaisedHandIndicator.tsx} | 9 +- ...eIndicator.js => ScreenShareIndicator.tsx} | 2 - .../native/{Thumbnail.js => Thumbnail.tsx} | 98 +++++++++---------- .../native/{TileView.js => TileView.tsx} | 79 +++++++-------- .../native/{styles.js => styles.ts} | 0 react/features/filmstrip/reducer.ts | 1 + .../native/{GifsMenu.js => GifsMenu.tsx} | 6 +- .../gifs/components/native/GifsMenuFooter.tsx | 10 +- .../native/{styles.js => styles.ts} | 0 .../components/AbstractGoogleSignInButton.ts | 33 ------- ...ative.js => GoogleSignInButton.native.tsx} | 33 +++++-- .../components/GoogleSignInButton.web.tsx | 24 ++++- .../components/{styles.js => styles.ts} | 2 - 22 files changed, 189 insertions(+), 220 deletions(-) rename react/features/filmstrip/components/native/{AudioMutedIndicator.js => AudioMutedIndicator.tsx} (98%) rename react/features/filmstrip/components/native/{Filmstrip.js => Filmstrip.tsx} (89%) rename react/features/filmstrip/components/native/{LocalThumbnail.js => LocalThumbnail.tsx} (75%) rename react/features/filmstrip/components/native/{PinnedIndicator.js => PinnedIndicator.tsx} (97%) rename react/features/filmstrip/components/native/{RaisedHandIndicator.js => RaisedHandIndicator.tsx} (80%) rename react/features/filmstrip/components/native/{ScreenShareIndicator.js => ScreenShareIndicator.tsx} (97%) rename react/features/filmstrip/components/native/{Thumbnail.js => Thumbnail.tsx} (87%) rename react/features/filmstrip/components/native/{TileView.js => TileView.tsx} (82%) rename react/features/filmstrip/components/native/{styles.js => styles.ts} (100%) rename react/features/gifs/components/native/{GifsMenu.js => GifsMenu.tsx} (91%) rename react/features/gifs/components/native/{styles.js => styles.ts} (100%) delete mode 100644 react/features/google-api/components/AbstractGoogleSignInButton.ts rename react/features/google-api/components/{GoogleSignInButton.native.js => GoogleSignInButton.native.tsx} (64%) rename react/features/google-api/components/{styles.js => styles.ts} (98%) diff --git a/react/features/base/react/components/AbstractContainer.ts b/react/features/base/react/components/AbstractContainer.ts index e1cf351a0d..c10be61e18 100644 --- a/react/features/base/react/components/AbstractContainer.ts +++ b/react/features/base/react/components/AbstractContainer.ts @@ -48,7 +48,7 @@ export interface IProps { * The style (as in stylesheet) to be applied to this * {@code AbstractContainer}. */ - style?: StyleType; + style?: StyleType | StyleType[]; tabIndex?: number; diff --git a/react/features/base/styles/functions.native.ts b/react/features/base/styles/functions.native.ts index 5a6e69094d..0650295f4a 100644 --- a/react/features/base/styles/functions.native.ts +++ b/react/features/base/styles/functions.native.ts @@ -9,7 +9,7 @@ export * from './functions.any'; * @param {StyleType} style - The passed style prop to the component. * @returns {StyleType} */ -export function getFixedPlatformStyle(style?: StyleType): StyleType { +export function getFixedPlatformStyle(style?: StyleType | StyleType[]) { // There is nothing to do on mobile - yet. return style ?? {}; diff --git a/react/features/base/styles/functions.web.ts b/react/features/base/styles/functions.web.ts index c2c2d129ff..2003613358 100644 --- a/react/features/base/styles/functions.web.ts +++ b/react/features/base/styles/functions.web.ts @@ -9,7 +9,7 @@ export * from './functions.any'; * @param {StyleType} style - The passed style prop to the component. * @returns {StyleType} */ -export function getFixedPlatformStyle(style?: StyleType) { +export function getFixedPlatformStyle(style?: StyleType | StyleType[]) { if (Array.isArray(style)) { const _style = {}; diff --git a/react/features/connection-indicator/components/native/ConnectionIndicator.tsx b/react/features/connection-indicator/components/native/ConnectionIndicator.tsx index a7281da1e1..dba1a27c46 100644 --- a/react/features/connection-indicator/components/native/ConnectionIndicator.tsx +++ b/react/features/connection-indicator/components/native/ConnectionIndicator.tsx @@ -1,5 +1,3 @@ -/* eslint-disable lines-around-comment */ - import React from 'react'; import { StyleProp, View, ViewStyle } from 'react-native'; import { connect } from 'react-redux'; @@ -12,12 +10,10 @@ import { getParticipantById, isScreenShareParticipant } from '../../../base/participants/functions'; -// @ts-ignore import BaseIndicator from '../../../base/react/components/native/BaseIndicator'; import { getTrackByMediaTypeAndParticipant } from '../../../base/tracks/functions.native'; -// @ts-ignore import indicatorStyles from '../../../filmstrip/components/native/styles'; import { isTrackStreamingStatusInactive, @@ -50,12 +46,12 @@ type IProps = AbstractProps & { /** * Whether the connection is inactive or not. */ - _isConnectionStatusInactive: boolean; + _isConnectionStatusInactive?: boolean; /** * Whether the connection is interrupted or not. */ - _isConnectionStatusInterrupted: boolean; + _isConnectionStatusInterrupted?: boolean; /** * Whether the current participant is a virtual screenshare. @@ -70,7 +66,7 @@ type IProps = AbstractProps & { /** * Icon style override. */ - iconStyle: any; + iconStyle?: any; }; type IState = { @@ -127,12 +123,10 @@ class ConnectionIndicator extends AbstractConnectionIndicator { _isVirtualScreenshareParticipant, _isConnectionStatusInactive, _isConnectionStatusInterrupted - // @ts-ignore } = this.props; const { showIndicator, stats - // @ts-ignore } = this.state; const { percent } = stats; @@ -167,10 +161,8 @@ class ConnectionIndicator extends AbstractConnectionIndicator { indicatorStyles.indicatorContainer as StyleProp, { backgroundColor: indicatorColor } ] }> - {/* @ts-ignore */} ); @@ -185,7 +177,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator { * @param {IProps} ownProps - The own props of the component. * @returns {IProps} */ -export function _mapStateToProps(state: IReduxState, ownProps: IProps) { +export function _mapStateToProps(state: IReduxState, ownProps: any) { const { participantId } = ownProps; const tracks = state['features/base/tracks']; const participant = participantId ? getParticipantById(state, participantId) : getLocalParticipant(state); @@ -212,5 +204,4 @@ export function _mapStateToProps(state: IReduxState, ownProps: IProps) { }; } -// @ts-ignore export default connect(_mapStateToProps)(ConnectionIndicator); diff --git a/react/features/filmstrip/components/AbstractRaisedHandIndicator.ts b/react/features/filmstrip/components/AbstractRaisedHandIndicator.ts index a0263bc8f9..b595f20444 100644 --- a/react/features/filmstrip/components/AbstractRaisedHandIndicator.ts +++ b/react/features/filmstrip/components/AbstractRaisedHandIndicator.ts @@ -20,7 +20,7 @@ export interface IProps { /** * Implements an abstract class for the RaisedHandIndicator component. */ -export default class AbstractRaisedHandIndicator

+export default abstract class AbstractRaisedHandIndicator

extends Component

{ /** @@ -41,7 +41,7 @@ export default class AbstractRaisedHandIndicator

* * @returns {React$Element<*>} */ - _renderIndicator: () => React.ReactElement; + abstract _renderIndicator(): React.ReactElement; } diff --git a/react/features/filmstrip/components/native/AudioMutedIndicator.js b/react/features/filmstrip/components/native/AudioMutedIndicator.tsx similarity index 98% rename from react/features/filmstrip/components/native/AudioMutedIndicator.js rename to react/features/filmstrip/components/native/AudioMutedIndicator.tsx index 0640d505a1..668c75332b 100644 --- a/react/features/filmstrip/components/native/AudioMutedIndicator.js +++ b/react/features/filmstrip/components/native/AudioMutedIndicator.tsx @@ -1,5 +1,3 @@ -// @flow - import React, { Component } from 'react'; import { IconMicSlash } from '../../../base/icons/svg'; diff --git a/react/features/filmstrip/components/native/Filmstrip.js b/react/features/filmstrip/components/native/Filmstrip.tsx similarity index 89% rename from react/features/filmstrip/components/native/Filmstrip.js rename to react/features/filmstrip/components/native/Filmstrip.tsx index f9faea1204..84bf55a047 100644 --- a/react/features/filmstrip/components/native/Filmstrip.js +++ b/react/features/filmstrip/components/native/Filmstrip.tsx @@ -1,10 +1,9 @@ -// @flow - import React, { PureComponent } from 'react'; -import { FlatList } from 'react-native'; +import { FlatList, ViewStyle, ViewToken } from 'react-native'; import { SafeAreaView, withSafeAreaInsets } from 'react-native-safe-area-context'; import { connect } from 'react-redux'; +import { IReduxState, IStore } from '../../../app/types'; import { getLocalParticipant } from '../../../base/participants/functions'; import Platform from '../../../base/react/Platform.native'; import { ASPECT_RATIO_NARROW } from '../../../base/responsive-ui/constants'; @@ -24,54 +23,54 @@ import styles from './styles'; // Immutable reference to avoid re-renders. -const NO_REMOTE_VIDEOS = []; +const NO_REMOTE_VIDEOS: any[] = []; /** * Filmstrip component's property types. */ -type Props = { +interface IProps { /** * Application's aspect ratio. */ - _aspectRatio: Symbol, + _aspectRatio: Symbol; - _clientWidth: number, + _clientHeight: number; - _clientHeight: number, + _clientWidth: number; /** * Whether or not to hide the self view. */ - _disableSelfView: boolean, + _disableSelfView: boolean; - /** - * Whether or not the toolbox is displayed. - */ - _toolboxVisible: Boolean, - - _localParticipantId: string, + _localParticipantId: string; /** * The participants in the conference. */ - _participants: Array, + _participants: Array; + + /** + * Whether or not the toolbox is displayed. + */ + _toolboxVisible: Boolean; /** * The indicator which determines whether the filmstrip is visible. */ - _visible: boolean, + _visible: boolean; /** * Invoked to trigger state changes in Redux. */ - dispatch: Function, + dispatch: IStore['dispatch']; /** * Object containing the safe area insets. */ - insets: Object, -}; + insets: Object; +} /** * Implements a React {@link Component} which represents the filmstrip on @@ -79,7 +78,7 @@ type Props = { * * @augments Component */ -class Filmstrip extends PureComponent { +class Filmstrip extends PureComponent { /** * Whether the local participant should be rendered separately from the * remote participants ie outside of their {@link ScrollView}. @@ -96,7 +95,7 @@ class Filmstrip extends PureComponent { * * @inheritdoc */ - constructor(props) { + constructor(props: IProps) { super(props); // XXX Our current design is to have the local participant separate from @@ -129,15 +128,13 @@ class Filmstrip extends PureComponent { this._renderThumbnail = this._renderThumbnail.bind(this); } - _keyExtractor: string => string; - /** * Returns a key for a passed item of the list. * * @param {string} item - The user ID. * @returns {string} - The user ID. */ - _keyExtractor(item) { + _keyExtractor(item: string) { return item; } @@ -166,16 +163,14 @@ class Filmstrip extends PureComponent { }); } - _getItemLayout: (?Array, number) => {length: number, offset: number, index: number}; - /** * Optimization for FlatList. Returns the length, offset and index for an item. * - * @param {Array} data - The data array with user IDs. + * @param {Array} _data - The data array with user IDs. * @param {number} index - The index number of the item. * @returns {Object} */ - _getItemLayout(data, index) { + _getItemLayout(_data: string[] | null | undefined, index: number) { const { _aspectRatio } = this.props; const isNarrowAspectRatio = _aspectRatio === ASPECT_RATIO_NARROW; const length = isNarrowAspectRatio ? styles.thumbnail.width : styles.thumbnail.height; @@ -187,8 +182,6 @@ class Filmstrip extends PureComponent { }; } - _onViewableItemsChanged: Object => void; - /** * A handler for visible items changes. * @@ -196,7 +189,7 @@ class Filmstrip extends PureComponent { * @param {Array} data.viewableItems - The visible items array. * @returns {void} */ - _onViewableItemsChanged({ viewableItems = [] }) { + _onViewableItemsChanged({ viewableItems = [] }: { viewableItems: ViewToken[]; }) { const { _disableSelfView } = this.props; if (!this._separateLocalThumbnail && !_disableSelfView && viewableItems[0]?.index === 0) { @@ -209,8 +202,8 @@ class Filmstrip extends PureComponent { return; } - let startIndex = viewableItems[0].index; - let endIndex = viewableItems[viewableItems.length - 1].index; + let startIndex = Number(viewableItems[0].index); + let endIndex = Number(viewableItems[viewableItems.length - 1].index); if (!this._separateLocalThumbnail && !_disableSelfView) { // We are off by one in the remote participants array. @@ -221,15 +214,13 @@ class Filmstrip extends PureComponent { this.props.dispatch(setVisibleRemoteParticipants(startIndex, endIndex)); } - _renderThumbnail: Object => Object; - /** * Creates React Element to display each participant in a thumbnail. * * @private * @returns {ReactElement} */ - _renderThumbnail({ item /* , index , separators */ }) { + _renderThumbnail({ item }: { item: string; }) { return ( { } return ( - + style = { filmstripStyle as ViewStyle }> { this._separateLocalThumbnail && !isNarrowAspectRatio @@ -317,9 +308,9 @@ class Filmstrip extends PureComponent { * * @param {Object} state - The redux state. * @private - * @returns {Props} + * @returns {IProps} */ -function _mapStateToProps(state) { +function _mapStateToProps(state: IReduxState) { const { enabled, remoteParticipants } = state['features/filmstrip']; const disableSelfView = getHideSelfView(state); const showRemoteVideos = shouldRemoteVideosBeVisible(state); @@ -330,7 +321,7 @@ function _mapStateToProps(state) { _clientHeight: responsiveUI.clientHeight, _clientWidth: responsiveUI.clientWidth, _disableSelfView: disableSelfView, - _localParticipantId: getLocalParticipant(state)?.id, + _localParticipantId: getLocalParticipant(state)?.id ?? '', _participants: showRemoteVideos ? remoteParticipants : NO_REMOTE_VIDEOS, _toolboxVisible: isToolboxVisible(state), _visible: enabled && isFilmstripVisible(state) diff --git a/react/features/filmstrip/components/native/LocalThumbnail.js b/react/features/filmstrip/components/native/LocalThumbnail.tsx similarity index 75% rename from react/features/filmstrip/components/native/LocalThumbnail.js rename to react/features/filmstrip/components/native/LocalThumbnail.tsx index b30cc43ce6..55848d8a44 100644 --- a/react/features/filmstrip/components/native/LocalThumbnail.js +++ b/react/features/filmstrip/components/native/LocalThumbnail.tsx @@ -1,7 +1,5 @@ -// @flow - import React from 'react'; -import { View } from 'react-native'; +import { View, ViewStyle } from 'react-native'; import Thumbnail from './Thumbnail'; import styles from './styles'; @@ -14,7 +12,7 @@ import styles from './styles'; */ export default function LocalThumbnail() { return ( - + ); diff --git a/react/features/filmstrip/components/native/PinnedIndicator.js b/react/features/filmstrip/components/native/PinnedIndicator.tsx similarity index 97% rename from react/features/filmstrip/components/native/PinnedIndicator.js rename to react/features/filmstrip/components/native/PinnedIndicator.tsx index b5f1b876a7..3c7459a54c 100644 --- a/react/features/filmstrip/components/native/PinnedIndicator.js +++ b/react/features/filmstrip/components/native/PinnedIndicator.tsx @@ -1,5 +1,3 @@ -// @flow - import React from 'react'; import { IconPin } from '../../../base/icons/svg'; diff --git a/react/features/filmstrip/components/native/RaisedHandIndicator.js b/react/features/filmstrip/components/native/RaisedHandIndicator.tsx similarity index 80% rename from react/features/filmstrip/components/native/RaisedHandIndicator.js rename to react/features/filmstrip/components/native/RaisedHandIndicator.tsx index 9cde13c136..00c9a59400 100644 --- a/react/features/filmstrip/components/native/RaisedHandIndicator.js +++ b/react/features/filmstrip/components/native/RaisedHandIndicator.tsx @@ -1,12 +1,11 @@ -// @flow - import React from 'react'; -import { View } from 'react-native'; +import { View, ViewStyle } from 'react-native'; import { connect } from 'react-redux'; import { IconRaiseHand } from '../../../base/icons/svg'; import BaseIndicator from '../../../base/react/components/native/BaseIndicator'; import AbstractRaisedHandIndicator, { + IProps, _mapStateToProps } from '../AbstractRaisedHandIndicator'; @@ -18,7 +17,7 @@ import styles from './styles'; * * @augments Component */ -class RaisedHandIndicator extends AbstractRaisedHandIndicator { +class RaisedHandIndicator extends AbstractRaisedHandIndicator { /** * Renders the platform specific indicator element. * @@ -26,7 +25,7 @@ class RaisedHandIndicator extends AbstractRaisedHandIndicator { */ _renderIndicator() { return ( - + diff --git a/react/features/filmstrip/components/native/ScreenShareIndicator.js b/react/features/filmstrip/components/native/ScreenShareIndicator.tsx similarity index 97% rename from react/features/filmstrip/components/native/ScreenShareIndicator.js rename to react/features/filmstrip/components/native/ScreenShareIndicator.tsx index f003cb3f62..0c77719feb 100644 --- a/react/features/filmstrip/components/native/ScreenShareIndicator.js +++ b/react/features/filmstrip/components/native/ScreenShareIndicator.tsx @@ -1,5 +1,3 @@ -// @flow - import React from 'react'; import { IconScreenshare } from '../../../base/icons/svg'; diff --git a/react/features/filmstrip/components/native/Thumbnail.js b/react/features/filmstrip/components/native/Thumbnail.tsx similarity index 87% rename from react/features/filmstrip/components/native/Thumbnail.js rename to react/features/filmstrip/components/native/Thumbnail.tsx index 55b7349dd2..dc4f908a11 100644 --- a/react/features/filmstrip/components/native/Thumbnail.js +++ b/react/features/filmstrip/components/native/Thumbnail.tsx @@ -1,8 +1,8 @@ import React, { PureComponent } from 'react'; -import { Image, View } from 'react-native'; +import { Image, ImageStyle, View, ViewStyle } from 'react-native'; import { connect } from 'react-redux'; -import type { Dispatch } from 'redux'; +import { IReduxState, IStore } from '../../../app/types'; import { JitsiTrackEvents } from '../../../base/lib-jitsi-meet'; import { MEDIA_TYPE, VIDEO_TYPE } from '../../../base/media/constants'; import { pinParticipant } from '../../../base/participants/actions'; @@ -18,14 +18,16 @@ import { } from '../../../base/participants/functions'; import { FakeParticipant } from '../../../base/participants/types'; import Container from '../../../base/react/components/native/Container'; +import { StyleType } from '../../../base/styles/functions.any'; import { trackStreamingStatusChanged } from '../../../base/tracks/actions.native'; import { getTrackByMediaTypeAndParticipant, getVideoTrackByParticipant } from '../../../base/tracks/functions.native'; +import { ITrack } from '../../../base/tracks/types'; import ConnectionIndicator from '../../../connection-indicator/components/native/ConnectionIndicator'; import DisplayNameLabel from '../../../display-name/components/native/DisplayNameLabel'; -import { getGifDisplayMode, getGifForParticipant } from '../../../gifs/functions'; +import { getGifDisplayMode, getGifForParticipant } from '../../../gifs/functions.native'; import { showConnectionStatus, showContextMenuDetails, @@ -44,42 +46,42 @@ import styles, { AVATAR_SIZE } from './styles'; /** * Thumbnail component's property types. */ -type Props = { +interface IProps { /** * Whether local audio (microphone) is muted or not. */ - _audioMuted: boolean, - - /** - * URL of GIF sent by this participant, null if there's none. - */ - _gifSrc: ?string, + _audioMuted: boolean; /** * The type of participant if the participant is fake. */ - _fakeParticipant?: FakeParticipant, + _fakeParticipant?: FakeParticipant; + + /** + * URL of GIF sent by this participant, null if there's none. + */ + _gifSrc?: string; /** * Indicates whether the participant is screen sharing. */ - _isScreenShare: boolean, + _isScreenShare: boolean; /** * Indicates whether the thumbnail is for a virtual screenshare participant. */ - _isVirtualScreenshare: boolean, + _isVirtualScreenshare: boolean; /** * Indicates whether the participant is local. */ - _local: boolean, + _local?: boolean; /** * Shared video local participant owner. */ - _localVideoOwner: boolean, + _localVideoOwner: boolean; /** * The ID of the participant obtain from the participant object in Redux. @@ -87,71 +89,71 @@ type Props = { * NOTE: Generally it should be the same as the participantID prop except the case where the passed * participantID doesn't correspond to any of the existing participants. */ - _participantId: string, + _participantId: string; /** * Indicates whether the participant is pinned or not. */ - _pinned: boolean, + _pinned?: boolean; /** * Whether or not the participant has the hand raised. */ - _raisedHand: boolean, + _raisedHand: boolean; /** * Whether to show the dominant speaker indicator or not. */ - _renderDominantSpeakerIndicator: boolean, + _renderDominantSpeakerIndicator?: boolean; /** * Whether to show the moderator indicator or not. */ - _renderModeratorIndicator: boolean, + _renderModeratorIndicator: boolean; /** * The video track that will be displayed in the thumbnail. */ - _videoTrack: ?Object, + _videoTrack?: ITrack; /** * Invoked to trigger state changes in Redux. */ - dispatch: Dispatch, + dispatch: IStore['dispatch']; /** - * The height of the thumnail. + * The height of the thumbnail. */ - height: ?number, + height?: number; /** * The ID of the participant related to the thumbnail. */ - participantID: ?string, + participantID?: string; /** * Whether to display or hide the display name of the participant in the thumbnail. */ - renderDisplayName: ?boolean, + renderDisplayName?: boolean; /** * If true, it tells the thumbnail that it needs to behave differently. E.g. React differently to a single tap. */ - tileView?: boolean -}; + tileView?: boolean; +} /** * React component for video thumbnail. */ -class Thumbnail extends PureComponent { +class Thumbnail extends PureComponent { /** * Creates new Thumbnail component. * - * @param {Props} props - The props of the component. + * @param {IProps} props - The props of the component. * @returns {Thumbnail} */ - constructor(props: Props) { + constructor(props: IProps) { super(props); this._onClick = this._onClick.bind(this); @@ -159,8 +161,6 @@ class Thumbnail extends PureComponent { this.handleTrackStreamingStatusChanged = this.handleTrackStreamingStatusChanged.bind(this); } - _onClick: () => void; - /** * Thumbnail click handler. * @@ -176,8 +176,6 @@ class Thumbnail extends PureComponent { } } - _onThumbnailLongPress: () => void; - /** * Thumbnail long press handler. * @@ -219,11 +217,11 @@ class Thumbnail extends PureComponent { if (!_fakeParticipant || _isVirtualScreenshare) { indicators.push( + style = { styles.thumbnailTopLeftIndicatorContainer as ViewStyle }> { !_isVirtualScreenshare && } { !_isVirtualScreenshare && } { tileView && (isScreenShare || _isVirtualScreenshare) && ( - + ) } @@ -231,7 +229,9 @@ class Thumbnail extends PureComponent { indicators.push( - + { audioMuted && !_isVirtualScreenshare && } { !tileView && _pinned && } { renderModeratorIndicator && !_isVirtualScreenshare && } @@ -275,7 +275,7 @@ class Thumbnail extends PureComponent { * @inheritdoc * @returns {void} */ - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps: IProps) { // TODO: after converting this component to a react function component, // use a custom hook to update local track streaming status. const { _videoTrack, dispatch } = this.props; @@ -323,7 +323,7 @@ class Thumbnail extends PureComponent { * @param {JitsiTrackStreamingStatus} streamingStatus - The updated track streaming status. * @returns {void} */ - handleTrackStreamingStatusChanged(jitsiTrack, streamingStatus) { + handleTrackStreamingStatusChanged(jitsiTrack: any, streamingStatus: string) { this.props.dispatch(trackStreamingStatusChanged(jitsiTrack, streamingStatus)); } @@ -363,11 +363,11 @@ class Thumbnail extends PureComponent { styleOverrides, _raisedHand && !_isVirtualScreenshare ? styles.thumbnailRaisedHand : null, _renderDominantSpeakerIndicator && !_isVirtualScreenshare ? styles.thumbnailDominantSpeaker : null - ] } + ] as StyleType[] } touchFeedback = { false }> { _gifSrc ? + style = { styles.thumbnailGif as ImageStyle } /> : <> { * Function that maps parts of Redux state tree into component props. * * @param {Object} state - Redux state. - * @param {Props} ownProps - Properties of component. + * @param {IProps} ownProps - Properties of component. * @returns {Object} */ -function _mapStateToProps(state, ownProps) { +function _mapStateToProps(state: IReduxState, ownProps: any) { const { ownerId } = state['features/shared-video']; const tracks = state['features/base/tracks']; const { participantID, tileView } = ownProps; const participant = getParticipantByIdOrUndefined(state, participantID); - const localParticipantId = getLocalParticipant(state).id; + const localParticipantId = getLocalParticipant(state)?.id; const id = participant?.id; const audioTrack = getTrackByMediaTypeAndParticipant(tracks, MEDIA_TYPE.AUDIO, id); const videoTrack = getVideoTrackByParticipant(state, participant); const isScreenShare = videoTrack?.videoType === VIDEO_TYPE.DESKTOP; const participantCount = getParticipantCount(state); - const renderDominantSpeakerIndicator = participant && participant.dominantSpeaker && participantCount > 2; + const renderDominantSpeakerIndicator = participant?.dominantSpeaker && participantCount > 2; const _isEveryoneModerator = isEveryoneModerator(state); const renderModeratorIndicator = tileView && !_isEveryoneModerator && participant?.role === PARTICIPANT_ROLE.MODERATOR; - const { gifUrl: gifSrc } = getGifForParticipant(state, id); + const { gifUrl: gifSrc } = getGifForParticipant(state, id ?? ''); const mode = getGifDisplayMode(state); return { _audioMuted: audioTrack?.muted ?? true, _fakeParticipant: participant?.fakeParticipant, - _gifSrc: mode === 'chat' ? null : gifSrc, + _gifSrc: mode === 'chat' ? undefined : gifSrc, _isScreenShare: isScreenShare, _isVirtualScreenshare: isScreenShareParticipant(participant), _local: participant?.local, _localVideoOwner: Boolean(ownerId === localParticipantId), - _participantId: id, + _participantId: id ?? '', _pinned: participant?.pinned, _raisedHand: hasRaisedHand(participant), _renderDominantSpeakerIndicator: renderDominantSpeakerIndicator, diff --git a/react/features/filmstrip/components/native/TileView.js b/react/features/filmstrip/components/native/TileView.tsx similarity index 82% rename from react/features/filmstrip/components/native/TileView.js rename to react/features/filmstrip/components/native/TileView.tsx index 6d17e89125..806e53f5ab 100644 --- a/react/features/filmstrip/components/native/TileView.js +++ b/react/features/filmstrip/components/native/TileView.tsx @@ -1,16 +1,17 @@ -// @flow - import React, { PureComponent } from 'react'; import { FlatList, + GestureResponderEvent, SafeAreaView, - TouchableWithoutFeedback + TouchableWithoutFeedback, + ViewToken } 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 type { Dispatch } from 'redux'; +import { IReduxState, IStore } from '../../../app/types'; import { getLocalParticipant, getParticipantCountWithFake } from '../../../base/participants/functions'; +import { ILocalParticipant } from '../../../base/participants/types'; import { getHideSelfView } from '../../../base/settings/functions.any'; import { setVisibleRemoteParticipants } from '../../actions.web'; @@ -20,74 +21,74 @@ import styles from './styles'; /** * The type of the React {@link Component} props of {@link TileView}. */ -type Props = { +interface IProps { /** * Application's aspect ratio. */ - _aspectRatio: Symbol, + _aspectRatio: Symbol; /** * The number of columns. */ - _columns: number, + _columns: number; /** * Whether or not to hide the self view. */ - _disableSelfView: boolean, + _disableSelfView: boolean; /** * Application's viewport height. */ - _height: number, + _height: number; /** * The local participant. */ - _localParticipant: Object, + _localParticipant?: ILocalParticipant; /** * The number of participants in the conference. */ - _participantCount: number, + _participantCount: number; /** * An array with the IDs of the remote participants in the conference. */ - _remoteParticipants: Array, + _remoteParticipants: Array; /** * The thumbnail height. */ - _thumbnailHeight: number, + _thumbnailHeight?: number; /** * Application's viewport height. */ - _width: number, + _width: number; /** * Invoked to update the receiver video quality. */ - dispatch: Dispatch, + dispatch: IStore['dispatch']; /** * Object containing the safe area insets. */ - insets: Object, + insets: EdgeInsets; /** * Callback to invoke when tile view is tapped. */ - onClick: Function -}; + onClick: (e?: GestureResponderEvent) => void; +} /** * An empty array. The purpose of the constant is to use the same reference every time we need an empty array. * This will prevent unnecessary re-renders. */ -const EMPTY_ARRAY = []; +const EMPTY_ARRAY: any[] = []; /** * Implements a React {@link PureComponent} which displays thumbnails in a two @@ -95,17 +96,17 @@ const EMPTY_ARRAY = []; * * @augments PureComponent */ -class TileView extends PureComponent { +class TileView extends PureComponent { /** * The styles for the content container of the FlatList. */ - _contentContainerStyles: Object; + _contentContainerStyles: any; /** * The styles for the FlatList. */ - _flatListStyles: Object; + _flatListStyles: any; /** * The FlatList's viewabilityConfig. @@ -115,9 +116,9 @@ class TileView extends PureComponent { /** * Creates new TileView component. * - * @param {Props} props - The props of the component. + * @param {IProps} props - The props of the component. */ - constructor(props: Props) { + constructor(props: IProps) { super(props); this._keyExtractor = this._keyExtractor.bind(this); @@ -137,20 +138,16 @@ class TileView extends PureComponent { }; } - _keyExtractor: string => string; - /** * Returns a key for a passed item of the list. * * @param {string} item - The user ID. * @returns {string} - The user ID. */ - _keyExtractor(item) { + _keyExtractor(item: string) { return item; } - _onViewableItemsChanged: Object => void; - /** * A handler for visible items changes. * @@ -158,7 +155,7 @@ class TileView extends PureComponent { * @param {Array} data.viewableItems - The visible items array. * @returns {void} */ - _onViewableItemsChanged({ viewableItems = [] }: { viewableItems: Array }) { + _onViewableItemsChanged({ viewableItems = [] }: { viewableItems: ViewToken[]; }) { const { _disableSelfView } = this.props; if (viewableItems[0]?.index === 0 && !_disableSelfView) { @@ -172,8 +169,8 @@ class TileView extends PureComponent { } // We are off by one in the remote participants array. - const startIndex = viewableItems[0].index - (_disableSelfView ? 0 : 1); - const endIndex = viewableItems[viewableItems.length - 1].index - (_disableSelfView ? 0 : 1); + const startIndex = Number(viewableItems[0].index) - (_disableSelfView ? 0 : 1); + const endIndex = Number(viewableItems[viewableItems.length - 1].index) - (_disableSelfView ? 0 : 1); this.props.dispatch(setVisibleRemoteParticipants(startIndex, endIndex)); } @@ -187,7 +184,7 @@ class TileView extends PureComponent { render() { const { _columns, _height, _thumbnailHeight, _width, onClick } = this.props; const participants = this._getSortedParticipants(); - const initialRowsToRender = Math.ceil(_height / (_thumbnailHeight + (2 * styles.thumbnail.margin))); + const initialRowsToRender = Math.ceil(_height / (Number(_thumbnailHeight) + (2 * styles.thumbnail.margin))); if (this._flatListStyles.minHeight !== _height || this._flatListStyles.minWidth !== _width) { this._flatListStyles = { @@ -250,15 +247,13 @@ class TileView extends PureComponent { return [ _localParticipant?.id, ..._remoteParticipants ]; } - _renderThumbnail: Object => Object; - /** * Creates React Element to display each participant in a thumbnail. * * @private * @returns {ReactElement} */ - _renderThumbnail({ item/* , index , separators */ }) { + _renderThumbnail({ item }: { item: string; }) { const { _thumbnailHeight } = this.props; return ( @@ -278,18 +273,18 @@ class TileView extends PureComponent { * @param {Object} state - The redux state. * @param {Object} ownProps - Component props. * @private - * @returns {Props} + * @returns {IProps} */ -function _mapStateToProps(state, ownProps) { +function _mapStateToProps(state: IReduxState, ownProps: any) { const responsiveUi = state['features/base/responsive-ui']; const { remoteParticipants, tileViewDimensions } = state['features/filmstrip']; const disableSelfView = getHideSelfView(state); - const { height } = tileViewDimensions.thumbnailSize; - const { columns } = tileViewDimensions; + const { height } = tileViewDimensions?.thumbnailSize ?? {}; + const { columns } = tileViewDimensions ?? {}; return { _aspectRatio: responsiveUi.aspectRatio, - _columns: columns, + _columns: columns ?? 1, _disableSelfView: disableSelfView, _height: responsiveUi.clientHeight - (ownProps.insets?.top || 0), _insets: ownProps.insets, diff --git a/react/features/filmstrip/components/native/styles.js b/react/features/filmstrip/components/native/styles.ts similarity index 100% rename from react/features/filmstrip/components/native/styles.js rename to react/features/filmstrip/components/native/styles.ts diff --git a/react/features/filmstrip/reducer.ts b/react/features/filmstrip/reducer.ts index b7839593d6..bd71883538 100644 --- a/react/features/filmstrip/reducer.ts +++ b/react/features/filmstrip/reducer.ts @@ -184,6 +184,7 @@ interface IDimensions { } interface IFilmstripDimensions { + columns?: number; filmstripHeight?: number; filmstripWidth?: number; gridDimensions?: { diff --git a/react/features/gifs/components/native/GifsMenu.js b/react/features/gifs/components/native/GifsMenu.tsx similarity index 91% rename from react/features/gifs/components/native/GifsMenu.js rename to react/features/gifs/components/native/GifsMenu.tsx index 13b42581f4..7986b4bc6f 100644 --- a/react/features/gifs/components/native/GifsMenu.js +++ b/react/features/gifs/components/native/GifsMenu.tsx @@ -1,4 +1,4 @@ -import { GiphyContent, GiphyGridView, GiphyMediaType } from '@giphy/react-native-sdk'; +import { GiphyContent, GiphyGridView, GiphyMediaType, GiphyRating } from '@giphy/react-native-sdk'; import React, { useCallback, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useDispatch, useSelector } from 'react-redux'; @@ -9,7 +9,7 @@ import JitsiScreen from '../../../base/modal/components/JitsiScreen'; import Input from '../../../base/ui/components/native/Input'; import { sendMessage } from '../../../chat/actions.any'; import { goBack } from '../../../mobile/navigation/components/conference/ConferenceNavigationContainerRef'; -import { formatGifUrlMessage, getGifRating, getGifUrl, getGiphyProxyUrl } from '../../functions'; +import { formatGifUrlMessage, getGifRating, getGifUrl, getGiphyProxyUrl } from '../../functions.native'; import GifsMenuFooter from './GifsMenuFooter'; import styles from './styles'; @@ -18,7 +18,7 @@ const GifsMenu = () => { const [ searchQuery, setSearchQuery ] = useState(''); const dispatch = useDispatch(); const { t } = useTranslation(); - const rating = useSelector(getGifRating); + const rating = useSelector(getGifRating) as GiphyRating; const proxyUrl = useSelector(getGiphyProxyUrl); const options = { diff --git a/react/features/gifs/components/native/GifsMenuFooter.tsx b/react/features/gifs/components/native/GifsMenuFooter.tsx index 01c8df16d4..98220b3def 100644 --- a/react/features/gifs/components/native/GifsMenuFooter.tsx +++ b/react/features/gifs/components/native/GifsMenuFooter.tsx @@ -1,8 +1,7 @@ import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Image, Text, View } from 'react-native'; +import { Image, Text, TextStyle, View, ViewStyle } from 'react-native'; -// @ts-ignore import styles from './styles'; @@ -15,9 +14,10 @@ const GifsMenuFooter = (): JSX.Element => { const { t } = useTranslation(); return ( - - { t('poweredby') } + + + { t('poweredby') } + diff --git a/react/features/gifs/components/native/styles.js b/react/features/gifs/components/native/styles.ts similarity index 100% rename from react/features/gifs/components/native/styles.js rename to react/features/gifs/components/native/styles.ts diff --git a/react/features/google-api/components/AbstractGoogleSignInButton.ts b/react/features/google-api/components/AbstractGoogleSignInButton.ts deleted file mode 100644 index b866290824..0000000000 --- a/react/features/google-api/components/AbstractGoogleSignInButton.ts +++ /dev/null @@ -1,33 +0,0 @@ -import React, { Component } from 'react'; -import { WithTranslation } from 'react-i18next'; - -/** - * {@code AbstractGoogleSignInButton} Component's property types. - */ -interface IProps extends WithTranslation { - - /** - * The callback to invoke when the button is clicked. - */ - onClick: (e?: React.MouseEvent) => void; - - /** - * True if the user is signed in, so it needs to render a different label - * and maybe different style (for the future). - */ - signedIn?: boolean; - - /** - * The text to display within {@code GoogleSignInButton}. - */ - text?: string; -} - -/** - * Abstract class of the {@code GoogleSignInButton} to share platform - * independent code. - * - * @inheritdoc - */ -export default class AbstractGoogleSignInButton extends Component { -} diff --git a/react/features/google-api/components/GoogleSignInButton.native.js b/react/features/google-api/components/GoogleSignInButton.native.tsx similarity index 64% rename from react/features/google-api/components/GoogleSignInButton.native.js rename to react/features/google-api/components/GoogleSignInButton.native.tsx index 83d0ef8c32..8736302113 100644 --- a/react/features/google-api/components/GoogleSignInButton.native.js +++ b/react/features/google-api/components/GoogleSignInButton.native.tsx @@ -1,13 +1,11 @@ -// @flow - -import React from 'react'; -import { Image, TouchableOpacity } from 'react-native'; +import React, { Component } from 'react'; +import { WithTranslation } from 'react-i18next'; +import { GestureResponderEvent, Image, ImageStyle, TouchableOpacity, ViewStyle } from 'react-native'; import { translate } from '../../base/i18n/functions'; import Button from '../../base/ui/components/native/Button'; import { BUTTON_TYPES } from '../../base/ui/constants.native'; -import AbstractGoogleSignInButton from './AbstractGoogleSignInButton'; import styles from './styles'; // eslint-disable-next-line @@ -21,12 +19,31 @@ const GOOGLE_BRAND_IMAGE = require('../../../../images/btn_google_signin_dark_no * this way), hence the custom button implementation. */ +interface IProps extends WithTranslation { + + /** + * The callback to invoke when the button is clicked. + */ + onClick: (e?: React.MouseEvent | GestureResponderEvent) => void; + + /** + * True if the user is signed in, so it needs to render a different label + * and maybe different style (for the future). + */ + signedIn?: boolean; + + /** + * The text to display within {@code GoogleSignInButton}. + */ + text?: string; +} + /** * A React Component showing a button to sign in with Google. * * @augments Component */ -class GoogleSignInButton extends AbstractGoogleSignInButton { +class GoogleSignInButton extends Component { /** * Implements React's {@link Component#render()}. @@ -51,11 +68,11 @@ class GoogleSignInButton extends AbstractGoogleSignInButton { return ( + style = { styles.signInButton as ViewStyle } > + style = { styles.signInImage as ImageStyle } /> ); } diff --git a/react/features/google-api/components/GoogleSignInButton.web.tsx b/react/features/google-api/components/GoogleSignInButton.web.tsx index d3326da810..8f4bd5dc20 100644 --- a/react/features/google-api/components/GoogleSignInButton.web.tsx +++ b/react/features/google-api/components/GoogleSignInButton.web.tsx @@ -1,15 +1,33 @@ -import React from 'react'; +import React, { Component } from 'react'; +import { WithTranslation } from 'react-i18next'; import { translate } from '../../base/i18n/functions'; -import AbstractGoogleSignInButton from './AbstractGoogleSignInButton'; +interface IProps extends WithTranslation { + + /** + * The callback to invoke when the button is clicked. + */ + onClick: (e?: React.MouseEvent) => void; + + /** + * True if the user is signed in, so it needs to render a different label + * and maybe different style (for the future). + */ + signedIn?: boolean; + + /** + * The text to display within {@code GoogleSignInButton}. + */ + text?: string; +} /** * A React Component showing a button to sign in with Google. * * @augments Component */ -class GoogleSignInButton extends AbstractGoogleSignInButton { +class GoogleSignInButton extends Component { /** * Implements React's {@link Component#render()}. diff --git a/react/features/google-api/components/styles.js b/react/features/google-api/components/styles.ts similarity index 98% rename from react/features/google-api/components/styles.js rename to react/features/google-api/components/styles.ts index 94d699012c..6265727797 100644 --- a/react/features/google-api/components/styles.js +++ b/react/features/google-api/components/styles.ts @@ -1,5 +1,3 @@ -// @flow - import { createStyleSheet } from '../../base/styles/functions.any'; /**