diff --git a/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs b/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs index 19fccdf94d..eed233945d 100644 --- a/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs +++ b/osu.Game.Tests/Visual/SongSelectV2/TestSceneSongSelectFiltering.cs @@ -309,6 +309,24 @@ namespace osu.Game.Tests.Visual.SongSelectV2 checkMatchedBeatmaps(3); } + [Test] + public void TestCantHideAllBeatmaps() + { + LoadSongSelect(); + ImportBeatmapForRuleset(0); + + checkMatchedBeatmaps(3); + + AddStep("hide selected", () => Beatmaps.Hide(Beatmap.Value.BeatmapInfo)); + checkMatchedBeatmaps(2); + + AddStep("hide selected", () => Beatmaps.Hide(Beatmap.Value.BeatmapInfo)); + checkMatchedBeatmaps(1); + + AddAssert("hide fails", () => Beatmaps.Hide(Beatmap.Value.BeatmapInfo), () => Is.False); + checkMatchedBeatmaps(1); + } + private NoResultsPlaceholder? getPlaceholder() => SongSelect.ChildrenOfType().FirstOrDefault(); private void checkMatchedBeatmaps(int expected) => AddUntilStep($"{expected} matching shown", () => Carousel.MatchedBeatmapsCount, () => Is.EqualTo(expected)); diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index 2c17908487..a3e7c1365e 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -218,24 +218,37 @@ namespace osu.Game.Beatmaps } /// - /// Delete a beatmap difficulty. + /// Hide a beatmap difficulty. + /// Will fail if all difficulties are about to be hidden. /// /// The beatmap difficulty to hide. - public void Hide(BeatmapInfo beatmapInfo) + public bool Hide(BeatmapInfo beatmapInfo) { - Realm.Run(r => + return Realm.Run(r => { using (var transaction = r.BeginWrite()) { if (!beatmapInfo.IsManaged) beatmapInfo = r.Find(beatmapInfo.ID)!; + if (!CanHide(beatmapInfo)) + return false; + beatmapInfo.Hidden = true; transaction.Commit(); + return true; } }); } + public bool CanHide(BeatmapInfo beatmapInfo) => Realm.Run(r => + { + if (!beatmapInfo.IsManaged) + beatmapInfo = r.Find(beatmapInfo.ID)!; + + return beatmapInfo.BeatmapSet!.Beatmaps.Count(b => !b.Hidden) > 1; + }); + /// /// Restore a beatmap difficulty. /// diff --git a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs index 74f0c714a3..a8f5b6dd24 100644 --- a/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/DrawableCarouselBeatmap.cs @@ -112,7 +112,7 @@ namespace osu.Game.Screens.Select.Carousel } if (manager != null) - hideRequested = manager.Hide; + hideRequested = b => manager.Hide(b); Header.Children = new Drawable[] { diff --git a/osu.Game/Screens/SelectV2/SoloSongSelect.cs b/osu.Game/Screens/SelectV2/SoloSongSelect.cs index 4c4df7f389..2b0ff66f91 100644 --- a/osu.Game/Screens/SelectV2/SoloSongSelect.cs +++ b/osu.Game/Screens/SelectV2/SoloSongSelect.cs @@ -84,7 +84,9 @@ namespace osu.Game.Screens.SelectV2 { Icon = FontAwesome.Solid.Eraser }; - yield return new OsuMenuItem(WebCommonStrings.ButtonsHide.ToSentence(), MenuItemType.Destructive, () => beatmaps.Hide(beatmap)); + + if (beatmaps.CanHide(beatmap)) + yield return new OsuMenuItem(WebCommonStrings.ButtonsHide.ToSentence(), MenuItemType.Destructive, () => beatmaps.Hide(beatmap)); } protected override void OnStart()