1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-22 17:12:54 +08:00

Merge pull request #16094 from peppy/beatmap-card-expanded-state-fix

Fix beatmap card potentially collapsing when it shouldn't
This commit is contained in:
Dean Herbert 2021-12-16 14:13:47 +09:00 committed by GitHub
commit e6e1366c28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 63 deletions

View File

@ -6,12 +6,12 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Beatmaps.Drawables.Cards; using osu.Game.Beatmaps.Drawables.Cards;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
using osu.Game.Online.API; using osu.Game.Online.API;
@ -19,11 +19,10 @@ using osu.Game.Online.API.Requests;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Overlays; using osu.Game.Overlays;
using osuTK; using osuTK;
using APIUser = osu.Game.Online.API.Requests.Responses.APIUser;
namespace osu.Game.Tests.Visual.Beatmaps namespace osu.Game.Tests.Visual.Beatmaps
{ {
public class TestSceneBeatmapCard : OsuTestScene public class TestSceneBeatmapCard : OsuManualInputManagerTestScene
{ {
/// <summary> /// <summary>
/// All cards on this scene use a common online ID to ensure that map download, preview tracks, etc. can be tested manually with online sources. /// All cards on this scene use a common online ID to ensure that map download, preview tracks, etc. can be tested manually with online sources.
@ -253,14 +252,32 @@ namespace osu.Game.Tests.Visual.Beatmaps
public void TestNormal() public void TestNormal()
{ {
createTestCase(beatmapSetInfo => new BeatmapCard(beatmapSetInfo)); createTestCase(beatmapSetInfo => new BeatmapCard(beatmapSetInfo));
}
AddToggleStep("toggle expanded state", expanded => [Test]
{ public void TestHoverState()
var card = this.ChildrenOfType<BeatmapCard>().Last(); {
if (!card.Expanded.Disabled) AddStep("create cards", () => Child = createContent(OverlayColourScheme.Blue, s => new BeatmapCard(s)));
card.Expanded.Value = expanded;
}); AddStep("Hover card", () => InputManager.MoveMouseTo(firstCard()));
AddToggleStep("disable/enable expansion", disabled => this.ChildrenOfType<BeatmapCard>().ForEach(card => card.Expanded.Disabled = disabled)); AddWaitStep("wait for potential state change", 5);
AddAssert("card is not expanded", () => !firstCard().Expanded.Value);
AddStep("Hover spectrum display", () => InputManager.MoveMouseTo(firstCard().ChildrenOfType<DifficultySpectrumDisplay>().Single()));
AddUntilStep("card is expanded", () => firstCard().Expanded.Value);
AddStep("Hover difficulty content", () => InputManager.MoveMouseTo(firstCard().ChildrenOfType<BeatmapCardDifficultyList>().Single()));
AddWaitStep("wait for potential state change", 5);
AddAssert("card is still expanded", () => firstCard().Expanded.Value);
AddStep("Hover main content again", () => InputManager.MoveMouseTo(firstCard()));
AddWaitStep("wait for potential state change", 5);
AddAssert("card is still expanded", () => firstCard().Expanded.Value);
AddStep("Hover away", () => InputManager.MoveMouseTo(this.ChildrenOfType<BeatmapCard>().Last()));
AddUntilStep("card is not expanded", () => !firstCard().Expanded.Value);
BeatmapCard firstCard() => this.ChildrenOfType<BeatmapCard>().First();
} }
} }
} }

View File

@ -33,7 +33,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
public const float TRANSITION_DURATION = 400; public const float TRANSITION_DURATION = 400;
public const float CORNER_RADIUS = 10; public const float CORNER_RADIUS = 10;
public Bindable<bool> Expanded { get; } = new BindableBool(); public IBindable<bool> Expanded { get; }
private const float width = 408; private const float width = 408;
private const float height = 100; private const float height = 100;
@ -64,9 +64,11 @@ namespace osu.Game.Beatmaps.Drawables.Cards
[Resolved] [Resolved]
private OverlayColourProvider colourProvider { get; set; } = null!; private OverlayColourProvider colourProvider { get; set; } = null!;
public BeatmapCard(APIBeatmapSet beatmapSet) public BeatmapCard(APIBeatmapSet beatmapSet, bool allowExpansion = true)
: base(HoverSampleSet.Submit) : base(HoverSampleSet.Submit)
{ {
Expanded = new BindableBool { Disabled = !allowExpansion };
this.beatmapSet = beatmapSet; this.beatmapSet = beatmapSet;
favouriteState = new Bindable<BeatmapSetFavouriteState>(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount)); favouriteState = new Bindable<BeatmapSetFavouriteState>(new BeatmapSetFavouriteState(beatmapSet.HasFavourited, beatmapSet.FavouriteCount));
downloadTracker = new BeatmapDownloadTracker(beatmapSet); downloadTracker = new BeatmapDownloadTracker(beatmapSet);
@ -282,15 +284,15 @@ namespace osu.Game.Beatmaps.Drawables.Cards
{ {
Hovered = _ => Hovered = _ =>
{ {
content.ScheduleShow(); content.ExpandAfterDelay();
return false; return false;
}, },
Unhovered = _ => Unhovered = _ =>
{ {
// This hide should only trigger if the expanded content has not shown yet. // Handles the case where a user has not shown explicit intent to view expanded info.
// ie. if the user has not shown intent to want to see it (quickly moved over the info row area). // ie. quickly moved over the info row area but didn't remain within it.
if (!Expanded.Value) if (!Expanded.Value)
content.ScheduleHide(); content.CancelExpand();
} }
} }
} }
@ -366,8 +368,6 @@ namespace osu.Game.Beatmaps.Drawables.Cards
protected override void OnHoverLost(HoverLostEvent e) protected override void OnHoverLost(HoverLostEvent e)
{ {
content.ScheduleHide();
updateState(); updateState();
base.OnHoverLost(e); base.OnHoverLost(e);
} }

View File

@ -31,7 +31,9 @@ namespace osu.Game.Beatmaps.Drawables.Cards
set => dropdownScroll.Child = value; set => dropdownScroll.Child = value;
} }
public Bindable<bool> Expanded { get; } = new BindableBool(); public IBindable<bool> Expanded => expanded;
private readonly BindableBool expanded = new BindableBool();
private readonly Box background; private readonly Box background;
private readonly Container content; private readonly Container content;
@ -54,7 +56,7 @@ namespace osu.Game.Beatmaps.Drawables.Cards
AutoSizeAxes = Axes.Y, AutoSizeAxes = Axes.Y,
CornerRadius = BeatmapCard.CORNER_RADIUS, CornerRadius = BeatmapCard.CORNER_RADIUS,
Masking = true, Masking = true,
Unhovered = _ => checkForHide(), Unhovered = _ => updateFromHoverChange(),
Children = new Drawable[] Children = new Drawable[]
{ {
background = new Box background = new Box
@ -76,10 +78,10 @@ namespace osu.Game.Beatmaps.Drawables.Cards
Alpha = 0, Alpha = 0,
Hovered = _ => Hovered = _ =>
{ {
keep(); updateFromHoverChange();
return true; return true;
}, },
Unhovered = _ => checkForHide(), Unhovered = _ => updateFromHoverChange(),
Child = dropdownScroll = new ExpandedContentScrollContainer Child = dropdownScroll = new ExpandedContentScrollContainer
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
@ -119,51 +121,20 @@ namespace osu.Game.Beatmaps.Drawables.Cards
private ScheduledDelegate? scheduledExpandedChange; private ScheduledDelegate? scheduledExpandedChange;
public void ScheduleShow() public void ExpandAfterDelay() => queueExpandedStateChange(true, 100);
{
scheduledExpandedChange?.Cancel();
if (Expanded.Disabled || Expanded.Value)
return;
scheduledExpandedChange = Scheduler.AddDelayed(() => public void CancelExpand() => scheduledExpandedChange?.Cancel();
{
if (!Expanded.Disabled)
Expanded.Value = true;
}, 100);
}
public void ScheduleHide() private void updateFromHoverChange() =>
{ queueExpandedStateChange(content.IsHovered || dropdownContent.IsHovered, 100);
scheduledExpandedChange?.Cancel();
if (Expanded.Disabled || !Expanded.Value)
return;
scheduledExpandedChange = Scheduler.AddDelayed(() => private void queueExpandedStateChange(bool newState, int delay = 0)
{
if (!Expanded.Disabled)
Expanded.Value = false;
}, 500);
}
private void checkForHide()
{
if (Expanded.Disabled)
return;
if (content.IsHovered || dropdownContent.IsHovered)
return;
scheduledExpandedChange?.Cancel();
Expanded.Value = false;
}
private void keep()
{ {
if (Expanded.Disabled) if (Expanded.Disabled)
return; return;
scheduledExpandedChange?.Cancel(); scheduledExpandedChange?.Cancel();
Expanded.Value = true; scheduledExpandedChange = Scheduler.AddDelayed(() => expanded.Value = newState, delay);
} }
private void updateState() private void updateState()

View File

@ -228,10 +228,7 @@ namespace osu.Game.Screens.Play
onlineBeatmapRequest.Success += beatmapSet => Schedule(() => onlineBeatmapRequest.Success += beatmapSet => Schedule(() =>
{ {
this.beatmapSet = beatmapSet; this.beatmapSet = beatmapSet;
beatmapPanelContainer.Child = new BeatmapCard(this.beatmapSet) beatmapPanelContainer.Child = new BeatmapCard(this.beatmapSet, allowExpansion: false);
{
Expanded = { Disabled = true }
};
checkForAutomaticDownload(); checkForAutomaticDownload();
}); });