From 84ad0200a8bd216249fabf704553eaad41e419cb Mon Sep 17 00:00:00 2001 From: Robert Pintilii Date: Wed, 12 Apr 2023 16:58:42 +0300 Subject: [PATCH] ref(TS) Convert some native components to TS (#13200) --- react/features/app/components/AbstractApp.ts | 2 +- .../{App.native.js => App.native.tsx} | 69 ++++++++++--------- react/features/app/getRouteToRender.native.ts | 2 +- .../{reducer.native.js => reducer.native.ts} | 2 +- react/features/authentication/actions.any.ts | 2 - .../authentication/components/index.native.ts | 1 - .../{LoginDialog.js => LoginDialog.tsx} | 54 ++++++++------- ...rOwnerDialog.js => WaitForOwnerDialog.tsx} | 14 ++-- .../base/avatar/components/Avatar.tsx | 1 + .../components/native/StatelessAvatar.tsx | 22 +++--- .../native/{styles.js => styles.ts} | 2 - .../avatar/components/web/StatelessAvatar.tsx | 5 ++ react/features/base/avatar/types.ts | 5 -- .../base/color-scheme/ColorSchemeRegistry.ts | 3 +- react/features/base/conference/actions.ts | 2 - react/features/base/connection/functions.ts | 9 ++- .../components/AbstractDialogContainer.ts | 4 +- ...nctions.native.js => functions.native.tsx} | 6 +- .../components/native/AbstractDialog.ts | 2 +- .../{AlertDialog.js => AlertDialog.tsx} | 19 ++--- .../{BottomSheet.js => BottomSheet.tsx} | 34 ++++----- .../{ConfirmDialog.js => ConfirmDialog.tsx} | 32 ++++----- ...DialogContainer.js => DialogContainer.tsx} | 3 +- .../{InputDialog.js => InputDialog.tsx} | 49 +++++-------- .../native/{styles.js => styles.ts} | 2 +- .../{ExpandedLabel.js => ExpandedLabel.tsx} | 22 +++--- .../components/native/{Label.js => Label.tsx} | 41 ++++++----- .../native/{styles.js => styles.ts} | 4 +- .../base/media/components/AbstractAudio.ts | 2 +- .../media/components/AbstractVideoTrack.tsx | 2 + .../components/native/{Audio.js => Audio.ts} | 10 +-- .../components/native/{Video.js => Video.tsx} | 27 ++++---- .../native/{VideoTrack.js => VideoTrack.tsx} | 7 +- .../native/{styles.js => styles.ts} | 0 .../native/{Pressable.js => Pressable.tsx} | 14 ++-- .../{SlidingView.js => SlidingView.tsx} | 63 ++++++++--------- ...dingviewstyles.js => slidingviewstyles.ts} | 2 - ...ative.js => DimensionsDetector.native.tsx} | 26 ++++--- .../{actionTypes.js => actionTypes.ts} | 0 .../native/MeetingParticipantList.tsx | 2 - .../{ReactionEmoji.js => ReactionEmoji.tsx} | 28 +++----- 41 files changed, 273 insertions(+), 323 deletions(-) rename react/features/app/components/{App.native.js => App.native.tsx} (83%) rename react/features/app/{reducer.native.js => reducer.native.ts} (88%) rename react/features/authentication/components/native/{LoginDialog.js => LoginDialog.tsx} (90%) rename react/features/authentication/components/native/{WaitForOwnerDialog.js => WaitForOwnerDialog.tsx} (90%) rename react/features/base/avatar/components/native/{styles.js => styles.ts} (99%) rename react/features/base/dialog/components/{functions.native.js => functions.native.tsx} (91%) rename react/features/base/dialog/components/native/{AlertDialog.js => AlertDialog.tsx} (82%) rename react/features/base/dialog/components/native/{BottomSheet.js => BottomSheet.tsx} (85%) rename react/features/base/dialog/components/native/{ConfirmDialog.js => ConfirmDialog.tsx} (84%) rename react/features/base/dialog/components/native/{DialogContainer.js => DialogContainer.tsx} (93%) rename react/features/base/dialog/components/native/{InputDialog.js => InputDialog.tsx} (81%) rename react/features/base/dialog/components/native/{styles.js => styles.ts} (98%) rename react/features/base/label/components/native/{ExpandedLabel.js => ExpandedLabel.tsx} (89%) rename react/features/base/label/components/native/{Label.js => Label.tsx} (83%) rename react/features/base/label/components/native/{styles.js => styles.ts} (95%) rename react/features/base/media/components/native/{Audio.js => Audio.ts} (94%) rename react/features/base/media/components/native/{Video.js => Video.tsx} (91%) rename react/features/base/media/components/native/{VideoTrack.js => VideoTrack.tsx} (76%) rename react/features/base/media/components/native/{styles.js => styles.ts} (100%) rename react/features/base/react/components/native/{Pressable.js => Pressable.tsx} (80%) rename react/features/base/react/components/native/{SlidingView.js => SlidingView.tsx} (87%) rename react/features/base/react/components/native/{slidingviewstyles.js => slidingviewstyles.ts} (98%) rename react/features/base/responsive-ui/components/{DimensionsDetector.native.js => DimensionsDetector.native.tsx} (78%) rename react/features/mobile/navigation/{actionTypes.js => actionTypes.ts} (100%) rename react/features/reactions/components/native/{ReactionEmoji.js => ReactionEmoji.tsx} (80%) diff --git a/react/features/app/components/AbstractApp.ts b/react/features/app/components/AbstractApp.ts index fc2bfea6a9..310e5d1430 100644 --- a/react/features/app/components/AbstractApp.ts +++ b/react/features/app/components/AbstractApp.ts @@ -25,7 +25,7 @@ export interface IProps { * * @abstract */ -export class AbstractApp extends BaseApp { +export class AbstractApp

extends BaseApp

{ /** * The deferred for the initialisation {{promise, resolve, reject}}. */ diff --git a/react/features/app/components/App.native.js b/react/features/app/components/App.native.tsx similarity index 83% rename from react/features/app/components/App.native.js rename to react/features/app/components/App.native.tsx index eaeb7a495b..aba7aa70da 100644 --- a/react/features/app/components/App.native.js +++ b/react/features/app/components/App.native.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { ComponentType } from 'react'; import { NativeModules, Platform, StyleSheet, View } from 'react-native'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import SplashScreen from 'react-native-splash-screen'; @@ -14,14 +14,13 @@ import { updateSettings } from '../../base/settings/actions'; import { _getRouteToRender } from '../getRouteToRender.native'; import logger from '../logger'; -import { AbstractApp } from './AbstractApp'; -import type { Props as AbstractAppProps } from './AbstractApp'; +import { AbstractApp, IProps as AbstractAppProps } from './AbstractApp'; // Register middlewares and reducers. -import '../middlewares'; -import '../reducers'; +import '../middlewares.native'; +import '../reducers.native'; -declare var __DEV__; +declare let __DEV__: any; const { AppInfo } = NativeModules; @@ -32,37 +31,33 @@ const DialogContainerWrapper = Platform.select({ /** * The type of React {@code Component} props of {@link App}. */ -type Props = AbstractAppProps & { +interface IProps extends AbstractAppProps { /** * An object with the feature flags. */ - flags: Object, + flags: Object; /** * An object with user information (display name, email, avatar URL). */ - userInfo: ?Object -}; + userInfo?: Object; +} /** * Root app {@code Component} on mobile/React Native. * * @augments AbstractApp */ -export class App extends AbstractApp { - /** - * The deferred for the initialisation {{promise, resolve, reject}}. - */ - _init: Object; +export class App extends AbstractApp { /** * Initializes a new {@code App} 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); // In the Release configuration, React Native will (intentionally) throw @@ -99,10 +94,11 @@ export class App extends AbstractApp { * @returns {void} */ async _extraInit() { - const { dispatch, getState } = this.state.store; + const { dispatch, getState } = this.state.store ?? {}; + const { flags } = this.props; // We set these early enough so then we avoid any unnecessary re-renders. - dispatch(updateFlags(this.props.flags)); + dispatch?.(updateFlags(flags)); const route = await _getRouteToRender(); @@ -113,8 +109,9 @@ export class App extends AbstractApp { // Wait until the root navigator is ready. // We really need to break the inheritance relationship between App, // AbstractApp and BaseApp, it's very inflexible and cumbersome right now. - const rootNavigationReady = new Promise(resolve => { + const rootNavigationReady = new Promise(resolve => { const i = setInterval(() => { + // @ts-ignore const { ready } = getState()['features/app'] || {}; if (ready) { @@ -127,26 +124,27 @@ export class App extends AbstractApp { await rootNavigationReady; // Check if serverURL is configured externally and not allowed to change. - const serverURLChangeEnabled = getFeatureFlag(getState(), SERVER_URL_CHANGE_ENABLED, true); + const serverURLChangeEnabled = getState && getFeatureFlag(getState(), SERVER_URL_CHANGE_ENABLED, true); if (!serverURLChangeEnabled) { // As serverURL is provided externally, so we push it to settings. if (typeof this.props.url !== 'undefined') { + // @ts-ignore const { serverURL } = this.props.url; if (typeof serverURL !== 'undefined') { - dispatch(updateSettings({ serverURL })); + dispatch?.(updateSettings({ serverURL })); } } } - dispatch(updateSettings(this.props.userInfo || {})); + dispatch?.(updateSettings(this.props.userInfo || {})); // Update settings with feature-flag. - const callIntegrationEnabled = this.props.flags[CALL_INTEGRATION_ENABLED]; + const callIntegrationEnabled = flags[CALL_INTEGRATION_ENABLED as keyof typeof flags]; if (typeof callIntegrationEnabled !== 'undefined') { - dispatch(updateSettings({ disableCallIntegration: !callIntegrationEnabled })); + dispatch?.(updateSettings({ disableCallIntegration: !callIntegrationEnabled })); } } @@ -156,7 +154,7 @@ export class App extends AbstractApp { * * @override */ - _createMainElement(component, props) { + _createMainElement(component: ComponentType, props: Object) { return ( void; - /** * Updates the known available size for the app to occupy. * @@ -216,9 +216,9 @@ export class App extends AbstractApp { * @returns {void} */ _onDimensionsChanged(width: number, height: number) { - const { dispatch } = this.state.store; + const { dispatch } = this.state.store ?? {}; - dispatch(clientResized(width, height)); + dispatch?.(clientResized(width, height)); } /** @@ -232,10 +232,10 @@ export class App extends AbstractApp { * @private * @returns {void} */ - _onSafeAreaInsetsChanged(insets) { - const { dispatch } = this.state.store; + _onSafeAreaInsetsChanged(insets: Object) { + const { dispatch } = this.state.store ?? {}; - dispatch(setSafeAreaInsets(insets)); + dispatch?.(setSafeAreaInsets(insets)); } /** @@ -266,7 +266,7 @@ export class App extends AbstractApp { * @private * @returns {void} */ -function _handleException(error, fatal) { +function _handleException(error: Error, fatal: boolean) { if (fatal) { // In the Release configuration, React Native will (intentionally) throw // an unhandled JavascriptException for an unhandled JavaScript error. @@ -275,6 +275,7 @@ function _handleException(error, fatal) { logger.error(error); } else { // Forward to the next globalHandler of ErrorUtils. + // @ts-ignore const { next } = _handleException; typeof next === 'function' && next(error, fatal); diff --git a/react/features/app/getRouteToRender.native.ts b/react/features/app/getRouteToRender.native.ts index 3e42f41b4e..1285940bf1 100644 --- a/react/features/app/getRouteToRender.native.ts +++ b/react/features/app/getRouteToRender.native.ts @@ -13,6 +13,6 @@ const route = { * @param {any} _stateful - Used on web. * @returns {Promise} */ -export function _getRouteToRender(_stateful: any) { +export function _getRouteToRender(_stateful?: any) { return Promise.resolve(route); } diff --git a/react/features/app/reducer.native.js b/react/features/app/reducer.native.ts similarity index 88% rename from react/features/app/reducer.native.js rename to react/features/app/reducer.native.ts index 1401e1921d..6451dbb92d 100644 --- a/react/features/app/reducer.native.js +++ b/react/features/app/reducer.native.ts @@ -9,7 +9,7 @@ import { _ROOT_NAVIGATION_READY } from '../mobile/navigation/actionTypes'; * @param {string} action.type - Type of action. * @returns {Object} */ -ReducerRegistry.register('features/app', (state = {}, action) => { +ReducerRegistry.register('features/app', (state: Object = {}, action) => { switch (action.type) { case _ROOT_NAVIGATION_READY: return { diff --git a/react/features/authentication/actions.any.ts b/react/features/authentication/actions.any.ts index c0867b7f79..fbcfb4499f 100644 --- a/react/features/authentication/actions.any.ts +++ b/react/features/authentication/actions.any.ts @@ -8,8 +8,6 @@ import { UPGRADE_ROLE_FINISHED, UPGRADE_ROLE_STARTED, WAIT_FOR_OWNER } from './actionTypes'; -// eslint-disable-next-line lines-around-comment -// @ts-ignore import { LoginDialog, WaitForOwnerDialog } from './components'; import logger from './logger'; diff --git a/react/features/authentication/components/index.native.ts b/react/features/authentication/components/index.native.ts index b5a75f2da1..4457a24a5d 100644 --- a/react/features/authentication/components/index.native.ts +++ b/react/features/authentication/components/index.native.ts @@ -1,4 +1,3 @@ -// @ts-ignore export { default as LoginDialog } from './native/LoginDialog'; // eslint-disable-next-line lines-around-comment // @ts-ignore diff --git a/react/features/authentication/components/native/LoginDialog.js b/react/features/authentication/components/native/LoginDialog.tsx similarity index 90% rename from react/features/authentication/components/native/LoginDialog.js rename to react/features/authentication/components/native/LoginDialog.tsx index e98efda7e2..639616eb2b 100644 --- a/react/features/authentication/components/native/LoginDialog.js +++ b/react/features/authentication/components/native/LoginDialog.tsx @@ -1,8 +1,9 @@ import React, { Component } from 'react'; import Dialog from 'react-native-dialog'; import { connect as reduxConnect } from 'react-redux'; -import type { Dispatch } from 'redux'; +import { IReduxState, IStore } from '../../../app/types'; +import { IJitsiConference } from '../../../base/conference/reducer'; import { connect } from '../../../base/connection/actions.native'; import { toJid } from '../../../base/connection/functions'; import { _abstractMapStateToProps } from '../../../base/dialog/functions'; @@ -13,61 +14,68 @@ import { authenticateAndUpgradeRole, cancelLogin } from '../../actions.native'; /** * The type of the React {@link Component} props of {@link LoginDialog}. */ -type Props = { +interface IProps { /** * {@link JitsiConference} That needs authentication - will hold a valid * value in XMPP login + guest access mode. */ - _conference: Object, + _conference?: IJitsiConference; /** * The server hosts specified in the global config. */ - _configHosts: Object, + _configHosts?: { + anonymousdomain?: string; + authdomain?: string; + domain: string; + focus?: string; + muc: string; + visitorFocus: string; + }; /** * Indicates if the dialog should display "connecting" status message. */ - _connecting: boolean, + _connecting: boolean; /** * The error which occurred during login/authentication. */ - _error: Object, + _error: any; /** * The progress in the floating range between 0 and 1 of the authenticating * and upgrading the role of the local participant/user. */ - _progress: number, + _progress?: number; /** * Redux store dispatch method. */ - dispatch: Dispatch, + dispatch: IStore['dispatch']; /** * Invoked to obtain translated strings. */ - t: Function -}; + t: Function; +} /** * The type of the React {@link Component} state of {@link LoginDialog}. */ -type State = { +interface IState { /** * The user entered password for the conference. */ - password: string, + password: string; /** * The user entered local participant name. */ - username: string -}; + username: string; +} /** * Dialog asks user for username and password. @@ -96,14 +104,14 @@ type State = { * See {@link https://github.com/jitsi/jicofo#secure-domain} for a description * of the configuration parameters. */ -class LoginDialog extends Component { +class LoginDialog extends Component { /** * Initializes a new LoginDialog instance. * * @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.state = { @@ -179,7 +187,7 @@ class LoginDialog extends Component { } = this.props; let messageKey; - const messageOptions = {}; + const messageOptions = { msg: '' }; if (progress && progress < 1) { messageKey = 'connection.FETCH_SESSION_ID'; @@ -196,7 +204,7 @@ class LoginDialog extends Component { && credentials.jid === toJid( this.state.username, - this.props._configHosts) + this.props._configHosts ?? {}) && credentials.password === this.state.password) { messageKey = 'dialog.incorrectPassword'; } @@ -222,7 +230,7 @@ class LoginDialog extends Component { * @returns {void} * @private */ - _onUsernameChange(text) { + _onUsernameChange(text: string) { this.setState({ username: text.trim() }); @@ -235,7 +243,7 @@ class LoginDialog extends Component { * @returns {void} * @private */ - _onPasswordChange(text) { + _onPasswordChange(text: string) { this.setState({ password: text }); @@ -261,7 +269,7 @@ class LoginDialog extends Component { _onLogin() { const { _conference: conference, dispatch } = this.props; const { password, username } = this.state; - const jid = toJid(username, this.props._configHosts); + const jid = toJid(username, this.props._configHosts ?? {}); let r; // If there's a conference it means that the connection has succeeded, @@ -282,9 +290,9 @@ class LoginDialog extends Component { * * @param {Object} state - The Redux state. * @private - * @returns {Props} + * @returns {IProps} */ -function _mapStateToProps(state) { +function _mapStateToProps(state: IReduxState) { const { error: authenticateAndUpgradeRoleError, progress, diff --git a/react/features/authentication/components/native/WaitForOwnerDialog.js b/react/features/authentication/components/native/WaitForOwnerDialog.tsx similarity index 90% rename from react/features/authentication/components/native/WaitForOwnerDialog.js rename to react/features/authentication/components/native/WaitForOwnerDialog.tsx index 947e61d99b..8f232ccc8a 100644 --- a/react/features/authentication/components/native/WaitForOwnerDialog.js +++ b/react/features/authentication/components/native/WaitForOwnerDialog.tsx @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; -import type { Dispatch } from 'redux'; +import { IStore } from '../../../app/types'; import ConfirmDialog from '../../../base/dialog/components/native/ConfirmDialog'; import { translate } from '../../../base/i18n/functions'; import { cancelWaitForOwner, openLoginDialog } from '../../actions.native'; @@ -9,18 +9,18 @@ import { cancelWaitForOwner, openLoginDialog } from '../../actions.native'; /** * The type of the React {@code Component} props of {@link WaitForOwnerDialog}. */ -type Props = { +interface IProps { /** * Redux store dispatch function. */ - dispatch: Dispatch, + dispatch: IStore['dispatch']; /** * Invoked to obtain translated strings. */ - t: Function -}; + t: Function; +} /** * The dialog is display in XMPP password + guest access configuration, after @@ -28,14 +28,14 @@ type Props = { * * See {@link LoginDialog} description for more details. */ -class WaitForOwnerDialog extends Component { +class WaitForOwnerDialog extends Component { /** * Initializes a new WaitForWonderDialog instance. * * @param {Object} props - The read-only properties with which the new * instance is to be initialized. */ - constructor(props) { + constructor(props: IProps) { super(props); // Bind event handlers so they are only bound once per instance. diff --git a/react/features/base/avatar/components/Avatar.tsx b/react/features/base/avatar/components/Avatar.tsx index 2ed00b1ecd..3cff264a29 100644 --- a/react/features/base/avatar/components/Avatar.tsx +++ b/react/features/base/avatar/components/Avatar.tsx @@ -185,6 +185,7 @@ class Avatar

extends PureComponent { id?: string; status?: string; testId?: string; + url?: string; useCORS?: boolean; } = { className, diff --git a/react/features/base/avatar/components/native/StatelessAvatar.tsx b/react/features/base/avatar/components/native/StatelessAvatar.tsx index 8f03d2590a..8f965f10ba 100644 --- a/react/features/base/avatar/components/native/StatelessAvatar.tsx +++ b/react/features/base/avatar/components/native/StatelessAvatar.tsx @@ -1,12 +1,11 @@ import React, { Component } from 'react'; -import { Image, Text, View } from 'react-native'; +import { Image, Text, TextStyle, View, ViewStyle } from 'react-native'; import Icon from '../../../icons/components/Icon'; import { StyleType } from '../../../styles/functions.native'; import { isIcon } from '../../functions'; import { IAvatarProps } from '../../types'; -// @ts-ignore import styles from './styles'; // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -23,6 +22,11 @@ interface IProps extends IAvatarProps { * External style passed to the component. */ style?: StyleType; + + /** + * The URL of the avatar to render. + */ + url?: string; } /** @@ -66,7 +70,7 @@ export default class StatelessAvatar extends Component { { avatar } @@ -90,7 +94,7 @@ export default class StatelessAvatar extends Component { return ( - + ); } @@ -125,7 +129,7 @@ export default class StatelessAvatar extends Component { return ( { return ( - { initials } + { initials } ); } @@ -166,9 +170,11 @@ export default class StatelessAvatar extends Component { _renderURLAvatar() { const { onAvatarLoadError, size, url } = this.props; - return ( // @ts-ignore + return ( = 0 ? id : `${id}@${authdomain || domain}`; } diff --git a/react/features/base/dialog/components/AbstractDialogContainer.ts b/react/features/base/dialog/components/AbstractDialogContainer.ts index 5c4e6dc8bb..d6d6cbbced 100644 --- a/react/features/base/dialog/components/AbstractDialogContainer.ts +++ b/react/features/base/dialog/components/AbstractDialogContainer.ts @@ -11,12 +11,12 @@ interface IProps { /** * The component to render. */ - _component: ComponentType; + _component?: ComponentType; /** * The props to pass to the component that will be rendered. */ - _componentProps: Object; + _componentProps?: Object; /** * Array of reactions to be displayed. diff --git a/react/features/base/dialog/components/functions.native.js b/react/features/base/dialog/components/functions.native.tsx similarity index 91% rename from react/features/base/dialog/components/functions.native.js rename to react/features/base/dialog/components/functions.native.tsx index 7f68ebb904..ce39d0efb7 100644 --- a/react/features/base/dialog/components/functions.native.js +++ b/react/features/base/dialog/components/functions.native.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Text } from 'react-native'; +import { Text, TextStyle } from 'react-native'; import { brandedDialog as styles } from './native/styles'; @@ -10,7 +10,7 @@ import { brandedDialog as styles } from './native/styles'; * contain HTML to render. * @returns {ReactElement[]|string} */ -export function renderHTML(html) { +export function renderHTML(html?: string) { if (typeof html === 'string') { // At the time of this writing, the specified HTML contains a couple // of spaces one after the other. They do not cause a visible @@ -36,7 +36,7 @@ export function renderHTML(html) { if (c = closing.exec(html)) { r.push(html.substring(prevClosingLastIndex, o.index)); r.push( - + { html.substring(opening.lastIndex, c.index) } ); opening.lastIndex diff --git a/react/features/base/dialog/components/native/AbstractDialog.ts b/react/features/base/dialog/components/native/AbstractDialog.ts index e602ac66fb..8db00ea4b9 100644 --- a/react/features/base/dialog/components/native/AbstractDialog.ts +++ b/react/features/base/dialog/components/native/AbstractDialog.ts @@ -25,7 +25,7 @@ export interface IState { /** * An abstract implementation of a dialog on Web/React and mobile/react-native. */ -export default class AbstractDialog

+export default class AbstractDialog

extends Component { _mounted: boolean; diff --git a/react/features/base/dialog/components/native/AlertDialog.js b/react/features/base/dialog/components/native/AlertDialog.tsx similarity index 82% rename from react/features/base/dialog/components/native/AlertDialog.js rename to react/features/base/dialog/components/native/AlertDialog.tsx index 16d4f471b2..6b68cf525b 100644 --- a/react/features/base/dialog/components/native/AlertDialog.js +++ b/react/features/base/dialog/components/native/AlertDialog.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { WithTranslation } from 'react-i18next'; import Dialog from 'react-native-dialog'; import { connect } from 'react-redux'; @@ -6,10 +7,9 @@ import { translate } from '../../../i18n/functions'; import { _abstractMapStateToProps } from '../../functions'; import { renderHTML } from '../functions.native'; -import AbstractDialog, { type Props as AbstractProps } from './AbstractDialog'; +import AbstractDialog, { IProps as AbstractProps } from './AbstractDialog'; - -type Props = AbstractProps & { +interface IProps extends AbstractProps, WithTranslation { /** * Untranslated i18n key of the content to be displayed. @@ -18,19 +18,14 @@ type Props = AbstractProps & { * translated using the provided params. See i18n function * {@code translate(string, Object)} for more details. */ - contentKey: string | { key: string, params: Object}, - - /** - * Translation function. - */ - t: Function -}; + contentKey: string | { key: string; params: Object; }; +} /** * Implements an alert dialog, to simply show an error or a message, * then disappear on dismiss. */ -class AlertDialog extends AbstractDialog { +class AlertDialog extends AbstractDialog { /** * Implements React's {@link Component#render}. * @@ -56,8 +51,6 @@ class AlertDialog extends AbstractDialog { ); } - - _onSubmit: () => boolean; } export default translate(connect(_abstractMapStateToProps)(AlertDialog)); diff --git a/react/features/base/dialog/components/native/BottomSheet.js b/react/features/base/dialog/components/native/BottomSheet.tsx similarity index 85% rename from react/features/base/dialog/components/native/BottomSheet.js rename to react/features/base/dialog/components/native/BottomSheet.tsx index c4af2adb5a..e813d54e06 100644 --- a/react/features/base/dialog/components/native/BottomSheet.js +++ b/react/features/base/dialog/components/native/BottomSheet.tsx @@ -1,5 +1,5 @@ -import React, { type Node, PureComponent } from 'react'; -import { SafeAreaView, ScrollView, View } from 'react-native'; +import React, { PureComponent, ReactNode } from 'react'; +import { SafeAreaView, ScrollView, View, ViewStyle } from 'react-native'; import { connect } from 'react-redux'; import SlidingView from '../../../react/components/native/SlidingView'; @@ -15,43 +15,43 @@ type Props = { /** * Whether to add padding to scroll view. */ - addScrollViewPadding?: boolean, + addScrollViewPadding?: boolean; /** * The children to be displayed within this component. */ - children: Node, + children: ReactNode; /** * Redux Dispatch function. */ - dispatch: Function, + dispatch: Function; /** * Handler for the cancel event, which happens when the user dismisses * the sheet. */ - onCancel: ?Function, + onCancel?: Function; /** - * Function to render a bottom sheet header element, if necessary. + * Function to render a bottom sheet footer element, if necessary. */ - renderHeader: ?Function, + renderFooter?: Function; /** - * Function to render a bottom sheet footer element, if necessary. + * Function to render a bottom sheet header element, if necessary. */ - renderFooter: ?Function, + renderHeader?: Function; /** * Whether to show sliding view or not. */ - showSlidingView?: boolean, + showSlidingView?: boolean; /** * The component's external style. */ - style: Object + style?: Object; }; /** @@ -109,19 +109,19 @@ class BottomSheet extends PureComponent { } = this.props; return ( - + show = { Boolean(showSlidingView) }> + style = { styles.sheetContainer as ViewStyle }> - { renderHeader && renderHeader() } + { renderHeader?.() } { ] } > { this.props.children } - { renderFooter && renderFooter() } + { renderFooter?.() } diff --git a/react/features/base/dialog/components/native/ConfirmDialog.js b/react/features/base/dialog/components/native/ConfirmDialog.tsx similarity index 84% rename from react/features/base/dialog/components/native/ConfirmDialog.js rename to react/features/base/dialog/components/native/ConfirmDialog.tsx index d310407868..f77791a110 100644 --- a/react/features/base/dialog/components/native/ConfirmDialog.js +++ b/react/features/base/dialog/components/native/ConfirmDialog.tsx @@ -1,11 +1,12 @@ import React from 'react'; +import { WithTranslation } from 'react-i18next'; import Dialog from 'react-native-dialog'; import { connect } from 'react-redux'; import { translate } from '../../../i18n/functions'; import { renderHTML } from '../functions.native'; -import AbstractDialog from './AbstractDialog'; +import AbstractDialog, { IProps as AbstractProps } from './AbstractDialog'; import styles from './styles'; @@ -13,43 +14,38 @@ import styles from './styles'; * The type of the React {@code Component} props of * {@link ConfirmDialog}. */ -type Props = { +interface IProps extends AbstractProps, WithTranslation { /** * The i18n key of the text label for the cancel button. */ - cancelLabel: string, + cancelLabel: string; /** * The React {@code Component} children. */ - children?: Node, + children?: React.ReactNode; /** * The i18n key of the text label for the confirm button. */ - confirmLabel: string, + confirmLabel: string; /** * Dialog description key for translations. */ - descriptionKey?: string | Object, + descriptionKey?: string | { key: string; params: string; }; /** * Whether or not the nature of the confirm button is destructive. */ - isConfirmDestructive?: Boolean, - - /** - * Invoked to obtain translated strings. - */ - t: Function, + isConfirmDestructive?: Boolean; /** * Dialog title. */ - title?: string -}; + title?: string; +} /** * React Component for getting confirmation to stop a file recording session in @@ -57,7 +53,7 @@ type Props = { * * @augments Component */ -class ConfirmDialog extends AbstractDialog { +class ConfirmDialog extends AbstractDialog { /** * Default values for {@code ConfirmDialog} component's properties. * @@ -78,7 +74,7 @@ class ConfirmDialog extends AbstractDialog { = typeof descriptionKey === 'string' ? t(descriptionKey) : renderHTML( - t(descriptionKey?.key, descriptionKey?.params) + t(descriptionKey?.key ?? '', descriptionKey?.params) ); return ( @@ -129,10 +125,6 @@ class ConfirmDialog extends AbstractDialog { ); } - - _onCancel: () => void; - - _onSubmit: (?string) => void; } export default translate(connect()(ConfirmDialog)); diff --git a/react/features/base/dialog/components/native/DialogContainer.js b/react/features/base/dialog/components/native/DialogContainer.tsx similarity index 93% rename from react/features/base/dialog/components/native/DialogContainer.js rename to react/features/base/dialog/components/native/DialogContainer.tsx index a037284fa4..6329f6e1ab 100644 --- a/react/features/base/dialog/components/native/DialogContainer.js +++ b/react/features/base/dialog/components/native/DialogContainer.tsx @@ -1,6 +1,7 @@ import React, { Fragment } from 'react'; import { connect } from 'react-redux'; +import { IReduxState } from '../../../../app/types'; import ReactionEmoji from '../../../../reactions/components/native/ReactionEmoji'; import { getReactionsQueue } from '../../../../reactions/functions.native'; import AbstractDialogContainer, { @@ -47,7 +48,7 @@ class DialogContainer extends AbstractDialogContainer { } } -const mapStateToProps = state => { +const mapStateToProps = (state: IReduxState) => { return { ...abstractMapStateToProps(state), _reactionsQueue: getReactionsQueue(state) diff --git a/react/features/base/dialog/components/native/InputDialog.js b/react/features/base/dialog/components/native/InputDialog.tsx similarity index 81% rename from react/features/base/dialog/components/native/InputDialog.js rename to react/features/base/dialog/components/native/InputDialog.tsx index fa1eb4bacd..71f0de1af4 100644 --- a/react/features/base/dialog/components/native/InputDialog.js +++ b/react/features/base/dialog/components/native/InputDialog.tsx @@ -1,4 +1,6 @@ import React from 'react'; +import { WithTranslation } from 'react-i18next'; +import { TextStyle } from 'react-native'; import Dialog from 'react-native-dialog'; import { connect } from 'react-redux'; @@ -6,67 +8,62 @@ import { translate } from '../../../i18n/functions'; import { _abstractMapStateToProps } from '../../functions'; import AbstractDialog, { - type Props as AbstractProps, - type State as AbstractState + IProps as AbstractProps, + IState as AbstractState } from './AbstractDialog'; import { inputDialog as styles } from './styles'; -type Props = AbstractProps & { +interface IProps extends AbstractProps, WithTranslation { /** * The dialog descriptionKey. */ - descriptionKey: string, + descriptionKey: string; /** * An optional initial value to initiate the field with. */ - initialValue?: ?string, + initialValue?: string; /** * A message key to be shown for the user (e.g. An error that is defined after submitting the form). */ - messageKey?: string, - - /** - * The translate function. - */ - t: Function, + messageKey?: string; /** * Props for the text input. */ - textInputProps: ?Object, + textInputProps?: Object; /** * The untranslated i18n key for the dialog title. */ - titleKey?: string, + titleKey?: string; /** * Validating of the input. */ - validateInput: ?Function + validateInput?: Function; } -type State = AbstractState & { +interface IState extends AbstractState { /** * The current value of the field. */ - fieldValue: ?string -}; + fieldValue?: string; +} /** * Implements a single field input dialog component. */ -class InputDialog extends AbstractDialog { +class InputDialog extends AbstractDialog { /** * Instantiates a new {@code InputDialog}. * * @inheritdoc */ - constructor(props: Props) { + constructor(props: IProps) { super(props); this.state = { @@ -96,7 +93,7 @@ class InputDialog extends AbstractDialog { coverScreen = { false } visible = { true }> - { t(titleKey) } + { t(titleKey ?? '') } { descriptionKey && ( @@ -113,7 +110,7 @@ class InputDialog extends AbstractDialog { { messageKey && ( + style = { styles.formMessage as TextStyle }> { t(messageKey) } ) @@ -128,17 +125,13 @@ class InputDialog extends AbstractDialog { ); } - _onCancel: () => void; - - _onChangeText: string => void; - /** * Callback to be invoked when the text in the field changes. * * @param {string} fieldValue - The updated field value. * @returns {void} */ - _onChangeText(fieldValue) { + _onChangeText(fieldValue: string) { if (this.props.validateInput && !this.props.validateInput(fieldValue)) { return; } @@ -148,10 +141,6 @@ class InputDialog extends AbstractDialog { }); } - _onSubmit: (?string) => boolean; - - _onSubmitValue: () => boolean; - /** * Callback to be invoked when the value of this dialog is submitted. * diff --git a/react/features/base/dialog/components/native/styles.js b/react/features/base/dialog/components/native/styles.ts similarity index 98% rename from react/features/base/dialog/components/native/styles.js rename to react/features/base/dialog/components/native/styles.ts index d2fe47b499..dad13928e3 100644 --- a/react/features/base/dialog/components/native/styles.js +++ b/react/features/base/dialog/components/native/styles.ts @@ -1,9 +1,9 @@ import { StyleSheet } from 'react-native'; -import BaseTheme from '../../../../base/ui/components/BaseTheme.native'; import ColorSchemeRegistry from '../../../color-scheme/ColorSchemeRegistry'; import { schemeColor } from '../../../color-scheme/functions'; import { BoxModel } from '../../../styles/components/styles/BoxModel'; +import BaseTheme from '../../../ui/components/BaseTheme.native'; import { PREFERRED_DIALOG_SIZE } from '../../constants'; const BORDER_RADIUS = 5; diff --git a/react/features/base/label/components/native/ExpandedLabel.js b/react/features/base/label/components/native/ExpandedLabel.tsx similarity index 89% rename from react/features/base/label/components/native/ExpandedLabel.js rename to react/features/base/label/components/native/ExpandedLabel.tsx index afaeb75e1f..57b6d6d0b3 100644 --- a/react/features/base/label/components/native/ExpandedLabel.js +++ b/react/features/base/label/components/native/ExpandedLabel.tsx @@ -1,37 +1,35 @@ -// @flow - import React, { Component } from 'react'; import { Animated, Text, View } from 'react-native'; import styles, { DEFAULT_COLOR } from './styles'; -export type Props = { +export interface IProps { /** * The position of the parent element (from right to left) to display the * arrow. */ - parentPosition: number, + parentPosition: number; /** * Custom styles. */ - style: ?Object -}; + style?: Object; +} -type State = { +interface IState { /** * The opacity animation Object. */ - opacityAnimation: Object -}; + opacityAnimation: Animated.Value; +} /** * A react {@code Component} that implements an expanded label as tooltip-like * component to explain the meaning of the {@code Label}. */ -export default class ExpandedLabel extends Component { +export default class ExpandedLabel

extends Component { /** * Instantiates a new {@code ExpandedLabel} instance. * @@ -55,7 +53,7 @@ export default class ExpandedLabel extends Component { toValue: 1, velocity: 1, useNativeDriver: true - }).start(); + } as Animated.DecayAnimationConfig).start(); } /** @@ -89,8 +87,6 @@ export default class ExpandedLabel extends Component { */ _getLabel: () => string; - _getColor: () => string; - /** * Defines the color of the expanded label. This function returns a default * value if implementing classes don't override it, but the goal is to have diff --git a/react/features/base/label/components/native/Label.js b/react/features/base/label/components/native/Label.tsx similarity index 83% rename from react/features/base/label/components/native/Label.js rename to react/features/base/label/components/native/Label.tsx index 81617c16be..de143791c1 100644 --- a/react/features/base/label/components/native/Label.js +++ b/react/features/base/label/components/native/Label.tsx @@ -1,6 +1,5 @@ -// @flow import React, { Component } from 'react'; -import { Animated, Text } from 'react-native'; +import { Animated, Text, ViewStyle } from 'react-native'; import Icon from '../../../icons/components/Icon'; import { StyleType, combineStyles } from '../../../styles/functions.native'; @@ -17,41 +16,41 @@ const STATUS_IN_PROGRESS = 'in_progress'; */ const STATUS_OFF = 'off'; -type Props = { +interface IProps { /** * An SVG icon to be rendered as the content of the label. */ - icon?: Function, + icon?: Function; /** * Color for the icon. */ - iconColor?: ?string, + iconColor?: string; /** * Status of the label. This prop adds some additional styles based on its * value. E.g. If status = off, it will render the label symbolising that * the thing it displays (e.g. Recording) is off. */ - status: ('in_progress' | 'off' | 'on'), + status?: 'in_progress' | 'off' | 'on'; /** * Style of the label. */ - style?: ?StyleType, + style?: StyleType; /** * String or component that will be rendered as the label itself. */ - text?: string, + text?: string; /** * Custom styles for the text. */ - textStyle?: ?StyleType + textStyle?: StyleType; -}; +} type State = { @@ -59,25 +58,25 @@ type State = { * An animation object handling the opacity changes of the in progress * label. */ - pulseAnimation: Object -} + pulseAnimation: Animated.Value; +}; /** * Renders a circular indicator to be used for status icons, such as recording * on, audio-only conference, video quality and similar. */ -export default class Label extends Component { +export default class Label extends Component { /** * A reference to the started animation of this label. */ - animationReference: Object; + animationReference: Animated.CompositeAnimation; /** * Instantiates a new instance of {@code Label}. * * @inheritdoc */ - constructor(props: Props) { + constructor(props: IProps) { super(props); this.state = { @@ -99,7 +98,7 @@ export default class Label extends Component { * * @inheritdoc */ - componentDidUpdate(prevProps: Props) { + componentDidUpdate(prevProps: IProps) { this._maybeToggleAnimation(prevProps, this.props); } @@ -127,8 +126,8 @@ export default class Label extends Component { return ( { icon && { * Checks if the animation has to be started or stopped and acts * accordingly. * - * @param {Props} oldProps - The previous values of the Props. - * @param {Props} newProps - The new values of the Props. + * @param {IProps} oldProps - The previous values of the Props. + * @param {IProps} newProps - The new values of the Props. * @returns {void} */ - _maybeToggleAnimation(oldProps, newProps) { + _maybeToggleAnimation(oldProps: Partial, newProps: IProps) { const { status: oldStatus } = oldProps; const { status: newStatus } = newProps; const { pulseAnimation } = this.state; diff --git a/react/features/base/label/components/native/styles.js b/react/features/base/label/components/native/styles.ts similarity index 95% rename from react/features/base/label/components/native/styles.js rename to react/features/base/label/components/native/styles.ts index d01d3d890b..0a6336c0af 100644 --- a/react/features/base/label/components/native/styles.js +++ b/react/features/base/label/components/native/styles.ts @@ -1,7 +1,5 @@ -// @flow - import { ColorPalette } from '../../../styles/components/styles/ColorPalette'; -import BaseTheme from '../../../ui/components/BaseTheme'; +import BaseTheme from '../../../ui/components/BaseTheme.native'; /** * The default color of the {@code Label} and {@code ExpandedLabel}. diff --git a/react/features/base/media/components/AbstractAudio.ts b/react/features/base/media/components/AbstractAudio.ts index 69783c23cf..ba849dbd40 100644 --- a/react/features/base/media/components/AbstractAudio.ts +++ b/react/features/base/media/components/AbstractAudio.ts @@ -92,7 +92,7 @@ export default class AbstractAudio extends Component { * @protected * @returns {void} */ - setAudioElementImpl(element?: AudioElement | null) { + setAudioElementImpl(element?: AudioElement | null | any) { this._audioElementImpl = element; const { setRef } = this.props; diff --git a/react/features/base/media/components/AbstractVideoTrack.tsx b/react/features/base/media/components/AbstractVideoTrack.tsx index cfd4261537..03c4051539 100644 --- a/react/features/base/media/components/AbstractVideoTrack.tsx +++ b/react/features/base/media/components/AbstractVideoTrack.tsx @@ -113,6 +113,8 @@ export default class AbstractVideoTrack

extends Component

{