feat(messages): word diff of the last edit on "(edited)" hover (#144)
CI / Build & Quality Checks (push) Successful in 1m40s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 8s
CI / Trigger Desktop Build (push) Successful in 7s
CI / Playwright smoke (e2e) (push) Canceled after 1m37s
CI / Build & Quality Checks (push) Successful in 1m40s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 8s
CI / Trigger Desktop Build (push) Successful in 7s
CI / Playwright smoke (e2e) (push) Canceled after 1m37s
Hovering or focusing "(edited)" shows a tooltip with only the most recent edit as a word diff — removed words struck, added words bold — plus a +N/−N summary. Clicking still opens the full history viewer. On touch, a long-press on the label shows the same diff as a popout (a plain tap opens the viewer; the message's own long-press action sheet is not triggered). utils/wordDiff.ts is a unit-tested LCS over words that ignores whitespace- only changes and gives up past 400 words. Only plain-text bodies are diffed; formatted edits fall back to the viewer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import { EventTimelineSet, MatrixEvent } from 'matrix-js-sdk';
|
||||
import { getEventEdits, trimReplyFromBody } from './room';
|
||||
import { DiffToken, wordDiff } from './wordDiff';
|
||||
|
||||
const isPlainText = (content: Record<string, unknown> | undefined): content is { body: string } =>
|
||||
!!content &&
|
||||
typeof content.body === 'string' &&
|
||||
content.format === undefined &&
|
||||
content.formatted_body === undefined;
|
||||
|
||||
/**
|
||||
* [Gitea #144] Word diff of the *last* edit to `mEvent`: the newest edit's body
|
||||
* against the one it replaced (an earlier edit, or the original). Only for
|
||||
* plain-text bodies — formatted edits return `undefined` and the caller falls
|
||||
* back to the history viewer.
|
||||
*/
|
||||
export function getLastEditDiff(
|
||||
mEvent: MatrixEvent,
|
||||
timelineSet: EventTimelineSet,
|
||||
): DiffToken[] | undefined {
|
||||
const eventId = mEvent.getId();
|
||||
if (!eventId) return undefined;
|
||||
const relations = getEventEdits(timelineSet, eventId, mEvent.getType());
|
||||
if (!relations) return undefined;
|
||||
const edits = relations
|
||||
.getRelations()
|
||||
.filter((e) => e.getSender() === mEvent.getSender())
|
||||
.sort((m1, m2) => m2.getTs() - m1.getTs());
|
||||
const latest = edits[0];
|
||||
if (!latest) return undefined;
|
||||
const after = latest.getContent()['m.new_content'] as Record<string, unknown> | undefined;
|
||||
const before = (edits[1]?.getContent()['m.new_content'] ?? mEvent.getContent()) as
|
||||
| Record<string, unknown>
|
||||
| undefined;
|
||||
if (!isPlainText(after) || !isPlainText(before)) return undefined;
|
||||
return wordDiff(trimReplyFromBody(before.body), trimReplyFromBody(after.body));
|
||||
}
|
||||
Reference in New Issue
Block a user