osu/osu.Game/Overlays/Comments/CommentsPage.cs

162 lines
5.8 KiB
C#
Raw Normal View History

2020-01-29 03:22:08 +00:00
// 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.Allocation;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics;
using osu.Framework.Bindables;
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 JetBrains.Annotations;
2020-01-29 03:22:08 +00:00
namespace osu.Game.Overlays.Comments
{
2020-01-29 03:58:53 +00:00
public class CommentsPage : CompositeDrawable
2020-01-29 03:22:08 +00:00
{
public readonly BindableBool ShowDeleted = new BindableBool();
public readonly Bindable<CommentsSortCriteria> Sort = new Bindable<CommentsSortCriteria>();
public readonly Bindable<CommentableType> Type = new Bindable<CommentableType>();
public readonly BindableLong CommentableId = new BindableLong();
[Resolved]
private IAPIProvider api { get; set; }
2020-01-29 03:22:08 +00:00
private readonly CommentBundle commentBundle;
private FillFlowContainer flow;
2020-01-29 03:22:08 +00:00
public CommentsPage(CommentBundle commentBundle)
{
this.commentBundle = commentBundle;
}
[BackgroundDependencyLoader]
2020-01-29 03:58:53 +00:00
private void load(OverlayColourProvider colourProvider)
2020-01-29 03:22:08 +00:00
{
RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y;
2020-01-29 03:58:53 +00:00
AddRangeInternal(new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background5
},
flow = new FillFlowContainer
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
Direction = FillDirection.Vertical,
}
});
2020-01-29 03:22:08 +00:00
if (!commentBundle.Comments.Any())
{
2020-01-29 03:58:53 +00:00
flow.Add(new NoCommentsPlaceholder());
2020-01-29 03:22:08 +00:00
return;
}
2020-02-25 07:29:03 +00:00
AppendComments(commentBundle);
}
2020-02-21 09:47:56 +00:00
private DrawableComment getDrawableComment(Comment comment)
{
2020-02-25 07:29:03 +00:00
if (CommentDictionary.TryGetValue(comment.Id, out var existing))
2020-02-21 09:47:56 +00:00
return existing;
2020-02-25 07:29:03 +00:00
return CommentDictionary[comment.Id] = new DrawableComment(comment)
2020-02-21 09:47:56 +00:00
{
ShowDeleted = { BindTarget = ShowDeleted },
Sort = { BindTarget = Sort },
RepliesRequested = onCommentRepliesRequested
};
}
private void onCommentRepliesRequested(DrawableComment drawableComment, int page)
{
var request = new GetCommentsRequest(CommentableId.Value, Type.Value, Sort.Value, page, drawableComment.Comment.Id);
2020-02-25 07:29:03 +00:00
request.Success += response => Schedule(() => AppendComments(response));
2020-02-21 09:47:56 +00:00
api.PerformAsync(request);
}
2020-02-25 07:29:03 +00:00
protected readonly Dictionary<long, DrawableComment> CommentDictionary = new Dictionary<long, DrawableComment>();
2020-02-13 01:50:04 +00:00
/// <summary>
2020-02-21 10:41:00 +00:00
/// Appends retrieved comments to the subtree rooted of comments in this page.
/// </summary>
/// <param name="bundle">The bundle of comments to add.</param>
2020-02-25 07:29:03 +00:00
protected void AppendComments([NotNull] CommentBundle bundle)
{
2020-02-21 10:41:00 +00:00
var orphaned = new List<Comment>();
2020-02-24 20:10:37 +00:00
foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments))
{
2020-02-24 20:30:27 +00:00
// Exclude possible duplicated comments.
2020-02-25 07:29:03 +00:00
if (CommentDictionary.ContainsKey(comment.Id))
continue;
2020-02-24 20:10:37 +00:00
addNewComment(comment);
}
2020-02-21 10:41:00 +00:00
// Comments whose parents were seen later than themselves can now be added.
foreach (var o in orphaned)
addNewComment(o);
2020-02-21 09:47:14 +00:00
void addNewComment(Comment comment)
{
var drawableComment = getDrawableComment(comment);
if (comment.ParentId == null)
{
2020-02-21 09:47:14 +00:00
// Comments that have no parent are added as top-level comments to the flow.
flow.Add(drawableComment);
}
2020-02-25 07:29:03 +00:00
else if (CommentDictionary.TryGetValue(comment.ParentId.Value, out var parentDrawable))
{
// The comment's parent has already been seen, so the parent<-> child links can be added.
2020-02-21 09:46:14 +00:00
comment.ParentComment = parentDrawable.Comment;
parentDrawable.Replies.Add(drawableComment);
}
2020-02-21 10:41:00 +00:00
else
{
// The comment's parent has not been seen yet, so keep it orphaned for the time being. This can occur if the comments arrive out of order.
// Since this comment has now been seen, any further children can be added to it without being orphaned themselves.
orphaned.Add(comment);
}
}
}
2020-01-29 03:22:08 +00:00
private class NoCommentsPlaceholder : CompositeDrawable
{
[BackgroundDependencyLoader]
private void load(OverlayColourProvider colourProvider)
{
Height = 80;
RelativeSizeAxes = Axes.X;
AddRangeInternal(new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = colourProvider.Background4
},
new OsuSpriteText
{
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
Margin = new MarginPadding { Left = 50 },
Text = @"No comments yet."
}
});
}
}
}
}