Loading refactor, SizeContainer&SmbServer delete
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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?";
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user