mirror of
https://github.com/ppy/osu.git
synced 2025-03-23 10:47:21 +08:00
Merge pull request #14272 from gagahpangeran/pinned-comment
Add pinned comment section in comment container
This commit is contained in:
commit
16c0f3d5b4
@ -42,19 +42,21 @@ namespace osu.Game.Tests.Visual.Online
|
||||
() => commentsContainer.ChildrenOfType<CommentsShowMoreButton>().Single().IsLoading);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSingleCommentsPage()
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestSingleCommentsPage(bool withPinned)
|
||||
{
|
||||
setUpCommentsResponse(exampleComments);
|
||||
setUpCommentsResponse(getExampleComments(withPinned));
|
||||
AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123));
|
||||
AddUntilStep("show more button hidden",
|
||||
() => commentsContainer.ChildrenOfType<CommentsShowMoreButton>().Single().Alpha == 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultipleCommentPages()
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestMultipleCommentPages(bool withPinned)
|
||||
{
|
||||
var comments = exampleComments;
|
||||
var comments = getExampleComments(withPinned);
|
||||
comments.HasMore = true;
|
||||
comments.TopLevelCount = 10;
|
||||
|
||||
@ -64,11 +66,12 @@ namespace osu.Game.Tests.Visual.Online
|
||||
() => commentsContainer.ChildrenOfType<CommentsShowMoreButton>().Single().Alpha == 1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultipleLoads()
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestMultipleLoads(bool withPinned)
|
||||
{
|
||||
var comments = exampleComments;
|
||||
int topLevelCommentCount = exampleComments.Comments.Count;
|
||||
var comments = getExampleComments(withPinned);
|
||||
int topLevelCommentCount = comments.Comments.Count;
|
||||
|
||||
AddStep("hide container", () => commentsContainer.Hide());
|
||||
setUpCommentsResponse(comments);
|
||||
@ -79,6 +82,48 @@ namespace osu.Game.Tests.Visual.Online
|
||||
() => commentsContainer.ChildrenOfType<DrawableComment>().Count() == topLevelCommentCount);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestNoComment()
|
||||
{
|
||||
var comments = getExampleComments();
|
||||
comments.Comments.Clear();
|
||||
|
||||
setUpCommentsResponse(comments);
|
||||
AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123));
|
||||
AddAssert("no comment shown", () => !commentsContainer.ChildrenOfType<DrawableComment>().Any());
|
||||
}
|
||||
|
||||
[TestCase(false)]
|
||||
[TestCase(true)]
|
||||
public void TestSingleComment(bool withPinned)
|
||||
{
|
||||
var comment = new Comment
|
||||
{
|
||||
Id = 1,
|
||||
Message = "This is a single comment",
|
||||
LegacyName = "SingleUser",
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
VotesCount = 0,
|
||||
Pinned = withPinned,
|
||||
};
|
||||
|
||||
var bundle = new CommentBundle
|
||||
{
|
||||
Comments = new List<Comment> { comment },
|
||||
IncludedComments = new List<Comment>(),
|
||||
PinnedComments = new List<Comment>(),
|
||||
};
|
||||
|
||||
if (withPinned)
|
||||
bundle.PinnedComments.Add(comment);
|
||||
|
||||
setUpCommentsResponse(bundle);
|
||||
AddStep("show comments", () => commentsContainer.ShowComments(CommentableType.Beatmapset, 123));
|
||||
AddUntilStep("wait comment load", () => commentsContainer.ChildrenOfType<DrawableComment>().Any());
|
||||
AddAssert("only one comment shown", () =>
|
||||
commentsContainer.ChildrenOfType<DrawableComment>().Count(d => d.Comment.Pinned == withPinned) == 1);
|
||||
}
|
||||
|
||||
private void setUpCommentsResponse(CommentBundle commentBundle)
|
||||
=> AddStep("set up response", () =>
|
||||
{
|
||||
@ -92,38 +137,71 @@ namespace osu.Game.Tests.Visual.Online
|
||||
};
|
||||
});
|
||||
|
||||
private CommentBundle exampleComments => new CommentBundle
|
||||
private CommentBundle getExampleComments(bool withPinned = false)
|
||||
{
|
||||
Comments = new List<Comment>
|
||||
var bundle = new CommentBundle
|
||||
{
|
||||
new Comment
|
||||
Comments = new List<Comment>
|
||||
{
|
||||
Id = 1,
|
||||
Message = "This is a comment",
|
||||
LegacyName = "FirstUser",
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
VotesCount = 19,
|
||||
RepliesCount = 1
|
||||
new Comment
|
||||
{
|
||||
Id = 1,
|
||||
Message = "This is a comment",
|
||||
LegacyName = "FirstUser",
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
VotesCount = 19,
|
||||
RepliesCount = 1
|
||||
},
|
||||
new Comment
|
||||
{
|
||||
Id = 5,
|
||||
ParentId = 1,
|
||||
Message = "This is a child comment",
|
||||
LegacyName = "SecondUser",
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
VotesCount = 4,
|
||||
},
|
||||
new Comment
|
||||
{
|
||||
Id = 10,
|
||||
Message = "This is another comment",
|
||||
LegacyName = "ThirdUser",
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
VotesCount = 0
|
||||
},
|
||||
},
|
||||
new Comment
|
||||
IncludedComments = new List<Comment>(),
|
||||
PinnedComments = new List<Comment>(),
|
||||
};
|
||||
|
||||
if (withPinned)
|
||||
{
|
||||
var pinnedComment = new Comment
|
||||
{
|
||||
Id = 5,
|
||||
ParentId = 1,
|
||||
Message = "This is a child comment",
|
||||
LegacyName = "SecondUser",
|
||||
Id = 15,
|
||||
Message = "This is pinned comment",
|
||||
LegacyName = "PinnedUser",
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
VotesCount = 4,
|
||||
},
|
||||
new Comment
|
||||
VotesCount = 999,
|
||||
Pinned = true,
|
||||
RepliesCount = 1,
|
||||
};
|
||||
|
||||
bundle.Comments.Add(pinnedComment);
|
||||
bundle.PinnedComments.Add(pinnedComment);
|
||||
|
||||
bundle.Comments.Add(new Comment
|
||||
{
|
||||
Id = 10,
|
||||
Message = "This is another comment",
|
||||
LegacyName = "ThirdUser",
|
||||
Id = 20,
|
||||
Message = "Reply to pinned comment",
|
||||
LegacyName = "AbandonedUser",
|
||||
CreatedAt = DateTimeOffset.Now,
|
||||
VotesCount = 0
|
||||
},
|
||||
},
|
||||
IncludedComments = new List<Comment>(),
|
||||
};
|
||||
VotesCount = 0,
|
||||
ParentId = 15,
|
||||
});
|
||||
}
|
||||
|
||||
return bundle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
{
|
||||
AddStep(description, () =>
|
||||
{
|
||||
comment.Pinned = description == "Pinned";
|
||||
comment.Message = text;
|
||||
container.Add(new DrawableComment(comment));
|
||||
});
|
||||
@ -59,6 +60,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
private static object[] comments =
|
||||
{
|
||||
new[] { "Plain", "This is plain comment" },
|
||||
new[] { "Pinned", "This is pinned comment" },
|
||||
new[] { "Link", "Please visit https://osu.ppy.sh" },
|
||||
|
||||
new[]
|
||||
|
@ -149,6 +149,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
}
|
||||
},
|
||||
IncludedComments = new List<Comment>(),
|
||||
PinnedComments = new List<Comment>(),
|
||||
UserVotes = new List<long>
|
||||
{
|
||||
5
|
||||
@ -178,6 +179,7 @@ namespace osu.Game.Tests.Visual.Online
|
||||
},
|
||||
},
|
||||
IncludedComments = new List<Comment>(),
|
||||
PinnedComments = new List<Comment>(),
|
||||
};
|
||||
|
||||
private class TestCommentsContainer : CommentsContainer
|
||||
|
@ -58,6 +58,9 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
[JsonProperty(@"edited_by_id")]
|
||||
public long? EditedById { get; set; }
|
||||
|
||||
[JsonProperty(@"pinned")]
|
||||
public bool Pinned { get; set; }
|
||||
|
||||
public User EditedUser { get; set; }
|
||||
|
||||
public bool IsTopLevel => !ParentId.HasValue;
|
||||
|
@ -4,6 +4,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using osu.Game.Users;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
@ -24,6 +25,9 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
[JsonProperty(@"included_comments")]
|
||||
public List<Comment> IncludedComments { get; set; }
|
||||
|
||||
[JsonProperty(@"pinned_comments")]
|
||||
public List<Comment> PinnedComments { get; set; }
|
||||
|
||||
private List<long> userVotes;
|
||||
|
||||
[JsonProperty(@"user_votes")]
|
||||
@ -49,26 +53,17 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
{
|
||||
users = value;
|
||||
|
||||
value.ForEach(u =>
|
||||
foreach (var user in value)
|
||||
{
|
||||
Comments.ForEach(c =>
|
||||
foreach (var comment in Comments.Concat(IncludedComments).Concat(PinnedComments))
|
||||
{
|
||||
if (c.UserId == u.Id)
|
||||
c.User = u;
|
||||
if (comment.UserId == user.Id)
|
||||
comment.User = user;
|
||||
|
||||
if (c.EditedById == u.Id)
|
||||
c.EditedUser = u;
|
||||
});
|
||||
|
||||
IncludedComments.ForEach(c =>
|
||||
{
|
||||
if (c.UserId == u.Id)
|
||||
c.User = u;
|
||||
|
||||
if (c.EditedById == u.Id)
|
||||
c.EditedUser = u;
|
||||
});
|
||||
});
|
||||
if (comment.EditedById == user.Id)
|
||||
comment.EditedUser = user;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,7 @@ namespace osu.Game.Overlays.Comments
|
||||
private CancellationTokenSource loadCancellation;
|
||||
private int currentPage;
|
||||
|
||||
private FillFlowContainer pinnedContent;
|
||||
private FillFlowContainer content;
|
||||
private DeletedCommentsCounter deletedCommentsCounter;
|
||||
private CommentsShowMoreButton moreButton;
|
||||
@ -63,6 +64,25 @@ namespace osu.Game.Overlays.Comments
|
||||
Children = new Drawable[]
|
||||
{
|
||||
commentCounter = new TotalCommentsCounter(),
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Background4,
|
||||
},
|
||||
pinnedContent = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Direction = FillDirection.Vertical,
|
||||
},
|
||||
},
|
||||
},
|
||||
new CommentsHeader
|
||||
{
|
||||
Sort = { BindTarget = Sort },
|
||||
@ -173,6 +193,7 @@ namespace osu.Game.Overlays.Comments
|
||||
deletedCommentsCounter.Count.Value = 0;
|
||||
moreButton.Show();
|
||||
moreButton.IsLoading = true;
|
||||
pinnedContent.Clear();
|
||||
content.Clear();
|
||||
CommentDictionary.Clear();
|
||||
}
|
||||
@ -202,7 +223,7 @@ namespace osu.Game.Overlays.Comments
|
||||
var topLevelComments = new List<DrawableComment>();
|
||||
var orphaned = new List<Comment>();
|
||||
|
||||
foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments))
|
||||
foreach (var comment in bundle.Comments.Concat(bundle.IncludedComments).Concat(bundle.PinnedComments))
|
||||
{
|
||||
// Exclude possible duplicated comments.
|
||||
if (CommentDictionary.ContainsKey(comment.Id))
|
||||
@ -219,13 +240,15 @@ namespace osu.Game.Overlays.Comments
|
||||
{
|
||||
LoadComponentsAsync(topLevelComments, loaded =>
|
||||
{
|
||||
content.AddRange(loaded);
|
||||
pinnedContent.AddRange(loaded.Where(d => d.Comment.Pinned));
|
||||
content.AddRange(loaded.Where(d => !d.Comment.Pinned));
|
||||
|
||||
deletedCommentsCounter.Count.Value += topLevelComments.Select(d => d.Comment).Count(c => c.IsDeleted && c.IsTopLevel);
|
||||
|
||||
if (bundle.HasMore)
|
||||
{
|
||||
int loadedTopLevelComments = 0;
|
||||
pinnedContent.Children.OfType<DrawableComment>().ForEach(p => loadedTopLevelComments++);
|
||||
content.Children.OfType<DrawableComment>().ForEach(p => loadedTopLevelComments++);
|
||||
|
||||
moreButton.Current.Value = bundle.TopLevelCount - loadedTopLevelComments;
|
||||
@ -300,11 +323,6 @@ namespace osu.Game.Overlays.Comments
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AddRangeInternal(new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = colourProvider.Background4
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
|
@ -21,6 +21,7 @@ using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using System.Collections.Specialized;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Overlays.Comments.Buttons;
|
||||
using osu.Game.Resources.Localisation.Web;
|
||||
|
||||
namespace osu.Game.Overlays.Comments
|
||||
{
|
||||
@ -137,12 +138,13 @@ namespace osu.Game.Overlays.Comments
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Direction = FillDirection.Horizontal,
|
||||
Spacing = new Vector2(10, 0),
|
||||
Children = new Drawable[]
|
||||
Children = new[]
|
||||
{
|
||||
username = new LinkFlowContainer(s => s.Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold))
|
||||
{
|
||||
AutoSizeAxes = Axes.Both
|
||||
},
|
||||
Comment.Pinned ? new PinnedCommentNotice() : Empty(),
|
||||
new ParentUsername(Comment),
|
||||
new OsuSpriteText
|
||||
{
|
||||
@ -321,9 +323,7 @@ namespace osu.Game.Overlays.Comments
|
||||
this.FadeTo(show.NewValue ? 1 : 0);
|
||||
}, true);
|
||||
childrenExpanded.BindValueChanged(expanded => childCommentsVisibilityContainer.FadeTo(expanded.NewValue ? 1 : 0), true);
|
||||
|
||||
updateButtonsState();
|
||||
|
||||
base.LoadComplete();
|
||||
}
|
||||
|
||||
@ -392,6 +392,33 @@ namespace osu.Game.Overlays.Comments
|
||||
};
|
||||
}
|
||||
|
||||
private class PinnedCommentNotice : FillFlowContainer
|
||||
{
|
||||
public PinnedCommentNotice()
|
||||
{
|
||||
AutoSizeAxes = Axes.Both;
|
||||
Direction = FillDirection.Horizontal;
|
||||
Spacing = new Vector2(2, 0);
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new SpriteIcon
|
||||
{
|
||||
Icon = FontAwesome.Solid.Thumbtack,
|
||||
Size = new Vector2(14),
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
},
|
||||
new OsuSpriteText
|
||||
{
|
||||
Font = OsuFont.GetFont(size: 14, weight: FontWeight.Bold),
|
||||
Text = CommentsStrings.Pinned,
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class ParentUsername : FillFlowContainer, IHasTooltip
|
||||
{
|
||||
public LocalisableString TooltipText => getParentMessage();
|
||||
|
Loading…
x
Reference in New Issue
Block a user