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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@ import { useCallback } from 'react'

import { route } from '@audius/common/utils'
import { useLinkTo } from '@react-navigation/native'
import { ImageBackground } from 'react-native'

import { Button, Flex, IconArrowRight, Text } from '@audius/harmony-native'
import {
Avatar,
Button,
Flex,
IconArrowRight,
Text
} from '@audius/harmony-native'
import imageCoverPhotoBlank from 'app/assets/images/imageCoverPhotoBlank.jpg'
import imageProfilePicEmpty from 'app/assets/images/imageProfilePicEmpty2X.png'

const { FEED_PAGE } = route

const COVER_PHOTO_HEIGHT = 96

const messages = {
helpText: 'This Account No Longer Exists',
description: 'The account you’re looking for has been deleted.',
buttonText: 'Take Me Back To The Music'
}

Expand All @@ -20,18 +32,41 @@ export const DeactivatedProfileTombstone = () => {
}, [linkTo])

return (
<Flex column alignItems='center' ph='m' pv='xl' gap='m'>
<Text variant='body' strength='default' textAlign='center'>
{messages.helpText}
</Text>
<Button
variant='primary'
fullWidth
iconRight={IconArrowRight}
onPress={handlePress}
<Flex flex={1} column backgroundColor='white'>
<ImageBackground
source={imageCoverPhotoBlank}
style={{ height: COVER_PHOTO_HEIGHT }}
resizeMode='repeat'
/>
{/* Fills the remaining viewport so the message sits centered rather
than pinned beneath the cover photo. */}
<Flex
flex={1}
column
alignItems='center'
justifyContent='center'
gap='xl'
ph='l'
pv='2xl'
>
{messages.buttonText}
</Button>
<Avatar source={imageProfilePicEmpty} size='xxl' variant='strong' />
<Flex column alignItems='center' gap='s'>
<Text variant='heading' size='s' textAlign='center'>
{messages.helpText}
</Text>
<Text variant='body' size='l' color='subdued' textAlign='center'>
{messages.description}
</Text>
</Flex>
<Button
variant='primary'
fullWidth
iconRight={IconArrowRight}
onPress={handlePress}
>
{messages.buttonText}
</Button>
</Flex>
</Flex>
)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { route } from '@audius/common/utils'
import { Button, IconArrowRight } from '@audius/harmony'
import cn from 'classnames'
import { Button, Flex, IconArrowRight, Text } from '@audius/harmony'
import { Link } from 'react-router'

import styles from './DeactivatedProfileTombstone.module.css'

const { HOME_PAGE } = route

const messages = {
helpText: 'This Account No Longer Exists',
description: 'The account you’re looking for has been deleted.',
buttonText: 'Take Me Back To The Music'
}

Expand All @@ -18,16 +16,46 @@ export const DeactivatedProfileTombstone = ({
isMobile?: boolean
}) => {
return (
<div className={cn(styles.deactivated, { [styles.mobile]: isMobile })}>
<div className={styles.deactivatedText}>{messages.helpText}</div>
<Button
variant='primary'
fullWidth={isMobile}
asChild
iconRight={IconArrowRight}
<Flex
w='100%'
column
alignItems='center'
justifyContent='center'
p='xl'
// Fill the space below the profile header so the message reads as a
// centered empty state rather than being pinned to the top. On mobile
// web the page container is stretched to the viewport, so `flex: 1`
// claims everything below the header; on desktop the page is sized by
// its content, so fall back to a fixed minimum.
flex={isMobile ? 1 : undefined}
css={{
minHeight: isMobile ? undefined : 'clamp(240px, 32vh, 420px)',
userSelect: 'none'
}}
>
<Flex
column
alignItems='center'
gap='xl'
css={{ width: '100%', maxWidth: 400 }}
>
<Link to={HOME_PAGE}>{messages.buttonText}</Link>
</Button>
</div>
<Flex column alignItems='center' gap='s'>
<Text variant='heading' size='m' textAlign='center'>
{messages.helpText}
</Text>
<Text variant='body' size='l' color='subdued' textAlign='center'>
{messages.description}
</Text>
</Flex>
<Button
variant='primary'
fullWidth={isMobile}
asChild
iconRight={IconArrowRight}
>
<Link to={HOME_PAGE}>{messages.buttonText}</Link>
</Button>
</Flex>
</Flex>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,12 @@ const ProfilePage = ({ containerRef }: ProfilePageProps) => {
fromOpacity={1}
>
<Box ref={profileFocusRootRef} w='100%' pb='2xl'>
{/* `useCoverPhoto`/`useProfilePicture` already scrub deactivated
accounts' images and return the default placeholders, so pass the
real userId — withholding it leaves the hooks unresolved and the
images stuck on a loading skeleton. */}
<CoverPhoto
userId={isDeactivated ? null : userId}
userId={userId}
updatedCoverPhoto={updatedCoverPhoto ? updatedCoverPhoto.url : ''}
error={updatedCoverPhoto ? updatedCoverPhoto.error : false}
loading={status === Status.LOADING}
Expand Down Expand Up @@ -484,7 +488,7 @@ const ProfilePage = ({ containerRef }: ProfilePageProps) => {
>
{/* @ts-ignore */}
<ProfilePicture
userId={isDeactivated ? undefined : userId}
userId={userId}
updatedProfilePicture={
updatedProfilePicture ? updatedProfilePicture.url : ''
}
Expand Down Expand Up @@ -551,12 +555,7 @@ const ProfilePage = ({ containerRef }: ProfilePageProps) => {
<Box>
<EmptyStatBanner />
<EmptyNavBanner />
<FlushPageContainer>
<Flex flex='1 1 100%' mh='auto' columnGap={PROFILE_COLUMN_GAP}>
<LeftColumnSpacer />
{status === Status.SUCCESS && <DeactivatedProfileTombstone />}
</Flex>
</FlushPageContainer>
{status === Status.SUCCESS && <DeactivatedProfileTombstone />}
</Box>
) : (
<Mask show={editMode} zIndex={zIndex.PROFILE_EDIT_MASK}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@
flex-direction: column;
}

/**
* Deactivated profiles render no artist info below the cover photo, so the
* header must size to its content instead of growing into the space the
* tombstone claims — otherwise the two split the viewport and leave a blank
* band between the avatar and the message.
*/
.headerContainer.deactivated {
flex: none;
}

.coverPhoto {
display: flex;
flex-direction: column;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useState, useRef, useCallback, useEffect } from 'react'

import { useArtistCreatedFanClub } from '@audius/common/api'
import { imageCoverPhotoBlank } from '@audius/common/assets'
import {
imageCoverPhotoBlank,
imageProfilePicEmpty
} from '@audius/common/assets'
import {
Name,
SquareSizes,
Expand Down Expand Up @@ -277,7 +280,11 @@ const ProfileHeader = ({
}

return (
<div className={styles.headerContainer}>
<div
className={cn(styles.headerContainer, {
[styles.deactivated]: isDeactivated
})}
>
<GrowingCoverPhoto
src={updatedCoverPhoto || coverPhoto}
style={coverPhotoStyle}
Expand All @@ -297,7 +304,9 @@ const ProfileHeader = ({
</GrowingCoverPhoto>
<Image
src={
isDeactivated ? undefined : updatedProfilePicture || profilePicture
isDeactivated
? imageProfilePicEmpty
: updatedProfilePicture || profilePicture
}
alt={messages.profilePicAltText}
className={cn(styles.profilePictureWrapper, styles.profilePicture, {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
.container {
flex-direction: column;
}

/**
* Deactivated profiles have no tabs or lineups, so the page would otherwise
* end just below the header and leave the rest of the viewport blank. Stretch
* the container to the full viewport so the tombstone (flex: 1) can fill it.
*/
.deactivatedContainer {
/**
* 100% (not 100dvh) so the page stops at the bottom of the scroll area
* rather than overflowing by the height of anything stacked above it,
* e.g. the announcement banner.
*/
min-height: 100%;
}

/* Bottom Section */

.tracksLineupContainer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -433,11 +433,9 @@ const ProfilePage = ({ containerRef }: ProfilePageProps) => {
}

if (profile.is_deactivated) {
content = (
<div className={styles.contentContainer}>
<DeactivatedProfileTombstone isMobile />
</div>
)
// Rendered as a direct child of the page container (a flex column) so the
// tombstone's `flex: 1` can claim the space left below the header.
content = <DeactivatedProfileTombstone isMobile />
} else if (!isLoading && !isEditing) {
content = (
<div className={styles.contentContainer}>
Expand All @@ -463,7 +461,9 @@ const ProfilePage = ({ containerRef }: ProfilePageProps) => {
structuredData={structuredData}
entityType='user'
hashId={profile?.user_id ? Id.parse(profile.user_id) : undefined}
containerClassName={styles.container}
containerClassName={cn(styles.container, {
[styles.deactivatedContainer]: profile.is_deactivated
})}
>
<ProfileHeader
isDeactivated={profile.is_deactivated ?? false}
Expand Down
Loading