@planningcenter/chat-react-native 3.2.0-rc.9 → 3.3.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 (362) hide show
  1. package/build/components/conversation/message_form/message_form_attachment_image.d.ts +13 -0
  2. package/build/components/conversation/message_form/message_form_attachment_image.d.ts.map +1 -0
  3. package/build/components/conversation/message_form/message_form_attachment_image.js +78 -0
  4. package/build/components/conversation/message_form/message_form_attachment_image.js.map +1 -0
  5. package/build/components/conversation/message_form.d.ts.map +1 -1
  6. package/build/components/conversation/message_form.js +128 -16
  7. package/build/components/conversation/message_form.js.map +1 -1
  8. package/build/components/conversations/conversation_actions.d.ts +2 -2
  9. package/build/components/conversations/conversation_actions.d.ts.map +1 -1
  10. package/build/components/conversations/conversation_actions.js.map +1 -1
  11. package/build/components/conversations/conversation_preview.d.ts +3 -1
  12. package/build/components/conversations/conversation_preview.d.ts.map +1 -1
  13. package/build/components/conversations/conversation_preview.js +2 -2
  14. package/build/components/conversations/conversation_preview.js.map +1 -1
  15. package/build/components/display/action_button.d.ts +2 -1
  16. package/build/components/display/action_button.d.ts.map +1 -1
  17. package/build/components/display/action_button.js +3 -4
  18. package/build/components/display/action_button.js.map +1 -1
  19. package/build/components/display/banner.d.ts +6 -1
  20. package/build/components/display/banner.d.ts.map +1 -1
  21. package/build/components/display/banner.js +2 -2
  22. package/build/components/display/banner.js.map +1 -1
  23. package/build/components/display/banner_collapsible.d.ts +1 -1
  24. package/build/components/display/banner_collapsible.d.ts.map +1 -1
  25. package/build/components/display/banner_collapsible.js +2 -2
  26. package/build/components/display/banner_collapsible.js.map +1 -1
  27. package/build/components/display/child_notice.d.ts +3 -1
  28. package/build/components/display/child_notice.d.ts.map +1 -1
  29. package/build/components/display/child_notice.js +2 -2
  30. package/build/components/display/child_notice.js.map +1 -1
  31. package/build/components/group_conversation_list.d.ts +19 -0
  32. package/build/components/group_conversation_list.d.ts.map +1 -0
  33. package/build/components/group_conversation_list.js +48 -0
  34. package/build/components/group_conversation_list.js.map +1 -0
  35. package/build/components/index.d.ts +1 -0
  36. package/build/components/index.d.ts.map +1 -1
  37. package/build/components/index.js +1 -0
  38. package/build/components/index.js.map +1 -1
  39. package/build/components/primitive/banner_primitive.d.ts +3 -0
  40. package/build/components/primitive/banner_primitive.d.ts.map +1 -1
  41. package/build/components/primitive/banner_primitive.js +4 -4
  42. package/build/components/primitive/banner_primitive.js.map +1 -1
  43. package/build/contexts/api_provider.d.ts +1 -1
  44. package/build/contexts/api_provider.d.ts.map +1 -1
  45. package/build/contexts/api_provider.js +3 -3
  46. package/build/contexts/api_provider.js.map +1 -1
  47. package/build/contexts/chat_context.d.ts +4 -4
  48. package/build/contexts/chat_context.d.ts.map +1 -1
  49. package/build/contexts/chat_context.js +3 -3
  50. package/build/contexts/chat_context.js.map +1 -1
  51. package/build/contexts/conversations_context.js +1 -1
  52. package/build/contexts/conversations_context.js.map +1 -1
  53. package/build/hooks/attachments/supported_extensions.d.ts +2 -0
  54. package/build/hooks/attachments/supported_extensions.d.ts.map +1 -0
  55. package/build/hooks/attachments/supported_extensions.js +48 -0
  56. package/build/hooks/attachments/supported_extensions.js.map +1 -0
  57. package/build/hooks/groups/use_group_members_for_new_conversation.d.ts +235 -0
  58. package/build/hooks/groups/use_group_members_for_new_conversation.d.ts.map +1 -0
  59. package/build/hooks/groups/use_group_members_for_new_conversation.js +55 -0
  60. package/build/hooks/groups/use_group_members_for_new_conversation.js.map +1 -0
  61. package/build/hooks/groups/use_groups_conversation_create.d.ts +9 -0
  62. package/build/hooks/groups/use_groups_conversation_create.d.ts.map +1 -0
  63. package/build/hooks/groups/use_groups_conversation_create.js +36 -0
  64. package/build/hooks/groups/use_groups_conversation_create.js.map +1 -0
  65. package/build/hooks/index.d.ts +4 -0
  66. package/build/hooks/index.d.ts.map +1 -1
  67. package/build/hooks/index.js +4 -0
  68. package/build/hooks/index.js.map +1 -1
  69. package/build/hooks/use_api.d.ts +43 -43
  70. package/build/hooks/use_api.d.ts.map +1 -1
  71. package/build/hooks/use_api.js +5 -0
  72. package/build/hooks/use_api.js.map +1 -1
  73. package/build/hooks/use_api_client.d.ts.map +1 -1
  74. package/build/hooks/use_api_client.js +5 -3
  75. package/build/hooks/use_api_client.js.map +1 -1
  76. package/build/hooks/use_attachment_uploader.d.ts +26 -0
  77. package/build/hooks/use_attachment_uploader.d.ts.map +1 -0
  78. package/build/hooks/use_attachment_uploader.js +111 -0
  79. package/build/hooks/use_attachment_uploader.js.map +1 -0
  80. package/build/hooks/use_chat_permissions.d.ts +14 -14
  81. package/build/hooks/use_conversation.d.ts.map +1 -1
  82. package/build/hooks/use_conversation.js +1 -0
  83. package/build/hooks/use_conversation.js.map +1 -1
  84. package/build/hooks/use_conversations_actions.d.ts.map +1 -1
  85. package/build/hooks/use_conversations_actions.js +10 -0
  86. package/build/hooks/use_conversations_actions.js.map +1 -1
  87. package/build/hooks/use_conversations_jolt_events.d.ts.map +1 -1
  88. package/build/hooks/use_conversations_jolt_events.js +4 -1
  89. package/build/hooks/use_conversations_jolt_events.js.map +1 -1
  90. package/build/hooks/use_current_person.d.ts +15 -0
  91. package/build/hooks/use_current_person.d.ts.map +1 -1
  92. package/build/hooks/use_current_person.js +26 -9
  93. package/build/hooks/use_current_person.js.map +1 -1
  94. package/build/hooks/use_groups.d.ts +26 -26
  95. package/build/hooks/use_groups_groups.d.ts +26 -26
  96. package/build/hooks/use_jolt.d.ts.map +1 -1
  97. package/build/hooks/use_jolt.js +15 -22
  98. package/build/hooks/use_jolt.js.map +1 -1
  99. package/build/hooks/use_message_create.js +2 -2
  100. package/build/hooks/use_message_create.js.map +1 -1
  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/hooks/use_upload_client.d.ts +28 -0
  106. package/build/hooks/use_upload_client.d.ts.map +1 -0
  107. package/build/hooks/use_upload_client.js +32 -0
  108. package/build/hooks/use_upload_client.js.map +1 -0
  109. package/build/index.d.ts +3 -2
  110. package/build/index.d.ts.map +1 -1
  111. package/build/index.js +3 -2
  112. package/build/index.js.map +1 -1
  113. package/build/navigation/index.d.ts +52 -34
  114. package/build/navigation/index.d.ts.map +1 -1
  115. package/build/navigation/index.js +16 -2
  116. package/build/navigation/index.js.map +1 -1
  117. package/build/screens/conversation_details_screen.js +2 -2
  118. package/build/screens/conversation_details_screen.js.map +1 -1
  119. package/build/screens/conversation_filter_recipients/components/checkbox_row.d.ts +10 -0
  120. package/build/screens/conversation_filter_recipients/components/checkbox_row.d.ts.map +1 -0
  121. package/build/screens/conversation_filter_recipients/components/checkbox_row.js +74 -0
  122. package/build/screens/conversation_filter_recipients/components/checkbox_row.js.map +1 -0
  123. package/build/screens/conversation_filter_recipients/components/header_row.d.ts +10 -0
  124. package/build/screens/conversation_filter_recipients/components/header_row.d.ts.map +1 -0
  125. package/build/screens/conversation_filter_recipients/components/header_row.js +69 -0
  126. package/build/screens/conversation_filter_recipients/components/header_row.js.map +1 -0
  127. package/build/screens/conversation_filter_recipients/components/navigation_header.d.ts +5 -0
  128. package/build/screens/conversation_filter_recipients/components/navigation_header.d.ts.map +1 -0
  129. package/build/screens/conversation_filter_recipients/components/navigation_header.js +46 -0
  130. package/build/screens/conversation_filter_recipients/components/navigation_header.js.map +1 -0
  131. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.d.ts +17 -0
  132. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.d.ts.map +1 -0
  133. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.js +37 -0
  134. package/build/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.js.map +1 -0
  135. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.d.ts +1 -3
  136. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.d.ts.map +1 -1
  137. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.js +67 -32
  138. package/build/screens/conversation_filter_recipients/conversation_filter_recipients_screen.js.map +1 -1
  139. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.d.ts +10 -0
  140. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.d.ts.map +1 -0
  141. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.js +32 -0
  142. package/build/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.js.map +1 -0
  143. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.d.ts +8 -0
  144. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.d.ts.map +1 -0
  145. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.js +65 -0
  146. package/build/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.js.map +1 -0
  147. package/build/screens/conversation_filter_recipients/types.d.ts +38 -0
  148. package/build/screens/conversation_filter_recipients/types.d.ts.map +1 -0
  149. package/build/screens/conversation_filter_recipients/types.js +6 -0
  150. package/build/screens/conversation_filter_recipients/types.js.map +1 -0
  151. package/build/screens/conversation_filters/components/conversation_filters.js +5 -2
  152. package/build/screens/conversation_filters/components/conversation_filters.js.map +1 -1
  153. package/build/screens/conversation_filters/components/rows.d.ts.map +1 -1
  154. package/build/screens/conversation_filters/components/rows.js +6 -1
  155. package/build/screens/conversation_filters/components/rows.js.map +1 -1
  156. package/build/screens/conversation_filters/group_filters.d.ts.map +1 -1
  157. package/build/screens/conversation_filters/group_filters.js +12 -4
  158. package/build/screens/conversation_filters/group_filters.js.map +1 -1
  159. package/build/screens/conversation_filters/hooks/filters.d.ts +40 -40
  160. package/build/screens/conversation_filters/hooks/filters.js +1 -1
  161. package/build/screens/conversation_filters/hooks/filters.js.map +1 -1
  162. package/build/screens/conversation_filters/team_filters.d.ts.map +1 -1
  163. package/build/screens/conversation_filters/team_filters.js +12 -4
  164. package/build/screens/conversation_filters/team_filters.js.map +1 -1
  165. package/build/screens/conversation_filters_screen.js +1 -0
  166. package/build/screens/conversation_filters_screen.js.map +1 -1
  167. package/build/screens/conversation_new/components/groups_form.d.ts +4 -2
  168. package/build/screens/conversation_new/components/groups_form.d.ts.map +1 -1
  169. package/build/screens/conversation_new/components/groups_form.js +40 -55
  170. package/build/screens/conversation_new/components/groups_form.js.map +1 -1
  171. package/build/screens/conversation_new/components/team_form.d.ts +1 -1
  172. package/build/screens/conversation_new/components/team_form.js.map +1 -1
  173. package/build/screens/conversation_new/conversation_new_screen.d.ts +5 -2
  174. package/build/screens/conversation_new/conversation_new_screen.d.ts.map +1 -1
  175. package/build/screens/conversation_new/conversation_new_screen.js +2 -2
  176. package/build/screens/conversation_new/conversation_new_screen.js.map +1 -1
  177. package/build/screens/conversation_screen.d.ts +7 -0
  178. package/build/screens/conversation_screen.d.ts.map +1 -1
  179. package/build/screens/conversation_screen.js +103 -4
  180. package/build/screens/conversation_screen.js.map +1 -1
  181. package/build/screens/conversation_select_recipients/components/groups_without_chat_disclaimer_row.d.ts +2 -0
  182. package/build/screens/conversation_select_recipients/components/groups_without_chat_disclaimer_row.d.ts.map +1 -0
  183. package/build/screens/conversation_select_recipients/components/groups_without_chat_disclaimer_row.js +17 -0
  184. package/build/screens/conversation_select_recipients/components/groups_without_chat_disclaimer_row.js.map +1 -0
  185. package/build/screens/conversation_select_recipients/components/recipient_link_row.d.ts +12 -0
  186. package/build/screens/conversation_select_recipients/components/recipient_link_row.d.ts.map +1 -0
  187. package/build/screens/conversation_select_recipients/components/recipient_link_row.js +61 -0
  188. package/build/screens/conversation_select_recipients/components/recipient_link_row.js.map +1 -0
  189. package/build/screens/conversation_select_recipients/components/view_more_link_row.d.ts +7 -0
  190. package/build/screens/conversation_select_recipients/components/view_more_link_row.d.ts.map +1 -0
  191. package/build/screens/conversation_select_recipients/components/view_more_link_row.js +21 -0
  192. package/build/screens/conversation_select_recipients/components/view_more_link_row.js.map +1 -0
  193. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.d.ts +4 -0
  194. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.d.ts.map +1 -0
  195. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.js +48 -0
  196. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.js.map +1 -0
  197. package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.d.ts +2 -6
  198. package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.d.ts.map +1 -1
  199. package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.js +37 -49
  200. package/build/screens/conversation_select_recipients/conversation_select_recipients_screen.js.map +1 -1
  201. package/build/screens/conversation_select_recipients/types/screen_props.d.ts +9 -0
  202. package/build/screens/conversation_select_recipients/types/screen_props.d.ts.map +1 -0
  203. package/build/screens/conversation_select_recipients/types/screen_props.js +2 -0
  204. package/build/screens/conversation_select_recipients/types/screen_props.js.map +1 -0
  205. package/build/screens/conversations/components/list_header_component.d.ts.map +1 -1
  206. package/build/screens/conversations/components/list_header_component.js +18 -4
  207. package/build/screens/conversations/components/list_header_component.js.map +1 -1
  208. package/build/screens/conversations/conversations_screen.d.ts +2 -1
  209. package/build/screens/conversations/conversations_screen.d.ts.map +1 -1
  210. package/build/screens/conversations/conversations_screen.js +32 -1
  211. package/build/screens/conversations/conversations_screen.js.map +1 -1
  212. package/build/screens/send_giphy_screen.js +29 -1
  213. package/build/screens/send_giphy_screen.js.map +1 -1
  214. package/build/types/resources/groups/groups_group_resource.d.ts +1 -1
  215. package/build/types/resources/groups/groups_group_resource.js.map +1 -1
  216. package/build/types/resources/groups/groups_member_resource_with_person.d.ts +14 -0
  217. package/build/types/resources/groups/groups_member_resource_with_person.d.ts.map +1 -0
  218. package/build/types/resources/groups/groups_member_resource_with_person.js +2 -0
  219. package/build/types/resources/groups/groups_member_resource_with_person.js.map +1 -0
  220. package/build/types/resources/member.d.ts +0 -10
  221. package/build/types/resources/member.d.ts.map +1 -1
  222. package/build/types/resources/member.js.map +1 -1
  223. package/build/types/resources/message.d.ts +2 -0
  224. package/build/types/resources/message.d.ts.map +1 -1
  225. package/build/types/resources/message.js.map +1 -1
  226. package/build/types/resources/oauth_token.d.ts +4 -4
  227. package/build/types/resources/oauth_token.d.ts.map +1 -1
  228. package/build/types/resources/oauth_token.js.map +1 -1
  229. package/build/utils/client/client.d.ts +4 -8
  230. package/build/utils/client/client.d.ts.map +1 -1
  231. package/build/utils/client/client.js +10 -9
  232. package/build/utils/client/client.js.map +1 -1
  233. package/build/utils/date.d.ts +5 -0
  234. package/build/utils/date.d.ts.map +1 -1
  235. package/build/utils/date.js +8 -1
  236. package/build/utils/date.js.map +1 -1
  237. package/build/utils/destructure_chat_group_graph_id.d.ts +10 -0
  238. package/build/utils/destructure_chat_group_graph_id.d.ts.map +1 -0
  239. package/build/utils/destructure_chat_group_graph_id.js +8 -0
  240. package/build/utils/destructure_chat_group_graph_id.js.map +1 -0
  241. package/build/utils/index.d.ts +1 -0
  242. package/build/utils/index.d.ts.map +1 -1
  243. package/build/utils/index.js +1 -0
  244. package/build/utils/index.js.map +1 -1
  245. package/build/utils/native_adapters/configuration.d.ts +4 -1
  246. package/build/utils/native_adapters/configuration.d.ts.map +1 -1
  247. package/build/utils/native_adapters/configuration.js +13 -1
  248. package/build/utils/native_adapters/configuration.js.map +1 -1
  249. package/build/utils/native_adapters/image_picker.d.ts +25 -0
  250. package/build/utils/native_adapters/image_picker.d.ts.map +1 -0
  251. package/build/utils/native_adapters/image_picker.js +9 -0
  252. package/build/utils/native_adapters/image_picker.js.map +1 -0
  253. package/build/utils/native_adapters/index.d.ts +1 -0
  254. package/build/utils/native_adapters/index.d.ts.map +1 -1
  255. package/build/utils/native_adapters/index.js +1 -0
  256. package/build/utils/native_adapters/index.js.map +1 -1
  257. package/build/utils/session.d.ts +6 -2
  258. package/build/utils/session.d.ts.map +1 -1
  259. package/build/utils/session.js +6 -1
  260. package/build/utils/session.js.map +1 -1
  261. package/build/utils/upload_uri.d.ts +23 -0
  262. package/build/utils/upload_uri.d.ts.map +1 -0
  263. package/build/utils/upload_uri.js +60 -0
  264. package/build/utils/upload_uri.js.map +1 -0
  265. package/build/utils/uri.d.ts +10 -2
  266. package/build/utils/uri.d.ts.map +1 -1
  267. package/build/utils/uri.js +24 -6
  268. package/build/utils/uri.js.map +1 -1
  269. package/build/vendor/tapestry/alias_tokens_color_map.d.ts +2 -0
  270. package/build/vendor/tapestry/alias_tokens_color_map.d.ts.map +1 -1
  271. package/build/vendor/tapestry/alias_tokens_color_map.js +2 -0
  272. package/build/vendor/tapestry/alias_tokens_color_map.js.map +1 -1
  273. package/package.json +4 -3
  274. package/src/__tests__/hooks/useTheme.tsx +1 -1
  275. package/src/__tests__/{client.ts → utils/client.ts} +7 -115
  276. package/src/__tests__/{session.ts → utils/session.ts} +4 -4
  277. package/src/__tests__/utils/uri.ts +107 -0
  278. package/src/components/conversation/message_form/message_form_attachment_image.tsx +121 -0
  279. package/src/components/conversation/message_form.tsx +197 -31
  280. package/src/components/conversations/conversation_actions.tsx +2 -2
  281. package/src/components/conversations/conversation_preview.tsx +8 -2
  282. package/src/components/display/action_button.tsx +4 -3
  283. package/src/components/display/banner.tsx +7 -1
  284. package/src/components/display/banner_collapsible.tsx +6 -1
  285. package/src/components/display/child_notice.tsx +9 -3
  286. package/src/components/group_conversation_list.tsx +82 -0
  287. package/src/components/index.tsx +1 -0
  288. package/src/components/primitive/banner_primitive.tsx +12 -5
  289. package/src/contexts/api_provider.tsx +3 -3
  290. package/src/contexts/chat_context.tsx +7 -7
  291. package/src/contexts/conversations_context.tsx +1 -1
  292. package/src/hooks/attachments/supported_extensions.ts +47 -0
  293. package/src/hooks/groups/use_group_members_for_new_conversation.ts +74 -0
  294. package/src/hooks/groups/use_groups_conversation_create.ts +50 -0
  295. package/src/hooks/index.ts +4 -0
  296. package/src/hooks/use_api.ts +13 -7
  297. package/src/hooks/use_api_client.ts +7 -3
  298. package/src/hooks/use_attachment_uploader.ts +179 -0
  299. package/src/hooks/use_conversation.ts +1 -0
  300. package/src/hooks/use_conversations_actions.ts +11 -0
  301. package/src/hooks/use_conversations_jolt_events.ts +5 -1
  302. package/src/hooks/use_current_person.ts +37 -9
  303. package/src/hooks/use_jolt.ts +18 -23
  304. package/src/hooks/use_message_create.ts +2 -2
  305. package/src/hooks/use_suspense_api.ts +6 -0
  306. package/src/hooks/use_upload_client.ts +67 -0
  307. package/src/index.tsx +3 -1
  308. package/src/navigation/index.tsx +23 -2
  309. package/src/screens/conversation_details_screen.tsx +2 -2
  310. package/src/screens/conversation_filter_recipients/components/checkbox_row.tsx +101 -0
  311. package/src/screens/conversation_filter_recipients/components/header_row.tsx +99 -0
  312. package/src/screens/conversation_filter_recipients/components/navigation_header.tsx +68 -0
  313. package/src/screens/conversation_filter_recipients/context/conversation_filter_recipients_context.tsx +53 -0
  314. package/src/screens/conversation_filter_recipients/conversation_filter_recipients_screen.tsx +90 -49
  315. package/src/screens/conversation_filter_recipients/hooks/use_flattened_array_of_service_types_with_teams.tsx +50 -0
  316. package/src/screens/conversation_filter_recipients/hooks/use_service_types_with_teams.ts +90 -0
  317. package/src/screens/conversation_filter_recipients/types.tsx +47 -0
  318. package/src/screens/conversation_filters/components/conversation_filters.tsx +5 -2
  319. package/src/screens/conversation_filters/components/rows.tsx +6 -1
  320. package/src/screens/conversation_filters/group_filters.tsx +23 -14
  321. package/src/screens/conversation_filters/hooks/filters.ts +1 -1
  322. package/src/screens/conversation_filters/team_filters.tsx +23 -14
  323. package/src/screens/conversation_filters_screen.tsx +1 -0
  324. package/src/screens/conversation_new/components/groups_form.tsx +66 -72
  325. package/src/screens/conversation_new/components/team_form.tsx +1 -1
  326. package/src/screens/conversation_new/conversation_new_screen.tsx +11 -4
  327. package/src/screens/conversation_screen.tsx +123 -4
  328. package/src/screens/conversation_select_recipients/components/groups_without_chat_disclaimer_row.tsx +21 -0
  329. package/src/screens/conversation_select_recipients/components/recipient_link_row.tsx +91 -0
  330. package/src/screens/conversation_select_recipients/components/view_more_link_row.tsx +30 -0
  331. package/src/screens/conversation_select_recipients/conversation_select_group_recipients_screen.tsx +79 -0
  332. package/src/screens/conversation_select_recipients/conversation_select_recipients_screen.tsx +57 -65
  333. package/src/screens/conversation_select_recipients/types/screen_props.tsx +11 -0
  334. package/src/screens/conversations/components/list_header_component.tsx +20 -4
  335. package/src/screens/conversations/conversations_screen.tsx +37 -2
  336. package/src/screens/send_giphy_screen.tsx +30 -1
  337. package/src/types/resources/groups/groups_group_resource.ts +1 -1
  338. package/src/types/resources/groups/groups_member_resource_with_person.ts +13 -0
  339. package/src/types/resources/member.ts +0 -11
  340. package/src/types/resources/message.ts +2 -0
  341. package/src/types/resources/oauth_token.ts +4 -4
  342. package/src/utils/client/client.ts +13 -13
  343. package/src/utils/date.ts +11 -1
  344. package/src/utils/destructure_chat_group_graph_id.ts +25 -0
  345. package/src/utils/index.ts +1 -0
  346. package/src/utils/native_adapters/configuration.ts +15 -1
  347. package/src/utils/native_adapters/image_picker.ts +31 -0
  348. package/src/utils/native_adapters/index.ts +1 -0
  349. package/src/utils/session.ts +10 -4
  350. package/src/utils/upload_uri.ts +69 -0
  351. package/src/utils/uri.ts +30 -6
  352. package/src/vendor/tapestry/alias_tokens_color_map.ts +3 -0
  353. package/build/screens/conversation_new/components/member_error_card.d.ts +0 -5
  354. package/build/screens/conversation_new/components/member_error_card.d.ts.map +0 -1
  355. package/build/screens/conversation_new/components/member_error_card.js +0 -17
  356. package/build/screens/conversation_new/components/member_error_card.js.map +0 -1
  357. package/build/screens/conversation_new/utils/fake_member_data.d.ts +0 -3
  358. package/build/screens/conversation_new/utils/fake_member_data.d.ts.map +0 -1
  359. package/build/screens/conversation_new/utils/fake_member_data.js +0 -129
  360. package/build/screens/conversation_new/utils/fake_member_data.js.map +0 -1
  361. package/src/screens/conversation_new/components/member_error_card.tsx +0 -20
  362. package/src/screens/conversation_new/utils/fake_member_data.ts +0 -130
@@ -1,19 +1,27 @@
1
+ // @ts-expect-error
2
+ import { date as formatDate } from '@planningcenter/datetime-fmt'
1
3
  import { HeaderTitle, HeaderTitleProps, PlatformPressable } from '@react-navigation/elements'
2
4
  import {
5
+ CommonActions,
6
+ RouteProp,
3
7
  StaticScreenProps,
4
8
  useNavigation,
5
9
  useTheme as useNavigationTheme,
6
10
  useRoute,
7
11
  } from '@react-navigation/native'
12
+ import moment from 'moment'
8
13
  import React, { useCallback, useEffect } from 'react'
9
14
  import { FlatList, Platform, StyleSheet, View } from 'react-native'
10
15
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
11
- import { Badge, Icon } from '../components'
16
+ import { Badge, Icon, Text } from '../components'
12
17
  import { Message } from '../components/conversation/message'
13
18
  import { MessageForm } from '../components/conversation/message_form'
14
19
  import { KeyboardView } from '../components/display/keyboard_view'
20
+ import { useTheme } from '../hooks'
15
21
  import { useConversation } from '../hooks/use_conversation'
16
22
  import { useConversationMessages } from '../hooks/use_conversation_messages'
23
+ import { MessageResource } from '../types'
24
+ import { getRelativeDateStatus } from '../utils/date'
17
25
 
18
26
  type ConversationRouteProps = {
19
27
  conversation_id: number
@@ -32,6 +40,8 @@ export function ConversationScreen({ route }: ConversationScreenProps) {
32
40
  const { messages, refetch, isRefetching, fetchNextPage } = useConversationMessages({
33
41
  conversation_id,
34
42
  })
43
+ useEnsureConversationsRouteExists()
44
+ const messagesWithSeparators = groupMessages(messages)
35
45
 
36
46
  // Seems to be necessary to define this way so we get the route picked up
37
47
  const headerTitle = useCallback(
@@ -51,13 +61,19 @@ export function ConversationScreen({ route }: ConversationScreenProps) {
51
61
  contentContainerStyle={styles.listContainer}
52
62
  refreshing={isRefetching}
53
63
  onRefresh={refetch}
54
- data={messages}
64
+ data={messagesWithSeparators}
55
65
  keyExtractor={item => item.id}
56
- renderItem={({ item }) => <Message {...item} conversation_id={conversation_id} />}
66
+ renderItem={({ item }) => {
67
+ if (item.type === 'DateSeparator') {
68
+ return <InlineDateSeparator {...item} />
69
+ }
70
+
71
+ return <Message {...item} conversation_id={conversation_id} />
72
+ }}
57
73
  onEndReached={() => fetchNextPage()}
58
74
  />
59
75
  <MessageForm.Root conversation={conversation}>
60
- {/* <MessageForm.AttachmentPicker /> */}
76
+ <MessageForm.AttachmentPicker />
61
77
  <MessageForm.Commands />
62
78
  <MessageForm.TextInput />
63
79
  <MessageForm.SubmitButton />
@@ -67,6 +83,82 @@ export function ConversationScreen({ route }: ConversationScreenProps) {
67
83
  )
68
84
  }
69
85
 
86
+ export type DateSeparator = { type: 'DateSeparator'; id: string; date: string }
87
+
88
+ function InlineDateSeparator({ date }: DateSeparator) {
89
+ const styles = useDateSeparatorStyles()
90
+ const { isThisYear } = getRelativeDateStatus(date)
91
+ const showYear = !isThisYear
92
+ const dateStamp = formatDate(date, { style: 'long', year: showYear })
93
+
94
+ return (
95
+ <View style={styles.container}>
96
+ <View style={styles.separator} />
97
+ <Text variant="footnote" style={styles.dateText}>
98
+ {dateStamp}
99
+ </Text>
100
+ <View style={styles.separator} />
101
+ </View>
102
+ )
103
+ }
104
+
105
+ const useDateSeparatorStyles = () => {
106
+ const theme = useTheme()
107
+ return StyleSheet.create({
108
+ container: {
109
+ alignItems: 'center',
110
+ flexDirection: 'row',
111
+ paddingHorizontal: 16,
112
+ paddingVertical: 16,
113
+ },
114
+ separator: {
115
+ flex: 1,
116
+ height: 1,
117
+ borderTopWidth: 1,
118
+ borderTopColor: theme.colors.borderColorDefaultBase,
119
+ },
120
+ dateText: {
121
+ paddingHorizontal: 8,
122
+ },
123
+ })
124
+ }
125
+
126
+ export const groupMessages = (ms: MessageResource[]) => {
127
+ let enrichedMessages: (MessageResource | DateSeparator)[] = []
128
+ let encounteredOneOfMyMessages = false
129
+
130
+ ms.forEach((message, i) => {
131
+ const prevMessage = ms[i + 1]
132
+ const nextMessage = ms[i - 1]
133
+ const date = moment(message.createdAt).format('YYYY-MM-DD')
134
+ const prevMessageDifferentAuthor = message.author?.id !== prevMessage?.author?.id
135
+ const nextMessageDifferentAuthor = message.author?.id !== nextMessage?.author?.id
136
+ const prevMessageMoreThan5Minutes =
137
+ prevMessage &&
138
+ new Date(message.createdAt).getTime() - new Date(prevMessage.createdAt).getTime() > 60000 * 5
139
+ const nextMessageMoreThan5Minutes =
140
+ nextMessage &&
141
+ new Date(nextMessage.createdAt).getTime() - new Date(message.createdAt).getTime() > 60000 * 5
142
+
143
+ if (message.mine && !encounteredOneOfMyMessages) {
144
+ encounteredOneOfMyMessages = true
145
+ message.myLatestInConversation = true
146
+ } else {
147
+ message.myLatestInConversation = false
148
+ }
149
+ message.lastInGroup = !nextMessage || nextMessageDifferentAuthor || nextMessageMoreThan5Minutes
150
+ message.renderAuthor =
151
+ !message.mine && (!prevMessage || prevMessageDifferentAuthor || prevMessageMoreThan5Minutes)
152
+
153
+ enrichedMessages.push(message)
154
+ if (!prevMessage || date !== moment(prevMessage.createdAt).format('YYYY-MM-DD')) {
155
+ enrichedMessages.push({ type: 'DateSeparator', id: `day-divider-${message.id}`, date })
156
+ }
157
+ })
158
+
159
+ return enrichedMessages
160
+ }
161
+
70
162
  const PressableHeaderTitle = ({ style, children }: HeaderTitleProps) => {
71
163
  const styles = usePressableHeaderStyle()
72
164
  const navigation = useNavigation()
@@ -143,3 +235,30 @@ const useStyles = () => {
143
235
  },
144
236
  })
145
237
  }
238
+
239
+ /**
240
+ * useEnsureConversationsRouteExists
241
+ */
242
+ const useEnsureConversationsRouteExists = () => {
243
+ const navigation = useNavigation()
244
+ const { params } = useRoute<RouteProp<ConversationScreenProps['route']>>()
245
+
246
+ useEffect(() => {
247
+ const navigationState = navigation.getState()
248
+ const routes = navigationState?.routes || []
249
+ const conversationsRoute = routes.find(r => r.name === 'Conversations')
250
+
251
+ if (conversationsRoute) return
252
+
253
+ navigation.dispatch(state => {
254
+ return CommonActions.reset({
255
+ ...state,
256
+ routes: [
257
+ { name: 'Conversations', params: { chat_group_graph_id: params?.chat_group_graph_id } },
258
+ ...routes,
259
+ ],
260
+ index: state.index + 1,
261
+ })
262
+ })
263
+ }, [navigation, params?.chat_group_graph_id])
264
+ }
@@ -0,0 +1,21 @@
1
+ import { Text } from '../../../components'
2
+ import { StyleSheet } from 'react-native'
3
+
4
+ export const GroupsWithoutChatDisclaimerRow = () => {
5
+ const styles = useStyles()
6
+
7
+ return (
8
+ <Text variant="footnote" style={styles.disclaimer}>
9
+ *You have additional groups without chat enabled or permissions to start a new conversation.
10
+ </Text>
11
+ )
12
+ }
13
+
14
+ const useStyles = () => {
15
+ return StyleSheet.create({
16
+ disclaimer: {
17
+ paddingHorizontal: 16,
18
+ paddingVertical: 12,
19
+ },
20
+ })
21
+ }
@@ -0,0 +1,91 @@
1
+ import { PlatformPressable } from '@react-navigation/elements'
2
+ import React from 'react'
3
+ import { StyleSheet, View } from 'react-native'
4
+ import { Icon, Image, Text } from '../../../components'
5
+ import { useTheme } from '../../../hooks'
6
+ import { platformFontWeightMedium } from '../../../utils'
7
+
8
+ interface RecipientLinkRowProps {
9
+ onPress: () => void
10
+ accessibilityLabel: string
11
+ accessibilityHint: string
12
+ imageUri?: string
13
+ title: string
14
+ subtitle: string
15
+ }
16
+
17
+ export const RecipientLinkRow = ({
18
+ onPress,
19
+ accessibilityLabel,
20
+ accessibilityHint,
21
+ imageUri,
22
+ title,
23
+ subtitle,
24
+ }: RecipientLinkRowProps) => {
25
+ const styles = useStyles()
26
+
27
+ return (
28
+ <PlatformPressable
29
+ style={styles.row}
30
+ onPress={onPress}
31
+ accessibilityRole="link"
32
+ accessibilityLabel={accessibilityLabel}
33
+ accessibilityHint={accessibilityHint}
34
+ >
35
+ <View style={styles.innerContainer}>
36
+ {imageUri && (
37
+ <Image source={{ uri: imageUri }} resizeMode="cover" style={styles.image} alt="" />
38
+ )}
39
+ <View style={styles.content}>
40
+ <Text style={styles.title} numberOfLines={2}>
41
+ {title}
42
+ </Text>
43
+ <Text variant="tertiary" numberOfLines={1}>
44
+ {subtitle}
45
+ </Text>
46
+ </View>
47
+ <Icon name="general.rightChevron" size={16} style={styles.icon} />
48
+ </View>
49
+ </PlatformPressable>
50
+ )
51
+ }
52
+
53
+ const ASPECT_RATIO = 16 / 9
54
+ const THUMBNAIL_WIDTH = 80
55
+ const THUMBNAIL_HEIGHT = THUMBNAIL_WIDTH / ASPECT_RATIO
56
+
57
+ const useStyles = () => {
58
+ const theme = useTheme()
59
+
60
+ return StyleSheet.create({
61
+ row: {
62
+ paddingLeft: 16,
63
+ },
64
+ innerContainer: {
65
+ flexDirection: 'row',
66
+ alignItems: 'center',
67
+ gap: 12,
68
+ paddingVertical: 16,
69
+ paddingRight: 16,
70
+ borderBottomWidth: 1,
71
+ borderColor: theme.colors.fillColorNeutral050Base,
72
+ },
73
+ image: {
74
+ width: THUMBNAIL_WIDTH,
75
+ height: THUMBNAIL_HEIGHT,
76
+ borderRadius: 4,
77
+ },
78
+ title: {
79
+ fontWeight: platformFontWeightMedium,
80
+ flexShrink: 1,
81
+ },
82
+ content: {
83
+ flexShrink: 1,
84
+ gap: 2,
85
+ },
86
+ icon: {
87
+ marginLeft: 'auto',
88
+ color: theme.colors.fillColorNeutral030,
89
+ },
90
+ })
91
+ }
@@ -0,0 +1,30 @@
1
+ import { StyleSheet, View } from 'react-native'
2
+ import { TextButton } from '../../../components'
3
+
4
+ interface ViewMoreLinkRowProps {
5
+ onPress: () => void
6
+ accessibilityHint: string
7
+ }
8
+
9
+ export const ViewMoreLinkRow = ({ accessibilityHint, onPress }: ViewMoreLinkRowProps) => {
10
+ const styles = useRowStyles()
11
+
12
+ return (
13
+ <View style={[styles.row]}>
14
+ <TextButton onPress={onPress} accessibilityHint={accessibilityHint} accessibilityRole="link">
15
+ View more
16
+ </TextButton>
17
+ </View>
18
+ )
19
+ }
20
+
21
+ const useRowStyles = () => {
22
+ return StyleSheet.create({
23
+ row: {
24
+ flexDirection: 'row',
25
+ alignItems: 'center',
26
+ paddingVertical: 12,
27
+ paddingHorizontal: 16,
28
+ },
29
+ })
30
+ }
@@ -0,0 +1,79 @@
1
+ import { useNavigation } from '@react-navigation/native'
2
+ import React from 'react'
3
+ import { StyleSheet, View } from 'react-native'
4
+ import { FlashList } from '@shopify/flash-list'
5
+ import { Heading } from '../../components'
6
+ import { GroupsGroupResource } from '../../types'
7
+ import { useGroupsGroups } from '../../hooks/use_groups_groups'
8
+ import { pluralize } from '../../utils'
9
+ import { RecipientLinkRow } from './components/recipient_link_row'
10
+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
11
+ import { ConversationSelectRecipientsScreenProps } from './types/screen_props'
12
+ import { GroupsWithoutChatDisclaimerRow } from './components/groups_without_chat_disclaimer_row'
13
+
14
+ export const ConversationSelectGroupRecipientsScreen = ({
15
+ route,
16
+ }: ConversationSelectRecipientsScreenProps) => {
17
+ const styles = useStyles()
18
+ const navigation = useNavigation()
19
+ const { data: groups = [] } = useGroupsGroups()
20
+ const groupsWithCreatePermission = groups.filter(g => g.canCreateConversation)
21
+ const showGroupsDisclaimer = groups.length > groupsWithCreatePermission.length
22
+
23
+ const handleNavigateToConversationNew = (group: GroupsGroupResource) => {
24
+ navigation.navigate('New', {
25
+ screen: 'ConversationNew',
26
+ params: {
27
+ group_id: group.id,
28
+ source_app_name: 'Groups',
29
+ ...route.params,
30
+ },
31
+ })
32
+ }
33
+
34
+ return (
35
+ <FlashList
36
+ data={groupsWithCreatePermission}
37
+ keyExtractor={item => item.id.toString()}
38
+ estimatedItemSize={65}
39
+ contentContainerStyle={styles.contentContainer}
40
+ ListHeaderComponent={
41
+ <View style={styles.sectionHeader}>
42
+ <Heading variant="h3">All my groups</Heading>
43
+ </View>
44
+ }
45
+ renderItem={({ item: group }: { item: GroupsGroupResource }) => {
46
+ const groupAccessibilityLabel = `Select ${group.name} with ${pluralize(group.membershipsCount, 'member')}`
47
+
48
+ return (
49
+ <RecipientLinkRow
50
+ key={group.id}
51
+ imageUri={group.headerImage?.thumbnail}
52
+ title={group.name}
53
+ subtitle={`${group.membershipsCount} members`}
54
+ onPress={() => handleNavigateToConversationNew(group)}
55
+ accessibilityLabel={groupAccessibilityLabel}
56
+ accessibilityHint={`Selects group as recipient and navigates to the final screen to finish creating the conversation`}
57
+ />
58
+ )
59
+ }}
60
+ ListFooterComponent={showGroupsDisclaimer ? <GroupsWithoutChatDisclaimerRow /> : null}
61
+ />
62
+ )
63
+ }
64
+
65
+ const useStyles = () => {
66
+ const { bottom } = useSafeAreaInsets()
67
+
68
+ return StyleSheet.create({
69
+ contentContainer: {
70
+ paddingBottom: bottom,
71
+ },
72
+ sectionHeader: {
73
+ flexDirection: 'row',
74
+ justifyContent: 'space-between',
75
+ padding: 16,
76
+ paddingBottom: 4,
77
+ },
78
+ })
79
+ }
@@ -1,26 +1,28 @@
1
- import { PlatformPressable } from '@react-navigation/elements'
2
- import { StaticScreenProps, useNavigation } from '@react-navigation/native'
1
+ import { useNavigation } from '@react-navigation/native'
3
2
  import React from 'react'
4
3
  import { ScrollView, StyleSheet, View } from 'react-native'
5
- import { useSafeAreaInsets } from 'react-native-safe-area-context'
6
- import { Button, Heading, Icon, Image, Text } from '../../components'
7
- import { useTheme } from '../../hooks'
4
+ import { Button, Heading } from '../../components'
8
5
  import { GroupsGroupResource } from '../../types'
9
6
  import { useGroupsGroups } from '../../hooks/use_groups_groups'
7
+ import { pluralize } from '../../utils'
8
+ import { RecipientLinkRow } from './components/recipient_link_row'
9
+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
10
+ import { ConversationSelectRecipientsScreenProps } from './types/screen_props'
11
+ import { ViewMoreLinkRow } from './components/view_more_link_row'
12
+ import { GroupsWithoutChatDisclaimerRow } from './components/groups_without_chat_disclaimer_row'
13
+ const MAX_VISIBLE_GROUPS = 5
10
14
 
11
- type ConversationSelectRecipientsScreenProps = StaticScreenProps<{
12
- chat_group_graph_id?: string
13
- }>
14
-
15
- const ASPECT_RATIO = 16 / 9
16
- const THUMBNAIL_WIDTH = 80
17
- const THUMBNAIL_HEIGHT = THUMBNAIL_WIDTH / ASPECT_RATIO
18
-
19
- export const ConversationSelectRecipientsScreen = ({}: ConversationSelectRecipientsScreenProps) => {
15
+ export const ConversationSelectRecipientsScreen = ({
16
+ route,
17
+ }: ConversationSelectRecipientsScreenProps) => {
20
18
  const styles = useStyles()
21
19
  const navigation = useNavigation()
22
20
  const { data: groups = [] } = useGroupsGroups()
23
21
  const groupsWithCreatePermission = groups.filter(g => g.canCreateConversation)
22
+ const visibleGroups = groupsWithCreatePermission.slice(0, MAX_VISIBLE_GROUPS)
23
+ const hasMoreGroups = groupsWithCreatePermission.length > MAX_VISIBLE_GROUPS
24
+ const hasGroupsWithoutChatPermission = groups.length > groupsWithCreatePermission.length
25
+ const showGroupsDisclaimer = hasGroupsWithoutChatPermission && !hasMoreGroups
24
26
 
25
27
  const handleNavigateToConversationNew = (group: GroupsGroupResource) => {
26
28
  navigation.navigate('New', {
@@ -28,48 +30,61 @@ export const ConversationSelectRecipientsScreen = ({}: ConversationSelectRecipie
28
30
  params: {
29
31
  group_id: group.id,
30
32
  source_app_name: 'Groups',
33
+ ...route.params,
34
+ },
35
+ })
36
+ }
37
+
38
+ const handleGroupsViewMore = () => {
39
+ navigation.navigate('New', {
40
+ screen: 'ConversationSelectGroupRecipients',
41
+ params: {
42
+ ...route.params,
31
43
  },
32
44
  })
33
45
  }
34
46
 
35
47
  return (
36
- <ScrollView style={styles.container}>
48
+ <ScrollView contentContainerStyle={styles.contentContainer}>
37
49
  <View style={styles.section}>
38
50
  <View style={styles.sectionHeader}>
39
- <Heading>My groups</Heading>
51
+ <Heading variant="h3">My groups</Heading>
40
52
  </View>
41
53
  <View>
42
- {groupsWithCreatePermission.map(group => (
43
- <PlatformPressable
44
- key={group.id}
45
- style={styles.row}
46
- onPress={() => handleNavigateToConversationNew(group)}
47
- >
48
- <Image
49
- source={{ uri: group.headerImage?.thumbnail }}
50
- resizeMode="cover"
51
- style={styles.rowImage}
52
- alt={`Image for ${group.name}`}
54
+ {visibleGroups.map(group => {
55
+ const groupAccessibilityLabel = `Select ${group.name} with ${pluralize(group.membershipsCount, 'member')}`
56
+
57
+ return (
58
+ <RecipientLinkRow
59
+ key={group.id}
60
+ imageUri={group.headerImage?.thumbnail}
61
+ title={group.name}
62
+ subtitle={`${group.membershipsCount} members`}
63
+ onPress={() => handleNavigateToConversationNew(group)}
64
+ accessibilityLabel={groupAccessibilityLabel}
65
+ accessibilityHint={`Selects group as recipient and navigates to the final screen to finish creating the conversation`}
53
66
  />
54
- <View>
55
- <Heading variant="h3">{group.name}</Heading>
56
- <Text>{group.membershipsCount} members</Text>
57
- </View>
58
- <Icon name="general.rightChevron" size={16} style={styles.rowIconRight} />
59
- </PlatformPressable>
60
- ))}
67
+ )
68
+ })}
69
+ {hasMoreGroups && (
70
+ <ViewMoreLinkRow
71
+ onPress={handleGroupsViewMore}
72
+ accessibilityHint="Navigate to a full list of your groups."
73
+ />
74
+ )}
75
+ {showGroupsDisclaimer && <GroupsWithoutChatDisclaimerRow />}
61
76
  </View>
62
77
  </View>
63
78
  <View style={styles.section}>
64
79
  <View style={styles.sectionHeader}>
65
- <Heading>Teams I lead</Heading>
80
+ <Heading variant="h3">Teams I lead</Heading>
66
81
  <Button
67
82
  style={styles.selectTeamsButton}
68
83
  onPress={() =>
69
84
  navigation.navigate('New', {
70
85
  screen: 'ConversationFilterRecipients',
71
86
  params: {
72
- conversation_id: '2196252',
87
+ source_app_name: 'Services',
73
88
  },
74
89
  })
75
90
  }
@@ -85,45 +100,22 @@ export const ConversationSelectRecipientsScreen = ({}: ConversationSelectRecipie
85
100
 
86
101
  const useStyles = () => {
87
102
  const { bottom } = useSafeAreaInsets()
88
- const theme = useTheme()
89
103
 
90
104
  return StyleSheet.create({
91
- container: {
92
- flex: 1,
93
- gap: 8,
105
+ contentContainer: {
106
+ gap: 24,
107
+ paddingTop: 16,
108
+ paddingBottom: 16 + bottom,
94
109
  },
95
110
  section: {
96
- padding: 16,
97
111
  flex: 1,
98
112
  },
99
113
  sectionHeader: {
100
114
  flexDirection: 'row',
101
115
  justifyContent: 'space-between',
116
+ paddingHorizontal: 16,
117
+ paddingBottom: 4,
102
118
  },
103
119
  selectTeamsButton: {},
104
- row: {
105
- flexDirection: 'row',
106
- alignItems: 'center',
107
- gap: 12,
108
- paddingVertical: 16,
109
- borderBottomWidth: 1,
110
- borderColor: theme.colors.fillColorNeutral050Base,
111
- },
112
- rowImage: {
113
- width: THUMBNAIL_WIDTH,
114
- height: THUMBNAIL_HEIGHT,
115
- borderRadius: 4,
116
- },
117
- rowIconRight: {
118
- marginLeft: 'auto',
119
- color: theme.colors.fillColorNeutral030,
120
- },
121
- routeDebug: {
122
- alignContent: 'center',
123
- padding: 16,
124
- paddingBottom: bottom,
125
- borderTopWidth: 1,
126
- borderTopColor: theme.colors.fillColorNeutral050Base,
127
- },
128
120
  })
129
121
  }
@@ -0,0 +1,11 @@
1
+ import { StaticScreenProps } from '@react-navigation/native'
2
+ import { AppName } from '../../../types/resources/app_name'
3
+ import { GraphId } from '../../../types/resources/group_resource'
4
+
5
+ export type ConversationSelectRecipientsParams = {
6
+ chat_group_graph_id?: GraphId
7
+ group_source_app_name?: AppName
8
+ }
9
+
10
+ export type ConversationSelectRecipientsScreenProps =
11
+ StaticScreenProps<ConversationSelectRecipientsParams>
@@ -1,8 +1,8 @@
1
1
  import { RouteProp, useNavigation, useRoute } from '@react-navigation/native'
2
- import React, { useMemo } from 'react'
3
- import { StyleSheet, View } from 'react-native'
2
+ import React, { useCallback, useMemo } from 'react'
3
+ import { Alert, StyleSheet, View } from 'react-native'
4
4
  import { Heading, TextButton, ToggleButton } from '../../../components'
5
- import { useTheme } from '../../../hooks'
5
+ import { useCurrentPerson, useCurrentPersonCache, useTheme } from '../../../hooks'
6
6
  import { useMarkAllRead } from '../../../hooks/use_conversations_actions'
7
7
  import { useCanDisplayGroups } from '../../../hooks/use_groups'
8
8
  import { ConversationScreenProps } from '../conversations_screen'
@@ -23,6 +23,8 @@ export const ListHeaderComponent = () => {
23
23
  const route = useRoute<RouteProp<ConversationScreenProps['route']>>()
24
24
  const { chat_group_graph_id, group_source_app_name = '' } = route.params || {}
25
25
 
26
+ const { unreadCount } = useCurrentPerson()
27
+ const currentPersonCache = useCurrentPersonCache()
26
28
  const { markAllRead, isPending } = useMarkAllRead()
27
29
 
28
30
  const active: FilterTypes = useMemo(() => {
@@ -37,6 +39,20 @@ export const ListHeaderComponent = () => {
37
39
  return FilterTypes.All
38
40
  }, [chat_group_graph_id, group_source_app_name])
39
41
 
42
+ const handleMarkAllRead = useCallback(() => {
43
+ currentPersonCache.update({ unreadCount: 0 })
44
+ markAllRead()
45
+ }, [currentPersonCache, markAllRead])
46
+
47
+ const alertMarkAllRead = useCallback(() => {
48
+ if (active === FilterTypes.All) return handleMarkAllRead()
49
+
50
+ Alert.alert('Mark all read', 'This includes conversations not shown by the current filter.', [
51
+ { text: 'Cancel' },
52
+ { text: 'OK', onPress: () => handleMarkAllRead() },
53
+ ])
54
+ }, [active, handleMarkAllRead])
55
+
40
56
  const showAppFilters = canFilterByGroups && canFilterByTeams
41
57
 
42
58
  return (
@@ -45,7 +61,7 @@ export const ListHeaderComponent = () => {
45
61
  <Heading numberOfLines={1} variant="h2">
46
62
  Conversations
47
63
  </Heading>
48
- <TextButton onPress={() => markAllRead()} disabled={isPending}>
64
+ <TextButton onPress={alertMarkAllRead} disabled={isPending || !unreadCount}>
49
65
  Mark all read
50
66
  </TextButton>
51
67
  </View>