mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-27 00:59:28 +01:00
handle notification click link
also correctly handle back on now playing from app open standardize route names
This commit is contained in:
parent
25cea64f1d
commit
ff0464a156
@ -1,26 +1,17 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.subsonify">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:allowBackup="false"
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustPan">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.subsonify">
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme" android:usesCleartextTraffic="true">
|
||||
<activity android:name=".MainActivity" android:label="@string/app_name" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustPan">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="trackplayer"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
@ -1,5 +1,4 @@
|
||||
import React from 'react'
|
||||
import { DarkTheme, NavigationContainer } from '@react-navigation/native'
|
||||
import SplashPage from '@app/screens/SplashPage'
|
||||
import RootNavigator from '@app/navigation/RootNavigator'
|
||||
import { Provider } from 'jotai'
|
||||
@ -7,18 +6,13 @@ import { StatusBar, View } from 'react-native'
|
||||
import colors from '@app/styles/colors'
|
||||
import TrackPlayerState from '@app/components/TrackPlayerState'
|
||||
|
||||
const theme = { ...DarkTheme }
|
||||
theme.colors.background = colors.gradient.high
|
||||
|
||||
const App = () => (
|
||||
<Provider>
|
||||
<StatusBar animated={true} backgroundColor={'rgba(0, 0, 0, 0.4)'} barStyle={'light-content'} translucent={true} />
|
||||
<TrackPlayerState />
|
||||
<View style={{ flex: 1, backgroundColor: colors.gradient.high }}>
|
||||
<SplashPage>
|
||||
<NavigationContainer theme={theme}>
|
||||
<RootNavigator />
|
||||
</NavigationContainer>
|
||||
<RootNavigator />
|
||||
</SplashPage>
|
||||
</View>
|
||||
</Provider>
|
||||
|
||||
@ -57,13 +57,13 @@ const ListItem: React.FC<{
|
||||
if (!onPress) {
|
||||
switch (item.itemType) {
|
||||
case 'album':
|
||||
onPress = () => navigation.navigate('AlbumView', { id: item.id, title: item.name })
|
||||
onPress = () => navigation.navigate('album', { id: item.id, title: item.name })
|
||||
break
|
||||
case 'artist':
|
||||
onPress = () => navigation.navigate('ArtistView', { id: item.id, title: item.name })
|
||||
onPress = () => navigation.navigate('artist', { id: item.id, title: item.name })
|
||||
break
|
||||
case 'playlist':
|
||||
onPress = () => navigation.navigate('PlaylistView', { id: item.id, title: item.name })
|
||||
onPress = () => navigation.navigate('playlist', { id: item.id, title: item.name })
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +64,7 @@ const NowPlayingBar = () => {
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
onPress={() => navigation.navigate('NowPlaying')}
|
||||
onPress={() => navigation.navigate('now-playing')}
|
||||
style={{ ...styles.container, display: track ? 'flex' : 'none' }}>
|
||||
<ProgressBar />
|
||||
<View style={styles.subContainer}>
|
||||
|
||||
@ -15,14 +15,14 @@ import { StyleSheet } from 'react-native'
|
||||
import { createNativeStackNavigator, NativeStackNavigationProp } from 'react-native-screens/native-stack'
|
||||
|
||||
type TabStackParamList = {
|
||||
TabMain: { toTop?: boolean }
|
||||
AlbumView: { id: string; title: string }
|
||||
ArtistView: { id: string; title: string }
|
||||
PlaylistView: { id: string; title: string }
|
||||
main: { toTop?: boolean }
|
||||
album: { id: string; title: string }
|
||||
artist: { id: string; title: string }
|
||||
playlist: { id: string; title: string }
|
||||
}
|
||||
|
||||
type AlbumScreenNavigationProp = NativeStackNavigationProp<TabStackParamList, 'AlbumView'>
|
||||
type AlbumScreenRouteProp = RouteProp<TabStackParamList, 'AlbumView'>
|
||||
type AlbumScreenNavigationProp = NativeStackNavigationProp<TabStackParamList, 'album'>
|
||||
type AlbumScreenRouteProp = RouteProp<TabStackParamList, 'album'>
|
||||
type AlbumScreenProps = {
|
||||
route: AlbumScreenRouteProp
|
||||
navigation: AlbumScreenNavigationProp
|
||||
@ -32,8 +32,8 @@ const AlbumScreen: React.FC<AlbumScreenProps> = ({ route }) => (
|
||||
<AlbumView id={route.params.id} title={route.params.title} />
|
||||
)
|
||||
|
||||
type ArtistScreenNavigationProp = NativeStackNavigationProp<TabStackParamList, 'ArtistView'>
|
||||
type ArtistScreenRouteProp = RouteProp<TabStackParamList, 'ArtistView'>
|
||||
type ArtistScreenNavigationProp = NativeStackNavigationProp<TabStackParamList, 'artist'>
|
||||
type ArtistScreenRouteProp = RouteProp<TabStackParamList, 'artist'>
|
||||
type ArtistScreenProps = {
|
||||
route: ArtistScreenRouteProp
|
||||
navigation: ArtistScreenNavigationProp
|
||||
@ -43,8 +43,8 @@ const ArtistScreen: React.FC<ArtistScreenProps> = ({ route }) => (
|
||||
<ArtistView id={route.params.id} title={route.params.title} />
|
||||
)
|
||||
|
||||
type PlaylistScreenNavigationProp = NativeStackNavigationProp<TabStackParamList, 'PlaylistView'>
|
||||
type PlaylistScreenRouteProp = RouteProp<TabStackParamList, 'PlaylistView'>
|
||||
type PlaylistScreenNavigationProp = NativeStackNavigationProp<TabStackParamList, 'playlist'>
|
||||
type PlaylistScreenRouteProp = RouteProp<TabStackParamList, 'playlist'>
|
||||
type PlaylistScreenProps = {
|
||||
route: PlaylistScreenRouteProp
|
||||
navigation: PlaylistScreenNavigationProp
|
||||
@ -86,11 +86,11 @@ function createTabStackNavigator(Component: React.ComponentType<any>) {
|
||||
})
|
||||
|
||||
return (
|
||||
<Stack.Navigator>
|
||||
<Stack.Screen name="TabMain" component={Component} options={{ headerShown: false }} />
|
||||
<Stack.Screen name="AlbumView" component={AlbumScreen} options={itemScreenOptions} />
|
||||
<Stack.Screen name="ArtistView" component={ArtistScreen} options={itemScreenOptions} />
|
||||
<Stack.Screen name="PlaylistView" component={PlaylistScreen} options={itemScreenOptions} />
|
||||
<Stack.Navigator initialRouteName="main">
|
||||
<Stack.Screen name="main" component={Component} options={{ headerShown: false }} />
|
||||
<Stack.Screen name="album" component={AlbumScreen} options={itemScreenOptions} />
|
||||
<Stack.Screen name="artist" component={ArtistScreen} options={itemScreenOptions} />
|
||||
<Stack.Screen name="playlist" component={PlaylistScreen} options={itemScreenOptions} />
|
||||
</Stack.Navigator>
|
||||
)
|
||||
}
|
||||
@ -106,11 +106,11 @@ const Tab = createBottomTabNavigator()
|
||||
|
||||
const BottomTabNavigator = () => {
|
||||
return (
|
||||
<Tab.Navigator tabBar={BottomTabBar}>
|
||||
<Tab.Screen name="Home" component={HomeTab} options={{ icon: 'home' } as any} />
|
||||
<Tab.Screen name="Library" component={LibraryTab} options={{ icon: 'library' } as any} />
|
||||
<Tab.Screen name="Search" component={SearchTab} options={{ icon: 'search' } as any} />
|
||||
<Tab.Screen name="Settings" component={SettingsView} options={{ icon: 'settings' } as any} />
|
||||
<Tab.Navigator tabBar={BottomTabBar} initialRouteName="home">
|
||||
<Tab.Screen name="home" component={HomeTab} options={{ icon: 'home' } as any} />
|
||||
<Tab.Screen name="library" component={LibraryTab} options={{ icon: 'library' } as any} />
|
||||
<Tab.Screen name="search" component={SearchTab} options={{ icon: 'search' } as any} />
|
||||
<Tab.Screen name="settings" component={SettingsView} options={{ icon: 'settings' } as any} />
|
||||
</Tab.Navigator>
|
||||
)
|
||||
}
|
||||
|
||||
@ -16,10 +16,11 @@ const LibraryTopTabNavigator = () => (
|
||||
style: styles.tabBar,
|
||||
labelStyle: styles.tablabelStyle,
|
||||
indicatorStyle: styles.tabindicatorStyle,
|
||||
}}>
|
||||
<Tab.Screen name="Albums" component={AlbumsTab} />
|
||||
<Tab.Screen name="Artists" component={ArtistsTab} />
|
||||
<Tab.Screen name="Playlists" component={PlaylistsTab} />
|
||||
}}
|
||||
initialRouteName="albums">
|
||||
<Tab.Screen name="albums" component={AlbumsTab} />
|
||||
<Tab.Screen name="artists" component={ArtistsTab} />
|
||||
<Tab.Screen name="playlists" component={PlaylistsTab} />
|
||||
</Tab.Navigator>
|
||||
)
|
||||
|
||||
|
||||
@ -1,18 +1,40 @@
|
||||
import BottomTabNavigator from '@app/navigation/BottomTabNavigator'
|
||||
import NowPlayingLayout from '@app/screens/NowPlayingLayout'
|
||||
import colors from '@app/styles/colors'
|
||||
import { DarkTheme, NavigationContainer } from '@react-navigation/native'
|
||||
import React from 'react'
|
||||
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
|
||||
import NowPlayingLayout from '@app/screens/NowPlayingLayout'
|
||||
import BottomTabNavigator from '@app/navigation/BottomTabNavigator'
|
||||
|
||||
const RootStack = createNativeStackNavigator()
|
||||
|
||||
const theme = { ...DarkTheme }
|
||||
theme.colors.background = colors.gradient.high
|
||||
|
||||
const RootNavigator = () => (
|
||||
<RootStack.Navigator
|
||||
screenOptions={{
|
||||
headerShown: false,
|
||||
<NavigationContainer
|
||||
theme={theme}
|
||||
linking={{
|
||||
prefixes: ['trackplayer'],
|
||||
config: {
|
||||
screens: {
|
||||
main: {
|
||||
path: ':/main',
|
||||
},
|
||||
'now-playing': {
|
||||
path: ':/notification.click',
|
||||
},
|
||||
},
|
||||
},
|
||||
}}>
|
||||
<RootStack.Screen name="Main" component={BottomTabNavigator} />
|
||||
<RootStack.Screen name="NowPlaying" component={NowPlayingLayout} />
|
||||
</RootStack.Navigator>
|
||||
<RootStack.Navigator
|
||||
screenOptions={{
|
||||
headerShown: false,
|
||||
}}
|
||||
initialRouteName="main">
|
||||
<RootStack.Screen name="main" component={BottomTabNavigator} />
|
||||
<RootStack.Screen name="now-playing" component={NowPlayingLayout} />
|
||||
</RootStack.Navigator>
|
||||
</NavigationContainer>
|
||||
)
|
||||
|
||||
export default RootNavigator
|
||||
|
||||
@ -24,7 +24,7 @@ const AlbumItem = React.memo<{
|
||||
|
||||
return (
|
||||
<PressableOpacity
|
||||
onPress={() => navigation.navigate('AlbumView', { id: album.id, title: album.name })}
|
||||
onPress={() => navigation.navigate('album', { id: album.id, title: album.name })}
|
||||
style={[styles.albumItem, { width }]}>
|
||||
<CoverArt coverArt={album.coverArt} style={{ height, width }} />
|
||||
<Text style={styles.albumTitle}>{album.name}</Text>
|
||||
|
||||
@ -28,7 +28,7 @@ const AlbumItem = React.memo<{
|
||||
|
||||
return (
|
||||
<PressableOpacity
|
||||
onPress={() => navigation.navigate('AlbumView', { id: album.id, title: album.name })}
|
||||
onPress={() => navigation.navigate('album', { id: album.id, title: album.name })}
|
||||
key={album.id}
|
||||
style={styles.item}>
|
||||
<CoverArt coverArt={album.coverArt} style={{ height: styles.item.width, width: styles.item.width }} />
|
||||
|
||||
@ -24,7 +24,7 @@ const AlbumItem = React.memo<{
|
||||
return (
|
||||
<PressableOpacity
|
||||
style={[styles.item, { maxWidth: size, height }]}
|
||||
onPress={() => navigation.navigate('AlbumView', { id, title: name })}>
|
||||
onPress={() => navigation.navigate('album', { id, title: name })}>
|
||||
<CoverArt coverArt={coverArt} style={{ height: size, width: size }} />
|
||||
<View style={styles.itemDetails}>
|
||||
<Text style={styles.title} numberOfLines={1}>
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { useNavigation } from '@react-navigation/native'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import React, { useEffect } from 'react'
|
||||
import { StatusBar, StyleSheet, Text, View } from 'react-native'
|
||||
import React, { useCallback, useEffect } from 'react'
|
||||
import { BackHandler, StatusBar, StyleSheet, Text, View } from 'react-native'
|
||||
import { State } from 'react-native-track-player'
|
||||
import IconFA from 'react-native-vector-icons/FontAwesome'
|
||||
import IconFA5 from 'react-native-vector-icons/FontAwesome5'
|
||||
@ -28,14 +27,17 @@ import ImageGradientBackground from '@app/components/ImageGradientBackground'
|
||||
import PressableOpacity from '@app/components/PressableOpacity'
|
||||
import dimensions from '@app/styles/dimensions'
|
||||
import { NativeStackScreenProps } from 'react-native-screens/native-stack'
|
||||
import { useFocusEffect } from '@react-navigation/native'
|
||||
|
||||
const NowPlayingHeader = () => {
|
||||
// eslint-disable-next-line no-spaced-func
|
||||
const NowPlayingHeader = React.memo<{
|
||||
backHandler: () => void
|
||||
}>(({ backHandler }) => {
|
||||
const queueName = useAtomValue(queueNameAtom)
|
||||
const navigation = useNavigation()
|
||||
|
||||
return (
|
||||
<View style={headerStyles.container}>
|
||||
<PressableOpacity onPress={() => navigation.goBack()} style={headerStyles.icons} ripple={true}>
|
||||
<PressableOpacity onPress={backHandler} style={headerStyles.icons} ripple={true}>
|
||||
<IconMat name="arrow-back" color="white" size={25} />
|
||||
</PressableOpacity>
|
||||
<Text numberOfLines={1} style={headerStyles.queueName}>
|
||||
@ -46,7 +48,7 @@ const NowPlayingHeader = () => {
|
||||
</PressableOpacity>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
const headerStyles = StyleSheet.create({
|
||||
container: {
|
||||
@ -302,24 +304,41 @@ const controlsStyles = StyleSheet.create({
|
||||
})
|
||||
|
||||
type RootStackParamList = {
|
||||
Main: undefined
|
||||
NowPlaying: undefined
|
||||
main: undefined
|
||||
'now-playing': undefined
|
||||
}
|
||||
type NowPlayingProps = NativeStackScreenProps<RootStackParamList, 'NowPlaying'>
|
||||
type NowPlayingProps = NativeStackScreenProps<RootStackParamList, 'now-playing'>
|
||||
|
||||
const NowPlayingLayout: React.FC<NowPlayingProps> = ({ navigation }) => {
|
||||
const track = useAtomValue(currentTrackAtom)
|
||||
|
||||
useEffect(() => {
|
||||
if (!track && navigation.canGoBack()) {
|
||||
const back = useCallback(() => {
|
||||
if (navigation.canGoBack()) {
|
||||
navigation.popToTop()
|
||||
} else {
|
||||
navigation.navigate('main')
|
||||
}
|
||||
return true
|
||||
}, [navigation])
|
||||
|
||||
useEffect(() => {
|
||||
if (!track) {
|
||||
back()
|
||||
}
|
||||
})
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
BackHandler.addEventListener('hardwareBackPress', back)
|
||||
|
||||
return () => BackHandler.removeEventListener('hardwareBackPress', back)
|
||||
}, [back]),
|
||||
)
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<ImageGradientBackground imageUri={track?.artwork as string} imageKey={`${track?.album}${track?.artist}`} />
|
||||
<NowPlayingHeader />
|
||||
<NowPlayingHeader backHandler={back} />
|
||||
<View style={styles.content}>
|
||||
<SongCoverArt />
|
||||
<SongInfo />
|
||||
|
||||
@ -18,7 +18,7 @@ const TestControls = () => {
|
||||
return (
|
||||
<View>
|
||||
<Button title="Remove all keys" onPress={removeAllKeys} />
|
||||
<Button title="Now Playing" onPress={() => navigation.navigate('NowPlaying')} />
|
||||
<Button title="Now Playing" onPress={() => navigation.navigate('now-playing')} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
@ -55,7 +55,8 @@
|
||||
"jest": "^26.6.3",
|
||||
"metro-react-native-babel-preset": "^0.64.0",
|
||||
"react-test-renderer": "17.0.1",
|
||||
"typescript": "^3.8.3"
|
||||
"typescript": "^3.8.3",
|
||||
"uri-scheme": "^1.0.91"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "^17"
|
||||
|
||||
@ -6718,6 +6718,11 @@ uri-js@^4.2.2:
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
uri-scheme@^1.0.91:
|
||||
version "1.0.91"
|
||||
resolved "https://registry.yarnpkg.com/uri-scheme/-/uri-scheme-1.0.91.tgz#9169b7d4ab421f29fc6576885b30a7be4e39780e"
|
||||
integrity sha512-/vy0dGnTgiojTGiV9QzmTy79HT4Xn2x1ee+rs8Geiav0w16Ayme2aRg5W71GcARB2ck/fYrxDZBIPlntVbwKuQ==
|
||||
|
||||
urix@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user