matrix_sdk_ui/timeline/
futures.rs1use std::future::IntoFuture;
2
3use eyeball::SharedObservable;
4use matrix_sdk::{attachment::AttachmentConfig, TransmissionProgress};
5use matrix_sdk_base::boxed_into_future;
6use mime::Mime;
7use tracing::{Instrument as _, Span};
8
9use super::{AttachmentSource, Error, Timeline};
10
11pub struct SendAttachment<'a> {
12 timeline: &'a Timeline,
13 source: AttachmentSource,
14 mime_type: Mime,
15 config: AttachmentConfig,
16 tracing_span: Span,
17 pub(crate) send_progress: SharedObservable<TransmissionProgress>,
18 use_send_queue: bool,
19}
20
21impl<'a> SendAttachment<'a> {
22 pub(crate) fn new(
23 timeline: &'a Timeline,
24 source: AttachmentSource,
25 mime_type: Mime,
26 config: AttachmentConfig,
27 ) -> Self {
28 Self {
29 timeline,
30 source,
31 mime_type,
32 config,
33 tracing_span: Span::current(),
34 send_progress: Default::default(),
35 use_send_queue: false,
36 }
37 }
38
39 pub fn use_send_queue(self) -> Self {
48 Self { use_send_queue: true, ..self }
49 }
50
51 pub fn subscribe_to_send_progress(&self) -> eyeball::Subscriber<TransmissionProgress> {
53 self.send_progress.subscribe()
54 }
55}
56
57impl<'a> IntoFuture for SendAttachment<'a> {
58 type Output = Result<(), Error>;
59 boxed_into_future!(extra_bounds: 'a);
60
61 fn into_future(self) -> Self::IntoFuture {
62 let Self {
63 timeline,
64 source,
65 mime_type,
66 config,
67 tracing_span,
68 use_send_queue,
69 send_progress,
70 } = self;
71
72 let fut = async move {
73 let (data, filename) = source.try_into_bytes_and_filename()?;
74
75 if use_send_queue {
76 let send_queue = timeline.room().send_queue();
77 let fut = send_queue.send_attachment(filename, mime_type, data, config);
78 fut.await.map_err(|_| Error::FailedSendingAttachment)?;
79 } else {
80 let fut = timeline
81 .room()
82 .send_attachment(filename, &mime_type, data, config)
83 .with_send_progress_observable(send_progress)
84 .store_in_cache();
85 fut.await.map_err(|_| Error::FailedSendingAttachment)?;
86 }
87
88 Ok(())
89 };
90
91 Box::pin(fut.instrument(tracing_span))
92 }
93}
94
95#[cfg(feature = "unstable-msc4274")]
96pub use galleries::*;
97
98#[cfg(feature = "unstable-msc4274")]
99mod galleries {
100 use std::future::IntoFuture;
101
102 use matrix_sdk_base::boxed_into_future;
103 use tracing::{Instrument as _, Span};
104
105 use super::{Error, Timeline};
106 use crate::timeline::GalleryConfig;
107
108 pub struct SendGallery<'a> {
109 timeline: &'a Timeline,
110 gallery: GalleryConfig,
111 tracing_span: Span,
112 }
113
114 impl<'a> SendGallery<'a> {
115 pub(crate) fn new(timeline: &'a Timeline, gallery: GalleryConfig) -> Self {
116 Self { timeline, gallery, tracing_span: Span::current() }
117 }
118 }
119
120 impl<'a> IntoFuture for SendGallery<'a> {
121 type Output = Result<(), Error>;
122 boxed_into_future!(extra_bounds: 'a);
123
124 fn into_future(self) -> Self::IntoFuture {
125 let Self { timeline, gallery, tracing_span } = self;
126
127 let fut = async move {
128 let send_queue = timeline.room().send_queue();
129 let fut = send_queue.send_gallery(gallery.try_into()?);
130 fut.await.map_err(|_| Error::FailedSendingAttachment)?;
131
132 Ok(())
133 };
134
135 Box::pin(fut.instrument(tracing_span))
136 }
137 }
138}