Skip to content

Commit

Permalink
[PAY-904] - Add gated content upload prompt (#3057)
Browse files Browse the repository at this point in the history
Co-authored-by: Saliou Diallo <saliou@audius.co>
  • Loading branch information
sddioulde and Saliou Diallo committed Mar 20, 2023
1 parent 1afc4e5 commit f206391
Show file tree
Hide file tree
Showing 16 changed files with 467 additions and 52 deletions.
2 changes: 2 additions & 0 deletions packages/mobile/src/app/Drawers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { EditCollectiblesDrawer } from 'app/components/edit-collectibles-drawer'
import { EnablePushNotificationsDrawer } from 'app/components/enable-push-notifications-drawer'
import { FeedFilterDrawer } from 'app/components/feed-filter-drawer'
import { ForgotPasswordDrawer } from 'app/components/forgot-password-drawer'
import { GatedContentUploadPromptDrawer } from 'app/components/gated-content-upload-prompt-drawer/GatedContentUploadPromptDrawer'
import { LockedContentDrawer } from 'app/components/locked-content-drawer'
import { OverflowMenuDrawer } from 'app/components/overflow-menu-drawer'
import { PlaybackRateDrawer } from 'app/components/playback-rate-drawer'
Expand Down Expand Up @@ -115,6 +116,7 @@ const nativeDrawersMap: { [DrawerName in Drawer]?: ComponentType } = {
RemoveDownloadedFavorites: RemoveDownloadedFavoritesDrawer,
UnfavoriteDownloadedCollection: UnfavoriteDownloadedCollectionDrawer,
LockedContent: LockedContentDrawer,
GatedContentUploadPrompt: GatedContentUploadPromptDrawer,
ChatActions: ChatActionsDrawer,
BlockMessages: BlockMessagesDrawer
}
Expand Down
12 changes: 12 additions & 0 deletions packages/mobile/src/assets/images/iconRocket.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import { useCallback } from 'react'

import { TouchableOpacity, View } from 'react-native'
import { useDispatch } from 'react-redux'

import IconArrow from 'app/assets/images/iconArrow.svg'
import IconExternalLink from 'app/assets/images/iconExternalLink.svg'
import IconRocket from 'app/assets/images/iconRocket.svg'
import { Button, Text, useLink } from 'app/components/core'
import { NativeDrawer } from 'app/components/drawer'
import { useNavigation } from 'app/hooks/useNavigation'
import { setVisibility } from 'app/store/drawers/slice'
import { flexRowCentered, makeStyles } from 'app/styles'
import { useColor } from 'app/utils/theme'

const LEARN_MORE_URL =
'https://blog.audius.co/guide-to-audius-availability-settings'

const messages = {
title: 'NEW UPDATE!',
subtitle: 'Control who has access to your tracks!',
description:
'Availability settings allow you to limit access to specific groups of users or offer exclusive content to your most dedicated fans.',
learnMore: 'Learn More',
gotIt: 'Got It',
checkItOut: 'Check It Out'
}

const useStyles = makeStyles(({ spacing, palette, typography }) => ({
drawer: {
marginVertical: spacing(8),
marginHorizontal: spacing(4),
alignItems: 'flex-start'
},
titleContainer: {
...flexRowCentered(),
justifyContent: 'center',
width: '100%',
paddingBottom: spacing(4),
marginBottom: spacing(6),
borderBottomWidth: 1,
borderBottomColor: palette.neutralLight8
},
titleText: {
marginLeft: spacing(3),
fontFamily: typography.fontByWeight.heavy,
fontSize: typography.fontSize.medium,
color: palette.neutralLight4
},
subtitle: {
marginBottom: spacing(6),
fontFamily: typography.fontByWeight.bold,
fontSize: typography.fontSize.large
},
description: {
marginBottom: spacing(6),
fontFamily: typography.fontByWeight.medium,
fontSize: typography.fontSize.large,
lineHeight: spacing(7)
},
button: {
marginBottom: spacing(6)
},
buttonText: {
fontSize: typography.fontSize.large
},
learnMore: {
...flexRowCentered(),
marginBottom: spacing(6)
},
learnMoreIcon: {
marginLeft: spacing(1)
}
}))

export const GatedContentUploadPromptDrawer = ({
isUpload
}: {
isUpload?: boolean
}) => {
const styles = useStyles()
const neutralLight4 = useColor('neutralLight4')
const navigation = useNavigation()
const dispatch = useDispatch()
const { onPress: onLearnMorePress } = useLink(LEARN_MORE_URL)

const handleClose = useCallback(() => {
dispatch(
setVisibility({ drawer: 'GatedContentUploadPrompt', visible: false })
)
}, [dispatch])

const handleSubmit = useCallback(() => {
handleClose()
navigation.push('Availability')
}, [handleClose, navigation])

if (!isUpload) return null

return (
<NativeDrawer drawerName='GatedContentUploadPrompt'>
<View style={styles.drawer}>
<View style={styles.titleContainer}>
<IconRocket fill={neutralLight4} width={24} height={24} />
<Text style={styles.titleText} weight='heavy' color='neutral'>
{messages.title}
</Text>
</View>
<Text style={styles.subtitle}>{messages.subtitle}</Text>
<Text style={styles.description}>{messages.description}</Text>
<TouchableOpacity style={styles.learnMore} onPress={onLearnMorePress}>
<Text weight='bold' color='neutralLight4' fontSize='large'>
{messages.learnMore}
</Text>
<IconExternalLink
style={styles.learnMoreIcon}
width={20}
height={20}
fill={neutralLight4}
/>
</TouchableOpacity>
<Button
title={messages.gotIt}
onPress={handleClose}
variant='commonAlt'
size='large'
styles={{
root: styles.button,
text: styles.buttonText
}}
fullWidth
/>
<Button
title={messages.checkItOut}
onPress={handleSubmit}
styles={{
root: styles.button,
text: styles.buttonText
}}
size='large'
icon={IconArrow}
fullWidth
/>
</View>
</NativeDrawer>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { GatedContentUploadPromptDrawer } from './GatedContentUploadPromptDrawer'
33 changes: 33 additions & 0 deletions packages/mobile/src/hooks/useOneTimeDrawer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useEffect } from 'react'

import AsyncStorage from '@react-native-async-storage/async-storage'
import { useDispatch } from 'react-redux'
import { useAsync } from 'react-use'

import type { Drawer as DrawerName } from 'app/store/drawers/slice'
import { setVisibility } from 'app/store/drawers/slice'

type UseOneTimeDrawerProps = {
key: string // AsyncStorage key
name: DrawerName
disabled?: boolean
}

export const useOneTimeDrawer = ({
key,
name,
disabled = false
}: UseOneTimeDrawerProps) => {
const dispatch = useDispatch()
const { value: seen, loading } = useAsync(() => AsyncStorage.getItem(key))

useEffect(() => {
if (disabled) return

const shouldOpen = !loading && !seen
if (shouldOpen) {
dispatch(setVisibility({ drawer: name, visible: true }))
AsyncStorage.setItem(key, 'true')
}
}, [disabled, loading, seen, dispatch, name, key])
}
15 changes: 15 additions & 0 deletions packages/mobile/src/screens/edit-track-screen/EditTrackForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import IconCaretRight from 'app/assets/images/iconCaretRight.svg'
import IconUpload from 'app/assets/images/iconUpload.svg'
import { Button, Tile } from 'app/components/core'
import { InputErrorMessage } from 'app/components/core/InputErrorMessage'
import { useIsGatedContentEnabled } from 'app/hooks/useIsGatedContentEnabled'
import { useIsSpecialAccessEnabled } from 'app/hooks/useIsSpecialAccessEnabled'
import { useNavigation } from 'app/hooks/useNavigation'
import { useOneTimeDrawer } from 'app/hooks/useOneTimeDrawer'
import { setVisibility } from 'app/store/drawers/slice'
import { makeStyles } from 'app/styles'

Expand All @@ -36,6 +39,9 @@ const messages = {
fixErrors: 'Fix Errors To Continue'
}

const GATED_CONTENT_UPLOAD_PROMPT_DRAWER_SEEN_KEY =
'gated_content_upload_prompt_drawer_seen'

const useStyles = makeStyles(({ spacing }) => ({
backButton: {
transform: [{ rotate: '180deg' }],
Expand Down Expand Up @@ -70,6 +76,15 @@ export const EditTrackForm = (props: EditTrackFormProps) => {
const navigation = useNavigation()
const dispatch = useDispatch()

const isGatedContentEnabled = useIsGatedContentEnabled()
const isSpecialAccessEnabled = useIsSpecialAccessEnabled()

useOneTimeDrawer({
key: GATED_CONTENT_UPLOAD_PROMPT_DRAWER_SEEN_KEY,
name: 'GatedContentUploadPrompt',
disabled: !isGatedContentEnabled || !isSpecialAccessEnabled
})

const handlePressBack = useCallback(() => {
if (!dirty) {
navigation.goBack()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createNativeStackNavigator } from '@react-navigation/native-stack'

import { GatedContentUploadPromptDrawer } from 'app/components/gated-content-upload-prompt-drawer'
import { useIsGatedContentEnabled } from 'app/hooks/useIsGatedContentEnabled'
import { useAppScreenOptions } from 'app/screens/app-screen/useAppScreenOptions'

Expand Down Expand Up @@ -28,27 +29,39 @@ export const EditTrackNavigator = (props: EditTrackNavigatorProps) => {
const screenOptions = useAppScreenOptions(screenOptionOverrides)

return (
<Stack.Navigator screenOptions={screenOptions}>
<Stack.Screen name='CompleteTrackForm'>
{() => <EditTrackForm {...props} />}
</Stack.Screen>
<Stack.Screen name='SelectGenre' component={SelectGenreScreen} />
<Stack.Screen name='SelectMood' component={SelectMoodScreen} />
<Stack.Screen name='RemixSettings' component={RemixSettingsScreen} />
<Stack.Screen name='AdvancedOptions' component={AdvancedOptionsScreen} />
{isGatedContentEnabled ? (
<Stack.Screen name='Availability' component={TrackAvailabilityScreen} />
) : (
<>
<Stack.Navigator screenOptions={screenOptions}>
<Stack.Screen name='CompleteTrackForm'>
{() => <EditTrackForm {...props} />}
</Stack.Screen>
<Stack.Screen name='SelectGenre' component={SelectGenreScreen} />
<Stack.Screen name='SelectMood' component={SelectMoodScreen} />
<Stack.Screen name='RemixSettings' component={RemixSettingsScreen} />
<Stack.Screen
name='TrackVisibility'
component={TrackVisibilityScreen}
name='AdvancedOptions'
component={AdvancedOptionsScreen}
/>
)}
{isGatedContentEnabled && (
<Stack.Screen name='NFTCollections' component={NFTCollectionsScreen} />
)}
<Stack.Screen name='IsrcIswc' component={IsrcIswcScreen} />
<Stack.Screen name='LicenseType' component={LicenseTypeScreen} />
</Stack.Navigator>
{isGatedContentEnabled ? (
<Stack.Screen
name='Availability'
component={TrackAvailabilityScreen}
/>
) : (
<Stack.Screen
name='TrackVisibility'
component={TrackVisibilityScreen}
/>
)}
{isGatedContentEnabled && (
<Stack.Screen
name='NFTCollections'
component={NFTCollectionsScreen}
/>
)}
<Stack.Screen name='IsrcIswc' component={IsrcIswcScreen} />
<Stack.Screen name='LicenseType' component={LicenseTypeScreen} />
</Stack.Navigator>
<GatedContentUploadPromptDrawer isUpload={props.isUpload} />
</>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { View, Image, Dimensions } from 'react-native'
import { TouchableOpacity } from 'react-native-gesture-handler'
import { useSelector } from 'react-redux'

import IconArrow from 'app/assets/images/iconArrow.svg'
import IconCaretRight from 'app/assets/images/iconCaretRight.svg'
import IconCollectible from 'app/assets/images/iconCollectible.svg'
import { Link, Text } from 'app/components/core'
import IconExternalLink from 'app/assets/images/iconExternalLink.svg'
import { Text, useLink } from 'app/components/core'
import { HelpCallout } from 'app/components/help-callout/HelpCallout'
import { useNavigation } from 'app/hooks/useNavigation'
import { useSetTrackAvailabilityFields } from 'app/hooks/useSetTrackAvailabilityFields'
Expand Down Expand Up @@ -73,10 +73,10 @@ const useStyles = makeStyles(({ typography, spacing, palette }) => ({
alignItems: 'center'
},
learnMoreText: {
marginRight: spacing(0.5),
marginRight: spacing(1),
fontFamily: typography.fontByWeight.bold,
fontSize: typography.fontSize.small,
color: palette.secondary
fontSize: typography.fontSize.large,
color: palette.neutralLight4
},
collectionContainer: {
marginTop: spacing(4),
Expand Down Expand Up @@ -129,6 +129,9 @@ const useStyles = makeStyles(({ typography, spacing, palette }) => ({
marginRight: spacing(4),
width: spacing(5),
height: spacing(5)
},
learnMoreIcon: {
marginLeft: spacing(1)
}
}))

Expand All @@ -148,6 +151,7 @@ export const CollectibleGatedAvailability = ({
const secondary = useColor('secondary')
const neutral = useColor('neutral')
const neutralLight4 = useColor('neutralLight4')
const { onPress: onLearnMorePress } = useLink(LEARN_MORE_URL)

const titleStyles: object[] = [styles.title]
if (selected) {
Expand Down Expand Up @@ -237,10 +241,17 @@ export const CollectibleGatedAvailability = ({
content={renderHelpCalloutContent()}
/>
) : null}
<Link url={LEARN_MORE_URL} style={styles.learnMore}>
<Text style={styles.learnMoreText}>{messages.learnMore}</Text>
<IconArrow fill={secondary} width={16} height={16} />
</Link>
<TouchableOpacity style={styles.learnMore} onPress={onLearnMorePress}>
<Text weight='bold' color='neutralLight4' fontSize='large'>
{messages.learnMore}
</Text>
<IconExternalLink
style={styles.learnMoreIcon}
width={20}
height={20}
fill={neutralLight4}
/>
</TouchableOpacity>
{selected && (
<TouchableOpacity
onPress={handlePickACollection}
Expand Down
2 changes: 2 additions & 0 deletions packages/mobile/src/screens/edit-track-screen/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ export type EditTrackScreenProps = {
onSubmit: (values: ExtendedTrackMetadata) => void
initialValues: ExtendedTrackMetadata & { trackArtwork?: string }
doneText?: string
isUpload?: boolean
} & Partial<ScreenProps>

export type EditTrackFormProps = FormikProps<FormValues> &
Partial<ScreenProps> & {
doneText?: string
isUpload?: boolean
}

export type RemixOfField = Nullable<{ tracks: { parent_track_id }[] }>
Loading

0 comments on commit f206391

Please sign in to comment.