Fixed disposer?
This commit is contained in:
@@ -4,7 +4,8 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:interactions="using:Microsoft.Xaml.Interactions.Core"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity">
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
Visibility="{x:Bind ViewModel.Visible, Mode=OneWay}">
|
||||
<UserControl.Resources>
|
||||
<SolidColorBrush x:Key="ButtonBackground" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="ButtonBorderBrush" Color="Transparent" />
|
||||
|
||||
@@ -8,4 +8,6 @@ public sealed partial class MediaButtonView :
|
||||
{
|
||||
public MediaButtonView() =>
|
||||
this.InitializeComponent(ref _contentLoaded);
|
||||
|
||||
private MediaButtonViewModel ViewModel => (MediaButtonViewModel)DataContext;
|
||||
}
|
||||
|
||||
@@ -2,14 +2,7 @@
|
||||
|
||||
namespace Hyperbar.Widget.MediaController.Windows;
|
||||
|
||||
public class MediaButtonViewModel :
|
||||
WidgetButtonViewModel,
|
||||
IInitialization,
|
||||
INotificationHandler<Changed<PlaybackInformation>>
|
||||
{
|
||||
private readonly PlaybackButtonType buttonType;
|
||||
|
||||
public MediaButtonViewModel(IServiceFactory serviceFactory,
|
||||
public class MediaButtonViewModel(IServiceFactory serviceFactory,
|
||||
IMediator mediator,
|
||||
IDisposer disposer,
|
||||
ITemplateFactory templateFactory,
|
||||
@@ -17,12 +10,11 @@ public class MediaButtonViewModel :
|
||||
Guid guid = default,
|
||||
string? text = null,
|
||||
string? icon = null,
|
||||
RelayCommand? command = null) : base (serviceFactory, mediator, disposer, templateFactory, guid, text, icon, command)
|
||||
{
|
||||
this.buttonType = buttonType;
|
||||
mediator.Subscribe(this);
|
||||
}
|
||||
|
||||
RelayCommand? command = null) :
|
||||
WidgetButtonViewModel(serviceFactory, mediator, disposer, templateFactory, guid, text, icon, command),
|
||||
IInitialization,
|
||||
INotificationHandler<Changed<PlaybackInformation>>
|
||||
{
|
||||
public Task Handle(Changed<PlaybackInformation> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
@@ -31,10 +23,10 @@ public class MediaButtonViewModel :
|
||||
switch (buttonType)
|
||||
{
|
||||
case PlaybackButtonType.Play:
|
||||
Visible = information.Status is PlaybackStatus.Playing;
|
||||
Visible = information.Status is PlaybackStatus.Paused;
|
||||
break;
|
||||
case PlaybackButtonType.Pause:
|
||||
Visible = information.Status is PlaybackStatus.Paused;
|
||||
Visible = information.Status is PlaybackStatus.Playing;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,28 +5,31 @@ namespace Hyperbar.Widget.MediaController.Windows;
|
||||
public class MediaControllerHandler(IMediator mediator,
|
||||
IServiceScopeProvider<MediaController> scopeProvider,
|
||||
ICache<MediaController, MediaControllerViewModel> cache) :
|
||||
INotificationHandler<Created<MediaController>>
|
||||
INotificationHandler<Created<MediaController>>,
|
||||
INotificationHandler<Removed<MediaController>>
|
||||
{
|
||||
public async Task Handle(Created<MediaController> notification,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (notification.Value is MediaController mediaController)
|
||||
if (notification.Value is MediaController mediaController &&
|
||||
scopeProvider.TryGet(mediaController, out IServiceScope? serviceScope) &&
|
||||
serviceScope?.ServiceProvider.GetService<IFactory<MediaController, MediaControllerViewModel?>>()
|
||||
is IFactory<MediaController, MediaControllerViewModel?> factory &&
|
||||
factory.Create(mediaController) is MediaControllerViewModel viewModel)
|
||||
{
|
||||
if (scopeProvider.TryGet(mediaController, out IServiceScope? serviceScope))
|
||||
cache.Add(mediaController, viewModel);
|
||||
await mediator.PublishAsync(new Created<MediaControllerViewModel>(viewModel), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
if (serviceScope is not null)
|
||||
public async Task Handle(Removed<MediaController> notification, CancellationToken cancellationToken)
|
||||
{
|
||||
if (serviceScope.ServiceProvider.GetService<IFactory<MediaController, MediaControllerViewModel?>>()
|
||||
is IFactory<MediaController, MediaControllerViewModel?> factory)
|
||||
if (notification.Value is MediaController mediaController &&
|
||||
cache.TryGetValue(mediaController, out MediaControllerViewModel? viewModel) &&
|
||||
viewModel is not null)
|
||||
{
|
||||
if (factory.Create(mediaController) is MediaControllerViewModel mediaControllerViewModel)
|
||||
{
|
||||
cache.Add(mediaController, mediaControllerViewModel);
|
||||
await mediator.PublishAsync(new Created<MediaControllerViewModel>(mediaControllerViewModel),
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
await mediator.PublishAsync(new Removed<MediaControllerViewModel>(viewModel), cancellationToken);
|
||||
cache.Remove(mediaController);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class MediaControllerManager(IMediator mediator,
|
||||
{
|
||||
if (!sessions.Any(x => x.SourceAppUserModelId == session.Key.SourceAppUserModelId))
|
||||
{
|
||||
await dispatcher.InvokeAsync(() => disposer.Dispose(session.Value));
|
||||
await mediator.PublishAsync(new Removed<MediaController>(session.Value));
|
||||
cache.Remove(session);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@ public class MediaControllerViewModel :
|
||||
Add<MediaButtonViewModel>(PlaybackButtonType.Forward,
|
||||
"Forward", "\uEB9D",
|
||||
new RelayCommand(async () => await mediator.PublishAsync<Forward>()));
|
||||
|
||||
mediator.Subscribe(this);
|
||||
}
|
||||
|
||||
public ITemplateFactory TemplateFactory { get; set; }
|
||||
|
||||
@@ -41,16 +41,6 @@ public class Cache<TKey, TValue>(IDisposer disposer) :
|
||||
TValue value)
|
||||
{
|
||||
cache.TryAdd(key, value);
|
||||
|
||||
disposer.Add(value, Disposable.Create(() =>
|
||||
{
|
||||
Remove(key);
|
||||
}));
|
||||
|
||||
disposer.Add(key, Disposable.Create(() =>
|
||||
{
|
||||
Remove(key);
|
||||
}));
|
||||
}
|
||||
|
||||
public void Clear() => cache.Clear();
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
namespace Hyperbar;
|
||||
|
||||
namespace Hyperbar;
|
||||
|
||||
public interface IObservableCollectionViewModel<TItem> :
|
||||
IList<TItem>,
|
||||
IList,
|
||||
IReadOnlyList<TItem>,
|
||||
INotifyCollectionChanged;
|
||||
public interface IObservableCollectionViewModel<TItem>;
|
||||
@@ -11,6 +11,10 @@ namespace Hyperbar;
|
||||
public partial class ObservableCollectionViewModel<TItem> :
|
||||
ObservableObject,
|
||||
IObservableCollectionViewModel<TItem>,
|
||||
IList<TItem>,
|
||||
IList,
|
||||
IReadOnlyList<TItem>,
|
||||
INotifyCollectionChanged,
|
||||
INotificationHandler<Removed<TItem>>,
|
||||
INotificationHandler<Created<TItem>>,
|
||||
INotificationHandler<Inserted<TItem>>,
|
||||
@@ -134,6 +138,12 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
InsertItem(index, item);
|
||||
}
|
||||
|
||||
public void Add(object item)
|
||||
{
|
||||
int index = collection.Count;
|
||||
InsertItem(index, (TItem)item);
|
||||
}
|
||||
|
||||
int IList.Add(object? value)
|
||||
{
|
||||
TItem? item = default;
|
||||
@@ -159,7 +169,15 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear() => ClearItems();
|
||||
public void Clear()
|
||||
{
|
||||
foreach (TItem item in collection)
|
||||
{
|
||||
Disposer.Dispose(item);
|
||||
}
|
||||
|
||||
ClearItems();
|
||||
}
|
||||
|
||||
public bool Contains(TItem item) =>
|
||||
collection.Contains(item);
|
||||
@@ -173,8 +191,11 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
void ICollection.CopyTo(Array array, int index) =>
|
||||
collection.CopyTo((TItem[])array, index);
|
||||
|
||||
public void Dispose() =>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
Disposer.Dispose(this);
|
||||
}
|
||||
|
||||
public System.Collections.Generic.IEnumerator<TItem> GetEnumerator() =>
|
||||
collection.GetEnumerator();
|
||||
@@ -187,15 +208,9 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
{
|
||||
foreach (TItem item in this.ToList())
|
||||
{
|
||||
if (notification.Value is not null)
|
||||
if (notification.Value is not null && notification.Value.Equals(item))
|
||||
{
|
||||
if (notification.Value.Equals(item))
|
||||
{
|
||||
if (item is IDisposable disposable)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
Remove(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +294,7 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
return false;
|
||||
}
|
||||
|
||||
Disposer.Remove(this, item);
|
||||
Disposer.Dispose(item);
|
||||
RemoveItem(index);
|
||||
|
||||
return true;
|
||||
@@ -302,14 +317,13 @@ public partial class ObservableCollectionViewModel<TItem> :
|
||||
protected virtual void InsertItem(int index,
|
||||
TItem value)
|
||||
{
|
||||
Disposer.Add(this, Disposable.Create(() =>
|
||||
Disposer.Add(this, value);
|
||||
Disposer.Add(value, value, Disposable.Create(() =>
|
||||
{
|
||||
Remove(value);
|
||||
}));
|
||||
|
||||
Disposer.Add(value, Disposable.Create(() =>
|
||||
if (value is IList collection)
|
||||
{
|
||||
Remove(value);
|
||||
collection.Clear();
|
||||
}
|
||||
}));
|
||||
|
||||
collection.Insert(index, value);
|
||||
|
||||
@@ -8,7 +8,7 @@ public class Mediator(IServiceProvider provider,
|
||||
IDispatcher dispatcher) :
|
||||
IMediator
|
||||
{
|
||||
private readonly ConcurrentDictionary<object, List<dynamic>> subjects = [];
|
||||
private readonly ConcurrentDictionary<object, List<dynamic>> subscriptions = [];
|
||||
|
||||
public Task PublishAsync<TNotification>(object key,
|
||||
CancellationToken cancellationToken = default)
|
||||
@@ -46,11 +46,14 @@ public class Mediator(IServiceProvider provider,
|
||||
List<INotificationHandler<TNotification>> handlers =
|
||||
provider.GetServices<INotificationHandler<TNotification>>().ToList();
|
||||
|
||||
foreach (KeyValuePair<object, List<dynamic>> handler in subjects)
|
||||
foreach (KeyValuePair<object, List<dynamic>> subscriber in subscriptions)
|
||||
{
|
||||
if (key is not null && handler.Key.Equals(key) || handler.Key.Equals(typeof(TNotification)))
|
||||
if (subscriber.Key.Equals($"{(key is not null ? $"{key}:" : "")}{typeof(TNotification)}"))
|
||||
{
|
||||
handlers.Add(handler.Value[0]);
|
||||
foreach (dynamic handler in subscriber.Value)
|
||||
{
|
||||
handlers.Add(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,14 +114,9 @@ public class Mediator(IServiceProvider provider,
|
||||
|
||||
foreach (Type interfaceType in GetNotificationHandlerInterfaces(handlerType))
|
||||
{
|
||||
if (interfaceType.GetGenericArguments().FirstOrDefault()
|
||||
is Type argumentType)
|
||||
if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType)
|
||||
{
|
||||
if (object.Equals(key, default))
|
||||
{
|
||||
|
||||
}
|
||||
subjects.AddOrUpdate(key ?? argumentType, new List<object> { handler }, (value, collection) =>
|
||||
subscriptions.AddOrUpdate($"{(key is not null ? $"{key}:" : "")}{argumentType}", new List<object> { handler }, (value, collection) =>
|
||||
{
|
||||
collection.Add(handler);
|
||||
return collection;
|
||||
|
||||
Reference in New Issue
Block a user