Musynth scans your device’s local storage and surfaces every audio file across six purpose-built tabs — Songs, Albums, Artists, Playlist (Android only), Favourites, and Genres. This page explains what each tab shows, how fast-scroll and collection screens work, and how theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/CesarArellano/Music-Player-App/llms.txt
Use this file to discover all available pages before exploring further.
PlaylistType enum ties every tab to a distinct playback context.
Tab overview
| Tab | Description |
|---|---|
| Songs | All tracks sorted alphabetically by title, with an A–Z fast-scroll rail on the right edge. |
| Albums | A 2-column artwork grid (4 columns in landscape). Tap an album to open its track list. |
| Artists | A scrollable list showing album and track counts. Tap to see an artist’s albums and songs. |
| Playlist | Android only. Create and delete MediaStore playlists, add songs from any context menu. |
| Favourites | Persisted favourites list. Plays as its own PlaylistType.favorites queue. |
| Genres | Every genre reported by the device. Tap to browse songs filtered to that genre. |
The Playlist tab is conditionally rendered only on Android. The
TabController length is set to 6 on Android and 5 on iOS, and all playlist-related operations are guarded by Platform.isAndroid.Songs tab
The Songs tab (SongsScreen) is the primary view. When the library loads, songs are already sorted by title (SongSortType.TITLE) so the alphabet rail is immediately meaningful.
Alphabet fast-scroll rail
A compactAlphabetScrollbar widget sits on the right edge of the Songs tab. It:
- Auto-reveals whenever the list is scrolling, then fades out after 1.5 s of inactivity.
- Highlights the active letter with a floating pill bubble.
- Triggers haptic feedback on each letter change via
HapticFeedback.selectionClick(). - Maps a touch Y-position to a letter index in O(1) time — each letter occupies a fixed
letterExtentslice, so the index is simplydy ~/ letterExtent.
_buildIndex(), only recomputing when the song list reference changes:
ScrollController.jumpTo() for an instant, jank-free jump.
Scroll-to-top button
A floating scroll-to-top button appears once the user scrolls down more than 50 px and is actively scrolling upward. It animates the list back to position 0 in 300 ms.Albums tab
AlbumsScreen renders a GridView with:
- 2 columns in portrait, 4 columns in landscape.
- Each card shows the album artwork (174 px tall), the album title, and the song count.
- Tapping navigates to
AlbumSelectedScreenviaAppRoutes.album.
Artists tab
ArtistScreen renders a list where each row shows the artist artwork, name, album count, and track count. Tapping navigates to ArtistSelectedScreen, which calls LibraryCubit.searchByArtistId to load songs and albums for that artist.
Off-thread artist resolution
searchByArtistId runs its filter and aggregation in a Dart Isolate, keeping the UI thread free while O(k+m) work completes (k = songs, m = albums):
LibraryState.artistCollection keyed by artistId, so subsequent visits are instant.
Playlists tab (Android only)
PlaylistsScreen lists all MediaStore playlists. Each row shows the playlist artwork, name, and song count, with a delete icon on the trailing edge.
Creating a playlist
Tap the + FAB (visible only when the Playlists tab is active) to openCreatePlaylistDialog. Confirming calls MusicQuerySelector.createPlaylist(name) and then refreshes the list:
Adding songs to a playlist
Long-press any song →MoreSongOptionsModal → Add to playlist → choose from a dropdown.
Deleting a playlist
Tap the delete icon or long-press a playlist row. The modal callsMusicQuerySelector.removePlaylist(id), then LibraryCubit.refreshPlaylist().
Favourites tab
FavoriteScreen reads from FavoritesCubit.state.favoriteList — a decoded list of SongModel instances persisted via SharedPreferences. Tapping a song plays the entire favourites list as PlaylistType.favorites.
See Favourites & Playlists for the full persistence and toggle details.
Genres tab
GenresScreen renders a list of every genre. Each row shows the genre artwork, name, and song count. Tapping navigates to GenreSelectedScreen, which calls LibraryCubit.searchByGenreId(genreId) to load the filtered song list.
Collection screens
AlbumSelectedScreen, ArtistSelectedScreen, GenreSelectedScreen, and PlaylistSelectedScreen share a common layout:
Collapsing header
A large artwork and metadata block at the top. As you scroll past 191 px the app-bar title fades in and the header collapses.
Sticky Play / Shuffle row
A
PlayShuffleButtons widget pinned to the top of the song list. Play starts the collection from the first track; Shuffle randomises the order.PlaylistType enum
Every tab and collection screen resolves its song list through aPlaylistType value. This enum is the single source of truth that MusicOrchestratorService.playSong and PlaylistResolverFactory use to build the correct queue.
| Value | Source |
|---|---|
PlaylistType.songs | Full LibraryState.songList |
PlaylistType.album | LibraryState.albumCollection[id] |
PlaylistType.artist | LibraryState.artistCollection[id].songs |
PlaylistType.genre | LibraryState.genreCollection[id] |
PlaylistType.playlist | LibraryState.playlistCollection[id] |
PlaylistType.favorites | FavoritesCubit.state.favoriteList |
Floating action button behaviour
The FAB adapts based on the active tab index:| Active tab | FAB icon | Action |
|---|---|---|
| Any except Playlist | Icons.shuffle | Picks a random song and starts the full PlaylistType.songs queue with shuffle enabled |
| Playlist (Android) | Icons.add | Opens CreatePlaylistDialog |
isCreatingArtworks: true), the FAB remains visible but its onPressed is set to null (disabled) and its child is replaced with a CircularProgressIndicator.
Scanning for new media
Open the app-bar overflow menu (⋮) and tap Scan media. This callsLibraryCubit.getAllSongs(), which re-queries all four MediaStore collections (songs, albums, artists, genres — and playlists on Android) concurrently and rebuilds the artwork cache for any new artwork.