You've already forked matrix-react-sdk
mirror of
https://github.com/matrix-org/matrix-react-sdk.git
synced 2025-12-07 03:42:20 +03:00
Apply prettier formatting
This commit is contained in:
@@ -16,28 +16,28 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { ReactElement, useCallback, useContext, useEffect } from 'react';
|
||||
import { EventStatus, MatrixEvent, MatrixEventEvent } from 'matrix-js-sdk/src/models/event';
|
||||
import classNames from 'classnames';
|
||||
import { MsgType, RelationType } from 'matrix-js-sdk/src/@types/event';
|
||||
import { Thread } from 'matrix-js-sdk/src/models/thread';
|
||||
import { M_BEACON_INFO } from 'matrix-js-sdk/src/@types/beacon';
|
||||
import React, { ReactElement, useCallback, useContext, useEffect } from "react";
|
||||
import { EventStatus, MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/models/event";
|
||||
import classNames from "classnames";
|
||||
import { MsgType, RelationType } from "matrix-js-sdk/src/@types/event";
|
||||
import { Thread } from "matrix-js-sdk/src/models/thread";
|
||||
import { M_BEACON_INFO } from "matrix-js-sdk/src/@types/beacon";
|
||||
|
||||
import { Icon as ContextMenuIcon } from '../../../../res/img/element-icons/context-menu.svg';
|
||||
import { Icon as EditIcon } from '../../../../res/img/element-icons/room/message-bar/edit.svg';
|
||||
import { Icon as EmojiIcon } from '../../../../res/img/element-icons/room/message-bar/emoji.svg';
|
||||
import { Icon as ResendIcon } from '../../../../res/img/element-icons/retry.svg';
|
||||
import { Icon as ThreadIcon } from '../../../../res/img/element-icons/message/thread.svg';
|
||||
import { Icon as TrashcanIcon } from '../../../../res/img/element-icons/trashcan.svg';
|
||||
import { Icon as StarIcon } from '../../../../res/img/element-icons/room/message-bar/star.svg';
|
||||
import { Icon as ReplyIcon } from '../../../../res/img/element-icons/room/message-bar/reply.svg';
|
||||
import { Icon as ExpandMessageIcon } from '../../../../res/img/element-icons/expand-message.svg';
|
||||
import { Icon as CollapseMessageIcon } from '../../../../res/img/element-icons/collapse-message.svg';
|
||||
import type { Relations } from 'matrix-js-sdk/src/models/relations';
|
||||
import { _t } from '../../../languageHandler';
|
||||
import dis, { defaultDispatcher } from '../../../dispatcher/dispatcher';
|
||||
import ContextMenu, { aboveLeftOf, ContextMenuTooltipButton, useContextMenu } from '../../structures/ContextMenu';
|
||||
import { isContentActionable, canEditContent, editEvent, canCancel } from '../../../utils/EventUtils';
|
||||
import { Icon as ContextMenuIcon } from "../../../../res/img/element-icons/context-menu.svg";
|
||||
import { Icon as EditIcon } from "../../../../res/img/element-icons/room/message-bar/edit.svg";
|
||||
import { Icon as EmojiIcon } from "../../../../res/img/element-icons/room/message-bar/emoji.svg";
|
||||
import { Icon as ResendIcon } from "../../../../res/img/element-icons/retry.svg";
|
||||
import { Icon as ThreadIcon } from "../../../../res/img/element-icons/message/thread.svg";
|
||||
import { Icon as TrashcanIcon } from "../../../../res/img/element-icons/trashcan.svg";
|
||||
import { Icon as StarIcon } from "../../../../res/img/element-icons/room/message-bar/star.svg";
|
||||
import { Icon as ReplyIcon } from "../../../../res/img/element-icons/room/message-bar/reply.svg";
|
||||
import { Icon as ExpandMessageIcon } from "../../../../res/img/element-icons/expand-message.svg";
|
||||
import { Icon as CollapseMessageIcon } from "../../../../res/img/element-icons/collapse-message.svg";
|
||||
import type { Relations } from "matrix-js-sdk/src/models/relations";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import dis, { defaultDispatcher } from "../../../dispatcher/dispatcher";
|
||||
import ContextMenu, { aboveLeftOf, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu";
|
||||
import { isContentActionable, canEditContent, editEvent, canCancel } from "../../../utils/EventUtils";
|
||||
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
||||
import Toolbar from "../../../accessibility/Toolbar";
|
||||
import { RovingAccessibleTooltipButton, useRovingTabIndex } from "../../../accessibility/RovingTabIndex";
|
||||
@@ -46,20 +46,20 @@ import Resend from "../../../Resend";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import { MediaEventHelper } from "../../../utils/MediaEventHelper";
|
||||
import DownloadActionButton from "./DownloadActionButton";
|
||||
import SettingsStore from '../../../settings/SettingsStore';
|
||||
import { RoomPermalinkCreator } from '../../../utils/permalinks/Permalinks';
|
||||
import ReplyChain from '../elements/ReplyChain';
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
|
||||
import ReplyChain from "../elements/ReplyChain";
|
||||
import ReactionPicker from "../emojipicker/ReactionPicker";
|
||||
import { CardContext } from '../right_panel/context';
|
||||
import { shouldDisplayReply } from '../../../utils/Reply';
|
||||
import { CardContext } from "../right_panel/context";
|
||||
import { shouldDisplayReply } from "../../../utils/Reply";
|
||||
import { Key } from "../../../Keyboard";
|
||||
import { ALTERNATE_KEY_NAME } from "../../../accessibility/KeyboardShortcuts";
|
||||
import { UserTab } from '../dialogs/UserTab';
|
||||
import { Action } from '../../../dispatcher/actions';
|
||||
import { UserTab } from "../dialogs/UserTab";
|
||||
import { Action } from "../../../dispatcher/actions";
|
||||
import SdkConfig from "../../../SdkConfig";
|
||||
import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload";
|
||||
import useFavouriteMessages from '../../../hooks/useFavouriteMessages';
|
||||
import { GetRelationsForEvent } from '../rooms/EventTile';
|
||||
import useFavouriteMessages from "../../../hooks/useFavouriteMessages";
|
||||
import { GetRelationsForEvent } from "../rooms/EventTile";
|
||||
|
||||
interface IOptionsButtonProps {
|
||||
mxEvent: MatrixEvent;
|
||||
@@ -85,16 +85,19 @@ const OptionsButton: React.FC<IOptionsButtonProps> = ({
|
||||
onFocusChange(menuDisplayed);
|
||||
}, [onFocusChange, menuDisplayed]);
|
||||
|
||||
const onOptionsClick = useCallback((e: React.MouseEvent): void => {
|
||||
// Don't open the regular browser or our context menu on right-click
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
openMenu();
|
||||
// when the context menu is opened directly, e.g. via mouse click, the onFocus handler which tracks
|
||||
// the element that is currently focused is skipped. So we want to call onFocus manually to keep the
|
||||
// position in the page even when someone is clicking around.
|
||||
onFocus();
|
||||
}, [openMenu, onFocus]);
|
||||
const onOptionsClick = useCallback(
|
||||
(e: React.MouseEvent): void => {
|
||||
// Don't open the regular browser or our context menu on right-click
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
openMenu();
|
||||
// when the context menu is opened directly, e.g. via mouse click, the onFocus handler which tracks
|
||||
// the element that is currently focused is skipped. So we want to call onFocus manually to keep the
|
||||
// position in the page even when someone is clicking around.
|
||||
onFocus();
|
||||
},
|
||||
[openMenu, onFocus],
|
||||
);
|
||||
|
||||
let contextMenu: ReactElement | null;
|
||||
if (menuDisplayed) {
|
||||
@@ -102,32 +105,36 @@ const OptionsButton: React.FC<IOptionsButtonProps> = ({
|
||||
const replyChain = getReplyChain && getReplyChain();
|
||||
|
||||
const buttonRect = button.current.getBoundingClientRect();
|
||||
contextMenu = <MessageContextMenu
|
||||
{...aboveLeftOf(buttonRect)}
|
||||
mxEvent={mxEvent}
|
||||
permalinkCreator={permalinkCreator}
|
||||
eventTileOps={tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined}
|
||||
collapseReplyChain={replyChain && replyChain.canCollapse() ? replyChain.collapse : undefined}
|
||||
onFinished={closeMenu}
|
||||
getRelationsForEvent={getRelationsForEvent}
|
||||
/>;
|
||||
contextMenu = (
|
||||
<MessageContextMenu
|
||||
{...aboveLeftOf(buttonRect)}
|
||||
mxEvent={mxEvent}
|
||||
permalinkCreator={permalinkCreator}
|
||||
eventTileOps={tile && tile.getEventTileOps ? tile.getEventTileOps() : undefined}
|
||||
collapseReplyChain={replyChain && replyChain.canCollapse() ? replyChain.collapse : undefined}
|
||||
onFinished={closeMenu}
|
||||
getRelationsForEvent={getRelationsForEvent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <React.Fragment>
|
||||
<ContextMenuTooltipButton
|
||||
className="mx_MessageActionBar_iconButton mx_MessageActionBar_optionsButton"
|
||||
title={_t("Options")}
|
||||
onClick={onOptionsClick}
|
||||
onContextMenu={onOptionsClick}
|
||||
isExpanded={menuDisplayed}
|
||||
inputRef={button}
|
||||
onFocus={onFocus}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
>
|
||||
<ContextMenuIcon />
|
||||
</ContextMenuTooltipButton>
|
||||
{ contextMenu }
|
||||
</React.Fragment>;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ContextMenuTooltipButton
|
||||
className="mx_MessageActionBar_iconButton mx_MessageActionBar_optionsButton"
|
||||
title={_t("Options")}
|
||||
onClick={onOptionsClick}
|
||||
onContextMenu={onOptionsClick}
|
||||
isExpanded={menuDisplayed}
|
||||
inputRef={button}
|
||||
onFocus={onFocus}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
>
|
||||
<ContextMenuIcon />
|
||||
</ContextMenuTooltipButton>
|
||||
{contextMenu}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
interface IReactButtonProps {
|
||||
@@ -146,39 +153,46 @@ const ReactButton: React.FC<IReactButtonProps> = ({ mxEvent, reactions, onFocusC
|
||||
let contextMenu;
|
||||
if (menuDisplayed) {
|
||||
const buttonRect = button.current.getBoundingClientRect();
|
||||
contextMenu = <ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu} managed={false}>
|
||||
<ReactionPicker mxEvent={mxEvent} reactions={reactions} onFinished={closeMenu} />
|
||||
</ContextMenu>;
|
||||
contextMenu = (
|
||||
<ContextMenu {...aboveLeftOf(buttonRect)} onFinished={closeMenu} managed={false}>
|
||||
<ReactionPicker mxEvent={mxEvent} reactions={reactions} onFinished={closeMenu} />
|
||||
</ContextMenu>
|
||||
);
|
||||
}
|
||||
|
||||
const onClick = useCallback((e: React.MouseEvent) => {
|
||||
// Don't open the regular browser or our context menu on right-click
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const onClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
// Don't open the regular browser or our context menu on right-click
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
openMenu();
|
||||
// when the context menu is opened directly, e.g. via mouse click, the onFocus handler which tracks
|
||||
// the element that is currently focused is skipped. So we want to call onFocus manually to keep the
|
||||
// position in the page even when someone is clicking around.
|
||||
onFocus();
|
||||
}, [openMenu, onFocus]);
|
||||
openMenu();
|
||||
// when the context menu is opened directly, e.g. via mouse click, the onFocus handler which tracks
|
||||
// the element that is currently focused is skipped. So we want to call onFocus manually to keep the
|
||||
// position in the page even when someone is clicking around.
|
||||
onFocus();
|
||||
},
|
||||
[openMenu, onFocus],
|
||||
);
|
||||
|
||||
return <React.Fragment>
|
||||
<ContextMenuTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
title={_t("React")}
|
||||
onClick={onClick}
|
||||
onContextMenu={onClick}
|
||||
isExpanded={menuDisplayed}
|
||||
inputRef={button}
|
||||
onFocus={onFocus}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
>
|
||||
<EmojiIcon />
|
||||
</ContextMenuTooltipButton>
|
||||
return (
|
||||
<React.Fragment>
|
||||
<ContextMenuTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
title={_t("React")}
|
||||
onClick={onClick}
|
||||
onContextMenu={onClick}
|
||||
isExpanded={menuDisplayed}
|
||||
inputRef={button}
|
||||
onFocus={onFocus}
|
||||
tabIndex={isActive ? 0 : -1}
|
||||
>
|
||||
<EmojiIcon />
|
||||
</ContextMenuTooltipButton>
|
||||
|
||||
{ contextMenu }
|
||||
</React.Fragment>;
|
||||
{contextMenu}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
interface IReplyInThreadButton {
|
||||
@@ -230,37 +244,38 @@ const ReplyInThreadButton = ({ mxEvent }: IReplyInThreadButton) => {
|
||||
}
|
||||
};
|
||||
|
||||
return <RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton mx_MessageActionBar_threadButton"
|
||||
disabled={hasARelation}
|
||||
tooltip={<>
|
||||
<div className="mx_Tooltip_title">
|
||||
{ !hasARelation
|
||||
return (
|
||||
<RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton mx_MessageActionBar_threadButton"
|
||||
disabled={hasARelation}
|
||||
tooltip={
|
||||
<>
|
||||
<div className="mx_Tooltip_title">
|
||||
{!hasARelation
|
||||
? _t("Reply in thread")
|
||||
: _t("Can't create a thread from an event with an existing relation")}
|
||||
</div>
|
||||
{!hasARelation && (
|
||||
<div className="mx_Tooltip_sub">
|
||||
{SettingsStore.getValue("feature_thread")
|
||||
? _t("Beta feature")
|
||||
: _t("Beta feature. Click to learn more.")}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
title={
|
||||
!hasARelation
|
||||
? _t("Reply in thread")
|
||||
: _t("Can't create a thread from an event with an existing relation") }
|
||||
</div>
|
||||
{ !hasARelation && (
|
||||
<div className="mx_Tooltip_sub">
|
||||
{ SettingsStore.getValue("feature_thread")
|
||||
? _t("Beta feature")
|
||||
: _t("Beta feature. Click to learn more.")
|
||||
}
|
||||
</div>
|
||||
) }
|
||||
</>}
|
||||
|
||||
title={!hasARelation
|
||||
? _t("Reply in thread")
|
||||
: _t("Can't create a thread from an event with an existing relation")}
|
||||
|
||||
onClick={onClick}
|
||||
onContextMenu={onClick}
|
||||
>
|
||||
<ThreadIcon />
|
||||
{ firstTimeSeeingThreads && !threadsEnabled && (
|
||||
<div className="mx_Indicator" />
|
||||
) }
|
||||
</RovingAccessibleTooltipButton>;
|
||||
: _t("Can't create a thread from an event with an existing relation")
|
||||
}
|
||||
onClick={onClick}
|
||||
onContextMenu={onClick}
|
||||
>
|
||||
<ThreadIcon />
|
||||
{firstTimeSeeingThreads && !threadsEnabled && <div className="mx_Indicator" />}
|
||||
</RovingAccessibleTooltipButton>
|
||||
);
|
||||
};
|
||||
|
||||
interface IFavouriteButtonProp {
|
||||
@@ -272,26 +287,31 @@ const FavouriteButton = ({ mxEvent }: IFavouriteButtonProp) => {
|
||||
|
||||
const eventId = mxEvent.getId();
|
||||
const classes = classNames("mx_MessageActionBar_iconButton mx_MessageActionBar_favouriteButton", {
|
||||
'mx_MessageActionBar_favouriteButton_fillstar': isFavourite(eventId),
|
||||
mx_MessageActionBar_favouriteButton_fillstar: isFavourite(eventId),
|
||||
});
|
||||
|
||||
const onClick = useCallback((e: React.MouseEvent) => {
|
||||
// Don't open the regular browser or our context menu on right-click
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const onClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
// Don't open the regular browser or our context menu on right-click
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
toggleFavourite(eventId);
|
||||
}, [toggleFavourite, eventId]);
|
||||
toggleFavourite(eventId);
|
||||
},
|
||||
[toggleFavourite, eventId],
|
||||
);
|
||||
|
||||
return <RovingAccessibleTooltipButton
|
||||
className={classes}
|
||||
title={_t("Favourite")}
|
||||
onClick={onClick}
|
||||
onContextMenu={onClick}
|
||||
data-testid={eventId}
|
||||
>
|
||||
<StarIcon />
|
||||
</RovingAccessibleTooltipButton>;
|
||||
return (
|
||||
<RovingAccessibleTooltipButton
|
||||
className={classes}
|
||||
title={_t("Favourite")}
|
||||
onClick={onClick}
|
||||
onContextMenu={onClick}
|
||||
data-testid={eventId}
|
||||
>
|
||||
<StarIcon />
|
||||
</RovingAccessibleTooltipButton>
|
||||
);
|
||||
};
|
||||
|
||||
interface IMessageActionBarProps {
|
||||
@@ -356,7 +376,7 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||
e.stopPropagation();
|
||||
|
||||
dis.dispatch({
|
||||
action: 'reply_to_event',
|
||||
action: "reply_to_event",
|
||||
event: this.props.mxEvent,
|
||||
context: this.context.timelineRenderingType,
|
||||
});
|
||||
@@ -370,9 +390,7 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||
editEvent(this.props.mxEvent, this.context.timelineRenderingType, this.props.getRelationsForEvent);
|
||||
};
|
||||
|
||||
private readonly forbiddenThreadHeadMsgType = [
|
||||
MsgType.KeyVerificationRequest,
|
||||
];
|
||||
private readonly forbiddenThreadHeadMsgType = [MsgType.KeyVerificationRequest];
|
||||
|
||||
private get showReplyInThreadAction(): boolean {
|
||||
if (!SettingsStore.getValue("feature_thread") && !Thread.hasServerSideSupport) {
|
||||
@@ -380,7 +398,8 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!SettingsStore.getBetaInfo("feature_thread") &&
|
||||
if (
|
||||
!SettingsStore.getBetaInfo("feature_thread") &&
|
||||
!SettingsStore.getValue("feature_thread") &&
|
||||
!SdkConfig.get("show_labs_settings")
|
||||
) {
|
||||
@@ -391,15 +410,13 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||
|
||||
const inNotThreadTimeline = this.context.timelineRenderingType !== TimelineRenderingType.Thread;
|
||||
|
||||
const isAllowedMessageType = (
|
||||
!this.forbiddenThreadHeadMsgType.includes(
|
||||
this.props.mxEvent.getContent().msgtype as MsgType) &&
|
||||
const isAllowedMessageType =
|
||||
!this.forbiddenThreadHeadMsgType.includes(this.props.mxEvent.getContent().msgtype as MsgType) &&
|
||||
/** forbid threads from live location shares
|
||||
* until cross-platform support
|
||||
* (PSF-1041)
|
||||
*/
|
||||
!M_BEACON_INFO.matches(this.props.mxEvent.getType())
|
||||
);
|
||||
!M_BEACON_INFO.matches(this.props.mxEvent.getType());
|
||||
|
||||
return inNotThreadTimeline && isAllowedMessageType;
|
||||
}
|
||||
@@ -446,26 +463,30 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||
public render(): JSX.Element {
|
||||
const toolbarOpts = [];
|
||||
if (canEditContent(this.props.mxEvent)) {
|
||||
toolbarOpts.push(<RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
title={_t("Edit")}
|
||||
onClick={this.onEditClick}
|
||||
onContextMenu={this.onEditClick}
|
||||
key="edit"
|
||||
>
|
||||
<EditIcon />
|
||||
</RovingAccessibleTooltipButton>);
|
||||
toolbarOpts.push(
|
||||
<RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
title={_t("Edit")}
|
||||
onClick={this.onEditClick}
|
||||
onContextMenu={this.onEditClick}
|
||||
key="edit"
|
||||
>
|
||||
<EditIcon />
|
||||
</RovingAccessibleTooltipButton>,
|
||||
);
|
||||
}
|
||||
|
||||
const cancelSendingButton = <RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
title={_t("Delete")}
|
||||
onClick={this.onCancelClick}
|
||||
onContextMenu={this.onCancelClick}
|
||||
key="cancel"
|
||||
>
|
||||
<TrashcanIcon />
|
||||
</RovingAccessibleTooltipButton>;
|
||||
const cancelSendingButton = (
|
||||
<RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
title={_t("Delete")}
|
||||
onClick={this.onCancelClick}
|
||||
onContextMenu={this.onCancelClick}
|
||||
key="cancel"
|
||||
>
|
||||
<TrashcanIcon />
|
||||
</RovingAccessibleTooltipButton>
|
||||
);
|
||||
|
||||
const threadTooltipButton = <ReplyInThreadButton mxEvent={this.props.mxEvent} key="reply_thread" />;
|
||||
|
||||
@@ -478,15 +499,19 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||
if (allowCancel && isFailed) {
|
||||
// The resend button needs to appear ahead of the edit button, so insert to the
|
||||
// start of the opts
|
||||
toolbarOpts.splice(0, 0, <RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
title={_t("Retry")}
|
||||
onClick={this.onResendClick}
|
||||
onContextMenu={this.onResendClick}
|
||||
key="resend"
|
||||
>
|
||||
<ResendIcon />
|
||||
</RovingAccessibleTooltipButton>);
|
||||
toolbarOpts.splice(
|
||||
0,
|
||||
0,
|
||||
<RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
title={_t("Retry")}
|
||||
onClick={this.onResendClick}
|
||||
onContextMenu={this.onResendClick}
|
||||
key="resend"
|
||||
>
|
||||
<ResendIcon />
|
||||
</RovingAccessibleTooltipButton>,
|
||||
);
|
||||
|
||||
// The delete button should appear last, so we can just drop it at the end
|
||||
toolbarOpts.push(cancelSendingButton);
|
||||
@@ -500,7 +525,9 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||
if (this.showReplyInThreadAction) {
|
||||
toolbarOpts.splice(0, 0, threadTooltipButton);
|
||||
}
|
||||
toolbarOpts.splice(0, 0, (
|
||||
toolbarOpts.splice(
|
||||
0,
|
||||
0,
|
||||
<RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
title={_t("Reply")}
|
||||
@@ -509,32 +536,39 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||
key="reply"
|
||||
>
|
||||
<ReplyIcon />
|
||||
</RovingAccessibleTooltipButton>
|
||||
));
|
||||
</RovingAccessibleTooltipButton>,
|
||||
);
|
||||
}
|
||||
if (this.context.canReact) {
|
||||
toolbarOpts.splice(0, 0, <ReactButton
|
||||
mxEvent={this.props.mxEvent}
|
||||
reactions={this.props.reactions}
|
||||
onFocusChange={this.onFocusChange}
|
||||
key="react"
|
||||
/>);
|
||||
toolbarOpts.splice(
|
||||
0,
|
||||
0,
|
||||
<ReactButton
|
||||
mxEvent={this.props.mxEvent}
|
||||
reactions={this.props.reactions}
|
||||
onFocusChange={this.onFocusChange}
|
||||
key="react"
|
||||
/>,
|
||||
);
|
||||
}
|
||||
if (SettingsStore.getValue("feature_favourite_messages")) {
|
||||
toolbarOpts.splice(-1, 0, (
|
||||
<FavouriteButton key="favourite" mxEvent={this.props.mxEvent} />
|
||||
));
|
||||
toolbarOpts.splice(-1, 0, <FavouriteButton key="favourite" mxEvent={this.props.mxEvent} />);
|
||||
}
|
||||
|
||||
// XXX: Assuming that the underlying tile will be a media event if it is eligible media.
|
||||
if (MediaEventHelper.isEligible(this.props.mxEvent)) {
|
||||
toolbarOpts.splice(0, 0, <DownloadActionButton
|
||||
mxEvent={this.props.mxEvent}
|
||||
mediaEventHelperGet={() => this.props.getTile?.().getMediaHelper?.()}
|
||||
key="download"
|
||||
/>);
|
||||
toolbarOpts.splice(
|
||||
0,
|
||||
0,
|
||||
<DownloadActionButton
|
||||
mxEvent={this.props.mxEvent}
|
||||
mediaEventHelperGet={() => this.props.getTile?.().getMediaHelper?.()}
|
||||
key="download"
|
||||
/>,
|
||||
);
|
||||
}
|
||||
} else if (SettingsStore.getValue("feature_thread") &&
|
||||
} else if (
|
||||
SettingsStore.getValue("feature_thread") &&
|
||||
// Show thread icon even for deleted messages, but only within main timeline
|
||||
this.context.timelineRenderingType === TimelineRenderingType.Room &&
|
||||
this.props.mxEvent.getThread()
|
||||
@@ -548,46 +582,49 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
|
||||
|
||||
if (this.props.isQuoteExpanded !== undefined && shouldDisplayReply(this.props.mxEvent)) {
|
||||
const expandClassName = classNames({
|
||||
'mx_MessageActionBar_iconButton': true,
|
||||
'mx_MessageActionBar_expandCollapseMessageButton': true,
|
||||
mx_MessageActionBar_iconButton: true,
|
||||
mx_MessageActionBar_expandCollapseMessageButton: true,
|
||||
});
|
||||
const tooltip = <>
|
||||
<div className="mx_Tooltip_title">
|
||||
{ this.props.isQuoteExpanded ? _t("Collapse quotes") : _t("Expand quotes") }
|
||||
</div>
|
||||
<div className="mx_Tooltip_sub">
|
||||
{ _t(ALTERNATE_KEY_NAME[Key.SHIFT]) + " + " + _t("Click") }
|
||||
</div>
|
||||
</>;
|
||||
toolbarOpts.push(<RovingAccessibleTooltipButton
|
||||
className={expandClassName}
|
||||
title={this.props.isQuoteExpanded ? _t("Collapse quotes") : _t("Expand quotes")}
|
||||
tooltip={tooltip}
|
||||
onClick={this.props.toggleThreadExpanded}
|
||||
key="expand"
|
||||
>
|
||||
{ this.props.isQuoteExpanded
|
||||
? <CollapseMessageIcon />
|
||||
: <ExpandMessageIcon />
|
||||
}
|
||||
</RovingAccessibleTooltipButton>);
|
||||
const tooltip = (
|
||||
<>
|
||||
<div className="mx_Tooltip_title">
|
||||
{this.props.isQuoteExpanded ? _t("Collapse quotes") : _t("Expand quotes")}
|
||||
</div>
|
||||
<div className="mx_Tooltip_sub">{_t(ALTERNATE_KEY_NAME[Key.SHIFT]) + " + " + _t("Click")}</div>
|
||||
</>
|
||||
);
|
||||
toolbarOpts.push(
|
||||
<RovingAccessibleTooltipButton
|
||||
className={expandClassName}
|
||||
title={this.props.isQuoteExpanded ? _t("Collapse quotes") : _t("Expand quotes")}
|
||||
tooltip={tooltip}
|
||||
onClick={this.props.toggleThreadExpanded}
|
||||
key="expand"
|
||||
>
|
||||
{this.props.isQuoteExpanded ? <CollapseMessageIcon /> : <ExpandMessageIcon />}
|
||||
</RovingAccessibleTooltipButton>,
|
||||
);
|
||||
}
|
||||
|
||||
// The menu button should be last, so dump it there.
|
||||
toolbarOpts.push(<OptionsButton
|
||||
mxEvent={this.props.mxEvent}
|
||||
getReplyChain={this.props.getReplyChain}
|
||||
getTile={this.props.getTile}
|
||||
permalinkCreator={this.props.permalinkCreator}
|
||||
onFocusChange={this.onFocusChange}
|
||||
key="menu"
|
||||
getRelationsForEvent={this.props.getRelationsForEvent}
|
||||
/>);
|
||||
toolbarOpts.push(
|
||||
<OptionsButton
|
||||
mxEvent={this.props.mxEvent}
|
||||
getReplyChain={this.props.getReplyChain}
|
||||
getTile={this.props.getTile}
|
||||
permalinkCreator={this.props.permalinkCreator}
|
||||
onFocusChange={this.onFocusChange}
|
||||
key="menu"
|
||||
getRelationsForEvent={this.props.getRelationsForEvent}
|
||||
/>,
|
||||
);
|
||||
}
|
||||
|
||||
// aria-live=off to not have this read out automatically as navigating around timeline, gets repetitive.
|
||||
return <Toolbar className="mx_MessageActionBar" aria-label={_t("Message Actions")} aria-live="off">
|
||||
{ toolbarOpts }
|
||||
</Toolbar>;
|
||||
return (
|
||||
<Toolbar className="mx_MessageActionBar" aria-label={_t("Message Actions")} aria-live="off">
|
||||
{toolbarOpts}
|
||||
</Toolbar>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user