Simplify EventTile structure
Only render MessageTimestamp to the DOM when a tile is hovered
This commit is contained in:
parent
d362321706
commit
171539d42d
2 changed files with 61 additions and 50 deletions
|
@ -645,39 +645,36 @@ export default class MessagePanel extends React.Component {
|
||||||
|
|
||||||
// use txnId as key if available so that we don't remount during sending
|
// use txnId as key if available so that we don't remount during sending
|
||||||
ret.push(
|
ret.push(
|
||||||
<li
|
<TileErrorBoundary key={mxEv.getTxnId() || eventId} mxEvent={mxEv}>
|
||||||
key={mxEv.getTxnId() || eventId}
|
<EventTile
|
||||||
ref={this._collectEventNode.bind(this, eventId)}
|
as="li"
|
||||||
data-scroll-tokens={scrollToken}
|
data-scroll-tokens={scrollToken}
|
||||||
>
|
ref={this._collectEventNode.bind(this, eventId)}
|
||||||
<TileErrorBoundary mxEvent={mxEv}>
|
mxEvent={mxEv}
|
||||||
<EventTile
|
continuation={continuation}
|
||||||
mxEvent={mxEv}
|
isRedacted={mxEv.isRedacted()}
|
||||||
continuation={continuation}
|
replacingEventId={mxEv.replacingEventId()}
|
||||||
isRedacted={mxEv.isRedacted()}
|
editState={isEditing && this.props.editState}
|
||||||
replacingEventId={mxEv.replacingEventId()}
|
onHeightChanged={this._onHeightChanged}
|
||||||
editState={isEditing && this.props.editState}
|
readReceipts={readReceipts}
|
||||||
onHeightChanged={this._onHeightChanged}
|
readReceiptMap={this._readReceiptMap}
|
||||||
readReceipts={readReceipts}
|
showUrlPreview={this.props.showUrlPreview}
|
||||||
readReceiptMap={this._readReceiptMap}
|
checkUnmounting={this._isUnmounting}
|
||||||
showUrlPreview={this.props.showUrlPreview}
|
eventSendStatus={mxEv.getAssociatedStatus()}
|
||||||
checkUnmounting={this._isUnmounting}
|
tileShape={this.props.tileShape}
|
||||||
eventSendStatus={mxEv.getAssociatedStatus()}
|
isTwelveHour={this.props.isTwelveHour}
|
||||||
tileShape={this.props.tileShape}
|
permalinkCreator={this.props.permalinkCreator}
|
||||||
isTwelveHour={this.props.isTwelveHour}
|
last={last}
|
||||||
permalinkCreator={this.props.permalinkCreator}
|
lastInSection={willWantDateSeparator}
|
||||||
last={last}
|
lastSuccessful={isLastSuccessful}
|
||||||
lastInSection={willWantDateSeparator}
|
isSelectedEvent={highlight}
|
||||||
lastSuccessful={isLastSuccessful}
|
getRelationsForEvent={this.props.getRelationsForEvent}
|
||||||
isSelectedEvent={highlight}
|
showReactions={this.props.showReactions}
|
||||||
getRelationsForEvent={this.props.getRelationsForEvent}
|
layout={this.props.layout}
|
||||||
showReactions={this.props.showReactions}
|
enableFlair={this.props.enableFlair}
|
||||||
layout={this.props.layout}
|
showReadReceipts={this.props.showReadReceipts}
|
||||||
enableFlair={this.props.enableFlair}
|
/>
|
||||||
showReadReceipts={this.props.showReadReceipts}
|
</TileErrorBoundary>,
|
||||||
/>
|
|
||||||
</TileErrorBoundary>
|
|
||||||
</li>,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -779,7 +776,7 @@ export default class MessagePanel extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
_collectEventNode = (eventId, node) => {
|
_collectEventNode = (eventId, node) => {
|
||||||
this.eventNodes[eventId] = node;
|
this.eventNodes[eventId] = node?.ref?.current;
|
||||||
}
|
}
|
||||||
|
|
||||||
// once dynamic content in the events load, make the scrollPanel check the
|
// once dynamic content in the events load, make the scrollPanel check the
|
||||||
|
|
|
@ -277,6 +277,9 @@ interface IProps {
|
||||||
|
|
||||||
// Helper to build permalinks for the room
|
// Helper to build permalinks for the room
|
||||||
permalinkCreator?: RoomPermalinkCreator;
|
permalinkCreator?: RoomPermalinkCreator;
|
||||||
|
|
||||||
|
// Symbol of the root node
|
||||||
|
as?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -291,6 +294,8 @@ interface IState {
|
||||||
previouslyRequestedKeys: boolean;
|
previouslyRequestedKeys: boolean;
|
||||||
// The Relations model from the JS SDK for reactions to `mxEvent`
|
// The Relations model from the JS SDK for reactions to `mxEvent`
|
||||||
reactions: Relations;
|
reactions: Relations;
|
||||||
|
|
||||||
|
hover: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@replaceableComponent("views.rooms.EventTile")
|
@replaceableComponent("views.rooms.EventTile")
|
||||||
|
@ -322,6 +327,8 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
previouslyRequestedKeys: false,
|
previouslyRequestedKeys: false,
|
||||||
// The Relations model from the JS SDK for reactions to `mxEvent`
|
// The Relations model from the JS SDK for reactions to `mxEvent`
|
||||||
reactions: this.getReactions(),
|
reactions: this.getReactions(),
|
||||||
|
|
||||||
|
hover: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
// don't do RR animations until we are mounted
|
// don't do RR animations until we are mounted
|
||||||
|
@ -333,6 +340,8 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
// to determine if we've already subscribed and use a combination of other flags to find
|
// to determine if we've already subscribed and use a combination of other flags to find
|
||||||
// out if we should even be subscribed at all.
|
// out if we should even be subscribed at all.
|
||||||
this.isListeningForReceipts = false;
|
this.isListeningForReceipts = false;
|
||||||
|
|
||||||
|
this.ref = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -960,7 +969,7 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
onFocusChange={this.onActionBarFocusChange}
|
onFocusChange={this.onActionBarFocusChange}
|
||||||
/> : undefined;
|
/> : undefined;
|
||||||
|
|
||||||
const timestamp = this.props.mxEvent.getTs() ?
|
const timestamp = this.props.mxEvent.getTs() && this.state.hover ?
|
||||||
<MessageTimestamp showTwelveHour={this.props.isTwelveHour} ts={this.props.mxEvent.getTs()} /> : null;
|
<MessageTimestamp showTwelveHour={this.props.isTwelveHour} ts={this.props.mxEvent.getTs()} /> : null;
|
||||||
|
|
||||||
const keyRequestHelpText =
|
const keyRequestHelpText =
|
||||||
|
@ -1131,11 +1140,20 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
|
|
||||||
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
|
// tab-index=-1 to allow it to be focusable but do not add tab stop for it, primarily for screen readers
|
||||||
return (
|
return (
|
||||||
<div className={classes} tabIndex={-1} aria-live={ariaLive} aria-atomic="true">
|
React.createElement(this.props.as || "div", {
|
||||||
{ ircTimestamp }
|
"ref": this.ref,
|
||||||
{ sender }
|
"className": classes,
|
||||||
{ ircPadlock }
|
"tabIndex": -1,
|
||||||
<div className="mx_EventTile_line">
|
"aria-live": ariaLive,
|
||||||
|
"aria-atomic": "true",
|
||||||
|
"data-scroll-tokens": this.props["data-scroll-tokens"],
|
||||||
|
"onMouseEnter": () => this.setState({ hover: true }),
|
||||||
|
"onMouseLeave": () => this.setState({ hover: false }),
|
||||||
|
}, [
|
||||||
|
ircTimestamp,
|
||||||
|
sender,
|
||||||
|
ircPadlock,
|
||||||
|
<div className="mx_EventTile_line" key="mx_EventTile_line">
|
||||||
{ groupTimestamp }
|
{ groupTimestamp }
|
||||||
{ groupPadlock }
|
{ groupPadlock }
|
||||||
{ thread }
|
{ thread }
|
||||||
|
@ -1152,16 +1170,12 @@ export default class EventTile extends React.Component<IProps, IState> {
|
||||||
{ keyRequestInfo }
|
{ keyRequestInfo }
|
||||||
{ reactionsRow }
|
{ reactionsRow }
|
||||||
{ actionBar }
|
{ actionBar }
|
||||||
</div>
|
</div>,
|
||||||
{msgOption}
|
msgOption,
|
||||||
{
|
avatar,
|
||||||
// The avatar goes after the event tile as it's absolutely positioned to be over the
|
|
||||||
// event tile line, so needs to be later in the DOM so it appears on top (this avoids
|
])
|
||||||
// the need for further z-indexing chaos)
|
)
|
||||||
}
|
|
||||||
{ avatar }
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue