完善图片视频添加预览功能
This commit is contained in:
@@ -6,6 +6,7 @@ use std::sync::Mutex;
|
||||
use tauri::menu::{MenuBuilder, MenuItemBuilder, SubmenuBuilder};
|
||||
use tauri::{Emitter, Manager};
|
||||
use tauri_plugin_dialog::DialogExt;
|
||||
use base64::Engine;
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
struct DirEntry {
|
||||
@@ -55,6 +56,59 @@ fn is_hidden_entry(entry: &fs::DirEntry) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the companion hidden resources directory path for a markdown file.
|
||||
/// Example: `notes/doc.md` → `notes/.doc`
|
||||
fn resources_dir_path(file_path: &str) -> Option<String> {
|
||||
let path = std::path::Path::new(file_path);
|
||||
if path.extension().map_or(true, |ext| ext != "md") {
|
||||
return None;
|
||||
}
|
||||
let stem = path.file_stem()?.to_str()?;
|
||||
let parent = path.parent()?;
|
||||
let dir_name = format!(".{}", stem);
|
||||
Some(parent.join(dir_name).to_string_lossy().to_string())
|
||||
}
|
||||
|
||||
/// On Windows, set the hidden attribute on a directory so it doesn't clutter
|
||||
/// the file manager.
|
||||
#[cfg(windows)]
|
||||
fn hide_windows_dir(dir_path: &str) {
|
||||
let _ = std::process::Command::new("attrib")
|
||||
.args(["+h", dir_path])
|
||||
.output();
|
||||
}
|
||||
|
||||
/// Ensure a directory exists, and hide it on Windows when the name starts with `.`.
|
||||
fn ensure_resources_dir(dir_path: &str) -> std::io::Result<()> {
|
||||
fs::create_dir_all(dir_path)?;
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let name = std::path::Path::new(dir_path)
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.unwrap_or("");
|
||||
if name.starts_with('.') {
|
||||
hide_windows_dir(dir_path);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn save_media_file(path: String, data: String) -> Result<(), String> {
|
||||
let bytes = base64::engine::general_purpose::STANDARD
|
||||
.decode(&data)
|
||||
.map_err(|e| format!("解码失败: {}", e))?;
|
||||
|
||||
if let Some(parent) = std::path::Path::new(&path).parent() {
|
||||
let parent_str = parent.to_string_lossy().to_string();
|
||||
ensure_resources_dir(&parent_str)
|
||||
.map_err(|e| format!("无法创建目录: {}", e))?;
|
||||
}
|
||||
|
||||
fs::write(&path, &bytes).map_err(|e| format!("无法写入文件: {}", e))
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn pick_folder(app: tauri::AppHandle) -> Option<String> {
|
||||
app.dialog()
|
||||
@@ -200,7 +254,14 @@ fn create_file(path: String) -> Result<(), String> {
|
||||
if let Some(parent) = PathBuf::from(&path).parent() {
|
||||
fs::create_dir_all(parent).map_err(|e| format!("无法创建父目录: {}", e))?;
|
||||
}
|
||||
fs::write(&path, "").map_err(|e| format!("无法创建文件: {}", e))
|
||||
fs::write(&path, "").map_err(|e| format!("无法创建文件: {}", e))?;
|
||||
|
||||
// Create companion hidden resources directory for markdown files.
|
||||
if let Some(res_dir) = resources_dir_path(&path) {
|
||||
ensure_resources_dir(&res_dir).map_err(|e| format!("无法创建资源文件夹: {}", e))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
@@ -209,7 +270,17 @@ fn delete_entry(path: String) -> Result<(), String> {
|
||||
if p.is_dir() {
|
||||
fs::remove_dir_all(&p).map_err(|e| format!("无法删除文件夹: {}", e))
|
||||
} else if p.is_file() {
|
||||
fs::remove_file(&p).map_err(|e| format!("无法删除文件: {}", e))
|
||||
fs::remove_file(&p).map_err(|e| format!("无法删除文件: {}", e))?;
|
||||
|
||||
// If this was a markdown file, also remove its companion resources directory.
|
||||
if let Some(res_dir) = resources_dir_path(&path) {
|
||||
let res = PathBuf::from(&res_dir);
|
||||
if res.is_dir() {
|
||||
let _ = fs::remove_dir_all(&res);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err("路径不存在".to_string())
|
||||
}
|
||||
@@ -222,6 +293,21 @@ fn rename_entry(path: String, new_name: String) -> Result<String, String> {
|
||||
.parent()
|
||||
.ok_or_else(|| "无法获取父目录".to_string())?;
|
||||
let new_path = parent.join(&new_name);
|
||||
|
||||
// If this is a markdown file, rename its companion resources directory first.
|
||||
if let Some(old_res_dir) = resources_dir_path(&path) {
|
||||
let old_res = PathBuf::from(&old_res_dir);
|
||||
if old_res.is_dir() {
|
||||
let new_res_dir = resources_dir_path(&new_path.to_string_lossy());
|
||||
if let Some(new_res) = new_res_dir {
|
||||
let new_res_path = PathBuf::from(&new_res);
|
||||
if new_res_path != old_res {
|
||||
let _ = fs::rename(&old_res, &new_res_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fs::rename(&p, &new_path).map_err(|e| format!("无法重命名: {}", e))?;
|
||||
Ok(new_path.to_string_lossy().to_string())
|
||||
}
|
||||
@@ -249,7 +335,8 @@ pub fn run() {
|
||||
create_folder,
|
||||
create_file,
|
||||
delete_entry,
|
||||
rename_entry
|
||||
rename_entry,
|
||||
save_media_file
|
||||
])
|
||||
.setup(|app| {
|
||||
// ---- File menu ----
|
||||
|
||||
Reference in New Issue
Block a user