mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-12 01:45:29 -04:00
ui: Add Timeline::retry_send
This commit is contained in:
committed by
Jonas Platte
parent
f1e62b0bb8
commit
df7beb4afd
@@ -18,11 +18,13 @@ use imbl::{vector, Vector};
|
||||
use indexmap::IndexMap;
|
||||
use matrix_sdk::{deserialized_responses::TimelineEvent, Result};
|
||||
use ruma::{
|
||||
assign,
|
||||
events::{
|
||||
policy::rule::{
|
||||
room::PolicyRuleRoomEventContent, server::PolicyRuleServerEventContent,
|
||||
user::PolicyRuleUserEventContent,
|
||||
},
|
||||
relation::InReplyTo,
|
||||
room::{
|
||||
aliases::RoomAliasesEventContent,
|
||||
avatar::RoomAvatarEventContent,
|
||||
@@ -232,6 +234,15 @@ impl Message {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Message> for RoomMessageEventContent {
|
||||
fn from(msg: Message) -> Self {
|
||||
let relates_to = msg.in_reply_to.map(|details| message::Relation::Reply {
|
||||
in_reply_to: InReplyTo::new(details.event_id),
|
||||
});
|
||||
assign!(Self::new(msg.msgtype), { relates_to })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(tarpaulin_include))]
|
||||
impl fmt::Debug for Message {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
||||
@@ -321,6 +321,30 @@ impl<P: RoomDataProvider> TimelineInner<P> {
|
||||
state.items.set(idx, Arc::new(new_item));
|
||||
}
|
||||
|
||||
pub(super) async fn prepare_retry(
|
||||
&self,
|
||||
txn_id: &TransactionId,
|
||||
) -> Option<TimelineItemContent> {
|
||||
let mut state = self.state.lock().await;
|
||||
|
||||
let (idx, item) = rfind_event_item(&state.items, |it| it.transaction_id() == Some(txn_id))?;
|
||||
let local_item = item.as_local()?;
|
||||
|
||||
if !matches!(&local_item.send_state, EventSendState::SendingFailed { .. }) {
|
||||
debug!("Attempted to retry sending of an item that is not in failed state");
|
||||
return None;
|
||||
}
|
||||
|
||||
let new_item = TimelineItem::Event(
|
||||
item.with_kind(local_item.with_send_state(EventSendState::NotSentYet)),
|
||||
);
|
||||
|
||||
let content = item.content.clone();
|
||||
state.items.set(idx, Arc::new(new_item));
|
||||
|
||||
Some(content)
|
||||
}
|
||||
|
||||
/// Handle a back-paginated event.
|
||||
///
|
||||
/// Returns the number of timeline updates that were made.
|
||||
|
||||
@@ -334,6 +334,67 @@ impl Timeline {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retry sending a message that previously failed to send.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `txn_id` - The transaction ID of a local echo timeline item that has a
|
||||
/// `send_state()` of `SendState::FailedToSend { .. }`
|
||||
pub async fn retry_send(&self, txn_id: &TransactionId) -> Result<(), Error> {
|
||||
macro_rules! error_return {
|
||||
($msg:literal) => {{
|
||||
error!($msg);
|
||||
return Ok(());
|
||||
}};
|
||||
}
|
||||
|
||||
let item = self.inner.prepare_retry(txn_id).await.ok_or(Error::RetryEventNotInTimeline)?;
|
||||
let content = match item {
|
||||
TimelineItemContent::Message(msg) => {
|
||||
AnyMessageLikeEventContent::RoomMessage(msg.into())
|
||||
}
|
||||
TimelineItemContent::RedactedMessage => {
|
||||
error_return!("Invalid state: attempting to retry a redacted message");
|
||||
}
|
||||
TimelineItemContent::Sticker(sticker) => {
|
||||
AnyMessageLikeEventContent::Sticker(sticker.content)
|
||||
}
|
||||
TimelineItemContent::UnableToDecrypt(_) => {
|
||||
error_return!("Invalid state: attempting to retry a UTD item");
|
||||
}
|
||||
TimelineItemContent::MembershipChange(_)
|
||||
| TimelineItemContent::ProfileChange(_)
|
||||
| TimelineItemContent::OtherState(_) => {
|
||||
error_return!("Retrying state events is not currently supported");
|
||||
}
|
||||
TimelineItemContent::FailedToParseMessageLike { .. }
|
||||
| TimelineItemContent::FailedToParseState { .. } => {
|
||||
error_return!("Invalid state: attempting to retry a failed-to-parse item");
|
||||
}
|
||||
};
|
||||
|
||||
let send_state = match Room::from(self.room().clone()) {
|
||||
Room::Joined(room) => {
|
||||
let response = room.send(content, Some(txn_id)).await;
|
||||
|
||||
match response {
|
||||
Ok(response) => EventSendState::Sent { event_id: response.event_id },
|
||||
Err(error) => EventSendState::SendingFailed { error: Arc::new(error) },
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
EventSendState::SendingFailed {
|
||||
// FIXME: Probably not exactly right
|
||||
error: Arc::new(matrix_sdk::Error::InconsistentState),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.inner.update_event_send_state(txn_id, send_state).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Fetch unavailable details about the event with the given ID.
|
||||
///
|
||||
/// This method only works for IDs of remote [`EventTimelineItem`]s,
|
||||
@@ -629,6 +690,10 @@ pub enum Error {
|
||||
#[error("Event with remote echo not found in timeline")]
|
||||
RemoteEventNotInTimeline,
|
||||
|
||||
/// Can't find an event with the given transaction ID, can't retry.
|
||||
#[error("Event not found, can't retry sending")]
|
||||
RetryEventNotInTimeline,
|
||||
|
||||
/// The event is currently unsupported for this use case.
|
||||
#[error("Unsupported event")]
|
||||
UnsupportedEvent,
|
||||
|
||||
Reference in New Issue
Block a user