diff --git a/bindings/matrix-sdk-ffi/src/timeline/mod.rs b/bindings/matrix-sdk-ffi/src/timeline/mod.rs index 4162af56582..99b9032d499 100644 --- a/bindings/matrix-sdk-ffi/src/timeline/mod.rs +++ b/bindings/matrix-sdk-ffi/src/timeline/mod.rs @@ -48,8 +48,8 @@ use ruma::{ }, receipt::ReceiptThread, room::message::{ - FormattedBody as RumaFormattedBody, ForwardThread, LocationMessageEventContent, - MessageType, RoomMessageEventContentWithoutRelation, + ForwardThread, LocationMessageEventContent, MessageType, + RoomMessageEventContentWithoutRelation, }, AnyMessageLikeEventContent, }, @@ -81,6 +81,7 @@ use crate::{ mod content; pub use content::MessageContent; +use matrix_sdk::utils::formatted_body_from; use crate::error::QueueWedgeError; @@ -289,7 +290,8 @@ impl Timeline { progress_watcher: Option>, use_send_queue: bool, ) -> Arc { - let formatted_caption = formatted_caption_from(&caption, &formatted_caption); + let formatted_caption = + formatted_body_from(caption.as_deref(), formatted_caption.map(Into::into)); SendAttachmentJoinHandle::new(RUNTIME.spawn(async move { let base_image_info = BaseImageInfo::try_from(&image_info) .map_err(|_| RoomError::InvalidAttachmentData)?; @@ -322,7 +324,8 @@ impl Timeline { progress_watcher: Option>, use_send_queue: bool, ) -> Arc { - let formatted_caption = formatted_caption_from(&caption, &formatted_caption); + let formatted_caption = + formatted_body_from(caption.as_deref(), formatted_caption.map(Into::into)); SendAttachmentJoinHandle::new(RUNTIME.spawn(async move { let base_video_info: BaseVideoInfo = BaseVideoInfo::try_from(&video_info) .map_err(|_| RoomError::InvalidAttachmentData)?; @@ -353,7 +356,8 @@ impl Timeline { progress_watcher: Option>, use_send_queue: bool, ) -> Arc { - let formatted_caption = formatted_caption_from(&caption, &formatted_caption); + let formatted_caption = + formatted_body_from(caption.as_deref(), formatted_caption.map(Into::into)); SendAttachmentJoinHandle::new(RUNTIME.spawn(async move { let base_audio_info: BaseAudioInfo = BaseAudioInfo::try_from(&audio_info) .map_err(|_| RoomError::InvalidAttachmentData)?; @@ -386,7 +390,8 @@ impl Timeline { progress_watcher: Option>, use_send_queue: bool, ) -> Arc { - let formatted_caption = formatted_caption_from(&caption, &formatted_caption); + let formatted_caption = + formatted_body_from(caption.as_deref(), formatted_caption.map(Into::into)); SendAttachmentJoinHandle::new(RUNTIME.spawn(async move { let base_audio_info: BaseAudioInfo = BaseAudioInfo::try_from(&audio_info) .map_err(|_| RoomError::InvalidAttachmentData)?; @@ -714,24 +719,6 @@ impl Timeline { } } -/// Given a pair of optional `caption` and `formatted_caption` parameters, -/// return a formatted caption: -/// -/// - If a `formatted_caption` exists, return it. -/// - If it doesn't exist but there is a `caption`, parse it as markdown and -/// return the result. -/// - Return `None` if there are no `caption` or `formatted_caption` parameters. -fn formatted_caption_from( - caption: &Option, - formatted_caption: &Option, -) -> Option { - match (&caption, formatted_caption) { - (None, None) => None, - (Some(body), None) => RumaFormattedBody::markdown(body), - (_, Some(formatted_body)) => Some(formatted_body.clone().into()), - } -} - /// A handle to perform actions onto a local echo. #[derive(uniffi::Object)] pub struct SendHandle { diff --git a/crates/matrix-sdk/Cargo.toml b/crates/matrix-sdk/Cargo.toml index 59b11de6b8c..a8afad86218 100644 --- a/crates/matrix-sdk/Cargo.toml +++ b/crates/matrix-sdk/Cargo.toml @@ -16,7 +16,7 @@ features = ["docsrs"] rustdoc-args = ["--cfg", "docsrs"] [features] -default = ["e2e-encryption", "automatic-room-key-forwarding", "sqlite", "native-tls"] +default = ["e2e-encryption", "automatic-room-key-forwarding", "sqlite", "native-tls", "markdown"] testing = ["matrix-sdk-sqlite?/testing", "matrix-sdk-indexeddb?/testing", "matrix-sdk-base/testing", "wiremock", "matrix-sdk-test", "assert_matches2"] e2e-encryption = [ diff --git a/crates/matrix-sdk/src/utils.rs b/crates/matrix-sdk/src/utils.rs index 327c0410176..3e1d5a14804 100644 --- a/crates/matrix-sdk/src/utils.rs +++ b/crates/matrix-sdk/src/utils.rs @@ -22,7 +22,7 @@ use futures_core::Stream; #[cfg(feature = "e2e-encryption")] use futures_util::StreamExt; use ruma::{ - events::{AnyMessageLikeEventContent, AnyStateEventContent}, + events::{room::message::FormattedBody, AnyMessageLikeEventContent, AnyStateEventContent}, serde::Raw, RoomAliasId, }; @@ -218,9 +218,28 @@ pub fn is_room_alias_format_valid(alias: String) -> bool { has_valid_format && is_lowercase && RoomAliasId::parse(alias).is_ok() } +/// Given a pair of optional `body` and `formatted_body` parameters, +/// returns a formatted body. +/// +/// Return the formatted body if available, or interpret the `body` parameter as +/// markdown, if provided. +pub fn formatted_body_from( + body: Option<&str>, + formatted_body: Option, +) -> Option { + if formatted_body.is_some() { + formatted_body + } else { + body.and_then(FormattedBody::markdown) + } +} + #[cfg(test)] mod test { - use crate::utils::is_room_alias_format_valid; + use assert_matches2::{assert_let, assert_matches}; + use ruma::events::room::message::FormattedBody; + + use crate::utils::{formatted_body_from, is_room_alias_format_valid}; #[cfg(feature = "e2e-encryption")] #[test] @@ -282,4 +301,46 @@ mod test { fn test_is_room_alias_format_valid_when_has_valid_format() { assert!(is_room_alias_format_valid("#alias.test:domain.org".to_owned())) } + + #[test] + fn test_formatted_body_from_nothing_returns_none() { + assert_matches!(formatted_body_from(None, None), None); + } + + #[test] + fn test_formatted_body_from_only_formatted_body_returns_the_formatted_body() { + let formatted_body = FormattedBody::html(r"

Hello!

"); + + assert_let!( + Some(result_formatted_body) = formatted_body_from(None, Some(formatted_body.clone())) + ); + + assert_eq!(formatted_body.body, result_formatted_body.body); + assert_eq!(result_formatted_body.format, result_formatted_body.format); + } + + #[test] + fn test_formatted_body_from_markdown_body_returns_a_processed_formatted_body() { + let markdown_body = Some(r"# Parsed"); + + assert_let!(Some(result_formatted_body) = formatted_body_from(markdown_body, None)); + + let expected_formatted_body = FormattedBody::html("

Parsed

\n".to_owned()); + assert_eq!(expected_formatted_body.body, result_formatted_body.body); + assert_eq!(expected_formatted_body.format, result_formatted_body.format); + } + + #[test] + fn test_formatted_body_from_body_and_formatted_body_returns_the_formatted_body() { + let markdown_body = Some(r"# Markdown"); + let formatted_body = FormattedBody::html(r"

HTML

"); + + assert_let!( + Some(result_formatted_body) = + formatted_body_from(markdown_body, Some(formatted_body.clone())) + ); + + assert_eq!(formatted_body.body, result_formatted_body.body); + assert_eq!(formatted_body.format, result_formatted_body.format); + } } diff --git a/xtask/src/ci.rs b/xtask/src/ci.rs index 40c8db5df2a..fa35a6f683f 100644 --- a/xtask/src/ci.rs +++ b/xtask/src/ci.rs @@ -285,17 +285,17 @@ fn run_wasm_checks(cmd: Option) -> Result<()> { (WasmFeatureSet::MatrixSdkQrcode, "-p matrix-sdk-qrcode --features js"), ( WasmFeatureSet::MatrixSdkNoDefault, - "-p matrix-sdk --no-default-features --features js,rustls-tls", + "-p matrix-sdk --no-default-features --features js,rustls-tls,markdown", ), (WasmFeatureSet::MatrixSdkBase, "-p matrix-sdk-base --features js,test-send-sync"), (WasmFeatureSet::MatrixSdkCommon, "-p matrix-sdk-common --features js"), ( WasmFeatureSet::MatrixSdkIndexeddbStoresNoCrypto, - "-p matrix-sdk --no-default-features --features js,indexeddb,rustls-tls", + "-p matrix-sdk --no-default-features --features js,indexeddb,rustls-tls,markdown", ), ( WasmFeatureSet::MatrixSdkIndexeddbStores, - "-p matrix-sdk --no-default-features --features js,indexeddb,e2e-encryption,rustls-tls", + "-p matrix-sdk --no-default-features --features js,indexeddb,e2e-encryption,rustls-tls,markdown", ), (WasmFeatureSet::IndexeddbAllFeatures, "-p matrix-sdk-indexeddb"), (