mirror of
https://github.com/Jellify-Music/App.git
synced 2025-12-30 15:29:49 -06:00
Detect Background State, Deps Updates (#538)
detect when we are running in the background to pause UI updates, dramatically reducing CPU load and therefore conserving battery life update dependency packages, Pods
This commit is contained in:
@@ -2891,7 +2891,7 @@ PODS:
|
||||
- ReactCommon/turbomodule/core
|
||||
- SocketRocket
|
||||
- Yoga
|
||||
- RNSentry (7.0.1):
|
||||
- RNSentry (7.1.0):
|
||||
- boost
|
||||
- DoubleConversion
|
||||
- fast_float
|
||||
@@ -2918,7 +2918,7 @@ PODS:
|
||||
- ReactCodegen
|
||||
- ReactCommon/turbomodule/bridging
|
||||
- ReactCommon/turbomodule/core
|
||||
- Sentry/HybridSDK (= 8.53.2)
|
||||
- Sentry/HybridSDK (= 8.56.0)
|
||||
- SocketRocket
|
||||
- Yoga
|
||||
- RNWorklets (0.4.1):
|
||||
@@ -3010,7 +3010,7 @@ PODS:
|
||||
- SDWebImage (5.11.1):
|
||||
- SDWebImage/Core (= 5.11.1)
|
||||
- SDWebImage/Core (5.11.1)
|
||||
- Sentry/HybridSDK (8.53.2)
|
||||
- Sentry/HybridSDK (8.56.0)
|
||||
- SocketRocket (0.7.1)
|
||||
- SSZipArchive (2.4.3)
|
||||
- SwiftAudioEx (1.1.0)
|
||||
@@ -3432,10 +3432,10 @@ SPEC CHECKSUMS:
|
||||
RNReactNativeHapticFeedback: be4f1b4bf0398c30b59b76ed92ecb0a2ff3a69c6
|
||||
RNReanimated: ee96d03fe3713993a30cc205522792b4cb08e4f9
|
||||
RNScreens: 0bbf16c074ae6bb1058a7bf2d1ae017f4306797c
|
||||
RNSentry: 6c63debc7b22a00cbf7d1c9ed8de43e336216545
|
||||
RNSentry: 60919c9cdac7e4b35e9f5dd0149f551ec12f35cb
|
||||
RNWorklets: e8335dff9d27004709f58316985769040cd1e8f2
|
||||
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
|
||||
Sentry: 59993bffde4a1ac297ba6d268dc4bbce068d7c1b
|
||||
Sentry: 3d82977434c80381cae856c40b99c39e4be6bc11
|
||||
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
|
||||
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
|
||||
SwiftAudioEx: f6aa653770f3a0d3851edaf8d834a30aee4a7646
|
||||
|
||||
18
package.json
18
package.json
@@ -45,28 +45,28 @@
|
||||
"@react-navigation/material-top-tabs": "^7.3.7",
|
||||
"@react-navigation/native": "^7.1.17",
|
||||
"@react-navigation/native-stack": "^7.3.26",
|
||||
"@sentry/react-native": "7.0.1",
|
||||
"@sentry/react-native": "7.1.0",
|
||||
"@shopify/flash-list": "^2.0.3",
|
||||
"@tamagui/config": "^1.132.23",
|
||||
"@tanstack/query-async-storage-persister": "^5.87.4",
|
||||
"@tanstack/react-query": "^5.87.4",
|
||||
"@tanstack/react-query-persist-client": "^5.87.4",
|
||||
"@tamagui/config": "1.132.25",
|
||||
"@tanstack/query-async-storage-persister": "5.89.0",
|
||||
"@tanstack/react-query": "5.89.0",
|
||||
"@tanstack/react-query-persist-client": "5.89.0",
|
||||
"@testing-library/react-native": "^13.2.3",
|
||||
"@typedigital/telemetrydeck-react": "^0.4.1",
|
||||
"axios": "^1.11.0",
|
||||
"axios": "1.12.2",
|
||||
"bundle": "^2.1.0",
|
||||
"dlx": "^0.2.1",
|
||||
"gem": "^2.4.3",
|
||||
"invert-color": "^2.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"openai": "^5.16.0",
|
||||
"openai": "5.21.0",
|
||||
"react": "19.1.0",
|
||||
"react-native": "0.81.4",
|
||||
"react-native-background-actions": "^4.0.1",
|
||||
"react-native-blob-util": "^0.22.2",
|
||||
"react-native-blurhash": "2.1.1",
|
||||
"react-native-carplay": "^2.4.1-beta.0",
|
||||
"react-native-config": "^1.5.6",
|
||||
"react-native-config": "1.5.6",
|
||||
"react-native-device-info": "^14.0.4",
|
||||
"react-native-dns-lookup": "^1.0.6",
|
||||
"react-native-draggable-flatlist": "^4.0.3",
|
||||
@@ -94,7 +94,7 @@
|
||||
"react-native-worklets": "0.4.1",
|
||||
"ruby": "^0.6.1",
|
||||
"scheduler": "^0.26.0",
|
||||
"tamagui": "^1.132.23",
|
||||
"tamagui": "1.132.25",
|
||||
"zustand": "^5.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3,9 +3,13 @@ import { FrequentlyPlayedArtistsQueryKey, FrequentlyPlayedTracksQueryKey } from
|
||||
import { useJellifyContext } from '../../../providers'
|
||||
import { fetchFrequentlyPlayed, fetchFrequentlyPlayedArtists } from './utils/frequents'
|
||||
import { ApiLimits } from '../query.config'
|
||||
import { queryClient } from '../../../constants/query-client'
|
||||
import { isUndefined } from 'lodash'
|
||||
|
||||
const FREQUENTS_QUERY_CONFIG = {
|
||||
refetchOnMount: false,
|
||||
staleTime: Infinity,
|
||||
} as const
|
||||
|
||||
export const useFrequentlyPlayedTracks = () => {
|
||||
const { api, user, library } = useJellifyContext()
|
||||
|
||||
@@ -18,6 +22,7 @@ export const useFrequentlyPlayedTracks = () => {
|
||||
console.debug('Getting next page for frequently played')
|
||||
return lastPage.length === ApiLimits.Home ? lastPageParam + 1 : undefined
|
||||
},
|
||||
...FREQUENTS_QUERY_CONFIG,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -36,5 +41,6 @@ export const useFrequentlyPlayedArtists = () => {
|
||||
return lastPage.length > 0 ? lastPageParam + 1 : undefined
|
||||
},
|
||||
enabled: !isUndefined(frequentlyPlayedTracks),
|
||||
...FREQUENTS_QUERY_CONFIG,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,9 +3,13 @@ import { RecentlyPlayedArtistsQueryKey, RecentlyPlayedTracksQueryKey } from './k
|
||||
import { useInfiniteQuery } from '@tanstack/react-query'
|
||||
import { fetchRecentlyPlayed, fetchRecentlyPlayedArtists } from './utils'
|
||||
import { ApiLimits } from '../query.config'
|
||||
import { queryClient } from '../../../constants/query-client'
|
||||
import { isUndefined } from 'lodash'
|
||||
|
||||
const RECENTS_QUERY_CONFIG = {
|
||||
refetchOnMount: false,
|
||||
staleTime: Infinity,
|
||||
} as const
|
||||
|
||||
export const useRecentlyPlayedTracks = () => {
|
||||
const { api, user, library } = useJellifyContext()
|
||||
|
||||
@@ -18,6 +22,7 @@ export const useRecentlyPlayedTracks = () => {
|
||||
console.debug('Getting next page for recent tracks')
|
||||
return lastPage.length === ApiLimits.Home ? lastPageParam + 1 : undefined
|
||||
},
|
||||
...RECENTS_QUERY_CONFIG,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -36,5 +41,6 @@ export const useRecentArtists = () => {
|
||||
return lastPage.length > 0 ? lastPageParam + 1 : undefined
|
||||
},
|
||||
enabled: !isUndefined(recentlyPlayedTracks),
|
||||
...RECENTS_QUERY_CONFIG,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import React, { useMemo, useCallback } from 'react'
|
||||
import { getToken, Progress, View, XStack, YStack, ZStack } from 'tamagui'
|
||||
import { getToken, Progress, View, XStack, YStack } from 'tamagui'
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { Text } from '../Global/helpers/text'
|
||||
import TextTicker from 'react-native-text-ticker'
|
||||
import PlayPauseButton from './components/buttons'
|
||||
import { TextTickerConfig } from './component.config'
|
||||
import { useJellifyContext } from '../../providers'
|
||||
import { RunTimeSeconds } from '../Global/helpers/time-codes'
|
||||
import { MINIPLAYER_UPDATE_INTERVAL } from '../../player/config'
|
||||
import { Progress as TrackPlayerProgress } from 'react-native-track-player'
|
||||
@@ -85,66 +84,61 @@ export const Miniplayer = React.memo(function Miniplayer(): React.JSX.Element {
|
||||
|
||||
return (
|
||||
<View testID='miniplayer-test-id'>
|
||||
{nowPlaying && (
|
||||
<GestureDetector gesture={gesture}>
|
||||
<YStack>
|
||||
<MiniPlayerProgress />
|
||||
<XStack paddingBottom={'$1'} alignItems='center' onPress={openPlayer}>
|
||||
<YStack justify='center' alignItems='center' marginLeft={'$2'}>
|
||||
<Animated.View
|
||||
entering={FadeIn}
|
||||
exiting={FadeOut}
|
||||
key={`${nowPlaying!.item.AlbumId}-album-image`}
|
||||
>
|
||||
<ItemImage
|
||||
item={nowPlaying!.item}
|
||||
width={'$12'}
|
||||
height={'$12'}
|
||||
/>
|
||||
</Animated.View>
|
||||
</YStack>
|
||||
|
||||
<YStack
|
||||
alignContent='flex-start'
|
||||
justifyContent='center'
|
||||
marginLeft={'$2'}
|
||||
flex={6}
|
||||
<GestureDetector gesture={gesture}>
|
||||
<YStack>
|
||||
<MiniPlayerProgress />
|
||||
<XStack paddingBottom={'$1'} alignItems='center' onPress={openPlayer}>
|
||||
<YStack justify='center' alignItems='center' marginLeft={'$2'}>
|
||||
<Animated.View
|
||||
entering={FadeIn}
|
||||
exiting={FadeOut}
|
||||
key={`${nowPlaying!.item.AlbumId}-album-image`}
|
||||
>
|
||||
<MiniPlayerRuntime duration={nowPlaying.duration} />
|
||||
<ItemImage item={nowPlaying!.item} width={'$12'} height={'$12'} />
|
||||
</Animated.View>
|
||||
</YStack>
|
||||
|
||||
<Animated.View
|
||||
entering={FadeIn}
|
||||
exiting={FadeOut}
|
||||
key={`${nowPlaying!.item.AlbumId}-mini-player-song-info`}
|
||||
>
|
||||
<View width={'100%'}>
|
||||
<TextTicker {...TextTickerConfig}>
|
||||
<Text bold width={'100%'}>
|
||||
{nowPlaying?.title ?? 'Nothing Playing'}
|
||||
</Text>
|
||||
</TextTicker>
|
||||
<YStack
|
||||
alignContent='flex-start'
|
||||
justifyContent='center'
|
||||
marginLeft={'$2'}
|
||||
flex={6}
|
||||
>
|
||||
<MiniPlayerRuntime duration={nowPlaying!.duration} />
|
||||
|
||||
<TextTicker {...TextTickerConfig}>
|
||||
<Text height={'$0.5'} width={'100%'}>
|
||||
{nowPlaying?.artist ?? ''}
|
||||
</Text>
|
||||
</TextTicker>
|
||||
</View>
|
||||
</Animated.View>
|
||||
</YStack>
|
||||
|
||||
<XStack
|
||||
justifyContent='flex-end'
|
||||
alignItems='center'
|
||||
flex={2}
|
||||
marginRight={'$2'}
|
||||
<Animated.View
|
||||
entering={FadeIn}
|
||||
exiting={FadeOut}
|
||||
key={`${nowPlaying!.item.AlbumId}-mini-player-song-info`}
|
||||
style={{
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<PlayPauseButton size={getToken('$12')} />
|
||||
</XStack>
|
||||
<TextTicker {...TextTickerConfig}>
|
||||
<Text bold width={'100%'}>
|
||||
{nowPlaying?.title ?? 'Nothing Playing'}
|
||||
</Text>
|
||||
</TextTicker>
|
||||
|
||||
<TextTicker {...TextTickerConfig}>
|
||||
<Text height={'$0.5'} width={'100%'}>
|
||||
{nowPlaying?.artist ?? ''}
|
||||
</Text>
|
||||
</TextTicker>
|
||||
</Animated.View>
|
||||
</YStack>
|
||||
|
||||
<XStack
|
||||
justifyContent='flex-end'
|
||||
alignItems='center'
|
||||
flex={2}
|
||||
marginRight={'$2'}
|
||||
>
|
||||
<PlayPauseButton size={getToken('$12')} />
|
||||
</XStack>
|
||||
</YStack>
|
||||
</GestureDetector>
|
||||
)}
|
||||
</XStack>
|
||||
</YStack>
|
||||
</GestureDetector>
|
||||
</View>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -7,8 +7,9 @@ const INFO_CAPTIONS = [
|
||||
|
||||
// Inside Jokes (that the internal Jellify team will get)
|
||||
'Thank you, Pikachu',
|
||||
'Now with 100% more nitro!', // since we use nitro modules
|
||||
'Boosted by Nitro!', // since we use nitro modules
|
||||
'git blame violet', // lol
|
||||
'Made possible by Niels', // O Captain, My Captain!
|
||||
|
||||
// Movie Quotes
|
||||
'Groovy, baby!', // Austin Powers
|
||||
|
||||
@@ -33,6 +33,10 @@ export const queryClient = new QueryClient({
|
||||
*/
|
||||
staleTime: ONE_HOUR * 2,
|
||||
|
||||
refetchIntervalInBackground: false,
|
||||
|
||||
refetchOnWindowFocus: false,
|
||||
|
||||
retry(failureCount: number, error: Error) {
|
||||
if (failureCount > 2) return false
|
||||
|
||||
|
||||
16
src/hooks/use-app-active.ts
Normal file
16
src/hooks/use-app-active.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { AppState } from 'react-native'
|
||||
|
||||
export default function useAppActive() {
|
||||
const [isActive, setIsActive] = useState(AppState.currentState === 'active')
|
||||
|
||||
useEffect(() => {
|
||||
const appStateListener = AppState.addEventListener('change', (state) =>
|
||||
setIsActive(state === 'active'),
|
||||
)
|
||||
|
||||
return () => appStateListener.remove()
|
||||
}, [])
|
||||
|
||||
return isActive
|
||||
}
|
||||
@@ -1,15 +1,11 @@
|
||||
import JellifyTrack from '../../../types/JellifyTrack'
|
||||
import { queryClient } from '../../../constants/query-client'
|
||||
import { Queue } from '../../../player/types/queue-item'
|
||||
import {
|
||||
ACTIVE_INDEX_QUERY_KEY,
|
||||
NOW_PLAYING_QUERY_KEY,
|
||||
PLAY_QUEUE_QUERY_KEY,
|
||||
QUEUE_REF_QUERY_KEY,
|
||||
SHUFFLED_QUERY_KEY,
|
||||
UNSHUFFLED_QUEUE_QUERY_KEY,
|
||||
} from '../constants/query-keys'
|
||||
import { CURRENT_INDEX_QUERY, NOW_PLAYING_QUERY, QUEUE_QUERY } from '../constants/queries'
|
||||
import { CURRENT_INDEX_QUERY, NOW_PLAYING_QUERY } from '../constants/queries'
|
||||
|
||||
export function getActiveIndex(): number | undefined {
|
||||
return queryClient.getQueryData(ACTIVE_INDEX_QUERY_KEY) as number | undefined
|
||||
@@ -32,7 +28,6 @@ export function setPlayQueue(tracks: JellifyTrack[]): void {
|
||||
}
|
||||
|
||||
export function handleActiveTrackChanged(): void {
|
||||
queryClient.invalidateQueries(NOW_PLAYING_QUERY)
|
||||
queryClient.ensureQueryData(QUEUE_QUERY)
|
||||
queryClient.invalidateQueries(CURRENT_INDEX_QUERY)
|
||||
queryClient.refetchQueries(NOW_PLAYING_QUERY)
|
||||
queryClient.refetchQueries(CURRENT_INDEX_QUERY)
|
||||
}
|
||||
|
||||
@@ -2,13 +2,18 @@ import { Miniplayer } from '../../components/Player/mini-player'
|
||||
import InternetConnectionWatcher from '../../components/Network/internetConnectionWatcher'
|
||||
import { useNowPlaying } from '../../providers/Player/hooks/queries'
|
||||
import { BottomTabBar, BottomTabBarProps } from '@react-navigation/bottom-tabs'
|
||||
import useAppActive from '../../hooks/use-app-active'
|
||||
|
||||
export default function TabBar({ ...props }: BottomTabBarProps): React.JSX.Element {
|
||||
const { data: nowPlaying } = useNowPlaying()
|
||||
|
||||
const appIsActive = useAppActive()
|
||||
|
||||
const showMiniPlayer = nowPlaying && appIsActive
|
||||
|
||||
return (
|
||||
<>
|
||||
{nowPlaying && (
|
||||
{showMiniPlayer && (
|
||||
/* Hide miniplayer if the queue is empty */
|
||||
<Miniplayer />
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user