Skip to content

feat: add full D-pad/Android TV support across all screens - #1499

Open
Karthik7013 wants to merge 8 commits into
rukamori:mainfrom
Karthik7013:kilo/radial-lake-ch3
Open

Karthik7013 wants to merge 8 commits into
rukamori:mainfrom
Karthik7013:kilo/radial-lake-ch3

Conversation

@Karthik7013

Copy link
Copy Markdown
  • Add TVFocusHandler component with D-pad key handling and tvCombinedClickable modifier
  • Enhance TvNavigationRail with bidirectional focus (rail <-> content)
  • Add TV focus management in MainActivity shell
  • Add TV-aware focus navigation to all screens: Home, Library, Search, Playlists, Account, Album, Stats, History, Explore, Charts, New Release, YouTube Browse, Artist screens, Settings, News, ViewNews, Podcast, Spotify Liked Songs
  • Add Player D-pad controls (TV only): Center/Enter=Play/Pause, Left=Prev, Right=Next, Up/Down=Volume
  • Make all clickable/interactive elements focusable for D-pad navigation

Pull Request

Before submitting a pull request, you must attest to the following:

<<<<<<< HEAD

1c00d59 (add no llm policy inspired by ytdlp)

Summary

Linked Work

  • Closes:
  • Related:

Change Type

  • Feature
  • Bug fix
  • UI / UX
  • Performance / memory
  • Playback / Media3
  • Lyrics / provider integration
  • Search / YouTube / network data
  • Local library / Room database
  • Widgets / notification / shortcuts
  • Settings / preferences / DataStore
  • Discord / Last.fm / ListenBrainz / external integration
  • Localization / strings / fastlane metadata
  • Build / Gradle / CI / release packaging
  • Dependency update
  • Documentation only

Affected Surfaces

  • :app
  • :core
  • :lyrics
  • :lastfm
  • :canvas
  • :shazamkit
  • :spotifycore
  • Other:

Screenshots / Recordings

Before After

Behavior Notes

Architecture Checklist

  • The change preserves UDF flow: UI -> ViewModel -> UseCase/domain -> Repository/data.
  • Screen state is represented structurally with Loading, Success, Empty, and Error where this PR introduces or changes screen state.
  • Composables receive immutable, UI-specific domain models instead of raw Room, network, or service entities.
  • Business work is not triggered directly from composition.
  • Exceptions are surfaced through explicit state or result types instead of being swallowed.
  • No runBlocking is introduced in app execution paths.

Compose / Material Checklist

  • UI state is hoisted out of composable layout code.
  • Reactive state is collected with collectAsStateWithLifecycle().
  • New UI models are annotated with @Immutable or @Stable.
  • Lazy layouts use stable key values and explicit contentType.
  • Non-primitive constants, structural lambdas, and allocation-heavy objects in hot paths are remembered.
  • Rapidly changing inputs such as scroll, gesture, animation, or playback progress use derivedStateOf where appropriate.
  • UI strings come from stringResource() and duplicated visible strings on the same screen are avoided.
  • Interactive elements keep a minimum 48dp touch target.
  • Material 3 / Material 3 Expressive tokens are used for color, typography, shape, and motion instead of hardcoded UI values.
  • Edge-to-edge layouts handle and consume WindowInsets correctly when this PR changes screen layout.

Concurrency / Performance Checklist

  • Business coroutines are scoped to viewModelScope or an existing lifecycle-owned application/service scope.
  • Disk, database, network, parsing, and heavy mapping work is dispatched to Dispatchers.IO or Dispatchers.Default.
  • Cancellation is handled explicitly where long-running work, playback, downloads, sync, lyrics fetching, or recognition is involved.
  • The change avoids blocking the main thread.
  • The change avoids unnecessary allocations in recomposition loops, playback loops, polling loops, and provider parsing paths.
  • Large lists, images, lyrics payloads, and network responses are bounded, streamed, cached, paged, or mapped off the main thread as appropriate.

Data / Persistence Checklist

  • Room entity, DAO, or database changes include a schema update under app/schemas.
  • Database migrations preserve existing user data and fail clearly when migration is impossible.
  • DataStore or preference-key changes are backward compatible.
  • Network DTOs remain isolated from UI models.
  • Provider responses handle missing, malformed, regional, or rate-limited data without crashing the app.

Playback / Integration Checklist

  • Media3 playback, queue, cache, and service behavior remains stable across foreground, background, notification, and process recreation paths.
  • Audio focus, notification controls, widgets, shortcuts, and media session actions are considered when playback behavior changes.
  • External integrations handle absent credentials, revoked auth, network failure, and API changes.
  • Native, AAR, or ABI-sensitive changes account for mobile/tv and universal, arm64, armeabi, x86, and x86_64 variants.

Localization / Assets Checklist

  • User-facing strings are added to the base resources and translated resources are updated or intentionally left for translation follow-up.
  • Unused string resources, drawables, and metadata are removed when replaced.
  • Image assets have explicit display dimensions and are decoded at the displayed size.
  • Fastlane metadata, screenshots, icons, or release text are updated when user-facing store behavior changes.

Privacy / Security Checklist

  • No secrets, keys, tokens, keystores, signing files, private certificates, or local machine paths are committed.
  • Logs do not expose access tokens, cookies, auth headers, user identifiers, listening history, or local file paths.
  • New network calls are justified by the feature and use existing client, proxy, timeout, and error-handling patterns.
  • User data remains local unless the PR explicitly documents the integration and consent path.

Verification

  • Android Studio sync:
  • Manual device/emulator verification:
  • UI screenshot/recording attached:
  • Accessibility or touch-target review:
  • Regression areas checked:
  • CI expectation:

Reviewer Focus

Release Notes

- Add TVFocusHandler component with D-pad key handling and tvCombinedClickable modifier
- Enhance TvNavigationRail with bidirectional focus (rail <-> content)
- Add TV focus management in MainActivity shell
- Add TV-aware focus navigation to all screens: Home, Library, Search, Playlists,
  Account, Album, Stats, History, Explore, Charts, New Release, YouTube Browse,
  Artist screens, Settings, News, ViewNews, Podcast, Spotify Liked Songs
- Add Player D-pad controls (TV only): Center/Enter=Play/Pause, Left=Prev, Right=Next,
  Up/Down=Volume
- Make all clickable/interactive elements focusable for D-pad navigation
- Add missing focusProperties import to MainActivity.kt
- Fix TVFocusHandler.kt: add missing key/type extension imports,
  clickable import, FocusDirection import, animateColorAsState import
- Fix Box contentAlignment parameter (was verticalAlignment)
- Remove unsupported direction parameter from focusProperties
…ded)

- Backup original build.yml as build.yml.backup
- New build-tv-debug.yml: builds only TV debug APK
- No matrix builds (single job, no multiple versions)
- No signing secrets required (debug variant)
- No Telegram notifications
- Triggers on manual dispatch or push to main/dev/kilo/**
- Replace Key.DPadCenter with Key(KEYCODE_DPAD_CENTER.toLong()) in TVFocusHandler.kt, Player.kt, HomeScreenComponents.kt
- Replace Key.Enter with Key(KEYCODE_ENTER.toLong())
- Add by keyword for animateColorAsState and animateFloatAsState delegates
- Fix Arrangement.CenterVertically reference
- Remove interactionSource/indication from clickable calls (not supported)
- Fix Queue.kt return@combinedClickable labels (invalid)
- Add missing focusable import to NewsScreen, ViewNewsScreen, LibraryScreen, SpotifyLikedSongsScreen, PodcastScreen, AppearanceSettings, MusicTogetherScreen, PalettePickerScreen, StorageSettings
- Add missing onKeyEvent/Key/key imports to HomeScreenComponents.kt
- Remove animations from TVFocusHandler.kt (use static colors instead of animateColorAsState/animateFloatAsState delegates)
- Fix Arrangement.CenterVertically reference
- Remove unused android.view.KeyEvent static imports from HomeScreenComponents.kt
- Revert to Key.DPadCenter/Key.Enter (exist in Compose Key object)
- All tvCombinedClickable, tvSectionFocus, tvDpadClickable use static key codes
- Change Arrangement.CenterVertically to Arrangement.Center in TVFocusHandler.kt
- Fix Modifier reference in Box to use androidx.compose.ui.Modifier
- Change Key.DPadCenter back to Key(KEYCODE_DPAD_CENTER.toLong()) in HomeScreenComponents.kt
- Ensure KEYCODE_ENTER and KEYCODE_NUMPAD_ENTER imports in HomeScreenComponents.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