Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 59 additions & 4 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::time::{Duration, Instant};

use emojis::Emoji;
use matrix_sdk::ruma::events::receipt::ReceiptThread;
use matrix_sdk::ruma::events::sticker::StickerEvent;
use ratatui::{
buffer::Buffer,
layout::{Alignment, Rect},
Expand Down Expand Up @@ -842,14 +843,17 @@ pub enum EventLocation {

/// The [EventId] belongs to a state event in the main timeline of the room.
State(MessageKey),

/// The [EventId] belongs to a sticker event in the main scrollback
Sticker(MessageKey),
}

impl EventLocation {
fn to_message_key(&self) -> Option<&MessageKey> {
if let EventLocation::Message(_, key) = self {
Some(key)
} else {
None
match self {
EventLocation::Message(_, key) => Some(key),
EventLocation::Sticker(key) => Some(key),
_ => None,
}
}
}
Expand Down Expand Up @@ -1057,6 +1061,12 @@ impl RoomInfo {

self.keys.remove(redacts);
},
Some(EventLocation::Sticker(key)) => {
if let Some(msg) = self.messages.get_mut(key) {
let ev = SyncRoomRedactionEvent::Original(ev);
msg.redact(ev, room_version);
}
},
}
}

Expand All @@ -1082,6 +1092,50 @@ impl RoomInfo {
}
}

/// Insert a sticker
pub fn insert_sticker(
&mut self,
room_id: OwnedRoomId,
store: AsyncProgramStore,
picker: Option<Picker>,
sticker: StickerEvent,
settings: &ApplicationSettings,
media: matrix_sdk::Media,
) {
match sticker {
MessageLikeEvent::Original(ref sticker_content) => {
let key =
(sticker_content.origin_server_ts.into(), sticker_content.event_id.clone());

let loc = EventLocation::Sticker(key.clone());

self.keys.insert(sticker_content.event_id.clone(), loc);
self.messages.insert_message(key.clone(), sticker.clone());

if picker.is_some() {
if let (Some(msg), Some(image_preview)) = (
self.get_event_mut(&sticker_content.event_id),
&settings.tunables.image_preview,
) {
msg.image_preview = ImageStatus::Downloading(image_preview.size.clone());
spawn_insert_preview(
store,
room_id,
sticker_content.event_id.clone(),
sticker_content.content.source.clone().into(),
media,
settings.dirs.image_previews.clone(),
)
}
}
},
MessageLikeEvent::Redacted(ref redaction) => {
let key = (redaction.origin_server_ts.into(), redaction.event_id.clone());
self.messages.insert_message(key.clone(), sticker.clone());
},
}
}

/// Insert an edit.
pub fn insert_edit(&mut self, msg: Replacement<RoomMessageEventContentWithoutRelation>) {
let event_id = msg.event_id;
Expand Down Expand Up @@ -1112,6 +1166,7 @@ impl RoomInfo {
},
MessageEvent::Redacted(_) |
MessageEvent::State(_) |
MessageEvent::Sticker(_) |
MessageEvent::EncryptedOriginal(_) |
MessageEvent::EncryptedRedacted(_) => {
return;
Expand Down
46 changes: 46 additions & 0 deletions src/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ use std::ops::{Deref, DerefMut};
use chrono::{DateTime, Local as LocalTz};
use humansize::{format_size, DECIMAL};
use matrix_sdk::ruma::events::receipt::ReceiptThread;
use matrix_sdk::ruma::events::room::message::RoomMessageEventContentWithoutRelation;
use matrix_sdk::ruma::events::sticker::{RedactedStickerEvent, StickerEvent};
use matrix_sdk::ruma::events::MessageLikeEvent;
use serde_json::json;
use unicode_width::UnicodeWidthStr;

Expand Down Expand Up @@ -445,6 +448,7 @@ pub enum MessageEvent {
Original(Box<OriginalRoomMessageEvent>),
Redacted(Box<RedactedRoomMessageEvent>),
State(Box<AnySyncStateEvent>),
Sticker(Box<StickerEvent>),
Local(OwnedEventId, Box<RoomMessageEventContent>),
}

Expand All @@ -456,6 +460,7 @@ impl MessageEvent {
MessageEvent::Original(ev) => ev.event_id.as_ref(),
MessageEvent::Redacted(ev) => ev.event_id.as_ref(),
MessageEvent::State(ev) => ev.event_id(),
MessageEvent::Sticker(ev) => ev.event_id(),
MessageEvent::Local(event_id, _) => event_id.as_ref(),
}
}
Expand All @@ -467,6 +472,7 @@ impl MessageEvent {
MessageEvent::EncryptedRedacted(_) => None,
MessageEvent::Redacted(_) => None,
MessageEvent::State(_) => None,
MessageEvent::Sticker(_) => None,
MessageEvent::Local(_, content) => Some(content),
}
}
Expand All @@ -484,6 +490,7 @@ impl MessageEvent {
MessageEvent::Original(ev) => body_cow_content(&ev.content),
MessageEvent::EncryptedRedacted(ev) => body_cow_reason(&ev.unsigned),
MessageEvent::Redacted(ev) => body_cow_reason(&ev.unsigned),
MessageEvent::Sticker(ev) => body_cow_sticker(ev),
MessageEvent::State(ev) => body_cow_state(ev),
MessageEvent::Local(_, content) => body_cow_content(content),
}
Expand All @@ -496,6 +503,7 @@ impl MessageEvent {
MessageEvent::Original(ev) => &ev.content,
MessageEvent::Redacted(_) => return None,
MessageEvent::State(ev) => return Some(html_state(ev)),
MessageEvent::Sticker(_) => return None,
MessageEvent::Local(_, content) => content,
};

Expand All @@ -517,6 +525,23 @@ impl MessageEvent {
MessageEvent::Redacted(_) => return,
MessageEvent::State(_) => return,
MessageEvent::Local(_, _) => return,
MessageEvent::Sticker(ev) => {
match ev.as_ref() {
MessageLikeEvent::Original(sticker) => {
let redacted = RedactedStickerEvent {
content: sticker.content.clone().redact(version),
event_id: ev.event_id().to_owned(),
sender: ev.sender().to_owned(),
origin_server_ts: ev.origin_server_ts(),
room_id: ev.room_id().to_owned(),
unsigned: redaction_unsigned(redaction),
};
*self =
MessageEvent::Sticker(Box::new(MessageLikeEvent::Redacted(redacted)));
},
MessageLikeEvent::Redacted(_) => {},
}
},
MessageEvent::Original(ev) => {
let redacted = RedactedRoomMessageEvent {
content: ev.content.clone().redact(version),
Expand Down Expand Up @@ -579,6 +604,15 @@ fn body_cow_content(content: &RoomMessageEventContent) -> Cow<'_, str> {
Cow::Borrowed(s)
}

fn body_cow_sticker(content: &StickerEvent) -> Cow<'_, str> {
match content {
MessageLikeEvent::Original(sticker) => {
Cow::Owned(format!("* sent a sticker: {}", sticker.content.body))
},
MessageLikeEvent::Redacted(_) => Cow::Borrowed("[Redacted]"),
}
}

fn body_cow_reason(unsigned: &RedactedUnsigned) -> Cow<'_, str> {
let reason = unsigned.redacted_because.content.reason.as_ref();

Expand Down Expand Up @@ -869,6 +903,7 @@ impl Message {
MessageEvent::Original(ev) => &ev.content,
MessageEvent::Redacted(_) => return None,
MessageEvent::State(_) => return None,
MessageEvent::Sticker(_) => return None,
};

match &content.relates_to {
Expand All @@ -890,6 +925,7 @@ impl Message {
MessageEvent::Original(ev) => &ev.content,
MessageEvent::Redacted(_) => return None,
MessageEvent::State(_) => return None,
MessageEvent::Sticker(_) => return None,
};

match &content.relates_to {
Expand Down Expand Up @@ -1188,6 +1224,16 @@ impl From<AnySyncStateEvent> for Message {
}
}

impl From<StickerEvent> for Message {
fn from(event: StickerEvent) -> Self {
let timestamp = event.origin_server_ts().into();
let user_id = event.sender().to_owned();
let event = MessageEvent::Sticker(event.into());

Message::new(event, user_id, timestamp)
}
}

impl Display for Message {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.event.body())
Expand Down
3 changes: 3 additions & 0 deletions src/windows/room/chat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ impl ChatState {
MessageEvent::Original(ev) => ev.event_id.clone(),
MessageEvent::Local(event_id, _) => event_id.clone(),
MessageEvent::State(ev) => ev.event_id().to_owned(),
MessageEvent::Sticker(ev) => ev.event_id().to_owned(),
MessageEvent::Redacted(_) => {
let msg = "Cannot react to a redacted message";
let err = UIError::Failure(msg.into());
Expand Down Expand Up @@ -428,6 +429,7 @@ impl ChatState {
MessageEvent::Original(ev) => ev.event_id.clone(),
MessageEvent::Local(event_id, _) => event_id.clone(),
MessageEvent::State(ev) => ev.event_id().to_owned(),
MessageEvent::Sticker(ev) => ev.event_id().to_owned(),
MessageEvent::Redacted(_) => {
let msg = "Cannot redact already redacted message";
let err = UIError::Failure(msg.into());
Expand Down Expand Up @@ -476,6 +478,7 @@ impl ChatState {
MessageEvent::Original(ev) => ev.event_id.clone(),
MessageEvent::Local(event_id, _) => event_id.clone(),
MessageEvent::State(ev) => ev.event_id().to_owned(),
MessageEvent::Sticker(ev) => ev.event_id().to_owned(),
MessageEvent::Redacted(_) => {
let msg = "Cannot unreact to a redacted message";
let err = UIError::Failure(msg.into());
Expand Down
43 changes: 43 additions & 0 deletions src/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::time::{Duration, Instant};

use futures::{stream::FuturesUnordered, StreamExt};
use gethostname::gethostname;
use matrix_sdk::ruma::events::sticker::StickerEventContent;
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender};
use tokio::sync::Semaphore;
use tokio::task::JoinHandle;
Expand Down Expand Up @@ -358,6 +359,16 @@ fn load_insert(
AnyTimelineEvent::MessageLike(AnyMessageLikeEvent::Reaction(ev)) => {
info.insert_reaction(ev);
},
AnyTimelineEvent::MessageLike(AnyMessageLikeEvent::Sticker(ev)) => {
info.insert_sticker(
room_id.clone(),
store.clone(),
picker.clone(),
ev,
settings,
client.media(),
);
},
AnyTimelineEvent::MessageLike(_) => {
continue;
},
Expand Down Expand Up @@ -1037,6 +1048,38 @@ impl ClientWorker {
},
);

let _ = self.client.add_event_handler(
|ev: SyncMessageLikeEvent<StickerEventContent>,
room: MatrixRoom,
client: Client,
store: Ctx<AsyncProgramStore>| {
async move {
let room_id = room.room_id();

let mut locked = store.lock().await;

let sender = ev.sender().to_owned();
let _ = locked.application.presences.get_or_default(sender);

let ChatStore { rooms, picker, settings, .. } = &mut locked.application;

let info = rooms.get_or_default(room_id.to_owned());

update_event_receipts(info, &room, ev.event_id()).await;

let full_ev = ev.into_full_event(room_id.to_owned());
info.insert_sticker(
room_id.to_owned(),
store.clone(),
picker.clone(),
full_ev,
settings,
client.media(),
);
}
},
);

let _ = self.client.add_event_handler(
|ev: SyncEphemeralRoomEvent<ReceiptEventContent>,
room: MatrixRoom,
Expand Down