mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-04 13:23:28 +00:00
[ENG-1229] Show hidden files not working correctly (#1583)
* Ensure hidden prop is updated when file is modified * Fix show hidden files in ephemeral locations * Restore hidden prop for NonIndexedPathItem
This commit is contained in:
parent
7ea5a0ee5b
commit
34fe26e442
|
@ -79,6 +79,7 @@ file_path::select!(file_path_walker {
|
|||
date_modified
|
||||
inode
|
||||
size_in_bytes_bytes
|
||||
hidden
|
||||
});
|
||||
file_path::select!(file_path_to_handle_custom_uri {
|
||||
pub_id
|
||||
|
@ -128,12 +129,13 @@ pub struct FilePathMetadata {
|
|||
pub hidden: bool,
|
||||
}
|
||||
|
||||
pub fn path_is_hidden(path: &Path, metadata: &Metadata) -> bool {
|
||||
pub fn path_is_hidden(path: impl AsRef<Path>, metadata: &Metadata) -> bool {
|
||||
#[cfg(target_family = "unix")]
|
||||
{
|
||||
use std::ffi::OsStr;
|
||||
let _ = metadata; // just to avoid warnings on Linux
|
||||
if path
|
||||
.as_ref()
|
||||
.file_name()
|
||||
.and_then(OsStr::to_str)
|
||||
.map(|s| s.starts_with('.'))
|
||||
|
@ -147,6 +149,7 @@ pub fn path_is_hidden(path: &Path, metadata: &Metadata) -> bool {
|
|||
{
|
||||
use std::os::macos::fs::MetadataExt;
|
||||
|
||||
// https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemDetails/FileSystemDetails.html#:~:text=UF_HIDDEN
|
||||
const UF_HIDDEN: u32 = 0x8000;
|
||||
|
||||
if (metadata.st_flags() & UF_HIDDEN) == UF_HIDDEN {
|
||||
|
@ -171,7 +174,10 @@ pub fn path_is_hidden(path: &Path, metadata: &Metadata) -> bool {
|
|||
}
|
||||
|
||||
impl FilePathMetadata {
|
||||
pub async fn from_path(path: &Path, metadata: &Metadata) -> Result<Self, FilePathError> {
|
||||
pub async fn from_path(
|
||||
path: impl AsRef<Path>,
|
||||
metadata: &Metadata,
|
||||
) -> Result<Self, FilePathError> {
|
||||
let inode = {
|
||||
#[cfg(target_family = "unix")]
|
||||
{
|
||||
|
@ -180,13 +186,13 @@ impl FilePathMetadata {
|
|||
|
||||
#[cfg(target_family = "windows")]
|
||||
{
|
||||
get_inode_from_path(&path).await?
|
||||
get_inode_from_path(path.as_ref()).await?
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
inode,
|
||||
hidden: path_is_hidden(path, metadata),
|
||||
hidden: path_is_hidden(path.as_ref(), metadata),
|
||||
size_in_bytes: metadata.len(),
|
||||
created_at: metadata.created_or_now().into(),
|
||||
modified_at: metadata.modified_or_now().into(),
|
||||
|
|
|
@ -232,6 +232,10 @@ async fn execute_indexer_update_step(
|
|||
(date_modified::NAME, json!(entry.metadata.modified_at)),
|
||||
date_modified::set(Some(entry.metadata.modified_at.into())),
|
||||
),
|
||||
(
|
||||
(hidden::NAME, json!(entry.metadata.hidden)),
|
||||
hidden::set(Some(entry.metadata.hidden)),
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.unzip();
|
||||
|
|
|
@ -104,7 +104,7 @@ pub fn no_os_protected() -> SystemIndexerRule {
|
|||
"C:/Users/*/ntuser.dat*",
|
||||
"C:/Users/*/{ntuser.ini,ntuser.dat,NTUSER.DAT}",
|
||||
// User special folders (most of these the user dont even have permission to access)
|
||||
"C:/Users/*/{Cookies,AppData,NetHood,Recent,PrintHood,SendTo,Templates,Start Menu,Application Data,Local Settings}",
|
||||
"C:/Users/*/{Cookies,AppData,NetHood,Recent,PrintHood,SendTo,Templates,Start Menu,Application Data,Local Settings,My Documents}",
|
||||
// System special folders
|
||||
"C:/{$Recycle.Bin,$WinREAgent,Documents and Settings,Program Files,Program Files (x86),ProgramData,Recovery,PerfLogs,Windows,Windows.old}",
|
||||
// NTFS internal dir, can exists on any drive
|
||||
|
|
|
@ -296,7 +296,7 @@ where
|
|||
|
||||
indexed_paths.insert(WalkingEntry {
|
||||
iso_file_path: iso_file_path_factory(root, true)?,
|
||||
maybe_metadata: Some(FilePathMetadata::from_path(root, &metadata).await?),
|
||||
maybe_metadata: Some(FilePathMetadata::from_path(&root, &metadata).await?),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,7 @@ where
|
|||
// Datetimes stored in DB loses a bit of precision, so we need to check against a delta
|
||||
// instead of using != operator
|
||||
|| DateTime::<FixedOffset>::from(metadata.modified_at) - *date_modified
|
||||
> Duration::milliseconds(1)
|
||||
> Duration::milliseconds(1) || file_path.hidden.is_none() || metadata.hidden != file_path.hidden.unwrap_or_default()
|
||||
)
|
||||
// We ignore the size of directories because it is not reliable, we need to
|
||||
// calculate it ourselves later
|
||||
|
@ -528,7 +528,7 @@ where
|
|||
let Ok(metadata) = entry
|
||||
.metadata()
|
||||
.await
|
||||
.map_err(|e| errors.push(FileIOError::from((entry.path(), e)).into()))
|
||||
.map_err(|e| errors.push(FileIOError::from((¤t_path, e)).into()))
|
||||
else {
|
||||
continue 'entries;
|
||||
};
|
||||
|
@ -575,7 +575,7 @@ where
|
|||
// Then we mark this directory the be walked in too
|
||||
if let Some(ref mut to_walk) = maybe_to_walk {
|
||||
to_walk.push_back(ToWalkEntry {
|
||||
path: entry.path(),
|
||||
path: current_path.clone(),
|
||||
parent_dir_accepted_by_its_children: accept_by_children_dir,
|
||||
maybe_parent: Some(path.clone()),
|
||||
});
|
||||
|
@ -640,7 +640,7 @@ where
|
|||
continue;
|
||||
};
|
||||
|
||||
let Ok(metadata) = FilePathMetadata::from_path(ancestor, &metadata)
|
||||
let Ok(metadata) = FilePathMetadata::from_path(&ancestor, &metadata)
|
||||
.await
|
||||
.map_err(|e| errors.push(e.into()))
|
||||
else {
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
check_file_path_exists, create_file_path, file_path_with_object,
|
||||
filter_existing_file_path_params,
|
||||
isolated_file_path_data::extract_normalized_materialized_path_str,
|
||||
loose_find_existing_file_path_params, FilePathError, FilePathMetadata,
|
||||
loose_find_existing_file_path_params, path_is_hidden, FilePathError, FilePathMetadata,
|
||||
IsolatedFilePathData, MetadataExt,
|
||||
},
|
||||
find_location,
|
||||
|
@ -123,7 +123,7 @@ pub(super) async fn create_dir(
|
|||
library,
|
||||
iso_file_path,
|
||||
None,
|
||||
FilePathMetadata::from_path(path, metadata).await?,
|
||||
FilePathMetadata::from_path(&path, metadata).await?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -176,7 +176,7 @@ async fn inner_create_file(
|
|||
let iso_file_path = IsolatedFilePathData::new(location_id, location_path, path, false)?;
|
||||
let extension = iso_file_path.extension.to_string();
|
||||
|
||||
let metadata = FilePathMetadata::from_path(path, metadata).await?;
|
||||
let metadata = FilePathMetadata::from_path(&path, metadata).await?;
|
||||
|
||||
// First we check if already exist a file with this same inode number
|
||||
// if it does, we just update it
|
||||
|
@ -416,6 +416,7 @@ async fn inner_update_file(
|
|||
}
|
||||
};
|
||||
|
||||
let is_hidden = path_is_hidden(full_path, &fs_metadata);
|
||||
if file_path.cas_id != cas_id {
|
||||
let (sync_params, db_params): (Vec<_>, Vec<_>) = {
|
||||
use file_path::*;
|
||||
|
@ -470,6 +471,16 @@ async fn inner_update_file(
|
|||
((inode::NAME, serde_json::Value::Null), None)
|
||||
}
|
||||
},
|
||||
{
|
||||
if is_hidden != file_path.hidden.unwrap_or_default() {
|
||||
(
|
||||
(hidden::NAME, json!(inode)),
|
||||
Some(hidden::set(Some(is_hidden))),
|
||||
)
|
||||
} else {
|
||||
((hidden::NAME, serde_json::Value::Null), None)
|
||||
}
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.filter_map(|(sync_param, maybe_db_param)| {
|
||||
|
@ -578,6 +589,26 @@ async fn inner_update_file(
|
|||
|
||||
invalidate_query!(library, "search.paths");
|
||||
invalidate_query!(library, "search.objects");
|
||||
} else if is_hidden != file_path.hidden.unwrap_or_default() {
|
||||
sync.write_ops(
|
||||
db,
|
||||
(
|
||||
vec![sync.shared_update(
|
||||
prisma_sync::file_path::SyncId {
|
||||
pub_id: file_path.pub_id.clone(),
|
||||
},
|
||||
file_path::hidden::NAME,
|
||||
json!(is_hidden),
|
||||
)],
|
||||
db.file_path().update(
|
||||
file_path::pub_id::equals(file_path.pub_id.clone()),
|
||||
vec![file_path::hidden::set(Some(is_hidden))],
|
||||
),
|
||||
),
|
||||
)
|
||||
.await?;
|
||||
|
||||
invalidate_query!(library, "search.paths");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -649,7 +680,7 @@ pub(super) async fn rename(
|
|||
trace!("Updated {updated} file_paths");
|
||||
}
|
||||
|
||||
let metadata = FilePathMetadata::from_path(new_path, &new_path_metadata).await?;
|
||||
let is_hidden = path_is_hidden(new_path, &new_path_metadata);
|
||||
|
||||
library
|
||||
.db
|
||||
|
@ -663,7 +694,7 @@ pub(super) async fn rename(
|
|||
file_path::date_modified::set(Some(
|
||||
DateTime::<Utc>::from(new_path_metadata.modified_or_now()).into(),
|
||||
)),
|
||||
file_path::hidden::set(Some(metadata.hidden)),
|
||||
file_path::hidden::set(Some(is_hidden)),
|
||||
],
|
||||
)
|
||||
.exec()
|
||||
|
|
|
@ -131,11 +131,11 @@ impl<'lib> EventHandler<'lib> for WindowsEventHandler<'lib> {
|
|||
)
|
||||
.await?;
|
||||
} else {
|
||||
let metadata = fs::metadata(&paths[0])
|
||||
.await
|
||||
.map_err(|e| FileIOError::from((&paths[0], e)))?;
|
||||
|
||||
let path = paths.remove(0);
|
||||
let metadata = fs::metadata(&path)
|
||||
.await
|
||||
.map_err(|e| FileIOError::from((&path, e)))?;
|
||||
|
||||
if metadata.is_dir() {
|
||||
// Don't need to dispatch a recalculate directory event as `create_dir` dispatches
|
||||
// a `scan_location_sub_path` function, which recalculates the size already
|
||||
|
|
|
@ -46,7 +46,7 @@ const EphemeralExplorer = memo((props: { args: PathParams }) => {
|
|||
'search.ephemeralPaths',
|
||||
{
|
||||
path: path ?? (os === 'windows' ? 'C:\\' : '/'),
|
||||
withHiddenFiles: false,
|
||||
withHiddenFiles: settingsSnapshot.showHiddenFiles,
|
||||
order: settingsSnapshot.order
|
||||
}
|
||||
],
|
||||
|
@ -63,13 +63,6 @@ const EphemeralExplorer = memo((props: { args: PathParams }) => {
|
|||
const ret: ExplorerItem[] = [];
|
||||
|
||||
for (const item of query.data.entries) {
|
||||
if (
|
||||
!settingsSnapshot.showHiddenFiles &&
|
||||
item.type === 'NonIndexedPath' &&
|
||||
item.item.hidden
|
||||
)
|
||||
continue;
|
||||
|
||||
if (settingsSnapshot.layoutMode !== 'media') ret.push(item);
|
||||
else {
|
||||
const { kind } = getExplorerItemData(item);
|
||||
|
|
Loading…
Reference in a new issue