forked from kent/consciousness
user: InteractScreen extracted, all screens use ScreenView trait
InteractScreen in chat.rs owns conversation/autonomous/tools panes, textarea, input history, scroll state. App is now just shared state (status, sampling params, agent_state, channel_status, idle_info). Event loop holds InteractScreen separately for UiMessage routing. Overlay screens (F2-F5) in screens vec. F-key switching preserves state across screen changes. handle_ui_message moved from App to InteractScreen. handle_key split: global keys on App, screen keys in tick(). draw dispatch eliminated — each screen draws itself. Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
8418bc9bc9
commit
68f115b880
8 changed files with 276 additions and 259 deletions
|
|
@ -14,7 +14,7 @@ use tokio::sync::Mutex;
|
|||
use crate::agent::Agent;
|
||||
use crate::agent::api::ApiClient;
|
||||
use crate::mind::MindCommand;
|
||||
use crate::user::{self as tui, HotkeyAction};
|
||||
use crate::user::{self as tui, HotkeyAction, ScreenView};
|
||||
use crate::user::ui_channel::{self, UiMessage};
|
||||
|
||||
// ── Slash commands ─────────────────────────────────────────────
|
||||
|
|
@ -381,14 +381,16 @@ pub async fn run(
|
|||
}
|
||||
let notify_rx = crate::thalamus::channels::subscribe_all();
|
||||
|
||||
// Overlay screens (F2-F5). Index 0 = no overlay (interact).
|
||||
// InteractScreen held separately for UiMessage routing
|
||||
let mut interact = crate::user::chat::InteractScreen::new();
|
||||
// Overlay screens: F2=conscious, F3=subconscious, F4=unconscious, F5=thalamus
|
||||
let mut screens: Vec<Box<dyn tui::ScreenView>> = vec![
|
||||
Box::new(crate::user::context::ConsciousScreen::new()),
|
||||
Box::new(crate::user::subconscious::SubconsciousScreen::new()),
|
||||
Box::new(crate::user::unconscious::UnconsciousScreen::new()),
|
||||
Box::new(crate::user::thalamus::ThalamusScreen::new()),
|
||||
];
|
||||
let mut active_screen: usize = 0; // 0 = interact, 1-4 = overlay index + 1
|
||||
let mut active_screen: usize = 0; // 0 = interact, 1-4 = overlay
|
||||
|
||||
let mut terminal = tui::init_terminal()?;
|
||||
let mut reader = EventStream::new();
|
||||
|
|
@ -403,9 +405,11 @@ pub async fn run(
|
|||
|
||||
let _ = ui_tx.send(UiMessage::Info("consciousness v0.3 (tui)".into()));
|
||||
|
||||
// Initial render — don't wait for Mind to init
|
||||
app.drain_messages(&mut ui_rx);
|
||||
terminal.draw(|f| app.draw(f))?;
|
||||
// Initial render
|
||||
terminal.draw(|f| {
|
||||
let area = f.area();
|
||||
interact.tick(f, area, None, &mut app);
|
||||
})?;
|
||||
|
||||
// Replay conversation after Mind init completes (non-blocking check)
|
||||
let mut startup_done = false;
|
||||
|
|
@ -423,8 +427,8 @@ pub async fn run(
|
|||
// F-keys switch screens
|
||||
if let ratatui::crossterm::event::KeyCode::F(n) = key.code {
|
||||
active_screen = match n {
|
||||
1 => 0,
|
||||
n @ 2..=5 => n as usize - 1,
|
||||
1 => 0, // interact
|
||||
n @ 2..=5 if (n as usize - 2) < screens.len() => n as usize - 1,
|
||||
_ => active_screen,
|
||||
};
|
||||
if active_screen == 4 { // thalamus — refresh channels
|
||||
|
|
@ -438,25 +442,18 @@ pub async fn run(
|
|||
continue;
|
||||
}
|
||||
|
||||
// App handles global keys (Ctrl combos) + interact keys
|
||||
if active_screen == 0 {
|
||||
app.handle_key(key);
|
||||
} else {
|
||||
// Global keys only
|
||||
app.handle_key(key);
|
||||
// Screen gets the key on next render tick
|
||||
}
|
||||
// Global keys (Ctrl combos)
|
||||
app.handle_global_key(key);
|
||||
|
||||
// Store pending key for active overlay screen
|
||||
pending_key = Some(key);
|
||||
dirty = true;
|
||||
}
|
||||
Some(Ok(Event::Mouse(mouse))) => {
|
||||
app.handle_mouse(mouse);
|
||||
Some(Ok(Event::Mouse(_mouse))) => {
|
||||
// TODO: route to active screen
|
||||
dirty = true;
|
||||
}
|
||||
Some(Ok(Event::Resize(w, h))) => {
|
||||
app.handle_resize(w, h);
|
||||
Some(Ok(Event::Resize(_w, _h))) => {
|
||||
terminal.clear()?;
|
||||
dirty = true;
|
||||
}
|
||||
|
|
@ -506,7 +503,7 @@ pub async fn run(
|
|||
}
|
||||
|
||||
Some(msg) = ui_rx.recv() => {
|
||||
app.handle_ui_message(msg);
|
||||
interact.handle_ui_message(&msg, &mut app);
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -540,7 +537,9 @@ pub async fn run(
|
|||
}
|
||||
}
|
||||
|
||||
if app.drain_messages(&mut ui_rx) {
|
||||
// Drain UiMessages to interact screen
|
||||
while let Ok(msg) = ui_rx.try_recv() {
|
||||
interact.handle_ui_message(&msg, &mut app);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
|
|
@ -548,12 +547,15 @@ pub async fn run(
|
|||
let key = pending_key.take();
|
||||
let mut screen_action = None;
|
||||
if active_screen == 0 {
|
||||
terminal.draw(|f| app.draw(f))?;
|
||||
terminal.draw(|f| {
|
||||
let area = f.area();
|
||||
screen_action = interact.tick(f, area, key, &mut app);
|
||||
})?;
|
||||
} else {
|
||||
let screen = &mut screens[active_screen - 1];
|
||||
terminal.draw(|f| {
|
||||
let area = f.area();
|
||||
screen_action = screen.tick(f, area, key, &app);
|
||||
screen_action = screen.tick(f, area, key, &mut app);
|
||||
})?;
|
||||
}
|
||||
if let Some(action) = screen_action {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue