Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit b5a5669

Browse files
authored
Refactor MessageComposerButtons (#7668)
1 parent 7c20eb9 commit b5a5669

File tree

2 files changed

+153
-82
lines changed

2 files changed

+153
-82
lines changed

src/components/views/rooms/MessageComposerButtons.tsx

Lines changed: 151 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ limitations under the License.
1717
import classNames from 'classnames';
1818
import { IEventRelation } from "matrix-js-sdk/src/models/event";
1919
import { M_POLL_START } from "matrix-events-sdk";
20-
import React, { useContext } from 'react';
20+
import React, { ReactElement, useContext } from 'react';
2121
import { Room } from 'matrix-js-sdk/src/models/room';
2222
import { MatrixClient } from 'matrix-js-sdk/src/client';
2323

@@ -56,85 +56,55 @@ const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
5656
const matrixClient: MatrixClient = useContext(MatrixClientContext);
5757
const { room, roomId } = useContext(RoomContext);
5858

59-
if (props.haveRecording) {
60-
return null;
61-
}
62-
63-
let uploadButtonIndex = 0;
64-
const buttons: JSX.Element[] = [];
65-
buttons.push(
66-
<PollButton
67-
key="polls"
68-
room={room}
69-
narrowMode={props.narrowMode}
70-
/>,
71-
);
72-
uploadButtonIndex = buttons.length;
73-
buttons.push(
74-
<UploadButton key="controls_upload" roomId={roomId} relation={props.relation} />,
75-
);
76-
if (props.showLocationButton) {
77-
const sender = room.getMember(matrixClient.getUserId());
78-
buttons.push(
79-
<LocationButton
80-
key="location"
81-
roomId={roomId}
82-
sender={sender}
83-
menuPosition={props.menuPosition}
84-
narrowMode={props.narrowMode}
85-
/>,
86-
);
87-
}
88-
buttons.push(
89-
<EmojiButton key="emoji_button" addEmoji={props.addEmoji} menuPosition={props.menuPosition} narrowMode={props.narrowMode} />,
59+
return (
60+
props.haveRecording
61+
? null
62+
: props.narrowMode
63+
? narrowMode(props, room, roomId, matrixClient)
64+
: wideMode(props, room, roomId, matrixClient)
9065
);
91-
if (props.showStickersButton) {
92-
let title: string;
93-
if (!props.narrowMode) {
94-
title = props.isStickerPickerOpen ? _t("Hide Stickers") : _t("Show Stickers");
95-
}
96-
97-
buttons.push(
98-
<AccessibleTooltipButton
99-
id='stickersButton'
100-
key="controls_stickers"
101-
className="mx_MessageComposer_button mx_MessageComposer_stickers"
102-
onClick={() => props.setStickerPickerOpen(!props.isStickerPickerOpen)}
103-
title={title}
104-
label={props.narrowMode ? _t("Send a sticker") : null}
105-
/>,
106-
);
107-
}
108-
109-
// XXX: the recording UI does not work well in narrow mode, so we hide this button for now
110-
if (!props.narrowMode) {
111-
buttons.push(
112-
<CollapsibleButton
113-
key="voice_message_send"
114-
className="mx_MessageComposer_button mx_MessageComposer_voiceMessage"
115-
onClick={props.onRecordStartEndClick}
116-
title={_t("Send voice message")}
117-
narrowMode={props.narrowMode}
118-
/>,
119-
);
120-
}
66+
};
12167

122-
if (!props.narrowMode) {
123-
return <>{ buttons }</>;
124-
}
68+
function wideMode(
69+
props: IProps,
70+
room: Room,
71+
roomId: string,
72+
matrixClient: MatrixClient,
73+
): ReactElement {
74+
return <>
75+
{ pollButton(props, room) }
76+
{ uploadButton(props, roomId) }
77+
{ showLocationButton(props, room, roomId, matrixClient) }
78+
{ emojiButton(props) }
79+
{ showStickersButton(props) }
80+
{ voiceRecordingButton(props) }
81+
</>;
82+
}
12583

126-
const classnames = classNames({
84+
function narrowMode(
85+
props: IProps,
86+
room: Room,
87+
roomId: string,
88+
matrixClient: MatrixClient,
89+
): ReactElement {
90+
const moreOptionsClasses = classNames({
12791
mx_MessageComposer_button: true,
12892
mx_MessageComposer_buttonMenu: true,
12993
mx_MessageComposer_closeButtonMenu: props.isMenuOpen,
13094
});
13195

132-
// we render the uploadButton at top level as it is a very common interaction, splice it out of the rest
133-
const [uploadButton] = buttons.splice(uploadButtonIndex, 1);
96+
const moreButtons = [
97+
pollButton(props, room),
98+
showLocationButton(props, room, roomId, matrixClient),
99+
emojiButton(props),
100+
showStickersButton(props),
101+
voiceRecordingButton(props),
102+
].filter(x => x);
103+
134104
return <>
135-
{ uploadButton }
105+
{ uploadButton(props, roomId) }
136106
<AccessibleTooltipButton
137-
className={classnames}
107+
className={moreOptionsClasses}
138108
onClick={props.toggleButtonMenu}
139109
title={_t("More options")}
140110
tooltip={false}
@@ -145,28 +115,50 @@ const MessageComposerButtons: React.FC<IProps> = (props: IProps) => {
145115
{...props.menuPosition}
146116
wrapperClassName="mx_MessageComposer_Menu"
147117
>
148-
{ buttons.map((button, index) => (
149-
<MenuItem className="mx_CallContextMenu_item" key={index} onClick={props.toggleButtonMenu}>
118+
{ moreButtons.map((button, index) => (
119+
<MenuItem
120+
className="mx_CallContextMenu_item"
121+
key={index}
122+
onClick={props.toggleButtonMenu}
123+
>
150124
{ button }
151125
</MenuItem>
152126
)) }
153127
</ContextMenu>
154128
) }
155129
</>;
156-
};
130+
}
131+
132+
function emojiButton(props: IProps): ReactElement {
133+
return <EmojiButton
134+
key="emoji_button"
135+
addEmoji={props.addEmoji}
136+
menuPosition={props.menuPosition}
137+
narrowMode={props.narrowMode}
138+
/>;
139+
}
157140

158141
interface IEmojiButtonProps extends Pick<ICollapsibleButtonProps, "narrowMode"> {
159142
addEmoji: (unicode: string) => boolean;
160143
menuPosition: AboveLeftOf;
161144
}
162145

163-
const EmojiButton: React.FC<IEmojiButtonProps> = ({ addEmoji, menuPosition, narrowMode }) => {
146+
const EmojiButton: React.FC<IEmojiButtonProps> = (
147+
{ addEmoji, menuPosition, narrowMode },
148+
) => {
164149
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
165150

166151
let contextMenu: React.ReactElement | null = null;
167152
if (menuDisplayed) {
168-
const position = menuPosition ?? aboveLeftOf(button.current.getBoundingClientRect());
169-
contextMenu = <ContextMenu {...position} onFinished={closeMenu} managed={false}>
153+
const position = (
154+
menuPosition ?? aboveLeftOf(button.current.getBoundingClientRect())
155+
);
156+
157+
contextMenu = <ContextMenu
158+
{...position}
159+
onFinished={closeMenu}
160+
managed={false}
161+
>
170162
<EmojiPicker onChoose={addEmoji} showQuickReactions={true} />
171163
</ContextMenu>;
172164
}
@@ -193,6 +185,14 @@ const EmojiButton: React.FC<IEmojiButtonProps> = ({ addEmoji, menuPosition, narr
193185
</React.Fragment>;
194186
};
195187

188+
function uploadButton(props: IProps, roomId: string): ReactElement {
189+
return <UploadButton
190+
key="controls_upload"
191+
roomId={roomId}
192+
relation={props.relation}
193+
/>;
194+
}
195+
196196
interface IUploadButtonProps {
197197
roomId: string;
198198
relation?: IEventRelation | null;
@@ -270,6 +270,51 @@ class UploadButton extends React.Component<IUploadButtonProps> {
270270
);
271271
}
272272
}
273+
274+
function showStickersButton(props: IProps): ReactElement {
275+
return (
276+
props.showStickersButton
277+
? <AccessibleTooltipButton
278+
id='stickersButton'
279+
key="controls_stickers"
280+
className="mx_MessageComposer_button mx_MessageComposer_stickers"
281+
onClick={() => props.setStickerPickerOpen(!props.isStickerPickerOpen)}
282+
title={
283+
props.narrowMode
284+
? null
285+
: props.isStickerPickerOpen
286+
? _t("Hide Stickers")
287+
: _t("Show Stickers")
288+
}
289+
label={props.narrowMode ? _t("Send a sticker") : null}
290+
/>
291+
: null
292+
);
293+
}
294+
295+
function voiceRecordingButton(props: IProps): ReactElement {
296+
// XXX: recording UI does not work well in narrow mode, so hide for now
297+
return (
298+
props.narrowMode
299+
? null
300+
: <CollapsibleButton
301+
key="voice_message_send"
302+
className="mx_MessageComposer_button mx_MessageComposer_voiceMessage"
303+
onClick={props.onRecordStartEndClick}
304+
title={_t("Send voice message")}
305+
narrowMode={props.narrowMode}
306+
/>
307+
);
308+
}
309+
310+
function pollButton(props: IProps, room: Room): ReactElement {
311+
return <PollButton
312+
key="polls"
313+
room={room}
314+
narrowMode={props.narrowMode}
315+
/>;
316+
}
317+
273318
interface IPollButtonProps extends Pick<ICollapsibleButtonProps, "narrowMode"> {
274319
room: Room;
275320
}
@@ -281,10 +326,17 @@ class PollButton extends React.PureComponent<IPollButtonProps> {
281326
MatrixClientPeg.get().getUserId(),
282327
);
283328
if (!canSend) {
284-
Modal.createTrackedDialog('Polls', 'permissions error: cannot start', ErrorDialog, {
285-
title: _t("Permission Required"),
286-
description: _t("You do not have permission to start polls in this room."),
287-
});
329+
Modal.createTrackedDialog(
330+
'Polls',
331+
'permissions error: cannot start',
332+
ErrorDialog,
333+
{
334+
title: _t("Permission Required"),
335+
description: _t(
336+
"You do not have permission to start polls in this room.",
337+
),
338+
},
339+
);
288340
} else {
289341
Modal.createTrackedDialog(
290342
'Polls',
@@ -312,4 +364,23 @@ class PollButton extends React.PureComponent<IPollButtonProps> {
312364
}
313365
}
314366

367+
function showLocationButton(
368+
props: IProps,
369+
room: Room,
370+
roomId: string,
371+
matrixClient: MatrixClient,
372+
): ReactElement {
373+
return (
374+
props.showLocationButton
375+
? <LocationButton
376+
key="location"
377+
roomId={roomId}
378+
sender={room.getMember(matrixClient.getUserId())}
379+
menuPosition={props.menuPosition}
380+
narrowMode={props.narrowMode}
381+
/>
382+
: null
383+
);
384+
}
385+
315386
export default MessageComposerButtons;

src/i18n/strings/en_EN.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,11 +1694,11 @@
16941694
"You do not have permission to post to this room": "You do not have permission to post to this room",
16951695
"%(seconds)ss left": "%(seconds)ss left",
16961696
"Send voice message": "Send voice message",
1697+
"Add emoji": "Add emoji",
1698+
"Upload file": "Upload file",
16971699
"Hide Stickers": "Hide Stickers",
16981700
"Show Stickers": "Show Stickers",
16991701
"Send a sticker": "Send a sticker",
1700-
"Add emoji": "Add emoji",
1701-
"Upload file": "Upload file",
17021702
"You do not have permission to start polls in this room.": "You do not have permission to start polls in this room.",
17031703
"Create poll": "Create poll",
17041704
"Bold": "Bold",

0 commit comments

Comments
 (0)