From b5a56698d674802d62181c4040c62b22332c0a91 Mon Sep 17 00:00:00 2001 From: Andy Balaam Date: Mon, 31 Jan 2022 09:19:26 +0000 Subject: [PATCH] Refactor MessageComposerButtons (#7668) --- .../views/rooms/MessageComposerButtons.tsx | 231 ++++++++++++------ src/i18n/strings/en_EN.json | 4 +- 2 files changed, 153 insertions(+), 82 deletions(-) diff --git a/src/components/views/rooms/MessageComposerButtons.tsx b/src/components/views/rooms/MessageComposerButtons.tsx index 389dc0bcde..bbabb689c1 100644 --- a/src/components/views/rooms/MessageComposerButtons.tsx +++ b/src/components/views/rooms/MessageComposerButtons.tsx @@ -17,7 +17,7 @@ limitations under the License. import classNames from 'classnames'; import { IEventRelation } from "matrix-js-sdk/src/models/event"; import { M_POLL_START } from "matrix-events-sdk"; -import React, { useContext } from 'react'; +import React, { ReactElement, useContext } from 'react'; import { Room } from 'matrix-js-sdk/src/models/room'; import { MatrixClient } from 'matrix-js-sdk/src/client'; @@ -56,85 +56,55 @@ const MessageComposerButtons: React.FC = (props: IProps) => { const matrixClient: MatrixClient = useContext(MatrixClientContext); const { room, roomId } = useContext(RoomContext); - if (props.haveRecording) { - return null; - } - - let uploadButtonIndex = 0; - const buttons: JSX.Element[] = []; - buttons.push( - , + return ( + props.haveRecording + ? null + : props.narrowMode + ? narrowMode(props, room, roomId, matrixClient) + : wideMode(props, room, roomId, matrixClient) ); - uploadButtonIndex = buttons.length; - buttons.push( - , - ); - if (props.showLocationButton) { - const sender = room.getMember(matrixClient.getUserId()); - buttons.push( - , - ); - } - buttons.push( - , - ); - if (props.showStickersButton) { - let title: string; - if (!props.narrowMode) { - title = props.isStickerPickerOpen ? _t("Hide Stickers") : _t("Show Stickers"); - } +}; - buttons.push( - props.setStickerPickerOpen(!props.isStickerPickerOpen)} - title={title} - label={props.narrowMode ? _t("Send a sticker") : null} - />, - ); - } +function wideMode( + props: IProps, + room: Room, + roomId: string, + matrixClient: MatrixClient, +): ReactElement { + return <> + { pollButton(props, room) } + { uploadButton(props, roomId) } + { showLocationButton(props, room, roomId, matrixClient) } + { emojiButton(props) } + { showStickersButton(props) } + { voiceRecordingButton(props) } + ; +} - // XXX: the recording UI does not work well in narrow mode, so we hide this button for now - if (!props.narrowMode) { - buttons.push( - , - ); - } - - if (!props.narrowMode) { - return <>{ buttons }; - } - - const classnames = classNames({ +function narrowMode( + props: IProps, + room: Room, + roomId: string, + matrixClient: MatrixClient, +): ReactElement { + const moreOptionsClasses = classNames({ mx_MessageComposer_button: true, mx_MessageComposer_buttonMenu: true, mx_MessageComposer_closeButtonMenu: props.isMenuOpen, }); - // we render the uploadButton at top level as it is a very common interaction, splice it out of the rest - const [uploadButton] = buttons.splice(uploadButtonIndex, 1); + const moreButtons = [ + pollButton(props, room), + showLocationButton(props, room, roomId, matrixClient), + emojiButton(props), + showStickersButton(props), + voiceRecordingButton(props), + ].filter(x => x); + return <> - { uploadButton } + { uploadButton(props, roomId) } = (props: IProps) => { {...props.menuPosition} wrapperClassName="mx_MessageComposer_Menu" > - { buttons.map((button, index) => ( - + { moreButtons.map((button, index) => ( + { button } )) } ) } ; -}; +} + +function emojiButton(props: IProps): ReactElement { + return ; +} interface IEmojiButtonProps extends Pick { addEmoji: (unicode: string) => boolean; menuPosition: AboveLeftOf; } -const EmojiButton: React.FC = ({ addEmoji, menuPosition, narrowMode }) => { +const EmojiButton: React.FC = ( + { addEmoji, menuPosition, narrowMode }, +) => { const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); let contextMenu: React.ReactElement | null = null; if (menuDisplayed) { - const position = menuPosition ?? aboveLeftOf(button.current.getBoundingClientRect()); - contextMenu = + const position = ( + menuPosition ?? aboveLeftOf(button.current.getBoundingClientRect()) + ); + + contextMenu = ; } @@ -193,6 +185,14 @@ const EmojiButton: React.FC = ({ addEmoji, menuPosition, narr ; }; +function uploadButton(props: IProps, roomId: string): ReactElement { + return ; +} + interface IUploadButtonProps { roomId: string; relation?: IEventRelation | null; @@ -270,6 +270,51 @@ class UploadButton extends React.Component { ); } } + +function showStickersButton(props: IProps): ReactElement { + return ( + props.showStickersButton + ? props.setStickerPickerOpen(!props.isStickerPickerOpen)} + title={ + props.narrowMode + ? null + : props.isStickerPickerOpen + ? _t("Hide Stickers") + : _t("Show Stickers") + } + label={props.narrowMode ? _t("Send a sticker") : null} + /> + : null + ); +} + +function voiceRecordingButton(props: IProps): ReactElement { + // XXX: recording UI does not work well in narrow mode, so hide for now + return ( + props.narrowMode + ? null + : + ); +} + +function pollButton(props: IProps, room: Room): ReactElement { + return ; +} + interface IPollButtonProps extends Pick { room: Room; } @@ -281,10 +326,17 @@ class PollButton extends React.PureComponent { MatrixClientPeg.get().getUserId(), ); if (!canSend) { - Modal.createTrackedDialog('Polls', 'permissions error: cannot start', ErrorDialog, { - title: _t("Permission Required"), - description: _t("You do not have permission to start polls in this room."), - }); + Modal.createTrackedDialog( + 'Polls', + 'permissions error: cannot start', + ErrorDialog, + { + title: _t("Permission Required"), + description: _t( + "You do not have permission to start polls in this room.", + ), + }, + ); } else { Modal.createTrackedDialog( 'Polls', @@ -312,4 +364,23 @@ class PollButton extends React.PureComponent { } } +function showLocationButton( + props: IProps, + room: Room, + roomId: string, + matrixClient: MatrixClient, +): ReactElement { + return ( + props.showLocationButton + ? + : null + ); +} + export default MessageComposerButtons; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 9861e92b73..c641173a09 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1694,11 +1694,11 @@ "You do not have permission to post to this room": "You do not have permission to post to this room", "%(seconds)ss left": "%(seconds)ss left", "Send voice message": "Send voice message", + "Add emoji": "Add emoji", + "Upload file": "Upload file", "Hide Stickers": "Hide Stickers", "Show Stickers": "Show Stickers", "Send a sticker": "Send a sticker", - "Add emoji": "Add emoji", - "Upload file": "Upload file", "You do not have permission to start polls in this room.": "You do not have permission to start polls in this room.", "Create poll": "Create poll", "Bold": "Bold",