From b9ce96869e89937278d673d70ae4c135dd318469 Mon Sep 17 00:00:00 2001 From: akbash Date: Wed, 9 Sep 2026 02:35:31 +0300 Subject: feat: navigate and highlight workspaces across machines (#3755) * fix: highlight workspace navigation with saved machines refs #3754 * feat: navigate workspaces across connected machines refs #3754 * feat: navigate workspaces across machines refs #3754 --------- Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com> Co-authored-by: Ogulcan Celik --- src/client/shell/input.rs | 77 +++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 52 deletions(-) (limited to 'src/client/shell/input.rs') diff --git a/src/client/shell/input.rs b/src/client/shell/input.rs index 9b5fff21..dd7bf87d 100644 --- a/src/client/shell/input.rs +++ b/src/client/shell/input.rs @@ -128,7 +128,9 @@ impl ClientShellState { } fn prepare_committed_text(&mut self, text: &str, outcome: &mut ClientShellInput) -> bool { - if self.insert_copy_search_text(text) { + if !(self.mode == ClientShellMode::Navigate && self.workspace_preview_action_blocked()) + && self.insert_copy_search_text(text) + { outcome.repaint = true; return true; } @@ -425,7 +427,12 @@ impl ClientShellState { } pub(super) fn modal_paste_target_active(&self) -> bool { - if self.popup_pending || self.popup_input_target().is_some() { + if self.popup_pending + || self.popup_input_target().is_some() + || (self.overlay.is_none() + && self.mode == ClientShellMode::Navigate + && self.workspace_preview_action_blocked()) + { return false; } if self @@ -655,6 +662,22 @@ impl ClientShellState { return; } + let (code, modifiers) = crate::config::normalize_key_combo((key.code, key.modifiers)); + if code == KeyCode::Enter && modifiers.is_empty() { + self.accept_navigate_workspace(outcome); + return; + } + if self.workspace_preview_action_blocked() { + self.push_endpoint_notice( + ClientEndpointNoticeKind::Rejected, + "navigate_endpoint_inactive", + "Confirm workspace first", + "Select an available workspace and press Enter before using workspace or pane actions", + ); + outcome.repaint = true; + return; + } + if let Some(index) = ('1'..='9').position(|digit| { crate::config::terminal_key_matches_combo( key, @@ -678,24 +701,8 @@ impl ClientShellState { return; } - let (code, modifiers) = crate::config::normalize_key_combo((key.code, key.modifiers)); if modifiers.is_empty() { match code { - KeyCode::Enter => { - let selected = self.navigate_workspace_id.clone(); - self.mode = ClientShellMode::Terminal; - self.navigate_workspace_id = None; - if let Some(workspace_id) = selected { - self.push_endpoint_method( - crate::api::schema::Method::WorkspaceFocus( - crate::api::schema::WorkspaceTarget { workspace_id }, - ), - outcome, - ); - } - outcome.repaint = true; - return; - } KeyCode::Tab => { self.record_navigate_binding( KeybindMatch::Action(KeybindAction::CyclePaneNext), @@ -804,7 +811,6 @@ impl ClientShellState { if !self.indexed_navigation_target_exists(&binding) { return; } - if let KeybindMatch::Action(KeybindAction::CyclePaneNext) = binding { self.cycle_pane(false, outcome); } else if let KeybindMatch::Action(KeybindAction::CyclePanePrevious) = binding { @@ -862,39 +868,6 @@ impl ClientShellState { } } - fn move_navigate_workspace(&mut self, delta: isize) { - let Some(snapshot) = self.snapshot.as_deref() else { - return; - }; - let mobile = self.mobile_layout_active(); - let entries = self.navigation_workspace_entries(snapshot); - if entries.is_empty() { - return; - } - let current = self - .navigate_workspace_id - .as_deref() - .and_then(|selected| { - entries - .iter() - .position(|entry| snapshot.workspaces[entry.index].workspace_id == selected) - }) - .unwrap_or(0); - let next = if mobile { - (current as isize + delta).clamp(0, entries.len().saturating_sub(1) as isize) as usize - } else { - (current as isize + delta).rem_euclid(entries.len() as isize) as usize - }; - let workspace_id = snapshot.workspaces[entries[next].index] - .workspace_id - .clone(); - self.navigate_workspace_id = Some(workspace_id.clone()); - self.reveal_mobile_workspace = mobile; - if !mobile { - self.reveal_workspace(&workspace_id); - } - } - fn cycle_pane(&mut self, reverse: bool, outcome: &mut ClientShellInput) { let Some(snapshot) = self.snapshot.as_deref() else { return; -- cgit v1.2.3