@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.
Files changed (58) hide show
  1. package/build/components/page/page_error_boundary.d.ts.map +1 -1
  2. package/build/components/page/page_error_boundary.js +29 -1
  3. package/build/components/page/page_error_boundary.js.map +1 -1
  4. package/build/contexts/api_provider.d.ts.map +1 -1
  5. package/build/contexts/api_provider.js +12 -2
  6. package/build/contexts/api_provider.js.map +1 -1
  7. package/build/contexts/conversations_context.d.ts +3 -1
  8. package/build/contexts/conversations_context.d.ts.map +1 -1
  9. package/build/contexts/conversations_context.js +2 -2
  10. package/build/contexts/conversations_context.js.map +1 -1
  11. package/build/hooks/services/use_team_members_for_new_conversation.d.ts +14 -14
  12. package/build/hooks/use_api.d.ts +48 -47
  13. package/build/hooks/use_api.d.ts.map +1 -1
  14. package/build/hooks/use_api.js +8 -10
  15. package/build/hooks/use_api.js.map +1 -1
  16. package/build/hooks/use_chat_permissions.d.ts +14 -14
  17. package/build/hooks/use_conversation_message.d.ts.map +1 -1
  18. package/build/hooks/use_conversation_message.js +1 -4
  19. package/build/hooks/use_conversation_message.js.map +1 -1
  20. package/build/hooks/use_conversations.d.ts +4 -2
  21. package/build/hooks/use_conversations.d.ts.map +1 -1
  22. package/build/hooks/use_conversations.js +2 -2
  23. package/build/hooks/use_conversations.js.map +1 -1
  24. package/build/hooks/use_groups.d.ts +26 -26
  25. package/build/hooks/use_groups_groups.d.ts +26 -26
  26. package/build/hooks/use_my_gender.d.ts.map +1 -1
  27. package/build/hooks/use_my_gender.js +1 -2
  28. package/build/hooks/use_my_gender.js.map +1 -1
  29. package/build/hooks/use_new_conversation_from_filter.js +2 -8
  30. package/build/hooks/use_new_conversation_from_filter.js.map +1 -1
  31. package/build/hooks/use_people_person.d.ts.map +1 -1
  32. package/build/hooks/use_people_person.js +1 -2
  33. package/build/hooks/use_people_person.js.map +1 -1
  34. package/build/hooks/use_teams.d.ts +26 -26
  35. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.d.ts +14 -14
  36. package/build/screens/conversation_filters/hooks/filters.d.ts +40 -40
  37. package/build/screens/conversations/components/chat_group_badge.d.ts.map +1 -1
  38. package/build/screens/conversations/components/chat_group_badge.js +1 -10
  39. package/build/screens/conversations/components/chat_group_badge.js.map +1 -1
  40. package/build/screens/conversations/conversations_screen.js +1 -1
  41. package/build/screens/conversations/conversations_screen.js.map +1 -1
  42. package/build/utils/performance_tracking.js +2 -0
  43. package/build/utils/performance_tracking.js.map +1 -1
  44. package/build/utils/uri.d.ts +1 -1
  45. package/package.json +2 -2
  46. package/src/__tests__/hooks/use_api.test.tsx +11 -0
  47. package/src/components/page/page_error_boundary.tsx +46 -1
  48. package/src/contexts/api_provider.tsx +16 -2
  49. package/src/contexts/conversations_context.tsx +19 -7
  50. package/src/hooks/use_api.ts +18 -27
  51. package/src/hooks/use_conversation_message.ts +1 -4
  52. package/src/hooks/use_conversations.ts +8 -4
  53. package/src/hooks/use_my_gender.ts +12 -10
  54. package/src/hooks/use_new_conversation_from_filter.ts +12 -12
  55. package/src/hooks/use_people_person.ts +12 -10
  56. package/src/screens/conversations/components/chat_group_badge.tsx +4 -10
  57. package/src/screens/conversations/conversations_screen.tsx +1 -1
  58. 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
- }: PropsWithChildren<{ args: ConversationFiltersParams }>) => {
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
- chat_group_graph_id,
46
- group_source_app_name,
47
- show_direct_messages,
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<InfiniteData<ApiCollection<ConversationResource>, unknown>, Response>
75
+ InfiniteQueryObserverResult<
76
+ InfiniteData<ApiCollection<ConversationResource>, unknown>,
77
+ ResponseError
78
+ >
67
79
  > {
68
80
  throw new Error('Function not implemented.')
69
81
  }
@@ -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, FailedResponse, ResourceObject } from '../types'
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 UseApiGetOptions = {
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?: UseApiGetOptions
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 && (args.enabled ?? true)
30
+ const enabled = !!session.token?.access_token && (opts?.enabled ?? true)
34
31
 
35
- const { data, ...query } = useQuery<Resource, FailedResponse>({
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?: PaginatorOptions
50
+ opts?: ApiGetQueryOptions
57
51
  ) => {
58
52
  const { session } = useContext(ChatContext)
59
53
  const apiClient = useApiClient()
60
- const enabled = !!session.token?.access_token && (args.enabled ?? true)
54
+ const enabled = !!session.token?.access_token && (opts?.enabled ?? true)
61
55
  const query = useInfiniteQuery<
62
56
  ApiCollection<T>,
63
- FailedResponse,
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 { useApiPaginator } from './use_api'
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
- Response
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(args?: Partial<ConversationRequestArgs>): UseConversationsValue {
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
- url: '/me',
21
- enabled: isFeatureEnabled,
22
- data: {
23
- include: ['gender'],
24
- fields: {
25
- Person: ['gender'],
26
- Gender: ['value'],
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
- app: 'people',
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
- data: { fields: { Group: ['name'] } },
31
- enabled: !!chatGroupGraphId,
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
- url: `/me/groups/${sourceId}`,
37
- data: { fields: { Group: ['can_create_conversation'] } },
38
- enabled: isGroupsGroup && !!sourceId,
39
- app: 'groups',
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
- url: `/people/${person?.id}`,
21
- enabled: Boolean(person?.id),
22
- data: {
23
- include: ['emails'],
24
- fields: {
25
- Person: ['id', 'name', 'avatar', 'emails'],
26
- Email: ['address', 'primary'],
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
- app: 'people',
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
- data: {
17
- fields: {
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>
@@ -89,6 +89,8 @@ async function sendPerformanceMetric(
89
89
  apiClient: ApiClient,
90
90
  metric: PerformanceMetric
91
91
  ): Promise<void> {
92
+ if (__DEV__) return
93
+
92
94
  try {
93
95
  await apiClient.chat.post({
94
96
  url: `/me/metrics`,