Новый дизайн, удаление

This commit is contained in:
Халимов Рустам
2026-03-12 22:54:15 +03:00
parent 1ec6b438d2
commit 9daafae9c5
158 changed files with 1511 additions and 254 deletions

View File

@@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Vortex.Modules.Identity.Domain;
using Vortex.Modules.Identity.Infrastructure.Persistence;
@@ -16,12 +17,18 @@ public sealed class StoriesController : ControllerBase
private readonly IdentityDbContext _context;
private readonly IUserContext _userContext;
private readonly IUserRepository _userRepository;
private readonly Microsoft.AspNetCore.SignalR.IHubContext<Vortex.Modules.Chats.Infrastructure.SignalR.ChatHub> _hubContext;
public StoriesController(IdentityDbContext context, IUserContext userContext, IUserRepository userRepository)
public StoriesController(
IdentityDbContext context,
IUserContext userContext,
IUserRepository userRepository,
Microsoft.AspNetCore.SignalR.IHubContext<Vortex.Modules.Chats.Infrastructure.SignalR.ChatHub> hubContext)
{
_context = context;
_userContext = userContext;
_userRepository = userRepository;
_hubContext = hubContext;
}
[HttpGet]
@@ -37,17 +44,25 @@ public sealed class StoriesController : ControllerBase
friendIds.Add(currentUserId);
var stories = await _context.Stories
.Include(s => s.Viewers)
.Where(s => s.ExpiresAt > DateTime.UtcNow && friendIds.Contains(s.UserId))
.OrderByDescending(s => s.CreatedAt)
.ToListAsync(ct);
var groups = stories.GroupBy(s => s.UserId);
var groups = stories.GroupBy(s => s.UserId).ToList();
var result = new List<object>();
var userIds = groups.Select(g => g.Key).ToList();
var userMap = new Dictionary<Guid, dynamic>();
foreach (var uid in userIds)
{
var u = await _userRepository.GetByIdAsync(uid, ct);
if (u != null) userMap[uid] = u;
}
foreach (var group in groups)
{
var user = await _userRepository.GetByIdAsync(group.Key, ct);
if (user == null) continue;
if (!userMap.TryGetValue(group.Key, out var user)) continue;
result.Add(new
{
@@ -67,10 +82,10 @@ public sealed class StoriesController : ControllerBase
bgColor = s.BgColor,
createdAt = s.CreatedAt,
expiresAt = s.ExpiresAt,
viewCount = 0,
viewed = false
}).ToList(),
hasUnviewed = true
viewCount = s.Viewers.Count,
viewed = s.Viewers.Any(v => v.UserId == currentUserId)
}).OrderBy(s => s.createdAt).ToList(),
hasUnviewed = group.Any(s => !s.Viewers.Any(v => v.UserId == currentUserId))
});
}
@@ -99,6 +114,84 @@ public sealed class StoriesController : ControllerBase
return Ok(new { id = story.Id });
}
[HttpPost("{id}/view")]
public async Task<IActionResult> ViewStory(Guid id, CancellationToken ct)
{
var story = await _context.Stories
.Include(s => s.Viewers)
.FirstOrDefaultAsync(s => s.Id == id, ct);
if (story == null) return NotFound();
if (story.UserId == _userContext.UserId) return Ok(new { message = "Owner view" });
if (!story.Viewers.Any(v => v.UserId == _userContext.UserId))
{
story.AddViewer(_userContext.UserId);
await _context.SaveChangesAsync(ct);
// Notify owner via SignalR
var viewer = await _userRepository.GetByIdAsync(_userContext.UserId, ct);
await _hubContext.Clients.User(story.UserId.ToString()).SendAsync("story_viewed", new
{
storyId = story.Id,
userId = _userContext.UserId,
username = viewer?.Username,
displayName = viewer?.DisplayName,
avatar = viewer?.Avatar,
viewedAt = DateTime.UtcNow,
viewCount = story.Viewers.Count
}, ct);
}
return Ok(new { message = "Story viewed" });
}
[HttpGet("{id}/viewers")]
public async Task<IActionResult> GetStoryViewers(Guid id, CancellationToken ct)
{
var story = await _context.Stories
.Include(s => s.Viewers)
.FirstOrDefaultAsync(s => s.Id == id, ct);
if (story == null) return NotFound();
if (story.UserId != _userContext.UserId) return Forbid();
var viewerIds = story.Viewers.Select(v => v.UserId).ToList();
var viewers = new List<object>();
foreach (var viewerId in viewerIds)
{
var user = await _userRepository.GetByIdAsync(viewerId, ct);
if (user == null) continue;
var viewerRecord = story.Viewers.First(v => v.UserId == viewerId);
viewers.Add(new
{
userId = user.Id,
username = user.Username,
displayName = user.DisplayName,
avatar = user.Avatar,
viewedAt = viewerRecord.ViewedAt
});
}
return Ok(viewers);
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteStory(Guid id, CancellationToken ct)
{
var story = await _context.Stories.FindAsync(new object[] { id }, ct);
if (story == null) return NotFound();
if (story.UserId != _userContext.UserId) return Forbid();
_context.Stories.Remove(story);
await _context.SaveChangesAsync(ct);
return Ok(new { message = "Story deleted" });
}
}
public sealed record CreateStoryRequest(string Type, string? MediaUrl, string? Content, string? BgColor);