]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Improve Criminal Records Computer usability (#30292)
authoreoineoineoin <github@eoinrul.es>
Fri, 9 Aug 2024 07:41:29 +0000 (08:41 +0100)
committerGitHub <noreply@github.com>
Fri, 9 Aug 2024 07:41:29 +0000 (17:41 +1000)
* 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>
Content.Client/CriminalRecords/CriminalRecordsConsoleWindow.xaml.cs

index b259e08e723cc7948948916bd4dba3ae153072e8..21aa54c9622f85929a2e584cef88ebf94b24aa1f 100644 (file)
@@ -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;
+        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 @@ 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)