107 lines
3.4 KiB
Rust
107 lines
3.4 KiB
Rust
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::<server::FtpServer>));
|
|
|
|
// 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();
|
|
} |