ref(TS) Convert some native components to TS (#13259)

This commit is contained in:
Robert Pintilii
2023-04-24 20:14:02 +03:00
committed by GitHub
parent b9e30f3c1b
commit 8b8565bf60
22 changed files with 189 additions and 220 deletions

View File

@@ -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;

View File

@@ -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 ?? {};

View File

@@ -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 = {};

View File

@@ -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<IProps, IState> {
_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<IProps, IState> {
indicatorStyles.indicatorContainer as StyleProp<ViewStyle>,
{ backgroundColor: indicatorColor }
] }>
{/* @ts-ignore */}
<BaseIndicator
icon = { IconConnection }
// @ts-ignore
iconStyle = { this.props.iconStyle || iconStyle } />
</View>
);
@@ -185,7 +177,7 @@ class ConnectionIndicator extends AbstractConnectionIndicator<IProps, IState> {
* @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);

View File

@@ -20,7 +20,7 @@ export interface IProps {
/**
* Implements an abstract class for the RaisedHandIndicator component.
*/
export default class AbstractRaisedHandIndicator<P extends IProps>
export default abstract class AbstractRaisedHandIndicator<P extends IProps>
extends Component<P> {
/**
@@ -41,7 +41,7 @@ export default class AbstractRaisedHandIndicator<P extends IProps>
*
* @returns {React$Element<*>}
*/
_renderIndicator: () => React.ReactElement;
abstract _renderIndicator(): React.ReactElement;
}

View File

@@ -1,5 +1,3 @@
// @flow
import React, { Component } from 'react';
import { IconMicSlash } from '../../../base/icons/svg';

View File

@@ -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<any>,
_participants: Array<any>;
/**
* 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<Props> {
class Filmstrip extends PureComponent<IProps> {
/**
* 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<Props> {
*
* @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<Props> {
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<Props> {
});
}
_getItemLayout: (?Array<string>, number) => {length: number, offset: number, index: number};
/**
* Optimization for FlatList. Returns the length, offset and index for an item.
*
* @param {Array<string>} data - The data array with user IDs.
* @param {Array<string>} _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<Props> {
};
}
_onViewableItemsChanged: Object => void;
/**
* A handler for visible items changes.
*
@@ -196,7 +189,7 @@ class Filmstrip extends PureComponent<Props> {
* @param {Array<Object>} 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<Props> {
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<Props> {
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 (
<Thumbnail
key = { item }
@@ -277,9 +268,9 @@ class Filmstrip extends PureComponent<Props> {
}
return (
<SafeAreaView
<SafeAreaView // @ts-ignore
edges = { [ bottomEdge && 'bottom', 'left', 'right' ].filter(Boolean) }
style = { filmstripStyle }>
style = { filmstripStyle as ViewStyle }>
{
this._separateLocalThumbnail
&& !isNarrowAspectRatio
@@ -317,9 +308,9 @@ class Filmstrip extends PureComponent<Props> {
*
* @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)

View File

@@ -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 (
<View style = { styles.localThumbnail }>
<View style = { styles.localThumbnail as ViewStyle }>
<Thumbnail />
</View>
);

View File

@@ -1,5 +1,3 @@
// @flow
import React from 'react';
import { IconPin } from '../../../base/icons/svg';

View File

@@ -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<Props> {
class RaisedHandIndicator extends AbstractRaisedHandIndicator<IProps> {
/**
* Renders the platform specific indicator element.
*
@@ -26,7 +25,7 @@ class RaisedHandIndicator extends AbstractRaisedHandIndicator<Props> {
*/
_renderIndicator() {
return (
<View style = { styles.raisedHandIndicator }>
<View style = { styles.raisedHandIndicator as ViewStyle }>
<BaseIndicator
icon = { IconRaiseHand }
iconStyle = { styles.raisedHandIcon } />

View File

@@ -1,5 +1,3 @@
// @flow
import React from 'react';
import { IconScreenshare } from '../../../base/icons/svg';

View File

@@ -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<any>,
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<Props> {
class Thumbnail extends PureComponent<IProps> {
/**
* 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<Props> {
this.handleTrackStreamingStatusChanged = this.handleTrackStreamingStatusChanged.bind(this);
}
_onClick: () => void;
/**
* Thumbnail click handler.
*
@@ -176,8 +176,6 @@ class Thumbnail extends PureComponent<Props> {
}
}
_onThumbnailLongPress: () => void;
/**
* Thumbnail long press handler.
*
@@ -219,11 +217,11 @@ class Thumbnail extends PureComponent<Props> {
if (!_fakeParticipant || _isVirtualScreenshare) {
indicators.push(<View
key = 'top-left-indicators'
style = { styles.thumbnailTopLeftIndicatorContainer }>
style = { styles.thumbnailTopLeftIndicatorContainer as ViewStyle }>
{ !_isVirtualScreenshare && <ConnectionIndicator participantId = { participantId } /> }
{ !_isVirtualScreenshare && <RaisedHandIndicator participantId = { participantId } /> }
{ tileView && (isScreenShare || _isVirtualScreenshare) && (
<View style = { styles.screenShareIndicatorContainer }>
<View style = { styles.screenShareIndicatorContainer as ViewStyle }>
<ScreenShareIndicator />
</View>
) }
@@ -231,7 +229,9 @@ class Thumbnail extends PureComponent<Props> {
indicators.push(<Container
key = 'bottom-indicators'
style = { styles.thumbnailIndicatorContainer }>
<Container style = { (audioMuted || renderModeratorIndicator) && styles.bottomIndicatorsContainer }>
<Container
style = { ((audioMuted || renderModeratorIndicator) && styles.bottomIndicatorsContainer
) as StyleType }>
{ audioMuted && !_isVirtualScreenshare && <AudioMutedIndicator /> }
{ !tileView && _pinned && <PinnedIndicator />}
{ renderModeratorIndicator && !_isVirtualScreenshare && <ModeratorIndicator />}
@@ -275,7 +275,7 @@ class Thumbnail extends PureComponent<Props> {
* @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<Props> {
* @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<Props> {
styleOverrides,
_raisedHand && !_isVirtualScreenshare ? styles.thumbnailRaisedHand : null,
_renderDominantSpeakerIndicator && !_isVirtualScreenshare ? styles.thumbnailDominantSpeaker : null
] }
] as StyleType[] }
touchFeedback = { false }>
{ _gifSrc ? <Image
source = {{ uri: _gifSrc }}
style = { styles.thumbnailGif } />
style = { styles.thumbnailGif as ImageStyle } />
: <>
<ParticipantView
avatarSize = { tileView ? AVATAR_SIZE * 1.5 : AVATAR_SIZE }
@@ -388,36 +388,36 @@ class Thumbnail extends PureComponent<Props> {
* 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,

View File

@@ -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<string>,
_remoteParticipants: Array<string>;
/**
* The thumbnail height.
*/
_thumbnailHeight: number,
_thumbnailHeight?: number;
/**
* Application's viewport height.
*/
_width: number,
_width: number;
/**
* Invoked to update the receiver video quality.
*/
dispatch: Dispatch<any>,
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<Props> {
class TileView extends PureComponent<IProps> {
/**
* 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<Props> {
/**
* 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<Props> {
};
}
_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<Props> {
* @param {Array<Object>} data.viewableItems - The visible items array.
* @returns {void}
*/
_onViewableItemsChanged({ viewableItems = [] }: { viewableItems: Array<Object> }) {
_onViewableItemsChanged({ viewableItems = [] }: { viewableItems: ViewToken[]; }) {
const { _disableSelfView } = this.props;
if (viewableItems[0]?.index === 0 && !_disableSelfView) {
@@ -172,8 +169,8 @@ class TileView extends PureComponent<Props> {
}
// 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<Props> {
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<Props> {
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<Props> {
* @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,

View File

@@ -184,6 +184,7 @@ interface IDimensions {
}
interface IFilmstripDimensions {
columns?: number;
filmstripHeight?: number;
filmstripWidth?: number;
gridDimensions?: {

View File

@@ -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 = {

View File

@@ -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 (
<View style = { styles.credit }>
<Text
style = { styles.creditText }>{ t('poweredby') }</Text>
<View style = { styles.credit as ViewStyle }>
<Text style = { styles.creditText as TextStyle }>
{ t('poweredby') }
</Text>
<Image
source = { require('../../../../../images/GIPHY_logo.png') } />
</View>

View File

@@ -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<IProps> {
}

View File

@@ -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<HTMLButtonElement> | 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<IProps> {
/**
* Implements React's {@link Component#render()}.
@@ -51,11 +68,11 @@ class GoogleSignInButton extends AbstractGoogleSignInButton {
return (
<TouchableOpacity
onPress = { onClick }
style = { styles.signInButton } >
style = { styles.signInButton as ViewStyle } >
<Image
resizeMode = { 'contain' }
source = { GOOGLE_BRAND_IMAGE }
style = { styles.signInImage } />
style = { styles.signInImage as ImageStyle } />
</TouchableOpacity>
);
}

View File

@@ -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<IProps> {
/**
* Implements React's {@link Component#render()}.

View File

@@ -1,5 +1,3 @@
// @flow
import { createStyleSheet } from '../../base/styles/functions.any';
/**