Skip to content

Commit

Permalink
Code Quality: Update thumbnail helper
Browse files Browse the repository at this point in the history
  • Loading branch information
yaira2 committed Mar 3, 2024
1 parent 4b93440 commit 2fca3f3
Show file tree
Hide file tree
Showing 20 changed files with 56 additions and 85 deletions.
3 changes: 1 addition & 2 deletions src/Files.App/Data/Items/DriveItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,9 @@ public async Task LoadThumbnailAsync()
DeviceID,
Constants.ShellIconSizes.Small,
false,
false,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

IconData ??= result.IconData;
IconData ??= result;
}

if (Root is not null)
Expand Down
3 changes: 1 addition & 2 deletions src/Files.App/Data/Items/SidebarLibraryItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,9 @@ public async Task LoadLibraryIconAsync()
Path,
Constants.ShellIconSizes.Small,
false,
false,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

var bitmapImage = await result.IconData.ToBitmapAsync();
var bitmapImage = await result.ToBitmapAsync();
if (bitmapImage is not null)
Icon = bitmapImage;
}
Expand Down
3 changes: 1 addition & 2 deletions src/Files.App/Data/Items/WidgetDriveCardItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,9 @@ public async Task LoadCardThumbnailAsync()
Item.Path,
Constants.ShellIconSizes.Large,
true,
false,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

thumbnailData = result.IconData;
thumbnailData = result;

var bitmapImage = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => thumbnailData.ToBitmapAsync(), Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
if (bitmapImage is not null)
Expand Down
3 changes: 1 addition & 2 deletions src/Files.App/Data/Items/WidgetFolderCardItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,9 @@ public async Task LoadCardThumbnailAsync()
Path,
Constants.ShellIconSizes.Large,
true,
false,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

_thumbnailData = result.IconData;
_thumbnailData = result;
if (_thumbnailData is not null)
Thumbnail = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => _thumbnailData.ToBitmapAsync(), Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
}
Expand Down
14 changes: 6 additions & 8 deletions src/Files.App/Data/Models/ItemViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -921,19 +921,18 @@ private async Task LoadThumbnailAsync(ListedItem item)
var returnIconOnly = UserSettingsService.FoldersSettingsService.ShowThumbnails == false || thumbnailSize < 48;

// Get thumbnail
var icon = await FileThumbnailHelper.GetIconAsync(
var result = await FileThumbnailHelper.GetIconAsync(
item.ItemPath,
thumbnailSize,
item.IsFolder,
false,
returnIconOnly ? IconOptions.ReturnIconOnly : IconOptions.None);

if (icon.IconData is not null)
if (result is not null)
{
await dispatcherQueue.EnqueueOrInvokeAsync(async () =>
{
// Assign FileImage property
var image = await icon.IconData.ToBitmapAsync();
var image = await result.ToBitmapAsync();
if (image is not null)
item.FileImage = image;
}, Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
Expand Down Expand Up @@ -1215,15 +1214,14 @@ await SafetyExtensions.IgnoreExceptions(() =>
ImageSource? groupImage = null;
if (item.PrimaryItemAttribute != StorageItemTypes.Folder || item.IsArchive)
{
var headerIconInfo = await FileThumbnailHelper.GetIconAsync(
var result = await FileThumbnailHelper.GetIconAsync(
item.ItemPath,
Constants.ShellIconSizes.Large,
false,
false,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

if (headerIconInfo.IconData is not null && !item.IsShortcut)
groupImage = await dispatcherQueue.EnqueueOrInvokeAsync(() => headerIconInfo.IconData.ToBitmapAsync(), Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
if (result is not null && !item.IsShortcut)
groupImage = await dispatcherQueue.EnqueueOrInvokeAsync(() => result.ToBitmapAsync(), Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);

// The groupImage is null if loading icon from fulltrust process failed
if (!item.IsShortcut && !item.IsHiddenItem && !FtpHelpers.IsFtpPath(item.ItemPath) && groupImage is null)
Expand Down
3 changes: 1 addition & 2 deletions src/Files.App/Data/Models/PinnedFoldersManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,9 @@ public async Task<LocationItem> CreateLocationItemFromPathAsync(string path)
res.Result.Path,
Constants.ShellIconSizes.Small,
true,
false,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

locationItem.IconData = result.IconData;
locationItem.IconData = result;

var bitmapImage = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => locationItem.IconData.ToBitmapAsync(), Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
if (bitmapImage is not null)
Expand Down
5 changes: 2 additions & 3 deletions src/Files.App/Helpers/Navigation/NavigationHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,10 @@ private static async Task UpdateTabInfoAsync(TabBarItem tabItem, object navigati
currentPath,
Constants.ShellIconSizes.Small,
true,
false,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

if (result.IconData is not null)
iconSource.ImageSource = await result.IconData.ToBitmapAsync();
if (result is not null)
iconSource.ImageSource = await result.ToBitmapAsync();
}

return (tabLocationHeader, iconSource, toolTipText);
Expand Down
3 changes: 1 addition & 2 deletions src/Files.App/Utils/Cloud/CloudDrivesManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,9 @@ public static async Task UpdateDrivesAsync()
provider.SyncFolder,
Constants.ShellIconSizes.Small,
false,
false,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

iconData = result.IconData;
iconData = result;
}

if (iconData is not null)
Expand Down
3 changes: 1 addition & 2 deletions src/Files.App/Utils/RecentItem/RecentItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,9 @@ public async Task LoadRecentItemIconAsync()
RecentPath,
Constants.ShellIconSizes.Small,
false,
false,
IconOptions.UseCurrentScale);

var bitmapImage = await result.IconData.ToBitmapAsync();
var bitmapImage = await result.ToBitmapAsync();
if (bitmapImage is not null)
FileImg = bitmapImage;
}
Expand Down
40 changes: 15 additions & 25 deletions src/Files.App/Utils/Shell/Win32API.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,26 +276,20 @@ public static string ExtractStringFromDLL(string file, int number)
private static readonly object _iconLock = new object();

/// <summary>
/// Returns an icon when a thumbnail isn't available or if getIconOnly is true.
/// <br/>
/// Returns an icon overlay when getOverlay is true.
/// <br/>
/// Returns a boolean indicating if the icon/thumbnail is cached.
/// Returns an icon if returnIconOnly is true, otherwise a thumbnail will be returned if available.
/// </summary>
/// <param name="path"></param>
/// <param name="thumbnailSize"></param>
/// <param name="size"></param>
/// <param name="isFolder"></param>
/// <param name="getIconOnly"></param>
/// <param name="returnIconOnly"></param>
/// <returns></returns>
public static (byte[]? icon, bool isIconCached) GetIcon(
public static byte[]? GetIcon(
string path,
int thumbnailSize,
int size,
bool isFolder,
bool getThumbnailOnly,
bool getIconOnly)
bool returnIconOnly)
{
byte[]? iconData = null;
bool isIconCached = false;

try
{
Expand All @@ -307,26 +301,22 @@ public static (byte[]? icon, bool isIconCached) GetIcon(
{
var flags = Shell32.SIIGBF.SIIGBF_BIGGERSIZEOK;

if (getIconOnly)
if (returnIconOnly)
flags |= Shell32.SIIGBF.SIIGBF_ICONONLY;
else if (getThumbnailOnly)
flags |= Shell32.SIIGBF.SIIGBF_THUMBNAILONLY;

var hres = shellFactory.GetImage(new SIZE(thumbnailSize, thumbnailSize), flags, out var hbitmap);
var hres = shellFactory.GetImage(new SIZE(size, size), flags, out var hbitmap);
if (hres == HRESULT.S_OK)
{
using var image = GetBitmapFromHBitmap(hbitmap);
if (image is not null)
iconData = (byte[]?)new ImageConverter().ConvertTo(image, typeof(byte[]));

isIconCached = true;
}

Marshal.ReleaseComObject(shellFactory);
}

if (iconData is not null)
return (iconData, isIconCached);
return iconData;
else
{
var shfi = new Shell32.SHFILEINFO();
Expand All @@ -337,11 +327,11 @@ public static (byte[]? icon, bool isIconCached) GetIcon(

var ret = Shell32.SHGetFileInfo(path, isFolder ? FileAttributes.Directory : 0, ref shfi, Shell32.SHFILEINFO.Size, flags);
if (ret == IntPtr.Zero)
return (iconData, isIconCached);
return iconData;

User32.DestroyIcon(shfi.hIcon);

var imageListSize = thumbnailSize switch
var imageListSize = size switch
{
<= 16 => Shell32.SHIL.SHIL_SMALL,
<= 32 => Shell32.SHIL.SHIL_LARGE,
Expand All @@ -352,7 +342,7 @@ public static (byte[]? icon, bool isIconCached) GetIcon(
lock (_iconLock)
{
if (!Shell32.SHGetImageList(imageListSize, typeof(ComCtl32.IImageList).GUID, out var imageListOut).Succeeded)
return (iconData, isIconCached);
return iconData;

var imageList = (ComCtl32.IImageList)imageListOut;

Expand All @@ -375,14 +365,14 @@ public static (byte[]? icon, bool isIconCached) GetIcon(
else if (isFolder)
{
// Could not icon, load generic icon
var icons = ExtractSelectedIconsFromDLL(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "imageres.dll"), new[] { 2 }, thumbnailSize);
var icons = ExtractSelectedIconsFromDLL(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "imageres.dll"), new[] { 2 }, size);
var generic = icons.SingleOrDefault(x => x.Index == 2);
iconData = generic?.IconData;
}
else
{
// Could not icon, load generic icon
var icons = ExtractSelectedIconsFromDLL(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "shell32.dll"), new[] { 1 }, thumbnailSize);
var icons = ExtractSelectedIconsFromDLL(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "shell32.dll"), new[] { 1 }, size);
var generic = icons.SingleOrDefault(x => x.Index == 1);
iconData = generic?.IconData;
}
Expand All @@ -391,7 +381,7 @@ public static (byte[]? icon, bool isIconCached) GetIcon(
Marshal.ReleaseComObject(imageList);
}

return (iconData, isIconCached);
return iconData;
}
}
finally
Expand Down
12 changes: 6 additions & 6 deletions src/Files.App/Utils/Storage/Helpers/FileThumbnailHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ public static class FileThumbnailHelper
/// <summary>
/// Returns icon or thumbnail for given file or folder
/// </summary>
public static async Task<(byte[] IconData, bool isIconCached)> GetIconAsync(string path, uint requestedSize, bool isFolder, bool getThumbnailOnly, IconOptions iconOptions)
public static async Task<byte[]?> GetIconAsync(string path, uint requestedSize, bool isFolder, IconOptions iconOptions)
{
var size = iconOptions.HasFlag(IconOptions.UseCurrentScale) ? requestedSize * App.AppModel.AppWindowDPI : requestedSize;
var getIconOnly = iconOptions.HasFlag(IconOptions.ReturnIconOnly);
var returnIconOnly = iconOptions.HasFlag(IconOptions.ReturnIconOnly);

return await Win32API.StartSTATask(() => Win32API.GetIcon(path, (int)size, isFolder, getThumbnailOnly, getIconOnly));
return await Win32API.StartSTATask(() => Win32API.GetIcon(path, (int)size, isFolder, returnIconOnly));
}

/// <summary>
Expand All @@ -28,10 +28,10 @@ public static class FileThumbnailHelper
=> await Win32API.StartSTATask(() => Win32API.GetIconOverlay(path, isFolder));

[Obsolete]
public static async Task<byte[]> LoadIconFromPathAsync(string filePath, uint thumbnailSize, ThumbnailMode thumbnailMode, ThumbnailOptions thumbnailOptions, bool isFolder = false)
public static async Task<byte[]?> LoadIconFromPathAsync(string filePath, uint thumbnailSize, ThumbnailMode thumbnailMode, ThumbnailOptions thumbnailOptions, bool isFolder = false)
{
var result = await GetIconAsync(filePath, thumbnailSize, isFolder, false, IconOptions.None);
return result.IconData;
var result = await GetIconAsync(filePath, thumbnailSize, isFolder, IconOptions.None);
return result;
}
}
}
5 changes: 2 additions & 3 deletions src/Files.App/Utils/Storage/Search/FolderSearch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -497,11 +497,10 @@ private async Task<ListedItem> GetListedItemAsync(IStorageItem item)
item.Path,
Constants.ShellIconSizes.Small,
item.IsOfType(StorageItemTypes.Folder),
false,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

if (iconResult.IconData is not null)
listedItem.FileImage = await iconResult.IconData.ToBitmapAsync();
if (iconResult is not null)
listedItem.FileImage = await iconResult.ToBitmapAsync();
else
listedItem.NeedsPlaceholderGlyph = true;
}
Expand Down
3 changes: 1 addition & 2 deletions src/Files.App/ViewModels/Properties/BasePropertiesPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,8 @@ protected override void OnNavigatedTo(NavigationEventArgs e)
file.Path,
Constants.ShellIconSizes.ExtraLarge,
false,
false,
IconOptions.UseCurrentScale);
ViewModel.IconData = result.IconData;
ViewModel.IconData = result;
}
});

Expand Down
10 changes: 5 additions & 5 deletions src/Files.App/ViewModels/Properties/Items/DriveProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,19 @@ public async override Task GetSpecialPropertiesAsync()
Drive.Path,
Constants.ShellIconSizes.ExtraLarge,
true,
false,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

if (result.IconData is not null)
ViewModel.IconData = result.IconData;
if (result is not null)
ViewModel.IconData = result;
else
{
result = await FileThumbnailHelper.GetIconAsync(
Drive.DeviceID,
Constants.ShellIconSizes.ExtraLarge,
true, false, IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale); // For network shortcuts
true,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale); // For network shortcuts

ViewModel.IconData = result.IconData;
ViewModel.IconData = result;
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/Files.App/ViewModels/Properties/Items/FileProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,11 @@ public override async Task GetSpecialPropertiesAsync()
Item.ItemPath,
Constants.ShellIconSizes.ExtraLarge,
false,
false,
IconOptions.UseCurrentScale);

if (result.IconData is not null)
if (result is not null)
{
ViewModel.IconData = result.IconData;
ViewModel.IconData = result;
ViewModel.LoadUnknownTypeGlyph = false;
ViewModel.LoadFileIcon = true;
}
Expand Down
5 changes: 2 additions & 3 deletions src/Files.App/ViewModels/Properties/Items/FolderProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,11 @@ public async override Task GetSpecialPropertiesAsync()
Item.ItemPath,
Constants.ShellIconSizes.ExtraLarge,
true,
false,
IconOptions.UseCurrentScale);

if (result.IconData is not null)
if (result is not null)
{
ViewModel.IconData = result.IconData;
ViewModel.IconData = result;
ViewModel.LoadFolderGlyph = false;
ViewModel.LoadFileIcon = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,11 @@ public async override Task GetSpecialPropertiesAsync()
Library.ItemPath,
Constants.ShellIconSizes.ExtraLarge,
true,
false,
IconOptions.UseCurrentScale);

if (result.IconData is not null)
if (result is not null)
{
ViewModel.IconData = result.IconData;
ViewModel.IconData = result;
ViewModel.LoadCustomIcon = false;
ViewModel.LoadFileIcon = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,10 @@ public async virtual Task<List<FileProperty>> LoadPreviewAndDetailsAsync()
Item.ItemPath,
Constants.ShellIconSizes.Jumbo,
false,
false,
IconOptions.None);

if (result.IconData is not null)
await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () => FileImage = await result.IconData.ToBitmapAsync());
if (result is not null)
await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(async () => FileImage = await result.ToBitmapAsync());
else
FileImage ??= await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => new BitmapImage());

Expand Down
Loading

0 comments on commit 2fca3f3

Please sign in to comment.