diff --git a/README.md b/README.md index 926efe9137..64c79e9f4f 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ Preview Pane is an existing feature in the File Explorer. To enable it, you jus ### Video Conference Mute (Experimental) -[](https://aka.ms/PowerToysOverview_VideoConference) [Video Conference Mute](https://aka.ms/PowerToysOverview_VideoConference) is a quick and easy way to do an global "mute" of both your microphone and webcam via Win+N. Just set your webcam in the target application to the PowerToys VideoConference camera. +[](https://aka.ms/PowerToysOverview_VideoConference) [Video Conference Mute](https://aka.ms/PowerToysOverview_VideoConference) is a quick and easy way to do a global "mute" of both your microphone and webcam via Win+N. Just set your webcam in the target application to the PowerToys VideoConference camera. **Note:** This is only included in the [pre-release version of PowerToys installer][github-prerelease-link]. This PowerToy requires Windows 10 1903 (build 18362) or later.
diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 59c1b28f89..8d57f38edd 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -438,18 +438,18 @@ - + - + - + diff --git a/src/action_runner/action_runner.cpp b/src/action_runner/action_runner.cpp index 36ee2add59..acabf8d767 100644 --- a/src/action_runner/action_runner.cpp +++ b/src/action_runner/action_runner.cpp @@ -190,7 +190,8 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) } else { - params = args[nextArg]; + params += args[nextArg]; + params += L' '; nextArg++; } } diff --git a/src/common/interop/interop.h b/src/common/interop/interop.h index 1de9837b74..45f71e44a6 100644 --- a/src/common/interop/interop.h +++ b/src/common/interop/interop.h @@ -127,5 +127,10 @@ public { public: literal int VK_WIN_BOTH = CommonSharedConstants::VK_WIN_BOTH; + + static String^ PowerLauncherSharedEvent() + { + return gcnew String(CommonSharedConstants::POWER_LAUNCHER_SHARED_EVENT); + } }; } diff --git a/src/common/settings_objects.cpp b/src/common/settings_objects.cpp index a6bdcd58cd..2bd2e8ca68 100644 --- a/src/common/settings_objects.cpp +++ b/src/common/settings_objects.cpp @@ -343,6 +343,11 @@ namespace PowerToysSettings return m_json.GetNamedObject(L"properties").GetNamedObject(property_name).GetNamedObject(L"value"); } + json::JsonObject PowerToyValues::get_raw_json() + { + return m_json; + } + std::wstring PowerToyValues::serialize() { set_version(); diff --git a/src/common/settings_objects.h b/src/common/settings_objects.h index 52f654b962..3f2a212eb6 100644 --- a/src/common/settings_objects.h +++ b/src/common/settings_objects.h @@ -83,6 +83,7 @@ namespace PowerToysSettings std::optional get_int_value(std::wstring_view property_name); std::optional get_string_value(std::wstring_view property_name); std::optional get_json(std::wstring_view property_name); + json::JsonObject get_raw_json(); std::wstring serialize(); void save_to_settings_file(); diff --git a/src/common/shared_constants.h b/src/common/shared_constants.h index f5a5b0b5de..69f5499454 100644 --- a/src/common/shared_constants.h +++ b/src/common/shared_constants.h @@ -8,4 +8,7 @@ namespace CommonSharedConstants // Fake key code to represent VK_WIN. inline const DWORD VK_WIN_BOTH = 0x104; -} \ No newline at end of file + + // Path to the event used by PowerLauncher + const wchar_t POWER_LAUNCHER_SHARED_EVENT[] = L"Local\\PowerToysRunInvokeEvent-30f26ad7-d36d-4c0e-ab02-68bb5ff3c4ab"; +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ColorPickerSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ColorPickerSettings.cs index 382f6927fa..849bae1909 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ColorPickerSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ColorPickerSettings.cs @@ -4,10 +4,11 @@ using System.Text.Json; using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class ColorPickerSettings : BasePTModuleSettings + public class ColorPickerSettings : BasePTModuleSettings, ISettingsConfig { public const string ModuleName = "ColorPicker"; @@ -21,7 +22,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib Name = ModuleName; } - public virtual void Save() + public virtual void Save(ISettingsUtils settingsUtils) { // Save settings to file var options = new JsonSerializerOptions @@ -29,7 +30,18 @@ namespace Microsoft.PowerToys.Settings.UI.Lib WriteIndented = true, }; - SettingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName); + settingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName); + } + + public string GetModuleName() + { + return Name; + } + + // This can be utilized in the future if the settings.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/FancyZonesSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/FancyZonesSettings.cs index e3e49aa9f9..570b75cc97 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/FancyZonesSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/FancyZonesSettings.cs @@ -3,19 +3,33 @@ // See the LICENSE file in the project root for more information. using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class FancyZonesSettings : BasePTModuleSettings + public class FancyZonesSettings : BasePTModuleSettings, ISettingsConfig { + public const string ModuleName = "FancyZones"; + public FancyZonesSettings() { - Version = string.Empty; - Name = string.Empty; + Version = "1.0"; + Name = ModuleName; Properties = new FZConfigProperties(); } [JsonPropertyName("properties")] public FZConfigProperties Properties { get; set; } + + public string GetModuleName() + { + return Name; + } + + // This can be utilized in the future if the settings.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/GeneralSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/GeneralSettings.cs index 6b8a4932b0..637e531516 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/GeneralSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/GeneralSettings.cs @@ -2,12 +2,15 @@ // 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.Text.Json; using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; +using Microsoft.PowerToys.Settings.UI.Lib.Utilities; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class GeneralSettings + public class GeneralSettings : ISettingsConfig { // Gets or sets a value indicating whether packaged. [JsonPropertyName("packaged")] @@ -82,5 +85,32 @@ namespace Microsoft.PowerToys.Settings.UI.Lib { return interop.CommonManaged.GetProductVersion(); } + + // This function is to implement the ISettingsConfig interface. + // This interface helps in getting the settings configurations. + public string GetModuleName() + { + // The SettingsUtils functions access general settings when the module name is an empty string. + return string.Empty; + } + + public bool UpgradeSettingsConfiguration() + { + try + { + if (Helper.CompareVersions(PowertoysVersion, Helper.GetProductVersion()) < 0) + { + // Update settings + PowertoysVersion = Helper.GetProductVersion(); + return true; + } + } + catch (FormatException) + { + // If there is an issue with the version number format, don't migrate settings. + } + + return false; + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ISettingsUtils.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ISettingsUtils.cs new file mode 100644 index 0000000000..c5083f3a16 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ISettingsUtils.cs @@ -0,0 +1,20 @@ +// 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 Microsoft.PowerToys.Settings.UI.Lib.Interface; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public interface ISettingsUtils + { + T GetSettings(string powertoy = "", string fileName = "settings.json") + where T : ISettingsConfig, new(); + + void SaveSettings(string jsonSettings, string powertoy = "", string fileName = "settings.json"); + + bool SettingsExists(string powertoy = "", string fileName = "settings.json"); + + void DeleteSettings(string powertoy = ""); + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ImageResizerSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ImageResizerSettings.cs index fcf512f591..103d98f655 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ImageResizerSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ImageResizerSettings.cs @@ -4,10 +4,11 @@ using System.Text.Json; using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class ImageResizerSettings : BasePTModuleSettings + public class ImageResizerSettings : BasePTModuleSettings, ISettingsConfig { public const string ModuleName = "Image Resizer"; @@ -29,5 +30,16 @@ namespace Microsoft.PowerToys.Settings.UI.Lib }; return JsonSerializer.Serialize(this, options); } + + public string GetModuleName() + { + return Name; + } + + // This can be utilized in the future if the settings.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/Interface/ISettingsConfig.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Interface/ISettingsConfig.cs new file mode 100644 index 0000000000..fa0291568f --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Interface/ISettingsConfig.cs @@ -0,0 +1,16 @@ +// 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. + +namespace Microsoft.PowerToys.Settings.UI.Lib.Interface +{ + // Common interface to be implemented by all the objects which get and store settings properties. + public interface ISettingsConfig + { + string ToJsonString(); + + string GetModuleName(); + + bool UpgradeSettingsConfiguration(); + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/Interface/ISettingsRepository`1.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Interface/ISettingsRepository`1.cs new file mode 100644 index 0000000000..6caadb85f9 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Interface/ISettingsRepository`1.cs @@ -0,0 +1,11 @@ +// 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. + +namespace Microsoft.PowerToys.Settings.UI.Lib.Interface +{ + public interface ISettingsRepository + { + T SettingsConfig { get; set; } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerProfile.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerProfile.cs index 52a0c2d764..66246e2cc4 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerProfile.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerProfile.cs @@ -2,11 +2,13 @@ // 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.Text.Json; using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class KeyboardManagerProfile + public class KeyboardManagerProfile : ISettingsConfig { [JsonPropertyName("remapKeys")] public RemapKeysDataModel RemapKeys { get; set; } @@ -19,5 +21,21 @@ namespace Microsoft.PowerToys.Settings.UI.Lib RemapKeys = new RemapKeysDataModel(); RemapShortcuts = new ShortcutsKeyDataModel(); } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + + public string GetModuleName() + { + return KeyboardManagerSettings.ModuleName; + } + + // This can be utilized in the future if the default.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerSettings.cs index 12ff998159..ffe032a47e 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeyboardManagerSettings.cs @@ -3,11 +3,14 @@ // See the LICENSE file in the project root for more information. using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class KeyboardManagerSettings : BasePTModuleSettings + public class KeyboardManagerSettings : BasePTModuleSettings, ISettingsConfig { + public const string ModuleName = "Keyboard Manager"; + [JsonPropertyName("properties")] public KeyboardManagerProperties Properties { get; set; } @@ -15,14 +18,18 @@ namespace Microsoft.PowerToys.Settings.UI.Lib { Properties = new KeyboardManagerProperties(); Version = "1"; - Name = "_unset_"; + Name = ModuleName; } - public KeyboardManagerSettings(string ptName) + public string GetModuleName() { - Properties = new KeyboardManagerProperties(); - Version = "1"; - Name = ptName; + return Name; + } + + // This can be utilized in the future if the settings.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeysDataModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeysDataModel.cs index 286e5510ae..47f211b26d 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeysDataModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/KeysDataModel.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.PowerToys.Settings.UI.Lib.Utilities; @@ -35,5 +36,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib { return MapKeys(NewRemapKeys); } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerLauncherSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerLauncherSettings.cs index 9b73b878eb..124657664c 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerLauncherSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerLauncherSettings.cs @@ -4,10 +4,11 @@ using System.Text.Json; using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class PowerLauncherSettings : BasePTModuleSettings + public class PowerLauncherSettings : BasePTModuleSettings, ISettingsConfig { public const string ModuleName = "PowerToys Run"; @@ -21,7 +22,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib Name = ModuleName; } - public virtual void Save() + public virtual void Save(ISettingsUtils settingsUtils) { // Save settings to file var options = new JsonSerializerOptions @@ -29,7 +30,18 @@ namespace Microsoft.PowerToys.Settings.UI.Lib WriteIndented = true, }; - SettingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName); + settingsUtils.SaveSettings(JsonSerializer.Serialize(this, options), ModuleName); + } + + public string GetModuleName() + { + return Name; + } + + // This can be utilized in the future if the settings.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerPreviewSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerPreviewSettings.cs index afe67754f5..e56be7273d 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerPreviewSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerPreviewSettings.cs @@ -3,10 +3,11 @@ // See the LICENSE file in the project root for more information. using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class PowerPreviewSettings : BasePTModuleSettings + public class PowerPreviewSettings : BasePTModuleSettings, ISettingsConfig { public const string ModuleName = "File Explorer"; @@ -20,11 +21,15 @@ namespace Microsoft.PowerToys.Settings.UI.Lib Name = ModuleName; } - public PowerPreviewSettings(string ptName) + public string GetModuleName() { - Properties = new PowerPreviewProperties(); - Version = "1"; - Name = ptName; + return Name; + } + + // This can be utilized in the future if the settings.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameLocalProperties.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameLocalProperties.cs index a0ba1966fe..3136edd2a6 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameLocalProperties.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameLocalProperties.cs @@ -3,10 +3,11 @@ // See the LICENSE file in the project root for more information. using System.Text.Json; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class PowerRenameLocalProperties + public class PowerRenameLocalProperties : ISettingsConfig { public PowerRenameLocalProperties() { @@ -51,5 +52,18 @@ namespace Microsoft.PowerToys.Settings.UI.Lib { return JsonSerializer.Serialize(this); } + + // This function is required to implement the ISettingsConfig interface and obtain the settings configurations. + public string GetModuleName() + { + string moduleName = PowerRenameSettings.ModuleName; + return moduleName; + } + + // This can be utilized in the future if the settings.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameSettings.cs index a3be125bc5..0d7dc58a98 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerRenameSettings.cs @@ -3,10 +3,11 @@ // See the LICENSE file in the project root for more information. using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class PowerRenameSettings : BasePTModuleSettings + public class PowerRenameSettings : BasePTModuleSettings, ISettingsConfig { public const string ModuleName = "PowerRename"; @@ -39,5 +40,16 @@ namespace Microsoft.PowerToys.Settings.UI.Lib Version = "1"; Name = ptName; } + + public string GetModuleName() + { + return Name; + } + + // This can be utilized in the future if the power-rename-settings.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/RemapKeysDataModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/RemapKeysDataModel.cs index 4f359197ae..873d5d7d64 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/RemapKeysDataModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/RemapKeysDataModel.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Text.Json; using System.Text.Json.Serialization; namespace Microsoft.PowerToys.Settings.UI.Lib @@ -16,5 +17,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib { InProcessRemapKeys = new List(); } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsRepository`1.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsRepository`1.cs new file mode 100644 index 0000000000..3bb7df8518 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsRepository`1.cs @@ -0,0 +1,66 @@ +// 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 Microsoft.PowerToys.Settings.UI.Lib.Interface; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + // This Singleton class is a wrapper around the settings configurations that are accessed by viewmodels. + // This class can have only one instance and therefore the settings configurations are common to all. + public class SettingsRepository : ISettingsRepository + where T : class, ISettingsConfig, new() + { + private static readonly object _SettingsRepoLock = new object(); + + private static ISettingsUtils _settingsUtils; + + private static SettingsRepository settingsRepository; + + private T settingsConfig; + + public static SettingsRepository GetInstance(ISettingsUtils settingsUtils) + { + // To ensure that only one instance of Settings Repository is created in a multi-threaded environment. + lock (_SettingsRepoLock) + { + if (settingsRepository == null) + { + settingsRepository = new SettingsRepository(); + _settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils)); + } + + return settingsRepository; + } + } + + // The Singleton class must have a private constructor so that it cannot be instantiated by any other object other than itself. + private SettingsRepository() + { + } + + // Settings configurations shared across all viewmodels + public T SettingsConfig + { + get + { + if (settingsConfig == null) + { + T settingsItem = new T(); + settingsConfig = _settingsUtils.GetSettings(settingsItem.GetModuleName()); + } + + return settingsConfig; + } + + set + { + if (value != null) + { + settingsConfig = value; + } + } + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs index c69883369b..681727ba22 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs @@ -3,30 +3,36 @@ // See the LICENSE file in the project root for more information. using System; -using System.IO; -using System.Runtime.Serialization; using System.Text.Json; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; +using Microsoft.PowerToys.Settings.UI.Lib.Utilities; namespace Microsoft.PowerToys.Settings.UI.Lib { - public static class SettingsUtils + public class SettingsUtils : ISettingsUtils { private const string DefaultFileName = "settings.json"; private const string DefaultModuleName = ""; + private IIOProvider _ioProvider; - public static void DeleteSettings(string powertoy, string fileName = DefaultFileName) + public SettingsUtils(IIOProvider ioProvider) { - File.Delete(GetSettingsPath(powertoy, fileName)); + _ioProvider = ioProvider ?? throw new ArgumentNullException(nameof(ioProvider)); } - public static bool SettingsFolderExists(string powertoy) + private bool SettingsFolderExists(string powertoy) { - return Directory.Exists(Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}")); + return _ioProvider.DirectoryExists(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}")); } - public static void CreateSettingsFolder(string powertoy) + private void CreateSettingsFolder(string powertoy) { - Directory.CreateDirectory(Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}")); + _ioProvider.CreateDirectory(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}")); + } + + public void DeleteSettings(string powertoy = "") + { + _ioProvider.DeleteDirectory(System.IO.Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}")); } /// @@ -37,38 +43,64 @@ namespace Microsoft.PowerToys.Settings.UI.Lib { if (string.IsNullOrWhiteSpace(powertoy)) { - return Path.Combine( + return System.IO.Path.Combine( LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{fileName}"); } - return Path.Combine( + return System.IO.Path.Combine( LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}\\{fileName}"); } - public static bool SettingsExists(string powertoy = DefaultModuleName, string fileName = DefaultFileName) + public bool SettingsExists(string powertoy = DefaultModuleName, string fileName = DefaultFileName) { - return File.Exists(GetSettingsPath(powertoy, fileName)); + return _ioProvider.FileExists(GetSettingsPath(powertoy, fileName)); } /// /// Get a Deserialized object of the json settings string. + /// This function creates a file in the powertoy folder if it does not exist and returns an object with default properties. /// /// Deserialized json settings object. - public static T GetSettings(string powertoy = DefaultModuleName, string fileName = DefaultFileName) + public T GetSettings(string powertoy = DefaultModuleName, string fileName = DefaultFileName) + where T : ISettingsConfig, new() + { + if (SettingsExists(powertoy, fileName)) + { + // Given the file already exists, to deserialize the file and read it's content. + T deserializedSettings = GetFile(powertoy, fileName); + + // IF the file needs to be modified, to save the new configurations accordingly. + if (deserializedSettings.UpgradeSettingsConfiguration()) + { + SaveSettings(deserializedSettings.ToJsonString(), powertoy, fileName); + } + + return deserializedSettings; + } + else + { + // If the settings file does not exist, to create a new object with default parameters and save it to a newly created settings file. + T newSettingsItem = new T(); + SaveSettings(newSettingsItem.ToJsonString(), powertoy, fileName); + return newSettingsItem; + } + } + + // Given the powerToy folder name and filename to be accessed, this function deserializes and returns the file. + private T GetFile(string powertoyFolderName = DefaultModuleName, string fileName = DefaultFileName) { // Adding Trim('\0') to overcome possible NTFS file corruption. // Look at issue https://github.com/microsoft/PowerToys/issues/6413 you'll see the file has a large sum of \0 to fill up a 4096 byte buffer for writing to disk // This, while not totally ideal, does work around the problem by trimming the end. // The file itself did write the content correctly but something is off with the actual end of the file, hence the 0x00 bug - var jsonSettingsString = File.ReadAllText(GetSettingsPath(powertoy, fileName)).Trim('\0'); - + var jsonSettingsString = _ioProvider.ReadAllText(GetSettingsPath(powertoyFolderName, fileName)).Trim('\0'); return JsonSerializer.Deserialize(jsonSettingsString); } // Save settings to a json file. - public static void SaveSettings(string jsonSettings, string powertoy = DefaultModuleName, string fileName = DefaultFileName) + public void SaveSettings(string jsonSettings, string powertoy = DefaultModuleName, string fileName = DefaultFileName) { try { @@ -79,7 +111,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib CreateSettingsFolder(powertoy); } - File.WriteAllText(GetSettingsPath(powertoy, fileName), jsonSettings); + _ioProvider.WriteAllText(GetSettingsPath(powertoy, fileName), jsonSettings); } } catch @@ -87,7 +119,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib } } - public static string LocalApplicationDataFolder() + private static string LocalApplicationDataFolder() { return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideSettings.cs index 6b5e41e631..343649fd80 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideSettings.cs @@ -3,10 +3,11 @@ // See the LICENSE file in the project root for more information. using System.Text.Json.Serialization; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib { - public class ShortcutGuideSettings : BasePTModuleSettings + public class ShortcutGuideSettings : BasePTModuleSettings, ISettingsConfig { public const string ModuleName = "Shortcut Guide"; @@ -19,5 +20,16 @@ namespace Microsoft.PowerToys.Settings.UI.Lib Properties = new ShortcutGuideProperties(); Version = "1.0"; } + + public string GetModuleName() + { + return Name; + } + + // This can be utilized in the future if the settings.json file is to be modified/deleted. + public bool UpgradeSettingsConfiguration() + { + return false; + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutsKeyDataModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutsKeyDataModel.cs index 0e1e131fe3..5195c6c1e9 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutsKeyDataModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutsKeyDataModel.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Text.Json; using System.Text.Json.Serialization; namespace Microsoft.PowerToys.Settings.UI.Lib @@ -20,5 +21,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib GlobalRemapShortcuts = new List(); AppSpecificRemapShortcuts = new List(); } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/IIOProvider.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/IIOProvider.cs new file mode 100644 index 0000000000..deed5f0fcd --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/IIOProvider.cs @@ -0,0 +1,21 @@ +// 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. + +namespace Microsoft.PowerToys.Settings.UI.Lib.Utilities +{ + public interface IIOProvider + { + bool FileExists(string path); + + bool DirectoryExists(string path); + + bool CreateDirectory(string path); + + void DeleteDirectory(string path); + + void WriteAllText(string path, string content); + + string ReadAllText(string path); + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/SystemIOProvider.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/SystemIOProvider.cs new file mode 100644 index 0000000000..bfcb4d55f7 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/Utilities/SystemIOProvider.cs @@ -0,0 +1,42 @@ +// 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.IO; + +namespace Microsoft.PowerToys.Settings.UI.Lib.Utilities +{ + public class SystemIOProvider : IIOProvider + { + public bool CreateDirectory(string path) + { + var directioryInfo = Directory.CreateDirectory(path); + return directioryInfo != null; + } + + public void DeleteDirectory(string path) + { + Directory.Delete(path, recursive: true); + } + + public bool DirectoryExists(string path) + { + return Directory.Exists(path); + } + + public bool FileExists(string path) + { + return File.Exists(path); + } + + public string ReadAllText(string path) + { + return File.ReadAllText(path); + } + + public void WriteAllText(string path, string content) + { + File.WriteAllText(path, content); + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ColorPickerViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ColorPickerViewModel.cs index e3ccd66207..5df080b77d 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ColorPickerViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ColorPickerViewModel.cs @@ -5,32 +5,38 @@ using System; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Lib.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { public class ColorPickerViewModel : Observable { + private GeneralSettings GeneralSettingsConfig { get; set; } + + private readonly ISettingsUtils _settingsUtils; + private ColorPickerSettings _colorPickerSettings; + private bool _isEnabled; private Func SendConfigMSG { get; } - public ColorPickerViewModel(Func ipcMSGCallBackFunc) + public ColorPickerViewModel(ISettingsUtils settingsUtils, ISettingsRepository settingsRepository, Func ipcMSGCallBackFunc) { - if (SettingsUtils.SettingsExists(ColorPickerSettings.ModuleName)) + // Obtain the general PowerToy settings configurations + GeneralSettingsConfig = settingsRepository.SettingsConfig; + + _settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils)); + if (_settingsUtils.SettingsExists(ColorPickerSettings.ModuleName)) { - _colorPickerSettings = SettingsUtils.GetSettings(ColorPickerSettings.ModuleName); + _colorPickerSettings = _settingsUtils.GetSettings(ColorPickerSettings.ModuleName); } else { _colorPickerSettings = new ColorPickerSettings(); } - if (SettingsUtils.SettingsExists()) - { - var generalSettings = SettingsUtils.GetSettings(); - _isEnabled = generalSettings.Enabled.ColorPicker; - } + _isEnabled = GeneralSettingsConfig.Enabled.ColorPicker; // set the callback functions value to hangle outgoing IPC message. SendConfigMSG = ipcMSGCallBackFunc; @@ -50,10 +56,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels _isEnabled = value; OnPropertyChanged(nameof(IsEnabled)); - // grab the latest version of settings - var generalSettings = SettingsUtils.GetSettings(); - generalSettings.Enabled.ColorPicker = value; - OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(generalSettings); + // Set the status of ColorPicker in the general settings + GeneralSettingsConfig.Enabled.ColorPicker = value; + OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig); + SendConfigMSG(outgoing.ToString()); } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/FancyZonesViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/FancyZonesViewModel.cs index 3b538c2c66..65eb24ad3b 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/FancyZonesViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/FancyZonesViewModel.cs @@ -6,13 +6,16 @@ using System; using System.Drawing; using System.Runtime.CompilerServices; using Microsoft.PowerToys.Settings.UI.Lib.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels.Commands; namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { public class FancyZonesViewModel : Observable { - private const string ModuleName = "FancyZones"; + private GeneralSettings GeneralSettingsConfig { get; set; } + + private const string ModuleName = FancyZonesSettings.ModuleName; public ButtonClickCommand LaunchEditorEventHandler { get; set; } @@ -22,19 +25,14 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels private string settingsConfigFileFolder = string.Empty; - public FancyZonesViewModel(Func ipcMSGCallBackFunc, string configFileSubfolder = "") + public FancyZonesViewModel(ISettingsRepository settingsRepository, ISettingsRepository moduleSettingsRepository, Func ipcMSGCallBackFunc, string configFileSubfolder = "") { + // To obtain the general settings configurations of PowerToys Settings. + GeneralSettingsConfig = settingsRepository.SettingsConfig; settingsConfigFileFolder = configFileSubfolder; - try - { - Settings = SettingsUtils.GetSettings(GetSettingsSubPath()); - } - catch - { - Settings = new FancyZonesSettings(); - SettingsUtils.SaveSettings(Settings.ToJsonString(), GetSettingsSubPath()); - } + // To obtain the settings configurations of Fancy zones. + Settings = moduleSettingsRepository.SettingsConfig; LaunchEditorEventHandler = new ButtonClickCommand(LaunchEditor); @@ -68,18 +66,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels string highlightColor = Settings.Properties.FancyzonesZoneHighlightColor.Value; _zoneHighlightColor = highlightColor != string.Empty ? highlightColor : "#0078D7"; - GeneralSettings generalSettings; - try - { - generalSettings = SettingsUtils.GetSettings(string.Empty); - } - catch - { - generalSettings = new GeneralSettings(); - SettingsUtils.SaveSettings(generalSettings.ToJsonString(), string.Empty); - } - - _isEnabled = generalSettings.Enabled.FancyZones; + _isEnabled = GeneralSettingsConfig.Enabled.FancyZones; } private bool _isEnabled; @@ -117,9 +104,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels if (value != _isEnabled) { _isEnabled = value; - GeneralSettings generalSettings = SettingsUtils.GetSettings(string.Empty); - generalSettings.Enabled.FancyZones = value; - OutGoingGeneralSettings snd = new OutGoingGeneralSettings(generalSettings); + + // Set the status of FancyZones in the general settings configuration + GeneralSettingsConfig.Enabled.FancyZones = value; + OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig); SendConfigMSG(snd.ToString()); OnPropertyChanged("IsEnabled"); diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/GeneralViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/GeneralViewModel.cs index 19e6ce3d6a..ff7667d86e 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/GeneralViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/GeneralViewModel.cs @@ -3,9 +3,9 @@ // See the LICENSE file in the project root for more information. using System; -using System.Diagnostics; using System.Runtime.CompilerServices; using Microsoft.PowerToys.Settings.UI.Lib.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; using Microsoft.PowerToys.Settings.UI.Lib.Utilities; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels.Commands; @@ -13,7 +13,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { public class GeneralViewModel : Observable { - private GeneralSettings GeneralSettingsConfigs { get; set; } + private GeneralSettings GeneralSettingsConfig { get; set; } public ButtonClickCommand CheckFoUpdatesEventHandler { get; set; } @@ -33,32 +33,13 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels private string _settingsConfigFileFolder = string.Empty; - public GeneralViewModel(string runAsAdminText, string runAsUserText, bool isElevated, bool isAdmin, Func updateTheme, Func ipcMSGCallBackFunc, Func ipcMSGRestartAsAdminMSGCallBackFunc, Func ipcMSGCheckForUpdatesCallBackFunc, string configFileSubfolder = "") + public GeneralViewModel(ISettingsRepository settingsRepository, string runAsAdminText, string runAsUserText, bool isElevated, bool isAdmin, Func updateTheme, Func ipcMSGCallBackFunc, Func ipcMSGRestartAsAdminMSGCallBackFunc, Func ipcMSGCheckForUpdatesCallBackFunc, string configFileSubfolder = "") { CheckFoUpdatesEventHandler = new ButtonClickCommand(CheckForUpdates_Click); RestartElevatedButtonEventHandler = new ButtonClickCommand(Restart_Elevated); - try - { - GeneralSettingsConfigs = SettingsUtils.GetSettings(string.Empty); - - if (Helper.CompareVersions(GeneralSettingsConfigs.PowertoysVersion, Helper.GetProductVersion()) < 0) - { - // Update settings - GeneralSettingsConfigs.PowertoysVersion = Helper.GetProductVersion(); - SettingsUtils.SaveSettings(GeneralSettingsConfigs.ToJsonString(), string.Empty); - } - } - catch (FormatException e) - { - // If there is an issue with the version number format, don't migrate settings. - Debug.WriteLine(e.Message); - } - catch - { - GeneralSettingsConfigs = new GeneralSettings(); - SettingsUtils.SaveSettings(GeneralSettingsConfigs.ToJsonString(), string.Empty); - } + // To obtain the general settings configuration of PowerToys if it exists, else to create a new file and return the default configurations. + GeneralSettingsConfig = settingsRepository.SettingsConfig; // set the callback functions value to hangle outgoing IPC message. SendConfigMSG = ipcMSGCallBackFunc; @@ -67,12 +48,12 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels // set the callback function value to update the UI theme. UpdateUIThemeCallBack = updateTheme; - UpdateUIThemeCallBack(GeneralSettingsConfigs.Theme.ToLower()); + UpdateUIThemeCallBack(GeneralSettingsConfig.Theme.ToLower()); // Update Settings file folder: _settingsConfigFileFolder = configFileSubfolder; - switch (GeneralSettingsConfigs.Theme.ToLower()) + switch (GeneralSettingsConfig.Theme.ToLower()) { case "light": _isLightThemeRadioButtonChecked = true; @@ -85,10 +66,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels break; } - _startup = GeneralSettingsConfigs.Startup; - _autoDownloadUpdates = GeneralSettingsConfigs.AutoDownloadUpdates; + _startup = GeneralSettingsConfig.Startup; + _autoDownloadUpdates = GeneralSettingsConfig.AutoDownloadUpdates; _isElevated = isElevated; - _runElevated = GeneralSettingsConfigs.RunElevated; + _runElevated = GeneralSettingsConfig.RunElevated; RunningAsUserDefaultText = runAsUserText; RunningAsAdminDefaultText = runAsAdminText; @@ -139,7 +120,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels if (_startup != value) { _startup = value; - GeneralSettingsConfigs.Startup = value; + GeneralSettingsConfig.Startup = value; RaisePropertyChanged(); } } @@ -211,7 +192,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels if (_runElevated != value) { _runElevated = value; - GeneralSettingsConfigs.RunElevated = value; + GeneralSettingsConfig.RunElevated = value; RaisePropertyChanged(); } } @@ -238,7 +219,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels if (_autoDownloadUpdates != value) { _autoDownloadUpdates = value; - GeneralSettingsConfigs.AutoDownloadUpdates = value; + GeneralSettingsConfig.AutoDownloadUpdates = value; RaisePropertyChanged(); } } @@ -255,11 +236,11 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { if (value == true) { - GeneralSettingsConfigs.Theme = "dark"; + GeneralSettingsConfig.Theme = "dark"; _isDarkThemeRadioButtonChecked = value; try { - UpdateUIThemeCallBack(GeneralSettingsConfigs.Theme); + UpdateUIThemeCallBack(GeneralSettingsConfig.Theme); } catch { @@ -281,11 +262,11 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { if (value == true) { - GeneralSettingsConfigs.Theme = "light"; + GeneralSettingsConfig.Theme = "light"; _isLightThemeRadioButtonChecked = value; try { - UpdateUIThemeCallBack(GeneralSettingsConfigs.Theme); + UpdateUIThemeCallBack(GeneralSettingsConfig.Theme); } catch { @@ -307,11 +288,11 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { if (value == true) { - GeneralSettingsConfigs.Theme = "system"; + GeneralSettingsConfig.Theme = "system"; _isSystemThemeRadioButtonChecked = value; try { - UpdateUIThemeCallBack(GeneralSettingsConfigs.Theme); + UpdateUIThemeCallBack(GeneralSettingsConfig.Theme); } catch { @@ -352,7 +333,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { // Notify UI of property change OnPropertyChanged(propertyName); - OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings(GeneralSettingsConfigs); + OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings(GeneralSettingsConfig); SendConfigMSG(outsettings.ToString()); } @@ -360,10 +341,9 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels // callback function to launch the URL to check for updates. private void CheckForUpdates_Click() { - GeneralSettings settings = SettingsUtils.GetSettings(_settingsConfigFileFolder); - settings.CustomActionName = "check_for_updates"; + GeneralSettingsConfig.CustomActionName = "check_for_updates"; - OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings(settings); + OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings(GeneralSettingsConfig); GeneralSettingsCustomAction customaction = new GeneralSettingsCustomAction(outsettings); SendCheckForUpdatesConfigMSG(customaction.ToString()); @@ -371,10 +351,9 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels public void Restart_Elevated() { - GeneralSettings settings = SettingsUtils.GetSettings(_settingsConfigFileFolder); - settings.CustomActionName = "restart_elevation"; + GeneralSettingsConfig.CustomActionName = "restart_elevation"; - OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings(settings); + OutGoingGeneralSettings outsettings = new OutGoingGeneralSettings(GeneralSettingsConfig); GeneralSettingsCustomAction customaction = new GeneralSettingsCustomAction(outsettings); SendRestartAsAdminConfigMSG(customaction.ToString()); diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ImageResizerViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ImageResizerViewModel.cs index 373f7d0f55..7a4dc3f475 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ImageResizerViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ImageResizerViewModel.cs @@ -7,45 +7,44 @@ using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using Microsoft.PowerToys.Settings.UI.Lib.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { public class ImageResizerViewModel : Observable { + private GeneralSettings GeneralSettingsConfig { get; set; } + + private readonly ISettingsUtils _settingsUtils; + private ImageResizerSettings Settings { get; set; } + // NOTE: Not using ImageResizerSettings.ModuleName ("Image Resizer") to be backward compatible. private const string ModuleName = "ImageResizer"; private Func SendConfigMSG { get; } - public ImageResizerViewModel(Func ipcMSGCallBackFunc) + public ImageResizerViewModel(ISettingsUtils settingsUtils, ISettingsRepository settingsRepository, Func ipcMSGCallBackFunc) { + _settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils)); + + // To obtain the general settings configurations of PowerToys. + GeneralSettingsConfig = settingsRepository.SettingsConfig; + try { - Settings = SettingsUtils.GetSettings(ModuleName); + Settings = _settingsUtils.GetSettings(ModuleName); } catch { Settings = new ImageResizerSettings(); - SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); - } - - GeneralSettings generalSettings; - - try - { - generalSettings = SettingsUtils.GetSettings(string.Empty); - } - catch - { - generalSettings = new GeneralSettings(); - SettingsUtils.SaveSettings(generalSettings.ToJsonString(), string.Empty); + _settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); } // set the callback functions value to hangle outgoing IPC message. SendConfigMSG = ipcMSGCallBackFunc; - _isEnabled = generalSettings.Enabled.ImageResizer; + _isEnabled = GeneralSettingsConfig.Enabled.ImageResizer; _advancedSizes = Settings.Properties.ImageresizerSizes.Value; _jpegQualityLevel = Settings.Properties.ImageresizerJpegQualityLevel.Value; _pngInterlaceOption = Settings.Properties.ImageresizerPngInterlaceOption.Value; @@ -83,10 +82,11 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { if (value != _isEnabled) { + // To set the status of ImageResizer in the General PowerToys settings. _isEnabled = value; - GeneralSettings generalSettings = SettingsUtils.GetSettings(string.Empty); - generalSettings.Enabled.ImageResizer = value; - OutGoingGeneralSettings snd = new OutGoingGeneralSettings(generalSettings); + GeneralSettingsConfig.Enabled.ImageResizer = value; + OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig); + SendConfigMSG(snd.ToString()); OnPropertyChanged("IsEnabled"); } @@ -121,7 +121,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { _jpegQualityLevel = value; Settings.Properties.ImageresizerJpegQualityLevel.Value = value; - SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); + _settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); OnPropertyChanged("JPEGQualityLevel"); } } @@ -140,7 +140,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { _pngInterlaceOption = value; Settings.Properties.ImageresizerPngInterlaceOption.Value = value; - SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); + _settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); OnPropertyChanged("PngInterlaceOption"); } } @@ -159,7 +159,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { _tiffCompressOption = value; Settings.Properties.ImageresizerTiffCompressOption.Value = value; - SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); + _settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); OnPropertyChanged("TiffCompressOption"); } } @@ -178,7 +178,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { _fileName = value; Settings.Properties.ImageresizerFileName.Value = value; - SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); + _settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); OnPropertyChanged("FileName"); } } @@ -195,7 +195,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { _keepDateModified = value; Settings.Properties.ImageresizerKeepDateModified.Value = value; - SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); + _settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); OnPropertyChanged("KeepDateModified"); } } @@ -212,9 +212,9 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels if (_encoderGuidId != value) { _encoderGuidId = value; - SettingsUtils.SaveSettings(Settings.Properties.ImageresizerSizes.ToJsonString(), ModuleName, "sizes.json"); + _settingsUtils.SaveSettings(Settings.Properties.ImageresizerSizes.ToJsonString(), ModuleName, "sizes.json"); Settings.Properties.ImageresizerFallbackEncoder.Value = GetEncoderGuid(value); - SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); + _settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); OnPropertyChanged("Encoder"); } } @@ -243,9 +243,9 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels public void SavesImageSizes(ObservableCollection imageSizes) { - SettingsUtils.SaveSettings(Settings.Properties.ImageresizerSizes.ToJsonString(), ModuleName, "sizes.json"); + _settingsUtils.SaveSettings(Settings.Properties.ImageresizerSizes.ToJsonString(), ModuleName, "sizes.json"); Settings.Properties.ImageresizerSizes = new ImageResizerSizes(imageSizes); - SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); + _settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); } public string GetEncoderGuid(int value) diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/KeyboardManagerViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/KeyboardManagerViewModel.cs index 712696733d..0e6d36f519 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/KeyboardManagerViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/KeyboardManagerViewModel.cs @@ -4,11 +4,13 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; using Microsoft.PowerToys.Settings.UI.Lib.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; using Microsoft.PowerToys.Settings.UI.Lib.Utilities; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels.Commands; @@ -16,7 +18,11 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { public class KeyboardManagerViewModel : Observable { - private const string PowerToyName = "Keyboard Manager"; + private GeneralSettings GeneralSettingsConfig { get; set; } + + private readonly ISettingsUtils _settingsUtils; + + private const string PowerToyName = KeyboardManagerSettings.ModuleName; private const string RemapKeyboardActionName = "RemapKeyboard"; private const string RemapKeyboardActionValue = "Open Remap Keyboard Window"; private const string EditShortcutActionName = "EditShortcut"; @@ -30,22 +36,25 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels private ICommand _remapKeyboardCommand; private ICommand _editShortcutCommand; private KeyboardManagerProfile _profile; - private GeneralSettings _generalSettings; private Func SendConfigMSG { get; } private Func, int> FilterRemapKeysList { get; } - public KeyboardManagerViewModel(Func ipcMSGCallBackFunc, Func, int> filterRemapKeysList) + public KeyboardManagerViewModel(ISettingsUtils settingsUtils, ISettingsRepository settingsRepository, Func ipcMSGCallBackFunc, Func, int> filterRemapKeysList) { + GeneralSettingsConfig = settingsRepository.SettingsConfig; + // set the callback functions value to hangle outgoing IPC message. SendConfigMSG = ipcMSGCallBackFunc; FilterRemapKeysList = filterRemapKeysList; - if (SettingsUtils.SettingsExists(PowerToyName)) + _settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils)); + + if (_settingsUtils.SettingsExists(PowerToyName)) { // Todo: Be more resilient while reading and saving settings. - Settings = SettingsUtils.GetSettings(PowerToyName); + Settings = _settingsUtils.GetSettings(PowerToyName); // Load profile. if (!LoadProfile()) @@ -55,18 +64,8 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels } else { - Settings = new KeyboardManagerSettings(PowerToyName); - SettingsUtils.SaveSettings(Settings.ToJsonString(), PowerToyName); - } - - if (SettingsUtils.SettingsExists()) - { - _generalSettings = SettingsUtils.GetSettings(string.Empty); - } - else - { - _generalSettings = new GeneralSettings(); - SettingsUtils.SaveSettings(_generalSettings.ToJsonString(), string.Empty); + Settings = new KeyboardManagerSettings(); + _settingsUtils.SaveSettings(Settings.ToJsonString(), PowerToyName); } } @@ -74,16 +73,16 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { get { - return _generalSettings.Enabled.KeyboardManager; + return GeneralSettingsConfig.Enabled.KeyboardManager; } set { - if (_generalSettings.Enabled.KeyboardManager != value) + if (GeneralSettingsConfig.Enabled.KeyboardManager != value) { - _generalSettings.Enabled.KeyboardManager = value; + GeneralSettingsConfig.Enabled.KeyboardManager = value; OnPropertyChanged(nameof(Enabled)); - OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(_generalSettings); + OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig); SendConfigMSG(outgoing.ToString()); } @@ -173,8 +172,19 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels // update the UI element here. try { - _profile = SettingsUtils.GetSettings(PowerToyName, Settings.Properties.ActiveConfiguration.Value + JsonFileType); - FilterRemapKeysList(_profile.RemapKeys.InProcessRemapKeys); + string fileName = Settings.Properties.ActiveConfiguration.Value + JsonFileType; + + if (_settingsUtils.SettingsExists(PowerToyName, fileName)) + { + _profile = _settingsUtils.GetSettings(PowerToyName, fileName); + } + else + { + // The KBM process out of runner creates the default.json file if it does not exist. + success = false; + } + + FilterRemapKeysList(_profile?.RemapKeys?.InProcessRemapKeys); } finally { diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerLauncherViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerLauncherViewModel.cs index fbccc433fe..82af7c1b5d 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerLauncherViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerLauncherViewModel.cs @@ -6,13 +6,17 @@ using System; using System.Runtime.CompilerServices; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Lib.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { public class PowerLauncherViewModel : Observable { + private GeneralSettings GeneralSettingsConfig { get; set; } + + private readonly ISettingsUtils _settingsUtils; + private PowerLauncherSettings settings; - private GeneralSettings generalSettings; public delegate void SendCallback(PowerLauncherSettings settings); @@ -20,11 +24,15 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels private Func SendConfigMSG { get; } - public PowerLauncherViewModel(Func ipcMSGCallBackFunc, int defaultKeyCode) + public PowerLauncherViewModel(ISettingsUtils settingsUtils, ISettingsRepository settingsRepository, Func ipcMSGCallBackFunc, int defaultKeyCode) { + _settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils)); + + // To obtain the general Settings configurations of PowerToys + GeneralSettingsConfig = settingsRepository.SettingsConfig; + // set the callback functions value to hangle outgoing IPC message. SendConfigMSG = ipcMSGCallBackFunc; - callback = (PowerLauncherSettings settings) => { // Propagate changes to Power Launcher through IPC @@ -32,9 +40,9 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels string.Format("{{ \"powertoys\": {{ \"{0}\": {1} }} }}", PowerLauncherSettings.ModuleName, JsonSerializer.Serialize(settings))); }; - if (SettingsUtils.SettingsExists(PowerLauncherSettings.ModuleName)) + if (_settingsUtils.SettingsExists(PowerLauncherSettings.ModuleName)) { - settings = SettingsUtils.GetSettings(PowerLauncherSettings.ModuleName); + settings = _settingsUtils.GetSettings(PowerLauncherSettings.ModuleName); } else { @@ -44,15 +52,6 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels settings.Properties.MaximumNumberOfResults = 4; callback(settings); } - - if (SettingsUtils.SettingsExists()) - { - generalSettings = SettingsUtils.GetSettings(); - } - else - { - generalSettings = new GeneralSettings(); - } } public PowerLauncherViewModel(PowerLauncherSettings settings, SendCallback callback) @@ -73,16 +72,16 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { get { - return generalSettings.Enabled.PowerLauncher; + return GeneralSettingsConfig.Enabled.PowerLauncher; } set { - if (generalSettings.Enabled.PowerLauncher != value) + if (GeneralSettingsConfig.Enabled.PowerLauncher != value) { - generalSettings.Enabled.PowerLauncher = value; + GeneralSettingsConfig.Enabled.PowerLauncher = value; OnPropertyChanged(nameof(EnablePowerLauncher)); - OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(generalSettings); + OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig); SendConfigMSG(outgoing.ToString()); } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerPreviewViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerPreviewViewModel.cs index e79746f2fe..0689bc9ca3 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerPreviewViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerPreviewViewModel.cs @@ -5,12 +5,13 @@ using System; using System.Runtime.CompilerServices; using Microsoft.PowerToys.Settings.UI.Lib.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { public class PowerPreviewViewModel : Observable { - private const string ModuleName = "File Explorer"; + private const string ModuleName = PowerPreviewSettings.ModuleName; private PowerPreviewSettings Settings { get; set; } @@ -18,20 +19,14 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels private string _settingsConfigFileFolder = string.Empty; - public PowerPreviewViewModel(Func ipcMSGCallBackFunc, string configFileSubfolder = "") + public PowerPreviewViewModel(ISettingsRepository moduleSettingsRepository, Func ipcMSGCallBackFunc, string configFileSubfolder = "") { // Update Settings file folder: _settingsConfigFileFolder = configFileSubfolder; - try - { - Settings = SettingsUtils.GetSettings(GetSettingsSubPath()); - } - catch - { - Settings = new PowerPreviewSettings(); - SettingsUtils.SaveSettings(Settings.ToJsonString(), GetSettingsSubPath()); - } + // To obtain the PowerPreview settings if it exists. + // If the file does not exist, to create a new one and return the default settings configurations. + Settings = moduleSettingsRepository.SettingsConfig; // set the callback functions value to hangle outgoing IPC message. SendConfigMSG = ipcMSGCallBackFunc; diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerRenameViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerRenameViewModel.cs index 43755e6914..2a6aaa2bf3 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerRenameViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/PowerRenameViewModel.cs @@ -5,12 +5,17 @@ using System; using System.Runtime.CompilerServices; using Microsoft.PowerToys.Settings.UI.Lib.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { public class PowerRenameViewModel : Observable { - private const string ModuleName = "PowerRename"; + private GeneralSettings GeneralSettingsConfig { get; set; } + + private readonly ISettingsUtils _settingsUtils; + + private const string ModuleName = PowerRenameSettings.ModuleName; private string _settingsConfigFileFolder = string.Empty; @@ -18,21 +23,24 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels private Func SendConfigMSG { get; } - public PowerRenameViewModel(Func ipcMSGCallBackFunc, string configFileSubfolder = "") + public PowerRenameViewModel(ISettingsUtils settingsUtils, ISettingsRepository settingsRepository, Func ipcMSGCallBackFunc, string configFileSubfolder = "") { // Update Settings file folder: _settingsConfigFileFolder = configFileSubfolder; + _settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils)); + + GeneralSettingsConfig = settingsRepository.SettingsConfig; try { - PowerRenameLocalProperties localSettings = SettingsUtils.GetSettings(GetSettingsSubPath(), "power-rename-settings.json"); + PowerRenameLocalProperties localSettings = _settingsUtils.GetSettings(GetSettingsSubPath(), "power-rename-settings.json"); Settings = new PowerRenameSettings(localSettings); } catch { PowerRenameLocalProperties localSettings = new PowerRenameLocalProperties(); Settings = new PowerRenameSettings(localSettings); - SettingsUtils.SaveSettings(localSettings.ToJsonString(), GetSettingsSubPath(), "power-rename-settings.json"); + _settingsUtils.SaveSettings(localSettings.ToJsonString(), GetSettingsSubPath(), "power-rename-settings.json"); } // set the callback functions value to hangle outgoing IPC message. @@ -43,19 +51,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels _powerRenameRestoreFlagsOnLaunch = Settings.Properties.PersistState.Value; _powerRenameMaxDispListNumValue = Settings.Properties.MaxMRUSize.Value; _autoComplete = Settings.Properties.MRUEnabled.Value; - - GeneralSettings generalSettings; - try - { - generalSettings = SettingsUtils.GetSettings(string.Empty); - } - catch - { - generalSettings = new GeneralSettings(); - SettingsUtils.SaveSettings(generalSettings.ToJsonString(), string.Empty); - } - - _powerRenameEnabled = generalSettings.Enabled.PowerRename; + _powerRenameEnabled = GeneralSettingsConfig.Enabled.PowerRename; } private bool _powerRenameEnabled = false; @@ -76,9 +72,9 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { if (value != _powerRenameEnabled) { - GeneralSettings generalSettings = SettingsUtils.GetSettings(string.Empty); - generalSettings.Enabled.PowerRename = value; - OutGoingGeneralSettings snd = new OutGoingGeneralSettings(generalSettings); + GeneralSettingsConfig.Enabled.PowerRename = value; + OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig); + SendConfigMSG(snd.ToString()); _powerRenameEnabled = value; diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ShortcutGuideViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ShortcutGuideViewModel.cs index 32ed136f5b..94806854af 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ShortcutGuideViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ViewModels/ShortcutGuideViewModel.cs @@ -5,50 +5,38 @@ using System; using System.Runtime.CompilerServices; using Microsoft.PowerToys.Settings.UI.Lib.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels { public class ShortcutGuideViewModel : Observable { + private GeneralSettings GeneralSettingsConfig { get; set; } + private ShortcutGuideSettings Settings { get; set; } - private const string ModuleName = "Shortcut Guide"; + private const string ModuleName = ShortcutGuideSettings.ModuleName; private Func SendConfigMSG { get; } private string _settingsConfigFileFolder = string.Empty; - public ShortcutGuideViewModel(Func ipcMSGCallBackFunc, string configFileSubfolder = "") + public ShortcutGuideViewModel(ISettingsRepository settingsRepository, ISettingsRepository moduleSettingsRepository, Func ipcMSGCallBackFunc, string configFileSubfolder = "") { // Update Settings file folder: _settingsConfigFileFolder = configFileSubfolder; - try - { - Settings = SettingsUtils.GetSettings(GetSettingsSubPath()); - } - catch - { - Settings = new ShortcutGuideSettings(); - SettingsUtils.SaveSettings(Settings.ToJsonString(), GetSettingsSubPath()); - } + // To obtain the general PowerToys settings. + GeneralSettingsConfig = settingsRepository.SettingsConfig; - GeneralSettings generalSettings; - - try - { - generalSettings = SettingsUtils.GetSettings(string.Empty); - } - catch - { - generalSettings = new GeneralSettings(); - SettingsUtils.SaveSettings(generalSettings.ToJsonString(), string.Empty); - } + // To obtain the shortcut guide settings, if the file exists. + // If not, to create a file with the default settings and to return the default configurations. + Settings = moduleSettingsRepository.SettingsConfig; // set the callback functions value to hangle outgoing IPC message. SendConfigMSG = ipcMSGCallBackFunc; - _isEnabled = generalSettings.Enabled.ShortcutGuide; + _isEnabled = GeneralSettingsConfig.Enabled.ShortcutGuide; _pressTime = Settings.Properties.PressTime.Value; _opacity = Settings.Properties.OverlayOpacity.Value; @@ -87,9 +75,11 @@ namespace Microsoft.PowerToys.Settings.UI.Lib.ViewModels if (value != _isEnabled) { _isEnabled = value; - GeneralSettings generalSettings = SettingsUtils.GetSettings(string.Empty); - generalSettings.Enabled.ShortcutGuide = value; - OutGoingGeneralSettings snd = new OutGoingGeneralSettings(generalSettings); + + // To update the status of shortcut guide in General PowerToy settings. + GeneralSettingsConfig.Enabled.ShortcutGuide = value; + OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig); + SendConfigMSG(snd.ToString()); OnPropertyChanged("IsEnabled"); } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Microsoft.PowerToys.Settings.UI.UnitTests.csproj b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Microsoft.PowerToys.Settings.UI.UnitTests.csproj index 525ce3d286..42214bf52e 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Microsoft.PowerToys.Settings.UI.UnitTests.csproj +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Microsoft.PowerToys.Settings.UI.UnitTests.csproj @@ -17,6 +17,7 @@ + diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Mocks/IIOProviderMocks.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Mocks/IIOProviderMocks.cs new file mode 100644 index 0000000000..08a6b02977 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Mocks/IIOProviderMocks.cs @@ -0,0 +1,38 @@ +using Microsoft.PowerToys.Settings.UI.Lib.Utilities; +using Moq; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks +{ + internal static class IIOProviderMocks + { + + /// + /// This method mocks an IO provider to validate tests wich required saving to a file, and then reading the contents of that file, or verifying it exists + /// + /// + internal static Mock GetMockIOProviderForSaveLoadExists() + { + string savePath = string.Empty; + string saveContent = string.Empty; + var mockIOProvider = new Mock(); + mockIOProvider.Setup(x => x.WriteAllText(It.IsAny(), It.IsAny())) + .Callback((path, content) => + { + savePath = path; + saveContent = content; + }); + mockIOProvider.Setup(x => x.ReadAllText(It.Is(x => x.Equals(savePath, StringComparison.Ordinal)))) + .Returns(() => saveContent); + + mockIOProvider.Setup(x => x.FileExists(It.Is(x => x.Equals(savePath, StringComparison.Ordinal)))) + .Returns(true); + mockIOProvider.Setup(x => x.FileExists(It.Is(x => !x.Equals(savePath, StringComparison.Ordinal)))) + .Returns(false); + + return mockIOProvider; + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Mocks/ISettingsUtilsMocks.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Mocks/ISettingsUtilsMocks.cs new file mode 100644 index 0000000000..b1c47f15b1 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/Mocks/ISettingsUtilsMocks.cs @@ -0,0 +1,21 @@ +using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; +using Moq; +using System; + +namespace Microsoft.PowerToys.Settings.UI.UnitTests.Mocks +{ + internal static class ISettingsUtilsMocks + { + //Stubs out empty values for imageresizersettings and general settings as needed by the imageresizer viewmodel + internal static Mock GetStubSettingsUtils() + where T : ISettingsConfig, new() + { + var settingsUtils = new Mock(); + settingsUtils.Setup(x => x.GetSettings(It.IsAny(), It.IsAny())) + .Returns(new T()); + + return settingsUtils; + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsTest.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsTest.cs index 84bba538c8..cc4a2d158c 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsTest.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTModuleSettingsTest.cs @@ -4,8 +4,11 @@ using System; using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Lib.Utilities; +using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.PowerToys.Settings.UnitTest; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Schema; @@ -21,6 +24,13 @@ namespace CommonLibTest [Obsolete] public void ToJsonString_ShouldReturnValidJSONOfModel_WhenSuccessful() { + //Mock Disk access + string saveContent = string.Empty; + string savePath = string.Empty; + var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); + + var settingsUtils = new SettingsUtils(mockIOProvider.Object); + // Arrange string file_name = "test\\BasePTModuleSettingsTest"; string expectedSchemaText = @" @@ -39,11 +49,11 @@ namespace CommonLibTest }"; string testSettingsConfigs = new BasePTSettingsTest().ToJsonString(); - SettingsUtils.SaveSettings(testSettingsConfigs, file_name); + settingsUtils.SaveSettings(testSettingsConfigs, file_name); JsonSchema expectedSchema = JsonSchema.Parse(expectedSchemaText); // Act - JObject actualSchema = JObject.Parse(SettingsUtils.GetSettings(file_name).ToJsonString()); + JObject actualSchema = JObject.Parse(settingsUtils.GetSettings(file_name).ToJsonString()); bool valid = actualSchema.IsValid(expectedSchema); // Assert diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs index 2bec4be724..023ee7e851 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/BasePTSettingsTest.cs @@ -3,15 +3,26 @@ // See the LICENSE file in the project root for more information. using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Lib.Interface; namespace Microsoft.PowerToys.Settings.UnitTest { - public class BasePTSettingsTest : BasePTModuleSettings + public class BasePTSettingsTest : BasePTModuleSettings, ISettingsConfig { public BasePTSettingsTest() { Name = string.Empty; Version = string.Empty; } + + public string GetModuleName() + { + return Name; + } + + public bool UpgradeSettingsConfiguration() + { + return false; + } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsRepositoryTest.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsRepositoryTest.cs new file mode 100644 index 0000000000..67aa719da8 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsRepositoryTest.cs @@ -0,0 +1,68 @@ +// 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.Collections.Generic; +using System.IO; +using System.Threading.Tasks; +using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; + +namespace CommonLibTest +{ + [TestClass] + public class SettingsRepositoryTest + { + private Task> GetSettingsRepository(ISettingsUtils settingsUtils) + { + + return Task.Run(() => + { + return SettingsRepository.GetInstance(settingsUtils); + }); + } + + + [TestMethod] + public void SettingsRepositoryInstanceWhenCalledMustReturnSameObject() + { + // The singleton class Settings Repository must always have a single instance + var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); + + // Arrange and Act + SettingsRepository firstInstance = SettingsRepository.GetInstance(mockSettingsUtils.Object); + SettingsRepository secondInstance = SettingsRepository.GetInstance(mockSettingsUtils.Object); + + // Assert + Assert.IsTrue(object.ReferenceEquals(firstInstance, secondInstance)); + } + + [TestMethod] + public void SettingsRepositoryInstanceMustBeTheSameAcrossThreads() + { + // Multiple tasks try to access and initialize the settings repository class, however they must all access the same settings Repository object. + + // Arrange + var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); + List>> settingsRepoTasks = new List>>(); + int numberOfTasks = 100; + + for(int i = 0; i < numberOfTasks; i++) + { + settingsRepoTasks.Add(GetSettingsRepository(mockSettingsUtils.Object)); + } + + // Act + Task.WaitAll(settingsRepoTasks.ToArray()); + + // Assert + for(int i=0; i< numberOfTasks-1; i++) + { + Assert.IsTrue(object.ReferenceEquals(settingsRepoTasks[i].Result, settingsRepoTasks[i + 1].Result)); + } + + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs index 1122c3845d..36a4165407 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ModelsTests/SettingsUtilsTests.cs @@ -7,45 +7,34 @@ using System.IO; using System.Linq; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Lib.Utilities; +using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.PowerToys.Settings.UnitTest; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; namespace CommonLibTest { [TestClass] public class SettingsUtilsTests { - public SettingsUtilsTests() - { - string file_name = "\\test"; - if (SettingsUtils.SettingsFolderExists(file_name)) - { - DeleteFolder(file_name); - } - } - [TestCleanup] - public void Cleanup() - { - string file_name = "\\test"; - if (SettingsUtils.SettingsFolderExists(file_name)) - { - DeleteFolder(file_name); - } - } [TestMethod] public void SaveSettings_SaveSettingsToFile_WhenFilePathExists() { // Arrange + var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); + var settingsUtils = new SettingsUtils(mockIOProvider.Object); + string file_name = "\\test"; string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}"; BasePTSettingsTest expected_json = JsonSerializer.Deserialize(file_contents_correct_json_content); // Act - SettingsUtils.SaveSettings(file_contents_correct_json_content, file_name); - BasePTSettingsTest actual_json = SettingsUtils.GetSettings(file_name); + settingsUtils.SaveSettings(file_contents_correct_json_content, file_name); + BasePTSettingsTest actual_json = settingsUtils.GetSettings(file_name); // Assert Assert.AreEqual(expected_json.ToJsonString(), actual_json.ToJsonString()); @@ -55,19 +44,15 @@ namespace CommonLibTest public void SaveSettings_ShouldCreateFile_WhenFilePathIsNotFound() { // Arrange + var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); + var settingsUtils = new SettingsUtils(mockIOProvider.Object); string file_name = "test\\Test Folder"; string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}"; BasePTSettingsTest expected_json = JsonSerializer.Deserialize(file_contents_correct_json_content); - // Act - if (SettingsUtils.SettingsFolderExists(file_name)) - { - DeleteFolder(file_name); - } - - SettingsUtils.SaveSettings(file_contents_correct_json_content, file_name); - BasePTSettingsTest actual_json = SettingsUtils.GetSettings(file_name); + settingsUtils.SaveSettings(file_contents_correct_json_content, file_name); + BasePTSettingsTest actual_json = settingsUtils.GetSettings(file_name); // Assert Assert.AreEqual(expected_json.ToJsonString(), actual_json.ToJsonString()); @@ -77,39 +62,23 @@ namespace CommonLibTest public void SettingsFolderExists_ShouldReturnFalse_WhenFilePathIsNotFound() { // Arrange + var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); + var settingsUtils = new SettingsUtils(mockIOProvider.Object); string file_name_random = "test\\" + RandomString(); string file_name_exists = "test\\exists"; string file_contents_correct_json_content = "{\"name\":\"powertoy module name\",\"version\":\"powertoy version\"}"; // Act - bool pathNotFound = SettingsUtils.SettingsFolderExists(file_name_random); + bool pathNotFound = settingsUtils.SettingsExists(file_name_random); - SettingsUtils.SaveSettings(file_contents_correct_json_content, file_name_exists); - bool pathFound = SettingsUtils.SettingsFolderExists(file_name_exists); + settingsUtils.SaveSettings(file_contents_correct_json_content, file_name_exists); + bool pathFound = settingsUtils.SettingsExists(file_name_exists); // Assert Assert.IsFalse(pathNotFound); Assert.IsTrue(pathFound); } - [TestMethod] - public void CreateSettingsFolder_ShouldCreateFolder_WhenSuccessful() - { - // Arrange - string file_name = "test\\" + RandomString(); - - // Act - SettingsUtils.CreateSettingsFolder(file_name); - - // Assert - Assert.IsTrue(SettingsUtils.SettingsFolderExists(file_name)); - } - - public void DeleteFolder(string powertoy) - { - Directory.Delete(Path.Combine(SettingsUtils.LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"), true); - } - public static string RandomString() { Random random = new Random(); diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs index 6265b658a3..4cb73efd6a 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ColorPicker.cs @@ -2,10 +2,6 @@ // 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.IO; -using System.Text.Json; -using Microsoft.PowerToys.Settings.UI.Lib; -using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace ViewModelTests @@ -13,51 +9,6 @@ namespace ViewModelTests [TestClass] public class ColorPicker { - private const string ModuleName = "ColorPicker"; - [TestInitialize] - public void Setup() - { - var generalSettings = new GeneralSettings(); - var colorPickerSettings = new ColorPickerSettings(); - - SettingsUtils.SaveSettings(generalSettings.ToJsonString()); - SettingsUtils.SaveSettings(colorPickerSettings.ToJsonString(), colorPickerSettings.Name, ModuleName + ".json"); - } - - [TestCleanup] - public void CleanUp() - { - string generalSettings_file_name = string.Empty; - if (SettingsUtils.SettingsFolderExists(generalSettings_file_name)) - { - DeleteFolder(generalSettings_file_name); - } - - if (SettingsUtils.SettingsFolderExists(ModuleName)) - { - DeleteFolder(ModuleName); - } - } - - [TestMethod] - public void ColorPickerIsEnabledByDefault() - { - var viewModel = new ColorPickerViewModel(ColorPickerIsEnabledByDefault_IPC); - - Assert.IsTrue(viewModel.IsEnabled); - } - - public int ColorPickerIsEnabledByDefault_IPC(string msg) - { - OutGoingGeneralSettings snd = JsonSerializer.Deserialize(msg); - Assert.IsTrue(snd.GeneralSettings.Enabled.ColorPicker); - return 0; - } - - private static void DeleteFolder(string powertoy) - { - Directory.Delete(Path.Combine(SettingsUtils.LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"), true); - } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/FancyZones.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/FancyZones.cs index aef1679f8a..c4cb98925e 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/FancyZones.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/FancyZones.cs @@ -9,7 +9,9 @@ using System.Text.Json; using CommonLibTest; using Microsoft.PowerToys.Settings.UI.Lib; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; +using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; namespace ViewModelTests { @@ -18,37 +20,15 @@ namespace ViewModelTests { public const string FancyZonesTestFolderName = "Test\\FancyZones"; + private Mock mockGeneralSettingsUtils; + + private Mock mockFancyZonesSettingsUtils; + [TestInitialize] - public void Setup() + public void SetUp_StubSettingUtils() { - // initialize creation of test settings file. - GeneralSettings generalSettings = new GeneralSettings(); - FZConfigProperties fZConfigProperties = new FZConfigProperties(); - - SettingsUtils.SaveSettings(generalSettings.ToJsonString()); - SettingsUtils.SaveSettings(fZConfigProperties.ToJsonString(), FancyZonesTestFolderName); - } - - [TestCleanup] - public void CleanUp() - { - // delete general settings folder created. - string generalSettings_file_name = string.Empty; - if (SettingsUtils.SettingsFolderExists(string.Empty)) - { - DeleteFolder(string.Empty); - } - - // delete fancy zones folder created. - if (SettingsUtils.SettingsFolderExists(FancyZonesTestFolderName)) - { - DeleteFolder(FancyZonesTestFolderName); - } - } - - public void DeleteFolder(string powertoy) - { - Directory.Delete(Path.Combine(SettingsUtils.LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"), true); + mockGeneralSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); + mockFancyZonesSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); } [TestMethod] @@ -62,7 +42,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsTrue(viewModel.IsEnabled); // check if the module is enabled. // act @@ -81,7 +61,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsTrue(viewModel.ShiftDrag); // check if value was initialized to false. // act @@ -100,7 +80,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsFalse(viewModel.OverrideSnapHotkeys); // check if value was initialized to false. // act @@ -119,7 +99,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsFalse(viewModel.MoveWindowsBasedOnPosition); // check if value was initialized to false. // act @@ -138,7 +118,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsFalse(viewModel.MakeDraggedWindowsTransparent); // check if value was initialized to false. // act @@ -157,7 +137,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsFalse(viewModel.MouseSwitch); // check if value was initialized to false. // act @@ -176,7 +156,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsFalse(viewModel.DisplayChangeMoveWindows); // check if value was initialized to false. // act @@ -195,7 +175,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsFalse(viewModel.ZoneSetChangeMoveWindows); // check if value was initialized to false. // act @@ -214,7 +194,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsFalse(viewModel.AppLastZoneMoveWindows); // check if value was initialized to false. // act @@ -232,7 +212,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsFalse(viewModel.OpenWindowOnActiveMonitor); // check if value was initialized to false. // act @@ -251,7 +231,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsFalse(viewModel.RestoreSize); // check if value was initialized to false. // act @@ -270,7 +250,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsTrue(viewModel.UseCursorPosEditorStartupScreen); // check if value was initialized to false. // act @@ -289,7 +269,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.IsFalse(viewModel.ShowOnAllMonitors); // check if value was initialized to false. // act @@ -308,7 +288,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.AreEqual(ConfigDefaults.DefaultFancyZonesZoneHighlightColor, viewModel.ZoneHighlightColor); // act @@ -327,7 +307,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.AreEqual(ConfigDefaults.DefaultFancyzonesBorderColor, viewModel.ZoneBorderColor); // act @@ -346,7 +326,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.AreEqual(ConfigDefaults.DefaultFancyZonesInActiveColor, viewModel.ZoneInActiveColor); // act @@ -365,7 +345,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.AreEqual(string.Empty, viewModel.ExcludedApps); // act @@ -384,7 +364,7 @@ namespace ViewModelTests }; // arrange - FancyZonesViewModel viewModel = new FancyZonesViewModel(SendMockIPCConfigMSG, FancyZonesTestFolderName); + FancyZonesViewModel viewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockFancyZonesSettingsUtils.Object), SendMockIPCConfigMSG, FancyZonesTestFolderName); Assert.AreEqual(50, viewModel.HighlightOpacity); // act diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs index 45e4660f85..c011ba7f58 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs @@ -8,6 +8,9 @@ using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Lib; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; +using Moq; +using NuGet.Frameworks; namespace ViewModelTests { @@ -16,27 +19,12 @@ namespace ViewModelTests { public const string generalSettings_file_name = "Test\\GenealSettings"; + private Mock mockGeneralSettingsUtils; + [TestInitialize] - public void Setup() + public void SetUp_StubSettingUtils() { - // initialize creation of test settings file. - GeneralSettings generalSettings = new GeneralSettings(); - SettingsUtils.SaveSettings(generalSettings.ToJsonString(), generalSettings_file_name); - } - - [TestCleanup] - public void CleanUp() - { - // delete folder created. - if (SettingsUtils.SettingsFolderExists(generalSettings_file_name)) - { - DeleteFolder(generalSettings_file_name); - } - } - - public void DeleteFolder(string powertoy) - { - Directory.Delete(Path.Combine(SettingsUtils.LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"), true); + mockGeneralSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); } [TestMethod] @@ -47,6 +35,7 @@ namespace ViewModelTests Func SendRestartAdminIPCMessage = msg => { return 0; }; Func SendCheckForUpdatesIPCMessage = msg => { return 0; }; GeneralViewModel viewModel = new GeneralViewModel( + SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), "GeneralSettings_RunningAsAdminText", "GeneralSettings_RunningAsUserText", false, @@ -83,6 +72,7 @@ namespace ViewModelTests Func SendRestartAdminIPCMessage = msg => { return 0; }; Func SendCheckForUpdatesIPCMessage = msg => { return 0; }; GeneralViewModel viewModel = new GeneralViewModel( + SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), "GeneralSettings_RunningAsAdminText", "GeneralSettings_RunningAsUserText", false, @@ -114,6 +104,7 @@ namespace ViewModelTests // Arrange GeneralViewModel viewModel = new GeneralViewModel( + SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), "GeneralSettings_RunningAsAdminText", "GeneralSettings_RunningAsUserText", false, @@ -146,6 +137,7 @@ namespace ViewModelTests Func SendRestartAdminIPCMessage = msg => { return 0; }; Func SendCheckForUpdatesIPCMessage = msg => { return 0; }; viewModel = new GeneralViewModel( + SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), "GeneralSettings_RunningAsAdminText", "GeneralSettings_RunningAsUserText", false, @@ -176,6 +168,7 @@ namespace ViewModelTests Func SendRestartAdminIPCMessage = msg => { return 0; }; Func SendCheckForUpdatesIPCMessage = msg => { return 0; }; GeneralViewModel viewModel = new GeneralViewModel( + SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), "GeneralSettings_RunningAsAdminText", "GeneralSettings_RunningAsUserText", false, @@ -193,6 +186,24 @@ namespace ViewModelTests viewModel.IsDarkThemeRadioButtonChecked = true; } + [TestMethod] + public void AllModulesAreEnabledByDefault() + { + //arrange + EnabledModules modules = new EnabledModules(); + + + //Assert + Assert.IsTrue(modules.FancyZones); + Assert.IsTrue(modules.ImageResizer); + Assert.IsTrue(modules.FileExplorerPreview); + Assert.IsTrue(modules.ShortcutGuide); + Assert.IsTrue(modules.PowerRename); + Assert.IsTrue(modules.KeyboardManager); + Assert.IsTrue(modules.PowerLauncher); + Assert.IsTrue(modules.ColorPicker); + } + public int UpdateUIThemeMethod(string themeName) { return 0; diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ImageResizer.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ImageResizer.cs index 1e18d186ca..f9ef7c51ec 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ImageResizer.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ImageResizer.cs @@ -7,8 +7,11 @@ using System.IO; using System.Linq; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Lib.Utilities; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; +using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; namespace ViewModelTests { @@ -17,38 +20,15 @@ namespace ViewModelTests { public const string Module = "ImageResizer"; + private Mock mockGeneralSettingsUtils; + + private Mock mockImgResizerSettingsUtils; + [TestInitialize] - public void Setup() + public void SetUp_StubSettingUtils() { - // initialize creation of test settings file. - // Test base path: - // C:\Users\\AppData\Local\Packages\08e1807b-8b6d-4bfa-adc4-79c64aae8e78_9abkseg265h2m\LocalState\Microsoft\PowerToys\ - GeneralSettings generalSettings = new GeneralSettings(); - ImageResizerSettings imageResizer = new ImageResizerSettings(); - - SettingsUtils.SaveSettings(generalSettings.ToJsonString()); - SettingsUtils.SaveSettings(imageResizer.ToJsonString(), imageResizer.Name); - } - - [TestCleanup] - public void CleanUp() - { - // delete folder created. - string generalSettings_file_name = string.Empty; - if (SettingsUtils.SettingsFolderExists(generalSettings_file_name)) - { - DeleteFolder(generalSettings_file_name); - } - - if (SettingsUtils.SettingsFolderExists(Module)) - { - DeleteFolder(Module); - } - } - - public void DeleteFolder(string powertoy) - { - Directory.Delete(Path.Combine(SettingsUtils.LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"), true); + mockGeneralSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); + mockImgResizerSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); } [TestMethod] @@ -63,7 +43,7 @@ namespace ViewModelTests }; // arrange - ImageResizerViewModel viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + ImageResizerViewModel viewModel = new ImageResizerViewModel(mockImgResizerSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); // act viewModel.IsEnabled = true; @@ -73,14 +53,16 @@ namespace ViewModelTests public void JPEGQualityLevel_ShouldSetValueToTen_WhenSuccessful() { // arrange + var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); + var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); Func SendMockIPCConfigMSG = msg => { return 0; }; - ImageResizerViewModel viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); // act viewModel.JPEGQualityLevel = 10; // Assert - viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); Assert.AreEqual(10, viewModel.JPEGQualityLevel); } @@ -88,14 +70,16 @@ namespace ViewModelTests public void PngInterlaceOption_ShouldSetValueToTen_WhenSuccessful() { // arrange + var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); + var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); Func SendMockIPCConfigMSG = msg => { return 0; }; - ImageResizerViewModel viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); // act viewModel.PngInterlaceOption = 10; // Assert - viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); Assert.AreEqual(10, viewModel.PngInterlaceOption); } @@ -103,14 +87,16 @@ namespace ViewModelTests public void TiffCompressOption_ShouldSetValueToTen_WhenSuccessful() { // arrange + var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); + var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); Func SendMockIPCConfigMSG = msg => { return 0; }; - ImageResizerViewModel viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); // act viewModel.TiffCompressOption = 10; // Assert - viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); Assert.AreEqual(10, viewModel.TiffCompressOption); } @@ -118,15 +104,17 @@ namespace ViewModelTests public void FileName_ShouldUpdateValue_WhenSuccessful() { // arrange + var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); + var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); Func SendMockIPCConfigMSG = msg => { return 0; }; - ImageResizerViewModel viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); string expectedValue = "%1 (%3)"; // act viewModel.FileName = expectedValue; // Assert - viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); Assert.AreEqual(expectedValue, viewModel.FileName); } @@ -134,29 +122,39 @@ namespace ViewModelTests public void KeepDateModified_ShouldUpdateValue_WhenSuccessful() { // arrange + var settingUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); + + var expectedSettingsString = new ImageResizerSettings() { Properties = new ImageResizerProperties() { ImageresizerKeepDateModified = new BoolProperty() { Value = true } } }.ToJsonString(); + settingUtils.Setup(x => x.SaveSettings( + It.Is(content => content.Equals(expectedSettingsString, StringComparison.Ordinal)), + It.Is(module => module.Equals(Module, StringComparison.Ordinal)), + It.IsAny())) + .Verifiable(); + Func SendMockIPCConfigMSG = msg => { return 0; }; - ImageResizerViewModel viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + ImageResizerViewModel viewModel = new ImageResizerViewModel(settingUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); // act viewModel.KeepDateModified = true; // Assert - ImageResizerSettings settings = SettingsUtils.GetSettings(Module); - Assert.AreEqual(true, settings.Properties.ImageresizerKeepDateModified.Value); + settingUtils.Verify(); } [TestMethod] public void Encoder_ShouldUpdateValue_WhenSuccessful() { // arrange + var mockIOProvider = IIOProviderMocks.GetMockIOProviderForSaveLoadExists(); + var mockSettingsUtils = new SettingsUtils(mockIOProvider.Object); Func SendMockIPCConfigMSG = msg => { return 0; }; - ImageResizerViewModel viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); // act viewModel.Encoder = 3; // Assert - viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + viewModel = new ImageResizerViewModel(mockSettingsUtils, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); Assert.AreEqual("163bcc30-e2e9-4f0b-961d-a3e9fdb788a3", viewModel.GetEncoderGuid(viewModel.Encoder)); Assert.AreEqual(3, viewModel.Encoder); } @@ -165,8 +163,9 @@ namespace ViewModelTests public void AddRow_ShouldAddEmptyImageSize_WhenSuccessful() { // arrange + var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); Func SendMockIPCConfigMSG = msg => { return 0; }; - ImageResizerViewModel viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); int sizeOfOriginalArray = viewModel.Sizes.Count; // act @@ -180,8 +179,9 @@ namespace ViewModelTests public void DeleteImageSize_ShouldDeleteImageSize_WhenSuccessful() { // arrange + var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); Func SendMockIPCConfigMSG = msg => { return 0; }; - ImageResizerViewModel viewModel = new ImageResizerViewModel(SendMockIPCConfigMSG); + ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG); int sizeOfOriginalArray = viewModel.Sizes.Count; ImageSize deleteCandidate = viewModel.Sizes.Where(x => x.Id == 0).First(); diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/KeyboardManager.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/KeyboardManager.cs index 970fe95512..9c730eba9a 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/KeyboardManager.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/KeyboardManager.cs @@ -13,7 +13,7 @@ namespace ViewModelTests [TestClass] public class KeyboardManager { - public const string Module = "Keyboard Manager"; + public const string Module = KeyboardManagerSettings.ModuleName; [TestInitialize] public void Setup() diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerLauncherViewModelTest.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerLauncherViewModelTest.cs index d2c7db9365..c1adf71bd0 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerLauncherViewModelTest.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerLauncherViewModelTest.cs @@ -5,6 +5,7 @@ using Microsoft.PowerToys.Settings.UI.Lib; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; namespace ViewModelTests { @@ -24,13 +25,11 @@ namespace ViewModelTests private PowerLauncherViewModel viewModel; private PowerLauncherSettings mockSettings; private SendCallbackMock sendCallbackMock; - [TestInitialize] public void Initialize() { mockSettings = new PowerLauncherSettings(); sendCallbackMock = new SendCallbackMock(); - viewModel = new PowerLauncherViewModel( mockSettings, new PowerLauncherViewModel.SendCallback(sendCallbackMock.OnSend)); diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs index d319e1cbb9..6b3a78ac2a 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerPreview.cs @@ -7,7 +7,9 @@ using System.IO; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Lib; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; +using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; namespace ViewModelTests { @@ -16,36 +18,12 @@ namespace ViewModelTests { public const string Module = "Test\\File Explorer"; + private Mock mockPowerPreviewSettingsUtils; + [TestInitialize] - public void Setup() + public void SetUp_StubSettingUtils() { - // initialize creation of test settings file. - GeneralSettings generalSettings = new GeneralSettings(); - PowerPreviewSettings powerpreview = new PowerPreviewSettings(); - - SettingsUtils.SaveSettings(generalSettings.ToJsonString()); - SettingsUtils.SaveSettings(powerpreview.ToJsonString(), powerpreview.Name); - } - - [TestCleanup] - public void CleanUp() - { - // delete folder created. - string generalSettings_file_name = string.Empty; - if (SettingsUtils.SettingsFolderExists(generalSettings_file_name)) - { - DeleteFolder(generalSettings_file_name); - } - - if (SettingsUtils.SettingsFolderExists(Module)) - { - DeleteFolder(Module); - } - } - - public void DeleteFolder(string powertoy) - { - Directory.Delete(Path.Combine(SettingsUtils.LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"), true); + mockPowerPreviewSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); } [TestMethod] @@ -60,7 +38,7 @@ namespace ViewModelTests }; // arrange - PowerPreviewViewModel viewModel = new PowerPreviewViewModel(SendMockIPCConfigMSG, Module); + PowerPreviewViewModel viewModel = new PowerPreviewViewModel(SettingsRepository.GetInstance(mockPowerPreviewSettingsUtils.Object), SendMockIPCConfigMSG, Module); // act viewModel.SVGRenderIsEnabled = true; @@ -78,7 +56,7 @@ namespace ViewModelTests }; // arrange - PowerPreviewViewModel viewModel = new PowerPreviewViewModel(SendMockIPCConfigMSG, Module); + PowerPreviewViewModel viewModel = new PowerPreviewViewModel(SettingsRepository.GetInstance(mockPowerPreviewSettingsUtils.Object), SendMockIPCConfigMSG, Module); // act viewModel.SVGThumbnailIsEnabled = true; @@ -96,7 +74,7 @@ namespace ViewModelTests }; // arrange - PowerPreviewViewModel viewModel = new PowerPreviewViewModel(SendMockIPCConfigMSG, Module);; + PowerPreviewViewModel viewModel = new PowerPreviewViewModel(SettingsRepository.GetInstance(mockPowerPreviewSettingsUtils.Object), SendMockIPCConfigMSG, Module); ; // act viewModel.MDRenderIsEnabled = true; diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerRename.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerRename.cs index 10cd6f918b..41b614732e 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerRename.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/PowerRename.cs @@ -7,34 +7,27 @@ using System.IO; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Lib; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; +using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; namespace ViewModelTests { [TestClass] public class PowerRename { - public const string ModuleName = "PowerRename"; + public const string ModuleName = PowerRenameSettings.ModuleName; public const string generalSettings_file_name = "Test\\PowerRename"; + + private Mock mockGeneralSettingsUtils; + + private Mock mockPowerRenamePropertiesUtils; + [TestInitialize] - public void Setup() + public void SetUp_StubSettingUtils() { - // initialize creation of test settings file. - GeneralSettings generalSettings = new GeneralSettings(); - PowerRenameSettings powerRename = new PowerRenameSettings(); - - SettingsUtils.SaveSettings(generalSettings.ToJsonString()); - SettingsUtils.SaveSettings(powerRename.ToJsonString(), generalSettings_file_name, "power-rename-settings.json"); - } - - [TestCleanup] - public void CleanUp() - { - // delete folder created. - if (SettingsUtils.SettingsFolderExists(generalSettings_file_name)) - { - DeleteFolder(generalSettings_file_name); - } + mockGeneralSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); + mockPowerRenamePropertiesUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); } [TestMethod] @@ -49,7 +42,7 @@ namespace ViewModelTests }; // arrange - PowerRenameViewModel viewModel = new PowerRenameViewModel(SendMockIPCConfigMSG, generalSettings_file_name); + PowerRenameViewModel viewModel = new PowerRenameViewModel(mockPowerRenamePropertiesUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG, generalSettings_file_name); // act viewModel.IsEnabled = true; @@ -67,7 +60,7 @@ namespace ViewModelTests }; // arrange - PowerRenameViewModel viewModel = new PowerRenameViewModel(SendMockIPCConfigMSG, generalSettings_file_name); + PowerRenameViewModel viewModel = new PowerRenameViewModel(mockPowerRenamePropertiesUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG, generalSettings_file_name); // act viewModel.MRUEnabled = true; @@ -77,7 +70,7 @@ namespace ViewModelTests public void WhenIsEnabledIsOffAndMRUEnabledIsOffGlobalAndMruShouldBeOff() { Func SendMockIPCConfigMSG = msg => { return 0; }; - PowerRenameViewModel viewModel = new PowerRenameViewModel(SendMockIPCConfigMSG, generalSettings_file_name); + PowerRenameViewModel viewModel = new PowerRenameViewModel(mockPowerRenamePropertiesUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG, generalSettings_file_name); viewModel.IsEnabled = false; viewModel.MRUEnabled = false; @@ -89,7 +82,7 @@ namespace ViewModelTests public void WhenIsEnabledIsOffAndMRUEnabledIsOnGlobalAndMruShouldBeOff() { Func SendMockIPCConfigMSG = msg => { return 0; }; - PowerRenameViewModel viewModel = new PowerRenameViewModel(SendMockIPCConfigMSG, generalSettings_file_name); + PowerRenameViewModel viewModel = new PowerRenameViewModel(mockPowerRenamePropertiesUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG, generalSettings_file_name); viewModel.IsEnabled = false; viewModel.MRUEnabled = true; @@ -101,7 +94,7 @@ namespace ViewModelTests public void WhenIsEnabledIsOnAndMRUEnabledIsOffGlobalAndMruShouldBeOff() { Func SendMockIPCConfigMSG = msg => { return 0; }; - PowerRenameViewModel viewModel = new PowerRenameViewModel(SendMockIPCConfigMSG, generalSettings_file_name); + PowerRenameViewModel viewModel = new PowerRenameViewModel(mockPowerRenamePropertiesUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG, generalSettings_file_name); viewModel.IsEnabled = true; viewModel.MRUEnabled = false; @@ -113,7 +106,7 @@ namespace ViewModelTests public void WhenIsEnabledIsOnAndMRUEnabledIsOnGlobalAndMruShouldBeOn() { Func SendMockIPCConfigMSG = msg => { return 0; }; - PowerRenameViewModel viewModel = new PowerRenameViewModel(SendMockIPCConfigMSG, generalSettings_file_name); + PowerRenameViewModel viewModel = new PowerRenameViewModel(mockPowerRenamePropertiesUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG, generalSettings_file_name); viewModel.IsEnabled = true; viewModel.MRUEnabled = true; @@ -133,7 +126,7 @@ namespace ViewModelTests }; // arrange - PowerRenameViewModel viewModel = new PowerRenameViewModel(SendMockIPCConfigMSG, generalSettings_file_name); + PowerRenameViewModel viewModel = new PowerRenameViewModel(mockPowerRenamePropertiesUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG, generalSettings_file_name); // act viewModel.EnabledOnContextMenu = true; @@ -151,7 +144,7 @@ namespace ViewModelTests }; // arrange - PowerRenameViewModel viewModel = new PowerRenameViewModel(SendMockIPCConfigMSG, generalSettings_file_name); + PowerRenameViewModel viewModel = new PowerRenameViewModel(mockPowerRenamePropertiesUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG, generalSettings_file_name); // act viewModel.EnabledOnContextMenu = true; @@ -169,7 +162,7 @@ namespace ViewModelTests }; // arrange - PowerRenameViewModel viewModel = new PowerRenameViewModel(SendMockIPCConfigMSG, generalSettings_file_name); + PowerRenameViewModel viewModel = new PowerRenameViewModel(mockPowerRenamePropertiesUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG, generalSettings_file_name); // act viewModel.RestoreFlagsOnLaunch = true; @@ -187,15 +180,10 @@ namespace ViewModelTests }; // arrange - PowerRenameViewModel viewModel = new PowerRenameViewModel(SendMockIPCConfigMSG, generalSettings_file_name); + PowerRenameViewModel viewModel = new PowerRenameViewModel(mockPowerRenamePropertiesUtils.Object, SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SendMockIPCConfigMSG, generalSettings_file_name); // act viewModel.MaxDispListNum = 20; } - - public void DeleteFolder(string powertoy) - { - Directory.Delete(Path.Combine(SettingsUtils.LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"), true); - } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs index 7401f6d319..24928c1006 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/ShortcutGuide.cs @@ -7,7 +7,9 @@ using System.IO; using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Lib; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; +using Microsoft.PowerToys.Settings.UI.UnitTests.Mocks; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; namespace ViewModelTests { @@ -16,40 +18,15 @@ namespace ViewModelTests { public const string ShortCutGuideTestFolderName = "Test\\ShortCutGuide"; + private Mock mockGeneralSettingsUtils; + + private Mock mockShortcutGuideSettingsUtils; + [TestInitialize] - public void Setup() + public void SetUp_StubSettingUtils() { - // initialize creation of test settings file. - // Test base path: - // C:\Users\\AppData\Local\Packages\08e1807b-8b6d-4bfa-adc4-79c64aae8e78_9abkseg265h2m\LocalState\Microsoft\PowerToys\ - GeneralSettings generalSettings = new GeneralSettings(); - ShortcutGuideSettings shortcutGuide = new ShortcutGuideSettings(); - - SettingsUtils.SaveSettings(generalSettings.ToJsonString()); - SettingsUtils.SaveSettings(shortcutGuide.ToJsonString(), ShortCutGuideTestFolderName); - } - - [TestCleanup] - public void CleanUp() - { - // delete folder created. - // delete general settings folder. - string ShortCutGuideTestFolderName = string.Empty; - if (SettingsUtils.SettingsFolderExists(string.Empty)) - { - DeleteFolder(string.Empty); - } - - // delete power rename folder. - if (SettingsUtils.SettingsFolderExists(ShortCutGuideTestFolderName)) - { - DeleteFolder(ShortCutGuideTestFolderName); - } - } - - public void DeleteFolder(string powertoy) - { - Directory.Delete(Path.Combine(SettingsUtils.LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}"), true); + mockGeneralSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); + mockShortcutGuideSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils(); } [TestMethod] @@ -65,7 +42,7 @@ namespace ViewModelTests }; // Arrange - ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SendMockIPCConfigMSG, ShortCutGuideTestFolderName); + ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockShortcutGuideSettingsUtils.Object), SendMockIPCConfigMSG, ShortCutGuideTestFolderName); // Act viewModel.IsEnabled = true; @@ -84,7 +61,7 @@ namespace ViewModelTests }; // Arrange - ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SendMockIPCConfigMSG, ShortCutGuideTestFolderName); + ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockShortcutGuideSettingsUtils.Object), SendMockIPCConfigMSG, ShortCutGuideTestFolderName); Assert.AreEqual(1, viewModel.ThemeIndex); // Act @@ -104,7 +81,7 @@ namespace ViewModelTests }; // Arrange - ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SendMockIPCConfigMSG, ShortCutGuideTestFolderName); + ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockShortcutGuideSettingsUtils.Object), SendMockIPCConfigMSG, ShortCutGuideTestFolderName); Assert.AreEqual(900, viewModel.PressTime); // Act @@ -126,7 +103,7 @@ namespace ViewModelTests }; // Arrange - ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SendMockIPCConfigMSG, ShortCutGuideTestFolderName); + ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SettingsRepository.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository.GetInstance(mockShortcutGuideSettingsUtils.Object), SendMockIPCConfigMSG, ShortCutGuideTestFolderName); Assert.AreEqual(90, viewModel.OverlayOpacity); // Act diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Converters/ModuleEnabledToForegroundConverter.cs b/src/core/Microsoft.PowerToys.Settings.UI/Converters/ModuleEnabledToForegroundConverter.cs index bc0558c153..415fa97ba7 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Converters/ModuleEnabledToForegroundConverter.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI/Converters/ModuleEnabledToForegroundConverter.cs @@ -4,6 +4,7 @@ using System; using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Lib.Utilities; using Windows.UI.Xaml; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Media; @@ -12,15 +13,17 @@ namespace Microsoft.PowerToys.Settings.UI.Converters { public sealed class ModuleEnabledToForegroundConverter : IValueConverter { + private readonly ISettingsUtils settingsUtils = new SettingsUtils(new SystemIOProvider()); + + private string selectedTheme = string.Empty; + public object Convert(object value, Type targetType, object parameter, string language) { bool isEnabled = (bool)value; - GeneralSettings generalSettings = SettingsUtils.GetSettings(string.Empty); var defaultTheme = new Windows.UI.ViewManagement.UISettings(); var uiTheme = defaultTheme.GetColorValue(Windows.UI.ViewManagement.UIColorType.Background).ToString(); - - string selectedTheme = generalSettings.Theme.ToLower(); + selectedTheme = SettingsRepository.GetInstance(settingsUtils).SettingsConfig.Theme.ToLower(); if (selectedTheme == "dark" || (selectedTheme == "system" && uiTheme == "#FF000000")) { diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj b/src/core/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj index 3cfa080421..8a8c1ba7ad 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj +++ b/src/core/Microsoft.PowerToys.Settings.UI/Microsoft.PowerToys.Settings.UI.csproj @@ -185,7 +185,7 @@ 6.1.2 - 2.5.0-prerelease.200812001 + 2.5.0-prerelease.200923002 2.0.1 diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs index 4d759ebde0..929fc9398c 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs @@ -2,6 +2,8 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Lib.Utilities; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; using Windows.UI.Xaml.Controls; @@ -13,7 +15,8 @@ namespace Microsoft.PowerToys.Settings.UI.Views public ColorPickerPage() { - ViewModel = new ColorPickerViewModel(ShellPage.SendDefaultIPCMessage); + var settingsUtils = new SettingsUtils(new SystemIOProvider()); + ViewModel = new ColorPickerViewModel(settingsUtils, SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; InitializeComponent(); } diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml b/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml index e4d4cf7c09..8775ea56bd 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml +++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml @@ -285,7 +285,7 @@ Margin="{StaticResource SmallTopMargin}" Text="{x:Bind Mode=TwoWay, Path=ViewModel.ExcludedApps}" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}" - Width="380" + Width="375" Height="160" HorizontalAlignment="Left" ScrollViewer.VerticalScrollBarVisibility ="Visible" diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml.cs index 0d02fa241d..e022e63fd9 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/FancyZonesPage.xaml.cs @@ -2,6 +2,8 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Lib.Utilities; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; using Windows.UI.Xaml.Controls; @@ -14,7 +16,8 @@ namespace Microsoft.PowerToys.Settings.UI.Views public FancyZonesPage() { InitializeComponent(); - ViewModel = new FancyZonesViewModel(ShellPage.SendDefaultIPCMessage); + var settingsUtils = new SettingsUtils(new SystemIOProvider()); + ViewModel = new FancyZonesViewModel(SettingsRepository.GetInstance(settingsUtils), SettingsRepository.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage); DataContext = ViewModel; } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs index 8e7cd9c732..739bafc106 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/GeneralPage.xaml.cs @@ -3,6 +3,8 @@ // See the LICENSE file in the project root for more information. using System; +using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Lib.Utilities; using Microsoft.PowerToys.Settings.UI.Lib.ViewModels; using Windows.ApplicationModel.Resources; using Windows.Data.Json; @@ -31,8 +33,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views // Load string resources ResourceLoader loader = ResourceLoader.GetForViewIndependentUse(); + var settingsUtils = new SettingsUtils(new SystemIOProvider()); ViewModel = new GeneralViewModel( + SettingsRepository.GetInstance(settingsUtils), loader.GetString("GeneralSettings_RunningAsAdminText"), loader.GetString("GeneralSettings_RunningAsUserText"), ShellPage.IsElevated, diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/ImageResizerPage.xaml b/src/core/Microsoft.PowerToys.Settings.UI/Views/ImageResizerPage.xaml index 16f1ae11e4..3939cea8ec 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Views/ImageResizerPage.xaml +++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/ImageResizerPage.xaml @@ -62,7 +62,10 @@ ItemsSource="{x:Bind ViewModel.Sizes, Mode=TwoWay}" Padding="0" IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}" - SelectionMode="None"> + SelectionMode="None" + ScrollViewer.HorizontalScrollMode="Enabled" + ScrollViewer.HorizontalScrollBarVisibility="Auto" + ScrollViewer.IsHorizontalRailEnabled="True">