jan/src-tauri/src/core/app/commands.rs
Roushan Kumar Singh eccaa282e0
refactor: resolve rust analyzer warnings and improve code quality (#6696)
- Update string formatting to use modern interpolation syntax
- Simplify expressions and remove unnecessary intermediate variables
- Improve logging statements for better readability
- Clean up code across core modules (app, downloads, mcp, server, etc.)
2025-10-02 15:01:06 +07:00

196 lines
6.3 KiB
Rust

use std::{fs, path::PathBuf};
use tauri::{AppHandle, Manager, Runtime, State};
use super::{
constants::CONFIGURATION_FILE_NAME, helpers::copy_dir_recursive, models::AppConfiguration,
};
use crate::core::state::AppState;
#[tauri::command]
pub fn get_app_configurations<R: Runtime>(app_handle: tauri::AppHandle<R>) -> AppConfiguration {
let mut app_default_configuration = AppConfiguration::default();
if std::env::var("CI").unwrap_or_default() == "e2e" {
return app_default_configuration;
}
let configuration_file = get_configuration_file_path(app_handle.clone());
let default_data_folder = default_data_folder_path(app_handle.clone());
if !configuration_file.exists() {
log::info!("App config not found, creating default config at {configuration_file:?}");
app_default_configuration.data_folder = default_data_folder;
if let Err(err) = fs::write(
&configuration_file,
serde_json::to_string(&app_default_configuration).unwrap(),
) {
log::error!("Failed to create default config: {err}");
}
return app_default_configuration;
}
match fs::read_to_string(&configuration_file) {
Ok(content) => match serde_json::from_str::<AppConfiguration>(&content) {
Ok(app_configurations) => app_configurations,
Err(err) => {
log::error!("Failed to parse app config, returning default config instead. Error: {err}");
app_default_configuration
}
},
Err(err) => {
log::error!("Failed to read app config, returning default config instead. Error: {err}");
app_default_configuration
}
}
}
#[tauri::command]
pub fn update_app_configuration<R: Runtime>(
app_handle: tauri::AppHandle<R>,
configuration: AppConfiguration,
) -> Result<(), String> {
let configuration_file = get_configuration_file_path(app_handle);
log::info!("update_app_configuration, configuration_file: {configuration_file:?}");
fs::write(
configuration_file,
serde_json::to_string(&configuration).map_err(|e| e.to_string())?,
)
.map_err(|e| e.to_string())
}
#[tauri::command]
pub fn get_jan_data_folder_path<R: Runtime>(app_handle: tauri::AppHandle<R>) -> PathBuf {
if cfg!(test) {
let path = std::env::current_dir()
.unwrap_or_else(|_| PathBuf::from("."))
.join("test-data");
if !path.exists() {
let _ = fs::create_dir_all(&path);
}
return path;
}
let app_configurations = get_app_configurations(app_handle);
PathBuf::from(app_configurations.data_folder)
}
#[tauri::command]
pub fn get_configuration_file_path<R: Runtime>(app_handle: tauri::AppHandle<R>) -> PathBuf {
let app_path = app_handle.path().app_data_dir().unwrap_or_else(|err| {
log::error!(
"Failed to get app data directory: {err}. Using home directory instead."
);
let home_dir = std::env::var(if cfg!(target_os = "windows") {
"USERPROFILE"
} else {
"HOME"
})
.expect("Failed to determine the home directory");
PathBuf::from(home_dir)
});
let package_name = env!("CARGO_PKG_NAME");
#[cfg(target_os = "linux")]
let old_data_dir = {
if let Some(config_path) = dirs::config_dir() {
config_path.join(package_name)
} else {
log::debug!("Could not determine config directory");
app_path
.parent()
.unwrap_or(&app_path.join("../"))
.join(package_name)
}
};
#[cfg(not(target_os = "linux"))]
let old_data_dir = app_path
.parent()
.unwrap_or(&app_path.join("../"))
.join(package_name);
if old_data_dir.exists() {
old_data_dir.join(CONFIGURATION_FILE_NAME)
} else {
app_path.join(CONFIGURATION_FILE_NAME)
}
}
#[tauri::command]
pub fn default_data_folder_path<R: Runtime>(app_handle: tauri::AppHandle<R>) -> String {
let mut path = app_handle.path().data_dir().unwrap();
let app_name = std::env::var("APP_NAME")
.unwrap_or_else(|_| app_handle.config().product_name.clone().unwrap());
path.push(app_name);
path.push("data");
let mut path_str = path.to_str().unwrap().to_string();
if let Some(stripped) = path.to_str().unwrap().to_string().strip_suffix(".ai.app") {
path_str = stripped.to_string();
}
path_str
}
#[tauri::command]
pub fn get_user_home_path<R: Runtime>(app: AppHandle<R>) -> String {
get_app_configurations(app.clone()).data_folder
}
#[tauri::command]
pub fn change_app_data_folder<R: Runtime>(
app_handle: tauri::AppHandle<R>,
new_data_folder: String,
) -> Result<(), String> {
// Get current data folder path
let current_data_folder = get_jan_data_folder_path(app_handle.clone());
let new_data_folder_path = PathBuf::from(&new_data_folder);
// Create the new data folder if it doesn't exist
if !new_data_folder_path.exists() {
fs::create_dir_all(&new_data_folder_path)
.map_err(|e| format!("Failed to create new data folder: {e}"))?;
}
// Copy all files from the old folder to the new one
if current_data_folder.exists() {
log::info!("Copying data from {current_data_folder:?} to {new_data_folder_path:?}");
// Check if this is a parent directory to avoid infinite recursion
if new_data_folder_path.starts_with(&current_data_folder) {
return Err(
"New data folder cannot be a subdirectory of the current data folder".to_string(),
);
}
copy_dir_recursive(
&current_data_folder,
&new_data_folder_path,
&[".uvx", ".npx"],
)
.map_err(|e| format!("Failed to copy data to new folder: {e}"))?;
} else {
log::info!("Current data folder does not exist, nothing to copy");
}
// Update the configuration to point to the new folder
let mut configuration = get_app_configurations(app_handle.clone());
configuration.data_folder = new_data_folder;
// Save the updated configuration
update_app_configuration(app_handle, configuration)
}
#[tauri::command]
pub fn app_token(state: State<'_, AppState>) -> Option<String> {
state.app_token.clone()
}