Unify notifications panel event design (#9754)
This commit is contained in:
parent
6585fb1f55
commit
bef8e077f6
9 changed files with 191 additions and 219 deletions
|
@ -29,8 +29,6 @@ import { CryptoEvent } from "matrix-js-sdk/src/crypto";
|
|||
import { UserTrustLevel } from "matrix-js-sdk/src/crypto/CrossSigning";
|
||||
import { Feature, ServerSupport } from "matrix-js-sdk/src/feature";
|
||||
|
||||
import { Icon as LinkIcon } from "../../../../res/img/element-icons/link.svg";
|
||||
import { Icon as ViewInRoomIcon } from "../../../../res/img/element-icons/view-in-room.svg";
|
||||
import ReplyChain from "../elements/ReplyChain";
|
||||
import { _t } from "../../../languageHandler";
|
||||
import dis from "../../../dispatcher/dispatcher";
|
||||
|
@ -63,8 +61,6 @@ import SettingsStore from "../../../settings/SettingsStore";
|
|||
import { MessagePreviewStore } from "../../../stores/room-list/MessagePreviewStore";
|
||||
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
|
||||
import { MediaEventHelper } from "../../../utils/MediaEventHelper";
|
||||
import Toolbar from "../../../accessibility/Toolbar";
|
||||
import { RovingAccessibleTooltipButton } from "../../../accessibility/roving/RovingAccessibleTooltipButton";
|
||||
import { ThreadNotificationState } from "../../../stores/notifications/ThreadNotificationState";
|
||||
import { RoomNotificationStateStore } from "../../../stores/notifications/RoomNotificationStateStore";
|
||||
import { NotificationStateEvents } from "../../../stores/notifications/NotificationState";
|
||||
|
@ -85,6 +81,7 @@ import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayloa
|
|||
import { isLocalRoom } from "../../../utils/localRoom/isLocalRoom";
|
||||
import { ElementCall } from "../../../models/Call";
|
||||
import { UnreadNotificationBadge } from "./NotificationBadge/UnreadNotificationBadge";
|
||||
import { EventTileThreadToolbar } from "./EventTile/EventTileThreadToolbar";
|
||||
|
||||
export type GetRelationsForEvent = (
|
||||
eventId: string,
|
||||
|
@ -972,6 +969,8 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
isContinuation = false;
|
||||
}
|
||||
|
||||
const isRenderingNotification = this.context.timelineRenderingType === TimelineRenderingType.Notification;
|
||||
|
||||
const isEditing = !!this.props.editState;
|
||||
const classes = classNames({
|
||||
mx_EventTile_bubbleContainer: isBubbleMessage,
|
||||
|
@ -996,7 +995,8 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
mx_EventTile_bad: isEncryptionFailure,
|
||||
mx_EventTile_emote: msgtype === MsgType.Emote,
|
||||
mx_EventTile_noSender: this.props.hideSender,
|
||||
mx_EventTile_clamp: this.context.timelineRenderingType === TimelineRenderingType.ThreadsList,
|
||||
mx_EventTile_clamp:
|
||||
this.context.timelineRenderingType === TimelineRenderingType.ThreadsList || isRenderingNotification,
|
||||
mx_EventTile_noBubble: noBubbleEvent,
|
||||
});
|
||||
|
||||
|
@ -1012,12 +1012,12 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
// Local echos have a send "status".
|
||||
const scrollToken = this.props.mxEvent.status ? undefined : this.props.mxEvent.getId();
|
||||
|
||||
let avatar: JSX.Element;
|
||||
let sender: JSX.Element;
|
||||
let avatar: JSX.Element | null = null;
|
||||
let sender: JSX.Element | null = null;
|
||||
let avatarSize: number;
|
||||
let needsSenderProfile: boolean;
|
||||
|
||||
if (this.context.timelineRenderingType === TimelineRenderingType.Notification) {
|
||||
if (isRenderingNotification) {
|
||||
avatarSize = 24;
|
||||
needsSenderProfile = true;
|
||||
} else if (isInfoMessage) {
|
||||
|
@ -1061,7 +1061,9 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
member = this.props.mxEvent.sender;
|
||||
}
|
||||
// In the ThreadsList view we use the entire EventTile as a click target to open the thread instead
|
||||
const viewUserOnClick = this.context.timelineRenderingType !== TimelineRenderingType.ThreadsList;
|
||||
const viewUserOnClick = ![TimelineRenderingType.ThreadsList, TimelineRenderingType.Notification].includes(
|
||||
this.context.timelineRenderingType,
|
||||
);
|
||||
avatar = (
|
||||
<div className="mx_EventTile_avatar">
|
||||
<MemberAvatar
|
||||
|
@ -1202,57 +1204,6 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
const isOwnEvent = this.props.mxEvent?.getSender() === MatrixClientPeg.get().getUserId();
|
||||
|
||||
switch (this.context.timelineRenderingType) {
|
||||
case TimelineRenderingType.Notification: {
|
||||
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
||||
return React.createElement(
|
||||
this.props.as || "li",
|
||||
{
|
||||
"className": classes,
|
||||
"aria-live": ariaLive,
|
||||
"aria-atomic": true,
|
||||
"data-scroll-tokens": scrollToken,
|
||||
},
|
||||
[
|
||||
<div className="mx_EventTile_roomName" key="mx_EventTile_roomName">
|
||||
<RoomAvatar room={room} width={28} height={28} />
|
||||
<a href={permalink} onClick={this.onPermalinkClicked}>
|
||||
{room ? room.name : ""}
|
||||
</a>
|
||||
</div>,
|
||||
<div className="mx_EventTile_senderDetails" key="mx_EventTile_senderDetails">
|
||||
{avatar}
|
||||
<a
|
||||
href={permalink}
|
||||
onClick={this.onPermalinkClicked}
|
||||
onContextMenu={this.onTimestampContextMenu}
|
||||
>
|
||||
{sender}
|
||||
{timestamp}
|
||||
</a>
|
||||
</div>,
|
||||
<div className={lineClasses} key="mx_EventTile_line" onContextMenu={this.onContextMenu}>
|
||||
{this.renderContextMenu()}
|
||||
{renderTile(
|
||||
TimelineRenderingType.Notification,
|
||||
{
|
||||
...this.props,
|
||||
|
||||
// overrides
|
||||
ref: this.tile,
|
||||
isSeeingThroughMessageHiddenForModeration,
|
||||
|
||||
// appease TS
|
||||
highlights: this.props.highlights,
|
||||
highlightLink: this.props.highlightLink,
|
||||
onHeightChanged: this.props.onHeightChanged,
|
||||
permalinkCreator: this.props.permalinkCreator,
|
||||
},
|
||||
this.context.showHiddenEvents,
|
||||
)}
|
||||
</div>,
|
||||
],
|
||||
);
|
||||
}
|
||||
case TimelineRenderingType.Thread: {
|
||||
return React.createElement(
|
||||
this.props.as || "li",
|
||||
|
@ -1289,8 +1240,8 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
// appease TS
|
||||
highlights: this.props.highlights,
|
||||
highlightLink: this.props.highlightLink,
|
||||
onHeightChanged: this.props.onHeightChanged,
|
||||
permalinkCreator: this.props.permalinkCreator,
|
||||
onHeightChanged: () => this.props.onHeightChanged,
|
||||
permalinkCreator: this.props.permalinkCreator!,
|
||||
},
|
||||
this.context.showHiddenEvents,
|
||||
)}
|
||||
|
@ -1304,6 +1255,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
],
|
||||
);
|
||||
}
|
||||
case TimelineRenderingType.Notification:
|
||||
case TimelineRenderingType.ThreadsList: {
|
||||
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
|
||||
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
|
||||
|
@ -1326,20 +1278,48 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
"onMouseEnter": () => this.setState({ hover: true }),
|
||||
"onMouseLeave": () => this.setState({ hover: false }),
|
||||
"onClick": (ev: MouseEvent) => {
|
||||
dis.dispatch<ShowThreadPayload>({
|
||||
action: Action.ShowThread,
|
||||
rootEvent: this.props.mxEvent,
|
||||
push: true,
|
||||
});
|
||||
const target = ev.currentTarget as HTMLElement;
|
||||
const index = Array.from(target.parentElement.children).indexOf(target);
|
||||
PosthogTrackers.trackInteraction("WebThreadsPanelThreadItem", ev, index);
|
||||
let index = -1;
|
||||
if (target.parentElement) index = Array.from(target.parentElement.children).indexOf(target);
|
||||
switch (this.context.timelineRenderingType) {
|
||||
case TimelineRenderingType.Notification:
|
||||
this.viewInRoom(ev);
|
||||
break;
|
||||
case TimelineRenderingType.ThreadsList:
|
||||
dis.dispatch<ShowThreadPayload>({
|
||||
action: Action.ShowThread,
|
||||
rootEvent: this.props.mxEvent,
|
||||
push: true,
|
||||
});
|
||||
PosthogTrackers.trackInteraction("WebThreadsPanelThreadItem", ev, index ?? -1);
|
||||
break;
|
||||
}
|
||||
},
|
||||
},
|
||||
<>
|
||||
{sender}
|
||||
{avatar}
|
||||
{timestamp}
|
||||
<div className="mx_EventTile_details">
|
||||
{sender}
|
||||
{isRenderingNotification && room ? (
|
||||
<span className="mx_EventTile_truncated">
|
||||
{" "}
|
||||
{_t(
|
||||
" in <strong>%(room)s</strong>",
|
||||
{ room: room.name },
|
||||
{ strong: (sub) => <strong>{sub}</strong> },
|
||||
)}
|
||||
</span>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
{timestamp}
|
||||
</div>
|
||||
{isRenderingNotification && room ? (
|
||||
<div className="mx_EventTile_avatar">
|
||||
<RoomAvatar room={room} width={28} height={28} />
|
||||
</div>
|
||||
) : (
|
||||
avatar
|
||||
)}
|
||||
<div className={lineClasses} key="mx_EventTile_line">
|
||||
<div className="mx_EventTile_body">
|
||||
{this.props.mxEvent.isRedacted() ? (
|
||||
|
@ -1350,24 +1330,13 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
|
|||
</div>
|
||||
{this.renderThreadPanelSummary()}
|
||||
</div>
|
||||
<Toolbar className="mx_MessageActionBar" aria-label={_t("Message Actions")} aria-live="off">
|
||||
<RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
onClick={this.viewInRoom}
|
||||
title={_t("View in room")}
|
||||
key="view_in_room"
|
||||
>
|
||||
<ViewInRoomIcon />
|
||||
</RovingAccessibleTooltipButton>
|
||||
<RovingAccessibleTooltipButton
|
||||
className="mx_MessageActionBar_iconButton"
|
||||
onClick={this.copyLinkToThread}
|
||||
title={_t("Copy link to thread")}
|
||||
key="copy_link_to_thread"
|
||||
>
|
||||
<LinkIcon />
|
||||
</RovingAccessibleTooltipButton>
|
||||
</Toolbar>
|
||||
{this.context.timelineRenderingType === TimelineRenderingType.ThreadsList && (
|
||||
<EventTileThreadToolbar
|
||||
viewInRoom={this.viewInRoom}
|
||||
copyLinkToThread={this.copyLinkToThread}
|
||||
/>
|
||||
)}
|
||||
|
||||
{msgOption}
|
||||
<UnreadNotificationBadge room={room} threadId={this.props.mxEvent.getId()} />
|
||||
</>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue