diff --git a/packages/common/src/adapters/accessConditionsFromSDK.ts b/packages/common/src/adapters/accessConditionsFromSDK.ts index f094b40646d..1e205eb11db 100644 --- a/packages/common/src/adapters/accessConditionsFromSDK.ts +++ b/packages/common/src/adapters/accessConditionsFromSDK.ts @@ -1,6 +1,5 @@ import type { full } from '@audius/sdk' import { - instanceOfTipGate, instanceOfFollowGate, instanceOfPurchaseGate, instanceOfTokenGate, @@ -16,8 +15,6 @@ export const accessConditionsFromSDK = ( return { follow_user_id: input.followUserId } } else if (instanceOfPurchaseGate(input)) { return { usdc_purchase: input.usdcPurchase } - } else if (instanceOfTipGate(input)) { - return { tip_user_id: input.tipUserId } } else if (instanceOfTokenGate(input)) { return { token_gate: { diff --git a/packages/common/src/adapters/accessConditionsToSDK.ts b/packages/common/src/adapters/accessConditionsToSDK.ts index 7242c4dc5f6..0457c5f22b6 100644 --- a/packages/common/src/adapters/accessConditionsToSDK.ts +++ b/packages/common/src/adapters/accessConditionsToSDK.ts @@ -3,7 +3,6 @@ import type { TrackMetadata } from '@audius/sdk' import { AccessConditions, isContentFollowGated, - isContentTipGated, isContentTokenGated, isContentUSDCPurchaseGated } from '~/models' @@ -26,10 +25,6 @@ export const accessConditionsToSDK = ( tokenAmount: input.token_gate.token_amount } } - } else if (isContentTipGated(input)) { - return { - tipUserId: input.tip_user_id - } } else { throw new Error( `Unsupported access conditions type: ${JSON.stringify(input)}` diff --git a/packages/common/src/adapters/audioTransactions.ts b/packages/common/src/adapters/audioTransactions.ts index 9392f2eccaf..bef28f321be 100644 --- a/packages/common/src/adapters/audioTransactions.ts +++ b/packages/common/src/adapters/audioTransactions.ts @@ -14,7 +14,6 @@ export const audioTransactionFromSdk = ( purchase_coinbase: TransactionType.PURCHASE, purchase_unknown: TransactionType.PURCHASE, 'purchase unknown': TransactionType.PURCHASE, - tip: TransactionType.TIP, user_reward: TransactionType.CHALLENGE_REWARD, trending_reward: TransactionType.TRENDING_REWARD, transfer: TransactionType.TRANSFER @@ -48,7 +47,6 @@ export const audioTransactionFromSdk = ( balance: tx.balance, metadata: undefined } - case TransactionType.TIP: case TransactionType.TRANSFER: return { signature: tx.signature, diff --git a/packages/common/src/adapters/index.ts b/packages/common/src/adapters/index.ts index e78368729ff..a55f7367f9e 100644 --- a/packages/common/src/adapters/index.ts +++ b/packages/common/src/adapters/index.ts @@ -12,7 +12,6 @@ export * from './playlistLibrary' export * from './remix' export * from './repost' export * from './search' -export * from './tip' export * from './track' export * from './trending' export * from './user' diff --git a/packages/common/src/adapters/notification.ts b/packages/common/src/adapters/notification.ts index a39065f61ae..9419cca300e 100644 --- a/packages/common/src/adapters/notification.ts +++ b/packages/common/src/adapters/notification.ts @@ -112,32 +112,6 @@ export const notificationFromSDK = ( ...formatBaseNotification(notification) } } - case 'tip_send': { - const data = notification.actions[0].data - const amount = data.amount - const receiverUserId = HashId.parse(data.receiverUserId) - return { - type: NotificationType.TipSend, - entityId: receiverUserId, - entityType: Entity.User, - amount: amount!.toString() as StringWei, - ...formatBaseNotification(notification) - } - } - case 'tip_receive': { - const data = notification.actions[0].data - const amount = data.amount - const senderUserId = HashId.parse(data.senderUserId) - return { - type: NotificationType.TipReceive, - entityId: senderUserId, - amount: amount!.toString() as StringWei, - entityType: Entity.User, - tipTxSignature: data.tipTxSignature, - reactionValue: data.reactionValue, - ...formatBaseNotification(notification) - } - } case 'track_added_to_purchased_album': { let trackId = 0 let playlistId = 0 @@ -188,38 +162,6 @@ export const notificationFromSDK = ( ...formatBaseNotification(notification) } } - case 'supporter_rank_up': { - const data = notification.actions[0].data - const senderUserId = HashId.parse(data.senderUserId) - return { - type: NotificationType.SupporterRankUp, - entityId: senderUserId, - rank: data.rank, - entityType: Entity.User, - ...formatBaseNotification(notification) - } - } - case 'supporting_rank_up': { - const data = notification.actions[0].data - const receiverUserId = HashId.parse(data.receiverUserId) - return { - type: NotificationType.SupportingRankUp, - entityId: receiverUserId, - rank: data.rank, - entityType: Entity.User, - ...formatBaseNotification(notification) - } - } - case 'supporter_dethroned': { - const data = notification.actions[0].data - return { - type: NotificationType.SupporterDethroned, - entityType: Entity.User, - entityId: HashId.parse(data.senderUserId), - supportedUserId: HashId.parse(data.receiverUserId), - ...formatBaseNotification(notification) - } - } case 'challenge_reward': { const data = notification.actions[0].data const challengeId = data.challengeId as ChallengeRewardID @@ -421,22 +363,6 @@ export const notificationFromSDK = ( ...formatBaseNotification(notification) } } - case 'reaction': { - const data = notification.actions[0].data - return { - type: NotificationType.Reaction, - entityId: HashId.parse(data.receiverUserId), - entityType: Entity.User, - reactionValue: data.reactionValue, - reactionType: data.reactionType, - reactedToEntity: { - tx_signature: data.reactedTo, - amount: data.tipAmount as StringWei, - tip_sender_id: HashId.parse(data.senderUserId) - }, - ...formatBaseNotification(notification) - } - } case 'repost_of_repost': { let entityId = 0 let entityType = Entity.Track diff --git a/packages/common/src/adapters/tip.ts b/packages/common/src/adapters/tip.ts deleted file mode 100644 index c0d1268e425..00000000000 --- a/packages/common/src/adapters/tip.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { full } from '@audius/sdk' - -import { StringWei } from '~/models' -import { UserTipWithUsers } from '~/models/Tipping' - -import { userMetadataFromSDK } from './user' - -export const userTipWithUsersFromSDK = ( - input: full.FullTip -): UserTipWithUsers | undefined => { - const sender = userMetadataFromSDK(input.sender) - const receiver = userMetadataFromSDK(input.receiver) - return sender && receiver - ? { - sender, - receiver, - sender_id: sender.user_id, - receiver_id: receiver.user_id, - amount: input.amount as StringWei, - created_at: input.createdAt, - // Intentionally empty for performance reasons - followee_supporter_ids: [], - followee_supporters: input.followeeSupporters.map(({ userId }) => ({ - user_id: userId - })), - slot: input.slot, - tx_signature: input.txSignature - } - : undefined -} diff --git a/packages/common/src/api/index.ts b/packages/common/src/api/index.ts index ce958bc81c0..85695521532 100644 --- a/packages/common/src/api/index.ts +++ b/packages/common/src/api/index.ts @@ -65,8 +65,6 @@ export * from './tan-query/purchases/usePurchasersCount' export * from './tan-query/purchases/useSalesAggregate' // Reactions -export * from './tan-query/reactions/useReaction' -export * from './tan-query/reactions/useWriteReaction' export * from './tan-query/reactions/types' export * from './tan-query/reactions/utils' @@ -120,9 +118,6 @@ export * from './tan-query/users/useMutualFollowers' export * from './tan-query/users/useMutedUsers' export * from './tan-query/users/useRelatedArtists' export * from './tan-query/users/useSuggestedArtists' -export * from './tan-query/users/useSupporter' -export * from './tan-query/users/useSupporters' -export * from './tan-query/users/useSupportedUsers' export * from './tan-query/users/useTopArtists' export * from './tan-query/users/useTopArtistsInGenre' export * from './tan-query/users/useUserAlbums' diff --git a/packages/common/src/api/tan-query/batchers/__tests__/getCollectionsBatcher.test.ts b/packages/common/src/api/tan-query/batchers/__tests__/getCollectionsBatcher.test.ts index 2e594000c38..d74ccc5bc64 100644 --- a/packages/common/src/api/tan-query/batchers/__tests__/getCollectionsBatcher.test.ts +++ b/packages/common/src/api/tan-query/batchers/__tests__/getCollectionsBatcher.test.ts @@ -81,8 +81,6 @@ describe('getCollectionsBatcher', () => { isAvailable: true, ercWallet: '', splWallet: '', - supporterCount: 0, - supportingCount: 0, totalAudioBalance: 0, wallet: '', balance: '0', @@ -106,7 +104,12 @@ describe('getCollectionsBatcher', () => { profilePictureCids: undefined, profilePictureLegacy: undefined, playlistLibrary: undefined, - allowAiAttribution: false + allowAiAttribution: false, + supporterCount: 0, + supportingCount: 0, + artistCoinBadge: undefined, + splUsdcWallet: undefined, + hasCollectibles: false } }) diff --git a/packages/common/src/api/tan-query/batchers/__tests__/getTracksBatcher.test.ts b/packages/common/src/api/tan-query/batchers/__tests__/getTracksBatcher.test.ts index 441dc546b51..c72ff26aeba 100644 --- a/packages/common/src/api/tan-query/batchers/__tests__/getTracksBatcher.test.ts +++ b/packages/common/src/api/tan-query/batchers/__tests__/getTracksBatcher.test.ts @@ -118,8 +118,6 @@ describe('getTracksBatcher', () => { isAvailable: true, ercWallet: '', splWallet: '', - supporterCount: 0, - supportingCount: 0, totalAudioBalance: 0, wallet: '', balance: '0', diff --git a/packages/common/src/api/tan-query/batchers/__tests__/getUsersBatcher.test.ts b/packages/common/src/api/tan-query/batchers/__tests__/getUsersBatcher.test.ts index 84c00202ecf..d6852521e84 100644 --- a/packages/common/src/api/tan-query/batchers/__tests__/getUsersBatcher.test.ts +++ b/packages/common/src/api/tan-query/batchers/__tests__/getUsersBatcher.test.ts @@ -32,8 +32,6 @@ describe('getUsersBatcher', () => { doesCurrentUserFollow: false, currentUserFolloweeFollowCount: 0, ercWallet: '', - supporterCount: 0, - supportingCount: 0, coverPhotoLegacy: undefined, profilePictureLegacy: undefined, coverPhotoCids: undefined, diff --git a/packages/common/src/api/tan-query/batchers/getReactionsBatcher.ts b/packages/common/src/api/tan-query/batchers/getReactionsBatcher.ts deleted file mode 100644 index a1509963c1b..00000000000 --- a/packages/common/src/api/tan-query/batchers/getReactionsBatcher.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { type full, HashId } from '@audius/sdk' -import { create, keyResolver, windowScheduler } from '@yornaath/batshit' -import { memoize } from 'lodash' - -import { transformAndCleanList } from '~/adapters' -import { toast } from '~/store/ui/toast/slice' -import { isResponseError } from '~/utils' - -import { messages } from '../reactions/messages' -import { Reaction } from '../reactions/types' -import { getReactionsQueryKey } from '../reactions/utils' - -import { contextCacheResolver } from './contextCacheResolver' -import { BatchContext } from './types' - -export const getReactionsBatcher = memoize( - (context: BatchContext) => - create({ - fetcher: async (entityIds: string[]): Promise => { - const { sdk, queryClient, dispatch } = context - if (!entityIds.length) return [] - - try { - const { data = [] } = await sdk.full.reactions.bulkGetReactions({ - reactedToIds: entityIds - }) - - // Transform the data - const reactions = transformAndCleanList( - data, - (item: full.Reaction) => ({ - ...item, - reactionValue: parseInt(item.reactionValue), - senderUserId: HashId.parse(item.senderUserId) - }) - ) - - // Create a map of all reactions, including empty ones for IDs with no reactions - const reactionMap = entityIds.reduce>( - (acc: Record, id: string) => { - acc[id] = { - reactedTo: id, - reactionValue: null, - senderUserId: 0 - } - return acc - }, - {} - ) - - // Overwrite with actual reactions - reactions.forEach((reaction) => { - reactionMap[reaction.reactedTo] = reaction - }) - - // Update the cache for all fetched IDs - queryClient.setQueryData(getReactionsQueryKey(entityIds), reactionMap) - - // Return array of reactions in same order as input - return entityIds.map((id) => reactionMap[id]) - } catch (error: unknown) { - // Handle 404 as a valid case (no reactions) - if (isResponseError(error) && error.response?.status === 404) { - // Create empty reactions for all requested IDs - const emptyReactions = entityIds.reduce>( - (acc: Record, id: string) => { - acc[id] = { - reactedTo: id, - reactionValue: null, - senderUserId: 0 - } - return acc - }, - {} - ) - - // Update the cache - queryClient.setQueryData( - getReactionsQueryKey(entityIds), - emptyReactions - ) - - // Return array of empty reactions in same order as input - return entityIds.map((id) => emptyReactions[id]) - } - - // Report other errors - dispatch(toast({ content: messages.mutationError('fetching') })) - throw error - } - }, - resolver: keyResolver('reactedTo'), - scheduler: windowScheduler(2000) // 2s window to collect requests - }), - contextCacheResolver() -) diff --git a/packages/common/src/api/tan-query/lineups/useExclusiveTracks.ts b/packages/common/src/api/tan-query/lineups/useExclusiveTracks.ts index ec84496766a..e2b772c4ed1 100644 --- a/packages/common/src/api/tan-query/lineups/useExclusiveTracks.ts +++ b/packages/common/src/api/tan-query/lineups/useExclusiveTracks.ts @@ -25,7 +25,7 @@ import { useLineupQuery } from './useLineupQuery' const DEFAULT_PAGE_SIZE = 10 -type GateCondition = 'ungated' | 'usdc_purchase' | 'follow' | 'tip' | 'token' +type GateCondition = 'ungated' | 'usdc_purchase' | 'follow' | 'token' type UseExclusiveTracksArgs = { userId: ID | null | undefined diff --git a/packages/common/src/api/tan-query/notifications/useNotifications.ts b/packages/common/src/api/tan-query/notifications/useNotifications.ts index 68453610940..8231149c174 100644 --- a/packages/common/src/api/tan-query/notifications/useNotifications.ts +++ b/packages/common/src/api/tan-query/notifications/useNotifications.ts @@ -106,15 +106,6 @@ const collectEntityIds = (notifications: Notification[]): EntityIds => { if (type === NotificationType.TrendingPlaylist) { collectionIds.add(notification.entityId) } - if ( - type === NotificationType.TipSend || - type === NotificationType.TipReceive || - type === NotificationType.SupporterRankUp || - type === NotificationType.SupportingRankUp || - type === NotificationType.Reaction - ) { - userIds.add(notification.entityId) - } if ( type === NotificationType.AddTrackToPlaylist || type === NotificationType.TrackAddedToPurchasedAlbum @@ -123,9 +114,6 @@ const collectEntityIds = (notifications: Notification[]): EntityIds => { userIds.add(notification.playlistOwnerId) collectionIds.add(notification.playlistId) } - if (type === NotificationType.SupporterDethroned) { - userIds.add(notification.supportedUserId).add(notification.entityId) - } if (type === NotificationType.Tastemaker) { userIds.add(notification.userId) trackIds.add(notification.entityId) diff --git a/packages/common/src/api/tan-query/purchases/useAudioTransactions.ts b/packages/common/src/api/tan-query/purchases/useAudioTransactions.ts index 4de8a4c7467..68bfbbd3177 100644 --- a/packages/common/src/api/tan-query/purchases/useAudioTransactions.ts +++ b/packages/common/src/api/tan-query/purchases/useAudioTransactions.ts @@ -1,21 +1,15 @@ -import { useMemo } from 'react' - import { full, Id } from '@audius/sdk' import { useQuery } from '@tanstack/react-query' import { audioTransactionFromSdk } from '~/adapters/audioTransactions' import { useQueryContext } from '~/api/tan-query/utils' import { ID } from '~/models' -import { - TransactionDetails, - TransactionType -} from '~/store/ui/transaction-details/types' -import { Nullable, removeNullable } from '~/utils/typeUtils' +import { TransactionDetails } from '~/store/ui/transaction-details/types' +import { Nullable } from '~/utils/typeUtils' import { QUERY_KEYS } from '../queryKeys' import { QueryKey, QueryOptions } from '../types' import { useCurrentUserId } from '../users/account/useCurrentUserId' -import { useUsers } from '../users/useUsers' type GetAudioTransactionsArgs = { page?: number @@ -85,23 +79,5 @@ export const useAudioTransactions = ( enabled: options?.enabled !== false && !!userId }) - // Get user IDs from tip transactions - const userIds = useMemo( - () => - queryResults.data - ?.map((tx: TransactionDetails) => { - if (tx.transactionType === TransactionType.TIP) { - return tx.metadata - } - return null - }) - .filter((tx: string | null) => tx !== null) - .filter(removeNullable) - .map((id: string) => parseInt(id)), - [queryResults.data] - ) - - useUsers(userIds) - return queryResults } diff --git a/packages/common/src/api/tan-query/queryKeys.ts b/packages/common/src/api/tan-query/queryKeys.ts index 060d4a4500b..c8f84579fe5 100644 --- a/packages/common/src/api/tan-query/queryKeys.ts +++ b/packages/common/src/api/tan-query/queryKeys.ts @@ -35,10 +35,6 @@ export const QUERY_KEYS = { collectionByPermalink: 'collectionByPermalink', followers: 'followers', favoritedTracks: 'favoritedTracks', - supporters: 'supporters', - supporter: 'supporter', - topSupporter: 'topSupporter', - supportedUsers: 'supportedUsers', relatedArtists: 'relatedArtists', rootWalletAddress: 'rootWalletAddress', mintRecovery: 'mintRecovery', @@ -101,8 +97,6 @@ export const QUERY_KEYS = { sendTokens: 'sendTokens', managedAccounts: 'managedAccounts', userManagers: 'userManagers', - reactions: 'reactions', - entityReaction: 'entityReaction', feelingLuckyTracks: 'feelingLuckyTracks', recentlyPlayedTracks: 'recentlyPlayedTracks', recentlyCommentedTracks: 'recentlyCommentedTracks', diff --git a/packages/common/src/api/tan-query/reactions/messages.ts b/packages/common/src/api/tan-query/reactions/messages.ts deleted file mode 100644 index 03e6227e678..00000000000 --- a/packages/common/src/api/tan-query/reactions/messages.ts +++ /dev/null @@ -1,4 +0,0 @@ -export const messages = { - mutationError: (action: 'writing' | 'fetching') => - `Error ${action} reaction. Please try again.` -} diff --git a/packages/common/src/api/tan-query/reactions/types.ts b/packages/common/src/api/tan-query/reactions/types.ts index 47a6ba5cd2d..8080e127ee3 100644 --- a/packages/common/src/api/tan-query/reactions/types.ts +++ b/packages/common/src/api/tan-query/reactions/types.ts @@ -1,26 +1,3 @@ -import { ID } from '~/models/Identifiers' - -export type Reaction = { - reactedTo: string - reactionValue: number | null - senderUserId: ID -} - -export type ReactionResponse = { - success: boolean - error?: string -} - -export type GetReactionsArgs = { - entityIds: string[] -} - -export type WriteReactionArgs = { - entityId: string - reaction: ReactionTypes | null - userId: ID -} - export type ReactionTypes = '😍' | '🔥' | '🥳' | '🤯' // The order these reactions appear in the web + mobile UI diff --git a/packages/common/src/api/tan-query/reactions/useReaction.ts b/packages/common/src/api/tan-query/reactions/useReaction.ts deleted file mode 100644 index 792063032e0..00000000000 --- a/packages/common/src/api/tan-query/reactions/useReaction.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { useMemo } from 'react' - -import { useQuery, useQueryClient } from '@tanstack/react-query' -import { useDispatch } from 'react-redux' - -import { useCurrentUserId } from '~/api/tan-query/users/account/useCurrentUserId' -import { useQueryContext } from '~/api/tan-query/utils' - -import { getReactionsBatcher } from '../batchers/getReactionsBatcher' -import { SelectableQueryOptions } from '../types' - -import { Reaction } from './types' -import { getEntityReactionQueryKey } from './utils' - -export const useReaction = ( - entityId: string | null | undefined, - options?: SelectableQueryOptions -) => { - const { audiusSdk } = useQueryContext() - const dispatch = useDispatch() - const queryClient = useQueryClient() - const { data: currentUserId } = useCurrentUserId() - - // eslint-disable-next-line react-hooks/exhaustive-deps - const select = useMemo(() => options?.select, []) - - return useQuery({ - queryKey: getEntityReactionQueryKey(entityId ?? ''), - queryFn: async () => { - const sdk = await audiusSdk() - const batchGetReactions = getReactionsBatcher({ - sdk, - queryClient, - dispatch, - currentUserId - }) - return await batchGetReactions.fetch(entityId!) - }, - ...options, - select, - enabled: options?.enabled !== false && !!entityId, - // Disable refetching since reactions are only updated through mutations - refetchOnWindowFocus: false, - refetchOnMount: false, - refetchOnReconnect: false, - staleTime: Infinity - }) -} diff --git a/packages/common/src/api/tan-query/reactions/useWriteReaction.ts b/packages/common/src/api/tan-query/reactions/useWriteReaction.ts deleted file mode 100644 index 14e06c4f755..00000000000 --- a/packages/common/src/api/tan-query/reactions/useWriteReaction.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Id } from '@audius/sdk' -import { useMutation, useQueryClient } from '@tanstack/react-query' -import { useDispatch } from 'react-redux' - -import { useQueryContext } from '~/api/tan-query/utils' -import { Feature } from '~/models' -import { toast } from '~/store/ui/toast/slice' - -import { messages } from './messages' -import { Reaction, WriteReactionArgs } from './types' -import { - getEntityReactionQueryKey, - getRawValueFromReaction, - getReactionsQueryKey -} from './utils' - -export const useWriteReaction = () => { - const { audiusSdk, reportToSentry } = useQueryContext() - const queryClient = useQueryClient() - const dispatch = useDispatch() - - return useMutation({ - mutationFn: async ({ entityId, reaction, userId }: WriteReactionArgs) => { - const sdk = await audiusSdk() - await sdk.users.sendTipReaction({ - userId: Id.parse(userId), - metadata: { - reactedTo: entityId, - reactionValue: reaction || '😍' - } - }) - }, - onMutate: async ({ entityId, reaction, userId }: WriteReactionArgs) => { - // Cancel any outgoing refetches - await queryClient.cancelQueries({ - queryKey: getEntityReactionQueryKey(entityId) - }) - - // Snapshot the previous value - const previousReaction = queryClient.getQueryData( - getEntityReactionQueryKey(entityId) - ) - - // Optimistically update to the new value - queryClient.setQueryData(getEntityReactionQueryKey(entityId), { - reactedTo: entityId, - reactionValue: getRawValueFromReaction(reaction), - senderUserId: userId - }) - - // Return a context object with the snapshotted value - return { previousReaction } - }, - onError: (err, { entityId }, context) => { - const error = err as Error - reportToSentry({ - error, - additionalInfo: { entityId }, - name: 'Reactions', - feature: Feature.Social - }) - dispatch(toast({ content: messages.mutationError('writing') })) - - // If the mutation fails, use the context returned from onMutate to roll back - if (context?.previousReaction) { - queryClient.setQueryData( - getEntityReactionQueryKey(entityId), - context.previousReaction - ) - } - }, - onSettled: (_, __, { entityId }) => { - // Always refetch after error or success to ensure we have the correct data - queryClient.invalidateQueries({ - queryKey: getEntityReactionQueryKey(entityId) - }) - queryClient.invalidateQueries({ - queryKey: getReactionsQueryKey([entityId]) - }) - } - }) -} diff --git a/packages/common/src/api/tan-query/reactions/utils.ts b/packages/common/src/api/tan-query/reactions/utils.ts index 7e26ca2c4ec..65b2304a361 100644 --- a/packages/common/src/api/tan-query/reactions/utils.ts +++ b/packages/common/src/api/tan-query/reactions/utils.ts @@ -1,15 +1,4 @@ -import { QUERY_KEYS } from '../queryKeys' -import { QueryKey } from '../types' - -import { ReactionTypes, reactionsMap, Reaction } from './types' - -export const getReactionsQueryKey = (entityIds: string[]) => - [QUERY_KEYS.reactions, entityIds] as unknown as QueryKey< - Record - > - -export const getEntityReactionQueryKey = (entityId: string) => - [QUERY_KEYS.entityReaction, entityId] as unknown as QueryKey +import { ReactionTypes, reactionsMap } from './types' export const getReactionFromRawValue = ( value: number | null diff --git a/packages/common/src/api/tan-query/users/useSupportedUsers.ts b/packages/common/src/api/tan-query/users/useSupportedUsers.ts deleted file mode 100644 index d35c573e599..00000000000 --- a/packages/common/src/api/tan-query/users/useSupportedUsers.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Id, OptionalId } from '@audius/sdk' -import { - InfiniteData, - useInfiniteQuery, - useQueryClient -} from '@tanstack/react-query' - -import { useQueryContext } from '~/api/tan-query/utils' -import { ID } from '~/models/Identifiers' -import { - SupportedUserMetadata, - supportedUserMetadataListFromSDK -} from '~/models/Tipping' -import { SUPPORTING_PAGINATION_SIZE } from '~/utils/constants' - -import { QUERY_KEYS } from '../queryKeys' -import { QueryKey, QueryOptions } from '../types' -import { primeUserData } from '../utils/primeUserData' - -import { useCurrentUserId } from './account/useCurrentUserId' -import { getSupporterQueryKey } from './useSupporter' - -type UseSupportedUsersArgs = { - userId: ID | null | undefined - pageSize?: number -} - -export const getSupportedUsersQueryKey = ( - userId: ID | null | undefined, - pageSize: number = SUPPORTING_PAGINATION_SIZE -) => - [QUERY_KEYS.supportedUsers, userId, pageSize] as unknown as QueryKey< - InfiniteData - > - -export const useSupportedUsers = ( - { userId, pageSize = SUPPORTING_PAGINATION_SIZE }: UseSupportedUsersArgs, - options?: QueryOptions -) => { - const { audiusSdk } = useQueryContext() - const queryClient = useQueryClient() - const { data: currentUserId } = useCurrentUserId() - - return useInfiniteQuery({ - queryKey: getSupportedUsersQueryKey(userId, pageSize), - initialPageParam: 0, - getNextPageParam: ( - lastPage: SupportedUserMetadata[], - allPages: SupportedUserMetadata[][] - ) => { - if (lastPage.length < pageSize) return undefined - return allPages.length * pageSize - }, - queryFn: async ({ pageParam }) => { - const sdk = await audiusSdk() - const { data = [] } = await sdk.full.users.getSupportedUsers({ - id: Id.parse(userId), - limit: pageSize, - offset: pageParam, - userId: OptionalId.parse(currentUserId) - }) - const supporting = supportedUserMetadataListFromSDK(data) - - // Prime the cache for each supporter - supporting.forEach((supportedUser) => { - queryClient.setQueryData( - getSupporterQueryKey(supportedUser.receiver.user_id, userId), - { - ...supportedUser, - sender: supportedUser.receiver - } - ) - }) - - primeUserData({ - users: supporting.map((supportedUser) => supportedUser.receiver), - queryClient - }) - return supporting - }, - select: (data) => data.pages.flat(), - ...options, - enabled: options?.enabled !== false && !!userId - }) -} diff --git a/packages/common/src/api/tan-query/users/useSupporter.ts b/packages/common/src/api/tan-query/users/useSupporter.ts deleted file mode 100644 index 7237b57aa36..00000000000 --- a/packages/common/src/api/tan-query/users/useSupporter.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Id, OptionalId } from '@audius/sdk' -import { useQuery, useQueryClient } from '@tanstack/react-query' - -import { useQueryContext } from '~/api/tan-query/utils' -import { ID } from '~/models/Identifiers' -import { - SupporterMetadata, - supporterMetadataFromSDK, - supporterMetadataListFromSDK -} from '~/models/Tipping' - -import { QUERY_KEYS } from '../queryKeys' -import { QueryKey, QueryOptions } from '../types' -import { primeUserData } from '../utils/primeUserData' - -import { useCurrentUserId } from './account/useCurrentUserId' - -type UseSupporterArgs = { - userId: ID | null | undefined - supporterUserId: ID | null | undefined -} - -const DEFAULT_STALE_TIME = 1000 * 30 - -export const getSupporterQueryKey = ( - userId: ID | null | undefined, - supporterUserId: ID | null | undefined -) => { - return [ - QUERY_KEYS.supporter, - userId, - supporterUserId - ] as unknown as QueryKey -} - -export const useSupporter = ( - { userId, supporterUserId }: UseSupporterArgs, - options?: QueryOptions -) => { - const { audiusSdk } = useQueryContext() - const { data: currentUserId } = useCurrentUserId() - const queryClient = useQueryClient() - - return useQuery({ - queryKey: getSupporterQueryKey(userId, supporterUserId), - queryFn: async () => { - const sdk = await audiusSdk() - const { data } = await sdk.full.users.getSupporter({ - id: Id.parse(userId), - supporterUserId: Id.parse(supporterUserId), - userId: OptionalId.parse(currentUserId) - }) - - if (!data) return null - - const supporter = supporterMetadataFromSDK(data) - if (supporter?.sender) { - primeUserData({ users: [supporter.sender], queryClient }) - } - return supporter - }, - staleTime: options?.staleTime ?? DEFAULT_STALE_TIME, - enabled: options?.enabled !== false && !!userId && !!supporterUserId - }) -} - -export const getTopSupporterQueryKey = (userId: ID | null | undefined) => { - return [ - QUERY_KEYS.topSupporter, - userId - ] as unknown as QueryKey -} - -export const useTopSupporter = (userId: ID | null | undefined) => { - const { audiusSdk } = useQueryContext() - const { data: currentUserId } = useCurrentUserId() - const queryClient = useQueryClient() - - return useQuery({ - queryKey: getTopSupporterQueryKey(userId), - queryFn: async () => { - const sdk = await audiusSdk() - const { data } = await sdk.full.users.getSupporters({ - id: Id.parse(userId), - userId: OptionalId.parse(currentUserId), - limit: 1 - }) - - if (!data) return null - - const [supporter] = supporterMetadataListFromSDK(data) - - // Prime the cache for each supporter - if (supporter?.sender) { - primeUserData({ users: [supporter.sender], queryClient }) - } - - return supporter - } - }) -} diff --git a/packages/common/src/api/tan-query/users/useSupporters.ts b/packages/common/src/api/tan-query/users/useSupporters.ts deleted file mode 100644 index f64e372f630..00000000000 --- a/packages/common/src/api/tan-query/users/useSupporters.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Id, OptionalId } from '@audius/sdk' -import { - InfiniteData, - useInfiniteQuery, - useQueryClient -} from '@tanstack/react-query' - -import { useQueryContext } from '~/api/tan-query/utils' -import { ID } from '~/models/Identifiers' -import { - SupporterMetadata, - supporterMetadataListFromSDK -} from '~/models/Tipping' - -import { QUERY_KEYS } from '../queryKeys' -import { QueryKey, QueryOptions } from '../types' -import { primeUserData } from '../utils/primeUserData' - -import { useCurrentUserId } from './account/useCurrentUserId' -import { getSupporterQueryKey } from './useSupporter' - -const DEFAULT_PAGE_SIZE = 20 - -type UseSupportersArgs = { - userId: ID | null | undefined - pageSize?: number -} - -export const getSupportersQueryKey = ( - userId: ID | null | undefined, - pageSize: number = DEFAULT_PAGE_SIZE -) => - [QUERY_KEYS.supporters, userId, pageSize] as unknown as QueryKey< - InfiniteData - > - -export const useSupporters = ( - { userId, pageSize = DEFAULT_PAGE_SIZE }: UseSupportersArgs, - options?: QueryOptions -) => { - const { audiusSdk } = useQueryContext() - const { data: currentUserId } = useCurrentUserId() - const queryClient = useQueryClient() - - return useInfiniteQuery({ - queryKey: getSupportersQueryKey(userId, pageSize), - initialPageParam: 0, - getNextPageParam: ( - lastPage: SupporterMetadata[], - allPages: SupporterMetadata[][] - ) => { - if (lastPage.length < pageSize) return undefined - return allPages.length * pageSize - }, - queryFn: async ({ pageParam }): Promise => { - const sdk = await audiusSdk() - const { data } = await sdk.full.users.getSupporters({ - id: Id.parse(userId), - limit: pageSize, - offset: pageParam, - userId: OptionalId.parse(currentUserId) - }) - const supporters = supporterMetadataListFromSDK(data) - - // Prime the cache for each supporter - supporters.forEach((supporter) => { - queryClient.setQueryData( - getSupporterQueryKey(userId, supporter.sender.user_id), - supporter - ) - }) - - primeUserData({ - users: supporters.map((supporter) => supporter.sender), - queryClient - }) - return supporters - }, - select: (data) => data.pages.flat(), - ...options, - enabled: options?.enabled !== false && !!userId - }) -} diff --git a/packages/common/src/context/comments/commentsContext.tsx b/packages/common/src/context/comments/commentsContext.tsx index 07479748d6e..b6200923b8c 100644 --- a/packages/common/src/context/comments/commentsContext.tsx +++ b/packages/common/src/context/comments/commentsContext.tsx @@ -18,7 +18,6 @@ import { QUERY_KEYS, useTrackCommentCount, resetPreviousCommentCount, - useSupporters, useTrack, useCurrentUserId } from '~/api' @@ -100,10 +99,6 @@ export function CommentSectionProvider( lineupActions } = props const { data: track } = useTrack(entityId) - const trackOwnerId = track?.owner_id - - // Prefetch the track owner's supporters - useSupporters({ userId: trackOwnerId }) const { analytics: { make, track: trackEvent } diff --git a/packages/common/src/hooks/chats/useAudienceUsers.ts b/packages/common/src/hooks/chats/useAudienceUsers.ts index 7ec8929b888..0eef43bb0ff 100644 --- a/packages/common/src/hooks/chats/useAudienceUsers.ts +++ b/packages/common/src/hooks/chats/useAudienceUsers.ts @@ -7,7 +7,6 @@ import { useFollowers, usePurchasers, useRemixers, - useSupporters, useUsers } from '~/api' import { UserMetadata } from '~/models' @@ -21,10 +20,6 @@ export const useAudienceUsers = (chat: ChatBlast, limit?: number) => { pageSize: limit }) const { data: followers } = useUsers(followerIds) - const { data: supporters } = useSupporters( - { userId: currentUserId, pageSize: limit }, - { enabled: chat.audience === ChatBlastAudience.TIPPERS } - ) const { data: purchasers } = usePurchasers( { contentId: OptionalHashId.parse(chat.audience_content_id), @@ -66,9 +61,6 @@ export const useAudienceUsers = (chat: ChatBlast, limit?: number) => { case ChatBlastAudience.FOLLOWERS: users = followers ?? [] break - case ChatBlastAudience.TIPPERS: - users = supporters?.map((supporter) => supporter.sender) ?? [] - break case ChatBlastAudience.CUSTOMERS: users = purchasersUsers ?? [] break diff --git a/packages/common/src/hooks/chats/useChatBlastAudienceContent.ts b/packages/common/src/hooks/chats/useChatBlastAudienceContent.ts index 003d163f7b3..8593ab71b07 100644 --- a/packages/common/src/hooks/chats/useChatBlastAudienceContent.ts +++ b/packages/common/src/hooks/chats/useChatBlastAudienceContent.ts @@ -68,8 +68,6 @@ export const useChatBlastAudienceContent = ({ chat }: { chat: ChatBlast }) => { switch (audience) { case ChatBlastAudience.FOLLOWERS: return user?.follower_count - case ChatBlastAudience.TIPPERS: - return user?.supporter_count case ChatBlastAudience.CUSTOMERS: return purchasersCount case ChatBlastAudience.REMIXERS: @@ -82,7 +80,6 @@ export const useChatBlastAudienceContent = ({ chat }: { chat: ChatBlast }) => { }, [ audience, user?.follower_count, - user?.supporter_count, purchasersCount, remixersCount, coinMembersCount diff --git a/packages/common/src/hooks/chats/useFirstAvailableBlastAudience.ts b/packages/common/src/hooks/chats/useFirstAvailableBlastAudience.ts index c6677b4d482..b88d4b8e833 100644 --- a/packages/common/src/hooks/chats/useFirstAvailableBlastAudience.ts +++ b/packages/common/src/hooks/chats/useFirstAvailableBlastAudience.ts @@ -22,18 +22,11 @@ export const useFirstAvailableBlastAudience = () => { const firstAvailableAudience = useMemo(() => { if (user?.follower_count) return ChatBlastAudience.FOLLOWERS - if (user?.supporter_count) return ChatBlastAudience.TIPPERS if (purchasersCount) return ChatBlastAudience.CUSTOMERS if (remixersCount) return ChatBlastAudience.REMIXERS if (coinMembersCount) return ChatBlastAudience.COIN_HOLDERS return null - }, [ - user?.follower_count, - user?.supporter_count, - purchasersCount, - remixersCount, - coinMembersCount - ]) + }, [user?.follower_count, purchasersCount, remixersCount, coinMembersCount]) return firstAvailableAudience } diff --git a/packages/common/src/hooks/index.ts b/packages/common/src/hooks/index.ts index eaeadd2d06c..49e637ecc08 100644 --- a/packages/common/src/hooks/index.ts +++ b/packages/common/src/hooks/index.ts @@ -41,7 +41,6 @@ export * from './useAccessAndRemixSettings' export * from './purchaseContent' export * from './content' export * from './chats' -export * from './useSupporterPrompt' export * from './useRemixCountdown' export * from './useFormattedUSDCBalance' export * from './useFormattedAudioBalance' diff --git a/packages/common/src/hooks/useAccessAndRemixSettings.test.ts b/packages/common/src/hooks/useAccessAndRemixSettings.test.ts index aa7fea4dce7..20e0937cb89 100644 --- a/packages/common/src/hooks/useAccessAndRemixSettings.test.ts +++ b/packages/common/src/hooks/useAccessAndRemixSettings.test.ts @@ -137,24 +137,6 @@ describe('useAccessAndRemixSettings', () => { } expect(actual).toEqual(expected) }) - it('tip gated - should enable everything', () => { - const actual = useAccessAndRemixSettings({ - isUpload: false, - isRemix: false, - isAlbum: undefined, - isInitiallyUnlisted: false, - isScheduledRelease: false - }) - const expected = { - disableUsdcGate: false, - disableSpecialAccessGate: false, - disableSpecialAccessGateFields: false, - disableTokenGate: false, - disableTokenGateFields: false, - disableHidden: false - } - expect(actual).toEqual(expected) - }) it('usdc gated - should enable everything', () => { const actual = useAccessAndRemixSettings({ isUpload: false, diff --git a/packages/common/src/hooks/useGatedContent.ts b/packages/common/src/hooks/useGatedContent.ts index ceedec15f61..bb85d159018 100644 --- a/packages/common/src/hooks/useGatedContent.ts +++ b/packages/common/src/hooks/useGatedContent.ts @@ -16,7 +16,6 @@ import { AccessConditions, Track, isContentFollowGated, - isContentTipGated, isContentTokenGated, isContentUSDCPurchaseGated } from '~/models/Track' @@ -136,23 +135,16 @@ export const useStreamConditionsEntity = ( const followUserId = isContentFollowGated(streamConditions) ? streamConditions?.follow_user_id : null - const tipUserId = isContentTipGated(streamConditions) - ? streamConditions?.tip_user_id - : null const tokenMint = isContentTokenGated(streamConditions) ? streamConditions?.token_gate.token_mint : null - const { byId: usersById } = useUsers( - [followUserId, tipUserId].filter(removeNullable) - ) + const { byId: usersById } = useUsers([followUserId].filter(removeNullable)) const followee = followUserId ? usersById[followUserId] : null - const tippedUser = tipUserId ? usersById[tipUserId] : null const { data: token } = useArtistCoin(tokenMint) return { followee, - tippedUser, token } } diff --git a/packages/common/src/hooks/useSupporterPrompt.ts b/packages/common/src/hooks/useSupporterPrompt.ts deleted file mode 100644 index 2434b454c7c..00000000000 --- a/packages/common/src/hooks/useSupporterPrompt.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { useMemo } from 'react' - -import { AUDIO, AudioWei } from '@audius/fixed-decimal' - -import { useCurrentUserId, useSupporter, useSupporters } from '~/api' -import { Nullable } from '~/utils/typeUtils' - -const zeroAudioWei = AUDIO('0').value -const oneAudioWei = AUDIO('1').value - -export const useSupporterPrompt = (receiverId?: Nullable) => { - const { data: accountUserId } = useCurrentUserId() - - // Get the top supporter - const { data: supporters = [], isPending: isSupportersPending } = - useSupporters({ - userId: receiverId, - pageSize: 1 - }) - const topSupporter = supporters[0] - - // Get the current user's support amount - const { - data: currentUserSupporter, - isPending: isCurrentUserSupporterPending - } = useSupporter({ userId: receiverId, supporterUserId: accountUserId }) - - // Compute if they would be first supporter - const isFirstSupporter = - !accountUserId || !receiverId - ? false - : !topSupporter && !currentUserSupporter - - // Compute amount needed to dethrone current top supporter - const amountToDethrone = useMemo(() => { - if ( - !accountUserId || - !receiverId || - !topSupporter || - accountUserId === topSupporter.sender.user_id - ) { - return null - } - - const topSupporterAmountWei = BigInt(topSupporter.amount) as AudioWei - const currentUserAmountWei = currentUserSupporter - ? (BigInt(currentUserSupporter.amount) as AudioWei) - : zeroAudioWei - - // Amount needed is (top supporter amount - current user amount + 1 AUDIO) - return (topSupporterAmountWei - - currentUserAmountWei + - oneAudioWei) as AudioWei - }, [accountUserId, receiverId, topSupporter, currentUserSupporter]) - - return { - isPending: isSupportersPending || isCurrentUserSupporterPending, - amountToDethrone, - isFirstSupporter - } -} diff --git a/packages/common/src/messages/edit.ts b/packages/common/src/messages/edit.ts index 2b5cdc47b23..9139ed763d8 100644 --- a/packages/common/src/messages/edit.ts +++ b/packages/common/src/messages/edit.ts @@ -26,7 +26,6 @@ export const priceAndAudienceMessages = { coinGated: 'Coin Gated', hidden: 'Hidden', followersOnly: 'Followers Only', - supportersOnly: 'Supporters Only', markedAsRemix: 'This track is marked as a remix. To enable additional availability options, unmark within Remix Settings.', done: 'Done', @@ -53,8 +52,7 @@ export const priceAndAudienceMessages = { specialAccessRadio: { title: 'Special Access', description: 'Anyone who meets your selected criteria can stream.', - followersOnly: 'Followers Only', - supportersOnly: 'Supporters Only' + followersOnly: 'Followers Only' }, tokenGatedRadio: { title: 'Coin Gated', diff --git a/packages/common/src/models/Analytics.ts b/packages/common/src/models/Analytics.ts index dab5cf7bc12..69dd1b6e1e8 100644 --- a/packages/common/src/models/Analytics.ts +++ b/packages/common/src/models/Analytics.ts @@ -3,11 +3,7 @@ import { ChatPermission, Genre } from '@audius/sdk' import { FeedFilter } from '~/models/FeedFilter' import { ID, PlayableType } from '~/models/Identifiers' import { TimeRange } from '~/models/TimeRange' -import { - SolanaWalletAddress, - StringAudio, - WalletAddress -} from '~/models/Wallet' +import { WalletAddress } from '~/models/Wallet' import { Nullable } from '~/utils/typeUtils' import { Chain } from './Chain' @@ -214,7 +210,6 @@ export enum Name { // Gated Track Uploads TRACK_UPLOAD_FOLLOW_GATED = 'Track Upload: Follow Gated', - TRACK_UPLOAD_TIP_GATED = 'Track Upload: Tip Gated', TRACK_UPLOAD_USDC_GATED = 'Track Upload: USDC Gated', TRACK_UPLOAD_TOKEN_GATED = 'Track Upload: Token Gated', TRACK_UPLOAD_CLICK_USDC_WAITLIST_LINK = 'Track Upload: Clicked USDC Waitlist Link', @@ -248,7 +243,6 @@ export enum Name { USDC_PURCHASE_GATED_TRACK_UNLOCKED = 'USDC Gated: Track Unlocked', USDC_PURCHASE_GATED_COLLECTION_UNLOCKED = 'USDC Gated: Collection Unlocked', FOLLOW_GATED_TRACK_UNLOCKED = 'Follow Gated: Track Unlocked', - TIP_GATED_TRACK_UNLOCKED = 'Tip Gated: Track Unlocked', TOKEN_GATED_TRACK_UNLOCKED = 'Token Gated: Track Unlocked', // Unlocked Download-Only Gated Tracks USDC_PURCHASE_GATED_DOWNLOAD_TRACK_UNLOCKED = 'USDC Gated: Download Track Unlocked', @@ -267,12 +261,7 @@ export enum Name { NOTIFICATIONS_CLICK_MILESTONE_TWITTER_SHARE = 'Notifications: Clicked Milestone Twitter Share', NOTIFICATIONS_CLICK_REMIX_CREATE_TWITTER_SHARE = 'Notifications: Clicked Remix Create Twitter Share', NOTIFICATIONS_CLICK_REMIX_COSIGN_TWITTER_SHARE = 'Notifications: Clicked Remix Co-Sign Twitter Share', - NOTIFICATIONS_CLICK_TIP_REACTION_TWITTER_SHARE = 'Notifications: Clicked Tip Reaction Twitter Share', - NOTIFICATIONS_CLICK_TIP_RECEIVED_TWITTER_SHARE = 'Notifications: Clicked Tip Received Twitter Share', - NOTIFICATIONS_CLICK_TIP_SENT_TWITTER_SHARE = 'Notifications: Clicked Tip Sent Twitter Share', NOTIFICATIONS_CLICK_DETHRONED_TWITTER_SHARE = 'Notifications: Clicked Dethroned Twitter Share', - NOTIFICATIONS_CLICK_SUPPORTER_RANK_UP_TWITTER_SHARE = 'Notifications: Clicked Supporter Rank Up Twitter Share', - NOTIFICATIONS_CLICK_SUPPORTING_RANK_UP_TWITTER_SHARE = 'Notifications: Clicked Supporting Rank Up Twitter Share', NOTIFICATIONS_CLICK_TRENDING_TRACK_TWITTER_SHARE = 'Notifications: Clicked Trending Track Twitter Share', NOTIFICATIONS_CLICK_TRENDING_PLAYLIST_TWITTER_SHARE = 'Notifications: Clicked Trending Playlist Twitter Share', NOTIFICATIONS_CLICK_TRENDING_UNDERGROUND_TWITTER_SHARE = 'Notifications: Clicked Trending Underground Twitter Share', @@ -381,13 +370,6 @@ export enum Name { REWARDS_CLAIM_SUCCESS = 'Rewards Claim: Success', REWARDS_CLAIM_BLOCKED = 'Rewards Claim: Blocked', - // Tipping - TIP_AUDIO_REQUEST = 'Tip Audio: Request', - TIP_AUDIO_SUCCESS = 'Tip Audio: Success', - TIP_AUDIO_FAILURE = 'Tip Audio: Failure', - TIP_AUDIO_TWITTER_SHARE = 'Tip Audio: Twitter Share', - TIP_FEED_TILE_DISMISS = 'Tip Feed Tile: Dismiss', - // Social Proof SOCIAL_PROOF_OPEN = 'Social Proof: Open', SOCIAL_PROOF_SUCCESS = 'Social Proof: Success', @@ -495,7 +477,6 @@ export enum Name { SEND_MESSAGE_REACTION_FAILURE = 'Send Message Reaction: Failure', MESSAGE_UNFURL_TRACK = 'Message Unfurl: Track', MESSAGE_UNFURL_PLAYLIST = 'Message Unfurl: Playlist', - TIP_UNLOCKED_CHAT = 'Unlocked Chat: Tip', CHAT_REPORT_USER = 'Report User: Chat', CHAT_ENTRY_POINT = 'Chat Entry Point', CHAT_WEBSOCKET_ERROR = 'Chat Websocket Error', @@ -1199,13 +1180,6 @@ type TrackUploadFollowGated = { lossless: boolean } -type TrackUploadTipGated = { - eventName: Name.TRACK_UPLOAD_TIP_GATED - kind: 'tracks' - downloadable: boolean - lossless: boolean -} - type TrackUploadUSDCGated = { eventName: Name.TRACK_UPLOAD_USDC_GATED price: number @@ -1333,11 +1307,6 @@ type FollowGatedTrackUnlocked = { trackId: number } -type TipGatedTrackUnlocked = { - eventName: Name.TIP_GATED_TRACK_UNLOCKED - trackId: number -} - type TokenGatedTrackUnlocked = { eventName: Name.TOKEN_GATED_TRACK_UNLOCKED trackId: number @@ -1393,30 +1362,10 @@ type NotificationsClickRemixCosign = { eventName: Name.NOTIFICATIONS_CLICK_REMIX_COSIGN_TWITTER_SHARE text: string } -type NotificationsClickTipReaction = { - eventName: Name.NOTIFICATIONS_CLICK_TIP_REACTION_TWITTER_SHARE - text: string -} -type NotificationsClickTipReceived = { - eventName: Name.NOTIFICATIONS_CLICK_TIP_RECEIVED_TWITTER_SHARE - text: string -} -type NotificationsClickTipSent = { - eventName: Name.NOTIFICATIONS_CLICK_TIP_SENT_TWITTER_SHARE - text: string -} type NotificationsClickDethroned = { eventName: Name.NOTIFICATIONS_CLICK_DETHRONED_TWITTER_SHARE text: string } -type NotificationsClickSupporterRankUp = { - eventName: Name.NOTIFICATIONS_CLICK_SUPPORTER_RANK_UP_TWITTER_SHARE - text: string -} -type NotificationsClickSupportingRankUp = { - eventName: Name.NOTIFICATIONS_CLICK_SUPPORTING_RANK_UP_TWITTER_SHARE - text: string -} type NotificationsClickAddTrackToPlaylist = { eventName: Name.NOTIFICATIONS_CLICK_ADD_TRACK_TO_PLAYLIST_TWITTER_SHARE text: string @@ -1830,68 +1779,6 @@ type RewardsClaimAllBlocked = { code: number } -export type TipSource = - | 'profile' - | 'feed' - | 'dethroned' - | 'buyAudio' - | 'trackPage' - | 'howToUnlockTrackPage' - | 'howToUnlockModal' - | 'inboxUnavailableModal' - -type TipAudioRequest = { - eventName: Name.TIP_AUDIO_REQUEST - amount: StringAudio - senderWallet?: SolanaWalletAddress - recipientWallet?: SolanaWalletAddress - senderHandle: string - recipientHandle: string - source: TipSource - device: 'web' | 'native' -} - -type TipAudioSuccess = { - eventName: Name.TIP_AUDIO_SUCCESS - amount: StringAudio - senderWallet?: SolanaWalletAddress - recipientWallet?: SolanaWalletAddress - senderHandle: string - recipientHandle: string - source: TipSource - device: 'web' | 'native' -} - -type TipAudioFailure = { - eventName: Name.TIP_AUDIO_FAILURE - amount: StringAudio - senderWallet?: SolanaWalletAddress - recipientWallet?: SolanaWalletAddress - senderHandle: string - recipientHandle: string - error: string - source: TipSource - device: 'web' | 'native' -} - -type TipAudioTwitterShare = { - eventName: Name.TIP_AUDIO_TWITTER_SHARE - amount: StringAudio - senderWallet?: SolanaWalletAddress - recipientWallet?: SolanaWalletAddress - senderHandle: string - recipientHandle: string - source: TipSource - device: 'web' | 'native' -} - -type TipFeedTileDismiss = { - eventName: Name.TIP_FEED_TILE_DISMISS - accountId: string - receiverId: string - device: 'web' | 'native' -} - type SocialProofOpen = { eventName: Name.SOCIAL_PROOF_OPEN kind: 'instagram' | 'twitter' | 'tiktok' @@ -2470,11 +2357,6 @@ type MessageUnfurlPlaylist = { eventName: Name.MESSAGE_UNFURL_PLAYLIST } -type TipUnlockedChat = { - eventName: Name.TIP_UNLOCKED_CHAT - recipientUserId: ID -} - type ChatReportUser = { eventName: Name.CHAT_REPORT_USER reportedUserId: ID @@ -3181,7 +3063,6 @@ export type AllTrackingEvents = | TrackUploadTrackUploading | TrackUploadCompleteUpload | TrackUploadFollowGated - | TrackUploadTipGated | TrackUploadUSDCGated | TrackUploadTokenGated | TrackUploadClickUSDCWaitListLink @@ -3208,7 +3089,6 @@ export type AllTrackingEvents = | TrackUploadViewTrackPage | USDCGatedTrackUnlocked | FollowGatedTrackUnlocked - | TipGatedTrackUnlocked | TokenGatedTrackUnlocked | USDCGatedDownloadTrackUnlocked | FollowGatedDownloadTrackUnlocked @@ -3220,12 +3100,7 @@ export type AllTrackingEvents = | NotificationsClickMilestone | NotificationsClickRemixCreate | NotificationsClickRemixCosign - | NotificationsClickTipReaction - | NotificationsClickTipReceived - | NotificationsClickTipSent | NotificationsClickDethroned - | NotificationsClickSupporterRankUp - | NotificationsClickSupportingRankUp | NotificationsClickAddTrackToPlaylist | NotificationsClickTrendingPlaylist | NotificationsClickTrendingTrack @@ -3299,11 +3174,6 @@ export type AllTrackingEvents = | RewardsClaimAllSuccess | RewardsClaimAllFailure | RewardsClaimAllBlocked - | TipAudioRequest - | TipAudioSuccess - | TipAudioFailure - | TipAudioTwitterShare - | TipFeedTileDismiss | SocialProofOpen | SocialProofSuccess | SocialProofError @@ -3403,7 +3273,6 @@ export type AllTrackingEvents = | SendMessageReactionFailure | MessageUnfurlTrack | MessageUnfurlPlaylist - | TipUnlockedChat | ChatReportUser | DeveloperAppCreateSubmit | DeveloperAppCreateSuccess diff --git a/packages/common/src/models/Tipping.ts b/packages/common/src/models/Tipping.ts deleted file mode 100644 index a47da279580..00000000000 --- a/packages/common/src/models/Tipping.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { full } from '@audius/sdk' - -import { userMetadataFromSDK } from '~/adapters/user' -import { ID } from '~/models/Identifiers' -import { removeNullable } from '~/utils/typeUtils' - -import { UserMetadata } from './User' -import { StringWei } from './Wallet' - -export type Supporter = { - sender_id: ID - amount: StringWei - rank: number -} - -export type Supporting = { - receiver_id: ID - amount: StringWei - rank: number -} - -export type UserTip = { - amount: StringWei - sender_id: ID - receiver_id: ID - followee_supporter_ids: ID[] - slot: number - created_at: string - tx_signature: string -} - -export type UserTipWithUsers = UserTip & { - sender: UserMetadata - receiver: UserMetadata - followee_supporters: { user_id: string }[] -} - -export type LastDismissedTip = { - receiver_id: ID -} - -export type SupporterMetadata = { - sender: UserMetadata - amount: StringWei - rank: number -} - -export type SupportedUserMetadata = { - receiver: UserMetadata - amount: StringWei - rank: number -} - -export const supporterMetadataFromSDK = ( - input: full.FullSupporter -): SupporterMetadata | undefined => { - const user = userMetadataFromSDK(input.sender) - return user - ? { sender: user, amount: input.amount as StringWei, rank: input.rank } - : undefined -} - -export const supporterMetadataListFromSDK = (input?: full.FullSupporter[]) => - input - ? input.map((d) => supporterMetadataFromSDK(d)).filter(removeNullable) - : [] - -export const supportedUserMetadataFromSDK = ( - input: full.FullSupporting -): SupportedUserMetadata | undefined => { - const user = userMetadataFromSDK(input.receiver) - return user - ? { receiver: user, amount: input.amount as StringWei, rank: input.rank } - : undefined -} - -export const supportedUserMetadataListFromSDK = ( - input?: full.FullSupporting[] -) => - input - ? input.map((d) => supportedUserMetadataFromSDK(d)).filter(removeNullable) - : [] diff --git a/packages/common/src/models/Track.ts b/packages/common/src/models/Track.ts index b443a691493..efadc43c471 100644 --- a/packages/common/src/models/Track.ts +++ b/packages/common/src/models/Track.ts @@ -46,8 +46,6 @@ export type RemixOf = { // Gated content export type FollowGatedConditions = { follow_user_id: number } -export type TipGatedConditions = { tip_user_id: number } - export type TokenGatedConditions = { token_gate: { token_mint: string @@ -76,7 +74,6 @@ export type USDCPurchaseConditions = { export type AccessConditions = | FollowGatedConditions - | TipGatedConditions | USDCPurchaseConditions | TokenGatedConditions | NftGatedConditions @@ -94,7 +91,6 @@ export enum GatedContentType { export enum TrackAccessType { PUBLIC = 'public', - TIP_GATED = 'tip_gated', FOLLOW_GATED = 'follow_gated', USDC_GATED = 'usdc_gated', TOKEN_GATED = 'token_gated' @@ -105,11 +101,6 @@ export const isContentFollowGated = ( ): gatedConditions is FollowGatedConditions => !!gatedConditions && 'follow_user_id' in (gatedConditions ?? {}) -export const isContentTipGated = ( - gatedConditions?: Nullable -): gatedConditions is TipGatedConditions => - !!gatedConditions && 'tip_user_id' in (gatedConditions ?? {}) - export const isContentTokenGated = ( gatedConditions?: Nullable ): gatedConditions is TokenGatedConditions => @@ -122,8 +113,8 @@ export const isContentNftGated = ( export const isContentSpecialAccess = ( gatedConditions?: Nullable -): gatedConditions is TipGatedConditions | FollowGatedConditions => - isContentFollowGated(gatedConditions) || isContentTipGated(gatedConditions) +): gatedConditions is FollowGatedConditions => + isContentFollowGated(gatedConditions) export const isContentUSDCPurchaseGated = ( gatedConditions?: Nullable< diff --git a/packages/common/src/models/User.ts b/packages/common/src/models/User.ts index 8565ac5ee3d..e1496aa1805 100644 --- a/packages/common/src/models/User.ts +++ b/packages/common/src/models/User.ts @@ -62,8 +62,6 @@ export type UserMetadata = { repost_count: number spl_wallet: Nullable spl_usdc_payout_wallet?: Nullable - supporter_count: number - supporting_count: number total_balance?: Nullable track_count: number user_id: number diff --git a/packages/common/src/models/index.ts b/packages/common/src/models/index.ts index 4516b8faf4a..2eef91d1321 100644 --- a/packages/common/src/models/index.ts +++ b/packages/common/src/models/index.ts @@ -27,7 +27,6 @@ export * from './Stems' export * from './Theme' export * from './TimeRange' export * from './Timestamped' -export * from './Tipping' export * from './Track' export * from './TrackAvailabilityType' export * from './USDCTransactions' diff --git a/packages/common/src/schemas/upload/uploadFormSchema.ts b/packages/common/src/schemas/upload/uploadFormSchema.ts index 6bbe1402e17..d85b6cb5c2e 100644 --- a/packages/common/src/schemas/upload/uploadFormSchema.ts +++ b/packages/common/src/schemas/upload/uploadFormSchema.ts @@ -26,13 +26,6 @@ const FollowGatedConditionsSchema = z }) .strict() -/** Same as SDK but snake-cased */ -const TipGatedConditionsSchema = z - .object({ - tip_user_id: z.number() - }) - .strict() - const TokenGatedConditionsSchema = z .object({ token_gate: z.object({ @@ -94,7 +87,6 @@ const premiumMetadataSchema = z.object({ .optional( z.union([ FollowGatedConditionsSchema, - TipGatedConditionsSchema, USDCPurchaseConditionsSchema, TokenGatedConditionsSchema ]) @@ -105,7 +97,6 @@ const premiumMetadataSchema = z.object({ .optional( z.union([ FollowGatedConditionsSchema, - TipGatedConditionsSchema, USDCPurchaseConditionsSchema, TokenGatedConditionsSchema ]) diff --git a/packages/common/src/services/remote-config/defaults.ts b/packages/common/src/services/remote-config/defaults.ts index 80dd28b6490..a7f167f3fb5 100644 --- a/packages/common/src/services/remote-config/defaults.ts +++ b/packages/common/src/services/remote-config/defaults.ts @@ -65,7 +65,7 @@ export const remoteConfigStringDefaults: { [StringKeys.TRENDING_REWARD_IDS]: 'trending-track,trending-playlist,trending-underground,top-api', [StringKeys.CHALLENGE_REWARD_IDS]: - 'track-upload,invite-friends,mobile-app,listen-streak,profile-completion,send-first-tip,first-playlist', + 'track-upload,invite-friends,mobile-app,listen-streak,profile-completion,first-playlist', [StringKeys.REWARDS_TWEET_ID_TRACKS]: '1374856377651187713', [StringKeys.REWARDS_TWEET_ID_PLAYLISTS]: '1374856377651187713', [StringKeys.REWARDS_TWEET_ID_UNDERGROUND]: '1374856377651187713', diff --git a/packages/common/src/store/gated-content/sagas.ts b/packages/common/src/store/gated-content/sagas.ts index af701377298..db4a5770638 100644 --- a/packages/common/src/store/gated-content/sagas.ts +++ b/packages/common/src/store/gated-content/sagas.ts @@ -18,7 +18,6 @@ import { ID, Name, isContentFollowGated, - isContentTipGated, isContentTokenGated, isContentUSDCPurchaseGated, GatedContentStatus, @@ -29,7 +28,6 @@ import { IntKeys } from '~/services/remote-config' import { getContext } from '~/store/effects' import { musicConfettiActions } from '~/store/music-confetti' import { usersSocialActions } from '~/store/social' -import { tippingActions } from '~/store/tipping' import { Nullable } from '~/utils/typeUtils' import { PurchaseableContentType } from '../purchase-content' @@ -44,12 +42,9 @@ const { updateGatedContentStatus, updateGatedContentStatuses, addFolloweeId, - removeFolloweeId, - addTippedUserId, - removeTippedUserId + removeFolloweeId } = gatedContentActions -const { refreshTipGatedTracks } = tippingActions const { show: showConfetti } = musicConfettiActions export function* pollGatedContent({ @@ -122,7 +117,6 @@ export function* pollGatedContent({ yield* put(updateGatedContentStatus({ contentId, status: 'UNLOCKED' })) // note: if necessary, update some ui status to show that the download is unlocked yield* put(removeFolloweeId({ id: ownerId })) - yield* put(removeTippedUserId({ id: ownerId })) // Show confetti if track is unlocked from the how to unlock section on track/collection page or modal if (isSourceTrack) { @@ -142,9 +136,6 @@ export function* pollGatedContent({ if (isContentFollowGated(apiEntity.stream_conditions)) { return Name.FOLLOW_GATED_TRACK_UNLOCKED } - if (isContentTipGated(apiEntity.stream_conditions)) { - return Name.TIP_GATED_TRACK_UNLOCKED - } if (isContentTokenGated(apiEntity.stream_conditions)) { return Name.TOKEN_GATED_TRACK_UNLOCKED } @@ -199,27 +190,22 @@ export function* pollGatedContent({ } /** - * 1. Get follow or tip gated tracks of user + * 1. Get follow gated tracks of user * 2. Set those track statuses to 'UNLOCKING' * 3. Poll for access for those tracks * 4. When access is returned, set those track statuses as 'UNLOCKED' */ function* updateSpecialAccessTracks( trackOwnerId: ID, - gate: 'follow' | 'tip', sourceTrackId?: Nullable ) { const currentUser = yield* call(queryAccountUser) const currentUserId = currentUser?.user_id if (!currentUserId) return - // Add followee or tipped user id to gated content store to subscribe to + // Add followee id to gated content store to subscribe to // polling their newly loaded gated track signatures. - if (gate === 'follow') { - yield* put(addFolloweeId({ id: trackOwnerId })) - } else { - yield* put(addTippedUserId({ id: trackOwnerId })) - } + yield* put(addFolloweeId({ id: trackOwnerId })) const statusMap: { [id: ID]: GatedContentStatus } = {} const tracksToPoll: Set = new Set() @@ -232,14 +218,8 @@ function* updateSpecialAccessTracks( stream_conditions: streamConditions, download_conditions: downloadConditions } = cachedTracks[id] - const isTrackStreamGated = - gate === 'follow' - ? isContentFollowGated(streamConditions) - : isContentTipGated(streamConditions) - const isTrackDownloadGated = - gate === 'follow' - ? isContentFollowGated(downloadConditions) - : isContentTipGated(downloadConditions) + const isTrackStreamGated = isContentFollowGated(streamConditions) + const isTrackDownloadGated = isContentFollowGated(downloadConditions) if (isTrackStreamGated && ownerId === trackOwnerId) { statusMap[id] = 'UNLOCKING' // note: if necessary, update some ui status to show that the track download is unlocking @@ -306,23 +286,7 @@ function* handleUnfollowUser( function* handleFollowUser( action: ReturnType ) { - yield* call( - updateSpecialAccessTracks, - action.userId, - 'follow', - action.trackId - ) -} - -function* handleTipGatedTracks( - action: ReturnType -) { - yield* call( - updateSpecialAccessTracks, - action.payload.userId, - 'tip', - action.payload.trackId - ) + yield* call(updateSpecialAccessTracks, action.userId, action.trackId) } /** @@ -350,19 +314,10 @@ function* watchUnfollowGatedTracks() { yield* takeEvery(usersSocialActions.UNFOLLOW_USER, handleUnfollowUser) } -function* watchTipGatedTracks() { - yield* takeEvery(refreshTipGatedTracks.type, handleTipGatedTracks) -} - function* watchRevokeAccess() { yield* takeEvery(revokeAccess.type, handleRevokeAccess) } export const sagas = () => { - return [ - watchFollowGatedTracks, - watchUnfollowGatedTracks, - watchTipGatedTracks, - watchRevokeAccess - ] + return [watchFollowGatedTracks, watchUnfollowGatedTracks, watchRevokeAccess] } diff --git a/packages/common/src/store/gated-content/selectors.ts b/packages/common/src/store/gated-content/selectors.ts index c883ab9bae8..2375e93a71c 100644 --- a/packages/common/src/store/gated-content/selectors.ts +++ b/packages/common/src/store/gated-content/selectors.ts @@ -11,6 +11,3 @@ export const getLockedContentId = (state: CommonState) => export const getFolloweeIds = (state: CommonState) => state.gatedContent.followeeIds - -export const getTippedUserIds = (state: CommonState) => - state.gatedContent.tippedUserIds diff --git a/packages/common/src/store/gated-content/slice.ts b/packages/common/src/store/gated-content/slice.ts index 2eaa90dc2db..55cda618272 100644 --- a/packages/common/src/store/gated-content/slice.ts +++ b/packages/common/src/store/gated-content/slice.ts @@ -8,15 +8,13 @@ type GatedContentState = { statusMap: { [id: ID]: GatedContentStatus } lockedContentId: Nullable followeeIds: ID[] - tippedUserIds: ID[] } const initialState: GatedContentState = { nftAccessSignatureMap: {}, statusMap: {}, lockedContentId: null, - followeeIds: [], - tippedUserIds: [] + followeeIds: [] } type UpdateNftAccessSignaturesPayload = { @@ -84,14 +82,6 @@ const slice = createSlice({ state.followeeIds = state.followeeIds.filter( (id) => id !== action.payload.id ) - }, - addTippedUserId: (state, action: PayloadAction) => { - state.tippedUserIds.push(action.payload.id) - }, - removeTippedUserId: (state, action: PayloadAction) => { - state.tippedUserIds = state.tippedUserIds.filter( - (id) => id !== action.payload.id - ) } } }) @@ -104,9 +94,7 @@ export const { setLockedContentId, resetLockedContentId, addFolloweeId, - removeFolloweeId, - addTippedUserId, - removeTippedUserId + removeFolloweeId } = slice.actions export const actions = slice.actions diff --git a/packages/common/src/store/index.ts b/packages/common/src/store/index.ts index b9491ae2aba..e833c99ee4d 100644 --- a/packages/common/src/store/index.ts +++ b/packages/common/src/store/index.ts @@ -17,7 +17,6 @@ export * from './remote-config' export * from './sign-out' export * from './social' export * from './stems-upload' -export * from './tipping' export * from './wallet' export * from './ui' export * from './user-list' diff --git a/packages/common/src/store/notifications/types.ts b/packages/common/src/store/notifications/types.ts index b0b93f1ddf6..9c3f6786446 100644 --- a/packages/common/src/store/notifications/types.ts +++ b/packages/common/src/store/notifications/types.ts @@ -32,14 +32,8 @@ export enum NotificationType { ChallengeReward = 'ChallengeReward', ClaimableReward = 'ClaimableReward', TierChange = 'TierChange', - Reaction = 'Reaction', - TipReceive = 'TipReceive', - TipSend = 'TipSend', - SupporterRankUp = 'SupporterRankUp', - SupportingRankUp = 'SupportingRankUp', AddTrackToPlaylist = 'AddTrackToPlaylist', TrackAddedToPurchasedAlbum = 'TrackAddedToPurchasedAlbum', - SupporterDethroned = 'SupporterDethroned', USDCPurchaseSeller = 'USDCPurchaseSeller', USDCPurchaseBuyer = 'USDCPurchaseBuyer', RequestManager = 'RequestManager', @@ -83,13 +77,6 @@ export enum PushNotificationType { Tastemaker = 'Tastemaker', TierChange = 'TierChange', PlaylistUpdate = 'PlaylistUpdate', - Tip = 'Tip', - TipReceive = 'TipReceive', - TipSend = 'TipSend', - Reaction = 'Reaction', - SupporterRankUp = 'SupporterRankUp', - SupportingRankUp = 'SupportingRankUp', - SupporterDethroned = 'SupporterDethroned', AddTrackToPlaylist = 'AddTrackToPlaylist', TrackAddedToPurchasedAlbum = 'TrackAddedToPurchasedAlbum', Message = 'Message', @@ -495,124 +482,6 @@ export type TierChangeNotification = BaseNotification & { tier: BadgeTier } -// TODO: when we support multiple reaction types, reactedToEntity type -// should differ in a discrimated union reactionType -export type ReactionNotification = BaseNotification & { - type: NotificationType.Reaction - entityId: ID - entityType: Entity.User - reactionValue: number - reactionType: string - reactedToEntity: { - tx_signature: string - amount: StringWei - tip_sender_id: ID - } -} - -export type ReactionPushNotification = { - type: PushNotificationType.Reaction - initiator: ID - slot: number - metadata: { - // TODO: Need to verify camelCase vs snake_case - reaction_value: number - reacted_to_entity: { - tx_signature: string - tip_sender_id: ID - amount: string - } - reaction_type: string - } -} - -export type TipReceiveNotification = BaseNotification & { - type: NotificationType.TipReceive - amount: StringWei - reactionValue: number - entityId: ID - entityType: Entity.User - tipTxSignature: string -} - -export type TipReceivePushNotification = { - type: PushNotificationType.TipReceive - slot: number - initiator: ID - metadata: { - entity_id: ID - entity_type: Entity.User - amount: StringWei - tx_signature: string - } -} - -export type TipSendNotification = BaseNotification & { - type: NotificationType.TipSend - amount: StringWei - entityId: ID - entityType: Entity.User -} - -export type TipSendPushNotification = { - type: PushNotificationType.TipSend - slot: number - initiator: ID - metadata: { - // TODO: Need to verify camelCase vs snake_case - entityId: ID - entityType: Entity.User - amount: StringWei - tipTxSignature: string - } -} - -export type SupporterRankUpNotification = BaseNotification & { - type: NotificationType.SupporterRankUp - rank: number - entityId: ID - entityType: Entity.User -} - -export type SupporterRankUpPushNotification = { - initiator: ID - slot: number - type: PushNotificationType.SupporterRankUp - metadata: { - rank: number - entity_type: Entity.User - entity_id: ID - } -} - -export type SupportingRankUpNotification = BaseNotification & { - type: NotificationType.SupportingRankUp - rank: number - entityId: ID - entityType: Entity.User -} - -export type SupportingRankUpPushNotification = { - initiator: ID - slot: number - type: PushNotificationType.SupportingRankUp - metadata: { - rank: number - entity_type: Entity.User - entity_id: ID - } -} - -export type SupporterDethronedNotification = BaseNotification & { - type: NotificationType.SupporterDethroned - entityType: Entity.User - entityId: ID // The usurping user - supportedUserId: ID - // Not currently used: - // newAmount "3000000000000000000" - // oldAmount "2000000000000000000" -} - export type AddTrackToPlaylistNotification = BaseNotification & { type: NotificationType.AddTrackToPlaylist trackId: ID @@ -782,12 +651,6 @@ export type Notification = | ChallengeRewardNotification | ClaimableRewardNotification | TierChangeNotification - | ReactionNotification - | TipReceiveNotification - | TipSendNotification - | SupporterRankUpNotification - | SupportingRankUpNotification - | SupporterDethronedNotification | AddTrackToPlaylistNotification | TrackAddedToPurchasedAlbumNotification | USDCPurchaseSellerNotification diff --git a/packages/common/src/store/pages/chat/selectors.ts b/packages/common/src/store/pages/chat/selectors.ts index f5c8e768b15..151dbdb5298 100644 --- a/packages/common/src/store/pages/chat/selectors.ts +++ b/packages/common/src/store/pages/chat/selectors.ts @@ -282,8 +282,6 @@ export const useCanCreateChat = (userId: ID | null | undefined) => { action = ChatPermissionAction.UNBLOCK } else if (userPermissions.permit_list.includes(ChatPermission.FOLLOWERS)) { action = ChatPermissionAction.FOLLOW - } else if (userPermissions.permit_list.includes(ChatPermission.TIPPERS)) { - action = ChatPermissionAction.TIP } else { action = ChatPermissionAction.NONE } diff --git a/packages/common/src/store/pages/chat/types.ts b/packages/common/src/store/pages/chat/types.ts index cf5a1b7ecee..b52f5bb264e 100644 --- a/packages/common/src/store/pages/chat/types.ts +++ b/packages/common/src/store/pages/chat/types.ts @@ -8,8 +8,6 @@ export enum ChatPermissionAction { NOT_APPLICABLE, /** Nothing current user can do (they're blocked or other user has closed inbox) */ NONE, - /** Current user can tip user */ - TIP, /** Current user can follow user */ FOLLOW, /** Current user can unblock user */ @@ -38,8 +36,6 @@ export class ChatWebsocketError extends Error { export type InboxSettingsFormValues = { [ChatPermission.ALL]: boolean [ChatPermission.FOLLOWEES]: boolean - [ChatPermission.TIPPERS]: boolean - [ChatPermission.TIPPEES]: boolean [ChatPermission.FOLLOWERS]: boolean [ChatPermission.VERIFIED]: boolean } diff --git a/packages/common/src/store/reducers.ts b/packages/common/src/store/reducers.ts index 50b8056455e..b41e9db0b4f 100644 --- a/packages/common/src/store/reducers.ts +++ b/packages/common/src/store/reducers.ts @@ -62,7 +62,6 @@ import savedCollectionsReducer from './saved-collections/slice' import searchReducer from './search/slice' import { SearchState } from './search/types' import stemsUpload from './stems-upload/slice' -import tippingReducer from './tipping/slice' import { searchUsersModalReducer, SearchUsersModalState, @@ -102,8 +101,6 @@ import purchasersUserListReducer from './user-list/purchasers/reducers' import relatedArtistsListReducer from './user-list/related-artists/reducers' import remixersUserListReducer from './user-list/remixers/reducers' import repostsUserListReducer from './user-list/reposts/reducers' -import supportingUserListReducer from './user-list/supporting/reducers' -import topSupportersUserListReducer from './user-list/top-supporters/reducers' import wallet from './wallet/slice' /** @@ -162,8 +159,6 @@ export const reducers = (storage: Storage, history?: History) => ({ following: followingUserListReducer, reposts: repostsUserListReducer, favorites: favoritesUserListReducer, - topSupporters: topSupportersUserListReducer, - supporting: supportingUserListReducer, mutuals: mutualsUserListReducer, notifications: notificationsUserListReducer, relatedArtists: relatedArtistsListReducer, @@ -200,9 +195,6 @@ export const reducers = (storage: Storage, history?: History) => ({ search: searchReducer(storage), stemsUpload, - // Tipping - tipping: tippingReducer, - // Gated content buyUSDC: buyUSDCReducer, gatedContent, @@ -271,8 +263,6 @@ export type CommonState = { following: ReturnType reposts: ReturnType favorites: ReturnType - topSupporters: ReturnType - supporting: ReturnType relatedArtists: ReturnType purchasers: ReturnType remixers: ReturnType @@ -310,9 +300,6 @@ export type CommonState = { // USDC buyUSDC: ReturnType - // Tipping - tipping: ReturnType - // Gated content purchaseContent: ReturnType gatedContent: ReturnType diff --git a/packages/common/src/store/sagas.ts b/packages/common/src/store/sagas.ts index d606dace8a0..e13ac8e569a 100644 --- a/packages/common/src/store/sagas.ts +++ b/packages/common/src/store/sagas.ts @@ -85,8 +85,6 @@ export const sagas = (_ctx: CommonStoreContext) => ({ // pages/user-list/reposts/sagas.ts // pages/user-list/favorites/sagas.ts // pages/user-list/mutuals/sagas.ts - // pages/user-list/supporting/sagas.ts - // pages/user-list/top-supporters/sagas.ts // pages/search-explore-page/store/sagas.ts // pages/search-explore-page/store/exploreCollections/sagas.ts // store/solana/sagas.ts diff --git a/packages/common/src/store/tipping/index.ts b/packages/common/src/store/tipping/index.ts deleted file mode 100644 index 03513d950a5..00000000000 --- a/packages/common/src/store/tipping/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * as tippingSelectors from './selectors' -export { default as tippingReducer, actions as tippingActions } from './slice' -export * from './types' diff --git a/packages/common/src/store/tipping/selectors.ts b/packages/common/src/store/tipping/selectors.ts deleted file mode 100644 index 24e892fa42f..00000000000 --- a/packages/common/src/store/tipping/selectors.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { CommonState } from '../commonStore' - -export const getSendStatus = (state: CommonState) => state.tipping.send.status -export const getSendAmount = (state: CommonState) => state.tipping.send.amount -export const getSendUser = (state: CommonState) => state.tipping.send.user -export const getSendTipData = (state: CommonState) => state.tipping.send diff --git a/packages/common/src/store/tipping/slice.ts b/packages/common/src/store/tipping/slice.ts deleted file mode 100644 index 274fd02b1a8..00000000000 --- a/packages/common/src/store/tipping/slice.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Action, createSlice, PayloadAction } from '@reduxjs/toolkit' - -import { TipSource } from '../../models/Analytics' -import { ID } from '../../models/Identifiers' -import { UserTip } from '../../models/Tipping' -import { User } from '../../models/User' -import type { Nullable } from '../../utils/typeUtils' - -import { TippingState } from './types' - -const initialState: TippingState = { - send: { - status: null, - user: null, - amount: '0', - error: null, - source: 'profile', - trackId: null - }, - tipToDisplay: null, - showTip: false -} - -const slice = createSlice({ - name: 'tipping', - initialState, - reducers: { - beginTip: ( - state, - action: PayloadAction<{ - user: User | null | undefined - source: TipSource - trackId?: ID - onSuccessActions?: Action[] - onSuccessConfirmedActions?: Action[] - }> - ) => { - if (!action.payload.user) { - return - } - state.send.status = 'SEND' - state.send.source = action.payload.source - state.send.user = action.payload.user - state.send.trackId = action.payload.trackId ?? null - state.send.onSuccessActions = action.payload.onSuccessActions - state.send.onSuccessConfirmedActions = - action.payload.onSuccessConfirmedActions - }, - sendTip: (state, action: PayloadAction<{ amount: string }>) => { - if (state.send.status !== 'SEND') { - return - } - state.send.status = 'CONFIRM' - state.send.amount = action.payload.amount - }, - confirmSendTip: (state) => { - if (state.send.status !== 'CONFIRM' && state.send.status !== 'ERROR') { - return - } - state.send.status = 'SENDING' - }, - convert: (state) => { - if (state.send.status !== 'SENDING') { - return - } - state.send.status = 'CONVERTING' - }, - sendTipSucceeded: (state) => { - state.send.status = 'SUCCESS' - }, - sendTipFailed: (state, action: PayloadAction<{ error: string }>) => { - state.send.status = 'ERROR' - state.send.error = action.payload.error - }, - resetSend: (state) => { - state.send.status = null - state.send.user = null - state.send.amount = '0' - state.send.error = null - state.send.trackId = null - }, - fetchRecentTips: (_state) => {}, - setTipToDisplay: ( - state, - action: PayloadAction<{ tipToDisplay: UserTip }> - ) => { - state.tipToDisplay = action.payload.tipToDisplay - }, - setShowTip: (state, action: PayloadAction<{ show: boolean }>) => { - state.showTip = action.payload.show - }, - refreshTipGatedTracks: ( - _state, - _action: PayloadAction<{ userId: ID; trackId?: Nullable }> - ) => { - // triggers saga - }, - revokeFollowGatedAccess: ( - _state, - _action: PayloadAction<{ userId: ID; trackId?: Nullable }> - ) => { - // triggers saga - } - } -}) - -export const { - beginTip, - sendTip, - confirmSendTip, - convert, - sendTipSucceeded, - sendTipFailed, - resetSend, - fetchRecentTips, - setTipToDisplay, - setShowTip, - refreshTipGatedTracks, - revokeFollowGatedAccess -} = slice.actions - -export const actions = slice.actions - -export default slice.reducer diff --git a/packages/common/src/store/tipping/types.ts b/packages/common/src/store/tipping/types.ts deleted file mode 100644 index fe63b67b287..00000000000 --- a/packages/common/src/store/tipping/types.ts +++ /dev/null @@ -1,36 +0,0 @@ -import type { Action } from '@reduxjs/toolkit' - -import { TipSource } from '../../models/Analytics' -import { UserTip } from '../../models/Tipping' -import { User } from '../../models/User' -import { StringAudio } from '../../models/Wallet' -import { Nullable } from '../../utils/typeUtils' - -export type TippingSendStatus = - | 'SEND' - | 'CONFIRM' - | 'SENDING' - | 'CONVERTING' - | 'SUCCESS' - | 'ERROR' - -export type TippingState = { - send: { - status: Nullable - user: Nullable - amount: StringAudio - error: Nullable - source: TipSource - trackId: Nullable // in case the user is sending a tip from a gated track page / modal - /** - * Actions to fire when the tip sends successfully - */ - onSuccessActions?: Action[] - /** - * Actions to fire when the tip is confirmed to be indexed by API - */ - onSuccessConfirmedActions?: Action[] - } - tipToDisplay: Nullable - showTip: boolean -} diff --git a/packages/common/src/store/ui/transaction-details/types.ts b/packages/common/src/store/ui/transaction-details/types.ts index 1974278e91c..b42aaa4c5bf 100644 --- a/packages/common/src/store/ui/transaction-details/types.ts +++ b/packages/common/src/store/ui/transaction-details/types.ts @@ -5,7 +5,6 @@ import { Nullable } from '../../../utils/typeUtils' export enum TransactionType { PURCHASE = 'PURCHASE', - TIP = 'TIP', CHALLENGE_REWARD = 'CHALLENGE_REWARD', TRENDING_REWARD = 'TRENDING_REWARD', TRANSFER = 'TRANSFER' @@ -51,7 +50,7 @@ export type TransactionDetails = } | { signature: string - transactionType: TransactionType.TIP | TransactionType.TRANSFER + transactionType: TransactionType.TRANSFER method: TransactionMethod.SEND | TransactionMethod.RECEIVE date: string change: StringAudio diff --git a/packages/common/src/store/user-list/index.ts b/packages/common/src/store/user-list/index.ts index b7698c6476c..6e1c870631c 100644 --- a/packages/common/src/store/user-list/index.ts +++ b/packages/common/src/store/user-list/index.ts @@ -7,14 +7,6 @@ export * as coinLeaderboardUserListSelectors from './coin-leaderboard/selectors' export * from './coin-leaderboard/types' export { default as coinLeaderboardUserListReducer } from './coin-leaderboard/reducers' -export * as topSupportersUserListActions from './top-supporters/actions' -export * as topSupportersUserListSelectors from './top-supporters/selectors' -export * from './top-supporters/types' - -export * as supportingUserListActions from './supporting/actions' -export * as supportingUserListSelectors from './supporting/selectors' -export * from './supporting/types' - export * as repostsUserListActions from './reposts/actions' export * as repostsUserListSelectors from './reposts/selectors' export * from './reposts/types' diff --git a/packages/common/src/store/user-list/supporting/actions.ts b/packages/common/src/store/user-list/supporting/actions.ts deleted file mode 100644 index 45e70c6feb5..00000000000 --- a/packages/common/src/store/user-list/supporting/actions.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { createCustomAction } from 'typesafe-actions' - -import { ID } from '~/models/Identifiers' - -export const SET_SUPPORTING = 'SUPPORTING_USER_PAGE/SET_SUPPORTING' - -export const setSupporting = createCustomAction(SET_SUPPORTING, (id: ID) => ({ - id -})) diff --git a/packages/common/src/store/user-list/supporting/reducers.ts b/packages/common/src/store/user-list/supporting/reducers.ts deleted file mode 100644 index 6cf453574d4..00000000000 --- a/packages/common/src/store/user-list/supporting/reducers.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createReducer, ActionType } from 'typesafe-actions' - -import * as actions from './actions' -import { SupportingPageState } from './types' - -type SupportingActions = ActionType - -const initialState = { - id: null -} - -const supportingReducer = createReducer( - initialState, - { - [actions.SET_SUPPORTING](state, action) { - return { - ...state, - id: action.id - } - } - } -) - -export default supportingReducer diff --git a/packages/common/src/store/user-list/supporting/selectors.ts b/packages/common/src/store/user-list/supporting/selectors.ts deleted file mode 100644 index 8f0edb00fd7..00000000000 --- a/packages/common/src/store/user-list/supporting/selectors.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ID } from '~/models/Identifiers' -import { CommonState } from '~/store/commonStore' - -export const getId = (state: CommonState): ID | null => - state.ui.userList.supporting.id diff --git a/packages/common/src/store/user-list/supporting/types.ts b/packages/common/src/store/user-list/supporting/types.ts deleted file mode 100644 index b593a44cb90..00000000000 --- a/packages/common/src/store/user-list/supporting/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ID } from '~/models/Identifiers' - -export type SupportingPageState = { - id: ID | null -} - -export const SUPPORTING_USER_LIST_TAG = 'SUPPORTING' diff --git a/packages/common/src/store/user-list/top-supporters/actions.ts b/packages/common/src/store/user-list/top-supporters/actions.ts deleted file mode 100644 index 0637d64de67..00000000000 --- a/packages/common/src/store/user-list/top-supporters/actions.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createCustomAction } from 'typesafe-actions' - -import { ID } from '~/models/Identifiers' - -export const SET_TOP_SUPPORTERS = 'TOP_SUPPORTERS_USER_PAGE/SET_TOP_SUPPORTERS' - -export const setTopSupporters = createCustomAction( - SET_TOP_SUPPORTERS, - (id: ID) => ({ - id - }) -) diff --git a/packages/common/src/store/user-list/top-supporters/reducers.ts b/packages/common/src/store/user-list/top-supporters/reducers.ts deleted file mode 100644 index 18333e06555..00000000000 --- a/packages/common/src/store/user-list/top-supporters/reducers.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createReducer, ActionType } from 'typesafe-actions' - -import * as actions from './actions' -import { TopSupportersPageState } from './types' - -type TopSupportersActions = ActionType - -const initialState = { - id: null -} - -const topSupportersReducer = createReducer< - TopSupportersPageState, - TopSupportersActions ->(initialState, { - [actions.SET_TOP_SUPPORTERS](state, action) { - return { - ...state, - id: action.id - } - } -}) - -export default topSupportersReducer diff --git a/packages/common/src/store/user-list/top-supporters/selectors.ts b/packages/common/src/store/user-list/top-supporters/selectors.ts deleted file mode 100644 index b31bade8da4..00000000000 --- a/packages/common/src/store/user-list/top-supporters/selectors.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ID } from '~/models/Identifiers' -import { CommonState } from '~/store/commonStore' - -export const getId = (state: CommonState): ID | null => - state.ui.userList.topSupporters.id diff --git a/packages/common/src/store/user-list/top-supporters/types.ts b/packages/common/src/store/user-list/top-supporters/types.ts deleted file mode 100644 index 96bdce4782a..00000000000 --- a/packages/common/src/store/user-list/top-supporters/types.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ID } from '~/models/Identifiers' - -export type TopSupportersPageState = { - id: ID | null -} - -export const TOP_SUPPORTERS_USER_LIST_TAG = 'TOP SUPPORTERS' diff --git a/packages/common/src/utils/chatUtils.ts b/packages/common/src/utils/chatUtils.ts index a9f6ca5db7e..fb61c5c5973 100644 --- a/packages/common/src/utils/chatUtils.ts +++ b/packages/common/src/utils/chatUtils.ts @@ -19,21 +19,18 @@ export const CHAT_BLOG_POST_URL = const messages = { blastTitleFollowers: 'All Followers', - blastTitleSupporters: 'Tip Supporters', blastTitleCustomers: 'Purchasers', blastTitleRemixers: 'Remix Creators', blastTitleCustomers2: 'All Purchasers', blastTitleRemixers2: 'Remixed', blastTitleCoinHolders: (ticker: string) => `$${ticker} Members`, blastFollowersDescription: 'Everyone who follows you.', - blastSupportersDescription: 'Everyone who has sent you a tip.', blastCustomersDescription: 'Everyone who has paid for your content.', blastRemixersDescription: 'Everyone who has remixed your tracks.', blastCoinHoldersDescription: (symbol: string) => `Everyone who holds $${symbol}.`, blastCTABase: 'Send a message blast to ', blastCTAFollowers: 'each of your followers', - blastCTASupporters: 'everyone who has sent you a tip', blastCTACustomers: (audienceContentId?: string) => audienceContentId ? 'all purchasers' @@ -195,14 +192,14 @@ export const getChatBlastTitle = ({ switch (audience) { case ChatBlastAudience.FOLLOWERS: return messages.blastTitleFollowers - case ChatBlastAudience.TIPPERS: - return messages.blastTitleSupporters case ChatBlastAudience.CUSTOMERS: return messages.blastTitleCustomers case ChatBlastAudience.REMIXERS: return messages.blastTitleRemixers case ChatBlastAudience.COIN_HOLDERS: return messages.blastTitleCoinHolders(coinSymbol ?? '') + default: + return '' } } @@ -218,8 +215,6 @@ export const getChatBlastSecondaryTitle = ({ switch (audience) { case ChatBlastAudience.FOLLOWERS: return messages.blastTitleFollowers - case ChatBlastAudience.TIPPERS: - return messages.blastTitleSupporters case ChatBlastAudience.CUSTOMERS: return audienceContentId ? messages.blastTitleCustomers @@ -230,6 +225,8 @@ export const getChatBlastSecondaryTitle = ({ : messages.blastTitleRemixers case ChatBlastAudience.COIN_HOLDERS: return messages.blastTitleCoinHolders(coinSymbol ?? '') + default: + return '' } } @@ -243,14 +240,14 @@ export const getChatBlastAudienceDescription = ({ switch (audience) { case ChatBlastAudience.FOLLOWERS: return messages.blastFollowersDescription - case ChatBlastAudience.TIPPERS: - return messages.blastSupportersDescription case ChatBlastAudience.CUSTOMERS: return messages.blastCustomersDescription case ChatBlastAudience.REMIXERS: return messages.blastRemixersDescription case ChatBlastAudience.COIN_HOLDERS: return messages.blastCoinHoldersDescription(coinSymbol ?? '') + default: + return '' } } @@ -266,8 +263,6 @@ export const getChatBlastCTA = ({ switch (audience) { case ChatBlastAudience.FOLLOWERS: return messages.blastCTABase + messages.blastCTAFollowers - case ChatBlastAudience.TIPPERS: - return messages.blastCTABase + messages.blastCTASupporters case ChatBlastAudience.CUSTOMERS: return ( messages.blastCTABase + messages.blastCTACustomers(audienceContentId) @@ -280,6 +275,8 @@ export const getChatBlastCTA = ({ return ( messages.blastCTABase + messages.blastCTACoinHolders(coinSymbol ?? '') ) + default: + return '' } } @@ -287,8 +284,6 @@ export const defaultChatPermitMap: InboxSettingsFormValues = { [ChatPermission.ALL]: false, [ChatPermission.FOLLOWERS]: false, [ChatPermission.FOLLOWEES]: false, - [ChatPermission.TIPPERS]: false, - [ChatPermission.TIPPEES]: false, [ChatPermission.VERIFIED]: false } diff --git a/packages/common/src/utils/constants.ts b/packages/common/src/utils/constants.ts index 9eec381d8a6..79dd0490131 100644 --- a/packages/common/src/utils/constants.ts +++ b/packages/common/src/utils/constants.ts @@ -1,12 +1,4 @@ -export const MAX_PROFILE_TOP_SUPPORTERS = 5 export const MAX_PROFILE_RELATED_ARTISTS = 5 -export const MAX_PROFILE_SUPPORTING_TILES = 1 -export const MAX_ARTIST_HOVER_TOP_SUPPORTING = 7 -/** Default pagination size for first page of "supporting" lists. This - * drives components like the top 3+view all tile list on mobile. We need at - * least 9 (if there are more than 9) for those components to render consistently. - */ -export const SUPPORTING_PAGINATION_SIZE = 9 export const MESSAGE_GROUP_THRESHOLD_MINUTES = 2 diff --git a/packages/common/src/utils/editableAccess.ts b/packages/common/src/utils/editableAccess.ts index 3123e257e56..ff558ac61e6 100644 --- a/packages/common/src/utils/editableAccess.ts +++ b/packages/common/src/utils/editableAccess.ts @@ -1,7 +1,6 @@ import { AccessConditions, isContentFollowGated, - isContentTipGated, isContentUSDCPurchaseGated, StreamTrackAvailabilityType } from '~/models' @@ -21,7 +20,6 @@ export const getUsersMayLoseAccess = ({ const isInitiallyUsdcGated = isContentUSDCPurchaseGated( initialStreamConditions ) - const isInitiallyTipGated = isContentTipGated(initialStreamConditions) const isInitiallyFollowGated = isContentFollowGated(initialStreamConditions) const stillUsdcGated = @@ -31,11 +29,7 @@ export const getUsersMayLoseAccess = ({ isInitiallyFollowGated && availability === StreamTrackAvailabilityType.SPECIAL_ACCESS && specialAccessType === 'follow' - const stillTipGated = - isInitiallyTipGated && - availability === StreamTrackAvailabilityType.SPECIAL_ACCESS && - specialAccessType === 'tip' - const stillSameGate = stillUsdcGated || stillFollowGated || stillTipGated + const stillSameGate = stillUsdcGated || stillFollowGated return ( !stillSameGate && diff --git a/packages/common/src/utils/route.ts b/packages/common/src/utils/route.ts index 64773ecd196..f84f327fefd 100644 --- a/packages/common/src/utils/route.ts +++ b/packages/common/src/utils/route.ts @@ -156,8 +156,6 @@ export const LEADERBOARD_USERS_ROUTE = '/leaderboard' export const COIN_DETAIL_MOBILE_WEB_ROUTE = '/coins/:ticker/details' export const COIN_EXCLUSIVE_TRACKS_MOBILE_ROUTE = '/coins/:ticker/exclusive-tracks/mobile' -export const SUPPORTING_USERS_ROUTE = '/supporting' -export const TOP_SUPPORTERS_USERS_ROUTE = '/top-supporters' export const ACCOUNT_SETTINGS_PAGE = '/settings/account' export const NOTIFICATION_SETTINGS_PAGE = '/settings/notifications' export const ABOUT_SETTINGS_PAGE = '/settings/about' @@ -320,8 +318,6 @@ export const orderedRoutes = [ FAVORITING_USERS_ROUTE, FOLLOWING_USERS_ROUTE, FOLLOWERS_USERS_ROUTE, - SUPPORTING_USERS_ROUTE, - TOP_SUPPORTERS_USERS_ROUTE, PROFILE_PAGE_COMMENTS, PROFILE_PAGE ] @@ -380,8 +376,6 @@ export const staticRoutes = new Set([ FAVORITING_USERS_ROUTE, FOLLOWING_USERS_ROUTE, FOLLOWERS_USERS_ROUTE, - SUPPORTING_USERS_ROUTE, - TOP_SUPPORTERS_USERS_ROUTE, ACCOUNT_SETTINGS_PAGE, NOTIFICATION_SETTINGS_PAGE, ABOUT_SETTINGS_PAGE, diff --git a/packages/harmony/src/assets/icons/Tipping.svg b/packages/harmony/src/assets/icons/Tipping.svg deleted file mode 100644 index 10fd253c7de..00000000000 --- a/packages/harmony/src/assets/icons/Tipping.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packages/harmony/src/icons/icons.tsx b/packages/harmony/src/icons/icons.tsx index caca483d951..3f8f9afdde6 100644 --- a/packages/harmony/src/icons/icons.tsx +++ b/packages/harmony/src/icons/icons.tsx @@ -69,7 +69,6 @@ export { IconThumbsUp } from './individual/IconThumbsUp' export { IconCloseAlt } from './individual/IconCloseAlt' export { IconMood } from './individual/IconMood' export { IconMoneyBracket } from './individual/IconMoneyBracket' -export { IconTipping } from './individual/IconTipping' export { IconCloudDownload } from './individual/IconCloudDownload' export { IconNoWifi } from './individual/IconNoWifi' export { IconTransaction } from './individual/IconTransaction' diff --git a/packages/harmony/src/icons/individual/IconTipping.ts b/packages/harmony/src/icons/individual/IconTipping.ts deleted file mode 100644 index da5b6fd08bc..00000000000 --- a/packages/harmony/src/icons/individual/IconTipping.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { IconComponent } from '~harmony/components' - -import IconSVG from '../../assets/icons/Tipping.svg' - -export const IconTipping = IconSVG as IconComponent diff --git a/packages/harmony/src/icons/utilityIcons.ts b/packages/harmony/src/icons/utilityIcons.ts index 8d62286b5d5..19f659bb740 100644 --- a/packages/harmony/src/icons/utilityIcons.ts +++ b/packages/harmony/src/icons/utilityIcons.ts @@ -126,7 +126,6 @@ import IconSupportSVG from '../assets/icons/Support.svg' import IconTastemakerSVG from '../assets/icons/Tastemaker.svg' import IconThumbsDownSVG from '../assets/icons/ThumbsDown.svg' import IconThumbsUpSVG from '../assets/icons/ThumbsUp.svg' -import IconTippingSVG from '../assets/icons/Tipping.svg' import IconTowerBroadcastSVG from '../assets/icons/TowerBroadcast.svg' import IconTransactionSVG from '../assets/icons/Transaction.svg' import IconTrashSVG from '../assets/icons/Trash.svg' @@ -223,7 +222,6 @@ export const IconThumbsUp = IconThumbsUpSVG as IconComponent export const IconCloseAlt = IconCloseAltSVG as IconComponent export const IconMood = IconMoodSVG as IconComponent export const IconMoneyBracket = IconMoneyBracketSVG as IconComponent -export const IconTipping = IconTippingSVG as IconComponent export const IconCloudDownload = IconCloudDownloadSVG as IconComponent export const IconNoWifi = IconNoWifiSVG as IconComponent export const IconTransaction = IconTransactionSVG as IconComponent diff --git a/packages/mobile/ios/Podfile.lock b/packages/mobile/ios/Podfile.lock index 34d18cc2368..448119d81d2 100644 --- a/packages/mobile/ios/Podfile.lock +++ b/packages/mobile/ios/Podfile.lock @@ -1350,7 +1350,7 @@ PODS: - React - react-native-google-cast/NoBluetoothArm (= 4.6.2) - react-native-google-cast/NoBluetoothArm (4.6.2): - - google-cast-sdk-dynamic-xcframework-no-bluetooth + - google-cast-sdk-dynamic-xcframework-no-bluetooth (= 4.7.1) - React - react-native-google-cast/RNGoogleCast - react-native-google-cast/RNGoogleCast (4.6.2): @@ -2557,7 +2557,7 @@ SPEC CHECKSUMS: react-native-document-picker: 4f90a074d1eb269e32d5563c53b70d469180cece react-native-fast-crypto: b30594570dab23aca7e74e206b2c03e28a006216 react-native-get-random-values: 384787fd76976f5aec9465aff6fa9e9129af1e74 - react-native-google-cast: 18b9b2fc518caabfa65d309409e160b3fc6d1733 + react-native-google-cast: 0a82cf63114470403e41e04ffa2b13d6448b6112 react-native-image-picker: f104798044ef2c9211c42a48025d0693b5f34981 react-native-in-app-review: db8bb167a5f238e7ceca5c242d6b36ce8c4404a4 react-native-keyboard-controller: 7c1271a9fe703b7ee588b75d6c486eda79e5081b diff --git a/packages/mobile/src/app/Drawers.tsx b/packages/mobile/src/app/Drawers.tsx index ec2f1357c52..e4f580f306b 100644 --- a/packages/mobile/src/app/Drawers.tsx +++ b/packages/mobile/src/app/Drawers.tsx @@ -42,7 +42,6 @@ import { SendTokensDrawer } from 'app/components/send-tokens-drawer' import { ShareDrawer } from 'app/components/share-drawer' import { SignOutConfirmationDrawer } from 'app/components/sign-out-confirmation-drawer' import { StripeOnrampDrawer } from 'app/components/stripe-onramp-drawer' -import { SupportersInfoDrawer } from 'app/components/supporters-info-drawer' import { TransferAudioMobileDrawer } from 'app/components/transfer-audio-mobile-drawer' import { VerificationErrorDrawer } from 'app/components/verification-error-drawer/VerificationErrorDrawer' import { VerificationSuccessDrawer } from 'app/components/verification-success-drawer/VerificationSuccessDrawer' @@ -165,7 +164,6 @@ const nativeDrawersMap: { [DrawerName in Drawer]?: ComponentType } = { BlockMessages: BlockMessagesDrawer, MuteComments: MuteCommentsConfirmationDrawer, DeleteChat: DeleteChatDrawer, - SupportersInfo: SupportersInfoDrawer, Welcome: WelcomeDrawer, ConnectNewWallet: ConnectNewWalletDrawer, PickWinners: PickWinnersDrawer, diff --git a/packages/mobile/src/components/comments/CommentBadge.tsx b/packages/mobile/src/components/comments/CommentBadge.tsx index 7e7d5ce67b9..4f2fc0c4d9a 100644 --- a/packages/mobile/src/components/comments/CommentBadge.tsx +++ b/packages/mobile/src/components/comments/CommentBadge.tsx @@ -1,30 +1,18 @@ -import { useSupporter } from '@audius/common/api' import { useCurrentCommentSection } from '@audius/common/context' import { useIsCoinMember } from '@audius/common/hooks' import type { ID } from '@audius/common/models' import type { IconComponent } from '@audius/harmony-native' -import { - Flex, - IconArtistCoin, - IconStar, - IconTipping, - IconTrophy, - Text -} from '@audius/harmony-native' +import { Flex, IconArtistCoin, IconStar, Text } from '@audius/harmony-native' -type BadgeType = 'artist' | 'topSupporter' | 'tipSupporter' | 'coinMember' +type BadgeType = 'artist' | 'coinMember' const iconMap: Record = { artist: IconStar, - topSupporter: IconTrophy, - tipSupporter: IconTipping, coinMember: IconArtistCoin } const messages: Record = { artist: 'Artist', - topSupporter: 'Top Supporter', - tipSupporter: 'Tip Supporter', coinMember: 'Coin Member' } @@ -38,27 +26,9 @@ export const CommentBadge = ({ isArtist }: CommentBadgeProps) => { const { artistId } = useCurrentCommentSection() - const { data: supporter } = useSupporter( - { - userId: artistId, - supporterUserId: commentUserId - }, - // Read only, relying on prefetch in commentsContext - { enabled: false } - ) const { isCoinHolder } = useIsCoinMember(commentUserId, artistId) - const isTopSupporter = supporter?.rank === 1 - - const badgeType = isArtist - ? 'artist' - : isCoinHolder - ? 'coinMember' - : isTopSupporter - ? 'topSupporter' - : supporter - ? 'tipSupporter' - : null + const badgeType = isArtist ? 'artist' : isCoinHolder ? 'coinMember' : null if (badgeType === null) return null diff --git a/packages/mobile/src/components/details-tile/DetailsTileGatedAccess.tsx b/packages/mobile/src/components/details-tile/DetailsTileGatedAccess.tsx index 4d276e25bb4..34bd1418910 100644 --- a/packages/mobile/src/components/details-tile/DetailsTileGatedAccess.tsx +++ b/packages/mobile/src/components/details-tile/DetailsTileGatedAccess.tsx @@ -6,7 +6,6 @@ import type { } from '@audius/common/models' import { isContentFollowGated, - isContentTipGated, isContentSpecialAccess, isContentUSDCPurchaseGated, isContentTokenGated @@ -41,7 +40,6 @@ export const DetailsTileGatedAccess = ({ ) const shouldDisplay = isContentFollowGated(streamConditions) || - isContentTipGated(streamConditions) || isContentTokenGated(streamConditions) || isContentSpecialAccess(streamConditions) || isContentUSDCPurchaseGated(streamConditions) diff --git a/packages/mobile/src/components/details-tile/DetailsTileHasAccess.tsx b/packages/mobile/src/components/details-tile/DetailsTileHasAccess.tsx index 466f0ba5505..6fb7a1f6e04 100644 --- a/packages/mobile/src/components/details-tile/DetailsTileHasAccess.tsx +++ b/packages/mobile/src/components/details-tile/DetailsTileHasAccess.tsx @@ -4,7 +4,6 @@ import type { Coin } from '@audius/common/adapters' import { useStreamConditionsEntity } from '@audius/common/hooks' import { isContentFollowGated, - isContentTipGated, isContentTokenGated, isContentUSDCPurchaseGated } from '@audius/common/models' @@ -42,10 +41,6 @@ const messages = { unlockedFollowGatedSuffix: (contentType: PurchaseableContentType) => `! This ${contentType} is now available.`, ownerFollowGated: 'Users can unlock access by following your account!', - unlockedTipGatedPrefix: 'Thank you for supporting ', - unlockedTipGatedSuffix: (contentType: PurchaseableContentType) => - ` by sending them a tip! This ${contentType} is now available.`, - ownerTipGated: 'Users can unlock access by sending you a tip!', unlockedUSDCPurchasePrefix: (contentType: PurchaseableContentType) => `You've purchased this ${contentType}. Thank you for supporting `, unlockedUSDCPurchaseSuffix: '.', @@ -104,10 +99,7 @@ const DetailsTileOwnerSection = ({ const styles = useStyles() const neutral = useColor('neutral') - if ( - isContentFollowGated(streamConditions) || - isContentTipGated(streamConditions) - ) { + if (isContentFollowGated(streamConditions)) { return ( - - {isContentFollowGated(streamConditions) - ? messages.ownerFollowGated - : messages.ownerTipGated} - + {messages.ownerFollowGated} @@ -213,7 +201,7 @@ export const DetailsTileHasAccess = ({ const styles = useStyles() const navigation = useNavigation() - const { followee, tippedUser } = useStreamConditionsEntity(streamConditions) + const { followee } = useStreamConditionsEntity(streamConditions) const handlePressArtistName = useCallback( (handle: string) => () => { @@ -263,14 +251,6 @@ export const DetailsTileHasAccess = ({ suffix: messages.unlockedFollowGatedSuffix(contentType) }) } - if (isContentTipGated(streamConditions)) { - if (!tippedUser) return null - return renderUnlockedSpecialAccessDescription({ - entity: tippedUser, - prefix: messages.unlockedTipGatedPrefix, - suffix: messages.unlockedTipGatedSuffix(contentType) - }) - } if (isContentUSDCPurchaseGated(streamConditions)) { if (!trackArtist) return null return renderUnlockedSpecialAccessDescription({ @@ -307,7 +287,6 @@ export const DetailsTileHasAccess = ({ contentType, followee, renderUnlockedSpecialAccessDescription, - tippedUser, trackArtist, handleTokenPress, token?.ticker diff --git a/packages/mobile/src/components/details-tile/DetailsTileNoAccess.tsx b/packages/mobile/src/components/details-tile/DetailsTileNoAccess.tsx index 141403a47f9..af2eb868dea 100644 --- a/packages/mobile/src/components/details-tile/DetailsTileNoAccess.tsx +++ b/packages/mobile/src/components/details-tile/DetailsTileNoAccess.tsx @@ -7,7 +7,6 @@ import { FollowSource, ModalSource, isContentFollowGated, - isContentTipGated, isContentUSDCPurchaseGated, isContentTokenGated } from '@audius/common/models' @@ -16,7 +15,6 @@ import { FeatureFlags } from '@audius/common/services' import { PurchaseableContentType, usersSocialActions, - tippingActions, usePremiumContentPurchaseModal, gatedContentSelectors } from '@audius/common/store' @@ -25,13 +23,7 @@ import type { ViewStyle } from 'react-native' import { Text, View } from 'react-native' import { useDispatch, useSelector } from 'react-redux' -import { - IconUserFollow, - IconTipping, - Flex, - Button, - useTheme -} from '@audius/harmony-native' +import { IconUserFollow, Flex, Button, useTheme } from '@audius/harmony-native' import { LockedStatusBadge } from 'app/components/core' import LoadingSpinner from 'app/components/loading-spinner' import { UserBadges } from 'app/components/user-badges' @@ -43,22 +35,16 @@ import { EventNames } from 'app/types/analytics' const { getGatedContentStatusMap } = gatedContentSelectors const { followUser } = usersSocialActions -const { beginTip } = tippingActions const messages = { unlocking: 'UNLOCKING', howToUnlock: 'HOW TO UNLOCK', goToCollection: 'Go To Collection', followArtist: 'Follow Artist', - sendTip: 'Send Tip', buy: (price: string) => `Buy ${price}`, lockedFollowGatedPrefix: 'Follow ', unlockingFollowGatedPrefix: 'Thank you for following ', unlockingFollowGatedSuffix: '!', - lockedTipGatedPrefix: 'Send ', - lockedTipGatedSuffix: ' a tip.', - unlockingTipGatedPrefix: 'Thank you for supporting ', - unlockingTipGatedSuffix: ' by sending them a tip!', lockedTokenGatedPrefix: 'You must hold at least ', lockedTokenGatedSuffix: ' in a connected wallet.', buyArtistCoin: 'Buy Artist Coin', @@ -187,13 +173,12 @@ export const DetailsTileNoAccess = (props: DetailsTileNoAccessProps) => { const { onOpen: openPremiumContentPurchaseModal } = usePremiumContentPurchaseModal() const { color } = useTheme() - const source = isModalOpen ? 'howToUnlockModal' : 'howToUnlockTrackPage' const followSource = isModalOpen ? FollowSource.HOW_TO_UNLOCK_MODAL : FollowSource.HOW_TO_UNLOCK_TRACK_PAGE const gatedTrackStatusMap = useSelector(getGatedContentStatusMap) const gatedTrackStatus = gatedTrackStatusMap[trackId] ?? null - const { followee, tippedUser } = useStreamConditionsEntity(streamConditions) + const { followee } = useStreamConditionsEntity(streamConditions) const { isEnabled: isUsdcPurchasesEnabled } = useFeatureFlag( FeatureFlags.USDC_PURCHASES ) @@ -204,12 +189,6 @@ export const DetailsTileNoAccess = (props: DetailsTileNoAccessProps) => { } }, [followee, dispatch, followSource, trackId]) - const handleSendTip = useCallback(() => { - onClose() - dispatch(beginTip({ user: tippedUser, source, trackId })) - navigation.navigate('TipArtist') - }, [dispatch, tippedUser, source, trackId, navigation, onClose]) - const handlePurchasePress = useCallback(() => { track( make({ @@ -294,21 +273,6 @@ export const DetailsTileNoAccess = (props: DetailsTileNoAccessProps) => { ) } - if (isContentTipGated(streamConditions)) { - if (!tippedUser) return null - return ( - <> - {renderLockedSpecialAccessDescription({ - entity: tippedUser, - prefix: messages.lockedTipGatedPrefix, - suffix: messages.lockedTipGatedSuffix - })} - - - ) - } if (isContentTokenGated(streamConditions)) { return ( @@ -368,8 +332,6 @@ export const DetailsTileNoAccess = (props: DetailsTileNoAccessProps) => { followee, renderLockedSpecialAccessDescription, handleFollowArtist, - tippedUser, - handleSendTip, handleTokenPress, token?.ticker, handleBuyTokenPress, @@ -407,19 +369,12 @@ export const DetailsTileNoAccess = (props: DetailsTileNoAccessProps) => { suffix: messages.unlockingFollowGatedSuffix }) } - if (tippedUser) { - return renderUnlockingSpecialAccessDescription({ - entity: tippedUser, - prefix: messages.unlockingTipGatedPrefix, - suffix: messages.unlockingTipGatedSuffix - }) - } console.warn( 'No entity for stream conditions... should not have reached here.' ) return null - }, [followee, tippedUser, renderUnlockingSpecialAccessDescription]) + }, [followee, renderUnlockingSpecialAccessDescription]) const isUnlocking = gatedTrackStatus === 'UNLOCKING' diff --git a/packages/mobile/src/components/edit/PriceAndAudienceField/PriceAndAudienceField.tsx b/packages/mobile/src/components/edit/PriceAndAudienceField/PriceAndAudienceField.tsx index d4c58a183f3..7ef38187f2b 100644 --- a/packages/mobile/src/components/edit/PriceAndAudienceField/PriceAndAudienceField.tsx +++ b/packages/mobile/src/components/edit/PriceAndAudienceField/PriceAndAudienceField.tsx @@ -5,7 +5,6 @@ import { priceAndAudienceMessages as messages } from '@audius/common/messages' import type { AccessConditions } from '@audius/common/models' import { isContentFollowGated, - isContentTipGated, isContentTokenGated, isContentUSDCPurchaseGated } from '@audius/common/models' @@ -43,9 +42,6 @@ export const PriceAndAudienceField = (props: PriceAndAudienceFieldProps) => { if (isContentFollowGated(streamConditions)) { return [messages.specialAccess, messages.followersOnly] } - if (isContentTipGated(streamConditions)) { - return [messages.specialAccess, messages.supportersOnly] - } if (isContentTokenGated(streamConditions)) { return [messages.coinGated] } diff --git a/packages/mobile/src/components/edit/PriceAndAudienceField/PriceAndAudienceScreen.tsx b/packages/mobile/src/components/edit/PriceAndAudienceField/PriceAndAudienceScreen.tsx index a65f933d70d..8a489e1d405 100644 --- a/packages/mobile/src/components/edit/PriceAndAudienceField/PriceAndAudienceScreen.tsx +++ b/packages/mobile/src/components/edit/PriceAndAudienceField/PriceAndAudienceScreen.tsx @@ -4,7 +4,6 @@ import { useFeatureFlag, useAccessAndRemixSettings } from '@audius/common/hooks' import { priceAndAudienceMessages as messages } from '@audius/common/messages' import { isContentFollowGated, - isContentTipGated, isContentTokenGated, isContentUSDCPurchaseGated, StreamTrackAvailabilityType @@ -63,10 +62,7 @@ export const PriceAndAudienceScreen = () => { if (isContentTokenGated(streamConditions)) { return StreamTrackAvailabilityType.TOKEN_GATED } - if ( - isContentFollowGated(streamConditions) || - isContentTipGated(streamConditions) - ) { + if (isContentFollowGated(streamConditions)) { return StreamTrackAvailabilityType.SPECIAL_ACCESS } return StreamTrackAvailabilityType.PUBLIC @@ -132,16 +128,13 @@ export const PriceAndAudienceScreen = () => { const navigation = useNavigation() const [usersMayLoseAccess, setUsersMayLoseAccess] = useState(false) const [specialAccessType, setSpecialAccessType] = useState< - 'follow' | 'tip' | undefined + 'follow' | undefined >(undefined) - // We do not know whether or not the special access is of type follow or tip. - // So we do that check here. + // Set the special access type based on stream conditions. useEffect(() => { if (isContentFollowGated(streamConditions)) { setSpecialAccessType('follow') - } else if (isContentTipGated(streamConditions)) { - setSpecialAccessType('tip') } }, [streamConditions]) diff --git a/packages/mobile/src/components/edit/PriceAndAudienceField/SpecialAccessRadioField.tsx b/packages/mobile/src/components/edit/PriceAndAudienceField/SpecialAccessRadioField.tsx index 81ffc287b14..20fcdf492ea 100644 --- a/packages/mobile/src/components/edit/PriceAndAudienceField/SpecialAccessRadioField.tsx +++ b/packages/mobile/src/components/edit/PriceAndAudienceField/SpecialAccessRadioField.tsx @@ -4,17 +4,12 @@ import { useCurrentUserId } from '@audius/common/api' import { priceAndAudienceMessages } from '@audius/common/messages' import { isContentFollowGated, - isContentTipGated, StreamTrackAvailabilityType } from '@audius/common/models' import type { AccessConditions } from '@audius/common/models' import type { Nullable } from '@audius/common/utils' -import { useDispatch } from 'react-redux' import { - Flex, - IconButton, - IconInfo, IconSparkles, Paper, Radio, @@ -22,13 +17,12 @@ import { RadioGroupContext } from '@audius/harmony-native' import { useSetEntityAvailabilityFields } from 'app/hooks/useSetTrackAvailabilityFields' -import { setVisibility } from 'app/store/drawers/slice' import { ExpandableRadio } from '../ExpandableRadio' const { specialAccessRadio: messages } = priceAndAudienceMessages -type SpecialAccessValue = 'followers' | 'supporters' +type SpecialAccessValue = 'followers' type SpecialAccessRadioFieldProps = { disabled?: boolean @@ -39,7 +33,6 @@ export const SpecialAccessRadioField = ( props: SpecialAccessRadioFieldProps ) => { const { disabled = false, previousStreamConditions } = props - const dispatch = useDispatch() const { value } = useContext(RadioGroupContext) const selected = value === StreamTrackAvailabilityType.SPECIAL_ACCESS @@ -50,8 +43,7 @@ export const SpecialAccessRadioField = ( ? { follow_user_id: currentUserId } : null const [selectedSpecialAccessGate, setSelectedSpecialAccessGate] = useState( - isContentFollowGated(previousStreamConditions) || - isContentTipGated(previousStreamConditions) + isContentFollowGated(previousStreamConditions) ? (previousStreamConditions ?? defaultSpecialAccess) : defaultSpecialAccess ) @@ -68,23 +60,14 @@ export const SpecialAccessRadioField = ( } }, [selected, selectedSpecialAccessGate, setFields]) - const handleInfoPress = useCallback(() => { - dispatch(setVisibility({ drawer: 'SupportersInfo', visible: true })) - }, [dispatch]) - - const [specialAccess, setSpecialAccess] = useState( - isContentTipGated(selectedSpecialAccessGate) ? 'supporters' : 'followers' - ) + const [specialAccess, setSpecialAccess] = + useState('followers') const handleAccessChange = useCallback( (value: SpecialAccessValue) => { if (!currentUserId || !selected) return setSpecialAccess(value) - setSelectedSpecialAccessGate( - value === 'followers' - ? { follow_user_id: currentUserId } - : { tip_user_id: currentUserId } - ) + setSelectedSpecialAccessGate({ follow_user_id: currentUserId }) }, [currentUserId, selected] ) @@ -108,19 +91,6 @@ export const SpecialAccessRadioField = ( label={messages.followersOnly} disabled={disabled} /> - - - - } diff --git a/packages/mobile/src/components/inbox-unavailable-drawer/InboxUnavailableDrawer.tsx b/packages/mobile/src/components/inbox-unavailable-drawer/InboxUnavailableDrawer.tsx index ff038aa2bf6..dbcb563f0dd 100644 --- a/packages/mobile/src/components/inbox-unavailable-drawer/InboxUnavailableDrawer.tsx +++ b/packages/mobile/src/components/inbox-unavailable-drawer/InboxUnavailableDrawer.tsx @@ -1,15 +1,13 @@ import type { ReactNode } from 'react' import { useCallback } from 'react' -import { useCurrentUserId, useUser } from '@audius/common/api' +import { useUser } from '@audius/common/api' import { FollowSource } from '@audius/common/models' import { useInboxUnavailableModal, chatActions, chatSelectors, - makeChatId, ChatPermissionAction, - tippingActions, usersSocialActions } from '@audius/common/store' import { CHAT_BLOG_POST_URL } from '@audius/common/utils' @@ -17,10 +15,9 @@ import type { Action } from '@reduxjs/toolkit' import { View } from 'react-native' import { useDispatch } from 'react-redux' -import { IconMessageLocked, IconTipping, Button } from '@audius/harmony-native' +import { IconMessageLocked, Button } from '@audius/harmony-native' import { Text, useLink } from 'app/components/core' import Drawer from 'app/components/drawer' -import { useNavigation } from 'app/hooks/useNavigation' import { makeStyles, flexRowCentered } from 'app/styles' import { useColor } from 'app/utils/theme' @@ -29,18 +26,10 @@ const { followUser } = usersSocialActions const { unblockUser, createChat } = chatActions const { useCanCreateChat } = chatSelectors -const { beginTip } = tippingActions const messages = { title: 'Inbox Unavailable', blockee: 'You cannot send messages to users you have blocked.', - tipGated: (displayName: ReactNode) => ( - <> - {'You must send '} - {displayName} - {' a tip before you can send them messages.'} - - ), followRequired: (displayName: ReactNode) => ( <> {'You must follow '} @@ -52,7 +41,6 @@ const messages = { info: 'This will not affect their ability to view your profile or interact with your content.', unblockUser: 'Unblock User', learnMore: 'Learn More', - sendAudio: 'Send $AUDIO', follow: 'Follow', cancel: 'Cancel' } @@ -109,9 +97,6 @@ type DrawerContentProps = { const DrawerContent = ({ data, onClose }: DrawerContentProps) => { const styles = useStyles() const dispatch = useDispatch() - const navigation = useNavigation() - - const { data: currentUserId } = useCurrentUserId() const { userId, presetMessage } = data const { data: user } = useUser(userId) const { callToAction } = useCanCreateChat(userId) @@ -134,36 +119,6 @@ const DrawerContent = ({ data, onClose }: DrawerContentProps) => { onClose() }, [onClose, onPressLearnMore]) - const handleTipPress = useCallback(() => { - if (!currentUserId || !user) { - console.error( - 'Unexpected undefined currentUserId or user when starting tip' - ) - return - } - const chatId = makeChatId([currentUserId, user.user_id]) - dispatch( - beginTip({ - user, - source: 'inboxUnavailableModal', - onSuccessActions: [ - chatActions.goToChat({ - chatId, - presetMessage - }) - ], - onSuccessConfirmedActions: [ - chatActions.createChat({ - userIds: [user.user_id], - skipNavigation: true - }) - ] - }) - ) - navigation.navigate('TipArtist') - onClose() - }, [onClose, currentUserId, dispatch, navigation, user, presetMessage]) - const handleFollowPress = useCallback(() => { if (userId) { const followSuccessActions: Action[] = [ @@ -209,32 +164,6 @@ const DrawerContent = ({ data, onClose }: DrawerContentProps) => { ) - case ChatPermissionAction.TIP: - return ( - <> - - {messages.tipGated( - user ? ( - - {user.name} - - - ) : null - )} - - - - ) case ChatPermissionAction.UNBLOCK: return ( <> diff --git a/packages/mobile/src/components/supporters-info-drawer/SupportersInfoDrawer.tsx b/packages/mobile/src/components/supporters-info-drawer/SupportersInfoDrawer.tsx deleted file mode 100644 index b8ea8cd1ac5..00000000000 --- a/packages/mobile/src/components/supporters-info-drawer/SupportersInfoDrawer.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { View } from 'react-native' - -import { IconQuestionCircle } from '@audius/harmony-native' -import { Text } from 'app/components/core' -import { NativeDrawer } from 'app/components/drawer' -import { flexRowCentered, makeStyles } from 'app/styles' -import { useColor } from 'app/utils/theme' - -const messages = { - title: 'WHAT IS THIS?', - subtitle: 'Anyone who has sent you a tip on Audius is considered a Supporter.' -} - -const useStyles = makeStyles(({ spacing, palette, typography }) => ({ - drawer: { - marginVertical: spacing(8), - marginHorizontal: spacing(4) - }, - titleContainer: { - ...flexRowCentered(), - justifyContent: 'center', - width: '100%', - marginBottom: spacing(6) - }, - titleText: { - marginLeft: spacing(3), - fontFamily: typography.fontByWeight.heavy, - fontSize: typography.fontSize.medium, - color: palette.neutralLight2 - }, - subtitle: { - fontFamily: typography.fontByWeight.medium, - fontSize: typography.fontSize.large - } -})) - -export const SupportersInfoDrawer = () => { - const styles = useStyles() - const neutralLight2 = useColor('neutralLight2') - - return ( - - - - - - {messages.title} - - - {messages.subtitle} - - - ) -} diff --git a/packages/mobile/src/components/supporters-info-drawer/index.ts b/packages/mobile/src/components/supporters-info-drawer/index.ts deleted file mode 100644 index bb573967e7e..00000000000 --- a/packages/mobile/src/components/supporters-info-drawer/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { SupportersInfoDrawer } from './SupportersInfoDrawer' diff --git a/packages/mobile/src/harmony-native/icons.tsx b/packages/mobile/src/harmony-native/icons.tsx index 8adb9584fcc..c21f389800a 100644 --- a/packages/mobile/src/harmony-native/icons.tsx +++ b/packages/mobile/src/harmony-native/icons.tsx @@ -80,7 +80,6 @@ export { default as IconMinus } from '@audius/harmony/src/assets/icons/Minus.svg export { default as IconThumbsUp } from '@audius/harmony/src/assets/icons/ThumbsUp.svg' export { default as IconCloseAlt } from '@audius/harmony/src/assets/icons/CloseAlt.svg' export { default as IconMood } from '@audius/harmony/src/assets/icons/Mood.svg' -export { default as IconTipping } from '@audius/harmony/src/assets/icons/Tipping.svg' export { default as IconCloudDownload } from '@audius/harmony/src/assets/icons/CloudDownload.svg' export { default as IconNoWifi } from '@audius/harmony/src/assets/icons/NoWifi.svg' export { default as IconTowerBroadcast } from '@audius/harmony/src/assets/icons/TowerBroadcast.svg' diff --git a/packages/mobile/src/hooks/useNotificationNavigation.ts b/packages/mobile/src/hooks/useNotificationNavigation.ts index e1e7eaf2064..7156d73ea88 100644 --- a/packages/mobile/src/hooks/useNotificationNavigation.ts +++ b/packages/mobile/src/hooks/useNotificationNavigation.ts @@ -24,17 +24,6 @@ import type { TrendingTrackNotification, ChallengeRewardNotification, TierChangeNotification, - ReactionNotification, - ReactionPushNotification, - TipReceiveNotification, - TipReceivePushNotification, - TipSendNotification, - TipSendPushNotification, - SupporterRankUpNotification, - SupporterRankUpPushNotification, - SupportingRankUpNotification, - SupportingRankUpPushNotification, - SupporterDethronedNotification, AddTrackToPlaylistNotification, AddTrackToPlaylistPushNotification, MessagePushNotification, @@ -53,18 +42,13 @@ import { NotificationType, PushNotificationType, Entity, - Achievement, - tippingActions + Achievement } from '@audius/common/store' import { OptionalId } from '@audius/sdk' -import type { AppState } from '@audius/web/src/store/types' import { useLinkTo } from '@react-navigation/native' -import { useDispatch, useStore } from 'react-redux' import { useNavigation } from './useNavigation' -const { beginTip } = tippingActions - /** * Navigator for notifications * @@ -72,8 +56,6 @@ const { beginTip } = tippingActions */ export const useNotificationNavigation = () => { const navigation = useNavigation() - const dispatch = useDispatch() - const store = useStore() const linkTo = useLinkTo() const socialActionHandler = useCallback( @@ -196,30 +178,6 @@ export const useNotificationNavigation = () => { [navigation] ) - const profileHandler = useCallback( - ( - notification: - | ReactionNotification - | ReactionPushNotification - | SupporterRankUpNotification - | SupporterRankUpPushNotification - | SupportingRankUpNotification - | SupportingRankUpPushNotification - | TipReceiveNotification - | TipReceivePushNotification - | TipSendNotification - | TipSendPushNotification - ) => { - navigation.navigate('Profile', { - id: - 'entityId' in notification - ? notification.entityId - : notification.initiator - }) - }, - [navigation] - ) - const messagesHandler = useCallback( ( notification: MessagePushNotification | MessageReactionPushNotification @@ -276,7 +234,6 @@ export const useNotificationNavigation = () => { [PushNotificationType.MilestoneListen]: milestoneHandler, [PushNotificationType.MilestoneRepost]: milestoneHandler, [NotificationType.Milestone]: milestoneHandler, - [NotificationType.Reaction]: profileHandler, [NotificationType.RemixCosign]: ( notification: RemixCosignNotification | RemixCosignPushNotification ) => { @@ -307,25 +264,9 @@ export const useNotificationNavigation = () => { [PushNotificationType.RepostOfRepostTrack]: socialActionHandler, [NotificationType.Repost]: socialActionHandler, [NotificationType.RepostOfRepost]: entityHandler, - [NotificationType.SupporterDethroned]: ( - notification: SupporterDethronedNotification - ) => { - // TODO: Need to handle the payload from identity - const { supportedUserId } = notification - const supportedUser = store.getState().users.entries[supportedUserId] - - dispatch( - beginTip({ user: supportedUser?.metadata, source: 'dethroned' }) - ) - navigation.navigate('TipArtist') - }, - [NotificationType.SupporterRankUp]: profileHandler, - [NotificationType.SupportingRankUp]: profileHandler, [NotificationType.TierChange]: (notification: TierChangeNotification) => { navigation.navigate('AudioScreen') }, - [NotificationType.TipReceive]: profileHandler, - [NotificationType.TipSend]: profileHandler, [NotificationType.TrendingTrack]: ( notification: TrendingTrackNotification ) => { @@ -384,12 +325,9 @@ export const useNotificationNavigation = () => { socialActionHandler, entityHandler, milestoneHandler, - profileHandler, userIdHandler, messagesHandler, - navigation, - store, - dispatch + navigation ] ) diff --git a/packages/mobile/src/screens/app-screen/AppScreen.tsx b/packages/mobile/src/screens/app-screen/AppScreen.tsx index b282a60ca00..d2af5337d72 100644 --- a/packages/mobile/src/screens/app-screen/AppScreen.tsx +++ b/packages/mobile/src/screens/app-screen/AppScreen.tsx @@ -13,7 +13,6 @@ import { EditCollectionScreen } from '../edit-collection-screen' import { EditTrackModalScreen } from '../edit-track-screen' import { ExternalWalletsModalScreen } from '../external-wallets' import { FeatureFlagOverrideScreen } from '../feature-flag-override-screen' -import { TipArtistModalScreen } from '../tip-artist-screen' import { UploadModalScreen } from '../upload-screen' import { VerificationWebViewModalScreen } from '../verification-webview-screen' @@ -39,14 +38,6 @@ export const AppScreen = () => { > - { /> - - diff --git a/packages/mobile/src/screens/chat-screen/ChatBlastWithAudienceCTA.tsx b/packages/mobile/src/screens/chat-screen/ChatBlastWithAudienceCTA.tsx index ffda1f40409..23f5a1aa971 100644 --- a/packages/mobile/src/screens/chat-screen/ChatBlastWithAudienceCTA.tsx +++ b/packages/mobile/src/screens/chat-screen/ChatBlastWithAudienceCTA.tsx @@ -2,11 +2,7 @@ import { useCallback } from 'react' import { useCurrentUserId } from '@audius/common/api' import { useCanSendChatBlast } from '@audius/common/hooks' -import { - chatActions, - followersUserListSelectors, - topSupportersUserListSelectors -} from '@audius/common/store' +import { chatActions, followersUserListSelectors } from '@audius/common/store' import { ChatBlastAudience } from '@audius/sdk' import { TouchableHighlight } from 'react-native-gesture-handler' import { useDispatch, useSelector } from 'react-redux' @@ -22,18 +18,13 @@ import { const { createChatBlast } = chatActions const getMessages = (audience: ChatBlastAudience) => { - switch (audience) { - case ChatBlastAudience.FOLLOWERS: - return { - title: 'Message Blast Your Followers', - description: 'Send bulk messages to your followers.' - } - case ChatBlastAudience.TIPPERS: - return { - title: 'Message Blast Your Tip Supporters', - description: 'Bulk message everyone who’s sent you a tip.' - } + if (audience === ChatBlastAudience.FOLLOWERS) { + return { + title: 'Message Blast Your Followers', + description: 'Send bulk messages to your followers.' + } } + return null } type ChatBlastWithAudienceCTAProps = { @@ -48,11 +39,7 @@ export const ChatBlastWithAudienceCTA = ( const { data: currentUserId } = useCurrentUserId() const followersUserId = useSelector(followersUserListSelectors.getId) - const supportersUserId = useSelector(topSupportersUserListSelectors.getId) - const targetUserId = - audience === ChatBlastAudience.FOLLOWERS - ? followersUserId - : supportersUserId + const targetUserId = followersUserId const isOwner = currentUserId === targetUserId diff --git a/packages/mobile/src/screens/chat-screen/ChatUnavailable.tsx b/packages/mobile/src/screens/chat-screen/ChatUnavailable.tsx index c29077b3908..7cf82e2c474 100644 --- a/packages/mobile/src/screens/chat-screen/ChatUnavailable.tsx +++ b/packages/mobile/src/screens/chat-screen/ChatUnavailable.tsx @@ -19,9 +19,6 @@ const messages = { follow: (user: ReactNode) => ( You must follow {user} before you can send them messages. ), - tip: (user: ReactNode) => ( - You must send {user} a tip before you can send them messages. - ), blockee: 'You cannot send messages to users you have blocked. ', learnMore: 'Learn More.', unblockUser: 'Unblock User' @@ -81,18 +78,6 @@ export const ChatUnavailable = ({ chatId }: ChatUnavailableProps) => { )} ) : null, - [ChatPermissionAction.TIP]: () => - otherUser ? ( - <> - {messages.tip( - - )} - - ) : null, [ChatPermissionAction.UNBLOCK]: () => ( {messages.blockee} diff --git a/packages/mobile/src/screens/chat-screen/ChatUserListItem.tsx b/packages/mobile/src/screens/chat-screen/ChatUserListItem.tsx index eb047ddc00c..1f224f58521 100644 --- a/packages/mobile/src/screens/chat-screen/ChatUserListItem.tsx +++ b/packages/mobile/src/screens/chat-screen/ChatUserListItem.tsx @@ -28,7 +28,6 @@ const messages = { followsYou: 'Follows You', followers: 'Followers', ctaNone: 'Cannot Be Messaged', - ctaTip: 'Send a Tip To Message', ctaFollow: 'Follow to Message', ctaBlock: 'Blocked' } @@ -129,7 +128,6 @@ const useStyles = makeStyles(({ spacing, palette, typography }) => ({ })) const ctaToTextMap: Record = { - [ChatPermissionAction.TIP]: messages.ctaTip, [ChatPermissionAction.FOLLOW]: messages.ctaFollow, [ChatPermissionAction.UNBLOCK]: messages.ctaBlock, [ChatPermissionAction.NONE]: messages.ctaNone, diff --git a/packages/mobile/src/screens/create-chat-blast-screen/ChatBlastSelectAudienceFields.tsx b/packages/mobile/src/screens/create-chat-blast-screen/ChatBlastSelectAudienceFields.tsx index d4e1308fac5..504897b9975 100644 --- a/packages/mobile/src/screens/create-chat-blast-screen/ChatBlastSelectAudienceFields.tsx +++ b/packages/mobile/src/screens/create-chat-blast-screen/ChatBlastSelectAudienceFields.tsx @@ -27,10 +27,6 @@ const messages = { label: 'My Followers', description: 'Send a bulk message to all of your followers.' }, - supporters: { - label: 'Tip Supporters', - description: 'Send a bulk message to everyone who has tipped you.' - }, purchasers: { label: 'Past Purchasers', description: @@ -61,7 +57,6 @@ export const ChatBlastSelectAudienceFields = () => { return ( - @@ -108,28 +103,6 @@ const FollowersMessageField = () => { ) } -const TipSupportersMessageField = () => { - const { data: user } = useCurrentAccountUser() - const [{ value: targetAudience }] = useField(TARGET_AUDIENCE_FIELD) - const isSelected = targetAudience === ChatBlastAudience.TIPPERS - const isDisabled = user?.supporter_count === 0 - - return ( - - } - description={messages.supporters.description} - /> - ) -} - const PastPurchasersMessageField = () => { const navigation = useNavigation() const [{ value: targetAudience }] = useField(TARGET_AUDIENCE_FIELD) diff --git a/packages/mobile/src/screens/edit-track-screen/EditTrackNavigator.tsx b/packages/mobile/src/screens/edit-track-screen/EditTrackNavigator.tsx index 8481ea9cfaa..19a0028d021 100644 --- a/packages/mobile/src/screens/edit-track-screen/EditTrackNavigator.tsx +++ b/packages/mobile/src/screens/edit-track-screen/EditTrackNavigator.tsx @@ -5,7 +5,6 @@ import { priceAndAudienceScreenName } from 'app/components/edit/PriceAndAudienceField' import { VisibilityScreen } from 'app/components/edit/VisibilityField' -import { SupportersInfoDrawer } from 'app/components/supporters-info-drawer' import { useAppScreenOptions } from 'app/screens/app-screen/useAppScreenOptions' import { messages as completeMessages } from '../upload-screen/screens/CompleteTrackScreen' @@ -74,7 +73,6 @@ export const EditTrackNavigator = (props: EditTrackNavigatorProps) => { component={CoverAttributionScreen} /> - diff --git a/packages/mobile/src/screens/notifications-screen/Notification/TipText.tsx b/packages/mobile/src/screens/notifications-screen/Notification/TipText.tsx deleted file mode 100644 index 0fa2ddd45e6..00000000000 --- a/packages/mobile/src/screens/notifications-screen/Notification/TipText.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { formatNumberCommas } from '@audius/common/utils' - -import { AudioText } from 'app/components/core' - -import { NotificationText } from './NotificationText' - -type TipTextProps = { - value: number -} - -export const TipText = (props: TipTextProps) => { - const { value } = props - return ( - - {formatNumberCommas(value)} - - ) -} diff --git a/packages/mobile/src/screens/notifications-screen/Notification/index.ts b/packages/mobile/src/screens/notifications-screen/Notification/index.ts index f91bbdcf578..15f6833caed 100644 --- a/packages/mobile/src/screens/notifications-screen/Notification/index.ts +++ b/packages/mobile/src/screens/notifications-screen/Notification/index.ts @@ -8,6 +8,5 @@ export * from './NotificationProfilePictureListSkeleton' export * from './NotificationProfilePicture' export * from './UserNameLink' export * from './EntityLink' -export * from './TipText' export * from './NotificationXButton' export * from './constants' diff --git a/packages/mobile/src/screens/notifications-screen/NotificationListItem.tsx b/packages/mobile/src/screens/notifications-screen/NotificationListItem.tsx index dea8cf6854f..a50fc39b9be 100644 --- a/packages/mobile/src/screens/notifications-screen/NotificationListItem.tsx +++ b/packages/mobile/src/screens/notifications-screen/NotificationListItem.tsx @@ -18,13 +18,7 @@ import { TrendingPlaylistNotification, TrendingTrackNotification, TrendingUndergroundNotification, - TopSupporterNotification, - TopSupportingNotification, - TipReactionNotification, - TipSentNotification, - TipReceivedNotification, AddTrackToPlaylistNotification, - SupporterDethronedNotification, RepostOfRepostNotification, FavoriteOfRepostNotification, TastemakerNotification, @@ -50,7 +44,7 @@ type NotificationListItemProps = { isVisible: boolean } export const NotificationListItem = (props: NotificationListItemProps) => { - const { notification, isVisible } = props + const { notification } = props const renderNotification = () => { switch (notification.type) { @@ -80,26 +74,6 @@ export const NotificationListItem = (props: NotificationListItemProps) => { return case NotificationType.TierChange: return - case NotificationType.Reaction: - return ( - - ) - case NotificationType.TipReceive: - return ( - - ) - case NotificationType.TipSend: - return - case NotificationType.SupporterRankUp: - return - case NotificationType.SupportingRankUp: - return case NotificationType.TrendingPlaylist: return case NotificationType.TrendingTrack: @@ -114,8 +88,6 @@ export const NotificationListItem = (props: NotificationListItemProps) => { return ( ) - case NotificationType.SupporterDethroned: - return case NotificationType.USDCPurchaseSeller: return case NotificationType.USDCPurchaseBuyer: diff --git a/packages/mobile/src/screens/notifications-screen/Notifications/ChallengeRewardNotification.tsx b/packages/mobile/src/screens/notifications-screen/Notifications/ChallengeRewardNotification.tsx index a780258884f..8bac51c406c 100644 --- a/packages/mobile/src/screens/notifications-screen/Notifications/ChallengeRewardNotification.tsx +++ b/packages/mobile/src/screens/notifications-screen/Notifications/ChallengeRewardNotification.tsx @@ -8,7 +8,7 @@ import { } from '@audius/common/utils' import type { FixedDecimal } from '@audius/fixed-decimal' import { AUDIO } from '@audius/fixed-decimal' -import { Platform, Image } from 'react-native' +import { Image } from 'react-native' import { IconAudiusLogo } from '@audius/harmony-native' import { useNotificationNavigation } from 'app/hooks/useNotificationNavigation' @@ -100,11 +100,7 @@ export const ChallengeRewardNotification = ( ) : undefined } > - - {Platform.OS === 'ios' && title.includes('Tip') - ? title.replace('Tip', '$AUDIO') - : title} - + {title} {notificationText} diff --git a/packages/mobile/src/screens/notifications-screen/Notifications/SupporterAndSupportingNotificationContent.tsx b/packages/mobile/src/screens/notifications-screen/Notifications/SupporterAndSupportingNotificationContent.tsx deleted file mode 100644 index 81c3935f861..00000000000 --- a/packages/mobile/src/screens/notifications-screen/Notifications/SupporterAndSupportingNotificationContent.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import type { User } from '@audius/common/models' -import { View } from 'react-native' - -import { IconTipping, IconTrending } from '@audius/harmony-native' -import { makeStyles } from 'app/styles' -import { spacing } from 'app/styles/spacing' -import { useThemeColors } from 'app/utils/theme' - -import { - NotificationHeader, - NotificationTitle, - NotificationProfilePicture, - UserNameLink, - NotificationText -} from '../Notification' - -const useStyles = makeStyles(() => ({ - trendingIcon: { - marginRight: spacing(2) - }, - textContainer: { - display: 'flex', - flexDirection: 'row', - alignItems: 'center' - } -})) - -type SupporterAndSupportingNotificationContentProps = { - user: User - title: string - body: string -} - -export const SupporterAndSupportingNotificationContent = ({ - user, - title, - body -}: SupporterAndSupportingNotificationContentProps) => { - const styles = useStyles() - const { neutralLight4 } = useThemeColors() - - return ( - <> - - {title} - - - - - - - - {body} - - - ) -} diff --git a/packages/mobile/src/screens/notifications-screen/Notifications/SupporterDethronedNotification.tsx b/packages/mobile/src/screens/notifications-screen/Notifications/SupporterDethronedNotification.tsx deleted file mode 100644 index 58fa7d4c01a..00000000000 --- a/packages/mobile/src/screens/notifications-screen/Notifications/SupporterDethronedNotification.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { useCallback } from 'react' - -import { useUser } from '@audius/common/api' -import type { SupporterDethronedNotification as SupporterDethroned } from '@audius/common/store' -import type { Nullable } from '@audius/common/utils' -import { Platform } from 'react-native' - -import { IconCrown } from '@audius/harmony-native' -import { useNotificationNavigation } from 'app/hooks/useNotificationNavigation' -import { EventNames } from 'app/types/analytics' - -import { - NotificationBody, - NotificationHeader, - NotificationText, - NotificationTile, - NotificationTitle, - NotificationXButton, - NotificationProfilePicture, - UserNameLink -} from '../Notification' - -type SupporterDethronedNotificationProps = { - notification: SupporterDethroned -} - -const messages = { - title: "You've Been Dethroned!", - body1: ' Dethroned You as ', - body2: "'s #1 Top Supporter! Tip to Reclaim Your Spot?", - // NOTE: Send tip -> Send $AUDIO change - body2Alt: "'s #1 Top Supporter! Send $AUDIO to Reclaim Your Spot?", // iOS only - xShare: (usurperHandle: string, supportingHandle: string) => - `I've been dethroned! ${usurperHandle} dethroned me as ${supportingHandle}'s #1 Top Supporter! $AUDIO` -} - -export const SupporterDethronedNotification = ( - props: SupporterDethronedNotificationProps -) => { - const { notification } = props - const navigation = useNotificationNavigation() - const { data: usurpingUser } = useUser(notification.entityId) - - const { data: supportedUser } = useUser(notification.supportedUserId) - - const handlePress = useCallback(() => { - navigation.navigate(notification) - }, [navigation, notification]) - - const handleShare = useCallback( - (usurpingHandle: string, supportingHandle?: Nullable) => { - // This shouldn't happen - if (!supportingHandle) { - return null - } - const shareText = messages.xShare(usurpingHandle, supportingHandle) - return { - shareText, - analytics: { - eventName: EventNames.NOTIFICATIONS_CLICK_DETHRONED_TWITTER_SHARE, - text: shareText - } as const - } - }, - [] - ) - - if (!usurpingUser || !supportedUser) return null - - return ( - - - {messages.title} - - - - - - {messages.body1} - - {Platform.OS === 'ios' ? messages.body2Alt : messages.body2} - - - - - ) -} diff --git a/packages/mobile/src/screens/notifications-screen/Notifications/TipReactionNotification.tsx b/packages/mobile/src/screens/notifications-screen/Notifications/TipReactionNotification.tsx deleted file mode 100644 index dcf64d9ac06..00000000000 --- a/packages/mobile/src/screens/notifications-screen/Notifications/TipReactionNotification.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import { useCallback } from 'react' - -import { useUser, getReactionFromRawValue } from '@audius/common/api' -import { useUIAudio } from '@audius/common/hooks' -import type { ReactionNotification } from '@audius/common/store' -import { Platform, View } from 'react-native' - -import { IconTipping } from '@audius/harmony-native' -import { UserBadges } from 'app/components/user-badges' -import { useNotificationNavigation } from 'app/hooks/useNotificationNavigation' -import { makeStyles } from 'app/styles' -import { EventNames } from 'app/types/analytics' - -import { - NotificationHeader, - NotificationTile, - NotificationTitle, - UserNameLink, - TipText, - NotificationText, - NotificationProfilePicture, - NotificationXButton -} from '../Notification' -import { reactionMap } from '../Reaction' - -const messages = { - reacted: 'reacted', - // NOTE: Send tip -> Send $AUDIO change - react: 'reacted to your tip of ', - reactAltPrefix: 'reacted to the ', // iOS only - reactAltSuffix: ' you sent them', // iOS only - // NOTE: Send tip -> Send $AUDIO change - xShare: (handle: string, ios: boolean) => - `I got a thanks from ${handle} for ${ - ios ? 'sending' : 'tipping' - } them $AUDIO on @audius! ${ios ? '' : ''}` -} - -const useStyles = makeStyles(() => ({ - body: { - flexDirection: 'row', - alignItems: 'center' - }, - profilePicture: { - position: 'absolute', - bottom: 0, - right: 0, - height: 26, - width: 26 - }, - userNameLink: { - flexDirection: 'row', - alignItems: 'center' - }, - content: { - flex: 1 - } -})) - -type TipReactionNotificationProps = { - notification: ReactionNotification - isVisible: boolean -} - -export const TipReactionNotification = ( - props: TipReactionNotificationProps -) => { - const { notification, isVisible } = props - - const { - reactionValue, - reactedToEntity: { amount } - } = notification - - const navigation = useNotificationNavigation() - const uiAmount = useUIAudio(amount) - const styles = useStyles() - - const { data: user } = useUser(notification.entityId) - - const handlePress = useCallback(() => { - navigation.navigate(notification) - }, [navigation, notification]) - - const handleXShare = useCallback((handle: string) => { - const shareText = messages.xShare(handle, Platform.OS === 'ios') - return { - shareText, - analytics: { - eventName: EventNames.NOTIFICATIONS_CLICK_TIP_REACTION_TWITTER_SHARE, - text: shareText - } as const - } - }, []) - - if (!user) return null - - const reactionType = getReactionFromRawValue(reactionValue) - if (!reactionType) return null - const Reaction = reactionMap[reactionType] - - return ( - - - - {messages.reacted} - - - - - - - - - - - - - - {Platform.OS === 'ios' ? messages.reactAltPrefix : messages.react} - - {Platform.OS === 'ios' ? messages.reactAltSuffix : ''} - - - - - - ) -} diff --git a/packages/mobile/src/screens/notifications-screen/Notifications/TipReceivedNotification.tsx b/packages/mobile/src/screens/notifications-screen/Notifications/TipReceivedNotification.tsx deleted file mode 100644 index f5afb397681..00000000000 --- a/packages/mobile/src/screens/notifications-screen/Notifications/TipReceivedNotification.tsx +++ /dev/null @@ -1,181 +0,0 @@ -import { useCallback } from 'react' - -import type { ReactionTypes } from '@audius/common/api' -import { - getReactionFromRawValue, - useArtistCoin, - useCurrentUserId, - useReaction, - useUser, - useWriteReaction -} from '@audius/common/api' -import { useUIAudio } from '@audius/common/hooks' -import type { TipReceiveNotification } from '@audius/common/store' -import type { Nullable } from '@audius/common/utils' -import { formatNumberCommas } from '@audius/common/utils' -import { Image, Platform, View } from 'react-native' - -import { IconTipping } from '@audius/harmony-native' -import Checkmark from 'app/assets/images/emojis/white-heavy-check-mark.png' -import { Text } from 'app/components/core' -import { useNotificationNavigation } from 'app/hooks/useNotificationNavigation' -import { env } from 'app/services/env' -import { EventNames } from 'app/types/analytics' - -import { - NotificationBody, - NotificationHeader, - NotificationProfilePicture, - NotificationText, - NotificationTile, - NotificationTitle, - NotificationXButton, - TipText, - UserNameLink -} from '../Notification' -import { ReactionList } from '../Reaction' - -const messages = { - title: 'You Received a Tip!', - // NOTE: Send tip -> Send $AUDIO change - titleAlt: 'You Received $AUDIO!', // iOS only - sent: 'sent you a tip of', - sentAlt: 'sent you', // iOS only - audio: '$AUDIO', - sayThanks: 'Say Thanks With a Reaction', - reactionSent: 'Reaction Sent!', - // NOTE: Send tip -> Send $AUDIO change - xShare: ( - senderHandle: string, - amount: number, - ios: boolean, - price?: string - ) => { - const totalValue = price && amount ? Number(price) * amount : null - return `Thanks ${senderHandle} for the ${formatNumberCommas(amount)} ${ - ios ? '$AUDIO' : '$AUDIO tip' - } ${totalValue ? `(~$${totalValue.toLocaleString('en-US', { maximumFractionDigits: 2 })})` : ''} on @audius! ${ios ? '' : ''}` - } -} - -type TipReceivedNotificationProps = { - notification: TipReceiveNotification - isVisible: boolean -} - -export const TipReceivedNotification = ( - props: TipReceivedNotificationProps -) => { - const { notification, isVisible } = props - const { - amount, - tipTxSignature, - reactionValue: notificationReactionValue - } = notification - const uiAmount = useUIAudio(amount) - const navigation = useNotificationNavigation() - const { data: tokenPriceData } = useArtistCoin(env.WAUDIO_MINT_ADDRESS) - - const tokenPrice = tokenPriceData?.price?.toString() - - const { data: user } = useUser(notification.entityId) - - const { data: reaction } = useReaction(tipTxSignature, { - // Only fetch if we don't have a reaction in the notification - enabled: notificationReactionValue === null - }) - - // Use the reaction from the query, falling back to notification data - const reactionValue = (reaction?.reactionValue ?? - (notificationReactionValue - ? getReactionFromRawValue(notificationReactionValue) - : null)) as Nullable - - const { mutate: writeReaction } = useWriteReaction() - const { data: currentUserId } = useCurrentUserId() - - const handleReaction = useCallback( - (reactionType: ReactionTypes) => { - if (!currentUserId) return - writeReaction({ - entityId: tipTxSignature, - reaction: reactionType, - userId: currentUserId - }) - }, - [tipTxSignature, writeReaction, currentUserId] - ) - - const handlePress = useCallback(() => { - navigation.navigate(notification) - }, [navigation, notification]) - - const handleXShare = useCallback( - (senderHandle: string) => { - const shareText = messages.xShare( - senderHandle, - uiAmount, - Platform.OS === 'ios', - tokenPrice - ) - return { - shareText, - analytics: { - eventName: EventNames.NOTIFICATIONS_CLICK_TIP_RECEIVED_TWITTER_SHARE, - text: shareText - } as const - } - }, - [uiAmount, tokenPrice] - ) - - if (!user) return null - - return ( - - - - {Platform.OS === 'ios' ? messages.titleAlt : messages.title} - - - - - - {' '} - {Platform.OS === 'ios' ? messages.sentAlt : messages.sent}{' '} - - - - {reactionValue ? ( - - - - {messages.reactionSent} - - - ) : ( - - {messages.sayThanks} - - )} - - - - ) -} diff --git a/packages/mobile/src/screens/notifications-screen/Notifications/TipSentNotification.tsx b/packages/mobile/src/screens/notifications-screen/Notifications/TipSentNotification.tsx deleted file mode 100644 index 978163882eb..00000000000 --- a/packages/mobile/src/screens/notifications-screen/Notifications/TipSentNotification.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { useCallback } from 'react' - -import { useArtistCoin, useUser } from '@audius/common/api' -import { useUIAudio } from '@audius/common/hooks' -import type { TipSendNotification } from '@audius/common/store' -import { Platform, View } from 'react-native' - -import { IconTipping } from '@audius/harmony-native' -import { useNotificationNavigation } from 'app/hooks/useNotificationNavigation' -import { env } from 'app/services/env' -import { EventNames } from 'app/types/analytics' - -import { - NotificationHeader, - NotificationProfilePicture, - NotificationText, - NotificationTile, - NotificationTitle, - NotificationXButton -} from '../Notification' -import { TipText } from '../Notification/TipText' -import { UserNameLink } from '../Notification/UserNameLink' - -const messages = { - title: 'Your Tip Was Sent!', - // NOTE: Send tip -> Send $AUDIO change - titleAlt: 'Your $AUDIO Was Sent!', // iOS only - sent: 'You successfully sent a tip of', - sentAlt: 'You successfully sent', // iOS only - to: 'to', - // NOTE: Send tip -> Send $AUDIO changes - xShare: ( - senderHandle: string, - uiAmount: number, - ios: boolean, - price?: string - ) => { - const totalValue = price && uiAmount ? Number(price) * uiAmount : null - return `I just ${ - ios ? 'tipped' : 'sent' - } ${senderHandle} ${uiAmount} $AUDIO ${totalValue ? `(~$${totalValue.toLocaleString('en-US', { maximumFractionDigits: 2 })})` : ''} on @audius ${ios ? '' : ''}` - } -} - -type TipSentNotificationProps = { - notification: TipSendNotification -} - -export const TipSentNotification = (props: TipSentNotificationProps) => { - const { notification } = props - - const { amount } = notification - const uiAmount = useUIAudio(amount) - const navigation = useNotificationNavigation() - const { data: tokenPriceData } = useArtistCoin(env.WAUDIO_MINT_ADDRESS) - - const tokenPrice = tokenPriceData?.price?.toString() - - const { data: user } = useUser(notification.entityId) - - const handlePress = useCallback(() => { - navigation.navigate(notification) - }, [navigation, notification]) - - const handleXShare = useCallback( - (senderHandle: string) => { - const shareText = messages.xShare( - senderHandle, - uiAmount, - Platform.OS === 'ios', - tokenPrice - ) - return { - shareText, - analytics: { - eventName: EventNames.NOTIFICATIONS_CLICK_TIP_SENT_TWITTER_SHARE, - text: shareText - } as const - } - }, - [uiAmount, tokenPrice] - ) - - if (!user) return null - - return ( - - - - {Platform.OS === 'ios' ? messages.titleAlt : messages.title} - - - - - - {Platform.OS === 'ios' ? messages.sentAlt : messages.sent}{' '} - {messages.to}{' '} - - - - - - ) -} diff --git a/packages/mobile/src/screens/notifications-screen/Notifications/TopSupporterNotification.tsx b/packages/mobile/src/screens/notifications-screen/Notifications/TopSupporterNotification.tsx deleted file mode 100644 index e68971c589b..00000000000 --- a/packages/mobile/src/screens/notifications-screen/Notifications/TopSupporterNotification.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { useCallback } from 'react' - -import { useUser } from '@audius/common/api' -import type { SupporterRankUpNotification } from '@audius/common/store' -import { Platform } from 'react-native' - -import { useNotificationNavigation } from 'app/hooks/useNotificationNavigation' -import { env } from 'app/services/env' -import { EventNames } from 'app/types/analytics' - -import { NotificationTile, NotificationXButton } from '../Notification' - -import { SupporterAndSupportingNotificationContent } from './SupporterAndSupportingNotificationContent' - -const messages = { - title: 'Top Supporter', - supporterChange: 'Became your', - supporter: 'Top Supporter', - // NOTE: Send tip -> Send $AUDIO change - xShare: (handle: string, rank: number, ios: boolean) => - `${handle} just became my #${rank} Top Supporter on @audius $AUDIO${ - ios ? '' : '' - }` -} - -type TopSupporterNotificationProps = { - notification: SupporterRankUpNotification -} - -export const TopSupporterNotification = ( - props: TopSupporterNotificationProps -) => { - const { notification } = props - const { rank } = notification - const navigation = useNotificationNavigation() - - const { data: user } = useUser(notification.entityId) - - const handlePress = useCallback(() => { - navigation.navigate(notification) - }, [navigation, notification]) - - const handleXShare = useCallback( - (handle: string) => { - const shareText = messages.xShare(handle, rank, Platform.OS === 'ios') - return { - shareText, - analytics: { - eventName: - EventNames.NOTIFICATIONS_CLICK_SUPPORTER_RANK_UP_TWITTER_SHARE, - text: shareText - } as const - } - }, - [rank] - ) - - if (!user) return null - - return ( - - - - - ) -} diff --git a/packages/mobile/src/screens/notifications-screen/Notifications/TopSupportingNotification.tsx b/packages/mobile/src/screens/notifications-screen/Notifications/TopSupportingNotification.tsx deleted file mode 100644 index b59b1e30a47..00000000000 --- a/packages/mobile/src/screens/notifications-screen/Notifications/TopSupportingNotification.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { useCallback } from 'react' - -import { useUser } from '@audius/common/api' -import type { SupportingRankUpNotification } from '@audius/common/store' -import { Platform } from 'react-native' - -import { useNotificationNavigation } from 'app/hooks/useNotificationNavigation' -import { env } from 'app/services/env' -import { EventNames } from 'app/types/analytics' - -import { NotificationTile, NotificationXButton } from '../Notification' - -import { SupporterAndSupportingNotificationContent } from './SupporterAndSupportingNotificationContent' - -const messages = { - title: 'Top Supporter', - supporterChange: "You're now their", - supporter: 'Top Supporter', - // NOTE: Send tip -> Send $AUDIO change - twitterShare: (handle: string, rank: number, ios: boolean) => - `I'm now ${handle}'s #${rank} Top Supporter on @audius $AUDIO${ - ios ? '' : '' - }` -} - -type TopSupportingNotificationProps = { - notification: SupportingRankUpNotification -} - -export const TopSupportingNotification = ( - props: TopSupportingNotificationProps -) => { - const { notification } = props - const { rank } = notification - const navigation = useNotificationNavigation() - - const { data: user } = useUser(notification.entityId) - - const handlePress = useCallback(() => { - navigation.navigate(notification) - }, [navigation, notification]) - - const handleTwitterShare = useCallback( - (handle: string) => { - const shareText = messages.twitterShare( - handle, - rank, - Platform.OS === 'ios' - ) - return { - shareText, - analytics: { - eventName: - EventNames.NOTIFICATIONS_CLICK_SUPPORTING_RANK_UP_TWITTER_SHARE, - text: shareText - } as const - } - }, - [rank] - ) - - if (!user) return null - - return ( - - - - - ) -} diff --git a/packages/mobile/src/screens/notifications-screen/Notifications/index.ts b/packages/mobile/src/screens/notifications-screen/Notifications/index.ts index 50ca7732f29..66e042bd0dc 100644 --- a/packages/mobile/src/screens/notifications-screen/Notifications/index.ts +++ b/packages/mobile/src/screens/notifications-screen/Notifications/index.ts @@ -9,18 +9,12 @@ export * from './RemixCreateNotification' export * from './RepostNotification' export * from './TastemakerNotification' export * from './TierChangeNotification' -export * from './TipReactionNotification' -export * from './TipReceivedNotification' -export * from './TipSentNotification' -export * from './TopSupportingNotification' -export * from './TopSupporterNotification' export * from './TrackAddedToPurchasedAlbumNotification' export * from './TrendingPlaylistNotification' export * from './TrendingTrackNotification' export * from './TrendingUndergroundNotification' export * from './UserSubscriptionNotification' export * from './AddTrackToPlaylistNotification' -export * from './SupporterDethronedNotification' export * from './RepostOfRepostNotification' export * from './FavoriteOfRepostNotification' export * from './USDCPurchaseSellerNotification' diff --git a/packages/mobile/src/screens/profile-screen/ProfileHeader/ProfileHeader.tsx b/packages/mobile/src/screens/profile-screen/ProfileHeader/ProfileHeader.tsx index 51c1122b8d4..f8bb163f1f0 100644 --- a/packages/mobile/src/screens/profile-screen/ProfileHeader/ProfileHeader.tsx +++ b/packages/mobile/src/screens/profile-screen/ProfileHeader/ProfileHeader.tsx @@ -20,7 +20,6 @@ import { BuyArtistCoinButton } from '../BuyArtistCoinButton' import { ProfileCoverPhoto } from '../ProfileCoverPhoto' import { ProfileInfo } from '../ProfileInfo' import { ProfileMetrics } from '../ProfileMetrics' -import { TipAudioButton } from '../TipAudioButton' import { UploadTrackButton } from '../UploadTrackButton' import { ArtistProfilePicture } from './ArtistProfilePicture' @@ -44,8 +43,7 @@ export const ProfileHeader = memo(() => { website, twitter_handle: twitterHandle, instagram_handle: instagramHandle, - tiktok_handle: tikTokHandle, - supporting_count: supportingCount + tiktok_handle: tikTokHandle } = useProfileUser({ select: (user) => ({ user_id: user.user_id, @@ -55,8 +53,7 @@ export const ProfileHeader = memo(() => { website: user.website, twitter_handle: user.twitter_handle, instagram_handle: user.instagram_handle, - tiktok_handle: user.tiktok_handle, - supporting_count: user.supporting_count + tiktok_handle: user.tiktok_handle }) }).user ?? {} @@ -73,14 +70,12 @@ export const ProfileHeader = memo(() => { const hasMultipleSocials = [website, twitterHandle, instagramHandle, tikTokHandle].filter(Boolean) .length > 1 - const isSupporting = supportingCount && supportingCount > 0 // Note: we also if the profile bio is longer than 3 lines, but that's handled in the Bio component. const shouldExpand = hasTier || hasMutuals || hasMultipleSocials || - isSupporting || (comments && comments?.length > 0) useEffect(() => { @@ -158,11 +153,9 @@ export const ProfileHeader = memo(() => { {isOwner ? ( - ) : isArtistCoinLoading ? null : userId && artistCoin?.mint ? ( + ) : !isArtistCoinLoading && userId && artistCoin?.mint ? ( - ) : ( - - )} + ) : null} diff --git a/packages/mobile/src/screens/profile-screen/ProfileHeader/ProfileInfoTiles.tsx b/packages/mobile/src/screens/profile-screen/ProfileHeader/ProfileInfoTiles.tsx index b3d4d53e730..184c2309ed1 100644 --- a/packages/mobile/src/screens/profile-screen/ProfileHeader/ProfileInfoTiles.tsx +++ b/packages/mobile/src/screens/profile-screen/ProfileHeader/ProfileInfoTiles.tsx @@ -5,8 +5,6 @@ import { useCurrentUserId, useMutualFollowers, useRelatedArtistsUsers, - useSupportedUsers, - useSupporters, useUserComments, useUsers, useProfileUser @@ -24,8 +22,6 @@ import { IconUserFollowing, IconUserGroup, Text, - IconTrophy, - IconTipping, IconMessage, useTheme, Paper @@ -77,9 +73,7 @@ const messages = { comments: 'Comments', mutuals: 'Mutuals', relatedArtists: 'Related Artists', - viewAll: 'View All', - topSupporters: 'Top Supporters', - supportedUsers: 'Supporting' + viewAll: 'View All' } type ProfileInfoTileProps = { @@ -205,70 +199,6 @@ const MutualsTile = ({ ) } -const SupportersTile = ({ - userId, - count -}: { - userId: number - count: number -}) => { - const { data: supporterRecords = [], isLoading } = useSupporters({ - userId, - pageSize: MAX_CARD_PROFILE_PICTURES - }) - - const supporters = useMemo(() => { - return supporterRecords.map((supporter) => supporter.sender) - }, [supporterRecords]) - - return ( - - } - /> - ) -} - -const SupportedUsersTile = ({ - userId, - count -}: { - userId: number - count: number -}) => { - const { data: supportedUserRecords = [], isLoading } = useSupportedUsers({ - userId, - pageSize: MAX_CARD_PROFILE_PICTURES - }) - - const supportedUsers = useMemo(() => { - return supportedUserRecords.map((supportedUser) => supportedUser.receiver) - }, [supportedUserRecords]) - - return ( - - } - /> - ) -} - const RelatedArtistsTile = ({ userId }: { userId: number }) => { const { data: relatedArtists = [], isLoading } = useRelatedArtistsUsers({ artistId: userId, @@ -318,16 +248,9 @@ const useStyles = makeStyles(({ spacing }) => ({ export const ProfileInfoTiles = () => { const styles = useStyles() - const { - user_id, - current_user_followee_follow_count, - supporting_count, - supporter_count - } = + const { user_id, current_user_followee_follow_count } = useProfileUser({ select: (user) => ({ - supporting_count: user.supporting_count, - supporter_count: user.supporter_count, current_user_followee_follow_count: user.current_user_followee_follow_count, user_id: user.user_id @@ -410,19 +333,12 @@ export const ProfileInfoTiles = () => { style={styles.staticTilesContainer} layout={layoutAnimation} > - {supporting_count && supporting_count > 0 ? ( - - ) : null} {hasMutuals ? ( ) : null} - {supporter_count && supporter_count > 0 ? ( - - ) : null} - diff --git a/packages/mobile/src/screens/profile-screen/ProfileScreenSkeleton.tsx b/packages/mobile/src/screens/profile-screen/ProfileScreenSkeleton.tsx index 4aa27e0526f..7133831b3f9 100644 --- a/packages/mobile/src/screens/profile-screen/ProfileScreenSkeleton.tsx +++ b/packages/mobile/src/screens/profile-screen/ProfileScreenSkeleton.tsx @@ -141,7 +141,6 @@ export const ExpandableSectionSkeleton = () => { - {/* TODO: add tip button and supporters skeletons */} ) } diff --git a/packages/mobile/src/screens/profile-screen/TipAudioButton.tsx b/packages/mobile/src/screens/profile-screen/TipAudioButton.tsx deleted file mode 100644 index 5a62c5aa60b..00000000000 --- a/packages/mobile/src/screens/profile-screen/TipAudioButton.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { useCallback } from 'react' - -import { useUser, useProfileUser } from '@audius/common/api' -import { tippingActions } from '@audius/common/store' -import { Platform } from 'react-native' -import { useDispatch } from 'react-redux' - -import { IconTokenGold, Button } from '@audius/harmony-native' -import { useNavigation } from 'app/hooks/useNavigation' - -const { beginTip } = tippingActions - -const messages = { - title: 'Tip $AUDIO', - // NOTE: Send tip -> Send $AUDIO change - titleAlt: 'Send $AUDIO', // iOS only - label: 'Tip Audio tokens', - labelAlt: 'Send Audio tokens' // iOS only -} - -export const TipAudioButton = () => { - const navigation = useNavigation() - const { user_id } = - useProfileUser({ - select: (user) => ({ user_id: user.user_id }) - }).user ?? {} - const { data: user } = useUser(user_id) - const dispatch = useDispatch() - - const handlePress = useCallback(() => { - if (user) { - dispatch(beginTip({ user, source: 'profile' })) - navigation.navigate('TipArtist') - } - }, [dispatch, user, navigation]) - - return ( - - ) -} diff --git a/packages/mobile/src/screens/settings-screen/InboxSettingsFields.tsx b/packages/mobile/src/screens/settings-screen/InboxSettingsFields.tsx index cd37f3a6e17..2d2f248146d 100644 --- a/packages/mobile/src/screens/settings-screen/InboxSettingsFields.tsx +++ b/packages/mobile/src/screens/settings-screen/InboxSettingsFields.tsx @@ -10,8 +10,6 @@ import { Switch } from 'app/components/core' const messages = { allowAll: 'Allow Messages from Everyone', followeeTitle: 'People You Follow', - tipperTitle: 'Tip Supporters', - tippedArtistsTitle: "Artists You've Tipped", followersTitle: 'Your Followers', verifiedTitle: 'Verified Users' } @@ -21,14 +19,6 @@ const options = [ title: messages.followeeTitle, value: ChatPermission.FOLLOWEES }, - { - title: messages.tipperTitle, - value: ChatPermission.TIPPERS - }, - { - title: messages.tippedArtistsTitle, - value: ChatPermission.TIPPEES - }, { title: messages.followersTitle, value: ChatPermission.FOLLOWERS diff --git a/packages/mobile/src/screens/tip-artist-screen/AvailableAudio.tsx b/packages/mobile/src/screens/tip-artist-screen/AvailableAudio.tsx deleted file mode 100644 index 14c5c605228..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/AvailableAudio.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { useAudioBalance } from '@audius/common/api' -import type { StringWei } from '@audius/common/models' -import { isNullOrUndefined } from '@audius/common/utils' -import { AUDIO } from '@audius/fixed-decimal' -import { Image, Platform, View } from 'react-native' - -import TokenBadgeNoTier from 'app/assets/images/tokenBadgeNoTier.png' -import { Text } from 'app/components/core' -import Skeleton from 'app/components/skeleton' -import { makeStyles } from 'app/styles' - -const useStyles = makeStyles(({ spacing, typography, palette }) => ({ - root: { - marginBottom: spacing(6), - marginHorizontal: spacing(2) - }, - text: { - fontFamily: typography.fontByWeight.heavy, - textTransform: 'uppercase', - color: palette.neutralLight4 - }, - availableAudio: { - flexDirection: 'row', - alignItems: 'center', - paddingVertical: spacing(2) - }, - audioToken: { - height: spacing(4), - width: spacing(4), - marginLeft: spacing(3), - marginRight: spacing(1) - } -})) - -const messages = { - available: 'Available to send', - disclaimer: '$AUDIO held in linked wallets cannot be used to tip', - // NOTE: Send tip -> Send $AUDIO change - disclaimerAlt: 'Cannot use $AUDIO held in linked wallets' // iOS only -} - -export const AvailableAudio = () => { - const { accountBalance: audioBalanceBigInt, isLoading: isBalanceLoading } = - useAudioBalance({ - includeConnectedWallets: false - }) - - // Convert BigInt to audio amount string for display - const accountBalance = audioBalanceBigInt - ? (audioBalanceBigInt.toString() as StringWei) - : null - - const styles = useStyles() - - return ( - - - - {messages.available} - - - {isBalanceLoading || isNullOrUndefined(accountBalance) ? ( - - ) : ( - - {AUDIO(BigInt(accountBalance)).toLocaleString(undefined, { - maximumFractionDigits: 0 - })} - - )} - - - {Platform.OS === 'ios' ? messages.disclaimerAlt : messages.disclaimer} - - - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/ConfirmSendTipScreen.tsx b/packages/mobile/src/screens/tip-artist-screen/ConfirmSendTipScreen.tsx deleted file mode 100644 index 87380c12f63..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/ConfirmSendTipScreen.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import { useCallback, useEffect } from 'react' - -import { tippingSelectors, tippingActions } from '@audius/common/store' -import type { NativeStackScreenProps } from '@react-navigation/native-stack' -import { useKeepAwake } from '@thehale/react-native-keep-awake' -import { Platform } from 'react-native' -import { useDispatch, useSelector } from 'react-redux' - -import { - Button, - IconCaretLeft, - IconCheck, - PlainButton -} from '@audius/harmony-native' -import { useNavigation } from 'app/hooks/useNavigation' -import { makeStyles } from 'app/styles' - -import { ReceiverDetails } from './ReceiverDetails' -import { SendTipStatusText } from './SendTipStatusText' -import { TipHeader } from './TipHeader' -import { TipScreen } from './TipScreen' -import type { TipArtistNavigationParamList } from './navigation' - -const { beginTip, confirmSendTip } = tippingActions -const { getSendTipData } = tippingSelectors - -const messages = { - title: 'Confirm Tip', - // NOTE: Send tip -> Send $AUDIO change - titleAlt: 'Confirm', // iOS only - confirm: 'Confirm Tip', - confirmAlt: 'Confirm', // iOS only - goBack: 'Go Back' -} - -const useStyles = makeStyles(({ spacing }) => ({ - disclaimer: { - textAlign: 'center', - marginBottom: spacing(6) - }, - confirmButton: { - marginBottom: spacing(6) - }, - goBack: { - alignSelf: 'center' - } -})) - -type ConfirmSendTipScreenProps = NativeStackScreenProps< - TipArtistNavigationParamList, - 'ConfirmTip' -> - -export const ConfirmSendTipScreen = ({ - navigation: nativeNavigation -}: ConfirmSendTipScreenProps) => { - useKeepAwake() - const styles = useStyles() - const { - user: receiver, - status: sendStatus, - source - } = useSelector(getSendTipData) - const navigation = useNavigation() - const dispatch = useDispatch() - - const handleConfirm = useCallback(() => { - dispatch(confirmSendTip()) - }, [dispatch]) - - const handleGoBack = useCallback(() => { - dispatch(beginTip({ user: receiver, source })) - navigation.goBack() - }, [dispatch, navigation, receiver, source]) - - const inProgress = sendStatus === 'SENDING' || sendStatus === 'CONVERTING' - - useEffect(() => { - if (sendStatus === 'SUCCESS') { - navigation.navigate('TipSent') - } - }, [sendStatus, navigation]) - - // Disable navigating back via swipes - // if we're in progress - useEffect(() => { - nativeNavigation.setOptions({ - gestureEnabled: !inProgress - }) - }, [nativeNavigation, inProgress]) - - return ( - - - - - - {inProgress ? null : ( - - {messages.goBack} - - )} - - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/DegradationNotice.tsx b/packages/mobile/src/screens/tip-artist-screen/DegradationNotice.tsx deleted file mode 100644 index e630b49d99f..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/DegradationNotice.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import React from 'react' - -import { useRemoteVar } from '@audius/common/hooks' -import { StringKeys } from '@audius/common/services' -import { Text } from 'react-native' -import LinearGradient from 'react-native-linear-gradient' - -import { makeStyles } from 'app/styles' -import { useThemeColors } from 'app/utils/theme' - -const useStyles = makeStyles(({ spacing, palette, typography }) => ({ - root: { - marginTop: -48, // TipScreen has paddingVertical 60 - marginBottom: spacing(12), - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'flex-start', - paddingVertical: spacing(2), - paddingHorizontal: spacing(3), - borderRadius: 4 - }, - text: { - marginLeft: spacing(3.5), - color: palette.white, - fontSize: typography.fontSize.medium, - fontFamily: typography.fontByWeight.demiBold, - lineHeight: typography.fontSize.medium * 1.3 - } -})) - -export const DegradationNotice = () => { - const styles = useStyles() - const { pageHeaderGradientColor1, pageHeaderGradientColor2 } = - useThemeColors() - - const audioFeaturesDegradedText = useRemoteVar( - StringKeys.AUDIO_FEATURES_DEGRADED_TEXT - ) - return audioFeaturesDegradedText ? ( - - {audioFeaturesDegradedText} - - ) : null -} diff --git a/packages/mobile/src/screens/tip-artist-screen/DescriptionText.tsx b/packages/mobile/src/screens/tip-artist-screen/DescriptionText.tsx deleted file mode 100644 index bf5a958e7e4..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/DescriptionText.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { TextProps } from 'app/components/core' -import { Text } from 'app/components/core' -import { makeStyles } from 'app/styles' - -const useStyles = makeStyles(({ spacing }) => ({ - text: { - textAlign: 'center', - lineHeight: 19, - marginBottom: spacing(6) - } -})) - -type DescriptionTextProps = TextProps - -export const DescriptionText = (props: DescriptionTextProps) => { - const styles = useStyles() - return ( - - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/ReceiverDetails.tsx b/packages/mobile/src/screens/tip-artist-screen/ReceiverDetails.tsx deleted file mode 100644 index fb465365bfc..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/ReceiverDetails.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { useCallback } from 'react' - -import { tippingSelectors } from '@audius/common/store' -import { css } from '@emotion/native' -import { useTheme } from '@emotion/react' -import { Pressable } from 'react-native' -import { useSelector } from 'react-redux' - -import { Flex, Text } from '@audius/harmony-native' -import { ProfilePicture } from 'app/components/core' -import { UserBadges } from 'app/components/user-badges' -import { useNavigation } from 'app/hooks/useNavigation' -const { getSendUser } = tippingSelectors - -export const ReceiverDetails = () => { - const receiver = useSelector(getSendUser) - const { spacing } = useTheme() - const navigation = useNavigation() - - const handlePress = useCallback(() => { - if (!receiver) return - navigation.getParent()?.goBack() - navigation.navigate('Profile', { handle: receiver?.handle }) - }, [receiver, navigation]) - - if (!receiver) return null - - const { name, handle } = receiver - - return ( - - - - - - - {name} - - - - - @{handle} - - - - - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/SendTipScreen.tsx b/packages/mobile/src/screens/tip-artist-screen/SendTipScreen.tsx deleted file mode 100644 index d5bcf7e5ed8..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/SendTipScreen.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { useCallback, useState } from 'react' - -import { useAudioBalance } from '@audius/common/api' -import { tippingSelectors, tippingActions } from '@audius/common/store' -import type { AudioWei } from '@audius/fixed-decimal' -import { AUDIO } from '@audius/fixed-decimal' -import { Platform } from 'react-native' -import { useDispatch, useSelector } from 'react-redux' - -import { IconArrowRight, IconClose, Button } from '@audius/harmony-native' -import { ErrorText } from 'app/components/core' -import { useNavigation } from 'app/hooks/useNavigation' -import { makeStyles } from 'app/styles' - -import { TopBarIconButton } from '../app-screen' - -import { AvailableAudio } from './AvailableAudio' -import { DegradationNotice } from './DegradationNotice' -import { ReceiverDetails } from './ReceiverDetails' -import { SupporterPrompt } from './SupporterPrompt' -import { TipInput } from './TipInput' -import { TipScreen } from './TipScreen' -import type { TipArtistNavigationParamList } from './navigation' - -const { sendTip } = tippingActions -const { getSendUser } = tippingSelectors - -const messages = { - sendTip: 'Send Tip', - // NOTE: Send tip -> Send $AUDIO change - sendAudio: 'Send $AUDIO', // iOS only - insufficientBalance: 'Insufficient Balance' -} - -const useStyles = makeStyles(({ spacing }) => ({ - sendButton: { - marginBottom: spacing(6) - } -})) - -const zeroWei = BigInt(0) as AudioWei - -export const SendTipScreen = () => { - const styles = useStyles() - const [tipAmount, setTipAmount] = useState('') - - const { accountBalance } = useAudioBalance({ - includeConnectedWallets: false - }) - - const navigation = useNavigation() - const dispatch = useDispatch() - - const receiver = useSelector(getSendUser) - - const handleBack = useCallback(() => { - navigation.goBack() - }, [navigation]) - - const handleSendTip = useCallback(() => { - dispatch(sendTip({ amount: tipAmount })) - navigation.navigate('ConfirmTip') - }, [dispatch, tipAmount, navigation]) - - let tipAmountWei: AudioWei | null = null - try { - tipAmountWei = tipAmount.length > 0 ? AUDIO(tipAmount).value : null - } catch { - tipAmountWei = null - } - - const hasInsufficientBalance = - tipAmountWei !== null && tipAmountWei > accountBalance - - return ( - } - > - - - - - - - {hasInsufficientBalance ? ( - {messages.insufficientBalance} - ) : null} - - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/SendTipStatusText.tsx b/packages/mobile/src/screens/tip-artist-screen/SendTipStatusText.tsx deleted file mode 100644 index a02fa52ce5d..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/SendTipStatusText.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { tippingSelectors } from '@audius/common/store' -import { Platform, View } from 'react-native' -import { useSelector } from 'react-redux' - -import { DescriptionText } from './DescriptionText' -const { getSendStatus } = tippingSelectors - -const messages = { - disclaimer: 'Are you sure? This tip cannot be reversed.', - // NOTE: Send tip -> Send $AUDIO change - disclaimerAlt: 'Are you sure? This action cannot be reversed.', // iOS only - maintenance: 'We’re performing some necessary one-time maintenance.', - severalMinutes: 'This may take several minutes.', - holdOn: 'Don’t close this screen or restart the app.', - somethingWrong: 'Something’s gone wrong. Wait a little while and try again.' -} - -export const SendTipStatusText = () => { - const sendStatus = useSelector(getSendStatus) - - if (sendStatus === 'CONFIRM') - return ( - - {Platform.OS === 'ios' ? messages.disclaimerAlt : messages.disclaimer} - - ) - if (sendStatus === 'SENDING') return null - if (sendStatus === 'CONVERTING') - return ( - - {messages.maintenance} - - {messages.severalMinutes} {'\n'} - {messages.holdOn} - - - ) - if (sendStatus === 'ERROR') - return ( - {messages.somethingWrong} - ) - - return null -} diff --git a/packages/mobile/src/screens/tip-artist-screen/SupporterPrompt.tsx b/packages/mobile/src/screens/tip-artist-screen/SupporterPrompt.tsx deleted file mode 100644 index 80d976006ce..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/SupporterPrompt.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react' - -import { useSupporterPrompt, useRemoteVar } from '@audius/common/hooks' -import { StringKeys } from '@audius/common/services' -import { AUDIO } from '@audius/fixed-decimal' -import { Platform, Text } from 'react-native' -import LinearGradient from 'react-native-linear-gradient' - -import { IconTrophy } from '@audius/harmony-native' -import { makeStyles } from 'app/styles' -import { useThemeColors } from 'app/utils/theme' - -const messages = { - becomeFirstSupporter: 'Tip to become their first supporter', - becomeFirstSupporterAlt: 'Send $AUDIO to become their first supporter', // iOS only - becomeTopSupporterPrefix: 'Tip ', - becomeTopSupporterPrefixAlt: 'Send ', // iOS only - becomeTopSupporterSuffix: ' $AUDIO to become their top supporter' -} - -const useStyles = makeStyles(({ spacing, palette, typography }) => ({ - root: { - marginBottom: spacing(6), - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'flex-start', - paddingVertical: spacing(2), - paddingHorizontal: spacing(3), - borderRadius: 4 - }, - text: { - marginLeft: spacing(3.5), - color: palette.white, - fontSize: typography.fontSize.medium, - fontFamily: typography.fontByWeight.demiBold - } -})) - -type SupporterPromptProps = { - receiverId?: number | null -} - -export const SupporterPrompt = ({ receiverId }: SupporterPromptProps) => { - const styles = useStyles() - const { white, pageHeaderGradientColor1, pageHeaderGradientColor2 } = - useThemeColors() - const { amountToDethrone, isFirstSupporter, isPending } = - useSupporterPrompt(receiverId) - const audioFeaturesDegradedText = useRemoteVar( - StringKeys.AUDIO_FEATURES_DEGRADED_TEXT - ) - - if (isPending) return null - - if (!audioFeaturesDegradedText && !isFirstSupporter && !amountToDethrone) - return null - - const isIOS = Platform.OS === 'ios' - - return ( - - - - {audioFeaturesDegradedText || - (isFirstSupporter ? ( - isIOS ? ( - messages.becomeFirstSupporterAlt - ) : ( - messages.becomeFirstSupporter - ) - ) : ( - <> - {isIOS - ? messages.becomeTopSupporterPrefixAlt - : messages.becomeTopSupporterPrefix} - {AUDIO(amountToDethrone!).trunc().toLocaleString('en-US', { - minimumFractionDigits: 0, - maximumFractionDigits: 0 - })} - {messages.becomeTopSupporterSuffix} - - ))} - - - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/TipArtistModalScreen.tsx b/packages/mobile/src/screens/tip-artist-screen/TipArtistModalScreen.tsx deleted file mode 100644 index 7ca69f43232..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/TipArtistModalScreen.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { useEffect } from 'react' - -import { tippingActions } from '@audius/common/store' -import { createNativeStackNavigator } from '@react-navigation/native-stack' -import { useDispatch } from 'react-redux' - -import { ModalScreen } from 'app/components/core' - -import { useAppScreenOptions } from '../app-screen/useAppScreenOptions' - -import { ConfirmSendTipScreen } from './ConfirmSendTipScreen' -import { SendTipScreen } from './SendTipScreen' -import { TipSentScreen } from './TipSentScreen' -const { resetSend } = tippingActions - -const Stack = createNativeStackNavigator() - -const screenOptionOverrides = { headerRight: () => null } - -export const TipArtistModalScreen = () => { - const screenOptions = useAppScreenOptions(screenOptionOverrides) - const dispatch = useDispatch() - - useEffect(() => { - return () => { - dispatch(resetSend()) - } - }, [dispatch]) - - return ( - - - - - - - - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/TipHeader.tsx b/packages/mobile/src/screens/tip-artist-screen/TipHeader.tsx deleted file mode 100644 index 2a7ebb26571..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/TipHeader.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { tippingSelectors } from '@audius/common/store' -import { formatNumberCommas } from '@audius/common/utils' -import { View } from 'react-native' -import { useSelector } from 'react-redux' - -import { IconCheck, IconSend } from '@audius/harmony-native' -import { Text, AudioText } from 'app/components/core' -import { makeStyles } from 'app/styles' -import { useThemeColors } from 'app/utils/theme' -const { getSendAmount } = tippingSelectors - -const messages = { - sending: 'Sending', - sent: 'Sent Successfully' -} - -const useStyles = makeStyles(({ spacing }) => ({ - header: { - alignSelf: 'center', - alignItems: 'center', - marginBottom: spacing(6) - }, - sending: { - textTransform: 'uppercase', - marginBottom: 0 - } -})) - -type TipHeaderProps = { - status: 'confirm' | 'sent' -} - -export const TipHeader = (props: TipHeaderProps) => { - const { status } = props - const sendAmount = useSelector(getSendAmount) - const styles = useStyles() - const { neutralLight4 } = useThemeColors() - const Icon = status === 'confirm' ? IconSend : IconCheck - const title = status === 'confirm' ? messages.sending : messages.sent - - return ( - - - {' '} - - {title} - - - - {formatNumberCommas(sendAmount)}{' '} - - - - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/TipInput.tsx b/packages/mobile/src/screens/tip-artist-screen/TipInput.tsx deleted file mode 100644 index 692b2bdad87..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/TipInput.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { useCallback, useState } from 'react' - -import { formatNumberCommas } from '@audius/common/utils' - -import type { TextInputProps } from 'app/components/core' -import { AudioText, TextInput } from 'app/components/core' -import { makeStyles } from 'app/styles' - -const messages = { - placeholder: 'Enter an amount' -} - -const useStyles = makeStyles(({ spacing, palette, typography }) => ({ - root: { - paddingVertical: spacing(5), - paddingHorizontal: spacing(4), - marginBottom: spacing(6) - }, - rootFocused: { - borderColor: palette.neutralLight6, - backgroundColor: palette.neutralLight9 - }, - input: { - fontSize: typography.fontSize.xl - } -})) - -type TipInputProps = TextInputProps - -export const TipInput = (props: TipInputProps) => { - const { value, onChangeText, ...other } = props - const styles = useStyles() - - const handleChangeText = useCallback( - (newValue: string) => { - // Allow whole numbers only - const unformattedValue = newValue.replace(/[^0-9]+/g, '') - const numericWhole = parseInt(unformattedValue, 10) - /** - * If not a number, e.g. we attempt to parse an empty string, - * then set the text to an empty string. - * Otherwise, set it as the string version of the whole number. - */ - if (isNaN(numericWhole)) { - onChangeText?.('') - } else { - onChangeText?.(numericWhole.toString()) - } - }, - [onChangeText] - ) - - const formattedValue = formatNumberCommas(value as string) - - const [isFocused, setIsFocused] = useState(false) - - return ( - } - onFocus={() => setIsFocused(true)} - onBlur={() => setIsFocused(false)} - value={formattedValue} - onChangeText={handleChangeText} - contextMenuHidden - {...other} - /> - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/TipScreen.tsx b/packages/mobile/src/screens/tip-artist-screen/TipScreen.tsx deleted file mode 100644 index 951a3a8d3ee..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/TipScreen.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import type { ScreenProps } from 'app/components/core' -import { ScreenContent, Screen } from 'app/components/core' - -type TipScreenProps = ScreenProps - -export const TipScreen = ({ children, ...props }: TipScreenProps) => { - return ( - - {children} - - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/TipSentScreen.tsx b/packages/mobile/src/screens/tip-artist-screen/TipSentScreen.tsx deleted file mode 100644 index 222853059b3..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/TipSentScreen.tsx +++ /dev/null @@ -1,141 +0,0 @@ -import { useCallback } from 'react' - -import { useArtistCoin, useCurrentAccountUser } from '@audius/common/api' -import type { SolanaWalletAddress } from '@audius/common/models' -import { tippingSelectors } from '@audius/common/store' -import { formatNumberCommas, getXShareHandle } from '@audius/common/utils' -import { useNavigation } from '@react-navigation/native' -import { Platform } from 'react-native' -import { useDispatch, useSelector } from 'react-redux' - -import { IconCheck, IconClose, PlainButton } from '@audius/harmony-native' -import { XButton } from 'app/components/x-button' -import { env } from 'app/services/env' -import { makeStyles } from 'app/styles' -import { EventNames } from 'app/types/analytics' - -import { TopBarIconButton } from '../app-screen' - -import { DescriptionText } from './DescriptionText' -import { ReceiverDetails } from './ReceiverDetails' -import { TipHeader } from './TipHeader' -import { TipScreen } from './TipScreen' -const { getSendTipData } = tippingSelectors - -const messages = { - title: 'Tip Sent', - // NOTE: Send tip -> Send $AUDIO change - titleAlt: '$AUDIO Sent', // iOS only - description: 'Share your support on X!', - done: 'Done', - xShare: ( - recipient: string, - amount: string, - isIOS: boolean, - price?: string - ) => { - const totalValue = price && amount ? Number(price) * Number(amount) : null - return `I just ${isIOS ? 'sent' : 'tipped'} ${recipient} ${formatNumberCommas(Number(amount))} $AUDIO ${totalValue ? `(~$${totalValue.toLocaleString('en-US', { maximumFractionDigits: 2 })})` : ''} on @audius` - } -} - -const useStyles = makeStyles(({ spacing }) => ({ - x: { - marginBottom: spacing(6) - }, - close: { - alignSelf: 'center' - }, - button: { - alignSelf: 'center' - } -})) - -export const TipSentScreen = () => { - const dispatch = useDispatch() - const { data: { user_id, handle, spl_wallet } = {} } = useCurrentAccountUser({ - select: (user) => ({ - user_id: user?.user_id, - handle: user?.handle, - spl_wallet: user?.spl_wallet - }) - }) - const { - user: recipient, - amount: sendAmount, - source, - onSuccessActions - } = useSelector(getSendTipData) - const { data: tokenPriceData } = useArtistCoin(env.WAUDIO_MINT_ADDRESS) - const styles = useStyles() - const navigation = useNavigation() - - const tokenPrice = tokenPriceData?.price?.toString() - - const getXShareText = () => { - if (user_id && recipient) { - const recipientName = getXShareHandle(recipient) - return messages.xShare( - recipientName, - sendAmount, - Platform.OS === 'ios', - tokenPrice - ) - } - return '' - } - - const handleClose = useCallback(() => { - // After success + close, take the user to the chat they were - // attempting to make if they were unlocking DMs by tipping. - // The saga will create the chat once the tip is confirmed - if (onSuccessActions && user_id && recipient?.user_id) { - for (const action of onSuccessActions) { - dispatch(action) - } - } else { - navigation.getParent()?.goBack() - } - }, [user_id, dispatch, onSuccessActions, navigation, recipient?.user_id]) - - return ( - } - > - - - {messages.description} - - - {messages.done} - - - ) -} diff --git a/packages/mobile/src/screens/tip-artist-screen/index.ts b/packages/mobile/src/screens/tip-artist-screen/index.ts deleted file mode 100644 index 9fb8764f23a..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './TipArtistModalScreen' diff --git a/packages/mobile/src/screens/tip-artist-screen/navigation.ts b/packages/mobile/src/screens/tip-artist-screen/navigation.ts deleted file mode 100644 index 532cdee4b7a..00000000000 --- a/packages/mobile/src/screens/tip-artist-screen/navigation.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type TipArtistNavigationParamList = { - SendTip: undefined - ConfirmTip: undefined - TipSent: undefined -} diff --git a/packages/mobile/src/screens/user-list-screen/SupporterInfo.tsx b/packages/mobile/src/screens/user-list-screen/SupporterInfo.tsx deleted file mode 100644 index d474515cf39..00000000000 --- a/packages/mobile/src/screens/user-list-screen/SupporterInfo.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { useSupporter } from '@audius/common/api' -import type { ID } from '@audius/common/models' - -import { Flex, Text, IconTrending, IconTrophy } from '@audius/harmony-native' -import { useRoute } from 'app/hooks/useRoute' -import { useThemeColors } from 'app/utils/theme' - -import { Tip } from './Tip' - -type SupporterInfoProps = { - userId: ID -} - -export const SupporterInfo = (props: SupporterInfoProps) => { - const { userId } = props - const { - params: { userId: supportersId } - } = useRoute<'TopSupporters'>() - - const { secondary, neutralLight4 } = useThemeColors() - const { data: supportFor } = useSupporter({ - userId: supportersId, - supporterUserId: userId - }) - - const rank = supportFor?.rank - const amount = supportFor?.amount - - const isTopRank = rank <= 5 - const RankIcon = isTopRank ? IconTrophy : IconTrending - - return ( - - - - - - #{rank} - {' '} - {isTopRank ? 'Supporter' : null} - - - - - ) -} diff --git a/packages/mobile/src/screens/user-list-screen/SupportingInfo.tsx b/packages/mobile/src/screens/user-list-screen/SupportingInfo.tsx deleted file mode 100644 index 5672080f24c..00000000000 --- a/packages/mobile/src/screens/user-list-screen/SupportingInfo.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { useSupporter } from '@audius/common/api' -import type { ID } from '@audius/common/models' - -import { useRoute } from 'app/hooks/useRoute' - -import { Tip } from './Tip' - -type SupportingInfoProps = { - userId: ID -} - -export const SupportingInfo = (props: SupportingInfoProps) => { - const { userId } = props - - const { - params: { userId: supportingId } - } = useRoute<'SupportingUsers'>() - - const { data: supportFor } = useSupporter({ - userId, - supporterUserId: supportingId - }) - - const amount = supportFor?.amount - - return -} diff --git a/packages/mobile/src/screens/user-list-screen/SupportingUsersScreen.tsx b/packages/mobile/src/screens/user-list-screen/SupportingUsersScreen.tsx deleted file mode 100644 index d8fee5cb14d..00000000000 --- a/packages/mobile/src/screens/user-list-screen/SupportingUsersScreen.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { useSupportedUsers, useUser } from '@audius/common/api' - -import { IconTipping } from '@audius/harmony-native' -import { useRoute } from 'app/hooks/useRoute' - -import { UserList } from './UserList' -import { UserListScreen } from './UserListScreen' -const messages = { - title: 'Supporting' -} - -export const SupportingUsersScreen = () => { - const { params } = useRoute<'SupportingUsers'>() - const { userId } = params - - const { data: supportingCount } = useUser(userId, { - select: (user) => user.supporting_count - }) - - const { data, isFetchingNextPage, isPending, fetchNextPage } = - useSupportedUsers({ userId }) - - return ( - - supporter.receiver.user_id)} - totalCount={supportingCount} - isFetchingNextPage={isFetchingNextPage} - isPending={isPending} - fetchNextPage={fetchNextPage} - tag='SUPPORTING' - /> - - ) -} diff --git a/packages/mobile/src/screens/user-list-screen/Tip.tsx b/packages/mobile/src/screens/user-list-screen/Tip.tsx deleted file mode 100644 index 769f3b59748..00000000000 --- a/packages/mobile/src/screens/user-list-screen/Tip.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import type { StringWei } from '@audius/common/models' -import { AUDIO } from '@audius/fixed-decimal' - -import { Flex, Text, IconTipping } from '@audius/harmony-native' -import { AudioText } from 'app/components/core' - -type TipProps = { - amount: StringWei -} - -export const Tip = (props: TipProps) => { - const { amount } = props - - return ( - - - - - {AUDIO(BigInt(amount)).toLocaleString()} - - - - - ) -} diff --git a/packages/mobile/src/screens/user-list-screen/TopSupportersScreen.tsx b/packages/mobile/src/screens/user-list-screen/TopSupportersScreen.tsx deleted file mode 100644 index bf5e391fa56..00000000000 --- a/packages/mobile/src/screens/user-list-screen/TopSupportersScreen.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useCurrentUserId, useSupporters, useUser } from '@audius/common/api' -import { ChatBlastAudience } from '@audius/sdk' -import { css } from '@emotion/native' - -import { Box, IconTrophy } from '@audius/harmony-native' -import { useRoute } from 'app/hooks/useRoute' - -import { ChatBlastWithAudienceCTA } from '../chat-screen/ChatBlastWithAudienceCTA' - -import { UserList } from './UserList' -import { UserListScreen } from './UserListScreen' - -const messages = { - title: 'Top Supporters' -} - -export const TopSupportersScreen = () => { - const { params } = useRoute<'TopSupporters'>() - const { userId } = params - - const { data: supporterCount } = useUser(userId, { - select: (user) => user.supporter_count - }) - - const { data: currentUserId } = useCurrentUserId() - const { data, isFetchingNextPage, isPending, fetchNextPage } = useSupporters({ - userId - }) - - return ( - - <> - supporter.sender.user_id)} - totalCount={supporterCount} - isFetchingNextPage={isFetchingNextPage} - isPending={isPending} - fetchNextPage={fetchNextPage} - tag='TOP SUPPORTERS' - /> - {currentUserId === userId ? ( - - - - ) : null} - - - ) -} diff --git a/packages/mobile/src/screens/user-list-screen/UserListItem.tsx b/packages/mobile/src/screens/user-list-screen/UserListItem.tsx index bd286fc87ba..053a0f7e258 100644 --- a/packages/mobile/src/screens/user-list-screen/UserListItem.tsx +++ b/packages/mobile/src/screens/user-list-screen/UserListItem.tsx @@ -16,9 +16,6 @@ import { useColorAnimation } from 'app/hooks/usePressColorAnimation' import { makeStyles } from 'app/styles' import { useThemeColors } from 'app/utils/theme' -import { SupporterInfo } from './SupporterInfo' -import { SupportingInfo } from './SupportingInfo' - const messages = { followers: (followerCount: number) => followerCount === 1 ? 'Follower' : 'Followers' @@ -42,7 +39,7 @@ type UserListItemProps = { } export const UserListItem = (props: UserListItemProps) => { - const { tag, userId, showRank, rank, renderRightContent } = props + const { userId, showRank, rank, renderRightContent } = props const { data: user } = useUser(userId, { select: (user) => pick(user, ['handle', 'follower_count']) }) @@ -97,10 +94,6 @@ export const UserListItem = (props: UserListItemProps) => { - {tag === 'SUPPORTING' ? : null} - {tag === 'TOP SUPPORTERS' ? ( - - ) : null} {renderRightContent && ( diff --git a/packages/mobile/src/screens/user-list-screen/UserListItemSkeleton.tsx b/packages/mobile/src/screens/user-list-screen/UserListItemSkeleton.tsx index ede827d8a69..1e59aee2c17 100644 --- a/packages/mobile/src/screens/user-list-screen/UserListItemSkeleton.tsx +++ b/packages/mobile/src/screens/user-list-screen/UserListItemSkeleton.tsx @@ -10,14 +10,11 @@ type Props = { const profileStyle = css({ height: 74, width: 74, borderRadius: 74 }) -export const UserListItemSkeleton = (props: Props) => { - const { tag } = props - const isSupporterTile = ['SUPPORTING', 'TOP SUPPORTERS'].includes(tag) - const itemHeight = isSupporterTile ? 171 : 154 +export const UserListItemSkeleton = (_props: Props) => { const { cornerRadius } = useTheme() return ( - + @@ -26,12 +23,6 @@ export const UserListItemSkeleton = (props: Props) => { - {isSupporterTile ? ( - - - - - ) : null} Send $AUDIO change - sendFirstTipTitleAlt: 'Send Your First $AUDIO', // iOS only - sendFirstTipDescription: - 'Show some love to your favorite artist and send them a tip', - sendFirstTipShortDescription: - 'Show some love to your favorite artist and send them a tip', - sendFirstTipDescriptionAlt: - 'Show some love to your favorite artist and send them $AUDIO', // iOS only - sendFirstTipShortDescriptionAlt: - 'Show some love to your favorite artist and send them $AUDIO', // iOS only - sendFirstTipButton: 'Send a Tip', - sendFirstTipButtonAlt: 'Find Artists to Support', // iOS only - sendFirstTipCompletedLabelAlt: 'Support Another Artist' // iOS only -} - export type ChallengesParamList = { trending: undefined explore: undefined diff --git a/packages/web/src/app/web-player/WebPlayer.tsx b/packages/web/src/app/web-player/WebPlayer.tsx index cea5a55769e..fc26c7c8ef5 100644 --- a/packages/web/src/app/web-player/WebPlayer.tsx +++ b/packages/web/src/app/web-player/WebPlayer.tsx @@ -209,12 +209,6 @@ const ExplorePage = lazy(() => })) ) const SettingsPage = lazy(() => import('pages/settings-page/SettingsPage')) -const SupportingPage = lazy( - () => import('pages/supporting-page/SupportingPage') -) -const TopSupportersPage = lazy( - () => import('pages/top-supporters-page/TopSupportersPage') -) const TrackCommentsPage = lazy(() => import('pages/track-page/TrackCommentsPage').then((m) => ({ default: m.TrackCommentsPage @@ -291,8 +285,6 @@ const { CHECK_PAGE, TRENDING_PLAYLISTS_PAGE_LEGACY, DEACTIVATE_PAGE, - SUPPORTING_USERS_ROUTE, - TOP_SUPPORTERS_USERS_ROUTE, publicSiteRoutes, CHAT_PAGE, PROFILE_PAGE_COMMENTS, @@ -1183,14 +1175,6 @@ const WebPlayer = (props: WebPlayerProps) => { path={COIN_DETAIL_MOBILE_WEB_ROUTE} element={} /> - } - /> - } - /> } /> ) : ( @@ -1219,14 +1203,6 @@ const WebPlayer = (props: WebPlayerProps) => { path={COIN_DETAIL_MOBILE_WEB_ROUTE} element={} /> - } - /> - } - /> } @@ -1520,14 +1496,6 @@ const WebPlayer = (props: WebPlayerProps) => { path={COIN_DETAIL_MOBILE_WEB_ROUTE} element={} /> - } - /> - } - /> } diff --git a/packages/web/src/common/store/cache/tracks/sagaHelpers.ts b/packages/web/src/common/store/cache/tracks/sagaHelpers.ts index 2075c419d1d..ef96c953b83 100644 --- a/packages/web/src/common/store/cache/tracks/sagaHelpers.ts +++ b/packages/web/src/common/store/cache/tracks/sagaHelpers.ts @@ -3,7 +3,6 @@ import { Name, TrackAccessType, isContentFollowGated, - isContentTipGated, isContentTokenGated, isContentUSDCPurchaseGated, Track @@ -19,8 +18,6 @@ function getTrackAccess({ if (is_stream_gated && stream_conditions) { if (isContentFollowGated(stream_conditions)) { return TrackAccessType.FOLLOW_GATED - } else if (isContentTipGated(stream_conditions)) { - return TrackAccessType.TIP_GATED } else if (isContentTokenGated(stream_conditions)) { return TrackAccessType.TOKEN_GATED } else if (isContentUSDCPurchaseGated(stream_conditions)) { diff --git a/packages/web/src/common/store/tipping/sagas.ts b/packages/web/src/common/store/tipping/sagas.ts deleted file mode 100644 index 39d67962e57..00000000000 --- a/packages/web/src/common/store/tipping/sagas.ts +++ /dev/null @@ -1,301 +0,0 @@ -import { - QUERY_KEYS, - getSupportedUsersQueryKey, - getSupporterQueryKey, - getSupportersQueryKey, - getUserQueryKey, - queryAccountUser, - queryWalletAddresses -} from '@audius/common/api' -import { Name, SolanaWalletAddress } from '@audius/common/models' -import { - chatActions, - tippingSelectors, - tippingActions, - getContext, - getSDK -} from '@audius/common/store' -import { isNullOrUndefined } from '@audius/common/utils' -import { AUDIO } from '@audius/fixed-decimal' -import { Id } from '@audius/sdk' -import { - call, - delay, - put, - select, - takeEvery, - fork, - cancel -} from 'typed-redux-saga' - -import { make } from 'common/store/analytics/actions' -import { reportToSentry } from 'store/errors/reportToSentry' - -const { - confirmSendTip, - convert, - sendTipFailed, - sendTipSucceeded, - refreshTipGatedTracks -} = tippingActions -const { getSendTipData } = tippingSelectors - -const { fetchPermissions } = chatActions - -/** - * Polls the /supporter endpoint to check if the sender is listed as a supporter of the recipient - */ -function* confirmTipIndexed({ - signature, - maxAttempts = 60, - delayMs = 1000 -}: { - signature: string - maxAttempts?: number - delayMs?: number -}) { - for (let attempts = 0; attempts < maxAttempts; attempts++) { - console.debug( - `Confirming tip is indexed... [${ - attempts + 1 - }/${maxAttempts}] (delay: ${delayMs}ms)` - ) - try { - const sdk = yield* getSDK() - const { data } = yield* call([sdk.full.tips, sdk.full.tips.getTips], { - txSignatures: [signature] - }) - - if (data && data.length > 0) { - console.info('Tip indexed') - return true - } else if (data?.length === 0) { - console.debug('Tip not indexed yet...') - } - yield* delay(delayMs) - } catch (e) { - console.error('Error confirming tip indexed: ', e) - return false - } - } - console.error('Tip could not be confirmed as indexed before timing out.') - return false -} - -function* wormholeAudioIfNecessary({ amount }: { amount: number }) { - const walletClient = yield* getContext('walletClient') - const { currentUser } = yield* call(queryWalletAddresses) - if (!currentUser) { - throw new Error('Failed to retrieve current user wallet address') - } - - const waudioBalanceWei = yield* call( - [walletClient, walletClient.getCurrentWAudioBalance], - { - ethAddress: currentUser - } - ) - const audioWeiAmount = AUDIO(amount).value - - if (isNullOrUndefined(waudioBalanceWei)) { - throw new Error('Failed to retrieve current wAudio balance') - } - - // If transferring spl wrapped audio and there are insufficent funds with only the - // user bank balance, transfer all eth AUDIO to spl wrapped audio - if (audioWeiAmount > waudioBalanceWei) { - console.info('Converting Ethereum AUDIO to Solana wAUDIO...') - - // Wait for a second before showing the notice that this might take a while - const showConvertingMessage = yield* fork(function* () { - yield delay(1000) - yield put(convert()) - }) - try { - yield* call([walletClient, walletClient.transferTokensFromEthToSol], { - ethAddress: currentUser - }) - } catch (e) { - reportToSentry({ - error: e instanceof Error ? e : new Error(e as string), - name: 'transferTokensFromEthToSol', - additionalInfo: { - ethAddress: currentUser - } - }) - } - // Cancel showing the notice if the conversion was magically super quick - yield cancel(showConvertingMessage) - } -} - -function* sendTipAsync() { - const audiusSdk = yield* getContext('audiusSdk') - const sdk = yield* call(audiusSdk) - const isNativeMobile = yield* getContext('isNativeMobile') - - const sender = yield* call(queryAccountUser) - const { - trackId, - user: receiver, - amount: stringAudioAmount, - onSuccessConfirmedActions, - source - } = yield* select(getSendTipData) - - if (!sender || !receiver) { - return - } - - const device = isNativeMobile ? 'mobile' : 'web' - - const senderUserId = Id.parse(sender.user_id) - const receiverUserId = Id.parse(receiver.user_id) - const amount = Number(stringAudioAmount) - - let senderWallet: SolanaWalletAddress | undefined - let recipientWallet: SolanaWalletAddress | undefined - - // Using `deriveUserBank` here because we just need the addresses for - // analytics. The SDK call to send the tip will create them if needed. - try { - senderWallet = (yield* call( - [ - sdk.services.claimableTokensClient, - sdk.services.claimableTokensClient.deriveUserBank - ], - { ethWallet: sender.erc_wallet, mint: 'wAUDIO' } - )).toString() as SolanaWalletAddress - recipientWallet = (yield* call( - [ - sdk.services.claimableTokensClient, - sdk.services.claimableTokensClient.deriveUserBank - ], - { ethWallet: receiver.erc_wallet, mint: 'wAUDIO' } - )).toString() as SolanaWalletAddress - } catch (e) { - // Don't want these to fail the saga as it's just used for analytics - console.warn('Failed to derive user bank address for tip analytics', e) - } - - try { - yield put( - make(Name.TIP_AUDIO_REQUEST, { - senderWallet, - recipientWallet, - senderHandle: sender.handle, - recipientHandle: receiver.handle, - amount, - device, - source - }) - ) - - yield* call(wormholeAudioIfNecessary, { amount }) - - const signature = yield* call([sdk.users, sdk.users.sendTip], { - amount, - senderUserId, - receiverUserId - }) - - yield put(sendTipSucceeded()) - yield put( - make(Name.TIP_AUDIO_SUCCESS, { - recipientHandle: receiver.handle, - amount: stringAudioAmount, - device, - source - }) - ) - - yield* put(refreshTipGatedTracks({ userId: receiver.user_id, trackId })) - - yield* fork(function* () { - // Wait for tip to index - yield* call(confirmTipIndexed, { signature }) - - // Trigger a refetch for all audio balances - queryClient.invalidateQueries({ - queryKey: [QUERY_KEYS.audioBalance] - }) - - // Refetch chat permissions - yield* put( - fetchPermissions({ userIds: [sender.user_id, receiver.user_id] }) - ) - - // Do any callbacks - if (onSuccessConfirmedActions) { - // Spread here to unfreeze the action - // Redux sagas can't "put" frozen actions - for (const action of onSuccessConfirmedActions) { - yield* put({ ...action }) - } - } - - // Record if the tip unlocked a chat - if (source === 'inboxUnavailableModal') { - yield* put( - make(Name.TIP_UNLOCKED_CHAT, { - recipientUserId: receiver.user_id - }) - ) - } - }) - - // Invalidate all the entities that are affected by this tip - const queryClient = yield* getContext('queryClient') - - queryClient.invalidateQueries({ - queryKey: getUserQueryKey(receiver.user_id) - }) - queryClient.invalidateQueries({ - queryKey: getUserQueryKey(sender.user_id) - }) - queryClient.invalidateQueries({ - queryKey: getSupportersQueryKey(receiver.user_id) - }) - queryClient.invalidateQueries({ - queryKey: getSupporterQueryKey(receiver.user_id, sender.user_id) - }) - queryClient.invalidateQueries({ - queryKey: getSupportedUsersQueryKey(sender.user_id) - }) - } catch (error) { - const e = error instanceof Error ? error : new Error(String(error)) - console.error(`Send tip failed`, error) - yield* put(sendTipFailed({ error: e.message })) - yield* put( - make(Name.TIP_AUDIO_FAILURE, { - senderWallet, - recipientWallet, - senderHandle: sender.handle, - recipientHandle: receiver.handle, - amount, - error: 'transactionMessage' in e ? e.transactionMessage : e.message, - device, - source - }) - ) - yield* call(reportToSentry, { - name: 'SendTip', - error: e, - additionalInfo: { - senderUserId, - receiverUserId, - amount - } - }) - } -} - -function* watchConfirmSendTip() { - yield* takeEvery(confirmSendTip.type, sendTipAsync) -} - -const sagas = () => { - return [watchConfirmSendTip] -} - -export default sagas diff --git a/packages/web/src/common/store/upload/sagaHelpers.ts b/packages/web/src/common/store/upload/sagaHelpers.ts index 1ca3c9236ff..26df30f94ae 100644 --- a/packages/web/src/common/store/upload/sagaHelpers.ts +++ b/packages/web/src/common/store/upload/sagaHelpers.ts @@ -2,7 +2,6 @@ import { queryAccountUser } from '@audius/common/api' import { Name, isContentFollowGated, - isContentTipGated, isContentTokenGated, isContentUSDCPurchaseGated, USDCPurchaseConditions @@ -42,14 +41,6 @@ export function* recordGatedTracks( lossless: isOriginalAvailable }) ) - } else if (isContentTipGated(streamConditions)) { - out.push( - make(Name.TRACK_UPLOAD_TIP_GATED, { - kind: 'tracks', - downloadable: isDownloadable, - lossless: isOriginalAvailable - }) - ) } else if (isContentTokenGated(streamConditions)) { out.push( make(Name.TRACK_UPLOAD_TOKEN_GATED, { diff --git a/packages/web/src/components/artist/ArtistCard.tsx b/packages/web/src/components/artist/ArtistCard.tsx index b4cfcb0bacb..64442b82774 100644 --- a/packages/web/src/components/artist/ArtistCard.tsx +++ b/packages/web/src/components/artist/ArtistCard.tsx @@ -9,7 +9,6 @@ import Stats, { StatProps } from 'components/stats/Stats' import styles from './ArtistCard.module.css' import { ArtistCardCover } from './ArtistCardCover' -import { ArtistSupporting } from './ArtistSupporting' const { followUser, unfollowUser } = usersSocialActions type ArtistCardProps = { @@ -95,7 +94,6 @@ export const ArtistCard = (props: ArtistCardProps) => {
-
{bio}
void showPopover?: boolean showFollowsYou?: boolean - showSupportFor?: ID - showSupportFrom?: ID className?: string popoverMount?: MountPlacement customChips?: React.ReactNode @@ -84,8 +80,6 @@ const ArtistChip = ({ onClickArtistName, showPopover = true, showFollowsYou = true, - showSupportFor, - showSupportFrom, className = '', popoverMount = MountPlacement.PAGE, customChips = null, @@ -180,15 +174,6 @@ const ArtistChip = ({ userId={userId} followerCount={follower_count} /> - {showSupportFor ? ( - - ) : null} - {showSupportFrom ? ( - - ) : null} )}
diff --git a/packages/web/src/components/artist/ArtistChipSupportFor.tsx b/packages/web/src/components/artist/ArtistChipSupportFor.tsx deleted file mode 100644 index 6e512894af6..00000000000 --- a/packages/web/src/components/artist/ArtistChipSupportFor.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { useSupporter } from '@audius/common/api' -import { ID } from '@audius/common/models' -import { AUDIO } from '@audius/fixed-decimal' -import { - IconTipping as IconTip, - IconTrophy, - IconTrending -} from '@audius/harmony' -import cn from 'classnames' - -import { TIPPING_TOP_RANK_THRESHOLD } from 'utils/constants' - -import styles from './ArtistChip.module.css' - -const messages = { - audio: '$AUDIO', - supporter: 'Supporter' -} - -type ArtistChipTipsProps = { - artistId: ID - userId?: ID -} - -export const ArtistChipSupportFor = ({ - artistId, - userId -}: ArtistChipTipsProps) => { - const { data: supportFor } = useSupporter({ - supporterUserId: artistId, - userId - }) - - const rank = supportFor?.rank - const amount = supportFor?.amount - - return ( -
-
- {rank && rank >= 1 && rank <= TIPPING_TOP_RANK_THRESHOLD ? ( -
- - #{rank} - {messages.supporter} -
- ) : rank ? ( -
- - #{rank} -
- ) : null} -
- {amount && ( -
- - - {AUDIO(BigInt(amount)).toLocaleString(undefined, { - maximumFractionDigits: 0 - })} - - {messages.audio} -
- )} -
- ) -} diff --git a/packages/web/src/components/artist/ArtistChipSupportFrom.tsx b/packages/web/src/components/artist/ArtistChipSupportFrom.tsx deleted file mode 100644 index 91158113535..00000000000 --- a/packages/web/src/components/artist/ArtistChipSupportFrom.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { useSupporter } from '@audius/common/api' -import { ID } from '@audius/common/models' -import { AUDIO } from '@audius/fixed-decimal' -import { IconTipping as IconTip } from '@audius/harmony' -import cn from 'classnames' - -import styles from './ArtistChip.module.css' - -const messages = { - audio: '$AUDIO' -} - -type ArtistChipTipsProps = { - artistId: ID - userId: ID -} - -export const ArtistChipSupportFrom = ({ - artistId, - userId -}: ArtistChipTipsProps) => { - const { data: supportFrom } = useSupporter({ - supporterUserId: userId, - userId: artistId - }) - - const amount = supportFrom?.amount - - return ( -
- {amount && ( -
- - - {AUDIO(BigInt(amount)).toLocaleString(undefined, { - maximumFractionDigits: 0 - })} - - {messages.audio} -
- )} -
- ) -} diff --git a/packages/web/src/components/artist/ArtistSupporting.module.css b/packages/web/src/components/artist/ArtistSupporting.module.css deleted file mode 100644 index 289cae27d1a..00000000000 --- a/packages/web/src/components/artist/ArtistSupporting.module.css +++ /dev/null @@ -1,50 +0,0 @@ -.emptyContainer { - /* - The non-empty supportingContainer with the profile picture list has - a height of 77px. - There are paddings of 8px on the top and bottom. - There is also a bottom margin 8px. - Finally, there are borders of 1px of the top and bottom. - This makes 77+8+8+8+1+1 = 103 - */ - height: 103px; -} -.supportingContainer { - margin-bottom: 8px; - padding: 8px; - border: 1px solid var(--harmony-n-150); - border-radius: 4px; -} -.supportingContainer:hover { - cursor: pointer; -} - -.supportingTitleContainer { - display: flex; - align-items: center; - color: var(--harmony-neutral); - font-weight: var(--harmony-font-bold); - font-size: var(--harmony-font-s); -} -.supportingTitle { - margin-left: 8px; -} -.supportingIcon { - width: 20px; - height: 20px; -} -.supportingIcon path { - fill: var(--harmony-neutral); -} - -.line { - width: 100%; - height: 1px; - background: var(--harmony-n-150); - margin: 6px 0 8px; -} - -.profilePictureWrapper { - width: 39px; - height: 39px; -} diff --git a/packages/web/src/components/artist/ArtistSupporting.tsx b/packages/web/src/components/artist/ArtistSupporting.tsx deleted file mode 100644 index 61e38c792e3..00000000000 --- a/packages/web/src/components/artist/ArtistSupporting.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { useCallback } from 'react' - -import { useSupportedUsers } from '@audius/common/api' -import { User } from '@audius/common/models' -import { - userListActions, - SUPPORTING_USER_LIST_TAG as SUPPORTING_TAG -} from '@audius/common/store' -import { MAX_ARTIST_HOVER_TOP_SUPPORTING } from '@audius/common/utils' -import { IconTipping as IconTip } from '@audius/harmony' -import { useDispatch } from 'react-redux' - -import { UserProfilePictureList } from 'components/user-profile-picture-list' -import { - setUsers, - setVisibility -} from 'store/application/ui/userListModal/slice' -import { - UserListEntityType, - UserListType -} from 'store/application/ui/userListModal/types' - -import styles from './ArtistSupporting.module.css' -const { loadMore, reset } = userListActions - -const messages = { - supporting: 'Supporting' -} - -type ArtistSupportingProps = { - artist: User - onNavigateAway?: () => void -} -export const ArtistSupporting = (props: ArtistSupportingProps) => { - const { artist, onNavigateAway } = props - const { user_id, supporting_count } = artist - const dispatch = useDispatch() - - const { data: supportedUsers = [] } = useSupportedUsers({ - userId: user_id, - pageSize: MAX_ARTIST_HOVER_TOP_SUPPORTING - }) - - const handleClick = useCallback(() => { - /** - * It's possible that we are already in the supporting - * user list modal, and that we are hovering over one - * of the users. - * Clicking on the supporting section is supposed to - * load a new user list modal that shows the users who - * are being supported by the user represented by the - * artist card. - */ - dispatch(reset(SUPPORTING_TAG)) - dispatch( - setUsers({ - userListType: UserListType.SUPPORTING, - entityType: UserListEntityType.USER, - id: user_id - }) - ) - dispatch(loadMore(SUPPORTING_TAG)) - // Wait until event bubbling finishes so that any modals are already dismissed - // Without this, the user list won't be visible if the popover is from an existing user list - setTimeout(() => { - dispatch(setVisibility(true)) - }, 0) - - // Used to dismiss popovers etc - if (onNavigateAway) { - onNavigateAway() - } - }, [dispatch, user_id, onNavigateAway]) - - return supportedUsers.length > 0 ? ( -
-
- - {messages.supporting} -
-
- supportedUser.receiver)} - disableProfileClick - disablePopover - profilePictureClassname={styles.profilePictureWrapper} - /> -
- ) : supporting_count > 0 ? ( -
- ) : null -} diff --git a/packages/web/src/components/audio-transaction-icon/AudioTransactionIcon.tsx b/packages/web/src/components/audio-transaction-icon/AudioTransactionIcon.tsx index 4050ff32e07..0e93acbb823 100644 --- a/packages/web/src/components/audio-transaction-icon/AudioTransactionIcon.tsx +++ b/packages/web/src/components/audio-transaction-icon/AudioTransactionIcon.tsx @@ -2,7 +2,6 @@ import React, { ReactNode } from 'react' import { TransactionType, TransactionMethod } from '@audius/common/store' import { - IconTipping as IconTip, IconReceive as IconReceiveMini, IconSend as IconSendMini, IconTransaction, @@ -30,7 +29,6 @@ type IconProps = { const typeIconSvgMap: Record = { [TransactionType.CHALLENGE_REWARD]: IconTrophy, [TransactionType.PURCHASE]: null, // Not needed, AppLogo is used for purchases - [TransactionType.TIP]: IconTip, [TransactionType.TRANSFER]: IconTransaction, [TransactionType.TRENDING_REWARD]: IconTrophy } as const @@ -55,7 +53,6 @@ const typeIconMap: Record< > = { [TransactionType.CHALLENGE_REWARD]: TypeIcon, [TransactionType.PURCHASE]: AppLogo, - [TransactionType.TIP]: TypeIcon, [TransactionType.TRANSFER]: TypeIcon, [TransactionType.TRENDING_REWARD]: TypeIcon } as const diff --git a/packages/web/src/components/audio-transactions-table/AudioTransactionsTable.tsx b/packages/web/src/components/audio-transactions-table/AudioTransactionsTable.tsx index 9a5eca80a7a..bea6b12b210 100644 --- a/packages/web/src/components/audio-transactions-table/AudioTransactionsTable.tsx +++ b/packages/web/src/components/audio-transactions-table/AudioTransactionsTable.tsx @@ -22,7 +22,6 @@ const transactionTypeLabelMap: Record = { [TransactionType.TRANSFER]: '$AUDIO', [TransactionType.CHALLENGE_REWARD]: '$AUDIO Reward Earned', [TransactionType.TRENDING_REWARD]: 'Trending Competition Award', - [TransactionType.TIP]: 'Tip', [TransactionType.PURCHASE]: 'Purchased $AUDIO' } @@ -76,9 +75,7 @@ const renderTransactionTypeCell = (cellInfo: TransactionCell) => { const methodText = transactionMethodLabelMap[method as TransactionMethod] ?? '' - const isTransferType = - transactionType === TransactionType.TIP || - transactionType === TransactionType.TRANSFER + const isTransferType = transactionType === TransactionType.TRANSFER return ( <>
diff --git a/packages/web/src/components/comments/CommentBadge.tsx b/packages/web/src/components/comments/CommentBadge.tsx index a54d975f4d8..6e23b255aa4 100644 --- a/packages/web/src/components/comments/CommentBadge.tsx +++ b/packages/web/src/components/comments/CommentBadge.tsx @@ -1,4 +1,3 @@ -import { useSupporter } from '@audius/common/api' import { useCurrentCommentSection } from '@audius/common/context' import { useIsCoinMember } from '@audius/common/hooks' import { ID } from '@audius/common/models' @@ -7,23 +6,17 @@ import { IconArtistCoin, IconComponent, IconStar, - IconTipping, - IconTrophy, Text } from '@audius/harmony' -type BadgeType = 'artist' | 'topSupporter' | 'tipSupporter' | 'coinMember' +type BadgeType = 'artist' | 'coinMember' const iconMap: Record = { artist: IconStar, - topSupporter: IconTrophy, - tipSupporter: IconTipping, coinMember: IconArtistCoin } const messages: Record = { artist: 'Artist', - topSupporter: 'Top Supporter', - tipSupporter: 'Tip Supporter', coinMember: 'Coin Member' } @@ -37,27 +30,9 @@ export const CommentBadge = ({ isArtist }: CommentBadgeProps) => { const { artistId } = useCurrentCommentSection() - const { data: supporter } = useSupporter( - { - userId: artistId, - supporterUserId: commentUserId - }, - // Read only, relying on prefetch in commentsContext - { enabled: false } - ) const { isCoinHolder } = useIsCoinMember(commentUserId, artistId) - const isTopSupporter = supporter?.rank === 1 - - const badgeType = isArtist - ? 'artist' - : isCoinHolder - ? 'coinMember' - : isTopSupporter - ? 'topSupporter' - : supporter - ? 'tipSupporter' - : null + const badgeType = isArtist ? 'artist' : isCoinHolder ? 'coinMember' : null if (badgeType === null) return null diff --git a/packages/web/src/components/edit/fields/download-availability/DownloadAvailability.tsx b/packages/web/src/components/edit/fields/download-availability/DownloadAvailability.tsx index 61bc8d0ff85..ebddfd2378a 100644 --- a/packages/web/src/components/edit/fields/download-availability/DownloadAvailability.tsx +++ b/packages/web/src/components/edit/fields/download-availability/DownloadAvailability.tsx @@ -4,7 +4,6 @@ import { AccessConditions, DownloadTrackAvailabilityType, isContentFollowGated, - isContentTipGated, isContentUSDCPurchaseGated } from '@audius/common/models' import { Nullable } from '@audius/common/utils' @@ -62,9 +61,7 @@ export const DownloadAvailability = (props: DownloadAvailabilityProps) => { const [{ value: streamConditions }] = useTrackField>(STREAM_CONDITIONS) const isUsdcGated = isContentUSDCPurchaseGated(streamConditions) - const isSpecialAccess = - isContentFollowGated(streamConditions) || - isContentTipGated(streamConditions) + const isSpecialAccess = isContentFollowGated(streamConditions) const shouldRenderCallout = isUsdcGated || isSpecialAccess const getCalloutMessage = useCallback(() => { diff --git a/packages/web/src/components/edit/fields/helpers.ts b/packages/web/src/components/edit/fields/helpers.ts index 8991b7fe3f0..564e9d72519 100644 --- a/packages/web/src/components/edit/fields/helpers.ts +++ b/packages/web/src/components/edit/fields/helpers.ts @@ -12,7 +12,6 @@ export const getCombinedDefaultGatedConditionValues = ( ) => ({ usdc_purchase: { price: null, albumTrackPrice: null }, follow_user_id: userId, - tip_user_id: userId, token_gate: { token_mint: '', token_amount: 0 diff --git a/packages/web/src/components/edit/fields/price-and-audience/PriceAndAudienceField.tsx b/packages/web/src/components/edit/fields/price-and-audience/PriceAndAudienceField.tsx index f4664466f56..5a30c830cd1 100644 --- a/packages/web/src/components/edit/fields/price-and-audience/PriceAndAudienceField.tsx +++ b/packages/web/src/components/edit/fields/price-and-audience/PriceAndAudienceField.tsx @@ -5,11 +5,9 @@ import { useUSDCPurchaseConfig } from '@audius/common/hooks' import { priceAndAudienceMessages } from '@audius/common/messages' import { isContentFollowGated, - isContentTipGated, isContentUSDCPurchaseGated, StreamTrackAvailabilityType, FollowGatedConditions, - TipGatedConditions, USDCPurchaseConditions, AccessConditions, isContentTokenGated, @@ -204,7 +202,6 @@ export const PriceAndAudienceField = (props: PriceAndAudienceFieldProps) => { useEditAccessConfirmationModal() const isUsdcGated = isContentUSDCPurchaseGated(savedStreamConditions) - const isTipGated = isContentTipGated(savedStreamConditions) const isFollowGated = isContentFollowGated(savedStreamConditions) const isTokenGated = isContentTokenGated(savedStreamConditions) @@ -231,7 +228,7 @@ export const PriceAndAudienceField = (props: PriceAndAudienceFieldProps) => { : undefined ) } - if (isFollowGated || isTipGated) { + if (isFollowGated) { availabilityType = StreamTrackAvailabilityType.SPECIAL_ACCESS } if (isTokenGated) { @@ -243,7 +240,7 @@ export const PriceAndAudienceField = (props: PriceAndAudienceFieldProps) => { set( initialValues, SPECIAL_ACCESS_TYPE, - isTipGated ? SpecialAccessType.TIP : SpecialAccessType.FOLLOW + isFollowGated ? SpecialAccessType.FOLLOW : null ) return initialValues as AccessAndSaleFormValues }, [ @@ -258,7 +255,6 @@ export const PriceAndAudienceField = (props: PriceAndAudienceFieldProps) => { isOwnedByUser, isUsdcGated, isFollowGated, - isTipGated, isTokenGated, fieldVisibility, preview @@ -268,7 +264,6 @@ export const PriceAndAudienceField = (props: PriceAndAudienceFieldProps) => { (values: AccessAndSaleFormValues) => { const availabilityType = get(values, STREAM_AVAILABILITY_TYPE) const preview = get(values, PREVIEW) - const specialAccessType = get(values, SPECIAL_ACCESS_TYPE) const fieldVisibility = get(values, FIELD_VISIBILITY) const streamConditions = get(values, STREAM_CONDITIONS) const lastGateKeeper = get(values, LAST_GATE_KEEPER) @@ -319,15 +314,9 @@ export const PriceAndAudienceField = (props: PriceAndAudienceFieldProps) => { break } case StreamTrackAvailabilityType.SPECIAL_ACCESS: { - if (specialAccessType === SpecialAccessType.FOLLOW) { - const { follow_user_id } = streamConditions as FollowGatedConditions - setStreamConditionsValue({ follow_user_id }) - setDownloadConditionsValue({ follow_user_id }) - } else { - const { tip_user_id } = streamConditions as TipGatedConditions - setStreamConditionsValue({ tip_user_id }) - setDownloadConditionsValue({ tip_user_id }) - } + const { follow_user_id } = streamConditions as FollowGatedConditions + setStreamConditionsValue({ follow_user_id }) + setDownloadConditionsValue({ follow_user_id }) setIsStreamGated(true) setIsDownloadGated(true) setLastGateKeeper({ @@ -432,8 +421,6 @@ export const PriceAndAudienceField = (props: PriceAndAudienceFieldProps) => { } } else if (isContentFollowGated(savedStreamConditions)) { selectedValues = [specialAccessValue, messages.followersOnly] - } else if (isContentTipGated(savedStreamConditions)) { - selectedValues = [specialAccessValue, messages.supportersOnly] } else if (isContentTokenGated(savedStreamConditions)) { selectedValues = [ { @@ -479,12 +466,10 @@ export const PriceAndAudienceField = (props: PriceAndAudienceFieldProps) => { initialValues={initialValues} onSubmit={(values) => { const availabilityType = get(values, STREAM_AVAILABILITY_TYPE) - const specialAccessType = get(values, SPECIAL_ACCESS_TYPE) const usersMayLoseAccess = getUsersMayLoseAccess({ availability: availabilityType, initialStreamConditions: parentFormInitialStreamConditions, - specialAccessType: - specialAccessType === SpecialAccessType.FOLLOW ? 'follow' : 'tip' + specialAccessType: 'follow' }) if (!isUpload && usersMayLoseAccess) { diff --git a/packages/web/src/components/edit/fields/stream-availability/SpecialAccessFields.tsx b/packages/web/src/components/edit/fields/stream-availability/SpecialAccessFields.tsx index 768944bd276..ea23c1852f2 100644 --- a/packages/web/src/components/edit/fields/stream-availability/SpecialAccessFields.tsx +++ b/packages/web/src/components/edit/fields/stream-availability/SpecialAccessFields.tsx @@ -3,14 +3,7 @@ import { ChangeEvent, useCallback } from 'react' import { useCurrentUserId } from '@audius/common/api' import { AccessConditions } from '@audius/common/models' import { Nullable } from '@audius/common/utils' -import { - Hint, - IconInfo, - Radio, - RadioGroup, - Text, - Tooltip -} from '@audius/harmony' +import { Hint, IconInfo, Radio, RadioGroup, Text } from '@audius/harmony' import cn from 'classnames' import { useField } from 'formik' @@ -27,8 +20,6 @@ import styles from './SpecialAccessFields.module.css' const messages = { followersOnly: 'Available to Followers Only', - supportersOnly: 'Available to Supporters Only', - supportersInfo: 'Supporters are fans that have sent you a tip.', premiumDownloads: 'Setting your track to Special Access will remove the availability you set on your premium downloads. Don’t worry, your stems are still saved!' } @@ -59,16 +50,10 @@ export const SpecialAccessFields = (props: TrackAvailabilityFieldsProps) => { const handleChange = useCallback( (e: ChangeEvent) => { const type = e.target.value as SpecialAccessType - if (accountUserId) { - if (type === SpecialAccessType.FOLLOW) { - setStreamConditionsValue({ - follow_user_id: accountUserId - }) - } else if (type === SpecialAccessType.TIP) { - setStreamConditionsValue({ - tip_user_id: accountUserId - }) - } + if (accountUserId && type === SpecialAccessType.FOLLOW) { + setStreamConditionsValue({ + follow_user_id: accountUserId + }) } specialAccessTypeField.onChange(e) }, @@ -91,23 +76,6 @@ export const SpecialAccessFields = (props: TrackAvailabilityFieldsProps) => { /> {messages.followersOnly} - {showPremiumDownloadsMessage ? ( {messages.premiumDownloads} diff --git a/packages/web/src/components/edit/fields/types.ts b/packages/web/src/components/edit/fields/types.ts index b8efd016b1b..75d229b46e5 100644 --- a/packages/web/src/components/edit/fields/types.ts +++ b/packages/web/src/components/edit/fields/types.ts @@ -8,7 +8,6 @@ import { import { Nullable } from '@audius/common/utils' export enum SpecialAccessType { - TIP = 'tip', FOLLOW = 'follow' } diff --git a/packages/web/src/components/inbox-settings-modal/InboxSettingsModal.tsx b/packages/web/src/components/inbox-settings-modal/InboxSettingsModal.tsx index 3788954f287..7844a75df87 100644 --- a/packages/web/src/components/inbox-settings-modal/InboxSettingsModal.tsx +++ b/packages/web/src/components/inbox-settings-modal/InboxSettingsModal.tsx @@ -30,8 +30,6 @@ const messages = { error: 'Something went wrong. Please try again.', allTitle: 'Allow Messages from Everyone', followeeTitle: 'People You Follow', - tipperTitle: 'Tip Supporters', - tippedArtistsTitle: "Artists You've Tipped", followersTitle: 'Your Followers', verifiedTitle: 'Verified Users' } @@ -41,14 +39,6 @@ const options = [ title: messages.followeeTitle, value: ChatPermission.FOLLOWEES }, - { - title: messages.tipperTitle, - value: ChatPermission.TIPPERS - }, - { - title: messages.tippedArtistsTitle, - value: ChatPermission.TIPPEES - }, { title: messages.followersTitle, value: ChatPermission.FOLLOWERS diff --git a/packages/web/src/components/inbox-unavailable-modal/InboxUnavailableModal.tsx b/packages/web/src/components/inbox-unavailable-modal/InboxUnavailableModal.tsx index 1e588d7b28c..7538d4d408f 100644 --- a/packages/web/src/components/inbox-unavailable-modal/InboxUnavailableModal.tsx +++ b/packages/web/src/components/inbox-unavailable-modal/InboxUnavailableModal.tsx @@ -5,9 +5,7 @@ import { FollowSource, User } from '@audius/common/models' import { chatActions, chatSelectors, - makeChatId, ChatPermissionAction, - tippingActions, useInboxUnavailableModal, usersSocialActions } from '@audius/common/store' @@ -20,7 +18,6 @@ import { ModalFooter, IconMessageUnblock as IconUnblockMessages, IconMessageLocked, - IconTipping, Button, ModalContentText } from '@audius/harmony' @@ -31,20 +28,12 @@ import { UserLink } from 'components/link/UserLink' const { unblockUser, createChat } = chatActions const { followUser } = usersSocialActions -const { beginTip } = tippingActions const { useCanCreateChat } = chatSelectors const messages = { title: 'Inbox Unavailable', content: "You can't send messages to this person.", button: 'Learn More', - tipContent: (displayName: ReactNode) => ( - <> - {'You must send '} - {displayName} - {' a tip before you can send them messages.'} - - ), followRequired: (displayName: ReactNode) => ( <> {'You must follow '} @@ -52,7 +41,6 @@ const messages = { {' before you can send them messages.'} ), - tipButton: 'Send $AUDIO', follow: 'Follow', unblockContent: 'You cannot send messages to users you have blocked.', unblockButton: 'Unblock', @@ -75,14 +63,6 @@ const actionToContent = ({ buttonText: messages.button, buttonIcon: null } - case ChatPermissionAction.TIP: - return { - content: messages.tipContent( - user ? : messages.defaultUsername - ), - buttonText: messages.tipButton, - buttonIcon: IconTipping - } case ChatPermissionAction.FOLLOW: return { content: messages.followRequired( @@ -114,7 +94,6 @@ export const InboxUnavailableModal = () => { const { data: currentUserId } = useCurrentUserId() const { callToAction } = useCanCreateChat(userId) const hasAction = - callToAction === ChatPermissionAction.TIP || callToAction === ChatPermissionAction.FOLLOW || callToAction === ChatPermissionAction.UNBLOCK @@ -125,31 +104,7 @@ export const InboxUnavailableModal = () => { ) return } - if (callToAction === ChatPermissionAction.TIP && currentUserId) { - const chatId = makeChatId([currentUserId, userId]) - const tipSuccessActions: Action[] = [ - chatActions.goToChat({ - chatId, - presetMessage - }) - ] - if (onSuccessAction) { - tipSuccessActions.push(onSuccessAction) - } - dispatch( - beginTip({ - user, - source: 'inboxUnavailableModal', - onSuccessActions: tipSuccessActions, - onSuccessConfirmedActions: [ - chatActions.createChat({ - userIds: [userId], - skipNavigation: true - }) - ] - }) - ) - } else if (callToAction === ChatPermissionAction.FOLLOW && currentUserId) { + if (callToAction === ChatPermissionAction.FOLLOW && currentUserId) { const followSuccessActions: Action[] = [ chatActions.createChat({ userIds: [userId] @@ -177,7 +132,6 @@ export const InboxUnavailableModal = () => { } onClose() }, [ - user, userId, callToAction, currentUserId, diff --git a/packages/web/src/components/notification/Notification/AddTrackToPlaylistNotification.tsx b/packages/web/src/components/notification/Notification/AddTrackToPlaylistNotification.tsx index f65a0444978..4380fd7d74b 100644 --- a/packages/web/src/components/notification/Notification/AddTrackToPlaylistNotification.tsx +++ b/packages/web/src/components/notification/Notification/AddTrackToPlaylistNotification.tsx @@ -55,7 +55,7 @@ export const AddTrackToPlaylistNotification = ( playlist as CollectionEntity ) const analytics = make( - Name.NOTIFICATIONS_CLICK_TIP_REACTION_TWITTER_SHARE, + Name.NOTIFICATIONS_CLICK_ADD_TRACK_TO_PLAYLIST_TWITTER_SHARE, { text: shareText } ) return { shareText, analytics } diff --git a/packages/web/src/components/notification/Notification/Notification.tsx b/packages/web/src/components/notification/Notification/Notification.tsx index f27756e8377..55177237e7d 100644 --- a/packages/web/src/components/notification/Notification/Notification.tsx +++ b/packages/web/src/components/notification/Notification/Notification.tsx @@ -31,14 +31,8 @@ import { RemixCreateNotification } from './RemixCreateNotification' import { RepostNotification } from './RepostNotification' import { RepostOfRepostNotification } from './RepostOfRepostNotification' import { RequestManagerNotification } from './RequestManagerNotification' -import { SupporterDethronedNotification } from './SupporterDethronedNotification' import { TastemakerNotification } from './TastemakerNotification' import { TierChangeNotification } from './TierChangeNotification' -import { TipReactionNotification } from './TipReactionNotification' -import { TipReceivedNotification } from './TipReceivedNotification' -import { TipSentNotification } from './TipSentNotification' -import { TopSupporterNotification } from './TopSupporterNotification' -import { TopSupportingNotification } from './TopSupportingNotification' import { TrackAddedToPurchasedAlbumNotification } from './TrackAddedToPurchasedAlbumNotification' import { TrendingPlaylistNotification } from './TrendingPlaylistNotification' import { TrendingTrackNotification } from './TrendingTrackNotification' @@ -95,21 +89,6 @@ export const Notification = (props: NotificationProps) => { case NotificationType.TierChange: { return } - case NotificationType.Reaction: { - return - } - case NotificationType.TipReceive: { - return - } - case NotificationType.TipSend: { - return - } - case NotificationType.SupporterRankUp: { - return - } - case NotificationType.SupportingRankUp: { - return - } case NotificationType.TrendingPlaylist: { return } @@ -142,9 +121,6 @@ export const Notification = (props: NotificationProps) => { ) } - case NotificationType.SupporterDethroned: { - return - } case NotificationType.Comment: { return } diff --git a/packages/web/src/components/notification/Notification/SupporterDethronedNotification.tsx b/packages/web/src/components/notification/Notification/SupporterDethronedNotification.tsx deleted file mode 100644 index be90aec512d..00000000000 --- a/packages/web/src/components/notification/Notification/SupporterDethronedNotification.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { useCallback } from 'react' - -import { useUser } from '@audius/common/api' -import { Name } from '@audius/common/models' -import { SupporterDethronedNotification as SupporterDethroned } from '@audius/common/store' -import { Nullable } from '@audius/common/utils' - -import crown from 'assets/img/crown2x.png' -import { make } from 'common/store/analytics/actions' -import { XShareButton } from 'components/x-share-button/XShareButton' - -import styles from './SupporterDethronedNotification.module.css' -import { NotificationBody } from './components/NotificationBody' -import { NotificationFooter } from './components/NotificationFooter' -import { NotificationHeader } from './components/NotificationHeader' -import { NotificationTile } from './components/NotificationTile' -import { NotificationTitle } from './components/NotificationTitle' -import { ProfilePicture } from './components/ProfilePicture' -import { UserNameLink } from './components/UserNameLink' -import { useGoToProfile } from './useGoToProfile' - -type SupporterDethronedNotificationProps = { - notification: SupporterDethroned -} - -const messages = { - title: "You've Been Dethroned!", - body1: ' Dethroned You as ', - body2: "'s #1 Top Supporter! Tip to Reclaim Your Spot?", - xShare: (usurperHandle: string, supportingHandle: string) => - `I've been dethroned! ${usurperHandle} dethroned me as ${supportingHandle}'s #1 Top Supporter! $AUDIO` -} - -const Crown = () => ( -
-) - -export const SupporterDethronedNotification = ({ - notification -}: SupporterDethronedNotificationProps) => { - const { supportedUserId, timeLabel, isViewed } = notification - const { data: usurpingUser } = useUser(notification.entityId) - - const { data: supportedUser } = useUser(supportedUserId) - - const handleClick = useGoToProfile(supportedUser) - - const handleShare = useCallback( - (usurpingHandle: string, supportingHandle?: Nullable) => { - // This shouldn't happen - if (!supportingHandle) { - return null - } - const shareText = messages.xShare(usurpingHandle, supportingHandle) - return { - shareText, - analytics: make(Name.NOTIFICATIONS_CLICK_DETHRONED_TWITTER_SHARE, { - text: shareText - }) - } - }, - [] - ) - - if (!usurpingUser || !supportedUser) { - return null - } - - return ( - - }> - {messages.title} - - - - - - {messages.body1} - - {messages.body2} - - - - - - ) -} diff --git a/packages/web/src/components/notification/Notification/TipReactionNotification.module.css b/packages/web/src/components/notification/Notification/TipReactionNotification.module.css deleted file mode 100644 index e42908893e8..00000000000 --- a/packages/web/src/components/notification/Notification/TipReactionNotification.module.css +++ /dev/null @@ -1,26 +0,0 @@ -.body { - display: flex; - align-items: center; -} - -.profileLink { - font-weight: var(--harmony-font-bold) !important; - margin-right: var(--harmony-unit-1); -} - -.reactionRoot { - position: relative; -} - -.profilePicture { - position: absolute; - right: 5px; - bottom: 5px; - height: 25px; - width: 25px; -} - -.reactionTextRoot { - display: flex; - align-items: center; -} diff --git a/packages/web/src/components/notification/Notification/TipReactionNotification.tsx b/packages/web/src/components/notification/Notification/TipReactionNotification.tsx deleted file mode 100644 index 514f4171e44..00000000000 --- a/packages/web/src/components/notification/Notification/TipReactionNotification.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import { useCallback } from 'react' - -import { getReactionFromRawValue, useUser } from '@audius/common/api' -import { useUIAudio } from '@audius/common/hooks' -import { Name } from '@audius/common/models' -import { ReactionNotification } from '@audius/common/store' - -import { make } from 'common/store/analytics/actions' -import { XShareButton } from 'components/x-share-button/XShareButton' - -import styles from './TipReactionNotification.module.css' -import { AudioText } from './components/AudioText' -import { NotificationBody } from './components/NotificationBody' -import { NotificationFooter } from './components/NotificationFooter' -import { NotificationHeader } from './components/NotificationHeader' -import { NotificationTile } from './components/NotificationTile' -import { NotificationTitle } from './components/NotificationTitle' -import { ProfilePicture } from './components/ProfilePicture' -import { reactionMap } from './components/Reaction' -import { UserNameLink } from './components/UserNameLink' -import { IconTip } from './components/icons' -import { useGoToProfile } from './useGoToProfile' - -const messages = { - reacted: 'reacted', - react: 'reacted to your tip of ', - xShare: (handle: string) => - `I got a thanks from ${handle} for tipping them $AUDIO on @audius!` -} - -type TipReactionNotificationProps = { - notification: ReactionNotification -} - -export const TipReactionNotification = ( - props: TipReactionNotificationProps -) => { - const { notification } = props - const { - reactionValue, - timeLabel, - isViewed, - reactedToEntity: { amount } - } = notification - - const uiAmount = useUIAudio(amount) - - const { data: user } = useUser(notification.entityId) - const handleClick = useGoToProfile(user) - - const handleShare = useCallback((twitterHandle: string) => { - const shareText = messages.xShare(twitterHandle) - const analytics = make( - Name.NOTIFICATIONS_CLICK_TIP_REACTION_TWITTER_SHARE, - { text: shareText } - ) - return { shareText, analytics } - }, []) - - if (!user) return null - - const userLinkElement = ( - - ) - - const reactionType = getReactionFromRawValue(reactionValue) - if (!reactionType) return null - const Reaction = reactionMap[reactionType] - - return ( - - }> - - {userLinkElement} {messages.reacted} - - - -
- - -
-
-
- {userLinkElement} {messages.react} - -
-
-
- - -
- ) -} diff --git a/packages/web/src/components/notification/Notification/TipReceivedNotification.module.css b/packages/web/src/components/notification/Notification/TipReceivedNotification.module.css deleted file mode 100644 index bdc9ab966fc..00000000000 --- a/packages/web/src/components/notification/Notification/TipReceivedNotification.module.css +++ /dev/null @@ -1,23 +0,0 @@ -.body { - flex-direction: column; - align-items: unset; -} - -.bodyText { - display: flex; - align-items: center; -} - -.profilePicture { - margin-right: var(--harmony-unit-2); -} - -.sayThanks { - margin-top: var(--harmony-unit-3); - font-size: var(--harmony-font-large); - color: var(--harmony-n-400); -} - -.reactionList { - display: flex; -} diff --git a/packages/web/src/components/notification/Notification/TipReceivedNotification.tsx b/packages/web/src/components/notification/Notification/TipReceivedNotification.tsx deleted file mode 100644 index d564ba66ec2..00000000000 --- a/packages/web/src/components/notification/Notification/TipReceivedNotification.tsx +++ /dev/null @@ -1,167 +0,0 @@ -import { ComponentType, useCallback } from 'react' - -import { - getReactionFromRawValue, - reactionOrder, - ReactionTypes, - useArtistCoin, - useCurrentUserId, - useReaction, - useUser, - useWriteReaction -} from '@audius/common/api' -import { useUIAudio } from '@audius/common/hooks' -import { Name } from '@audius/common/models' -import { TipReceiveNotification } from '@audius/common/store' - -import { make } from 'common/store/analytics/actions' -import { XShareButton } from 'components/x-share-button/XShareButton' -import { env } from 'services/env' - -import styles from './TipReceivedNotification.module.css' -import { AudioText } from './components/AudioText' -import { NotificationBody } from './components/NotificationBody' -import { NotificationFooter } from './components/NotificationFooter' -import { NotificationHeader } from './components/NotificationHeader' -import { NotificationTile } from './components/NotificationTile' -import { NotificationTitle } from './components/NotificationTitle' -import { ProfilePicture } from './components/ProfilePicture' -import { reactionMap, ReactionProps } from './components/Reaction' -import { UserNameLink } from './components/UserNameLink' -import { IconTip } from './components/icons' -import { useGoToProfile } from './useGoToProfile' - -const reactionList: [ReactionTypes, ComponentType][] = - reactionOrder.map((r) => [r, reactionMap[r]]) - -const messages = { - title: 'You Received a Tip!', - sent: 'sent you a tip of', - audio: '$AUDIO', - sayThanks: 'Say Thanks With a Reaction', - reactionSent: 'Reaction Sent!', - xShare: (senderHandle: string, amount: number, price?: string) => { - const totalValue = price && amount ? Number(price) * amount : null - return `Thanks ${senderHandle} for the ${amount} $AUDIO ${totalValue ? `(~$${totalValue.toLocaleString('en-US', { maximumFractionDigits: 2 })})` : ''} tip on @audius!` - } -} - -type TipReceivedNotificationProps = { - notification: TipReceiveNotification -} - -export const TipReceivedNotification = ( - props: TipReceivedNotificationProps -) => { - const { notification } = props - const { - amount, - timeLabel, - isViewed, - tipTxSignature, - reactionValue: notificationReactionValue - } = notification - - const { data: user } = useUser(notification.entityId) - const { data: tokenPriceData } = useArtistCoin(env.WAUDIO_MINT_ADDRESS) - - const tokenPrice = tokenPriceData?.price?.toString() - - const { data: reaction } = useReaction(tipTxSignature, { - // Only fetch if we don't have a reaction in the notification - enabled: notificationReactionValue === null - }) - - // Use the reaction from the query, falling back to notification data - const reactionValue = - reaction?.reactionValue ?? - (notificationReactionValue - ? getReactionFromRawValue(notificationReactionValue) - : null) - - const { mutate: writeReaction } = useWriteReaction() - const { data: currentUserId } = useCurrentUserId() - - const handleReaction = useCallback( - (e: React.MouseEvent, reactionType: ReactionTypes) => { - e.stopPropagation() - if (!currentUserId) return - writeReaction({ - entityId: tipTxSignature, - reaction: reactionType, - userId: currentUserId - }) - }, - [tipTxSignature, writeReaction, currentUserId] - ) - - const uiAmount = useUIAudio(amount) - - const handleClick = useGoToProfile(user) - - const handleShare = useCallback( - (senderHandle: string) => { - const shareText = messages.xShare(senderHandle, uiAmount, tokenPrice) - const analytics = make( - Name.NOTIFICATIONS_CLICK_TIP_RECEIVED_TWITTER_SHARE, - { text: shareText } - ) - - return { shareText, analytics } - }, - [uiAmount, tokenPrice] - ) - - if (!user) return null - - return ( - - }> - {messages.title} - - -
- - - {' '} - {messages.sent} - -
-
- {reactionValue ? ( - <> - {' '} - {messages.reactionSent}{' '} - - ) : ( - messages.sayThanks - )} -
-
- {reactionList.map(([reactionType, Reaction]) => ( - handleReaction(e, reactionType)} - isActive={ - reactionValue // treat 0 and null equivalently here - ? reactionType === reactionValue - : undefined - } - isResponsive - /> - ))} -
-
- - -
- ) -} diff --git a/packages/web/src/components/notification/Notification/TipSentNotification.module.css b/packages/web/src/components/notification/Notification/TipSentNotification.module.css deleted file mode 100644 index 95bbd0509e4..00000000000 --- a/packages/web/src/components/notification/Notification/TipSentNotification.module.css +++ /dev/null @@ -1,8 +0,0 @@ -.body { - display: flex; - align-items: center; -} - -.profilePicture { - margin-right: var(--harmony-unit-2); -} diff --git a/packages/web/src/components/notification/Notification/TipSentNotification.tsx b/packages/web/src/components/notification/Notification/TipSentNotification.tsx deleted file mode 100644 index cf8d2e9dfa8..00000000000 --- a/packages/web/src/components/notification/Notification/TipSentNotification.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { useCallback } from 'react' - -import { useArtistCoin, useUser } from '@audius/common/api' -import { useUIAudio } from '@audius/common/hooks' -import { Name } from '@audius/common/models' -import { TipSendNotification } from '@audius/common/store' - -import { make } from 'common/store/analytics/actions' -import { XShareButton } from 'components/x-share-button/XShareButton' -import { env } from 'services/env' - -import styles from './TipSentNotification.module.css' -import { AudioText } from './components/AudioText' -import { NotificationBody } from './components/NotificationBody' -import { NotificationFooter } from './components/NotificationFooter' -import { NotificationHeader } from './components/NotificationHeader' -import { NotificationTile } from './components/NotificationTile' -import { NotificationTitle } from './components/NotificationTitle' -import { ProfilePicture } from './components/ProfilePicture' -import { UserNameLink } from './components/UserNameLink' -import { IconTip } from './components/icons' -import { useGoToProfile } from './useGoToProfile' - -const messages = { - title: 'Your Tip Was Sent!', - sent: 'You successfully sent a tip of', - to: 'to', - xShare: (senderHandle: string, uiAmount: number, price?: string) => { - const totalValue = price && uiAmount ? Number(price) * uiAmount : null - return `I just tipped ${senderHandle} ${uiAmount} $AUDIO ${totalValue ? `(~$${totalValue.toLocaleString('en-US', { maximumFractionDigits: 2 })})` : ''} on @audius` - } -} - -type TipSentNotificationProps = { - notification: TipSendNotification -} - -export const TipSentNotification = (props: TipSentNotificationProps) => { - const { notification } = props - const { amount, timeLabel, isViewed } = notification - const uiAmount = useUIAudio(amount) - const { data: tokenPriceData } = useArtistCoin(env.WAUDIO_MINT_ADDRESS) - - const tokenPrice = tokenPriceData?.price?.toString() - - const { data: user } = useUser(notification.entityId) - const handleClick = useGoToProfile(user) - - const handleShare = useCallback( - (senderHandle: string) => { - const shareText = messages.xShare(senderHandle, uiAmount, tokenPrice) - return { - shareText, - analytics: make(Name.NOTIFICATIONS_CLICK_TIP_SENT_TWITTER_SHARE, { - text: shareText - }) - } - }, - [uiAmount, tokenPrice] - ) - - if (!user) return null - - return ( - - }> - {messages.title} - - - - - {messages.sent} {messages.to}{' '} - - - - - - - ) -} diff --git a/packages/web/src/components/notification/Notification/TopSupporterNotification.tsx b/packages/web/src/components/notification/Notification/TopSupporterNotification.tsx deleted file mode 100644 index f7b9b389ece..00000000000 --- a/packages/web/src/components/notification/Notification/TopSupporterNotification.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { useCallback } from 'react' - -import { useUser } from '@audius/common/api' -import { Name } from '@audius/common/models' -import { SupporterRankUpNotification } from '@audius/common/store' -import { IconTrending } from '@audius/harmony' - -import { make } from 'common/store/analytics/actions' -import { XShareButton } from 'components/x-share-button/XShareButton' -import { env } from 'services/env' - -import styles from './TopSupporterNotification.module.css' -import { NotificationBody } from './components/NotificationBody' -import { NotificationFooter } from './components/NotificationFooter' -import { NotificationHeader } from './components/NotificationHeader' -import { NotificationTile } from './components/NotificationTile' -import { NotificationTitle } from './components/NotificationTitle' -import { ProfilePicture } from './components/ProfilePicture' -import { UserNameLink } from './components/UserNameLink' -import { IconTip } from './components/icons' -import { useGoToProfile } from './useGoToProfile' - -const messages = { - title: 'Top Supporter', - supporterChange: 'Became your', - supporter: 'Top Supporter', - xShare: (handle: string, rank: number) => - `${handle} just became my #${rank} Top Supporter on @audius $AUDIO` -} - -type TopSupporterNotificationProps = { - notification: SupporterRankUpNotification -} - -export const TopSupporterNotification = ( - props: TopSupporterNotificationProps -) => { - const { notification } = props - const { rank, timeLabel, isViewed } = notification - - const { data: user } = useUser(notification.entityId) - - const handleClick = useGoToProfile(user) - - const handleXShare = useCallback( - (twitterHandle: string) => { - const shareText = messages.xShare(twitterHandle, rank) - return { - shareText, - analytics: make( - Name.NOTIFICATIONS_CLICK_SUPPORTER_RANK_UP_TWITTER_SHARE, - { text: shareText } - ) - } - }, - [rank] - ) - - if (!user) return null - - return ( - - }> - - #{rank} {messages.title} - - - -
- - -
- - - {messages.supporterChange} #{rank} {messages.supporter} - -
- - -
- ) -} diff --git a/packages/web/src/components/notification/Notification/TopSupportingNotification.tsx b/packages/web/src/components/notification/Notification/TopSupportingNotification.tsx deleted file mode 100644 index 4381f7085e8..00000000000 --- a/packages/web/src/components/notification/Notification/TopSupportingNotification.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { useCallback } from 'react' - -import { Name } from '@audius/common/models' -import { useUser } from '@audius/common/src/api/tan-query/users/useUser' -import { SupportingRankUpNotification } from '@audius/common/store' -import { IconTrending } from '@audius/harmony' - -import { make } from 'common/store/analytics/actions' -import { XShareButton } from 'components/x-share-button/XShareButton' -import { env } from 'services/env' - -import styles from './TopSupportingNotification.module.css' -import { NotificationBody } from './components/NotificationBody' -import { NotificationFooter } from './components/NotificationFooter' -import { NotificationHeader } from './components/NotificationHeader' -import { NotificationTile } from './components/NotificationTile' -import { NotificationTitle } from './components/NotificationTitle' -import { ProfilePicture } from './components/ProfilePicture' -import { UserNameLink } from './components/UserNameLink' -import { IconTip } from './components/icons' -import { useGoToProfile } from './useGoToProfile' - -const messages = { - title: 'Top Supporter', - supporterChange: "You're now their", - supporter: 'Top Supporter', - xShare: (handle: string, rank: number) => - `I'm now ${handle}'s #${rank} Top Supporter on @audius $AUDIO` -} - -type TopSupportingNotificationProps = { - notification: SupportingRankUpNotification -} - -export const TopSupportingNotification = ( - props: TopSupportingNotificationProps -) => { - const { notification } = props - const { rank, timeLabel, isViewed } = notification - - const { data: user } = useUser(notification.entityId) - - const handleClick = useGoToProfile(user) - - const handleXShare = useCallback( - (twitterHandle: string) => { - const shareText = messages.xShare(twitterHandle, rank) - return { - shareText, - analytics: make( - Name.NOTIFICATIONS_CLICK_SUPPORTING_RANK_UP_TWITTER_SHARE, - { text: shareText } - ) - } - }, - [rank] - ) - - if (!user) return null - - return ( - - }> - - #{rank} {messages.title} - - - -
- - -
- - - {messages.supporterChange} #{rank} {messages.supporter} - -
- - -
- ) -} diff --git a/packages/web/src/components/notification/Notification/components/icons.tsx b/packages/web/src/components/notification/Notification/components/icons.tsx index f56498f1418..5bf6621df46 100644 --- a/packages/web/src/components/notification/Notification/components/icons.tsx +++ b/packages/web/src/components/notification/Notification/components/icons.tsx @@ -3,7 +3,6 @@ import { ReactNode } from 'react' import { IconAudiusLogo, useTheme, - IconTipping as IconTipBase, IconHeart, IconPlaylists as IconPlaylist, IconRemix as IconRemixBase, @@ -62,10 +61,6 @@ export const IconRemix = () => { return } -export const IconTip = () => { - return -} - export const IconAnnouncement = () => { const { spacing } = useTheme() return ( diff --git a/packages/web/src/components/tipping/tip-audio/ConfirmSendTip.tsx b/packages/web/src/components/tipping/tip-audio/ConfirmSendTip.tsx deleted file mode 100644 index 46dae6a7adb..00000000000 --- a/packages/web/src/components/tipping/tip-audio/ConfirmSendTip.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import { useCallback, useEffect, useState } from 'react' - -import { tippingSelectors, tippingActions } from '@audius/common/store' -import { IconCaretLeft, IconSend, IconCheck, Button } from '@audius/harmony' -import cn from 'classnames' -import { useDispatch, useSelector } from 'react-redux' -// eslint-disable-next-line no-restricted-imports -- TODO: migrate to @react-spring/web -import { Transition, animated } from 'react-spring/renderprops.cjs' - -import { ProfileInfo } from '../../profile-info/ProfileInfo' - -import styles from './TipAudio.module.css' -const animatedAny = animated as any -const { getSendTipData } = tippingSelectors -const { confirmSendTip, beginTip } = tippingActions - -const messages = { - sending: 'SENDING', - areYouSure: 'Are you sure? This cannot be reversed.', - confirmTip: 'Confirm Tip', - confirmAndTryAgain: 'Confirm & Try Again', - goBack: 'Go Back', - somethingWrong: 'Something’s gone wrong. Wait a little while and try again.', - maintenance: 'We’re performing some necessary one-time maintenance.', - severalMinutes: 'This may take several minutes.', - holdOn: 'Don’t close this window or refresh the page.' -} - -const ErrorMessage = () => ( -
- {messages.somethingWrong} -
-) - -const ConfirmInfo = () => ( -
- {messages.areYouSure} -
-) - -const ConvertingInfo = ({ isVisible }: { isVisible: boolean }) => ( - - {(item) => (style) => - item ? ( - -

{messages.maintenance}

-
-

{messages.severalMinutes}

-

{messages.holdOn}

-
- ) : null - } -
-) - -export const ConfirmSendTip = () => { - const dispatch = useDispatch() - const { - user: receiver, - status: sendStatus, - amount: sendAmount, - source - } = useSelector(getSendTipData) - const [isDisabled, setIsDisabled] = useState(false) - const [hasError, setHasError] = useState(false) - const [isSending, setIsSending] = useState(false) - const [isConverting, setIsConverting] = useState(false) - - useEffect(() => { - setIsDisabled(isSending || isConverting) - }, [isSending, isConverting]) - - const handleConfirmSendClick = useCallback(() => { - setHasError(false) - dispatch(confirmSendTip()) - }, [dispatch]) - - const handleGoBackClick = useCallback(() => { - if (!isDisabled) { - dispatch(beginTip({ user: receiver, source })) - } - }, [isDisabled, dispatch, receiver, source]) - - // Make the states stick so that the transitions look nice - useEffect(() => { - if (sendStatus === 'ERROR') { - setHasError(true) - setIsSending(false) - setIsConverting(false) - } else if (sendStatus === 'SENDING') { - setIsSending(true) - setIsConverting(false) - setHasError(false) - } else if (sendStatus === 'CONVERTING') { - setIsConverting(true) - setIsSending(false) - setHasError(false) - } - }, [sendStatus, setHasError, setIsSending, setIsConverting]) - - const renderSendingAudio = () => ( -
-
- - - - {messages.sending} -
-
- {sendAmount} - $AUDIO -
-
- ) - - return receiver ? ( -
- {renderSendingAudio()} - - {/* - Even though the isVisible prop is being passed in, we - only render the converting message if is converting. - This will make it so that when we are converting, the - message will be animated/faded in, but when conversion - is done (whether successful or failed), we hide the - message without fading out. This is so that the UI - does not show both the large conversion message and the - error message at the same time. - */} - {isConverting ? : null} - {hasError ? : null} - {!hasError && !isSending && !isConverting ? : null} -
- -
- {!isSending && !isConverting ? ( -
- - {messages.goBack} -
- ) : null} -
- ) : null -} diff --git a/packages/web/src/components/tipping/tip-audio/SendTip.tsx b/packages/web/src/components/tipping/tip-audio/SendTip.tsx deleted file mode 100644 index 1cad25a06b3..00000000000 --- a/packages/web/src/components/tipping/tip-audio/SendTip.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import { cloneElement, useCallback, useState } from 'react' - -import { useAudioBalance } from '@audius/common/api' -import { BadgeTier, StringAudio, StringWei } from '@audius/common/models' -import { - tippingSelectors, - tippingActions, - getTierAndNumberForBalance -} from '@audius/common/store' -import { isNullOrUndefined } from '@audius/common/utils' -import { AUDIO, AudioWei } from '@audius/fixed-decimal' -import { - IconQuestionCircle, - IconArrowRight as IconArrow, - TokenAmountInput, - TokenAmountInputChangeHandler, - Button, - Flex, - Tooltip -} from '@audius/harmony' -import cn from 'classnames' -import { useDispatch, useSelector } from 'react-redux' - -import IconNoTierBadge from 'assets/img/tokenBadgePurple16@2x.webp' -import Skeleton from 'components/skeleton/Skeleton' -import { audioTierMap } from 'components/user-badges/UserBadges' - -import { ProfileInfo } from '../../profile-info/ProfileInfo' - -import { SupporterPrompt } from './SupporterPrompt' -import styles from './TipAudio.module.css' - -const { getSendUser } = tippingSelectors -const { sendTip } = tippingActions - -const messages = { - availableToSend: 'AVAILABLE TO SEND', - sendATip: 'Send Tip', - enterAnAmount: 'Enter an amount', - insufficientBalance: 'Insufficient Balance', - tooltip: '$AUDIO held in linked wallets cannot be used for tipping', - inputLabel: 'Amount to tip', - inputPlaceholder: 'Enter an amount', - inputTokenLabel: '$AUDIO' -} - -export const SendTip = () => { - const dispatch = useDispatch() - const receiver = useSelector(getSendUser) - - const { accountBalance: audioBalanceBigInt, isLoading: isBalanceLoading } = - useAudioBalance({ - includeConnectedWallets: false - }) - - const accountBalance = audioBalanceBigInt ?? (BigInt(0) as AudioWei) - - const [tipAmount, setTipAmount] = useState('') - const [tipAmountWei, setTipAmountWei] = useState( - BigInt(0) as AudioWei - ) - - const { tier } = getTierAndNumberForBalance( - accountBalance.toString() as StringWei - ) - const audioBadge = audioTierMap[tier as BadgeTier] - - const handleTipAmountChange = useCallback( - (value, valueBigInt) => { - setTipAmount(value as StringAudio) - setTipAmountWei(valueBigInt as AudioWei) - }, - [setTipAmount, setTipAmountWei] - ) - - const handleSendClick = useCallback(() => { - dispatch(sendTip({ amount: tipAmount })) - }, [dispatch, tipAmount]) - - const isDisabled = - !tipAmount || tipAmountWei <= BigInt(0) || tipAmountWei > accountBalance - - const renderAvailableAmount = () => ( -
-
- {messages.availableToSend} - - - - - -
-
- {audioBadge ? ( - cloneElement(audioBadge, { - // @ts-ignore - height: 16, - // @ts-ignore - width: 16 - }) - ) : ( - no tier - )} - - {isBalanceLoading || isNullOrUndefined(accountBalance) ? ( - - ) : ( - AUDIO(accountBalance).toLocaleString('en-US', { - maximumFractionDigits: 0 - }) - )} - -
-
- ) - - return receiver ? ( - -
- - -
- -
- {renderAvailableAmount()} -
- - - {isDisabled && tipAmount && ( -
- {messages.insufficientBalance} -
- )} -
-
- ) : null -} diff --git a/packages/web/src/components/tipping/tip-audio/SupporterPrompt.tsx b/packages/web/src/components/tipping/tip-audio/SupporterPrompt.tsx deleted file mode 100644 index 3e3bc101154..00000000000 --- a/packages/web/src/components/tipping/tip-audio/SupporterPrompt.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { useSupporterPrompt } from '@audius/common/hooks' -import { StringKeys } from '@audius/common/services' -import { AUDIO } from '@audius/fixed-decimal' -import { IconTrophy } from '@audius/harmony' - -import { useRemoteVar } from 'hooks/useRemoteConfig' - -import styles from './TipAudio.module.css' - -const messages = { - becomeFirstSupporter: 'Send A Tip To Become Their First Supporter', - becomeTopSupporterPrefix: 'Send ', - becomeTopSupporterSuffix: ' $AUDIO To Become Top Supporter' -} - -type SupporterPromptProps = { - receiverId?: number | null -} - -export const SupporterPrompt = ({ receiverId }: SupporterPromptProps) => { - const { amountToDethrone, isFirstSupporter, isPending } = - useSupporterPrompt(receiverId) - const audioFeaturesDegradedText = useRemoteVar( - StringKeys.AUDIO_FEATURES_DEGRADED_TEXT - ) - - if (isPending) return null - - if (!audioFeaturesDegradedText && !isFirstSupporter && !amountToDethrone) - return null - - return ( -
- {!audioFeaturesDegradedText && } - - {audioFeaturesDegradedText || - (isFirstSupporter ? ( - messages.becomeFirstSupporter - ) : ( - <> - {messages.becomeTopSupporterPrefix} - - {AUDIO(amountToDethrone!).toLocaleString(undefined, { - maximumFractionDigits: 0 - })} - - {messages.becomeTopSupporterSuffix} - - ))} - -
- ) -} diff --git a/packages/web/src/components/tipping/tip-audio/TipAudio.module.css b/packages/web/src/components/tipping/tip-audio/TipAudio.module.css deleted file mode 100644 index 6e344f69933..00000000000 --- a/packages/web/src/components/tipping/tip-audio/TipAudio.module.css +++ /dev/null @@ -1,280 +0,0 @@ -.modalBody { - width: 488px; - height: 548px; - max-height: 95vh; -} -.modalContentContainer { - position: relative; - height: 100%; -} - -.modalContentContainer > div { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - display: flex; - align-items: center; -} - -.modalTitleIcon { - display: flex; - align-items: center; - margin-right: 8px; -} - -.dismissButton { - color: var(--harmony-n-400); -} - -.container { - width: 100%; - padding: 0 var(--harmony-unit-6); -} -.containerFill { - height: 100%; -} -.container > div { - margin-top: 24px; - margin-bottom: 24px; -} -.container.containerDense > div { - margin-top: 18px; - margin-bottom: 18px; -} - -.flexCenter { - display: flex; - justify-content: center; - align-items: center; -} - -.textCenter { - text-align: center; -} - -.confirmReceiver { - margin-top: 0; -} - -.topBanner { - display: flex; - align-items: center; - gap: 6px; - padding: 0 8px; - font-size: var(--harmony-font-m); - font-weight: var(--harmony-font-demi-bold); - color: var(--harmony-white); - background: linear-gradient( - 315deg, - var(--harmony-gradient-color-1) 0%, - var(--harmony-gradient-color-2) 100% - ); - border-radius: 4px; -} - -.divider { - border-bottom: 1px solid var(--harmony-n-100); -} - -.topBannerText { - padding: 8px 0; - flex: 1; - text-align: center; - line-height: 130%; -} - -.topBanner .amount { - font-weight: var(--harmony-font-bold); -} - -.amountToSend { - margin-left: 24px; - margin-right: 24px; -} - -.amountAvailableContainer { - display: flex; - justify-content: space-between; - align-items: center; - margin-left: 40px; - margin-right: 40px; - color: var(--harmony-n-400); - font-weight: var(--harmony-font-heavy); -} - -.amountAvailableText { - display: flex; - align-items: center; - font-size: var(--harmony-font-s); -} - -.amountAvailableText svg path { - fill: var(--harmony-n-400) !important; -} - -.amountAvailableInfo { - margin-left: 6px; -} - -.amountContainer { - display: flex; - align-items: center; -} - -.amountAvailable { - margin-left: 4px; - font-size: var(--harmony-font-s); - font-weight: var(--harmony-font-heavy); - color: var(--harmony-n-400); - transition: color 0.07s ease-in-out; - cursor: pointer; -} - -.buttonText { - font-size: var(--harmony-font-l) !important; -} - -.wrapperPhoto { - position: relative; - - overflow: hidden; - flex: 0 0 78px; - height: 78px; -} - -.dynamicPhoto { - height: 78px; - border-radius: 40px; - border: 1px solid var(--harmony-white); - box-shadow: 0 0 1px 0 rgba(133, 129, 153, 0.5); - - text-align: center; - background-size: cover; - background-position: center; - background-repeat: no-repeat; - background-color: var(--default-profile-picture-background); -} - -.info { - font-size: var(--harmony-font-m); - font-weight: var(--harmony-font-demi-bold); - text-align: center; - line-height: 150%; -} - -.empty { - height: 16px; -} - -.goBackContainer { - text-align: center; - cursor: pointer; -} -.goBack { - margin-left: 8px; - font-weight: var(--harmony-font-bold); - font-size: var(--harmony-font-l); - color: var(--harmony-n-400); -} -.goBackContainer path { - fill: var(--harmony-n-400); -} -.goBackContainer:hover .goBack { - color: var(--harmony-secondary); -} -.goBackContainer:hover path { - fill: var(--harmony-secondary); -} - -.disabled { - cursor: unset; -} - -.loadingSpinner { - height: 24px; - width: 24px; -} - -.loadingSpinner g path { - stroke: var(--harmony-white) !important; -} - -.modalContentHeaderTitle { - color: var(--harmony-n-400); - font-size: var(--harmony-font-s); - font-weight: var(--harmony-font-bold); - letter-spacing: 0.1em; -} - -.modalContentHeaderSubtitle { - font-size: var(--harmony-font-3xl); - font-weight: var(--harmony-font-heavy); - color: var(--harmony-n-400); - padding: 8px 0; -} - -.sendingIcon { - margin-right: 4px; -} - -.sendingIcon svg { - width: 14px; - height: 14px; -} - -.sendingIcon svg path { - fill: var(--harmony-n-400) !important; -} - -.sendAmount { - margin-right: 4px; - color: var(--harmony-neutral); -} - -.sentSuccessfullyIcon { - margin-right: 4px; -} - -.sentSuccessfullyIcon svg { - width: 14px; - height: 14px; -} - -.sentSuccessfullyIcon svg path { - fill: var(--harmony-n-400) !important; -} - -.support { - font-size: var(--harmony-font-m); - font-weight: var(--harmony-font-demi-bold); -} - -.error { - font-size: var(--harmony-font-m); - font-weight: var(--harmony-font-demi-bold); - color: var(--harmony-red); -} - -.confirmButton { - width: 252px; -} -.button:hover { - background: var(--harmony-p-200) !important; -} -.button:not(.disabled):active { - background: var(--harmony-p-300) !important; - transform: perspective(1px) scale3d(0.99, 0.99, 0.99); -} -.buttonContainer .disabled:hover { - background: var(--harmony-n-150) !important; -} - -.buttonIcon { - margin: 0 2px 0 0px !important; -} - -.iconToken path { - fill: revert-layer; -} diff --git a/packages/web/src/components/tipping/tip-audio/TipAudioButton.tsx b/packages/web/src/components/tipping/tip-audio/TipAudioButton.tsx deleted file mode 100644 index a12137ffc11..00000000000 --- a/packages/web/src/components/tipping/tip-audio/TipAudioButton.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { useProfileUser } from '@audius/common/api' -import { useIsManagedAccount } from '@audius/common/hooks' -import { tippingActions } from '@audius/common/store' -import { Button, IconTokenGold } from '@audius/harmony' -import { useDispatch } from 'react-redux' - -import { useRequiresAccountCallback } from 'hooks/useRequiresAccount' - -const { beginTip } = tippingActions - -const messages = { - tipAudio: 'Tip $AUDIO' -} - -export const TipAudioButton = () => { - const isManagedAccount = useIsManagedAccount() - const dispatch = useDispatch() - const { user: profile } = useProfileUser() - - const handleClick = useRequiresAccountCallback(() => { - dispatch(beginTip({ user: profile, source: 'profile' })) - }, [dispatch, profile]) - - if (isManagedAccount) { - return null - } - - return ( - - ) -} diff --git a/packages/web/src/components/tipping/tip-audio/TipAudioModal.tsx b/packages/web/src/components/tipping/tip-audio/TipAudioModal.tsx deleted file mode 100644 index 6dcf72262f2..00000000000 --- a/packages/web/src/components/tipping/tip-audio/TipAudioModal.tsx +++ /dev/null @@ -1,199 +0,0 @@ -import { useCallback } from 'react' - -import { useCurrentUserId } from '@audius/common/api' -import { - tippingActions, - tippingSelectors, - TippingSendStatus -} from '@audius/common/store' -import { Nullable } from '@audius/common/utils' -import { - CompletionCheck, - Modal, - ModalHeader, - ModalTitle -} from '@audius/harmony' -import { useDispatch } from 'react-redux' -// eslint-disable-next-line no-restricted-imports -- TODO: migrate to @react-spring/web -import { animated, Transition } from 'react-spring/renderprops.cjs' -import { usePrevious } from 'react-use' - -import IconGoldBadge from 'assets/img/tokenBadgeGold48@2x.webp' -import { useSelector } from 'common/hooks/useSelector' -import { useManagedAccountNotAllowedCallback } from 'hooks/useManagedAccountNotAllowedRedirect' - -import { ConfirmSendTip } from './ConfirmSendTip' -import { SendTip } from './SendTip' -import styles from './TipAudio.module.css' -import { TipSent } from './TipSent' -const animatedAny = animated as any -const { resetSend } = tippingActions -const { getSendStatus, getSendTipData } = tippingSelectors - -const messages = { - sendATip: 'Send Tip', - confirm: 'Confirm', - sending: 'Sending', - tipSent: 'Tip Sent', - holdOn: '⚠️ Hold On a Moment' -} - -const GoldBadgeIconImage = () => ( - Gold badge -) - -const titleMessagesMap: { [key in TippingSendStatus]?: string } = { - SEND: messages.sendATip, - CONFIRM: messages.confirm, - SENDING: messages.sending, - CONVERTING: messages.holdOn, - ERROR: messages.confirm, - SUCCESS: messages.tipSent -} - -const titleIconsMap: { [key in TippingSendStatus]?: Nullable } = { - SEND: , - CONFIRM: , - SENDING: , - CONVERTING: null, - ERROR: , - SUCCESS: ( - - ) -} - -const renderModalContent = (pageNumber: number) => { - switch (pageNumber) { - case 0: - return - case 1: - return - case 2: - return - default: - return null - } -} - -const statusOrder = { - SEND: 0, - CONFIRM: 1, - SENDING: 1, - CONVERTING: 1, - ERROR: 1, - SUCCESS: 2 -} - -const defaultTransitions = { - initial: { opacity: 1, transform: 'translate3d(0%, 0, 0)' }, - enter: { opacity: 1, transform: 'translate3d(0%, 0 ,0)' } -} - -const nextScreenTransition = { - ...defaultTransitions, - // Next screen enters from right - from: { opacity: 0, transform: 'translate3d(100%, 0, 0)' }, - // Current screen leaves on left - leave: { opacity: 0, transform: 'translate3d(-100%, 0, 0)' } -} - -const previousScreenTransition = { - ...defaultTransitions, - // Previous screen enters from left - from: { opacity: 0, transform: 'translate3d(-100%, 0, 0)' }, - // Current screen leaves on right - leave: { opacity: 0, transform: 'translate3d(100%, 0, 0)' } -} - -export const TipAudioModal = () => { - const dispatch = useDispatch() - const sendStatus = useSelector(getSendStatus) - const previousSendStatus = usePrevious(sendStatus) - const { user: recipient, onSuccessActions } = useSelector(getSendTipData) - const { data: currentUserId } = useCurrentUserId() - - const onClose = useCallback(() => { - // After success + close, take the user to the chat they were - // attempting to make if they were unlocking DMs by tipping. - // The saga will create the chat once the tip is confirmed - if ( - onSuccessActions && - sendStatus === 'SUCCESS' && - recipient?.user_id && - currentUserId - ) { - for (const action of onSuccessActions) { - dispatch(action) - } - } - dispatch(resetSend()) - }, [ - currentUserId, - dispatch, - onSuccessActions, - recipient?.user_id, - sendStatus - ]) - - const transitions = - !previousSendStatus || - !sendStatus || - statusOrder[sendStatus] >= statusOrder[previousSendStatus] - ? nextScreenTransition - : previousScreenTransition - - const isOpen = sendStatus !== null - - useManagedAccountNotAllowedCallback({ trigger: isOpen, callback: onClose }) - - return ( - - - - -
- - {(item) => (style) => ( - - {renderModalContent(item)} - - )} - -
-
- ) -} diff --git a/packages/web/src/components/tipping/tip-audio/TipSent.tsx b/packages/web/src/components/tipping/tip-audio/TipSent.tsx deleted file mode 100644 index 35e0ce6b553..00000000000 --- a/packages/web/src/components/tipping/tip-audio/TipSent.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import { useCallback } from 'react' - -import { useArtistCoin, useCurrentAccountUser } from '@audius/common/api' -import { Name, type SolanaWalletAddress } from '@audius/common/models' -import { tippingSelectors } from '@audius/common/store' -import { formatNumberCommas } from '@audius/common/utils' -import { IconCheck } from '@audius/harmony' -import cn from 'classnames' - -import { useSelector } from 'common/hooks/useSelector' -import { make, useRecord } from 'common/store/analytics/actions' -import { XShareButton } from 'components/x-share-button/XShareButton' -import { audiusSdk } from 'services/audius-sdk' -import { env } from 'services/env' - -import { ProfileInfo } from '../../profile-info/ProfileInfo' - -import styles from './TipAudio.module.css' -const { getSendTipData } = tippingSelectors - -const messages = { - sending: 'SENDING', - sentSuccessfully: 'SENT SUCCESSFULLY', - supportOnX: 'Share your support on X!', - xShare: (recipient: string, amount: string, price?: string) => { - const totalValue = price && amount ? Number(price) * Number(amount) : null - return `I just tipped ${recipient} ${formatNumberCommas(Number(amount))} $AUDIO ${totalValue ? `(~$${totalValue.toLocaleString('en-US', { maximumFractionDigits: 2 })})` : ''} on @audius` - } -} - -export const TipSent = () => { - const record = useRecord() - const { data: accountData } = useCurrentAccountUser({ - select: (user) => ({ - accountUserId: user?.user_id, - accountHandle: user?.handle, - accountErcWallet: user?.erc_wallet - }) - }) - const { accountHandle, accountErcWallet, accountUserId } = accountData ?? {} - const { data: tokenPriceData } = useArtistCoin(env.WAUDIO_MINT_ADDRESS) - - const tokenPrice = tokenPriceData?.price?.toString() - - if (!accountErcWallet) { - throw new Error('Failed to get account ERC wallet') - } - const sendTipData = useSelector(getSendTipData) - const { user: recipient, amount: sendAmount, source } = sendTipData - - const handleShareData = useCallback( - (xHandle: string) => { - const shareText = messages.xShare(xHandle, sendAmount, tokenPrice) - - const analytics = make(Name.TIP_AUDIO_TWITTER_SHARE, { - senderHandle: accountHandle ?? '', - recipientHandle: recipient?.handle ?? '', - amount: sendAmount, - device: 'web' as const, - source - }) - - return { shareText, analytics } - }, - [sendAmount, accountHandle, recipient?.handle, source, tokenPrice] - ) - - const recordDetailedAnalytics = useCallback(async () => { - if (accountUserId && recipient && accountErcWallet) { - try { - const sdk = await audiusSdk() - const [senderWallet, recipientWallet] = await Promise.all([ - sdk.services.claimableTokensClient.deriveUserBank({ - ethWallet: accountErcWallet, - mint: 'wAUDIO' - }), - sdk.services.claimableTokensClient.deriveUserBank({ - ethWallet: recipient.erc_wallet, - mint: 'wAUDIO' - }) - ]) - - record( - make(Name.TIP_AUDIO_TWITTER_SHARE, { - senderWallet: senderWallet.toBase58() as SolanaWalletAddress, - recipientWallet: recipientWallet.toBase58() as SolanaWalletAddress, - senderHandle: accountHandle ?? '', - recipientHandle: recipient.handle, - amount: sendAmount, - device: 'web', - source - }) - ) - } catch (error) { - console.error('Failed to derive wallet analytics:', error) - } - } - }, [ - accountUserId, - recipient, - accountErcWallet, - accountHandle, - sendAmount, - source, - record - ]) - - const renderSentAudio = () => ( -
-
- - - - {messages.sentSuccessfully} -
-
- {sendAmount} - $AUDIO -
-
- ) - - return recipient ? ( -
- {renderSentAudio()} - -
- {messages.supportOnX} -
-
- -
-
- ) : null -} diff --git a/packages/web/src/components/track/GatedContentSection.tsx b/packages/web/src/components/track/GatedContentSection.tsx index fbaf8970ef7..aa08f69dc52 100644 --- a/packages/web/src/components/track/GatedContentSection.tsx +++ b/packages/web/src/components/track/GatedContentSection.tsx @@ -6,7 +6,6 @@ import { FollowSource, ModalSource, isContentFollowGated, - isContentTipGated, isContentUSDCPurchaseGated, ID, AccessConditions, @@ -15,7 +14,6 @@ import { } from '@audius/common/models' import { usersSocialActions as socialActions, - tippingActions, usePremiumContentPurchaseModal, gatedContentSelectors, PurchaseableContentType, @@ -30,7 +28,6 @@ import { IconSparkles, Button, IconUserFollow, - IconTipping, IconArtistCoin } from '@audius/harmony' import cn from 'classnames' @@ -49,7 +46,6 @@ import { LockedStatusBadge } from '../locked-status-badge' import styles from './GiantTrackTile.module.css' -const { beginTip } = tippingActions const { getGatedContentStatusMap } = gatedContentSelectors const BUY_BUTTON_WIDTH = 250 @@ -62,7 +58,6 @@ const getMessages = (contentType: PurchaseableContentType) => ({ unlocked: 'unlocked', coinGated: 'COIN GATED', specialAccess: 'SPECIAL ACCESS', - sendTip: 'Send Tip', followArtist: 'Follow Artist', buyArtistCoin: 'Buy Artist Coin', period: '.', @@ -71,12 +66,7 @@ const getMessages = (contentType: PurchaseableContentType) => ({ unlockFollowGatedContentPrefix: 'Follow', thankYouForFollowing: 'Thank you for following', unlockedFollowGatedContentSuffix: `! This ${contentType} is now available.`, - ownTipGated: 'Users can unlock access by sending you a tip!', - unlockTipGatedContentPrefix: 'Send', - unlockTipGatedContentSuffix: 'a tip.', thankYouForSupporting: 'Thank you for supporting', - unlockingTipGatedContentSuffix: 'by sending them a tip!', - unlockedTipGatedContentSuffix: `by sending them a tip! This ${contentType} is now available.`, unlockWithPurchase: `Unlock this ${contentType} with a one-time purchase!`, ofArtistsCoin: "of the artist's coin", artistCoin: 'Artist coin', @@ -98,7 +88,6 @@ type GatedContentAccessSectionProps = { trackOwner: Nullable streamConditions: AccessConditions followee: Nullable - tippedUser: Nullable isOwner: boolean className?: string buttonClassName?: string @@ -110,7 +99,6 @@ const LockedGatedContentSection = ({ contentType, streamConditions, followee, - tippedUser, className, buttonClassName, source @@ -126,9 +114,6 @@ const LockedGatedContentSection = ({ ? streamConditions.token_gate.token_mint : '' ) - const tipSource = lockedContentModalVisibility - ? 'howToUnlockModal' - : 'howToUnlockTrackPage' const followSource = lockedContentModalVisibility ? FollowSource.HOW_TO_UNLOCK_MODAL : FollowSource.HOW_TO_UNLOCK_TRACK_PAGE @@ -198,23 +183,6 @@ const LockedGatedContentSection = ({ setLockedContentModalVisibility ]) - const handleSendTip = useRequiresAccountCallback(() => { - dispatch( - beginTip({ user: tippedUser, source: tipSource, trackId: contentId }) - ) - - if (lockedContentModalVisibility) { - setLockedContentModalVisibility(false) - } - }, [ - dispatch, - tippedUser, - tipSource, - contentId, - lockedContentModalVisibility, - setLockedContentModalVisibility - ]) - const handleFollow = useRequiresAccountCallback(() => { if (isContentFollowGated(streamConditions)) { dispatch( @@ -248,16 +216,6 @@ const LockedGatedContentSection = ({ ) } - if (isContentTipGated(streamConditions) && tippedUser) { - return ( - - {messages.unlockTipGatedContentPrefix}{' '} - {' '} - {messages.unlockTipGatedContentSuffix} - - ) - } - if (isContentTokenGated(streamConditions)) { const { token_gate } = streamConditions @@ -305,20 +263,6 @@ const LockedGatedContentSection = ({ ) } - if (isContentTipGated(streamConditions)) { - return ( - - ) - } - if (isContentTokenGated(streamConditions)) { return (
- ) - } - if (isContentUSDCPurchaseGated(streamConditions)) { return ( @@ -476,7 +407,6 @@ const UnlockedGatedContentSection = ({ contentType, streamConditions, followee, - tippedUser, isOwner, trackOwner, className @@ -503,18 +433,6 @@ const UnlockedGatedContentSection = ({ ) } - if (isContentTipGated(streamConditions) && tippedUser) { - return isOwner ? ( - messages.ownTipGated - ) : ( - <> - {messages.thankYouForSupporting}{' '} - - {messages.unlockedTipGatedContentSuffix} - - ) - } - if (isContentTokenGated(streamConditions)) { return isOwner ? ( messages.ownTokenGated @@ -636,22 +554,18 @@ export const GatedContentSection = ({ const gatedContentStatus = gatedContentStatusMap[contentId] ?? null const isFollowGated = isContentFollowGated(streamConditions) - const isTipGated = isContentTipGated(streamConditions) const isTokenGated = isContentTokenGated(streamConditions) const isUSDCPurchaseGated = isContentUSDCPurchaseGated(streamConditions) - const shouldDisplay = - isFollowGated || isTipGated || isUSDCPurchaseGated || isTokenGated + const shouldDisplay = isFollowGated || isUSDCPurchaseGated || isTokenGated const { byId: users } = useUsers( [ isFollowGated ? streamConditions.follow_user_id : null, - isTipGated ? streamConditions.tip_user_id : null, isUSDCPurchaseGated ? ownerId : null ].filter(removeNullable) ) const followee = isFollowGated ? users[streamConditions.follow_user_id] : null const trackOwner = isUSDCPurchaseGated && ownerId !== null ? users[ownerId] : null - const tippedUser = isTipGated ? users[streamConditions.tip_user_id] : null const fadeIn = { [styles.show]: !isLoading, @@ -670,7 +584,6 @@ export const GatedContentSection = ({ contentType={contentType} streamConditions={streamConditions} followee={followee} - tippedUser={tippedUser} isOwner={isOwner} className={className} trackOwner={trackOwner} @@ -688,7 +601,6 @@ export const GatedContentSection = ({ contentType={contentType} streamConditions={streamConditions} followee={followee} - tippedUser={tippedUser} isOwner={isOwner} className={className} /> @@ -704,7 +616,6 @@ export const GatedContentSection = ({ trackOwner={trackOwner} streamConditions={streamConditions} followee={followee} - tippedUser={tippedUser} isOwner={isOwner} className={cn(styles.gatedContentSectionLocked, className)} buttonClassName={buttonClassName} diff --git a/packages/web/src/components/transaction-details-modal/components/TransactionDetailsContent.tsx b/packages/web/src/components/transaction-details-modal/components/TransactionDetailsContent.tsx index 11fab283b86..a9d5ef31681 100644 --- a/packages/web/src/components/transaction-details-modal/components/TransactionDetailsContent.tsx +++ b/packages/web/src/components/transaction-details-modal/components/TransactionDetailsContent.tsx @@ -1,6 +1,5 @@ import { useEffect, useState } from 'react' -import { useUser } from '@audius/common/api' import { ChallengeRewardID, SolanaWalletAddress } from '@audius/common/models' import { TransactionType, @@ -12,8 +11,7 @@ import { formatCapitalizeString, isNullOrUndefined, makeSolanaAccountLink, - makeSolanaTransactionLink, - route + makeSolanaTransactionLink } from '@audius/common/utils' import { wAUDIO } from '@audius/fixed-decimal' import { @@ -21,23 +19,16 @@ import { IconLogoLinkByStripe as LogoStripeLink } from '@audius/harmony' import cn from 'classnames' -import { pick } from 'lodash' -import { useDispatch } from 'react-redux' -import { useSetVisibility } from 'common/hooks/useModalState' import { AudioTransactionIcon } from 'components/audio-transaction-icon' import { isChangePositive } from 'components/audio-transactions-table/AudioTransactionsTable' import LoadingSpinner from 'components/loading-spinner/LoadingSpinner' -import UserBadges from 'components/user-badges/UserBadges' import { getChallengeConfig } from 'pages/rewards-page/config' -import { push } from 'utils/navigation' import { Block, BlockContainer } from './Block' import styles from './TransactionDetailsContent.module.css' import { TransactionPurchaseMetadata } from './TransactionPurchaseMetadata' -const { profilePage } = route - const messages = { transaction: 'Transaction', method: 'Method', @@ -53,51 +44,16 @@ const messages = { transferDescription: '$AUDIO ', transferSentHeader: 'Destination Wallet', transferReceivedHeader: 'Origin Wallet', - tipDescription: 'Tip ', - tipSentHeader: 'To User', - tipReceivedHeader: 'From User', unknown: 'Unknown' } const transactionDescriptions: Record = { [TransactionType.PURCHASE]: messages.purchaseDescription, - [TransactionType.TIP]: messages.tipDescription, [TransactionType.TRANSFER]: messages.transferDescription, [TransactionType.TRENDING_REWARD]: messages.trendingRewardDescription, [TransactionType.CHALLENGE_REWARD]: messages.challengeRewardDescription } -type UserDetailsProps = { - userId: number -} - -const UserDetails = ({ userId }: UserDetailsProps) => { - const setVisibility = useSetVisibility() - const dispatch = useDispatch() - const { data: user, isPending } = useUser(userId, { - select: (user) => pick(user, 'handle', 'name') - }) - const { handle, name } = user ?? {} - return ( - <> - {isPending || !handle ? ( - - ) : ( -
{ - setVisibility('TransactionDetails')(false) - dispatch(push(profilePage(handle))) - }} - > - {name} - -
- )} - - ) -} - const dateAndMetadataBlocks = ({ transactionDetails, isValidSolanaAddress @@ -137,25 +93,6 @@ const dateAndMetadataBlocks = ({ ) } - case TransactionType.TIP: { - return ( - <> - - {transactionDetails.date} - - - - - - ) - } case TransactionType.TRANSFER: { return ( <> @@ -227,9 +164,7 @@ export const TransactionDetailsContent = ({
{transactionDescriptions[transactionDetails.transactionType] + - ([TransactionType.TIP, TransactionType.TRANSFER].includes( - transactionDetails.transactionType - ) + (transactionDetails.transactionType === TransactionType.TRANSFER ? formatCapitalizeString(transactionDetails.method) : '')} diff --git a/packages/web/src/components/user-list-modal/UserListModal.tsx b/packages/web/src/components/user-list-modal/UserListModal.tsx index 398b97aa4b7..1ea43667c43 100644 --- a/packages/web/src/components/user-list-modal/UserListModal.tsx +++ b/packages/web/src/components/user-list-modal/UserListModal.tsx @@ -8,7 +8,6 @@ import { import { Modal, Scrollbar, - IconTipping as IconTip, IconUser, IconUserGroup, IconTrophy, @@ -31,8 +30,6 @@ import { PurchasersUserList } from 'components/user-list/lists/PurchasersUserLis import { RelatedArtistsUserList } from 'components/user-list/lists/RelatedArtistsUserList' import { RemixersUserList } from 'components/user-list/lists/RemixersUserList' import { RepostsUserList } from 'components/user-list/lists/RepostsUserList' -import { SupportingUserList } from 'components/user-list/lists/SupportingUserList' -import { TopSupportersUserList } from 'components/user-list/lists/TopSupportersUserList' import { ChatBlastWithAudienceCTA } from 'pages/chat-page/components/ChatBlastWithAudienceCTA' import { getUserListType, @@ -49,8 +46,6 @@ const messages = { favorites: 'Favorites', followers: 'Followers', following: 'Following', - topSupporters: 'Top Supporters', - supporting: 'Supporting', relatedArtists: 'Related Artists', mutuals: 'Mutuals', purchasers: 'Purchasers', @@ -114,18 +109,6 @@ export const UserListModal = () => { Icon: IconTrophy, title: notificationTitle } - case UserListType.SUPPORTER: - return { - component: , - Icon: IconTrophy, - title: messages.topSupporters - } - case UserListType.SUPPORTING: - return { - component: , - Icon: IconTip, - title: messages.supporting - } case UserListType.MUTUAL_FOLLOWER: return { component: , @@ -175,15 +158,9 @@ export const UserListModal = () => { {component} - {!isChatBlastPath && - (userListType === UserListType.FOLLOWER || - userListType === UserListType.SUPPORTER) ? ( + {!isChatBlastPath && userListType === UserListType.FOLLOWER ? ( ) : null} diff --git a/packages/web/src/components/user-list/UserList.tsx b/packages/web/src/components/user-list/UserList.tsx index 5c8e91be4bc..a691a3bbb7b 100644 --- a/packages/web/src/components/user-list/UserList.tsx +++ b/packages/web/src/components/user-list/UserList.tsx @@ -45,14 +45,6 @@ type UserListProps = { * Function to load more users */ fetchNextPage?: () => void - /** - * Optional user ID to show support for (used in top supporters list) - */ - showSupportFor?: ID - /** - * Optional user ID to show support from (used in supporting list) - */ - showSupportFrom?: ID /** * Whether to show ranks (1, 2, 3, etc.) next to users */ @@ -70,8 +62,6 @@ export const UserList = ({ isFetchingNextPage, isPending, fetchNextPage, - showSupportFor, - showSupportFrom, showRank = false, renderRightContent }: UserListProps) => { @@ -89,23 +79,14 @@ export const UserList = ({ const loadedCount = data?.length ?? 0 const skeletonData = useMemo(() => { - // Determine the tag for skeleton items based on whether we're showing support info - let skeletonTag: string | undefined - if (showSupportFor) { - skeletonTag = 'TOP SUPPORTERS' - } else if (showSupportFrom) { - skeletonTag = 'SUPPORTING' - } - const skeletonCount = totalCount ? Math.min(totalCount - loadedCount, DEFAULT_SKELETON_COUNT) : DEFAULT_SKELETON_COUNT return range(skeletonCount).map((index) => ({ - key: `skeleton ${index}`, - tag: skeletonTag + key: `skeleton ${index}` })) - }, [totalCount, showSupportFor, showSupportFrom, loadedCount]) + }, [totalCount, loadedCount]) const defaultRenderRightContent = (item: T, index: number) => { const userId = getUserId(item) @@ -162,11 +143,7 @@ export const UserList = ({ {rank} )} - + {renderRightContent ? renderRightContent(item, index) @@ -176,7 +153,7 @@ export const UserList = ({ })} {showSkeletons ? skeletonData.map((skeleton) => ( - + )) : null} diff --git a/packages/web/src/components/user-list/UserListItemSkeleton.tsx b/packages/web/src/components/user-list/UserListItemSkeleton.tsx index 0d2f71bd9c8..232226e24f4 100644 --- a/packages/web/src/components/user-list/UserListItemSkeleton.tsx +++ b/packages/web/src/components/user-list/UserListItemSkeleton.tsx @@ -1,15 +1,6 @@ import { Flex, Skeleton } from '@audius/harmony' -type Props = { - /** - * Type of user list (e.g. 'SUPPORTING', 'TOP SUPPORTERS') - */ - tag?: string -} - -export const UserListItemSkeleton = ({ tag }: Props) => { - const isSupporterTile = tag && ['SUPPORTING', 'TOP SUPPORTERS'].includes(tag) - +export const UserListItemSkeleton = () => { return ( { - {isSupporterTile && ( - - - - - )} diff --git a/packages/web/src/components/user-list/lists/SupportingUserList.tsx b/packages/web/src/components/user-list/lists/SupportingUserList.tsx deleted file mode 100644 index 2e521f2351f..00000000000 --- a/packages/web/src/components/user-list/lists/SupportingUserList.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { useSupportedUsers, useUser } from '@audius/common/api' -import { supportingUserListSelectors } from '@audius/common/store' -import { useSelector } from 'react-redux' - -import { UserList } from '../UserList' - -export const SupportingUserList = () => { - const userId = useSelector(supportingUserListSelectors.getId) - - const { data: supportingCount } = useUser(userId, { - select: (user) => user.supporting_count - }) - - const { data, hasNextPage, isFetchingNextPage, fetchNextPage, isPending } = - useSupportedUsers({ userId }) - - if (!userId) return null - - return ( - supporter.receiver.user_id)} - totalCount={supportingCount} - hasNextPage={hasNextPage} - isFetchingNextPage={isFetchingNextPage} - isPending={isPending} - fetchNextPage={fetchNextPage} - showSupportFrom={userId} - /> - ) -} diff --git a/packages/web/src/components/user-list/lists/TopSupportersUserList.tsx b/packages/web/src/components/user-list/lists/TopSupportersUserList.tsx deleted file mode 100644 index 1f03714b8b5..00000000000 --- a/packages/web/src/components/user-list/lists/TopSupportersUserList.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { useSupporters, useUser } from '@audius/common/api' -import { topSupportersUserListSelectors } from '@audius/common/store' -import { useSelector } from 'react-redux' - -import { UserList } from '../UserList' - -export const TopSupportersUserList = () => { - const userId = useSelector(topSupportersUserListSelectors.getId) - - const { data: supporterCount } = useUser(userId, { - select: (user) => user.supporter_count - }) - - const { data, hasNextPage, isFetchingNextPage, fetchNextPage, isPending } = - useSupporters({ userId }) - - if (!userId) return null - - return ( - supporter.sender.user_id)} - totalCount={supporterCount} - hasNextPage={hasNextPage} - isFetchingNextPage={isFetchingNextPage} - isPending={isPending} - fetchNextPage={fetchNextPage} - showSupportFor={userId} - /> - ) -} diff --git a/packages/web/src/pages/chat-page/components/ChatBlastAudienceDisplay.tsx b/packages/web/src/pages/chat-page/components/ChatBlastAudienceDisplay.tsx index 324429ce8f4..1ae6745f56f 100644 --- a/packages/web/src/pages/chat-page/components/ChatBlastAudienceDisplay.tsx +++ b/packages/web/src/pages/chat-page/components/ChatBlastAudienceDisplay.tsx @@ -51,9 +51,6 @@ export const ChatBlastAudienceDisplay = ( case ChatBlastAudience.FOLLOWERS: userListType = UserListType.FOLLOWER break - case ChatBlastAudience.TIPPERS: - userListType = UserListType.SUPPORTER - break case ChatBlastAudience.CUSTOMERS: userListType = UserListType.PURCHASER break diff --git a/packages/web/src/pages/chat-page/components/ChatBlastModal.tsx b/packages/web/src/pages/chat-page/components/ChatBlastModal.tsx index bef107bdc7c..f4c8ac4b00d 100644 --- a/packages/web/src/pages/chat-page/components/ChatBlastModal.tsx +++ b/packages/web/src/pages/chat-page/components/ChatBlastModal.tsx @@ -44,10 +44,6 @@ const messages = { label: 'My Followers', description: 'Send a bulk message to all of your followers.' }, - supporters: { - label: 'Tip Supporters', - description: 'Send a bulk message to everyone who has tipped you.' - }, purchasers: { label: 'Past Purchasers', description: @@ -172,7 +168,6 @@ const ChatBlastsFields = () => { - @@ -230,34 +225,6 @@ const FollowersMessageField = () => { ) } -const TipSupportersMessageField = () => { - const { data: user } = useCurrentAccountUser() - const [{ value }] = useField(TARGET_AUDIENCE_FIELD) - const selected = value === ChatBlastAudience.TIPPERS - const isDisabled = user?.supporter_count === 0 - return ( - - - - - {selected ? ( - {messages.supporters.description} - ) : null} - - - ) -} - const PastPurchasersMessageField = () => { const [{ value }] = useField(TARGET_AUDIENCE_FIELD) const [ diff --git a/packages/web/src/pages/chat-page/components/ChatBlastWithAudienceCTA.tsx b/packages/web/src/pages/chat-page/components/ChatBlastWithAudienceCTA.tsx index fa93818e9a7..27df889bdec 100644 --- a/packages/web/src/pages/chat-page/components/ChatBlastWithAudienceCTA.tsx +++ b/packages/web/src/pages/chat-page/components/ChatBlastWithAudienceCTA.tsx @@ -2,11 +2,7 @@ import { useCallback } from 'react' import { useCurrentUserId } from '@audius/common/api' import { useCanSendChatBlast } from '@audius/common/hooks' -import { - chatActions, - followersUserListSelectors, - topSupportersUserListSelectors -} from '@audius/common/store' +import { chatActions, followersUserListSelectors } from '@audius/common/store' import { Box, Flex, @@ -21,18 +17,13 @@ import { useDispatch, useSelector } from 'react-redux' const { createChatBlast } = chatActions const getMessages = (audience: ChatBlastAudience) => { - switch (audience) { - case ChatBlastAudience.FOLLOWERS: - return { - title: 'Message Blast Your Followers', - description: 'Send bulk messages to your followers.' - } - case ChatBlastAudience.TIPPERS: - return { - title: 'Message Blast Your Tip Supporters', - description: 'Bulk message everyone who’s sent you a tip.' - } + if (audience === ChatBlastAudience.FOLLOWERS) { + return { + title: 'Message Blast Your Followers', + description: 'Send bulk messages to your followers.' + } } + return null } type ChatBlastWithAudienceCTAProps = { @@ -49,11 +40,7 @@ export const ChatBlastWithAudienceCTA = ( const { data: currentUserId } = useCurrentUserId() const followersUserId = useSelector(followersUserListSelectors.getId) - const supportersUserId = useSelector(topSupportersUserListSelectors.getId) - const targetUserId = - audience === ChatBlastAudience.FOLLOWERS - ? followersUserId - : supportersUserId + const targetUserId = followersUserId const isOwner = currentUserId === targetUserId diff --git a/packages/web/src/pages/chat-page/components/CreateChatUserResult.tsx b/packages/web/src/pages/chat-page/components/CreateChatUserResult.tsx index 3927f737d57..cfd95177e61 100644 --- a/packages/web/src/pages/chat-page/components/CreateChatUserResult.tsx +++ b/packages/web/src/pages/chat-page/components/CreateChatUserResult.tsx @@ -36,7 +36,6 @@ const messages = { block: 'Block Messages', unblock: 'Unblock Messages', notPermitted: 'Cannot Be Messaged', - sendTipRequired: 'Send a Tip to Message', unblockRequired: 'Blocked', followRequired: 'Follow to Message' } @@ -66,13 +65,6 @@ const renderTrigger = ( const renderCustomChip = (callToAction: ChatPermissionAction) => { switch (callToAction) { - case ChatPermissionAction.TIP: - return ( -
- - {messages.sendTipRequired} -
- ) case ChatPermissionAction.FOLLOW: return (
diff --git a/packages/web/src/pages/chat-page/components/InboxUnavailableMessage.tsx b/packages/web/src/pages/chat-page/components/InboxUnavailableMessage.tsx index eba2631bcb3..078feb28829 100644 --- a/packages/web/src/pages/chat-page/components/InboxUnavailableMessage.tsx +++ b/packages/web/src/pages/chat-page/components/InboxUnavailableMessage.tsx @@ -16,12 +16,6 @@ const messages = { can send them messages. ), - tip: (userId: ID) => ( - <> - You must send a tip before - you can send them them messages. - - ), unblock: 'You cannot send messages to users you have blocked. ', default: (userId: ID) => ( @@ -63,9 +57,6 @@ export const InboxUnavailableMessage = ({ case ChatPermissionAction.FOLLOW: content = messages.follow(userId) break - case ChatPermissionAction.TIP: - content = messages.tip(userId) - break case ChatPermissionAction.UNBLOCK: content = ( diff --git a/packages/web/src/pages/dashboard-page/components/hooks.ts b/packages/web/src/pages/dashboard-page/components/hooks.ts index 42264b53e91..aeb3f10be56 100644 --- a/packages/web/src/pages/dashboard-page/components/hooks.ts +++ b/packages/web/src/pages/dashboard-page/components/hooks.ts @@ -9,7 +9,6 @@ import { Collection, Track, isContentFollowGated, - isContentTipGated, isContentUSDCPurchaseGated } from '@audius/common/models' import { @@ -85,9 +84,7 @@ const useSegregatedTrackData = () => { ) const specialAccessTracks = tracks.filter( (data) => - data.is_stream_gated && - (isContentFollowGated(data.stream_conditions) || - isContentTipGated(data.stream_conditions)) + data.is_stream_gated && isContentFollowGated(data.stream_conditions) ) const hiddenTracks = tracks.filter((data) => !!data.is_unlisted) const premiumTracks = tracks.filter( diff --git a/packages/web/src/pages/modals/Modals.tsx b/packages/web/src/pages/modals/Modals.tsx index 8b856e639a9..bc350844e55 100644 --- a/packages/web/src/pages/modals/Modals.tsx +++ b/packages/web/src/pages/modals/Modals.tsx @@ -39,7 +39,6 @@ import { ReplaceTrackProgressModal } from 'components/replace-track-progress-mod import { ClaimAllRewardsModal } from 'components/rewards/modals/ClaimAllRewardsModal' import TopAPIModal from 'components/rewards/modals/TopAPI' import { SendTokensModal } from 'components/send-tokens-modal' -import { TipAudioModal } from 'components/tipping/tip-audio/TipAudioModal' import ConnectedMobileOverflowModal from 'components/track-overflow-modal/ConnectedMobileOverflowModal' import { TransactionDetailsModal } from 'components/transaction-details-modal' import UnfollowConfirmationModal from 'components/unfollow-confirmation-modal/UnfollowConfirmationModal' @@ -162,7 +161,6 @@ const Modals = () => { )} - ) diff --git a/packages/web/src/pages/profile-page/ProfilePage.test.tsx b/packages/web/src/pages/profile-page/ProfilePage.test.tsx index 4db98c5ebf2..b9e59fee871 100644 --- a/packages/web/src/pages/profile-page/ProfilePage.test.tsx +++ b/packages/web/src/pages/profile-page/ProfilePage.test.tsx @@ -16,8 +16,6 @@ import { mockArtistCoin } from 'test/mocks/fixtures/artistCoins' import { artistUser, nonArtistUser } from 'test/mocks/fixtures/users' import { mockUserByHandle, - mockSupportingUsers, - mockSupporterUsers, mockRelatedUsers, mockUserConnectedWallets, mockNfts, @@ -67,8 +65,6 @@ const ProfilePageWithRef = () => { export function renderProfilePage(user: any, options?: RenderOptions) { mswServer.use( mockUserByHandle(user), - mockSupportingUsers(user), - mockSupporterUsers(user), mockRelatedUsers(user), mockUserConnectedWallets(user), mockNfts(), @@ -196,10 +192,6 @@ describe('ProfilePage', () => { // TODO: test recent comments block - // TODO: supporting block - - // TODO: supporters block - // TODO: show share button }) diff --git a/packages/web/src/pages/profile-page/components/desktop/ProfileLeftNav.tsx b/packages/web/src/pages/profile-page/components/desktop/ProfileLeftNav.tsx index 0b9a82d70d3..92042afca6c 100644 --- a/packages/web/src/pages/profile-page/components/desktop/ProfileLeftNav.tsx +++ b/packages/web/src/pages/profile-page/components/desktop/ProfileLeftNav.tsx @@ -11,7 +11,6 @@ import { } from '@audius/harmony' import Input from 'components/data-entry/Input' -import { TipAudioButton } from 'components/tipping/tip-audio/TipAudioButton' import UploadChip from 'components/upload/UploadChip' import { Type } from 'pages/profile-page/components/SocialLink' import { ProfileTopTags } from 'pages/profile-page/components/desktop/ProfileTopTags' @@ -25,8 +24,6 @@ import { ProfileBio } from './ProfileBio' import { ProfileMutuals } from './ProfileMutuals' import { RecentComments } from './RecentComments' import { RelatedArtists } from './RelatedArtists' -import { SupportingList } from './SupportingList' -import { TopSupporters } from './TopSupporters' import { PROFILE_LEFT_COLUMN_WIDTH_PX } from './constants' const messages = { @@ -235,14 +232,8 @@ export const ProfileLeftNav = (props: ProfileLeftNavProps) => { /> {/* For artist coin owners, replace the tip CTA with their coin */} - {showArtistCoinCTA ? ( - - ) : !isArtistCoinLoading && !isOwner ? ( - - ) : null} + {showArtistCoinCTA ? : null} - - {isArtist ? : null} diff --git a/packages/web/src/pages/profile-page/components/desktop/SupportingList.tsx b/packages/web/src/pages/profile-page/components/desktop/SupportingList.tsx deleted file mode 100644 index 5cec5157e04..00000000000 --- a/packages/web/src/pages/profile-page/components/desktop/SupportingList.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { useCallback } from 'react' - -import { useProfileUser, useSupportedUsers } from '@audius/common/api' -import { formatCount, MAX_PROFILE_SUPPORTING_TILES } from '@audius/common/utils' -import { - IconTipping, - IconArrowRight, - PlainButton, - Skeleton, - Flex, - Box -} from '@audius/harmony' -import { useDispatch } from 'react-redux' - -import { - setUsers, - setVisibility -} from 'store/application/ui/userListModal/slice' -import { - UserListEntityType, - UserListType -} from 'store/application/ui/userListModal/types' - -import { ProfilePageNavSectionItem } from './ProfilePageNavSectionItem' -import { ProfilePageNavSectionTitle } from './ProfilePageNavSectionTitle' -import { SupportingTile } from './SupportingTile' - -const messages = { - supporting: 'Supporting', - viewAll: 'View All' -} - -const formatViewAllMessage = (count: number) => { - return `${messages.viewAll} ${formatCount(count)}` -} - -export const SupportingList = () => { - const { user: profile } = useProfileUser() - const dispatch = useDispatch() - const { data: supportedUsers = [], isLoading } = useSupportedUsers({ - userId: profile?.user_id, - pageSize: MAX_PROFILE_SUPPORTING_TILES - }) - - const handleClickSeeMore = useCallback(() => { - if (profile) { - dispatch( - setUsers({ - userListType: UserListType.SUPPORTING, - entityType: UserListEntityType.USER, - id: profile.user_id - }) - ) - dispatch(setVisibility(true)) - } - }, [profile, dispatch]) - - const shouldShowSection = profile && profile.supporting_count > 0 - - if (!shouldShowSection) return null - - return ( - - - {isLoading ? ( - - - {/* Spacer to account for the gap between the last tile and the see more button */} - - - ) : ( - <> - {supportedUsers.map((supporting) => ( - - ))} - {profile?.supporting_count && - profile.supporting_count > MAX_PROFILE_SUPPORTING_TILES ? ( - - {formatViewAllMessage(profile.supporting_count)} - - ) : null} - - )} - - ) -} diff --git a/packages/web/src/pages/profile-page/components/desktop/SupportingTile.tsx b/packages/web/src/pages/profile-page/components/desktop/SupportingTile.tsx deleted file mode 100644 index b9be98732d0..00000000000 --- a/packages/web/src/pages/profile-page/components/desktop/SupportingTile.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { useCallback } from 'react' - -import { - SquareSizes, - WidthSizes, - SupportedUserMetadata -} from '@audius/common/models' -import { Flex, IconTrophy, Paper, Text, useTheme } from '@audius/harmony' -import { useDispatch } from 'react-redux' - -import { Avatar } from 'components/avatar' -import { CoverPhotoV2 } from 'components/cover-photo/CoverPhotoV2' -import { UserLink } from 'components/link' -import { TIPPING_TOP_RANK_THRESHOLD } from 'utils/constants' -import { push } from 'utils/navigation' - -type SupportingCardProps = { - supporting: SupportedUserMetadata -} - -export const SupportingTile = ({ supporting }: SupportingCardProps) => { - const { spacing } = useTheme() - const { receiver, rank } = supporting - const dispatch = useDispatch() - const handle = receiver?.handle - const isTopRank = rank >= 1 && rank <= TIPPING_TOP_RANK_THRESHOLD - - const handleClick = useCallback(() => { - dispatch(push(`/${handle}`)) - }, [dispatch, handle]) - - return receiver ? ( - - {isTopRank ? ( - - - - - # - - - {rank} - - - - ) : null} - - - - - - ) : null -} diff --git a/packages/web/src/pages/profile-page/components/desktop/TopSupporters.tsx b/packages/web/src/pages/profile-page/components/desktop/TopSupporters.tsx deleted file mode 100644 index 1f7547fec3d..00000000000 --- a/packages/web/src/pages/profile-page/components/desktop/TopSupporters.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { useCallback } from 'react' - -import { useProfileUser, useSupporters } from '@audius/common/api' -import { MAX_PROFILE_TOP_SUPPORTERS } from '@audius/common/utils' -import { IconTrophy, Skeleton } from '@audius/harmony' -import { useDispatch } from 'react-redux' - -import { - setUsers, - setVisibility -} from 'store/application/ui/userListModal/slice' -import { - UserListEntityType, - UserListType -} from 'store/application/ui/userListModal/types' - -import { ProfilePageNavSectionItem } from './ProfilePageNavSectionItem' -import { ProfilePageNavSectionTitle } from './ProfilePageNavSectionTitle' -import { ProfilePictureListTile } from './ProfilePictureListTile' - -const messages = { - topSupporters: 'Top Supporters' -} - -export const TopSupporters = () => { - const dispatch = useDispatch() - const { user: profile } = useProfileUser() - const { data: supporters = [], isLoading } = useSupporters({ - userId: profile?.user_id, - pageSize: MAX_PROFILE_TOP_SUPPORTERS - }) - - const handleClick = useCallback(() => { - if (profile) { - dispatch( - setUsers({ - userListType: UserListType.SUPPORTER, - entityType: UserListEntityType.USER, - id: profile.user_id - }) - ) - dispatch(setVisibility(true)) - } - }, [profile, dispatch]) - - if (!profile || profile.supporter_count === 0) { - return null - } - - return ( - - - {isLoading ? ( - - ) : ( - supporter.sender)} - totalUserCount={profile.supporter_count} - limit={MAX_PROFILE_TOP_SUPPORTERS} - disableProfileClick - /> - )} - - ) -} diff --git a/packages/web/src/pages/profile-page/components/mobile/ProfileHeader.tsx b/packages/web/src/pages/profile-page/components/mobile/ProfileHeader.tsx index 44dcd28db2b..ca81e92a115 100644 --- a/packages/web/src/pages/profile-page/components/mobile/ProfileHeader.tsx +++ b/packages/web/src/pages/profile-page/components/mobile/ProfileHeader.tsx @@ -34,7 +34,6 @@ import { ArtistRecommendationsDropdown } from 'components/artist-recommendations import DynamicImage from 'components/dynamic-image/DynamicImage' import Skeleton from 'components/skeleton/Skeleton' import SubscribeButton from 'components/subscribe-button/SubscribeButton' -import { TipAudioButton } from 'components/tipping/tip-audio/TipAudioButton' import FollowsYouBadge from 'components/user-badges/FollowsYouBadge' import ProfilePageBadge from 'components/user-badges/ProfilePageBadge' import UserBadges from 'components/user-badges/UserBadges' @@ -453,13 +452,9 @@ const ProfileHeader = ({ /> {/* Artist coin buy button or tip button */} - {mode !== 'owner' && - !isArtistCoinLoading && - (artistCoin?.mint ? ( - - ) : ( - - ))} + {mode !== 'owner' && !isArtistCoinLoading && artistCoin?.mint && ( + + )}
)} {mode === 'owner' && !isEditing && } diff --git a/packages/web/src/pages/supporting-page/SupportingPage.tsx b/packages/web/src/pages/supporting-page/SupportingPage.tsx deleted file mode 100644 index b84642129a7..00000000000 --- a/packages/web/src/pages/supporting-page/SupportingPage.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { useContext, useEffect } from 'react' - -import MobilePageContainer from 'components/mobile-page-container/MobilePageContainer' -import NavContext, { LeftPreset } from 'components/nav/mobile/NavContext' -import { SupportingUserList } from 'components/user-list/lists/SupportingUserList' - -const messages = { - title: 'Supporting' -} - -const SupportingPage = () => { - const { setLeft, setCenter, setRight } = useContext(NavContext)! - - useEffect(() => { - setLeft(LeftPreset.BACK) - setCenter(messages.title) - setRight(null) - }, [setLeft, setCenter, setRight]) - - return ( - - - - ) -} - -export default SupportingPage diff --git a/packages/web/src/pages/top-supporters-page/TopSupportersPage.tsx b/packages/web/src/pages/top-supporters-page/TopSupportersPage.tsx deleted file mode 100644 index 8a2ce431871..00000000000 --- a/packages/web/src/pages/top-supporters-page/TopSupportersPage.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { useContext, useEffect } from 'react' - -import MobilePageContainer from 'components/mobile-page-container/MobilePageContainer' -import NavContext, { LeftPreset } from 'components/nav/mobile/NavContext' -import { TopSupportersUserList } from 'components/user-list/lists/TopSupportersUserList' - -const messages = { - title: 'Top Supporters' -} - -const TopSupportersPage = () => { - const { setLeft, setCenter, setRight } = useContext(NavContext)! - - useEffect(() => { - setLeft(LeftPreset.BACK) - setCenter(messages.title) - setRight(null) - }, [setLeft, setCenter, setRight]) - - return ( - - - - ) -} - -export default TopSupportersPage diff --git a/packages/web/src/store/application/ui/userListModal/sagas.ts b/packages/web/src/store/application/ui/userListModal/sagas.ts index dee3db0d4a5..9a20119eb56 100644 --- a/packages/web/src/store/application/ui/userListModal/sagas.ts +++ b/packages/web/src/store/application/ui/userListModal/sagas.ts @@ -1,8 +1,6 @@ import { FavoriteType } from '@audius/common/models' import { coinLeaderboardUserListActions, - topSupportersUserListActions as topSupporterActions, - supportingUserListActions as supportingActions, repostsUserListActions as repostActions, notificationsUserListActions as notificationActions, mutualsUserListActions, @@ -80,12 +78,6 @@ function* watchSetUsers() { case UserListType.RELATED_ARTISTS: yield put(setRelatedArtists(id)) break - case UserListType.SUPPORTER: - yield put(topSupporterActions.setTopSupporters(id)) - break - case UserListType.SUPPORTING: - yield put(supportingActions.setSupporting(id)) - break case UserListType.REMIXER: yield put(remixersUserListActions.setRemixers(id)) break diff --git a/packages/web/src/store/application/ui/userListModal/types.ts b/packages/web/src/store/application/ui/userListModal/types.ts index 49922f09088..cc5c5c18918 100644 --- a/packages/web/src/store/application/ui/userListModal/types.ts +++ b/packages/web/src/store/application/ui/userListModal/types.ts @@ -5,8 +5,6 @@ export enum UserListType { FOLLOWING = 'FOLLOWING', MUTUAL_FOLLOWER = 'MUTUAL_FOLLOWER', NOTIFICATION = 'NOTIFICATION', - SUPPORTER = 'SUPPORTER', - SUPPORTING = 'SUPPORTING', RELATED_ARTISTS = 'RELATED_ARTISTS', PURCHASER = 'PURCHASER', REMIXER = 'REMIXER', diff --git a/packages/web/src/store/sagas.ts b/packages/web/src/store/sagas.ts index af040671c02..d6ca3eeb2e7 100644 --- a/packages/web/src/store/sagas.ts +++ b/packages/web/src/store/sagas.ts @@ -52,7 +52,6 @@ import recoveryEmailSagas from 'common/store/recovery-email/sagas' import savedCollectionsSagas from 'common/store/saved-collections/sagas' import searchAiBarSagas from 'common/store/search-ai-bar/sagas' import socialSagas from 'common/store/social/sagas' -import tippingSagas from 'common/store/tipping/sagas' import uploadSagas from 'common/store/upload/sagas' import firstUploadModalSagas from 'components/first-upload-modal/store/sagas' import passwordResetSagas from 'components/password-reset/store/sagas' @@ -155,9 +154,6 @@ export default function* rootSaga() { // Remote config remoteConfigSagas(), - // Tipping - tippingSagas(), - // Gated content gatedContentSagas(), buyUSDCSagas(), diff --git a/packages/web/src/test/msw/mswMocks.ts b/packages/web/src/test/msw/mswMocks.ts index ee8c67720cd..c3330b6351d 100644 --- a/packages/web/src/test/msw/mswMocks.ts +++ b/packages/web/src/test/msw/mswMocks.ts @@ -34,22 +34,6 @@ export const mockUserByHandle = (user: typeof artistUser) => HttpResponse.json({ data: [user] }) ) -export const mockSupportingUsers = ( - user: typeof artistUser, - supportingUsers?: TestUser[] -) => - http.get(`${apiEndpoint}/v1/full/users/${user.id}/supporting`, () => - HttpResponse.json({ data: supportingUsers ?? [] }) - ) - -export const mockSupporterUsers = ( - user: typeof artistUser, - supporterUsers?: TestUser[] -) => - http.get(`${apiEndpoint}/v1/full/users/${user.id}/supporters`, () => - HttpResponse.json({ data: supporterUsers ?? [] }) - ) - export const mockRelatedUsers = ( user: typeof artistUser, relatedUsers?: TestUser[] diff --git a/packages/web/src/utils/constants.ts b/packages/web/src/utils/constants.ts index d9b55f34072..8f6ea95b32a 100644 --- a/packages/web/src/utils/constants.ts +++ b/packages/web/src/utils/constants.ts @@ -5,5 +5,4 @@ export const CLAIM_REWARD_TOAST_TIMEOUT_MILLIS = 3000 export const STATIC_EXPLORE_CONTENT_URL = 'https://download.audius.co/static-resources/explore-content.json' -export const TIPPING_TOP_RANK_THRESHOLD = 5 export const NUM_FEED_TIPPERS_DISPLAYED = 2