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

Remove CollectionManager

This commit is contained in:
Dean Herbert 2022-07-27 15:59:36 +09:00
parent 6b73f7c7ec
commit 9c543fef48
19 changed files with 276 additions and 292 deletions

View File

@ -5,12 +5,14 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Extensions;
using osu.Framework.Platform;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Tests.Resources;
@ -30,7 +32,11 @@ namespace osu.Game.Tests.Collections.IO
await importCollectionsFromStream(osu, new MemoryStream());
Assert.That(osu.CollectionManager.Collections.Count, Is.Zero);
osu.Realm.Run(realm =>
{
var collections = realm.All<RealmBeatmapCollection>().ToList();
Assert.That(collections.Count, Is.Zero);
});
}
finally
{
@ -50,18 +56,22 @@ namespace osu.Game.Tests.Collections.IO
await importCollectionsFromStream(osu, TestResources.OpenResource("Collections/collections.db"));
Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(2));
osu.Realm.Run(realm =>
{
var collections = realm.All<RealmBeatmapCollection>().ToList();
Assert.That(collections.Count, Is.EqualTo(2));
// Even with no beatmaps imported, collections are tracking the hashes and will continue to.
// In the future this whole mechanism will be replaced with having the collections in realm,
// but until that happens it makes rough sense that we want to track not-yet-imported beatmaps
// and have them associate with collections if/when they become available.
// Even with no beatmaps imported, collections are tracking the hashes and will continue to.
// In the future this whole mechanism will be replaced with having the collections in realm,
// but until that happens it makes rough sense that we want to track not-yet-imported beatmaps
// and have them associate with collections if/when they become available.
Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First"));
Assert.That(osu.CollectionManager.Collections[0].BeatmapHashes.Count, Is.EqualTo(1));
Assert.That(collections[0].Name, Is.EqualTo("First"));
Assert.That(collections[0].BeatmapMD5Hashes.Count, Is.EqualTo(1));
Assert.That(osu.CollectionManager.Collections[1].Name.Value, Is.EqualTo("Second"));
Assert.That(osu.CollectionManager.Collections[1].BeatmapHashes.Count, Is.EqualTo(12));
Assert.That(collections[1].Name, Is.EqualTo("Second"));
Assert.That(collections[1].BeatmapMD5Hashes.Count, Is.EqualTo(12));
});
}
finally
{
@ -81,13 +91,18 @@ namespace osu.Game.Tests.Collections.IO
await importCollectionsFromStream(osu, TestResources.OpenResource("Collections/collections.db"));
Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(2));
osu.Realm.Run(realm =>
{
var collections = realm.All<RealmBeatmapCollection>().ToList();
Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First"));
Assert.That(osu.CollectionManager.Collections[0].BeatmapHashes.Count, Is.EqualTo(1));
Assert.That(collections.Count, Is.EqualTo(2));
Assert.That(osu.CollectionManager.Collections[1].Name.Value, Is.EqualTo("Second"));
Assert.That(osu.CollectionManager.Collections[1].BeatmapHashes.Count, Is.EqualTo(12));
Assert.That(collections[0].Name, Is.EqualTo("First"));
Assert.That(collections[0].BeatmapMD5Hashes.Count, Is.EqualTo(1));
Assert.That(collections[1].Name, Is.EqualTo("Second"));
Assert.That(collections[1].BeatmapMD5Hashes.Count, Is.EqualTo(12));
});
}
finally
{
@ -124,7 +139,11 @@ namespace osu.Game.Tests.Collections.IO
}
Assert.That(exceptionThrown, Is.False);
Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(0));
osu.Realm.Run(realm =>
{
var collections = realm.All<RealmBeatmapCollection>().ToList();
Assert.That(collections.Count, Is.EqualTo(0));
});
}
finally
{
@ -149,12 +168,18 @@ namespace osu.Game.Tests.Collections.IO
await importCollectionsFromStream(osu, TestResources.OpenResource("Collections/collections.db"));
// Move first beatmap from second collection into the first.
osu.CollectionManager.Collections[0].BeatmapHashes.Add(osu.CollectionManager.Collections[1].BeatmapHashes[0]);
osu.CollectionManager.Collections[1].BeatmapHashes.RemoveAt(0);
// ReSharper disable once MethodHasAsyncOverload
osu.Realm.Write(realm =>
{
var collections = realm.All<RealmBeatmapCollection>().ToList();
// Rename the second collecction.
osu.CollectionManager.Collections[1].Name.Value = "Another";
// Move first beatmap from second collection into the first.
collections[0].BeatmapMD5Hashes.Add(collections[1].BeatmapMD5Hashes[0]);
collections[1].BeatmapMD5Hashes.RemoveAt(0);
// Rename the second collecction.
collections[1].Name = "Another";
});
}
finally
{
@ -169,13 +194,17 @@ namespace osu.Game.Tests.Collections.IO
{
var osu = LoadOsuIntoHost(host, true);
Assert.That(osu.CollectionManager.Collections.Count, Is.EqualTo(2));
osu.Realm.Run(realm =>
{
var collections = realm.All<RealmBeatmapCollection>().ToList();
Assert.That(collections.Count, Is.EqualTo(2));
Assert.That(osu.CollectionManager.Collections[0].Name.Value, Is.EqualTo("First"));
Assert.That(osu.CollectionManager.Collections[0].BeatmapHashes.Count, Is.EqualTo(2));
Assert.That(collections[0].Name, Is.EqualTo("First"));
Assert.That(collections[0].BeatmapMD5Hashes.Count, Is.EqualTo(2));
Assert.That(osu.CollectionManager.Collections[1].Name.Value, Is.EqualTo("Another"));
Assert.That(osu.CollectionManager.Collections[1].BeatmapHashes.Count, Is.EqualTo(11));
Assert.That(collections[1].Name, Is.EqualTo("Another"));
Assert.That(collections[1].BeatmapMD5Hashes.Count, Is.EqualTo(11));
});
}
finally
{
@ -188,7 +217,7 @@ namespace osu.Game.Tests.Collections.IO
{
// intentionally spin this up on a separate task to avoid disposal deadlocks.
// see https://github.com/EventStore/EventStore/issues/1179
await Task.Factory.StartNew(() => new LegacyCollectionImporter(osu.CollectionManager).Import(stream).WaitSafely(), TaskCreationOptions.LongRunning);
await Task.Factory.StartNew(() => new LegacyCollectionImporter(osu.Realm).Import(stream).WaitSafely(), TaskCreationOptions.LongRunning);
}
}
}

View File

@ -10,7 +10,7 @@ using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Extensions;
using osu.Framework.Platform;
using osu.Game.Collections;
using osu.Game.Database;
using osu.Game.Tests.Resources;
namespace osu.Game.Tests
@ -47,7 +47,7 @@ namespace osu.Game.Tests
public class TestOsuGameBase : OsuGameBase
{
public CollectionManager CollectionManager { get; private set; }
public RealmAccess Realm => Dependencies.Get<RealmAccess>();
private readonly bool withBeatmap;
@ -62,8 +62,6 @@ namespace osu.Game.Tests
// Beatmap must be imported before the collection manager is loaded.
if (withBeatmap)
BeatmapManager.Import(TestResources.GetTestBeatmapForImport()).WaitSafely();
AddInternal(CollectionManager = new CollectionManager());
}
}
}

View File

@ -1,8 +1,6 @@
// 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.
#nullable disable
using System.Linq;
using NUnit.Framework;
using osu.Framework.Allocation;
@ -27,13 +25,10 @@ namespace osu.Game.Tests.Visual.Collections
{
protected override Container<Drawable> Content { get; } = new Container { RelativeSizeAxes = Axes.Both };
private DialogOverlay dialogOverlay;
private CollectionManager manager;
private RulesetStore rulesets;
private BeatmapManager beatmapManager;
private ManageCollectionsDialog dialog;
private DialogOverlay dialogOverlay = null!;
private RulesetStore rulesets = null!;
private BeatmapManager beatmapManager = null!;
private ManageCollectionsDialog dialog = null!;
[BackgroundDependencyLoader]
private void load(GameHost host)
@ -46,19 +41,17 @@ namespace osu.Game.Tests.Visual.Collections
base.Content.AddRange(new Drawable[]
{
manager = new CollectionManager(),
Content,
dialogOverlay = new DialogOverlay(),
});
Dependencies.Cache(manager);
Dependencies.CacheAs<IDialogOverlay>(dialogOverlay);
}
[SetUp]
public void SetUp() => Schedule(() =>
{
manager.Collections.Clear();
Realm.Write(r => r.RemoveAll<RealmBeatmapCollection>());
Child = dialog = new ManageCollectionsDialog();
});
@ -78,17 +71,17 @@ namespace osu.Game.Tests.Visual.Collections
[Test]
public void TestLastItemIsPlaceholder()
{
AddAssert("last item is placeholder", () => !manager.Collections.Contains(dialog.ChildrenOfType<DrawableCollectionListItem>().Last().Model));
AddAssert("last item is placeholder", () => !dialog.ChildrenOfType<DrawableCollectionListItem>().Last().Model.IsManaged);
}
[Test]
public void TestAddCollectionExternal()
{
AddStep("add collection", () => manager.Collections.Add(new BeatmapCollection { Name = { Value = "First collection" } }));
AddStep("add collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "First collection"))));
assertCollectionCount(1);
assertCollectionName(0, "First collection");
AddStep("add another collection", () => manager.Collections.Add(new BeatmapCollection { Name = { Value = "Second collection" } }));
AddStep("add another collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "Second collection"))));
assertCollectionCount(2);
assertCollectionName(1, "Second collection");
}
@ -108,7 +101,7 @@ namespace osu.Game.Tests.Visual.Collections
[Test]
public void TestAddCollectionViaPlaceholder()
{
DrawableCollectionListItem placeholderItem = null;
DrawableCollectionListItem placeholderItem = null!;
AddStep("focus placeholder", () =>
{
@ -117,23 +110,31 @@ namespace osu.Game.Tests.Visual.Collections
});
// Done directly via the collection since InputManager methods cannot add text to textbox...
AddStep("change collection name", () => placeholderItem.Model.Name.Value = "a");
AddStep("change collection name", () => placeholderItem.Model.Name = "a");
assertCollectionCount(1);
AddAssert("collection now exists", () => manager.Collections.Contains(placeholderItem.Model));
AddAssert("collection now exists", () => placeholderItem.Model.IsManaged);
AddAssert("last item is placeholder", () => !manager.Collections.Contains(dialog.ChildrenOfType<DrawableCollectionListItem>().Last().Model));
AddAssert("last item is placeholder", () => !dialog.ChildrenOfType<DrawableCollectionListItem>().Last().Model.IsManaged);
}
[Test]
public void TestRemoveCollectionExternal()
{
AddStep("add two collections", () => manager.Collections.AddRange(new[]
{
new BeatmapCollection { Name = { Value = "1" } },
new BeatmapCollection { Name = { Value = "2" } },
}));
RealmBeatmapCollection first = null!;
AddStep("remove first collection", () => manager.Collections.RemoveAt(0));
AddStep("add two collections", () =>
{
Realm.Write(r =>
{
r.Add(new[]
{
first = new RealmBeatmapCollection(name: "1"),
new RealmBeatmapCollection(name: "2"),
});
});
});
AddStep("change first collection name", () => Realm.Write(r => r.Remove(first)));
assertCollectionCount(1);
assertCollectionName(0, "2");
}
@ -151,21 +152,27 @@ namespace osu.Game.Tests.Visual.Collections
Width = 0.4f,
});
});
AddStep("add two collections with same name", () => manager.Collections.AddRange(new[]
AddStep("add two collections with same name", () => Realm.Write(r => r.Add(new[]
{
new BeatmapCollection { Name = { Value = "1" } },
new BeatmapCollection { Name = { Value = "1" }, BeatmapHashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } },
}));
new RealmBeatmapCollection(name: "1"),
new RealmBeatmapCollection(name: "1")
{
BeatmapMD5Hashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash }
},
})));
}
[Test]
public void TestRemoveCollectionViaButton()
{
AddStep("add two collections", () => manager.Collections.AddRange(new[]
AddStep("add two collections", () => Realm.Write(r => r.Add(new[]
{
new BeatmapCollection { Name = { Value = "1" } },
new BeatmapCollection { Name = { Value = "2" }, BeatmapHashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } },
}));
new RealmBeatmapCollection(name: "1"),
new RealmBeatmapCollection(name: "2")
{
BeatmapMD5Hashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash }
},
})));
assertCollectionCount(2);
@ -198,10 +205,13 @@ namespace osu.Game.Tests.Visual.Collections
[Test]
public void TestCollectionNotRemovedWhenDialogCancelled()
{
AddStep("add two collections", () => manager.Collections.AddRange(new[]
AddStep("add collection", () => Realm.Write(r => r.Add(new[]
{
new BeatmapCollection { Name = { Value = "1" }, BeatmapHashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash } },
}));
new RealmBeatmapCollection(name: "1")
{
BeatmapMD5Hashes = { beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0].MD5Hash }
},
})));
assertCollectionCount(1);
@ -224,13 +234,21 @@ namespace osu.Game.Tests.Visual.Collections
[Test]
public void TestCollectionRenamedExternal()
{
AddStep("add two collections", () => manager.Collections.AddRange(new[]
{
new BeatmapCollection { Name = { Value = "1" } },
new BeatmapCollection { Name = { Value = "2" } },
}));
RealmBeatmapCollection first = null!;
AddStep("change first collection name", () => manager.Collections[0].Name.Value = "First");
AddStep("add two collections", () =>
{
Realm.Write(r =>
{
r.Add(new[]
{
first = new RealmBeatmapCollection(name: "1"),
new RealmBeatmapCollection(name: "2"),
});
});
});
AddStep("change first collection name", () => Realm.Write(_ => first.Name = "First"));
assertCollectionName(0, "First");
}
@ -238,16 +256,24 @@ namespace osu.Game.Tests.Visual.Collections
[Test]
public void TestCollectionRenamedOnTextChange()
{
AddStep("add two collections", () => manager.Collections.AddRange(new[]
RealmBeatmapCollection first = null!;
AddStep("add two collections", () =>
{
new BeatmapCollection { Name = { Value = "1" } },
new BeatmapCollection { Name = { Value = "2" } },
}));
Realm.Write(r =>
{
r.Add(new[]
{
first = new RealmBeatmapCollection(name: "1"),
new RealmBeatmapCollection(name: "2"),
});
});
});
assertCollectionCount(2);
AddStep("change first collection name", () => dialog.ChildrenOfType<TextBox>().First().Text = "First");
AddAssert("collection has new name", () => manager.Collections[0].Name.Value == "First");
AddUntilStep("collection has new name", () => first.Name == "First");
}
private void assertCollectionCount(int count)

View File

@ -1,8 +1,6 @@
// 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.
#nullable disable
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
@ -28,12 +26,9 @@ namespace osu.Game.Tests.Visual.SongSelect
{
protected override Container<Drawable> Content { get; } = new Container { RelativeSizeAxes = Axes.Both };
private CollectionManager collectionManager;
private RulesetStore rulesets;
private BeatmapManager beatmapManager;
private FilterControl control;
private RulesetStore rulesets = null!;
private BeatmapManager beatmapManager = null!;
private FilterControl control = null!;
[BackgroundDependencyLoader]
private void load(GameHost host)
@ -46,17 +41,14 @@ namespace osu.Game.Tests.Visual.SongSelect
base.Content.AddRange(new Drawable[]
{
collectionManager = new CollectionManager(),
Content
});
Dependencies.Cache(collectionManager);
}
[SetUp]
public void SetUp() => Schedule(() =>
{
collectionManager.Collections.Clear();
Realm.Write(r => r.RemoveAll<RealmBeatmapCollection>());
Child = control = new FilterControl
{
@ -77,8 +69,8 @@ namespace osu.Game.Tests.Visual.SongSelect
[Test]
public void TestCollectionAddedToDropdown()
{
AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } }));
AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "2" } }));
AddStep("add collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "1"))));
AddStep("add collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "2"))));
assertCollectionDropdownContains("1");
assertCollectionDropdownContains("2");
}
@ -86,9 +78,11 @@ namespace osu.Game.Tests.Visual.SongSelect
[Test]
public void TestCollectionRemovedFromDropdown()
{
AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } }));
AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "2" } }));
AddStep("remove collection", () => collectionManager.Collections.RemoveAt(0));
var first = new RealmBeatmapCollection(name: "1");
AddStep("add collection", () => Realm.Write(r => r.Add(first)));
AddStep("add collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "2"))));
AddStep("remove collection", () => Realm.Write(r => r.Remove(first)));
assertCollectionDropdownContains("1", false);
assertCollectionDropdownContains("2");
@ -97,7 +91,7 @@ namespace osu.Game.Tests.Visual.SongSelect
[Test]
public void TestCollectionRenamed()
{
AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } }));
AddStep("add collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "1"))));
AddStep("select collection", () =>
{
var dropdown = control.ChildrenOfType<CollectionFilterDropdown>().Single();
@ -106,7 +100,7 @@ namespace osu.Game.Tests.Visual.SongSelect
addExpandHeaderStep();
AddStep("change name", () => collectionManager.Collections[0].Name.Value = "First");
AddStep("change name", () => Realm.Write(_ => getFirstCollection().Name = "First"));
assertCollectionDropdownContains("First");
assertCollectionHeaderDisplays("First");
@ -124,7 +118,7 @@ namespace osu.Game.Tests.Visual.SongSelect
public void TestCollectionFilterHasAddButton()
{
addExpandHeaderStep();
AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } }));
AddStep("add collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "1"))));
AddStep("hover collection", () => InputManager.MoveMouseTo(getAddOrRemoveButton(1)));
AddAssert("collection has add button", () => getAddOrRemoveButton(1).IsPresent);
}
@ -134,7 +128,7 @@ namespace osu.Game.Tests.Visual.SongSelect
{
addExpandHeaderStep();
AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } }));
AddStep("add collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "1"))));
AddStep("select available beatmap", () => Beatmap.Value = beatmapManager.GetWorkingBeatmap(beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0]));
AddAssert("button enabled", () => getAddOrRemoveButton(1).Enabled.Value);
@ -150,13 +144,13 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("select available beatmap", () => Beatmap.Value = beatmapManager.GetWorkingBeatmap(beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0]));
AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } }));
AddStep("add collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "1"))));
AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare));
AddStep("add beatmap to collection", () => collectionManager.Collections[0].BeatmapHashes.Add(Beatmap.Value.BeatmapInfo.MD5Hash));
AddStep("add beatmap to collection", () => getFirstCollection().BeatmapMD5Hashes.Add(Beatmap.Value.BeatmapInfo.MD5Hash));
AddAssert("button is minus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.MinusSquare));
AddStep("remove beatmap from collection", () => collectionManager.Collections[0].BeatmapHashes.Clear());
AddStep("remove beatmap from collection", () => getFirstCollection().BeatmapMD5Hashes.Clear());
AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare));
}
@ -167,15 +161,15 @@ namespace osu.Game.Tests.Visual.SongSelect
AddStep("select available beatmap", () => Beatmap.Value = beatmapManager.GetWorkingBeatmap(beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps[0]));
AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } }));
AddStep("add collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "1"))));
AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare));
addClickAddOrRemoveButtonStep(1);
AddAssert("collection contains beatmap", () => collectionManager.Collections[0].BeatmapHashes.Contains(Beatmap.Value.BeatmapInfo.MD5Hash));
AddAssert("collection contains beatmap", () => getFirstCollection().BeatmapMD5Hashes.Contains(Beatmap.Value.BeatmapInfo.MD5Hash));
AddAssert("button is minus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.MinusSquare));
addClickAddOrRemoveButtonStep(1);
AddAssert("collection does not contain beatmap", () => !collectionManager.Collections[0].BeatmapHashes.Contains(Beatmap.Value.BeatmapInfo.MD5Hash));
AddAssert("collection does not contain beatmap", () => !getFirstCollection().BeatmapMD5Hashes.Contains(Beatmap.Value.BeatmapInfo.MD5Hash));
AddAssert("button is plus", () => getAddOrRemoveButton(1).Icon.Equals(FontAwesome.Solid.PlusSquare));
}
@ -184,7 +178,7 @@ namespace osu.Game.Tests.Visual.SongSelect
{
addExpandHeaderStep();
AddStep("add collection", () => collectionManager.Collections.Add(new BeatmapCollection { Name = { Value = "1" } }));
AddStep("add collection", () => Realm.Write(r => r.Add(new RealmBeatmapCollection(name: "1"))));
AddStep("select collection", () =>
{
InputManager.MoveMouseTo(getCollectionDropdownItems().ElementAt(1));
@ -202,6 +196,8 @@ namespace osu.Game.Tests.Visual.SongSelect
AddAssert("collection filter still selected", () => control.CreateCriteria().Collection?.Name.Value == "1");
}
private RealmBeatmapCollection getFirstCollection() => Realm.Run(r => r.All<RealmBeatmapCollection>().First());
private void assertCollectionHeaderDisplays(string collectionName, bool shouldDisplay = true)
=> AddAssert($"collection dropdown header displays '{collectionName}'",
() => shouldDisplay == (control.ChildrenOfType<CollectionFilterDropdown.CollectionDropdownHeader>().Single().ChildrenOfType<SpriteText>().First().Text == collectionName));

View File

@ -16,14 +16,14 @@ namespace osu.Game.Beatmaps
public string Name { get; set; } = string.Empty;
public List<string> BeatmapMD5Hashes { get; set; } = null!;
public IList<string> BeatmapMD5Hashes { get; } = null!;
/// <summary>
/// The date when this collection was last modified.
/// </summary>
public DateTimeOffset LastModified { get; set; }
public RealmBeatmapCollection(string? name, List<string>? beatmapMD5Hashes)
public RealmBeatmapCollection(string? name = null, IList<string>? beatmapMD5Hashes = null)
{
ID = Guid.NewGuid();
Name = name ?? string.Empty;

View File

@ -46,9 +46,6 @@ namespace osu.Game.Collections
[Resolved(CanBeNull = true)]
private ManageCollectionsDialog manageCollectionsDialog { get; set; }
[Resolved(CanBeNull = true)]
private CollectionManager collectionManager { get; set; }
public CollectionFilterDropdown()
{
ItemSource = filters;
@ -59,8 +56,7 @@ namespace osu.Game.Collections
{
base.LoadComplete();
if (collectionManager != null)
collections.BindTo(collectionManager.Collections);
// TODO: bind to realm data
// Dropdown has logic which triggers a change on the bindable with every change to the contained items.
// This is not desirable here, as it leads to multiple filter operations running even though nothing has changed.

View File

@ -1,62 +0,0 @@
// 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.
#nullable disable
using System;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Overlays.Notifications;
using Realms;
namespace osu.Game.Collections
{
/// <summary>
/// Handles user-defined collections of beatmaps.
/// </summary>
public class CollectionManager : Component, IPostNotifications
{
public readonly BindableList<BeatmapCollection> Collections = new BindableList<BeatmapCollection>();
[Resolved]
private RealmAccess realm { get; set; }
[BackgroundDependencyLoader]
private void load()
{
}
protected override void LoadComplete()
{
base.LoadComplete();
realm.RegisterForNotifications(r => r.All<RealmBeatmapCollection>(), collectionsChanged);
}
private void collectionsChanged(IRealmCollection<RealmBeatmapCollection> sender, ChangeSet changes, Exception error)
{
// TODO: hook up with realm changes.
if (changes == null)
{
foreach (var collection in sender)
Collections.Add(new BeatmapCollection
{
Name = { Value = collection.Name },
BeatmapHashes = { Value = collection.BeatmapMD5Hashes },
});
}
}
public Action<Notification> PostNotification { protected get; set; }
public void DeleteAll()
{
Collections.Clear();
PostNotification?.Invoke(new ProgressCompletionNotification { Text = "Deleted all collections!" });
}
}
}

View File

@ -8,16 +8,16 @@ namespace osu.Game.Collections
{
public class CollectionToggleMenuItem : ToggleMenuItem
{
public CollectionToggleMenuItem(BeatmapCollection collection, IBeatmapInfo beatmap)
: base(collection.Name.Value, MenuItemType.Standard, state =>
public CollectionToggleMenuItem(RealmBeatmapCollection collection, IBeatmapInfo beatmap)
: base(collection.Name, MenuItemType.Standard, state =>
{
if (state)
collection.BeatmapHashes.Add(beatmap.MD5Hash);
collection.BeatmapMD5Hashes.Add(beatmap.MD5Hash);
else
collection.BeatmapHashes.Remove(beatmap.MD5Hash);
collection.BeatmapMD5Hashes.Remove(beatmap.MD5Hash);
})
{
State.Value = collection.BeatmapHashes.Contains(beatmap.MD5Hash);
State.Value = collection.BeatmapMD5Hashes.Contains(beatmap.MD5Hash);
}
}
}

View File

@ -6,16 +6,17 @@
using System;
using Humanizer;
using osu.Framework.Graphics.Sprites;
using osu.Game.Beatmaps;
using osu.Game.Overlays.Dialog;
namespace osu.Game.Collections
{
public class DeleteCollectionDialog : PopupDialog
{
public DeleteCollectionDialog(BeatmapCollection collection, Action deleteAction)
public DeleteCollectionDialog(RealmBeatmapCollection collection, Action deleteAction)
{
HeaderText = "Confirm deletion of";
BodyText = $"{collection.Name.Value} ({"beatmap".ToQuantity(collection.BeatmapHashes.Count)})";
BodyText = $"{collection.Name} ({"beatmap".ToQuantity(collection.BeatmapMD5Hashes.Count)})";
Icon = FontAwesome.Regular.TrashAlt;

View File

@ -7,28 +7,31 @@ using System.Linq;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;
using osuTK;
namespace osu.Game.Collections
{
/// <summary>
/// Visualises a list of <see cref="BeatmapCollection"/>s.
/// Visualises a list of <see cref="RealmBeatmapCollection"/>s.
/// </summary>
public class DrawableCollectionList : OsuRearrangeableListContainer<BeatmapCollection>
public class DrawableCollectionList : OsuRearrangeableListContainer<RealmBeatmapCollection>
{
private Scroll scroll;
protected override ScrollContainer<Drawable> CreateScrollContainer() => scroll = new Scroll();
protected override FillFlowContainer<RearrangeableListItem<BeatmapCollection>> CreateListFillFlowContainer() => new Flow
protected override FillFlowContainer<RearrangeableListItem<RealmBeatmapCollection>> CreateListFillFlowContainer() => new Flow
{
DragActive = { BindTarget = DragActive }
};
protected override OsuRearrangeableListItem<BeatmapCollection> CreateOsuDrawable(BeatmapCollection item)
// TODO: source from realm
protected override OsuRearrangeableListItem<RealmBeatmapCollection> CreateOsuDrawable(RealmBeatmapCollection item)
{
if (item == scroll.PlaceholderItem.Model)
if (item.ID == scroll.PlaceholderItem.Model.ID)
return scroll.ReplacePlaceholder();
return new DrawableCollectionListItem(item, true);
@ -95,7 +98,7 @@ namespace osu.Game.Collections
var previous = PlaceholderItem;
placeholderContainer.Clear(false);
placeholderContainer.Add(PlaceholderItem = new DrawableCollectionListItem(new BeatmapCollection(), false));
placeholderContainer.Add(PlaceholderItem = new DrawableCollectionListItem(new RealmBeatmapCollection(), false));
return previous;
}
@ -104,7 +107,7 @@ namespace osu.Game.Collections
/// <summary>
/// The flow of <see cref="DrawableCollectionListItem"/>. Disables layout easing unless a drag is in progress.
/// </summary>
private class Flow : FillFlowContainer<RearrangeableListItem<BeatmapCollection>>
private class Flow : FillFlowContainer<RearrangeableListItem<RealmBeatmapCollection>>
{
public readonly IBindable<bool> DragActive = new Bindable<bool>();

View File

@ -12,6 +12,8 @@ using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Input.Events;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.UserInterface;
@ -22,15 +24,15 @@ using osuTK.Graphics;
namespace osu.Game.Collections
{
/// <summary>
/// Visualises a <see cref="BeatmapCollection"/> inside a <see cref="DrawableCollectionList"/>.
/// Visualises a <see cref="RealmBeatmapCollection"/> inside a <see cref="DrawableCollectionList"/>.
/// </summary>
public class DrawableCollectionListItem : OsuRearrangeableListItem<BeatmapCollection>
public class DrawableCollectionListItem : OsuRearrangeableListItem<RealmBeatmapCollection>
{
private const float item_height = 35;
private const float button_width = item_height * 0.75f;
/// <summary>
/// Whether the <see cref="BeatmapCollection"/> currently exists inside the <see cref="CollectionManager"/>.
/// Whether the <see cref="RealmBeatmapCollection"/> currently exists inside realm.
/// </summary>
public IBindable<bool> IsCreated => isCreated;
@ -39,9 +41,9 @@ namespace osu.Game.Collections
/// <summary>
/// Creates a new <see cref="DrawableCollectionListItem"/>.
/// </summary>
/// <param name="item">The <see cref="BeatmapCollection"/>.</param>
/// <param name="isCreated">Whether <paramref name="item"/> currently exists inside the <see cref="CollectionManager"/>.</param>
public DrawableCollectionListItem(BeatmapCollection item, bool isCreated)
/// <param name="item">The <see cref="RealmBeatmapCollection"/>.</param>
/// <param name="isCreated">Whether <paramref name="item"/> currently exists inside realm.</param>
public DrawableCollectionListItem(RealmBeatmapCollection item, bool isCreated)
: base(item)
{
this.isCreated.Value = isCreated;
@ -61,24 +63,18 @@ namespace osu.Game.Collections
{
public readonly Bindable<bool> IsCreated = new Bindable<bool>();
private readonly IBindable<string> collectionName;
private readonly BeatmapCollection collection;
[Resolved(CanBeNull = true)]
private CollectionManager collectionManager { get; set; }
private readonly RealmBeatmapCollection collection;
private Container textBoxPaddingContainer;
private ItemTextBox textBox;
public ItemContent(BeatmapCollection collection)
public ItemContent(RealmBeatmapCollection collection)
{
this.collection = collection;
RelativeSizeAxes = Axes.X;
Height = item_height;
Masking = true;
collectionName = collection.Name.GetBoundCopy();
}
[BackgroundDependencyLoader]
@ -111,14 +107,17 @@ namespace osu.Game.Collections
};
}
[Resolved]
private RealmAccess realm { get; set; }
protected override void LoadComplete()
{
base.LoadComplete();
// Bind late, as the collection name may change externally while still loading.
textBox.Current = collection.Name;
textBox.Current.Value = collection.Name;
textBox.Current.BindValueChanged(_ => createNewCollection(), true);
collectionName.BindValueChanged(_ => createNewCollection(), true);
IsCreated.BindValueChanged(created => textBoxPaddingContainer.Padding = new MarginPadding { Right = created.NewValue ? button_width : 0 }, true);
}
@ -127,11 +126,11 @@ namespace osu.Game.Collections
if (IsCreated.Value)
return;
if (string.IsNullOrEmpty(collectionName.Value))
if (string.IsNullOrEmpty(textBox.Current.Value))
return;
// Add the new collection and disable our placeholder. If all text is removed, the placeholder should not show back again.
collectionManager?.Collections.Add(collection);
realm.Write(r => r.Add(collection));
textBox.PlaceholderText = string.Empty;
// When this item changes from placeholder to non-placeholder (via changing containers), its textbox will lose focus, so it needs to be re-focused.
@ -162,15 +161,15 @@ namespace osu.Game.Collections
[Resolved(CanBeNull = true)]
private IDialogOverlay dialogOverlay { get; set; }
[Resolved(CanBeNull = true)]
private CollectionManager collectionManager { get; set; }
[Resolved]
private RealmAccess realmAccess { get; set; }
private readonly BeatmapCollection collection;
private readonly RealmBeatmapCollection collection;
private Drawable fadeContainer;
private Drawable background;
public DeleteButton(BeatmapCollection collection)
public DeleteButton(RealmBeatmapCollection collection)
{
this.collection = collection;
RelativeSizeAxes = Axes.Y;
@ -227,7 +226,7 @@ namespace osu.Game.Collections
{
background.FlashColour(Color4.White, 150);
if (collection.BeatmapHashes.Count == 0)
if (collection.BeatmapMD5Hashes.Count == 0)
deleteCollection();
else
dialogOverlay?.Push(new DeleteCollectionDialog(collection, deleteCollection));
@ -235,7 +234,7 @@ namespace osu.Game.Collections
return true;
}
private void deleteCollection() => collectionManager?.Collections.Remove(collection);
private void deleteCollection() => realmAccess.Write(r => r.Remove(collection));
}
}
}

View File

@ -5,7 +5,6 @@
using osu.Framework.Allocation;
using osu.Framework.Audio;
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
@ -26,9 +25,6 @@ namespace osu.Game.Collections
private AudioFilter lowPassFilter;
[Resolved(CanBeNull = true)]
private CollectionManager collectionManager { get; set; }
public ManageCollectionsDialog()
{
Anchor = Anchor.Centre;
@ -107,7 +103,6 @@ namespace osu.Game.Collections
new DrawableCollectionList
{
RelativeSizeAxes = Axes.Both,
Items = { BindTarget = collectionManager?.Collections ?? new BindableList<BeatmapCollection>() }
}
}
}

View File

@ -1,14 +1,13 @@
// 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.
#nullable disable
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using osu.Framework.Logging;
using osu.Game.Collections;
using osu.Game.Beatmaps;
using osu.Game.IO;
using osu.Game.IO.Legacy;
using osu.Game.Overlays.Notifications;
@ -17,17 +16,17 @@ namespace osu.Game.Database
{
public class LegacyCollectionImporter
{
private readonly CollectionManager collections;
public Action<Notification>? PostNotification { protected get; set; }
public LegacyCollectionImporter(CollectionManager collections)
{
this.collections = collections;
}
public Action<Notification> PostNotification { protected get; set; }
private readonly RealmAccess realm;
private const string database_name = "collection.db";
public LegacyCollectionImporter(RealmAccess realm)
{
this.realm = realm;
}
public Task<int> GetAvailableCount(StableStorage stableStorage)
{
if (!stableStorage.Exists(database_name))
@ -76,26 +75,30 @@ namespace osu.Game.Database
notification.State = ProgressNotificationState.Completed;
}
private Task importCollections(List<BeatmapCollection> newCollections)
private Task importCollections(List<RealmBeatmapCollection> newCollections)
{
var tcs = new TaskCompletionSource<bool>();
// Schedule(() =>
// {
try
{
foreach (var newCol in newCollections)
realm.Write(r =>
{
var existing = collections.Collections.FirstOrDefault(c => c.Name.Value == newCol.Name.Value);
if (existing == null)
collections.Collections.Add(existing = new BeatmapCollection { Name = { Value = newCol.Name.Value } });
foreach (string newBeatmap in newCol.BeatmapHashes)
foreach (var collection in newCollections)
{
if (!existing.BeatmapHashes.Contains(newBeatmap))
existing.BeatmapHashes.Add(newBeatmap);
var existing = r.All<RealmBeatmapCollection>().FirstOrDefault(c => c.Name == collection.Name);
if (existing != null)
{
foreach (string newBeatmap in existing.BeatmapMD5Hashes)
{
if (!existing.BeatmapMD5Hashes.Contains(newBeatmap))
existing.BeatmapMD5Hashes.Add(newBeatmap);
}
}
else
r.Add(collection);
}
}
});
tcs.SetResult(true);
}
@ -104,12 +107,11 @@ namespace osu.Game.Database
Logger.Error(e, "Failed to import collection.");
tcs.SetException(e);
}
// });
return tcs.Task;
}
private List<BeatmapCollection> readCollections(Stream stream, ProgressNotification notification = null)
private List<RealmBeatmapCollection> readCollections(Stream stream, ProgressNotification? notification = null)
{
if (notification != null)
{
@ -117,7 +119,7 @@ namespace osu.Game.Database
notification.Progress = 0;
}
var result = new List<BeatmapCollection>();
var result = new List<RealmBeatmapCollection>();
try
{
@ -133,7 +135,7 @@ namespace osu.Game.Database
if (notification?.CancellationToken.IsCancellationRequested == true)
return result;
var collection = new BeatmapCollection { Name = { Value = sr.ReadString() } };
var collection = new RealmBeatmapCollection(sr.ReadString());
int mapCount = sr.ReadInt32();
for (int j = 0; j < mapCount; j++)
@ -143,7 +145,7 @@ namespace osu.Game.Database
string checksum = sr.ReadString();
collection.BeatmapHashes.Add(checksum);
collection.BeatmapMD5Hashes.Add(checksum);
}
if (notification != null)

View File

@ -13,7 +13,6 @@ using osu.Framework.Extensions.EnumExtensions;
using osu.Framework.Graphics;
using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Collections;
using osu.Game.IO;
using osu.Game.Overlays;
using osu.Game.Overlays.Settings.Sections.Maintenance;
@ -36,15 +35,15 @@ namespace osu.Game.Database
[Resolved]
private ScoreManager scores { get; set; }
[Resolved]
private CollectionManager collections { get; set; }
[Resolved(canBeNull: true)]
private OsuGame game { get; set; }
[Resolved]
private IDialogOverlay dialogOverlay { get; set; }
[Resolved]
private RealmAccess realmAccess { get; set; }
[Resolved(canBeNull: true)]
private DesktopGameHost desktopGameHost { get; set; }
@ -72,7 +71,7 @@ namespace osu.Game.Database
return await new LegacySkinImporter(skins).GetAvailableCount(stableStorage);
case StableContent.Collections:
return await new LegacyCollectionImporter(collections).GetAvailableCount(stableStorage);
return await new LegacyCollectionImporter(realmAccess).GetAvailableCount(stableStorage);
case StableContent.Scores:
return await new LegacyScoreImporter(scores).GetAvailableCount(stableStorage);
@ -109,7 +108,7 @@ namespace osu.Game.Database
importTasks.Add(new LegacySkinImporter(skins).ImportFromStableAsync(stableStorage));
if (content.HasFlagFast(StableContent.Collections))
importTasks.Add(beatmapImportTask.ContinueWith(_ => new LegacyCollectionImporter(collections).ImportFromStableAsync(stableStorage), TaskContinuationOptions.OnlyOnRanToCompletion));
importTasks.Add(beatmapImportTask.ContinueWith(_ => new LegacyCollectionImporter(realmAccess).ImportFromStableAsync(stableStorage), TaskContinuationOptions.OnlyOnRanToCompletion));
if (content.HasFlagFast(StableContent.Scores))
importTasks.Add(beatmapImportTask.ContinueWith(_ => new LegacyScoreImporter(scores).ImportFromStableAsync(stableStorage), TaskContinuationOptions.OnlyOnRanToCompletion));

View File

@ -858,11 +858,6 @@ namespace osu.Game
d.Origin = Anchor.TopRight;
}), rightFloatingOverlayContent.Add, true);
loadComponentSingleFile(new CollectionManager
{
PostNotification = n => Notifications.Post(n),
}, Add, true);
loadComponentSingleFile(legacyImportManager, Add);
loadComponentSingleFile(screenshotManager, Add);

View File

@ -3,9 +3,10 @@
using osu.Framework.Allocation;
using osu.Framework.Localisation;
using osu.Game.Collections;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Localisation;
using osu.Game.Overlays.Notifications;
namespace osu.Game.Overlays.Settings.Sections.Maintenance
{
@ -15,11 +16,15 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
private SettingsButton importCollectionsButton = null!;
[BackgroundDependencyLoader]
private void load(CollectionManager? collectionManager, LegacyImportManager? legacyImportManager, IDialogOverlay? dialogOverlay)
{
if (collectionManager == null) return;
[Resolved]
private RealmAccess realm { get; set; } = null!;
[Resolved]
private INotificationOverlay notificationOverlay { get; set; } = null!;
[BackgroundDependencyLoader]
private void load(LegacyImportManager? legacyImportManager, IDialogOverlay? dialogOverlay)
{
if (legacyImportManager?.SupportsImportFromStable == true)
{
Add(importCollectionsButton = new SettingsButton
@ -38,9 +43,15 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance
Text = MaintenanceSettingsStrings.DeleteAllCollections,
Action = () =>
{
dialogOverlay?.Push(new MassDeleteConfirmationDialog(collectionManager.DeleteAll));
dialogOverlay?.Push(new MassDeleteConfirmationDialog(deleteAllCollections));
}
});
}
private void deleteAllCollections()
{
realm.Write(r => r.RemoveAll<RealmBeatmapCollection>());
notificationOverlay.Post(new ProgressCompletionNotification { Text = "Deleted all collections!" });
}
}
}

View File

@ -94,6 +94,9 @@ namespace osu.Game.Screens.OnlinePlay
private PanelBackground panelBackground;
private FillFlowContainer mainFillFlow;
[Resolved]
private RealmAccess realm { get; set; }
[Resolved]
private RulesetStore rulesets { get; set; }
@ -112,9 +115,6 @@ namespace osu.Game.Screens.OnlinePlay
[Resolved(CanBeNull = true)]
private BeatmapSetOverlay beatmapOverlay { get; set; }
[Resolved(CanBeNull = true)]
private CollectionManager collectionManager { get; set; }
[Resolved(CanBeNull = true)]
private ManageCollectionsDialog manageCollectionsDialog { get; set; }
@ -495,11 +495,11 @@ namespace osu.Game.Screens.OnlinePlay
if (beatmapOverlay != null)
items.Add(new OsuMenuItem("Details...", MenuItemType.Standard, () => beatmapOverlay.FetchAndShowBeatmap(Item.Beatmap.OnlineID)));
if (collectionManager != null && beatmap != null)
if (beatmap != null)
{
if (beatmaps.QueryBeatmap(b => b.OnlineID == beatmap.OnlineID) is BeatmapInfo local && !local.BeatmapSet.AsNonNull().DeletePending)
{
var collectionItems = collectionManager.Collections.Select(c => new CollectionToggleMenuItem(c, beatmap)).Cast<OsuMenuItem>().ToList();
var collectionItems = realm.Realm.All<RealmBeatmapCollection>().Select(c => new CollectionToggleMenuItem(c, beatmap)).Cast<OsuMenuItem>().ToList();
if (manageCollectionsDialog != null)
collectionItems.Add(new OsuMenuItem("Manage...", MenuItemType.Standard, manageCollectionsDialog.Show));

View File

@ -22,6 +22,7 @@ using osu.Framework.Input.Events;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.Drawables;
using osu.Game.Collections;
using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Backgrounds;
using osu.Game.Graphics.Sprites;
@ -63,12 +64,12 @@ namespace osu.Game.Screens.Select.Carousel
[Resolved]
private BeatmapDifficultyCache difficultyCache { get; set; }
[Resolved(CanBeNull = true)]
private CollectionManager collectionManager { get; set; }
[Resolved(CanBeNull = true)]
private ManageCollectionsDialog manageCollectionsDialog { get; set; }
[Resolved]
private RealmAccess realm { get; set; }
private IBindable<StarDifficulty?> starDifficultyBindable;
private CancellationTokenSource starDifficultyCancellationSource;
@ -237,14 +238,11 @@ namespace osu.Game.Screens.Select.Carousel
if (beatmapInfo.OnlineID > 0 && beatmapOverlay != null)
items.Add(new OsuMenuItem("Details...", MenuItemType.Standard, () => beatmapOverlay.FetchAndShowBeatmap(beatmapInfo.OnlineID)));
if (collectionManager != null)
{
var collectionItems = collectionManager.Collections.Select(c => new CollectionToggleMenuItem(c, beatmapInfo)).Cast<OsuMenuItem>().ToList();
if (manageCollectionsDialog != null)
collectionItems.Add(new OsuMenuItem("Manage...", MenuItemType.Standard, manageCollectionsDialog.Show));
var collectionItems = realm.Realm.All<RealmBeatmapCollection>().Select(c => new CollectionToggleMenuItem(c, beatmapInfo)).Cast<OsuMenuItem>().ToList();
if (manageCollectionsDialog != null)
collectionItems.Add(new OsuMenuItem("Manage...", MenuItemType.Standard, manageCollectionsDialog.Show));
items.Add(new OsuMenuItem("Collections") { Items = collectionItems });
}
items.Add(new OsuMenuItem("Collections") { Items = collectionItems });
if (hideRequested != null)
items.Add(new OsuMenuItem(CommonStrings.ButtonsHide.ToSentence(), MenuItemType.Destructive, () => hideRequested(beatmapInfo)));

View File

@ -17,6 +17,7 @@ using osu.Framework.Graphics.UserInterface;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Collections;
using osu.Game.Database;
using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays;
@ -32,12 +33,12 @@ namespace osu.Game.Screens.Select.Carousel
[Resolved(CanBeNull = true)]
private IDialogOverlay dialogOverlay { get; set; }
[Resolved(CanBeNull = true)]
private CollectionManager collectionManager { get; set; }
[Resolved(CanBeNull = true)]
private ManageCollectionsDialog manageCollectionsDialog { get; set; }
[Resolved]
private RealmAccess realm { get; set; }
public IEnumerable<DrawableCarouselItem> DrawableBeatmaps => beatmapContainer?.IsLoaded != true ? Enumerable.Empty<DrawableCarouselItem>() : beatmapContainer.AliveChildren;
[CanBeNull]
@ -223,14 +224,11 @@ namespace osu.Game.Screens.Select.Carousel
if (beatmapSet.OnlineID > 0 && viewDetails != null)
items.Add(new OsuMenuItem("Details...", MenuItemType.Standard, () => viewDetails(beatmapSet.OnlineID)));
if (collectionManager != null)
{
var collectionItems = collectionManager.Collections.Select(createCollectionMenuItem).ToList();
if (manageCollectionsDialog != null)
collectionItems.Add(new OsuMenuItem("Manage...", MenuItemType.Standard, manageCollectionsDialog.Show));
var collectionItems = realm.Realm.All<RealmBeatmapCollection>().AsEnumerable().Select(createCollectionMenuItem).ToList();
if (manageCollectionsDialog != null)
collectionItems.Add(new OsuMenuItem("Manage...", MenuItemType.Standard, manageCollectionsDialog.Show));
items.Add(new OsuMenuItem("Collections") { Items = collectionItems });
}
items.Add(new OsuMenuItem("Collections") { Items = collectionItems });
if (beatmapSet.Beatmaps.Any(b => b.Hidden))
items.Add(new OsuMenuItem("Restore all hidden", MenuItemType.Standard, () => restoreHiddenRequested(beatmapSet)));
@ -241,13 +239,13 @@ namespace osu.Game.Screens.Select.Carousel
}
}
private MenuItem createCollectionMenuItem(BeatmapCollection collection)
private MenuItem createCollectionMenuItem(RealmBeatmapCollection collection)
{
Debug.Assert(beatmapSet != null);
TernaryState state;
int countExisting = beatmapSet.Beatmaps.Count(b => collection.BeatmapHashes.Contains(b.MD5Hash));
int countExisting = beatmapSet.Beatmaps.Count(b => collection.BeatmapMD5Hashes.Contains(b.MD5Hash));
if (countExisting == beatmapSet.Beatmaps.Count)
state = TernaryState.True;
@ -256,21 +254,21 @@ namespace osu.Game.Screens.Select.Carousel
else
state = TernaryState.False;
return new TernaryStateToggleMenuItem(collection.Name.Value, MenuItemType.Standard, s =>
return new TernaryStateToggleMenuItem(collection.Name, MenuItemType.Standard, s =>
{
foreach (var b in beatmapSet.Beatmaps)
{
switch (s)
{
case TernaryState.True:
if (collection.BeatmapHashes.Contains(b.MD5Hash))
if (collection.BeatmapMD5Hashes.Contains(b.MD5Hash))
continue;
collection.BeatmapHashes.Add(b.MD5Hash);
collection.BeatmapMD5Hashes.Add(b.MD5Hash);
break;
case TernaryState.False:
collection.BeatmapHashes.Remove(b.MD5Hash);
collection.BeatmapMD5Hashes.Remove(b.MD5Hash);
break;
}
}