Merge pull request #17873 from frenzibyte/update-paginated-profile-items-count

Update paginated profile subsections to display items inline with web
This commit is contained in:
Bartłomiej Dach
2022-04-19 22:43:20 +02:00
committed by GitHub
13 changed files with 86 additions and 41 deletions

View File

@ -13,8 +13,8 @@ namespace osu.Game.Online.API.Requests
private readonly BeatmapSetType type; private readonly BeatmapSetType type;
public GetUserBeatmapsRequest(long userId, BeatmapSetType type, int page = 0, int itemsPerPage = 6) public GetUserBeatmapsRequest(long userId, BeatmapSetType type, PaginationParameters pagination)
: base(page, itemsPerPage) : base(pagination)
{ {
this.userId = userId; this.userId = userId;
this.type = type; this.type = type;

View File

@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests
{ {
private readonly long userId; private readonly long userId;
public GetUserKudosuHistoryRequest(long userId, int page = 0, int itemsPerPage = 5) public GetUserKudosuHistoryRequest(long userId, PaginationParameters pagination)
: base(page, itemsPerPage) : base(pagination)
{ {
this.userId = userId; this.userId = userId;
} }

View File

@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests
{ {
private readonly long userId; private readonly long userId;
public GetUserMostPlayedBeatmapsRequest(long userId, int page = 0, int itemsPerPage = 5) public GetUserMostPlayedBeatmapsRequest(long userId, PaginationParameters pagination)
: base(page, itemsPerPage) : base(pagination)
{ {
this.userId = userId; this.userId = userId;
} }

View File

@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests
{ {
private readonly long userId; private readonly long userId;
public GetUserRecentActivitiesRequest(long userId, int page = 0, int itemsPerPage = 5) public GetUserRecentActivitiesRequest(long userId, PaginationParameters pagination)
: base(page, itemsPerPage) : base(pagination)
{ {
this.userId = userId; this.userId = userId;
} }

View File

@ -14,8 +14,8 @@ namespace osu.Game.Online.API.Requests
private readonly ScoreType type; private readonly ScoreType type;
private readonly RulesetInfo ruleset; private readonly RulesetInfo ruleset;
public GetUserScoresRequest(long userId, ScoreType type, int page = 0, int itemsPerPage = 5, RulesetInfo ruleset = null) public GetUserScoresRequest(long userId, ScoreType type, PaginationParameters pagination, RulesetInfo ruleset = null)
: base(page, itemsPerPage) : base(pagination)
{ {
this.userId = userId; this.userId = userId;
this.type = type; this.type = type;

View File

@ -8,21 +8,19 @@ namespace osu.Game.Online.API.Requests
{ {
public abstract class PaginatedAPIRequest<T> : APIRequest<T> where T : class public abstract class PaginatedAPIRequest<T> : APIRequest<T> where T : class
{ {
private readonly int page; private readonly PaginationParameters pagination;
private readonly int itemsPerPage;
protected PaginatedAPIRequest(int page, int itemsPerPage) protected PaginatedAPIRequest(PaginationParameters pagination)
{ {
this.page = page; this.pagination = pagination;
this.itemsPerPage = itemsPerPage;
} }
protected override WebRequest CreateWebRequest() protected override WebRequest CreateWebRequest()
{ {
var req = base.CreateWebRequest(); var req = base.CreateWebRequest();
req.AddParameter("offset", (page * itemsPerPage).ToString(CultureInfo.InvariantCulture)); req.AddParameter("offset", pagination.Offset.ToString(CultureInfo.InvariantCulture));
req.AddParameter("limit", itemsPerPage.ToString(CultureInfo.InvariantCulture)); req.AddParameter("limit", pagination.Limit.ToString(CultureInfo.InvariantCulture));
return req; return req;
} }

View File

@ -0,0 +1,38 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
namespace osu.Game.Online.API.Requests
{
/// <summary>
/// Represents a pagination data used for <see cref="PaginatedAPIRequest{T}"/>.
/// </summary>
public readonly struct PaginationParameters
{
/// <summary>
/// The starting point of the request.
/// </summary>
public int Offset { get; }
/// <summary>
/// The maximum number of items to return in this request.
/// </summary>
public int Limit { get; }
public PaginationParameters(int offset, int limit)
{
Offset = offset;
Limit = limit;
}
public PaginationParameters(int limit)
: this(0, limit)
{
}
/// <summary>
/// Returns a <see cref="PaginationParameters"/> of the next number of items defined by <paramref name="limit"/> after this.
/// </summary>
/// <param name="limit">The limit of the next pagination.</param>
public PaginationParameters TakeNext(int limit) => new PaginationParameters(Offset + Limit, limit);
}
}

View File

@ -20,11 +20,12 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
private const float panel_padding = 10f; private const float panel_padding = 10f;
private readonly BeatmapSetType type; private readonly BeatmapSetType type;
protected override int InitialItemsCount => type == BeatmapSetType.Graveyard ? 2 : 6;
public PaginatedBeatmapContainer(BeatmapSetType type, Bindable<APIUser> user, LocalisableString headerText) public PaginatedBeatmapContainer(BeatmapSetType type, Bindable<APIUser> user, LocalisableString headerText)
: base(user, headerText) : base(user, headerText)
{ {
this.type = type; this.type = type;
ItemsPerPage = 6;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -57,8 +58,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps
} }
} }
protected override APIRequest<List<APIBeatmapSet>> CreateRequest() => protected override APIRequest<List<APIBeatmapSet>> CreateRequest(PaginationParameters pagination) =>
new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); new GetUserBeatmapsRequest(User.Value.Id, type, pagination);
protected override Drawable CreateDrawableItem(APIBeatmapSet model) => model.OnlineID > 0 protected override Drawable CreateDrawableItem(APIBeatmapSet model) => model.OnlineID > 0
? new BeatmapCardNormal(model) ? new BeatmapCardNormal(model)

View File

@ -19,7 +19,6 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
public PaginatedMostPlayedBeatmapContainer(Bindable<APIUser> user) public PaginatedMostPlayedBeatmapContainer(Bindable<APIUser> user)
: base(user, UsersStrings.ShowExtraHistoricalMostPlayedTitle) : base(user, UsersStrings.ShowExtraHistoricalMostPlayedTitle)
{ {
ItemsPerPage = 5;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -30,8 +29,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical
protected override int GetCount(APIUser user) => user.BeatmapPlayCountsCount; protected override int GetCount(APIUser user) => user.BeatmapPlayCountsCount;
protected override APIRequest<List<APIUserMostPlayedBeatmap>> CreateRequest() => protected override APIRequest<List<APIUserMostPlayedBeatmap>> CreateRequest(PaginationParameters pagination) =>
new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, ItemsPerPage); new GetUserMostPlayedBeatmapsRequest(User.Value.Id, pagination);
protected override Drawable CreateDrawableItem(APIUserMostPlayedBeatmap mostPlayed) => protected override Drawable CreateDrawableItem(APIUserMostPlayedBeatmap mostPlayed) =>
new DrawableMostPlayedBeatmap(mostPlayed); new DrawableMostPlayedBeatmap(mostPlayed);

View File

@ -17,11 +17,10 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu
public PaginatedKudosuHistoryContainer(Bindable<APIUser> user) public PaginatedKudosuHistoryContainer(Bindable<APIUser> user)
: base(user, missingText: UsersStrings.ShowExtraKudosuEntryEmpty) : base(user, missingText: UsersStrings.ShowExtraKudosuEntryEmpty)
{ {
ItemsPerPage = 5;
} }
protected override APIRequest<List<APIKudosuHistory>> CreateRequest() protected override APIRequest<List<APIKudosuHistory>> CreateRequest(PaginationParameters pagination)
=> new GetUserKudosuHistoryRequest(User.Value.Id, VisiblePages++, ItemsPerPage); => new GetUserKudosuHistoryRequest(User.Value.Id, pagination);
protected override Drawable CreateDrawableItem(APIKudosuHistory item) => new DrawableKudosuHistoryItem(item); protected override Drawable CreateDrawableItem(APIKudosuHistory item) => new DrawableKudosuHistoryItem(item);
} }

View File

@ -14,6 +14,7 @@ using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osuTK; using osuTK;
@ -21,11 +22,20 @@ namespace osu.Game.Overlays.Profile.Sections
{ {
public abstract class PaginatedProfileSubsection<TModel> : ProfileSubsection public abstract class PaginatedProfileSubsection<TModel> : ProfileSubsection
{ {
/// <summary>
/// The number of items displayed per page.
/// </summary>
protected virtual int ItemsPerPage => 50;
/// <summary>
/// The number of items displayed initially.
/// </summary>
protected virtual int InitialItemsCount => 5;
[Resolved] [Resolved]
private IAPIProvider api { get; set; } private IAPIProvider api { get; set; }
protected int VisiblePages; protected PaginationParameters? CurrentPage { get; private set; }
protected int ItemsPerPage;
protected ReverseChildIDFillFlowContainer<Drawable> ItemsContainer { get; private set; } protected ReverseChildIDFillFlowContainer<Drawable> ItemsContainer { get; private set; }
@ -87,7 +97,7 @@ namespace osu.Game.Overlays.Profile.Sections
loadCancellation?.Cancel(); loadCancellation?.Cancel();
retrievalRequest?.Cancel(); retrievalRequest?.Cancel();
VisiblePages = 0; CurrentPage = null;
ItemsContainer.Clear(); ItemsContainer.Clear();
if (e.NewValue != null) if (e.NewValue != null)
@ -101,7 +111,9 @@ namespace osu.Game.Overlays.Profile.Sections
{ {
loadCancellation = new CancellationTokenSource(); loadCancellation = new CancellationTokenSource();
retrievalRequest = CreateRequest(); CurrentPage = CurrentPage?.TakeNext(ItemsPerPage) ?? new PaginationParameters(InitialItemsCount);
retrievalRequest = CreateRequest(CurrentPage.Value);
retrievalRequest.Success += UpdateItems; retrievalRequest.Success += UpdateItems;
api.Queue(retrievalRequest); api.Queue(retrievalRequest);
@ -111,7 +123,7 @@ namespace osu.Game.Overlays.Profile.Sections
{ {
OnItemsReceived(items); OnItemsReceived(items);
if (!items.Any() && VisiblePages == 1) if (!items.Any() && CurrentPage?.Offset == 0)
{ {
moreButton.Hide(); moreButton.Hide();
moreButton.IsLoading = false; moreButton.IsLoading = false;
@ -125,7 +137,8 @@ namespace osu.Game.Overlays.Profile.Sections
LoadComponentsAsync(items.Select(CreateDrawableItem).Where(d => d != null), drawables => LoadComponentsAsync(items.Select(CreateDrawableItem).Where(d => d != null), drawables =>
{ {
missing.Hide(); missing.Hide();
moreButton.FadeTo(items.Count == ItemsPerPage ? 1 : 0);
moreButton.FadeTo(items.Count == CurrentPage?.Limit ? 1 : 0);
moreButton.IsLoading = false; moreButton.IsLoading = false;
ItemsContainer.AddRange(drawables); ItemsContainer.AddRange(drawables);
@ -138,7 +151,7 @@ namespace osu.Game.Overlays.Profile.Sections
{ {
} }
protected abstract APIRequest<List<TModel>> CreateRequest(); protected abstract APIRequest<List<TModel>> CreateRequest(PaginationParameters pagination);
protected abstract Drawable CreateDrawableItem(TModel model); protected abstract Drawable CreateDrawableItem(TModel model);

View File

@ -23,8 +23,6 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
: base(user, headerText) : base(user, headerText)
{ {
this.type = type; this.type = type;
ItemsPerPage = 5;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -56,14 +54,14 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
protected override void OnItemsReceived(List<APIScore> items) protected override void OnItemsReceived(List<APIScore> items)
{ {
if (VisiblePages == 0) if (CurrentPage == null || CurrentPage?.Offset == 0)
drawableItemIndex = 0; drawableItemIndex = 0;
base.OnItemsReceived(items); base.OnItemsReceived(items);
} }
protected override APIRequest<List<APIScore>> CreateRequest() => protected override APIRequest<List<APIScore>> CreateRequest(PaginationParameters pagination) =>
new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage); new GetUserScoresRequest(User.Value.Id, type, pagination);
private int drawableItemIndex; private int drawableItemIndex;

View File

@ -19,7 +19,6 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
public PaginatedRecentActivityContainer(Bindable<APIUser> user) public PaginatedRecentActivityContainer(Bindable<APIUser> user)
: base(user, missingText: EventsStrings.Empty) : base(user, missingText: EventsStrings.Empty)
{ {
ItemsPerPage = 10;
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
@ -28,8 +27,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent
ItemsContainer.Spacing = new Vector2(0, 8); ItemsContainer.Spacing = new Vector2(0, 8);
} }
protected override APIRequest<List<APIRecentActivity>> CreateRequest() => protected override APIRequest<List<APIRecentActivity>> CreateRequest(PaginationParameters pagination) =>
new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, ItemsPerPage); new GetUserRecentActivitiesRequest(User.Value.Id, pagination);
protected override Drawable CreateDrawableItem(APIRecentActivity model) => new DrawableRecentActivity(model); protected override Drawable CreateDrawableItem(APIRecentActivity model) => new DrawableRecentActivity(model);
} }