mirror of
https://github.com/Jellify-Music/App.git
synced 2026-03-17 18:51:24 -05:00
defer non-critical startup operations
- delay StorageProvider queries until 2s after initial render - defer player queue restoration with InteractionManager - add enabled option to download query hooks
This commit is contained in:
@@ -3,13 +3,22 @@ import { useQuery } from '@tanstack/react-query'
|
||||
import fetchStorageInUse from './utils/storage-in-use'
|
||||
import { AUDIO_CACHE_QUERY } from './constants'
|
||||
|
||||
export const useStorageInUse = () =>
|
||||
type QueryOptions = {
|
||||
enabled?: boolean
|
||||
}
|
||||
|
||||
export const useStorageInUse = (options?: QueryOptions) =>
|
||||
useQuery({
|
||||
queryKey: [QueryKeys.StorageInUse],
|
||||
queryFn: fetchStorageInUse,
|
||||
enabled: options?.enabled,
|
||||
})
|
||||
|
||||
export const useAllDownloadedTracks = () => useQuery(AUDIO_CACHE_QUERY)
|
||||
export const useAllDownloadedTracks = (options?: QueryOptions) =>
|
||||
useQuery({
|
||||
...AUDIO_CACHE_QUERY,
|
||||
enabled: options?.enabled,
|
||||
})
|
||||
|
||||
export const useDownloadedTracks = (itemIds: (string | null | undefined)[]) =>
|
||||
useAllDownloadedTracks().data?.filter((download) => itemIds.includes(download.item.Id))
|
||||
|
||||
@@ -1,48 +1,55 @@
|
||||
import { isUndefined } from 'lodash'
|
||||
import { InteractionManager } from 'react-native'
|
||||
import TrackPlayer, { RepeatMode } from 'react-native-track-player'
|
||||
import { usePlayerQueueStore } from '../../../stores/player/queue'
|
||||
import { createMMKV } from 'react-native-mmkv'
|
||||
|
||||
export default async function Initialize() {
|
||||
const {
|
||||
queue: persistedQueue,
|
||||
currentIndex: persistedIndex,
|
||||
repeatMode,
|
||||
} = usePlayerQueueStore.getState()
|
||||
export default function Initialize() {
|
||||
// Defer queue restoration until after UI interactions complete
|
||||
// This allows the home screen to render faster on cold start
|
||||
InteractionManager.runAfterInteractions(async () => {
|
||||
const {
|
||||
queue: persistedQueue,
|
||||
currentIndex: persistedIndex,
|
||||
repeatMode,
|
||||
} = usePlayerQueueStore.getState()
|
||||
|
||||
// Read saved position BEFORE reset() to prevent it from being cleared
|
||||
const progressStorage = createMMKV({ id: 'progress_storage' })
|
||||
const savedPosition = progressStorage.getNumber('player-key') ?? 0
|
||||
console.log('savedPosition before reset', savedPosition)
|
||||
// Read saved position BEFORE reset() to prevent it from being cleared
|
||||
const progressStorage = createMMKV({ id: 'progress_storage' })
|
||||
const savedPosition = progressStorage.getNumber('player-key') ?? 0
|
||||
console.log('savedPosition before reset', savedPosition)
|
||||
|
||||
const storedPlayQueue = persistedQueue.length > 0 ? persistedQueue : undefined
|
||||
const storedIndex = persistedIndex
|
||||
const storedPlayQueue = persistedQueue.length > 0 ? persistedQueue : undefined
|
||||
const storedIndex = persistedIndex
|
||||
|
||||
if (
|
||||
Array.isArray(storedPlayQueue) &&
|
||||
storedPlayQueue.length > 0 &&
|
||||
!isUndefined(storedIndex) &&
|
||||
storedIndex !== null
|
||||
) {
|
||||
await TrackPlayer.reset()
|
||||
await TrackPlayer.add(storedPlayQueue)
|
||||
await TrackPlayer.skip(storedIndex)
|
||||
if (
|
||||
Array.isArray(storedPlayQueue) &&
|
||||
storedPlayQueue.length > 0 &&
|
||||
!isUndefined(storedIndex) &&
|
||||
storedIndex !== null
|
||||
) {
|
||||
await TrackPlayer.reset()
|
||||
await TrackPlayer.add(storedPlayQueue)
|
||||
await TrackPlayer.skip(storedIndex)
|
||||
|
||||
usePlayerQueueStore.getState().setQueue(storedPlayQueue)
|
||||
usePlayerQueueStore.getState().setCurrentIndex(storedIndex)
|
||||
usePlayerQueueStore.getState().setCurrentTrack(storedPlayQueue[storedIndex] ?? undefined)
|
||||
}
|
||||
|
||||
const restoredRepeatMode = repeatMode ?? RepeatMode.Off
|
||||
await TrackPlayer.setRepeatMode(restoredRepeatMode)
|
||||
|
||||
// Restore saved playback position after queue is loaded
|
||||
if (savedPosition > 0) {
|
||||
try {
|
||||
await TrackPlayer.seekTo(savedPosition)
|
||||
console.log('Restored playback position:', savedPosition)
|
||||
} catch (error) {
|
||||
console.warn('Failed to restore playback position:', error)
|
||||
usePlayerQueueStore.getState().setQueue(storedPlayQueue)
|
||||
usePlayerQueueStore.getState().setCurrentIndex(storedIndex)
|
||||
usePlayerQueueStore
|
||||
.getState()
|
||||
.setCurrentTrack(storedPlayQueue[storedIndex] ?? undefined)
|
||||
}
|
||||
}
|
||||
|
||||
const restoredRepeatMode = repeatMode ?? RepeatMode.Off
|
||||
await TrackPlayer.setRepeatMode(restoredRepeatMode)
|
||||
|
||||
// Restore saved playback position after queue is loaded
|
||||
if (savedPosition > 0) {
|
||||
try {
|
||||
await TrackPlayer.seekTo(savedPosition)
|
||||
console.log('Restored playback position:', savedPosition)
|
||||
} catch (error) {
|
||||
console.warn('Failed to restore playback position:', error)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import React, { PropsWithChildren, createContext, use, useContext, useState } from 'react'
|
||||
import React, {
|
||||
PropsWithChildren,
|
||||
createContext,
|
||||
use,
|
||||
useContext,
|
||||
useState,
|
||||
useEffect,
|
||||
} from 'react'
|
||||
import { useAllDownloadedTracks, useStorageInUse } from '../../api/queries/download'
|
||||
import { JellifyDownload, JellifyDownloadProgress } from '../../types/JellifyDownload'
|
||||
import {
|
||||
@@ -57,16 +64,24 @@ const sumDownloadBytes = (download: JellifyDownload | undefined) => {
|
||||
}
|
||||
|
||||
export function StorageProvider({ children }: PropsWithChildren): React.JSX.Element {
|
||||
// Defer storage queries until after initial app render to improve cold start time
|
||||
const [shouldFetch, setShouldFetch] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => setShouldFetch(true), 2000)
|
||||
return () => clearTimeout(timer)
|
||||
}, [])
|
||||
|
||||
const {
|
||||
data: downloads,
|
||||
refetch: refetchDownloads,
|
||||
isFetching: isFetchingDownloads,
|
||||
} = useAllDownloadedTracks()
|
||||
} = useAllDownloadedTracks({ enabled: shouldFetch })
|
||||
const {
|
||||
data: storageInfo,
|
||||
refetch: refetchStorageInfo,
|
||||
isFetching: isFetchingStorage,
|
||||
} = useStorageInUse()
|
||||
} = useStorageInUse({ enabled: shouldFetch })
|
||||
const activeDownloads = useDownloadProgress()
|
||||
|
||||
const [selection, setSelection] = useState<StorageSelectionState>({})
|
||||
|
||||
Reference in New Issue
Block a user