use std::path::{Path, PathBuf};
use serde::Serialize;
use crate::file_types::{detect_file_type, FileType};
#[derive(Serialize, Debug)]
pub struct FilePreview {
pub kind: String,
pub content: String,
pub language: Option<String>,
pub truncated: bool,
}
pub fn get_file_preview_impl(path: &Path) -> Result<FilePreview, String> {
if !path.is_file() {
return Err(format!("File not found: {}", path.display()));
}
let file_type = detect_file_type(path);
match file_type {
FileType::Markdown => {
let content = std::fs::read_to_string(path)
.map_err(|e| format!("Failed to read markdown file: {}", e))?;
let truncated = content.len() > 200;
let preview: String = content.chars().take(200).collect();
Ok(FilePreview {
kind: "markdown".to_string(),
content: preview,
language: None,
truncated,
})
}
FileType::Code { language } => {
let content = std::fs::read_to_string(path)
.map_err(|e| format!("Failed to read code file: {}", e))?;
let lines: Vec<&str> = content.lines().collect();
let truncated = lines.len() > 10;
let preview = lines.iter().take(10).copied().collect::<Vec<_>>().join("\n");
Ok(FilePreview {
kind: "code".to_string(),
content: preview,
language: Some(language),
truncated,
})
}
FileType::Image { format } => {
let (width, height) = extract_image_dimensions(path).unwrap_or((0, 0));
let size = std::fs::metadata(path)
.map(|m| m.len())
.unwrap_or(0);
let content = format!(
"{}x{} pixels, {} format, {:.1} KB",
width, height, format, size as f64 / 1024.0
);
Ok(FilePreview {
kind: "image".to_string(),
content,
language: None,
truncated: false,
})
}
FileType::Hex => {
let size = std::fs::metadata(path)
.map(|m| m.len())
.unwrap_or(0);
let ext = path
.extension()
.and_then(|e| e.to_str())
.unwrap_or("unknown");
let content = format!("{} file, {:.1} KB", ext, size as f64 / 1024.0);
Ok(FilePreview {
kind: "other".to_string(),
content,
language: None,
truncated: false,
})
}
}
}
fn extract_image_dimensions(path: &Path) -> Option<(u32, u32)> {
use image::ImageReader;
let reader = ImageReader::open(path).ok()?;
let dimensions = reader.into_dimensions().ok()?;
Some(dimensions)
}
#[tauri::command]
pub async fn get_file_preview(path: String) -> Result<FilePreview, String> {
let p = PathBuf::from(&path);
get_file_preview_impl(&p)
}