Loading threads with server-side assistance (#9356)

* Fix bug with message context menu
* fix bug where ThreadSummary failed if no last reply is available
* Fix relations direction API
* Use same API for threads as for any other timeline
* Determine if event belongs to thread on jumping to event
* properly listen to thread deletion
* Add thread redaction tests
* Add fetchInitialEvent tests
* Paginate using default TimelinePanel behaviour
* Remove unused threads deleted code

Co-authored-by: Germain <germain@souquet.com>
Co-authored-by: Germain <germains@element.io>
This commit is contained in:
Janne Mareike Koschinski 2022-10-28 13:48:15 +02:00 committed by GitHub
parent 750ca78e98
commit d92fdc1f5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 205 additions and 82 deletions

View file

@ -382,7 +382,13 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
public render(): JSX.Element {
const cli = MatrixClientPeg.get();
const me = cli.getUserId();
const { mxEvent, rightClick, link, eventTileOps, reactions, collapseReplyChain } = this.props;
const {
mxEvent, rightClick, link, eventTileOps, reactions, collapseReplyChain,
...other
} = this.props;
delete other.getRelationsForEvent;
delete other.permalinkCreator;
const eventStatus = mxEvent.status;
const unsentReactionsCount = this.getUnsentReactions().length;
const contentActionable = isContentActionable(mxEvent);
@ -747,7 +753,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
return (
<React.Fragment>
<IconizedContextMenu
{...this.props}
{...other}
className="mx_MessageContextMenu"
compact={true}
data-testid="mx_MessageContextMenu"

View file

@ -540,7 +540,11 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
private renderThreadInfo(): React.ReactNode {
if (this.state.thread?.id === this.props.mxEvent.getId()) {
return <ThreadSummary mxEvent={this.props.mxEvent} thread={this.state.thread} />;
return <ThreadSummary
mxEvent={this.props.mxEvent}
thread={this.state.thread}
data-testid="thread-summary"
/>;
}
if (this.context.timelineRenderingType === TimelineRenderingType.Search && this.props.mxEvent.threadRootId) {
@ -1528,9 +1532,11 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
// Wrap all event tiles with the tile error boundary so that any throws even during construction are captured
const SafeEventTile = forwardRef((props: EventTileProps, ref: RefObject<UnwrappedEventTile>) => {
return <TileErrorBoundary mxEvent={props.mxEvent} layout={props.layout}>
<UnwrappedEventTile ref={ref} {...props} />
</TileErrorBoundary>;
return <>
<TileErrorBoundary mxEvent={props.mxEvent} layout={props.layout}>
<UnwrappedEventTile ref={ref} {...props} />
</TileErrorBoundary>
</>;
});
export default SafeEventTile;

View file

@ -37,7 +37,7 @@ interface IProps {
thread: Thread;
}
const ThreadSummary = ({ mxEvent, thread }: IProps) => {
const ThreadSummary = ({ mxEvent, thread, ...props }: IProps) => {
const roomContext = useContext(RoomContext);
const cardContext = useContext(CardContext);
const count = useTypedEventEmitterState(thread, ThreadEvent.Update, () => thread.length);
@ -50,6 +50,7 @@ const ThreadSummary = ({ mxEvent, thread }: IProps) => {
return (
<AccessibleButton
{...props}
className="mx_ThreadSummary"
onClick={(ev: ButtonEvent) => {
defaultDispatcher.dispatch<ShowThreadPayload>({
@ -94,7 +95,9 @@ export const ThreadMessagePreview = ({ thread, showDisplayname = false }: IPrevi
await cli.decryptEventIfNeeded(lastReply);
return MessagePreviewStore.instance.generatePreviewForEvent(lastReply);
}, [lastReply, content]);
if (!preview) return null;
if (!preview || !lastReply) {
return null;
}
return <>
<MemberAvatar