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

Commit e718242

Browse files
authored
Read Receipts "Fall from the Sky" (#8414)
* fix: don't pass hideTitle to base avatar * fix: correctly position read receipt markers
1 parent 942ca74 commit e718242

File tree

2 files changed

+76
-27
lines changed

2 files changed

+76
-27
lines changed

src/components/views/avatars/MemberAvatar.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,16 @@ export default class MemberAvatar extends React.PureComponent<IProps, IState> {
107107
}
108108

109109
render() {
110-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
111-
let { member, fallbackUserId, onClick, viewUserOnClick, forceHistorical, ...otherProps } = this.props;
110+
let {
111+
member,
112+
fallbackUserId,
113+
onClick,
114+
viewUserOnClick,
115+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
116+
forceHistorical,
117+
hideTitle,
118+
...otherProps
119+
} = this.props;
112120
const userId = member ? member.userId : fallbackUserId;
113121

114122
if (viewUserOnClick) {
@@ -125,7 +133,7 @@ export default class MemberAvatar extends React.PureComponent<IProps, IState> {
125133
<BaseAvatar
126134
{...otherProps}
127135
name={this.state.name}
128-
title={this.props.hideTitle ? undefined : this.state.title}
136+
title={hideTitle ? undefined : this.state.title}
129137
idName={userId}
130138
url={this.state.imageUrl}
131139
onClick={onClick}

src/components/views/rooms/ReadReceiptMarker.tsx

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { logger } from "matrix-js-sdk/src/logger";
2222
import NodeAnimator from "../../../NodeAnimator";
2323
import { toPx } from "../../../utils/units";
2424
import MemberAvatar from '../avatars/MemberAvatar';
25+
import { READ_AVATAR_SIZE } from "./ReadReceiptGroup";
2526

2627
export interface IReadReceiptInfo {
2728
top?: number;
@@ -101,10 +102,7 @@ export default class ReadReceiptMarker extends React.PureComponent<IProps, IStat
101102
return;
102103
}
103104

104-
const avatarNode = this.avatar.current;
105-
rrInfo.top = avatarNode.offsetTop;
106-
rrInfo.right = avatarNode.getBoundingClientRect().right - avatarNode.offsetParent.getBoundingClientRect().right;
107-
rrInfo.parent = avatarNode.offsetParent;
105+
this.buildReadReceiptInfo(rrInfo);
108106
}
109107

110108
public componentDidMount(): void {
@@ -123,42 +121,85 @@ export default class ReadReceiptMarker extends React.PureComponent<IProps, IStat
123121
}
124122
}
125123

126-
private animateMarker(): void {
127-
// treat new RRs as though they were off the top of the screen
128-
let oldTop = -15;
124+
private buildReadReceiptInfo(target: IReadReceiptInfo = {}): IReadReceiptInfo {
125+
const element = this.avatar.current;
126+
// this is the mx_ReadReceiptsGroup_container
127+
const horizontalContainer = element.offsetParent;
128+
if (!horizontalContainer || !(horizontalContainer instanceof HTMLElement)) {
129+
// this seems to happen sometimes for reasons I don't understand
130+
// the docs for `offsetParent` say it may be null if `display` is
131+
// `none`, but I can't see why that would happen.
132+
logger.warn(
133+
`ReadReceiptMarker for ${this.props.fallbackUserId} has no valid horizontalContainer`,
134+
);
129135

130-
const oldInfo = this.props.readReceiptInfo;
131-
if (oldInfo && oldInfo.parent) {
132-
oldTop = oldInfo.top + oldInfo.parent.getBoundingClientRect().top;
136+
target.top = 0;
137+
target.right = 0;
138+
target.parent = null;
139+
return;
133140
}
141+
// this is the mx_ReadReceiptsGroup
142+
const verticalContainer = horizontalContainer.offsetParent;
143+
if (!verticalContainer || !(verticalContainer instanceof HTMLElement)) {
144+
// this seems to happen sometimes for reasons I don't understand
145+
// the docs for `offsetParent` say it may be null if `display` is
146+
// `none`, but I can't see why that would happen.
147+
logger.warn(
148+
`ReadReceiptMarker for ${this.props.fallbackUserId} has no valid verticalContainer`,
149+
);
134150

135-
const newElement = this.avatar.current;
136-
let startTopOffset;
137-
if (!newElement.offsetParent) {
151+
target.top = 0;
152+
target.right = 0;
153+
target.parent = null;
154+
return;
155+
}
156+
157+
target.top = element.offsetTop;
158+
target.right = element.getBoundingClientRect().right - horizontalContainer.getBoundingClientRect().right;
159+
target.parent = verticalContainer;
160+
return target;
161+
}
162+
163+
private readReceiptPosition(info: IReadReceiptInfo): number {
164+
if (!info.parent) {
138165
// this seems to happen sometimes for reasons I don't understand
139166
// the docs for `offsetParent` say it may be null if `display` is
140167
// `none`, but I can't see why that would happen.
141168
logger.warn(
142-
`ReadReceiptMarker for ${this.props.fallbackUserId} in has no offsetParent`,
169+
`ReadReceiptMarker for ${this.props.fallbackUserId} has no offsetParent`,
143170
);
144-
startTopOffset = 0;
145-
} else {
146-
startTopOffset = oldTop - newElement.offsetParent.getBoundingClientRect().top;
171+
return 0;
147172
}
148173

149-
const startStyles = [];
174+
return info.top + info.parent.getBoundingClientRect().top;
175+
}
150176

151-
if (oldInfo && oldInfo.right) {
177+
private animateMarker(): void {
178+
const oldInfo = this.props.readReceiptInfo;
179+
const newInfo = this.buildReadReceiptInfo();
180+
181+
const newPosition = this.readReceiptPosition(newInfo);
182+
const oldPosition = oldInfo
152183
// start at the old height and in the old h pos
153-
startStyles.push({ top: startTopOffset+"px",
154-
right: toPx(oldInfo.right) });
155-
}
184+
? this.readReceiptPosition(oldInfo)
185+
// treat new RRs as though they were off the top of the screen
186+
: -READ_AVATAR_SIZE;
156187

157-
startStyles.push({ top: startTopOffset+'px', right: '0' });
188+
const startStyles = [];
189+
if (oldInfo && oldInfo.right) {
190+
startStyles.push({
191+
top: oldPosition - newPosition,
192+
right: oldInfo.right,
193+
});
194+
}
195+
startStyles.push({
196+
top: oldPosition - newPosition,
197+
right: 0,
198+
});
158199

159200
this.setState({
160201
suppressDisplay: false,
161-
startStyles: startStyles,
202+
startStyles,
162203
});
163204
}
164205

0 commit comments

Comments
 (0)