matrix_sdk_ui/
events.rs

1// Copyright 2023 The Matrix.org Foundation C.I.C.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use ruma::{
16    events::{
17        EventContent, EventContentFromType, MessageLikeEventContent, MessageLikeEventType,
18        MessageLikeUnsigned, OriginalSyncMessageLikeEvent, OriginalSyncStateEvent,
19        PossiblyRedactedStateEventContent, RedactContent, RedactedMessageLikeEventContent,
20        RedactedStateEventContent, RedactedSyncMessageLikeEvent, RedactedSyncStateEvent,
21        StateEventContent, StateEventType, StaticStateEventContent, TimelineEventType,
22    },
23    serde::from_raw_json_value,
24    EventId, MilliSecondsSinceUnixEpoch, TransactionId, UserId,
25};
26use serde::{de, Deserialize, Serialize};
27use serde_json::value::RawValue as RawJsonValue;
28
29#[allow(clippy::large_enum_variant)]
30pub(crate) enum SyncTimelineEventWithoutContent {
31    OriginalMessageLike(OriginalSyncMessageLikeEvent<NoMessageLikeEventContent>),
32    RedactedMessageLike(RedactedSyncMessageLikeEvent<NoMessageLikeEventContent>),
33    OriginalState(OriginalSyncStateEvent<NoStateEventContent>),
34    RedactedState(RedactedSyncStateEvent<NoStateEventContent>),
35}
36
37impl SyncTimelineEventWithoutContent {
38    pub(crate) fn event_id(&self) -> &EventId {
39        match self {
40            Self::OriginalMessageLike(ev) => &ev.event_id,
41            Self::RedactedMessageLike(ev) => &ev.event_id,
42            Self::OriginalState(ev) => &ev.event_id,
43            Self::RedactedState(ev) => &ev.event_id,
44        }
45    }
46
47    pub(crate) fn origin_server_ts(&self) -> MilliSecondsSinceUnixEpoch {
48        match self {
49            SyncTimelineEventWithoutContent::OriginalMessageLike(ev) => ev.origin_server_ts,
50            SyncTimelineEventWithoutContent::RedactedMessageLike(ev) => ev.origin_server_ts,
51            SyncTimelineEventWithoutContent::OriginalState(ev) => ev.origin_server_ts,
52            SyncTimelineEventWithoutContent::RedactedState(ev) => ev.origin_server_ts,
53        }
54    }
55
56    pub(crate) fn sender(&self) -> &UserId {
57        match self {
58            Self::OriginalMessageLike(ev) => &ev.sender,
59            Self::RedactedMessageLike(ev) => &ev.sender,
60            Self::OriginalState(ev) => &ev.sender,
61            Self::RedactedState(ev) => &ev.sender,
62        }
63    }
64
65    pub(crate) fn transaction_id(&self) -> Option<&TransactionId> {
66        match self {
67            SyncTimelineEventWithoutContent::OriginalMessageLike(ev) => {
68                ev.unsigned.transaction_id.as_deref()
69            }
70            SyncTimelineEventWithoutContent::OriginalState(ev) => {
71                ev.unsigned.transaction_id.as_deref()
72            }
73            SyncTimelineEventWithoutContent::RedactedMessageLike(_)
74            | SyncTimelineEventWithoutContent::RedactedState(_) => None,
75        }
76    }
77
78    pub(crate) fn event_type(&self) -> TimelineEventType {
79        match self {
80            SyncTimelineEventWithoutContent::OriginalMessageLike(ev) => {
81                ev.content.event_type().into()
82            }
83            SyncTimelineEventWithoutContent::RedactedMessageLike(ev) => {
84                ev.content.event_type().into()
85            }
86            SyncTimelineEventWithoutContent::OriginalState(ev) => ev.content.event_type().into(),
87            SyncTimelineEventWithoutContent::RedactedState(ev) => ev.content.event_type().into(),
88        }
89    }
90}
91
92#[derive(Deserialize)]
93struct EventDeHelper {
94    state_key: Option<de::IgnoredAny>,
95    #[serde(default)]
96    unsigned: UnsignedDeHelper,
97}
98
99#[derive(Deserialize, Default)]
100struct UnsignedDeHelper {
101    redacted_because: Option<de::IgnoredAny>,
102}
103
104impl<'de> Deserialize<'de> for SyncTimelineEventWithoutContent {
105    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
106    where
107        D: de::Deserializer<'de>,
108    {
109        let json = Box::<RawJsonValue>::deserialize(deserializer)?;
110        let EventDeHelper { state_key, unsigned } = from_raw_json_value(&json)?;
111
112        Ok(match (state_key.is_some(), unsigned.redacted_because.is_some()) {
113            (false, false) => Self::OriginalMessageLike(from_raw_json_value(&json)?),
114            (false, true) => Self::RedactedMessageLike(from_raw_json_value(&json)?),
115            (true, false) => Self::OriginalState(from_raw_json_value(&json)?),
116            (true, true) => Self::RedactedState(from_raw_json_value(&json)?),
117        })
118    }
119}
120
121#[derive(Clone, Debug, Serialize)]
122pub(crate) struct NoMessageLikeEventContent {
123    #[serde(skip)]
124    pub event_type: MessageLikeEventType,
125}
126
127impl EventContent for NoMessageLikeEventContent {
128    type EventType = MessageLikeEventType;
129
130    fn event_type(&self) -> Self::EventType {
131        self.event_type.clone()
132    }
133}
134impl EventContentFromType for NoMessageLikeEventContent {
135    fn from_parts(event_type: &str, _content: &RawJsonValue) -> serde_json::Result<Self> {
136        Ok(Self { event_type: event_type.into() })
137    }
138}
139impl MessageLikeEventContent for NoMessageLikeEventContent {}
140impl RedactedMessageLikeEventContent for NoMessageLikeEventContent {}
141
142#[derive(Clone, Debug, Serialize)]
143pub(crate) struct NoStateEventContent {
144    #[serde(skip)]
145    pub event_type: StateEventType,
146}
147
148impl EventContent for NoStateEventContent {
149    type EventType = StateEventType;
150
151    fn event_type(&self) -> Self::EventType {
152        self.event_type.clone()
153    }
154}
155impl EventContentFromType for NoStateEventContent {
156    fn from_parts(event_type: &str, _content: &RawJsonValue) -> serde_json::Result<Self> {
157        Ok(Self { event_type: event_type.into() })
158    }
159}
160impl RedactContent for NoStateEventContent {
161    type Redacted = Self;
162
163    fn redact(self, _version: &ruma::RoomVersionId) -> Self::Redacted {
164        self
165    }
166}
167impl StateEventContent for NoStateEventContent {
168    type StateKey = String;
169}
170impl StaticStateEventContent for NoStateEventContent {
171    // We don't care about the `prev_content` since it won't deserialize with useful
172    // data. Use this type which is `StateUnsigned` minus the `prev_content`
173    // field.
174    type Unsigned = MessageLikeUnsigned<NoMessageLikeEventContent>;
175    type PossiblyRedacted = Self;
176}
177impl RedactedStateEventContent for NoStateEventContent {
178    type StateKey = String;
179}
180impl PossiblyRedactedStateEventContent for NoStateEventContent {
181    type StateKey = String;
182}