Skip to content

Commit 0a796cb

Browse files
Johennesbnjbvr
authored andcommitted
feat(timeline): communicate media upload progress through EventSendState::NotSentYet
Signed-off-by: Johannes Marbach <[email protected]>
1 parent e3390c1 commit 0a796cb

File tree

16 files changed

+216
-65
lines changed

16 files changed

+216
-65
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
@@ -623,7 +623,7 @@ mod tests {
623623

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

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

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@ pub(super) use self::{
6262
};
6363
use super::{
6464
DateDividerMode, EmbeddedEvent, Error, EventSendState, EventTimelineItem, InReplyToDetails,
65-
PaginationError, Profile, TimelineDetails, TimelineEventItemId, TimelineFocus, TimelineItem,
66-
TimelineItemContent, TimelineItemKind, VirtualTimelineItem,
65+
MediaUploadProgress, PaginationError, Profile, TimelineDetails, TimelineEventItemId,
66+
TimelineFocus, TimelineItem, TimelineItemContent, TimelineItemKind, VirtualTimelineItem,
6767
algorithms::{rfind_event_by_id, rfind_event_item},
6868
event_item::{ReactionStatus, RemoteEventOrigin},
6969
item::TimelineUniqueId,
@@ -1072,7 +1072,11 @@ impl<P: RoomDataProvider, D: Decryptor> TimelineController<P, D> {
10721072
warn!("We looked for a local item, but it transitioned as remote??");
10731073
return false;
10741074
};
1075-
prev_local_item.with_send_state(EventSendState::NotSentYet)
1075+
// If the local echo had an upload progress, retain it.
1076+
let progress = as_variant!(&prev_local_item.send_state,
1077+
EventSendState::NotSentYet { progress } => progress.clone())
1078+
.flatten();
1079+
prev_local_item.with_send_state(EventSendState::NotSentYet { progress })
10761080
};
10771081

10781082
// Replace the local-related state (kind) and the content state.
@@ -1358,17 +1362,26 @@ impl<P: RoomDataProvider, D: Decryptor> TimelineController<P, D> {
13581362
}
13591363

13601364
RoomSendQueueUpdate::RetryEvent { transaction_id } => {
1361-
self.update_event_send_state(&transaction_id, EventSendState::NotSentYet).await;
1365+
self.update_event_send_state(
1366+
&transaction_id,
1367+
EventSendState::NotSentYet { progress: None },
1368+
)
1369+
.await;
13621370
}
13631371

13641372
RoomSendQueueUpdate::SentEvent { transaction_id, event_id } => {
13651373
self.update_event_send_state(&transaction_id, EventSendState::Sent { event_id })
13661374
.await;
13671375
}
13681376

1369-
RoomSendQueueUpdate::MediaUpload { related_to, .. } => {
1370-
// TODO(bnjbvr): Do something else?
1371-
info!(txn_id = %related_to, "some media for a media event has been uploaded");
1377+
RoomSendQueueUpdate::MediaUpload { related_to, index, progress, .. } => {
1378+
self.update_event_send_state(
1379+
&related_to,
1380+
EventSendState::NotSentYet {
1381+
progress: Some(MediaUploadProgress { index, progress }),
1382+
},
1383+
)
1384+
.await;
13721385
}
13731386
}
13741387
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ mod observable_items_tests {
781781
thread_summary: None,
782782
}),
783783
EventTimelineItemKind::Local(LocalEventTimelineItem {
784-
send_state: EventSendState::NotSentYet,
784+
send_state: EventSendState::NotSentYet { progress: None },
785785
transaction_id: transaction_id.into(),
786786
send_handle: None,
787787
}),

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

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

731731
let kind: EventTimelineItemKind = match &self.ctx.flow {
732732
Flow::Local { txn_id, send_handle } => LocalEventTimelineItem {
733-
send_state: EventSendState::NotSentYet,
733+
send_state: EventSendState::NotSentYet { progress: None },
734734
transaction_id: txn_id.to_owned(),
735735
send_handle: send_handle.clone(),
736736
}

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

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

1717
use as_variant::as_variant;
18-
use matrix_sdk::{Error, send_queue::SendHandle};
18+
use matrix_sdk::{
19+
Error,
20+
send_queue::{AbstractProgress, SendHandle},
21+
};
1922
use ruma::{EventId, OwnedEventId, OwnedTransactionId};
2023

2124
use super::TimelineEventItemId;
@@ -65,7 +68,11 @@ impl LocalEventTimelineItem {
6568
#[derive(Clone, Debug)]
6669
pub enum EventSendState {
6770
/// The local event has not been sent yet.
68-
NotSentYet,
71+
NotSentYet {
72+
/// The progress of the sending operation, if the event involves a media
73+
/// upload.
74+
progress: Option<MediaUploadProgress>,
75+
},
6976
/// The local event has been sent to the server, but unsuccessfully: The
7077
/// sending has failed.
7178
SendingFailed {
@@ -84,3 +91,18 @@ pub enum EventSendState {
8491
event_id: OwnedEventId,
8592
},
8693
}
94+
95+
/// This type represents the progress of a media (consisting of a file and
96+
/// possibly a thumbnail) being uploaded.
97+
#[derive(Clone, Debug)]
98+
pub struct MediaUploadProgress {
99+
/// The index of the media within the transaction. A file and its
100+
/// thumbnail share the same index. Will always be 0 for non-gallery
101+
/// media uploads.
102+
pub index: u64,
103+
104+
/// The combined upload progress across the file and, if existing, its
105+
/// thumbnail. For gallery uploads, the progress is reported per indexed
106+
/// gallery item.
107+
pub progress: AbstractProgress,
108+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub use self::{
5050
PollResult, PollState, RoomMembershipChange, RoomPinnedEventsChange, Sticker,
5151
ThreadSummary, TimelineItemContent,
5252
},
53-
local::EventSendState,
53+
local::{EventSendState, MediaUploadProgress},
5454
};
5555
pub(super) use self::{
5656
content::{

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,11 @@ pub use self::{
9393
error::*,
9494
event_item::{
9595
AnyOtherFullStateEventContent, EmbeddedEvent, EncryptedMessage, EventItemOrigin,
96-
EventSendState, EventTimelineItem, InReplyToDetails, MemberProfileChange, MembershipChange,
97-
Message, MsgLikeContent, MsgLikeKind, OtherState, PollResult, PollState, Profile,
98-
ReactionInfo, ReactionStatus, ReactionsByKeyBySender, RoomMembershipChange,
99-
RoomPinnedEventsChange, Sticker, ThreadSummary, TimelineDetails, TimelineEventItemId,
100-
TimelineItemContent,
96+
EventSendState, EventTimelineItem, InReplyToDetails, MediaUploadProgress,
97+
MemberProfileChange, MembershipChange, Message, MsgLikeContent, MsgLikeKind, OtherState,
98+
PollResult, PollState, Profile, ReactionInfo, ReactionStatus, ReactionsByKeyBySender,
99+
RoomMembershipChange, RoomPinnedEventsChange, Sticker, ThreadSummary, TimelineDetails,
100+
TimelineEventItemId, TimelineItemContent,
101101
},
102102
event_type_filter::TimelineEventTypeFilter,
103103
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
@@ -198,7 +198,7 @@ async fn test_edit_local_echo() {
198198
let internal_id = item.unique_id();
199199

200200
let item = item.as_event().unwrap();
201-
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet));
201+
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet { progress: None }));
202202

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

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

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

636636
let item = item.as_event().unwrap();
637-
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet));
637+
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet { progress: None }));
638638

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

690690
let item = item.as_event().unwrap();
691-
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet));
691+
assert_matches!(item.send_state(), Some(EventSendState::NotSentYet { progress: None }));
692692

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

0 commit comments

Comments
 (0)