diff --git a/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs new file mode 100644 index 0000000000..e46c8a4a71 --- /dev/null +++ b/osu.Game.Tests/Visual/Online/TestSceneRankingsSpotlightSelector.cs @@ -0,0 +1,87 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using osu.Framework.Allocation; +using osu.Game.Online.API; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays; +using osu.Game.Overlays.Rankings; + +namespace osu.Game.Tests.Visual.Online +{ + public class TestSceneRankingsSpotlightSelector : OsuTestScene + { + public override IReadOnlyList RequiredTypes => new[] + { + typeof(SpotlightSelector), + }; + + protected override bool UseOnlineAPI => true; + + [Cached] + private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Green); + + [Resolved] + private IAPIProvider api { get; set; } + + private readonly SpotlightSelector selector; + + public TestSceneRankingsSpotlightSelector() + { + Add(selector = new SpotlightSelector()); + } + + [Test] + public void TestLocalSpotlights() + { + var spotlights = new[] + { + new APISpotlight + { + Name = "Spotlight 1", + StartDate = DateTimeOffset.Now, + EndDate = DateTimeOffset.Now, + }, + new APISpotlight + { + Name = "Spotlight 2", + StartDate = DateTimeOffset.Now, + EndDate = DateTimeOffset.Now, + }, + new APISpotlight + { + Name = "Spotlight 3", + StartDate = DateTimeOffset.Now, + EndDate = DateTimeOffset.Now, + }, + }; + + AddStep("load spotlights", () => selector.Spotlights = spotlights); + AddStep("change to spotlight 3", () => selector.Current.Value = spotlights[2]); + } + + [Test] + public void TestOnlineSpotlights() + { + List spotlights = null; + + AddStep("retrieve spotlights", () => + { + var req = new GetSpotlightsRequest(); + req.Success += res => spotlights = res.Spotlights; + + api.Perform(req); + }); + + AddStep("set spotlights", () => + { + if (spotlights != null) + selector.Spotlights = spotlights; + }); + } + } +} diff --git a/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs b/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs new file mode 100644 index 0000000000..6fafb3933c --- /dev/null +++ b/osu.Game/Online/API/Requests/GetSpotlightsRequest.cs @@ -0,0 +1,20 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Collections.Generic; +using Newtonsoft.Json; +using osu.Game.Online.API.Requests.Responses; + +namespace osu.Game.Online.API.Requests +{ + public class GetSpotlightsRequest : APIRequest + { + protected override string Target => "spotlights"; + } + + public class SpotlightsCollection + { + [JsonProperty("spotlights")] + public List Spotlights; + } +} diff --git a/osu.Game/Online/API/Requests/Responses/APISpotlight.cs b/osu.Game/Online/API/Requests/Responses/APISpotlight.cs new file mode 100644 index 0000000000..3a002e57b2 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/APISpotlight.cs @@ -0,0 +1,31 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using Newtonsoft.Json; + +namespace osu.Game.Online.API.Requests.Responses +{ + public class APISpotlight + { + [JsonProperty("id")] + public int Id; + + [JsonProperty("name")] + public string Name; + + [JsonProperty("type")] + public string Type; + + [JsonProperty("mode_specific")] + public bool ModeSpecific; + + [JsonProperty(@"start_date")] + public DateTimeOffset StartDate; + + [JsonProperty(@"end_date")] + public DateTimeOffset EndDate; + + public override string ToString() => Name; + } +} diff --git a/osu.Game/Overlays/Rankings/SpotlightSelector.cs b/osu.Game/Overlays/Rankings/SpotlightSelector.cs new file mode 100644 index 0000000000..e34c01113e --- /dev/null +++ b/osu.Game/Overlays/Rankings/SpotlightSelector.cs @@ -0,0 +1,161 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Allocation; +using osu.Framework.Bindables; +using osu.Framework.Graphics; +using osu.Framework.Graphics.Containers; +using osu.Framework.Graphics.Shapes; +using osu.Game.Graphics; +using osu.Game.Graphics.Sprites; +using osu.Game.Graphics.UserInterface; +using osu.Game.Online.API.Requests.Responses; +using osuTK; +using System; +using System.Collections.Generic; +using osu.Framework.Graphics.UserInterface; + +namespace osu.Game.Overlays.Rankings +{ + public class SpotlightSelector : CompositeDrawable, IHasCurrentValue + { + private readonly Box background; + private readonly SpotlightsDropdown dropdown; + + private readonly BindableWithCurrent current = new BindableWithCurrent(); + + public Bindable Current + { + get => current.Current; + set => current.Current = value; + } + + public IEnumerable Spotlights + { + get => dropdown.Items; + set => dropdown.Items = value; + } + + private readonly InfoColumn startDateColumn; + private readonly InfoColumn endDateColumn; + + public SpotlightSelector() + { + RelativeSizeAxes = Axes.X; + Height = 100; + + InternalChildren = new Drawable[] + { + background = new Box + { + RelativeSizeAxes = Axes.Both, + }, + new Container + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Horizontal = UserProfileOverlay.CONTENT_X_MARGIN, Vertical = 10 }, + Children = new Drawable[] + { + dropdown = new SpotlightsDropdown + { + Anchor = Anchor.TopCentre, + Origin = Anchor.TopCentre, + RelativeSizeAxes = Axes.X, + Current = Current, + Depth = -float.MaxValue + }, + new FillFlowContainer + { + Anchor = Anchor.BottomRight, + Origin = Anchor.BottomRight, + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(15, 0), + Children = new Drawable[] + { + startDateColumn = new InfoColumn(@"Start Date"), + endDateColumn = new InfoColumn(@"End Date"), + } + } + } + }, + }; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + background.Colour = colourProvider.Dark3; + } + + protected override void LoadComplete() + { + base.LoadComplete(); + + Current.BindValueChanged(onCurrentChanged); + } + + private void onCurrentChanged(ValueChangedEvent spotlight) + { + startDateColumn.Value = dateToString(spotlight.NewValue.StartDate); + endDateColumn.Value = dateToString(spotlight.NewValue.EndDate); + } + + private string dateToString(DateTimeOffset date) => date.ToString("yyyy-MM-dd"); + + private class InfoColumn : FillFlowContainer + { + public string Value + { + set => valueText.Text = value; + } + + private readonly OsuSpriteText valueText; + + public InfoColumn(string name) + { + AutoSizeAxes = Axes.Both; + Direction = FillDirection.Vertical; + Children = new Drawable[] + { + new OsuSpriteText + { + Text = name, + Font = OsuFont.GetFont(size: 10), + }, + new Container + { + AutoSizeAxes = Axes.X, + Height = 20, + Child = valueText = new OsuSpriteText + { + Anchor = Anchor.BottomLeft, + Origin = Anchor.BottomLeft, + Font = OsuFont.GetFont(size: 18, weight: FontWeight.Light), + } + } + }; + } + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + valueText.Colour = colourProvider.Content2; + } + } + + private class SpotlightsDropdown : OsuDropdown + { + private DropdownMenu menu; + + protected override DropdownMenu CreateMenu() => menu = base.CreateMenu().With(m => m.MaxHeight = 400); + + [BackgroundDependencyLoader] + private void load(OverlayColourProvider colourProvider) + { + menu.BackgroundColour = colourProvider.Background5; + AccentColour = colourProvider.Background6; + } + } + } +}