added shortcut guide settings (#2247)

This commit is contained in:
Lavius Motileng 2020-04-20 06:03:26 -07:00 committed by GitHub
parent 0417b6266a
commit cae77ae291
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 450 additions and 49 deletions

View File

@ -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);
}
}
}

View File

@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Lib namespace Microsoft.PowerToys.Settings.UI.Lib
@ -14,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
this.ImageResizer = false; this.ImageResizer = false;
this.FileExplorerPreview = false; this.FileExplorerPreview = false;
this.PowerRename = false; this.PowerRename = false;
this.ShortcutGuide = true; this.ShortcutGuide = false;
} }
[JsonPropertyName("FancyZones")] [JsonPropertyName("FancyZones")]
@ -30,5 +31,10 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
public bool ShortcutGuide { get; set; } public bool ShortcutGuide { get; set; }
public bool PowerRename { get; set; } public bool PowerRename { get; set; }
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
} }
} }

View File

@ -11,6 +11,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
public static class SettingsUtils public static class SettingsUtils
{ {
private const string DefaultFileName = "settings.json"; private const string DefaultFileName = "settings.json";
private const string DefaultModuleName = "";
public static bool SettingsFolderExists(string powertoy) 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. /// Get a Deserialized object of the json settings string.
/// </summary> /// </summary>
/// <returns>Deserialized json settings object.</returns> /// <returns>Deserialized json settings object.</returns>
public static T GetSettings<T>(string powertoy, string fileName = DefaultFileName) public static T GetSettings<T>(string powertoy = DefaultModuleName, string fileName = DefaultFileName)
{ {
var jsonSettingsString = File.ReadAllText(GetSettingsPath(powertoy, fileName)); var jsonSettingsString = File.ReadAllText(GetSettingsPath(powertoy, fileName));
return JsonSerializer.Deserialize<T>(jsonSettingsString); return JsonSerializer.Deserialize<T>(jsonSettingsString);
} }
// Save settings to a json file. // 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 try
{ {

View File

@ -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; }
}
}

View File

@ -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);
}
}
}

View File

@ -15,7 +15,7 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
public SndModuleSettings(T settings) public SndModuleSettings(T settings)
{ {
powertoys = settings; this.powertoys = settings;
} }
public string ToJsonString() public string ToJsonString()

View File

@ -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);
}
}
}

View File

@ -142,7 +142,7 @@
<comment>Navigation view item name for PowerRename</comment> <comment>Navigation view item name for PowerRename</comment>
</data> </data>
<data name="Shell_ShortcutGuide.Content" xml:space="preserve"> <data name="Shell_ShortcutGuide.Content" xml:space="preserve">
<value>Shortcut Guide [Not Functional]</value> <value>Shortcut Guide</value>
<comment>Navigation view item name for Shortcut Guide</comment> <comment>Navigation view item name for Shortcut Guide</comment>
</data> </data>
<data name="Shell_PowerPreview.Content" xml:space="preserve"> <data name="Shell_PowerPreview.Content" xml:space="preserve">
@ -410,4 +410,19 @@
<data name="FancyZones_SaveZoneInActiveColor.Content" xml:space="preserve"> <data name="FancyZones_SaveZoneInActiveColor.Content" xml:space="preserve">
<value>Save Zone Inactive Color Choice</value> <value>Save Zone Inactive Color Choice</value>
</data> </data>
<data name="ShortcutGuide_Description.Text" xml:space="preserve">
<value>Shows a help overlay with Windows shortcuts when the Windows key is pressed.</value>
</data>
<data name="ShortcutGuide_PressTime.Header" xml:space="preserve">
<value>How long to press the Windows key before showing the Shortcut Guide</value>
</data>
<data name="ShortcutGuide_Appearance_Behaiviour.Text" xml:space="preserve">
<value>Appearance &amp; behaviour</value>
</data>
<data name="ShortcutGuide_Enable.Header" xml:space="preserve">
<value>Enable Shortcut Guide</value>
</data>
<data name="ShortcutGuide_OverlayOpacity.Header" xml:space="preserve">
<value>Opacity of the Shortcut Guide's overlay background (%)</value>
</data>
</root> </root>

View File

@ -2,14 +2,172 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // 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.Helpers;
using Microsoft.PowerToys.Settings.UI.Lib;
using Microsoft.PowerToys.Settings.UI.Views;
namespace Microsoft.PowerToys.Settings.UI.ViewModels namespace Microsoft.PowerToys.Settings.UI.ViewModels
{ {
public class ShortcutGuideViewModel : Observable public class ShortcutGuideViewModel : Observable
{ {
private ShortcutGuideSettings Settings { get; set; }
private const string ModuleName = "Shortcut Guide";
public ShortcutGuideViewModel() public ShortcutGuideViewModel()
{ {
try
{
Settings = SettingsUtils.GetSettings<ShortcutGuideSettings>(ModuleName);
}
catch
{
Settings = new ShortcutGuideSettings();
SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
}
GeneralSettings generalSettings;
try
{
generalSettings = SettingsUtils.GetSettings<GeneralSettings>(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<GeneralSettings>(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<SndShortcutGuideSettings> ipcMessage = new SndModuleSettings<SndShortcutGuideSettings>(outsettings);
ShellPage.DefaultSndMSGCallback(ipcMessage.ToJsonString());
} }
} }
} }

View File

@ -40,35 +40,46 @@
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical" x:Name="ShortCutGuideView">
<TextBlock Text="Shows a help overlay with Windows shortcuts when the Windows key is pressed." <TextBlock x:Uid="ShortcutGuide_Description"
TextWrapping="Wrap"/> TextWrapping="Wrap"/>
<ToggleSwitch Header="Enable Shortcut Guide" <ToggleSwitch x:Uid="ShortcutGuide_Enable"
IsOn="True" IsOn="{ Binding Mode=TwoWay, Path=IsEnabled}"
Margin="{StaticResource SmallTopMargin}" /> Margin="{StaticResource SmallTopMargin}"/>
<TextBlock Text="Appearance &amp; behaviour" <TextBlock x:Uid="ShortcutGuide_Appearance_Behaiviour"
Style="{StaticResource SettingsGroupTitleStyle}"/> Style="{StaticResource SettingsGroupTitleStyle}"/>
<muxc:NumberBox Header="How long to press the Windows key before showing the Shortcut Guide" <muxc:NumberBox x:Uid="ShortcutGuide_PressTime"
Minimum="100" Minimum="100"
Value="900"
SpinButtonPlacementMode="Inline" SpinButtonPlacementMode="Inline"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}" /> Margin="{StaticResource SmallTopMargin}"
Value="{ Binding Mode=TwoWay, Path=PressTime}"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"/>
<Slider Header="Opacity of the Shortcut Guide's overlay background (%)" <Slider x:Uid="ShortcutGuide_OverlayOpacity"
Minimum="0" Minimum="0"
Maximum="100" Maximum="100"
Value="70" Value="{ Binding Mode=TwoWay, Path=OverlayOpacity}"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Margin="{StaticResource MediumTopMargin}"/> Margin="{StaticResource MediumTopMargin}"
IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"/>
<muxc:RadioButtons Header="Theme" Margin="{StaticResource SmallTopMargin}">
<RadioButton Content="Dark"/> <muxc:RadioButtons x:Uid="RadioButtons_Name_Theme"
<RadioButton Content="Light"/> Margin="{StaticResource SmallTopMargin}"
<RadioButton Content="System default" IsChecked="True"/> IsEnabled="{ Binding Mode=TwoWay, Path=IsEnabled}"
SelectedIndex="{ Binding Mode=TwoWay, Path=ThemeIndex}">
<RadioButton x:Uid="GeneralPage_Radio_Theme_Dark"
IsChecked="{ Binding Mode=TwoWay, Path=IsDarkThemeRadioButtonChecked}"/>
<RadioButton x:Uid="GeneralPage_Radio_Theme_Light"
IsChecked="{ Binding Mode=TwoWay, Path=IsLightThemeRadioButtonChecked}"/>
<RadioButton x:Uid="GeneralPage_Radio_Theme_Default"
IsChecked="{ Binding Mode=TwoWay, Path=IsSystemThemeRadioButtonChecked}"/>
</muxc:RadioButtons> </muxc:RadioButtons>
</StackPanel> </StackPanel>
@ -80,12 +91,14 @@
Grid.Column="1"> Grid.Column="1">
<TextBlock <TextBlock
Text="About this feature" x:Uid="About_This_Feature"
Style="{StaticResource SettingsGroupTitleStyle}" Style="{StaticResource SettingsGroupTitleStyle}"
Margin="{StaticResource XSmallBottomMargin}"/> Margin="{StaticResource XSmallBottomMargin}"/>
<Image Source="https://raw.githubusercontent.com/microsoft/PowerToys/dev/build-features/doc/images/shortcut_guide/usage.png" />
<HyperlinkButton <HyperlinkButton
Content="Module overview" x:Uid="Module_overview"
NavigateUri="https://github.com/microsoft/PowerToys/blob/master/src/modules/shortcut_guide/README.md"/> NavigateUri="https://github.com/microsoft/PowerToys/blob/master/src/modules/shortcut_guide/README.md"/>
</StackPanel> </StackPanel>
</Grid> </Grid>

View File

@ -9,11 +9,13 @@ namespace Microsoft.PowerToys.Settings.UI.Views
{ {
public sealed partial class ShortcutGuidePage : Page public sealed partial class ShortcutGuidePage : Page
{ {
public ShortcutGuideViewModel ViewModel { get; } = new ShortcutGuideViewModel(); public ShortcutGuideViewModel ViewModel { get; set; }
public ShortcutGuidePage() public ShortcutGuidePage()
{ {
InitializeComponent(); InitializeComponent();
ViewModel = new ShortcutGuideViewModel();
this.ShortCutGuideView.DataContext = ViewModel;
} }
} }
} }

View File

@ -126,7 +126,7 @@
<Compile Include="UnitTestApp.xaml.cs"> <Compile Include="UnitTestApp.xaml.cs">
<DependentUpon>UnitTestApp.xaml</DependentUpon> <DependentUpon>UnitTestApp.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="ViewModelTests\GeneralSettingsViewModelTest.cs" /> <Compile Include="ViewModelTests\ShortcutGuideViewModelTest.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ApplicationDefinition Include="UnitTestApp.xaml"> <ApplicationDefinition Include="UnitTestApp.xaml">
@ -153,10 +153,10 @@
<Version>6.2.9</Version> <Version>6.2.9</Version>
</PackageReference> </PackageReference>
<PackageReference Include="MSTest.TestAdapter"> <PackageReference Include="MSTest.TestAdapter">
<Version>1.4.0</Version> <Version>2.1.1</Version>
</PackageReference> </PackageReference>
<PackageReference Include="MSTest.TestFramework"> <PackageReference Include="MSTest.TestFramework">
<Version>1.4.0</Version> <Version>2.1.1</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -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;
}
}
}

View File

@ -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\<user name>\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<OutGoingGeneralSettings>(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<ShortcutGuideSettings> snd = JsonSerializer.Deserialize<SndModuleSettings<ShortcutGuideSettings>>(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<ShortcutGuideSettings> snd = JsonSerializer.Deserialize<SndModuleSettings<ShortcutGuideSettings>>(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<ShortcutGuideSettings> snd = JsonSerializer.Deserialize<SndModuleSettings<ShortcutGuideSettings>>(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;
}
}
}