diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index f91339e060..48230ff9e9 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -116,11 +116,11 @@ namespace osu.Game.Tests.Visual.SongSelect { AddStep("ensure no scores displayed", () => leaderboard.SetScores(null)); - AddStep(@"Network failure", () => leaderboard.SetErrorState(LeaderboardErrorState.NetworkFailure)); - AddStep(@"No supporter", () => leaderboard.SetErrorState(LeaderboardErrorState.NotSupporter)); - AddStep(@"Not logged in", () => leaderboard.SetErrorState(LeaderboardErrorState.NotLoggedIn)); - AddStep(@"Unavailable", () => leaderboard.SetErrorState(LeaderboardErrorState.Unavailable)); - AddStep(@"None selected", () => leaderboard.SetErrorState(LeaderboardErrorState.NoneSelected)); + AddStep(@"Network failure", () => leaderboard.SetErrorState(LeaderboardState.NetworkFailure)); + AddStep(@"No supporter", () => leaderboard.SetErrorState(LeaderboardState.NotSupporter)); + AddStep(@"Not logged in", () => leaderboard.SetErrorState(LeaderboardState.NotLoggedIn)); + AddStep(@"Unavailable", () => leaderboard.SetErrorState(LeaderboardState.Unavailable)); + AddStep(@"None selected", () => leaderboard.SetErrorState(LeaderboardState.NoneSelected)); } private void showPersonalBestWithNullPosition() @@ -404,7 +404,7 @@ namespace osu.Game.Tests.Visual.SongSelect private class FailableLeaderboard : BeatmapLeaderboard { - public new void SetErrorState(LeaderboardErrorState errorState) => base.SetErrorState(errorState); + public new void SetErrorState(LeaderboardState state) => base.SetErrorState(state); public new void SetScores(IEnumerable scores, ScoreInfo userScore = default) => base.SetScores(scores, userScore); } } diff --git a/osu.Game/Online/Leaderboards/Leaderboard.cs b/osu.Game/Online/Leaderboards/Leaderboard.cs index e96b12bc5d..7ac05fb0c0 100644 --- a/osu.Game/Online/Leaderboards/Leaderboard.cs +++ b/osu.Game/Online/Leaderboards/Leaderboard.cs @@ -58,7 +58,7 @@ namespace osu.Game.Online.Leaderboards private APIRequest fetchScoresRequest; - private LeaderboardErrorState errorState; + private LeaderboardState state; [Resolved(CanBeNull = true)] private IAPIProvider api { get; set; } @@ -160,19 +160,20 @@ namespace osu.Game.Online.Leaderboards /// /// Call when a retrieval or display failure happened to show a relevant message to the user. /// - /// The state to display. - protected void SetErrorState(LeaderboardErrorState errorState) + /// The state to display. + protected void SetErrorState(LeaderboardState state) { - switch (errorState) + switch (state) { - case LeaderboardErrorState.NoScores: - case LeaderboardErrorState.NoError: - throw new InvalidOperationException($"State {errorState} cannot be set by a leaderboard implementation."); + case LeaderboardState.NoScores: + case LeaderboardState.Retrieving: + case LeaderboardState.Success: + throw new InvalidOperationException($"State {state} cannot be set by a leaderboard implementation."); } Debug.Assert(scores?.Any() != true); - setErrorState(errorState); + setState(state); } /// @@ -212,8 +213,7 @@ namespace osu.Game.Online.Leaderboards cancelPendingWork(); SetScores(null); - setErrorState(LeaderboardErrorState.NoError); - loading.Show(); + setState(LeaderboardState.Retrieving); currentFetchCancellationSource = new CancellationTokenSource(); @@ -227,7 +227,7 @@ namespace osu.Game.Online.Leaderboards if (e is OperationCanceledException || currentFetchCancellationSource.IsCancellationRequested) return; - SetErrorState(LeaderboardErrorState.NetworkFailure); + SetErrorState(LeaderboardState.NetworkFailure); }); api?.Queue(fetchScoresRequest); @@ -251,15 +251,10 @@ namespace osu.Game.Online.Leaderboards if (scores?.Any() != true) { - setErrorState(LeaderboardErrorState.NoScores); - loading.Hide(); + setState(LeaderboardState.NoScores); return; } - // ensure placeholder is hidden when displaying scores - setErrorState(LeaderboardErrorState.NoError); - loading.Show(); - LoadComponentAsync(new FillFlowContainer { RelativeSizeAxes = Axes.X, @@ -269,6 +264,8 @@ namespace osu.Game.Online.Leaderboards ChildrenEnumerable = scores.Select((s, index) => CreateDrawableScore(s, index + 1)) }, newFlow => { + setState(LeaderboardState.Success); + scrollContainer.Add(scoreFlowContainer = newFlow); double delay = 0; @@ -282,7 +279,6 @@ namespace osu.Game.Online.Leaderboards } scrollContainer.ScrollToStart(false); - loading.Hide(); }, (currentScoresAsyncLoadCancellationSource = new CancellationTokenSource()).Token); } @@ -290,16 +286,21 @@ namespace osu.Game.Online.Leaderboards private Placeholder placeholder; - private void setErrorState(LeaderboardErrorState errorState) + private void setState(LeaderboardState state) { - if (errorState == this.errorState) + if (state == this.state) return; - this.errorState = errorState; + if (state == LeaderboardState.Retrieving) + loading.Show(); + else + loading.Hide(); + + this.state = state; placeholder?.FadeOut(150, Easing.OutQuint).Expire(); - placeholder = getPlaceholderFor(errorState); + placeholder = getPlaceholderFor(state); if (placeholder == null) return; @@ -310,32 +311,35 @@ namespace osu.Game.Online.Leaderboards placeholder.FadeInFromZero(fade_duration, Easing.OutQuint); } - private Placeholder getPlaceholderFor(LeaderboardErrorState errorState) + private Placeholder getPlaceholderFor(LeaderboardState state) { - switch (errorState) + switch (state) { - case LeaderboardErrorState.NetworkFailure: + case LeaderboardState.NetworkFailure: return new ClickablePlaceholder(@"Couldn't fetch scores!", FontAwesome.Solid.Sync) { Action = RefetchScores }; - case LeaderboardErrorState.NoneSelected: + case LeaderboardState.NoneSelected: return new MessagePlaceholder(@"Please select a beatmap!"); - case LeaderboardErrorState.Unavailable: + case LeaderboardState.Unavailable: return new MessagePlaceholder(@"Leaderboards are not available for this beatmap!"); - case LeaderboardErrorState.NoScores: + case LeaderboardState.NoScores: return new MessagePlaceholder(@"No records yet!"); - case LeaderboardErrorState.NotLoggedIn: + case LeaderboardState.NotLoggedIn: return new LoginPlaceholder(@"Please sign in to view online leaderboards!"); - case LeaderboardErrorState.NotSupporter: + case LeaderboardState.NotSupporter: return new MessagePlaceholder(@"Please invest in an osu!supporter tag to view this leaderboard!"); - case LeaderboardErrorState.NoError: + case LeaderboardState.Retrieving: + return null; + + case LeaderboardState.Success: return null; default: diff --git a/osu.Game/Online/Leaderboards/LeaderboardErrorState.cs b/osu.Game/Online/Leaderboards/LeaderboardState.cs similarity index 82% rename from osu.Game/Online/Leaderboards/LeaderboardErrorState.cs rename to osu.Game/Online/Leaderboards/LeaderboardState.cs index 17f47bb557..75e2c6e6db 100644 --- a/osu.Game/Online/Leaderboards/LeaderboardErrorState.cs +++ b/osu.Game/Online/Leaderboards/LeaderboardState.cs @@ -3,9 +3,10 @@ namespace osu.Game.Online.Leaderboards { - public enum LeaderboardErrorState + public enum LeaderboardState { - NoError, + Success, + Retrieving, NetworkFailure, Unavailable, NoneSelected, diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 3521a2ef78..48eb33cc05 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -101,7 +101,7 @@ namespace osu.Game.Screens.Select.Leaderboards if (fetchBeatmapInfo == null) { - SetErrorState(LeaderboardErrorState.NoneSelected); + SetErrorState(LeaderboardState.NoneSelected); return null; } @@ -113,19 +113,19 @@ namespace osu.Game.Screens.Select.Leaderboards if (api?.IsLoggedIn != true) { - SetErrorState(LeaderboardErrorState.NotLoggedIn); + SetErrorState(LeaderboardState.NotLoggedIn); return null; } if (fetchBeatmapInfo.OnlineID <= 0 || fetchBeatmapInfo.Status <= BeatmapOnlineStatus.Pending) { - SetErrorState(LeaderboardErrorState.Unavailable); + SetErrorState(LeaderboardState.Unavailable); return null; } if (!api.LocalUser.Value.IsSupporter && (Scope != BeatmapLeaderboardScope.Global || filterMods)) { - SetErrorState(LeaderboardErrorState.NotSupporter); + SetErrorState(LeaderboardState.NotSupporter); return null; }