diff --git a/Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs b/Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs index b259e08e723c..21aa54c9622f 100644 --- a/Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs +++ b/Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs @@ -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; @@ -36,7 +38,6 @@ public sealed partial class CriminalRecordsConsoleWindow : FancyWindow public Action? OnDialogConfirmed; private uint _maxLength; - private bool _isPopulating; private bool _access; private uint? _selectedKey; private CriminalRecord? _selectedRecord; @@ -74,7 +75,7 @@ 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); @@ -82,8 +83,7 @@ public CriminalRecordsConsoleWindow(EntityUid console, uint maxLength, IPlayerMa RecordListing.OnItemDeselected += _ => { - if (!_isPopulating) - OnKeySelected?.Invoke(null); + OnKeySelected?.Invoke(null); }; FilterType.OnItemSelected += eventArgs => @@ -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; @@ -167,19 +162,59 @@ public void UpdateState(CriminalRecordsConsoleState state) } } - private void PopulateRecordListing(Dictionary listing) + private void PopulateRecordListing(Dictionary? 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) @@ -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)