Skip to content

feat(player): show Bangumi episode comments - #68

Merged
ModerRAS merged 2 commits into
masterfrom
codex/feat-bangumi-episode-comments
Aug 13, 2026
Merged

feat(player): show Bangumi episode comments#68
ModerRAS merged 2 commits into
masterfrom
codex/feat-bangumi-episode-comments

Conversation

@ModerRAS

@ModerRAS ModerRAS commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • add an on-demand Bangumi episode comments panel to the TV player
  • preserve top-level comments and replies, rich text, inline emoticons, images, and masked spoiler content
  • cache comments per playback session with TV-friendly focus, retry, local pagination, and back handling

Implementation

  • resolve comments from the public Bangumi episode page because the public v0 API does not expose episode comments
  • parse the rendered HTML with Jsoup into a strict content model instead of rendering arbitrary HTML
  • reject private/local comment image targets and surface unsupported markup as an explicit panel error
  • bump the release baseline from 2.8.0 to 2.9.0 for this user-visible feature

Verification

  • ./gradlew test lint :app:assembleDebug (1160 tasks, successful)
  • ./gradlew :scraper-core:test :ui-tv:testDebugUnitTest :ui-tv:lint :app:assembleDebug
  • git diff --check
  • installed with adb install -r; verified DPAD focus reaches Comments, error/retry focus, panel back handling, and no crash without clearing app data

Summary by CodeRabbit

  • New Features

    • Added episode comments to the TV player.
    • View formatted comments, images, spoilers, user details, timestamps, and nested replies.
    • Added loading, retry, pagination, empty-state, and TV remote focus support.
    • Comments are retrieved anonymously from episode pages.
    • Updated the app version to 2.9.0.
  • Security

    • Restricted comment images to safe, publicly accessible HTTP(S) addresses.
  • Tests

    • Added coverage for comment retrieval, parsing, pagination behavior, formatting, and image URL validation.

@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ModerRAS, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 94 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f812bf2f-35d1-4ac2-a204-165d852359b9

📥 Commits

Reviewing files that changed from the base of the PR and between 2427d6e and de2f058.

📒 Files selected for processing (6)
  • app/build.gradle.kts
  • gradle/libs.versions.toml
  • ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/BangumiCommentsPanel.kt
  • ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/PlayerViewModel.kt
  • ui-tv/src/test/kotlin/com/miruplay/tv/ui/player/BangumiCommentsPanelTest.kt
  • ui-tv/src/test/kotlin/com/miruplay/tv/ui/player/PlayerTimelineFocusTest.kt
📝 Walkthrough

Walkthrough

Adds Bangumi episode comment models, HTML retrieval and parsing, scraper and dependency-injection wiring, paginated playback state, and a TV comments panel with focus navigation, spoilers, images, retries, and pagination.

Changes

Bangumi episode comments

Layer / File(s) Summary
Comment contract and dependency setup
app/build.gradle.kts, gradle/libs.versions.toml, repository-api/..., scraper-core/build.gradle.kts
Adds comment models and the retrieval service contract. Adds Jsoup and updates the app version to 2.9.0.
Episode retrieval and HTML parsing
scraper-core/src/main/..., scraper-core/src/test/...
Fetches Bangumi episode HTML and parses nested comments, rich text, spoilers, images, users, timestamps, and normalized URLs. Tests cover supported and rejected markup.
Scraper wiring and playback state
scraper/src/main/..., ui-tv/src/main/.../PlayerViewModel.kt
Exposes the comments service through Hilt. Adds paginated comment loading, caching, error handling, and stale-playback request protection.
TV comments panel and player integration
ui-tv/src/main/.../BangumiCommentsPanel.kt, ui-tv/src/main/.../PlayerScreen.kt, ui-tv/src/test/...
Adds the comments overlay, remote focus navigation, spoiler activation, safe image URL validation, timestamps, retries, pagination, and focus-test updates.

Estimated code review effort: 4 (Complex) | ~60 minutes

Mergeability Score: 🟡 Moderate · up to 2427d

The comments panel can still accept IPv4-mapped addresses that reach loopback or private hosts, and an older request can overwrite state for a newer playback session. These can expose local network targets or show stale panel state, so the PR is not merge-ready until the security and session-state issues are fixed; runtime compatibility and focus behavior also need owner follow-up.

Sequence Diagram(s)

sequenceDiagram
  participant Viewer
  participant PlayerScreen
  participant PlayerViewModel
  participant BangumiScraper
  participant BangumiApiClient
  participant BangumiCommentsPanel
  Viewer->>PlayerScreen: Open comments
  PlayerScreen->>PlayerViewModel: loadEpisodeComments()
  PlayerViewModel->>BangumiScraper: getEpisodeComments(episodeId)
  BangumiScraper->>BangumiApiClient: Fetch episode comments
  BangumiApiClient-->>PlayerViewModel: Parsed comment Result
  PlayerViewModel-->>BangumiCommentsPanel: EpisodeCommentsUiState
  BangumiCommentsPanel-->>Viewer: Render comments and pagination
Loading

Possibly related PRs

  • ModerRAS/MiruPlay#52: Both changes update the app version in app/build.gradle.kts; their feature changes are unrelated.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding Bangumi episode comments to the player.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/feat-bangumi-episode-comments

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
ui-tv/src/test/kotlin/com/miruplay/tv/ui/player/PlayerTimelineFocusTest.kt (1)

63-83: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Test the comments fallback branch.

This test provides one audio track, so focus moves to the audio action. It does not execute the new fallback at PlayerScreen.kt Line 1141. Add a case with empty audio and subtitle lists, then assert that the “评论” action receives focus after pressing Down.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ui-tv/src/test/kotlin/com/miruplay/tv/ui/player/PlayerTimelineFocusTest.kt`
around lines 63 - 83, The PlayerTimelineFocusTest currently exercises audio
focus instead of the comments fallback. Add a test case using empty audioTracks
and subtitles, trigger the Down navigation from the timeline, and assert that
the “评论” action receives focus while preserving the existing test behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gradle/libs.versions.toml`:
- Line 31: Update the Android app module configuration to enable core-library
desugaring and add the required NIO desugared library dependency for Jsoup
1.23.1. Configure the desugaring dependency using the existing version-catalog
Jsoup setup, ensuring the app packaging scraper-core can compile and run with
the required APIs.

In `@ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/BangumiCommentsPanel.kt`:
- Around line 66-69: Update the LaunchedEffect in BangumiCommentsPanel so its
keys use state.comments.isNotEmpty() and state.errorMessage instead of the
complete state.comments list, preserving the existing focus request condition
for initial content and errors while preventing pagination appends from
resetting focus.
- Around line 287-312: Update safeBangumiCommentImageUrl to detect IPv4-mapped
IPv6 hosts, normalize the embedded IPv4 address, and run it through the existing
IPv4 local-target checks so mapped loopback, private, link-local, and
unspecified addresses are rejected. Preserve current handling for other IPv6 and
hostname inputs, and add corresponding cases to BangumiCommentsPanelTest.

In `@ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/PlayerViewModel.kt`:
- Around line 253-263: In the comment-loading coroutine around getCachedEpisode
and the _episodeComments updates, re-check that the source remains active and
episodeCommentsGeneration is still current immediately after the metadata
lookup. Return without updating state when either guard fails, before applying
the missing-Bangumi error or isLoading=true.

---

Nitpick comments:
In `@ui-tv/src/test/kotlin/com/miruplay/tv/ui/player/PlayerTimelineFocusTest.kt`:
- Around line 63-83: The PlayerTimelineFocusTest currently exercises audio focus
instead of the comments fallback. Add a test case using empty audioTracks and
subtitles, trigger the Down navigation from the timeline, and assert that the
“评论” action receives focus while preserving the existing test behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c92e3cb-fd0d-405a-a7d3-12e66432ec90

📥 Commits

Reviewing files that changed from the base of the PR and between aa45a56 and 2427d6e.

📒 Files selected for processing (15)
  • app/build.gradle.kts
  • gradle/libs.versions.toml
  • repository-api/src/main/kotlin/com/miruplay/tv/repository/BangumiEpisodeComments.kt
  • scraper-core/build.gradle.kts
  • scraper-core/src/main/kotlin/com/miruplay/tv/scraper/core/BangumiApiClient.kt
  • scraper-core/src/main/kotlin/com/miruplay/tv/scraper/core/BangumiEpisodeCommentHtmlParser.kt
  • scraper-core/src/test/kotlin/com/miruplay/tv/scraper/core/BangumiApiClientTest.kt
  • scraper-core/src/test/kotlin/com/miruplay/tv/scraper/core/BangumiEpisodeCommentHtmlParserTest.kt
  • scraper/src/main/kotlin/com/miruplay/tv/scraper/BangumiScraper.kt
  • scraper/src/main/kotlin/com/miruplay/tv/scraper/di/ScraperModule.kt
  • ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/BangumiCommentsPanel.kt
  • ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/PlayerScreen.kt
  • ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/PlayerViewModel.kt
  • ui-tv/src/test/kotlin/com/miruplay/tv/ui/player/BangumiCommentsPanelTest.kt
  • ui-tv/src/test/kotlin/com/miruplay/tv/ui/player/PlayerTimelineFocusTest.kt

Comment thread gradle/libs.versions.toml
Comment thread ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/BangumiCommentsPanel.kt Outdated
Comment thread ui-tv/src/main/kotlin/com/miruplay/tv/ui/player/PlayerViewModel.kt
@ModerRAS
ModerRAS merged commit 9494afd into master Aug 13, 2026
13 checks passed
@ModerRAS
ModerRAS deleted the codex/feat-bangumi-episode-comments branch August 13, 2026 04:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant