From a61f0c9a5e56ac56baa15fde9ce6dace747bc499 Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Mon, 3 Jun 2024 17:04:28 -0700 Subject: [PATCH 1/4] [C-4421] Add UserCard --- .../CollectionCardSkeleton.tsx | 64 +++++--------- .../profile-list/ProfileCardSkeleton.tsx | 51 ----------- .../components/profile-list/ProfileList.tsx | 11 ++- .../src/components/profile-list/UserCard.tsx | 85 +++++++++++++++++++ .../profile-list/UserCardSkeleton.tsx | 29 +++++++ .../components/Avatar/Avatar.tsx | 38 ++++----- .../src/harmony-native/utils/styleProps.ts | 27 ------ packages/mobile/tsconfig.json | 14 +-- 8 files changed, 159 insertions(+), 160 deletions(-) delete mode 100644 packages/mobile/src/components/profile-list/ProfileCardSkeleton.tsx create mode 100644 packages/mobile/src/components/profile-list/UserCard.tsx create mode 100644 packages/mobile/src/components/profile-list/UserCardSkeleton.tsx delete mode 100644 packages/mobile/src/harmony-native/utils/styleProps.ts diff --git a/packages/mobile/src/components/collection-list/CollectionCardSkeleton.tsx b/packages/mobile/src/components/collection-list/CollectionCardSkeleton.tsx index c5009934e65..791a2773c31 100644 --- a/packages/mobile/src/components/collection-list/CollectionCardSkeleton.tsx +++ b/packages/mobile/src/components/collection-list/CollectionCardSkeleton.tsx @@ -1,51 +1,25 @@ -import { View } from 'react-native' +import { Divider, Flex, Paper } from '@audius/harmony-native' -import { Tile } from 'app/components/core' -import { Skeleton, StaticSkeleton } from 'app/components/skeleton' -import { makeStyles } from 'app/styles' - -const useStyles = makeStyles(({ spacing }) => ({ - root: { - height: 218 - }, - cardContent: { - paddingHorizontal: spacing(2) - }, - imageContainer: { - paddingTop: spacing(2), - paddingHorizontal: spacing(1) - }, - image: { - height: 152, - width: '100%', - borderRadius: 6 - }, - textContainer: { - paddingVertical: spacing(1), - alignItems: 'center' - }, - title: { - height: 16, - width: 75, - marginVertical: spacing(1) - }, - stats: { - height: 14, - width: 150 - } -})) +import { Skeleton } from '../skeleton' export const CollectionCardSkeleton = () => { - const styles = useStyles() return ( - - - - - - - - - + + + + + + + + + + + ) } diff --git a/packages/mobile/src/components/profile-list/ProfileCardSkeleton.tsx b/packages/mobile/src/components/profile-list/ProfileCardSkeleton.tsx deleted file mode 100644 index d911e6f5b3c..00000000000 --- a/packages/mobile/src/components/profile-list/ProfileCardSkeleton.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { View } from 'react-native' - -import { Tile } from 'app/components/core' -import { Skeleton, StaticSkeleton } from 'app/components/skeleton' -import { makeStyles } from 'app/styles' - -const useStyles = makeStyles(({ spacing }) => ({ - root: { - height: 218 - }, - cardContent: { - paddingHorizontal: spacing(2) - }, - imageContainer: { - paddingTop: spacing(2), - paddingHorizontal: spacing(1) - }, - image: { - height: 152, - width: 152, - borderRadius: 152 / 2 - }, - textContainer: { - paddingVertical: spacing(1), - alignItems: 'center' - }, - title: { - height: 16, - width: 75, - marginVertical: spacing(1) - }, - stats: { - height: 14, - width: 150 - } -})) - -export const ProfileCardSkeleton = () => { - const styles = useStyles() - return ( - - - - - - - - - - ) -} diff --git a/packages/mobile/src/components/profile-list/ProfileList.tsx b/packages/mobile/src/components/profile-list/ProfileList.tsx index 2b9ab826ecf..9611370fd91 100644 --- a/packages/mobile/src/components/profile-list/ProfileList.tsx +++ b/packages/mobile/src/components/profile-list/ProfileList.tsx @@ -3,8 +3,8 @@ import type { ID, User } from '@audius/common/models' import type { CardListProps } from 'app/components/core' import { CardList } from 'app/components/core' -import { ProfileCard } from './ProfileCard' -import { ProfileCardSkeleton } from './ProfileCardSkeleton' +import { UserCard } from './UserCard' +import { UserCardSkeleton } from './UserCardSkeleton' type ListProps = Omit, 'data'> @@ -19,9 +19,12 @@ export const ProfileList = (props: ProfileListProps) => { ( - + onCardPress?.(item.user_id)} + /> )} - LoadingCardComponent={ProfileCardSkeleton} + LoadingCardComponent={UserCardSkeleton} {...other} /> ) diff --git a/packages/mobile/src/components/profile-list/UserCard.tsx b/packages/mobile/src/components/profile-list/UserCard.tsx new file mode 100644 index 00000000000..9eaeb59bb0a --- /dev/null +++ b/packages/mobile/src/components/profile-list/UserCard.tsx @@ -0,0 +1,85 @@ +import { useCallback } from 'react' + +import { SquareSizes, type ID } from '@audius/common/models' +import { cacheUsersSelectors } from '@audius/common/store' +import { formatCount } from '@audius/common/utils' +import type { GestureResponderEvent } from 'react-native' +import { useSelector } from 'react-redux' + +import { + Avatar, + Divider, + Flex, + Paper, + Text, + type PaperProps +} from '@audius/harmony-native' +import { useNavigation } from 'app/hooks/useNavigation' + +import { useProfilePicture } from '../image/UserImage' +import { UserLink } from '../user-link' + +const { getUser } = cacheUsersSelectors + +const messages = { + followers: (count: number) => (count === 1 ? 'Follower' : 'Followers') +} + +type UserCardProps = PaperProps & { + userId: ID + noNavigation?: boolean +} +export const UserCard = (props: UserCardProps) => { + const { userId, onPress, noNavigation, ...other } = props + + const user = useSelector((state) => getUser(state, { id: userId })) + const navigation = useNavigation() + + const handlePress = useCallback( + (e: GestureResponderEvent) => { + onPress?.(e) + if (noNavigation) return + navigation.navigate('Profile', { id: userId }) + }, + [onPress, noNavigation, navigation, userId] + ) + + const { source, handleError } = useProfilePicture( + userId, + SquareSizes.SIZE_480_BY_480 + ) + + if (user === null) return null + + const { handle, follower_count } = user + + return ( + + + + + + @{handle} + + + + + + {formatCount(follower_count)} {messages.followers(follower_count)} + + + + ) +} diff --git a/packages/mobile/src/components/profile-list/UserCardSkeleton.tsx b/packages/mobile/src/components/profile-list/UserCardSkeleton.tsx new file mode 100644 index 00000000000..7651c1c6495 --- /dev/null +++ b/packages/mobile/src/components/profile-list/UserCardSkeleton.tsx @@ -0,0 +1,29 @@ +import { Box, Divider, Flex, Paper } from '@audius/harmony-native' + +import { Skeleton } from '../skeleton' + +export const UserCardSkeleton = () => { + return ( + + + + + + + + + + + + + + ) +} diff --git a/packages/mobile/src/harmony-native/components/Avatar/Avatar.tsx b/packages/mobile/src/harmony-native/components/Avatar/Avatar.tsx index 5af2894d404..4d4b2afbaf4 100644 --- a/packages/mobile/src/harmony-native/components/Avatar/Avatar.tsx +++ b/packages/mobile/src/harmony-native/components/Avatar/Avatar.tsx @@ -4,9 +4,8 @@ import { css } from '@emotion/native' import { View } from 'react-native' import type { SetRequired } from 'type-fest' -import { useTheme } from '@audius/harmony-native' -import type { MarginProps } from 'app/harmony-native/utils/styleProps' -import { useMargin } from 'app/harmony-native/utils/styleProps' +import type { BoxProps } from '@audius/harmony-native' +import { Box, useTheme } from '@audius/harmony-native' import type { FastImageProps } from '../FastImage/FastImage' import { FastImage } from '../FastImage/FastImage' @@ -17,10 +16,10 @@ type TweakedFastImageProps = Omit & export type AvatarProps = Omit & SetRequired & - MarginProps + BoxProps const sizeMap = { - auto: '100%' as const, + auto: undefined, small: 24, medium: 40, large: 72, @@ -40,7 +39,7 @@ export const Avatar = (props: AvatarProps) => { const { children, source, - size = 'medium', + size = 'auto', strokeWidth = 'default', variant = 'default', style, @@ -49,8 +48,6 @@ export const Avatar = (props: AvatarProps) => { const { color, shadows } = useTheme() - const margin = useMargin(other) - const borderRadius = 9999 const rootCss = css({ @@ -65,7 +62,8 @@ export const Avatar = (props: AvatarProps) => { }) const imageCss = css({ - flex: 1, + width: '100%', + aspectRatio: 1, alignItems: 'center', justifyContent: 'center', overflow: 'hidden', @@ -73,16 +71,16 @@ export const Avatar = (props: AvatarProps) => { }) return ( - - {source !== undefined ? ( - - {children} - - ) : ( - - {children} - - )} - + + + {source !== undefined ? ( + + {children} + + ) : ( + {children} + )} + + ) } diff --git a/packages/mobile/src/harmony-native/utils/styleProps.ts b/packages/mobile/src/harmony-native/utils/styleProps.ts deleted file mode 100644 index 1678574755a..00000000000 --- a/packages/mobile/src/harmony-native/utils/styleProps.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { css } from '@emotion/native' -import { useTheme } from '@emotion/react' - -import type { SpacingOptions } from '../foundations' - -export type MarginProps = { - m?: SpacingOptions - mt?: SpacingOptions - mr?: SpacingOptions - mb?: SpacingOptions - ml?: SpacingOptions - mx?: SpacingOptions - my?: SpacingOptions -} - -export const useMargin = (props: T) => { - const { spacing } = useTheme() - return css({ - ...(props.m && { margin: spacing[props.m] }), - ...(props.mt && { marginTop: spacing[props.mt] }), - ...(props.mr && { marginRight: spacing[props.mr] }), - ...(props.mb && { marginBottom: spacing[props.mb] }), - ...(props.ml && { marginLeft: spacing[props.ml] }), - ...(props.mx && { marginHorizontal: spacing[props.mx] }), - ...(props.my && { marginVertical: spacing[props.my] }) - }) -} diff --git a/packages/mobile/tsconfig.json b/packages/mobile/tsconfig.json index 2d2b369ce06..e921ba0d8e0 100644 --- a/packages/mobile/tsconfig.json +++ b/packages/mobile/tsconfig.json @@ -21,21 +21,9 @@ "module": "esnext", "paths": { "@audius/harmony-native": ["./src/harmony-native/index.ts"], - "@audius/common/adapters": ["../../common/src/adapters/index.ts"], - "@audius/common/api": ["../../common/src/api/index.ts"], - "@audius/common/assets": ["../../common/src/assets/index.ts"], - "@audius/common/audius-query": ["../../common/src/audius-query/index.ts"], - "@audius/common/context": ["../../common/src/context/index.ts"], - "@audius/common/hooks": ["../../common/src/hooks/index.ts"], - "@audius/common/messages": ["../../common/src/messages/index.ts"], - "@audius/common/models": ["../../common/src/models/index.ts"], - "@audius/common/schemas": ["../../common/src/schemas/index.ts"], - "@audius/common/services": ["../../common/src/services/index.ts"], - "@audius/common/store": ["../../common/src/store/index.ts"], - "@audius/common/serverStore": ["../../common/src/serverStore/index.ts"], - "@audius/common/utils": ["../../common/src/utils/index.ts"], "@audius/common/src/*": ["../../common/src/*"], "~/*": ["../common/src/*"], + "@audius/common/*": ["../../common/src/*"], "app/*": ["./src/*"], // Remove these when no longer dependent on @audius/web "audio/*": ["../../node_modules/@audius/web/src/audio/*"], From e6450fd7e8b79d5f93d04abd1484f32d6240154e Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Mon, 3 Jun 2024 17:12:51 -0700 Subject: [PATCH 2/4] Renames --- .../src/components/suggested-follows/SuggestedArtistsList.tsx | 4 ++-- .../components/{profile-list => user-list}/ProfileCard.tsx | 1 + .../src/components/{profile-list => user-list}/UserCard.tsx | 0 .../{profile-list => user-list}/UserCardSkeleton.tsx | 0 .../{profile-list/ProfileList.tsx => user-list/UserList.tsx} | 0 .../src/components/{profile-list => user-list}/index.ts | 2 +- .../mobile/src/screens/explore-screen/tabs/ArtistsTab.tsx | 2 +- .../src/screens/search-results-screen/tabs/ProfilesTab.tsx | 2 +- 8 files changed, 6 insertions(+), 5 deletions(-) rename packages/mobile/src/components/{profile-list => user-list}/ProfileCard.tsx (97%) rename packages/mobile/src/components/{profile-list => user-list}/UserCard.tsx (100%) rename packages/mobile/src/components/{profile-list => user-list}/UserCardSkeleton.tsx (100%) rename packages/mobile/src/components/{profile-list/ProfileList.tsx => user-list/UserList.tsx} (100%) rename packages/mobile/src/components/{profile-list => user-list}/index.ts (50%) diff --git a/packages/mobile/src/components/suggested-follows/SuggestedArtistsList.tsx b/packages/mobile/src/components/suggested-follows/SuggestedArtistsList.tsx index 425bb1baf07..fcf1b509cbf 100644 --- a/packages/mobile/src/components/suggested-follows/SuggestedArtistsList.tsx +++ b/packages/mobile/src/components/suggested-follows/SuggestedArtistsList.tsx @@ -12,8 +12,8 @@ import { import LinearGradient from 'react-native-linear-gradient' import { useDispatch, useSelector } from 'react-redux' -import type { ProfileListProps } from 'app/components/profile-list' -import { ProfileCard, ProfileList } from 'app/components/profile-list' +import type { ProfileListProps } from 'app/components/user-list' +import { ProfileCard, ProfileList } from 'app/components/user-list' import type { AppState } from 'app/store' import { makeStyles } from 'app/styles' import { useThemeColors } from 'app/utils/theme' diff --git a/packages/mobile/src/components/profile-list/ProfileCard.tsx b/packages/mobile/src/components/user-list/ProfileCard.tsx similarity index 97% rename from packages/mobile/src/components/profile-list/ProfileCard.tsx rename to packages/mobile/src/components/user-list/ProfileCard.tsx index 0a61c07062b..c91c2bd855b 100644 --- a/packages/mobile/src/components/profile-list/ProfileCard.tsx +++ b/packages/mobile/src/components/user-list/ProfileCard.tsx @@ -21,6 +21,7 @@ type ProfileCardProps = Partial> & { onPress?: (id: ID) => void } +// @deprecated -- use UserCard instead export const ProfileCard = (props: ProfileCardProps) => { const { profile, preventNavigation, onPress, ...other } = props const { user_id, handle } = profile diff --git a/packages/mobile/src/components/profile-list/UserCard.tsx b/packages/mobile/src/components/user-list/UserCard.tsx similarity index 100% rename from packages/mobile/src/components/profile-list/UserCard.tsx rename to packages/mobile/src/components/user-list/UserCard.tsx diff --git a/packages/mobile/src/components/profile-list/UserCardSkeleton.tsx b/packages/mobile/src/components/user-list/UserCardSkeleton.tsx similarity index 100% rename from packages/mobile/src/components/profile-list/UserCardSkeleton.tsx rename to packages/mobile/src/components/user-list/UserCardSkeleton.tsx diff --git a/packages/mobile/src/components/profile-list/ProfileList.tsx b/packages/mobile/src/components/user-list/UserList.tsx similarity index 100% rename from packages/mobile/src/components/profile-list/ProfileList.tsx rename to packages/mobile/src/components/user-list/UserList.tsx diff --git a/packages/mobile/src/components/profile-list/index.ts b/packages/mobile/src/components/user-list/index.ts similarity index 50% rename from packages/mobile/src/components/profile-list/index.ts rename to packages/mobile/src/components/user-list/index.ts index d55e3be6b8c..d347d5b81c1 100644 --- a/packages/mobile/src/components/profile-list/index.ts +++ b/packages/mobile/src/components/user-list/index.ts @@ -1,2 +1,2 @@ -export * from './ProfileList' +export * from './UserList' export * from './ProfileCard' diff --git a/packages/mobile/src/screens/explore-screen/tabs/ArtistsTab.tsx b/packages/mobile/src/screens/explore-screen/tabs/ArtistsTab.tsx index 1b0650ac85e..4a0ff37dad3 100644 --- a/packages/mobile/src/screens/explore-screen/tabs/ArtistsTab.tsx +++ b/packages/mobile/src/screens/explore-screen/tabs/ArtistsTab.tsx @@ -5,7 +5,7 @@ import { Status } from '@audius/common/models' import { explorePageSelectors, explorePageActions } from '@audius/common/store' import { useDispatch, useSelector } from 'react-redux' -import { ProfileList } from 'app/components/profile-list' +import { ProfileList } from 'app/components/user-list' import { TabInfo } from '../components/TabInfo' const { getExploreArtists, getExploreStatus, getArtistsStatus } = diff --git a/packages/mobile/src/screens/search-results-screen/tabs/ProfilesTab.tsx b/packages/mobile/src/screens/search-results-screen/tabs/ProfilesTab.tsx index 7da15e4a7f8..7becedbe043 100644 --- a/packages/mobile/src/screens/search-results-screen/tabs/ProfilesTab.tsx +++ b/packages/mobile/src/screens/search-results-screen/tabs/ProfilesTab.tsx @@ -3,7 +3,7 @@ import { Status } from '@audius/common/models' import type { CommonState } from '@audius/common/store' import { searchResultsPageSelectors, SearchKind } from '@audius/common/store' -import { ProfileList } from 'app/components/profile-list' +import { ProfileList } from 'app/components/user-list' import { spacing } from 'app/styles/spacing' import { EmptyResults } from '../EmptyResults' From a9937bf8ddb68e1da47c1bc817a1a28ee69950af Mon Sep 17 00:00:00 2001 From: Dylan Jeffers Date: Mon, 3 Jun 2024 17:13:59 -0700 Subject: [PATCH 3/4] More fixes --- .../components/suggested-follows/SuggestedArtistsList.tsx | 8 ++++---- packages/mobile/src/components/user-list/UserList.tsx | 4 ++-- .../mobile/src/screens/explore-screen/tabs/ArtistsTab.tsx | 4 ++-- .../screens/search-results-screen/tabs/ProfilesTab.tsx | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/mobile/src/components/suggested-follows/SuggestedArtistsList.tsx b/packages/mobile/src/components/suggested-follows/SuggestedArtistsList.tsx index fcf1b509cbf..12a5c1c1249 100644 --- a/packages/mobile/src/components/suggested-follows/SuggestedArtistsList.tsx +++ b/packages/mobile/src/components/suggested-follows/SuggestedArtistsList.tsx @@ -12,8 +12,8 @@ import { import LinearGradient from 'react-native-linear-gradient' import { useDispatch, useSelector } from 'react-redux' -import type { ProfileListProps } from 'app/components/user-list' -import { ProfileCard, ProfileList } from 'app/components/user-list' +import type { UserListProps } from 'app/components/user-list' +import { ProfileCard, UserList } from 'app/components/user-list' import type { AppState } from 'app/store' import { makeStyles } from 'app/styles' import { useThemeColors } from 'app/utils/theme' @@ -24,7 +24,7 @@ const useStyles = makeStyles(({ palette }) => ({ } })) -type SuggestedArtistsListProps = Partial +type SuggestedArtistsListProps = Partial export const SuggestedArtistsList = (props: SuggestedArtistsListProps) => { const styles = useStyles() @@ -59,7 +59,7 @@ export const SuggestedArtistsList = (props: SuggestedArtistsListProps) => { ) return ( - { const { user_id } = artist diff --git a/packages/mobile/src/components/user-list/UserList.tsx b/packages/mobile/src/components/user-list/UserList.tsx index 9611370fd91..56ac7e96b27 100644 --- a/packages/mobile/src/components/user-list/UserList.tsx +++ b/packages/mobile/src/components/user-list/UserList.tsx @@ -8,12 +8,12 @@ import { UserCardSkeleton } from './UserCardSkeleton' type ListProps = Omit, 'data'> -export type ProfileListProps = { +export type UserListProps = { profiles: User[] | undefined onCardPress?: (user_id: ID) => void } & Partial -export const ProfileList = (props: ProfileListProps) => { +export const UserList = (props: UserListProps) => { const { profiles, onCardPress, ...other } = props return ( { }, [exploreStatus, dispatch]) return ( - { useFetchTabResultsEffect(SearchKind.USERS) return ( - Date: Tue, 4 Jun 2024 17:57:15 -0700 Subject: [PATCH 4/4] More fixes --- .../mobile/src/components/user-list/UserCard.tsx | 16 ++++++---------- .../components/user-list/UserCardSkeleton.tsx | 2 ++ .../harmony-native/components/Avatar/Avatar.tsx | 5 ++++- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/mobile/src/components/user-list/UserCard.tsx b/packages/mobile/src/components/user-list/UserCard.tsx index 9eaeb59bb0a..288fbae78b4 100644 --- a/packages/mobile/src/components/user-list/UserCard.tsx +++ b/packages/mobile/src/components/user-list/UserCard.tsx @@ -2,7 +2,7 @@ import { useCallback } from 'react' import { SquareSizes, type ID } from '@audius/common/models' import { cacheUsersSelectors } from '@audius/common/store' -import { formatCount } from '@audius/common/utils' +import { formatCount, pluralize } from '@audius/common/utils' import type { GestureResponderEvent } from 'react-native' import { useSelector } from 'react-redux' @@ -22,7 +22,7 @@ import { UserLink } from '../user-link' const { getUser } = cacheUsersSelectors const messages = { - followers: (count: number) => (count === 1 ? 'Follower' : 'Followers') + follower: 'Follower' } type UserCardProps = PaperProps & { @@ -55,13 +55,7 @@ export const UserCard = (props: UserCardProps) => { return ( - + @@ -76,8 +70,10 @@ export const UserCard = (props: UserCardProps) => { borderBottomLeftRadius='m' borderBottomRightRadius='m' > + {/* Ensures correct footer height */} - {formatCount(follower_count)} {messages.followers(follower_count)} + {formatCount(follower_count)}{' '} + {pluralize(messages.follower, follower_count)} diff --git a/packages/mobile/src/components/user-list/UserCardSkeleton.tsx b/packages/mobile/src/components/user-list/UserCardSkeleton.tsx index 7651c1c6495..1812d76faa4 100644 --- a/packages/mobile/src/components/user-list/UserCardSkeleton.tsx +++ b/packages/mobile/src/components/user-list/UserCardSkeleton.tsx @@ -11,6 +11,7 @@ export const UserCardSkeleton = () => { /> + {/* marginBottom is simulating line-height */} @@ -22,6 +23,7 @@ export const UserCardSkeleton = () => { borderBottomLeftRadius='m' borderBottomRightRadius='m' > + {/* marginBottom is simulating line-height */} diff --git a/packages/mobile/src/harmony-native/components/Avatar/Avatar.tsx b/packages/mobile/src/harmony-native/components/Avatar/Avatar.tsx index 4d4b2afbaf4..8eac9a29b77 100644 --- a/packages/mobile/src/harmony-native/components/Avatar/Avatar.tsx +++ b/packages/mobile/src/harmony-native/components/Avatar/Avatar.tsx @@ -15,7 +15,10 @@ type TweakedFastImageProps = Omit & Partial> export type AvatarProps = Omit & - SetRequired & + ( + | SetRequired + | (TweakedFastImageProps & { 'aria-hidden'?: true }) + ) & BoxProps const sizeMap = {