diff --git a/packages/mobile/src/assets/images/iconCart.svg b/packages/mobile/src/assets/images/iconCart.svg
new file mode 100644
index 0000000000..ddae1070e1
--- /dev/null
+++ b/packages/mobile/src/assets/images/iconCart.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/mobile/src/components/core/DogEar.tsx b/packages/mobile/src/components/core/DogEar.tsx
index 2f773b53bd..d8f1c689c2 100644
--- a/packages/mobile/src/components/core/DogEar.tsx
+++ b/packages/mobile/src/components/core/DogEar.tsx
@@ -2,9 +2,9 @@ import type { ViewStyle } from 'react-native'
import { View } from 'react-native'
import LinearGradient from 'react-native-linear-gradient'
+import IconCart from 'app/assets/images/iconCart.svg'
import IconCollectible from 'app/assets/images/iconCollectible.svg'
import IconHidden from 'app/assets/images/iconHidden.svg'
-import IconLock from 'app/assets/images/iconLock.svg'
import IconSpecialAccess from 'app/assets/images/iconSpecialAccess.svg'
import IconStar from 'app/assets/images/iconStar.svg'
import { makeStyles } from 'app/styles'
@@ -39,9 +39,9 @@ const useStyles = makeStyles(({ spacing }) => ({
export enum DogEarType {
STAR = 'star',
HIDDEN = 'hidden',
- LOCKED = 'locked',
COLLECTIBLE_GATED = 'collectible gated',
- SPECIAL_ACCESS = 'special access'
+ SPECIAL_ACCESS = 'special access',
+ USDC_PURCHASE = 'usdc purchase'
}
type DogEarProps = {
@@ -58,7 +58,8 @@ export const DogEar = (props: DogEarProps) => {
pageHeaderGradientColor2,
secondary,
staticWhite,
- accentBlue
+ accentBlue,
+ specialLightGreen1
} = useThemeColors()
const { icon: Icon, colors } = {
@@ -70,10 +71,6 @@ export const DogEar = (props: DogEarProps) => {
icon: IconHidden,
colors: [neutral, neutralLight3]
},
- [DogEarType.LOCKED]: {
- icon: IconLock,
- colors: [accentBlue, accentBlue]
- },
[DogEarType.COLLECTIBLE_GATED]: {
icon: IconCollectible,
colors: [accentBlue, accentBlue]
@@ -81,6 +78,10 @@ export const DogEar = (props: DogEarProps) => {
[DogEarType.SPECIAL_ACCESS]: {
icon: IconSpecialAccess,
colors: [accentBlue, accentBlue]
+ },
+ [DogEarType.USDC_PURCHASE]: {
+ icon: IconCart,
+ colors: [specialLightGreen1, specialLightGreen1]
}
}[type]
diff --git a/packages/mobile/src/components/details-tile/DetailsTile.tsx b/packages/mobile/src/components/details-tile/DetailsTile.tsx
index b0144fb31c..cb4d72855e 100644
--- a/packages/mobile/src/components/details-tile/DetailsTile.tsx
+++ b/packages/mobile/src/components/details-tile/DetailsTile.tsx
@@ -28,6 +28,7 @@ import {
import Text from 'app/components/text'
import UserBadges from 'app/components/user-badges'
import { light } from 'app/haptics'
+import { useIsUSDCEnabled } from 'app/hooks/useIsUSDCEnabled'
import { useNavigation } from 'app/hooks/useNavigation'
import { useFeatureFlag } from 'app/hooks/useRemoteConfig'
import { flexRowCentered, makeStyles } from 'app/styles'
@@ -228,6 +229,7 @@ export const DetailsTile = ({
const { isEnabled: isAiGeneratedTracksEnabled } = useFeatureFlag(
FeatureFlags.AI_ATTRIBUTION
)
+ const isUSDCEnabled = useIsUSDCEnabled()
const { track_id: trackId, premium_conditions: premiumConditions } =
track ?? {}
@@ -266,10 +268,12 @@ export const DetailsTile = ({
const dogEarType = showPremiumDogEar
? isOwner
- ? premiumConditions.nft_collection
+ ? isUSDCEnabled && premiumConditions.usdc_purchase
+ ? DogEarType.USDC_PURCHASE
+ : premiumConditions.nft_collection
? DogEarType.COLLECTIBLE_GATED
: DogEarType.SPECIAL_ACCESS
- : DogEarType.LOCKED
+ : null
: null
if (showPremiumDogEar && dogEarType) {
diff --git a/packages/mobile/src/components/lineup-tile/LineupTile.tsx b/packages/mobile/src/components/lineup-tile/LineupTile.tsx
index f9657267e6..0199f0de56 100644
--- a/packages/mobile/src/components/lineup-tile/LineupTile.tsx
+++ b/packages/mobile/src/components/lineup-tile/LineupTile.tsx
@@ -11,6 +11,7 @@ import { useSelector, useDispatch } from 'react-redux'
import { DogEar, DogEarType } from 'app/components/core'
import type { LineupTileProps } from 'app/components/lineup-tile/types'
+import { useIsUSDCEnabled } from 'app/hooks/useIsUSDCEnabled'
import { setVisibility } from 'app/store/drawers/slice'
import { LineupTileActionButtons } from './LineupTileActionButtons'
@@ -59,6 +60,8 @@ export const LineupTile = ({
repost_count,
save_count
} = item
+ const dispatch = useDispatch()
+ const isUSDCEnabled = useIsUSDCEnabled()
const { artist_pick_track_id, name, user_id } = user
const currentUserId = useSelector(getUserId)
const isOwner = user_id === currentUserId
@@ -68,7 +71,6 @@ export const LineupTile = ({
const premiumConditions = isTrack ? item.premium_conditions : null
const isArtistPick = artist_pick_track_id === id
const { doesUserHaveAccess } = usePremiumContentAccess(isTrack ? item : null)
- const dispatch = useDispatch()
const showPremiumDogEar =
premiumConditions &&
@@ -76,7 +78,9 @@ export const LineupTile = ({
!(showArtistPick && isArtistPick)
const dogEarType = showPremiumDogEar
- ? premiumConditions.nft_collection
+ ? isUSDCEnabled && premiumConditions.usdc_purchase
+ ? DogEarType.USDC_PURCHASE
+ : premiumConditions.nft_collection
? DogEarType.COLLECTIBLE_GATED
: DogEarType.SPECIAL_ACCESS
: null
@@ -159,6 +163,7 @@ export const LineupTile = ({
isShareHidden={hideShare}
isUnlisted={isUnlisted}
trackId={trackId}
+ premiumConditions={premiumConditions}
doesUserHaveAccess={doesUserHaveAccess}
onPressOverflow={onPressOverflow}
onPressRepost={onPressRepost}
diff --git a/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx b/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx
index 23b32cd3e1..1fa767da8a 100644
--- a/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx
+++ b/packages/mobile/src/components/lineup-tile/LineupTileAccessStatus.tsx
@@ -1,4 +1,4 @@
-import type { ID } from '@audius/common'
+import type { ID, PremiumConditions } from '@audius/common'
import { premiumContentSelectors } from '@audius/common'
import { View } from 'react-native'
import { useSelector } from 'react-redux'
@@ -6,6 +6,7 @@ import { useSelector } from 'react-redux'
import IconLock from 'app/assets/images/iconLock.svg'
import { Text } from 'app/components/core'
import LoadingSpinner from 'app/components/loading-spinner'
+import { useIsUSDCEnabled } from 'app/hooks/useIsUSDCEnabled'
import { flexRowCentered, makeStyles } from 'app/styles'
import { useColor } from 'app/utils/theme'
@@ -33,17 +34,34 @@ const useStyles = makeStyles(({ palette, spacing, typography }) => ({
loadingSpinner: {
width: spacing(4),
height: spacing(4)
+ },
+ usdcPurchase: {
+ backgroundColor: palette.specialLightGreen1
}
}))
-export const LineupTileAccessStatus = ({ trackId }: { trackId: ID }) => {
+export const LineupTileAccessStatus = ({
+ trackId,
+ premiumConditions
+}: {
+ trackId: ID
+ premiumConditions: PremiumConditions
+}) => {
const styles = useStyles()
+ const isUSDCEnabled = useIsUSDCEnabled()
const premiumTrackStatusMap = useSelector(getPremiumTrackStatusMap)
const premiumTrackStatus = premiumTrackStatusMap[trackId]
const staticWhite = useColor('staticWhite')
return (
-
+
{premiumTrackStatus === 'UNLOCKING' ? (
) : (
diff --git a/packages/mobile/src/components/lineup-tile/LineupTileActionButtons.tsx b/packages/mobile/src/components/lineup-tile/LineupTileActionButtons.tsx
index 4efd382c79..bd8f9752bc 100644
--- a/packages/mobile/src/components/lineup-tile/LineupTileActionButtons.tsx
+++ b/packages/mobile/src/components/lineup-tile/LineupTileActionButtons.tsx
@@ -1,4 +1,4 @@
-import type { ID } from '@audius/common'
+import type { ID, Nullable, PremiumConditions } from '@audius/common'
import { View } from 'react-native'
import IconKebabHorizontal from 'app/assets/images/iconKebabHorizontal.svg'
@@ -20,6 +20,7 @@ type Props = {
isShareHidden?: boolean
isUnlisted?: boolean
trackId?: ID
+ premiumConditions?: Nullable
doesUserHaveAccess?: boolean
onPressOverflow?: GestureResponderHandler
onPressRepost?: GestureResponderHandler
@@ -57,6 +58,7 @@ export const LineupTileActionButtons = ({
isUnlisted,
trackId,
doesUserHaveAccess = false,
+ premiumConditions,
onPressOverflow,
onPressRepost,
onPressSave,
@@ -111,9 +113,12 @@ export const LineupTileActionButtons = ({
return (
- {showPremiumAccessStatus && (
-
- )}
+ {showPremiumAccessStatus && premiumConditions != null ? (
+
+ ) : null}
{showLeftButtons && (
<>
{repostButton}
diff --git a/packages/mobile/src/components/lineup-tile/LineupTilePremiumContentTypeTag.tsx b/packages/mobile/src/components/lineup-tile/LineupTilePremiumContentTypeTag.tsx
index 6648f020f6..1916add6aa 100644
--- a/packages/mobile/src/components/lineup-tile/LineupTilePremiumContentTypeTag.tsx
+++ b/packages/mobile/src/components/lineup-tile/LineupTilePremiumContentTypeTag.tsx
@@ -3,16 +3,19 @@ import { useMemo } from 'react'
import type { PremiumConditions } from '@audius/common'
import { View } from 'react-native'
+import IconCart from 'app/assets/images/iconCart.svg'
import IconCollectible from 'app/assets/images/iconCollectible.svg'
import IconSpecialAccess from 'app/assets/images/iconSpecialAccess.svg'
import Text from 'app/components/text'
+import { useIsUSDCEnabled } from 'app/hooks/useIsUSDCEnabled'
import { makeStyles, flexRowCentered } from 'app/styles'
import { spacing } from 'app/styles/spacing'
import { useThemeColors } from 'app/utils/theme'
const messages = {
collectibleGated: 'Collectible Gated',
- specialAccess: 'Special Access'
+ specialAccess: 'Special Access',
+ premium: 'Premium'
}
const useStyles = makeStyles(({ spacing, palette, typography }) => ({
@@ -28,7 +31,8 @@ const useStyles = makeStyles(({ spacing, palette, typography }) => ({
enum PremiumContentType {
COLLECTIBLE_GATED = 'collectible gated',
- SPECIAL_ACCESS = 'special access'
+ SPECIAL_ACCESS = 'special access',
+ USDC_PURCHASE = 'usdc purchase'
}
type LineupTilePremiumContentTypeTagProps = {
@@ -49,11 +53,15 @@ export const LineupTilePremiumContentTypeTag = ({
isOwner
}: LineupTilePremiumContentTypeTagProps) => {
const styles = useStyles()
- const { accentBlue, neutralLight4 } = useThemeColors()
+ const { accentBlue, neutralLight4, specialLightGreen1 } = useThemeColors()
+ const isUSDCEnabled = useIsUSDCEnabled()
- const type = premiumConditions?.nft_collection
- ? PremiumContentType.COLLECTIBLE_GATED
- : PremiumContentType.SPECIAL_ACCESS
+ const type =
+ isUSDCEnabled && premiumConditions?.usdc_purchase
+ ? PremiumContentType.USDC_PURCHASE
+ : premiumConditions?.nft_collection
+ ? PremiumContentType.COLLECTIBLE_GATED
+ : PremiumContentType.SPECIAL_ACCESS
const premiumContentTypeMap = useMemo(() => {
return {
@@ -66,9 +74,21 @@ export const LineupTilePremiumContentTypeTag = ({
icon: IconSpecialAccess,
color: doesUserHaveAccess && !isOwner ? neutralLight4 : accentBlue,
text: messages.specialAccess
+ },
+ [PremiumContentType.USDC_PURCHASE]: {
+ icon: IconCart,
+ color:
+ doesUserHaveAccess && !isOwner ? neutralLight4 : specialLightGreen1,
+ text: messages.premium
}
}
- }, [accentBlue, doesUserHaveAccess, isOwner, neutralLight4])
+ }, [
+ accentBlue,
+ doesUserHaveAccess,
+ isOwner,
+ neutralLight4,
+ specialLightGreen1
+ ])
const { icon: Icon, color, text } = premiumContentTypeMap[type]
diff --git a/packages/mobile/src/components/lineup-tile/LineupTileStats.tsx b/packages/mobile/src/components/lineup-tile/LineupTileStats.tsx
index d9d81f65aa..43d6f751b0 100644
--- a/packages/mobile/src/components/lineup-tile/LineupTileStats.tsx
+++ b/packages/mobile/src/components/lineup-tile/LineupTileStats.tsx
@@ -22,6 +22,7 @@ import IconUnlocked from 'app/assets/images/iconUnlocked.svg'
import { CollectionDownloadStatusIndicator } from 'app/components/offline-downloads/CollectionDownloadStatusIndicator'
import { TrackDownloadStatusIndicator } from 'app/components/offline-downloads/TrackDownloadStatusIndicator'
import Text from 'app/components/text'
+import { useIsUSDCEnabled } from 'app/hooks/useIsUSDCEnabled'
import { useNavigation } from 'app/hooks/useNavigation'
import { makeStyles, flexRowCentered } from 'app/styles'
import { useThemeColors } from 'app/utils/theme'
@@ -77,6 +78,9 @@ const useStyles = makeStyles(({ spacing, palette }) => ({
},
iconUnlocked: {
backgroundColor: palette.accentBlue
+ },
+ iconUSDC: {
+ backgroundColor: palette.specialLightGreen1
}
}))
@@ -122,6 +126,7 @@ export const LineupTileStats = ({
const { neutralLight4, staticWhite } = useThemeColors()
const dispatch = useDispatch()
const navigation = useNavigation()
+ const isUSDCEnabled = useIsUSDCEnabled()
const hasEngagement = Boolean(repostCount || saveCount)
@@ -203,7 +208,10 @@ export const LineupTileStats = ({
style={[
styles.iconLocked,
styles.listenCount,
- doesUserHaveAccess ? styles.iconUnlocked : null
+ doesUserHaveAccess ? styles.iconUnlocked : null,
+ isUSDCEnabled && premiumConditions.usdc_purchase
+ ? styles.iconUSDC
+ : null
]}
>
{doesUserHaveAccess ? (
diff --git a/packages/mobile/src/utils/theme.ts b/packages/mobile/src/utils/theme.ts
index 550431c121..f56126534f 100644
--- a/packages/mobile/src/utils/theme.ts
+++ b/packages/mobile/src/utils/theme.ts
@@ -57,6 +57,7 @@ export const defaultTheme = {
staticNeutralLight2: '#AAA7B8',
staticNeutralLight8: '#F2F2F4',
staticAccentGreenLight1: '#23AD1A',
+ specialLightGreen1: '#13C65A',
staticPrimary: '#CC0FE0',
staticSecondary: '#7E1BCC',
pageHeaderGradientColor1: '#5B23E1',
@@ -115,6 +116,7 @@ export const darkTheme = {
staticNeutralLight2: '#AAA7B8',
staticNeutralLight8: '#F2F2F4',
staticAccentGreenLight1: '#23AD1A',
+ specialLightGreen1: '#13C65A',
staticPrimary: '#CC0FE0',
staticSecondary: '#7E1BCC',
pageHeaderGradientColor1: '#7652CC',
@@ -162,6 +164,7 @@ export const matrixTheme = {
staticNeutralLight2: '#AAA7B8',
staticNeutralLight8: '#F2F2F4',
staticAccentGreenLight1: '#23AD1A',
+ specialLightGreen1: '#13C65A',
staticPrimary: '#CC0FE0',
staticSecondary: '#7E1BCC',
pageHeaderGradientColor1: '#4FF069',
@@ -223,6 +226,7 @@ export type ThemeColors = {
staticNeutralLight2: string
staticNeutralLight8: string
staticAccentGreenLight1: string
+ specialLightGreen1: string
staticPrimary: string
staticSecondary: string
pageHeaderGradientColor1: string