Read Receipts "Fall from the Sky" (#8414)
* fix: don't pass hideTitle to base avatar * fix: correctly position read receipt markerspull/28788/head^2
parent
942ca74316
commit
e718242912
|
@ -107,8 +107,16 @@ export default class MemberAvatar extends React.PureComponent<IProps, IState> {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
let {
|
||||||
let { member, fallbackUserId, onClick, viewUserOnClick, forceHistorical, ...otherProps } = this.props;
|
member,
|
||||||
|
fallbackUserId,
|
||||||
|
onClick,
|
||||||
|
viewUserOnClick,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
forceHistorical,
|
||||||
|
hideTitle,
|
||||||
|
...otherProps
|
||||||
|
} = this.props;
|
||||||
const userId = member ? member.userId : fallbackUserId;
|
const userId = member ? member.userId : fallbackUserId;
|
||||||
|
|
||||||
if (viewUserOnClick) {
|
if (viewUserOnClick) {
|
||||||
|
@ -125,7 +133,7 @@ export default class MemberAvatar extends React.PureComponent<IProps, IState> {
|
||||||
<BaseAvatar
|
<BaseAvatar
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
name={this.state.name}
|
name={this.state.name}
|
||||||
title={this.props.hideTitle ? undefined : this.state.title}
|
title={hideTitle ? undefined : this.state.title}
|
||||||
idName={userId}
|
idName={userId}
|
||||||
url={this.state.imageUrl}
|
url={this.state.imageUrl}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { logger } from "matrix-js-sdk/src/logger";
|
||||||
import NodeAnimator from "../../../NodeAnimator";
|
import NodeAnimator from "../../../NodeAnimator";
|
||||||
import { toPx } from "../../../utils/units";
|
import { toPx } from "../../../utils/units";
|
||||||
import MemberAvatar from '../avatars/MemberAvatar';
|
import MemberAvatar from '../avatars/MemberAvatar';
|
||||||
|
import { READ_AVATAR_SIZE } from "./ReadReceiptGroup";
|
||||||
|
|
||||||
export interface IReadReceiptInfo {
|
export interface IReadReceiptInfo {
|
||||||
top?: number;
|
top?: number;
|
||||||
|
@ -101,10 +102,7 @@ export default class ReadReceiptMarker extends React.PureComponent<IProps, IStat
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const avatarNode = this.avatar.current;
|
this.buildReadReceiptInfo(rrInfo);
|
||||||
rrInfo.top = avatarNode.offsetTop;
|
|
||||||
rrInfo.right = avatarNode.getBoundingClientRect().right - avatarNode.offsetParent.getBoundingClientRect().right;
|
|
||||||
rrInfo.parent = avatarNode.offsetParent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public componentDidMount(): void {
|
public componentDidMount(): void {
|
||||||
|
@ -123,42 +121,85 @@ export default class ReadReceiptMarker extends React.PureComponent<IProps, IStat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private animateMarker(): void {
|
private buildReadReceiptInfo(target: IReadReceiptInfo = {}): IReadReceiptInfo {
|
||||||
// treat new RRs as though they were off the top of the screen
|
const element = this.avatar.current;
|
||||||
let oldTop = -15;
|
// this is the mx_ReadReceiptsGroup_container
|
||||||
|
const horizontalContainer = element.offsetParent;
|
||||||
const oldInfo = this.props.readReceiptInfo;
|
if (!horizontalContainer || !(horizontalContainer instanceof HTMLElement)) {
|
||||||
if (oldInfo && oldInfo.parent) {
|
|
||||||
oldTop = oldInfo.top + oldInfo.parent.getBoundingClientRect().top;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newElement = this.avatar.current;
|
|
||||||
let startTopOffset;
|
|
||||||
if (!newElement.offsetParent) {
|
|
||||||
// this seems to happen sometimes for reasons I don't understand
|
// this seems to happen sometimes for reasons I don't understand
|
||||||
// the docs for `offsetParent` say it may be null if `display` is
|
// the docs for `offsetParent` say it may be null if `display` is
|
||||||
// `none`, but I can't see why that would happen.
|
// `none`, but I can't see why that would happen.
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`ReadReceiptMarker for ${this.props.fallbackUserId} in has no offsetParent`,
|
`ReadReceiptMarker for ${this.props.fallbackUserId} has no valid horizontalContainer`,
|
||||||
);
|
);
|
||||||
startTopOffset = 0;
|
|
||||||
} else {
|
target.top = 0;
|
||||||
startTopOffset = oldTop - newElement.offsetParent.getBoundingClientRect().top;
|
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 = [];
|
const startStyles = [];
|
||||||
|
|
||||||
if (oldInfo && oldInfo.right) {
|
if (oldInfo && oldInfo.right) {
|
||||||
// start at the old height and in the old h pos
|
startStyles.push({
|
||||||
startStyles.push({ top: startTopOffset+"px",
|
top: oldPosition - newPosition,
|
||||||
right: toPx(oldInfo.right) });
|
right: oldInfo.right,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
startStyles.push({
|
||||||
startStyles.push({ top: startTopOffset+'px', right: '0' });
|
top: oldPosition - newPosition,
|
||||||
|
right: 0,
|
||||||
|
});
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
suppressDisplay: false,
|
suppressDisplay: false,
|
||||||
startStyles: startStyles,
|
startStyles,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue