kptui: organize client code into kordophoned-client
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
mod daemon;
|
||||
use kordophoned_client as daemon;
|
||||
|
||||
use anyhow::Result;
|
||||
use crossterm::event::{Event as CEvent, KeyCode, KeyEventKind, KeyModifiers};
|
||||
@@ -25,6 +25,7 @@ enum Focus {
|
||||
struct AppState {
|
||||
conversations: Vec<daemon::ConversationSummary>,
|
||||
selected_idx: usize,
|
||||
selected_conversation_id: Option<String>,
|
||||
messages: Vec<daemon::ChatMessage>,
|
||||
active_conversation_id: Option<String>,
|
||||
active_conversation_title: String,
|
||||
@@ -42,6 +43,7 @@ impl AppState {
|
||||
Self {
|
||||
conversations: Vec::new(),
|
||||
selected_idx: 0,
|
||||
selected_conversation_id: None,
|
||||
messages: Vec::new(),
|
||||
active_conversation_id: None,
|
||||
active_conversation_title: String::new(),
|
||||
@@ -58,23 +60,34 @@ impl AppState {
|
||||
fn select_next(&mut self) {
|
||||
if self.conversations.is_empty() {
|
||||
self.selected_idx = 0;
|
||||
self.selected_conversation_id = None;
|
||||
return;
|
||||
}
|
||||
self.selected_idx = (self.selected_idx + 1).min(self.conversations.len() - 1);
|
||||
self.selected_conversation_id = self
|
||||
.conversations
|
||||
.get(self.selected_idx)
|
||||
.map(|c| c.id.clone());
|
||||
}
|
||||
|
||||
fn select_prev(&mut self) {
|
||||
if self.conversations.is_empty() {
|
||||
self.selected_idx = 0;
|
||||
self.selected_conversation_id = None;
|
||||
return;
|
||||
}
|
||||
self.selected_idx = self.selected_idx.saturating_sub(1);
|
||||
self.selected_conversation_id = self
|
||||
.conversations
|
||||
.get(self.selected_idx)
|
||||
.map(|c| c.id.clone());
|
||||
}
|
||||
|
||||
fn open_selected_conversation(&mut self) {
|
||||
if let Some(conv) = self.conversations.get(self.selected_idx) {
|
||||
self.active_conversation_id = Some(conv.id.clone());
|
||||
self.active_conversation_title = conv.title.clone();
|
||||
self.selected_conversation_id = Some(conv.id.clone());
|
||||
self.messages.clear();
|
||||
self.transcript_scroll = 0;
|
||||
self.pinned_to_bottom = true;
|
||||
@@ -331,14 +344,31 @@ fn run_app(terminal: &mut ratatui::Terminal<ratatui::backend::CrosstermBackend<s
|
||||
while let Ok(evt) = event_rx.try_recv() {
|
||||
match evt {
|
||||
daemon::Event::Conversations(convs) => {
|
||||
let keep_selected_id = app
|
||||
.selected_conversation_id
|
||||
.clone()
|
||||
.or_else(|| app.active_conversation_id.clone());
|
||||
|
||||
app.refresh_conversations_in_flight = false;
|
||||
app.status.clear();
|
||||
app.conversations = convs;
|
||||
if app.selected_idx >= app.conversations.len() {
|
||||
app.selected_idx = app.conversations.len().saturating_sub(1);
|
||||
}
|
||||
if app.active_conversation_id.is_none() && !app.conversations.is_empty() {
|
||||
if app.conversations.is_empty() {
|
||||
app.selected_idx = 0;
|
||||
app.selected_conversation_id = None;
|
||||
} else if let Some(id) = keep_selected_id {
|
||||
if let Some(idx) = app.conversations.iter().position(|c| c.id == id) {
|
||||
app.selected_idx = idx;
|
||||
app.selected_conversation_id = Some(id);
|
||||
} else {
|
||||
app.selected_idx = 0;
|
||||
app.selected_conversation_id =
|
||||
Some(app.conversations[0].id.clone());
|
||||
}
|
||||
} else {
|
||||
app.selected_idx = app.selected_idx.min(app.conversations.len() - 1);
|
||||
app.selected_conversation_id = Some(
|
||||
app.conversations[app.selected_idx].id.clone(),
|
||||
);
|
||||
}
|
||||
}
|
||||
daemon::Event::Messages {
|
||||
@@ -477,7 +507,7 @@ fn run_app(terminal: &mut ratatui::Terminal<ratatui::backend::CrosstermBackend<s
|
||||
requested_view = ViewMode::List;
|
||||
app.focus = Focus::Navigation;
|
||||
}
|
||||
KeyCode::Char('i') => app.focus = Focus::Input,
|
||||
KeyCode::Char('i') if app.focus != Focus::Input => app.focus = Focus::Input,
|
||||
_ => {
|
||||
handle_chat_keys(&mut app, &request_tx, key.code, max_scroll);
|
||||
}
|
||||
@@ -490,7 +520,7 @@ fn run_app(terminal: &mut ratatui::Terminal<ratatui::backend::CrosstermBackend<s
|
||||
}
|
||||
}
|
||||
KeyCode::Esc => app.focus = Focus::Navigation,
|
||||
KeyCode::Char('i') => app.focus = Focus::Input,
|
||||
KeyCode::Char('i') if app.focus != Focus::Input => app.focus = Focus::Input,
|
||||
KeyCode::Up => {
|
||||
if app.focus == Focus::Navigation {
|
||||
app.select_prev()
|
||||
|
||||
Reference in New Issue
Block a user