[Shortcut Guide] Move into separate process (#11359)

This commit is contained in:
Mykhailo Pylyp
2021-05-20 15:07:34 +03:00
committed by GitHub
parent c948c1fca8
commit 601da71f15
114 changed files with 2346 additions and 1771 deletions

View File

@@ -14,8 +14,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library
PressTime = new IntProperty(900);
Theme = new StringProperty("system");
DisabledApps = new StringProperty();
OpenShortcutGuide = new HotkeySettings(true, false, false, true, 0xBF);
}
[JsonPropertyName("open_shortcutguide")]
public HotkeySettings OpenShortcutGuide { get; set; }
[JsonPropertyName("overlay_opacity")]
public IntProperty OverlayOpacity { get; set; }

View File

@@ -11,6 +11,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
{
public class ShortcutGuideViewModel : Observable
{
private ISettingsUtils SettingsUtils { get; set; }
private GeneralSettings GeneralSettingsConfig { get; set; }
private ShortcutGuideSettings Settings { get; set; }
@@ -22,8 +24,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
private string _settingsConfigFileFolder = string.Empty;
private string _disabledApps;
public ShortcutGuideViewModel(ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<ShortcutGuideSettings> moduleSettingsRepository, Func<string, int> ipcMSGCallBackFunc, string configFileSubfolder = "")
public ShortcutGuideViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, ISettingsRepository<ShortcutGuideSettings> moduleSettingsRepository, Func<string, int> ipcMSGCallBackFunc, string configFileSubfolder = "")
{
SettingsUtils = settingsUtils;
// Update Settings file folder:
_settingsConfigFileFolder = configFileSubfolder;
@@ -98,6 +102,23 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
}
}
public HotkeySettings OpenShortcutGuide
{
get
{
return Settings.Properties.OpenShortcutGuide;
}
set
{
if (Settings.Properties.OpenShortcutGuide != value)
{
Settings.Properties.OpenShortcutGuide = value;
NotifyPropertyChanged();
}
}
}
public int ThemeIndex
{
get
@@ -136,24 +157,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
}
}
public int PressTime
{
get
{
return _pressTime;
}
set
{
if (_pressTime != value)
{
_pressTime = value;
Settings.Properties.PressTime.Value = value;
NotifyPropertyChanged();
}
}
}
public int OverlayOpacity
{
get
@@ -198,9 +201,11 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
public void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
OnPropertyChanged(propertyName);
SndShortcutGuideSettings outsettings = new SndShortcutGuideSettings(Settings);
SndModuleSettings<SndShortcutGuideSettings> ipcMessage = new SndModuleSettings<SndShortcutGuideSettings>(outsettings);
SendConfigMSG(ipcMessage.ToJsonString());
SettingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
}
}
}

View File

@@ -42,12 +42,11 @@ namespace ViewModelTests
// Initialise View Model with test Config files
Func<string, int> sendMockIPCConfigMSG = msg => { return 0; };
ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(generalSettingsRepository, shortcutSettingsRepository, sendMockIPCConfigMSG);
ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(mockSettingsUtils, generalSettingsRepository, shortcutSettingsRepository, sendMockIPCConfigMSG);
// Verify that the old settings persisted
Assert.AreEqual(originalGeneralSettings.Enabled.ShortcutGuide, viewModel.IsEnabled);
Assert.AreEqual(originalSettings.Properties.OverlayOpacity.Value, viewModel.OverlayOpacity);
Assert.AreEqual(originalSettings.Properties.PressTime.Value, viewModel.PressTime);
// Verify that the stub file was used
var expectedCallCount = 2; // once via the view model, and once by the test (GetSettings<T>)
@@ -69,6 +68,8 @@ namespace ViewModelTests
[TestMethod]
public void IsEnabledShouldEnableModuleWhenSuccessful()
{
var settingsUtilsMock = new Mock<SettingsUtils>();
// Assert
// Initialize mock function of sending IPC message.
Func<string, int> sendMockIPCConfigMSG = msg =>
@@ -79,7 +80,7 @@ namespace ViewModelTests
};
// Arrange
ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository<ShortcutGuideSettings>.GetInstance(mockShortcutGuideSettingsUtils.Object), sendMockIPCConfigMSG, ShortCutGuideTestFolderName);
ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(settingsUtilsMock.Object, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository<ShortcutGuideSettings>.GetInstance(mockShortcutGuideSettingsUtils.Object), sendMockIPCConfigMSG, ShortCutGuideTestFolderName);
// Act
viewModel.IsEnabled = true;
@@ -88,65 +89,35 @@ namespace ViewModelTests
[TestMethod]
public void ThemeIndexShouldSetThemeToDarkWhenSuccessful()
{
// Assert
// Initialize mock function of sending IPC message.
Func<string, int> sendMockIPCConfigMSG = msg =>
{
ShortcutGuideSettingsIPCMessage snd = JsonSerializer.Deserialize<ShortcutGuideSettingsIPCMessage>(msg);
Assert.AreEqual("dark", snd.Powertoys.ShortcutGuide.Properties.Theme.Value);
return 0;
};
// Arrange
ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository<ShortcutGuideSettings>.GetInstance(mockShortcutGuideSettingsUtils.Object), sendMockIPCConfigMSG, ShortCutGuideTestFolderName);
var settingsUtilsMock = new Mock<ISettingsUtils>();
ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(settingsUtilsMock.Object, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository<ShortcutGuideSettings>.GetInstance(mockShortcutGuideSettingsUtils.Object), msg => { return 0; }, ShortCutGuideTestFolderName);
// Initialize shortcut guide settings theme to 'system' to be in sync with shortcut_guide.h.
Assert.AreEqual(2, viewModel.ThemeIndex);
// Act
viewModel.ThemeIndex = 0;
}
[TestMethod]
public void PressTimeShouldSetPressTimeToOneHundredWhenSuccessful()
{
// Assert
// Initialize mock function of sending IPC message.
Func<string, int> sendMockIPCConfigMSG = msg =>
{
ShortcutGuideSettingsIPCMessage snd = JsonSerializer.Deserialize<ShortcutGuideSettingsIPCMessage>(msg);
Assert.AreEqual(100, snd.Powertoys.ShortcutGuide.Properties.PressTime.Value);
return 0;
};
// Arrange
ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository<ShortcutGuideSettings>.GetInstance(mockShortcutGuideSettingsUtils.Object), sendMockIPCConfigMSG, ShortCutGuideTestFolderName);
Assert.AreEqual(900, viewModel.PressTime);
// Act
viewModel.PressTime = 100;
Func<string, bool> isDark = s => JsonSerializer.Deserialize<ShortcutGuideSettings>(s).Properties.Theme.Value == "dark";
settingsUtilsMock.Verify(x => x.SaveSettings(It.Is<string>(y => isDark(y)), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
}
[TestMethod]
public void OverlayOpacityShouldSeOverlayOpacityToOneHundredWhenSuccessful()
{
// Assert
// Initialize mock function of sending IPC message.
Func<string, int> sendMockIPCConfigMSG = msg =>
{
ShortcutGuideSettingsIPCMessage snd = JsonSerializer.Deserialize<ShortcutGuideSettingsIPCMessage>(msg);
// Serialisation not working as expected in the test project:
Assert.AreEqual(100, snd.Powertoys.ShortcutGuide.Properties.OverlayOpacity.Value);
return 0;
};
// Arrange
ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository<ShortcutGuideSettings>.GetInstance(mockShortcutGuideSettingsUtils.Object), sendMockIPCConfigMSG, ShortCutGuideTestFolderName);
var settingsUtilsMock = new Mock<ISettingsUtils>();
ShortcutGuideViewModel viewModel = new ShortcutGuideViewModel(settingsUtilsMock.Object, SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object), SettingsRepository<ShortcutGuideSettings>.GetInstance(mockShortcutGuideSettingsUtils.Object), msg => { return 0; }, ShortCutGuideTestFolderName);
Assert.AreEqual(90, viewModel.OverlayOpacity);
// Act
viewModel.OverlayOpacity = 100;
// Assert
Func<string, bool> equal100 = s => JsonSerializer.Deserialize<ShortcutGuideSettings>(s).Properties.OverlayOpacity.Value == 100;
settingsUtilsMock.Verify(x => x.SaveSettings(It.Is<string>(y => equal100(y)), It.IsAny<string>(), It.IsAny<string>()), Times.Once);
}
}
}

View File

@@ -28,13 +28,6 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
ColorPickerSharedEventCallback = implementation;
}
public static Func<string> ShortcutGuideSharedEventCallback { get; set; }
public static void SetShortcutGuideSharedEventCallback(Func<string> implementation)
{
ShortcutGuideSharedEventCallback = implementation;
}
public static Action<Type> OpenMainWindowCallback { get; set; }
public static void SetOpenMainWindowCallback(Action<Type> implementation)

View File

@@ -2,6 +2,9 @@
// 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.Diagnostics;
using System.Globalization;
using System.IO;
using System.Threading;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
@@ -27,12 +30,12 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
private void Start_ShortcutGuide_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.ShortcutGuideSharedEventCallback != null)
var executablePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\modules\ShortcutGuide\ShortcutGuide\PowerToys.ShortcutGuide.exe");
var id = Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture);
var p = Process.Start(executablePath, id);
if (p != null)
{
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, OobeShellPage.ShortcutGuideSharedEventCallback()))
{
eventHandle.Set();
}
p.Close();
}
ViewModel.LogRunningModuleEvent();

View File

@@ -477,10 +477,6 @@
<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>Press duration before showing (ms)</value>
<comment>pressing a key in milliseconds</comment>
</data>
<data name="ShortcutGuide_Appearance_Behavior.Text" xml:space="preserve">
<value>Appearance &amp; behavior</value>
</data>
@@ -1097,7 +1093,7 @@ From there, simply click on a Markdown file or SVG icon in the File Explorer and
<value>PowerToys Run supports various action keys to funnel search queries for a specific subset of results. Typing {&lt;} searches for running processes only, {?} will search only for file, or {.} for installed applications! See PowerToys documentation for the complete set of 'Action Keys' available.</value>
</data>
<data name="Oobe_ShortcutGuide_HowToLaunch.Text" xml:space="preserve">
<value>{Win} + {?} to open Shortcut Guide, press it again to close or press {Esc}. You can also launch it by holding the {Win} key for one second!</value>
<value>{Shift} + {Win} + {/} to open Shortcut Guide, press it again to close or press {Esc}.</value>
</data>
<data name="Oobe_TipsAndTricks.Text" xml:space="preserve">
<value>Tips &amp; tricks</value>
@@ -1195,4 +1191,7 @@ From there, simply click on a Markdown file or SVG icon in the File Explorer and
<data name="FancyZones_QuickLayoutSwitch_GroupSettings.Text" xml:space="preserve">
<value>Quick layout switch</value>
</data>
</root>
<data name="ShortcutGuide_OpenShortcutGuide.Header" xml:space="preserve">
<value>Open Shortcut Guide</value>
</data>
</root>

View File

@@ -2,12 +2,11 @@
x:Class="Microsoft.PowerToys.Settings.UI.Views.ShortcutGuidePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModel="using:Microsoft.PowerToys.Settings.UI.ViewModels"
xmlns:CustomControls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:converters="using:Microsoft.Toolkit.Uwp.UI.Converters"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
AutomationProperties.LandmarkType="Main">
@@ -58,21 +57,22 @@
<ToggleSwitch x:Uid="ShortcutGuide_Enable"
IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.IsEnabled}"/>
<TextBlock x:Uid="Shortcuts"
Style="{StaticResource SettingsGroupTitleStyle}"
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
<CustomControls:HotkeySettingsControl x:Uid="ShortcutGuide_OpenShortcutGuide"
HorizontalAlignment="Left"
MinWidth="240"
Margin="{StaticResource SmallTopMargin}"
HotkeySettings="{x:Bind Path=ViewModel.OpenShortcutGuide, Mode=TwoWay}"
Keys="Win, Ctrl, Alt, Shift"
Enabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"/>
<TextBlock x:Uid="ShortcutGuide_Appearance_Behavior"
Style="{StaticResource SettingsGroupTitleStyle}"
Foreground="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled, Converter={StaticResource ModuleEnabledToForegroundConverter}}"/>
<muxc:NumberBox x:Uid="ShortcutGuide_PressTime"
Minimum="100"
SpinButtonPlacementMode="Compact"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
MinWidth="240"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.PressTime}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}"
SmallChange="50"
LargeChange="100"/>
<StackPanel Orientation="Horizontal" Margin="{StaticResource MediumTopMargin}" Spacing="12">
<Slider x:Uid="ShortcutGuide_OverlayOpacity"
Minimum="0"

View File

@@ -18,7 +18,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
InitializeComponent();
var settingsUtils = new SettingsUtils();
ViewModel = new ShortcutGuideViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<ShortcutGuideSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
ViewModel = new ShortcutGuideViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), SettingsRepository<ShortcutGuideSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}

View File

@@ -78,12 +78,6 @@ namespace PowerToys.Settings
return Constants.ShowColorPickerSharedEvent();
});
OobeShellPage.SetShortcutGuideSharedEventCallback(() =>
{
NativeMethods.AllowSetForegroundWindow(PowerToys.Settings.Program.PowerToysPID);
return Constants.ShowShortcutGuideSharedEvent();
});
OobeShellPage.SetOpenMainWindowCallback((Type type) =>
{
((App)Application.Current).OpenSettingsWindow(type);