Skip to content

Conversation

@Johennes
Copy link
Contributor

@Johennes Johennes commented Nov 12, 2025

At the moment, TimelineController::init_focus doesn't use the event cache at all in the TimelineFocus::Event arm. I believe this is because the cache currently cannot load surrounding context for an event. However, when no context is requested, meaning num_context_events = 0, this result in a potentially superfluous /context request.

This pull request, differentiates this special case and attempts to load the event from the cache before falling back to the server.

Additionally, common relations (reactions & edits) are included, if possible. This is similar to the behavior in the TimelineFocus::PinnedEvents arm and allows using focused timelines to power event details views.

Open questions:

  • Given the similarity to the TimelineFocus::PinnedEvents behavior, I'm not sure if it might be better to generalize TimelineFocus::PinnedEvents to support both cases.

  • It would be great if TimelineFocus::Event would make use of the event cache regardless of whether context was requested or not. I'm not sure if that's feasibly possible though.

  • Public API changes documented in changelogs (optional)

@codspeed-hq
Copy link

codspeed-hq bot commented Nov 12, 2025

CodSpeed Performance Report

Merging #5858 will not alter performance

Comparing Johennes:johannes/focus-no-context (37d56be) with main (20ee85b)

Summary

✅ 50 untouched

@Johennes Johennes force-pushed the johannes/focus-no-context branch 2 times, most recently from 1b0b967 to fa1bcaf Compare November 12, 2025 08:47
…ocusing on an event without context

Signed-off-by: Johannes Marbach <[email protected]>
@Johennes Johennes force-pushed the johannes/focus-no-context branch from fa1bcaf to 93dc44a Compare November 12, 2025 08:48
@codecov
Copy link

codecov bot commented Nov 12, 2025

Codecov Report

❌ Patch coverage is 84.61538% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.64%. Comparing base (ec44c74) to head (37d56be).
⚠️ Report is 31 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...rates/matrix-sdk-ui/src/timeline/controller/mod.rs 84.61% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5858      +/-   ##
==========================================
- Coverage   88.65%   88.64%   -0.01%     
==========================================
  Files         362      362              
  Lines      103146   103163      +17     
  Branches   103146   103163      +17     
==========================================
+ Hits        91440    91446       +6     
- Misses       7458     7469      +11     
  Partials     4248     4248              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@Johennes Johennes marked this pull request as ready for review November 12, 2025 09:05
@Johennes Johennes requested a review from a team as a code owner November 12, 2025 09:05
@Johennes Johennes requested review from andybalaam and removed request for a team November 12, 2025 09:05
@Hywan Hywan requested review from Hywan and stefanceriu and removed request for andybalaam November 12, 2025 09:28
Comment on lines 478 to 508
let events = if *num_context_events == 0 {
// If no context is requested, try to load the event from the cache first and
// include common relations such as reactions and edits.
let request_config = Some(RequestConfig::default().retry_limit(3));
let relations_filter =
Some(vec![RelationType::Annotation, RelationType::Replacement]);

// Load the event from the cache or, failing that, the server.
match self
.room_data_provider
.load_event_with_relations(event_id, request_config, relations_filter)
.await
{
Ok((event, related_events)) => {
let mut events = vec![event];
events.extend(related_events);
events
}
Err(err) => {
warn!("error when loading focussed event: {err}");
vec![]
}
}
} else {
// Start a /context request to load the focussed event and surrounding events.
let start_from_result = event_paginator
.start_from(event_id, (*num_context_events).into())
.await
.map_err(PaginationError::Paginator)?;
start_from_result.events
};
Copy link
Contributor Author

@Johennes Johennes Nov 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A potential issue I'm now seeing is that the if branch will leave the paginator in initial state meaning you cannot use it to extend the timeline later. This isn't really an issue for the intended event details use case but might still be problematic. Maybe this is further reason to extend TimelineFocus::PinnedEvents rather than TimelineFocus::Event? We could just add a different loader type that loads a single event only based on a specified ID.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it related to my feedback about falling back to /context if the if branch fails?

Copy link
Contributor Author

@Johennes Johennes Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think partially. If the if branch does not fail, we'd still leave the paginator in initial state with the current implementation though. This might be ok, however, since pagination doesn't seem like a likely use case when loading no context at all.

Copy link
Member

@Hywan Hywan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Can you add a test when num_context_events = 0 to test the new code please?

Comment on lines 478 to 508
let events = if *num_context_events == 0 {
// If no context is requested, try to load the event from the cache first and
// include common relations such as reactions and edits.
let request_config = Some(RequestConfig::default().retry_limit(3));
let relations_filter =
Some(vec![RelationType::Annotation, RelationType::Replacement]);

// Load the event from the cache or, failing that, the server.
match self
.room_data_provider
.load_event_with_relations(event_id, request_config, relations_filter)
.await
{
Ok((event, related_events)) => {
let mut events = vec![event];
events.extend(related_events);
events
}
Err(err) => {
warn!("error when loading focussed event: {err}");
vec![]
}
}
} else {
// Start a /context request to load the focussed event and surrounding events.
let start_from_result = event_paginator
.start_from(event_id, (*num_context_events).into())
.await
.map_err(PaginationError::Paginator)?;
start_from_result.events
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it related to my feedback about falling back to /context if the if branch fails?

… when focusing on an event without context

Switch to error and fallback to /context when loading single event fails

Signed-off-by: Johannes Marbach <[email protected]>
… when focusing on an event without context

Add tests with num_context_events = 0

Signed-off-by: Johannes Marbach <[email protected]>
@Johennes
Copy link
Contributor Author

Johennes commented Nov 25, 2025

Can you add a test when num_context_events = 0 to test the new code please?

Have added two tests with e27d0d5 / 37d56be.

… when focusing on an event without context

Use different event ID to work around spurious test failure

Signed-off-by: Johannes Marbach <[email protected]>
@Johennes Johennes requested a review from Hywan November 25, 2025 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants