Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 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
3 changes: 3 additions & 0 deletions src/Files.App.CsWin32/ManualGuid.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ public static Guid* IID_IStorageProviderStatusUISourceFactory

[GuidRVAGen.Guid("00021500-0000-0000-C000-000000000046")]
public static partial Guid* IID_IQueryInfo { get; }

[GuidRVAGen.Guid("000214F9-0000-0000-C000-000000000046")]
public static partial Guid* IID_IShellLinkW { get; }
}

public static unsafe partial class CLSID
Expand Down
3 changes: 3 additions & 0 deletions src/Files.App.CsWin32/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
GetKeyState
CreateDirectoryFromApp
WNetCancelConnection2
NET_USE_CONNECT_FLAGS

Check warning on line 48 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

Method, type or constant "NET_USE_CONNECT_FLAGS" not found

Check warning on line 48 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, x64)

Method, type or constant "NET_USE_CONNECT_FLAGS" not found

Check warning on line 48 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

Method, type or constant "NET_USE_CONNECT_FLAGS" not found

Check warning on line 48 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

Method, type or constant "NET_USE_CONNECT_FLAGS" not found
NETRESOURCEW
WNetAddConnection3
CREDENTIALW
Expand Down Expand Up @@ -78,7 +78,7 @@
SetEntriesInAcl
ACL_SIZE_INFORMATION
DeleteAce
EXPLICIT_ACCESS

Check warning on line 81 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

Method, type or constant "EXPLICIT_ACCESS" not found. Did you mean or "EXPLICIT_ACCESS_A" or "EXPLICIT_ACCESS_W"?

Check warning on line 81 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, x64)

Method, type or constant "EXPLICIT_ACCESS" not found. Did you mean or "EXPLICIT_ACCESS_A" or "EXPLICIT_ACCESS_W"?

Check warning on line 81 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

Method, type or constant "EXPLICIT_ACCESS" not found. Did you mean or "EXPLICIT_ACCESS_A" or "EXPLICIT_ACCESS_W"?

Check warning on line 81 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

Method, type or constant "EXPLICIT_ACCESS" not found. Did you mean or "EXPLICIT_ACCESS_A" or "EXPLICIT_ACCESS_W"?
ACCESS_ALLOWED_ACE
LookupAccountSid
GetComputerName
Expand Down Expand Up @@ -134,7 +134,7 @@
CoTaskMemFree
QueryDosDevice
DeviceIoControl
GetLastError

Check warning on line 137 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, x64)

This API will not be generated. Do not generate GetLastError. Call Marshal.GetLastWin32Error() instead. Learn more from https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshal.getlastwin32error

Check warning on line 137 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, x64)

This API will not be generated. Do not generate GetLastError. Call Marshal.GetLastWin32Error() instead. Learn more from https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshal.getlastwin32error

Check warning on line 137 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Release, arm64)

This API will not be generated. Do not generate GetLastError. Call Marshal.GetLastWin32Error() instead. Learn more from https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshal.getlastwin32error

Check warning on line 137 in src/Files.App.CsWin32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / build (Debug, arm64)

This API will not be generated. Do not generate GetLastError. Call Marshal.GetLastWin32Error() instead. Learn more from https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshal.getlastwin32error
CreateFile
GetVolumeInformation
COMPRESSION_FORMAT
Expand Down Expand Up @@ -226,3 +226,6 @@
RoGetAgileReference
IQueryInfo
QITIPF_FLAGS
GetDiskFreeSpaceEx
GetDriveType
SLGP_FLAGS
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

namespace Files.App.Storage
{
public interface IWindowsFile : IWindowsStorable, IChildFile
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

namespace Files.App.Storage
{
public interface IWindowsFolder : IWindowsStorable, IChildFolder
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Files.App.Storage
{
public interface IWindowsStorable : IDisposable
public interface IWindowsStorable : IStorableChild, IEquatable<IWindowsStorable>, IDisposable
{
ComPtr<IShellItem> ThisPtr { get; }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace Files.App.Storage
{
[DebuggerDisplay("{" + nameof(ToString) + "()}")]
public sealed class WindowsFile : WindowsStorable, IChildFile
public sealed class WindowsFile : WindowsStorable, IWindowsFile
{
public WindowsFile(ComPtr<IShellItem> nativeObject)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace Files.App.Storage
{
[DebuggerDisplay("{" + nameof(ToString) + "()}")]
public sealed class WindowsFolder : WindowsStorable, IChildFolder
public sealed class WindowsFolder : WindowsStorable, IWindowsFolder
{
public WindowsFolder(ComPtr<IShellItem> nativeObject)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Files.App.Storage
{
public abstract class WindowsStorable : IWindowsStorable, IStorableChild, IEquatable<IWindowsStorable>
public abstract class WindowsStorable : IWindowsStorable
{
public ComPtr<IShellItem> ThisPtr { get; protected set; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,19 @@ public unsafe static HRESULT TryGetShellTooltip(this IWindowsStorable storable,

return HRESULT.S_OK;
}

public unsafe static HRESULT TryGetShellLink(this IWindowsStorable storable, out ComPtr<IShellLinkW> pShellLink)
{
pShellLink = default;

using ComPtr<IShellLinkW> pShellLinkW = default;
HRESULT hr = storable.ThisPtr.Get()->BindToHandler(null, BHID.BHID_SFUIObject, IID.IID_IShellLinkW, (void**)pShellLinkW.GetAddressOf());
if (hr.ThrowIfFailedOnDebug().Failed)
return hr;

pShellLink = pShellLinkW;

return HRESULT.S_OK;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.NetworkManagement.WNet;
using Windows.Win32.Storage.FileSystem;
using Windows.Win32.UI.Shell;

Expand Down Expand Up @@ -84,5 +85,37 @@ public static bool TryShowFormatDriveDialog(HWND hWnd, uint driveLetterIndex, SH
var result = PInvoke.SHFormatDrive(hWnd, driveLetterIndex, id, options);
return result is 0xFFFF;
}

public static bool TryGetDriveTotalSpace(this IWindowsStorable storable, out ulong totalSize)
{
ulong ulTotalSize = 0UL;
bool res = PInvoke.GetDiskFreeSpaceEx(storable.GetDisplayName(), null, &ulTotalSize, null);

totalSize = ulTotalSize;

return res;
}

public static bool TryGetDriveFreeSpace(this IWindowsStorable storable, out ulong freeSize)
{
ulong ulFreeSize = 0UL;
bool res = PInvoke.GetDiskFreeSpaceEx(storable.GetDisplayName(), null, null, &ulFreeSize);

freeSize = ulFreeSize;

return res;
}

public static bool TryGetDriveType(this IWindowsStorable storable, out uint driveType)
{
driveType = PInvoke.GetDriveType(storable.GetDisplayName());

return driveType is 0U; // DRIVE_UNKNOWN
}

public static bool TryDisconnectNetworkDrive(this IWindowsStorable storable)
{
return PInvoke.WNetCancelConnection2W(storable.GetDisplayName().TrimEnd('\\'), NET_CONNECT_FLAGS.CONNECT_UPDATE_PROFILE, true) is WIN32_ERROR.NO_ERROR;
}
}
}
73 changes: 42 additions & 31 deletions src/Files.App/Data/Items/WidgetDriveCardItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,61 @@
// Licensed under the MIT License.

using Microsoft.UI.Xaml.Media.Imaging;
using Windows.Win32;
using Windows.Win32.UI.Shell;

namespace Files.App.Data.Items
{
public sealed partial class WidgetDriveCardItem : WidgetCardItem, IWidgetCardItem<DriveItem>, IComparable<WidgetDriveCardItem>
public sealed partial class WidgetDriveCardItem : WidgetCardItem, IWidgetCardItem<IWindowsFolder>, IDisposable
{
private byte[] thumbnailData;
// Properties

public new DriveItem Item { get; private set; }
public required new IWindowsFolder Item { get; set; }

private BitmapImage thumbnail;
public BitmapImage Thumbnail
{
get => thumbnail;
set => SetProperty(ref thumbnail, value);
}
public required string Text { get; set; }

public bool ShowStorageSense => UsedSize.GigaBytes / TotalSize.GigaBytes >= Constants.Widgets.Drives.LowStorageSpacePercentageThreshold;

public bool ShowDriveUsage => TotalSize.GigaBytes > 0D;

public ByteSizeLib.ByteSize TotalSize { get; set; } = default;

public ByteSizeLib.ByteSize FreeSize { get; set; } = default;

public ByteSizeLib.ByteSize UsedSize => ByteSizeLib.ByteSize.FromBytes(TotalSize.Bytes - FreeSize.Bytes);

public string? UsageText => string.Format(Strings.DriveFreeSpaceAndCapacity.GetLocalizedResource(), FreeSize.ToSizeString(), TotalSize.ToSizeString());

public required SystemIO.DriveType DriveType { get; set; }

public WidgetDriveCardItem(DriveItem item)
private BitmapImage? _Thumbnail;
public BitmapImage? Thumbnail { get => _Thumbnail; set => SetProperty(ref _Thumbnail, value); }

// Constructor

public WidgetDriveCardItem()
{
Item = item;
Path = item.Path;
}

// Methods

public async Task LoadCardThumbnailAsync()
{
var result = await FileThumbnailHelper.GetIconAsync(
Item.Path,
Constants.ShellIconSizes.Large,
true,
IconOptions.ReturnIconOnly | IconOptions.UseCurrentScale);

if (result is null)
{
using var thumbnail = await DriveHelpers.GetThumbnailAsync(Item.Root);
result ??= await thumbnail.ToByteArrayAsync();
}

thumbnailData = result;

var bitmapImage = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => thumbnailData.ToBitmapAsync(), Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal);
if (bitmapImage is not null)
Thumbnail = bitmapImage;
if (string.IsNullOrEmpty(Path) || Item is not IWindowsStorable windowsStorable)
return;

windowsStorable.TryGetThumbnail((int)(Constants.ShellIconSizes.Large * App.AppModel.AppWindowDPI), SIIGBF.SIIGBF_ICONONLY, out var rawThumbnailData);
if (rawThumbnailData is null)
return;

Thumbnail = await rawThumbnailData.ToBitmapAsync();
}

public int CompareTo(WidgetDriveCardItem? other)
=> Item.Path.CompareTo(other?.Item?.Path);
// Disposer

public void Dispose()
{
Item.Dispose();
}
}
}
24 changes: 12 additions & 12 deletions src/Files.App/UserControls/Widgets/DrivesWidget.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
AutomationProperties.Name="{x:Bind Item.Text, Mode=OneWay}"
AutomationProperties.Name="{x:Bind Text, Mode=OneWay}"
Click="Button_Click"
CornerRadius="{StaticResource ControlCornerRadius}"
DataContext="{x:Bind}"
PointerPressed="Button_PointerPressed"
RightTapped="Button_RightTapped"
Tag="{x:Bind Item.Path}"
ToolTipService.ToolTip="{x:Bind Item.Text, Mode=OneWay}">
Tag="{x:Bind Path}"
ToolTipService.ToolTip="{x:Bind Text, Mode=OneWay}">
<Grid
Margin="8"
HorizontalAlignment="Stretch"
Expand Down Expand Up @@ -75,7 +75,7 @@
VerticalAlignment="Center"
FontSize="14"
FontWeight="Medium"
Text="{x:Bind Item.Text, Mode=OneWay}"
Text="{x:Bind Text, Mode=OneWay}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap" />

Expand All @@ -85,10 +85,10 @@
Grid.Column="1"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
x:Load="{x:Bind Item.ShowDriveDetails, Mode=OneWay}"
x:Load="{x:Bind ShowDriveUsage, Mode=OneWay}"
AutomationProperties.AccessibilityView="Raw"
Maximum="{x:Bind Item.MaxSpace.GigaBytes, Mode=OneWay}"
Value="{x:Bind Item.SpaceUsed.GigaBytes, Mode=OneWay}" />
Maximum="{x:Bind TotalSize.GigaBytes, Mode=OneWay}"
Value="{x:Bind UsedSize.GigaBytes, Mode=OneWay}" />

<Button
x:Name="GoToStorageSense"
Expand All @@ -100,12 +100,12 @@
Padding="0"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
x:Load="{x:Bind Item.ShowStorageSense, Mode=OneWay}"
x:Load="{x:Bind ShowStorageSense, Mode=OneWay}"
AutomationProperties.Name="{helpers:ResourceString Name=OpenStorageSense}"
Background="Transparent"
BorderBrush="Transparent"
Click="GoToStorageSense_Click"
Tag="{x:Bind Item.Path}"
Tag="{x:Bind Path}"
ToolTipService.ToolTip="{helpers:ResourceString Name=OpenStorageSense}">
<FontIcon
HorizontalAlignment="Center"
Expand All @@ -121,13 +121,13 @@
Grid.ColumnSpan="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
x:Load="{x:Bind Item.ShowDriveDetails, Mode=OneWay}"
x:Load="{x:Bind ShowDriveUsage, Mode=OneWay}"
x:Phase="1"
FontSize="12"
Text="{x:Bind Item.SpaceText, Mode=OneWay}"
Text="{x:Bind UsageText, Mode=OneWay}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"
ToolTipService.ToolTip="{x:Bind Item.SpaceText, Mode=OneWay}" />
ToolTipService.ToolTip="{x:Bind UsageText, Mode=OneWay}" />
</Grid>
</Button>
</DataTemplate>
Expand Down
20 changes: 10 additions & 10 deletions src/Files.App/UserControls/Widgets/NetworkLocationsWidget.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
AutomationProperties.Name="{x:Bind Item.Text, Mode=OneWay}"
AutomationProperties.Name="{x:Bind Text, Mode=OneWay}"
Click="Button_Click"
CornerRadius="{StaticResource ControlCornerRadius}"
DataContext="{x:Bind}"
PointerPressed="Button_PointerPressed"
RightTapped="Button_RightTapped"
Tag="{x:Bind Item.Path}"
ToolTipService.ToolTip="{x:Bind Item.Text, Mode=OneWay}">
Tag="{x:Bind Path}"
ToolTipService.ToolTip="{x:Bind Text, Mode=OneWay}">
<Grid
Margin="8"
HorizontalAlignment="Stretch"
Expand Down Expand Up @@ -101,7 +101,7 @@
VerticalAlignment="Center"
FontSize="14"
FontWeight="Medium"
Text="{x:Bind Item.Text, Mode=OneWay}"
Text="{x:Bind Text, Mode=OneWay}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap" />

Expand All @@ -111,24 +111,24 @@
Grid.Column="1"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
x:Load="{x:Bind Item.ShowDriveDetails, Mode=OneWay}"
x:Load="{x:Bind ShowDriveUsage, Mode=OneWay}"
AutomationProperties.AccessibilityView="Raw"
Maximum="{x:Bind Item.MaxSpace.GigaBytes, Mode=OneWay}"
Value="{x:Bind Item.SpaceUsed.GigaBytes, Mode=OneWay}" />
Maximum="{x:Bind TotalSize.GigaBytes, Mode=OneWay}"
Value="{x:Bind UsedSize.GigaBytes, Mode=OneWay}" />

<TextBlock
x:Name="DriveSpaceTextBlock"
Grid.Row="2"
Grid.Column="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
x:Load="{x:Bind Item.ShowDriveDetails, Mode=OneWay}"
x:Load="{x:Bind ShowDriveUsage, Mode=OneWay}"
x:Phase="1"
FontSize="12"
Text="{x:Bind Item.SpaceText, Mode=OneWay}"
Text="{x:Bind UsageText, Mode=OneWay}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap"
ToolTipService.ToolTip="{x:Bind Item.SpaceText, Mode=OneWay}" />
ToolTipService.ToolTip="{x:Bind UsageText, Mode=OneWay}" />
</Grid>
</Button>
</DataTemplate>
Expand Down
Loading
Loading