Skip to content

feat(player): add local music player, configurable autoplay, and playlist sync/dedup fixes - #290

Closed
Arunkumar-Anbazhagan wants to merge 2 commits into
Clash-Projects:mainfrom
Arunkumar-Anbazhagan:main
Closed

Arunkumar-Anbazhagan wants to merge 2 commits into
Clash-Projects:mainfrom
Arunkumar-Anbazhagan:main

Conversation

@Arunkumar-Anbazhagan

Copy link
Copy Markdown
Contributor

Summary

This PR addresses several community-requested player and playlist improvements:

  1. Local Music Player: Enables LastWave to discover and play songs stored locally on the device (as well as open audio files directly from external file managers).
  2. Playlist Track Deletion Index Fix: Fixes a critical bug where deleting a track while a playlist is sorted or filtered removed the wrong song.
  3. Playlist Deduplication: Adds intelligent song identity matching (normalizing remasters, features, bonus tracks) and provides one-tap playlist deduplication.
  4. Configurable Autoplay ("Auto-Add" Issue): Adds a user setting to control whether radio tracks automatically queue up when a playlist or queue reaches the end (defaults to false so playback stops as expected).
  5. Playlist YouTube Music Sync Fix: Fixes an issue where non-exact video matches were silently dropped during remote sync passes, and enriches tracks with resolved YouTube URLs to prevent repeated resolution loops.

Key Changes & Implementations

1. Local Music Player (feat)

  • MediaStore Ingestion: Created LocalAudioRepository querying MediaStore.Audio.Media.EXTERNAL_CONTENT_URI with proper runtime permission handling (READ_MEDIA_AUDIO on Android 13+ / API 33+ and legacy storage fallback).
  • Dedicated UI: Added LocalMusicScreen and LocalMusicViewModel featuring:
    • Real-time search filtering across title, artist, and album.
    • Sorting options: Recently Added, Title, Artist, and Duration.
    • Full playback controls (Play All, Shuffle, and context menu actions for queueing and playlists).
  • Navigation & Entry Point: Added a Device Music navigation card in PlaylistScreen and registered the route in NavGraph and MainShell.
  • System File Association / Intent Handling: Added ACTION_VIEW intent filter for audio/* in AndroidManifest.xml and handled playback with MediaMetadataRetriever in MainActivity so tapping audio files in file managers plays them directly in LastWave.

2. Playlist Track Deletion Index Fix (fix)

  • Root Cause: In PlaylistDetailScreen, deleting a song passed the filtered/sorted index (displayIndex) directly to playlistRepository.removeTrackAt(), causing the wrong track to be deleted whenever the list was searched or reordered.
  • Fix: Introduced IndexedDisplayTrack pairing every display track with its original unshifted index (originalIndex). Deletions now target the exact index in the underlying playlist model.

3. Song Identity Matching & Playlist Deduplication (feat/fix)

  • Smart Song Matching: Added cleanCoreTitle() and cleanCoreArtist() in GeneratedTrack.kt to strip noisy metadata tags (e.g., (Remastered ...), [Deluxe Edition], feat. ..., [Official Audio]).
  • One-Tap Deduplication: Added atomic deduplicate(playlistId) in PlaylistRepository and exposed it via the playlist detail menu, preserving user-pinned tracks and video IDs while eliminating duplicate entries.
  • Unit Tests: Added unit tests in TrackIdentityTest.kt verifying variant matching and deduplication behavior.

4. Configurable Autoplay / Endless Queue Control (fix/feat)

  • Root Cause: When a playlist reached its last track, MusicPlayer.kt unconditionally initiated an endless radio queue, injecting 35 tracks and continuing playback without user consent.
  • Fix:
    • Added autoplayEnabled: Boolean = false preference in SettingsPreferences and exposed an "Autoplay similar tracks" toggle under Settings → Audio.
    • Updated MusicPlayer.kt so playback cleanly stops at the end of a queue/playlist unless the user explicitly toggles autoplay on.

5. YouTube Music Playlist Sync Drop Fix (fix)

  • Root Cause: YtMusicSyncManager.kt filtered additions with && it in exactVideoIds, which dropped tracks added from Last.fm, Discover, search, or local import whose video IDs were resolved after creation.
  • Fix: Removed the strict check and persisted resolved YouTube URLs (https://music.youtube.com/watch?v=$videoId) directly onto synced tracks, preventing repeated resolution calls and ensuring sync parity with remote YouTube Music playlists.
  • Wrapped remote network calls and concurrent playlist mutations with non-fatal logging to prevent crashes from aborting the sync routine.

Verification & Testing

  • Unit Tests: Ran ./gradlew.bat testDebugUnitTest — all unit tests pass with zero regressions.
  • Release Build: Ran ./gradlew.bat assembleRelease — compiles cleanly with R8 optimization (~23.8 MB).
  • Rebase Verification: Branch is rebased cleanly on top of upstream/main (b6db40a) with linear git history and no merge conflicts.

Modified & Added Files

  • Manifest & App:
    • AndroidManifest.xml
    • MainActivity.kt
  • Data & Playback:
    • LocalAudioRepository.kt (new)
    • SettingsPreferences.kt
    • YtMusicSyncManager.kt
    • PlaylistRepository.kt
    • YtMusicLibraryManager.kt
    • GeneratedTrack.kt
    • MusicPlayer.kt
  • UI & Navigation:
    • LocalMusicScreen.kt (new)
    • LocalMusicViewModel.kt (new)
    • PlaylistScreen.kt
    • PlaylistDetailScreen.kt
    • PlaylistViewModel.kt
    • SettingsScreen.kt
    • SettingsViewModel.kt
    • NavGraph.kt
    • Screen.kt
    • MainShell.kt
    • PlayerHost.kt
  • Tests:
    • TrackIdentityTest.kt

…songs

- Enhanced song identity matching with title/artist cleaning to recognize variants
- Fixed playlist track removal by preserving exact original index during sort/filter
- Added atomic deduplicate method to PlaylistRepository and one-tap action in PlaylistDetailScreen
- Deduplicated library playlists in YtMusicLibraryManager and ViewModel
- Added unit tests for track identity matching and deduplication
…st playlist sync

- Local Music Player:
  - Add READ_MEDIA_AUDIO permission and intent filter for audio/* files
  - Handle ACTION_VIEW intent in MainActivity with MediaMetadataRetriever
  - Create LocalAudioRepository for querying MediaStore.Audio
  - Create LocalMusicScreen and LocalMusicViewModel with search, sorting, and playback actions
  - Add Device Music navigation card in PlaylistScreen and register route in NavGraph and MainShell

- Autoplay / Auto-add Control:
  - Add autoplayEnabled toggle in SettingsPreferences and SettingsScreen
  - Gate automatic radio track queue injection behind autoplay preference in MusicPlayer

- Playlist Sync Reliability:
  - Prevent drops of non-exact matched tracks in YtMusicSyncManager
  - Persist resolved YouTube video URLs to avoid repeated re-resolutions
  - Make remote playlist fetch and updates robust against concurrent sync passes
@ajisth69 ajisth69 closed this Oct 13, 2026
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.

2 participants