@planningcenter/chat-react-native 3.2.0-rc.2 → 3.2.0-rc.21

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 (349) hide show
  1. package/build/components/conversation/message_form.d.ts +2 -2
  2. package/build/components/conversation/message_form.d.ts.map +1 -1
  3. package/build/components/conversation/message_form.js +95 -41
  4. package/build/components/conversation/message_form.js.map +1 -1
  5. package/build/components/conversations/action_toggle_button.d.ts +1 -1
  6. package/build/components/conversations/action_toggle_button.d.ts.map +1 -1
  7. package/build/components/conversations/action_toggle_button.js +2 -1
  8. package/build/components/conversations/action_toggle_button.js.map +1 -1
  9. package/build/components/conversations/conversation_actions.d.ts.map +1 -1
  10. package/build/components/conversations/conversation_actions.js +25 -11
  11. package/build/components/conversations/conversation_actions.js.map +1 -1
  12. package/build/components/conversations/conversations.d.ts +3 -6
  13. package/build/components/conversations/conversations.d.ts.map +1 -1
  14. package/build/components/conversations/conversations.js +8 -18
  15. package/build/components/conversations/conversations.js.map +1 -1
  16. package/build/components/display/action_button.d.ts +2 -1
  17. package/build/components/display/action_button.d.ts.map +1 -1
  18. package/build/components/display/action_button.js +3 -4
  19. package/build/components/display/action_button.js.map +1 -1
  20. package/build/components/display/banner.d.ts +6 -1
  21. package/build/components/display/banner.d.ts.map +1 -1
  22. package/build/components/display/banner.js +2 -2
  23. package/build/components/display/banner.js.map +1 -1
  24. package/build/components/display/banner_collapsible.d.ts +1 -1
  25. package/build/components/display/banner_collapsible.d.ts.map +1 -1
  26. package/build/components/display/banner_collapsible.js +2 -2
  27. package/build/components/display/banner_collapsible.js.map +1 -1
  28. package/build/components/display/child_notice.d.ts +3 -1
  29. package/build/components/display/child_notice.d.ts.map +1 -1
  30. package/build/components/display/child_notice.js +2 -2
  31. package/build/components/display/child_notice.js.map +1 -1
  32. package/build/components/display/person.d.ts +3 -1
  33. package/build/components/display/person.d.ts.map +1 -1
  34. package/build/components/display/person.js +2 -2
  35. package/build/components/display/person.js.map +1 -1
  36. package/build/components/primitive/banner_primitive.d.ts +3 -0
  37. package/build/components/primitive/banner_primitive.d.ts.map +1 -1
  38. package/build/components/primitive/banner_primitive.js +4 -5
  39. package/build/components/primitive/banner_primitive.js.map +1 -1
  40. package/build/contexts/api_provider.d.ts +1 -1
  41. package/build/contexts/api_provider.d.ts.map +1 -1
  42. package/build/contexts/api_provider.js +3 -3
  43. package/build/contexts/api_provider.js.map +1 -1
  44. package/build/contexts/chat_context.d.ts +5 -3
  45. package/build/contexts/chat_context.d.ts.map +1 -1
  46. package/build/contexts/chat_context.js +8 -3
  47. package/build/contexts/chat_context.js.map +1 -1
  48. package/build/contexts/conversations_context.d.ts +14 -0
  49. package/build/contexts/conversations_context.d.ts.map +1 -0
  50. package/build/contexts/conversations_context.js +38 -0
  51. package/build/contexts/conversations_context.js.map +1 -0
  52. package/build/hooks/groups/use_group_members_for_new_conversation.d.ts +226 -0
  53. package/build/hooks/groups/use_group_members_for_new_conversation.d.ts.map +1 -0
  54. package/build/hooks/groups/use_group_members_for_new_conversation.js +54 -0
  55. package/build/hooks/groups/use_group_members_for_new_conversation.js.map +1 -0
  56. package/build/hooks/groups/use_groups_conversation_create.d.ts +9 -0
  57. package/build/hooks/groups/use_groups_conversation_create.d.ts.map +1 -0
  58. package/build/hooks/groups/use_groups_conversation_create.js +36 -0
  59. package/build/hooks/groups/use_groups_conversation_create.js.map +1 -0
  60. package/build/hooks/use_api.d.ts +41 -41
  61. package/build/hooks/use_api.d.ts.map +1 -1
  62. package/build/hooks/use_api.js +5 -0
  63. package/build/hooks/use_api.js.map +1 -1
  64. package/build/hooks/use_api_client.d.ts.map +1 -1
  65. package/build/hooks/use_api_client.js +5 -3
  66. package/build/hooks/use_api_client.js.map +1 -1
  67. package/build/hooks/use_chat_permissions.d.ts +14 -14
  68. package/build/hooks/use_conversations.d.ts +6 -32
  69. package/build/hooks/use_conversations.d.ts.map +1 -1
  70. package/build/hooks/use_conversations.js +15 -14
  71. package/build/hooks/use_conversations.js.map +1 -1
  72. package/build/hooks/use_conversations_actions.d.ts +221 -0
  73. package/build/hooks/use_conversations_actions.d.ts.map +1 -0
  74. package/build/hooks/use_conversations_actions.js +103 -0
  75. package/build/hooks/use_conversations_actions.js.map +1 -0
  76. package/build/hooks/use_conversations_cache.d.ts +18 -0
  77. package/build/hooks/use_conversations_cache.d.ts.map +1 -0
  78. package/build/hooks/{use_conversation_jolt_events.js → use_conversations_cache.js} +27 -17
  79. package/build/hooks/use_conversations_cache.js.map +1 -0
  80. package/build/hooks/use_conversations_jolt_events.d.ts +3 -0
  81. package/build/hooks/use_conversations_jolt_events.d.ts.map +1 -0
  82. package/build/hooks/use_conversations_jolt_events.js +15 -0
  83. package/build/hooks/use_conversations_jolt_events.js.map +1 -0
  84. package/build/hooks/use_current_person.d.ts +15 -0
  85. package/build/hooks/use_current_person.d.ts.map +1 -1
  86. package/build/hooks/use_current_person.js +26 -9
  87. package/build/hooks/use_current_person.js.map +1 -1
  88. package/build/hooks/use_giphy.d.ts +9 -0
  89. package/build/hooks/use_giphy.d.ts.map +1 -0
  90. package/build/hooks/use_giphy.js +63 -0
  91. package/build/hooks/use_giphy.js.map +1 -0
  92. package/build/hooks/use_groups.d.ts +26 -26
  93. package/build/hooks/use_groups_groups.d.ts +26 -26
  94. package/build/hooks/use_jolt.d.ts.map +1 -1
  95. package/build/hooks/use_jolt.js +42 -20
  96. package/build/hooks/use_jolt.js.map +1 -1
  97. package/build/hooks/use_message_create.d.ts +11 -0
  98. package/build/hooks/use_message_create.d.ts.map +1 -0
  99. package/build/hooks/use_message_create.js +35 -0
  100. package/build/hooks/use_message_create.js.map +1 -0
  101. package/build/hooks/use_suspense_api.d.ts.map +1 -1
  102. package/build/hooks/use_suspense_api.js +5 -0
  103. package/build/hooks/use_suspense_api.js.map +1 -1
  104. package/build/hooks/use_teams.d.ts +26 -26
  105. package/build/index.d.ts +2 -2
  106. package/build/index.d.ts.map +1 -1
  107. package/build/index.js +2 -2
  108. package/build/index.js.map +1 -1
  109. package/build/navigation/index.d.ts +65 -38
  110. package/build/navigation/index.d.ts.map +1 -1
  111. package/build/navigation/index.js +29 -10
  112. package/build/navigation/index.js.map +1 -1
  113. package/build/screens/conversation_details_screen.js +2 -2
  114. package/build/screens/conversation_details_screen.js.map +1 -1
  115. package/build/screens/conversation_filter_recipients/components/checkbox_row.d.ts +10 -0
  116. package/build/screens/conversation_filter_recipients/components/checkbox_row.d.ts.map +1 -0
  117. package/build/screens/conversation_filter_recipients/components/checkbox_row.js +74 -0
  118. package/build/screens/conversation_filter_recipients/components/checkbox_row.js.map +1 -0
  119. package/build/screens/conversation_filter_recipients/components/header_row.d.ts +10 -0
  120. package/build/screens/conversation_filter_recipients/components/header_row.d.ts.map +1 -0
  121. package/build/screens/conversation_filter_recipients/components/header_row.js +69 -0
  122. package/build/screens/conversation_filter_recipients/components/header_row.js.map +1 -0
  123. package/build/screens/conversation_filter_recipients/components/navigation_header.d.ts +5 -0
  124. package/build/screens/conversation_filter_recipients/components/navigation_header.d.ts.map +1 -0
  125. package/build/screens/conversation_filter_recipients/components/navigation_header.js +46 -0
  126. package/build/screens/conversation_filter_recipients/components/navigation_header.js.map +1 -0
  127. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.d.ts +17 -0
  128. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.d.ts.map +1 -0
  129. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.js +37 -0
  130. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.js.map +1 -0
  131. package/build/screens/{create → conversation_filter_recipients}/conversation_filter_recipients_screen.d.ts +1 -3
  132. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.d.ts.map +1 -0
  133. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.js +87 -0
  134. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.js.map +1 -0
  135. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.d.ts +10 -0
  136. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.d.ts.map +1 -0
  137. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.js +32 -0
  138. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.js.map +1 -0
  139. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.d.ts +8 -0
  140. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.d.ts.map +1 -0
  141. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.js +65 -0
  142. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.js.map +1 -0
  143. package/build/screens/conversation_filter_recipients/types.d.ts +38 -0
  144. package/build/screens/conversation_filter_recipients/types.d.ts.map +1 -0
  145. package/build/screens/conversation_filter_recipients/types.js +6 -0
  146. package/build/screens/conversation_filter_recipients/types.js.map +1 -0
  147. package/build/screens/conversation_filters/hooks/filters.d.ts +40 -40
  148. package/build/screens/conversation_filters/hooks/filters.js +1 -1
  149. package/build/screens/conversation_filters/hooks/filters.js.map +1 -1
  150. package/build/screens/conversation_new/components/form_list.d.ts +12 -0
  151. package/build/screens/conversation_new/components/form_list.d.ts.map +1 -0
  152. package/build/screens/conversation_new/components/form_list.js +42 -0
  153. package/build/screens/conversation_new/components/form_list.js.map +1 -0
  154. package/build/screens/conversation_new/components/groups_form.d.ts +7 -0
  155. package/build/screens/conversation_new/components/groups_form.d.ts.map +1 -0
  156. package/build/screens/conversation_new/components/groups_form.js +105 -0
  157. package/build/screens/conversation_new/components/groups_form.js.map +1 -0
  158. package/build/screens/conversation_new/components/source_app_error_card.d.ts +2 -0
  159. package/build/screens/conversation_new/components/source_app_error_card.d.ts.map +1 -0
  160. package/build/screens/conversation_new/components/source_app_error_card.js +16 -0
  161. package/build/screens/conversation_new/components/source_app_error_card.js.map +1 -0
  162. package/build/screens/conversation_new/components/team_form.d.ts +8 -0
  163. package/build/screens/conversation_new/components/team_form.d.ts.map +1 -0
  164. package/build/screens/conversation_new/components/team_form.js +11 -0
  165. package/build/screens/conversation_new/components/team_form.js.map +1 -0
  166. package/build/screens/conversation_new/conversation_new_screen.d.ts +15 -0
  167. package/build/screens/conversation_new/conversation_new_screen.d.ts.map +1 -0
  168. package/build/screens/conversation_new/conversation_new_screen.js +16 -0
  169. package/build/screens/conversation_new/conversation_new_screen.js.map +1 -0
  170. package/build/screens/conversation_screen.d.ts +1 -0
  171. package/build/screens/conversation_screen.d.ts.map +1 -1
  172. package/build/screens/conversation_screen.js +1 -1
  173. package/build/screens/conversation_screen.js.map +1 -1
  174. package/build/screens/conversation_select_recipients/components/groups_without_chat_disclaimer_row.d.ts +2 -0
  175. package/build/screens/conversation_select_recipients/components/groups_without_chat_disclaimer_row.d.ts.map +1 -0
  176. package/build/screens/conversation_select_recipients/components/groups_without_chat_disclaimer_row.js +17 -0
  177. package/build/screens/conversation_select_recipients/components/groups_without_chat_disclaimer_row.js.map +1 -0
  178. package/build/screens/conversation_select_recipients/components/recipient_link_row.d.ts +12 -0
  179. package/build/screens/conversation_select_recipients/components/recipient_link_row.d.ts.map +1 -0
  180. package/build/screens/conversation_select_recipients/components/recipient_link_row.js +61 -0
  181. package/build/screens/conversation_select_recipients/components/recipient_link_row.js.map +1 -0
  182. package/build/screens/conversation_select_recipients/components/view_more_link_row.d.ts +7 -0
  183. package/build/screens/conversation_select_recipients/components/view_more_link_row.d.ts.map +1 -0
  184. package/build/screens/conversation_select_recipients/components/view_more_link_row.js +21 -0
  185. package/build/screens/conversation_select_recipients/components/view_more_link_row.js.map +1 -0
  186. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.d.ts +4 -0
  187. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.d.ts.map +1 -0
  188. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.js +48 -0
  189. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.js.map +1 -0
  190. package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.d.ts +4 -0
  191. package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.d.ts.map +1 -0
  192. package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.js +86 -0
  193. package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.js.map +1 -0
  194. package/build/screens/conversation_select_recipients/types/screen_props.d.ts +9 -0
  195. package/build/screens/conversation_select_recipients/types/screen_props.d.ts.map +1 -0
  196. package/build/screens/conversation_select_recipients/types/screen_props.js +2 -0
  197. package/build/screens/conversation_select_recipients/types/screen_props.js.map +1 -0
  198. package/build/screens/conversations/components/list_header_component.d.ts.map +1 -1
  199. package/build/screens/conversations/components/list_header_component.js +22 -4
  200. package/build/screens/conversations/components/list_header_component.js.map +1 -1
  201. package/build/screens/conversations/conversations_screen.d.ts +2 -1
  202. package/build/screens/conversations/conversations_screen.d.ts.map +1 -1
  203. package/build/screens/conversations/conversations_screen.js +35 -11
  204. package/build/screens/conversations/conversations_screen.js.map +1 -1
  205. package/build/screens/message_actions_screen.d.ts +2 -2
  206. package/build/screens/message_actions_screen.d.ts.map +1 -1
  207. package/build/screens/message_actions_screen.js.map +1 -1
  208. package/build/screens/send_giphy_screen.d.ts +10 -0
  209. package/build/screens/send_giphy_screen.d.ts.map +1 -0
  210. package/build/screens/send_giphy_screen.js +126 -0
  211. package/build/screens/send_giphy_screen.js.map +1 -0
  212. package/build/types/resources/groups/groups_group_resource.d.ts +1 -1
  213. package/build/types/resources/groups/groups_group_resource.js.map +1 -1
  214. package/build/types/resources/groups/groups_member_resource_with_person.d.ts +14 -0
  215. package/build/types/resources/groups/groups_member_resource_with_person.d.ts.map +1 -0
  216. package/build/types/resources/groups/groups_member_resource_with_person.js +2 -0
  217. package/build/types/resources/groups/groups_member_resource_with_person.js.map +1 -0
  218. package/build/types/resources/member.d.ts +0 -10
  219. package/build/types/resources/member.d.ts.map +1 -1
  220. package/build/types/resources/member.js.map +1 -1
  221. package/build/types/resources/oauth_token.d.ts +4 -4
  222. package/build/types/resources/oauth_token.d.ts.map +1 -1
  223. package/build/types/resources/oauth_token.js.map +1 -1
  224. package/build/utils/cache/page_mutations.d.ts +18 -0
  225. package/build/utils/cache/page_mutations.d.ts.map +1 -1
  226. package/build/utils/cache/page_mutations.js +13 -0
  227. package/build/utils/cache/page_mutations.js.map +1 -1
  228. package/build/utils/client/client.d.ts +4 -8
  229. package/build/utils/client/client.d.ts.map +1 -1
  230. package/build/utils/client/client.js +10 -9
  231. package/build/utils/client/client.js.map +1 -1
  232. package/build/utils/destructure_chat_group_graph_id.d.ts +10 -0
  233. package/build/utils/destructure_chat_group_graph_id.d.ts.map +1 -0
  234. package/build/utils/destructure_chat_group_graph_id.js +8 -0
  235. package/build/utils/destructure_chat_group_graph_id.js.map +1 -0
  236. package/build/utils/index.d.ts +1 -0
  237. package/build/utils/index.d.ts.map +1 -1
  238. package/build/utils/index.js +1 -0
  239. package/build/utils/index.js.map +1 -1
  240. package/build/utils/request/conversation.d.ts +1 -3
  241. package/build/utils/request/conversation.d.ts.map +1 -1
  242. package/build/utils/request/conversation.js +37 -30
  243. package/build/utils/request/conversation.js.map +1 -1
  244. package/build/utils/session.d.ts +6 -2
  245. package/build/utils/session.d.ts.map +1 -1
  246. package/build/utils/session.js +6 -1
  247. package/build/utils/session.js.map +1 -1
  248. package/build/utils/uri.d.ts +10 -2
  249. package/build/utils/uri.d.ts.map +1 -1
  250. package/build/utils/uri.js +24 -6
  251. package/build/utils/uri.js.map +1 -1
  252. package/build/vendor/tapestry/alias_tokens_color_map.d.ts +2 -0
  253. package/build/vendor/tapestry/alias_tokens_color_map.d.ts.map +1 -1
  254. package/build/vendor/tapestry/alias_tokens_color_map.js +2 -0
  255. package/build/vendor/tapestry/alias_tokens_color_map.js.map +1 -1
  256. package/package.json +4 -3
  257. package/src/__tests__/hooks/useTheme.tsx +1 -1
  258. package/src/__tests__/utils/cache/page_mutations.ts +49 -15
  259. package/src/__tests__/{client.ts → utils/client.ts} +7 -115
  260. package/src/__tests__/{session.ts → utils/session.ts} +4 -4
  261. package/src/__tests__/utils/uri.ts +107 -0
  262. package/src/components/conversation/message_form.tsx +127 -58
  263. package/src/components/conversations/action_toggle_button.tsx +2 -1
  264. package/src/components/conversations/conversation_actions.tsx +41 -14
  265. package/src/components/conversations/conversations.tsx +39 -52
  266. package/src/components/display/action_button.tsx +4 -3
  267. package/src/components/display/banner.tsx +7 -1
  268. package/src/components/display/banner_collapsible.tsx +6 -1
  269. package/src/components/display/child_notice.tsx +9 -3
  270. package/src/components/display/person.tsx +4 -3
  271. package/src/components/primitive/banner_primitive.tsx +12 -6
  272. package/src/contexts/api_provider.tsx +3 -3
  273. package/src/contexts/chat_context.tsx +13 -6
  274. package/src/contexts/conversations_context.tsx +69 -0
  275. package/src/hooks/groups/use_group_members_for_new_conversation.ts +62 -0
  276. package/src/hooks/groups/use_groups_conversation_create.ts +50 -0
  277. package/src/hooks/use_api.ts +11 -5
  278. package/src/hooks/use_api_client.ts +7 -3
  279. package/src/hooks/use_conversations.ts +34 -16
  280. package/src/hooks/use_conversations_actions.ts +119 -0
  281. package/src/hooks/{use_conversation_jolt_events.ts → use_conversations_cache.ts} +35 -20
  282. package/src/hooks/use_conversations_jolt_events.ts +25 -0
  283. package/src/hooks/use_current_person.ts +37 -9
  284. package/src/hooks/use_giphy.ts +97 -0
  285. package/src/hooks/use_jolt.ts +56 -20
  286. package/src/hooks/use_message_create.ts +55 -0
  287. package/src/hooks/use_suspense_api.ts +6 -0
  288. package/src/index.tsx +2 -1
  289. package/src/navigation/index.tsx +39 -10
  290. package/src/screens/conversation_details_screen.tsx +2 -2
  291. package/src/screens/conversation_filter_recipients/components/checkbox_row.tsx +101 -0
  292. package/src/screens/conversation_filter_recipients/components/header_row.tsx +99 -0
  293. package/src/screens/conversation_filter_recipients/components/navigation_header.tsx +68 -0
  294. package/src/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.tsx +53 -0
  295. package/src/screens/conversation_filter_recipients/conversation_filter_recipients_screen.tsx +120 -0
  296. package/src/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.tsx +50 -0
  297. package/src/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.ts +90 -0
  298. package/src/screens/conversation_filter_recipients/types.tsx +47 -0
  299. package/src/screens/conversation_filters/hooks/filters.ts +1 -1
  300. package/src/screens/conversation_new/components/form_list.tsx +67 -0
  301. package/src/screens/conversation_new/components/groups_form.tsx +163 -0
  302. package/src/screens/conversation_new/components/source_app_error_card.tsx +24 -0
  303. package/src/screens/conversation_new/components/team_form.tsx +18 -0
  304. package/src/screens/conversation_new/conversation_new_screen.tsx +29 -0
  305. package/src/screens/conversation_screen.tsx +2 -1
  306. package/src/screens/conversation_select_recipients/components/groups_without_chat_disclaimer_row.tsx +21 -0
  307. package/src/screens/conversation_select_recipients/components/recipient_link_row.tsx +91 -0
  308. package/src/screens/conversation_select_recipients/components/view_more_link_row.tsx +30 -0
  309. package/src/screens/conversation_select_recipients/conversation_select_group_recipients_screen.tsx +79 -0
  310. package/src/screens/conversation_select_recipients/conversation_select_recipients_screen.tsx +121 -0
  311. package/src/screens/conversation_select_recipients/types/screen_props.tsx +11 -0
  312. package/src/screens/conversations/components/list_header_component.tsx +25 -4
  313. package/src/screens/conversations/conversations_screen.tsx +39 -17
  314. package/src/screens/message_actions_screen.tsx +2 -2
  315. package/src/screens/send_giphy_screen.tsx +184 -0
  316. package/src/types/resources/groups/groups_group_resource.ts +1 -1
  317. package/src/types/resources/groups/groups_member_resource_with_person.ts +13 -0
  318. package/src/types/resources/member.ts +0 -11
  319. package/src/types/resources/oauth_token.ts +4 -4
  320. package/src/utils/cache/page_mutations.ts +22 -0
  321. package/src/utils/client/client.ts +13 -13
  322. package/src/utils/destructure_chat_group_graph_id.ts +25 -0
  323. package/src/utils/index.ts +1 -0
  324. package/src/utils/request/conversation.ts +39 -34
  325. package/src/utils/session.ts +10 -4
  326. package/src/utils/uri.ts +30 -6
  327. package/src/vendor/tapestry/alias_tokens_color_map.ts +3 -0
  328. package/build/contexts/swipeable_active_conversation.d.ts +0 -11
  329. package/build/contexts/swipeable_active_conversation.d.ts.map +0 -1
  330. package/build/contexts/swipeable_active_conversation.js +0 -16
  331. package/build/contexts/swipeable_active_conversation.js.map +0 -1
  332. package/build/hooks/use_conversation_jolt_events.d.ts +0 -2
  333. package/build/hooks/use_conversation_jolt_events.d.ts.map +0 -1
  334. package/build/hooks/use_conversation_jolt_events.js.map +0 -1
  335. package/build/screens/create/conversation_create_screen.d.ts +0 -9
  336. package/build/screens/create/conversation_create_screen.d.ts.map +0 -1
  337. package/build/screens/create/conversation_create_screen.js +0 -122
  338. package/build/screens/create/conversation_create_screen.js.map +0 -1
  339. package/build/screens/create/conversation_filter_recipients_screen.d.ts.map +0 -1
  340. package/build/screens/create/conversation_filter_recipients_screen.js +0 -52
  341. package/build/screens/create/conversation_filter_recipients_screen.js.map +0 -1
  342. package/build/screens/create/conversation_select_recipients_screen.d.ts +0 -8
  343. package/build/screens/create/conversation_select_recipients_screen.d.ts.map +0 -1
  344. package/build/screens/create/conversation_select_recipients_screen.js +0 -97
  345. package/build/screens/create/conversation_select_recipients_screen.js.map +0 -1
  346. package/src/contexts/swipeable_active_conversation.tsx +0 -27
  347. package/src/screens/create/conversation_create_screen.tsx +0 -151
  348. package/src/screens/create/conversation_filter_recipients_screen.tsx +0 -79
  349. package/src/screens/create/conversation_select_recipients_screen.tsx +0 -128
@@ -4,10 +4,10 @@ import {
4
4
  useInfiniteQuery,
5
5
  useQuery,
6
6
  } from '@tanstack/react-query'
7
- import { ApiCollection, ApiResource, ResourceObject } from '../types'
7
+ import { ApiCollection, ApiError, ApiResource, ResourceObject } from '../types'
8
8
  import { GetRequest, RequestData } from '../utils/client/types'
9
9
  import { App, useApiClient } from './use_api_client'
10
- import { getRequestQueryKey } from './use_suspense_api'
10
+ import { getRequestQueryKey, RequestQueryKey } from './use_suspense_api'
11
11
 
12
12
  interface ApiGetOptions extends GetRequest {
13
13
  app?: App
@@ -16,9 +16,15 @@ interface ApiGetOptions extends GetRequest {
16
16
 
17
17
  export const useApiGet = <T extends ResourceObject | ResourceObject[]>(args: ApiGetOptions) => {
18
18
  type Resource = ApiResource<T>
19
+ const apiClient = useApiClient()
19
20
 
20
- const { data, ...query } = useQuery<Resource, Response>({
21
+ const { data, ...query } = useQuery<Resource, ApiError>({
21
22
  queryKey: getRequestQueryKey(args),
23
+ queryFn: ({ queryKey }) => {
24
+ const [url, d, headers, app = 'chat'] = queryKey as RequestQueryKey
25
+
26
+ return apiClient[app].get({ url, data: d, headers }) as Promise<Resource>
27
+ },
22
28
  enabled: args.enabled,
23
29
  })
24
30
 
@@ -42,7 +48,7 @@ export const useApiPaginator = <T extends ResourceObject>(
42
48
  const apiClient = useApiClient()
43
49
  const query = useInfiniteQuery<
44
50
  ApiCollection<T>,
45
- Response,
51
+ ApiError,
46
52
  InfiniteData<ApiCollection<T>>,
47
53
  any,
48
54
  Partial<RequestData> | undefined
@@ -56,7 +62,7 @@ export const useApiPaginator = <T extends ResourceObject>(
56
62
  const offset = pageParam?.offset || args.data.offset
57
63
  const data = { ...args.data, where, offset }
58
64
 
59
- return apiClient[app].get({
65
+ return apiClient[app].get<ApiCollection<T>>({
60
66
  url: args.url,
61
67
  data,
62
68
  })
@@ -1,6 +1,7 @@
1
1
  import { useContext, useMemo } from 'react'
2
2
  import { ChatContext } from '../contexts/chat_context'
3
3
  import { Client } from '../utils/client'
4
+ import { Uri } from '../utils'
4
5
 
5
6
  export type App = 'chat' | 'groups' | 'services'
6
7
  const apps: App[] = ['chat', 'groups', 'services']
@@ -9,18 +10,21 @@ export type ApiClient = { [_K in App]: Client }
9
10
 
10
11
  export const useApiClient = () => {
11
12
  const { session, onUnauthorizedResponse } = useContext(ChatContext)
13
+
14
+ const uri = useMemo(() => new Uri({ session }), [session])
15
+
12
16
  const api = useMemo(
13
17
  () =>
14
18
  apps.reduce((acc, app) => {
15
19
  acc[app] = new Client({
16
- app,
17
- session,
20
+ root: uri.api(`/${app}/v2`),
21
+ defaultHeaders: uri.headers,
18
22
  version: '2018-11-01',
19
23
  onUnauthorizedResponse,
20
24
  })
21
25
  return acc
22
26
  }, {} as ApiClient),
23
- [session, onUnauthorizedResponse]
27
+ [uri, onUnauthorizedResponse]
24
28
  )
25
29
 
26
30
  return api
@@ -1,25 +1,43 @@
1
+ import { InfiniteData, UseSuspenseInfiniteQueryResult } from '@tanstack/react-query'
1
2
  import { useMemo } from 'react'
2
- import { ConversationResource } from '../types'
3
- import { useSuspensePaginator } from './use_suspense_api'
3
+ import { ApiCollection, ConversationResource } from '../types'
4
4
  import { ConversationRequestArgs, getConversationsRequestArgs } from '../utils/request/conversation'
5
+ import { useSuspensePaginator } from './use_suspense_api'
5
6
 
6
- export function useConversations(args?: Partial<ConversationRequestArgs>) {
7
+ export type ConversationPaginationResult = UseSuspenseInfiniteQueryResult<
8
+ InfiniteData<ApiCollection<ConversationResource>, unknown>,
9
+ Response
10
+ >
11
+
12
+ export type UseConversationsValue = Pick<
13
+ ConversationPaginationResult,
14
+ | 'isFetching'
15
+ | 'isError'
16
+ | 'error'
17
+ | 'fetchNextPage'
18
+ | 'hasNextPage'
19
+ | 'isFetched'
20
+ | 'isRefetching'
21
+ > & {
22
+ conversations: ConversationResource[]
23
+ refetch: () => Promise<any>
24
+ }
25
+
26
+ export function useConversations(args?: Partial<ConversationRequestArgs>): UseConversationsValue {
7
27
  const requestArgs = getConversationsRequestArgs(args)
8
28
  const { data, ...rest } = useSuspensePaginator<ConversationResource>(requestArgs)
9
29
 
10
- const conversations = useMemo(
11
- () =>
12
- data.sort((a, b) => {
13
- const dateA = a.lastMessageCreatedAt || a.createdAt
14
- const dateB = b.lastMessageCreatedAt || b.createdAt
15
- if (a.lastMessageCreatedAt && !b.lastMessageCreatedAt) return 1
16
- if (!a.lastMessageCreatedAt && b.lastMessageCreatedAt) return -1
17
- if (dateB > dateA) return 1
18
- if (dateB < dateA) return -1
19
- return 0
20
- }),
21
- [data]
22
- )
30
+ const conversations = useMemo(() => data.sort(sortByLastMessage), [data])
23
31
 
24
32
  return { conversations, ...rest }
25
33
  }
34
+
35
+ function sortByLastMessage(a: ConversationResource, b: ConversationResource): number {
36
+ const dateA = a.lastMessageCreatedAt || a.createdAt
37
+ const dateB = b.lastMessageCreatedAt || b.createdAt
38
+ if (a.lastMessageCreatedAt && !b.lastMessageCreatedAt) return 1
39
+ if (!a.lastMessageCreatedAt && b.lastMessageCreatedAt) return -1
40
+ if (dateB > dateA) return 1
41
+ if (dateB < dateA) return -1
42
+ return 0
43
+ }
@@ -0,0 +1,119 @@
1
+ import { useMutation } from '@tanstack/react-query'
2
+ import { Alert } from 'react-native'
3
+ import { useConversationsContext } from '../contexts/conversations_context'
4
+ import { ApiResource, ConversationResource } from '../types'
5
+ import { useApiClient } from './use_api_client'
6
+ import { useConversationsCache } from './use_conversations_cache'
7
+ import { useCurrentPersonCache } from './use_current_person'
8
+
9
+ export const useConversationsMarkRead = ({
10
+ conversation,
11
+ }: {
12
+ conversation: ConversationResource
13
+ }) => {
14
+ const apiClient = useApiClient()
15
+ const { args } = useConversationsContext()
16
+ const currentPersonCache = useCurrentPersonCache()
17
+ const { update, invalidate } = useConversationsCache(args)
18
+
19
+ function handlePersonUnreadCount(read: boolean) {
20
+ currentPersonCache.update({}, person => {
21
+ const currentUnread = person.unreadCount
22
+ const updatedUnread = read ? Math.max(currentUnread - 1, 0) : currentUnread + 1
23
+ return { ...person, unreadCount: updatedUnread }
24
+ })
25
+ }
26
+
27
+ const { mutate: handleMarkRead, ...mutation } = useMutation({
28
+ onMutate: async (read: boolean) => {
29
+ update({
30
+ ...conversation,
31
+ unreadCount: read ? 0 : 1,
32
+ })
33
+ handlePersonUnreadCount(read)
34
+ },
35
+ mutationKey: ['markRead', conversation.id],
36
+ mutationFn: async (read: boolean) => {
37
+ const action = read ? 'mark_read' : 'mark_unread'
38
+
39
+ return apiClient.chat.post<ApiResource<ConversationResource>>({
40
+ url: `/me/conversations/${conversation.id}/${action}`,
41
+ data: { data: { type: '', attributes: {} }, fields: { Conversation: 'unread_count' } },
42
+ })
43
+ },
44
+ onSuccess: (response: ApiResource<ConversationResource>) => {
45
+ update(response.data)
46
+ },
47
+ onError: () => {
48
+ Alert.alert('Oops', 'Something went wrong updating this conversation, please try again')
49
+ invalidate()
50
+ },
51
+ })
52
+
53
+ return {
54
+ read: conversation.unreadCount < 1, // prefer cache
55
+ markRead: handleMarkRead,
56
+ ...mutation,
57
+ }
58
+ }
59
+
60
+ export const useConversationsMute = ({ conversation }: { conversation: ConversationResource }) => {
61
+ const apiClient = useApiClient()
62
+ const { args } = useConversationsContext()
63
+ const { update, invalidate } = useConversationsCache(args)
64
+
65
+ const { mutate: setMuted, ...mutation } = useMutation({
66
+ onMutate: async (muted: boolean) => {
67
+ update({
68
+ ...conversation,
69
+ muted,
70
+ })
71
+ },
72
+ mutationKey: ['muteConversation'],
73
+ mutationFn: async (muted: boolean) => {
74
+ const action = muted ? 'mute' : 'unmute'
75
+
76
+ return apiClient.chat.post<ApiResource<ConversationResource>>({
77
+ url: `/me/conversations/${conversation.id}/${action}`,
78
+ data: { data: { type: '', attributes: {} }, fields: { Conversation: 'muted' } },
79
+ })
80
+ },
81
+ onSuccess: (response: ApiResource<ConversationResource>) => {
82
+ update(response.data)
83
+ },
84
+ onError: () => {
85
+ Alert.alert('Oops', 'Something went wrong muting this conversation, please try again')
86
+ invalidate()
87
+ },
88
+ })
89
+
90
+ return {
91
+ muted: conversation.muted, // prefer cache
92
+ setMuted,
93
+ ...mutation,
94
+ }
95
+ }
96
+
97
+ export const useMarkAllRead = () => {
98
+ const apiClient = useApiClient()
99
+ const { args } = useConversationsContext()
100
+ const { invalidate, updateAll } = useConversationsCache(args)
101
+ const { mutate: markAllRead, ...query } = useMutation({
102
+ onMutate: () => {
103
+ updateAll({
104
+ unreadCount: 0,
105
+ })
106
+ },
107
+ mutationKey: ['markAllRead', args],
108
+ mutationFn: () =>
109
+ apiClient.chat.post({
110
+ url: '/me/mark_all_read',
111
+ }),
112
+ onSettled: invalidate,
113
+ })
114
+
115
+ return {
116
+ markAllRead,
117
+ ...query,
118
+ }
119
+ }
@@ -1,23 +1,20 @@
1
1
  import { InfiniteData, useQueryClient } from '@tanstack/react-query'
2
2
  import { ApiCollection, ApiResource, ConversationResource } from '../types'
3
- import { deleteRecordInPagesData, updateOrCreateRecordInPagesData } from '../utils'
3
+ import {
4
+ deleteRecordInPagesData,
5
+ updateAllRecordsInPagesData,
6
+ updateOrCreateRecordInPagesData,
7
+ } from '../utils'
8
+ import { ConversationRequestArgs, getConversationsRequestArgs } from '../utils/request/conversation'
4
9
  import { useApiClient } from './use_api_client'
5
- import { useCurrentPerson } from './use_current_person'
6
- import { useJoltChannel, useJoltEvent } from './use_jolt'
7
10
  import { getRequestQueryKey } from './use_suspense_api'
8
- import { JoltConversationEvent } from '../types/jolt_events'
9
- import { ConversationDeletedEvent } from '../types/jolt_events/conversation_events'
10
- import { getConversationsRequestArgs } from '../utils/request/conversation'
11
11
 
12
12
  type QueryData = InfiniteData<ApiCollection<ConversationResource>>
13
13
 
14
- export function useConversationsJoltEvents() {
14
+ export function useConversationsCache(args?: Partial<ConversationRequestArgs>) {
15
15
  const apiClient = useApiClient()
16
16
  const queryClient = useQueryClient()
17
- const currentPerson = useCurrentPerson()
18
- const joltChannel = useJoltChannel(`chat.people.${currentPerson.id}`)
19
-
20
- const conversationsRequestArgs = getConversationsRequestArgs()
17
+ const conversationsRequestArgs = getConversationsRequestArgs(args)
21
18
  const conversationQueryKey = getRequestQueryKey(conversationsRequestArgs)
22
19
 
23
20
  const fetchConversation = async (id: number) => {
@@ -33,10 +30,7 @@ export function useConversationsJoltEvents() {
33
30
  return data
34
31
  }
35
32
 
36
- const handleConversationUpdateOrCreate = async (e: JoltConversationEvent) => {
37
- const { data } = e.data
38
- const conversation: ConversationResource = await fetchConversation(data.id).catch(c => c)
39
-
33
+ const updateOrCreate = async (conversation: ConversationResource) => {
40
34
  queryClient.setQueryData<QueryData>(conversationQueryKey, prev =>
41
35
  updateOrCreateRecordInPagesData({
42
36
  data: prev,
@@ -48,16 +42,37 @@ export function useConversationsJoltEvents() {
48
42
  )
49
43
  }
50
44
 
51
- const handleConversationDestroy = (e: ConversationDeletedEvent) => {
45
+ const updateAll = async (update: Partial<ConversationResource>) => {
46
+ queryClient.setQueryData<QueryData>(conversationQueryKey, prev =>
47
+ updateAllRecordsInPagesData({
48
+ data: prev,
49
+ processRecord: record => ({ ...record, ...update }),
50
+ })
51
+ )
52
+ }
53
+
54
+ const fetchAndUpdateOrCreate = async ({ id }: { id: number }) => {
55
+ const conversation: ConversationResource = await fetchConversation(id).catch(c => c)
56
+
57
+ updateOrCreate(conversation)
58
+ }
59
+
60
+ const handleConversationDestroy = ({ id }: { id: number }) => {
52
61
  queryClient.setQueryData<QueryData>(conversationQueryKey, prev =>
53
62
  deleteRecordInPagesData({
54
63
  data: prev,
55
- record: { id: e.data.data.id },
64
+ record: { id },
56
65
  })
57
66
  )
58
67
  }
59
68
 
60
- useJoltEvent(joltChannel, 'conversation.updated', handleConversationUpdateOrCreate)
61
- useJoltEvent(joltChannel, 'conversation.created', handleConversationUpdateOrCreate)
62
- useJoltEvent(joltChannel, 'conversation.destroyed', handleConversationDestroy)
69
+ return {
70
+ create: updateOrCreate,
71
+ destroy: handleConversationDestroy,
72
+ fetchCreate: fetchAndUpdateOrCreate,
73
+ fetchUpdate: fetchAndUpdateOrCreate,
74
+ invalidate: () => queryClient.invalidateQueries({ queryKey: conversationQueryKey }),
75
+ update: updateOrCreate,
76
+ updateAll,
77
+ }
63
78
  }
@@ -0,0 +1,25 @@
1
+ import { JoltConversationEvent } from '../types/jolt_events'
2
+ import { ConversationRequestArgs } from '../utils/request/conversation'
3
+ import { useConversationsCache } from './use_conversations_cache'
4
+ import { useCurrentPerson, useCurrentPersonCache } from './use_current_person'
5
+ import { useJoltChannel, useJoltEvent } from './use_jolt'
6
+
7
+ export function useConversationsJoltEvents(args?: Partial<ConversationRequestArgs>) {
8
+ const currentPerson = useCurrentPerson()
9
+ const joltChannel = useJoltChannel(`chat.people.${currentPerson.id}`)
10
+ const cache = useConversationsCache(args)
11
+ const currentPersonCache = useCurrentPersonCache()
12
+
13
+ useJoltEvent(joltChannel, 'conversation.updated', (e: JoltConversationEvent) =>
14
+ cache.fetchUpdate({ id: e.data.data.id })
15
+ )
16
+ useJoltEvent(joltChannel, 'conversation.created', (e: JoltConversationEvent) =>
17
+ cache.fetchCreate({ id: e.data.data.id })
18
+ )
19
+ useJoltEvent(joltChannel, 'conversation.destroyed', (e: JoltConversationEvent) =>
20
+ cache.destroy({ id: e.data.data.id })
21
+ )
22
+
23
+ useJoltEvent(joltChannel, 'STREAM_USER_UPDATED', currentPersonCache.invalidate) // Would be nice to have a non-stream chat event
24
+ useJoltEvent(joltChannel, 'conversation.read', currentPersonCache.invalidate)
25
+ }
@@ -1,15 +1,43 @@
1
+ import { useQueryClient } from '@tanstack/react-query'
1
2
  import { CurrentPersonResource } from '../types'
2
- import { useSuspenseGet } from './use_suspense_api'
3
+ import { getRequestQueryKey, useSuspenseGet } from './use_suspense_api'
4
+ import { ApiResource } from '../types/api_primitives'
3
5
 
4
- export const useCurrentPerson = () => {
5
- const { data: person } = useSuspenseGet<CurrentPersonResource>({
6
- url: '/me',
7
- data: {
8
- fields: {
9
- Person: ['id', 'name', 'avatar', 'can_chat', 'unread_count', 'pco_chat_enabled'],
10
- },
6
+ export const currentPersonRequestArgs = {
7
+ url: '/me',
8
+ data: {
9
+ fields: {
10
+ Person: ['id', 'name', 'avatar', 'can_chat', 'unread_count', 'pco_chat_enabled'],
11
11
  },
12
- })
12
+ },
13
+ }
14
+
15
+ export const currentPersonQueryKey = getRequestQueryKey(currentPersonRequestArgs)
16
+
17
+ export const useCurrentPerson = () => {
18
+ const { data: person } = useSuspenseGet<CurrentPersonResource>(currentPersonRequestArgs)
13
19
 
14
20
  return person
15
21
  }
22
+
23
+ type ProcessRecord<T> = (record: T, update: Partial<T>) => T
24
+
25
+ export const useCurrentPersonCache = () => {
26
+ const queryClient = useQueryClient()
27
+ const handleUpdate = (
28
+ update: Partial<CurrentPersonResource>,
29
+ processRecord: ProcessRecord<CurrentPersonResource> = (r, u) => ({ ...r, ...u })
30
+ ) => {
31
+ queryClient.setQueryData<ApiResource<CurrentPersonResource>>(currentPersonQueryKey, data => {
32
+ if (!data) return data
33
+
34
+ return { ...data, data: processRecord(data.data, update) }
35
+ })
36
+ }
37
+
38
+ const handleInvalidate = () => {
39
+ queryClient.invalidateQueries({ queryKey: currentPersonQueryKey })
40
+ }
41
+
42
+ return { update: handleUpdate, invalidate: handleInvalidate }
43
+ }
@@ -0,0 +1,97 @@
1
+ import { useCallback, useContext, useEffect, useState } from 'react'
2
+ import { DenormalizedGiphyAttachmentResourceForCreate } from '../types/resources/denormalized_attachment_resource'
3
+ import { ChatContext } from '../contexts/chat_context'
4
+
5
+ interface GiphyGif {
6
+ id: string
7
+ url: string
8
+ title: string
9
+ images: {
10
+ original: GiphyVariant
11
+ fixed_height: GiphyVariant
12
+ fixed_height_still: GiphyVariant
13
+ fixed_height_downsampled: GiphyVariant
14
+ fixed_width: GiphyVariant
15
+ fixed_width_still: GiphyVariant
16
+ fixed_width_downsampled: GiphyVariant
17
+ }
18
+ }
19
+
20
+ interface GiphyVariant {
21
+ url: string
22
+ width: number
23
+ height: number
24
+ size: string
25
+ frames: string
26
+ }
27
+
28
+ export function useGiphy(term: string = '') {
29
+ const { giphyApiKey } = useContext(ChatContext)
30
+ const [isSearching, setIsSearching] = useState(false)
31
+ const [results, setResults] = useState<DenormalizedGiphyAttachmentResourceForCreate[]>([])
32
+ const [resultIndex, setResultIndex] = useState(0)
33
+ const result = results[resultIndex]
34
+
35
+ useEffect(() => {
36
+ if (!giphyApiKey || !term) {
37
+ setResults([])
38
+ return
39
+ }
40
+
41
+ setIsSearching(true)
42
+ fetch(`https://api.giphy.com/v1/gifs/search?api_key=${giphyApiKey}&q=${term}&limit=20&rating=g`)
43
+ .then(response => response.json())
44
+ .then(data => {
45
+ const originalGiphys: GiphyGif[] = data.data
46
+ const denormalizedGiphys = denormalizeGiphys(term, originalGiphys)
47
+
48
+ setResults(denormalizedGiphys)
49
+ setResultIndex(0)
50
+ })
51
+ .catch(error => {
52
+ console.error('Error fetching gifs:', error)
53
+ })
54
+ .finally(() => {
55
+ setIsSearching(false)
56
+ })
57
+ }, [giphyApiKey, term])
58
+
59
+ const nextResult = useCallback(() => {
60
+ setResultIndex(oldResultIndex => (oldResultIndex < results.length - 1 ? oldResultIndex + 1 : 0))
61
+ }, [results.length])
62
+
63
+ const prevResult = useCallback(() => {
64
+ setResultIndex(oldResultIndex => (oldResultIndex > 0 ? oldResultIndex - 1 : results.length - 1))
65
+ }, [results.length])
66
+
67
+ return {
68
+ isSearching,
69
+ result,
70
+ resultIndex,
71
+ nextResult,
72
+ prevResult,
73
+ }
74
+ }
75
+
76
+ function denormalizeGiphys(
77
+ term: string,
78
+ giphys: GiphyGif[]
79
+ ): DenormalizedGiphyAttachmentResourceForCreate[] {
80
+ return giphys.map(giphy => ({
81
+ type: 'giphy',
82
+ id: giphy.id,
83
+ title: term,
84
+ original_giphy_title: giphy.title,
85
+ title_link: giphy.url,
86
+ thumb_url: giphy.images.fixed_width.url,
87
+ giphy: {
88
+ original: giphy.images.original,
89
+ fixed_height: giphy.images.fixed_height,
90
+ fixed_height_still: giphy.images.fixed_height_still,
91
+ fixed_height_downsampled: giphy.images.fixed_height_downsampled,
92
+ fixed_width: giphy.images.fixed_width,
93
+ fixed_width_still: giphy.images.fixed_width_still,
94
+ fixed_width_downsampled: giphy.images.fixed_width_downsampled,
95
+ },
96
+ }))
97
+ }
@@ -1,13 +1,17 @@
1
1
  import JoltClient from '@planningcenter/jolt-client'
2
- import { CustomMessage } from '@planningcenter/jolt-client/dist/types/JoltConnection'
2
+ import {
3
+ CustomMessage,
4
+ FetchAuthToken,
5
+ } from '@planningcenter/jolt-client/dist/types/JoltConnection'
3
6
  import {
4
7
  FetchSubscribeToken,
5
8
  JoltSubscription,
6
9
  } from '@planningcenter/jolt-client/dist/types/JoltSubscription'
7
- import { useQuery, useSuspenseQuery } from '@tanstack/react-query'
8
- import { useEffect, useState } from 'react'
10
+ import { useQuery, useQueryClient, useSuspenseQuery } from '@tanstack/react-query'
11
+ import { useCallback, useEffect, useMemo, useState } from 'react'
12
+ import { useChatContext } from '../contexts/chat_context'
9
13
  import { ApiResource } from '../types'
10
- import { useApiClient } from './use_api_client'
14
+ import { Client, Uri } from '../utils'
11
15
 
12
16
  interface JoltResponse {
13
17
  type: 'JoltToken'
@@ -16,28 +20,45 @@ interface JoltResponse {
16
20
  }
17
21
 
18
22
  export const useJoltClient = (): JoltClient | undefined => {
19
- const apiClient = useApiClient()
20
- const { data: joltToken } = useSuspenseQuery<ApiResource<JoltResponse>>({
21
- queryKey: ['jolt-token'],
22
- queryFn: () => {
23
- return apiClient.chat.post({
24
- url: '/me/jolt_authorize',
23
+ const { session } = useChatContext()
24
+ const queryClient = useQueryClient()
25
+ const uri = useMemo(() => new Uri({ session }), [session])
26
+ const apiClient = useMemo(
27
+ () =>
28
+ new Client({
29
+ root: uri.api(`/chat/v2`),
30
+ defaultHeaders: uri.headers,
31
+ version: '2018-11-01',
32
+ }),
33
+ [uri]
34
+ )
35
+
36
+ const fetchJoltToken = useCallback(async () => {
37
+ return apiClient.post<ApiResource<JoltResponse>>({
38
+ url: '/me/jolt_authorize',
39
+ data: {
25
40
  data: {
26
- data: {
27
- type: 'JoltToken',
28
- attributes: {},
29
- },
41
+ type: 'JoltToken',
42
+ attributes: {},
30
43
  },
31
- })
32
- },
44
+ },
45
+ })
46
+ }, [apiClient])
47
+
48
+ const { data: joltToken } = useSuspenseQuery<ApiResource<JoltResponse>>({
49
+ queryKey: ['jolt-token'],
50
+ queryFn: fetchJoltToken,
33
51
  })
34
52
 
35
- const fetchAuthTokenFn = async () => {
36
- return joltToken.data.id || ''
53
+ const fetchAuthTokenFn: FetchAuthToken = () => {
54
+ return queryClient.fetchQuery({
55
+ queryKey: ['jolt-auth-token'],
56
+ queryFn: () => fetchJoltToken().then(res => res.data.id),
57
+ })
37
58
  }
38
59
 
39
- const fetchSubscribeTokenFn: FetchSubscribeToken = (channel: string, connectionId: string) => {
40
- return apiClient.chat
60
+ const fetchSubscribeToken: FetchSubscribeToken = (channel: string, connectionId: string) => {
61
+ return apiClient
41
62
  .post<ApiResource<JoltResponse>>({
42
63
  url: '/me/jolt_subscribe',
43
64
  data: {
@@ -48,6 +69,21 @@ export const useJoltClient = (): JoltClient | undefined => {
48
69
  },
49
70
  })
50
71
  .then(res => res.data.id)
72
+ .catch((res: unknown) => {
73
+ console.error('failed to subscribe to Jolt channel', res)
74
+ return ''
75
+ })
76
+ }
77
+
78
+ const fetchSubscribeTokenFn: FetchSubscribeToken = (
79
+ channel: string,
80
+ connectionId: string,
81
+ options
82
+ ) => {
83
+ return queryClient.fetchQuery({
84
+ queryKey: ['jolt-subscribe-token', channel, connectionId],
85
+ queryFn: () => fetchSubscribeToken(channel, connectionId, options),
86
+ })
51
87
  }
52
88
 
53
89
  const { data: joltClient } = useQuery({
@@ -0,0 +1,55 @@
1
+ import { InfiniteData, useMutation } from '@tanstack/react-query'
2
+ import { getMessagesQueryKey, getMessagesRequestArgs } from './use_conversation_messages'
3
+ import { useApiClient } from './use_api_client'
4
+ import { ApiCollection, ApiResource, MessageResource } from '../types'
5
+ import { chatQueryClient } from '../contexts/api_provider'
6
+ import { updateOrCreateRecordInPagesData } from '../utils'
7
+ import { DenormalizedAttachmentResourceForCreate } from '../types/resources/denormalized_attachment_resource'
8
+
9
+ interface Props {
10
+ conversationId: number
11
+ }
12
+
13
+ export function useMessageCreate({ conversationId }: Props) {
14
+ const apiClient = useApiClient()
15
+ const mutation = useMutation({
16
+ mutationFn: ({
17
+ text,
18
+ attachments,
19
+ }: {
20
+ text: string
21
+ attachments?: DenormalizedAttachmentResourceForCreate[]
22
+ }) => {
23
+ const requestParams = getMessagesRequestArgs({ conversation_id: conversationId })
24
+ const fieldsWithValueJoined = Object.fromEntries(
25
+ Object.entries(requestParams.data.fields).map(([k, v]) => [k, v.join(',')])
26
+ )
27
+
28
+ return apiClient.chat.post<ApiResource<MessageResource>>({
29
+ url: `/me/conversations/${conversationId}/messages`,
30
+ data: {
31
+ ...requestParams.data,
32
+ data: {
33
+ type: 'Message',
34
+ attributes: { text, ...(attachments ? { attachments } : {}) },
35
+ },
36
+ fields: fieldsWithValueJoined,
37
+ },
38
+ })
39
+ },
40
+ onSuccess: (result: ApiResource<MessageResource>) => {
41
+ const updatedMessage = result.data
42
+ type QueryData = InfiniteData<ApiCollection<MessageResource>>
43
+ const queryKey = getMessagesQueryKey({ conversation_id: conversationId })
44
+
45
+ chatQueryClient.setQueryData<QueryData>(queryKey, data =>
46
+ updateOrCreateRecordInPagesData({
47
+ data,
48
+ record: updatedMessage,
49
+ })
50
+ )
51
+ },
52
+ })
53
+
54
+ return mutation
55
+ }