Files
ai-terminal-assistant/packages/desktop/src-tauri/src/commands.rs
T
kurihada 6ef9d95172 feat: 添加 Tauri 桌面应用
- 创建 packages/desktop 模块
- 实现 Tauri 2.0 + React 桌面应用
- 复用 Web 前端代码
- 添加系统托盘功能
- 实现本地文件访问命令
- 配置 Vite + Tauri 集成
- 更新 .gitignore 添加 Rust/Tauri 相关规则
2025-12-12 13:19:00 +08:00

119 lines
2.8 KiB
Rust

use serde::Serialize;
use std::fs;
use std::path::PathBuf;
use std::sync::mpsc;
use tauri_plugin_dialog::DialogExt;
#[derive(Serialize)]
pub struct AppInfo {
pub name: String,
pub version: String,
pub tauri_version: String,
}
#[tauri::command]
pub fn get_app_info() -> AppInfo {
AppInfo {
name: "AI Assistant".to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
tauri_version: tauri::VERSION.to_string(),
}
}
#[tauri::command]
pub async fn open_directory_dialog(app: tauri::AppHandle) -> Result<Option<String>, String> {
let (tx, rx) = mpsc::channel();
app.dialog()
.file()
.set_title("Select Working Directory")
.pick_folder(move |path| {
let _ = tx.send(path);
});
match rx.recv() {
Ok(Some(path)) => Ok(Some(path.to_string())),
Ok(None) => Ok(None),
Err(e) => Err(e.to_string()),
}
}
#[derive(Serialize)]
pub struct FileContent {
pub path: String,
pub content: String,
pub size: u64,
}
#[tauri::command]
pub async fn read_local_file(path: String) -> Result<FileContent, String> {
let path_buf = PathBuf::from(&path);
if !path_buf.exists() {
return Err(format!("File not found: {}", path));
}
let metadata = fs::metadata(&path_buf).map_err(|e| e.to_string())?;
if metadata.len() > 10 * 1024 * 1024 {
return Err("File too large (max 10MB)".to_string());
}
let content = fs::read_to_string(&path_buf).map_err(|e| e.to_string())?;
Ok(FileContent {
path,
content,
size: metadata.len(),
})
}
#[derive(Serialize)]
pub struct DirectoryEntry {
pub name: String,
pub path: String,
pub is_dir: bool,
pub size: u64,
}
#[tauri::command]
pub async fn list_directory(path: String) -> Result<Vec<DirectoryEntry>, String> {
let path_buf = PathBuf::from(&path);
if !path_buf.exists() {
return Err(format!("Directory not found: {}", path));
}
if !path_buf.is_dir() {
return Err(format!("Not a directory: {}", path));
}
let mut entries = Vec::new();
let read_dir = fs::read_dir(&path_buf).map_err(|e| e.to_string())?;
for entry in read_dir {
let entry = entry.map_err(|e| e.to_string())?;
let metadata = entry.metadata().map_err(|e| e.to_string())?;
entries.push(DirectoryEntry {
name: entry.file_name().to_string_lossy().to_string(),
path: entry.path().to_string_lossy().to_string(),
is_dir: metadata.is_dir(),
size: metadata.len(),
});
}
entries.sort_by(|a, b| {
if a.is_dir == b.is_dir {
a.name.to_lowercase().cmp(&b.name.to_lowercase())
} else if a.is_dir {
std::cmp::Ordering::Less
} else {
std::cmp::Ordering::Greater
}
});
Ok(entries)
}