Compare commits
2 Commits
89406870bd
...
b3ed98322b
| Author | SHA1 | Date | |
|---|---|---|---|
| b3ed98322b | |||
| 4cfd4387b6 |
@@ -47,6 +47,7 @@ public class Post : ModelBase, IIdentifiedResource, IActivity
|
|||||||
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; }
|
[NotMapped] public int RepliesCount { get; set; }
|
||||||
|
[NotMapped] public Dictionary<string, bool>? ReactionsMade { get; set; }
|
||||||
|
|
||||||
public Guid? RepliedPostId { get; set; }
|
public Guid? RepliedPostId { get; set; }
|
||||||
public Post? RepliedPost { get; set; }
|
public Post? RepliedPost { get; set; }
|
||||||
|
|||||||
@@ -151,6 +151,30 @@ public class PostController(
|
|||||||
return Ok(posts);
|
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")]
|
[HttpGet("{id:guid}/replies/featured")]
|
||||||
public async Task<ActionResult<Post>> GetFeaturedReply(Guid id)
|
public async Task<ActionResult<Post>> GetFeaturedReply(Guid id)
|
||||||
{
|
{
|
||||||
@@ -165,7 +189,7 @@ public class PostController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
var userPublishers = currentUser is null ? [] : await pub.GetUserPublishers(Guid.Parse(currentUser.Id));
|
var userPublishers = currentUser is null ? [] : await pub.GetUserPublishers(Guid.Parse(currentUser.Id));
|
||||||
|
|
||||||
var now = SystemClock.Instance.GetCurrentInstant();
|
var now = SystemClock.Instance.GetCurrentInstant();
|
||||||
var post = await db.Posts
|
var post = await db.Posts
|
||||||
.Where(e => e.RepliedPostId == id)
|
.Where(e => e.RepliedPostId == id)
|
||||||
@@ -181,7 +205,7 @@ public class PostController(
|
|||||||
|
|
||||||
// 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);
|
await ps.IncreaseViewCount(post.Id, currentUser?.Id);
|
||||||
|
|
||||||
return await ps.LoadPostInfo(post);
|
return await ps.LoadPostInfo(post);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -182,7 +182,8 @@ public partial class PostService(
|
|||||||
Title = localizer["PostReplyTitle", sender.Nick],
|
Title = localizer["PostReplyTitle", sender.Nick],
|
||||||
Body = string.IsNullOrWhiteSpace(post.Title)
|
Body = string.IsNullOrWhiteSpace(post.Title)
|
||||||
? localizer["PostReplyBody", sender.Nick, ChopPostForNotification(post).content]
|
? 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,
|
IsSavable = true,
|
||||||
ActionUri = $"/posts/{post.Id}"
|
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>
|
/// <summary>
|
||||||
/// Increases the view count for a post.
|
/// Increases the view count for a post.
|
||||||
/// Uses the flush buffer service to batch database updates for better performance.
|
/// Uses the flush buffer service to batch database updates for better performance.
|
||||||
@@ -595,20 +614,28 @@ public partial class PostService(
|
|||||||
var postsId = posts.Select(e => e.Id).ToList();
|
var postsId = posts.Select(e => e.Id).ToList();
|
||||||
|
|
||||||
var reactionMaps = await GetPostReactionMapBatch(postsId);
|
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);
|
var repliesCountMap = await GetPostRepliesCountBatch(postsId);
|
||||||
|
|
||||||
foreach (var post in posts)
|
foreach (var post in posts)
|
||||||
{
|
{
|
||||||
// Set reactions count
|
// Set reaction count
|
||||||
post.ReactionsCount = reactionMaps.TryGetValue(post.Id, out var count)
|
post.ReactionsCount = reactionMaps.TryGetValue(post.Id, out var count)
|
||||||
? count
|
? count
|
||||||
: new Dictionary<string, int>();
|
: 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)
|
post.RepliesCount = repliesCountMap.TryGetValue(post.Id, out var repliesCount)
|
||||||
? repliesCount
|
? repliesCount
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
// Track view for each post in the list
|
// Track view for each post in the list
|
||||||
if (currentUser != null)
|
if (currentUser != null)
|
||||||
await IncreaseViewCount(post.Id, currentUser.Id);
|
await IncreaseViewCount(post.Id, currentUser.Id);
|
||||||
@@ -688,4 +715,4 @@ public static class PostQueryExtensions
|
|||||||
(e.Publisher.AccountId != null && userFriends.Contains(e.Publisher.AccountId.Value)) ||
|
(e.Publisher.AccountId != null && userFriends.Contains(e.Publisher.AccountId.Value)) ||
|
||||||
publishersId.Contains(e.PublisherId));
|
publishersId.Contains(e.PublisherId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user