[Peek]Asynchronously display correct folder size (#31504)

* asynchronously display correct folder size

* use async
This commit is contained in:
Davide Giacometti
2024-02-27 17:09:32 +01:00
committed by GitHub
parent 79de69547e
commit 1f9fd2631c
4 changed files with 105 additions and 42 deletions

View File

@@ -102,32 +102,6 @@ namespace Peek.Common.Extensions
return size;
}
public static ulong GetSizeInBytes(this IFileSystemItem item)
{
ulong sizeInBytes = 0;
try
{
switch (item)
{
case FolderItem _:
FileSystemObject fileSystemObject = new FileSystemObject();
Folder folder = fileSystemObject.GetFolder(item.Path);
sizeInBytes = (ulong)folder.Size;
break;
case FileItem _:
sizeInBytes = item.FileSizeBytes;
break;
}
}
catch
{
sizeInBytes = 0;
}
return sizeInBytes;
}
public static async Task<string> GetContentTypeAsync(this IFileSystemItem item)
{
string contentType = string.Empty;

View File

@@ -349,9 +349,7 @@ namespace Peek.FilePreviewer
string dateModifiedFormatted = string.IsNullOrEmpty(dateModified) ? string.Empty : "\n" + ReadableStringHelper.FormatResourceString("PreviewTooltip_DateModified", dateModified);
sb.Append(dateModifiedFormatted);
cancellationToken.ThrowIfCancellationRequested();
ulong bytes = await Task.Run(Item.GetSizeInBytes);
string fileSize = ReadableStringHelper.BytesToReadableString(bytes);
string fileSize = ReadableStringHelper.BytesToReadableString(Item.FileSizeBytes);
string fileSizeFormatted = string.IsNullOrEmpty(fileSize) ? string.Empty : "\n" + ReadableStringHelper.FormatResourceString("PreviewTooltip_FileSize", fileSize);
sb.Append(fileSizeFormatted);

View File

@@ -4,10 +4,13 @@
using System;
using System.Globalization;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using ManagedCommon;
using Microsoft.UI.Dispatching;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media.Imaging;
using Peek.Common.Extensions;
using Peek.Common.Helpers;
@@ -20,6 +23,11 @@ namespace Peek.FilePreviewer.Previewers
{
public partial class UnsupportedFilePreviewer : ObservableObject, IUnsupportedFilePreviewer, IDisposable
{
private static readonly EnumerationOptions _fileEnumOptions = new() { MatchType = MatchType.Win32, AttributesToSkip = 0, IgnoreInaccessible = true };
private static readonly EnumerationOptions _directoryEnumOptions = new() { MatchType = MatchType.Win32, AttributesToSkip = FileAttributes.ReparsePoint, IgnoreInaccessible = true };
private readonly DispatcherTimer _folderSizeDispatcherTimer = new();
private ulong _folderSize;
[ObservableProperty]
private UnsupportedFilePreviewData preview = new UnsupportedFilePreviewData();
@@ -28,6 +36,9 @@ namespace Peek.FilePreviewer.Previewers
public UnsupportedFilePreviewer(IFileSystemItem file)
{
_folderSizeDispatcherTimer.Interval = TimeSpan.FromMilliseconds(500);
_folderSizeDispatcherTimer.Tick += FolderSizeDispatcherTimer_Tick;
Item = file;
Preview.FileName = file.Name;
Preview.DateModified = file.DateModified?.ToString(CultureInfo.CurrentCulture);
@@ -46,6 +57,7 @@ namespace Peek.FilePreviewer.Previewers
public void Dispose()
{
_folderSizeDispatcherTimer.Tick -= FolderSizeDispatcherTimer_Tick;
GC.SuppressFinalize(this);
}
@@ -117,21 +129,25 @@ namespace Peek.FilePreviewer.Previewers
var isTaskSuccessful = await TaskExtension.RunSafe(async () =>
{
// File Properties
cancellationToken.ThrowIfCancellationRequested();
var bytes = await Task.Run(Item.GetSizeInBytes);
cancellationToken.ThrowIfCancellationRequested();
var type = await Task.Run(Item.GetContentTypeAsync);
cancellationToken.ThrowIfCancellationRequested();
var readableFileSize = ReadableStringHelper.BytesToReadableString(bytes);
isDisplayValid = type != null;
var readableFileSize = string.Empty;
if (Item is FileItem)
{
readableFileSize = ReadableStringHelper.BytesToReadableString(Item.FileSizeBytes);
}
else if (Item is FolderItem)
{
ComputeFolderSize(cancellationToken);
}
await Dispatcher.RunOnUiThread(() =>
{
Preview.FileSize = readableFileSize;
@@ -150,5 +166,71 @@ namespace Peek.FilePreviewer.Previewers
return !isLoadingIconPreviewSuccessful || !isLoadingDisplayInfoSuccessful;
}
private void ComputeFolderSize(CancellationToken cancellationToken)
{
Task.Run(
async () =>
{
try
{
// Special folders like recycle bin don't have a path
if (string.IsNullOrWhiteSpace(Item.Path))
{
return;
}
await Dispatcher.RunOnUiThread(_folderSizeDispatcherTimer.Start);
GetDirectorySize(new DirectoryInfo(Item.Path), cancellationToken);
}
catch (OperationCanceledException)
{
}
catch (Exception ex)
{
Logger.LogError("Failed to calculate folder size", ex);
}
finally
{
await Dispatcher.RunOnUiThread(_folderSizeDispatcherTimer.Stop);
}
// If everything went well, ensure the UI is updated
await Dispatcher.RunOnUiThread(UpdateFolderSize);
},
cancellationToken);
}
private void GetDirectorySize(DirectoryInfo directory, CancellationToken cancellationToken)
{
var files = directory.GetFiles("*", _fileEnumOptions);
for (var i = 0; i < files.Length; i++)
{
cancellationToken.ThrowIfCancellationRequested();
var f = files[i];
if (f.Length > 0)
{
_folderSize += Convert.ToUInt64(f.Length);
}
}
var directories = directory.GetDirectories("*", _directoryEnumOptions);
for (var i = 0; i < directories.Length; i++)
{
cancellationToken.ThrowIfCancellationRequested();
GetDirectorySize(directories[i], cancellationToken);
}
}
private void UpdateFolderSize()
{
Preview.FileSize = ReadableStringHelper.BytesToReadableString(_folderSize);
}
private void FolderSizeDispatcherTimer_Tick(object? sender, object e)
{
UpdateFolderSize();
}
}
}

View File

@@ -339,14 +339,23 @@ namespace Peek.UI.Views
private void UpdateDefaultAppToLaunch()
{
// Update the name of default app to launch
DefaultAppName = DefaultAppHelper.TryGetDefaultAppName(Item.Extension);
if (Item is FileItem)
{
// Update the name of default app to launch
DefaultAppName = DefaultAppHelper.TryGetDefaultAppName(Item.Extension);
string openWithAppTextFormat = ResourceLoaderInstance.ResourceLoader.GetString("LaunchAppButton_OpenWithApp_Text");
OpenWithAppText = string.Format(CultureInfo.InvariantCulture, openWithAppTextFormat, DefaultAppName);
string openWithAppTextFormat = ResourceLoaderInstance.ResourceLoader.GetString("LaunchAppButton_OpenWithApp_Text");
OpenWithAppText = string.Format(CultureInfo.InvariantCulture, openWithAppTextFormat, DefaultAppName);
string openWithAppToolTipFormat = ResourceLoaderInstance.ResourceLoader.GetString("LaunchAppButton_OpenWithApp_ToolTip");
OpenWithAppToolTip = string.Format(CultureInfo.InvariantCulture, openWithAppToolTipFormat, DefaultAppName);
string openWithAppToolTipFormat = ResourceLoaderInstance.ResourceLoader.GetString("LaunchAppButton_OpenWithApp_ToolTip");
OpenWithAppToolTip = string.Format(CultureInfo.InvariantCulture, openWithAppToolTipFormat, DefaultAppName);
}
else
{
DefaultAppName = string.Empty;
OpenWithAppText = string.Empty;
OpenWithAppToolTip = string.Empty;
}
}
}
}