From 4b96a81bbe770651c98f3ce00f5d0379760f5ad0 Mon Sep 17 00:00:00 2001 From: Germain Souquet Date: Mon, 6 Sep 2021 16:15:50 +0100 Subject: [PATCH] Migrate MessageActionBar to TypeScript --- ...ssageActionBar.js => MessageActionBar.tsx} | 143 ++++++++++-------- 1 file changed, 79 insertions(+), 64 deletions(-) rename src/components/views/messages/{MessageActionBar.js => MessageActionBar.tsx} (74%) diff --git a/src/components/views/messages/MessageActionBar.js b/src/components/views/messages/MessageActionBar.tsx similarity index 74% rename from src/components/views/messages/MessageActionBar.js rename to src/components/views/messages/MessageActionBar.tsx index cb8ea7a50d..bfca3406d3 100644 --- a/src/components/views/messages/MessageActionBar.js +++ b/src/components/views/messages/MessageActionBar.tsx @@ -17,8 +17,7 @@ limitations under the License. */ import React, { useEffect } from 'react'; -import PropTypes from 'prop-types'; -import { EventStatus } from 'matrix-js-sdk/src/models/event'; +import { MatrixEvent, EventStatus } from 'matrix-js-sdk/src/models/event'; import { _t } from '../../../languageHandler'; import * as sdk from '../../../index'; @@ -37,48 +36,64 @@ import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MediaEventHelper } from "../../../utils/MediaEventHelper"; import DownloadActionButton from "./DownloadActionButton"; import SettingsStore from '../../../settings/SettingsStore'; +import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks'; -const OptionsButton = ({ mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange }) => { - const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); - const [onFocus, isActive, ref] = useRovingTabIndex(button); - useEffect(() => { - onFocusChange(menuDisplayed); - }, [onFocusChange, menuDisplayed]); +interface IOptionsButtonProps { + mxEvent: MatrixEvent; + getTile: () => any; // TODO: FIXME, haven't figured out what the return type is here + getReplyThread: () => any; // TODO: FIXME, haven't figured out what the return type is here + permalinkCreator: RoomPermalinkCreator; + onFocusChange: (menuDisplayed: boolean) => void; +} - let contextMenu; - if (menuDisplayed) { - const MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu'); +const OptionsButton: React.FC = + ({ mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange }) => { + const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); + const [onFocus, isActive, ref] = useRovingTabIndex(button); + useEffect(() => { + onFocusChange(menuDisplayed); + }, [onFocusChange, menuDisplayed]); - const tile = getTile && getTile(); - const replyThread = getReplyThread && getReplyThread(); + let contextMenu; + if (menuDisplayed) { + const MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu'); - const buttonRect = button.current.getBoundingClientRect(); - contextMenu = ; - } + const tile = getTile && getTile(); + const replyThread = getReplyThread && getReplyThread(); - return - + const buttonRect = button.current.getBoundingClientRect(); + contextMenu = ; + } - { contextMenu } - ; -}; + return + -const ReactButton = ({ mxEvent, reactions, onFocusChange }) => { + { contextMenu } + ; + }; + +interface IReactButtonProps { + mxEvent: MatrixEvent; + reactions: any; + onFocusChange: (menuDisplayed: boolean) => void; +} + +const ReactButton: React.FC = ({ mxEvent, reactions, onFocusChange }) => { const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); const [onFocus, isActive, ref] = useRovingTabIndex(button); useEffect(() => { @@ -109,21 +124,21 @@ const ReactButton = ({ mxEvent, reactions, onFocusChange }) => { ; }; +interface IMessageActionBarProps { + mxEvent: MatrixEvent; + // The Relations model from the JS SDK for reactions to `mxEvent` + reactions?: any; + permalinkCreator?: RoomPermalinkCreator; + getTile: () => any; // TODO: FIXME, haven't figured out what the return type is here + getReplyThread?: () => JSX.Element; + onFocusChange?: (menuDisplayed: boolean) => void; +} + @replaceableComponent("views.messages.MessageActionBar") -export default class MessageActionBar extends React.PureComponent { - static propTypes = { - mxEvent: PropTypes.object.isRequired, - // The Relations model from the JS SDK for reactions to `mxEvent` - reactions: PropTypes.object, - permalinkCreator: PropTypes.object, - getTile: PropTypes.func, - getReplyThread: PropTypes.func, - onFocusChange: PropTypes.func, - }; +export default class MessageActionBar extends React.PureComponent { + public static contextType = RoomContext; - static contextType = RoomContext; - - componentDidMount() { + public componentDidMount(): void { if (this.props.mxEvent.status && this.props.mxEvent.status !== EventStatus.SENT) { this.props.mxEvent.on("Event.status", this.onSent); } @@ -137,43 +152,43 @@ export default class MessageActionBar extends React.PureComponent { this.props.mxEvent.on("Event.beforeRedaction", this.onBeforeRedaction); } - componentWillUnmount() { + public componentWillUnmount(): void { this.props.mxEvent.off("Event.status", this.onSent); this.props.mxEvent.off("Event.decrypted", this.onDecrypted); this.props.mxEvent.off("Event.beforeRedaction", this.onBeforeRedaction); } - onDecrypted = () => { + private onDecrypted = (): void => { // When an event decrypts, it is likely to change the set of available // actions, so we force an update to check again. this.forceUpdate(); }; - onBeforeRedaction = () => { + private onBeforeRedaction = (): void => { // When an event is redacted, we can't edit it so update the available actions. this.forceUpdate(); }; - onSent = () => { + private onSent = (): void => { // When an event is sent and echoed the possible actions change. this.forceUpdate(); }; - onFocusChange = (focused) => { + private onFocusChange = (focused: boolean): void => { if (!this.props.onFocusChange) { return; } this.props.onFocusChange(focused); }; - onReplyClick = (ev) => { + private onReplyClick = (ev: React.MouseEvent): void => { dis.dispatch({ action: 'reply_to_event', event: this.props.mxEvent, }); }; - onThreadClick = () => { + private onThreadClick = (): void => { dis.dispatch({ action: Action.SetRightPanelPhase, phase: RightPanelPhases.ThreadView, @@ -182,9 +197,9 @@ export default class MessageActionBar extends React.PureComponent { event: this.props.mxEvent, }, }); - } + }; - onEditClick = (ev) => { + private onEditClick = (ev: React.MouseEvent): void => { dis.dispatch({ action: 'edit_event', event: this.props.mxEvent, @@ -200,7 +215,7 @@ export default class MessageActionBar extends React.PureComponent { * @param {Function} fn The execution function. * @param {Function} checkFn The test function. */ - runActionOnFailedEv(fn, checkFn) { + private runActionOnFailedEv(fn: (ev: MatrixEvent) => void, checkFn?: (ev: MatrixEvent) => boolean): void { if (!checkFn) checkFn = () => true; const mxEvent = this.props.mxEvent; @@ -215,18 +230,18 @@ export default class MessageActionBar extends React.PureComponent { } } - onResendClick = (ev) => { + private onResendClick = (ev: React.MouseEvent): void => { this.runActionOnFailedEv((tarEv) => Resend.resend(tarEv)); }; - onCancelClick = (ev) => { + private onCancelClick = (ev: React.MouseEvent): void => { this.runActionOnFailedEv( (tarEv) => Resend.removeFromQueue(tarEv), (testEv) => canCancel(testEv.status), ); }; - render() { + public render(): JSX.Element { const toolbarOpts = []; if (canEditContent(this.props.mxEvent)) { toolbarOpts.push(