PowerToys/src/modules/launcher/PowerLauncher/SettingsWatcher.cs

165 lines
6.6 KiB
C#
Raw Normal View History

// 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.IO;
using System.IO.Abstractions;
using System.Threading;
using System.Windows.Input;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Library;
using PowerLauncher.Helper;
using Wox.Core.Plugin;
using Wox.Infrastructure.Hotkey;
using Wox.Infrastructure.UserSettings;
using Wox.Plugin;
using Wox.Plugin.Logger;
using JsonException = System.Text.Json.JsonException;
namespace PowerLauncher
{
// Watch for /Local/Microsoft/PowerToys/Launcher/Settings.json changes
public class SettingsWatcher : BaseModel
{
private readonly ISettingsUtils _settingsUtils;
private const int MaxRetries = 10;
private static readonly object _watcherSyncObject = new object();
private readonly IFileSystemWatcher _watcher;
[fxcop] Wox.Infrastructure (#7590) * CA1052: Static holder types should be Static or NotInheritable * CA1041: Provide ObsoleteAttribute message * CA1062: Validate arguments of public methods * CA1304: Specify CultureInfo / CA1305: Specify IFormatProvider / CA1307: Specify StringComparison for clarity * CA1802: Use Literals Where Appropriate * CA1820: Test for empty strings using string length * CA1707: Identifiers should not contain underscores * CA1805: Do not initialize unnecessarily. * CA1822: Mark members as static * CA2227: Collection properties should be read only * CA1054: URI parameters should not be strings * CA1031: Do not catch general exception types * CA1060: Move P/Invokes to NativeMethods class * CA1308: Normalize strings to uppercase * CA2000: Dispose objects before losing scope / CA2234: Pass System.Uri objects instead of strings * CA2234: Pass System.Uri objects instead of strings * CA1044: Properties should not be write only * CA1716: Identifiers should not match keywords * CA2007: Do not directly await a Task * CA2007: Do not directly await a Task (Suppressed) * CA5350: Do Not Use Weak Cryptographic Algorithms (Suppressed) * CA1724: Type names should not match namespaces (renamed Settings.cs to PowerToysRunSettings.cs) * CA1033: Interface methods should be callable by child types (Added sealed modifier to class) * CA1724: Type names should not match namespaces (Renamed Plugin.cs to RunPlugin.cs) * CA1724: Type names should not match namespaces (Renamed Http.cs to HttpClient.cs) * CA5364: Do not use deprecated security protocols (Remove unused code) * Enabled FxCopAnalyzer for Wox.Infrastructure * fixed comment * Addressed comments - Changed Ordinal to InvariantCulture - Added comments - Removed unused obsolete code - Removed unused method (CA2007: Do not directly await a Task) * Addressed comments - fixed justification for CA1031 suppression * Addressed comments - Fixed justification for CA1031 suppression in Wox.Core/Wox.Plugin
2020-10-30 08:52:35 +08:00
private readonly PowerToysRunSettings _settings;
private readonly ThemeManager _themeManager;
[fxcop] Wox.Infrastructure (#7590) * CA1052: Static holder types should be Static or NotInheritable * CA1041: Provide ObsoleteAttribute message * CA1062: Validate arguments of public methods * CA1304: Specify CultureInfo / CA1305: Specify IFormatProvider / CA1307: Specify StringComparison for clarity * CA1802: Use Literals Where Appropriate * CA1820: Test for empty strings using string length * CA1707: Identifiers should not contain underscores * CA1805: Do not initialize unnecessarily. * CA1822: Mark members as static * CA2227: Collection properties should be read only * CA1054: URI parameters should not be strings * CA1031: Do not catch general exception types * CA1060: Move P/Invokes to NativeMethods class * CA1308: Normalize strings to uppercase * CA2000: Dispose objects before losing scope / CA2234: Pass System.Uri objects instead of strings * CA2234: Pass System.Uri objects instead of strings * CA1044: Properties should not be write only * CA1716: Identifiers should not match keywords * CA2007: Do not directly await a Task * CA2007: Do not directly await a Task (Suppressed) * CA5350: Do Not Use Weak Cryptographic Algorithms (Suppressed) * CA1724: Type names should not match namespaces (renamed Settings.cs to PowerToysRunSettings.cs) * CA1033: Interface methods should be callable by child types (Added sealed modifier to class) * CA1724: Type names should not match namespaces (Renamed Plugin.cs to RunPlugin.cs) * CA1724: Type names should not match namespaces (Renamed Http.cs to HttpClient.cs) * CA5364: Do not use deprecated security protocols (Remove unused code) * Enabled FxCopAnalyzer for Wox.Infrastructure * fixed comment * Addressed comments - Changed Ordinal to InvariantCulture - Added comments - Removed unused obsolete code - Removed unused method (CA2007: Do not directly await a Task) * Addressed comments - fixed justification for CA1031 suppression * Addressed comments - Fixed justification for CA1031 suppression in Wox.Core/Wox.Plugin
2020-10-30 08:52:35 +08:00
public SettingsWatcher(PowerToysRunSettings settings, ThemeManager themeManager)
{
_settingsUtils = new SettingsUtils();
_settings = settings;
_themeManager = themeManager;
// Set up watcher
_watcher = Microsoft.PowerToys.Settings.UI.Library.Utilities.Helper.GetFileWatcher(PowerLauncherSettings.ModuleName, "settings.json", OverloadSettings);
// Load initial settings file
OverloadSettings();
2020-11-03 18:30:19 +08:00
// Apply theme at startup
_themeManager.ChangeTheme(_settings.Theme, _settings.Theme == Theme.System);
}
public void CreateSettingsIfNotExists()
{
if (!_settingsUtils.SettingsExists(PowerLauncherSettings.ModuleName))
{
Log.Info("PT Run settings.json was missing, creating a new one", GetType());
var defaultSettings = new PowerLauncherSettings();
defaultSettings.Save(_settingsUtils);
}
}
public void OverloadSettings()
{
Monitor.Enter(_watcherSyncObject);
var retry = true;
var retryCount = 0;
while (retry)
{
try
{
retryCount++;
CreateSettingsIfNotExists();
var overloadSettings = _settingsUtils.GetSettings<PowerLauncherSettings>(PowerLauncherSettings.ModuleName);
var openPowerlauncher = ConvertHotkey(overloadSettings.Properties.OpenPowerLauncher);
if (_settings.Hotkey != openPowerlauncher)
{
_settings.Hotkey = openPowerlauncher;
}
var shell = PluginManager.AllPlugins.Find(pp => pp.Metadata.Name == "Shell");
if (shell != null)
{
var shellSettings = shell.Plugin as ISettingProvider;
shellSettings.UpdateSettings(overloadSettings);
}
if (_settings.MaxResultsToShow != overloadSettings.Properties.MaximumNumberOfResults)
{
_settings.MaxResultsToShow = overloadSettings.Properties.MaximumNumberOfResults;
}
if (_settings.IgnoreHotkeysOnFullscreen != overloadSettings.Properties.IgnoreHotkeysInFullscreen)
{
_settings.IgnoreHotkeysOnFullscreen = overloadSettings.Properties.IgnoreHotkeysInFullscreen;
}
// Using OrdinalIgnoreCase since this is internal
var indexer = PluginManager.AllPlugins.Find(p => p.Metadata.Name.Equals("Windows Indexer", StringComparison.OrdinalIgnoreCase));
if (indexer != null)
{
var indexerSettings = indexer.Plugin as ISettingProvider;
indexerSettings.UpdateSettings(overloadSettings);
}
if (_settings.ClearInputOnLaunch != overloadSettings.Properties.ClearInputOnLaunch)
{
_settings.ClearInputOnLaunch = overloadSettings.Properties.ClearInputOnLaunch;
}
if (_settings.Theme != overloadSettings.Properties.Theme)
{
_settings.Theme = overloadSettings.Properties.Theme;
_themeManager.ChangeTheme(_settings.Theme, _settings.Theme == Theme.System);
}
retry = false;
}
// the settings application can hold a lock on the settings.json file which will result in a IOException.
// This should be changed to properly synch with the settings app instead of retrying.
catch (IOException e)
{
if (retryCount > MaxRetries)
{
retry = false;
Log.Exception($"Failed to Deserialize PowerToys settings, Retrying {e.Message}", e, GetType());
}
else
{
Thread.Sleep(1000);
}
}
catch (JsonException e)
{
if (retryCount > MaxRetries)
{
retry = false;
Log.Exception($"Failed to Deserialize PowerToys settings, Creating new settings as file could be corrupted {e.Message}", e, GetType());
// Settings.json could possibly be corrupted. To mitigate this we delete the
// current file and replace it with a correct json value.
_settingsUtils.DeleteSettings(PowerLauncherSettings.ModuleName);
CreateSettingsIfNotExists();
ErrorReporting.ShowMessageBox(Properties.Resources.deseralization_error_title, Properties.Resources.deseralization_error_message);
}
else
{
Thread.Sleep(1000);
}
}
}
Monitor.Exit(_watcherSyncObject);
}
private static string ConvertHotkey(HotkeySettings hotkey)
{
Key key = KeyInterop.KeyFromVirtualKey(hotkey.Code);
HotkeyModel model = new HotkeyModel(hotkey.Alt, hotkey.Shift, hotkey.Win, hotkey.Ctrl, key);
return model.ToString();
}
}
}