atagen

matrix-rust-sdk

public
Star0
Watch0
ssh://brewery@pls.lobotomise.me:33/atagen/matrix-rust-sdk.git

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

7ff8adafe9e4atagen2026-10-22 12:30 UTC1
// Copyright 2023 The Matrix.org Foundation C.I.C.
7ff8adafe9e4atagen2026-10-22 12:30 UTC2
//
7ff8adafe9e4atagen2026-10-22 12:30 UTC3
// Licensed under the Apache License, Version 2.0 (the "License");
7ff8adafe9e4atagen2026-10-22 12:30 UTC4
// you may not use this file except in compliance with the License.
7ff8adafe9e4atagen2026-10-22 12:30 UTC5
// You may obtain a copy of the License at
7ff8adafe9e4atagen2026-10-22 12:30 UTC6
//
7ff8adafe9e4atagen2026-10-22 12:30 UTC7
//     http://www.apache.org/licenses/LICENSE-2.0
7ff8adafe9e4atagen2026-10-22 12:30 UTC8
//
7ff8adafe9e4atagen2026-10-22 12:30 UTC9
// Unless required by applicable law or agreed to in writing, software
7ff8adafe9e4atagen2026-10-22 12:30 UTC10
// distributed under the License is distributed on an "AS IS" BASIS,
7ff8adafe9e4atagen2026-10-22 12:30 UTC11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
7ff8adafe9e4atagen2026-10-22 12:30 UTC12
// See the License for the specific language governing permissions and
7ff8adafe9e4atagen2026-10-22 12:30 UTC13
// limitations under the License.
7ff8adafe9e4atagen2026-10-22 12:30 UTC14
7ff8adafe9e4atagen2026-10-22 12:30 UTC15
use std::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC16
    collections::{BTreeSet, HashMap},
7ff8adafe9e4atagen2026-10-22 12:30 UTC17
    sync::Arc,
7ff8adafe9e4atagen2026-10-22 12:30 UTC18
    time::Duration,
7ff8adafe9e4atagen2026-10-22 12:30 UTC19
};
7ff8adafe9e4atagen2026-10-22 12:30 UTC20
7ff8adafe9e4atagen2026-10-22 12:30 UTC21
use extension_trait::extension_trait;
7ff8adafe9e4atagen2026-10-22 12:30 UTC22
use matrix_sdk::attachment::{BaseAudioInfo, BaseFileInfo, BaseImageInfo, BaseVideoInfo};
7ff8adafe9e4atagen2026-10-22 12:30 UTC23
use ruma::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC24
    KeyDerivationAlgorithm as RumaKeyDerivationAlgorithm, MatrixToUri, MatrixUri as RumaMatrixUri,
7ff8adafe9e4atagen2026-10-22 12:30 UTC25
    OwnedRoomId, OwnedUserId, UInt, UserId, assign,
7ff8adafe9e4atagen2026-10-22 12:30 UTC26
    events::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC27
        GlobalAccountDataEvent as RumaGlobalAccountDataEvent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC28
        GlobalAccountDataEventType as RumaGlobalAccountDataEventType,
7ff8adafe9e4atagen2026-10-22 12:30 UTC29
        RoomAccountDataEvent as RumaRoomAccountDataEvent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC30
        RoomAccountDataEventType as RumaRoomAccountDataEventType,
7ff8adafe9e4atagen2026-10-22 12:30 UTC31
        direct::DirectEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC32
        fully_read::FullyReadEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC33
        identity_server::IdentityServerEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC34
        ignored_user_list::{IgnoredUser as RumaIgnoredUser, IgnoredUserListEventContent},
7ff8adafe9e4atagen2026-10-22 12:30 UTC35
        location::AssetType as RumaAssetType,
7ff8adafe9e4atagen2026-10-22 12:30 UTC36
        marked_unread::{MarkedUnreadEventContent, UnstableMarkedUnreadEventContent},
7ff8adafe9e4atagen2026-10-22 12:30 UTC37
        media_preview_config::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC38
            InviteAvatars as RumaInviteAvatars, MediaPreviewConfigEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC39
            MediaPreviews as RumaMediaPreviews,
7ff8adafe9e4atagen2026-10-22 12:30 UTC40
        },
7ff8adafe9e4atagen2026-10-22 12:30 UTC41
        poll::start::PollKind as RumaPollKind,
7ff8adafe9e4atagen2026-10-22 12:30 UTC42
        push_rules::PushRulesEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC43
        room::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC44
            ImageInfo as RumaImageInfo, MediaSource as RumaMediaSource,
7ff8adafe9e4atagen2026-10-22 12:30 UTC45
            ThumbnailInfo as RumaThumbnailInfo,
7ff8adafe9e4atagen2026-10-22 12:30 UTC46
            message::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC47
                AudioInfo as RumaAudioInfo,
7ff8adafe9e4atagen2026-10-22 12:30 UTC48
                AudioMessageEventContent as RumaAudioMessageEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC49
                EmoteMessageEventContent as RumaEmoteMessageEventContent, FileInfo as RumaFileInfo,
7ff8adafe9e4atagen2026-10-22 12:30 UTC50
                FileMessageEventContent as RumaFileMessageEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC51
                FormattedBody as RumaFormattedBody,
7ff8adafe9e4atagen2026-10-22 12:30 UTC52
                ImageMessageEventContent as RumaImageMessageEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC53
                LocationMessageEventContent as RumaLocationMessageEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC54
                MessageType as RumaMessageType,
7ff8adafe9e4atagen2026-10-22 12:30 UTC55
                NoticeMessageEventContent as RumaNoticeMessageEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC56
                RoomMessageEventContentWithoutRelation,
7ff8adafe9e4atagen2026-10-22 12:30 UTC57
                TextMessageEventContent as RumaTextMessageEventContent, UnstableAmplitude,
7ff8adafe9e4atagen2026-10-22 12:30 UTC58
                UnstableAudioDetailsContentBlock as RumaUnstableAudioDetailsContentBlock,
7ff8adafe9e4atagen2026-10-22 12:30 UTC59
                UnstableVoiceContentBlock as RumaUnstableVoiceContentBlock,
7ff8adafe9e4atagen2026-10-22 12:30 UTC60
                VideoInfo as RumaVideoInfo,
7ff8adafe9e4atagen2026-10-22 12:30 UTC61
                VideoMessageEventContent as RumaVideoMessageEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC62
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC63
        },
7ff8adafe9e4atagen2026-10-22 12:30 UTC64
        rtc::notification::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC65
            CallIntent as RumaCallIntent, NotificationType as RumaNotificationType,
7ff8adafe9e4atagen2026-10-22 12:30 UTC66
        },
7ff8adafe9e4atagen2026-10-22 12:30 UTC67
        secret_storage::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC68
            default_key::SecretStorageDefaultKeyEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC69
            key::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC70
                PassPhrase as RumaPassPhrase,
7ff8adafe9e4atagen2026-10-22 12:30 UTC71
                SecretStorageEncryptionAlgorithm as RumaSecretStorageEncryptionAlgorithm,
7ff8adafe9e4atagen2026-10-22 12:30 UTC72
                SecretStorageKeyEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC73
                SecretStorageV1AesHmacSha2Properties as RumaSecretStorageV1AesHmacSha2Properties,
7ff8adafe9e4atagen2026-10-22 12:30 UTC74
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC75
        },
7ff8adafe9e4atagen2026-10-22 12:30 UTC76
        tag::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC77
            TagEventContent, TagInfo as RumaTagInfo, TagName as RumaTagName,
7ff8adafe9e4atagen2026-10-22 12:30 UTC78
            UserTagName as RumaUserTagName,
7ff8adafe9e4atagen2026-10-22 12:30 UTC79
        },
7ff8adafe9e4atagen2026-10-22 12:30 UTC80
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC81
    matrix_uri::MatrixId as RumaMatrixId,
7ff8adafe9e4atagen2026-10-22 12:30 UTC82
    push::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC83
        ConditionalPushRule as RumaConditionalPushRule, PatternedPushRule as RumaPatternedPushRule,
7ff8adafe9e4atagen2026-10-22 12:30 UTC84
        Ruleset as RumaRuleset, SimplePushRule as RumaSimplePushRule,
7ff8adafe9e4atagen2026-10-22 12:30 UTC85
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC86
    serde::JsonObject,
7ff8adafe9e4atagen2026-10-22 12:30 UTC87
};
7ff8adafe9e4atagen2026-10-22 12:30 UTC88
use tracing::info;
7ff8adafe9e4atagen2026-10-22 12:30 UTC89
7ff8adafe9e4atagen2026-10-22 12:30 UTC90
use crate::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC91
    error::{ClientError, MediaInfoError},
7ff8adafe9e4atagen2026-10-22 12:30 UTC92
    helpers::unwrap_or_clone_arc,
7ff8adafe9e4atagen2026-10-22 12:30 UTC93
    notification_settings::{Action, PushCondition},
7ff8adafe9e4atagen2026-10-22 12:30 UTC94
    timeline::MessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC95
    utils::u64_to_uint,
7ff8adafe9e4atagen2026-10-22 12:30 UTC96
};
7ff8adafe9e4atagen2026-10-22 12:30 UTC97
7ff8adafe9e4atagen2026-10-22 12:30 UTC98
#[derive(uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC99
pub enum AuthData {
7ff8adafe9e4atagen2026-10-22 12:30 UTC100
    /// Password-based authentication (`m.login.password`).
7ff8adafe9e4atagen2026-10-22 12:30 UTC101
    Password { password_details: AuthDataPasswordDetails },
7ff8adafe9e4atagen2026-10-22 12:30 UTC102
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC103
7ff8adafe9e4atagen2026-10-22 12:30 UTC104
#[derive(uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC105
pub struct AuthDataPasswordDetails {
7ff8adafe9e4atagen2026-10-22 12:30 UTC106
    /// One of the user's identifiers.
7ff8adafe9e4atagen2026-10-22 12:30 UTC107
    identifier: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC108
7ff8adafe9e4atagen2026-10-22 12:30 UTC109
    /// The plaintext password.
7ff8adafe9e4atagen2026-10-22 12:30 UTC110
    password: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC111
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC112
7ff8adafe9e4atagen2026-10-22 12:30 UTC113
impl From<AuthData> for ruma::api::client::uiaa::AuthData {
7ff8adafe9e4atagen2026-10-22 12:30 UTC114
    fn from(value: AuthData) -> ruma::api::client::uiaa::AuthData {
7ff8adafe9e4atagen2026-10-22 12:30 UTC115
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC116
            AuthData::Password { password_details } => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC117
                let user_id = ruma::UserId::parse(password_details.identifier).unwrap();
7ff8adafe9e4atagen2026-10-22 12:30 UTC118
7ff8adafe9e4atagen2026-10-22 12:30 UTC119
                ruma::api::client::uiaa::AuthData::Password(ruma::api::client::uiaa::Password::new(
7ff8adafe9e4atagen2026-10-22 12:30 UTC120
                    user_id.into(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC121
                    password_details.password,
7ff8adafe9e4atagen2026-10-22 12:30 UTC122
                ))
7ff8adafe9e4atagen2026-10-22 12:30 UTC123
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC124
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC125
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC126
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC127
7ff8adafe9e4atagen2026-10-22 12:30 UTC128
/// Parse a matrix entity from a given URI, be it either
7ff8adafe9e4atagen2026-10-22 12:30 UTC129
/// a `matrix.to` link or a `matrix:` URI
7ff8adafe9e4atagen2026-10-22 12:30 UTC130
#[matrix_sdk_ffi_macros::export]
7ff8adafe9e4atagen2026-10-22 12:30 UTC131
pub fn parse_matrix_entity_from(uri: String) -> Option<MatrixEntity> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC132
    if let Ok(matrix_uri) = RumaMatrixUri::parse(&uri) {
7ff8adafe9e4atagen2026-10-22 12:30 UTC133
        return Some(MatrixEntity {
7ff8adafe9e4atagen2026-10-22 12:30 UTC134
            id: matrix_uri.id().into(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC135
            via: matrix_uri.via().iter().map(|via| via.to_string()).collect(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC136
        });
7ff8adafe9e4atagen2026-10-22 12:30 UTC137
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC138
7ff8adafe9e4atagen2026-10-22 12:30 UTC139
    if let Ok(matrix_to_uri) = MatrixToUri::parse(&uri) {
7ff8adafe9e4atagen2026-10-22 12:30 UTC140
        return Some(MatrixEntity {
7ff8adafe9e4atagen2026-10-22 12:30 UTC141
            id: matrix_to_uri.id().into(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC142
            via: matrix_to_uri.via().iter().map(|via| via.to_string()).collect(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC143
        });
7ff8adafe9e4atagen2026-10-22 12:30 UTC144
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC145
7ff8adafe9e4atagen2026-10-22 12:30 UTC146
    None
7ff8adafe9e4atagen2026-10-22 12:30 UTC147
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC148
7ff8adafe9e4atagen2026-10-22 12:30 UTC149
/// A Matrix entity that can be a room, room alias, user, or event, and a list
7ff8adafe9e4atagen2026-10-22 12:30 UTC150
/// of via servers.
7ff8adafe9e4atagen2026-10-22 12:30 UTC151
#[derive(uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC152
pub struct MatrixEntity {
7ff8adafe9e4atagen2026-10-22 12:30 UTC153
    id: MatrixId,
7ff8adafe9e4atagen2026-10-22 12:30 UTC154
    via: Vec<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC155
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC156
7ff8adafe9e4atagen2026-10-22 12:30 UTC157
/// A Matrix ID that can be a room, room alias, user, or event.
7ff8adafe9e4atagen2026-10-22 12:30 UTC158
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC159
pub enum MatrixId {
7ff8adafe9e4atagen2026-10-22 12:30 UTC160
    Room { id: String },
7ff8adafe9e4atagen2026-10-22 12:30 UTC161
    RoomAlias { alias: String },
7ff8adafe9e4atagen2026-10-22 12:30 UTC162
    User { id: String },
7ff8adafe9e4atagen2026-10-22 12:30 UTC163
    EventOnRoomId { room_id: String, event_id: String },
7ff8adafe9e4atagen2026-10-22 12:30 UTC164
    EventOnRoomAlias { alias: String, event_id: String },
7ff8adafe9e4atagen2026-10-22 12:30 UTC165
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC166
7ff8adafe9e4atagen2026-10-22 12:30 UTC167
impl From<&RumaMatrixId> for MatrixId {
7ff8adafe9e4atagen2026-10-22 12:30 UTC168
    fn from(value: &RumaMatrixId) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC169
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC170
            RumaMatrixId::User(id) => MatrixId::User { id: id.to_string() },
7ff8adafe9e4atagen2026-10-22 12:30 UTC171
            RumaMatrixId::Room(id) => MatrixId::Room { id: id.to_string() },
7ff8adafe9e4atagen2026-10-22 12:30 UTC172
            RumaMatrixId::RoomAlias(id) => MatrixId::RoomAlias { alias: id.to_string() },
7ff8adafe9e4atagen2026-10-22 12:30 UTC173
7ff8adafe9e4atagen2026-10-22 12:30 UTC174
            RumaMatrixId::Event(room_id_or_alias, event_id) => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC175
                if room_id_or_alias.is_room_id() {
7ff8adafe9e4atagen2026-10-22 12:30 UTC176
                    MatrixId::EventOnRoomId {
7ff8adafe9e4atagen2026-10-22 12:30 UTC177
                        room_id: room_id_or_alias.to_string(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC178
                        event_id: event_id.to_string(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC179
                    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC180
                } else if room_id_or_alias.is_room_alias_id() {
7ff8adafe9e4atagen2026-10-22 12:30 UTC181
                    MatrixId::EventOnRoomAlias {
7ff8adafe9e4atagen2026-10-22 12:30 UTC182
                        alias: room_id_or_alias.to_string(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC183
                        event_id: event_id.to_string(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC184
                    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC185
                } else {
7ff8adafe9e4atagen2026-10-22 12:30 UTC186
                    panic!("Unexpected MatrixId type: {room_id_or_alias:?}")
7ff8adafe9e4atagen2026-10-22 12:30 UTC187
                }
7ff8adafe9e4atagen2026-10-22 12:30 UTC188
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC189
            _ => panic!("Unexpected MatrixId type: {value:?}"),
7ff8adafe9e4atagen2026-10-22 12:30 UTC190
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC191
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC192
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC193
7ff8adafe9e4atagen2026-10-22 12:30 UTC194
#[matrix_sdk_ffi_macros::export]
7ff8adafe9e4atagen2026-10-22 12:30 UTC195
pub fn message_event_content_new(
7ff8adafe9e4atagen2026-10-22 12:30 UTC196
    msgtype: MessageType,
7ff8adafe9e4atagen2026-10-22 12:30 UTC197
) -> Result<Arc<RoomMessageEventContentWithoutRelation>, ClientError> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC198
    Ok(Arc::new(RoomMessageEventContentWithoutRelation::new(msgtype.try_into()?)))
7ff8adafe9e4atagen2026-10-22 12:30 UTC199
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC200
7ff8adafe9e4atagen2026-10-22 12:30 UTC201
#[matrix_sdk_ffi_macros::export]
7ff8adafe9e4atagen2026-10-22 12:30 UTC202
pub fn message_event_content_from_markdown(
7ff8adafe9e4atagen2026-10-22 12:30 UTC203
    md: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC204
) -> Arc<RoomMessageEventContentWithoutRelation> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC205
    Arc::new(RoomMessageEventContentWithoutRelation::new(RumaMessageType::text_markdown(md)))
7ff8adafe9e4atagen2026-10-22 12:30 UTC206
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC207
7ff8adafe9e4atagen2026-10-22 12:30 UTC208
#[matrix_sdk_ffi_macros::export]
7ff8adafe9e4atagen2026-10-22 12:30 UTC209
pub fn message_event_content_from_markdown_as_emote(
7ff8adafe9e4atagen2026-10-22 12:30 UTC210
    md: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC211
) -> Arc<RoomMessageEventContentWithoutRelation> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC212
    Arc::new(RoomMessageEventContentWithoutRelation::new(RumaMessageType::emote_markdown(md)))
7ff8adafe9e4atagen2026-10-22 12:30 UTC213
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC214
7ff8adafe9e4atagen2026-10-22 12:30 UTC215
#[matrix_sdk_ffi_macros::export]
7ff8adafe9e4atagen2026-10-22 12:30 UTC216
pub fn message_event_content_from_html(
7ff8adafe9e4atagen2026-10-22 12:30 UTC217
    body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC218
    html_body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC219
) -> Arc<RoomMessageEventContentWithoutRelation> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC220
    Arc::new(RoomMessageEventContentWithoutRelation::new(RumaMessageType::text_html(
7ff8adafe9e4atagen2026-10-22 12:30 UTC221
        body, html_body,
7ff8adafe9e4atagen2026-10-22 12:30 UTC222
    )))
7ff8adafe9e4atagen2026-10-22 12:30 UTC223
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC224
7ff8adafe9e4atagen2026-10-22 12:30 UTC225
#[matrix_sdk_ffi_macros::export]
7ff8adafe9e4atagen2026-10-22 12:30 UTC226
pub fn message_event_content_from_html_as_emote(
7ff8adafe9e4atagen2026-10-22 12:30 UTC227
    body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC228
    html_body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC229
) -> Arc<RoomMessageEventContentWithoutRelation> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC230
    Arc::new(RoomMessageEventContentWithoutRelation::new(RumaMessageType::emote_html(
7ff8adafe9e4atagen2026-10-22 12:30 UTC231
        body, html_body,
7ff8adafe9e4atagen2026-10-22 12:30 UTC232
    )))
7ff8adafe9e4atagen2026-10-22 12:30 UTC233
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC234
7ff8adafe9e4atagen2026-10-22 12:30 UTC235
#[derive(Clone, uniffi::Object)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC236
pub struct MediaSource {
7ff8adafe9e4atagen2026-10-22 12:30 UTC237
    pub(crate) media_source: RumaMediaSource,
7ff8adafe9e4atagen2026-10-22 12:30 UTC238
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC239
7ff8adafe9e4atagen2026-10-22 12:30 UTC240
#[matrix_sdk_ffi_macros::export]
7ff8adafe9e4atagen2026-10-22 12:30 UTC241
impl MediaSource {
7ff8adafe9e4atagen2026-10-22 12:30 UTC242
    #[uniffi::constructor]
7ff8adafe9e4atagen2026-10-22 12:30 UTC243
    pub fn from_url(url: String) -> Result<Arc<MediaSource>, ClientError> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC244
        let media_source = RumaMediaSource::Plain(url.into());
7ff8adafe9e4atagen2026-10-22 12:30 UTC245
        media_source.verify()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC246
7ff8adafe9e4atagen2026-10-22 12:30 UTC247
        Ok(Arc::new(MediaSource { media_source }))
7ff8adafe9e4atagen2026-10-22 12:30 UTC248
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC249
7ff8adafe9e4atagen2026-10-22 12:30 UTC250
    pub fn url(&self) -> String {
7ff8adafe9e4atagen2026-10-22 12:30 UTC251
        self.media_source.url()
7ff8adafe9e4atagen2026-10-22 12:30 UTC252
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC253
7ff8adafe9e4atagen2026-10-22 12:30 UTC254
    // Used on Element X Android
7ff8adafe9e4atagen2026-10-22 12:30 UTC255
    #[uniffi::constructor]
7ff8adafe9e4atagen2026-10-22 12:30 UTC256
    pub fn from_json(json: String) -> Result<Arc<Self>, ClientError> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC257
        let media_source: RumaMediaSource = serde_json::from_str(&json)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC258
        media_source.verify()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC259
7ff8adafe9e4atagen2026-10-22 12:30 UTC260
        Ok(Arc::new(MediaSource { media_source }))
7ff8adafe9e4atagen2026-10-22 12:30 UTC261
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC262
7ff8adafe9e4atagen2026-10-22 12:30 UTC263
    // Used on Element X Android
7ff8adafe9e4atagen2026-10-22 12:30 UTC264
    pub fn to_json(&self) -> String {
7ff8adafe9e4atagen2026-10-22 12:30 UTC265
        serde_json::to_string(&self.media_source)
7ff8adafe9e4atagen2026-10-22 12:30 UTC266
            .expect("Media source should always be serializable ")
7ff8adafe9e4atagen2026-10-22 12:30 UTC267
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC268
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC269
7ff8adafe9e4atagen2026-10-22 12:30 UTC270
impl TryFrom<RumaMediaSource> for MediaSource {
7ff8adafe9e4atagen2026-10-22 12:30 UTC271
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC272
7ff8adafe9e4atagen2026-10-22 12:30 UTC273
    fn try_from(value: RumaMediaSource) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC274
        value.verify()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC275
        Ok(Self { media_source: value })
7ff8adafe9e4atagen2026-10-22 12:30 UTC276
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC277
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC278
7ff8adafe9e4atagen2026-10-22 12:30 UTC279
impl TryFrom<&RumaMediaSource> for MediaSource {
7ff8adafe9e4atagen2026-10-22 12:30 UTC280
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC281
7ff8adafe9e4atagen2026-10-22 12:30 UTC282
    fn try_from(value: &RumaMediaSource) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC283
        value.verify()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC284
        Ok(Self { media_source: value.clone() })
7ff8adafe9e4atagen2026-10-22 12:30 UTC285
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC286
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC287
7ff8adafe9e4atagen2026-10-22 12:30 UTC288
impl From<MediaSource> for RumaMediaSource {
7ff8adafe9e4atagen2026-10-22 12:30 UTC289
    fn from(value: MediaSource) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC290
        value.media_source
7ff8adafe9e4atagen2026-10-22 12:30 UTC291
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC292
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC293
7ff8adafe9e4atagen2026-10-22 12:30 UTC294
#[extension_trait]
7ff8adafe9e4atagen2026-10-22 12:30 UTC295
pub(crate) impl MediaSourceExt for RumaMediaSource {
7ff8adafe9e4atagen2026-10-22 12:30 UTC296
    fn verify(&self) -> Result<(), ClientError> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC297
        match self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC298
            RumaMediaSource::Plain(url) => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC299
                url.validate().map_err(ClientError::from_err)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC300
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC301
            RumaMediaSource::Encrypted(file) => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC302
                file.url.validate().map_err(ClientError::from_err)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC303
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC304
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC305
7ff8adafe9e4atagen2026-10-22 12:30 UTC306
        Ok(())
7ff8adafe9e4atagen2026-10-22 12:30 UTC307
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC308
7ff8adafe9e4atagen2026-10-22 12:30 UTC309
    fn url(&self) -> String {
7ff8adafe9e4atagen2026-10-22 12:30 UTC310
        match self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC311
            RumaMediaSource::Plain(url) => url.to_string(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC312
            RumaMediaSource::Encrypted(file) => file.url.to_string(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC313
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC314
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC315
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC316
7ff8adafe9e4atagen2026-10-22 12:30 UTC317
#[extension_trait]
7ff8adafe9e4atagen2026-10-22 12:30 UTC318
pub impl RoomMessageEventContentWithoutRelationExt for RoomMessageEventContentWithoutRelation {
7ff8adafe9e4atagen2026-10-22 12:30 UTC319
    fn with_mentions(self: Arc<Self>, mentions: Mentions) -> Arc<Self> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC320
        let mut content = unwrap_or_clone_arc(self);
7ff8adafe9e4atagen2026-10-22 12:30 UTC321
        content.mentions = Some(mentions.into());
7ff8adafe9e4atagen2026-10-22 12:30 UTC322
        Arc::new(content)
7ff8adafe9e4atagen2026-10-22 12:30 UTC323
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC324
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC325
7ff8adafe9e4atagen2026-10-22 12:30 UTC326
#[derive(Clone)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC327
pub struct Mentions {
7ff8adafe9e4atagen2026-10-22 12:30 UTC328
    pub user_ids: Vec<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC329
    pub room: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC330
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC331
7ff8adafe9e4atagen2026-10-22 12:30 UTC332
impl From<Mentions> for ruma::events::Mentions {
7ff8adafe9e4atagen2026-10-22 12:30 UTC333
    fn from(value: Mentions) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC334
        let mut user_ids = BTreeSet::<OwnedUserId>::new();
7ff8adafe9e4atagen2026-10-22 12:30 UTC335
        for user_id in value.user_ids {
7ff8adafe9e4atagen2026-10-22 12:30 UTC336
            if let Ok(user_id) = UserId::parse(user_id) {
7ff8adafe9e4atagen2026-10-22 12:30 UTC337
                user_ids.insert(user_id);
7ff8adafe9e4atagen2026-10-22 12:30 UTC338
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC339
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC340
        let mut result = Self::default();
7ff8adafe9e4atagen2026-10-22 12:30 UTC341
        result.user_ids = user_ids;
7ff8adafe9e4atagen2026-10-22 12:30 UTC342
        result.room = value.room;
7ff8adafe9e4atagen2026-10-22 12:30 UTC343
        result
7ff8adafe9e4atagen2026-10-22 12:30 UTC344
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC345
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC346
7ff8adafe9e4atagen2026-10-22 12:30 UTC347
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC348
pub enum MessageType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC349
    Emote {
7ff8adafe9e4atagen2026-10-22 12:30 UTC350
        content: EmoteMessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC351
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC352
    Image {
7ff8adafe9e4atagen2026-10-22 12:30 UTC353
        content: ImageMessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC354
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC355
    Audio {
7ff8adafe9e4atagen2026-10-22 12:30 UTC356
        content: AudioMessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC357
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC358
    Video {
7ff8adafe9e4atagen2026-10-22 12:30 UTC359
        content: VideoMessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC360
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC361
    File {
7ff8adafe9e4atagen2026-10-22 12:30 UTC362
        content: FileMessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC363
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC364
    #[cfg(feature = "unstable-msc4274")]
7ff8adafe9e4atagen2026-10-22 12:30 UTC365
    Gallery {
7ff8adafe9e4atagen2026-10-22 12:30 UTC366
        content: GalleryMessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC367
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC368
    Notice {
7ff8adafe9e4atagen2026-10-22 12:30 UTC369
        content: NoticeMessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC370
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC371
    Text {
7ff8adafe9e4atagen2026-10-22 12:30 UTC372
        content: TextMessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC373
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC374
    Location {
7ff8adafe9e4atagen2026-10-22 12:30 UTC375
        content: LocationContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC376
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC377
    Other {
7ff8adafe9e4atagen2026-10-22 12:30 UTC378
        msgtype: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC379
        body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC380
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC381
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC382
7ff8adafe9e4atagen2026-10-22 12:30 UTC383
/// From MSC2530: https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/2530-body-as-caption.md
7ff8adafe9e4atagen2026-10-22 12:30 UTC384
/// If the filename field is present in a media message, clients should treat
7ff8adafe9e4atagen2026-10-22 12:30 UTC385
/// body as a caption instead of a file name. Otherwise, the body is the
7ff8adafe9e4atagen2026-10-22 12:30 UTC386
/// file name.
7ff8adafe9e4atagen2026-10-22 12:30 UTC387
///
7ff8adafe9e4atagen2026-10-22 12:30 UTC388
/// So:
7ff8adafe9e4atagen2026-10-22 12:30 UTC389
/// - if a media has a filename and a caption, the body is the caption, filename
7ff8adafe9e4atagen2026-10-22 12:30 UTC390
///   is its own field.
7ff8adafe9e4atagen2026-10-22 12:30 UTC391
/// - if a media only has a filename, then body is the filename.
7ff8adafe9e4atagen2026-10-22 12:30 UTC392
fn get_body_and_filename(filename: String, caption: Option<String>) -> (String, Option<String>) {
7ff8adafe9e4atagen2026-10-22 12:30 UTC393
    if let Some(caption) = caption { (caption, Some(filename)) } else { (filename, None) }
7ff8adafe9e4atagen2026-10-22 12:30 UTC394
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC395
7ff8adafe9e4atagen2026-10-22 12:30 UTC396
impl TryFrom<MessageType> for RumaMessageType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC397
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC398
7ff8adafe9e4atagen2026-10-22 12:30 UTC399
    fn try_from(value: MessageType) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC400
        Ok(match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC401
            MessageType::Emote { content } => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC402
                Self::Emote(assign!(RumaEmoteMessageEventContent::plain(content.body), {
7ff8adafe9e4atagen2026-10-22 12:30 UTC403
                    formatted: content.formatted.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC404
                }))
7ff8adafe9e4atagen2026-10-22 12:30 UTC405
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC406
            MessageType::Image { content } => Self::Image(content.into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC407
            MessageType::Audio { content } => Self::Audio(content.into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC408
            MessageType::Video { content } => Self::Video(content.into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC409
            MessageType::File { content } => Self::File(content.into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC410
            #[cfg(feature = "unstable-msc4274")]
7ff8adafe9e4atagen2026-10-22 12:30 UTC411
            MessageType::Gallery { content } => Self::Gallery(content.try_into()?),
7ff8adafe9e4atagen2026-10-22 12:30 UTC412
            MessageType::Notice { content } => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC413
                Self::Notice(assign!(RumaNoticeMessageEventContent::plain(content.body), {
7ff8adafe9e4atagen2026-10-22 12:30 UTC414
                    formatted: content.formatted.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC415
                }))
7ff8adafe9e4atagen2026-10-22 12:30 UTC416
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC417
            MessageType::Text { content } => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC418
                Self::Text(assign!(RumaTextMessageEventContent::plain(content.body), {
7ff8adafe9e4atagen2026-10-22 12:30 UTC419
                    formatted: content.formatted.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC420
                }))
7ff8adafe9e4atagen2026-10-22 12:30 UTC421
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC422
            MessageType::Location { content } => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC423
                Self::Location(RumaLocationMessageEventContent::new(content.body, content.geo_uri))
7ff8adafe9e4atagen2026-10-22 12:30 UTC424
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC425
            MessageType::Other { msgtype, body } => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC426
                Self::new(&msgtype, body, JsonObject::default())?
7ff8adafe9e4atagen2026-10-22 12:30 UTC427
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC428
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC429
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC430
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC431
7ff8adafe9e4atagen2026-10-22 12:30 UTC432
impl TryFrom<RumaMessageType> for MessageType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC433
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC434
7ff8adafe9e4atagen2026-10-22 12:30 UTC435
    fn try_from(value: RumaMessageType) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC436
        Ok(match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC437
            RumaMessageType::Emote(c) => MessageType::Emote {
7ff8adafe9e4atagen2026-10-22 12:30 UTC438
                content: EmoteMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC439
                    body: c.body.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC440
                    formatted: c.formatted.as_ref().map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC441
                },
7ff8adafe9e4atagen2026-10-22 12:30 UTC442
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC443
            RumaMessageType::Image(c) => MessageType::Image { content: c.try_into()? },
7ff8adafe9e4atagen2026-10-22 12:30 UTC444
            RumaMessageType::Audio(c) => MessageType::Audio { content: c.try_into()? },
7ff8adafe9e4atagen2026-10-22 12:30 UTC445
            RumaMessageType::Video(c) => MessageType::Video { content: c.try_into()? },
7ff8adafe9e4atagen2026-10-22 12:30 UTC446
            RumaMessageType::File(c) => MessageType::File { content: c.try_into()? },
7ff8adafe9e4atagen2026-10-22 12:30 UTC447
            #[cfg(feature = "unstable-msc4274")]
7ff8adafe9e4atagen2026-10-22 12:30 UTC448
            RumaMessageType::Gallery(c) => MessageType::Gallery { content: c.try_into()? },
7ff8adafe9e4atagen2026-10-22 12:30 UTC449
            RumaMessageType::Notice(c) => MessageType::Notice {
7ff8adafe9e4atagen2026-10-22 12:30 UTC450
                content: NoticeMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC451
                    body: c.body.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC452
                    formatted: c.formatted.as_ref().map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC453
                },
7ff8adafe9e4atagen2026-10-22 12:30 UTC454
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC455
            RumaMessageType::Text(c) => MessageType::Text {
7ff8adafe9e4atagen2026-10-22 12:30 UTC456
                content: TextMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC457
                    body: c.body.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC458
                    formatted: c.formatted.as_ref().map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC459
                },
7ff8adafe9e4atagen2026-10-22 12:30 UTC460
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC461
            RumaMessageType::Location(c) => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC462
                let (description, zoom_level) =
7ff8adafe9e4atagen2026-10-22 12:30 UTC463
                    c.location.map(|loc| (loc.description, loc.zoom_level)).unwrap_or((None, None));
7ff8adafe9e4atagen2026-10-22 12:30 UTC464
                MessageType::Location {
7ff8adafe9e4atagen2026-10-22 12:30 UTC465
                    content: LocationContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC466
                        body: c.body,
7ff8adafe9e4atagen2026-10-22 12:30 UTC467
                        geo_uri: c.geo_uri,
7ff8adafe9e4atagen2026-10-22 12:30 UTC468
                        description,
7ff8adafe9e4atagen2026-10-22 12:30 UTC469
                        zoom_level: zoom_level.and_then(|z| z.get().try_into().ok()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC470
                        asset: c.asset.map(|a| a.type_).into(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC471
                    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC472
                }
7ff8adafe9e4atagen2026-10-22 12:30 UTC473
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC474
            _ => MessageType::Other {
7ff8adafe9e4atagen2026-10-22 12:30 UTC475
                msgtype: value.msgtype().to_owned(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC476
                body: value.body().to_owned(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC477
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC478
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC479
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC480
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC481
7ff8adafe9e4atagen2026-10-22 12:30 UTC482
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC483
pub enum RtcNotificationType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC484
    Ring,
7ff8adafe9e4atagen2026-10-22 12:30 UTC485
    Notification,
7ff8adafe9e4atagen2026-10-22 12:30 UTC486
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC487
7ff8adafe9e4atagen2026-10-22 12:30 UTC488
impl From<RumaNotificationType> for RtcNotificationType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC489
    fn from(val: RumaNotificationType) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC490
        match val {
7ff8adafe9e4atagen2026-10-22 12:30 UTC491
            RumaNotificationType::Ring => Self::Ring,
7ff8adafe9e4atagen2026-10-22 12:30 UTC492
            _ => Self::Notification,
7ff8adafe9e4atagen2026-10-22 12:30 UTC493
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC494
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC495
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC496
7ff8adafe9e4atagen2026-10-22 12:30 UTC497
impl From<RtcNotificationType> for RumaNotificationType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC498
    fn from(value: RtcNotificationType) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC499
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC500
            RtcNotificationType::Ring => RumaNotificationType::Ring,
7ff8adafe9e4atagen2026-10-22 12:30 UTC501
            RtcNotificationType::Notification => RumaNotificationType::Notification,
7ff8adafe9e4atagen2026-10-22 12:30 UTC502
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC503
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC504
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC505
7ff8adafe9e4atagen2026-10-22 12:30 UTC506
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC507
pub enum RtcCallIntent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC508
    Video,
7ff8adafe9e4atagen2026-10-22 12:30 UTC509
    Audio,
7ff8adafe9e4atagen2026-10-22 12:30 UTC510
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC511
7ff8adafe9e4atagen2026-10-22 12:30 UTC512
impl From<RumaCallIntent> for RtcCallIntent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC513
    fn from(val: RumaCallIntent) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC514
        match val {
7ff8adafe9e4atagen2026-10-22 12:30 UTC515
            RumaCallIntent::Audio => Self::Audio,
7ff8adafe9e4atagen2026-10-22 12:30 UTC516
            // No support for custom intents, so we can just use video as default
7ff8adafe9e4atagen2026-10-22 12:30 UTC517
            _ => Self::Video,
7ff8adafe9e4atagen2026-10-22 12:30 UTC518
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC519
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC520
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC521
7ff8adafe9e4atagen2026-10-22 12:30 UTC522
impl From<RtcCallIntent> for RumaCallIntent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC523
    fn from(value: RtcCallIntent) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC524
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC525
            RtcCallIntent::Video => RumaCallIntent::Video,
7ff8adafe9e4atagen2026-10-22 12:30 UTC526
            RtcCallIntent::Audio => RumaCallIntent::Audio,
7ff8adafe9e4atagen2026-10-22 12:30 UTC527
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC528
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC529
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC530
7ff8adafe9e4atagen2026-10-22 12:30 UTC531
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC532
pub struct EmoteMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC533
    pub body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC534
    pub formatted: Option<FormattedBody>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC535
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC536
7ff8adafe9e4atagen2026-10-22 12:30 UTC537
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC538
pub struct ImageMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC539
    /// The computed filename, for use in a client.
7ff8adafe9e4atagen2026-10-22 12:30 UTC540
    pub filename: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC541
    pub caption: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC542
    pub formatted_caption: Option<FormattedBody>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC543
    pub source: Arc<MediaSource>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC544
    pub info: Option<ImageInfo>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC545
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC546
7ff8adafe9e4atagen2026-10-22 12:30 UTC547
impl From<ImageMessageContent> for RumaImageMessageEventContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC548
    fn from(value: ImageMessageContent) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC549
        let (body, filename) = get_body_and_filename(value.filename, value.caption);
7ff8adafe9e4atagen2026-10-22 12:30 UTC550
        let mut event_content = Self::new(body, (*value.source).clone().into())
7ff8adafe9e4atagen2026-10-22 12:30 UTC551
            .info(value.info.map(Into::into).map(Box::new));
7ff8adafe9e4atagen2026-10-22 12:30 UTC552
        event_content.formatted = value.formatted_caption.map(Into::into);
7ff8adafe9e4atagen2026-10-22 12:30 UTC553
        event_content.filename = filename;
7ff8adafe9e4atagen2026-10-22 12:30 UTC554
        event_content
7ff8adafe9e4atagen2026-10-22 12:30 UTC555
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC556
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC557
7ff8adafe9e4atagen2026-10-22 12:30 UTC558
impl TryFrom<RumaImageMessageEventContent> for ImageMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC559
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC560
7ff8adafe9e4atagen2026-10-22 12:30 UTC561
    fn try_from(value: RumaImageMessageEventContent) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC562
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC563
            filename: value.filename().to_owned(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC564
            caption: value.caption().map(str::to_owned),
7ff8adafe9e4atagen2026-10-22 12:30 UTC565
            formatted_caption: value.formatted_caption().map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC566
            source: Arc::new(value.source.try_into()?),
7ff8adafe9e4atagen2026-10-22 12:30 UTC567
            info: value.info.as_deref().map(TryInto::try_into).transpose()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC568
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC569
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC570
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC571
7ff8adafe9e4atagen2026-10-22 12:30 UTC572
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC573
pub struct AudioMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC574
    /// The computed filename, for use in a client.
7ff8adafe9e4atagen2026-10-22 12:30 UTC575
    pub filename: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC576
    pub caption: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC577
    pub formatted_caption: Option<FormattedBody>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC578
    pub source: Arc<MediaSource>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC579
    pub info: Option<AudioInfo>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC580
    pub audio: Option<UnstableAudioDetailsContent>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC581
    pub voice: Option<UnstableVoiceContent>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC582
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC583
7ff8adafe9e4atagen2026-10-22 12:30 UTC584
impl From<AudioMessageContent> for RumaAudioMessageEventContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC585
    fn from(value: AudioMessageContent) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC586
        let (body, filename) = get_body_and_filename(value.filename, value.caption);
7ff8adafe9e4atagen2026-10-22 12:30 UTC587
        let mut event_content = Self::new(body, (*value.source).clone().into())
7ff8adafe9e4atagen2026-10-22 12:30 UTC588
            .info(value.info.map(Into::into).map(Box::new));
7ff8adafe9e4atagen2026-10-22 12:30 UTC589
        event_content.formatted = value.formatted_caption.map(Into::into);
7ff8adafe9e4atagen2026-10-22 12:30 UTC590
        event_content.filename = filename;
7ff8adafe9e4atagen2026-10-22 12:30 UTC591
        event_content.audio = value.audio.map(Into::into);
7ff8adafe9e4atagen2026-10-22 12:30 UTC592
        event_content.voice = value.voice.map(Into::into);
7ff8adafe9e4atagen2026-10-22 12:30 UTC593
        event_content
7ff8adafe9e4atagen2026-10-22 12:30 UTC594
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC595
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC596
7ff8adafe9e4atagen2026-10-22 12:30 UTC597
impl TryFrom<RumaAudioMessageEventContent> for AudioMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC598
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC599
7ff8adafe9e4atagen2026-10-22 12:30 UTC600
    fn try_from(value: RumaAudioMessageEventContent) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC601
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC602
            filename: value.filename().to_owned(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC603
            caption: value.caption().map(str::to_owned),
7ff8adafe9e4atagen2026-10-22 12:30 UTC604
            formatted_caption: value.formatted_caption().map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC605
            source: Arc::new(value.source.try_into()?),
7ff8adafe9e4atagen2026-10-22 12:30 UTC606
            info: value.info.as_deref().map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC607
            audio: value.audio.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC608
            voice: value.voice.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC609
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC610
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC611
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC612
7ff8adafe9e4atagen2026-10-22 12:30 UTC613
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC614
pub struct VideoMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC615
    /// The computed filename, for use in a client.
7ff8adafe9e4atagen2026-10-22 12:30 UTC616
    pub filename: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC617
    pub caption: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC618
    pub formatted_caption: Option<FormattedBody>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC619
    pub source: Arc<MediaSource>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC620
    pub info: Option<VideoInfo>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC621
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC622
7ff8adafe9e4atagen2026-10-22 12:30 UTC623
impl From<VideoMessageContent> for RumaVideoMessageEventContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC624
    fn from(value: VideoMessageContent) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC625
        let (body, filename) = get_body_and_filename(value.filename, value.caption);
7ff8adafe9e4atagen2026-10-22 12:30 UTC626
        let mut event_content = Self::new(body, (*value.source).clone().into())
7ff8adafe9e4atagen2026-10-22 12:30 UTC627
            .info(value.info.map(Into::into).map(Box::new));
7ff8adafe9e4atagen2026-10-22 12:30 UTC628
        event_content.formatted = value.formatted_caption.map(Into::into);
7ff8adafe9e4atagen2026-10-22 12:30 UTC629
        event_content.filename = filename;
7ff8adafe9e4atagen2026-10-22 12:30 UTC630
        event_content
7ff8adafe9e4atagen2026-10-22 12:30 UTC631
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC632
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC633
7ff8adafe9e4atagen2026-10-22 12:30 UTC634
impl TryFrom<RumaVideoMessageEventContent> for VideoMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC635
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC636
7ff8adafe9e4atagen2026-10-22 12:30 UTC637
    fn try_from(value: RumaVideoMessageEventContent) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC638
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC639
            filename: value.filename().to_owned(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC640
            caption: value.caption().map(str::to_owned),
7ff8adafe9e4atagen2026-10-22 12:30 UTC641
            formatted_caption: value.formatted_caption().map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC642
            source: Arc::new(value.source.try_into()?),
7ff8adafe9e4atagen2026-10-22 12:30 UTC643
            info: value.info.as_deref().map(TryInto::try_into).transpose()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC644
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC645
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC646
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC647
7ff8adafe9e4atagen2026-10-22 12:30 UTC648
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC649
pub struct FileMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC650
    /// The computed filename, for use in a client.
7ff8adafe9e4atagen2026-10-22 12:30 UTC651
    pub filename: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC652
    pub caption: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC653
    pub formatted_caption: Option<FormattedBody>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC654
    pub source: Arc<MediaSource>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC655
    pub info: Option<FileInfo>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC656
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC657
7ff8adafe9e4atagen2026-10-22 12:30 UTC658
impl From<FileMessageContent> for RumaFileMessageEventContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC659
    fn from(value: FileMessageContent) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC660
        let (body, filename) = get_body_and_filename(value.filename, value.caption);
7ff8adafe9e4atagen2026-10-22 12:30 UTC661
        let mut event_content = Self::new(body, (*value.source).clone().into())
7ff8adafe9e4atagen2026-10-22 12:30 UTC662
            .info(value.info.map(Into::into).map(Box::new));
7ff8adafe9e4atagen2026-10-22 12:30 UTC663
        event_content.formatted = value.formatted_caption.map(Into::into);
7ff8adafe9e4atagen2026-10-22 12:30 UTC664
        event_content.filename = filename;
7ff8adafe9e4atagen2026-10-22 12:30 UTC665
        event_content
7ff8adafe9e4atagen2026-10-22 12:30 UTC666
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC667
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC668
7ff8adafe9e4atagen2026-10-22 12:30 UTC669
impl TryFrom<RumaFileMessageEventContent> for FileMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC670
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC671
7ff8adafe9e4atagen2026-10-22 12:30 UTC672
    fn try_from(value: RumaFileMessageEventContent) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC673
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC674
            filename: value.filename().to_owned(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC675
            caption: value.caption().map(str::to_owned),
7ff8adafe9e4atagen2026-10-22 12:30 UTC676
            formatted_caption: value.formatted_caption().map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC677
            source: Arc::new(value.source.try_into()?),
7ff8adafe9e4atagen2026-10-22 12:30 UTC678
            info: value.info.as_deref().map(TryInto::try_into).transpose()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC679
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC680
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC681
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC682
7ff8adafe9e4atagen2026-10-22 12:30 UTC683
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC684
pub struct ImageInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC685
    pub height: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC686
    pub width: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC687
    pub mimetype: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC688
    pub size: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC689
    pub thumbnail_info: Option<ThumbnailInfo>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC690
    pub thumbnail_source: Option<Arc<MediaSource>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC691
    pub blurhash: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC692
    pub is_animated: Option<bool>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC693
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC694
7ff8adafe9e4atagen2026-10-22 12:30 UTC695
impl From<ImageInfo> for RumaImageInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC696
    fn from(value: ImageInfo) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC697
        assign!(RumaImageInfo::new(), {
7ff8adafe9e4atagen2026-10-22 12:30 UTC698
            height: value.height.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC699
            width: value.width.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC700
            mimetype: value.mimetype,
7ff8adafe9e4atagen2026-10-22 12:30 UTC701
            size: value.size.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC702
            thumbnail_info: value.thumbnail_info.map(Into::into).map(Box::new),
7ff8adafe9e4atagen2026-10-22 12:30 UTC703
            thumbnail_source: value.thumbnail_source.map(|source| (*source).clone().into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC704
            blurhash: value.blurhash,
7ff8adafe9e4atagen2026-10-22 12:30 UTC705
            is_animated: value.is_animated,
7ff8adafe9e4atagen2026-10-22 12:30 UTC706
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC707
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC708
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC709
7ff8adafe9e4atagen2026-10-22 12:30 UTC710
impl TryFrom<&ImageInfo> for BaseImageInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC711
    type Error = MediaInfoError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC712
7ff8adafe9e4atagen2026-10-22 12:30 UTC713
    fn try_from(value: &ImageInfo) -> Result<Self, MediaInfoError> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC714
        let height = UInt::try_from(value.height.ok_or(MediaInfoError::MissingField)?)
7ff8adafe9e4atagen2026-10-22 12:30 UTC715
            .map_err(|_| MediaInfoError::InvalidField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC716
        let width = UInt::try_from(value.width.ok_or(MediaInfoError::MissingField)?)
7ff8adafe9e4atagen2026-10-22 12:30 UTC717
            .map_err(|_| MediaInfoError::InvalidField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC718
        let size = UInt::try_from(value.size.ok_or(MediaInfoError::MissingField)?)
7ff8adafe9e4atagen2026-10-22 12:30 UTC719
            .map_err(|_| MediaInfoError::InvalidField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC720
        let blurhash = value.blurhash.clone().ok_or(MediaInfoError::MissingField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC721
7ff8adafe9e4atagen2026-10-22 12:30 UTC722
        Ok(BaseImageInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC723
            height: Some(height),
7ff8adafe9e4atagen2026-10-22 12:30 UTC724
            width: Some(width),
7ff8adafe9e4atagen2026-10-22 12:30 UTC725
            size: Some(size),
7ff8adafe9e4atagen2026-10-22 12:30 UTC726
            blurhash: Some(blurhash),
7ff8adafe9e4atagen2026-10-22 12:30 UTC727
            is_animated: value.is_animated,
7ff8adafe9e4atagen2026-10-22 12:30 UTC728
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC729
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC730
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC731
7ff8adafe9e4atagen2026-10-22 12:30 UTC732
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC733
pub struct AudioInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC734
    pub duration: Option<Duration>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC735
    pub size: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC736
    pub mimetype: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC737
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC738
7ff8adafe9e4atagen2026-10-22 12:30 UTC739
impl From<AudioInfo> for RumaAudioInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC740
    fn from(value: AudioInfo) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC741
        assign!(RumaAudioInfo::new(), {
7ff8adafe9e4atagen2026-10-22 12:30 UTC742
            duration: value.duration,
7ff8adafe9e4atagen2026-10-22 12:30 UTC743
            size: value.size.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC744
            mimetype: value.mimetype,
7ff8adafe9e4atagen2026-10-22 12:30 UTC745
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC746
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC747
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC748
7ff8adafe9e4atagen2026-10-22 12:30 UTC749
impl TryFrom<&AudioInfo> for BaseAudioInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC750
    type Error = MediaInfoError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC751
7ff8adafe9e4atagen2026-10-22 12:30 UTC752
    fn try_from(value: &AudioInfo) -> Result<Self, MediaInfoError> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC753
        let duration = value.duration.ok_or(MediaInfoError::MissingField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC754
        let size = UInt::try_from(value.size.ok_or(MediaInfoError::MissingField)?)
7ff8adafe9e4atagen2026-10-22 12:30 UTC755
            .map_err(|_| MediaInfoError::InvalidField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC756
7ff8adafe9e4atagen2026-10-22 12:30 UTC757
        Ok(BaseAudioInfo { duration: Some(duration), size: Some(size), waveform: None })
7ff8adafe9e4atagen2026-10-22 12:30 UTC758
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC759
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC760
7ff8adafe9e4atagen2026-10-22 12:30 UTC761
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC762
pub struct UnstableAudioDetailsContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC763
    pub duration: Duration,
7ff8adafe9e4atagen2026-10-22 12:30 UTC764
    pub waveform: Vec<u16>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC765
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC766
7ff8adafe9e4atagen2026-10-22 12:30 UTC767
impl From<RumaUnstableAudioDetailsContentBlock> for UnstableAudioDetailsContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC768
    fn from(details: RumaUnstableAudioDetailsContentBlock) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC769
        Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC770
            duration: details.duration,
7ff8adafe9e4atagen2026-10-22 12:30 UTC771
            waveform: details
7ff8adafe9e4atagen2026-10-22 12:30 UTC772
                .waveform
7ff8adafe9e4atagen2026-10-22 12:30 UTC773
                .iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC774
                .map(|x| u16::try_from(x.get()).unwrap_or(0))
7ff8adafe9e4atagen2026-10-22 12:30 UTC775
                .collect(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC776
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC777
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC778
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC779
7ff8adafe9e4atagen2026-10-22 12:30 UTC780
impl From<UnstableAudioDetailsContent> for RumaUnstableAudioDetailsContentBlock {
7ff8adafe9e4atagen2026-10-22 12:30 UTC781
    fn from(details: UnstableAudioDetailsContent) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC782
        Self::new(
7ff8adafe9e4atagen2026-10-22 12:30 UTC783
            details.duration,
7ff8adafe9e4atagen2026-10-22 12:30 UTC784
            details.waveform.iter().map(|x| UnstableAmplitude::new(x.to_owned())).collect(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC785
        )
7ff8adafe9e4atagen2026-10-22 12:30 UTC786
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC787
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC788
7ff8adafe9e4atagen2026-10-22 12:30 UTC789
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC790
pub struct UnstableVoiceContent {}
7ff8adafe9e4atagen2026-10-22 12:30 UTC791
7ff8adafe9e4atagen2026-10-22 12:30 UTC792
impl From<RumaUnstableVoiceContentBlock> for UnstableVoiceContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC793
    fn from(_details: RumaUnstableVoiceContentBlock) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC794
        Self {}
7ff8adafe9e4atagen2026-10-22 12:30 UTC795
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC796
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC797
7ff8adafe9e4atagen2026-10-22 12:30 UTC798
impl From<UnstableVoiceContent> for RumaUnstableVoiceContentBlock {
7ff8adafe9e4atagen2026-10-22 12:30 UTC799
    fn from(_details: UnstableVoiceContent) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC800
        Self::new()
7ff8adafe9e4atagen2026-10-22 12:30 UTC801
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC802
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC803
7ff8adafe9e4atagen2026-10-22 12:30 UTC804
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC805
pub struct VideoInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC806
    pub duration: Option<Duration>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC807
    pub height: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC808
    pub width: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC809
    pub mimetype: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC810
    pub size: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC811
    pub thumbnail_info: Option<ThumbnailInfo>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC812
    pub thumbnail_source: Option<Arc<MediaSource>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC813
    pub blurhash: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC814
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC815
7ff8adafe9e4atagen2026-10-22 12:30 UTC816
impl From<VideoInfo> for RumaVideoInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC817
    fn from(value: VideoInfo) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC818
        assign!(RumaVideoInfo::new(), {
7ff8adafe9e4atagen2026-10-22 12:30 UTC819
            duration: value.duration,
7ff8adafe9e4atagen2026-10-22 12:30 UTC820
            height: value.height.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC821
            width: value.width.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC822
            mimetype: value.mimetype,
7ff8adafe9e4atagen2026-10-22 12:30 UTC823
            size: value.size.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC824
            thumbnail_info: value.thumbnail_info.map(Into::into).map(Box::new),
7ff8adafe9e4atagen2026-10-22 12:30 UTC825
            thumbnail_source: value.thumbnail_source.map(|source| (*source).clone().into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC826
            blurhash: value.blurhash,
7ff8adafe9e4atagen2026-10-22 12:30 UTC827
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC828
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC829
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC830
7ff8adafe9e4atagen2026-10-22 12:30 UTC831
impl TryFrom<&VideoInfo> for BaseVideoInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC832
    type Error = MediaInfoError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC833
7ff8adafe9e4atagen2026-10-22 12:30 UTC834
    fn try_from(value: &VideoInfo) -> Result<Self, MediaInfoError> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC835
        let duration = value.duration.ok_or(MediaInfoError::MissingField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC836
        let height = UInt::try_from(value.height.ok_or(MediaInfoError::MissingField)?)
7ff8adafe9e4atagen2026-10-22 12:30 UTC837
            .map_err(|_| MediaInfoError::InvalidField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC838
        let width = UInt::try_from(value.width.ok_or(MediaInfoError::MissingField)?)
7ff8adafe9e4atagen2026-10-22 12:30 UTC839
            .map_err(|_| MediaInfoError::InvalidField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC840
        let size = UInt::try_from(value.size.ok_or(MediaInfoError::MissingField)?)
7ff8adafe9e4atagen2026-10-22 12:30 UTC841
            .map_err(|_| MediaInfoError::InvalidField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC842
        let blurhash = value.blurhash.clone().ok_or(MediaInfoError::MissingField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC843
7ff8adafe9e4atagen2026-10-22 12:30 UTC844
        Ok(BaseVideoInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC845
            duration: Some(duration),
7ff8adafe9e4atagen2026-10-22 12:30 UTC846
            height: Some(height),
7ff8adafe9e4atagen2026-10-22 12:30 UTC847
            width: Some(width),
7ff8adafe9e4atagen2026-10-22 12:30 UTC848
            size: Some(size),
7ff8adafe9e4atagen2026-10-22 12:30 UTC849
            blurhash: Some(blurhash),
7ff8adafe9e4atagen2026-10-22 12:30 UTC850
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC851
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC852
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC853
7ff8adafe9e4atagen2026-10-22 12:30 UTC854
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC855
pub struct FileInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC856
    pub mimetype: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC857
    pub size: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC858
    pub thumbnail_info: Option<ThumbnailInfo>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC859
    pub thumbnail_source: Option<Arc<MediaSource>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC860
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC861
7ff8adafe9e4atagen2026-10-22 12:30 UTC862
impl From<FileInfo> for RumaFileInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC863
    fn from(value: FileInfo) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC864
        assign!(RumaFileInfo::new(), {
7ff8adafe9e4atagen2026-10-22 12:30 UTC865
            mimetype: value.mimetype,
7ff8adafe9e4atagen2026-10-22 12:30 UTC866
            size: value.size.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC867
            thumbnail_info: value.thumbnail_info.map(Into::into).map(Box::new),
7ff8adafe9e4atagen2026-10-22 12:30 UTC868
            thumbnail_source: value.thumbnail_source.map(|source| (*source).clone().into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC869
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC870
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC871
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC872
7ff8adafe9e4atagen2026-10-22 12:30 UTC873
impl TryFrom<&FileInfo> for BaseFileInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC874
    type Error = MediaInfoError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC875
7ff8adafe9e4atagen2026-10-22 12:30 UTC876
    fn try_from(value: &FileInfo) -> Result<Self, MediaInfoError> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC877
        let size = UInt::try_from(value.size.ok_or(MediaInfoError::MissingField)?)
7ff8adafe9e4atagen2026-10-22 12:30 UTC878
            .map_err(|_| MediaInfoError::InvalidField)?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC879
7ff8adafe9e4atagen2026-10-22 12:30 UTC880
        Ok(BaseFileInfo { size: Some(size) })
7ff8adafe9e4atagen2026-10-22 12:30 UTC881
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC882
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC883
7ff8adafe9e4atagen2026-10-22 12:30 UTC884
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC885
pub struct ThumbnailInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC886
    pub height: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC887
    pub width: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC888
    pub mimetype: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC889
    pub size: Option<u64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC890
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC891
7ff8adafe9e4atagen2026-10-22 12:30 UTC892
impl From<ThumbnailInfo> for RumaThumbnailInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC893
    fn from(value: ThumbnailInfo) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC894
        assign!(RumaThumbnailInfo::new(), {
7ff8adafe9e4atagen2026-10-22 12:30 UTC895
            height: value.height.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC896
            width: value.width.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC897
            mimetype: value.mimetype,
7ff8adafe9e4atagen2026-10-22 12:30 UTC898
            size: value.size.map(u64_to_uint),
7ff8adafe9e4atagen2026-10-22 12:30 UTC899
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC900
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC901
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC902
7ff8adafe9e4atagen2026-10-22 12:30 UTC903
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC904
pub struct NoticeMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC905
    pub body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC906
    pub formatted: Option<FormattedBody>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC907
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC908
7ff8adafe9e4atagen2026-10-22 12:30 UTC909
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC910
pub struct TextMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC911
    pub body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC912
    pub formatted: Option<FormattedBody>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC913
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC914
7ff8adafe9e4atagen2026-10-22 12:30 UTC915
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC916
pub struct LocationContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC917
    pub body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC918
    pub geo_uri: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC919
    pub description: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC920
    pub zoom_level: Option<u8>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC921
    pub asset: AssetType,
7ff8adafe9e4atagen2026-10-22 12:30 UTC922
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC923
7ff8adafe9e4atagen2026-10-22 12:30 UTC924
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC925
pub enum AssetType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC926
    Sender,
7ff8adafe9e4atagen2026-10-22 12:30 UTC927
    Pin,
7ff8adafe9e4atagen2026-10-22 12:30 UTC928
    Unknown,
7ff8adafe9e4atagen2026-10-22 12:30 UTC929
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC930
7ff8adafe9e4atagen2026-10-22 12:30 UTC931
impl From<AssetType> for RumaAssetType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC932
    fn from(value: AssetType) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC933
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC934
            AssetType::Sender => Self::Self_,
7ff8adafe9e4atagen2026-10-22 12:30 UTC935
            AssetType::Pin => Self::Pin,
7ff8adafe9e4atagen2026-10-22 12:30 UTC936
            _ => panic!("Invalid asset type"),
7ff8adafe9e4atagen2026-10-22 12:30 UTC937
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC938
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC939
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC940
7ff8adafe9e4atagen2026-10-22 12:30 UTC941
impl From<RumaAssetType> for AssetType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC942
    fn from(value: RumaAssetType) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC943
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC944
            RumaAssetType::Self_ => Self::Sender,
7ff8adafe9e4atagen2026-10-22 12:30 UTC945
            RumaAssetType::Pin => Self::Pin,
7ff8adafe9e4atagen2026-10-22 12:30 UTC946
            _ => Self::Unknown,
7ff8adafe9e4atagen2026-10-22 12:30 UTC947
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC948
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC949
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC950
7ff8adafe9e4atagen2026-10-22 12:30 UTC951
impl From<Option<RumaAssetType>> for AssetType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC952
    fn from(value: Option<RumaAssetType>) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC953
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC954
            None => Self::Sender,
7ff8adafe9e4atagen2026-10-22 12:30 UTC955
            Some(asset_type) => asset_type.into(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC956
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC957
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC958
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC959
7ff8adafe9e4atagen2026-10-22 12:30 UTC960
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC961
pub struct FormattedBody {
7ff8adafe9e4atagen2026-10-22 12:30 UTC962
    pub format: MessageFormat,
7ff8adafe9e4atagen2026-10-22 12:30 UTC963
    pub body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC964
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC965
7ff8adafe9e4atagen2026-10-22 12:30 UTC966
impl From<FormattedBody> for RumaFormattedBody {
7ff8adafe9e4atagen2026-10-22 12:30 UTC967
    fn from(f: FormattedBody) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC968
        Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC969
            format: match f.format {
7ff8adafe9e4atagen2026-10-22 12:30 UTC970
                MessageFormat::Html => matrix_sdk::ruma::events::room::message::MessageFormat::Html,
7ff8adafe9e4atagen2026-10-22 12:30 UTC971
                MessageFormat::Unknown { format } => format.into(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC972
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC973
            body: f.body,
7ff8adafe9e4atagen2026-10-22 12:30 UTC974
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC975
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC976
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC977
7ff8adafe9e4atagen2026-10-22 12:30 UTC978
impl From<&RumaFormattedBody> for FormattedBody {
7ff8adafe9e4atagen2026-10-22 12:30 UTC979
    fn from(f: &RumaFormattedBody) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC980
        Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC981
            format: match &f.format {
7ff8adafe9e4atagen2026-10-22 12:30 UTC982
                matrix_sdk::ruma::events::room::message::MessageFormat::Html => MessageFormat::Html,
7ff8adafe9e4atagen2026-10-22 12:30 UTC983
                _ => MessageFormat::Unknown { format: f.format.to_string() },
7ff8adafe9e4atagen2026-10-22 12:30 UTC984
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC985
            body: f.body.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC986
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC987
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC988
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC989
7ff8adafe9e4atagen2026-10-22 12:30 UTC990
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC991
pub enum MessageFormat {
7ff8adafe9e4atagen2026-10-22 12:30 UTC992
    Html,
7ff8adafe9e4atagen2026-10-22 12:30 UTC993
    Unknown { format: String },
7ff8adafe9e4atagen2026-10-22 12:30 UTC994
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC995
7ff8adafe9e4atagen2026-10-22 12:30 UTC996
impl TryFrom<&matrix_sdk::ruma::events::room::ImageInfo> for ImageInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC997
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC998
7ff8adafe9e4atagen2026-10-22 12:30 UTC999
    fn try_from(info: &matrix_sdk::ruma::events::room::ImageInfo) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1000
        let thumbnail_info = info.thumbnail_info.as_ref().map(|info| ThumbnailInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1001
            height: info.height.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1002
            width: info.width.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1003
            mimetype: info.mimetype.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1004
            size: info.size.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1005
        });
7ff8adafe9e4atagen2026-10-22 12:30 UTC1006
7ff8adafe9e4atagen2026-10-22 12:30 UTC1007
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1008
            height: info.height.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1009
            width: info.width.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1010
            mimetype: info.mimetype.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1011
            size: info.size.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1012
            thumbnail_info,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1013
            thumbnail_source: info
7ff8adafe9e4atagen2026-10-22 12:30 UTC1014
                .thumbnail_source
7ff8adafe9e4atagen2026-10-22 12:30 UTC1015
                .as_ref()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1016
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1017
                .transpose()?
7ff8adafe9e4atagen2026-10-22 12:30 UTC1018
                .map(Arc::new),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1019
            blurhash: info.blurhash.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1020
            is_animated: info.is_animated,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1021
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1022
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1023
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1024
7ff8adafe9e4atagen2026-10-22 12:30 UTC1025
impl From<&RumaAudioInfo> for AudioInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1026
    fn from(info: &RumaAudioInfo) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1027
        Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1028
            duration: info.duration,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1029
            size: info.size.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1030
            mimetype: info.mimetype.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1031
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1032
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1033
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1034
7ff8adafe9e4atagen2026-10-22 12:30 UTC1035
impl TryFrom<&RumaVideoInfo> for VideoInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1036
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1037
7ff8adafe9e4atagen2026-10-22 12:30 UTC1038
    fn try_from(info: &RumaVideoInfo) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1039
        let thumbnail_info = info.thumbnail_info.as_ref().map(|info| ThumbnailInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1040
            height: info.height.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1041
            width: info.width.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1042
            mimetype: info.mimetype.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1043
            size: info.size.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1044
        });
7ff8adafe9e4atagen2026-10-22 12:30 UTC1045
7ff8adafe9e4atagen2026-10-22 12:30 UTC1046
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1047
            duration: info.duration,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1048
            height: info.height.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1049
            width: info.width.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1050
            mimetype: info.mimetype.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1051
            size: info.size.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1052
            thumbnail_info,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1053
            thumbnail_source: info
7ff8adafe9e4atagen2026-10-22 12:30 UTC1054
                .thumbnail_source
7ff8adafe9e4atagen2026-10-22 12:30 UTC1055
                .as_ref()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1056
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1057
                .transpose()?
7ff8adafe9e4atagen2026-10-22 12:30 UTC1058
                .map(Arc::new),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1059
            blurhash: info.blurhash.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1060
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1061
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1062
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1063
7ff8adafe9e4atagen2026-10-22 12:30 UTC1064
impl TryFrom<&RumaFileInfo> for FileInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1065
    type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1066
7ff8adafe9e4atagen2026-10-22 12:30 UTC1067
    fn try_from(info: &RumaFileInfo) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1068
        let thumbnail_info = info.thumbnail_info.as_ref().map(|info| ThumbnailInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1069
            height: info.height.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1070
            width: info.width.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1071
            mimetype: info.mimetype.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1072
            size: info.size.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1073
        });
7ff8adafe9e4atagen2026-10-22 12:30 UTC1074
7ff8adafe9e4atagen2026-10-22 12:30 UTC1075
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1076
            mimetype: info.mimetype.clone(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1077
            size: info.size.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1078
            thumbnail_info,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1079
            thumbnail_source: info
7ff8adafe9e4atagen2026-10-22 12:30 UTC1080
                .thumbnail_source
7ff8adafe9e4atagen2026-10-22 12:30 UTC1081
                .as_ref()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1082
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1083
                .transpose()?
7ff8adafe9e4atagen2026-10-22 12:30 UTC1084
                .map(Arc::new),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1085
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1086
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1087
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1088
7ff8adafe9e4atagen2026-10-22 12:30 UTC1089
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1090
pub enum PollKind {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1091
    Disclosed,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1092
    Undisclosed,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1093
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1094
7ff8adafe9e4atagen2026-10-22 12:30 UTC1095
impl From<PollKind> for RumaPollKind {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1096
    fn from(value: PollKind) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1097
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1098
            PollKind::Disclosed => Self::Disclosed,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1099
            PollKind::Undisclosed => Self::Undisclosed,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1100
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1101
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1102
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1103
7ff8adafe9e4atagen2026-10-22 12:30 UTC1104
impl From<RumaPollKind> for PollKind {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1105
    fn from(value: RumaPollKind) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1106
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1107
            RumaPollKind::Disclosed => Self::Disclosed,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1108
            RumaPollKind::Undisclosed => Self::Undisclosed,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1109
            _ => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1110
                info!("Unknown poll kind, defaulting to undisclosed");
7ff8adafe9e4atagen2026-10-22 12:30 UTC1111
                Self::Undisclosed
7ff8adafe9e4atagen2026-10-22 12:30 UTC1112
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1113
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1114
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1115
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1116
7ff8adafe9e4atagen2026-10-22 12:30 UTC1117
/// Creates a [`RoomMessageEventContentWithoutRelation`] given a
7ff8adafe9e4atagen2026-10-22 12:30 UTC1118
/// [`MessageContent`] value.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1119
#[matrix_sdk_ffi_macros::export]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1120
pub fn content_without_relation_from_message(
7ff8adafe9e4atagen2026-10-22 12:30 UTC1121
    message: MessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1122
) -> Result<Arc<RoomMessageEventContentWithoutRelation>, ClientError> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1123
    let msg_type = message.msg_type.try_into()?;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1124
    Ok(Arc::new(RoomMessageEventContentWithoutRelation::new(msg_type)))
7ff8adafe9e4atagen2026-10-22 12:30 UTC1125
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1126
7ff8adafe9e4atagen2026-10-22 12:30 UTC1127
/// Types of global account data events.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1128
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1129
pub enum AccountDataEventType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1130
    /// m.direct
7ff8adafe9e4atagen2026-10-22 12:30 UTC1131
    Direct,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1132
    /// m.identity_server
7ff8adafe9e4atagen2026-10-22 12:30 UTC1133
    IdentityServer,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1134
    /// m.ignored_user_list
7ff8adafe9e4atagen2026-10-22 12:30 UTC1135
    IgnoredUserList,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1136
    /// m.push_rules
7ff8adafe9e4atagen2026-10-22 12:30 UTC1137
    PushRules,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1138
    /// m.secret_storage.default_key
7ff8adafe9e4atagen2026-10-22 12:30 UTC1139
    SecretStorageDefaultKey,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1140
    /// m.secret_storage.key.*
7ff8adafe9e4atagen2026-10-22 12:30 UTC1141
    SecretStorageKey { key_id: String },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1142
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1143
7ff8adafe9e4atagen2026-10-22 12:30 UTC1144
impl TryFrom<RumaGlobalAccountDataEventType> for AccountDataEventType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1145
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1146
7ff8adafe9e4atagen2026-10-22 12:30 UTC1147
    fn try_from(value: RumaGlobalAccountDataEventType) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1148
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1149
            RumaGlobalAccountDataEventType::Direct => Ok(Self::Direct),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1150
            RumaGlobalAccountDataEventType::IdentityServer => Ok(Self::IdentityServer),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1151
            RumaGlobalAccountDataEventType::IgnoredUserList => Ok(Self::IgnoredUserList),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1152
            RumaGlobalAccountDataEventType::PushRules => Ok(Self::PushRules),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1153
            RumaGlobalAccountDataEventType::SecretStorageDefaultKey => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1154
                Ok(Self::SecretStorageDefaultKey)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1155
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1156
            RumaGlobalAccountDataEventType::SecretStorageKey(key_id) => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1157
                Ok(Self::SecretStorageKey { key_id })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1158
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1159
            _ => Err("Unsupported account data event type".to_owned()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1160
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1161
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1162
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1163
7ff8adafe9e4atagen2026-10-22 12:30 UTC1164
/// Global account data events.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1165
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1166
pub enum AccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1167
    /// m.direct
7ff8adafe9e4atagen2026-10-22 12:30 UTC1168
    Direct {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1169
        /// The mapping of user ID to a list of room IDs of the ‘direct’ rooms
7ff8adafe9e4atagen2026-10-22 12:30 UTC1170
        /// for that user ID.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1171
        map: HashMap<String, Vec<String>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1172
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1173
    /// m.identity_server
7ff8adafe9e4atagen2026-10-22 12:30 UTC1174
    IdentityServer {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1175
        /// The base URL for the identity server for client-server connections.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1176
        base_url: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1177
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1178
    /// m.ignored_user_list
7ff8adafe9e4atagen2026-10-22 12:30 UTC1179
    IgnoredUserList {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1180
        /// The map of users to ignore. This is a mapping of user ID to empty
7ff8adafe9e4atagen2026-10-22 12:30 UTC1181
        /// object.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1182
        ignored_users: HashMap<String, IgnoredUser>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1183
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1184
    /// m.push_rules
7ff8adafe9e4atagen2026-10-22 12:30 UTC1185
    PushRules {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1186
        /// The global ruleset.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1187
        global: Ruleset,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1188
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1189
    /// m.secret_storage.default_key
7ff8adafe9e4atagen2026-10-22 12:30 UTC1190
    SecretStorageDefaultKey {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1191
        /// The ID of the default key.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1192
        key_id: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1193
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1194
    /// m.secret_storage.key.*
7ff8adafe9e4atagen2026-10-22 12:30 UTC1195
    SecretStorageKey {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1196
        /// The ID of the key.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1197
        key_id: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1198
7ff8adafe9e4atagen2026-10-22 12:30 UTC1199
        /// The name of the key.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1200
        name: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1201
7ff8adafe9e4atagen2026-10-22 12:30 UTC1202
        /// The encryption algorithm used for this key.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1203
        ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC1204
        /// Currently, only `m.secret_storage.v1.aes-hmac-sha2` is supported.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1205
        algorithm: SecretStorageEncryptionAlgorithm,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1206
7ff8adafe9e4atagen2026-10-22 12:30 UTC1207
        /// The passphrase from which to generate the key.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1208
        passphrase: Option<PassPhrase>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1209
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1210
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1211
7ff8adafe9e4atagen2026-10-22 12:30 UTC1212
/// The policy that decides if media previews should be shown in the timeline.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1213
#[derive(Clone, uniffi::Enum, Default)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1214
pub enum MediaPreviews {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1215
    /// Always show media previews in the timeline.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1216
    #[default]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1217
    On,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1218
    /// Show media previews in the timeline only if the room is private.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1219
    Private,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1220
    /// Never show media previews in the timeline.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1221
    Off,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1222
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1223
7ff8adafe9e4atagen2026-10-22 12:30 UTC1224
impl From<RumaMediaPreviews> for MediaPreviews {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1225
    fn from(value: RumaMediaPreviews) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1226
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1227
            RumaMediaPreviews::On => Self::On,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1228
            RumaMediaPreviews::Private => Self::Private,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1229
            RumaMediaPreviews::Off => Self::Off,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1230
            _ => Default::default(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1231
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1232
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1233
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1234
7ff8adafe9e4atagen2026-10-22 12:30 UTC1235
impl From<MediaPreviews> for RumaMediaPreviews {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1236
    fn from(value: MediaPreviews) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1237
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1238
            MediaPreviews::On => Self::On,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1239
            MediaPreviews::Private => Self::Private,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1240
            MediaPreviews::Off => Self::Off,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1241
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1242
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1243
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1244
7ff8adafe9e4atagen2026-10-22 12:30 UTC1245
/// The policy that decides if avatars should be shown in invite requests.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1246
#[derive(Clone, uniffi::Enum, Default)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1247
pub enum InviteAvatars {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1248
    /// Always show avatars in invite requests.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1249
    #[default]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1250
    On,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1251
    /// Never show avatars in invite requests.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1252
    Off,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1253
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1254
7ff8adafe9e4atagen2026-10-22 12:30 UTC1255
impl From<RumaInviteAvatars> for InviteAvatars {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1256
    fn from(value: RumaInviteAvatars) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1257
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1258
            RumaInviteAvatars::On => Self::On,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1259
            RumaInviteAvatars::Off => Self::Off,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1260
            _ => Default::default(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1261
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1262
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1263
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1264
7ff8adafe9e4atagen2026-10-22 12:30 UTC1265
impl From<InviteAvatars> for RumaInviteAvatars {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1266
    fn from(value: InviteAvatars) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1267
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1268
            InviteAvatars::On => Self::On,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1269
            InviteAvatars::Off => Self::Off,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1270
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1271
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1272
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1273
7ff8adafe9e4atagen2026-10-22 12:30 UTC1274
/// Details about an ignored user.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1275
///
7ff8adafe9e4atagen2026-10-22 12:30 UTC1276
/// This is currently empty.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1277
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1278
pub struct IgnoredUser {}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1279
7ff8adafe9e4atagen2026-10-22 12:30 UTC1280
impl From<RumaIgnoredUser> for IgnoredUser {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1281
    fn from(_value: RumaIgnoredUser) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1282
        IgnoredUser {}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1283
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1284
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1285
7ff8adafe9e4atagen2026-10-22 12:30 UTC1286
/// A push ruleset scopes a set of rules according to some criteria.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1287
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1288
pub struct Ruleset {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1289
    /// These rules configure behavior for (unencrypted) messages that match
7ff8adafe9e4atagen2026-10-22 12:30 UTC1290
    /// certain patterns.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1291
    pub content: Vec<PatternedPushRule>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1292
7ff8adafe9e4atagen2026-10-22 12:30 UTC1293
    /// These user-configured rules are given the highest priority.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1294
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC1295
    /// This field is named `override_` instead of `override` because the latter
7ff8adafe9e4atagen2026-10-22 12:30 UTC1296
    /// is a reserved keyword in Rust.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1297
    pub override_: Vec<ConditionalPushRule>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1298
7ff8adafe9e4atagen2026-10-22 12:30 UTC1299
    /// These rules change the behavior of all messages for a given room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1300
    pub room: Vec<SimplePushRule>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1301
7ff8adafe9e4atagen2026-10-22 12:30 UTC1302
    /// These rules configure notification behavior for messages from a specific
7ff8adafe9e4atagen2026-10-22 12:30 UTC1303
    /// Matrix user ID.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1304
    pub sender: Vec<SimplePushRule>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1305
7ff8adafe9e4atagen2026-10-22 12:30 UTC1306
    /// These rules are identical to override rules, but have a lower priority
7ff8adafe9e4atagen2026-10-22 12:30 UTC1307
    /// than `content`, `room` and `sender` rules.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1308
    pub underride: Vec<ConditionalPushRule>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1309
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1310
7ff8adafe9e4atagen2026-10-22 12:30 UTC1311
impl TryFrom<RumaRuleset> for Ruleset {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1312
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1313
7ff8adafe9e4atagen2026-10-22 12:30 UTC1314
    fn try_from(value: RumaRuleset) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1315
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1316
            content: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1317
                .content
7ff8adafe9e4atagen2026-10-22 12:30 UTC1318
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1319
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1320
                .collect::<Result<Vec<_>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1321
            override_: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1322
                .override_
7ff8adafe9e4atagen2026-10-22 12:30 UTC1323
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1324
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1325
                .collect::<Result<Vec<_>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1326
            room: value.room.into_iter().map(TryInto::try_into).collect::<Result<Vec<_>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1327
            sender: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1328
                .sender
7ff8adafe9e4atagen2026-10-22 12:30 UTC1329
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1330
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1331
                .collect::<Result<Vec<_>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1332
            underride: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1333
                .underride
7ff8adafe9e4atagen2026-10-22 12:30 UTC1334
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1335
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1336
                .collect::<Result<Vec<_>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1337
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1338
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1339
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1340
7ff8adafe9e4atagen2026-10-22 12:30 UTC1341
/// Like [`SimplePushRule`], but with an additional `pattern`` field.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1342
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1343
pub struct PatternedPushRule {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1344
    /// Actions to determine if and how a notification is delivered for events
7ff8adafe9e4atagen2026-10-22 12:30 UTC1345
    /// matching this rule.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1346
    pub actions: Vec<Action>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1347
7ff8adafe9e4atagen2026-10-22 12:30 UTC1348
    /// Whether this is a default rule, or has been set explicitly.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1349
    pub default: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1350
7ff8adafe9e4atagen2026-10-22 12:30 UTC1351
    /// Whether the push rule is enabled or not.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1352
    pub enabled: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1353
7ff8adafe9e4atagen2026-10-22 12:30 UTC1354
    /// The ID of this rule.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1355
    pub rule_id: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1356
7ff8adafe9e4atagen2026-10-22 12:30 UTC1357
    /// The glob-style pattern to match against.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1358
    pub pattern: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1359
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1360
7ff8adafe9e4atagen2026-10-22 12:30 UTC1361
impl TryFrom<RumaPatternedPushRule> for PatternedPushRule {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1362
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1363
7ff8adafe9e4atagen2026-10-22 12:30 UTC1364
    fn try_from(value: RumaPatternedPushRule) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1365
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1366
            actions: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1367
                .actions
7ff8adafe9e4atagen2026-10-22 12:30 UTC1368
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1369
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1370
                .collect::<Result<Vec<_>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1371
            default: value.default,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1372
            enabled: value.enabled,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1373
            rule_id: value.rule_id,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1374
            pattern: value.pattern,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1375
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1376
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1377
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1378
7ff8adafe9e4atagen2026-10-22 12:30 UTC1379
/// Like [`SimplePushRule`], but with an additional `conditions` field.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1380
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1381
pub struct ConditionalPushRule {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1382
    /// Actions to determine if and how a notification is delivered for events
7ff8adafe9e4atagen2026-10-22 12:30 UTC1383
    /// matching this rule.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1384
    pub actions: Vec<Action>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1385
7ff8adafe9e4atagen2026-10-22 12:30 UTC1386
    /// Whether this is a default rule, or has been set explicitly.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1387
    pub default: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1388
7ff8adafe9e4atagen2026-10-22 12:30 UTC1389
    /// Whether the push rule is enabled or not.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1390
    pub enabled: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1391
7ff8adafe9e4atagen2026-10-22 12:30 UTC1392
    /// The ID of this rule.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1393
    pub rule_id: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1394
7ff8adafe9e4atagen2026-10-22 12:30 UTC1395
    /// The conditions that must hold true for an event in order for a rule to
7ff8adafe9e4atagen2026-10-22 12:30 UTC1396
    /// be applied to an event.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1397
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC1398
    /// A rule with no conditions always matches.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1399
    pub conditions: Vec<PushCondition>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1400
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1401
7ff8adafe9e4atagen2026-10-22 12:30 UTC1402
impl TryFrom<RumaConditionalPushRule> for ConditionalPushRule {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1403
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1404
7ff8adafe9e4atagen2026-10-22 12:30 UTC1405
    fn try_from(value: RumaConditionalPushRule) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1406
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1407
            actions: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1408
                .actions
7ff8adafe9e4atagen2026-10-22 12:30 UTC1409
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1410
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1411
                .collect::<Result<Vec<_>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1412
            default: value.default,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1413
            enabled: value.enabled,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1414
            rule_id: value.rule_id,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1415
            conditions: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1416
                .conditions
7ff8adafe9e4atagen2026-10-22 12:30 UTC1417
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1418
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1419
                .collect::<Result<Vec<_>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1420
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1421
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1422
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1423
7ff8adafe9e4atagen2026-10-22 12:30 UTC1424
/// A push rule is a single rule that states under what conditions an event
7ff8adafe9e4atagen2026-10-22 12:30 UTC1425
/// should be passed onto a push gateway and how the notification should be
7ff8adafe9e4atagen2026-10-22 12:30 UTC1426
/// presented.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1427
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1428
pub struct SimplePushRule {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1429
    /// Actions to determine if and how a notification is delivered for events
7ff8adafe9e4atagen2026-10-22 12:30 UTC1430
    /// matching this rule.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1431
    pub actions: Vec<Action>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1432
7ff8adafe9e4atagen2026-10-22 12:30 UTC1433
    /// Whether this is a default rule, or has been set explicitly.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1434
    pub default: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1435
7ff8adafe9e4atagen2026-10-22 12:30 UTC1436
    /// Whether the push rule is enabled or not.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1437
    pub enabled: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1438
7ff8adafe9e4atagen2026-10-22 12:30 UTC1439
    /// The ID of this rule.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1440
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC1441
    /// This is generally the Matrix ID of the entity that it applies to.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1442
    pub rule_id: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1443
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1444
7ff8adafe9e4atagen2026-10-22 12:30 UTC1445
impl TryFrom<RumaSimplePushRule<OwnedRoomId>> for SimplePushRule {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1446
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1447
7ff8adafe9e4atagen2026-10-22 12:30 UTC1448
    fn try_from(value: RumaSimplePushRule<OwnedRoomId>) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1449
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1450
            actions: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1451
                .actions
7ff8adafe9e4atagen2026-10-22 12:30 UTC1452
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1453
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1454
                .collect::<Result<Vec<_>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1455
            default: value.default,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1456
            enabled: value.enabled,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1457
            rule_id: value.rule_id.into(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1458
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1459
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1460
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1461
7ff8adafe9e4atagen2026-10-22 12:30 UTC1462
impl TryFrom<RumaSimplePushRule<OwnedUserId>> for SimplePushRule {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1463
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1464
7ff8adafe9e4atagen2026-10-22 12:30 UTC1465
    fn try_from(value: RumaSimplePushRule<OwnedUserId>) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1466
        Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1467
            actions: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1468
                .actions
7ff8adafe9e4atagen2026-10-22 12:30 UTC1469
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1470
                .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1471
                .collect::<Result<Vec<_>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1472
            default: value.default,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1473
            enabled: value.enabled,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1474
            rule_id: value.rule_id.into(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1475
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1476
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1477
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1478
7ff8adafe9e4atagen2026-10-22 12:30 UTC1479
/// An algorithm and its properties, used to encrypt a secret.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1480
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1481
pub enum SecretStorageEncryptionAlgorithm {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1482
    /// Encrypted using the `m.secret_storage.v1.aes-hmac-sha2` algorithm.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1483
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC1484
    /// Secrets using this method are encrypted using AES-CTR-256 and
7ff8adafe9e4atagen2026-10-22 12:30 UTC1485
    /// authenticated using HMAC-SHA-256.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1486
    V1AesHmacSha2 { properties: SecretStorageV1AesHmacSha2Properties },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1487
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1488
7ff8adafe9e4atagen2026-10-22 12:30 UTC1489
impl TryFrom<RumaSecretStorageEncryptionAlgorithm> for SecretStorageEncryptionAlgorithm {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1490
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1491
7ff8adafe9e4atagen2026-10-22 12:30 UTC1492
    fn try_from(value: RumaSecretStorageEncryptionAlgorithm) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1493
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1494
            RumaSecretStorageEncryptionAlgorithm::V1AesHmacSha2(properties) => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1495
                Ok(Self::V1AesHmacSha2 { properties: properties.into() })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1496
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1497
            _ => Err("Unsupported encryption algorithm".to_owned()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1498
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1499
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1500
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1501
7ff8adafe9e4atagen2026-10-22 12:30 UTC1502
/// The key properties for the `m.secret_storage.v1.aes-hmac-sha2`` algorithm.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1503
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1504
pub struct SecretStorageV1AesHmacSha2Properties {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1505
    /// The 16-byte initialization vector, encoded as base64.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1506
    pub iv: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1507
7ff8adafe9e4atagen2026-10-22 12:30 UTC1508
    /// The MAC, encoded as base64.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1509
    pub mac: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1510
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1511
7ff8adafe9e4atagen2026-10-22 12:30 UTC1512
impl From<RumaSecretStorageV1AesHmacSha2Properties> for SecretStorageV1AesHmacSha2Properties {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1513
    fn from(value: RumaSecretStorageV1AesHmacSha2Properties) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1514
        Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1515
            iv: value.iv.map(|base64| base64.encode()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1516
            mac: value.mac.map(|base64| base64.encode()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1517
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1518
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1519
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1520
7ff8adafe9e4atagen2026-10-22 12:30 UTC1521
/// The content of an `m.media_preview_config` event.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1522
///
7ff8adafe9e4atagen2026-10-22 12:30 UTC1523
/// Is also the content of the unstable
7ff8adafe9e4atagen2026-10-22 12:30 UTC1524
/// `io.element.msc4278.media_preview_config`.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1525
#[derive(Clone, uniffi::Record, Default)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1526
pub struct MediaPreviewConfig {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1527
    /// The media previews setting for the user.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1528
    pub media_previews: Option<MediaPreviews>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1529
7ff8adafe9e4atagen2026-10-22 12:30 UTC1530
    /// The invite avatars setting for the user.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1531
    pub invite_avatars: Option<InviteAvatars>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1532
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1533
7ff8adafe9e4atagen2026-10-22 12:30 UTC1534
impl From<MediaPreviewConfigEventContent> for MediaPreviewConfig {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1535
    fn from(value: MediaPreviewConfigEventContent) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1536
        Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1537
            media_previews: value.media_previews.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1538
            invite_avatars: value.invite_avatars.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1539
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1540
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1541
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1542
7ff8adafe9e4atagen2026-10-22 12:30 UTC1543
/// A passphrase from which a key is to be derived.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1544
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1545
pub struct PassPhrase {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1546
    /// The algorithm to use to generate the key from the passphrase.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1547
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC1548
    /// Must be `m.pbkdf2`.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1549
    pub algorithm: KeyDerivationAlgorithm,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1550
7ff8adafe9e4atagen2026-10-22 12:30 UTC1551
    /// The salt used in PBKDF2.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1552
    pub salt: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1553
7ff8adafe9e4atagen2026-10-22 12:30 UTC1554
    /// The number of iterations to use in PBKDF2.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1555
    pub iterations: u64,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1556
7ff8adafe9e4atagen2026-10-22 12:30 UTC1557
    /// The number of bits to generate for the key.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1558
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC1559
    /// Defaults to 256
7ff8adafe9e4atagen2026-10-22 12:30 UTC1560
    pub bits: u64,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1561
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1562
7ff8adafe9e4atagen2026-10-22 12:30 UTC1563
impl TryFrom<RumaPassPhrase> for PassPhrase {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1564
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1565
7ff8adafe9e4atagen2026-10-22 12:30 UTC1566
    fn try_from(value: RumaPassPhrase) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1567
        Ok(PassPhrase {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1568
            algorithm: value.algorithm.try_into()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1569
            salt: value.salt,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1570
            iterations: value.iterations.into(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1571
            bits: value.bits.into(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1572
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1573
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1574
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1575
7ff8adafe9e4atagen2026-10-22 12:30 UTC1576
/// A key algorithm to be used to generate a key from a passphrase.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1577
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1578
pub enum KeyDerivationAlgorithm {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1579
    /// PBKDF2
7ff8adafe9e4atagen2026-10-22 12:30 UTC1580
    Pbkfd2,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1581
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1582
7ff8adafe9e4atagen2026-10-22 12:30 UTC1583
impl TryFrom<RumaKeyDerivationAlgorithm> for KeyDerivationAlgorithm {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1584
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1585
7ff8adafe9e4atagen2026-10-22 12:30 UTC1586
    fn try_from(value: RumaKeyDerivationAlgorithm) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1587
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1588
            RumaKeyDerivationAlgorithm::Pbkfd2 => Ok(Self::Pbkfd2),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1589
            _ => Err("Unsupported key derivation algorithm".to_owned()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1590
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1591
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1592
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1593
7ff8adafe9e4atagen2026-10-22 12:30 UTC1594
impl From<RumaGlobalAccountDataEvent<DirectEventContent>> for AccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1595
    fn from(value: RumaGlobalAccountDataEvent<DirectEventContent>) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1596
        Self::Direct {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1597
            map: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1598
                .content
7ff8adafe9e4atagen2026-10-22 12:30 UTC1599
                .0
7ff8adafe9e4atagen2026-10-22 12:30 UTC1600
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1601
                .map(|(user_id, room_ids)| {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1602
                    (user_id.to_string(), room_ids.iter().map(ToString::to_string).collect())
7ff8adafe9e4atagen2026-10-22 12:30 UTC1603
                })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1604
                .collect(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1605
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1606
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1607
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1608
7ff8adafe9e4atagen2026-10-22 12:30 UTC1609
impl From<RumaGlobalAccountDataEvent<IdentityServerEventContent>> for AccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1610
    fn from(value: RumaGlobalAccountDataEvent<IdentityServerEventContent>) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1611
        Self::IdentityServer { base_url: value.content.base_url.into_option() }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1612
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1613
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1614
7ff8adafe9e4atagen2026-10-22 12:30 UTC1615
impl From<RumaGlobalAccountDataEvent<IgnoredUserListEventContent>> for AccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1616
    fn from(value: RumaGlobalAccountDataEvent<IgnoredUserListEventContent>) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1617
        Self::IgnoredUserList {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1618
            ignored_users: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1619
                .content
7ff8adafe9e4atagen2026-10-22 12:30 UTC1620
                .ignored_users
7ff8adafe9e4atagen2026-10-22 12:30 UTC1621
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1622
                .map(|(user_id, ignored_user)| {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1623
                    (user_id.to_string(), IgnoredUser::from(ignored_user))
7ff8adafe9e4atagen2026-10-22 12:30 UTC1624
                })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1625
                .collect(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1626
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1627
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1628
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1629
7ff8adafe9e4atagen2026-10-22 12:30 UTC1630
impl TryFrom<RumaGlobalAccountDataEvent<PushRulesEventContent>> for AccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1631
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1632
7ff8adafe9e4atagen2026-10-22 12:30 UTC1633
    fn try_from(
7ff8adafe9e4atagen2026-10-22 12:30 UTC1634
        value: RumaGlobalAccountDataEvent<PushRulesEventContent>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1635
    ) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1636
        Ok(Self::PushRules { global: value.content.global.try_into()? })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1637
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1638
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1639
7ff8adafe9e4atagen2026-10-22 12:30 UTC1640
impl From<RumaGlobalAccountDataEvent<SecretStorageDefaultKeyEventContent>> for AccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1641
    fn from(value: RumaGlobalAccountDataEvent<SecretStorageDefaultKeyEventContent>) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1642
        Self::SecretStorageDefaultKey { key_id: value.content.key_id }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1643
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1644
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1645
7ff8adafe9e4atagen2026-10-22 12:30 UTC1646
impl TryFrom<RumaGlobalAccountDataEvent<SecretStorageKeyEventContent>> for AccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1647
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1648
7ff8adafe9e4atagen2026-10-22 12:30 UTC1649
    fn try_from(
7ff8adafe9e4atagen2026-10-22 12:30 UTC1650
        value: RumaGlobalAccountDataEvent<SecretStorageKeyEventContent>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1651
    ) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1652
        Ok(Self::SecretStorageKey {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1653
            key_id: value.content.key_id,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1654
            name: value.content.name,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1655
            algorithm: value.content.algorithm.try_into()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1656
            passphrase: value.content.passphrase.map(TryInto::try_into).transpose()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1657
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1658
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1659
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1660
7ff8adafe9e4atagen2026-10-22 12:30 UTC1661
/// Types of room account data events.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1662
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1663
pub enum RoomAccountDataEventType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1664
    /// m.fully_read
7ff8adafe9e4atagen2026-10-22 12:30 UTC1665
    FullyRead,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1666
    /// m.marked_unread
7ff8adafe9e4atagen2026-10-22 12:30 UTC1667
    MarkedUnread,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1668
    /// m.tag
7ff8adafe9e4atagen2026-10-22 12:30 UTC1669
    Tag,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1670
    /// com.famedly.marked_unread
7ff8adafe9e4atagen2026-10-22 12:30 UTC1671
    UnstableMarkedUnread,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1672
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1673
7ff8adafe9e4atagen2026-10-22 12:30 UTC1674
impl TryFrom<RumaRoomAccountDataEventType> for RoomAccountDataEventType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1675
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1676
7ff8adafe9e4atagen2026-10-22 12:30 UTC1677
    fn try_from(value: RumaRoomAccountDataEventType) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1678
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1679
            RumaRoomAccountDataEventType::FullyRead => Ok(Self::FullyRead),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1680
            RumaRoomAccountDataEventType::MarkedUnread => Ok(Self::MarkedUnread),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1681
            RumaRoomAccountDataEventType::Tag => Ok(Self::Tag),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1682
            RumaRoomAccountDataEventType::UnstableMarkedUnread => Ok(Self::UnstableMarkedUnread),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1683
            _ => Err("Unsupported account data event type".to_owned()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1684
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1685
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1686
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1687
7ff8adafe9e4atagen2026-10-22 12:30 UTC1688
/// Room account data events.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1689
#[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1690
pub enum RoomAccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1691
    /// m.fully_read
7ff8adafe9e4atagen2026-10-22 12:30 UTC1692
    FullyReadEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1693
        /// The event the user's read marker is located at in the room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1694
        event_id: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1695
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1696
    /// m.marked_unread
7ff8adafe9e4atagen2026-10-22 12:30 UTC1697
    MarkedUnread {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1698
        /// The current unread state.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1699
        unread: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1700
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1701
    /// m.tag
7ff8adafe9e4atagen2026-10-22 12:30 UTC1702
    Tag { tags: HashMap<TagName, TagInfo> },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1703
    /// com.famedly.marked_unread
7ff8adafe9e4atagen2026-10-22 12:30 UTC1704
    UnstableMarkedUnread {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1705
        /// The current unread state.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1706
        unread: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1707
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1708
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1709
7ff8adafe9e4atagen2026-10-22 12:30 UTC1710
/// The name of a tag.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1711
#[derive(Clone, PartialEq, Eq, Hash, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1712
#[uniffi::export(Eq, Hash)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1713
pub enum TagName {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1714
    /// `m.favourite`: The user's favorite rooms.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1715
    Favorite,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1716
7ff8adafe9e4atagen2026-10-22 12:30 UTC1717
    /// `m.lowpriority`: These should be shown with lower precedence than
7ff8adafe9e4atagen2026-10-22 12:30 UTC1718
    /// others.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1719
    LowPriority,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1720
7ff8adafe9e4atagen2026-10-22 12:30 UTC1721
    /// `m.server_notice`: Used to identify
7ff8adafe9e4atagen2026-10-22 12:30 UTC1722
    ServerNotice,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1723
7ff8adafe9e4atagen2026-10-22 12:30 UTC1724
    /// `u.*`: User-defined tag
7ff8adafe9e4atagen2026-10-22 12:30 UTC1725
    User { name: UserTagName },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1726
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1727
7ff8adafe9e4atagen2026-10-22 12:30 UTC1728
impl TryFrom<RumaTagName> for TagName {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1729
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1730
7ff8adafe9e4atagen2026-10-22 12:30 UTC1731
    fn try_from(value: RumaTagName) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1732
        match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1733
            RumaTagName::Favorite => Ok(Self::Favorite),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1734
            RumaTagName::LowPriority => Ok(Self::LowPriority),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1735
            RumaTagName::ServerNotice => Ok(Self::ServerNotice),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1736
            RumaTagName::User(name) => Ok(Self::User { name: name.into() }),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1737
            _ => Err("Unsupported tag name".to_owned()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1738
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1739
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1740
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1741
7ff8adafe9e4atagen2026-10-22 12:30 UTC1742
/// A user-defined tag name.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1743
#[derive(Clone, PartialEq, Eq, Hash, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1744
pub struct UserTagName {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1745
    name: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1746
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1747
7ff8adafe9e4atagen2026-10-22 12:30 UTC1748
impl From<RumaUserTagName> for UserTagName {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1749
    fn from(value: RumaUserTagName) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1750
        Self { name: value.as_ref().to_owned() }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1751
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1752
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1753
7ff8adafe9e4atagen2026-10-22 12:30 UTC1754
/// Information about a tag.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1755
#[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1756
pub struct TagInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1757
    /// Value to use for lexicographically ordering rooms with this tag.
7ff8adafe9e4atagen2026-10-22 12:30 UTC1758
    pub order: Option<f64>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1759
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1760
7ff8adafe9e4atagen2026-10-22 12:30 UTC1761
impl From<RumaTagInfo> for TagInfo {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1762
    fn from(value: RumaTagInfo) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1763
        Self { order: value.order }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1764
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1765
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1766
7ff8adafe9e4atagen2026-10-22 12:30 UTC1767
impl From<RumaRoomAccountDataEvent<FullyReadEventContent>> for RoomAccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1768
    fn from(value: RumaRoomAccountDataEvent<FullyReadEventContent>) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1769
        Self::FullyReadEvent { event_id: value.content.event_id.into() }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1770
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1771
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1772
7ff8adafe9e4atagen2026-10-22 12:30 UTC1773
impl From<RumaRoomAccountDataEvent<MarkedUnreadEventContent>> for RoomAccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1774
    fn from(value: RumaRoomAccountDataEvent<MarkedUnreadEventContent>) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1775
        Self::MarkedUnread { unread: value.content.unread }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1776
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1777
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1778
7ff8adafe9e4atagen2026-10-22 12:30 UTC1779
impl TryFrom<RumaRoomAccountDataEvent<TagEventContent>> for RoomAccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1780
    type Error = String;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1781
7ff8adafe9e4atagen2026-10-22 12:30 UTC1782
    fn try_from(value: RumaRoomAccountDataEvent<TagEventContent>) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1783
        Ok(Self::Tag {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1784
            tags: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1785
                .content
7ff8adafe9e4atagen2026-10-22 12:30 UTC1786
                .tags
7ff8adafe9e4atagen2026-10-22 12:30 UTC1787
                .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1788
                .map(|(name, info)| name.try_into().map(|name| (name, info.into())))
7ff8adafe9e4atagen2026-10-22 12:30 UTC1789
                .collect::<Result<HashMap<TagName, _>, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1790
        })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1791
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1792
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1793
7ff8adafe9e4atagen2026-10-22 12:30 UTC1794
impl From<RumaRoomAccountDataEvent<UnstableMarkedUnreadEventContent>> for RoomAccountDataEvent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1795
    fn from(value: RumaRoomAccountDataEvent<UnstableMarkedUnreadEventContent>) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1796
        Self::UnstableMarkedUnread { unread: value.content.unread }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1797
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1798
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC1799
7ff8adafe9e4atagen2026-10-22 12:30 UTC1800
#[cfg(feature = "unstable-msc4274")]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1801
pub use galleries::*;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1802
7ff8adafe9e4atagen2026-10-22 12:30 UTC1803
#[cfg(feature = "unstable-msc4274")]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1804
mod galleries {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1805
    use ruma::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC1806
        events::room::message::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC1807
            GalleryItemType as RumaGalleryItemType,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1808
            GalleryMessageEventContent as RumaGalleryMessageEventContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1809
        },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1810
        serde::JsonObject,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1811
    };
7ff8adafe9e4atagen2026-10-22 12:30 UTC1812
7ff8adafe9e4atagen2026-10-22 12:30 UTC1813
    use crate::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC1814
        error::ClientError,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1815
        ruma::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC1816
            AudioMessageContent, FileMessageContent, FormattedBody, ImageMessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1817
            VideoMessageContent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1818
        },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1819
    };
7ff8adafe9e4atagen2026-10-22 12:30 UTC1820
7ff8adafe9e4atagen2026-10-22 12:30 UTC1821
    #[derive(Clone, uniffi::Record)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1822
    pub struct GalleryMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1823
        pub body: String,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1824
        pub formatted: Option<FormattedBody>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1825
        pub itemtypes: Vec<GalleryItemType>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1826
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1827
7ff8adafe9e4atagen2026-10-22 12:30 UTC1828
    impl TryFrom<GalleryMessageContent> for RumaGalleryMessageEventContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1829
        type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1830
7ff8adafe9e4atagen2026-10-22 12:30 UTC1831
        fn try_from(value: GalleryMessageContent) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1832
            Ok(Self::new(
7ff8adafe9e4atagen2026-10-22 12:30 UTC1833
                value.body,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1834
                value.formatted.map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1835
                value.itemtypes.into_iter().map(TryInto::try_into).collect::<Result<_, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1836
            ))
7ff8adafe9e4atagen2026-10-22 12:30 UTC1837
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1838
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1839
7ff8adafe9e4atagen2026-10-22 12:30 UTC1840
    impl TryFrom<RumaGalleryMessageEventContent> for GalleryMessageContent {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1841
        type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1842
7ff8adafe9e4atagen2026-10-22 12:30 UTC1843
        fn try_from(value: RumaGalleryMessageEventContent) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1844
            Ok(Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1845
                body: value.body,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1846
                formatted: value.formatted.as_ref().map(Into::into),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1847
                itemtypes: value
7ff8adafe9e4atagen2026-10-22 12:30 UTC1848
                    .itemtypes
7ff8adafe9e4atagen2026-10-22 12:30 UTC1849
                    .into_iter()
7ff8adafe9e4atagen2026-10-22 12:30 UTC1850
                    .map(TryInto::try_into)
7ff8adafe9e4atagen2026-10-22 12:30 UTC1851
                    .collect::<Result<_, _>>()?,
7ff8adafe9e4atagen2026-10-22 12:30 UTC1852
            })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1853
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1854
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1855
7ff8adafe9e4atagen2026-10-22 12:30 UTC1856
    #[derive(Clone, uniffi::Enum)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC1857
    pub enum GalleryItemType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1858
        Image { content: ImageMessageContent },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1859
        Audio { content: AudioMessageContent },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1860
        Video { content: VideoMessageContent },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1861
        File { content: FileMessageContent },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1862
        Other { itemtype: String, body: String },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1863
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1864
7ff8adafe9e4atagen2026-10-22 12:30 UTC1865
    impl TryFrom<GalleryItemType> for RumaGalleryItemType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1866
        type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1867
7ff8adafe9e4atagen2026-10-22 12:30 UTC1868
        fn try_from(value: GalleryItemType) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1869
            Ok(match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1870
                GalleryItemType::Image { content } => Self::Image(content.into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1871
                GalleryItemType::Audio { content } => Self::Audio(content.into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1872
                GalleryItemType::Video { content } => Self::Video(content.into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1873
                GalleryItemType::File { content } => Self::File(content.into()),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1874
                GalleryItemType::Other { itemtype, body } => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1875
                    Self::new(&itemtype, body, JsonObject::default())?
7ff8adafe9e4atagen2026-10-22 12:30 UTC1876
                }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1877
            })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1878
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1879
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1880
7ff8adafe9e4atagen2026-10-22 12:30 UTC1881
    impl TryFrom<RumaGalleryItemType> for GalleryItemType {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1882
        type Error = ClientError;
7ff8adafe9e4atagen2026-10-22 12:30 UTC1883
7ff8adafe9e4atagen2026-10-22 12:30 UTC1884
        fn try_from(value: RumaGalleryItemType) -> Result<Self, Self::Error> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1885
            Ok(match value {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1886
                RumaGalleryItemType::Image(c) => GalleryItemType::Image { content: c.try_into()? },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1887
                RumaGalleryItemType::Audio(c) => GalleryItemType::Audio { content: c.try_into()? },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1888
                RumaGalleryItemType::Video(c) => GalleryItemType::Video { content: c.try_into()? },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1889
                RumaGalleryItemType::File(c) => GalleryItemType::File { content: c.try_into()? },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1890
                _ => GalleryItemType::Other {
7ff8adafe9e4atagen2026-10-22 12:30 UTC1891
                    itemtype: value.itemtype().to_owned(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1892
                    body: value.body().to_owned(),
7ff8adafe9e4atagen2026-10-22 12:30 UTC1893
                },
7ff8adafe9e4atagen2026-10-22 12:30 UTC1894
            })
7ff8adafe9e4atagen2026-10-22 12:30 UTC1895
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1896
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC1897
}