Support sending and displaying message reactions (#2)

This commit is contained in:
Ulyssa 2023-02-09 17:53:33 -08:00
parent 3629f15e0d
commit c9c547acc1
No known key found for this signature in database
GPG key ID: 1B3965A3D18B9B64
10 changed files with 368 additions and 63 deletions

View file

@ -9,8 +9,9 @@ use tokio;
use matrix_sdk::{
attachment::AttachmentConfig,
media::{MediaFormat, MediaRequest},
room::Room as MatrixRoom,
room::{Joined, Room as MatrixRoom},
ruma::{
events::reaction::{ReactionEventContent, Relation as Reaction},
events::room::message::{
MessageType,
OriginalRoomMessageEvent,
@ -19,6 +20,7 @@ use matrix_sdk::{
RoomMessageEventContent,
TextMessageEventContent,
},
EventId,
OwnedRoomId,
RoomId,
},
@ -73,6 +75,7 @@ use crate::base::{
};
use crate::message::{Message, MessageEvent, MessageKey, MessageTimeStamp};
use crate::worker::Requester;
use super::scrollback::{Scrollback, ScrollbackState};
@ -115,6 +118,10 @@ impl ChatState {
}
}
fn get_joined(&self, worker: &Requester) -> Result<Joined, IambError> {
worker.client.get_joined_room(self.id()).ok_or(IambError::NotJoined)
}
fn get_reply_to<'a>(&self, info: &'a RoomInfo) -> Option<&'a OriginalRoomMessageEvent> {
let key = self.reply_to.as_ref()?;
let msg = info.messages.get(key)?;
@ -149,7 +156,10 @@ impl ChatState {
let settings = &store.application.settings;
let info = store.application.rooms.entry(self.room_id.clone()).or_default();
let msg = self.scrollback.get_mut(info).ok_or(IambError::NoSelectedMessage)?;
let msg = self
.scrollback
.get_mut(&mut info.messages)
.ok_or(IambError::NoSelectedMessage)?;
match act {
MessageAction::Cancel => {
@ -282,19 +292,32 @@ impl ChatState {
Ok(None)
},
MessageAction::Redact(reason) => {
let room = store
.application
.worker
.client
.get_joined_room(self.id())
.ok_or(IambError::NotJoined)?;
MessageAction::React(emoji) => {
let room = self.get_joined(&store.application.worker)?;
let event_id = match &msg.event {
MessageEvent::Original(ev) => ev.event_id.clone(),
MessageEvent::Local(event_id, _) => event_id.clone(),
MessageEvent::Redacted(_) => {
let msg = "";
let msg = "Cannot react to a redacted message";
let err = UIError::Failure(msg.into());
return Err(err);
},
};
let reaction = Reaction::new(event_id, emoji);
let msg = ReactionEventContent::new(reaction);
let _ = room.send(msg, None).await.map_err(IambError::from)?;
Ok(None)
},
MessageAction::Redact(reason) => {
let room = self.get_joined(&store.application.worker)?;
let event_id = match &msg.event {
MessageEvent::Original(ev) => ev.event_id.clone(),
MessageEvent::Local(event_id, _) => event_id.clone(),
MessageEvent::Redacted(_) => {
let msg = "Cannot redact already redacted message";
let err = UIError::Failure(msg.into());
return Err(err);
@ -311,6 +334,46 @@ impl ChatState {
self.reply_to = self.scrollback.get_key(info);
self.focus = RoomFocus::MessageBar;
Ok(None)
},
MessageAction::Unreact(emoji) => {
let room = self.get_joined(&store.application.worker)?;
let event_id: &EventId = match &msg.event {
MessageEvent::Original(ev) => ev.event_id.as_ref(),
MessageEvent::Local(event_id, _) => event_id.as_ref(),
MessageEvent::Redacted(_) => {
let msg = "Cannot unreact to a redacted message";
let err = UIError::Failure(msg.into());
return Err(err);
},
};
let reactions = match info.reactions.get(event_id) {
Some(r) => r,
None => return Ok(None),
};
let reactions = reactions.iter().filter_map(|(event_id, (reaction, user_id))| {
if user_id != &settings.profile.user_id {
return None;
}
if let Some(emoji) = &emoji {
if emoji == reaction {
return Some(event_id);
} else {
return None;
}
} else {
return Some(event_id);
}
});
for reaction in reactions {
let _ = room.redact(reaction, None, None).await.map_err(IambError::from)?;
}
Ok(None)
},
}

View file

@ -62,7 +62,7 @@ use modalkit::editing::{
use crate::{
base::{IambBufferId, IambInfo, ProgramContext, ProgramStore, RoomFocus, RoomInfo},
config::ApplicationSettings,
message::{Message, MessageCursor, MessageKey},
message::{Message, MessageCursor, MessageKey, Messages},
};
fn nth_key_before(pos: MessageKey, n: usize, info: &RoomInfo) -> MessageKey {
@ -164,11 +164,11 @@ impl ScrollbackState {
.or_else(|| info.messages.last_key_value().map(|kv| kv.0.clone()))
}
pub fn get_mut<'a>(&mut self, info: &'a mut RoomInfo) -> Option<&'a mut Message> {
pub fn get_mut<'a>(&mut self, messages: &'a mut Messages) -> Option<&'a mut Message> {
if let Some(k) = &self.cursor.timestamp {
info.messages.get_mut(k)
messages.get_mut(k)
} else {
info.messages.last_entry().map(|o| o.into_mut())
messages.last_entry().map(|o| o.into_mut())
}
}