Improve Criminal Records Computer usability (#30292)
* Avoid destroying and recreating record list on every update message * Add early-out on nullptr input * Remove sussy null suppress --------- Co-authored-by: Eoin Mcloughlin <helloworld@eoinrul.es> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
@@ -7,10 +7,12 @@ using Content.Shared.Security;
|
||||
using Content.Shared.StationRecords;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Client.CriminalRecords;
|
||||
|
||||
@@ -36,7 +38,6 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
|
||||
public Action<SecurityStatus, string>? OnDialogConfirmed;
|
||||
|
||||
private uint _maxLength;
|
||||
private bool _isPopulating;
|
||||
private bool _access;
|
||||
private uint? _selectedKey;
|
||||
private CriminalRecord? _selectedRecord;
|
||||
@@ -74,7 +75,7 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
|
||||
|
||||
RecordListing.OnItemSelected += args =>
|
||||
{
|
||||
if (_isPopulating || RecordListing[args.ItemIndex].Metadata is not uint cast)
|
||||
if (RecordListing[args.ItemIndex].Metadata is not uint cast)
|
||||
return;
|
||||
|
||||
OnKeySelected?.Invoke(cast);
|
||||
@@ -82,8 +83,7 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
|
||||
|
||||
RecordListing.OnItemDeselected += _ =>
|
||||
{
|
||||
if (!_isPopulating)
|
||||
OnKeySelected?.Invoke(null);
|
||||
OnKeySelected?.Invoke(null);
|
||||
};
|
||||
|
||||
FilterType.OnItemSelected += eventArgs =>
|
||||
@@ -133,13 +133,8 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
|
||||
|
||||
FilterType.SelectId((int)_currentFilterType);
|
||||
|
||||
// set up the records listing panel
|
||||
RecordListing.Clear();
|
||||
|
||||
var hasRecords = state.RecordListing != null && state.RecordListing.Count > 0;
|
||||
NoRecords.Visible = !hasRecords;
|
||||
if (hasRecords)
|
||||
PopulateRecordListing(state.RecordListing!);
|
||||
NoRecords.Visible = state.RecordListing == null || state.RecordListing.Count == 0;
|
||||
PopulateRecordListing(state.RecordListing);
|
||||
|
||||
// set up the selected person's record
|
||||
var selected = _selectedKey != null;
|
||||
@@ -167,19 +162,59 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateRecordListing(Dictionary<uint, string> listing)
|
||||
private void PopulateRecordListing(Dictionary<uint, string>? listing)
|
||||
{
|
||||
_isPopulating = true;
|
||||
|
||||
foreach (var (key, name) in listing)
|
||||
if (listing == null)
|
||||
{
|
||||
var item = RecordListing.AddItem(name);
|
||||
item.Metadata = key;
|
||||
item.Selected = key == _selectedKey;
|
||||
RecordListing.Clear();
|
||||
return;
|
||||
}
|
||||
_isPopulating = false;
|
||||
|
||||
RecordListing.SortItemsByText();
|
||||
var entries = listing.ToList();
|
||||
entries.Sort((a, b) => string.Compare(a.Value, b.Value, StringComparison.Ordinal));
|
||||
// `entries` now contains the definitive list of items which should be in
|
||||
// our list of records and is in the order we want to present those items.
|
||||
|
||||
// Walk through the existing items in RecordListing and in the updated listing
|
||||
// in parallel to synchronize the items in RecordListing with `entries`.
|
||||
int i = RecordListing.Count - 1;
|
||||
int j = entries.Count - 1;
|
||||
while(i >= 0 && j >= 0)
|
||||
{
|
||||
var strcmp = string.Compare(RecordListing[i].Text, entries[j].Value, StringComparison.Ordinal);
|
||||
if (strcmp == 0)
|
||||
{
|
||||
// This item exists in both RecordListing and `entries`. Nothing to do.
|
||||
i--;
|
||||
j--;
|
||||
}
|
||||
else if (strcmp > 0)
|
||||
{
|
||||
// Item exists in RecordListing, but not in `entries`. Remove it.
|
||||
RecordListing.RemoveAt(i);
|
||||
i--;
|
||||
}
|
||||
else if (strcmp < 0)
|
||||
{
|
||||
// A new entry which doesn't exist in RecordListing. Create it.
|
||||
RecordListing.Insert(i + 1, new ItemList.Item(RecordListing){Text = entries[j].Value, Metadata = entries[j].Key});
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
// Any remaining items in RecordListing don't exist in `entries`, so remove them
|
||||
while (i >= 0)
|
||||
{
|
||||
RecordListing.RemoveAt(i);
|
||||
i--;
|
||||
}
|
||||
|
||||
// And finally, any remaining items in `entries`, don't exist in RecordListing. Create them.
|
||||
while (j >= 0)
|
||||
{
|
||||
RecordListing.Insert(0, new ItemList.Item(RecordListing){Text = entries[j].Value, Metadata = entries[j].Key});
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateRecordContainer(GeneralStationRecord stationRecord, CriminalRecord criminalRecord)
|
||||
@@ -211,10 +246,7 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow
|
||||
|
||||
private void FilterListingOfRecords(string text = "")
|
||||
{
|
||||
if (!_isPopulating)
|
||||
{
|
||||
OnFiltersChanged?.Invoke(_currentFilterType, text);
|
||||
}
|
||||
OnFiltersChanged?.Invoke(_currentFilterType, text);
|
||||
}
|
||||
|
||||
private void SetStatus(SecurityStatus status)
|
||||
|
||||
Reference in New Issue
Block a user