Code/SboxSuperuser/UI/AdminMenuRenderer.Restrictions.cs
using Sandbox;
using SboxSuperuser.Engine.Vendor.ImGui;
namespace SboxSuperuser.UI;
internal sealed partial class AdminMenuRenderer
{
/// <summary>Every active ban, mute and gag the caller may see, newest first, with revoke buttons.</summary>
private void DrawRestrictionsWindow()
{
if ( !BeginWindow( RestrictionsWindow, "Active restrictions", new Vector2( 56, 56 ), new Vector2( 760, 420 ), new Vector2( 420, 240 ), out var expanded ) ) return;
if ( expanded )
{
Caption( "Every active restriction you are authorized to see. Click a row to open the player." );
DrawRestrictionSearch();
DrawRestrictionTable();
}
ImGui.End();
}
private void DrawRestrictionSearch()
{
var style = ImGui.GetStyle();
var submit = Field( "##restriction-search", "Filter by Steam ID", ref Server.RestrictionSearch, 17,
ImGui.GetContentRegionAvail().x - ButtonWidth( "Search" ) - style.ItemSpacing.x, ImGuiInputTextFlags.EnterReturnsTrue );
ImGui.SameLine();
if ( !ImGui.Button( "Search##restrictions" ) && !submit ) return;
Server.RestrictionPage = 0;
Server.RequestRestrictions( DateTimeOffset.UtcNow, true );
}
private void DrawRestrictionTable()
{
var reply = Server.Restrictions;
if ( reply is null ) { Caption( "Loading..." ); return; }
if ( reply.Status != CommandStatus.Success ) { ColoredWrapped( reply.Message, AdminMenuTheme.Tone( reply.Status ) ); return; }
if ( reply.Restrictions.Length == 0 )
{
Caption( Server.RestrictionSearch.Length > 0 ? "No active restrictions match this Steam ID." : "No active restrictions." );
return;
}
var flags = ImGuiTableFlags.RowBg | ImGuiTableFlags.Borders | ImGuiTableFlags.Resizable | ImGuiTableFlags.ScrollY;
var footer = reply.HasMore || Server.RestrictionPage > 0 ? ImGui.GetFrameHeightWithSpacing() : 0;
if ( ImGui.BeginTable( "restrictions-table", 5, flags, new Vector2( 0, -footer ) ) )
{
ImGui.TableSetupScrollFreeze( 0, 1 );
ImGui.TableSetupColumn( "Player", ImGuiTableColumnFlags.WidthStretch, 1.2f );
ImGui.TableSetupColumn( "Type", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize( "Unmute" ).x );
ImGui.TableSetupColumn( "Expires", ImGuiTableColumnFlags.WidthFixed, ImGui.CalcTextSize( "in 00d 00h" ).x );
ImGui.TableSetupColumn( "Reason", ImGuiTableColumnFlags.WidthStretch, 1.6f );
ImGui.TableSetupColumn( "##revoke", ImGuiTableColumnFlags.WidthFixed, ButtonWidth( "Unmute" ) );
ImGui.TableHeadersRow();
foreach ( var row in reply.Restrictions ) DrawRestrictionRow( row, reply.Actions );
ImGui.EndTable();
}
if ( !reply.HasMore && Server.RestrictionPage == 0 ) return;
var change = Pager( "restrictions", Server.RestrictionPage, reply.HasMore );
if ( change == 0 ) return;
Server.RestrictionPage += change;
Server.RequestRestrictions( DateTimeOffset.UtcNow, true );
}
private void DrawRestrictionRow( AdminModerationRow row, AdminAction[] allowed )
{
ImGui.TableNextRow();
ImGui.PushID( row.RequestId.ToString( "N" ) );
ImGui.TableNextColumn();
// The Steam ID is the row's ID; a name, when the player is online, is drawn text only.
if ( ImGui.Selectable( "##open", false, ImGuiSelectableFlags.SpanAllColumns | ImGuiSelectableFlags.AllowOverlap ) ) SelectPlayer( row.SteamId );
ImGui.SameLine();
var name = NameOf( row.SteamId );
if ( name is null ) ImGui.TextUnformatted( row.SteamId );
else
{
ImGui.TextUnformatted( name );
ImGui.SameLine();
ImGui.TextDisabled( "{0}", row.SteamId );
}
ImGui.TableNextColumn();
ImGui.TextColored( KindTone( row.Kind ), "{0}", KindLabel( row.Kind ) );
ImGui.TableNextColumn();
DrawExpiry( row.ExpiresUtc, true );
ImGui.TableNextColumn();
ImGui.TextWrapped( "{0}", row.Reason );
ImGui.TableNextColumn();
if ( !string.IsNullOrEmpty( row.RestoreCommand ) )
{
if ( ImGui.SmallButton( "Restore" ) ) RunCommand( "Restore this ability?", row.RestoreCommand, new[] { row.SteamId }, confirm: true, needsReason: true, danger: false, ("Original reason", row.Reason) );
ImGui.PopID();
return;
}
AdminAction? lift = row.Kind switch { "Ban" => AdminAction.Unban, "TextMute" => AdminAction.Unmute, "Gag" => AdminAction.Ungag, "Gimp" => AdminAction.Ungimp, _ => null };
if ( lift is { } revoke && allowed.Contains( revoke ) && ImGui.SmallButton( ActionLabel( revoke ) ) )
{
RunCommand( $"{ActionLabel( revoke )} this player?", revoke.ToString().ToLowerInvariant(), new[] { row.SteamId },
confirm: true, needsReason: true, danger: false,
("Player", name is null ? row.SteamId : $"{name} ({row.SteamId})"), ("Original reason", row.Reason) );
}
ImGui.PopID();
}
private string NameOf( string steamId ) =>
Model.Players?.Players.FirstOrDefault( player => player.SteamId == steamId )?.Name;
}