diff --git a/osu.Android.props b/osu.Android.props
index b9b127309a..b9ef783b2a 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -53,7 +53,7 @@
-
+
diff --git a/osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas-overlay.png b/osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas-overlay.png
new file mode 100644
index 0000000000..3a6612378e
Binary files /dev/null and b/osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas-overlay.png differ
diff --git a/osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas.png b/osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas.png
new file mode 100644
index 0000000000..afb8698b2d
Binary files /dev/null and b/osu.Game.Rulesets.Catch.Tests/Resources/old-skin/fruit-bananas.png differ
diff --git a/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs
new file mode 100644
index 0000000000..7c05d99c59
--- /dev/null
+++ b/osu.Game.Tests/Visual/Online/TestSceneBeatmapListingOverlay.cs
@@ -0,0 +1,39 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System;
+using System.Collections.Generic;
+using osu.Game.Overlays;
+using NUnit.Framework;
+
+namespace osu.Game.Tests.Visual.Online
+{
+ public class TestSceneBeatmapListingOverlay : OsuTestScene
+ {
+ public override IReadOnlyList RequiredTypes => new[]
+ {
+ typeof(BeatmapListingOverlay),
+ };
+
+ protected override bool UseOnlineAPI => true;
+
+ private readonly BeatmapListingOverlay overlay;
+
+ public TestSceneBeatmapListingOverlay()
+ {
+ Add(overlay = new BeatmapListingOverlay());
+ }
+
+ [Test]
+ public void TestShow()
+ {
+ AddStep("Show", overlay.Show);
+ }
+
+ [Test]
+ public void TestHide()
+ {
+ AddStep("Hide", overlay.Hide);
+ }
+ }
+}
diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs
index 5652b8d2bd..930ca8fdf1 100644
--- a/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs
+++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsRequest.cs
@@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using System.ComponentModel;
+using osu.Framework.IO.Network;
using osu.Game.Overlays;
using osu.Game.Overlays.Direct;
using osu.Game.Rulesets;
@@ -26,8 +27,21 @@ namespace osu.Game.Online.API.Requests
this.direction = direction;
}
- // ReSharper disable once ImpureMethodCallOnReadonlyValueField
- protected override string Target => $@"beatmapsets/search?q={query}&m={ruleset.ID ?? 0}&s={searchCategory.ToString().ToLowerInvariant()}&sort={sortCriteria.ToString().ToLowerInvariant()}_{directionString}";
+ protected override WebRequest CreateWebRequest()
+ {
+ var req = base.CreateWebRequest();
+ req.AddParameter("q", query);
+
+ if (ruleset.ID.HasValue)
+ req.AddParameter("m", ruleset.ID.Value.ToString());
+
+ req.AddParameter("s", searchCategory.ToString().ToLowerInvariant());
+ req.AddParameter("sort", $"{sortCriteria.ToString().ToLowerInvariant()}_{directionString}");
+
+ return req;
+ }
+
+ protected override string Target => @"beatmapsets/search";
}
public enum BeatmapSearchCategory
diff --git a/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs b/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs
index 28863cb0e0..3c4fb11ed1 100644
--- a/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs
+++ b/osu.Game/Online/API/Requests/SearchBeatmapSetsResponse.cs
@@ -2,12 +2,17 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
+using Newtonsoft.Json;
using osu.Game.Online.API.Requests.Responses;
namespace osu.Game.Online.API.Requests
{
public class SearchBeatmapSetsResponse : ResponseWithCursor
{
+ [JsonProperty("beatmapsets")]
public IEnumerable BeatmapSets;
+
+ [JsonProperty("total")]
+ public int Total;
}
}
diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs
new file mode 100644
index 0000000000..5af92914de
--- /dev/null
+++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingHeader.cs
@@ -0,0 +1,24 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Graphics;
+using osu.Game.Graphics.UserInterface;
+
+namespace osu.Game.Overlays.BeatmapListing
+{
+ public class BeatmapListingHeader : OverlayHeader
+ {
+ protected override ScreenTitle CreateTitle() => new BeatmapListingTitle();
+
+ private class BeatmapListingTitle : ScreenTitle
+ {
+ public BeatmapListingTitle()
+ {
+ Title = @"beatmap";
+ Section = @"listing";
+ }
+
+ protected override Drawable CreateIcon() => new ScreenTitleTextureIcon(@"Icons/changelog");
+ }
+ }
+}
diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchSection.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchSection.cs
index f47144e5d8..f9799d8a6b 100644
--- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchSection.cs
+++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSearchSection.cs
@@ -104,6 +104,8 @@ namespace osu.Game.Overlays.BeatmapListing
}
}
});
+
+ Category.Value = BeatmapSearchCategory.Leaderboard;
}
[BackgroundDependencyLoader]
diff --git a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs
index cb41b33bc4..27c43b092a 100644
--- a/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs
+++ b/osu.Game/Overlays/BeatmapListing/BeatmapListingSortTabControl.cs
@@ -8,16 +8,17 @@ using osu.Framework.Graphics;
using osuTK.Graphics;
using osuTK;
using osu.Framework.Input.Events;
+using osu.Game.Overlays.Direct;
namespace osu.Game.Overlays.BeatmapListing
{
- public class BeatmapListingSortTabControl : OverlaySortTabControl
+ public class BeatmapListingSortTabControl : OverlaySortTabControl
{
public readonly Bindable SortDirection = new Bindable(Overlays.SortDirection.Descending);
public BeatmapListingSortTabControl()
{
- Current.Value = BeatmapSortCriteria.Ranked;
+ Current.Value = DirectSortCriteria.Ranked;
}
protected override SortTabControl CreateControl() => new BeatmapSortTabControl
@@ -29,7 +30,7 @@ namespace osu.Game.Overlays.BeatmapListing
{
public readonly Bindable SortDirection = new Bindable();
- protected override TabItem CreateTabItem(BeatmapSortCriteria value) => new BeatmapSortTabItem(value)
+ protected override TabItem CreateTabItem(DirectSortCriteria value) => new BeatmapSortTabItem(value)
{
SortDirection = { BindTarget = SortDirection }
};
@@ -39,12 +40,12 @@ namespace osu.Game.Overlays.BeatmapListing
{
public readonly Bindable SortDirection = new Bindable();
- public BeatmapSortTabItem(BeatmapSortCriteria value)
+ public BeatmapSortTabItem(DirectSortCriteria value)
: base(value)
{
}
- protected override TabButton CreateTabButton(BeatmapSortCriteria value) => new BeatmapTabButton(value)
+ protected override TabButton CreateTabButton(DirectSortCriteria value) => new BeatmapTabButton(value)
{
Active = { BindTarget = Active },
SortDirection = { BindTarget = SortDirection }
@@ -66,7 +67,7 @@ namespace osu.Game.Overlays.BeatmapListing
private readonly SpriteIcon icon;
- public BeatmapTabButton(BeatmapSortCriteria value)
+ public BeatmapTabButton(DirectSortCriteria value)
: base(value)
{
Add(icon = new SpriteIcon
@@ -104,15 +105,4 @@ namespace osu.Game.Overlays.BeatmapListing
}
}
}
-
- public enum BeatmapSortCriteria
- {
- Title,
- Artist,
- Difficulty,
- Ranked,
- Rating,
- Plays,
- Favourites,
- }
}
diff --git a/osu.Game/Overlays/BeatmapListingOverlay.cs b/osu.Game/Overlays/BeatmapListingOverlay.cs
new file mode 100644
index 0000000000..213e9a4244
--- /dev/null
+++ b/osu.Game/Overlays/BeatmapListingOverlay.cs
@@ -0,0 +1,299 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using System.Linq;
+using osu.Framework.Allocation;
+using osu.Framework.Extensions.Color4Extensions;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Effects;
+using osu.Framework.Graphics.Shapes;
+using osu.Framework.Graphics.Sprites;
+using osu.Framework.Graphics.Textures;
+using osu.Framework.Threading;
+using osu.Game.Audio;
+using osu.Game.Beatmaps;
+using osu.Game.Graphics.Containers;
+using osu.Game.Graphics.Sprites;
+using osu.Game.Online.API.Requests;
+using osu.Game.Overlays.BeatmapListing;
+using osu.Game.Overlays.Direct;
+using osu.Game.Rulesets;
+using osuTK;
+using osuTK.Graphics;
+
+namespace osu.Game.Overlays
+{
+ public class BeatmapListingOverlay : FullscreenOverlay
+ {
+ [Resolved]
+ private PreviewTrackManager previewTrackManager { get; set; }
+
+ [Resolved]
+ private RulesetStore rulesets { get; set; }
+
+ private SearchBeatmapSetsRequest getSetsRequest;
+
+ private Container panelsPlaceholder;
+ private Drawable currentContent;
+ private BeatmapListingSearchSection searchSection;
+ private BeatmapListingSortTabControl sortControl;
+
+ public BeatmapListingOverlay()
+ : base(OverlayColourScheme.Blue)
+ {
+ }
+
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = ColourProvider.Background6
+ },
+ new BasicScrollContainer
+ {
+ RelativeSizeAxes = Axes.Both,
+ ScrollbarVisible = false,
+ Child = new ReverseChildIDFillFlowContainer
+ {
+ AutoSizeAxes = Axes.Y,
+ RelativeSizeAxes = Axes.X,
+ Direction = FillDirection.Vertical,
+ Spacing = new Vector2(0, 10),
+ Children = new Drawable[]
+ {
+ new FillFlowContainer
+ {
+ AutoSizeAxes = Axes.Y,
+ RelativeSizeAxes = Axes.X,
+ Direction = FillDirection.Vertical,
+ Masking = true,
+ EdgeEffect = new EdgeEffectParameters
+ {
+ Colour = Color4.Black.Opacity(0.25f),
+ Type = EdgeEffectType.Shadow,
+ Radius = 3,
+ Offset = new Vector2(0f, 1f),
+ },
+ Children = new Drawable[]
+ {
+ new BeatmapListingHeader(),
+ searchSection = new BeatmapListingSearchSection(),
+ }
+ },
+ new Container
+ {
+ AutoSizeAxes = Axes.Y,
+ RelativeSizeAxes = Axes.X,
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = ColourProvider.Background4,
+ },
+ new FillFlowContainer
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Children = new Drawable[]
+ {
+ new Container
+ {
+ RelativeSizeAxes = Axes.X,
+ Height = 40,
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = ColourProvider.Background5
+ },
+ sortControl = new BeatmapListingSortTabControl
+ {
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.CentreLeft,
+ Margin = new MarginPadding { Left = 20 }
+ }
+ }
+ },
+ panelsPlaceholder = new Container
+ {
+ AutoSizeAxes = Axes.Y,
+ RelativeSizeAxes = Axes.X,
+ Padding = new MarginPadding { Horizontal = 20 },
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ };
+ }
+
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ var sortCriteria = sortControl.Current;
+ var sortDirection = sortControl.SortDirection;
+
+ searchSection.Query.BindValueChanged(query =>
+ {
+ sortCriteria.Value = string.IsNullOrEmpty(query.NewValue) ? DirectSortCriteria.Ranked : DirectSortCriteria.Relevance;
+ sortDirection.Value = SortDirection.Descending;
+
+ queueUpdateSearch(true);
+ });
+
+ searchSection.Ruleset.BindValueChanged(_ => queueUpdateSearch());
+ searchSection.Category.BindValueChanged(_ => queueUpdateSearch());
+ sortCriteria.BindValueChanged(_ => queueUpdateSearch());
+ sortDirection.BindValueChanged(_ => queueUpdateSearch());
+ }
+
+ private ScheduledDelegate queryChangedDebounce;
+
+ private void queueUpdateSearch(bool queryTextChanged = false)
+ {
+ getSetsRequest?.Cancel();
+
+ queryChangedDebounce?.Cancel();
+ queryChangedDebounce = Scheduler.AddDelayed(updateSearch, queryTextChanged ? 500 : 100);
+ }
+
+ private void updateSearch()
+ {
+ if (!IsLoaded)
+ return;
+
+ if (State.Value == Visibility.Hidden)
+ return;
+
+ if (API == null)
+ return;
+
+ previewTrackManager.StopAnyPlaying(this);
+
+ currentContent?.FadeColour(Color4.DimGray, 400, Easing.OutQuint);
+
+ getSetsRequest = new SearchBeatmapSetsRequest(
+ searchSection.Query.Value,
+ searchSection.Ruleset.Value,
+ searchSection.Category.Value,
+ sortControl.Current.Value,
+ sortControl.SortDirection.Value);
+
+ getSetsRequest.Success += response => Schedule(() => recreatePanels(response));
+
+ API.Queue(getSetsRequest);
+ }
+
+ private void recreatePanels(SearchBeatmapSetsResponse response)
+ {
+ if (response.Total == 0)
+ {
+ searchSection.BeatmapSet = null;
+ LoadComponentAsync(new NotFoundDrawable(), addContentToPlaceholder);
+ return;
+ }
+
+ var beatmaps = response.BeatmapSets.Select(r => r.ToBeatmapSet(rulesets)).ToList();
+
+ var newPanels = new FillFlowContainer
+ {
+ RelativeSizeAxes = Axes.X,
+ AutoSizeAxes = Axes.Y,
+ Spacing = new Vector2(10),
+ Alpha = 0,
+ Margin = new MarginPadding { Vertical = 15 },
+ ChildrenEnumerable = beatmaps.Select(b => new DirectGridPanel(b)
+ {
+ Anchor = Anchor.TopCentre,
+ Origin = Anchor.TopCentre,
+ })
+ };
+
+ LoadComponentAsync(newPanels, loaded =>
+ {
+ addContentToPlaceholder(loaded);
+ searchSection.BeatmapSet = beatmaps.First();
+ });
+ }
+
+ private void addContentToPlaceholder(Drawable content)
+ {
+ Drawable lastContent = currentContent;
+
+ if (lastContent != null)
+ {
+ lastContent.FadeOut(100, Easing.OutQuint).Expire();
+
+ // Consider the case when the new content is smaller than the last content.
+ // If the auto-size computation is delayed until fade out completes, the background remain high for too long making the resulting transition to the smaller height look weird.
+ // At the same time, if the last content's height is bypassed immediately, there is a period where the new content is at Alpha = 0 when the auto-sized height will be 0.
+ // To resolve both of these issues, the bypass is delayed until a point when the content transitions (fade-in and fade-out) overlap and it looks good to do so.
+ lastContent.Delay(25).Schedule(() => lastContent.BypassAutoSizeAxes = Axes.Y);
+ }
+
+ panelsPlaceholder.Add(currentContent = content);
+ currentContent.FadeIn(200, Easing.OutQuint);
+ }
+
+ protected override void Dispose(bool isDisposing)
+ {
+ getSetsRequest?.Cancel();
+ queryChangedDebounce?.Cancel();
+
+ base.Dispose(isDisposing);
+ }
+
+ private class NotFoundDrawable : CompositeDrawable
+ {
+ public NotFoundDrawable()
+ {
+ RelativeSizeAxes = Axes.X;
+ Height = 250;
+ Alpha = 0;
+ Margin = new MarginPadding { Top = 15 };
+ }
+
+ [BackgroundDependencyLoader]
+ private void load(TextureStore textures)
+ {
+ AddInternal(new FillFlowContainer
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ RelativeSizeAxes = Axes.Y,
+ AutoSizeAxes = Axes.X,
+ Direction = FillDirection.Horizontal,
+ Spacing = new Vector2(10, 0),
+ Children = new Drawable[]
+ {
+ new Sprite
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ RelativeSizeAxes = Axes.Both,
+ FillMode = FillMode.Fit,
+ Texture = textures.Get(@"Online/not-found")
+ },
+ new OsuSpriteText
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Text = @"... nope, nothing found.",
+ }
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/osu.Game/Overlays/Direct/FilterControl.cs b/osu.Game/Overlays/Direct/FilterControl.cs
index 8b04bf0387..70a3ab54fb 100644
--- a/osu.Game/Overlays/Direct/FilterControl.cs
+++ b/osu.Game/Overlays/Direct/FilterControl.cs
@@ -34,14 +34,13 @@ namespace osu.Game.Overlays.Direct
public enum DirectSortCriteria
{
- Relevance,
Title,
Artist,
- Creator,
Difficulty,
Ranked,
Rating,
Plays,
Favourites,
+ Relevance,
}
}
diff --git a/osu.Game/Overlays/Music/PlaylistOverlay.cs b/osu.Game/Overlays/Music/PlaylistOverlay.cs
index 8f753fd3aa..b878aba489 100644
--- a/osu.Game/Overlays/Music/PlaylistOverlay.cs
+++ b/osu.Game/Overlays/Music/PlaylistOverlay.cs
@@ -75,8 +75,6 @@ namespace osu.Game.Overlays.Music
},
};
- list.Items.BindTo(beatmapSets);
-
filter.Search.OnCommit = (sender, newText) =>
{
BeatmapInfo toSelect = list.FirstVisibleSet?.Beatmaps?.FirstOrDefault();
@@ -87,7 +85,13 @@ namespace osu.Game.Overlays.Music
beatmap.Value.Track.Restart();
}
};
+ }
+ protected override void LoadComplete()
+ {
+ base.LoadComplete();
+
+ list.Items.BindTo(beatmapSets);
beatmap.BindValueChanged(working => list.SelectedSet.Value = working.NewValue.BeatmapSetInfo, true);
}
diff --git a/osu.Game/Overlays/MusicController.cs b/osu.Game/Overlays/MusicController.cs
index 7c7daf6eb9..d788929739 100644
--- a/osu.Game/Overlays/MusicController.cs
+++ b/osu.Game/Overlays/MusicController.cs
@@ -25,7 +25,16 @@ namespace osu.Game.Overlays
[Resolved]
private BeatmapManager beatmaps { get; set; }
- public IBindableList BeatmapSets => beatmapSets;
+ public IBindableList BeatmapSets
+ {
+ get
+ {
+ if (LoadState < LoadState.Ready)
+ throw new InvalidOperationException($"{nameof(BeatmapSets)} should not be accessed before the music controller is loaded.");
+
+ return beatmapSets;
+ }
+ }
///
/// Point in time after which the current track will be restarted on triggering a "previous track" action.
@@ -54,16 +63,18 @@ namespace osu.Game.Overlays
[BackgroundDependencyLoader]
private void load()
{
- beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next()));
beatmaps.ItemAdded += handleBeatmapAdded;
beatmaps.ItemRemoved += handleBeatmapRemoved;
+
+ beatmapSets.AddRange(beatmaps.GetAllUsableBeatmapSets().OrderBy(_ => RNG.Next()));
}
protected override void LoadComplete()
{
+ base.LoadComplete();
+
beatmap.BindValueChanged(beatmapChanged, true);
mods.BindValueChanged(_ => ResetTrackAdjustments(), true);
- base.LoadComplete();
}
///
@@ -82,11 +93,16 @@ namespace osu.Game.Overlays
///
public bool IsPlaying => current?.Track.IsRunning ?? false;
- private void handleBeatmapAdded(BeatmapSetInfo set) =>
- Schedule(() => beatmapSets.Add(set));
+ private void handleBeatmapAdded(BeatmapSetInfo set) => Schedule(() =>
+ {
+ if (!beatmapSets.Contains(set))
+ beatmapSets.Add(set);
+ });
- private void handleBeatmapRemoved(BeatmapSetInfo set) =>
- Schedule(() => beatmapSets.RemoveAll(s => s.ID == set.ID));
+ private void handleBeatmapRemoved(BeatmapSetInfo set) => Schedule(() =>
+ {
+ beatmapSets.RemoveAll(s => s.ID == set.ID);
+ });
private ScheduledDelegate seekDelegate;
diff --git a/osu.Game/Overlays/NowPlayingOverlay.cs b/osu.Game/Overlays/NowPlayingOverlay.cs
index dfcf99d30c..118cb037cb 100644
--- a/osu.Game/Overlays/NowPlayingOverlay.cs
+++ b/osu.Game/Overlays/NowPlayingOverlay.cs
@@ -58,6 +58,9 @@ namespace osu.Game.Overlays
[Resolved]
private Bindable beatmap { get; set; }
+ [Resolved]
+ private OsuColour colours { get; set; }
+
public NowPlayingOverlay()
{
Width = 400;
@@ -65,7 +68,7 @@ namespace osu.Game.Overlays
}
[BackgroundDependencyLoader]
- private void load(OsuColour colours)
+ private void load()
{
Children = new Drawable[]
{
@@ -182,15 +185,15 @@ namespace osu.Game.Overlays
}
}
};
-
- playlist.BeatmapSets.BindTo(musicController.BeatmapSets);
- playlist.State.ValueChanged += s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint);
}
protected override void LoadComplete()
{
base.LoadComplete();
+ playlist.BeatmapSets.BindTo(musicController.BeatmapSets);
+ playlist.State.BindValueChanged(s => playlistButton.FadeColour(s.NewValue == Visibility.Visible ? colours.Yellow : Color4.White, 200, Easing.OutQuint), true);
+
beatmap.BindDisabledChanged(beatmapDisabledChanged, true);
musicController.TrackChanged += trackChanged;
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index bd5219b872..6b8f8fee8c 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -22,7 +22,7 @@
-
+
diff --git a/osu.iOS.props b/osu.iOS.props
index 2c1aff7d3c..f68bedc57f 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -73,7 +73,7 @@
-
+