@planningcenter/chat-react-native 3.41.0 → 3.41.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/page/page_error_boundary.d.ts.map +1 -1
- package/build/components/page/page_error_boundary.js +29 -1
- package/build/components/page/page_error_boundary.js.map +1 -1
- package/build/contexts/api_provider.d.ts.map +1 -1
- package/build/contexts/api_provider.js +12 -2
- package/build/contexts/api_provider.js.map +1 -1
- package/build/contexts/conversations_context.d.ts +3 -1
- package/build/contexts/conversations_context.d.ts.map +1 -1
- package/build/contexts/conversations_context.js +2 -2
- package/build/contexts/conversations_context.js.map +1 -1
- package/build/hooks/services/use_team_members_for_new_conversation.d.ts +14 -14
- package/build/hooks/use_api.d.ts +48 -47
- package/build/hooks/use_api.d.ts.map +1 -1
- package/build/hooks/use_api.js +8 -10
- package/build/hooks/use_api.js.map +1 -1
- package/build/hooks/use_chat_permissions.d.ts +14 -14
- package/build/hooks/use_conversation_message.d.ts.map +1 -1
- package/build/hooks/use_conversation_message.js +1 -4
- package/build/hooks/use_conversation_message.js.map +1 -1
- package/build/hooks/use_conversations.d.ts +4 -2
- package/build/hooks/use_conversations.d.ts.map +1 -1
- package/build/hooks/use_conversations.js +2 -2
- package/build/hooks/use_conversations.js.map +1 -1
- package/build/hooks/use_groups.d.ts +26 -26
- package/build/hooks/use_groups_groups.d.ts +26 -26
- package/build/hooks/use_my_gender.d.ts.map +1 -1
- package/build/hooks/use_my_gender.js +1 -2
- package/build/hooks/use_my_gender.js.map +1 -1
- package/build/hooks/use_new_conversation_from_filter.js +2 -8
- package/build/hooks/use_new_conversation_from_filter.js.map +1 -1
- package/build/hooks/use_people_person.d.ts.map +1 -1
- package/build/hooks/use_people_person.js +1 -2
- package/build/hooks/use_people_person.js.map +1 -1
- package/build/hooks/use_teams.d.ts +26 -26
- package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.d.ts +14 -14
- package/build/screens/conversation_filters/hooks/filters.d.ts +40 -40
- package/build/screens/conversations/components/chat_group_badge.d.ts.map +1 -1
- package/build/screens/conversations/components/chat_group_badge.js +1 -10
- package/build/screens/conversations/components/chat_group_badge.js.map +1 -1
- package/build/screens/conversations/conversations_screen.js +1 -1
- package/build/screens/conversations/conversations_screen.js.map +1 -1
- package/build/utils/performance_tracking.js +2 -0
- package/build/utils/performance_tracking.js.map +1 -1
- package/build/utils/uri.d.ts +1 -1
- package/package.json +2 -2
- package/src/__tests__/hooks/use_api.test.tsx +11 -0
- package/src/components/page/page_error_boundary.tsx +46 -1
- package/src/contexts/api_provider.tsx +16 -2
- package/src/contexts/conversations_context.tsx +19 -7
- package/src/hooks/use_api.ts +18 -27
- package/src/hooks/use_conversation_message.ts +1 -4
- package/src/hooks/use_conversations.ts +8 -4
- package/src/hooks/use_my_gender.ts +12 -10
- package/src/hooks/use_new_conversation_from_filter.ts +12 -12
- package/src/hooks/use_people_person.ts +12 -10
- package/src/screens/conversations/components/chat_group_badge.tsx +4 -10
- package/src/screens/conversations/conversations_screen.tsx +1 -1
- package/src/utils/performance_tracking.ts +2 -0
|
@@ -4,9 +4,11 @@ import {
|
|
|
4
4
|
InfiniteData,
|
|
5
5
|
} from '@tanstack/react-query'
|
|
6
6
|
import React, { createContext, PropsWithChildren, useContext, useMemo, useState } from 'react'
|
|
7
|
+
import { ApiGetQueryOptions } from '../hooks'
|
|
7
8
|
import { useConversations, UseConversationsValue } from '../hooks/use_conversations'
|
|
8
9
|
import { ConversationFiltersParams } from '../screens/conversation_filters/screen_props'
|
|
9
10
|
import { ApiCollection, ConversationResource } from '../types'
|
|
11
|
+
import { ResponseError } from '../utils/response_error'
|
|
10
12
|
|
|
11
13
|
interface ConversationsContextValue extends UseConversationsValue {
|
|
12
14
|
activeConversationId?: number
|
|
@@ -37,15 +39,22 @@ const ConversationsContext = createContext<ConversationsContextValue>({
|
|
|
37
39
|
export const ConversationsContextProvider = ({
|
|
38
40
|
children,
|
|
39
41
|
args = {},
|
|
40
|
-
|
|
42
|
+
opts: paginatorOptions,
|
|
43
|
+
}: PropsWithChildren<{
|
|
44
|
+
args: ConversationFiltersParams
|
|
45
|
+
opts?: ApiGetQueryOptions
|
|
46
|
+
}>) => {
|
|
41
47
|
const [activeConversationId, setActiveConversationId] = useState<number | undefined>()
|
|
42
48
|
const { chat_group_graph_id, group_source_app_name, show_direct_messages } = args
|
|
43
49
|
|
|
44
|
-
const query = useConversations(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
const query = useConversations(
|
|
51
|
+
{
|
|
52
|
+
chat_group_graph_id,
|
|
53
|
+
group_source_app_name,
|
|
54
|
+
show_direct_messages,
|
|
55
|
+
},
|
|
56
|
+
paginatorOptions
|
|
57
|
+
)
|
|
49
58
|
|
|
50
59
|
const value = useMemo(
|
|
51
60
|
() => ({
|
|
@@ -63,7 +72,10 @@ export const ConversationsContextProvider = ({
|
|
|
63
72
|
function fetchNextPage(
|
|
64
73
|
_options?: FetchNextPageOptions
|
|
65
74
|
): Promise<
|
|
66
|
-
InfiniteQueryObserverResult<
|
|
75
|
+
InfiniteQueryObserverResult<
|
|
76
|
+
InfiniteData<ApiCollection<ConversationResource>, unknown>,
|
|
77
|
+
ResponseError
|
|
78
|
+
>
|
|
67
79
|
> {
|
|
68
80
|
throw new Error('Function not implemented.')
|
|
69
81
|
}
|
package/src/hooks/use_api.ts
CHANGED
|
@@ -1,66 +1,60 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AnyUseSuspenseInfiniteQueryOptions,
|
|
3
|
-
InfiniteData,
|
|
4
|
-
useInfiniteQuery,
|
|
5
|
-
useQuery,
|
|
6
|
-
} from '@tanstack/react-query'
|
|
1
|
+
import { InfiniteData, useInfiniteQuery, useQuery } from '@tanstack/react-query'
|
|
7
2
|
import { useContext } from 'react'
|
|
8
3
|
import { ChatContext } from '../contexts/chat_context'
|
|
9
|
-
import { ApiCollection, ApiResource,
|
|
4
|
+
import { ApiCollection, ApiResource, ResourceObject } from '../types'
|
|
10
5
|
import { GetRequest, RequestData } from '../utils/client'
|
|
6
|
+
import { ResponseError, throwResponseError } from '../utils/response_error'
|
|
11
7
|
import { getNextPageParamFromMeta } from './paginator_meta'
|
|
12
8
|
import { App, useApiClient } from './use_api_client'
|
|
13
9
|
import { getRequestQueryKey, RequestQueryKey } from './use_suspense_api'
|
|
14
10
|
|
|
15
11
|
interface ApiGetOptions extends GetRequest {
|
|
16
12
|
app?: App
|
|
17
|
-
enabled?: boolean
|
|
18
13
|
}
|
|
19
14
|
|
|
20
|
-
type
|
|
15
|
+
export type ApiGetQueryOptions = {
|
|
21
16
|
staleTime?: number
|
|
22
17
|
gcTime?: number
|
|
18
|
+
enabled?: boolean
|
|
19
|
+
throwOnError?: boolean | ((error: ResponseError) => boolean)
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
export const useApiGet = <T extends ResourceObject | ResourceObject[]>(
|
|
26
23
|
args: ApiGetOptions,
|
|
27
|
-
opts?:
|
|
24
|
+
opts?: ApiGetQueryOptions
|
|
28
25
|
) => {
|
|
29
26
|
type Resource = ApiResource<T>
|
|
30
27
|
const { session } = useContext(ChatContext)
|
|
31
28
|
const apiClient = useApiClient()
|
|
32
29
|
|
|
33
|
-
const enabled = !!session.token?.access_token && (
|
|
30
|
+
const enabled = !!session.token?.access_token && (opts?.enabled ?? true)
|
|
34
31
|
|
|
35
|
-
const { data, ...query } = useQuery<Resource,
|
|
32
|
+
const { data, ...query } = useQuery<Resource, ResponseError>({
|
|
36
33
|
queryKey: getRequestQueryKey(args),
|
|
37
34
|
queryFn: ({ queryKey }) => {
|
|
38
35
|
const [url, d, headers, app = 'chat'] = queryKey as RequestQueryKey
|
|
39
36
|
|
|
40
|
-
return apiClient[app].get({ url, data: d, headers }) as Promise<Resource>
|
|
37
|
+
return (apiClient[app].get({ url, data: d, headers }) as Promise<Resource>).catch(
|
|
38
|
+
throwResponseError
|
|
39
|
+
)
|
|
41
40
|
},
|
|
42
|
-
enabled,
|
|
43
41
|
...opts,
|
|
42
|
+
enabled,
|
|
44
43
|
})
|
|
45
44
|
|
|
46
45
|
return { ...data, ...query }
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
export type PaginatorOptions = Omit<
|
|
50
|
-
AnyUseSuspenseInfiniteQueryOptions,
|
|
51
|
-
'getNextPageParam' | 'initialPageParam' | 'queryFn' | 'queryKey'
|
|
52
|
-
>
|
|
53
|
-
|
|
54
48
|
export const useApiPaginator = <T extends ResourceObject>(
|
|
55
49
|
args: ApiGetOptions,
|
|
56
|
-
opts?:
|
|
50
|
+
opts?: ApiGetQueryOptions
|
|
57
51
|
) => {
|
|
58
52
|
const { session } = useContext(ChatContext)
|
|
59
53
|
const apiClient = useApiClient()
|
|
60
|
-
const enabled = !!session.token?.access_token && (
|
|
54
|
+
const enabled = !!session.token?.access_token && (opts?.enabled ?? true)
|
|
61
55
|
const query = useInfiniteQuery<
|
|
62
56
|
ApiCollection<T>,
|
|
63
|
-
|
|
57
|
+
ResponseError,
|
|
64
58
|
InfiniteData<ApiCollection<T>>,
|
|
65
59
|
any,
|
|
66
60
|
Partial<RequestData> | undefined
|
|
@@ -74,15 +68,12 @@ export const useApiPaginator = <T extends ResourceObject>(
|
|
|
74
68
|
const offset = pageParam?.offset || args.data.offset
|
|
75
69
|
const data = { ...args.data, where, offset }
|
|
76
70
|
|
|
77
|
-
return apiClient[app].get<ApiCollection<T>>({
|
|
78
|
-
url: args.url,
|
|
79
|
-
data,
|
|
80
|
-
})
|
|
71
|
+
return apiClient[app].get<ApiCollection<T>>({ url: args.url, data }).catch(throwResponseError)
|
|
81
72
|
},
|
|
82
73
|
initialPageParam: {} as Partial<RequestData>,
|
|
83
74
|
getNextPageParam: lastPage => getNextPageParamFromMeta(lastPage.meta?.next),
|
|
84
|
-
enabled,
|
|
85
75
|
...(opts || {}),
|
|
76
|
+
enabled,
|
|
86
77
|
})
|
|
87
78
|
|
|
88
79
|
const data: T[] = query.data?.pages?.flatMap(page => page.data) || []
|
|
@@ -15,10 +15,7 @@ export const useConversationMessage = ({
|
|
|
15
15
|
data: message,
|
|
16
16
|
isError,
|
|
17
17
|
isLoading,
|
|
18
|
-
} = useApiGet<MessageResource>({
|
|
19
|
-
...getMessageRequestArgs({ conversation_id, messageId }),
|
|
20
|
-
enabled,
|
|
21
|
-
})
|
|
18
|
+
} = useApiGet<MessageResource>(getMessageRequestArgs({ conversation_id, messageId }), { enabled })
|
|
22
19
|
const queryKey = getMessageQueryKey({ conversation_id, messageId })
|
|
23
20
|
|
|
24
21
|
return { message, isError, isLoading, queryKey }
|
|
@@ -2,11 +2,12 @@ import { InfiniteData, UseInfiniteQueryResult } from '@tanstack/react-query'
|
|
|
2
2
|
import { useMemo } from 'react'
|
|
3
3
|
import { ApiCollection, ConversationResource } from '../types'
|
|
4
4
|
import { ConversationRequestArgs, getConversationsRequestArgs } from '../utils/request/conversation'
|
|
5
|
-
import {
|
|
5
|
+
import { ResponseError } from '../utils/response_error'
|
|
6
|
+
import { ApiGetQueryOptions, useApiPaginator } from './use_api'
|
|
6
7
|
|
|
7
8
|
export type ConversationPaginationResult = UseInfiniteQueryResult<
|
|
8
9
|
InfiniteData<ApiCollection<ConversationResource>, unknown>,
|
|
9
|
-
|
|
10
|
+
ResponseError
|
|
10
11
|
>
|
|
11
12
|
|
|
12
13
|
export type UseConversationsValue = Pick<
|
|
@@ -24,9 +25,12 @@ export type UseConversationsValue = Pick<
|
|
|
24
25
|
refetch: () => Promise<any>
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
export function useConversations(
|
|
28
|
+
export function useConversations(
|
|
29
|
+
args?: Partial<ConversationRequestArgs>,
|
|
30
|
+
opts?: ApiGetQueryOptions
|
|
31
|
+
): UseConversationsValue {
|
|
28
32
|
const requestArgs = getConversationsRequestArgs(args)
|
|
29
|
-
const { data, ...rest } = useApiPaginator<ConversationResource>(requestArgs)
|
|
33
|
+
const { data, ...rest } = useApiPaginator<ConversationResource>(requestArgs, opts)
|
|
30
34
|
|
|
31
35
|
const conversations = useMemo(() => data.sort(sortByLastMessage), [data])
|
|
32
36
|
|
|
@@ -16,18 +16,20 @@ export function useMyGender() {
|
|
|
16
16
|
const { featureEnabled } = useFeatures()
|
|
17
17
|
const isFeatureEnabled = featureEnabled(availableFeatures.gender_specific_conversations)
|
|
18
18
|
|
|
19
|
-
const { data, isFetching } = useApiGet<PersonWithGender>(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
const { data, isFetching } = useApiGet<PersonWithGender>(
|
|
20
|
+
{
|
|
21
|
+
url: '/me',
|
|
22
|
+
data: {
|
|
23
|
+
include: ['gender'],
|
|
24
|
+
fields: {
|
|
25
|
+
Person: ['gender'],
|
|
26
|
+
Gender: ['value'],
|
|
27
|
+
},
|
|
27
28
|
},
|
|
29
|
+
app: 'people',
|
|
28
30
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
{ enabled: isFeatureEnabled }
|
|
32
|
+
)
|
|
31
33
|
|
|
32
34
|
const gender = data?.gender
|
|
33
35
|
const genderValue = gender?.value ?? null
|
|
@@ -25,19 +25,19 @@ export function useNewConversationFromFilter(
|
|
|
25
25
|
const isGroupsGroup = sourceAppName === 'Groups' && sourceType === 'Group'
|
|
26
26
|
const isServicesTeam = sourceAppName === 'Services' && sourceType === 'Team'
|
|
27
27
|
|
|
28
|
-
const { data: group } = useApiGet<GroupResource>(
|
|
29
|
-
url: `/me/groups/${chatGroupGraphId}`,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
app: 'chat',
|
|
33
|
-
})
|
|
28
|
+
const { data: group } = useApiGet<GroupResource>(
|
|
29
|
+
{ url: `/me/groups/${chatGroupGraphId}`, data: { fields: { Group: ['name'] } }, app: 'chat' },
|
|
30
|
+
{ enabled: !!chatGroupGraphId }
|
|
31
|
+
)
|
|
34
32
|
|
|
35
|
-
const { data: groupsGroup } = useApiGet<GroupsGroupResource>(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
const { data: groupsGroup } = useApiGet<GroupsGroupResource>(
|
|
34
|
+
{
|
|
35
|
+
url: `/me/groups/${sourceId}`,
|
|
36
|
+
data: { fields: { Group: ['can_create_conversation'] } },
|
|
37
|
+
app: 'groups',
|
|
38
|
+
},
|
|
39
|
+
{ enabled: isGroupsGroup && !!sourceId }
|
|
40
|
+
)
|
|
41
41
|
|
|
42
42
|
return useMemo(() => {
|
|
43
43
|
if (isGroupsGroup && group?.name && sourceId) {
|
|
@@ -16,18 +16,20 @@ interface PeoplePerson extends ResourceObject {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export const usePeoplePerson = (person?: { id: number }) => {
|
|
19
|
-
const { data: peoplePerson } = useApiGet<PeoplePerson>(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
const { data: peoplePerson } = useApiGet<PeoplePerson>(
|
|
20
|
+
{
|
|
21
|
+
url: `/people/${person?.id}`,
|
|
22
|
+
data: {
|
|
23
|
+
include: ['emails'],
|
|
24
|
+
fields: {
|
|
25
|
+
Person: ['id', 'name', 'avatar', 'emails'],
|
|
26
|
+
Email: ['address', 'primary'],
|
|
27
|
+
},
|
|
27
28
|
},
|
|
29
|
+
app: 'people',
|
|
28
30
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
{ enabled: Boolean(person?.id) }
|
|
32
|
+
)
|
|
31
33
|
|
|
32
34
|
return peoplePerson
|
|
33
35
|
}
|
|
@@ -11,16 +11,10 @@ export const ChatGroupBadge = ({ rowPaddingHorizontal }: { rowPaddingHorizontal:
|
|
|
11
11
|
const navigation = useNavigation()
|
|
12
12
|
const route = useRoute<RouteProp<ConversationsScreenProps['route']>>()
|
|
13
13
|
const { chat_group_graph_id } = route.params || {}
|
|
14
|
-
const { data: group } = useApiGet<GroupResource>(
|
|
15
|
-
url: `/me/groups/${chat_group_graph_id}`,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Group: [],
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
enabled: !!chat_group_graph_id,
|
|
22
|
-
app: 'chat',
|
|
23
|
-
})
|
|
14
|
+
const { data: group } = useApiGet<GroupResource>(
|
|
15
|
+
{ url: `/me/groups/${chat_group_graph_id}`, data: { fields: { Group: [] } }, app: 'chat' },
|
|
16
|
+
{ enabled: !!chat_group_graph_id }
|
|
17
|
+
)
|
|
24
18
|
|
|
25
19
|
const handleBadgePress = useCallback(() => {
|
|
26
20
|
navigation.setParams({
|
|
@@ -22,7 +22,7 @@ export function ConversationsScreen({ route }: ConversationsScreenProps) {
|
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
24
|
<View style={styles.container}>
|
|
25
|
-
<ConversationsContextProvider args={route.params}>
|
|
25
|
+
<ConversationsContextProvider args={route.params} opts={{ throwOnError: true }}>
|
|
26
26
|
<Conversations ListHeaderComponent={ListHeaderComponent} />
|
|
27
27
|
</ConversationsContextProvider>
|
|
28
28
|
</View>
|