From 66f3b23e461a7d7dc3d688f256bc07e29c5cd39e Mon Sep 17 00:00:00 2001
From: pancakes
Date: Tue, 7 Jan 2025 17:38:38 +1000
Subject: [PATCH] [backend/razor] Add polls to public preview notes
---
.../PublicPreview/Renderers/NoteRenderer.cs | 28 +++++++++--
.../PublicPreview/Schemas/PreviewNote.cs | 9 ++++
Iceshrimp.Backend/Pages/NotePreview.razor | 27 ++++++++++
Iceshrimp.Backend/Pages/NotePreview.razor.css | 49 +++++++++++++++++++
4 files changed, 110 insertions(+), 3 deletions(-)
create mode 100644 Iceshrimp.Backend/Pages/NotePreview.razor.css
diff --git a/Iceshrimp.Backend/Components/PublicPreview/Renderers/NoteRenderer.cs b/Iceshrimp.Backend/Components/PublicPreview/Renderers/NoteRenderer.cs
index 06964374..e4d1728e 100644
--- a/Iceshrimp.Backend/Components/PublicPreview/Renderers/NoteRenderer.cs
+++ b/Iceshrimp.Backend/Components/PublicPreview/Renderers/NoteRenderer.cs
@@ -28,13 +28,15 @@ public class NoteRenderer(
var emoji = await GetEmojiAsync(allNotes);
var users = await GetUsersAsync(allNotes);
var attachments = await GetAttachmentsAsync(allNotes);
+ var polls = await GetPollsAsync(allNotes);
- return await RenderAsync(note, users, mentions, emoji, attachments);
+ return await RenderAsync(note, users, mentions, emoji, attachments, polls);
}
private async Task RenderAsync(
Note note, List users, Dictionary> mentions,
- Dictionary> emoji, Dictionary?> attachments
+ Dictionary> emoji, Dictionary?> attachments,
+ Dictionary polls
)
{
var renderedText = await mfm.RenderAsync(note.Text, note.User.Host, mentions[note.Id], emoji[note.Id], "span", attachments[note.Id]);
@@ -49,6 +51,7 @@ public class NoteRenderer(
QuoteUrl = note.Renote?.Url ?? note.Renote?.Uri ?? note.Renote?.GetPublicUriOrNull(instance.Value),
QuoteInaccessible = note.Renote?.VisibilityIsPublicOrHome == false,
Attachments = attachments[note.Id]?.Where(p => !inlineMediaUrls.Contains(p.Url)).ToList(),
+ Poll = polls.GetValueOrDefault(note.Id),
CreatedAt = note.CreatedAt.ToDisplayStringTz(),
UpdatedAt = note.UpdatedAt?.ToDisplayStringTz()
};
@@ -112,6 +115,24 @@ public class NoteRenderer(
.ToList());
}
+ private async Task> GetPollsAsync(List notes)
+ {
+ if (notes is []) return new Dictionary();
+ var ids = notes.Select(p => p.Id).ToList();
+ var polls = await db.Polls
+ .Where(p => ids.Contains(p.NoteId))
+ .ToListAsync();
+
+ return polls.ToDictionary(p => p.NoteId,
+ p => new PreviewPoll
+ {
+ ExpiresAt = p.ExpiresAt,
+ Multiple = p.Multiple,
+ Choices = p.Choices.Zip(p.Votes).Select(c => (c.First, c.Second)).ToList(),
+ VotersCount = p.VotersCount
+ });
+ }
+
public async Task> RenderManyAsync(List notes)
{
if (notes is []) return [];
@@ -120,7 +141,8 @@ public class NoteRenderer(
var mentions = await GetMentionsAsync(allNotes);
var emoji = await GetEmojiAsync(allNotes);
var attachments = await GetAttachmentsAsync(allNotes);
- return await notes.Select(p => RenderAsync(p, users, mentions, emoji, attachments))
+ var polls = await GetPollsAsync(allNotes);
+ return await notes.Select(p => RenderAsync(p, users, mentions, emoji, attachments, polls))
.AwaitAllAsync()
.ToListAsync();
}
diff --git a/Iceshrimp.Backend/Components/PublicPreview/Schemas/PreviewNote.cs b/Iceshrimp.Backend/Components/PublicPreview/Schemas/PreviewNote.cs
index 8e07ce45..c688756d 100644
--- a/Iceshrimp.Backend/Components/PublicPreview/Schemas/PreviewNote.cs
+++ b/Iceshrimp.Backend/Components/PublicPreview/Schemas/PreviewNote.cs
@@ -11,6 +11,7 @@ public class PreviewNote
public required string? QuoteUrl;
public required bool QuoteInaccessible;
public required List? Attachments;
+ public required PreviewPoll? Poll;
public required string CreatedAt;
public required string? UpdatedAt;
}
@@ -22,4 +23,12 @@ public class PreviewAttachment
public required string Name;
public required string? Alt;
public required bool Sensitive;
+}
+
+public class PreviewPoll
+{
+ public required DateTime? ExpiresAt { get; set; }
+ public required bool Multiple { get; set; }
+ public required List<(string Value, int Votes)> Choices { get; set; }
+ public required int? VotersCount { get; set; }
}
\ No newline at end of file
diff --git a/Iceshrimp.Backend/Pages/NotePreview.razor b/Iceshrimp.Backend/Pages/NotePreview.razor
index ab60acab..a5528d46 100644
--- a/Iceshrimp.Backend/Pages/NotePreview.razor
+++ b/Iceshrimp.Backend/Pages/NotePreview.razor
@@ -30,6 +30,33 @@ else
}
+ if (_note.Poll != null)
+ {
+ var total = _note.Poll.Choices.Sum(p => p.Votes);
+
+
+ @foreach (var choice in _note.Poll.Choices)
+ {
+ var percentage = Math.Floor(choice.Votes / (double)total * 100);
+
+
+ @choice.Value
+ @choice.Votes votes@percentage%
+
+ }
+
+
+ List footerText = [];
+ @if (_note.Poll.Multiple)
+ footerText.Add("Multiple choice");
+ @if (_note.Poll.VotersCount != null)
+ footerText.Add($"{_note.Poll.VotersCount} users voted");
+ @if (_note.Poll.ExpiresAt != null)
+ footerText.Add(_note.Poll.ExpiresAt <= DateTime.UtcNow ? "Ended" : $"Ends at {_note.Poll.ExpiresAt.Value.ToLocalTime():G}");
+
+ @string.Join(" - ", footerText)
+ }
+
if (!ShowMedia && _note.Attachments != null)
{
diff --git a/Iceshrimp.Backend/Pages/NotePreview.razor.css b/Iceshrimp.Backend/Pages/NotePreview.razor.css
new file mode 100644
index 00000000..85a1b137
--- /dev/null
+++ b/Iceshrimp.Backend/Pages/NotePreview.razor.css
@@ -0,0 +1,49 @@
+.poll-results {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ width: 100%;
+ margin-top: 0.5em;
+}
+
+.poll-result {
+ --percentage: 0%;
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+ padding: 0.2rem 0.5rem;
+ border-radius: 0.5rem;
+ background: linear-gradient(to right, var(--selection) var(--percentage), var(--background) var(--percentage), var(--background));
+}
+
+.poll-value {
+ flex-grow: 1;
+ text-wrap: wrap;
+ word-break: break-word;
+}
+
+.poll-info {
+ flex-shrink: 0;
+}
+
+.vote-count, .vote-percentage {
+ display: inline-block;
+ vertical-align: middle;
+ text-wrap: nowrap;
+}
+
+.vote-count {
+ margin-right: 0.5rem;
+ font-size: 0.7em;
+}
+
+@media (max-width: 768px) {
+ .poll-result {
+ flex-direction: column;
+ align-items: start;
+ }
+
+ .vote-count {
+ font-size: 1em;
+ }
+}
\ No newline at end of file