Skip to content

Commit

Permalink
[PAY-2719] Hidden album upload (#8191)
Browse files Browse the repository at this point in the history
  • Loading branch information
DejayJD authored Apr 23, 2024
1 parent 7793044 commit ffba9e9
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 45 deletions.
10 changes: 5 additions & 5 deletions packages/common/src/hooks/useAccessAndRemixSettings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ describe('useAccessAndRemixSettings', () => {
})
})
describe('album upload', () => {
it('should only allow usdc for album uploads', () => {
it('should allow usdc & hidden for album uploads', () => {
const actual = useAccessAndRemixSettings({
isUpload: true,
isRemix: false,
Expand All @@ -328,13 +328,13 @@ describe('useAccessAndRemixSettings', () => {
disableSpecialAccessGateFields: true,
disableCollectibleGate: true,
disableCollectibleGateFields: true,
disableHidden: true
disableHidden: false
}
expect(actual).toEqual(expected)
})
})
describe('album edit', () => {
it('public track - should disable all options', () => {
it('public track - should disable all other options', () => {
const actual = useAccessAndRemixSettings({
isUpload: false,
isRemix: false,
Expand All @@ -353,7 +353,7 @@ describe('useAccessAndRemixSettings', () => {
}
expect(actual).toEqual(expected)
})
it('usdc gated - should disable everything except original option', () => {
it('usdc gated - should only allow usdc + public', () => {
mockedUseSelector.mockImplementation(
mockUseSelector(reduxStateWithCollectibles)
)
Expand Down Expand Up @@ -393,7 +393,7 @@ describe('useAccessAndRemixSettings', () => {
disableSpecialAccessGateFields: true,
disableCollectibleGate: true,
disableCollectibleGateFields: true,
disableHidden: true // atm hidden albums are not supported so this is currently disabled
disableHidden: false
}
expect(actual).toEqual(expected)
})
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/hooks/useAccessAndRemixSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const useAccessAndRemixSettings = ({
disableCollectibleGate || (!isUpload && !isInitiallyHidden)

const disableHidden =
isAlbum || isScheduledRelease || (!isUpload && !isInitiallyUnlisted)
isScheduledRelease || (!isUpload && !isInitiallyUnlisted)

return {
disableUsdcGate,
Expand Down
31 changes: 19 additions & 12 deletions packages/common/src/schemas/upload/uploadFormSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@ const premiumMetadataSchema = z.object({
.nullable()
})

const hiddenMetadataSchema = z.object({
is_unlisted: z.optional(z.boolean()),
field_visibility: z.optional(
z.object({
mood: z.optional(z.boolean()),
tags: z.optional(z.boolean()),
genre: z.optional(z.boolean()),
share: z.optional(z.boolean()),
play_count: z.optional(z.boolean()),
remixes: z.optional(z.boolean())
})
)
})

// TODO: KJ - Need to update the schema in sdk and then import here
/**
* Creates a schema for validating tracks to be uploaded.
Expand All @@ -137,24 +151,13 @@ const createSdkSchema = () =>
.object({
ai_attribution_user_id: z.optional(z.number()).nullable(),
description: z.optional(z.string().max(1000)),
field_visibility: z.optional(
z.object({
mood: z.optional(z.boolean()),
tags: z.optional(z.boolean()),
genre: z.optional(z.boolean()),
share: z.optional(z.boolean()),
play_count: z.optional(z.boolean()),
remixes: z.optional(z.boolean())
})
),

genre: GenreSchema,
isrc: z.optional(z.string().nullable()),
is_scheduled_release: z.optional(z.boolean()),
is_unlisted: z.optional(z.boolean()),
iswc: z.optional(z.string().nullable()),
license: z.optional(z.string().nullable()),
mood: MoodSchema,

release_date: z.optional(z.string()).nullable(),
remix_of: z.optional(
z
Expand Down Expand Up @@ -190,6 +193,7 @@ const createSdkSchema = () =>
parentalWarningType: z.optional(z.string().nullable())
})
.merge(premiumMetadataSchema)
.merge(hiddenMetadataSchema)

/**
* This is not really used as it is, since we pick out the title only of it
Expand Down Expand Up @@ -263,6 +267,7 @@ export const createCollectionSchema = (collectionType: 'playlist' | 'album') =>
mood: MoodSchema,
tags: z.optional(z.string())
}),
is_unlisted: z.optional(z.boolean()),
is_album: z.literal(collectionType === 'album'),
tracks: z.array(z.object({ metadata: CollectionTrackMetadataSchema })),
ddex_release_ids: z.optional(z.record(z.string()).nullable()),
Expand All @@ -284,8 +289,10 @@ export const createCollectionSchema = (collectionType: 'playlist' | 'album') =>
})
)
.optional()
.nullable()
})
)
.merge(hiddenMetadataSchema)

/**
* Extra metadata on the collection that doesn't get validated to
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/store/cache/collections/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export const getIsCollectionEmpty = (
return Object.values(collectionTracks).length === 0
}

export const getCollecitonHasHiddenTracks = (
export const getCollectionHasHiddenTracks = (
state: CommonState,
{ id }: { id?: ID }
) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { RepostButton } from 'app/components/repost-button'
import { makeStyles } from 'app/styles'
import type { GestureResponderHandler } from 'app/types/gesture'

const { getCollecitonHasHiddenTracks, getIsCollectionEmpty } =
const { getCollectionHasHiddenTracks, getIsCollectionEmpty } =
cacheCollectionsSelectors

const getMessages = (collectionType: 'album' | 'playlist') => ({
Expand Down Expand Up @@ -94,7 +94,7 @@ export const DetailsTileActionButtons = ({
{ disabled: !collectionId || !isCollection }
)
const collectionHasHiddenTracks = useSelector((state: CommonState) =>
getCollecitonHasHiddenTracks(state, { id: collectionId })
getCollectionHasHiddenTracks(state, { id: collectionId })
)
const messages = getMessages(collection?.is_album ? 'album' : 'playlist')
const { isEnabled: isEditAlbumsEnabled } = useFeatureFlag(
Expand Down
19 changes: 14 additions & 5 deletions packages/web/src/common/store/upload/sagas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Collection,
CollectionMetadata,
FieldVisibility,
ID,
Kind,
Name,
Expand Down Expand Up @@ -33,6 +34,7 @@ import {
import { EntityManagerAction } from '@audius/sdk'
import type { ProgressCB } from '@audius/sdk/dist/services/creatorNode'
import type { TrackMetadata, UploadTrackMetadata } from '@audius/sdk/dist/utils'
import { mapValues } from 'lodash'
import { Channel, Task, buffers, channel } from 'redux-saga'
import {
all,
Expand Down Expand Up @@ -104,8 +106,17 @@ function* combineMetadata(
metadata.tags = collectionMetadata.trackDetails.tags
}

if (collectionMetadata.is_downloadable) {
metadata.is_downloadable = true
// Set download & hidden status
metadata.is_downloadable = !!collectionMetadata.is_downloadable

metadata.is_unlisted = !!collectionMetadata.is_unlisted
if (collectionMetadata.is_unlisted && collectionMetadata.field_visibility) {
// Convert any undefined values to booleans
const booleanFieldVisibility = mapValues(
collectionMetadata.field_visibility,
Boolean
) as FieldVisibility
metadata.field_visibility = booleanFieldVisibility
}

// If the tracks were added as part of a premium album, add all the necessary premium track metadata
Expand Down Expand Up @@ -779,15 +790,13 @@ export function* uploadCollection(
`${collectionMetadata.playlist_name}_${Date.now()}`,
function* () {
console.debug('Creating playlist')
// Uploaded collections are always public
const isPrivate = false
const { blockHash, blockNumber, error } = yield* call(
audiusBackendInstance.createPlaylist,
playlistId,
collectionMetadata as unknown as CollectionMetadata,
isAlbum,
trackIds,
isPrivate
!!collectionMetadata.is_unlisted
)

if (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,10 @@ export const CollectionHeader = (props: CollectionHeaderProps) => {
) : null}
<Flex direction='column' justifyContent='space-between'>
<Flex direction='column' gap='xl'>
<Flex className={cn(fadeIn)} gap='s' mt='s'>
{!isPublished ? <IconVisibilityHidden /> : null}
<Flex className={cn(fadeIn)} gap='s' mt='s' alignItems='center'>
{!isPublished ? (
<IconVisibilityHidden color='subdued' aria-label='hidden' />
) : null}
{isPremium ? <IconCart size='s' color='subdued' /> : null}
<Text
variant='label'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { EditButton } from './EditButton'
import { OverflowMenuButton } from './OverflowMenuButton'
import { PublishButton } from './PublishButton'
import { ShareButton } from './ShareButton'
import { BUTTON_COLLAPSE_WIDTHS } from './utils'
const { getCollection } = collectionPageSelectors

type OwnerActionButtonProps = {
Expand Down Expand Up @@ -35,12 +34,7 @@ export const OwnerActionButtons = (props: OwnerActionButtonProps) => {
: undefined
}
/>
{is_private ? (
<PublishButton
collectionId={collectionId}
widthToHideText={BUTTON_COLLAPSE_WIDTHS.fourth}
/>
) : null}
{is_private ? <PublishButton collectionId={collectionId} /> : null}

{!is_private ? (
<OverflowMenuButton collectionId={collectionId} isOwner />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Tooltip } from 'components/tooltip'
import { PublishConfirmationModal } from './PublishConfirmationModal'

const { getCollection } = collectionPageSelectors
const { getCollecitonHasHiddenTracks } = cacheCollectionsSelectors
const { getCollectionHasHiddenTracks } = cacheCollectionsSelectors

const messages = {
publish: 'Make Public',
Expand All @@ -33,7 +33,7 @@ export const PublishButton = (props: PublishButtonProps) => {
(state: CommonState) => getCollection(state, { id: collectionId })
) as Collection
const hasHiddenTracks = useSelector((state: CommonState) =>
getCollecitonHasHiddenTracks(state, { id: collectionId })
getCollectionHasHiddenTracks(state, { id: collectionId })
)

const [isConfirming, toggleIsConfirming] = useToggle(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,10 @@ const CollectionPage = ({

const isNftPlaylist = typeTitle === 'Audio NFT Playlist'

const isStreamGated =
metadata && 'is_stream_gated' in metadata && metadata?.is_stream_gated
const streamConditions =
metadata && 'stream_conditions' in metadata && metadata?.stream_conditions
metadata && 'stream_conditions' in metadata
? metadata?.stream_conditions
: null

const {
isEmpty,
Expand All @@ -200,8 +200,6 @@ const CollectionPage = ({
const isPlayable = !areAllTracksDeleted && numTracks > 0
const dogEarType =
(!collectionLoading &&
isStreamGated &&
streamConditions &&
getDogEarType({
streamConditions,
isUnlisted: isPrivate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ const messages = {
specialAccessSubtitle:
'Special Access tracks are only available to users who meet certain criteria, such as following the artist.',
hidden: 'Hidden',
hiddenSubtitle:
hiddenSubtitleTracks:
"Hidden tracks won't be visible to your followers. Only you will see them on your profile. Anyone who has the link will be able to listen.",
hiddenSubtitleAlbums:
'Hidden albums remain invisible to your followers, visible only to you on your profile. They can be shared and listened to via direct link.',
hiddenHint: 'Scheduled tracks are hidden by default until release.'
}

Expand Down Expand Up @@ -148,7 +150,11 @@ export const AccessAndSaleMenuFields = (props: AccesAndSaleMenuFieldsProps) => {
icon={<IconVisibilityHidden />}
label={messages.hidden}
value={StreamTrackAvailabilityType.HIDDEN}
description={messages.hiddenSubtitle}
description={
isAlbum
? messages.hiddenSubtitleAlbums
: messages.hiddenSubtitleTracks
}
disabled={disableHidden}
// isInitiallyUnlisted is undefined on create
// show hint on scheduled releases that are in create or already unlisted
Expand All @@ -157,7 +163,7 @@ export const AccessAndSaleMenuFields = (props: AccesAndSaleMenuFieldsProps) => {
? messages.hiddenHint
: ''
}
checkedContent={<HiddenAvailabilityFields />}
checkedContent={isAlbum ? null : <HiddenAvailabilityFields />}
/>
</RadioGroup>
</div>
Expand Down

0 comments on commit ffba9e9

Please sign in to comment.