Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 1 addition & 36 deletions packages/mobile/src/screens/app-screen/AccountPictureHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,20 @@
import { useCurrentUserId } from '@audius/common/api'
import {
useAccountHasClaimableRewards,
useRemoteVar
} from '@audius/common/hooks'
import { StringKeys } from '@audius/common/services'
import { chatSelectors } from '@audius/common/store'
import { useDrawerProgress } from '@react-navigation/drawer'
import type { StyleProp, ViewStyle } from 'react-native'
import { View } from 'react-native'
import { TouchableOpacity } from 'react-native-gesture-handler'
import Animated, {
interpolate,
useAnimatedStyle
} from 'react-native-reanimated'
import type { SharedValue } from 'react-native-reanimated'
import { useSelector } from 'react-redux'

import { ProfilePicture } from 'app/components/core'
import { makeStyles } from 'app/styles'

const { getHasUnreadMessages } = chatSelectors

const useStyles = makeStyles(({ spacing, palette }) => ({
const useStyles = makeStyles(({ spacing }) => ({
root: {
height: spacing(8) + 2,
width: spacing(8) + 2
},
notificationBubbleRoot: {
height: spacing(4),
width: spacing(4),
borderColor: palette.white,
borderWidth: 2,
borderRadius: 10,
position: 'absolute',
top: 0,
right: 0
},
notificationBubble: {
flex: 1,
backgroundColor: palette.secondary,
overflow: 'hidden',
borderRadius: 10
}
}))

Expand All @@ -54,10 +28,6 @@ export const AccountPictureHeader = (props: AccountPictureHeaderProps) => {
const drawerProgress = useDrawerProgress() as SharedValue<number>
const styles = useStyles()
const { data: accountId } = useCurrentUserId()
const challengeRewardIds = useRemoteVar(StringKeys.CHALLENGE_REWARD_IDS)
const hasClaimableRewards = useAccountHasClaimableRewards(challengeRewardIds)
const hasUnreadMessages = useSelector(getHasUnreadMessages)
const showNotificationBubble = hasClaimableRewards || hasUnreadMessages

const animatedStyle = useAnimatedStyle(() => ({
opacity: interpolate(drawerProgress.value, [0, 1], [1, 0])
Expand All @@ -71,11 +41,6 @@ export const AccountPictureHeader = (props: AccountPictureHeaderProps) => {
style={styles.root}
borderWidth='thin'
/>
{showNotificationBubble ? (
<View style={styles.notificationBubbleRoot}>
<View style={styles.notificationBubble} />
</View>
) : null}
</TouchableOpacity>
</Animated.View>
)
Expand Down
94 changes: 94 additions & 0 deletions packages/mobile/src/screens/app-screen/MobileRootHeader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import type { ReactNode } from 'react'
import { useCallback, useContext } from 'react'

import { View } from 'react-native'
import { useSafeAreaInsets } from 'react-native-safe-area-context'

import { IconAudiusLogoHorizontal } from '@audius/harmony-native'
import { GradientText } from 'app/components/core'
import { useDrawer } from 'app/hooks/useDrawer'
import { makeStyles } from 'app/styles'

import { AppDrawerContext } from '../app-drawer-screen'

import { AccountPictureHeader } from './AccountPictureHeader'

type MobileRootHeaderProps = {
title: string
children?: ReactNode
showDivider?: boolean
}

const useStyles = makeStyles(({ palette, spacing, typography }) => ({
container: {
backgroundColor: palette.white
},
logoContainer: {
position: 'absolute',
alignSelf: 'center',
top: 22,
width: 78,
height: 16,
opacity: 0.45
},
row: {
flexDirection: 'row',
alignItems: 'center',
gap: spacing(4),
paddingHorizontal: spacing(4),
paddingVertical: spacing(3)
},
title: {
fontSize: 24,
lineHeight: 32,
fontFamily: typography.fontByWeight.heavy
},
titleContainer: {
flex: 1,
minWidth: 0
},
divider: {
height: 1,
backgroundColor: palette.neutralLight8
}
}))

/**
* Custom header for root (bottom-bar) tab screens.
*
* Layout (single row): [Avatar] [GradientText title] [right content]
*
* Audius logo is positioned in the status bar area (under dynamic island)
* at low opacity so it appears in screenshots but is hidden behind the
* system chrome during normal use.
*/
export const MobileRootHeader = (props: MobileRootHeaderProps) => {
const { title, children, showDivider = true } = props
const insets = useSafeAreaInsets()
const styles = useStyles()
const { drawerHelpers } = useContext(AppDrawerContext)
const { isOpen: isNowPlayingDrawerOpen } = useDrawer('NowPlaying')

const handleOpenLeftNavDrawer = useCallback(() => {
if (isNowPlayingDrawerOpen) return
drawerHelpers?.openDrawer()
}, [drawerHelpers, isNowPlayingDrawerOpen])

return (
<View style={styles.container}>
<View style={styles.logoContainer}>
<IconAudiusLogoHorizontal height={16} width={78} color='subdued' />
</View>
<View style={[styles.row, { marginTop: insets.top }]}>
<AccountPictureHeader onPress={handleOpenLeftNavDrawer} />
<View style={styles.titleContainer}>
<GradientText accessibilityRole='header' style={styles.title}>
{title}
</GradientText>
</View>
{children}
</View>
{showDivider ? <View style={styles.divider} /> : null}
</View>
)
}
6 changes: 5 additions & 1 deletion packages/mobile/src/screens/feed-screen/FeedFilterButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ export const FeedFilterButton = () => {
}, [dispatch])

return (
<ScreenHeaderButton onPress={handlePress} label={messageMap[feedFilter]} />
<ScreenHeaderButton
onPress={handlePress}
label={messageMap[feedFilter]}
size='large'
/>
)
}
20 changes: 12 additions & 8 deletions packages/mobile/src/screens/feed-screen/FeedScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
} from '@audius/common/store'
import { useDispatch } from 'react-redux'

import { IconFeed } from '@audius/harmony-native'
import { Screen, ScreenContent, ScreenHeader } from 'app/components/core'
import { Screen, ScreenContent } from 'app/components/core'
import { Lineup } from 'app/components/lineup'
import { EndOfLineupNotice } from 'app/components/lineup/EndOfLineupNotice'
import { OnlineOnly } from 'app/components/offline-placeholder/OnlineOnly'
import { SuggestedFollows } from 'app/components/suggested-follows'
import { useAppTabScreen } from 'app/hooks/useAppTabScreen'
import { MobileRootHeader } from 'app/screens/app-screen/MobileRootHeader'

import { FeedFilterButton } from './FeedFilterButton'
const { getDiscoverFeedLineup } = feedPageSelectors
Expand All @@ -39,12 +39,16 @@ export const FeedScreen = () => {
)

return (
<Screen url='Feed'>
<ScreenHeader text={messages.header} icon={IconFeed}>
<OnlineOnly>
<FeedFilterButton />
</OnlineOnly>
</ScreenHeader>
<Screen
url='Feed'
header={() => (
<MobileRootHeader title={messages.header} showDivider={false}>
<OnlineOnly>
<FeedFilterButton />
</OnlineOnly>
</MobileRootHeader>
)}
>
<ScreenContent>
<Lineup
pullToRefresh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ const { setSelectedCategory } = libraryPageActions
const useStyles = makeStyles(({ spacing }) => ({
container: {
flexGrow: 1,
flexDirection: 'row',
marginTop: spacing(3)
flexDirection: 'row'
},
scrollContainer: {
columnGap: spacing(2)
columnGap: spacing(2),
paddingHorizontal: spacing(4),
paddingBottom: spacing(2)
}
}))

Expand Down Expand Up @@ -130,6 +131,7 @@ export const LibraryCategorySelectionMenu = () => {
<View style={styles.container}>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
accessibilityRole='radiogroup'
contentContainerStyle={styles.scrollContainer}
alwaysBounceHorizontal={false}
Expand All @@ -140,6 +142,7 @@ export const LibraryCategorySelectionMenu = () => {
<SelectablePill
key={value}
type='radio'
size='large'
label={label}
value={value}
onChange={handleChange}
Expand Down
38 changes: 17 additions & 21 deletions packages/mobile/src/screens/library-screen/LibraryScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { LibraryPageTabs } from '@audius/common/store'
import { View } from 'react-native'

import {
IconAlbum,
IconLibrary,
IconNote,
IconPlaylists
} from '@audius/harmony-native'
import { Screen, ScreenContent, ScreenHeader } from 'app/components/core'
import { IconAlbum, IconNote, IconPlaylists } from '@audius/harmony-native'
import { Screen, ScreenContent } from 'app/components/core'
import { ScreenPrimaryContent } from 'app/components/core/Screen/ScreenPrimaryContent'
import { ScreenSecondaryContent } from 'app/components/core/Screen/ScreenSecondaryContent'
import { TopTabNavigator } from 'app/components/top-tab-bar'
import { useAppTabScreen } from 'app/hooks/useAppTabScreen'
import { MobileRootHeader } from 'app/screens/app-screen/MobileRootHeader'
import { makeStyles } from 'app/styles'

import { AlbumsTab } from './AlbumsTab'
Expand Down Expand Up @@ -41,29 +38,28 @@ const libraryScreens = [
}
]

const useHeaderStyles = makeStyles(({ spacing }) => ({
root: {
flexWrap: 'wrap',
height: 88,
paddingVertical: spacing(2)
const useStyles = makeStyles(({ palette }) => ({
subHeader: {
backgroundColor: palette.white
}
}))

export const LibraryScreen = () => {
useAppTabScreen()
const headerStyles = useHeaderStyles()
const styles = useStyles()

return (
<Screen>
<ScreenPrimaryContent>
<ScreenHeader
text={messages.header}
icon={IconLibrary}
styles={headerStyles}
>
<Screen
header={() => (
<MobileRootHeader title={messages.header} showDivider={false}>
<LibraryDownloadSection />
</MobileRootHeader>
)}
>
<ScreenPrimaryContent>
<View style={styles.subHeader}>
<LibraryCategorySelectionMenu />
</ScreenHeader>
</View>
</ScreenPrimaryContent>
<ScreenContent isOfflineCapable>
<ScreenSecondaryContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { useCallback } from 'react'
import { useMarkNotificationsAsViewed } from '@audius/common/api'
import { useFocusEffect } from '@react-navigation/native'

import { IconNotificationOn } from '@audius/harmony-native'
import { Screen, ScreenContent, ScreenHeader } from 'app/components/core'
import { Screen, ScreenContent } from 'app/components/core'
import { ScreenPrimaryContent } from 'app/components/core/Screen/ScreenPrimaryContent'
import { ScreenSecondaryContent } from 'app/components/core/Screen/ScreenSecondaryContent'
import { useAppTabScreen } from 'app/hooks/useAppTabScreen'
import { MobileRootHeader } from 'app/screens/app-screen/MobileRootHeader'

import { NotificationList } from './NotificationList'

Expand All @@ -26,14 +26,8 @@ export const NotificationsScreen = () => {
useFocusEffect(handleMarkAsViewed)

return (
<Screen>
<ScreenPrimaryContent>
<ScreenHeader
text={messages.header}
icon={IconNotificationOn}
iconProps={{ height: 28, width: 28 }}
/>
</ScreenPrimaryContent>
<Screen header={() => <MobileRootHeader title={messages.header} />}>
<ScreenPrimaryContent>{null}</ScreenPrimaryContent>
<ScreenContent>
<ScreenSecondaryContent>
<NotificationList />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { TimeRange } from '@audius/common/models'
import { modalsActions, trendingPageSelectors } from '@audius/common/store'
import { ALL_GENRES } from '@audius/common/utils'
import { useDispatch, useSelector } from 'react-redux'

import { Flex, IconLeading, SelectablePill } from '@audius/harmony-native'

import { TRENDING_FILTER_MODAL } from './TrendingCombinedFilterDrawer'

export const TrendingFilterButton = () => {
const dispatch = useDispatch()
const timeRange = useSelector(trendingPageSelectors.getTrendingTimeRange)
const genre = useSelector(trendingPageSelectors.getTrendingGenre)

const hasActiveFilters =
(timeRange ?? TimeRange.WEEK) !== TimeRange.WEEK ||
(genre ?? ALL_GENRES) !== ALL_GENRES

const handleOpenFilter = () => {
dispatch(
modalsActions.setVisibility({
modal: TRENDING_FILTER_MODAL,
visible: true
})
)
}

return (
<Flex>
<SelectablePill
type='button'
icon={IconLeading}
size='large'
isSelected={hasActiveFilters}
isControlled
onPress={handleOpenFilter}
accessibilityLabel='Open filter'
/>
</Flex>
)
}
Loading