From 576d3ed8a7132e0d7c7a75eed5640ff3003683b0 Mon Sep 17 00:00:00 2001 From: robertpin Date: Mon, 6 Feb 2023 11:01:55 +0200 Subject: [PATCH] ref(chat) Convert components to TS --- .../{AbstractButton.js => AbstractButton.tsx} | 57 +++++++++-------- ...ToolboxItem.js => AbstractToolboxItem.tsx} | 63 +++++++++---------- ...xItem.native.js => ToolboxItem.native.tsx} | 15 ++--- ...ToolboxItem.web.js => ToolboxItem.web.tsx} | 22 +++---- .../{AbstractChat.js => AbstractChat.ts} | 63 ++++++++----------- react/features/chat/components/native/Chat.js | 2 +- .../chat/components/web/{Chat.js => Chat.tsx} | 39 ++++-------- .../web/{ChatButton.js => ChatButton.tsx} | 26 ++++---- .../web/{ChatCounter.js => ChatCounter.tsx} | 19 +++--- .../web/{ChatHeader.js => ChatHeader.tsx} | 34 +++++----- .../chat/components/web/ChatInput.tsx | 2 +- .../chat/components/web/DisplayNameForm.tsx | 2 +- ...KeyboardAvoider.js => KeyboardAvoider.tsx} | 2 - .../chat/components/web/MessageRecipient.tsx | 2 +- .../web/{SmileysPanel.js => SmileysPanel.tsx} | 22 +++---- 15 files changed, 163 insertions(+), 207 deletions(-) rename react/features/base/toolbox/components/{AbstractButton.js => AbstractButton.tsx} (90%) rename react/features/base/toolbox/components/{AbstractToolboxItem.js => AbstractToolboxItem.tsx} (81%) rename react/features/base/toolbox/components/{ToolboxItem.native.js => ToolboxItem.native.tsx} (84%) rename react/features/base/toolbox/components/{ToolboxItem.web.js => ToolboxItem.web.tsx} (89%) rename react/features/chat/components/{AbstractChat.js => AbstractChat.ts} (77%) rename react/features/chat/components/web/{Chat.js => Chat.tsx} (88%) rename react/features/chat/components/web/{ChatButton.js => ChatButton.tsx} (73%) rename react/features/chat/components/web/{ChatCounter.js => ChatCounter.tsx} (84%) rename react/features/chat/components/web/{ChatHeader.js => ChatHeader.tsx} (72%) rename react/features/chat/components/web/{KeyboardAvoider.js => KeyboardAvoider.tsx} (99%) rename react/features/chat/components/web/{SmileysPanel.js => SmileysPanel.tsx} (90%) diff --git a/react/features/base/toolbox/components/AbstractButton.js b/react/features/base/toolbox/components/AbstractButton.tsx similarity index 90% rename from react/features/base/toolbox/components/AbstractButton.js rename to react/features/base/toolbox/components/AbstractButton.tsx index b82618490..8992f0663 100644 --- a/react/features/base/toolbox/components/AbstractButton.js +++ b/react/features/base/toolbox/components/AbstractButton.tsx @@ -1,80 +1,76 @@ -// @flow - -import React, { Component } from 'react'; +import React, { Component, ReactNode } from 'react'; import { NOTIFY_CLICK_MODE } from '../../../toolbox/constants'; -import { combineStyles } from '../../styles'; +import { combineStyles } from '../../styles/functions.any'; import type { Styles } from './AbstractToolboxItem'; import ToolboxItem from './ToolboxItem'; -export type Props = {| +export type Props = { /** * Function to be called after the click handler has been processed. */ - afterClick: ?Function, + afterClick?: Function; /** * The button's key. */ - buttonKey?: string, + buttonKey?: string; /** * Whether or not the button is displayed in a context menu. */ - contextMenu?: boolean, + contextMenu?: boolean; /** * An extra class name to be added at the end of the element's class name * in order to enable custom styling. */ - customClass?: string, + customClass?: string; /** * Extra styles which will be applied in conjunction with `styles` or * `toggledStyles` when the button is disabled;. */ - disabledStyles: ?Styles, + disabledStyles?: Styles; /** * External handler for click action. */ - handleClick?: Function, + handleClick?: Function; /** * Notify mode for `toolbarButtonClicked` event - * whether to only notify or to also prevent button click routine. */ - notifyMode?: string, + notifyMode?: string; /** * Whether to show the label or not. */ - showLabel: boolean, + showLabel: boolean; /** * Collection of styles for the button. */ - styles: ?Styles, + styles?: Styles; /** * Collection of styles for the button, when in toggled state. */ - toggledStyles: ?Styles, + toggledStyles?: Styles; /** * From which direction the tooltip should appear, relative to the button. */ - tooltipPosition: string, + tooltipPosition: string; /** * Whether this button is visible or not. */ - visible: boolean -|}; - -declare var APP: Object; + visible: boolean; +}; /** * Default style for disabled buttons. @@ -93,7 +89,7 @@ export const defaultDisabledButtonStyles = { /** * An abstract implementation of a button. */ -export default class AbstractButton extends Component { +export default class AbstractButton

extends Component { static defaultProps = { afterClick: undefined, disabledStyles: defaultDisabledButtonStyles, @@ -146,7 +142,9 @@ export default class AbstractButton extends Component { * * @abstract */ - tooltip: ?string; + get tooltip(): string | undefined { + return undefined; + } /** * Initializes a new {@code AbstractButton} instance. @@ -229,7 +227,7 @@ export default class AbstractButton extends Component { * @private * @returns {?Styles} */ - _getStyles(): ?Styles { + _getStyles(): Styles | undefined { const { disabledStyles, styles, toggledStyles } = this.props; const buttonStyles = (this._isToggled() ? toggledStyles : styles) || styles; @@ -280,11 +278,9 @@ export default class AbstractButton extends Component { * @returns {?boolean} */ _isToggled() { - return undefined; + return false; } - _onClick: (*) => void; - /** * Handles clicking / pressing the button. * @@ -292,7 +288,7 @@ export default class AbstractButton extends Component { * @private * @returns {void} */ - _onClick(e) { + _onClick(e: React.MouseEvent) { const { afterClick, handleClick, notifyMode, buttonKey } = this.props; if (typeof APP !== 'undefined' && notifyMode) { @@ -309,9 +305,10 @@ export default class AbstractButton extends Component { this._handleClick(); } - afterClick && afterClick(e); + afterClick?.(e); // blur after click to release focus from button to allow PTT. + // @ts-ignore e?.currentTarget?.blur && e.currentTarget.blur(); } @@ -321,7 +318,7 @@ export default class AbstractButton extends Component { * @inheritdoc * @returns {React$Node} */ - render(): React$Node { + render(): ReactNode { const props = { ...this.props, accessibilityLabel: this.accessibilityLabel, @@ -337,6 +334,8 @@ export default class AbstractButton extends Component { return ( diff --git a/react/features/base/toolbox/components/AbstractToolboxItem.js b/react/features/base/toolbox/components/AbstractToolboxItem.tsx similarity index 81% rename from react/features/base/toolbox/components/AbstractToolboxItem.js rename to react/features/base/toolbox/components/AbstractToolboxItem.tsx index 13f41dfde..28fca2855 100644 --- a/react/features/base/toolbox/components/AbstractToolboxItem.js +++ b/react/features/base/toolbox/components/AbstractToolboxItem.tsx @@ -1,30 +1,29 @@ -// @flow +import React, { Component, ReactNode } from 'react'; +import { GestureResponderEvent } from 'react-native'; -import { Component } from 'react'; - -import type { StyleType } from '../../styles'; +import { StyleType } from '../../styles/functions.any'; export type Styles = { /** * Style for the item's icon. */ - iconStyle: StyleType, + iconStyle: StyleType; /** * Style for the item's label. */ - labelStyle: StyleType, + labelStyle: StyleType; /** * Style for the item itself. */ - style: StyleType, + style: StyleType; /** * Color for the item underlay (shows when clicked). */ - underlayColor: ?string + underlayColor?: string; }; export type Props = { @@ -33,76 +32,78 @@ export type Props = { * A succinct description of what the item does. Used by accessibility * tools and torture tests. */ - accessibilityLabel: string, + accessibilityLabel: string; /** * An extra class name to be added at the end of the element's class name * in order to enable custom styling. */ - customClass?: string, + customClass?: string; /** * Whether this item is disabled or not. When disabled, clicking an the item * has no effect, and it may reflect on its style. */ - disabled: boolean, + disabled: boolean; /** * A React Element to display at the end of {@code ToolboxItem}. */ - elementAfter?: React$Node, + elementAfter?: ReactNode; /** * The icon to render for this {@code ToolboxItem}. */ - icon: Object, + icon: Function; /** * The text associated with this item. When `showLabel` is set to * {@code true}, it will be displayed alongside the icon. */ - label: string, + label: string; + + labelProps: any; /** * On click handler. */ - onClick: Function, + onClick: (e?: React.MouseEvent | GestureResponderEvent) => void; /** * Whether to show the label or not. */ - showLabel: boolean, + showLabel: boolean; /** * Collection of styles for the item. Used only on native. */ - styles: ?Styles, + styles?: Styles; /** * Invoked to obtain translated strings. */ - t: ?Function, + t?: Function; /** * True if the item is toggled, false otherwise. */ - toggled: ?boolean, + toggled?: boolean; /** * The text to display in the tooltip. Used only on web. */ - tooltip: ?string, + tooltip?: string; /** * From which direction the tooltip should appear, relative to the * item. Used only on web. */ - tooltipPosition: string, + tooltipPosition: string; /** * Whether this item is visible or not. */ - visible: boolean + visible: boolean; }; /** @@ -111,7 +112,7 @@ export type Props = { * * @abstract */ -export default class AbstractToolboxItem

extends Component

{ +export default class AbstractToolboxItem

extends Component

{ /** * Default values for {@code AbstractToolboxItem} component's properties. * @@ -147,7 +148,7 @@ export default class AbstractToolboxItem

extends Component

{ * @protected * @returns {?string} */ - get label(): ?string { + get label(): string | undefined { return this._maybeTranslateAttribute(this.props.label, this.props.labelProps); } @@ -158,7 +159,7 @@ export default class AbstractToolboxItem

extends Component

{ * @protected * @returns {?string} */ - get tooltip(): ?string { + get tooltip(): string | undefined { return this._maybeTranslateAttribute(this.props.tooltip); } @@ -169,7 +170,7 @@ export default class AbstractToolboxItem

extends Component

{ * @protected * @returns {?string} */ - get accessibilityLabel(): ?string { + get accessibilityLabel(): string | undefined { return this._maybeTranslateAttribute(this.props.accessibilityLabel); } @@ -182,7 +183,7 @@ export default class AbstractToolboxItem

extends Component

{ * @private * @returns {string} */ - _maybeTranslateAttribute(text, textProps) { + _maybeTranslateAttribute(text?: string, textProps?: string) { const { t } = this.props; if (textProps) { @@ -193,8 +194,6 @@ export default class AbstractToolboxItem

extends Component

{ return typeof t === 'function' ? t(text) : text; } - _onClick: (*) => void; - /** * Handles clicking/pressing this {@code AbstractToolboxItem} by * forwarding the event to the {@code onClick} prop of this instance if any. @@ -202,10 +201,10 @@ export default class AbstractToolboxItem

extends Component

{ * @protected * @returns {void} */ - _onClick(...args) { + _onClick(...args: any) { const { disabled, onClick } = this.props; - disabled || (onClick && onClick(...args)); + disabled || onClick?.(...args); } /** @@ -218,7 +217,7 @@ export default class AbstractToolboxItem

extends Component

{ */ _renderItem() { // To be implemented by a subclass. - return null; + return <>; } /** diff --git a/react/features/base/toolbox/components/ToolboxItem.native.js b/react/features/base/toolbox/components/ToolboxItem.native.tsx similarity index 84% rename from react/features/base/toolbox/components/ToolboxItem.native.js rename to react/features/base/toolbox/components/ToolboxItem.native.tsx index 6378bdcfc..8bd77fced 100644 --- a/react/features/base/toolbox/components/ToolboxItem.native.js +++ b/react/features/base/toolbox/components/ToolboxItem.native.tsx @@ -1,12 +1,9 @@ -// @flow - import React from 'react'; import { Text, TouchableHighlight, View } from 'react-native'; -import { Icon } from '../../icons'; +import Icon from '../../icons/components/Icon'; -import AbstractToolboxItem from './AbstractToolboxItem'; -import type { Props } from './AbstractToolboxItem'; +import AbstractToolboxItem, { Props } from './AbstractToolboxItem'; /** * Native implementation of {@code AbstractToolboxItem}. @@ -24,7 +21,7 @@ export default class ToolboxItem extends AbstractToolboxItem { return ( + style = { styles?.iconStyle } /> ); } @@ -49,7 +46,7 @@ export default class ToolboxItem extends AbstractToolboxItem { // XXX When using a wrapper View, apply the style to it instead of // applying it to the TouchableHighlight. - let style = styles && styles.style; + let style = styles?.style; if (showLabel) { // XXX TouchableHighlight requires 1 child. If there's a need to @@ -58,7 +55,7 @@ export default class ToolboxItem extends AbstractToolboxItem { children = ( { children } - + { this.label } { elementAfter } @@ -78,7 +75,7 @@ export default class ToolboxItem extends AbstractToolboxItem { disabled = { disabled } onPress = { onClick } style = { style } - underlayColor = { styles && styles.underlayColor } > + underlayColor = { styles?.underlayColor } > { children } ); diff --git a/react/features/base/toolbox/components/ToolboxItem.web.js b/react/features/base/toolbox/components/ToolboxItem.web.tsx similarity index 89% rename from react/features/base/toolbox/components/ToolboxItem.web.js rename to react/features/base/toolbox/components/ToolboxItem.web.tsx index 21c2e6807..9df5d6e1d 100644 --- a/react/features/base/toolbox/components/ToolboxItem.web.js +++ b/react/features/base/toolbox/components/ToolboxItem.web.tsx @@ -1,8 +1,8 @@ -// @flow - import React, { Fragment } from 'react'; -import { Icon } from '../../icons'; +import Icon from '../../icons/components/Icon'; +// eslint-disable-next-line lines-around-comment +// @ts-ignore import { Tooltip } from '../../tooltip'; import ContextMenuItem from '../../ui/components/web/ContextMenuItem'; @@ -14,12 +14,12 @@ type Props = AbstractToolboxItemProps & { /** * Whether or not the item is displayed in a context menu. */ - contextMenu?: boolean, + contextMenu?: boolean; /** * On key down handler. */ - onKeyDown: Function + onKeyDown: (e?: React.KeyboardEvent) => void; }; /** @@ -37,8 +37,6 @@ export default class ToolboxItem extends AbstractToolboxItem { this._onKeyPress = this._onKeyPress.bind(this); } - _onKeyPress: (Object) => void; - /** * Handles 'Enter' and Space key on the button to trigger onClick for accessibility. * @@ -46,9 +44,9 @@ export default class ToolboxItem extends AbstractToolboxItem { * @private * @returns {void} */ - _onKeyPress(event) { - if (event.key === 'Enter' || event.key === ' ') { - event.preventDefault(); + _onKeyPress(event?: React.KeyboardEvent) { + if (event?.key === 'Enter' || event?.key === ' ') { + event?.preventDefault(); this.props.onClick(); } } @@ -92,13 +90,13 @@ export default class ToolboxItem extends AbstractToolboxItem { if (contextMenu) { return (); + text = { this.label ?? '' } />); } let children = ( diff --git a/react/features/chat/components/AbstractChat.js b/react/features/chat/components/AbstractChat.ts similarity index 77% rename from react/features/chat/components/AbstractChat.js rename to react/features/chat/components/AbstractChat.ts index b24bd1450..94ec15120 100644 --- a/react/features/chat/components/AbstractChat.js +++ b/react/features/chat/components/AbstractChat.ts @@ -1,103 +1,98 @@ -// @flow - import { Component } from 'react'; -import type { Dispatch } from 'redux'; +import { WithTranslation } from 'react-i18next'; -import { getLocalParticipant } from '../../base/participants'; +import { IReduxState, IStore } from '../../app/types'; +import { getLocalParticipant } from '../../base/participants/functions'; import { sendMessage, setIsPollsTabFocused } from '../actions'; import { SMALL_WIDTH_THRESHOLD } from '../constants'; +import { IMessage } from '../reducer'; /** * The type of the React {@code Component} props of {@code AbstractChat}. */ -export type Props = { +export interface IProps extends WithTranslation { /** * Whether the chat is opened in a modal or not (computed based on window width). */ - _isModal: boolean, + _isModal: boolean; /** * True if the chat window should be rendered. */ - _isOpen: boolean, + _isOpen: boolean; /** * True if the polls feature is enabled. */ - _isPollsEnabled: boolean, + _isPollsEnabled: boolean; /** * Whether the poll tab is focused or not. */ - _isPollsTabFocused: boolean, + _isPollsTabFocused: boolean; /** * All the chat messages in the conference. */ - _messages: Array, + _messages: Array; /** * Number of unread chat messages. */ - _nbUnreadMessages: number, + _nbUnreadMessages: number; /** * Number of unread poll messages. */ - _nbUnreadPolls: number, + _nbUnreadPolls: number; /** * Function to send a text message. * * @protected */ - _onSendMessage: Function, + _onSendMessage: Function; + + /** + * Function to toggle the chat window. + */ + _onToggleChat: Function; /** * Function to display the chat tab. * * @protected */ - _onToggleChatTab: Function, + _onToggleChatTab: Function; /** * Function to display the polls tab. * * @protected */ - _onTogglePollsTab: Function, - - /** - * Function to toggle the chat window. - */ - _onToggleChat: Function, + _onTogglePollsTab: Function; /** * Whether or not to block chat access with a nickname input form. */ - _showNamePrompt: boolean, + _showNamePrompt: boolean; /** * The Redux dispatch function. */ - dispatch: Dispatch, - - /** - * Function to be used to translate i18n labels. - */ - t: Function, -}; + dispatch: IStore['dispatch']; +} /** * Implements an abstract chat panel. */ -export default class AbstractChat extends Component

{ +export default class AbstractChat

extends Component

{ /** * Initializes a new {@code AbstractChat} instance. * - * @param {Props} props - The React {@code Component} props to initialize + * @param {IProps} props - The React {@code Component} props to initialize * the new {@code AbstractChat} instance with. */ constructor(props: P) { @@ -109,8 +104,6 @@ export default class AbstractChat extends Component

{ this._onTogglePollsTab = this._onTogglePollsTab.bind(this); } - _onSendMessage: (string) => void; - /** * Sends a text message. * @@ -123,8 +116,6 @@ export default class AbstractChat extends Component

{ this.props.dispatch(sendMessage(text)); } - _onToggleChatTab: () => void; - /** * Display the Chat tab. * @@ -135,8 +126,6 @@ export default class AbstractChat extends Component

{ this.props.dispatch(setIsPollsTabFocused(false)); } - _onTogglePollsTab: () => void; - /** * Display the Polls tab. * @@ -160,7 +149,7 @@ export default class AbstractChat extends Component

{ * _showNamePrompt: boolean * }} */ -export function _mapStateToProps(state: Object) { +export function _mapStateToProps(state: IReduxState) { const { isOpen, isPollsTabFocused, messages, nbUnreadMessages } = state['features/chat']; const { nbUnreadPolls } = state['features/polls']; const _localParticipant = getLocalParticipant(state); diff --git a/react/features/chat/components/native/Chat.js b/react/features/chat/components/native/Chat.js index ec578bee0..e2ae463a8 100644 --- a/react/features/chat/components/native/Chat.js +++ b/react/features/chat/components/native/Chat.js @@ -9,7 +9,7 @@ import { connect } from '../../../base/redux'; import { TabBarLabelCounter } from '../../../mobile/navigation/components/TabBarLabelCounter'; import { closeChat } from '../../actions.native'; import AbstractChat, { - type Props as AbstractProps, + type IProps as AbstractProps, _mapStateToProps } from '../AbstractChat'; diff --git a/react/features/chat/components/web/Chat.js b/react/features/chat/components/web/Chat.tsx similarity index 88% rename from react/features/chat/components/web/Chat.js rename to react/features/chat/components/web/Chat.tsx index aab8f3365..05c620be0 100644 --- a/react/features/chat/components/web/Chat.js +++ b/react/features/chat/components/web/Chat.tsx @@ -1,14 +1,14 @@ import clsx from 'clsx'; -import React from 'react'; +import React, { KeyboardEvent } from 'react'; +import { connect } from 'react-redux'; -import { translate } from '../../../base/i18n'; -import { connect } from '../../../base/redux'; +import { translate } from '../../../base/i18n/functions'; import Tabs from '../../../base/ui/components/web/Tabs'; -import { PollsPane } from '../../../polls/components'; +import PollsPane from '../../../polls/components/web/PollsPane'; import { toggleChat } from '../../actions.web'; import { CHAT_TABS } from '../../constants'; import AbstractChat, { - type Props, + IProps, _mapStateToProps } from '../AbstractChat'; @@ -19,11 +19,12 @@ import KeyboardAvoider from './KeyboardAvoider'; import MessageContainer from './MessageContainer'; import MessageRecipient from './MessageRecipient'; + /** * React Component for holding the chat feature in a side panel that slides in * and out of view. */ -class Chat extends AbstractChat { +class Chat extends AbstractChat { /** * Reference to the React Component for displaying chat messages. Used for @@ -37,7 +38,7 @@ class Chat extends AbstractChat { * @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._messageContainerRef = React.createRef(); @@ -67,8 +68,7 @@ class Chat extends AbstractChat { + isPollsEnabled = { _isPollsEnabled } /> { _showNamePrompt ? : this._renderChat() } @@ -76,15 +76,13 @@ class Chat extends AbstractChat { ); } - _onChatTabKeyDown: (KeyboardEvent) => void; - /** * Key press handler for the chat tab. * * @param {KeyboardEvent} event - The event. * @returns {void} */ - _onChatTabKeyDown(event) { + _onChatTabKeyDown(event: KeyboardEvent) { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); event.stopPropagation(); @@ -92,15 +90,13 @@ class Chat extends AbstractChat { } } - _onEscClick: (KeyboardEvent) => void; - /** * Click handler for the chat sidenav. * * @param {KeyboardEvent} event - Esc key click to close the popup. * @returns {void} */ - _onEscClick(event) { + _onEscClick(event: KeyboardEvent) { if (event.key === 'Escape' && this.props._isOpen) { event.preventDefault(); event.stopPropagation(); @@ -108,15 +104,13 @@ class Chat extends AbstractChat { } } - _onPollsTabKeyDown: (KeyboardEvent) => void; - /** * Key press handler for the polls tab. * * @param {KeyboardEvent} event - The event. * @returns {void} */ - _onPollsTabKeyDown(event) { + _onPollsTabKeyDown(event: KeyboardEvent) { if (event.key === 'Enter' || event.key === ' ') { event.preventDefault(); event.stopPropagation(); @@ -196,10 +190,6 @@ class Chat extends AbstractChat { ); } - _onSendMessage: (string) => void; - - _onToggleChat: () => void; - /** * Toggles the chat window. * @@ -208,9 +198,6 @@ class Chat extends AbstractChat { _onToggleChat() { this.props.dispatch(toggleChat()); } - _onTogglePollsTab: () => void; - _onToggleChatTab: () => void; - _onChangeTab: (string) => void; /** * Change selected tab. @@ -218,7 +205,7 @@ class Chat extends AbstractChat { * @param {string} id - Id of the clicked tab. * @returns {void} */ - _onChangeTab(id) { + _onChangeTab(id: string) { id === CHAT_TABS.CHAT ? this._onToggleChatTab() : this._onTogglePollsTab(); } } diff --git a/react/features/chat/components/web/ChatButton.js b/react/features/chat/components/web/ChatButton.tsx similarity index 73% rename from react/features/chat/components/web/ChatButton.js rename to react/features/chat/components/web/ChatButton.tsx index e28156178..27e2df695 100644 --- a/react/features/chat/components/web/ChatButton.js +++ b/react/features/chat/components/web/ChatButton.tsx @@ -1,29 +1,29 @@ -// @flow +import React, { ReactNode } from 'react'; +import { WithTranslation } from 'react-i18next'; +import { connect } from 'react-redux'; -import React from 'react'; - -import { translate } from '../../../base/i18n'; -import { IconMessage } from '../../../base/icons'; -import { connect } from '../../../base/redux'; -import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components'; +import { IReduxState } from '../../../app/types'; +import { translate } from '../../../base/i18n/functions'; +import { IconMessage } from '../../../base/icons/svg'; +import AbstractButton, { Props as AbstractButtonProps } from '../../../base/toolbox/components/AbstractButton'; import ChatCounter from './ChatCounter'; /** * The type of the React {@code Component} props of {@link ChatButton}. */ -type Props = AbstractButtonProps & { +interface IProps extends AbstractButtonProps, WithTranslation { /** * Whether or not the chat feature is currently displayed. */ - _chatOpen: boolean, -}; + _chatOpen: boolean; +} /** * Implementation of a button for accessing chat pane. */ -class ChatButton extends AbstractButton { +class ChatButton extends AbstractButton { accessibilityLabel = 'toolbar.accessibilityLabel.chat'; icon = IconMessage; label = 'toolbar.openChat'; @@ -67,7 +67,7 @@ class ChatButton extends AbstractButton { * @protected * @returns {boReact$Nodeolean} */ - render(): React$Node { + render(): ReactNode { return (

{ * @param {Object} state - Redux state. * @returns {Object} */ -const mapStateToProps = state => { +const mapStateToProps = (state: IReduxState) => { return { _chatOpen: state['features/chat'].isOpen }; diff --git a/react/features/chat/components/web/ChatCounter.js b/react/features/chat/components/web/ChatCounter.tsx similarity index 84% rename from react/features/chat/components/web/ChatCounter.js rename to react/features/chat/components/web/ChatCounter.tsx index 8869a3cbd..9044fe27e 100644 --- a/react/features/chat/components/web/ChatCounter.js +++ b/react/features/chat/components/web/ChatCounter.tsx @@ -1,26 +1,25 @@ -// @flow - import React, { Component } from 'react'; +import { connect } from 'react-redux'; -import { connect } from '../../../base/redux'; +import { IReduxState } from '../../../app/types'; import { getUnreadPollCount } from '../../../polls/functions'; import { getUnreadCount } from '../../functions'; /** * The type of the React {@code Component} props of {@link ChatCounter}. */ -type Props = { +interface IProps { /** * The value of to display as a count. */ - _count: number, + _count: number; /** * True if the chat window should be rendered. */ - _isOpen: boolean -}; + _isOpen: boolean; +} /** * Implements a React {@link Component} which displays a count of the number of @@ -28,7 +27,7 @@ type Props = { * * @augments Component */ -class ChatCounter extends Component { +class ChatCounter extends Component { /** * Implements React's {@link Component#render()}. @@ -61,14 +60,12 @@ class ChatCounter extends Component { * _count: number * }} */ -function _mapStateToProps(state) { +function _mapStateToProps(state: IReduxState) { const { isOpen } = state['features/chat']; return { - _count: getUnreadCount(state) + getUnreadPollCount(state), _isOpen: isOpen - }; } diff --git a/react/features/chat/components/web/ChatHeader.js b/react/features/chat/components/web/ChatHeader.tsx similarity index 72% rename from react/features/chat/components/web/ChatHeader.js rename to react/features/chat/components/web/ChatHeader.tsx index 0b5b476a0..106fbd5e6 100644 --- a/react/features/chat/components/web/ChatHeader.js +++ b/react/features/chat/components/web/ChatHeader.tsx @@ -1,41 +1,41 @@ -// @flow - import React, { useCallback } from 'react'; +import { WithTranslation } from 'react-i18next'; +import { connect } from 'react-redux'; -import { translate } from '../../../base/i18n'; -import { Icon, IconCloseLarge } from '../../../base/icons'; -import { connect } from '../../../base/redux'; +import { translate } from '../../../base/i18n/functions'; +import Icon from '../../../base/icons/components/Icon'; +import { IconCloseLarge } from '../../../base/icons/svg'; import { toggleChat } from '../../actions.web'; -type Props = { - - /** - * Function to be called when pressing the close button. - */ - onCancel: Function, +interface IProps extends WithTranslation { /** * An optional class name. */ - className: string, + className: string; + + /** + * Optional id. + */ + id?: string; /** * Whether the polls feature is enabled or not. */ - isPollsEnabled: boolean, + isPollsEnabled: boolean; /** - * Invoked to obtain translated strings. + * Function to be called when pressing the close button. */ - t: Function -}; + onCancel: Function; +} /** * Custom header of the {@code ChatDialog}. * * @returns {React$Element} */ -function Header({ onCancel, className, isPollsEnabled, t }: Props) { +function Header({ onCancel, className, isPollsEnabled, t }: IProps) { const onKeyPressHandler = useCallback(e => { if (onCancel && (e.key === ' ' || e.key === 'Enter')) { diff --git a/react/features/chat/components/web/ChatInput.tsx b/react/features/chat/components/web/ChatInput.tsx index e4451551e..1b67c42c5 100644 --- a/react/features/chat/components/web/ChatInput.tsx +++ b/react/features/chat/components/web/ChatInput.tsx @@ -1,11 +1,11 @@ import React, { Component, RefObject } from 'react'; import { WithTranslation } from 'react-i18next'; +import { connect } from 'react-redux'; import { IReduxState, IStore } from '../../../app/types'; import { isMobileBrowser } from '../../../base/environment/utils'; import { translate } from '../../../base/i18n/functions'; import { IconFaceSmile, IconSend } from '../../../base/icons/svg'; -import { connect } from '../../../base/redux/functions'; import Button from '../../../base/ui/components/web/Button'; import Input from '../../../base/ui/components/web/Input'; import { areSmileysDisabled } from '../../functions'; diff --git a/react/features/chat/components/web/DisplayNameForm.tsx b/react/features/chat/components/web/DisplayNameForm.tsx index 2c2c637da..522ab426c 100644 --- a/react/features/chat/components/web/DisplayNameForm.tsx +++ b/react/features/chat/components/web/DisplayNameForm.tsx @@ -1,9 +1,9 @@ import React, { Component } from 'react'; import { WithTranslation } from 'react-i18next'; +import { connect } from 'react-redux'; import { IStore } from '../../../app/types'; import { translate } from '../../../base/i18n/functions'; -import { connect } from '../../../base/redux/functions'; import { updateSettings } from '../../../base/settings/actions'; import Button from '../../../base/ui/components/web/Button'; import Input from '../../../base/ui/components/web/Input'; diff --git a/react/features/chat/components/web/KeyboardAvoider.js b/react/features/chat/components/web/KeyboardAvoider.tsx similarity index 99% rename from react/features/chat/components/web/KeyboardAvoider.js rename to react/features/chat/components/web/KeyboardAvoider.tsx index c9b38d4d2..ea583d52c 100644 --- a/react/features/chat/components/web/KeyboardAvoider.js +++ b/react/features/chat/components/web/KeyboardAvoider.tsx @@ -1,5 +1,3 @@ -// @flow - import React, { useEffect, useState } from 'react'; import { isIosMobileBrowser } from '../../../base/environment/utils'; diff --git a/react/features/chat/components/web/MessageRecipient.tsx b/react/features/chat/components/web/MessageRecipient.tsx index ccf9e0035..3433868d4 100644 --- a/react/features/chat/components/web/MessageRecipient.tsx +++ b/react/features/chat/components/web/MessageRecipient.tsx @@ -1,10 +1,10 @@ import { Theme } from '@mui/material'; import { withStyles } from '@mui/styles'; import React from 'react'; +import { connect } from 'react-redux'; import { translate } from '../../../base/i18n/functions'; import { IconCloseLarge } from '../../../base/icons/svg'; -import { connect } from '../../../base/redux/functions'; import { withPixelLineHeight } from '../../../base/styles/functions.web'; import Button from '../../../base/ui/components/web/Button'; import { BUTTON_TYPES } from '../../../base/ui/constants.any'; diff --git a/react/features/chat/components/web/SmileysPanel.js b/react/features/chat/components/web/SmileysPanel.tsx similarity index 90% rename from react/features/chat/components/web/SmileysPanel.js rename to react/features/chat/components/web/SmileysPanel.tsx index 05a095c8b..d1251bc4f 100644 --- a/react/features/chat/components/web/SmileysPanel.js +++ b/react/features/chat/components/web/SmileysPanel.tsx @@ -1,5 +1,3 @@ -// @flow - import React, { PureComponent } from 'react'; import Emoji from 'react-emoji-render'; @@ -14,7 +12,7 @@ type Props = { * Callback to invoke when a smiley is selected. The smiley will be passed * back. */ - onSmileySelect: Function + onSmileySelect: Function; }; /** @@ -38,8 +36,6 @@ class SmileysPanel extends PureComponent { this._onEscKey = this._onEscKey.bind(this); } - _onEscKey: (Object) => void; - /** * KeyPress handler for accessibility. * @@ -47,7 +43,7 @@ class SmileysPanel extends PureComponent { * * @returns {void} */ - _onEscKey(e) { + _onEscKey(e: React.KeyboardEvent) { // Escape handling does not work in onKeyPress if (e.key === 'Escape') { e.preventDefault(); @@ -56,8 +52,6 @@ class SmileysPanel extends PureComponent { } } - _onKeyPress: (Object) => void; - /** * KeyPress handler for accessibility. * @@ -65,15 +59,13 @@ class SmileysPanel extends PureComponent { * * @returns {void} */ - _onKeyPress(e) { + _onKeyPress(e: any) { if (e.key === ' ') { e.preventDefault(); - this.props.onSmileySelect(e.target.id && smileys[e.target.id]); + this.props.onSmileySelect(e.target.id && smileys[e.target.id as keyof typeof smileys]); } } - _onClick: (Object) => void; - /** * Click handler for to select emoji. * @@ -81,9 +73,9 @@ class SmileysPanel extends PureComponent { * * @returns {void} */ - _onClick(e) { + _onClick(e: React.MouseEvent) { e.preventDefault(); - this.props.onSmileySelect(e.currentTarget.id && smileys[e.currentTarget.id]); + this.props.onSmileySelect(e.currentTarget.id && smileys[e.currentTarget.id as keyof typeof smileys]); } /** @@ -105,7 +97,7 @@ class SmileysPanel extends PureComponent { tabIndex = { 0 }> + text = { smileys[smileyKey as keyof typeof smileys] } />
));