From 5eaf5fca2ad8d162835212151b8c1c530f7ca0f1 Mon Sep 17 00:00:00 2001 From: StanR Date: Tue, 2 Jan 2024 20:33:36 +0600 Subject: [PATCH 1/8] Add user card with global/country ranks for login overlay --- osu.Game/Overlays/Login/LoginPanel.cs | 7 +- osu.Game/Users/ExtendedUserPanel.cs | 9 -- osu.Game/Users/UserPanel.cs | 41 +++-- osu.Game/Users/UserRankPanel.cs | 212 ++++++++++++++++++++++++++ 4 files changed, 241 insertions(+), 28 deletions(-) create mode 100644 osu.Game/Users/UserRankPanel.cs diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 19af95459f..892d613ea4 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -30,7 +30,7 @@ namespace osu.Game.Overlays.Login [Resolved] private OsuColour colours { get; set; } = null!; - private UserGridPanel panel = null!; + private UserRankPanel panel = null!; private UserDropdown dropdown = null!; /// @@ -131,7 +131,7 @@ namespace osu.Game.Overlays.Login Text = LoginPanelStrings.SignedIn, Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), }, - panel = new UserGridPanel(api.LocalUser.Value) + panel = new UserRankPanel(api.LocalUser.Value) { RelativeSizeAxes = Axes.X, Action = RequestHide @@ -140,9 +140,6 @@ namespace osu.Game.Overlays.Login }, }; - panel.Status.BindTo(api.LocalUser.Value.Status); - panel.Activity.BindTo(api.LocalUser.Value.Activity); - dropdown.Current.BindValueChanged(action => { switch (action.NewValue) diff --git a/osu.Game/Users/ExtendedUserPanel.cs b/osu.Game/Users/ExtendedUserPanel.cs index 1359f5d792..e33fb7a44e 100644 --- a/osu.Game/Users/ExtendedUserPanel.cs +++ b/osu.Game/Users/ExtendedUserPanel.cs @@ -3,7 +3,6 @@ #nullable disable -using osuTK; using osu.Framework.Allocation; using osu.Framework.Bindables; using osu.Framework.Extensions; @@ -53,14 +52,6 @@ namespace osu.Game.Users 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) diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index b6a77e754d..d38f5d8ccc 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -23,6 +23,8 @@ using osu.Game.Localisation; 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 { @@ -77,23 +79,18 @@ namespace osu.Game.Users { 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(); @@ -110,6 +107,22 @@ namespace osu.Game.Users Text = User.Username, }; + protected virtual Drawable? CreateBackground() => Background = new UserCoverBackground + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + User = User + }; + + 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 diff --git a/osu.Game/Users/UserRankPanel.cs b/osu.Game/Users/UserRankPanel.cs new file mode 100644 index 0000000000..272d2eecb4 --- /dev/null +++ b/osu.Game/Users/UserRankPanel.cs @@ -0,0 +1,212 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Extensions.LocalisationExtensions; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Input.Events; +using osu.Framework.Localisation; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.Profile.Header.Components; +using osu.Game.Resources.Localisation.Web; +using osuTK; + +namespace osu.Game.Users +{ + /// + /// User card that shows user's global and country ranks in the bottom. + /// Meant to be used in the toolbar login overlay. + /// + public partial class UserRankPanel : UserPanel + { + private const int padding = 10; + private const int main_content_height = 80; + + public UserRankPanel(APIUser user) + : base(user) + { + AutoSizeAxes = Axes.Y; + CornerRadius = 10; + } + + [BackgroundDependencyLoader] + private void load() + { + BorderColour = ColourProvider?.Light1 ?? Colours.GreyVioletLighter; + } + + protected override Drawable CreateLayout() + { + FillFlowContainer details; + + var layout = new Container + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Children = new Drawable[] + { + new Container + { + Name = "Main content", + RelativeSizeAxes = Axes.X, + Height = main_content_height, + CornerRadius = 10, + Masking = true, + Children = new Drawable[] + { + new UserCoverBackground + { + RelativeSizeAxes = Axes.Both, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + User = User, + Alpha = 0.3f + }, + new GridContainer + { + AutoSizeAxes = Axes.Y, + RelativeSizeAxes = Axes.X, + ColumnDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, padding), + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + new Dimension(GridSizeMode.Absolute, padding), + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.Absolute, padding), + new Dimension(GridSizeMode.AutoSize), + }, + Content = new[] + { + new[] + { + Empty(), + Empty(), + Empty(), + Empty() + }, + new[] + { + Empty(), + CreateAvatar().With(avatar => + { + avatar.Size = new Vector2(60); + avatar.Masking = true; + avatar.CornerRadius = 6; + }), + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Left = padding }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.Both, + ColumnDimensions = new[] + { + new Dimension() + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, + Content = new[] + { + new Drawable[] + { + details = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(6), + Children = new Drawable[] + { + CreateFlag(), + } + } + }, + new Drawable[] + { + CreateUsername().With(username => + { + username.Anchor = Anchor.CentreLeft; + username.Origin = Anchor.CentreLeft; + }) + } + } + } + }, + Empty() + } + } + } + } + }, + new Container + { + Name = "Bottom content", + Margin = new MarginPadding { Top = main_content_height }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Left = 80, Vertical = padding }, + Child = new GridContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + ColumnDimensions = new[] + { + new Dimension(), + new Dimension() + }, + RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) }, + Content = new[] + { + new Drawable[] + { + new ProfileValueDisplay(true) + { + Title = UsersStrings.ShowRankGlobalSimple, + Content = User.Statistics?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-" + }, + new ProfileValueDisplay(true) + { + Title = UsersStrings.ShowRankCountrySimple, + Content = User.Statistics?.CountryRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-" + } + } + } + } + } + } + }; + + if (User.IsSupporter) + { + details.Add(new SupporterIcon + { + Height = 26, + SupportLevel = User.SupportLevel + }); + } + + return layout; + } + + protected override bool OnHover(HoverEvent e) + { + BorderThickness = 2; + return base.OnHover(e); + } + + protected override void OnHoverLost(HoverLostEvent e) + { + BorderThickness = 0; + base.OnHoverLost(e); + } + + protected override Drawable? CreateBackground() => null; + } +} From c4be6fa9741c5fdcf8c347bdec9bf5fe3641d3fb Mon Sep 17 00:00:00 2001 From: StanR Date: Wed, 3 Jan 2024 00:37:24 +0600 Subject: [PATCH 2/8] Fix code quality, add new cards to the test scene --- .../Visual/Online/TestSceneUserPanel.cs | 25 +++++++++++++++++-- osu.Game/Overlays/Login/LoginPanel.cs | 3 +-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index b3b8fd78d3..81e17cd1b8 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -11,6 +11,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; 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; @@ -29,6 +30,9 @@ namespace osu.Game.Tests.Visual.Online private UserGridPanel boundPanel1; private TestUserListPanel boundPanel2; + [Cached] + private OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Purple); + [Resolved] private IRulesetStore rulesetStore { get; set; } @@ -85,8 +89,25 @@ namespace osu.Game.Tests.Visual.Online 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); diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 892d613ea4..57a9f4035c 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -30,7 +30,6 @@ namespace osu.Game.Overlays.Login [Resolved] private OsuColour colours { get; set; } = null!; - private UserRankPanel panel = null!; private UserDropdown dropdown = null!; /// @@ -131,7 +130,7 @@ namespace osu.Game.Overlays.Login Text = LoginPanelStrings.SignedIn, Font = OsuFont.GetFont(size: 18, weight: FontWeight.Bold), }, - panel = new UserRankPanel(api.LocalUser.Value) + new UserRankPanel(api.LocalUser.Value) { RelativeSizeAxes = Axes.X, Action = RequestHide From 3df7430d2e278cbd3dacc173270053e6a415af07 Mon Sep 17 00:00:00 2001 From: StanR Date: Wed, 3 Jan 2024 14:32:32 +0600 Subject: [PATCH 3/8] Bind `UserRankPanel` values to `Statistics` bindable in `APIAccess` --- .../Visual/Online/TestSceneUserPanel.cs | 18 ++++++++++++++++++ osu.Game/Users/UserRankPanel.cs | 17 +++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs index 81e17cd1b8..4df34e6244 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneUserPanel.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; 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; @@ -157,6 +158,23 @@ namespace osu.Game.Tests.Visual.Online 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) diff --git a/osu.Game/Users/UserRankPanel.cs b/osu.Game/Users/UserRankPanel.cs index 272d2eecb4..74ff0a06dd 100644 --- a/osu.Game/Users/UserRankPanel.cs +++ b/osu.Game/Users/UserRankPanel.cs @@ -7,6 +7,7 @@ using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; using osu.Framework.Localisation; +using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Profile.Header.Components; using osu.Game.Resources.Localisation.Web; @@ -23,6 +24,12 @@ namespace osu.Game.Users private const int padding = 10; private const int main_content_height = 80; + [Resolved] + private IAPIProvider api { get; set; } = null!; + + private ProfileValueDisplay globalRankDisplay = null!; + private ProfileValueDisplay countryRankDisplay = null!; + public UserRankPanel(APIUser user) : base(user) { @@ -34,6 +41,12 @@ namespace osu.Game.Users private void load() { BorderColour = ColourProvider?.Light1 ?? Colours.GreyVioletLighter; + + api.Statistics.ValueChanged += e => + { + globalRankDisplay.Content = e.NewValue?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; + countryRankDisplay.Content = e.NewValue?.CountryRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; + }; } protected override Drawable CreateLayout() @@ -166,12 +179,12 @@ namespace osu.Game.Users { new Drawable[] { - new ProfileValueDisplay(true) + globalRankDisplay = new ProfileValueDisplay(true) { Title = UsersStrings.ShowRankGlobalSimple, Content = User.Statistics?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-" }, - new ProfileValueDisplay(true) + countryRankDisplay = new ProfileValueDisplay(true) { Title = UsersStrings.ShowRankCountrySimple, Content = User.Statistics?.CountryRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-" From 7262fef67f5c0abc51b78f8aa643c3b68d9bbbe3 Mon Sep 17 00:00:00 2001 From: StanR Date: Wed, 3 Jan 2024 17:39:48 +0600 Subject: [PATCH 4/8] Add comments --- osu.Game/Users/UserGridPanel.cs | 2 ++ osu.Game/Users/UserPanel.cs | 17 ++++++++++------- osu.Game/Users/UserRankPanel.cs | 6 ++++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/osu.Game/Users/UserGridPanel.cs b/osu.Game/Users/UserGridPanel.cs index aac2315b2f..fe3435c248 100644 --- a/osu.Game/Users/UserGridPanel.cs +++ b/osu.Game/Users/UserGridPanel.cs @@ -91,6 +91,7 @@ namespace osu.Game.Users Children = new Drawable[] { CreateFlag(), + // supporter icon is being added later } } }, @@ -108,6 +109,7 @@ namespace osu.Game.Users }, new[] { + // padding Empty(), Empty() }, diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index d38f5d8ccc..ef5c95c422 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -100,13 +100,9 @@ namespace osu.Game.Users protected abstract Drawable CreateLayout(); - protected OsuSpriteText CreateUsername() => new OsuSpriteText - { - Font = OsuFont.GetFont(size: 16, weight: FontWeight.Bold), - Shadow = false, - Text = User.Username, - }; - + /// + /// Panel background container. Can be null if a panel doesn't want a background under it's layout + /// protected virtual Drawable? CreateBackground() => Background = new UserCoverBackground { RelativeSizeAxes = Axes.Both, @@ -115,6 +111,13 @@ namespace osu.Game.Users 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) diff --git a/osu.Game/Users/UserRankPanel.cs b/osu.Game/Users/UserRankPanel.cs index 74ff0a06dd..a2e234cf82 100644 --- a/osu.Game/Users/UserRankPanel.cs +++ b/osu.Game/Users/UserRankPanel.cs @@ -96,6 +96,7 @@ namespace osu.Game.Users { new[] { + // padding Empty(), Empty(), Empty(), @@ -103,7 +104,7 @@ namespace osu.Game.Users }, new[] { - Empty(), + Empty(), // padding CreateAvatar().With(avatar => { avatar.Size = new Vector2(60); @@ -138,6 +139,7 @@ namespace osu.Game.Users Children = new Drawable[] { CreateFlag(), + // supporter icon is being added later } } }, @@ -152,7 +154,7 @@ namespace osu.Game.Users } } }, - Empty() + Empty() // padding } } } From e3989c854d39ec82d1ea27ada8f70a9dea159633 Mon Sep 17 00:00:00 2001 From: StanR Date: Mon, 15 Jan 2024 16:57:22 +0600 Subject: [PATCH 5/8] Change `LoginPanel` to use `LocalUser.Status` for the dropdown --- osu.Game/Overlays/Login/LoginPanel.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 513088ba0c..7db3644de6 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -139,7 +139,7 @@ namespace osu.Game.Overlays.Login }, }; - panel.Status.BindValueChanged(_ => updateDropdownCurrent(), true); + api.LocalUser.Value.Status.BindValueChanged(e => updateDropdownCurrent(e.NewValue), true); dropdown.Current.BindValueChanged(action => { @@ -172,9 +172,9 @@ namespace osu.Game.Overlays.Login 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; From fe06402951ada9980fe5c02308cab9423bacfa20 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 Jan 2024 16:50:48 +0900 Subject: [PATCH 6/8] Fix incorrect bindable usage --- osu.Game/Overlays/Login/LoginPanel.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/osu.Game/Overlays/Login/LoginPanel.cs b/osu.Game/Overlays/Login/LoginPanel.cs index 7db3644de6..ea65656eb1 100644 --- a/osu.Game/Overlays/Login/LoginPanel.cs +++ b/osu.Game/Overlays/Login/LoginPanel.cs @@ -38,6 +38,7 @@ namespace osu.Game.Overlays.Login public Action? RequestHide; private readonly IBindable apiState = new Bindable(); + private readonly Bindable userStatus = new Bindable(); [Resolved] private IAPIProvider api { get; set; } = null!; @@ -139,7 +140,8 @@ namespace osu.Game.Overlays.Login }, }; - api.LocalUser.Value.Status.BindValueChanged(e => updateDropdownCurrent(e.NewValue), true); + userStatus.BindTo(api.LocalUser.Value.Status); + userStatus.BindValueChanged(e => updateDropdownCurrent(e.NewValue), true); dropdown.Current.BindValueChanged(action => { From 66c7a29e794197478a597922bbc6c7028515b304 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 Jan 2024 16:57:22 +0900 Subject: [PATCH 7/8] Add comment about messy methods --- osu.Game/Users/UserPanel.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osu.Game/Users/UserPanel.cs b/osu.Game/Users/UserPanel.cs index ef5c95c422..b88619c8b7 100644 --- a/osu.Game/Users/UserPanel.cs +++ b/osu.Game/Users/UserPanel.cs @@ -98,6 +98,8 @@ namespace osu.Game.Users }; } + // TODO: this whole api is messy. half these Create methods are expected to by the implementation and half are implictly called. + protected abstract Drawable CreateLayout(); /// From 353df2f31227a71da752e40dbdcb650e288e889d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 17 Jan 2024 17:00:30 +0900 Subject: [PATCH 8/8] Fix one more incorrect bindable flow and simplify string setters --- osu.Game/Users/UserRankPanel.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/osu.Game/Users/UserRankPanel.cs b/osu.Game/Users/UserRankPanel.cs index a2e234cf82..a38962dfc7 100644 --- a/osu.Game/Users/UserRankPanel.cs +++ b/osu.Game/Users/UserRankPanel.cs @@ -2,11 +2,11 @@ // See the LICENCE file in the repository root for full licence text. using osu.Framework.Allocation; +using osu.Framework.Bindables; using osu.Framework.Extensions.LocalisationExtensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Containers; using osu.Framework.Input.Events; -using osu.Framework.Localisation; using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Profile.Header.Components; @@ -30,6 +30,8 @@ namespace osu.Game.Users private ProfileValueDisplay globalRankDisplay = null!; private ProfileValueDisplay countryRankDisplay = null!; + private readonly IBindable statistics = new Bindable(); + public UserRankPanel(APIUser user) : base(user) { @@ -42,11 +44,12 @@ namespace osu.Game.Users { BorderColour = ColourProvider?.Light1 ?? Colours.GreyVioletLighter; - api.Statistics.ValueChanged += e => + statistics.BindTo(api.Statistics); + statistics.BindValueChanged(stats => { - globalRankDisplay.Content = e.NewValue?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; - countryRankDisplay.Content = e.NewValue?.CountryRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-"; - }; + globalRankDisplay.Content = stats.NewValue?.GlobalRank?.ToLocalisableString("\\##,##0") ?? "-"; + countryRankDisplay.Content = stats.NewValue?.CountryRank?.ToLocalisableString("\\##,##0") ?? "-"; + }, true); } protected override Drawable CreateLayout() @@ -184,12 +187,10 @@ namespace osu.Game.Users globalRankDisplay = new ProfileValueDisplay(true) { Title = UsersStrings.ShowRankGlobalSimple, - Content = User.Statistics?.GlobalRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-" }, countryRankDisplay = new ProfileValueDisplay(true) { Title = UsersStrings.ShowRankCountrySimple, - Content = User.Statistics?.CountryRank?.ToLocalisableString("\\##,##0") ?? (LocalisableString)"-" } } }