Port message sending

This commit is contained in:
Joscha 2022-07-20 20:37:31 +02:00
parent 98f51a5a2e
commit 066ea0cb07
4 changed files with 122 additions and 92 deletions

View file

@ -1,8 +1,12 @@
mod tree; mod tree;
use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use crossterm::event::KeyEvent; use crossterm::event::KeyEvent;
use parking_lot::FairMutex;
use toss::frame::{Frame, Size}; use toss::frame::{Frame, Size};
use toss::terminal::Terminal;
use crate::store::{Msg, MsgStore}; use crate::store::{Msg, MsgStore};
@ -55,26 +59,20 @@ impl<M: Msg, S: MsgStore<M>> ChatState<M, S> {
} }
} }
// pub async fn handle_messaging( pub async fn handle_messaging(
// &mut self, &mut self,
// terminal: &mut Terminal, terminal: &mut Terminal,
// crossterm_lock: &Arc<FairMutex<()>>, crossterm_lock: &Arc<FairMutex<()>>,
// event: KeyEvent, event: KeyEvent,
// ) -> Option<(Option<M::Id>, String)> { ) -> Option<(Option<M::Id>, String)> {
// match self.mode { match self.mode {
// Mode::Tree => { Mode::Tree => {
// self.tree self.tree
// .handle_messaging( .handle_messaging(terminal, crossterm_lock, event)
// &mut self.store, .await
// &mut self.cursor, }
// terminal, }
// crossterm_lock, }
// event,
// )
// .await
// }
// }
// }
} }
//////////// ////////////

View file

@ -1,4 +1,4 @@
// mod action; mod action;
mod blocks; mod blocks;
mod cursor; mod cursor;
mod layout; mod layout;
@ -9,8 +9,10 @@ use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use crossterm::event::{KeyCode, KeyEvent}; use crossterm::event::{KeyCode, KeyEvent};
use parking_lot::FairMutex;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use toss::frame::{Frame, Size}; use toss::frame::{Frame, Size};
use toss::terminal::Terminal;
use crate::store::{Msg, MsgStore}; use crate::store::{Msg, MsgStore};
use crate::ui::widgets::Widget; use crate::ui::widgets::Widget;
@ -55,6 +57,22 @@ impl<M: Msg, S: MsgStore<M>> InnerTreeViewState<M, S> {
_ => {} _ => {}
} }
} }
async fn handle_messaging(
&self,
terminal: &mut Terminal,
crossterm_lock: &Arc<FairMutex<()>>,
event: KeyEvent,
) -> Option<(Option<M::Id>, String)> {
match event.code {
KeyCode::Char('r') => self.reply_normal(terminal, crossterm_lock).await,
KeyCode::Char('R') => self.reply_alternate(terminal, crossterm_lock).await,
KeyCode::Char('t') | KeyCode::Char('T') => {
Self::create_new_thread(terminal, crossterm_lock)
}
_ => None,
}
}
} }
pub struct TreeViewState<M: Msg, S: MsgStore<M>>(Arc<Mutex<InnerTreeViewState<M, S>>>); pub struct TreeViewState<M: Msg, S: MsgStore<M>>(Arc<Mutex<InnerTreeViewState<M, S>>>);
@ -71,6 +89,19 @@ impl<M: Msg, S: MsgStore<M>> TreeViewState<M, S> {
pub async fn handle_navigation(&mut self, event: KeyEvent) { pub async fn handle_navigation(&mut self, event: KeyEvent) {
self.0.lock().await.handle_navigation(event).await; self.0.lock().await.handle_navigation(event).await;
} }
pub async fn handle_messaging(
&self,
terminal: &mut Terminal,
crossterm_lock: &Arc<FairMutex<()>>,
event: KeyEvent,
) -> Option<(Option<M::Id>, String)> {
self.0
.lock()
.await
.handle_messaging(terminal, crossterm_lock, event)
.await
}
} }
//////////// ////////////

View file

@ -4,42 +4,33 @@ use parking_lot::FairMutex;
use toss::terminal::Terminal; use toss::terminal::Terminal;
use crate::store::{Msg, MsgStore}; use crate::store::{Msg, MsgStore};
use crate::ui::util;
use super::{Cursor, TreeView}; use super::{Cursor, InnerTreeViewState};
impl<M: Msg> TreeView<M> { impl<M: Msg, S: MsgStore<M>> InnerTreeViewState<M, S> {
fn prompt_msg(crossterm_lock: &Arc<FairMutex<()>>, terminal: &mut Terminal) -> Option<String> { pub async fn reply_normal(
let content = { &self,
let _guard = crossterm_lock.lock();
terminal.suspend().expect("could not suspend");
let content = edit::edit("").expect("could not edit");
terminal.unsuspend().expect("could not unsuspend");
content
};
if content.trim().is_empty() {
None
} else {
Some(content)
}
}
pub async fn reply_normal<S: MsgStore<M>>(
store: &S,
cursor: &Option<Cursor<M::Id>>,
terminal: &mut Terminal, terminal: &mut Terminal,
crossterm_lock: &Arc<FairMutex<()>>, crossterm_lock: &Arc<FairMutex<()>>,
) -> Option<(Option<M::Id>, String)> { ) -> Option<(Option<M::Id>, String)> {
if let Some(cursor) = cursor { match &self.cursor {
let tree = store.tree(store.path(&cursor.id).await.first()).await; Cursor::Bottom => {
let parent_id = if tree.next_sibling(&cursor.id).is_some() { if let Some(content) = util::prompt(terminal, crossterm_lock) {
return Some((None, content));
}
}
Cursor::Msg(msg) => {
let path = self.store.path(msg).await;
let tree = self.store.tree(path.first()).await;
let parent_id = if tree.next_sibling(msg).is_some() {
// A reply to a message that has further siblings should be a // A reply to a message that has further siblings should be a
// direct reply. An indirect reply might end up a lot further // direct reply. An indirect reply might end up a lot further
// down in the current conversation. // down in the current conversation.
cursor.id.clone() msg.clone()
} else if let Some(parent) = tree.parent(&cursor.id) { } else if let Some(parent) = tree.parent(msg) {
// A reply to a message without further siblings should be an // A reply to a message without younger siblings should be
// indirect reply so as not to create unnecessarily deep // an indirect reply so as not to create unnecessarily deep
// threads. In the case that our message has children, this // threads. In the case that our message has children, this
// might get a bit confusing. I'm not sure yet how well this // might get a bit confusing. I'm not sure yet how well this
// "smart" reply actually works in practice. // "smart" reply actually works in practice.
@ -47,50 +38,60 @@ impl<M: Msg> TreeView<M> {
} else { } else {
// When replying to a top-level message, it makes sense to avoid // When replying to a top-level message, it makes sense to avoid
// creating unnecessary new threads. // creating unnecessary new threads.
cursor.id.clone() msg.clone()
}; };
if let Some(content) = Self::prompt_msg(crossterm_lock, terminal) { if let Some(content) = util::prompt(terminal, crossterm_lock) {
return Some((Some(parent_id), content)); return Some((Some(parent_id), content));
} }
} }
_ => {}
}
None None
} }
/// Does approximately the opposite of [`Self::reply_normal`]. /// Does approximately the opposite of [`Self::reply_normal`].
pub async fn reply_alternate<S: MsgStore<M>>( pub async fn reply_alternate(
store: &S, &self,
cursor: &Option<Cursor<M::Id>>,
terminal: &mut Terminal, terminal: &mut Terminal,
crossterm_lock: &Arc<FairMutex<()>>, crossterm_lock: &Arc<FairMutex<()>>,
) -> Option<(Option<M::Id>, String)> { ) -> Option<(Option<M::Id>, String)> {
if let Some(cursor) = cursor { match &self.cursor {
let tree = store.tree(store.path(&cursor.id).await.first()).await; Cursor::Bottom => {
let parent_id = if tree.next_sibling(&cursor.id).is_none() { if let Some(content) = util::prompt(terminal, crossterm_lock) {
return Some((None, content));
}
}
Cursor::Msg(msg) => {
let path = self.store.path(msg).await;
let tree = self.store.tree(path.first()).await;
let parent_id = if tree.next_sibling(msg).is_none() {
// The opposite of replying normally // The opposite of replying normally
cursor.id.clone() msg.clone()
} else if let Some(parent) = tree.parent(&cursor.id) { } else if let Some(parent) = tree.parent(msg) {
// The opposite of replying normally // The opposite of replying normally
parent parent
} else { } else {
// The same as replying normally, still to avoid creating // The same as replying normally, still to avoid creating
// unnecessary new threads // unnecessary new threads
cursor.id.clone() msg.clone()
}; };
if let Some(content) = Self::prompt_msg(crossterm_lock, terminal) { if let Some(content) = util::prompt(terminal, crossterm_lock) {
return Some((Some(parent_id), content)); return Some((Some(parent_id), content));
} }
} }
_ => {}
}
None None
} }
pub async fn create_new_thread( pub fn create_new_thread(
terminal: &mut Terminal, terminal: &mut Terminal,
crossterm_lock: &Arc<FairMutex<()>>, crossterm_lock: &Arc<FairMutex<()>>,
) -> Option<(Option<M::Id>, String)> { ) -> Option<(Option<M::Id>, String)> {
Self::prompt_msg(crossterm_lock, terminal).map(|c| (None, c)) util::prompt(terminal, crossterm_lock).map(|content| (None, content))
} }
} }

View file

@ -304,13 +304,13 @@ impl EuphRoom {
} }
} }
// if let Some((parent, content)) = self let potential_message = self
// .chat .chat
// .handle_messaging(terminal, crossterm_lock, event) .handle_messaging(terminal, crossterm_lock, event)
// .await .await;
// { if let Some((parent, content)) = potential_message {
// let _ = room.send(parent, content); let _ = room.send(parent, content);
// } }
} }
} }
} }