Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new default 'search score' sorting method for plugin search #1882

Merged
merged 1 commit into from
Jul 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Add new default 'search score' sorting method for plugin search
  • Loading branch information
nebel committed Jul 2, 2024
commit 22d3fb98de8555d0d6b07008adbc427acae71522
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ internal class PluginInstallerWindow : Window, IDisposable

private PluginSortKind sortKind = PluginSortKind.Alphabetical;
private string filterText = Locs.SortBy_Alphabetical;
private bool adaptiveSort = true;

private OperationStatus installStatus = OperationStatus.Idle;
private OperationStatus updateStatus = OperationStatus.Idle;
Expand Down Expand Up @@ -208,6 +209,7 @@ private enum PluginSortKind
NotInstalled,
EnabledDisabled,
ProfileOrNot,
SearchScore,
}

[Flags]
Expand Down Expand Up @@ -280,6 +282,7 @@ public override void OnOpen()
if (!this.isSearchTextPrefilled) this.searchText = string.Empty;
this.sortKind = PluginSortKind.Alphabetical;
this.filterText = Locs.SortBy_Alphabetical;
this.adaptiveSort = true;

if (this.updateStatus == OperationStatus.Complete || this.updateStatus == OperationStatus.Idle)
{
Expand Down Expand Up @@ -588,6 +591,7 @@ private void DrawHeader()
var sortByTextWidth = ImGui.CalcTextSize(sortByText).X;
var sortSelectables = new (string Localization, PluginSortKind SortKind)[]
{
(Locs.SortBy_SearchScore, PluginSortKind.SearchScore),
(Locs.SortBy_Alphabetical, PluginSortKind.Alphabetical),
(Locs.SortBy_DownloadCounts, PluginSortKind.DownloadCount),
(Locs.SortBy_LastUpdate, PluginSortKind.LastUpdate),
Expand Down Expand Up @@ -640,7 +644,29 @@ private void DrawHeader()
}

if (searchTextChanged)
{
if (this.adaptiveSort)
{
if (string.IsNullOrWhiteSpace(this.searchText))
{
this.sortKind = PluginSortKind.Alphabetical;
this.filterText = Locs.SortBy_Alphabetical;
}
else
{
this.sortKind = PluginSortKind.SearchScore;
this.filterText = Locs.SortBy_SearchScore;
}

this.ResortPlugins();
}
else if (this.sortKind == PluginSortKind.SearchScore)
{
this.ResortPlugins();
}

this.UpdateCategoriesOnSearchChange(prevSearchText);
}
}

// Disable sort if changelogs or profile editor
Expand All @@ -653,10 +679,14 @@ private void DrawHeader()
{
foreach (var selectable in sortSelectables)
{
if (selectable.SortKind == PluginSortKind.SearchScore && string.IsNullOrWhiteSpace(this.searchText))
continue;

if (ImGui.Selectable(selectable.Localization))
{
this.sortKind = selectable.SortKind;
this.filterText = selectable.Localization;
this.adaptiveSort = false;

lock (this.listLock)
{
Expand Down Expand Up @@ -3461,8 +3491,6 @@ private bool DrawPluginImages(LocalPlugin? plugin, IPluginManifest manifest, boo

private bool IsManifestFiltered(IPluginManifest manifest)
{
var searchString = this.searchText.ToLowerInvariant();
var matcher = new FuzzyMatcher(searchString, MatchMode.FuzzyParts);
var hasSearchString = !string.IsNullOrWhiteSpace(this.searchText);
var oldApi = (manifest.TestingDalamudApiLevel == null
|| manifest.TestingDalamudApiLevel < PluginManager.DalamudApiLevel)
Expand All @@ -3472,12 +3500,30 @@ private bool IsManifestFiltered(IPluginManifest manifest)
if (oldApi && !hasSearchString && !installed)
return true;

return hasSearchString && !(
(!manifest.Name.IsNullOrEmpty() && matcher.Matches(manifest.Name.ToLowerInvariant()) > 0) ||
(!manifest.InternalName.IsNullOrEmpty() && matcher.Matches(manifest.InternalName.ToLowerInvariant()) > 0) ||
(!manifest.Author.IsNullOrEmpty() && matcher.Matches(manifest.Author.ToLowerInvariant()) > 0) ||
(!manifest.Punchline.IsNullOrEmpty() && manifest.Punchline.ToLowerInvariant().Contains(searchString)) ||
(manifest.Tags != null && matcher.MatchesAny(manifest.Tags.Select(term => term.ToLowerInvariant()).ToArray()) > 0));
if (!hasSearchString)
return false;

return this.GetManifestSearchScore(manifest) < 1;
}

private int GetManifestSearchScore(IPluginManifest manifest)
{
var searchString = this.searchText.ToLowerInvariant();
var matcher = new FuzzyMatcher(searchString, MatchMode.FuzzyParts);
var scores = new List<int> { 0 };

if (!manifest.Name.IsNullOrEmpty())
scores.Add(matcher.Matches(manifest.Name.ToLowerInvariant()) * 110);
if (!manifest.InternalName.IsNullOrEmpty())
scores.Add(matcher.Matches(manifest.InternalName.ToLowerInvariant()) * 105);
if (!manifest.Author.IsNullOrEmpty())
scores.Add(matcher.Matches(manifest.Author.ToLowerInvariant()) * 100);
if (!manifest.Punchline.IsNullOrEmpty())
scores.Add(matcher.Matches(manifest.Punchline.ToLowerInvariant()) * 100);
if (manifest.Tags != null)
scores.Add(matcher.MatchesAny(manifest.Tags.ToArray()) * 100);

return scores.Max();
}

private (bool IsInstalled, LocalPlugin Plugin) IsManifestInstalled(IPluginManifest? manifest)
Expand Down Expand Up @@ -3578,6 +3624,10 @@ bool IsEnabled(PluginManifest manifest)
var profman = Service<ProfileManager>.Get();
this.pluginListInstalled.Sort((p1, p2) => profman.IsInDefaultProfile(p1.EffectiveWorkingPluginId).CompareTo(profman.IsInDefaultProfile(p2.EffectiveWorkingPluginId)));
break;
case PluginSortKind.SearchScore:
this.pluginListAvailable = this.pluginListAvailable.OrderByDescending(this.GetManifestSearchScore).ThenBy(m => m.Name).ToList();
this.pluginListInstalled = this.pluginListInstalled.OrderByDescending(p => this.GetManifestSearchScore(p.Manifest)).ThenBy(m => m.Name).ToList();
break;
default:
throw new InvalidEnumArgumentException("Unknown plugin sort type.");
}
Expand Down Expand Up @@ -3723,6 +3773,8 @@ internal static class Locs

#region SortBy

public static string SortBy_SearchScore => Loc.Localize("InstallerSearchScore", "Search score");

public static string SortBy_Alphabetical => Loc.Localize("InstallerAlphabetical", "Alphabetical");

public static string SortBy_DownloadCounts => Loc.Localize("InstallerDownloadCount", "Download Count");
Expand Down
Loading