Skip to content

Commit

Permalink
Update profile page to render basic info and pictures on the server side
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyle-Shanks committed Mar 22, 2024
1 parent 0c8911a commit b28c892
Show file tree
Hide file tree
Showing 16 changed files with 269 additions and 173 deletions.
7 changes: 5 additions & 2 deletions packages/web/src/components/cover-photo/CoverPhoto.module.css
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
.coverPhoto {
width: 100%;
height: 100%;
min-height: 376px;
height: 376px;
position: relative;
display: flex;
justify-content: center;
overflow: hidden;
}

.placeholder,
.photo {
position: absolute;
width: 100%;
height: 100%;
min-height: 376px;
display: flex;
background-position: center;
z-index: 0;
}

.photo {
Expand Down Expand Up @@ -47,6 +49,7 @@
.hide {
opacity: 0;
}

.show {
opacity: 1;
}
26 changes: 14 additions & 12 deletions packages/web/src/components/cover-photo/CoverPhoto.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,25 +104,27 @@ const CoverPhoto = ({
isUrl={false}
wrapperClassName={styles.photo}
imageStyle={backgroundStyle}
useBlur={shouldBlur}
usePlaceholder={false}
immediate={immediate}
useBlur={shouldBlur}
>
<div className={styles.spinner}>
{processing ? loadingElement : null}
</div>
</DynamicImage>
<div className={styles.button}>
{edit ? (
<ImageSelectionButton
imageName={messages.imageName}
hasImage={Boolean(image || updatedCoverPhoto)}
error={!!error}
onSelect={handleDrop}
source='CoverPhoto'
/>
) : null}
</div>
<ClientOnly>
<div className={styles.button}>
{edit ? (
<ImageSelectionButton
imageName={messages.imageName}
hasImage={Boolean(image || updatedCoverPhoto)}
error={!!error}
onSelect={handleDrop}
source='CoverPhoto'
/>
) : null}
</div>
</ClientOnly>
</div>
)
}
Expand Down
7 changes: 0 additions & 7 deletions packages/web/src/components/nav-banner/NavBanner.module.css
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
.wrapper {
position: relative;
width: 100%;
display: flex;
justify-content: center;
}

.background {
position: absolute;
top: 0;
Expand Down
57 changes: 31 additions & 26 deletions packages/web/src/components/nav-banner/NavBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ import { ReactElement } from 'react'

import { removeNullable } from '@audius/common/utils'
import {
Flex,
IconButton,
PopupMenu,
IconSort as SortIcon,
useTheme
} from '@audius/harmony'
import cn from 'classnames'

import { ClientOnly } from 'components/client-only/ClientOnly'

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

type NavBannerProps = {
Expand Down Expand Up @@ -52,7 +55,7 @@ const NavBanner = (props: NavBannerProps) => {
].filter(removeNullable)

return (
<div className={styles.wrapper}>
<Flex h={48} w='100%' justifyContent='center'>
<div className={styles.background} />
{!empty ? (
<div
Expand All @@ -64,36 +67,38 @@ const NavBanner = (props: NavBannerProps) => {

{isArtist && (
<div className={styles.dropdown}>
{!dropdownDisabled ? (
<PopupMenu
items={menuItems}
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
renderTrigger={(ref, triggerPopup) => (
<IconButton
aria-label='open'
ref={ref}
css={{
borderRadius: cornerRadius.s,
backgroundColor: color.background.white,
'&:hover': {
backgroundColor: color.secondary.secondary,
path: {
fill: color.icon.staticWhite
<ClientOnly>
{!dropdownDisabled ? (
<PopupMenu
items={menuItems}
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
renderTrigger={(ref, triggerPopup) => (
<IconButton
aria-label='open'
ref={ref}
css={{
borderRadius: cornerRadius.s,
backgroundColor: color.background.white,
'&:hover': {
backgroundColor: color.secondary.secondary,
path: {
fill: color.icon.staticWhite
}
}
}
}}
icon={SortIcon}
color='subdued'
onClick={() => triggerPopup()}
/>
)}
/>
) : null}
}}
icon={SortIcon}
color='subdued'
onClick={() => triggerPopup()}
/>
)}
/>
) : null}
</ClientOnly>
</div>
)}
</div>
) : null}
</div>
</Flex>
)
}

Expand Down
21 changes: 19 additions & 2 deletions packages/web/src/components/profile-picture/ProfilePicture.jsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import { memo, useState, useEffect } from 'react'

import { imageProfilePicEmpty } from '@audius/common/assets'
import { SquareSizes } from '@audius/common/models'
import { cacheUsersSelectors } from '@audius/common/store'
import cn from 'classnames'
import PropTypes from 'prop-types'
import Lottie from 'react-lottie'
import { useSelector } from 'react-redux'

import loadingSpinner from 'assets/animations/loadingSpinner.json'
import DynamicImage from 'components/dynamic-image/DynamicImage'
import ImageSelectionButton from 'components/image-selection/ImageSelectionButton'
import { StaticImage } from 'components/static-image/StaticImage'
import { useUserProfilePicture } from 'hooks/useUserProfilePicture'
import { useSsrContext } from 'ssr/SsrContext'

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

const { getUser } = cacheUsersSelectors

const ProfilePicture = ({
editMode,
userId,
Expand All @@ -34,6 +41,8 @@ const ProfilePicture = ({
const [hasChanged, setHasChanged] = useState(false)
const [processing, setProcessing] = useState(false)
const [modalOpen, setModalOpen] = useState(false)
const user = useSelector((state) => getUser(state, { id: userId }))
const { isSsrEnabled } = useSsrContext()

useEffect(() => {
if (editMode) {
Expand All @@ -57,6 +66,8 @@ const ProfilePicture = ({
setModalOpen(false)
}

const ImageElement = isSsrEnabled ? StaticImage : DynamicImage

return (
<div
className={cn(styles.profilePictureWrapper, {
Expand All @@ -67,7 +78,13 @@ const ProfilePicture = ({
})}
>
<div className={styles.profilePictureBackground}>
<DynamicImage
<ImageElement
cid={user?.profile_picture_sizes}
size={SquareSizes.SIZE_480_BY_480}
imageUrl={
updatedProfilePicture ||
(!user?.profile_picture_sizes ? imageProfilePicEmpty : undefined)
}
usePlaceholder={false}
image={updatedProfilePicture || image}
skeletonClassName={styles.profilePictureSkeleton}
Expand All @@ -88,7 +105,7 @@ const ProfilePicture = ({
/>
</div>
)}
</DynamicImage>
</ImageElement>
{(editMode || showEdit) && (
<ImageSelectionButton
wrapperClassName={styles.imageSelectionButtonWrapper}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
background-repeat: no-repeat;
background-color: var(--default-profile-picture-background);
overflow: hidden;
width: 100%;
height: 100%;

display: flex;
align-items: center;
justify-content: center;
}

.profilePictureSkeleton {
border-radius: 50%;
}
Expand Down Expand Up @@ -85,9 +88,7 @@
}

.editMode.hasChanged:not(.modalOpen) .profilePictureBackground:hover .overlay,
.editMode.hasChanged:not(.modalOpen)
.profilePictureBackground:hover
.imageSelectionButton {
.editMode.hasChanged:not(.modalOpen) .profilePictureBackground:hover .imageSelectionButton {
opacity: 1;
pointer-events: all;
}
Expand All @@ -98,6 +99,7 @@
.loadingSkeleton :global(.ant-skeleton-header) {
padding: 0 !important;
}

.profilePictureWrapper .loadingSkeleton :global(.ant-skeleton-avatar) {
position: absolute;
top: 0;
Expand Down
15 changes: 9 additions & 6 deletions packages/web/src/components/stat-banner/StatBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
import cn from 'classnames'

import { ArtistRecommendationsPopup } from 'components/artist-recommendations/ArtistRecommendationsPopup'
import { ClientOnly } from 'components/client-only/ClientOnly'
import Stats, { StatProps } from 'components/stats/Stats'
import SubscribeButton from 'components/subscribe-button/SubscribeButton'
import { useFlag } from 'hooks/useRemoteConfig'
Expand Down Expand Up @@ -244,12 +245,14 @@ export const StatBanner = (props: StatsBannerProps) => {
onFollow={onFollow}
onUnfollow={onUnfollow}
/>
<ArtistRecommendationsPopup
anchorRef={followButtonRef}
artistId={profileId!}
isVisible={areArtistRecommendationsVisible}
onClose={onCloseArtistRecommendations!}
/>
<ClientOnly>
<ArtistRecommendationsPopup
anchorRef={followButtonRef}
artistId={profileId!}
isVisible={areArtistRecommendationsVisible}
onClose={onCloseArtistRecommendations!}
/>
</ClientOnly>
</>
</>
)
Expand Down
35 changes: 31 additions & 4 deletions packages/web/src/components/static-image/StaticImage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ComponentPropsWithoutRef } from 'react'

import { SquareSizes } from '@audius/common/models'
import { WidthSizes, SquareSizes } from '@audius/common/models'
import { Box, Flex } from '@audius/harmony'
import {
DiscoveryNodeSelector,
Expand All @@ -17,11 +17,15 @@ export type StaticImageProps = {
// Image CID
cid?: string | null
// Size of image to select
size?: SquareSizes
size?: SquareSizes | WidthSizes
// Override image url. Used for updated profile picture and things
imageUrl?: string
// Set height and width of wrapper container to 100%
fullWidth?: boolean
// Classes to apply to the wrapper
wrapperClassName?: string
// Whether or not to blur the background image
useBlur?: boolean
} & ComponentPropsWithoutRef<'img'>

const sdkConfigs = {
Expand Down Expand Up @@ -50,9 +54,11 @@ export const StaticImage = (props: StaticImageProps) => {
const {
cid,
size = SquareSizes.SIZE_1000_BY_1000,
imageUrl,
fullWidth = false,
wrapperClassName,
children,
useBlur,
...other
} = props

Expand All @@ -70,14 +76,35 @@ export const StaticImage = (props: StaticImageProps) => {
className={wrapperClassName}
css={{ overflow: 'hidden' }}
>
<img height='100%' width='100%' src={url} {...other} />
<img
css={{
height: '100%',
width: '100%',
maxWidth: '100%',
objectFit: 'cover'
}}
src={imageUrl ?? url}
{...other}
/>

{useBlur ? (
<Box
css={{
position: 'absolute',
height: '100%',
width: '100%',
backdropFilter: 'blur(25px)',
zIndex: 3
}}
/>
) : null}
{children ? (
<Flex
h='100%'
w='100%'
alignItems='center'
justifyContent='center'
css={{ zIndex: 3 }}
css={{ position: 'absolute', top: 0, left: 0, zIndex: 3 }}
>
{children}
</Flex>
Expand Down
Loading

0 comments on commit b28c892

Please sign in to comment.