Fixed more edge cases
This commit is contained in:
@@ -54,7 +54,10 @@ public class ContentControlHandler :
|
|||||||
control.Unloaded += HandleUnloaded;
|
control.Unloaded += HandleUnloaded;
|
||||||
|
|
||||||
control.DataContext = args.Content;
|
control.DataContext = args.Content;
|
||||||
|
|
||||||
|
contentControl.Content = null;
|
||||||
contentControl.Content = control;
|
contentControl.Content = control;
|
||||||
|
|
||||||
await taskCompletionSource.Task;
|
await taskCompletionSource.Task;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Immutable;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
|
||||||
namespace Toolkit.Foundation;
|
namespace Toolkit.Foundation;
|
||||||
@@ -10,6 +10,12 @@ public class Cache<TValue>(IDisposer disposer,
|
|||||||
{
|
{
|
||||||
private readonly SortedSet<TValue> cache = new(comparer);
|
private readonly SortedSet<TValue> cache = new(comparer);
|
||||||
|
|
||||||
|
public int IndexOf(TValue value)
|
||||||
|
{
|
||||||
|
ImmutableSortedSet<TValue> hashSet = cache.ToImmutableSortedSet(comparer);
|
||||||
|
return hashSet.IndexOf(value);
|
||||||
|
}
|
||||||
|
|
||||||
public void Add(TValue value)
|
public void Add(TValue value)
|
||||||
{
|
{
|
||||||
if (value is null)
|
if (value is null)
|
||||||
@@ -21,6 +27,17 @@ public class Cache<TValue>(IDisposer disposer,
|
|||||||
cache.Add(value);
|
cache.Add(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool TryGetValue(TValue key, out TValue? value)
|
||||||
|
{
|
||||||
|
if (cache.TryGetValue(key, out value))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = default;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void Clear() => cache.Clear();
|
public void Clear() => cache.Clear();
|
||||||
|
|
||||||
public IEnumerator<TValue> GetEnumerator() => cache.GetEnumerator();
|
public IEnumerator<TValue> GetEnumerator() => cache.GetEnumerator();
|
||||||
@@ -30,14 +47,15 @@ public class Cache<TValue>(IDisposer disposer,
|
|||||||
public bool Remove(TValue value) => cache.Remove(value);
|
public bool Remove(TValue value) => cache.Remove(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Cache<TKey, TValue> :
|
public class Cache<TKey, TValue>(IDisposer disposer,
|
||||||
|
IComparer<TKey> comparer) :
|
||||||
ICache<TKey, TValue>
|
ICache<TKey, TValue>
|
||||||
where TKey :
|
where TKey :
|
||||||
notnull
|
notnull
|
||||||
where TValue :
|
where TValue :
|
||||||
notnull
|
notnull
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<TKey, TValue> cache = new();
|
private readonly SortedList<TKey, TValue> cache = new(comparer);
|
||||||
|
|
||||||
public void Add(TKey key,
|
public void Add(TKey key,
|
||||||
TValue value)
|
TValue value)
|
||||||
@@ -49,6 +67,8 @@ public class Cache<TKey, TValue> :
|
|||||||
|
|
||||||
public bool ContainsKey(TKey key) => cache.ContainsKey(key);
|
public bool ContainsKey(TKey key) => cache.ContainsKey(key);
|
||||||
|
|
||||||
|
public int IndexOf(TKey key) => cache.IndexOfKey(key);
|
||||||
|
|
||||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => cache.GetEnumerator();
|
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => cache.GetEnumerator();
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public record Created
|
||||||
|
{
|
||||||
|
public static CreatedEventArgs<TValue> As<TValue>(TValue value) =>
|
||||||
|
new(value);
|
||||||
|
|
||||||
|
public static CreatedEventArgs<TValue> As<TValue>() where TValue : new() =>
|
||||||
|
new(new TValue());
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public record CreatedEventArgs<TValue>(TValue Value);
|
||||||
@@ -7,7 +7,11 @@ public interface ICache<TValue> :
|
|||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
int IndexOf(TValue value);
|
||||||
|
|
||||||
bool Remove(TValue value);
|
bool Remove(TValue value);
|
||||||
|
|
||||||
|
bool TryGetValue(TValue key, out TValue? value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ICache<TKey, TValue> :
|
public interface ICache<TKey, TValue> :
|
||||||
@@ -17,13 +21,14 @@ public interface ICache<TKey, TValue> :
|
|||||||
where TValue :
|
where TValue :
|
||||||
notnull
|
notnull
|
||||||
{
|
{
|
||||||
void Add(TKey key,
|
void Add(TKey key, TValue value);
|
||||||
TValue value);
|
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
bool ContainsKey(TKey key);
|
bool ContainsKey(TKey key);
|
||||||
|
|
||||||
|
int IndexOf(TKey key);
|
||||||
|
|
||||||
bool Remove(TKey key);
|
bool Remove(TKey key);
|
||||||
|
|
||||||
bool TryGetValue(TKey key, out TValue? value);
|
bool TryGetValue(TKey key, out TValue? value);
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using Microsoft.Extensions.FileProviders;
|
|
||||||
using Microsoft.Extensions.FileProviders.Physical;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using System.Text.Json;
|
|
||||||
|
|
||||||
namespace Toolkit.Foundation;
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public record Modified
|
||||||
|
{
|
||||||
|
public static ModifiedEventArgs<TValue> As<TValue>(TValue oldValue, TValue newValue) =>
|
||||||
|
new(oldValue, newValue);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public record ModifiedEventArgs<TValue>(TValue OldView, TValue NewValue);
|
||||||
@@ -8,12 +8,25 @@ public class NavigateHandler(NamedComponent scope,
|
|||||||
{
|
{
|
||||||
public Task Handle(NavigateEventArgs args)
|
public Task Handle(NavigateEventArgs args)
|
||||||
{
|
{
|
||||||
INavigationScope? navigationScope;
|
INavigationScope? navigationScope = null;
|
||||||
if (args.Scope == "self" && args.Sender is IServiceProviderRequired requireServiceProvider)
|
if (args.Scope is "self" || args.Scope is "new")
|
||||||
{
|
{
|
||||||
navigationScope = requireServiceProvider.Provider.GetRequiredService<INavigationScope>();
|
if (args.Sender is IServiceProviderRequired requireServiceProvider)
|
||||||
|
{
|
||||||
|
if (args.Scope is "self")
|
||||||
|
{
|
||||||
|
navigationScope = requireServiceProvider.Provider.GetRequiredService<INavigationScope>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.Scope is "new")
|
||||||
|
{
|
||||||
|
IServiceScope serviceScope = requireServiceProvider.Provider.CreateScope();
|
||||||
|
navigationScope = serviceScope.ServiceProvider.GetRequiredService<INavigationScope>();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (navigationScope is null)
|
||||||
{
|
{
|
||||||
ComponentScopeDescriptor? descriptor = componentScopeProvider.Get(args.Scope ?? scope.Name);
|
ComponentScopeDescriptor? descriptor = componentScopeProvider.Get(args.Scope ?? scope.Name);
|
||||||
navigationScope = descriptor?.Services?.GetRequiredService<INavigationScope>();
|
navigationScope = descriptor?.Services?.GetRequiredService<INavigationScope>();
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public partial class Observable :
|
|||||||
public virtual Task OnDeactivating() =>
|
public virtual Task OnDeactivating() =>
|
||||||
Task.CompletedTask;
|
Task.CompletedTask;
|
||||||
|
|
||||||
public void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
Disposer.Dispose(this);
|
Disposer.Dispose(this);
|
||||||
|
|||||||
@@ -24,12 +24,14 @@ public partial class ObservableCollection<TItem> :
|
|||||||
IPublisherRequired,
|
IPublisherRequired,
|
||||||
IDisposerRequired,
|
IDisposerRequired,
|
||||||
INotificationHandler<RemoveEventArgs<TItem>>,
|
INotificationHandler<RemoveEventArgs<TItem>>,
|
||||||
|
INotificationHandler<RemoveAtEventArgs<TItem>>,
|
||||||
|
INotificationHandler<RemoveAndInsertAtEventArgs<TItem>>,
|
||||||
INotificationHandler<CreateEventArgs<TItem>>,
|
INotificationHandler<CreateEventArgs<TItem>>,
|
||||||
INotificationHandler<InsertEventArgs<TItem>>,
|
INotificationHandler<InsertEventArgs<TItem>>,
|
||||||
INotificationHandler<MoveEventArgs<TItem>>,
|
INotificationHandler<MoveEventArgs<TItem>>,
|
||||||
INotificationHandler<ReplaceEventArgs<TItem>>
|
INotificationHandler<ReplaceEventArgs<TItem>>
|
||||||
where TItem :
|
where TItem :
|
||||||
notnull
|
IDisposable
|
||||||
{
|
{
|
||||||
private readonly System.Collections.ObjectModel.ObservableCollection<TItem> collection = [];
|
private readonly System.Collections.ObjectModel.ObservableCollection<TItem> collection = [];
|
||||||
|
|
||||||
@@ -111,12 +113,6 @@ public partial class ObservableCollection<TItem> :
|
|||||||
set => SetItem(index, value);
|
set => SetItem(index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResetAndAddRange(Action<ObservableCollection<TItem>> args)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
args.Invoke(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
object? IList.this[int index]
|
object? IList.this[int index]
|
||||||
{
|
{
|
||||||
get => collection[index];
|
get => collection[index];
|
||||||
@@ -136,18 +132,13 @@ public partial class ObservableCollection<TItem> :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TItem Add() =>
|
public TItem Add() =>
|
||||||
Add<TItem>(null, false);
|
Add<TItem>(null, false);
|
||||||
|
|
||||||
public TItem Add<T>(params object?[] parameters)
|
public TItem Add<T>(params object?[] parameters)
|
||||||
where T : TItem => Add<T>(null, false, parameters);
|
where T : TItem => Add<T>(false, parameters);
|
||||||
|
|
||||||
public TItem Add<T>(IDisposable? owner,
|
public TItem Add<T>(bool scope = false,
|
||||||
params object?[] parameters)
|
|
||||||
where T : TItem => Add<T>(owner, false, parameters);
|
|
||||||
|
|
||||||
public TItem Add<T>(IDisposable? owner = null,
|
|
||||||
bool scope = false,
|
|
||||||
params object?[] parameters)
|
params object?[] parameters)
|
||||||
where T :
|
where T :
|
||||||
TItem
|
TItem
|
||||||
@@ -162,17 +153,6 @@ public partial class ObservableCollection<TItem> :
|
|||||||
T? item = factory is not null ? factory.Create<T>(parameters) : Factory.Create<T>(parameters);
|
T? item = factory is not null ? factory.Create<T>(parameters) : Factory.Create<T>(parameters);
|
||||||
Add(item);
|
Add(item);
|
||||||
|
|
||||||
if (owner is not null)
|
|
||||||
{
|
|
||||||
Disposer.Add(owner, Disposable.Create(() =>
|
|
||||||
{
|
|
||||||
if (item is IRemovable)
|
|
||||||
{
|
|
||||||
Remove(item);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +193,20 @@ public partial class ObservableCollection<TItem> :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void BeginAggregation()
|
||||||
|
{
|
||||||
|
if (this.GetAttribute<AggerateAttribute>() is AggerateAttribute attribute)
|
||||||
|
{
|
||||||
|
if (attribute.Mode == AggerateMode.Reset)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
object? key = this.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key;
|
||||||
|
Publisher.PublishUI(OnPrepareAggregation(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Clear()
|
public void Clear()
|
||||||
{
|
{
|
||||||
clearing = true;
|
clearing = true;
|
||||||
@@ -220,6 +214,7 @@ public partial class ObservableCollection<TItem> :
|
|||||||
foreach (TItem item in this.ToList())
|
foreach (TItem item in this.ToList())
|
||||||
{
|
{
|
||||||
Disposer.Dispose(item);
|
Disposer.Dispose(item);
|
||||||
|
Disposer.Remove(this, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClearItems();
|
ClearItems();
|
||||||
@@ -250,20 +245,6 @@ public partial class ObservableCollection<TItem> :
|
|||||||
Disposer.Dispose(this);
|
Disposer.Dispose(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginAggregation()
|
|
||||||
{
|
|
||||||
if (this.GetAttribute<AggerateAttribute>() is AggerateAttribute attribute)
|
|
||||||
{
|
|
||||||
if (attribute.Mode == AggerateMode.Reset)
|
|
||||||
{
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
object? key = this.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key;
|
|
||||||
Publisher.PublishUI(OnPrepareAggregation(key));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerator<TItem> GetEnumerator() =>
|
public IEnumerator<TItem> GetEnumerator() =>
|
||||||
collection.GetEnumerator();
|
collection.GetEnumerator();
|
||||||
|
|
||||||
@@ -323,6 +304,27 @@ public partial class ObservableCollection<TItem> :
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task Handle(RemoveAtEventArgs<TItem> args)
|
||||||
|
{
|
||||||
|
if (args.Index >= 0 && args.Index <= Count - 1)
|
||||||
|
{
|
||||||
|
RemoveAt(args.Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Handle(RemoveAndInsertAtEventArgs<TItem> args)
|
||||||
|
{
|
||||||
|
if (args.OldIndex >= 0 && args.OldIndex <= Count - 1 && args.Value is TItem item)
|
||||||
|
{
|
||||||
|
RemoveAt(args.OldIndex);
|
||||||
|
Insert(args.NewIndex, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
public int IndexOf(TItem item) =>
|
public int IndexOf(TItem item) =>
|
||||||
collection.IndexOf(item);
|
collection.IndexOf(item);
|
||||||
|
|
||||||
@@ -385,8 +387,10 @@ public partial class ObservableCollection<TItem> :
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Disposer.Dispose(item);
|
Disposer.Dispose(item);
|
||||||
|
Disposer.Remove(this, item);
|
||||||
|
|
||||||
RemoveItem(index);
|
RemoveItem(index);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -419,6 +423,12 @@ public partial class ObservableCollection<TItem> :
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ResetAndAddRange(Action<ObservableCollection<TItem>> args)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
args.Invoke(this);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void ClearItems() =>
|
protected virtual void ClearItems() =>
|
||||||
collection.Clear();
|
collection.Clear();
|
||||||
|
|
||||||
@@ -439,7 +449,7 @@ public partial class ObservableCollection<TItem> :
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
collection.Insert(index, item);
|
collection.Insert(index > Count ? Count : index, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual IAggerate OnPrepareAggregation(object? key) =>
|
protected virtual IAggerate OnPrepareAggregation(object? key) =>
|
||||||
@@ -476,7 +486,7 @@ public partial class ObservableCollection<TValue, TViewModel>(IServiceProvider p
|
|||||||
IMediator mediator,
|
IMediator mediator,
|
||||||
IPublisher publisher,
|
IPublisher publisher,
|
||||||
ISubscription subscriber, IDisposer disposer) : ObservableCollection<TViewModel>(provider, factory, mediator, publisher, subscriber, disposer)
|
ISubscription subscriber, IDisposer disposer) : ObservableCollection<TViewModel>(provider, factory, mediator, publisher, subscriber, disposer)
|
||||||
where TViewModel : notnull
|
where TViewModel : IDisposable
|
||||||
{
|
{
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
private TValue? value;
|
private TValue? value;
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public record RemoveAndInsertAt
|
||||||
|
{
|
||||||
|
public static RemoveAndInsertAtEventArgs<TValue> As<TValue>(int oldIndex, int newIndex, TValue value) =>
|
||||||
|
new(oldIndex, newIndex, value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public record RemoveAndInsertAtEventArgs<TValue>(int OldIndex, int NewIndex, TValue Value);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public record RemoveAt
|
||||||
|
{
|
||||||
|
public static RemoveAtEventArgs<TValue> As<TValue>(int index) =>
|
||||||
|
new(index);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
|
public record RemoveAtEventArgs<TValue>(int Index);
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
namespace Toolkit.Foundation;
|
namespace Toolkit.Foundation;
|
||||||
|
|
||||||
public record RemoveEventArgs<TValue>(TValue Value);
|
public record RemoveEventArgs<TValue>(TValue Value);
|
||||||
|
|
||||||
|
public record RemoveAndInsertEventArgs<TValue>(TValue Value);
|
||||||
@@ -21,7 +21,7 @@ public class Subscription(SubscriptionCollection subscriptions,
|
|||||||
return collection;
|
return collection;
|
||||||
});
|
});
|
||||||
|
|
||||||
disposer.Add(subscriber, Disposable.Create(() => RemoveSubscriber(subscriber, argumentType)));
|
disposer.Add(subscriber, Disposable.Create(() => RemoveSubscriber(subscriber, subscriptionKey)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,10 +51,9 @@ public class Subscription(SubscriptionCollection subscriptions,
|
|||||||
|
|
||||||
|
|
||||||
private void RemoveSubscriber(object subscriber,
|
private void RemoveSubscriber(object subscriber,
|
||||||
Type argumentType)
|
string key)
|
||||||
{
|
{
|
||||||
string subscriptionKey = $"{argumentType}";
|
if (subscriptions.TryGetValue(key, out List<WeakReference>? subscribers))
|
||||||
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers))
|
|
||||||
{
|
{
|
||||||
for (int i = subscribers.Count - 1; i >= 0; i--)
|
for (int i = subscribers.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
@@ -66,7 +65,7 @@ public class Subscription(SubscriptionCollection subscriptions,
|
|||||||
|
|
||||||
if (subscribers.Count == 0)
|
if (subscribers.Count == 0)
|
||||||
{
|
{
|
||||||
subscriptions.TryRemove(subscriptionKey, out _);
|
subscriptions.TryRemove(key, out _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
|
||||||
using Avalonia.Metadata;
|
using Avalonia.Metadata;
|
||||||
using Avalonia.Xaml.Interactivity;
|
using Avalonia.Xaml.Interactivity;
|
||||||
using Toolkit.Foundation;
|
using Toolkit.Foundation;
|
||||||
|
|||||||
Reference in New Issue
Block a user