Skip to content

Commit 6ac8e59

Browse files
authored
Merge pull request #35426 from bdach/collection-grouping-order
Fix song select collection group order not matching other collection lists when certain characters are used
2 parents ec6ffb3 + 6ded2e3 commit 6ac8e59

File tree

2 files changed

+18
-5
lines changed

2 files changed

+18
-5
lines changed

osu.Game/Screens/SelectV2/BeatmapCarousel.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,15 @@ protected override Task<IEnumerable<CarouselItem>> FilterAsync(bool clearExistin
809809
[Resolved]
810810
private RealmAccess realm { get; set; } = null!;
811811

812-
protected virtual List<BeatmapCollection> GetAllCollections() => realm.Run(r => r.All<BeatmapCollection>().AsEnumerable().Detach());
812+
/// <remarks>
813+
/// FOOTGUN WARNING: this being sorted on the realm side before detaching is IMPORTANT.
814+
/// realm supports sorting as an internal operation, and realm's implementation of string sorting does NOT match dotnet's
815+
/// with respect to treatment of punctuation characters like <c>-</c> or <c>_</c>, among others.
816+
/// All other places that show lists of collections also use the realm-side sorting implementation,
817+
/// because they use the sorting operation inside subscription queries for efficient drawable management,
818+
/// so this usage kind of has to follow suit.
819+
/// </remarks>
820+
protected virtual List<BeatmapCollection> GetAllCollections() => realm.Run(r => r.All<BeatmapCollection>().OrderBy(c => c.Name).AsEnumerable().Detach());
813821

814822
protected virtual Dictionary<Guid, ScoreRank> GetBeatmapInfoGuidToTopRankMapping(FilterCriteria criteria) => realm.Run(r =>
815823
{

osu.Game/Screens/SelectV2/BeatmapCarouselFilterGrouping.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,15 +398,20 @@ private IEnumerable<GroupDefinition> defineGroupBySource(string source)
398398
return new GroupDefinition(0, source).Yield();
399399
}
400400

401-
private IEnumerable<GroupDefinition> defineGroupByCollection(BeatmapInfo beatmap, IEnumerable<BeatmapCollection> collections)
401+
private IEnumerable<GroupDefinition> defineGroupByCollection(BeatmapInfo beatmap, List<BeatmapCollection> collections)
402402
{
403403
bool anyCollections = false;
404404

405-
foreach (var collection in collections)
405+
for (int i = 0; i < collections.Count; i++)
406406
{
407+
var collection = collections[i];
408+
407409
if (collection.BeatmapMD5Hashes.Contains(beatmap.MD5Hash))
408410
{
409-
yield return new GroupDefinition(0, collection.Name);
411+
// NOTE: the ordering of the incoming collection list is significant and needs to be preserved.
412+
// the fallback to ordering by name cannot be relied on.
413+
// see xmldoc of `BeatmapCarousel.GetAllCollections()`.
414+
yield return new GroupDefinition(i, collection.Name);
410415

411416
anyCollections = true;
412417
}
@@ -415,7 +420,7 @@ private IEnumerable<GroupDefinition> defineGroupByCollection(BeatmapInfo beatmap
415420
if (anyCollections)
416421
yield break;
417422

418-
yield return new GroupDefinition(1, "Not in collection");
423+
yield return new GroupDefinition(int.MaxValue, "Not in collection");
419424
}
420425

421426
private IEnumerable<GroupDefinition> defineGroupByOwnMaps(BeatmapInfo beatmap, int? localUserId, string? localUserUsername)

0 commit comments

Comments
 (0)