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