Fix duplicate SshProject's in Remote Projects menu (#20271)

Closes #20269

Release Notes:

- Changes SshConnection to use a BTreeSet of SshProject's instead of a
Vec of SshProject's in order to remove duplicate remote projects from
"settings.json" and the Remote Projects menu.
This commit is contained in:
AidanV 2024-11-05 20:31:57 -08:00 committed by GitHub
parent 38b1940251
commit c10c35ffda
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 19 additions and 10 deletions

View file

@ -1,3 +1,4 @@
use std::collections::BTreeSet;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
@ -173,7 +174,7 @@ impl ProjectPicker {
.as_mut() .as_mut()
.and_then(|connections| connections.get_mut(ix)) .and_then(|connections| connections.get_mut(ix))
{ {
server.projects.push(SshProject { paths }) server.projects.insert(SshProject { paths });
} }
} }
}); });
@ -784,7 +785,8 @@ impl RemoteServerProjects {
.end_hover_slot::<AnyElement>(Some( .end_hover_slot::<AnyElement>(Some(
div() div()
.mr_2() .mr_2()
.child( .child({
let project = project.clone();
// Right-margin to offset it from the Scrollbar // Right-margin to offset it from the Scrollbar
IconButton::new("remove-remote-project", IconName::TrashAlt) IconButton::new("remove-remote-project", IconName::TrashAlt)
.icon_size(IconSize::Small) .icon_size(IconSize::Small)
@ -792,9 +794,9 @@ impl RemoteServerProjects {
.size(ButtonSize::Large) .size(ButtonSize::Large)
.tooltip(|cx| Tooltip::text("Delete Remote Project", cx)) .tooltip(|cx| Tooltip::text("Delete Remote Project", cx))
.on_click(cx.listener(move |this, _, cx| { .on_click(cx.listener(move |this, _, cx| {
this.delete_ssh_project(server_ix, ix, cx) this.delete_ssh_project(server_ix, &project, cx)
})), }))
) })
.into_any_element(), .into_any_element(),
)), )),
) )
@ -823,14 +825,20 @@ impl RemoteServerProjects {
}); });
} }
fn delete_ssh_project(&mut self, server: usize, project: usize, cx: &mut ViewContext<Self>) { fn delete_ssh_project(
&mut self,
server: usize,
project: &SshProject,
cx: &mut ViewContext<Self>,
) {
let project = project.clone();
self.update_settings_file(cx, move |setting, _| { self.update_settings_file(cx, move |setting, _| {
if let Some(server) = setting if let Some(server) = setting
.ssh_connections .ssh_connections
.as_mut() .as_mut()
.and_then(|connections| connections.get_mut(server)) .and_then(|connections| connections.get_mut(server))
{ {
server.projects.remove(project); server.projects.remove(&project);
} }
}); });
} }
@ -848,7 +856,7 @@ impl RemoteServerProjects {
host: SharedString::from(connection_options.host), host: SharedString::from(connection_options.host),
username: connection_options.username, username: connection_options.username,
port: connection_options.port, port: connection_options.port,
projects: vec![], projects: BTreeSet::<SshProject>::new(),
nickname: None, nickname: None,
args: connection_options.args.unwrap_or_default(), args: connection_options.args.unwrap_or_default(),
upload_binary_over_ssh: None, upload_binary_over_ssh: None,

View file

@ -1,3 +1,4 @@
use std::collections::BTreeSet;
use std::{path::PathBuf, sync::Arc, time::Duration}; use std::{path::PathBuf, sync::Arc, time::Duration};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
@ -75,7 +76,7 @@ pub struct SshConnection {
#[serde(default)] #[serde(default)]
pub args: Vec<String>, pub args: Vec<String>,
#[serde(default)] #[serde(default)]
pub projects: Vec<SshProject>, pub projects: BTreeSet<SshProject>,
/// Name to use for this server in UI. /// Name to use for this server in UI.
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub nickname: Option<String>, pub nickname: Option<String>,
@ -101,7 +102,7 @@ impl From<SshConnection> for SshConnectionOptions {
} }
} }
#[derive(Clone, Default, Serialize, PartialEq, Deserialize, JsonSchema)] #[derive(Clone, Default, Serialize, PartialEq, Eq, PartialOrd, Ord, Deserialize, JsonSchema)]
pub struct SshProject { pub struct SshProject {
pub paths: Vec<String>, pub paths: Vec<String>,
} }