Main.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Collections.Generic; 7 using System.Globalization; 8 using System.Linq; 9 using System.Windows.Controls; 10 11 using ManagedCommon; 12 using Microsoft.PowerToys.Run.Plugin.System.Components; 13 using Microsoft.PowerToys.Run.Plugin.System.Properties; 14 using Microsoft.PowerToys.Settings.UI.Library; 15 using Wox.Infrastructure; 16 using Wox.Plugin; 17 using Wox.Plugin.Common.Win32; 18 19 namespace Microsoft.PowerToys.Run.Plugin.System 20 { 21 public class Main : IPlugin, IPluginI18n, ISettingProvider, IContextMenu, IDelayedExecutionPlugin 22 { 23 private PluginInitContext _context; 24 25 private bool _confirmSystemCommands; 26 private bool _showSuccessOnEmptyRB; 27 private bool _localizeSystemCommands; 28 private bool _reduceNetworkResultScore; 29 private bool _separateEmptyRB; 30 31 public string Name => Resources.Microsoft_plugin_sys_plugin_name; 32 33 public string Description => Resources.Microsoft_plugin_sys_plugin_description; 34 35 public static string PluginID => "CEA08895D2544B019B2E9C5009600DF4"; 36 37 public string IconTheme { get; set; } 38 39 public bool IsBootedInUefiMode { get; set; } 40 41 public IEnumerable<PluginAdditionalOption> AdditionalOptions => new List<PluginAdditionalOption>() 42 { 43 new PluginAdditionalOption() 44 { 45 Key = "ConfirmSystemCommands", 46 DisplayLabel = Resources.confirm_system_commands, 47 Value = false, 48 }, 49 new PluginAdditionalOption() 50 { 51 Key = "ShowSuccessOnEmptyRB", 52 DisplayLabel = Resources.Microsoft_plugin_sys_RecycleBin_ShowEmptySuccessMessage, 53 Value = false, 54 }, 55 new PluginAdditionalOption() 56 { 57 Key = "LocalizeSystemCommands", 58 DisplayLabel = Resources.Use_localized_system_commands, 59 Value = true, 60 }, 61 new PluginAdditionalOption() 62 { 63 Key = "SeparateResultEmptyRB", 64 DisplayLabel = Resources.Microsoft_plugin_sys_RecycleBin_ShowEmptySeparate, 65 Value = false, 66 }, 67 new PluginAdditionalOption() 68 { 69 Key = "ReduceNetworkResultScore", 70 DisplayLabel = Resources.Reduce_Network_Result_Score, 71 DisplayDescription = Resources.Reduce_Network_Result_Score_Description, 72 Value = true, 73 }, 74 }; 75 76 public void Init(PluginInitContext context) 77 { 78 _context = context; 79 _context.API.ThemeChanged += OnThemeChanged; 80 UpdateIconTheme(_context.API.GetCurrentTheme()); 81 IsBootedInUefiMode = Win32Helpers.GetSystemFirmwareType() == FirmwareType.Uefi; 82 83 // Log info if the system hasn't boot in uefi mode. 84 // (Because this is only going into the log we can ignore the fact that normally UEFI and BIOS are written upper case. No need to convert the enumeration value to upper case.) 85 if (!IsBootedInUefiMode) 86 { 87 Wox.Plugin.Logger.Log.Info($"The UEFI command will not show to the user. The system has not booted in UEFI mode or the system does not have an UEFI firmware! (Detected type: {Win32Helpers.GetSystemFirmwareType()})", typeof(Main)); 88 } 89 } 90 91 public List<Result> Query(Query query) 92 { 93 List<Result> results = new List<Result>(); 94 CultureInfo culture = _localizeSystemCommands ? CultureInfo.CurrentUICulture : new CultureInfo("en-US"); 95 96 if (query == null) 97 { 98 return results; 99 } 100 101 // normal system commands are fast and can be returned immediately 102 var systemCommands = Commands.GetSystemCommands(IsBootedInUefiMode, _separateEmptyRB, _confirmSystemCommands, _showSuccessOnEmptyRB, IconTheme, culture); 103 foreach (var c in systemCommands) 104 { 105 var resultMatch = StringMatcher.FuzzySearch(query.Search, c.Title); 106 if (resultMatch.Score > 0) 107 { 108 c.Score = resultMatch.Score; 109 c.TitleHighlightData = resultMatch.MatchData; 110 results.Add(c); 111 } 112 else if (c?.ContextData is SystemPluginContext contextData) 113 { 114 var searchTagMatch = StringMatcher.FuzzySearch(query.Search, contextData.SearchTag); 115 if (searchTagMatch.Score > 0) 116 { 117 c.Score = resultMatch.Score; 118 results.Add(c); 119 } 120 } 121 } 122 123 // The following information result is not returned because delayed queries doesn't clear output if no results are available. 124 // On global queries the first word/part has to be 'ip', 'mac' or 'address' for network results 125 // string[] keywordList = Resources.ResourceManager.GetString("Microsoft_plugin_sys_Search_NetworkKeywordList", culture).Split("; "); 126 // if (!string.IsNullOrEmpty(query.ActionKeyword) || keywordList.Any(x => query.Search.StartsWith(x, StringComparison.CurrentCultureIgnoreCase))) 127 // { 128 // results.Add(new Result() 129 // { 130 // Title = "Getting network information. Please wait ...", 131 // IcoPath = $"Images\\networkAdapter.{IconTheme}.png", 132 // Score = StringMatcher.FuzzySearch("address", "ip address").Score, 133 // }); 134 // } 135 return results; 136 } 137 138 public List<Result> Query(Query query, bool delayedExecution) 139 { 140 List<Result> results = new List<Result>(); 141 CultureInfo culture = _localizeSystemCommands ? CultureInfo.CurrentUICulture : new CultureInfo("en-US"); 142 143 if (query == null) 144 { 145 return results; 146 } 147 148 // Network (ip and mac) results are slow with many network cards and returned delayed. 149 // On global queries the first word/part has to be 'ip', 'mac' or 'address' for network results 150 string[] keywordList = Resources.ResourceManager.GetString("Microsoft_plugin_sys_Search_NetworkKeywordList", culture).Split("; "); 151 if (!string.IsNullOrEmpty(query.ActionKeyword) || keywordList.Any(x => query.Search.StartsWith(x, StringComparison.CurrentCultureIgnoreCase))) 152 { 153 var networkConnectionResults = Commands.GetNetworkConnectionResults(IconTheme, culture); 154 foreach (var r in networkConnectionResults) 155 { 156 var resultMatch = StringMatcher.FuzzySearch(query.Search, r.SubTitle); 157 if (resultMatch.Score > 0) 158 { 159 r.Score = _reduceNetworkResultScore ? (int)(resultMatch.Score * 65 / 100) : resultMatch.Score; // Adjust score to improve user experience and priority order 160 r.SubTitleHighlightData = resultMatch.MatchData; 161 results.Add(r); 162 } 163 else if (r?.ContextData is SystemPluginContext contextData) 164 { 165 var searchTagMatch = StringMatcher.FuzzySearch(query.Search, contextData.SearchTag); 166 if (searchTagMatch.Score > 0) 167 { 168 r.Score = resultMatch.Score; 169 results.Add(r); 170 } 171 } 172 } 173 } 174 175 return results; 176 } 177 178 public List<ContextMenuResult> LoadContextMenus(Result selectedResult) 179 { 180 return ResultHelper.GetContextMenuForResult(selectedResult, _showSuccessOnEmptyRB); 181 } 182 183 private void UpdateIconTheme(Theme theme) 184 { 185 if (theme == Theme.Light || theme == Theme.HighContrastWhite) 186 { 187 IconTheme = "light"; 188 } 189 else 190 { 191 IconTheme = "dark"; 192 } 193 } 194 195 private void OnThemeChanged(Theme currentTheme, Theme newTheme) 196 { 197 UpdateIconTheme(newTheme); 198 } 199 200 public string GetTranslatedPluginDescription() 201 { 202 return Resources.Microsoft_plugin_sys_plugin_description; 203 } 204 205 public string GetTranslatedPluginTitle() 206 { 207 return Resources.Microsoft_plugin_sys_plugin_name; 208 } 209 210 public Control CreateSettingPanel() 211 { 212 throw new NotImplementedException(); 213 } 214 215 public void UpdateSettings(PowerLauncherPluginSettings settings) 216 { 217 var confirmSystemCommands = false; 218 var showSuccessOnEmptyRB = false; 219 var localizeSystemCommands = true; 220 var reduceNetworkResultScore = true; 221 var separateEmptyRB = false; 222 223 if (settings != null && settings.AdditionalOptions != null) 224 { 225 var optionConfirm = settings.AdditionalOptions.FirstOrDefault(x => x.Key == "ConfirmSystemCommands"); 226 confirmSystemCommands = optionConfirm?.Value ?? confirmSystemCommands; 227 228 var optionEmptyRBSuccessMsg = settings.AdditionalOptions.FirstOrDefault(x => x.Key == "ShowSuccessOnEmptyRB"); 229 showSuccessOnEmptyRB = optionEmptyRBSuccessMsg?.Value ?? showSuccessOnEmptyRB; 230 231 var optionLocalize = settings.AdditionalOptions.FirstOrDefault(x => x.Key == "LocalizeSystemCommands"); 232 localizeSystemCommands = optionLocalize?.Value ?? localizeSystemCommands; 233 234 var optionNetworkScore = settings.AdditionalOptions.FirstOrDefault(x => x.Key == "ReduceNetworkResultScore"); 235 reduceNetworkResultScore = optionNetworkScore?.Value ?? reduceNetworkResultScore; 236 237 var optionSeparateEmptyRB = settings.AdditionalOptions.FirstOrDefault(x => x.Key == "SeparateResultEmptyRB"); 238 separateEmptyRB = optionSeparateEmptyRB?.Value ?? separateEmptyRB; 239 } 240 241 _confirmSystemCommands = confirmSystemCommands; 242 _showSuccessOnEmptyRB = showSuccessOnEmptyRB; 243 _localizeSystemCommands = localizeSystemCommands; 244 _reduceNetworkResultScore = reduceNetworkResultScore; 245 _separateEmptyRB = separateEmptyRB; 246 } 247 } 248 }