1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-06 06:57:39 +08:00

Add initial implementation of beatmap carousel no-results-placeholder

This commit is contained in:
Dean Herbert 2022-06-07 16:32:15 +09:00
parent df9174ec00
commit 0d32c94104
3 changed files with 170 additions and 1 deletions

View File

@ -18,6 +18,7 @@ using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Chat;
using osu.Game.Overlays;
using osu.Game.Overlays.Mods;
using osu.Game.Rulesets;
@ -80,6 +81,37 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("delete all beatmaps", () => manager?.Delete());
}
[Test]
public void TestPlaceholderBeatmapPresence()
{
createSongSelect();
AddUntilStep("wait for placeholder visible", () => getPlaceholder()?.State.Value == Visibility.Visible);
addRulesetImportStep(0);
AddUntilStep("wait for placeholder hidden", () => getPlaceholder()?.State.Value == Visibility.Hidden);
AddStep("delete all beatmaps", () => manager?.Delete());
AddUntilStep("wait for placeholder visible", () => getPlaceholder()?.State.Value == Visibility.Visible);
}
[Test]
public void TestPlaceholderConvertSetting()
{
changeRuleset(2);
addRulesetImportStep(0);
AddStep("change convert setting", () => config.SetValue(OsuSetting.ShowConvertedBeatmaps, false));
createSongSelect();
AddUntilStep("wait for placeholder visible", () => getPlaceholder()?.State.Value == Visibility.Visible);
AddStep("click link in placeholder", () => getPlaceholder().ChildrenOfType<DrawableLinkCompiler>().First().TriggerClick());
AddUntilStep("convert setting changed", () => config.Get<bool>(OsuSetting.ShowConvertedBeatmaps));
AddUntilStep("wait for placeholder visible", () => getPlaceholder()?.State.Value == Visibility.Hidden);
}
[Test]
public void TestSingleFilterOnEnter()
{
@ -941,6 +973,8 @@ namespace osu.Game.Tests.Visual.SongSelect
private int getBeatmapIndex(BeatmapSetInfo set, BeatmapInfo info) => set.Beatmaps.IndexOf(info);
private NoResultsPlaceholder getPlaceholder() => songSelect.ChildrenOfType<NoResultsPlaceholder>().FirstOrDefault();
private int getCurrentBeatmapIndex() => getBeatmapIndex(songSelect.Carousel.SelectedBeatmapSet, songSelect.Carousel.SelectedBeatmapInfo);
private int getDifficultyIconIndex(DrawableCarouselBeatmapSet set, FilterableDifficultyIcon icon)

View File

@ -97,6 +97,8 @@ namespace osu.Game.Screens.Select
protected readonly CarouselScrollContainer Scroll;
private readonly NoResultsPlaceholder noResultsPlaceholder;
private IEnumerable<CarouselBeatmapSet> beatmapSets => root.Children.OfType<CarouselBeatmapSet>();
// todo: only used for testing, maybe remove.
@ -170,7 +172,8 @@ namespace osu.Game.Screens.Select
Scroll = new CarouselScrollContainer
{
RelativeSizeAxes = Axes.Both,
}
},
noResultsPlaceholder = new NoResultsPlaceholder()
}
};
}
@ -648,8 +651,18 @@ namespace osu.Game.Screens.Select
// First we iterate over all non-filtered carousel items and populate their
// vertical position data.
if (revalidateItems)
{
updateYPositions();
if (visibleItems.Count == 0)
{
noResultsPlaceholder.Filter = activeCriteria;
noResultsPlaceholder.Show();
}
else
noResultsPlaceholder.Hide();
}
// if there is a pending scroll action we apply it without animation and transfer the difference in position to the panels.
// this is intentionally applied before updating the visible range below, to avoid animating new items (sourced from pool) from locations off-screen, as it looks bad.
if (pendingScrollOperation != PendingScrollOperation.None)

View File

@ -0,0 +1,122 @@
// 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.
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Online.Chat;
using osu.Game.Overlays;
using osuTK;
namespace osu.Game.Screens.Select
{
public class NoResultsPlaceholder : CompositeDrawable
{
private FilterCriteria filter;
private LinkFlowContainer textFlow;
[Resolved]
private BeatmapManager beatmaps { get; set; }
[Resolved(CanBeNull = true)]
private FirstRunSetupOverlay firstRunSetupOverlay { get; set; }
public FilterCriteria Filter
{
get => filter;
set
{
filter = value;
Scheduler.AddOnce(updateText);
}
}
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
Masking = true;
CornerRadius = 10;
Width = 300;
AutoSizeAxes = Axes.Y;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
InternalChildren = new Drawable[]
{
new Box
{
Colour = colours.Gray2,
RelativeSizeAxes = Axes.Both,
},
new SpriteIcon
{
Icon = FontAwesome.Regular.QuestionCircle,
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
Margin = new MarginPadding(10),
Size = new Vector2(50),
},
textFlow = new LinkFlowContainer
{
Y = 70,
Padding = new MarginPadding(10),
TextAnchor = Anchor.TopCentre,
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
}
};
}
public override void Show()
{
this.FadeIn(600, Easing.OutQuint);
this.ScaleTo(0.8f)
.ScaleTo(1f, 1000, Easing.OutElastic);
Scheduler.AddOnce(updateText);
}
public override void Hide()
{
this.FadeOut(200, Easing.OutQuint);
}
private void updateText()
{
textFlow.Clear();
if (beatmaps.QueryBeatmapSet(s => !s.Protected && !s.DeletePending) == null)
{
textFlow.AddParagraph("No beatmaps found!");
textFlow.AddParagraph(string.Empty);
textFlow.AddParagraph("Consider running the ");
textFlow.AddLink("first run setup", () => firstRunSetupOverlay?.Show());
textFlow.AddText(" to load or import some beatmaps!");
}
else
{
textFlow.AddParagraph("No beatmaps match your filter criteria!");
textFlow.AddParagraph(string.Empty);
// TODO: hint when beatmaps are available in another ruleset
// TODO: hint when beatmaps are available by toggling "show converted".
if (!string.IsNullOrEmpty(filter?.SearchText))
{
textFlow.AddParagraph("You can try ");
textFlow.AddLink("searching online", LinkAction.SearchBeatmapSet, filter.SearchText);
textFlow.AddText(" for this query.");
}
}
}
}
}