@planningcenter/chat-react-native 4.4.0-rc.7 → 4.4.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 (339) hide show
  1. package/build/components/conversation/jump_to_bottom_button.d.ts.map +1 -1
  2. package/build/components/conversation/jump_to_bottom_button.js +42 -40
  3. package/build/components/conversation/jump_to_bottom_button.js.map +1 -1
  4. package/build/components/conversation/message.d.ts +2 -1
  5. package/build/components/conversation/message.d.ts.map +1 -1
  6. package/build/components/conversation/message.js +3 -1
  7. package/build/components/conversation/message.js.map +1 -1
  8. package/build/components/conversation/message_form.d.ts.map +1 -1
  9. package/build/components/conversation/message_form.js +3 -1
  10. package/build/components/conversation/message_form.js.map +1 -1
  11. package/build/components/conversation/message_list.d.ts.map +1 -1
  12. package/build/components/conversation/message_list.js +35 -31
  13. package/build/components/conversation/message_list.js.map +1 -1
  14. package/build/components/conversation/message_reaction.d.ts +2 -1
  15. package/build/components/conversation/message_reaction.d.ts.map +1 -1
  16. package/build/components/conversation/message_reaction.js +67 -60
  17. package/build/components/conversation/message_reaction.js.map +1 -1
  18. package/build/components/conversation/messages_disabled_banners.d.ts +7 -5
  19. package/build/components/conversation/messages_disabled_banners.d.ts.map +1 -1
  20. package/build/components/conversation/messages_disabled_banners.js +15 -14
  21. package/build/components/conversation/messages_disabled_banners.js.map +1 -1
  22. package/build/components/conversation/system_message.d.ts +2 -1
  23. package/build/components/conversation/system_message.d.ts.map +1 -1
  24. package/build/components/conversation/system_message.js +133 -100
  25. package/build/components/conversation/system_message.js.map +1 -1
  26. package/build/components/conversations/archived_results_footer.d.ts +6 -0
  27. package/build/components/conversations/archived_results_footer.d.ts.map +1 -0
  28. package/build/components/conversations/archived_results_footer.js +51 -0
  29. package/build/components/conversations/archived_results_footer.js.map +1 -0
  30. package/build/components/conversations/conversation_actions.d.ts.map +1 -1
  31. package/build/components/conversations/conversation_actions.js +241 -206
  32. package/build/components/conversations/conversation_actions.js.map +1 -1
  33. package/build/components/conversations/conversation_preview.d.ts.map +1 -1
  34. package/build/components/conversations/conversation_preview.js +102 -93
  35. package/build/components/conversations/conversation_preview.js.map +1 -1
  36. package/build/components/conversations/conversations.d.ts.map +1 -1
  37. package/build/components/conversations/conversations.js +66 -41
  38. package/build/components/conversations/conversations.js.map +1 -1
  39. package/build/components/conversations/conversations_blank_state.d.ts.map +1 -1
  40. package/build/components/conversations/conversations_blank_state.js +55 -12
  41. package/build/components/conversations/conversations_blank_state.js.map +1 -1
  42. package/build/components/conversations/filtered_results_footer.d.ts +2 -0
  43. package/build/components/conversations/filtered_results_footer.d.ts.map +1 -0
  44. package/build/components/conversations/filtered_results_footer.js +77 -0
  45. package/build/components/conversations/filtered_results_footer.js.map +1 -0
  46. package/build/components/display/action_button.d.ts.map +1 -1
  47. package/build/components/display/action_button.js +18 -16
  48. package/build/components/display/action_button.js.map +1 -1
  49. package/build/components/display/filter_dropdown.d.ts +14 -0
  50. package/build/components/display/filter_dropdown.d.ts.map +1 -0
  51. package/build/components/display/filter_dropdown.js +193 -0
  52. package/build/components/display/filter_dropdown.js.map +1 -0
  53. package/build/components/display/icon_tile.d.ts +13 -0
  54. package/build/components/display/icon_tile.d.ts.map +1 -0
  55. package/build/components/display/icon_tile.js +149 -0
  56. package/build/components/display/icon_tile.js.map +1 -0
  57. package/build/components/display/index.d.ts +2 -0
  58. package/build/components/display/index.d.ts.map +1 -1
  59. package/build/components/display/index.js +2 -0
  60. package/build/components/display/index.js.map +1 -1
  61. package/build/contexts/api_provider.d.ts.map +1 -1
  62. package/build/contexts/api_provider.js +21 -9
  63. package/build/contexts/api_provider.js.map +1 -1
  64. package/build/contexts/conversations_context.d.ts.map +1 -1
  65. package/build/contexts/conversations_context.js +21 -18
  66. package/build/contexts/conversations_context.js.map +1 -1
  67. package/build/hooks/groups/use_group_members_for_new_conversation.d.ts +196 -16
  68. package/build/hooks/groups/use_group_members_for_new_conversation.d.ts.map +1 -1
  69. package/build/hooks/groups/use_group_members_for_new_conversation.js +72 -58
  70. package/build/hooks/groups/use_group_members_for_new_conversation.js.map +1 -1
  71. package/build/hooks/index.d.ts +3 -0
  72. package/build/hooks/index.d.ts.map +1 -1
  73. package/build/hooks/index.js +3 -0
  74. package/build/hooks/index.js.map +1 -1
  75. package/build/hooks/use_animated_message_background_color.d.ts.map +1 -1
  76. package/build/hooks/use_animated_message_background_color.js +5 -3
  77. package/build/hooks/use_animated_message_background_color.js.map +1 -1
  78. package/build/hooks/use_api.d.ts +3 -2
  79. package/build/hooks/use_api.d.ts.map +1 -1
  80. package/build/hooks/use_api.js.map +1 -1
  81. package/build/hooks/use_can_browse_archived_conversations.d.ts +2 -0
  82. package/build/hooks/use_can_browse_archived_conversations.d.ts.map +1 -0
  83. package/build/hooks/use_can_browse_archived_conversations.js +29 -0
  84. package/build/hooks/use_can_browse_archived_conversations.js.map +1 -0
  85. package/build/hooks/use_clear_conversation_filters.d.ts +2 -0
  86. package/build/hooks/use_clear_conversation_filters.d.ts.map +1 -0
  87. package/build/hooks/use_clear_conversation_filters.js +25 -0
  88. package/build/hooks/use_clear_conversation_filters.js.map +1 -0
  89. package/build/hooks/use_conversation.d.ts +73 -1
  90. package/build/hooks/use_conversation.d.ts.map +1 -1
  91. package/build/hooks/use_conversation.js +130 -3
  92. package/build/hooks/use_conversation.js.map +1 -1
  93. package/build/hooks/use_conversation_messages.d.ts.map +1 -1
  94. package/build/hooks/use_conversation_messages.js +29 -26
  95. package/build/hooks/use_conversation_messages.js.map +1 -1
  96. package/build/hooks/use_current_person.d.ts.map +1 -1
  97. package/build/hooks/use_current_person.js +1 -1
  98. package/build/hooks/use_current_person.js.map +1 -1
  99. package/build/hooks/use_jolt.d.ts +1 -0
  100. package/build/hooks/use_jolt.d.ts.map +1 -1
  101. package/build/hooks/use_jolt.js +59 -0
  102. package/build/hooks/use_jolt.js.map +1 -1
  103. package/build/hooks/use_manual_archiving_enabled.d.ts +2 -0
  104. package/build/hooks/use_manual_archiving_enabled.d.ts.map +1 -0
  105. package/build/hooks/use_manual_archiving_enabled.js +18 -0
  106. package/build/hooks/use_manual_archiving_enabled.js.map +1 -0
  107. package/build/hooks/use_mark_latest_message_read.d.ts.map +1 -1
  108. package/build/hooks/use_mark_latest_message_read.js +3 -3
  109. package/build/hooks/use_mark_latest_message_read.js.map +1 -1
  110. package/build/hooks/use_reduce_motion.d.ts +2 -0
  111. package/build/hooks/use_reduce_motion.d.ts.map +1 -0
  112. package/build/hooks/use_reduce_motion.js +28 -0
  113. package/build/hooks/use_reduce_motion.js.map +1 -0
  114. package/build/hooks/use_unarchive_conversation_action.d.ts +7 -0
  115. package/build/hooks/use_unarchive_conversation_action.d.ts.map +1 -0
  116. package/build/hooks/use_unarchive_conversation_action.js +52 -0
  117. package/build/hooks/use_unarchive_conversation_action.js.map +1 -0
  118. package/build/screens/attachment_actions/attachment_actions_screen.d.ts.map +1 -1
  119. package/build/screens/attachment_actions/attachment_actions_screen.js +84 -61
  120. package/build/screens/attachment_actions/attachment_actions_screen.js.map +1 -1
  121. package/build/screens/conversation_details_screen.d.ts.map +1 -1
  122. package/build/screens/conversation_details_screen.js +490 -395
  123. package/build/screens/conversation_details_screen.js.map +1 -1
  124. package/build/screens/conversation_filters/components/conversation_filters.d.ts.map +1 -1
  125. package/build/screens/conversation_filters/components/conversation_filters.js +88 -18
  126. package/build/screens/conversation_filters/components/conversation_filters.js.map +1 -1
  127. package/build/screens/conversation_filters/components/rows.d.ts +9 -0
  128. package/build/screens/conversation_filters/components/rows.d.ts.map +1 -1
  129. package/build/screens/conversation_filters/components/rows.js +93 -1
  130. package/build/screens/conversation_filters/components/rows.js.map +1 -1
  131. package/build/screens/conversation_filters/context/conversation_filter_context.d.ts.map +1 -1
  132. package/build/screens/conversation_filters/context/conversation_filter_context.js +8 -4
  133. package/build/screens/conversation_filters/context/conversation_filter_context.js.map +1 -1
  134. package/build/screens/conversation_filters/filter_types.d.ts +1 -0
  135. package/build/screens/conversation_filters/filter_types.d.ts.map +1 -1
  136. package/build/screens/conversation_filters/filter_types.js +1 -0
  137. package/build/screens/conversation_filters/filter_types.js.map +1 -1
  138. package/build/screens/conversation_filters/screen_props.d.ts +1 -0
  139. package/build/screens/conversation_filters/screen_props.d.ts.map +1 -1
  140. package/build/screens/conversation_filters/screen_props.js.map +1 -1
  141. package/build/screens/conversation_filters_screen.d.ts +1 -0
  142. package/build/screens/conversation_filters_screen.d.ts.map +1 -1
  143. package/build/screens/conversation_filters_screen.js +79 -48
  144. package/build/screens/conversation_filters_screen.js.map +1 -1
  145. package/build/screens/conversation_new/components/groups_form.d.ts.map +1 -1
  146. package/build/screens/conversation_new/components/groups_form.js +37 -34
  147. package/build/screens/conversation_new/components/groups_form.js.map +1 -1
  148. package/build/screens/conversation_screen.d.ts.map +1 -1
  149. package/build/screens/conversation_screen.js +13 -10
  150. package/build/screens/conversation_screen.js.map +1 -1
  151. package/build/screens/conversations/components/filter_dropdown_list_header_component.d.ts +2 -0
  152. package/build/screens/conversations/components/filter_dropdown_list_header_component.d.ts.map +1 -0
  153. package/build/screens/conversations/components/filter_dropdown_list_header_component.js +580 -0
  154. package/build/screens/conversations/components/filter_dropdown_list_header_component.js.map +1 -0
  155. package/build/screens/conversations/components/list_header_component.d.ts.map +1 -1
  156. package/build/screens/conversations/components/list_header_component.js +95 -90
  157. package/build/screens/conversations/components/list_header_component.js.map +1 -1
  158. package/build/screens/conversations/components/search_list_header_component.d.ts.map +1 -1
  159. package/build/screens/conversations/components/search_list_header_component.js +100 -95
  160. package/build/screens/conversations/components/search_list_header_component.js.map +1 -1
  161. package/build/screens/conversations/conversations_screen.d.ts +1 -0
  162. package/build/screens/conversations/conversations_screen.d.ts.map +1 -1
  163. package/build/screens/conversations/conversations_screen.js +15 -2
  164. package/build/screens/conversations/conversations_screen.js.map +1 -1
  165. package/build/screens/design_system_screen.d.ts.map +1 -1
  166. package/build/screens/design_system_screen.js +275 -215
  167. package/build/screens/design_system_screen.js.map +1 -1
  168. package/build/screens/message_actions_screen.d.ts.map +1 -1
  169. package/build/screens/message_actions_screen.js +112 -92
  170. package/build/screens/message_actions_screen.js.map +1 -1
  171. package/build/screens/search/search_screen.d.ts.map +1 -1
  172. package/build/screens/search/search_screen.js +10 -2
  173. package/build/screens/search/search_screen.js.map +1 -1
  174. package/build/screens/send_giphy_screen.d.ts +1 -0
  175. package/build/screens/send_giphy_screen.d.ts.map +1 -1
  176. package/build/screens/send_giphy_screen.js +108 -106
  177. package/build/screens/send_giphy_screen.js.map +1 -1
  178. package/build/screens/team_conversation_screen.js +1 -1
  179. package/build/screens/team_conversation_screen.js.map +1 -1
  180. package/build/types/jolt_events/message_events.d.ts +2 -0
  181. package/build/types/jolt_events/message_events.d.ts.map +1 -1
  182. package/build/types/jolt_events/message_events.js.map +1 -1
  183. package/build/types/resources/conversation.d.ts +2 -2
  184. package/build/types/resources/conversation.d.ts.map +1 -1
  185. package/build/types/resources/conversation.js.map +1 -1
  186. package/build/types/resources/member_ability.d.ts +2 -0
  187. package/build/types/resources/member_ability.d.ts.map +1 -1
  188. package/build/types/resources/member_ability.js.map +1 -1
  189. package/build/types/resources/message.d.ts +2 -0
  190. package/build/types/resources/message.d.ts.map +1 -1
  191. package/build/types/resources/message.js.map +1 -1
  192. package/build/types/resources/person.d.ts +1 -0
  193. package/build/types/resources/person.d.ts.map +1 -1
  194. package/build/types/resources/person.js.map +1 -1
  195. package/build/utils/archived_conversation.d.ts +5 -0
  196. package/build/utils/archived_conversation.d.ts.map +1 -0
  197. package/build/utils/archived_conversation.js +5 -0
  198. package/build/utils/archived_conversation.js.map +1 -0
  199. package/build/utils/date.d.ts +1 -0
  200. package/build/utils/date.d.ts.map +1 -1
  201. package/build/utils/date.js +9 -0
  202. package/build/utils/date.js.map +1 -1
  203. package/build/utils/index.d.ts +1 -0
  204. package/build/utils/index.d.ts.map +1 -1
  205. package/build/utils/index.js +1 -0
  206. package/build/utils/index.js.map +1 -1
  207. package/build/utils/jolt/transform_message_event_data_to_message_resource.d.ts.map +1 -1
  208. package/build/utils/jolt/transform_message_event_data_to_message_resource.js +2 -1
  209. package/build/utils/jolt/transform_message_event_data_to_message_resource.js.map +1 -1
  210. package/build/utils/native_adapters/configuration.d.ts +3 -0
  211. package/build/utils/native_adapters/configuration.d.ts.map +1 -1
  212. package/build/utils/native_adapters/configuration.js +3 -0
  213. package/build/utils/native_adapters/configuration.js.map +1 -1
  214. package/build/utils/native_adapters/index.d.ts +1 -0
  215. package/build/utils/native_adapters/index.d.ts.map +1 -1
  216. package/build/utils/native_adapters/index.js +1 -0
  217. package/build/utils/native_adapters/index.js.map +1 -1
  218. package/build/utils/native_adapters/menu.d.ts +41 -0
  219. package/build/utils/native_adapters/menu.d.ts.map +1 -0
  220. package/build/utils/native_adapters/menu.js +56 -0
  221. package/build/utils/native_adapters/menu.js.map +1 -0
  222. package/build/utils/request/conversation.d.ts +2 -1
  223. package/build/utils/request/conversation.d.ts.map +1 -1
  224. package/build/utils/request/conversation.js +4 -1
  225. package/build/utils/request/conversation.js.map +1 -1
  226. package/build/utils/request/messages_data_options.d.ts.map +1 -1
  227. package/build/utils/request/messages_data_options.js +1 -1
  228. package/build/utils/request/messages_data_options.js.map +1 -1
  229. package/build/utils/system_messages.d.ts +7 -5
  230. package/build/utils/system_messages.d.ts.map +1 -1
  231. package/build/utils/system_messages.js +10 -2
  232. package/build/utils/system_messages.js.map +1 -1
  233. package/build/vendor/font_awesome_pro_solid_icons.d.ts +1 -0
  234. package/build/vendor/font_awesome_pro_solid_icons.d.ts.map +1 -1
  235. package/build/vendor/font_awesome_pro_solid_icons.js +5 -0
  236. package/build/vendor/font_awesome_pro_solid_icons.js.map +1 -1
  237. package/package.json +3 -3
  238. package/src/__tests__/hooks/use_can_browse_archived_conversations.test.tsx +98 -0
  239. package/src/__tests__/screens/conversation_filters/components/conversation_filters.test.tsx +132 -0
  240. package/src/__tests__/screens/conversation_filters_screen.test.tsx +76 -0
  241. package/src/__tests__/screens/conversation_new/components/services_form.test.tsx +1 -0
  242. package/src/__tests__/screens/message_actions_screen.test.tsx +65 -2
  243. package/src/__tests__/screens/send_giphy_screen.test.tsx +102 -0
  244. package/src/__tests__/utils/system_messages.ts +19 -32
  245. package/src/components/conversation/__tests__/message_list.test.tsx +68 -2
  246. package/src/components/conversation/__tests__/system_message.test.tsx +106 -0
  247. package/src/components/conversation/jump_to_bottom_button.tsx +4 -3
  248. package/src/components/conversation/message.tsx +3 -0
  249. package/src/components/conversation/message_form.tsx +3 -1
  250. package/src/components/conversation/message_list.tsx +9 -1
  251. package/src/components/conversation/message_reaction.tsx +7 -2
  252. package/src/components/conversation/messages_disabled_banners.tsx +17 -18
  253. package/src/components/conversation/system_message.tsx +44 -16
  254. package/src/components/conversations/__tests__/conversation_actions.test.tsx +67 -0
  255. package/src/components/conversations/__tests__/conversation_preview.test.tsx +105 -0
  256. package/src/components/conversations/__tests__/conversations.test.tsx +93 -0
  257. package/src/components/conversations/__tests__/conversations_blank_state.test.tsx +73 -0
  258. package/src/components/conversations/archived_results_footer.tsx +36 -0
  259. package/src/components/conversations/conversation_actions.tsx +27 -19
  260. package/src/components/conversations/conversation_preview.tsx +39 -10
  261. package/src/components/conversations/conversations.tsx +26 -3
  262. package/src/components/conversations/conversations_blank_state.tsx +21 -0
  263. package/src/components/conversations/filtered_results_footer.tsx +38 -0
  264. package/src/components/display/__tests__/filter_dropdown.test.tsx +114 -0
  265. package/src/components/display/__tests__/icon_tile.test.tsx +16 -0
  266. package/src/components/display/action_button.tsx +4 -3
  267. package/src/components/display/filter_dropdown.tsx +124 -0
  268. package/src/components/display/icon_tile.tsx +67 -0
  269. package/src/components/display/index.ts +2 -0
  270. package/src/contexts/api_provider.tsx +8 -0
  271. package/src/contexts/conversations_context.tsx +2 -1
  272. package/src/hooks/__tests__/use_conversation_archive.test.tsx +152 -0
  273. package/src/hooks/__tests__/use_conversation_jolt_events.test.tsx +74 -0
  274. package/src/hooks/__tests__/use_conversation_messages.test.tsx +10 -2
  275. package/src/hooks/__tests__/use_jolt.test.tsx +100 -1
  276. package/src/hooks/__tests__/use_mark_latest_message_read.test.tsx +21 -7
  277. package/src/hooks/__tests__/use_reduce_motion.test.tsx +61 -0
  278. package/src/hooks/__tests__/use_unarchive_conversation_action.test.tsx +67 -0
  279. package/src/hooks/groups/use_group_members_for_new_conversation.ts +21 -16
  280. package/src/hooks/index.ts +3 -0
  281. package/src/hooks/use_animated_message_background_color.ts +6 -3
  282. package/src/hooks/use_api.ts +9 -2
  283. package/src/hooks/use_can_browse_archived_conversations.ts +17 -0
  284. package/src/hooks/use_clear_conversation_filters.ts +16 -0
  285. package/src/hooks/use_conversation.ts +44 -3
  286. package/src/hooks/use_conversation_messages.ts +7 -5
  287. package/src/hooks/use_current_person.ts +1 -0
  288. package/src/hooks/use_jolt.ts +57 -1
  289. package/src/hooks/use_manual_archiving_enabled.ts +10 -0
  290. package/src/hooks/use_mark_latest_message_read.ts +4 -3
  291. package/src/hooks/use_reduce_motion.ts +19 -0
  292. package/src/hooks/use_unarchive_conversation_action.ts +24 -0
  293. package/src/screens/__tests__/conversation_details_screen.test.tsx +305 -0
  294. package/src/screens/attachment_actions/__tests__/attachment_actions_screen.test.tsx +72 -0
  295. package/src/screens/attachment_actions/attachment_actions_screen.tsx +3 -1
  296. package/src/screens/conversation_details_screen.tsx +80 -16
  297. package/src/screens/conversation_filters/__tests__/conversation_filters.test.tsx +101 -0
  298. package/src/screens/conversation_filters/components/conversation_filters.tsx +40 -7
  299. package/src/screens/conversation_filters/components/rows.tsx +29 -1
  300. package/src/screens/conversation_filters/context/conversation_filter_context.tsx +4 -0
  301. package/src/screens/conversation_filters/filter_types.ts +1 -0
  302. package/src/screens/conversation_filters/screen_props.ts +1 -0
  303. package/src/screens/conversation_filters_screen.tsx +25 -5
  304. package/src/screens/conversation_new/components/groups_form.tsx +1 -0
  305. package/src/screens/conversation_screen.tsx +4 -2
  306. package/src/screens/conversations/__tests__/conversations_screen.test.tsx +52 -0
  307. package/src/screens/conversations/components/__tests__/filter_dropdown_list_header_component.test.tsx +259 -0
  308. package/src/screens/conversations/components/__tests__/list_header_component.test.tsx +21 -4
  309. package/src/screens/conversations/components/filter_dropdown_list_header_component.tsx +286 -0
  310. package/src/screens/conversations/components/list_header_component.tsx +17 -12
  311. package/src/screens/conversations/components/search_list_header_component.tsx +17 -12
  312. package/src/screens/conversations/conversations_screen.tsx +15 -2
  313. package/src/screens/design_system_screen.tsx +26 -0
  314. package/src/screens/message_actions_screen.tsx +29 -20
  315. package/src/screens/search/__tests__/search_screen.test.tsx +13 -1
  316. package/src/screens/search/search_screen.tsx +8 -2
  317. package/src/screens/send_giphy_screen.tsx +6 -3
  318. package/src/screens/team_conversation_screen.tsx +1 -1
  319. package/src/types/jolt_events/message_events.ts +2 -0
  320. package/src/types/resources/conversation.ts +2 -2
  321. package/src/types/resources/member_ability.ts +2 -0
  322. package/src/types/resources/message.ts +3 -0
  323. package/src/types/resources/person.ts +1 -0
  324. package/src/utils/__tests__/conversation.test.ts +1 -0
  325. package/src/utils/__tests__/date.test.ts +23 -0
  326. package/src/utils/__tests__/group_messages.test.ts +1 -0
  327. package/src/utils/archived_conversation.ts +13 -0
  328. package/src/utils/date.ts +8 -0
  329. package/src/utils/index.ts +1 -0
  330. package/src/utils/jolt/__tests__/transform_message_event_data_to_message_resource.test.ts +35 -0
  331. package/src/utils/jolt/transform_message_event_data_to_message_resource.ts +1 -0
  332. package/src/utils/native_adapters/__tests__/menu.test.tsx +46 -0
  333. package/src/utils/native_adapters/configuration.ts +5 -0
  334. package/src/utils/native_adapters/index.ts +1 -0
  335. package/src/utils/native_adapters/menu.tsx +70 -0
  336. package/src/utils/request/conversation.ts +4 -0
  337. package/src/utils/request/messages_data_options.ts +1 -0
  338. package/src/utils/system_messages.ts +19 -10
  339. package/src/vendor/font_awesome_pro_solid_icons.ts +12 -0
@@ -9,6 +9,7 @@ import { useReactionStyles } from '../components/conversation/message_reaction'
9
9
  import FormSheet, { getFormSheetScreenOptions } from '../components/primitive/form_sheet'
10
10
  import { useCreateAndroidRippleColor, useFontScale, useTheme } from '../hooks'
11
11
  import { useApiClient } from '../hooks/use_api_client'
12
+ import { useConversation } from '../hooks/use_conversation'
12
13
  import { useConversationMessages } from '../hooks/use_conversation_messages'
13
14
  import { availableFeatures, useFeatures } from '../hooks/use_features'
14
15
  import { useMessageReactionToggle } from '../hooks/use_message_reaction_toggle'
@@ -49,6 +50,7 @@ export function MessageActionsScreen({ route }: MessageActionsScreenProps) {
49
50
  { conversation_id },
50
51
  { refetchOnMount: false }
51
52
  )
53
+ const { data: conversation } = useConversation({ conversation_id }, { refetchOnMount: false })
52
54
  const message = messages.find(m => m.id === message_id)
53
55
 
54
56
  if (!message) return null
@@ -57,6 +59,7 @@ export function MessageActionsScreen({ route }: MessageActionsScreenProps) {
57
59
  <MessageActionsScreenContent
58
60
  message={message}
59
61
  conversation_id={conversation_id}
62
+ conversationDisabled={!!conversation.disabled}
60
63
  canDeleteNonAuthoredMessages={canDeleteNonAuthoredMessages || false}
61
64
  refetchMessages={refetch}
62
65
  inReplyScreen={inReplyScreen}
@@ -69,6 +72,7 @@ export function MessageActionsScreen({ route }: MessageActionsScreenProps) {
69
72
  function MessageActionsScreenContent({
70
73
  message,
71
74
  conversation_id,
75
+ conversationDisabled,
72
76
  canDeleteNonAuthoredMessages,
73
77
  refetchMessages,
74
78
  inReplyScreen,
@@ -77,6 +81,7 @@ function MessageActionsScreenContent({
77
81
  }: {
78
82
  message: MessageResource
79
83
  conversation_id: number
84
+ conversationDisabled: boolean
80
85
  canDeleteNonAuthoredMessages: boolean
81
86
  refetchMessages: () => void
82
87
  inReplyScreen?: boolean
@@ -241,28 +246,32 @@ function MessageActionsScreenContent({
241
246
 
242
247
  const showReportMessageAction =
243
248
  !message?.mine && featureEnabled(availableFeatures.message_reporting)
249
+ const showDeleteMessageAction =
250
+ !conversationDisabled && (message?.mine || canDeleteNonAuthoredMessages)
244
251
 
245
252
  return (
246
253
  <FormSheet.Root style={styles.formSheetContent}>
247
- <View style={styles.reactionList}>
248
- {availableReactions.map((reaction, index) => (
249
- <Reaction
250
- key={index}
251
- reaction={reaction}
252
- onPress={() => {
253
- Haptic.impactLight()
254
- handleReactionToggle({
255
- value: reaction.value,
256
- mine: reaction.mine,
257
- })
258
- navigation.goBack()
259
- }}
260
- />
261
- ))}
262
- </View>
254
+ {!conversationDisabled && (
255
+ <View style={styles.reactionList}>
256
+ {availableReactions.map((reaction, index) => (
257
+ <Reaction
258
+ key={index}
259
+ reaction={reaction}
260
+ onPress={() => {
261
+ Haptic.impactLight()
262
+ handleReactionToggle({
263
+ value: reaction.value,
264
+ mine: reaction.mine,
265
+ })
266
+ navigation.goBack()
267
+ }}
268
+ />
269
+ ))}
270
+ </View>
271
+ )}
263
272
  {!isSystemMessage && (
264
273
  <View style={styles.actions}>
265
- {!inReplyScreen && (
274
+ {!inReplyScreen && !conversationDisabled && (
266
275
  <FormSheet.Action
267
276
  onPress={handleReplyPress}
268
277
  title="Reply to message"
@@ -285,7 +294,7 @@ function MessageActionsScreenContent({
285
294
  accessibilityHint="Opens a form to report this message"
286
295
  />
287
296
  )}
288
- {message?.mine && (
297
+ {message?.mine && !conversationDisabled && (
289
298
  <FormSheet.Action
290
299
  onPress={() => handleEditPress()}
291
300
  title="Edit message"
@@ -301,7 +310,7 @@ function MessageActionsScreenContent({
301
310
  accessibilityHint="Opens a modal with a list of people who read your message."
302
311
  />
303
312
  )}
304
- {message?.mine && hasExpandedLink && (
313
+ {message?.mine && hasExpandedLink && !conversationDisabled && (
305
314
  <FormSheet.Action
306
315
  onPress={() => handleRemoveLinkPreviewConfirm()}
307
316
  title="Remove link preview"
@@ -309,7 +318,7 @@ function MessageActionsScreenContent({
309
318
  accessibilityHint="Removes an expanded link preview from the message."
310
319
  />
311
320
  )}
312
- {(message?.mine || canDeleteNonAuthoredMessages) && (
321
+ {showDeleteMessageAction && (
313
322
  <FormSheet.Action
314
323
  onPress={() => handleDeleteConfirm()}
315
324
  title="Delete message"
@@ -1,6 +1,6 @@
1
1
  import { act, fireEvent, render } from '@testing-library/react-native'
2
2
  import React from 'react'
3
- import { Keyboard } from 'react-native'
3
+ import { Keyboard, ScrollView } from 'react-native'
4
4
  import type { useSearchResults } from '../../../hooks/use_search_results'
5
5
  import type {
6
6
  ConversationSearchResultResource,
@@ -116,6 +116,18 @@ describe('SearchScreen', () => {
116
116
  expect(view.getByLabelText('Loading results')).toBeTruthy()
117
117
  })
118
118
 
119
+ it('lets the prompt scroll while taps still reach the field', () => {
120
+ const view = render(<SearchScreen />)
121
+
122
+ const scrollView = view.UNSAFE_getByType(ScrollView)
123
+ expect(scrollView.props.keyboardShouldPersistTaps).toBe('handled')
124
+ expect(scrollView.props.contentContainerStyle).toMatchObject({
125
+ flexGrow: 1,
126
+ justifyContent: 'center',
127
+ })
128
+ expect(view.getByText('Search chat')).toBeTruthy()
129
+ })
130
+
119
131
  it('returns to the prompt as soon as the term is cleared', () => {
120
132
  const view = render(<SearchScreen />)
121
133
  const input = view.getByLabelText(inputLabel)
@@ -4,7 +4,7 @@ import {
4
4
  NativeStackScreenProps,
5
5
  } from '@react-navigation/native-stack'
6
6
  import React, { useRef, useState } from 'react'
7
- import { Keyboard, StyleSheet, View } from 'react-native'
7
+ import { Keyboard, ScrollView, StyleSheet, View } from 'react-native'
8
8
  import { KeyboardView } from '../../components'
9
9
  import {
10
10
  composeOptions,
@@ -73,7 +73,9 @@ export function SearchScreen() {
73
73
  onSettled={publishSearch}
74
74
  />
75
75
  ) : (
76
- <SearchPromptBlankState />
76
+ <ScrollView contentContainerStyle={styles.prompt} keyboardShouldPersistTaps="handled">
77
+ <SearchPromptBlankState />
78
+ </ScrollView>
77
79
  )}
78
80
  </View>
79
81
  </KeyboardView>
@@ -84,4 +86,8 @@ const styles = StyleSheet.create({
84
86
  container: {
85
87
  flex: 1,
86
88
  },
89
+ prompt: {
90
+ flexGrow: 1,
91
+ justifyContent: 'center',
92
+ },
87
93
  })
@@ -17,16 +17,18 @@ export const SendGiphyScreenOptions = getFormSheetScreenOptions({
17
17
 
18
18
  export type SendGiphyScreenProps = StaticScreenProps<{
19
19
  conversation_id: number
20
+ reply_root_id?: string | null
20
21
  search_term: string
21
22
  }>
22
23
 
23
24
  export function SendGiphyScreen({ route }: SendGiphyScreenProps) {
24
- const { conversation_id, search_term } = route.params
25
+ const { conversation_id, reply_root_id, search_term } = route.params
25
26
  const styles = useStyles()
26
27
  const navigation = useNavigation()
27
28
 
28
29
  const { isPending, mutate } = useMessageCreateOrUpdate({
29
30
  conversationId: conversation_id,
31
+ replyRootId: reply_root_id,
30
32
  })
31
33
  const { isSearching, result, nextResult, prevResult } = useGiphy(search_term)
32
34
  const disabled = isPending || isSearching
@@ -53,11 +55,12 @@ export function SendGiphyScreen({ route }: SendGiphyScreenProps) {
53
55
 
54
56
  function goBack({ clearInput = false }) {
55
57
  if (clearInput) {
58
+ const routeName = reply_root_id ? 'ConversationReply' : 'Conversation'
56
59
  const routes = navigation.getState()?.routes || []
57
- const conversationParams = routes.find(r => r.name === 'Conversation')?.params || {}
60
+ const conversationParams = routes.findLast(r => r.name === routeName)?.params || {}
58
61
 
59
62
  navigation.dispatch(
60
- StackActions.popTo('Conversation', {
63
+ StackActions.popTo(routeName, {
61
64
  ...conversationParams,
62
65
  conversation_id,
63
66
  clear_input: true,
@@ -39,7 +39,7 @@ export const TeamConversationScreen = ({ route }: TeamConversationScreenProps) =
39
39
  navigation.dispatch(
40
40
  StackActions.replace('Conversation', {
41
41
  conversation_id: conversation.id,
42
- title: conversation.title,
42
+ title: conversation.title ?? undefined,
43
43
  })
44
44
  )
45
45
 
@@ -1,5 +1,6 @@
1
1
  import type { CustomMessage } from '@planningcenter/jolt-client/dist/types/JoltConnection'
2
2
  import { DenormalizedAttachmentResource } from '../resources/denormalized_attachment_resource'
3
+ import type { SystemTextFormat } from '../resources/message'
3
4
 
4
5
  interface BaseMessageEventData extends Record<string, unknown> {
5
6
  data: {
@@ -21,6 +22,7 @@ interface BaseMessageEventData extends Record<string, unknown> {
21
22
  message_type: string
22
23
  system_event_person_ids: number[] | null
23
24
  system_text_parts: { names: string[]; overflow_count: number; action: string } | null
25
+ system_text_format: SystemTextFormat | null
24
26
  }
25
27
  }
26
28
 
@@ -6,7 +6,7 @@ import { MemberAbilityResource } from './member_ability'
6
6
  import { ReactionCountResource } from './reaction'
7
7
 
8
8
  export interface ConversationPreviewData {
9
- kind: 'reaction' | 'message'
9
+ kind: 'reaction' | 'message' | 'system'
10
10
  authorName: string
11
11
  value: ReactionCountResource['value'] | null
12
12
  text: string
@@ -41,7 +41,7 @@ export interface ConversationResource {
41
41
  memberAbility?: MemberAbilityResource
42
42
  muted: boolean
43
43
  repliesDisabled: boolean
44
- title: string
44
+ title: string | null
45
45
  unreadCount: number
46
46
  unreadReaction: boolean
47
47
  updatedAt: string
@@ -6,4 +6,6 @@ export interface MemberAbilityResource {
6
6
  leader: boolean
7
7
  canReply: boolean
8
8
  canMessageAvailableMembers: boolean
9
+ canArchive: boolean
10
+ canUnarchive: boolean
9
11
  }
@@ -3,6 +3,8 @@ import { DenormalizedAttachmentResourceForCreate } from './denormalized_attachme
3
3
  import type { PersonResource } from './person'
4
4
  import type { ReactionCountResource } from './reaction'
5
5
 
6
+ export type SystemTextFormat = 'people' | 'actor'
7
+
6
8
  export interface MessageResource {
7
9
  type: 'Message'
8
10
  id: string
@@ -22,6 +24,7 @@ export interface MessageResource {
22
24
  messageType: string
23
25
  personIdsForSystemEvent?: number[] | null
24
26
  systemTextParts?: { names: string[]; overflowCount: number; action: string } | null
27
+ systemTextFormat?: SystemTextFormat | null
25
28
 
26
29
  // Custom Local Properties we set for rendering
27
30
  renderAuthor?: boolean
@@ -23,5 +23,6 @@ export interface CurrentPersonResource extends PersonResource {
23
23
  ageQualificationStatus?: AgeQualificationStatus
24
24
  directMessagesDisabled: boolean
25
25
  directMessagesEligible: boolean
26
+ canBrowseArchivedConversations?: boolean
26
27
  under_18: boolean
27
28
  }
@@ -12,6 +12,7 @@ describe('getConversationsRequestArgs', () => {
12
12
  ],
13
13
  ['chat_group_graph_id', { chat_group_graph_id: groupId }, 'mine_or_not_empty,group'],
14
14
  ['show_direct_messages', { show_direct_messages: true }, 'mine_or_not_empty,direct_message'],
15
+ ['show_archived', { show_archived: true }, 'mine_or_not_empty,archived'],
15
16
  ])('%s uses filter: %s', (_label, args, expectedFilter) => {
16
17
  expect(getConversationsRequestArgs(args).data.filter).toBe(expectedFilter)
17
18
  })
@@ -0,0 +1,23 @@
1
+ import { formatEventDateTime } from '../date'
2
+
3
+ describe('formatEventDateTime', () => {
4
+ beforeEach(() => {
5
+ jest.useFakeTimers({ now: new Date(2026, 5, 15, 12, 0) })
6
+ })
7
+
8
+ afterEach(() => {
9
+ jest.useRealTimers()
10
+ })
11
+
12
+ it('leaves out the year for dates in the current year', () => {
13
+ expect(formatEventDateTime(new Date(2026, 1, 3, 14, 18))).toBe('Feb 3 at 2:18pm')
14
+ })
15
+
16
+ it('includes the year for dates in other years', () => {
17
+ expect(formatEventDateTime(new Date(2025, 1, 3, 14, 18))).toBe('Feb 3, 2025 at 2:18pm')
18
+ })
19
+
20
+ it('drops the minutes on the hour', () => {
21
+ expect(formatEventDateTime(new Date(2026, 1, 3, 14, 0))).toBe('Feb 3 at 2pm')
22
+ })
23
+ })
@@ -206,6 +206,7 @@ describe('groupMessages — system messages', () => {
206
206
  const messages = [
207
207
  message('sys', {
208
208
  messageType: 'user_joined',
209
+ systemTextFormat: 'people',
209
210
  systemTextParts: { names: ['A'], overflowCount: 0, action: 'joined' },
210
211
  personIdsForSystemEvent: [1],
211
212
  }),
@@ -0,0 +1,13 @@
1
+ import type { ConversationResource } from '../types/resources/conversation'
2
+
3
+ export const ARCHIVED_DISABLED_REASON = 'archived'
4
+
5
+ const DEFAULT_ARCHIVED_MESSAGE = 'This conversation is archived.'
6
+
7
+ export const isArchivedConversation = (
8
+ conversation: Pick<ConversationResource, 'disabledReason'>
9
+ ) => conversation.disabledReason === ARCHIVED_DISABLED_REASON
10
+
11
+ export const archivedConversationMessage = (
12
+ conversation: Pick<ConversationResource, 'disabledMessage'>
13
+ ) => conversation.disabledMessage || DEFAULT_ARCHIVED_MESSAGE
package/src/utils/date.ts CHANGED
@@ -61,3 +61,11 @@ export function relativeTime(date: DateProps): string {
61
61
  return dayjs(date).format('h:mma')
62
62
  }
63
63
  }
64
+
65
+ export function formatEventDateTime(date: DateProps) {
66
+ const { isThisYear } = getRelativeDateStatus(date)
67
+ const local = dayjs(date)
68
+ const day = local.format(isThisYear ? 'MMM D' : 'MMM D, YYYY')
69
+ const time = local.format(local.minute() === 0 ? 'ha' : 'h:mma')
70
+ return `${day} at ${time}`
71
+ }
@@ -1,3 +1,4 @@
1
+ export * from './archived_conversation'
1
2
  export * from './assert_keys_are_numbers'
2
3
  export * from './attachment_kind'
3
4
  export * from './chat_type_label'
@@ -0,0 +1,35 @@
1
+ import type { MessageCreatedEvent } from '../../../types/jolt_events/message_events'
2
+ import { isSystemMessage } from '../../system_messages'
3
+ import { transformMessageEventDataToMessageResource } from '../transform_message_event_data_to_message_resource'
4
+
5
+ const archivedEventData: MessageCreatedEvent['data']['data'] = {
6
+ author_avatar: '',
7
+ author_id: 1,
8
+ author_name: 'Wes',
9
+ conversation_id: 1,
10
+ created_at: '2026-01-01T00:00:00Z',
11
+ deleted_at: null,
12
+ organization_id: 1,
13
+ sort_key: '01J0000000000000000000001',
14
+ text: 'This conversation was archived by Wes',
15
+ text_edited_at: null,
16
+ html: '',
17
+ attachments: [],
18
+ reply_count: 0,
19
+ reply_root_id: null,
20
+ message_type: 'conversation_archived',
21
+ system_event_person_ids: [1],
22
+ system_text_parts: null,
23
+ system_text_format: 'actor',
24
+ }
25
+
26
+ describe('transformMessageEventDataToMessageResource', () => {
27
+ it('keeps the system text format so realtime archive events render as system messages', () => {
28
+ const message = transformMessageEventDataToMessageResource({
29
+ data: archivedEventData,
30
+ currentPersonId: 2,
31
+ })
32
+
33
+ expect(isSystemMessage(message)).toBe(true)
34
+ })
35
+ })
@@ -39,5 +39,6 @@ export function transformMessageEventDataToMessageResource({
39
39
  action: data.system_text_parts.action,
40
40
  }
41
41
  : null,
42
+ systemTextFormat: data.system_text_format,
42
43
  }
43
44
  }
@@ -0,0 +1,46 @@
1
+ import { render, screen } from '@testing-library/react-native'
2
+ import React from 'react'
3
+ import { Text } from 'react-native'
4
+ import { MenuAdapter, MenuViewProps } from '../menu'
5
+
6
+ const actions = [{ id: 'all', title: 'All' }]
7
+
8
+ describe('MenuAdapter', () => {
9
+ it('renders the trigger and warns when the host configured no menu', () => {
10
+ const warn = jest.spyOn(console, 'warn').mockImplementation(() => {})
11
+ const { View, isConfigured } = new MenuAdapter()
12
+
13
+ expect(isConfigured).toBe(false)
14
+
15
+ render(
16
+ <View actions={actions}>
17
+ <Text>Trigger</Text>
18
+ </View>
19
+ )
20
+
21
+ expect(screen.getByText('Trigger')).toBeTruthy()
22
+ expect(warn).toHaveBeenCalledTimes(1)
23
+ warn.mockRestore()
24
+ })
25
+
26
+ it('renders through the view the host supplies', () => {
27
+ const HostMenuView = ({ actions: hostActions, children }: MenuViewProps) => (
28
+ <>
29
+ {children}
30
+ <Text>{hostActions.map(action => action.title).join(',')}</Text>
31
+ </>
32
+ )
33
+ const { View, isConfigured } = new MenuAdapter({ View: HostMenuView })
34
+
35
+ expect(isConfigured).toBe(true)
36
+
37
+ render(
38
+ <View actions={actions}>
39
+ <Text>Trigger</Text>
40
+ </View>
41
+ )
42
+
43
+ expect(screen.getByText('Trigger')).toBeTruthy()
44
+ expect(screen.getByText('All')).toBeTruthy()
45
+ })
46
+ })
@@ -7,6 +7,7 @@ import { HapticAdapter } from './haptic'
7
7
  import { ImagePickerAdapter } from './image_picker'
8
8
  import { LinkingAdapter } from './linking'
9
9
  import { LogAdapter } from './log'
10
+ import { MenuAdapter } from './menu'
10
11
  import { StorageAdapter } from './storage_adapter'
11
12
  import { VideoAdapter } from './video'
12
13
 
@@ -19,6 +20,7 @@ type ChatConfigurations = {
19
20
  log?: LogAdapter
20
21
  linking?: LinkingAdapter
21
22
  haptic?: HapticAdapter
23
+ menu?: MenuAdapter
22
24
  }
23
25
 
24
26
  export class ChatAdapters {
@@ -31,6 +33,7 @@ export class ChatAdapters {
31
33
  Log = configurations.log || new LogAdapter()
32
34
  Linking = configurations.linking || new LinkingAdapter(RNLinking)
33
35
  Haptic = configurations.haptic || new HapticAdapter()
36
+ Menu = configurations.menu || new MenuAdapter()
34
37
  }
35
38
  }
36
39
 
@@ -82,6 +85,8 @@ export let Linking: LinkingAdapter = new LinkingAdapter(RNLinking)
82
85
 
83
86
  export let Haptic: HapticAdapter = new HapticAdapter()
84
87
 
88
+ export let Menu: MenuAdapter = new MenuAdapter()
89
+
85
90
  export let Storage = new StorageAdapter({
86
91
  getItem: AsyncStorage.getItem,
87
92
  setItem: AsyncStorage.setItem,
@@ -5,6 +5,7 @@ export * from './document_picker'
5
5
  export * from './image_picker'
6
6
  export * from './linking'
7
7
  export * from './log'
8
+ export * from './menu'
8
9
  export * from './video'
9
10
  export * from './haptic'
10
11
  export * from './storage_adapter'
@@ -0,0 +1,70 @@
1
+ import React, { useEffect } from 'react'
2
+ import { StyleProp, View, ViewStyle } from 'react-native'
3
+
4
+ // =================================
5
+ // ====== Types ====================
6
+ // =================================
7
+
8
+ // Mirrors the props shared by `@expo/ui/community/menu` and
9
+ // `@react-native-menu/menu`, so a host can pass either `MenuView` straight in.
10
+
11
+ export type MenuActionState = 'on' | 'off'
12
+
13
+ export interface MenuActionAttributes {
14
+ destructive?: boolean
15
+ disabled?: boolean
16
+ hidden?: boolean
17
+ }
18
+
19
+ export interface MenuAction {
20
+ id?: string
21
+ title: string
22
+ state?: MenuActionState
23
+ attributes?: MenuActionAttributes
24
+ subactions?: MenuAction[]
25
+ displayInline?: boolean
26
+ }
27
+
28
+ export interface MenuActionEvent {
29
+ nativeEvent: { event: string }
30
+ }
31
+
32
+ export interface MenuViewProps {
33
+ actions: MenuAction[]
34
+ onPressAction?: (event: MenuActionEvent) => void
35
+ onOpenMenu?: () => void
36
+ onCloseMenu?: () => void
37
+ shouldOpenOnLongPress?: boolean
38
+ title?: string
39
+ style?: StyleProp<ViewStyle>
40
+ testID?: string
41
+ children?: React.ReactNode
42
+ }
43
+
44
+ export type MenuView = React.ComponentType<MenuViewProps>
45
+
46
+ // =================================
47
+ // ====== Adapter ==================
48
+ // =================================
49
+
50
+ function UnconfiguredMenuView({ children, style, testID }: MenuViewProps) {
51
+ useEffect(() => {
52
+ console.warn('ChatAdapters.configure() must include a menu adapter before rendering a menu')
53
+ }, [])
54
+
55
+ return (
56
+ <View style={style} testID={testID}>
57
+ {children}
58
+ </View>
59
+ )
60
+ }
61
+
62
+ export class MenuAdapter {
63
+ View: MenuView
64
+ isConfigured: boolean
65
+
66
+ constructor(methods?: { View: MenuView }) {
67
+ this.View = methods?.View ?? UnconfiguredMenuView
68
+ this.isConfigured = !!methods?.View
69
+ }
70
+ }
@@ -6,6 +6,7 @@ export interface ConversationRequestArgs {
6
6
  chat_group_graph_id?: GraphId
7
7
  group_source_app_name?: string
8
8
  show_direct_messages?: boolean
9
+ show_archived?: boolean
9
10
  }
10
11
 
11
12
  export const getConversationsRequestArgs = ({
@@ -13,10 +14,13 @@ export const getConversationsRequestArgs = ({
13
14
  chat_group_graph_id,
14
15
  group_source_app_name,
15
16
  show_direct_messages,
17
+ show_archived,
16
18
  }: Partial<ConversationRequestArgs> = {}): GetRequest => {
17
19
  let filter: string
18
20
  if (chat_group_graph_id) {
19
21
  filter = 'mine_or_not_empty,group'
22
+ } else if (show_archived) {
23
+ filter = 'mine_or_not_empty,archived'
20
24
  } else if (show_direct_messages) {
21
25
  filter = 'mine_or_not_empty,direct_message'
22
26
  } else if (group_source_app_name) {
@@ -14,6 +14,7 @@ export const getMessageFields = {
14
14
  'message_type',
15
15
  'person_ids_for_system_event',
16
16
  'system_text_parts',
17
+ 'system_text_format',
17
18
  ],
18
19
  Person: ['name', 'avatar'],
19
20
  ReactionCount: ['value', 'count', 'mine', 'message_id', 'author_ids'],
@@ -1,16 +1,25 @@
1
1
  import type { MessageResource } from '../types'
2
2
 
3
- const SYSTEM_MESSAGE_TYPES = ['user_joined'] as const
4
-
5
- type SystemMessageType = (typeof SYSTEM_MESSAGE_TYPES)[number]
6
-
7
- export interface SystemMessageResource extends MessageResource {
8
- messageType: SystemMessageType
3
+ export interface PeopleSystemMessageResource extends MessageResource {
4
+ systemTextFormat: 'people'
9
5
  systemTextParts: { names: string[]; overflowCount: number; action: string }
10
6
  personIdsForSystemEvent: number[]
11
7
  }
12
8
 
13
- export const isSystemMessage = (message: MessageResource): message is SystemMessageResource =>
14
- SYSTEM_MESSAGE_TYPES.includes(message.messageType as SystemMessageType) &&
15
- message.systemTextParts != null &&
16
- message.personIdsForSystemEvent != null
9
+ export interface ActorSystemMessageResource extends MessageResource {
10
+ systemTextFormat: 'actor'
11
+ text: string
12
+ }
13
+
14
+ export type SystemMessageResource = PeopleSystemMessageResource | ActorSystemMessageResource
15
+
16
+ export const isSystemMessage = (message: MessageResource): message is SystemMessageResource => {
17
+ switch (message.systemTextFormat) {
18
+ case 'people':
19
+ return message.systemTextParts != null && message.personIdsForSystemEvent != null
20
+ case 'actor':
21
+ return !!message.text
22
+ default:
23
+ return false
24
+ }
25
+ }
@@ -608,3 +608,15 @@ export const faTag: IconDefinition = {
608
608
  'M32.5 96l0 149.5c0 17 6.7 33.3 18.7 45.3l192 192c25 25 65.5 25 90.5 0L483.2 333.3c25-25 25-65.5 0-90.5l-192-192C279.2 38.7 263 32 246 32L96.5 32c-35.3 0-64 28.7-64 64zm112 16a32 32 0 1 1 0 64 32 32 0 1 1 0-64z',
609
609
  ],
610
610
  }
611
+
612
+ export const faBoxArchive: IconDefinition = {
613
+ prefix: 'fas',
614
+ iconName: 'box-archive',
615
+ icon: [
616
+ 512,
617
+ 512,
618
+ ['archive'],
619
+ 'f187',
620
+ 'M0 64C0 46.3 14.3 32 32 32l448 0c17.7 0 32 14.3 32 32l0 32c0 17.7-14.3 32-32 32L32 128C14.3 128 0 113.7 0 96L0 64zM32 176l448 0 0 240c0 35.3-28.7 64-64 64L96 480c-35.3 0-64-28.7-64-64l0-240zm152 64c-13.3 0-24 10.7-24 24s10.7 24 24 24l144 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-144 0z',
621
+ ],
622
+ }