mirror of
https://github.com/osukey/osukey.git
synced 2025-05-29 09:27:18 +09:00
Also refactor placeholder
logic to make more sense
This commit is contained in:
parent
b434e29a7c
commit
c401629dd8
@ -114,12 +114,12 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestPlaceholderStates()
|
public void TestPlaceholderStates()
|
||||||
{
|
{
|
||||||
AddStep(@"Empty Scores", () => leaderboard.SetRetrievalState(PlaceholderState.NoScores));
|
AddStep(@"Empty Scores", () => leaderboard.SetErrorState(LeaderboardErrorState.NoScores));
|
||||||
AddStep(@"Network failure", () => leaderboard.SetRetrievalState(PlaceholderState.NetworkFailure));
|
AddStep(@"Network failure", () => leaderboard.SetErrorState(LeaderboardErrorState.NetworkFailure));
|
||||||
AddStep(@"No supporter", () => leaderboard.SetRetrievalState(PlaceholderState.NotSupporter));
|
AddStep(@"No supporter", () => leaderboard.SetErrorState(LeaderboardErrorState.NotSupporter));
|
||||||
AddStep(@"Not logged in", () => leaderboard.SetRetrievalState(PlaceholderState.NotLoggedIn));
|
AddStep(@"Not logged in", () => leaderboard.SetErrorState(LeaderboardErrorState.NotLoggedIn));
|
||||||
AddStep(@"Unavailable", () => leaderboard.SetRetrievalState(PlaceholderState.Unavailable));
|
AddStep(@"Unavailable", () => leaderboard.SetErrorState(LeaderboardErrorState.Unavailable));
|
||||||
AddStep(@"None selected", () => leaderboard.SetRetrievalState(PlaceholderState.NoneSelected));
|
AddStep(@"None selected", () => leaderboard.SetErrorState(LeaderboardErrorState.NoneSelected));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showPersonalBestWithNullPosition()
|
private void showPersonalBestWithNullPosition()
|
||||||
@ -401,22 +401,9 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showBeatmapWithStatus(BeatmapOnlineStatus status)
|
|
||||||
{
|
|
||||||
leaderboard.BeatmapInfo = new BeatmapInfo
|
|
||||||
{
|
|
||||||
OnlineID = 1113057,
|
|
||||||
Status = status,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private class FailableLeaderboard : BeatmapLeaderboard
|
private class FailableLeaderboard : BeatmapLeaderboard
|
||||||
{
|
{
|
||||||
public void SetRetrievalState(PlaceholderState state)
|
public new void SetErrorState(LeaderboardErrorState errorState) => base.SetErrorState(errorState);
|
||||||
{
|
|
||||||
Scores = null;
|
|
||||||
PlaceholderState = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public new ICollection<ScoreInfo> Scores
|
public new ICollection<ScoreInfo> Scores
|
||||||
{
|
{
|
||||||
|
@ -53,6 +53,8 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
|
|
||||||
private APIRequest fetchScoresRequest;
|
private APIRequest fetchScoresRequest;
|
||||||
|
|
||||||
|
private LeaderboardErrorState errorState;
|
||||||
|
|
||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
private IAPIProvider api { get; set; }
|
private IAPIProvider api { get; set; }
|
||||||
|
|
||||||
@ -169,14 +171,37 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
RefetchScores();
|
RefetchScores();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Perform a full refetch of scores using current criteria.
|
||||||
|
/// </summary>
|
||||||
public void RefetchScores() => Scheduler.AddOnce(refetchScores);
|
public void RefetchScores() => Scheduler.AddOnce(refetchScores);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset the leaderboard into an empty state.
|
||||||
|
/// </summary>
|
||||||
protected virtual void Reset()
|
protected virtual void Reset()
|
||||||
{
|
{
|
||||||
cancelPendingWork();
|
cancelPendingWork();
|
||||||
Scores = null;
|
Scores = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Call when a retrieval or display failure happened to show a relevant message to the user.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="errorState">The state to display.</param>
|
||||||
|
protected void SetErrorState(LeaderboardErrorState errorState)
|
||||||
|
{
|
||||||
|
switch (errorState)
|
||||||
|
{
|
||||||
|
case LeaderboardErrorState.NoError:
|
||||||
|
throw new InvalidOperationException($"State {errorState} cannot be set by a leaderboard implementation.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.Assert(scores?.Any() != true);
|
||||||
|
|
||||||
|
setErrorState(errorState);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Performs a fetch/refresh of scores to be displayed.
|
/// Performs a fetch/refresh of scores to be displayed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -195,7 +220,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
|
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
PlaceholderState = PlaceholderState.Retrieving;
|
setErrorState(LeaderboardErrorState.NoError);
|
||||||
loading.Show();
|
loading.Show();
|
||||||
|
|
||||||
currentFetchCancellationSource = new CancellationTokenSource();
|
currentFetchCancellationSource = new CancellationTokenSource();
|
||||||
@ -210,7 +235,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
if (e is OperationCanceledException || currentFetchCancellationSource.IsCancellationRequested)
|
if (e is OperationCanceledException || currentFetchCancellationSource.IsCancellationRequested)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PlaceholderState = PlaceholderState.NetworkFailure;
|
SetErrorState(LeaderboardErrorState.NetworkFailure);
|
||||||
});
|
});
|
||||||
|
|
||||||
api?.Queue(fetchScoresRequest);
|
api?.Queue(fetchScoresRequest);
|
||||||
@ -223,77 +248,6 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
fetchScoresRequest?.Cancel();
|
fetchScoresRequest?.Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Placeholder handling
|
|
||||||
|
|
||||||
private Placeholder currentPlaceholder;
|
|
||||||
|
|
||||||
private PlaceholderState placeholderState;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Update the placeholder visibility.
|
|
||||||
/// Setting this to anything other than PlaceholderState.Successful will cancel all existing retrieval requests and hide scores.
|
|
||||||
/// </summary>
|
|
||||||
protected PlaceholderState PlaceholderState
|
|
||||||
{
|
|
||||||
get => placeholderState;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == placeholderState)
|
|
||||||
return;
|
|
||||||
|
|
||||||
placeholderState = value;
|
|
||||||
|
|
||||||
switch (placeholderState)
|
|
||||||
{
|
|
||||||
case PlaceholderState.NetworkFailure:
|
|
||||||
Debug.Assert(scores?.Any() != true);
|
|
||||||
replacePlaceholder(new ClickablePlaceholder(@"Couldn't fetch scores!", FontAwesome.Solid.Sync)
|
|
||||||
{
|
|
||||||
Action = RefetchScores
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PlaceholderState.NoneSelected:
|
|
||||||
Debug.Assert(scores?.Any() != true);
|
|
||||||
replacePlaceholder(new MessagePlaceholder(@"Please select a beatmap!"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PlaceholderState.Unavailable:
|
|
||||||
Debug.Assert(scores?.Any() != true);
|
|
||||||
replacePlaceholder(new MessagePlaceholder(@"Leaderboards are not available for this beatmap!"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PlaceholderState.NoScores:
|
|
||||||
Debug.Assert(scores?.Any() != true);
|
|
||||||
replacePlaceholder(new MessagePlaceholder(@"No records yet!"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PlaceholderState.NotLoggedIn:
|
|
||||||
Debug.Assert(scores?.Any() != true);
|
|
||||||
replacePlaceholder(new LoginPlaceholder(@"Please sign in to view online leaderboards!"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PlaceholderState.NotSupporter:
|
|
||||||
Debug.Assert(scores?.Any() != true);
|
|
||||||
replacePlaceholder(new MessagePlaceholder(@"Please invest in an osu!supporter tag to view this leaderboard!"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PlaceholderState.Retrieving:
|
|
||||||
Debug.Assert(scores?.Any() != true);
|
|
||||||
replacePlaceholder(null);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PlaceholderState.Successful:
|
|
||||||
Debug.Assert(scores?.Any() == true);
|
|
||||||
replacePlaceholder(null);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateScoresDrawables()
|
private void updateScoresDrawables()
|
||||||
{
|
{
|
||||||
currentScoresAsyncLoadCancellationSource?.Cancel();
|
currentScoresAsyncLoadCancellationSource?.Cancel();
|
||||||
@ -305,13 +259,14 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
|
|
||||||
if (scores?.Any() != true)
|
if (scores?.Any() != true)
|
||||||
{
|
{
|
||||||
|
SetErrorState(LeaderboardErrorState.NoScores);
|
||||||
loading.Hide();
|
loading.Hide();
|
||||||
PlaceholderState = PlaceholderState.NoScores;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure placeholder is hidden when displaying scores
|
// ensure placeholder is hidden when displaying scores
|
||||||
PlaceholderState = PlaceholderState.Successful;
|
setErrorState(LeaderboardErrorState.NoError);
|
||||||
|
loading.Show();
|
||||||
|
|
||||||
LoadComponentAsync(new FillFlowContainer<LeaderboardScore>
|
LoadComponentAsync(new FillFlowContainer<LeaderboardScore>
|
||||||
{
|
{
|
||||||
@ -339,25 +294,61 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
}, (currentScoresAsyncLoadCancellationSource = new CancellationTokenSource()).Token);
|
}, (currentScoresAsyncLoadCancellationSource = new CancellationTokenSource()).Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replacePlaceholder(Placeholder placeholder)
|
#region Placeholder handling
|
||||||
|
|
||||||
|
private Placeholder placeholder;
|
||||||
|
|
||||||
|
private void setErrorState(LeaderboardErrorState errorState)
|
||||||
{
|
{
|
||||||
if (placeholder != null && placeholder.Equals(currentPlaceholder))
|
if (errorState == this.errorState)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
currentPlaceholder?.FadeOut(150, Easing.OutQuint).Expire();
|
this.errorState = errorState;
|
||||||
|
|
||||||
|
placeholder?.FadeOut(150, Easing.OutQuint).Expire();
|
||||||
|
|
||||||
|
placeholder = getPlaceholderFor(errorState);
|
||||||
|
|
||||||
if (placeholder == null)
|
if (placeholder == null)
|
||||||
{
|
|
||||||
currentPlaceholder = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
placeholderContainer.Child = placeholder;
|
placeholderContainer.Child = placeholder;
|
||||||
|
|
||||||
placeholder.ScaleTo(0.8f).Then().ScaleTo(1, fade_duration * 3, Easing.OutQuint);
|
placeholder.ScaleTo(0.8f).Then().ScaleTo(1, fade_duration * 3, Easing.OutQuint);
|
||||||
placeholder.FadeInFromZero(fade_duration, Easing.OutQuint);
|
placeholder.FadeInFromZero(fade_duration, Easing.OutQuint);
|
||||||
|
}
|
||||||
|
|
||||||
currentPlaceholder = placeholder;
|
private Placeholder getPlaceholderFor(LeaderboardErrorState errorState)
|
||||||
|
{
|
||||||
|
switch (errorState)
|
||||||
|
{
|
||||||
|
case LeaderboardErrorState.NetworkFailure:
|
||||||
|
return new ClickablePlaceholder(@"Couldn't fetch scores!", FontAwesome.Solid.Sync)
|
||||||
|
{
|
||||||
|
Action = RefetchScores
|
||||||
|
};
|
||||||
|
|
||||||
|
case LeaderboardErrorState.NoneSelected:
|
||||||
|
return new MessagePlaceholder(@"Please select a beatmap!");
|
||||||
|
|
||||||
|
case LeaderboardErrorState.Unavailable:
|
||||||
|
return new MessagePlaceholder(@"Leaderboards are not available for this beatmap!");
|
||||||
|
|
||||||
|
case LeaderboardErrorState.NoScores:
|
||||||
|
return new MessagePlaceholder(@"No records yet!");
|
||||||
|
|
||||||
|
case LeaderboardErrorState.NotLoggedIn:
|
||||||
|
return new LoginPlaceholder(@"Please sign in to view online leaderboards!");
|
||||||
|
|
||||||
|
case LeaderboardErrorState.NotSupporter:
|
||||||
|
return new MessagePlaceholder(@"Please invest in an osu!supporter tag to view this leaderboard!");
|
||||||
|
|
||||||
|
case LeaderboardErrorState.NoError:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -3,10 +3,9 @@
|
|||||||
|
|
||||||
namespace osu.Game.Online.Leaderboards
|
namespace osu.Game.Online.Leaderboards
|
||||||
{
|
{
|
||||||
public enum PlaceholderState
|
public enum LeaderboardErrorState
|
||||||
{
|
{
|
||||||
Successful,
|
NoError,
|
||||||
Retrieving,
|
|
||||||
NetworkFailure,
|
NetworkFailure,
|
||||||
Unavailable,
|
Unavailable,
|
||||||
NoneSelected,
|
NoneSelected,
|
@ -33,19 +33,12 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (beatmapInfo == null && value == null)
|
if (beatmapInfo == null && value == null)
|
||||||
{
|
|
||||||
// always null scores to ensure a correct initial display.
|
|
||||||
// see weird `scoresLoadedOnce` logic in base implementation.
|
|
||||||
Scores = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (beatmapInfo?.Equals(value) == true)
|
if (beatmapInfo?.Equals(value) == true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
beatmapInfo = value;
|
beatmapInfo = value;
|
||||||
Scores = null;
|
|
||||||
|
|
||||||
RefetchScores();
|
RefetchScores();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,7 +107,7 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
|
|
||||||
if (fetchBeatmapInfo == null)
|
if (fetchBeatmapInfo == null)
|
||||||
{
|
{
|
||||||
PlaceholderState = PlaceholderState.NoneSelected;
|
SetErrorState(LeaderboardErrorState.NoneSelected);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,19 +119,19 @@ namespace osu.Game.Screens.Select.Leaderboards
|
|||||||
|
|
||||||
if (api?.IsLoggedIn != true)
|
if (api?.IsLoggedIn != true)
|
||||||
{
|
{
|
||||||
PlaceholderState = PlaceholderState.NotLoggedIn;
|
SetErrorState(LeaderboardErrorState.NotLoggedIn);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fetchBeatmapInfo.OnlineID <= 0 || fetchBeatmapInfo.Status <= BeatmapOnlineStatus.Pending)
|
if (fetchBeatmapInfo.OnlineID <= 0 || fetchBeatmapInfo.Status <= BeatmapOnlineStatus.Pending)
|
||||||
{
|
{
|
||||||
PlaceholderState = PlaceholderState.Unavailable;
|
SetErrorState(LeaderboardErrorState.Unavailable);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!api.LocalUser.Value.IsSupporter && (Scope != BeatmapLeaderboardScope.Global || filterMods))
|
if (!api.LocalUser.Value.IsSupporter && (Scope != BeatmapLeaderboardScope.Global || filterMods))
|
||||||
{
|
{
|
||||||
PlaceholderState = PlaceholderState.NotSupporter;
|
SetErrorState(LeaderboardErrorState.NotSupporter);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user