Easily Selectable History (#1672)

This update replaces the previous ratatui history widget with an
append-only log so that the terminal can handle text selection and
scrolling. It also disables streaming responses, which we'll do our best
to bring back in a later PR. It also adds a small summary of token use
after the TUI exits.
This commit is contained in:
easong-openai
2025-07-25 01:56:40 -07:00
committed by GitHub
parent 508abbe990
commit 480e82b00d
24 changed files with 394 additions and 353 deletions

View File

@@ -50,10 +50,6 @@ impl<'a> BottomPaneView<'a> for ApprovalModalView<'a> {
self.current.is_complete() && self.queue.is_empty()
}
fn calculate_required_height(&self, area: &Rect) -> u16 {
self.current.get_height(area)
}
fn render(&self, area: Rect, buf: &mut Buffer) {
(&self.current).render_ref(area, buf);
}

View File

@@ -22,9 +22,6 @@ pub(crate) trait BottomPaneView<'a> {
false
}
/// Height required to render the view.
fn calculate_required_height(&self, area: &Rect) -> u16;
/// Render the view: this will be displayed in place of the composer.
fn render(&self, area: Rect, buf: &mut Buffer);

View File

@@ -22,11 +22,6 @@ use crate::app_event::AppEvent;
use crate::app_event_sender::AppEventSender;
use codex_file_search::FileMatch;
/// Minimum number of visible text rows inside the textarea.
const MIN_TEXTAREA_ROWS: usize = 1;
/// Rows consumed by the border.
const BORDER_LINES: u16 = 2;
const BASE_PLACEHOLDER_TEXT: &str = "send a message";
/// If the pasted content exceeds this number of characters, replace it with a
/// placeholder in the UI.
@@ -609,17 +604,6 @@ impl ChatComposer<'_> {
self.dismissed_file_popup_token = None;
}
pub fn calculate_required_height(&self, area: &Rect) -> u16 {
let rows = self.textarea.lines().len().max(MIN_TEXTAREA_ROWS);
let num_popup_rows = match &self.active_popup {
ActivePopup::Command(popup) => popup.calculate_required_height(area),
ActivePopup::File(popup) => popup.calculate_required_height(area),
ActivePopup::None => 0,
};
rows as u16 + BORDER_LINES + num_popup_rows
}
fn update_border(&mut self, has_focus: bool) {
struct BlockState {
right_title: Line<'static>,

View File

@@ -65,10 +65,8 @@ impl BottomPane<'_> {
if !view.is_complete() {
self.active_view = Some(view);
} else if self.is_task_running {
let height = self.composer.calculate_required_height(&Rect::default());
self.active_view = Some(Box::new(StatusIndicatorView::new(
self.app_event_tx.clone(),
height,
)));
}
self.request_redraw();
@@ -138,10 +136,8 @@ impl BottomPane<'_> {
match (running, self.active_view.is_some()) {
(true, false) => {
// Show status indicator overlay.
let height = self.composer.calculate_required_height(&Rect::default());
self.active_view = Some(Box::new(StatusIndicatorView::new(
self.app_event_tx.clone(),
height,
)));
self.request_redraw();
}
@@ -203,14 +199,6 @@ impl BottomPane<'_> {
}
/// Height (terminal rows) required by the current bottom pane.
pub fn calculate_required_height(&self, area: &Rect) -> u16 {
if let Some(view) = &self.active_view {
view.calculate_required_height(area)
} else {
self.composer.calculate_required_height(area)
}
}
pub(crate) fn request_redraw(&self) {
self.app_event_tx.send(AppEvent::RequestRedraw)
}

View File

@@ -1,5 +1,4 @@
use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::widgets::WidgetRef;
use crate::app_event_sender::AppEventSender;
@@ -13,9 +12,9 @@ pub(crate) struct StatusIndicatorView {
}
impl StatusIndicatorView {
pub fn new(app_event_tx: AppEventSender, height: u16) -> Self {
pub fn new(app_event_tx: AppEventSender) -> Self {
Self {
view: StatusIndicatorWidget::new(app_event_tx, height),
view: StatusIndicatorWidget::new(app_event_tx),
}
}
@@ -34,11 +33,7 @@ impl BottomPaneView<'_> for StatusIndicatorView {
true
}
fn calculate_required_height(&self, _area: &Rect) -> u16 {
self.view.get_height()
}
fn render(&self, area: Rect, buf: &mut Buffer) {
fn render(&self, area: ratatui::layout::Rect, buf: &mut Buffer) {
self.view.render_ref(area, buf);
}
}