Iceshrimp.NET/Iceshrimp.Backend/Pages/NotePreview.razor
2025-03-15 17:32:42 +01:00

141 lines
No EOL
5 KiB
Text

@page "/notes/{id}"
@using Iceshrimp.Backend.Components.PublicPreview.Attributes
@using Iceshrimp.Backend.Core.Extensions
@attribute [PublicPreviewRouteFilter]
@inherits AsyncComponentBase
@if (_note is null)
{
Context.Response.StatusCode = 404;
<div>
<h2>Not found</h2>
<p>This note either doesn't exist or is only accessible to authenticated users</p>
</div>
}
else
{
<NoteComponent Note="_note"/>
if (_note.QuoteUrl != null)
{
var displayUrl = _note.QuoteUrl.StartsWith("https://") ? _note.QuoteUrl[8..] : _note.QuoteUrl[7..];
<p>
@if (_note.QuoteInaccessible)
{
<i>This note is quoting <a href="@_note.QuoteUrl">@displayUrl</a>, which has either been deleted or is not publicly visible.</i>
}
else
{
<i>This note is quoting <a href="@_note.QuoteUrl">@displayUrl</a></i>
}
</p>
}
if (_note.Poll != null)
{
var total = _note.Poll.Choices.Sum(p => p.Votes);
<div class="poll-results">
@foreach (var choice in _note.Poll.Choices)
{
var percentage = total == 0 ? 0 : Math.Floor(choice.Votes / (double)total * 100);
<span class="poll-result" style="--percentage: @percentage%;">
<span class="poll-value">@choice.Value</span>
<span class="poll-info"><span class="vote-count">@choice.Votes votes</span><span class="vote-percentage">@percentage%</span></span>
</span>
}
</div>
List<string> 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}");
<span>@string.Join(" - ", footerText)</span>
}
if (!ShowMedia && _note.Attachments != null)
{
<p>
<i>This post has attachments, but this server's configuration prevents them from being displayed here.</i>
</p>
}
else if (ShowMedia && _note.Attachments is { Count: > 0 })
{
foreach (var file in _note.Attachments)
{
if (file.MimeType.StartsWith("image/"))
{
<img src="@file.Url" max-width="200px" max-height="200px" alt="@(file.Alt ?? "")"/>
}
else if (file.MimeType.StartsWith("video/"))
{
<video controls max-width="200px" max-height="200px">
<source src="@file.Url" type="@file.MimeType"/>
<p>@(file.Alt ?? "No alt text.")</p>
</video>
}
else
{
<div>Attachment: <a href="@file.Url">@file.Name</a> (@file.MimeType)</div>
}
}
}
<PageTitle>Note by @@@_note.User.Username - @_instanceName</PageTitle>
<HeadContent>
@{
var cardType = "summary";
var previewImageUrl = _note.User.AvatarUrl;
if (ShowMedia && _note.Attachments != null)
{
if (_note.Attachments.FirstOrDefault(p => p.MimeType.StartsWith("image/") && !p.Sensitive) is { } img)
{
cardType = "summary_large_image";
previewImageUrl = img.Url;
}
}
string description;
if (_note.Cw is { } cw)
{
description = $"Content warning: {cw}";
}
else
{
var text = _note.RawText?.TruncateEllipsis(280);
if (_note.Attachments is { Count: > 0 })
{
var attachmentText = $"({_note.Attachments.Count} attachments)";
text = text is null
? attachmentText
: text + $"\n{attachmentText}";
}
description = text + (_note.QuoteUrl != null ? $"\n\nRE: {_note.QuoteUrl}" : "");
}
var username = _note.User.Username;
var title = _note.User.RawDisplayName is { } name ? $"{name} (@{username})" : $"@{username}";
}
<meta name="twitter:card" content="@cardType">
<meta property="og:site_name" content="@_instanceName">
<meta property="og:title" content="@title">
<meta property="og:image" content="@previewImageUrl">
<meta property="og:description" content="@description">
<link rel="alternate" type="application/activity+json" href="@_note.Uri">
<VersionedLink rel="stylesheet" href="/css/public-preview.css"/>
</HeadContent>
if (!ShowRemoteReplies)
{
<p>
<i>This server's configuration is preventing remotely originating content from being shown. This view may therefore be incomplete.</i>
</p>
}
}