diff --git a/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs b/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs index 1217ce6b42..0ed8864860 100644 --- a/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs +++ b/osu.Game.Tests/Visual/Online/TestSceneCommentsPage.cs @@ -58,8 +58,8 @@ namespace osu.Game.Tests.Visual.Online } }); - AddStep("load comments", () => createPage(comment_bundle)); - AddStep("load empty comments", () => createPage(empty_comment_bundle)); + AddStep("load comments", () => createPage(getCommentBundle())); + AddStep("load empty comments", () => createPage(getEmptyCommentBundle())); } private void createPage(CommentBundle commentBundle) @@ -71,13 +71,12 @@ namespace osu.Game.Tests.Visual.Online }); } - private static readonly CommentBundle empty_comment_bundle = new CommentBundle + private CommentBundle getEmptyCommentBundle() => new CommentBundle { Comments = new List(), - Total = 0, }; - private static readonly CommentBundle comment_bundle = new CommentBundle + private CommentBundle getCommentBundle() => new CommentBundle { Comments = new List { @@ -90,6 +89,33 @@ namespace osu.Game.Tests.Visual.Online VotesCount = 5 }, new Comment + { + Id = 100, + Message = "This comment has \"load replies\" button because it has unloaded replies", + LegacyName = "TestUser1100", + CreatedAt = DateTimeOffset.Now, + VotesCount = 5, + RepliesCount = 2, + }, + new Comment + { + Id = 111, + Message = "This comment has \"Show More\" button because it has unloaded replies, but some of them are loaded", + LegacyName = "TestUser1111", + CreatedAt = DateTimeOffset.Now, + VotesCount = 100, + RepliesCount = 2, + }, + new Comment + { + Id = 112, + ParentId = 111, + Message = "I'm here to make my parent work", + LegacyName = "someone", + CreatedAt = DateTimeOffset.Now, + VotesCount = 2, + }, + new Comment { Id = 2, Message = "This comment has been deleted :( but visible for admins", @@ -155,8 +181,6 @@ namespace osu.Game.Tests.Visual.Online Username = "Good_Admin" } }, - TopLevelCount = 4, - Total = 7 }; } } diff --git a/osu.Game/Online/API/Requests/GetCommentRepliesRequest.cs b/osu.Game/Online/API/Requests/GetCommentRepliesRequest.cs new file mode 100644 index 0000000000..203f5d5635 --- /dev/null +++ b/osu.Game/Online/API/Requests/GetCommentRepliesRequest.cs @@ -0,0 +1,45 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using Humanizer; +using osu.Framework.IO.Network; +using osu.Game.Online.API.Requests.Responses; +using osu.Game.Overlays.Comments; + +namespace osu.Game.Online.API.Requests +{ + public class GetCommentRepliesRequest : APIRequest + { + private readonly long commentId; + private readonly CommentableType commentableType; + private readonly long commentableId; + private readonly int page; + private readonly CommentsSortCriteria sort; + + public GetCommentRepliesRequest(long commentId, CommentableType commentableType, long commentableId, CommentsSortCriteria sort, int page) + { + this.commentId = commentId; + this.page = page; + this.sort = sort; + + // These parameters are necessary to get deleted comments + this.commentableType = commentableType; + this.commentableId = commentableId; + } + + protected override WebRequest CreateWebRequest() + { + var req = base.CreateWebRequest(); + + req.AddParameter("parent_id", commentId.ToString()); + req.AddParameter("sort", sort.ToString().ToLowerInvariant()); + req.AddParameter("commentable_type", commentableType.ToString().Underscore().ToLowerInvariant()); + req.AddParameter("commentable_id", commentableId.ToString()); + req.AddParameter("page", page.ToString()); + + return req; + } + + protected override string Target => "comments"; + } +} diff --git a/osu.Game/Online/API/Requests/Responses/Comment.cs b/osu.Game/Online/API/Requests/Responses/Comment.cs index 3e38c3067b..05a24cec0e 100644 --- a/osu.Game/Online/API/Requests/Responses/Comment.cs +++ b/osu.Game/Online/API/Requests/Responses/Comment.cs @@ -4,8 +4,6 @@ using Newtonsoft.Json; using osu.Game.Users; using System; -using System.Collections.Generic; -using System.Linq; namespace osu.Game.Online.API.Requests.Responses { @@ -17,8 +15,6 @@ namespace osu.Game.Online.API.Requests.Responses [JsonProperty(@"parent_id")] public long? ParentId { get; set; } - public readonly List ChildComments = new List(); - public Comment ParentComment { get; set; } [JsonProperty(@"user_id")] @@ -71,7 +67,5 @@ namespace osu.Game.Online.API.Requests.Responses public bool HasMessage => !string.IsNullOrEmpty(Message); public bool IsVoted { get; set; } - - public int DeletedChildrenCount => ChildComments.Count(c => c.IsDeleted); } } diff --git a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs index 9b3ef8b6e5..f4c81bf66f 100644 --- a/osu.Game/Online/API/Requests/Responses/CommentBundle.cs +++ b/osu.Game/Online/API/Requests/Responses/CommentBundle.cs @@ -9,31 +9,8 @@ namespace osu.Game.Online.API.Requests.Responses { public class CommentBundle { - private List comments; - [JsonProperty(@"comments")] - public List Comments - { - get => comments; - set - { - comments = value; - comments.ForEach(child => - { - if (child.ParentId != null) - { - comments.ForEach(parent => - { - if (parent.Id == child.ParentId) - { - parent.ChildComments.Add(child); - child.ParentComment = parent; - } - }); - } - }); - } - } + public List Comments { get; set; } [JsonProperty(@"has_more")] public bool HasMore { get; set; } diff --git a/osu.Game/Overlays/Comments/CommentsContainer.cs b/osu.Game/Overlays/Comments/CommentsContainer.cs index 33a6be0d7a..751fd8a353 100644 --- a/osu.Game/Overlays/Comments/CommentsContainer.cs +++ b/osu.Game/Overlays/Comments/CommentsContainer.cs @@ -18,8 +18,8 @@ namespace osu.Game.Overlays.Comments { public class CommentsContainer : CompositeDrawable { - private CommentableType type; - private long? id; + private readonly Bindable type = new Bindable(); + private readonly BindableLong id = new BindableLong(); public readonly Bindable Sort = new Bindable(); public readonly BindableBool ShowDeleted = new BindableBool(); @@ -127,8 +127,8 @@ namespace osu.Game.Overlays.Comments /// The id of the resource to get comments for. public void ShowComments(CommentableType type, long id) { - this.type = type; - this.id = id; + this.type.Value = type; + this.id.Value = id; if (!IsLoaded) return; @@ -147,12 +147,12 @@ namespace osu.Game.Overlays.Comments private void getComments() { - if (!id.HasValue) + if (id.Value == 0) return; request?.Cancel(); loadCancellation?.Cancel(); - request = new GetCommentsRequest(type, id.Value, Sort.Value, currentPage++); + request = new GetCommentsRequest(type.Value, id.Value, Sort.Value, currentPage++); request.Success += onSuccess; api.PerformAsync(request); } @@ -172,7 +172,10 @@ namespace osu.Game.Overlays.Comments LoadComponentAsync(new CommentsPage(response) { - ShowDeleted = { BindTarget = ShowDeleted } + ShowDeleted = { BindTarget = ShowDeleted }, + Sort = { BindTarget = Sort }, + Type = { BindTarget = type }, + CommentableId = { BindTarget = id } }, loaded => { content.Add(loaded); diff --git a/osu.Game/Overlays/Comments/CommentsPage.cs b/osu.Game/Overlays/Comments/CommentsPage.cs index 153ce676eb..976af72abb 100644 --- a/osu.Game/Overlays/Comments/CommentsPage.cs +++ b/osu.Game/Overlays/Comments/CommentsPage.cs @@ -9,12 +9,22 @@ using osu.Game.Online.API.Requests.Responses; using osu.Framework.Graphics.Shapes; using osu.Game.Graphics.Sprites; using System.Linq; +using osu.Game.Online.API.Requests; +using osu.Game.Online.API; +using System.Collections.Generic; +using osu.Framework.Extensions.IEnumerableExtensions; namespace osu.Game.Overlays.Comments { public class CommentsPage : CompositeDrawable { public readonly BindableBool ShowDeleted = new BindableBool(); + public readonly Bindable Sort = new Bindable(); + public readonly Bindable Type = new Bindable(); + public readonly BindableLong CommentableId = new BindableLong(); + + [Resolved] + private IAPIProvider api { get; set; } private readonly CommentBundle commentBundle; @@ -52,18 +62,58 @@ namespace osu.Game.Overlays.Comments return; } - foreach (var c in commentBundle.Comments) + foreach (var comment in commentBundle.Comments) { - if (c.IsTopLevel) + var drawableComment = createDrawableComment(comment); + + var children = commentBundle.Comments.Where(c => c.ParentId == comment.Id); + + if (children.Any()) { - flow.Add(new DrawableComment(c) + children.ForEach(c => { - ShowDeleted = { BindTarget = ShowDeleted } + c.ParentComment = comment; }); + drawableComment.OnLoadComplete += loaded => ((DrawableComment)loaded).AddReplies(children.Select(c => createDrawableComment(c))); } + + if (comment.IsTopLevel) + flow.Add(drawableComment); } } + private void onCommentRepliesRequested(DrawableComment drawableComment, int page) + { + var request = new GetCommentRepliesRequest(drawableComment.Comment.Id, Type.Value, CommentableId.Value, Sort.Value, page); + request.Success += response => onCommentRepliesReceived(response, drawableComment); + api.PerformAsync(request); + } + + private void onCommentRepliesReceived(CommentBundle response, DrawableComment drawableComment) + { + var receivedComments = response.Comments; + + var uniqueComments = new List(); + + // We may receive already loaded comments + receivedComments.ForEach(c => + { + if (drawableComment.LoadedReplies.All(loadedReply => loadedReply.Id != c.Id)) + uniqueComments.Add(c); + }); + + uniqueComments.ForEach(c => c.ParentComment = drawableComment.Comment); + + drawableComment.AddReplies(uniqueComments.Select(comment => createDrawableComment(comment))); + } + + private DrawableComment createDrawableComment(Comment comment) => new DrawableComment(comment) + { + ShowDeleted = { BindTarget = ShowDeleted }, + Sort = { BindTarget = Sort }, + RepliesRequested = onCommentRepliesRequested + }; + private class NoCommentsPlaceholder : CompositeDrawable { [BackgroundDependencyLoader] diff --git a/osu.Game/Overlays/Comments/DrawableComment.cs b/osu.Game/Overlays/Comments/DrawableComment.cs index 70ea478814..e7aac3c44d 100644 --- a/osu.Game/Overlays/Comments/DrawableComment.cs +++ b/osu.Game/Overlays/Comments/DrawableComment.cs @@ -12,11 +12,14 @@ using osu.Game.Graphics.Containers; using osu.Game.Utils; using osu.Framework.Graphics.Cursor; using osu.Framework.Bindables; -using osu.Framework.Graphics.Shapes; 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; namespace osu.Game.Overlays.Comments { @@ -25,24 +28,35 @@ namespace osu.Game.Overlays.Comments private const int avatar_size = 40; private const int margin = 10; + public Action RepliesRequested; + + public readonly Comment Comment; + public readonly BindableBool ShowDeleted = new BindableBool(); + public readonly Bindable Sort = new Bindable(); + public readonly List LoadedReplies = new List(); private readonly BindableBool childrenExpanded = new BindableBool(true); + private int currentPage; + private FillFlowContainer childCommentsVisibilityContainer; - private readonly Comment comment; + private FillFlowContainer childCommentsContainer; + private LoadMoreCommentsButton loadMoreCommentsButton; + private ShowMoreButton showMoreButton; + private RepliesButton repliesButton; + private ChevronButton chevronButton; + private DeletedCommentsCounter deletedCommentsCounter; public DrawableComment(Comment comment) { - this.comment = comment; + Comment = comment; } [BackgroundDependencyLoader] private void load() { LinkFlowContainer username; - FillFlowContainer childCommentsContainer; - DeletedCommentsCounter deletedCommentsCounter; FillFlowContainer info; LinkFlowContainer message; GridContainer content; @@ -50,234 +64,267 @@ namespace osu.Game.Overlays.Comments RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; - InternalChild = new FillFlowContainer + InternalChildren = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] + new FillFlowContainer { - new Container + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding(margin) { Left = margin + 5 }, - Child = content = new GridContainer + new Container { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, - ColumnDimensions = new[] + Padding = new MarginPadding(margin) { Left = margin + 5 }, + Child = content = new GridContainer { - new Dimension(GridSizeMode.AutoSize), - new Dimension(), - }, - RowDimensions = new[] - { - new Dimension(GridSizeMode.AutoSize) - }, - Content = new[] - { - new Drawable[] + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + ColumnDimensions = new[] { - new FillFlowContainer + new Dimension(GridSizeMode.AutoSize), + new Dimension(), + }, + RowDimensions = new[] + { + new Dimension(GridSizeMode.AutoSize) + }, + Content = new[] + { + new Drawable[] { - AutoSizeAxes = Axes.Both, - Margin = new MarginPadding { Horizontal = margin }, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(5, 0), - Children = new Drawable[] + new FillFlowContainer { - new Container + AutoSizeAxes = Axes.Both, + Margin = new MarginPadding { Horizontal = margin }, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(5, 0), + Children = new Drawable[] { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Width = 40, - AutoSizeAxes = Axes.Y, - Child = votePill = new VotePill(comment) + new Container { - Anchor = Anchor.CentreRight, - Origin = Anchor.CentreRight, - } - }, - new UpdateableAvatar(comment.User) - { - Anchor = Anchor.Centre, - Origin = Anchor.Centre, - Size = new Vector2(avatar_size), - Masking = true, - CornerRadius = avatar_size / 2f, - CornerExponent = 2, - }, - } - }, - new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Spacing = new Vector2(0, 3), - Children = new Drawable[] - { - new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(7, 0), - Children = new Drawable[] - { - username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Width = 40, + AutoSizeAxes = Axes.Y, + Child = votePill = new VotePill(Comment) { - AutoSizeAxes = Axes.Both, - }, - new ParentUsername(comment), - new OsuSpriteText - { - Alpha = comment.IsDeleted ? 1 : 0, - Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), - Text = @"deleted", + Anchor = Anchor.CentreRight, + Origin = Anchor.CentreRight, } - } - }, - message = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Padding = new MarginPadding { Right = 40 } - }, - info = new FillFlowContainer - { - AutoSizeAxes = Axes.Both, - Direction = FillDirection.Horizontal, - Spacing = new Vector2(10, 0), - Colour = OsuColour.Gray(0.7f), - Children = new Drawable[] + }, + new UpdateableAvatar(Comment.User) { - new OsuSpriteText + Anchor = Anchor.Centre, + Origin = Anchor.Centre, + Size = new Vector2(avatar_size), + Masking = true, + CornerRadius = avatar_size / 2f, + CornerExponent = 2, + }, + } + }, + new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Spacing = new Vector2(0, 3), + Children = new Drawable[] + { + new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(7, 0), + Children = new Drawable[] { - Anchor = Anchor.CentreLeft, - Origin = Anchor.CentreLeft, - Font = OsuFont.GetFont(size: 12), - Text = HumanizerUtils.Humanize(comment.CreatedAt) - }, - new RepliesButton(comment.RepliesCount) + username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true)) + { + AutoSizeAxes = Axes.Both, + }, + new ParentUsername(Comment), + new OsuSpriteText + { + Alpha = Comment.IsDeleted ? 1 : 0, + Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold, italics: true), + Text = @"deleted", + } + } + }, + message = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14)) + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Padding = new MarginPadding { Right = 40 } + }, + info = new FillFlowContainer + { + AutoSizeAxes = Axes.Both, + Direction = FillDirection.Horizontal, + Spacing = new Vector2(10, 0), + Children = new Drawable[] { - Expanded = { BindTarget = childrenExpanded } - }, + 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) + { + Expanded = { BindTarget = childrenExpanded } + }, + loadMoreCommentsButton = new LoadMoreCommentsButton + { + Action = () => RepliesRequested(this, ++currentPage) + } + } } } } } } } - } - }, - childCommentsVisibilityContainer = new FillFlowContainer - { - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical, - Children = new Drawable[] + }, + childCommentsVisibilityContainer = new FillFlowContainer { - childCommentsContainer = new FillFlowContainer + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = new Drawable[] { - Padding = new MarginPadding { Left = 20 }, - RelativeSizeAxes = Axes.X, - AutoSizeAxes = Axes.Y, - Direction = FillDirection.Vertical - }, - deletedCommentsCounter = new DeletedCommentsCounter - { - ShowDeleted = { BindTarget = ShowDeleted } + childCommentsContainer = new FillFlowContainer + { + Padding = new MarginPadding { Left = 20 }, + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical + }, + deletedCommentsCounter = new DeletedCommentsCounter + { + ShowDeleted = { BindTarget = ShowDeleted } + }, + showMoreButton = new ShowMoreButton + { + Action = () => RepliesRequested(this, ++currentPage) + } } - } + }, } + }, + chevronButton = new ChevronButton + { + Anchor = Anchor.TopRight, + Origin = Anchor.TopRight, + Margin = new MarginPadding { Right = 30, Top = margin }, + Expanded = { BindTarget = childrenExpanded }, + Alpha = 0 } }; - deletedCommentsCounter.Count.Value = comment.DeletedChildrenCount; - - if (comment.UserId.HasValue) - username.AddUserLink(comment.User); + if (Comment.UserId.HasValue) + username.AddUserLink(Comment.User); else - username.AddText(comment.LegacyName); + username.AddText(Comment.LegacyName); - if (comment.EditedAt.HasValue) + if (Comment.EditedAt.HasValue) { info.Add(new OsuSpriteText { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, Font = OsuFont.GetFont(size: 12), - Text = $@"edited {HumanizerUtils.Humanize(comment.EditedAt.Value)} by {comment.EditedUser.Username}" + Text = $@"edited {HumanizerUtils.Humanize(Comment.EditedAt.Value)} by {Comment.EditedUser.Username}" }); } - if (comment.HasMessage) + if (Comment.HasMessage) { - var formattedSource = MessageFormatter.FormatText(comment.Message); + var formattedSource = MessageFormatter.FormatText(Comment.Message); message.AddLinks(formattedSource.Text, formattedSource.Links); } - if (comment.IsDeleted) + if (Comment.IsDeleted) { content.FadeColour(OsuColour.Gray(0.5f)); votePill.Hide(); } - if (comment.IsTopLevel) + if (Comment.IsTopLevel) { - AddInternal(new Container + AddInternal(new Box { - RelativeSizeAxes = Axes.X, - Height = 1.5f, Anchor = Anchor.BottomCentre, Origin = Anchor.BottomCentre, - Child = new Box - { - RelativeSizeAxes = Axes.Both, - Colour = OsuColour.Gray(0.1f) - } + RelativeSizeAxes = Axes.X, + Height = 1.5f, + Colour = OsuColour.Gray(0.1f) }); - - if (comment.ChildComments.Any()) - { - AddInternal(new ChevronButton(comment) - { - Anchor = Anchor.TopRight, - Origin = Anchor.TopRight, - Margin = new MarginPadding { Right = 30, Top = margin }, - Expanded = { BindTarget = childrenExpanded } - }); - } } - - comment.ChildComments.ForEach(c => childCommentsContainer.Add(new DrawableComment(c) - { - ShowDeleted = { BindTarget = ShowDeleted } - })); } protected override void LoadComplete() { ShowDeleted.BindValueChanged(show => { - if (comment.IsDeleted) + if (Comment.IsDeleted) this.FadeTo(show.NewValue ? 1 : 0); }, true); childrenExpanded.BindValueChanged(expanded => childCommentsVisibilityContainer.FadeTo(expanded.NewValue ? 1 : 0), true); + + updateButtonsState(); + base.LoadComplete(); } + public void AddReplies(IEnumerable replies) + { + LoadComponentAsync(createRepliesPage(replies), page => + { + var newReplies = replies.Select(reply => reply.Comment); + LoadedReplies.AddRange(newReplies); + deletedCommentsCounter.Count.Value += newReplies.Count(reply => reply.IsDeleted); + childCommentsContainer.Add(page); + updateButtonsState(); + }); + } + + private FillFlowContainer createRepliesPage(IEnumerable replies) => new FillFlowContainer + { + RelativeSizeAxes = Axes.X, + AutoSizeAxes = Axes.Y, + Direction = FillDirection.Vertical, + Children = replies.ToList() + }; + + private void updateButtonsState() + { + var loadedReplesCount = LoadedReplies.Count; + var hasUnloadedReplies = loadedReplesCount != Comment.RepliesCount; + + loadMoreCommentsButton.FadeTo(hasUnloadedReplies && loadedReplesCount == 0 ? 1 : 0); + showMoreButton.FadeTo(hasUnloadedReplies && loadedReplesCount > 0 ? 1 : 0); + repliesButton.FadeTo(loadedReplesCount != 0 ? 1 : 0); + + if (Comment.IsTopLevel) + chevronButton.FadeTo(loadedReplesCount != 0 ? 1 : 0); + + showMoreButton.IsLoading = loadMoreCommentsButton.IsLoading = false; + } + private class ChevronButton : ShowChildrenButton { private readonly SpriteIcon icon; - public ChevronButton(Comment comment) + public ChevronButton() { - Alpha = comment.IsTopLevel && comment.ChildComments.Any() ? 1 : 0; Child = icon = new SpriteIcon { Size = new Vector2(12), - Colour = OsuColour.Gray(0.7f) }; } @@ -296,7 +343,6 @@ namespace osu.Game.Overlays.Comments { this.count = count; - Alpha = count == 0 ? 0 : 1; Child = text = new OsuSpriteText { Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), @@ -309,6 +355,30 @@ namespace osu.Game.Overlays.Comments } } + 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] + private void load(OverlayColourProvider colourProvider) + { + Margin = new MarginPadding { Vertical = 10, Left = 80 }; + IdleColour = colourProvider.Light2; + HoverColour = colourProvider.Light1; + } + + protected override string GetText() => @"Show More"; + } + private class ParentUsername : FillFlowContainer, IHasTooltip { public string TooltipText => getParentMessage(); diff --git a/osu.Game/Overlays/Comments/GetCommentRepliesButton.cs b/osu.Game/Overlays/Comments/GetCommentRepliesButton.cs new file mode 100644 index 0000000000..a3817ba416 --- /dev/null +++ b/osu.Game/Overlays/Comments/GetCommentRepliesButton.cs @@ -0,0 +1,45 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Graphics; +using osu.Game.Graphics; +using osu.Game.Graphics.UserInterface; +using osu.Framework.Graphics.Containers; +using osu.Game.Graphics.Sprites; +using System.Collections.Generic; +using osuTK; + +namespace osu.Game.Overlays.Comments +{ + public abstract class GetCommentRepliesButton : LoadingButton + { + private const int duration = 200; + + protected override IEnumerable EffectTargets => new[] { text }; + + private OsuSpriteText text; + + protected GetCommentRepliesButton() + { + AutoSizeAxes = Axes.Both; + LoadingAnimationSize = new Vector2(8); + } + + protected override Drawable CreateContent() => new Container + { + AutoSizeAxes = Axes.Both, + Child = text = new OsuSpriteText + { + AlwaysPresent = true, + Font = OsuFont.GetFont(size: 12, weight: FontWeight.Bold), + Text = GetText() + } + }; + + protected abstract string GetText(); + + protected override void OnLoadStarted() => text.FadeOut(duration, Easing.OutQuint); + + protected override void OnLoadFinished() => text.FadeIn(duration, Easing.OutQuint); + } +} diff --git a/osu.Game/Overlays/Comments/ShowChildrenButton.cs b/osu.Game/Overlays/Comments/ShowChildrenButton.cs index be04b6e5de..5ec7c1d471 100644 --- a/osu.Game/Overlays/Comments/ShowChildrenButton.cs +++ b/osu.Game/Overlays/Comments/ShowChildrenButton.cs @@ -3,8 +3,9 @@ using osu.Framework.Graphics; using osu.Game.Graphics.Containers; -using osu.Framework.Input.Events; using osu.Framework.Bindables; +using osuTK.Graphics; +using osu.Game.Graphics; namespace osu.Game.Overlays.Comments { @@ -15,20 +16,18 @@ namespace osu.Game.Overlays.Comments protected ShowChildrenButton() { AutoSizeAxes = Axes.Both; + IdleColour = OsuColour.Gray(0.7f); + HoverColour = Color4.White; } protected override void LoadComplete() { + Action = Expanded.Toggle; + Expanded.BindValueChanged(OnExpandedChanged, true); base.LoadComplete(); } protected abstract void OnExpandedChanged(ValueChangedEvent expanded); - - protected override bool OnClick(ClickEvent e) - { - Expanded.Value = !Expanded.Value; - return true; - } } }