atagen

matrix-rust-sdk

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

Blame: crates/matrix-sdk-base/src/sync.rs

7ff8adafe9e4atagen2026-10-22 12:30 UTC1
// Copyright 2022 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
//! The SDK's representation of the result of a `/sync` request.
7ff8adafe9e4atagen2026-10-22 12:30 UTC16
7ff8adafe9e4atagen2026-10-22 12:30 UTC17
use std::{collections::BTreeMap, fmt};
7ff8adafe9e4atagen2026-10-22 12:30 UTC18
7ff8adafe9e4atagen2026-10-22 12:30 UTC19
use matrix_sdk_common::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC20
    debug::DebugRawEvent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC21
    deserialized_responses::{ProcessedToDeviceEvent, TimelineEvent},
7ff8adafe9e4atagen2026-10-22 12:30 UTC22
};
7ff8adafe9e4atagen2026-10-22 12:30 UTC23
pub use ruma::api::client::sync::sync_events::v3::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC24
    InvitedRoom as InvitedRoomUpdate, KnockedRoom as KnockedRoomUpdate,
7ff8adafe9e4atagen2026-10-22 12:30 UTC25
};
7ff8adafe9e4atagen2026-10-22 12:30 UTC26
use ruma::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC27
    OwnedEventId, OwnedMxcUri, OwnedRoomId, OwnedUserId,
7ff8adafe9e4atagen2026-10-22 12:30 UTC28
    api::client::sync::sync_events::UnreadNotificationsCount as RumaUnreadNotificationsCount,
7ff8adafe9e4atagen2026-10-22 12:30 UTC29
    events::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC30
        AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, AnySyncEphemeralRoomEvent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC31
        AnySyncStateEvent, presence::PresenceEvent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC32
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC33
    push::Action,
7ff8adafe9e4atagen2026-10-22 12:30 UTC34
    serde::Raw,
7ff8adafe9e4atagen2026-10-22 12:30 UTC35
};
7ff8adafe9e4atagen2026-10-22 12:30 UTC36
use serde::{Deserialize, Serialize};
7ff8adafe9e4atagen2026-10-22 12:30 UTC37
7ff8adafe9e4atagen2026-10-22 12:30 UTC38
use crate::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC39
    debug::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC40
        DebugInvitedRoom, DebugKnockedRoom, DebugListOfProcessedToDeviceEvents,
7ff8adafe9e4atagen2026-10-22 12:30 UTC41
        DebugListOfRawEvents, DebugListOfRawEventsNoId,
7ff8adafe9e4atagen2026-10-22 12:30 UTC42
    },
7ff8adafe9e4atagen2026-10-22 12:30 UTC43
    deserialized_responses::{AmbiguityChange, RawAnySyncOrStrippedTimelineEvent},
7ff8adafe9e4atagen2026-10-22 12:30 UTC44
};
7ff8adafe9e4atagen2026-10-22 12:30 UTC45
7ff8adafe9e4atagen2026-10-22 12:30 UTC46
/// Generalized representation of a `/sync` response.
7ff8adafe9e4atagen2026-10-22 12:30 UTC47
///
7ff8adafe9e4atagen2026-10-22 12:30 UTC48
/// This type is intended to be applicable regardless of the endpoint used for
7ff8adafe9e4atagen2026-10-22 12:30 UTC49
/// syncing.
7ff8adafe9e4atagen2026-10-22 12:30 UTC50
#[derive(Clone, Default)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC51
pub struct SyncResponse {
7ff8adafe9e4atagen2026-10-22 12:30 UTC52
    /// Updates to rooms.
7ff8adafe9e4atagen2026-10-22 12:30 UTC53
    pub rooms: RoomUpdates,
7ff8adafe9e4atagen2026-10-22 12:30 UTC54
    /// Updates to the presence status of other users.
7ff8adafe9e4atagen2026-10-22 12:30 UTC55
    pub presence: Vec<Raw<PresenceEvent>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC56
    /// The global private data created by this user.
7ff8adafe9e4atagen2026-10-22 12:30 UTC57
    pub account_data: Vec<Raw<AnyGlobalAccountDataEvent>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC58
    /// Messages sent directly between devices.
7ff8adafe9e4atagen2026-10-22 12:30 UTC59
    pub to_device: Vec<ProcessedToDeviceEvent>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC60
    /// New notifications per room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC61
    pub notifications: BTreeMap<OwnedRoomId, Vec<Notification>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC62
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC63
7ff8adafe9e4atagen2026-10-22 12:30 UTC64
#[cfg(not(tarpaulin_include))]
7ff8adafe9e4atagen2026-10-22 12:30 UTC65
impl fmt::Debug for SyncResponse {
7ff8adafe9e4atagen2026-10-22 12:30 UTC66
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7ff8adafe9e4atagen2026-10-22 12:30 UTC67
        f.debug_struct("SyncResponse")
7ff8adafe9e4atagen2026-10-22 12:30 UTC68
            .field("rooms", &self.rooms)
7ff8adafe9e4atagen2026-10-22 12:30 UTC69
            .field("account_data", &DebugListOfRawEventsNoId(&self.account_data))
7ff8adafe9e4atagen2026-10-22 12:30 UTC70
            .field("to_device", &DebugListOfProcessedToDeviceEvents(&self.to_device))
7ff8adafe9e4atagen2026-10-22 12:30 UTC71
            .field("notifications", &self.notifications)
7ff8adafe9e4atagen2026-10-22 12:30 UTC72
            .finish_non_exhaustive()
7ff8adafe9e4atagen2026-10-22 12:30 UTC73
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC74
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC75
7ff8adafe9e4atagen2026-10-22 12:30 UTC76
/// Updates to rooms in a [`SyncResponse`].
7ff8adafe9e4atagen2026-10-22 12:30 UTC77
#[derive(Clone, Default)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC78
pub struct RoomUpdates {
7ff8adafe9e4atagen2026-10-22 12:30 UTC79
    /// The rooms that the user has left or been banned from.
7ff8adafe9e4atagen2026-10-22 12:30 UTC80
    pub left: BTreeMap<OwnedRoomId, LeftRoomUpdate>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC81
    /// The rooms that the user has joined.
7ff8adafe9e4atagen2026-10-22 12:30 UTC82
    pub joined: BTreeMap<OwnedRoomId, JoinedRoomUpdate>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC83
    /// The rooms that the user has been invited to.
7ff8adafe9e4atagen2026-10-22 12:30 UTC84
    pub invited: BTreeMap<OwnedRoomId, InvitedRoomUpdate>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC85
    /// The rooms that the user has knocked on.
7ff8adafe9e4atagen2026-10-22 12:30 UTC86
    pub knocked: BTreeMap<OwnedRoomId, KnockedRoomUpdate>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC87
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC88
7ff8adafe9e4atagen2026-10-22 12:30 UTC89
impl RoomUpdates {
7ff8adafe9e4atagen2026-10-22 12:30 UTC90
    /// Iterate over all room IDs, from [`RoomUpdates::left`],
7ff8adafe9e4atagen2026-10-22 12:30 UTC91
    /// [`RoomUpdates::joined`], [`RoomUpdates::invited`] and
7ff8adafe9e4atagen2026-10-22 12:30 UTC92
    /// [`RoomUpdates::knocked`].
7ff8adafe9e4atagen2026-10-22 12:30 UTC93
    pub fn iter_all_room_ids(&self) -> impl Iterator<Item = &OwnedRoomId> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC94
        self.left
7ff8adafe9e4atagen2026-10-22 12:30 UTC95
            .keys()
7ff8adafe9e4atagen2026-10-22 12:30 UTC96
            .chain(self.joined.keys())
7ff8adafe9e4atagen2026-10-22 12:30 UTC97
            .chain(self.invited.keys())
7ff8adafe9e4atagen2026-10-22 12:30 UTC98
            .chain(self.knocked.keys())
7ff8adafe9e4atagen2026-10-22 12:30 UTC99
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC100
7ff8adafe9e4atagen2026-10-22 12:30 UTC101
    /// Returns whether or not this update contains any changes to the list
7ff8adafe9e4atagen2026-10-22 12:30 UTC102
    /// of invited, joined, knocked or left rooms.
7ff8adafe9e4atagen2026-10-22 12:30 UTC103
    pub fn is_empty(&self) -> bool {
7ff8adafe9e4atagen2026-10-22 12:30 UTC104
        self.invited.is_empty()
7ff8adafe9e4atagen2026-10-22 12:30 UTC105
            && self.joined.is_empty()
7ff8adafe9e4atagen2026-10-22 12:30 UTC106
            && self.knocked.is_empty()
7ff8adafe9e4atagen2026-10-22 12:30 UTC107
            && self.left.is_empty()
7ff8adafe9e4atagen2026-10-22 12:30 UTC108
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC109
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC110
7ff8adafe9e4atagen2026-10-22 12:30 UTC111
#[cfg(test)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC112
mod tests {
7ff8adafe9e4atagen2026-10-22 12:30 UTC113
    use std::collections::BTreeMap;
7ff8adafe9e4atagen2026-10-22 12:30 UTC114
7ff8adafe9e4atagen2026-10-22 12:30 UTC115
    use assert_matches::assert_matches;
7ff8adafe9e4atagen2026-10-22 12:30 UTC116
    use ruma::room_id;
7ff8adafe9e4atagen2026-10-22 12:30 UTC117
7ff8adafe9e4atagen2026-10-22 12:30 UTC118
    use super::{
7ff8adafe9e4atagen2026-10-22 12:30 UTC119
        InvitedRoomUpdate, JoinedRoomUpdate, KnockedRoomUpdate, LeftRoomUpdate, RoomUpdates,
7ff8adafe9e4atagen2026-10-22 12:30 UTC120
    };
7ff8adafe9e4atagen2026-10-22 12:30 UTC121
7ff8adafe9e4atagen2026-10-22 12:30 UTC122
    #[test]
7ff8adafe9e4atagen2026-10-22 12:30 UTC123
    fn test_room_updates_iter_all_room_ids() {
7ff8adafe9e4atagen2026-10-22 12:30 UTC124
        let room_id_0 = room_id!("!r0");
7ff8adafe9e4atagen2026-10-22 12:30 UTC125
        let room_id_1 = room_id!("!r1");
7ff8adafe9e4atagen2026-10-22 12:30 UTC126
        let room_id_2 = room_id!("!r2");
7ff8adafe9e4atagen2026-10-22 12:30 UTC127
        let room_id_3 = room_id!("!r3");
7ff8adafe9e4atagen2026-10-22 12:30 UTC128
        let room_id_4 = room_id!("!r4");
7ff8adafe9e4atagen2026-10-22 12:30 UTC129
        let room_id_5 = room_id!("!r5");
7ff8adafe9e4atagen2026-10-22 12:30 UTC130
        let room_id_6 = room_id!("!r6");
7ff8adafe9e4atagen2026-10-22 12:30 UTC131
        let room_id_7 = room_id!("!r7");
7ff8adafe9e4atagen2026-10-22 12:30 UTC132
        let room_updates = RoomUpdates {
7ff8adafe9e4atagen2026-10-22 12:30 UTC133
            left: {
7ff8adafe9e4atagen2026-10-22 12:30 UTC134
                let mut left = BTreeMap::new();
7ff8adafe9e4atagen2026-10-22 12:30 UTC135
                left.insert(room_id_0.to_owned(), LeftRoomUpdate::default());
7ff8adafe9e4atagen2026-10-22 12:30 UTC136
                left.insert(room_id_1.to_owned(), LeftRoomUpdate::default());
7ff8adafe9e4atagen2026-10-22 12:30 UTC137
                left
7ff8adafe9e4atagen2026-10-22 12:30 UTC138
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC139
            joined: {
7ff8adafe9e4atagen2026-10-22 12:30 UTC140
                let mut joined = BTreeMap::new();
7ff8adafe9e4atagen2026-10-22 12:30 UTC141
                joined.insert(room_id_2.to_owned(), JoinedRoomUpdate::default());
7ff8adafe9e4atagen2026-10-22 12:30 UTC142
                joined.insert(room_id_3.to_owned(), JoinedRoomUpdate::default());
7ff8adafe9e4atagen2026-10-22 12:30 UTC143
                joined
7ff8adafe9e4atagen2026-10-22 12:30 UTC144
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC145
            invited: {
7ff8adafe9e4atagen2026-10-22 12:30 UTC146
                let mut invited = BTreeMap::new();
7ff8adafe9e4atagen2026-10-22 12:30 UTC147
                invited.insert(room_id_4.to_owned(), InvitedRoomUpdate::default());
7ff8adafe9e4atagen2026-10-22 12:30 UTC148
                invited.insert(room_id_5.to_owned(), InvitedRoomUpdate::default());
7ff8adafe9e4atagen2026-10-22 12:30 UTC149
                invited
7ff8adafe9e4atagen2026-10-22 12:30 UTC150
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC151
            knocked: {
7ff8adafe9e4atagen2026-10-22 12:30 UTC152
                let mut knocked = BTreeMap::new();
7ff8adafe9e4atagen2026-10-22 12:30 UTC153
                knocked.insert(room_id_6.to_owned(), KnockedRoomUpdate::default());
7ff8adafe9e4atagen2026-10-22 12:30 UTC154
                knocked.insert(room_id_7.to_owned(), KnockedRoomUpdate::default());
7ff8adafe9e4atagen2026-10-22 12:30 UTC155
                knocked
7ff8adafe9e4atagen2026-10-22 12:30 UTC156
            },
7ff8adafe9e4atagen2026-10-22 12:30 UTC157
        };
7ff8adafe9e4atagen2026-10-22 12:30 UTC158
7ff8adafe9e4atagen2026-10-22 12:30 UTC159
        let mut iter = room_updates.iter_all_room_ids();
7ff8adafe9e4atagen2026-10-22 12:30 UTC160
        assert_matches!(iter.next(), Some(room_id) => assert_eq!(room_id, room_id_0));
7ff8adafe9e4atagen2026-10-22 12:30 UTC161
        assert_matches!(iter.next(), Some(room_id) => assert_eq!(room_id, room_id_1));
7ff8adafe9e4atagen2026-10-22 12:30 UTC162
        assert_matches!(iter.next(), Some(room_id) => assert_eq!(room_id, room_id_2));
7ff8adafe9e4atagen2026-10-22 12:30 UTC163
        assert_matches!(iter.next(), Some(room_id) => assert_eq!(room_id, room_id_3));
7ff8adafe9e4atagen2026-10-22 12:30 UTC164
        assert_matches!(iter.next(), Some(room_id) => assert_eq!(room_id, room_id_4));
7ff8adafe9e4atagen2026-10-22 12:30 UTC165
        assert_matches!(iter.next(), Some(room_id) => assert_eq!(room_id, room_id_5));
7ff8adafe9e4atagen2026-10-22 12:30 UTC166
        assert_matches!(iter.next(), Some(room_id) => assert_eq!(room_id, room_id_6));
7ff8adafe9e4atagen2026-10-22 12:30 UTC167
        assert_matches!(iter.next(), Some(room_id) => assert_eq!(room_id, room_id_7));
7ff8adafe9e4atagen2026-10-22 12:30 UTC168
        assert!(iter.next().is_none());
7ff8adafe9e4atagen2026-10-22 12:30 UTC169
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC170
7ff8adafe9e4atagen2026-10-22 12:30 UTC171
    #[test]
7ff8adafe9e4atagen2026-10-22 12:30 UTC172
    fn test_empty_room_updates() {
7ff8adafe9e4atagen2026-10-22 12:30 UTC173
        let room_updates = RoomUpdates::default();
7ff8adafe9e4atagen2026-10-22 12:30 UTC174
7ff8adafe9e4atagen2026-10-22 12:30 UTC175
        let mut iter = room_updates.iter_all_room_ids();
7ff8adafe9e4atagen2026-10-22 12:30 UTC176
        assert!(iter.next().is_none());
7ff8adafe9e4atagen2026-10-22 12:30 UTC177
7ff8adafe9e4atagen2026-10-22 12:30 UTC178
        assert!(room_updates.is_empty());
7ff8adafe9e4atagen2026-10-22 12:30 UTC179
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC180
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC181
7ff8adafe9e4atagen2026-10-22 12:30 UTC182
#[cfg(not(tarpaulin_include))]
7ff8adafe9e4atagen2026-10-22 12:30 UTC183
impl fmt::Debug for RoomUpdates {
7ff8adafe9e4atagen2026-10-22 12:30 UTC184
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7ff8adafe9e4atagen2026-10-22 12:30 UTC185
        f.debug_struct("RoomUpdates")
7ff8adafe9e4atagen2026-10-22 12:30 UTC186
            .field("left", &self.left)
7ff8adafe9e4atagen2026-10-22 12:30 UTC187
            .field("joined", &self.joined)
7ff8adafe9e4atagen2026-10-22 12:30 UTC188
            .field("invited", &DebugInvitedRoomUpdates(&self.invited))
7ff8adafe9e4atagen2026-10-22 12:30 UTC189
            .field("knocked", &DebugKnockedRoomUpdates(&self.knocked))
7ff8adafe9e4atagen2026-10-22 12:30 UTC190
            .finish()
7ff8adafe9e4atagen2026-10-22 12:30 UTC191
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC192
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC193
7ff8adafe9e4atagen2026-10-22 12:30 UTC194
/// Updates to joined rooms.
7ff8adafe9e4atagen2026-10-22 12:30 UTC195
#[derive(Clone, Default)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC196
pub struct JoinedRoomUpdate {
7ff8adafe9e4atagen2026-10-22 12:30 UTC197
    /// Counts of unread notifications for this room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC198
    pub unread_notifications: UnreadNotificationsCount,
7ff8adafe9e4atagen2026-10-22 12:30 UTC199
    /// The timeline of messages and state changes in the room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC200
    pub timeline: Timeline,
7ff8adafe9e4atagen2026-10-22 12:30 UTC201
    /// Updates to the state.
7ff8adafe9e4atagen2026-10-22 12:30 UTC202
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC203
    /// If `since` is missing or `full_state` is true, the start point of the
7ff8adafe9e4atagen2026-10-22 12:30 UTC204
    /// update is the beginning of the timeline. Otherwise, the start point
7ff8adafe9e4atagen2026-10-22 12:30 UTC205
    /// is the time specified in `since`.
7ff8adafe9e4atagen2026-10-22 12:30 UTC206
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC207
    /// If `state_after` was used, the end point of the update is the end of the
7ff8adafe9e4atagen2026-10-22 12:30 UTC208
    /// `timeline`. Otherwise, the end point of these updates is the start of
7ff8adafe9e4atagen2026-10-22 12:30 UTC209
    /// the `timeline`, and to calculate room state we must scan the `timeline`
7ff8adafe9e4atagen2026-10-22 12:30 UTC210
    /// for state events as well as using this information in this property.
7ff8adafe9e4atagen2026-10-22 12:30 UTC211
    pub state: State,
7ff8adafe9e4atagen2026-10-22 12:30 UTC212
    /// The private data that this user has attached to this room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC213
    pub account_data: Vec<Raw<AnyRoomAccountDataEvent>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC214
    /// The ephemeral events in the room that aren't recorded in the timeline or
7ff8adafe9e4atagen2026-10-22 12:30 UTC215
    /// state of the room. e.g. typing.
7ff8adafe9e4atagen2026-10-22 12:30 UTC216
    pub ephemeral: Vec<Raw<AnySyncEphemeralRoomEvent>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC217
    /// Collection of ambiguity changes that room member events trigger.
7ff8adafe9e4atagen2026-10-22 12:30 UTC218
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC219
    /// This is a map of event ID of the `m.room.member` event to the
7ff8adafe9e4atagen2026-10-22 12:30 UTC220
    /// details of the ambiguity change.
7ff8adafe9e4atagen2026-10-22 12:30 UTC221
    pub ambiguity_changes: BTreeMap<OwnedEventId, AmbiguityChange>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC222
    /// Collection of avatar changes that room member events trigger.
7ff8adafe9e4atagen2026-10-22 12:30 UTC223
    pub avatar_changes: Option<BTreeMap<OwnedUserId, Option<OwnedMxcUri>>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC224
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC225
7ff8adafe9e4atagen2026-10-22 12:30 UTC226
#[cfg(not(tarpaulin_include))]
7ff8adafe9e4atagen2026-10-22 12:30 UTC227
impl fmt::Debug for JoinedRoomUpdate {
7ff8adafe9e4atagen2026-10-22 12:30 UTC228
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7ff8adafe9e4atagen2026-10-22 12:30 UTC229
        f.debug_struct("JoinedRoomUpdate")
7ff8adafe9e4atagen2026-10-22 12:30 UTC230
            .field("unread_notifications", &self.unread_notifications)
7ff8adafe9e4atagen2026-10-22 12:30 UTC231
            .field("timeline", &self.timeline)
7ff8adafe9e4atagen2026-10-22 12:30 UTC232
            .field("state", &self.state)
7ff8adafe9e4atagen2026-10-22 12:30 UTC233
            .field("account_data", &DebugListOfRawEventsNoId(&self.account_data))
7ff8adafe9e4atagen2026-10-22 12:30 UTC234
            .field("ephemeral", &self.ephemeral)
7ff8adafe9e4atagen2026-10-22 12:30 UTC235
            .field("ambiguity_changes", &self.ambiguity_changes)
7ff8adafe9e4atagen2026-10-22 12:30 UTC236
            .finish()
7ff8adafe9e4atagen2026-10-22 12:30 UTC237
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC238
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC239
7ff8adafe9e4atagen2026-10-22 12:30 UTC240
impl JoinedRoomUpdate {
7ff8adafe9e4atagen2026-10-22 12:30 UTC241
    pub(crate) fn new(
7ff8adafe9e4atagen2026-10-22 12:30 UTC242
        timeline: Timeline,
7ff8adafe9e4atagen2026-10-22 12:30 UTC243
        state: State,
7ff8adafe9e4atagen2026-10-22 12:30 UTC244
        account_data: Vec<Raw<AnyRoomAccountDataEvent>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC245
        ephemeral: Vec<Raw<AnySyncEphemeralRoomEvent>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC246
        unread_notifications: UnreadNotificationsCount,
7ff8adafe9e4atagen2026-10-22 12:30 UTC247
        ambiguity_changes: BTreeMap<OwnedEventId, AmbiguityChange>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC248
        avatar_changes: Option<BTreeMap<OwnedUserId, Option<OwnedMxcUri>>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC249
    ) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC250
        Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC251
            unread_notifications,
7ff8adafe9e4atagen2026-10-22 12:30 UTC252
            timeline,
7ff8adafe9e4atagen2026-10-22 12:30 UTC253
            state,
7ff8adafe9e4atagen2026-10-22 12:30 UTC254
            account_data,
7ff8adafe9e4atagen2026-10-22 12:30 UTC255
            ephemeral,
7ff8adafe9e4atagen2026-10-22 12:30 UTC256
            ambiguity_changes,
7ff8adafe9e4atagen2026-10-22 12:30 UTC257
            avatar_changes,
7ff8adafe9e4atagen2026-10-22 12:30 UTC258
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC259
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC260
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC261
7ff8adafe9e4atagen2026-10-22 12:30 UTC262
/// Counts of unread notifications for a room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC263
#[derive(Copy, Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC264
pub struct UnreadNotificationsCount {
7ff8adafe9e4atagen2026-10-22 12:30 UTC265
    /// The number of unread notifications for this room with the highlight flag
7ff8adafe9e4atagen2026-10-22 12:30 UTC266
    /// set.
7ff8adafe9e4atagen2026-10-22 12:30 UTC267
    pub highlight_count: u64,
7ff8adafe9e4atagen2026-10-22 12:30 UTC268
    /// The total number of unread notifications for this room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC269
    pub notification_count: u64,
7ff8adafe9e4atagen2026-10-22 12:30 UTC270
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC271
7ff8adafe9e4atagen2026-10-22 12:30 UTC272
impl From<RumaUnreadNotificationsCount> for UnreadNotificationsCount {
7ff8adafe9e4atagen2026-10-22 12:30 UTC273
    fn from(notifications: RumaUnreadNotificationsCount) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC274
        Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC275
            highlight_count: notifications.highlight_count.map(|c| c.into()).unwrap_or(0),
7ff8adafe9e4atagen2026-10-22 12:30 UTC276
            notification_count: notifications.notification_count.map(|c| c.into()).unwrap_or(0),
7ff8adafe9e4atagen2026-10-22 12:30 UTC277
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC278
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC279
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC280
7ff8adafe9e4atagen2026-10-22 12:30 UTC281
/// Updates to left rooms.
7ff8adafe9e4atagen2026-10-22 12:30 UTC282
#[derive(Clone, Default)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC283
pub struct LeftRoomUpdate {
7ff8adafe9e4atagen2026-10-22 12:30 UTC284
    /// The timeline of messages and state changes in the room up to the point
7ff8adafe9e4atagen2026-10-22 12:30 UTC285
    /// when the user left.
7ff8adafe9e4atagen2026-10-22 12:30 UTC286
    pub timeline: Timeline,
7ff8adafe9e4atagen2026-10-22 12:30 UTC287
    /// Updates to the state.
7ff8adafe9e4atagen2026-10-22 12:30 UTC288
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC289
    /// If `since` is missing or `full_state` is true, the start point of the
7ff8adafe9e4atagen2026-10-22 12:30 UTC290
    /// update is the beginning of the timeline. Otherwise, the start point
7ff8adafe9e4atagen2026-10-22 12:30 UTC291
    /// is the time specified in `since`.
7ff8adafe9e4atagen2026-10-22 12:30 UTC292
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC293
    /// If `state_after` was used, the end point of the update is the end of the
7ff8adafe9e4atagen2026-10-22 12:30 UTC294
    /// `timeline`. Otherwise, the end point of these updates is the start of
7ff8adafe9e4atagen2026-10-22 12:30 UTC295
    /// the `timeline`, and to calculate room state we must scan the `timeline`
7ff8adafe9e4atagen2026-10-22 12:30 UTC296
    /// for state events as well as using this information in this property.
7ff8adafe9e4atagen2026-10-22 12:30 UTC297
    pub state: State,
7ff8adafe9e4atagen2026-10-22 12:30 UTC298
    /// The private data that this user has attached to this room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC299
    pub account_data: Vec<Raw<AnyRoomAccountDataEvent>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC300
    /// Collection of ambiguity changes that room member events trigger.
7ff8adafe9e4atagen2026-10-22 12:30 UTC301
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC302
    /// This is a map of event ID of the `m.room.member` event to the
7ff8adafe9e4atagen2026-10-22 12:30 UTC303
    /// details of the ambiguity change.
7ff8adafe9e4atagen2026-10-22 12:30 UTC304
    pub ambiguity_changes: BTreeMap<OwnedEventId, AmbiguityChange>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC305
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC306
7ff8adafe9e4atagen2026-10-22 12:30 UTC307
impl LeftRoomUpdate {
7ff8adafe9e4atagen2026-10-22 12:30 UTC308
    pub(crate) fn new(
7ff8adafe9e4atagen2026-10-22 12:30 UTC309
        timeline: Timeline,
7ff8adafe9e4atagen2026-10-22 12:30 UTC310
        state: State,
7ff8adafe9e4atagen2026-10-22 12:30 UTC311
        account_data: Vec<Raw<AnyRoomAccountDataEvent>>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC312
        ambiguity_changes: BTreeMap<OwnedEventId, AmbiguityChange>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC313
    ) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC314
        Self { timeline, state, account_data, ambiguity_changes }
7ff8adafe9e4atagen2026-10-22 12:30 UTC315
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC316
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC317
7ff8adafe9e4atagen2026-10-22 12:30 UTC318
#[cfg(not(tarpaulin_include))]
7ff8adafe9e4atagen2026-10-22 12:30 UTC319
impl fmt::Debug for LeftRoomUpdate {
7ff8adafe9e4atagen2026-10-22 12:30 UTC320
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7ff8adafe9e4atagen2026-10-22 12:30 UTC321
        f.debug_struct("LeftRoomUpdate")
7ff8adafe9e4atagen2026-10-22 12:30 UTC322
            .field("timeline", &self.timeline)
7ff8adafe9e4atagen2026-10-22 12:30 UTC323
            .field("state", &self.state)
7ff8adafe9e4atagen2026-10-22 12:30 UTC324
            .field("account_data", &DebugListOfRawEventsNoId(&self.account_data))
7ff8adafe9e4atagen2026-10-22 12:30 UTC325
            .field("ambiguity_changes", &self.ambiguity_changes)
7ff8adafe9e4atagen2026-10-22 12:30 UTC326
            .finish()
7ff8adafe9e4atagen2026-10-22 12:30 UTC327
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC328
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC329
7ff8adafe9e4atagen2026-10-22 12:30 UTC330
/// Events in the room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC331
#[derive(Clone, Debug, Default)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC332
pub struct Timeline {
7ff8adafe9e4atagen2026-10-22 12:30 UTC333
    /// True if the number of events returned was limited by the `limit` on the
7ff8adafe9e4atagen2026-10-22 12:30 UTC334
    /// filter.
7ff8adafe9e4atagen2026-10-22 12:30 UTC335
    pub limited: bool,
7ff8adafe9e4atagen2026-10-22 12:30 UTC336
7ff8adafe9e4atagen2026-10-22 12:30 UTC337
    /// A token that can be supplied to to the `from` parameter of the
7ff8adafe9e4atagen2026-10-22 12:30 UTC338
    /// `/rooms/{roomId}/messages` endpoint.
7ff8adafe9e4atagen2026-10-22 12:30 UTC339
    pub prev_batch: Option<String>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC340
7ff8adafe9e4atagen2026-10-22 12:30 UTC341
    /// A list of events.
7ff8adafe9e4atagen2026-10-22 12:30 UTC342
    pub events: Vec<TimelineEvent>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC343
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC344
7ff8adafe9e4atagen2026-10-22 12:30 UTC345
impl Timeline {
7ff8adafe9e4atagen2026-10-22 12:30 UTC346
    pub(crate) fn new(limited: bool, prev_batch: Option<String>) -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC347
        Self { limited, prev_batch, ..Default::default() }
7ff8adafe9e4atagen2026-10-22 12:30 UTC348
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC349
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC350
7ff8adafe9e4atagen2026-10-22 12:30 UTC351
/// State changes in the room.
7ff8adafe9e4atagen2026-10-22 12:30 UTC352
#[derive(Clone)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC353
pub enum State {
7ff8adafe9e4atagen2026-10-22 12:30 UTC354
    /// The state changes between the previous sync and the start of the
7ff8adafe9e4atagen2026-10-22 12:30 UTC355
    /// timeline.
7ff8adafe9e4atagen2026-10-22 12:30 UTC356
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC357
    /// To get the full list of state changes since the previous sync, the state
7ff8adafe9e4atagen2026-10-22 12:30 UTC358
    /// events in [`Timeline`] must be added to these events to update the local
7ff8adafe9e4atagen2026-10-22 12:30 UTC359
    /// state.
7ff8adafe9e4atagen2026-10-22 12:30 UTC360
    Before(Vec<Raw<AnySyncStateEvent>>),
7ff8adafe9e4atagen2026-10-22 12:30 UTC361
7ff8adafe9e4atagen2026-10-22 12:30 UTC362
    /// The state changes between the previous sync and the end of the timeline.
7ff8adafe9e4atagen2026-10-22 12:30 UTC363
    ///
7ff8adafe9e4atagen2026-10-22 12:30 UTC364
    /// This contains the full list of state changes since the previous sync.
7ff8adafe9e4atagen2026-10-22 12:30 UTC365
    /// State events in [`Timeline`] must be ignored to update the local state.
7ff8adafe9e4atagen2026-10-22 12:30 UTC366
    After(Vec<Raw<AnySyncStateEvent>>),
7ff8adafe9e4atagen2026-10-22 12:30 UTC367
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC368
7ff8adafe9e4atagen2026-10-22 12:30 UTC369
impl Default for State {
7ff8adafe9e4atagen2026-10-22 12:30 UTC370
    fn default() -> Self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC371
        Self::Before(vec![])
7ff8adafe9e4atagen2026-10-22 12:30 UTC372
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC373
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC374
7ff8adafe9e4atagen2026-10-22 12:30 UTC375
#[cfg(not(tarpaulin_include))]
7ff8adafe9e4atagen2026-10-22 12:30 UTC376
impl fmt::Debug for State {
7ff8adafe9e4atagen2026-10-22 12:30 UTC377
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7ff8adafe9e4atagen2026-10-22 12:30 UTC378
        match self {
7ff8adafe9e4atagen2026-10-22 12:30 UTC379
            Self::Before(events) => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC380
                f.debug_tuple("Before").field(&DebugListOfRawEvents(events)).finish()
7ff8adafe9e4atagen2026-10-22 12:30 UTC381
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC382
            Self::After(events) => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC383
                f.debug_tuple("After").field(&DebugListOfRawEvents(events)).finish()
7ff8adafe9e4atagen2026-10-22 12:30 UTC384
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC385
        }
7ff8adafe9e4atagen2026-10-22 12:30 UTC386
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC387
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC388
7ff8adafe9e4atagen2026-10-22 12:30 UTC389
struct DebugInvitedRoomUpdates<'a>(&'a BTreeMap<OwnedRoomId, InvitedRoomUpdate>);
7ff8adafe9e4atagen2026-10-22 12:30 UTC390
7ff8adafe9e4atagen2026-10-22 12:30 UTC391
#[cfg(not(tarpaulin_include))]
7ff8adafe9e4atagen2026-10-22 12:30 UTC392
impl fmt::Debug for DebugInvitedRoomUpdates<'_> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC393
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7ff8adafe9e4atagen2026-10-22 12:30 UTC394
        f.debug_map().entries(self.0.iter().map(|(k, v)| (k, DebugInvitedRoom(v)))).finish()
7ff8adafe9e4atagen2026-10-22 12:30 UTC395
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC396
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC397
7ff8adafe9e4atagen2026-10-22 12:30 UTC398
struct DebugKnockedRoomUpdates<'a>(&'a BTreeMap<OwnedRoomId, KnockedRoomUpdate>);
7ff8adafe9e4atagen2026-10-22 12:30 UTC399
7ff8adafe9e4atagen2026-10-22 12:30 UTC400
#[cfg(not(tarpaulin_include))]
7ff8adafe9e4atagen2026-10-22 12:30 UTC401
impl fmt::Debug for DebugKnockedRoomUpdates<'_> {
7ff8adafe9e4atagen2026-10-22 12:30 UTC402
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7ff8adafe9e4atagen2026-10-22 12:30 UTC403
        f.debug_map().entries(self.0.iter().map(|(k, v)| (k, DebugKnockedRoom(v)))).finish()
7ff8adafe9e4atagen2026-10-22 12:30 UTC404
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC405
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC406
7ff8adafe9e4atagen2026-10-22 12:30 UTC407
/// A notification triggered by a sync response.
7ff8adafe9e4atagen2026-10-22 12:30 UTC408
#[derive(Clone)]
7ff8adafe9e4atagen2026-10-22 12:30 UTC409
pub struct Notification {
7ff8adafe9e4atagen2026-10-22 12:30 UTC410
    /// The actions to perform when the conditions for this rule are met.
7ff8adafe9e4atagen2026-10-22 12:30 UTC411
    pub actions: Vec<Action>,
7ff8adafe9e4atagen2026-10-22 12:30 UTC412
7ff8adafe9e4atagen2026-10-22 12:30 UTC413
    /// The event that triggered the notification.
7ff8adafe9e4atagen2026-10-22 12:30 UTC414
    pub event: RawAnySyncOrStrippedTimelineEvent,
7ff8adafe9e4atagen2026-10-22 12:30 UTC415
}
7ff8adafe9e4atagen2026-10-22 12:30 UTC416
7ff8adafe9e4atagen2026-10-22 12:30 UTC417
#[cfg(not(tarpaulin_include))]
7ff8adafe9e4atagen2026-10-22 12:30 UTC418
impl fmt::Debug for Notification {
7ff8adafe9e4atagen2026-10-22 12:30 UTC419
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
7ff8adafe9e4atagen2026-10-22 12:30 UTC420
        let event_debug = match &self.event {
7ff8adafe9e4atagen2026-10-22 12:30 UTC421
            RawAnySyncOrStrippedTimelineEvent::Sync(ev) => DebugRawEvent(ev),
7ff8adafe9e4atagen2026-10-22 12:30 UTC422
            RawAnySyncOrStrippedTimelineEvent::Stripped(ev) => {
7ff8adafe9e4atagen2026-10-22 12:30 UTC423
                DebugRawEvent(ev.cast_ref_unchecked())
7ff8adafe9e4atagen2026-10-22 12:30 UTC424
            }
7ff8adafe9e4atagen2026-10-22 12:30 UTC425
        };
7ff8adafe9e4atagen2026-10-22 12:30 UTC426
7ff8adafe9e4atagen2026-10-22 12:30 UTC427
        f.debug_struct("Notification")
7ff8adafe9e4atagen2026-10-22 12:30 UTC428
            .field("actions", &self.actions)
7ff8adafe9e4atagen2026-10-22 12:30 UTC429
            .field("event", &event_debug)
7ff8adafe9e4atagen2026-10-22 12:30 UTC430
            .finish()
7ff8adafe9e4atagen2026-10-22 12:30 UTC431
    }
7ff8adafe9e4atagen2026-10-22 12:30 UTC432
}