From c8748644d29a4a92f9ab8a49b9130b48be550bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81d=C3=A1m=20Kov=C3=A1cs?= Date: Wed, 23 Feb 2022 23:49:22 +0100 Subject: [PATCH] Loading refactor, SizeContainer&SmbServer delete --- .../ContainerScanSnapshotProvider.cs | 9 +++++ .../ContainerSizeContainer.cs | 9 ++++- .../ContainerSizeScanner/ScanSizeTask.cs | 4 +-- src/Core/FileTime.Core/Models/IContainer.cs | 6 ++-- .../FileTime.Core/Models/VirtualContainer.cs | 8 ++--- .../Providers/AbstractContainer.cs | 21 +++++++++--- .../Providers/LazyLoadingContainer.cs | 15 -------- .../FileTime.Core/Providers/TopContainer.cs | 12 ++++--- .../FileTime.Core/Search/SearchContainer.cs | 9 +++-- .../FileTime.Core/Timeline/TimeContainer.cs | 12 ++++--- .../Application/TabContainer.cs | 34 ++++++++++++------- .../Services/CommandHandlerService.cs | 4 +-- .../ViewModels/ContainerViewModel.cs | 10 +++--- .../FileTime.Avalonia/Views/MainWindow.axaml | 2 +- .../SmbContentProvider.cs | 9 +++++ .../FileTime.Providers.Smb/SmbServer.cs | 9 +++-- 16 files changed, 105 insertions(+), 68 deletions(-) diff --git a/src/Core/FileTime.Core/ContainerSizeScanner/ContainerScanSnapshotProvider.cs b/src/Core/FileTime.Core/ContainerSizeScanner/ContainerScanSnapshotProvider.cs index 6e81046..ff8a91e 100644 --- a/src/Core/FileTime.Core/ContainerSizeScanner/ContainerScanSnapshotProvider.cs +++ b/src/Core/FileTime.Core/ContainerSizeScanner/ContainerScanSnapshotProvider.cs @@ -29,5 +29,14 @@ namespace FileTime.Core.ContainerSizeScanner await RefreshAsync(); } } + + public async Task RemoveSnapshotAsync(ContainerSizeContainer snapshot) + { + if (RootContainers?.Contains(snapshot) == true) + { + RootContainers.Remove(snapshot); + await RefreshAsync(); + } + } } } \ No newline at end of file diff --git a/src/Core/FileTime.Core/ContainerSizeScanner/ContainerSizeContainer.cs b/src/Core/FileTime.Core/ContainerSizeScanner/ContainerSizeContainer.cs index 4db9272..921a30d 100644 --- a/src/Core/FileTime.Core/ContainerSizeScanner/ContainerSizeContainer.cs +++ b/src/Core/FileTime.Core/ContainerSizeScanner/ContainerSizeContainer.cs @@ -23,6 +23,7 @@ namespace FileTime.Core.ContainerSizeScanner public ContainerSizeContainer(ContainerScanSnapshotProvider provider, IContainer parent, IContainer baseContainer, string? displayName = null) : base(provider, parent, baseContainer.Name) { _baseContainer = baseContainer; + CanDelete = SupportsDelete.True; AllowRecursiveDeletion = false; CanHandleEscape = true; if (displayName != null) @@ -37,7 +38,13 @@ namespace FileTime.Core.ContainerSizeScanner public override Task CreateElementAsync(string name) => throw new NotSupportedException(); - public override Task Delete(bool hardDelete = false) => throw new NotSupportedException(); + public override async Task Delete(bool hardDelete = false) + { + if (GetParent() is ContainerScanSnapshotProvider provider) + { + await provider.RemoveSnapshotAsync(this); + } + } public override async Task RefreshAsync(CancellationToken token = default) { diff --git a/src/Core/FileTime.Core/ContainerSizeScanner/ScanSizeTask.cs b/src/Core/FileTime.Core/ContainerSizeScanner/ScanSizeTask.cs index b2e604a..7747a2e 100644 --- a/src/Core/FileTime.Core/ContainerSizeScanner/ScanSizeTask.cs +++ b/src/Core/FileTime.Core/ContainerSizeScanner/ScanSizeTask.cs @@ -43,7 +43,7 @@ namespace FileTime.Core.ContainerSizeScanner { try { - Task.Run(async () => await Snapshot.RunWithLazyLoading(async (token) => await ScanAsync(ContainerToScan, Snapshot, token))).Wait(); + Task.Run(async () => await Snapshot.RunWithLoading(async (token) => await ScanAsync(ContainerToScan, Snapshot, token))).Wait(); } finally { @@ -93,7 +93,7 @@ namespace FileTime.Core.ContainerSizeScanner { return; } - await newSizeContainer.RunWithLazyLoading(async (token) => await ScanAsync(childContainer, newSizeContainer, token), token); + await newSizeContainer.RunWithLoading(async (token) => await ScanAsync(childContainer, newSizeContainer, token), token); } } diff --git a/src/Core/FileTime.Core/Models/IContainer.cs b/src/Core/FileTime.Core/Models/IContainer.cs index ca6c7a9..071c43d 100644 --- a/src/Core/FileTime.Core/Models/IContainer.cs +++ b/src/Core/FileTime.Core/Models/IContainer.cs @@ -9,8 +9,7 @@ namespace FileTime.Core.Models Task?> GetContainers(CancellationToken token = default); Task?> GetElements(CancellationToken token = default); bool AllowRecursiveDeletion { get; } - bool UseLazyLoad { get; } - bool LazyLoading { get; } + bool Loading { get; } bool CanHandleEscape { get; } Task RefreshAsync(CancellationToken token = default); @@ -50,11 +49,12 @@ namespace FileTime.Core.Models void Unload(); Task HandleEscape(); + Task RunWithLoading(Func func, CancellationToken token = default); bool IsLoaded { get; } bool SupportsDirectoryLevelSoftDelete { get; } AsyncEventHandler Refreshed { get; } - AsyncEventHandler LazyLoadingChanged { get; } + AsyncEventHandler LoadingChanged { get; } } } \ No newline at end of file diff --git a/src/Core/FileTime.Core/Models/VirtualContainer.cs b/src/Core/FileTime.Core/Models/VirtualContainer.cs index 07bb98e..e248496 100644 --- a/src/Core/FileTime.Core/Models/VirtualContainer.cs +++ b/src/Core/FileTime.Core/Models/VirtualContainer.cs @@ -41,10 +41,8 @@ namespace FileTime.Core.Models public bool IsExists => BaseContainer.IsExists; public bool AllowRecursiveDeletion => BaseContainer.AllowRecursiveDeletion; - public bool UseLazyLoad => BaseContainer.UseLazyLoad; - - public bool LazyLoading => BaseContainer.LazyLoading; - public AsyncEventHandler LazyLoadingChanged { get; protected set; } = new(); + public bool Loading => BaseContainer.Loading; + public AsyncEventHandler LoadingChanged { get; protected set; } = new(); public bool CanHandleEscape => BaseContainer.CanHandleEscape; @@ -192,5 +190,7 @@ namespace FileTime.Core.Models BaseContainer.Unload(); } public async Task HandleEscape() => await BaseContainer.HandleEscape(); + + public async Task RunWithLoading(Func func, CancellationToken token = default) => await BaseContainer.RunWithLoading(func, token); } } \ No newline at end of file diff --git a/src/Core/FileTime.Core/Providers/AbstractContainer.cs b/src/Core/FileTime.Core/Providers/AbstractContainer.cs index 1382300..55c5093 100644 --- a/src/Core/FileTime.Core/Providers/AbstractContainer.cs +++ b/src/Core/FileTime.Core/Providers/AbstractContainer.cs @@ -19,7 +19,7 @@ namespace FileTime.Core.Providers public bool SupportsDirectoryLevelSoftDelete { get; protected set; } public AsyncEventHandler Refreshed { get; protected set; } = new(); - public AsyncEventHandler LazyLoadingChanged { get; protected set; } = new(); + public AsyncEventHandler LoadingChanged { get; protected set; } = new(); public string Name { get; protected set; } public virtual string DisplayName { get; protected set; } @@ -44,9 +44,7 @@ namespace FileTime.Core.Providers public virtual bool AllowRecursiveDeletion { get; protected set; } - public bool UseLazyLoad { get; protected set; } - - public bool LazyLoading { get; protected set; } + public bool Loading { get; protected set; } public bool CanHandleEscape { get; protected set; } @@ -109,6 +107,21 @@ namespace FileTime.Core.Providers return _items; } + public async Task RunWithLoading(Func func, CancellationToken token = default) + { + try + { + Loading = true; + await LoadingChanged.InvokeAsync(this, Loading, token); + await func(token); + } + finally + { + Loading = false; + await LoadingChanged.InvokeAsync(this, Loading, token); + } + } + public virtual IContainer? GetParent() => _parent; public virtual async Task IsExistsAsync(string name) diff --git a/src/Core/FileTime.Core/Providers/LazyLoadingContainer.cs b/src/Core/FileTime.Core/Providers/LazyLoadingContainer.cs index 8a86614..843d7ef 100644 --- a/src/Core/FileTime.Core/Providers/LazyLoadingContainer.cs +++ b/src/Core/FileTime.Core/Providers/LazyLoadingContainer.cs @@ -25,21 +25,6 @@ namespace FileTime.Core.Providers _items = Containers.Cast().Concat(Elements).ToList().AsReadOnly(); } - public async Task RunWithLazyLoading(Func func, CancellationToken token = default) - { - try - { - LazyLoading = true; - await LazyLoadingChanged.InvokeAsync(this, LazyLoading, token); - await func(token); - } - finally - { - LazyLoading = false; - await LazyLoadingChanged.InvokeAsync(this, LazyLoading, token); - } - } - public virtual async Task AddContainerAsync(TContainer container) { Containers.Add(container); diff --git a/src/Core/FileTime.Core/Providers/TopContainer.cs b/src/Core/FileTime.Core/Providers/TopContainer.cs index c1f6872..95815f8 100644 --- a/src/Core/FileTime.Core/Providers/TopContainer.cs +++ b/src/Core/FileTime.Core/Providers/TopContainer.cs @@ -36,12 +36,9 @@ namespace FileTime.Core.Providers public bool IsDestroyed => false; public bool IsExists => true; public bool AllowRecursiveDeletion => false; - - public bool UseLazyLoad => false; - - public bool LazyLoading => false; + public bool Loading => false; public bool CanHandleEscape => false; - public AsyncEventHandler LazyLoadingChanged { get; protected set; } = new(); + public AsyncEventHandler LoadingChanged { get; protected set; } = new(); public TopContainer(IEnumerable contentProviders) { @@ -83,5 +80,10 @@ namespace FileTime.Core.Providers public void Unload() { } public Task HandleEscape() => Task.FromResult(new ContainerEscapeResult(false)); + + public async Task RunWithLoading(Func func, CancellationToken token = default) + { + await func(token); + } } } \ No newline at end of file diff --git a/src/Core/FileTime.Core/Search/SearchContainer.cs b/src/Core/FileTime.Core/Search/SearchContainer.cs index 4d73196..5537c17 100644 --- a/src/Core/FileTime.Core/Search/SearchContainer.cs +++ b/src/Core/FileTime.Core/Search/SearchContainer.cs @@ -30,7 +30,6 @@ namespace FileTime.Core.Search _elementsReadOnly = _elements.AsReadOnly(); _items = _containers.Cast().Concat(_elements).ToList().AsReadOnly(); - UseLazyLoad = true; CanHandleEscape = true; CanDelete = SupportsDelete.False; } @@ -39,14 +38,14 @@ namespace FileTime.Core.Search { try { - LazyLoading = true; - await LazyLoadingChanged.InvokeAsync(this, LazyLoading, token); + Loading = true; + await LoadingChanged.InvokeAsync(this, Loading, token); await func(token); } finally { - LazyLoading = false; - await LazyLoadingChanged.InvokeAsync(this, LazyLoading, token); + Loading = false; + await LoadingChanged.InvokeAsync(this, Loading, token); } } diff --git a/src/Core/FileTime.Core/Timeline/TimeContainer.cs b/src/Core/FileTime.Core/Timeline/TimeContainer.cs index bab44cc..315f7c2 100644 --- a/src/Core/FileTime.Core/Timeline/TimeContainer.cs +++ b/src/Core/FileTime.Core/Timeline/TimeContainer.cs @@ -36,12 +36,9 @@ namespace FileTime.Core.Timeline public string? NativePath => FullName; public bool IsExists => true; public bool AllowRecursiveDeletion => true; - - public bool UseLazyLoad => false; - - public bool LazyLoading => false; + public bool Loading => false; public bool CanHandleEscape => false; - public AsyncEventHandler LazyLoadingChanged { get; protected set; } = new(); + public AsyncEventHandler LoadingChanged { get; protected set; } = new(); public TimeContainer(string name, IContainer parent, IContentProvider contentProvider, IContentProvider virtualContentProvider, PointInTime pointInTime) { @@ -139,5 +136,10 @@ namespace FileTime.Core.Timeline public void Destroy() => IsDestroyed = true; public void Unload() { } public Task HandleEscape() => Task.FromResult(new ContainerEscapeResult(false)); + + public async Task RunWithLoading(Func func, CancellationToken token = default) + { + await func(token); + } } } \ No newline at end of file diff --git a/src/GuiApp/FileTime.Avalonia/Application/TabContainer.cs b/src/GuiApp/FileTime.Avalonia/Application/TabContainer.cs index 3a73b6d..2b073d3 100644 --- a/src/GuiApp/FileTime.Avalonia/Application/TabContainer.cs +++ b/src/GuiApp/FileTime.Avalonia/Application/TabContainer.cs @@ -176,22 +176,30 @@ namespace FileTime.Avalonia.Application private async Task Tab_CurrentLocationChanged(object? sender, AsyncEventArgs e, CancellationToken token = default) { - var currentLocation = await Tab.GetCurrentLocation(token); - var parent = GenerateParent(currentLocation); - CurrentLocation = new ContainerViewModel(this, parent, currentLocation, ItemNameConverterService, AppState); - await CurrentLocation.Init(token: token); - - if (token.IsCancellationRequested) return; - - if (parent != null) + var oldCurrentLocation = CurrentLocation; + try { - parent.ChildrenToAdopt.Add(CurrentLocation); - Parent = parent; - await Parent.Init(token: token); + var currentLocation = await Tab.GetCurrentLocation(token); + var parent = GenerateParent(currentLocation); + CurrentLocation = new ContainerViewModel(this, parent, currentLocation, ItemNameConverterService, AppState); + await CurrentLocation.Init(token: token); + + if (token.IsCancellationRequested) return; + + if (parent != null) + { + parent.ChildrenToAdopt.Add(CurrentLocation); + Parent = parent; + await Parent.Init(token: token); + } + else + { + Parent = null; + } } - else + finally { - Parent = null; + oldCurrentLocation.Unload(unloadEvents: true); } } diff --git a/src/GuiApp/FileTime.Avalonia/Services/CommandHandlerService.cs b/src/GuiApp/FileTime.Avalonia/Services/CommandHandlerService.cs index cd6580a..47a3454 100644 --- a/src/GuiApp/FileTime.Avalonia/Services/CommandHandlerService.cs +++ b/src/GuiApp/FileTime.Avalonia/Services/CommandHandlerService.cs @@ -393,7 +393,7 @@ namespace FileTime.Avalonia.Services if (currentSelectedItems.Count == 1) { if ((await currentSelectedItems[0].ResolveAsync()) is IContainer container - && (await container.GetItems())?.Count > 0) + && (await container.GetItems())?.Count > 0 && container.AllowRecursiveDeletion) { askForDelete = true; questionText = $"The container '{container.Name}' is not empty. Proceed with delete?"; @@ -416,7 +416,7 @@ namespace FileTime.Avalonia.Services new AbsolutePath(currentSelectedItem) }; - if (currentSelectedItem is IContainer container && (await container.GetItems())?.Count > 0) + if (currentSelectedItem is IContainer container && (await container.GetItems())?.Count > 0 && container.AllowRecursiveDeletion) { askForDelete = true; questionText = $"The container '{container.Name}' is not empty. Proceed with delete?"; diff --git a/src/GuiApp/FileTime.Avalonia/ViewModels/ContainerViewModel.cs b/src/GuiApp/FileTime.Avalonia/ViewModels/ContainerViewModel.cs index 916ba85..a58183a 100644 --- a/src/GuiApp/FileTime.Avalonia/ViewModels/ContainerViewModel.cs +++ b/src/GuiApp/FileTime.Avalonia/ViewModels/ContainerViewModel.cs @@ -63,7 +63,7 @@ namespace FileTime.Avalonia.ViewModels public List ChildrenToAdopt { get; } = new List(); - public bool LazyLoading => _container.LazyLoading; + public bool Loading => _container.Loading; [PropertyInvalidate(nameof(IsSelected))] [PropertyInvalidate(nameof(IsAlternative))] @@ -144,7 +144,7 @@ namespace FileTime.Avalonia.ViewModels sizeContainer.SizeChanged.Add(UpdateSize); } Container.Refreshed.Add(Container_Refreshed); - Container.LazyLoadingChanged.Add(Container_LazyLoadingChanged); + Container.LoadingChanged.Add(Container_LoadingChanged); } private Task UpdateSize(object? sender, long? size, CancellationToken token) @@ -167,9 +167,9 @@ namespace FileTime.Avalonia.ViewModels await Refresh(false, false, token: token); } - private Task Container_LazyLoadingChanged(object? sender, bool lazyLoading, CancellationToken token = default) + private Task Container_LoadingChanged(object? sender, bool loading, CancellationToken token = default) { - OnPropertyChanged(nameof(LazyLoading)); + OnPropertyChanged(nameof(Loading)); return Task.CompletedTask; } @@ -335,7 +335,7 @@ namespace FileTime.Avalonia.ViewModels sizeContainer.SizeChanged.Remove(UpdateSize); } Container.Refreshed.Remove(Container_Refreshed); - Container.LazyLoadingChanged.Remove(Container_LazyLoadingChanged); + Container.LoadingChanged.Remove(Container_LoadingChanged); } _containers.Clear(); diff --git a/src/GuiApp/FileTime.Avalonia/Views/MainWindow.axaml b/src/GuiApp/FileTime.Avalonia/Views/MainWindow.axaml index 3a62205..37620ba 100644 --- a/src/GuiApp/FileTime.Avalonia/Views/MainWindow.axaml +++ b/src/GuiApp/FileTime.Avalonia/Views/MainWindow.axaml @@ -276,7 +276,7 @@ Fill="{DynamicResource ContentSeparatorBrush}" /> - + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "\\" : "/"; + + public async Task RemoveServerAsync(SmbServer server) + { + if(RootContainers?.Contains(server) == true) + { + RootContainers.Remove(server); + await RefreshAsync(); + } + } } } \ No newline at end of file diff --git a/src/Providers/FileTime.Providers.Smb/SmbServer.cs b/src/Providers/FileTime.Providers.Smb/SmbServer.cs index ad391da..b5f4eb7 100644 --- a/src/Providers/FileTime.Providers.Smb/SmbServer.cs +++ b/src/Providers/FileTime.Providers.Smb/SmbServer.cs @@ -16,6 +16,7 @@ namespace FileTime.Providers.Smb private ISMBClient? _client; private readonly object _clientGuard = new(); private bool _refreshingClient; + private readonly SmbContentProvider _contentProvider; private readonly IInputInterface _inputInterface; private readonly SmbClientContext _smbClientContext; @@ -26,6 +27,7 @@ namespace FileTime.Providers.Smb public SmbServer(string name, SmbContentProvider contentProvider, IInputInterface inputInterface, string? username = null, string? password = null) : base(contentProvider, contentProvider, name) { + _contentProvider = contentProvider; _inputInterface = inputInterface; _smbClientContext = new SmbClientContext(GetSmbClient, DisposeSmbClient); Username = username; @@ -49,9 +51,9 @@ namespace FileTime.Providers.Smb throw new NotSupportedException(); } - public override Task Delete(bool hardDelete = false) + public override async Task Delete(bool hardDelete = false) { - return Task.CompletedTask; + await _contentProvider.RemoveServerAsync(this); } async Task IContainer.GetByPath(string path, bool acceptDeepestMatch) @@ -78,7 +80,8 @@ namespace FileTime.Providers.Smb { try { - var shares = await _smbClientContext.RunWithSmbClientAsync((client) => client.ListShares(out var status), IsLoaded ? MAXRETRIES : 1); + var shares = new List(); + await RunWithLoading(async (_) => shares = await _smbClientContext.RunWithSmbClientAsync((client) => client.ListShares(out var status), IsLoaded ? MAXRETRIES : 1), token); return shares.Select(s => new SmbShare(s, Provider, this, _smbClientContext)); }