[backend/core] Allow editing of locally originated polls (ISH-136)
This also improves the behavior of handling remotely originating poll edits.
This commit is contained in:
parent
84f7ac7051
commit
57ac4750ad
3 changed files with 62 additions and 13 deletions
|
@ -331,20 +331,29 @@ public class StatusController(
|
||||||
public async Task<IActionResult> EditNote(string id, [FromHybrid] StatusSchemas.EditStatusRequest request)
|
public async Task<IActionResult> EditNote(string id, [FromHybrid] StatusSchemas.EditStatusRequest request)
|
||||||
{
|
{
|
||||||
var user = HttpContext.GetUserOrFail();
|
var user = HttpContext.GetUserOrFail();
|
||||||
var note = await db.Notes.IncludeCommonProperties().FirstOrDefaultAsync(p => p.Id == id && p.User == user) ??
|
var note = await db.Notes
|
||||||
|
.Include(p => p.Poll)
|
||||||
|
.IncludeCommonProperties()
|
||||||
|
.FirstOrDefaultAsync(p => p.Id == id && p.User == user) ??
|
||||||
throw GracefulException.RecordNotFound();
|
throw GracefulException.RecordNotFound();
|
||||||
|
|
||||||
if (request.Text == null && request.MediaIds is not { Count: > 0 } && request.Poll == null)
|
if (request.Text == null && request.MediaIds is not { Count: > 0 } && request.Poll == null)
|
||||||
throw GracefulException.BadRequest("Posts must have text, media or poll");
|
throw GracefulException.BadRequest("Posts must have text, media or poll");
|
||||||
|
|
||||||
if (request.Poll != null)
|
var poll = request.Poll != null
|
||||||
throw GracefulException.BadRequest("Poll edits haven't been implemented yet, please delete & redraft instead");
|
? new Poll
|
||||||
|
{
|
||||||
|
Choices = request.Poll.Options,
|
||||||
|
Multiple = request.Poll.Multiple,
|
||||||
|
ExpiresAt = DateTime.UtcNow + TimeSpan.FromSeconds(request.Poll.ExpiresIn)
|
||||||
|
}
|
||||||
|
: null;
|
||||||
|
|
||||||
var attachments = request.MediaIds != null
|
var attachments = request.MediaIds != null
|
||||||
? await db.DriveFiles.Where(p => request.MediaIds.Contains(p.Id)).ToListAsync()
|
? await db.DriveFiles.Where(p => request.MediaIds.Contains(p.Id)).ToListAsync()
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
note = await noteSvc.UpdateNoteAsync(note, request.Text, request.Cw, attachments);
|
note = await noteSvc.UpdateNoteAsync(note, request.Text, request.Cw, attachments, poll);
|
||||||
var res = await noteRenderer.RenderAsync(note, user);
|
var res = await noteRenderer.RenderAsync(note, user);
|
||||||
|
|
||||||
return Ok(res);
|
return Ok(res);
|
||||||
|
|
|
@ -144,7 +144,7 @@ public abstract class BackgroundTaskQueue
|
||||||
var db = scope.GetRequiredService<DatabaseContext>();
|
var db = scope.GetRequiredService<DatabaseContext>();
|
||||||
var poll = await db.Polls.FirstOrDefaultAsync(p => p.NoteId == job.NoteId, cancellationToken: token);
|
var poll = await db.Polls.FirstOrDefaultAsync(p => p.NoteId == job.NoteId, cancellationToken: token);
|
||||||
if (poll == null) return;
|
if (poll == null) return;
|
||||||
if (poll.ExpiresAt > DateTime.UtcNow + TimeSpan.FromMinutes(5)) return;
|
if (poll.ExpiresAt > DateTime.UtcNow + TimeSpan.FromSeconds(30)) return;
|
||||||
var note = await db.Notes.IncludeCommonProperties()
|
var note = await db.Notes.IncludeCommonProperties()
|
||||||
.FirstOrDefaultAsync(p => p.Id == poll.NoteId, cancellationToken: token);
|
.FirstOrDefaultAsync(p => p.Id == poll.NoteId, cancellationToken: token);
|
||||||
if (note == null) return;
|
if (note == null) return;
|
||||||
|
|
|
@ -208,7 +208,8 @@ public class NoteService(
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Note> UpdateNoteAsync(
|
public async Task<Note> UpdateNoteAsync(
|
||||||
Note note, string? text = null, string? cw = null, IReadOnlyCollection<DriveFile>? attachments = null
|
Note note, string? text = null, string? cw = null, IReadOnlyCollection<DriveFile>? attachments = null,
|
||||||
|
Poll? poll = null
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var noteEdit = new NoteEdit
|
var noteEdit = new NoteEdit
|
||||||
|
@ -268,6 +269,38 @@ public class NoteService(
|
||||||
|
|
||||||
note.UpdatedAt = DateTime.UtcNow;
|
note.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
if (poll != null)
|
||||||
|
{
|
||||||
|
if (note.Poll != null)
|
||||||
|
{
|
||||||
|
if (note.Poll.ExpiresAt != poll.ExpiresAt)
|
||||||
|
{
|
||||||
|
note.Poll.ExpiresAt = poll.ExpiresAt;
|
||||||
|
await EnqueuePollExpiryTask(note.Poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!note.Poll.Choices.SequenceEqual(poll.Choices) || note.Poll.Multiple != poll.Multiple)
|
||||||
|
{
|
||||||
|
await db.PollVotes.Where(p => p.Note == note).ExecuteDeleteAsync();
|
||||||
|
note.Poll.Choices = poll.Choices;
|
||||||
|
note.Poll.Votes = poll.Choices.Select(p => 0).ToList();
|
||||||
|
note.Poll.Multiple = poll.Multiple;
|
||||||
|
db.Update(note.Poll);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
poll.Note = note;
|
||||||
|
poll.UserId = note.User.Id;
|
||||||
|
poll.UserHost = note.UserHost;
|
||||||
|
poll.Votes = poll.Choices.Select(_ => 0).ToList();
|
||||||
|
poll.NoteVisibility = note.Visibility;
|
||||||
|
await db.AddAsync(poll);
|
||||||
|
await EnqueuePollExpiryTask(poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
note.HasPoll = true;
|
||||||
|
}
|
||||||
|
|
||||||
db.Update(note);
|
db.Update(note);
|
||||||
await db.AddAsync(noteEdit);
|
await db.AddAsync(noteEdit);
|
||||||
await db.SaveChangesAsync();
|
await db.SaveChangesAsync();
|
||||||
|
@ -658,12 +691,19 @@ public class NoteService(
|
||||||
|
|
||||||
if (dbNote.Poll != null)
|
if (dbNote.Poll != null)
|
||||||
{
|
{
|
||||||
if (!dbNote.Poll.Choices.SequenceEqual(choices.Select(p => p.Name)))
|
if (dbNote.Poll.ExpiresAt != (question.EndTime ?? question.Closed))
|
||||||
|
{
|
||||||
|
dbNote.Poll.ExpiresAt = question.EndTime ?? question.Closed;
|
||||||
|
if (dbNote.Poll.ExpiresAt != null)
|
||||||
|
await EnqueuePollExpiryTask(dbNote.Poll);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dbNote.Poll.Choices.SequenceEqual(choices.Select(p => p.Name)) ||
|
||||||
|
dbNote.Poll.Multiple != (question.AnyOf != null))
|
||||||
{
|
{
|
||||||
await db.PollVotes.Where(p => p.Note == dbNote).ExecuteDeleteAsync();
|
await db.PollVotes.Where(p => p.Note == dbNote).ExecuteDeleteAsync();
|
||||||
dbNote.Poll.Choices = choices.Select(p => p.Name).Cast<string>().ToList();
|
dbNote.Poll.Choices = choices.Select(p => p.Name).Cast<string>().ToList();
|
||||||
dbNote.Poll.Votes = choices.Select(p => (int?)p.Replies?.TotalItems ?? 0).ToList();
|
dbNote.Poll.Votes = choices.Select(p => (int?)p.Replies?.TotalItems ?? 0).ToList();
|
||||||
dbNote.Poll.ExpiresAt = question.EndTime ?? question.Closed;
|
|
||||||
dbNote.Poll.Multiple = question.AnyOf != null;
|
dbNote.Poll.Multiple = question.AnyOf != null;
|
||||||
db.Update(dbNote.Poll);
|
db.Update(dbNote.Poll);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue