Read Receipts "Fall from the Sky" (#8414)

* fix: don't pass hideTitle to base avatar
* fix: correctly position read receipt markers
This commit is contained in:
Janne Mareike Koschinski 2022-04-26 18:09:41 +02:00 committed by GitHub
parent 942ca74316
commit e718242912
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 30 deletions

View file

@ -107,8 +107,16 @@ export default class MemberAvatar extends React.PureComponent<IProps, IState> {
}
render() {
let {
member,
fallbackUserId,
onClick,
viewUserOnClick,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let { member, fallbackUserId, onClick, viewUserOnClick, forceHistorical, ...otherProps } = this.props;
forceHistorical,
hideTitle,
...otherProps
} = this.props;
const userId = member ? member.userId : fallbackUserId;
if (viewUserOnClick) {
@ -125,7 +133,7 @@ export default class MemberAvatar extends React.PureComponent<IProps, IState> {
<BaseAvatar
{...otherProps}
name={this.state.name}
title={this.props.hideTitle ? undefined : this.state.title}
title={hideTitle ? undefined : this.state.title}
idName={userId}
url={this.state.imageUrl}
onClick={onClick}

View file

@ -22,6 +22,7 @@ import { logger } from "matrix-js-sdk/src/logger";
import NodeAnimator from "../../../NodeAnimator";
import { toPx } from "../../../utils/units";
import MemberAvatar from '../avatars/MemberAvatar';
import { READ_AVATAR_SIZE } from "./ReadReceiptGroup";
export interface IReadReceiptInfo {
top?: number;
@ -101,10 +102,7 @@ export default class ReadReceiptMarker extends React.PureComponent<IProps, IStat
return;
}
const avatarNode = this.avatar.current;
rrInfo.top = avatarNode.offsetTop;
rrInfo.right = avatarNode.getBoundingClientRect().right - avatarNode.offsetParent.getBoundingClientRect().right;
rrInfo.parent = avatarNode.offsetParent;
this.buildReadReceiptInfo(rrInfo);
}
public componentDidMount(): void {
@ -123,42 +121,85 @@ export default class ReadReceiptMarker extends React.PureComponent<IProps, IStat
}
}
private animateMarker(): void {
// treat new RRs as though they were off the top of the screen
let oldTop = -15;
const oldInfo = this.props.readReceiptInfo;
if (oldInfo && oldInfo.parent) {
oldTop = oldInfo.top + oldInfo.parent.getBoundingClientRect().top;
}
const newElement = this.avatar.current;
let startTopOffset;
if (!newElement.offsetParent) {
private buildReadReceiptInfo(target: IReadReceiptInfo = {}): IReadReceiptInfo {
const element = this.avatar.current;
// this is the mx_ReadReceiptsGroup_container
const horizontalContainer = element.offsetParent;
if (!horizontalContainer || !(horizontalContainer instanceof HTMLElement)) {
// this seems to happen sometimes for reasons I don't understand
// the docs for `offsetParent` say it may be null if `display` is
// `none`, but I can't see why that would happen.
logger.warn(
`ReadReceiptMarker for ${this.props.fallbackUserId} in has no offsetParent`,
`ReadReceiptMarker for ${this.props.fallbackUserId} has no valid horizontalContainer`,
);
startTopOffset = 0;
} else {
startTopOffset = oldTop - newElement.offsetParent.getBoundingClientRect().top;
target.top = 0;
target.right = 0;
target.parent = null;
return;
}
// this is the mx_ReadReceiptsGroup
const verticalContainer = horizontalContainer.offsetParent;
if (!verticalContainer || !(verticalContainer instanceof HTMLElement)) {
// this seems to happen sometimes for reasons I don't understand
// the docs for `offsetParent` say it may be null if `display` is
// `none`, but I can't see why that would happen.
logger.warn(
`ReadReceiptMarker for ${this.props.fallbackUserId} has no valid verticalContainer`,
);
target.top = 0;
target.right = 0;
target.parent = null;
return;
}
target.top = element.offsetTop;
target.right = element.getBoundingClientRect().right - horizontalContainer.getBoundingClientRect().right;
target.parent = verticalContainer;
return target;
}
private readReceiptPosition(info: IReadReceiptInfo): number {
if (!info.parent) {
// this seems to happen sometimes for reasons I don't understand
// the docs for `offsetParent` say it may be null if `display` is
// `none`, but I can't see why that would happen.
logger.warn(
`ReadReceiptMarker for ${this.props.fallbackUserId} has no offsetParent`,
);
return 0;
}
return info.top + info.parent.getBoundingClientRect().top;
}
private animateMarker(): void {
const oldInfo = this.props.readReceiptInfo;
const newInfo = this.buildReadReceiptInfo();
const newPosition = this.readReceiptPosition(newInfo);
const oldPosition = oldInfo
// start at the old height and in the old h pos
? this.readReceiptPosition(oldInfo)
// treat new RRs as though they were off the top of the screen
: -READ_AVATAR_SIZE;
const startStyles = [];
if (oldInfo && oldInfo.right) {
// start at the old height and in the old h pos
startStyles.push({ top: startTopOffset+"px",
right: toPx(oldInfo.right) });
startStyles.push({
top: oldPosition - newPosition,
right: oldInfo.right,
});
}
startStyles.push({ top: startTopOffset+'px', right: '0' });
startStyles.push({
top: oldPosition - newPosition,
right: 0,
});
this.setState({
suppressDisplay: false,
startStyles: startStyles,
startStyles,
});
}