start working on terminal launcher
This commit is contained in:
parent
60c24e3ee4
commit
89bc74e644
12
src-tauri/Cargo.lock
generated
12
src-tauri/Cargo.lock
generated
@ -1066,6 +1066,7 @@ dependencies = [
|
||||
"tauri-plugin-single-instance",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5145,6 +5146,17 @@ dependencies = [
|
||||
"windows-metadata",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
|
||||
dependencies = [
|
||||
"either",
|
||||
"libc",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
@ -46,6 +46,7 @@ clap = { version = "3.2.23", features = ["derive"] }
|
||||
is-terminal = "0.4.7"
|
||||
argon2 = { version = "0.5.0", features = ["std"] }
|
||||
chacha20poly1305 = { version = "0.10.1", features = ["std"] }
|
||||
which = "4.4.0"
|
||||
|
||||
[features]
|
||||
# by default Tauri runs in production mode
|
||||
|
@ -42,6 +42,7 @@ pub fn run() -> tauri::Result<()> {
|
||||
ipc::save_credentials,
|
||||
ipc::get_config,
|
||||
ipc::save_config,
|
||||
ipc::launch_terminal,
|
||||
])
|
||||
.setup(|app| rt::block_on(setup(app)))
|
||||
.build(tauri::generate_context!())?
|
||||
|
@ -9,6 +9,16 @@ use sqlx::SqlitePool;
|
||||
use crate::errors::*;
|
||||
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct TermConfig {
|
||||
pub name: String,
|
||||
// we call it exec because it isn't always the actual path,
|
||||
// in some cases it's just the name and relies on path-searching
|
||||
pub exec: PathBuf,
|
||||
pub args: Vec<String>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct AppConfig {
|
||||
#[serde(default = "default_listen_addr")]
|
||||
@ -21,6 +31,7 @@ pub struct AppConfig {
|
||||
pub start_minimized: bool,
|
||||
#[serde(default = "default_start_on_login")]
|
||||
pub start_on_login: bool,
|
||||
pub terminal: Option<TermConfig>,
|
||||
}
|
||||
|
||||
|
||||
@ -32,6 +43,7 @@ impl Default for AppConfig {
|
||||
rehide_ms: default_rehide_ms(),
|
||||
start_minimized: default_start_minimized(),
|
||||
start_on_login: default_start_on_login(),
|
||||
terminal: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use crate::credentials::{Session,BaseCredentials};
|
||||
use crate::errors::*;
|
||||
use crate::clientinfo::Client;
|
||||
use crate::state::AppState;
|
||||
use crate::terminal;
|
||||
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
@ -78,3 +79,12 @@ pub async fn save_config(config: AppConfig, app_state: State<'_, AppState>) -> R
|
||||
.map_err(|e| format!("Error saving config: {e}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn launch_terminal(base: bool) -> bool {
|
||||
match terminal::launch(base).await {
|
||||
Ok(_) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
@ -7,4 +7,5 @@ mod clientinfo;
|
||||
mod ipc;
|
||||
mod state;
|
||||
mod server;
|
||||
mod terminal;
|
||||
mod tray;
|
||||
|
97
src-tauri/src/terminal.rs
Normal file
97
src-tauri/src/terminal.rs
Normal file
@ -0,0 +1,97 @@
|
||||
use std::process::Command;
|
||||
|
||||
use tauri::Manager;
|
||||
|
||||
use crate::app::APP;
|
||||
use crate::config::TermConfig;
|
||||
use crate::credentials::Session;
|
||||
use crate::errors::*;
|
||||
use crate::state::AppState;
|
||||
|
||||
|
||||
pub async fn launch(use_base: bool) -> Result<(), ExecError> {
|
||||
// we may have multiple candidates, because we might be on unix and
|
||||
// we don't have a good way of detecting for sure what default to use
|
||||
let state = APP.get().unwrap().state::<AppState>();
|
||||
let config = state.config.read().await;
|
||||
let _ = match config.terminal {
|
||||
Some(ref term) => launch_term(term, use_base).await,
|
||||
None => launch_default(use_base).await,
|
||||
}?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
async fn launch_term(term: &TermConfig, use_base: bool) -> Result<(), std::io::Error> {
|
||||
// do all this in a block so we don't hold the lock any longer than necessary
|
||||
let mut cmd = Command::new(&term.exec);
|
||||
cmd.args(&term.args);
|
||||
{
|
||||
// note: if called from launch(), there is already a lock being held on state.config
|
||||
// don't read that here or we will deadlock
|
||||
let state = APP.get().unwrap().state::<AppState>();
|
||||
let app_session = state.session.read().await;
|
||||
let (base_creds, session_creds) = match *app_session {
|
||||
Session::Locked(_) | Session::Empty => todo!(),
|
||||
Session::Unlocked{ref base, ref session} => (base, session),
|
||||
};
|
||||
|
||||
if use_base {
|
||||
cmd.env("AWS_ACCESS_KEY_ID", &base_creds.access_key_id);
|
||||
cmd.env("AWS_SECRET_ACCESS_KEY", &base_creds.secret_access_key);
|
||||
}
|
||||
else {
|
||||
cmd.env("AWS_ACCESS_KEY_ID", &session_creds.access_key_id);
|
||||
cmd.env("AWS_SECRET_ACCESS_KEY", &session_creds.secret_access_key);
|
||||
cmd.env("AWS_SESSION_TOKEN", &session_creds.token);
|
||||
}
|
||||
}
|
||||
|
||||
let _ = cmd.spawn()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
async fn launch_default(use_base: bool) -> Result<(), std::io::Error> {
|
||||
let defaults = default_terms();
|
||||
let last_idx = defaults.len() - 1;
|
||||
for (i, candidate) in defaults.iter().enumerate() {
|
||||
match launch_term(candidate, use_base).await {
|
||||
Ok(_) => return Ok(()),
|
||||
Err(e) => {
|
||||
if std::io::ErrorKind::NotFound == e.kind() && i < last_idx {
|
||||
continue;
|
||||
}
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
// we only continue the loop if there are further iterations left, so this is safe
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
|
||||
pub fn default_terms() -> Vec<TermConfig> {
|
||||
#[cfg(windows)]
|
||||
return vec![
|
||||
TermConfig {
|
||||
name: "powershell.exe".into(),
|
||||
exec: "conhost.exe".into(),
|
||||
args: vec!["powershell.exe".into()]
|
||||
}
|
||||
];
|
||||
|
||||
#[cfg(unix)]
|
||||
return vec![
|
||||
TermConfig {
|
||||
name: "gnome-terminal".into(),
|
||||
exec: "gnome-terminal".into(),
|
||||
args: vec![],
|
||||
},
|
||||
TermConfig {
|
||||
name: "konsole".into(),
|
||||
exec: "konsole".into(),
|
||||
args: vec![],
|
||||
},
|
||||
];
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user