diff --git a/Content.Client/Administration/UI/BanList/BanListControl.xaml b/Content.Client/Administration/UI/BanList/BanListControl.xaml new file mode 100644 index 0000000000..b202e92e57 --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListControl.xaml @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/Content.Client/Administration/UI/BanList/BanListControl.xaml.cs b/Content.Client/Administration/UI/BanList/BanListControl.xaml.cs new file mode 100644 index 0000000000..d9a892ffad --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListControl.xaml.cs @@ -0,0 +1,72 @@ +using System.Linq; +using Content.Client.Administration.UI.CustomControls; +using Content.Shared.Administration.BanList; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.Administration.UI.BanList; + +[GenerateTypedNameReferences] +public sealed partial class BanListControl : Control +{ + private BanListIdsPopup? _popup; + + public BanListControl() + { + RobustXamlLoader.Load(this); + } + + public void SetBans(List bans) + { + foreach (var control in Bans.Children.ToArray()[1..]) + { + control.Orphan(); + } + + foreach (var ban in bans) + { + Bans.AddChild(new HSeparator()); + + var line = new BanListLine(ban); + line.OnIdsClicked += LineIdsClicked; + + Bans.AddChild(line); + } + } + + private void ClosePopup() + { + _popup?.Close(); + _popup = null; + } + + private bool LineIdsClicked(BanListLine line) + { + ClosePopup(); + + var ban = line.Ban; + var ip = ban.Address == null + ? string.Empty + : Loc.GetString("ban-list-ip", ("ip", ban.Address.Value.address)); + var hwid = ban.HWId == null ? string.Empty : Loc.GetString("ban-list-hwid", ("hwid", ban.HWId)); + var guid = ban.UserId == null ? string.Empty : Loc.GetString("ban-list-guid", ("guid", ban.UserId.Value.ToString())); + + _popup = new BanListIdsPopup(ip, hwid, guid); + + var box = UIBox2.FromDimensions(UserInterfaceManager.MousePositionScaled.Position, (1, 1)); + _popup.Open(box); + + return true; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + if (_popup != null) + { + UserInterfaceManager.PopupRoot.RemoveChild(_popup); + } + } +} diff --git a/Content.Client/Administration/UI/BanList/BanListEui.cs b/Content.Client/Administration/UI/BanList/BanListEui.cs new file mode 100644 index 0000000000..86f2541e51 --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListEui.cs @@ -0,0 +1,34 @@ +using Content.Client.Eui; +using Content.Shared.Administration.BanList; +using Content.Shared.Eui; + +namespace Content.Client.Administration.UI.BanList; + +public sealed class BanListEui : BaseEui +{ + public BanListEui() + { + BanWindow = new BanListWindow(); + BanControl = BanWindow.BanList; + } + + private BanListWindow BanWindow { get; } + + private BanListControl BanControl { get; } + + public override void HandleState(EuiStateBase state) + { + if (state is not BanListEuiState s) + return; + + BanWindow.SetTitlePlayer(s.BanListPlayerName); + + s.Bans.Sort((a, b) => a.BanTime.CompareTo(b.BanTime)); + BanControl.SetBans(s.Bans); + } + + public override void Opened() + { + BanWindow.OpenCentered(); + } +} diff --git a/Content.Client/Administration/UI/BanList/BanListHeader.xaml b/Content.Client/Administration/UI/BanList/BanListHeader.xaml new file mode 100644 index 0000000000..af02027758 --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListHeader.xaml @@ -0,0 +1,31 @@ + + + + + + diff --git a/Content.Client/Administration/UI/BanList/BanListHeader.xaml.cs b/Content.Client/Administration/UI/BanList/BanListHeader.xaml.cs new file mode 100644 index 0000000000..6c49ff3e5b --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListHeader.xaml.cs @@ -0,0 +1,14 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.Administration.UI.BanList; + +[GenerateTypedNameReferences] +public sealed partial class BanListHeader : ContainerButton +{ + public BanListHeader() + { + RobustXamlLoader.Load(this); + } +} diff --git a/Content.Client/Administration/UI/BanList/BanListIdsPopup.xaml b/Content.Client/Administration/UI/BanList/BanListIdsPopup.xaml new file mode 100644 index 0000000000..dbd58b8c27 --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListIdsPopup.xaml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/Content.Client/Administration/UI/BanList/BanListIdsPopup.xaml.cs b/Content.Client/Administration/UI/BanList/BanListIdsPopup.xaml.cs new file mode 100644 index 0000000000..6fb2257e97 --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListIdsPopup.xaml.cs @@ -0,0 +1,20 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.Administration.UI.BanList; + +[GenerateTypedNameReferences] +public sealed partial class BanListIdsPopup : Popup +{ + public BanListIdsPopup(string? ip, string? hwid, string? guid) + { + RobustXamlLoader.Load(this); + + IP.Text = ip; + HWId.Text = hwid; + GUID.Text = guid; + + UserInterfaceManager.ModalRoot.AddChild(this); + } +} diff --git a/Content.Client/Administration/UI/BanList/BanListLine.xaml b/Content.Client/Administration/UI/BanList/BanListLine.xaml new file mode 100644 index 0000000000..8d324f12b6 --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListLine.xaml @@ -0,0 +1,38 @@ + + + + + diff --git a/Content.Client/Administration/UI/BanList/BanListLine.xaml.cs b/Content.Client/Administration/UI/BanList/BanListLine.xaml.cs new file mode 100644 index 0000000000..90503fda22 --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListLine.xaml.cs @@ -0,0 +1,70 @@ +using Content.Shared.Administration.BanList; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Input; + +namespace Content.Client.Administration.UI.BanList; + +[GenerateTypedNameReferences] +public sealed partial class BanListLine : BoxContainer +{ + public readonly SharedServerBan Ban; + + public event Func? OnIdsClicked; + + public BanListLine(SharedServerBan ban) + { + RobustXamlLoader.Load(this); + + Ban = ban; + + IdsHidden.OnKeyBindDown += IdsKeyBindDown; + + Reason.Text = ban.Reason; + BanTime.Text = FormatDate(ban.BanTime); + Expires.Text = ban.ExpirationTime == null + ? Loc.GetString("ban-list-permanent") + : FormatDate(ban.ExpirationTime.Value); + + if (ban.Unban is { } unban) + { + var unbanned = Loc.GetString("ban-list-unbanned", ("date", FormatDate(unban.UnbanTime))); + var unbannedBy = unban.UnbanningAdmin == null + ? string.Empty + : $"\n{Loc.GetString("ban-list-unbanned-by", ("unbanner", unban.UnbanningAdmin))}"; + + Expires.Text += $"\n{unbanned}{unbannedBy}"; + } + + BanningAdmin.Text = ban.BanningAdminName; + } + + private static string FormatDate(DateTimeOffset date) + { + return date.ToString("MM/dd/yyyy h:mm tt"); + } + + private void IdsKeyBindDown(GUIBoundKeyEventArgs args) + { + if (args.Function != EngineKeyFunctions.UIRightClick && + args.Function != EngineKeyFunctions.UIClick) + { + return; + } + + if (OnIdsClicked?.Invoke(this) == true) + { + args.Handle(); + } + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + IdsHidden.OnKeyBindDown -= IdsKeyBindDown; + OnIdsClicked = null; + } +} diff --git a/Content.Client/Administration/UI/BanList/BanListWindow.xaml b/Content.Client/Administration/UI/BanList/BanListWindow.xaml new file mode 100644 index 0000000000..d246a3e3a2 --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListWindow.xaml @@ -0,0 +1,6 @@ + + + diff --git a/Content.Client/Administration/UI/BanList/BanListWindow.xaml.cs b/Content.Client/Administration/UI/BanList/BanListWindow.xaml.cs new file mode 100644 index 0000000000..2bb08a8825 --- /dev/null +++ b/Content.Client/Administration/UI/BanList/BanListWindow.xaml.cs @@ -0,0 +1,19 @@ +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.CustomControls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.Administration.UI.BanList; + +[GenerateTypedNameReferences] +public sealed partial class BanListWindow : DefaultWindow +{ + public BanListWindow() + { + RobustXamlLoader.Load(this); + } + + public void SetTitlePlayer(string playerName) + { + Title = Loc.GetString("ban-list-title", ("player", playerName)); + } +} diff --git a/Content.Client/Administration/UI/BwoinkWindow.xaml b/Content.Client/Administration/UI/BwoinkWindow.xaml index ead47e6905..5b40e57513 100644 --- a/Content.Client/Administration/UI/BwoinkWindow.xaml +++ b/Content.Client/Administration/UI/BwoinkWindow.xaml @@ -10,6 +10,7 @@ +