ui: Move timeline-internal traits into separate module
This commit is contained in:
parent
7552f4f72a
commit
2bcc70beb9
|
@ -60,7 +60,7 @@ use tracing::{debug, error};
|
|||
|
||||
use super::{EventTimelineItem, Profile, TimelineDetails};
|
||||
use crate::timeline::{
|
||||
inner::RoomDataProvider, Error as TimelineError, TimelineItem, DEFAULT_SANITIZER_MODE,
|
||||
traits::RoomDataProvider, Error as TimelineError, TimelineItem, DEFAULT_SANITIZER_MODE,
|
||||
};
|
||||
|
||||
/// The content of an [`EventTimelineItem`][super::EventTimelineItem].
|
||||
|
|
|
@ -16,12 +16,11 @@
|
|||
use std::collections::BTreeSet;
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use eyeball_im::{ObservableVector, VectorSubscriber};
|
||||
#[cfg(feature = "testing")]
|
||||
use eyeball_im_util::{FilterMapVectorSubscriber, VectorExt};
|
||||
use imbl::Vector;
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
use indexmap::IndexSet;
|
||||
#[cfg(all(test, feature = "e2e-encryption"))]
|
||||
use matrix_sdk::crypto::OlmMachine;
|
||||
use matrix_sdk::{
|
||||
|
@ -41,10 +40,8 @@ use ruma::{
|
|||
receipt::{Receipt, ReceiptThread, ReceiptType},
|
||||
relation::Annotation,
|
||||
AnyMessageLikeEventContent, AnyRoomAccountDataEvent, AnySyncEphemeralRoomEvent,
|
||||
AnySyncTimelineEvent,
|
||||
},
|
||||
push::{Action, PushConditionRoomCtx, Ruleset},
|
||||
serde::Raw,
|
||||
push::Action,
|
||||
EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, OwnedUserId,
|
||||
TransactionId, UserId,
|
||||
};
|
||||
|
@ -53,15 +50,18 @@ use tracing::{debug, error, field::debug, info, instrument, trace, warn};
|
|||
#[cfg(feature = "e2e-encryption")]
|
||||
use tracing::{field, info_span, Instrument as _};
|
||||
|
||||
#[cfg(feature = "e2e-encryption")]
|
||||
use super::traits::Decryptor;
|
||||
use super::{
|
||||
compare_events_positions,
|
||||
event_handler::{
|
||||
update_read_marker, Flow, HandleEventResult, TimelineEventHandler, TimelineEventKind,
|
||||
TimelineEventMetadata, TimelineItemPosition,
|
||||
},
|
||||
rfind_event_by_id, rfind_event_item, EventSendState, EventTimelineItem, InReplyToDetails,
|
||||
Message, Profile, RelativePosition, RepliedToEvent, TimelineDetails, TimelineItem,
|
||||
TimelineItemContent,
|
||||
rfind_event_by_id, rfind_event_item,
|
||||
traits::RoomDataProvider,
|
||||
EventSendState, EventTimelineItem, InReplyToDetails, Message, Profile, RelativePosition,
|
||||
RepliedToEvent, TimelineDetails, TimelineItem, TimelineItemContent,
|
||||
};
|
||||
use crate::events::SyncTimelineEventWithoutContent;
|
||||
|
||||
|
@ -928,92 +928,3 @@ async fn fetch_replied_to_event(
|
|||
};
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub(super) trait RoomDataProvider {
|
||||
fn own_user_id(&self) -> &UserId;
|
||||
async fn profile(&self, user_id: &UserId) -> Option<Profile>;
|
||||
async fn read_receipts_for_event(&self, event_id: &EventId) -> IndexMap<OwnedUserId, Receipt>;
|
||||
async fn push_rules_and_context(&self) -> Option<(Ruleset, PushConditionRoomCtx)>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl RoomDataProvider for room::Common {
|
||||
fn own_user_id(&self) -> &UserId {
|
||||
(**self).own_user_id()
|
||||
}
|
||||
|
||||
async fn profile(&self, user_id: &UserId) -> Option<Profile> {
|
||||
match self.get_member_no_sync(user_id).await {
|
||||
Ok(Some(member)) => Some(Profile {
|
||||
display_name: member.display_name().map(ToOwned::to_owned),
|
||||
display_name_ambiguous: member.name_ambiguous(),
|
||||
avatar_url: member.avatar_url().map(ToOwned::to_owned),
|
||||
}),
|
||||
Ok(None) if self.are_members_synced() => Some(Profile {
|
||||
display_name: None,
|
||||
display_name_ambiguous: false,
|
||||
avatar_url: None,
|
||||
}),
|
||||
Ok(None) => None,
|
||||
Err(e) => {
|
||||
error!(%user_id, "Failed to getch room member information: {e}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_receipts_for_event(&self, event_id: &EventId) -> IndexMap<OwnedUserId, Receipt> {
|
||||
match self.event_receipts(ReceiptType::Read, ReceiptThread::Unthreaded, event_id).await {
|
||||
Ok(receipts) => receipts.into_iter().collect(),
|
||||
Err(e) => {
|
||||
error!(?event_id, "Failed to get read receipts for event: {e}");
|
||||
IndexMap::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn push_rules_and_context(&self) -> Option<(Ruleset, PushConditionRoomCtx)> {
|
||||
match self.push_context().await {
|
||||
Ok(Some(push_context)) => match self.client().account().push_rules().await {
|
||||
Ok(push_rules) => Some((push_rules, push_context)),
|
||||
Err(e) => {
|
||||
error!("Could not get push rules: {e}");
|
||||
None
|
||||
}
|
||||
},
|
||||
Ok(None) => {
|
||||
debug!("Could not aggregate push context");
|
||||
None
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Could not get push context: {e}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Internal helper to make most of retry_event_decryption independent of a room
|
||||
// object, which is annoying to create for testing and not really needed
|
||||
#[async_trait]
|
||||
trait Decryptor: Copy {
|
||||
async fn decrypt_event_impl(&self, raw: &Raw<AnySyncTimelineEvent>) -> Result<TimelineEvent>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Decryptor for &room::Common {
|
||||
async fn decrypt_event_impl(&self, raw: &Raw<AnySyncTimelineEvent>) -> Result<TimelineEvent> {
|
||||
self.decrypt_event(raw.cast_ref()).await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, feature = "e2e-encryption"))]
|
||||
#[async_trait]
|
||||
impl Decryptor for (&OlmMachine, &RoomId) {
|
||||
async fn decrypt_event_impl(&self, raw: &Raw<AnySyncTimelineEvent>) -> Result<TimelineEvent> {
|
||||
let (olm_machine, room_id) = self;
|
||||
let event = olm_machine.decrypt_room_event(raw.cast_ref(), room_id).await?;
|
||||
Ok(event)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ mod sliding_sync_ext;
|
|||
mod tests;
|
||||
#[cfg(feature = "e2e-encryption")]
|
||||
mod to_device;
|
||||
mod traits;
|
||||
mod virtual_item;
|
||||
|
||||
pub(crate) use self::builder::TimelineBuilder;
|
||||
|
|
|
@ -24,10 +24,8 @@ use ruma::{
|
|||
use tracing::{error, warn};
|
||||
|
||||
use super::{
|
||||
compare_events_positions,
|
||||
event_item::EventTimelineItemKind,
|
||||
inner::{RoomDataProvider, TimelineInnerState},
|
||||
rfind_event_by_id, EventTimelineItem, RelativePosition, TimelineItem,
|
||||
compare_events_positions, event_item::EventTimelineItemKind, inner::TimelineInnerState,
|
||||
rfind_event_by_id, traits::RoomDataProvider, EventTimelineItem, RelativePosition, TimelineItem,
|
||||
};
|
||||
|
||||
struct FullReceipt<'a> {
|
||||
|
|
|
@ -45,7 +45,7 @@ use ruma::{
|
|||
};
|
||||
use serde_json::{json, Value as JsonValue};
|
||||
|
||||
use super::{inner::RoomDataProvider, Profile, TimelineInner, TimelineItem};
|
||||
use super::{traits::RoomDataProvider, Profile, TimelineInner, TimelineItem};
|
||||
|
||||
mod basic;
|
||||
mod echo;
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
// Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use async_trait::async_trait;
|
||||
use indexmap::IndexMap;
|
||||
use matrix_sdk::room;
|
||||
#[cfg(feature = "e2e-encryption")]
|
||||
use matrix_sdk::{deserialized_responses::TimelineEvent, Result};
|
||||
use ruma::{
|
||||
events::receipt::{Receipt, ReceiptThread, ReceiptType},
|
||||
push::{PushConditionRoomCtx, Ruleset},
|
||||
EventId, OwnedUserId, UserId,
|
||||
};
|
||||
#[cfg(feature = "e2e-encryption")]
|
||||
use ruma::{events::AnySyncTimelineEvent, serde::Raw};
|
||||
use tracing::{debug, error};
|
||||
|
||||
use super::Profile;
|
||||
|
||||
#[async_trait]
|
||||
pub(super) trait RoomDataProvider {
|
||||
fn own_user_id(&self) -> &UserId;
|
||||
async fn profile(&self, user_id: &UserId) -> Option<Profile>;
|
||||
async fn read_receipts_for_event(&self, event_id: &EventId) -> IndexMap<OwnedUserId, Receipt>;
|
||||
async fn push_rules_and_context(&self) -> Option<(Ruleset, PushConditionRoomCtx)>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl RoomDataProvider for room::Common {
|
||||
fn own_user_id(&self) -> &UserId {
|
||||
(**self).own_user_id()
|
||||
}
|
||||
|
||||
async fn profile(&self, user_id: &UserId) -> Option<Profile> {
|
||||
match self.get_member_no_sync(user_id).await {
|
||||
Ok(Some(member)) => Some(Profile {
|
||||
display_name: member.display_name().map(ToOwned::to_owned),
|
||||
display_name_ambiguous: member.name_ambiguous(),
|
||||
avatar_url: member.avatar_url().map(ToOwned::to_owned),
|
||||
}),
|
||||
Ok(None) if self.are_members_synced() => Some(Profile {
|
||||
display_name: None,
|
||||
display_name_ambiguous: false,
|
||||
avatar_url: None,
|
||||
}),
|
||||
Ok(None) => None,
|
||||
Err(e) => {
|
||||
error!(%user_id, "Failed to getch room member information: {e}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_receipts_for_event(&self, event_id: &EventId) -> IndexMap<OwnedUserId, Receipt> {
|
||||
match self.event_receipts(ReceiptType::Read, ReceiptThread::Unthreaded, event_id).await {
|
||||
Ok(receipts) => receipts.into_iter().collect(),
|
||||
Err(e) => {
|
||||
error!(?event_id, "Failed to get read receipts for event: {e}");
|
||||
IndexMap::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn push_rules_and_context(&self) -> Option<(Ruleset, PushConditionRoomCtx)> {
|
||||
match self.push_context().await {
|
||||
Ok(Some(push_context)) => match self.client().account().push_rules().await {
|
||||
Ok(push_rules) => Some((push_rules, push_context)),
|
||||
Err(e) => {
|
||||
error!("Could not get push rules: {e}");
|
||||
None
|
||||
}
|
||||
},
|
||||
Ok(None) => {
|
||||
debug!("Could not aggregate push context");
|
||||
None
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Could not get push context: {e}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Internal helper to make most of retry_event_decryption independent of a room
|
||||
// object, which is annoying to create for testing and not really needed
|
||||
#[cfg(feature = "e2e-encryption")]
|
||||
#[async_trait]
|
||||
pub(super) trait Decryptor: Copy {
|
||||
async fn decrypt_event_impl(&self, raw: &Raw<AnySyncTimelineEvent>) -> Result<TimelineEvent>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "e2e-encryption")]
|
||||
#[async_trait]
|
||||
impl Decryptor for &room::Common {
|
||||
async fn decrypt_event_impl(&self, raw: &Raw<AnySyncTimelineEvent>) -> Result<TimelineEvent> {
|
||||
self.decrypt_event(raw.cast_ref()).await
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(test, feature = "e2e-encryption"))]
|
||||
#[async_trait]
|
||||
impl Decryptor for (&matrix_sdk_base::crypto::OlmMachine, &ruma::RoomId) {
|
||||
async fn decrypt_event_impl(&self, raw: &Raw<AnySyncTimelineEvent>) -> Result<TimelineEvent> {
|
||||
let (olm_machine, room_id) = self;
|
||||
let event = olm_machine.decrypt_room_event(raw.cast_ref(), room_id).await?;
|
||||
Ok(event)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue