From cae77ae29110bba91bcd87f4e1089f630eae99ea Mon Sep 17 00:00:00 2001 From: Lavius Motileng <58791731+laviusmotileng-ms@users.noreply.github.com> Date: Mon, 20 Apr 2020 06:03:26 -0700 Subject: [PATCH] added shortcut guide settings (#2247) --- .../DoubleProperty.cs | 29 ++++ .../EnabledModules.cs | 8 +- .../SettingsUtils.cs | 5 +- .../ShortcutGuideProperties.cs | 31 ++++ .../ShortcutGuideSettings.cs | 36 ++++ .../SndModuleSettings.cs | 2 +- .../SndShortcutGuideSettings.cs | 25 +++ .../Strings/en-us/Resources.resw | 17 +- .../ViewModels/ShortcutGuideViewModel.cs | 158 ++++++++++++++++++ .../Views/ShortcutGuidePage.xaml | 49 ++++-- .../Views/ShortcutGuidePage.xaml.cs | 4 +- ...crosoft.PowerToys.Settings.UnitTest.csproj | 6 +- .../GeneralSettingsViewModelTest.cs | 22 --- .../ShortcutGuideViewModelTest.cs | 107 ++++++++++++ 14 files changed, 450 insertions(+), 49 deletions(-) create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/DoubleProperty.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideProperties.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideSettings.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/SndShortcutGuideSettings.cs delete mode 100644 src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/GeneralSettingsViewModelTest.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/ShortcutGuideViewModelTest.cs diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/DoubleProperty.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/DoubleProperty.cs new file mode 100644 index 0000000000..662d18a185 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/DoubleProperty.cs @@ -0,0 +1,29 @@ +// 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.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + + // Represents the configuration property of the settings that store Double type. + public class DoubleProperty + { + public DoubleProperty() + { + this.Value = 0.0; + } + + // Gets or sets the double value of the settings configuration. + [JsonPropertyName("value")] + public double Value { get; set; } + + // Returns a JSON version of the class settings configuration class. + public override string ToString() + { + return JsonSerializer.Serialize(this); + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/EnabledModules.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/EnabledModules.cs index b96606ed98..8ade31aac7 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/EnabledModules.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/EnabledModules.cs @@ -2,6 +2,7 @@ // 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; namespace Microsoft.PowerToys.Settings.UI.Lib @@ -14,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib this.ImageResizer = false; this.FileExplorerPreview = false; this.PowerRename = false; - this.ShortcutGuide = true; + this.ShortcutGuide = false; } [JsonPropertyName("FancyZones")] @@ -30,5 +31,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib public bool ShortcutGuide { get; set; } public bool PowerRename { get; set; } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } } } \ No newline at end of file diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs index 5a60a913ff..aea23689c6 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs @@ -11,6 +11,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib public static class SettingsUtils { private const string DefaultFileName = "settings.json"; + private const string DefaultModuleName = ""; public static bool SettingsFolderExists(string powertoy) { @@ -49,14 +50,14 @@ namespace Microsoft.PowerToys.Settings.UI.Lib /// Get a Deserialized object of the json settings string. /// /// Deserialized json settings object. - public static T GetSettings(string powertoy, string fileName = DefaultFileName) + public static T GetSettings(string powertoy = DefaultModuleName, string fileName = DefaultFileName) { var jsonSettingsString = File.ReadAllText(GetSettingsPath(powertoy, fileName)); return JsonSerializer.Deserialize(jsonSettingsString); } // Save settings to a json file. - public static void SaveSettings(string jsonSettings, string powertoy, string fileName = DefaultFileName) + public static void SaveSettings(string jsonSettings, string powertoy = DefaultModuleName, string fileName = DefaultFileName) { try { diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideProperties.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideProperties.cs new file mode 100644 index 0000000000..832570e038 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideProperties.cs @@ -0,0 +1,31 @@ +// 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.Text; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + + public class ShortcutGuideProperties + { + public ShortcutGuideProperties() + { + OverlayOpacity = new IntProperty(); + PressTime = new IntProperty(); + Theme = new StringProperty(); + } + + [JsonPropertyName("overlay_opacity")] + public IntProperty OverlayOpacity { get; set; } + + [JsonPropertyName("press_time")] + public IntProperty PressTime { get; set; } + + [JsonPropertyName("theme")] + public StringProperty Theme { get; set; } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideSettings.cs new file mode 100644 index 0000000000..a195f0037f --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ShortcutGuideSettings.cs @@ -0,0 +1,36 @@ +// 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.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class ShortcutGuideSettings + { + public ShortcutGuideSettings() + { + Name = "Shortcut Guide"; + Properties = new ShortcutGuideProperties(); + Version = "1.0"; + } + + [JsonPropertyName("name")] + public string Name { get; set; } + + [JsonPropertyName("properties")] + public ShortcutGuideProperties Properties { get; set; } + + [JsonPropertyName("version")] + public string Version { get; set; } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndModuleSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndModuleSettings.cs index 14b6fbe00c..440208e30b 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndModuleSettings.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndModuleSettings.cs @@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib public SndModuleSettings(T settings) { - powertoys = settings; + this.powertoys = settings; } public string ToJsonString() diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndShortcutGuideSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndShortcutGuideSettings.cs new file mode 100644 index 0000000000..2b75e2aef2 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SndShortcutGuideSettings.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + + public class SndShortcutGuideSettings + { + [JsonPropertyName("Shortcut Guide")] + public ShortcutGuideSettings ShortcutGuide { get; set; } + + public SndShortcutGuideSettings(ShortcutGuideSettings settings) + { + this.ShortcutGuide = settings; + } + + public string ToJsonString() + { + return JsonSerializer.Serialize(this); + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw b/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw index 0b49b12b8d..d7ffa2fdb7 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw +++ b/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw @@ -142,7 +142,7 @@ Navigation view item name for PowerRename - Shortcut Guide [Not Functional] + Shortcut Guide Navigation view item name for Shortcut Guide @@ -410,4 +410,19 @@ Save Zone Inactive Color Choice + + Shows a help overlay with Windows shortcuts when the Windows key is pressed. + + + How long to press the Windows key before showing the Shortcut Guide + + + Appearance & behaviour + + + Enable Shortcut Guide + + + Opacity of the Shortcut Guide's overlay background (%) + \ No newline at end of file diff --git a/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/ShortcutGuideViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/ShortcutGuideViewModel.cs index e1298f3598..8674767d3f 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/ShortcutGuideViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/ShortcutGuideViewModel.cs @@ -2,14 +2,172 @@ // 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.Runtime.CompilerServices; using Microsoft.PowerToys.Settings.UI.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Views; namespace Microsoft.PowerToys.Settings.UI.ViewModels { public class ShortcutGuideViewModel : Observable { + private ShortcutGuideSettings Settings { get; set; } + + private const string ModuleName = "Shortcut Guide"; + public ShortcutGuideViewModel() { + try + { + Settings = SettingsUtils.GetSettings(ModuleName); + } + catch + { + Settings = new ShortcutGuideSettings(); + SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName); + } + + GeneralSettings generalSettings; + + try + { + generalSettings = SettingsUtils.GetSettings(string.Empty); + } + catch + { + generalSettings = new GeneralSettings(); + SettingsUtils.SaveSettings(generalSettings.ToJsonString(), string.Empty); + } + + this._isEnabled = generalSettings.Enabled.ShortcutGuide; + this._pressTime = Settings.Properties.PressTime.Value; + this._opacity = Settings.Properties.OverlayOpacity.Value; + + string theme = Settings.Properties.Theme.Value; + + if (theme == "dark") + { + _themeIndex = 0; + } + + if (theme == "light") + { + _themeIndex = 1; + } + + if (theme == "system") + { + _themeIndex = 2; + } + } + + private bool _isEnabled = false; + private int _themeIndex = 0; + private int _pressTime = 0; + private int _opacity = 0; + + public bool IsEnabled + { + get + { + return _isEnabled; + } + + set + { + if (value != _isEnabled) + { + _isEnabled = value; + GeneralSettings generalSettings = SettingsUtils.GetSettings(string.Empty); + generalSettings.Enabled.ShortcutGuide = value; + OutGoingGeneralSettings snd = new OutGoingGeneralSettings(generalSettings); + + ShellPage.DefaultSndMSGCallback(snd.ToString()); + RaisePropertyChanged(); + } + } + } + + public int ThemeIndex + { + get + { + return _themeIndex; + } + + set + { + if (_themeIndex != value) + { + if (value == 0) + { + // set theme to dark. + Settings.Properties.Theme.Value = "dark"; + _themeIndex = value; + RaisePropertyChanged(); + } + + if (value == 1) + { + // set theme to light. + Settings.Properties.Theme.Value = "light"; + _themeIndex = value; + RaisePropertyChanged(); + } + + if (value == 2) + { + // set theme to system default. + Settings.Properties.Theme.Value = "system"; + _themeIndex = value; + RaisePropertyChanged(); + } + } + } + } + + public int PressTime + { + get + { + return _pressTime; + } + + set + { + if (_pressTime != value) + { + _pressTime = value; + Settings.Properties.PressTime.Value = value; + RaisePropertyChanged(); + } + } + } + + public int OverlayOpacity + { + get + { + return _opacity; + } + + set + { + if (_opacity != value) + { + _opacity = value; + Settings.Properties.OverlayOpacity.Value = value; + RaisePropertyChanged(); + } + } + } + + public void RaisePropertyChanged([CallerMemberName] string propertyName = null) + { + OnPropertyChanged(propertyName); + SndShortcutGuideSettings outsettings = new SndShortcutGuideSettings(Settings); + SndModuleSettings ipcMessage = new SndModuleSettings(outsettings); + ShellPage.DefaultSndMSGCallback(ipcMessage.ToJsonString()); } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml b/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml index cbc26719e2..0c00e3d43e 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml +++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml @@ -40,35 +40,46 @@ - - + - + - - + Margin="{StaticResource SmallTopMargin}" + Value="{ Binding Mode=TwoWay, Path=PressTime}" + IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"/> - + Margin="{StaticResource MediumTopMargin}" + IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"/> - - - - + + + + + + + @@ -80,12 +91,14 @@ Grid.Column="1"> + + diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml.cs index fe5d0c57d6..77c30926e6 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/ShortcutGuidePage.xaml.cs @@ -9,11 +9,13 @@ namespace Microsoft.PowerToys.Settings.UI.Views { public sealed partial class ShortcutGuidePage : Page { - public ShortcutGuideViewModel ViewModel { get; } = new ShortcutGuideViewModel(); + public ShortcutGuideViewModel ViewModel { get; set; } public ShortcutGuidePage() { InitializeComponent(); + ViewModel = new ShortcutGuideViewModel(); + this.ShortCutGuideView.DataContext = ViewModel; } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UnitTest/Microsoft.PowerToys.Settings.UnitTest.csproj b/src/core/Microsoft.PowerToys.Settings.UnitTest/Microsoft.PowerToys.Settings.UnitTest.csproj index d41e17e914..ed0726395e 100644 --- a/src/core/Microsoft.PowerToys.Settings.UnitTest/Microsoft.PowerToys.Settings.UnitTest.csproj +++ b/src/core/Microsoft.PowerToys.Settings.UnitTest/Microsoft.PowerToys.Settings.UnitTest.csproj @@ -126,7 +126,7 @@ UnitTestApp.xaml - + @@ -153,10 +153,10 @@ 6.2.9 - 1.4.0 + 2.1.1 - 1.4.0 + 2.1.1 diff --git a/src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/GeneralSettingsViewModelTest.cs b/src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/GeneralSettingsViewModelTest.cs deleted file mode 100644 index 257b86167a..0000000000 --- a/src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/GeneralSettingsViewModelTest.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Microsoft.PowerToys.Settings.UI.Lib; -using Microsoft.PowerToys.Settings.UI.ViewModels; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Newtonsoft.Json.Linq; -using Newtonsoft.Json.Schema; -using System; -using System.Diagnostics; - -namespace Microsoft.PowerToys.Settings.UnitTest.ViewModelTests -{ - [TestClass] - public class GeneralSettingsViewModelTest - { - [TestMethod] - [DebuggerStepThrough] - public void Packaged_ShouldSendConfigsWithUpdatedPackageValue_WhenSuccessful() - { - //GeneralViewModel viewModel = new GeneralViewModel(); - //viewModel.Packaged = true; - } - } -} diff --git a/src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/ShortcutGuideViewModelTest.cs b/src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/ShortcutGuideViewModelTest.cs new file mode 100644 index 0000000000..a3fda157a2 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UnitTest/ViewModelTests/ShortcutGuideViewModelTest.cs @@ -0,0 +1,107 @@ +using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.ViewModels; +using Microsoft.PowerToys.Settings.UI.Views; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Schema; +using System; +using System.Diagnostics; +using System.IO; +using System.Text.Json; +using Windows.UI.Popups; + +namespace Microsoft.PowerToys.Settings.UnitTest.ViewModelTests +{ + [TestClass] + public class ShortcutGuideViewModelTest + { + [TestInitialize] + public void Setup() + { + // 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(), shortcutGuide.Name); + } + + [TestMethod] + public void IsEnabled_ShouldEnableModule_WhenSuccessful() + { + // Arrange + ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(); + + // Assert + // Initilize mock function of sending IPC message. + ShellPage.DefaultSndMSGCallback = msg => + { + OutGoingGeneralSettings snd = JsonSerializer.Deserialize(msg); + Assert.IsTrue(snd.general.Enabled.ShortcutGuide); + }; + + // Act + viewModel.IsEnabled = true; + } + + [TestMethod] + public void ThemeIndex_ShouldSetThemeToDark_WhenSuccessful() + { + // Arrange + ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(); + + // Assert + // Initilize mock function of sending IPC message. + ShellPage.DefaultSndMSGCallback = msg => + { + SndModuleSettings snd = JsonSerializer.Deserialize>(msg); + Assert.AreEqual("dark", snd.powertoys.Properties.Theme.Value); + Assert.AreEqual("hey", msg); + }; + + // Act + viewModel.ThemeIndex = 0; + } + + [TestMethod] + public void PressTime_ShouldSetPressTimeToOneHundred_WhenSuccessful() + { + // Arrange + ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(); + + // Assert + // Initilize mock function of sending IPC message. + ShellPage.DefaultSndMSGCallback = msg => + { + SndModuleSettings snd = JsonSerializer.Deserialize>(msg); + // https://stackoverflow.com/questions/59198417/deserialization-of-reference-types-without-parameterless-constructor-is-not-supp + Assert.AreEqual(100, snd.powertoys.Properties.PressTime.Value); + }; + + // Act + viewModel.PressTime = 100; + } + + [TestMethod] + public void OverlayOpacity_ShouldSeOverlayOpacityToOneHundred_WhenSuccessful() + { + // Arrange + ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(); + + // Assert + // Initilize mock function of sending IPC message. + ShellPage.DefaultSndMSGCallback = msg => + { + SndModuleSettings snd = JsonSerializer.Deserialize>(msg); + // Serialisation not working as expected in the test project: + // https://stackoverflow.com/questions/59198417/deserialization-of-reference-types-without-parameterless-constructor-is-not-supp + Assert.AreEqual(100, snd.powertoys.Properties.OverlayOpacity.Value); + }; + + // Act + viewModel.OverlayOpacity = 100; + } + } +}