@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
@@ -1,7 +1,7 @@
1
1
  import { GroupsGroupResource } from '../../../types';
2
2
  import { GroupResource } from '../../../types/resources/group_resource';
3
3
  export declare const useTeamsToFilter: () => {
4
- error: import("../../..").FailedResponse;
4
+ error: import("../../..").ResponseError;
5
5
  isError: true;
6
6
  isPending: false;
7
7
  isLoading: false;
@@ -10,8 +10,8 @@ export declare const useTeamsToFilter: () => {
10
10
  isSuccess: false;
11
11
  isPlaceholderData: false;
12
12
  status: "error";
13
- fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
14
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
13
+ fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
14
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
15
15
  hasNextPage: boolean;
16
16
  hasPreviousPage: boolean;
17
17
  isFetchNextPageError: boolean;
@@ -21,7 +21,7 @@ export declare const useTeamsToFilter: () => {
21
21
  dataUpdatedAt: number;
22
22
  errorUpdatedAt: number;
23
23
  failureCount: number;
24
- failureReason: import("../../..").FailedResponse | null;
24
+ failureReason: import("../../..").ResponseError | null;
25
25
  errorUpdateCount: number;
26
26
  isFetched: boolean;
27
27
  isFetchedAfterMount: boolean;
@@ -30,7 +30,7 @@ export declare const useTeamsToFilter: () => {
30
30
  isPaused: boolean;
31
31
  isRefetching: boolean;
32
32
  isStale: boolean;
33
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
33
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
34
34
  fetchStatus: import("@tanstack/query-core").FetchStatus;
35
35
  promise: Promise<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>>;
36
36
  teams: GroupResource[];
@@ -46,8 +46,8 @@ export declare const useTeamsToFilter: () => {
46
46
  isSuccess: true;
47
47
  isPlaceholderData: false;
48
48
  status: "success";
49
- fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
50
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
49
+ fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
50
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
51
51
  hasNextPage: boolean;
52
52
  hasPreviousPage: boolean;
53
53
  isFetchingNextPage: boolean;
@@ -55,7 +55,7 @@ export declare const useTeamsToFilter: () => {
55
55
  dataUpdatedAt: number;
56
56
  errorUpdatedAt: number;
57
57
  failureCount: number;
58
- failureReason: import("../../..").FailedResponse | null;
58
+ failureReason: import("../../..").ResponseError | null;
59
59
  errorUpdateCount: number;
60
60
  isFetched: boolean;
61
61
  isFetchedAfterMount: boolean;
@@ -64,12 +64,12 @@ export declare const useTeamsToFilter: () => {
64
64
  isPaused: boolean;
65
65
  isRefetching: boolean;
66
66
  isStale: boolean;
67
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
67
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
68
68
  fetchStatus: import("@tanstack/query-core").FetchStatus;
69
69
  promise: Promise<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>>;
70
70
  teams: GroupResource[];
71
71
  } | {
72
- error: import("../../..").FailedResponse;
72
+ error: import("../../..").ResponseError;
73
73
  isError: true;
74
74
  isPending: false;
75
75
  isLoading: false;
@@ -80,8 +80,8 @@ export declare const useTeamsToFilter: () => {
80
80
  isSuccess: false;
81
81
  isPlaceholderData: false;
82
82
  status: "error";
83
- fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
84
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
83
+ fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
84
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
85
85
  hasNextPage: boolean;
86
86
  hasPreviousPage: boolean;
87
87
  isFetchingNextPage: boolean;
@@ -89,7 +89,7 @@ export declare const useTeamsToFilter: () => {
89
89
  dataUpdatedAt: number;
90
90
  errorUpdatedAt: number;
91
91
  failureCount: number;
92
- failureReason: import("../../..").FailedResponse | null;
92
+ failureReason: import("../../..").ResponseError | null;
93
93
  errorUpdateCount: number;
94
94
  isFetched: boolean;
95
95
  isFetchedAfterMount: boolean;
@@ -98,7 +98,7 @@ export declare const useTeamsToFilter: () => {
98
98
  isPaused: boolean;
99
99
  isRefetching: boolean;
100
100
  isStale: boolean;
101
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
101
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
102
102
  fetchStatus: import("@tanstack/query-core").FetchStatus;
103
103
  promise: Promise<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>>;
104
104
  teams: GroupResource[];
@@ -114,8 +114,8 @@ export declare const useTeamsToFilter: () => {
114
114
  isSuccess: false;
115
115
  isPlaceholderData: false;
116
116
  status: "pending";
117
- fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
118
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
117
+ fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
118
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
119
119
  hasNextPage: boolean;
120
120
  hasPreviousPage: boolean;
121
121
  isFetchingNextPage: boolean;
@@ -123,7 +123,7 @@ export declare const useTeamsToFilter: () => {
123
123
  dataUpdatedAt: number;
124
124
  errorUpdatedAt: number;
125
125
  failureCount: number;
126
- failureReason: import("../../..").FailedResponse | null;
126
+ failureReason: import("../../..").ResponseError | null;
127
127
  errorUpdateCount: number;
128
128
  isFetched: boolean;
129
129
  isFetchedAfterMount: boolean;
@@ -132,7 +132,7 @@ export declare const useTeamsToFilter: () => {
132
132
  isPaused: boolean;
133
133
  isRefetching: boolean;
134
134
  isStale: boolean;
135
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
135
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
136
136
  fetchStatus: import("@tanstack/query-core").FetchStatus;
137
137
  promise: Promise<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>>;
138
138
  teams: GroupResource[];
@@ -147,8 +147,8 @@ export declare const useTeamsToFilter: () => {
147
147
  isSuccess: false;
148
148
  isPlaceholderData: false;
149
149
  status: "pending";
150
- fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
151
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
150
+ fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
151
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
152
152
  hasNextPage: boolean;
153
153
  hasPreviousPage: boolean;
154
154
  isFetchingNextPage: boolean;
@@ -156,7 +156,7 @@ export declare const useTeamsToFilter: () => {
156
156
  dataUpdatedAt: number;
157
157
  errorUpdatedAt: number;
158
158
  failureCount: number;
159
- failureReason: import("../../..").FailedResponse | null;
159
+ failureReason: import("../../..").ResponseError | null;
160
160
  errorUpdateCount: number;
161
161
  isFetched: boolean;
162
162
  isFetchedAfterMount: boolean;
@@ -166,7 +166,7 @@ export declare const useTeamsToFilter: () => {
166
166
  isPaused: boolean;
167
167
  isRefetching: boolean;
168
168
  isStale: boolean;
169
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
169
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
170
170
  fetchStatus: import("@tanstack/query-core").FetchStatus;
171
171
  promise: Promise<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>>;
172
172
  teams: GroupResource[];
@@ -182,8 +182,8 @@ export declare const useTeamsToFilter: () => {
182
182
  isFetchNextPageError: false;
183
183
  isFetchPreviousPageError: false;
184
184
  status: "success";
185
- fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
186
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
185
+ fetchNextPage: (options?: import("@tanstack/query-core").FetchNextPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
186
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
187
187
  hasNextPage: boolean;
188
188
  hasPreviousPage: boolean;
189
189
  isFetchingNextPage: boolean;
@@ -191,7 +191,7 @@ export declare const useTeamsToFilter: () => {
191
191
  dataUpdatedAt: number;
192
192
  errorUpdatedAt: number;
193
193
  failureCount: number;
194
- failureReason: import("../../..").FailedResponse | null;
194
+ failureReason: import("../../..").ResponseError | null;
195
195
  errorUpdateCount: number;
196
196
  isFetched: boolean;
197
197
  isFetchedAfterMount: boolean;
@@ -200,7 +200,7 @@ export declare const useTeamsToFilter: () => {
200
200
  isPaused: boolean;
201
201
  isRefetching: boolean;
202
202
  isStale: boolean;
203
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
203
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
204
204
  fetchStatus: import("@tanstack/query-core").FetchStatus;
205
205
  promise: Promise<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>>;
206
206
  teams: GroupResource[];
@@ -208,7 +208,7 @@ export declare const useTeamsToFilter: () => {
208
208
  export interface FilteredGroup extends GroupResource, Partial<Pick<GroupsGroupResource, 'headerImage' | 'membershipsCount'>> {
209
209
  }
210
210
  export declare const useGroupsToFilter: () => {
211
- error: import("../../..").FailedResponse;
211
+ error: import("../../..").ResponseError;
212
212
  isError: true;
213
213
  isPending: false;
214
214
  isLoading: false;
@@ -217,7 +217,7 @@ export declare const useGroupsToFilter: () => {
217
217
  isSuccess: false;
218
218
  isPlaceholderData: false;
219
219
  status: "error";
220
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
220
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
221
221
  hasNextPage: boolean;
222
222
  hasPreviousPage: boolean;
223
223
  isFetchNextPageError: boolean;
@@ -227,7 +227,7 @@ export declare const useGroupsToFilter: () => {
227
227
  dataUpdatedAt: number;
228
228
  errorUpdatedAt: number;
229
229
  failureCount: number;
230
- failureReason: import("../../..").FailedResponse | null;
230
+ failureReason: import("../../..").ResponseError | null;
231
231
  errorUpdateCount: number;
232
232
  isFetched: boolean;
233
233
  isFetchedAfterMount: boolean;
@@ -253,7 +253,7 @@ export declare const useGroupsToFilter: () => {
253
253
  isSuccess: true;
254
254
  isPlaceholderData: false;
255
255
  status: "success";
256
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
256
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
257
257
  hasNextPage: boolean;
258
258
  hasPreviousPage: boolean;
259
259
  isFetchingNextPage: boolean;
@@ -261,7 +261,7 @@ export declare const useGroupsToFilter: () => {
261
261
  dataUpdatedAt: number;
262
262
  errorUpdatedAt: number;
263
263
  failureCount: number;
264
- failureReason: import("../../..").FailedResponse | null;
264
+ failureReason: import("../../..").ResponseError | null;
265
265
  errorUpdateCount: number;
266
266
  isFetched: boolean;
267
267
  isFetchedAfterMount: boolean;
@@ -276,7 +276,7 @@ export declare const useGroupsToFilter: () => {
276
276
  fetchNextPage: () => void;
277
277
  refetch: () => void;
278
278
  } | {
279
- error: import("../../..").FailedResponse;
279
+ error: import("../../..").ResponseError;
280
280
  isError: true;
281
281
  isPending: false;
282
282
  isLoading: false;
@@ -287,7 +287,7 @@ export declare const useGroupsToFilter: () => {
287
287
  isSuccess: false;
288
288
  isPlaceholderData: false;
289
289
  status: "error";
290
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
290
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
291
291
  hasNextPage: boolean;
292
292
  hasPreviousPage: boolean;
293
293
  isFetchingNextPage: boolean;
@@ -295,7 +295,7 @@ export declare const useGroupsToFilter: () => {
295
295
  dataUpdatedAt: number;
296
296
  errorUpdatedAt: number;
297
297
  failureCount: number;
298
- failureReason: import("../../..").FailedResponse | null;
298
+ failureReason: import("../../..").ResponseError | null;
299
299
  errorUpdateCount: number;
300
300
  isFetched: boolean;
301
301
  isFetchedAfterMount: boolean;
@@ -321,7 +321,7 @@ export declare const useGroupsToFilter: () => {
321
321
  isSuccess: false;
322
322
  isPlaceholderData: false;
323
323
  status: "pending";
324
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
324
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
325
325
  hasNextPage: boolean;
326
326
  hasPreviousPage: boolean;
327
327
  isFetchingNextPage: boolean;
@@ -329,7 +329,7 @@ export declare const useGroupsToFilter: () => {
329
329
  dataUpdatedAt: number;
330
330
  errorUpdatedAt: number;
331
331
  failureCount: number;
332
- failureReason: import("../../..").FailedResponse | null;
332
+ failureReason: import("../../..").ResponseError | null;
333
333
  errorUpdateCount: number;
334
334
  isFetched: boolean;
335
335
  isFetchedAfterMount: boolean;
@@ -354,7 +354,7 @@ export declare const useGroupsToFilter: () => {
354
354
  isSuccess: false;
355
355
  isPlaceholderData: false;
356
356
  status: "pending";
357
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
357
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
358
358
  hasNextPage: boolean;
359
359
  hasPreviousPage: boolean;
360
360
  isFetchingNextPage: boolean;
@@ -362,7 +362,7 @@ export declare const useGroupsToFilter: () => {
362
362
  dataUpdatedAt: number;
363
363
  errorUpdatedAt: number;
364
364
  failureCount: number;
365
- failureReason: import("../../..").FailedResponse | null;
365
+ failureReason: import("../../..").ResponseError | null;
366
366
  errorUpdateCount: number;
367
367
  isFetched: boolean;
368
368
  isFetchedAfterMount: boolean;
@@ -389,7 +389,7 @@ export declare const useGroupsToFilter: () => {
389
389
  isFetchNextPageError: false;
390
390
  isFetchPreviousPageError: false;
391
391
  status: "success";
392
- fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").FailedResponse>>;
392
+ fetchPreviousPage: (options?: import("@tanstack/query-core").FetchPreviousPageOptions) => Promise<import("@tanstack/query-core").InfiniteQueryObserverResult<import("@tanstack/query-core").InfiniteData<import("../../..").ApiCollection<GroupResource>, unknown>, import("../../..").ResponseError>>;
393
393
  hasNextPage: boolean;
394
394
  hasPreviousPage: boolean;
395
395
  isFetchingNextPage: boolean;
@@ -397,7 +397,7 @@ export declare const useGroupsToFilter: () => {
397
397
  dataUpdatedAt: number;
398
398
  errorUpdatedAt: number;
399
399
  failureCount: number;
400
- failureReason: import("../../..").FailedResponse | null;
400
+ failureReason: import("../../..").ResponseError | null;
401
401
  errorUpdateCount: number;
402
402
  isFetched: boolean;
403
403
  isFetchedAfterMount: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"chat_group_badge.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversations/components/chat_group_badge.tsx"],"names":[],"mappings":"AACA,OAAO,KAAsB,MAAM,OAAO,CAAA;AAO1C,eAAO,MAAM,cAAc,GAAI,0BAA0B;IAAE,oBAAoB,EAAE,MAAM,CAAA;CAAE,6BA8BxF,CAAA"}
1
+ {"version":3,"file":"chat_group_badge.d.ts","sourceRoot":"","sources":["../../../../src/screens/conversations/components/chat_group_badge.tsx"],"names":[],"mappings":"AACA,OAAO,KAAsB,MAAM,OAAO,CAAA;AAO1C,eAAO,MAAM,cAAc,GAAI,0BAA0B;IAAE,oBAAoB,EAAE,MAAM,CAAA;CAAE,6BAwBxF,CAAA"}
@@ -8,16 +8,7 @@ export const ChatGroupBadge = ({ rowPaddingHorizontal }) => {
8
8
  const navigation = useNavigation();
9
9
  const route = useRoute();
10
10
  const { chat_group_graph_id } = route.params || {};
11
- const { data: group } = useApiGet({
12
- url: `/me/groups/${chat_group_graph_id}`,
13
- data: {
14
- fields: {
15
- Group: [],
16
- },
17
- },
18
- enabled: !!chat_group_graph_id,
19
- app: 'chat',
20
- });
11
+ const { data: group } = useApiGet({ url: `/me/groups/${chat_group_graph_id}`, data: { fields: { Group: [] } }, app: 'chat' }, { enabled: !!chat_group_graph_id });
21
12
  const handleBadgePress = useCallback(() => {
22
13
  navigation.setParams({
23
14
  chat_group_graph_id: undefined,
@@ -1 +1 @@
1
- {"version":3,"file":"chat_group_badge.js","sourceRoot":"","sources":["../../../../src/screens/conversations/components/chat_group_badge.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,aAAa,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAC7E,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAIlD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAE,oBAAoB,EAAoC,EAAE,EAAE;IAC3F,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,oBAAoB,EAAE,CAAC,CAAA;IAClD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,KAAK,GAAG,QAAQ,EAAgD,CAAA;IACtE,MAAM,EAAE,mBAAmB,EAAE,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAA;IAClD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,SAAS,CAAgB;QAC/C,GAAG,EAAE,cAAc,mBAAmB,EAAE;QACxC,IAAI,EAAE;YACJ,MAAM,EAAE;gBACN,KAAK,EAAE,EAAE;aACV;SACF;QACD,OAAO,EAAE,CAAC,CAAC,mBAAmB;QAC9B,GAAG,EAAE,MAAM;KACZ,CAAC,CAAA;IAEF,MAAM,gBAAgB,GAAG,WAAW,CAAC,GAAG,EAAE;QACxC,UAAU,CAAC,SAAS,CAAC;YACnB,mBAAmB,EAAE,SAAS;YAC9B,qBAAqB,EAAE,SAAS;SACjC,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAA;IAEhB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IAEvB,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACtB;MAAA,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,gBAAgB,CAAC,EACvF;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,CAAC,EAAE,oBAAoB,EAAoC,EAAE,EAAE;IAC/E,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,GAAG,EAAE;YACH,aAAa,EAAE,KAAK;YACpB,iBAAiB,EAAE,oBAAoB;SACxC;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { RouteProp, useNavigation, useRoute } from '@react-navigation/native'\nimport React, { useCallback } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Badge } from '../../../components'\nimport { useApiGet } from '../../../hooks/use_api'\nimport { GroupResource } from '../../../types/resources/group_resource'\nimport { ConversationsScreenProps } from '../conversations_screen'\n\nexport const ChatGroupBadge = ({ rowPaddingHorizontal }: { rowPaddingHorizontal: number }) => {\n const styles = useStyles({ rowPaddingHorizontal })\n const navigation = useNavigation()\n const route = useRoute<RouteProp<ConversationsScreenProps['route']>>()\n const { chat_group_graph_id } = route.params || {}\n const { data: group } = useApiGet<GroupResource>({\n url: `/me/groups/${chat_group_graph_id}`,\n data: {\n fields: {\n Group: [],\n },\n },\n enabled: !!chat_group_graph_id,\n app: 'chat',\n })\n\n const handleBadgePress = useCallback(() => {\n navigation.setParams({\n chat_group_graph_id: undefined,\n group_source_app_name: undefined,\n })\n }, [navigation])\n\n if (!group) return null\n\n return (\n <View style={styles.row}>\n <Badge iconNameRight=\"general.x\" label={group?.name || ''} onPress={handleBadgePress} />\n </View>\n )\n}\n\nconst useStyles = ({ rowPaddingHorizontal }: { rowPaddingHorizontal: number }) => {\n return StyleSheet.create({\n row: {\n flexDirection: 'row',\n paddingHorizontal: rowPaddingHorizontal,\n },\n })\n}\n"]}
1
+ {"version":3,"file":"chat_group_badge.js","sourceRoot":"","sources":["../../../../src/screens/conversations/components/chat_group_badge.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,aAAa,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAC7E,OAAO,KAAK,EAAE,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAA;AAIlD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAAE,oBAAoB,EAAoC,EAAE,EAAE;IAC3F,MAAM,MAAM,GAAG,SAAS,CAAC,EAAE,oBAAoB,EAAE,CAAC,CAAA;IAClD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,KAAK,GAAG,QAAQ,EAAgD,CAAA;IACtE,MAAM,EAAE,mBAAmB,EAAE,GAAG,KAAK,CAAC,MAAM,IAAI,EAAE,CAAA;IAClD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,SAAS,CAC/B,EAAE,GAAG,EAAE,cAAc,mBAAmB,EAAE,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,EAC1F,EAAE,OAAO,EAAE,CAAC,CAAC,mBAAmB,EAAE,CACnC,CAAA;IAED,MAAM,gBAAgB,GAAG,WAAW,CAAC,GAAG,EAAE;QACxC,UAAU,CAAC,SAAS,CAAC;YACnB,mBAAmB,EAAE,SAAS;YAC9B,qBAAqB,EAAE,SAAS;SACjC,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAA;IAEhB,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAA;IAEvB,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CACtB;MAAA,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,gBAAgB,CAAC,EACvF;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC,CAAA;AAED,MAAM,SAAS,GAAG,CAAC,EAAE,oBAAoB,EAAoC,EAAE,EAAE;IAC/E,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,GAAG,EAAE;YACH,aAAa,EAAE,KAAK;YACpB,iBAAiB,EAAE,oBAAoB;SACxC;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { RouteProp, useNavigation, useRoute } from '@react-navigation/native'\nimport React, { useCallback } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Badge } from '../../../components'\nimport { useApiGet } from '../../../hooks/use_api'\nimport { GroupResource } from '../../../types/resources/group_resource'\nimport { ConversationsScreenProps } from '../conversations_screen'\n\nexport const ChatGroupBadge = ({ rowPaddingHorizontal }: { rowPaddingHorizontal: number }) => {\n const styles = useStyles({ rowPaddingHorizontal })\n const navigation = useNavigation()\n const route = useRoute<RouteProp<ConversationsScreenProps['route']>>()\n const { chat_group_graph_id } = route.params || {}\n const { data: group } = useApiGet<GroupResource>(\n { url: `/me/groups/${chat_group_graph_id}`, data: { fields: { Group: [] } }, app: 'chat' },\n { enabled: !!chat_group_graph_id }\n )\n\n const handleBadgePress = useCallback(() => {\n navigation.setParams({\n chat_group_graph_id: undefined,\n group_source_app_name: undefined,\n })\n }, [navigation])\n\n if (!group) return null\n\n return (\n <View style={styles.row}>\n <Badge iconNameRight=\"general.x\" label={group?.name || ''} onPress={handleBadgePress} />\n </View>\n )\n}\n\nconst useStyles = ({ rowPaddingHorizontal }: { rowPaddingHorizontal: number }) => {\n return StyleSheet.create({\n row: {\n flexDirection: 'row',\n paddingHorizontal: rowPaddingHorizontal,\n },\n })\n}\n"]}
@@ -8,7 +8,7 @@ export function ConversationsScreen({ route }) {
8
8
  const styles = useStyles();
9
9
  usePublishProductAnalyticsEvent(analyticsEvents.conversation_index_opened);
10
10
  return (<View style={styles.container}>
11
- <ConversationsContextProvider args={route.params}>
11
+ <ConversationsContextProvider args={route.params} opts={{ throwOnError: true }}>
12
12
  <Conversations ListHeaderComponent={ListHeaderComponent}/>
13
13
  </ConversationsContextProvider>
14
14
  </View>);
@@ -1 +1 @@
1
- {"version":3,"file":"conversations_screen.js","sourceRoot":"","sources":["../../../src/screens/conversations/conversations_screen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAA;AACnF,OAAO,EAAE,eAAe,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAA;AAGpG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAA;AASxE,MAAM,UAAU,mBAAmB,CAAC,EAAE,KAAK,EAA4B;IACrE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,+BAA+B,CAAC,eAAe,CAAC,yBAAyB,CAAC,CAAA;IAE1E,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;MAAA,CAAC,4BAA4B,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAC/C;QAAA,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,mBAAmB,CAAC,EAC1D;MAAA,EAAE,4BAA4B,CAChC;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,IAAI,EAAE,CAAC;YACP,cAAc,EAAE,QAAQ;SACzB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { StaticScreenProps } from '@react-navigation/native'\nimport React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Conversations } from '../../components'\nimport { ConversationsContextProvider } from '../../contexts/conversations_context'\nimport { analyticsEvents, usePublishProductAnalyticsEvent } from '../../hooks/use_product_analytics'\nimport { AppName } from '../../types/resources/app_name'\nimport { GraphId } from '../../types/resources/group_resource'\nimport { ListHeaderComponent } from './components/list_header_component'\n\nexport type ConversationsScreenProps = StaticScreenProps<{\n title?: string\n chat_group_graph_id?: GraphId\n group_source_app_name?: AppName\n show_direct_messages?: boolean\n}>\n\nexport function ConversationsScreen({ route }: ConversationsScreenProps) {\n const styles = useStyles()\n\n usePublishProductAnalyticsEvent(analyticsEvents.conversation_index_opened)\n\n return (\n <View style={styles.container}>\n <ConversationsContextProvider args={route.params}>\n <Conversations ListHeaderComponent={ListHeaderComponent} />\n </ConversationsContextProvider>\n </View>\n )\n}\n\nconst useStyles = () => {\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n },\n })\n}\n"]}
1
+ {"version":3,"file":"conversations_screen.js","sourceRoot":"","sources":["../../../src/screens/conversations/conversations_screen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,4BAA4B,EAAE,MAAM,sCAAsC,CAAA;AACnF,OAAO,EAAE,eAAe,EAAE,+BAA+B,EAAE,MAAM,mCAAmC,CAAA;AAGpG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAA;AASxE,MAAM,UAAU,mBAAmB,CAAC,EAAE,KAAK,EAA4B;IACrE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,+BAA+B,CAAC,eAAe,CAAC,yBAAyB,CAAC,CAAA;IAE1E,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;MAAA,CAAC,4BAA4B,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAC7E;QAAA,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAC,mBAAmB,CAAC,EAC1D;MAAA,EAAE,4BAA4B,CAChC;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,IAAI,EAAE,CAAC;YACP,cAAc,EAAE,QAAQ;SACzB;KACF,CAAC,CAAA;AACJ,CAAC,CAAA","sourcesContent":["import { StaticScreenProps } from '@react-navigation/native'\nimport React from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { Conversations } from '../../components'\nimport { ConversationsContextProvider } from '../../contexts/conversations_context'\nimport { analyticsEvents, usePublishProductAnalyticsEvent } from '../../hooks/use_product_analytics'\nimport { AppName } from '../../types/resources/app_name'\nimport { GraphId } from '../../types/resources/group_resource'\nimport { ListHeaderComponent } from './components/list_header_component'\n\nexport type ConversationsScreenProps = StaticScreenProps<{\n title?: string\n chat_group_graph_id?: GraphId\n group_source_app_name?: AppName\n show_direct_messages?: boolean\n}>\n\nexport function ConversationsScreen({ route }: ConversationsScreenProps) {\n const styles = useStyles()\n\n usePublishProductAnalyticsEvent(analyticsEvents.conversation_index_opened)\n\n return (\n <View style={styles.container}>\n <ConversationsContextProvider args={route.params} opts={{ throwOnError: true }}>\n <Conversations ListHeaderComponent={ListHeaderComponent} />\n </ConversationsContextProvider>\n </View>\n )\n}\n\nconst useStyles = () => {\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n },\n })\n}\n"]}
@@ -61,6 +61,8 @@ function durationForIdempotentKey(idempotentKey) {
61
61
  * Send performance metric to backend for Datadog submission
62
62
  */
63
63
  async function sendPerformanceMetric(apiClient, metric) {
64
+ if (__DEV__)
65
+ return;
64
66
  try {
65
67
  await apiClient.chat.post({
66
68
  url: `/me/metrics`,
@@ -1 +1 @@
1
- {"version":3,"file":"performance_tracking.js","sourceRoot":"","sources":["../../src/utils/performance_tracking.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Performance tracking utilities for client-side metrics (React Native)\n *\n * This module provides functionality to track performance metrics and send them\n * to Datadog via the backend API for aggregation.\n */\n\nimport { Platform } from 'react-native'\nimport DeviceInfo from 'react-native-device-info'\nimport type { ApiClient } from '../hooks/use_api_client'\nconst appName = DeviceInfo.getApplicationName()\n\ninterface PerformanceMetric {\n name: string\n value: number\n unit: 'milliseconds' | 'seconds' | 'count'\n}\n\ninterface PendingMessageMetric {\n idempotentKey: string\n startTime: number\n}\n\nconst pendingMetrics = new Map<string, PendingMessageMetric>()\n\n/**\n * Start tracking message creation performance\n */\nexport function startMessageCreationTracking(idempotentKey: string): void {\n if (!idempotentKey) return\n const startTime = Date.now()\n pendingMetrics.set(`message:${idempotentKey}`, { idempotentKey, startTime })\n pendingMetrics.set(`conversation:${idempotentKey}`, { idempotentKey, startTime })\n cleanupStaleMetrics()\n}\n\n/**\n * Complete message creation tracking when the message.created event is received\n */\nexport function completeMessageCreationTracking({\n apiClient,\n idempotentKey,\n}: {\n apiClient: ApiClient\n idempotentKey: string\n}): void {\n if (!idempotentKey) return\n const duration = durationForIdempotentKey(`message:${idempotentKey}`)\n if (!duration) return\n sendPerformanceMetric(apiClient, {\n name: 'chat.message.creation.message_roundtrip_time',\n value: duration,\n unit: 'milliseconds',\n })\n}\n\n/**\n * Complete message creation tracking when the conversation.updated event is received\n */\nexport function completeMessageCreationConversationTracking({\n apiClient,\n idempotentKey,\n}: {\n apiClient: ApiClient\n idempotentKey: string\n}): void {\n if (!idempotentKey) return\n const duration = durationForIdempotentKey(`conversation:${idempotentKey}`)\n if (!duration) return\n sendPerformanceMetric(apiClient, {\n name: 'chat.message.creation.conversation_roundtrip_time',\n value: duration,\n unit: 'milliseconds',\n })\n}\n\nfunction durationForIdempotentKey(idempotentKey: string): number | undefined {\n const metric = pendingMetrics.get(idempotentKey)\n if (!metric) return undefined\n pendingMetrics.delete(idempotentKey)\n const endTime = Date.now()\n return endTime - metric.startTime\n}\n\n/**\n * Send performance metric to backend for Datadog submission\n */\nasync function sendPerformanceMetric(\n apiClient: ApiClient,\n metric: PerformanceMetric\n): Promise<void> {\n try {\n await apiClient.chat.post({\n url: `/me/metrics`,\n data: {\n data: {\n type: 'Metric',\n attributes: {\n metric: {\n name: metric.name,\n value: metric.value,\n unit: metric.unit,\n platform: Platform.OS,\n app: appName,\n },\n },\n },\n },\n })\n } catch (_e) {\n // Ignore errors\n }\n}\n\n/**\n * Clean up any stale metrics (older than 5 minutes)\n * This prevents memory leaks if messages fail to complete for any reason\n */\nfunction cleanupStaleMetrics(): void {\n const now = Date.now()\n const staleThreshold = 5 * 60 * 1000 // 5 minutes in milliseconds\n\n for (const [key, metric] of pendingMetrics.entries()) {\n if (now - metric.startTime > staleThreshold) {\n pendingMetrics.delete(key)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"performance_tracking.js","sourceRoot":"","sources":["../../src/utils/performance_tracking.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Performance tracking utilities for client-side metrics (React Native)\n *\n * This module provides functionality to track performance metrics and send them\n * to Datadog via the backend API for aggregation.\n */\n\nimport { Platform } from 'react-native'\nimport DeviceInfo from 'react-native-device-info'\nimport type { ApiClient } from '../hooks/use_api_client'\nconst appName = DeviceInfo.getApplicationName()\n\ninterface PerformanceMetric {\n name: string\n value: number\n unit: 'milliseconds' | 'seconds' | 'count'\n}\n\ninterface PendingMessageMetric {\n idempotentKey: string\n startTime: number\n}\n\nconst pendingMetrics = new Map<string, PendingMessageMetric>()\n\n/**\n * Start tracking message creation performance\n */\nexport function startMessageCreationTracking(idempotentKey: string): void {\n if (!idempotentKey) return\n const startTime = Date.now()\n pendingMetrics.set(`message:${idempotentKey}`, { idempotentKey, startTime })\n pendingMetrics.set(`conversation:${idempotentKey}`, { idempotentKey, startTime })\n cleanupStaleMetrics()\n}\n\n/**\n * Complete message creation tracking when the message.created event is received\n */\nexport function completeMessageCreationTracking({\n apiClient,\n idempotentKey,\n}: {\n apiClient: ApiClient\n idempotentKey: string\n}): void {\n if (!idempotentKey) return\n const duration = durationForIdempotentKey(`message:${idempotentKey}`)\n if (!duration) return\n sendPerformanceMetric(apiClient, {\n name: 'chat.message.creation.message_roundtrip_time',\n value: duration,\n unit: 'milliseconds',\n })\n}\n\n/**\n * Complete message creation tracking when the conversation.updated event is received\n */\nexport function completeMessageCreationConversationTracking({\n apiClient,\n idempotentKey,\n}: {\n apiClient: ApiClient\n idempotentKey: string\n}): void {\n if (!idempotentKey) return\n const duration = durationForIdempotentKey(`conversation:${idempotentKey}`)\n if (!duration) return\n sendPerformanceMetric(apiClient, {\n name: 'chat.message.creation.conversation_roundtrip_time',\n value: duration,\n unit: 'milliseconds',\n })\n}\n\nfunction durationForIdempotentKey(idempotentKey: string): number | undefined {\n const metric = pendingMetrics.get(idempotentKey)\n if (!metric) return undefined\n pendingMetrics.delete(idempotentKey)\n const endTime = Date.now()\n return endTime - metric.startTime\n}\n\n/**\n * Send performance metric to backend for Datadog submission\n */\nasync function sendPerformanceMetric(\n apiClient: ApiClient,\n metric: PerformanceMetric\n): Promise<void> {\n if (__DEV__) return\n\n try {\n await apiClient.chat.post({\n url: `/me/metrics`,\n data: {\n data: {\n type: 'Metric',\n attributes: {\n metric: {\n name: metric.name,\n value: metric.value,\n unit: metric.unit,\n platform: Platform.OS,\n app: appName,\n },\n },\n },\n },\n })\n } catch (_e) {\n // Ignore errors\n }\n}\n\n/**\n * Clean up any stale metrics (older than 5 minutes)\n * This prevents memory leaks if messages fail to complete for any reason\n */\nfunction cleanupStaleMetrics(): void {\n const now = Date.now()\n const staleThreshold = 5 * 60 * 1000 // 5 minutes in milliseconds\n\n for (const [key, metric] of pendingMetrics.entries()) {\n if (now - metric.startTime > staleThreshold) {\n pendingMetrics.delete(key)\n }\n }\n}\n"]}
@@ -11,7 +11,7 @@ export declare class Uri {
11
11
  });
12
12
  get schema(): string;
13
13
  get host(): string;
14
- get subdomain(): "api.staging" | "api-staging" | "api";
14
+ get subdomain(): "api" | "api.staging" | "api-staging";
15
15
  get domain(): 'pco' | 'planningcenteronline' | 'churchcenter';
16
16
  get tld(): "test" | "com";
17
17
  get isChurchCenter(): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "3.41.0",
3
+ "version": "3.41.1-rc.0",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "react-native": "./src/index.tsx",
@@ -72,5 +72,5 @@
72
72
  "react-native-url-polyfill": "^2.0.0",
73
73
  "typescript": "~5.9.2"
74
74
  },
75
- "gitHead": "cd30a30a10939724e6378698eaf549c114870a8e"
75
+ "gitHead": "6812e566d23cb1f3bbcd97a2379f0f1e233565ae"
76
76
  }
@@ -6,6 +6,7 @@ import { ChatContext, ChatContextValue } from '../../contexts/chat_context'
6
6
  import { useApiGet } from '../../hooks/use_api'
7
7
  import { ApiClient, useApiClient } from '../../hooks/use_api_client'
8
8
  import { Session } from '../../utils'
9
+ import { ResponseError } from '../../utils/response_error'
9
10
 
10
11
  jest.mock('../../hooks/use_api_client')
11
12
 
@@ -50,4 +51,14 @@ describe('useApiGet', () => {
50
51
 
51
52
  await waitFor(() => expect(get).toHaveBeenCalledTimes(1))
52
53
  })
54
+
55
+ it('wraps HTTP errors in ResponseError', async () => {
56
+ get.mockRejectedValue(new Response(null, { status: 429, statusText: 'Too Many Requests' }))
57
+
58
+ const { result } = renderUseApiGet(new Session({ token: { access_token: 'a-real-token' } }))
59
+
60
+ await waitFor(() => expect(result.current.isError).toBe(true))
61
+ expect(result.current.error).toBeInstanceOf(ResponseError)
62
+ expect((result.current.error as ResponseError).status).toBe(429)
63
+ })
53
64
  })
@@ -1,6 +1,6 @@
1
1
  import { useNavigation } from '@react-navigation/native'
2
2
  import { useQueryErrorResetBoundary } from '@tanstack/react-query'
3
- import React, { PropsWithChildren, useCallback, useEffect, useMemo } from 'react'
3
+ import React, { PropsWithChildren, useCallback, useEffect, useMemo, useRef, useState } from 'react'
4
4
  import { onAuthRefresh } from '../../utils/auth_events'
5
5
  import { ResponseError } from '../../utils/response_error'
6
6
  import BlankState from '../primitive/blank_state_primitive'
@@ -85,9 +85,54 @@ function ResponseErrorView({ response, onReset }: { response: Response; onReset:
85
85
  return onAuthRefresh(onReset)
86
86
  }, [status, onReset])
87
87
 
88
+ if (status === 429) {
89
+ return <RateLimitedView response={response} onReset={onReset} />
90
+ }
91
+
88
92
  return <ErrorContent heading={heading} body={body} />
89
93
  }
90
94
 
95
+ const RATE_LIMIT_WINDOW_S = 20
96
+
97
+ function RateLimitedView({ response, onReset }: { response: Response; onReset: () => void }) {
98
+ const retryAfterS = parseInt(
99
+ response.headers?.get('Retry-After') ?? String(RATE_LIMIT_WINDOW_S),
100
+ 10
101
+ )
102
+ const readyAt = useRef(Date.now() + retryAfterS * 1000).current
103
+ const [now, setNow] = useState(Date.now)
104
+
105
+ useEffect(() => {
106
+ const id = setInterval(() => {
107
+ setNow(prev => (prev >= readyAt ? prev : Date.now()))
108
+ }, 1000)
109
+ return () => clearInterval(id)
110
+ }, [readyAt])
111
+
112
+ const navigation = useNavigation()
113
+ const secondsLeft = Math.max(0, Math.ceil((readyAt - now) / 1000))
114
+
115
+ return (
116
+ <BlankState.Root>
117
+ <BlankState.Imagery name="people.noTextMessage" />
118
+ <BlankState.Content>
119
+ <BlankState.Heading>Too many requests</BlankState.Heading>
120
+ <BlankState.Text>
121
+ Chat is being accessed too frequently. Please wait a moment.
122
+ </BlankState.Text>
123
+ </BlankState.Content>
124
+ <BlankState.Button
125
+ title={secondsLeft > 0 ? `Retry in ${secondsLeft}s` : 'Try again'}
126
+ disabled={secondsLeft > 0}
127
+ onPress={onReset}
128
+ size="md"
129
+ accessibilityRole="button"
130
+ />
131
+ <BlankState.TextButton onPress={navigation.goBack}>Go back</BlankState.TextButton>
132
+ </BlankState.Root>
133
+ )
134
+ }
135
+
91
136
  function ErrorContent({ heading, body }: { heading: string; body: string }) {
92
137
  const navigation = useNavigation()
93
138
 
@@ -12,6 +12,7 @@ import { useAppState } from '../hooks/use_app_state'
12
12
  import { appGrantsRequestArgs } from '../hooks/use_chat_permissions'
13
13
  import { getRequestQueryKey, RequestQueryKey } from '../hooks/use_suspense_api'
14
14
  import { emitAuthRefresh } from '../utils/auth_events'
15
+ import { ResponseError } from '../utils/response_error'
15
16
  import { ChatContext, ChatContextValue } from './chat_context'
16
17
 
17
18
  let apiClient: ApiClient | undefined
@@ -26,11 +27,21 @@ const defaultQueryFn = ({ queryKey }: { queryKey: QueryKey }) => {
26
27
  return apiClient[app].get({ url, data, headers })
27
28
  }
28
29
 
30
+ const configuredRetry = (failureCount: number, error: any) => {
31
+ if (is429Error(error)) return false
32
+
33
+ return failureCount < 3
34
+ }
35
+
36
+ const is429Error = (error: any): boolean => {
37
+ return error instanceof ResponseError && error.status === 429
38
+ }
39
+
29
40
  export const chatQueryClient = new QueryClient({
30
41
  defaultOptions: {
31
42
  queries: {
32
43
  queryFn: defaultQueryFn,
33
- retry: 3,
44
+ retry: configuredRetry,
34
45
  },
35
46
  },
36
47
  })
@@ -98,7 +109,10 @@ function useSessionChanged(value: Pick<ChatContextValue, 'token' | 'env'>): bool
98
109
  const tokenChanged = Boolean(
99
110
  prevToken?.access_token && newToken?.access_token !== prevToken?.access_token
100
111
  )
101
- return tokenChanged || Boolean(prevEnv && newEnv !== prevEnv)
112
+
113
+ const envChanged = Boolean(prevEnv && newEnv !== prevEnv)
114
+
115
+ return tokenChanged || envChanged
102
116
  }
103
117
 
104
118
  function usePrevious<T>(value: T): T {