1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Fixed VM disposal issues

This commit is contained in:
Robert 2023-05-12 23:27:27 +02:00
parent 5adc837673
commit e783dcaa58
8 changed files with 17 additions and 36 deletions

View File

@ -11,10 +11,9 @@ public static class LinuxInputDeviceFinder
public static IEnumerable<LinuxInputDevice> Find() public static IEnumerable<LinuxInputDevice> Find()
{ {
var lineGroups = File.ReadAllLines(DEVICES_FILE) IEnumerable<IEnumerable<string>> lineGroups = File.ReadAllLines(DEVICES_FILE).PartitionBy(s => s?.Length == 0); //split on empty lines
.PartitionBy(s => s?.Length == 0); //split on empty lines
foreach (var lineGroup in lineGroups) foreach (IEnumerable<string> lineGroup in lineGroups)
{ {
LinuxInputDevice device; LinuxInputDevice device;

View File

@ -54,7 +54,7 @@ internal class PropertyInputService : IPropertyInputService
return existing; return existing;
} }
_container.Register(viewModelType); _container.Register(viewModelType, setup: Setup.With(preventDisposal: true));
PropertyInputRegistration registration = new(this, plugin, supportedType, viewModelType); PropertyInputRegistration registration = new(this, plugin, supportedType, viewModelType);
_registeredPropertyEditors.Add(registration); _registeredPropertyEditors.Add(registration);
return registration; return registration;

View File

@ -220,7 +220,7 @@ public abstract class PropertyInputViewModel<T> : PropertyInputViewModel
/// <summary> /// <summary>
/// For internal use only, implement <see cref="PropertyInputViewModel" /> instead. /// For internal use only, implement <see cref="PropertyInputViewModel" /> instead.
/// </summary> /// </summary>
public abstract class PropertyInputViewModel : ReactiveValidationObject, IActivatableViewModel, IDisposable public abstract class PropertyInputViewModel : ReactiveValidationObject, IActivatableViewModel
{ {
/// <summary> /// <summary>
/// Prevents this type being implemented directly, implement /// Prevents this type being implemented directly, implement
@ -229,28 +229,6 @@ public abstract class PropertyInputViewModel : ReactiveValidationObject, IActiva
// ReSharper disable once UnusedMember.Global // ReSharper disable once UnusedMember.Global
internal abstract object InternalGuard { get; } internal abstract object InternalGuard { get; }
/// <summary>
/// Releases the unmanaged resources used by the object and optionally releases the managed resources.
/// </summary>
/// <param name="disposing">
/// <see langword="true" /> to release both managed and unmanaged resources;
/// <see langword="false" /> to release only unmanaged resources.
/// </param>
protected virtual void Dispose(bool disposing)
{
}
#region Implementation of IActivatableViewModel
/// <inheritdoc /> /// <inheritdoc />
public ViewModelActivator Activator { get; } = new(); public ViewModelActivator Activator { get; } = new();
#endregion
/// <inheritdoc />
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
} }

View File

@ -25,7 +25,7 @@ public static class ContainerExtensions
Assembly[] thisAssembly = {typeof(ContainerExtensions).Assembly}; Assembly[] thisAssembly = {typeof(ContainerExtensions).Assembly};
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<ViewModelBase>(), setup: Setup.With(preventDisposal: true)); container.RegisterMany(thisAssembly, type => type.IsAssignableTo<ViewModelBase>(), setup: Setup.With(preventDisposal: true));
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<IToolViewModel>() && type.IsInterface); container.RegisterMany(thisAssembly, type => type.IsAssignableTo<IToolViewModel>() && type.IsInterface, setup: Setup.With(preventDisposal: true));
container.RegisterMany(thisAssembly, type => type.IsAssignableTo<IVmFactory>() && type != typeof(PropertyVmFactory)); container.RegisterMany(thisAssembly, type => type.IsAssignableTo<IVmFactory>() && type != typeof(PropertyVmFactory));
container.Register<NodeScriptWindowViewModelBase, NodeScriptWindowViewModel>(Reuse.Singleton); container.Register<NodeScriptWindowViewModelBase, NodeScriptWindowViewModel>(Reuse.Singleton);

View File

@ -13,7 +13,8 @@
VerticalAlignment="Top" VerticalAlignment="Top"
Source="/Assets/Images/home-banner.png" Source="/Assets/Images/home-banner.png"
Height="200" Height="200"
Stretch="UniformToFill" /> Stretch="UniformToFill"
RenderOptions.BitmapInterpolationMode="HighQuality"/>
<!-- TODO: Replace with a shadow when available --> <!-- TODO: Replace with a shadow when available -->
<TextBlock Grid.Row="0" <TextBlock Grid.Row="0"

View File

@ -17,9 +17,13 @@ public partial class TreePropertyView : ReactiveUserControl<ITreePropertyViewMod
InitializeComponent(); InitializeComponent();
this.WhenActivated(d => this.WhenActivated(d =>
{ {
Observable.FromEventPattern<LayerPropertyEventArgs>(e => ViewModel!.BaseLayerProperty.CurrentValueSet += e, e => ViewModel!.BaseLayerProperty.CurrentValueSet -= e) ITreePropertyViewModel? viewModel = ViewModel;
if (viewModel != null)
{
Observable.FromEventPattern<LayerPropertyEventArgs>(e => viewModel.BaseLayerProperty.CurrentValueSet += e, e => viewModel.BaseLayerProperty.CurrentValueSet -= e)
.Subscribe(_ => this.BringIntoView()) .Subscribe(_ => this.BringIntoView())
.DisposeWith(d); .DisposeWith(d);
}
}); });
} }

View File

@ -32,7 +32,6 @@ internal class TreePropertyViewModel<T> : ActivatableViewModelBase, ITreePropert
_profileEditorService.Time.Subscribe(t => _time = t).DisposeWith(d); _profileEditorService.Time.Subscribe(t => _time = t).DisposeWith(d);
_isCurrentlySelected = _profileEditorService.LayerProperty.Select(l => l == LayerProperty).ToProperty(this, vm => vm.IsCurrentlySelected).DisposeWith(d); _isCurrentlySelected = _profileEditorService.LayerProperty.Select(l => l == LayerProperty).ToProperty(this, vm => vm.IsCurrentlySelected).DisposeWith(d);
_dataBindingEnabled = LayerProperty.BaseDataBinding.AsObservable().Select(b => b.IsEnabled).ToProperty(this, vm => vm.DataBindingEnabled).DisposeWith(d); _dataBindingEnabled = LayerProperty.BaseDataBinding.AsObservable().Select(b => b.IsEnabled).ToProperty(this, vm => vm.DataBindingEnabled).DisposeWith(d);
this.WhenAnyValue(vm => vm.LayerProperty.KeyframesEnabled).Subscribe(_ => this.RaisePropertyChanged(nameof(KeyframesEnabled))).DisposeWith(d); this.WhenAnyValue(vm => vm.LayerProperty.KeyframesEnabled).Subscribe(_ => this.RaisePropertyChanged(nameof(KeyframesEnabled))).DisposeWith(d);
}); });

View File

@ -22,7 +22,6 @@ namespace Artemis.UI.Screens.ProfileEditor;
public class ProfileEditorViewModel : MainScreenViewModel public class ProfileEditorViewModel : MainScreenViewModel
{ {
private readonly IMainWindowService _mainWindowService;
private readonly IProfileEditorService _profileEditorService; private readonly IProfileEditorService _profileEditorService;
private readonly ISettingsService _settingsService; private readonly ISettingsService _settingsService;
private readonly SourceList<IToolViewModel> _tools; private readonly SourceList<IToolViewModel> _tools;
@ -51,7 +50,6 @@ public class ProfileEditorViewModel : MainScreenViewModel
{ {
_profileEditorService = profileEditorService; _profileEditorService = profileEditorService;
_settingsService = settingsService; _settingsService = settingsService;
_mainWindowService = mainWindowService;
_tools = new SourceList<IToolViewModel>(); _tools = new SourceList<IToolViewModel>();
_tools.AddRange(toolViewModels); _tools.AddRange(toolViewModels);
@ -77,6 +75,8 @@ public class ProfileEditorViewModel : MainScreenViewModel
{ {
mainWindowService.MainWindowFocused -= MainWindowServiceOnMainWindowFocused; mainWindowService.MainWindowFocused -= MainWindowServiceOnMainWindowFocused;
mainWindowService.MainWindowUnfocused -= MainWindowServiceOnMainWindowUnfocused; mainWindowService.MainWindowUnfocused -= MainWindowServiceOnMainWindowUnfocused;
foreach (IToolViewModel toolViewModel in _tools.Items)
toolViewModel.Dispose();
}).DisposeWith(d); }).DisposeWith(d);
// Slow and steady wins the race (and doesn't lock up the entire UI) // Slow and steady wins the race (and doesn't lock up the entire UI)