mod server; mod ui; use std::net::SocketAddr; use std::path::PathBuf; use std::rc::Rc; use std::cell::RefCell; use gtk::prelude::*; fn main() { let rt = tokio::runtime::Builder::new_multi_thread() .enable_all() .build() .expect("Failed to create Tokio runtime"); // Create UI let ui = ui::FtpUi::new(); // Create server instance let server = Rc::new(RefCell::new(None::)); // Connect signals let ui_clone = ui.clone(); let server_clone = server.clone(); let rt_clone = rt.handle().clone(); ui.start_button.connect_clicked(move |_| { // Get settings from UI let ip = ui_clone.ip_entry.text(); let port: u16 = ui_clone.port_entry.text().parse().unwrap_or(2121); let dir = ui_clone.dir_entry.text(); // Validate directory let dir_path = PathBuf::from(&dir); if !dir_path.exists() { ui_clone.status_label.set_text("Error: Directory does not exist"); return; } // Update server address let addr: SocketAddr = format!("{}:{}", ip, port).parse().unwrap(); // Create and start server match server::FtpServer::new(addr, dir_path) { Ok(mut srv) => { // First start the server (initialize it) if let Err(e) = srv.start() { ui_clone.status_label.set_text(&format!("Error: {}", e)); return; } // Then run the server in the Tokio runtime let handle = rt_clone.clone(); match handle.block_on(async { srv.run() }) { Ok(()) => { server_clone.borrow_mut().replace(srv); ui_clone.status_label.set_text("Status: Running"); ui_clone.start_button.set_sensitive(false); ui_clone.stop_button.set_sensitive(true); } Err(e) => { ui_clone.status_label.set_text(&format!("Error: {}", e)); } } } Err(e) => { ui_clone.status_label.set_text(&format!("Error: {}", e)); } } }); let ui_clone = ui.clone(); let server_clone2 = server.clone(); ui.stop_button.connect_clicked(move |_| { let mut server_ref = server_clone2.borrow_mut(); if let Some(mut srv) = server_ref.take() { srv.stop(); } ui_clone.status_label.set_text("Status: Stopped"); ui_clone.start_button.set_sensitive(true); ui_clone.stop_button.set_sensitive(false); }); // Directory browse button let ui_clone = ui.clone(); ui.dir_button.connect_clicked(move |_| { let dialog = gtk::FileChooserDialog::with_buttons( Some("选择目录"), Some(&ui_clone.window), gtk::FileChooserAction::SelectFolder, &[("取消", gtk::ResponseType::Cancel), ("确定", gtk::ResponseType::Accept)] ); if dialog.run() == gtk::ResponseType::Accept { if let Some(filename) = dialog.filename() { ui_clone.dir_entry.set_text(&filename.to_string_lossy()); } } dialog.close(); }); // Show window ui.window.show_all(); // Start GTK main loop gtk::main(); }