From 202479873216c56b685c9da3fd1329877ddd022e Mon Sep 17 00:00:00 2001 From: thepra Date: Mon, 5 Oct 2026 17:55:39 +0200 Subject: [PATCH] Custom emoji, downvotes, blurhash and focal points on the cards What other platforms send now shows as they meant it: - custom emoji (a post's or account's :shortcode:) as their pictures in posts, names, content warnings, bios and fields: only the shortcodes the server listed, only http(s) pictures, never inside a tag, the shortcode kept as alt text; - a threadiverse post's downvotes next to its favourites; - blurhash placeholders until a picture loads (wwwroot/js/blurhash.js, a small decoder that watches the page), and a picture's focal point; - an event's online link, participants and capacity, and whether it is tentative or cancelled. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw --- CLAUDE.md | 5 ++ Components/Content.razor | 43 ++++++++++++++-- Helpers/CustomEmojis.cs | 47 ++++++++++++++++++ Pages/Profile.razor | 8 +-- Resources/AllStrings.it.resx | 18 +++++++ Resources/AllStrings.resx | 18 +++++++ Styles/feed.css | 10 ++++ wwwroot/index.html | 1 + wwwroot/js/blurhash.js | 95 ++++++++++++++++++++++++++++++++++++ 9 files changed, 236 insertions(+), 9 deletions(-) create mode 100644 Helpers/CustomEmojis.cs create mode 100644 wwwroot/js/blurhash.js diff --git a/CLAUDE.md b/CLAUDE.md index f0b532c..5ca6cbc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -224,6 +224,11 @@ supplies: with its own `PublicAct`: joining an event (owner decision 2026-10-05) is asked once more, since the event's server shows who takes part. An event card shows the persona's participation (`privapub.event.participation`: pending, accepted, rejected) with Join or Leave, except for events by invitation or taken on another site (`join_mode`). +- **What a card shows of other platforms:** custom emoji (`Helpers/CustomEmojis.cs`: a post's or account's `:shortcode:` + in its text, name, warning, bio and fields, as the picture the server listed, never inside a tag), a threadiverse + post's downvotes next to its favourites, blurhash placeholders until a picture loads (`wwwroot/js/blurhash.js` + watches the page for `img[data-blurhash]`), a picture's focal point (`object-position`), and an event's online + link, participants and status. - **Profiles and search** (`Pages/Profile.razor` at `/account/{id}`, `Pages/Search.razor` at `/search?q=`): a card's author and a notification's account open the profile in the app; "Open original" is the only way to the remote site. A card in a fixed-height flex column with `overflow-hidden` needs `flex-none`, or it collapses to nothing. diff --git a/Components/Content.razor b/Components/Content.razor index 20fc44c..7aa30d1 100644 --- a/Components/Content.razor +++ b/Components/Content.razor @@ -54,7 +54,7 @@ {

- @booster.Name + @CustomEmojis.Text(booster.Name, booster.Emojis) @Localizer["boosted"]

} @@ -81,7 +81,7 @@
- @status.Account?.Name + @CustomEmojis.Text(status.Account?.Name, status.Account?.Emojis ?? []) @("@" + status.Account?.Acct) @@ -137,7 +137,7 @@
- @spoiler + @CustomEmojis.Text(spoiler, status.Emojis)
@Body(status) @@ -229,6 +229,13 @@ @status.FavouritesCount } + @* a threadiverse post's downvotes: its upvotes are its favourites *@ + @if (status.Privapub?.Votes is { Down: > 0 } votes) + { + + @votes.Down + + } @@ -400,7 +407,7 @@ RenderFragment Body(Status status) => @
@if (status.Content is { Length: > 0 } content) { -
@((MarkupString)content)
+
@((MarkupString)CustomEmojis.Html(content, status.Emojis))
} @if (status.MediaAttachments.Count > 0) @@ -492,6 +499,25 @@ { @(venue.Name ?? venue.Address ?? venue.Url) } + @if (IsWebLink(happening.OnlineUrl)) + { + @Localizer["Online"] + } + @if (happening.Participants is { } going) + { + + @(happening.Capacity is { } capacity ? Localizer["{0} of {1} going", going, capacity] : Localizer["{0} going", going]) + + } + @switch (happening.Status?.ToUpperInvariant()) + { + case "CANCELLED": + @Localizer["Cancelled"] + break; + case "TENTATIVE": + @Localizer["Tentative"] + break; + } @if (CanJoin(happening)) {
@@ -544,7 +570,7 @@ { "image" => @ @media.Description + src="@(media.PreviewUrl ?? media.Url)" data-blurhash="@media.Blurhash" style="@FocalPoint(media)" /> , "gifv" => @, "video" => @