Skip to content

Commit 721b7aa

Browse files
committed
feat(ffi): Expose sending method for sending galleries
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
1 parent d3be744 commit 721b7aa

File tree

6 files changed

+606
-85
lines changed

6 files changed

+606
-85
lines changed

bindings/matrix-sdk-ffi/src/event.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ pub enum RoomMessageEventMessageType {
387387
Audio,
388388
Emote,
389389
File,
390+
Gallery,
390391
Image,
391392
Location,
392393
Notice,
@@ -403,6 +404,7 @@ impl From<RumaMessageType> for RoomMessageEventMessageType {
403404
RumaMessageType::Audio { .. } => Self::Audio,
404405
RumaMessageType::Emote { .. } => Self::Emote,
405406
RumaMessageType::File { .. } => Self::File,
407+
RumaMessageType::Gallery { .. } => Self::Gallery,
406408
RumaMessageType::Image { .. } => Self::Image,
407409
RumaMessageType::Location { .. } => Self::Location,
408410
RumaMessageType::Notice { .. } => Self::Notice,

bindings/matrix-sdk-ffi/src/ruma.rs

Lines changed: 199 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ use ruma::{
4242
AudioMessageEventContent as RumaAudioMessageEventContent,
4343
EmoteMessageEventContent as RumaEmoteMessageEventContent, FileInfo as RumaFileInfo,
4444
FileMessageEventContent as RumaFileMessageEventContent,
45-
FormattedBody as RumaFormattedBody,
45+
FormattedBody as RumaFormattedBody, GalleryItemType as RumaGalleryItemType,
46+
GalleryMessageEventContent as RumaGalleryMessageEventContent,
4647
ImageMessageEventContent as RumaImageMessageEventContent,
4748
LocationMessageEventContent as RumaLocationMessageEventContent,
4849
MessageType as RumaMessageType,
@@ -350,6 +351,7 @@ pub enum MessageType {
350351
Audio { content: AudioMessageContent },
351352
Video { content: VideoMessageContent },
352353
File { content: FileMessageContent },
354+
Gallery { content: GalleryMessageContent },
353355
Notice { content: NoticeMessageContent },
354356
Text { content: TextMessageContent },
355357
Location { content: LocationContent },
@@ -383,44 +385,11 @@ impl TryFrom<MessageType> for RumaMessageType {
383385
formatted: content.formatted.map(Into::into),
384386
}))
385387
}
386-
MessageType::Image { content } => {
387-
let (body, filename) = get_body_and_filename(content.filename, content.caption);
388-
let mut event_content =
389-
RumaImageMessageEventContent::new(body, (*content.source).clone().into())
390-
.info(content.info.map(Into::into).map(Box::new));
391-
event_content.formatted = content.formatted_caption.map(Into::into);
392-
event_content.filename = filename;
393-
Self::Image(event_content)
394-
}
395-
MessageType::Audio { content } => {
396-
let (body, filename) = get_body_and_filename(content.filename, content.caption);
397-
let mut event_content =
398-
RumaAudioMessageEventContent::new(body, (*content.source).clone().into())
399-
.info(content.info.map(Into::into).map(Box::new));
400-
event_content.formatted = content.formatted_caption.map(Into::into);
401-
event_content.filename = filename;
402-
event_content.audio = content.audio.map(Into::into);
403-
event_content.voice = content.voice.map(Into::into);
404-
Self::Audio(event_content)
405-
}
406-
MessageType::Video { content } => {
407-
let (body, filename) = get_body_and_filename(content.filename, content.caption);
408-
let mut event_content =
409-
RumaVideoMessageEventContent::new(body, (*content.source).clone().into())
410-
.info(content.info.map(Into::into).map(Box::new));
411-
event_content.formatted = content.formatted_caption.map(Into::into);
412-
event_content.filename = filename;
413-
Self::Video(event_content)
414-
}
415-
MessageType::File { content } => {
416-
let (body, filename) = get_body_and_filename(content.filename, content.caption);
417-
let mut event_content =
418-
RumaFileMessageEventContent::new(body, (*content.source).clone().into())
419-
.info(content.info.map(Into::into).map(Box::new));
420-
event_content.formatted = content.formatted_caption.map(Into::into);
421-
event_content.filename = filename;
422-
Self::File(event_content)
423-
}
388+
MessageType::Image { content } => Self::Image(content.into()),
389+
MessageType::Audio { content } => Self::Audio(content.into()),
390+
MessageType::Video { content } => Self::Video(content.into()),
391+
MessageType::File { content } => Self::File(content.into()),
392+
MessageType::Gallery { content } => Self::Gallery(content.try_into()?),
424393
MessageType::Notice { content } => {
425394
Self::Notice(assign!(RumaNoticeMessageEventContent::plain(content.body), {
426395
formatted: content.formatted.map(Into::into),
@@ -452,45 +421,11 @@ impl TryFrom<RumaMessageType> for MessageType {
452421
formatted: c.formatted.as_ref().map(Into::into),
453422
},
454423
},
455-
RumaMessageType::Image(c) => MessageType::Image {
456-
content: ImageMessageContent {
457-
filename: c.filename().to_owned(),
458-
caption: c.caption().map(ToString::to_string),
459-
formatted_caption: c.formatted_caption().map(Into::into),
460-
source: Arc::new(c.source.try_into()?),
461-
info: c.info.as_deref().map(TryInto::try_into).transpose()?,
462-
},
463-
},
464-
465-
RumaMessageType::Audio(c) => MessageType::Audio {
466-
content: AudioMessageContent {
467-
filename: c.filename().to_owned(),
468-
caption: c.caption().map(ToString::to_string),
469-
formatted_caption: c.formatted_caption().map(Into::into),
470-
source: Arc::new(c.source.try_into()?),
471-
info: c.info.as_deref().map(Into::into),
472-
audio: c.audio.map(Into::into),
473-
voice: c.voice.map(Into::into),
474-
},
475-
},
476-
RumaMessageType::Video(c) => MessageType::Video {
477-
content: VideoMessageContent {
478-
filename: c.filename().to_owned(),
479-
caption: c.caption().map(ToString::to_string),
480-
formatted_caption: c.formatted_caption().map(Into::into),
481-
source: Arc::new(c.source.try_into()?),
482-
info: c.info.as_deref().map(TryInto::try_into).transpose()?,
483-
},
484-
},
485-
RumaMessageType::File(c) => MessageType::File {
486-
content: FileMessageContent {
487-
filename: c.filename().to_owned(),
488-
caption: c.caption().map(ToString::to_string),
489-
formatted_caption: c.formatted_caption().map(Into::into),
490-
source: Arc::new(c.source.try_into()?),
491-
info: c.info.as_deref().map(TryInto::try_into).transpose()?,
492-
},
493-
},
424+
RumaMessageType::Image(c) => MessageType::Image { content: c.try_into()? },
425+
RumaMessageType::Audio(c) => MessageType::Audio { content: c.try_into()? },
426+
RumaMessageType::Video(c) => MessageType::Video { content: c.try_into()? },
427+
RumaMessageType::File(c) => MessageType::File { content: c.try_into()? },
428+
RumaMessageType::Gallery(c) => MessageType::Gallery { content: c.try_into()? },
494429
RumaMessageType::Notice(c) => MessageType::Notice {
495430
content: NoticeMessageContent {
496431
body: c.body.clone(),
@@ -568,6 +503,31 @@ pub struct ImageMessageContent {
568503
pub info: Option<ImageInfo>,
569504
}
570505

506+
impl From<ImageMessageContent> for RumaImageMessageEventContent {
507+
fn from(value: ImageMessageContent) -> Self {
508+
let (body, filename) = get_body_and_filename(value.filename, value.caption);
509+
let mut event_content = Self::new(body, (*value.source).clone().into())
510+
.info(value.info.map(Into::into).map(Box::new));
511+
event_content.formatted = value.formatted_caption.map(Into::into);
512+
event_content.filename = filename;
513+
event_content
514+
}
515+
}
516+
517+
impl TryFrom<RumaImageMessageEventContent> for ImageMessageContent {
518+
type Error = ClientError;
519+
520+
fn try_from(value: RumaImageMessageEventContent) -> Result<Self, Self::Error> {
521+
Ok(Self {
522+
filename: value.filename().to_owned(),
523+
caption: value.caption().map(ToString::to_string),
524+
formatted_caption: value.formatted_caption().map(Into::into),
525+
source: Arc::new(value.source.try_into()?),
526+
info: value.info.as_deref().map(TryInto::try_into).transpose()?,
527+
})
528+
}
529+
}
530+
571531
#[derive(Clone, uniffi::Record)]
572532
pub struct AudioMessageContent {
573533
/// The computed filename, for use in a client.
@@ -580,6 +540,35 @@ pub struct AudioMessageContent {
580540
pub voice: Option<UnstableVoiceContent>,
581541
}
582542

543+
impl From<AudioMessageContent> for RumaAudioMessageEventContent {
544+
fn from(value: AudioMessageContent) -> Self {
545+
let (body, filename) = get_body_and_filename(value.filename, value.caption);
546+
let mut event_content = Self::new(body, (*value.source).clone().into())
547+
.info(value.info.map(Into::into).map(Box::new));
548+
event_content.formatted = value.formatted_caption.map(Into::into);
549+
event_content.filename = filename;
550+
event_content.audio = value.audio.map(Into::into);
551+
event_content.voice = value.voice.map(Into::into);
552+
event_content
553+
}
554+
}
555+
556+
impl TryFrom<RumaAudioMessageEventContent> for AudioMessageContent {
557+
type Error = ClientError;
558+
559+
fn try_from(value: RumaAudioMessageEventContent) -> Result<Self, Self::Error> {
560+
Ok(Self {
561+
filename: value.filename().to_owned(),
562+
caption: value.caption().map(ToString::to_string),
563+
formatted_caption: value.formatted_caption().map(Into::into),
564+
source: Arc::new(value.source.try_into()?),
565+
info: value.info.as_deref().map(Into::into),
566+
audio: value.audio.map(Into::into),
567+
voice: value.voice.map(Into::into),
568+
})
569+
}
570+
}
571+
583572
#[derive(Clone, uniffi::Record)]
584573
pub struct VideoMessageContent {
585574
/// The computed filename, for use in a client.
@@ -590,6 +579,31 @@ pub struct VideoMessageContent {
590579
pub info: Option<VideoInfo>,
591580
}
592581

582+
impl From<VideoMessageContent> for RumaVideoMessageEventContent {
583+
fn from(value: VideoMessageContent) -> Self {
584+
let (body, filename) = get_body_and_filename(value.filename, value.caption);
585+
let mut event_content = Self::new(body, (*value.source).clone().into())
586+
.info(value.info.map(Into::into).map(Box::new));
587+
event_content.formatted = value.formatted_caption.map(Into::into);
588+
event_content.filename = filename;
589+
event_content
590+
}
591+
}
592+
593+
impl TryFrom<RumaVideoMessageEventContent> for VideoMessageContent {
594+
type Error = ClientError;
595+
596+
fn try_from(value: RumaVideoMessageEventContent) -> Result<Self, Self::Error> {
597+
Ok(Self {
598+
filename: value.filename().to_owned(),
599+
caption: value.caption().map(ToString::to_string),
600+
formatted_caption: value.formatted_caption().map(Into::into),
601+
source: Arc::new(value.source.try_into()?),
602+
info: value.info.as_deref().map(TryInto::try_into).transpose()?,
603+
})
604+
}
605+
}
606+
593607
#[derive(Clone, uniffi::Record)]
594608
pub struct FileMessageContent {
595609
/// The computed filename, for use in a client.
@@ -600,6 +614,66 @@ pub struct FileMessageContent {
600614
pub info: Option<FileInfo>,
601615
}
602616

617+
impl From<FileMessageContent> for RumaFileMessageEventContent {
618+
fn from(value: FileMessageContent) -> Self {
619+
let (body, filename) = get_body_and_filename(value.filename, value.caption);
620+
let mut event_content = Self::new(body, (*value.source).clone().into())
621+
.info(value.info.map(Into::into).map(Box::new));
622+
event_content.formatted = value.formatted_caption.map(Into::into);
623+
event_content.filename = filename;
624+
event_content
625+
}
626+
}
627+
628+
impl TryFrom<RumaFileMessageEventContent> for FileMessageContent {
629+
type Error = ClientError;
630+
631+
fn try_from(value: RumaFileMessageEventContent) -> Result<Self, Self::Error> {
632+
Ok(Self {
633+
filename: value.filename().to_owned(),
634+
caption: value.caption().map(ToString::to_string),
635+
formatted_caption: value.formatted_caption().map(Into::into),
636+
source: Arc::new(value.source.try_into()?),
637+
info: value.info.as_deref().map(TryInto::try_into).transpose()?,
638+
})
639+
}
640+
}
641+
642+
#[derive(Clone, uniffi::Record)]
643+
pub struct GalleryMessageContent {
644+
pub body: String,
645+
pub formatted: Option<FormattedBody>,
646+
pub itemtypes: Vec<GalleryItemType>,
647+
}
648+
649+
impl TryFrom<GalleryMessageContent> for RumaGalleryMessageEventContent {
650+
type Error = ClientError;
651+
652+
fn try_from(value: GalleryMessageContent) -> Result<Self, Self::Error> {
653+
Ok(Self::new(
654+
value.body,
655+
value.formatted.map(Into::into),
656+
value.itemtypes.into_iter().map(TryInto::try_into).collect::<Result<_, _>>()?,
657+
))
658+
}
659+
}
660+
661+
impl TryFrom<RumaGalleryMessageEventContent> for GalleryMessageContent {
662+
type Error = ClientError;
663+
664+
fn try_from(value: RumaGalleryMessageEventContent) -> Result<Self, Self::Error> {
665+
Ok(Self {
666+
body: value.body,
667+
formatted: value.formatted.as_ref().map(Into::into),
668+
itemtypes: value
669+
.itemtypes
670+
.into_iter()
671+
.map(TryInto::try_into)
672+
.collect::<Result<_, _>>()?,
673+
})
674+
}
675+
}
676+
603677
#[derive(Clone, uniffi::Record)]
604678
pub struct ImageInfo {
605679
pub height: Option<u64>,
@@ -820,6 +894,48 @@ impl From<ThumbnailInfo> for RumaThumbnailInfo {
820894
}
821895
}
822896

897+
#[derive(Clone, uniffi::Enum)]
898+
pub enum GalleryItemType {
899+
Image { content: ImageMessageContent },
900+
Audio { content: AudioMessageContent },
901+
Video { content: VideoMessageContent },
902+
File { content: FileMessageContent },
903+
Other { itemtype: String, body: String },
904+
}
905+
906+
impl TryFrom<GalleryItemType> for RumaGalleryItemType {
907+
type Error = ClientError;
908+
909+
fn try_from(value: GalleryItemType) -> Result<Self, Self::Error> {
910+
Ok(match value {
911+
GalleryItemType::Image { content } => Self::Image(content.into()),
912+
GalleryItemType::Audio { content } => Self::Audio(content.into()),
913+
GalleryItemType::Video { content } => Self::Video(content.into()),
914+
GalleryItemType::File { content } => Self::File(content.into()),
915+
GalleryItemType::Other { itemtype, body } => {
916+
Self::new(&itemtype, body, JsonObject::default())?
917+
}
918+
})
919+
}
920+
}
921+
922+
impl TryFrom<RumaGalleryItemType> for GalleryItemType {
923+
type Error = ClientError;
924+
925+
fn try_from(value: RumaGalleryItemType) -> Result<Self, Self::Error> {
926+
Ok(match value {
927+
RumaGalleryItemType::Image(c) => GalleryItemType::Image { content: c.try_into()? },
928+
RumaGalleryItemType::Audio(c) => GalleryItemType::Audio { content: c.try_into()? },
929+
RumaGalleryItemType::Video(c) => GalleryItemType::Video { content: c.try_into()? },
930+
RumaGalleryItemType::File(c) => GalleryItemType::File { content: c.try_into()? },
931+
_ => GalleryItemType::Other {
932+
itemtype: value.itemtype().to_owned(),
933+
body: value.body().to_owned(),
934+
},
935+
})
936+
}
937+
}
938+
823939
#[derive(Clone, uniffi::Record)]
824940
pub struct NoticeMessageContent {
825941
pub body: String,
@@ -886,6 +1002,11 @@ impl From<&RumaFormattedBody> for FormattedBody {
8861002
}
8871003
}
8881004

1005+
#[uniffi::export]
1006+
pub fn formatted_body_from_html(body: String) -> FormattedBody {
1007+
FormattedBody::from(&RumaFormattedBody::html(body))
1008+
}
1009+
8891010
#[derive(Clone, uniffi::Enum)]
8901011
pub enum MessageFormat {
8911012
Html,

0 commit comments

Comments
 (0)