fix(accounts): adapt 5chan to compact account history hooks#1118
fix(accounts): adapt 5chan to compact account history hooks#1118tomcasaburi merged 3 commits intomasterfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThis PR migrates account-comment lookups to guarded, queryable patterns: introduces Changes
Sequence Diagram(s)sequenceDiagram
participant Component
participant useSafeAccountComment
participant useAccount
participant useAccountComment
participant Fallback as AuthorCheck
rect rgba(100,150,200,0.5)
Note over Component,useSafeAccountComment: Safe account-comment lookup flow
Component->>useSafeAccountComment: call({ commentIndex? / commentCid? })
useSafeAccountComment->>useAccount: get account
alt valid commentIndex
useSafeAccountComment->>useAccountComment: call({ commentIndex: normalized })
useAccountComment-->>useSafeAccountComment: account comment | empty
else commentCid && account exists
useSafeAccountComment->>useAccountComment: call({ commentCid })
useAccountComment-->>useSafeAccountComment: account comment | empty
else no valid input/account
useSafeAccountComment->>useAccountComment: call({ commentIndex: -1 })
useAccountComment-->>useSafeAccountComment: sentinel empty
end
useSafeAccountComment-->>Component: return result
end
sequenceDiagram
participant QuoteComponent
participant useSafeAccountComment
participant useAccount
participant Fallback as AuthorCheck
rect rgba(200,150,100,0.5)
Note over QuoteComponent,useSafeAccountComment: Quote-preview ownership check
QuoteComponent->>useSafeAccountComment: lookup by quotelink.cid
useSafeAccountComment->>useAccount: get account
useSafeAccountComment->>useSafeAccountComment: attempt CID lookup (delegates to useAccountComment)
alt found matching account comment
useSafeAccountComment-->>QuoteComponent: isOwn = true
else not found
QuoteComponent->>Fallback: compare quotelink.author.address vs useAccount().author.address
Fallback-->>QuoteComponent: isOwn = result
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
📝 Coding Plan
Comment Tip CodeRabbit can generate a title for your PR based on the changes with custom instructions.Set the |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
src/views/catalog/catalog.tsx (1)
286-297: Consider extracting the recent-account injection logic into a shared hook.This scoped lookup/filter block now matches
src/views/board/board.tsxalmost line-for-line. Pulling it intosrc/hooks/would keep the sentinel lookup, one-hour window, and post-only filter from drifting between the two views.As per coding guidelines, "Avoid copy-paste logic across components. Extract custom hooks in
src/hooks/."Also applies to: 303-331
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/views/catalog/catalog.tsx` around lines 286 - 297, The recent-account lookup/filter (accountCommentLookupOptions + useAccountComments usage) is duplicated with board.tsx; extract this logic into a shared hook (e.g., useRecentAccountComments) under src/hooks/ that encapsulates the sentinel lookup, RECENT_ACCOUNT_COMMENT_WINDOW_SECONDS, post-only filtering and returns the same shape used now (e.g., { accountComments }). Replace the inline accountCommentLookupOptions and direct useAccountComments calls in catalog.tsx (and board.tsx) with the new hook, reusing EMPTY_ACCOUNT_COMMENT_LOOKUP and useAccountComments inside the hook to preserve behavior and dependencies (communityAddress).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.cursor/agents/plan-implementer.md:
- Line 3: Update the Codex agent configuration so the model value matches the
Cursor change: open plan-implementer.toml and replace the existing model =
"gpt-5.3-codex" entry with model = "composer-2" (preserve TOML formatting and
quoting). Ensure there are no duplicate model keys and save the file so both
agent toolchains use the same model name.
In `@src/components/reply-quote-preview/reply-quote-preview.tsx`:
- Around line 84-89: The ownership check in useIsOwnQuotelink is too permissive;
change the logic to require an exact cid match first (ownQuotelink?.cid ===
quotelinkReply?.cid) and only fall back to comparing author addresses when BOTH
addresses are present (ownQuotelink?.author?.address &&
quotelinkReply?.author?.address) before checking equality; reference the
useIsOwnQuotelink function and the quotelinkReply, ownQuotelink, and account
symbols when making this change.
In `@src/views/catalog/catalog.tsx`:
- Around line 443-453: The rows useMemo can hang when columnCount is 0; before
chunking processedFeed in the loop inside the rows useMemo (which uses
columnCount, isFeedLoaded, processedFeed), clamp the step to at least 1 (e.g.,
const step = Math.max(1, columnCount)) and use that step in the for loop and
slice calls so you never do i += 0 and the render cannot enter an infinite loop.
In `@src/views/pending-post/pending-post.tsx`:
- Around line 12-13: Pass the raw accountCommentIndex string directly into
useSafeAccountComment instead of parsing it—remove the parseInt usage that sets
commentIndex and instead forward accountCommentIndex to useSafeAccountComment
(the hook accepts both string and number and performs strict normalization);
additionally, update the hook's boundary check from allowing indices <=
accountComments.length to strictly < accountComments.length so out-of-range
(equal-to-length) indices are rejected.
---
Nitpick comments:
In `@src/views/catalog/catalog.tsx`:
- Around line 286-297: The recent-account lookup/filter
(accountCommentLookupOptions + useAccountComments usage) is duplicated with
board.tsx; extract this logic into a shared hook (e.g.,
useRecentAccountComments) under src/hooks/ that encapsulates the sentinel
lookup, RECENT_ACCOUNT_COMMENT_WINDOW_SECONDS, post-only filtering and returns
the same shape used now (e.g., { accountComments }). Replace the inline
accountCommentLookupOptions and direct useAccountComments calls in catalog.tsx
(and board.tsx) with the new hook, reusing EMPTY_ACCOUNT_COMMENT_LOOKUP and
useAccountComments inside the hook to preserve behavior and dependencies
(communityAddress).
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: cc5ee1ed-97b9-44e2-9fd4-d9b83490a251
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (30)
.cursor/agents/browser-check.md.cursor/agents/code-quality.md.cursor/agents/plan-implementer.md.cursor/agents/react-doctor-fixer.md.cursor/agents/react-patterns-enforcer.md.cursor/agents/translator.mdpackage.jsonsrc/app.tsxsrc/components/board-buttons/__tests__/board-buttons.test.tsxsrc/components/board-buttons/board-buttons.tsxsrc/components/board-header/__tests__/board-header.test.tsxsrc/components/board-header/board-header.tsxsrc/components/boards-bar/__tests__/boards-bar.test.tsxsrc/components/boards-bar/boards-bar.tsxsrc/components/post-desktop/post-desktop.tsxsrc/components/post-form/post-form.tsxsrc/components/post-mobile/post-mobile.tsxsrc/components/reply-quote-preview/__tests__/reply-quote-preview.test.tsxsrc/components/reply-quote-preview/reply-quote-preview.tsxsrc/hooks/__tests__/use-fresh-replies.test.tsxsrc/hooks/__tests__/use-safe-account-comment.test.tsxsrc/hooks/use-fresh-replies.tssrc/hooks/use-safe-account-comment.tssrc/hooks/use-theme.tssrc/views/board/__tests__/board.test.tsxsrc/views/board/board.tsxsrc/views/catalog/__tests__/catalog.test.tsxsrc/views/catalog/catalog.tsxsrc/views/pending-post/__tests__/pending-post.test.tsxsrc/views/pending-post/pending-post.tsx
| --- | ||
| name: plan-implementer | ||
| model: composer-1.5 | ||
| model: composer-2 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Read-only verification for model/config consistency across Cursor and Codex surfaces.
set -euo pipefail
echo "== Agent files still on composer-1.5 (if any) =="
rg -n --glob '.cursor/agents/**' --glob '.codex/agents/**' '^\s*model:\s*composer-1\.5\s*$' || true
echo
echo "== Agent files on composer-2 =="
rg -n --glob '.cursor/agents/**' --glob '.codex/agents/**' '^\s*model:\s*composer-2\s*$' || true
echo
echo "== Entry points referencing model/agent orchestration =="
fd 'config\.toml$|hooks\.json$' .codex .cursor 2>/dev/null | xargs -r -I{} sh -c 'echo "--- {}"; rg -n "composer|agent|hook|model" "{}" || true'Repository: bitsocialnet/5chan
Length of output: 2364
🏁 Script executed:
#!/bin/bash
echo "=== Finding all agent files ==="
fd . .cursor/agents .codex/agents 2>/dev/null | sort
echo
echo "=== Checking plan-implementer files ==="
fd 'plan-implementer' .cursor .codex 2>/dev/null
echo
echo "=== Content of .cursor/agents/plan-implementer.md (if exists) ==="
if [ -f ".cursor/agents/plan-implementer.md" ]; then
cat -n ".cursor/agents/plan-implementer.md"
fi
echo
echo "=== Content of .codex/agents/plan-implementer.toml (if exists) ==="
if [ -f ".codex/agents/plan-implementer.toml" ]; then
cat -n ".codex/agents/plan-implementer.toml"
fi
echo
echo "=== All model specifications in cursor and codex agent files ==="
rg -n 'model\s*[:=]' .cursor/agents/ .codex/agents/ 2>/dev/null || trueRepository: bitsocialnet/5chan
Length of output: 5439
Update .codex/agents/plan-implementer.toml to match the model change in .cursor/agents/plan-implementer.md.
The .cursor/ agent was updated to composer-2, but .codex/agents/plan-implementer.toml still specifies model = "gpt-5.3-codex". Both toolchain implementations must use the same model to avoid split behavior. Update the Codex side to align with the Cursor change.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.cursor/agents/plan-implementer.md at line 3, Update the Codex agent
configuration so the model value matches the Cursor change: open
plan-implementer.toml and replace the existing model = "gpt-5.3-codex" entry
with model = "composer-2" (preserve TOML formatting and quoting). Ensure there
are no duplicate model keys and save the file so both agent toolchains use the
same model name.
|
Addressed the valid review findings in Fixed:
Declined:
Local verification after the fixes:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/views/pending-post/pending-post.tsx`:
- Around line 20-25: The validation currently treats an empty accountComments
array as "OK" which lets any non‑negative index pass; change the logic in
isValidAccountCommentIndex to only allow the escape when the account comments
are truly not yet loaded (e.g., accountComments == null/undefined) instead of
when accountComments.length === 0. Specifically, update the condition that
references accountComments?.length === 0 so it checks for an explicit "not
ready" state (accountComments == null) and otherwise enforce
normalizedAccountCommentIndex < accountComments.length; keep the other checks
(accountCommentIndex falsy, hasNormalizedAccountCommentIndex, Number.isInteger)
unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6be25f90-c63d-4c2f-b1d2-63af214610b8
📒 Files selected for processing (8)
src/components/reply-quote-preview/__tests__/reply-quote-preview.test.tsxsrc/components/reply-quote-preview/reply-quote-preview.tsxsrc/hooks/__tests__/use-safe-account-comment.test.tsxsrc/hooks/use-catalog-feed-rows.tssrc/views/catalog/__tests__/catalog.test.tsxsrc/views/catalog/catalog.tsxsrc/views/pending-post/__tests__/pending-post.test.tsxsrc/views/pending-post/pending-post.tsx
💤 Files with no reviewable changes (1)
- src/hooks/use-catalog-feed-rows.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- src/components/reply-quote-preview/tests/reply-quote-preview.test.tsx
- src/components/reply-quote-preview/reply-quote-preview.tsx
- src/views/pending-post/tests/pending-post.test.tsx
- src/views/catalog/catalog.tsx
- src/views/catalog/tests/catalog.test.tsx
| const isValidAccountCommentIndex = | ||
| !accountCommentIndex || | ||
| (!isNaN(parseInt(accountCommentIndex)) && | ||
| parseInt(accountCommentIndex) >= 0 && | ||
| Number.isInteger(parseFloat(accountCommentIndex)) && | ||
| (accountComments?.length === 0 || parseInt(accountCommentIndex) <= accountComments.length)); | ||
| (hasNormalizedAccountCommentIndex && | ||
| normalizedAccountCommentIndex >= 0 && | ||
| Number.isInteger(normalizedAccountCommentIndex) && | ||
| (accountComments?.length === 0 || normalizedAccountCommentIndex < accountComments.length)); |
There was a problem hiding this comment.
An empty history still bypasses the out-of-range check.
Line 25 makes every non-negative integer valid whenever accountComments.length === 0, so a loaded account with no comments will never send /pending-post/0 or /pending-post/999 to /not-found. Please gate that escape hatch on an explicit “account not ready” condition instead of the array being empty.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/views/pending-post/pending-post.tsx` around lines 20 - 25, The validation
currently treats an empty accountComments array as "OK" which lets any
non‑negative index pass; change the logic in isValidAccountCommentIndex to only
allow the escape when the account comments are truly not yet loaded (e.g.,
accountComments == null/undefined) instead of when accountComments.length === 0.
Specifically, update the condition that references accountComments?.length === 0
so it checks for an explicit "not ready" state (accountComments == null) and
otherwise enforce normalizedAccountCommentIndex < accountComments.length; keep
the other checks (accountCommentIndex falsy, hasNormalizedAccountCommentIndex,
Number.isInteger) unchanged.

Adapt 5chan to the newer compact account-history hooks without changing user-visible behavior.
(You), fresh replies, and recent local post injection onto narrower account-history lookupsCloses #1117
Note
Medium Risk
Touches many routes/components that read account comment history and changes how/when lookups are issued; mistakes could cause missing pending posts, incorrect “(You)” labels, or feed injection regressions. Scope is broad but largely refactors around safer parsing and narrower queries rather than new behavior.
Overview
Adapts account-history usage to the updated
@bitsocialnet/bitsocial-react-hooksrevision by introducinguseSafeAccountCommentand replacing directuseAccountCommentcalls across app layout, headers, boards bar, post views, and forms to avoid invalid indices/CID lookups before account data is ready.Scopes account-history queries to reduce work:
Board/Catalognow request only recent community-specific account posts for local feed injection, anduseFreshRepliesrequests only indexed account comments;ReplyQuotePreviewnow determines “(You)” via a direct account-comment CID lookup before falling back to author-address matching.Removes
useCatalogFeedRowsin favor of inline row chunking with a safe minimum column count, tightens/pending/:accountCommentIndexvalidation, and adds/updates regression tests to cover the new lookup paths. Also bumps Cursor agent configs tocomposer-2.Written by Cursor Bugbot for commit a4af5b6. This will update automatically on new commits. Configure here.
Summary by CodeRabbit
Bug Fixes
Performance
Refactor
Chores
Tests