@planningcenter/chat-react-native 3.1.0-rc.9 → 3.2.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/build/components/conversation/attachments/attachment_card.d.ts +9 -0
  2. package/build/components/conversation/attachments/attachment_card.d.ts.map +1 -0
  3. package/build/components/conversation/attachments/attachment_card.js +35 -0
  4. package/build/components/conversation/attachments/attachment_card.js.map +1 -0
  5. package/build/components/conversation/attachments/audio_attachment.d.ts +6 -0
  6. package/build/components/conversation/attachments/audio_attachment.d.ts.map +1 -0
  7. package/build/components/conversation/attachments/audio_attachment.js +84 -0
  8. package/build/components/conversation/attachments/audio_attachment.js.map +1 -0
  9. package/build/components/conversation/attachments/constants.d.ts +3 -0
  10. package/build/components/conversation/attachments/constants.d.ts.map +1 -0
  11. package/build/components/conversation/attachments/constants.js +4 -0
  12. package/build/components/conversation/attachments/constants.js.map +1 -0
  13. package/build/components/conversation/attachments/download_attachment_button.d.ts +9 -0
  14. package/build/components/conversation/attachments/download_attachment_button.d.ts.map +1 -0
  15. package/build/components/conversation/attachments/download_attachment_button.js +29 -0
  16. package/build/components/conversation/attachments/download_attachment_button.js.map +1 -0
  17. package/build/components/conversation/attachments/expanded_link.d.ts +5 -0
  18. package/build/components/conversation/attachments/expanded_link.d.ts.map +1 -0
  19. package/build/components/conversation/attachments/expanded_link.js +44 -0
  20. package/build/components/conversation/attachments/expanded_link.js.map +1 -0
  21. package/build/components/conversation/attachments/generic_file_attachment.d.ts +7 -0
  22. package/build/components/conversation/attachments/generic_file_attachment.d.ts.map +1 -0
  23. package/build/components/conversation/attachments/generic_file_attachment.js +63 -0
  24. package/build/components/conversation/attachments/generic_file_attachment.js.map +1 -0
  25. package/build/components/conversation/attachments/giphy_attachment.d.ts +6 -0
  26. package/build/components/conversation/attachments/giphy_attachment.d.ts.map +1 -0
  27. package/build/components/conversation/attachments/giphy_attachment.js +42 -0
  28. package/build/components/conversation/attachments/giphy_attachment.js.map +1 -0
  29. package/build/components/conversation/attachments/image_attachment.d.ts +5 -0
  30. package/build/components/conversation/attachments/image_attachment.d.ts.map +1 -0
  31. package/build/components/conversation/attachments/image_attachment.js +24 -0
  32. package/build/components/conversation/attachments/image_attachment.js.map +1 -0
  33. package/build/components/conversation/attachments/video_attachment.d.ts +6 -0
  34. package/build/components/conversation/attachments/video_attachment.d.ts.map +1 -0
  35. package/build/components/conversation/attachments/video_attachment.js +64 -0
  36. package/build/components/conversation/attachments/video_attachment.js.map +1 -0
  37. package/build/components/conversation/message.d.ts +1 -1
  38. package/build/components/conversation/message.d.ts.map +1 -1
  39. package/build/components/conversation/message.js +13 -7
  40. package/build/components/conversation/message.js.map +1 -1
  41. package/build/components/conversation/message_attachments.d.ts +6 -0
  42. package/build/components/conversation/message_attachments.d.ts.map +1 -0
  43. package/build/components/conversation/message_attachments.js +52 -0
  44. package/build/components/conversation/message_attachments.js.map +1 -0
  45. package/build/components/conversation/message_markdown.d.ts +7 -0
  46. package/build/components/conversation/message_markdown.d.ts.map +1 -0
  47. package/build/components/conversation/message_markdown.js +38 -0
  48. package/build/components/conversation/message_markdown.js.map +1 -0
  49. package/build/components/conversations/conversation_preview.d.ts +9 -0
  50. package/build/components/conversations/conversation_preview.d.ts.map +1 -0
  51. package/build/components/conversations/conversation_preview.js +58 -0
  52. package/build/components/conversations/conversation_preview.js.map +1 -0
  53. package/build/components/conversations/conversations.d.ts +8 -0
  54. package/build/components/conversations/conversations.d.ts.map +1 -0
  55. package/build/components/conversations/conversations.js +40 -0
  56. package/build/components/conversations/conversations.js.map +1 -0
  57. package/build/components/conversations/unread_count_badge.d.ts +5 -0
  58. package/build/components/conversations/unread_count_badge.d.ts.map +1 -0
  59. package/build/components/conversations/unread_count_badge.js +33 -0
  60. package/build/components/conversations/unread_count_badge.js.map +1 -0
  61. package/build/components/display/badge.d.ts +9 -1
  62. package/build/components/display/badge.d.ts.map +1 -1
  63. package/build/components/display/badge.js +22 -10
  64. package/build/components/display/badge.js.map +1 -1
  65. package/build/components/display/button.d.ts +1 -1
  66. package/build/components/display/button.d.ts.map +1 -1
  67. package/build/components/display/button.js.map +1 -1
  68. package/build/components/display/child_notice.js +2 -2
  69. package/build/components/display/child_notice.js.map +1 -1
  70. package/build/components/display/icon.d.ts.map +1 -1
  71. package/build/components/display/icon.js +10 -8
  72. package/build/components/display/icon.js.map +1 -1
  73. package/build/components/display/text.js +2 -8
  74. package/build/components/display/text.js.map +1 -1
  75. package/build/components/index.d.ts +1 -1
  76. package/build/components/index.d.ts.map +1 -1
  77. package/build/components/index.js +1 -1
  78. package/build/components/index.js.map +1 -1
  79. package/build/components/page/error_boundary.d.ts +1 -1
  80. package/build/hooks/use_api.d.ts +6 -4
  81. package/build/hooks/use_api.d.ts.map +1 -1
  82. package/build/hooks/use_api.js +5 -2
  83. package/build/hooks/use_api.js.map +1 -1
  84. package/build/hooks/use_api_client.d.ts +1 -2
  85. package/build/hooks/use_api_client.d.ts.map +1 -1
  86. package/build/hooks/use_api_client.js.map +1 -1
  87. package/build/hooks/use_conversation.d.ts +76 -0
  88. package/build/hooks/use_conversation.d.ts.map +1 -1
  89. package/build/hooks/use_conversation.js +47 -3
  90. package/build/hooks/use_conversation.js.map +1 -1
  91. package/build/hooks/use_conversation_jolt_events.js +1 -1
  92. package/build/hooks/use_conversation_jolt_events.js.map +1 -1
  93. package/build/hooks/use_conversation_messages_jolt_events.js +1 -1
  94. package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
  95. package/build/hooks/use_conversations.d.ts +2 -3
  96. package/build/hooks/use_conversations.d.ts.map +1 -1
  97. package/build/hooks/use_conversations.js +3 -29
  98. package/build/hooks/use_conversations.js.map +1 -1
  99. package/build/hooks/use_groups.d.ts +214 -0
  100. package/build/hooks/use_groups.d.ts.map +1 -0
  101. package/build/hooks/use_groups.js +22 -0
  102. package/build/hooks/use_groups.js.map +1 -0
  103. package/build/hooks/use_groups_groups.d.ts +208 -0
  104. package/build/hooks/use_groups_groups.d.ts.map +1 -0
  105. package/build/hooks/use_groups_groups.js +18 -0
  106. package/build/hooks/use_groups_groups.js.map +1 -0
  107. package/build/hooks/use_services_team.d.ts +4 -0
  108. package/build/hooks/use_services_team.d.ts.map +1 -0
  109. package/build/hooks/use_services_team.js +22 -0
  110. package/build/hooks/use_services_team.js.map +1 -0
  111. package/build/hooks/use_suspense_api.d.ts +2 -1
  112. package/build/hooks/use_suspense_api.d.ts.map +1 -1
  113. package/build/hooks/use_suspense_api.js +2 -1
  114. package/build/hooks/use_suspense_api.js.map +1 -1
  115. package/build/hooks/use_teams.d.ts +208 -0
  116. package/build/hooks/use_teams.d.ts.map +1 -0
  117. package/build/hooks/use_teams.js +22 -0
  118. package/build/hooks/use_teams.js.map +1 -0
  119. package/build/navigation/index.d.ts +4 -0
  120. package/build/navigation/index.d.ts.map +1 -1
  121. package/build/navigation/index.js +5 -0
  122. package/build/navigation/index.js.map +1 -1
  123. package/build/screens/conversation_details_screen.d.ts.map +1 -1
  124. package/build/screens/conversation_details_screen.js +139 -59
  125. package/build/screens/conversation_details_screen.js.map +1 -1
  126. package/build/screens/conversation_filters/components/conversation_filters.d.ts +3 -0
  127. package/build/screens/conversation_filters/components/conversation_filters.d.ts.map +1 -0
  128. package/build/screens/conversation_filters/components/conversation_filters.js +173 -0
  129. package/build/screens/conversation_filters/components/conversation_filters.js.map +1 -0
  130. package/build/screens/conversation_filters/components/rows.d.ts +31 -0
  131. package/build/screens/conversation_filters/components/rows.d.ts.map +1 -0
  132. package/build/screens/conversation_filters/components/rows.js +111 -0
  133. package/build/screens/conversation_filters/components/rows.js.map +1 -0
  134. package/build/screens/conversation_filters/context/conversation_filter_context.d.ts +23 -0
  135. package/build/screens/conversation_filters/context/conversation_filter_context.d.ts.map +1 -0
  136. package/build/screens/conversation_filters/context/conversation_filter_context.js +51 -0
  137. package/build/screens/conversation_filters/context/conversation_filter_context.js.map +1 -0
  138. package/build/screens/conversation_filters/filter_types.d.ts +7 -0
  139. package/build/screens/conversation_filters/filter_types.d.ts.map +1 -0
  140. package/build/screens/conversation_filters/filter_types.js +8 -0
  141. package/build/screens/conversation_filters/filter_types.js.map +1 -0
  142. package/build/screens/conversation_filters/group_filters.d.ts +6 -0
  143. package/build/screens/conversation_filters/group_filters.d.ts.map +1 -0
  144. package/build/screens/conversation_filters/group_filters.js +15 -0
  145. package/build/screens/conversation_filters/group_filters.js.map +1 -0
  146. package/build/screens/conversation_filters/hooks/filters.d.ts +415 -0
  147. package/build/screens/conversation_filters/hooks/filters.d.ts.map +1 -0
  148. package/build/screens/conversation_filters/hooks/filters.js +41 -0
  149. package/build/screens/conversation_filters/hooks/filters.js.map +1 -0
  150. package/build/screens/conversation_filters/screen_props.d.ts +13 -0
  151. package/build/screens/conversation_filters/screen_props.d.ts.map +1 -0
  152. package/build/screens/conversation_filters/screen_props.js +2 -0
  153. package/build/screens/conversation_filters/screen_props.js.map +1 -0
  154. package/build/screens/conversation_filters/team_filters.d.ts +6 -0
  155. package/build/screens/conversation_filters/team_filters.d.ts.map +1 -0
  156. package/build/screens/conversation_filters/team_filters.js +15 -0
  157. package/build/screens/conversation_filters/team_filters.js.map +1 -0
  158. package/build/screens/conversation_filters_screen.d.ts +6 -0
  159. package/build/screens/conversation_filters_screen.d.ts.map +1 -0
  160. package/build/screens/conversation_filters_screen.js +125 -0
  161. package/build/screens/conversation_filters_screen.js.map +1 -0
  162. package/build/screens/conversation_screen.js +10 -4
  163. package/build/screens/conversation_screen.js.map +1 -1
  164. package/build/screens/conversations_screen.d.ts +4 -2
  165. package/build/screens/conversations_screen.d.ts.map +1 -1
  166. package/build/screens/conversations_screen.js +139 -11
  167. package/build/screens/conversations_screen.js.map +1 -1
  168. package/build/screens/create/conversation_select_recipients_screen.d.ts.map +1 -1
  169. package/build/screens/create/conversation_select_recipients_screen.js +3 -11
  170. package/build/screens/create/conversation_select_recipients_screen.js.map +1 -1
  171. package/build/types/resources/group_resource.d.ts +4 -2
  172. package/build/types/resources/group_resource.d.ts.map +1 -1
  173. package/build/types/resources/group_resource.js.map +1 -1
  174. package/build/types/resources/index.d.ts +1 -0
  175. package/build/types/resources/index.d.ts.map +1 -1
  176. package/build/types/resources/index.js +1 -0
  177. package/build/types/resources/index.js.map +1 -1
  178. package/build/types/resources/member_ability.d.ts +1 -0
  179. package/build/types/resources/member_ability.d.ts.map +1 -1
  180. package/build/types/resources/member_ability.js.map +1 -1
  181. package/build/types/resources/services/index.d.ts +2 -0
  182. package/build/types/resources/services/index.d.ts.map +1 -0
  183. package/build/types/resources/services/index.js +2 -0
  184. package/build/types/resources/services/index.js.map +1 -0
  185. package/build/types/resources/services/team_resource.d.ts +48 -0
  186. package/build/types/resources/services/team_resource.d.ts.map +1 -0
  187. package/build/types/resources/services/team_resource.js +7 -0
  188. package/build/types/resources/services/team_resource.js.map +1 -0
  189. package/build/utils/index.d.ts +1 -0
  190. package/build/utils/index.d.ts.map +1 -1
  191. package/build/utils/index.js +1 -0
  192. package/build/utils/index.js.map +1 -1
  193. package/build/utils/native_adapters/audio.d.ts +13 -0
  194. package/build/utils/native_adapters/audio.d.ts.map +1 -0
  195. package/build/utils/native_adapters/audio.js +7 -0
  196. package/build/utils/native_adapters/audio.js.map +1 -0
  197. package/build/utils/native_adapters/configuration.d.ts +7 -1
  198. package/build/utils/native_adapters/configuration.d.ts.map +1 -1
  199. package/build/utils/native_adapters/configuration.js +17 -1
  200. package/build/utils/native_adapters/configuration.js.map +1 -1
  201. package/build/utils/native_adapters/index.d.ts +2 -0
  202. package/build/utils/native_adapters/index.d.ts.map +1 -1
  203. package/build/utils/native_adapters/index.js +2 -0
  204. package/build/utils/native_adapters/index.js.map +1 -1
  205. package/build/utils/native_adapters/video.d.ts +25 -0
  206. package/build/utils/native_adapters/video.d.ts.map +1 -0
  207. package/build/utils/native_adapters/video.js +7 -0
  208. package/build/utils/native_adapters/video.js.map +1 -0
  209. package/build/utils/parse_simple_markdown.d.ts +7 -0
  210. package/build/utils/parse_simple_markdown.d.ts.map +1 -0
  211. package/build/utils/parse_simple_markdown.js +32 -0
  212. package/build/utils/parse_simple_markdown.js.map +1 -0
  213. package/build/utils/pluralize.d.ts +2 -0
  214. package/build/utils/pluralize.d.ts.map +1 -0
  215. package/build/utils/pluralize.js +10 -0
  216. package/build/utils/pluralize.js.map +1 -0
  217. package/build/utils/request/conversation.d.ts +10 -0
  218. package/build/utils/request/conversation.d.ts.map +1 -0
  219. package/build/utils/request/conversation.js +32 -0
  220. package/build/utils/request/conversation.js.map +1 -0
  221. package/build/utils/request/messages.d.ts +15 -0
  222. package/build/utils/request/messages.d.ts.map +1 -0
  223. package/build/utils/request/messages.js +22 -0
  224. package/build/utils/request/messages.js.map +1 -0
  225. package/build/utils/theme.d.ts +1 -1
  226. package/build/utils/theme.d.ts.map +1 -1
  227. package/build/utils/theme.js +1 -1
  228. package/build/utils/theme.js.map +1 -1
  229. package/package.json +2 -2
  230. package/src/__tests__/utils/parse_simple_markdown.ts +93 -0
  231. package/src/__tests__/utils/pluralize.tsx +17 -0
  232. package/src/components/conversation/attachments/attachment_card.tsx +46 -0
  233. package/src/components/conversation/attachments/audio_attachment.tsx +102 -0
  234. package/src/components/conversation/attachments/constants.ts +5 -0
  235. package/src/components/conversation/attachments/download_attachment_button.tsx +46 -0
  236. package/src/components/conversation/attachments/expanded_link.tsx +54 -0
  237. package/src/components/conversation/attachments/generic_file_attachment.tsx +75 -0
  238. package/src/components/conversation/attachments/giphy_attachment.tsx +56 -0
  239. package/src/components/conversation/attachments/image_attachment.tsx +31 -0
  240. package/src/components/conversation/attachments/video_attachment.tsx +92 -0
  241. package/src/components/conversation/message.tsx +15 -6
  242. package/src/components/conversation/message_attachments.tsx +61 -0
  243. package/src/components/conversation/message_markdown.tsx +52 -0
  244. package/src/components/conversations/conversation_preview.tsx +84 -0
  245. package/src/components/conversations/conversations.tsx +79 -0
  246. package/src/components/conversations/unread_count_badge.tsx +38 -0
  247. package/src/components/display/badge.tsx +41 -10
  248. package/src/components/display/button.tsx +1 -1
  249. package/src/components/display/child_notice.tsx +2 -2
  250. package/src/components/display/icon.tsx +10 -8
  251. package/src/components/display/text.tsx +1 -7
  252. package/src/components/index.tsx +1 -1
  253. package/src/hooks/use_api.ts +11 -10
  254. package/src/hooks/use_api_client.ts +1 -1
  255. package/src/hooks/use_conversation.ts +51 -3
  256. package/src/hooks/use_conversation_jolt_events.ts +1 -1
  257. package/src/hooks/use_conversation_messages_jolt_events.ts +1 -1
  258. package/src/hooks/use_conversations.ts +3 -31
  259. package/src/hooks/use_groups.ts +31 -0
  260. package/src/hooks/use_groups_groups.ts +20 -0
  261. package/src/hooks/use_services_team.ts +30 -0
  262. package/src/hooks/use_suspense_api.ts +4 -4
  263. package/src/hooks/use_teams.ts +25 -0
  264. package/src/navigation/index.tsx +8 -0
  265. package/src/screens/conversation_details_screen.tsx +224 -111
  266. package/src/screens/conversation_filters/components/conversation_filters.tsx +233 -0
  267. package/src/screens/conversation_filters/components/rows.tsx +164 -0
  268. package/src/screens/conversation_filters/context/conversation_filter_context.tsx +65 -0
  269. package/src/screens/conversation_filters/filter_types.ts +6 -0
  270. package/src/screens/conversation_filters/group_filters.tsx +31 -0
  271. package/src/screens/conversation_filters/hooks/filters.ts +68 -0
  272. package/src/screens/conversation_filters/screen_props.ts +15 -0
  273. package/src/screens/conversation_filters/team_filters.tsx +31 -0
  274. package/src/screens/conversation_filters_screen.tsx +152 -0
  275. package/src/screens/conversation_screen.tsx +16 -4
  276. package/src/screens/conversations_screen.tsx +210 -13
  277. package/src/screens/create/conversation_select_recipients_screen.tsx +3 -11
  278. package/src/types/resources/group_resource.ts +5 -2
  279. package/src/types/resources/index.ts +1 -0
  280. package/src/types/resources/member_ability.ts +1 -0
  281. package/src/types/resources/services/index.ts +1 -0
  282. package/src/types/resources/services/team_resource.ts +60 -0
  283. package/src/utils/client/types.d.ts +2 -1
  284. package/src/utils/index.ts +1 -0
  285. package/src/utils/native_adapters/audio.ts +15 -0
  286. package/src/utils/native_adapters/configuration.ts +24 -1
  287. package/src/utils/native_adapters/index.ts +2 -0
  288. package/src/utils/native_adapters/video.ts +30 -0
  289. package/src/utils/parse_simple_markdown.ts +40 -0
  290. package/src/utils/pluralize.ts +11 -0
  291. package/src/utils/request/conversation.ts +46 -0
  292. package/src/utils/request/messages.ts +21 -0
  293. package/src/utils/theme.ts +2 -2
  294. package/build/components/conversations.d.ts +0 -3
  295. package/build/components/conversations.d.ts.map +0 -1
  296. package/build/components/conversations.js +0 -100
  297. package/build/components/conversations.js.map +0 -1
  298. package/src/components/conversations.tsx +0 -144
@@ -0,0 +1,152 @@
1
+ import { HeaderTitle, HeaderTitleProps, useHeaderHeight } from '@react-navigation/elements'
2
+ import { createComponentForStaticNavigation, RouteProp, useRoute } from '@react-navigation/native'
3
+ import {
4
+ createNativeStackNavigator,
5
+ NativeStackNavigationOptions,
6
+ } from '@react-navigation/native-stack'
7
+ import React from 'react'
8
+ import { Platform, StyleSheet, useWindowDimensions, View } from 'react-native'
9
+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
10
+ import { Button, TextButton } from '../components'
11
+ import {
12
+ FilterContext,
13
+ FilterProvider,
14
+ } from './conversation_filters/context/conversation_filter_context'
15
+ import { ConversationFilters } from './conversation_filters/components/conversation_filters'
16
+ import { GroupFilters } from './conversation_filters/group_filters'
17
+ import {
18
+ ConversationFiltersScreenProps,
19
+ ConversationFilterStackParamList,
20
+ } from './conversation_filters/screen_props'
21
+ import { useTheme } from '../hooks'
22
+ import { TeamFilters } from './conversation_filters/team_filters'
23
+
24
+ const FilterHeaderTitle = ({ tintColor }: HeaderTitleProps) => {
25
+ const styles = useStyles()
26
+ return <HeaderTitle style={[styles.headerTitle, { color: tintColor }]}>Filters</HeaderTitle>
27
+ }
28
+
29
+ const HeaderRight = () => {
30
+ const { resetFilter, applyFilters } = React.useContext(FilterContext)
31
+ const route = useRoute<RouteProp<ConversationFiltersScreenProps['route']>>()
32
+ const styles = useStyles()
33
+
34
+ return (
35
+ <View style={styles.headerRight}>
36
+ <TextButton onPress={resetFilter}>Reset</TextButton>
37
+ <Button title="Apply" onPress={() => applyFilters(route.params)} />
38
+ </View>
39
+ )
40
+ }
41
+
42
+ const HeaderRightWithContext = () => {
43
+ return (
44
+ <FilterProvider>
45
+ <HeaderRight />
46
+ </FilterProvider>
47
+ )
48
+ }
49
+
50
+ export const ConversationFiltersScreenOptions: NativeStackNavigationOptions = {
51
+ presentation: Platform.select({ android: 'modal', ios: 'formSheet' }),
52
+ sheetAllowedDetents: Platform.select({
53
+ android: [0.75, 0.94],
54
+ default: [0.75, 1],
55
+ }),
56
+ sheetGrabberVisible: true,
57
+ headerBackVisible: false,
58
+ headerRight: HeaderRightWithContext,
59
+ headerTitle: FilterHeaderTitle,
60
+ headerTitleAlign: 'left',
61
+ }
62
+
63
+ const FilterNavigator = createNativeStackNavigator<ConversationFilterStackParamList>({
64
+ initialRouteName: 'Filters',
65
+ screens: {
66
+ Filters: {
67
+ screen: ConversationFilters,
68
+ options: {
69
+ headerShown: false,
70
+ },
71
+ },
72
+ GroupFilters: {
73
+ screen: GroupFilters,
74
+ options: {
75
+ headerTitle: Platform.select({
76
+ android: 'Groups',
77
+ ios: '',
78
+ }),
79
+ headerBackTitle: 'Groups',
80
+ },
81
+ },
82
+ TeamFilters: {
83
+ screen: TeamFilters,
84
+ options: {
85
+ headerTitle: Platform.select({
86
+ android: 'Teams',
87
+ ios: '',
88
+ }),
89
+ headerBackTitle: 'Teams',
90
+ },
91
+ },
92
+ },
93
+ })
94
+
95
+ const Filters = createComponentForStaticNavigation(FilterNavigator, 'Filters')
96
+
97
+ export const ConversationFiltersScreen = (_props: ConversationFiltersScreenProps) => {
98
+ const styles = useStyles()
99
+
100
+ return (
101
+ <FilterProvider>
102
+ <View style={styles.container}>
103
+ <Filters />
104
+ </View>
105
+ </FilterProvider>
106
+ )
107
+ }
108
+
109
+ const useStyles = () => {
110
+ const { top } = useSafeAreaInsets()
111
+ const { height } = useWindowDimensions()
112
+ const headerHeight = useHeaderHeight()
113
+ const theme = useTheme()
114
+
115
+ const containerHeight = Platform.select({
116
+ android: height,
117
+ ios: height - top - headerHeight,
118
+ })
119
+
120
+ return StyleSheet.create({
121
+ container: {
122
+ height: containerHeight,
123
+ },
124
+ headerTitle: {
125
+ textAlign: 'left',
126
+ flex: 1,
127
+ },
128
+ filterBar: {
129
+ backgroundColor: theme.colors.fillColorNeutral100Inverted,
130
+ flexDirection: 'row',
131
+ justifyContent: 'space-between',
132
+ alignItems: 'center',
133
+ paddingHorizontal: 16,
134
+ paddingVertical: 16,
135
+ gap: 8,
136
+ },
137
+ filterBarScroll: {
138
+ elevation: 4,
139
+ boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.1)',
140
+ },
141
+ filterBarActions: {
142
+ flexDirection: 'row',
143
+ gap: 8,
144
+ alignItems: 'center',
145
+ },
146
+ headerRight: {
147
+ flexDirection: 'row',
148
+ gap: 8,
149
+ alignItems: 'center',
150
+ },
151
+ })
152
+ }
@@ -8,7 +8,7 @@ import {
8
8
  import React, { useCallback, useEffect } from 'react'
9
9
  import { FlatList, Platform, StyleSheet, View } from 'react-native'
10
10
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
11
- import { Icon, Text } from '../components'
11
+ import { Badge, Icon } from '../components'
12
12
  import { Message } from '../components/conversation/message'
13
13
  import { MessageForm } from '../components/conversation/message_form'
14
14
  import { KeyboardView } from '../components/display/keyboard_view'
@@ -74,7 +74,9 @@ const PressableHeaderTitle = ({ style, children }: HeaderTitleProps) => {
74
74
 
75
75
  const { data: conversation } = useConversation(route.params)
76
76
  const badge = conversation.badges?.[0]
77
- const subtitle = [badge?.pcoResourceType, badge?.text].filter(f => f).join(': ')
77
+ const resourceType = badge?.pcoResourceType || ''
78
+ const productName = badge?.appName
79
+ const name = badge?.text || undefined
78
80
 
79
81
  return (
80
82
  <PlatformPressable
@@ -87,7 +89,13 @@ const PressableHeaderTitle = ({ style, children }: HeaderTitleProps) => {
87
89
  <HeaderTitle style={[styles.title, style]}>{children}</HeaderTitle>
88
90
  <Icon name="general.downChevron" size={12} />
89
91
  </View>
90
- <Text variant="tertiary">{subtitle}</Text>
92
+ <Badge
93
+ variant="metaSubtle"
94
+ productLogoName={productName}
95
+ label={resourceType}
96
+ metaLabel={name}
97
+ style={styles.badge}
98
+ />
91
99
  </PlatformPressable>
92
100
  )
93
101
  }
@@ -99,13 +107,17 @@ const usePressableHeaderStyle = () => {
99
107
  },
100
108
  titleWrapper: {
101
109
  alignItems: 'center',
102
- columnGap: 8,
110
+ columnGap: 4,
103
111
  flexDirection: 'row',
104
112
  },
105
113
  title: {
106
114
  padding: 0,
107
115
  margin: 0,
108
116
  },
117
+ badge: {
118
+ alignSelf: Platform.select({ android: 'flex-start', default: 'center' }),
119
+ marginTop: 2,
120
+ },
109
121
  })
110
122
  }
111
123
 
@@ -1,25 +1,222 @@
1
- import { StaticScreenProps } from '@react-navigation/native'
2
- import React from 'react'
1
+ import { RouteProp, StaticScreenProps, useNavigation, useRoute } from '@react-navigation/native'
2
+ import React, { useCallback, useMemo } from 'react'
3
3
  import { StyleSheet, View } from 'react-native'
4
- import { Conversations } from '../components'
4
+ import { Badge, Button, ButtonProps, Conversations, Heading, TextButton } from '../components'
5
+ import { ActionButton } from '../components/display/action_button'
6
+ import { useCanCreateConversations, useTheme } from '../hooks'
7
+ import { useApiGet } from '../hooks/use_api'
8
+ import { GraphId, GroupResource } from '../types/resources/group_resource'
9
+ import { useCanDisplayGroups } from '../hooks/use_groups'
5
10
 
6
11
  export type ConversationScreenProps = StaticScreenProps<{
7
12
  title?: string
8
- chat_group_graph_id?: string
13
+ chat_group_graph_id?: GraphId
14
+ group_source_app_name?: string
9
15
  }>
10
16
 
11
- export function ConversationsScreen(_props: ConversationScreenProps) {
17
+ export function ConversationsScreen({ route }: ConversationScreenProps) {
18
+ const navigation = useNavigation()
19
+ const canCreateConversations = useCanCreateConversations()
20
+ const styles = useStyles()
21
+ const { chat_group_graph_id, group_source_app_name } = route.params
22
+
23
+ const filter = useMemo(() => {
24
+ if (chat_group_graph_id) {
25
+ return 'group'
26
+ } else if (group_source_app_name) {
27
+ return 'group_source_app_name'
28
+ }
29
+
30
+ return 'mine_or_not_empty'
31
+ }, [chat_group_graph_id, group_source_app_name])
32
+
12
33
  return (
13
34
  <View style={styles.container}>
14
- <Conversations />
35
+ <Conversations
36
+ ListHeaderComponent={ListHeaderComponent}
37
+ group={chat_group_graph_id}
38
+ group_source_app_name={group_source_app_name}
39
+ filter={filter}
40
+ />
41
+ <ActionButton
42
+ visible={canCreateConversations}
43
+ title="New conversation"
44
+ onPress={() => navigation.navigate('Create')}
45
+ />
46
+ </View>
47
+ )
48
+ }
49
+
50
+ enum FilterTypes {
51
+ All = 'All',
52
+ Groups = 'Groups',
53
+ Teams = 'Teams',
54
+ More = 'More',
55
+ }
56
+
57
+ const ListHeaderComponent = () => {
58
+ const styles = useStyles()
59
+ const navigation = useNavigation()
60
+ const canFilterByTeams = useCanDisplayGroups({ source_app_name: 'Services', source_type: 'Team' })
61
+ const canFilterByGroups = useCanDisplayGroups({ source_app_name: 'Groups', source_type: 'Group' })
62
+ const route = useRoute<RouteProp<ConversationScreenProps['route']>>()
63
+ const { chat_group_graph_id, group_source_app_name = '' } = route.params
64
+
65
+ const active: FilterTypes = useMemo(() => {
66
+ if (chat_group_graph_id) {
67
+ return FilterTypes.More
68
+ } else if (/groups/i.test(group_source_app_name)) {
69
+ return FilterTypes.Groups
70
+ } else if (/services/i.test(group_source_app_name)) {
71
+ return FilterTypes.Teams
72
+ }
73
+
74
+ return FilterTypes.All
75
+ }, [chat_group_graph_id, group_source_app_name])
76
+
77
+ const hideAppFilters = !canFilterByGroups || !canFilterByTeams
78
+
79
+ return (
80
+ <View style={styles.listHeader}>
81
+ <View style={styles.titleRow}>
82
+ <Heading numberOfLines={1} variant="h2">
83
+ Conversations
84
+ </Heading>
85
+ <TextButton>Mark all read</TextButton>
86
+ </View>
87
+ <View style={styles.filterRow}>
88
+ <FilterButton
89
+ title={FilterTypes.All}
90
+ activeTitle={active}
91
+ hidden={!canFilterByGroups || !canFilterByTeams}
92
+ onPress={() =>
93
+ navigation.setParams({
94
+ chat_group_graph_id: undefined,
95
+ group_source_app_name: undefined,
96
+ })
97
+ }
98
+ />
99
+ <FilterButton
100
+ title={FilterTypes.Groups}
101
+ activeTitle={active}
102
+ hidden={hideAppFilters}
103
+ onPress={() =>
104
+ navigation.setParams({
105
+ chat_group_graph_id: undefined,
106
+ group_source_app_name: 'Groups',
107
+ })
108
+ }
109
+ />
110
+ <FilterButton
111
+ title={FilterTypes.Teams}
112
+ activeTitle={active}
113
+ hidden={hideAppFilters}
114
+ onPress={() =>
115
+ navigation.setParams({
116
+ chat_group_graph_id: undefined,
117
+ group_source_app_name: 'Services',
118
+ })
119
+ }
120
+ />
121
+ <Button
122
+ title={hideAppFilters ? 'Filter' : FilterTypes.More}
123
+ onPress={() =>
124
+ navigation.navigate('ConversationFilters', {
125
+ chat_group_graph_id,
126
+ group_source_app_name,
127
+ })
128
+ }
129
+ variant={active === FilterTypes.More ? 'fill' : 'outline'}
130
+ iconNameRight="general.threeReducingHorizontalBars"
131
+ />
132
+ </View>
133
+ <Badges />
15
134
  </View>
16
135
  )
17
136
  }
18
137
 
19
- const styles = StyleSheet.create({
20
- container: {
21
- flex: 1,
22
- justifyContent: 'center',
23
- gap: 8,
24
- },
25
- })
138
+ const Badges = () => {
139
+ const styles = useStyles()
140
+ const navigation = useNavigation()
141
+ const route = useRoute<RouteProp<ConversationScreenProps['route']>>()
142
+ const { chat_group_graph_id } = route.params
143
+ const { data: group } = useApiGet<GroupResource>({
144
+ url: `/me/groups/${chat_group_graph_id}`,
145
+ data: {
146
+ fields: {
147
+ Group: [],
148
+ },
149
+ },
150
+ enabled: !!chat_group_graph_id,
151
+ app: 'chat',
152
+ })
153
+
154
+ const handleBadgePress = useCallback(() => {
155
+ navigation.setParams({
156
+ chat_group_graph_id: undefined,
157
+ group_source_app_name: undefined,
158
+ })
159
+ }, [navigation])
160
+
161
+ if (!group) return null
162
+
163
+ return (
164
+ <View style={styles.groupBadge}>
165
+ <Badge iconNameRight="general.x" label={group?.name || ''} onPress={handleBadgePress} />
166
+ </View>
167
+ )
168
+ }
169
+
170
+ function FilterButton({
171
+ title,
172
+ activeTitle,
173
+ onPress,
174
+ hidden = false,
175
+ ...restProps
176
+ }: {
177
+ title: string
178
+ activeTitle: string
179
+ onPress: () => void
180
+ hidden?: boolean
181
+ } & ButtonProps) {
182
+ if (hidden) return null
183
+
184
+ return (
185
+ <Button
186
+ title={title}
187
+ variant={activeTitle === title ? 'fill' : 'outline'}
188
+ onPress={onPress}
189
+ {...restProps}
190
+ />
191
+ )
192
+ }
193
+
194
+ const useStyles = () => {
195
+ const theme = useTheme()
196
+ return StyleSheet.create({
197
+ container: {
198
+ flex: 1,
199
+ justifyContent: 'center',
200
+ },
201
+ listHeader: {
202
+ borderBottomWidth: 1,
203
+ borderBottomColor: theme.colors.fillColorNeutral050Base,
204
+ paddingHorizontal: 16,
205
+ paddingBottom: 16,
206
+ gap: 12,
207
+ },
208
+ titleRow: {
209
+ flexDirection: 'row',
210
+ justifyContent: 'space-between',
211
+ paddingTop: 8,
212
+ },
213
+ filterRow: {
214
+ flexDirection: 'row',
215
+ justifyContent: 'flex-start',
216
+ gap: 8,
217
+ },
218
+ groupBadge: {
219
+ flexDirection: 'row',
220
+ },
221
+ })
222
+ }
@@ -4,8 +4,9 @@ import React from 'react'
4
4
  import { ScrollView, StyleSheet, View } from 'react-native'
5
5
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
6
6
  import { Button, Heading, Icon, Image, Text } from '../../components'
7
- import { useSuspenseGet, useTheme } from '../../hooks'
7
+ import { useTheme } from '../../hooks'
8
8
  import { GroupsGroupResource } from '../../types'
9
+ import { useGroupsGroups } from '../../hooks/use_groups_groups'
9
10
 
10
11
  type ConversationSelectRecipientsScreenProps = StaticScreenProps<{
11
12
  chat_group_graph_id?: string
@@ -18,16 +19,7 @@ const THUMBNAIL_HEIGHT = THUMBNAIL_WIDTH / ASPECT_RATIO
18
19
  export const ConversationSelectRecipientsScreen = ({}: ConversationSelectRecipientsScreenProps) => {
19
20
  const styles = useStyles()
20
21
  const navigation = useNavigation()
21
- const { data: groups = [] } = useSuspenseGet<GroupsGroupResource[]>({
22
- url: '/me/groups',
23
- data: {
24
- perPage: 100,
25
- fields: {
26
- Group: ['can_create_conversation', 'name', 'header_image', 'memberships_count'],
27
- },
28
- },
29
- app: 'groups',
30
- })
22
+ const { data: groups = [] } = useGroupsGroups()
31
23
  const groupsWithCreatePermission = groups.filter(g => g.canCreateConversation)
32
24
 
33
25
  const handleNavigateToCreateConversation = (group: GroupsGroupResource) => {
@@ -1,10 +1,13 @@
1
1
  import { AppName } from './app_name'
2
2
 
3
+ export type SourceType = 'Team' | 'Group' | 'PlanTeam'
4
+ export type GraphId = `${AppName}-${SourceType}-${number}`
5
+
3
6
  export interface GroupResource {
7
+ id: GraphId
4
8
  type: 'Group'
5
- id: string
6
9
  links: { self: string }
7
10
  name: string | null
8
11
  sourceAppName: AppName
9
- sourceType: string
12
+ sourceType: SourceType
10
13
  }
@@ -5,3 +5,4 @@ export * from './oauth_token'
5
5
  export * from './person'
6
6
  export * from './groups'
7
7
  export * from './app_grant'
8
+ export * from './services'
@@ -2,4 +2,5 @@ export interface MemberAbilityResource {
2
2
  type: 'MemberAbility'
3
3
  canUpdate: boolean
4
4
  canDelete: boolean
5
+ leader: boolean
5
6
  }
@@ -0,0 +1 @@
1
+ export * from './team_resource'
@@ -0,0 +1,60 @@
1
+ // All of our calls out to services go out to /chat, which isn't a typical pco-api vertex.
2
+ // They all have a shared type of 'Chat' which has the following array attributes:
3
+ // group_identifiers, people, plans, teams and, teams_i_lead.
4
+ // All of these have a type array, are only rendered on request, and are exclusively used for this form.
5
+ // There is also a payload which is a string, and is used to create a conversation in chat.
6
+
7
+ import { ResourceObject } from '../../api_primitives'
8
+
9
+ interface ServicesChatResource extends ResourceObject {
10
+ type: 'Chat'
11
+ }
12
+
13
+ export interface TeamResource extends ServicesChatResource {
14
+ teamsILead: TeamResponseItem[]
15
+ }
16
+ export interface TeamResponseItem {
17
+ name: string
18
+ value: {
19
+ teamId: number
20
+ serviceTypeId: number
21
+ }
22
+ serviceTypeName: string
23
+ teamName: string
24
+ order: [number, string, string] // [serviceTypeId, serviceTypeName, teamName]
25
+ }
26
+
27
+ export interface TeamOptionResource extends ServicesChatResource {
28
+ teams: TeamOptionResponseItem[]
29
+ }
30
+
31
+ export interface TeamOptionResponseItem extends TeamResponseItem {
32
+ group: TeamOptionResponseItemGroupName
33
+ }
34
+
35
+ export type TeamOptionResponseItemGroupName = 'teams_i_lead' | 'other_teams'
36
+
37
+ export interface PlansResource extends ServicesChatResource {
38
+ plans: PlansResponseItem[]
39
+ }
40
+
41
+ interface PlansResponseItem {
42
+ value: number
43
+ name: string
44
+ }
45
+
46
+ export interface TeamPeopleResource extends ServicesChatResource {
47
+ people: PersonResponseItem[]
48
+ }
49
+
50
+ interface PersonResponseItem {
51
+ id: number
52
+ name: string
53
+ avatar: string
54
+ badges: { title: string }[]
55
+ child: boolean
56
+ }
57
+
58
+ export interface ServicesChatPayloadResource extends ServicesChatResource {
59
+ payload: string
60
+ }
@@ -16,6 +16,7 @@ export interface GenericRequest {
16
16
 
17
17
  export interface GetRequest extends GenericRequest {
18
18
  data: {
19
+ filter?: string
19
20
  fields: Record<string, string[]>
20
21
  where?: Record<string, string>
21
22
  include?: string[]
@@ -23,7 +24,7 @@ export interface GetRequest extends GenericRequest {
23
24
  perPage?: number
24
25
  offset?: number
25
26
  walk?: boolean
26
- }
27
+ } & Record<string, unknown>
27
28
  }
28
29
 
29
30
  export interface Relationship {
@@ -6,3 +6,4 @@ export * from './client'
6
6
  export * from './uri'
7
7
  export * from './cache'
8
8
  export * from './native_adapters'
9
+ export * from './pluralize'
@@ -0,0 +1,15 @@
1
+ interface Audio {
2
+ play: () => void
3
+ pause: () => void
4
+ isPlaying: boolean
5
+ duration: number
6
+ position: number
7
+ }
8
+
9
+ export class AudioAdapter {
10
+ useAudio: (_: string) => Audio
11
+
12
+ constructor(methods: AudioAdapter) {
13
+ this.useAudio = methods.useAudio
14
+ }
15
+ }
@@ -1,12 +1,18 @@
1
+ import { AudioAdapter } from './audio'
1
2
  import { ClipboardAdapter } from './clipboard'
3
+ import { VideoAdapter } from './video'
2
4
 
3
5
  type ChatConfigurations = {
4
6
  clipboard: ClipboardAdapter
7
+ audio: AudioAdapter
8
+ video: VideoAdapter
5
9
  }
6
10
 
7
11
  export class ChatAdapters {
8
12
  static configure(configurations: ChatConfigurations) {
9
13
  Clipboard = configurations.clipboard
14
+ Audio = configurations.audio
15
+ Video = configurations.video
10
16
  }
11
17
  }
12
18
 
@@ -22,4 +28,21 @@ let Clipboard: ClipboardAdapter = new ClipboardAdapter({
22
28
  setStringAsync: async (_: string) => methodMissing(),
23
29
  })
24
30
 
25
- export { Clipboard }
31
+ let Audio: AudioAdapter = new AudioAdapter({
32
+ useAudio: (_: string) => {
33
+ methodMissing()
34
+ return {} as any
35
+ },
36
+ })
37
+
38
+ let Video: VideoAdapter = new VideoAdapter({
39
+ Player: Object.assign(
40
+ () => {
41
+ methodMissing()
42
+ return null
43
+ },
44
+ { $$typeof: Symbol.for('react.forward_ref') }
45
+ ),
46
+ })
47
+
48
+ export { Clipboard, Audio, Video }
@@ -1,2 +1,4 @@
1
1
  export * from './clipboard'
2
2
  export * from './configuration'
3
+ export * from './audio'
4
+ export * from './video'
@@ -0,0 +1,30 @@
1
+ import { StyleProp, ViewStyle } from 'react-native'
2
+
3
+ export interface VideoPlayerProps {
4
+ source: { uri: string }
5
+ aspectRatio?: number
6
+ style?: StyleProp<ViewStyle>
7
+ onFullscreenPlayerWillPresent?: () => void
8
+ onFullscreenPlayerDidPresent?: () => void
9
+ onFullscreenPlayerWillDismiss?: () => void
10
+ onFullscreenPlayerDidDismiss?: () => void
11
+ }
12
+
13
+ export interface VideoPlayerHandle {
14
+ play: () => void
15
+ pause: () => void
16
+ presentFullscreenPlayer: () => void
17
+ dismissFullscreen: () => void
18
+ }
19
+
20
+ type VideoPlayer = React.ForwardRefExoticComponent<
21
+ VideoPlayerProps & React.RefAttributes<VideoPlayerHandle>
22
+ >
23
+
24
+ export class VideoAdapter {
25
+ Player: VideoPlayer
26
+
27
+ constructor(methods: VideoAdapter) {
28
+ this.Player = methods.Player
29
+ }
30
+ }