burst paste edge cases (#2683)
This PR fixes two edge cases in managing burst paste (mainly on power shell). Bugs: - Needs an event key after paste to render the pasted items > ChatComposer::flush_paste_burst_if_due() flushes on timeout. Called: > - Pre-render in App on TuiEvent::Draw. > - Via a delayed frame > BottomPane::request_redraw_in(ChatComposer::recommended_paste_flush_delay()). - Parses two key events separately before starting parsing burst paste > When threshold is crossed, pull preceding burst chars out of the textarea and prepend to paste_burst_buffer, then keep buffering. - Integrates with #2567 to bring image pasting to windows.
This commit is contained in:
@@ -13,6 +13,7 @@ use ratatui::layout::Constraint;
|
||||
use ratatui::layout::Layout;
|
||||
use ratatui::layout::Rect;
|
||||
use ratatui::widgets::WidgetRef;
|
||||
use std::time::Duration;
|
||||
|
||||
mod approval_modal_view;
|
||||
mod bottom_pane_view;
|
||||
@@ -21,6 +22,7 @@ mod chat_composer_history;
|
||||
mod command_popup;
|
||||
mod file_search_popup;
|
||||
mod list_selection_view;
|
||||
mod paste_burst;
|
||||
mod popup_consts;
|
||||
mod scroll_state;
|
||||
mod selection_popup_common;
|
||||
@@ -69,6 +71,7 @@ pub(crate) struct BottomPaneParams {
|
||||
pub(crate) has_input_focus: bool,
|
||||
pub(crate) enhanced_keys_supported: bool,
|
||||
pub(crate) placeholder_text: String,
|
||||
pub(crate) disable_paste_burst: bool,
|
||||
}
|
||||
|
||||
impl BottomPane {
|
||||
@@ -81,6 +84,7 @@ impl BottomPane {
|
||||
params.app_event_tx.clone(),
|
||||
enhanced_keys_supported,
|
||||
params.placeholder_text,
|
||||
params.disable_paste_burst,
|
||||
),
|
||||
active_view: None,
|
||||
app_event_tx: params.app_event_tx,
|
||||
@@ -182,6 +186,9 @@ impl BottomPane {
|
||||
if needs_redraw {
|
||||
self.request_redraw();
|
||||
}
|
||||
if self.composer.is_in_paste_burst() {
|
||||
self.request_redraw_in(ChatComposer::recommended_paste_flush_delay());
|
||||
}
|
||||
input_result
|
||||
}
|
||||
}
|
||||
@@ -382,12 +389,24 @@ impl BottomPane {
|
||||
self.frame_requester.schedule_frame();
|
||||
}
|
||||
|
||||
pub(crate) fn request_redraw_in(&self, dur: Duration) {
|
||||
self.frame_requester.schedule_frame_in(dur);
|
||||
}
|
||||
|
||||
// --- History helpers ---
|
||||
|
||||
pub(crate) fn set_history_metadata(&mut self, log_id: u64, entry_count: usize) {
|
||||
self.composer.set_history_metadata(log_id, entry_count);
|
||||
}
|
||||
|
||||
pub(crate) fn flush_paste_burst_if_due(&mut self) -> bool {
|
||||
self.composer.flush_paste_burst_if_due()
|
||||
}
|
||||
|
||||
pub(crate) fn is_in_paste_burst(&self) -> bool {
|
||||
self.composer.is_in_paste_burst()
|
||||
}
|
||||
|
||||
pub(crate) fn on_history_entry_response(
|
||||
&mut self,
|
||||
log_id: u64,
|
||||
@@ -473,6 +492,7 @@ mod tests {
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
disable_paste_burst: false,
|
||||
});
|
||||
pane.push_approval_request(exec_request());
|
||||
assert_eq!(CancellationEvent::Handled, pane.on_ctrl_c());
|
||||
@@ -492,6 +512,7 @@ mod tests {
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
disable_paste_burst: false,
|
||||
});
|
||||
|
||||
// Create an approval modal (active view).
|
||||
@@ -522,6 +543,7 @@ mod tests {
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
disable_paste_burst: false,
|
||||
});
|
||||
|
||||
// Start a running task so the status indicator is active above the composer.
|
||||
@@ -589,6 +611,7 @@ mod tests {
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
disable_paste_burst: false,
|
||||
});
|
||||
|
||||
// Begin a task: show initial status.
|
||||
@@ -619,6 +642,7 @@ mod tests {
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
disable_paste_burst: false,
|
||||
});
|
||||
|
||||
// Activate spinner (status view replaces composer) with no live ring.
|
||||
@@ -669,6 +693,7 @@ mod tests {
|
||||
has_input_focus: true,
|
||||
enhanced_keys_supported: false,
|
||||
placeholder_text: "Ask Codex to do anything".to_string(),
|
||||
disable_paste_burst: false,
|
||||
});
|
||||
|
||||
pane.set_task_running(true);
|
||||
|
||||
Reference in New Issue
Block a user