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

Merge pull request #30616 from peppy/collection-management-revamp

Fix collection management dialog refreshing full display when any change occurs
This commit is contained in:
Bartłomiej Dach 2024-11-14 13:21:09 +01:00 committed by GitHub
commit 7ee9802923
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 73 additions and 24 deletions

View File

@ -205,7 +205,9 @@ namespace osu.Game.Tests.Visual.Collections
AddStep("click first delete button", () =>
{
InputManager.MoveMouseTo(dialog.ChildrenOfType<DrawableCollectionListItem.DeleteButton>().First(), new Vector2(5, 0));
InputManager.MoveMouseTo(dialog
.ChildrenOfType<DrawableCollectionListItem>().Single(i => i.Model.Value.Name == "1")
.ChildrenOfType<DrawableCollectionListItem.DeleteButton>().Single(), new Vector2(5, 0));
InputManager.Click(MouseButton.Left);
});
@ -213,9 +215,11 @@ namespace osu.Game.Tests.Visual.Collections
assertCollectionCount(1);
assertCollectionName(0, "2");
AddStep("click first delete button", () =>
AddStep("click second delete button", () =>
{
InputManager.MoveMouseTo(dialog.ChildrenOfType<DrawableCollectionListItem.DeleteButton>().First(), new Vector2(5, 0));
InputManager.MoveMouseTo(dialog
.ChildrenOfType<DrawableCollectionListItem>().Single(i => i.Model.Value.Name == "2")
.ChildrenOfType<DrawableCollectionListItem.DeleteButton>().Single(), new Vector2(5, 0));
InputManager.Click(MouseButton.Left);
});
@ -261,6 +265,7 @@ namespace osu.Game.Tests.Visual.Collections
}
[Test]
[Solo]
public void TestCollectionRenamedExternal()
{
BeatmapCollection first = null!;
@ -310,7 +315,7 @@ namespace osu.Game.Tests.Visual.Collections
AddStep("focus first collection", () =>
{
InputManager.MoveMouseTo(firstItem = dialog.ChildrenOfType<DrawableCollectionListItem>().First());
InputManager.MoveMouseTo(firstItem = dialog.ChildrenOfType<DrawableCollectionListItem>().Single(i => i.Model.Value.Name == "1"));
InputManager.Click(MouseButton.Left);
});
@ -337,6 +342,6 @@ namespace osu.Game.Tests.Visual.Collections
=> AddUntilStep($"{count} collections shown", () => dialog.ChildrenOfType<DrawableCollectionListItem>().Count() == count + 1); // +1 for placeholder
private void assertCollectionName(int index, string name)
=> AddUntilStep($"item {index + 1} has correct name", () => dialog.ChildrenOfType<DrawableCollectionListItem>().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

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
@ -29,7 +30,11 @@ namespace osu.Game.Collections
private IDisposable? realmSubscription;
protected override FillFlowContainer<RearrangeableListItem<Live<BeatmapCollection>>> CreateListFillFlowContainer() => new Flow
private Flow flow = null!;
public IEnumerable<Drawable> OrderedItems => flow.FlowingChildren;
protected override FillFlowContainer<RearrangeableListItem<Live<BeatmapCollection>>> CreateListFillFlowContainer() => flow = new Flow
{
DragActive = { BindTarget = DragActive }
};
@ -43,8 +48,25 @@ namespace osu.Game.Collections
private void collectionsChanged(IRealmCollection<BeatmapCollection> collections, ChangeSet? changes)
{
Items.Clear();
Items.AddRange(collections.AsEnumerable().Select(c => c.ToLive(realm)));
if (changes == null)
{
Items.AddRange(collections.AsEnumerable().Select(c => c.ToLive(realm)));
return;
}
foreach (int i in changes.DeletedIndices.OrderDescending())
Items.RemoveAt(i);
foreach (int i in changes.InsertedIndices)
Items.Insert(i, collections[i].ToLive(realm));
foreach (int i in changes.NewModifiedIndices)
{
var updatedItem = collections[i];
Items.RemoveAt(i);
Items.Insert(i, updatedItem.ToLive(realm));
}
}
protected override OsuRearrangeableListItem<Live<BeatmapCollection>> CreateOsuDrawable(Live<BeatmapCollection> item)
@ -123,12 +145,37 @@ namespace osu.Game.Collections
var previous = PlaceholderItem;
placeholderContainer.Clear(false);
placeholderContainer.Add(PlaceholderItem = new DrawableCollectionListItem(new BeatmapCollection().ToLiveUnmanaged(), false));
placeholderContainer.Add(PlaceholderItem = new NewCollectionEntryItem());
return previous;
}
}
private partial class NewCollectionEntryItem : DrawableCollectionListItem
{
[Resolved]
private RealmAccess realm { get; set; } = null!;
public NewCollectionEntryItem()
: base(new BeatmapCollection().ToLiveUnmanaged(), false)
{
}
protected override void LoadComplete()
{
base.LoadComplete();
TextBox.OnCommit += (sender, newText) =>
{
if (string.IsNullOrEmpty(TextBox.Text))
return;
realm.Write(r => r.Add(new BeatmapCollection(TextBox.Text)));
TextBox.Text = string.Empty;
};
}
}
/// <summary>
/// The flow of <see cref="DrawableCollectionListItem"/>. Disables layout easing unless a drag is in progress.
/// </summary>

View File

@ -28,6 +28,10 @@ namespace osu.Game.Collections
private const float item_height = 35;
private const float button_width = item_height * 0.75f;
protected TextBox TextBox => content.TextBox;
private ItemContent content = null!;
/// <summary>
/// Creates a new <see cref="DrawableCollectionListItem"/>.
/// </summary>
@ -48,7 +52,7 @@ namespace osu.Game.Collections
CornerRadius = item_height / 2;
}
protected override Drawable CreateContent() => new ItemContent(Model);
protected override Drawable CreateContent() => content = new ItemContent(Model);
/// <summary>
/// The main content of the <see cref="DrawableCollectionListItem"/>.
@ -57,10 +61,7 @@ namespace osu.Game.Collections
{
private readonly Live<BeatmapCollection> collection;
private ItemTextBox textBox = null!;
[Resolved]
private RealmAccess realm { get; set; } = null!;
public ItemTextBox TextBox { get; private set; } = null!;
public ItemContent(Live<BeatmapCollection> collection)
{
@ -80,7 +81,7 @@ namespace osu.Game.Collections
{
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
IsTextBoxHovered = v => textBox.ReceivePositionalInputAt(v)
IsTextBoxHovered = v => TextBox.ReceivePositionalInputAt(v)
}
: Empty(),
new Container
@ -89,7 +90,7 @@ namespace osu.Game.Collections
Padding = new MarginPadding { Right = collection.IsManaged ? button_width : 0 },
Children = new Drawable[]
{
textBox = new ItemTextBox
TextBox = new ItemTextBox
{
RelativeSizeAxes = Axes.Both,
Size = Vector2.One,
@ -107,18 +108,14 @@ namespace osu.Game.Collections
base.LoadComplete();
// Bind late, as the collection name may change externally while still loading.
textBox.Current.Value = collection.PerformRead(c => c.IsValid ? c.Name : string.Empty);
textBox.OnCommit += onCommit;
TextBox.Current.Value = collection.PerformRead(c => c.IsValid ? c.Name : string.Empty);
TextBox.OnCommit += onCommit;
}
private void onCommit(TextBox sender, bool newText)
{
if (collection.IsManaged)
collection.PerformWrite(c => c.Name = textBox.Current.Value);
else if (!string.IsNullOrEmpty(textBox.Current.Value))
realm.Write(r => r.Add(new BeatmapCollection(textBox.Current.Value)));
textBox.Text = string.Empty;
if (collection.IsManaged && collection.Value.Name != TextBox.Current.Value)
collection.PerformWrite(c => c.Name = TextBox.Current.Value);
}
}