using System.Linq; using Content.Client.Administration.Systems; using Content.Client.Administration.UI.CustomControls; using Content.Client.UserInterface.Controls; using Content.Client.Verbs.UI; using Content.Shared.Administration.Logs; using Robust.Client.AutoGenerated; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Input; using Robust.Shared.Network; namespace Content.Client.Administration.UI.Logs.Entries; [GenerateTypedNameReferences] public sealed partial class AdminLogEntryDetails : BoxContainer { private readonly AdminSystem _adminSystem; private readonly IUserInterfaceManager _uiManager; private readonly IEntityManager _entManager; public AdminLogEntryDetails(SharedAdminLog log) { RobustXamlLoader.Load(this); _entManager = IoCManager.Resolve(); _uiManager = IoCManager.Resolve(); _adminSystem = _entManager.System(); Type.Text = log.Type.ToString(); Impact.Text = log.Impact.ToString(); LocalTime.Text = $"{log.Date.ToLocalTime():HH:mm:ss}"; UTCTime.Text = $"{log.Date:HH:mm:ss}"; // TimeSpan and DateTime use different formatting string conventions for some completely logical reason // that mere mortals such as myself will never be able to understand. CurTime.Text = new TimeSpan(log.CurTime).ToString(@"hh\:mm\:ss"); PlayerListContainer.ItemKeyBindDown += PlayerListItemKeyBindDown; PlayerListContainer.GenerateItem += GenerateButton; PopulateList(log.Players); } private void PopulateList(Guid[] players) { if (players.Length == 0) return; if (_adminSystem.PlayerList is not { } allPlayers || allPlayers.Count == 0) return; var listData = new List(); foreach (var playerGuid in players) { var netUserId = new NetUserId(playerGuid); // Linq here is fine since this runs in response to admin input in the UI and // this loop only tends to go through 1-4 iterations. if (allPlayers.FirstOrDefault(player => player.SessionId == netUserId) is not { } playerInfo) continue; listData.Add(new PlayerListData(playerInfo)); } if (listData.Count == 0) return; PlayerListContainer.PopulateList(listData); } private void PlayerListItemKeyBindDown(GUIBoundKeyEventArgs? args, ListData? data) { if (args == null || data is not PlayerListData { Info: var selectedPlayer }) return; if (!(args.Function == EngineKeyFunctions.UIRightClick || args.Function == EngineKeyFunctions.UIClick) || selectedPlayer.NetEntity == null) return; _uiManager.GetUIController().OpenVerbMenu(selectedPlayer.NetEntity.Value, true); args.Handle(); } private void GenerateButton(ListData data, ListContainerButton button) { if (data is not PlayerListData { Info: var info }) return; var entryLabel = new Label(); entryLabel.Text = $"{info.CharacterName} ({info.Username})"; var entry = new BoxContainer(); entry.AddChild(entryLabel); button.AddChild(entry); button.AddStyleClass(ListContainer.StyleClassListContainerButton); } }