Skip to content

Commit

Permalink
Ability to copy admin logs (#74)
Browse files Browse the repository at this point in the history
  • Loading branch information
InsaneCake authored Jul 2, 2023
1 parent d3dbbc4 commit 237bd52
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 46 deletions.
4 changes: 2 additions & 2 deletions Content.Client/Administration/UI/Logs/AdminLogsControl.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@
<Button Name="RefreshButton" Access="Public" Text="{Loc admin-logs-refresh}" StyleClasses="ButtonSquare"/>
<Button Name="NextButton" Access="Public" Text="{Loc admin-logs-next}" StyleClasses="OpenLeft"/>
</BoxContainer>
<ScrollContainer VerticalExpand="True" HorizontalExpand="True" HScrollEnabled="False">
<BoxContainer Name="LogsContainer" Access="Public" Orientation="Vertical" VerticalExpand="True"/>
<ScrollContainer Name="AdminLogsScrollContainer" Access="Public" VerticalExpand="True" HorizontalExpand="True" HScrollEnabled="False">
<TextEdit Name="AdminLogsTextEdit" Access="Public" VerticalExpand="True"/>
</ScrollContainer>
</BoxContainer>
</BoxContainer>
Expand Down
110 changes: 66 additions & 44 deletions Content.Client/Administration/UI/Logs/AdminLogsControl.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using System.Linq;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Content.Client.Administration.UI.CustomControls;
using Content.Shared.Administration.Logs;
using Content.Shared.Database;
Expand All @@ -15,13 +15,20 @@ namespace Content.Client.Administration.UI.Logs;
[GenerateTypedNameReferences]
public sealed partial class AdminLogsControl : Control
{
/// <summary>
/// <para>List of used tags can be found here: Robust.Client/UserInterface/RichText/MarkupTagManager.cs</para>
/// <para>Pattern test online: https://regex101.com/r/3krK2I/2</para>
/// </summary>
private const string BBCodeRegexPattern = "((\\[|\\[/)(color|cmdlink|font|bold|italic)=?\\w*\\])";
private readonly Comparer<AdminLogTypeButton> _adminLogTypeButtonComparer =
Comparer<AdminLogTypeButton>.Create((a, b) =>
string.Compare(a.Type.ToString(), b.Type.ToString(), StringComparison.Ordinal));
Comparer<AdminLogTypeButton>.Create(
(a, b) => string.Compare(a.Type.ToString(), b.Type.ToString(), StringComparison.Ordinal)
);

private readonly Comparer<AdminLogPlayerButton> _adminLogPlayerButtonComparer =
Comparer<AdminLogPlayerButton>.Create((a, b) =>
string.Compare(a.Text, b.Text, StringComparison.Ordinal));
Comparer<AdminLogPlayerButton>.Create(
(a, b) => string.Compare(a.Text, b.Text, StringComparison.Ordinal)
);

public AdminLogsControl()
{
Expand All @@ -44,6 +51,8 @@ public AdminLogsControl()

ResetRoundButton.OnPressed += ResetRoundPressed;

RecievedLogs = new List<SharedAdminLog>();

SetImpacts(Enum.GetValues<LogImpact>().OrderBy(impact => impact).ToArray());
SetTypes(Enum.GetValues<LogType>());
}
Expand All @@ -55,6 +64,12 @@ public AdminLogsControl()
private int ShownLogs { get; set; }
private int TotalLogs { get; set; }
private int RoundLogs { get; set; }

/// <summary>
/// Storage of recieved logs
/// </summary>
private List<SharedAdminLog> RecievedLogs { get; set; }

public bool IncludeNonPlayerLogs { get; set; }

public HashSet<LogType> SelectedTypes { get; } = new();
Expand Down Expand Up @@ -239,22 +254,47 @@ private void UpdatePlayers()
private void UpdateLogs()
{
ShownLogs = 0;
var logsText = "";

foreach (var child in LogsContainer.Children)
// build logs string
for (var i = RecievedLogs.Count - 1; i >= 0; i--)
{
if (child is not AdminLogLabel log)
var log = RecievedLogs[i];
if (ShouldShowLog(log))
{
continue;
ShownLogs++;
logsText += string.Format(
"{0:HH:mm:ss} - {1}\n{2}\n\n",
log.Date,
log.Type,
log.Message
);
}

child.Visible = ShouldShowLog(log);
if (child.Visible)
}
// set new text in TextEdit and clear BB tags only in result log string to
// preserve original log messages for posible future use
AdminLogsTextEdit.TextRope = new Robust.Shared.Utility.Rope.Leaf(
Regex.Replace(logsText, BBCodeRegexPattern, "")
);
UpdateCount(ShownLogs, RecievedLogs.Count);
ScrollLogsToBottom();
}

/// <summary>
/// Try to scroll AdminLogsTextEdit to the end
/// </summary>
private void ScrollLogsToBottom()
{
// find scrollbar in TextEdit's children
// it must be at index 1, but may be changed in future
for (var i = 0; i < AdminLogsTextEdit.ChildCount; i++)
{
if (AdminLogsTextEdit.GetChild(i) is VScrollBar scrollbar)
{
ShownLogs++;
scrollbar.ValueTarget = float.PositiveInfinity;
break;
}
}

UpdateCount();
}

private bool ShouldShowType(AdminLogTypeButton button)
Expand All @@ -269,30 +309,30 @@ private bool ShouldShowPlayer(AdminLogPlayerButton button)
button.Text.Contains(PlayerSearch.Text, StringComparison.OrdinalIgnoreCase);
}

private bool LogMatchesPlayerFilter(AdminLogLabel label)
private bool LogMatchesPlayerFilter(SharedAdminLog log)
{
if (label.Log.Players.Length == 0)
if (log.Players.Length == 0)
return SelectedPlayers.Count == 0 || IncludeNonPlayerLogs;

return SelectedPlayers.Overlaps(label.Log.Players);
return SelectedPlayers.Overlaps(log.Players);
}

private bool ShouldShowLog(AdminLogLabel label)
private bool ShouldShowLog(SharedAdminLog log)
{
// Check log type
if (!SelectedTypes.Contains(label.Log.Type))
if (!SelectedTypes.Contains(log.Type))
return false;

// Check players
if (!LogMatchesPlayerFilter(label))
if (!LogMatchesPlayerFilter(log))
return false;

// Check impact
if (!SelectedImpacts.Contains(label.Log.Impact))
if (!SelectedImpacts.Contains(log.Impact))
return false;

// Check search
if (!label.Log.Message.Contains(LogSearch.Text, StringComparison.OrdinalIgnoreCase))
if (!log.Message.Contains(LogSearch.Text, StringComparison.OrdinalIgnoreCase))
return false;

return true;
Expand Down Expand Up @@ -458,32 +498,14 @@ public void SetPlayers(Dictionary<Guid, string> players)

public void AddLogs(List<SharedAdminLog> logs)
{
var span = CollectionsMarshal.AsSpan(logs);
for (var i = 0; i < span.Length; i++)
{
ref var log = ref span[i];
var separator = new HSeparator();
var label = new AdminLogLabel(ref log, separator);
label.Visible = ShouldShowLog(label);

TotalLogs++;
if (label.Visible)
{
ShownLogs++;
}

LogsContainer.AddChild(label);
LogsContainer.AddChild(separator);
}

UpdateCount();
RecievedLogs.AddRange(logs);
UpdateLogs();
}

public void SetLogs(List<SharedAdminLog> logs)
{
LogsContainer.RemoveAllChildren();
UpdateCount(0, 0);
AddLogs(logs);
RecievedLogs = logs;
UpdateLogs();
}

public void UpdateCount(int? shown = null, int? total = null, int? round = null)
Expand Down

0 comments on commit 237bd52

Please sign in to comment.