mirror of
https://github.com/rust-kotlin/ashell.git
synced 2026-10-03 16:00:18 +00:00
fix(app): 优化系统监控与会话选择,修复分屏 SFTP 及窗口激活问题 (#119)
This commit is contained in:
+1
-45
@@ -729,50 +729,6 @@ impl Ashell {
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.p_2()
|
||||
.rounded_md()
|
||||
.border_1()
|
||||
.border_color(if selected_index == 1 {
|
||||
_cx.theme().primary
|
||||
} else {
|
||||
_cx.theme().border
|
||||
})
|
||||
.bg(if selected_index == 1 {
|
||||
_cx.theme().tab_active
|
||||
} else {
|
||||
_cx.theme().muted
|
||||
})
|
||||
.cursor_pointer()
|
||||
.hover(|this| this.bg(_cx.theme().secondary))
|
||||
.on_mouse_down(
|
||||
MouseButton::Left,
|
||||
window.listener_for(&view, |this, _, window, cx| {
|
||||
this.active_dialog = None;
|
||||
window.close_dialog(cx);
|
||||
this.open_new_ssh_dialog(window, cx);
|
||||
cx.notify();
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(1.0))
|
||||
.font_weight(FontWeight::SEMIBOLD)
|
||||
.child(t!("new_connection")),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.917))
|
||||
.text_color(_cx.theme().muted_foreground)
|
||||
.child(t!("create_or_edit_ssh_session")),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.relative()
|
||||
@@ -790,7 +746,7 @@ impl Ashell {
|
||||
|(ix, session)| {
|
||||
let connect_id = session.id.clone();
|
||||
let is_selected =
|
||||
selected_index == ix + 2;
|
||||
selected_index == ix + 1;
|
||||
let name = session.name.clone();
|
||||
let detail = if session.protocol
|
||||
== "serial"
|
||||
|
||||
+25
-1
@@ -421,6 +421,7 @@ pub(crate) struct Ashell {
|
||||
pub(crate) search_bar_bounds: Option<Bounds<Pixels>>,
|
||||
|
||||
pub(crate) system_tab_id: Option<String>,
|
||||
pub(crate) last_applied_system_tab_id: Option<String>,
|
||||
pub(crate) sftp_handles: std::collections::HashMap<String, crate::sftp::SftpHandle>,
|
||||
|
||||
pub(crate) remote_sample_in_flight: bool,
|
||||
@@ -449,7 +450,6 @@ pub(crate) struct HoveredUrl {
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum SelectorEntry {
|
||||
Local,
|
||||
NewSsh,
|
||||
Saved(String),
|
||||
}
|
||||
|
||||
@@ -944,6 +944,7 @@ impl Ashell {
|
||||
search_bar_bounds: None,
|
||||
|
||||
system_tab_id: None,
|
||||
last_applied_system_tab_id: None,
|
||||
sftp_handles: std::collections::HashMap::new(),
|
||||
|
||||
remote_sample_in_flight: false,
|
||||
@@ -1283,7 +1284,11 @@ impl Ashell {
|
||||
}
|
||||
|
||||
fn on_window_activation_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let was_active = self.window_active;
|
||||
self.sync_window_activation(window);
|
||||
if !was_active && self.window_active {
|
||||
window.activate_window();
|
||||
}
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
@@ -1390,6 +1395,7 @@ impl Ashell {
|
||||
tab.disconnected_reason = None;
|
||||
}
|
||||
self.sync_sftp_path_from_terminal_title(&tab_id, cx);
|
||||
self.sync_sftp_to_active_tab();
|
||||
self.sync_system_tab_to_active_group();
|
||||
if self.system_tab_id.as_deref() == Some(tab_id.as_str()) {
|
||||
self.system_status = None;
|
||||
@@ -1488,6 +1494,12 @@ impl Ashell {
|
||||
if self.is_connected_system_tab(&tab_id) {
|
||||
self.remote_sample_in_flight = false;
|
||||
self.system_status = None;
|
||||
if self.last_applied_system_tab_id.as_deref() != Some(&tab_id) {
|
||||
self.last_applied_system_tab_id = Some(tab_id.clone());
|
||||
self.cpu_history.clear();
|
||||
self.net_rx_history.clear();
|
||||
self.net_tx_history.clear();
|
||||
}
|
||||
self.apply_system_snapshot(snapshot);
|
||||
}
|
||||
}
|
||||
@@ -1496,6 +1508,11 @@ impl Ashell {
|
||||
self.remote_sample_in_flight = false;
|
||||
self.system_status = Some(reason.clone().into());
|
||||
self.status = reason.into();
|
||||
self.last_applied_system_tab_id = Some(tab_id);
|
||||
self.system = SystemSnapshot::default();
|
||||
self.cpu_history.clear();
|
||||
self.net_rx_history.clear();
|
||||
self.net_tx_history.clear();
|
||||
}
|
||||
}
|
||||
BackendEvent::RemoteProcesses { tab_id, processes } => {
|
||||
@@ -1734,6 +1751,12 @@ impl Ashell {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if self.last_applied_system_tab_id.is_some() {
|
||||
self.last_applied_system_tab_id = None;
|
||||
self.cpu_history.clear();
|
||||
self.net_rx_history.clear();
|
||||
self.net_tx_history.clear();
|
||||
}
|
||||
let snapshot = self.system_sampler.sample();
|
||||
self.apply_system_snapshot(snapshot);
|
||||
return true;
|
||||
@@ -1760,6 +1783,7 @@ impl Ashell {
|
||||
self.cpu_history.clear();
|
||||
self.net_rx_history.clear();
|
||||
self.net_tx_history.clear();
|
||||
self.last_applied_system_tab_id = None;
|
||||
self.remote_sample_in_flight = false;
|
||||
self.remote_processes_in_flight = false;
|
||||
self.remote_processes.clear();
|
||||
|
||||
+262
-81
@@ -1884,10 +1884,26 @@ impl Ashell {
|
||||
};
|
||||
let mem_pct = self.system.mem_percent;
|
||||
let swap_pct = self.system.swap_percent;
|
||||
let mem_detail = self.system.mem_detail.clone();
|
||||
let swap_detail = self.system.swap_detail.clone();
|
||||
let net_rx = self.system.net_rx.clone();
|
||||
let net_tx = self.system.net_tx.clone();
|
||||
let mem_detail = if self.system.mem_detail.is_empty() {
|
||||
"-- / --".to_string()
|
||||
} else {
|
||||
self.system.mem_detail.clone()
|
||||
};
|
||||
let swap_detail = if self.system.swap_detail.is_empty() {
|
||||
"-- / --".to_string()
|
||||
} else {
|
||||
self.system.swap_detail.clone()
|
||||
};
|
||||
let net_rx = if self.system.net_rx.is_empty() {
|
||||
"--".to_string()
|
||||
} else {
|
||||
self.system.net_rx.clone()
|
||||
};
|
||||
let net_tx = if self.system.net_tx.is_empty() {
|
||||
"--".to_string()
|
||||
} else {
|
||||
self.system.net_tx.clone()
|
||||
};
|
||||
|
||||
let (disk_used, disk_total) = self.system.disks.iter().fold((0u64, 0u64), |(u, t), d| {
|
||||
(u + (d.total_bytes - d.available_bytes), t + d.total_bytes)
|
||||
@@ -2208,7 +2224,11 @@ impl Ashell {
|
||||
div()
|
||||
.text_size(ui_rems(0.833))
|
||||
.text_color(muted_fg)
|
||||
.child(format!("{:.0}%", disk_pct)),
|
||||
.child(if disk_total > 0 {
|
||||
format!("{:.0}%", disk_pct)
|
||||
} else {
|
||||
"--".to_string()
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
@@ -2222,40 +2242,72 @@ impl Ashell {
|
||||
.track_scroll(&self.disk_scroll_handle)
|
||||
.overflow_y_scroll()
|
||||
.size_full()
|
||||
.children(disks.iter().map(|disk| {
|
||||
let pct = if disk.total_bytes > 0 {
|
||||
(disk.total_bytes - disk.available_bytes) as f64
|
||||
/ disk.total_bytes as f64
|
||||
* 100.0
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let mount_short = disk.mount.clone();
|
||||
let mount_id = format!("disk-{}", mount_short);
|
||||
h_flex()
|
||||
.w_full()
|
||||
.items_center()
|
||||
.gap_1()
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.667))
|
||||
.text_color(muted_fg)
|
||||
.child(mount_short),
|
||||
)
|
||||
.child(
|
||||
Progress::new(mount_id)
|
||||
.value(pct as f32)
|
||||
.color(disk_color)
|
||||
.with_size(px(4.))
|
||||
.flex_1(),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.667))
|
||||
.text_color(muted_fg)
|
||||
.child(format!("{:.0}%", pct)),
|
||||
)
|
||||
})),
|
||||
.children(if disks.is_empty() {
|
||||
vec![
|
||||
h_flex()
|
||||
.w_full()
|
||||
.items_center()
|
||||
.gap_1()
|
||||
.child(
|
||||
div()
|
||||
.w(px(20.))
|
||||
.h(px(8.))
|
||||
.rounded_sm()
|
||||
.bg(cx.theme().skeleton),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex_1()
|
||||
.h(px(4.))
|
||||
.rounded_full()
|
||||
.bg(cx.theme().skeleton.opacity(0.4)),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w(px(22.))
|
||||
.h(px(8.))
|
||||
.rounded_sm()
|
||||
.bg(cx.theme().skeleton.opacity(0.7)),
|
||||
)
|
||||
.into_any_element(),
|
||||
]
|
||||
} else {
|
||||
disks.iter().map(|disk| {
|
||||
let pct = if disk.total_bytes > 0 {
|
||||
(disk.total_bytes - disk.available_bytes) as f64
|
||||
/ disk.total_bytes as f64
|
||||
* 100.0
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let mount_short = disk.mount.clone();
|
||||
let mount_id = format!("disk-{}", mount_short);
|
||||
h_flex()
|
||||
.w_full()
|
||||
.items_center()
|
||||
.gap_1()
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.667))
|
||||
.text_color(muted_fg)
|
||||
.child(mount_short),
|
||||
)
|
||||
.child(
|
||||
Progress::new(mount_id)
|
||||
.value(pct as f32)
|
||||
.color(disk_color)
|
||||
.with_size(px(4.))
|
||||
.flex_1(),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.667))
|
||||
.text_color(muted_fg)
|
||||
.child(format!("{:.0}%", pct)),
|
||||
)
|
||||
.into_any_element()
|
||||
}).collect()
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
@@ -2313,7 +2365,32 @@ impl Ashell {
|
||||
let disk_color = cx.theme().chart_5;
|
||||
let net_color = cx.theme().chart_4;
|
||||
let muted_fg = cx.theme().muted_foreground;
|
||||
let mem_detail = if self.system.mem_detail.is_empty() {
|
||||
"-- / --".to_string()
|
||||
} else {
|
||||
self.system.mem_detail.clone()
|
||||
};
|
||||
let swap_detail = if self.system.swap_detail.is_empty() {
|
||||
"-- / --".to_string()
|
||||
} else {
|
||||
self.system.swap_detail.clone()
|
||||
};
|
||||
let net_rx = if self.system.net_rx.is_empty() {
|
||||
"--".to_string()
|
||||
} else {
|
||||
self.system.net_rx.clone()
|
||||
};
|
||||
let net_tx = if self.system.net_tx.is_empty() {
|
||||
"--".to_string()
|
||||
} else {
|
||||
self.system.net_tx.clone()
|
||||
};
|
||||
let active_is_ssh = matches!(self.active_kind(), Some(TabKind::Ssh));
|
||||
let is_connecting_ssh = self
|
||||
.active_tab
|
||||
.as_ref()
|
||||
.and_then(|active_id| self.tabs.iter().find(|tab| tab.id == *active_id))
|
||||
.is_some_and(|tab| tab.kind == TabKind::Ssh && !tab.connected && tab.disconnected_reason.is_none());
|
||||
let (monitor_title, monitor_detail) = self
|
||||
.active_tab
|
||||
.as_ref()
|
||||
@@ -2323,6 +2400,8 @@ impl Ashell {
|
||||
.unwrap_or_else(|| (t!("system_info").to_string(), t!("live").to_string()));
|
||||
let status_color = if interactive {
|
||||
cx.theme().success
|
||||
} else if is_connecting_ssh {
|
||||
cx.theme().warning
|
||||
} else if active_is_ssh {
|
||||
cx.theme().danger
|
||||
} else {
|
||||
@@ -2448,7 +2527,7 @@ impl Ashell {
|
||||
div()
|
||||
.text_size(ui_rems(0.85))
|
||||
.text_color(muted_fg)
|
||||
.child(self.system.mem_detail.clone()),
|
||||
.child(mem_detail),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
@@ -2475,7 +2554,7 @@ impl Ashell {
|
||||
div()
|
||||
.text_size(ui_rems(0.85))
|
||||
.text_color(muted_fg)
|
||||
.child(self.system.swap_detail.clone()),
|
||||
.child(swap_detail),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
@@ -2514,49 +2593,146 @@ impl Ashell {
|
||||
div()
|
||||
.relative()
|
||||
.w_full()
|
||||
.h(px(90.))
|
||||
.child(
|
||||
v_flex()
|
||||
.id("sidebar-disk-scroll")
|
||||
.track_scroll(&self.disk_scroll_handle)
|
||||
.overflow_y_scroll()
|
||||
.max_h(px(90.))
|
||||
.size_full()
|
||||
.gap_2()
|
||||
.children(self.system.disks.iter().map(|disk| {
|
||||
let pct = if disk.total_bytes > 0 {
|
||||
(disk.total_bytes - disk.available_bytes) as f64
|
||||
/ disk.total_bytes as f64
|
||||
* 100.0
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let mount_short = disk.mount.clone();
|
||||
let mount_id = format!("sidebar-disk-{}", mount_short);
|
||||
v_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
h_flex()
|
||||
.justify_between()
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.75))
|
||||
.text_color(muted_fg)
|
||||
.child(mount_short),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.75))
|
||||
.text_color(muted_fg)
|
||||
.child(format!("{:.1}%", pct)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Progress::new(mount_id)
|
||||
.value(pct as f32)
|
||||
.color(disk_color)
|
||||
.with_size(px(4.))
|
||||
.w_full(),
|
||||
)
|
||||
})),
|
||||
.children(if self.system.disks.is_empty() {
|
||||
vec![
|
||||
v_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
h_flex()
|
||||
.justify_between()
|
||||
.items_center()
|
||||
.h(px(14.))
|
||||
.child(
|
||||
div()
|
||||
.w(px(44.))
|
||||
.h(px(10.))
|
||||
.rounded_sm()
|
||||
.bg(cx.theme().skeleton),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w(px(28.))
|
||||
.h(px(10.))
|
||||
.rounded_sm()
|
||||
.bg(cx.theme().skeleton.opacity(0.7)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.h(px(4.))
|
||||
.rounded_full()
|
||||
.bg(cx.theme().skeleton.opacity(0.4)),
|
||||
)
|
||||
.into_any_element(),
|
||||
v_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
h_flex()
|
||||
.justify_between()
|
||||
.items_center()
|
||||
.h(px(14.))
|
||||
.child(
|
||||
div()
|
||||
.w(px(64.))
|
||||
.h(px(10.))
|
||||
.rounded_sm()
|
||||
.bg(cx.theme().skeleton),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w(px(32.))
|
||||
.h(px(10.))
|
||||
.rounded_sm()
|
||||
.bg(cx.theme().skeleton.opacity(0.7)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.h(px(4.))
|
||||
.rounded_full()
|
||||
.bg(cx.theme().skeleton.opacity(0.4)),
|
||||
)
|
||||
.into_any_element(),
|
||||
v_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
h_flex()
|
||||
.justify_between()
|
||||
.items_center()
|
||||
.h(px(14.))
|
||||
.child(
|
||||
div()
|
||||
.w(px(36.))
|
||||
.h(px(10.))
|
||||
.rounded_sm()
|
||||
.bg(cx.theme().skeleton),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w(px(26.))
|
||||
.h(px(10.))
|
||||
.rounded_sm()
|
||||
.bg(cx.theme().skeleton.opacity(0.7)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w_full()
|
||||
.h(px(4.))
|
||||
.rounded_full()
|
||||
.bg(cx.theme().skeleton.opacity(0.4)),
|
||||
)
|
||||
.into_any_element(),
|
||||
]
|
||||
} else {
|
||||
self.system.disks.iter().map(|disk| {
|
||||
let pct = if disk.total_bytes > 0 {
|
||||
(disk.total_bytes - disk.available_bytes) as f64
|
||||
/ disk.total_bytes as f64
|
||||
* 100.0
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
let mount_short = disk.mount.clone();
|
||||
let mount_id = format!("sidebar-disk-{}", mount_short);
|
||||
v_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
h_flex()
|
||||
.justify_between()
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.75))
|
||||
.text_color(muted_fg)
|
||||
.child(mount_short),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.75))
|
||||
.text_color(muted_fg)
|
||||
.child(format!("{:.1}%", pct)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Progress::new(mount_id)
|
||||
.value(pct as f32)
|
||||
.color(disk_color)
|
||||
.with_size(px(4.))
|
||||
.w_full(),
|
||||
)
|
||||
.into_any_element()
|
||||
}).collect()
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
@@ -2621,7 +2797,7 @@ impl Ashell {
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.75))
|
||||
.child(self.system.net_rx.clone()),
|
||||
.child(net_rx),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
@@ -2639,7 +2815,7 @@ impl Ashell {
|
||||
.child(
|
||||
div()
|
||||
.text_size(ui_rems(0.75))
|
||||
.child(self.system.net_tx.clone()),
|
||||
.child(net_tx),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -5311,7 +5487,12 @@ impl Render for Ashell {
|
||||
}
|
||||
}
|
||||
|
||||
let has_ssh_session = self.active_ssh_session().is_some();
|
||||
let has_ssh_session = self.active_ssh_session().is_some()
|
||||
|| self
|
||||
.active_group
|
||||
.as_ref()
|
||||
.and_then(|id| self.tab_groups.iter().find(|g| &g.id == id))
|
||||
.is_some_and(|g| g.sftp.is_some());
|
||||
let is_monitor_bottom = self.config.monitoring_position() == "Bottom";
|
||||
let is_active_ssh_connected = self
|
||||
.active_tab
|
||||
|
||||
+121
-26
@@ -1267,7 +1267,7 @@ impl Ashell {
|
||||
}
|
||||
|
||||
pub(crate) fn selector_entries(&self) -> Vec<SelectorEntry> {
|
||||
let mut entries = vec![SelectorEntry::Local, SelectorEntry::NewSsh];
|
||||
let mut entries = vec![SelectorEntry::Local];
|
||||
entries.extend(
|
||||
self.config
|
||||
.sessions()
|
||||
@@ -1278,11 +1278,7 @@ impl Ashell {
|
||||
}
|
||||
|
||||
pub(crate) fn default_selector_index(&self) -> usize {
|
||||
if self.config.sessions().is_empty() {
|
||||
0
|
||||
} else {
|
||||
2
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
pub(crate) fn move_selector_selection(&mut self, delta: i32, cx: &mut Context<Self>) {
|
||||
@@ -1294,8 +1290,8 @@ impl Ashell {
|
||||
let next = (current + delta).clamp(0, entries.len() as i32 - 1) as usize;
|
||||
if next != self.selector_selection {
|
||||
self.selector_selection = next;
|
||||
if next >= 2 {
|
||||
self.selector_scroll_handle.scroll_to_item(next - 2);
|
||||
if next >= 1 {
|
||||
self.selector_scroll_handle.scroll_to_item(next - 1);
|
||||
}
|
||||
cx.notify();
|
||||
}
|
||||
@@ -1317,10 +1313,6 @@ impl Ashell {
|
||||
self.open_local(cx);
|
||||
window.close_dialog(cx);
|
||||
}
|
||||
SelectorEntry::NewSsh => {
|
||||
window.close_dialog(cx);
|
||||
self.open_new_ssh_dialog(window, cx);
|
||||
}
|
||||
SelectorEntry::Saved(session_id) => {
|
||||
self.connect_saved_session(session_id, window, cx);
|
||||
window.close_dialog(cx);
|
||||
@@ -2111,12 +2103,28 @@ impl Ashell {
|
||||
}
|
||||
|
||||
pub(crate) fn active_ssh_session(&self) -> Option<(String, Session)> {
|
||||
let active_id = self.active_tab.as_ref()?;
|
||||
let tab = self.tabs.iter().find(|tab| &tab.id == active_id)?;
|
||||
if !tab.connected {
|
||||
return None;
|
||||
if let Some(active_id) = self.active_tab.as_ref() {
|
||||
if let Some(tab) = self.tabs.iter().find(|tab| &tab.id == active_id) {
|
||||
if tab.kind == TabKind::Ssh {
|
||||
if let Some(session) = tab.session.clone() {
|
||||
return Some((tab.id.clone(), session));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some((tab.id.clone(), tab.session.clone()?))
|
||||
if let Some(group_id) = self.active_group.as_ref() {
|
||||
if let Some(group) = self.tab_groups.iter().find(|g| &g.id == group_id) {
|
||||
let pane_tab_ids = group.pane_root.tab_ids();
|
||||
for tab in &self.tabs {
|
||||
if pane_tab_ids.contains(&tab.id.as_str()) && tab.kind == TabKind::Ssh {
|
||||
if let Some(session) = tab.session.clone() {
|
||||
return Some((tab.id.clone(), session));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn active_session_id(&self) -> Option<&str> {
|
||||
@@ -2536,7 +2544,7 @@ impl Ashell {
|
||||
let Some(group_id) = self.active_group.clone() else {
|
||||
return;
|
||||
};
|
||||
let target = self.active_tab.as_ref().and_then(|active_id| {
|
||||
let mut target = self.active_tab.as_ref().and_then(|active_id| {
|
||||
self.tabs
|
||||
.iter()
|
||||
.find(|tab| {
|
||||
@@ -2544,12 +2552,49 @@ impl Ashell {
|
||||
})
|
||||
.and_then(|tab| tab.session.clone().map(|session| (tab.id.clone(), session)))
|
||||
});
|
||||
let target_tab_id = target.as_ref().map(|(tab_id, _)| tab_id.as_str());
|
||||
|
||||
if target.is_none() {
|
||||
if let Some(group) = self.tab_groups.iter().find(|g| g.id == group_id) {
|
||||
let pane_tab_ids = group.pane_root.tab_ids();
|
||||
target = self
|
||||
.tabs
|
||||
.iter()
|
||||
.find(|tab| {
|
||||
pane_tab_ids.contains(&tab.id.as_str())
|
||||
&& tab.kind == TabKind::Ssh
|
||||
&& (tab.connected || force)
|
||||
})
|
||||
.and_then(|tab| tab.session.clone().map(|session| (tab.id.clone(), session)));
|
||||
}
|
||||
}
|
||||
|
||||
let current_tab_id = self
|
||||
.tab_groups
|
||||
.iter()
|
||||
.find(|group| group.id == group_id)
|
||||
.and_then(|group| group.sftp_tab_id.clone());
|
||||
|
||||
let group_has_ssh = self
|
||||
.tab_groups
|
||||
.iter()
|
||||
.find(|g| g.id == group_id)
|
||||
.map(|g| {
|
||||
let pane_tab_ids = g.pane_root.tab_ids();
|
||||
self.tabs
|
||||
.iter()
|
||||
.any(|t| pane_tab_ids.contains(&t.id.as_str()) && t.kind == TabKind::Ssh)
|
||||
})
|
||||
.unwrap_or(false);
|
||||
|
||||
if target.is_none()
|
||||
&& !force
|
||||
&& group_has_ssh
|
||||
&& (self.sftp_handles.contains_key(&group_id) || current_tab_id.is_some())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
let target_tab_id = target.as_ref().map(|(tab_id, _)| tab_id.as_str());
|
||||
let current_session_id = current_tab_id.as_ref().and_then(|tab_id| {
|
||||
self.tabs
|
||||
.iter()
|
||||
@@ -2560,7 +2605,7 @@ impl Ashell {
|
||||
let target_session_id = target.as_ref().map(|(_, session)| session.id.as_str());
|
||||
|
||||
if !force {
|
||||
if current_tab_id.as_deref() == target_tab_id {
|
||||
if current_tab_id.as_deref() == target_tab_id && target_tab_id.is_some() {
|
||||
return;
|
||||
}
|
||||
if current_session_id.as_deref() == target_session_id
|
||||
@@ -2605,12 +2650,51 @@ impl Ashell {
|
||||
}
|
||||
|
||||
pub(crate) fn sync_system_tab_to_active_group(&mut self) {
|
||||
let active_ssh_tab = self.active_tab.as_ref().and_then(|id| {
|
||||
self.tabs
|
||||
.iter()
|
||||
.find(|tab| tab.id == *id && tab.kind == TabKind::Ssh)
|
||||
let active_group = self.active_group.as_ref().and_then(|group_id| {
|
||||
self.tab_groups.iter().find(|group| &group.id == group_id)
|
||||
});
|
||||
let new_id = active_ssh_tab.map(|tab| tab.id.clone());
|
||||
|
||||
if let Some(current_sys_id) = &self.system_tab_id {
|
||||
if let Some(group) = active_group {
|
||||
let pane_tab_ids = group.pane_root.tab_ids();
|
||||
if pane_tab_ids.contains(¤t_sys_id.as_str()) {
|
||||
if self
|
||||
.tabs
|
||||
.iter()
|
||||
.any(|t| &t.id == current_sys_id && t.kind == TabKind::Ssh && t.connected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let new_id = self
|
||||
.active_tab
|
||||
.as_ref()
|
||||
.and_then(|id| {
|
||||
self.tabs
|
||||
.iter()
|
||||
.find(|tab| tab.id == *id && tab.kind == TabKind::Ssh)
|
||||
.map(|tab| tab.id.clone())
|
||||
})
|
||||
.or_else(|| {
|
||||
active_group.and_then(|group| {
|
||||
let pane_tab_ids = group.pane_root.tab_ids();
|
||||
self.tabs
|
||||
.iter()
|
||||
.find(|tab| {
|
||||
pane_tab_ids.contains(&tab.id.as_str())
|
||||
&& tab.kind == TabKind::Ssh
|
||||
&& tab.connected
|
||||
})
|
||||
.map(|tab| tab.id.clone())
|
||||
})
|
||||
});
|
||||
|
||||
let active_ssh_tab = new_id
|
||||
.as_ref()
|
||||
.and_then(|id| self.tabs.iter().find(|tab| &tab.id == id && tab.kind == TabKind::Ssh));
|
||||
let active_ssh_status = active_ssh_tab.and_then(|tab| {
|
||||
(!tab.connected).then(|| {
|
||||
tab.disconnected_reason
|
||||
@@ -2621,13 +2705,24 @@ impl Ashell {
|
||||
|
||||
if self.system_tab_id != new_id {
|
||||
self.system_tab_id = new_id;
|
||||
self.reset_system_monitor_state();
|
||||
self.remote_sample_in_flight = false;
|
||||
self.remote_processes_in_flight = false;
|
||||
self.remote_ports_in_flight = false;
|
||||
|
||||
if let Some(status) = active_ssh_status {
|
||||
self.system_status = Some(status.clone().into());
|
||||
self.remote_process_status = Some(status.into());
|
||||
self.system = crate::system::SystemSnapshot::default();
|
||||
self.cpu_history.clear();
|
||||
self.net_rx_history.clear();
|
||||
self.net_tx_history.clear();
|
||||
self.remote_processes.clear();
|
||||
self.remote_ports.clear();
|
||||
self.last_applied_system_tab_id = self.system_tab_id.clone();
|
||||
} else {
|
||||
self.system_status = None;
|
||||
}
|
||||
|
||||
self.request_active_system_snapshot();
|
||||
if self.active_dialog == Some(crate::app::DialogKind::Processes) {
|
||||
self.request_active_process_snapshot();
|
||||
|
||||
Reference in New Issue
Block a user