refactor: remove sync_usage option, enhance SSH connection error messages
This commit is contained in:
+2
-9
@@ -13,7 +13,6 @@ pub enum SettingsField {
|
|||||||
S3Bucket,
|
S3Bucket,
|
||||||
S3AccessKey,
|
S3AccessKey,
|
||||||
S3SecretKey,
|
S3SecretKey,
|
||||||
SyncUsage,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SettingsField {
|
impl SettingsField {
|
||||||
@@ -37,7 +36,6 @@ impl SettingsField {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fields.push(SettingsField::SyncUsage);
|
|
||||||
fields
|
fields
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,12 +51,11 @@ impl SettingsField {
|
|||||||
Self::S3Bucket => "Bucket",
|
Self::S3Bucket => "Bucket",
|
||||||
Self::S3AccessKey => "Access Key",
|
Self::S3AccessKey => "Access Key",
|
||||||
Self::S3SecretKey => "Secret Key",
|
Self::S3SecretKey => "Secret Key",
|
||||||
Self::SyncUsage => "Sync Usage",
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_toggle(self) -> bool {
|
pub fn is_toggle(self) -> bool {
|
||||||
matches!(self, Self::Backend | Self::SyncUsage)
|
matches!(self, Self::Backend)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_text(self) -> bool {
|
pub fn is_text(self) -> bool {
|
||||||
@@ -78,7 +75,6 @@ pub struct SettingsState {
|
|||||||
pub s3_bucket: String,
|
pub s3_bucket: String,
|
||||||
pub s3_access_key: String,
|
pub s3_access_key: String,
|
||||||
pub s3_secret_key: String,
|
pub s3_secret_key: String,
|
||||||
pub sync_usage: bool,
|
|
||||||
pub active: SettingsField,
|
pub active: SettingsField,
|
||||||
pub cursor: usize,
|
pub cursor: usize,
|
||||||
}
|
}
|
||||||
@@ -148,7 +144,6 @@ impl Default for SettingsState {
|
|||||||
s3_bucket: String::new(),
|
s3_bucket: String::new(),
|
||||||
s3_access_key: String::new(),
|
s3_access_key: String::new(),
|
||||||
s3_secret_key: String::new(),
|
s3_secret_key: String::new(),
|
||||||
sync_usage: false,
|
|
||||||
active: SettingsField::SyncPassword,
|
active: SettingsField::SyncPassword,
|
||||||
cursor: 0,
|
cursor: 0,
|
||||||
}
|
}
|
||||||
@@ -225,7 +220,6 @@ impl App {
|
|||||||
self.config.settings.s3_access_key.clone().unwrap_or_default();
|
self.config.settings.s3_access_key.clone().unwrap_or_default();
|
||||||
self.session.settings.s3_secret_key =
|
self.session.settings.s3_secret_key =
|
||||||
self.config.settings.s3_secret_key.clone().unwrap_or_default();
|
self.config.settings.s3_secret_key.clone().unwrap_or_default();
|
||||||
self.session.settings.sync_usage = self.config.settings.sync_usage_count;
|
|
||||||
self.session.settings.active = SettingsField::SyncPassword;
|
self.session.settings.active = SettingsField::SyncPassword;
|
||||||
self.session.settings.cursor = char_len(self.session.settings.active_text());
|
self.session.settings.cursor = char_len(self.session.settings.active_text());
|
||||||
self.session.mode = Mode::Settings;
|
self.session.mode = Mode::Settings;
|
||||||
@@ -259,7 +253,6 @@ impl App {
|
|||||||
} else {
|
} else {
|
||||||
Some(s3_sk)
|
Some(s3_sk)
|
||||||
};
|
};
|
||||||
self.config.settings.sync_usage_count = self.session.settings.sync_usage;
|
|
||||||
self.config.save()?;
|
self.config.save()?;
|
||||||
self.session.mode = Mode::Home;
|
self.session.mode = Mode::Home;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -64,8 +64,6 @@ pub struct Settings {
|
|||||||
pub s3_bucket: Option<String>,
|
pub s3_bucket: Option<String>,
|
||||||
pub s3_access_key: Option<String>,
|
pub s3_access_key: Option<String>,
|
||||||
pub s3_secret_key: Option<String>,
|
pub s3_secret_key: Option<String>,
|
||||||
#[serde(default)]
|
|
||||||
pub sync_usage_count: bool,
|
|
||||||
pub sync_password: Option<String>,
|
pub sync_password: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+33
-2
@@ -1,9 +1,38 @@
|
|||||||
use crate::config::{ConnectionType, CredentialEntry, SshellConfig};
|
use crate::config::{ConnectionType, CredentialEntry, SshellConfig, find_binary};
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use tempfile::NamedTempFile;
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
|
fn require_binary(name: &str) -> Result<()> {
|
||||||
|
if find_binary(name).is_some() {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let hint = match name {
|
||||||
|
"ssh" => "\n\
|
||||||
|
sshell requires `ssh` to connect via SSH.\n\
|
||||||
|
\n\
|
||||||
|
Install it with:\n\
|
||||||
|
macOS: pre-installed (or: xcode-select --install)\n\
|
||||||
|
Debian: sudo apt install openssh-client\n\
|
||||||
|
Arch: sudo pacman -S openssh\n\
|
||||||
|
Fedora: sudo dnf install openssh-clients\n\
|
||||||
|
Windows: Settings → Apps → Optional Features → OpenSSH Client"
|
||||||
|
,
|
||||||
|
"sshpass" => "\n\
|
||||||
|
Password-based SSH login requires `sshpass`.\n\
|
||||||
|
Consider switching to private-key auth instead, or install it:\n\
|
||||||
|
macOS: brew install hudochenkov/sshpass/sshpass\n\
|
||||||
|
Debian: sudo apt install sshpass\n\
|
||||||
|
Arch: sudo pacman -S sshpass\n\
|
||||||
|
Fedora: sudo dnf install sshpass\n\
|
||||||
|
Windows: not available — use private-key auth"
|
||||||
|
,
|
||||||
|
_ => "",
|
||||||
|
};
|
||||||
|
bail!("command not found: `{name}`{hint}");
|
||||||
|
}
|
||||||
|
|
||||||
pub fn connect(name: &str, cfg: &SshellConfig) -> Result<()> {
|
pub fn connect(name: &str, cfg: &SshellConfig) -> Result<()> {
|
||||||
let profile = cfg
|
let profile = cfg
|
||||||
.connections
|
.connections
|
||||||
@@ -41,8 +70,10 @@ fn connect_ssh(
|
|||||||
if auth_ref.is_empty() {
|
if auth_ref.is_empty() {
|
||||||
bail!("this connection has no credential; edit it and set password or private key");
|
bail!("this connection has no credential; edit it and set password or private key");
|
||||||
}
|
}
|
||||||
|
require_binary("ssh")?;
|
||||||
match cfg.credential(auth_ref) {
|
match cfg.credential(auth_ref) {
|
||||||
Some(CredentialEntry::Password { value, .. }) => {
|
Some(CredentialEntry::Password { value, .. }) => {
|
||||||
|
require_binary("sshpass")?;
|
||||||
let args = vec![
|
let args = vec![
|
||||||
"ssh".to_string(),
|
"ssh".to_string(),
|
||||||
"-o".to_string(),
|
"-o".to_string(),
|
||||||
@@ -87,7 +118,7 @@ fn run_sshpass(args: &[String], password: &str) -> Result<()> {
|
|||||||
.args(args)
|
.args(args)
|
||||||
.env("SSHPASS", password)
|
.env("SSHPASS", password)
|
||||||
.status()
|
.status()
|
||||||
.context("failed to run sshpass — is it installed?")?;
|
.context("failed to run sshpass")?;
|
||||||
std::process::exit(status.code().unwrap_or(1));
|
std::process::exit(status.code().unwrap_or(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-8
@@ -60,9 +60,6 @@ pub(crate) fn build_sync_payload(
|
|||||||
sync_password: Option<&str>,
|
sync_password: Option<&str>,
|
||||||
) -> Result<toml::Value> {
|
) -> Result<toml::Value> {
|
||||||
let mut payload = cfg.clone();
|
let mut payload = cfg.clone();
|
||||||
payload.settings.sync_password = None;
|
|
||||||
payload.settings.webdav_password = None;
|
|
||||||
payload.settings.s3_secret_key = None;
|
|
||||||
|
|
||||||
let synced_refs: Vec<String> = payload
|
let synced_refs: Vec<String> = payload
|
||||||
.connections
|
.connections
|
||||||
@@ -90,14 +87,10 @@ pub(crate) fn build_sync_payload(
|
|||||||
"version".to_string(),
|
"version".to_string(),
|
||||||
toml::Value::Integer(payload.version as i64),
|
toml::Value::Integer(payload.version as i64),
|
||||||
);
|
);
|
||||||
table.insert("settings".to_string(), to_toml_value(&payload.settings)?);
|
|
||||||
|
|
||||||
let mut conns = toml::map::Map::new();
|
let mut conns = toml::map::Map::new();
|
||||||
for (name, profile) in &mut payload.connections {
|
for (name, profile) in &mut payload.connections {
|
||||||
profile.local_tags.clear();
|
profile.local_tags.clear();
|
||||||
if !payload.settings.sync_usage_count {
|
profile.usage_count = 0;
|
||||||
profile.usage_count = 0;
|
|
||||||
}
|
|
||||||
match &mut profile.kind {
|
match &mut profile.kind {
|
||||||
ConnectionType::Shell {
|
ConnectionType::Shell {
|
||||||
auth_ref,
|
auth_ref,
|
||||||
|
|||||||
+2
-12
@@ -1,7 +1,7 @@
|
|||||||
use crate::app::{App, FormAction, Mode, SettingsField, SettingsState, char_len};
|
use crate::app::{App, FormAction, Mode, SettingsField, SettingsState, char_len};
|
||||||
use crate::config::SyncBackend;
|
use crate::config::SyncBackend;
|
||||||
use crate::ui::component::{FormRow, badge_span};
|
use crate::ui::component::{FormRow, badge_span};
|
||||||
use crate::ui::{ACCENT, GREEN, ORANGE, PURPLE, RED};
|
use crate::ui::{ACCENT, ORANGE, PURPLE};
|
||||||
|
|
||||||
use super::{View, handle_form_nav};
|
use super::{View, handle_form_nav};
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ impl View for SettingsView {
|
|||||||
let active = settings.active == field;
|
let active = settings.active == field;
|
||||||
let label = field.label().to_string();
|
let label = field.label().to_string();
|
||||||
|
|
||||||
if i == 2 || matches!(field, SettingsField::SyncUsage) {
|
if i == 2 {
|
||||||
rows.push(FormRow::Separator);
|
rows.push(FormRow::Separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,13 +42,6 @@ impl View for SettingsView {
|
|||||||
SyncBackend::Webdav => badge_span("WebDAV", ORANGE),
|
SyncBackend::Webdav => badge_span("WebDAV", ORANGE),
|
||||||
SyncBackend::S3 => badge_span("S3", PURPLE),
|
SyncBackend::S3 => badge_span("S3", PURPLE),
|
||||||
},
|
},
|
||||||
SettingsField::SyncUsage => {
|
|
||||||
if settings.sync_usage {
|
|
||||||
badge_span("Yes", GREEN)
|
|
||||||
} else {
|
|
||||||
badge_span("No", RED)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
rows.push(FormRow::Toggle {
|
rows.push(FormRow::Toggle {
|
||||||
@@ -131,9 +124,6 @@ fn settings_toggle(settings: &mut SettingsState) {
|
|||||||
};
|
};
|
||||||
settings.ensure_active_visible();
|
settings.ensure_active_visible();
|
||||||
}
|
}
|
||||||
SettingsField::SyncUsage => {
|
|
||||||
settings.sync_usage = !settings.sync_usage;
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user