@@ -23,6 +23,7 @@ use imbl::Vector;
2323#[ cfg( test) ]
2424use matrix_sdk:: Result ;
2525use matrix_sdk:: {
26+ config:: RequestConfig ,
2627 deserialized_responses:: TimelineEvent ,
2728 event_cache:: { RoomEventCache , RoomPaginationStatus } ,
2829 paginators:: { PaginationResult , PaginationToken , Paginator } ,
@@ -41,7 +42,7 @@ use ruma::{
4142 poll:: unstable_start:: UnstablePollStartEventContent ,
4243 reaction:: ReactionEventContent ,
4344 receipt:: { Receipt , ReceiptThread , ReceiptType } ,
44- relation:: Annotation ,
45+ relation:: { Annotation , RelationType } ,
4546 room:: message:: { MessageType , Relation } ,
4647 } ,
4748 room_version_rules:: RoomVersionRules ,
@@ -474,16 +475,40 @@ impl<P: RoomDataProvider> TimelineController<P> {
474475
475476 let event_paginator = Paginator :: new ( self . room_data_provider . clone ( ) ) ;
476477
477- // Start a /context request so we can know if the event is in a thread or not,
478- // and know which kind of pagination we'll be using then.
479- let start_from_result = event_paginator
480- . start_from ( event_id, ( * num_context_events) . into ( ) )
481- . await
482- . map_err ( PaginationError :: Paginator ) ?;
478+ let events = if * num_context_events == 0 {
479+ // If no context is requested, try to load the event from the cache first and
480+ // include common relations such as reactions and edits.
481+ let request_config = Some ( RequestConfig :: default ( ) . retry_limit ( 3 ) ) ;
482+ let relations_filter =
483+ Some ( vec ! [ RelationType :: Annotation , RelationType :: Replacement ] ) ;
484+
485+ // Load the event from the cache or, failing that, the server.
486+ match self
487+ . room_data_provider
488+ . load_event_with_relations ( event_id, request_config, relations_filter)
489+ . await
490+ {
491+ Ok ( ( event, related_events) ) => {
492+ let mut events = vec ! [ event] ;
493+ events. extend ( related_events) ;
494+ events
495+ }
496+ Err ( err) => {
497+ warn ! ( "error when loading focussed event: {err}" ) ;
498+ vec ! [ ]
499+ }
500+ }
501+ } else {
502+ // Start a /context request to load the focussed event and surrounding events.
503+ let start_from_result = event_paginator
504+ . start_from ( event_id, ( * num_context_events) . into ( ) )
505+ . await
506+ . map_err ( PaginationError :: Paginator ) ?;
507+ start_from_result. events
508+ } ;
483509
484510 // Find the target event, and see if it's part of a thread.
485- let thread_root_event_id = start_from_result
486- . events
511+ let thread_root_event_id = events
487512 . iter ( )
488513 . find (
489514 |event| {
@@ -499,7 +524,7 @@ impl<P: RoomDataProvider> TimelineController<P> {
499524 // Look if the thread root event is part of the /context response. This
500525 // allows us to spare some backwards pagination with
501526 // /relations.
502- let includes_root_event = start_from_result . events . iter ( ) . any ( |event| {
527+ let includes_root_event = events. iter ( ) . any ( |event| {
503528 if let Some ( id) = event. event_id ( ) { id == root_id } else { false }
504529 } ) ;
505530
@@ -522,8 +547,7 @@ impl<P: RoomDataProvider> TimelineController<P> {
522547 } ,
523548 } ) ;
524549
525- let has_events = !start_from_result. events . is_empty ( ) ;
526- let events = start_from_result. events ;
550+ let has_events = !events. is_empty ( ) ;
527551
528552 match paginator. get ( ) . expect ( "Paginator was not instantiated" ) {
529553 AnyPaginator :: Unthreaded { .. } => {
0 commit comments