From cfcc6631699dd398d32857d400e0edf437864b13 Mon Sep 17 00:00:00 2001 From: Joscha Date: Tue, 2 Aug 2022 21:43:30 +0200 Subject: [PATCH] Remove pseudo message after server replied --- src/euph/room.rs | 25 +++++++++++++++++++------ src/ui/chat.rs | 11 +++++++++++ src/ui/chat/tree.rs | 18 ++++++++++++++++++ src/ui/room.rs | 38 ++++++++++++++++++++++++++++++++------ src/ui/widgets/editor.rs | 4 ++++ 5 files changed, 84 insertions(+), 12 deletions(-) diff --git a/src/euph/room.rs b/src/euph/room.rs index fac1659..e183d99 100644 --- a/src/euph/room.rs +++ b/src/euph/room.rs @@ -36,7 +36,7 @@ enum Event { Status(oneshot::Sender>), RequestLogs, Nick(String), - Send(Option, String), + Send(Option, String, oneshot::Sender), } #[derive(Debug)] @@ -164,7 +164,7 @@ impl State { Event::Status(reply_tx) => self.on_status(reply_tx).await, Event::RequestLogs => self.on_request_logs(), Event::Nick(name) => self.on_nick(name), - Event::Send(parent, content) => self.on_send(parent, content), + Event::Send(parent, content, id_tx) => self.on_send(parent, content, id_tx), } } Ok(()) @@ -291,11 +291,18 @@ impl State { } } - fn on_send(&self, parent: Option, content: String) { + fn on_send( + &self, + parent: Option, + content: String, + id_tx: oneshot::Sender, + ) { if let Some(conn_tx) = &self.conn_tx { let conn_tx = conn_tx.clone(); task::spawn(async move { - let _ = conn_tx.send(Send { content, parent }).await; + if let Ok(reply) = conn_tx.send(Send { content, parent }).await { + let _ = id_tx.send(reply.0.id); + } }); } } @@ -348,9 +355,15 @@ impl Room { .map_err(|_| Error::Stopped) } - pub fn send(&self, parent: Option, content: String) -> Result<(), Error> { + pub fn send( + &self, + parent: Option, + content: String, + ) -> Result, Error> { + let (id_tx, id_rx) = oneshot::channel(); self.event_tx - .send(Event::Send(parent, content)) + .send(Event::Send(parent, content, id_tx)) + .map(|_| id_rx) .map_err(|_| Error::Stopped) } } diff --git a/src/ui/chat.rs b/src/ui/chat.rs index 90448d2..b841a02 100644 --- a/src/ui/chat.rs +++ b/src/ui/chat.rs @@ -99,6 +99,17 @@ impl> ChatState { } } } + + /// A [`Reaction::Composed`] message was sent, either successfully or + /// unsuccessfully. + /// + /// If successful, include the message's id as an argument. If unsuccessful, + /// instead pass a `None`. + pub async fn sent(&mut self, id: Option) { + match self.mode { + Mode::Tree => self.tree.sent(id).await, + } + } } //////////// diff --git a/src/ui/chat/tree.rs b/src/ui/chat/tree.rs index edac567..95ae013 100644 --- a/src/ui/chat/tree.rs +++ b/src/ui/chat/tree.rs @@ -258,6 +258,20 @@ impl> InnerTreeViewState { } } } + + fn sent(&mut self, id: Option) { + if let Cursor::Pseudo { coming_from, .. } = &self.cursor { + if let Some(id) = id { + self.cursor = Cursor::Msg(id); + self.editor.clear(); + } else { + self.cursor = match coming_from { + Some(id) => Cursor::Msg(id.clone()), + None => Cursor::Bottom, + }; + }; + } + } } pub struct TreeViewState>(Arc>>); @@ -287,6 +301,10 @@ impl> TreeViewState { .handle_key_event(terminal, crossterm_lock, event, can_compose) .await } + + pub async fn sent(&mut self, id: Option) { + self.0.lock().await.sent(id) + } } //////////// diff --git a/src/ui/room.rs b/src/ui/room.rs index ba7a776..9274177 100644 --- a/src/ui/room.rs +++ b/src/ui/room.rs @@ -4,11 +4,12 @@ use std::sync::Arc; use crossterm::event::{KeyCode, KeyEvent}; use crossterm::style::{Color, ContentStyle, Stylize}; use parking_lot::FairMutex; -use tokio::sync::mpsc; +use tokio::sync::oneshot::error::TryRecvError; +use tokio::sync::{mpsc, oneshot}; use toss::styled::Styled; use toss::terminal::Terminal; -use crate::euph::api::{SessionType, SessionView}; +use crate::euph::api::{SessionType, SessionView, Snowflake}; use crate::euph::{self, Joined, Status}; use crate::vault::EuphVault; @@ -34,10 +35,13 @@ enum State { pub struct EuphRoom { ui_event_tx: mpsc::UnboundedSender, + room: Option, + state: State, - room: Option, chat: ChatState, + last_msg_sent: Option>, + nick_list: ListState, } @@ -45,9 +49,10 @@ impl EuphRoom { pub fn new(vault: EuphVault, ui_event_tx: mpsc::UnboundedSender) -> Self { Self { ui_event_tx, - state: State::Normal, room: None, + state: State::Normal, chat: ChatState::new(vault), + last_msg_sent: None, nick_list: ListState::new(), } } @@ -85,7 +90,25 @@ impl EuphRoom { } } - pub async fn widget(&self) -> BoxedWidget { + async fn stabilize_pseudo_msg(&mut self) { + if let Some(id_rx) = &mut self.last_msg_sent { + match id_rx.try_recv() { + Ok(id) => { + self.chat.sent(Some(id)).await; + self.last_msg_sent = None; + } + Err(TryRecvError::Empty) => {} // Wait a bit longer + Err(TryRecvError::Closed) => { + self.chat.sent(None).await; + self.last_msg_sent = None; + } + } + } + } + + pub async fn widget(&mut self) -> BoxedWidget { + self.stabilize_pseudo_msg().await; + let status = self.status().await; let chat = match &status { Some(Some(Status::Joined(joined))) => self.widget_with_nick_list(&status, joined), @@ -295,7 +318,10 @@ impl EuphRoom { Reaction::NotHandled => {} Reaction::Handled => return true, Reaction::Composed { parent, content } => { - let _ = room.send(parent, content); + match room.send(parent, content) { + Ok(id_rx) => self.last_msg_sent = Some(id_rx), + Err(_) => self.chat.sent(None).await, + } return true; } } diff --git a/src/ui/widgets/editor.rs b/src/ui/widgets/editor.rs index 8a756b5..2a555cf 100644 --- a/src/ui/widgets/editor.rs +++ b/src/ui/widgets/editor.rs @@ -214,6 +214,10 @@ impl EditorState { self.0.lock().set_text(text); } + pub fn clear(&self) { + self.set_text(String::new()); + } + pub fn insert_char(&self, ch: char) { self.0.lock().insert_char(ch); }