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/23 12:35:08 UTC

(maka) 02/02: fix(tui): keep branch recovery controls stable and reachable

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 dc19862e63e412672cc290e012d469e8b0fb89cd
Author: M4n5ter <m4...@gmail.com>
AuthorDate: Wed Sep 23 20:31:34 2026 +0800

    fix(tui): keep branch recovery controls stable and reachable
    
    Keep recovery geometry independent of arriving catalog names, wait for a live Host in the restart test, and keep keyboard focus on visible enabled actions.
    
    Generated-by: Codex
---
 crates/cli/tests/integration/tui/branch.rs |  1 +
 crates/tui/src/pages/branch.rs             | 40 +++++++++++++++++++++++++++---
 crates/tui/src/pages/branch/view.rs        | 24 ++++++------------
 3 files changed, 45 insertions(+), 20 deletions(-)

diff --git a/crates/cli/tests/integration/tui/branch.rs b/crates/cli/tests/integration/tui/branch.rs
index ca4f931b05..8c19783e16 100644
--- a/crates/cli/tests/integration/tui/branch.rs
+++ b/crates/cli/tests/integration/tui/branch.rs
@@ -137,6 +137,7 @@ fn branch_preserves_selected_history_and_draft_and_reopens_by_original_receipt()
     });
     let mut reopened = Pty::spawn(&["--root", host.root.to_str().unwrap()]);
     reopened.wait_for("Preserved branch draft");
+    reopened.wait_for("Later reply."); // Restored draft alone does not mean Host is connected.
     reopened.send(b"\x10");
     reopened.wait_for("Check session branch");
     reopened.click_text("Check session branch");
diff --git a/crates/tui/src/pages/branch.rs b/crates/tui/src/pages/branch.rs
index 35fb88ffd9..cf54c38742 100644
--- a/crates/tui/src/pages/branch.rs
+++ b/crates/tui/src/pages/branch.rs
@@ -348,6 +348,7 @@ impl App {
         };
         state.pending = Some(request.clone());
         state.phase = if query { Phase::Pending } else { Phase::Saving };
+        state.focus = 0;
         Some(request)
     }
     pub fn branch_after_checkpoint(
@@ -515,6 +516,11 @@ mod tests {
         app.apply(Action::Branch(Command::Confirm));
         let request = app.branch_request().unwrap();
         assert!(!request.query);
+        app.input(Event::Key(KeyEvent::new(KeyCode::Tab, KeyModifiers::NONE)));
+        assert_eq!(
+            app.branch.focus, 0,
+            "pending dialog has only one focusable action"
+        );
         let saved = serde_json::to_value(app.branch.checkpoint()).unwrap();
         let mut stale = request.clone();
         stale.sequence += 1;
@@ -540,10 +546,7 @@ mod tests {
         let mut recovered = State::default();
         recovered.restore(serde_json::from_value(saved.clone()).unwrap());
         app.branch = recovered;
-        app.connection = ConnectionState::Connected {
-            root_id: "root".into(),
-            epoch: "new-epoch".into(),
-        };
+        app.connection = ConnectionState::Connecting;
         assert!(
             app.branch_request().is_none(),
             "reopen neither writes nor polls"
@@ -551,6 +554,35 @@ mod tests {
         app.apply(Action::Branch(Command::Resume));
         frame(&mut app, 80, 24);
         app.apply(Action::Branch(Command::Query));
+        assert!(
+            app.branch_request().is_none(),
+            "restored drafts do not establish a connection"
+        );
+        app.connection = ConnectionState::Connected {
+            root_id: "root".into(),
+            epoch: "new-epoch".into(),
+        };
+        frame(&mut app, 80, 24);
+        let button = app
+            .hits
+            .iter()
+            .find(|hit| hit.action == Action::Branch(Command::Query))
+            .unwrap()
+            .area;
+        let mut source = super::super::sessions::tests::item("source");
+        source.name = "A source name arriving after the dialog was opened".repeat(4);
+        app.sessions.items.push(source);
+        frame(&mut app, 80, 24);
+        assert_eq!(
+            app.hits
+                .iter()
+                .find(|hit| hit.action == Action::Branch(Command::Query))
+                .unwrap()
+                .area,
+            button,
+            "catalog arrivals cannot move the recovery action under the mouse"
+        );
+        app.apply(Action::Branch(Command::Query));
         let query = app.branch_request().unwrap();
         assert!(query.query);
         assert_eq!(query.input, request.input);
diff --git a/crates/tui/src/pages/branch/view.rs b/crates/tui/src/pages/branch/view.rs
index 9456de8b7c..8d588d6ce9 100644
--- a/crates/tui/src/pages/branch/view.rs
+++ b/crates/tui/src/pages/branch/view.rs
@@ -40,7 +40,14 @@ impl App {
                 }
                 KeyCode::Esc => Some(Command::Close),
                 KeyCode::Tab | KeyCode::BackTab | KeyCode::Left | KeyCode::Right => {
-                    self.branch.focus ^= 1;
+                    self.branch.focus = if primary(self.branch.phase)
+                        .as_ref()
+                        .is_some_and(|command| self.branch_enabled(command))
+                    {
+                        self.branch.focus ^ 1
+                    } else {
+                        0
+                    };
                     None
                 }
                 KeyCode::Enter => {
@@ -85,21 +92,6 @@ pub fn draw(frame: &mut Frame<'_>, app: &mut App, area: Rect, base: Style) {
         .basis
         .as_ref()
         .map(|basis| basis.name.as_str())
-        .or_else(|| {
-            let source = &state.saved.as_ref()?.input.source_session_id;
-            app.sessions
-                .items
-                .iter()
-                .find(|item| item.id == *source)
-                .map(|item| item.name.as_str())
-                .or_else(|| {
-                    app.tabs
-                        .entries
-                        .iter()
-                        .find(|tab| tab.id == *source)
-                        .and_then(|tab| tab.name.as_deref())
-                })
-        })
         .unwrap_or("");
     let mut heading = safe(name);
     if let Some(basis) = &state.basis {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@maka.apache.org
For additional commands, e-mail: commits-help@maka.apache.org