diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/ViewModels/IMainWindowViewModel.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.App/ViewModels/IMainWindowViewModel.cs index fa49c66..ab50a91 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/ViewModels/IMainWindowViewModel.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/ViewModels/IMainWindowViewModel.cs @@ -1,4 +1,5 @@ -using Avalonia; +using System.Collections.ObjectModel; +using Avalonia; using FileTime.App.CommandPalette.Services; using FileTime.App.Core.Services; using FileTime.App.Core.ViewModels; @@ -24,8 +25,9 @@ public interface IMainWindowViewModel : IMainWindowViewModelBase ITimelineViewModel TimelineViewModel { get; } IPossibleCommandsViewModel PossibleCommands { get; } ICloudDriveService CloudDriveService { get; } - IRootDriveInfoService RootDriveInfoService { get; } Action? ShowWindow { get; set; } Thickness IconStatusPanelMargin { get; } + ObservableCollection LocalDrives { get; set; } + ObservableCollection NetworkDrives { get; set; } Task RunOrOpenItem(IItemViewModel itemViewModel); } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/ViewModels/MainWindowViewModel.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.App/ViewModels/MainWindowViewModel.cs index 42546b6..11752ea 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/ViewModels/MainWindowViewModel.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/ViewModels/MainWindowViewModel.cs @@ -1,4 +1,5 @@ -using System.Reactive.Linq; +using System.Collections.ObjectModel; +using System.Reactive.Linq; using System.Reflection; using System.Runtime.InteropServices; using Avalonia; @@ -20,6 +21,7 @@ using FileTime.Providers.Local; using FileTime.Providers.LocalAdmin; using Microsoft.Extensions.Logging; using MvvmGen; +using ObservableComputations; namespace FileTime.GuiApp.App.ViewModels; @@ -45,9 +47,10 @@ 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)] +[Inject(typeof(IRootDriveInfoService), PropertyName = "_rootDriveInfoService")] public partial class MainWindowViewModel : IMainWindowViewModel { + private readonly OcConsumer _rootDriveInfosConsumer = new(); public bool Loading => false; public IObservable MainFont => _fontService.MainFont.Select(x => x ?? ""); public DeclarativeProperty FatalError { get; } = new(); @@ -58,6 +61,9 @@ public partial class MainWindowViewModel : IMainWindowViewModel public Action? FocusDefaultElement { get; set; } public Action? ShowWindow { get; set; } + public ObservableCollection LocalDrives { get; set; } + public ObservableCollection NetworkDrives { get; set; } + partial void OnInitialize() { _logger.LogInformation($"Starting {nameof(MainWindowViewModel)} initialization..."); @@ -84,6 +90,15 @@ public partial class MainWindowViewModel : IMainWindowViewModel #endif Title.SetValueSafe(title); + + var localDrives = _rootDriveInfoService.RootDriveInfos.Filtering(r => r.DriveType != DriveType.Network); + var networkDrives = _rootDriveInfoService.RootDriveInfos.Filtering(r => r.DriveType == DriveType.Network); + + localDrives.For(_rootDriveInfosConsumer); + networkDrives.For(_rootDriveInfosConsumer); + + LocalDrives = localDrives; + NetworkDrives = networkDrives; _modalService.AllModalClosed += (_, _) => FocusDefaultElement?.Invoke(); _instanceMessageHandler.ShowWindow += () => ShowWindow?.Invoke(); diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Views/MainWindow.axaml b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Views/MainWindow.axaml index 0def58f..f2dd210 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Views/MainWindow.axaml +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Views/MainWindow.axaml @@ -41,6 +41,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -111,103 +187,49 @@ - + Grid.Column="0"> + CornerRadius="10" + IsVisible="{Binding LocalDrives.Count, Converter={StaticResource GreaterThanConverter}, ConverterParameter=0}"> + Text="Local drives" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ItemTemplate="{StaticResource RootDriveTemplate}" + ItemsSource="{Binding LocalDrives}" /> + + + + + + + + + - + _driveInfo.DriveType; public long UsedPercentage => Size == 0 ? 0 : Used * 100 / Size; diff --git a/src/Providers/FileTime.Providers.Local/RootDriveInfoService.cs b/src/Providers/FileTime.Providers.Local/RootDriveInfoService.cs index 9d299c6..bb0d44d 100644 --- a/src/Providers/FileTime.Providers.Local/RootDriveInfoService.cs +++ b/src/Providers/FileTime.Providers.Local/RootDriveInfoService.cs @@ -34,13 +34,14 @@ public class RootDriveInfoService : IRootDriveInfoService var rootDriveInfos = _rootDrives.Selecting(r => GetContainer(r)) .Filtering(t => t.Item != null) .Selecting(t => new RootDriveInfo(t.Drive, t.Item!)) - .Ordering(d => d.Name) + .Ordering(d => GetDriveOrder(d.DriveType)) + .ThenOrdering(d => d.Name) .For(_rootDriveInfosConsumer); RootDriveInfos = new ReadOnlyObservableCollection(rootDriveInfos); AllDrives = new ReadOnlyObservableCollection(_allDrives); - (DriveInfo[] RootDrives, DriveInfo[] AllDrives) GetRootDrives() + static (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); @@ -70,6 +71,16 @@ public class RootDriveInfoService : IRootDriveInfoService return (rootDriveInfo, task.Result as IContainer); } + private static int GetDriveOrder(DriveType type) + => type switch + { + DriveType.Fixed => 0, + DriveType.Removable => 1, + DriveType.CDRom => 2, + DriveType.Network => 3, + _ => 5 + }; + public Task ExitAsync(CancellationToken token = default) { _rootDriveInfosConsumer.Dispose();