diff --git a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs
index 05b33e4386..0025a26baf 100644
--- a/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs
+++ b/osu.Game.Tests/Visual/Online/TestSceneChatOverlay.cs
@@ -246,7 +246,12 @@ namespace osu.Game.Tests.Visual.Online
             {
                 ((BindableList<Channel>)ChannelManager.AvailableChannels).AddRange(channels);
 
-                Child = ChatOverlay = new TestChatOverlay { RelativeSizeAxes = Axes.Both, };
+                InternalChildren = new Drawable[]
+                {
+                    ChannelManager,
+                    ChatOverlay = new TestChatOverlay { RelativeSizeAxes = Axes.Both, },
+                };
+
                 ChatOverlay.Show();
             }
         }
diff --git a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs
index 745820696a..3d335995ac 100644
--- a/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs
+++ b/osu.Game.Tests/Visual/Settings/TestSceneKeyBindingPanel.cs
@@ -1,13 +1,19 @@
 // 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.
 
+using System.Diagnostics;
+using System.Linq;
 using NUnit.Framework;
+using osu.Framework.Testing;
+using osu.Framework.Threading;
 using osu.Game.Overlays;
+using osu.Game.Overlays.KeyBinding;
+using osuTK.Input;
 
 namespace osu.Game.Tests.Visual.Settings
 {
     [TestFixture]
-    public class TestSceneKeyBindingPanel : OsuTestScene
+    public class TestSceneKeyBindingPanel : OsuManualInputManagerTestScene
     {
         private readonly KeyBindingPanel panel;
 
@@ -21,5 +27,42 @@ namespace osu.Game.Tests.Visual.Settings
             base.LoadComplete();
             panel.Show();
         }
+
+        [Test]
+        public void TestClickTwiceOnClearButton()
+        {
+            KeyBindingRow firstRow = null;
+
+            AddStep("click first row", () =>
+            {
+                firstRow = panel.ChildrenOfType<KeyBindingRow>().First();
+                InputManager.MoveMouseTo(firstRow);
+                InputManager.Click(MouseButton.Left);
+            });
+
+            AddStep("schedule button clicks", () =>
+            {
+                var clearButton = firstRow.ChildrenOfType<KeyBindingRow.ClearButton>().Single();
+
+                InputManager.MoveMouseTo(clearButton);
+
+                int buttonClicks = 0;
+                ScheduledDelegate clickDelegate = null;
+
+                clickDelegate = Scheduler.AddDelayed(() =>
+                {
+                    InputManager.PressButton(MouseButton.Left);
+                    InputManager.ReleaseButton(MouseButton.Left);
+
+                    if (++buttonClicks == 2)
+                    {
+                        // ReSharper disable once AccessToModifiedClosure
+                        Debug.Assert(clickDelegate != null);
+                        // ReSharper disable once AccessToModifiedClosure
+                        clickDelegate.Cancel();
+                    }
+                }, 0, true);
+            });
+        }
     }
 }
diff --git a/osu.Game/Online/Chat/ChannelManager.cs b/osu.Game/Online/Chat/ChannelManager.cs
index 53872ddcba..b17e0812da 100644
--- a/osu.Game/Online/Chat/ChannelManager.cs
+++ b/osu.Game/Online/Chat/ChannelManager.cs
@@ -93,12 +93,6 @@ namespace osu.Game.Online.Chat
         {
             if (!(e.NewValue is ChannelSelectorTabItem.ChannelSelectorTabChannel))
                 JoinChannel(e.NewValue);
-
-            if (e.NewValue?.MessagesLoaded == false)
-            {
-                // let's fetch a small number of messages to bring us up-to-date with the backlog.
-                fetchInitalMessages(e.NewValue);
-            }
         }
 
         /// <summary>
@@ -240,7 +234,6 @@ namespace osu.Game.Online.Chat
                     }
 
                     JoinChannel(channel);
-                    CurrentChannel.Value = channel;
                     break;
 
                 case "help":
@@ -275,7 +268,7 @@ namespace osu.Game.Online.Chat
 
                     // join any channels classified as "defaults"
                     if (joinDefaults && defaultChannels.Any(c => c.Equals(channel.Name, StringComparison.OrdinalIgnoreCase)))
-                        JoinChannel(ch);
+                        joinChannel(ch);
                 }
             };
             req.Failure += error =>
@@ -296,7 +289,7 @@ namespace osu.Game.Online.Chat
         /// <param name="channel">The channel </param>
         private void fetchInitalMessages(Channel channel)
         {
-            if (channel.Id <= 0) return;
+            if (channel.Id <= 0 || channel.MessagesLoaded) return;
 
             var fetchInitialMsgReq = new GetMessagesRequest(channel);
             fetchInitialMsgReq.Success += messages =>
@@ -351,9 +344,10 @@ namespace osu.Game.Online.Chat
         /// Joins a channel if it has not already been joined.
         /// </summary>
         /// <param name="channel">The channel to join.</param>
-        /// <param name="alreadyJoined">Whether the channel has already been joined server-side. Will skip a join request.</param>
         /// <returns>The joined channel. Note that this may not match the parameter channel as it is a backed object.</returns>
-        public Channel JoinChannel(Channel channel, bool alreadyJoined = false)
+        public Channel JoinChannel(Channel channel) => joinChannel(channel, true);
+
+        private Channel joinChannel(Channel channel, bool fetchInitialMessages = false)
         {
             if (channel == null) return null;
 
@@ -362,21 +356,36 @@ namespace osu.Game.Online.Chat
             // ensure we are joined to the channel
             if (!channel.Joined.Value)
             {
-                if (alreadyJoined)
-                    channel.Joined.Value = true;
-                else
+                switch (channel.Type)
                 {
-                    switch (channel.Type)
-                    {
-                        case ChannelType.Public:
-                            var req = new JoinChannelRequest(channel, api.LocalUser.Value);
-                            req.Success += () => JoinChannel(channel, true);
-                            req.Failure += ex => LeaveChannel(channel);
-                            api.Queue(req);
-                            return channel;
-                    }
+                    case ChannelType.Multiplayer:
+                        // join is implicit. happens when you join a multiplayer game.
+                        // this will probably change in the future.
+                        channel.Joined.Value = true;
+                        joinChannel(channel, fetchInitialMessages);
+                        return channel;
+
+                    case ChannelType.Private:
+                        // can't do this yet.
+                        break;
+
+                    default:
+                        var req = new JoinChannelRequest(channel, api.LocalUser.Value);
+                        req.Success += () =>
+                        {
+                            channel.Joined.Value = true;
+                            joinChannel(channel, fetchInitialMessages);
+                        };
+                        req.Failure += ex => LeaveChannel(channel);
+                        api.Queue(req);
+                        return channel;
                 }
             }
+            else
+            {
+                if (fetchInitialMessages)
+                    fetchInitalMessages(channel);
+            }
 
             if (CurrentChannel.Value == null)
                 CurrentChannel.Value = channel;
@@ -420,7 +429,8 @@ namespace osu.Game.Online.Chat
                     foreach (var channel in updates.Presence)
                     {
                         // we received this from the server so should mark the channel already joined.
-                        JoinChannel(channel, true);
+                        channel.Joined.Value = true;
+                        joinChannel(channel);
                     }
 
                     //todo: handle left channels
diff --git a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs
index 01d5991d3e..eafb4572ca 100644
--- a/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs
+++ b/osu.Game/Overlays/KeyBinding/KeyBindingRow.cs
@@ -274,6 +274,9 @@ namespace osu.Game.Overlays.KeyBinding
 
         private void clear()
         {
+            if (bindTarget == null)
+                return;
+
             bindTarget.UpdateKeyCombination(InputKey.None);
             finalise();
         }
@@ -333,7 +336,7 @@ namespace osu.Game.Overlays.KeyBinding
             }
         }
 
-        private class ClearButton : TriangleButton
+        public class ClearButton : TriangleButton
         {
             public ClearButton()
             {
diff --git a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs
index fd8ac33aef..81d5d113ae 100644
--- a/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs
+++ b/osu.Game/Screens/Ranking/Expanded/ExpandedPanelMiddleContent.cs
@@ -211,7 +211,7 @@ namespace osu.Game.Screens.Ranking.Expanded
                         Anchor = Anchor.TopCentre,
                         Origin = Anchor.TopCentre,
                         Font = OsuFont.GetFont(size: 10, weight: FontWeight.SemiBold),
-                        Text = $"Played on {score.Date.ToLocalTime():g}"
+                        Text = $"Played on {score.Date.ToLocalTime():d MMMM yyyy HH:mm}"
                     }
                 }
             };
diff --git a/osu.Game/Screens/Ranking/ScorePanel.cs b/osu.Game/Screens/Ranking/ScorePanel.cs
index a99b48e8f0..65fb901c89 100644
--- a/osu.Game/Screens/Ranking/ScorePanel.cs
+++ b/osu.Game/Screens/Ranking/ScorePanel.cs
@@ -243,5 +243,10 @@ namespace osu.Game.Screens.Ranking
 
             return true;
         }
+
+        public override bool ReceivePositionalInputAt(Vector2 screenSpacePos)
+            => base.ReceivePositionalInputAt(screenSpacePos)
+               || topLayerContainer.ReceivePositionalInputAt(screenSpacePos)
+               || middleLayerContainer.ReceivePositionalInputAt(screenSpacePos);
     }
 }