Skip to content

Conversation

@y-hbb
Copy link
Contributor

@y-hbb y-hbb commented Jan 20, 2026

Adds random play functionality to the TV interface, addressing feature parity with the phone layout. Users can now play random content from the Home and Library screens using buttons in the top toolbar.

Changes:

  • Add random button to Home TV toolbar (between search and account)
  • Add random button to Library TV toolbar (after search field)
  • Enable "Random Button" setting visibility for TV users
  • Add placeholder views in phone layouts for ViewBinding compatibility
  • Implement dynamic focus chain updates for proper D-pad navigation
  • Extract shared click handlers to reduce code duplication

Technical details:

  • Use defensive .toList() copy before .random() to prevent race conditions
  • Dynamically update nextFocusRightId/nextFocusLeftId when button visibility changes
  • Reset focus chain when button is hidden to maintain proper TV navigation

Code and commit generated using AI. Let me know if you need me test anything.

Closes #2347

TV
Library:
image

Home:
image

Phone
Library:
image

Home:
image

Copy link
Collaborator

@fire-light42 fire-light42 left a comment

Choose a reason for hiding this comment

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

Good pull request, however I need you to change some things.

  1. "Use defensive .toList() copy before .random() to prevent race conditions" needs to be changed if you want to properly prevent race conditions.
  2. "Dynamically update nextFocusRightId/nextFocusLeftId when button visibility changes" is useless and all code related to it should be removed. Instead it should be written in the xml navigation as our navigation can handle hidden views.
  3. You forgot about EMULATOR and that views should match exactly, so make the dummy views into ImageViews.

if (listHomepageItems.isNotEmpty()) {
activity.loadSearchResult(listHomepageItems.random())
val randomClickListener = View.OnClickListener {
val items = listHomepageItems.toList()
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is bad, and does not fully solve the problem. If you want to solve it then move it into the page observe, like:

val distinct = mutableListOfResponse.distinctBy { it.url } // <- local variable instead of global

homeRandom.isVisible = distinct.isNotEmpty()
homeRandom.setOnClickListener {
    distinct.randomOrNull()?.let { item ->
        activity.loadSearchResult(item)
    }
}

tools:visibility="visible" />

<!-- Placeholder for TV layout random button - always hidden on phone -->
<View
Copy link
Collaborator

Choose a reason for hiding this comment

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

ImageView.

tools:visibility="visible" />

<!-- Placeholder for TV layout random button - always hidden on phone -->
<View
Copy link
Collaborator

Choose a reason for hiding this comment

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

ImageView

val settingsManager = PreferenceManager.getDefaultSharedPreferences(requireContext())

getPref(R.string.random_button_key)?.hideOn(EMULATOR or TV)
getPref(R.string.random_button_key)?.hideOn(EMULATOR)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove entirely.

if (listLibraryItems.isNotEmpty()) {
val listLibraryItem = listLibraryItems.random()
val randomClickListener = View.OnClickListener {
val items = listLibraryItems.toList()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same issue here.

binding.libraryRandomButtonTv.isVisible = hasItems
binding.libraryRandom.isGone = true
// Update focus chain: random button is after search field
binding.mainSearch.nextFocusRightId = if (hasItems) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove.

homeRandom.isGone = true
homeRandomButtonTv.isGone = true
// Reset focus chain when random button is hidden
if (!isLayout(PHONE)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove.

homeRandomButtonTv.isVisible = hasItems
homeRandom.isGone = true
// Update focus chain when random button is visible
if (hasItems) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove.

binding.libraryRandom.isGone = true
binding.libraryRandomButtonTv.isGone = true
// Reset focus chain when random button is hidden
if (!isLayout(PHONE)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove.

@y-hbb y-hbb requested a review from fire-light42 January 21, 2026 21:45
@y-hbb
Copy link
Contributor Author

y-hbb commented Jan 22, 2026

Good pull request, however I need you to change some things.

1. "Use defensive .toList() copy before .random() to prevent race conditions" needs to be changed if you want to properly prevent race conditions.

2. "Dynamically update nextFocusRightId/nextFocusLeftId when button visibility changes" is useless and all code related to it should be removed. Instead it should be written in the xml navigation as our navigation can handle hidden views.

3. You forgot about EMULATOR and that views should match exactly, so make the dummy views into ImageViews.

review comments were fixed. added additional changes to get different random without repeatation.

Copy link
Collaborator

@fire-light42 fire-light42 left a comment

Choose a reason for hiding this comment

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

Do not store it as global variables in the class, that just creates the race condition you wanted to "solve". Furthermore your "random" is overengineered where a simple shuffle and incrementing index should solve it just fine.

y-hbb added 3 commits January 22, 2026 11:30
Adds random play functionality to the TV interface, addressing feature
parity with the phone layout. Users can now play random content from
the Home and Library screens using buttons in the top toolbar.

Changes:
- Add random button to Home TV toolbar (between search and account)
- Add random button to Library TV toolbar (after search field)
- Enable "Random Button" setting visibility for TV users
- Add placeholder views in phone layouts for ViewBinding compatibility
- Implement dynamic focus chain updates for proper D-pad navigation
- Extract shared click handlers to reduce code duplication

Technical details:
- Use defensive .toList() copy before .random() to prevent race conditions
- Dynamically update nextFocusRightId/nextFocusLeftId when button visibility
changes
- Reset focus chain when button is hidden to maintain proper TV navigation

Code and commit generated using AI
Track previously suggested items to avoid showing the same content
repeatedly when using the random button. Resets tracking when content
changes or when all items have been shown.

includes review comment fixes
Remove shuffle state tracking entirely - just pick a random item on
each click using randomOrNull().
@y-hbb
Copy link
Contributor Author

y-hbb commented Jan 22, 2026

reverted the shuffle changes went back to random function

Simplify visibility and click listener setup by replacing nested
if/else with direct boolean assignments. Also removes redundant
.toList() call.
@y-hbb y-hbb requested a review from fire-light42 January 22, 2026 17:17
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.

Play random media in TV

2 participants