use super::{overlay_block, render_overlay_fill, render_scroll_view_persistent};
use crate::tui::{PADDED_INLINE_SEPARATOR, input, state::MissionControlState, theme::MATRIX_GREEN};
use ratatui::{
Frame,
layout::{Alignment, Rect},
text::{Line, Span},
widgets::{Clear, Paragraph, Wrap},
};
pub(super) fn draw_status(frame: &mut Frame<'_>, area: Rect, state: &MissionControlState) {
frame.render_widget(
Paragraph::new(Line::from(Span::styled(
footer_left_text(state),
MATRIX_GREEN.status_line(),
)))
.style(MATRIX_GREEN.status_line()),
area,
);
frame.render_widget(
Paragraph::new(footer_right_line(state))
.style(MATRIX_GREEN.status_line())
.alignment(Alignment::Right),
area,
);
}
fn footer_left_text(state: &MissionControlState) -> String {
let mut text = format!("📂Cwd: {}", state.footer_cwd);
if let Some(branch) = state
.footer_git_branch
.as_deref()
.filter(|branch| !branch.is_empty())
{
text.push_str(PADDED_INLINE_SEPARATOR);
text.push_str("🪾Branch: ");
text.push_str(branch);
}
text
}
fn footer_right_text(state: &MissionControlState) -> String {
let base = format!("🤘MAGI-CODE v{}🤘", env!("CARGO_PKG_VERSION"));
#[cfg(any(test, debug_assertions))]
{
if let Some(perf) = state.perf.footer_text() {
return format!("{perf}{PADDED_INLINE_SEPARATOR}{base}");
}
}
base
}
fn footer_right_line(state: &MissionControlState) -> Line<'static> {
let text = footer_right_text(state);
Line::from(Span::styled(text, MATRIX_GREEN.accent(false)))
}
pub(super) fn draw_help(frame: &mut Frame<'_>, area: Rect, state: &MissionControlState) {
frame.render_widget(Clear, area);
let block = overlay_block("Help");
let inner = block.inner(area);
frame.render_widget(block, area);
let text_area = render_overlay_fill(frame, inner);
let help_text = input::help_text();
let wrap_width = super::scroll_view_content_width(text_area).max(1);
let scroll = state.help_render_offset(text_area.height, wrap_width, help_text);
render_scroll_view_persistent(
frame,
text_area,
super::usize_to_u16_saturating(scroll),
super::usize_to_u16_saturating(crate::tui::transcript::ratatui_wrapped_visual_rows(
help_text, wrap_width,
)),
Paragraph::new(help_text)
.style(MATRIX_GREEN.panel_alt())
.wrap(Wrap { trim: false }),
&state.scroll_views.help,
);
}
#[cfg(test)]
mod tests {
use super::*;
use ratatui::{Terminal, backend::TestBackend};
fn render_status_buffer(state: MissionControlState) -> ratatui::buffer::Buffer {
let backend = TestBackend::new(100, 1);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|frame| draw_status(frame, Rect::new(0, 0, 100, 1), &state))
.unwrap();
terminal.backend().buffer().clone()
}
fn render_status_text(state: MissionControlState) -> String {
render_status_buffer(state)
.content()
.iter()
.map(|cell| cell.symbol())
.collect()
}
#[test]
fn footer_left_shows_cwd_and_branch_without_session_or_provider() {
let mut state = MissionControlState {
provider: crate::providers::OPENAI_CODEX_PROVIDER.to_string(),
model: "gpt-5".to_string(),
footer_session: "session".to_string(),
footer_cwd: "/repo".to_string(),
footer_git_branch: Some("main".to_string()),
..Default::default()
};
state.refresh_thinking_levels(
crate::thinking::ThinkingLevel::Medium,
crate::thinking::ThinkingLevel::EFFORT_GENERIC.to_vec(),
);
assert_eq!(footer_left_text(&state), "📂Cwd: /repo • 🪾Branch: main");
let text = render_status_text(state);
assert!(text.contains("📂 Cwd: /repo • 🪾 Branch: main"), "{text}");
assert!(!text.contains("Sess:"), "{text}");
assert!(!text.contains("Model:"), "{text}");
assert!(!text.contains("openai-codex/gpt-5"), "{text}");
assert!(!text.contains("Thinking:"), "{text}");
}
#[test]
fn footer_left_omits_empty_branch() {
let state = MissionControlState {
footer_cwd: "/repo".to_string(),
..Default::default()
};
assert_eq!(footer_left_text(&state), "📂Cwd: /repo");
let text = render_status_text(state);
assert!(text.contains("📂 Cwd: /repo"), "{text}");
assert!(!text.contains("🪾 Branch:"), "{text}");
}
#[test]
fn footer_right_shows_version_without_update() {
assert_eq!(
footer_right_text(&MissionControlState::default()),
format!("🤘MAGI-CODE v{}🤘", env!("CARGO_PKG_VERSION"))
);
let text = render_status_text(MissionControlState::default());
assert!(
text.contains(&format!("🤘 MAGI-CODE v{}🤘", env!("CARGO_PKG_VERSION"))),
"{text}"
);
assert!(!text.contains("[F1] help"), "{text}");
}
#[test]
fn footer_right_includes_perf_text_only_after_snapshot_exists() {
let state = MissionControlState {
#[cfg(any(test, debug_assertions))]
perf: crate::tui::perf::TuiPerfCounters::with_enabled(true),
..Default::default()
};
assert!(!footer_right_text(&state).contains("perf drain"));
#[cfg(any(test, debug_assertions))]
{
state.perf.record_drain_us(400);
state.perf.increment_projected_cards();
state.perf.set_backlog_before_drain(3);
state.perf.set_backlog_after_drain(2);
state.perf.set_backlog_before_draw(1);
state.perf.record_draw_us(2100);
}
let text = footer_right_text(&state);
assert!(text.contains("perf drain 0.4/0.4ms draw 2.1/2.1ms cards 1 backlog 3/2/1"));
assert!(text.contains("MAGI-CODE v"));
}
}