-
Notifications
You must be signed in to change notification settings - Fork 132
Expand file tree
/
Copy pathuseNotifications.ts
More file actions
140 lines (123 loc) · 4.38 KB
/
useNotifications.ts
File metadata and controls
140 lines (123 loc) · 4.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import { useEffect, useMemo } from 'react'
import { Id } from '@audius/sdk'
import {
InfiniteData,
useInfiniteQuery,
useQueryClient
} from '@tanstack/react-query'
import { usePrevious } from 'react-use'
import { notificationFromSDK, transformAndCleanList } from '~/adapters'
import { useQueryContext } from '~/api/tan-query/utils/QueryContext'
import { useRemoteVar } from '~/hooks'
import { ChallengeRewardID } from '~/models'
import { ID } from '~/models/Identifiers'
import { StringKeys } from '~/services'
import { NotificationType, Notification } from '~/store/notifications/types'
import { QUERY_KEYS } from '../queryKeys'
import { QueryKey, QueryOptions } from '../types'
import { useCurrentUserId } from '../users/account/useCurrentUserId'
import { primeRelatedData } from '../utils/primeRelatedData'
import { useNotificationUnreadCount } from './useNotificationUnreadCount'
const DEFAULT_LIMIT = 20
type PageParam = {
timestamp: number
groupId: string | undefined
} | null
export const getNotificationsQueryKey = ({
currentUserId,
pageSize
}: {
currentUserId: ID | null | undefined
pageSize: number
}) =>
[
QUERY_KEYS.notifications,
currentUserId,
{ pageSize }
] as unknown as QueryKey<InfiniteData<Notification[]>>
/**
* Hook that returns paginated notifications for the current user.
* Uses infinite query to support "Load More" functionality.
* Pagination is based on the timestamp and groupId of the last notification.
*/
export const useNotifications = (options?: QueryOptions) => {
const { audiusSdk } = useQueryContext()
const queryClient = useQueryClient()
const { data: currentUserId } = useCurrentUserId()
const pageSize = DEFAULT_LIMIT
const { data: unreadCount } = useNotificationUnreadCount()
const prevUnreadCount = usePrevious(unreadCount)
// Get whitelisted challenge reward IDs from remote config
const challengeRewardIdsString = useRemoteVar(StringKeys.CHALLENGE_REWARD_IDS)
const whitelistedChallengeIds = useMemo(() => {
if (!challengeRewardIdsString) return new Set<ChallengeRewardID>()
return new Set(
challengeRewardIdsString
.split(',')
.map((id) => id.trim()) as ChallengeRewardID[]
)
}, [challengeRewardIdsString])
const query = useInfiniteQuery({
queryKey: getNotificationsQueryKey({
currentUserId,
pageSize
}),
initialPageParam: null as PageParam,
queryFn: async ({ pageParam = null }) => {
const sdk = await audiusSdk()
const response = await sdk.notifications.getNotifications({
id: Id.parse(currentUserId),
// Requester id sent as `?user_id=` so the backend personalizes
// embedded related.users (e.g. does_current_user_follow). The path
// id alone identifies the notifications owner, not the requester.
userId: Id.parse(currentUserId),
limit: DEFAULT_LIMIT,
timestamp: pageParam?.timestamp,
groupId: pageParam?.groupId
})
primeRelatedData({ related: response.related, queryClient })
const notifications = transformAndCleanList(
response?.data?.notifications,
notificationFromSDK
) as Notification[]
// Filter out challenge reward notifications that aren't whitelisted
return notifications.filter((notification) => {
if (notification.type === NotificationType.ChallengeReward) {
return whitelistedChallengeIds.has(notification.challengeId)
}
return true
})
},
getNextPageParam: (lastPage: Notification[]) => {
const lastNotification = lastPage[lastPage.length - 1]
if (!lastNotification || lastPage.length < DEFAULT_LIMIT) {
return null
}
return {
timestamp: lastNotification.timestamp,
groupId: lastNotification.groupId
}
},
...options,
enabled: options?.enabled !== false && !!currentUserId
})
// Refetch when new notifications arrive
useEffect(() => {
if (
prevUnreadCount !== undefined &&
unreadCount !== undefined &&
unreadCount > prevUnreadCount
) {
// Only refetch if we're not already fetching
if (!query.isFetching) {
query.refetch()
}
}
}, [unreadCount, prevUnreadCount, query])
const notifications = query.data?.pages.flat() ?? []
const queryResults = query as typeof query & {
notifications: Notification[]
}
queryResults.notifications = notifications
return queryResults
}