From 96d4369cc823d71370f1c2fa9f8faaecba66f828 Mon Sep 17 00:00:00 2001 From: Salman Ahmed Date: Tue, 19 Apr 2022 02:04:23 +0300 Subject: [PATCH] Introduce `Pagination` and simplify paginated API requests --- .../API/Requests/GetUserBeatmapsRequest.cs | 4 +- .../Requests/GetUserKudosuHistoryRequest.cs | 4 +- .../GetUserMostPlayedBeatmapsRequest.cs | 4 +- .../GetUserRecentActivitiesRequest.cs | 4 +- .../API/Requests/GetUserScoresRequest.cs | 4 +- .../API/Requests/PaginatedAPIRequest.cs | 19 +++------- osu.Game/Online/API/Requests/Pagination.cs | 38 +++++++++++++++++++ .../Beatmaps/PaginatedBeatmapContainer.cs | 4 +- .../PaginatedMostPlayedBeatmapContainer.cs | 4 +- .../Kudosu/PaginatedKudosuHistoryContainer.cs | 4 +- .../Sections/PaginatedProfileSubsection.cs | 16 ++++---- .../Sections/Ranks/PaginatedScoreContainer.cs | 6 +-- .../PaginatedRecentActivityContainer.cs | 4 +- 13 files changed, 73 insertions(+), 42 deletions(-) create mode 100644 osu.Game/Online/API/Requests/Pagination.cs diff --git a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs index b7681cb71b..019c805c9a 100644 --- a/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserBeatmapsRequest.cs @@ -13,8 +13,8 @@ namespace osu.Game.Online.API.Requests private readonly BeatmapSetType type; - public GetUserBeatmapsRequest(long userId, BeatmapSetType type, int page, int itemsPerPage, int initialItems) - : base(page, itemsPerPage, initialItems) + public GetUserBeatmapsRequest(long userId, BeatmapSetType type, Pagination pagination) + : base(pagination) { this.userId = userId; this.type = type; diff --git a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs index d2102d7697..3759c59722 100644 --- a/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserKudosuHistoryRequest.cs @@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; - public GetUserKudosuHistoryRequest(long userId, int page, int itemsPerPage, int initialItems) - : base(page, itemsPerPage, initialItems) + public GetUserKudosuHistoryRequest(long userId, Pagination pagination) + : base(pagination) { this.userId = userId; } diff --git a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs index a9b6dd7edc..37359e2cd0 100644 --- a/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserMostPlayedBeatmapsRequest.cs @@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; - public GetUserMostPlayedBeatmapsRequest(long userId, int page, int itemsPerPage, int initialItems) - : base(page, itemsPerPage, initialItems) + public GetUserMostPlayedBeatmapsRequest(long userId, Pagination pagination) + : base(pagination) { this.userId = userId; } diff --git a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs index 60acc27182..c16633c17a 100644 --- a/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserRecentActivitiesRequest.cs @@ -10,8 +10,8 @@ namespace osu.Game.Online.API.Requests { private readonly long userId; - public GetUserRecentActivitiesRequest(long userId, int page, int itemsPerPage, int initialItems) - : base(page, itemsPerPage, initialItems) + public GetUserRecentActivitiesRequest(long userId, Pagination pagination) + : base(pagination) { this.userId = userId; } diff --git a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs index 85b58fc596..af01969a1a 100644 --- a/osu.Game/Online/API/Requests/GetUserScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetUserScoresRequest.cs @@ -14,8 +14,8 @@ namespace osu.Game.Online.API.Requests private readonly ScoreType type; private readonly RulesetInfo ruleset; - public GetUserScoresRequest(long userId, ScoreType type, int page, int itemsPerPage, int initialItems, RulesetInfo ruleset = null) - : base(page, itemsPerPage, initialItems) + public GetUserScoresRequest(long userId, ScoreType type, Pagination pagination, RulesetInfo ruleset = null) + : base(pagination) { this.userId = userId; this.type = type; diff --git a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs index ea59fcfc25..ddc453bf17 100644 --- a/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs +++ b/osu.Game/Online/API/Requests/PaginatedAPIRequest.cs @@ -8,28 +8,19 @@ namespace osu.Game.Online.API.Requests { public abstract class PaginatedAPIRequest : APIRequest where T : class { - private readonly int page; - private readonly int initialItems; - private readonly int itemsPerPage; + private readonly Pagination pagination; - protected PaginatedAPIRequest(int page, int itemsPerPage, int initialItems) + protected PaginatedAPIRequest(Pagination pagination) { - this.page = page; - this.initialItems = initialItems; - this.itemsPerPage = itemsPerPage; + this.pagination = pagination; } protected override WebRequest CreateWebRequest() { var req = base.CreateWebRequest(); - if (page == 0) - req.AddParameter("limit", initialItems.ToString(CultureInfo.InvariantCulture)); - else - { - req.AddParameter("offset", (initialItems + (page - 1) * itemsPerPage).ToString(CultureInfo.InvariantCulture)); - req.AddParameter("limit", itemsPerPage.ToString(CultureInfo.InvariantCulture)); - } + req.AddParameter("offset", pagination.Offset.ToString(CultureInfo.InvariantCulture)); + req.AddParameter("limit", pagination.Limit.ToString(CultureInfo.InvariantCulture)); return req; } diff --git a/osu.Game/Online/API/Requests/Pagination.cs b/osu.Game/Online/API/Requests/Pagination.cs new file mode 100644 index 0000000000..a1caac7592 --- /dev/null +++ b/osu.Game/Online/API/Requests/Pagination.cs @@ -0,0 +1,38 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +namespace osu.Game.Online.API.Requests +{ + /// + /// Represents a pagination data used for . + /// + public readonly struct Pagination + { + /// + /// The starting point of the request. + /// + public int Offset { get; } + + /// + /// The maximum number of items to return in this request. + /// + public int Limit { get; } + + public Pagination(int offset, int limit) + { + Offset = offset; + Limit = limit; + } + + public Pagination(int limit) + : this(0, limit) + { + } + + /// + /// Returns a of the next number of items defined by after this. + /// + /// The limit of the next pagination. + public Pagination TakeNext(int limit) => new Pagination(Offset + Limit, limit); + } +} diff --git a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs index deeb63b5bf..f1c2b4bf7a 100644 --- a/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Beatmaps/PaginatedBeatmapContainer.cs @@ -58,8 +58,8 @@ namespace osu.Game.Overlays.Profile.Sections.Beatmaps } } - protected override APIRequest> CreateRequest(int itemsPerPage, int initialItems) => - new GetUserBeatmapsRequest(User.Value.Id, type, VisiblePages++, itemsPerPage, initialItems); + protected override APIRequest> CreateRequest(Pagination pagination) => + new GetUserBeatmapsRequest(User.Value.Id, type, pagination); protected override Drawable CreateDrawableItem(APIBeatmapSet model) => model.OnlineID > 0 ? new BeatmapCardNormal(model) diff --git a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs index ccd60fcd89..281bcc3a03 100644 --- a/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Historical/PaginatedMostPlayedBeatmapContainer.cs @@ -29,8 +29,8 @@ namespace osu.Game.Overlays.Profile.Sections.Historical protected override int GetCount(APIUser user) => user.BeatmapPlayCountsCount; - protected override APIRequest> CreateRequest(int itemsPerPage, int initialItems) => - new GetUserMostPlayedBeatmapsRequest(User.Value.Id, VisiblePages++, itemsPerPage, initialItems); + protected override APIRequest> CreateRequest(Pagination pagination) => + new GetUserMostPlayedBeatmapsRequest(User.Value.Id, pagination); protected override Drawable CreateDrawableItem(APIUserMostPlayedBeatmap mostPlayed) => new DrawableMostPlayedBeatmap(mostPlayed); diff --git a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs index 311a64a10d..5aada2b655 100644 --- a/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Kudosu/PaginatedKudosuHistoryContainer.cs @@ -19,8 +19,8 @@ namespace osu.Game.Overlays.Profile.Sections.Kudosu { } - protected override APIRequest> CreateRequest(int itemsPerPage, int initialItems) - => new GetUserKudosuHistoryRequest(User.Value.Id, VisiblePages++, itemsPerPage, initialItems); + protected override APIRequest> CreateRequest(Pagination pagination) + => new GetUserKudosuHistoryRequest(User.Value.Id, pagination); protected override Drawable CreateDrawableItem(APIKudosuHistory item) => new DrawableKudosuHistoryItem(item); } diff --git a/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs b/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs index 646c16fbd7..a1f9e7546a 100644 --- a/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs +++ b/osu.Game/Overlays/Profile/Sections/PaginatedProfileSubsection.cs @@ -14,6 +14,7 @@ using osu.Game.Graphics.Sprites; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API; using osu.Game.Graphics.Containers; +using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests.Responses; using osuTK; @@ -34,7 +35,7 @@ namespace osu.Game.Overlays.Profile.Sections [Resolved] private IAPIProvider api { get; set; } - protected int VisiblePages; + protected Pagination? CurrentPage { get; private set; } protected ReverseChildIDFillFlowContainer ItemsContainer { get; private set; } @@ -96,7 +97,7 @@ namespace osu.Game.Overlays.Profile.Sections loadCancellation?.Cancel(); retrievalRequest?.Cancel(); - VisiblePages = 0; + CurrentPage = null; ItemsContainer.Clear(); if (e.NewValue != null) @@ -110,7 +111,9 @@ namespace osu.Game.Overlays.Profile.Sections { loadCancellation = new CancellationTokenSource(); - retrievalRequest = CreateRequest(ItemsPerPage, InitialItemsCount); + CurrentPage = CurrentPage?.TakeNext(ItemsPerPage) ?? new Pagination(InitialItemsCount); + + retrievalRequest = CreateRequest(CurrentPage.Value); retrievalRequest.Success += UpdateItems; api.Queue(retrievalRequest); @@ -120,7 +123,7 @@ namespace osu.Game.Overlays.Profile.Sections { OnItemsReceived(items); - if (!items.Any() && VisiblePages == 1) + if (!items.Any() && CurrentPage?.Offset == 0) { moreButton.Hide(); moreButton.IsLoading = false; @@ -135,8 +138,7 @@ namespace osu.Game.Overlays.Profile.Sections { missing.Hide(); - int maxCount = VisiblePages == 1 ? InitialItemsCount : ItemsPerPage; - moreButton.FadeTo(items.Count == maxCount ? 1 : 0); + moreButton.FadeTo(items.Count == CurrentPage?.Limit ? 1 : 0); moreButton.IsLoading = false; ItemsContainer.AddRange(drawables); @@ -149,7 +151,7 @@ namespace osu.Game.Overlays.Profile.Sections { } - protected abstract APIRequest> CreateRequest(int itemsPerPage, int initialItems); + protected abstract APIRequest> CreateRequest(Pagination pagination); protected abstract Drawable CreateDrawableItem(TModel model); diff --git a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs index cc5952017d..c3a5e3f8b8 100644 --- a/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Ranks/PaginatedScoreContainer.cs @@ -54,14 +54,14 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks protected override void OnItemsReceived(List items) { - if (VisiblePages == 0) + if (CurrentPage == null || CurrentPage?.Offset == 0) drawableItemIndex = 0; base.OnItemsReceived(items); } - protected override APIRequest> CreateRequest(int itemsPerPage, int initialItems) => - new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, itemsPerPage, initialItems); + protected override APIRequest> CreateRequest(Pagination pagination) => + new GetUserScoresRequest(User.Value.Id, type, pagination); private int drawableItemIndex; diff --git a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs index 60cba95fda..e5118094ce 100644 --- a/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs +++ b/osu.Game/Overlays/Profile/Sections/Recent/PaginatedRecentActivityContainer.cs @@ -27,8 +27,8 @@ namespace osu.Game.Overlays.Profile.Sections.Recent ItemsContainer.Spacing = new Vector2(0, 8); } - protected override APIRequest> CreateRequest(int itemsPerPage, int initialItems) => - new GetUserRecentActivitiesRequest(User.Value.Id, VisiblePages++, itemsPerPage, initialItems); + protected override APIRequest> CreateRequest(Pagination pagination) => + new GetUserRecentActivitiesRequest(User.Value.Id, pagination); protected override Drawable CreateDrawableItem(APIRecentActivity model) => new DrawableRecentActivity(model); }