Fix recent participants hidden user logic not handling edge case correctly

Hiding just one user never makes sense, so this will now always show up
to the required circle count until two users are required to be hidden.
This will make the listing more consistent with the width requirement
spec.
This commit is contained in:
Dean Herbert 2021-08-12 18:10:06 +09:00
parent 127fd4d292
commit 8a67304b9f
3 changed files with 71 additions and 27 deletions

View File

@ -31,12 +31,36 @@ namespace osu.Game.Tests.Visual.Multiplayer
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
NumberOfAvatars = 3
NumberOfCircles = 3
};
});
[Test]
public void TestAvatarCount()
public void TestCircleCountNearLimit()
{
AddStep("add 8 users", () =>
{
for (int i = 0; i < 8; i++)
addUser(i);
});
AddStep("set 8 circles", () => list.NumberOfCircles = 8);
AddAssert("0 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 0);
AddStep("add one more user", () => addUser(9));
AddAssert("2 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 2);
AddStep("remove first user", () => removeUserAt(0));
AddAssert("0 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 0);
AddStep("add one more user", () => addUser(9));
AddAssert("2 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 2);
AddStep("remove last user", () => removeUserAt(8));
AddAssert("0 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 0);
}
[Test]
public void TestCircleCount()
{
AddStep("add 50 users", () =>
{
@ -44,12 +68,12 @@ namespace osu.Game.Tests.Visual.Multiplayer
addUser(i);
});
AddStep("set 3 avatars", () => list.NumberOfAvatars = 3);
AddAssert("3 avatars displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 3);
AddStep("set 3 circles", () => list.NumberOfCircles = 3);
AddAssert("3 circles displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 3);
AddAssert("47 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 47);
AddStep("set 10 avatars", () => list.NumberOfAvatars = 10);
AddAssert("10 avatars displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 10);
AddStep("set 10 circles", () => list.NumberOfCircles = 10);
AddAssert("10 circles displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 10);
AddAssert("40 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 40);
}
@ -63,24 +87,24 @@ namespace osu.Game.Tests.Visual.Multiplayer
});
AddStep("remove from start", () => removeUserAt(0));
AddAssert("3 avatars displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 3);
AddAssert("3 circles displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 3);
AddAssert("46 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 46);
AddStep("remove from end", () => removeUserAt(SelectedRoom.Value.RecentParticipants.Count - 1));
AddAssert("3 avatars displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 3);
AddAssert("3 circles displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 3);
AddAssert("45 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 45);
AddRepeatStep("remove 45 users", () => removeUserAt(0), 45);
AddAssert("3 avatars displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 3);
AddAssert("3 circles displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 3);
AddAssert("0 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 0);
AddAssert("hidden users bubble hidden", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Alpha < 0.5f);
AddStep("remove another user", () => removeUserAt(0));
AddAssert("2 avatars displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 2);
AddAssert("2 circles displayed", () => list.ChildrenOfType<UpdateableAvatar>().Count() == 2);
AddAssert("0 hidden users", () => list.ChildrenOfType<RecentParticipantsList.HiddenUserCount>().Single().Count == 0);
AddRepeatStep("remove the remaining two users", () => removeUserAt(0), 2);
AddAssert("0 avatars displayed", () => !list.ChildrenOfType<UpdateableAvatar>().Any());
AddAssert("0 circles displayed", () => !list.ChildrenOfType<UpdateableAvatar>().Any());
}
private void addUser(int id)

View File

@ -120,7 +120,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
numberOfAvatars = value;
if (recentParticipantsList != null)
recentParticipantsList.NumberOfAvatars = value;
recentParticipantsList.NumberOfCircles = value;
}
}
@ -315,7 +315,7 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
NumberOfAvatars = NumberOfAvatars
NumberOfCircles = NumberOfAvatars
}
}
},

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
@ -21,6 +22,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
{
private const float avatar_size = 36;
private bool canDisplayMoreUsers = true;
private FillFlowContainer<CircularAvatar> avatarFlow;
private HiddenUserCount hiddenUsers;
@ -91,14 +94,17 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
ParticipantCount.BindValueChanged(_ => updateHiddenUserCount(), true);
}
private int numberOfAvatars = 3;
private int numberOfCircles = 3;
public int NumberOfAvatars
/// <summary>
/// The maximum number of circles visible (including the "hidden count" circle in the overflow case).
/// </summary>
public int NumberOfCircles
{
get => numberOfAvatars;
get => numberOfCircles;
set
{
numberOfAvatars = value;
numberOfCircles = value;
if (LoadState < LoadState.Loaded)
return;
@ -107,6 +113,8 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
clearUsers();
foreach (var u in RecentParticipants)
addUser(u);
updateHiddenUserCount();
}
}
@ -136,34 +144,46 @@ namespace osu.Game.Screens.OnlinePlay.Lounge.Components
addUser(u);
break;
}
updateHiddenUserCount();
}
private void addUser(User user)
{
if (avatarFlow.Count < NumberOfAvatars)
avatarFlow.Add(new CircularAvatar { User = user });
if (!canDisplayMoreUsers)
return;
updateHiddenUserCount();
if (avatarFlow.Count < NumberOfCircles)
avatarFlow.Add(new CircularAvatar { User = user });
else if (avatarFlow.Count == NumberOfCircles)
avatarFlow.Remove(avatarFlow.Last());
}
private void removeUser(User user)
{
if (avatarFlow.RemoveAll(a => a.User == user) > 0)
{
if (RecentParticipants.Count >= NumberOfAvatars)
avatarFlow.Add(new CircularAvatar { User = RecentParticipants.First(u => avatarFlow.All(a => a.User != u)) });
}
var nextUser = RecentParticipants.FirstOrDefault(u => avatarFlow.All(a => a.User != u));
if (nextUser == null)
return;
updateHiddenUserCount();
if (canDisplayMoreUsers || NumberOfCircles == RecentParticipants.Count)
avatarFlow.Add(new CircularAvatar { User = nextUser });
}
private void clearUsers()
{
canDisplayMoreUsers = true;
avatarFlow.Clear();
updateHiddenUserCount();
}
private void updateHiddenUserCount() => hiddenUsers.Count = ParticipantCount.Value - avatarFlow.Count;
private void updateHiddenUserCount()
{
int count = ParticipantCount.Value - avatarFlow.Count;
Debug.Assert(count != 1);
hiddenUsers.Count = count;
}
private class CircularAvatar : CompositeDrawable
{