Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
[C-934] Add fully native user lists (#1830)
Browse files Browse the repository at this point in the history
  • Loading branch information
sliptype committed Sep 9, 2022
1 parent ec23451 commit b80f930
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
favoritesUserListActions,
favoritesUserListSelectors
} from '@audius/common'
import { useDispatch } from 'react-redux'

import IconHeart from 'app/assets/images/iconHeart.svg'
import { useDispatchWeb } from 'app/hooks/useDispatchWeb'
import { useRoute } from 'app/hooks/useRoute'

import { UserList } from './UserList'
Expand All @@ -21,11 +21,11 @@ const messages = {
export const FavoritedScreen = () => {
const { params } = useRoute<'Favorited'>()
const { id, favoriteType } = params
const dispatchWeb = useDispatchWeb()
const dispatch = useDispatch()

const handleSetFavorited = useCallback(() => {
dispatchWeb(setFavorite(id, favoriteType))
}, [dispatchWeb, id, favoriteType])
dispatch(setFavorite(id, favoriteType))
}, [dispatch, id, favoriteType])

return (
<UserListScreen title={messages.title} titleIcon={IconHeart}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
followersUserListSelectors,
followersUserListActions
} from '@audius/common'
import { useDispatch } from 'react-redux'

import IconUser from 'app/assets/images/iconUser.svg'
import { useDispatchWeb } from 'app/hooks/useDispatchWeb'
import { useProfileRoute } from 'app/hooks/useRoute'

import { UserList } from './UserList'
Expand All @@ -21,11 +21,11 @@ const messages = {
export const FollowersScreen = () => {
const { params } = useProfileRoute<'Followers'>()
const { userId } = params
const dispatchWeb = useDispatchWeb()
const dispatch = useDispatch()

const handleSetFollowers = useCallback(() => {
dispatchWeb(setFollowers(userId))
}, [dispatchWeb, userId])
dispatch(setFollowers(userId))
}, [dispatch, userId])

return (
<UserListScreen title={messages.title} titleIcon={IconUser}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
followingUserListActions,
followingUserListSelectors
} from '@audius/common'
import { useDispatch } from 'react-redux'

import IconUser from 'app/assets/images/iconUser.svg'
import { useDispatchWeb } from 'app/hooks/useDispatchWeb'
import { useProfileRoute } from 'app/hooks/useRoute'

import { UserList } from './UserList'
Expand All @@ -21,11 +21,11 @@ const messages = {
export const FollowingScreen = () => {
const { params } = useProfileRoute<'Following'>()
const { userId } = params
const dispatchWeb = useDispatchWeb()
const dispatch = useDispatch()

const handleSetFollowing = useCallback(() => {
dispatchWeb(setFollowing(userId))
}, [dispatchWeb, userId])
dispatch(setFollowing(userId))
}, [dispatch, userId])

return (
<UserListScreen title={messages.title} titleIcon={IconUser}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import {
mutualsUserListSelectors,
MUTUALS_USER_LIST_TAG
} from '@audius/common'
import { useDispatch } from 'react-redux'

import IconFollowing from 'app/assets/images/iconFollowing.svg'
import { useDispatchWeb } from 'app/hooks/useDispatchWeb'
import { useProfileRoute } from 'app/hooks/useRoute'

import { UserList } from './UserList'
Expand All @@ -22,11 +22,11 @@ const messages = {
export const MutualsScreen = () => {
const { params } = useProfileRoute<'Mutuals'>()
const { userId } = params
const dispatchWeb = useDispatchWeb()
const dispatch = useDispatch()

const handleSetMutals = useCallback(() => {
dispatchWeb(setMutuals(userId))
}, [dispatchWeb, userId])
dispatch(setMutuals(userId))
}, [dispatch, userId])

return (
<UserListScreen title={messages.title} titleIcon={IconFollowing}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,39 @@ import {
notificationsUserListActions,
notificationsUserListSelectors
} from '@audius/common'
import { useDispatch } from 'react-redux'

import { Screen } from 'app/components/core'
import { useDispatchWeb } from 'app/hooks/useDispatchWeb'
import { useRoute } from 'app/hooks/useRoute'
import { formatCount } from 'app/utils/format'

import { UserList } from './UserList'
import { UserListScreen } from './UserListScreen'
const { getUserList } = notificationsUserListSelectors
const { setNotificationId } = notificationsUserListActions

export const NotificationUsersScreen = () => {
const { params } = useRoute<'NotificationUsers'>()
const { notificationType, count, id } = params
const dispatchWeb = useDispatchWeb()
const dispatch = useDispatch()

const handleSetNotificationId = useCallback(() => {
dispatchWeb(setNotificationId(id))
}, [dispatchWeb, id])
dispatch(setNotificationId(id))
}, [dispatch, id])

const getTitle = useCallback(() => {
if (notificationType === NotificationType.Follow) {
return `${formatCount(count)} new followers`
return `${formatCount(count)} New Followers`
}
return `${formatCount(count)} ${notificationType.toLowerCase()}s`
return `${formatCount(count)} ${notificationType}s`
}, [notificationType, count])

return (
<Screen title={getTitle()} variant='white'>
<UserListScreen title={getTitle()}>
<UserList
userSelector={getUserList}
tag='NOTIFICATION'
setUserList={handleSetNotificationId}
/>
</Screen>
</UserListScreen>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
repostsUserListActions,
repostsUserListSelectors
} from '@audius/common'
import { useDispatch } from 'react-redux'

import IconRepost from 'app/assets/images/iconRepost.svg'
import { useDispatchWeb } from 'app/hooks/useDispatchWeb'
import { useRoute } from 'app/hooks/useRoute'

import { UserList } from './UserList'
Expand All @@ -21,11 +21,11 @@ const messages = {
export const RepostsScreen = () => {
const { params } = useRoute<'Reposts'>()
const { id, repostType } = params
const dispatchWeb = useDispatchWeb()
const dispatch = useDispatch()

const handleSetRepost = useCallback(() => {
dispatchWeb(setRepost(id, repostType))
}, [dispatchWeb, id, repostType])
dispatch(setRepost(id, repostType))
}, [dispatch, id, repostType])

return (
<UserListScreen title={messages.title} titleIcon={IconRepost}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
supportingUserListActions,
supportingUserListSelectors
} from '@audius/common'
import { useDispatch } from 'react-redux'

import IconTip from 'app/assets/images/iconTip.svg'
import { useDispatchWeb } from 'app/hooks/useDispatchWeb'
import { useRoute } from 'app/hooks/useRoute'

import { UserList } from './UserList'
Expand All @@ -21,11 +21,11 @@ const messages = {
export const SupportingUsersScreen = () => {
const { params } = useRoute<'SupportingUsers'>()
const { userId } = params
const dispatchWeb = useDispatchWeb()
const dispatch = useDispatch()

const handleSetSupporting = useCallback(() => {
dispatchWeb(setSupporting(userId))
}, [dispatchWeb, userId])
dispatch(setSupporting(userId))
}, [dispatch, userId])

return (
<UserListScreen title={messages.title} titleIcon={IconTip}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import {
topSupportersUserListActions
} from '@audius/common'
import { View } from 'react-native'
import { useDispatch, useSelector } from 'react-redux'

import IconTrophy from 'app/assets/images/iconTrophy.svg'
import { Text } from 'app/components/core'
import { useDispatchWeb } from 'app/hooks/useDispatchWeb'
import { useRoute } from 'app/hooks/useRoute'
import { useSelectorWeb } from 'app/hooks/useSelectorWeb'
import { makeStyles } from 'app/styles'

import { UserList } from './UserList'
Expand Down Expand Up @@ -39,15 +38,15 @@ export const TopSupportersScreen = () => {
const styles = useStyles()
const { params } = useRoute<'TopSupporters'>()
const { userId, source } = params
const supportersId = useSelectorWeb(getSupportersId)
const supportersUser = useSelectorWeb((state) =>
const supportersId = useSelector(getSupportersId)
const supportersUser = useSelector((state) =>
getUser(state, { id: supportersId })
)
const dispatchWeb = useDispatchWeb()
const dispatch = useDispatch()

const handleSetSupporters = useCallback(() => {
dispatchWeb(setTopSupporters(userId))
}, [dispatchWeb, userId])
dispatch(setTopSupporters(userId))
}, [dispatch, userId])

const title =
source === 'feed' && supportersUser ? (
Expand Down
28 changes: 13 additions & 15 deletions packages/mobile/src/screens/user-list-screen/UserList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ import {
import { useFocusEffect, useIsFocused } from '@react-navigation/native'
import { View } from 'react-native'
import type { Selector } from 'react-redux'
import { useDispatch, useSelector } from 'react-redux'

import { Divider, FlatList } from 'app/components/core'
import LoadingSpinner from 'app/components/loading-spinner'
import { useDispatchWeb } from 'app/hooks/useDispatchWeb'
import { isEqual, useSelectorWeb } from 'app/hooks/useSelectorWeb'
import { makeStyles } from 'app/styles'

import { UserListItem } from './UserListItem'
Expand Down Expand Up @@ -60,17 +59,16 @@ export const UserList = (props: UserListProps) => {
const isFocused = useIsFocused()
const styles = useStyles()
const cachedUsers = useRef<User[]>([])
const dispatchWeb = useDispatchWeb()
const dispatch = useDispatch()
const [isRefreshing, setIsRefreshing] = useState(true)
const { hasMore, userIds, loading } = useSelectorWeb(userSelector, isEqual)
const { hasMore, userIds, loading } = useSelector(userSelector)
const getOptimisticUserIds = makeGetOptimisticUserIdsIfNeeded({
userIds,
tag
})
const optimisticUserIds: ID[] = useSelectorWeb(getOptimisticUserIds)
const usersMap = useSelectorWeb(
(state) => getUsers(state, { ids: optimisticUserIds }),
isEqual
const optimisticUserIds: ID[] = useSelector(getOptimisticUserIds)
const usersMap = useSelector((state) =>
getUsers(state, { ids: optimisticUserIds })
)
const users: User[] = useMemo(
() =>
Expand All @@ -84,13 +82,13 @@ export const UserList = (props: UserListProps) => {
useCallback(() => {
setIsRefreshing(true)
setUserList()
dispatchWeb(setLoading(tag, true))
dispatchWeb(loadMore(tag))
dispatch(setLoading(tag, true))
dispatch(loadMore(tag))

return () => {
dispatchWeb(reset(tag))
dispatch(reset(tag))
}
}, [dispatchWeb, setUserList, tag])
}, [dispatch, setUserList, tag])
)

const isEmpty = users.length === 0
Expand All @@ -110,10 +108,10 @@ export const UserList = (props: UserListProps) => {

const handleEndReached = useCallback(() => {
if (hasMore && isFocused) {
dispatchWeb(setLoading(tag, true))
dispatchWeb(loadMore(tag))
dispatch(setLoading(tag, true))
dispatch(loadMore(tag))
}
}, [hasMore, isFocused, dispatchWeb, tag])
}, [hasMore, isFocused, dispatch, tag])

const data =
isEmpty || isRefreshing || loading || !isFocused
Expand Down
4 changes: 2 additions & 2 deletions packages/mobile/src/screens/user-list-screen/UserListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useCallback } from 'react'
import type { User } from '@audius/common'
import { FollowSource, accountSelectors } from '@audius/common'
import { Pressable, View, Animated } from 'react-native'
import { useSelector } from 'react-redux'

import IconUser from 'app/assets/images/iconUser.svg'
import { Text } from 'app/components/core'
Expand All @@ -14,7 +15,6 @@ import {
import UserBadges from 'app/components/user-badges'
import { useNavigation } from 'app/hooks/useNavigation'
import { useColorAnimation } from 'app/hooks/usePressColorAnimation'
import { useSelectorWeb } from 'app/hooks/useSelectorWeb'
import { makeStyles } from 'app/styles'
import { formatCount } from 'app/utils/format'
import { useThemeColors } from 'app/utils/theme'
Expand Down Expand Up @@ -76,7 +76,7 @@ export const UserListItem = (props: UserListItemProps) => {
const { tag, user } = props
const { user_id, handle, name, follower_count, does_follow_current_user } =
user
const currentUserId = useSelectorWeb(getUserId)
const currentUserId = useSelector(getUserId)
const styles = useStyles()
const navigation = useNavigation()
const { white, neutralLight10 } = useThemeColors()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ export const UserListScreen = (props: UserListScreenProps) => {
const { title, titleIcon, children } = props

const headerTitle = useCallback(() => {
if (!titleIcon) {
return null
}
return <UserListTitle icon={titleIcon} title={title} />
}, [titleIcon, title])

Expand Down
16 changes: 9 additions & 7 deletions packages/mobile/src/screens/user-list-screen/UserListTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const useStyles = makeStyles(({ spacing, palette }) => ({
}))

type UserListTitleProps = {
icon: ComponentType<SvgProps>
icon?: ComponentType<SvgProps>
title: ReactNode
}
export const UserListTitle = (props: UserListTitleProps) => {
Expand All @@ -32,12 +32,14 @@ export const UserListTitle = (props: UserListTitleProps) => {

return (
<View style={styles.root}>
<Icon
style={styles.icon}
fill={neutralLight2}
height={spacing(6)}
width={spacing(6)}
/>
{Icon ? (
<Icon
style={styles.icon}
fill={neutralLight2}
height={spacing(6)}
width={spacing(6)}
/>
) : null}
<Text
variant='h1'
accessibilityRole='header'
Expand Down

0 comments on commit b80f930

Please sign in to comment.