Post reactions and replies counting

🎨 Improve the styles of post service
This commit is contained in:
LittleSheep 2025-06-20 00:31:16 +08:00
parent abc89dc782
commit 27276c66c5
4 changed files with 68 additions and 28 deletions

View File

@ -24,8 +24,7 @@ public class ActivityService(AppDatabase db, PublisherService pub, RelationshipS
.FilterWithVisibility(null, [], [], isListing: true) .FilterWithVisibility(null, [], [], isListing: true)
.Take(take) .Take(take)
.ToListAsync(); .ToListAsync();
posts = PostService.TruncatePostContent(posts); posts = await ps.LoadPostInfo(posts, null, true);
posts = await ps.LoadPublishers(posts);
var postsId = posts.Select(e => e.Id).ToList(); var postsId = posts.Select(e => e.Id).ToList();
var reactionMaps = await ps.GetPostReactionMapBatch(postsId); var reactionMaps = await ps.GetPostReactionMapBatch(postsId);
@ -63,8 +62,7 @@ public class ActivityService(AppDatabase db, PublisherService pub, RelationshipS
.FilterWithVisibility(currentUser, userFriends, userPublishers, isListing: true) .FilterWithVisibility(currentUser, userFriends, userPublishers, isListing: true)
.Take(take) .Take(take)
.ToListAsync(); .ToListAsync();
posts = PostService.TruncatePostContent(posts); posts = await ps.LoadPostInfo(posts, currentUser, true);
posts = await ps.LoadPublishers(posts);
var postsId = posts.Select(e => e.Id).ToList(); var postsId = posts.Select(e => e.Id).ToList();
var reactionMaps = await ps.GetPostReactionMapBatch(postsId); var reactionMaps = await ps.GetPostReactionMapBatch(postsId);

View File

@ -44,6 +44,7 @@ public class Post : ModelBase, IIdentifiedResource, IActivity
public int Upvotes { get; set; } public int Upvotes { get; set; }
public int Downvotes { get; set; } public int Downvotes { get; set; }
[NotMapped] public Dictionary<string, int> ReactionsCount { get; set; } = new(); [NotMapped] public Dictionary<string, int> ReactionsCount { get; set; } = new();
[NotMapped] public int RepliesCount { get; set; }
public Guid? RepliedPostId { get; set; } public Guid? RepliedPostId { get; set; }
public Post? RepliedPost { get; set; } public Post? RepliedPost { get; set; }

View File

@ -52,26 +52,7 @@ public class PostController(
.Skip(offset) .Skip(offset)
.Take(take) .Take(take)
.ToListAsync(); .ToListAsync();
posts = PostService.TruncatePostContent(posts); posts = await ps.LoadPostInfo(posts, currentUser, true);
posts = await ps.LoadPublishers(posts);
var postsId = posts.Select(e => e.Id).ToList();
var reactionMaps = await ps.GetPostReactionMapBatch(postsId);
foreach (var post in posts)
{
post.ReactionsCount =
reactionMaps.TryGetValue(post.Id, out var count) ? count : new Dictionary<string, int>();
// Track view for each post in the list
if (currentUser != null)
{
await ps.IncreaseViewCount(post.Id, currentUser.Id.ToString());
}
else
{
await ps.IncreaseViewCount(post.Id);
}
}
Response.Headers["X-Total"] = totalCount.ToString(); Response.Headers["X-Total"] = totalCount.ToString();
@ -94,8 +75,7 @@ public class PostController(
.FilterWithVisibility(currentUser, userFriends, userPublishers) .FilterWithVisibility(currentUser, userFriends, userPublishers)
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
if (post is null) return NotFound(); if (post is null) return NotFound();
post = await ps.LoadPostInfo(post, currentUser);
post.ReactionsCount = await ps.GetPostReactionMap(post.Id);
// Track view - use the account ID as viewer ID if user is logged in // Track view - use the account ID as viewer ID if user is logged in
await ps.IncreaseViewCount(post.Id, currentUser?.Id.ToString()); await ps.IncreaseViewCount(post.Id, currentUser?.Id.ToString());
@ -131,8 +111,7 @@ public class PostController(
.Skip(offset) .Skip(offset)
.Take(take) .Take(take)
.ToListAsync(); .ToListAsync();
posts = PostService.TruncatePostContent(posts); posts = await ps.LoadPostInfo(posts, currentUser, true);
posts = await ps.LoadPublishers(posts);
var postsId = posts.Select(e => e.Id).ToList(); var postsId = posts.Select(e => e.Id).ToList();
var reactionMaps = await ps.GetPostReactionMapBatch(postsId); var reactionMaps = await ps.GetPostReactionMapBatch(postsId);

View File

@ -435,6 +435,68 @@ public class PostService(
return posts; return posts;
} }
public async Task<List<Post>> LoadInteractive(List<Post> posts, Account.Account? currentUser = null)
{
if (posts.Count == 0) return posts;
var postsId = posts.Select(e => e.Id).ToList();
var reactionMaps = await GetPostReactionMapBatch(postsId);
var repliesCountMap = await GetPostRepliesCountBatch(postsId);
foreach (var post in posts)
{
// Set reactions count
post.ReactionsCount = reactionMaps.TryGetValue(post.Id, out var count)
? count
: new Dictionary<string, int>();
// Set replies count
post.RepliesCount = repliesCountMap.TryGetValue(post.Id, out var repliesCount)
? repliesCount
: 0;
// Track view for each post in the list
if (currentUser != null)
await IncreaseViewCount(post.Id, currentUser.Id.ToString());
else
await IncreaseViewCount(post.Id);
}
return posts;
}
private async Task<Dictionary<Guid, int>> GetPostRepliesCountBatch(List<Guid> postIds)
{
return await db.Posts
.Where(p => p.RepliedPostId != null && postIds.Contains(p.RepliedPostId.Value))
.GroupBy(p => p.RepliedPostId!.Value)
.ToDictionaryAsync(
g => g.Key,
g => g.Count()
);
}
public async Task<List<Post>> LoadPostInfo(List<Post> posts, Account.Account? currentUser = null, bool truncate = false)
{
if (posts.Count == 0) return posts;
posts = await LoadPublishers(posts);
posts = await LoadInteractive(posts, currentUser);
if (truncate)
posts = TruncatePostContent(posts);
return posts;
}
public async Task<Post> LoadPostInfo(Post post, Account.Account? currentUser = null, bool truncate = false)
{
// Convert single post to list, process it, then return the single post
var posts = await LoadPostInfo([post], currentUser, truncate);
return posts.First();
}
} }
public static class PostQueryExtensions public static class PostQueryExtensions