diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs index acf037198f..06572f66bf 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapDetails.cs @@ -5,6 +5,7 @@ using System.Linq; using NUnit.Framework; using osu.Framework.Graphics; using osu.Game.Beatmaps; +using osu.Game.Online.API; using osu.Game.Screens.Select; namespace osu.Game.Tests.Visual.SongSelect @@ -14,6 +15,8 @@ namespace osu.Game.Tests.Visual.SongSelect { private BeatmapDetails details; + private DummyAPIAccess api => (DummyAPIAccess)API; + [SetUp] public void Setup() => Schedule(() => { @@ -173,6 +176,8 @@ namespace osu.Game.Tests.Visual.SongSelect { OnlineBeatmapID = 162, }); + AddStep("set online", () => api.SetState(APIState.Online)); + AddStep("set offline", () => api.SetState(APIState.Offline)); } } } diff --git a/osu.Game/Online/OnlineViewContainer.cs b/osu.Game/Online/OnlineViewContainer.cs index 8868f90524..4955aa9058 100644 --- a/osu.Game/Online/OnlineViewContainer.cs +++ b/osu.Game/Online/OnlineViewContainer.cs @@ -23,13 +23,17 @@ namespace osu.Game.Online private readonly string placeholderMessage; - private Placeholder placeholder; + private Drawable placeholder; private const double transform_duration = 300; [Resolved] protected IAPIProvider API { get; private set; } + /// + /// Construct a new instance of an online view container. + /// + /// The message to display when not logged in. If empty, no button will display. public OnlineViewContainer(string placeholderMessage) { this.placeholderMessage = placeholderMessage; @@ -40,10 +44,10 @@ namespace osu.Game.Online [BackgroundDependencyLoader] private void load(IAPIProvider api) { - InternalChildren = new Drawable[] + InternalChildren = new[] { Content, - placeholder = new LoginPlaceholder(placeholderMessage), + placeholder = string.IsNullOrEmpty(placeholderMessage) ? Empty() : new LoginPlaceholder(placeholderMessage), LoadingSpinner = new LoadingSpinner { Alpha = 0, diff --git a/osu.Game/Screens/Select/BeatmapDetails.cs b/osu.Game/Screens/Select/BeatmapDetails.cs index 8a1c291fca..26da4279f0 100644 --- a/osu.Game/Screens/Select/BeatmapDetails.cs +++ b/osu.Game/Screens/Select/BeatmapDetails.cs @@ -9,7 +9,6 @@ using osu.Framework.Graphics.Containers; using osu.Game.Graphics.Sprites; using System.Linq; using osu.Game.Online.API; -using osu.Framework.Threading; using osu.Framework.Graphics.Shapes; using osu.Framework.Extensions.Color4Extensions; using osu.Game.Screens.Select.Details; @@ -19,6 +18,7 @@ using osu.Game.Graphics.Containers; using osu.Game.Graphics.UserInterface; using osu.Game.Online.API.Requests; using osu.Game.Rulesets; +using osu.Game.Online; namespace osu.Game.Screens.Select { @@ -27,11 +27,8 @@ namespace osu.Game.Screens.Select private const float spacing = 10; private const float transition_duration = 250; - private readonly FillFlowContainer top, statsFlow; private readonly AdvancedStats advanced; - private readonly DetailBox ratingsContainer; private readonly UserRatings ratings; - private readonly OsuScrollContainer metadataScroll; private readonly MetadataSection description, source, tags; private readonly Container failRetryContainer; private readonly FailRetryGraph failRetryGraph; @@ -40,8 +37,6 @@ namespace osu.Game.Screens.Select [Resolved] private IAPIProvider api { get; set; } - private ScheduledDelegate pendingBeatmapSwitch; - [Resolved] private RulesetStore rulesets { get; set; } @@ -56,8 +51,7 @@ namespace osu.Game.Screens.Select beatmap = value; - pendingBeatmapSwitch?.Cancel(); - pendingBeatmapSwitch = Schedule(updateStatistics); + Scheduler.AddOnce(updateStatistics); } } @@ -76,99 +70,105 @@ namespace osu.Game.Screens.Select Padding = new MarginPadding { Horizontal = spacing }, Children = new Drawable[] { - top = new FillFlowContainer + new GridContainer { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Horizontal, - Children = new Drawable[] + RelativeSizeAxes = Axes.Both, + RowDimensions = new[] { - statsFlow = new FillFlowContainer + new Dimension(GridSizeMode.AutoSize), + new Dimension() + }, + Content = new[] + { + new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Width = 0.5f, - Spacing = new Vector2(spacing), - Padding = new MarginPadding { Right = spacing / 2 }, - Children = new[] - { - new DetailBox - { - Child = advanced = new AdvancedStats - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Horizontal = spacing, Top = spacing * 2, Bottom = spacing }, - }, - }, - ratingsContainer = new DetailBox - { - Child = ratings = new UserRatings - { - RelativeSizeAxes = Axes.X, - Height = 134, - Padding = new MarginPadding { Horizontal = spacing, Top = spacing }, - }, - }, - }, - }, - metadataScroll = new OsuScrollContainer - { - RelativeSizeAxes = Axes.X, - Width = 0.5f, - ScrollbarVisible = false, - Padding = new MarginPadding { Left = spacing / 2 }, - Child = new FillFlowContainer + new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - LayoutDuration = transition_duration, - LayoutEasing = Easing.OutQuad, - Spacing = new Vector2(spacing * 2), - Margin = new MarginPadding { Top = spacing * 2 }, - Children = new[] + Direction = FillDirection.Horizontal, + Children = new Drawable[] { - description = new MetadataSection("Description"), - source = new MetadataSection("Source"), - tags = new MetadataSection("Tags"), + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Width = 0.5f, + Spacing = new Vector2(spacing), + Padding = new MarginPadding { Right = spacing / 2 }, + Children = new[] + { + new DetailBox().WithChild(advanced = new AdvancedStats + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Horizontal = spacing, Top = spacing * 2, Bottom = spacing }, + }), + new DetailBox().WithChild(new OnlineViewContainer(string.Empty) + { + RelativeSizeAxes = Axes.X, + Height = 134, + Padding = new MarginPadding { Horizontal = spacing, Top = spacing }, + Child = ratings = new UserRatings + { + RelativeSizeAxes = Axes.Both, + }, + }), + }, + }, + new OsuScrollContainer + { + RelativeSizeAxes = Axes.Both, + Width = 0.5f, + ScrollbarVisible = false, + Padding = new MarginPadding { Left = spacing / 2 }, + Child = new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + LayoutDuration = transition_duration, + LayoutEasing = Easing.OutQuad, + Spacing = new Vector2(spacing * 2), + Margin = new MarginPadding { Top = spacing * 2 }, + Children = new[] + { + description = new MetadataSection("Description"), + source = new MetadataSection("Source"), + tags = new MetadataSection("Tags"), + }, + }, + }, }, }, }, - }, - }, - failRetryContainer = new Container - { - Anchor = Anchor.BottomLeft, - Origin = Anchor.BottomLeft, - RelativeSizeAxes = Axes.X, - Children = new Drawable[] - { - new OsuSpriteText + new Drawable[] { - Text = "Points of Failure", - Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), - }, - failRetryGraph = new FailRetryGraph - { - RelativeSizeAxes = Axes.Both, - Padding = new MarginPadding { Top = 14 + spacing / 2 }, - }, - }, + failRetryContainer = new OnlineViewContainer("Sign in to view more details") + { + RelativeSizeAxes = Axes.Both, + Children = new Drawable[] + { + new OsuSpriteText + { + Text = "Points of Failure", + Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 14), + }, + failRetryGraph = new FailRetryGraph + { + RelativeSizeAxes = Axes.Both, + Padding = new MarginPadding { Top = 14 + spacing / 2 }, + }, + }, + }, + } + } }, }, }, - loading = new LoadingLayer(true), + loading = new LoadingLayer(true) }; } - protected override void UpdateAfterChildren() - { - base.UpdateAfterChildren(); - - metadataScroll.Height = statsFlow.DrawHeight; - failRetryContainer.Height = DrawHeight - Padding.TotalVertical - (top.DrawHeight + spacing / 2); - } - private void updateStatistics() { advanced.Beatmap = Beatmap; @@ -184,7 +184,7 @@ namespace osu.Game.Screens.Select } // for now, let's early abort if an OnlineBeatmapID is not present (should have been populated at import time). - if (Beatmap?.OnlineBeatmapID == null) + if (Beatmap?.OnlineBeatmapID == null || api.State.Value == APIState.Offline) { updateMetrics(); return; @@ -239,12 +239,13 @@ namespace osu.Game.Screens.Select if (hasRatings) { ratings.Metrics = beatmap.BeatmapSet.Metrics; - ratingsContainer.FadeIn(transition_duration); + ratings.FadeIn(transition_duration); } else { + // loading or just has no data server-side. ratings.Metrics = new BeatmapSetMetrics { Ratings = new int[10] }; - ratingsContainer.FadeTo(0.25f, transition_duration); + ratings.FadeTo(0.25f, transition_duration); } if (hasRetriesFails) @@ -259,7 +260,6 @@ namespace osu.Game.Screens.Select Fails = new int[100], Retries = new int[100], }; - failRetryContainer.FadeOut(transition_duration); } loading.Hide();