Added startup setup
This commit is contained in:
@@ -29,33 +29,42 @@ fn default_theme() -> Theme {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn config_path() -> PathBuf {
|
||||
// Respect XDG_CONFIG_HOME; fall back to ~/.config on all platforms.
|
||||
let base = std::env::var("XDG_CONFIG_HOME")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| {
|
||||
dirs::home_dir()
|
||||
.unwrap_or_else(|| PathBuf::from("."))
|
||||
.join(".config")
|
||||
});
|
||||
base.join(env!("CARGO_PKG_NAME")).join("config.toml")
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Returns true when a config file already exists.
|
||||
pub fn exists() -> bool {
|
||||
config_path().exists()
|
||||
}
|
||||
|
||||
/// Load config from disk. Panics-safe: returns error if file is missing or malformed.
|
||||
pub fn load() -> Result<Self> {
|
||||
// Respect XDG_CONFIG_HOME; fall back to ~/.config on all platforms.
|
||||
let config_base = std::env::var("XDG_CONFIG_HOME")
|
||||
.map(PathBuf::from)
|
||||
.unwrap_or_else(|_| {
|
||||
dirs::home_dir()
|
||||
.unwrap_or_else(|| PathBuf::from("."))
|
||||
.join(".config")
|
||||
});
|
||||
let config_path = config_base
|
||||
.join(env!("CARGO_PKG_NAME"))
|
||||
.join("config.toml");
|
||||
|
||||
if !config_path.exists() {
|
||||
let default = Config {
|
||||
server_url: "http://localhost:8080/api/menu".to_string(),
|
||||
timeout_sec: 10,
|
||||
theme: default_theme(),
|
||||
update_api: None,
|
||||
};
|
||||
fs::create_dir_all(config_path.parent().unwrap())?;
|
||||
fs::write(config_path, toml::to_string_pretty(&default)?)?;
|
||||
return Ok(default);
|
||||
}
|
||||
|
||||
let content = fs::read_to_string(config_path)?;
|
||||
let path = config_path();
|
||||
let content = fs::read_to_string(&path)?;
|
||||
Ok(toml::from_str(&content)?)
|
||||
}
|
||||
|
||||
/// Create and persist a new config with the given server URL.
|
||||
pub fn create_with_url(server_url: &str) -> Result<Self> {
|
||||
let path = config_path();
|
||||
let config = Config {
|
||||
server_url: server_url.to_string(),
|
||||
timeout_sec: 10,
|
||||
theme: default_theme(),
|
||||
update_api: None,
|
||||
};
|
||||
fs::create_dir_all(path.parent().unwrap())?;
|
||||
fs::write(&path, toml::to_string_pretty(&config)?)?;
|
||||
Ok(config)
|
||||
}
|
||||
}
|
||||
|
||||
38
src/main.rs
38
src/main.rs
@@ -20,7 +20,12 @@ use tokio::sync::mpsc;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let config = config::Config::load()?;
|
||||
let config = if config::Config::exists() {
|
||||
config::Config::load()?
|
||||
} else {
|
||||
let url = prompt_server_url()?;
|
||||
config::Config::create_with_url(&url)?
|
||||
};
|
||||
|
||||
enable_raw_mode()?;
|
||||
let mut stdout = io::stdout();
|
||||
@@ -143,6 +148,37 @@ async fn run_exec(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Runs before ratatui starts. Prompts for the server URL on first launch.
|
||||
fn prompt_server_url() -> Result<String> {
|
||||
use std::io::Write;
|
||||
|
||||
println!();
|
||||
println!(" ╔══════════════════════════════════╗");
|
||||
println!(" ║ Ostiary — первый запуск ║");
|
||||
println!(" ╚══════════════════════════════════╝");
|
||||
println!();
|
||||
println!(" Конфиг будет сохранён в:");
|
||||
println!(" {}", config::config_path().display());
|
||||
println!();
|
||||
|
||||
loop {
|
||||
print!(" URL сервера меню: ");
|
||||
std::io::stdout().flush()?;
|
||||
|
||||
let mut url = String::new();
|
||||
std::io::stdin().read_line(&mut url)?;
|
||||
let url = url.trim().to_string();
|
||||
|
||||
if url.is_empty() {
|
||||
println!(" URL не может быть пустым. Попробуйте ещё раз.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
println!();
|
||||
return Ok(url);
|
||||
}
|
||||
}
|
||||
|
||||
async fn read_crossterm_event() -> Result<Option<crossterm::event::Event>> {
|
||||
if crossterm::event::poll(std::time::Duration::from_millis(100))? {
|
||||
Ok(Some(crossterm::event::read()?))
|
||||
|
||||
Reference in New Issue
Block a user