Compare commits

...

2 Commits

Author SHA1 Message Date
b3ed98322b Able to get post reactions list 2025-07-31 20:51:28 +08:00
4cfd4387b6 Reaction made status 2025-07-31 20:48:44 +08:00
3 changed files with 59 additions and 7 deletions

View File

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

View File

@@ -151,6 +151,30 @@ public class PostController(
return Ok(posts);
}
[HttpGet("{id:guid}/reactions")]
public async Task<ActionResult<List<PostReaction>>> GetReactions(
Guid id,
[FromQuery] string? symbol = null,
[FromQuery] int offset = 0,
[FromQuery] int take = 20
)
{
var query = db.PostReactions
.Where(e => e.PostId == id);
if (symbol is not null) query = query.Where(e => e.Symbol == symbol);
var totalCount = await query.CountAsync();
Response.Headers.Append("X-Total", totalCount.ToString());
var reactions = await query
.OrderBy(r => r.Symbol)
.ThenByDescending(r => r.CreatedAt)
.Take(take)
.Skip(offset)
.ToListAsync();
return Ok(reactions);
}
[HttpGet("{id:guid}/replies/featured")]
public async Task<ActionResult<Post>> GetFeaturedReply(Guid id)
{

View File

@@ -182,7 +182,8 @@ public partial class PostService(
Title = localizer["PostReplyTitle", sender.Nick],
Body = string.IsNullOrWhiteSpace(post.Title)
? localizer["PostReplyBody", sender.Nick, ChopPostForNotification(post).content]
: localizer["PostReplyContentBody", sender.Nick, post.Title, ChopPostForNotification(post).content],
: localizer["PostReplyContentBody", sender.Nick, post.Title,
ChopPostForNotification(post).content],
IsSavable = true,
ActionUri = $"/posts/{post.Id}"
}
@@ -519,6 +520,24 @@ public partial class PostService(
);
}
public async Task<Dictionary<Guid, Dictionary<string, bool>>> GetPostReactionMadeMapBatch(List<Guid> postIds, Guid accountId)
{
var reactions = await db.Set<PostReaction>()
.Where(r => postIds.Contains(r.PostId) && r.AccountId == accountId)
.Select(r => new { r.PostId, r.Symbol })
.ToListAsync();
return postIds.ToDictionary(
postId => postId,
postId => reactions
.Where(r => r.PostId == postId)
.ToDictionary(
r => r.Symbol,
_ => true
)
);
}
/// <summary>
/// Increases the view count for a post.
/// Uses the flush buffer service to batch database updates for better performance.
@@ -595,16 +614,24 @@ public partial class PostService(
var postsId = posts.Select(e => e.Id).ToList();
var reactionMaps = await GetPostReactionMapBatch(postsId);
var reactionMadeMap = currentUser is not null
? await GetPostReactionMadeMapBatch(postsId, Guid.Parse(currentUser.Id))
: new Dictionary<Guid, Dictionary<string, bool>>();
var repliesCountMap = await GetPostRepliesCountBatch(postsId);
foreach (var post in posts)
{
// Set reactions count
// Set reaction count
post.ReactionsCount = reactionMaps.TryGetValue(post.Id, out var count)
? count
: new Dictionary<string, int>();
// Set replies count
// Set reaction made status
post.ReactionsMade = reactionMadeMap.TryGetValue(post.Id, out var made)
? made
: [];
// Set reply count
post.RepliesCount = repliesCountMap.TryGetValue(post.Id, out var repliesCount)
? repliesCount
: 0;