Repository navigation
Follow hashtags: chips, tag feed header, Topics pinning, Tags tab - #1715
Conversation
A signed-in reader can follow a plain hashtag the way they favorite an author. One hook, useFollowTag, derives the state from the user's followed list (one cached request for every chip on the page) and drives two controls: FollowTagBtn on the new tag feed header, and FollowTagChipToggle at the trailing edge of a tag chip, which stops the click before the chip's link navigates. A signed-out reader sees both and gets the login modal. Post footer chips get the toggle (community chips keep subscribe), the tag feed gets a header with the tag name and a Follow button, the Topics card pins the user's followed tags first and lists each tag once, and the Bookmarks dialog gains a Tags tab with unfollow.
|
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
|
Warning Review limit reachedNext included review available in 4 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (14)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Summary by QodoAdd hashtag follow controls and tag management surfaces
AI Description
Diagram
High-Level Assessment
Files changed (13)
|
Code Review by Qodo
1.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4e29fa6356
ℹ️ 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".
| if (followed) { | ||
| await remove(tag); | ||
| } else { | ||
| await add(tag); |
There was a problem hiding this comment.
Catch rejected follow mutations
When either favorite-tag request fails because of a network error or non-2xx response, mutateAsync rejects and this async toggle propagates that rejection. Its callers either return the promise from onClick or discard it with void toggle(), neither of which handles the rejection, so an error that already produced the configured toast also becomes an unhandled promise rejection. Catch the failure here or use the non-promise mutate API.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 0bd0f40, together with Qodo's same finding: toggle catches the rejection and the spec asserts no unhandled rejection surfaces.
| {/* Personal feed (/@user/feed) is where new users land after login; | ||
| the card self-gates to fresh accounts and renders nothing otherwise. */} | ||
| {filter === "feed" && <WavesOnboardingChecklist />} | ||
| {showTagHeader && <TagFeedHeader tag={tag} />} |
There was a problem hiding this comment.
Render the tag header on archive pages
For a URL such as /created/photography?before=..., the cursor branch returns at line 98 before this header is reached, so visitors following the newly exposed Older links lose both the tag heading and the follow control. Include TagFeedHeader in the archive rendering path as well so the follow surface remains available throughout the tag feed.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 0bd0f40. The header decision is made before the cursor branch and the archive page renders TagFeedHeader above its list as well.
…share pending state Review round 1. The plain list endpoint answers its default page of 20, so a user past that saw the 21st tag as unfollowed; the hook and the Topics card now read the paginated endpoint as one page at the 100-tag cap. A list that failed to load is asked again before a toggle acts on it, pending state is shared across every control for the user on the page through useIsMutating, and a rejected mutation is caught since the hook already toasts it. The Tags tab shows a failed request as an error with a retry rather than an empty list, and the tag feed header renders on archive pages too.
…token, stop the Tags tab spinner Review round 2. After an add the SDK invalidates the followed list, and cached data keeps isPending false during that refetch, so a control read "unfollowed" with an enabled button and took a second add; isFetching now counts as in progress. A signed-in account without an access token is a supported state the favorite button already renders disabled for, so the chip toggle exposes aria-disabled and stops accepting activation instead of looking enabled and ignoring it. The Tags tab reads isLoading rather than isPending, since a disabled query with nothing cached stays pending forever.
The hook's onError already reports a failed unfollow; the ignored rejected promise from mutateAsync would still reach the global error reporter.
While the followed list loads or refetches, or a mutation is in flight, the chip looked enabled and dropped the activation. It now carries aria-disabled with a wait cursor for that state, keeping focus so a control the user just activated does not lose it; without a token it stays unfocusable as before.
First half of #1712: the follow surfaces. The notification type (
tags, main type 23) and its settings toggle follow in a second PR so this one stays reviewable. Uses@ecency/sdk2.3.96 (#1714); backend routes are live.What changes
features/shared/follow-tag-btn:useFollowTag(tag)derives followed state from the user's followed list (one cached request, however many chips are on the page) and exposes the add/remove toggle. Two controls on top of it:FollowTagBtn: Follow / Following button.FollowTagChipToggle: the small plus / check at the trailing edge of a tag chip. It sits inside the chip's link and stops the click before the link navigates, the same way the Topics card's dismiss control does.LoginRequired promptOnAnon). Both render nothing for a community or a value the tag rule refuses.entry-tags.tsx): the toggle on every plain tag chip; the community chip is unchanged.feed/_components/tag-feed-header.tsx):#tagand a Follow button above a plain tag's feed. Shown for trending, hot and created on a queryable non-community tag, never formy.FavoriteTagsList,FavoriteTagItem) with unfollow, andinitialTab="tags".follow-tag.*andfavorite-tags.*.Tests
specs/features/shared/follow-tag-btn.spec.tsx: follow and unfollow in normalised form, the signed-out path never reaching the API, nothing rendered for a community tag, the chip toggle not letting the click reach its link, keyboard activation.specs/app/trending-tags-card.spec.tsx: pinned-first ordering with no duplicates and toggles only when signed in.specs/features/shared/bookmarks.spec.tsx: the Tags tab, by click and byinitialTab.38 tests green across the touched specs plus the i18n duplicate-key guard; typecheck, lint and the icon, SCSS and slim-entries audits clean.
Part of #1712