Loading refactor, SizeContainer&SmbServer delete

This commit is contained in:
2022-02-23 23:49:22 +01:00
parent cef8e5de18
commit c8748644d2
16 changed files with 105 additions and 68 deletions

View File

@@ -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();
}
}
}
}

View File

@@ -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<IElement> 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)
{

View File

@@ -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);
}
}

View File

@@ -9,8 +9,7 @@ namespace FileTime.Core.Models
Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default);
Task<IReadOnlyList<IElement>?> 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<ContainerEscapeResult> HandleEscape();
Task RunWithLoading(Func<CancellationToken, Task> func, CancellationToken token = default);
bool IsLoaded { get; }
bool SupportsDirectoryLevelSoftDelete { get; }
AsyncEventHandler Refreshed { get; }
AsyncEventHandler<bool> LazyLoadingChanged { get; }
AsyncEventHandler<bool> LoadingChanged { get; }
}
}

View File

@@ -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<bool> LazyLoadingChanged { get; protected set; } = new();
public bool Loading => BaseContainer.Loading;
public AsyncEventHandler<bool> LoadingChanged { get; protected set; } = new();
public bool CanHandleEscape => BaseContainer.CanHandleEscape;
@@ -192,5 +190,7 @@ namespace FileTime.Core.Models
BaseContainer.Unload();
}
public async Task<ContainerEscapeResult> HandleEscape() => await BaseContainer.HandleEscape();
public async Task RunWithLoading(Func<CancellationToken, Task> func, CancellationToken token = default) => await BaseContainer.RunWithLoading(func, token);
}
}

View File

@@ -19,7 +19,7 @@ namespace FileTime.Core.Providers
public bool SupportsDirectoryLevelSoftDelete { get; protected set; }
public AsyncEventHandler Refreshed { get; protected set; } = new();
public AsyncEventHandler<bool> LazyLoadingChanged { get; protected set; } = new();
public AsyncEventHandler<bool> 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<CancellationToken, Task> 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<bool> IsExistsAsync(string name)

View File

@@ -25,21 +25,6 @@ namespace FileTime.Core.Providers
_items = Containers.Cast<IItem>().Concat(Elements).ToList().AsReadOnly();
}
public async Task RunWithLazyLoading(Func<CancellationToken, Task> 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);

View File

@@ -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<bool> LazyLoadingChanged { get; protected set; } = new();
public AsyncEventHandler<bool> LoadingChanged { get; protected set; } = new();
public TopContainer(IEnumerable<IContentProvider> contentProviders)
{
@@ -83,5 +80,10 @@ namespace FileTime.Core.Providers
public void Unload() { }
public Task<ContainerEscapeResult> HandleEscape() => Task.FromResult(new ContainerEscapeResult(false));
public async Task RunWithLoading(Func<CancellationToken, Task> func, CancellationToken token = default)
{
await func(token);
}
}
}

View File

@@ -30,7 +30,6 @@ namespace FileTime.Core.Search
_elementsReadOnly = _elements.AsReadOnly();
_items = _containers.Cast<IItem>().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);
}
}

View File

@@ -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<bool> LazyLoadingChanged { get; protected set; } = new();
public AsyncEventHandler<bool> 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<ContainerEscapeResult> HandleEscape() => Task.FromResult(new ContainerEscapeResult(false));
public async Task RunWithLoading(Func<CancellationToken, Task> func, CancellationToken token = default)
{
await func(token);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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?";

View File

@@ -63,7 +63,7 @@ namespace FileTime.Avalonia.ViewModels
public List<IItemViewModel> ChildrenToAdopt { get; } = new List<IItemViewModel>();
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();

View File

@@ -276,7 +276,7 @@
Fill="{DynamicResource ContentSeparatorBrush}" />
<Grid Grid.Column="2" RowDefinitions="Auto,*">
<Grid IsVisible="{Binding AppState.SelectedTab.CurrentLocation.LazyLoading}">
<Grid IsVisible="{Binding AppState.SelectedTab.CurrentLocation.Loading}">
<Image Width="40" Height="40" Source="{SvgImage /Assets/loading.svg}" Classes="LoadingAnimation"/>
</Grid>
<ListBox

View File

@@ -95,5 +95,14 @@ namespace FileTime.Providers.Smb
}
public static string GetNativePathSeparator() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "\\" : "/";
public async Task RemoveServerAsync(SmbServer server)
{
if(RootContainers?.Contains(server) == true)
{
RootContainers.Remove(server);
await RefreshAsync();
}
}
}
}

View File

@@ -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<IItem?> 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<string>();
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));
}