diff --git a/app/components/GradientScrollView.tsx b/app/components/GradientScrollView.tsx index 8787770..4d46bc5 100644 --- a/app/components/GradientScrollView.tsx +++ b/app/components/GradientScrollView.tsx @@ -2,10 +2,11 @@ import GradientBackground from '@app/components/GradientBackground' import colors from '@app/styles/colors' import dimensions from '@app/styles/dimensions' import React from 'react' -import { ScrollView, ScrollViewProps, useWindowDimensions } from 'react-native' +import { ScrollViewProps, useWindowDimensions } from 'react-native' +import Animated from 'react-native-reanimated' const GradientScrollView: React.FC< - ScrollViewProps & { + Animated.AnimateProps & { offset?: number } > = props => { @@ -14,14 +15,14 @@ const GradientScrollView: React.FC< const minHeight = layout.height - (dimensions.top() + dimensions.bottom()) return ( - + contentContainerStyle={[props.contentContainerStyle as any, { minHeight }]}> {props.children} - + ) } diff --git a/app/navigation/BottomTabNavigator.tsx b/app/navigation/BottomTabNavigator.tsx index 5b4d44e..2f3154d 100644 --- a/app/navigation/BottomTabNavigator.tsx +++ b/app/navigation/BottomTabNavigator.tsx @@ -90,7 +90,7 @@ function createTabStackNavigator(Component: React.ComponentType) { - + ) diff --git a/app/screens/ArtistView.tsx b/app/screens/ArtistView.tsx index 548d3f5..bb7c685 100644 --- a/app/screens/ArtistView.tsx +++ b/app/screens/ArtistView.tsx @@ -4,16 +4,20 @@ import GradientBackground from '@app/components/GradientBackground' import GradientScrollView from '@app/components/GradientScrollView' import Header from '@app/components/Header' import ListItem from '@app/components/ListItem' +import PressableOpacity from '@app/components/PressableOpacity' import { useArtistInfo } from '@app/hooks/music' import { useSetQueue } from '@app/hooks/trackplayer' import { Album, Song } from '@app/models/music' import colors from '@app/styles/colors' +import dimensions from '@app/styles/dimensions' import font from '@app/styles/font' import { useLayout } from '@react-native-community/hooks' import { useNavigation } from '@react-navigation/native' -import React, { useEffect } from 'react' -import { ActivityIndicator, StyleSheet, Text, View } from 'react-native' +import React, { useCallback } from 'react' +import { ActivityIndicator, StatusBar, StyleSheet, Text, View } from 'react-native' import FastImage from 'react-native-fast-image' +import Animated, { useAnimatedScrollHandler, useAnimatedStyle, useSharedValue } from 'react-native-reanimated' +import IconMat from 'react-native-vector-icons/MaterialIcons' const AlbumItem = React.memo<{ album: Album @@ -70,10 +74,79 @@ const ArtistDetailsFallback = React.memo(() => ( )) -const ArtistDetails: React.FC<{ id: string }> = ({ id }) => { +const NowPlayingHeader = React.memo<{ title: string; animatedOpacity: { opacity: number } }>( + ({ title, animatedOpacity }) => { + const navigation = useNavigation() + + const back = useCallback(() => { + navigation.goBack() + }, [navigation]) + + return ( + + + + + + + {title} + + + {/* + + */} + + ) + }, +) + +const headerStyles = StyleSheet.create({ + container: { + height: dimensions.top(), + paddingTop: StatusBar.currentHeight, + backgroundColor: colors.gradient.high, + width: '100%', + position: 'absolute', + zIndex: 1, + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'space-between', + }, + icons: { + height: 42, + width: 42, + marginHorizontal: 8, + }, + center: { + flex: 1, + }, + queueName: { + fontFamily: font.semiBold, + fontSize: 18, + color: colors.text.primary, + flex: 1, + textAlignVertical: 'center', + paddingLeft: 14, + }, +}) + +const ArtistView = React.memo<{ id: string; title: string }>(({ id, title }) => { const artist = useArtistInfo(id) const albumsLayout = useLayout() const coverLayout = useLayout() + const headerOpacity = useSharedValue(0) + + const onScroll = useAnimatedScrollHandler({ + onScroll: event => { + headerOpacity.value = Math.max(0, event.contentOffset.y - 70) / (artistCoverHeight - (70 + dimensions.header)) + }, + }) + + const animatedOpacity = useAnimatedStyle(() => { + return { + opacity: headerOpacity.value, + } + }) const albumSize = albumsLayout.width / 2 - styles.container.paddingHorizontal / 2 @@ -86,54 +159,53 @@ const ArtistDetails: React.FC<{ id: string }> = ({ id }) => { .sort((a, b) => (b.year || 0) - (a.year || 0)) return ( - - - - {artist.name} - - - {artist.topSongs.length > 0 ? ( - - ) : ( - <> - )} -
Albums
- - {_albums.map(a => ( - - ))} + + + + + + {artist.name} - -
+ + {artist.topSongs.length > 0 ? ( + + ) : ( + <> + )} +
Albums
+ + {_albums.map(a => ( + + ))} + +
+ + ) -} - -const ArtistView = React.memo<{ - id: string - title: string -}>(({ id, title }) => { - const navigation = useNavigation() - - useEffect(() => { - navigation.setOptions({ title }) - }) - - return }) -const artistCoverHeight = 280 +const artistCoverHeight = 350 const styles = StyleSheet.create({ + headerText: { + flex: 1, + textAlign: 'center', + textAlignVertical: 'center', + fontFamily: font.semiBold, + fontSize: 22, + color: colors.text.primary, + }, scroll: { flex: 1, },