Skip to content

Add user card with global/country ranks to login overlay #26340

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jan 17, 2024
43 changes: 41 additions & 2 deletions osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Osu;
using osu.Game.Scoring;
Expand All @@ -29,6 +31,9 @@ public partial class TestSceneUserPanel : OsuTestScene
private UserGridPanel boundPanel1;
private TestUserListPanel boundPanel2;

[Cached]
private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple);

[Resolved]
private IRulesetStore rulesetStore { get; set; }

Expand Down Expand Up @@ -85,8 +90,25 @@ public void SetUp() => Schedule(() =>
CoverUrl = @"https://assets.ppy.sh/user-profile-covers/8195163/4a8e2ad5a02a2642b631438cfa6c6bd7e2f9db289be881cb27df18331f64144c.jpeg",
IsOnline = false,
LastVisit = DateTimeOffset.Now
})
},
}),
new UserRankPanel(new APIUser
{
Username = @"flyte",
Id = 3103765,
CountryCode = CountryCode.JP,
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c6.jpg",
Statistics = new UserStatistics { GlobalRank = 12345, CountryRank = 1234 }
}) { Width = 300 },
new UserRankPanel(new APIUser
{
Username = @"peppy",
Id = 2,
Colour = "99EB47",
CountryCode = CountryCode.AU,
CoverUrl = @"https://osu.ppy.sh/images/headers/profile-covers/c3.jpg",
Statistics = new UserStatistics { GlobalRank = null, CountryRank = null }
}) { Width = 300 }
}
};

boundPanel1.Status.BindTo(status);
Expand Down Expand Up @@ -136,6 +158,23 @@ public void TestUserActivityChange()
AddAssert("visit message is not visible", () => !boundPanel2.LastVisitMessage.IsPresent);
}

[Test]
public void TestUserStatisticsChange()
{
AddStep("update statistics", () =>
{
API.UpdateStatistics(new UserStatistics
{
GlobalRank = RNG.Next(100000),
CountryRank = RNG.Next(100000)
});
});
AddStep("set statistics to empty", () =>
{
API.UpdateStatistics(new UserStatistics());
});
}

private UserActivity soloGameStatusForRuleset(int rulesetId) => new UserActivity.InSoloGame(new BeatmapInfo(), rulesetStore.GetRuleset(rulesetId)!);

private ScoreInfo createScore(string name) => new ScoreInfo(new TestBeatmap(Ruleset.Value).BeatmapInfo)
Expand Down
14 changes: 6 additions & 8 deletions osu.Game/Overlays/Login/LoginPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ public partial class LoginPanel : Container
[Resolved]
private OsuColour colours { get; set; } = null!;

private UserGridPanel panel = null!;
private UserDropdown dropdown = null!;

/// <summary>
Expand All @@ -39,6 +38,7 @@ public partial class LoginPanel : Container
public Action? RequestHide;

private readonly IBindable<APIState> apiState = new Bindable<APIState>();
private readonly Bindable<UserStatus?> userStatus = new Bindable<UserStatus?>();

[Resolved]
private IAPIProvider api { get; set; } = null!;
Expand Down Expand Up @@ -131,7 +131,7 @@ private void onlineStateChanged(ValueChangedEvent<APIState> state) => Schedule((
Text = LoginPanelStrings.SignedIn,
Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold),
},
panel = new UserGridPanel(api.LocalUser.Value)
new UserRankPanel(api.LocalUser.Value)
{
RelativeSizeAxes = Axes.X,
Action = RequestHide
Expand All @@ -140,10 +140,8 @@ private void onlineStateChanged(ValueChangedEvent<APIState> state) => Schedule((
},
};

panel.Status.BindTo(api.LocalUser.Value.Status);
panel.Activity.BindTo(api.LocalUser.Value.Activity);

panel.Status.BindValueChanged(_ => updateDropdownCurrent(), true);
userStatus.BindTo(api.LocalUser.Value.Status);
userStatus.BindValueChanged(e => updateDropdownCurrent(e.NewValue), true);

dropdown.Current.BindValueChanged(action =>
{
Expand Down Expand Up @@ -176,9 +174,9 @@ private void onlineStateChanged(ValueChangedEvent<APIState> state) => Schedule((
ScheduleAfterChildren(() => GetContainingInputManager()?.ChangeFocus(form));
});

private void updateDropdownCurrent()
private void updateDropdownCurrent(UserStatus? status)
{
switch (panel.Status.Value)
switch (status)
{
case UserStatus.Online:
dropdown.Current.Value = UserAction.Online;
Expand Down
9 changes: 0 additions & 9 deletions osu.Game/Users/ExtendedUserPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#nullable disable

using osuTK;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Extensions;
Expand Down Expand Up @@ -53,14 +52,6 @@ protected override void LoadComplete()
statusIcon.FinishTransforms();
}

protected UpdateableAvatar CreateAvatar() => new UpdateableAvatar(User, false);

protected UpdateableFlag CreateFlag() => new UpdateableFlag(User.CountryCode)
{
Size = new Vector2(36, 26),
Action = Action,
};

protected Container CreateStatusIcon() => statusIcon = new StatusIcon();

protected FillFlowContainer CreateStatusMessage(bool rightAlignedChildren)
Expand Down
2 changes: 2 additions & 0 deletions osu.Game/Users/UserGridPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ protected override Drawable CreateLayout()
Children = new Drawable[]
{
CreateFlag(),
// supporter icon is being added later
}
}
},
Expand All @@ -108,6 +109,7 @@ protected override Drawable CreateLayout()
},
new[]
{
// padding
Empty(),
Empty()
},
Expand Down
44 changes: 30 additions & 14 deletions osu.Game/Users/UserPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
using osu.Game.Online.Multiplayer;
using osu.Game.Screens;
using osu.Game.Screens.Play;
using osu.Game.Users.Drawables;
using osuTK;

namespace osu.Game.Users
{
Expand Down Expand Up @@ -77,23 +79,18 @@ private void load()
{
Masking = true;

AddRange(new[]
Add(new Box
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = ColourProvider?.Background5 ?? Colours.Gray1
},
Background = new UserCoverBackground
{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
User = User,
},
CreateLayout()
RelativeSizeAxes = Axes.Both,
Colour = ColourProvider?.Background5 ?? Colours.Gray1
});

var background = CreateBackground();
if (background != null)
Add(background);

Add(CreateLayout());

base.Action = ViewProfile = () =>
{
Action?.Invoke();
Expand All @@ -103,13 +100,32 @@ private void load()

protected abstract Drawable CreateLayout();

/// <summary>
/// Panel background container. Can be null if a panel doesn't want a background under it's layout
/// </summary>
protected virtual Drawable? CreateBackground() => Background = new UserCoverBackground
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so weird. So there's one method called CreateX and it's virtual and requires override to do something, then there's three other Create methods which are required to be called by the implementation to actually do something.

At very least this needs xmldoc. Optimally, they shouldn't use the same naming structure.

{
RelativeSizeAxes = Axes.Both,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
User = User
};

protected OsuSpriteText CreateUsername() => new OsuSpriteText
{
Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold),
Shadow = false,
Text = User.Username,
};

protected UpdateableAvatar CreateAvatar() => new UpdateableAvatar(User, false);

protected UpdateableFlag CreateFlag() => new UpdateableFlag(User.CountryCode)
{
Size = new Vector2(36, 26),
Action = Action,
};

public MenuItem[] ContextMenuItems
{
get
Expand Down
Loading