diff --git a/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapLeaderboardWedge.cs b/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapLeaderboardWedge.cs index f03d83b5e8..61d23c4513 100644 --- a/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapLeaderboardWedge.cs +++ b/osu.Game.Tests/Visual/SongSelectV2/TestSceneBeatmapLeaderboardWedge.cs @@ -137,6 +137,7 @@ namespace osu.Game.Tests.Visual.SongSelectV2 { AddStep("ensure no scores displayed", () => leaderboard.SetScores(Array.Empty())); + AddStep(@"Retrieving", () => leaderboard.SetState(LeaderboardState.Retrieving)); AddStep(@"Network failure", () => leaderboard.SetState(LeaderboardState.NetworkFailure)); AddStep(@"No team", () => leaderboard.SetState(LeaderboardState.NoTeam)); AddStep(@"No supporter", () => leaderboard.SetState(LeaderboardState.NotSupporter)); diff --git a/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs b/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs index 774c1540c7..c6e110b282 100644 --- a/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs +++ b/osu.Game/Screens/SelectV2/BeatmapLeaderboardWedge.cs @@ -12,14 +12,12 @@ using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Game.Beatmaps; -using osu.Game.Extensions; using osu.Game.Graphics; using osu.Game.Graphics.Containers; using osu.Game.Graphics.Cursor; using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Localisation; -using osu.Game.Online.API; using osu.Game.Online.Leaderboards; using osu.Game.Online.Placeholders; using osu.Game.Overlays; @@ -54,21 +52,16 @@ namespace osu.Game.Screens.SelectV2 [Resolved] private IBindable> mods { get; set; } = null!; - [Resolved] - private IAPIProvider api { get; set; } = null!; - [Resolved] private OverlayColourProvider colourProvider { get; set; } = null!; public IBindable Scope { get; } = new Bindable(); - private bool isOnlineScope => Scope.Value != BeatmapLeaderboardScope.Local; - public IBindable FilterBySelectedMods { get; } = new BindableBool(); private CancellationTokenSource? cancellationTokenSource; - private readonly Bindable fetchedScores = new Bindable(); + private readonly IBindable fetchedScores = new Bindable(); [BackgroundDependencyLoader] private void load() @@ -147,7 +140,7 @@ namespace osu.Game.Screens.SelectV2 } }; - ((IBindable)fetchedScores).BindTo(leaderboardManager.Scores); + fetchedScores.BindTo(leaderboardManager.Scores); } protected override void LoadComplete() @@ -179,10 +172,11 @@ namespace osu.Game.Screens.SelectV2 refetchScores(); } + private bool initialFetchComplete; + private void refetchScores() { SetScores(Array.Empty(), null); - SetState(LeaderboardState.Retrieving); if (beatmap.IsDefault) { @@ -190,55 +184,35 @@ namespace osu.Game.Screens.SelectV2 return; } + SetState(LeaderboardState.Retrieving); + var fetchBeatmapInfo = beatmap.Value.BeatmapInfo; var fetchRuleset = ruleset.Value ?? fetchBeatmapInfo.Ruleset; - if (!api.IsLoggedIn && isOnlineScope) + // For now, we forcefully refresh to keep things simple. + // In the future, removing this requirement may be deemed useful, but will need ample testing of edge case scenarios + // (like returning from gameplay after setting a new score, returning to song select after main menu). + leaderboardManager.FetchWithCriteria(new LeaderboardCriteria(fetchBeatmapInfo, fetchRuleset, Scope.Value, FilterBySelectedMods.Value ? mods.Value.ToArray() : null), forceRefresh: true); + + if (!initialFetchComplete) { - SetState(LeaderboardState.NotLoggedIn); - return; + // only bind this after the first fetch to avoid reading stale scores. + fetchedScores.BindTo(leaderboardManager.Scores); + fetchedScores.BindValueChanged(_ => updateScores(), true); + initialFetchComplete = true; } + } - if (!fetchRuleset.IsLegacyRuleset()) - { - SetState(LeaderboardState.RulesetUnavailable); - return; - } + private void updateScores() + { + var scores = fetchedScores.Value; - if ((fetchBeatmapInfo.OnlineID <= 0 || fetchBeatmapInfo.Status <= BeatmapOnlineStatus.Pending) && isOnlineScope) - { - SetState(LeaderboardState.BeatmapUnavailable); - return; - } + if (scores == null) return; - if (Scope.Value.RequiresSupporter(FilterBySelectedMods.Value) && !api.LocalUser.Value.IsSupporter) - { - SetState(LeaderboardState.NotSupporter); - return; - } - - if (Scope.Value == BeatmapLeaderboardScope.Team && api.LocalUser.Value.Team == null) - { - SetState(LeaderboardState.NoTeam); - return; - } - - leaderboardManager.FetchWithCriteriaAsync(new LeaderboardCriteria(fetchBeatmapInfo, fetchRuleset, Scope.Value, FilterBySelectedMods.Value ? mods.Value.ToArray() : null)) - .ContinueWith(t => - { - if (t.Exception != null && !t.IsCanceled) - { - Schedule(() => SetState(LeaderboardState.NetworkFailure)); - return; - } - - fetchedScores.UnbindEvents(); - fetchedScores.BindValueChanged(scores => - { - if (scores.NewValue != null) - Schedule(() => SetScores(scores.NewValue.TopScores, scores.NewValue.UserScore)); - }, true); - }); + if (scores.FailState != null) + SetState((LeaderboardState)scores.FailState); + else + SetScores(scores.TopScores, scores.UserScore); } protected void SetScores(IEnumerable scores, ScoreInfo? userScore) @@ -349,6 +323,8 @@ namespace osu.Game.Screens.SelectV2 if (placeholder == null) return; + clearScores(); + placeholderContainer.Child = placeholder; placeholder.ScaleTo(0.8f).Then().ScaleTo(1, 900, Easing.OutQuint);