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(); 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) public ContainerSizeContainer(ContainerScanSnapshotProvider provider, IContainer parent, IContainer baseContainer, string? displayName = null) : base(provider, parent, baseContainer.Name)
{ {
_baseContainer = baseContainer; _baseContainer = baseContainer;
CanDelete = SupportsDelete.True;
AllowRecursiveDeletion = false; AllowRecursiveDeletion = false;
CanHandleEscape = true; CanHandleEscape = true;
if (displayName != null) if (displayName != null)
@@ -37,7 +38,13 @@ namespace FileTime.Core.ContainerSizeScanner
public override Task<IElement> CreateElementAsync(string name) => throw new NotSupportedException(); 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) public override async Task RefreshAsync(CancellationToken token = default)
{ {

View File

@@ -43,7 +43,7 @@ namespace FileTime.Core.ContainerSizeScanner
{ {
try 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 finally
{ {
@@ -93,7 +93,7 @@ namespace FileTime.Core.ContainerSizeScanner
{ {
return; 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<IContainer>?> GetContainers(CancellationToken token = default);
Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default); Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default);
bool AllowRecursiveDeletion { get; } bool AllowRecursiveDeletion { get; }
bool UseLazyLoad { get; } bool Loading { get; }
bool LazyLoading { get; }
bool CanHandleEscape { get; } bool CanHandleEscape { get; }
Task RefreshAsync(CancellationToken token = default); Task RefreshAsync(CancellationToken token = default);
@@ -50,11 +49,12 @@ namespace FileTime.Core.Models
void Unload(); void Unload();
Task<ContainerEscapeResult> HandleEscape(); Task<ContainerEscapeResult> HandleEscape();
Task RunWithLoading(Func<CancellationToken, Task> func, CancellationToken token = default);
bool IsLoaded { get; } bool IsLoaded { get; }
bool SupportsDirectoryLevelSoftDelete { get; } bool SupportsDirectoryLevelSoftDelete { get; }
AsyncEventHandler Refreshed { 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 IsExists => BaseContainer.IsExists;
public bool AllowRecursiveDeletion => BaseContainer.AllowRecursiveDeletion; public bool AllowRecursiveDeletion => BaseContainer.AllowRecursiveDeletion;
public bool UseLazyLoad => BaseContainer.UseLazyLoad; public bool Loading => BaseContainer.Loading;
public AsyncEventHandler<bool> LoadingChanged { get; protected set; } = new();
public bool LazyLoading => BaseContainer.LazyLoading;
public AsyncEventHandler<bool> LazyLoadingChanged { get; protected set; } = new();
public bool CanHandleEscape => BaseContainer.CanHandleEscape; public bool CanHandleEscape => BaseContainer.CanHandleEscape;
@@ -192,5 +190,7 @@ namespace FileTime.Core.Models
BaseContainer.Unload(); BaseContainer.Unload();
} }
public async Task<ContainerEscapeResult> HandleEscape() => await BaseContainer.HandleEscape(); 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 bool SupportsDirectoryLevelSoftDelete { get; protected set; }
public AsyncEventHandler Refreshed { get; protected set; } = new(); 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 string Name { get; protected set; }
public virtual string DisplayName { 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 virtual bool AllowRecursiveDeletion { get; protected set; }
public bool UseLazyLoad { get; protected set; } public bool Loading { get; protected set; }
public bool LazyLoading { get; protected set; }
public bool CanHandleEscape { get; protected set; } public bool CanHandleEscape { get; protected set; }
@@ -109,6 +107,21 @@ namespace FileTime.Core.Providers
return _items; 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 IContainer? GetParent() => _parent;
public virtual async Task<bool> IsExistsAsync(string name) 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(); _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) public virtual async Task AddContainerAsync(TContainer container)
{ {
Containers.Add(container); Containers.Add(container);

View File

@@ -36,12 +36,9 @@ namespace FileTime.Core.Providers
public bool IsDestroyed => false; public bool IsDestroyed => false;
public bool IsExists => true; public bool IsExists => true;
public bool AllowRecursiveDeletion => false; public bool AllowRecursiveDeletion => false;
public bool Loading => false;
public bool UseLazyLoad => false;
public bool LazyLoading => false;
public bool CanHandleEscape => 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) public TopContainer(IEnumerable<IContentProvider> contentProviders)
{ {
@@ -83,5 +80,10 @@ namespace FileTime.Core.Providers
public void Unload() { } public void Unload() { }
public Task<ContainerEscapeResult> HandleEscape() => Task.FromResult(new ContainerEscapeResult(false)); 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(); _elementsReadOnly = _elements.AsReadOnly();
_items = _containers.Cast<IItem>().Concat(_elements).ToList().AsReadOnly(); _items = _containers.Cast<IItem>().Concat(_elements).ToList().AsReadOnly();
UseLazyLoad = true;
CanHandleEscape = true; CanHandleEscape = true;
CanDelete = SupportsDelete.False; CanDelete = SupportsDelete.False;
} }
@@ -39,14 +38,14 @@ namespace FileTime.Core.Search
{ {
try try
{ {
LazyLoading = true; Loading = true;
await LazyLoadingChanged.InvokeAsync(this, LazyLoading, token); await LoadingChanged.InvokeAsync(this, Loading, token);
await func(token); await func(token);
} }
finally finally
{ {
LazyLoading = false; Loading = false;
await LazyLoadingChanged.InvokeAsync(this, LazyLoading, token); await LoadingChanged.InvokeAsync(this, Loading, token);
} }
} }

View File

@@ -36,12 +36,9 @@ namespace FileTime.Core.Timeline
public string? NativePath => FullName; public string? NativePath => FullName;
public bool IsExists => true; public bool IsExists => true;
public bool AllowRecursiveDeletion => true; public bool AllowRecursiveDeletion => true;
public bool Loading => false;
public bool UseLazyLoad => false;
public bool LazyLoading => false;
public bool CanHandleEscape => 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) 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 Destroy() => IsDestroyed = true;
public void Unload() { } public void Unload() { }
public Task<ContainerEscapeResult> HandleEscape() => Task.FromResult(new ContainerEscapeResult(false)); 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) private async Task Tab_CurrentLocationChanged(object? sender, AsyncEventArgs e, CancellationToken token = default)
{ {
var currentLocation = await Tab.GetCurrentLocation(token); var oldCurrentLocation = CurrentLocation;
var parent = GenerateParent(currentLocation); try
CurrentLocation = new ContainerViewModel(this, parent, currentLocation, ItemNameConverterService, AppState);
await CurrentLocation.Init(token: token);
if (token.IsCancellationRequested) return;
if (parent != null)
{ {
parent.ChildrenToAdopt.Add(CurrentLocation); var currentLocation = await Tab.GetCurrentLocation(token);
Parent = parent; var parent = GenerateParent(currentLocation);
await Parent.Init(token: token); 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 (currentSelectedItems.Count == 1)
{ {
if ((await currentSelectedItems[0].ResolveAsync()) is IContainer container if ((await currentSelectedItems[0].ResolveAsync()) is IContainer container
&& (await container.GetItems())?.Count > 0) && (await container.GetItems())?.Count > 0 && container.AllowRecursiveDeletion)
{ {
askForDelete = true; askForDelete = true;
questionText = $"The container '{container.Name}' is not empty. Proceed with delete?"; questionText = $"The container '{container.Name}' is not empty. Proceed with delete?";
@@ -416,7 +416,7 @@ namespace FileTime.Avalonia.Services
new AbsolutePath(currentSelectedItem) 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; askForDelete = true;
questionText = $"The container '{container.Name}' is not empty. Proceed with delete?"; 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 List<IItemViewModel> ChildrenToAdopt { get; } = new List<IItemViewModel>();
public bool LazyLoading => _container.LazyLoading; public bool Loading => _container.Loading;
[PropertyInvalidate(nameof(IsSelected))] [PropertyInvalidate(nameof(IsSelected))]
[PropertyInvalidate(nameof(IsAlternative))] [PropertyInvalidate(nameof(IsAlternative))]
@@ -144,7 +144,7 @@ namespace FileTime.Avalonia.ViewModels
sizeContainer.SizeChanged.Add(UpdateSize); sizeContainer.SizeChanged.Add(UpdateSize);
} }
Container.Refreshed.Add(Container_Refreshed); Container.Refreshed.Add(Container_Refreshed);
Container.LazyLoadingChanged.Add(Container_LazyLoadingChanged); Container.LoadingChanged.Add(Container_LoadingChanged);
} }
private Task UpdateSize(object? sender, long? size, CancellationToken token) private Task UpdateSize(object? sender, long? size, CancellationToken token)
@@ -167,9 +167,9 @@ namespace FileTime.Avalonia.ViewModels
await Refresh(false, false, token: token); 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; return Task.CompletedTask;
} }
@@ -335,7 +335,7 @@ namespace FileTime.Avalonia.ViewModels
sizeContainer.SizeChanged.Remove(UpdateSize); sizeContainer.SizeChanged.Remove(UpdateSize);
} }
Container.Refreshed.Remove(Container_Refreshed); Container.Refreshed.Remove(Container_Refreshed);
Container.LazyLoadingChanged.Remove(Container_LazyLoadingChanged); Container.LoadingChanged.Remove(Container_LoadingChanged);
} }
_containers.Clear(); _containers.Clear();

View File

@@ -276,7 +276,7 @@
Fill="{DynamicResource ContentSeparatorBrush}" /> Fill="{DynamicResource ContentSeparatorBrush}" />
<Grid Grid.Column="2" RowDefinitions="Auto,*"> <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"/> <Image Width="40" Height="40" Source="{SvgImage /Assets/loading.svg}" Classes="LoadingAnimation"/>
</Grid> </Grid>
<ListBox <ListBox

View File

@@ -95,5 +95,14 @@ namespace FileTime.Providers.Smb
} }
public static string GetNativePathSeparator() => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "\\" : "/"; 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 ISMBClient? _client;
private readonly object _clientGuard = new(); private readonly object _clientGuard = new();
private bool _refreshingClient; private bool _refreshingClient;
private readonly SmbContentProvider _contentProvider;
private readonly IInputInterface _inputInterface; private readonly IInputInterface _inputInterface;
private readonly SmbClientContext _smbClientContext; 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) public SmbServer(string name, SmbContentProvider contentProvider, IInputInterface inputInterface, string? username = null, string? password = null)
: base(contentProvider, contentProvider, name) : base(contentProvider, contentProvider, name)
{ {
_contentProvider = contentProvider;
_inputInterface = inputInterface; _inputInterface = inputInterface;
_smbClientContext = new SmbClientContext(GetSmbClient, DisposeSmbClient); _smbClientContext = new SmbClientContext(GetSmbClient, DisposeSmbClient);
Username = username; Username = username;
@@ -49,9 +51,9 @@ namespace FileTime.Providers.Smb
throw new NotSupportedException(); 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) async Task<IItem?> IContainer.GetByPath(string path, bool acceptDeepestMatch)
@@ -78,7 +80,8 @@ namespace FileTime.Providers.Smb
{ {
try 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)); return shares.Select(s => new SmbShare(s, Provider, this, _smbClientContext));
} }