Files
PowerToys/src/settings-ui/Settings.UI/ViewModels/HostsViewModel.cs
Noraa Junker 7cd201d355 Remove ISettingsUtils and ISettingsPath interfaces (#44331)
<!-- Enter a brief description/summary of your PR here. What does it
fix/what does it change/how was it tested (even manually, if necessary)?
-->
## Summary of the Pull Request

This PR removes the ISettingsUtils and ISettingsPath interfaces to
reduce some complexity. They only existed so the classes can be used
with moq. But this is also possible by using virtual methods which is
cleaner.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist

- [ ] Closes: #xxx
<!-- - [ ] Closes: #yyy (add separate lines for additional resolved
issues) -->
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [x] **Tests:** Added/updated and all pass
- [ ] **Localization:** All end-user-facing strings can be localized
- [ ] **Dev docs:** Added/updated
- [ ] **New binaries:** Added on the required places
- [ ] [JSON for
signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json)
for new binaries
- [ ] [WXS for
installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs)
for new binaries and localization folder
- [ ] [YML for CI
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml)
for new test projects
- [ ] [YML for signed
pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml)
- [ ] **Documentation updated:** If checked, please file a pull request
on [our docs
repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys)
and link it here: #xxx
2025-12-19 10:30:01 +08:00

280 lines
9.0 KiB
C#

// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using global::PowerToys.GPOWrapper;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands;
using PowerToys.Interop;
using Settings.UI.Library.Enumerations;
namespace Microsoft.PowerToys.Settings.UI.ViewModels
{
public partial class HostsViewModel : Observable
{
private bool _isElevated;
private GpoRuleConfigured _enabledGpoRuleConfiguration;
private bool _enabledStateIsGPOConfigured;
private bool _isEnabled;
private SettingsUtils SettingsUtils { get; set; }
private GeneralSettings GeneralSettingsConfig { get; set; }
private HostsSettings Settings { get; set; }
private Func<string, int> SendConfigMSG { get; }
public ButtonClickCommand LaunchEventHandler => new ButtonClickCommand(Launch);
public ButtonClickCommand SelectBackupPathEventHandler => new ButtonClickCommand(SelectBackupPath);
public bool IsEnabled
{
get => _isEnabled;
set
{
if (_enabledStateIsGPOConfigured)
{
// If it's GPO configured, shouldn't be able to change this state.
return;
}
if (value != _isEnabled)
{
_isEnabled = value;
// Set the status in the general settings configuration
GeneralSettingsConfig.Enabled.Hosts = value;
OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(snd.ToString());
OnPropertyChanged(nameof(IsEnabled));
}
}
}
public bool IsEnabledGpoConfigured
{
get => _enabledStateIsGPOConfigured;
}
public bool LaunchAdministratorEnabled => IsEnabled && !_isElevated;
public bool ShowStartupWarning
{
get => Settings.Properties.ShowStartupWarning;
set
{
if (value != Settings.Properties.ShowStartupWarning)
{
Settings.Properties.ShowStartupWarning = value;
NotifyPropertyChanged();
}
}
}
public bool LoopbackDuplicates
{
get => Settings.Properties.LoopbackDuplicates;
set
{
if (value != Settings.Properties.LoopbackDuplicates)
{
Settings.Properties.LoopbackDuplicates = value;
NotifyPropertyChanged();
}
}
}
public bool LaunchAdministrator
{
get => Settings.Properties.LaunchAdministrator;
set
{
if (value != Settings.Properties.LaunchAdministrator)
{
Settings.Properties.LaunchAdministrator = value;
NotifyPropertyChanged();
}
}
}
public bool NoLeadingSpaces
{
get => Settings.Properties.NoLeadingSpaces;
set
{
if (value != Settings.Properties.NoLeadingSpaces)
{
Settings.Properties.NoLeadingSpaces = value;
NotifyPropertyChanged();
}
}
}
public int AdditionalLinesPosition
{
get => (int)Settings.Properties.AdditionalLinesPosition;
set
{
if (value != (int)Settings.Properties.AdditionalLinesPosition)
{
Settings.Properties.AdditionalLinesPosition = (HostsAdditionalLinesPosition)value;
NotifyPropertyChanged();
}
}
}
public int Encoding
{
get => (int)Settings.Properties.Encoding;
set
{
if (value != (int)Settings.Properties.Encoding)
{
Settings.Properties.Encoding = (HostsEncoding)value;
NotifyPropertyChanged();
}
}
}
public bool BackupHosts
{
get => Settings.Properties.BackupHosts;
set
{
if (value != Settings.Properties.BackupHosts)
{
Settings.Properties.BackupHosts = value;
NotifyPropertyChanged();
}
}
}
public string BackupPath
{
get => Settings.Properties.BackupPath;
set
{
if (value != Settings.Properties.BackupPath)
{
Settings.Properties.BackupPath = value;
NotifyPropertyChanged();
}
}
}
public int DeleteBackupsMode
{
get => (int)Settings.Properties.DeleteBackupsMode;
set
{
if (value != (int)Settings.Properties.DeleteBackupsMode)
{
Settings.Properties.DeleteBackupsMode = (HostsDeleteBackupMode)value;
NotifyPropertyChanged();
OnPropertyChanged(nameof(MinimumBackupsCount));
}
}
}
public int DeleteBackupsDays
{
get => Settings.Properties.DeleteBackupsDays;
set
{
if (value != Settings.Properties.DeleteBackupsDays)
{
Settings.Properties.DeleteBackupsDays = value;
NotifyPropertyChanged();
}
}
}
public int DeleteBackupsCount
{
get => Settings.Properties.DeleteBackupsCount;
set
{
if (value != Settings.Properties.DeleteBackupsCount)
{
Settings.Properties.DeleteBackupsCount = value;
NotifyPropertyChanged();
}
}
}
public int MinimumBackupsCount => DeleteBackupsMode == 1 ? 1 : 0;
public HostsViewModel(SettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<HostsSettings> moduleSettingsRepository, Func<string, int> ipcMSGCallBackFunc, bool isElevated)
{
SettingsUtils = settingsUtils;
GeneralSettingsConfig = settingsRepository.SettingsConfig;
Settings = moduleSettingsRepository.SettingsConfig;
SendConfigMSG = ipcMSGCallBackFunc;
_isElevated = isElevated;
InitializeEnabledValue();
}
private void InitializeEnabledValue()
{
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredHostsFileEditorEnabledValue();
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
{
// Get the enabled state from GPO.
_enabledStateIsGPOConfigured = true;
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
}
else
{
_isEnabled = GeneralSettingsConfig.Enabled.Hosts;
}
}
public void Launch()
{
string eventName = !_isElevated && LaunchAdministrator
? Constants.ShowHostsAdminSharedEvent()
: Constants.ShowHostsSharedEvent();
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName))
{
eventHandle.Set();
}
}
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
OnPropertyChanged(propertyName);
SettingsUtils.SaveSettings(Settings.ToJsonString(), HostsSettings.ModuleName);
}
public void RefreshEnabledState()
{
InitializeEnabledValue();
OnPropertyChanged(nameof(IsEnabled));
}
public void SelectBackupPath()
{
// This function was changed to use the shell32 API to open folder dialog
// as the old one (PickSingleFolderAsync) can't work when the process is elevated
// TODO: go back PickSingleFolderAsync when it's fixed
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.GetSettingsWindow());
var result = ShellGetFolder.GetFolderDialog(hwnd);
if (!string.IsNullOrEmpty(result))
{
BackupPath = result;
}
}
}
}