Skip to content

feat(tv): improve Shield setup, controls, and subtitle switching - #159

Merged
RXWatcher merged 29 commits into
Silo-Server:mainfrom
RXWatcher:feature/shield-playback-and-instant-srt
Aug 2, 2026
Merged

feat(tv): improve Shield setup, controls, and subtitle switching#159
RXWatcher merged 29 commits into
Silo-Server:mainfrom
RXWatcher:feature/shield-playback-and-instant-srt

Conversation

@RXWatcher

@RXWatcher RXWatcher commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Improves the Android TV/Shield setup and playback experience, culminating in instant switching between negotiated external SRT/VTT subtitles.

Companion server PR: Silo-Server/silo-server#532

What changed

  • Keep server/auth fields visible above the stock Android TV IME.
  • Repair the phone-pairing card and constrain pairing codes to eight characters.
  • Make D-pad down focus the playback transport controls and improve their readability.
  • Close the HUD after quick subtitle selection and use more readable subtitle size steps.
  • Switch already-mounted external text subtitles locally without rebuffering.
  • Decode and negotiate the additive server sidecar set while remaining compatible with unchanged servers.
  • Preserve the existing staged-replan fallback for old-server/catalog-only subtitle rows at the current position, audio track, and quality.
  • Prevent local SRT overlays on burn-in routes by requiring a safe replacement plan first.
  • Keep Cast excluded from the new local-sidecar capability.

Compatibility

The Android build works unchanged without server PR #532. If sidecars is absent, it decodes as an empty list and uses the existing subtitle artifact/replan flow. Instant switching activates only when the updated server explicitly negotiates the feature.

Testing

  • ./gradlew test — PASS (257 actionable tasks)
  • ./gradlew :androidTvApp:assembleDebug — PASS
  • Focused playback mapper and TV subtitle transaction suites — PASS
  • git diff --check — PASS
  • Independent adversarial re-review — no remaining Critical or Important issues
  • ARM64 debug APK installed on NVIDIA Shield as v0.3.11 (versionCode=15), manually reviewed, then force-stopped; it was not launched after the final install

AI disclosure

  • Tool: OpenAI Codex
  • Model: GPT-5
  • Involvement: design, implementation, tests, device build/install, verification, and adversarial review coordination

Summary by CodeRabbit

  • New Features

    • Added support for compatible external SRT/VTT subtitle tracks during playback.
    • TV subtitles now use clearer, fixed-size presets.
    • Added faster switching for already-mounted TV subtitle tracks.
    • TV authentication fields now remain visible when the on-screen keyboard appears.
    • Improved match-code layout for longer codes.
  • Bug Fixes

    • D-pad Down now consistently focuses playback controls.
    • Subtitle picker selection and Back dismissal now behave distinctly.
    • Improved subtitle mounting, fallback, and rollback handling.
    • Increased TV playback control accessibility and sizing.

@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

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

Next review available in: 38 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 966b6030-833b-4c2f-bbed-af782bef5ccb

📥 Commits

Reviewing files that changed from the base of the PR and between 3041b94 and a6f43e8.

📒 Files selected for processing (4)
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/auth/TvServerSetupScreen.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerRemoteKeyAction.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerRemoteKeyActionTest.kt
  • docs/superpowers/specs/2026-08-02-tv-player-transport-accessibility-design.md
📝 Walkthrough

Walkthrough

Changes

The PR adds external subtitle sidecar negotiation and mounting for local Media3 playback, with Cast exclusion and protocol compatibility coverage. It adds fixed TV subtitle sizing, shared Android TV IME-aware form scrolling, responsive login match-code sizing, subtitle-picker exit handling, transport accessibility updates, and mounted-sidecar transaction coverage.

Playback subtitle capabilities

Layer / File(s) Summary
Protocol and sidecar negotiation
shared/src/.../PlaybackProtocolV3.kt, android-shared/src/.../PlaybackCapabilityDetector.kt, android-shared/src/.../PlaybackSessionManager.kt, android-shared/src/.../*Test.kt
V3 playback supports external sidecar metadata. Local Media3 playback advertises the feature. Cast playback does not.
Sidecar mounting and validation
android-shared/src/.../PlaybackV3Session.kt, android-shared/src/.../PlaybackV3SessionTest.kt
Valid SRT, SubRip, and WebVTT sidecars are mounted, deduplicated, and excluded for burn-in mode.
Platform-specific subtitle sizing
android-shared/src/.../AndroidSubtitleTextSizePolicy.kt, android-shared/src/.../SubtitleManager.kt, android-shared/src/.../*Subtitle*Test.kt
Phone subtitles use fractional sizing. TV subtitles use fixed SP presets.

Android TV IME-aware forms

Layer / File(s) Summary
Shared IME relocation
androidTvApp/src/androidMain/.../TvImeAwareForm.kt, androidTvApp/src/androidUnitTest/.../TvImeAwareFormTest.kt
Focused, measured fields relocate when the IME is visible. Form scroll restores when the IME closes.
Authentication form integration
androidTvApp/src/androidMain/.../auth/*.kt, androidTvApp/src/androidMain/.../TvTextInputDialog.kt
Authentication screens and the text-input dialog use the shared IME-aware modifier and scroll state.
Responsive match-code layout
androidTvApp/src/androidMain/.../TvLoginScreen.kt, androidTvApp/src/androidUnitTest/.../TvLoginMatchCodeLayoutTest.kt
Match-code tiles calculate their width to fit the available content width.

Android TV player interactions

Layer / File(s) Summary
Subtitle picker behavior
androidTvApp/src/androidMain/.../TvQuickSubtitlePickerChromePolicy.kt, androidTvApp/src/androidMain/.../TvPlayerScreen.kt, related tests
Selection applies the subtitle before hiding the picker and controls. Back hides only the picker.
Transport accessibility
androidTvApp/src/androidMain/.../TvPlayerRemoteKeyAction.kt, androidTvApp/src/androidMain/.../TvPlayerTransport*.kt, related tests
D-pad Down focuses the transport. Transport controls use centralized 44dp button metrics.
Mounted sidecar transactions
androidTvApp/src/androidMain/.../TvSubtitleTransactionAdapter.kt, related transaction tests
Locally mounted server sidecars use local selection confirmation. Unavailable sidecars use staged replanning.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: quick104

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.85% 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 summarizes the main Android TV changes to Shield setup, playback controls, and subtitle switching.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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: 3

🤖 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
`@androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/auth/TvServerSetupScreen.kt`:
- Around line 405-463: The ManualEntryCard layout currently inherits the fixed
SERVER_SETUP_CHOOSER_HEIGHT and cannot expand for validation or
cleartext-warning content. Update the chooser/card sizing around ManualEntryCard
to use that value as a minimum height rather than a fixed height, allowing the
card to grow while preserving the existing baseline size and outer scrolling
behavior.

In
`@androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerRemoteKeyAction.kt`:
- Around line 35-38: Update the KEYCODE_DPAD_DOWN branch in
TvPlayerRemoteKeyAction so it returns FocusTransport only for the initial
ACTION_DOWN event, consumes repeated ACTION_DOWN events without remapping focus,
and preserves the existing non-down behavior. Match the established media
Left/Right handling pattern and add a regression test asserting repeatCount = 1
is consumed without returning FocusTransport.

In
`@docs/superpowers/specs/2026-08-02-tv-player-transport-accessibility-design.md`:
- Around line 31-33: Update the transport-dimensions boundary description in the
design document to identify TvPlayerTransportVisualPolicy.kt as the
centralization point, with TvPlayerTransportCluster.kt consuming that policy.
Leave the hidden-overlay key mapping and all HUD, subtitle, and player-state
requirements unchanged.
🪄 Autofix (Beta)

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 589d8a60-60cd-4e1a-be44-ced555e8c963

📥 Commits

Reviewing files that changed from the base of the PR and between 981c7a4 and 3041b94.

📒 Files selected for processing (42)
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/AndroidSubtitleTextSizePolicy.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/PlaybackCapabilityDetector.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/PlaybackSessionManager.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/PlaybackV3Session.kt
  • android-shared/src/androidMain/kotlin/org/siloserver/silo/common/player/SubtitleManager.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/AndroidSubtitleTextSizePolicyTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/PlaybackSessionManagerSeekReanchorTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/PlaybackV3SessionTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/SubtitleManagerAppearanceTest.kt
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/cast/CastPlaybackPreparerTest.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/components/TvImeAwareForm.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/components/TvTextInputDialog.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/auth/TvLoginScreen.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/auth/TvServerSetupScreen.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/auth/TvSetupScreen.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/auth/TvSignupScreen.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerRemoteKeyAction.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerScreen.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerTransportCluster.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerTransportVisualPolicy.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvQuickSubtitlePickerChromePolicy.kt
  • androidTvApp/src/androidMain/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleTransactionAdapter.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/components/TvImeAwareFormTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/auth/TvLoginMatchCodeLayoutTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/SubtitleTransactionIntegrationTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerRemoteKeyActionTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvPlayerTransportVisualPolicyTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvQuickSubtitlePickerChromePolicyTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleFinalRollbackTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleSettlementOwnershipTest.kt
  • androidTvApp/src/androidUnitTest/kotlin/org/siloserver/silo/tv/ui/screens/player/TvSubtitleTransactionAdapterTest.kt
  • docs/superpowers/plans/2026-08-02-android-tv-auth-ime-relocation.md
  • docs/superpowers/plans/2026-08-02-instant-external-srt-switching-android.md
  • docs/superpowers/plans/2026-08-02-tv-mounted-srt-fast-switch.md
  • docs/superpowers/plans/2026-08-02-tv-player-transport-accessibility.md
  • docs/superpowers/plans/2026-08-02-tv-subtitle-picker-and-sizing.md
  • docs/superpowers/specs/2026-08-02-android-tv-auth-ime-relocation-design.md
  • docs/superpowers/specs/2026-08-02-tv-mounted-srt-fast-switch-design.md
  • docs/superpowers/specs/2026-08-02-tv-player-transport-accessibility-design.md
  • docs/superpowers/specs/2026-08-02-tv-subtitle-picker-and-sizing-design.md
  • shared/src/commonMain/kotlin/org/siloserver/silo/model/playback/PlaybackProtocolV3.kt
  • shared/src/commonTest/kotlin/org/siloserver/silo/model/playback/PlaybackProtocolV3Test.kt
💤 Files with no reviewable changes (1)
  • android-shared/src/androidUnitTest/kotlin/org/siloserver/silo/common/player/SubtitleManagerAppearanceTest.kt

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