@planningcenter/chat-react-native 4.2.1-qa-staging.5 → 4.2.1-rc.0
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 +1 -2
- package/build/components/conversation/message_form.d.ts.map +1 -1
- package/build/components/conversation/message_form.js +51 -54
- package/build/components/conversation/message_form.js.map +1 -1
- package/build/components/conversation/message_list.d.ts +2 -3
- package/build/components/conversation/message_list.d.ts.map +1 -1
- package/build/components/conversation/message_list.js +66 -152
- package/build/components/conversation/message_list.js.map +1 -1
- package/build/contexts/api_provider.d.ts.map +1 -1
- package/build/contexts/api_provider.js +1 -2
- package/build/contexts/api_provider.js.map +1 -1
- package/build/contexts/conversation_context.d.ts +1 -3
- package/build/contexts/conversation_context.d.ts.map +1 -1
- package/build/contexts/conversation_context.js +18 -23
- package/build/contexts/conversation_context.js.map +1 -1
- package/build/hooks/index.d.ts +0 -1
- package/build/hooks/index.d.ts.map +1 -1
- package/build/hooks/index.js +0 -1
- package/build/hooks/index.js.map +1 -1
- package/build/hooks/paginator_meta.d.ts +1 -3
- package/build/hooks/paginator_meta.d.ts.map +1 -1
- package/build/hooks/paginator_meta.js +8 -25
- package/build/hooks/paginator_meta.js.map +1 -1
- package/build/hooks/use_api.d.ts.map +1 -1
- package/build/hooks/use_api.js +8 -5
- package/build/hooks/use_api.js.map +1 -1
- package/build/hooks/use_conversation_messages.d.ts +2 -9
- package/build/hooks/use_conversation_messages.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages.js +45 -84
- package/build/hooks/use_conversation_messages.js.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.d.ts +1 -17
- package/build/hooks/use_conversation_messages_jolt_events.d.ts.map +1 -1
- package/build/hooks/use_conversation_messages_jolt_events.js +80 -89
- package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
- package/build/hooks/use_mark_latest_message_read.d.ts +1 -2
- package/build/hooks/use_mark_latest_message_read.d.ts.map +1 -1
- package/build/hooks/use_mark_latest_message_read.js +3 -4
- package/build/hooks/use_mark_latest_message_read.js.map +1 -1
- package/build/hooks/use_message_create_or_update.d.ts.map +1 -1
- package/build/hooks/use_message_create_or_update.js +80 -91
- 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 +40 -45
- package/build/hooks/use_message_reaction_toggle.js.map +1 -1
- package/build/hooks/use_suspense_api.d.ts.map +1 -1
- package/build/hooks/use_suspense_api.js +8 -5
- package/build/hooks/use_suspense_api.js.map +1 -1
- package/build/screens/conversation_new/components/services_form.js +8 -9
- package/build/screens/conversation_new/components/services_form.js.map +1 -1
- package/build/screens/conversation_screen.d.ts +0 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +254 -481
- 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 +26 -21
- 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 +44 -17
- 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 +88 -70
- package/build/screens/reactions_screen.js.map +1 -1
- package/build/types/api_primitives.d.ts +0 -2
- package/build/types/api_primitives.d.ts.map +1 -1
- package/build/types/api_primitives.js.map +1 -1
- package/build/types/resources/member.d.ts +0 -1
- package/build/types/resources/member.d.ts.map +1 -1
- package/build/types/resources/member.js.map +1 -1
- package/build/utils/cache/messages_cache.d.ts +0 -1
- package/build/utils/cache/messages_cache.d.ts.map +1 -1
- package/build/utils/cache/messages_cache.js +0 -3
- package/build/utils/cache/messages_cache.js.map +1 -1
- package/build/utils/cache/optimistically_update_message.d.ts +1 -2
- 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/client/types.d.ts +0 -1
- package/build/utils/client/types.d.ts.map +1 -1
- package/build/utils/client/types.js.map +1 -1
- package/build/utils/generate_placeholder_ulid.d.ts +6 -0
- package/build/utils/generate_placeholder_ulid.d.ts.map +1 -1
- package/build/utils/generate_placeholder_ulid.js +2 -2
- package/build/utils/generate_placeholder_ulid.js.map +1 -1
- package/build/utils/request/get_messages.d.ts +6 -18
- package/build/utils/request/get_messages.d.ts.map +1 -1
- package/build/utils/request/get_messages.js +12 -10
- package/build/utils/request/get_messages.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/hooks/paginator_meta.test.ts +2 -73
- package/src/components/conversation/__tests__/message_list.test.tsx +0 -42
- package/src/components/conversation/message_form.tsx +0 -3
- package/src/components/conversation/message_list.tsx +4 -58
- package/src/contexts/api_provider.tsx +1 -2
- package/src/contexts/conversation_context.tsx +1 -6
- package/src/hooks/index.ts +0 -1
- package/src/hooks/paginator_meta.ts +5 -29
- package/src/hooks/use_api.ts +5 -4
- package/src/hooks/use_conversation_messages.ts +11 -52
- package/src/hooks/use_conversation_messages_jolt_events.ts +43 -62
- package/src/hooks/use_mark_latest_message_read.ts +3 -4
- package/src/hooks/use_message_create_or_update.ts +8 -8
- package/src/hooks/use_message_reaction_toggle.ts +1 -3
- package/src/hooks/use_suspense_api.ts +5 -4
- package/src/screens/conversation_new/components/services_form.tsx +5 -5
- package/src/screens/conversation_screen.tsx +14 -123
- package/src/screens/message_actions_screen.tsx +5 -3
- package/src/screens/message_report_screen.tsx +3 -2
- package/src/screens/reactions_screen.tsx +4 -2
- package/src/types/api_primitives.ts +0 -2
- package/src/types/resources/member.ts +0 -1
- package/src/utils/cache/__tests__/messages_cache.test.ts +1 -14
- package/src/utils/cache/messages_cache.ts +0 -3
- package/src/utils/cache/optimistically_update_message.ts +5 -2
- package/src/utils/client/types.ts +0 -1
- package/src/utils/generate_placeholder_ulid.ts +2 -2
- package/src/utils/request/get_messages.ts +14 -12
- package/build/components/conversation/anchor_not_found_boundary.d.ts +0 -18
- package/build/components/conversation/anchor_not_found_boundary.d.ts.map +0 -1
- package/build/components/conversation/anchor_not_found_boundary.js +0 -20
- package/build/components/conversation/anchor_not_found_boundary.js.map +0 -1
- package/build/hooks/use_conversation_message_lookup.d.ts +0 -7
- package/build/hooks/use_conversation_message_lookup.d.ts.map +0 -1
- package/build/hooks/use_conversation_message_lookup.js +0 -52
- package/build/hooks/use_conversation_message_lookup.js.map +0 -1
- package/build/hooks/use_direct_message_eligibility.d.ts +0 -14
- package/build/hooks/use_direct_message_eligibility.d.ts.map +0 -1
- package/build/hooks/use_direct_message_eligibility.js +0 -87
- package/build/hooks/use_direct_message_eligibility.js.map +0 -1
- package/build/hooks/use_fetch_newer_messages.d.ts +0 -9
- package/build/hooks/use_fetch_newer_messages.d.ts.map +0 -1
- package/build/hooks/use_fetch_newer_messages.js +0 -69
- package/build/hooks/use_fetch_newer_messages.js.map +0 -1
- package/build/hooks/use_fetch_newer_on_foreground.d.ts +0 -8
- package/build/hooks/use_fetch_newer_on_foreground.d.ts.map +0 -1
- package/build/hooks/use_fetch_newer_on_foreground.js +0 -42
- package/build/hooks/use_fetch_newer_on_foreground.js.map +0 -1
- package/build/hooks/use_held_back_messages.d.ts +0 -11
- package/build/hooks/use_held_back_messages.d.ts.map +0 -1
- package/build/hooks/use_held_back_messages.js +0 -24
- package/build/hooks/use_held_back_messages.js.map +0 -1
- package/build/utils/cache/find_message_in_caches.d.ts +0 -4
- package/build/utils/cache/find_message_in_caches.d.ts.map +0 -1
- package/build/utils/cache/find_message_in_caches.js +0 -16
- package/build/utils/cache/find_message_in_caches.js.map +0 -1
- package/build/utils/cache/invalidate_refetchable_queries.d.ts +0 -3
- package/build/utils/cache/invalidate_refetchable_queries.d.ts.map +0 -1
- package/build/utils/cache/invalidate_refetchable_queries.js +0 -8
- package/build/utils/cache/invalidate_refetchable_queries.js.map +0 -1
- package/build/utils/cache/prepend_newer_page.d.ts +0 -7
- package/build/utils/cache/prepend_newer_page.d.ts.map +0 -1
- package/build/utils/cache/prepend_newer_page.js +0 -15
- package/build/utils/cache/prepend_newer_page.js.map +0 -1
- package/build/utils/gated_message_cache.d.ts +0 -7
- package/build/utils/gated_message_cache.d.ts.map +0 -1
- package/build/utils/gated_message_cache.js +0 -13
- package/build/utils/gated_message_cache.js.map +0 -1
- package/build/utils/ulid.d.ts +0 -3
- package/build/utils/ulid.d.ts.map +0 -1
- package/build/utils/ulid.js +0 -7
- package/build/utils/ulid.js.map +0 -1
- package/src/__tests__/hooks/use_conversation_messages.test.ts +0 -22
- package/src/__tests__/hooks/use_conversation_messages_jolt_events.test.ts +0 -33
- package/src/__tests__/hooks/use_direct_message_eligibility.test.tsx +0 -83
- package/src/__tests__/screens/conversation_new/components/services_form.test.tsx +0 -91
- package/src/__tests__/utils/gated_message_cache.test.ts +0 -26
- package/src/__tests__/utils/request/get_messages.test.ts +0 -24
- package/src/__tests__/utils/ulid.test.ts +0 -15
- package/src/components/conversation/__tests__/anchor_not_found_boundary.test.tsx +0 -51
- package/src/components/conversation/anchor_not_found_boundary.tsx +0 -21
- package/src/hooks/__tests__/use_fetch_newer_messages.test.tsx +0 -95
- package/src/hooks/__tests__/use_held_back_messages.test.tsx +0 -60
- package/src/hooks/__tests__/use_message_reaction_toggle.test.tsx +0 -73
- package/src/hooks/use_conversation_message_lookup.ts +0 -29
- package/src/hooks/use_direct_message_eligibility.ts +0 -40
- package/src/hooks/use_fetch_newer_messages.ts +0 -52
- package/src/hooks/use_fetch_newer_on_foreground.ts +0 -25
- package/src/hooks/use_held_back_messages.ts +0 -33
- package/src/utils/cache/__tests__/find_message_in_caches.test.ts +0 -37
- package/src/utils/cache/__tests__/invalidate_refetchable_queries.test.ts +0 -23
- package/src/utils/cache/__tests__/prepend_newer_page.test.ts +0 -34
- package/src/utils/cache/find_message_in_caches.ts +0 -20
- package/src/utils/cache/invalidate_refetchable_queries.ts +0 -9
- package/src/utils/cache/prepend_newer_page.ts +0 -19
- package/src/utils/gated_message_cache.ts +0 -19
- package/src/utils/ulid.ts +0 -11
package/src/hooks/use_api.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { ChatContext } from '../contexts/chat_context'
|
|
|
4
4
|
import { ApiCollection, ApiResource, ResourceObject } from '../types'
|
|
5
5
|
import { GetRequest, RequestData } from '../utils/client'
|
|
6
6
|
import { ResponseError, throwResponseError } from '../utils/response_error'
|
|
7
|
-
import { getNextPageParamFromMeta
|
|
7
|
+
import { getNextPageParamFromMeta } from './paginator_meta'
|
|
8
8
|
import { App, useApiClient } from './use_api_client'
|
|
9
9
|
import { getRequestQueryKey, RequestQueryKey } from './use_suspense_api'
|
|
10
10
|
|
|
@@ -61,11 +61,12 @@ export const useApiPaginator = <T extends ResourceObject>(
|
|
|
61
61
|
>({
|
|
62
62
|
queryKey: getRequestQueryKey(args),
|
|
63
63
|
queryFn: ({ pageParam }) => {
|
|
64
|
-
const
|
|
64
|
+
const pageParmWhere = pageParam?.where || {}
|
|
65
|
+
const argsWhere = args.data.where || {}
|
|
66
|
+
const where = { ...argsWhere, ...pageParmWhere }
|
|
65
67
|
const app = args.app || 'chat'
|
|
66
68
|
const offset = pageParam?.offset || args.data.offset
|
|
67
|
-
const
|
|
68
|
-
const data = { ...args.data, where, offset, order }
|
|
69
|
+
const data = { ...args.data, where, offset }
|
|
69
70
|
|
|
70
71
|
return apiClient[app].get<ApiCollection<T>>({ url: args.url, data }).catch(throwResponseError)
|
|
71
72
|
},
|
|
@@ -2,52 +2,21 @@ import { useMemo } from 'react'
|
|
|
2
2
|
import { MessageResource } from '../types'
|
|
3
3
|
import { replaceEqualById } from '../utils/replace_equal_by_id'
|
|
4
4
|
import { getMessagesQueryKey, getMessagesRequestArgs } from '../utils/request/get_messages'
|
|
5
|
-
import { ResponseError } from '../utils/response_error'
|
|
6
|
-
import { getNewerPageParam } from './paginator_meta'
|
|
7
5
|
import { SuspensePaginatorOptions, useSuspensePaginator } from './use_suspense_api'
|
|
8
6
|
|
|
9
|
-
type Options = {
|
|
10
|
-
conversation_id: number
|
|
11
|
-
reply_root_id?: string | null
|
|
12
|
-
anchor?: string | null
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const anchoredRetry = (failureCount: number, error: unknown) => {
|
|
16
|
-
const status = error instanceof ResponseError ? error.status : undefined
|
|
17
|
-
if (status === 404 || status === 429) return false
|
|
18
|
-
|
|
19
|
-
return failureCount < 3
|
|
20
|
-
}
|
|
21
|
-
|
|
22
7
|
export const useConversationMessages = (
|
|
23
|
-
{ conversation_id, reply_root_id
|
|
8
|
+
{ conversation_id, reply_root_id }: { conversation_id: number; reply_root_id?: string | null },
|
|
24
9
|
opts?: SuspensePaginatorOptions
|
|
25
10
|
) => {
|
|
26
|
-
const {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} = useSuspensePaginator<MessageResource>(
|
|
36
|
-
getMessagesRequestArgs({ conversation_id, reply_root_id, anchor }),
|
|
37
|
-
{
|
|
38
|
-
structuralSharing: replaceEqualById,
|
|
39
|
-
...(anchor
|
|
40
|
-
? {
|
|
41
|
-
getPreviousPageParam: (page, _pages, pageParam) => getNewerPageParam(page, pageParam),
|
|
42
|
-
gcTime: 0,
|
|
43
|
-
staleTime: Infinity,
|
|
44
|
-
retry: anchoredRetry,
|
|
45
|
-
}
|
|
46
|
-
: {}),
|
|
47
|
-
...opts,
|
|
48
|
-
}
|
|
49
|
-
)
|
|
50
|
-
const queryKey = getMessagesQueryKey({ conversation_id, reply_root_id, anchor })
|
|
11
|
+
const { data, refetch, isRefetching, fetchNextPage, hasNextPage } =
|
|
12
|
+
useSuspensePaginator<MessageResource>(
|
|
13
|
+
getMessagesRequestArgs({ conversation_id, reply_root_id }),
|
|
14
|
+
{
|
|
15
|
+
structuralSharing: replaceEqualById,
|
|
16
|
+
...opts,
|
|
17
|
+
}
|
|
18
|
+
)
|
|
19
|
+
const queryKey = getMessagesQueryKey({ conversation_id, reply_root_id })
|
|
51
20
|
const messages = useMemo(
|
|
52
21
|
() =>
|
|
53
22
|
data
|
|
@@ -60,15 +29,5 @@ export const useConversationMessages = (
|
|
|
60
29
|
[data]
|
|
61
30
|
)
|
|
62
31
|
|
|
63
|
-
return {
|
|
64
|
-
messages,
|
|
65
|
-
refetch,
|
|
66
|
-
isRefetching,
|
|
67
|
-
fetchNextPage,
|
|
68
|
-
hasNextPage,
|
|
69
|
-
fetchPreviousPage,
|
|
70
|
-
hasPreviousPage,
|
|
71
|
-
isFetchingPreviousPage,
|
|
72
|
-
queryKey,
|
|
73
|
-
}
|
|
32
|
+
return { messages, refetch, isRefetching, fetchNextPage, hasNextPage, queryKey }
|
|
74
33
|
}
|
|
@@ -12,69 +12,28 @@ import {
|
|
|
12
12
|
updateCacheWithIndividualMessage,
|
|
13
13
|
updateCacheWithReaction,
|
|
14
14
|
updateCacheReplyRoots,
|
|
15
|
+
getThreadedMessagesQueryKey,
|
|
15
16
|
} from '../utils/cache/messages_cache'
|
|
16
17
|
import { transformMessageEventDataToMessageResource } from '../utils/jolt/transform_message_event_data_to_message_resource'
|
|
17
18
|
import { completeMessageCreationTracking } from '../utils/performance_tracking'
|
|
18
19
|
import { getMessageQueryKey } from '../utils/request/get_message'
|
|
19
|
-
import {
|
|
20
|
+
import { getMessagesRequestArgs } from '../utils/request/get_messages'
|
|
20
21
|
import { useApiClient } from './use_api_client'
|
|
21
22
|
import { useCurrentPerson } from './use_current_person'
|
|
22
23
|
import { useJoltChannel, useJoltEvent } from './use_jolt'
|
|
24
|
+
import { getRequestQueryKey } from './use_suspense_api'
|
|
23
25
|
import { TYPING_TIMEOUT_INTERVAL, useTypingStatusCache } from './use_typing_status_cache'
|
|
24
26
|
|
|
25
|
-
export type MessagesJoltEvent =
|
|
26
|
-
| 'message.created'
|
|
27
|
-
| 'message.updated'
|
|
28
|
-
| 'message.destroyed'
|
|
29
|
-
| 'reaction'
|
|
30
|
-
|
|
31
|
-
export interface MessagesCache {
|
|
32
|
-
queryKey: unknown[]
|
|
33
|
-
canUpdate?: (event: MessagesJoltEvent) => boolean
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface MessagesView {
|
|
37
|
-
replyRootId: string | null
|
|
38
|
-
cache: MessagesCache
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
type MessageEventData = { sort_key: string; reply_root_id?: string | null }
|
|
42
|
-
|
|
43
27
|
interface Props {
|
|
44
28
|
conversationId: number
|
|
45
|
-
replyRootId?: string | null
|
|
46
|
-
messageCache?: MessagesCache
|
|
47
29
|
}
|
|
48
30
|
|
|
49
|
-
|
|
50
|
-
replyRootId === null || data.reply_root_id === replyRootId || data.sort_key === replyRootId
|
|
51
|
-
|
|
52
|
-
export const queryKeysForEvent = (
|
|
53
|
-
event: MessagesJoltEvent,
|
|
54
|
-
view: MessagesView,
|
|
55
|
-
data: MessageEventData
|
|
56
|
-
) => {
|
|
57
|
-
const accepted = !view.cache.canUpdate || view.cache.canUpdate(event)
|
|
58
|
-
return belongsToView(view.replyRootId, data) && accepted ? [view.cache.queryKey] : []
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function useConversationMessagesJoltEvents({
|
|
62
|
-
conversationId,
|
|
63
|
-
replyRootId = null,
|
|
64
|
-
messageCache,
|
|
65
|
-
}: Props) {
|
|
31
|
+
export function useConversationMessagesJoltEvents({ conversationId }: Props) {
|
|
66
32
|
const queryClient = useQueryClient()
|
|
67
33
|
const currentPerson = useCurrentPerson()
|
|
68
34
|
const joltChannel = useJoltChannel(`chat.conversations.${conversationId}`)
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
cache: messageCache ?? {
|
|
72
|
-
queryKey: getMessagesQueryKey({
|
|
73
|
-
conversation_id: conversationId,
|
|
74
|
-
reply_root_id: replyRootId,
|
|
75
|
-
}),
|
|
76
|
-
},
|
|
77
|
-
}
|
|
35
|
+
const messagesRequestArgs = getMessagesRequestArgs({ conversation_id: conversationId })
|
|
36
|
+
const messagesQueryKey = getRequestQueryKey(messagesRequestArgs)
|
|
78
37
|
const apiClient = useApiClient()
|
|
79
38
|
|
|
80
39
|
const { addTypingEvent, removeTypingEventById, removeAllTypingEventsByAuthorId } =
|
|
@@ -95,12 +54,21 @@ export function useConversationMessagesJoltEvents({
|
|
|
95
54
|
}
|
|
96
55
|
}
|
|
97
56
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
if (
|
|
103
|
-
|
|
57
|
+
// Update the main conversation cache
|
|
58
|
+
updateCacheWithMessage(queryClient, messagesQueryKey, message, e.event)
|
|
59
|
+
|
|
60
|
+
// If message has a reply_root_id, also update the threaded cache
|
|
61
|
+
if (data.reply_root_id) {
|
|
62
|
+
const threadedMessagesQueryKey = getThreadedMessagesQueryKey(
|
|
63
|
+
conversationId,
|
|
64
|
+
data.reply_root_id
|
|
65
|
+
)
|
|
66
|
+
updateCacheWithMessage(queryClient, threadedMessagesQueryKey, message, e.event)
|
|
67
|
+
|
|
68
|
+
if (isReplyRootUpdate) {
|
|
69
|
+
updateCacheReplyRoots(queryClient, messagesQueryKey, message)
|
|
70
|
+
updateCacheReplyRoots(queryClient, threadedMessagesQueryKey, message)
|
|
71
|
+
}
|
|
104
72
|
}
|
|
105
73
|
|
|
106
74
|
// Update individual message query cache so reply shadow messages update immediately
|
|
@@ -120,21 +88,34 @@ export function useConversationMessagesJoltEvents({
|
|
|
120
88
|
currentPersonId: currentPerson.id,
|
|
121
89
|
})
|
|
122
90
|
|
|
123
|
-
|
|
124
|
-
|
|
91
|
+
// Update the main conversation cache
|
|
92
|
+
queryClient.setQueryData<QueryData>(messagesQueryKey, prev =>
|
|
93
|
+
deleteRecordInPagesData({ data: prev, record: message })
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
// If message has a reply_root_id, also update the threaded cache
|
|
97
|
+
if (data.reply_root_id) {
|
|
98
|
+
const threadedMessagesQueryKey = getThreadedMessagesQueryKey(
|
|
99
|
+
conversationId,
|
|
100
|
+
data.reply_root_id
|
|
101
|
+
)
|
|
102
|
+
queryClient.setQueryData<QueryData>(threadedMessagesQueryKey, prev =>
|
|
125
103
|
deleteRecordInPagesData({ data: prev, record: message })
|
|
126
104
|
)
|
|
127
|
-
|
|
105
|
+
}
|
|
128
106
|
}
|
|
129
107
|
|
|
130
108
|
const handleReactionJoltEvent = async (e: JoltReactionEvent) => {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
109
|
+
// Update the main conversation cache and capture the reply_root_id if present
|
|
110
|
+
updateCacheWithReaction(queryClient, messagesQueryKey, e, currentPerson.id)
|
|
111
|
+
|
|
112
|
+
const replyRootId = e.data.data.reply_root_id
|
|
113
|
+
|
|
114
|
+
// If the message has a reply_root_id, also update the threaded cache
|
|
115
|
+
if (replyRootId) {
|
|
116
|
+
const threadedMessagesQueryKey = getThreadedMessagesQueryKey(conversationId, replyRootId)
|
|
117
|
+
updateCacheWithReaction(queryClient, threadedMessagesQueryKey, e, currentPerson.id)
|
|
134
118
|
}
|
|
135
|
-
queryKeysForEvent('reaction', view, data).forEach(queryKey =>
|
|
136
|
-
updateCacheWithReaction(queryClient, queryKey, e, currentPerson.id)
|
|
137
|
-
)
|
|
138
119
|
}
|
|
139
120
|
|
|
140
121
|
const handleTypingEvent = async (e: JoltTypingEvent) => {
|
|
@@ -7,10 +7,9 @@ import { useConversationsMarkRead } from './use_conversations_actions'
|
|
|
7
7
|
interface Props {
|
|
8
8
|
conversation: ConversationResource
|
|
9
9
|
messages: MessageResource[]
|
|
10
|
-
enabled?: boolean
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
export function useMarkLatestMessageRead({ conversation
|
|
12
|
+
export function useMarkLatestMessageRead({ conversation }: Props) {
|
|
14
13
|
const firedOnce = useRef<boolean>(false)
|
|
15
14
|
const { markRead } = useConversationsMarkRead({ conversation })
|
|
16
15
|
const debouncedMarkRead = useMemo(
|
|
@@ -25,10 +24,10 @@ export function useMarkLatestMessageRead({ conversation, enabled = true }: Props
|
|
|
25
24
|
const isActive = appState === 'active'
|
|
26
25
|
|
|
27
26
|
useEffect(() => {
|
|
28
|
-
if (!
|
|
27
|
+
if (!isActive || !shouldMarkRead) return
|
|
29
28
|
|
|
30
29
|
firedOnce.current = true
|
|
31
30
|
|
|
32
31
|
debouncedMarkRead(true)
|
|
33
|
-
}, [debouncedMarkRead,
|
|
32
|
+
}, [debouncedMarkRead, isActive, shouldMarkRead, unreadReaction])
|
|
34
33
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { InfiniteData, useMutation } from '@tanstack/react-query'
|
|
2
2
|
import { chatQueryClient } from '../contexts/api_provider'
|
|
3
|
-
import { useConversationContext } from '../contexts/conversation_context'
|
|
4
3
|
import { ApiCollection, ApiResource, MessageResource } from '../types'
|
|
5
4
|
import { DenormalizedAttachmentResourceForCreate } from '../types/resources/denormalized_attachment_resource_for_create'
|
|
6
5
|
import {
|
|
@@ -36,12 +35,6 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
|
|
|
36
35
|
const isEditing = !isNewMessage(message)
|
|
37
36
|
const apiClient = useApiClient()
|
|
38
37
|
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
|
|
45
38
|
|
|
46
39
|
const mutation = useMutation({
|
|
47
40
|
mutationFn: ({ text, attachments, idempotentKey }: ResolvedMessageMutationVariables) => {
|
|
@@ -86,7 +79,6 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
|
|
|
86
79
|
message,
|
|
87
80
|
text,
|
|
88
81
|
replyRootId,
|
|
89
|
-
queryKey,
|
|
90
82
|
})
|
|
91
83
|
|
|
92
84
|
return { message: optimisticMessage }
|
|
@@ -110,6 +102,10 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
|
|
|
110
102
|
|
|
111
103
|
// Add error to the optimistic message from the cache on error
|
|
112
104
|
if (optimisticMessage) {
|
|
105
|
+
const queryKey = getMessagesQueryKey({
|
|
106
|
+
conversation_id: conversationId,
|
|
107
|
+
reply_root_id: replyRootId,
|
|
108
|
+
})
|
|
113
109
|
chatQueryClient.setQueryData(
|
|
114
110
|
queryKey,
|
|
115
111
|
(data: InfiniteData<ApiCollection<MessageResource>> | undefined) =>
|
|
@@ -129,6 +125,10 @@ export function useMessageCreateOrUpdate({ conversationId, message, replyRootId
|
|
|
129
125
|
const { message: optimisticMessage } = context || {}
|
|
130
126
|
const updatedMessage = result.data
|
|
131
127
|
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,7 +1,6 @@
|
|
|
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'
|
|
5
4
|
import { ApiCollection, ApiResource, MessageResource } from '../types'
|
|
6
5
|
import { ReactionCountResource } from '../types/resources/reaction'
|
|
7
6
|
import { updateRecordInPagesData, REACTION_EMOJIS } from '../utils'
|
|
@@ -31,8 +30,7 @@ export function useMessageReactionToggle({
|
|
|
31
30
|
}: UseMessageReactionToggleProps) {
|
|
32
31
|
const apiClient = useApiClient()
|
|
33
32
|
const queryClient = useQueryClient()
|
|
34
|
-
const {
|
|
35
|
-
const queryKey = messagesQueryKey ?? getMessagesQueryKey({ conversation_id })
|
|
33
|
+
const queryKey = getMessagesQueryKey({ conversation_id })
|
|
36
34
|
const message_id = message.id
|
|
37
35
|
|
|
38
36
|
const toggleReaction = useCallback(
|
|
@@ -10,7 +10,7 @@ import { FailedResponse } from '../types/api_primitives'
|
|
|
10
10
|
import { Log } from '../utils'
|
|
11
11
|
import { GetRequest, RequestData } from '../utils/client'
|
|
12
12
|
import { throwResponseError } from '../utils/response_error'
|
|
13
|
-
import { getNextPageParamFromMeta
|
|
13
|
+
import { getNextPageParamFromMeta } from './paginator_meta'
|
|
14
14
|
import { App, useApiClient } from './use_api_client'
|
|
15
15
|
|
|
16
16
|
interface SuspenseGetOptions extends GetRequest {
|
|
@@ -65,11 +65,12 @@ export const useSuspensePaginator = <T extends ResourceObject>(
|
|
|
65
65
|
queryFn: ({ pageParam }) => {
|
|
66
66
|
Log.info('useSuspenseGet', { pageParam })
|
|
67
67
|
|
|
68
|
-
const
|
|
68
|
+
const pageParmWhere = pageParam?.where || {}
|
|
69
|
+
const argsWhere = args.data.where || {}
|
|
70
|
+
const where = { ...argsWhere, ...pageParmWhere }
|
|
69
71
|
const app = args.app || 'chat'
|
|
70
72
|
const offset = pageParam?.offset || args.data.offset
|
|
71
|
-
const
|
|
72
|
-
const data = { ...args.data, where, offset, order }
|
|
73
|
+
const data = { ...args.data, where, offset }
|
|
73
74
|
|
|
74
75
|
return apiClient[app]
|
|
75
76
|
.get<ApiCollection<T>>({
|
|
@@ -45,7 +45,6 @@ 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<boolean>(!!initialPlanId)
|
|
49
48
|
const initialState = useMemo(() => uniq(initialTeamIds) || [], [initialTeamIds]) // Uniq here because services can send duplicates in the teams_i_lead response.
|
|
50
49
|
const [selectedTeamIds, setSelectedTeamIds] = useState<number[]>(initialState)
|
|
51
50
|
|
|
@@ -53,7 +52,6 @@ export const ServicesForm = ({
|
|
|
53
52
|
useEffect(() => {
|
|
54
53
|
setSelectedTeamIds(initialState)
|
|
55
54
|
setSelectedPlanId(initialPlanId)
|
|
56
|
-
setFilterByPlan(!!initialPlanId)
|
|
57
55
|
}, [initialState, initialPlanId])
|
|
58
56
|
|
|
59
57
|
const removeSelection = useCallback(
|
|
@@ -63,7 +61,9 @@ export const ServicesForm = ({
|
|
|
63
61
|
[selectedTeamIds]
|
|
64
62
|
)
|
|
65
63
|
|
|
66
|
-
const
|
|
64
|
+
const [filerByPlan, setFilterByPlan] = useState(false)
|
|
65
|
+
|
|
66
|
+
const activePlanId = filerByPlan ? selectedPlanId : undefined
|
|
67
67
|
|
|
68
68
|
const { payload, isLoading: isLoadingPayload } = useServicesChatConversationPayload({
|
|
69
69
|
teamIds: selectedTeamIds,
|
|
@@ -79,7 +79,7 @@ export const ServicesForm = ({
|
|
|
79
79
|
|
|
80
80
|
const { members, isError: isMemberError } = useTeamMembersForNewConversation({
|
|
81
81
|
teamIds: selectedTeamIds,
|
|
82
|
-
planId:
|
|
82
|
+
planId: selectedPlanId,
|
|
83
83
|
})
|
|
84
84
|
const adultMembers = useMemo(() => members.filter(member => !member.child), [members])
|
|
85
85
|
|
|
@@ -118,7 +118,7 @@ export const ServicesForm = ({
|
|
|
118
118
|
removeSelection={removeSelection}
|
|
119
119
|
selectedPlanId={selectedPlanId}
|
|
120
120
|
setSelectedPlanId={setSelectedPlanId}
|
|
121
|
-
filterByPlan={
|
|
121
|
+
filterByPlan={filerByPlan}
|
|
122
122
|
setFilterByPlan={setFilterByPlan}
|
|
123
123
|
members={members}
|
|
124
124
|
isMemberError={isMemberError}
|
|
@@ -7,11 +7,10 @@ import {
|
|
|
7
7
|
useTheme as useNavigationTheme,
|
|
8
8
|
useRoute,
|
|
9
9
|
} from '@react-navigation/native'
|
|
10
|
-
import React, {
|
|
10
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
|
11
11
|
import { FlatList, Platform, StyleSheet, useWindowDimensions, View } from 'react-native'
|
|
12
12
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
13
13
|
import { Badge, Icon } from '../components'
|
|
14
|
-
import { AnchorNotFoundBoundary } from '../components/conversation/anchor_not_found_boundary'
|
|
15
14
|
import { ConversationStartBanner } from '../components/conversation/conversation_start_banner'
|
|
16
15
|
import { JumpToBottomButton } from '../components/conversation/jump_to_bottom_button'
|
|
17
16
|
import { MessageForm } from '../components/conversation/message_form'
|
|
@@ -31,9 +30,6 @@ import { useConversation } from '../hooks/use_conversation'
|
|
|
31
30
|
import { useConversationJoltEvents } from '../hooks/use_conversation_jolt_events'
|
|
32
31
|
import { useConversationMessages } from '../hooks/use_conversation_messages'
|
|
33
32
|
import { useConversationMessagesJoltEvents } from '../hooks/use_conversation_messages_jolt_events'
|
|
34
|
-
import { useFetchNewerMessages } from '../hooks/use_fetch_newer_messages'
|
|
35
|
-
import { useFetchNewerOnForeground } from '../hooks/use_fetch_newer_on_foreground'
|
|
36
|
-
import { useHeldBackMessages } from '../hooks/use_held_back_messages'
|
|
37
33
|
import { useMarkLatestMessageRead } from '../hooks/use_mark_latest_message_read'
|
|
38
34
|
import {
|
|
39
35
|
analyticsEvents,
|
|
@@ -45,10 +41,6 @@ import { useVideoModerationJoltEvents } from '../hooks/use_video_moderation_jolt
|
|
|
45
41
|
import { ConversationResource } from '../types/resources/conversation'
|
|
46
42
|
import { ConversationBadgeResource } from '../types/resources/conversation_badge'
|
|
47
43
|
import { MessageResource } from '../types/resources/message'
|
|
48
|
-
import { newestPersistedMessageId } from '../utils/cache/messages_cache'
|
|
49
|
-
import { gatedMessageCache } from '../utils/gated_message_cache'
|
|
50
|
-
import { getMessagesQueryKey } from '../utils/request/get_messages'
|
|
51
|
-
import { decodeUlidTime } from '../utils/ulid'
|
|
52
44
|
|
|
53
45
|
export type ConversationRouteProps = {
|
|
54
46
|
conversation_id: number
|
|
@@ -57,7 +49,6 @@ export type ConversationRouteProps = {
|
|
|
57
49
|
chat_group_graph_id?: string
|
|
58
50
|
clear_input?: boolean
|
|
59
51
|
editing_message_id?: number | null
|
|
60
|
-
initial_message_id?: string | null
|
|
61
52
|
title?: string
|
|
62
53
|
subtitle?: string
|
|
63
54
|
badge?: ConversationBadgeResource
|
|
@@ -68,16 +59,9 @@ export type ConversationRouteProps = {
|
|
|
68
59
|
export type ConversationScreenProps = StaticScreenProps<ConversationRouteProps>
|
|
69
60
|
|
|
70
61
|
export function ConversationScreen({ route }: ConversationScreenProps) {
|
|
71
|
-
const { conversation_id, reply_root_id
|
|
62
|
+
const { conversation_id, reply_root_id } = route.params
|
|
72
63
|
|
|
73
64
|
const { data: conversation } = useConversation({ conversation_id })
|
|
74
|
-
const [anchor, setAnchor] = useState(() =>
|
|
75
|
-
isBeforeLatestMessage(initial_message_id, conversation?.lastMessageCreatedAt)
|
|
76
|
-
? initial_message_id
|
|
77
|
-
: null
|
|
78
|
-
)
|
|
79
|
-
const exitAnchoredMode = useCallback(() => startTransition(() => setAnchor(null)), [])
|
|
80
|
-
const dropAnchor = useCallback(() => setAnchor(null), [])
|
|
81
65
|
|
|
82
66
|
usePublishProductAnalyticsEvent(analyticsEvents.conversation_show_opened, {
|
|
83
67
|
reply_root_id,
|
|
@@ -88,83 +72,27 @@ export function ConversationScreen({ route }: ConversationScreenProps) {
|
|
|
88
72
|
<ConversationContextProvider
|
|
89
73
|
conversationId={conversation_id}
|
|
90
74
|
currentPageReplyRootId={reply_root_id ?? null}
|
|
91
|
-
messagesQueryKey={getMessagesQueryKey({ conversation_id, reply_root_id, anchor })}
|
|
92
75
|
>
|
|
93
|
-
{
|
|
94
|
-
<AnchorNotFoundBoundary onAnchorNotFound={dropAnchor}>
|
|
95
|
-
<ConversationScreenContent
|
|
96
|
-
route={route}
|
|
97
|
-
anchor={anchor}
|
|
98
|
-
onExitAnchoredMode={exitAnchoredMode}
|
|
99
|
-
/>
|
|
100
|
-
</AnchorNotFoundBoundary>
|
|
101
|
-
) : (
|
|
102
|
-
<ConversationScreenContent
|
|
103
|
-
route={route}
|
|
104
|
-
anchor={null}
|
|
105
|
-
onExitAnchoredMode={exitAnchoredMode}
|
|
106
|
-
/>
|
|
107
|
-
)}
|
|
76
|
+
<ConversationScreenContent route={route} />
|
|
108
77
|
</ConversationContextProvider>
|
|
109
78
|
)
|
|
110
79
|
}
|
|
111
80
|
|
|
112
|
-
|
|
113
|
-
anchor: string | null | undefined
|
|
114
|
-
onExitAnchoredMode: () => void
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function ConversationScreenContent({
|
|
118
|
-
route,
|
|
119
|
-
anchor,
|
|
120
|
-
onExitAnchoredMode,
|
|
121
|
-
}: ConversationScreenContentProps) {
|
|
81
|
+
function ConversationScreenContent({ route }: ConversationScreenProps) {
|
|
122
82
|
const styles = useStyles()
|
|
123
83
|
const navigation = useNavigation()
|
|
124
84
|
const { conversation_id, editing_message_id, reply_root_id, reply_root_author_name } =
|
|
125
85
|
route.params
|
|
126
86
|
const { data: conversation } = useConversation(route.params)
|
|
127
|
-
const
|
|
128
|
-
const {
|
|
129
|
-
messages,
|
|
130
|
-
fetchNextPage,
|
|
131
|
-
hasNextPage,
|
|
132
|
-
fetchPreviousPage,
|
|
133
|
-
hasPreviousPage,
|
|
134
|
-
isFetchingPreviousPage,
|
|
135
|
-
queryKey,
|
|
136
|
-
} = useConversationMessages({ conversation_id, reply_root_id, anchor })
|
|
137
|
-
const behindLatest = anchored && hasPreviousPage
|
|
138
|
-
const caughtUp = !hasPreviousPage
|
|
139
|
-
const [showJumpToBottomButton, setShowJumpToBottomButton] = useState(false)
|
|
140
|
-
const readingHistory = showJumpToBottomButton
|
|
141
|
-
const newestMessageId = newestPersistedMessageId(messages)
|
|
142
|
-
const fetchNewer = useFetchNewerMessages({
|
|
87
|
+
const { messages, fetchNextPage, hasNextPage } = useConversationMessages({
|
|
143
88
|
conversation_id,
|
|
144
89
|
reply_root_id,
|
|
145
|
-
queryKey,
|
|
146
|
-
onTooFarBehind: anchored ? onExitAnchoredMode : undefined,
|
|
147
|
-
})
|
|
148
|
-
const { onSkippedNewMessage } = useHeldBackMessages({
|
|
149
|
-
fetchNewer,
|
|
150
|
-
newestMessageId,
|
|
151
|
-
readingHistory,
|
|
152
|
-
caughtUp,
|
|
153
90
|
})
|
|
154
91
|
useConversationJoltEvents({ conversationId: conversation_id })
|
|
155
|
-
useConversationMessagesJoltEvents({
|
|
156
|
-
conversationId: conversation_id,
|
|
157
|
-
replyRootId: reply_root_id ?? null,
|
|
158
|
-
messageCache: gatedMessageCache({
|
|
159
|
-
queryKey,
|
|
160
|
-
acceptNewMessages: caughtUp && !readingHistory,
|
|
161
|
-
onSkippedNewMessage,
|
|
162
|
-
}),
|
|
163
|
-
})
|
|
92
|
+
useConversationMessagesJoltEvents({ conversationId: conversation_id })
|
|
164
93
|
const { markHandledByMessageForm } = useVideoModerationJoltEvents()
|
|
165
94
|
useEnsureConversationsRouteExists()
|
|
166
|
-
useMarkLatestMessageRead({ conversation, messages
|
|
167
|
-
useFetchNewerOnForeground({ fetchNewer, newestMessageId, enabled: anchored && caughtUp })
|
|
95
|
+
useMarkLatestMessageRead({ conversation, messages })
|
|
168
96
|
const noMessages = messages.length === 0
|
|
169
97
|
|
|
170
98
|
const { repliesDisabled, memberAbility, badges, title } = conversation
|
|
@@ -179,8 +107,12 @@ function ConversationScreenContent({
|
|
|
179
107
|
const muted = conversation.conversationMembership?.muted ?? conversation.muted
|
|
180
108
|
|
|
181
109
|
const listRef = useRef<FlatList>(null)
|
|
182
|
-
const [
|
|
183
|
-
|
|
110
|
+
const [showJumpToBottomButton, setShowJumpToBottomButton] = useState(false)
|
|
111
|
+
|
|
112
|
+
const trackScroll = (event: any) => {
|
|
113
|
+
const offsetY = event.nativeEvent.contentOffset.y
|
|
114
|
+
setShowJumpToBottomButton(offsetY > 200)
|
|
115
|
+
}
|
|
184
116
|
|
|
185
117
|
const { restOffset, onLayout, onContentSizeChange, onMomentumScrollEnd, onScrollEndDrag } =
|
|
186
118
|
useRestAwayFromDismissEdge({
|
|
@@ -194,28 +126,6 @@ function ConversationScreenContent({
|
|
|
194
126
|
})
|
|
195
127
|
}, [restOffset])
|
|
196
128
|
|
|
197
|
-
const exitAnchoredMode = useCallback(() => {
|
|
198
|
-
onExitAnchoredMode()
|
|
199
|
-
handleReturnToBottom()
|
|
200
|
-
}, [handleReturnToBottom, onExitAnchoredMode])
|
|
201
|
-
const jumpToLatest = useCallback(() => {
|
|
202
|
-
setShowJumpToBottomButton(false)
|
|
203
|
-
if (anchored) exitAnchoredMode()
|
|
204
|
-
else handleReturnToBottom()
|
|
205
|
-
}, [anchored, exitAnchoredMode, handleReturnToBottom])
|
|
206
|
-
|
|
207
|
-
const trackScroll = (event: any) => {
|
|
208
|
-
const offsetY = event.nativeEvent.contentOffset.y
|
|
209
|
-
setShowJumpToBottomButton(offsetY > 200)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const loadNewerMessages = () => {
|
|
213
|
-
if (!hasPreviousPage || isFetchingPreviousPage) return
|
|
214
|
-
|
|
215
|
-
setHasDragged(false)
|
|
216
|
-
fetchPreviousPage()
|
|
217
|
-
}
|
|
218
|
-
|
|
219
129
|
useEffect(() => {
|
|
220
130
|
if (reply_root_id) {
|
|
221
131
|
navigation.setParams({
|
|
@@ -264,7 +174,6 @@ function ConversationScreenContent({
|
|
|
264
174
|
conversationId={conversation_id}
|
|
265
175
|
messages={messages}
|
|
266
176
|
replyRootId={reply_root_id}
|
|
267
|
-
anchorMessageId={anchor}
|
|
268
177
|
hasNextPage={hasNextPage}
|
|
269
178
|
onEndReached={() => fetchNextPage()}
|
|
270
179
|
onScroll={trackScroll}
|
|
@@ -272,18 +181,9 @@ function ConversationScreenContent({
|
|
|
272
181
|
onContentSizeChange={onContentSizeChange}
|
|
273
182
|
onScrollEndDrag={onScrollEndDrag}
|
|
274
183
|
onMomentumScrollEnd={onMomentumScrollEnd}
|
|
275
|
-
onScrollBeginDrag={anchored ? () => setHasDragged(true) : undefined}
|
|
276
|
-
onStartReached={anchored && hasDragged ? loadNewerMessages : undefined}
|
|
277
|
-
onStartReachedThreshold={anchored ? 0.5 : undefined}
|
|
278
|
-
maintainVisibleContentPosition={
|
|
279
|
-
holdListPosition ? { minIndexForVisible: 0 } : undefined
|
|
280
|
-
}
|
|
281
184
|
/>
|
|
282
185
|
)}
|
|
283
|
-
<JumpToBottomButton
|
|
284
|
-
onPress={jumpToLatest}
|
|
285
|
-
visible={behindLatest || showJumpToBottomButton}
|
|
286
|
-
/>
|
|
186
|
+
<JumpToBottomButton onPress={handleReturnToBottom} visible={showJumpToBottomButton} />
|
|
287
187
|
{!noMessages && <TypingIndicator />}
|
|
288
188
|
{showLeaderDisabledReplyBanner && <LeaderMessagesDisabledBanner />}
|
|
289
189
|
<ConversationBottomBar
|
|
@@ -293,7 +193,6 @@ function ConversationScreenContent({
|
|
|
293
193
|
replyRootId={reply_root_id}
|
|
294
194
|
currentlyEditingMessage={currentlyEditingMessage}
|
|
295
195
|
onFlaggedInMessageForm={markHandledByMessageForm}
|
|
296
|
-
onBeforeSubmit={jumpToLatest}
|
|
297
196
|
/>
|
|
298
197
|
</KeyboardView>
|
|
299
198
|
</View>
|
|
@@ -307,7 +206,6 @@ interface ConversationBottomBarProps {
|
|
|
307
206
|
replyRootId: string | null | undefined
|
|
308
207
|
currentlyEditingMessage: MessageResource | undefined
|
|
309
208
|
onFlaggedInMessageForm?: (id: string) => void
|
|
310
|
-
onBeforeSubmit?: () => void
|
|
311
209
|
}
|
|
312
210
|
|
|
313
211
|
function ConversationBottomBar({
|
|
@@ -317,7 +215,6 @@ function ConversationBottomBar({
|
|
|
317
215
|
replyRootId,
|
|
318
216
|
currentlyEditingMessage,
|
|
319
217
|
onFlaggedInMessageForm,
|
|
320
|
-
onBeforeSubmit,
|
|
321
218
|
}: ConversationBottomBarProps) {
|
|
322
219
|
const messageLink = useMessageAvailableMembersAction(conversation)
|
|
323
220
|
|
|
@@ -336,7 +233,6 @@ function ConversationBottomBar({
|
|
|
336
233
|
replyRootId={replyRootId}
|
|
337
234
|
currentlyEditingMessage={currentlyEditingMessage}
|
|
338
235
|
onFlaggedInMessageForm={onFlaggedInMessageForm}
|
|
339
|
-
onBeforeSubmit={onBeforeSubmit}
|
|
340
236
|
key={
|
|
341
237
|
currentlyEditingMessage
|
|
342
238
|
? `edit-message-form-${currentlyEditingMessage.id}`
|
|
@@ -351,11 +247,6 @@ function ConversationBottomBar({
|
|
|
351
247
|
)
|
|
352
248
|
}
|
|
353
249
|
|
|
354
|
-
const isBeforeLatestMessage = (anchor?: string | null, latestMessageCreatedAt?: string) =>
|
|
355
|
-
!!anchor &&
|
|
356
|
-
!!latestMessageCreatedAt &&
|
|
357
|
-
decodeUlidTime(anchor) < Date.parse(latestMessageCreatedAt)
|
|
358
|
-
|
|
359
250
|
interface ConversationScreenTitleProps extends HeaderTitleProps {
|
|
360
251
|
conversation_id: number
|
|
361
252
|
badge?: ConversationBadgeResource
|