Using CancellationToken
This commit is contained in:
@@ -43,7 +43,7 @@ namespace FileTime.ConsoleUI.App.UI
|
|||||||
if (paneState == null) throw new Exception($"{nameof(paneState)} can not be null");
|
if (paneState == null) throw new Exception($"{nameof(paneState)} can not be null");
|
||||||
|
|
||||||
Tab = pane;
|
Tab = pane;
|
||||||
Tab.CurrentLocationChanged.Add((_, _) => { _currentDisplayStartY = 0; return Task.CompletedTask; });
|
Tab.CurrentLocationChanged.Add((_, _, _) => { _currentDisplayStartY = 0; return Task.CompletedTask; });
|
||||||
|
|
||||||
TabState = paneState;
|
TabState = paneState;
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ namespace FileTime.ConsoleUI.App.UI
|
|||||||
|
|
||||||
if (currentLocation.GetParent() is var parentContainer && parentContainer is not null)
|
if (currentLocation.GetParent() is var parentContainer && parentContainer is not null)
|
||||||
{
|
{
|
||||||
await parentContainer.Refresh();
|
await parentContainer.RefreshAsync();
|
||||||
|
|
||||||
await PrintColumn(
|
await PrintColumn(
|
||||||
currentVirtualContainer != null
|
currentVirtualContainer != null
|
||||||
@@ -96,7 +96,7 @@ namespace FileTime.ConsoleUI.App.UI
|
|||||||
|
|
||||||
if (token.IsCancellationRequested) return;
|
if (token.IsCancellationRequested) return;
|
||||||
|
|
||||||
await currentLocation.Refresh();
|
await currentLocation.RefreshAsync();
|
||||||
|
|
||||||
await CheckAndSetCurrentDisplayStartY();
|
await CheckAndSetCurrentDisplayStartY();
|
||||||
await PrintColumn(
|
await PrintColumn(
|
||||||
@@ -112,7 +112,7 @@ namespace FileTime.ConsoleUI.App.UI
|
|||||||
|
|
||||||
if (currentSelectedItem is IContainer selectedContainer)
|
if (currentSelectedItem is IContainer selectedContainer)
|
||||||
{
|
{
|
||||||
await selectedContainer.Refresh();
|
await selectedContainer.RefreshAsync();
|
||||||
|
|
||||||
selectedContainer = currentVirtualContainer != null
|
selectedContainer = currentVirtualContainer != null
|
||||||
? currentVirtualContainer.CloneVirtualChainFor(selectedContainer, v => v.IsTransitive)
|
? currentVirtualContainer.CloneVirtualChainFor(selectedContainer, v => v.IsTransitive)
|
||||||
|
|||||||
@@ -2,55 +2,68 @@
|
|||||||
{
|
{
|
||||||
public class AsyncEventHandler<TSender, TArg>
|
public class AsyncEventHandler<TSender, TArg>
|
||||||
{
|
{
|
||||||
private readonly List<Func<TSender, TArg, Task>> _handlers;
|
private readonly object _guard = new();
|
||||||
private readonly Action<Func<TSender, TArg, Task>> _add;
|
private readonly List<Func<TSender, TArg, CancellationToken, Task>> _handlers;
|
||||||
private readonly Action<Func<TSender, TArg, Task>> _remove;
|
private readonly Action<Func<TSender, TArg, CancellationToken, Task>> _add;
|
||||||
|
private readonly Action<Func<TSender, TArg, CancellationToken, Task>> _remove;
|
||||||
|
|
||||||
public IReadOnlyList<Func<TSender, TArg, Task>> Handlers { get; }
|
public IReadOnlyList<Func<TSender, TArg, CancellationToken, Task>> Handlers { get; }
|
||||||
|
|
||||||
public AsyncEventHandler(Action<Func<TSender, TArg, Task>>? add = null, Action<Func<TSender, TArg, Task>>? remove = null)
|
public AsyncEventHandler(Action<Func<TSender, TArg, CancellationToken, Task>>? add = null, Action<Func<TSender, TArg, CancellationToken, Task>>? remove = null)
|
||||||
{
|
{
|
||||||
_handlers = new List<Func<TSender, TArg, Task>>();
|
_handlers = new List<Func<TSender, TArg, CancellationToken, Task>>();
|
||||||
Handlers = _handlers.AsReadOnly();
|
Handlers = _handlers.AsReadOnly();
|
||||||
_add = add ?? AddInternal;
|
_add = add ?? AddInternal;
|
||||||
_remove = remove ?? RemoveInternal;
|
_remove = remove ?? RemoveInternal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(Func<TSender, TArg, Task> handler)
|
public void Add(Func<TSender, TArg, CancellationToken, Task> handler)
|
||||||
|
{
|
||||||
|
lock (_guard)
|
||||||
{
|
{
|
||||||
_add.Invoke(handler);
|
_add.Invoke(handler);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Remove(Func<TSender, TArg, Task> handler)
|
public void Remove(Func<TSender, TArg, CancellationToken, Task> handler)
|
||||||
|
{
|
||||||
|
lock (_guard)
|
||||||
{
|
{
|
||||||
_remove.Invoke(handler);
|
_remove.Invoke(handler);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void AddInternal(Func<TSender, TArg, Task> handler)
|
private void AddInternal(Func<TSender, TArg, CancellationToken, Task> handler)
|
||||||
{
|
{
|
||||||
_handlers.Add(handler);
|
_handlers.Add(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveInternal(Func<TSender, TArg, Task> handler)
|
private void RemoveInternal(Func<TSender, TArg, CancellationToken, Task> handler)
|
||||||
{
|
{
|
||||||
_handlers.Remove(handler);
|
_handlers.Remove(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task InvokeAsync(TSender sender, TArg args)
|
public async Task InvokeAsync(TSender sender, TArg args, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
foreach(var handler in _handlers)
|
List<Func<TSender, TArg, CancellationToken, Task>>? handlers;
|
||||||
|
lock (_guard)
|
||||||
{
|
{
|
||||||
await handler(sender, args);
|
handlers = _handlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var handler in handlers)
|
||||||
|
{
|
||||||
|
await handler(sender, args, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsyncEventHandler<TSender, TArg> operator +(AsyncEventHandler<TSender, TArg> obj, Func<TSender, TArg, Task> handler)
|
public static AsyncEventHandler<TSender, TArg> operator +(AsyncEventHandler<TSender, TArg> obj, Func<TSender, TArg, CancellationToken, Task> handler)
|
||||||
{
|
{
|
||||||
obj.Add(handler);
|
obj.Add(handler);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AsyncEventHandler<TSender, TArg> operator -(AsyncEventHandler<TSender, TArg> obj, Func<TSender, TArg, Task> handler)
|
public static AsyncEventHandler<TSender, TArg> operator -(AsyncEventHandler<TSender, TArg> obj, Func<TSender, TArg, CancellationToken, Task> handler)
|
||||||
{
|
{
|
||||||
obj.Remove(handler);
|
obj.Remove(handler);
|
||||||
return obj;
|
return obj;
|
||||||
@@ -58,11 +71,11 @@
|
|||||||
}
|
}
|
||||||
public class AsyncEventHandler<TArg> : AsyncEventHandler<object?, TArg>
|
public class AsyncEventHandler<TArg> : AsyncEventHandler<object?, TArg>
|
||||||
{
|
{
|
||||||
public AsyncEventHandler(Action<Func<object?, TArg, Task>>? add = null, Action<Func<object?, TArg, Task>>? remove = null) : base(add, remove) { }
|
public AsyncEventHandler(Action<Func<object?, TArg, CancellationToken, Task>>? add = null, Action<Func<object?, TArg, CancellationToken, Task>>? remove = null) : base(add, remove) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AsyncEventHandler : AsyncEventHandler<AsyncEventArgs>
|
public class AsyncEventHandler : AsyncEventHandler<AsyncEventArgs>
|
||||||
{
|
{
|
||||||
public AsyncEventHandler(Action<Func<object?, AsyncEventArgs, Task>>? add = null, Action<Func<object?, AsyncEventArgs, Task>>? remove = null) : base(add, remove) { }
|
public AsyncEventHandler(Action<Func<object?, AsyncEventArgs, CancellationToken, Task>>? add = null, Action<Func<object?, AsyncEventArgs, CancellationToken, Task>>? remove = null) : base(add, remove) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ namespace FileTime.Core.Components
|
|||||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||||
private string? _lastPath;
|
private string? _lastPath;
|
||||||
|
|
||||||
|
private readonly object _guardSetCurrentSelectedItemCTS = new object();
|
||||||
|
private CancellationTokenSource? _setCurrentSelectedItemCTS;
|
||||||
|
|
||||||
public int CurrentSelectedIndex { get; private set; }
|
public int CurrentSelectedIndex { get; private set; }
|
||||||
|
|
||||||
public AsyncEventHandler CurrentLocationChanged = new();
|
public AsyncEventHandler CurrentLocationChanged = new();
|
||||||
@@ -21,7 +24,7 @@ namespace FileTime.Core.Components
|
|||||||
await SetCurrentLocation(currentPath);
|
await SetCurrentLocation(currentPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<IContainer> GetCurrentLocation()
|
public Task<IContainer> GetCurrentLocation(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
return Task.FromResult(_currentLocation);
|
return Task.FromResult(_currentLocation);
|
||||||
}
|
}
|
||||||
@@ -49,7 +52,7 @@ namespace FileTime.Core.Components
|
|||||||
return Task.FromResult(_currentSelectedItem);
|
return Task.FromResult(_currentSelectedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SetCurrentSelectedItem(IItem? value)
|
public async Task SetCurrentSelectedItem(IItem? value, bool secondary = false)
|
||||||
{
|
{
|
||||||
if (_currentSelectedItem != value)
|
if (_currentSelectedItem != value)
|
||||||
{
|
{
|
||||||
@@ -63,10 +66,22 @@ namespace FileTime.Core.Components
|
|||||||
if (itemToSelect == null) throw new IndexOutOfRangeException("Provided item does not exists in the current container.");
|
if (itemToSelect == null) throw new IndexOutOfRangeException("Provided item does not exists in the current container.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CancellationToken newToken;
|
||||||
|
lock (_guardSetCurrentSelectedItemCTS)
|
||||||
|
{
|
||||||
|
_setCurrentSelectedItemCTS?.Cancel();
|
||||||
|
_setCurrentSelectedItemCTS = new CancellationTokenSource();
|
||||||
|
newToken = _setCurrentSelectedItemCTS.Token;
|
||||||
|
}
|
||||||
|
|
||||||
_currentSelectedItem = itemToSelect;
|
_currentSelectedItem = itemToSelect;
|
||||||
_lastPath = GetCommonPath(_lastPath, itemToSelect?.FullName);
|
_lastPath = GetCommonPath(_lastPath, itemToSelect?.FullName);
|
||||||
CurrentSelectedIndex = await GetItemIndex(itemToSelect);
|
|
||||||
await CurrentSelectedItemChanged.InvokeAsync(this, AsyncEventArgs.Empty);
|
var newCurrentSelectedIndex = await GetItemIndex(itemToSelect, newToken);
|
||||||
|
if (newToken.IsCancellationRequested) return;
|
||||||
|
CurrentSelectedIndex = newCurrentSelectedIndex;
|
||||||
|
|
||||||
|
await CurrentSelectedItemChanged.InvokeAsync(this, AsyncEventArgs.Empty, newToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public async Task<IItem?> GetItemByLastPath(IContainer? container = null)
|
public async Task<IItem?> GetItemByLastPath(IContainer? container = null)
|
||||||
@@ -85,21 +100,16 @@ namespace FileTime.Core.Components
|
|||||||
|
|
||||||
var itemNameToSelect = _lastPath
|
var itemNameToSelect = _lastPath
|
||||||
.Split(Constants.SeparatorChar)
|
.Split(Constants.SeparatorChar)
|
||||||
.Skip(
|
.Skip((containerFullName?.Split(Constants.SeparatorChar).Length) ?? 0)
|
||||||
containerFullName == null
|
|
||||||
? 0
|
|
||||||
: containerFullName
|
|
||||||
.Split(Constants.SeparatorChar)
|
|
||||||
.Count())
|
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
return (await container.GetItems())?.FirstOrDefault(i => i.Name == itemNameToSelect);
|
return (await container.GetItems())?.FirstOrDefault(i => i.Name == itemNameToSelect);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetCommonPath(string? oldPath, string? newPath)
|
private static string GetCommonPath(string? oldPath, string? newPath)
|
||||||
{
|
{
|
||||||
var oldPathParts = oldPath?.Split(Constants.SeparatorChar) ?? new string[0];
|
var oldPathParts = oldPath?.Split(Constants.SeparatorChar) ?? Array.Empty<string>();
|
||||||
var newPathParts = newPath?.Split(Constants.SeparatorChar) ?? new string[0];
|
var newPathParts = newPath?.Split(Constants.SeparatorChar) ?? Array.Empty<string>();
|
||||||
|
|
||||||
var commonPathParts = new List<string>();
|
var commonPathParts = new List<string>();
|
||||||
|
|
||||||
@@ -126,13 +136,13 @@ namespace FileTime.Core.Components
|
|||||||
return string.Join(Constants.SeparatorChar, commonPathParts);
|
return string.Join(Constants.SeparatorChar, commonPathParts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleCurrentLocationRefresh(object? sender, AsyncEventArgs e)
|
private async Task HandleCurrentLocationRefresh(object? sender, AsyncEventArgs e, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var currentSelectedName = (await GetCurrentSelectedItem())?.FullName ?? (await GetItemByLastPath())?.FullName;
|
var currentSelectedName = (await GetCurrentSelectedItem())?.FullName ?? (await GetItemByLastPath())?.FullName;
|
||||||
var currentLocationItems = (await (await GetCurrentLocation()).GetItems())!;
|
var currentLocationItems = (await (await GetCurrentLocation(token)).GetItems(token))!;
|
||||||
if (currentSelectedName != null)
|
if (currentSelectedName != null)
|
||||||
{
|
{
|
||||||
await SetCurrentSelectedItem(currentLocationItems.FirstOrDefault(i => i.FullName == currentSelectedName) ?? currentLocationItems.FirstOrDefault());
|
await SetCurrentSelectedItem(currentLocationItems.FirstOrDefault(i => i.FullName == currentSelectedName) ?? currentLocationItems[0]);
|
||||||
}
|
}
|
||||||
else if (currentLocationItems.Count > 0)
|
else if (currentLocationItems.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -184,7 +194,7 @@ namespace FileTime.Core.Components
|
|||||||
|
|
||||||
if (await GetCurrentSelectedItem() != null)
|
if (await GetCurrentSelectedItem() != null)
|
||||||
{
|
{
|
||||||
(await GetCurrentLocation())?.Refresh();
|
(await GetCurrentLocation())?.RefreshAsync();
|
||||||
|
|
||||||
IItem? newSelectedItem = null;
|
IItem? newSelectedItem = null;
|
||||||
foreach (var item in currentPossibleItems)
|
foreach (var item in currentPossibleItems)
|
||||||
@@ -272,11 +282,12 @@ namespace FileTime.Core.Components
|
|||||||
|
|
||||||
public async Task OpenContainer(IContainer container) => await SetCurrentLocation(container);
|
public async Task OpenContainer(IContainer container) => await SetCurrentLocation(container);
|
||||||
|
|
||||||
private async Task<int> GetItemIndex(IItem? item)
|
private async Task<int> GetItemIndex(IItem? item, CancellationToken token)
|
||||||
{
|
{
|
||||||
if (item == null) return -1;
|
if (item == null) return -1;
|
||||||
var currentLocationItems = (await (await GetCurrentLocation()).GetItems())!;
|
var currentLocationItems = (await (await GetCurrentLocation(token)).GetItems(token))!;
|
||||||
|
|
||||||
|
if (token.IsCancellationRequested) return -1;
|
||||||
for (var i = 0; i < currentLocationItems.Count; i++)
|
for (var i = 0; i < currentLocationItems.Count; i++)
|
||||||
{
|
{
|
||||||
if (currentLocationItems[i] == item) return i;
|
if (currentLocationItems[i] == item) return i;
|
||||||
|
|||||||
@@ -9,7 +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);
|
||||||
|
|
||||||
Task Refresh();
|
Task RefreshAsync(CancellationToken token = default);
|
||||||
Task<IItem?> GetByPath(string path, bool acceptDeepestMatch = false);
|
Task<IItem?> GetByPath(string path, bool acceptDeepestMatch = false);
|
||||||
Task<IContainer> CreateContainer(string name);
|
Task<IContainer> CreateContainer(string name);
|
||||||
Task<IElement> CreateElement(string name);
|
Task<IElement> CreateElement(string name);
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ namespace FileTime.Core.Models
|
|||||||
|
|
||||||
public AsyncEventHandler Refreshed { get; }
|
public AsyncEventHandler Refreshed { get; }
|
||||||
|
|
||||||
private void RefreshAddBase(Func<object?, AsyncEventArgs, Task> handler)
|
private void RefreshAddBase(Func<object?, AsyncEventArgs, CancellationToken, Task> handler)
|
||||||
{
|
{
|
||||||
BaseContainer.Refreshed.Add(handler);
|
BaseContainer.Refreshed.Add(handler);
|
||||||
}
|
}
|
||||||
private void RefreshRemoveBase(Func<object?, AsyncEventArgs, Task> handler)
|
private void RefreshRemoveBase(Func<object?, AsyncEventArgs, CancellationToken, Task> handler)
|
||||||
{
|
{
|
||||||
BaseContainer.Refreshed.Add(handler);
|
BaseContainer.Refreshed.Add(handler);
|
||||||
}
|
}
|
||||||
@@ -67,10 +67,10 @@ namespace FileTime.Core.Models
|
|||||||
await InitItems();
|
await InitItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task InitItems()
|
private async Task InitItems(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
Containers = _containerTransformators.Aggregate((await BaseContainer.GetContainers())?.AsEnumerable(), (a, t) => t(a!))?.ToList()?.AsReadOnly();
|
Containers = _containerTransformators.Aggregate((await BaseContainer.GetContainers(token))?.AsEnumerable(), (a, t) => t(a!))?.ToList()?.AsReadOnly();
|
||||||
Elements = _elementTransformators.Aggregate((await BaseContainer.GetElements())?.AsEnumerable(), (a, t) => t(a!))?.ToList()?.AsReadOnly();
|
Elements = _elementTransformators.Aggregate((await BaseContainer.GetElements(token))?.AsEnumerable(), (a, t) => t(a!))?.ToList()?.AsReadOnly();
|
||||||
|
|
||||||
Items = (Elements != null
|
Items = (Elements != null
|
||||||
? Containers?.Cast<IItem>().Concat(Elements)
|
? Containers?.Cast<IItem>().Concat(Elements)
|
||||||
@@ -82,10 +82,10 @@ namespace FileTime.Core.Models
|
|||||||
|
|
||||||
public IContainer? GetParent() => BaseContainer.GetParent();
|
public IContainer? GetParent() => BaseContainer.GetParent();
|
||||||
|
|
||||||
public async Task Refresh()
|
public async Task RefreshAsync(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
await BaseContainer.Refresh();
|
await BaseContainer.RefreshAsync(token);
|
||||||
await InitItems();
|
await InitItems(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IContainer GetRealContainer() =>
|
public IContainer GetRealContainer() =>
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace FileTime.Core.Providers
|
|||||||
|
|
||||||
public Task<bool> IsExists(string name) => throw new NotImplementedException();
|
public Task<bool> IsExists(string name) => throw new NotImplementedException();
|
||||||
|
|
||||||
public async Task Refresh() => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty);
|
public async Task RefreshAsync(CancellationToken token = default) => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty);
|
||||||
|
|
||||||
public Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default) => Task.FromResult(_items);
|
public Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default) => Task.FromResult(_items);
|
||||||
public Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default) => Task.FromResult(_containers);
|
public Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default) => Task.FromResult(_containers);
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ namespace FileTime.Core.Timeline
|
|||||||
|
|
||||||
public async Task<bool> IsExists(string name) => (await GetItems())?.Any(i => i.Name == name) ?? false;
|
public async Task<bool> IsExists(string name) => (await GetItems())?.Any(i => i.Name == name) ?? false;
|
||||||
|
|
||||||
public async Task Refresh() => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty);
|
public async Task RefreshAsync(CancellationToken token = default) => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty, token);
|
||||||
|
|
||||||
public Task Rename(string newName) => Task.CompletedTask;
|
public Task Rename(string newName) => Task.CompletedTask;
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ namespace FileTime.Core.Timeline
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task Refresh() => Task.CompletedTask;
|
public Task RefreshAsync(CancellationToken token = default) => Task.CompletedTask;
|
||||||
|
|
||||||
public Task Rename(string newName) => throw new NotSupportedException();
|
public Task Rename(string newName) => throw new NotSupportedException();
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using FileTime.App.Core.Tab;
|
using FileTime.App.Core.Tab;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace FileTime.Avalonia.Application
|
namespace FileTime.Avalonia.Application
|
||||||
{
|
{
|
||||||
@@ -71,12 +72,13 @@ namespace FileTime.Avalonia.Application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TabItemMarked(TabState tabState, AbsolutePath item)
|
private async Task TabItemMarked(TabState tabState, AbsolutePath item, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var tabContainer = Tabs.FirstOrDefault(t => t.TabState == tabState);
|
var tabContainer = Tabs.FirstOrDefault(t => t.TabState == tabState);
|
||||||
if (tabContainer != null)
|
if (tabContainer != null)
|
||||||
{
|
{
|
||||||
var item2 = (await tabContainer.CurrentLocation.GetItems()).FirstOrDefault(i => i.Item.FullName == item.Path);
|
var item2 = (await tabContainer.CurrentLocation.GetItems(token)).FirstOrDefault(i => i.Item.FullName == item.Path);
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
if (item2 != null)
|
if (item2 != null)
|
||||||
{
|
{
|
||||||
item2.IsMarked = true;
|
item2.IsMarked = true;
|
||||||
@@ -84,12 +86,13 @@ namespace FileTime.Avalonia.Application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task TabItemUnmarked(TabState tabState, AbsolutePath item)
|
private async Task TabItemUnmarked(TabState tabState, AbsolutePath item, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var tabContainer = Tabs.FirstOrDefault(t => t.TabState == tabState);
|
var tabContainer = Tabs.FirstOrDefault(t => t.TabState == tabState);
|
||||||
if (tabContainer != null)
|
if (tabContainer != null)
|
||||||
{
|
{
|
||||||
var item2 = (await tabContainer.CurrentLocation.GetItems()).FirstOrDefault(i => i.Item.FullName == item.Path);
|
var item2 = (await tabContainer.CurrentLocation.GetItems(token)).FirstOrDefault(i => i.Item.FullName == item.Path);
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
if (item2 != null)
|
if (item2 != null)
|
||||||
{
|
{
|
||||||
item2.IsMarked = false;
|
item2.IsMarked = false;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FileTime.Avalonia.ViewModels;
|
using FileTime.Avalonia.ViewModels;
|
||||||
|
|
||||||
@@ -5,6 +6,6 @@ namespace FileTime.Avalonia.Application
|
|||||||
{
|
{
|
||||||
public interface INewItemProcessor
|
public interface INewItemProcessor
|
||||||
{
|
{
|
||||||
Task UpdateMarkedItems(ContainerViewModel containerViewModel);
|
Task UpdateMarkedItems(ContainerViewModel containerViewModel, CancellationToken token = default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FileTime.App.Core.Tab;
|
using FileTime.App.Core.Tab;
|
||||||
using System.Collections.Generic;
|
using System.Threading;
|
||||||
|
|
||||||
namespace FileTime.Avalonia.Application
|
namespace FileTime.Avalonia.Application
|
||||||
{
|
{
|
||||||
@@ -40,18 +40,27 @@ namespace FileTime.Avalonia.Application
|
|||||||
|
|
||||||
private IItemViewModel? _selectedItem;
|
private IItemViewModel? _selectedItem;
|
||||||
|
|
||||||
|
[Obsolete($"Use {nameof(SetSelectedItemAsync)} instead.")]
|
||||||
public IItemViewModel? SelectedItem
|
public IItemViewModel? SelectedItem
|
||||||
{
|
{
|
||||||
get => _selectedItem;
|
get => _selectedItem;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (_selectedItem != value)// && value != null
|
if (value != null)
|
||||||
|
{
|
||||||
|
SetSelectedItemAsync(value, true).Wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetSelectedItemAsync(IItemViewModel? value, bool fromDataBinding = false)
|
||||||
|
{
|
||||||
|
if (_selectedItem != value)
|
||||||
{
|
{
|
||||||
_selectedItem = value;
|
_selectedItem = value;
|
||||||
|
|
||||||
OnPropertyChanged("SelectedItem");
|
OnPropertyChanged(nameof(SelectedItem));
|
||||||
SelectedItemChanged().Wait();
|
await Tab.SetCurrentSelectedItem(SelectedItem?.Item, fromDataBinding);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,18 +105,20 @@ namespace FileTime.Avalonia.Application
|
|||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Tab_CurrentLocationChanged(object? sender, AsyncEventArgs e)
|
private async Task Tab_CurrentLocationChanged(object? sender, AsyncEventArgs e, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var currentLocation = await Tab.GetCurrentLocation();
|
var currentLocation = await Tab.GetCurrentLocation(token);
|
||||||
var parent = GenerateParent(currentLocation);
|
var parent = GenerateParent(currentLocation);
|
||||||
CurrentLocation = new ContainerViewModel(this, parent, currentLocation, ItemNameConverterService);
|
CurrentLocation = new ContainerViewModel(this, parent, currentLocation, ItemNameConverterService);
|
||||||
await CurrentLocation.Init();
|
await CurrentLocation.Init(token: token);
|
||||||
|
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
|
|
||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
parent.ChildrenToAdopt.Add(CurrentLocation);
|
parent.ChildrenToAdopt.Add(CurrentLocation);
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
await Parent.Init();
|
await Parent.Init(token: token);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -115,42 +126,47 @@ namespace FileTime.Avalonia.Application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Tab_CurrentSelectedItemChanged(object? sender, AsyncEventArgs e)
|
private async Task Tab_CurrentSelectedItemChanged(object? sender, AsyncEventArgs e, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
await UpdateCurrentSelectedItem();
|
await UpdateCurrentSelectedItem(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateCurrentSelectedItem()
|
public async Task UpdateCurrentSelectedItem(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var tabCurrentSelectenItem = await Tab.GetCurrentSelectedItem();
|
var tabCurrentSelectenItem = await Tab.GetCurrentSelectedItem();
|
||||||
|
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
|
|
||||||
IItemViewModel? currentSelectenItem = null;
|
IItemViewModel? currentSelectenItem = null;
|
||||||
if (tabCurrentSelectenItem == null)
|
if (tabCurrentSelectenItem == null)
|
||||||
{
|
{
|
||||||
SelectedItem = null;
|
await SetSelectedItemAsync(null);
|
||||||
ChildContainer = null;
|
ChildContainer = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
currentSelectenItem = (await _currentLocation.GetItems()).FirstOrDefault(i => i.Item.Name == tabCurrentSelectenItem.Name);
|
currentSelectenItem = (await _currentLocation.GetItems(token)).FirstOrDefault(i => i.Item.Name == tabCurrentSelectenItem.Name);
|
||||||
if (currentSelectenItem is ContainerViewModel currentSelectedContainer)
|
if (currentSelectenItem is ContainerViewModel currentSelectedContainer)
|
||||||
{
|
{
|
||||||
SelectedItem = currentSelectedContainer;
|
await SetSelectedItemAsync(currentSelectedContainer);
|
||||||
ChildContainer = currentSelectedContainer;
|
ChildContainer = currentSelectedContainer;
|
||||||
}
|
}
|
||||||
else if (currentSelectenItem is ElementViewModel element)
|
else if (currentSelectenItem is ElementViewModel element)
|
||||||
{
|
{
|
||||||
SelectedItem = element;
|
await SetSelectedItemAsync(element);
|
||||||
ChildContainer = null;
|
ChildContainer = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SelectedItem = null;
|
await SetSelectedItemAsync(null);
|
||||||
ChildContainer = null;
|
ChildContainer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
|
|
||||||
var items = await _currentLocation.GetItems();
|
var items = await _currentLocation.GetItems();
|
||||||
if (items?.Count > 0)
|
if (items?.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -173,6 +189,7 @@ namespace FileTime.Avalonia.Application
|
|||||||
var child = item;
|
var child = item;
|
||||||
while (child is ContainerViewModel containerViewModel && containerViewModel.Container.IsLoaded)
|
while (child is ContainerViewModel containerViewModel && containerViewModel.Container.IsLoaded)
|
||||||
{
|
{
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
var activeChildItem = await Tab.GetItemByLastPath(containerViewModel.Container);
|
var activeChildItem = await Tab.GetItemByLastPath(containerViewModel.Container);
|
||||||
child = (await containerViewModel.GetItems()).FirstOrDefault(i => i.Item == activeChildItem);
|
child = (await containerViewModel.GetItems()).FirstOrDefault(i => i.Item == activeChildItem);
|
||||||
if (child != null)
|
if (child != null)
|
||||||
@@ -206,15 +223,6 @@ namespace FileTime.Avalonia.Application
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SelectedItemChanged()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await Tab.SetCurrentSelectedItem(SelectedItem?.Item);
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task SetCurrentSelectedItem(IItem newItem)
|
public async Task SetCurrentSelectedItem(IItem newItem)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -309,13 +317,14 @@ namespace FileTime.Avalonia.Application
|
|||||||
await _tabState.MakrCurrentItem();
|
await _tabState.MakrCurrentItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateMarkedItems(ContainerViewModel containerViewModel)
|
public async Task UpdateMarkedItems(ContainerViewModel containerViewModel, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (containerViewModel == CurrentLocation && containerViewModel.Container.IsLoaded)
|
if (containerViewModel == CurrentLocation && containerViewModel.Container.IsLoaded)
|
||||||
{
|
{
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
var selectedItems = TabState.GetCurrentMarkedItems(containerViewModel.Container);
|
var selectedItems = TabState.GetCurrentMarkedItems(containerViewModel.Container);
|
||||||
|
|
||||||
foreach (var item in await containerViewModel.GetItems())
|
foreach (var item in await containerViewModel.GetItems(token))
|
||||||
{
|
{
|
||||||
item.IsMarked = selectedItems.Any(c => c.Path == item.Item.FullName);
|
item.IsMarked = selectedItems.Any(c => c.Path == item.Item.FullName);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FileTime.Avalonia.Application;
|
using FileTime.Avalonia.Application;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace FileTime.Avalonia.ViewModels
|
namespace FileTime.Avalonia.ViewModels
|
||||||
{
|
{
|
||||||
@@ -130,21 +131,22 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
|
|
||||||
public void InvalidateDisplayName() => OnPropertyChanged(nameof(DisplayName));
|
public void InvalidateDisplayName() => OnPropertyChanged(nameof(DisplayName));
|
||||||
|
|
||||||
public async Task Init(bool initializeChildren = true)
|
public async Task Init(bool initializeChildren = true, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
await Refresh(initializeChildren);
|
await Refresh(initializeChildren, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task Container_Refreshed(object? sender, AsyncEventArgs e)
|
private async Task Container_Refreshed(object? sender, AsyncEventArgs e, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
await Refresh(false);
|
await Refresh(false, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete($"Use the parametrizable version of {nameof(Refresh)}.")]
|
||||||
private async Task Refresh()
|
private async Task Refresh()
|
||||||
{
|
{
|
||||||
await Refresh(true);
|
await Refresh(true);
|
||||||
}
|
}
|
||||||
private async Task Refresh(bool initializeChildren)
|
private async Task Refresh(bool initializeChildren, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_isRefreshing) return;
|
if (_isRefreshing) return;
|
||||||
|
|
||||||
@@ -157,6 +159,9 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
|
|
||||||
var containers = (await _container.GetContainers())!.Select(c => AdoptOrReuseOrCreateItem(c, (c2) => new ContainerViewModel(_newItemProcessor, this, c2, ItemNameConverterService))).ToList();
|
var containers = (await _container.GetContainers())!.Select(c => AdoptOrReuseOrCreateItem(c, (c2) => new ContainerViewModel(_newItemProcessor, this, c2, ItemNameConverterService))).ToList();
|
||||||
var elements = (await _container.GetElements())!.Select(e => AdoptOrReuseOrCreateItem(e, (e2) => new ElementViewModel(e2, this, ItemNameConverterService))).ToList();
|
var elements = (await _container.GetElements())!.Select(e => AdoptOrReuseOrCreateItem(e, (e2) => new ElementViewModel(e2, this, ItemNameConverterService))).ToList();
|
||||||
|
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
|
|
||||||
Exceptions = new List<Exception>(_container.Exceptions);
|
Exceptions = new List<Exception>(_container.Exceptions);
|
||||||
|
|
||||||
foreach (var containerToRemove in _containers.Except(containers))
|
foreach (var containerToRemove in _containers.Except(containers))
|
||||||
@@ -168,7 +173,8 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
{
|
{
|
||||||
foreach (var container in containers)
|
foreach (var container in containers)
|
||||||
{
|
{
|
||||||
await container.Init(false);
|
if (token.IsCancellationRequested) return;
|
||||||
|
await container.Init(false, token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,21 +226,21 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
_items = new ObservableCollection<IItemViewModel>();
|
_items = new ObservableCollection<IItemViewModel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ObservableCollection<ContainerViewModel>> GetContainers()
|
public async Task<ObservableCollection<ContainerViewModel>> GetContainers(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (!_isInitialized) await Task.Run(Refresh);
|
if (!_isInitialized) await Task.Run(async () => await Refresh(false, token), token);
|
||||||
return _containers;
|
return _containers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ObservableCollection<ElementViewModel>> GetElements()
|
public async Task<ObservableCollection<ElementViewModel>> GetElements(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (!_isInitialized) await Task.Run(Refresh);
|
if (!_isInitialized) await Task.Run(async () => await Refresh(false, token), token);
|
||||||
return _elements;
|
return _elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ObservableCollection<IItemViewModel>> GetItems()
|
public async Task<ObservableCollection<IItemViewModel>> GetItems(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (!_isInitialized) await Task.Run(Refresh);
|
if (!_isInitialized) await Task.Run(async () => await Refresh(false, token), token);
|
||||||
return _items;
|
return _items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -605,7 +605,7 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
|
|
||||||
private async Task RefreshCurrentLocation()
|
private async Task RefreshCurrentLocation()
|
||||||
{
|
{
|
||||||
await AppState.SelectedTab.CurrentLocation.Container.Refresh();
|
await AppState.SelectedTab.CurrentLocation.Container.RefreshAsync();
|
||||||
await AppState.SelectedTab.UpdateCurrentSelectedItem();
|
await AppState.SelectedTab.UpdateCurrentSelectedItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,7 +640,7 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
var possibleContainer = await contentProvider.GetByPath(path);
|
var possibleContainer = await contentProvider.GetByPath(path);
|
||||||
if (possibleContainer is IContainer container)
|
if (possibleContainer is IContainer container)
|
||||||
{
|
{
|
||||||
AppState.SelectedTab.OpenContainer(container).Wait();
|
await AppState.SelectedTab.OpenContainer(container);
|
||||||
}
|
}
|
||||||
//TODO: multiple possible content provider handler
|
//TODO: multiple possible content provider handler
|
||||||
return;
|
return;
|
||||||
@@ -873,7 +873,7 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
|
|
||||||
var selectedItemName = AppState.SelectedTab.SelectedItem?.Item.Name;
|
var selectedItemName = AppState.SelectedTab.SelectedItem?.Item.Name;
|
||||||
var currentLocationItems = await AppState.SelectedTab.CurrentLocation.GetItems();
|
var currentLocationItems = await AppState.SelectedTab.CurrentLocation.GetItems();
|
||||||
if (currentLocationItems.FirstOrDefault(i => i.Item.Name.ToLower() == AppState.RapidTravelText.ToLower()) is IItemViewModel matchItem)
|
if (currentLocationItems.FirstOrDefault(i => string.Equals(i.Item.Name, AppState.RapidTravelText, StringComparison.OrdinalIgnoreCase)) is IItemViewModel matchItem)
|
||||||
{
|
{
|
||||||
await AppState.SelectedTab.SetCurrentSelectedItem(matchItem.Item);
|
await AppState.SelectedTab.SetCurrentSelectedItem(matchItem.Item);
|
||||||
}
|
}
|
||||||
@@ -882,7 +882,6 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
await AppState.SelectedTab.MoveCursorToFirst();
|
await AppState.SelectedTab.MoveCursorToFirst();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -899,7 +898,7 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
}
|
}
|
||||||
private void ReadInputs(List<Core.Interactions.InputElement> inputs, Func<Task> inputHandler)
|
private void ReadInputs(List<Core.Interactions.InputElement> inputs, Func<Task> inputHandler)
|
||||||
{
|
{
|
||||||
Inputs = inputs.Select(i => new InputElementWrapper(i, i.DefaultValue)).ToList();
|
Inputs = inputs.ConvertAll(i => new InputElementWrapper(i, i.DefaultValue));
|
||||||
_inputHandler = inputHandler;
|
_inputHandler = inputHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AsyncEvent;
|
using AsyncEvent;
|
||||||
using FileTime.Core.Command;
|
using FileTime.Core.Command;
|
||||||
@@ -27,7 +28,7 @@ namespace FileTime.Avalonia.ViewModels
|
|||||||
_commandTimeState.Command.ProgressChanged.Add(HandleProgressChange);
|
_commandTimeState.Command.ProgressChanged.Add(HandleProgressChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task HandleProgressChange(object? sender, AsyncEventArgs e)
|
private Task HandleProgressChange(object? sender, AsyncEventArgs e, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
Progress = _commandTimeState.Command.Progress;
|
Progress = _commandTimeState.Command.Progress;
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ namespace FileTime.Avalonia.Views
|
|||||||
&& sender is StyledElement control
|
&& sender is StyledElement control
|
||||||
&& control.DataContext is PlaceInfo placeInfo)
|
&& control.DataContext is PlaceInfo placeInfo)
|
||||||
{
|
{
|
||||||
ViewModel.OpenContainer(placeInfo.Container).Wait();
|
ViewModel.OpenContainer(placeInfo.Container);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ namespace FileTime.Providers.Local
|
|||||||
return remainingPath.Length == 0 ? rootContainer : await rootContainer.GetByPath(remainingPath, acceptDeepestMatch);
|
return remainingPath.Length == 0 ? rootContainer : await rootContainer.GetByPath(remainingPath, acceptDeepestMatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Refresh() => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty);
|
public async Task RefreshAsync(CancellationToken token = default) => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty, token);
|
||||||
|
|
||||||
public Task<IContainer> Clone() => Task.FromResult((IContainer)this);
|
public Task<IContainer> Clone() => Task.FromResult((IContainer)this);
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace FileTime.Providers.Local
|
|||||||
if (_parent is LocalFolder parentFolder)
|
if (_parent is LocalFolder parentFolder)
|
||||||
{
|
{
|
||||||
System.IO.File.Move(File.FullName, Path.Combine(parentFolder.Directory.FullName, newName));
|
System.IO.File.Move(File.FullName, Path.Combine(parentFolder.Directory.FullName, newName));
|
||||||
await _parent.Refresh();
|
await _parent.RefreshAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,16 +59,22 @@ namespace FileTime.Providers.Local
|
|||||||
|
|
||||||
public Task<IContainer> Clone() => Task.FromResult((IContainer)new LocalFolder(Directory, Provider, _parent));
|
public Task<IContainer> Clone() => Task.FromResult((IContainer)new LocalFolder(Directory, Provider, _parent));
|
||||||
|
|
||||||
public Task Refresh()
|
public Task RefreshAsync(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
_containers = new List<IContainer>();
|
_containers = new List<IContainer>();
|
||||||
_elements = new List<IElement>();
|
_elements = new List<IElement>();
|
||||||
|
_items = new List<IItem>();
|
||||||
_exceptions.Clear();
|
_exceptions.Clear();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
if (token.IsCancellationRequested) return Task.CompletedTask;
|
||||||
_containers = Directory.GetDirectories().Select(d => new LocalFolder(d, Provider, this)).OrderBy(d => d.Name).ToList().AsReadOnly();
|
_containers = Directory.GetDirectories().Select(d => new LocalFolder(d, Provider, this)).OrderBy(d => d.Name).ToList().AsReadOnly();
|
||||||
|
|
||||||
|
if (token.IsCancellationRequested) return Task.CompletedTask;
|
||||||
_elements = Directory.GetFiles().Select(f => new LocalFile(f, this, Provider)).OrderBy(f => f.Name).ToList().AsReadOnly();
|
_elements = Directory.GetFiles().Select(f => new LocalFile(f, this, Provider)).OrderBy(f => f.Name).ToList().AsReadOnly();
|
||||||
|
|
||||||
|
if (token.IsCancellationRequested) return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -76,24 +82,24 @@ namespace FileTime.Providers.Local
|
|||||||
}
|
}
|
||||||
|
|
||||||
_items = _containers.Cast<IItem>().Concat(_elements).ToList().AsReadOnly();
|
_items = _containers.Cast<IItem>().Concat(_elements).ToList().AsReadOnly();
|
||||||
Refreshed?.InvokeAsync(this, AsyncEventArgs.Empty);
|
Refreshed?.InvokeAsync(this, AsyncEventArgs.Empty, token);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
|
public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_items == null) await Refresh();
|
if (_items == null) await RefreshAsync(token);
|
||||||
return _items;
|
return _items;
|
||||||
}
|
}
|
||||||
public async Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default)
|
public async Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_containers == null) await Refresh();
|
if (_containers == null) await RefreshAsync(token);
|
||||||
return _containers;
|
return _containers;
|
||||||
}
|
}
|
||||||
public async Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default)
|
public async Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_elements == null) await Refresh();
|
if (_elements == null) await RefreshAsync(token);
|
||||||
return _elements;
|
return _elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +124,7 @@ namespace FileTime.Providers.Local
|
|||||||
public async Task<IContainer> CreateContainer(string name)
|
public async Task<IContainer> CreateContainer(string name)
|
||||||
{
|
{
|
||||||
Directory.CreateSubdirectory(name);
|
Directory.CreateSubdirectory(name);
|
||||||
await Refresh();
|
await RefreshAsync();
|
||||||
|
|
||||||
return _containers!.FirstOrDefault(c => Provider.NormalizePath(c.Name) == Provider.NormalizePath(name))!;
|
return _containers!.FirstOrDefault(c => Provider.NormalizePath(c.Name) == Provider.NormalizePath(name))!;
|
||||||
}
|
}
|
||||||
@@ -126,7 +132,7 @@ namespace FileTime.Providers.Local
|
|||||||
public async Task<IElement> CreateElement(string name)
|
public async Task<IElement> CreateElement(string name)
|
||||||
{
|
{
|
||||||
using (File.Create(Path.Combine(Directory.FullName, name))) { }
|
using (File.Create(Path.Combine(Directory.FullName, name))) { }
|
||||||
await Refresh();
|
await RefreshAsync();
|
||||||
|
|
||||||
return _elements!.FirstOrDefault(e => Provider.NormalizePath(e.Name) == Provider.NormalizePath(name))!;
|
return _elements!.FirstOrDefault(e => Provider.NormalizePath(e.Name) == Provider.NormalizePath(name))!;
|
||||||
}
|
}
|
||||||
@@ -150,7 +156,7 @@ namespace FileTime.Providers.Local
|
|||||||
if (_parent is LocalFolder parentFolder)
|
if (_parent is LocalFolder parentFolder)
|
||||||
{
|
{
|
||||||
System.IO.Directory.Move(Directory.FullName, Path.Combine(parentFolder.Directory.FullName, newName));
|
System.IO.Directory.Move(Directory.FullName, Path.Combine(parentFolder.Directory.FullName, newName));
|
||||||
await _parent.Refresh();
|
await _parent.RefreshAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace FileTime.Providers.Smb
|
|||||||
_items = _rootContainers.OrderBy(c => c.Name).ToList().AsReadOnly();
|
_items = _rootContainers.OrderBy(c => c.Name).ToList().AsReadOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
await Refresh();
|
await RefreshAsync();
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ namespace FileTime.Providers.Smb
|
|||||||
|
|
||||||
public async Task<bool> IsExists(string name) => (await GetItems())?.Any(i => i.Name == name) ?? false;
|
public async Task<bool> IsExists(string name) => (await GetItems())?.Any(i => i.Name == name) ?? false;
|
||||||
|
|
||||||
public async Task Refresh() => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty);
|
public async Task RefreshAsync(CancellationToken token = default) => await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty, token);
|
||||||
|
|
||||||
public bool CanHandlePath(string path) => path.StartsWith("smb://") || path.StartsWith(@"\\");
|
public bool CanHandlePath(string path) => path.StartsWith("smb://") || path.StartsWith(@"\\");
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ namespace FileTime.Providers.Smb
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Refresh()
|
public async Task RefreshAsync(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var containers = new List<IContainer>();
|
var containers = new List<IContainer>();
|
||||||
var elements = new List<IElement>();
|
var elements = new List<IElement>();
|
||||||
@@ -96,7 +96,7 @@ namespace FileTime.Providers.Smb
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var path = FullName![(_smbShare.FullName!.Length + 1)..];
|
var path = FullName![(_smbShare.FullName!.Length + 1)..];
|
||||||
(containers, elements) = await _smbShare.ListFolder(this, _smbShare.Name, path);
|
(containers, elements) = await _smbShare.ListFolder(this, _smbShare.Name, path, token);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
@@ -104,22 +104,22 @@ namespace FileTime.Providers.Smb
|
|||||||
_elements = elements.AsReadOnly();
|
_elements = elements.AsReadOnly();
|
||||||
|
|
||||||
_items = _containers.Cast<IItem>().Concat(_elements).ToList().AsReadOnly();
|
_items = _containers.Cast<IItem>().Concat(_elements).ToList().AsReadOnly();
|
||||||
await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty);
|
await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
|
public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_items == null) await Refresh();
|
if (_items == null) await RefreshAsync();
|
||||||
return _items;
|
return _items;
|
||||||
}
|
}
|
||||||
public async Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default)
|
public async Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_containers == null) await Refresh();
|
if (_containers == null) await RefreshAsync();
|
||||||
return _containers;
|
return _containers;
|
||||||
}
|
}
|
||||||
public async Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default)
|
public async Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_elements == null) await Refresh();
|
if (_elements == null) await RefreshAsync();
|
||||||
return _elements;
|
return _elements;
|
||||||
}
|
}
|
||||||
public Task<bool> CanOpen() => Task.FromResult(true);
|
public Task<bool> CanOpen() => Task.FromResult(true);
|
||||||
|
|||||||
@@ -51,12 +51,12 @@ namespace FileTime.Providers.Smb
|
|||||||
|
|
||||||
public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
|
public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_shares == null) await Refresh();
|
if (_shares == null) await RefreshAsync();
|
||||||
return _shares;
|
return _shares;
|
||||||
}
|
}
|
||||||
public async Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default)
|
public async Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_shares == null) await Refresh();
|
if (_shares == null) await RefreshAsync();
|
||||||
return _shares;
|
return _shares;
|
||||||
}
|
}
|
||||||
public Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default)
|
public Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default)
|
||||||
@@ -91,7 +91,7 @@ namespace FileTime.Providers.Smb
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Refresh()
|
public async Task RefreshAsync(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
List<string> shares = await _smbClientContext.RunWithSmbClientAsync((client) => client.ListShares(out var status));
|
List<string> shares = await _smbClientContext.RunWithSmbClientAsync((client) => client.ListShares(out var status));
|
||||||
|
|
||||||
|
|||||||
@@ -43,17 +43,17 @@ namespace FileTime.Providers.Smb
|
|||||||
|
|
||||||
public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
|
public async Task<IReadOnlyList<IItem>?> GetItems(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_items == null) await Refresh();
|
if (_items == null) await RefreshAsync();
|
||||||
return _items;
|
return _items;
|
||||||
}
|
}
|
||||||
public async Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default)
|
public async Task<IReadOnlyList<IContainer>?> GetContainers(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_containers == null) await Refresh();
|
if (_containers == null) await RefreshAsync();
|
||||||
return _containers;
|
return _containers;
|
||||||
}
|
}
|
||||||
public async Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default)
|
public async Task<IReadOnlyList<IElement>?> GetElements(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
if (_elements == null) await Refresh();
|
if (_elements == null) await RefreshAsync();
|
||||||
return _elements;
|
return _elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,14 +100,14 @@ namespace FileTime.Providers.Smb
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Refresh()
|
public async Task RefreshAsync(CancellationToken token = default)
|
||||||
{
|
{
|
||||||
var containers = new List<IContainer>();
|
var containers = new List<IContainer>();
|
||||||
var elements = new List<IElement>();
|
var elements = new List<IElement>();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
(containers, elements) = await ListFolder(this, Name, string.Empty);
|
(containers, elements) = await ListFolder(this, Name, string.Empty, token);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
|
||||||
@@ -115,10 +115,10 @@ namespace FileTime.Providers.Smb
|
|||||||
_elements = elements.AsReadOnly();
|
_elements = elements.AsReadOnly();
|
||||||
|
|
||||||
_items = _containers.Cast<IItem>().Concat(_elements).ToList().AsReadOnly();
|
_items = _containers.Cast<IItem>().Concat(_elements).ToList().AsReadOnly();
|
||||||
await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty);
|
await Refreshed.InvokeAsync(this, AsyncEventArgs.Empty, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<(List<IContainer> containers, List<IElement> elements)> ListFolder(IContainer parent, string shareName, string folderName)
|
public async Task<(List<IContainer> containers, List<IElement> elements)> ListFolder(IContainer parent, string shareName, string folderName, CancellationToken token = default)
|
||||||
{
|
{
|
||||||
return await _smbClientContext.RunWithSmbClientAsync(client =>
|
return await _smbClientContext.RunWithSmbClientAsync(client =>
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user