Incremental item loading, movement does not respect order
This commit is contained in:
@@ -82,7 +82,6 @@ public partial class TabViewModel : ITabViewModel
|
|||||||
|
|
||||||
CurrentItems = tab.CurrentItems
|
CurrentItems = tab.CurrentItems
|
||||||
.Select(items => items?.Transform(i => MapItemToViewModel(i, ItemViewModelType.Main)))
|
.Select(items => items?.Transform(i => MapItemToViewModel(i, ItemViewModelType.Main)))
|
||||||
.Select(items => items?.Sort(SortItems()))
|
|
||||||
.Publish(null)
|
.Publish(null)
|
||||||
.RefCount();
|
.RefCount();
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ public interface IContentProvider : IContainer, IOnContainerEnter
|
|||||||
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
||||||
ItemInitializationSettings itemInitializationSettings = default);
|
ItemInitializationSettings itemInitializationSettings = default);
|
||||||
|
|
||||||
Task<List<AbsolutePath>> GetItemsByContainerAsync(FullName fullName, PointInTime pointInTime);
|
|
||||||
NativePath GetNativePath(FullName fullName);
|
NativePath GetNativePath(FullName fullName);
|
||||||
|
|
||||||
Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default);
|
Task<byte[]?> GetContentAsync(IElement element, int? maxLength = null, CancellationToken cancellationToken = default);
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ public abstract class ContentProviderBase : IContentProvider
|
|||||||
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
AbsolutePathType forceResolvePathType = AbsolutePathType.Unknown,
|
||||||
ItemInitializationSettings itemInitializationSettings = default);
|
ItemInitializationSettings itemInitializationSettings = default);
|
||||||
|
|
||||||
public abstract Task<List<AbsolutePath>> GetItemsByContainerAsync(FullName fullName, PointInTime pointInTime);
|
|
||||||
public abstract NativePath GetNativePath(FullName fullName);
|
public abstract NativePath GetNativePath(FullName fullName);
|
||||||
|
|
||||||
public abstract Task<byte[]?> GetContentAsync(IElement element,
|
public abstract Task<byte[]?> GetContentAsync(IElement element,
|
||||||
|
|||||||
@@ -26,7 +26,14 @@ public record Container(
|
|||||||
ReadOnlyExtensionCollection Extensions,
|
ReadOnlyExtensionCollection Extensions,
|
||||||
IObservable<IObservable<IChangeSet<AbsolutePath, string>>?> Items) : IContainer
|
IObservable<IObservable<IChangeSet<AbsolutePath, string>>?> Items) : IContainer
|
||||||
{
|
{
|
||||||
BehaviorSubject<bool> IsLoading { get; } = new(false);
|
private readonly CancellationTokenSource _loadingCancellationTokenSource = new();
|
||||||
|
public CancellationToken LoadingCancellationToken => _loadingCancellationTokenSource.Token;
|
||||||
|
public BehaviorSubject<bool> IsLoading { get; } = new(false);
|
||||||
IObservable<bool> IContainer.IsLoading => IsLoading.AsObservable();
|
IObservable<bool> IContainer.IsLoading => IsLoading.AsObservable();
|
||||||
public AbsolutePathType Type => AbsolutePathType.Container;
|
public AbsolutePathType Type => AbsolutePathType.Container;
|
||||||
|
|
||||||
|
public void CancelLoading()
|
||||||
|
{
|
||||||
|
_loadingCancellationTokenSource.Cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ using System.Reactive.Linq;
|
|||||||
using System.Reactive.Subjects;
|
using System.Reactive.Subjects;
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
using DynamicData.Alias;
|
using DynamicData.Alias;
|
||||||
|
using DynamicData.Binding;
|
||||||
using FileTime.Core.Helper;
|
using FileTime.Core.Helper;
|
||||||
using FileTime.Core.Models;
|
using FileTime.Core.Models;
|
||||||
using FileTime.Core.Timeline;
|
using FileTime.Core.Timeline;
|
||||||
@@ -52,7 +53,11 @@ public class Tab : ITab
|
|||||||
.Switch()
|
.Switch()
|
||||||
.Select(items => items?.TransformAsync(MapItem)),
|
.Select(items => items?.TransformAsync(MapItem)),
|
||||||
_itemFilters.Connect().StartWithEmpty().ToCollection(),
|
_itemFilters.Connect().StartWithEmpty().ToCollection(),
|
||||||
(items, filters) => items?.Where(i => filters.All(f => f.Filter(i)))),
|
(items, filters) =>
|
||||||
|
items
|
||||||
|
?.Where(i => filters.All(f => f.Filter(i)))
|
||||||
|
.Sort(SortItems())
|
||||||
|
),
|
||||||
CurrentLocation
|
CurrentLocation
|
||||||
.Where(c => c is null)
|
.Where(c => c is null)
|
||||||
.Select(_ => (IObservable<IChangeSet<IItem, string>>?)null)
|
.Select(_ => (IObservable<IChangeSet<IItem, string>>?)null)
|
||||||
@@ -89,6 +94,12 @@ public class Tab : ITab
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static SortExpressionComparer<IItem> SortItems()
|
||||||
|
//TODO: Order
|
||||||
|
=> SortExpressionComparer<IItem>
|
||||||
|
.Ascending(i => i.Type)
|
||||||
|
.ThenByAscending(i => i.DisplayName?.ToLower() ?? "");
|
||||||
|
|
||||||
private async Task<IItem> MapItem(AbsolutePath item) => await item.ResolveAsync(true);
|
private async Task<IItem> MapItem(AbsolutePath item) => await item.ResolveAsync(true);
|
||||||
|
|
||||||
public void Init(IContainer currentLocation)
|
public void Init(IContainer currentLocation)
|
||||||
|
|||||||
@@ -177,23 +177,6 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task<List<AbsolutePath>> GetItemsByContainerAsync(FullName fullName, PointInTime pointInTime)
|
|
||||||
=> Task.FromResult(GetItemsByContainer(fullName, pointInTime));
|
|
||||||
|
|
||||||
private List<AbsolutePath> GetItemsByContainer(FullName fullName, PointInTime pointInTime)
|
|
||||||
=> GetItemsByContainer(new DirectoryInfo(GetNativePath(fullName).Path), pointInTime);
|
|
||||||
|
|
||||||
private List<AbsolutePath> GetItemsByContainer(DirectoryInfo directoryInfo, PointInTime pointInTime)
|
|
||||||
=> directoryInfo
|
|
||||||
.GetDirectories()
|
|
||||||
.Select(d => DirectoryToAbsolutePath(d, pointInTime))
|
|
||||||
.Concat(
|
|
||||||
directoryInfo
|
|
||||||
.GetFiles()
|
|
||||||
.Select(f => FileToAbsolutePath(f, pointInTime))
|
|
||||||
)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
private AbsolutePath DirectoryToAbsolutePath(DirectoryInfo directoryInfo, PointInTime pointInTime)
|
private AbsolutePath DirectoryToAbsolutePath(DirectoryInfo directoryInfo, PointInTime pointInTime)
|
||||||
{
|
{
|
||||||
var fullName = GetFullName(directoryInfo);
|
var fullName = GetFullName(directoryInfo);
|
||||||
@@ -221,7 +204,9 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
|||||||
AbsolutePathType.Container);
|
AbsolutePathType.Container);
|
||||||
var exceptions = new BehaviorSubject<IEnumerable<Exception>>(Enumerable.Empty<Exception>());
|
var exceptions = new BehaviorSubject<IEnumerable<Exception>>(Enumerable.Empty<Exception>());
|
||||||
|
|
||||||
return new Container(
|
var children = new SourceCache<AbsolutePath, string>(i => i.Path.Path);
|
||||||
|
|
||||||
|
var container = new Container(
|
||||||
directoryInfo.Name,
|
directoryInfo.Name,
|
||||||
directoryInfo.Name,
|
directoryInfo.Name,
|
||||||
fullName,
|
fullName,
|
||||||
@@ -239,10 +224,13 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
|||||||
exceptions,
|
exceptions,
|
||||||
new ExtensionCollection().AsReadOnly(),
|
new ExtensionCollection().AsReadOnly(),
|
||||||
//Observable.FromAsync(async () => await Task.Run(InitChildrenHelper)
|
//Observable.FromAsync(async () => await Task.Run(InitChildrenHelper)
|
||||||
Observable.Return(InitChildren())
|
//Observable.Return(InitChildren())
|
||||||
|
Observable.Return(children.Connect())
|
||||||
);
|
);
|
||||||
|
|
||||||
Task<IObservable<IChangeSet<AbsolutePath, string>>?> InitChildrenHelper() => Task.FromResult(InitChildren());
|
Task.Run(() => LoadChildren(container, directoryInfo, children, pointInTime));
|
||||||
|
|
||||||
|
return container;
|
||||||
|
|
||||||
IObservable<IChangeSet<AbsolutePath, string>>? InitChildren()
|
IObservable<IChangeSet<AbsolutePath, string>>? InitChildren()
|
||||||
{
|
{
|
||||||
@@ -267,6 +255,69 @@ public sealed partial class LocalContentProvider : ContentProviderBase, ILocalCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void LoadChildren(
|
||||||
|
Container container,
|
||||||
|
DirectoryInfo directoryInfo,
|
||||||
|
SourceCache<AbsolutePath, string> children,
|
||||||
|
PointInTime pointInTime)
|
||||||
|
{
|
||||||
|
var lockobj = new object();
|
||||||
|
var loadingIndicatorCancellation = new CancellationTokenSource();
|
||||||
|
|
||||||
|
Task.Run(DelayedLoadingIndicator);
|
||||||
|
LoadChildren();
|
||||||
|
|
||||||
|
lock (lockobj)
|
||||||
|
{
|
||||||
|
loadingIndicatorCancellation.Cancel();
|
||||||
|
container.IsLoading.OnNext(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadChildren()
|
||||||
|
{
|
||||||
|
foreach (var directory in directoryInfo.EnumerateDirectories())
|
||||||
|
{
|
||||||
|
if (container.LoadingCancellationToken.IsCancellationRequested) break;
|
||||||
|
var absolutePath = DirectoryToAbsolutePath(directory, pointInTime);
|
||||||
|
children.AddOrUpdate(absolutePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var file in directoryInfo.EnumerateFiles())
|
||||||
|
{
|
||||||
|
if (container.LoadingCancellationToken.IsCancellationRequested) break;
|
||||||
|
var absolutePath = FileToAbsolutePath(file, pointInTime);
|
||||||
|
children.AddOrUpdate(absolutePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task DelayedLoadingIndicator()
|
||||||
|
{
|
||||||
|
var token = loadingIndicatorCancellation.Token;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Task.Delay(500, token);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
lock (lockobj)
|
||||||
|
{
|
||||||
|
if (token.IsCancellationRequested) return;
|
||||||
|
container.IsLoading.OnNext(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<AbsolutePath> GetItemsByContainer(DirectoryInfo directoryInfo, PointInTime pointInTime)
|
||||||
|
=> directoryInfo
|
||||||
|
.GetDirectories()
|
||||||
|
.Select(d => DirectoryToAbsolutePath(d, pointInTime))
|
||||||
|
.Concat(
|
||||||
|
directoryInfo
|
||||||
|
.GetFiles()
|
||||||
|
.Select(f => FileToAbsolutePath(f, pointInTime))
|
||||||
|
)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
private Element FileToElement(FileInfo fileInfo, PointInTime pointInTime)
|
private Element FileToElement(FileInfo fileInfo, PointInTime pointInTime)
|
||||||
{
|
{
|
||||||
var fullName = GetFullName(fileInfo);
|
var fullName = GetFullName(fileInfo);
|
||||||
|
|||||||
Reference in New Issue
Block a user