You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maka.apache.org by wy...@apache.org on 2026/09/25 06:11:58 UTC
(maka) 01/04: fix(tui): hold the reviewed view while a plugin action awaits confirmation
This is an automated email from the ASF dual-hosted git repository.
M4n5ter pushed a commit to branch feat/runtime-host-rust
in repository https://gitbox.apache.org/repos/asf/maka.git
commit 7fad4a819f7751c712f674d7eff6cbb57229179c
Author: M4n5ter <m4...@gmail.com>
AuthorDate: Fri Sep 25 13:24:27 2026 +0800
fix(tui): hold the reviewed view while a plugin action awaits confirmation
Defer live reads until confirmation closes so submission keeps the original revision, fields and recovery route. Cancel catches up without writing. Fence navigation PTY waits on the actual destination before closing the terminal.
Generated-by: Codex
---
crates/cli/tests/integration/tui/navigation.rs | 4 +-
crates/tui/src/apps.rs | 85 +++++++++++++++++++++++++-
2 files changed, 87 insertions(+), 2 deletions(-)
diff --git a/crates/cli/tests/integration/tui/navigation.rs b/crates/cli/tests/integration/tui/navigation.rs
index a9cca21b4f..b23ec7b4d3 100644
--- a/crates/cli/tests/integration/tui/navigation.rs
+++ b/crates/cli/tests/integration/tui/navigation.rs
@@ -50,7 +50,9 @@ fn restart_keeps_forward_history_and_keyboard_control_without_replaying_actions(
tui.send(b"\x1b"); // Help closes without becoming a navigation entry.
tui.wait_until(|screen| !screen.contains("Move focus between controls"));
tui.command("Open workspace");
- tui.wait_for("No sessions yet");
+ // The sidebar already says "No sessions yet" on Settings. Observe the
+ // destination before sending Back, or an old frame can satisfy both waits.
+ tui.wait_until(|screen| screen.contains("No sessions yet") && !screen.contains("Unicode ▾"));
tui.send(b"\x1b[1;3D"); // A real destination leaves forward history.
tui.wait_for("Unicode ▾");
tui.close_terminal();
diff --git a/crates/tui/src/apps.rs b/crates/tui/src/apps.rs
index 861b1d151e..39e3488817 100644
--- a/crates/tui/src/apps.rs
+++ b/crates/tui/src/apps.rs
@@ -449,7 +449,30 @@ impl App {
work: Work::Directory(cursor),
});
}
+ // A confirmation belongs to the view the reader actually reviewed.
+ // Defer live reads until it closes; submitting still uses that view's
+ // revision, fields and recovery identity. Retirement cancels the sheet.
+ if apps.confirmation().is_none() {
+ apps.confirming = None;
+ }
for (key, instance) in &mut apps.instances {
+ if apps
+ .confirming
+ .as_ref()
+ .is_some_and(|(holder, _)| holder == key)
+ {
+ if matches!(
+ instance.pending,
+ Some(Work::Call {
+ input: Input::Read { .. },
+ ..
+ })
+ ) {
+ instance.pending = None;
+ instance.stale = true;
+ }
+ continue;
+ }
if instance.busy {
continue;
}
@@ -983,7 +1006,12 @@ impl App {
instance.submit(&id, &locale);
}
}
- Command::CancelConfirm => apps.confirming = None,
+ Command::CancelConfirm => {
+ apps.confirming = None;
+ if instance.stale && instance.idle() && !instance.keeps() {
+ instance.read(&locale);
+ }
+ }
Command::View(Intent::Navigate(route)) => instance.navigate(route, &locale),
Command::View(Intent::Open(session)) => {
return self.apply(Action::Visit(Route::Session(session)));
@@ -1688,6 +1716,61 @@ pub(crate) mod tests {
command(Command::View(Intent::Submit(action.into())))
}
+ #[test]
+ fn confirmation_keeps_its_reviewed_revision_fields_and_recovery_across_live_updates() {
+ for approve in [false, true] {
+ let mut app = app();
+ let view = instance_mut(&mut app).view.as_mut().unwrap();
+ view.actions[0].confirm = Some(maka_plugins::terminal_ui::view::Confirm {
+ title: "Save these values?".into(),
+ message: "Review the current notebook.".into(),
+ destructive: false,
+ });
+ view.actions[0].recovery = Some(json!({"decision":"original"}));
+ // Opening a confirmation overtakes a background read already in flight.
+ instance_mut(&mut app).read("en");
+ let old = next(&mut app).unwrap();
+ app.apps_action(save());
+ assert!(app.apps.confirm_visible());
+ let mut replacement = form();
+ replacement.revision = "later".into();
+ app.apps_complete(old, Ok(Output::Reply(Reply::View { view: replacement })));
+ app.apps_session_changed("session");
+ assert!(
+ next(&mut app).is_none(),
+ "updates wait for the decision sheet"
+ );
+ assert_eq!(instance(&app).view.as_ref().unwrap().revision, "one");
+ app.apps_action(command(if approve {
+ Command::Confirm
+ } else {
+ Command::CancelConfirm
+ }));
+ let request = next(&mut app).unwrap();
+ if approve {
+ assert!(
+ matches!(request.work, Work::Call { input: Input::Submit { ref revision, ref fields, .. }, .. }
+ if revision == "one" && fields["name"] == "My notes")
+ );
+ assert_eq!(
+ instance(&app).unresolved.as_ref().unwrap().recovery,
+ Some(json!({"decision":"original"}))
+ );
+ } else {
+ assert!(
+ matches!(
+ request.work,
+ Work::Call {
+ input: Input::Read { .. },
+ ..
+ }
+ ),
+ "cancelling catches up with the deferred updates without writing"
+ );
+ }
+ }
+ }
+
#[test]
fn consent_requires_visible_explicit_confirmation_and_never_steals_another_page() {
use maka_plugins::authorization::{Capability, Request as Proposal, Target};
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org