Iceshrimp.NET/Iceshrimp.Backend/Pages/Note.cshtml
2024-09-24 02:17:56 +02:00

171 lines
No EOL
5.7 KiB
Text

@page "/notes/{id}"
@using AngleSharp
@using Iceshrimp.Backend.Core.Database.Tables
@using Iceshrimp.Backend.Core.Extensions
@model NoteModel
@section styles
{
<link rel="stylesheet" href="~/css/public-preview.css"/>
}
@if (Model.Note == null)
{
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
{
async Task RenderNote(string name, Note note)
{
Model.TextContent.TryGetValue(note.Id, out var textContent);
var acct = "@" + note.User.Username + (note.User.IsLocalUser ? "" : "@" + note.User.Host);
var displayName = await RenderDisplayName(note.User.DisplayName ?? note.User.Username);
var url = note.User.UserProfile?.Url ?? note.User.Uri ?? note.User.GetPublicUrl(Model.WebDomain);
var avatarUrl = note.User.AvatarUrl == null || !Model.ShowMedia ? note.User.IdenticonUrlPath : note.User.AvatarUrl;
<div class="user">
<a href="@url">
<img src="@avatarUrl" class="avatar" alt="User avatar"/>
</a>
<div class="title">@name by <a class="display-name" href="@url">@Html.Raw(displayName)</a></div>
<span class="acct">@acct</span>
</div>
<small>Published at: @note.CreatedAt.ToDisplayString()</small>
@if (note.UpdatedAt != null)
{
<small>Edited at: @note.UpdatedAt.Value.ToDisplayString()</small>
}
if (textContent != null)
{
<div class="content-wrapper">
@if (note.Cw != null)
{
<details>
<summary>@note.Cw</summary>
@Html.Raw(textContent)
</details>
}
else
{
<div class="content">@Html.Raw(textContent)</div>
}
</div>
}
if (!Model.MediaAttachments.TryGetValue(note.Id, out var files)) return;
if (!Model.ShowMedia)
{
<p>
<i>This post has attachments, but this server's configuration prevents them from being displayed here.</i>
</p>
return;
}
@foreach (var file in files)
{
if (file.Type.StartsWith("image/"))
{
<img src="@file.Url" max-width="200px" alt="@file.Comment"/>
}
else if (file.Type.StartsWith("video/"))
{
<video controls max-width="200px">
<source src="@file.Url" type="@file.Type"/>
<p>@(file.Comment ?? "No alt text.")</p>
</video>
}
else
{
<div>Attachment: <a href="@file.Url">@file.Name</a> (@file.Type)</div>
}
}
return;
async Task<string> RenderDisplayName(string input)
{
var res = Html.Encode(input);
var emojis = Model.UserEmoji[note.User.Id];
if (emojis is []) return res;
var context = BrowsingContext.New();
var document = await context.OpenNewAsync();
foreach (var emoji in emojis)
{
var el = document.CreateElement("span");
var inner = document.CreateElement("img");
inner.SetAttribute("src", emoji.PublicUrl);
el.AppendChild(inner);
el.ClassList.Add("emoji");
res = res.Replace($":{emoji.Name.Trim(':')}:", el.OuterHtml);
}
return res;
}
}
async Task RenderQuoteUrl(string url)
{
var displayUrl = url.StartsWith("https://") ? url[8..] : url[7..];
<p>
<i>This post is quoting <a href="@url">@displayUrl</a>, but that post either has been deleted or is not publicly visible.</i>
</p>
}
ViewData["title"] = $"Note by @{Model.Note.User.Username} - {Model.InstanceName}";
@section head
{
@{
Model.MediaAttachments.TryGetValue(Model.Note.Id, out var attachments);
}
<meta name="twitter:card" content="summary">
<meta name="og:title" content="Note by @@@Model.Note.User.Username">
@if (Model.Note.Cw != null)
{
<meta name="og:description" content="Content warning: @Model.Note.Cw)">
}
else
{
var text = Model.Note.Text;
if (attachments is { Count: > 0 })
{
var attachmentText = $"({attachments.Count} attachments)";
if (string.IsNullOrWhiteSpace(text))
text = attachmentText;
else
text += $"\n{attachmentText}";
}
<meta name="og:description" content="@(text + (Model.QuoteUrl != null ? $"\n\nRE: {Model.QuoteUrl}" : ""))">
}
<meta name="og:site_name" content="@Model.InstanceName">
@if (Model.ShowMedia && attachments != null)
{
if (attachments.Any(p => p.Type.StartsWith("image/")))
{
<meta name="og:image" content="@attachments.First(p => p.Type.StartsWith("image/")).Url">
}
}
}
<div class="note">
@{
await RenderNote("Note", Model.Note);
if (Model.Note.Renote != null)
await RenderNote("Quote", Model.Note.Renote);
else if (Model.QuoteUrl != null)
await RenderQuoteUrl(Model.QuoteUrl);
}
</div>
if (!Model.ShowRemoteReplies)
{
<p>
<i>This server's configuration is preventing remotely originating content from being shown. This view may therefore be incomplete.</i>
</p>
}
}