Commit 93d4735d70cf
tarball2 files changed+80-1
@@ -914,6 +914,9 @@ impl Service {
914914
};915915
resolve_replies(std::iter::once(&mut **event), &targets);916916
}917
+ if let Some(saved) = data.events.get(&identity) {918
+ improve(&mut item, &saved.item);919
+ }917920
self.supplement(data, &key, &item, &media, &value);918921
let (reasons, suppressed, unresolved) = self.classify(data, room_id, &value).await;919922
if unresolved {@@ -1680,7 +1683,8 @@ fn retry_at(error: &Error, fallback_ms: u64) -> u64 {
16801683
}16811684
16821685
/// the capture fetched what observing at sync time couldn't, so its profile and reply win1683
-/// over the saved ones, while the saved content keeps its own edits and redactions1686
+/// over the saved ones, while the saved content keeps its own edits and redactions. observing1687
+/// again calls it the other way round, or every sync in the room wipes the profile16841688
fn improve(saved: &mut TimelineItem, captured: &TimelineItem) {16851689
let (TimelineItem::Event(saved), TimelineItem::Event(captured)) = (saved, captured) else {16861690
return;@@ -696,3 +696,78 @@ async fn explicit_recovery_rechecks_server_support() {
696696
assert!(service.data.coverage.recovering);697697
assert_eq!(service.recovery_budget, 20);698698
}699
+700
+#[tokio::test]701
+async fn observing_again_keeps_the_profiles_a_capture_fetched() {702
+ let server = MatrixMockServer::new().await;703
+ let room_id = room_id!("!mentions:localhost");704
+ let (client, own_user) = joined_client(&server, room_id).await;705
+ let raw = |event: matrix_sdk::ruma::serde::Raw<_>, timestamp: u64| {706
+ let mut value: serde_json::Value = serde_json::from_str(event.json().get()).unwrap();707
+ value["origin_server_ts"] = json!(timestamp);708
+ value709
+ };710
+ let factory = EventFactory::new().room(room_id).sender(user_id!("@bob:localhost"));711
+ let mention = raw(712
+ factory713
+ .text_msg("ping")714
+ .mentions(Mentions::with_user_ids([own_user]))715
+ .event_id(event_id!("$ping:localhost"))716
+ .into_raw_sync(),717
+ 10,718
+ );719
+ let following = raw(720
+ factory721
+ .text_msg("following")722
+ .event_id(event_id!("$following:localhost"))723
+ .into_raw_sync(),724
+ 11,725
+ );726
+ let service = service(&client, None).await;727
+ let room_id = room_id.to_owned();728
+ let mut data = Data::default();729
+ service.observe(&mut data, &room_id, mention.clone()).await;730
+ let ping = format!("{room_id}\n$ping:localhost");731
+ let following_id = format!("{room_id}\n$following:localhost");732
+733
+ let profiled = |item: &TimelineItem| {734
+ let mut item = item.clone();735
+ if let TimelineItem::Event(event) = &mut item {736
+ event.sender.display_name = Some("Bob".to_owned());737
+ }738
+ item739
+ };740
+ let target = profiled(&data.entries[&ping].event);741
+ let mut neighbour = normalise_observed(&following, None, &following_id).unwrap().0;742
+ neighbour = profiled(&neighbour);743
+ let revision = data.entries[&ping].revision;744
+ service.captured(745
+ &mut data,746
+ ping.clone(),747
+ revision,748
+ Ok((749
+ crate::EventContext {750
+ events_before: Vec::new(),751
+ event: target,752
+ events_after: vec![neighbour],753
+ start_token: None,754
+ end_token: None,755
+ },756
+ Vec::new(),757
+ Vec::new(),758
+ )),759
+ );760
+ let capture = data.entries[&ping].capture.clone();761
+762
+ service.observe(&mut data, &room_id, following).await;763
+ service.observe(&mut data, &room_id, mention).await;764
+765
+ let name = |item: &TimelineItem| match item {766
+ TimelineItem::Event(event) => event.sender.display_name.clone(),767
+ _ => None,768
+ };769
+ assert_eq!(name(&data.entries[&ping].event).as_deref(), Some("Bob"));770
+ assert_eq!(name(&data.events[&ping].item).as_deref(), Some("Bob"));771
+ assert_eq!(name(&data.events[&following_id].item).as_deref(), Some("Bob"));772
+ assert_eq!(data.entries[&ping].capture, capture);773
+}