diff --git a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs index 3b7e30dafe..b25479704c 100644 --- a/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/Leaderboard.cs @@ -20,6 +20,8 @@ using osu.Game.Online.API.Requests; using System.Linq; using osu.Game.Graphics.Sprites; using osu.Game.Graphics; +using osu.Framework.Logging; +using System.Net; namespace osu.Game.Screens.Select.Leaderboards { @@ -29,7 +31,8 @@ namespace osu.Game.Screens.Select.Leaderboards private readonly ScrollContainer scrollContainer; private FillFlowContainer scrollFlow; - private Container placeholderContainer; + private Container noResultsPlaceholder; + private Container retryPlaceholder; public Action ScoreSelected; @@ -44,19 +47,20 @@ namespace osu.Game.Screens.Select.Leaderboards { scores = value; getScoresRequest?.Cancel(); + getScoresRequest = null; - placeholderContainer.FadeOut(fade_duration); + noResultsPlaceholder.FadeOut(fade_duration); scrollFlow?.FadeOut(fade_duration).Expire(); scrollFlow = null; + loading.Hide(); + if (scores == null) return; - loading.Hide(); - if (scores.Count() == 0) { - placeholderContainer.FadeIn(fade_duration); + noResultsPlaceholder.FadeIn(fade_duration); return; } @@ -110,7 +114,7 @@ namespace osu.Game.Screens.Select.Leaderboards ScrollbarVisible = false, }, loading = new LoadingAnimation(), - placeholderContainer = new Container + noResultsPlaceholder = new Container { Alpha = 0, RelativeSizeAxes = Axes.Both, @@ -139,6 +143,35 @@ namespace osu.Game.Screens.Select.Leaderboards }, }, }, + retryPlaceholder = new Container + { + Alpha = 0, + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new FillFlowContainer + { + Direction = FillDirection.Horizontal, + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + AutoSizeAxes = Axes.Both, + Children = new Drawable[] + { + new RetryButton + { + Action = updateScores, + Margin = new MarginPadding { Right = 10 }, + }, + new OsuSpriteText + { + Anchor = Anchor.TopLeft, + Text = @"An error occurred!", + TextSize = 22, + }, + } + }, + }, + }, }; } @@ -180,6 +213,8 @@ namespace osu.Game.Screens.Select.Leaderboards { if (!IsLoaded) return; + retryPlaceholder.FadeOut(fade_duration); + Scores = null; if (api == null || Beatmap?.OnlineBeatmapID == null) return; @@ -198,6 +233,17 @@ namespace osu.Game.Screens.Select.Leaderboards { Scores = r.Scores; }; + getScoresRequest.Failure += e => + { + // TODO: check why failure is repeatedly invoked even on successful requests + if (e is WebException) + { + Scores = null; + retryPlaceholder.FadeIn(fade_duration); + Logger.Error(e, @"Couldn't fetch beatmap scores!"); + } + }; + api.Queue(getScoresRequest); } @@ -229,6 +275,51 @@ namespace osu.Game.Screens.Select.Leaderboards } } } + + private class RetryButton : ClickableContainer + { + private SpriteIcon icon; + + public RetryButton() + { + Height = 26; + Width = 26; + Children = new Drawable[] + { + icon = new SpriteIcon + { + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Icon = FontAwesome.fa_refresh, + Size = new Vector2(26), + } + }; + } + + protected override bool OnHover(Framework.Input.InputState state) + { + icon.ScaleTo(1.4f, 400, Easing.OutQuint); + return base.OnHover(state); + } + + protected override void OnHoverLost(Framework.Input.InputState state) + { + icon.ScaleTo(1f, 400, Easing.OutQuint); + base.OnHoverLost(state); + } + + protected override bool OnMouseDown(Framework.Input.InputState state, Framework.Input.MouseDownEventArgs args) + { + icon.ScaleTo(0.8f, 200, Easing.InElastic); + return base.OnMouseDown(state, args); + } + + protected override bool OnMouseUp(Framework.Input.InputState state, Framework.Input.MouseUpEventArgs args) + { + icon.ScaleTo(1.2f, 400, Easing.OutElastic).Then().ScaleTo(1f, 400, Easing.OutElastic); + return base.OnMouseUp(state, args); + } + } } public enum LeaderboardScope