element-hq / element-hq/element-x-android

Rework timeline events rendering

Open
#7,633 0 comments 0 reactions 0 assignees View on GitHub
T-Enhancement
Dominant language
Kotlin
Stars
2.4k
Forks
624
Avg merge
1d 14h
Merged PRs (30d)
149

Description

### Your use case

#### What would you like to do?

Rework the rendering of timeline events so we don't just have a `TextView` with spans and a few drawn overlays, but we can actually add interactive components like scrollable or expandable code blocks or quotes, spoiler tags, inline images, etc.

As a bonus, it would also be nice to modernise the Rich Text Editor (RTE) so it uses Compose components instead of a legacy `EditText` wrapped in a Composable bridge. However, this is orders of magnitudes more complex and is out of scope.

#### Why would you like to do it?

- The current rendering is quite efficient, but it was built when the available APIs in Compose were quite limited and so we had to fall back to `TextView` instead.
- We also did this so we could have a shared implementation with the RTE library to have a single source of truth, but this has proven problematic: having the RTE as a separate library slows down any new feature or fix related to timeline rendering, we need to make exceptions for corner cases about line spacing, and adds an extra layer of complexity at rendering the messages that's not really needed.
- It's impossible, or at least very complex and awkward to render interactive components given the current implementation. There have been several request to add those and rendering other HTML tags that aren't included in the RTE:
- https://github.com/element-hq/element-x-android/issues/7491
- https://github.com/element-hq/element-x-android/issues/2860
- https://github.com/element-hq/element-x-android/issues/1551
- https://github.com/element-hq/element-x-android/issues/2870
- https://github.com/element-hq/element-x-android/issues/1874
- https://github.com/element-hq/element-x-android/issues/3076
- Having this new rendering could potentially simplify some of our internal code for timeline events and improve performance. Emphasis in *could*, as this would only be possible if rendering several components would 'cache' the rendering for those independently, allowing us to only re-render those that have changed.

#### How would you like to achieve it?

- Stop using the RTE's `HtmlToSpanParser` for converting HTML into spanned rich text, and depending in the RTE's renderer altogether for rendering events.
- Instead, create our own HTML parser that converts those into either a list of composable functions, or some abstractions over the different tags (paragraph, code block, spoiler, quote, etc.) that can be passed around and then turned into composable functions when needed.
- Stop using `TextView` to render the data, use rich Compose components with its own logic, and in the case of pure text, move to using the Composable `Text` function instead with styles.
- Rewrite the mention/room pills so they work with `Text`.
- Still take into account what's the latest composable to render to be able to place the timestamp and resize the message bubble accordingly.

### Have you considered any alternatives?

The only alternative would be to keep using the current rendering. Given iOS is already way past this, having interactive code blocks and working on supporting spoiler tags, we should try to reach parity.

### Additional context

_No response_

### Are you willing to provide a PR?

Yes

Contributor guide

Open the contributing guide

Research direction

Start by tracing timeline event rendering and the RTE's HtmlToSpanParser, then compare how TextView spans and overlays are used today. Done means timeline events render through Compose components without depending on the RTE renderer, while supporting interactive elements such as code blocks, quotes, spoilers, inline images, mentions, room pills, timestamps, and message bubble sizing.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
frontend, mobile
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.