Collapse runs of deleted messages in the timeline (#7195)

* Collapse runs of deleted messages in the timeline (#7111)

* Collapse runs of deleted messages in the timeline

Collapse a run of three or more consecutive deleted messages into a single
expandable group, reusing the existing state-change grouping (the same way
element-web does it) instead of showing one "Message removed" placeholder per
deletion. The header shows the count only ("N deleted messages"); the Rust SDK
does not expose who performed the redaction, so we don't attribute it.

On by default. Runs shorter than three are left as individual placeholders, and
day dividers and read receipts are preserved (a run is broken by any
non-redacted item, so a day is never emptied).

Run the collapse as the final step of TimelineItemGrouper.group() instead of
a separate pass in the presenter, as suggested in review. Kept as its own
finalization step rather than via canBeGrouped() so the group stays all
redacted and the count-only header is preserved.
The group id is resolved through the grouper's existing id registry, like the
other groups, so it stays stable however the run grows and the user's
expand/collapse state is kept across timeline updates.

* Replace temporary strings with final ones

* Update screenshots

---------

Co-authored-by: Hi Dude! <klarkmonty@tuta.io>
Co-authored-by: manfrommedan <manfrommedan@users.noreply.github.com>
Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
Jorge Martin Espinosa
2026-07-13 15:57:55 +02:00
committed by GitHub
parent 03304b3ece
commit f9112cc583
37 changed files with 477 additions and 54 deletions
@@ -158,6 +158,7 @@ class KonsistPreviewTest {
"TimelineItemGroupedEventsRowContentCollapsePreview",
"TimelineItemGroupedEventsRowContentExpandedPreview",
"TimelineItemImageViewHideMediaContentPreview",
"TimelineItemRedactedMessagesGroupPreview",
"TimelineItemVideoViewHideMediaContentPreview",
"TimelineItemVoiceViewUnifiedPreview",
"TimelineVideoWithCaptionRowPreview",
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d19e7a09114e76294a0626e5d617cf55fe7c13a0188a7d5b364f57c0d9daedc1
size 12123
oid sha256:b5dc5c492ed3fd552e77c0be85b639d55bc7e976f15b761f927b0b80ecca601d
size 12115
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:42f03759fcffbb750181168256130b6a94a1fcf91ee028e69a19a6e3b68ed0e8
size 11711
oid sha256:5896eb5df6f5398bdb94e74280d0d5c04b6a5a53c2378b7377c60fa58eef544b
size 12013
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6bbc8c05e6f6818d00282228f52424ebe93e6e3dca3431d742e8c652d56460d6
size 11712
oid sha256:e7ce8a8c6b4d1692e4b127b7f17f507552666c631893025082c385b93d835a73
size 11726
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:66f6d0d6b03ee4c999cd4edc9c6ae567d31b8b537ca6f9cc8fbe436d06ce80ab
size 11643
oid sha256:8b93c08531efbeacb55f84b17ac793a7b226e5a2db7bc5072e94bc040cd1e9bc
size 11386