using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using Flow.Launcher.Plugin; using Flow.Launcher.Plugin.WindowsSettings.Classes; using Flow.Launcher.Plugin.WindowsSettings.Properties; namespace Flow.Launcher.Plugin.WindowsSettings.Helper { /// /// Helper class to easier work with results /// internal static class ResultHelper { private static IPublicAPI? _api; public static void Init(IPublicAPI api) => _api = api; /// /// Return a list with s, based on the given list. /// /// The original result list to convert. /// Query for specific result List /// The path to the icon of each entry. /// A list with . internal static List GetResultList( in IEnumerable list, Query query, string windowsSettingIconPath, string controlPanelIconPath) { var resultList = new List(); foreach (var entry in list) { const int highScore = 20; const int midScore = 10; Result? result; Debug.Assert(_api != null, nameof(_api) + " != null"); var nameMatch = _api.FuzzySearch(query.Search, entry.Name); if (nameMatch.IsSearchPrecisionScoreMet()) { var settingResult = NewSettingResult(nameMatch.Score + highScore, entry.Type); settingResult.TitleHighlightData = nameMatch.MatchData; result = settingResult; } else { var areaMatch = _api.FuzzySearch(query.Search, entry.Area); if (areaMatch.IsSearchPrecisionScoreMet()) { var settingResult = NewSettingResult(areaMatch.Score + midScore, entry.Type); settingResult.SubTitleHighlightData = areaMatch.MatchData.Select(x => x + 6).ToList(); result = settingResult; } else { result = entry.AltNames? .Select(altName => _api.FuzzySearch(query.Search, altName)) .Where(match => match.IsSearchPrecisionScoreMet()) .Select(altNameMatch => NewSettingResult(altNameMatch.Score + midScore, entry.Type)) .FirstOrDefault(); } if (result is null && entry.Keywords is not null) { string[] searchKeywords = query.SearchTerms; if (searchKeywords .All(x => entry .Keywords .SelectMany(x => x) .Contains(x, StringComparer.CurrentCultureIgnoreCase)) ) result = NewSettingResult(midScore, entry.Type); } } if (result is null) continue; AddOptionalToolTip(entry, result); resultList.Add(result); Result NewSettingResult(int score, string type) => new() { Action = _ => DoOpenSettingsAction(entry), IcoPath = type == "AppSettingsApp" ? windowsSettingIconPath : controlPanelIconPath, SubTitle = GetSubtitle(entry.Area, type), Title = entry.Name + entry.glyph, ContextData = entry, Score = score }; } return resultList; } private static string GetSubtitle(string section, string entryType) { var settingType = entryType == "AppSettingsApp" ? "System settings" : "Control Panel"; return $"{settingType} > {section}"; } /// /// Add a tool-tip to the given , based o the given . /// /// The that contain informations for the tool-tip. /// The that need a tool-tip. private static void AddOptionalToolTip(WindowsSetting entry, Result result) { var toolTipText = new StringBuilder(); var settingType = entry.Type == "AppSettingsApp" ? "System settings" : "Control Panel"; toolTipText.AppendLine($"{Resources.Application}: {settingType}"); toolTipText.AppendLine($"{Resources.Area}: {entry.Area}"); if (entry.AltNames != null && entry.AltNames.Any()) { var altList = entry.AltNames.Aggregate((current, next) => $"{current}, {next}"); toolTipText.AppendLine($"{Resources.AlternativeName}: {altList}"); } toolTipText.Append($"{Resources.Command}: {entry.Command}"); if (!string.IsNullOrEmpty(entry.Note)) { toolTipText.AppendLine(string.Empty); toolTipText.AppendLine(string.Empty); toolTipText.Append($"{Resources.Note}: {entry.Note}"); } result.TitleToolTip = toolTipText.ToString(); result.SubTitleToolTip = result.TitleToolTip; } /// /// Open the settings page of the given . /// /// The that contain the information to open the setting on command level. /// if the settings could be opened, otherwise . private static bool DoOpenSettingsAction(WindowsSetting entry) { ProcessStartInfo processStartInfo; var command = entry.Command; command = Environment.ExpandEnvironmentVariables(command); if (command.Contains(' ')) { var commandSplit = command.Split(' '); var file = commandSplit.First(); var arguments = command[file.Length..].TrimStart(); processStartInfo = new ProcessStartInfo(file, arguments) { UseShellExecute = false, }; } else { processStartInfo = new ProcessStartInfo(command) { UseShellExecute = true, }; } try { Process.Start(processStartInfo); return true; } catch (Exception exception) { Log.Exception("can't open settings", exception, typeof(ResultHelper)); return false; } } } }