Skip to content

Commit 42f5efa

Browse files
authored
Merge pull request matrix-org#6750 from matrix-org/gsouquet/migrate-messageactionbar
2 parents 51f1d21 + 9cbf871 commit 42f5efa

File tree

1 file changed

+83
-67
lines changed

1 file changed

+83
-67
lines changed

src/components/views/messages/MessageActionBar.js renamed to src/components/views/messages/MessageActionBar.tsx

Lines changed: 83 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ limitations under the License.
1717
*/
1818

1919
import React, { useEffect } from 'react';
20-
import PropTypes from 'prop-types';
21-
import { EventStatus } from 'matrix-js-sdk/src/models/event';
20+
import { MatrixEvent, EventStatus } from 'matrix-js-sdk/src/models/event';
2221

2322
import { _t } from '../../../languageHandler';
2423
import * as sdk from '../../../index';
@@ -37,48 +36,65 @@ import { MatrixClientPeg } from "../../../MatrixClientPeg";
3736
import { MediaEventHelper } from "../../../utils/MediaEventHelper";
3837
import DownloadActionButton from "./DownloadActionButton";
3938
import SettingsStore from '../../../settings/SettingsStore';
39+
import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
40+
import ReplyThread from '../elements/ReplyThread';
41+
42+
interface IOptionsButtonProps {
43+
mxEvent: MatrixEvent;
44+
getTile: () => any; // TODO: FIXME, haven't figured out what the return type is here
45+
getReplyThread: () => ReplyThread;
46+
permalinkCreator: RoomPermalinkCreator;
47+
onFocusChange: (menuDisplayed: boolean) => void;
48+
}
4049

41-
const OptionsButton = ({ mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange }) => {
42-
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
43-
const [onFocus, isActive, ref] = useRovingTabIndex(button);
44-
useEffect(() => {
45-
onFocusChange(menuDisplayed);
46-
}, [onFocusChange, menuDisplayed]);
47-
48-
let contextMenu;
49-
if (menuDisplayed) {
50-
const MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu');
51-
52-
const tile = getTile && getTile();
53-
const replyThread = getReplyThread && getReplyThread();
54-
55-
const buttonRect = button.current.getBoundingClientRect();
56-
contextMenu = <MessageContextMenu
57-
{...aboveLeftOf(buttonRect)}
58-
mxEvent={mxEvent}
59-
permalinkCreator={permalinkCreator}
60-
eventTileOps={tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined}
61-
collapseReplyThread={replyThread && replyThread.canCollapse() ? replyThread.collapse : undefined}
62-
onFinished={closeMenu}
63-
/>;
64-
}
50+
const OptionsButton: React.FC<IOptionsButtonProps> =
51+
({ mxEvent, getTile, getReplyThread, permalinkCreator, onFocusChange }) => {
52+
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
53+
const [onFocus, isActive, ref] = useRovingTabIndex(button);
54+
useEffect(() => {
55+
onFocusChange(menuDisplayed);
56+
}, [onFocusChange, menuDisplayed]);
57+
58+
let contextMenu;
59+
if (menuDisplayed) {
60+
const MessageContextMenu = sdk.getComponent('context_menus.MessageContextMenu');
61+
62+
const tile = getTile && getTile();
63+
const replyThread = getReplyThread && getReplyThread();
64+
65+
const buttonRect = button.current.getBoundingClientRect();
66+
contextMenu = <MessageContextMenu
67+
{...aboveLeftOf(buttonRect)}
68+
mxEvent={mxEvent}
69+
permalinkCreator={permalinkCreator}
70+
eventTileOps={tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined}
71+
collapseReplyThread={replyThread && replyThread.canCollapse() ? replyThread.collapse : undefined}
72+
onFinished={closeMenu}
73+
/>;
74+
}
6575

66-
return <React.Fragment>
67-
<ContextMenuTooltipButton
68-
className="mx_MessageActionBar_maskButton mx_MessageActionBar_optionsButton"
69-
title={_t("Options")}
70-
onClick={openMenu}
71-
isExpanded={menuDisplayed}
72-
inputRef={ref}
73-
onFocus={onFocus}
74-
tabIndex={isActive ? 0 : -1}
75-
/>
76+
return <React.Fragment>
77+
<ContextMenuTooltipButton
78+
className="mx_MessageActionBar_maskButton mx_MessageActionBar_optionsButton"
79+
title={_t("Options")}
80+
onClick={openMenu}
81+
isExpanded={menuDisplayed}
82+
inputRef={ref}
83+
onFocus={onFocus}
84+
tabIndex={isActive ? 0 : -1}
85+
/>
86+
87+
{ contextMenu }
88+
</React.Fragment>;
89+
};
7690

77-
{ contextMenu }
78-
</React.Fragment>;
79-
};
91+
interface IReactButtonProps {
92+
mxEvent: MatrixEvent;
93+
reactions: any; // TODO: types
94+
onFocusChange: (menuDisplayed: boolean) => void;
95+
}
8096

81-
const ReactButton = ({ mxEvent, reactions, onFocusChange }) => {
97+
const ReactButton: React.FC<IReactButtonProps> = ({ mxEvent, reactions, onFocusChange }) => {
8298
const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu();
8399
const [onFocus, isActive, ref] = useRovingTabIndex(button);
84100
useEffect(() => {
@@ -109,21 +125,21 @@ const ReactButton = ({ mxEvent, reactions, onFocusChange }) => {
109125
</React.Fragment>;
110126
};
111127

112-
@replaceableComponent("views.messages.MessageActionBar")
113-
export default class MessageActionBar extends React.PureComponent {
114-
static propTypes = {
115-
mxEvent: PropTypes.object.isRequired,
116-
// The Relations model from the JS SDK for reactions to `mxEvent`
117-
reactions: PropTypes.object,
118-
permalinkCreator: PropTypes.object,
119-
getTile: PropTypes.func,
120-
getReplyThread: PropTypes.func,
121-
onFocusChange: PropTypes.func,
122-
};
128+
interface IMessageActionBarProps {
129+
mxEvent: MatrixEvent;
130+
// The Relations model from the JS SDK for reactions to `mxEvent`
131+
reactions?: any; // TODO: types
132+
permalinkCreator?: RoomPermalinkCreator;
133+
getTile: () => any; // TODO: FIXME, haven't figured out what the return type is here
134+
getReplyThread?: () => ReplyThread;
135+
onFocusChange?: (menuDisplayed: boolean) => void;
136+
}
123137

124-
static contextType = RoomContext;
138+
@replaceableComponent("views.messages.MessageActionBar")
139+
export default class MessageActionBar extends React.PureComponent<IMessageActionBarProps> {
140+
public static contextType = RoomContext;
125141

126-
componentDidMount() {
142+
public componentDidMount(): void {
127143
if (this.props.mxEvent.status && this.props.mxEvent.status !== EventStatus.SENT) {
128144
this.props.mxEvent.on("Event.status", this.onSent);
129145
}
@@ -137,43 +153,43 @@ export default class MessageActionBar extends React.PureComponent {
137153
this.props.mxEvent.on("Event.beforeRedaction", this.onBeforeRedaction);
138154
}
139155

140-
componentWillUnmount() {
156+
public componentWillUnmount(): void {
141157
this.props.mxEvent.off("Event.status", this.onSent);
142158
this.props.mxEvent.off("Event.decrypted", this.onDecrypted);
143159
this.props.mxEvent.off("Event.beforeRedaction", this.onBeforeRedaction);
144160
}
145161

146-
onDecrypted = () => {
162+
private onDecrypted = (): void => {
147163
// When an event decrypts, it is likely to change the set of available
148164
// actions, so we force an update to check again.
149165
this.forceUpdate();
150166
};
151167

152-
onBeforeRedaction = () => {
168+
private onBeforeRedaction = (): void => {
153169
// When an event is redacted, we can't edit it so update the available actions.
154170
this.forceUpdate();
155171
};
156172

157-
onSent = () => {
173+
private onSent = (): void => {
158174
// When an event is sent and echoed the possible actions change.
159175
this.forceUpdate();
160176
};
161177

162-
onFocusChange = (focused) => {
178+
private onFocusChange = (focused: boolean): void => {
163179
if (!this.props.onFocusChange) {
164180
return;
165181
}
166182
this.props.onFocusChange(focused);
167183
};
168184

169-
onReplyClick = (ev) => {
185+
private onReplyClick = (ev: React.MouseEvent): void => {
170186
dis.dispatch({
171187
action: 'reply_to_event',
172188
event: this.props.mxEvent,
173189
});
174190
};
175191

176-
onThreadClick = () => {
192+
private onThreadClick = (): void => {
177193
dis.dispatch({
178194
action: Action.SetRightPanelPhase,
179195
phase: RightPanelPhases.ThreadView,
@@ -182,9 +198,9 @@ export default class MessageActionBar extends React.PureComponent {
182198
event: this.props.mxEvent,
183199
},
184200
});
185-
}
201+
};
186202

187-
onEditClick = (ev) => {
203+
private onEditClick = (ev: React.MouseEvent): void => {
188204
dis.dispatch({
189205
action: 'edit_event',
190206
event: this.props.mxEvent,
@@ -200,7 +216,7 @@ export default class MessageActionBar extends React.PureComponent {
200216
* @param {Function} fn The execution function.
201217
* @param {Function} checkFn The test function.
202218
*/
203-
runActionOnFailedEv(fn, checkFn) {
219+
private runActionOnFailedEv(fn: (ev: MatrixEvent) => void, checkFn?: (ev: MatrixEvent) => boolean): void {
204220
if (!checkFn) checkFn = () => true;
205221

206222
const mxEvent = this.props.mxEvent;
@@ -215,18 +231,18 @@ export default class MessageActionBar extends React.PureComponent {
215231
}
216232
}
217233

218-
onResendClick = (ev) => {
234+
private onResendClick = (ev: React.MouseEvent): void => {
219235
this.runActionOnFailedEv((tarEv) => Resend.resend(tarEv));
220236
};
221237

222-
onCancelClick = (ev) => {
238+
private onCancelClick = (ev: React.MouseEvent): void => {
223239
this.runActionOnFailedEv(
224240
(tarEv) => Resend.removeFromQueue(tarEv),
225241
(testEv) => canCancel(testEv.status),
226242
);
227243
};
228244

229-
render() {
245+
public render(): JSX.Element {
230246
const toolbarOpts = [];
231247
if (canEditContent(this.props.mxEvent)) {
232248
toolbarOpts.push(<RovingAccessibleTooltipButton
@@ -249,7 +265,7 @@ export default class MessageActionBar extends React.PureComponent {
249265
const editStatus = mxEvent.replacingEvent() && mxEvent.replacingEvent().status;
250266
const redactStatus = mxEvent.localRedactionEvent() && mxEvent.localRedactionEvent().status;
251267
const allowCancel = canCancel(mxEvent.status) || canCancel(editStatus) || canCancel(redactStatus);
252-
const isFailed = [mxEvent.status, editStatus, redactStatus].includes("not_sent");
268+
const isFailed = [mxEvent.status, editStatus, redactStatus].includes(EventStatus.NOT_SENT);
253269
if (allowCancel && isFailed) {
254270
// The resend button needs to appear ahead of the edit button, so insert to the
255271
// start of the opts

0 commit comments

Comments
 (0)