1
0
Fork 0

feat: process more chat event types

This commit is contained in:
əlemi 2025-01-13 22:42:01 +01:00
parent c6f9d34490
commit ddcbbf274e
Signed by: alemi
GPG key ID: A4895B84D311642C
3 changed files with 49 additions and 18 deletions

View file

@ -20,7 +20,7 @@ impl History {
fn down(&mut self, x: u16) { fn down(&mut self, x: u16) {
if self.count < self.height { return }; if self.count < self.height { return };
let delta = self.count - self.height; let delta = self.count - (self.height/2);
if self.offset >= delta { return } if self.offset >= delta { return }
self.offset += std::cmp::min(x, delta - self.offset); self.offset += std::cmp::min(x, delta - self.offset);
} }
@ -103,12 +103,17 @@ pub async fn run<T: ratatui::backend::Backend>(term: &mut Terminal<T>, args: cra
let tl_input_len = ((tl_input.len() as u16 + 3) / history.width) + 1; let tl_input_len = ((tl_input.len() as u16 + 3) / history.width) + 1;
let tl_header = args.server.clone(); let tl_header = args.server.clone();
// TODO only render bottom lines // TODO only render bottom lines
let tl_text = history let mut tl_text_vec = history
.lines .lines
.iter() .iter()
.map(|x| format!("{x}")) .map(|x| format!("{x}"))
.collect::<Vec<String>>() .collect::<Vec<String>>();
.join("\n");
// two empty lines because my math is wrong and im lazy rn
tl_text_vec.push("".to_string());
tl_text_vec.push("".to_string());
let tl_text = tl_text_vec.join("\n");
term.draw(|frame| { term.draw(|frame| {
let layout = Layout::default() let layout = Layout::default()

View file

@ -27,16 +27,20 @@ pub enum ChatLine {
body: String, body: String,
}, },
Error(String), Error(String),
Rename(String, String),
Join(String), Join(String),
Leave(String), Leave(String),
Connect(String), Connect(String),
Raw(String),
} }
impl Display for ChatEvent { impl Display for ChatEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let time = self.0.format("%H:%M:%S"); let time = self.0.format("%H:%M:%S");
match &self.1 { match &self.1 {
ChatLine::Raw(s) => write!(f, "{time} {s}"),
ChatLine::Error(err) => write!(f, "{time} /!\\ {err}"), ChatLine::Error(err) => write!(f, "{time} /!\\ {err}"),
ChatLine::Rename(before, after) => write!(f, "{time} user <{before}> renamed to <{after}>"),
ChatLine::Join(user) => write!(f, "{time} [{user} joined]"), ChatLine::Join(user) => write!(f, "{time} [{user} joined]"),
ChatLine::Leave(user) => write!(f, "{time} [{user} left]"), ChatLine::Leave(user) => write!(f, "{time} [{user} left]"),
ChatLine::Connect(user) => write!(f, "{time} [{user} connected]"), ChatLine::Connect(user) => write!(f, "{time} [{user} connected]"),
@ -110,16 +114,23 @@ impl Chat {
Message::Ping(_) | tokio_tungstenite::tungstenite::Message::Pong(_) => {}, // ignore Message::Ping(_) | tokio_tungstenite::tungstenite::Message::Pong(_) => {}, // ignore
Message::Text(payload) => for line in payload.lines() { Message::Text(payload) => for line in payload.lines() {
match serde_json::from_str::<Event>(line) { match serde_json::from_str::<Event>(line) {
Err(e) => chan.send(ChatEvent(chrono::Utc::now(), ChatLine::Error(format!("failed parsing message: {e}"))))?, Err(e) => {
chan.send(ChatEvent(chrono::Utc::now(), ChatLine::Error(format!("failed parsing message: {e}"))))?;
chan.send(ChatEvent(chrono::Utc::now(), ChatLine::Raw(line.to_string())))?;
},
Ok(event) => match event.inner { Ok(event) => match event.inner {
EventInner::Chat { body, visible: _ } => EventInner::Chat { body, user, visible } =>
chan.send(ChatEvent(event.timestamp, ChatLine::Message { user: event.user.display_name, body }))?, chan.send(ChatEvent(event.timestamp, if visible { ChatLine::Message { user: user.display_name, body } } else { ChatLine::Raw("| REDACTED |".into()) }))?,
EventInner::ConnectedUserInfo => EventInner::ConnectedUserInfo { user } =>
chan.send(ChatEvent(event.timestamp, ChatLine::Connect(event.user.display_name)))?, chan.send(ChatEvent(event.timestamp, ChatLine::Connect(user.display_name)))?,
EventInner::UserJoined => EventInner::UserJoined { user } =>
chan.send(ChatEvent(event.timestamp, ChatLine::Join(event.user.display_name)))?, chan.send(ChatEvent(event.timestamp, ChatLine::Join(user.display_name)))?,
EventInner::UserParted => EventInner::UserParted { user } =>
chan.send(ChatEvent(event.timestamp, ChatLine::Leave(event.user.display_name)))?, chan.send(ChatEvent(event.timestamp, ChatLine::Leave(user.display_name)))?,
EventInner::NameChange { old_name, user } =>
chan.send(ChatEvent(event.timestamp, ChatLine::Rename(old_name, user.display_name)))?,
EventInner::ChatAction { body } =>
chan.send(ChatEvent(event.timestamp, ChatLine::Raw(body)))?,
} }
} }
}, },

View file

@ -33,26 +33,41 @@ pub mod ws {
pub struct Event { pub struct Event {
pub id: String, pub id: String,
pub timestamp: chrono::DateTime<chrono::Utc>, pub timestamp: chrono::DateTime<chrono::Utc>,
pub user: User,
#[serde(flatten)] #[serde(flatten)]
pub inner: EventInner, pub inner: EventInner,
} }
// TODO can i avoid repeating id,timestamp,user in each msg type?? // TODO can i avoid repeating id,timestamp,user in each msg type??
#[derive(Debug, serde::Deserialize)] #[derive(Debug, serde::Deserialize)]
#[serde(tag = "type")] #[serde(tag = "type", rename_all = "camelCase")]
pub enum EventInner { pub enum EventInner {
#[serde(rename = "CHAT")] #[serde(rename = "CHAT")]
Chat { Chat {
body: String, body: String,
visible: bool, visible: bool,
user: User,
}, },
#[serde(rename = "CONNECTED_USER_INFO")] #[serde(rename = "CONNECTED_USER_INFO")]
ConnectedUserInfo, ConnectedUserInfo {
user: User,
},
#[serde(rename = "USER_JOINED")] #[serde(rename = "USER_JOINED")]
UserJoined, UserJoined {
user: User,
},
#[serde(rename = "USER_PARTED")] #[serde(rename = "USER_PARTED")]
UserParted, UserParted {
user: User,
},
#[serde(rename = "NAME_CHANGE")]
NameChange {
old_name: String,
user: User,
},
#[serde(rename = "CHAT_ACTION")]
ChatAction {
body: String,
}
} }
#[derive(Debug, serde::Deserialize)] #[derive(Debug, serde::Deserialize)]