mirror of
https://github.com/ppy/osu.git
synced 2024-11-06 06:57:39 +08:00
Implement paging
This commit is contained in:
parent
b7790de66f
commit
46ea775cfb
@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
@ -72,40 +73,93 @@ namespace osu.Game.Screens.Multi.Ranking
|
||||
lowerScoresCursor = userScore.ScoresAround.Lower.Cursor;
|
||||
}
|
||||
|
||||
success(allScores);
|
||||
performSuccessCallback(scoresCallback, allScores);
|
||||
};
|
||||
|
||||
userScoreReq.Failure += _ =>
|
||||
{
|
||||
// Fallback to a normal index.
|
||||
var indexReq = new IndexPlaylistScoresRequest(roomId, playlistItem.ID);
|
||||
indexReq.Success += r => success(r.Scores);
|
||||
|
||||
indexReq.Success += r =>
|
||||
{
|
||||
performSuccessCallback(scoresCallback, r.Scores);
|
||||
lowerScoresCursor = r.Cursor;
|
||||
};
|
||||
|
||||
indexReq.Failure += __ => loadingLayer.Hide();
|
||||
|
||||
api.Queue(indexReq);
|
||||
};
|
||||
|
||||
return userScoreReq;
|
||||
}
|
||||
|
||||
void success(List<MultiplayerScore> scores)
|
||||
protected override APIRequest FetchNextPage(int direction, Action<IEnumerable<ScoreInfo>> scoresCallback)
|
||||
{
|
||||
Debug.Assert(direction == 1 || direction == -1);
|
||||
|
||||
Cursor cursor;
|
||||
MultiplayerScoresSort sort;
|
||||
|
||||
switch (direction)
|
||||
{
|
||||
var scoreInfos = new List<ScoreInfo>(scores.Select(s => s.CreateScoreInfo(playlistItem)));
|
||||
case -1:
|
||||
cursor = higherScoresCursor;
|
||||
sort = MultiplayerScoresSort.Ascending;
|
||||
break;
|
||||
|
||||
// Select a score if we don't already have one selected.
|
||||
// Note: This is done before the callback so that the panel list centres on the selected score before panels are added (eliminating initial scroll).
|
||||
if (SelectedScore.Value == null)
|
||||
default:
|
||||
cursor = lowerScoresCursor;
|
||||
sort = MultiplayerScoresSort.Descending;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cursor == null)
|
||||
return null;
|
||||
|
||||
var indexReq = new IndexPlaylistScoresRequest(roomId, playlistItem.ID, cursor, sort);
|
||||
|
||||
indexReq.Success += r =>
|
||||
{
|
||||
switch (direction)
|
||||
{
|
||||
Schedule(() =>
|
||||
{
|
||||
// Prefer selecting the local user's score, or otherwise default to the first visible score.
|
||||
SelectedScore.Value = scoreInfos.FirstOrDefault(s => s.User.Id == api.LocalUser.Value.Id) ?? scoreInfos.FirstOrDefault();
|
||||
});
|
||||
case -1:
|
||||
higherScoresCursor = r.Cursor;
|
||||
break;
|
||||
|
||||
default:
|
||||
lowerScoresCursor = r.Cursor;
|
||||
break;
|
||||
}
|
||||
|
||||
// Invoke callback to add the scores. Exclude the user's current score which was added previously.
|
||||
scoresCallback?.Invoke(scoreInfos.Where(s => s.ID != Score?.OnlineScoreID));
|
||||
performSuccessCallback(scoresCallback, r.Scores);
|
||||
};
|
||||
|
||||
loadingLayer.Hide();
|
||||
indexReq.Failure += _ => loadingLayer.Hide();
|
||||
|
||||
return indexReq;
|
||||
}
|
||||
|
||||
private void performSuccessCallback(Action<IEnumerable<ScoreInfo>> callback, List<MultiplayerScore> scores)
|
||||
{
|
||||
var scoreInfos = new List<ScoreInfo>(scores.Select(s => s.CreateScoreInfo(playlistItem)));
|
||||
|
||||
// Select a score if we don't already have one selected.
|
||||
// Note: This is done before the callback so that the panel list centres on the selected score before panels are added (eliminating initial scroll).
|
||||
if (SelectedScore.Value == null)
|
||||
{
|
||||
Schedule(() =>
|
||||
{
|
||||
// Prefer selecting the local user's score, or otherwise default to the first visible score.
|
||||
SelectedScore.Value = scoreInfos.FirstOrDefault(s => s.User.Id == api.LocalUser.Value.Id) ?? scoreInfos.FirstOrDefault();
|
||||
});
|
||||
}
|
||||
|
||||
// Invoke callback to add the scores. Exclude the user's current score which was added previously.
|
||||
callback?.Invoke(scoreInfos.Where(s => s.ID != Score?.OnlineScoreID));
|
||||
|
||||
loadingLayer.Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,11 +164,7 @@ namespace osu.Game.Screens.Ranking
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
var req = FetchScores(scores => Schedule(() =>
|
||||
{
|
||||
foreach (var s in scores)
|
||||
addScore(s);
|
||||
}));
|
||||
var req = FetchScores(fetchScoresCallback);
|
||||
|
||||
if (req != null)
|
||||
api.Queue(req);
|
||||
@ -176,6 +172,29 @@ namespace osu.Game.Screens.Ranking
|
||||
statisticsPanel.State.BindValueChanged(onStatisticsStateChanged, true);
|
||||
}
|
||||
|
||||
private APIRequest nextPageRequest;
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (hasAnyScores && nextPageRequest == null)
|
||||
{
|
||||
if (scorePanelList.IsScrolledToStart)
|
||||
nextPageRequest = FetchNextPage(-1, fetchScoresCallback);
|
||||
else if (scorePanelList.IsScrolledToEnd)
|
||||
nextPageRequest = FetchNextPage(1, fetchScoresCallback);
|
||||
|
||||
if (nextPageRequest != null)
|
||||
{
|
||||
nextPageRequest.Success += () => nextPageRequest = null;
|
||||
nextPageRequest.Failure += _ => nextPageRequest = null;
|
||||
|
||||
api.Queue(nextPageRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs a fetch/refresh of scores to be displayed.
|
||||
/// </summary>
|
||||
@ -183,6 +202,18 @@ namespace osu.Game.Screens.Ranking
|
||||
/// <returns>An <see cref="APIRequest"/> responsible for the fetch operation. This will be queued and performed automatically.</returns>
|
||||
protected virtual APIRequest FetchScores(Action<IEnumerable<ScoreInfo>> scoresCallback) => null;
|
||||
|
||||
protected virtual APIRequest FetchNextPage(int direction, Action<IEnumerable<ScoreInfo>> scoresCallback) => null;
|
||||
|
||||
private bool hasAnyScores;
|
||||
|
||||
private void fetchScoresCallback(IEnumerable<ScoreInfo> scores) => Schedule(() =>
|
||||
{
|
||||
foreach (var s in scores)
|
||||
addScore(s);
|
||||
|
||||
hasAnyScores = true;
|
||||
});
|
||||
|
||||
public override void OnEntering(IScreen last)
|
||||
{
|
||||
base.OnEntering(last);
|
||||
|
@ -26,6 +26,10 @@ namespace osu.Game.Screens.Ranking
|
||||
/// </summary>
|
||||
private const float expanded_panel_spacing = 15;
|
||||
|
||||
public bool IsScrolledToStart => flow.Count > 0 && scroll.ScrollableExtent > 0 && scroll.Current <= 100;
|
||||
|
||||
public bool IsScrolledToEnd => flow.Count > 0 && scroll.ScrollableExtent > 0 && scroll.IsScrolledToEnd(100);
|
||||
|
||||
/// <summary>
|
||||
/// An action to be invoked if a <see cref="ScorePanel"/> is clicked while in an expanded state.
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user