diff --git a/filepi-server/src/handlers/files.rs b/filepi-server/src/handlers/files.rs index 7f3e3a6..a54a1bd 100644 --- a/filepi-server/src/handlers/files.rs +++ b/filepi-server/src/handlers/files.rs @@ -101,10 +101,12 @@ pub async fn get_files( let entry_path = entry.path(); // Create FileInfo with absolute path and current directory context - files.push(FileInfo::from_path(&entry_path, &full_path).map_err(|e| { - error!("Error creating FileInfo: {}", e); - AppError::InternalError(format!("Failed to read file info: {}", e)) - })?); + files.push( + FileInfo::from_path(&entry_path, &full_path, &config.root_dir).map_err(|e| { + error!("Error creating FileInfo: {}", e); + AppError::InternalError(format!("Failed to read file info: {}", e)) + })?, + ); } result_handler::format_result(&mut files, ¶ms) @@ -194,7 +196,12 @@ pub async fn get_videos( continue; } - video_files.push(FileInfo::from_path(&file_path, &full_path).unwrap()); + video_files.push( + FileInfo::from_path(&file_path, &full_path, &config.root_dir).map_err(|e| { + error!("Error creating FileInfo: {}", e); + AppError::InternalError(format!("Failed to read file info: {}", e)) + })?, + ); } result_handler::format_result(&mut video_files, ¶ms) @@ -282,7 +289,12 @@ pub async fn search( continue; } - matching_files.push(FileInfo::from_path(&file_path, &path).unwrap()); + matching_files.push( + FileInfo::from_path(&file_path, &full_path, &config.root_dir).map_err(|e| { + error!("Error creating FileInfo: {}", e); + AppError::InternalError(format!("Failed to read file info: {}", e)) + })?, + ); } result_handler::format_result(&mut matching_files, ¶ms) diff --git a/filepi-server/src/models/file_info.rs b/filepi-server/src/models/file_info.rs index 79f950f..a079f8d 100644 --- a/filepi-server/src/models/file_info.rs +++ b/filepi-server/src/models/file_info.rs @@ -19,11 +19,14 @@ pub struct FileInfo { } impl FileInfo { - pub fn from_path, T: AsRef>( + pub fn from_path, C: AsRef, R: AsRef>( absolute_path: P, - current_dir: T, + current_dir: C, + root_dir: R, ) -> std::io::Result { let path = absolute_path.as_ref(); + let current = current_dir.as_ref(); + let root = root_dir.as_ref(); let metadata = fs::metadata(path)?; // Basic info @@ -32,7 +35,12 @@ impl FileInfo { .map(|n| n.to_string_lossy().to_string()) .unwrap_or_default(); - let full_name = String::from(path.to_str().unwrap()); + // full_name should be relative to current_dir (without leading /) + let full_name = path + .strip_prefix(current) + .ok() + .map(|rel| rel.to_string_lossy().to_string()) + .unwrap_or_else(|| String::from(path.to_str().unwrap())); let size = match get_size(path) { Ok(size) => size, @@ -49,7 +57,17 @@ impl FileInfo { .created() .ok() .and_then(|t| t.duration_since(UNIX_EPOCH).ok()) - .map(|d| d.as_millis()); + .map(|d| d.as_millis()) + .or_else(|| { + // Fallback to ctime on Unix systems + #[cfg(unix)] + { + use std::os::unix::fs::MetadataExt; + Some(metadata.ctime() as u128 * 1000) + } + #[cfg(not(unix))] + None + }); let modified_time = metadata .modified() @@ -62,12 +80,15 @@ impl FileInfo { // Owner info (Unix/Linux only) let owner = get_file_owner(path); - // Parent directory - let parent_dir = path.parent().map(|p| p.to_string_lossy().to_string()); + // Parent directory is current_dir (relative to root_dir without leading /) + let parent_dir = current + .strip_prefix(root) + .ok() + .map(|rel| rel.to_string_lossy().to_string()); - // Relative path from current directory + // Relative path from root_dir to file (without leading /) let rel_path = path - .strip_prefix(¤t_dir) + .strip_prefix(root) .ok() .map(|rel| rel.to_string_lossy().to_string());