Take the content moderation rules from the SDK - #3503
Conversation
The app carried its own copy of the rules deciding when content is dimmed, and it had drifted from the website: downvoted meant -7B rshares and 4 voters here against -10B and 5 there, every author under reputation 25 was dimmed no matter what they wrote, and the low-trust check did not exist at all. Low reputation was also checked before downvotes, so a heavily downvoted post read "low reputation account" here and "Downvoted by users" on the website. Downvotes sink reputation, so that mislabelled the common case. parsePost and parseComment now call getContentModerationReason from the SDK, and the local thresholds are gone. MutedReason becomes the SDK enum under the same local name, so components keep reading one mobile-side symbol. The feed's own mute filter calls the shared isAuthorMuted, and the website now drops muted authors from lists the same way instead of dimming them. Two visible changes: low reputation on its own no longer dims anything, it needs an outbound promotional link too, and heavily downvoted content is flagged as downvoted rather than as a low reputation account. Reasons written by older app versions are kept in LegacyMutedReason so cached posts keep their copy until the cache turns over. The rule tests moved to the SDK next to the implementation.
Code Review by Qodo
1. Author check ordered wrongly
|
PR Summary by QodoUse SDK content moderation rules for consistent dimming and mute reasons
AI Description
Diagram
High-Level Assessment
Files changed (7)
|
Code Review by Qodo
1. Author check ordered wrongly
|
| // Authors the viewer muted are dropped from the list rather than dimmed, and the | ||
| // website now does the same. Shared helper so both stay on one definition. | ||
| _data = _data.filter((item) => !isAuthorMuted(item.author, mutes) && !!item?.author); |
There was a problem hiding this comment.
1. Author check ordered wrongly 🐞 Bug ☼ Reliability
postsListContainer calls isAuthorMuted(item.author, mutes) before verifying item.author exists, so entries with a missing/empty author will still invoke the SDK helper. If isAuthorMuted assumes a non-empty string, this can throw or misclassify items before they’re filtered out, breaking feed rendering.
Agent Prompt
### Issue description
`isAuthorMuted(item.author, mutes)` is evaluated before `!!item?.author`, so the helper is invoked with a potentially missing/empty author.
### Issue Context
This affects both the main `_data` filter and the promoted-posts filter.
### Fix Focus Areas
- src/components/postsList/container/postsListContainer.tsx[109-121]
### Suggested change
Reorder the predicate so author validation happens first:
- `_data = _data.filter((item) => !!item?.author && !isAuthorMuted(item.author, mutes));`
- Apply the same ordering in the `_promotedPosts` filter.
If `isAuthorMuted` accepts only strings, consider normalizing: `const author = item?.author ?? "";` and keep the explicit `!!author` guard before calling the helper.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
Half right, and worth fixing, though not for the stated reason. isAuthorMuted is null-safe on its own:
return !!author && !!mutedAuthors?.includes(author);so an entry with a missing or empty author cannot throw there or be misclassified; it returns false and the !!item?.author check then drops the item.
What is real is the ordering: item.author is dereferenced twice before the ?. that exists to tolerate a nullish item, so a null entry would take the feed down at the dereference rather than being filtered out. That predates this PR (the previous line was !isMuted && !!item?.author), but it reads as the opposite of what the code means.
Fixed in #3504, guard first in both the main filter and the promoted one.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9f856b9a18
ℹ️ 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".
| import { get } from 'lodash'; | ||
| import { Platform } from 'react-native'; | ||
| import { postBodySummary, renderPostBody, catchPostImage } from '@ecency/render-helper'; | ||
| import { getContentModerationReason } from '@ecency/sdk'; |
There was a problem hiding this comment.
Bump the SDK before importing the moderation API
Every clean install remains locked to @ecency/sdk 2.3.86, which exports none of getContentModerationReason, isAuthorMuted, or ContentModerationReason; consequently yarn typecheck reports TS2305 at all three new imports and the app cannot build. Update package.json and yarn.lock to the SDK release containing these APIs as part of this change.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Right, and resolved in 32e2e6e before merge: @ecency/sdk 2.3.87 (published from ecency/vision-web#1493 under the patch:sdk label) is now pinned in both package.json and yarn.lock. The PR was open as a draft precisely because the SDK release did not exist yet.
The module the parser now calls landed in 2.3.87. Dependencies are unchanged between 2.3.86 and 2.3.87, so the lockfile entry only moves version, resolved and integrity; verified against the published tarball, whose sha1 matches the resolved hash.
|
Unblocked and ready for review. @ecency/sdk 2.3.87 is on npm (ecency/vision-web#1493 merged with the Dependencies are identical between 2.3.86 and 2.3.87, so the yarn.lock entry only moves version, resolved and integrity. I verified that against the published tarball rather than trusting the edit: its sha1 is Re-verified with the published package rather than my local build of it: 872 unit tests pass, Still not verified on a device. Merged is not shipped here, this needs a build before anyone can see it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe parser now uses the SDK moderation helper for posts and comments. The type layer preserves legacy reasons. Muted-post messaging includes low-trust content. Post lists use shared author-mute checks. Tests cover updated moderation and downvote conditions. ChangesModeration reason alignment
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: 🟡 Moderate · up to The PR now relies on a moderation API that is not yet available in the published SDK, leaving the current dependency state unable to pass CI. It is not merge-ready until the SDK is published and the dependency and lockfile are updated. Sequence Diagram(s)sequenceDiagram
participant PostParser
participant ModerationSDK
participant PostCard
PostParser->>ModerationSDK: getContentModerationReason(post)
ModerationSDK-->>PostParser: mutedReason
PostParser->>PostCard: provide parsed post
PostCard->>PostCard: select muted message
Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
Code review by qodo was updated up to the latest commit 9f856b9 |
Closes #3502. Consumer side of ecency/vision-web#1492.
Draft: blocked on the SDK publish. The code calls
getContentModerationReasonfrom@ecency/sdk, which does not exist in a published version yet. Once ecency/vision-web#1493 is labelledpatch:sdk, merged and published, this needs one more commit bumping the dependency andyarn.lock. CI installs from the lockfile, so it stays red until then. Verified locally against a build of the web PR's SDK: 872 unit tests,yarn typecheckclean, lint clean.The app carried its own copy of the rules and it had drifted from the website:
net_rshares < -7Band> 3voters< -10Band>= 5votersThe old precedence was the worst of it: downvotes sink an author's reputation, so a heavily downvoted post read "Content from a low reputation account" here and "Downvoted by users" on the website.
Changes
parsePostandparseCommentcallgetContentModerationReason; the local thresholds andgetMutedReasonare goneMutedReasonis now the SDK'sContentModerationReasonre-exported under the same local name, so components keep reading one mobile-side symbolpost.muted_low_truststring for the low-trust caseLegacyMutedReason, so posts already in the persisted query cache keep their copy instead of falling back to the generic message until the cache turns overisAuthorMuted. Behaviour is unchanged here, the website moves to match itWorth knowing
Low-trust detection scans the post body for outbound links, which is new work in
parsePost. For lists the body is raw markdown, for a single post it has already been throughrenderPostBody, and the check matches links in both.Not verified on a device yet.
Summary by CodeRabbit