1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-11 05:42:58 +08:00

Add search bar to collection management dialog

This commit is contained in:
Dean Herbert 2024-11-18 15:57:39 +09:00
parent a570863854
commit 5ce1f7679b
No known key found for this signature in database
4 changed files with 103 additions and 9 deletions

View File

@ -12,6 +12,7 @@ using osu.Framework.Platform;
using osu.Framework.Testing; using osu.Framework.Testing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Collections; using osu.Game.Collections;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Dialog; using osu.Game.Overlays.Dialog;
using osu.Game.Rulesets; using osu.Game.Rulesets;
@ -265,7 +266,6 @@ namespace osu.Game.Tests.Visual.Collections
} }
[Test] [Test]
[Solo]
public void TestCollectionRenamedExternal() public void TestCollectionRenamedExternal()
{ {
BeatmapCollection first = null!; BeatmapCollection first = null!;
@ -338,10 +338,44 @@ namespace osu.Game.Tests.Visual.Collections
AddUntilStep("collection has new name", () => first.Name == "First"); AddUntilStep("collection has new name", () => first.Name == "First");
} }
[Test]
public void TestSearch()
{
BeatmapCollection first = null!;
AddStep("add two collections", () =>
{
Realm.Write(r =>
{
r.Add(new[]
{
first = new BeatmapCollection(name: "1"),
new BeatmapCollection(name: "2"),
});
});
});
assertCollectionName(0, "1");
assertCollectionName(1, "2");
AddStep("search for 1", () => dialog.ChildrenOfType<SearchTextBox>().Single().Current.Value = "1");
assertCollectionCount(1);
AddStep("change first collection name", () => Realm.Write(_ => first.Name = "First"));
assertCollectionCount(0);
AddStep("search for first", () => dialog.ChildrenOfType<SearchTextBox>().Single().Current.Value = "firs");
assertCollectionCount(1);
}
private void assertCollectionCount(int count) private void assertCollectionCount(int count)
=> AddUntilStep($"{count} collections shown", () => dialog.ChildrenOfType<DrawableCollectionListItem>().Count() == count + 1); // +1 for placeholder => AddUntilStep($"{count} collections shown", () => dialog.ChildrenOfType<DrawableCollectionListItem>().Count(i => i.IsPresent) == count + 1); // +1 for placeholder
private void assertCollectionName(int index, string name) private void assertCollectionName(int index, string name)
=> AddUntilStep($"item {index + 1} has correct name", () => dialog.ChildrenOfType<DrawableCollectionList>().Single().OrderedItems.ElementAt(index).ChildrenOfType<TextBox>().First().Text == name); => AddUntilStep($"item {index + 1} has correct name",
() => dialog.ChildrenOfType<DrawableCollectionList>().Single().OrderedItems.ElementAt(index).ChildrenOfType<TextBox>().First().Text == name);
} }
} }

View File

@ -34,6 +34,12 @@ namespace osu.Game.Collections
public IEnumerable<Drawable> OrderedItems => flow.FlowingChildren; public IEnumerable<Drawable> OrderedItems => flow.FlowingChildren;
public string SearchTerm
{
get => flow.SearchTerm;
set => flow.SearchTerm = value;
}
protected override FillFlowContainer<RearrangeableListItem<Live<BeatmapCollection>>> CreateListFillFlowContainer() => flow = new Flow protected override FillFlowContainer<RearrangeableListItem<Live<BeatmapCollection>>> CreateListFillFlowContainer() => flow = new Flow
{ {
DragActive = { BindTarget = DragActive } DragActive = { BindTarget = DragActive }
@ -128,7 +134,6 @@ namespace osu.Game.Collections
public Scroll() public Scroll()
{ {
Padding = new MarginPadding(10);
ScrollbarOverlapsContent = false; ScrollbarOverlapsContent = false;
base.Content.Add(new FillFlowContainer base.Content.Add(new FillFlowContainer
@ -157,7 +162,7 @@ namespace osu.Game.Collections
base.Update(); base.Update();
// AutoSizeAxes cannot be used as the height should represent the post-layout-transform height at all times, so that the placeholder doesn't bounce around. // AutoSizeAxes cannot be used as the height should represent the post-layout-transform height at all times, so that the placeholder doesn't bounce around.
content.Height = ((Flow)Child).Children.Sum(c => c.DrawHeight + 5); content.Height = ((Flow)Child).Children.Sum(c => c.IsPresent ? c.DrawHeight + 5 : 0);
} }
/// <summary> /// <summary>
@ -203,7 +208,7 @@ namespace osu.Game.Collections
/// <summary> /// <summary>
/// The flow of <see cref="DrawableCollectionListItem"/>. Disables layout easing unless a drag is in progress. /// The flow of <see cref="DrawableCollectionListItem"/>. Disables layout easing unless a drag is in progress.
/// </summary> /// </summary>
private partial class Flow : FillFlowContainer<RearrangeableListItem<Live<BeatmapCollection>>> private partial class Flow : SearchContainer<RearrangeableListItem<Live<BeatmapCollection>>>
{ {
public readonly IBindable<bool> DragActive = new Bindable<bool>(); public readonly IBindable<bool> DragActive = new Bindable<bool>();

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Collections.Generic;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
@ -10,6 +11,7 @@ using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.UserInterface; using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events; using osu.Framework.Input.Events;
using osu.Framework.Localisation;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Containers; using osu.Game.Graphics.Containers;
@ -23,7 +25,7 @@ namespace osu.Game.Collections
/// <summary> /// <summary>
/// Visualises a <see cref="BeatmapCollection"/> inside a <see cref="DrawableCollectionList"/>. /// Visualises a <see cref="BeatmapCollection"/> inside a <see cref="DrawableCollectionList"/>.
/// </summary> /// </summary>
public partial class DrawableCollectionListItem : OsuRearrangeableListItem<Live<BeatmapCollection>> public partial class DrawableCollectionListItem : OsuRearrangeableListItem<Live<BeatmapCollection>>, IFilterable
{ {
private const float item_height = 35; private const float item_height = 35;
private const float button_width = item_height * 0.75f; private const float button_width = item_height * 0.75f;
@ -207,5 +209,25 @@ namespace osu.Game.Collections
private void deleteCollection() => collection.PerformWrite(c => c.Realm!.Remove(c)); private void deleteCollection() => collection.PerformWrite(c => c.Realm!.Remove(c));
} }
public IEnumerable<LocalisableString> FilterTerms => [(LocalisableString)Model.Value.Name];
private bool matchingFilter = true;
public bool MatchingFilter
{
get => matchingFilter;
set
{
matchingFilter = value;
if (matchingFilter)
this.FadeIn(200);
else
Hide();
}
}
public bool FilteringActive { get; set; }
} }
} }

View File

@ -12,6 +12,7 @@ using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Graphics.UserInterface; using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Resources.Localisation.Web;
using osuTK; using osuTK;
namespace osu.Game.Collections namespace osu.Game.Collections
@ -26,6 +27,9 @@ namespace osu.Game.Collections
private IDisposable? duckOperation; private IDisposable? duckOperation;
private BasicSearchTextBox searchTextBox = null!;
private DrawableCollectionList list = null!;
[Resolved] [Resolved]
private MusicController? musicController { get; set; } private MusicController? musicController { get; set; }
@ -104,10 +108,29 @@ namespace osu.Game.Collections
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Colour = colours.GreySeaFoamDarker Colour = colours.GreySeaFoamDarker
}, },
new DrawableCollectionList new FillFlowContainer
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
} Direction = FillDirection.Vertical,
Padding = new MarginPadding(10),
Spacing = new Vector2(0, 10),
Children = new Drawable[]
{
searchTextBox = new BasicSearchTextBox
{
RelativeSizeAxes = Axes.X,
Y = 10,
Height = 40,
ReleaseFocusOnCommit = false,
HoldFocus = true,
PlaceholderText = HomeStrings.SearchPlaceholder,
},
list = new DrawableCollectionList
{
RelativeSizeAxes = Axes.Both,
}
}
},
} }
} }
}, },
@ -117,6 +140,16 @@ namespace osu.Game.Collections
}; };
} }
protected override void LoadComplete()
{
base.LoadComplete();
searchTextBox.Current.BindValueChanged(_ =>
{
list.SearchTerm = searchTextBox.Current.Value;
});
}
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {
base.Dispose(isDisposing); base.Dispose(isDisposing);