Fix RootDriveInfo not show every drive
This commit is contained in:
@@ -7,7 +7,6 @@ namespace FileTime.GuiApp.App.ViewModels;
|
||||
|
||||
public interface IGuiAppState : IAppState
|
||||
{
|
||||
ObservableCollection<RootDriveInfo> RootDriveInfos { get; set; }
|
||||
IReadOnlyList<PlaceInfo> Places { get; set; }
|
||||
ObservableCollection<string> PopupTexts { get; }
|
||||
IObservable<GuiPanel> ActivePanel { get; }
|
||||
|
||||
@@ -6,6 +6,7 @@ using FileTime.App.Core.ViewModels.Timeline;
|
||||
using FileTime.App.FrequencyNavigation.Services;
|
||||
using FileTime.GuiApp.App.CloudDrives;
|
||||
using FileTime.GuiApp.App.Services;
|
||||
using FileTime.Providers.Local;
|
||||
using FileTime.Providers.LocalAdmin;
|
||||
|
||||
namespace FileTime.GuiApp.App.ViewModels;
|
||||
@@ -23,6 +24,7 @@ public interface IMainWindowViewModel : IMainWindowViewModelBase
|
||||
ITimelineViewModel TimelineViewModel { get; }
|
||||
IPossibleCommandsViewModel PossibleCommands { get; }
|
||||
ICloudDriveService CloudDriveService { get; }
|
||||
IRootDriveInfoService RootDriveInfoService { get; }
|
||||
Action? ShowWindow { get; set; }
|
||||
Thickness IconStatusPanelMargin { get; }
|
||||
Task RunOrOpenItem(IItemViewModel itemViewModel);
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace FileTime.GuiApp.App.ViewModels;
|
||||
[Inject(typeof(IPossibleCommandsViewModel), PropertyName = "PossibleCommands", PropertyAccessModifier = AccessModifier.Public)]
|
||||
[Inject(typeof(IInstanceMessageHandler), PropertyName = "_instanceMessageHandler")]
|
||||
[Inject(typeof(ICloudDriveService), PropertyAccessModifier = AccessModifier.Public)]
|
||||
[Inject(typeof(IRootDriveInfoService), PropertyAccessModifier = AccessModifier.Public)]
|
||||
public partial class MainWindowViewModel : IMainWindowViewModel
|
||||
{
|
||||
public bool Loading => false;
|
||||
|
||||
@@ -128,12 +128,13 @@
|
||||
|
||||
<ItemsRepeater
|
||||
Grid.Row="1"
|
||||
ItemsSource="{Binding AppState.RootDriveInfos}">
|
||||
ItemsSource="{Binding RootDriveInfoService.RootDriveInfos}">
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate x:DataType="local1:RootDriveInfo">
|
||||
<Grid
|
||||
Classes="SidebarContainerPresenter"
|
||||
PointerPressed="OnHasContainerPointerPressed">
|
||||
PointerPressed="OnHasContainerPointerPressed"
|
||||
ToolTip.Tip="{Binding FullName}">
|
||||
<Grid
|
||||
Margin="10,5"
|
||||
ColumnDefinitions="Auto,*,Auto"
|
||||
@@ -147,6 +148,7 @@
|
||||
Source="{SvgImage /Assets/material/folder.svg}" />
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
@@ -155,7 +157,7 @@
|
||||
<TextBlock
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Text="{Binding FullName}" />
|
||||
Text="{Binding Name}" />
|
||||
|
||||
<TextBlock
|
||||
Margin="5,0,0,0"
|
||||
|
||||
@@ -13,17 +13,14 @@ public partial class GuiAppState : AppStateBase, IGuiAppState, IDisposable
|
||||
{
|
||||
private readonly BehaviorSubject<GuiPanel> _activePanel = new(GuiPanel.FileBrowser);
|
||||
|
||||
[Notify] private ObservableCollection<RootDriveInfo> _rootDriveInfos;
|
||||
|
||||
[Notify] private IReadOnlyList<PlaceInfo> _places = new List<PlaceInfo>();
|
||||
public ObservableCollection<string> PopupTexts { get; } = new();
|
||||
|
||||
public IObservable<GuiPanel> ActivePanel { get; }
|
||||
|
||||
public GuiAppState(IRootDriveInfoService rootDriveInfoService)
|
||||
public GuiAppState()
|
||||
{
|
||||
ActivePanel = _activePanel.AsObservable();
|
||||
_rootDriveInfos = rootDriveInfoService.RootDriveInfos;
|
||||
}
|
||||
|
||||
public void SetActivePanel(GuiPanel newPanel)
|
||||
|
||||
@@ -5,5 +5,6 @@ namespace FileTime.Providers.Local;
|
||||
|
||||
public interface IRootDriveInfoService : IExitHandler
|
||||
{
|
||||
ObservableCollection<RootDriveInfo> RootDriveInfos { get; set; }
|
||||
ReadOnlyObservableCollection<RootDriveInfo> RootDriveInfos { get; set; }
|
||||
ReadOnlyObservableCollection<DriveInfo> AllDrives { get; set; }
|
||||
}
|
||||
@@ -31,14 +31,7 @@ public partial class RootDriveInfo
|
||||
|
||||
_name = container.Name;
|
||||
|
||||
_fullName = _name;
|
||||
try
|
||||
{
|
||||
_fullName = container.FullName?.Path[(container.Provider.FullName!.Path.Length + 1)..] ?? _fullName;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
_fullName = driveInfo.Name;
|
||||
|
||||
Path = container.FullName ?? throw new NullReferenceException($"Container does not have a {nameof(FullName)}");
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
||||
private readonly ITimelessContentProvider _timelessContentProvider;
|
||||
private readonly IContentProviderRegistry _contentProviderRegistry;
|
||||
private readonly bool _isCaseInsensitive;
|
||||
private readonly Lazy<ObservableCollection<RootDriveInfo>> _rootDriveInfos;
|
||||
private readonly Lazy<IRootDriveInfoService> _rootDriveInfo;
|
||||
|
||||
public LocalContentProvider(
|
||||
ITimelessContentProvider timelessContentProvider,
|
||||
@@ -26,7 +26,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
||||
_contentProviderRegistry = contentProviderRegistry;
|
||||
_isCaseInsensitive = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
|
||||
_rootDriveInfos = new Lazy<ObservableCollection<RootDriveInfo>>(() => serviceProvider.GetRequiredService<IRootDriveInfoService>().RootDriveInfos);
|
||||
_rootDriveInfo = new Lazy<IRootDriveInfoService>(serviceProvider.GetRequiredService<IRootDriveInfoService>);
|
||||
|
||||
SupportsContentStreams = true;
|
||||
|
||||
@@ -68,12 +68,26 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
||||
|
||||
public override ValueTask<VolumeSizeInfo?> GetVolumeSizeInfoAsync(FullName path)
|
||||
{
|
||||
var rootDriveInfos = _rootDriveInfos.Value;
|
||||
var rootDriveInfo = rootDriveInfos.FirstOrDefault(d => path.Path.StartsWith(d.Path.Path));
|
||||
var nativePath = GetNativePath(path);
|
||||
|
||||
var possibleRootDrives = _rootDriveInfo.Value.AllDrives.Where(d => nativePath.Path.StartsWith(d.RootDirectory.FullName)).ToArray();
|
||||
var rootDrive = possibleRootDrives.Length == 0
|
||||
? null
|
||||
: possibleRootDrives.MaxBy(d => d.RootDirectory.FullName.Length);
|
||||
|
||||
return rootDrive is null
|
||||
? ValueTask.FromResult<VolumeSizeInfo?>(null)
|
||||
: ValueTask.FromResult<VolumeSizeInfo?>(new VolumeSizeInfo(rootDrive.TotalSize, rootDrive.AvailableFreeSpace));
|
||||
|
||||
/*var rootDriveInfos = _rootDriveInfo.Value;
|
||||
var possibleRootDriveInfo = rootDriveInfos.RootDriveInfos.Where(d => path.Path.StartsWith(d.Path.Path)).ToArray();
|
||||
var rootDriveInfo = possibleRootDriveInfo.Length == 0
|
||||
? null
|
||||
: possibleRootDriveInfo.MaxBy(d => d.FullName.Length);
|
||||
|
||||
if (rootDriveInfo is null) return ValueTask.FromResult<VolumeSizeInfo?>(null);
|
||||
|
||||
return ValueTask.FromResult<VolumeSizeInfo?>(new VolumeSizeInfo(rootDriveInfo.Size, rootDriveInfo.Free));
|
||||
return ValueTask.FromResult<VolumeSizeInfo?>(new VolumeSizeInfo(rootDriveInfo.Size, rootDriveInfo.Free));*/
|
||||
}
|
||||
|
||||
public override async Task<IItem> GetItemByNativePathAsync(NativePath nativePath,
|
||||
@@ -103,7 +117,8 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
||||
return FileToElement(new FileInfo(path), pointInTime);
|
||||
}
|
||||
|
||||
var pathParts = path.Split(Path.DirectorySeparatorChar).SelectMany(p => p.Split(Constants.SeparatorChar)).ToArray();
|
||||
var pathParts = path.Split(Path.DirectorySeparatorChar).SelectMany(p => p.Split(Constants.SeparatorChar))
|
||||
.ToArray();
|
||||
|
||||
for (var i = pathParts.Length - 1; i > 0; i--)
|
||||
{
|
||||
@@ -116,7 +131,8 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
||||
|
||||
var subPath = string.Join(Constants.SeparatorChar, pathParts.Skip(i));
|
||||
|
||||
var resolvedItem = await subContentProvider.GetItemByFullNameAsync(element, new FullName(subPath), pointInTime, forceResolvePathType, itemInitializationSettings);
|
||||
var resolvedItem = await subContentProvider.GetItemByFullNameAsync(element, new FullName(subPath),
|
||||
pointInTime, forceResolvePathType, itemInitializationSettings);
|
||||
|
||||
if (resolvedItem is not null)
|
||||
{
|
||||
@@ -155,7 +171,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
||||
AbsolutePathType.Container => CreateEmptyContainer(
|
||||
nativePath,
|
||||
pointInTime,
|
||||
new List<Exception> {innerException}
|
||||
new List<Exception> { innerException }
|
||||
),
|
||||
AbsolutePathType.Element => CreateEmptyElement(nativePath),
|
||||
_ => throw new Exception(
|
||||
@@ -167,7 +183,8 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
||||
public override ValueTask<NativePath?> GetSupportedPathPart(NativePath nativePath)
|
||||
{
|
||||
var path = nativePath.Path;
|
||||
var pathParts = path.Split(Path.DirectorySeparatorChar).SelectMany(p => p.Split(Constants.SeparatorChar)).ToArray();
|
||||
var pathParts = path.Split(Path.DirectorySeparatorChar).SelectMany(p => p.Split(Constants.SeparatorChar))
|
||||
.ToArray();
|
||||
|
||||
for (var i = pathParts.Length - 1; i > 0; i--)
|
||||
{
|
||||
@@ -440,7 +457,7 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
||||
var finalSize = size switch
|
||||
{
|
||||
> int.MaxValue => int.MaxValue,
|
||||
_ => (int) size
|
||||
_ => (int)size
|
||||
};
|
||||
var buffer = new byte[finalSize];
|
||||
var realSize = await reader.ReadAsync(buffer.AsMemory(0, finalSize), cancellationToken);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using FileTime.Core.Models;
|
||||
using FileTime.Core.Timeline;
|
||||
using ObservableComputations;
|
||||
|
||||
namespace FileTime.Providers.Local;
|
||||
@@ -8,66 +9,65 @@ namespace FileTime.Providers.Local;
|
||||
public class RootDriveInfoService : IRootDriveInfoService
|
||||
{
|
||||
private readonly ILocalContentProvider _localContentProvider;
|
||||
private readonly List<DriveInfo> _rootDrives = new();
|
||||
private readonly ObservableCollection<DriveInfo> _rootDrives = new();
|
||||
private readonly ObservableCollection<DriveInfo> _allDrives = new();
|
||||
private readonly OcConsumer _rootDriveInfosConsumer = new();
|
||||
|
||||
public ObservableCollection<RootDriveInfo> RootDriveInfos { get; set; }
|
||||
public ReadOnlyObservableCollection<DriveInfo> AllDrives { get; set; }
|
||||
public ReadOnlyObservableCollection<RootDriveInfo> RootDriveInfos { get; set; }
|
||||
|
||||
public RootDriveInfoService(ILocalContentProvider localContentProvider)
|
||||
{
|
||||
_localContentProvider = localContentProvider;
|
||||
InitRootDrives();
|
||||
var (rootDrives, allDrives) = GetRootDrives();
|
||||
|
||||
var rootDriveInfos = localContentProvider.Items.Selecting<AbsolutePath, (AbsolutePath Path, DriveInfo? Drive)>(
|
||||
i => MatchRootDrive(i)
|
||||
)
|
||||
.Filtering(t => IsNotNull(t.Drive))
|
||||
.Selecting(t => Resolve(t))
|
||||
.Filtering(t => t.Item is IContainer)
|
||||
.Selecting(t => new RootDriveInfo(t.Drive, (IContainer) t.Item!))
|
||||
.Ordering(d => d.Name);
|
||||
|
||||
rootDriveInfos.For(_rootDriveInfosConsumer);
|
||||
|
||||
RootDriveInfos = rootDriveInfos;
|
||||
|
||||
void InitRootDrives()
|
||||
foreach (var driveInfo in rootDrives)
|
||||
{
|
||||
var drives = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||
? DriveInfo.GetDrives().Where(d => d.DriveType == DriveType.Fixed)
|
||||
: DriveInfo.GetDrives().Where(d =>
|
||||
d.DriveType == DriveType.Fixed
|
||||
_rootDrives.Add(driveInfo);
|
||||
}
|
||||
|
||||
foreach (var driveInfo in allDrives)
|
||||
{
|
||||
_allDrives.Add(driveInfo);
|
||||
}
|
||||
|
||||
var rootDriveInfos = _rootDrives.Selecting(r => GetContainer(r))
|
||||
.Filtering(t => t.Item != null)
|
||||
.Selecting(t => new RootDriveInfo(t.Drive, t.Item!))
|
||||
.Ordering(d => d.Name)
|
||||
.For(_rootDriveInfosConsumer);
|
||||
|
||||
RootDriveInfos = new ReadOnlyObservableCollection<RootDriveInfo>(rootDriveInfos);
|
||||
AllDrives = new ReadOnlyObservableCollection<DriveInfo>(_allDrives);
|
||||
|
||||
(DriveInfo[] RootDrives, DriveInfo[] AllDrives) GetRootDrives()
|
||||
{
|
||||
var allDrives = DriveInfo.GetDrives();
|
||||
var drives = DriveInfo.GetDrives().Where(d => d.DriveType is not DriveType.Unknown and not DriveType.Ram);
|
||||
drives = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||
? drives
|
||||
: drives.Where(d =>
|
||||
d.TotalSize != 0
|
||||
&& d.DriveFormat != "pstorefs"
|
||||
&& d.DriveFormat != "bpf_fs"
|
||||
&& d.DriveFormat != "tracefs"
|
||||
&& d.DriveFormat != "rpc_pipefs"
|
||||
&& !d.RootDirectory.FullName.StartsWith("/snap/"));
|
||||
|
||||
_rootDrives.Clear();
|
||||
_rootDrives.AddRange(drives);
|
||||
return (drives.ToArray(), allDrives);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsNotNull(object? obj) => obj is not null;
|
||||
|
||||
private static (IItem? Item, DriveInfo Drive) Resolve((AbsolutePath Path, DriveInfo? Drive) tuple)
|
||||
private (DriveInfo Drive, IContainer? Item) GetContainer(DriveInfo rootDriveInfo)
|
||||
{
|
||||
var t = Task.Run(async () => await tuple.Path.ResolveAsyncSafe());
|
||||
t.Wait();
|
||||
return (Item: t.Result, Drive: tuple.Drive!);
|
||||
}
|
||||
var task = Task.Run(
|
||||
async () => await _localContentProvider.GetItemByNativePathAsync(
|
||||
new NativePath(rootDriveInfo.RootDirectory.FullName),
|
||||
PointInTime.Present)
|
||||
);
|
||||
task.Wait();
|
||||
|
||||
private (AbsolutePath Path, DriveInfo? Drive) MatchRootDrive(AbsolutePath sourceItem)
|
||||
{
|
||||
var rootDrive = _rootDrives.FirstOrDefault(d =>
|
||||
{
|
||||
var containerPath = _localContentProvider.GetNativePath(sourceItem.Path).Path;
|
||||
var drivePath = d.Name.TrimEnd(Path.DirectorySeparatorChar);
|
||||
return containerPath == drivePath
|
||||
|| (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && containerPath == "/" &&
|
||||
d.Name == "/");
|
||||
});
|
||||
|
||||
return (Path: sourceItem, Drive: rootDrive);
|
||||
return (rootDriveInfo, task.Result as IContainer);
|
||||
}
|
||||
|
||||
public Task ExitAsync(CancellationToken token = default)
|
||||
|
||||
Reference in New Issue
Block a user