From 789c921af1869435142f77c82fbdf5227c3a7af5 Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sat, 11 Jul 2020 06:47:52 +0300
Subject: [PATCH 01/17] Move replies button to a new line

---
 osu.Game/Overlays/Comments/DrawableComment.cs | 26 ++++++++++++-------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs
index 46f600615a..2a63060385 100644
--- a/osu.Game/Overlays/Comments/DrawableComment.cs
+++ b/osu.Game/Overlays/Comments/DrawableComment.cs
@@ -163,20 +163,28 @@ namespace osu.Game.Overlays.Comments
                                                     AutoSizeAxes = Axes.Y,
                                                     Padding = new MarginPadding { Right = 40 }
                                                 },
-                                                info = new FillFlowContainer
+                                                new FillFlowContainer
                                                 {
                                                     AutoSizeAxes = Axes.Both,
-                                                    Direction = FillDirection.Horizontal,
-                                                    Spacing = new Vector2(10, 0),
+                                                    Direction = FillDirection.Vertical,
                                                     Children = new Drawable[]
                                                     {
-                                                        new OsuSpriteText
+                                                        info = new FillFlowContainer
                                                         {
-                                                            Anchor = Anchor.CentreLeft,
-                                                            Origin = Anchor.CentreLeft,
-                                                            Font = OsuFont.GetFont(size: 12),
-                                                            Colour = OsuColour.Gray(0.7f),
-                                                            Text = HumanizerUtils.Humanize(Comment.CreatedAt)
+                                                            AutoSizeAxes = Axes.Both,
+                                                            Direction = FillDirection.Horizontal,
+                                                            Spacing = new Vector2(10, 0),
+                                                            Children = new Drawable[]
+                                                            {
+                                                                new OsuSpriteText
+                                                                {
+                                                                    Anchor = Anchor.CentreLeft,
+                                                                    Origin = Anchor.CentreLeft,
+                                                                    Font = OsuFont.GetFont(size: 12),
+                                                                    Colour = OsuColour.Gray(0.7f),
+                                                                    Text = HumanizerUtils.Humanize(Comment.CreatedAt)
+                                                                },
+                                                            }
                                                         },
                                                         repliesButton = new RepliesButton(Comment.RepliesCount)
                                                         {

From da249abd19382e9c3c6c0deeab0529f510314bd9 Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sat, 11 Jul 2020 07:47:17 +0300
Subject: [PATCH 02/17] Implement CommentRepliesButton

---
 .../TestSceneCommentRepliesButton.cs          |  54 ++++++++++
 .../Comments/Buttons/CommentRepliesButton.cs  | 100 ++++++++++++++++++
 .../Comments/Buttons/LoadRepliesButton.cs     |  10 ++
 .../Comments/Buttons/ShowRepliesButton.cs     |  19 ++++
 4 files changed, 183 insertions(+)
 create mode 100644 osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
 create mode 100644 osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
 create mode 100644 osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
 create mode 100644 osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs

diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
new file mode 100644
index 0000000000..b4f518a5d0
--- /dev/null
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
@@ -0,0 +1,54 @@
+// 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 osu.Game.Overlays.Comments.Buttons;
+using osu.Framework.Graphics;
+using osu.Framework.Allocation;
+using osu.Game.Overlays;
+using osu.Framework.Graphics.Containers;
+using osuTK;
+
+namespace osu.Game.Tests.Visual.UserInterface
+{
+    public class TestSceneCommentRepliesButton : OsuTestScene
+    {
+        [Cached]
+        private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
+
+        public TestSceneCommentRepliesButton()
+        {
+            Child = new FillFlowContainer
+            {
+                Anchor = Anchor.Centre,
+                Origin = Anchor.Centre,
+                AutoSizeAxes = Axes.Both,
+                Direction = FillDirection.Vertical,
+                Spacing = new Vector2(0, 10),
+                Children = new Drawable[]
+                {
+                    new TestButton
+                    {
+                        Action = () => { }
+                    },
+                    new LoadRepliesButton
+                    {
+                        Action = () => { }
+                    },
+                    new ShowRepliesButton(1)
+                    {
+                        Action = () => { }
+                    },
+                    new ShowRepliesButton(2)
+                    {
+                        Action = () => { }
+                    }
+                }
+            };
+        }
+
+        private class TestButton : CommentRepliesButton
+        {
+            protected override string GetText() => "sample text";
+        }
+    }
+}
diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
new file mode 100644
index 0000000000..13924200c2
--- /dev/null
+++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
@@ -0,0 +1,100 @@
+// 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.Collections.Generic;
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Framework.Graphics.Sprites;
+using osu.Game.Graphics;
+using osu.Game.Graphics.Containers;
+using osu.Game.Graphics.Sprites;
+using osuTK;
+
+namespace osu.Game.Overlays.Comments.Buttons
+{
+    public abstract class CommentRepliesButton : OsuHoverContainer
+    {
+        protected override IEnumerable<Drawable> EffectTargets => new[] { background };
+
+        protected ChevronIcon Icon;
+        private Box background;
+
+        public CommentRepliesButton()
+        {
+            AutoSizeAxes = Axes.Both;
+        }
+
+        [BackgroundDependencyLoader]
+        private void load(OverlayColourProvider colourProvider)
+        {
+            Add(new CircularContainer
+            {
+                AutoSizeAxes = Axes.Both,
+                Masking = true,
+                Children = new Drawable[]
+                {
+                    background = new Box
+                    {
+                        RelativeSizeAxes = Axes.Both
+                    },
+                    new Container
+                    {
+                        AutoSizeAxes = Axes.Both,
+                        Margin = new MarginPadding
+                        {
+                            Vertical = 5,
+                            Horizontal = 10,
+                        },
+                        Child = new FillFlowContainer
+                        {
+                            AutoSizeAxes = Axes.Both,
+                            Direction = FillDirection.Horizontal,
+                            Spacing = new Vector2(15, 0),
+                            Anchor = Anchor.Centre,
+                            Origin = Anchor.Centre,
+                            Children = new Drawable[]
+                            {
+                                new OsuSpriteText
+                                {
+                                    Anchor = Anchor.CentreLeft,
+                                    Origin = Anchor.CentreLeft,
+                                    Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold),
+                                    Text = GetText()
+                                },
+                                Icon = new ChevronIcon
+                                {
+                                    Anchor = Anchor.CentreLeft,
+                                    Origin = Anchor.CentreLeft,
+                                }
+                            }
+                        }
+                    }
+                }
+            });
+
+            IdleColour = colourProvider.Background2;
+            HoverColour = colourProvider.Background1;
+        }
+
+        protected abstract string GetText();
+
+        protected class ChevronIcon : SpriteIcon
+        {
+            public ChevronIcon()
+            {
+                Anchor = Anchor.Centre;
+                Origin = Anchor.Centre;
+                Size = new Vector2(7.5f);
+                Icon = FontAwesome.Solid.ChevronDown;
+            }
+
+            [BackgroundDependencyLoader]
+            private void load(OverlayColourProvider colourProvider)
+            {
+                Colour = colourProvider.Foreground1;
+            }
+        }
+    }
+}
diff --git a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
new file mode 100644
index 0000000000..41cce72272
--- /dev/null
+++ b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
@@ -0,0 +1,10 @@
+// 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.
+
+namespace osu.Game.Overlays.Comments.Buttons
+{
+    public class LoadRepliesButton : CommentRepliesButton
+    {
+        protected override string GetText() => "load replies";
+    }
+}
diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
new file mode 100644
index 0000000000..1e8c732453
--- /dev/null
+++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
@@ -0,0 +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 Humanizer;
+
+namespace osu.Game.Overlays.Comments.Buttons
+{
+    public class ShowRepliesButton : CommentRepliesButton
+    {
+        private readonly int count;
+
+        public ShowRepliesButton(int count)
+        {
+            this.count = count;
+        }
+
+        protected override string GetText() => "reply".ToQuantity(count);
+    }
+}

From 0861ee0c8e985bb413681037ab54ea00f1910d82 Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sat, 11 Jul 2020 07:54:37 +0300
Subject: [PATCH 03/17] Make Icon rotate when clicking ShowRepliesButton

---
 .../Comments/Buttons/ShowRepliesButton.cs     | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
index 1e8c732453..2381727431 100644
--- a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
@@ -2,11 +2,17 @@
 // See the LICENCE file in the repository root for full licence text.
 
 using Humanizer;
+using osu.Framework.Bindables;
+using osu.Framework.Graphics;
+using osu.Framework.Input.Events;
+using osuTK;
 
 namespace osu.Game.Overlays.Comments.Buttons
 {
     public class ShowRepliesButton : CommentRepliesButton
     {
+        public readonly BindableBool Expanded = new BindableBool(true);
+
         private readonly int count;
 
         public ShowRepliesButton(int count)
@@ -14,6 +20,23 @@ namespace osu.Game.Overlays.Comments.Buttons
             this.count = count;
         }
 
+        protected override void LoadComplete()
+        {
+            base.LoadComplete();
+            Expanded.BindValueChanged(onExpandedChanged, true);
+        }
+
+        private void onExpandedChanged(ValueChangedEvent<bool> expanded)
+        {
+            Icon.ScaleTo(new Vector2(1, expanded.NewValue ? -1 : 1));
+        }
+
+        protected override bool OnClick(ClickEvent e)
+        {
+            Expanded.Toggle();
+            return base.OnClick(e);
+        }
+
         protected override string GetText() => "reply".ToQuantity(count);
     }
 }

From 42d3288f176d312833cad45f23cb69e73718e48c Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sat, 11 Jul 2020 08:01:11 +0300
Subject: [PATCH 04/17] Update old buttons usage

---
 osu.Game/Overlays/Comments/DrawableComment.cs | 50 ++++---------------
 1 file changed, 10 insertions(+), 40 deletions(-)

diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs
index 2a63060385..7bd5e22038 100644
--- a/osu.Game/Overlays/Comments/DrawableComment.cs
+++ b/osu.Game/Overlays/Comments/DrawableComment.cs
@@ -16,12 +16,12 @@ using System.Linq;
 using osu.Game.Graphics.Sprites;
 using osu.Game.Online.Chat;
 using osu.Framework.Allocation;
-using osuTK.Graphics;
 using System.Collections.Generic;
 using System;
 using osu.Framework.Graphics.Shapes;
 using osu.Framework.Extensions.IEnumerableExtensions;
 using System.Collections.Specialized;
+using osu.Game.Overlays.Comments.Buttons;
 
 namespace osu.Game.Overlays.Comments
 {
@@ -46,9 +46,9 @@ namespace osu.Game.Overlays.Comments
 
         private FillFlowContainer childCommentsVisibilityContainer;
         private FillFlowContainer childCommentsContainer;
-        private LoadMoreCommentsButton loadMoreCommentsButton;
+        private LoadRepliesButton loadRepliesButton;
         private ShowMoreButton showMoreButton;
-        private RepliesButton repliesButton;
+        private ShowRepliesButton showRepliesButton;
         private ChevronButton chevronButton;
         private DeletedCommentsCounter deletedCommentsCounter;
 
@@ -186,11 +186,11 @@ namespace osu.Game.Overlays.Comments
                                                                 },
                                                             }
                                                         },
-                                                        repliesButton = new RepliesButton(Comment.RepliesCount)
+                                                        showRepliesButton = new ShowRepliesButton(Comment.RepliesCount)
                                                         {
                                                             Expanded = { BindTarget = childrenExpanded }
                                                         },
-                                                        loadMoreCommentsButton = new LoadMoreCommentsButton
+                                                        loadRepliesButton = new LoadRepliesButton
                                                         {
                                                             Action = () => RepliesRequested(this, ++currentPage)
                                                         }
@@ -347,14 +347,16 @@ namespace osu.Game.Overlays.Comments
             var loadedReplesCount = loadedReplies.Count;
             var hasUnloadedReplies = loadedReplesCount != Comment.RepliesCount;
 
-            loadMoreCommentsButton.FadeTo(hasUnloadedReplies && loadedReplesCount == 0 ? 1 : 0);
+            loadRepliesButton.FadeTo(hasUnloadedReplies && loadedReplesCount == 0 ? 1 : 0);
             showMoreButton.FadeTo(hasUnloadedReplies && loadedReplesCount > 0 ? 1 : 0);
-            repliesButton.FadeTo(loadedReplesCount != 0 ? 1 : 0);
+            showRepliesButton.FadeTo(loadedReplesCount != 0 ? 1 : 0);
 
             if (Comment.IsTopLevel)
                 chevronButton.FadeTo(loadedReplesCount != 0 ? 1 : 0);
 
-            showMoreButton.IsLoading = loadMoreCommentsButton.IsLoading = false;
+            showMoreButton.IsLoading = false;
+
+            //loadRepliesButton.IsLoading = false;
         }
 
         private class ChevronButton : ShowChildrenButton
@@ -375,38 +377,6 @@ namespace osu.Game.Overlays.Comments
             }
         }
 
-        private class RepliesButton : ShowChildrenButton
-        {
-            private readonly SpriteText text;
-            private readonly int count;
-
-            public RepliesButton(int count)
-            {
-                this.count = count;
-
-                Child = text = new OsuSpriteText
-                {
-                    Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold),
-                };
-            }
-
-            protected override void OnExpandedChanged(ValueChangedEvent<bool> expanded)
-            {
-                text.Text = $@"{(expanded.NewValue ? "[-]" : "[+]")} replies ({count})";
-            }
-        }
-
-        private class LoadMoreCommentsButton : GetCommentRepliesButton
-        {
-            public LoadMoreCommentsButton()
-            {
-                IdleColour = OsuColour.Gray(0.7f);
-                HoverColour = Color4.White;
-            }
-
-            protected override string GetText() => @"[+] load replies";
-        }
-
         private class ShowMoreButton : GetCommentRepliesButton
         {
             [BackgroundDependencyLoader]

From b1b2e961bc0027b6305751ad469bf60e69186ee2 Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sat, 11 Jul 2020 08:13:11 +0300
Subject: [PATCH 05/17] Update arrow colour on hover

---
 .../TestSceneCommentRepliesButton.cs          |  18 +--
 .../Comments/Buttons/CommentRepliesButton.cs  | 125 ++++++++++--------
 2 files changed, 70 insertions(+), 73 deletions(-)

diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
index b4f518a5d0..e62092a180 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
@@ -26,22 +26,10 @@ namespace osu.Game.Tests.Visual.UserInterface
                 Spacing = new Vector2(0, 10),
                 Children = new Drawable[]
                 {
-                    new TestButton
-                    {
-                        Action = () => { }
-                    },
-                    new LoadRepliesButton
-                    {
-                        Action = () => { }
-                    },
-                    new ShowRepliesButton(1)
-                    {
-                        Action = () => { }
-                    },
+                    new TestButton(),
+                    new LoadRepliesButton(),
+                    new ShowRepliesButton(1),
                     new ShowRepliesButton(2)
-                    {
-                        Action = () => { }
-                    }
                 }
             };
         }
diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
index 13924200c2..7ea256d113 100644
--- a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
@@ -1,100 +1,109 @@
 // 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.Collections.Generic;
+using System;
 using osu.Framework.Allocation;
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
 using osu.Framework.Graphics.Shapes;
 using osu.Framework.Graphics.Sprites;
+using osu.Framework.Input.Events;
 using osu.Game.Graphics;
-using osu.Game.Graphics.Containers;
 using osu.Game.Graphics.Sprites;
+using osu.Game.Graphics.UserInterface;
 using osuTK;
 
 namespace osu.Game.Overlays.Comments.Buttons
 {
-    public abstract class CommentRepliesButton : OsuHoverContainer
+    public abstract class CommentRepliesButton : CompositeDrawable
     {
-        protected override IEnumerable<Drawable> EffectTargets => new[] { background };
+        public Action Action { get; set; }
 
-        protected ChevronIcon Icon;
+        [Resolved]
+        private OverlayColourProvider colourProvider { get; set; }
+
+        protected SpriteIcon Icon;
         private Box background;
 
-        public CommentRepliesButton()
+        [BackgroundDependencyLoader]
+        private void load()
         {
             AutoSizeAxes = Axes.Both;
-        }
-
-        [BackgroundDependencyLoader]
-        private void load(OverlayColourProvider colourProvider)
-        {
-            Add(new CircularContainer
+            InternalChildren = new Drawable[]
             {
-                AutoSizeAxes = Axes.Both,
-                Masking = true,
-                Children = new Drawable[]
+                new CircularContainer
                 {
-                    background = new Box
+                    AutoSizeAxes = Axes.Both,
+                    Masking = true,
+                    Children = new Drawable[]
                     {
-                        RelativeSizeAxes = Axes.Both
-                    },
-                    new Container
-                    {
-                        AutoSizeAxes = Axes.Both,
-                        Margin = new MarginPadding
+                        background = new Box
                         {
-                            Vertical = 5,
-                            Horizontal = 10,
+                            RelativeSizeAxes = Axes.Both,
+                            Colour = colourProvider.Background2
                         },
-                        Child = new FillFlowContainer
+                        new Container
                         {
                             AutoSizeAxes = Axes.Both,
-                            Direction = FillDirection.Horizontal,
-                            Spacing = new Vector2(15, 0),
-                            Anchor = Anchor.Centre,
-                            Origin = Anchor.Centre,
-                            Children = new Drawable[]
+                            Margin = new MarginPadding
                             {
-                                new OsuSpriteText
+                                Vertical = 5,
+                                Horizontal = 10,
+                            },
+                            Child = new FillFlowContainer
+                            {
+                                AutoSizeAxes = Axes.Both,
+                                Direction = FillDirection.Horizontal,
+                                Spacing = new Vector2(15, 0),
+                                Anchor = Anchor.Centre,
+                                Origin = Anchor.Centre,
+                                Children = new Drawable[]
                                 {
-                                    Anchor = Anchor.CentreLeft,
-                                    Origin = Anchor.CentreLeft,
-                                    Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold),
-                                    Text = GetText()
-                                },
-                                Icon = new ChevronIcon
-                                {
-                                    Anchor = Anchor.CentreLeft,
-                                    Origin = Anchor.CentreLeft,
+                                    new OsuSpriteText
+                                    {
+                                        Anchor = Anchor.CentreLeft,
+                                        Origin = Anchor.CentreLeft,
+                                        Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold),
+                                        Text = GetText()
+                                    },
+                                    Icon = new SpriteIcon
+                                    {
+                                        Anchor = Anchor.CentreLeft,
+                                        Origin = Anchor.CentreLeft,
+                                        Size = new Vector2(7.5f),
+                                        Icon = FontAwesome.Solid.ChevronDown,
+                                        Colour = colourProvider.Foreground1
+                                    }
                                 }
                             }
                         }
                     }
-                }
-            });
-
-            IdleColour = colourProvider.Background2;
-            HoverColour = colourProvider.Background1;
+                },
+                new HoverClickSounds(),
+            };
         }
 
         protected abstract string GetText();
 
-        protected class ChevronIcon : SpriteIcon
+        protected override bool OnHover(HoverEvent e)
         {
-            public ChevronIcon()
-            {
-                Anchor = Anchor.Centre;
-                Origin = Anchor.Centre;
-                Size = new Vector2(7.5f);
-                Icon = FontAwesome.Solid.ChevronDown;
-            }
+            base.OnHover(e);
+            background.FadeColour(colourProvider.Background1, 200, Easing.OutQuint);
+            Icon.FadeColour(colourProvider.Light1, 200, Easing.OutQuint);
+            return true;
+        }
 
-            [BackgroundDependencyLoader]
-            private void load(OverlayColourProvider colourProvider)
-            {
-                Colour = colourProvider.Foreground1;
-            }
+        protected override void OnHoverLost(HoverLostEvent e)
+        {
+            base.OnHoverLost(e);
+            background.FadeColour(colourProvider.Background2, 200, Easing.OutQuint);
+            Icon.FadeColour(colourProvider.Foreground1, 200, Easing.OutQuint);
+        }
+
+        protected override bool OnClick(ClickEvent e)
+        {
+            Action?.Invoke();
+            return base.OnClick(e);
         }
     }
 }

From 84392d0d130242616ded329ac711355bbc7c8c0c Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sat, 11 Jul 2020 08:50:35 +0300
Subject: [PATCH 06/17] Add loading spinner

---
 osu.Game/Overlays/Comments/DrawableComment.cs | 43 +++++++++++++++++--
 1 file changed, 40 insertions(+), 3 deletions(-)

diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs
index 7bd5e22038..fef8194712 100644
--- a/osu.Game/Overlays/Comments/DrawableComment.cs
+++ b/osu.Game/Overlays/Comments/DrawableComment.cs
@@ -22,6 +22,7 @@ using osu.Framework.Graphics.Shapes;
 using osu.Framework.Extensions.IEnumerableExtensions;
 using System.Collections.Specialized;
 using osu.Game.Overlays.Comments.Buttons;
+using osu.Game.Graphics.UserInterface;
 
 namespace osu.Game.Overlays.Comments
 {
@@ -51,6 +52,7 @@ namespace osu.Game.Overlays.Comments
         private ShowRepliesButton showRepliesButton;
         private ChevronButton chevronButton;
         private DeletedCommentsCounter deletedCommentsCounter;
+        private Loading loading;
 
         public DrawableComment(Comment comment)
         {
@@ -192,7 +194,12 @@ namespace osu.Game.Overlays.Comments
                                                         },
                                                         loadRepliesButton = new LoadRepliesButton
                                                         {
-                                                            Action = () => RepliesRequested(this, ++currentPage)
+                                                            Action = () =>
+                                                            {
+                                                                RepliesRequested(this, ++currentPage);
+                                                                loadRepliesButton.Hide();
+                                                                loading.Show();
+                                                            }
                                                         }
                                                     }
                                                 }
@@ -202,6 +209,11 @@ namespace osu.Game.Overlays.Comments
                                 }
                             }
                         },
+                        loading = new Loading
+                        {
+                            RelativeSizeAxes = Axes.X,
+                            AutoSizeAxes = Axes.Y
+                        },
                         childCommentsVisibilityContainer = new FillFlowContainer
                         {
                             RelativeSizeAxes = Axes.X,
@@ -355,8 +367,7 @@ namespace osu.Game.Overlays.Comments
                 chevronButton.FadeTo(loadedReplesCount != 0 ? 1 : 0);
 
             showMoreButton.IsLoading = false;
-
-            //loadRepliesButton.IsLoading = false;
+            loading.Hide();
         }
 
         private class ChevronButton : ShowChildrenButton
@@ -427,5 +438,31 @@ namespace osu.Game.Overlays.Comments
                 return parentComment.HasMessage ? parentComment.Message : parentComment.IsDeleted ? @"deleted" : string.Empty;
             }
         }
+
+        private class Loading : Container
+        {
+            private readonly LoadingSpinner loading;
+
+            public Loading()
+            {
+                Child = loading = new LoadingSpinner
+                {
+                    Anchor = Anchor.TopLeft,
+                    Origin = Anchor.TopLeft,
+                    Size = new Vector2(15),
+                    Margin = new MarginPadding
+                    {
+                        Vertical = 5,
+                        Left = 80
+                    }
+                };
+            }
+
+            protected override void LoadComplete()
+            {
+                base.LoadComplete();
+                loading.Show();
+            }
+        }
     }
 }

From 024ccc75eefcec4e62b5a6a79d658df8a421657b Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sat, 11 Jul 2020 09:03:03 +0300
Subject: [PATCH 07/17] Adjust margins/paddings

---
 osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs | 4 ++++
 osu.Game/Overlays/Comments/DrawableComment.cs              | 2 +-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
index 7ea256d113..f4bab3d9d7 100644
--- a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
@@ -29,6 +29,10 @@ namespace osu.Game.Overlays.Comments.Buttons
         private void load()
         {
             AutoSizeAxes = Axes.Both;
+            Margin = new MarginPadding
+            {
+                Vertical = 2
+            };
             InternalChildren = new Drawable[]
             {
                 new CircularContainer
diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs
index fef8194712..813540b28d 100644
--- a/osu.Game/Overlays/Comments/DrawableComment.cs
+++ b/osu.Game/Overlays/Comments/DrawableComment.cs
@@ -83,7 +83,7 @@ namespace osu.Game.Overlays.Comments
                         {
                             RelativeSizeAxes = Axes.X,
                             AutoSizeAxes = Axes.Y,
-                            Padding = new MarginPadding(margin) { Left = margin + 5 },
+                            Padding = new MarginPadding(margin) { Left = margin + 5, Top = Comment.IsTopLevel ? 10 : 0 },
                             Child = content = new GridContainer
                             {
                                 RelativeSizeAxes = Axes.X,

From da40f29b4405990a3db8150fbd0fafa4f34f9f83 Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sun, 12 Jul 2020 12:27:26 +0300
Subject: [PATCH 08/17] Make button text a property

---
 .../TestSceneCommentRepliesButton.cs          |  5 ++-
 .../Comments/Buttons/CommentRepliesButton.cs  | 32 ++++++++++++-------
 .../Comments/Buttons/LoadRepliesButton.cs     |  5 ++-
 .../Comments/Buttons/ShowRepliesButton.cs     |  6 +---
 4 files changed, 29 insertions(+), 19 deletions(-)

diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
index e62092a180..baeb1ae822 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
@@ -36,7 +36,10 @@ namespace osu.Game.Tests.Visual.UserInterface
 
         private class TestButton : CommentRepliesButton
         {
-            protected override string GetText() => "sample text";
+            public TestButton()
+            {
+                Text = "sample text";
+            }
         }
     }
 }
diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
index f4bab3d9d7..1121ac5327 100644
--- a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
@@ -19,14 +19,20 @@ namespace osu.Game.Overlays.Comments.Buttons
     {
         public Action Action { get; set; }
 
+        protected string Text
+        {
+            get => text.Text;
+            set => text.Text = value;
+        }
+
         [Resolved]
         private OverlayColourProvider colourProvider { get; set; }
 
-        protected SpriteIcon Icon;
-        private Box background;
+        protected readonly SpriteIcon Icon;
+        private readonly Box background;
+        private readonly OsuSpriteText text;
 
-        [BackgroundDependencyLoader]
-        private void load()
+        public CommentRepliesButton()
         {
             AutoSizeAxes = Axes.Both;
             Margin = new MarginPadding
@@ -43,8 +49,7 @@ namespace osu.Game.Overlays.Comments.Buttons
                     {
                         background = new Box
                         {
-                            RelativeSizeAxes = Axes.Both,
-                            Colour = colourProvider.Background2
+                            RelativeSizeAxes = Axes.Both
                         },
                         new Container
                         {
@@ -63,20 +68,18 @@ namespace osu.Game.Overlays.Comments.Buttons
                                 Origin = Anchor.Centre,
                                 Children = new Drawable[]
                                 {
-                                    new OsuSpriteText
+                                    text = new OsuSpriteText
                                     {
                                         Anchor = Anchor.CentreLeft,
                                         Origin = Anchor.CentreLeft,
-                                        Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold),
-                                        Text = GetText()
+                                        Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)
                                     },
                                     Icon = new SpriteIcon
                                     {
                                         Anchor = Anchor.CentreLeft,
                                         Origin = Anchor.CentreLeft,
                                         Size = new Vector2(7.5f),
-                                        Icon = FontAwesome.Solid.ChevronDown,
-                                        Colour = colourProvider.Foreground1
+                                        Icon = FontAwesome.Solid.ChevronDown
                                     }
                                 }
                             }
@@ -87,7 +90,12 @@ namespace osu.Game.Overlays.Comments.Buttons
             };
         }
 
-        protected abstract string GetText();
+        [BackgroundDependencyLoader]
+        private void load()
+        {
+            background.Colour = colourProvider.Background2;
+            Icon.Colour = colourProvider.Foreground1;
+        }
 
         protected override bool OnHover(HoverEvent e)
         {
diff --git a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
index 41cce72272..9387c95758 100644
--- a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
@@ -5,6 +5,9 @@ namespace osu.Game.Overlays.Comments.Buttons
 {
     public class LoadRepliesButton : CommentRepliesButton
     {
-        protected override string GetText() => "load replies";
+        public LoadRepliesButton()
+        {
+            Text = "load replies";
+        }
     }
 }
diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
index 2381727431..01c2e8a7a7 100644
--- a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
@@ -13,11 +13,9 @@ namespace osu.Game.Overlays.Comments.Buttons
     {
         public readonly BindableBool Expanded = new BindableBool(true);
 
-        private readonly int count;
-
         public ShowRepliesButton(int count)
         {
-            this.count = count;
+            Text = "reply".ToQuantity(count);
         }
 
         protected override void LoadComplete()
@@ -36,7 +34,5 @@ namespace osu.Game.Overlays.Comments.Buttons
             Expanded.Toggle();
             return base.OnClick(e);
         }
-
-        protected override string GetText() => "reply".ToQuantity(count);
     }
 }

From c3524cbe57f60e826df8b12fdcdf5bb178497b80 Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sun, 12 Jul 2020 12:32:26 +0300
Subject: [PATCH 09/17] Make icon private but expose a protected method

---
 .../Comments/Buttons/CommentRepliesButton.cs         | 12 +++++++-----
 .../Overlays/Comments/Buttons/ShowRepliesButton.cs   |  9 +--------
 2 files changed, 8 insertions(+), 13 deletions(-)

diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
index 1121ac5327..dd02a35a06 100644
--- a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
@@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Comments.Buttons
         [Resolved]
         private OverlayColourProvider colourProvider { get; set; }
 
-        protected readonly SpriteIcon Icon;
+        private readonly SpriteIcon icon;
         private readonly Box background;
         private readonly OsuSpriteText text;
 
@@ -74,7 +74,7 @@ namespace osu.Game.Overlays.Comments.Buttons
                                         Origin = Anchor.CentreLeft,
                                         Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)
                                     },
-                                    Icon = new SpriteIcon
+                                    icon = new SpriteIcon
                                     {
                                         Anchor = Anchor.CentreLeft,
                                         Origin = Anchor.CentreLeft,
@@ -94,14 +94,16 @@ namespace osu.Game.Overlays.Comments.Buttons
         private void load()
         {
             background.Colour = colourProvider.Background2;
-            Icon.Colour = colourProvider.Foreground1;
+            icon.Colour = colourProvider.Foreground1;
         }
 
+        protected void ToggleIcon(bool upwards) => icon.ScaleTo(new Vector2(1, upwards ? -1 : 1));
+
         protected override bool OnHover(HoverEvent e)
         {
             base.OnHover(e);
             background.FadeColour(colourProvider.Background1, 200, Easing.OutQuint);
-            Icon.FadeColour(colourProvider.Light1, 200, Easing.OutQuint);
+            icon.FadeColour(colourProvider.Light1, 200, Easing.OutQuint);
             return true;
         }
 
@@ -109,7 +111,7 @@ namespace osu.Game.Overlays.Comments.Buttons
         {
             base.OnHoverLost(e);
             background.FadeColour(colourProvider.Background2, 200, Easing.OutQuint);
-            Icon.FadeColour(colourProvider.Foreground1, 200, Easing.OutQuint);
+            icon.FadeColour(colourProvider.Foreground1, 200, Easing.OutQuint);
         }
 
         protected override bool OnClick(ClickEvent e)
diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
index 01c2e8a7a7..118cac5b4c 100644
--- a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
@@ -3,9 +3,7 @@
 
 using Humanizer;
 using osu.Framework.Bindables;
-using osu.Framework.Graphics;
 using osu.Framework.Input.Events;
-using osuTK;
 
 namespace osu.Game.Overlays.Comments.Buttons
 {
@@ -21,12 +19,7 @@ namespace osu.Game.Overlays.Comments.Buttons
         protected override void LoadComplete()
         {
             base.LoadComplete();
-            Expanded.BindValueChanged(onExpandedChanged, true);
-        }
-
-        private void onExpandedChanged(ValueChangedEvent<bool> expanded)
-        {
-            Icon.ScaleTo(new Vector2(1, expanded.NewValue ? -1 : 1));
+            Expanded.BindValueChanged(expanded => ToggleIcon(expanded.NewValue), true);
         }
 
         protected override bool OnClick(ClickEvent e)

From be36a4b7686a120641a7ec29f727a2898dd54053 Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sun, 12 Jul 2020 12:39:48 +0300
Subject: [PATCH 10/17] Make ctor protected

---
 osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
index dd02a35a06..65648f6751 100644
--- a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
@@ -32,7 +32,7 @@ namespace osu.Game.Overlays.Comments.Buttons
         private readonly Box background;
         private readonly OsuSpriteText text;
 
-        public CommentRepliesButton()
+        protected CommentRepliesButton()
         {
             AutoSizeAxes = Axes.Both;
             Margin = new MarginPadding

From c9d21894e5aeba8e2ddbf7c97779584bbc95ac93 Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sun, 12 Jul 2020 13:19:28 +0300
Subject: [PATCH 11/17] Add test for icon toggle

---
 .../TestSceneCommentRepliesButton.cs          | 20 ++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
index baeb1ae822..73fe66d6eb 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
@@ -7,6 +7,9 @@ using osu.Framework.Allocation;
 using osu.Game.Overlays;
 using osu.Framework.Graphics.Containers;
 using osuTK;
+using NUnit.Framework;
+using System.Linq;
+using osu.Framework.Graphics.Sprites;
 
 namespace osu.Game.Tests.Visual.UserInterface
 {
@@ -15,6 +18,8 @@ namespace osu.Game.Tests.Visual.UserInterface
         [Cached]
         private readonly OverlayColourProvider colourProvider = new OverlayColourProvider(OverlayColourScheme.Blue);
 
+        private readonly TestButton button;
+
         public TestSceneCommentRepliesButton()
         {
             Child = new FillFlowContainer
@@ -26,7 +31,7 @@ namespace osu.Game.Tests.Visual.UserInterface
                 Spacing = new Vector2(0, 10),
                 Children = new Drawable[]
                 {
-                    new TestButton(),
+                    button = new TestButton(),
                     new LoadRepliesButton(),
                     new ShowRepliesButton(1),
                     new ShowRepliesButton(2)
@@ -34,12 +39,25 @@ namespace osu.Game.Tests.Visual.UserInterface
             };
         }
 
+        [Test]
+        public void TestArrowRotation()
+        {
+            AddStep("Toggle icon up", () => button.ToggleIcon(true));
+            AddAssert("Icon facing upwards", () => button.Icon.Scale.Y == -1);
+            AddStep("Toggle icon down", () => button.ToggleIcon(false));
+            AddAssert("Icon facing downwards", () => button.Icon.Scale.Y == 1);
+        }
+
         private class TestButton : CommentRepliesButton
         {
+            public SpriteIcon Icon => InternalChildren.OfType<CircularContainer>().First().Children.OfType<Container>().First().Children.OfType<FillFlowContainer>().First().Children.OfType<SpriteIcon>().First();
+
             public TestButton()
             {
                 Text = "sample text";
             }
+
+            public new void ToggleIcon(bool upwards) => base.ToggleIcon(upwards);
         }
     }
 }

From 0d6dbb652315f7f8e341ddf2478617308e3ac59f Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Sun, 12 Jul 2020 13:36:42 +0300
Subject: [PATCH 12/17] Clean up exposed icon for tests

---
 .../Visual/UserInterface/TestSceneCommentRepliesButton.cs      | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
index 73fe66d6eb..7f5806705e 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
@@ -10,6 +10,7 @@ using osuTK;
 using NUnit.Framework;
 using System.Linq;
 using osu.Framework.Graphics.Sprites;
+using osu.Framework.Testing;
 
 namespace osu.Game.Tests.Visual.UserInterface
 {
@@ -50,7 +51,7 @@ namespace osu.Game.Tests.Visual.UserInterface
 
         private class TestButton : CommentRepliesButton
         {
-            public SpriteIcon Icon => InternalChildren.OfType<CircularContainer>().First().Children.OfType<Container>().First().Children.OfType<FillFlowContainer>().First().Children.OfType<SpriteIcon>().First();
+            public SpriteIcon Icon => this.ChildrenOfType<SpriteIcon>().First();
 
             public TestButton()
             {

From 56349e65f3929032561d3059622a201f87afc604 Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Tue, 14 Jul 2020 03:01:14 +0300
Subject: [PATCH 13/17] Rename arrow direction method

---
 .../Visual/UserInterface/TestSceneCommentRepliesButton.cs | 8 ++++----
 .../Overlays/Comments/Buttons/CommentRepliesButton.cs     | 2 +-
 osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs   | 2 +-
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
index 7f5806705e..c2dc804385 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
@@ -41,11 +41,11 @@ namespace osu.Game.Tests.Visual.UserInterface
         }
 
         [Test]
-        public void TestArrowRotation()
+        public void TestArrowDirection()
         {
-            AddStep("Toggle icon up", () => button.ToggleIcon(true));
+            AddStep("Set upwards", () => button.SetIconDirection(true));
             AddAssert("Icon facing upwards", () => button.Icon.Scale.Y == -1);
-            AddStep("Toggle icon down", () => button.ToggleIcon(false));
+            AddStep("Set downwards", () => button.SetIconDirection(false));
             AddAssert("Icon facing downwards", () => button.Icon.Scale.Y == 1);
         }
 
@@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual.UserInterface
                 Text = "sample text";
             }
 
-            public new void ToggleIcon(bool upwards) => base.ToggleIcon(upwards);
+            public new void SetIconDirection(bool upwards) => base.SetIconDirection(upwards);
         }
     }
 }
diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
index 65648f6751..abe80722e2 100644
--- a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
@@ -97,7 +97,7 @@ namespace osu.Game.Overlays.Comments.Buttons
             icon.Colour = colourProvider.Foreground1;
         }
 
-        protected void ToggleIcon(bool upwards) => icon.ScaleTo(new Vector2(1, upwards ? -1 : 1));
+        protected void SetIconDirection(bool upwards) => icon.ScaleTo(new Vector2(1, upwards ? -1 : 1));
 
         protected override bool OnHover(HoverEvent e)
         {
diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
index 118cac5b4c..e2023c2f58 100644
--- a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
@@ -19,7 +19,7 @@ namespace osu.Game.Overlays.Comments.Buttons
         protected override void LoadComplete()
         {
             base.LoadComplete();
-            Expanded.BindValueChanged(expanded => ToggleIcon(expanded.NewValue), true);
+            Expanded.BindValueChanged(expanded => SetIconDirection(expanded.NewValue), true);
         }
 
         protected override bool OnClick(ClickEvent e)

From 7c71cc6b6174a6a62a0f78cd9029bb12943ff82b Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Tue, 14 Jul 2020 03:06:51 +0300
Subject: [PATCH 14/17] Remove unneeded class from DrawableComment

---
 osu.Game/Overlays/Comments/DrawableComment.cs | 41 +++++--------------
 1 file changed, 11 insertions(+), 30 deletions(-)

diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs
index 813540b28d..731ebe7104 100644
--- a/osu.Game/Overlays/Comments/DrawableComment.cs
+++ b/osu.Game/Overlays/Comments/DrawableComment.cs
@@ -52,7 +52,7 @@ namespace osu.Game.Overlays.Comments
         private ShowRepliesButton showRepliesButton;
         private ChevronButton chevronButton;
         private DeletedCommentsCounter deletedCommentsCounter;
-        private Loading loading;
+        private LoadingSpinner loading;
 
         public DrawableComment(Comment comment)
         {
@@ -209,10 +209,16 @@ namespace osu.Game.Overlays.Comments
                                 }
                             }
                         },
-                        loading = new Loading
+                        loading = new LoadingSpinner
                         {
-                            RelativeSizeAxes = Axes.X,
-                            AutoSizeAxes = Axes.Y
+                            Anchor = Anchor.TopLeft,
+                            Origin = Anchor.TopLeft,
+                            Size = new Vector2(15),
+                            Margin = new MarginPadding
+                            {
+                                Vertical = 5,
+                                Left = 80
+                            }
                         },
                         childCommentsVisibilityContainer = new FillFlowContainer
                         {
@@ -368,6 +374,7 @@ namespace osu.Game.Overlays.Comments
 
             showMoreButton.IsLoading = false;
             loading.Hide();
+            loading.FinishTransforms();
         }
 
         private class ChevronButton : ShowChildrenButton
@@ -438,31 +445,5 @@ namespace osu.Game.Overlays.Comments
                 return parentComment.HasMessage ? parentComment.Message : parentComment.IsDeleted ? @"deleted" : string.Empty;
             }
         }
-
-        private class Loading : Container
-        {
-            private readonly LoadingSpinner loading;
-
-            public Loading()
-            {
-                Child = loading = new LoadingSpinner
-                {
-                    Anchor = Anchor.TopLeft,
-                    Origin = Anchor.TopLeft,
-                    Size = new Vector2(15),
-                    Margin = new MarginPadding
-                    {
-                        Vertical = 5,
-                        Left = 80
-                    }
-                };
-            }
-
-            protected override void LoadComplete()
-            {
-                base.LoadComplete();
-                loading.Show();
-            }
-        }
     }
 }

From 4c2294f0cd65ebce410d979af5f3b7b395da64ef Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Tue, 14 Jul 2020 15:02:29 +0300
Subject: [PATCH 15/17] Refactor LoadRepliesButton to inherit LoadingButton

---
 .../TestSceneCommentRepliesButton.cs          |  5 +++-
 .../Comments/Buttons/CommentRepliesButton.cs  | 12 +++-------
 .../Comments/Buttons/LoadRepliesButton.cs     | 23 ++++++++++++++++--
 .../Comments/Buttons/ShowRepliesButton.cs     |  4 ++++
 osu.Game/Overlays/Comments/DrawableComment.cs | 24 ++-----------------
 5 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
index c2dc804385..c2ac5179c9 100644
--- a/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
+++ b/osu.Game.Tests/Visual/UserInterface/TestSceneCommentRepliesButton.cs
@@ -33,7 +33,10 @@ namespace osu.Game.Tests.Visual.UserInterface
                 Children = new Drawable[]
                 {
                     button = new TestButton(),
-                    new LoadRepliesButton(),
+                    new LoadRepliesButton
+                    {
+                        Action = () => { }
+                    },
                     new ShowRepliesButton(1),
                     new ShowRepliesButton(2)
                 }
diff --git a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
index abe80722e2..f7e0cb0a6c 100644
--- a/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/CommentRepliesButton.cs
@@ -1,7 +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.
 
-using System;
 using osu.Framework.Allocation;
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
@@ -17,8 +16,6 @@ namespace osu.Game.Overlays.Comments.Buttons
 {
     public abstract class CommentRepliesButton : CompositeDrawable
     {
-        public Action Action { get; set; }
-
         protected string Text
         {
             get => text.Text;
@@ -72,6 +69,7 @@ namespace osu.Game.Overlays.Comments.Buttons
                                     {
                                         Anchor = Anchor.CentreLeft,
                                         Origin = Anchor.CentreLeft,
+                                        AlwaysPresent = true,
                                         Font = OsuFont.GetFont(size: 12, weight: FontWeight.SemiBold)
                                     },
                                     icon = new SpriteIcon
@@ -99,6 +97,8 @@ namespace osu.Game.Overlays.Comments.Buttons
 
         protected void SetIconDirection(bool upwards) => icon.ScaleTo(new Vector2(1, upwards ? -1 : 1));
 
+        public void ToggleTextVisibility(bool visible) => text.FadeTo(visible ? 1 : 0, 200, Easing.OutQuint);
+
         protected override bool OnHover(HoverEvent e)
         {
             base.OnHover(e);
@@ -113,11 +113,5 @@ namespace osu.Game.Overlays.Comments.Buttons
             background.FadeColour(colourProvider.Background2, 200, Easing.OutQuint);
             icon.FadeColour(colourProvider.Foreground1, 200, Easing.OutQuint);
         }
-
-        protected override bool OnClick(ClickEvent e)
-        {
-            Action?.Invoke();
-            return base.OnClick(e);
-        }
     }
 }
diff --git a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
index 9387c95758..4998e5391e 100644
--- a/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/LoadRepliesButton.cs
@@ -1,13 +1,32 @@
 // 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 osu.Framework.Graphics;
+using osu.Game.Graphics.UserInterface;
+
 namespace osu.Game.Overlays.Comments.Buttons
 {
-    public class LoadRepliesButton : CommentRepliesButton
+    public class LoadRepliesButton : LoadingButton
     {
+        private ButtonContent content;
+
         public LoadRepliesButton()
         {
-            Text = "load replies";
+            AutoSizeAxes = Axes.Both;
+        }
+
+        protected override Drawable CreateContent() => content = new ButtonContent();
+
+        protected override void OnLoadStarted() => content.ToggleTextVisibility(false);
+
+        protected override void OnLoadFinished() => content.ToggleTextVisibility(true);
+
+        private class ButtonContent : CommentRepliesButton
+        {
+            public ButtonContent()
+            {
+                Text = "load replies";
+            }
         }
     }
 }
diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
index e2023c2f58..aeb33e6756 100644
--- a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
@@ -1,6 +1,7 @@
 // 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;
 using Humanizer;
 using osu.Framework.Bindables;
 using osu.Framework.Input.Events;
@@ -9,6 +10,8 @@ namespace osu.Game.Overlays.Comments.Buttons
 {
     public class ShowRepliesButton : CommentRepliesButton
     {
+        public Action Action;
+
         public readonly BindableBool Expanded = new BindableBool(true);
 
         public ShowRepliesButton(int count)
@@ -25,6 +28,7 @@ namespace osu.Game.Overlays.Comments.Buttons
         protected override bool OnClick(ClickEvent e)
         {
             Expanded.Toggle();
+            Action?.Invoke();
             return base.OnClick(e);
         }
     }
diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs
index 731ebe7104..3cdc0a0cbd 100644
--- a/osu.Game/Overlays/Comments/DrawableComment.cs
+++ b/osu.Game/Overlays/Comments/DrawableComment.cs
@@ -22,7 +22,6 @@ using osu.Framework.Graphics.Shapes;
 using osu.Framework.Extensions.IEnumerableExtensions;
 using System.Collections.Specialized;
 using osu.Game.Overlays.Comments.Buttons;
-using osu.Game.Graphics.UserInterface;
 
 namespace osu.Game.Overlays.Comments
 {
@@ -52,7 +51,6 @@ namespace osu.Game.Overlays.Comments
         private ShowRepliesButton showRepliesButton;
         private ChevronButton chevronButton;
         private DeletedCommentsCounter deletedCommentsCounter;
-        private LoadingSpinner loading;
 
         public DrawableComment(Comment comment)
         {
@@ -194,12 +192,7 @@ namespace osu.Game.Overlays.Comments
                                                         },
                                                         loadRepliesButton = new LoadRepliesButton
                                                         {
-                                                            Action = () =>
-                                                            {
-                                                                RepliesRequested(this, ++currentPage);
-                                                                loadRepliesButton.Hide();
-                                                                loading.Show();
-                                                            }
+                                                            Action = () => RepliesRequested(this, ++currentPage)
                                                         }
                                                     }
                                                 }
@@ -209,17 +202,6 @@ namespace osu.Game.Overlays.Comments
                                 }
                             }
                         },
-                        loading = new LoadingSpinner
-                        {
-                            Anchor = Anchor.TopLeft,
-                            Origin = Anchor.TopLeft,
-                            Size = new Vector2(15),
-                            Margin = new MarginPadding
-                            {
-                                Vertical = 5,
-                                Left = 80
-                            }
-                        },
                         childCommentsVisibilityContainer = new FillFlowContainer
                         {
                             RelativeSizeAxes = Axes.X,
@@ -372,9 +354,7 @@ namespace osu.Game.Overlays.Comments
             if (Comment.IsTopLevel)
                 chevronButton.FadeTo(loadedReplesCount != 0 ? 1 : 0);
 
-            showMoreButton.IsLoading = false;
-            loading.Hide();
-            loading.FinishTransforms();
+            showMoreButton.IsLoading = loadRepliesButton.IsLoading = false;
         }
 
         private class ChevronButton : ShowChildrenButton

From 28006ac33f7f71fefd1dafdf490a760d260f661a Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Tue, 14 Jul 2020 15:12:18 +0300
Subject: [PATCH 16/17] Remove unnecessary action from ShowRepliesButton

---
 osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
index aeb33e6756..e2023c2f58 100644
--- a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
@@ -1,7 +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.
 
-using System;
 using Humanizer;
 using osu.Framework.Bindables;
 using osu.Framework.Input.Events;
@@ -10,8 +9,6 @@ namespace osu.Game.Overlays.Comments.Buttons
 {
     public class ShowRepliesButton : CommentRepliesButton
     {
-        public Action Action;
-
         public readonly BindableBool Expanded = new BindableBool(true);
 
         public ShowRepliesButton(int count)
@@ -28,7 +25,6 @@ namespace osu.Game.Overlays.Comments.Buttons
         protected override bool OnClick(ClickEvent e)
         {
             Expanded.Toggle();
-            Action?.Invoke();
             return base.OnClick(e);
         }
     }

From 85c875757219da92b49e4d3582def1653ae2c8f6 Mon Sep 17 00:00:00 2001
From: Andrei Zavatski <megaman9919@gmail.com>
Date: Tue, 14 Jul 2020 21:18:46 +0300
Subject: [PATCH 17/17] Return true on click

---
 osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
index e2023c2f58..04e7e25cc5 100644
--- a/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
+++ b/osu.Game/Overlays/Comments/Buttons/ShowRepliesButton.cs
@@ -25,7 +25,7 @@ namespace osu.Game.Overlays.Comments.Buttons
         protected override bool OnClick(ClickEvent e)
         {
             Expanded.Toggle();
-            return base.OnClick(e);
+            return true;
         }
     }
 }