Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion BepisModSettings/BepisModSettings.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Version>1.1.1</Version>
<Version>1.2.0</Version>
<Authors>ResoniteModding</Authors>
<TargetFramework>net9.0</TargetFramework>
<Product>Bepis Mod Settings</Product>
Expand Down
10 changes: 6 additions & 4 deletions BepisModSettings/ConfigAttributes/CustomDataFeed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,19 @@ public sealed class CustomDataFeed(DataFeedMethod action)
public static DataFeedMethod GetCustomFeedMethod(ConfigEntryBase config)
{
if (config?.Description?.Tags == null) return null;
foreach (var tag in config.Description.Tags)
foreach (object tag in config.Description.Tags)
{
if(tag is CustomDataFeed customDataFeed)
if (tag is CustomDataFeed customDataFeed)
{
return customDataFeed._action;
}
if(tag is Func<IReadOnlyList<string>, IReadOnlyList<string>, IAsyncEnumerable<DataFeedItem>> func)

if (tag is Func<IReadOnlyList<string>, IReadOnlyList<string>, IAsyncEnumerable<DataFeedItem>> func)
{
return (DataFeedMethod) Delegate.CreateDelegate(typeof(DataFeedMethod), func.Target, func.Method);
return (DataFeedMethod)Delegate.CreateDelegate(typeof(DataFeedMethod), func.Target, func.Method);
}
}

return null;
}
}
2 changes: 1 addition & 1 deletion BepisModSettings/ConfigAttributes/HiddenConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace BepisModSettings.ConfigAttributes;

public class HiddenConfig
public class HiddenConfig
{
public static bool IsHidden(ConfigEntryBase config)
{
Expand Down
8 changes: 5 additions & 3 deletions BepisModSettings/ConfigAttributes/ProtectedConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ public ProtectedConfig() : this("*") { }
public static string GetMask(ConfigEntryBase config)
{
if (config?.Description?.Tags == null) return null;
foreach (var tag in config.Description.Tags)
foreach (object tag in config.Description.Tags)
{
if(tag is ProtectedConfig protectedConfig)
if (tag is ProtectedConfig protectedConfig)
{
return protectedConfig.MaskString;
}
else if(tag as string == "Protected")

if (tag as string == "Protected")
{
return "*";
}
}

return null;
}
}
313 changes: 161 additions & 152 deletions BepisModSettings/DataFeeds/BepisPluginPage.cs

Large diffs are not rendered by default.

141 changes: 120 additions & 21 deletions BepisModSettings/DataFeeds/BepisSettingsPage.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.NET.Common;
using BepInExResoniteShim;
using BepisLocaleLoader;
using Elements.Core;
using FrooxEngine;
using FrooxEngine.UIX;

namespace BepisModSettings.DataFeeds;

public static class BepisSettingsPage
{
public static event Func<IReadOnlyList<string>, IAsyncEnumerable<DataFeedItem>> CustomPluginsPages;

public static string SearchString { get; set; } = "";

internal static async IAsyncEnumerable<DataFeedItem> Enumerate(IReadOnlyList<string> path)
{
await Task.CompletedTask;

DataFeedGroup searchGroup = new DataFeedGroup();
searchGroup.InitBase("SearchGroup", path, null, "Settings.BepInEx.Search".AsLocaleKey());
yield return searchGroup;

string[] searchGroupParam = ["SearchGroup"];

DataFeedValueField<string> searchField = new DataFeedValueField<string>();
searchField.InitBase("SearchField", path, searchGroupParam, "Settings.BepInEx.SearchField".AsLocaleKey());
searchField.InitSetupValue(field =>
{
Slot slot = field.FindNearestParent<Slot>();
if (slot == null) return;

field.Value = SearchString;
field.Changed += _ => SearchString = field.Value;
slot.GetComponentInParents<TextEditor>().LocalEditingFinished += _ => DataFeedHelpers.RefreshSettingsScreen();
});
yield return searchField;

DataFeedGroup plguinsGroup = new DataFeedGroup();
plguinsGroup.InitBase("BepInExPlugins", path, null, "Settings.BepInEx.Plugins".AsLocaleKey());
yield return plguinsGroup;
Expand All @@ -29,36 +55,66 @@ internal static async IAsyncEnumerable<DataFeedItem> Enumerate(IReadOnlyList<str
{
List<PluginInfo> sortedPlugins = new List<PluginInfo>(NetChainloader.Instance.Plugins.Values);
sortedPlugins.Sort((a, b) => string.Compare(a.Metadata.Name, b.Metadata.Name, StringComparison.OrdinalIgnoreCase));
foreach (PluginInfo plugin in sortedPlugins)

List<PluginInfo> filteredPlugins = FilterPlugins(sortedPlugins, SearchString).ToList();
if (filteredPlugins.Count > 0)
{
BepInPlugin metaData = plugin.Metadata;
foreach (PluginInfo pluginInfo in filteredPlugins)
{
BepInPlugin pMetadata = MetadataHelper.GetMetadata(pluginInfo.Instance) ?? pluginInfo.Metadata;
ResonitePlugin resonitePlugin = pMetadata as ResonitePlugin;

string pluginname = metaData.Name;
string pluginGuid = metaData.GUID;
ModMeta metaData = new ModMeta(pMetadata.Name, pMetadata.Version.ToString(), pMetadata.GUID, resonitePlugin?.Author, resonitePlugin?.Link);

LocaleString nameKey = pluginname;
LocaleString description = $"{pluginname}\n{pluginGuid}\n({metaData.Version})"; // "Settings.BepInEx.Plugin.Description".AsLocaleKey(("name", pluginname), ("guid", metaData.GUID), ("version", metaData.Version));
string pluginName = metaData.Name;
string pluginGuid = metaData.ID;
string pluginAuthor = metaData.Author;

if (LocaleLoader.PluginsWithLocales.Contains(plugin))
{
nameKey = $"Settings.{pluginGuid}".AsLocaleKey();
description = $"Settings.{pluginGuid}.Description".AsLocaleKey();
}
else
{
LocaleLoader.AddLocaleString($"Settings.{pluginGuid}.Breadcrumb", pluginname, authors: PluginMetadata.AUTHORS);
}
LocaleString nameKey = pluginName;
LocaleString description = $"{pluginName} ({metaData.Version}){(!string.IsNullOrEmpty(pluginAuthor) ? $"\nby \"{pluginAuthor}\"" : "")}\n\n{pluginGuid}";

if (LocaleLoader.PluginsWithLocales.Contains(pluginInfo))
{
nameKey = $"Settings.{pluginGuid}".AsLocaleKey();
description = $"Settings.{pluginGuid}.Description".AsLocaleKey();
}
else
{
LocaleLoader.AddLocaleString($"Settings.{pluginGuid}.Breadcrumb", pluginName, authors: PluginMetadata.AUTHORS);
}

DataFeedCategory loadedPlugin = new DataFeedCategory();
loadedPlugin.InitBase(pluginGuid, path, loadedPluginsGroup, nameKey, description);
yield return loadedPlugin;
DataFeedCategory loadedPlugin = new DataFeedCategory();
loadedPlugin.InitBase(pluginGuid, path, loadedPluginsGroup, nameKey, description);
yield return loadedPlugin;
}
}
else if (!string.IsNullOrWhiteSpace(SearchString))
{
DataFeedLabel noResults = new DataFeedLabel();
noResults.InitBase("NoSearchResults", path, loadedPluginsGroup, "Settings.BepInEx.Plugins.NoSearchResults".AsLocaleKey());
yield return noResults;
}
else
{
yield return CreateNoPluginsLabel(path, loadedPluginsGroup);
}
}
else
{
DataFeedLabel noPlugins = new DataFeedLabel();
noPlugins.InitBase("NoPlugins", path, loadedPluginsGroup, "Settings.BepInEx.Plugins.NoPlugins".AsLocaleKey());
yield return noPlugins;
yield return CreateNoPluginsLabel(path, loadedPluginsGroup);
}

if (CustomPluginsPages != null)
{
foreach (Delegate del in CustomPluginsPages.GetInvocationList())
{
if (del is not Func<IReadOnlyList<string>, IAsyncEnumerable<DataFeedItem>> handler) continue;

await foreach (DataFeedItem item in handler(path))
{
yield return item;
}
}
}

DataFeedGroup coreGroup = new DataFeedGroup();
Expand All @@ -71,4 +127,47 @@ internal static async IAsyncEnumerable<DataFeedItem> Enumerate(IReadOnlyList<str
bepisCategory.InitBase("BepInEx.Core.Config", path, coreGroupParam, "Settings.BepInEx.Core.Config".AsLocaleKey());
yield return bepisCategory;
}

private static DataFeedLabel CreateNoPluginsLabel(IReadOnlyList<string> path, string[] loadedPluginsGroup)
{
DataFeedLabel noPlugins = new DataFeedLabel();
noPlugins.InitBase("NoPlugins", path, loadedPluginsGroup, "Settings.BepInEx.Plugins.NoPlugins".AsLocaleKey());
return noPlugins;
}

private static IEnumerable<PluginInfo> FilterPlugins(List<PluginInfo> plugins, string searchString)
{
searchString = searchString.Trim();

return plugins.Where(plugin =>
{
if (!Plugin.ShowEmptyPages.Value)
{
if (plugin.Instance is BasePlugin plug && plug.Config.Count == 0)
return false;
}

if (string.IsNullOrWhiteSpace(searchString))
return true;

BepInPlugin pMetadata = MetadataHelper.GetMetadata(plugin.Instance) ?? plugin.Metadata;
ResonitePlugin resonitePlugin = pMetadata as ResonitePlugin;

ModMeta metadata = new ModMeta(pMetadata.Name, pMetadata.Version.ToString(), pMetadata.GUID, resonitePlugin?.Author, resonitePlugin?.Link);

if (metadata.Name.Contains(searchString, StringComparison.InvariantCultureIgnoreCase))
return true;

if (metadata.ID.Contains(searchString, StringComparison.InvariantCultureIgnoreCase))
return true;

if (metadata.Version.Contains(searchString, StringComparison.InvariantCultureIgnoreCase))
return true;

if (!string.IsNullOrEmpty(metadata.Author) && metadata.Author.Contains(searchString, StringComparison.InvariantCultureIgnoreCase))
return true;

return false;
});
}
}
Loading