Skip to content

Commit 4753ceb

Browse files
committed
Revert "Init"
This reverts commit f238f71.
1 parent f238f71 commit 4753ceb

29 files changed

+555
-391
lines changed

src/Files.App.CsWin32/NativeMethods.txt

-1
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,3 @@ IFileOperation
133133
IShellItem2
134134
PSGetPropertyKeyFromName
135135
ShellExecuteEx
136-
QueryDosDevice

src/Files.App.Storage/Files.App.Storage.csproj

-2
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
<ItemGroup>
1515
<PackageReference Include="FluentFTP" Version="43.0.1" />
16-
<PackageReference Include="Microsoft.Management.Infrastructure" Version="3.0.0" />
17-
<PackageReference Include="Microsoft.Management.Infrastructure.Runtime.Win" Version="3.0.0" />
1816
</ItemGroup>
1917

2018
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">

src/Files.App.Storage/Watchers/DeviceWatcher.cs

-151
This file was deleted.

src/Files.App/Actions/FileSystem/FormatDriveAction.cs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
// Copyright (c) 2024 Files Community
22
// Licensed under the MIT License. See the LICENSE.
33

4+
using Files.App.Utils.Shell;
5+
46
namespace Files.App.Actions
57
{
68
internal sealed class FormatDriveAction : ObservableObject, IAction
79
{
810
private readonly IContentPageContext context;
911

10-
private readonly IRemovableDrivesService StorageDevicesService = Ioc.Default.GetRequiredService<IRemovableDrivesService>();
12+
private readonly DrivesViewModel drivesViewModel;
1113

1214
public string Label
1315
=> "FormatDriveText".GetLocalizedResource();
@@ -18,12 +20,13 @@ public string Description
1820
public bool IsExecutable =>
1921
context.HasItem &&
2022
!context.HasSelection &&
21-
(StorageDevicesService.Drives.Cast<DriveItem>().FirstOrDefault(x =>
23+
(drivesViewModel.Drives.Cast<DriveItem>().FirstOrDefault(x =>
2224
string.Equals(x.Path, context.Folder?.ItemPath))?.MenuOptions.ShowFormatDrive ?? false);
2325

2426
public FormatDriveAction()
2527
{
2628
context = Ioc.Default.GetRequiredService<IContentPageContext>();
29+
drivesViewModel = Ioc.Default.GetRequiredService<DrivesViewModel>();
2730

2831
context.PropertyChanged += Context_PropertyChanged;
2932
}
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
11
// Copyright (c) 2024 Files Community
22
// Licensed under the MIT License. See the LICENSE.
33

4+
using Files.Core.Storage.Storables;
5+
46
namespace Files.App.Data.Contracts
57
{
68
/// <summary>
7-
/// Represents a service to enumerate and update drives.
9+
/// Represents a service to enumerate drives and create a storage device watcher
810
/// </summary>
9-
public interface IRemovableDrivesService : INotifyPropertyChanged
11+
public interface IRemovableDrivesService
1012
{
1113
/// <summary>
12-
/// Gets drives.
14+
/// Gets the primary system drive. This item is typically excluded when enumerating removable drives
15+
/// </summary>
16+
/// <returns>The location of the drive which the operating system is installed to.</returns>
17+
Task<ILocatableFolder> GetPrimaryDriveAsync();
18+
19+
/// <summary>
20+
/// Creates a watcher for storage devices
1321
/// </summary>
14-
ObservableCollection<ILocatableFolder> Drives { get; }
22+
/// <returns>The created storage device watcher</returns>
23+
IStorageDeviceWatcher CreateWatcher();
1524

1625
/// <summary>
17-
/// Gets or sets a value that indicates whether the application should show consent dialog when the primary drive isn't accessible.
26+
/// Enumerates all removable drives
1827
/// </summary>
19-
bool ShowUserConsentOnInit { get; set; }
28+
/// <returns>A collection of removable storage devices</returns>
29+
IAsyncEnumerable<ILocatableFolder> GetDrivesAsync();
2030

2131
/// <summary>
22-
/// Updates all connected devices.
32+
/// Refreshes the properties of a drive
2333
/// </summary>
34+
/// <param name="drive"></param>
2435
/// <returns></returns>
25-
Task UpdateDrivesAsync();
36+
Task UpdateDrivePropertiesAsync(ILocatableFolder drive);
2637
}
2738
}

src/Files.App.Storage/Data/EventArrivedEventArgs.cs renamed to src/Files.App/Data/EventArguments/EventArrivedEventArgs.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
// Licensed under the MIT License. See the LICENSE.
33

44
using Microsoft.Management.Infrastructure;
5+
using System;
56

6-
namespace Files.App.Storage
7+
namespace Files.App.Data.EventArguments
78
{
89
/// <summary>
910
/// CimWatcher event args, which contains CimSubscriptionResult

src/Files.App.Storage/Data/DeviceEvent.cs renamed to src/Files.App/Data/Items/DeviceEvent.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// Copyright (c) 2024 Files Community
22
// Licensed under the MIT License. See the LICENSE.
33

4-
namespace Files.App.Storage
4+
namespace Files.App.Data.Items
55
{
6-
internal enum DeviceEvent
6+
public enum DeviceEvent
77
{
88
Added,
99

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// Copyright (c) 2024 Files Community
2+
// Licensed under the MIT License. See the LICENSE.
3+
4+
using Files.App.Services.SizeProvider;
5+
using Files.Core.Storage.Storables;
6+
using Microsoft.Extensions.Logging;
7+
using System.IO;
8+
9+
namespace Files.App.Data.Models
10+
{
11+
public sealed class DrivesViewModel : ObservableObject, IDisposable
12+
{
13+
public ObservableCollection<ILocatableFolder> Drives
14+
{
15+
get => drives;
16+
private set => SetProperty(ref drives, value);
17+
}
18+
19+
public bool ShowUserConsentOnInit
20+
{
21+
get => showUserConsentOnInit;
22+
set => SetProperty(ref showUserConsentOnInit, value);
23+
}
24+
25+
private bool showUserConsentOnInit;
26+
private ObservableCollection<ILocatableFolder> drives;
27+
private readonly IRemovableDrivesService removableDrivesService;
28+
private readonly ISizeProvider folderSizeProvider;
29+
private readonly IStorageDeviceWatcher watcher;
30+
private readonly ILogger<App> logger;
31+
32+
public DrivesViewModel(IRemovableDrivesService removableDrivesService, ISizeProvider folderSizeProvider, ILogger<App> logger)
33+
{
34+
this.removableDrivesService = removableDrivesService;
35+
this.folderSizeProvider = folderSizeProvider;
36+
this.logger = logger;
37+
38+
drives = [];
39+
40+
watcher = removableDrivesService.CreateWatcher();
41+
watcher.DeviceAdded += Watcher_DeviceAdded;
42+
watcher.DeviceRemoved += Watcher_DeviceRemoved;
43+
watcher.DeviceModified += Watcher_DeviceModified;
44+
watcher.EnumerationCompleted += Watcher_EnumerationCompleted;
45+
}
46+
47+
private async void Watcher_EnumerationCompleted(object? sender, System.EventArgs e)
48+
{
49+
logger.LogDebug("Watcher_EnumerationCompleted");
50+
await folderSizeProvider.CleanAsync();
51+
}
52+
53+
private async void Watcher_DeviceModified(object? sender, string e)
54+
{
55+
var matchingDriveEjected = Drives.FirstOrDefault(x => Path.GetFullPath(x.Path) == Path.GetFullPath(e));
56+
if (matchingDriveEjected != null)
57+
await removableDrivesService.UpdateDrivePropertiesAsync(matchingDriveEjected);
58+
}
59+
60+
private void Watcher_DeviceRemoved(object? sender, string e)
61+
{
62+
logger.LogInformation($"Drive removed: {e}");
63+
lock (Drives)
64+
{
65+
var drive = Drives.FirstOrDefault(x => x.Id == e);
66+
if (drive is not null)
67+
Drives.Remove(drive);
68+
}
69+
70+
// Update the collection on the ui-thread.
71+
Watcher_EnumerationCompleted(null, EventArgs.Empty);
72+
}
73+
74+
private void Watcher_DeviceAdded(object? sender, ILocatableFolder e)
75+
{
76+
lock (Drives)
77+
{
78+
// If drive already in list, remove it first.
79+
var matchingDrive = Drives.FirstOrDefault(x =>
80+
x.Id == e.Id ||
81+
string.IsNullOrEmpty(e.Path)
82+
? x.Path.Contains(e.Name, StringComparison.OrdinalIgnoreCase)
83+
: Path.GetFullPath(x.Path) == Path.GetFullPath(e.Path)
84+
);
85+
86+
if (matchingDrive is not null)
87+
Drives.Remove(matchingDrive);
88+
89+
logger.LogInformation($"Drive added: {e.Path}");
90+
Drives.Add(e);
91+
}
92+
93+
Watcher_EnumerationCompleted(null, EventArgs.Empty);
94+
}
95+
96+
public async Task UpdateDrivesAsync()
97+
{
98+
Drives.Clear();
99+
await foreach (ILocatableFolder item in removableDrivesService.GetDrivesAsync())
100+
{
101+
Drives.AddIfNotPresent(item);
102+
}
103+
104+
var osDrive = await removableDrivesService.GetPrimaryDriveAsync();
105+
106+
// Show consent dialog if the OS drive could not be accessed
107+
if (!Drives.Any(x => Path.GetFullPath(x.Path) == Path.GetFullPath(osDrive.Path)))
108+
ShowUserConsentOnInit = true;
109+
110+
if (watcher.CanBeStarted)
111+
watcher.Start();
112+
}
113+
114+
public void Dispose()
115+
{
116+
watcher.Stop();
117+
watcher.DeviceAdded -= Watcher_DeviceAdded;
118+
watcher.DeviceRemoved -= Watcher_DeviceRemoved;
119+
watcher.DeviceModified -= Watcher_DeviceModified;
120+
watcher.EnumerationCompleted -= Watcher_EnumerationCompleted;
121+
}
122+
}
123+
}

0 commit comments

Comments
 (0)