Fix alignment of RTL messages (#12837)

* Fix alignment of RTL messages

Inspired by https://github.com/matrix-org/matrix-react-sdk/pull/5453 but
hopefully with the edited marker in the right place.

This is a PoC: types aren't correct and the style needs pulling
out to a class. Plus it would probably need more visual tests added.
If this looks acceptable, I can make these changes.

* Fix spacing between text and edited annotation

* Update snapshot

* Update more snapshots

* More snapshots

* More more snapshots

* Split out style

* Fix emotes

This will cause them always be right-justified if the display name
is rtl.

* Add playwright test for ltr/rtl message rendering

* Better snapshots

* Await on message sending

* Better waiting, hopefully

* Old snapshot files

* Really hopefully fixed screenshots this time

* Don't include the message action bar in the screenshots
This commit is contained in:
David Baker 2024-07-31 23:23:46 +01:00 committed by GitHub
parent f3ac6692da
commit a0c029c3c1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 242 additions and 79 deletions

View file

@ -303,7 +303,6 @@ export interface EventRenderOpts {
disableBigEmoji?: boolean;
stripReplyFallback?: boolean;
forComposerQuote?: boolean;
ref?: React.Ref<HTMLSpanElement>;
}
function analyseEvent(content: IContent, highlights: Optional<string[]>, opts: EventRenderOpts = {}): EventAnalysis {
@ -375,7 +374,61 @@ function analyseEvent(content: IContent, highlights: Optional<string[]>, opts: E
}
}
export function bodyToNode(content: IContent, highlights: Optional<string[]>, opts: EventRenderOpts = {}): ReactNode {
export function bodyToDiv(
content: IContent,
highlights: Optional<string[]>,
opts: EventRenderOpts = {},
ref?: React.Ref<HTMLDivElement>,
): ReactNode {
const { strippedBody, formattedBody, emojiBodyElements, className } = bodyToNode(content, highlights, opts);
return formattedBody ? (
<div
key="body"
ref={ref}
className={className}
dangerouslySetInnerHTML={{ __html: formattedBody }}
dir="auto"
/>
) : (
<div key="body" ref={ref} className={className} dir="auto">
{emojiBodyElements || strippedBody}
</div>
);
}
export function bodyToSpan(
content: IContent,
highlights: Optional<string[]>,
opts: EventRenderOpts = {},
ref?: React.Ref<HTMLSpanElement>,
includeDir = true,
): ReactNode {
const { strippedBody, formattedBody, emojiBodyElements, className } = bodyToNode(content, highlights, opts);
return formattedBody ? (
<span
key="body"
ref={ref}
className={className}
dangerouslySetInnerHTML={{ __html: formattedBody }}
dir={includeDir ? "auto" : undefined}
/>
) : (
<span key="body" ref={ref} className={className} dir={includeDir ? "auto" : undefined}>
{emojiBodyElements || strippedBody}
</span>
);
}
interface BodyToNodeReturn {
strippedBody: string;
formattedBody?: string;
emojiBodyElements: JSX.Element[] | undefined;
className: string;
}
function bodyToNode(content: IContent, highlights: Optional<string[]>, opts: EventRenderOpts = {}): BodyToNodeReturn {
const eventInfo = analyseEvent(content, highlights, opts);
let emojiBody = false;
@ -419,19 +472,7 @@ export function bodyToNode(content: IContent, highlights: Optional<string[]>, op
emojiBodyElements = formatEmojis(eventInfo.strippedBody, false) as JSX.Element[];
}
return formattedBody ? (
<span
key="body"
ref={opts.ref}
className={className}
dangerouslySetInnerHTML={{ __html: formattedBody }}
dir="auto"
/>
) : (
<span key="body" ref={opts.ref} className={className} dir="auto">
{emojiBodyElements || eventInfo.strippedBody}
</span>
);
return { strippedBody: eventInfo.strippedBody, formattedBody, emojiBodyElements, className };
}
/**