diff --git a/LibreHardwareMonitor.Windows.WinUI.Tests/ViewModels/SensorSelectionServiceTests.cs b/LibreHardwareMonitor.Windows.WinUI.Tests/ViewModels/SensorSelectionServiceTests.cs new file mode 100644 index 0000000..9704c42 --- /dev/null +++ b/LibreHardwareMonitor.Windows.WinUI.Tests/ViewModels/SensorSelectionServiceTests.cs @@ -0,0 +1,83 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. + +using System.Linq; +using LibreHardwareMonitor.Hardware; +using LibreHardwareMonitor.Windows.WinUI.Services; +using LibreHardwareMonitor.Windows.WinUI.ViewModels; +using Moq; +using Xunit; + +namespace LibreHardwareMonitor.Windows.WinUI.Tests.ViewModels; + +public class SensorSelectionServiceTests +{ + [Fact] + public void SetSensorInTray_PersistsReadsBack_AndRaisesEvent() + { + (SensorSelectionService service, _, SensorTreeItemViewModel item) = Build(); + int raised = 0; + service.TraySensorsChanged += (_, _) => raised++; + + service.SetSensorInTray(item, true); + Assert.True(service.IsSensorInTray(item)); + + service.SetSensorInTray(item, false); + Assert.False(service.IsSensorInTray(item)); + + Assert.Equal(2, raised); + } + + [Fact] + public void SetSensorInGadget_PersistsReadsBack_AndRaisesEvent() + { + (SensorSelectionService service, _, SensorTreeItemViewModel item) = Build(); + int raised = 0; + service.GadgetSensorsChanged += (_, _) => raised++; + + service.SetSensorInGadget(item, true); + Assert.True(service.IsSensorInGadget(item)); + + service.SetSensorInGadget(item, false); + Assert.False(service.IsSensorInGadget(item)); + + Assert.Equal(2, raised); + } + + [Fact] + public void GetTraySensorItems_ReturnsOnlyTrayFlaggedSensors() + { + (SensorSelectionService service, SensorTreeItemViewModel root, SensorTreeItemViewModel item) = Build(); + + service.SetSensorInTray(item, true); + Assert.Contains(item, service.GetTraySensorItems(root)); + + service.SetSensorInTray(item, false); + Assert.DoesNotContain(item, service.GetTraySensorItems(root)); + } + + private static (SensorSelectionService Service, SensorTreeItemViewModel Root, SensorTreeItemViewModel SensorItem) Build() + { + AppSettings settings = AppSettings.LoadDefault(); + + var hardwareMock = new Mock(); + var sensorMock = new Mock(); + sensorMock.Setup(s => s.Name).Returns("Sensor"); + sensorMock.Setup(s => s.SensorType).Returns(SensorType.Temperature); + sensorMock.Setup(s => s.Index).Returns(0); + sensorMock.Setup(s => s.Identifier).Returns(new Identifier("cpu", "0", "temperature", "0")); + + hardwareMock.Setup(h => h.Name).Returns("CPU"); + hardwareMock.Setup(h => h.HardwareType).Returns(HardwareType.Cpu); + hardwareMock.Setup(h => h.Identifier).Returns(new Identifier("cpu", "0")); + hardwareMock.Setup(h => h.Sensors).Returns([sensorMock.Object]); + hardwareMock.Setup(h => h.SubHardware).Returns([]); + + var root = SensorTreeItemViewModel.CreateRoot("HOST"); + root.Children.Add(SensorTreeItemViewModel.FromHardware(hardwareMock.Object, settings)); + SensorTreeItemViewModel sensorItem = root.EnumerateSensors().First(); + + return (new SensorSelectionService(settings), root, sensorItem); + } +} diff --git a/LibreHardwareMonitor.Windows.WinUI/ViewModels/MainWindowViewModel.cs b/LibreHardwareMonitor.Windows.WinUI/ViewModels/MainWindowViewModel.cs index 6c0a0fd..bff804d 100644 --- a/LibreHardwareMonitor.Windows.WinUI/ViewModels/MainWindowViewModel.cs +++ b/LibreHardwareMonitor.Windows.WinUI/ViewModels/MainWindowViewModel.cs @@ -85,6 +85,7 @@ public sealed class MainWindowViewModel : ViewModelBase, IDisposable private readonly DispatcherQueue _dispatcherQueue; private readonly Logger _logger; private readonly PlotTrackingService _plotTracking = new(); + private readonly SensorSelectionService _sensorSelection; private readonly RemoteWebServer _remoteWebServer; private readonly StartupService _startupService = new(); private readonly WinUiStartupTrace? _startupTrace; @@ -125,6 +126,7 @@ public sealed class MainWindowViewModel : ViewModelBase, IDisposable _dispatcherQueue = DispatcherQueue.GetForCurrentThread(); _hardwareMonitor = new HardwareMonitorService(settings); _logger = new Logger(_hardwareMonitor.Computer); + _sensorSelection = new SensorSelectionService(settings); _remoteWebServer = new RemoteWebServer( () => RootItems.FirstOrDefault(), _hardwareMonitor.Computer, @@ -163,9 +165,17 @@ public sealed class MainWindowViewModel : ViewModelBase, IDisposable public event EventHandler? PlotInvalidated; - public event EventHandler? GadgetSensorsChanged; + public event EventHandler? GadgetSensorsChanged + { + add => _sensorSelection.GadgetSensorsChanged += value; + remove => _sensorSelection.GadgetSensorsChanged -= value; + } - public event EventHandler? TraySensorsChanged; + public event EventHandler? TraySensorsChanged + { + add => _sensorSelection.TraySensorsChanged += value; + remove => _sensorSelection.TraySensorsChanged -= value; + } public Visibility MaxColumnVisibility => ShowMaxColumn ? Visibility.Visible : Visibility.Collapsed; @@ -789,42 +799,32 @@ public sealed class MainWindowViewModel : ViewModelBase, IDisposable public bool IsSensorInGadget(SensorTreeItemViewModel item) { - return item.Sensor != null && Settings.GetValue(GetSensorSettingName(item.Sensor, "gadget"), false); + return _sensorSelection.IsSensorInGadget(item); } public bool IsSensorInTray(SensorTreeItemViewModel item) { - return item.Sensor != null && Settings.GetValue(GetSensorSettingName(item.Sensor, "tray"), false); + return _sensorSelection.IsSensorInTray(item); } public IEnumerable GetGadgetSensorItems() { - return RootItems.FirstOrDefault()?.EnumerateSensors().Where(IsSensorInGadget) ?? []; + return _sensorSelection.GetGadgetSensorItems(RootItems.FirstOrDefault()); } public IEnumerable GetTraySensorItems() { - return RootItems.FirstOrDefault()?.EnumerateSensors().Where(IsSensorInTray) ?? []; + return _sensorSelection.GetTraySensorItems(RootItems.FirstOrDefault()); } public void SetSensorInGadget(SensorTreeItemViewModel item, bool value) { - if (item.Sensor == null) - return; - - SetSensorBooleanSetting(item.Sensor, "gadget", value); - GadgetSensorsChanged?.Invoke(this, EventArgs.Empty); + _sensorSelection.SetSensorInGadget(item, value); } public void SetSensorInTray(SensorTreeItemViewModel item, bool value) { - if (item.Sensor == null) - return; - - SetSensorBooleanSetting(item.Sensor, "tray", value); - if (!value) - Settings.Remove(GetSensorSettingName(item.Sensor, "traycolor")); - TraySensorsChanged?.Invoke(this, EventArgs.Empty); + _sensorSelection.SetSensorInTray(item, value); } public void SetSensorPenColor(SensorTreeItemViewModel item, Color? color) @@ -1001,20 +1001,6 @@ public sealed class MainWindowViewModel : ViewModelBase, IDisposable OnPropertyChanged(); } - private void SetSensorBooleanSetting(ISensor sensor, string suffix, bool value) - { - string settingName = GetSensorSettingName(sensor, suffix); - if (value) - Settings.SetValue(settingName, true); - else - Settings.Remove(settingName); - } - - private static string GetSensorSettingName(ISensor sensor, string suffix) - { - return new Identifier(sensor.Identifier, suffix).ToString(); - } - private void SetHardwareFlag(bool value, bool currentValue, Action setValue) { if (currentValue == value) diff --git a/LibreHardwareMonitor.Windows.WinUI/ViewModels/SensorSelectionService.cs b/LibreHardwareMonitor.Windows.WinUI/ViewModels/SensorSelectionService.cs new file mode 100644 index 0000000..cabe22e --- /dev/null +++ b/LibreHardwareMonitor.Windows.WinUI/ViewModels/SensorSelectionService.cs @@ -0,0 +1,84 @@ +// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. +// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +// Copyright (C) LibreHardwareMonitor and Contributors. + +using System; +using System.Collections.Generic; +using System.Linq; +using LibreHardwareMonitor.Hardware; +using LibreHardwareMonitor.Windows.WinUI.Services; + +namespace LibreHardwareMonitor.Windows.WinUI.ViewModels; + +/// +/// Tracks which sensors the user has chosen to show in the system-tray icons and in the desktop gadget, persisting each +/// choice as a per-sensor setting. Extracted from to keep that selection concern (and +/// its settings-key convention) in one testable place. +/// +internal sealed class SensorSelectionService +{ + private readonly AppSettings _settings; + + public SensorSelectionService(AppSettings settings) + { + _settings = settings; + } + + public event EventHandler? GadgetSensorsChanged; + + public event EventHandler? TraySensorsChanged; + + public bool IsSensorInGadget(SensorTreeItemViewModel item) + { + return item.Sensor != null && _settings.GetValue(GetSensorSettingName(item.Sensor, "gadget"), false); + } + + public bool IsSensorInTray(SensorTreeItemViewModel item) + { + return item.Sensor != null && _settings.GetValue(GetSensorSettingName(item.Sensor, "tray"), false); + } + + public IEnumerable GetGadgetSensorItems(SensorTreeItemViewModel? root) + { + return root?.EnumerateSensors().Where(IsSensorInGadget) ?? []; + } + + public IEnumerable GetTraySensorItems(SensorTreeItemViewModel? root) + { + return root?.EnumerateSensors().Where(IsSensorInTray) ?? []; + } + + public void SetSensorInGadget(SensorTreeItemViewModel item, bool value) + { + if (item.Sensor == null) + return; + + SetSensorBooleanSetting(item.Sensor, "gadget", value); + GadgetSensorsChanged?.Invoke(this, EventArgs.Empty); + } + + public void SetSensorInTray(SensorTreeItemViewModel item, bool value) + { + if (item.Sensor == null) + return; + + SetSensorBooleanSetting(item.Sensor, "tray", value); + if (!value) + _settings.Remove(GetSensorSettingName(item.Sensor, "traycolor")); + TraySensorsChanged?.Invoke(this, EventArgs.Empty); + } + + public static string GetSensorSettingName(ISensor sensor, string suffix) + { + return new Identifier(sensor.Identifier, suffix).ToString(); + } + + private void SetSensorBooleanSetting(ISensor sensor, string suffix, bool value) + { + string settingName = GetSensorSettingName(sensor, suffix); + if (value) + _settings.SetValue(settingName, true); + else + _settings.Remove(settingName); + } +}