From 5fe3fef4862a22813354353e0c06c1a7388c589b Mon Sep 17 00:00:00 2001 From: CodeF0x Date: Mon, 17 Nov 2025 02:06:59 +0100 Subject: [PATCH] feat(ui): allow directory selection and include all files recursively #57 --- core/src/lib.rs | 52 ++++++++++++++++++++++++++++++++++++++++- ui/index.html | 9 ++++--- ui/src-tauri/src/lib.rs | 2 ++ ui/src/main.ts | 2 +- ui/src/styles.css | 13 +++++++++-- 5 files changed, 71 insertions(+), 7 deletions(-) diff --git a/core/src/lib.rs b/core/src/lib.rs index 5c198d3..ae0efc1 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -5,6 +5,7 @@ pub mod progress; use std::process::exit; use std::{fs, io::ErrorKind}; +use std::path::Path; #[cfg(feature = "ui")] use tauri::{AppHandle, Emitter}; pub use args::CmdArgs; @@ -76,6 +77,55 @@ pub fn load_paths( } } } else { - cmd_args.input.clone().unwrap() + let paths = cmd_args.input.clone().unwrap(); + let mut files: Vec = vec![]; + + for p in paths { + let path = Path::new(&p); + if path.is_file() { + files.push(p); + } else if path.is_dir() { + let mut stack = vec![path.to_path_buf()]; + while let Some(dir) = stack.pop() { + match fs::read_dir(&dir) { + Ok(entries) => { + for entry_res in entries { + if let Ok(entry) = entry_res { + let entry_path = entry.path(); + if entry_path.is_dir() { + stack.push(entry_path); + } else if entry_path.is_file() { + if let Some(s) = entry_path.to_str() { + files.push(s.to_string()); + } + } + } + } + } + Err(err) => { + let error = format!("Failed to read directory {}: {}", dir.display(), err); + eprintln!("{}", error); + + #[cfg(feature = "ui")] + { + let _ = app_handle.emit("file-list-error", error); + } + + continue; + } + } + } + } else { + let error = format!("The path {} is neither a file nor a directory.", p); + eprintln!("{}", error); + + #[cfg(feature = "ui")] + { + let _ = app_handle.emit("file-list-error", error); + } + } + } + + files } } diff --git a/ui/index.html b/ui/index.html index ee3b4e4..5e8f4c9 100644 --- a/ui/index.html +++ b/ui/index.html @@ -35,6 +35,9 @@

Input Files

Selected Files (0)

+
+ If you selected an entire folder, not all files will be listed. They'll show up in the log / progressbar once you start the job. +
Non selected
@@ -45,9 +48,9 @@

Selected Files (0)

Browse Files -
+

File List Path

-
+
None selected
@@ -74,7 +77,7 @@

Processing Options

Most systems can handle 2. Increase for powerful computers. Adding more threads does not automatically make your job - faster!
diff --git a/ui/src-tauri/src/lib.rs b/ui/src-tauri/src/lib.rs index 109cdd3..593f5f2 100644 --- a/ui/src-tauri/src/lib.rs +++ b/ui/src-tauri/src/lib.rs @@ -13,6 +13,8 @@ fn start_job(app: AppHandle, options: String) { let logger = Arc::new(Logger::new(Arc::clone(&progress), app_handle.clone())); let processor = Processor::new(Arc::clone(&logger), Arc::clone(&progress)); + println!("{:?}", paths); + let _ = app_handle.emit("update-total-file-count", paths.len()); thread::spawn(move || { diff --git a/ui/src/main.ts b/ui/src/main.ts index 37088a2..18fadc4 100644 --- a/ui/src/main.ts +++ b/ui/src/main.ts @@ -38,7 +38,7 @@ document.addEventListener('DOMContentLoaded', () => { browseFilesBtn.addEventListener('click', async () => { const files: string[] | null = await open({ multiple: true, - directory: false, + directory: true, }); allFiles = files; diff --git a/ui/src/styles.css b/ui/src/styles.css index 78e1768..540ede3 100644 --- a/ui/src/styles.css +++ b/ui/src/styles.css @@ -226,12 +226,21 @@ body { margin-top: var(--space-xl); } -.selected-files h3 { +.selected-files h3, +.selected-file-list h3 { font-size: var(--font-lg); - margin-bottom: var(--space-md); + margin-bottom: 0; color: var(--text-color); } +.selected-files .info-text { + margin-bottom: var(--space-md); +} + +.selected-file-list h3 { + margin-bottom: var(--space-md); +} + .file-list-input { display: flex; gap: var(--space-sm);