diff --git a/.editorconfig b/.editorconfig index 35af4a6..9d2b516 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,2 +1,4 @@ [*.cs] -dotnet_diagnostic.RCS1196.severity = none \ No newline at end of file +dotnet_diagnostic.RCS1196.severity = none +csharp_style_namespace_declarations = file_scoped:error +dotnet_diagnostic.IDE0161.severity = error \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Command/Commands.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Command/Commands.cs index 22a7765..cde308b 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Command/Commands.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Command/Commands.cs @@ -1,66 +1,65 @@ -namespace FileTime.App.Core.Command -{ - public enum Commands - { - None, +namespace FileTime.App.Core.Command; - AutoRefresh, - ChangeTimelineMode, - CloseTab, - Compress, - Copy, - CopyHash, - CopyPath, - CreateContainer, - CreateElement, - Cut, - Edit, - EnterRapidTravel, - FindByName, - FindByNameRegex, - GoToHome, - GoToPath, - GoToProvider, - GoToRoot, - GoUp, - HardDelete, - Mark, - MoveCursorDown, - MoveCursorDownPage, - MoveCursorUp, - MoveCursorUpPage, - MoveToFirst, - MoveToLast, - NextTimelineBlock, - NextTimelineCommand, - Open, - OpenInFileBrowser, - OpenOrRun, - PasteMerge, - PasteOverwrite, - PasteSkip, - PinFavorite, - PreviousTimelineBlock, - PreviousTimelineCommand, - Refresh, - Rename, - RunCommand, - ScanContainerSize, - ShowAllShotcut, - SoftDelete, - SwitchToLastTab, - SwitchToTab1, - SwitchToTab2, - SwitchToTab3, - SwitchToTab4, - SwitchToTab5, - SwitchToTab6, - SwitchToTab7, - SwitchToTab8, - TimelinePause, - TimelineRefresh, - TimelineStart, - ToggleAdvancedIcons, - ToggleHidden, - } +public enum Commands +{ + None, + + AutoRefresh, + ChangeTimelineMode, + CloseTab, + Compress, + Copy, + CopyHash, + CopyPath, + CreateContainer, + CreateElement, + Cut, + Edit, + EnterRapidTravel, + FindByName, + FindByNameRegex, + GoToHome, + GoToPath, + GoToProvider, + GoToRoot, + GoUp, + HardDelete, + Mark, + MoveCursorDown, + MoveCursorDownPage, + MoveCursorUp, + MoveCursorUpPage, + MoveToFirst, + MoveToLast, + NextTimelineBlock, + NextTimelineCommand, + Open, + OpenInFileBrowser, + OpenOrRun, + PasteMerge, + PasteOverwrite, + PasteSkip, + PinFavorite, + PreviousTimelineBlock, + PreviousTimelineCommand, + Refresh, + Rename, + RunCommand, + ScanContainerSize, + ShowAllShotcut, + SoftDelete, + SwitchToLastTab, + SwitchToTab1, + SwitchToTab2, + SwitchToTab3, + SwitchToTab4, + SwitchToTab5, + SwitchToTab6, + SwitchToTab7, + SwitchToTab8, + TimelinePause, + TimelineRefresh, + TimelineStart, + ToggleAdvancedIcons, + ToggleHidden, } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/FileTime.App.Core.Abstraction.csproj b/src/AppCommon/FileTime.App.Core.Abstraction/FileTime.App.Core.Abstraction.csproj index d2d0d89..64ce252 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/FileTime.App.Core.Abstraction.csproj +++ b/src/AppCommon/FileTime.App.Core.Abstraction/FileTime.App.Core.Abstraction.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Models/BindedCollection.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Models/BindedCollection.cs index fb2a153..8287d63 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Models/BindedCollection.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Models/BindedCollection.cs @@ -1,26 +1,25 @@ using System.Collections.ObjectModel; using DynamicData; -namespace FileTime.App.Core.Models +namespace FileTime.App.Core.Models; + +public class BindedCollection : IDisposable { - public class BindedCollection : IDisposable + private readonly IDisposable _disposable; + public ReadOnlyObservableCollection Collection { get; } + public BindedCollection(IObservable> dynamicList) { - private readonly IDisposable _disposable; - public ReadOnlyObservableCollection Collection { get; } - public BindedCollection(IObservable> dynamicList) - { - _disposable = dynamicList - .Bind(out var collection) - .DisposeMany() - .Subscribe(); + _disposable = dynamicList + .Bind(out var collection) + .DisposeMany() + .Subscribe(); - Collection = collection; - } + Collection = collection; + } - public void Dispose() - { - _disposable.Dispose(); - GC.SuppressFinalize(this); - } + public void Dispose() + { + _disposable.Dispose(); + GC.SuppressFinalize(this); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ItemAttributeType.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ItemAttributeType.cs index 030402b..09e9074 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ItemAttributeType.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ItemAttributeType.cs @@ -1,10 +1,9 @@ -namespace FileTime.App.Core.Models.Enums +namespace FileTime.App.Core.Models.Enums; + +public enum ItemAttributeType { - public enum ItemAttributeType - { - File, - Element, - Container, - SizeContainer - } + File, + Element, + Container, + SizeContainer } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ItemViewMode.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ItemViewMode.cs index 2f8eb6e..ec0052f 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ItemViewMode.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ItemViewMode.cs @@ -1,12 +1,11 @@ -namespace FileTime.App.Core.Models.Enums +namespace FileTime.App.Core.Models.Enums; + +public enum ItemViewMode { - public enum ItemViewMode - { - Default, - Alternative, - Selected, - Marked, - MarkedSelected, - MarkedAlternative - } + Default, + Alternative, + Selected, + Marked, + MarkedSelected, + MarkedAlternative } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ViewMode.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ViewMode.cs index 5cff236..b11da9b 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ViewMode.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Models/Enums/ViewMode.cs @@ -1,8 +1,7 @@ -namespace FileTime.App.Core.Models.Enums +namespace FileTime.App.Core.Models.Enums; + +public enum ViewMode { - public enum ViewMode - { - Default, - RapidTravel - } + Default, + RapidTravel } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Models/ItemNamePart.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Models/ItemNamePart.cs index 81e01fe..946b30c 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Models/ItemNamePart.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Models/ItemNamePart.cs @@ -1,14 +1,13 @@ -namespace FileTime.App.Core.Models -{ - public class ItemNamePart - { - public string Text { get; set; } - public bool IsSpecial { get; set; } +namespace FileTime.App.Core.Models; - public ItemNamePart(string text, bool isSpecial = false) - { - Text = text; - IsSpecial = isSpecial; - } +public class ItemNamePart +{ + public string Text { get; set; } + public bool IsSpecial { get; set; } + + public ItemNamePart(string text, bool isSpecial = false) + { + Text = text; + IsSpecial = isSpecial; } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Services/IClipboardService.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Services/IClipboardService.cs index 2dc008e..16f4a40 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Services/IClipboardService.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Services/IClipboardService.cs @@ -1,16 +1,15 @@ using FileTime.Core.Command; using FileTime.Core.Models; -namespace FileTime.App.Core.Services -{ - public interface IClipboardService - { - Type? CommandType { get; } - IReadOnlyList Content { get; } +namespace FileTime.App.Core.Services; - void AddContent(IAbsolutePath absolutePath); - void RemoveContent(IAbsolutePath absolutePath); - void Clear(); - void SetCommand() where T : ITransportationCommand; - } +public interface IClipboardService +{ + Type? CommandType { get; } + IReadOnlyList Content { get; } + + void AddContent(IAbsolutePath absolutePath); + void RemoveContent(IAbsolutePath absolutePath); + void Clear(); + void SetCommand() where T : ITransportationCommand; } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Services/ICommandHandler.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Services/ICommandHandler.cs index 67156c7..116fb4f 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Services/ICommandHandler.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Services/ICommandHandler.cs @@ -1,10 +1,9 @@ using FileTime.App.Core.Command; -namespace FileTime.App.Core.Services +namespace FileTime.App.Core.Services; + +public interface ICommandHandler { - public interface ICommandHandler - { - bool CanHandleCommand(Commands command); - Task HandleCommandAsync(Commands command); - } + bool CanHandleCommand(Commands command); + Task HandleCommandAsync(Commands command); } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Services/ICommandHandlerService.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Services/ICommandHandlerService.cs index 4f43ccc..b48cef7 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Services/ICommandHandlerService.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Services/ICommandHandlerService.cs @@ -1,9 +1,8 @@ using FileTime.App.Core.Command; -namespace FileTime.App.Core.Services +namespace FileTime.App.Core.Services; + +public interface ICommandHandlerService { - public interface ICommandHandlerService - { - Task HandleCommandAsync(Commands command); - } + Task HandleCommandAsync(Commands command); } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Services/IItemNameConverterService.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Services/IItemNameConverterService.cs index 72825c1..fac1901 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Services/IItemNameConverterService.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Services/IItemNameConverterService.cs @@ -1,11 +1,10 @@ using FileTime.App.Core.Models; -namespace FileTime.App.Core.Services +namespace FileTime.App.Core.Services; + +public interface IItemNameConverterService { - public interface IItemNameConverterService - { - List GetDisplayName(string name, string? searchText); - string GetFileExtension(string fullName); - string GetFileName(string fullName); - } + List GetDisplayName(string name, string? searchText); + string GetFileExtension(string fullName); + string GetFileName(string fullName); } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/Services/IRxSchedulerService.cs b/src/AppCommon/FileTime.App.Core.Abstraction/Services/IRxSchedulerService.cs index e9310bf..6b114ff 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/Services/IRxSchedulerService.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/Services/IRxSchedulerService.cs @@ -1,10 +1,9 @@ using System.Reactive.Concurrency; -namespace FileTime.App.Core.Services +namespace FileTime.App.Core.Services; + +public interface IRxSchedulerService { - public interface IRxSchedulerService - { - IScheduler GetWorkerScheduler(); - IScheduler GetUIScheduler(); - } + IScheduler GetWorkerScheduler(); + IScheduler GetUIScheduler(); } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IAppState.cs b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IAppState.cs index 1b322ef..77cc837 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IAppState.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IAppState.cs @@ -1,17 +1,16 @@ using System.Collections.ObjectModel; using FileTime.App.Core.Models.Enums; -namespace FileTime.App.Core.ViewModels -{ - public interface IAppState - { - ObservableCollection Tabs { get; } - IObservable SelectedTab { get; } - IObservable SearchText { get; } - ViewMode ViewMode { get; } +namespace FileTime.App.Core.ViewModels; - void AddTab(ITabViewModel tabViewModel); - void RemoveTab(ITabViewModel tabViewModel); - void SetSearchText(string? searchText); - } +public interface IAppState +{ + ObservableCollection Tabs { get; } + IObservable SelectedTab { get; } + IObservable SearchText { get; } + ViewMode ViewMode { get; } + + void AddTab(ITabViewModel tabViewModel); + void RemoveTab(ITabViewModel tabViewModel); + void SetSearchText(string? searchText); } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IContainerSizeContainerViewModel.cs b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IContainerSizeContainerViewModel.cs index 5d01f51..7d95dbb 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IContainerSizeContainerViewModel.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IContainerSizeContainerViewModel.cs @@ -1,10 +1,9 @@ using FileTime.Core.Models; using InitableService; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +public interface IContainerSizeContainerViewModel : IItemViewModel, IInitable { - public interface IContainerSizeContainerViewModel : IItemViewModel, IInitable - { - long Size { get; set; } - } + long Size { get; set; } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IContainerViewModel.cs b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IContainerViewModel.cs index 2125333..387d7f1 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IContainerViewModel.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IContainerViewModel.cs @@ -1,10 +1,9 @@ using FileTime.Core.Models; using InitableService; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +public interface IContainerViewModel : IItemViewModel, IInitable { - public interface IContainerViewModel : IItemViewModel, IInitable - { - IContainer? Container { get; } - } + IContainer? Container { get; } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IElementViewModel.cs b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IElementViewModel.cs index 84fef93..5ea0814 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IElementViewModel.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IElementViewModel.cs @@ -1,10 +1,9 @@ using FileTime.Core.Models; using InitableService; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +public interface IElementViewModel : IItemViewModel, IInitable { - public interface IElementViewModel : IItemViewModel, IInitable - { - long? Size { get; set; } - } + long? Size { get; set; } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IFileViewModel.cs b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IFileViewModel.cs index 22118e6..e3f0c0f 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IFileViewModel.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IFileViewModel.cs @@ -1,9 +1,8 @@ using FileTime.Core.Models; using InitableService; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +public interface IFileViewModel : IElementViewModel, IInitable { - public interface IFileViewModel : IElementViewModel, IInitable - { - } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IItemViewModel.cs b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IItemViewModel.cs index ceeded9..15daeae 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IItemViewModel.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/IItemViewModel.cs @@ -3,19 +3,18 @@ using FileTime.App.Core.Models.Enums; using FileTime.Core.Models; using InitableService; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +public interface IItemViewModel : IInitable { - public interface IItemViewModel : IInitable - { - IItem? BaseItem { get; set; } - IObservable>? DisplayName { get; set; } - string? DisplayNameText { get; set; } - IObservable? IsSelected { get; set; } - IObservable? IsMarked { get; set; } - IObservable IsAlternative { get; } - IObservable ViewMode { get; set; } - DateTime? CreatedAt { get; set; } - string? Attributes { get; set; } - bool EqualsTo(IItemViewModel? itemViewModel); - } + IItem? BaseItem { get; set; } + IObservable>? DisplayName { get; set; } + string? DisplayNameText { get; set; } + IObservable? IsSelected { get; set; } + IObservable? IsMarked { get; set; } + IObservable IsAlternative { get; } + IObservable ViewMode { get; set; } + DateTime? CreatedAt { get; set; } + string? Attributes { get; set; } + bool EqualsTo(IItemViewModel? itemViewModel); } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/ITabViewModel.cs b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/ITabViewModel.cs index bc1c7d9..be498e7 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/ITabViewModel.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/ITabViewModel.cs @@ -5,26 +5,25 @@ using FileTime.Core.Models; using FileTime.Core.Services; using InitableService; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +public interface ITabViewModel : IInitable { - public interface ITabViewModel : IInitable - { - ITab? Tab { get; } - int TabNumber { get; } - IObservable IsSelected { get; } - IObservable CurrentLocation { get; } - IObservable CurrentSelectedItem { get; } - IObservable>?> CurrentItems { get; } - IObservable> MarkedItems { get; } - IObservable>?> SelectedsChildren { get; } - IObservable>?> ParentsChildren { get; } - BindedCollection? CurrentItemsCollection { get; } - BindedCollection? SelectedsChildrenCollection { get; } - BindedCollection? ParentsChildrenCollection { get; } - IObservable?> CurrentItemsCollectionObservable { get; } - void ClearMarkedItems(); - void RemoveMarkedItem(IAbsolutePath item); - void AddMarkedItem(IAbsolutePath item); - void ToggleMarkedItem(IAbsolutePath item); - } + ITab? Tab { get; } + int TabNumber { get; } + IObservable IsSelected { get; } + IObservable CurrentLocation { get; } + IObservable CurrentSelectedItem { get; } + IObservable>?> CurrentItems { get; } + IObservable> MarkedItems { get; } + IObservable>?> SelectedsChildren { get; } + IObservable>?> ParentsChildren { get; } + BindedCollection? CurrentItemsCollection { get; } + BindedCollection? SelectedsChildrenCollection { get; } + BindedCollection? ParentsChildrenCollection { get; } + IObservable?> CurrentItemsCollectionObservable { get; } + void ClearMarkedItems(); + void RemoveMarkedItem(IAbsolutePath item); + void AddMarkedItem(IAbsolutePath item); + void ToggleMarkedItem(IAbsolutePath item); } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Extensions/ObservableExtensions.cs b/src/AppCommon/FileTime.App.Core/Extensions/ObservableExtensions.cs index 727666f..2895890 100644 --- a/src/AppCommon/FileTime.App.Core/Extensions/ObservableExtensions.cs +++ b/src/AppCommon/FileTime.App.Core/Extensions/ObservableExtensions.cs @@ -1,9 +1,8 @@ using System.Reactive.Linq; -namespace FileTime.App.Core.Extensions +namespace FileTime.App.Core.Extensions; + +public static class ObservableExtensions { - public static class ObservableExtensions - { - public static IObservable WhereNotNull(this IObservable source) => source.Where(c => c != null)!; - } + public static IObservable WhereNotNull(this IObservable source) => source.Where(c => c != null)!; } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Extensions/ViewModelExtensions.cs b/src/AppCommon/FileTime.App.Core/Extensions/ViewModelExtensions.cs index 377afae..5e91b89 100644 --- a/src/AppCommon/FileTime.App.Core/Extensions/ViewModelExtensions.cs +++ b/src/AppCommon/FileTime.App.Core/Extensions/ViewModelExtensions.cs @@ -1,14 +1,13 @@ using FileTime.App.Core.ViewModels; using FileTime.Core.Models; -namespace FileTime.App.Core.Extensions +namespace FileTime.App.Core.Extensions; + +public static class ViewModelExtensions { - public static class ViewModelExtensions + public static IAbsolutePath ToAbsolutePath(this IItemViewModel itemViewModel) { - public static IAbsolutePath ToAbsolutePath(this IItemViewModel itemViewModel) - { - var item = itemViewModel.BaseItem ?? throw new ArgumentException($"{nameof(itemViewModel)} does not have {nameof(IItemViewModel.BaseItem)}"); - return new AbsolutePath(item); - } + var item = itemViewModel.BaseItem ?? throw new ArgumentException($"{nameof(itemViewModel)} does not have {nameof(IItemViewModel.BaseItem)}"); + return new AbsolutePath(item); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj b/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj index c889896..228348f 100644 --- a/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj +++ b/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/AppCommon/FileTime.App.Core/Services/ClipboardService.cs b/src/AppCommon/FileTime.App.Core/Services/ClipboardService.cs index e00a298..beeed61 100644 --- a/src/AppCommon/FileTime.App.Core/Services/ClipboardService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/ClipboardService.cs @@ -1,51 +1,50 @@ using FileTime.Core.Command; using FileTime.Core.Models; -namespace FileTime.App.Core.Services +namespace FileTime.App.Core.Services; + +public class ClipboardService : IClipboardService { - public class ClipboardService : IClipboardService + private List _content; + public IReadOnlyList Content { get; private set; } + public Type? CommandType { get; private set; } + + public ClipboardService() { - private List _content; - public IReadOnlyList Content { get; private set; } - public Type? CommandType { get; private set; } + _content = new List(); + Content = _content.AsReadOnly(); + } - public ClipboardService() + public void AddContent(IAbsolutePath absolutePath) + { + foreach (var content in _content) { - _content = new List(); - Content = _content.AsReadOnly(); + if (content.Equals(absolutePath)) return; } - public void AddContent(IAbsolutePath absolutePath) + _content.Add(absolutePath); + } + + public void RemoveContent(IAbsolutePath absolutePath) + { + for (var i = 0; i < _content.Count; i++) { - foreach (var content in _content) + if (_content[i].Equals(absolutePath)) { - if (content.Equals(absolutePath)) return; + _content.RemoveAt(i--); } - - _content.Add(absolutePath); - } - - public void RemoveContent(IAbsolutePath absolutePath) - { - for (var i = 0; i < _content.Count; i++) - { - if (_content[i].Equals(absolutePath)) - { - _content.RemoveAt(i--); - } - } - } - - public void Clear() - { - _content = new List(); - Content = _content.AsReadOnly(); - CommandType = null; - } - - public void SetCommand() where T : ITransportationCommand - { - CommandType = typeof(T); } } + + public void Clear() + { + _content = new List(); + Content = _content.AsReadOnly(); + CommandType = null; + } + + public void SetCommand() where T : ITransportationCommand + { + CommandType = typeof(T); + } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Services/CommandHandler/CommandHandlerBase.cs b/src/AppCommon/FileTime.App.Core/Services/CommandHandler/CommandHandlerBase.cs index ba42208..034a38a 100644 --- a/src/AppCommon/FileTime.App.Core/Services/CommandHandler/CommandHandlerBase.cs +++ b/src/AppCommon/FileTime.App.Core/Services/CommandHandler/CommandHandlerBase.cs @@ -4,51 +4,50 @@ using FileTime.App.Core.Command; using FileTime.App.Core.ViewModels; using FileTime.Core.Models; -namespace FileTime.App.Core.Services.CommandHandler +namespace FileTime.App.Core.Services.CommandHandler; + +public abstract class CommandHandlerBase : ICommandHandler { - public abstract class CommandHandlerBase : ICommandHandler + private readonly Dictionary> _commandHandlers = new(); + private readonly IAppState? _appState; + + protected CommandHandlerBase(IAppState? appState = null) { - private readonly Dictionary> _commandHandlers = new(); - private readonly IAppState? _appState; + _appState = appState; + } - protected CommandHandlerBase(IAppState? appState = null) + public bool CanHandleCommand(Commands command) => _commandHandlers.ContainsKey(command); + + public async Task HandleCommandAsync(Commands command) => await _commandHandlers[command].Invoke(); + + protected void AddCommandHandler(Commands command, Func handler) => _commandHandlers.Add(command, handler); + protected void AddCommandHandlers(IEnumerable<(Commands command, Func handler)> commandHandlers) + { + foreach (var (command, handler) in commandHandlers) { - _appState = appState; - } - - public bool CanHandleCommand(Commands command) => _commandHandlers.ContainsKey(command); - - public async Task HandleCommandAsync(Commands command) => await _commandHandlers[command].Invoke(); - - protected void AddCommandHandler(Commands command, Func handler) => _commandHandlers.Add(command, handler); - protected void AddCommandHandlers(IEnumerable<(Commands command, Func handler)> commandHandlers) - { - foreach (var (command, handler) in commandHandlers) - { - AddCommandHandler(command, handler); - } - } - - protected void RemoveCommandHandler(Commands command) => _commandHandlers.Remove(command); - - protected IDisposable SaveSelectedTab(Action handler) => RunWithAppState(appState => appState.SelectedTab.Subscribe(handler)); - protected IDisposable SaveCurrentSelectedItem(Action handler) - => RunWithAppState(appState => appState.SelectedTab.Select(t => t == null ? Observable.Return(null) : t.CurrentSelectedItem).Switch().Subscribe(handler)); - - protected IDisposable SaveCurrentLocation(Action handler) - => RunWithAppState(appState => appState.SelectedTab.Select(t => t == null ? Observable.Return(null) : t.CurrentLocation).Switch().Subscribe(handler)); - - protected IDisposable SaveCurrentItems(Action> handler) - => RunWithAppState(appState => appState.SelectedTab.Select(t => t?.CurrentItemsCollectionObservable ?? Observable.Return((IEnumerable?)Enumerable.Empty())).Switch().Subscribe(i => handler(i ?? Enumerable.Empty()))); - - protected IDisposable SaveMarkedItems(Action> handler) - => RunWithAppState(appstate => appstate.SelectedTab.Select(t => t == null ? Observable.Empty>() : t.MarkedItems).Switch().Subscribe(handler)); - - private IDisposable RunWithAppState(Func act) - { - if (_appState == null) throw new NullReferenceException($"AppState is nit initialized in {nameof(CommandHandlerBase)}."); - - return act(_appState); + AddCommandHandler(command, handler); } } + + protected void RemoveCommandHandler(Commands command) => _commandHandlers.Remove(command); + + protected IDisposable SaveSelectedTab(Action handler) => RunWithAppState(appState => appState.SelectedTab.Subscribe(handler)); + protected IDisposable SaveCurrentSelectedItem(Action handler) + => RunWithAppState(appState => appState.SelectedTab.Select(t => t == null ? Observable.Return(null) : t.CurrentSelectedItem).Switch().Subscribe(handler)); + + protected IDisposable SaveCurrentLocation(Action handler) + => RunWithAppState(appState => appState.SelectedTab.Select(t => t == null ? Observable.Return(null) : t.CurrentLocation).Switch().Subscribe(handler)); + + protected IDisposable SaveCurrentItems(Action> handler) + => RunWithAppState(appState => appState.SelectedTab.Select(t => t?.CurrentItemsCollectionObservable ?? Observable.Return((IEnumerable?)Enumerable.Empty())).Switch().Subscribe(i => handler(i ?? Enumerable.Empty()))); + + protected IDisposable SaveMarkedItems(Action> handler) + => RunWithAppState(appstate => appstate.SelectedTab.Select(t => t == null ? Observable.Empty>() : t.MarkedItems).Switch().Subscribe(handler)); + + private IDisposable RunWithAppState(Func act) + { + if (_appState == null) throw new NullReferenceException($"AppState is nit initialized in {nameof(CommandHandlerBase)}."); + + return act(_appState); + } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Services/CommandHandler/ItemManipulationCommandHandler.cs b/src/AppCommon/FileTime.App.Core/Services/CommandHandler/ItemManipulationCommandHandler.cs index c197273..f6d25de 100644 --- a/src/AppCommon/FileTime.App.Core/Services/CommandHandler/ItemManipulationCommandHandler.cs +++ b/src/AppCommon/FileTime.App.Core/Services/CommandHandler/ItemManipulationCommandHandler.cs @@ -6,91 +6,90 @@ using FileTime.Core.Command; using FileTime.Core.Command.Copy; using FileTime.Core.Models; -namespace FileTime.App.Core.Services.CommandHandler +namespace FileTime.App.Core.Services.CommandHandler; + +public class ItemManipulationCommandHandler : CommandHandlerBase { - public class ItemManipulationCommandHandler : CommandHandlerBase + private ITabViewModel? _selectedTab; + private IItemViewModel? _currentSelectedItem; + private readonly ICommandHandlerService _commandHandlerService; + private readonly IClipboardService _clipboardService; + private BindedCollection? _markedItems; + + public ItemManipulationCommandHandler( + IAppState appState, + ICommandHandlerService commandHandlerService, + IClipboardService clipboardService) : base(appState) { - private ITabViewModel? _selectedTab; - private IItemViewModel? _currentSelectedItem; - private readonly ICommandHandlerService _commandHandlerService; - private readonly IClipboardService _clipboardService; - private BindedCollection? _markedItems; + _commandHandlerService = commandHandlerService; + _clipboardService = clipboardService; - public ItemManipulationCommandHandler( - IAppState appState, - ICommandHandlerService commandHandlerService, - IClipboardService clipboardService) : base(appState) + SaveSelectedTab(t => { - _commandHandlerService = commandHandlerService; - _clipboardService = clipboardService; + _selectedTab = t; + _markedItems?.Dispose(); + _markedItems = t == null ? null : new BindedCollection(t.MarkedItems); + }); + SaveCurrentSelectedItem(i => _currentSelectedItem = i); - SaveSelectedTab(t => - { - _selectedTab = t; - _markedItems?.Dispose(); - _markedItems = t == null ? null : new BindedCollection(t.MarkedItems); - }); - SaveCurrentSelectedItem(i => _currentSelectedItem = i); - - AddCommandHandlers(new (Commands, Func)[] - { - (Commands.Copy, Copy), - (Commands.Mark, MarkItem), - (Commands.PasteMerge, PasteMerge), - (Commands.PasteOverwrite, PasteOverwrite), - (Commands.PasteSkip, PasteSkip), - }); - } - - private async Task MarkItem() + AddCommandHandlers(new (Commands, Func)[] { - if (_selectedTab == null || _currentSelectedItem?.BaseItem?.FullName == null) return; + (Commands.Copy, Copy), + (Commands.Mark, MarkItem), + (Commands.PasteMerge, PasteMerge), + (Commands.PasteOverwrite, PasteOverwrite), + (Commands.PasteSkip, PasteSkip), + }); + } - _selectedTab.ToggleMarkedItem(new AbsolutePath(_currentSelectedItem.BaseItem)); - await _commandHandlerService.HandleCommandAsync(Commands.MoveCursorDown); - } + private async Task MarkItem() + { + if (_selectedTab == null || _currentSelectedItem?.BaseItem?.FullName == null) return; - private Task Copy() + _selectedTab.ToggleMarkedItem(new AbsolutePath(_currentSelectedItem.BaseItem)); + await _commandHandlerService.HandleCommandAsync(Commands.MoveCursorDown); + } + + private Task Copy() + { + _clipboardService.Clear(); + _clipboardService.SetCommand(); + + if ((_markedItems?.Collection.Count ?? 0) > 0) { - _clipboardService.Clear(); - _clipboardService.SetCommand(); - - if ((_markedItems?.Collection.Count ?? 0) > 0) + foreach (var item in _markedItems!.Collection) { - foreach (var item in _markedItems!.Collection) - { - _clipboardService.AddContent(item); - } - - _selectedTab?.ClearMarkedItems(); - } - else if (_currentSelectedItem?.BaseItem != null) - { - _clipboardService.AddContent(new AbsolutePath(_currentSelectedItem.BaseItem)); + _clipboardService.AddContent(item); } - return Task.CompletedTask; + _selectedTab?.ClearMarkedItems(); + } + else if (_currentSelectedItem?.BaseItem != null) + { + _clipboardService.AddContent(new AbsolutePath(_currentSelectedItem.BaseItem)); } - private async Task PasteMerge() - { - await Paste(TransportMode.Merge); - } + return Task.CompletedTask; + } - private async Task PasteOverwrite() - { - await Paste(TransportMode.Overwrite); - } + private async Task PasteMerge() + { + await Paste(TransportMode.Merge); + } - private async Task PasteSkip() - { - await Paste(TransportMode.Skip); - } + private async Task PasteOverwrite() + { + await Paste(TransportMode.Overwrite); + } - private Task Paste(TransportMode skip) - { - if (_clipboardService.CommandType is null) return Task.CompletedTask; - return Task.CompletedTask; - } + private async Task PasteSkip() + { + await Paste(TransportMode.Skip); + } + + private Task Paste(TransportMode skip) + { + if (_clipboardService.CommandType is null) return Task.CompletedTask; + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Services/CommandHandler/NavigationCommandHandler.cs b/src/AppCommon/FileTime.App.Core/Services/CommandHandler/NavigationCommandHandler.cs index d98ae63..82f4361 100644 --- a/src/AppCommon/FileTime.App.Core/Services/CommandHandler/NavigationCommandHandler.cs +++ b/src/AppCommon/FileTime.App.Core/Services/CommandHandler/NavigationCommandHandler.cs @@ -4,65 +4,64 @@ using FileTime.App.Core.Extensions; using FileTime.App.Core.ViewModels; using FileTime.Core.Models; -namespace FileTime.App.Core.Services.CommandHandler +namespace FileTime.App.Core.Services.CommandHandler; + +public class NavigationCommandHandler : CommandHandlerBase { - public class NavigationCommandHandler : CommandHandlerBase + private ITabViewModel? _selectedTab; + private IContainer? _currentLocation; + private IItemViewModel? _currentSelectedItem; + private IEnumerable _currentItems = Enumerable.Empty(); + + public NavigationCommandHandler(IAppState appState) : base(appState) { - private ITabViewModel? _selectedTab; - private IContainer? _currentLocation; - private IItemViewModel? _currentSelectedItem; - private IEnumerable _currentItems = Enumerable.Empty(); + SaveSelectedTab(t => _selectedTab = t); + SaveCurrentSelectedItem(i => _currentSelectedItem = i); + SaveCurrentLocation(l => _currentLocation = l); + SaveCurrentItems(i => _currentItems = i); - public NavigationCommandHandler(IAppState appState) : base(appState) + AddCommandHandlers(new (Commands, Func)[] { - SaveSelectedTab(t => _selectedTab = t); - SaveCurrentSelectedItem(i => _currentSelectedItem = i); - SaveCurrentLocation(l => _currentLocation = l); - SaveCurrentItems(i => _currentItems = i); + (Commands.GoUp, GoUp), + (Commands.MoveCursorDown, MoveCursorDown), + (Commands.MoveCursorUp, MoveCursorUp), + (Commands.Open, OpenContainer), + }); + } - AddCommandHandlers(new (Commands, Func)[] - { - (Commands.GoUp, GoUp), - (Commands.MoveCursorDown, MoveCursorDown), - (Commands.MoveCursorUp, MoveCursorUp), - (Commands.Open, OpenContainer), - }); - } + private Task OpenContainer() + { + if (_currentSelectedItem is not IContainerViewModel containerViewModel || containerViewModel.Container is null) return Task.CompletedTask; - private Task OpenContainer() - { - if (_currentSelectedItem is not IContainerViewModel containerViewModel || containerViewModel.Container is null) return Task.CompletedTask; + _selectedTab?.Tab?.SetCurrentLocation(containerViewModel.Container); + return Task.CompletedTask; + } - _selectedTab?.Tab?.SetCurrentLocation(containerViewModel.Container); - return Task.CompletedTask; - } + private async Task GoUp() + { + if (_currentLocation?.Parent is not IAbsolutePath parentPath || await parentPath.ResolveAsyncSafe() is not IContainer newContainer) return; + _selectedTab?.Tab?.SetCurrentLocation(newContainer); + } - private async Task GoUp() - { - if (_currentLocation?.Parent is not IAbsolutePath parentPath || await parentPath.ResolveAsyncSafe() is not IContainer newContainer) return; - _selectedTab?.Tab?.SetCurrentLocation(newContainer); - } + private Task MoveCursorDown() + { + SelectNewSelectedItem(i => i.SkipWhile(i => !i.EqualsTo(_currentSelectedItem)).Skip(1).FirstOrDefault()); + return Task.CompletedTask; + } - private Task MoveCursorDown() - { - SelectNewSelectedItem(i => i.SkipWhile(i => !i.EqualsTo(_currentSelectedItem)).Skip(1).FirstOrDefault()); - return Task.CompletedTask; - } + private Task MoveCursorUp() + { + SelectNewSelectedItem(i => i.TakeWhile(i => !i.EqualsTo(_currentSelectedItem)).LastOrDefault()); + return Task.CompletedTask; + } - private Task MoveCursorUp() - { - SelectNewSelectedItem(i => i.TakeWhile(i => !i.EqualsTo(_currentSelectedItem)).LastOrDefault()); - return Task.CompletedTask; - } + private void SelectNewSelectedItem(Func, IItemViewModel?> getNewSelected) + { + if (_selectedTab is null || _currentLocation is null) return; - private void SelectNewSelectedItem(Func, IItemViewModel?> getNewSelected) - { - if (_selectedTab is null || _currentLocation is null) return; + var newSelectedItem = getNewSelected(_currentItems); + if (newSelectedItem == null) return; - var newSelectedItem = getNewSelected(_currentItems); - if (newSelectedItem == null) return; - - _selectedTab.Tab?.SetSelectedItem(newSelectedItem.ToAbsolutePath()); - } + _selectedTab.Tab?.SetSelectedItem(newSelectedItem.ToAbsolutePath()); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Services/CommandHandlerService.cs b/src/AppCommon/FileTime.App.Core/Services/CommandHandlerService.cs index eddfcc5..aa96613 100644 --- a/src/AppCommon/FileTime.App.Core/Services/CommandHandlerService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/CommandHandlerService.cs @@ -1,80 +1,79 @@ using FileTime.App.Core.Command; using Microsoft.Extensions.DependencyInjection; -namespace FileTime.App.Core.Services +namespace FileTime.App.Core.Services; + +public class CommandHandlerService : ICommandHandlerService { - public class CommandHandlerService : ICommandHandlerService + private readonly Lazy> _commandHandlers; + + public CommandHandlerService(IServiceProvider serviceProvider) { - private readonly Lazy> _commandHandlers; + _commandHandlers = new Lazy>(() => serviceProvider.GetServices()); - public CommandHandlerService(IServiceProvider serviceProvider) + //(Commands.AutoRefresh, ToggleAutoRefresh), + //(Commands.ChangeTimelineMode, ChangeTimelineMode), + //(Commands.CloseTab, CloseTab), + //(Commands.Compress, Compress), + //(Commands.Copy, Copy), + //(Commands.CopyHash, CopyHash), + //(Commands.CopyPath, CopyPath), + //(Commands.CreateContainer, CreateContainer), + //(Commands.CreateElement, CreateElement), + //(Commands.Cut, Cut), + //(Commands.Edit, Edit), + //(Commands.EnterRapidTravel, EnterRapidTravelMode), + //(Commands.FindByName, FindByName), + //(Commands.FindByNameRegex, FindByNameRegex), + //(Commands.GoToHome, GotToHome), + //(Commands.GoToPath, GoToContainer), + //(Commands.GoToProvider, GotToProvider), + //(Commands.GoToRoot, GotToRoot), + //(Commands.HardDelete, HardDelete), + //(Commands.Mark, MarkCurrentItem), + //(Commands.MoveCursorDownPage, MoveCursorDownPage), + //(Commands.MoveCursorUpPage, MoveCursorUpPage), + //(Commands.MoveToFirst, MoveToFirst), + //(Commands.MoveToLast, MoveToLast), + //(Commands.NextTimelineBlock, SelectNextTimelineBlock), + //(Commands.NextTimelineCommand, SelectNextTimelineCommand), + //(Commands.OpenInFileBrowser, OpenInDefaultFileExplorer), + //(Commands.OpenOrRun, OpenOrRun), + //(Commands.PasteMerge, PasteMerge), + //(Commands.PasteOverwrite, PasteOverwrite), + //(Commands.PasteSkip, PasteSkip), + //(Commands.PinFavorite, PinFavorite), + //(Commands.PreviousTimelineBlock, SelectPreviousTimelineBlock), + //(Commands.PreviousTimelineCommand, SelectPreviousTimelineCommand), + //(Commands.Refresh, RefreshCurrentLocation), + //(Commands.Rename, Rename), + //(Commands.RunCommand, RunCommandInContainer), + //(Commands.ScanContainerSize, ScanContainerSize), + //(Commands.ShowAllShotcut, ShowAllShortcut), + //(Commands.SoftDelete, SoftDelete), + //(Commands.SwitchToLastTab, async() => await SwitchToTab(-1)), + //(Commands.SwitchToTab1, async() => await SwitchToTab(1)), + //(Commands.SwitchToTab2, async() => await SwitchToTab(2)), + //(Commands.SwitchToTab3, async() => await SwitchToTab(3)), + //(Commands.SwitchToTab4, async() => await SwitchToTab(4)), + //(Commands.SwitchToTab5, async() => await SwitchToTab(5)), + //(Commands.SwitchToTab6, async() => await SwitchToTab(6)), + //(Commands.SwitchToTab7, async() => await SwitchToTab(7)), + //(Commands.SwitchToTab8, async() => await SwitchToTab(8)), + //(Commands.TimelinePause, PauseTimeline), + //(Commands.TimelineRefresh, RefreshTimeline), + //(Commands.TimelineStart, ContinueTimeline), + //(Commands.ToggleAdvancedIcons, ToggleAdvancedIcons), + //(Commands.ToggleHidden, ToggleHidden), + } + + public async Task HandleCommandAsync(Commands command) + { + var handler = _commandHandlers.Value.FirstOrDefault(h => h.CanHandleCommand(command)); + + if (handler != null) { - _commandHandlers = new Lazy>(() => serviceProvider.GetServices()); - - //(Commands.AutoRefresh, ToggleAutoRefresh), - //(Commands.ChangeTimelineMode, ChangeTimelineMode), - //(Commands.CloseTab, CloseTab), - //(Commands.Compress, Compress), - //(Commands.Copy, Copy), - //(Commands.CopyHash, CopyHash), - //(Commands.CopyPath, CopyPath), - //(Commands.CreateContainer, CreateContainer), - //(Commands.CreateElement, CreateElement), - //(Commands.Cut, Cut), - //(Commands.Edit, Edit), - //(Commands.EnterRapidTravel, EnterRapidTravelMode), - //(Commands.FindByName, FindByName), - //(Commands.FindByNameRegex, FindByNameRegex), - //(Commands.GoToHome, GotToHome), - //(Commands.GoToPath, GoToContainer), - //(Commands.GoToProvider, GotToProvider), - //(Commands.GoToRoot, GotToRoot), - //(Commands.HardDelete, HardDelete), - //(Commands.Mark, MarkCurrentItem), - //(Commands.MoveCursorDownPage, MoveCursorDownPage), - //(Commands.MoveCursorUpPage, MoveCursorUpPage), - //(Commands.MoveToFirst, MoveToFirst), - //(Commands.MoveToLast, MoveToLast), - //(Commands.NextTimelineBlock, SelectNextTimelineBlock), - //(Commands.NextTimelineCommand, SelectNextTimelineCommand), - //(Commands.OpenInFileBrowser, OpenInDefaultFileExplorer), - //(Commands.OpenOrRun, OpenOrRun), - //(Commands.PasteMerge, PasteMerge), - //(Commands.PasteOverwrite, PasteOverwrite), - //(Commands.PasteSkip, PasteSkip), - //(Commands.PinFavorite, PinFavorite), - //(Commands.PreviousTimelineBlock, SelectPreviousTimelineBlock), - //(Commands.PreviousTimelineCommand, SelectPreviousTimelineCommand), - //(Commands.Refresh, RefreshCurrentLocation), - //(Commands.Rename, Rename), - //(Commands.RunCommand, RunCommandInContainer), - //(Commands.ScanContainerSize, ScanContainerSize), - //(Commands.ShowAllShotcut, ShowAllShortcut), - //(Commands.SoftDelete, SoftDelete), - //(Commands.SwitchToLastTab, async() => await SwitchToTab(-1)), - //(Commands.SwitchToTab1, async() => await SwitchToTab(1)), - //(Commands.SwitchToTab2, async() => await SwitchToTab(2)), - //(Commands.SwitchToTab3, async() => await SwitchToTab(3)), - //(Commands.SwitchToTab4, async() => await SwitchToTab(4)), - //(Commands.SwitchToTab5, async() => await SwitchToTab(5)), - //(Commands.SwitchToTab6, async() => await SwitchToTab(6)), - //(Commands.SwitchToTab7, async() => await SwitchToTab(7)), - //(Commands.SwitchToTab8, async() => await SwitchToTab(8)), - //(Commands.TimelinePause, PauseTimeline), - //(Commands.TimelineRefresh, RefreshTimeline), - //(Commands.TimelineStart, ContinueTimeline), - //(Commands.ToggleAdvancedIcons, ToggleAdvancedIcons), - //(Commands.ToggleHidden, ToggleHidden), - } - - public async Task HandleCommandAsync(Commands command) - { - var handler = _commandHandlers.Value.FirstOrDefault(h => h.CanHandleCommand(command)); - - if (handler != null) - { - await handler.HandleCommandAsync(command); - } + await handler.HandleCommandAsync(command); } } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Services/ItemNameConverterService.cs b/src/AppCommon/FileTime.App.Core/Services/ItemNameConverterService.cs index 24f85ae..c966825 100644 --- a/src/AppCommon/FileTime.App.Core/Services/ItemNameConverterService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/ItemNameConverterService.cs @@ -1,56 +1,55 @@ using FileTime.App.Core.Models; -namespace FileTime.App.Core.Services +namespace FileTime.App.Core.Services; + +public class ItemNameConverterService : IItemNameConverterService { - public class ItemNameConverterService : IItemNameConverterService + public List GetDisplayName(string name, string? searchText) { - public List GetDisplayName(string name, string? searchText) + var nameParts = new List(); + searchText = searchText?.ToLower(); + + if (!string.IsNullOrEmpty(searchText)) { - var nameParts = new List(); - searchText = searchText?.ToLower(); + var nameLeft = name; - if (!string.IsNullOrEmpty(searchText)) + while (nameLeft.ToLower().IndexOf(searchText, StringComparison.Ordinal) is int rapidTextStart && rapidTextStart != -1) { - var nameLeft = name; + var before = rapidTextStart > 0 ? nameLeft.Substring(0, rapidTextStart) : null; + var rapidTravel = nameLeft.Substring(rapidTextStart, searchText.Length); - while (nameLeft.ToLower().IndexOf(searchText, StringComparison.Ordinal) is int rapidTextStart && rapidTextStart != -1) + nameLeft = nameLeft.Substring(rapidTextStart + searchText.Length); + + if (before != null) { - var before = rapidTextStart > 0 ? nameLeft.Substring(0, rapidTextStart) : null; - var rapidTravel = nameLeft.Substring(rapidTextStart, searchText.Length); - - nameLeft = nameLeft.Substring(rapidTextStart + searchText.Length); - - if (before != null) - { - nameParts.Add(new ItemNamePart(before)); - } - - nameParts.Add(new ItemNamePart(rapidTravel, true)); + nameParts.Add(new ItemNamePart(before)); } - if (nameLeft.Length > 0) - { - nameParts.Add(new ItemNamePart(nameLeft)); - } + nameParts.Add(new ItemNamePart(rapidTravel, true)); } - else + + if (nameLeft.Length > 0) { - nameParts.Add(new ItemNamePart(name)); + nameParts.Add(new ItemNamePart(nameLeft)); } - return nameParts; } - - public string GetFileName(string fullName) + else { - var parts = fullName.Split('.'); - var fileName = string.Join('.', parts[..^1]); - return string.IsNullOrEmpty(fileName) ? fullName : fileName; - } - - public string GetFileExtension(string fullName) - { - var parts = fullName.Split('.'); - return parts.Length == 1 || (parts.Length == 2 && string.IsNullOrEmpty(parts[0])) ? "" : parts[^1]; + nameParts.Add(new ItemNamePart(name)); } + return nameParts; } -} + + public string GetFileName(string fullName) + { + var parts = fullName.Split('.'); + var fileName = string.Join('.', parts[..^1]); + return string.IsNullOrEmpty(fileName) ? fullName : fileName; + } + + public string GetFileExtension(string fullName) + { + var parts = fullName.Split('.'); + return parts.Length == 1 || (parts.Length == 2 && string.IsNullOrEmpty(parts[0])) ? "" : parts[^1]; + } +} \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/Startup.cs b/src/AppCommon/FileTime.App.Core/Startup.cs index 13a8229..0c5524b 100644 --- a/src/AppCommon/FileTime.App.Core/Startup.cs +++ b/src/AppCommon/FileTime.App.Core/Startup.cs @@ -3,27 +3,26 @@ using FileTime.App.Core.Services.CommandHandler; using FileTime.App.Core.ViewModels; using Microsoft.Extensions.DependencyInjection; -namespace FileTime.App.Core -{ - public static class Startup - { - public static IServiceCollection AddCoreAppServices(this IServiceCollection serviceCollection) - { - return serviceCollection - .AddTransient() - .AddTransient() - .AddTransient() - .AddTransient() - .AddSingleton() - .AddSingleton() - .AddCommandHandlers(); - } +namespace FileTime.App.Core; - private static IServiceCollection AddCommandHandlers(this IServiceCollection serviceCollection) - { - return serviceCollection - .AddSingleton() - .AddSingleton(); - } +public static class Startup +{ + public static IServiceCollection AddCoreAppServices(this IServiceCollection serviceCollection) + { + return serviceCollection + .AddTransient() + .AddTransient() + .AddTransient() + .AddTransient() + .AddSingleton() + .AddSingleton() + .AddCommandHandlers(); + } + + private static IServiceCollection AddCommandHandlers(this IServiceCollection serviceCollection) + { + return serviceCollection + .AddSingleton() + .AddSingleton(); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/AppStateBase.cs b/src/AppCommon/FileTime.App.Core/ViewModels/AppStateBase.cs index 18fd13c..1807c19 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/AppStateBase.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/AppStateBase.cs @@ -5,50 +5,49 @@ using FileTime.App.Core.Models.Enums; using MvvmGen; using MoreLinq; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +[ViewModel] +public abstract partial class AppStateBase : IAppState { - [ViewModel] - public abstract partial class AppStateBase : IAppState + private readonly BehaviorSubject _searchText = new(null); + private readonly BehaviorSubject _selectedTab = new(null); + private readonly BehaviorSubject> _tabs = new(Enumerable.Empty()); + + [Property] + private ViewMode _viewMode; + + public ObservableCollection Tabs { get; } = new(); + public IObservable SearchText { get; private set; } + + public IObservable SelectedTab { get; private set; } + + partial void OnInitialize() { - private readonly BehaviorSubject _searchText = new(null); - private readonly BehaviorSubject _selectedTab = new(null); - private readonly BehaviorSubject> _tabs = new(Enumerable.Empty()); + Tabs.CollectionChanged += (_, _) => _tabs.OnNext(Tabs); + SearchText = _searchText.AsObservable(); + SelectedTab = Observable.CombineLatest(_tabs, _selectedTab, GetSelectedTab); + } - [Property] - private ViewMode _viewMode; + public void AddTab(ITabViewModel tabViewModel) + { + Tabs.Add(tabViewModel); + } - public ObservableCollection Tabs { get; } = new(); - public IObservable SearchText { get; private set; } + public void RemoveTab(ITabViewModel tabViewModel) + { + if (!Tabs.Contains(tabViewModel)) return; - public IObservable SelectedTab { get; private set; } + Tabs.Remove(tabViewModel); + } - partial void OnInitialize() - { - Tabs.CollectionChanged += (_, _) => _tabs.OnNext(Tabs); - SearchText = _searchText.AsObservable(); - SelectedTab = Observable.CombineLatest(_tabs, _selectedTab, GetSelectedTab); - } + public void SetSearchText(string? searchText) => _searchText.OnNext(searchText); - public void AddTab(ITabViewModel tabViewModel) - { - Tabs.Add(tabViewModel); - } + public void SetSelectedTab(ITabViewModel tabToSelect) => _selectedTab.OnNext(tabToSelect); - public void RemoveTab(ITabViewModel tabViewModel) - { - if (!Tabs.Contains(tabViewModel)) return; - - Tabs.Remove(tabViewModel); - } - - public void SetSearchText(string? searchText) => _searchText.OnNext(searchText); - - public void SetSelectedTab(ITabViewModel tabToSelect) => _selectedTab.OnNext(tabToSelect); - - private ITabViewModel? GetSelectedTab(IEnumerable tabs, ITabViewModel? expectedSelectedTab) - { - var (prefered, others) = tabs.OrderBy(t => t.TabNumber).Partition(t => t.TabNumber >= (expectedSelectedTab?.TabNumber ?? 0)); - return prefered.Concat(others).FirstOrDefault(); - } + private ITabViewModel? GetSelectedTab(IEnumerable tabs, ITabViewModel? expectedSelectedTab) + { + var (prefered, others) = tabs.OrderBy(t => t.TabNumber).Partition(t => t.TabNumber >= (expectedSelectedTab?.TabNumber ?? 0)); + return prefered.Concat(others).FirstOrDefault(); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/ContainerSizeContainerViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/ContainerSizeContainerViewModel.cs index 856c0e5..66eb239 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/ContainerSizeContainerViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/ContainerSizeContainerViewModel.cs @@ -2,21 +2,20 @@ using FileTime.App.Core.Services; using FileTime.Core.Models; using MvvmGen; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +[ViewModel(GenerateConstructor = false)] +public partial class ContainerSizeContainerViewModel : ItemViewModel, IContainerSizeContainerViewModel { - [ViewModel(GenerateConstructor = false)] - public partial class ContainerSizeContainerViewModel : ItemViewModel, IContainerSizeContainerViewModel + [Property] + private long _size; + + public ContainerSizeContainerViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState) { - [Property] - private long _size; + } - public ContainerSizeContainerViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState) - { - } - - public void Init(IContainer item, ITabViewModel parentTab) - { - Init((IItem)item, parentTab); - } + public void Init(IContainer item, ITabViewModel parentTab) + { + Init((IItem)item, parentTab); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/ContainerViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/ContainerViewModel.cs index ab8fe8c..d793d28 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/ContainerViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/ContainerViewModel.cs @@ -2,20 +2,19 @@ using FileTime.App.Core.Services; using FileTime.Core.Models; using MvvmGen; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +[ViewModel(GenerateConstructor = false)] +public partial class ContainerViewModel : ItemViewModel, IContainerViewModel { - [ViewModel(GenerateConstructor = false)] - public partial class ContainerViewModel : ItemViewModel, IContainerViewModel + public IContainer? Container => BaseItem as IContainer; + + public ContainerViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState) { - public IContainer? Container => BaseItem as IContainer; + } - public ContainerViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState) - { - } - - public void Init(IContainer item, ITabViewModel parentTab) - { - Init((IItem)item, parentTab); - } + public void Init(IContainer item, ITabViewModel parentTab) + { + Init((IItem)item, parentTab); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/ElementViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/ElementViewModel.cs index e2944ad..c9eb96c 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/ElementViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/ElementViewModel.cs @@ -2,21 +2,20 @@ using FileTime.App.Core.Services; using FileTime.Core.Models; using MvvmGen; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +[ViewModel(GenerateConstructor = false)] +public partial class ElementViewModel : ItemViewModel, IElementViewModel { - [ViewModel(GenerateConstructor = false)] - public partial class ElementViewModel : ItemViewModel, IElementViewModel + [Property] + private long? _size; + + public ElementViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState) { - [Property] - private long? _size; + } - public ElementViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState) - { - } - - public void Init(IElement item, ITabViewModel parentTab) - { - Init((IItem)item, parentTab); - } + public void Init(IElement item, ITabViewModel parentTab) + { + Init((IItem)item, parentTab); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/FileViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/FileViewModel.cs index 7dd1aa6..7ba9fe0 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/FileViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/FileViewModel.cs @@ -2,18 +2,17 @@ using FileTime.App.Core.Services; using FileTime.Core.Models; using MvvmGen; -namespace FileTime.App.Core.ViewModels -{ - [ViewModel(GenerateConstructor = false)] - public partial class FileViewModel : ElementViewModel, IFileViewModel - { - public FileViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState) - { - } +namespace FileTime.App.Core.ViewModels; - public void Init(IFileElement item, ITabViewModel parentTab) - { - Init((IElement)item, parentTab); - } +[ViewModel(GenerateConstructor = false)] +public partial class FileViewModel : ElementViewModel, IFileViewModel +{ + public FileViewModel(IItemNameConverterService _itemNameConverterService, IAppState _appState) : base(_itemNameConverterService, _appState) + { + } + + public void Init(IFileElement item, ITabViewModel parentTab) + { + Init((IElement)item, parentTab); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/ItemViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/ItemViewModel.cs index c73e746..0b690c2 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/ItemViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/ItemViewModel.cs @@ -7,54 +7,54 @@ using FileTime.Core.Models; using MoreLinq; using MvvmGen; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +[ViewModel] +[Inject(typeof(IAppState), "_appState")] +[Inject(typeof(IItemNameConverterService), "_itemNameConverterService")] +public abstract partial class ItemViewModel : IItemViewModel { - [ViewModel] - [Inject(typeof(IAppState), "_appState")] - [Inject(typeof(IItemNameConverterService), "_itemNameConverterService")] - public abstract partial class ItemViewModel : IItemViewModel + [Property] + private IItem? _baseItem; + + [Property] + private IObservable>? _displayName; + + [Property] + private string? _displayNameText; + + [Property] + private IObservable? _isSelected; + + [Property] + private IObservable? _isMarked; + + [Property] + private IObservable _viewMode; + + [Property] + private DateTime? _createdAt; + + [Property] + private string? _attributes; + + [Property] + private IObservable _isAlternative; + + public void Init(IItem item, ITabViewModel parentTab) { - [Property] - private IItem? _baseItem; + BaseItem = item; + DisplayName = _appState.SearchText.Select(s => _itemNameConverterService.GetDisplayName(item.DisplayName, s)); + DisplayNameText = item.DisplayName; + IsMarked = parentTab.MarkedItems.ToCollection().Select(m => m.Any(i => i.Path.Path == item.FullName?.Path)); + IsSelected = parentTab.CurrentSelectedItem.Select(EqualsTo); + IsAlternative = parentTab.CurrentItemsCollectionObservable.Select(c => c?.Index().FirstOrDefault(i => EqualsTo(i.Value)).Key % 2 == 0); + ViewMode = Observable.CombineLatest(IsMarked, IsSelected, IsAlternative, GenerateViewMode); + Attributes = item.Attributes; + CreatedAt = item.CreatedAt; + } - [Property] - private IObservable>? _displayName; - - [Property] - private string? _displayNameText; - - [Property] - private IObservable? _isSelected; - - [Property] - private IObservable? _isMarked; - - [Property] - private IObservable _viewMode; - - [Property] - private DateTime? _createdAt; - - [Property] - private string? _attributes; - - [Property] - private IObservable _isAlternative; - - public void Init(IItem item, ITabViewModel parentTab) - { - BaseItem = item; - DisplayName = _appState.SearchText.Select(s => _itemNameConverterService.GetDisplayName(item.DisplayName, s)); - DisplayNameText = item.DisplayName; - IsMarked = parentTab.MarkedItems.ToCollection().Select(m => m.Any(i => i.Path.Path == item.FullName?.Path)); - IsSelected = parentTab.CurrentSelectedItem.Select(EqualsTo); - IsAlternative = parentTab.CurrentItemsCollectionObservable.Select(c => c?.Index().FirstOrDefault(i => EqualsTo(i.Value)).Key % 2 == 0); - ViewMode = Observable.CombineLatest(IsMarked, IsSelected, IsAlternative, GenerateViewMode); - Attributes = item.Attributes; - CreatedAt = item.CreatedAt; - } - - private ItemViewMode GenerateViewMode(bool isMarked, bool isSelected, bool sAlternative) + private ItemViewMode GenerateViewMode(bool isMarked, bool isSelected, bool sAlternative) => (isMarked, isSelected, sAlternative) switch { (true, true, _) => ItemViewMode.MarkedSelected, @@ -65,9 +65,8 @@ namespace FileTime.App.Core.ViewModels _ => ItemViewMode.Default }; - public bool EqualsTo(IItemViewModel? itemViewModel) - { - return BaseItem?.FullName?.Path is string path && path == itemViewModel?.BaseItem?.FullName?.Path; - } + public bool EqualsTo(IItemViewModel? itemViewModel) + { + return BaseItem?.FullName?.Path is string path && path == itemViewModel?.BaseItem?.FullName?.Path; } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs index 27bd68c..87cf897 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs @@ -9,118 +9,118 @@ using FileTime.Tools.Extensions; using Microsoft.Extensions.DependencyInjection; using MvvmGen; -namespace FileTime.App.Core.ViewModels +namespace FileTime.App.Core.ViewModels; + +[ViewModel] +public partial class TabViewModel : ITabViewModel, IDisposable { - [ViewModel] - public partial class TabViewModel : ITabViewModel, IDisposable + private readonly IServiceProvider _serviceProvider; + private readonly IItemNameConverterService _itemNameConverterService; + private readonly IAppState _appState; + private readonly IRxSchedulerService _rxSchedulerService; + private readonly SourceList _markedItems = new(); + private readonly List _disposables = new(); + private bool disposed; + + public ITab? Tab { get; private set; } + public int TabNumber { get; private set; } + + public IObservable IsSelected { get; } + + public IObservable CurrentLocation { get; private set; } = null!; + public IObservable CurrentSelectedItem { get; private set; } = null!; + public IObservable>?> CurrentItems { get; private set; } = null!; + public IObservable> MarkedItems { get; } + public IObservable>?> SelectedsChildren { get; private set; } = null!; + public IObservable>?> ParentsChildren { get; private set; } = null!; + + public IObservable?> CurrentItemsCollectionObservable { get; private set; } = null!; + + [Property] + private BindedCollection? _currentItemsCollection; + + [Property] + private BindedCollection? _parentsChildrenCollection; + + [Property] + private BindedCollection? _selectedsChildrenCollection; + + public TabViewModel( + IServiceProvider serviceProvider, + IItemNameConverterService itemNameConverterService, + IAppState appState, + IRxSchedulerService rxSchedulerService) { - private readonly IServiceProvider _serviceProvider; - private readonly IItemNameConverterService _itemNameConverterService; - private readonly IAppState _appState; - private readonly IRxSchedulerService _rxSchedulerService; - private readonly SourceList _markedItems = new(); - private readonly List _disposables = new(); - private bool disposed; + _serviceProvider = serviceProvider; + _itemNameConverterService = itemNameConverterService; + _appState = appState; - public ITab? Tab { get; private set; } - public int TabNumber { get; private set; } + MarkedItems = _markedItems.Connect().StartWithEmpty(); + IsSelected = _appState.SelectedTab.Select(s => s == this); + _rxSchedulerService = rxSchedulerService; + } - public IObservable IsSelected { get; } + public void Init(ITab tab, int tabNumber) + { + Tab = tab; + TabNumber = tabNumber; - public IObservable CurrentLocation { get; private set; } = null!; - public IObservable CurrentSelectedItem { get; private set; } = null!; - public IObservable>?> CurrentItems { get; private set; } = null!; - public IObservable> MarkedItems { get; } - public IObservable>?> SelectedsChildren { get; private set; } = null!; - public IObservable>?> ParentsChildren { get; private set; } = null!; + CurrentLocation = tab.CurrentLocation.AsObservable(); + CurrentItems = tab.CurrentItems + .Select(items => items?.Transform(MapItemToViewModel)) + .ObserveOn(_rxSchedulerService.GetWorkerScheduler()) + .SubscribeOn(_rxSchedulerService.GetUIScheduler()) + .Publish(null) + .RefCount(); - public IObservable?> CurrentItemsCollectionObservable { get; private set; } = null!; - - [Property] - private BindedCollection? _currentItemsCollection; - - [Property] - private BindedCollection? _parentsChildrenCollection; - - [Property] - private BindedCollection? _selectedsChildrenCollection; - - public TabViewModel( - IServiceProvider serviceProvider, - IItemNameConverterService itemNameConverterService, - IAppState appState, - IRxSchedulerService rxSchedulerService) - { - _serviceProvider = serviceProvider; - _itemNameConverterService = itemNameConverterService; - _appState = appState; - - MarkedItems = _markedItems.Connect().StartWithEmpty(); - IsSelected = _appState.SelectedTab.Select(s => s == this); - _rxSchedulerService = rxSchedulerService; - } - - public void Init(ITab tab, int tabNumber) - { - Tab = tab; - TabNumber = tabNumber; - - CurrentLocation = tab.CurrentLocation.AsObservable(); - CurrentItems = tab.CurrentItems - .Select(items => items?.Transform(MapItemToViewModel)) - .ObserveOn(_rxSchedulerService.GetWorkerScheduler()) - .SubscribeOn(_rxSchedulerService.GetUIScheduler()) - .Publish(null) - .RefCount(); - - CurrentSelectedItem = - Observable.CombineLatest( + CurrentSelectedItem = + Observable.CombineLatest( CurrentItems, tab.CurrentSelectedItem, (currentItems, currentSelectedItemPath) => currentItems == null - ? Observable.Return((IItemViewModel?)null) - : currentItems - .ToCollection() - .Select(items => items.FirstOrDefault(i => i.BaseItem?.FullName == currentSelectedItemPath?.Path)) + ? Observable.Return((IItemViewModel?)null) + : currentItems + .ToCollection() + .Select(items => items.FirstOrDefault(i => i.BaseItem?.FullName == currentSelectedItemPath?.Path)) ) .Switch() .Publish(null) .RefCount(); - SelectedsChildren = InitSelectedsChildren(); - ParentsChildren = InitParentsChildren(); + SelectedsChildren = InitSelectedsChildren(); + ParentsChildren = InitParentsChildren(); - CurrentItemsCollectionObservable = CurrentItems - .Select(c => c != null ? c.ToCollection() : Observable.Return((IReadOnlyCollection?)null)) - .Switch() - .Publish(null) - .RefCount(); + CurrentItemsCollectionObservable = CurrentItems + .Select(c => c != null ? c.ToCollection() : Observable.Return((IReadOnlyCollection?)null)) + .Switch() + .Publish(null) + .RefCount(); - CurrentItems.Subscribe(children => - { - CurrentItemsCollection?.Dispose(); - CurrentItemsCollection = children.MapNull(c => new BindedCollection(c!)); - }); + CurrentItems.Subscribe(children => + { + CurrentItemsCollection?.Dispose(); + CurrentItemsCollection = children.MapNull(c => new BindedCollection(c!)); + }); - ParentsChildren.Subscribe(children => - { - ParentsChildrenCollection?.Dispose(); - ParentsChildrenCollection = children.MapNull(c => new BindedCollection(c!)); - }); + ParentsChildren.Subscribe(children => + { + ParentsChildrenCollection?.Dispose(); + ParentsChildrenCollection = children.MapNull(c => new BindedCollection(c!)); + }); - SelectedsChildren.Subscribe(children => - { - SelectedsChildrenCollection?.Dispose(); - SelectedsChildrenCollection = children.MapNull(c => new BindedCollection(c!)); - }); + SelectedsChildren.Subscribe(children => + { + SelectedsChildrenCollection?.Dispose(); + SelectedsChildrenCollection = children.MapNull(c => new BindedCollection(c!)); + }); - tab.CurrentLocation.Subscribe((_) => _markedItems.Clear()); + tab.CurrentLocation.Subscribe((_) => _markedItems.Clear()); - IObservable>?> InitSelectedsChildren() - { - var currentSelectedItemThrottled = CurrentSelectedItem.Throttle(TimeSpan.FromMilliseconds(250)).Publish(null).RefCount(); - return Observable.Merge( + IObservable>?> InitSelectedsChildren() + { + var currentSelectedItemThrottled = CurrentSelectedItem.Throttle(TimeSpan.FromMilliseconds(250)).Publish(null).RefCount(); + return Observable.Merge( currentSelectedItemThrottled .WhereNotNull() .OfType() @@ -136,17 +136,17 @@ namespace FileTime.App.Core.ViewModels .SubscribeOn(_rxSchedulerService.GetUIScheduler()) .Publish(null) .RefCount(); - } + } - IObservable>?> InitParentsChildren() - { - var parentThrottled = CurrentLocation - .Select(l => l?.Parent) - .DistinctUntilChanged() - .Publish(null) - .RefCount(); + IObservable>?> InitParentsChildren() + { + var parentThrottled = CurrentLocation + .Select(l => l?.Parent) + .DistinctUntilChanged() + .Publish(null) + .RefCount(); - return Observable.Merge( + return Observable.Merge( parentThrottled .Where(p => p is not null) .Select(p => Observable.FromAsync(async () => (IContainer)await p!.ResolveAsync())) @@ -162,85 +162,84 @@ namespace FileTime.App.Core.ViewModels .SubscribeOn(_rxSchedulerService.GetUIScheduler()) .Publish(null) .RefCount(); - } - } - - private static async Task MapItem(IAbsolutePath item) - => await item.ResolveAsync(forceResolve: true, itemInitializationSettings: new ItemInitializationSettings(true)); - - private IItemViewModel MapItemToViewModel(IItem item) - { - if (item is IContainer container) - { - var containerViewModel = _serviceProvider.GetInitableResolver(container, this).GetRequiredService(); - - return containerViewModel; - } - else if (item is IFileElement fileElement) - { - var fileViewModel = _serviceProvider.GetInitableResolver(fileElement, this).GetRequiredService(); - fileViewModel.Size = fileElement.Size; - - return fileViewModel; - } - else if (item is IElement element) - { - var elementViewModel = _serviceProvider.GetInitableResolver(element, this).GetRequiredService(); - - return elementViewModel; - } - - throw new ArgumentException($"{nameof(item)} is not {nameof(IContainer)} neither {nameof(IElement)}"); - } - - public void AddMarkedItem(IAbsolutePath item) => _markedItems.Add(item); - - public void RemoveMarkedItem(IAbsolutePath item) - { - var itemsToRemove = _markedItems.Items.Where(i => i.Path.Path == item.Path.Path).ToList(); - - _markedItems.RemoveMany(itemsToRemove); - } - - public void ToggleMarkedItem(IAbsolutePath item) - { - if (_markedItems.Items.Any(i => i.Path.Path == item.Path.Path)) - { - RemoveMarkedItem(item); - } - else - { - AddMarkedItem(item); - } - } - - public void ClearMarkedItems() - { - _markedItems.Clear(); - } - - ~TabViewModel() => Dispose(false); - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private void Dispose(bool disposing) - { - if (!disposed && disposing) - { - foreach (var disposable in _disposables) - { - try - { - disposable.Dispose(); - } - catch { } - } - } - disposed = true; } } + + private static async Task MapItem(IAbsolutePath item) + => await item.ResolveAsync(forceResolve: true, itemInitializationSettings: new ItemInitializationSettings(true)); + + private IItemViewModel MapItemToViewModel(IItem item) + { + if (item is IContainer container) + { + var containerViewModel = _serviceProvider.GetInitableResolver(container, this).GetRequiredService(); + + return containerViewModel; + } + else if (item is IFileElement fileElement) + { + var fileViewModel = _serviceProvider.GetInitableResolver(fileElement, this).GetRequiredService(); + fileViewModel.Size = fileElement.Size; + + return fileViewModel; + } + else if (item is IElement element) + { + var elementViewModel = _serviceProvider.GetInitableResolver(element, this).GetRequiredService(); + + return elementViewModel; + } + + throw new ArgumentException($"{nameof(item)} is not {nameof(IContainer)} neither {nameof(IElement)}"); + } + + public void AddMarkedItem(IAbsolutePath item) => _markedItems.Add(item); + + public void RemoveMarkedItem(IAbsolutePath item) + { + var itemsToRemove = _markedItems.Items.Where(i => i.Path.Path == item.Path.Path).ToList(); + + _markedItems.RemoveMany(itemsToRemove); + } + + public void ToggleMarkedItem(IAbsolutePath item) + { + if (_markedItems.Items.Any(i => i.Path.Path == item.Path.Path)) + { + RemoveMarkedItem(item); + } + else + { + AddMarkedItem(item); + } + } + + public void ClearMarkedItems() + { + _markedItems.Clear(); + } + + ~TabViewModel() => Dispose(false); + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!disposed && disposing) + { + foreach (var disposable in _disposables) + { + try + { + disposable.Dispose(); + } + catch { } + } + } + disposed = true; + } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs b/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs index 967ea73..a3a38c1 100644 --- a/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs +++ b/src/AppCommon/FileTime.App.DependencyInjection/DependencyInjection.cs @@ -3,18 +3,17 @@ using FileTime.Core.Services; using FileTime.Providers.Local; using Microsoft.Extensions.DependencyInjection; -namespace FileTime.App.DependencyInjection -{ - public static class DependencyInjection - { - public static IServiceCollection RegisterDefaultServices(IServiceCollection? serviceCollection = null) - { - serviceCollection ??= new ServiceCollection(); +namespace FileTime.App.DependencyInjection; - return serviceCollection - .AddTransient() - .AddCoreAppServices() - .AddLocalServices(); - } +public static class DependencyInjection +{ + public static IServiceCollection RegisterDefaultServices(IServiceCollection? serviceCollection = null) + { + serviceCollection ??= new ServiceCollection(); + + return serviceCollection + .AddTransient() + .AddCoreAppServices() + .AddLocalServices(); } } \ No newline at end of file diff --git a/src/AppCommon/FileTime.App.DependencyInjection/FileTime.App.DependencyInjection.csproj b/src/AppCommon/FileTime.App.DependencyInjection/FileTime.App.DependencyInjection.csproj index 16d495d..440ce50 100644 --- a/src/AppCommon/FileTime.App.DependencyInjection/FileTime.App.DependencyInjection.csproj +++ b/src/AppCommon/FileTime.App.DependencyInjection/FileTime.App.DependencyInjection.csproj @@ -5,6 +5,11 @@ enable enable + + + true + + diff --git a/src/ConsoleApp/FileTime.ConsoleUI.App/FileTime.ConsoleUI.App.csproj b/src/ConsoleApp/FileTime.ConsoleUI.App/FileTime.ConsoleUI.App.csproj index 132c02c..ec0a628 100644 --- a/src/ConsoleApp/FileTime.ConsoleUI.App/FileTime.ConsoleUI.App.csproj +++ b/src/ConsoleApp/FileTime.ConsoleUI.App/FileTime.ConsoleUI.App.csproj @@ -6,4 +6,8 @@ enable + + true + + diff --git a/src/ConsoleApp/FileTime.ConsoleUI/FileTime.ConsoleUI.csproj b/src/ConsoleApp/FileTime.ConsoleUI/FileTime.ConsoleUI.csproj index 5bb66e7..f29c3c7 100644 --- a/src/ConsoleApp/FileTime.ConsoleUI/FileTime.ConsoleUI.csproj +++ b/src/ConsoleApp/FileTime.ConsoleUI/FileTime.ConsoleUI.csproj @@ -7,6 +7,10 @@ enable + + true + + diff --git a/src/Core/FileTime.Core.Abstraction/Behaviors/IOnContainerEnter.cs b/src/Core/FileTime.Core.Abstraction/Behaviors/IOnContainerEnter.cs index 47bc880..0f3d100 100644 --- a/src/Core/FileTime.Core.Abstraction/Behaviors/IOnContainerEnter.cs +++ b/src/Core/FileTime.Core.Abstraction/Behaviors/IOnContainerEnter.cs @@ -1,7 +1,6 @@ -namespace FileTime.Core.Behaviors +namespace FileTime.Core.Behaviors; + +public interface IOnContainerEnter { - public interface IOnContainerEnter - { - Task OnEnter(); - } + Task OnEnter(); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Command/ICommand.cs b/src/Core/FileTime.Core.Abstraction/Command/ICommand.cs index d119d7e..8508a67 100644 --- a/src/Core/FileTime.Core.Abstraction/Command/ICommand.cs +++ b/src/Core/FileTime.Core.Abstraction/Command/ICommand.cs @@ -1,7 +1,6 @@ -namespace FileTime.Core.Command +namespace FileTime.Core.Command; + +public interface ICommand { - public interface ICommand - { - } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs b/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs index 338c855..ac66aee 100644 --- a/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs +++ b/src/Core/FileTime.Core.Abstraction/Command/ITransportationCommand.cs @@ -1,7 +1,6 @@ -namespace FileTime.Core.Command +namespace FileTime.Core.Command; + +public interface ITransportationCommand : ICommand { - public interface ITransportationCommand : ICommand - { - } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Enums/AbsolutePathType.cs b/src/Core/FileTime.Core.Abstraction/Enums/AbsolutePathType.cs index 8ea7f63..6526cc8 100644 --- a/src/Core/FileTime.Core.Abstraction/Enums/AbsolutePathType.cs +++ b/src/Core/FileTime.Core.Abstraction/Enums/AbsolutePathType.cs @@ -1,9 +1,8 @@ -namespace FileTime.Core.Enums +namespace FileTime.Core.Enums; + +public enum AbsolutePathType { - public enum AbsolutePathType - { - Unknown, - Container, - Element - } + Unknown, + Container, + Element } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Enums/SupportsDelete.cs b/src/Core/FileTime.Core.Abstraction/Enums/SupportsDelete.cs index ce052d5..04e3703 100644 --- a/src/Core/FileTime.Core.Abstraction/Enums/SupportsDelete.cs +++ b/src/Core/FileTime.Core.Abstraction/Enums/SupportsDelete.cs @@ -1,9 +1,8 @@ -namespace FileTime.Core.Enums +namespace FileTime.Core.Enums; + +public enum SupportsDelete { - public enum SupportsDelete - { - False, - True, - HardDeleteOnly, - } + False, + True, + HardDeleteOnly, } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/FileTime.Core.Abstraction.csproj b/src/Core/FileTime.Core.Abstraction/FileTime.Core.Abstraction.csproj index 0bf3e28..e9c5d5a 100644 --- a/src/Core/FileTime.Core.Abstraction/FileTime.Core.Abstraction.csproj +++ b/src/Core/FileTime.Core.Abstraction/FileTime.Core.Abstraction.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/Core/FileTime.Core.Abstraction/Models/Constants.cs b/src/Core/FileTime.Core.Abstraction/Models/Constants.cs index 7244ea6..343cb4b 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/Constants.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/Constants.cs @@ -1,7 +1,6 @@ -namespace FileTime.Core.Models +namespace FileTime.Core.Models; + +public static class Constants { - public static class Constants - { - public const char SeparatorChar = '/'; - } + public const char SeparatorChar = '/'; } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Models/FullName.cs b/src/Core/FileTime.Core.Abstraction/Models/FullName.cs index 406f5dd..d57a913 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/FullName.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/FullName.cs @@ -1,17 +1,16 @@ -namespace FileTime.Core.Models -{ - public record FullName(string Path) - { - public FullName? GetParent() - { - if (Path is null) return null; +namespace FileTime.Core.Models; - var pathParts = Path.TrimEnd(Constants.SeparatorChar).Split(Constants.SeparatorChar); - return pathParts.Length switch - { - > 1 => new(string.Join(Constants.SeparatorChar, pathParts.SkipLast(1))), - _ => null - }; - } +public record FullName(string Path) +{ + public FullName? GetParent() + { + if (Path is null) return null; + + var pathParts = Path.TrimEnd(Constants.SeparatorChar).Split(Constants.SeparatorChar); + return pathParts.Length switch + { + > 1 => new(string.Join(Constants.SeparatorChar, pathParts.SkipLast(1))), + _ => null + }; } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Models/IAbsolutePath.cs b/src/Core/FileTime.Core.Abstraction/Models/IAbsolutePath.cs index f0f8ea5..f958f00 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/IAbsolutePath.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/IAbsolutePath.cs @@ -1,16 +1,15 @@ using FileTime.Core.Enums; using FileTime.Core.Services; -namespace FileTime.Core.Models -{ - public interface IAbsolutePath - { - IContentProvider ContentProvider { get; } - IContentProvider? VirtualContentProvider { get; } - FullName Path { get; } - AbsolutePathType Type { get; } +namespace FileTime.Core.Models; - Task ResolveAsync(bool forceResolve = false, ItemInitializationSettings itemInitializationSettings = default); - Task ResolveAsyncSafe(bool forceResolve = false, ItemInitializationSettings itemInitializationSettings = default); - } +public interface IAbsolutePath +{ + IContentProvider ContentProvider { get; } + IContentProvider? VirtualContentProvider { get; } + FullName Path { get; } + AbsolutePathType Type { get; } + + Task ResolveAsync(bool forceResolve = false, ItemInitializationSettings itemInitializationSettings = default); + Task ResolveAsyncSafe(bool forceResolve = false, ItemInitializationSettings itemInitializationSettings = default); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Models/IContainer.cs b/src/Core/FileTime.Core.Abstraction/Models/IContainer.cs index b008d5c..e1c6b29 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/IContainer.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/IContainer.cs @@ -1,10 +1,9 @@ using DynamicData; -namespace FileTime.Core.Models +namespace FileTime.Core.Models; + +public interface IContainer : IItem { - public interface IContainer : IItem - { - IObservable>?> Items { get; } - IObservable IsLoading { get; } - } + IObservable>?> Items { get; } + IObservable IsLoading { get; } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Models/IElement.cs b/src/Core/FileTime.Core.Abstraction/Models/IElement.cs index cb68137..2b48a74 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/IElement.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/IElement.cs @@ -1,7 +1,6 @@ -namespace FileTime.Core.Models +namespace FileTime.Core.Models; + +public interface IElement : IItem { - public interface IElement : IItem - { - } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Models/IFileElement.cs b/src/Core/FileTime.Core.Abstraction/Models/IFileElement.cs index 6dff1a6..7a364a2 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/IFileElement.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/IFileElement.cs @@ -1,7 +1,6 @@ -namespace FileTime.Core.Models +namespace FileTime.Core.Models; + +public interface IFileElement : IElement { - public interface IFileElement : IElement - { - long Size { get; } - } + long Size { get; } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Models/IItem.cs b/src/Core/FileTime.Core.Abstraction/Models/IItem.cs index 15ed4cc..58208d0 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/IItem.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/IItem.cs @@ -1,23 +1,22 @@ using FileTime.Core.Enums; using FileTime.Core.Services; -namespace FileTime.Core.Models +namespace FileTime.Core.Models; + +public interface IItem { - public interface IItem - { - string Name { get; } - string DisplayName { get; } - FullName? FullName { get; } - NativePath? NativePath { get; } - IAbsolutePath? Parent { get; } - bool IsHidden { get; } - bool IsExists { get; } - DateTime? CreatedAt { get; } - SupportsDelete CanDelete { get; } - bool CanRename { get; } - IContentProvider Provider { get; } - string? Attributes { get; } - AbsolutePathType Type { get; } - IObservable> Exceptions { get; } - } + string Name { get; } + string DisplayName { get; } + FullName? FullName { get; } + NativePath? NativePath { get; } + IAbsolutePath? Parent { get; } + bool IsHidden { get; } + bool IsExists { get; } + DateTime? CreatedAt { get; } + SupportsDelete CanDelete { get; } + bool CanRename { get; } + IContentProvider Provider { get; } + string? Attributes { get; } + AbsolutePathType Type { get; } + IObservable> Exceptions { get; } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Models/ItemInitializationSettings.cs b/src/Core/FileTime.Core.Abstraction/Models/ItemInitializationSettings.cs index 82a14eb..b44a70b 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/ItemInitializationSettings.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/ItemInitializationSettings.cs @@ -1,12 +1,11 @@ -namespace FileTime.Core.Models -{ - public readonly struct ItemInitializationSettings - { - public readonly bool SkipChildInitialization; +namespace FileTime.Core.Models; - public ItemInitializationSettings(bool skipChildInitialization) - { - SkipChildInitialization = skipChildInitialization; - } +public readonly struct ItemInitializationSettings +{ + public readonly bool SkipChildInitialization; + + public ItemInitializationSettings(bool skipChildInitialization) + { + SkipChildInitialization = skipChildInitialization; } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Models/ItemsTransformator.cs b/src/Core/FileTime.Core.Abstraction/Models/ItemsTransformator.cs index c16b576..7213d21 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/ItemsTransformator.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/ItemsTransformator.cs @@ -1,7 +1,6 @@ -namespace FileTime.Core.Models -{ - public record ItemsTransformator( - string Name, - Func, Task>> Transformator - ); -} \ No newline at end of file +namespace FileTime.Core.Models; + +public record ItemsTransformator( + string Name, + Func, Task>> Transformator +); \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Models/NativePath.cs b/src/Core/FileTime.Core.Abstraction/Models/NativePath.cs index 8f1d703..3a1b7e7 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/NativePath.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/NativePath.cs @@ -1,4 +1,3 @@ -namespace FileTime.Core.Models -{ - public record NativePath(string Path); -} \ No newline at end of file +namespace FileTime.Core.Models; + +public record NativePath(string Path); \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Services/IContentProvider.cs b/src/Core/FileTime.Core.Abstraction/Services/IContentProvider.cs index 82ab077..c803d60 100644 --- a/src/Core/FileTime.Core.Abstraction/Services/IContentProvider.cs +++ b/src/Core/FileTime.Core.Abstraction/Services/IContentProvider.cs @@ -2,22 +2,21 @@ using FileTime.Core.Behaviors; using FileTime.Core.Enums; using FileTime.Core.Models; -namespace FileTime.Core.Services +namespace FileTime.Core.Services; + +public interface IContentProvider : IContainer, IOnContainerEnter { - public interface IContentProvider : IContainer, IOnContainerEnter - { - Task GetItemByFullNameAsync( - FullName fullName, - bool forceResolve = false, - AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, - ItemInitializationSettings itemInitializationSettings = default); + Task GetItemByFullNameAsync( + FullName fullName, + bool forceResolve = false, + AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, + ItemInitializationSettings itemInitializationSettings = default); - Task GetItemByNativePathAsync( - NativePath nativePath, - bool forceResolve = false, - AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, - ItemInitializationSettings itemInitializationSettings = default); + Task GetItemByNativePathAsync( + NativePath nativePath, + bool forceResolve = false, + AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, + ItemInitializationSettings itemInitializationSettings = default); - Task> GetItemsByContainerAsync(FullName fullName); - } + Task> GetItemsByContainerAsync(FullName fullName); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Abstraction/Services/ITab.cs b/src/Core/FileTime.Core.Abstraction/Services/ITab.cs index 54539cb..6733f3f 100644 --- a/src/Core/FileTime.Core.Abstraction/Services/ITab.cs +++ b/src/Core/FileTime.Core.Abstraction/Services/ITab.cs @@ -2,18 +2,17 @@ using DynamicData; using FileTime.Core.Models; using InitableService; -namespace FileTime.Core.Services -{ - public interface ITab : IInitable - { - IObservable CurrentLocation { get; } - IObservable CurrentSelectedItem { get; } - IObservable>?> CurrentItems { get; } +namespace FileTime.Core.Services; - void SetCurrentLocation(IContainer newLocation); - void AddSelectedItemsTransformator(ItemsTransformator transformator); - void RemoveSelectedItemsTransformator(ItemsTransformator transformator); - void RemoveSelectedItemsTransformatorByName(string name); - void SetSelectedItem(IAbsolutePath newSelectedItem); - } +public interface ITab : IInitable +{ + IObservable CurrentLocation { get; } + IObservable CurrentSelectedItem { get; } + IObservable>?> CurrentItems { get; } + + void SetCurrentLocation(IContainer newLocation); + void AddSelectedItemsTransformator(ItemsTransformator transformator); + void RemoveSelectedItemsTransformator(ItemsTransformator transformator); + void RemoveSelectedItemsTransformatorByName(string name); + void SetSelectedItem(IAbsolutePath newSelectedItem); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs b/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs index 528c95a..385a55b 100644 --- a/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs +++ b/src/Core/FileTime.Core.Command/Copy/CopyCommand.cs @@ -1,7 +1,6 @@ -namespace FileTime.Core.Command.Copy -{ - public class CopyCommand : ITransportationCommand - { +namespace FileTime.Core.Command.Copy; + +public class CopyCommand : ITransportationCommand +{ - } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Command/FileTime.Core.Command.csproj b/src/Core/FileTime.Core.Command/FileTime.Core.Command.csproj index 05261ba..e75e348 100644 --- a/src/Core/FileTime.Core.Command/FileTime.Core.Command.csproj +++ b/src/Core/FileTime.Core.Command/FileTime.Core.Command.csproj @@ -1,9 +1,13 @@ - - + + + + true + + net6.0 enable diff --git a/src/Core/FileTime.Core.Command/TransportMode.cs b/src/Core/FileTime.Core.Command/TransportMode.cs index 45b11cf..e8117a9 100644 --- a/src/Core/FileTime.Core.Command/TransportMode.cs +++ b/src/Core/FileTime.Core.Command/TransportMode.cs @@ -1,9 +1,8 @@ -namespace FileTime.Core.Command +namespace FileTime.Core.Command; + +public enum TransportMode { - public enum TransportMode - { - Merge, - Overwrite, - Skip - } + Merge, + Overwrite, + Skip } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Models/AbsolutePath.cs b/src/Core/FileTime.Core.Models/AbsolutePath.cs index c57cbf1..38d9b9f 100644 --- a/src/Core/FileTime.Core.Models/AbsolutePath.cs +++ b/src/Core/FileTime.Core.Models/AbsolutePath.cs @@ -1,45 +1,44 @@ using FileTime.Core.Enums; using FileTime.Core.Services; -namespace FileTime.Core.Models +namespace FileTime.Core.Models; + +public class AbsolutePath : IAbsolutePath { - public class AbsolutePath : IAbsolutePath + public IContentProvider ContentProvider { get; } + public IContentProvider? VirtualContentProvider { get; } + + public FullName Path { get; } + public AbsolutePathType Type { get; } + + public AbsolutePath(IContentProvider contentProvider, FullName path, AbsolutePathType type, IContentProvider? virtualContentProvider = null) { - public IContentProvider ContentProvider { get; } - public IContentProvider? VirtualContentProvider { get; } + ContentProvider = contentProvider; + Path = path; + VirtualContentProvider = virtualContentProvider; + Type = type; + } - public FullName Path { get; } - public AbsolutePathType Type { get; } + public AbsolutePath(IItem item, IContentProvider? virtualContentProvider = null) + { + ContentProvider = item.Provider; + Path = item.FullName ?? throw new ArgumentException($"{nameof(item.FullName)} can not be null.", nameof(item)); + VirtualContentProvider = virtualContentProvider; + Type = item.Type; + } - public AbsolutePath(IContentProvider contentProvider, FullName path, AbsolutePathType type, IContentProvider? virtualContentProvider = null) + public async Task ResolveAsync(bool forceResolve = false, ItemInitializationSettings itemInitializationSettings = default) + { + var provider = VirtualContentProvider ?? ContentProvider; + return await provider.GetItemByFullNameAsync(Path, forceResolve, Type, itemInitializationSettings); + } + + public async Task ResolveAsyncSafe(bool forceResolve = false, ItemInitializationSettings itemInitializationSettings = default) + { + try { - ContentProvider = contentProvider; - Path = path; - VirtualContentProvider = virtualContentProvider; - Type = type; - } - - public AbsolutePath(IItem item, IContentProvider? virtualContentProvider = null) - { - ContentProvider = item.Provider; - Path = item.FullName ?? throw new ArgumentException($"{nameof(item.FullName)} can not be null.", nameof(item)); - VirtualContentProvider = virtualContentProvider; - Type = item.Type; - } - - public async Task ResolveAsync(bool forceResolve = false, ItemInitializationSettings itemInitializationSettings = default) - { - var provider = VirtualContentProvider ?? ContentProvider; - return await provider.GetItemByFullNameAsync(Path, forceResolve, Type, itemInitializationSettings); - } - - public async Task ResolveAsyncSafe(bool forceResolve = false, ItemInitializationSettings itemInitializationSettings = default) - { - try - { - return await ResolveAsync(forceResolve, itemInitializationSettings); - } - catch { return null; } + return await ResolveAsync(forceResolve, itemInitializationSettings); } + catch { return null; } } } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Models/Container.cs b/src/Core/FileTime.Core.Models/Container.cs index 6837ab7..06a7a29 100644 --- a/src/Core/FileTime.Core.Models/Container.cs +++ b/src/Core/FileTime.Core.Models/Container.cs @@ -4,26 +4,25 @@ using DynamicData; using FileTime.Core.Enums; using FileTime.Core.Services; -namespace FileTime.Core.Models +namespace FileTime.Core.Models; + +public record Container( + string Name, + string DisplayName, + FullName FullName, + NativePath NativePath, + IAbsolutePath? Parent, + bool IsHidden, + bool IsExists, + DateTime? CreatedAt, + SupportsDelete CanDelete, + bool CanRename, + string? Attributes, + IContentProvider Provider, + IObservable> Exceptions, + IObservable>?> Items) : IContainer { - public record Container( - string Name, - string DisplayName, - FullName FullName, - NativePath NativePath, - IAbsolutePath? Parent, - bool IsHidden, - bool IsExists, - DateTime? CreatedAt, - SupportsDelete CanDelete, - bool CanRename, - string? Attributes, - IContentProvider Provider, - IObservable> Exceptions, - IObservable>?> Items) : IContainer - { - BehaviorSubject IsLoading { get; } = new BehaviorSubject(false); - IObservable IContainer.IsLoading => IsLoading.AsObservable(); - public AbsolutePathType Type => AbsolutePathType.Container; - } + BehaviorSubject IsLoading { get; } = new BehaviorSubject(false); + IObservable IContainer.IsLoading => IsLoading.AsObservable(); + public AbsolutePathType Type => AbsolutePathType.Container; } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Models/Element.cs b/src/Core/FileTime.Core.Models/Element.cs index 5dc83e5..1733937 100644 --- a/src/Core/FileTime.Core.Models/Element.cs +++ b/src/Core/FileTime.Core.Models/Element.cs @@ -1,23 +1,22 @@ using FileTime.Core.Enums; using FileTime.Core.Services; -namespace FileTime.Core.Models +namespace FileTime.Core.Models; + +public record Element( + string Name, + string DisplayName, + FullName FullName, + NativePath NativePath, + IAbsolutePath? Parent, + bool IsHidden, + bool IsExists, + DateTime? CreatedAt, + SupportsDelete CanDelete, + bool CanRename, + string? Attributes, + IContentProvider Provider, + IObservable> Exceptions) : IElement { - public record Element( - string Name, - string DisplayName, - FullName FullName, - NativePath NativePath, - IAbsolutePath? Parent, - bool IsHidden, - bool IsExists, - DateTime? CreatedAt, - SupportsDelete CanDelete, - bool CanRename, - string? Attributes, - IContentProvider Provider, - IObservable> Exceptions) : IElement - { - public AbsolutePathType Type => AbsolutePathType.Element; - } + public AbsolutePathType Type => AbsolutePathType.Element; } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Models/FileElement.cs b/src/Core/FileTime.Core.Models/FileElement.cs index 69bb9f5..33da745 100644 --- a/src/Core/FileTime.Core.Models/FileElement.cs +++ b/src/Core/FileTime.Core.Models/FileElement.cs @@ -1,9 +1,9 @@ using FileTime.Core.Enums; using FileTime.Core.Services; -namespace FileTime.Core.Models -{ - public record FileElement( +namespace FileTime.Core.Models; + +public record FileElement( string Name, string DisplayName, FullName FullName, @@ -32,5 +32,4 @@ namespace FileTime.Core.Models Attributes, Provider, Exceptions - ), IFileElement; -} \ No newline at end of file + ), IFileElement; \ No newline at end of file diff --git a/src/Core/FileTime.Core.Models/FileTime.Core.Models.csproj b/src/Core/FileTime.Core.Models/FileTime.Core.Models.csproj index 72dd3f9..f7ad8a6 100644 --- a/src/Core/FileTime.Core.Models/FileTime.Core.Models.csproj +++ b/src/Core/FileTime.Core.Models/FileTime.Core.Models.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/Core/FileTime.Core.Services/ContentProviderBase.cs b/src/Core/FileTime.Core.Services/ContentProviderBase.cs index e9b5b9d..4637447 100644 --- a/src/Core/FileTime.Core.Services/ContentProviderBase.cs +++ b/src/Core/FileTime.Core.Services/ContentProviderBase.cs @@ -4,64 +4,63 @@ using DynamicData; using FileTime.Core.Enums; using FileTime.Core.Models; -namespace FileTime.Core.Services +namespace FileTime.Core.Services; + +public abstract class ContentProviderBase : IContentProvider { - public abstract class ContentProviderBase : IContentProvider + protected BehaviorSubject>?> Items { get; } = new (null); + + IObservable>?> IContainer.Items => Items; + + public string Name { get; } + + public string DisplayName { get; } + + public FullName? FullName => null; + + public NativePath? NativePath => null; + + public bool IsHidden => false; + + public bool IsExists => true; + + public SupportsDelete CanDelete => SupportsDelete.False; + + public bool CanRename => false; + + public IContentProvider Provider => this; + + public IAbsolutePath? Parent => null; + + public DateTime? CreatedAt => null; + + public string? Attributes => null; + + protected BehaviorSubject IsLoading { get; } = new(false); + + IObservable IContainer.IsLoading => IsLoading.AsObservable(); + + public AbsolutePathType Type => AbsolutePathType.Container; + + public IObservable> Exceptions => Observable.Return(Enumerable.Empty()); + + protected ContentProviderBase(string name) { - protected BehaviorSubject>?> Items { get; } = new (null); - - IObservable>?> IContainer.Items => Items; - - public string Name { get; } - - public string DisplayName { get; } - - public FullName? FullName => null; - - public NativePath? NativePath => null; - - public bool IsHidden => false; - - public bool IsExists => true; - - public SupportsDelete CanDelete => SupportsDelete.False; - - public bool CanRename => false; - - public IContentProvider Provider => this; - - public IAbsolutePath? Parent => null; - - public DateTime? CreatedAt => null; - - public string? Attributes => null; - - protected BehaviorSubject IsLoading { get; } = new(false); - - IObservable IContainer.IsLoading => IsLoading.AsObservable(); - - public AbsolutePathType Type => AbsolutePathType.Container; - - public IObservable> Exceptions => Observable.Return(Enumerable.Empty()); - - protected ContentProviderBase(string name) - { - DisplayName = Name = name; - } - - public virtual Task OnEnter() => Task.CompletedTask; - public virtual async Task GetItemByFullNameAsync( - FullName fullName, - bool forceResolve = false, - AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, - ItemInitializationSettings itemInitializationSettings = default) - => await GetItemByNativePathAsync(GetNativePath(fullName), forceResolve, forceResolvePathType, itemInitializationSettings); - public abstract Task GetItemByNativePathAsync( - NativePath nativePath, - bool forceResolve = false, - AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, - ItemInitializationSettings itemInitializationSettings = default); - public abstract Task> GetItemsByContainerAsync(FullName fullName); - public abstract NativePath GetNativePath(FullName fullName); + DisplayName = Name = name; } + + public virtual Task OnEnter() => Task.CompletedTask; + public virtual async Task GetItemByFullNameAsync( + FullName fullName, + bool forceResolve = false, + AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, + ItemInitializationSettings itemInitializationSettings = default) + => await GetItemByNativePathAsync(GetNativePath(fullName), forceResolve, forceResolvePathType, itemInitializationSettings); + public abstract Task GetItemByNativePathAsync( + NativePath nativePath, + bool forceResolve = false, + AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, + ItemInitializationSettings itemInitializationSettings = default); + public abstract Task> GetItemsByContainerAsync(FullName fullName); + public abstract NativePath GetNativePath(FullName fullName); } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Services/FileTime.Core.Services.csproj b/src/Core/FileTime.Core.Services/FileTime.Core.Services.csproj index f2cc8f8..0c5eee1 100644 --- a/src/Core/FileTime.Core.Services/FileTime.Core.Services.csproj +++ b/src/Core/FileTime.Core.Services/FileTime.Core.Services.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/Core/FileTime.Core.Services/Tab.cs b/src/Core/FileTime.Core.Services/Tab.cs index d6c632c..4063dd6 100644 --- a/src/Core/FileTime.Core.Services/Tab.cs +++ b/src/Core/FileTime.Core.Services/Tab.cs @@ -3,24 +3,24 @@ using System.Reactive.Subjects; using DynamicData; using FileTime.Core.Models; -namespace FileTime.Core.Services +namespace FileTime.Core.Services; + +public class Tab : ITab { - public class Tab : ITab + private readonly BehaviorSubject _currentLocation = new(null); + private readonly BehaviorSubject _currentSelectedItem = new(null); + private readonly List _transformators = new(); + private IAbsolutePath? _currentSelectedItemCached; + + public IObservable CurrentLocation { get; } + public IObservable>?> CurrentItems { get; } + public IObservable CurrentSelectedItem { get; } + + public Tab() { - private readonly BehaviorSubject _currentLocation = new(null); - private readonly BehaviorSubject _currentSelectedItem = new(null); - private readonly List _transformators = new(); - private IAbsolutePath? _currentSelectedItemCached; - - public IObservable CurrentLocation { get; } - public IObservable>?> CurrentItems { get; } - public IObservable CurrentSelectedItem { get; } - - public Tab() - { - CurrentLocation = _currentLocation.DistinctUntilChanged().Publish(null).RefCount(); - CurrentItems = - Observable.Merge( + CurrentLocation = _currentLocation.DistinctUntilChanged().Publish(null).RefCount(); + CurrentItems = + Observable.Merge( CurrentLocation .Where(c => c is not null) .Select(c => c!.Items) @@ -33,13 +33,13 @@ namespace FileTime.Core.Services .Publish((IObservable>?)null) .RefCount(); - CurrentSelectedItem = - Observable.CombineLatest( + CurrentSelectedItem = + Observable.CombineLatest( CurrentItems .Select(c => c == null - ? Observable.Return?>(null) - : c.ToCollection() + ? Observable.Return?>(null) + : c.ToCollection() ) .Switch(), _currentSelectedItem, @@ -55,41 +55,40 @@ namespace FileTime.Core.Services .Publish(null) .RefCount(); - CurrentSelectedItem.Subscribe(s => - { - _currentSelectedItemCached = s; - _currentSelectedItem.OnNext(s); - }); - } - - private async Task MapItem(IAbsolutePath item) => await item.ResolveAsync(true); - - public void Init(IContainer currentLocation) + CurrentSelectedItem.Subscribe(s => { - _currentLocation.OnNext(currentLocation); - } + _currentSelectedItemCached = s; + _currentSelectedItem.OnNext(s); + }); + } - private static IAbsolutePath? GetSelectedItemByItems(IEnumerable items) - { - //TODO: - return new AbsolutePath(items.First()); - } + private async Task MapItem(IAbsolutePath item) => await item.ResolveAsync(true); - public void SetCurrentLocation(IContainer newLocation) => _currentLocation.OnNext(newLocation); + public void Init(IContainer currentLocation) + { + _currentLocation.OnNext(currentLocation); + } - public void SetSelectedItem(IAbsolutePath newSelectedItem) => _currentSelectedItem.OnNext(newSelectedItem); + private static IAbsolutePath? GetSelectedItemByItems(IEnumerable items) + { + //TODO: + return new AbsolutePath(items.First()); + } - public void AddSelectedItemsTransformator(ItemsTransformator transformator) => _transformators.Add(transformator); - public void RemoveSelectedItemsTransformator(ItemsTransformator transformator) => _transformators.Remove(transformator); - public void RemoveSelectedItemsTransformatorByName(string name) => _transformators.RemoveAll(t => t.Name == name); + public void SetCurrentLocation(IContainer newLocation) => _currentLocation.OnNext(newLocation); - public async Task OpenSelected() - { - if (_currentSelectedItemCached == null) return; - var resolvedSelectedItem = await _currentSelectedItemCached.ContentProvider.GetItemByFullNameAsync(_currentSelectedItemCached.Path); + public void SetSelectedItem(IAbsolutePath newSelectedItem) => _currentSelectedItem.OnNext(newSelectedItem); - if (resolvedSelectedItem is not IContainer resolvedContainer) return; - SetCurrentLocation(resolvedContainer); - } + public void AddSelectedItemsTransformator(ItemsTransformator transformator) => _transformators.Add(transformator); + public void RemoveSelectedItemsTransformator(ItemsTransformator transformator) => _transformators.Remove(transformator); + public void RemoveSelectedItemsTransformatorByName(string name) => _transformators.RemoveAll(t => t.Name == name); + + public async Task OpenSelected() + { + if (_currentSelectedItemCached == null) return; + var resolvedSelectedItem = await _currentSelectedItemCached.ContentProvider.GetItemByFullNameAsync(_currentSelectedItemCached.Path); + + if (resolvedSelectedItem is not IContainer resolvedContainer) return; + SetCurrentLocation(resolvedContainer); } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/CommandBindingConfiguration.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/CommandBindingConfiguration.cs index 22dcd0e..c33e702 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/CommandBindingConfiguration.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/CommandBindingConfiguration.cs @@ -1,89 +1,88 @@ using Avalonia.Input; using FileTime.App.Core.Command; -namespace FileTime.GuiApp.Configuration +namespace FileTime.GuiApp.Configuration; + +public class CommandBindingConfiguration { - public class CommandBindingConfiguration + public List Keys { get; set; } = new List(); + + public Commands Command { get; set; } = Commands.None; + + public string KeysDisplayText => GetKeysDisplayText(); + + public CommandBindingConfiguration() { } + + public CommandBindingConfiguration(Commands command, IEnumerable keys) { - public List Keys { get; set; } = new List(); + Keys = new List(keys); + Command = command; + } - public Commands Command { get; set; } = Commands.None; + public CommandBindingConfiguration(Commands command, KeyConfig key) + { + Keys = new List() { key }; + Command = command; + } - public string KeysDisplayText => GetKeysDisplayText(); + public CommandBindingConfiguration(Commands command, IEnumerable keys) + { + Keys = keys.Select(k => new KeyConfig(k)).ToList(); + Command = command; + } - public CommandBindingConfiguration() { } + public CommandBindingConfiguration(Commands command, Key key) + { + Keys = new List() { new KeyConfig(key) }; + Command = command; + } - public CommandBindingConfiguration(Commands command, IEnumerable keys) + public string GetKeysDisplayText() + { + var s = ""; + + foreach (var k in Keys) { - Keys = new List(keys); - Command = command; - } + var keyString = k.Key.ToString(); - public CommandBindingConfiguration(Commands command, KeyConfig key) - { - Keys = new List() { key }; - Command = command; - } - - public CommandBindingConfiguration(Commands command, IEnumerable keys) - { - Keys = keys.Select(k => new KeyConfig(k)).ToList(); - Command = command; - } - - public CommandBindingConfiguration(Commands command, Key key) - { - Keys = new List() { new KeyConfig(key) }; - Command = command; - } - - public string GetKeysDisplayText() - { - var s = ""; - - foreach (var k in Keys) + if (keyString.Length == 1) { - var keyString = k.Key.ToString(); - - if (keyString.Length == 1) - { - s += AddKeyWithCtrlOrAlt(k, s, (_, _, _) => k.Shift ? keyString.ToUpper() : keyString.ToLower()); - } - else - { - s += AddKeyWithCtrlOrAlt(k, s, AddSpecialKey); - } + s += AddKeyWithCtrlOrAlt(k, s, (_, _, _) => k.Shift ? keyString.ToUpper() : keyString.ToLower()); + } + else + { + s += AddKeyWithCtrlOrAlt(k, s, AddSpecialKey); } - - return s; } - private static string AddKeyWithCtrlOrAlt(KeyConfig key, string currentText, Func keyProcessor) - { - var s = ""; + return s; + } - bool ctrlOrAlt = key.Ctrl || key.Alt; + private static string AddKeyWithCtrlOrAlt(KeyConfig key, string currentText, Func keyProcessor) + { + var s = ""; - if (ctrlOrAlt && currentText.Length > 0 && currentText.Last() != ' ') s += " "; + bool ctrlOrAlt = key.Ctrl || key.Alt; - if (key.Ctrl) s += "CTRL+"; - if (key.Alt) s += "ALT+"; - s += keyProcessor(key, currentText, ctrlOrAlt); + if (ctrlOrAlt && currentText.Length > 0 && currentText.Last() != ' ') s += " "; - if (ctrlOrAlt) s += " "; + if (key.Ctrl) s += "CTRL+"; + if (key.Alt) s += "ALT+"; + s += keyProcessor(key, currentText, ctrlOrAlt); - return s; - } + if (ctrlOrAlt) s += " "; - private static string AddSpecialKey(KeyConfig key, string currentText, bool wasCtrlOrAlt) - { - var s = ""; + return s; + } - if (currentText.Length > 0 && currentText.Last() != ' ' && !wasCtrlOrAlt) s += " "; - s += key.Key.ToString(); - if (!wasCtrlOrAlt) s += " "; + private static string AddSpecialKey(KeyConfig key, string currentText, bool wasCtrlOrAlt) + { + var s = ""; - return s; - } + if (currentText.Length > 0 && currentText.Last() != ' ' && !wasCtrlOrAlt) s += " "; + s += key.Key.ToString(); + if (!wasCtrlOrAlt) s += " "; + + return s; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/KeyBindingConfiguration.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/KeyBindingConfiguration.cs index 7fec8f1..d9801ee 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/KeyBindingConfiguration.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/KeyBindingConfiguration.cs @@ -1,9 +1,8 @@ -namespace FileTime.GuiApp.Configuration +namespace FileTime.GuiApp.Configuration; + +public class KeyBindingConfiguration { - public class KeyBindingConfiguration - { - public bool UseDefaultBindings { get; set; } = true; - public List DefaultKeyBindings { get; set; } = new(); - public List KeyBindings { get; set; } = new(); - } + public bool UseDefaultBindings { get; set; } = true; + public List DefaultKeyBindings { get; set; } = new(); + public List KeyBindings { get; set; } = new(); } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/KeyConfig.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/KeyConfig.cs index 902319b..3aac821 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/KeyConfig.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/KeyConfig.cs @@ -1,32 +1,31 @@ using Avalonia.Input; -namespace FileTime.GuiApp.Configuration +namespace FileTime.GuiApp.Configuration; + +public class KeyConfig { - public class KeyConfig + public Key Key { get; set; } + public bool Shift { get; set; } + public bool Alt { get; set; } + public bool Ctrl { get; set; } + + public KeyConfig() { } + + public KeyConfig( + Key key, + bool shift = false, + bool alt = false, + bool ctrl = false) { - public Key Key { get; set; } - public bool Shift { get; set; } - public bool Alt { get; set; } - public bool Ctrl { get; set; } - - public KeyConfig() { } - - public KeyConfig( - Key key, - bool shift = false, - bool alt = false, - bool ctrl = false) - { - Key = key; - Shift = shift; - Alt = alt; - Ctrl = ctrl; - } - - public bool AreEquals(KeyConfig otherKeyConfig) => - Key == otherKeyConfig.Key - && Alt == otherKeyConfig.Alt - && Shift == otherKeyConfig.Shift - && Ctrl == otherKeyConfig.Ctrl; + Key = key; + Shift = shift; + Alt = alt; + Ctrl = ctrl; } + + public bool AreEquals(KeyConfig otherKeyConfig) => + Key == otherKeyConfig.Key + && Alt == otherKeyConfig.Alt + && Shift == otherKeyConfig.Shift + && Ctrl == otherKeyConfig.Ctrl; } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs index 64a2e51..61db9c6 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/MainConfiguration.cs @@ -3,125 +3,124 @@ using FileTime.App.Core.Command; using System; using System.Collections.Generic; -namespace FileTime.GuiApp.Configuration +namespace FileTime.GuiApp.Configuration; + +public static class MainConfiguration { - public static class MainConfiguration + private static readonly Lazy> _defaultKeybindings = new(InitDefaultKeyBindings); + + public static Dictionary Configuration { get; } + + static MainConfiguration() { - private static readonly Lazy> _defaultKeybindings = new(InitDefaultKeyBindings); + Configuration = new(); + PopulateDefaultEditorPrograms(Configuration); + PopulateDefaultKeyBindings(Configuration, _defaultKeybindings.Value, SectionNames.KeybindingSectionName + ":" + nameof(KeyBindingConfiguration.DefaultKeyBindings)); + } - public static Dictionary Configuration { get; } - - static MainConfiguration() + private static void PopulateDefaultKeyBindings(Dictionary configuration, List commandBindingConfigs, string basePath) + { + for (var i = 0; i < commandBindingConfigs.Count; i++) { - Configuration = new(); - PopulateDefaultEditorPrograms(Configuration); - PopulateDefaultKeyBindings(Configuration, _defaultKeybindings.Value, SectionNames.KeybindingSectionName + ":" + nameof(KeyBindingConfiguration.DefaultKeyBindings)); - } + var baseKey = basePath + $":[{i}]:"; + var commandBindingConfig = commandBindingConfigs[i]; + configuration.Add(baseKey + nameof(CommandBindingConfiguration.Command), commandBindingConfig.Command.ToString()); - private static void PopulateDefaultKeyBindings(Dictionary configuration, List commandBindingConfigs, string basePath) - { - for (var i = 0; i < commandBindingConfigs.Count; i++) + for (var j = 0; j < commandBindingConfig.Keys.Count; j++) { - var baseKey = basePath + $":[{i}]:"; - var commandBindingConfig = commandBindingConfigs[i]; - configuration.Add(baseKey + nameof(CommandBindingConfiguration.Command), commandBindingConfig.Command.ToString()); - - for (var j = 0; j < commandBindingConfig.Keys.Count; j++) - { - var key = commandBindingConfig.Keys[j]; - var keyBaseKey = baseKey + $"keys:[{j}]:"; - configuration.Add(keyBaseKey + nameof(KeyConfig.Key), key.Key.ToString()); - configuration.Add(keyBaseKey + nameof(KeyConfig.Shift), key.Shift.ToString()); - configuration.Add(keyBaseKey + nameof(KeyConfig.Alt), key.Alt.ToString()); - configuration.Add(keyBaseKey + nameof(KeyConfig.Ctrl), key.Ctrl.ToString()); - } + var key = commandBindingConfig.Keys[j]; + var keyBaseKey = baseKey + $"keys:[{j}]:"; + configuration.Add(keyBaseKey + nameof(KeyConfig.Key), key.Key.ToString()); + configuration.Add(keyBaseKey + nameof(KeyConfig.Shift), key.Shift.ToString()); + configuration.Add(keyBaseKey + nameof(KeyConfig.Alt), key.Alt.ToString()); + configuration.Add(keyBaseKey + nameof(KeyConfig.Ctrl), key.Ctrl.ToString()); } } + } - private static List InitDefaultKeyBindings() + private static List InitDefaultKeyBindings() + { + return new List() { - return new List() - { - new CommandBindingConfiguration(Commands.AutoRefresh, new KeyConfig(Key.R, shift: true)), - new CommandBindingConfiguration(Commands.ChangeTimelineMode, new[] { Key.T, Key.M }), - new CommandBindingConfiguration(Commands.CloseTab, Key.Q), - new CommandBindingConfiguration(Commands.Compress, new[] { Key.Y, Key.C }), - new CommandBindingConfiguration(Commands.Copy, new[] { Key.Y, Key.Y }), - new CommandBindingConfiguration(Commands.CopyHash, new[] { Key.C, Key.H }), - new CommandBindingConfiguration(Commands.CopyPath, new[] { Key.C, Key.P }), - new CommandBindingConfiguration(Commands.CreateContainer, Key.F7), - new CommandBindingConfiguration(Commands.CreateContainer, new[] { Key.C, Key.C }), - new CommandBindingConfiguration(Commands.CreateElement, new[] { Key.C, Key.E }), - new CommandBindingConfiguration(Commands.Cut, new[] { Key.D, Key.D }), - new CommandBindingConfiguration(Commands.Edit, new KeyConfig(Key.F4)), - new CommandBindingConfiguration(Commands.EnterRapidTravel, new KeyConfig(Key.OemComma, shift: true)), - new CommandBindingConfiguration(Commands.FindByName, new[] { Key.F, Key.N }), - new CommandBindingConfiguration(Commands.FindByNameRegex, new[] { Key.F, Key.R }), - new CommandBindingConfiguration(Commands.GoToHome, new[] { Key.G, Key.H }), - new CommandBindingConfiguration(Commands.GoToPath, new KeyConfig(Key.L, ctrl: true)), - new CommandBindingConfiguration(Commands.GoToPath, new[] { Key.G, Key.P }), - new CommandBindingConfiguration(Commands.GoToProvider, new[] { Key.G, Key.T }), - new CommandBindingConfiguration(Commands.GoToRoot, new[] { Key.G, Key.R }), - new CommandBindingConfiguration(Commands.HardDelete, new[] { new KeyConfig(Key.D,shift: true), new KeyConfig(Key.D, shift: true) }), - new CommandBindingConfiguration(Commands.Mark, Key.Space), - new CommandBindingConfiguration(Commands.MoveToLast, new KeyConfig(Key.G, shift: true)), - new CommandBindingConfiguration(Commands.MoveToFirst, new[] { Key.G, Key.G }), - new CommandBindingConfiguration(Commands.NextTimelineBlock, Key.L ), - new CommandBindingConfiguration(Commands.NextTimelineCommand, Key.J ), - new CommandBindingConfiguration(Commands.OpenInFileBrowser, new[] { Key.O, Key.E }), - new CommandBindingConfiguration(Commands.PasteMerge, new[] { Key.P, Key.P }), - new CommandBindingConfiguration(Commands.PasteOverwrite, new[] { Key.P, Key.O }), - new CommandBindingConfiguration(Commands.PasteSkip, new[] { Key.P, Key.S }), - new CommandBindingConfiguration(Commands.PinFavorite, new[] { Key.F, Key.P }), - new CommandBindingConfiguration(Commands.PreviousTimelineBlock, Key.H ), - new CommandBindingConfiguration(Commands.PreviousTimelineCommand, Key.K ), - new CommandBindingConfiguration(Commands.Refresh, Key.R), - new CommandBindingConfiguration(Commands.Rename, Key.F2), - new CommandBindingConfiguration(Commands.Rename, new[] { Key.C, Key.W }), - new CommandBindingConfiguration(Commands.RunCommand, new KeyConfig(Key.D4, shift: true)), - new CommandBindingConfiguration(Commands.ScanContainerSize, new[] { Key.C, Key.S }), - new CommandBindingConfiguration(Commands.ShowAllShotcut, Key.F1), - new CommandBindingConfiguration(Commands.SoftDelete, new[] { new KeyConfig(Key.D), new KeyConfig(Key.D, shift: true) }), - new CommandBindingConfiguration(Commands.SwitchToLastTab, Key.D9), - new CommandBindingConfiguration(Commands.SwitchToTab1, Key.D1), - new CommandBindingConfiguration(Commands.SwitchToTab2, Key.D2), - new CommandBindingConfiguration(Commands.SwitchToTab3, Key.D3), - new CommandBindingConfiguration(Commands.SwitchToTab4, Key.D4), - new CommandBindingConfiguration(Commands.SwitchToTab5, Key.D5), - new CommandBindingConfiguration(Commands.SwitchToTab6, Key.D6), - new CommandBindingConfiguration(Commands.SwitchToTab7, Key.D7), - new CommandBindingConfiguration(Commands.SwitchToTab8, Key.D8), - new CommandBindingConfiguration(Commands.TimelinePause, new[] { Key.T, Key.P }), - new CommandBindingConfiguration(Commands.TimelineRefresh, new[] { Key.T, Key.R }), - new CommandBindingConfiguration(Commands.TimelineStart, new[] { Key.T, Key.S }), - new CommandBindingConfiguration(Commands.ToggleAdvancedIcons, new[] { Key.Z, Key.I }), - new CommandBindingConfiguration(Commands.GoUp, Key.Left), - new CommandBindingConfiguration(Commands.Open, Key.Right), - new CommandBindingConfiguration(Commands.OpenOrRun, Key.Enter), - new CommandBindingConfiguration(Commands.MoveCursorUp, Key.Up), - new CommandBindingConfiguration(Commands.MoveCursorDown, Key.Down), - new CommandBindingConfiguration(Commands.MoveCursorUpPage, Key.PageUp), - new CommandBindingConfiguration(Commands.MoveCursorDownPage, Key.PageDown), - }; - } + new CommandBindingConfiguration(Commands.AutoRefresh, new KeyConfig(Key.R, shift: true)), + new CommandBindingConfiguration(Commands.ChangeTimelineMode, new[] { Key.T, Key.M }), + new CommandBindingConfiguration(Commands.CloseTab, Key.Q), + new CommandBindingConfiguration(Commands.Compress, new[] { Key.Y, Key.C }), + new CommandBindingConfiguration(Commands.Copy, new[] { Key.Y, Key.Y }), + new CommandBindingConfiguration(Commands.CopyHash, new[] { Key.C, Key.H }), + new CommandBindingConfiguration(Commands.CopyPath, new[] { Key.C, Key.P }), + new CommandBindingConfiguration(Commands.CreateContainer, Key.F7), + new CommandBindingConfiguration(Commands.CreateContainer, new[] { Key.C, Key.C }), + new CommandBindingConfiguration(Commands.CreateElement, new[] { Key.C, Key.E }), + new CommandBindingConfiguration(Commands.Cut, new[] { Key.D, Key.D }), + new CommandBindingConfiguration(Commands.Edit, new KeyConfig(Key.F4)), + new CommandBindingConfiguration(Commands.EnterRapidTravel, new KeyConfig(Key.OemComma, shift: true)), + new CommandBindingConfiguration(Commands.FindByName, new[] { Key.F, Key.N }), + new CommandBindingConfiguration(Commands.FindByNameRegex, new[] { Key.F, Key.R }), + new CommandBindingConfiguration(Commands.GoToHome, new[] { Key.G, Key.H }), + new CommandBindingConfiguration(Commands.GoToPath, new KeyConfig(Key.L, ctrl: true)), + new CommandBindingConfiguration(Commands.GoToPath, new[] { Key.G, Key.P }), + new CommandBindingConfiguration(Commands.GoToProvider, new[] { Key.G, Key.T }), + new CommandBindingConfiguration(Commands.GoToRoot, new[] { Key.G, Key.R }), + new CommandBindingConfiguration(Commands.HardDelete, new[] { new KeyConfig(Key.D,shift: true), new KeyConfig(Key.D, shift: true) }), + new CommandBindingConfiguration(Commands.Mark, Key.Space), + new CommandBindingConfiguration(Commands.MoveToLast, new KeyConfig(Key.G, shift: true)), + new CommandBindingConfiguration(Commands.MoveToFirst, new[] { Key.G, Key.G }), + new CommandBindingConfiguration(Commands.NextTimelineBlock, Key.L ), + new CommandBindingConfiguration(Commands.NextTimelineCommand, Key.J ), + new CommandBindingConfiguration(Commands.OpenInFileBrowser, new[] { Key.O, Key.E }), + new CommandBindingConfiguration(Commands.PasteMerge, new[] { Key.P, Key.P }), + new CommandBindingConfiguration(Commands.PasteOverwrite, new[] { Key.P, Key.O }), + new CommandBindingConfiguration(Commands.PasteSkip, new[] { Key.P, Key.S }), + new CommandBindingConfiguration(Commands.PinFavorite, new[] { Key.F, Key.P }), + new CommandBindingConfiguration(Commands.PreviousTimelineBlock, Key.H ), + new CommandBindingConfiguration(Commands.PreviousTimelineCommand, Key.K ), + new CommandBindingConfiguration(Commands.Refresh, Key.R), + new CommandBindingConfiguration(Commands.Rename, Key.F2), + new CommandBindingConfiguration(Commands.Rename, new[] { Key.C, Key.W }), + new CommandBindingConfiguration(Commands.RunCommand, new KeyConfig(Key.D4, shift: true)), + new CommandBindingConfiguration(Commands.ScanContainerSize, new[] { Key.C, Key.S }), + new CommandBindingConfiguration(Commands.ShowAllShotcut, Key.F1), + new CommandBindingConfiguration(Commands.SoftDelete, new[] { new KeyConfig(Key.D), new KeyConfig(Key.D, shift: true) }), + new CommandBindingConfiguration(Commands.SwitchToLastTab, Key.D9), + new CommandBindingConfiguration(Commands.SwitchToTab1, Key.D1), + new CommandBindingConfiguration(Commands.SwitchToTab2, Key.D2), + new CommandBindingConfiguration(Commands.SwitchToTab3, Key.D3), + new CommandBindingConfiguration(Commands.SwitchToTab4, Key.D4), + new CommandBindingConfiguration(Commands.SwitchToTab5, Key.D5), + new CommandBindingConfiguration(Commands.SwitchToTab6, Key.D6), + new CommandBindingConfiguration(Commands.SwitchToTab7, Key.D7), + new CommandBindingConfiguration(Commands.SwitchToTab8, Key.D8), + new CommandBindingConfiguration(Commands.TimelinePause, new[] { Key.T, Key.P }), + new CommandBindingConfiguration(Commands.TimelineRefresh, new[] { Key.T, Key.R }), + new CommandBindingConfiguration(Commands.TimelineStart, new[] { Key.T, Key.S }), + new CommandBindingConfiguration(Commands.ToggleAdvancedIcons, new[] { Key.Z, Key.I }), + new CommandBindingConfiguration(Commands.GoUp, Key.Left), + new CommandBindingConfiguration(Commands.Open, Key.Right), + new CommandBindingConfiguration(Commands.OpenOrRun, Key.Enter), + new CommandBindingConfiguration(Commands.MoveCursorUp, Key.Up), + new CommandBindingConfiguration(Commands.MoveCursorDown, Key.Down), + new CommandBindingConfiguration(Commands.MoveCursorUpPage, Key.PageUp), + new CommandBindingConfiguration(Commands.MoveCursorDownPage, Key.PageDown), + }; + } - private static void PopulateDefaultEditorPrograms(Dictionary configuration) + private static void PopulateDefaultEditorPrograms(Dictionary configuration) + { + var editorPrograms = new List() { - var editorPrograms = new List() - { - new ProgramConfiguration(@"c:\Program Files\Notepad++\notepad++.exe"), - new ProgramConfiguration("notepad.exe"), - }; + new ProgramConfiguration(@"c:\Program Files\Notepad++\notepad++.exe"), + new ProgramConfiguration("notepad.exe"), + }; - for (var i = 0; i < editorPrograms.Count; i++) - { - if (editorPrograms[i].Path is not string path) continue; - configuration.Add($"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}", path); + for (var i = 0; i < editorPrograms.Count; i++) + { + if (editorPrograms[i].Path is not string path) continue; + configuration.Add($"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Path)}", path); - if (editorPrograms[i].Arguments is string arguments) - { - configuration.Add($"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}", arguments); - } + if (editorPrograms[i].Arguments is string arguments) + { + configuration.Add($"{SectionNames.ProgramsSectionName}:{nameof(ProgramsConfiguration.DefaultEditorPrograms)}:[{i}]:{nameof(ProgramConfiguration.Arguments)}", arguments); } } } diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/ProgramConfiguration.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/ProgramConfiguration.cs index 83df6da..1cdf1e8 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/ProgramConfiguration.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/ProgramConfiguration.cs @@ -1,16 +1,15 @@ -namespace FileTime.GuiApp.Configuration +namespace FileTime.GuiApp.Configuration; + +public class ProgramConfiguration { - public class ProgramConfiguration + public string? Path { get; set; } + public string? Arguments { get; set; } + + public ProgramConfiguration() { } + + public ProgramConfiguration(string? path, string? arguments = null) { - public string? Path { get; set; } - public string? Arguments { get; set; } - - public ProgramConfiguration() { } - - public ProgramConfiguration(string? path, string? arguments = null) - { - Path = path; - Arguments = arguments; - } + Path = path; + Arguments = arguments; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/ProgramsConfiguration.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/ProgramsConfiguration.cs index 446abdf..28230f7 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/ProgramsConfiguration.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/ProgramsConfiguration.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; -namespace FileTime.GuiApp.Configuration +namespace FileTime.GuiApp.Configuration; + +public class ProgramsConfiguration { - public class ProgramsConfiguration - { - public List DefaultEditorPrograms { get; set; } = new(); - public List EditorPrograms { get; set; } = new(); - } + public List DefaultEditorPrograms { get; set; } = new(); + public List EditorPrograms { get; set; } = new(); } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/SectionNames.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/SectionNames.cs index be44f8f..c8afcce 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/SectionNames.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Configuration/SectionNames.cs @@ -1,8 +1,7 @@ -namespace FileTime.GuiApp.Configuration +namespace FileTime.GuiApp.Configuration; + +public static class SectionNames { - public static class SectionNames - { - public const string KeybindingSectionName = "KeyBindings"; - public const string ProgramsSectionName = "Programs"; - } + public const string KeybindingSectionName = "KeyBindings"; + public const string ProgramsSectionName = "Programs"; } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/FileTime.GuiApp.Abstractions.csproj b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/FileTime.GuiApp.Abstractions.csproj index e4d07e5..e7b2eb3 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/FileTime.GuiApp.Abstractions.csproj +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/FileTime.GuiApp.Abstractions.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Models/SpecialKeysStatus.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Models/SpecialKeysStatus.cs index 10b54d1..c0f8f06 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Models/SpecialKeysStatus.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Models/SpecialKeysStatus.cs @@ -1,4 +1,3 @@ -namespace FileTime.GuiApp.Models -{ - public record SpecialKeysStatus(bool IsAltPressed, bool IsShiftPressed, bool IsCtrlPressed); -} \ No newline at end of file +namespace FileTime.GuiApp.Models; + +public record SpecialKeysStatus(bool IsAltPressed, bool IsShiftPressed, bool IsCtrlPressed); \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDefaultModeKeyInputHandler.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDefaultModeKeyInputHandler.cs index 9d84b42..781bfcd 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDefaultModeKeyInputHandler.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IDefaultModeKeyInputHandler.cs @@ -1,4 +1,3 @@ -namespace FileTime.GuiApp.Services -{ - public interface IDefaultModeKeyInputHandler : IKeyInputHandler { } -} \ No newline at end of file +namespace FileTime.GuiApp.Services; + +public interface IDefaultModeKeyInputHandler : IKeyInputHandler { } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyInputHandler.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyInputHandler.cs index 1ae5f77..bb53e19 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyInputHandler.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyInputHandler.cs @@ -1,10 +1,9 @@ using Avalonia.Input; using FileTime.GuiApp.Models; -namespace FileTime.GuiApp.Services +namespace FileTime.GuiApp.Services; + +public interface IKeyInputHandler { - public interface IKeyInputHandler - { - Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action setHandled); - } + Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action setHandled); } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyInputHandlerService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyInputHandlerService.cs index 7da92c9..b203507 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyInputHandlerService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyInputHandlerService.cs @@ -1,9 +1,8 @@ using Avalonia.Input; -namespace FileTime.GuiApp.Services +namespace FileTime.GuiApp.Services; + +public interface IKeyInputHandlerService { - public interface IKeyInputHandlerService - { - Task ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action setHandled); - } + Task ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action setHandled); } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyboardConfigurationService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyboardConfigurationService.cs index 84f9922..224a9ac 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyboardConfigurationService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IKeyboardConfigurationService.cs @@ -1,11 +1,10 @@ using FileTime.GuiApp.Configuration; -namespace FileTime.GuiApp.Services +namespace FileTime.GuiApp.Services; + +public interface IKeyboardConfigurationService { - public interface IKeyboardConfigurationService - { - IReadOnlyList CommandBindings { get; } - IReadOnlyList UniversalCommandBindings { get; } - IReadOnlyList AllShortcut { get; } - } + IReadOnlyList CommandBindings { get; } + IReadOnlyList UniversalCommandBindings { get; } + IReadOnlyList AllShortcut { get; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IRapidTravelModeKeyInputHandler.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IRapidTravelModeKeyInputHandler.cs index e15ca90..8f7ddad 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IRapidTravelModeKeyInputHandler.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/Services/IRapidTravelModeKeyInputHandler.cs @@ -1,4 +1,3 @@ -namespace FileTime.GuiApp.Services -{ - public interface IRapidTravelModeKeyInputHandler : IKeyInputHandler { } -} \ No newline at end of file +namespace FileTime.GuiApp.Services; + +public interface IRapidTravelModeKeyInputHandler : IKeyInputHandler { } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/IGuiAppState.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/IGuiAppState.cs index bf714ec..bfad024 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/IGuiAppState.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.Abstractions/ViewModels/IGuiAppState.cs @@ -1,14 +1,13 @@ using FileTime.App.Core.ViewModels; using FileTime.GuiApp.Configuration; -namespace FileTime.GuiApp.ViewModels +namespace FileTime.GuiApp.ViewModels; + +public interface IGuiAppState : IAppState { - public interface IGuiAppState : IAppState - { - List PreviousKeys { get; } - bool IsAllShortcutVisible { get; set; } - bool NoCommandFound { get; set; } - string? MessageBoxText { get; set; } - List PossibleCommands { get; set; } - } + List PreviousKeys { get; } + bool IsAllShortcutVisible { get; set; } + bool NoCommandFound { get; set; } + string? MessageBoxText { get; set; } + List PossibleCommands { get; set; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/App.axaml.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.App/App.axaml.cs index 3349073..1e871f5 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/App.axaml.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/App.axaml.cs @@ -7,40 +7,39 @@ using FileTime.GuiApp.Views; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -namespace FileTime.GuiApp +namespace FileTime.GuiApp; + +public partial class App : Application { - public partial class App : Application + static App() { - static App() - { - DI.ServiceProvider ??= DependencyInjection - .RegisterDefaultServices() - .AddConfiguration() - .RegisterLogging() - .RegisterServices() - .AddViewModels() - .BuildServiceProvider() - .InitSerilog(); + DI.ServiceProvider ??= DependencyInjection + .RegisterDefaultServices() + .AddConfiguration() + .RegisterLogging() + .RegisterServices() + .AddViewModels() + .BuildServiceProvider() + .InitSerilog(); - var logger = DI.ServiceProvider.GetRequiredService>(); - logger.LogInformation("App initialization completed"); - } - public override void Initialize() - { - AvaloniaXamlLoader.Load(this); - } + var logger = DI.ServiceProvider.GetRequiredService>(); + logger.LogInformation("App initialization completed"); + } + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } - public override void OnFrameworkInitializationCompleted() + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { - if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + desktop.MainWindow = new MainWindow { - desktop.MainWindow = new MainWindow - { - DataContext = new MainWindowLoadingViewModel(), - }; - } - - base.OnFrameworkInitializationCompleted(); + DataContext = new MainWindowLoadingViewModel(), + }; } + + base.OnFrameworkInitializationCompleted(); } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/FileTime.GuiApp.App.csproj b/src/GuiApp/Avalonia/FileTime.GuiApp.App/FileTime.GuiApp.App.csproj index d257293..fbbdc3b 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/FileTime.GuiApp.App.csproj +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/FileTime.GuiApp.App.csproj @@ -9,6 +9,11 @@ filetime.ico 0.0.1 + + + true + + diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Program.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Program.cs index 9301818..2ffdf23 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Program.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Program.cs @@ -3,19 +3,19 @@ using System.IO; using Avalonia; using Avalonia.ReactiveUI; -namespace FileTime.GuiApp +namespace FileTime.GuiApp; + +public static class Program { - public static class Program + public static string AppDataRoot { get; } + public static string EnvironmentName { get; } + + static Program() { - public static string AppDataRoot { get; } - public static string EnvironmentName { get; } - - static Program() - { #if DEBUG - EnvironmentName = "Development"; + EnvironmentName = "Development"; - AppDataRoot = Path.Combine(Environment.CurrentDirectory, "appdata"); + AppDataRoot = Path.Combine(Environment.CurrentDirectory, "appdata"); #else EnvironmentName = "Release"; @@ -43,20 +43,19 @@ namespace FileTime.GuiApp if (appDataRoot == null) throw new UnauthorizedAccessException(); AppDataRoot = appDataRoot; #endif - } - - // Initialization code. Don't use any Avalonia, third-party APIs or any - // SynchronizationContext-reliant code before AppMain is called: things aren't initialized - // yet and stuff might break. - [STAThread] - public static void Main(string[] args) => BuildAvaloniaApp() - .StartWithClassicDesktopLifetime(args); - - // Avalonia configuration, don't remove; also used by visual designer. - public static AppBuilder BuildAvaloniaApp() - => AppBuilder.Configure() - .UsePlatformDetect() - .UseReactiveUI() - .LogToTrace(); } -} + + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UsePlatformDetect() + .UseReactiveUI() + .LogToTrace(); +} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs index fd03de2..f815899 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/Startup.cs @@ -11,70 +11,69 @@ using Microsoft.Extensions.DependencyInjection; using Serilog; using Serilog.Configuration; -namespace FileTime.GuiApp +namespace FileTime.GuiApp; + +public static class Startup { - public static class Startup + internal static IServiceCollection AddViewModels(this IServiceCollection serviceCollection) { - internal static IServiceCollection AddViewModels(this IServiceCollection serviceCollection) - { - return serviceCollection - .AddSingleton() - .AddSingleton() - .AddSingleton(s => s.GetRequiredService()) - .AddSingleton(s => s.GetRequiredService()); - } - internal static IServiceCollection RegisterServices(this IServiceCollection serviceCollection) - { - return serviceCollection - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton(); - } + return serviceCollection + .AddSingleton() + .AddSingleton() + .AddSingleton(s => s.GetRequiredService()) + .AddSingleton(s => s.GetRequiredService()); + } + internal static IServiceCollection RegisterServices(this IServiceCollection serviceCollection) + { + return serviceCollection + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(); + } - internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection) - { - return serviceCollection.AddLogging(loggingBuilder => - loggingBuilder.AddSerilog(dispose: true) - ); - } + internal static IServiceCollection RegisterLogging(this IServiceCollection serviceCollection) + { + return serviceCollection.AddLogging(loggingBuilder => + loggingBuilder.AddSerilog(dispose: true) + ); + } - internal static IServiceCollection AddConfiguration(this IServiceCollection serviceCollection) - { - var configuration = new ConfigurationBuilder() - .AddInMemoryCollection(MainConfiguration.Configuration) - .AddJsonFile("appsettings.json", optional: true) - .AddJsonFile($"appsettings.{Program.EnvironmentName}.json", true) - .Build(); + internal static IServiceCollection AddConfiguration(this IServiceCollection serviceCollection) + { + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(MainConfiguration.Configuration) + .AddJsonFile("appsettings.json", optional: true) + .AddJsonFile($"appsettings.{Program.EnvironmentName}.json", true) + .Build(); - return serviceCollection - .Configure(configuration.GetSection(SectionNames.ProgramsSectionName)) - .Configure(configuration.GetSection(SectionNames.KeybindingSectionName)) - .AddSingleton(configuration); - } + return serviceCollection + .Configure(configuration.GetSection(SectionNames.ProgramsSectionName)) + .Configure(configuration.GetSection(SectionNames.KeybindingSectionName)) + .AddSingleton(configuration); + } - internal static IServiceProvider InitSerilog(this IServiceProvider serviceProvider) - { - Log.Logger = new LoggerConfiguration() - .ReadFrom.Configuration(serviceProvider.GetService()) - .Enrich.FromLogContext() - .WriteTo.File( - Path.Combine(Program.AppDataRoot, "logs", "appLog.log"), - fileSizeLimitBytes: 10 * 1024 * 1024, - rollOnFileSizeLimit: true, - rollingInterval: RollingInterval.Day) - .WriteTo.MessageBoxSink(serviceProvider) - .CreateLogger(); + internal static IServiceProvider InitSerilog(this IServiceProvider serviceProvider) + { + Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(serviceProvider.GetService()) + .Enrich.FromLogContext() + .WriteTo.File( + Path.Combine(Program.AppDataRoot, "logs", "appLog.log"), + fileSizeLimitBytes: 10 * 1024 * 1024, + rollOnFileSizeLimit: true, + rollingInterval: RollingInterval.Day) + .WriteTo.MessageBoxSink(serviceProvider) + .CreateLogger(); - return serviceProvider; - } + return serviceProvider; + } - internal static LoggerConfiguration MessageBoxSink( - this LoggerSinkConfiguration loggerConfiguration, - IServiceProvider serviceProvider) - { - return loggerConfiguration.Sink(serviceProvider.GetService()); - } + internal static LoggerConfiguration MessageBoxSink( + this LoggerSinkConfiguration loggerConfiguration, + IServiceProvider serviceProvider) + { + return loggerConfiguration.Sink(serviceProvider.GetService()); } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/FileTime.GuiApp.CustomImpl.csproj b/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/FileTime.GuiApp.CustomImpl.csproj index 92c9dea..e71c27f 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/FileTime.GuiApp.CustomImpl.csproj +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/FileTime.GuiApp.CustomImpl.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/ViewModels/GuiAppState.cs b/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/ViewModels/GuiAppState.cs index 0183ec0..5e2c5d8 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/ViewModels/GuiAppState.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.CustomImpl/ViewModels/GuiAppState.cs @@ -2,23 +2,22 @@ using FileTime.App.Core.ViewModels; using FileTime.GuiApp.Configuration; using MvvmGen; -namespace FileTime.GuiApp.ViewModels +namespace FileTime.GuiApp.ViewModels; + +[ViewModel] +public partial class GuiAppState : AppStateBase, IGuiAppState { - [ViewModel] - public partial class GuiAppState : AppStateBase, IGuiAppState - { - [Property] - private bool _isAllShortcutVisible; + [Property] + private bool _isAllShortcutVisible; - [Property] - private bool _noCommandFound; + [Property] + private bool _noCommandFound; - [Property] - private string? _messageBoxText; + [Property] + private string? _messageBoxText; - [Property] - private List _possibleCommands = new(); + [Property] + private List _possibleCommands = new(); - public List PreviousKeys { get; } = new(); - } + public List PreviousKeys { get; } = new(); } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/CompareConverter.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/CompareConverter.cs index ba7a427..868a83b 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/CompareConverter.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/CompareConverter.cs @@ -1,54 +1,53 @@ using System.Globalization; using Avalonia.Data.Converters; -namespace FileTime.GuiApp.Converters +namespace FileTime.GuiApp.Converters; + +public enum ComparisonCondition { - public enum ComparisonCondition + Equal, + GreaterThan, + LessThan, + LessThanOrEqual, + NotEqual, + GreaterThanOrEqual +} + +public class CompareConverter : IValueConverter +{ + public ComparisonCondition ComparisonCondition { get; set; } = ComparisonCondition.Equal; + + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { - Equal, - GreaterThan, - LessThan, - LessThanOrEqual, - NotEqual, - GreaterThanOrEqual + return Compare(value, parameter); } - public class CompareConverter : IValueConverter + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { - public ComparisonCondition ComparisonCondition { get; set; } = ComparisonCondition.Equal; + throw new NotImplementedException(); + } - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + private bool Compare(object? value, object? parameter) + { + if (ComparisonCondition == ComparisonCondition.GreaterThan) { - return Compare(value, parameter); + if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt > parameterInt; + else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble > parameterDouble; + else throw new NotSupportedException(); + } + else if (ComparisonCondition == ComparisonCondition.NotEqual) + { + if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt != parameterInt; + else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble != parameterDouble; + return value != parameter; + } + else if (ComparisonCondition == ComparisonCondition.Equal) + { + if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt == parameterInt; + else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble == parameterDouble; + else if (value?.GetType().IsEnum ?? false && Enum.TryParse(value.GetType(), parameter?.ToString(), out var _)) return value.ToString() == parameter?.ToString(); } - public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - - private bool Compare(object? value, object? parameter) - { - if (ComparisonCondition == ComparisonCondition.GreaterThan) - { - if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt > parameterInt; - else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble > parameterDouble; - else throw new NotSupportedException(); - } - else if (ComparisonCondition == ComparisonCondition.NotEqual) - { - if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt != parameterInt; - else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble != parameterDouble; - return value != parameter; - } - else if (ComparisonCondition == ComparisonCondition.Equal) - { - if (value is int valueInt && (parameter is int parameterInt || int.TryParse(parameter?.ToString(), out parameterInt))) return valueInt == parameterInt; - else if (value is double valueDouble && (parameter is double parameterDouble || double.TryParse(parameter?.ToString(), out parameterDouble))) return valueDouble == parameterDouble; - else if (value?.GetType().IsEnum ?? false && Enum.TryParse(value.GetType(), parameter?.ToString(), out var _)) return value.ToString() == parameter?.ToString(); - } - - return value == parameter; - } + return value == parameter; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/DateTimeConverter.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/DateTimeConverter.cs index 3d8b00f..7ecdb8f 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/DateTimeConverter.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/DateTimeConverter.cs @@ -1,18 +1,17 @@ using System.Globalization; using Avalonia.Data.Converters; -namespace FileTime.GuiApp.Converters -{ - public class DateTimeConverter : IValueConverter - { - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) => - value is DateTime dateTime && parameter is string parameterS - ? dateTime.ToString(parameterS) - : value; +namespace FileTime.GuiApp.Converters; - public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } +public class DateTimeConverter : IValueConverter +{ + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) => + value is DateTime dateTime && parameter is string parameterS + ? dateTime.ToString(parameterS) + : value; + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ExceptionToStringConverter.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ExceptionToStringConverter.cs index 780f803..b616024 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ExceptionToStringConverter.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ExceptionToStringConverter.cs @@ -1,45 +1,44 @@ using System.Globalization; using Avalonia.Data.Converters; -namespace FileTime.GuiApp.Converters +namespace FileTime.GuiApp.Converters; + +public class ExceptionToStringConverter : IValueConverter { - public class ExceptionToStringConverter : IValueConverter + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + if (value is not Exception e) return value; + + if (e is UnauthorizedAccessException) { - if (value is not Exception e) return value; - - if (e is UnauthorizedAccessException) - { - return e.Message; - } - else if (e.InnerException != null) - { - return TraverseInnerException(e); - } - - return FormatException(e); + return e.Message; + } + else if (e.InnerException != null) + { + return TraverseInnerException(e); } - private static string TraverseInnerException(Exception e) - { - string s = ""; - if (e.InnerException != null) s += TraverseInnerException(e.InnerException) + Environment.NewLine; - else return FormatException(e); + return FormatException(e); + } - s += "In: " + FormatException(e); + private static string TraverseInnerException(Exception e) + { + string s = ""; + if (e.InnerException != null) s += TraverseInnerException(e.InnerException) + Environment.NewLine; + else return FormatException(e); - return s; - } + s += "In: " + FormatException(e); - private static string FormatException(Exception e) - { - return $"{e.Message} ({e.GetType().FullName})"; - } + return s; + } - public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } + private static string FormatException(Exception e) + { + return $"{e.Message} ({e.GetType().FullName})"; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/FormatSizeConverter.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/FormatSizeConverter.cs index 30d57bc..282e126 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/FormatSizeConverter.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/FormatSizeConverter.cs @@ -1,47 +1,46 @@ using System.Globalization; using Avalonia.Data.Converters; -namespace FileTime.GuiApp.Converters +namespace FileTime.GuiApp.Converters; + +public class FormatSizeConverter : IValueConverter { - public class FormatSizeConverter : IValueConverter + private const long OneKiloByte = 1024; + private const long OneMegaByte = OneKiloByte * 1024; + private const long OneGigaByte = OneMegaByte * 1024; + private const long OneTerraByte = OneGigaByte * 1024; + + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { - private const long OneKiloByte = 1024; - private const long OneMegaByte = OneKiloByte * 1024; - private const long OneGigaByte = OneMegaByte * 1024; - private const long OneTerraByte = OneGigaByte * 1024; - - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + return (value, int.TryParse(parameter?.ToString(), out var prec)) switch { - return (value, int.TryParse(parameter?.ToString(), out var prec)) switch - { - (long size, true) => ToSizeString(size, prec), - (long size, false) => ToSizeString(size), - (null, _) => "...", - _ => value - }; - } + (long size, true) => ToSizeString(size, prec), + (long size, false) => ToSizeString(size), + (null, _) => "...", + _ => value + }; + } - public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + + public static string ToSizeString(long fileSize, int precision = 1) + { + var fileSizeD = (decimal)fileSize; + var (size, suffix) = fileSize switch { - throw new NotImplementedException(); - } + > OneTerraByte => (fileSizeD / OneTerraByte, "T"), + > OneGigaByte => (fileSizeD / OneGigaByte, "G"), + > OneMegaByte => (fileSizeD / OneMegaByte, "M"), + > OneKiloByte => (fileSizeD / OneKiloByte, "K"), + _ => (fileSizeD, "B") + }; - public static string ToSizeString(long fileSize, int precision = 1) - { - var fileSizeD = (decimal)fileSize; - var (size, suffix) = fileSize switch - { - > OneTerraByte => (fileSizeD / OneTerraByte, "T"), - > OneGigaByte => (fileSizeD / OneGigaByte, "G"), - > OneMegaByte => (fileSizeD / OneMegaByte, "M"), - > OneKiloByte => (fileSizeD / OneKiloByte, "K"), - _ => (fileSizeD, "B") - }; + var result = string.Format("{0:N" + precision + "}", size).Replace(',', '.'); - var result = string.Format("{0:N" + precision + "}", size).Replace(',', '.'); - - if (result.Contains('.')) result = result.TrimEnd('0').TrimEnd('.'); - return result + " " + suffix; - } + if (result.Contains('.')) result = result.TrimEnd('0').TrimEnd('.'); + return result + " " + suffix; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/GetFileExtensionConverter.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/GetFileExtensionConverter.cs index 6d55585..1c82ef9 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/GetFileExtensionConverter.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/GetFileExtensionConverter.cs @@ -3,22 +3,21 @@ using Avalonia.Data.Converters; using FileTime.App.Core.Services; using Microsoft.Extensions.DependencyInjection; -namespace FileTime.GuiApp.Converters +namespace FileTime.GuiApp.Converters; + +public class GetFileExtensionConverter : IValueConverter { - public class GetFileExtensionConverter : IValueConverter + private IItemNameConverterService? _itemNameConverterService; + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { - private IItemNameConverterService? _itemNameConverterService; - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - { - if (value is not string fullName) return value; - _itemNameConverterService ??= DI.ServiceProvider.GetRequiredService(); + if (value is not string fullName) return value; + _itemNameConverterService ??= DI.ServiceProvider.GetRequiredService(); - return _itemNameConverterService.GetFileExtension(fullName); - } + return _itemNameConverterService.GetFileExtension(fullName); + } - public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ItemViewModeToBrushConverter.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ItemViewModeToBrushConverter.cs index 29a8800..44f277c 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ItemViewModeToBrushConverter.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ItemViewModeToBrushConverter.cs @@ -3,39 +3,38 @@ using Avalonia.Data.Converters; using Avalonia.Media; using FileTime.App.Core.Models.Enums; -namespace FileTime.GuiApp.Converters +namespace FileTime.GuiApp.Converters; + +public class ItemViewModeToBrushConverter : IValueConverter { - public class ItemViewModeToBrushConverter : IValueConverter + public Brush? DefaultBrush { get; set; } + public Brush? AlternativeBrush { get; set; } + public Brush? SelectedBrush { get; set; } + public Brush? MarkedBrush { get; set; } + public Brush? MarkedSelectedBrush { get; set; } + public Brush? MarkedAlternativeBrush { get; set; } + + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { - public Brush? DefaultBrush { get; set; } - public Brush? AlternativeBrush { get; set; } - public Brush? SelectedBrush { get; set; } - public Brush? MarkedBrush { get; set; } - public Brush? MarkedSelectedBrush { get; set; } - public Brush? MarkedAlternativeBrush { get; set; } - - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + if (value is ItemViewMode viewMode) { - if (value is ItemViewMode viewMode) + return viewMode switch { - return viewMode switch - { - ItemViewMode.Default => DefaultBrush, - ItemViewMode.Alternative => AlternativeBrush, - ItemViewMode.Selected => SelectedBrush, - ItemViewMode.Marked => MarkedBrush, - ItemViewMode.MarkedSelected => MarkedSelectedBrush, - ItemViewMode.MarkedAlternative => MarkedAlternativeBrush, - _ => throw new NotImplementedException() - }; - } - - return value; + ItemViewMode.Default => DefaultBrush, + ItemViewMode.Alternative => AlternativeBrush, + ItemViewMode.Selected => SelectedBrush, + ItemViewMode.Marked => MarkedBrush, + ItemViewMode.MarkedSelected => MarkedSelectedBrush, + ItemViewMode.MarkedAlternative => MarkedAlternativeBrush, + _ => throw new NotImplementedException() + }; } - public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } + return value; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ItemViewModelIsAttributeTypeConverter.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ItemViewModelIsAttributeTypeConverter.cs index edadd74..62bc9f6 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ItemViewModelIsAttributeTypeConverter.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ItemViewModelIsAttributeTypeConverter.cs @@ -3,35 +3,34 @@ using Avalonia.Data.Converters; using FileTime.App.Core.Models.Enums; using FileTime.App.Core.ViewModels; -namespace FileTime.GuiApp.Converters +namespace FileTime.GuiApp.Converters; + +public class ItemViewModelIsAttributeTypeConverter : IValueConverter { - public class ItemViewModelIsAttributeTypeConverter : IValueConverter + public bool Invert { get; set; } + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { - public bool Invert { get; set; } - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - { - var attributeType = GetAttributeType(value); - if (parameter == null) return attributeType; - var result = parameter is ItemAttributeType targetAttribute && attributeType == targetAttribute; - if (Invert && parameter is ItemAttributeType) result = !result; - return result; - } + var attributeType = GetAttributeType(value); + if (parameter == null) return attributeType; + var result = parameter is ItemAttributeType targetAttribute && attributeType == targetAttribute; + if (Invert && parameter is ItemAttributeType) result = !result; + return result; + } - private static ItemAttributeType? GetAttributeType(object? value) + private static ItemAttributeType? GetAttributeType(object? value) + { + return value switch { - return value switch - { - IFileViewModel => ItemAttributeType.File, - IContainerSizeContainerViewModel => ItemAttributeType.SizeContainer, - IElementViewModel => ItemAttributeType.Element, - IContainerViewModel => ItemAttributeType.Container, - _ => null - }; - } + IFileViewModel => ItemAttributeType.File, + IContainerSizeContainerViewModel => ItemAttributeType.SizeContainer, + IElementViewModel => ItemAttributeType.Element, + IContainerViewModel => ItemAttributeType.Container, + _ => null + }; + } - public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/NamePartShrinkerConverter.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/NamePartShrinkerConverter.cs index 596cb3c..399a159 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/NamePartShrinkerConverter.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/NamePartShrinkerConverter.cs @@ -4,112 +4,111 @@ using Avalonia.Media; using FileTime.App.Core.Models; using FileTime.GuiApp.ViewModels; -namespace FileTime.GuiApp.Converters +namespace FileTime.GuiApp.Converters; + +public class NamePartShrinkerConverter : IMultiValueConverter { - public class NamePartShrinkerConverter : IMultiValueConverter + private const int PixelPerChar = 8; + public object? Convert(IList values, Type targetType, object? parameter, CultureInfo culture) { - private const int PixelPerChar = 8; - public object? Convert(IList values, Type targetType, object? parameter, CultureInfo culture) + if (values.Count > 0 && values[0] is IList nameParts) { - if (values.Count > 0 && values[0] is IList nameParts) + var attributeWidth = values[2] is bool b && b ? 340 : 0; + var newNameParts = nameParts; + if (values.Count > 1 && values[1] is double width && width > 0) { - var attributeWidth = values[2] is bool b && b ? 340 : 0; - var newNameParts = nameParts; - if (values.Count > 1 && values[1] is double width && width > 0) - { - newNameParts = GetNamePartsForWidth(nameParts, width - attributeWidth); - } - - return newNameParts.Select(p => new ItemNamePartViewModel(p.Text, p.IsSpecial ? TextDecorations.Underline : null)).ToList(); + newNameParts = GetNamePartsForWidth(nameParts, width - attributeWidth); } - return null; + + return newNameParts.Select(p => new ItemNamePartViewModel(p.Text, p.IsSpecial ? TextDecorations.Underline : null)).ToList(); + } + return null; + } + + private static List GetNamePartsForWidth(IList nameParts, double maxWidth) + { + //Best case, we are in the range + var textLength = nameParts.Select(p => p.Text.Length).Sum(); + if (textLength * PixelPerChar <= maxWidth) + { + return nameParts.ToList(); } - private static List GetNamePartsForWidth(IList nameParts, double maxWidth) + //Trying at least with the special parts + var newNameParts = new ItemNamePart?[nameParts.Count]; + for (var i = 0; i < nameParts.Count; i++) { - //Best case, we are in the range - var textLength = nameParts.Select(p => p.Text.Length).Sum(); - if (textLength * PixelPerChar <= maxWidth) + if (nameParts[i].IsSpecial) { - return nameParts.ToList(); + newNameParts[i] = nameParts[i]; } - - //Trying at least with the special parts - var newNameParts = new ItemNamePart?[nameParts.Count]; - for (var i = 0; i < nameParts.Count; i++) - { - if (nameParts[i].IsSpecial) - { - newNameParts[i] = nameParts[i]; - } - } - - return GetNamePartsForWidthOptimistic(nameParts, newNameParts, maxWidth); } - private static List GetNamePartsForWidthOptimistic(IList nameParts, ItemNamePart?[] newNameParts, double maxWidth) + return GetNamePartsForWidthOptimistic(nameParts, newNameParts, maxWidth); + } + + private static List GetNamePartsForWidthOptimistic(IList nameParts, ItemNamePart?[] newNameParts, double maxWidth) + { + var trimmedIndexes = new List(); + for (var i = 0; i < newNameParts.Length; i++) { - var trimmedIndexes = new List(); - for (var i = 0; i < newNameParts.Length; i++) + if (newNameParts[i] == null) { - if (newNameParts[i] == null) - { - trimmedIndexes.Add(i); - newNameParts[i] = new ItemNamePart("..."); - } + trimmedIndexes.Add(i); + newNameParts[i] = new ItemNamePart("..."); } - - var textLength = newNameParts.Select(p => p?.Text.Length ?? 0).Sum(); - if (textLength * PixelPerChar > maxWidth) - { - return GetNamePartsForWidthPessimistic(nameParts, maxWidth); - } - - foreach (var trimmedIndex in trimmedIndexes) - { - var baseTextLength = newNameParts.Select((p, i) => i == trimmedIndex ? 0 : (p?.Text.Length ?? 0)).Sum(); - var proposedText = nameParts[trimmedIndex].Text; - var trimmed = false; - while ((baseTextLength + proposedText.Length + (trimmed ? 3 : 0)) * PixelPerChar > maxWidth) - { - proposedText = proposedText[0..^1]; - trimmed = true; - } - newNameParts[trimmedIndex] = new ItemNamePart(proposedText + (trimmed ? "..." : "")); - if (trimmed) break; - } - - return newNameParts.Where(f => f is not null).ToList()!; } - private static List GetNamePartsForWidthPessimistic(IList nameParts, double maxWidth) + var textLength = newNameParts.Select(p => p?.Text.Length ?? 0).Sum(); + if (textLength * PixelPerChar > maxWidth) { - var newNameParts = new List(nameParts); - foreach (var namePart in nameParts) - { - var baseTextLength = newNameParts.Select(p => p.Text.Length).Sum(); - var proposedText = namePart.Text; - var trimmed = false; - - while ((baseTextLength + 3) * PixelPerChar > maxWidth && proposedText != "") - { - proposedText = proposedText[0..^1]; - trimmed = true; - } - - if (!string.IsNullOrWhiteSpace(proposedText)) newNameParts.Add(new ItemNamePart(proposedText, namePart.IsSpecial)); - if (trimmed) break; - } - if (newNameParts.Last().IsSpecial) - { - newNameParts.Add(new ItemNamePart("...")); - } - else - { - var last = newNameParts.Last(); - last.Text += "..."; - } - return newNameParts; + return GetNamePartsForWidthPessimistic(nameParts, maxWidth); } + + foreach (var trimmedIndex in trimmedIndexes) + { + var baseTextLength = newNameParts.Select((p, i) => i == trimmedIndex ? 0 : (p?.Text.Length ?? 0)).Sum(); + var proposedText = nameParts[trimmedIndex].Text; + var trimmed = false; + while ((baseTextLength + proposedText.Length + (trimmed ? 3 : 0)) * PixelPerChar > maxWidth) + { + proposedText = proposedText[0..^1]; + trimmed = true; + } + newNameParts[trimmedIndex] = new ItemNamePart(proposedText + (trimmed ? "..." : "")); + if (trimmed) break; + } + + return newNameParts.Where(f => f is not null).ToList()!; + } + + private static List GetNamePartsForWidthPessimistic(IList nameParts, double maxWidth) + { + var newNameParts = new List(nameParts); + foreach (var namePart in nameParts) + { + var baseTextLength = newNameParts.Select(p => p.Text.Length).Sum(); + var proposedText = namePart.Text; + var trimmed = false; + + while ((baseTextLength + 3) * PixelPerChar > maxWidth && proposedText != "") + { + proposedText = proposedText[0..^1]; + trimmed = true; + } + + if (!string.IsNullOrWhiteSpace(proposedText)) newNameParts.Add(new ItemNamePart(proposedText, namePart.IsSpecial)); + if (trimmed) break; + } + if (newNameParts.Last().IsSpecial) + { + newNameParts.Add(new ItemNamePart("...")); + } + else + { + var last = newNameParts.Last(); + last.Text += "..."; + } + return newNameParts; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/SplitStringConverter.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/SplitStringConverter.cs index debe186..5c360b7 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/SplitStringConverter.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/SplitStringConverter.cs @@ -1,27 +1,26 @@ using System.Globalization; using Avalonia.Data.Converters; -namespace FileTime.GuiApp.Converters +namespace FileTime.GuiApp.Converters; + +public class SplitStringConverter : IValueConverter { - public class SplitStringConverter : IValueConverter + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + if (value is string path && parameter is string separator) { - if (value is string path && parameter is string separator) - { - return path.Split(separator); - } - else if (value is string path2 && parameter is char separator2) - { - return path2.Split(separator2); - } - - return value; + return path.Split(separator); + } + else if (value is string path2 && parameter is char separator2) + { + return path2.Split(separator2); } - public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } + return value; + } + + public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/DependencyInjection.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/DependencyInjection.cs index 8d18446..e257f75 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/DependencyInjection.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/DependencyInjection.cs @@ -1,7 +1,6 @@ -namespace FileTime.GuiApp +namespace FileTime.GuiApp; + +public static class DI { - public static class DI - { - public static IServiceProvider ServiceProvider { get; set; } = null!; - } + public static IServiceProvider ServiceProvider { get; set; } = null!; } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Extensions/KeyConfigExtensions.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Extensions/KeyConfigExtensions.cs index 0760077..2d726f7 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Extensions/KeyConfigExtensions.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Extensions/KeyConfigExtensions.cs @@ -1,10 +1,9 @@ using FileTime.GuiApp.Configuration; -namespace FileTime.GuiApp.Extensions +namespace FileTime.GuiApp.Extensions; + +public static class KeyConfigExtensions { - public static class KeyConfigExtensions - { - public static bool AreKeysEqual(this IReadOnlyList collection1, IReadOnlyList collection2) + public static bool AreKeysEqual(this IReadOnlyList collection1, IReadOnlyList collection2) => collection1.Count == collection2.Count && collection1.Zip(collection2).All(t => t.First.AreEquals(t.Second)); - } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/FileTime.GuiApp.csproj b/src/GuiApp/Avalonia/FileTime.GuiApp/FileTime.GuiApp.csproj index 7a5eee8..c0c8c88 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/FileTime.GuiApp.csproj +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/FileTime.GuiApp.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Logging/ToastMessageSink.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Logging/ToastMessageSink.cs index e880018..a8d7b70 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Logging/ToastMessageSink.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Logging/ToastMessageSink.cs @@ -1,24 +1,23 @@ using Serilog.Core; using Serilog.Events; -namespace FileTime.GuiApp.Logging +namespace FileTime.GuiApp.Logging; + +public class ToastMessageSink : ILogEventSink { - public class ToastMessageSink : ILogEventSink + //private readonly IDialogService dialogService; + + public ToastMessageSink(/*IDialogService dialogService*/) { - //private readonly IDialogService dialogService; - - public ToastMessageSink(/*IDialogService dialogService*/) - { - //this.dialogService = dialogService; - } - - public void Emit(LogEvent logEvent) - { - /*if (logEvent.Level >= LogEventLevel.Error) - { - var message = logEvent.RenderMessage(); - dialogService.ShowToastMessage(message); - }*/ - } + //this.dialogService = dialogService; } -} + + public void Emit(LogEvent logEvent) + { + /*if (logEvent.Level >= LogEventLevel.Error) + { + var message = logEvent.RenderMessage(); + dialogService.ShowToastMessage(message); + }*/ + } +} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Models/InputElementWrapper.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Models/InputElementWrapper.cs index 197f4ac..e346d7e 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Models/InputElementWrapper.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Models/InputElementWrapper.cs @@ -1,20 +1,19 @@ -namespace FileTime.GuiApp.Models +namespace FileTime.GuiApp.Models; + +public class InputElementWrapper { - public class InputElementWrapper + /*public InputElement InputElement { get; } + + public string Value { get; set; } + + public object? Option { get; set; } + + public char? PasswordChar { get; set; } + + public InputElementWrapper(InputElement inputElement, string? defaultValue = null) { - /*public InputElement InputElement { get; } - - public string Value { get; set; } - - public object? Option { get; set; } - - public char? PasswordChar { get; set; } - - public InputElementWrapper(InputElement inputElement, string? defaultValue = null) - { - InputElement = inputElement; - Value = defaultValue ?? ""; - PasswordChar = inputElement.InputType == InputType.Password ? '*' : null; - }*/ - } -} + InputElement = inputElement; + Value = defaultValue ?? ""; + PasswordChar = inputElement.InputType == InputType.Password ? '*' : null; + }*/ +} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/AvaloniaRxSchedulerService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/AvaloniaRxSchedulerService.cs index 1f8032c..c7b9d10 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/AvaloniaRxSchedulerService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/AvaloniaRxSchedulerService.cs @@ -2,12 +2,11 @@ using System.Reactive.Concurrency; using FileTime.App.Core.Services; using ReactiveUI; -namespace FileTime.GuiApp.Services -{ - public class AvaloniaRxSchedulerService : IRxSchedulerService - { - public IScheduler GetUIScheduler() => RxApp.MainThreadScheduler; +namespace FileTime.GuiApp.Services; - public IScheduler GetWorkerScheduler() => RxApp.TaskpoolScheduler; - } +public class AvaloniaRxSchedulerService : IRxSchedulerService +{ + public IScheduler GetUIScheduler() => RxApp.MainThreadScheduler; + + public IScheduler GetWorkerScheduler() => RxApp.TaskpoolScheduler; } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs index 1ebc34b..9a97079 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/DefaultModeKeyInputHandler.cs @@ -10,142 +10,141 @@ using FileTime.GuiApp.Models; using FileTime.GuiApp.ViewModels; using Microsoft.Extensions.Logging; -namespace FileTime.GuiApp.Services +namespace FileTime.GuiApp.Services; + +public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler { - public class DefaultModeKeyInputHandler : IDefaultModeKeyInputHandler + private readonly IGuiAppState _appState; + private readonly IKeyboardConfigurationService _keyboardConfigurationService; + private readonly List _keysToSkip = new(); + private ITabViewModel? _selectedTab; + private IContainer? _currentLocation; + private readonly ILogger _logger; + private readonly ICommandHandlerService _commandHandlerService; + + public DefaultModeKeyInputHandler( + IGuiAppState appState, + IKeyboardConfigurationService keyboardConfigurationService, + ILogger logger, + ICommandHandlerService commandHandlerService) { - private readonly IGuiAppState _appState; - private readonly IKeyboardConfigurationService _keyboardConfigurationService; - private readonly List _keysToSkip = new(); - private ITabViewModel? _selectedTab; - private IContainer? _currentLocation; - private readonly ILogger _logger; - private readonly ICommandHandlerService _commandHandlerService; + _appState = appState; + _keyboardConfigurationService = keyboardConfigurationService; + _logger = logger; + _commandHandlerService = commandHandlerService; - public DefaultModeKeyInputHandler( - IGuiAppState appState, - IKeyboardConfigurationService keyboardConfigurationService, - ILogger logger, - ICommandHandlerService commandHandlerService) + _appState.SelectedTab.Subscribe(t => _selectedTab = t); + _appState.SelectedTab.Select(t => t == null ? Observable.Return(null) : t.CurrentLocation!).Switch().Subscribe(l => _currentLocation = l); + + _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Up) }); + _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Down) }); + _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Tab) }); + _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.PageDown) }); + _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.PageUp) }); + _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.F4, alt: true) }); + _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.LWin) }); + _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.RWin) }); + } + + public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action setHandled) + { + var keyWithModifiers = new KeyConfig(key, shift: specialKeysStatus.IsShiftPressed, alt: specialKeysStatus.IsAltPressed, ctrl: specialKeysStatus.IsCtrlPressed); + _appState.PreviousKeys.Add(keyWithModifiers); + + var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys)); + selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys)); + + if (key == Key.Escape) { - _appState = appState; - _keyboardConfigurationService = keyboardConfigurationService; - _logger = logger; - _commandHandlerService = commandHandlerService; - - _appState.SelectedTab.Subscribe(t => _selectedTab = t); - _appState.SelectedTab.Select(t => t == null ? Observable.Return(null) : t.CurrentLocation!).Switch().Subscribe(l => _currentLocation = l); - - _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Up) }); - _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Down) }); - _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.Tab) }); - _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.PageDown) }); - _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.PageUp) }); - _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.F4, alt: true) }); - _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.LWin) }); - _keysToSkip.Add(new KeyConfig[] { new KeyConfig(Key.RWin) }); - } - - public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action setHandled) - { - var keyWithModifiers = new KeyConfig(key, shift: specialKeysStatus.IsShiftPressed, alt: specialKeysStatus.IsAltPressed, ctrl: specialKeysStatus.IsCtrlPressed); - _appState.PreviousKeys.Add(keyWithModifiers); - - var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys)); - selectedCommandBinding ??= _keyboardConfigurationService.CommandBindings.FirstOrDefault(c => c.Keys.AreKeysEqual(_appState.PreviousKeys)); - - if (key == Key.Escape) + var doGeneralReset = false; + if (_appState.PreviousKeys.Count > 1 || _appState.IsAllShortcutVisible || _appState.MessageBoxText != null) { - var doGeneralReset = false; - if (_appState.PreviousKeys.Count > 1 || _appState.IsAllShortcutVisible || _appState.MessageBoxText != null) - { - doGeneralReset = true; - } - /*else if (_currentLocation.Container.CanHandleEscape) - { - var escapeResult = await _currentLocation.Container.HandleEscape(); - if (escapeResult.NavigateTo != null) - { - setHandled(true); - _appState.PreviousKeys.Clear(); - await _appState.SelectedTab.OpenContainer(escapeResult.NavigateTo); - } - else - { - if (escapeResult.Handled) - { - _appState.PreviousKeys.Clear(); - } - else - { - doGeneralReset = true; - } - } - }*/ - - if (doGeneralReset) + doGeneralReset = true; + } + /*else if (_currentLocation.Container.CanHandleEscape) + { + var escapeResult = await _currentLocation.Container.HandleEscape(); + if (escapeResult.NavigateTo != null) { setHandled(true); - _appState.IsAllShortcutVisible = false; - _appState.MessageBoxText = null; - _appState.PreviousKeys.Clear(); - _appState.PossibleCommands = new(); - } - } - else if (key == Key.Enter - && _appState.MessageBoxText != null) - { - _appState.PreviousKeys.Clear(); - //_dialogService.ProcessMessageBox(); - setHandled(true); - } - else if (selectedCommandBinding != null) - { - setHandled(true); - _appState.PreviousKeys.Clear(); - _appState.PossibleCommands = new(); - await CallCommandAsync(selectedCommandBinding.Command); - } - else if (_keysToSkip.Any(k => k.AreKeysEqual(_appState.PreviousKeys))) - { - _appState.PreviousKeys.Clear(); - _appState.PossibleCommands = new(); - return; - } - else if (_appState.PreviousKeys.Count == 2) - { - setHandled(true); - _appState.NoCommandFound = true; - _appState.PreviousKeys.Clear(); - _appState.PossibleCommands = new(); - } - else - { - setHandled(true); - var possibleCommands = _keyboardConfigurationService.AllShortcut.Where(c => c.Keys[0].AreEquals(keyWithModifiers)).ToList(); - - if (possibleCommands.Count == 0) - { - _appState.NoCommandFound = true; _appState.PreviousKeys.Clear(); + await _appState.SelectedTab.OpenContainer(escapeResult.NavigateTo); } else { - _appState.PossibleCommands = possibleCommands; + if (escapeResult.Handled) + { + _appState.PreviousKeys.Clear(); + } + else + { + doGeneralReset = true; + } } + }*/ + + if (doGeneralReset) + { + setHandled(true); + _appState.IsAllShortcutVisible = false; + _appState.MessageBoxText = null; + _appState.PreviousKeys.Clear(); + _appState.PossibleCommands = new(); } } - - private async Task CallCommandAsync(Commands command) + else if (key == Key.Enter + && _appState.MessageBoxText != null) { - try + _appState.PreviousKeys.Clear(); + //_dialogService.ProcessMessageBox(); + setHandled(true); + } + else if (selectedCommandBinding != null) + { + setHandled(true); + _appState.PreviousKeys.Clear(); + _appState.PossibleCommands = new(); + await CallCommandAsync(selectedCommandBinding.Command); + } + else if (_keysToSkip.Any(k => k.AreKeysEqual(_appState.PreviousKeys))) + { + _appState.PreviousKeys.Clear(); + _appState.PossibleCommands = new(); + return; + } + else if (_appState.PreviousKeys.Count == 2) + { + setHandled(true); + _appState.NoCommandFound = true; + _appState.PreviousKeys.Clear(); + _appState.PossibleCommands = new(); + } + else + { + setHandled(true); + var possibleCommands = _keyboardConfigurationService.AllShortcut.Where(c => c.Keys[0].AreEquals(keyWithModifiers)).ToList(); + + if (possibleCommands.Count == 0) { - await _commandHandlerService.HandleCommandAsync(command); + _appState.NoCommandFound = true; + _appState.PreviousKeys.Clear(); } - catch (Exception e) + else { - _logger.LogError(e, "Unknown error while running command. {Command} {Error}", command, e); + _appState.PossibleCommands = possibleCommands; } } } + + private async Task CallCommandAsync(Commands command) + { + try + { + await _commandHandlerService.HandleCommandAsync(command); + } + catch (Exception e) + { + _logger.LogError(e, "Unknown error while running command. {Command} {Error}", command, e); + } + } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyInputHandlerService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyInputHandlerService.cs index ceb187b..3250918 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyInputHandlerService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyInputHandlerService.cs @@ -4,53 +4,52 @@ using FileTime.GuiApp.Configuration; using FileTime.GuiApp.Models; using FileTime.GuiApp.ViewModels; -namespace FileTime.GuiApp.Services -{ - public class KeyInputHandlerService : IKeyInputHandlerService - { - private readonly IGuiAppState _appState; - private readonly IDefaultModeKeyInputHandler _defaultModeKeyInputHandler; - private readonly IRapidTravelModeKeyInputHandler _rapidTravelModeKeyInputHandler; +namespace FileTime.GuiApp.Services; - public KeyInputHandlerService( - IGuiAppState appState, - IDefaultModeKeyInputHandler defaultModeKeyInputHandler, - IRapidTravelModeKeyInputHandler rapidTravelModeKeyInputHandler - ) +public class KeyInputHandlerService : IKeyInputHandlerService +{ + private readonly IGuiAppState _appState; + private readonly IDefaultModeKeyInputHandler _defaultModeKeyInputHandler; + private readonly IRapidTravelModeKeyInputHandler _rapidTravelModeKeyInputHandler; + + public KeyInputHandlerService( + IGuiAppState appState, + IDefaultModeKeyInputHandler defaultModeKeyInputHandler, + IRapidTravelModeKeyInputHandler rapidTravelModeKeyInputHandler + ) + { + _appState = appState; + _defaultModeKeyInputHandler = defaultModeKeyInputHandler; + _rapidTravelModeKeyInputHandler = rapidTravelModeKeyInputHandler; + } + + public async Task ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action setHandled) + { + if (key == Key.LeftAlt + || key == Key.RightAlt + || key == Key.LeftShift + || key == Key.RightShift + || key == Key.LeftCtrl + || key == Key.RightCtrl) { - _appState = appState; - _defaultModeKeyInputHandler = defaultModeKeyInputHandler; - _rapidTravelModeKeyInputHandler = rapidTravelModeKeyInputHandler; + return; } - public async Task ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action setHandled) + //_appState.NoCommandFound = false; + + var isAltPressed = (keyModifiers & KeyModifiers.Alt) == KeyModifiers.Alt; + var isShiftPressed = (keyModifiers & KeyModifiers.Shift) == KeyModifiers.Shift; + var isCtrlPressed = (keyModifiers & KeyModifiers.Control) == KeyModifiers.Control; + + var specialKeyStatus = new SpecialKeysStatus(isAltPressed, isShiftPressed, isCtrlPressed); + + if (_appState.ViewMode == ViewMode.Default) { - if (key == Key.LeftAlt - || key == Key.RightAlt - || key == Key.LeftShift - || key == Key.RightShift - || key == Key.LeftCtrl - || key == Key.RightCtrl) - { - return; - } - - //_appState.NoCommandFound = false; - - var isAltPressed = (keyModifiers & KeyModifiers.Alt) == KeyModifiers.Alt; - var isShiftPressed = (keyModifiers & KeyModifiers.Shift) == KeyModifiers.Shift; - var isCtrlPressed = (keyModifiers & KeyModifiers.Control) == KeyModifiers.Control; - - var specialKeyStatus = new SpecialKeysStatus(isAltPressed, isShiftPressed, isCtrlPressed); - - if (_appState.ViewMode == ViewMode.Default) - { - await _defaultModeKeyInputHandler.HandleInputKey(key, specialKeyStatus, setHandled); - } - else - { - await _rapidTravelModeKeyInputHandler.HandleInputKey(key, specialKeyStatus, setHandled); - } + await _defaultModeKeyInputHandler.HandleInputKey(key, specialKeyStatus, setHandled); + } + else + { + await _rapidTravelModeKeyInputHandler.HandleInputKey(key, specialKeyStatus, setHandled); } } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyboardConfigurationService.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyboardConfigurationService.cs index 6429ae4..d5238a5 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyboardConfigurationService.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/KeyboardConfigurationService.cs @@ -2,60 +2,59 @@ using FileTime.App.Core.Command; using FileTime.GuiApp.Configuration; using Microsoft.Extensions.Options; -namespace FileTime.GuiApp.Services +namespace FileTime.GuiApp.Services; + +public class KeyboardConfigurationService : IKeyboardConfigurationService { - public class KeyboardConfigurationService : IKeyboardConfigurationService + public IReadOnlyList CommandBindings { get; } + public IReadOnlyList UniversalCommandBindings { get; } + public IReadOnlyList AllShortcut { get; } + + public KeyboardConfigurationService(IOptions keyBindingConfiguration) { - public IReadOnlyList CommandBindings { get; } - public IReadOnlyList UniversalCommandBindings { get; } - public IReadOnlyList AllShortcut { get; } + var commandBindings = new List(); + var universalCommandBindings = new List(); + IEnumerable keyBindings = keyBindingConfiguration.Value.KeyBindings; - public KeyboardConfigurationService(IOptions keyBindingConfiguration) + if (keyBindingConfiguration.Value.UseDefaultBindings) { - var commandBindings = new List(); - var universalCommandBindings = new List(); - IEnumerable keyBindings = keyBindingConfiguration.Value.KeyBindings; - - if (keyBindingConfiguration.Value.UseDefaultBindings) - { - keyBindings = keyBindings.Concat(keyBindingConfiguration.Value.DefaultKeyBindings); - } - - foreach (var keyBinding in keyBindings) - { - if (keyBinding.Command == Commands.None) - { - throw new FormatException($"No command is set in keybinding for keys '{keyBinding.KeysDisplayText}'"); - } - else if (keyBinding.Keys.Count == 0) - { - throw new FormatException($"No keys set in keybinding for command '{keyBinding.Command}'."); - } - - if (IsUniversal(keyBinding)) - { - universalCommandBindings.Add(keyBinding); - } - else - { - commandBindings.Add(keyBinding); - } - } - - CommandBindings = commandBindings.AsReadOnly(); - UniversalCommandBindings = universalCommandBindings.AsReadOnly(); - AllShortcut = new List(CommandBindings.Concat(UniversalCommandBindings)).AsReadOnly(); + keyBindings = keyBindings.Concat(keyBindingConfiguration.Value.DefaultKeyBindings); } - private static bool IsUniversal(CommandBindingConfiguration keyMapping) + foreach (var keyBinding in keyBindings) { - return keyMapping.Command == Commands.GoUp - || keyMapping.Command == Commands.Open - || keyMapping.Command == Commands.OpenOrRun - || keyMapping.Command == Commands.MoveCursorUp - || keyMapping.Command == Commands.MoveCursorDown - || keyMapping.Command == Commands.MoveCursorUpPage - || keyMapping.Command == Commands.MoveCursorDownPage; + if (keyBinding.Command == Commands.None) + { + throw new FormatException($"No command is set in keybinding for keys '{keyBinding.KeysDisplayText}'"); + } + else if (keyBinding.Keys.Count == 0) + { + throw new FormatException($"No keys set in keybinding for command '{keyBinding.Command}'."); + } + + if (IsUniversal(keyBinding)) + { + universalCommandBindings.Add(keyBinding); + } + else + { + commandBindings.Add(keyBinding); + } } + + CommandBindings = commandBindings.AsReadOnly(); + UniversalCommandBindings = universalCommandBindings.AsReadOnly(); + AllShortcut = new List(CommandBindings.Concat(UniversalCommandBindings)).AsReadOnly(); + } + + private static bool IsUniversal(CommandBindingConfiguration keyMapping) + { + return keyMapping.Command == Commands.GoUp + || keyMapping.Command == Commands.Open + || keyMapping.Command == Commands.OpenOrRun + || keyMapping.Command == Commands.MoveCursorUp + || keyMapping.Command == Commands.MoveCursorDown + || keyMapping.Command == Commands.MoveCursorUpPage + || keyMapping.Command == Commands.MoveCursorDownPage; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs index f7a7f05..7848e95 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Services/RapidTravelModeKeyInputHandler.cs @@ -1,88 +1,87 @@ using Avalonia.Input; using FileTime.GuiApp.Models; -namespace FileTime.GuiApp.Services -{ - public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler - { - public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action setHandled) - { - /*var keyString = key.ToString(); - var updateRapidTravelFilter = false; +namespace FileTime.GuiApp.Services; - if (key == Key.Escape) +public class RapidTravelModeKeyInputHandler : IRapidTravelModeKeyInputHandler +{ + public async Task HandleInputKey(Key key, SpecialKeysStatus specialKeysStatus, Action setHandled) + { + /*var keyString = key.ToString(); + var updateRapidTravelFilter = false; + + if (key == Key.Escape) + { + setHandled(true); + if (_appState.IsAllShortcutVisible) { - setHandled(true); - if (_appState.IsAllShortcutVisible) - { - _appState.IsAllShortcutVisible = false; - } - else if (_appState.MessageBoxText != null) - { - _appState.MessageBoxText = null; - } - else - { - await _appState.ExitRapidTravelMode(); - } + _appState.IsAllShortcutVisible = false; } - else if (key == Key.Back) + else if (_appState.MessageBoxText != null) { - if (_appState.RapidTravelText.Length > 0) - { - setHandled(true); - _appState.RapidTravelText = _appState.RapidTravelText.Substring(0, _appState.RapidTravelText.Length - 1); - updateRapidTravelFilter = true; - } - } - else if (keyString.Length == 1) - { - setHandled(true); - _appState.RapidTravelText += keyString.ToLower(); - updateRapidTravelFilter = true; + _appState.MessageBoxText = null; } else { - var currentKeyAsList = new List() { new KeyConfig(key) }; - var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => AreKeysEqual(c.Keys, currentKeyAsList)); - if (selectedCommandBinding != null) - { - setHandled(true); - await CallCommandAsync(selectedCommandBinding.Command); - } + await _appState.ExitRapidTravelMode(); } - - if (updateRapidTravelFilter) - { - var currentLocation = await _appState.SelectedTab.CurrentLocation.Container.WithoutVirtualContainer(MainPageViewModel.RAPIDTRAVEL); - var newLocation = new VirtualContainer( - currentLocation, - new List, IEnumerable>>() - { - container => container.Where(c => c.Name.ToLower().Contains(_appState.RapidTravelText)) - }, - new List, IEnumerable>>() - { - element => element.Where(e => e.Name.ToLower().Contains(_appState.RapidTravelText)) - }, - virtualContainerName: MainPageViewModel.RAPIDTRAVEL - ); - - await newLocation.Init(); - - await _appState.SelectedTab.OpenContainer(newLocation); - - var selectedItemName = _appState.SelectedTab.SelectedItem?.Item.Name; - var currentLocationItems = await _appState.SelectedTab.CurrentLocation.GetItems(); - if (currentLocationItems.FirstOrDefault(i => string.Equals(i.Item.Name, _appState.RapidTravelText, StringComparison.OrdinalIgnoreCase)) is IItemViewModel matchItem) - { - await _appState.SelectedTab.SetCurrentSelectedItem(matchItem.Item); - } - else if (!currentLocationItems.Select(i => i.Item.Name).Any(n => n == selectedItemName)) - { - await _appState.SelectedTab.MoveCursorToFirst(); - } - }*/ } + else if (key == Key.Back) + { + if (_appState.RapidTravelText.Length > 0) + { + setHandled(true); + _appState.RapidTravelText = _appState.RapidTravelText.Substring(0, _appState.RapidTravelText.Length - 1); + updateRapidTravelFilter = true; + } + } + else if (keyString.Length == 1) + { + setHandled(true); + _appState.RapidTravelText += keyString.ToLower(); + updateRapidTravelFilter = true; + } + else + { + var currentKeyAsList = new List() { new KeyConfig(key) }; + var selectedCommandBinding = _keyboardConfigurationService.UniversalCommandBindings.FirstOrDefault(c => AreKeysEqual(c.Keys, currentKeyAsList)); + if (selectedCommandBinding != null) + { + setHandled(true); + await CallCommandAsync(selectedCommandBinding.Command); + } + } + + if (updateRapidTravelFilter) + { + var currentLocation = await _appState.SelectedTab.CurrentLocation.Container.WithoutVirtualContainer(MainPageViewModel.RAPIDTRAVEL); + var newLocation = new VirtualContainer( + currentLocation, + new List, IEnumerable>>() + { + container => container.Where(c => c.Name.ToLower().Contains(_appState.RapidTravelText)) + }, + new List, IEnumerable>>() + { + element => element.Where(e => e.Name.ToLower().Contains(_appState.RapidTravelText)) + }, + virtualContainerName: MainPageViewModel.RAPIDTRAVEL + ); + + await newLocation.Init(); + + await _appState.SelectedTab.OpenContainer(newLocation); + + var selectedItemName = _appState.SelectedTab.SelectedItem?.Item.Name; + var currentLocationItems = await _appState.SelectedTab.CurrentLocation.GetItems(); + if (currentLocationItems.FirstOrDefault(i => string.Equals(i.Item.Name, _appState.RapidTravelText, StringComparison.OrdinalIgnoreCase)) is IItemViewModel matchItem) + { + await _appState.SelectedTab.SetCurrentSelectedItem(matchItem.Item); + } + else if (!currentLocationItems.Select(i => i.Item.Name).Any(n => n == selectedItemName)) + { + await _appState.SelectedTab.MoveCursorToFirst(); + } + }*/ } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/IMainWindowViewModelBase.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/IMainWindowViewModelBase.cs index 386e533..a25a4a3 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/IMainWindowViewModelBase.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/IMainWindowViewModelBase.cs @@ -1,7 +1,6 @@ -namespace FileTime.GuiApp.ViewModels +namespace FileTime.GuiApp.ViewModels; + +public interface IMainWindowViewModelBase { - public interface IMainWindowViewModelBase - { - bool Loading { get; } - } + bool Loading { get; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/ItemNamePartViewModel.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/ItemNamePartViewModel.cs index f3ce2c0..7d60e04 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/ItemNamePartViewModel.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/ItemNamePartViewModel.cs @@ -1,16 +1,15 @@ using Avalonia.Media; -namespace FileTime.GuiApp.ViewModels -{ - public class ItemNamePartViewModel - { - public string Text { get; set; } - public TextDecorationCollection? TextDecorations { get; set; } +namespace FileTime.GuiApp.ViewModels; - public ItemNamePartViewModel(string text, TextDecorationCollection? textDecorations) - { - Text = text; - TextDecorations = textDecorations; - } +public class ItemNamePartViewModel +{ + public string Text { get; set; } + public TextDecorationCollection? TextDecorations { get; set; } + + public ItemNamePartViewModel(string text, TextDecorationCollection? textDecorations) + { + Text = text; + TextDecorations = textDecorations; } } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowLoadingViewModel.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowLoadingViewModel.cs index 576d851..82aa0cf 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowLoadingViewModel.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowLoadingViewModel.cs @@ -1,7 +1,6 @@ -namespace FileTime.GuiApp.ViewModels +namespace FileTime.GuiApp.ViewModels; + +public class MainWindowLoadingViewModel : IMainWindowViewModelBase { - public class MainWindowLoadingViewModel : IMainWindowViewModelBase - { - public bool Loading => true; - } + public bool Loading => true; } \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowViewModel.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowViewModel.cs index fb55618..3ceb0ed 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowViewModel.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/ViewModels/MainWindowViewModel.cs @@ -11,49 +11,48 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using MvvmGen; -namespace FileTime.GuiApp.ViewModels +namespace FileTime.GuiApp.ViewModels; + +[ViewModel] +[Inject(typeof(IAppState), "_appState")] +[Inject(typeof(ILocalContentProvider), "_localContentProvider")] +[Inject(typeof(IServiceProvider), PropertyName = "_serviceProvider")] +[Inject(typeof(ILogger), PropertyName = "_logger")] +[Inject(typeof(IKeyInputHandlerService), PropertyName = "_keyInputHandlerService")] +public partial class MainWindowViewModel : IMainWindowViewModelBase { - [ViewModel] - [Inject(typeof(IAppState), "_appState")] - [Inject(typeof(ILocalContentProvider), "_localContentProvider")] - [Inject(typeof(IServiceProvider), PropertyName = "_serviceProvider")] - [Inject(typeof(ILogger), PropertyName = "_logger")] - [Inject(typeof(IKeyInputHandlerService), PropertyName = "_keyInputHandlerService")] - public partial class MainWindowViewModel : IMainWindowViewModelBase + public bool Loading => false; + public IAppState AppState => _appState; + public string Title { get; private set; } + + partial void OnInitialize() { - public bool Loading => false; - public IAppState AppState => _appState; - public string Title { get; private set; } + _logger?.LogInformation($"Starting {nameof(MainWindowViewModel)} initialization..."); - partial void OnInitialize() + var version = Assembly.GetEntryAssembly()!.GetName().Version; + var versionString = "Unknwon version"; + if (version != null) { - _logger?.LogInformation($"Starting {nameof(MainWindowViewModel)} initialization..."); - - var version = Assembly.GetEntryAssembly()!.GetName().Version; - var versionString = "Unknwon version"; - if (version != null) + versionString = $"{version.Major}.{version.Minor}.{version.Build}"; + if (version.Revision != 0) { - versionString = $"{version.Major}.{version.Minor}.{version.Build}"; - if (version.Revision != 0) - { - versionString += $" ({version.Revision})"; - } - } - Title = "FileTime " + versionString; - - //TODO: refactor - if (AppState.Tabs.Count == 0) - { - var tab = _serviceProvider.GetInitableResolver(_localContentProvider).GetRequiredService(); - var tabViewModel = _serviceProvider.GetInitableResolver(tab, 1).GetRequiredService(); - - _appState.AddTab(tabViewModel); + versionString += $" ({version.Revision})"; } } + Title = "FileTime " + versionString; - public void ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action setHandled) + //TODO: refactor + if (AppState.Tabs.Count == 0) { - _keyInputHandlerService.ProcessKeyDown(key, keyModifiers, setHandled); + var tab = _serviceProvider.GetInitableResolver(_localContentProvider).GetRequiredService(); + var tabViewModel = _serviceProvider.GetInitableResolver(tab, 1).GetRequiredService(); + + _appState.AddTab(tabViewModel); } } -} + + public void ProcessKeyDown(Key key, KeyModifiers keyModifiers, Action setHandled) + { + _keyInputHandlerService.ProcessKeyDown(key, keyModifiers, setHandled); + } +} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Views/ItemView.axaml.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Views/ItemView.axaml.cs index 728f75e..b9271f6 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Views/ItemView.axaml.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Views/ItemView.axaml.cs @@ -1,21 +1,20 @@ using Avalonia; using Avalonia.Controls; -namespace FileTime.GuiApp.Views +namespace FileTime.GuiApp.Views; + +public partial class ItemView : UserControl { - public partial class ItemView : UserControl + public static readonly StyledProperty ShowAttributesProperty = AvaloniaProperty.Register(nameof(ShowAttributes), true); + + public bool ShowAttributes { - public static readonly StyledProperty ShowAttributesProperty = AvaloniaProperty.Register(nameof(ShowAttributes), true); - - public bool ShowAttributes - { - get => GetValue(ShowAttributesProperty); - set => SetValue(ShowAttributesProperty, value); - } - - public ItemView() - { - InitializeComponent(); - } + get => GetValue(ShowAttributesProperty); + set => SetValue(ShowAttributesProperty, value); } -} + + public ItemView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml.cs index 3e8a70d..72a0efe 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml.cs +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml.cs @@ -7,66 +7,65 @@ using FileTime.GuiApp.ViewModels; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -namespace FileTime.GuiApp.Views +namespace FileTime.GuiApp.Views; + +public partial class MainWindow : Window { - public partial class MainWindow : Window + private readonly ILogger? _logger; + private InputElementWrapper? _inputElementWrapper; + + public MainWindowViewModel? ViewModel { - private readonly ILogger? _logger; - private InputElementWrapper? _inputElementWrapper; - - public MainWindowViewModel? ViewModel + get => DataContext as MainWindowViewModel; + set { - get => DataContext as MainWindowViewModel; - set + if (value != DataContext) { - if (value != DataContext) - { - DataContext = value; - } - } - } - - public MainWindow() - { - _logger = DI.ServiceProvider.GetService>(); - _logger?.LogInformation($"Starting {nameof(MainWindow)} initialization..."); - InitializeComponent(); - } - - private void OnWindowOpened(object sender, EventArgs e) - { - if (DataContext is not MainWindowViewModel) - { - _logger?.LogInformation($"{nameof(MainWindow)} opened, starting {nameof(MainWindowViewModel)} initialization..."); - ViewModel = DI.ServiceProvider.GetRequiredService(); - } - } - - private void OnKeyDown(object sender, KeyEventArgs e) - { - if (_inputElementWrapper == null) - { - ViewModel?.ProcessKeyDown(e.Key, e.KeyModifiers, h => e.Handled = h); - } - } - - private void HeaderPointerPressed(object sender, PointerPressedEventArgs e) - { - if (e.ClickCount == 2) - { - if (WindowState == WindowState.Maximized) - { - WindowState = WindowState.Normal; - } - else - { - WindowState = WindowState.Maximized; - } - } - else - { - BeginMoveDrag(e); + DataContext = value; } } } + + public MainWindow() + { + _logger = DI.ServiceProvider.GetService>(); + _logger?.LogInformation($"Starting {nameof(MainWindow)} initialization..."); + InitializeComponent(); + } + + private void OnWindowOpened(object sender, EventArgs e) + { + if (DataContext is not MainWindowViewModel) + { + _logger?.LogInformation($"{nameof(MainWindow)} opened, starting {nameof(MainWindowViewModel)} initialization..."); + ViewModel = DI.ServiceProvider.GetRequiredService(); + } + } + + private void OnKeyDown(object sender, KeyEventArgs e) + { + if (_inputElementWrapper == null) + { + ViewModel?.ProcessKeyDown(e.Key, e.KeyModifiers, h => e.Handled = h); + } + } + + private void HeaderPointerPressed(object sender, PointerPressedEventArgs e) + { + if (e.ClickCount == 2) + { + if (WindowState == WindowState.Maximized) + { + WindowState = WindowState.Normal; + } + else + { + WindowState = WindowState.Maximized; + } + } + else + { + BeginMoveDrag(e); + } + } } \ No newline at end of file diff --git a/src/Library/InitableService/InitableService.csproj b/src/Library/InitableService/InitableService.csproj index dbde20d..6115779 100644 --- a/src/Library/InitableService/InitableService.csproj +++ b/src/Library/InitableService/InitableService.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/Providers/FileTime.Providers.Local.Abstractions/FileTime.Providers.Local.Abstractions.csproj b/src/Providers/FileTime.Providers.Local.Abstractions/FileTime.Providers.Local.Abstractions.csproj index b077d38..2046d63 100644 --- a/src/Providers/FileTime.Providers.Local.Abstractions/FileTime.Providers.Local.Abstractions.csproj +++ b/src/Providers/FileTime.Providers.Local.Abstractions/FileTime.Providers.Local.Abstractions.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/Providers/FileTime.Providers.Local.Abstractions/ILocalContentProvider.cs b/src/Providers/FileTime.Providers.Local.Abstractions/ILocalContentProvider.cs index 0144a2f..d06ef2f 100644 --- a/src/Providers/FileTime.Providers.Local.Abstractions/ILocalContentProvider.cs +++ b/src/Providers/FileTime.Providers.Local.Abstractions/ILocalContentProvider.cs @@ -1,9 +1,8 @@ using FileTime.Core.Services; -namespace FileTime.Providers.Local -{ - public interface ILocalContentProvider : IContentProvider - { +namespace FileTime.Providers.Local; + +public interface ILocalContentProvider : IContentProvider +{ - } } \ No newline at end of file diff --git a/src/Providers/FileTime.Providers.Local/FileTime.Providers.Local.csproj b/src/Providers/FileTime.Providers.Local/FileTime.Providers.Local.csproj index 73dfdbe..5e7e480 100644 --- a/src/Providers/FileTime.Providers.Local/FileTime.Providers.Local.csproj +++ b/src/Providers/FileTime.Providers.Local/FileTime.Providers.Local.csproj @@ -6,6 +6,10 @@ enable + + true + + diff --git a/src/Providers/FileTime.Providers.Local/LocalContentProvider.DirectoryHelper.cs b/src/Providers/FileTime.Providers.Local/LocalContentProvider.DirectoryHelper.cs index 9ffc9e4..c27dd65 100644 --- a/src/Providers/FileTime.Providers.Local/LocalContentProvider.DirectoryHelper.cs +++ b/src/Providers/FileTime.Providers.Local/LocalContentProvider.DirectoryHelper.cs @@ -1,23 +1,22 @@ using System.Runtime.InteropServices; -namespace FileTime.Providers.Local +namespace FileTime.Providers.Local; + +partial class LocalContentProvider { - partial class LocalContentProvider + private static string GetDirectoryAttributes(DirectoryInfo directoryInfo) { - private static string GetDirectoryAttributes(DirectoryInfo directoryInfo) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return ""; - } - else - { - return "d" - + ((directoryInfo.Attributes & FileAttributes.Archive) == FileAttributes.Archive ? "a" : "-") - + ((directoryInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly ? "r" : "-") - + ((directoryInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden ? "h" : "-") - + ((directoryInfo.Attributes & FileAttributes.System) == FileAttributes.System ? "s" : "-"); - } + return ""; + } + else + { + return "d" + + ((directoryInfo.Attributes & FileAttributes.Archive) == FileAttributes.Archive ? "a" : "-") + + ((directoryInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly ? "r" : "-") + + ((directoryInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden ? "h" : "-") + + ((directoryInfo.Attributes & FileAttributes.System) == FileAttributes.System ? "s" : "-"); } } } \ No newline at end of file diff --git a/src/Providers/FileTime.Providers.Local/LocalContentProvider.FileHelper.cs b/src/Providers/FileTime.Providers.Local/LocalContentProvider.FileHelper.cs index 20dd049..496feca 100644 --- a/src/Providers/FileTime.Providers.Local/LocalContentProvider.FileHelper.cs +++ b/src/Providers/FileTime.Providers.Local/LocalContentProvider.FileHelper.cs @@ -1,23 +1,22 @@ using System.Runtime.InteropServices; -namespace FileTime.Providers.Local +namespace FileTime.Providers.Local; + +partial class LocalContentProvider { - partial class LocalContentProvider + private static string GetFileAttributes(FileInfo fileInfo) { - private static string GetFileAttributes(FileInfo fileInfo) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return ""; - } - else - { - return "-" - + ((fileInfo.Attributes & FileAttributes.Archive) == FileAttributes.Archive ? "a" : "-") - + ((fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly ? "r" : "-") - + ((fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden ? "h" : "-") - + ((fileInfo.Attributes & FileAttributes.System) == FileAttributes.System ? "s" : "-"); - } + return ""; + } + else + { + return "-" + + ((fileInfo.Attributes & FileAttributes.Archive) == FileAttributes.Archive ? "a" : "-") + + ((fileInfo.Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly ? "r" : "-") + + ((fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden ? "h" : "-") + + ((fileInfo.Attributes & FileAttributes.System) == FileAttributes.System ? "s" : "-"); } } } \ No newline at end of file diff --git a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs index 0c26c4a..67c744a 100644 --- a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs +++ b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs @@ -6,218 +6,217 @@ using FileTime.Core.Enums; using FileTime.Core.Models; using FileTime.Core.Services; -namespace FileTime.Providers.Local +namespace FileTime.Providers.Local; + +public sealed partial class LocalContentProvider : ContentProviderBase, ILocalContentProvider { - public sealed partial class LocalContentProvider : ContentProviderBase, ILocalContentProvider + private readonly SourceList _rootDirectories = new(); + private readonly bool _isCaseInsensitive; + public LocalContentProvider() : base("local") { - private readonly SourceList _rootDirectories = new(); - private readonly bool _isCaseInsensitive; - public LocalContentProvider() : base("local") + _isCaseInsensitive = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + + RefreshRootDirectories(); + + Items.OnNext(_rootDirectories.Connect()); + } + + public override Task OnEnter() + { + RefreshRootDirectories(); + + return Task.CompletedTask; + } + + private void RefreshRootDirectories() + { + var rootDirectories = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) + ? new DirectoryInfo("/").GetDirectories() + : Environment.GetLogicalDrives().Select(d => new DirectoryInfo(d)); + + _rootDirectories.Edit(actions => { - _isCaseInsensitive = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + actions.Clear(); + actions.AddRange(rootDirectories.Select(DirectoryToAbsolutePath)); + }); + } - RefreshRootDirectories(); - - Items.OnNext(_rootDirectories.Connect()); - } - - public override Task OnEnter() + public override Task GetItemByNativePathAsync( + NativePath nativePath, + bool forceResolve = false, + AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, + ItemInitializationSettings itemInitializationSettings = default) + { + var path = nativePath.Path; + Exception? innerException; + try { - RefreshRootDirectories(); - - return Task.CompletedTask; - } - - private void RefreshRootDirectories() - { - var rootDirectories = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) - ? new DirectoryInfo("/").GetDirectories() - : Environment.GetLogicalDrives().Select(d => new DirectoryInfo(d)); - - _rootDirectories.Edit(actions => + if ((path?.Length ?? 0) == 0) { - actions.Clear(); - actions.AddRange(rootDirectories.Select(DirectoryToAbsolutePath)); - }); + return Task.FromResult((IItem)this); + } + else if (Directory.Exists(path)) + { + return Task.FromResult((IItem)DirectoryToContainer(new DirectoryInfo(path!.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar), !itemInitializationSettings.SkipChildInitialization)); + } + else if (File.Exists(path)) + { + return Task.FromResult((IItem)FileToElement(new FileInfo(path))); + } + + var type = forceResolvePathType switch + { + AbsolutePathType.Container => "Directory", + AbsolutePathType.Element => "File", + _ => "Directory or file" + }; + + innerException = forceResolvePathType switch + { + AbsolutePathType.Container => new DirectoryNotFoundException($"{type} not found: '{path}'"), + _ => new FileNotFoundException(type + " not found", path) + }; + } + catch (Exception e) + { + if (!forceResolve) throw new Exception($"Could not resolve path '{nativePath.Path}' and {nameof(forceResolve)} is false.", e); + innerException = e; } - public override Task GetItemByNativePathAsync( - NativePath nativePath, - bool forceResolve = false, - AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown, - ItemInitializationSettings itemInitializationSettings = default) + return forceResolvePathType switch { - var path = nativePath.Path; - Exception? innerException; + AbsolutePathType.Container => Task.FromResult((IItem)CreateEmptyContainer(nativePath, Observable.Return(new List() { innerException }))), + AbsolutePathType.Element => Task.FromResult(CreateEmptyElement(nativePath)), + _ => throw new Exception($"Could not resolve path '{nativePath.Path}' and could not force create, because {nameof(forceResolvePathType)} is {nameof(AbsolutePathType.Unknown)}.", innerException) + }; + } + + private Container CreateEmptyContainer(NativePath nativePath, IObservable>? exceptions = null) + { + var nonNullExceptions = exceptions ?? Observable.Return(Enumerable.Empty()); + var name = nativePath.Path.Split(Path.DirectorySeparatorChar).LastOrDefault() ?? "???"; + var fullName = GetFullName(nativePath); + + var parentFullName = fullName.GetParent(); + var parent = new AbsolutePath( + this, + parentFullName ?? new FullName(""), + AbsolutePathType.Container); + + return new Container( + name, + name, + fullName, + nativePath, + parent, + false, + true, + DateTime.MinValue, + SupportsDelete.False, + false, + "???", + this, + nonNullExceptions, + Observable.Return>?>(null) + ); + } + + private IItem CreateEmptyElement(NativePath nativePath) + { + throw new NotImplementedException(); + } + + public override Task> GetItemsByContainerAsync(FullName fullName) => Task.FromResult(GetItemsByContainer(fullName)); + private List GetItemsByContainer(FullName fullName) => GetItemsByContainer(new DirectoryInfo(GetNativePath(fullName).Path)); + private List GetItemsByContainer(DirectoryInfo directoryInfo) => directoryInfo.GetDirectories().Select(DirectoryToAbsolutePath).Concat(directoryInfo.GetFiles().Select(FileToAbsolutePath)).ToList(); + + private IAbsolutePath DirectoryToAbsolutePath(DirectoryInfo directoryInfo) + { + var fullName = GetFullName(directoryInfo); + return new AbsolutePath(this, fullName, AbsolutePathType.Container); + } + + private IAbsolutePath FileToAbsolutePath(FileInfo file) + { + var fullName = GetFullName(file); + return new AbsolutePath(this, fullName, AbsolutePathType.Element); + } + + private Container DirectoryToContainer(DirectoryInfo directoryInfo, bool initializeChildren = true) + { + var fullName = GetFullName(directoryInfo.FullName); + var parentFullName = fullName.GetParent(); + var parent = new AbsolutePath( + this, + parentFullName ?? new FullName(""), + AbsolutePathType.Container); + var exceptions = new BehaviorSubject>(Enumerable.Empty()); + + return new( + directoryInfo.Name, + directoryInfo.Name, + fullName, + new(directoryInfo.FullName), + parent, + (directoryInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden, + directoryInfo.Exists, + directoryInfo.CreationTime, + SupportsDelete.True, + true, + GetDirectoryAttributes(directoryInfo), + this, + exceptions, + Observable.FromAsync(async () => await Task.Run(InitChildren)) + ); + + Task>?> InitChildren() + { + SourceList? result = null; try { - if ((path?.Length ?? 0) == 0) + var items = initializeChildren ? (List?)GetItemsByContainer(directoryInfo) : null; + if (items != null) { - return Task.FromResult((IItem)this); + result = new SourceList(); + result.AddRange(items); } - else if (Directory.Exists(path)) - { - return Task.FromResult((IItem)DirectoryToContainer(new DirectoryInfo(path!.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar), !itemInitializationSettings.SkipChildInitialization)); - } - else if (File.Exists(path)) - { - return Task.FromResult((IItem)FileToElement(new FileInfo(path))); - } - - var type = forceResolvePathType switch - { - AbsolutePathType.Container => "Directory", - AbsolutePathType.Element => "File", - _ => "Directory or file" - }; - - innerException = forceResolvePathType switch - { - AbsolutePathType.Container => new DirectoryNotFoundException($"{type} not found: '{path}'"), - _ => new FileNotFoundException(type + " not found", path) - }; } catch (Exception e) { - if (!forceResolve) throw new Exception($"Could not resolve path '{nativePath.Path}' and {nameof(forceResolve)} is false.", e); - innerException = e; + exceptions.OnNext(new List() { e }); } - return forceResolvePathType switch - { - AbsolutePathType.Container => Task.FromResult((IItem)CreateEmptyContainer(nativePath, Observable.Return(new List() { innerException }))), - AbsolutePathType.Element => Task.FromResult(CreateEmptyElement(nativePath)), - _ => throw new Exception($"Could not resolve path '{nativePath.Path}' and could not force create, because {nameof(forceResolvePathType)} is {nameof(AbsolutePathType.Unknown)}.", innerException) - }; + return Task.FromResult(result?.Connect()); } - - private Container CreateEmptyContainer(NativePath nativePath, IObservable>? exceptions = null) - { - var nonNullExceptions = exceptions ?? Observable.Return(Enumerable.Empty()); - var name = nativePath.Path.Split(Path.DirectorySeparatorChar).LastOrDefault() ?? "???"; - var fullName = GetFullName(nativePath); - - var parentFullName = fullName.GetParent(); - var parent = new AbsolutePath( - this, - parentFullName ?? new FullName(""), - AbsolutePathType.Container); - - return new Container( - name, - name, - fullName, - nativePath, - parent, - false, - true, - DateTime.MinValue, - SupportsDelete.False, - false, - "???", - this, - nonNullExceptions, - Observable.Return>?>(null) - ); - } - - private IItem CreateEmptyElement(NativePath nativePath) - { - throw new NotImplementedException(); - } - - public override Task> GetItemsByContainerAsync(FullName fullName) => Task.FromResult(GetItemsByContainer(fullName)); - private List GetItemsByContainer(FullName fullName) => GetItemsByContainer(new DirectoryInfo(GetNativePath(fullName).Path)); - private List GetItemsByContainer(DirectoryInfo directoryInfo) => directoryInfo.GetDirectories().Select(DirectoryToAbsolutePath).Concat(directoryInfo.GetFiles().Select(FileToAbsolutePath)).ToList(); - - private IAbsolutePath DirectoryToAbsolutePath(DirectoryInfo directoryInfo) - { - var fullName = GetFullName(directoryInfo); - return new AbsolutePath(this, fullName, AbsolutePathType.Container); - } - - private IAbsolutePath FileToAbsolutePath(FileInfo file) - { - var fullName = GetFullName(file); - return new AbsolutePath(this, fullName, AbsolutePathType.Element); - } - - private Container DirectoryToContainer(DirectoryInfo directoryInfo, bool initializeChildren = true) - { - var fullName = GetFullName(directoryInfo.FullName); - var parentFullName = fullName.GetParent(); - var parent = new AbsolutePath( - this, - parentFullName ?? new FullName(""), - AbsolutePathType.Container); - var exceptions = new BehaviorSubject>(Enumerable.Empty()); - - return new( - directoryInfo.Name, - directoryInfo.Name, - fullName, - new(directoryInfo.FullName), - parent, - (directoryInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden, - directoryInfo.Exists, - directoryInfo.CreationTime, - SupportsDelete.True, - true, - GetDirectoryAttributes(directoryInfo), - this, - exceptions, - Observable.FromAsync(async () => await Task.Run(InitChildren)) - ); - - Task>?> InitChildren() - { - SourceList? result = null; - try - { - var items = initializeChildren ? (List?)GetItemsByContainer(directoryInfo) : null; - if (items != null) - { - result = new SourceList(); - result.AddRange(items); - } - } - catch (Exception e) - { - exceptions.OnNext(new List() { e }); - } - - return Task.FromResult(result?.Connect()); - } - } - - private Element FileToElement(FileInfo fileInfo) - { - var fullName = GetFullName(fileInfo); - var parentFullName = fullName.GetParent() ?? throw new Exception($"Path does not have parent: '{fileInfo.FullName}'"); - var parent = new AbsolutePath(this, parentFullName, AbsolutePathType.Container); - - return new( - fileInfo.Name, - fileInfo.Name, - fullName, - new(fileInfo.FullName), - parent, - (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden, - fileInfo.Exists, - fileInfo.CreationTime, - SupportsDelete.True, - true, - GetFileAttributes(fileInfo), - this, - Observable.Return(Enumerable.Empty()) - ); - } - - private FullName GetFullName(DirectoryInfo directoryInfo) => GetFullName(directoryInfo.FullName); - private FullName GetFullName(FileInfo fileInfo) => GetFullName(fileInfo.FullName); - private FullName GetFullName(NativePath nativePath) => GetFullName(nativePath.Path); - private FullName GetFullName(string nativePath) => new((Name + Constants.SeparatorChar + string.Join(Constants.SeparatorChar, nativePath.Split(Path.DirectorySeparatorChar))).TrimEnd(Constants.SeparatorChar)); - - public override NativePath GetNativePath(FullName fullName) => new(string.Join(Path.DirectorySeparatorChar, fullName.Path.Split(Constants.SeparatorChar).Skip(1))); } + + private Element FileToElement(FileInfo fileInfo) + { + var fullName = GetFullName(fileInfo); + var parentFullName = fullName.GetParent() ?? throw new Exception($"Path does not have parent: '{fileInfo.FullName}'"); + var parent = new AbsolutePath(this, parentFullName, AbsolutePathType.Container); + + return new( + fileInfo.Name, + fileInfo.Name, + fullName, + new(fileInfo.FullName), + parent, + (fileInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden, + fileInfo.Exists, + fileInfo.CreationTime, + SupportsDelete.True, + true, + GetFileAttributes(fileInfo), + this, + Observable.Return(Enumerable.Empty()) + ); + } + + private FullName GetFullName(DirectoryInfo directoryInfo) => GetFullName(directoryInfo.FullName); + private FullName GetFullName(FileInfo fileInfo) => GetFullName(fileInfo.FullName); + private FullName GetFullName(NativePath nativePath) => GetFullName(nativePath.Path); + private FullName GetFullName(string nativePath) => new((Name + Constants.SeparatorChar + string.Join(Constants.SeparatorChar, nativePath.Split(Path.DirectorySeparatorChar))).TrimEnd(Constants.SeparatorChar)); + + public override NativePath GetNativePath(FullName fullName) => new(string.Join(Path.DirectorySeparatorChar, fullName.Path.Split(Constants.SeparatorChar).Skip(1))); } \ No newline at end of file diff --git a/src/Providers/FileTime.Providers.Local/Startup.cs b/src/Providers/FileTime.Providers.Local/Startup.cs index 121f452..b2be663 100644 --- a/src/Providers/FileTime.Providers.Local/Startup.cs +++ b/src/Providers/FileTime.Providers.Local/Startup.cs @@ -1,15 +1,14 @@ using FileTime.Core.Services; using Microsoft.Extensions.DependencyInjection; -namespace FileTime.Providers.Local +namespace FileTime.Providers.Local; + +public static class Startup { - public static class Startup + public static IServiceCollection AddLocalServices(this IServiceCollection serviceCollection) { - public static IServiceCollection AddLocalServices(this IServiceCollection serviceCollection) - { - return serviceCollection - .AddSingleton() - .AddSingleton(sp => sp.GetRequiredService()); - } + return serviceCollection + .AddSingleton() + .AddSingleton(sp => sp.GetRequiredService()); } } \ No newline at end of file diff --git a/src/Tools/FileTime.Tools/Extensions/ObjectExtensions.cs b/src/Tools/FileTime.Tools/Extensions/ObjectExtensions.cs index 189e7e7..81080be 100644 --- a/src/Tools/FileTime.Tools/Extensions/ObjectExtensions.cs +++ b/src/Tools/FileTime.Tools/Extensions/ObjectExtensions.cs @@ -1,11 +1,10 @@ -namespace FileTime.Tools.Extensions -{ - public static class ObjectExtensions - { - public static TResult? MapNull(this T obj, Func nullHandler, Func valueHandler) - => obj == null ? nullHandler() : valueHandler(obj); +namespace FileTime.Tools.Extensions; - public static TResult? MapNull(this T obj, Func valueHandler) - => obj == null ? default : valueHandler(obj); - } +public static class ObjectExtensions +{ + public static TResult? MapNull(this T obj, Func nullHandler, Func valueHandler) + => obj == null ? nullHandler() : valueHandler(obj); + + public static TResult? MapNull(this T obj, Func valueHandler) + => obj == null ? default : valueHandler(obj); } \ No newline at end of file diff --git a/src/Tools/FileTime.Tools/FileTime.Tools.csproj b/src/Tools/FileTime.Tools/FileTime.Tools.csproj index bafd05b..e566a20 100644 --- a/src/Tools/FileTime.Tools/FileTime.Tools.csproj +++ b/src/Tools/FileTime.Tools/FileTime.Tools.csproj @@ -6,4 +6,8 @@ enable + + true + +