Separate navigation and messaging
This commit is contained in:
parent
416b5bf31e
commit
03dfe10f3e
4 changed files with 53 additions and 51 deletions
|
|
@ -54,28 +54,36 @@ impl<M: Msg, S: MsgStore<M>> Chat<M, S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Handled<I> {
|
|
||||||
Ok,
|
|
||||||
NewMessage { parent: Option<I>, content: String },
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<M: Msg, S: MsgStore<M>> Chat<M, S> {
|
impl<M: Msg, S: MsgStore<M>> Chat<M, S> {
|
||||||
pub async fn handle_key_event(
|
pub async fn handle_navigation(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: KeyEvent,
|
|
||||||
terminal: &mut Terminal,
|
terminal: &mut Terminal,
|
||||||
size: Size,
|
size: Size,
|
||||||
crossterm_lock: &Arc<FairMutex<()>>,
|
event: KeyEvent,
|
||||||
) -> Handled<M::Id> {
|
) {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
Mode::Tree => {
|
Mode::Tree => {
|
||||||
self.tree
|
self.tree
|
||||||
.handle_key_event(
|
.handle_navigation(&mut self.store, &mut self.cursor, terminal, size, event)
|
||||||
crossterm_lock,
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn handle_messaging(
|
||||||
|
&mut self,
|
||||||
|
terminal: &mut Terminal,
|
||||||
|
crossterm_lock: &Arc<FairMutex<()>>,
|
||||||
|
event: KeyEvent,
|
||||||
|
) -> Option<(Option<M::Id>, String)> {
|
||||||
|
match self.mode {
|
||||||
|
Mode::Tree => {
|
||||||
|
self.tree
|
||||||
|
.handle_messaging(
|
||||||
&mut self.store,
|
&mut self.store,
|
||||||
&mut self.cursor,
|
&mut self.cursor,
|
||||||
terminal,
|
terminal,
|
||||||
size,
|
crossterm_lock,
|
||||||
event,
|
event,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use toss::terminal::Terminal;
|
||||||
|
|
||||||
use crate::store::{Msg, MsgStore};
|
use crate::store::{Msg, MsgStore};
|
||||||
|
|
||||||
use super::{Cursor, Handled};
|
use super::Cursor;
|
||||||
|
|
||||||
pub struct TreeView<M: Msg> {
|
pub struct TreeView<M: Msg> {
|
||||||
// pub focus: Option<M::Id>,
|
// pub focus: Option<M::Id>,
|
||||||
|
|
@ -31,17 +31,15 @@ impl<M: Msg> TreeView<M> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_key_event<S: MsgStore<M>>(
|
pub async fn handle_navigation<S: MsgStore<M>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
l: &Arc<FairMutex<()>>,
|
|
||||||
s: &mut S,
|
s: &mut S,
|
||||||
c: &mut Option<Cursor<M::Id>>,
|
c: &mut Option<Cursor<M::Id>>,
|
||||||
t: &mut Terminal,
|
t: &mut Terminal,
|
||||||
z: Size,
|
z: Size,
|
||||||
event: KeyEvent,
|
event: KeyEvent,
|
||||||
) -> Handled<M::Id> {
|
) {
|
||||||
match event.code {
|
match event.code {
|
||||||
// Cursor movement
|
|
||||||
KeyCode::Char('k') => self.move_up(s, c, t.frame(), z).await,
|
KeyCode::Char('k') => self.move_up(s, c, t.frame(), z).await,
|
||||||
KeyCode::Char('j') => self.move_down(s, c, t.frame(), z).await,
|
KeyCode::Char('j') => self.move_down(s, c, t.frame(), z).await,
|
||||||
KeyCode::Char('K') => self.move_up_sibling(s, c, t.frame(), z).await,
|
KeyCode::Char('K') => self.move_up_sibling(s, c, t.frame(), z).await,
|
||||||
|
|
@ -50,14 +48,24 @@ impl<M: Msg> TreeView<M> {
|
||||||
KeyCode::Char('g') => self.move_to_first(s, c, t.frame(), z).await,
|
KeyCode::Char('g') => self.move_to_first(s, c, t.frame(), z).await,
|
||||||
KeyCode::Char('G') => self.move_to_last(s, c, t.frame(), z).await,
|
KeyCode::Char('G') => self.move_to_last(s, c, t.frame(), z).await,
|
||||||
KeyCode::Esc => *c = None, // TODO Make 'G' do the same thing?
|
KeyCode::Esc => *c = None, // TODO Make 'G' do the same thing?
|
||||||
// Writing messages
|
|
||||||
KeyCode::Char('r') => return Self::reply_normal(l, s, c, t).await,
|
|
||||||
KeyCode::Char('R') => return Self::reply_alternate(l, s, c, t).await,
|
|
||||||
KeyCode::Char('t') | KeyCode::Char('T') => return Self::create_new_thread(l, t).await,
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Handled::Ok
|
pub async fn handle_messaging<S: MsgStore<M>>(
|
||||||
|
&mut self,
|
||||||
|
s: &mut S,
|
||||||
|
c: &mut Option<Cursor<M::Id>>,
|
||||||
|
t: &mut Terminal,
|
||||||
|
l: &Arc<FairMutex<()>>,
|
||||||
|
event: KeyEvent,
|
||||||
|
) -> Option<(Option<M::Id>, String)> {
|
||||||
|
match event.code {
|
||||||
|
KeyCode::Char('r') => Self::reply_normal(s, c, t, l).await,
|
||||||
|
KeyCode::Char('R') => Self::reply_alternate(s, c, t, l).await,
|
||||||
|
KeyCode::Char('t') | KeyCode::Char('T') => Self::create_new_thread(t, l).await,
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn render<S: MsgStore<M>>(
|
pub async fn render<S: MsgStore<M>>(
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||||
use parking_lot::FairMutex;
|
use parking_lot::FairMutex;
|
||||||
use toss::terminal::Terminal;
|
use toss::terminal::Terminal;
|
||||||
|
|
||||||
use crate::chat::{Cursor, Handled};
|
use crate::chat::Cursor;
|
||||||
use crate::store::{Msg, MsgStore};
|
use crate::store::{Msg, MsgStore};
|
||||||
|
|
||||||
use super::TreeView;
|
use super::TreeView;
|
||||||
|
|
@ -26,11 +26,11 @@ impl<M: Msg> TreeView<M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn reply_normal<S: MsgStore<M>>(
|
pub async fn reply_normal<S: MsgStore<M>>(
|
||||||
crossterm_lock: &Arc<FairMutex<()>>,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
cursor: &Option<Cursor<M::Id>>,
|
cursor: &Option<Cursor<M::Id>>,
|
||||||
terminal: &mut Terminal,
|
terminal: &mut Terminal,
|
||||||
) -> Handled<M::Id> {
|
crossterm_lock: &Arc<FairMutex<()>>,
|
||||||
|
) -> Option<(Option<M::Id>, String)> {
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
let tree = store.tree(store.path(&cursor.id).await.first()).await;
|
let tree = store.tree(store.path(&cursor.id).await.first()).await;
|
||||||
let parent_id = if tree.next_sibling(&cursor.id).is_some() {
|
let parent_id = if tree.next_sibling(&cursor.id).is_some() {
|
||||||
|
|
@ -52,23 +52,20 @@ impl<M: Msg> TreeView<M> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(content) = Self::prompt_msg(crossterm_lock, terminal) {
|
if let Some(content) = Self::prompt_msg(crossterm_lock, terminal) {
|
||||||
return Handled::NewMessage {
|
return Some((Some(parent_id), content));
|
||||||
parent: Some(parent_id),
|
|
||||||
content,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Handled::Ok
|
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<S: MsgStore<M>>(
|
||||||
crossterm_lock: &Arc<FairMutex<()>>,
|
|
||||||
store: &S,
|
store: &S,
|
||||||
cursor: &Option<Cursor<M::Id>>,
|
cursor: &Option<Cursor<M::Id>>,
|
||||||
terminal: &mut Terminal,
|
terminal: &mut Terminal,
|
||||||
) -> Handled<M::Id> {
|
crossterm_lock: &Arc<FairMutex<()>>,
|
||||||
|
) -> Option<(Option<M::Id>, String)> {
|
||||||
if let Some(cursor) = cursor {
|
if let Some(cursor) = cursor {
|
||||||
let tree = store.tree(store.path(&cursor.id).await.first()).await;
|
let tree = store.tree(store.path(&cursor.id).await.first()).await;
|
||||||
let parent_id = if tree.next_sibling(&cursor.id).is_none() {
|
let parent_id = if tree.next_sibling(&cursor.id).is_none() {
|
||||||
|
|
@ -84,27 +81,17 @@ impl<M: Msg> TreeView<M> {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(content) = Self::prompt_msg(crossterm_lock, terminal) {
|
if let Some(content) = Self::prompt_msg(crossterm_lock, terminal) {
|
||||||
return Handled::NewMessage {
|
return Some((Some(parent_id), content));
|
||||||
parent: Some(parent_id),
|
|
||||||
content,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Handled::Ok
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_new_thread(
|
pub async fn create_new_thread(
|
||||||
crossterm_lock: &Arc<FairMutex<()>>,
|
|
||||||
terminal: &mut Terminal,
|
terminal: &mut Terminal,
|
||||||
) -> Handled<M::Id> {
|
crossterm_lock: &Arc<FairMutex<()>>,
|
||||||
if let Some(content) = Self::prompt_msg(crossterm_lock, terminal) {
|
) -> Option<(Option<M::Id>, String)> {
|
||||||
Handled::NewMessage {
|
Self::prompt_msg(crossterm_lock, terminal).map(|c| (None, c))
|
||||||
parent: None,
|
|
||||||
content,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Handled::Ok
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -192,14 +192,13 @@ impl Ui {
|
||||||
|
|
||||||
match self.visible {
|
match self.visible {
|
||||||
Visible::Main => {
|
Visible::Main => {
|
||||||
|
self.chat.handle_navigation(terminal, size, event).await;
|
||||||
self.chat
|
self.chat
|
||||||
.handle_key_event(event, terminal, size, crossterm_lock)
|
.handle_messaging(terminal, crossterm_lock, event)
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
Visible::Log => {
|
Visible::Log => {
|
||||||
self.log_chat
|
self.log_chat.handle_navigation(terminal, size, event).await;
|
||||||
.handle_key_event(event, terminal, size, crossterm_lock)
|
|
||||||
.await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue