Add MediaEventContent trait and implement it for corresponding room events
Add helper methods in Clientmaster
parent
b805670c8a
commit
df883d3328
|
@ -45,7 +45,7 @@ use matrix_sdk_base::{
|
|||
deserialized_responses::SyncResponse,
|
||||
events::AnyMessageEventContent,
|
||||
identifiers::MxcUri,
|
||||
media::{MediaFormat, MediaRequest, MediaType},
|
||||
media::{MediaEventContent, MediaFormat, MediaRequest, MediaThumbnailSize, MediaType},
|
||||
BaseClient, BaseClientConfig, SendAccessToken, Session, Store,
|
||||
};
|
||||
use mime::{self, Mime};
|
||||
|
@ -2503,7 +2503,7 @@ impl Client {
|
|||
let content = {
|
||||
let mut cursor = Cursor::new(content);
|
||||
let mut reader =
|
||||
AttachmentDecryptor::new(&mut cursor, file.clone().into())?;
|
||||
AttachmentDecryptor::new(&mut cursor, file.as_ref().clone().into())?;
|
||||
|
||||
let mut decrypted = Vec::new();
|
||||
reader.read_to_end(&mut decrypted)?;
|
||||
|
@ -2557,6 +2557,120 @@ impl Client {
|
|||
pub async fn remove_media_content_for_uri(&self, uri: &MxcUri) -> Result<()> {
|
||||
Ok(self.base_client.store().remove_media_content_for_uri(&uri).await?)
|
||||
}
|
||||
|
||||
/// Get the file of the given media event content.
|
||||
///
|
||||
/// If the content is encrypted and encryption is enabled, the content will
|
||||
/// be decrypted.
|
||||
///
|
||||
/// Returns `Ok(None)` if the event content has no file.
|
||||
///
|
||||
/// This is a convenience method that calls the
|
||||
/// [`get_media_content`](#method.get_media_content) method.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `event_content` - The media event content.
|
||||
///
|
||||
/// * `use_cache` - If we should use the media cache for this file.
|
||||
pub async fn get_file(
|
||||
&self,
|
||||
event_content: impl MediaEventContent,
|
||||
use_cache: bool,
|
||||
) -> Result<Option<Vec<u8>>> {
|
||||
if let Some(media_type) = event_content.file() {
|
||||
Ok(Some(
|
||||
self.get_media_content(
|
||||
&MediaRequest { media_type, format: MediaFormat::File },
|
||||
use_cache,
|
||||
)
|
||||
.await?,
|
||||
))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the file of the given media event content from the cache.
|
||||
///
|
||||
/// This is a convenience method that calls the
|
||||
/// [`remove_media_content`](#method.remove_media_content) method.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `event_content` - The media event content.
|
||||
pub async fn remove_file(&self, event_content: impl MediaEventContent) -> Result<()> {
|
||||
if let Some(media_type) = event_content.file() {
|
||||
self.remove_media_content(&MediaRequest { media_type, format: MediaFormat::File })
|
||||
.await?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get a thumbnail of the given media event content.
|
||||
///
|
||||
/// If the content is encrypted and encryption is enabled, the content will
|
||||
/// be decrypted.
|
||||
///
|
||||
/// Returns `Ok(None)` if the event content has no thumbnail.
|
||||
///
|
||||
/// This is a convenience method that calls the
|
||||
/// [`get_media_content`](#method.get_media_content) method.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `event_content` - The media event content.
|
||||
///
|
||||
/// * `size` - The _desired_ size of the thumbnail. The actual thumbnail may
|
||||
/// not match the size specified.
|
||||
///
|
||||
/// * `use_cache` - If we should use the media cache for this thumbnail.
|
||||
pub async fn get_thumbnail(
|
||||
&self,
|
||||
event_content: impl MediaEventContent,
|
||||
size: MediaThumbnailSize,
|
||||
use_cache: bool,
|
||||
) -> Result<Option<Vec<u8>>> {
|
||||
if let Some(media_type) = event_content.thumbnail() {
|
||||
Ok(Some(
|
||||
self.get_media_content(
|
||||
&MediaRequest { media_type, format: MediaFormat::Thumbnail(size) },
|
||||
use_cache,
|
||||
)
|
||||
.await?,
|
||||
))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the thumbnail of the given media event content from the cache.
|
||||
///
|
||||
/// This is a convenience method that calls the
|
||||
/// [`remove_media_content`](#method.remove_media_content) method.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `event_content` - The media event content.
|
||||
///
|
||||
/// * `size` - The _desired_ size of the thumbnail. Must match the size
|
||||
/// requested with [`get_thumbnail`](#method.get_thumbnail).
|
||||
pub async fn remove_thumbnail(
|
||||
&self,
|
||||
event_content: impl MediaEventContent,
|
||||
size: MediaThumbnailSize,
|
||||
) -> Result<()> {
|
||||
if let Some(media_type) = event_content.file() {
|
||||
self.remove_media_content(&MediaRequest {
|
||||
media_type,
|
||||
format: MediaFormat::Thumbnail(size),
|
||||
})
|
||||
.await?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
//! Common types for [media content](https://matrix.org/docs/spec/client_server/r0.6.1#id66).
|
||||
|
||||
use matrix_sdk_common::{
|
||||
api::r0::media::get_content_thumbnail::Method, events::room::EncryptedFile,
|
||||
identifiers::MxcUri, UInt,
|
||||
api::r0::media::get_content_thumbnail::Method,
|
||||
events::{
|
||||
room::{
|
||||
message::{
|
||||
AudioMessageEventContent, FileMessageEventContent, ImageMessageEventContent,
|
||||
LocationMessageEventContent, VideoMessageEventContent,
|
||||
},
|
||||
EncryptedFile,
|
||||
},
|
||||
sticker::StickerEventContent,
|
||||
},
|
||||
identifiers::MxcUri,
|
||||
UInt,
|
||||
};
|
||||
|
||||
const UNIQUE_SEPARATOR: &str = "_";
|
||||
|
@ -61,7 +72,7 @@ pub enum MediaType {
|
|||
Uri(MxcUri),
|
||||
|
||||
/// An encrypted media content.
|
||||
Encrypted(EncryptedFile),
|
||||
Encrypted(Box<EncryptedFile>),
|
||||
}
|
||||
|
||||
impl UniqueKey for MediaType {
|
||||
|
@ -88,3 +99,118 @@ impl UniqueKey for MediaRequest {
|
|||
format!("{}{}{}", self.media_type.unique_key(), UNIQUE_SEPARATOR, self.format.unique_key())
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for media event content.
|
||||
pub trait MediaEventContent {
|
||||
/// Get the type of the file for `Self`.
|
||||
///
|
||||
/// Returns `None` if `Self` has no file.
|
||||
fn file(&self) -> Option<MediaType>;
|
||||
|
||||
/// Get the type of the thumbnail for `Self`.
|
||||
///
|
||||
/// Returns `None` if `Self` has no thumbnail.
|
||||
fn thumbnail(&self) -> Option<MediaType>;
|
||||
}
|
||||
|
||||
impl MediaEventContent for StickerEventContent {
|
||||
fn file(&self) -> Option<MediaType> {
|
||||
Some(MediaType::Uri(self.url.clone()))
|
||||
}
|
||||
|
||||
fn thumbnail(&self) -> Option<MediaType> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl MediaEventContent for AudioMessageEventContent {
|
||||
fn file(&self) -> Option<MediaType> {
|
||||
self.url
|
||||
.as_ref()
|
||||
.map(|uri| MediaType::Uri(uri.clone()))
|
||||
.or_else(|| self.file.as_ref().map(|e| MediaType::Encrypted(e.clone())))
|
||||
}
|
||||
|
||||
fn thumbnail(&self) -> Option<MediaType> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl MediaEventContent for FileMessageEventContent {
|
||||
fn file(&self) -> Option<MediaType> {
|
||||
self.url
|
||||
.as_ref()
|
||||
.map(|uri| MediaType::Uri(uri.clone()))
|
||||
.or_else(|| self.file.as_ref().map(|e| MediaType::Encrypted(e.clone())))
|
||||
}
|
||||
|
||||
fn thumbnail(&self) -> Option<MediaType> {
|
||||
self.info.as_ref().and_then(|info| {
|
||||
if let Some(uri) = info.thumbnail_url.as_ref() {
|
||||
Some(MediaType::Uri(uri.clone()))
|
||||
} else {
|
||||
info.thumbnail_file.as_ref().map(|file| MediaType::Encrypted(file.clone()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl MediaEventContent for ImageMessageEventContent {
|
||||
fn file(&self) -> Option<MediaType> {
|
||||
self.url
|
||||
.as_ref()
|
||||
.map(|uri| MediaType::Uri(uri.clone()))
|
||||
.or_else(|| self.file.as_ref().map(|e| MediaType::Encrypted(e.clone())))
|
||||
}
|
||||
|
||||
fn thumbnail(&self) -> Option<MediaType> {
|
||||
self.info
|
||||
.as_ref()
|
||||
.and_then(|info| {
|
||||
if let Some(uri) = info.thumbnail_url.as_ref() {
|
||||
Some(MediaType::Uri(uri.clone()))
|
||||
} else {
|
||||
info.thumbnail_file.as_ref().map(|file| MediaType::Encrypted(file.clone()))
|
||||
}
|
||||
})
|
||||
.or_else(|| self.url.as_ref().map(|uri| MediaType::Uri(uri.clone())))
|
||||
}
|
||||
}
|
||||
|
||||
impl MediaEventContent for VideoMessageEventContent {
|
||||
fn file(&self) -> Option<MediaType> {
|
||||
self.url
|
||||
.as_ref()
|
||||
.map(|uri| MediaType::Uri(uri.clone()))
|
||||
.or_else(|| self.file.as_ref().map(|e| MediaType::Encrypted(e.clone())))
|
||||
}
|
||||
|
||||
fn thumbnail(&self) -> Option<MediaType> {
|
||||
self.info
|
||||
.as_ref()
|
||||
.and_then(|info| {
|
||||
if let Some(uri) = info.thumbnail_url.as_ref() {
|
||||
Some(MediaType::Uri(uri.clone()))
|
||||
} else {
|
||||
info.thumbnail_file.as_ref().map(|file| MediaType::Encrypted(file.clone()))
|
||||
}
|
||||
})
|
||||
.or_else(|| self.url.as_ref().map(|uri| MediaType::Uri(uri.clone())))
|
||||
}
|
||||
}
|
||||
|
||||
impl MediaEventContent for LocationMessageEventContent {
|
||||
fn file(&self) -> Option<MediaType> {
|
||||
None
|
||||
}
|
||||
|
||||
fn thumbnail(&self) -> Option<MediaType> {
|
||||
self.info.as_ref().and_then(|info| {
|
||||
if let Some(uri) = info.thumbnail_url.as_ref() {
|
||||
Some(MediaType::Uri(uri.clone()))
|
||||
} else {
|
||||
info.thumbnail_file.as_ref().map(|file| MediaType::Encrypted(file.clone()))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue