Timeline: use ObservableCollection instead of DynamicData

This commit is contained in:
2023-08-14 17:15:03 +02:00
parent 8aa8d83598
commit 4381f1b47a
11 changed files with 49 additions and 191 deletions

View File

@@ -1,27 +0,0 @@
using DynamicData;
using FileTime.Core.Models;
namespace FileTime.Core.Extensions;
public static class BindedCollectionExtensions
{
public static BindedCollection<T> ToBindedCollection<T>(this IObservable<IChangeSet<T>> source)
{
return new BindedCollection<T>(source);
}
public static BindedCollection<T> ToBindedCollection<T>(this IObservable<IObservable<IChangeSet<T>>?> source)
{
return new BindedCollection<T>(source);
}
public static BindedCollection<T, TKey> ToBindedCollection<T, TKey>(this IObservable<IChangeSet<T, TKey>> source) where TKey : notnull
{
return new BindedCollection<T, TKey>(source);
}
public static BindedCollection<T, TKey> ToBindedCollection<T, TKey>(this IObservable<IObservable<IChangeSet<T, TKey>>?> source) where TKey : notnull
{
return new BindedCollection<T, TKey>(source);
}
}

View File

@@ -1,106 +0,0 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using DynamicData;
using PropertyChanged.SourceGenerator;
namespace FileTime.Core.Models;
public partial class BindedCollection<T> : IDisposable, INotifyPropertyChanged
{
private readonly IDisposable? _disposable;
private IDisposable? _innerDisposable;
[Notify] private ReadOnlyObservableCollection<T>? _collection;
public BindedCollection()
{
}
public BindedCollection(IObservable<IChangeSet<T>> dynamicList)
{
_disposable = dynamicList
.Bind(out var collection)
.DisposeMany()
.Subscribe();
_collection = collection;
}
public BindedCollection(IObservable<IObservable<IChangeSet<T>>?> dynamicListSource)
{
_disposable = dynamicListSource.Subscribe(dynamicList =>
{
_innerDisposable?.Dispose();
if (dynamicList is not null)
{
_innerDisposable = dynamicList
.Bind(out var collection)
.DisposeMany()
.Subscribe();
Collection = collection;
}
else
{
Collection = null;
}
});
}
public void Dispose()
{
_disposable?.Dispose();
_innerDisposable?.Dispose();
GC.SuppressFinalize(this);
}
}
public partial class BindedCollection<T, TKey> : IDisposable, INotifyPropertyChanged where TKey : notnull
{
private readonly IDisposable? _disposable;
private IDisposable? _innerDisposable;
[Notify] private ReadOnlyObservableCollection<T>? _collection;
public BindedCollection()
{
}
public BindedCollection(IObservable<IChangeSet<T, TKey>> dynamicList)
{
_disposable = dynamicList
.Bind(out var collection)
.DisposeMany()
.Subscribe();
_collection = collection;
}
public BindedCollection(IObservable<IObservable<IChangeSet<T, TKey>>?> dynamicListSource)
{
_disposable = dynamicListSource.Subscribe(dynamicList =>
{
_innerDisposable?.Dispose();
if (dynamicList is not null)
{
_innerDisposable = dynamicList
.Bind(out var collection)
.DisposeMany()
.Subscribe();
Collection = collection;
}
else
{
Collection = null;
}
});
}
public void Dispose()
{
_disposable?.Dispose();
_innerDisposable?.Dispose();
GC.SuppressFinalize(this);
}
}

View File

@@ -1,4 +1,4 @@
using DynamicData;
using System.Collections.ObjectModel;
using FileTime.Core.Command;
using FileTime.Core.Models;
@@ -8,7 +8,7 @@ public interface ICommandScheduler
{
Task AddCommand(ICommand command, int? batchId = null, bool toNewBatch = false);
IObservable<FullName> ContainerToRefresh { get; }
IObservable<IChangeSet<ParallelCommands>> CommandsToRun { get; }
ReadOnlyObservableCollection<ParallelCommands> CommandsToRun { get; }
bool IsRunningEnabled { get; }
void RefreshContainer(FullName container);
Task SetRunningEnabledAsync(bool value);

View File

@@ -1,21 +1,17 @@
using DynamicData;
using System.Collections.ObjectModel;
using FileTime.Core.Command;
using FileTime.Core.Extensions;
using FileTime.Core.Models;
namespace FileTime.Core.Timeline;
public class ParallelCommands : IDisposable
public class ParallelCommands
{
private static ushort _idCounter;
private readonly SourceList<CommandTimeState> _commands;
private readonly ObservableCollection<CommandTimeState> _commands;
private PointInTime? _startTime;
public ushort Id { get; }
public IObservable<IChangeSet<CommandTimeState>> Commands { get; }
public BindedCollection<CommandTimeState> CommandsCollection { get; }
public ReadOnlyObservableCollection<CommandTimeState> Commands { get; }
public int CommandCount => _commands.Count;
public PointInTime? Result { get; private set; }
@@ -37,10 +33,8 @@ public class ParallelCommands : IDisposable
{
Id = _idCounter++;
_commands = new SourceList<CommandTimeState>();
_commands.Edit((innerList) => innerList.AddRange(commands));
Commands = _commands.Connect();
CommandsCollection = Commands.ToBindedCollection();
_commands = new ObservableCollection<CommandTimeState>(commands);
Commands = new(_commands);
Result = result;
}
@@ -85,7 +79,7 @@ public class ParallelCommands : IDisposable
public async Task RemoveCommand(ICommand command)
{
var commandTimeState = _commands.Items.First(c => c.Command == command);
var commandTimeState = _commands.First(c => c.Command == command);
_commands.Remove(commandTimeState);
await RefreshResult();
}
@@ -93,7 +87,7 @@ public class ParallelCommands : IDisposable
public async Task<PointInTime?> RefreshResult()
{
var result = StartTime;
foreach (var commandTimeState in _commands.Items)
foreach (var commandTimeState in _commands)
{
await commandTimeState.UpdateStateAsync(result);
if (result != null)
@@ -113,9 +107,4 @@ public class ParallelCommands : IDisposable
Result = result;
return Result;
}
public void Dispose()
{
CommandsCollection.Dispose();
}
}

View File

@@ -1,6 +1,6 @@
using System.Collections.ObjectModel;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using DynamicData;
using FileTime.Core.Command;
using FileTime.Core.Models;
@@ -8,7 +8,7 @@ namespace FileTime.Core.Timeline;
public class CommandScheduler : ICommandScheduler
{
private readonly SourceList<ParallelCommands> _commandsToRun = new();
private readonly ObservableCollection<ParallelCommands> _commandsToRun = new();
private readonly List<ICommandExecutor> _commandExecutors = new();
private readonly Subject<FullName> _containerToRefresh = new();
@@ -29,11 +29,11 @@ public class CommandScheduler : ICommandScheduler
}
}
public IObservable<IChangeSet<ParallelCommands>> CommandsToRun { get; }
public ReadOnlyObservableCollection<ParallelCommands> CommandsToRun { get; }
public CommandScheduler(ILocalCommandExecutor localExecutor)
{
CommandsToRun = _commandsToRun.Connect();
CommandsToRun = new(_commandsToRun);
ContainerToRefresh = _containerToRefresh.AsObservable();
@@ -55,16 +55,16 @@ public class CommandScheduler : ICommandScheduler
}
else if (toNewBatch)
{
batchToAdd = new ParallelCommands(_commandsToRun.Items.Last().Result);
batchToAdd = new ParallelCommands(_commandsToRun.Last().Result);
_commandsToRun.Add(batchToAdd);
}
else if (batchId != null && _commandsToRun.Items.First(b => b.Id == batchId) is { } parallelCommands)
else if (batchId != null && _commandsToRun.First(b => b.Id == batchId) is { } parallelCommands)
{
batchToAdd = parallelCommands;
}
else
{
batchToAdd = _commandsToRun.Items.First();
batchToAdd = _commandsToRun.First();
}
await batchToAdd.AddCommand(command);
@@ -88,13 +88,13 @@ public class CommandScheduler : ICommandScheduler
{
if (!_isRunningEnabled) return;
var commandsToExecute = _commandsToRun.Items.FirstOrDefault()?.CommandsCollection.Collection;
var commandsToExecute = _commandsToRun.FirstOrDefault()?.Commands;
if (commandsToExecute is null || commandsToExecute.All(c => c.ExecutionState != ExecutionState.Initializing && c.ExecutionState != ExecutionState.Waiting)) return;
foreach (var commandToExecute in commandsToExecute)
{
if (commandToExecute.ExecutionState != ExecutionState.Waiting
&& commandToExecute.ExecutionState != ExecutionState.Initializing )
&& commandToExecute.ExecutionState != ExecutionState.Initializing)
{
continue;
}
@@ -113,17 +113,14 @@ public class CommandScheduler : ICommandScheduler
return _commandExecutors[0];
}
private async void ExecutorOnCommandFinished(object? sender, ICommand command)
{
private async void ExecutorOnCommandFinished(object? sender, ICommand command) =>
await RunWithLockAsync(async () =>
{
var firstCommandBlock = _commandsToRun
.Items
.FirstOrDefault();
var state = firstCommandBlock
?.CommandsCollection
.Collection
?.FirstOrDefault(c => c.Command == command);
?.Commands
.FirstOrDefault(c => c.Command == command);
if (state is null) return;
@@ -137,13 +134,12 @@ public class CommandScheduler : ICommandScheduler
}
}
});
}
private async Task RefreshCommands()
{
var currentTime = PointInTime.CreateEmpty();
foreach (var batch in _commandsToRun.Items)
foreach (var batch in _commandsToRun)
{
currentTime = await batch.SetStartTimeAsync(currentTime);
}