Skip to content

Public reaction list pages for each post#490

Merged
dahlia merged 11 commits into
fedify-dev:mainfrom
dahlia:feat/reactions
May 17, 2026
Merged

Public reaction list pages for each post#490
dahlia merged 11 commits into
fedify-dev:mainfrom
dahlia:feat/reactions

Conversation

@dahlia
Copy link
Copy Markdown
Member

@dahlia dahlia commented May 16, 2026

Summary

Hollo's public post permalink page already shows the post and its replies, but there's no way to see who liked, boosted, reacted with a particular emoji, or quoted it. This PR adds four server-rendered pages under each local post permalink:

  • /@:handle/:id/likes: accounts that liked the post
  • /@:handle/:id/shares: accounts that boosted it
  • /@:handle/:id/reactions/:emoji: accounts that reacted with the given emoji
  • /@:handle/:id/quotes: posts that quote it

Each page renders the original post above the list, with ?page=N pagination at 100 entries per page. On the profile feed and post permalink page, the per-post like, share, quote, and reaction-emoji indicators are now clickable links into these pages for local posts; remote posts continue to render the counts as plain text.

The /shares and /quotes lists filter to visibility ∈ {public, unlisted} so private boosts and accepted private quotes aren't exposed in the public HTML. That's stricter than the pre-existing /api/v1/statuses/:id/reblogged_by endpoint, which returns all shares regardless of visibility. The post-footer counter on the source post still shows the persisted sharesCount/quotesCount, matching Mastodon's API convention; the destination heading and the listing both apply the same visibility filter, so the heading number reflects only what's actually visible.

Implementation notes

The four routes live in src/pages/profile/postReactions.tsx, mounted alongside src/pages/profile/profilePost.tsx under the same /:handle/:id prefix. The new src/components/PublicAccountList.tsx renders the likes/shares/reactions rows; the /quotes page reuses the existing Post component with the same divider styling as the permalink page's reply list.

src/components/Post.tsx gained a localPermalink computation that switches on post.account.owner != null. When the relation is loaded, the count indicators and reaction emojis become links into the new pages; otherwise the existing plain-text rendering is preserved. To decide whether the footer indicators should link, the profile and tag queries now load account.owner anywhere a post can render its footer: top-level posts, shared posts, quote targets, and replies (src/pages/profile/profilePost.tsx, src/pages/profile/index.tsx, src/pages/tags/index.tsx).

Custom emoji reactions render the image inline in the destination page heading by looking up one of the loaded rows' customEmoji URL and passing it through proxyUrl. Plain Unicode emojis fall back to the text character.

Test plan

  • On a local profile feed, verify likes/shares/quotes counts and reaction emojis on a post are now clickable.
  • Visit /likes, /shares, /quotes, and a /reactions/:emoji page (both Unicode and custom emoji). Confirm the featured post renders at the top and the list below.
  • Confirm a boosted remote post (rendered via the local profile) keeps its counts as plain text with no link wrappers.
  • Hit /@:handle/:id/reactions/<emoji-nobody-used> and /@:handle/:id/likes?page=999. Both requests should return 404 Not Found.
  • Boost or quote a local post with visibility=private and confirm it does not appear on the /shares or /quotes page.
  • mise run check passes.

dahlia added 2 commits May 17, 2026 06:55
Four new SSR pages let visitors see who reacted to a local post:
/@:handle/:id/likes lists likers, /shares lists boosters,
/reactions/:emoji lists accounts that used that emoji, and /quotes
lists posts that quote it.  Each page features the original post
above its list, with ?page-based pagination at 100 entries per
page.  The per-post like, share, quote, and reaction-emoji
indicators on the profile feed and post permalink page now link
into these pages for local posts; remote posts keep displaying
the counts as plain text.

The /shares and /quotes lists filter to public/unlisted entries
so private boosts and private accepted quotes aren't exposed on
the public HTML.

Assisted-by: Codex:gpt-5.5
The /@:handle/:id/reactions/:emoji heading was interpolating the raw
emoji column, which for custom emojis is the bare `:shortcode:` string.
Look up one row's customEmoji URL (already loaded for the listing) and
render it through proxyUrl as an <img>; fall back to the unicode
character when no customEmoji URL is present.

Assisted-by: Codex:gpt-5.5
@dahlia dahlia added this to the Hollo 0.9 milestone May 16, 2026
@dahlia dahlia self-assigned this May 16, 2026
@dahlia dahlia added the enhancement New feature or request label May 16, 2026
@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 16, 2026

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Delightful!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces public reaction list pages for local posts, enabling users to view accounts that liked, shared, or reacted to a post, as well as posts that quoted it. Key changes include the addition of a PublicAccountList component, a new postReactions route, and updates to the Post component to link reaction counts to these lists. Database queries were also updated to include account owner information. Feedback focuses on internationalization, specifically recommending the removal of hardcoded English strings and locales in favor of a localization system, and suggests refactoring duplicated post summary logic into a shared utility.

Comment thread src/pages/profile/postReactions.tsx
Comment thread src/pages/profile/postReactions.tsx
Comment thread src/pages/profile/postReactions.tsx Outdated
Comment thread src/pages/profile/postReactions.tsx
Comment thread src/pages/profile/postReactions.tsx
Comment thread src/components/Post.tsx
Comment thread src/components/Post.tsx
Comment thread src/components/Post.tsx
Both profilePost.tsx and postReactions.tsx derived the page title
summary with the same five-line snippet: fall back to post.summary,
truncate post.content at 30 characters with an ellipsis, otherwise
return the content as-is.  Lift that into summarizePostForTitle in a
new src/pages/profile/summary.ts so the rule lives in one place.

fedify-dev#490 (comment)

Assisted-by: Claude Code:claude-opus-4-7
@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 16, 2026

/gemini review

@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 16, 2026

@codex review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements public reaction list pages for local posts, including views for likes, shares, emoji reactions, and quotes. Key additions include a PublicAccountList component for displaying user profiles and a CountLink component within the Post view to navigate to these new lists. The feedback identifies opportunities to reduce type duplication by sharing a hydrated post structure, recommends localizing hardcoded strings for better internationalization, and suggests using more idiomatic Drizzle ORM query syntax.

Comment thread src/pages/profile/postReactions.tsx Outdated
Comment thread src/pages/profile/postReactions.tsx
Comment thread src/pages/profile/postReactions.tsx
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

The deeply nested post shape inside PostProps was duplicated as a
local FeaturedPost type in postReactions.tsx.  Lift the shape out as
an exported PostForView type alias and reuse it from postReactions.tsx
so the renderable-post type lives in one place.  Drops the unused
Medium/Poll/PollOption/Post/Reaction imports that the local type
needed.

fedify-dev#490 (comment)

Assisted-by: Claude Code:claude-opus-4-7
@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 16, 2026

/gemini review

@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 16, 2026

@codex review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements public reaction list pages for local posts, enabling users to view detailed lists of likes, shares, emoji reactions, and quotes. Key changes include the addition of a postReactions.tsx page, a PublicAccountList component, and a shared summarizePostForTitle utility. The Post component was updated to link reaction counts to these new pages, and database queries now include account owner data for local permalink construction. Feedback from the review highlights an opportunity to reduce code duplication by extracting shared relational query projections and identifies a bug in the emoji URL lookup logic that could fail during pagination, providing a specific code suggestion for the fix.

Comment thread src/pages/profile/postReactions.tsx Outdated
Comment thread src/pages/profile/postReactions.tsx Outdated
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

dahlia added 2 commits May 17, 2026 10:06
The custom emoji heading on /@:handle/:id/reactions/:emoji scanned
only the current page of result rows for a non-null customEmoji URL.
If every row on that page happened to have a null customEmoji (for
example after federation rows where only some bodies carried the
image URL), the heading fell back to the raw shortcode even when
post.reactions contained the URL.  Look it up on post.reactions
instead, which is loaded in full for the page header.

fedify-dev#490 (comment)

Assisted-by: Claude Code:claude-opus-4-7
The deeply nested `with` clause used to hydrate a post for PostView
rendering (author + owner, media, poll, sharing, reply target, quote
target, reactions) was repeated verbatim across the four SSR queries:
the profile feed and its pinned-posts subquery, the post permalink,
the hashtag feed, and the reaction list pages (both the post header
loader and the /quotes listing).  Lift it into a single
`postViewRelations` constant in a new src/pages/profile/postRelations.ts
and reference it from every site, so schema-level relation changes
land in one place.  The profilePost replies-list query spreads the
constant into its outer `with` and reuses it again as the inner
`replies.with`.

fedify-dev#490 (comment)

Assisted-by: Claude Code:claude-opus-4-7
@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 17, 2026

/gemini review

@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 17, 2026

@codex review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces public reaction list pages for local posts, allowing users to view accounts that liked, shared, reacted to, or quoted a post. Key architectural changes include the addition of the postReactions route, the PublicAccountList and CountLink components, and a centralized postViewRelations constant to streamline Drizzle ORM data fetching across profile and tag pages. Feedback suggests refining the logic for post summaries and descriptions to use truthiness checks instead of nullish coalescing; this ensures that empty strings—common in some ActivityPub implementations—correctly trigger a fallback to the post's content.

Comment thread src/pages/profile/postReactions.tsx Outdated
Comment thread src/pages/profile/summary.ts Outdated
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

ActivityPub bodies occasionally arrive with summary set to "" (an
empty content warning), and the existing nullish-coalescing checks
treated those rows as if the post had a summary.  That meant the
permalink and reaction list page titles showed the empty string,
and the OpenGraph description meta tag emitted an empty value
instead of falling back to the post content.

Switch summarizePostForTitle to a plain truthiness check, and use
|| (not ??) for the description fallback in the post permalink and
the reaction list pages so an empty summary defers to the content.

fedify-dev#490 (comment)
fedify-dev#490 (comment)

Assisted-by: Claude Code:claude-opus-4-7
@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 17, 2026

/gemini review

@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 17, 2026

@codex review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements public reaction list pages for local posts, enabling users to view accounts that liked, boosted, or reacted to a post, along with a list of quotes. Key changes include the addition of reaction endpoints, a shared database relation configuration, and a new account list component. Review feedback suggests standardizing the 'empty state' behavior for emoji reactions, adding unique keys to list items in the account list component, and ensuring meta descriptions are plain text by stripping HTML from post content.

Comment thread src/pages/profile/postReactions.tsx
Comment thread src/components/PublicAccountList.tsx
Comment thread src/pages/profile/postReactions.tsx
@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

The <li> wrappers around each PublicAccountItem in PublicAccountList
didn't carry a key prop.  Hono JSX doesn't require it for static SSR,
but the rest of the codebase (Post.tsx and other list renderers)
keys list items, so add `key={account.id}` for consistency.

fedify-dev#490 (comment)

Assisted-by: Claude Code:claude-opus-4-7
@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 17, 2026

/gemini review

@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 17, 2026

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements public reaction list pages for local posts, allowing users to view lists of accounts that liked, shared, or reacted to a post, as well as a list of quotes. Key architectural improvements include the introduction of the PostForView type and postViewRelations constant to standardize post data fetching and prop definitions. The feedback suggests further simplifying component interfaces by consistently applying the new PostForView type across profile and tag pages, and recommends adding unique key props to list items in the new reaction views to ensure efficient rendering.

Comment thread src/pages/profile/index.tsx Outdated
Comment thread src/pages/profile/index.tsx Outdated
Comment thread src/pages/profile/profilePost.tsx Outdated
Comment thread src/pages/profile/profilePost.tsx Outdated
Comment thread src/pages/tags/index.tsx Outdated
Comment thread src/pages/tags/index.tsx Outdated
Comment thread src/pages/profile/postReactions.tsx Outdated
dahlia added 2 commits May 17, 2026 10:48
The page-level component prop types in src/pages/profile/index.tsx,
src/pages/profile/profilePost.tsx, and src/pages/tags/index.tsx each
inlined the same deeply nested post shape that the recent
PostForView export already names.  Replace those nested type
literals with PostForView (or PostForView[] for the lists), and let
profilePost's PostPageProps express the extra replies array as
`PostForView & { replies: PostForView[] }`.  Drops the now-unused
Medium / Poll / PollOption / Post / Reaction / PostAccount imports
from each file.

fedify-dev#490 (comment)
fedify-dev#490 (comment)
fedify-dev#490 (comment)
fedify-dev#490 (comment)
fedify-dev#490 (comment)
fedify-dev#490 (comment)

Assisted-by: Claude Code:claude-opus-4-7
The PostView elements rendered for each row in the /quotes list
weren't keyed.  Add `key={q.id}` to match the same convention now
used for the PublicAccountList items and for other list renderers
in the codebase.

fedify-dev#490 (comment)

Assisted-by: Claude Code:claude-opus-4-7
@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 17, 2026

/gemini review

@dahlia
Copy link
Copy Markdown
Member Author

dahlia commented May 17, 2026

@codex review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements public reaction list pages for local posts, enabling users to view lists of accounts that liked, boosted, quoted, or reacted with specific emojis. To support this, a new postReactions.tsx page handler and a PublicAccountList component were added. The PR also introduces a centralized postViewRelations constant to standardize Drizzle ORM queries across the profile feed, post permalinks, and reaction pages. Additionally, the Post component was refactored to include clickable links for reaction counts on local posts. I have no feedback to provide.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@dahlia dahlia merged commit c50df2d into fedify-dev:main May 17, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant