sdk: Add get_media_file function

This commit is contained in:
Doug
2023-03-15 09:22:53 +00:00
committed by GitHub
parent 9574f93320
commit b1074e400e
6 changed files with 111 additions and 2 deletions
Generated
+1
View File
@@ -2755,6 +2755,7 @@ dependencies = [
"matrix-sdk-sled",
"matrix-sdk-test",
"mime",
"mime_guess",
"once_cell",
"pin-project-lite",
"rand 0.8.5",
+7
View File
@@ -176,6 +176,13 @@ interface Client {
[Throws=ClientError]
void login(string username, string password, string? initial_device_name, string? device_id);
[Throws=ClientError]
MediaFileHandle get_media_file(MediaSource source, string mime_type);
};
interface MediaFileHandle {
string path();
};
enum MembershipState {
+37 -1
View File
@@ -2,7 +2,7 @@ use std::sync::{Arc, RwLock};
use anyhow::{anyhow, Context};
use matrix_sdk::{
media::{MediaFormat, MediaRequest, MediaThumbnailSize},
media::{MediaFileHandle as SdkMediaFileHandle, MediaFormat, MediaRequest, MediaThumbnailSize},
ruma::{
api::client::{
account::whoami,
@@ -181,6 +181,29 @@ impl Client {
Ok(())
})
}
pub fn get_media_file(
&self,
media_source: Arc<MediaSource>,
mime_type: String,
) -> anyhow::Result<Arc<MediaFileHandle>> {
let client = self.client.clone();
let source = (*media_source).clone();
let mime_type: mime::Mime = mime_type.parse()?;
RUNTIME.block_on(async move {
let handle = client
.media()
.get_media_file(
&MediaRequest { source, format: MediaFormat::File },
&mime_type,
true,
)
.await?;
Ok(Arc::new(MediaFileHandle { inner: handle }))
})
}
}
#[uniffi::export]
@@ -617,3 +640,16 @@ pub struct Session {
fn gen_transaction_id() -> String {
TransactionId::new().to_string()
}
/// A file handle that takes ownership of a media file on disk. When the handle
/// is dropped, the file will be removed from the disk.
pub struct MediaFileHandle {
inner: SdkMediaFileHandle,
}
impl MediaFileHandle {
/// Get the media file's path.
pub fn path(&self) -> String {
self.inner.path().to_str().unwrap().to_owned()
}
}
+2
View File
@@ -589,6 +589,7 @@ pub struct AudioInfo {
// for that
pub duration: Option<u64>,
pub size: Option<u64>,
pub mimetype: Option<String>,
}
#[derive(Clone, uniffi::Record)]
@@ -681,6 +682,7 @@ impl From<&matrix_sdk::ruma::events::room::message::AudioInfo> for AudioInfo {
Self {
duration: info.duration.map(|d| d.as_millis() as u64),
size: info.size.map(Into::into),
mimetype: info.mimetype.clone(),
}
}
}
+2 -1
View File
@@ -87,6 +87,7 @@ matrix-sdk-common = { version = "0.6.0", path = "../matrix-sdk-common" }
matrix-sdk-indexeddb = { version = "0.2.0", path = "../matrix-sdk-indexeddb", default-features = false, optional = true }
matrix-sdk-sled = { version = "0.2.0", path = "../matrix-sdk-sled", default-features = false, optional = true }
mime = "0.3.16"
mime_guess = "2.0.4"
pin-project-lite = "0.2.9"
rand = { version = "0.8.5", optional = true }
reqwest = { version = "0.11.10", default_features = false }
@@ -94,6 +95,7 @@ ruma = { workspace = true, features = ["rand", "unstable-msc2448", "unstable-msc
serde = { workspace = true }
serde_html_form = { workspace = true }
serde_json = { workspace = true }
tempfile = "3.3.0"
thiserror = { workspace = true }
tower = { version = "0.4.13", features = ["make"], optional = true }
tracing = { workspace = true, features = ["attributes"] }
@@ -137,7 +139,6 @@ dirs = "4.0.0"
futures = { version = "0.3.21", default-features = false, features = ["executor"] }
matrix-sdk-test = { version = "0.6.0", path = "../../testing/matrix-sdk-test" }
once_cell = { workspace = true }
tempfile = "3.3.0"
tracing-subscriber = { version = "0.3.11", features = ["env-filter"] }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
+62
View File
@@ -17,16 +17,24 @@
#[cfg(feature = "e2e-encryption")]
use std::io::Read;
#[cfg(not(target_arch = "wasm32"))]
use std::path::Path;
use std::time::Duration;
pub use matrix_sdk_base::media::*;
use mime::Mime;
#[cfg(not(target_arch = "wasm32"))]
use mime_guess;
use ruma::{
api::client::media::{create_content, get_content, get_content_thumbnail},
assign,
events::room::MediaSource,
MxcUri,
};
#[cfg(not(target_arch = "wasm32"))]
use tempfile::{Builder as TempFileBuilder, NamedTempFile};
#[cfg(not(target_arch = "wasm32"))]
use tokio::{fs::File as TokioFile, io::AsyncWriteExt};
use crate::{
attachment::{AttachmentInfo, Thumbnail},
@@ -45,6 +53,23 @@ pub struct Media {
client: Client,
}
/// A file handle that takes ownership of a media file on disk. When the handle
/// is dropped, the file will be removed from the disk.
#[derive(Debug)]
#[cfg(not(target_arch = "wasm32"))]
pub struct MediaFileHandle {
/// The temporary file that contains the media.
file: NamedTempFile,
}
#[cfg(not(target_arch = "wasm32"))]
impl MediaFileHandle {
/// Get the media file's path.
pub fn path(&self) -> &Path {
self.file.path()
}
}
impl Media {
pub(crate) fn new(client: Client) -> Self {
Self { client }
@@ -96,6 +121,43 @@ impl Media {
Ok(self.client.send(request, Some(request_config)).await?)
}
/// Gets a media file by copying it to a temporary location on disk.
///
/// The file won't be encrypted even if it is encrypted on the server.
///
/// Returns a `MediaFileHandle` which takes ownership of the file. When the
/// handle is dropped, the file will be deleted from the temporary location.
///
/// # Arguments
///
/// * `request` - The `MediaRequest` of the content.
///
/// * `content_type` - The type of the media, this will be used to set the
/// temporary file's extension.
///
/// * `use_cache` - If we should use the media cache for this request.
#[cfg(not(target_arch = "wasm32"))]
pub async fn get_media_file(
&self,
request: &MediaRequest,
content_type: &Mime,
use_cache: bool,
) -> Result<MediaFileHandle> {
let data = self.get_media_content(request, use_cache).await?;
let mut suffix = String::from("");
if let Some(extension) =
mime_guess::get_mime_extensions(content_type).and_then(|a| a.first())
{
suffix = String::from(".") + extension;
}
let file = TempFileBuilder::new().suffix(&suffix).tempfile()?;
TokioFile::from_std(file.reopen()?).write_all(&data).await?;
Ok(MediaFileHandle { file })
}
/// Get a media file's content.
///
/// If the content is encrypted and encryption is enabled, the content will