Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
bnjbvr committed Aug 26, 2024
1 parent 64cae16 commit 6611815
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 20 deletions.
6 changes: 5 additions & 1 deletion crates/matrix-sdk-ui/src/timeline/event_item/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use as_variant::as_variant;
use indexmap::IndexMap;
use matrix_sdk::{
deserialized_responses::{EncryptionInfo, ShieldState},
send_queue::SendHandle,
send_queue::{SendHandle, SendReactionHandle},
Client, Error,
};
use matrix_sdk_base::{
Expand Down Expand Up @@ -625,6 +625,10 @@ pub enum EventItemOrigin {
/// What's the status of a reaction?
#[derive(Clone, Debug)]
pub enum ReactionStatus {
/// It's a local reaction to a local echo.
///
/// The handle is missing only in testing contexts.
LocalToLocal(Option<SendReactionHandle>),
/// It's a local reaction to a remote event.
///
/// The handle is missing only in testing contexts.
Expand Down
75 changes: 57 additions & 18 deletions crates/matrix-sdk-ui/src/timeline/inner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ use matrix_sdk::crypto::OlmMachine;
use matrix_sdk::{
deserialized_responses::SyncTimelineEvent,
event_cache::{paginator::Paginator, RoomEventCache},
send_queue::{LocalEcho, LocalEchoContent, RoomSendQueueUpdate, SendHandle},
send_queue::{
LocalEcho, LocalEchoContent, RoomSendQueueUpdate, SendHandle, SendReactionHandle,
},
Result, Room,
};
#[cfg(test)]
Expand All @@ -45,7 +47,8 @@ use ruma::{
AnySyncTimelineEvent, MessageLikeEventType,
},
serde::Raw,
EventId, OwnedEventId, OwnedTransactionId, RoomVersionId, TransactionId, UserId,
EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedTransactionId, RoomVersionId,
TransactionId, UserId,
};
use tokio::sync::{RwLock, RwLockWriteGuard};
use tracing::{debug, error, field::debug, info, instrument, trace, warn};
Expand All @@ -64,8 +67,8 @@ use super::{
traits::RoomDataProvider,
util::{rfind_event_by_id, rfind_event_item, RelativePosition},
Error, EventSendState, EventTimelineItem, InReplyToDetails, Message, PaginationError, Profile,
RepliedToEvent, TimelineDetails, TimelineEventItemId, TimelineFocus, TimelineItem,
TimelineItemContent, TimelineItemKind,
ReactionInfo, RepliedToEvent, TimelineDetails, TimelineEventItemId, TimelineFocus,
TimelineItem, TimelineItemContent, TimelineItemKind,
};
use crate::{
timeline::{
Expand Down Expand Up @@ -478,19 +481,24 @@ impl<P: RoomDataProvider> TimelineInner<P> {

trace!("removing a previous reaction");
match prev_status {
ReactionStatus::LocalToRemote(send_handle) => {
// No need to keep the lock.
drop(state);
ReactionStatus::LocalToLocal(send_reaction_handle) => {
if let Some(handle) = send_reaction_handle {
if !handle.abort().await.map_err(|err| Error::SendQueueError(err.into()))? {
// Impossible state: the reaction has moved from local to echo under our
// feet, but the timeline was supposed to be locked!
warn!("unexpectedly unable to abort sending of local reaction");
}
} else {
warn!("no send reaction handle (this should only happen in testing contexts)");
}
}

ReactionStatus::LocalToRemote(send_handle) => {
// No need to reflect the change ourselves, since handling the discard of the
// local echo will take care of it.
trace!("aborting send of the previous reaction that was a local echo");
if let Some(send_handle) = send_handle {
if !send_handle
.abort()
.await
.map_err(|err| Error::SendQueueError(err.into()))?
{
if let Some(handle) = send_handle {
if !handle.abort().await.map_err(|err| Error::SendQueueError(err.into()))? {
// Impossible state: the reaction has moved from local to echo under our
// feet, but the timeline was supposed to be locked!
warn!("unexpectedly unable to abort sending of local reaction");
Expand Down Expand Up @@ -790,10 +798,8 @@ impl<P: RoomDataProvider> TimelineInner<P> {
state.meta.reactions.map.remove(&TimelineEventItemId::TransactionId(txn_id.to_owned()))
{
let item = match &full_key.item {
TimelineEventItemId::TransactionId(_) => {
// TODO(bnjbvr): reactions on local echoes
warn!("reactions on local echoes are NYI");
return false;
TimelineEventItemId::TransactionId(txn_id) => {
rfind_event_item(&state.items, |item| item.transaction_id() == Some(&txn_id))
}
TimelineEventItemId::EventId(event_id) => rfind_event_by_id(&state.items, event_id),
};
Expand Down Expand Up @@ -1181,11 +1187,44 @@ impl<P: RoomDataProvider> TimelineInner<P> {
}

LocalEchoContent::React { key, send_handle, applies_to } => {
todo!();
self.handle_local_reaction(key, send_handle, applies_to).await;
}
}
}

/// Adds a reaction (local echo) to a local echo.
#[instrument(skip(self, send_handle))]
async fn handle_local_reaction(
&self,
reaction_key: String,
send_handle: SendReactionHandle,
applies_to: OwnedTransactionId,
) {
let mut state = self.state.write().await;

let Some((item_pos, item)) =
rfind_event_item(&state.items, |item| item.transaction_id() == Some(&applies_to))
else {
warn!("Local item not found anymore.");
return;
};

let user_id = self.room_data_provider.own_user_id();

let reaction_info = ReactionInfo {
timestamp: MilliSecondsSinceUnixEpoch::now(),
status: ReactionStatus::LocalToLocal(Some(send_handle)),
};

let mut reactions = item.reactions().clone();
let by_user = reactions.entry(reaction_key).or_default();
by_user.insert(user_id.to_owned(), reaction_info);

trace!("Adding local reaction to local echo");
let new_item = item.with_reactions(reactions);
state.items.set(item_pos, new_item);
}

/// Handle a single room send queue update.
pub(crate) async fn handle_room_send_queue_update(&self, update: RoomSendQueueUpdate) {
match update {
Expand Down
4 changes: 3 additions & 1 deletion crates/matrix-sdk-ui/src/timeline/tests/reactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ macro_rules! assert_reaction_is_updated {
let reactions = event.reactions().get(&REACTION_KEY.to_owned()).unwrap();
let reaction = reactions.get(*ALICE).unwrap();
match reaction.status {
ReactionStatus::LocalToRemote(_) => assert!(!$is_remote_echo),
ReactionStatus::LocalToRemote(_) | ReactionStatus::LocalToLocal(_) => {
assert!(!$is_remote_echo)
}
ReactionStatus::RemoteToRemote(_) => assert!($is_remote_echo),
};
event
Expand Down

0 comments on commit 6611815

Please sign in to comment.