Skip to content

Migrate to Nitro Player#969

Open
anultravioletaurora wants to merge 135 commits intomainfrom
feature/nitro-player
Open

Migrate to Nitro Player#969
anultravioletaurora wants to merge 135 commits intomainfrom
feature/nitro-player

Conversation

@anultravioletaurora
Copy link
Member

What is the change

Migrate from RNTP to Ritesh's fabulous react-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

@anultravioletaurora anultravioletaurora linked an issue Feb 4, 2026 that may be closed by this pull request
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 DownloadManager with 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

  • usePlaybackState maintains a local playbackState (including a Google Cast mapping), but the hook always returns useNowPlaying().currentState instead. This makes the Cast state mapping dead code and likely returns the wrong state while casting. Return playbackState (or isCasting ? playbackState : state) and remove the unused useNowPlaying() call if not needed.
    src/components/Player/components/buttons.tsx:33
  • isTrackStoppedOrBuffering is computed as ['stopped'].includes(currentState ?? 'stopped'), which (a) treats the normal stopped state as “buffering” and shows a spinner instead of a play button, and (b) doesn’t include an actual buffering/loading state if Nitro emits one. Consider checking for buffering/loading explicitly and letting stopped render 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()
}
anultravioletaurora and others added 3 commits March 13, 2026 08:36
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
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.

Migrate to React Native Nitro Player

3 participants