diff --git a/src/@types/common.ts b/src/@types/common.ts index 991cfb7e08..d70d80fcd5 100644 --- a/src/@types/common.ts +++ b/src/@types/common.ts @@ -34,3 +34,10 @@ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...0[]]; export type Leaves = [D] extends [never] ? never : T extends object ? { [K in keyof T]-?: Join> }[keyof T] : ""; + +export type RecursivePartial = { + [P in keyof T]?: + T[P] extends (infer U)[] ? RecursivePartial[] : + T[P] extends object ? RecursivePartial : + T[P]; +}; diff --git a/src/components/views/rooms/EventTile.tsx b/src/components/views/rooms/EventTile.tsx index 28073fed32..92c783bfce 100644 --- a/src/components/views/rooms/EventTile.tsx +++ b/src/components/views/rooms/EventTile.tsx @@ -1403,11 +1403,8 @@ export class UnwrappedEventTile extends React.Component { msgOption = readAvatars; } - const renderTarget = this.context.timelineRenderingType === TimelineRenderingType.Thread - ? RelationType.Thread - : undefined; - - const replyChain = haveTileForEvent(this.props.mxEvent) && shouldDisplayReply(this.props.mxEvent, renderTarget) + const inThread = this.context.timelineRenderingType === TimelineRenderingType.Thread; + const replyChain = haveTileForEvent(this.props.mxEvent) && shouldDisplayReply(this.props.mxEvent, inThread) ? { if (!ev) return {}; - const mixin: any = { + const mixin: RecursivePartial = { 'm.relates_to': { 'm.in_reply_to': { 'event_id': ev.getId(), + 'io.element.is_falling_back': !inThread, // MSC3440 unstable `is_falling_back` field }, }, }; - if (renderIn) { - mixin['m.relates_to']['m.in_reply_to']['m.render_in'] = renderIn; - } - /** * If the event replied is part of a thread * Add the `m.thread` relation so that clients @@ -173,19 +171,12 @@ export function makeReplyMixIn(ev: MatrixEvent, renderIn?: string[]) { return mixin; } -export function shouldDisplayReply(event: MatrixEvent, renderTarget?: string): boolean { +export function shouldDisplayReply(event: MatrixEvent, inThread = false): boolean { const parentExist = Boolean(getParentEventId(event)); + if (!parentExist) return false; + if (!inThread) return true; - const relations = event.getRelation(); - const renderIn = relations?.["m.in_reply_to"]?.["m.render_in"] ?? []; - - const shouldRenderInTarget = !renderTarget || (renderIn.includes(renderTarget)); - - return parentExist && shouldRenderInTarget; -} - -export function getRenderInMixin(relation?: IEventRelation): string[] | undefined { - if (relation?.rel_type === RelationType.Thread) { - return [RelationType.Thread]; - } + const inReplyTo = event.getRelation()?.["m.in_reply_to"]; + const isFallingBack = inReplyTo?.is_falling_back ?? inReplyTo?.["io.element.is_falling_back"]; + return !isFallingBack; }