Skip to content

Commit 66427ee

Browse files
authored
feat(ui): allow directory selection and include all files recursively… (#58)
* feat(ui): allow directory selection and include all files recursively #57 * refactor: use walkdir crate instead of own solution #57
1 parent 4511e44 commit 66427ee

8 files changed

Lines changed: 87 additions & 15 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clap::Parser;
2+
use colored::*;
23
use ffzap_core::{load_paths, CmdArgs, Logger, Processor, Progress};
34
use std::sync::Arc;
4-
use colored::*;
55

66
fn main() {
77
let cmd_args = CmdArgs::parse();

core/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ clap.workspace = true
2121
serde = { workspace = true, features = ["derive"] }
2222
tauri = { workspace = true, optional = true }
2323
colored = { workspace = true }
24+
walkdir = "2.5.0"
2425

2526

2627
[features]

core/src/lib.rs

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@ pub mod logger;
33
pub mod processor;
44
pub mod progress;
55

6-
use std::process::exit;
7-
use std::{fs, io::ErrorKind};
8-
#[cfg(feature = "ui")]
9-
use tauri::{AppHandle, Emitter};
106
pub use args::CmdArgs;
117
pub use logger::Logger;
128
pub use processor::Processor;
139
pub use progress::Progress;
10+
use std::path::Path;
11+
use std::process::exit;
12+
use std::{fs, io::ErrorKind};
13+
#[cfg(feature = "ui")]
14+
use tauri::{AppHandle, Emitter};
15+
use walkdir::WalkDir;
1416

1517
pub fn load_paths(
1618
cmd_args: &CmdArgs,
17-
#[cfg(feature = "ui")]
18-
app_handle: &AppHandle
19+
#[cfg(feature = "ui")] app_handle: &AppHandle,
1920
) -> Vec<String> {
2021
if let Some(input_file_path) = &cmd_args.file_list {
2122
match fs::read_to_string(input_file_path) {
@@ -33,7 +34,8 @@ pub fn load_paths(
3334
exit(1);
3435
}
3536
ErrorKind::PermissionDenied => {
36-
let error = format!("Permission denied when reading file {input_file_path}.");
37+
let error =
38+
format!("Permission denied when reading file {input_file_path}.");
3739
eprintln!("{}", error);
3840
#[cfg(not(feature = "ui"))]
3941
exit(1);
@@ -76,6 +78,43 @@ pub fn load_paths(
7678
}
7779
}
7880
} else {
79-
cmd_args.input.clone().unwrap()
81+
let paths = cmd_args.input.clone().unwrap();
82+
let mut files: Vec<String> = vec![];
83+
84+
for p in paths {
85+
let path = Path::new(&p);
86+
if path.is_file() {
87+
files.push(p);
88+
} else if path.is_dir() {
89+
for entry in WalkDir::new(path)
90+
.follow_links(false)
91+
.into_iter()
92+
.filter_entry(|e| !e.path_is_symlink())
93+
{
94+
match entry {
95+
Ok(entry) => {
96+
if entry.file_type().is_file() {
97+
files.push(entry.path().to_str().unwrap().to_string());
98+
}
99+
}
100+
Err(err) => {
101+
let error = format!(
102+
"Failed to read directory {}: {}",
103+
&err.path().unwrap().display(),
104+
err
105+
);
106+
107+
#[cfg(not(feature = "ui"))]
108+
eprintln!("{}", error);
109+
110+
#[cfg(feature = "ui")]
111+
let _ = app_handle.emit("file-list-error", error);
112+
}
113+
}
114+
}
115+
}
116+
}
117+
118+
files
80119
}
81120
}

core/src/logger.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
use tauri::AppHandle;
33

44
use crate::progress::Progress;
5+
use colored::*;
56
use std::fs;
67
use std::fs::File;
78
use std::io::Write;
89
use std::path::{Display, PathBuf};
910
use std::sync::{Arc, Mutex, MutexGuard};
10-
use colored::*;
1111

1212
pub struct Logger {
1313
progress: Arc<Progress>,

ui/index.html

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,15 @@ <h2>Input Files</h2>
3232
<button class="browse-btn" id="browse-files-btn">
3333
Browse Files
3434
</button>
35+
<button class="browse-btn" id="browse-folder-btn">
36+
Browse Folders
37+
</button>
3538
</div>
3639
<div class="selected-files">
3740
<h3>Selected Files (<span id="file-amount">0</span>)</h3>
41+
<div class="info-text">
42+
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.
43+
</div>
3844
<div class="file-list" id="file-list">Non selected</div>
3945
</div>
4046
</div>
@@ -45,9 +51,9 @@ <h3>Selected Files (<span id="file-amount">0</span>)</h3>
4551
Browse Files
4652
</button>
4753
</div>
48-
<div class="selected-files">
54+
<div class="selected-file-list">
4955
<h3>File List Path</h3>
50-
<div class="file-list-path" id="file-list-path">
56+
<div class="file-list" id="file-list-path">
5157
None selected
5258
</div>
5359
</div>
@@ -74,7 +80,7 @@ <h2>Processing Options</h2>
7480
<span class="info-text"
7581
>Most systems can handle 2. Increase for powerful computers.
7682
Adding more threads does not automatically make your job
77-
faster!</span
83+
faster! Balance out your ffmpeg options accordingly.</span
7884
>
7985
</div>
8086
</div>

ui/src/main.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ document.addEventListener('DOMContentLoaded', () => {
3434
const browseListBtn = document.getElementById(
3535
'browse-list-btn',
3636
) as HTMLButtonElement;
37+
const browseFolderBtn = document.getElementById('browse-folder-btn') as HTMLButtonElement;
3738

3839
browseFilesBtn.addEventListener('click', async () => {
3940
const files: string[] | null = await open({
@@ -49,6 +50,20 @@ document.addEventListener('DOMContentLoaded', () => {
4950
updateFileList(filesList);
5051
validateButton(allFiles, filesList);
5152
});
53+
browseFolderBtn.addEventListener('click', async () => {
54+
const path: string | null = await open({
55+
multiple: false,
56+
directory: true,
57+
});
58+
59+
allFiles = path ? [path] : [];
60+
filesList = null;
61+
62+
updateFileCount(allFiles?.length ?? 0);
63+
updatePathsList(allFiles);
64+
updateFileList(filesList);
65+
validateButton(allFiles, filesList);
66+
})
5267
browseListBtn.addEventListener('click', async () => {
5368
const file: string | null = await open({
5469
multiple: false,

ui/src/styles.css

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ body {
195195
/* File Input Section */
196196
.browse-files-btn-container {
197197
display: flex;
198+
gap: var(--space-md);
198199
justify-content: center;
199200
}
200201

@@ -226,12 +227,21 @@ body {
226227
margin-top: var(--space-xl);
227228
}
228229

229-
.selected-files h3 {
230+
.selected-files h3,
231+
.selected-file-list h3 {
230232
font-size: var(--font-lg);
231-
margin-bottom: var(--space-md);
233+
margin-bottom: 0;
232234
color: var(--text-color);
233235
}
234236

237+
.selected-files .info-text {
238+
margin-bottom: var(--space-md);
239+
}
240+
241+
.selected-file-list h3 {
242+
margin-bottom: var(--space-md);
243+
}
244+
235245
.file-list-input {
236246
display: flex;
237247
gap: var(--space-sm);

0 commit comments

Comments
 (0)