mirror of
https://github.com/rust-kotlin/ashell.git
synced 2026-09-22 08:01:00 +00:00
fix: retry connection in existing tab and perfectly detect graceful ssh exit
This commit is contained in:
+11
-1
@@ -115,7 +115,8 @@ async fn run_ssh(
|
||||
tab_id: tab_id.clone(),
|
||||
});
|
||||
|
||||
let mut exit_reason = "ssh session closed".to_string();
|
||||
let mut exit_reason = "ssh connection lost (unknown)".to_string();
|
||||
let mut is_graceful_close = false;
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
@@ -132,6 +133,7 @@ async fn run_ssh(
|
||||
}
|
||||
Some(BackendCommand::Close) | None => {
|
||||
let _ = channel.eof().await;
|
||||
exit_reason = "ssh session closed".to_string();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -144,7 +146,15 @@ async fn run_ssh(
|
||||
bytes: data.to_vec(),
|
||||
});
|
||||
}
|
||||
Some(ChannelMsg::ExitStatus { exit_status: _ }) => {
|
||||
is_graceful_close = true;
|
||||
}
|
||||
Some(ChannelMsg::Close) => {
|
||||
if is_graceful_close {
|
||||
exit_reason = "ssh session closed".to_string();
|
||||
} else {
|
||||
exit_reason = "ssh connection lost (abrupt close)".to_string();
|
||||
}
|
||||
break;
|
||||
}
|
||||
None => {
|
||||
|
||||
+45
-9
@@ -431,17 +431,53 @@ impl Ashell {
|
||||
return;
|
||||
};
|
||||
|
||||
// Close old backend
|
||||
self.tabs[ix].backend.send(BackendCommand::Close);
|
||||
self.tabs.remove(ix);
|
||||
if self.active_tab.as_deref() == Some(progress.tab_id.as_str()) {
|
||||
self.active_tab = self
|
||||
.tabs
|
||||
.get(ix)
|
||||
.or_else(|| self.tabs.get(ix.saturating_sub(1)))
|
||||
.map(|tab| tab.id.clone());
|
||||
|
||||
// Spawn new backend
|
||||
let backend = ssh::spawn_ssh_terminal(
|
||||
self.runtime.handle(),
|
||||
progress.tab_id.clone(),
|
||||
session.clone(),
|
||||
DEFAULT_COLS,
|
||||
DEFAULT_ROWS,
|
||||
self.events_tx.clone(),
|
||||
);
|
||||
|
||||
// Replace tab state in-place to reuse the UI component
|
||||
self.tabs[ix] = TerminalTab::new_ssh(
|
||||
progress.tab_id.clone(),
|
||||
&session,
|
||||
backend,
|
||||
self.events_tx.clone(),
|
||||
);
|
||||
|
||||
// Restart SFTP if applicable
|
||||
if let Some(group) = self.tab_groups.iter_mut().find(|g| g.pane_root.contains(&progress.tab_id)) {
|
||||
if let Some(old_handle) = self.sftp_handles.remove(&group.id) {
|
||||
old_handle.close();
|
||||
}
|
||||
let sftp_handle = crate::sftp::spawn_sftp(
|
||||
self.runtime.handle(),
|
||||
group.id.clone(),
|
||||
session.clone(),
|
||||
self.events_tx.clone(),
|
||||
);
|
||||
self.sftp_handles.insert(group.id.clone(), sftp_handle);
|
||||
|
||||
if let Some(sftp) = group.sftp.as_mut() {
|
||||
sftp.status = rust_i18n::t!("sftp_connecting").to_string();
|
||||
}
|
||||
}
|
||||
self.connection_progress = None;
|
||||
self.open_ssh_session(session, cx);
|
||||
|
||||
self.connection_progress = Some(ConnectionProgress {
|
||||
tab_id: progress.tab_id.clone(),
|
||||
title: t!("connecting").into(),
|
||||
lines: vec![t!("starting_connection").into()],
|
||||
failed: false,
|
||||
});
|
||||
self.status = "ssh tab retrying".into();
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub(crate) fn cancel_connection_progress(&mut self, cx: &mut Context<Self>) {
|
||||
|
||||
Reference in New Issue
Block a user