2026-04-03 19:30:26 -04:00
|
|
|
// thalamus_screen.rs — F5: presence, idle state, and channel status
|
2026-04-03 17:25:59 -04:00
|
|
|
//
|
2026-04-03 19:30:26 -04:00
|
|
|
// Shows idle state from the in-process thalamus (no subprocess spawn),
|
|
|
|
|
// then channel daemon status from cached data.
|
2026-04-03 17:25:59 -04:00
|
|
|
|
|
|
|
|
use ratatui::{
|
|
|
|
|
layout::Rect,
|
|
|
|
|
style::{Color, Style},
|
2026-04-03 18:46:14 -04:00
|
|
|
text::{Line, Span},
|
2026-04-03 17:25:59 -04:00
|
|
|
widgets::{Block, Borders, Paragraph, Wrap},
|
|
|
|
|
Frame,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
use super::{App, SCREEN_LEGEND};
|
|
|
|
|
|
|
|
|
|
impl App {
|
|
|
|
|
pub(crate) fn draw_thalamus(&self, frame: &mut Frame, size: Rect) {
|
|
|
|
|
let section = Style::default().fg(Color::Yellow);
|
2026-04-03 18:46:14 -04:00
|
|
|
let dim = Style::default().fg(Color::DarkGray);
|
2026-04-03 17:25:59 -04:00
|
|
|
let mut lines: Vec<Line> = Vec::new();
|
2026-04-03 18:46:14 -04:00
|
|
|
|
2026-04-03 19:30:26 -04:00
|
|
|
// Presence / idle state from in-process thalamus
|
|
|
|
|
lines.push(Line::styled("── Presence ──", section));
|
|
|
|
|
lines.push(Line::raw(""));
|
|
|
|
|
|
|
|
|
|
if let Some(ref idle) = self.idle_info {
|
|
|
|
|
let presence = if idle.user_present {
|
|
|
|
|
Span::styled("present", Style::default().fg(Color::Green))
|
|
|
|
|
} else {
|
|
|
|
|
Span::styled("away", Style::default().fg(Color::DarkGray))
|
|
|
|
|
};
|
|
|
|
|
lines.push(Line::from(vec![
|
|
|
|
|
Span::raw(" User: "),
|
|
|
|
|
presence,
|
|
|
|
|
Span::raw(format!(" (last {:.0}s ago)", idle.since_activity)),
|
|
|
|
|
]));
|
|
|
|
|
lines.push(Line::raw(format!(" Activity: {:.1}%", idle.activity_ewma * 100.0)));
|
|
|
|
|
lines.push(Line::raw(format!(" Idle state: {}", idle.block_reason)));
|
|
|
|
|
|
|
|
|
|
if idle.dreaming {
|
|
|
|
|
lines.push(Line::styled(" ◆ dreaming", Style::default().fg(Color::Magenta)));
|
|
|
|
|
}
|
|
|
|
|
if idle.sleeping {
|
|
|
|
|
lines.push(Line::styled(" ◆ sleeping", Style::default().fg(Color::Blue)));
|
2026-04-03 18:46:14 -04:00
|
|
|
}
|
2026-04-03 19:30:26 -04:00
|
|
|
} else {
|
|
|
|
|
lines.push(Line::styled(" not initialized", dim));
|
2026-04-03 18:46:14 -04:00
|
|
|
}
|
2026-04-03 19:30:26 -04:00
|
|
|
lines.push(Line::raw(""));
|
2026-04-03 18:46:14 -04:00
|
|
|
|
2026-04-04 13:48:24 -04:00
|
|
|
// Sampling parameters
|
|
|
|
|
lines.push(Line::styled("── Sampling ──", section));
|
|
|
|
|
lines.push(Line::raw(""));
|
|
|
|
|
lines.push(Line::raw(format!(" temperature: {:.2}", self.temperature)));
|
|
|
|
|
lines.push(Line::raw(format!(" top_p: {:.2}", self.top_p)));
|
|
|
|
|
lines.push(Line::raw(format!(" top_k: {}", self.top_k)));
|
|
|
|
|
lines.push(Line::raw(""));
|
|
|
|
|
|
2026-04-03 19:05:48 -04:00
|
|
|
// Channel status from cached data
|
2026-04-03 18:46:14 -04:00
|
|
|
lines.push(Line::styled("── Channels ──", section));
|
2026-04-03 17:25:59 -04:00
|
|
|
lines.push(Line::raw(""));
|
|
|
|
|
|
2026-04-03 19:05:48 -04:00
|
|
|
if self.channel_status.is_empty() {
|
2026-04-03 18:46:14 -04:00
|
|
|
lines.push(Line::styled(" no channels configured", dim));
|
|
|
|
|
} else {
|
2026-04-03 19:05:48 -04:00
|
|
|
for ch in &self.channel_status {
|
|
|
|
|
let (symbol, color) = if ch.connected {
|
2026-04-03 18:46:14 -04:00
|
|
|
("●", Color::Green)
|
|
|
|
|
} else {
|
2026-04-03 19:05:48 -04:00
|
|
|
("○", Color::Red)
|
2026-04-03 18:46:14 -04:00
|
|
|
};
|
2026-04-03 19:05:48 -04:00
|
|
|
|
|
|
|
|
let unread_str = if ch.unread > 0 {
|
|
|
|
|
format!(" ({} unread)", ch.unread)
|
2026-04-03 18:46:14 -04:00
|
|
|
} else {
|
2026-04-03 19:05:48 -04:00
|
|
|
String::new()
|
2026-04-03 18:46:14 -04:00
|
|
|
};
|
2026-04-03 19:05:48 -04:00
|
|
|
|
2026-04-03 18:46:14 -04:00
|
|
|
lines.push(Line::from(vec![
|
|
|
|
|
Span::raw(" "),
|
|
|
|
|
Span::styled(symbol, Style::default().fg(color)),
|
2026-04-03 19:05:48 -04:00
|
|
|
Span::raw(format!(" {:<24}", ch.name)),
|
|
|
|
|
Span::styled(
|
|
|
|
|
if ch.connected { "connected" } else { "disconnected" },
|
|
|
|
|
Style::default().fg(color),
|
|
|
|
|
),
|
|
|
|
|
Span::styled(unread_str, Style::default().fg(Color::Yellow)),
|
2026-04-03 18:46:14 -04:00
|
|
|
]));
|
|
|
|
|
}
|
2026-04-03 17:25:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let block = Block::default()
|
|
|
|
|
.title_top(Line::from(SCREEN_LEGEND).left_aligned())
|
|
|
|
|
.title_top(Line::from(" thalamus ").right_aligned())
|
|
|
|
|
.borders(Borders::ALL)
|
|
|
|
|
.border_style(Style::default().fg(Color::Cyan));
|
|
|
|
|
|
|
|
|
|
let para = Paragraph::new(lines)
|
|
|
|
|
.block(block)
|
|
|
|
|
.wrap(Wrap { trim: false })
|
|
|
|
|
.scroll((self.debug_scroll, 0));
|
|
|
|
|
|
|
|
|
|
frame.render_widget(para, size);
|
|
|
|
|
}
|
|
|
|
|
}
|