fix(edit-history): harden diff after review
Address findings from 2 review agents on the edit-history diff: - Perf: diffWords is O(n*m); cap at 2000 tokens/side and fall back to a coarse whole-block replaced diff above that, so a very large multi-edit message can't freeze the main thread. Memoize the per-row diff in DiffText. (Added a unit test for the coarse fallback.) - Perceivability (a11y/design): the added-word <ins> highlight was color-fill only, which is faint against the modal surface in the lotus themes. Add a Success.ContainerLine border + horizontal padding (so the rounded corners read as a chip) + box-decoration-break: clone for clean wrapping, so the "added" cue survives low fill contrast. - Consistency: a media/no-body edit now renders "(no text)" in diff mode too (matched the toggle-off view; was blank). - Softened the code comment's screen-reader claim (bare <ins>/<del> aren't announced by default). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { ReactNode, useCallback, useEffect, useState } from 'react';
|
||||
import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import parse from 'html-react-parser';
|
||||
import Linkify from 'linkify-react';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
@@ -113,10 +113,11 @@ function getVersionText(evt: MatrixEvent): string {
|
||||
}
|
||||
|
||||
// Renders a word-level diff of prev -> next: added words highlighted, removed
|
||||
// words struck-through. Uses semantic <ins>/<del> so screen readers announce
|
||||
// the change. Plain-text only (formatting isn't diffed — see the toggle).
|
||||
// words struck-through, using semantic <ins>/<del> elements. Plain-text only
|
||||
// (formatting isn't diffed — see the "Highlight changes" toggle).
|
||||
function DiffText({ prev, next }: { prev: string; next: string }) {
|
||||
const segments = diffWords(prev, next);
|
||||
const segments = useMemo(() => diffWords(prev, next), [prev, next]);
|
||||
if (segments.length === 0) return <>(no text)</>;
|
||||
return (
|
||||
<>
|
||||
{segments.map((seg, i) => {
|
||||
@@ -128,8 +129,12 @@ function DiffText({ prev, next }: { prev: string; next: string }) {
|
||||
style={{
|
||||
background: color.Success.Container,
|
||||
color: color.Success.OnContainer,
|
||||
border: `${config.borderWidth.B300} solid ${color.Success.ContainerLine}`,
|
||||
borderRadius: config.radii.R300,
|
||||
padding: `0 ${config.space.S100}`,
|
||||
textDecoration: 'none',
|
||||
boxDecorationBreak: 'clone',
|
||||
WebkitBoxDecorationBreak: 'clone',
|
||||
}}
|
||||
>
|
||||
{seg.text}
|
||||
|
||||
Reference in New Issue
Block a user