mirror of
https://github.com/codewhale-hq/Codewhale.git
synced 2026-11-11 01:51:34 -10:00
fix(tui): drive the composer send cue from the draft, not the paste-burst window
The `[↵]` chip read `composer_enter_would_submit`, which also consults the paste-burst window. That window is re-extended on every fast keystroke, so on terminals outside the bracketed-paste allowlist (tmux, VS Code, kitty, Alacritty, GNOME Terminal, SSH) the chip strobed `[↵]`/`[·]` while typing. Add `App::composer_draft_is_submittable` (time-independent, trimmed-empty check) and paint the chip from it. Enter routing, mouse submit and hover registration stay on the timing predicate. Lands the preserved patch from the fix/issue-sweep-0.10.0 worktree, with its placement corrected so `composer_enter_would_submit` keeps its own doc comment and `#[must_use]`. The pinned test at ui/tests.rs:6641 now asserts a steady `[↵]` while the burst window is open and Enter routing still waits. Refs #6397 Checks (run from a HEAD snapshot + these three files, because the shared checkout's lib-test build was broken by other lanes' in-flight edits in git_history.rs, context_report/, core/engine/tests.rs and debug/cache.rs): - cargo test -p codewhale-tui --lib -- paste_safety composer_submit composer_enter submit_cue composer_draft: 6 passed, 0 failed - rustfmt --check composer.rs: clean Not run: manual tmux / VS Code terminal check. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
2fce1aad0e
commit
389619a693
3 files changed
+28
-4
No files matched your search
@@ -1870,6 +1870,21 @@ impl App {
|
||||
!self.input.trim().is_empty()
|
||||
}
|
||||
|
||||
/// Whether the *draft* is in a submittable state, for display only.
|
||||
///
|
||||
/// Deliberately time-independent. [`Self::composer_enter_would_submit`]
|
||||
/// additionally consults the paste-burst heuristic, whose suppression
|
||||
/// window is re-extended on every fast keystroke -- correct for deciding
|
||||
/// what a newline does mid-paste, wrong for a persistent affordance.
|
||||
/// Driving the `[↵]` chip from it made the chip strobe `[↵]`/`[·]` for as
|
||||
/// long as the user kept typing, because the window kept reopening
|
||||
/// (#6397). Enter routing, mouse submit and hover registration stay on
|
||||
/// the timing predicate.
|
||||
#[must_use]
|
||||
pub fn composer_draft_is_submittable(&self) -> bool {
|
||||
!self.input.trim().is_empty()
|
||||
}
|
||||
|
||||
/// Public wrapper around [`Self::consolidate_large_input`] that no-ops
|
||||
/// when the current input fits inside the safety cap. Both the paste-
|
||||
/// insert path (visible-before-submit) and the submit-time safety net
|
||||
|
||||
@@ -6638,15 +6638,20 @@ fn raw_paste_beginning_with_space_preserves_payload_over_reasoning_action() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn paste_safety_expiry_repaints_the_submit_cue_without_another_key() {
|
||||
fn paste_safety_window_keeps_the_submit_cue_steady_while_routing_waits() {
|
||||
// #6397: the `[↵]` chip follows the time-independent draft predicate,
|
||||
// so an open paste-burst window (re-extended on every fast keystroke)
|
||||
// must not flip it to `[·]`. Enter routing still waits on the window.
|
||||
let mut app = create_test_app();
|
||||
app.use_paste_burst_detection = true;
|
||||
app.insert_str("/mcp");
|
||||
let now = Instant::now();
|
||||
app.paste_burst.extend_window(now);
|
||||
assert!(!app.composer_enter_would_submit());
|
||||
assert!(app.composer_draft_is_submittable());
|
||||
let waiting = render_underwater_test_app(&mut app, 80, 24);
|
||||
assert!(waiting.contains("[·]"), "{waiting}");
|
||||
assert!(waiting.contains("[↵]"), "{waiting}");
|
||||
assert!(!waiting.contains("[·]"), "{waiting}");
|
||||
app.needs_redraw = false;
|
||||
assert!(flush_paste_burst_before_composer(
|
||||
&mut app,
|
||||
|
||||
@@ -1942,7 +1942,11 @@ impl Renderable for ComposerWidget<'_> {
|
||||
area,
|
||||
buf,
|
||||
&self.app.ui_theme,
|
||||
self.app.composer_enter_would_submit(),
|
||||
// Display state, not key-routing state: the paste-burst
|
||||
// window reopens on every fast keystroke, so drawing from
|
||||
// `composer_enter_would_submit` strobed the chip while
|
||||
// typing (#6397).
|
||||
self.app.composer_draft_is_submittable(),
|
||||
crate::tui::color_compat::ascii_safe_enabled(),
|
||||
);
|
||||
}
|
||||
@@ -6969,7 +6973,7 @@ mod tests {
|
||||
let mut buf = Buffer::empty(area);
|
||||
widget.render(area, &mut buf);
|
||||
let submit = active_composer_submit_rect(&app, area).unwrap();
|
||||
let ready = app.composer_enter_would_submit();
|
||||
let ready = app.composer_draft_is_submittable();
|
||||
let painted: String = (submit.x..submit.right())
|
||||
.map(|x| buf[(x, submit.y)].symbol())
|
||||
.collect();
|
||||
|
||||
Reference in new issue
Block a user