diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs index d1c1164768ec..789d2ad9ae0c 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsOverlay.cs @@ -59,14 +59,32 @@ public void TestShowCountry() AddStep("Show US", () => rankingsOverlay.ShowCountry(CountryCode.US)); } + [Test] + public void TestPageSelection() + { + AddStep("Set scope to performance", () => scope.Value = RankingsScope.Performance); + AddStep("Move to next page", () => rankingsOverlay.Header.CurrentPage.Value += 1); + AddStep("Switch to another scope", () => scope.Value = RankingsScope.Score); + AddAssert("Check page is first one", () => rankingsOverlay.Header.CurrentPage.Value == 0); + AddStep("Move to next page", () => rankingsOverlay.Header.CurrentPage.Value += 1); + AddStep("Switch to another ruleset", () => rankingsOverlay.Header.Ruleset.Value = new ManiaRuleset().RulesetInfo); + AddAssert("Check page is first one", () => rankingsOverlay.Header.CurrentPage.Value == 0); + + AddStep("Set scope to kudosu", () => scope.Value = RankingsScope.Kudosu); + AddAssert("Check available pages is 20", () => rankingsOverlay.Header.AvailablesPages.Value == 20); + AddStep("Set scope to performance", () => scope.Value = RankingsScope.Performance); + AddAssert("Check available pages is 200", () => rankingsOverlay.Header.AvailablesPages.Value == 200); + } + private void loadRankingsOverlay() { Child = rankingsOverlay = new TestRankingsOverlay { - Country = { BindTarget = countryBindable }, - Header = { Current = { BindTarget = scope } }, State = { Value = Visibility.Visible }, }; + + countryBindable.BindTo(rankingsOverlay.Country); + scope.BindTo(rankingsOverlay.Header.Current); } private partial class TestRankingsOverlay : RankingsOverlay diff --git a/osu.Game/Overlays/PageableTabbleOnlineOverlay.cs b/osu.Game/Overlays/PageableTabbleOnlineOverlay.cs new file mode 100644 index 000000000000..1a8afbb73bbb --- /dev/null +++ b/osu.Game/Overlays/PageableTabbleOnlineOverlay.cs @@ -0,0 +1,32 @@ +// 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.Overlays +{ + public abstract partial class PageableTabbleOnlineOverlay : TabbableOnlineOverlay + where THeader : PagedTabControlOverlayHeader + { + protected PageableTabbleOnlineOverlay(OverlayColourScheme colourScheme) + : base(colourScheme) + { + } + + protected override void LoadComplete() + { + base.LoadComplete(); + Header.CurrentPage.BindValueChanged(page => OnPageChanged(page.NewValue)); + } + + protected override void OnTabChanged(TEnum tab) + { + // Go back to first page if we switch to another tab + Header.CurrentPage.SetDefault(); + base.OnTabChanged(tab); + } + + protected virtual void OnPageChanged(int page) + { + base.OnTabChanged(Header.Current.Value); + } + } +} diff --git a/osu.Game/Overlays/PagedTabControlOverlayHeader.cs b/osu.Game/Overlays/PagedTabControlOverlayHeader.cs new file mode 100644 index 000000000000..07f1e31cc19c --- /dev/null +++ b/osu.Game/Overlays/PagedTabControlOverlayHeader.cs @@ -0,0 +1,43 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable + +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Game.Graphics.UserInterface.PageSelector; + +namespace osu.Game.Overlays +{ + /// + /// + /// An extended overlay header that add a pagination support for a + /// + /// + public abstract partial class PagedTabControlOverlayHeader : TabControlOverlayHeader + { + private readonly PageSelector pageSelector; + + public BindableInt CurrentPage => pageSelector.CurrentPage; + public BindableInt AvailablesPages => pageSelector.AvailablePages; + + protected PagedTabControlOverlayHeader() + { + HeaderInfo.Add( + pageSelector = new PageSelector + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + Margin = new MarginPadding { Vertical = 15 }, + }); + } + + public void ShowPageSelector(bool visible) + { + if (visible) + pageSelector.Show(); + else + pageSelector.Hide(); + } + } +} diff --git a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs index 0eaa6ce82780..369af6c45b3e 100644 --- a/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs +++ b/osu.Game/Overlays/Rankings/RankingsOverlayHeader.cs @@ -11,7 +11,7 @@ namespace osu.Game.Overlays.Rankings { - public partial class RankingsOverlayHeader : TabControlOverlayHeader + public partial class RankingsOverlayHeader : PagedTabControlOverlayHeader { public Bindable Ruleset => rulesetSelector.Current; diff --git a/osu.Game/Overlays/RankingsOverlay.cs b/osu.Game/Overlays/RankingsOverlay.cs index 6a32515cbc1e..f1e0ed65722b 100644 --- a/osu.Game/Overlays/RankingsOverlay.cs +++ b/osu.Game/Overlays/RankingsOverlay.cs @@ -15,10 +15,13 @@ namespace osu.Game.Overlays { - public partial class RankingsOverlay : TabbableOnlineOverlay + public partial class RankingsOverlay : PageableTabbleOnlineOverlay { protected Bindable Country => Header.Country; + // First page is 0, need to apply +1 to get the right data actually. + private int currentPage => Header.CurrentPage.Value + 1; + private APIRequest lastRequest; [Resolved] @@ -45,7 +48,12 @@ protected override void LoadComplete() { // if a country is requested, force performance scope. if (!Country.IsDefault) + { Header.Current.Value = RankingsScope.Performance; + } + + // Hide page selection with country filter + Header.ShowPageSelector(Country.IsDefault); Scheduler.AddOnce(triggerTabChanged); }); @@ -78,12 +86,21 @@ protected override void OnTabChanged(RankingsScope tab) if (Header.Current.Value != RankingsScope.Performance) Country.SetDefault(); + // Kudosu scope have only 20 fetchable pages. + Header.AvailablesPages.Value = tab == RankingsScope.Kudosu ? 20 : 200; + + // Hide page selection for spotlights scope + Header.ShowPageSelector(tab != RankingsScope.Spotlights); + Scheduler.AddOnce(triggerTabChanged); } private void triggerTabChanged() => base.OnTabChanged(Header.Current.Value); - protected override RankingsOverlayHeader CreateHeader() => new RankingsOverlayHeader(); + protected override RankingsOverlayHeader CreateHeader() => new RankingsOverlayHeader + { + AvailablesPages = { Value = 200 } + }; public void ShowCountry(CountryCode requested) { @@ -128,16 +145,16 @@ private APIRequest createScopedRequest() switch (Header.Current.Value) { case RankingsScope.Performance: - return new GetUserRankingsRequest(ruleset.Value, countryCode: Country.Value); + return new GetUserRankingsRequest(ruleset.Value, page: currentPage, countryCode: Country.Value); case RankingsScope.Country: - return new GetCountryRankingsRequest(ruleset.Value); + return new GetCountryRankingsRequest(ruleset.Value, page: currentPage); case RankingsScope.Score: - return new GetUserRankingsRequest(ruleset.Value, UserRankingsType.Score); + return new GetUserRankingsRequest(ruleset.Value, UserRankingsType.Score, page: currentPage); case RankingsScope.Kudosu: - return new GetKudosuRankingsRequest(); + return new GetKudosuRankingsRequest(page: currentPage); } return null; @@ -154,10 +171,10 @@ private Drawable createTableFromResponse(APIRequest request) switch (userRequest.Type) { case UserRankingsType.Performance: - return new PerformanceTable(1, userRequest.Response.Users); + return new PerformanceTable(currentPage, userRequest.Response.Users); case UserRankingsType.Score: - return new ScoresTable(1, userRequest.Response.Users); + return new ScoresTable(currentPage, userRequest.Response.Users); } return null; @@ -167,14 +184,14 @@ private Drawable createTableFromResponse(APIRequest request) if (countryRequest.Response == null) return null; - return new CountriesTable(1, countryRequest.Response.Countries); + return new CountriesTable(currentPage, countryRequest.Response.Countries); } case GetKudosuRankingsRequest kudosuRequest: if (kudosuRequest.Response == null) return null; - return new KudosuTable(1, kudosuRequest.Response.Users); + return new KudosuTable(currentPage, kudosuRequest.Response.Users); } return null;