using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
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;
private static List GetDefaultResults(in IEnumerable list,
string windowsSettingIconPath,
string controlPanelIconPath)
{
return list.Select(entry =>
{
var result = NewSettingResult(100, entry.Type, windowsSettingIconPath, controlPanelIconPath, entry);
AddOptionalToolTip(entry, result);
return result;
}).ToList();
}
///
/// 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)
{
if (string.IsNullOrWhiteSpace(query.Search))
{
return GetDefaultResults(list, windowsSettingIconPath, controlPanelIconPath);
}
var resultList = new List();
foreach (var entry in list)
{
// Adjust the score to lower the order of many irrelevant matches from area strings
// that may only be for description.
const int nonNameMatchScoreAdj = 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, entry.Type, windowsSettingIconPath, controlPanelIconPath, entry);
settingResult.TitleHighlightData = nameMatch.MatchData;
result = settingResult;
}
else
{
var areaMatch = _api.FuzzySearch(query.Search, entry.Area);
if (areaMatch.IsSearchPrecisionScoreMet())
{
var settingResult = NewSettingResult(areaMatch.Score - nonNameMatchScoreAdj, entry.Type, windowsSettingIconPath, controlPanelIconPath, entry);
result = settingResult;
}
else
{
result = entry.AltNames?
.Select(altName => _api.FuzzySearch(query.Search, altName))
.Where(match => match.IsSearchPrecisionScoreMet())
.Select(altNameMatch => NewSettingResult(altNameMatch.Score - nonNameMatchScoreAdj, entry.Type, windowsSettingIconPath, controlPanelIconPath, entry))
.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(nonNameMatchScoreAdj, entry.Type, windowsSettingIconPath, controlPanelIconPath, entry);
}
}
if (result is null)
continue;
AddOptionalToolTip(entry, result);
resultList.Add(result);
}
return resultList;
}
private const int TaskLinkScorePenalty = 50;
private static Result NewSettingResult(int score, string type, string windowsSettingIconPath, string controlPanelIconPath, WindowsSetting entry) => new()
{
Action = _ => DoOpenSettingsAction(entry),
IcoPath = type == "AppSettingsApp" ? windowsSettingIconPath : controlPanelIconPath,
Glyph = entry.IconGlyph,
SubTitle = GetSubtitle(entry.Area, type),
Title = entry.Name,
ContextData = entry,
Score = score - (type == "TaskLink" ? TaskLinkScorePenalty : 0),
};
private static string GetSubtitle(string section, string entryType)
{
var settingType = entryType == "AppSettingsApp" ? Resources.AppSettingsApp : Resources.AppControlPanel;
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" ? Resources.AppSettingsApp : Resources.AppControlPanel;
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 (Win32Exception)
{
try
{
processStartInfo.UseShellExecute = true;
processStartInfo.Verb = "runas";
Process.Start(processStartInfo);
return true;
}
catch (Exception exception)
{
Log.Exception("can't open settings on elevated permission", exception, typeof(ResultHelper));
return false;
}
}
catch (Exception exception)
{
Log.Exception("can't open settings", exception, typeof(ResultHelper));
return false;
}
}
}
}