Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/Files.App/ViewModels/ShellViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ public sealed partial class ShellViewModel : ObservableObject, IDisposable
// Only used for Binding and ApplyFilesAndFoldersChangesAsync, don't manipulate on this!
public BulkConcurrentObservableCollection<ListedItem> FilesAndFolders { get; }

/// <summary>
/// Gets the total count of all enumerated items including those that may be filtered from the display.
/// This represents the actual number of items in the directory, not just the visible ones.
/// </summary>
public int TotalItemCount => filesAndFolders?.Count ?? 0;

private LayoutPreferencesManager folderSettings = null;

private ListedItem? currentFolder;
Expand Down Expand Up @@ -2093,7 +2099,7 @@ public async Task<CloudDriveSyncStatus> CheckCloudDriveSyncStatusAsync(IStorageI
else if (matchingStorageItem is BaseStorageFolder folder && folder.Properties != null)
return await FilesystemTasks.Wrap(() => folder.Properties.RetrievePropertiesAsync(["System.FreeSpace", "System.Capacity", "System.SFGAOFlags"]).AsTask());

return null;
return null;
}

private async Task WatchForStorageFolderChangesAsync(BaseStorageFolder? rootFolder)
Expand Down Expand Up @@ -2244,6 +2250,7 @@ private void WatchForDirectoryChanges(string path, CloudDriveSyncStatus syncStat
do
{
notifyInfo = ref Unsafe.As<byte, FILE_NOTIFY_INFORMATION>(ref buff[offset]);

string? FileName = null;
unsafe
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace Files.App.ViewModels.Previews
{
public sealed class FolderPreviewViewModel
{
private readonly IContentPageContext _contentPageContext = Ioc.Default.GetRequiredService<IContentPageContext>();

public ListedItem Item { get; }

public BitmapImage Thumbnail { get; set; } = new();
Expand All @@ -25,7 +27,9 @@ private async Task LoadPreviewAndDetailsAsync()
{
var rootItem = await FilesystemTasks.Wrap(() => DriveHelpers.GetRootFromPathAsync(Item.ItemPath));
Folder = await StorageFileExtensions.DangerousGetFolderFromPathAsync(Item.ItemPath, rootItem);
var items = await Folder.GetItemsAsync();

// Get actual item count including hidden files based on user settings
int itemCount = await GetItemCountAsync();

var result = await FileThumbnailHelper.GetIconAsync(
Item.ItemPath,
Expand All @@ -46,7 +50,7 @@ private async Task LoadPreviewAndDetailsAsync()

Item.FileDetails =
[
GetFileProperty("PropertyItemCount", items.Count),
GetFileProperty("PropertyItemCount", itemCount),
GetFileProperty("PropertyDateModified", info.DateModified),
GetFileProperty("PropertyDateCreated", info.DateCreated),
GetFileProperty("PropertyParsingPath", Folder.Path),
Expand All @@ -67,6 +71,72 @@ private async Task LoadPreviewAndDetailsAsync()
}
}

private async Task<int> GetItemCountAsync()
{
// If this is the current folder being viewed, use ShellViewModel's TotalItemCount
// which includes hidden files when the setting is enabled (same as status bar)
if (_contentPageContext.ShellPage?.ShellViewModel is not null &&
_contentPageContext.Folder?.ItemPath == Item.ItemPath)
{
return _contentPageContext.ShellPage.ShellViewModel.TotalItemCount;
}

// For other folders (e.g., selected folder in the file list), enumerate directly
// This respects the user's "Show hidden files" setting
return await Task.Run(() => CountItemsInFolder(Item.ItemPath));
}

private static int CountItemsInFolder(string folderPath)
{
try
{
var userSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>();
var showHiddenItems = userSettingsService.FoldersSettingsService.ShowHiddenItems;
var showProtectedSystemFiles = userSettingsService.FoldersSettingsService.ShowProtectedSystemFiles;

int count = 0;
var directory = new DirectoryInfo(folderPath);

// Count files
foreach (var file in directory.EnumerateFiles())
{
var isHidden = (file.Attributes & System.IO.FileAttributes.Hidden) != 0;
var isSystem = (file.Attributes & System.IO.FileAttributes.System) != 0;

// Skip hidden & system files if their respective settings are off
if (isHidden && (!showHiddenItems || (isSystem && !showProtectedSystemFiles)))
continue;

count++;
}

// Count directories
foreach (var dir in directory.EnumerateDirectories())
{
var isHidden = (dir.Attributes & System.IO.FileAttributes.Hidden) != 0;
var isSystem = (dir.Attributes & System.IO.FileAttributes.System) != 0;

// Skip hidden & system directories if their respective settings are off
if (isHidden && (!showHiddenItems || (isSystem && !showProtectedSystemFiles)))
continue;

count++;
}

return count;
}
catch (UnauthorizedAccessException)
{
// If we can't access the folder, return 0
return 0;
}
catch (Exception)
{
// For any other error, return 0
return 0;
}
}

private static FileProperty GetFileProperty(string nameResource, object value)
=> new() { NameResource = nameResource, Value = value };
}
Expand Down
4 changes: 2 additions & 2 deletions src/Files.App/Views/Shells/BaseShellPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ protected async void FilesystemViewModel_DirectoryInfoUpdated(object sender, Eve
if (ContentPage is null)
return;

var directoryItemCountLocalization = Strings.Items.GetLocalizedFormatResource(ShellViewModel.FilesAndFolders.Count);
var directoryItemCountLocalization = Strings.Items.GetLocalizedFormatResource(ShellViewModel.TotalItemCount);

BranchItem? headBranch = headBranch = InstanceViewModel.IsGitRepository
? await GitHelpers.GetRepositoryHead(InstanceViewModel.GitRepositoryPath)
Expand Down Expand Up @@ -265,7 +265,7 @@ protected async void FilesystemViewModel_DirectoryInfoUpdated(object sender, Eve
headBranch);
}

contentPage.StatusBarViewModel.DirectoryItemCount = $"{ShellViewModel.FilesAndFolders.Count} {directoryItemCountLocalization}";
contentPage.StatusBarViewModel.DirectoryItemCount = $"{ShellViewModel.TotalItemCount} {directoryItemCountLocalization}";
contentPage.UpdateSelectionSize();
}

Expand Down
Loading