From 77bdae5fff6604d6a93fa14958381836c4579201 Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Mon, 28 Jul 2025 04:13:34 +0200 Subject: [PATCH] Add directory dialog --- .../src/components/add-library-form.tsx | 17 +- .../src/components/directory-dialog.tsx | 173 ++++++++++++++++++ src/services/fs.rs | 29 ++- 3 files changed, 207 insertions(+), 12 deletions(-) create mode 100644 music-metadata-manager-frontend/src/components/directory-dialog.tsx diff --git a/music-metadata-manager-frontend/src/components/add-library-form.tsx b/music-metadata-manager-frontend/src/components/add-library-form.tsx index 30d13f1..31468dc 100644 --- a/music-metadata-manager-frontend/src/components/add-library-form.tsx +++ b/music-metadata-manager-frontend/src/components/add-library-form.tsx @@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { toast } from "sonner"; +import { DirectoryDialog } from "./directory-dialog"; export function AddLibraryForm() { const [path, setPath] = useState(""); @@ -35,12 +36,16 @@ export function AddLibraryForm() {
- setPath(e.target.value)} - placeholder="/home/username/Music" - /> +
+ setPath(e.target.value)} + placeholder="/home/username/Music" + className="flex-1" + /> + setPath(selectedPath)} /> +
+ + + + Choose a directory + + Browse for a directory to add as a library. + + + setSearchQuery(e.target.value)} + className="my-2" + /> + +
+ {renderTree(directoryTree)} +
+
+
+ + ); +} diff --git a/src/services/fs.rs b/src/services/fs.rs index ffcdc8d..bddd5ac 100644 --- a/src/services/fs.rs +++ b/src/services/fs.rs @@ -1,6 +1,7 @@ use std::{ + collections::HashSet, fs::{self, OpenOptions}, - path::Path, + path::{Path, PathBuf}, }; use serde::Serialize; @@ -13,6 +14,7 @@ pub struct Directory { name: String, path: String, parent: Option, + is_root: bool, } fn is_readable_and_writable(path: &Path) -> bool { @@ -57,6 +59,7 @@ fn is_hidden(entry: &DirEntry) -> bool { pub fn get_readable_writable_dirs(root: &Path) -> Vec { let mut dirs = Vec::new(); + let mut all_paths = HashSet::new(); for entry in WalkDir::new(root) .follow_links(false) @@ -69,13 +72,27 @@ pub fn get_readable_writable_dirs(root: &Path) -> Vec { let path = entry.path(); if is_readable_and_writable(path) { - dirs.push(Directory { - name: entry.file_name().to_string_lossy().to_string(), - path: path.to_string_lossy().to_string(), - parent: path.parent().map(|p| p.to_string_lossy().to_string()), - }); + all_paths.insert(path.to_path_buf()); } } + for path in &all_paths { + let parent = path.parent().map(|p| p.to_string_lossy().to_string()); + let is_root = parent + .as_ref() + .map(|p| !all_paths.contains(&PathBuf::from(p))) + .unwrap_or(true); + + dirs.push(Directory { + name: path + .file_name() + .map(|f| f.to_string_lossy().to_string()) + .unwrap_or_else(|| "/".to_string()), + path: path.to_string_lossy().to_string(), + parent, + is_root, + }); + } + dirs }