mirror of
https://github.com/ppy/osu.git
synced 2025-01-15 14:12:54 +08:00
Maintain a placeholder state and add tests showing all the states.
- Also don't replace placeholder if new one is same as old
This commit is contained in:
parent
afcb9912e4
commit
01c4b1e544
@ -9,7 +9,6 @@ using osu.Game.Users;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
|
||||||
@ -33,8 +32,10 @@ namespace osu.Game.Tests.Visual
|
|||||||
});
|
});
|
||||||
|
|
||||||
AddStep(@"New Scores", newScores);
|
AddStep(@"New Scores", newScores);
|
||||||
AddStep(@"Empty Scores", () => leaderboard.Scores = Enumerable.Empty<Score>());
|
AddStep(@"Empty Scores", () => leaderboard.SetRetrievalState(PlaceholderState.NoScores));
|
||||||
AddStep(@"Network failure", networkFailure);
|
AddStep(@"Network failure", () => leaderboard.SetRetrievalState(PlaceholderState.NetworkFailure));
|
||||||
|
AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter));
|
||||||
|
AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn));
|
||||||
AddStep(@"Real beatmap", realBeatmap);
|
AddStep(@"Real beatmap", realBeatmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,19 +266,11 @@ namespace osu.Game.Tests.Visual
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void networkFailure()
|
|
||||||
{
|
|
||||||
leaderboard.Beatmap = new BeatmapInfo { Ruleset = rulesets.GetRuleset(0) };
|
|
||||||
}
|
|
||||||
|
|
||||||
private class FailableLeaderboard : Leaderboard
|
private class FailableLeaderboard : Leaderboard
|
||||||
{
|
{
|
||||||
protected override void UpdateScores()
|
public void SetRetrievalState(PlaceholderState state)
|
||||||
{
|
{
|
||||||
if (Beatmap?.OnlineBeatmapID == null)
|
PlaceholderState = state;
|
||||||
OnUpdateFailed(new WebException());
|
|
||||||
else
|
|
||||||
base.UpdateScores();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,21 +48,16 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
{
|
{
|
||||||
scores = value;
|
scores = value;
|
||||||
|
|
||||||
placeholderContainer.FadeOut(fade_duration);
|
|
||||||
|
|
||||||
scrollFlow?.FadeOut(fade_duration).Expire();
|
scrollFlow?.FadeOut(fade_duration).Expire();
|
||||||
scrollFlow = null;
|
scrollFlow = null;
|
||||||
|
|
||||||
loading.Hide();
|
loading.Hide();
|
||||||
|
|
||||||
if (scores == null)
|
if (scores == null || !scores.Any())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!scores.Any())
|
// ensure placeholder is hidden when displaying scores
|
||||||
{
|
PlaceholderState = PlaceholderState.Successful;
|
||||||
replacePlaceholder(new MessagePlaceholder(@"No records yet!"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// schedule because we may not be loaded yet (LoadComponentAsync complains).
|
// schedule because we may not be loaded yet (LoadComponentAsync complains).
|
||||||
Schedule(() =>
|
Schedule(() =>
|
||||||
@ -100,7 +95,43 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
if (value == scope) return;
|
if (value == scope) return;
|
||||||
|
|
||||||
scope = value;
|
scope = value;
|
||||||
UpdateScores();
|
updateScores();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlaceholderState placeholderState;
|
||||||
|
protected PlaceholderState PlaceholderState
|
||||||
|
{
|
||||||
|
get { return placeholderState; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == placeholderState) return;
|
||||||
|
|
||||||
|
switch (placeholderState = value)
|
||||||
|
{
|
||||||
|
case PlaceholderState.NetworkFailure:
|
||||||
|
replacePlaceholder(new RetrievalFailurePlaceholder
|
||||||
|
{
|
||||||
|
OnRetry = updateScores,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PlaceholderState.NoScores:
|
||||||
|
replacePlaceholder(new MessagePlaceholder(@"No records yet!"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PlaceholderState.NotLoggedIn:
|
||||||
|
replacePlaceholder(new MessagePlaceholder(@"Please login to view online leaderboards!"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PlaceholderState.NotSupporter:
|
||||||
|
replacePlaceholder(new MessagePlaceholder(@"Please invest in a supporter tag to view this leaderboard!"));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
replacePlaceholder(null);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +174,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
Scores = null;
|
Scores = null;
|
||||||
|
|
||||||
pendingBeatmapSwitch?.Cancel();
|
pendingBeatmapSwitch?.Cancel();
|
||||||
pendingBeatmapSwitch = Schedule(UpdateScores);
|
pendingBeatmapSwitch = Schedule(updateScores);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +201,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
|
|
||||||
private GetScoresRequest getScoresRequest;
|
private GetScoresRequest getScoresRequest;
|
||||||
|
|
||||||
private void handleRulesetChange(RulesetInfo ruleset) => UpdateScores();
|
private void handleRulesetChange(RulesetInfo ruleset) => updateScores();
|
||||||
|
|
||||||
private void handleApiStateChange(APIState oldState, APIState newState)
|
private void handleApiStateChange(APIState oldState, APIState newState)
|
||||||
{
|
{
|
||||||
@ -179,46 +210,43 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (newState == APIState.Online)
|
if (newState == APIState.Online)
|
||||||
UpdateScores();
|
updateScores();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void UpdateScores()
|
private void updateScores()
|
||||||
{
|
{
|
||||||
if (!IsLoaded) return;
|
if (!IsLoaded) return;
|
||||||
|
|
||||||
getScoresRequest?.Cancel();
|
getScoresRequest?.Cancel();
|
||||||
getScoresRequest = null;
|
getScoresRequest = null;
|
||||||
|
|
||||||
Scores = null;
|
Scores = null;
|
||||||
|
|
||||||
if (Scope == LeaderboardScope.Local)
|
if (Scope == LeaderboardScope.Local)
|
||||||
{
|
{
|
||||||
// TODO: get local scores from wherever here.
|
// TODO: get local scores from wherever here.
|
||||||
Scores = Enumerable.Empty<Score>();
|
PlaceholderState = PlaceholderState.NoScores;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (api?.IsLoggedIn != true)
|
if (api?.IsLoggedIn != true)
|
||||||
{
|
{
|
||||||
replacePlaceholder(new MessagePlaceholder(@"Please login to view online leaderboards!"));
|
PlaceholderState = PlaceholderState.NotLoggedIn;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Beatmap?.OnlineBeatmapID == null)
|
if (Beatmap?.OnlineBeatmapID == null)
|
||||||
{
|
{
|
||||||
replacePlaceholder(new RetrievalFailurePlaceholder
|
PlaceholderState = PlaceholderState.NetworkFailure;
|
||||||
{
|
|
||||||
OnRetry = UpdateScores,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlaceholderState = PlaceholderState.Retrieving;
|
||||||
loading.Show();
|
loading.Show();
|
||||||
|
|
||||||
if (Scope != LeaderboardScope.Global && !api.LocalUser.Value.IsSupporter)
|
if (Scope != LeaderboardScope.Global && !api.LocalUser.Value.IsSupporter)
|
||||||
{
|
{
|
||||||
loading.Hide();
|
loading.Hide();
|
||||||
replacePlaceholder(new MessagePlaceholder(@"Please invest in a supporter tag to view this leaderboard!"));
|
PlaceholderState = PlaceholderState.NotSupporter;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,27 +254,37 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
getScoresRequest.Success += r =>
|
getScoresRequest.Success += r =>
|
||||||
{
|
{
|
||||||
Scores = r.Scores;
|
Scores = r.Scores;
|
||||||
|
PlaceholderState = Scores.Any() ? PlaceholderState.Successful : PlaceholderState.NoScores;
|
||||||
};
|
};
|
||||||
getScoresRequest.Failure += OnUpdateFailed;
|
getScoresRequest.Failure += onUpdateFailed;
|
||||||
|
|
||||||
api.Queue(getScoresRequest);
|
api.Queue(getScoresRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void OnUpdateFailed(Exception e)
|
private void onUpdateFailed(Exception e)
|
||||||
{
|
{
|
||||||
if (e is OperationCanceledException) return;
|
if (e is OperationCanceledException) return;
|
||||||
|
|
||||||
Scores = null;
|
PlaceholderState = PlaceholderState.NetworkFailure;
|
||||||
replacePlaceholder(new RetrievalFailurePlaceholder
|
|
||||||
{
|
|
||||||
OnRetry = UpdateScores,
|
|
||||||
});
|
|
||||||
Logger.Error(e, @"Couldn't fetch beatmap scores!");
|
Logger.Error(e, @"Couldn't fetch beatmap scores!");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replacePlaceholder(Drawable placeholder)
|
private void replacePlaceholder(Placeholder placeholder)
|
||||||
|
{
|
||||||
|
if (placeholder == null)
|
||||||
{
|
{
|
||||||
placeholderContainer.FadeOutFromOne(fade_duration, Easing.OutQuint);
|
placeholderContainer.FadeOutFromOne(fade_duration, Easing.OutQuint);
|
||||||
|
placeholderContainer.Clear(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existingPlaceholder = placeholderContainer.Children.FirstOrDefault() as Placeholder;
|
||||||
|
|
||||||
|
if (placeholder.Equals(existingPlaceholder))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Scores = null;
|
||||||
|
|
||||||
placeholderContainer.Clear(true);
|
placeholderContainer.Clear(true);
|
||||||
placeholderContainer.Child = placeholder;
|
placeholderContainer.Child = placeholder;
|
||||||
placeholderContainer.FadeInFromZero(fade_duration, Easing.OutQuint);
|
placeholderContainer.FadeInFromZero(fade_duration, Easing.OutQuint);
|
||||||
@ -281,8 +319,15 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MessagePlaceholder : FillFlowContainer
|
private abstract class Placeholder : FillFlowContainer, IEquatable<Placeholder>
|
||||||
{
|
{
|
||||||
|
public virtual bool Equals(Placeholder other) => GetType() == other?.GetType();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MessagePlaceholder : Placeholder
|
||||||
|
{
|
||||||
|
private readonly string message;
|
||||||
|
|
||||||
public MessagePlaceholder(string message)
|
public MessagePlaceholder(string message)
|
||||||
{
|
{
|
||||||
Direction = FillDirection.Horizontal;
|
Direction = FillDirection.Horizontal;
|
||||||
@ -297,14 +342,16 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
},
|
},
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
Text = message,
|
Text = this.message = message,
|
||||||
TextSize = 22,
|
TextSize = 22,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool Equals(Placeholder other) => (other as MessagePlaceholder)?.message == message;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class RetrievalFailurePlaceholder : FillFlowContainer
|
private class RetrievalFailurePlaceholder : Placeholder
|
||||||
{
|
{
|
||||||
public Action OnRetry;
|
public Action OnRetry;
|
||||||
|
|
||||||
@ -327,7 +374,6 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private class RetryButton : OsuHoverContainer
|
private class RetryButton : OsuHoverContainer
|
||||||
{
|
{
|
||||||
@ -367,6 +413,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public enum LeaderboardScope
|
public enum LeaderboardScope
|
||||||
{
|
{
|
||||||
@ -375,4 +422,14 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
Global,
|
Global,
|
||||||
Friend,
|
Friend,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum PlaceholderState
|
||||||
|
{
|
||||||
|
Successful,
|
||||||
|
Retrieving,
|
||||||
|
NetworkFailure,
|
||||||
|
NoScores,
|
||||||
|
NotLoggedIn,
|
||||||
|
NotSupporter,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user