1use std::time::Duration;
18
19use ruma::{
20 assign,
21 events::{
22 room::{
23 message::{AudioInfo, FileInfo, FormattedBody, VideoInfo},
24 ImageInfo, ThumbnailInfo,
25 },
26 Mentions,
27 },
28 OwnedTransactionId, TransactionId, UInt,
29};
30
31use crate::room::reply::Reply;
32
33#[derive(Debug, Clone, Default)]
35pub struct BaseImageInfo {
36 pub height: Option<UInt>,
38 pub width: Option<UInt>,
40 pub size: Option<UInt>,
42 pub blurhash: Option<String>,
44 pub is_animated: Option<bool>,
46}
47
48#[derive(Debug, Clone, Default)]
50pub struct BaseVideoInfo {
51 pub duration: Option<Duration>,
53 pub height: Option<UInt>,
55 pub width: Option<UInt>,
57 pub size: Option<UInt>,
59 pub blurhash: Option<String>,
61}
62
63#[derive(Debug, Clone, Default)]
65pub struct BaseAudioInfo {
66 pub duration: Option<Duration>,
68 pub size: Option<UInt>,
70}
71
72#[derive(Debug, Clone, Default)]
74pub struct BaseFileInfo {
75 pub size: Option<UInt>,
77}
78
79#[derive(Debug)]
81pub enum AttachmentInfo {
82 Image(BaseImageInfo),
84 Video(BaseVideoInfo),
86 Audio(BaseAudioInfo),
88 File(BaseFileInfo),
90 Voice {
92 audio_info: BaseAudioInfo,
94 waveform: Option<Vec<u16>>,
96 },
97}
98
99impl From<AttachmentInfo> for ImageInfo {
100 fn from(info: AttachmentInfo) -> Self {
101 match info {
102 AttachmentInfo::Image(info) => assign!(ImageInfo::new(), {
103 height: info.height,
104 width: info.width,
105 size: info.size,
106 blurhash: info.blurhash,
107 is_animated: info.is_animated,
108 }),
109 _ => ImageInfo::new(),
110 }
111 }
112}
113
114impl From<AttachmentInfo> for VideoInfo {
115 fn from(info: AttachmentInfo) -> Self {
116 match info {
117 AttachmentInfo::Video(info) => assign!(VideoInfo::new(), {
118 duration: info.duration,
119 height: info.height,
120 width: info.width,
121 size: info.size,
122 blurhash: info.blurhash,
123 }),
124 _ => VideoInfo::new(),
125 }
126 }
127}
128
129impl From<AttachmentInfo> for AudioInfo {
130 fn from(info: AttachmentInfo) -> Self {
131 match info {
132 AttachmentInfo::Audio(info) => assign!(AudioInfo::new(), {
133 duration: info.duration,
134 size: info.size,
135 }),
136 AttachmentInfo::Voice { audio_info, .. } => assign!(AudioInfo::new(), {
137 duration: audio_info.duration,
138 size: audio_info.size,
139 }),
140 _ => AudioInfo::new(),
141 }
142 }
143}
144
145impl From<AttachmentInfo> for FileInfo {
146 fn from(info: AttachmentInfo) -> Self {
147 match info {
148 AttachmentInfo::File(info) => assign!(FileInfo::new(), {
149 size: info.size,
150 }),
151 _ => FileInfo::new(),
152 }
153 }
154}
155
156#[derive(Debug)]
158pub struct Thumbnail {
159 pub data: Vec<u8>,
161 pub content_type: mime::Mime,
163 pub height: UInt,
165 pub width: UInt,
167 pub size: UInt,
169}
170
171impl Thumbnail {
172 pub fn into_parts(self) -> (Vec<u8>, mime::Mime, Box<ThumbnailInfo>) {
174 let thumbnail_info = assign!(ThumbnailInfo::new(), {
175 height: Some(self.height),
176 width: Some(self.width),
177 size: Some(self.size),
178 mimetype: Some(self.content_type.to_string())
179 });
180 (self.data, self.content_type, Box::new(thumbnail_info))
181 }
182}
183
184#[derive(Debug, Default)]
186pub struct AttachmentConfig {
187 pub(crate) txn_id: Option<OwnedTransactionId>,
188 pub(crate) info: Option<AttachmentInfo>,
189 pub(crate) thumbnail: Option<Thumbnail>,
190 pub(crate) caption: Option<String>,
191 pub(crate) formatted_caption: Option<FormattedBody>,
192 pub(crate) mentions: Option<Mentions>,
193 pub(crate) reply: Option<Reply>,
194}
195
196impl AttachmentConfig {
197 pub fn new() -> Self {
199 Self::default()
200 }
201
202 #[must_use]
209 pub fn thumbnail(mut self, thumbnail: Option<Thumbnail>) -> Self {
210 self.thumbnail = thumbnail;
211 self
212 }
213
214 #[must_use]
222 pub fn txn_id(mut self, txn_id: &TransactionId) -> Self {
223 self.txn_id = Some(txn_id.to_owned());
224 self
225 }
226
227 #[must_use]
234 pub fn info(mut self, info: AttachmentInfo) -> Self {
235 self.info = Some(info);
236 self
237 }
238
239 pub fn caption(mut self, caption: Option<String>) -> Self {
245 self.caption = caption;
246 self
247 }
248
249 pub fn formatted_caption(mut self, formatted_caption: Option<FormattedBody>) -> Self {
255 self.formatted_caption = formatted_caption;
256 self
257 }
258
259 pub fn mentions(mut self, mentions: Option<Mentions>) -> Self {
265 self.mentions = mentions;
266 self
267 }
268
269 pub fn reply(mut self, reply: Option<Reply>) -> Self {
275 self.reply = reply;
276 self
277 }
278}