From 84522d8f96134357be6adb3a5cf6ff7c3695b2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Fri, 15 Apr 2022 00:13:22 +0200 Subject: [PATCH] Show children --- .../ViewModels/ITabViewModel.cs | 3 +- .../Extensions/ObservableExtensions.cs | 9 + .../FileTime.App.Core.csproj | 1 + .../Services/CommandHandlerService.cs | 2 +- .../ViewModels/TabViewModel.cs | 34 +- .../Models/IAbsolutePath.cs | 3 +- .../Models/IContainer.cs | 2 +- .../FileTime.Core.Abstraction/Models/IItem.cs | 1 + .../Services/IContentProvider.cs | 5 +- .../Services/ITab.cs | 3 +- src/Core/FileTime.Core.Models/AbsolutePath.cs | 13 +- src/Core/FileTime.Core.Models/Container.cs | 3 +- src/Core/FileTime.Core.Models/Element.cs | 3 +- src/Core/FileTime.Core.Models/FileElement.cs | 4 +- .../ContentProviderBase.cs | 9 +- src/Core/FileTime.Core.Services/Tab.cs | 20 +- .../Avalonia/FileTime.GuiApp.App/App.axaml | 351 ++++++++---------- .../Converters/ExceptionToStringConverter.cs | 45 +++ .../FileTime.GuiApp/Views/MainWindow.axaml | 317 +++++++++------- .../LocalContentProvider.cs | 87 ++++- src/Settings.XamlStyler | 42 +++ 21 files changed, 591 insertions(+), 366 deletions(-) create mode 100644 src/AppCommon/FileTime.App.Core/Extensions/ObservableExtensions.cs create mode 100644 src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ExceptionToStringConverter.cs create mode 100644 src/Settings.XamlStyler diff --git a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/ITabViewModel.cs b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/ITabViewModel.cs index 62bd9c1..5f33c20 100644 --- a/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/ITabViewModel.cs +++ b/src/AppCommon/FileTime.App.Core.Abstraction/ViewModels/ITabViewModel.cs @@ -12,7 +12,8 @@ namespace FileTime.App.Core.ViewModels IObservable IsSelected { get; } IObservable CurrentLocation { get; } IObservable CurrentSelectedItem { get; } - IObservable> CurrentItems { get; } + IObservable> CurrentItems { get; } IObservable> MarkedItems { get; } + IObservable?> SelectedsChildren { get; } } } \ 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 new file mode 100644 index 0000000..727666f --- /dev/null +++ b/src/AppCommon/FileTime.App.Core/Extensions/ObservableExtensions.cs @@ -0,0 +1,9 @@ +using System.Reactive.Linq; + +namespace FileTime.App.Core.Extensions +{ + public static class ObservableExtensions + { + 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/FileTime.App.Core.csproj b/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj index a957c4c..e2fd5b3 100644 --- a/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj +++ b/src/AppCommon/FileTime.App.Core/FileTime.App.Core.csproj @@ -9,6 +9,7 @@ + diff --git a/src/AppCommon/FileTime.App.Core/Services/CommandHandlerService.cs b/src/AppCommon/FileTime.App.Core/Services/CommandHandlerService.cs index 7a68ea9..2baf417 100644 --- a/src/AppCommon/FileTime.App.Core/Services/CommandHandlerService.cs +++ b/src/AppCommon/FileTime.App.Core/Services/CommandHandlerService.cs @@ -100,7 +100,7 @@ namespace FileTime.App.Core.Services private async Task GoUp() { - if (_currentLocation?.Parent is not IAbsolutePath parentPath || await parentPath.ResolveAsync() is not IContainer newContainer) return; + if (_currentLocation?.Parent is not IAbsolutePath parentPath || await parentPath.ResolveAsyncSafe() is not IContainer newContainer) return; _selectedTab?.Tab?.SetCurrentLocation(newContainer); } diff --git a/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs b/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs index a21ab61..843404d 100644 --- a/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs +++ b/src/AppCommon/FileTime.App.Core/ViewModels/TabViewModel.cs @@ -1,7 +1,9 @@ using System.Reactive.Linq; using System.Reactive.Subjects; +using FileTime.App.Core.Extensions; using FileTime.App.Core.Models.Enums; using FileTime.App.Core.Services; +using FileTime.Core.Enums; using FileTime.Core.Models; using FileTime.Core.Services; using Microsoft.Extensions.DependencyInjection; @@ -24,8 +26,9 @@ namespace FileTime.App.Core.ViewModels public IObservable CurrentLocation { get; private set; } = null!; public IObservable CurrentSelectedItem { get; private set; } = null!; - public IObservable> CurrentItems { get; private set; } = null!; + public IObservable> CurrentItems { get; private set; } = null!; public IObservable> MarkedItems { get; } + public IObservable?> SelectedsChildren { get; private set; } = null!; public TabViewModel( IServiceProvider serviceProvider, @@ -46,7 +49,7 @@ namespace FileTime.App.Core.ViewModels TabNumber = tabNumber; CurrentLocation = tab.CurrentLocation.AsObservable(); - CurrentItems = tab.CurrentItems.Select(items => items.Select(MapItemToViewModel).ToList()).Publish(Enumerable.Empty()).RefCount(); + CurrentItems = tab.CurrentItems.Select(items => items.Select(MapItemToViewModel).ToList()).Publish(new List()).RefCount(); CurrentSelectedItem = Observable.CombineLatest( CurrentItems, @@ -55,7 +58,34 @@ namespace FileTime.App.Core.ViewModels ) .Publish(null) .RefCount(); + + var currentSelectedItemThrottled = CurrentSelectedItem.Throttle(TimeSpan.FromMilliseconds(250)).Publish(null).RefCount(); + SelectedsChildren = Observable.Merge( + currentSelectedItemThrottled + .WhereNotNull() + .OfType() + .Where(c => c?.Container is not null) + .Select(c => c.Container!.Items) + .Switch() + .Select(items => Observable.FromAsync(async () => await Map(items))) + .Switch() + .Select(items => items?.Select(MapItemToViewModel).ToList()), + currentSelectedItemThrottled + .Where(c => c is null || c is not IContainerViewModel) + .Select(_ => (IReadOnlyList?)null) + ); + tab.CurrentLocation.Subscribe((_) => _markedItems.OnNext(Enumerable.Empty())); + + static async Task?> Map(IEnumerable? items) + { + if (items == null) return null; + + return await items + .ToAsyncEnumerable() + .SelectAwait(async i => await i.ResolveAsync(true)) + .ToListAsync(); + } } private IItemViewModel MapItemToViewModel(IItem item, int index) diff --git a/src/Core/FileTime.Core.Abstraction/Models/IAbsolutePath.cs b/src/Core/FileTime.Core.Abstraction/Models/IAbsolutePath.cs index bfc45dc..23b501f 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/IAbsolutePath.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/IAbsolutePath.cs @@ -10,6 +10,7 @@ namespace FileTime.Core.Models FullName Path { get; } AbsolutePathType Type { get; } - Task ResolveAsync(); + Task ResolveAsync(bool forceResolve = false); + Task ResolveAsyncSafe(bool forceResolve = false); } } \ 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 0a59313..2f87b23 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/IContainer.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/IContainer.cs @@ -2,7 +2,7 @@ namespace FileTime.Core.Models { public interface IContainer : IItem { - IObservable> Items { get; } + IObservable?> Items { get; } IObservable IsLoading { 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 50074a1..15ed4cc 100644 --- a/src/Core/FileTime.Core.Abstraction/Models/IItem.cs +++ b/src/Core/FileTime.Core.Abstraction/Models/IItem.cs @@ -18,5 +18,6 @@ namespace FileTime.Core.Models 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/Services/IContentProvider.cs b/src/Core/FileTime.Core.Abstraction/Services/IContentProvider.cs index 30df12a..15e83e7 100644 --- a/src/Core/FileTime.Core.Abstraction/Services/IContentProvider.cs +++ b/src/Core/FileTime.Core.Abstraction/Services/IContentProvider.cs @@ -1,12 +1,13 @@ using FileTime.Core.Behaviors; +using FileTime.Core.Enums; using FileTime.Core.Models; namespace FileTime.Core.Services { public interface IContentProvider : IContainer, IOnContainerEnter { - Task GetItemByFullNameAsync(FullName fullName); - Task GetItemByNativePathAsync(NativePath nativePath); + Task GetItemByFullNameAsync(FullName fullName, bool forceResolve = false, AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown); + Task GetItemByNativePathAsync(NativePath nativePath, bool forceResolve = false, AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown); 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 a99a3ed..be77e4e 100644 --- a/src/Core/FileTime.Core.Abstraction/Services/ITab.cs +++ b/src/Core/FileTime.Core.Abstraction/Services/ITab.cs @@ -1,6 +1,5 @@ using FileTime.Core.Models; using InitableService; -using System.Reactive.Subjects; namespace FileTime.Core.Services { @@ -8,7 +7,7 @@ namespace FileTime.Core.Services { IObservable CurrentLocation { get; } IObservable CurrentSelectedItem { get; } - IObservable> CurrentItems { get; } + IObservable?> CurrentItems { get; } void SetCurrentLocation(IContainer newLocation); void AddSelectedItemsTransformator(ItemsTransformator transformator); diff --git a/src/Core/FileTime.Core.Models/AbsolutePath.cs b/src/Core/FileTime.Core.Models/AbsolutePath.cs index e573edb..f5d42e7 100644 --- a/src/Core/FileTime.Core.Models/AbsolutePath.cs +++ b/src/Core/FileTime.Core.Models/AbsolutePath.cs @@ -19,10 +19,19 @@ namespace FileTime.Core.Models Type = type; } - public async Task ResolveAsync() + public async Task ResolveAsync(bool forceResolve = false) { var provider = VirtualContentProvider ?? ContentProvider; - return await provider.GetItemByFullNameAsync(Path); + return await provider.GetItemByFullNameAsync(Path, forceResolve, Type); + } + + public async Task ResolveAsyncSafe(bool forceResolve = false) + { + try + { + return await ResolveAsync(forceResolve); + } + 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 17213f6..3221231 100644 --- a/src/Core/FileTime.Core.Models/Container.cs +++ b/src/Core/FileTime.Core.Models/Container.cs @@ -18,7 +18,8 @@ namespace FileTime.Core.Models bool CanRename, string? Attributes, IContentProvider Provider, - IObservable> Items) : IContainer + IObservable> Exceptions, + IObservable?> Items) : IContainer { BehaviorSubject IsLoading { get; } = new BehaviorSubject(false); IObservable IContainer.IsLoading => IsLoading.AsObservable(); diff --git a/src/Core/FileTime.Core.Models/Element.cs b/src/Core/FileTime.Core.Models/Element.cs index fee18b7..5dc83e5 100644 --- a/src/Core/FileTime.Core.Models/Element.cs +++ b/src/Core/FileTime.Core.Models/Element.cs @@ -15,7 +15,8 @@ namespace FileTime.Core.Models SupportsDelete CanDelete, bool CanRename, string? Attributes, - IContentProvider Provider) : IElement + IContentProvider Provider, + IObservable> Exceptions) : IElement { public AbsolutePathType Type => AbsolutePathType.Element; } diff --git a/src/Core/FileTime.Core.Models/FileElement.cs b/src/Core/FileTime.Core.Models/FileElement.cs index 3a84236..69bb9f5 100644 --- a/src/Core/FileTime.Core.Models/FileElement.cs +++ b/src/Core/FileTime.Core.Models/FileElement.cs @@ -16,6 +16,7 @@ namespace FileTime.Core.Models bool CanRename, string? Attributes, IContentProvider Provider, + IObservable> Exceptions, long Size) : Element( Name, @@ -29,6 +30,7 @@ namespace FileTime.Core.Models CanDelete, CanRename, Attributes, - Provider + Provider, + Exceptions ), IFileElement; } \ No newline at end of file diff --git a/src/Core/FileTime.Core.Services/ContentProviderBase.cs b/src/Core/FileTime.Core.Services/ContentProviderBase.cs index 534f41a..69ec570 100644 --- a/src/Core/FileTime.Core.Services/ContentProviderBase.cs +++ b/src/Core/FileTime.Core.Services/ContentProviderBase.cs @@ -9,7 +9,7 @@ namespace FileTime.Core.Services { protected BehaviorSubject> Items { get; } = new BehaviorSubject>(new List()); - IObservable> IContainer.Items => Items; + IObservable> IContainer.Items => Items; public string Name { get; } @@ -41,14 +41,17 @@ namespace FileTime.Core.Services 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) => await GetItemByNativePathAsync(GetNativePath(fullName)); - public abstract Task GetItemByNativePathAsync(NativePath nativePath); + public virtual async Task GetItemByFullNameAsync(FullName fullName, bool forceResolve = false, AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown) + => await GetItemByNativePathAsync(GetNativePath(fullName), forceResolve, forceResolvePathType); + public abstract Task GetItemByNativePathAsync(NativePath nativePath, bool forceResolve = false, AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown); public abstract Task> GetItemsByContainerAsync(FullName fullName); public abstract NativePath GetNativePath(FullName fullName); } diff --git a/src/Core/FileTime.Core.Services/Tab.cs b/src/Core/FileTime.Core.Services/Tab.cs index 6dbfd44..3d9baf8 100644 --- a/src/Core/FileTime.Core.Services/Tab.cs +++ b/src/Core/FileTime.Core.Services/Tab.cs @@ -11,7 +11,7 @@ namespace FileTime.Core.Services private readonly List _transformators = new(); private IAbsolutePath? _currentSelectedItemCached; public IObservable CurrentLocation { get; } - public IObservable> CurrentItems { get; } + public IObservable?> CurrentItems { get; } public IObservable CurrentSelectedItem { get; } public Tab() @@ -23,7 +23,7 @@ namespace FileTime.Core.Services .Where(c => c is not null) .Select(c => c!.Items) .Switch() - .Select(i => Observable.FromAsync(async () => await MapItems(i))) + .Select(i => i == null ? Observable.Return?>(null) : Observable.FromAsync(async () => await MapItems(i))) .Switch(), CurrentLocation .Where(c => c is null) @@ -43,21 +43,11 @@ namespace FileTime.Core.Services CurrentSelectedItem.Subscribe(s => _currentSelectedItemCached = s); } - private async Task> MapItems(IReadOnlyList items) + private async Task> MapItems(IEnumerable items) { IEnumerable resolvedItems = await items .ToAsyncEnumerable() - .SelectAwait( - async i => - { - try - { - //TODO: force create by AbsolutePath name - return await i.ContentProvider.GetItemByFullNameAsync(i.Path); - } - catch { return null!; } - } - ) + .SelectAwait(async i => await i.ResolveAsync(true)) .Where(i => i != null) .ToListAsync(); @@ -79,7 +69,7 @@ namespace FileTime.Core.Services private IObservable GetSelectedItemByLocation(IContainer? currentLocation) { //TODO: - return currentLocation?.Items?.Select(i => i.Count == 0 ? null : i[0]) ?? Observable.Return((IAbsolutePath?)null); + return currentLocation?.Items?.Select(i => i.FirstOrDefault()) ?? Observable.Return((IAbsolutePath?)null); } public void SetCurrentLocation(IContainer newLocation) => _currentLocation.OnNext(newLocation); diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp.App/App.axaml b/src/GuiApp/Avalonia/FileTime.GuiApp.App/App.axaml index e5a3e94..7c51834 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp.App/App.axaml +++ b/src/GuiApp/Avalonia/FileTime.GuiApp.App/App.axaml @@ -1,218 +1,185 @@ - - - - #E7073642 - #083e4c - #D0083e4c - #80083e4c + + + + #E7073642 + #083e4c + #D0083e4c + #80083e4c - #00000000 - #10000000 - #93a1a1 - #00000000 - #10000000 - #b58900 + #00000000 + #10000000 + #93a1a1 + #00000000 + #10000000 + #b58900 - #93a1a1 - #268bd2 - #fdf6e3 - #7793a1a1 - #93a1a1 - #073642 - #b58900 - #b58900 - #002b36 + #93a1a1 + #268bd2 + #fdf6e3 + #7793a1a1 + #93a1a1 + #073642 + #b58900 + #b58900 + #002b36 - #dc322f + #dc322f - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - - - - + + + + + + - - - - - - - - - + + + + + + + + + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + + - - - - - - + + + + + + - + - + - + - - + + - - + + diff --git a/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ExceptionToStringConverter.cs b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ExceptionToStringConverter.cs new file mode 100644 index 0000000..780f803 --- /dev/null +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Converters/ExceptionToStringConverter.cs @@ -0,0 +1,45 @@ +using System.Globalization; +using Avalonia.Data.Converters; + +namespace FileTime.GuiApp.Converters +{ + public class ExceptionToStringConverter : IValueConverter + { + public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + 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); + } + + private static string TraverseInnerException(Exception e) + { + string s = ""; + if (e.InnerException != null) s += TraverseInnerException(e.InnerException) + Environment.NewLine; + else return FormatException(e); + + s += "In: " + FormatException(e); + + return s; + } + + 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/Views/MainWindow.axaml b/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml index 671c2c7..e9dd5dd 100644 --- a/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml +++ b/src/GuiApp/Avalonia/FileTime.GuiApp/Views/MainWindow.axaml @@ -1,145 +1,208 @@ - + + + + - - - - - - - + + + + + + + - - + + - - - - - + + + + + - + - - - - - - - - - - + + + + + + + + + + - + - - + + - - - - - + + + + + - - - - - - - - - + + + + + + + + + - + - - - - - - - - - - - + + + + + + + + + + + - - Empty - - + + Empty + + - + - - - - - + + + + + + + + + - + + Empty + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 9df7566..5ca5764 100644 --- a/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs +++ b/src/Providers/FileTime.Providers.Local/LocalContentProvider.cs @@ -31,23 +31,80 @@ namespace FileTime.Providers.Local Items.OnNext(rootDirectories.Select(DirectoryToAbsolutePath).ToList()); } - public override Task GetItemByNativePathAsync(NativePath nativePath) + public override Task GetItemByNativePathAsync(NativePath nativePath, bool forceResolve = false, AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown) { var path = nativePath.Path; - if ((path?.Length ?? 0) == 0) + try { - return Task.FromResult((IItem)this); - } - else if (Directory.Exists(path)) - { - return Task.FromResult((IItem)DirectoryToContainer(new DirectoryInfo(path!.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar))); - } - else if (File.Exists(path)) - { - return Task.FromResult((IItem)FileToElement(new FileInfo(path))); - } + if ((path?.Length ?? 0) == 0) + { + return Task.FromResult((IItem)this); + } + else if (Directory.Exists(path)) + { + return Task.FromResult((IItem)DirectoryToContainer(new DirectoryInfo(path!.TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar))); + } + else if (File.Exists(path)) + { + return Task.FromResult((IItem)FileToElement(new FileInfo(path))); + } - throw new FileNotFoundException("Directory or file not found", path); + var type = forceResolvePathType switch + { + AbsolutePathType.Container => "Directory", + AbsolutePathType.Element => "File", + _ => "Directory or file" + }; + + if (forceResolvePathType == AbsolutePathType.Container) throw new DirectoryNotFoundException($"{type} not found: '{path}'"); + throw 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); + + return forceResolvePathType switch + { + AbsolutePathType.Container => Task.FromResult((IItem)CreateEmptyContainer(nativePath, Observable.Return(new List() { e }))), + 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)}.", e) + }; + } + } + + 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)); @@ -88,6 +145,7 @@ namespace FileTime.Providers.Local true, GetDirectoryAttributes(directoryInfo), this, + Observable.Return(Enumerable.Empty()), Observable.Return(GetItemsByContainer(directoryInfo)) ); } @@ -110,7 +168,8 @@ namespace FileTime.Providers.Local SupportsDelete.True, true, GetFileAttributes(fileInfo), - this + this, + Observable.Return(Enumerable.Empty()) ); } diff --git a/src/Settings.XamlStyler b/src/Settings.XamlStyler new file mode 100644 index 0000000..6837c7d --- /dev/null +++ b/src/Settings.XamlStyler @@ -0,0 +1,42 @@ +{ + "AttributesTolerance": 1, + "KeepFirstAttributeOnSameLine": false, + "MaxAttributeCharactersPerLine": 0, + "MaxAttributesPerLine": 1, + "NewlineExemptionElements": "RadialGradientBrush, GradientStop, LinearGradientBrush, ScaleTransform, SkewTransform, RotateTransform, TranslateTransform, Trigger, Condition, Setter", + "SeparateByGroups": false, + "AttributeIndentation": 0, + "AttributeIndentationStyle": 1, + "RemoveDesignTimeReferences": false, + "EnableAttributeReordering": true, + "AttributeOrderingRuleGroups": [ + "x:Class", + "xmlns, xmlns:x", + "xmlns:*", + "x:Key, Key, x:Name, Name, x:Uid, Uid, Title", + "DataContext", + "Grid.Row, Grid.RowSpan, Grid.Column, Grid.ColumnSpan, Canvas.Left, Canvas.Top, Canvas.Right, Canvas.Bottom", + "Width, Height, MinWidth, MinHeight, MaxWidth, MaxHeight", + "Margin, Padding, HorizontalAlignment, VerticalAlignment, HorizontalContentAlignment, VerticalContentAlignment, Panel.ZIndex", + "*:*, *", + "PageSource, PageIndex, Offset, Color, TargetName, Property, Value, StartPoint, EndPoint", + "mc:Ignorable, d:IsDataSource, d:LayoutOverrides, d:IsStaticText", + "Storyboard.*, From, To, Duration" + ], + "FirstLineAttributes": "", + "OrderAttributesByName": true, + "PutEndingBracketOnNewLine": false, + "RemoveEndingTagOfEmptyElement": true, + "SpaceBeforeClosingSlash": true, + "RootElementLineBreakRule": 0, + "ReorderVSM": 2, + "ReorderGridChildren": false, + "ReorderCanvasChildren": false, + "ReorderSetters": 0, + "FormatMarkupExtension": true, + "NoNewLineMarkupExtensions": "x:Bind, Binding", + "ThicknessSeparator": 2, + "ThicknessAttributes": "Margin, Padding, BorderThickness, ThumbnailClipMargin", + "FormatOnSave": true, + "CommentPadding": 2, +} \ No newline at end of file