Open
Conversation
Co-authored-by: riteshshukla04 <riteshshukla2381@gmail.com>
…e it adjusting references accordingly getting a lot more things to work properly tidying up utils folder and breaking down large files
add miniplayer progress shadow to improve visibility fix text in library sticky headers
text press animations settings page fixes
…ed items to their respective tracks
smol styling and scrubber enhancements too :)
rnnp patch for removing the current track from the playlist update match docs
query client fixes player fixes in dev mode
There was a problem hiding this comment.
Pull request overview
This PR migrates the app’s playback and download stack from RN Track Player (RNTP) to react-native-nitro-player (Nitro Modules), aiming to improve gapless playback, system audio integration, and performance. It also updates surrounding utilities, state persistence, and several UI components to align with the new track/download data model and newer Tamagui patterns.
Changes:
- Replace RNTP-based player initialization/events/queueing with Nitro Player + new event handlers and persisted playback position.
- Migrate downloads to Nitro
DownloadManagerwith new query/mutation hooks and updated storage management UI. - Refactor track payload handling (extraPayload JSON) and update multiple UI components + Tamagui config/styling.
Reviewed changes
Copilot reviewed 199 out of 209 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| src/utils/trackDetails.ts | Explicit-rating check now on BaseItemDto |
| src/utils/toasts/deletion-toast.ts | Centralized deletion toast helper |
| src/utils/parsing/blurhash.ts | Guard for empty blurhash keys |
| src/utils/mapping/track-extra-payload.ts | Helpers to read Nitro extraPayload |
| src/utils/mapping/slimify-dto.ts | Map/trim DTOs for storage/UI |
| src/utils/mapping/item-to-audio-api-url.ts | Build stream/transcode URLs for audio |
| src/utils/formatting/artist-names.ts | Add formatting for ArtistItems |
| src/utils/fetching/track-media-info.ts | Resolve/update playback URLs & media info |
| src/utils/audio/normalization.ts | Normalization now reads from Nitro payload |
| src/utils/audio/device-profiles.ts | Fix import paths for device profile mapping |
| src/types/TrackMediaInfo.ts | New type placeholder for media source |
| src/types/JellifyTrack.ts | Replace RNTP track type with Nitro payload types |
| src/types/JellifyDownload.ts | Downloads now based on Nitro TrackItem |
| src/stores/settings/player.ts | Update device profile import path |
| src/stores/player/playback.ts | New persisted playback-position store |
| src/stores/player/engine.ts | Engine uses Nitro TrackPlayer |
| src/stores/network/downloads.ts | Download queue now uses Nitro tracks + URL resolve |
| src/stores/index.ts | Add migration flag for Nitro player |
| src/stores/device-profile.ts | Update device profile import path |
| src/services/types/queuing-request.ts | New queuing request type |
| src/services/types/queue-item.ts | Define queue reference type |
| src/services/player.ts | Configure Nitro TrackPlayer |
| src/services/downloads.ts | Configure Nitro DownloadManager + query cache updates |
| src/services/carplay.ts | CarPlay connect/disconnect registration |
| src/screens/types.d.ts | Route types updated (playlist param added) |
| src/screens/navigation.ts | Fix navigation type import path |
| src/screens/index.tsx | Use Tamagui Paragraph for headers |
| src/screens/YearSelection/index.tsx | Button text updated to Paragraph |
| src/screens/Tabs/index.tsx | Tab icons adjusted |
| src/screens/Settings/storage-selection-modal.tsx | Storage review uses Nitro downloads + new toast |
| src/screens/Settings/storage-management/useDeletionToast.ts | Remove old screen-local toast hook |
| src/screens/Settings/sign-out-modal.tsx | Clear downloads via Nitro DownloadManager |
| src/screens/Settings/index.tsx | Storage screen route updated |
| src/screens/Player/types.d.ts | Artists sheet now uses NameGuidPair[] |
| src/screens/Login/server-authentication.tsx | UI tweaks for buttons/icons |
| src/screens/GenreSelection/index.tsx | Use transition instead of animation |
| src/screens/Context/index.tsx | Pass optional playlist through route |
| src/providers/Player/utils/initialization.ts | Nitro player restore + event handler registration |
| src/providers/Player/utils/index.ts | Remove old RNTP queue helper utilities |
| src/providers/Player/utils/event-handlers.ts | New Nitro player event handlers + reporting |
| src/providers/Player/utils/auto-download.ts | Auto-download using Nitro DownloadManager |
| src/providers/Player/index.tsx | Remove RNTP event wiring; init Nitro |
| src/providers/Artist/index.tsx | Similar artists query key/function simplified |
| src/player/index.ts | Remove RNTP playback service |
| src/hooks/use-update-options.ts | Remove RNTP updateOptions hook |
| src/hooks/use-mini-player.ts | Mini-player activation simplified |
| src/hooks/use-download-processor.ts | Remove legacy download processor |
| src/hooks/player/interfaces.ts | Remove queuingType from queue mutation interface |
| src/hooks/player/index.ts | Progress/state now backed by Nitro + casting integration |
| src/hooks/player/functions/utils/shuffle.ts | Shuffle works on Nitro TrackItem |
| src/hooks/player/functions/utils/queue.ts | Add playlist cleanup + downloaded filtering update |
| src/hooks/player/functions/repeat-mode.ts | Repeat toggle for Nitro repeat mode |
| src/hooks/player/functions/index.ts | Remove old active-track handler |
| src/hooks/player/functions/controls.ts | Previous/skip using Nitro state + haptics |
| src/hooks/downloads/queries.ts | Query: list all downloaded tracks (Nitro) |
| src/hooks/downloads/mutations.ts | Download/delete mutations using Nitro |
| src/hooks/downloads/keys.ts | Download query key |
| src/hooks/downloads/index.ts | Downloads hook + useIsDownloaded helper |
| src/enums/queuing-type.ts | Update queuing enum values |
| src/constants/player.ts | Remove RNTP capabilities constants |
| src/configs/style.config.ts | Replace animation usage with transition; add icon press styles |
| src/configs/query.config.ts | Reduce library shuffle limit |
| src/configs/player.config.ts | Replace RNTP config with Nitro lookahead + new threshold |
| src/configs/gapless.config.ts | Remove old gapless config (Nitro handles) |
| src/configs/fonts.config.ts | Add Figtree font config for Tamagui |
| src/components/theme.ts | Move Tamagui config import |
| src/components/jellify.tsx | Sentry init moved into useEffect; remove download processor |
| src/components/Tracks/component.tsx | Queue type import moved to services |
| src/components/Settings/tab-bar.tsx | Remove custom settings tab bar |
| src/components/Settings/components/usage-tab.tsx | Use Nitro downloaded-tracks hook |
| src/components/Settings/components/sign-out-button.tsx | Remove explicit color prop |
| src/components/Settings/components/settings-list-group.tsx | Simplify group styling and sizing |
| src/components/Settings/components/preferences-tab.tsx | Use transition prop |
| src/components/Settings/components/labs-tab.tsx | Remove borderColor prop |
| src/components/Settings/components/account-tab.tsx | Remove explicit color prop |
| src/components/Settings/component.tsx | Safe area wrapper + new tab bar colors |
| src/components/Search/index.tsx | Navigation ref import fixed |
| src/components/Queue/config.ts | Remove unused queue config constant |
| src/components/Playlist/index.tsx | Download + queue load updated to Nitro-based hooks |
| src/components/Playlist/components/header.tsx | Queue load + UI button updates |
| src/components/Player/index.tsx | Layout/safe-area adjustments + gesture cleanup |
| src/components/Player/components/scrubber.tsx | Progress source swapped; quality badge wiring updated |
| src/components/Player/components/quality-badge.tsx | Determine stream vs download via Nitro downloads |
| src/components/Player/components/lyrics.tsx | Progress + track identity updated for Nitro |
| src/components/Player/components/header.tsx | Artwork now uses DTO from payload + transitions |
| src/components/Player/components/footer.tsx | Remove releaseDate prop |
| src/components/Player/components/controls.tsx | Controls now call Nitro queue/controls functions |
| src/components/Player/components/buttons.tsx | Play/pause uses Nitro now-playing state |
| src/components/Player/components/blurred-background.tsx | Blurhash from DTO parsed from Nitro payload |
| src/components/Player/component.config.ts | Remove old progress multiplier notes |
| src/components/Library/tab-bar.tsx | Nitro TrackPlayer usage + transition props |
| src/components/Library/component.tsx | Tab bar colors aligned with theme |
| src/components/Home/index.tsx | Layout tweak (remove Android margin) |
| src/components/Home/helpers/recently-played.tsx | Queue load uses new function |
| src/components/Home/helpers/frequent-tracks.tsx | Queue load uses new function |
| src/components/Global/helpers/time-codes.tsx | Use Tamagui Paragraph instead of custom Text |
| src/components/Global/helpers/text.tsx | Add optional outline via text shadow |
| src/components/Global/helpers/switch-with-label.tsx | Switch styling updated (activeStyle/transition) |
| src/components/Global/helpers/radio-group-item-with-label.tsx | Replace space with gap |
| src/components/Global/helpers/flashlist-sticky-header.tsx | Simplify sticky header visuals |
| src/components/Global/components/list-group.tsx | Remove explicit separator prop |
| src/components/Global/components/library-selector.tsx | Update ToggleGroup styling/transition |
| src/components/Global/components/item-row.tsx | Queue actions updated; new queuing type mapping |
| src/components/Global/components/item-card.tsx | Remove warmContext prefetch + update transitions |
| src/components/Global/components/instant-mix-button.tsx | Icon/name changes + Tamagui Text usage |
| src/components/Global/components/image.tsx | Support custom blurhash + style refactor |
| src/components/Global/components/icon.tsx | New sizing options + transition + outline |
| src/components/Global/components/favorite-context-menu-row.tsx | Replace animation with transition |
| src/components/Global/components/downloaded-icon.tsx | Show download progress via Nitro hook |
| src/components/Global/components/circular-progress-indicator.tsx | New animated circular progress component |
| src/components/Global/components/Track/content.tsx | Track row layout updated (explicit/download icon) |
| src/components/Filters/index.tsx | Replace animation with transition |
| src/components/Discover/helpers/suggested-artists.tsx | Navigation ref import fixed |
| src/components/Discover/helpers/suggested-albums.tsx | Navigation ref import fixed |
| src/components/Discover/helpers/public-playlists.tsx | Navigation ref import fixed |
| src/components/Discover/helpers/just-added.tsx | Navigation ref import fixed |
| src/components/Discover/component.tsx | Layout tweak (remove Android margin) |
| src/components/Context/utils/navigation.ts | Navigation ref import fixed |
| src/components/Context/components/remove-from-playlist-row.tsx | New “remove from playlist” action row |
| src/components/Context/components/delete-playlist-row.tsx | Navigation ref import fixed |
| src/components/CarPlay/Tracks.tsx | CarPlay queue load uses new function |
| src/components/CarPlay/Album.tsx | CarPlay queue load uses new function |
| src/components/Artist/header.tsx | Track loading hook updated; UI transitions |
| src/components/Artist/TracksTab.tsx | Use useArtistTracks |
| src/components/Album/index.tsx | Album downloads via Nitro hooks |
| src/components/Album/header.tsx | Play/shuffle uses new queue loader + UI tweaks |
| src/components/Album/footer.tsx | Navigation ref import fixed; simplify animations |
| src/components/AddToPlaylist/index.tsx | Replace animation with transition |
| src/api/utils/nitro.ts | Mark helper deprecated |
| src/api/queries/user-data/keys.ts | Query key now uses itemId |
| src/api/queries/user-data/index.ts | Use new user-data query key signature |
| src/api/queries/suggestions/utils/similar.ts | Remove libraryId requirement |
| src/api/queries/suggestions/index.ts | Similar queries keyed by itemId only |
| src/api/queries/recents/utils/index.ts | Cache artists into new artist query key |
| src/api/queries/media/utils/index.ts | Fetch media info pulls api from store |
| src/api/queries/media/queries.ts | New shared MediaInfoQuery + ensure helper |
| src/api/queries/media/index.ts | Stream media hook uses shared MediaInfoQuery |
| src/api/queries/lyrics/keys.ts | Lyrics key now uses Nitro track id |
| src/api/queries/lyrics/index.ts | Lyrics uses Nitro now-playing |
| src/api/queries/image/utils/index.ts | Image fallback improved (tags optional; artist fallback) |
| src/api/queries/frequents/utils/frequents.ts | Cache artists into new artist query key |
| src/api/queries/download/utils/storage-in-use.ts | Remove RNFS-based storage query |
| src/api/queries/download/keys.ts | Remove legacy download query keys |
| src/api/queries/download/index.ts | Remove legacy download queries |
| src/api/queries/download/constants/index.ts | Remove legacy download query constants |
| src/api/queries/artist/keys.ts | Add artist-by-id query key |
| src/api/queries/artist/index.ts | Add useArtist query |
| src/api/queries/album/queries.ts | Add AlbumQuery |
| src/api/queries/album/keys.ts | Add AlbumQueryKey |
| src/api/queries/album/index.ts | Add useAlbum hook |
| src/api/mutations/playback/functions/playback-stopped.ts | Playback stop report uses Nitro track id/payload |
| src/api/mutations/playback/functions/playback-started.ts | Playback start report uses Nitro track id/payload |
| src/api/mutations/playback/functions/playback-progress.ts | Playback progress report uses Nitro track id/payload |
| src/api/mutations/playback/functions/playback-completed.ts | Playback completed uses parsed DTO/media info |
| src/api/mutations/favorite/index.ts | User data cache key updated |
| src/api/mutations/download/utils/index.ts | Remove legacy save-audio helper |
| src/api/mutations/download/index.ts | Remove legacy download mutations |
| patches/react-native-worklets-core+1.6.2.patch | Remove patch no longer needed |
| patches/react-native-worklets+0.7.2.patch | Patch RN compatibility list for 0.84 |
| patches/react-native-nitro-player+0.6.0.patch | Patch: handle removed-current-track in native core |
| patches/react-native-fs+2.20.0.patch | Remove old RNFS patch |
| patches/@tamagui+element+2.0.0-rc.22.patch | Patch: relax HTMLElement checks for web |
| jest/setup/rntp.ts | Remove RNTP Jest mock |
| jest/setup/rnfs.ts | Remove RNFS Jest mock |
| jest/setup/nitro-player.ts | Add Nitro player Jest mock |
| jest/functional/blurhash.test.ts | Add blurhash functional coverage |
| jest/functional/Shuffle.test.tsx | Update shuffle tests for Nitro track model |
| jest/functional/RunTimeTicks.test.ts | Add ticks/seconds conversion tests |
| jest/functional/Player/utils.test.ts | Remove RNTP Progress type dependency |
| jest/functional/Player/controls.test.ts | Update control tests for Nitro APIs |
| jest/functional/Normalization.test.ts | Update normalization tests for Nitro payload |
| jest/functional/AddToQueue.test.ts | Update queue tests for Nitro playlist APIs |
| jest/contextual/SwipeableRow.behavior.test.tsx | Update Tamagui config import + theme |
| jest.config.js | Update setup files + transform ignore patterns |
| ios/Jellify/Info.plist | Add background fetch mode; remove location usage entry |
| index.js | Remove RNTP playback service registration |
| babel.config.js | Add Tamagui babel plugin config |
| android/app/src/main/AndroidManifest.xml | Add foreground service perms + work manager service |
| README.md | Update dependency list to Nitro Player |
| CONTRIBUTING.md | Update iOS run/device signing steps |
| App.tsx | Replace RNTP setup with Nitro configure routines |
| .gitignore | Ignore Tamagui output directory |
| bun.lockb | Lockfile updated for new deps/patches |
Comments suppressed due to low confidence (2)
src/hooks/player/index.ts:91
usePlaybackStatemaintains a localplaybackState(including a Google Cast mapping), but the hook always returnsuseNowPlaying().currentStateinstead. This makes the Cast state mapping dead code and likely returns the wrong state while casting. ReturnplaybackState(orisCasting ? playbackState : state) and remove the unuseduseNowPlaying()call if not needed.
src/components/Player/components/buttons.tsx:33isTrackStoppedOrBufferingis computed as['stopped'].includes(currentState ?? 'stopped'), which (a) treats the normalstoppedstate as “buffering” and shows a spinner instead of a play button, and (b) doesn’t include an actualbuffering/loadingstate if Nitro emits one. Consider checking forbuffering/loadingexplicitly and lettingstoppedrender the play icon.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Comment on lines
+6
to
+14
| export function buildTranscodedAudioApiUrl( | ||
| playbackInfoResponse: PlaybackInfoResponse | undefined, | ||
| ): string { | ||
| const api = getApi() | ||
|
|
||
| if (!api) throw new Error('API instance not found') | ||
|
|
||
| return `${api.basePath}${playbackInfoResponse?.MediaSources?.[0].TranscodingUrl}` | ||
| } |
Comment on lines
+6
to
+12
| export const useIsDownloaded = (trackIds: (string | null | undefined)[]) => { | ||
| const { data: downloadedTracks } = useDownloads() | ||
|
|
||
| return trackIds.every((id) => | ||
| downloadedTracks?.some((download) => download.originalTrack.id === id), | ||
| ) | ||
| } |
Comment on lines
+19
to
+24
| export function getTrackMediaSourceInfo(track: TrackItem | undefined): MediaSourceInfo | undefined { | ||
| const mediaSourceInfo = JSON.parse( | ||
| (track?.extraPayload as TrackExtraPayload)?.mediaSourceInfo ?? '{}', | ||
| ) as MediaSourceInfo | ||
| return mediaSourceInfo | ||
| } |
Comment on lines
+24
to
+46
| let urlParams: Record<string, string> = {} | ||
| let container: string = 'mp3' | ||
|
|
||
| if (playbackInfoResponse?.MediaSources && playbackInfoResponse.MediaSources.length > 0) { | ||
| const mediaSource = playbackInfoResponse.MediaSources[0] | ||
|
|
||
| urlParams = { | ||
| playSessionId: playbackInfoResponse?.PlaySessionId || '', | ||
| startTimeTicks: '0', | ||
| static: 'true', | ||
| } | ||
|
|
||
| if (mediaSource.Container! !== 'mpeg') container = mediaSource.Container! | ||
| } else { | ||
| urlParams = { | ||
| playSessionId: uuid.v4(), | ||
| StartTimeTicks: '0', | ||
| static: 'true', | ||
| } | ||
| } | ||
|
|
||
| return `${api.basePath}/Audio/${item.Id!}/stream?${new URLSearchParams(urlParams)}` | ||
| } |
Comment on lines
+14
to
+17
| export default function getTrackDto(track: TrackItem | undefined): BaseItemDto | undefined { | ||
| const item = JSON.parse((track?.extraPayload as TrackExtraPayload)?.item ?? '{}') as BaseItemDto | ||
| return item | ||
| } |
Comment on lines
+32
to
+35
| export function getTrackArtists(track: TrackItem | undefined): NameGuidPair[] | undefined { | ||
| const item = JSON.parse((track?.extraPayload as TrackExtraPayload)?.item ?? '{}') as BaseItemDto | ||
| return (item?.ArtistItems ?? item?.ArtistItems) || undefined | ||
| } |
Comment on lines
+54
to
+60
| export function getTrackAlbumInfo(track: TrackItem | undefined): NameGuidPair { | ||
| const item = JSON.parse((track?.extraPayload as TrackExtraPayload)?.item ?? '{}') as BaseItemDto | ||
| return { | ||
| Id: item.AlbumId!, | ||
| Name: item.Album, | ||
| } | ||
| } |
Comment on lines
+39
to
+43
| const handleDelete = async () => { | ||
| const result = await deleteSelection() | ||
| if (result?.deletedCount) { | ||
| showDeletionToast(`Deleted ${result.deletedCount} downloads`, result.freedBytes) | ||
| navigation.goBack() | ||
| } | ||
| }, [deleteSelection, navigation, showDeletionToast]) | ||
| showDeletionToast(`Deleted ${selectedDownloads.length} downloads`, 0) | ||
| navigation.goBack() | ||
| } |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is the change
Migrate from
RNTPto Ritesh's fabulousreact-native-nitro-player, powered by Nitro Modules 🔥What does this address
Gapless playback, system audio menu integration, and performance
Issue number / link
Tag reviewers
@anultravioletaurora