Skip to content

Commit 6a82e29

Browse files
committed
feat(timeline): communicate media upload progress through EventSendState::NotSentYet
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
1 parent e4e2796 commit 6a82e29

File tree

16 files changed

+199
-67
lines changed

16 files changed

+199
-67
lines changed

crates/matrix-sdk-ui/src/timeline/controller/decryption_retry_task.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -627,7 +627,7 @@ mod tests {
627627

628628
fn local_event() -> Arc<TimelineItem> {
629629
let event_kind = EventTimelineItemKind::Local(LocalEventTimelineItem {
630-
send_state: EventSendState::NotSentYet,
630+
send_state: EventSendState::NotSentYet { progress: None },
631631
transaction_id: OwnedTransactionId::from("trans"),
632632
send_handle: None,
633633
});

crates/matrix-sdk-ui/src/timeline/controller/mod.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,9 @@ use super::{
6666
item::TimelineUniqueId,
6767
subscriber::TimelineSubscriber,
6868
traits::{Decryptor, RoomDataProvider},
69-
DateDividerMode, EmbeddedEvent, Error, EventSendState, EventTimelineItem, InReplyToDetails,
70-
PaginationError, Profile, TimelineDetails, TimelineEventItemId, TimelineFocus, TimelineItem,
71-
TimelineItemContent, TimelineItemKind, VirtualTimelineItem,
69+
DateDividerMode, EmbeddedEvent, Error, EventSendProgress, EventSendState, EventTimelineItem,
70+
InReplyToDetails, PaginationError, Profile, TimelineDetails, TimelineEventItemId,
71+
TimelineFocus, TimelineItem, TimelineItemContent, TimelineItemKind, VirtualTimelineItem,
7272
};
7373
use crate::{
7474
timeline::{
@@ -1031,7 +1031,7 @@ impl<P: RoomDataProvider, D: Decryptor> TimelineController<P, D> {
10311031
warn!("We looked for a local item, but it transitioned as remote??");
10321032
return false;
10331033
};
1034-
prev_local_item.with_send_state(EventSendState::NotSentYet)
1034+
prev_local_item.with_send_state(EventSendState::NotSentYet { progress: None })
10351035
};
10361036

10371037
// Replace the local-related state (kind) and the content state.
@@ -1309,17 +1309,26 @@ impl<P: RoomDataProvider, D: Decryptor> TimelineController<P, D> {
13091309
}
13101310

13111311
RoomSendQueueUpdate::RetryEvent { transaction_id } => {
1312-
self.update_event_send_state(&transaction_id, EventSendState::NotSentYet).await;
1312+
self.update_event_send_state(
1313+
&transaction_id,
1314+
EventSendState::NotSentYet { progress: None },
1315+
)
1316+
.await;
13131317
}
13141318

13151319
RoomSendQueueUpdate::SentEvent { transaction_id, event_id } => {
13161320
self.update_event_send_state(&transaction_id, EventSendState::Sent { event_id })
13171321
.await;
13181322
}
13191323

1320-
RoomSendQueueUpdate::MediaUpload { related_to, .. } => {
1321-
// TODO(bnjbvr): Do something else?
1322-
info!(txn_id = %related_to, "some media for a media event has been uploaded");
1324+
RoomSendQueueUpdate::MediaUpload { related_to, index, progress, .. } => {
1325+
self.update_event_send_state(
1326+
&related_to,
1327+
EventSendState::NotSentYet {
1328+
progress: Some(EventSendProgress::MediaUpload { index, progress }),
1329+
},
1330+
)
1331+
.await;
13231332
}
13241333
}
13251334
}

crates/matrix-sdk-ui/src/timeline/controller/observable_items.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ mod observable_items_tests {
784784
thread_summary: None,
785785
}),
786786
EventTimelineItemKind::Local(LocalEventTimelineItem {
787-
send_state: EventSendState::NotSentYet,
787+
send_state: EventSendState::NotSentYet { progress: None },
788788
transaction_id: transaction_id.into(),
789789
send_handle: None,
790790
}),

crates/matrix-sdk-ui/src/timeline/event_handler.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ impl<'a, 'o> TimelineEventHandler<'a, 'o> {
741741

742742
let kind: EventTimelineItemKind = match &self.ctx.flow {
743743
Flow::Local { txn_id, send_handle } => LocalEventTimelineItem {
744-
send_state: EventSendState::NotSentYet,
744+
send_state: EventSendState::NotSentYet { progress: None },
745745
transaction_id: txn_id.to_owned(),
746746
send_handle: send_handle.clone(),
747747
}

crates/matrix-sdk-ui/src/timeline/event_item/local.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use std::sync::Arc;
1616

1717
use as_variant::as_variant;
18-
use matrix_sdk::{send_queue::SendHandle, Error};
18+
use matrix_sdk::{send_queue::SendHandle, AbstractProgress, Error};
1919
use ruma::{EventId, OwnedEventId, OwnedTransactionId};
2020

2121
use super::TimelineEventItemId;
@@ -65,7 +65,10 @@ impl LocalEventTimelineItem {
6565
#[derive(Clone, Debug)]
6666
pub enum EventSendState {
6767
/// The local event has not been sent yet.
68-
NotSentYet,
68+
NotSentYet {
69+
/// The progress of the sending operation, if any is available.
70+
progress: Option<EventSendProgress>,
71+
},
6972
/// The local event has been sent to the server, but unsuccessfully: The
7073
/// sending has failed.
7174
SendingFailed {
@@ -84,3 +87,19 @@ pub enum EventSendState {
8487
event_id: OwnedEventId,
8588
},
8689
}
90+
91+
/// This type represents the "send progress" of a local event timeline item.
92+
#[derive(Clone, Debug)]
93+
pub enum EventSendProgress {
94+
/// A media (consisting of a file and possibly a thumbnail) is being
95+
/// uploaded.
96+
MediaUpload {
97+
/// The index of the media within the transaction. A file and its
98+
/// thumbnail share the same index.
99+
index: u64,
100+
101+
/// The combined upload progress across the file and, if existing, its
102+
/// thumbnail.
103+
progress: AbstractProgress,
104+
},
105+
}

crates/matrix-sdk-ui/src/timeline/event_item/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pub use self::{
5656
PollResult, PollState, RoomMembershipChange, RoomPinnedEventsChange, Sticker,
5757
ThreadSummary, TimelineItemContent,
5858
},
59-
local::EventSendState,
59+
local::{EventSendProgress, EventSendState},
6060
};
6161

6262
/// An item in the timeline that represents at least one event.

crates/matrix-sdk-ui/src/timeline/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ pub use self::{
9191
error::*,
9292
event_item::{
9393
AnyOtherFullStateEventContent, EmbeddedEvent, EncryptedMessage, EventItemOrigin,
94-
EventSendState, EventTimelineItem, InReplyToDetails, MemberProfileChange, MembershipChange,
95-
Message, MsgLikeContent, MsgLikeKind, OtherState, PollResult, PollState, Profile,
96-
ReactionInfo, ReactionStatus, ReactionsByKeyBySender, RoomMembershipChange,
97-
RoomPinnedEventsChange, Sticker, ThreadSummary, TimelineDetails, TimelineEventItemId,
98-
TimelineItemContent,
94+
EventSendProgress, EventSendState, EventTimelineItem, InReplyToDetails,
95+
MemberProfileChange, MembershipChange, Message, MsgLikeContent, MsgLikeKind, OtherState,
96+
PollResult, PollState, Profile, ReactionInfo, ReactionStatus, ReactionsByKeyBySender,
97+
RoomMembershipChange, RoomPinnedEventsChange, Sticker, ThreadSummary, TimelineDetails,
98+
TimelineEventItemId, TimelineItemContent,
9999
},
100100
event_type_filter::TimelineEventTypeFilter,
101101
item::{TimelineItem, TimelineItemKind, TimelineUniqueId},

crates/matrix-sdk-ui/src/timeline/tests/echo.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ async fn test_remote_echo_full_trip() {
5050
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
5151
let event_item = item.as_event().unwrap();
5252
assert!(event_item.is_local_echo());
53-
assert_matches!(event_item.send_state(), Some(EventSendState::NotSentYet));
53+
assert_matches!(
54+
event_item.send_state(),
55+
Some(EventSendState::NotSentYet { progress: None })
56+
);
5457
assert!(!event_item.can_be_replied_to());
5558
item.unique_id().to_owned()
5659
};
@@ -308,7 +311,7 @@ async fn test_no_reuse_of_counters() {
308311
let local_id = assert_next_matches_with_timeout!(stream, VectorDiff::PushBack { value: item } => {
309312
let event_item = item.as_event().unwrap();
310313
assert!(event_item.is_local_echo());
311-
assert_matches!(event_item.send_state(), Some(EventSendState::NotSentYet));
314+
assert_matches!(event_item.send_state(), Some(EventSendState::NotSentYet { progress: None }));
312315
assert!(!event_item.can_be_replied_to());
313316
item.unique_id().to_owned()
314317
});

crates/matrix-sdk-ui/tests/integration/timeline/echo.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ async fn test_echo() {
6868

6969
assert_let!(VectorDiff::PushBack { value: local_echo } = &timeline_updates[0]);
7070
let item = local_echo.as_event().unwrap();
71-
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet));
71+
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet { progress: None }));
7272
assert_let!(Some(msg) = item.content().as_message());
7373
assert_let!(MessageType::Text(text) = msg.msgtype());
7474
assert_eq!(text.body, "Hello, World!");
@@ -150,7 +150,7 @@ async fn test_retry_failed() {
150150

151151
// First, local echo is added.
152152
assert_next_matches!(timeline_stream, VectorDiff::PushBack { value } => {
153-
assert_matches!(value.send_state(), Some(EventSendState::NotSentYet));
153+
assert_matches!(value.send_state(), Some(EventSendState::NotSentYet { progress: None }));
154154
});
155155

156156
// Sending fails, because the error is a transient one that's recoverable,
@@ -216,7 +216,7 @@ async fn test_dedup_by_event_id_late() {
216216
// Timeline: [local echo]
217217
assert_let!(VectorDiff::PushBack { value: local_echo } = &timeline_updates[0]);
218218
let item = local_echo.as_event().unwrap();
219-
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet));
219+
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet { progress: None }));
220220

221221
// Timeline: [date-divider, local echo]
222222
assert_let!(VectorDiff::PushFront { value: date_divider } = &timeline_updates[1]);
@@ -283,7 +283,7 @@ async fn test_cancel_failed() {
283283

284284
// Local echo is added (immediately)
285285
assert_next_matches!(timeline_stream, VectorDiff::PushBack { value } => {
286-
assert_matches!(value.send_state(), Some(EventSendState::NotSentYet));
286+
assert_matches!(value.send_state(), Some(EventSendState::NotSentYet { progress: None }));
287287
});
288288

289289
// Sending fails, the mock server has no matching route

crates/matrix-sdk-ui/tests/integration/timeline/edit.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ async fn test_edit_local_echo() {
199199
let internal_id = item.unique_id();
200200

201201
let item = item.as_event().unwrap();
202-
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet));
202+
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet { progress: None }));
203203

204204
assert_let!(VectorDiff::PushFront { value: date_divider } = &timeline_updates[1]);
205205
assert!(date_divider.is_date_divider());
@@ -249,7 +249,7 @@ async fn test_edit_local_echo() {
249249
assert!(item.is_local_echo());
250250

251251
// The send state has been reset.
252-
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet));
252+
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet { progress: None }));
253253

254254
let edit_message = item.content().as_message().unwrap();
255255
assert_eq!(edit_message.body(), "hello, world");
@@ -635,7 +635,7 @@ async fn test_edit_local_echo_with_unsupported_content() {
635635
assert_let!(VectorDiff::PushBack { value: item } = &timeline_updates[0]);
636636

637637
let item = item.as_event().unwrap();
638-
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet));
638+
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet { progress: None }));
639639

640640
assert_let!(VectorDiff::PushFront { value: date_divider } = &timeline_updates[1]);
641641
assert!(date_divider.is_date_divider());
@@ -689,7 +689,7 @@ async fn test_edit_local_echo_with_unsupported_content() {
689689
assert_let!(VectorDiff::PushBack { value: item } = &timeline_updates[0]);
690690

691691
let item = item.as_event().unwrap();
692-
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet));
692+
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet { progress: None }));
693693

694694
// Let's edit the local echo (poll start) with an unsupported type (message).
695695
let edit_err = timeline

0 commit comments

Comments
 (0)