Update m.render_in to is_falling_back (+ unstable field) (#7979)

pull/21833/head
Michael Telatynski 2022-03-09 16:15:53 +00:00 committed by GitHub
parent 2ab8b46ba3
commit 288e47fd81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 26 additions and 31 deletions

View File

@ -34,3 +34,10 @@ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...0[]];
export type Leaves<T, D extends number = 5> = [D] extends [never] ? never : T extends object ? export type Leaves<T, D extends number = 5> = [D] extends [never] ? never : T extends object ?
{ [K in keyof T]-?: Join<K, Leaves<T[K], Prev[D]>> }[keyof T] : ""; { [K in keyof T]-?: Join<K, Leaves<T[K], Prev[D]>> }[keyof T] : "";
export type RecursivePartial<T> = {
[P in keyof T]?:
T[P] extends (infer U)[] ? RecursivePartial<U>[] :
T[P] extends object ? RecursivePartial<T[P]> :
T[P];
};

View File

@ -1403,11 +1403,8 @@ export class UnwrappedEventTile extends React.Component<IProps, IState> {
msgOption = readAvatars; msgOption = readAvatars;
} }
const renderTarget = this.context.timelineRenderingType === TimelineRenderingType.Thread const inThread = this.context.timelineRenderingType === TimelineRenderingType.Thread;
? RelationType.Thread const replyChain = haveTileForEvent(this.props.mxEvent) && shouldDisplayReply(this.props.mxEvent, inThread)
: undefined;
const replyChain = haveTileForEvent(this.props.mxEvent) && shouldDisplayReply(this.props.mxEvent, renderTarget)
? <ReplyChain ? <ReplyChain
parentEv={this.props.mxEvent} parentEv={this.props.mxEvent}
onHeightChanged={this.props.onHeightChanged} onHeightChanged={this.props.onHeightChanged}

View File

@ -57,12 +57,12 @@ import { ComposerType } from "../../../dispatcher/payloads/ComposerInsertPayload
import { getSlashCommand, isSlashCommand, runSlashCommand, shouldSendAnyway } from "../../../editor/commands"; import { getSlashCommand, isSlashCommand, runSlashCommand, shouldSendAnyway } from "../../../editor/commands";
import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts";
import { PosthogAnalytics } from "../../../PosthogAnalytics"; import { PosthogAnalytics } from "../../../PosthogAnalytics";
import { getNestedReplyText, getRenderInMixin, makeReplyMixIn } from '../../../utils/Reply'; import { getNestedReplyText, makeReplyMixIn } from '../../../utils/Reply';
interface IAddReplyOpts { interface IAddReplyOpts {
permalinkCreator?: RoomPermalinkCreator; permalinkCreator?: RoomPermalinkCreator;
includeLegacyFallback?: boolean; includeLegacyFallback?: boolean;
renderIn?: string[]; inThread?: boolean;
} }
function addReplyToMessageContent( function addReplyToMessageContent(
@ -72,7 +72,7 @@ function addReplyToMessageContent(
includeLegacyFallback: true, includeLegacyFallback: true,
}, },
): void { ): void {
const replyContent = makeReplyMixIn(replyToEvent, opts.renderIn); const replyContent = makeReplyMixIn(replyToEvent, opts.inThread);
Object.assign(content, replyContent); Object.assign(content, replyContent);
if (opts.includeLegacyFallback) { if (opts.includeLegacyFallback) {
@ -131,8 +131,8 @@ export function createMessageContent(
if (replyToEvent) { if (replyToEvent) {
addReplyToMessageContent(content, replyToEvent, { addReplyToMessageContent(content, replyToEvent, {
permalinkCreator, permalinkCreator,
includeLegacyFallback: true, includeLegacyFallback: includeReplyLegacyFallback,
renderIn: getRenderInMixin(relation), inThread: relation?.rel_type === RelationType.Thread,
}); });
} }
@ -398,7 +398,7 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
addReplyToMessageContent(content, replyToEvent, { addReplyToMessageContent(content, replyToEvent, {
permalinkCreator: this.props.permalinkCreator, permalinkCreator: this.props.permalinkCreator,
includeLegacyFallback: true, includeLegacyFallback: true,
renderIn: getRenderInMixin(this.props.relation), inThread: this.props.relation?.rel_type === RelationType.Thread,
}); });
} }
} else { } else {

View File

@ -14,13 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { IEventRelation, MatrixEvent } from "matrix-js-sdk/src/models/event"; import { IContent, MatrixEvent } from "matrix-js-sdk/src/models/event";
import { RelationType } from "matrix-js-sdk/src/@types/event"; import { RelationType } from "matrix-js-sdk/src/@types/event";
import sanitizeHtml from "sanitize-html"; import sanitizeHtml from "sanitize-html";
import escapeHtml from "escape-html"; import escapeHtml from "escape-html";
import { PERMITTED_URL_SCHEMES } from "../HtmlUtils"; import { PERMITTED_URL_SCHEMES } from "../HtmlUtils";
import { makeUserPermalink, RoomPermalinkCreator } from "./permalinks/Permalinks"; import { makeUserPermalink, RoomPermalinkCreator } from "./permalinks/Permalinks";
import { RecursivePartial } from "../@types/common";
export function getParentEventId(ev: MatrixEvent): string | undefined { export function getParentEventId(ev: MatrixEvent): string | undefined {
if (!ev || ev.isRedacted()) return; if (!ev || ev.isRedacted()) return;
@ -141,21 +142,18 @@ export function getNestedReplyText(
return { body, html }; return { body, html };
} }
export function makeReplyMixIn(ev: MatrixEvent, renderIn?: string[]) { export function makeReplyMixIn(ev?: MatrixEvent, inThread = false): RecursivePartial<IContent> {
if (!ev) return {}; if (!ev) return {};
const mixin: any = { const mixin: RecursivePartial<IContent> = {
'm.relates_to': { 'm.relates_to': {
'm.in_reply_to': { 'm.in_reply_to': {
'event_id': ev.getId(), '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 * If the event replied is part of a thread
* Add the `m.thread` relation so that clients * Add the `m.thread` relation so that clients
@ -173,19 +171,12 @@ export function makeReplyMixIn(ev: MatrixEvent, renderIn?: string[]) {
return mixin; return mixin;
} }
export function shouldDisplayReply(event: MatrixEvent, renderTarget?: string): boolean { export function shouldDisplayReply(event: MatrixEvent, inThread = false): boolean {
const parentExist = Boolean(getParentEventId(event)); const parentExist = Boolean(getParentEventId(event));
if (!parentExist) return false;
if (!inThread) return true;
const relations = event.getRelation(); const inReplyTo = event.getRelation()?.["m.in_reply_to"];
const renderIn = relations?.["m.in_reply_to"]?.["m.render_in"] ?? []; const isFallingBack = inReplyTo?.is_falling_back ?? inReplyTo?.["io.element.is_falling_back"];
return !isFallingBack;
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];
}
} }