feature/exif-endpoint #44

Merged
cameron merged 29 commits from feature/exif-endpoint into master 2025-12-27 03:25:19 +00:00
Showing only changes of commit 28d85dc4a5 - Show all commits

View File

@@ -250,6 +250,15 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
true true
} }
}) })
.filter(|f| {
// Apply media type filtering if specified
if let Some(ref media_type) = req.media_type {
let path = PathBuf::from(&f.file_name);
matches_media_type(&path, media_type)
} else {
true
}
})
.collect::<Vec<FileWithTagCount>>() .collect::<Vec<FileWithTagCount>>()
}) })
.map(|files| sort(files, req.sort.unwrap_or(NameAsc))) .map(|files| sort(files, req.sort.unwrap_or(NameAsc)))
@@ -274,9 +283,33 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
.unwrap_or_else(|e| e.error_response()); .unwrap_or_else(|e| e.error_response());
} }
match file_system.get_files_for_path(search_path) { // Use recursive or non-recursive file listing based on flag
let files_result = if search_recursively {
// For recursive search without tags, manually list files recursively
is_valid_full_path(
&PathBuf::from(&app_state.base_path),
&PathBuf::from(search_path),
false,
)
.map(|path| {
debug!("Valid path for recursive search: {:?}", path);
list_files_recursive(&path).unwrap_or_default()
})
.context("Invalid path")
} else {
file_system.get_files_for_path(search_path)
};
match files_result {
Ok(files) => { Ok(files) => {
info!("Found {:?} files in path: {:?}", files.len(), search_path); info!(
"Found {:?} files in path: {:?} (recursive: {})",
files.len(),
search_path,
search_recursively
);
info!("Starting to filter {} files from filesystem", files.len());
let photos = files let photos = files
.iter() .iter()
@@ -356,11 +389,13 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
}) })
.collect::<Vec<FileWithTagCount>>(); .collect::<Vec<FileWithTagCount>>();
info!("After all filters, {} files remain", photos.len());
// Handle sorting - use FileWithMetadata for date sorting to support EXIF dates // Handle sorting - use FileWithMetadata for date sorting to support EXIF dates
let response_files = if let Some(sort_type) = req.sort { let response_files = if let Some(sort_type) = req.sort {
match sort_type { match sort_type {
SortType::DateTakenAsc | SortType::DateTakenDesc => { SortType::DateTakenAsc | SortType::DateTakenDesc => {
debug!("Date sorting requested, fetching EXIF data"); info!("Date sorting requested, fetching EXIF data");
// Collect file paths for batch EXIF query // Collect file paths for batch EXIF query
let file_paths: Vec<String> = let file_paths: Vec<String> =
@@ -533,6 +568,43 @@ pub fn list_files(dir: &Path) -> io::Result<Vec<PathBuf>> {
Ok(files) Ok(files)
} }
pub fn list_files_recursive(dir: &Path) -> io::Result<Vec<PathBuf>> {
let tracer = global_tracer();
let mut span = tracer.start("list_files_recursive");
let dir_name_string = dir.to_str().unwrap_or_default().to_string();
span.set_attribute(KeyValue::new("dir", dir_name_string));
info!("Recursively listing files in: {:?}", dir);
let mut result = Vec::new();
fn visit_dirs(dir: &Path, files: &mut Vec<PathBuf>) -> io::Result<()> {
if dir.is_dir() {
for entry in read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
visit_dirs(&path, files)?;
} else if is_image_or_video(&path) {
files.push(path);
}
}
}
Ok(())
}
visit_dirs(dir, &mut result)?;
span.set_attribute(KeyValue::new("file_count", result.len().to_string()));
span.set_status(Status::Ok);
info!(
"Found {:?} files recursively in directory: {:?}",
result.len(),
dir
);
Ok(result)
}
pub fn is_image_or_video(path: &Path) -> bool { pub fn is_image_or_video(path: &Path) -> bool {
let extension = path let extension = path
.extension() .extension()
@@ -560,7 +632,7 @@ fn matches_media_type(path: &Path, media_type: &MediaType) -> bool {
.and_then(|p| p.to_str()) .and_then(|p| p.to_str())
.map_or(String::from(""), |p| p.to_lowercase()); .map_or(String::from(""), |p| p.to_lowercase());
match media_type { let result = match media_type {
MediaType::All => true, MediaType::All => true,
MediaType::Photo => { MediaType::Photo => {
extension == "png" extension == "png"
@@ -575,7 +647,14 @@ fn matches_media_type(path: &Path, media_type: &MediaType) -> bool {
|| extension == "avif" || extension == "avif"
} }
MediaType::Video => extension == "mp4" || extension == "mov", MediaType::Video => extension == "mp4" || extension == "mov",
} };
debug!(
"Media type check: path={:?}, extension='{}', type={:?}, match={}",
path, extension, media_type, result
);
result
} }
pub fn is_valid_full_path<P: AsRef<Path> + Debug + AsRef<std::ffi::OsStr>>( pub fn is_valid_full_path<P: AsRef<Path> + Debug + AsRef<std::ffi::OsStr>>(