events: Remove conversions between extensible types and room messages
They are more difficult to implement and use with generic replacements, for little gain.
This commit is contained in:
parent
ec853e968a
commit
7c802c89ca
@ -13,27 +13,15 @@ mod waveform_serde;
|
|||||||
|
|
||||||
use waveform_serde::WaveformSerDeHelper;
|
use waveform_serde::WaveformSerDeHelper;
|
||||||
|
|
||||||
use super::{
|
use super::{file::FileContent, message::MessageContent, room::message::Relation};
|
||||||
file::FileContent,
|
|
||||||
message::MessageContent,
|
|
||||||
room::message::{
|
|
||||||
AudioInfo, AudioMessageEventContent, MessageType, Relation, RoomMessageEventContent,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The payload for an extensible audio message.
|
/// The payload for an extensible audio message.
|
||||||
///
|
///
|
||||||
/// This is the new primary type introduced in [MSC3246] and should not be sent before the end of
|
/// This is the new primary type introduced in [MSC3246] and should not be sent before the end of
|
||||||
/// the transition period. See the documentation of the [`message`] module for more information.
|
/// the transition period. See the documentation of the [`message`] module for more information.
|
||||||
///
|
///
|
||||||
/// `AudioEventContent` can be converted to a [`RoomMessageEventContent`] with a
|
|
||||||
/// [`MessageType::Audio`]. You can convert it back with
|
|
||||||
/// [`AudioEventContent::from_audio_room_message()`].
|
|
||||||
///
|
|
||||||
/// [MSC3246]: https://github.com/matrix-org/matrix-spec-proposals/pull/3246
|
/// [MSC3246]: https://github.com/matrix-org/matrix-spec-proposals/pull/3246
|
||||||
/// [`message`]: super::message
|
/// [`message`]: super::message
|
||||||
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
|
|
||||||
/// [`MessageType::Audio`]: super::room::message::MessageType::Audio
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.audio", kind = MessageLike, without_relation)]
|
#[ruma_event(type = "m.audio", kind = MessageLike, without_relation)]
|
||||||
@ -70,52 +58,6 @@ impl AudioEventContent {
|
|||||||
pub fn with_message(message: MessageContent, file: FileContent) -> Self {
|
pub fn with_message(message: MessageContent, file: FileContent) -> Self {
|
||||||
Self { message, file, audio: Default::default(), relates_to: None }
|
Self { message, file, audio: Default::default(), relates_to: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `AudioEventContent` from the given `AudioMessageEventContent` and optional
|
|
||||||
/// relation.
|
|
||||||
pub fn from_audio_room_message(
|
|
||||||
content: AudioMessageEventContent,
|
|
||||||
relates_to: Option<Relation>,
|
|
||||||
) -> Self {
|
|
||||||
// Otherwise the `voice` field has an extra indentation
|
|
||||||
#[rustfmt::skip]
|
|
||||||
let AudioMessageEventContent {
|
|
||||||
body,
|
|
||||||
source,
|
|
||||||
info,
|
|
||||||
message,
|
|
||||||
file,
|
|
||||||
audio,
|
|
||||||
#[cfg(feature = "unstable-msc3245")]
|
|
||||||
voice: _,
|
|
||||||
} = content;
|
|
||||||
let AudioInfo { duration, mimetype, size } = info.map(|info| *info).unwrap_or_default();
|
|
||||||
|
|
||||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
|
||||||
let file = file.unwrap_or_else(|| {
|
|
||||||
FileContent::from_room_message_content(source, None, mimetype, size)
|
|
||||||
});
|
|
||||||
let audio = audio.unwrap_or_else(|| {
|
|
||||||
let mut content = AudioContent::new();
|
|
||||||
content.duration = duration;
|
|
||||||
content
|
|
||||||
});
|
|
||||||
|
|
||||||
Self { message, file, audio, relates_to }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<AudioEventContent> for RoomMessageEventContent {
|
|
||||||
fn from(content: AudioEventContent) -> Self {
|
|
||||||
let AudioEventContent { message, file, audio, relates_to } = content;
|
|
||||||
|
|
||||||
Self {
|
|
||||||
msgtype: MessageType::Audio(AudioMessageEventContent::from_extensible_content(
|
|
||||||
message, file, audio,
|
|
||||||
)),
|
|
||||||
relates_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Audio content.
|
/// Audio content.
|
||||||
|
@ -5,24 +5,15 @@
|
|||||||
use ruma_macros::EventContent;
|
use ruma_macros::EventContent;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{
|
use super::{message::MessageContent, room::message::Relation};
|
||||||
message::MessageContent,
|
|
||||||
room::message::{EmoteMessageEventContent, MessageType, Relation, RoomMessageEventContent},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The payload for an extensible emote message.
|
/// The payload for an extensible emote message.
|
||||||
///
|
///
|
||||||
/// This is the new primary type introduced in [MSC1767] and should not be sent before the end of
|
/// This is the new primary type introduced in [MSC1767] and should not be sent before the end of
|
||||||
/// the transition period. See the documentation of the [`message`] module for more information.
|
/// the transition period. See the documentation of the [`message`] module for more information.
|
||||||
///
|
///
|
||||||
/// `EmoteEventContent` can be converted to a [`RoomMessageEventContent`] with a
|
|
||||||
/// [`MessageType::Emote`]. You can convert it back with
|
|
||||||
/// [`EmoteEventContent::from_emote_room_message()`].
|
|
||||||
///
|
|
||||||
/// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
/// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
||||||
/// [`message`]: super::message
|
/// [`message`]: super::message
|
||||||
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
|
|
||||||
/// [`MessageType::Emote`]: super::room::message::MessageType::Emote
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.emote", kind = MessageLike, without_relation)]
|
#[ruma_event(type = "m.emote", kind = MessageLike, without_relation)]
|
||||||
@ -55,26 +46,4 @@ impl EmoteEventContent {
|
|||||||
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
|
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
|
||||||
Self { message: MessageContent::markdown(body), relates_to: None }
|
Self { message: MessageContent::markdown(body), relates_to: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `EmoteEventContent` from the given `EmoteMessageEventContent` and optional
|
|
||||||
/// relation.
|
|
||||||
pub fn from_emote_room_message(
|
|
||||||
content: EmoteMessageEventContent,
|
|
||||||
relates_to: Option<Relation>,
|
|
||||||
) -> Self {
|
|
||||||
let EmoteMessageEventContent { body, formatted, message, .. } = content;
|
|
||||||
if let Some(message) = message {
|
|
||||||
Self { message, relates_to }
|
|
||||||
} else {
|
|
||||||
Self { message: MessageContent::from_room_message_content(body, formatted), relates_to }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<EmoteEventContent> for RoomMessageEventContent {
|
|
||||||
fn from(content: EmoteEventContent) -> Self {
|
|
||||||
let EmoteEventContent { message, relates_to, .. } = content;
|
|
||||||
|
|
||||||
Self { msgtype: MessageType::Emote(message.into()), relates_to }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
message::MessageContent,
|
message::MessageContent,
|
||||||
room::{
|
room::{message::Relation, EncryptedFile, JsonWebKey},
|
||||||
message::{
|
|
||||||
FileInfo, FileMessageEventContent, MessageType, Relation, RoomMessageEventContent,
|
|
||||||
},
|
|
||||||
EncryptedFile, JsonWebKey, MediaSource,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use crate::{serde::Base64, OwnedMxcUri};
|
use crate::{serde::Base64, OwnedMxcUri};
|
||||||
|
|
||||||
@ -24,14 +19,8 @@ use crate::{serde::Base64, OwnedMxcUri};
|
|||||||
/// This is the new primary type introduced in [MSC3551] and should not be sent before the end of
|
/// This is the new primary type introduced in [MSC3551] and should not be sent before the end of
|
||||||
/// the transition period. See the documentation of the [`message`] module for more information.
|
/// the transition period. See the documentation of the [`message`] module for more information.
|
||||||
///
|
///
|
||||||
/// `FileEventContent` can be converted to a [`RoomMessageEventContent`] with a
|
|
||||||
/// [`MessageType::File`]. You can convert it back with
|
|
||||||
/// [`FileEventContent::from_file_room_message()`].
|
|
||||||
///
|
|
||||||
/// [MSC3551]: https://github.com/matrix-org/matrix-spec-proposals/pull/3551
|
/// [MSC3551]: https://github.com/matrix-org/matrix-spec-proposals/pull/3551
|
||||||
/// [`message`]: super::message
|
/// [`message`]: super::message
|
||||||
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
|
|
||||||
/// [`MessageType::File`]: super::room::message::MessageType::File
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.file", kind = MessageLike, without_relation)]
|
#[ruma_event(type = "m.file", kind = MessageLike, without_relation)]
|
||||||
@ -99,36 +88,6 @@ impl FileEventContent {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
Self { message, file: FileContent::encrypted(url, encryption_info, info), relates_to: None }
|
Self { message, file: FileContent::encrypted(url, encryption_info, info), relates_to: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `FileEventContent` from the given `FileMessageEventContent` and optional
|
|
||||||
/// relation.
|
|
||||||
pub fn from_file_room_message(
|
|
||||||
content: FileMessageEventContent,
|
|
||||||
relates_to: Option<Relation>,
|
|
||||||
) -> Self {
|
|
||||||
let FileMessageEventContent { body, filename, source, info, message, file } = content;
|
|
||||||
let FileInfo { mimetype, size, .. } = info.map(|info| *info).unwrap_or_default();
|
|
||||||
|
|
||||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
|
||||||
let file = file.unwrap_or_else(|| {
|
|
||||||
FileContent::from_room_message_content(source, filename, mimetype, size)
|
|
||||||
});
|
|
||||||
|
|
||||||
Self { message, file, relates_to }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<FileEventContent> for RoomMessageEventContent {
|
|
||||||
fn from(content: FileEventContent) -> Self {
|
|
||||||
let FileEventContent { message, file, relates_to } = content;
|
|
||||||
|
|
||||||
Self {
|
|
||||||
msgtype: MessageType::File(FileMessageEventContent::from_extensible_content(
|
|
||||||
message, file,
|
|
||||||
)),
|
|
||||||
relates_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// File content.
|
/// File content.
|
||||||
@ -164,20 +123,6 @@ impl FileContent {
|
|||||||
Self { url, info, encryption_info: Some(Box::new(encryption_info)) }
|
Self { url, info, encryption_info: Some(Box::new(encryption_info)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `FileContent` with the given media source, file info and filename.
|
|
||||||
pub(crate) fn from_room_message_content(
|
|
||||||
source: MediaSource,
|
|
||||||
filename: Option<String>,
|
|
||||||
mimetype: Option<String>,
|
|
||||||
size: Option<UInt>,
|
|
||||||
) -> Self {
|
|
||||||
let (url, encryption_info) = source.into_extensible_content();
|
|
||||||
let info =
|
|
||||||
FileContentInfo::from_room_message_content(filename, mimetype, size).map(Box::new);
|
|
||||||
|
|
||||||
Self { url, encryption_info: encryption_info.map(Box::new), info }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the file is encrypted.
|
/// Whether the file is encrypted.
|
||||||
pub fn is_encrypted(&self) -> bool {
|
pub fn is_encrypted(&self) -> bool {
|
||||||
self.encryption_info.is_some()
|
self.encryption_info.is_some()
|
||||||
|
@ -9,10 +9,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use super::{
|
use super::{
|
||||||
file::{EncryptedContent, FileContent},
|
file::{EncryptedContent, FileContent},
|
||||||
message::MessageContent,
|
message::MessageContent,
|
||||||
room::{
|
room::{message::Relation, MediaSource, ThumbnailInfo},
|
||||||
message::{ImageMessageEventContent, MessageType, Relation, RoomMessageEventContent},
|
|
||||||
ImageInfo, MediaSource, ThumbnailInfo,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
use crate::OwnedMxcUri;
|
use crate::OwnedMxcUri;
|
||||||
|
|
||||||
@ -21,14 +18,8 @@ use crate::OwnedMxcUri;
|
|||||||
/// This is the new primary type introduced in [MSC3552] and should not be sent before the end of
|
/// This is the new primary type introduced in [MSC3552] and should not be sent before the end of
|
||||||
/// the transition period. See the documentation of the [`message`] module for more information.
|
/// the transition period. See the documentation of the [`message`] module for more information.
|
||||||
///
|
///
|
||||||
/// `ImageEventContent` can be converted to a [`RoomMessageEventContent`] with a
|
|
||||||
/// [`MessageType::Image`]. You can convert it back with
|
|
||||||
/// [`ImageEventContent::from_image_room_message()`].
|
|
||||||
///
|
|
||||||
/// [MSC3552]: https://github.com/matrix-org/matrix-spec-proposals/pull/3552
|
/// [MSC3552]: https://github.com/matrix-org/matrix-spec-proposals/pull/3552
|
||||||
/// [`message`]: super::message
|
/// [`message`]: super::message
|
||||||
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
|
|
||||||
/// [`MessageType::Image`]: super::room::message::MessageType::Image
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.image", kind = MessageLike, without_relation)]
|
#[ruma_event(type = "m.image", kind = MessageLike, without_relation)]
|
||||||
@ -87,54 +78,6 @@ impl ImageEventContent {
|
|||||||
relates_to: None,
|
relates_to: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `ImageEventContent` from the given `ImageMessageEventContent` and optional
|
|
||||||
/// relation.
|
|
||||||
pub fn from_image_room_message(
|
|
||||||
content: ImageMessageEventContent,
|
|
||||||
relates_to: Option<Relation>,
|
|
||||||
) -> Self {
|
|
||||||
let ImageMessageEventContent {
|
|
||||||
body,
|
|
||||||
source,
|
|
||||||
info,
|
|
||||||
message,
|
|
||||||
file,
|
|
||||||
image,
|
|
||||||
thumbnail,
|
|
||||||
caption,
|
|
||||||
} = content;
|
|
||||||
let ImageInfo { height, width, mimetype, size, thumbnail_info, thumbnail_source, .. } =
|
|
||||||
info.map(|info| *info).unwrap_or_default();
|
|
||||||
|
|
||||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
|
||||||
let file = file.unwrap_or_else(|| {
|
|
||||||
FileContent::from_room_message_content(source, None, mimetype, size)
|
|
||||||
});
|
|
||||||
let image = image
|
|
||||||
.or_else(|| ImageContent::from_room_message_content(width, height).map(Box::new))
|
|
||||||
.unwrap_or_default();
|
|
||||||
let thumbnail = thumbnail.unwrap_or_else(|| {
|
|
||||||
ThumbnailContent::from_room_message_content(thumbnail_source, thumbnail_info)
|
|
||||||
.into_iter()
|
|
||||||
.collect()
|
|
||||||
});
|
|
||||||
|
|
||||||
Self { message, file, image, thumbnail, caption, relates_to }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ImageEventContent> for RoomMessageEventContent {
|
|
||||||
fn from(content: ImageEventContent) -> Self {
|
|
||||||
let ImageEventContent { message, file, image, thumbnail, caption, relates_to } = content;
|
|
||||||
|
|
||||||
Self {
|
|
||||||
msgtype: MessageType::Image(ImageMessageEventContent::from_extensible_content(
|
|
||||||
message, file, image, thumbnail, caption,
|
|
||||||
)),
|
|
||||||
relates_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Image content.
|
/// Image content.
|
||||||
|
@ -8,10 +8,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
mod zoomlevel_serde;
|
mod zoomlevel_serde;
|
||||||
|
|
||||||
use super::{
|
use super::{message::MessageContent, room::message::Relation};
|
||||||
message::MessageContent,
|
|
||||||
room::message::{LocationMessageEventContent, MessageType, Relation, RoomMessageEventContent},
|
|
||||||
};
|
|
||||||
use crate::{MilliSecondsSinceUnixEpoch, PrivOwnedStr};
|
use crate::{MilliSecondsSinceUnixEpoch, PrivOwnedStr};
|
||||||
|
|
||||||
/// The payload for an extensible location message.
|
/// The payload for an extensible location message.
|
||||||
@ -19,14 +16,8 @@ use crate::{MilliSecondsSinceUnixEpoch, PrivOwnedStr};
|
|||||||
/// This is the new primary type introduced in [MSC3488] and should not be sent before the end of
|
/// This is the new primary type introduced in [MSC3488] and should not be sent before the end of
|
||||||
/// the transition period. See the documentation of the [`message`] module for more information.
|
/// the transition period. See the documentation of the [`message`] module for more information.
|
||||||
///
|
///
|
||||||
/// `LocationEventContent` can be converted to a [`RoomMessageEventContent`] with a
|
|
||||||
/// [`MessageType::Location`]. You can convert it back with
|
|
||||||
/// [`LocationEventContent::from_location_room_message()`].
|
|
||||||
///
|
|
||||||
/// [MSC3488]: https://github.com/matrix-org/matrix-spec-proposals/pull/3488
|
/// [MSC3488]: https://github.com/matrix-org/matrix-spec-proposals/pull/3488
|
||||||
/// [`message`]: super::message
|
/// [`message`]: super::message
|
||||||
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
|
|
||||||
/// [`MessageType::Location`]: super::room::message::MessageType::Location
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.location", kind = MessageLike, without_relation)]
|
#[ruma_event(type = "m.location", kind = MessageLike, without_relation)]
|
||||||
@ -68,35 +59,6 @@ impl LocationEventContent {
|
|||||||
pub fn with_message(message: MessageContent, location: LocationContent) -> Self {
|
pub fn with_message(message: MessageContent, location: LocationContent) -> Self {
|
||||||
Self { message, location, asset: Default::default(), ts: None, relates_to: None }
|
Self { message, location, asset: Default::default(), ts: None, relates_to: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `LocationEventContent` from the given `LocationMessageEventContent` and
|
|
||||||
/// optional relation.
|
|
||||||
pub fn from_location_room_message(
|
|
||||||
content: LocationMessageEventContent,
|
|
||||||
relates_to: Option<Relation>,
|
|
||||||
) -> Self {
|
|
||||||
let LocationMessageEventContent { body, geo_uri, message, location, asset, ts, .. } =
|
|
||||||
content;
|
|
||||||
|
|
||||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
|
||||||
let location = location.unwrap_or_else(|| LocationContent::new(geo_uri));
|
|
||||||
let asset = asset.unwrap_or_default();
|
|
||||||
|
|
||||||
Self { message, location, asset, ts, relates_to }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<LocationEventContent> for RoomMessageEventContent {
|
|
||||||
fn from(content: LocationEventContent) -> Self {
|
|
||||||
let LocationEventContent { message, location, asset, ts, relates_to } = content;
|
|
||||||
|
|
||||||
Self {
|
|
||||||
msgtype: MessageType::Location(LocationMessageEventContent::from_extensible_content(
|
|
||||||
message, location, asset, ts,
|
|
||||||
)),
|
|
||||||
relates_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Location content.
|
/// Location content.
|
||||||
|
@ -27,17 +27,9 @@
|
|||||||
//! the `unstable-mscXXXX` features (where `XXXX` is the number of the MSC).
|
//! the `unstable-mscXXXX` features (where `XXXX` is the number of the MSC).
|
||||||
//!
|
//!
|
||||||
//! The recommended way to send transitional extensible events while they are unstable and during
|
//! The recommended way to send transitional extensible events while they are unstable and during
|
||||||
//! the transition period is to build one of the new primary types and then to convert it to a
|
//! the transition period is to use the constructors and helper methods of
|
||||||
//! [`RoomMessageEventContent`] by using `.into()` or `RoomMessageEventContent::from()`. The
|
//! [`RoomMessageEventContent`]. The data will be duplicated in both the legacy and extensible
|
||||||
//! provided constructors will copy the relevant data in the legacy fields.
|
//! events fields as needed.
|
||||||
//!
|
|
||||||
//! For incoming events, a `RoomMessageEventContent` can be converted to an extensible event with
|
|
||||||
//! the relevant `from_*_room_message` method on the primary type. This conversion will work even
|
|
||||||
//! with legacy `m.room.message` events that don't have extensible events content.
|
|
||||||
//!
|
|
||||||
//! It is also possible to enable extensible events support and continue using
|
|
||||||
//! `RoomMessageEventContent`'s constructors. The data will be duplicated in both the legacy and
|
|
||||||
//! extensible events fields.
|
|
||||||
//!
|
//!
|
||||||
//! [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
//! [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
||||||
//! [1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
//! [1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
||||||
@ -48,6 +40,7 @@
|
|||||||
//! [3488]: https://github.com/matrix-org/matrix-spec-proposals/pull/3488
|
//! [3488]: https://github.com/matrix-org/matrix-spec-proposals/pull/3488
|
||||||
//! [MSC3245]: https://github.com/matrix-org/matrix-spec-proposals/pull/3245
|
//! [MSC3245]: https://github.com/matrix-org/matrix-spec-proposals/pull/3245
|
||||||
//! [MSC3381]: https://github.com/matrix-org/matrix-spec-proposals/pull/3381
|
//! [MSC3381]: https://github.com/matrix-org/matrix-spec-proposals/pull/3381
|
||||||
|
//! [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use ruma_macros::EventContent;
|
use ruma_macros::EventContent;
|
||||||
@ -58,10 +51,7 @@ pub(crate) mod content_serde;
|
|||||||
|
|
||||||
use content_serde::MessageContentSerDeHelper;
|
use content_serde::MessageContentSerDeHelper;
|
||||||
|
|
||||||
use super::room::message::{
|
use super::room::message::Relation;
|
||||||
FormattedBody, MessageFormat, MessageType, Relation, RoomMessageEventContent,
|
|
||||||
TextMessageEventContent,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The payload for an extensible text message.
|
/// The payload for an extensible text message.
|
||||||
///
|
///
|
||||||
@ -71,14 +61,8 @@ use super::room::message::{
|
|||||||
/// To construct a `MessageEventContent` with a custom [`MessageContent`], convert it with
|
/// To construct a `MessageEventContent` with a custom [`MessageContent`], convert it with
|
||||||
/// `MessageEventContent::from()` / `.into()`.
|
/// `MessageEventContent::from()` / `.into()`.
|
||||||
///
|
///
|
||||||
/// `MessageEventContent` can be converted to a [`RoomMessageEventContent`] with a
|
|
||||||
/// [`MessageType::Text`]. You can convert it back with
|
|
||||||
/// [`MessageEventContent::from_text_room_message()`].
|
|
||||||
///
|
|
||||||
/// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
/// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
||||||
/// [`message`]: super::message
|
/// [`message`]: super::message
|
||||||
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
|
|
||||||
/// [`MessageType::Text`]: super::room::message::MessageType::Text
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.message", kind = MessageLike, without_relation)]
|
#[ruma_event(type = "m.message", kind = MessageLike, without_relation)]
|
||||||
@ -111,20 +95,6 @@ impl MessageEventContent {
|
|||||||
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
|
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
|
||||||
Self { message: MessageContent::markdown(body), relates_to: None }
|
Self { message: MessageContent::markdown(body), relates_to: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `MessageEventContent` from the given `TextMessageEventContent` and optional
|
|
||||||
/// relation.
|
|
||||||
pub fn from_text_room_message(
|
|
||||||
content: TextMessageEventContent,
|
|
||||||
relates_to: Option<Relation>,
|
|
||||||
) -> Self {
|
|
||||||
let TextMessageEventContent { body, formatted, message, .. } = content;
|
|
||||||
if let Some(message) = message {
|
|
||||||
Self { message, relates_to }
|
|
||||||
} else {
|
|
||||||
Self { message: MessageContent::from_room_message_content(body, formatted), relates_to }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MessageContent> for MessageEventContent {
|
impl From<MessageContent> for MessageEventContent {
|
||||||
@ -133,14 +103,6 @@ impl From<MessageContent> for MessageEventContent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<MessageEventContent> for RoomMessageEventContent {
|
|
||||||
fn from(content: MessageEventContent) -> Self {
|
|
||||||
let MessageEventContent { message, relates_to, .. } = content;
|
|
||||||
|
|
||||||
Self { msgtype: MessageType::Text(message.into()), relates_to }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Text message content.
|
/// Text message content.
|
||||||
///
|
///
|
||||||
/// A `MessageContent` must contain at least one message to be used as a fallback text
|
/// A `MessageContent` must contain at least one message to be used as a fallback text
|
||||||
@ -188,20 +150,6 @@ impl MessageContent {
|
|||||||
Self(message)
|
Self(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `MessageContent` from the given body and optional formatted body.
|
|
||||||
pub(crate) fn from_room_message_content(
|
|
||||||
body: String,
|
|
||||||
formatted: Option<FormattedBody>,
|
|
||||||
) -> Self {
|
|
||||||
if let Some(FormattedBody { body: html_body, .. }) =
|
|
||||||
formatted.filter(|formatted| formatted.format == MessageFormat::Html)
|
|
||||||
{
|
|
||||||
Self::html(body, html_body)
|
|
||||||
} else {
|
|
||||||
Self::plain(body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the plain text representation of this message.
|
/// Get the plain text representation of this message.
|
||||||
pub fn find_plain(&self) -> Option<&str> {
|
pub fn find_plain(&self) -> Option<&str> {
|
||||||
self.iter()
|
self.iter()
|
||||||
|
@ -5,24 +5,15 @@
|
|||||||
use ruma_macros::EventContent;
|
use ruma_macros::EventContent;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{
|
use super::{message::MessageContent, room::message::Relation};
|
||||||
message::MessageContent,
|
|
||||||
room::message::{MessageType, NoticeMessageEventContent, Relation, RoomMessageEventContent},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The payload for an extensible notice message.
|
/// The payload for an extensible notice message.
|
||||||
///
|
///
|
||||||
/// This is the new primary type introduced in [MSC1767] and should not be sent before the end of
|
/// This is the new primary type introduced in [MSC1767] and should not be sent before the end of
|
||||||
/// the transition period. See the documentation of the [`message`] module for more information.
|
/// the transition period. See the documentation of the [`message`] module for more information.
|
||||||
///
|
///
|
||||||
/// `NoticeEventContent` can be converted to a [`RoomMessageEventContent`] with a
|
|
||||||
/// [`MessageType::Notice`]. You can convert it back with
|
|
||||||
/// [`NoticeEventContent::from_notice_room_message()`].
|
|
||||||
///
|
|
||||||
/// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
/// [MSC1767]: https://github.com/matrix-org/matrix-spec-proposals/pull/1767
|
||||||
/// [`message`]: super::message
|
/// [`message`]: super::message
|
||||||
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
|
|
||||||
/// [`MessageType::Notice`]: super::room::message::MessageType::Notice
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.notice", kind = MessageLike, without_relation)]
|
#[ruma_event(type = "m.notice", kind = MessageLike, without_relation)]
|
||||||
@ -55,26 +46,4 @@ impl NoticeEventContent {
|
|||||||
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
|
pub fn markdown(body: impl AsRef<str> + Into<String>) -> Self {
|
||||||
Self { message: MessageContent::markdown(body), relates_to: None }
|
Self { message: MessageContent::markdown(body), relates_to: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `NoticeEventContent` from the given `NoticeMessageEventContent` and optional
|
|
||||||
/// relation.
|
|
||||||
pub fn from_notice_room_message(
|
|
||||||
content: NoticeMessageEventContent,
|
|
||||||
relates_to: Option<Relation>,
|
|
||||||
) -> Self {
|
|
||||||
let NoticeMessageEventContent { body, formatted, message, .. } = content;
|
|
||||||
if let Some(message) = message {
|
|
||||||
Self { message, relates_to }
|
|
||||||
} else {
|
|
||||||
Self { message: MessageContent::from_room_message_content(body, formatted), relates_to }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<NoticeEventContent> for RoomMessageEventContent {
|
|
||||||
fn from(content: NoticeEventContent) -> Self {
|
|
||||||
let NoticeEventContent { message, relates_to, .. } = content;
|
|
||||||
|
|
||||||
Self { msgtype: MessageType::Notice(message.into()), relates_to }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,7 @@ use serde::{de, Deserialize, Serialize};
|
|||||||
#[cfg(feature = "unstable-msc3551")]
|
#[cfg(feature = "unstable-msc3551")]
|
||||||
use super::file::{EncryptedContent, EncryptedContentInit, FileContent};
|
use super::file::{EncryptedContent, EncryptedContentInit, FileContent};
|
||||||
#[cfg(feature = "unstable-msc3552")]
|
#[cfg(feature = "unstable-msc3552")]
|
||||||
use super::{
|
use super::image::ThumbnailFileContent;
|
||||||
file::FileContentInfo,
|
|
||||||
image::{ImageContent, ThumbnailContent, ThumbnailFileContent, ThumbnailFileContentInfo},
|
|
||||||
};
|
|
||||||
#[cfg(feature = "unstable-msc3551")]
|
#[cfg(feature = "unstable-msc3551")]
|
||||||
use crate::MxcUri;
|
use crate::MxcUri;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -165,48 +162,6 @@ impl ImageInfo {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an `ImageInfo` from the given file info, image info and thumbnail.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the `ImageInfo` would be empty.
|
|
||||||
#[cfg(feature = "unstable-msc3552")]
|
|
||||||
fn from_extensible_content(
|
|
||||||
file_info: Option<&FileContentInfo>,
|
|
||||||
image: &ImageContent,
|
|
||||||
thumbnail: &[ThumbnailContent],
|
|
||||||
) -> Option<Self> {
|
|
||||||
if file_info.is_none() && image.is_empty() && thumbnail.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let (mimetype, size) = file_info
|
|
||||||
.map(|info| (info.mimetype.to_owned(), info.size.to_owned()))
|
|
||||||
.unwrap_or_default();
|
|
||||||
let ImageContent { height, width } = image.to_owned();
|
|
||||||
let (thumbnail_source, thumbnail_info) = thumbnail
|
|
||||||
.get(0)
|
|
||||||
.map(|thumbnail| {
|
|
||||||
let source = (&thumbnail.file).into();
|
|
||||||
let info = ThumbnailInfo::from_extensible_content(
|
|
||||||
thumbnail.file.info.as_deref(),
|
|
||||||
thumbnail.image.as_deref(),
|
|
||||||
)
|
|
||||||
.map(Box::new);
|
|
||||||
(Some(source), info)
|
|
||||||
})
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
Some(Self {
|
|
||||||
height,
|
|
||||||
width,
|
|
||||||
mimetype,
|
|
||||||
size,
|
|
||||||
thumbnail_source,
|
|
||||||
thumbnail_info,
|
|
||||||
#[cfg(feature = "unstable-msc2448")]
|
|
||||||
blurhash: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata about a thumbnail.
|
/// Metadata about a thumbnail.
|
||||||
@ -235,24 +190,6 @@ impl ThumbnailInfo {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `ThumbnailInfo` with the given file info and image info.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the `ThumbnailInfo` would be empty.
|
|
||||||
#[cfg(feature = "unstable-msc3552")]
|
|
||||||
fn from_extensible_content(
|
|
||||||
file_info: Option<&ThumbnailFileContentInfo>,
|
|
||||||
image: Option<&ImageContent>,
|
|
||||||
) -> Option<Self> {
|
|
||||||
if file_info.is_none() && image.is_none() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let ThumbnailFileContentInfo { mimetype, size } =
|
|
||||||
file_info.map(ToOwned::to_owned).unwrap_or_default();
|
|
||||||
let ImageContent { height, width } = image.map(ToOwned::to_owned).unwrap_or_default();
|
|
||||||
Some(Self { height, width, mimetype, size })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A file sent to a room with end-to-end encryption enabled.
|
/// A file sent to a room with end-to-end encryption enabled.
|
||||||
|
@ -98,24 +98,6 @@ impl FileMessageEventContent {
|
|||||||
info: None,
|
info: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `FileMessageEventContent` with the given message and file info.
|
|
||||||
#[cfg(feature = "unstable-msc3551")]
|
|
||||||
pub(crate) fn from_extensible_content(message: MessageContent, file: FileContent) -> Self {
|
|
||||||
let body = if let Some(body) = message.find_plain() {
|
|
||||||
body.to_owned()
|
|
||||||
} else {
|
|
||||||
message[0].body.clone()
|
|
||||||
};
|
|
||||||
let filename = file.info.as_deref().and_then(|info| info.name.clone());
|
|
||||||
let info = file.info.as_deref().and_then(|info| {
|
|
||||||
FileInfo::from_extensible_content(info.mimetype.to_owned(), info.size.to_owned())
|
|
||||||
.map(Box::new)
|
|
||||||
});
|
|
||||||
let source = (&file).into();
|
|
||||||
|
|
||||||
Self { message: Some(message), file: Some(file), body, filename, source, info }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata about a file.
|
/// Metadata about a file.
|
||||||
@ -148,16 +130,4 @@ impl FileInfo {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `FileInfo` with the given optional mimetype and size.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the `FileInfo` would be empty.
|
|
||||||
#[cfg(feature = "unstable-msc3551")]
|
|
||||||
fn from_extensible_content(mimetype: Option<String>, size: Option<UInt>) -> Option<Self> {
|
|
||||||
if mimetype.is_none() && size.is_none() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(Self { mimetype, size, ..Default::default() })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -143,36 +143,4 @@ impl ImageMessageEventContent {
|
|||||||
info: None,
|
info: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `ImageMessageEventContent` with the given message, file info, image info,
|
|
||||||
/// thumbnails and captions.
|
|
||||||
#[cfg(feature = "unstable-msc3552")]
|
|
||||||
pub(crate) fn from_extensible_content(
|
|
||||||
message: MessageContent,
|
|
||||||
file: FileContent,
|
|
||||||
image: Box<ImageContent>,
|
|
||||||
thumbnail: Vec<ThumbnailContent>,
|
|
||||||
caption: Option<MessageContent>,
|
|
||||||
) -> Self {
|
|
||||||
let body = if let Some(body) = message.find_plain() {
|
|
||||||
body.to_owned()
|
|
||||||
} else {
|
|
||||||
message[0].body.clone()
|
|
||||||
};
|
|
||||||
let source = (&file).into();
|
|
||||||
let info = ImageInfo::from_extensible_content(file.info.as_deref(), &image, &thumbnail)
|
|
||||||
.map(Box::new);
|
|
||||||
let thumbnail = if thumbnail.is_empty() { None } else { Some(thumbnail) };
|
|
||||||
|
|
||||||
Self {
|
|
||||||
message: Some(message),
|
|
||||||
file: Some(file),
|
|
||||||
image: Some(image),
|
|
||||||
thumbnail,
|
|
||||||
caption,
|
|
||||||
body,
|
|
||||||
source,
|
|
||||||
info,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -78,33 +78,6 @@ impl LocationMessageEventContent {
|
|||||||
info: None,
|
info: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `LocationMessageEventContent` with the given message, location info, asset and
|
|
||||||
/// timestamp.
|
|
||||||
#[cfg(feature = "unstable-msc3488")]
|
|
||||||
pub(crate) fn from_extensible_content(
|
|
||||||
message: MessageContent,
|
|
||||||
location: LocationContent,
|
|
||||||
asset: AssetContent,
|
|
||||||
ts: Option<MilliSecondsSinceUnixEpoch>,
|
|
||||||
) -> Self {
|
|
||||||
let body = if let Some(body) = message.find_plain() {
|
|
||||||
body.to_owned()
|
|
||||||
} else {
|
|
||||||
message[0].body.clone()
|
|
||||||
};
|
|
||||||
let geo_uri = location.uri.clone();
|
|
||||||
|
|
||||||
Self {
|
|
||||||
message: Some(message),
|
|
||||||
location: Some(location),
|
|
||||||
asset: Some(asset),
|
|
||||||
ts,
|
|
||||||
body,
|
|
||||||
geo_uri,
|
|
||||||
info: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Thumbnail info associated with a location.
|
/// Thumbnail info associated with a location.
|
||||||
|
@ -149,38 +149,6 @@ impl VideoMessageEventContent {
|
|||||||
info: None,
|
info: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `VideoMessageEventContent` with the given message, file info, video info,
|
|
||||||
/// thumbnails and captions.
|
|
||||||
#[cfg(feature = "unstable-msc3553")]
|
|
||||||
pub(crate) fn from_extensible_content(
|
|
||||||
message: MessageContent,
|
|
||||||
file: FileContent,
|
|
||||||
video: Box<VideoContent>,
|
|
||||||
thumbnail: Vec<ThumbnailContent>,
|
|
||||||
caption: Option<MessageContent>,
|
|
||||||
) -> Self {
|
|
||||||
let body = if let Some(body) = message.find_plain() {
|
|
||||||
body.to_owned()
|
|
||||||
} else {
|
|
||||||
message[0].body.clone()
|
|
||||||
};
|
|
||||||
let source = (&file).into();
|
|
||||||
let info = VideoInfo::from_extensible_content(file.info.as_deref(), &video, &thumbnail)
|
|
||||||
.map(Box::new);
|
|
||||||
let thumbnail = if thumbnail.is_empty() { None } else { Some(thumbnail) };
|
|
||||||
|
|
||||||
Self {
|
|
||||||
message: Some(message),
|
|
||||||
file: Some(file),
|
|
||||||
video: Some(video),
|
|
||||||
thumbnail,
|
|
||||||
caption,
|
|
||||||
body,
|
|
||||||
source,
|
|
||||||
info,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Metadata about a video.
|
/// Metadata about a video.
|
||||||
@ -237,47 +205,4 @@ impl VideoInfo {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a `VideoInfo` from the given file info, video info and thumbnail.
|
|
||||||
///
|
|
||||||
/// Returns `None` if the `VideoInfo` would be empty.
|
|
||||||
#[cfg(feature = "unstable-msc3553")]
|
|
||||||
fn from_extensible_content(
|
|
||||||
file_info: Option<&FileContentInfo>,
|
|
||||||
video: &VideoContent,
|
|
||||||
thumbnail: &[ThumbnailContent],
|
|
||||||
) -> Option<Self> {
|
|
||||||
if file_info.is_none() && video.is_empty() && thumbnail.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let (mimetype, size) = file_info
|
|
||||||
.map(|info| (info.mimetype.to_owned(), info.size.to_owned()))
|
|
||||||
.unwrap_or_default();
|
|
||||||
let VideoContent { duration, height, width } = video.to_owned();
|
|
||||||
let (thumbnail_source, thumbnail_info) = thumbnail
|
|
||||||
.get(0)
|
|
||||||
.map(|thumbnail| {
|
|
||||||
let source = (&thumbnail.file).into();
|
|
||||||
let info = ThumbnailInfo::from_extensible_content(
|
|
||||||
thumbnail.file.info.as_deref(),
|
|
||||||
thumbnail.image.as_deref(),
|
|
||||||
)
|
|
||||||
.map(Box::new);
|
|
||||||
(Some(source), info)
|
|
||||||
})
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
Some(Self {
|
|
||||||
duration,
|
|
||||||
height,
|
|
||||||
width,
|
|
||||||
mimetype,
|
|
||||||
size,
|
|
||||||
thumbnail_info,
|
|
||||||
thumbnail_source,
|
|
||||||
#[cfg(feature = "unstable-msc2448")]
|
|
||||||
blurhash: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,7 @@ use ruma_macros::EventContent;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
file::FileContent,
|
file::FileContent, image::ThumbnailContent, message::MessageContent, room::message::Relation,
|
||||||
image::ThumbnailContent,
|
|
||||||
message::MessageContent,
|
|
||||||
room::message::{
|
|
||||||
MessageType, Relation, RoomMessageEventContent, VideoInfo, VideoMessageEventContent,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The payload for an extensible video message.
|
/// The payload for an extensible video message.
|
||||||
@ -22,14 +17,8 @@ use super::{
|
|||||||
/// This is the new primary type introduced in [MSC3553] and should not be sent before the end of
|
/// This is the new primary type introduced in [MSC3553] and should not be sent before the end of
|
||||||
/// the transition period. See the documentation of the [`message`] module for more information.
|
/// the transition period. See the documentation of the [`message`] module for more information.
|
||||||
///
|
///
|
||||||
/// `VideoEventContent` can be converted to a [`RoomMessageEventContent`] with a
|
|
||||||
/// [`MessageType::Video`]. You can convert it back with
|
|
||||||
/// [`VideoEventContent::from_video_room_message()`].
|
|
||||||
///
|
|
||||||
/// [MSC3553]: https://github.com/matrix-org/matrix-spec-proposals/pull/3553
|
/// [MSC3553]: https://github.com/matrix-org/matrix-spec-proposals/pull/3553
|
||||||
/// [`message`]: super::message
|
/// [`message`]: super::message
|
||||||
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
|
|
||||||
/// [`MessageType::Video`]: super::room::message::MessageType::Video
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.video", kind = MessageLike, without_relation)]
|
#[ruma_event(type = "m.video", kind = MessageLike, without_relation)]
|
||||||
@ -88,62 +77,6 @@ impl VideoEventContent {
|
|||||||
relates_to: None,
|
relates_to: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `VideoEventContent` from the given `VideoMessageEventContent` and optional
|
|
||||||
/// relation.
|
|
||||||
pub fn from_video_room_message(
|
|
||||||
content: VideoMessageEventContent,
|
|
||||||
relates_to: Option<Relation>,
|
|
||||||
) -> Self {
|
|
||||||
let VideoMessageEventContent {
|
|
||||||
body,
|
|
||||||
source,
|
|
||||||
info,
|
|
||||||
message,
|
|
||||||
file,
|
|
||||||
video,
|
|
||||||
thumbnail,
|
|
||||||
caption,
|
|
||||||
} = content;
|
|
||||||
let VideoInfo {
|
|
||||||
duration,
|
|
||||||
height,
|
|
||||||
width,
|
|
||||||
mimetype,
|
|
||||||
size,
|
|
||||||
thumbnail_info,
|
|
||||||
thumbnail_source,
|
|
||||||
..
|
|
||||||
} = info.map(|info| *info).unwrap_or_default();
|
|
||||||
|
|
||||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
|
||||||
let file = file.unwrap_or_else(|| {
|
|
||||||
FileContent::from_room_message_content(source, None, mimetype, size)
|
|
||||||
});
|
|
||||||
let video = video.unwrap_or_else(|| {
|
|
||||||
Box::new(VideoContent::from_room_message_content(height, width, duration))
|
|
||||||
});
|
|
||||||
let thumbnail = thumbnail.unwrap_or_else(|| {
|
|
||||||
ThumbnailContent::from_room_message_content(thumbnail_source, thumbnail_info)
|
|
||||||
.into_iter()
|
|
||||||
.collect()
|
|
||||||
});
|
|
||||||
|
|
||||||
Self { message, file, video, thumbnail, caption, relates_to }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<VideoEventContent> for RoomMessageEventContent {
|
|
||||||
fn from(content: VideoEventContent) -> Self {
|
|
||||||
let VideoEventContent { message, file, video, thumbnail, caption, relates_to } = content;
|
|
||||||
|
|
||||||
Self {
|
|
||||||
msgtype: MessageType::Video(VideoMessageEventContent::from_extensible_content(
|
|
||||||
message, file, video, thumbnail, caption,
|
|
||||||
)),
|
|
||||||
relates_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Video content.
|
/// Video content.
|
||||||
|
@ -6,12 +6,7 @@ use ruma_macros::EventContent;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
audio::AudioContent,
|
audio::AudioContent, file::FileContent, message::MessageContent, room::message::Relation,
|
||||||
file::FileContent,
|
|
||||||
message::{MessageContent, TryFromExtensibleError},
|
|
||||||
room::message::{
|
|
||||||
AudioInfo, AudioMessageEventContent, MessageType, Relation, RoomMessageEventContent,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The payload for an extensible voice message.
|
/// The payload for an extensible voice message.
|
||||||
@ -19,14 +14,8 @@ use super::{
|
|||||||
/// This is the new primary type introduced in [MSC3245] and should not be sent before the end of
|
/// This is the new primary type introduced in [MSC3245] and should not be sent before the end of
|
||||||
/// the transition period. See the documentation of the [`message`] module for more information.
|
/// the transition period. See the documentation of the [`message`] module for more information.
|
||||||
///
|
///
|
||||||
/// `VoiceEventContent` can be converted to a [`RoomMessageEventContent`] with a
|
|
||||||
/// [`MessageType::Audio`] with the `m.voice` flag. You can convert it back with
|
|
||||||
/// [`VoiceEventContent::try_from_audio_room_message()`].
|
|
||||||
///
|
|
||||||
/// [MSC3245]: https://github.com/matrix-org/matrix-spec-proposals/pull/3245
|
/// [MSC3245]: https://github.com/matrix-org/matrix-spec-proposals/pull/3245
|
||||||
/// [`message`]: super::message
|
/// [`message`]: super::message
|
||||||
/// [`RoomMessageEventContent`]: super::room::message::RoomMessageEventContent
|
|
||||||
/// [`MessageType::Audio`]: super::room::message::MessageType::Audio
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
#[derive(Clone, Debug, Serialize, Deserialize, EventContent)]
|
||||||
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
|
||||||
#[ruma_event(type = "m.voice", kind = MessageLike, without_relation)]
|
#[ruma_event(type = "m.voice", kind = MessageLike, without_relation)]
|
||||||
@ -74,46 +63,6 @@ impl VoiceEventContent {
|
|||||||
relates_to: None,
|
relates_to: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new `VoiceEventContent` from the given `AudioMessageEventContent` and optional
|
|
||||||
/// relation.
|
|
||||||
///
|
|
||||||
/// This can fail if the `AudioMessageEventContent` is not a voice message.
|
|
||||||
pub fn try_from_audio_room_message(
|
|
||||||
content: AudioMessageEventContent,
|
|
||||||
relates_to: Option<Relation>,
|
|
||||||
) -> Result<Self, TryFromExtensibleError> {
|
|
||||||
let AudioMessageEventContent { body, source, info, message, file, audio, voice } = content;
|
|
||||||
let AudioInfo { duration, mimetype, size } = info.map(|info| *info).unwrap_or_default();
|
|
||||||
|
|
||||||
let message = message.unwrap_or_else(|| MessageContent::plain(body));
|
|
||||||
let file = file.unwrap_or_else(|| {
|
|
||||||
FileContent::from_room_message_content(source, None, mimetype, size)
|
|
||||||
});
|
|
||||||
let audio = audio
|
|
||||||
.or_else(|| duration.map(AudioContent::from_room_message_content))
|
|
||||||
.unwrap_or_default();
|
|
||||||
let voice = if let Some(voice) = voice {
|
|
||||||
voice
|
|
||||||
} else {
|
|
||||||
return Err(TryFromExtensibleError::MissingField("m.voice".to_owned()));
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Self { message, file, audio, voice, relates_to })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<VoiceEventContent> for RoomMessageEventContent {
|
|
||||||
fn from(content: VoiceEventContent) -> Self {
|
|
||||||
let VoiceEventContent { message, file, audio, voice, relates_to } = content;
|
|
||||||
|
|
||||||
Self {
|
|
||||||
msgtype: MessageType::Audio(AudioMessageEventContent::from_extensible_voice_content(
|
|
||||||
message, file, audio, voice,
|
|
||||||
)),
|
|
||||||
relates_to,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Voice content.
|
/// Voice content.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user