From 9f24cdb355bff38f788c6b2cb6e1f8bfce0b7e5b Mon Sep 17 00:00:00 2001
From: Denrage <denrage@gmail.com>
Date: Mon, 19 Apr 2021 16:53:44 +0200
Subject: [PATCH 01/15] Added Author Link in BeatmapInfoWedge

---
 osu.Game/Screens/Select/BeatmapInfoWedge.cs | 29 +++++++++------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs
index 4069dc82ed..14e5831ef9 100644
--- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs
+++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs
@@ -29,6 +29,7 @@ using osu.Game.Rulesets;
 using osu.Game.Rulesets.Mods;
 using osu.Game.Rulesets.UI;
 using osu.Game.Screens.Ranking.Expanded;
+using osu.Game.Graphics.Containers;
 
 namespace osu.Game.Screens.Select
 {
@@ -307,7 +308,7 @@ namespace osu.Game.Screens.Select
                                 Margin = new MarginPadding { Top = 10 },
                                 Direction = FillDirection.Horizontal,
                                 AutoSizeAxes = Axes.Both,
-                                Children = getMapper(metadata)
+                                Children = new[] { getMapper(metadata) },
                             },
                             infoLabelContainer = new FillFlowContainer
                             {
@@ -430,24 +431,20 @@ namespace osu.Game.Screens.Select
                 ForceRedraw();
             }
 
-            private OsuSpriteText[] getMapper(BeatmapMetadata metadata)
+            private LinkFlowContainer getMapper(BeatmapMetadata metadata)
             {
-                if (string.IsNullOrEmpty(metadata.Author?.Username))
-                    return Array.Empty<OsuSpriteText>();
+                if (metadata.Author == null)
+                    return new LinkFlowContainer();
 
-                return new[]
+                return new LinkFlowContainer(s =>
                 {
-                    new OsuSpriteText
-                    {
-                        Text = "mapped by ",
-                        Font = OsuFont.GetFont(size: 15),
-                    },
-                    new OsuSpriteText
-                    {
-                        Text = metadata.Author.Username,
-                        Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15),
-                    }
-                };
+                    s.Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 15);
+                }).With(d =>
+                {
+                    d.AutoSizeAxes = Axes.Both;
+                    d.AddText("mapped by ");
+                    d.AddUserLink(metadata.Author);
+                });
             }
 
             protected override void Dispose(bool isDisposing)

From eb977312ed71bee57676714afb2a81c0522bdd9d Mon Sep 17 00:00:00 2001
From: Denrage <denrage@gmail.com>
Date: Mon, 19 Apr 2021 16:54:29 +0200
Subject: [PATCH 02/15] Added Author link in BeatmapSet Overlay

---
 osu.Game/Overlays/BeatmapSet/AuthorInfo.cs | 23 +++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs
index 31c1439c8f..1ffcf9722a 100644
--- a/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs
+++ b/osu.Game/Overlays/BeatmapSet/AuthorInfo.cs
@@ -13,6 +13,8 @@ using osuTK.Graphics;
 using osu.Framework.Graphics.Effects;
 using osu.Framework.Graphics.Sprites;
 using osu.Game.Graphics;
+using osu.Game.Users;
+using osu.Game.Graphics.Containers;
 
 namespace osu.Game.Overlays.BeatmapSet
 {
@@ -50,7 +52,7 @@ namespace osu.Game.Overlays.BeatmapSet
 
             fields.Children = new Drawable[]
             {
-                new Field("mapped by", BeatmapSet.Metadata.Author.Username, OsuFont.GetFont(weight: FontWeight.Regular, italics: true)),
+                new Field("mapped by", BeatmapSet.Metadata.Author, OsuFont.GetFont(weight: FontWeight.Regular, italics: true)),
                 new Field("submitted", online.Submitted, OsuFont.GetFont(weight: FontWeight.Bold))
                 {
                     Margin = new MarginPadding { Top = 5 },
@@ -146,6 +148,25 @@ namespace osu.Game.Overlays.BeatmapSet
                     }
                 };
             }
+
+            public Field(string first, User second, FontUsage secondFont)
+            {
+                AutoSizeAxes = Axes.Both;
+                Direction = FillDirection.Horizontal;
+
+                Children = new[]
+                {
+                    new LinkFlowContainer(s =>
+                    {
+                        s.Font = OsuFont.GetFont(size: 11);
+                    }).With(d =>
+                    {
+                        d.AutoSizeAxes = Axes.Both;
+                        d.AddText($"{first} ");
+                        d.AddUserLink(second, s => s.Font = secondFont.With(size: 11));
+                    }),
+                };
+            }
         }
     }
 }

From 6bf6084ae9c3129d8a5672946e33205e8eabfcd3 Mon Sep 17 00:00:00 2001
From: Denrage <denrage@gmail.com>
Date: Mon, 19 Apr 2021 19:24:46 +0200
Subject: [PATCH 03/15] fixed according to suggestions

---
 osu.Game/Screens/Select/BeatmapInfoWedge.cs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/osu.Game/Screens/Select/BeatmapInfoWedge.cs b/osu.Game/Screens/Select/BeatmapInfoWedge.cs
index 14e5831ef9..deb77c27de 100644
--- a/osu.Game/Screens/Select/BeatmapInfoWedge.cs
+++ b/osu.Game/Screens/Select/BeatmapInfoWedge.cs
@@ -308,7 +308,7 @@ namespace osu.Game.Screens.Select
                                 Margin = new MarginPadding { Top = 10 },
                                 Direction = FillDirection.Horizontal,
                                 AutoSizeAxes = Axes.Both,
-                                Children = new[] { getMapper(metadata) },
+                                Child = getMapper(metadata),
                             },
                             infoLabelContainer = new FillFlowContainer
                             {
@@ -431,10 +431,10 @@ namespace osu.Game.Screens.Select
                 ForceRedraw();
             }
 
-            private LinkFlowContainer getMapper(BeatmapMetadata metadata)
+            private Drawable getMapper(BeatmapMetadata metadata)
             {
                 if (metadata.Author == null)
-                    return new LinkFlowContainer();
+                    return Empty();
 
                 return new LinkFlowContainer(s =>
                 {

From c73bbf0aa7566c1bf33784caacb91fc786a7a2cc Mon Sep 17 00:00:00 2001
From: Denrage <denrage@gmail.com>
Date: Mon, 19 Apr 2021 19:24:58 +0200
Subject: [PATCH 04/15] Fixed Tests

---
 osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs
index 7ea6373763..16afc5ace7 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapInfoWedge.cs
@@ -107,7 +107,7 @@ namespace osu.Game.Tests.Visual.SongSelect
             AddAssert("check version", () => infoWedge.Info.VersionLabel.Current.Value == $"{ruleset.ShortName}Version");
             AddAssert("check title", () => infoWedge.Info.TitleLabel.Current.Value == $"{ruleset.ShortName}Source — {ruleset.ShortName}Title");
             AddAssert("check artist", () => infoWedge.Info.ArtistLabel.Current.Value == $"{ruleset.ShortName}Artist");
-            AddAssert("check author", () => infoWedge.Info.MapperContainer.Children.OfType<OsuSpriteText>().Any(s => s.Current.Value == $"{ruleset.ShortName}Author"));
+            AddAssert("check author", () => infoWedge.Info.MapperContainer.ChildrenOfType<OsuSpriteText>().Any(s => s.Current.Value == $"{ruleset.ShortName}Author"));
         }
 
         private void testInfoLabels(int expectedCount)
@@ -123,7 +123,7 @@ namespace osu.Game.Tests.Visual.SongSelect
             AddAssert("check empty version", () => string.IsNullOrEmpty(infoWedge.Info.VersionLabel.Current.Value));
             AddAssert("check default title", () => infoWedge.Info.TitleLabel.Current.Value == Beatmap.Default.BeatmapInfo.Metadata.Title);
             AddAssert("check default artist", () => infoWedge.Info.ArtistLabel.Current.Value == Beatmap.Default.BeatmapInfo.Metadata.Artist);
-            AddAssert("check empty author", () => !infoWedge.Info.MapperContainer.Children.Any());
+            AddAssert("check empty author", () => !infoWedge.Info.MapperContainer.ChildrenOfType<OsuSpriteText>().Any());
             AddAssert("check no info labels", () => !infoWedge.Info.ChildrenOfType<BeatmapInfoWedge.BufferedWedgeInfo.InfoLabel>().Any());
         }
 

From d4658c609b61d3f15cccbe840023bb6003efc91c Mon Sep 17 00:00:00 2001
From: Joseph Madamba <madamba.joehu@outlook.com>
Date: Wed, 5 May 2021 22:43:16 -0700
Subject: [PATCH 05/15] Fix warning text of bg source setting not being updated
 when user with supporter signs in/out

---
 .../Settings/Sections/UserInterface/MainMenuSettings.cs       | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs
index 7c4c88f344..5f703ed5a4 100644
--- a/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs
+++ b/osu.Game/Overlays/Settings/Sections/UserInterface/MainMenuSettings.cs
@@ -57,11 +57,11 @@ namespace osu.Game.Overlays.Settings.Sections.UserInterface
         {
             base.LoadComplete();
 
-            backgroundSourceDropdown.Current.BindValueChanged(source =>
+            user.BindValueChanged(u =>
             {
                 const string not_supporter_note = "Changes to this setting will only apply with an active osu!supporter tag.";
 
-                backgroundSourceDropdown.WarningText = user.Value?.IsSupporter != true ? not_supporter_note : string.Empty;
+                backgroundSourceDropdown.WarningText = u.NewValue?.IsSupporter != true ? not_supporter_note : string.Empty;
             }, true);
         }
     }

From af75c9ac82ab73f43188284eef35a67b7bf1dbfd Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Thu, 6 May 2021 16:08:28 +0900
Subject: [PATCH 06/15] Update framework

---
 osu.Android.props        | 2 +-
 osu.Game/osu.Game.csproj | 2 +-
 osu.iOS.props            | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/osu.Android.props b/osu.Android.props
index 5aee9e15cc..99cda7693d 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,6 +52,6 @@
   </ItemGroup>
   <ItemGroup>
     <PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
-    <PackageReference Include="ppy.osu.Framework.Android" Version="2021.427.0" />
+    <PackageReference Include="ppy.osu.Framework.Android" Version="2021.506.0" />
   </ItemGroup>
 </Project>
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index 1e0eabfff7..e448972066 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -29,7 +29,7 @@
     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
     <PackageReference Include="Microsoft.NETCore.Targets" Version="3.1.0" />
     <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
-    <PackageReference Include="ppy.osu.Framework" Version="2021.427.0" />
+    <PackageReference Include="ppy.osu.Framework" Version="2021.506.0" />
     <PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
     <PackageReference Include="Sentry" Version="3.3.4" />
     <PackageReference Include="SharpCompress" Version="0.28.2" />
diff --git a/osu.iOS.props b/osu.iOS.props
index e26e727e69..43ed2d7dc8 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -70,7 +70,7 @@
     <Reference Include="System.Net.Http" />
   </ItemGroup>
   <ItemGroup Label="Package References">
-    <PackageReference Include="ppy.osu.Framework.iOS" Version="2021.427.0" />
+    <PackageReference Include="ppy.osu.Framework.iOS" Version="2021.506.0" />
     <PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
   </ItemGroup>
   <!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
@@ -93,7 +93,7 @@
     <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
     <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
     <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
-    <PackageReference Include="ppy.osu.Framework" Version="2021.427.0" />
+    <PackageReference Include="ppy.osu.Framework" Version="2021.506.0" />
     <PackageReference Include="SharpCompress" Version="0.28.2" />
     <PackageReference Include="NUnit" Version="3.13.2" />
     <PackageReference Include="SharpRaven" Version="2.4.0" />

From 84da24700204724cde9a8b90506b078add49c964 Mon Sep 17 00:00:00 2001
From: Salman Ahmed <frenzibyte@gmail.com>
Date: Fri, 7 May 2021 05:32:55 +0300
Subject: [PATCH 07/15] Fix editor clock using the wrong beatmap track on
 creation

---
 osu.Game/Screens/Edit/Editor.cs | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs
index da0e9ebbaf..138d8cfaff 100644
--- a/osu.Game/Screens/Edit/Editor.cs
+++ b/osu.Game/Screens/Edit/Editor.cs
@@ -145,7 +145,7 @@ namespace osu.Game.Screens.Edit
             // Todo: should probably be done at a DrawableRuleset level to share logic with Player.
             clock = new EditorClock(playableBeatmap, beatDivisor) { IsCoupled = false };
 
-            UpdateClockSource();
+            updateClockSource(loadableBeatmap);
 
             dependencies.CacheAs(clock);
             AddInternal(clock);
@@ -308,9 +308,11 @@ namespace osu.Game.Screens.Edit
         /// <summary>
         /// If the beatmap's track has changed, this method must be called to keep the editor in a valid state.
         /// </summary>
-        public void UpdateClockSource()
+        public void UpdateClockSource() => updateClockSource(Beatmap.Value);
+
+        private void updateClockSource(WorkingBeatmap beatmap)
         {
-            var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
+            var sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock();
             clock.ChangeSource(sourceClock);
         }
 

From 539643c72b390b1c40b8fb8340b37f33ef91d7d5 Mon Sep 17 00:00:00 2001
From: Salman Ahmed <frenzibyte@gmail.com>
Date: Fri, 7 May 2021 07:18:43 +0300
Subject: [PATCH 08/15] Set loadable beatmap track to clock immediately in BDL

This reverts commit 84da24700204724cde9a8b90506b078add49c964.

Use loadable beatmap track for clock directly in BDL
---
 osu.Game/Screens/Edit/Editor.cs | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs
index 138d8cfaff..a4c331c4e0 100644
--- a/osu.Game/Screens/Edit/Editor.cs
+++ b/osu.Game/Screens/Edit/Editor.cs
@@ -144,8 +144,7 @@ namespace osu.Game.Screens.Edit
 
             // Todo: should probably be done at a DrawableRuleset level to share logic with Player.
             clock = new EditorClock(playableBeatmap, beatDivisor) { IsCoupled = false };
-
-            updateClockSource(loadableBeatmap);
+            clock.ChangeSource(loadableBeatmap.Track);
 
             dependencies.CacheAs(clock);
             AddInternal(clock);
@@ -308,11 +307,9 @@ namespace osu.Game.Screens.Edit
         /// <summary>
         /// If the beatmap's track has changed, this method must be called to keep the editor in a valid state.
         /// </summary>
-        public void UpdateClockSource() => updateClockSource(Beatmap.Value);
-
-        private void updateClockSource(WorkingBeatmap beatmap)
+        public void UpdateClockSource()
         {
-            var sourceClock = (IAdjustableClock)beatmap.Track ?? new StopwatchClock();
+            var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
             clock.ChangeSource(sourceClock);
         }
 

From f9d99a98826525b58d8a076f772da6a9a77329ec Mon Sep 17 00:00:00 2001
From: Salman Ahmed <frenzibyte@gmail.com>
Date: Fri, 7 May 2021 07:25:14 +0300
Subject: [PATCH 09/15] Mark `WorkingBeatmap.Track` as not null

---
 osu.Game/Beatmaps/WorkingBeatmap.cs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs
index e0eeaf6db0..bef258753e 100644
--- a/osu.Game/Beatmaps/WorkingBeatmap.cs
+++ b/osu.Game/Beatmaps/WorkingBeatmap.cs
@@ -298,6 +298,7 @@ namespace osu.Game.Beatmaps
         /// Get the loaded audio track instance. <see cref="LoadTrack"/> must have first been called.
         /// This generally happens via MusicController when changing the global beatmap.
         /// </summary>
+        [NotNull]
         public Track Track
         {
             get

From 71547bece0dcd99cfbe6ba95bd2e42066b6eb686 Mon Sep 17 00:00:00 2001
From: Salman Ahmed <frenzibyte@gmail.com>
Date: Fri, 7 May 2021 07:43:06 +0300
Subject: [PATCH 10/15] Remove any null-coalescing/conditionals in
 `WorkingBeatmap.Track` usages

---
 osu.Game/Screens/Edit/Editor.cs               | 9 ++-------
 osu.Game/Tests/Visual/EditorClockTestScene.cs | 3 +--
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs
index a4c331c4e0..434683a016 100644
--- a/osu.Game/Screens/Edit/Editor.cs
+++ b/osu.Game/Screens/Edit/Editor.cs
@@ -17,7 +17,6 @@ using osu.Framework.Input.Bindings;
 using osu.Framework.Input.Events;
 using osu.Framework.Logging;
 using osu.Framework.Screens;
-using osu.Framework.Timing;
 using osu.Game.Beatmaps;
 using osu.Game.Configuration;
 using osu.Game.Graphics;
@@ -307,11 +306,7 @@ namespace osu.Game.Screens.Edit
         /// <summary>
         /// If the beatmap's track has changed, this method must be called to keep the editor in a valid state.
         /// </summary>
-        public void UpdateClockSource()
-        {
-            var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
-            clock.ChangeSource(sourceClock);
-        }
+        public void UpdateClockSource() => clock.ChangeSource(Beatmap.Value.Track);
 
         protected void Save()
         {
@@ -582,7 +577,7 @@ namespace osu.Game.Screens.Edit
 
         private void resetTrack(bool seekToStart = false)
         {
-            Beatmap.Value.Track?.Stop();
+            Beatmap.Value.Track.Stop();
 
             if (seekToStart)
             {
diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs
index 79cfee8518..34393fba7d 100644
--- a/osu.Game/Tests/Visual/EditorClockTestScene.cs
+++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs
@@ -4,7 +4,6 @@
 using osu.Framework.Allocation;
 using osu.Framework.Bindables;
 using osu.Framework.Input.Events;
-using osu.Framework.Timing;
 using osu.Game.Beatmaps;
 using osu.Game.Beatmaps.ControlPoints;
 using osu.Game.Screens.Edit;
@@ -46,7 +45,7 @@ namespace osu.Game.Tests.Visual
         private void beatmapChanged(ValueChangedEvent<WorkingBeatmap> e)
         {
             Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo;
-            Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock());
+            Clock.ChangeSource(e.NewValue.Track);
             Clock.ProcessFrame();
         }
 

From 37f44d2e37602ec557ed7fda6ca7afced0bfec81 Mon Sep 17 00:00:00 2001
From: Salman Ahmed <frenzibyte@gmail.com>
Date: Fri, 7 May 2021 08:27:56 +0300
Subject: [PATCH 11/15] Revert wrong not-null track changes

This reverts commit f9d99a98826525b58d8a076f772da6a9a77329ec.
This reverts commit 71547bece0dcd99cfbe6ba95bd2e42066b6eb686.
---
 osu.Game/Beatmaps/WorkingBeatmap.cs           | 1 -
 osu.Game/Screens/Edit/Editor.cs               | 9 +++++++--
 osu.Game/Tests/Visual/EditorClockTestScene.cs | 3 ++-
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/osu.Game/Beatmaps/WorkingBeatmap.cs b/osu.Game/Beatmaps/WorkingBeatmap.cs
index bef258753e..e0eeaf6db0 100644
--- a/osu.Game/Beatmaps/WorkingBeatmap.cs
+++ b/osu.Game/Beatmaps/WorkingBeatmap.cs
@@ -298,7 +298,6 @@ namespace osu.Game.Beatmaps
         /// Get the loaded audio track instance. <see cref="LoadTrack"/> must have first been called.
         /// This generally happens via MusicController when changing the global beatmap.
         /// </summary>
-        [NotNull]
         public Track Track
         {
             get
diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs
index 434683a016..a4c331c4e0 100644
--- a/osu.Game/Screens/Edit/Editor.cs
+++ b/osu.Game/Screens/Edit/Editor.cs
@@ -17,6 +17,7 @@ using osu.Framework.Input.Bindings;
 using osu.Framework.Input.Events;
 using osu.Framework.Logging;
 using osu.Framework.Screens;
+using osu.Framework.Timing;
 using osu.Game.Beatmaps;
 using osu.Game.Configuration;
 using osu.Game.Graphics;
@@ -306,7 +307,11 @@ namespace osu.Game.Screens.Edit
         /// <summary>
         /// If the beatmap's track has changed, this method must be called to keep the editor in a valid state.
         /// </summary>
-        public void UpdateClockSource() => clock.ChangeSource(Beatmap.Value.Track);
+        public void UpdateClockSource()
+        {
+            var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
+            clock.ChangeSource(sourceClock);
+        }
 
         protected void Save()
         {
@@ -577,7 +582,7 @@ namespace osu.Game.Screens.Edit
 
         private void resetTrack(bool seekToStart = false)
         {
-            Beatmap.Value.Track.Stop();
+            Beatmap.Value.Track?.Stop();
 
             if (seekToStart)
             {
diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs
index 34393fba7d..79cfee8518 100644
--- a/osu.Game/Tests/Visual/EditorClockTestScene.cs
+++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs
@@ -4,6 +4,7 @@
 using osu.Framework.Allocation;
 using osu.Framework.Bindables;
 using osu.Framework.Input.Events;
+using osu.Framework.Timing;
 using osu.Game.Beatmaps;
 using osu.Game.Beatmaps.ControlPoints;
 using osu.Game.Screens.Edit;
@@ -45,7 +46,7 @@ namespace osu.Game.Tests.Visual
         private void beatmapChanged(ValueChangedEvent<WorkingBeatmap> e)
         {
             Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo;
-            Clock.ChangeSource(e.NewValue.Track);
+            Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock());
             Clock.ProcessFrame();
         }
 

From b1134c3857980e5f473dc3ba3f57d1ab7bdcabdb Mon Sep 17 00:00:00 2001
From: Salman Ahmed <frenzibyte@gmail.com>
Date: Fri, 7 May 2021 08:30:50 +0300
Subject: [PATCH 12/15] Guard against potentially null track if ever

---
 osu.Game/Screens/Edit/Editor.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs
index a4c331c4e0..78d5c24108 100644
--- a/osu.Game/Screens/Edit/Editor.cs
+++ b/osu.Game/Screens/Edit/Editor.cs
@@ -144,7 +144,7 @@ namespace osu.Game.Screens.Edit
 
             // Todo: should probably be done at a DrawableRuleset level to share logic with Player.
             clock = new EditorClock(playableBeatmap, beatDivisor) { IsCoupled = false };
-            clock.ChangeSource(loadableBeatmap.Track);
+            clock.ChangeSource((IAdjustableClock)loadableBeatmap.Track ?? new StopwatchClock());
 
             dependencies.CacheAs(clock);
             AddInternal(clock);

From 7c4e54a1d43990996e015affd03911514dc18952 Mon Sep 17 00:00:00 2001
From: Salman Ahmed <frenzibyte@gmail.com>
Date: Fri, 7 May 2021 09:53:54 +0300
Subject: [PATCH 13/15] Unrevert null-colaescing/conditionals removal

---
 osu.Game/Screens/Edit/Editor.cs               | 8 ++------
 osu.Game/Tests/Visual/EditorClockTestScene.cs | 3 +--
 2 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs
index 78d5c24108..50dcb84235 100644
--- a/osu.Game/Screens/Edit/Editor.cs
+++ b/osu.Game/Screens/Edit/Editor.cs
@@ -307,11 +307,7 @@ namespace osu.Game.Screens.Edit
         /// <summary>
         /// If the beatmap's track has changed, this method must be called to keep the editor in a valid state.
         /// </summary>
-        public void UpdateClockSource()
-        {
-            var sourceClock = (IAdjustableClock)Beatmap.Value.Track ?? new StopwatchClock();
-            clock.ChangeSource(sourceClock);
-        }
+        public void UpdateClockSource() => clock.ChangeSource(Beatmap.Value.Track);
 
         protected void Save()
         {
@@ -582,7 +578,7 @@ namespace osu.Game.Screens.Edit
 
         private void resetTrack(bool seekToStart = false)
         {
-            Beatmap.Value.Track?.Stop();
+            Beatmap.Value.Track.Stop();
 
             if (seekToStart)
             {
diff --git a/osu.Game/Tests/Visual/EditorClockTestScene.cs b/osu.Game/Tests/Visual/EditorClockTestScene.cs
index 79cfee8518..34393fba7d 100644
--- a/osu.Game/Tests/Visual/EditorClockTestScene.cs
+++ b/osu.Game/Tests/Visual/EditorClockTestScene.cs
@@ -4,7 +4,6 @@
 using osu.Framework.Allocation;
 using osu.Framework.Bindables;
 using osu.Framework.Input.Events;
-using osu.Framework.Timing;
 using osu.Game.Beatmaps;
 using osu.Game.Beatmaps.ControlPoints;
 using osu.Game.Screens.Edit;
@@ -46,7 +45,7 @@ namespace osu.Game.Tests.Visual
         private void beatmapChanged(ValueChangedEvent<WorkingBeatmap> e)
         {
             Clock.ControlPointInfo = e.NewValue.Beatmap.ControlPointInfo;
-            Clock.ChangeSource((IAdjustableClock)e.NewValue.Track ?? new StopwatchClock());
+            Clock.ChangeSource(e.NewValue.Track);
             Clock.ProcessFrame();
         }
 

From fc2a527e9d419040697cd4e075c7ae04d1cd2c82 Mon Sep 17 00:00:00 2001
From: Salman Ahmed <frenzibyte@gmail.com>
Date: Fri, 7 May 2021 09:54:58 +0300
Subject: [PATCH 14/15] Revert "Guard against potentially null track if ever"

This reverts commit b1134c3857980e5f473dc3ba3f57d1ab7bdcabdb.
---
 osu.Game/Screens/Edit/Editor.cs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/osu.Game/Screens/Edit/Editor.cs b/osu.Game/Screens/Edit/Editor.cs
index 50dcb84235..434683a016 100644
--- a/osu.Game/Screens/Edit/Editor.cs
+++ b/osu.Game/Screens/Edit/Editor.cs
@@ -17,7 +17,6 @@ using osu.Framework.Input.Bindings;
 using osu.Framework.Input.Events;
 using osu.Framework.Logging;
 using osu.Framework.Screens;
-using osu.Framework.Timing;
 using osu.Game.Beatmaps;
 using osu.Game.Configuration;
 using osu.Game.Graphics;
@@ -144,7 +143,7 @@ namespace osu.Game.Screens.Edit
 
             // Todo: should probably be done at a DrawableRuleset level to share logic with Player.
             clock = new EditorClock(playableBeatmap, beatDivisor) { IsCoupled = false };
-            clock.ChangeSource((IAdjustableClock)loadableBeatmap.Track ?? new StopwatchClock());
+            clock.ChangeSource(loadableBeatmap.Track);
 
             dependencies.CacheAs(clock);
             AddInternal(clock);

From 5b2f786f971ef65100be176ebc828b87e87f8c3f Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Fri, 7 May 2021 19:16:00 +0900
Subject: [PATCH 15/15] Update framework

---
 osu.Android.props        | 2 +-
 osu.Game/osu.Game.csproj | 2 +-
 osu.iOS.props            | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/osu.Android.props b/osu.Android.props
index 99cda7693d..80b1c5b52f 100644
--- a/osu.Android.props
+++ b/osu.Android.props
@@ -52,6 +52,6 @@
   </ItemGroup>
   <ItemGroup>
     <PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
-    <PackageReference Include="ppy.osu.Framework.Android" Version="2021.506.0" />
+    <PackageReference Include="ppy.osu.Framework.Android" Version="2021.507.0" />
   </ItemGroup>
 </Project>
diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj
index e448972066..29189781a7 100644
--- a/osu.Game/osu.Game.csproj
+++ b/osu.Game/osu.Game.csproj
@@ -29,7 +29,7 @@
     <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
     <PackageReference Include="Microsoft.NETCore.Targets" Version="3.1.0" />
     <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
-    <PackageReference Include="ppy.osu.Framework" Version="2021.506.0" />
+    <PackageReference Include="ppy.osu.Framework" Version="2021.507.0" />
     <PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
     <PackageReference Include="Sentry" Version="3.3.4" />
     <PackageReference Include="SharpCompress" Version="0.28.2" />
diff --git a/osu.iOS.props b/osu.iOS.props
index 43ed2d7dc8..c4eb7aefba 100644
--- a/osu.iOS.props
+++ b/osu.iOS.props
@@ -70,7 +70,7 @@
     <Reference Include="System.Net.Http" />
   </ItemGroup>
   <ItemGroup Label="Package References">
-    <PackageReference Include="ppy.osu.Framework.iOS" Version="2021.506.0" />
+    <PackageReference Include="ppy.osu.Framework.iOS" Version="2021.507.0" />
     <PackageReference Include="ppy.osu.Game.Resources" Version="2021.422.0" />
   </ItemGroup>
   <!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
@@ -93,7 +93,7 @@
     <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
     <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
     <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
-    <PackageReference Include="ppy.osu.Framework" Version="2021.506.0" />
+    <PackageReference Include="ppy.osu.Framework" Version="2021.507.0" />
     <PackageReference Include="SharpCompress" Version="0.28.2" />
     <PackageReference Include="NUnit" Version="3.13.2" />
     <PackageReference Include="SharpRaven" Version="2.4.0" />