Skip to content

Commit

Permalink
Improve Criminal Records Computer usability (#30292)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: metalgearsloth <[email protected]>
  • Loading branch information
3 people authored Aug 9, 2024
1 parent 0b2fa94 commit d0a2187
Showing 1 changed file with 55 additions and 23 deletions.
78 changes: 55 additions & 23 deletions Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
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;

Expand All @@ -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;
Expand Down Expand Up @@ -74,16 +75,15 @@ public CriminalRecordsConsoleWindow(EntityUid console, uint maxLength, IPlayerMa

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);
};

RecordListing.OnItemDeselected += _ =>
{
if (!_isPopulating)
OnKeySelected?.Invoke(null);
OnKeySelected?.Invoke(null);
};

FilterType.OnItemSelected += eventArgs =>
Expand Down Expand Up @@ -133,13 +133,8 @@ public void UpdateState(CriminalRecordsConsoleState state)

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;
Expand Down Expand Up @@ -167,19 +162,59 @@ public void UpdateState(CriminalRecordsConsoleState state)
}
}

private void PopulateRecordListing(Dictionary<uint, string> listing)
private void PopulateRecordListing(Dictionary<uint, string>? listing)
{
_isPopulating = true;
if (listing == null)
{
RecordListing.Clear();
return;
}

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--;
}
}

foreach (var (key, name) in listing)
// Any remaining items in RecordListing don't exist in `entries`, so remove them
while (i >= 0)
{
var item = RecordListing.AddItem(name);
item.Metadata = key;
item.Selected = key == _selectedKey;
RecordListing.RemoveAt(i);
i--;
}
_isPopulating = false;

RecordListing.SortItemsByText();
// 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)
Expand Down Expand Up @@ -211,10 +246,7 @@ private void AddStatusSelect(SecurityStatus status)

private void FilterListingOfRecords(string text = "")
{
if (!_isPopulating)
{
OnFiltersChanged?.Invoke(_currentFilterType, text);
}
OnFiltersChanged?.Invoke(_currentFilterType, text);
}

private void SetStatus(SecurityStatus status)
Expand Down

0 comments on commit d0a2187

Please sign in to comment.