@planningcenter/chat-react-native 4.2.1-qa-staging.2 → 4.2.1-qa-staging.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/conversation/message_form.d.ts.map +1 -1
- package/build/components/conversation/message_form.js +1 -1
- package/build/components/conversation/message_form.js.map +1 -1
- package/build/contexts/conversation_context.d.ts +3 -1
- package/build/contexts/conversation_context.d.ts.map +1 -1
- package/build/contexts/conversation_context.js +23 -18
- package/build/contexts/conversation_context.js.map +1 -1
- package/build/hooks/use_conversation_message_lookup.d.ts +7 -0
- package/build/hooks/use_conversation_message_lookup.d.ts.map +1 -0
- package/build/hooks/use_conversation_message_lookup.js +52 -0
- package/build/hooks/use_conversation_message_lookup.js.map +1 -0
- package/build/hooks/use_conversation_messages.d.ts +1 -0
- package/build/hooks/use_conversation_messages.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages.js +8 -1
- package/build/hooks/use_conversation_messages.js.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.d.ts +12 -4
- package/build/hooks/use_conversation_messages_jolt_events.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.js +82 -88
- package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
- package/build/hooks/use_fetch_newer_messages.d.ts.map +1 -1
- package/build/hooks/use_fetch_newer_messages.js +27 -21
- package/build/hooks/use_fetch_newer_messages.js.map +1 -1
- package/build/hooks/use_fetch_newer_on_foreground.d.ts +1 -1
- package/build/hooks/use_fetch_newer_on_foreground.d.ts.map +1 -1
- package/build/hooks/use_fetch_newer_on_foreground.js +2 -1
- package/build/hooks/use_fetch_newer_on_foreground.js.map +1 -1
- package/build/hooks/use_held_back_messages.d.ts +11 -0
- package/build/hooks/use_held_back_messages.d.ts.map +1 -0
- package/build/hooks/use_held_back_messages.js +24 -0
- package/build/hooks/use_held_back_messages.js.map +1 -0
- package/build/hooks/use_message_create_or_update.d.ts.map +1 -1
- package/build/hooks/use_message_create_or_update.js +91 -80
- package/build/hooks/use_message_create_or_update.js.map +1 -1
- package/build/hooks/use_message_reaction_toggle.d.ts.map +1 -1
- package/build/hooks/use_message_reaction_toggle.js +45 -40
- package/build/hooks/use_message_reaction_toggle.js.map +1 -1
- package/build/screens/conversation_new/components/services_form.js.map +1 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +485 -156
- package/build/screens/conversation_screen.js.map +1 -1
- package/build/screens/message_actions_screen.d.ts.map +1 -1
- package/build/screens/message_actions_screen.js +21 -26
- package/build/screens/message_actions_screen.js.map +1 -1
- package/build/screens/message_report_screen.d.ts.map +1 -1
- package/build/screens/message_report_screen.js +17 -44
- package/build/screens/message_report_screen.js.map +1 -1
- package/build/screens/reactions_screen.d.ts.map +1 -1
- package/build/screens/reactions_screen.js +70 -88
- package/build/screens/reactions_screen.js.map +1 -1
- package/build/utils/cache/find_message_in_caches.d.ts +4 -0
- package/build/utils/cache/find_message_in_caches.d.ts.map +1 -0
- package/build/utils/cache/find_message_in_caches.js +16 -0
- package/build/utils/cache/find_message_in_caches.js.map +1 -0
- package/build/utils/cache/optimistically_update_message.d.ts +2 -1
- package/build/utils/cache/optimistically_update_message.d.ts.map +1 -1
- package/build/utils/cache/optimistically_update_message.js +4 -4
- package/build/utils/cache/optimistically_update_message.js.map +1 -1
- package/build/utils/cache/prepend_newer_page.d.ts +1 -1
- package/build/utils/cache/prepend_newer_page.d.ts.map +1 -1
- package/build/utils/cache/prepend_newer_page.js +10 -9
- package/build/utils/cache/prepend_newer_page.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/hooks/use_conversation_messages.test.ts +22 -0
- package/src/__tests__/hooks/use_conversation_messages_jolt_events.test.ts +22 -25
- package/src/components/conversation/message_form.tsx +1 -2
- package/src/contexts/conversation_context.tsx +6 -1
- package/src/hooks/__tests__/use_fetch_newer_messages.test.tsx +68 -0
- package/src/hooks/__tests__/use_held_back_messages.test.tsx +60 -0
- package/src/hooks/__tests__/use_message_reaction_toggle.test.tsx +73 -0
- package/src/hooks/use_conversation_message_lookup.ts +29 -0
- package/src/hooks/use_conversation_messages.ts +9 -0
- package/src/hooks/use_conversation_messages_jolt_events.ts +43 -41
- package/src/hooks/use_fetch_newer_messages.ts +19 -12
- package/src/hooks/use_fetch_newer_on_foreground.ts +2 -2
- package/src/hooks/use_held_back_messages.ts +33 -0
- package/src/hooks/use_message_create_or_update.ts +8 -8
- package/src/hooks/use_message_reaction_toggle.ts +3 -1
- package/src/screens/conversation_new/components/services_form.tsx +1 -1
- package/src/screens/conversation_screen.tsx +20 -20
- package/src/screens/message_actions_screen.tsx +3 -5
- package/src/screens/message_report_screen.tsx +2 -3
- package/src/screens/reactions_screen.tsx +2 -4
- package/src/utils/cache/__tests__/find_message_in_caches.test.ts +37 -0
- package/src/utils/cache/__tests__/prepend_newer_page.test.ts +13 -14
- package/src/utils/cache/find_message_in_caches.ts +20 -0
- package/src/utils/cache/optimistically_update_message.ts +2 -5
- package/src/utils/cache/prepend_newer_page.ts +7 -10
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { InfiniteData, useMutation } from '@tanstack/react-query'
|
|
2
2
|
import { chatQueryClient } from '../contexts/api_provider'
|
|
3
|
+
import { useConversationContext } from '../contexts/conversation_context'
|
|
3
4
|
import { ApiCollection, ApiResource, MessageResource } from '../types'
|
|
4
5
|
import { DenormalizedAttachmentResourceForCreate } from '../types/resources/denormalized_attachment_resource_for_create'
|
|
5
6
|
import {
|
|
@@ -35,6 +36,12 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
|
|
|
35
36
|
const isEditing = !isNewMessage(message)
|
|
36
37
|
const apiClient = useApiClient()
|
|
37
38
|
const currentPerson = useCurrentPerson()
|
|
39
|
+
const { messagesQueryKey } = useConversationContext()
|
|
40
|
+
const liveQueryKey = getMessagesQueryKey({
|
|
41
|
+
conversation_id: conversationId,
|
|
42
|
+
reply_root_id: replyRootId,
|
|
43
|
+
})
|
|
44
|
+
const queryKey = isEditing ? (messagesQueryKey ?? liveQueryKey) : liveQueryKey
|
|
38
45
|
|
|
39
46
|
const mutation = useMutation({
|
|
40
47
|
mutationFn: ({ text, attachments, idempotentKey }: ResolvedMessageMutationVariables) => {
|
|
@@ -79,6 +86,7 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
|
|
|
79
86
|
message,
|
|
80
87
|
text,
|
|
81
88
|
replyRootId,
|
|
89
|
+
queryKey,
|
|
82
90
|
})
|
|
83
91
|
|
|
84
92
|
return { message: optimisticMessage }
|
|
@@ -102,10 +110,6 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
|
|
|
102
110
|
|
|
103
111
|
// Add error to the optimistic message from the cache on error
|
|
104
112
|
if (optimisticMessage) {
|
|
105
|
-
const queryKey = getMessagesQueryKey({
|
|
106
|
-
conversation_id: conversationId,
|
|
107
|
-
reply_root_id: replyRootId,
|
|
108
|
-
})
|
|
109
113
|
chatQueryClient.setQueryData(
|
|
110
114
|
queryKey,
|
|
111
115
|
(data: InfiniteData<ApiCollection<MessageResource>> | undefined) =>
|
|
@@ -125,10 +129,6 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
|
|
|
125
129
|
const { message: optimisticMessage } = context || {}
|
|
126
130
|
const updatedMessage = result.data
|
|
127
131
|
type QueryData = InfiniteData<ApiCollection<MessageResource>>
|
|
128
|
-
const queryKey = getMessagesQueryKey({
|
|
129
|
-
conversation_id: conversationId,
|
|
130
|
-
reply_root_id: replyRootId,
|
|
131
|
-
})
|
|
132
132
|
|
|
133
133
|
// First remove the optimistic message if it exists
|
|
134
134
|
if (optimisticMessage) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { InfiniteData, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
2
2
|
import { useCallback } from 'react'
|
|
3
3
|
import { Alert } from 'react-native'
|
|
4
|
+
import { useConversationContext } from '../contexts/conversation_context'
|
|
4
5
|
import { ApiCollection, ApiResource, MessageResource } from '../types'
|
|
5
6
|
import { ReactionCountResource } from '../types/resources/reaction'
|
|
6
7
|
import { updateRecordInPagesData, REACTION_EMOJIS } from '../utils'
|
|
@@ -30,7 +31,8 @@ export function useMessageReactionToggle({
|
|
|
30
31
|
}: UseMessageReactionToggleProps) {
|
|
31
32
|
const apiClient = useApiClient()
|
|
32
33
|
const queryClient = useQueryClient()
|
|
33
|
-
const
|
|
34
|
+
const { messagesQueryKey } = useConversationContext()
|
|
35
|
+
const queryKey = messagesQueryKey ?? getMessagesQueryKey({ conversation_id })
|
|
34
36
|
const message_id = message.id
|
|
35
37
|
|
|
36
38
|
const toggleReaction = useCallback(
|
|
@@ -45,7 +45,7 @@ export const ServicesForm = ({
|
|
|
45
45
|
const customAvatarsEnabled = featureEnabled(availableFeatures.custom_conversation_avatars)
|
|
46
46
|
const safetyLockEnabled = featureEnabled(availableFeatures.conversation_safety_lock)
|
|
47
47
|
const [selectedPlanId, setSelectedPlanId] = useState<number | undefined>(initialPlanId)
|
|
48
|
-
const [filterByPlan, setFilterByPlan] = useState(!!initialPlanId)
|
|
48
|
+
const [filterByPlan, setFilterByPlan] = useState<boolean>(!!initialPlanId)
|
|
49
49
|
const initialState = useMemo(() => uniq(initialTeamIds) || [], [initialTeamIds]) // Uniq here because services can send duplicates in the teams_i_lead response.
|
|
50
50
|
const [selectedTeamIds, setSelectedTeamIds] = useState<number[]>(initialState)
|
|
51
51
|
|
|
@@ -33,6 +33,7 @@ import { useConversationMessages } from '../hooks/use_conversation_messages'
|
|
|
33
33
|
import { useConversationMessagesJoltEvents } from '../hooks/use_conversation_messages_jolt_events'
|
|
34
34
|
import { useFetchNewerMessages } from '../hooks/use_fetch_newer_messages'
|
|
35
35
|
import { useFetchNewerOnForeground } from '../hooks/use_fetch_newer_on_foreground'
|
|
36
|
+
import { useHeldBackMessages } from '../hooks/use_held_back_messages'
|
|
36
37
|
import { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read'
|
|
37
38
|
import {
|
|
38
39
|
analyticsEvents,
|
|
@@ -45,6 +46,7 @@ import { ConversationResource } from '../types/resources/conversation'
|
|
|
45
46
|
import { ConversationBadgeResource } from '../types/resources/conversation_badge'
|
|
46
47
|
import { MessageResource } from '../types/resources/message'
|
|
47
48
|
import { gatedMessageCache } from '../utils/gated_message_cache'
|
|
49
|
+
import { getMessagesQueryKey } from '../utils/request/get_messages'
|
|
48
50
|
import { decodeUlidTime } from '../utils/ulid'
|
|
49
51
|
|
|
50
52
|
export type ConversationRouteProps = {
|
|
@@ -85,6 +87,7 @@ export function ConversationScreen({ route }: ConversationScreenProps) {
|
|
|
85
87
|
<ConversationContextProvider
|
|
86
88
|
conversationId={conversation_id}
|
|
87
89
|
currentPageReplyRootId={reply_root_id ?? null}
|
|
90
|
+
messagesQueryKey={getMessagesQueryKey({ conversation_id, reply_root_id, anchor })}
|
|
88
91
|
>
|
|
89
92
|
{anchor ? (
|
|
90
93
|
<AnchorNotFoundBoundary onAnchorNotFound={dropAnchor}>
|
|
@@ -134,23 +137,27 @@ function ConversationScreenContent({
|
|
|
134
137
|
const caughtUp = !hasPreviousPage
|
|
135
138
|
const [showJumpToBottomButton, setShowJumpToBottomButton] = useState(false)
|
|
136
139
|
const readingHistory = showJumpToBottomButton
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
+
const newestMessageId = messages[0]?.id
|
|
141
|
+
const fetchNewer = useFetchNewerMessages({ conversation_id, reply_root_id, queryKey })
|
|
142
|
+
const { onSkippedNewMessage } = useHeldBackMessages({
|
|
143
|
+
fetchNewer,
|
|
144
|
+
newestMessageId,
|
|
145
|
+
readingHistory,
|
|
146
|
+
caughtUp,
|
|
147
|
+
})
|
|
148
|
+
useConversationJoltEvents({ conversationId: conversation_id })
|
|
149
|
+
useConversationMessagesJoltEvents({
|
|
150
|
+
conversationId: conversation_id,
|
|
151
|
+
replyRootId: reply_root_id ?? null,
|
|
152
|
+
messageCache: gatedMessageCache({
|
|
140
153
|
queryKey,
|
|
141
154
|
acceptNewMessages: caughtUp && !readingHistory,
|
|
142
|
-
onSkippedNewMessage
|
|
143
|
-
skippedNewMessages.current = true
|
|
144
|
-
},
|
|
155
|
+
onSkippedNewMessage,
|
|
145
156
|
}),
|
|
146
|
-
|
|
147
|
-
const newestMessageId = messages[0]?.id
|
|
148
|
-
useConversationJoltEvents({ conversationId: conversation_id })
|
|
149
|
-
useConversationMessagesJoltEvents({ conversationId: conversation_id, messageCaches })
|
|
157
|
+
})
|
|
150
158
|
const { markHandledByMessageForm } = useVideoModerationJoltEvents()
|
|
151
159
|
useEnsureConversationsRouteExists()
|
|
152
160
|
useMarkLatestMessageRead({ conversation, messages, enabled: !behindLatest })
|
|
153
|
-
const fetchNewer = useFetchNewerMessages({ conversation_id, reply_root_id, queryKey })
|
|
154
161
|
useFetchNewerOnForeground({ fetchNewer, newestMessageId, enabled: anchored && caughtUp })
|
|
155
162
|
const noMessages = messages.length === 0
|
|
156
163
|
|
|
@@ -187,9 +194,9 @@ function ConversationScreenContent({
|
|
|
187
194
|
}, [handleReturnToBottom, onExitAnchoredMode])
|
|
188
195
|
const jumpToLatest = useCallback(() => {
|
|
189
196
|
setShowJumpToBottomButton(false)
|
|
190
|
-
if (
|
|
197
|
+
if (anchored) exitAnchoredMode()
|
|
191
198
|
else handleReturnToBottom()
|
|
192
|
-
}, [
|
|
199
|
+
}, [anchored, exitAnchoredMode, handleReturnToBottom])
|
|
193
200
|
|
|
194
201
|
const trackScroll = (event: any) => {
|
|
195
202
|
const offsetY = event.nativeEvent.contentOffset.y
|
|
@@ -203,13 +210,6 @@ function ConversationScreenContent({
|
|
|
203
210
|
fetchPreviousPage()
|
|
204
211
|
}
|
|
205
212
|
|
|
206
|
-
useEffect(() => {
|
|
207
|
-
if (readingHistory || !caughtUp || !newestMessageId || !skippedNewMessages.current) return
|
|
208
|
-
|
|
209
|
-
skippedNewMessages.current = false
|
|
210
|
-
fetchNewer(newestMessageId)
|
|
211
|
-
}, [caughtUp, fetchNewer, newestMessageId, readingHistory])
|
|
212
|
-
|
|
213
213
|
useEffect(() => {
|
|
214
214
|
if (reply_root_id) {
|
|
215
215
|
navigation.setParams({
|
|
@@ -9,6 +9,7 @@ import { useReactionStyles } from '../components/conversation/message_reaction'
|
|
|
9
9
|
import FormSheet, { getFormSheetScreenOptions } from '../components/primitive/form_sheet'
|
|
10
10
|
import { useCreateAndroidRippleColor, useFontScale, useTheme } from '../hooks'
|
|
11
11
|
import { useApiClient } from '../hooks/use_api_client'
|
|
12
|
+
import { useConversationMessageLookup } from '../hooks/use_conversation_message_lookup'
|
|
12
13
|
import { useConversationMessages } from '../hooks/use_conversation_messages'
|
|
13
14
|
import { availableFeatures, useFeatures } from '../hooks/use_features'
|
|
14
15
|
import { useMessageReactionToggle } from '../hooks/use_message_reaction_toggle'
|
|
@@ -41,11 +42,8 @@ export function MessageActionsScreen({ route }: MessageActionsScreenProps) {
|
|
|
41
42
|
isSystemMessage,
|
|
42
43
|
} = route.params
|
|
43
44
|
|
|
44
|
-
const {
|
|
45
|
-
|
|
46
|
-
{ refetchOnMount: false }
|
|
47
|
-
)
|
|
48
|
-
const message = messages.find(m => m.id === message_id)
|
|
45
|
+
const { refetch } = useConversationMessages({ conversation_id }, { refetchOnMount: false })
|
|
46
|
+
const message = useConversationMessageLookup({ conversation_id, message_id })
|
|
49
47
|
|
|
50
48
|
if (!message) return null
|
|
51
49
|
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from '../components/display/platform_modal_header_buttons'
|
|
15
15
|
import BlankState from '../components/primitive/blank_state_primitive'
|
|
16
16
|
import { useTheme } from '../hooks'
|
|
17
|
-
import {
|
|
17
|
+
import { useConversationMessageLookup } from '../hooks/use_conversation_message_lookup'
|
|
18
18
|
import { useReportMessage } from '../hooks/use_report_message'
|
|
19
19
|
import { MessageResource } from '../types'
|
|
20
20
|
import { MessageReportReason } from '../types/resources/message_report'
|
|
@@ -51,8 +51,7 @@ export type MessageReportScreenProps = StaticScreenProps<{
|
|
|
51
51
|
export function MessageReportScreen({ route }: MessageReportScreenProps) {
|
|
52
52
|
const { conversation_id, message_id } = route.params
|
|
53
53
|
|
|
54
|
-
const
|
|
55
|
-
const message = messages.find(m => m.id === message_id)
|
|
54
|
+
const message = useConversationMessageLookup({ conversation_id, message_id })
|
|
56
55
|
|
|
57
56
|
if (!message) return null
|
|
58
57
|
|
|
@@ -7,7 +7,7 @@ import { Avatar, Text } from '../components'
|
|
|
7
7
|
import { Tabs } from '../components/display/tabs'
|
|
8
8
|
import FormSheet, { getFormSheetScreenOptions } from '../components/primitive/form_sheet'
|
|
9
9
|
import { useSuspenseGet, useTheme } from '../hooks'
|
|
10
|
-
import {
|
|
10
|
+
import { useConversationMessageLookup } from '../hooks/use_conversation_message_lookup'
|
|
11
11
|
import { useFontScale } from '../hooks/use_font_scale'
|
|
12
12
|
import { MemberResource } from '../types'
|
|
13
13
|
import { ReactionCountResource } from '../types/resources/reaction'
|
|
@@ -31,9 +31,7 @@ export function ReactionsScreen({ route }: ReactionScreenProps) {
|
|
|
31
31
|
const { conversation_id, message_id, reaction_value } = route.params
|
|
32
32
|
const styles = useStyles()
|
|
33
33
|
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
const message = messages.find(m => m.id === message_id)
|
|
34
|
+
const message = useConversationMessageLookup({ conversation_id, message_id })
|
|
37
35
|
const reactionCounts = message?.reactionCounts || []
|
|
38
36
|
const initialReactionCount =
|
|
39
37
|
reactionCounts.find(r => r.value === reaction_value) || reactionCounts[0]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { QueryClient } from '@tanstack/react-query'
|
|
2
|
+
import { getMessagesQueryKey } from '../../request/get_messages'
|
|
3
|
+
import { findMessageInCaches } from '../find_message_in_caches'
|
|
4
|
+
|
|
5
|
+
const page = (ids: string[]) => ({
|
|
6
|
+
data: ids.map(id => ({ id, type: 'Message' })),
|
|
7
|
+
links: {},
|
|
8
|
+
meta: { count: ids.length, totalCount: ids.length },
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
const seed = (queryClient: QueryClient, key: unknown[], ids: string[]) =>
|
|
12
|
+
queryClient.setQueryData(key, { pages: [page(ids)], pageParams: [{}] })
|
|
13
|
+
|
|
14
|
+
describe('findMessageInCaches', () => {
|
|
15
|
+
const queryClient = new QueryClient()
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
queryClient.clear()
|
|
19
|
+
seed(queryClient, getMessagesQueryKey({ conversation_id: 1 }), ['01C', '01B'])
|
|
20
|
+
seed(queryClient, getMessagesQueryKey({ conversation_id: 1, anchor: '01A' }), ['01A', '00Z'])
|
|
21
|
+
seed(queryClient, getMessagesQueryKey({ conversation_id: 1, reply_root_id: '01B' }), ['01R'])
|
|
22
|
+
seed(queryClient, getMessagesQueryKey({ conversation_id: 2 }), ['02A'])
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('finds a message in the live cache', () => {
|
|
26
|
+
expect(findMessageInCaches(queryClient, 1, '01B')?.id).toBe('01B')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('finds a message that only the anchored cache holds', () => {
|
|
30
|
+
expect(findMessageInCaches(queryClient, 1, '00Z')?.id).toBe('00Z')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('ignores reply threads and other conversations', () => {
|
|
34
|
+
expect(findMessageInCaches(queryClient, 1, '01R')).toBeUndefined()
|
|
35
|
+
expect(findMessageInCaches(queryClient, 1, '02A')).toBeUndefined()
|
|
36
|
+
})
|
|
37
|
+
})
|
|
@@ -5,31 +5,30 @@ const page = (ids: string[], next?: { idGt: string }) => ({
|
|
|
5
5
|
links: {},
|
|
6
6
|
meta: { count: ids.length, totalCount: ids.length, next },
|
|
7
7
|
})
|
|
8
|
-
const pageParam = { where: { id_gt: '01C' }, order: 'asc' }
|
|
9
8
|
|
|
10
9
|
describe('prependNewerPage', () => {
|
|
11
10
|
const cached = { pages: [page(['01C', '01B']), page(['01A'])], pageParams: [{}, { offset: 1 }] }
|
|
12
11
|
|
|
13
|
-
it('
|
|
14
|
-
const result = prependNewerPage(cached, page(['01C', '01D', '01E'])
|
|
12
|
+
it('merges the new rows into the first page and leaves the page params alone', () => {
|
|
13
|
+
const result = prependNewerPage(cached, [page(['01C', '01D', '01E'])])
|
|
15
14
|
|
|
16
|
-
expect(result?.pages
|
|
17
|
-
expect(result?.pages).
|
|
18
|
-
expect(result?.pageParams
|
|
15
|
+
expect(result?.pages).toHaveLength(2)
|
|
16
|
+
expect(result?.pages[0].data.map(m => m.id)).toEqual(['01D', '01E', '01C', '01B'])
|
|
17
|
+
expect(result?.pageParams).toEqual(cached.pageParams)
|
|
19
18
|
})
|
|
20
19
|
|
|
21
|
-
it('
|
|
22
|
-
|
|
23
|
-
})
|
|
20
|
+
it('merges every fetched batch, newest last', () => {
|
|
21
|
+
const result = prependNewerPage(cached, [page(['01D', '01E']), page(['01F'])])
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
expect(result?.pages[0].data.map(m => m.id)).toEqual(['01D', '01E', '01F', '01C', '01B'])
|
|
24
|
+
})
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
expect(
|
|
26
|
+
it('returns the same data when nothing new came back', () => {
|
|
27
|
+
expect(prependNewerPage(cached, [page(['01C'])])).toBe(cached)
|
|
28
|
+
expect(prependNewerPage(cached, [])).toBe(cached)
|
|
30
29
|
})
|
|
31
30
|
|
|
32
31
|
it('does nothing without cached data', () => {
|
|
33
|
-
expect(prependNewerPage(undefined, page(['01D'])
|
|
32
|
+
expect(prependNewerPage(undefined, [page(['01D'])])).toBeUndefined()
|
|
34
33
|
})
|
|
35
34
|
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { InfiniteData, QueryClient } from '@tanstack/react-query'
|
|
2
|
+
import { ApiCollection, MessageResource } from '../../types'
|
|
3
|
+
import { getMessagesRequestArgs } from '../request/get_messages'
|
|
4
|
+
|
|
5
|
+
type QueryData = InfiniteData<ApiCollection<MessageResource>>
|
|
6
|
+
|
|
7
|
+
export const findMessageInCaches = (
|
|
8
|
+
queryClient: QueryClient,
|
|
9
|
+
conversation_id: number,
|
|
10
|
+
message_id: string
|
|
11
|
+
): MessageResource | undefined => {
|
|
12
|
+
const { url } = getMessagesRequestArgs({ conversation_id })
|
|
13
|
+
|
|
14
|
+
for (const [, data] of queryClient.getQueriesData<QueryData>({ queryKey: [url] })) {
|
|
15
|
+
const found = data?.pages.flatMap(page => page.data).find(message => message.id === message_id)
|
|
16
|
+
if (found) return found
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return undefined
|
|
20
|
+
}
|
|
@@ -9,19 +9,16 @@ export function optimisticallyUpdateMessage({
|
|
|
9
9
|
message,
|
|
10
10
|
text,
|
|
11
11
|
replyRootId,
|
|
12
|
+
queryKey = getMessagesQueryKey({ conversation_id: conversationId, reply_root_id: replyRootId }),
|
|
12
13
|
}: {
|
|
13
14
|
conversationId: number
|
|
14
15
|
message: MessageResource
|
|
15
16
|
text: string
|
|
16
17
|
replyRootId?: string | null
|
|
18
|
+
queryKey?: unknown[]
|
|
17
19
|
}) {
|
|
18
20
|
type QueryData = InfiniteData<ApiCollection<MessageResource>>
|
|
19
21
|
|
|
20
|
-
const queryKey = getMessagesQueryKey({
|
|
21
|
-
conversation_id: conversationId,
|
|
22
|
-
reply_root_id: replyRootId,
|
|
23
|
-
})
|
|
24
|
-
|
|
25
22
|
let optimisticMessage = message
|
|
26
23
|
|
|
27
24
|
chatQueryClient.setQueryData<QueryData>(queryKey, data =>
|
|
@@ -6,17 +6,14 @@ type PagesData<T extends ResourceObject> = InfiniteData<ApiCollection<T>, Partia
|
|
|
6
6
|
|
|
7
7
|
export function prependNewerPage<T extends ResourceObject>(
|
|
8
8
|
data: PagesData<T> | undefined,
|
|
9
|
-
|
|
10
|
-
pageParam: Partial<RequestData>
|
|
9
|
+
pages: ApiCollection<T>[]
|
|
11
10
|
): PagesData<T> | undefined {
|
|
12
|
-
if (!data) return data
|
|
11
|
+
if (!data || data.pages.length === 0) return data
|
|
13
12
|
|
|
14
|
-
const knownIds = new Set(data.pages.flatMap(
|
|
15
|
-
const fresh = page.data.filter(record => !knownIds.has(record.id))
|
|
16
|
-
if (fresh.length === 0
|
|
13
|
+
const knownIds = new Set(data.pages.flatMap(page => page.data.map(record => record.id)))
|
|
14
|
+
const fresh = pages.flatMap(page => page.data).filter(record => !knownIds.has(record.id))
|
|
15
|
+
if (fresh.length === 0) return data
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
pageParams: [pageParam, ...data.pageParams],
|
|
21
|
-
}
|
|
17
|
+
const [first, ...rest] = data.pages
|
|
18
|
+
return { ...data, pages: [{ ...first, data: [...fresh, ...first.data] }, ...rest] }
|
|
22
19
|
}
|