project_panel: Add ability to hide hidden files (#39843)

Closes #5185

Release Notes:

- Added an option to hide hidden files in the project panel by setting
`hide_hidden` in the project panel settings.

---------

Co-authored-by: Gaauwe Rombouts <gromdroid@gmail.com>
Co-authored-by: Gaauwe Rombouts <mail@grombouts.nl>
This commit is contained in:
Smit Barmase
2025-10-12 18:31:55 +05:30
committed by GitHub
co-authored by Gaauwe Rombouts Gaauwe Rombouts
parent abe1fd5e16
commit 998fece3af
16 changed files with 223 additions and 4 deletions
+31
View File
@@ -439,6 +439,10 @@ impl Worktree {
entry.is_private = !share_private_files && settings.is_path_private(path);
}
}
entry.is_hidden = abs_path
.file_name()
.and_then(|name| name.to_str())
.map_or(false, |name| is_path_hidden(name));
snapshot.insert_entry(entry, fs.as_ref());
}
@@ -2668,6 +2672,7 @@ impl BackgroundScannerState {
scan_queue: scan_job_tx.clone(),
ancestor_inodes,
is_external: entry.is_external,
is_hidden: entry.is_hidden,
})
.unwrap();
}
@@ -3177,6 +3182,11 @@ pub struct Entry {
/// exclude them from searches.
pub is_ignored: bool,
/// Whether this entry is hidden or inside hidden directory.
///
/// We only scan hidden entries once the directory is expanded.
pub is_hidden: bool,
/// Whether this entry is always included in searches.
///
/// This is used for entries that are always included in searches, even
@@ -3351,6 +3361,7 @@ impl Entry {
size: metadata.len,
canonical_path,
is_ignored: false,
is_hidden: false,
is_always_included: false,
is_external: false,
is_private: false,
@@ -4219,6 +4230,11 @@ impl BackgroundScanner {
child_entry.canonical_path = Some(canonical_path.into());
}
child_entry.is_hidden = job.is_hidden
|| child_name
.to_str()
.map_or(false, |name| is_path_hidden(name));
if child_entry.is_dir() {
child_entry.is_ignored = ignore_stack.is_abs_path_ignored(&child_abs_path, true);
child_entry.is_always_included = self.settings.is_path_always_included(&child_path);
@@ -4234,6 +4250,7 @@ impl BackgroundScanner {
abs_path: child_abs_path.clone(),
path: child_path,
is_external: child_entry.is_external,
is_hidden: child_entry.is_hidden,
ignore_stack: if child_entry.is_ignored {
IgnoreStack::all()
} else {
@@ -4384,6 +4401,13 @@ impl BackgroundScanner {
fs_entry.is_private = self.is_path_private(path);
fs_entry.is_always_included = self.settings.is_path_always_included(path);
let parent_is_hidden = path
.parent()
.and_then(|parent| state.snapshot.entry_for_path(parent))
.map_or(false, |parent_entry| parent_entry.is_hidden);
fs_entry.is_hidden = parent_is_hidden
|| path.file_name().map_or(false, |name| is_path_hidden(name));
if let (Some(scan_queue_tx), true) = (&scan_queue_tx, is_dir) {
if state.should_scan_directory(&fs_entry)
|| (fs_entry.path.is_empty()
@@ -4945,6 +4969,10 @@ fn char_bag_for_path(root_char_bag: CharBag, path: &RelPath) -> CharBag {
result
}
fn is_path_hidden(name: &str) -> bool {
name.starts_with('.')
}
#[derive(Debug)]
struct ScanJob {
abs_path: Arc<Path>,
@@ -4953,6 +4981,7 @@ struct ScanJob {
scan_queue: Sender<ScanJob>,
ancestor_inodes: TreeSet<u64>,
is_external: bool,
is_hidden: bool,
}
struct UpdateIgnoreStatusJob {
@@ -5374,6 +5403,7 @@ impl<'a> From<&'a Entry> for proto::Entry {
inode: entry.inode,
mtime: entry.mtime.map(|time| time.into()),
is_ignored: entry.is_ignored,
is_hidden: entry.is_hidden,
is_external: entry.is_external,
is_fifo: entry.is_fifo,
size: Some(entry.size),
@@ -5412,6 +5442,7 @@ impl TryFrom<(&CharBag, &PathMatcher, proto::Entry)> for Entry {
.canonical_path
.map(|path_string| Arc::from(PathBuf::from(path_string))),
is_ignored: entry.is_ignored,
is_hidden: entry.is_hidden,
is_always_included,
is_external: entry.is_external,
is_private: false,