diff --git a/src-tauri/src/drive.rs b/src-tauri/src/drive.rs index 9b27366..f1d60fc 100644 --- a/src-tauri/src/drive.rs +++ b/src-tauri/src/drive.rs @@ -1,119 +1,101 @@ use serde::{Deserialize, Serialize}; use std::fs; use std::path::{Path, PathBuf}; -use tauri::{Manager, Window}; +use tauri::{Emitter, Manager, Window}; #[derive(Debug, Serialize, Deserialize)] -struct FileItem { +pub struct FileItem { name: String, path: String, is_dir: bool, } -impl Drive { - #[tauri::command] - fn list_files(path: &str) -> Result, String> { - let base_path = Path::new(path); - let mut files = Vec::new(); +#[tauri::command] +pub fn list_files(path: &str) -> Result, String> { + let base_path = Path::new(path); + let mut files = Vec::new(); - if !base_path.exists() { - return Err("Path does not exist".into()); - } + if !base_path.exists() { + return Err("Path does not exist".into()); + } - for entry in fs::read_dir(base_path).map_err(|e| e.to_string())? { - let entry = entry.map_err(|e| e.to_string())?; - let path = entry.path(); - let name = path - .file_name() - .and_then(|n| n.to_str()) - .unwrap_or("") - .to_string(); + for entry in fs::read_dir(base_path).map_err(|e| e.to_string())? { + let entry = entry.map_err(|e| e.to_string())?; + let path = entry.path(); + let name = path + .file_name() + .and_then(|n| n.to_str()) + .unwrap_or("") + .to_string(); - files.push(FileItem { - name, - path: path.to_str().unwrap_or("").to_string(), - is_dir: path.is_dir(), - }); - } - - // Sort directories first, then files - files.sort_by(|a, b| { - if a.is_dir && !b.is_dir { - std::cmp::Ordering::Less - } else if !a.is_dir && b.is_dir { - std::cmp::Ordering::Greater - } else { - a.name.cmp(&b.name) - } + files.push(FileItem { + name, + path: path.to_str().unwrap_or("").to_string(), + is_dir: path.is_dir(), }); - - Ok(files) } - #[tauri::command] - async fn upload_file( - window: Window, - src_path: String, - dest_path: String, - ) -> Result<(), String> { - use std::fs::File; - use std::io::{Read, Write}; - use tauri::api::path::home_dir; - - let src = PathBuf::from(&src_path); - let dest_dir = PathBuf::from(&dest_path); - let dest = dest_dir.join(src.file_name().ok_or("Invalid source file")?); - - // Create destination directory if it doesn't exist - if !dest_dir.exists() { - fs::create_dir_all(&dest_dir).map_err(|e| e.to_string())?; + // Sort directories first, then files + files.sort_by(|a, b| { + if a.is_dir && !b.is_dir { + std::cmp::Ordering::Less + } else if !a.is_dir && b.is_dir { + std::cmp::Ordering::Greater + } else { + a.name.cmp(&b.name) } + }); - let mut source_file = File::open(&src).map_err(|e| e.to_string())?; - let mut dest_file = File::create(&dest).map_err(|e| e.to_string())?; - - let file_size = source_file.metadata().map_err(|e| e.to_string())?.len(); - let mut buffer = [0; 8192]; - let mut total_read = 0; - - loop { - let bytes_read = source_file.read(&mut buffer).map_err(|e| e.to_string())?; - if bytes_read == 0 { - break; - } - - dest_file - .write_all(&buffer[..bytes_read]) - .map_err(|e| e.to_string())?; - total_read += bytes_read as u64; - - let progress = (total_read as f64 / file_size as f64) * 100.0; - window - .emit("upload_progress", progress) - .map_err(|e| e.to_string())?; - } - - Ok(()) - } - - #[tauri::command] - fn create_folder(path: String, name: String) -> Result<(), String> { - let full_path = Path::new(&path).join(&name); - if full_path.exists() { - return Err("Folder already exists".into()); - } - fs::create_dir(full_path).map_err(|e| e.to_string())?; - Ok(()) - } - - fn main() { - tauri::Builder::default() - .invoke_handler(tauri::generate_handler![ - list_files, - upload_file, - create_folder - ]) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); - } + Ok(files) +} + +#[tauri::command] +pub async fn upload_file(window: Window, src_path: String, dest_path: String) -> Result<(), String> { + use std::fs::File; + use std::io::{Read, Write}; + + let src = PathBuf::from(&src_path); + let dest_dir = PathBuf::from(&dest_path); + let dest = dest_dir.join(src.file_name().ok_or("Invalid source file")?); + + // Create destination directory if it doesn't exist + if !dest_dir.exists() { + fs::create_dir_all(&dest_dir).map_err(|e| e.to_string())?; + } + + let mut source_file = File::open(&src).map_err(|e| e.to_string())?; + let mut dest_file = File::create(&dest).map_err(|e| e.to_string())?; + + let file_size = source_file.metadata().map_err(|e| e.to_string())?.len(); + let mut buffer = [0; 8192]; + let mut total_read = 0; + + loop { + let bytes_read = source_file.read(&mut buffer).map_err(|e| e.to_string())?; + if bytes_read == 0 { + break; + } + + dest_file + .write_all(&buffer[..bytes_read]) + .map_err(|e| e.to_string())?; + total_read += bytes_read as u64; + + let progress = (total_read as f64 / file_size as f64) * 100.0; + window + .emit("upload_progress", progress) + .map_err(|e| e.to_string())?; + } + + Ok(()) +} + +#[tauri::command] +pub fn create_folder(path: String, name: String) -> Result<(), String> { + let full_path = Path::new(&path).join(&name); + if full_path.exists() { + return Err("Folder already exists".into()); + } + fs::create_dir(full_path).map_err(|e| e.to_string())?; + Ok(()) } diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 440caf8..0271078 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,39 +1,4 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] - -use serde::{Deserialize, Serialize}; -use std::env; -use std::fs::{create_dir_all, File, OpenOptions}; -use std::io::Write; -use std::path::Path; -use std::process::{Command, Stdio}; -use std::sync::Mutex; -use tauri::{Manager, Window}; - pub mod drive; -use drive::Drive::; - -// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ -#[tauri::command] -fn greet(name: &str) -> String { - format!("Hello, {}! You've been greeted from Rust!", name) -} - -#[cfg_attr(mobile, tauri::mobile_entry_point)] -pub fn run() { - tauri::Builder::default() - .manage(AppState { - sync_processes: Mutex::new(Vec::new()), - sync_active: Mutex::new(false), - }) - .plugin(tauri_plugin_opener::init()) - .invoke_handler(tauri::generate_handler![ - save_config, - list_files, - start_sync, - stop_sync, - get_status - ]) - .run(tauri::generate_context!()) - .expect("error while running tauri application"); -} +pub mod sync; \ No newline at end of file diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index f5b33ae..b1208a1 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -2,7 +2,35 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] pub mod drive; +pub mod sync; -fn main() { - my_tauri_app_lib::run() +use sync::AppState; +use std::sync::Mutex; + +// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ +#[tauri::command] +fn greet(name: &str) -> String { + format!("Hello, {}! You've been greeted from Rust!", name) } + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +fn main() { + tauri::Builder::default() + .manage(AppState { + sync_processes: Mutex::new(Vec::new()), + sync_active: Mutex::new(false), + }) + .plugin(tauri_plugin_opener::init()) + .invoke_handler(tauri::generate_handler![ + sync::save_config, + drive::list_files, + drive::upload_file, + drive::create_folder, + sync::start_sync, + sync::stop_sync, + sync::get_status + ]) + .run(tauri::generate_context!()) + .expect("error while running tauri application"); +} + diff --git a/src-tauri/src/sync.rs b/src-tauri/src/sync.rs index ea85130..de0cb68 100644 --- a/src-tauri/src/sync.rs +++ b/src-tauri/src/sync.rs @@ -9,7 +9,7 @@ use std::env; #[derive(Debug, Clone, Serialize, Deserialize)] -struct RcloneConfig { +pub struct RcloneConfig { name: String, remote_path: String, local_path: String, @@ -18,7 +18,7 @@ struct RcloneConfig { } #[derive(Debug, Clone, Serialize, Deserialize)] -struct SyncStatus { +pub struct SyncStatus { name: String, status: String, transferred: String, @@ -27,13 +27,13 @@ struct SyncStatus { last_updated: String, } -struct AppState { - sync_processes: Mutex>, - sync_active: Mutex, +pub(crate) struct AppState { + pub sync_processes: Mutex>, + pub sync_active: Mutex, } #[tauri::command] -fn save_config(config: RcloneConfig) -> Result<(), String> { +pub fn save_config(config: RcloneConfig) -> Result<(), String> { let home_dir = env::var("HOME").map_err(|_| "HOME environment variable not set".to_string())?; let config_path = Path::new(&home_dir).join(".config/rclone/rclone.conf"); @@ -54,7 +54,7 @@ fn save_config(config: RcloneConfig) -> Result<(), String> { } #[tauri::command] -fn start_sync(config: RcloneConfig, state: tauri::State) -> Result<(), String> { +pub fn start_sync(config: RcloneConfig, state: tauri::State) -> Result<(), String> { let local_path = Path::new(&config.local_path); if !local_path.exists() { create_dir_all(local_path).map_err(|e| format!("Failed to create local path: {}", e))?; @@ -78,7 +78,7 @@ fn start_sync(config: RcloneConfig, state: tauri::State) -> Result<(), } #[tauri::command] -fn stop_sync(state: tauri::State) -> Result<(), String> { +pub fn stop_sync(state: tauri::State) -> Result<(), String> { let mut processes = state.sync_processes.lock().unwrap(); for child in processes.iter_mut() { child.kill().map_err(|e| format!("Failed to kill process: {}", e))?; @@ -89,7 +89,7 @@ fn stop_sync(state: tauri::State) -> Result<(), String> { } #[tauri::command] -fn get_status(remote_name: String) -> Result { +pub fn get_status(remote_name: String) -> Result { let output = Command::new("rclone") .arg("rc") .arg("core/stats") @@ -129,7 +129,7 @@ fn get_status(remote_name: String) -> Result { }) } -fn format_bytes(bytes: u64) -> String { +pub fn format_bytes(bytes: u64) -> String { const KB: u64 = 1024; const MB: u64 = KB * 1024; const GB: u64 = MB * 1024;