Add search filter to the admin menu player tab (#28030)

This commit is contained in:
ShadowCommander
2024-05-30 23:28:08 -07:00
committed by GitHub
parent dbcdefc5fd
commit 3ed1ee6a5b
12 changed files with 236 additions and 80 deletions

View File

@@ -1,5 +1,6 @@
using System.Linq;
using Content.Client.Administration.Systems;
using Content.Client.UserInterface.Controls;
using Content.Shared.Administration;
using Robust.Client.AutoGenerated;
using Robust.Client.Graphics;
@@ -28,15 +29,14 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
private bool _ascending = true;
private bool _showDisconnected;
public event Action<PlayerTabEntry, GUIBoundKeyEventArgs>? OnEntryKeyBindDown;
public event Action<GUIBoundKeyEventArgs, ListData>? OnEntryKeyBindDown;
public PlayerTab()
{
IoCManager.InjectDependencies(this);
_adminSystem = _entManager.System<AdminSystem>();
RobustXamlLoader.Load(this);
RefreshPlayerList(_adminSystem.PlayerList);
_adminSystem = _entManager.System<AdminSystem>();
_adminSystem.PlayerListChanged += RefreshPlayerList;
_adminSystem.OverlayEnabled += OverlayEnabled;
_adminSystem.OverlayDisabled += OverlayDisabled;
@@ -46,8 +46,17 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
ListHeader.BackgroundColorPanel.PanelOverride = new StyleBoxFlat(_altColor);
ListHeader.OnHeaderClicked += HeaderClicked;
SearchList.SearchBar = SearchLineEdit;
SearchList.GenerateItem += GenerateButton;
SearchList.DataFilterCondition += DataFilterCondition;
SearchList.ItemKeyBindDown += (args, data) => OnEntryKeyBindDown?.Invoke(args, data);
RefreshPlayerList(_adminSystem.PlayerList);
}
#region Antag Overlay
private void OverlayEnabled()
{
OverlayButton.Pressed = true;
@@ -70,6 +79,8 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
}
}
#endregion
private void ShowDisconnectedPressed(ButtonEventArgs args)
{
_showDisconnected = args.Button.Pressed;
@@ -92,14 +103,10 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
}
}
#region ListContainer
private void RefreshPlayerList(IReadOnlyList<PlayerInfo> players)
{
foreach (var child in PlayerList.Children.ToArray())
{
if (child is PlayerTabEntry)
child.Dispose();
}
_players = players;
PlayerCount.Text = $"Players: {_playerMan.PlayerCount}";
@@ -108,29 +115,66 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
UpdateHeaderSymbols();
var useAltColor = false;
foreach (var player in sortedPlayers)
{
if (!_showDisconnected && !player.Connected)
continue;
var entry = new PlayerTabEntry(player.Username,
player.CharacterName,
player.IdentityName,
player.StartingJob,
player.Antag ? "YES" : "NO",
new StyleBoxFlat(useAltColor ? _altColor : _defaultColor),
player.Connected,
player.PlaytimeString);
entry.PlayerEntity = player.NetEntity;
entry.OnKeyBindDown += args => OnEntryKeyBindDown?.Invoke(entry, args);
entry.ToolTip = Loc.GetString("player-tab-entry-tooltip");
PlayerList.AddChild(entry);
useAltColor ^= true;
}
SearchList.PopulateList(sortedPlayers.Select(info => new PlayerListData(info,
$"{info.Username} {info.CharacterName} {info.IdentityName} {info.StartingJob}"))
.ToList());
}
private void GenerateButton(ListData data, ListContainerButton button)
{
if (data is not PlayerListData { Info: var player})
return;
var entry = new PlayerTabEntry(player, new StyleBoxFlat(button.Index % 2 == 0 ? _altColor : _defaultColor));
button.AddChild(entry);
button.ToolTip = $"{player.Username}, {player.CharacterName}, {player.IdentityName}, {player.StartingJob}";
}
/// <summary>
/// Determines whether <paramref name="filter"/> is contained in <paramref name="listData"/>.FilteringString.
/// If all characters are lowercase, the comparison ignores case.
/// If there is an uppercase character, the comparison is case sensitive.
/// </summary>
/// <param name="filter"></param>
/// <param name="listData"></param>
/// <returns>Whether <paramref name="filter"/> is contained in <paramref name="listData"/>.FilteringString.</returns>
private bool DataFilterCondition(string filter, ListData listData)
{
if (listData is not PlayerListData {Info: var info, FilteringString: var playerString})
return false;
if (!_showDisconnected && !info.Connected)
return false;
if (IsAllLower(filter))
{
if (!playerString.Contains(filter, StringComparison.CurrentCultureIgnoreCase))
return false;
}
else
{
if (!playerString.Contains(filter))
return false;
}
return true;
}
private bool IsAllLower(string input)
{
foreach (var c in input)
{
if (char.IsLetter(c) && !char.IsLower(c))
return false;
}
return true;
}
#endregion
#region Header
private void UpdateHeaderSymbols()
{
ListHeader.ResetHeaderText();
@@ -174,5 +218,9 @@ namespace Content.Client.Administration.UI.Tabs.PlayerTab
RefreshPlayerList(_adminSystem.PlayerList);
}
#endregion
}
public record PlayerListData(PlayerInfo Info, string FilteringString) : ListData;
}