mirror of
https://github.com/veeso/termscp.git
synced 2026-09-26 05:51:20 -07:00
@@ -53,6 +53,12 @@ Released on FIXME:
|
|||||||
- **Tui-realm migration**:
|
- **Tui-realm migration**:
|
||||||
- migrated application to tui-realm 1.x
|
- migrated application to tui-realm 1.x
|
||||||
- Improved application performance
|
- Improved application performance
|
||||||
|
- **SSH Config**
|
||||||
|
- Added `ssh config` parameter in configuration
|
||||||
|
- It is now possible to specify the ssh configuration file to use
|
||||||
|
- The supported parameters are described at <https://github.com/veeso/ssh2-config>.
|
||||||
|
- If the field is left empty, **no file will be loaded**.
|
||||||
|
- **By default, no file will be used**.
|
||||||
- Dependencies:
|
- Dependencies:
|
||||||
- Updated `tui-realm` to `1.3.0`
|
- Updated `tui-realm` to `1.3.0`
|
||||||
- Updated `tui-realm-stdlib` to `1.1.4`
|
- Updated `tui-realm-stdlib` to `1.1.4`
|
||||||
|
|||||||
@@ -308,6 +308,7 @@ These parameters can be changed:
|
|||||||
- **Local File formatter syntax**: syntax to display file info for each file in the local explorer. See [File explorer format](#file-explorer-format)
|
- **Local File formatter syntax**: syntax to display file info for each file in the local explorer. See [File explorer format](#file-explorer-format)
|
||||||
- **Enable notifications?**: If set to `Yes`, notifications will be displayed.
|
- **Enable notifications?**: If set to `Yes`, notifications will be displayed.
|
||||||
- **Notifications: minimum transfer size**: if transfer size is greater or equal than the specified value, notifications for transfer will be displayed. The accepted values are in format `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
- **Notifications: minimum transfer size**: if transfer size is greater or equal than the specified value, notifications for transfer will be displayed. The accepted values are in format `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
||||||
|
- **SSH configuration path**: Set SSH configuration file to use when connecting to a SCP/SFTP server. If unset (empty) no file will be used. You can specify a path starting with `~` to indicate the home path (e.g. `~/.ssh/config`)
|
||||||
|
|
||||||
### SSH Key Storage 🔐
|
### SSH Key Storage 🔐
|
||||||
|
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ Estos parámetros se pueden cambiar:
|
|||||||
- **Local File formatter syntax**: sintaxis para mostrar información de archivo para cada archivo en el explorador local. Consulte [Formato del explorador de archivos](#formato-del-explorador-de-archivos).
|
- **Local File formatter syntax**: sintaxis para mostrar información de archivo para cada archivo en el explorador local. Consulte [Formato del explorador de archivos](#formato-del-explorador-de-archivos).
|
||||||
- **Enable notifications?**: Si se establece en "Sí", se mostrarán las notificaciones.
|
- **Enable notifications?**: Si se establece en "Sí", se mostrarán las notificaciones.
|
||||||
- **Notifications: minimum transfer size**: si el tamaño de la transferencia es mayor o igual que el valor especificado, se mostrarán notificaciones de transferencia. Los valores aceptados están en formato `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
- **Notifications: minimum transfer size**: si el tamaño de la transferencia es mayor o igual que el valor especificado, se mostrarán notificaciones de transferencia. Los valores aceptados están en formato `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
||||||
|
- **SSH configuration path**: Configure el archivo de configuración SSH para usar al conectarse a un servidor SCP / SFTP. Si no se configura (está vacío), no se utilizará ningún archivo. Puede especificar una ruta que comience con `~` para indicar la ruta de inicio (por ejemplo, `~/.ssh/config`)
|
||||||
|
|
||||||
### SSH Key Storage 🔐
|
### SSH Key Storage 🔐
|
||||||
|
|
||||||
|
|||||||
@@ -305,6 +305,7 @@ Ces paramètres peuvent être modifiés :
|
|||||||
- **Local File formatter syntax**: syntaxe pour afficher les informations de fichier pour chaque fichier dans l'explorateur local. Voir [File explorer format](#format-de-lexplorateur-de-fichiers)
|
- **Local File formatter syntax**: syntaxe pour afficher les informations de fichier pour chaque fichier dans l'explorateur local. Voir [File explorer format](#format-de-lexplorateur-de-fichiers)
|
||||||
- **Enable notifications?**: S'il est défini sur `Yes`, les notifications seront affichées.
|
- **Enable notifications?**: S'il est défini sur `Yes`, les notifications seront affichées.
|
||||||
- **Notifications: minimum transfer size**: si la taille du transfert est supérieure ou égale à la valeur spécifiée, les notifications de transfert seront affichées. Les valeurs acceptées sont au format `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
- **Notifications: minimum transfer size**: si la taille du transfert est supérieure ou égale à la valeur spécifiée, les notifications de transfert seront affichées. Les valeurs acceptées sont au format `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
||||||
|
- **SSH configuration path** : définissez le fichier de configuration SSH à utiliser lors de la connexion à un serveur SCP/SFTP. S'il n'est pas défini (vide), aucun fichier ne sera utilisé. Vous pouvez spécifier un chemin commençant par `~` pour indiquer le chemin d'accueil (par exemple `~/.ssh/config`)
|
||||||
|
|
||||||
### SSH Key Storage 🔐
|
### SSH Key Storage 🔐
|
||||||
|
|
||||||
|
|||||||
@@ -303,6 +303,7 @@ Questi parametri possono essere impostati:
|
|||||||
- **Local File formatter syntax**: La formattazione da usare per formattare i file sull'explorer locale. Vedi [File explorer format](#file-explorer-format)
|
- **Local File formatter syntax**: La formattazione da usare per formattare i file sull'explorer locale. Vedi [File explorer format](#file-explorer-format)
|
||||||
- **Enable notifications?**: Se impostato a `yes`, le notifiche desktop saranno abilitate.
|
- **Enable notifications?**: Se impostato a `yes`, le notifiche desktop saranno abilitate.
|
||||||
- **Notifications: minimum transfer size**: se la dimensione di un trasferimento supera o è uguale al valore impostato, al termine del trasferimento riceverai una notifica desktop (se queste sono abilitate). Il formato del valore dev'essere `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
- **Notifications: minimum transfer size**: se la dimensione di un trasferimento supera o è uguale al valore impostato, al termine del trasferimento riceverai una notifica desktop (se queste sono abilitate). Il formato del valore dev'essere `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
||||||
|
- **SSH configuration path**: Imposta il percorso del file di configurazione per SSH, per quando ci si connette ad un server SFTP/SCP. Se lasciato vuoto, nessun file verrà usato. Il percorso può anche iniziare con `~` per indicare il percorso della home dell'utente attuale (e.s. `~/.ssh/config`).
|
||||||
|
|
||||||
### SSH Key Storage 🔐
|
### SSH Key Storage 🔐
|
||||||
|
|
||||||
|
|||||||
@@ -306,6 +306,7 @@ These parameters can be changed:
|
|||||||
- **Local File formatter syntax**: syntax to display file info for each file in the local explorer. See [File explorer format](#file-explorer-format)
|
- **Local File formatter syntax**: syntax to display file info for each file in the local explorer. See [File explorer format](#file-explorer-format)
|
||||||
- **Enable notifications?**: If set to `Yes`, notifications will be displayed.
|
- **Enable notifications?**: If set to `Yes`, notifications will be displayed.
|
||||||
- **Notifications: minimum transfer size**: if transfer size is greater or equal than the specified value, notifications for transfer will be displayed. The accepted values are in format `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
- **Notifications: minimum transfer size**: if transfer size is greater or equal than the specified value, notifications for transfer will be displayed. The accepted values are in format `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
||||||
|
- **SSH configuration path**: Set SSH configuration file to use when connecting to a SCP/SFTP server. If unset (empty) no file will be used. You can specify a path starting with `~` to indicate the home path (e.g. `~/.ssh/config`)
|
||||||
|
|
||||||
### SSH Key Storage 🔐
|
### SSH Key Storage 🔐
|
||||||
|
|
||||||
|
|||||||
@@ -299,6 +299,7 @@ termscp和书签一样,只需要保证这些路径是可访问的:
|
|||||||
- **Local File formatter syntax**:在本地资源管理器中显示每个文件的文件信息的语法。参见[资源管理器格式](#资源管理器格式)
|
- **Local File formatter syntax**:在本地资源管理器中显示每个文件的文件信息的语法。参见[资源管理器格式](#资源管理器格式)
|
||||||
- **Enable notifications?**: 如果设置为 `Yes`,则会显示通知。
|
- **Enable notifications?**: 如果设置为 `Yes`,则会显示通知。
|
||||||
- **Notifications: minimum transfer size**: 如果传输大小大于或等于指定值,将显示传输通知。 接受的值格式为 `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
- **Notifications: minimum transfer size**: 如果传输大小大于或等于指定值,将显示传输通知。 接受的值格式为 `{UNSIGNED} B/KB/MB/GB/TB/PB`
|
||||||
|
- **SSH Configuration path**:设置连接到 SCP/SFTP 服务器时使用的 SSH 配置文件。 如果未设置(空),则不会使用任何文件。 你可以指定一个以 `~` 开头的路径来表示主路径(例如 `~/.ssh/config`)
|
||||||
|
|
||||||
### SSH Key Storage
|
### SSH Key Storage
|
||||||
|
|
||||||
|
|||||||
+17
-5
@@ -52,16 +52,21 @@ pub struct UserInterfaceConfig {
|
|||||||
pub check_for_updates: Option<bool>, // @! Since 0.3.3
|
pub check_for_updates: Option<bool>, // @! Since 0.3.3
|
||||||
pub prompt_on_file_replace: Option<bool>, // @! Since 0.7.0; Default True
|
pub prompt_on_file_replace: Option<bool>, // @! Since 0.7.0; Default True
|
||||||
pub group_dirs: Option<String>,
|
pub group_dirs: Option<String>,
|
||||||
pub file_fmt: Option<String>, // Refers to local host (for backward compatibility)
|
/// file fmt. Refers to local host (for backward compatibility)
|
||||||
pub remote_file_fmt: Option<String>, // @! Since 0.5.0
|
pub file_fmt: Option<String>,
|
||||||
pub notifications: Option<bool>, // @! Since 0.7.0; Default true
|
pub remote_file_fmt: Option<String>, // @! Since 0.5.0
|
||||||
|
pub notifications: Option<bool>, // @! Since 0.7.0; Default true
|
||||||
pub notification_threshold: Option<u64>, // @! Since 0.7.0; Default 512MB
|
pub notification_threshold: Option<u64>, // @! Since 0.7.0; Default 512MB
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Default)]
|
#[derive(Deserialize, Serialize, Debug, Default)]
|
||||||
/// Contains configuratio related to remote hosts
|
/// Contains configuratio related to remote hosts
|
||||||
pub struct RemoteConfig {
|
pub struct RemoteConfig {
|
||||||
pub ssh_keys: HashMap<String, PathBuf>, // Association between host name and path to private key
|
/// Ssh configuration path. If NONE, won't be read
|
||||||
|
pub ssh_config: Option<String>,
|
||||||
|
/// Association between host name and path to private key
|
||||||
|
/// NOTE: this parameter must stay as last: <https://github.com/alexcrichton/toml-rs/issues/142>
|
||||||
|
pub ssh_keys: HashMap<String, PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for UserInterfaceConfig {
|
impl Default for UserInterfaceConfig {
|
||||||
@@ -99,7 +104,10 @@ mod tests {
|
|||||||
String::from("192.168.1.31"),
|
String::from("192.168.1.31"),
|
||||||
PathBuf::from("/tmp/private.key"),
|
PathBuf::from("/tmp/private.key"),
|
||||||
);
|
);
|
||||||
let remote: RemoteConfig = RemoteConfig { ssh_keys: keys };
|
let remote: RemoteConfig = RemoteConfig {
|
||||||
|
ssh_keys: keys,
|
||||||
|
ssh_config: Some(String::from("~/.ssh/config")),
|
||||||
|
};
|
||||||
let ui: UserInterfaceConfig = UserInterfaceConfig {
|
let ui: UserInterfaceConfig = UserInterfaceConfig {
|
||||||
default_protocol: String::from("SFTP"),
|
default_protocol: String::from("SFTP"),
|
||||||
text_editor: PathBuf::from("nano"),
|
text_editor: PathBuf::from("nano"),
|
||||||
@@ -130,6 +138,10 @@ mod tests {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
PathBuf::from("/tmp/private.key")
|
PathBuf::from("/tmp/private.key")
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
cfg.remote.ssh_config.as_deref().unwrap(),
|
||||||
|
String::from("~/.ssh/config")
|
||||||
|
);
|
||||||
assert_eq!(cfg.user_interface.default_protocol, String::from("SFTP"));
|
assert_eq!(cfg.user_interface.default_protocol, String::from("SFTP"));
|
||||||
assert_eq!(cfg.user_interface.text_editor, PathBuf::from("nano"));
|
assert_eq!(cfg.user_interface.text_editor, PathBuf::from("nano"));
|
||||||
assert_eq!(cfg.user_interface.show_hidden_files, true);
|
assert_eq!(cfg.user_interface.show_hidden_files, true);
|
||||||
|
|||||||
@@ -197,6 +197,11 @@ mod tests {
|
|||||||
assert_eq!(cfg.user_interface.notifications.unwrap(), false);
|
assert_eq!(cfg.user_interface.notifications.unwrap(), false);
|
||||||
assert_eq!(cfg.user_interface.notification_threshold.unwrap(), 1024);
|
assert_eq!(cfg.user_interface.notification_threshold.unwrap(), 1024);
|
||||||
assert_eq!(cfg.user_interface.group_dirs, Some(String::from("last")));
|
assert_eq!(cfg.user_interface.group_dirs, Some(String::from("last")));
|
||||||
|
// Remote
|
||||||
|
assert_eq!(
|
||||||
|
cfg.remote.ssh_config.as_deref(),
|
||||||
|
Some("/home/omar/.ssh/config")
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cfg.user_interface.file_fmt,
|
cfg.user_interface.file_fmt,
|
||||||
Some(String::from("{NAME} {PEX}"))
|
Some(String::from("{NAME} {PEX}"))
|
||||||
@@ -244,6 +249,7 @@ mod tests {
|
|||||||
assert!(cfg.user_interface.remote_file_fmt.is_none());
|
assert!(cfg.user_interface.remote_file_fmt.is_none());
|
||||||
assert!(cfg.user_interface.notifications.is_none());
|
assert!(cfg.user_interface.notifications.is_none());
|
||||||
assert!(cfg.user_interface.notification_threshold.is_none());
|
assert!(cfg.user_interface.notification_threshold.is_none());
|
||||||
|
assert!(cfg.remote.ssh_config.is_none());
|
||||||
// Verify keys
|
// Verify keys
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
*cfg.remote
|
*cfg.remote
|
||||||
@@ -322,6 +328,9 @@ mod tests {
|
|||||||
notifications = false
|
notifications = false
|
||||||
notification_threshold = 1024
|
notification_threshold = 1024
|
||||||
|
|
||||||
|
[remote]
|
||||||
|
ssh_config = "/home/omar/.ssh/config"
|
||||||
|
|
||||||
[remote.ssh_keys]
|
[remote.ssh_keys]
|
||||||
"192.168.1.31" = "/home/omar/.ssh/raspberry.key"
|
"192.168.1.31" = "/home/omar/.ssh/raspberry.key"
|
||||||
"192.168.1.32" = "/home/omar/.ssh/beaglebone.key"
|
"192.168.1.32" = "/home/omar/.ssh/beaglebone.key"
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ use remotefs::client::{
|
|||||||
ssh::{ScpFs, SftpFs, SshOpts},
|
ssh::{ScpFs, SftpFs, SshOpts},
|
||||||
};
|
};
|
||||||
use remotefs::RemoteFs;
|
use remotefs::RemoteFs;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
/// Remotefs builder
|
/// Remotefs builder
|
||||||
pub struct Builder;
|
pub struct Builder;
|
||||||
@@ -117,6 +118,9 @@ impl Builder {
|
|||||||
if let Some(password) = params.password {
|
if let Some(password) = params.password {
|
||||||
opts = opts.password(password);
|
opts = opts.password(password);
|
||||||
}
|
}
|
||||||
|
if let Some(config_path) = config_client.get_ssh_config() {
|
||||||
|
opts = opts.config_file(PathBuf::from(config_path));
|
||||||
|
}
|
||||||
opts
|
opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -239,6 +239,18 @@ impl ConfigClient {
|
|||||||
self.config.user_interface.notification_threshold = Some(value);
|
self.config.user_interface.notification_threshold = Some(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remote params
|
||||||
|
|
||||||
|
/// Get ssh config path
|
||||||
|
pub fn get_ssh_config(&self) -> Option<&str> {
|
||||||
|
self.config.remote.ssh_config.as_deref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set ssh config path
|
||||||
|
pub fn set_ssh_config(&mut self, p: Option<String>) {
|
||||||
|
self.config.remote.ssh_config = p;
|
||||||
|
}
|
||||||
|
|
||||||
// SSH Keys
|
// SSH Keys
|
||||||
|
|
||||||
/// Save a SSH key into configuration.
|
/// Save a SSH key into configuration.
|
||||||
@@ -655,6 +667,20 @@ mod tests {
|
|||||||
assert_eq!(client.get_notification_threshold(), 64);
|
assert_eq!(client.get_notification_threshold(), 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_system_config_remote_ssh_config() {
|
||||||
|
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||||
|
let (cfg_path, key_path): (PathBuf, PathBuf) = get_paths(tmp_dir.path());
|
||||||
|
let mut client: ConfigClient = ConfigClient::new(cfg_path.as_path(), key_path.as_path())
|
||||||
|
.ok()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(client.get_ssh_config(), None); // Null ?
|
||||||
|
client.set_ssh_config(Some(String::from("/tmp/ssh_config")));
|
||||||
|
assert_eq!(client.get_ssh_config(), Some("/tmp/ssh_config"));
|
||||||
|
client.set_ssh_config(None);
|
||||||
|
assert_eq!(client.get_ssh_config(), None);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_system_config_ssh_keys() {
|
fn test_system_config_ssh_keys() {
|
||||||
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
let tmp_dir: TempDir = TempDir::new().ok().unwrap();
|
||||||
|
|||||||
@@ -391,6 +391,7 @@ impl BookmarkName {
|
|||||||
impl Component<Msg, NoUserEvent> for BookmarkName {
|
impl Component<Msg, NoUserEvent> for BookmarkName {
|
||||||
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||||
match ev {
|
match ev {
|
||||||
|
Event::Keyboard(KeyEvent { code: Key::Esc, .. }) => Some(Msg::CloseSaveBookmark),
|
||||||
Event::Keyboard(KeyEvent {
|
Event::Keyboard(KeyEvent {
|
||||||
code: Key::Left, ..
|
code: Key::Left, ..
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
@@ -368,6 +368,43 @@ impl Component<Msg, NoUserEvent> for RemoteFileFmt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(MockComponent)]
|
||||||
|
pub struct SshConfig {
|
||||||
|
component: Input,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SshConfig {
|
||||||
|
pub fn new(value: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
component: Input::default()
|
||||||
|
.borders(
|
||||||
|
Borders::default()
|
||||||
|
.color(Color::LightBlue)
|
||||||
|
.modifiers(BorderType::Rounded),
|
||||||
|
)
|
||||||
|
.foreground(Color::LightBlue)
|
||||||
|
.input_type(InputType::Text)
|
||||||
|
.placeholder(
|
||||||
|
"~/.ssh/config",
|
||||||
|
Style::default().fg(Color::Rgb(128, 128, 128)),
|
||||||
|
)
|
||||||
|
.title("SSH configuration path", Alignment::Left)
|
||||||
|
.value(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component<Msg, NoUserEvent> for SshConfig {
|
||||||
|
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
|
||||||
|
handle_input_ev(
|
||||||
|
self,
|
||||||
|
ev,
|
||||||
|
Msg::Config(ConfigMsg::SshConfigBlurDown),
|
||||||
|
Msg::Config(ConfigMsg::SshConfigBlurUp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(MockComponent)]
|
#[derive(MockComponent)]
|
||||||
pub struct TextEditor {
|
pub struct TextEditor {
|
||||||
component: Input,
|
component: Input,
|
||||||
@@ -448,7 +485,7 @@ fn handle_input_ev(
|
|||||||
}
|
}
|
||||||
Event::Keyboard(KeyEvent {
|
Event::Keyboard(KeyEvent {
|
||||||
code: Key::Char(ch),
|
code: Key::Char(ch),
|
||||||
modifiers: KeyModifiers::NONE,
|
modifiers: KeyModifiers::NONE | KeyModifiers::SHIFT,
|
||||||
}) => {
|
}) => {
|
||||||
component.perform(Cmd::Type(ch));
|
component.perform(Cmd::Type(ch));
|
||||||
Some(Msg::Config(ConfigMsg::ConfigChanged))
|
Some(Msg::Config(ConfigMsg::ConfigChanged))
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ mod theme;
|
|||||||
pub(super) use commons::{ErrorPopup, Footer, Header, Keybindings, QuitPopup, SavePopup};
|
pub(super) use commons::{ErrorPopup, Footer, Header, Keybindings, QuitPopup, SavePopup};
|
||||||
pub(super) use config::{
|
pub(super) use config::{
|
||||||
CheckUpdates, DefaultProtocol, GroupDirs, HiddenFiles, LocalFileFmt, NotificationsEnabled,
|
CheckUpdates, DefaultProtocol, GroupDirs, HiddenFiles, LocalFileFmt, NotificationsEnabled,
|
||||||
NotificationsThreshold, PromptOnFileReplace, RemoteFileFmt, TextEditor,
|
NotificationsThreshold, PromptOnFileReplace, RemoteFileFmt, SshConfig, TextEditor,
|
||||||
};
|
};
|
||||||
pub(super) use ssh::{DelSshKeyPopup, SshHost, SshKeys, SshUsername};
|
pub(super) use ssh::{DelSshKeyPopup, SshHost, SshKeys, SshUsername};
|
||||||
pub(super) use theme::*;
|
pub(super) use theme::*;
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ impl SetupActivity {
|
|||||||
pub(super) fn save_config(&mut self) -> Result<(), String> {
|
pub(super) fn save_config(&mut self) -> Result<(), String> {
|
||||||
match self.config().write_config() {
|
match self.config().write_config() {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(err) => Err(format!("Could not save configuration: {}", err)),
|
Err(err) => {
|
||||||
|
error!("Could not save configuration: {}", err);
|
||||||
|
Err(format!("Could not save configuration: {}", err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ enum IdConfig {
|
|||||||
NotificationsThreshold,
|
NotificationsThreshold,
|
||||||
PromptOnFileReplace,
|
PromptOnFileReplace,
|
||||||
RemoteFileFmt,
|
RemoteFileFmt,
|
||||||
|
SshConfig,
|
||||||
TextEditor,
|
TextEditor,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,6 +168,8 @@ pub enum ConfigMsg {
|
|||||||
PromptOnFileReplaceBlurUp,
|
PromptOnFileReplaceBlurUp,
|
||||||
RemoteFileFmtBlurDown,
|
RemoteFileFmtBlurDown,
|
||||||
RemoteFileFmtBlurUp,
|
RemoteFileFmtBlurUp,
|
||||||
|
SshConfigBlurDown,
|
||||||
|
SshConfigBlurUp,
|
||||||
TextEditorBlurDown,
|
TextEditorBlurDown,
|
||||||
TextEditorBlurUp,
|
TextEditorBlurUp,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,11 +80,13 @@ impl SetupActivity {
|
|||||||
CommonMsg::RevertChanges => match self.layout {
|
CommonMsg::RevertChanges => match self.layout {
|
||||||
ViewLayout::Theme => {
|
ViewLayout::Theme => {
|
||||||
if let Err(err) = self.action_reset_theme() {
|
if let Err(err) = self.action_reset_theme() {
|
||||||
|
error!("Failed to reset theme: {}", err);
|
||||||
self.mount_error(err);
|
self.mount_error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ViewLayout::SshKeys | ViewLayout::SetupForm => {
|
ViewLayout::SshKeys | ViewLayout::SetupForm => {
|
||||||
if let Err(err) = self.action_reset_config() {
|
if let Err(err) = self.action_reset_config() {
|
||||||
|
error!("Failed to reset config: {}", err);
|
||||||
self.mount_error(err);
|
self.mount_error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,6 +94,7 @@ impl SetupActivity {
|
|||||||
CommonMsg::SaveAndQuit => {
|
CommonMsg::SaveAndQuit => {
|
||||||
// Save changes
|
// Save changes
|
||||||
if let Err(err) = self.action_save_all() {
|
if let Err(err) = self.action_save_all() {
|
||||||
|
error!("Failed to save config: {}", err);
|
||||||
self.mount_error(err.as_str());
|
self.mount_error(err.as_str());
|
||||||
}
|
}
|
||||||
// Exit
|
// Exit
|
||||||
@@ -99,6 +102,7 @@ impl SetupActivity {
|
|||||||
}
|
}
|
||||||
CommonMsg::SaveConfig => {
|
CommonMsg::SaveConfig => {
|
||||||
if let Err(err) = self.action_save_all() {
|
if let Err(err) = self.action_save_all() {
|
||||||
|
error!("Failed to save config: {}", err);
|
||||||
self.mount_error(err.as_str());
|
self.mount_error(err.as_str());
|
||||||
}
|
}
|
||||||
self.umount_save_popup();
|
self.umount_save_popup();
|
||||||
@@ -173,7 +177,7 @@ impl SetupActivity {
|
|||||||
.is_ok());
|
.is_ok());
|
||||||
}
|
}
|
||||||
ConfigMsg::NotificationsThresholdBlurDown => {
|
ConfigMsg::NotificationsThresholdBlurDown => {
|
||||||
assert!(self.app.active(&Id::Config(IdConfig::TextEditor)).is_ok());
|
assert!(self.app.active(&Id::Config(IdConfig::SshConfig)).is_ok());
|
||||||
}
|
}
|
||||||
ConfigMsg::NotificationsThresholdBlurUp => {
|
ConfigMsg::NotificationsThresholdBlurUp => {
|
||||||
assert!(self
|
assert!(self
|
||||||
@@ -203,6 +207,12 @@ impl SetupActivity {
|
|||||||
.is_ok());
|
.is_ok());
|
||||||
}
|
}
|
||||||
ConfigMsg::TextEditorBlurUp => {
|
ConfigMsg::TextEditorBlurUp => {
|
||||||
|
assert!(self.app.active(&Id::Config(IdConfig::SshConfig)).is_ok());
|
||||||
|
}
|
||||||
|
ConfigMsg::SshConfigBlurDown => {
|
||||||
|
assert!(self.app.active(&Id::Config(IdConfig::TextEditor)).is_ok());
|
||||||
|
}
|
||||||
|
ConfigMsg::SshConfigBlurUp => {
|
||||||
assert!(self
|
assert!(self
|
||||||
.app
|
.app
|
||||||
.active(&Id::Config(IdConfig::NotificationsThreshold))
|
.active(&Id::Config(IdConfig::NotificationsThreshold))
|
||||||
@@ -230,6 +240,7 @@ impl SetupActivity {
|
|||||||
}
|
}
|
||||||
SshMsg::EditSshKey(i) => {
|
SshMsg::EditSshKey(i) => {
|
||||||
if let Err(err) = self.edit_ssh_key(i) {
|
if let Err(err) = self.edit_ssh_key(i) {
|
||||||
|
error!("Failed to edit ssh key: {}", err);
|
||||||
self.mount_error(err.as_str());
|
self.mount_error(err.as_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ impl SetupActivity {
|
|||||||
Constraint::Length(3), // Remote Format input
|
Constraint::Length(3), // Remote Format input
|
||||||
Constraint::Length(3), // Notifications enabled
|
Constraint::Length(3), // Notifications enabled
|
||||||
Constraint::Length(3), // Notifications threshold
|
Constraint::Length(3), // Notifications threshold
|
||||||
|
Constraint::Length(3), // Ssh config
|
||||||
Constraint::Length(1), // Filler
|
Constraint::Length(1), // Filler
|
||||||
]
|
]
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
@@ -144,6 +145,8 @@ impl SetupActivity {
|
|||||||
f,
|
f,
|
||||||
ui_cfg_chunks_col2[3],
|
ui_cfg_chunks_col2[3],
|
||||||
);
|
);
|
||||||
|
self.app
|
||||||
|
.view(&Id::Config(IdConfig::SshConfig), f, ui_cfg_chunks_col2[4]);
|
||||||
// Popups
|
// Popups
|
||||||
self.view_popups(f);
|
self.view_popups(f);
|
||||||
});
|
});
|
||||||
@@ -261,6 +264,17 @@ impl SetupActivity {
|
|||||||
vec![]
|
vec![]
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
// Ssh config
|
||||||
|
assert!(self
|
||||||
|
.app
|
||||||
|
.remount(
|
||||||
|
Id::Config(IdConfig::SshConfig),
|
||||||
|
Box::new(components::SshConfig::new(
|
||||||
|
self.config().get_ssh_config().unwrap_or("")
|
||||||
|
)),
|
||||||
|
vec![]
|
||||||
|
)
|
||||||
|
.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect values from input and put them into the configuration
|
/// Collect values from input and put them into the configuration
|
||||||
@@ -332,5 +346,19 @@ impl SetupActivity {
|
|||||||
{
|
{
|
||||||
self.config_mut().set_notification_threshold(bytes);
|
self.config_mut().set_notification_threshold(bytes);
|
||||||
}
|
}
|
||||||
|
if let Ok(State::One(StateValue::String(mut path))) =
|
||||||
|
self.app.state(&Id::Config(IdConfig::SshConfig))
|
||||||
|
{
|
||||||
|
if path.is_empty() {
|
||||||
|
self.config_mut().set_ssh_config(None);
|
||||||
|
} else {
|
||||||
|
// Replace '~' with home path
|
||||||
|
if path.starts_with('~') {
|
||||||
|
let home_dir = dirs::home_dir().unwrap_or_else(|| PathBuf::from("/root"));
|
||||||
|
path = path.replacen('~', &home_dir.to_string_lossy(), 1);
|
||||||
|
}
|
||||||
|
self.config_mut().set_ssh_config(Some(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user