@planningcenter/chat-react-native 3.1.0-rc.13 → 3.1.0-rc.14

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 (218) 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 +10 -6
  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/conversations.d.ts +6 -1
  46. package/build/components/conversations.d.ts.map +1 -1
  47. package/build/components/conversations.js +19 -24
  48. package/build/components/conversations.js.map +1 -1
  49. package/build/components/display/badge.d.ts +9 -1
  50. package/build/components/display/badge.d.ts.map +1 -1
  51. package/build/components/display/badge.js +22 -10
  52. package/build/components/display/badge.js.map +1 -1
  53. package/build/components/display/button.d.ts +1 -1
  54. package/build/components/display/button.d.ts.map +1 -1
  55. package/build/components/display/button.js.map +1 -1
  56. package/build/components/display/child_notice.js +2 -2
  57. package/build/components/display/child_notice.js.map +1 -1
  58. package/build/components/display/icon.d.ts.map +1 -1
  59. package/build/components/display/icon.js +10 -8
  60. package/build/components/display/icon.js.map +1 -1
  61. package/build/components/page/error_boundary.d.ts +1 -1
  62. package/build/hooks/use_api.d.ts +6 -4
  63. package/build/hooks/use_api.d.ts.map +1 -1
  64. package/build/hooks/use_api.js +5 -2
  65. package/build/hooks/use_api.js.map +1 -1
  66. package/build/hooks/use_api_client.d.ts +1 -2
  67. package/build/hooks/use_api_client.d.ts.map +1 -1
  68. package/build/hooks/use_api_client.js.map +1 -1
  69. package/build/hooks/use_conversation.js +1 -1
  70. package/build/hooks/use_conversation.js.map +1 -1
  71. package/build/hooks/use_conversation_jolt_events.js +1 -1
  72. package/build/hooks/use_conversation_jolt_events.js.map +1 -1
  73. package/build/hooks/use_conversation_messages_jolt_events.js +1 -1
  74. package/build/hooks/use_conversation_messages_jolt_events.js.map +1 -1
  75. package/build/hooks/use_conversations.d.ts +2 -3
  76. package/build/hooks/use_conversations.d.ts.map +1 -1
  77. package/build/hooks/use_conversations.js +3 -29
  78. package/build/hooks/use_conversations.js.map +1 -1
  79. package/build/hooks/use_groups.d.ts +214 -0
  80. package/build/hooks/use_groups.d.ts.map +1 -0
  81. package/build/hooks/use_groups.js +22 -0
  82. package/build/hooks/use_groups.js.map +1 -0
  83. package/build/hooks/use_groups_groups.d.ts +208 -0
  84. package/build/hooks/use_groups_groups.d.ts.map +1 -0
  85. package/build/hooks/use_groups_groups.js +18 -0
  86. package/build/hooks/use_groups_groups.js.map +1 -0
  87. package/build/hooks/use_services_team.d.ts +4 -0
  88. package/build/hooks/use_services_team.d.ts.map +1 -0
  89. package/build/hooks/use_services_team.js +22 -0
  90. package/build/hooks/use_services_team.js.map +1 -0
  91. package/build/hooks/use_suspense_api.d.ts +2 -1
  92. package/build/hooks/use_suspense_api.d.ts.map +1 -1
  93. package/build/hooks/use_suspense_api.js +2 -1
  94. package/build/hooks/use_suspense_api.js.map +1 -1
  95. package/build/hooks/use_teams.d.ts +208 -0
  96. package/build/hooks/use_teams.d.ts.map +1 -0
  97. package/build/hooks/use_teams.js +22 -0
  98. package/build/hooks/use_teams.js.map +1 -0
  99. package/build/navigation/index.d.ts +11 -0
  100. package/build/navigation/index.d.ts.map +1 -1
  101. package/build/navigation/index.js +5 -0
  102. package/build/navigation/index.js.map +1 -1
  103. package/build/screens/conversation_details_screen.d.ts.map +1 -1
  104. package/build/screens/conversation_details_screen.js +86 -62
  105. package/build/screens/conversation_details_screen.js.map +1 -1
  106. package/build/screens/conversation_filters_screen.d.ts +13 -0
  107. package/build/screens/conversation_filters_screen.d.ts.map +1 -0
  108. package/build/screens/conversation_filters_screen.js +346 -0
  109. package/build/screens/conversation_filters_screen.js.map +1 -0
  110. package/build/screens/conversation_screen.js +2 -1
  111. package/build/screens/conversation_screen.js.map +1 -1
  112. package/build/screens/conversations_screen.d.ts +4 -2
  113. package/build/screens/conversations_screen.d.ts.map +1 -1
  114. package/build/screens/conversations_screen.js +139 -11
  115. package/build/screens/conversations_screen.js.map +1 -1
  116. package/build/screens/create/conversation_select_recipients_screen.d.ts.map +1 -1
  117. package/build/screens/create/conversation_select_recipients_screen.js +3 -11
  118. package/build/screens/create/conversation_select_recipients_screen.js.map +1 -1
  119. package/build/types/resources/group_resource.d.ts +4 -2
  120. package/build/types/resources/group_resource.d.ts.map +1 -1
  121. package/build/types/resources/group_resource.js.map +1 -1
  122. package/build/types/resources/index.d.ts +1 -0
  123. package/build/types/resources/index.d.ts.map +1 -1
  124. package/build/types/resources/index.js +1 -0
  125. package/build/types/resources/index.js.map +1 -1
  126. package/build/types/resources/services/index.d.ts +2 -0
  127. package/build/types/resources/services/index.d.ts.map +1 -0
  128. package/build/types/resources/services/index.js +2 -0
  129. package/build/types/resources/services/index.js.map +1 -0
  130. package/build/types/resources/services/team_resource.d.ts +48 -0
  131. package/build/types/resources/services/team_resource.d.ts.map +1 -0
  132. package/build/types/resources/services/team_resource.js +7 -0
  133. package/build/types/resources/services/team_resource.js.map +1 -0
  134. package/build/utils/index.d.ts +1 -0
  135. package/build/utils/index.d.ts.map +1 -1
  136. package/build/utils/index.js +1 -0
  137. package/build/utils/index.js.map +1 -1
  138. package/build/utils/native_adapters/audio.d.ts +13 -0
  139. package/build/utils/native_adapters/audio.d.ts.map +1 -0
  140. package/build/utils/native_adapters/audio.js +7 -0
  141. package/build/utils/native_adapters/audio.js.map +1 -0
  142. package/build/utils/native_adapters/configuration.d.ts +7 -1
  143. package/build/utils/native_adapters/configuration.d.ts.map +1 -1
  144. package/build/utils/native_adapters/configuration.js +17 -1
  145. package/build/utils/native_adapters/configuration.js.map +1 -1
  146. package/build/utils/native_adapters/index.d.ts +2 -0
  147. package/build/utils/native_adapters/index.d.ts.map +1 -1
  148. package/build/utils/native_adapters/index.js +2 -0
  149. package/build/utils/native_adapters/index.js.map +1 -1
  150. package/build/utils/native_adapters/video.d.ts +25 -0
  151. package/build/utils/native_adapters/video.d.ts.map +1 -0
  152. package/build/utils/native_adapters/video.js +7 -0
  153. package/build/utils/native_adapters/video.js.map +1 -0
  154. package/build/utils/pluralize.d.ts +2 -0
  155. package/build/utils/pluralize.d.ts.map +1 -0
  156. package/build/utils/pluralize.js +10 -0
  157. package/build/utils/pluralize.js.map +1 -0
  158. package/build/utils/request/conversation.d.ts +10 -0
  159. package/build/utils/request/conversation.d.ts.map +1 -0
  160. package/build/utils/request/conversation.js +32 -0
  161. package/build/utils/request/conversation.js.map +1 -0
  162. package/build/utils/request/messages.d.ts +15 -0
  163. package/build/utils/request/messages.d.ts.map +1 -0
  164. package/build/utils/request/messages.js +22 -0
  165. package/build/utils/request/messages.js.map +1 -0
  166. package/build/utils/theme.d.ts +1 -1
  167. package/build/utils/theme.d.ts.map +1 -1
  168. package/build/utils/theme.js +1 -1
  169. package/build/utils/theme.js.map +1 -1
  170. package/package.json +2 -2
  171. package/src/__tests__/utils/pluralize.tsx +17 -0
  172. package/src/components/conversation/attachments/attachment_card.tsx +46 -0
  173. package/src/components/conversation/attachments/audio_attachment.tsx +102 -0
  174. package/src/components/conversation/attachments/constants.ts +5 -0
  175. package/src/components/conversation/attachments/download_attachment_button.tsx +46 -0
  176. package/src/components/conversation/attachments/expanded_link.tsx +54 -0
  177. package/src/components/conversation/attachments/generic_file_attachment.tsx +75 -0
  178. package/src/components/conversation/attachments/giphy_attachment.tsx +56 -0
  179. package/src/components/conversation/attachments/image_attachment.tsx +31 -0
  180. package/src/components/conversation/attachments/video_attachment.tsx +92 -0
  181. package/src/components/conversation/message.tsx +10 -5
  182. package/src/components/conversation/message_attachments.tsx +61 -0
  183. package/src/components/conversations.tsx +37 -35
  184. package/src/components/display/badge.tsx +41 -10
  185. package/src/components/display/button.tsx +1 -1
  186. package/src/components/display/child_notice.tsx +2 -2
  187. package/src/components/display/icon.tsx +10 -8
  188. package/src/hooks/use_api.ts +11 -10
  189. package/src/hooks/use_api_client.ts +1 -1
  190. package/src/hooks/use_conversation.ts +1 -1
  191. package/src/hooks/use_conversation_jolt_events.ts +1 -1
  192. package/src/hooks/use_conversation_messages_jolt_events.ts +1 -1
  193. package/src/hooks/use_conversations.ts +3 -31
  194. package/src/hooks/use_groups.ts +31 -0
  195. package/src/hooks/use_groups_groups.ts +20 -0
  196. package/src/hooks/use_services_team.ts +30 -0
  197. package/src/hooks/use_suspense_api.ts +4 -4
  198. package/src/hooks/use_teams.ts +25 -0
  199. package/src/navigation/index.tsx +8 -0
  200. package/src/screens/conversation_details_screen.tsx +149 -117
  201. package/src/screens/conversation_filters_screen.tsx +488 -0
  202. package/src/screens/conversation_screen.tsx +8 -1
  203. package/src/screens/conversations_screen.tsx +210 -13
  204. package/src/screens/create/conversation_select_recipients_screen.tsx +3 -11
  205. package/src/types/resources/group_resource.ts +5 -2
  206. package/src/types/resources/index.ts +1 -0
  207. package/src/types/resources/services/index.ts +1 -0
  208. package/src/types/resources/services/team_resource.ts +60 -0
  209. package/src/utils/client/types.d.ts +2 -1
  210. package/src/utils/index.ts +1 -0
  211. package/src/utils/native_adapters/audio.ts +15 -0
  212. package/src/utils/native_adapters/configuration.ts +24 -1
  213. package/src/utils/native_adapters/index.ts +2 -0
  214. package/src/utils/native_adapters/video.ts +30 -0
  215. package/src/utils/pluralize.ts +11 -0
  216. package/src/utils/request/conversation.ts +46 -0
  217. package/src/utils/request/messages.ts +21 -0
  218. package/src/utils/theme.ts +2 -2
@@ -2,12 +2,12 @@ import { InfiniteData, useQueryClient } from '@tanstack/react-query'
2
2
  import { ApiCollection, ApiResource, ConversationResource } from '../types'
3
3
  import { deleteRecordInPagesData, updateOrCreateRecordInPagesData } from '../utils'
4
4
  import { useApiClient } from './use_api_client'
5
- import { getConversationsRequestArgs } from './use_conversations'
6
5
  import { useCurrentPerson } from './use_current_person'
7
6
  import { useJoltChannel, useJoltEvent } from './use_jolt'
8
7
  import { getRequestQueryKey } from './use_suspense_api'
9
8
  import { JoltConversationEvent } from '../types/jolt_events'
10
9
  import { ConversationDeletedEvent } from '../types/jolt_events/conversation_events'
10
+ import { getConversationsRequestArgs } from '../utils/request/conversation'
11
11
 
12
12
  type QueryData = InfiniteData<ApiCollection<ConversationResource>>
13
13
 
@@ -9,10 +9,10 @@ import { MessageCreatedEvent, MessageDeletedEvent } from '../types/jolt_events/m
9
9
  import { InfiniteData, useQueryClient } from '@tanstack/react-query'
10
10
  import { useCurrentPerson } from './use_current_person'
11
11
  import { transformMessageEventDataToMessageResource } from '../utils/jolt/transform_message_event_data_to_message_resource'
12
- import { getMessagesRequestArgs } from './use_conversation_messages'
13
12
  import { getRequestQueryKey } from './use_suspense_api'
14
13
  import { JoltReactionEvent } from '../types/jolt_events'
15
14
  import { transformReactionEventDataToReactionCountResource } from '../utils/jolt/transform_reaction_event_data_to_reaction_count_resource'
15
+ import { getMessagesRequestArgs } from '../utils/request/messages'
16
16
 
17
17
  interface Props {
18
18
  conversationId: number
@@ -1,38 +1,10 @@
1
1
  import { useMemo } from 'react'
2
2
  import { ConversationResource } from '../types'
3
- import { GetRequest } from '../utils/client/types'
4
3
  import { useSuspensePaginator } from './use_suspense_api'
4
+ import { ConversationRequestArgs, getConversationsRequestArgs } from '../utils/request/conversation'
5
5
 
6
- export const getConversationsRequestArgs = (): GetRequest => ({
7
- url: '/me/conversations',
8
- data: {
9
- perPage: 20,
10
- order: '-last_message',
11
- fields: {
12
- Conversation: [
13
- 'created_at',
14
- 'badges',
15
- 'groups',
16
- 'last_message_author_id',
17
- 'last_message_author_name',
18
- 'last_message_created_at',
19
- 'last_message_text_preview',
20
- 'preview_avatar_urls',
21
- 'member_ability',
22
- 'muted',
23
- 'replies_disabled',
24
- 'title',
25
- 'unread_count',
26
- 'updated_at',
27
- ],
28
- ConversationBadge: ['app_name', 'pco_resource_type', 'text'],
29
- },
30
- include: ['badges'],
31
- },
32
- })
33
-
34
- export function useConversations() {
35
- const requestArgs = getConversationsRequestArgs()
6
+ export function useConversations(args?: Partial<ConversationRequestArgs>) {
7
+ const requestArgs = getConversationsRequestArgs(args)
36
8
  const { data, ...rest } = useSuspensePaginator<ConversationResource>(requestArgs)
37
9
 
38
10
  const conversations = useMemo(
@@ -0,0 +1,31 @@
1
+ import { AppName } from '../types/resources/app_name'
2
+ import { GroupResource, SourceType } from '../types/resources/group_resource'
3
+ import { useApiPaginator } from './use_api'
4
+
5
+ type UseGroupsProps = {
6
+ source_app_name: AppName
7
+ source_type: SourceType
8
+ }
9
+
10
+ export const useGroups = ({ source_app_name, source_type }: UseGroupsProps) => {
11
+ return useApiPaginator<GroupResource>({
12
+ url: '/me/groups',
13
+ data: {
14
+ fields: {
15
+ Group: [],
16
+ },
17
+ where: {
18
+ source_app_name,
19
+ source_type,
20
+ },
21
+ perPage: 100,
22
+ },
23
+ app: 'chat',
24
+ })
25
+ }
26
+
27
+ export const useCanDisplayGroups = (props: UseGroupsProps) => {
28
+ const { data: teams = [] } = useGroups(props)
29
+
30
+ return teams?.length > 0
31
+ }
@@ -0,0 +1,20 @@
1
+ import { GroupsGroupResource } from '../types'
2
+ import { useApiPaginator } from './use_api'
3
+
4
+ export const useGroupsGroups = () => {
5
+ return useApiPaginator<GroupsGroupResource>({
6
+ url: '/me/groups',
7
+ data: {
8
+ perPage: 100,
9
+ fields: {
10
+ Group: ['can_create_conversation', 'name', 'header_image', 'memberships_count'],
11
+ },
12
+ },
13
+ app: 'groups',
14
+ })
15
+ }
16
+
17
+ export const useCanDisplayGroupsGroups = () => {
18
+ const { data: groups = [] } = useGroupsGroups()
19
+ return groups?.length > 0
20
+ }
@@ -0,0 +1,30 @@
1
+ import { TeamOptionResource, TeamOptionResponseItem } from '../types'
2
+ import { useApiGet } from './use_api'
3
+
4
+ export const useServicesTeams = () => {
5
+ const { data: chat } = useApiGet<TeamOptionResource>({
6
+ url: '/chat',
7
+ data: {
8
+ fields: {
9
+ Chat: ['teams'],
10
+ },
11
+ },
12
+ app: 'services',
13
+ })
14
+
15
+ return chat?.teams || []
16
+ }
17
+
18
+ export const useServicesTeamsMap = () => {
19
+ const teams = useServicesTeams()
20
+
21
+ return teams.reduce(
22
+ (acc, team) => {
23
+ const id = `Services-Team-${team.value.teamId}`
24
+ acc[id] = team
25
+
26
+ return acc
27
+ },
28
+ {} as Record<string, TeamOptionResponseItem>
29
+ )
30
+ }
@@ -6,10 +6,10 @@ import {
6
6
  } from '@tanstack/react-query'
7
7
  import { ApiCollection, ApiResource, ResourceObject } from '../types'
8
8
  import { GetRequest, RequestData } from '../utils/client/types'
9
- import { useApiClient } from './use_api_client'
9
+ import { App, useApiClient } from './use_api_client'
10
10
 
11
11
  interface SuspenseGetOptions extends GetRequest {
12
- app?: 'chat' | 'groups'
12
+ app?: App
13
13
  }
14
14
 
15
15
  export const useSuspenseGet = <T extends ResourceObject | ResourceObject[]>(
@@ -51,11 +51,11 @@ export const useSuspensePaginator = <T extends ResourceObject>(
51
51
  const pageParmWhere = pageParam?.where || {}
52
52
  const argsWhere = args.data.where || {}
53
53
  const where = { ...argsWhere, ...pageParmWhere }
54
-
54
+ const app = args.app || 'chat'
55
55
  const offset = pageParam?.offset || args.data.offset
56
56
  const data = { ...args.data, where, offset }
57
57
 
58
- return apiClient.chat.get({
58
+ return apiClient[app].get({
59
59
  url: args.url,
60
60
  data,
61
61
  })
@@ -0,0 +1,25 @@
1
+ import { GroupResource } from '../types/resources/group_resource'
2
+ import { useApiPaginator } from './use_api'
3
+
4
+ export const useTeams = () => {
5
+ return useApiPaginator<GroupResource>({
6
+ url: '/me/groups',
7
+ data: {
8
+ fields: {
9
+ Group: [],
10
+ },
11
+ where: {
12
+ source_app_name: 'Services',
13
+ source_type: 'Team',
14
+ },
15
+ perPage: 100,
16
+ },
17
+ app: 'chat',
18
+ })
19
+ }
20
+
21
+ export const useCanDisplayTeams = () => {
22
+ const { data: teams = [] } = useTeams()
23
+
24
+ return teams?.length > 0
25
+ }
@@ -23,6 +23,10 @@ import { NotFound } from '../screens/not_found'
23
23
  import { ReactionsScreen, ReactionsScreenOptions } from '../screens/reactions_screen'
24
24
  import { HeaderRightButton } from './header'
25
25
  import { ScreenLayout } from './screenLayout'
26
+ import {
27
+ ConversationFiltersScreen,
28
+ ConversationFiltersScreenOptions,
29
+ } from '../screens/conversation_filters_screen'
26
30
 
27
31
  export const CreateConversationStack = createNativeStackNavigator({
28
32
  initialRouteName: 'ConversationSelectRecipients',
@@ -75,6 +79,10 @@ export const ChatStack = createNativeStackNavigator({
75
79
  ),
76
80
  }),
77
81
  },
82
+ ConversationFilters: {
83
+ screen: ConversationFiltersScreen,
84
+ options: ConversationFiltersScreenOptions,
85
+ },
78
86
  Conversation: {
79
87
  screen: ConversationScreen,
80
88
  },
@@ -62,6 +62,7 @@ interface DataItem<T, TName extends SectionTypes> {
62
62
  data: T
63
63
  sectionOuterStyle?: ViewStyle
64
64
  sectionInnerStyle?: ViewStyle
65
+ showBottomBorder?: boolean
65
66
  }
66
67
 
67
68
  // =================================
@@ -100,6 +101,28 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
100
101
  },
101
102
  })
102
103
 
104
+ const memberSectionStyleMap = {
105
+ first: styles.sectionInnerFirstMember,
106
+ middle: styles.sectionInnerMiddleMiddle,
107
+ last: styles.sectionInnerLastMember,
108
+ }
109
+
110
+ const memberItems = members.map((data, index) => {
111
+ const isFirst = index === 0
112
+ const isLast = index === members.length - 1
113
+ const memberPosition = isFirst ? 'first' : isLast ? 'last' : 'middle'
114
+ const memberSectionStyle = memberSectionStyleMap[memberPosition]
115
+
116
+ return {
117
+ type: data.child ? SectionTypes.hidden : SectionTypes.members,
118
+ data,
119
+ sectionInnerStyle: memberSectionStyle,
120
+ }
121
+ })
122
+
123
+ const childMembers = members.filter(member => member.child)
124
+ const hasChildren = childMembers.length > 0
125
+
103
126
  const teamsGroup =
104
127
  conversation.groups
105
128
  ?.filter(g => g.sourceAppName === 'Services')
@@ -107,18 +130,9 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
107
130
  ?.filter(g => g.name !== null) || []
108
131
  const hasTeams = teamsGroup.length > 0
109
132
 
110
- const memberItems = members.map(data => ({
111
- type: data.child ? SectionTypes.hidden : SectionTypes.members,
112
- data,
113
- sectionOuterStyle: styles.memberSectionOuter,
114
- sectionInnerStyle: styles.memberSectionInner,
115
- }))
116
-
117
- const childMembers = members.filter(member => member.child)
118
- const hasChildren = childMembers.length > 0
119
-
120
133
  const badge = conversation.badges?.[0]
121
134
  const resourceType = badge?.pcoResourceType || ''
135
+ const productName = badge?.appName
122
136
  const name = badge?.text || undefined
123
137
 
124
138
  const handleDelete = useCallback(() => {
@@ -152,11 +166,12 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
152
166
  label={resourceType}
153
167
  metaLabel={name}
154
168
  style={styles.headerTitleBadge}
169
+ productLogoName={productName}
155
170
  />
156
171
  </View>
157
172
  )
158
173
  },
159
- [name, resourceType, styles.headerTitleBadge, styles.headerTitleContainer]
174
+ [name, productName, resourceType, styles.headerTitleBadge, styles.headerTitleContainer]
160
175
  )
161
176
 
162
177
  const HeaderRight = useCallback(() => {
@@ -192,11 +207,13 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
192
207
  />
193
208
  ),
194
209
  },
210
+ sectionInnerStyle: styles.sectionInnerTitleInput,
195
211
  },
196
212
  {
197
213
  type: SectionTypes.header,
198
214
  data: { title: 'Settings' },
199
- sectionInnerStyle: styles.addBottomBorder,
215
+ showBottomBorder: true,
216
+ sectionInnerStyle: styles.sectionInnerHeaderWithBottomBorder,
200
217
  },
201
218
  {
202
219
  type: SectionTypes.setting,
@@ -204,7 +221,7 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
204
221
  title: 'Mute',
205
222
  rightItem: <Switch value={muted} onChange={() => setMuted(!muted)} />,
206
223
  },
207
- sectionInnerStyle: styles.addBottomBorder,
224
+ showBottomBorder: true,
208
225
  },
209
226
  {
210
227
  type: canUpdate ? SectionTypes.setting : SectionTypes.hidden,
@@ -215,13 +232,12 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
215
232
  <Switch value={repliesDisabled} onChange={() => setRepliesDisabled(!repliesDisabled)} />
216
233
  ),
217
234
  },
218
- sectionInnerStyle: styles.addBottomBorder,
235
+ showBottomBorder: true,
219
236
  },
220
237
  {
221
238
  type: canDelete ? SectionTypes.setting : SectionTypes.hidden,
222
239
  data: {
223
240
  title: 'Delete conversation…',
224
- style: styles.deleteButton,
225
241
  buttonTextStyle: styles.deleteButtonText,
226
242
  appearance: 'danger',
227
243
  onPress: handleDelete,
@@ -230,6 +246,7 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
230
246
  {
231
247
  type: hasTeams ? SectionTypes.header : SectionTypes.hidden,
232
248
  data: { title: 'Teams' },
249
+ sectionInnerStyle: styles.sectionInnerHeader,
233
250
  },
234
251
  {
235
252
  type: hasTeams ? SectionTypes.view : SectionTypes.hidden,
@@ -239,14 +256,15 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
239
256
  },
240
257
  {
241
258
  type: SectionTypes.header,
242
- data: { title: 'Members' },
259
+ data: { title: 'People' },
260
+ sectionInnerStyle: styles.sectionInnerHeader,
243
261
  },
244
262
  {
245
263
  type: hasChildren && isLeader ? SectionTypes.view : SectionTypes.hidden,
246
264
  data: {
247
265
  children: <ChildNotice childMembers={childMembers} />,
248
266
  },
249
- sectionOuterStyle: styles.childNoticeSectionOuter,
267
+ sectionInnerStyle: styles.sectionInnerChildNotice,
250
268
  },
251
269
  ...memberItems,
252
270
  ].filter(item => item.type !== SectionTypes.hidden)
@@ -256,97 +274,98 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
256
274
  .filter(isDefined)
257
275
 
258
276
  return (
259
- <FlashList
260
- data={listData as SectionListData}
261
- estimatedItemSize={52}
262
- contentContainerStyle={styles.contentContainer}
263
- renderItem={({ item, index }) => {
264
- const [isStart, isEnd] = [
265
- index === 0 || headerIndices.includes(index),
266
- index === listData.length - 1 || headerIndices.includes(index + 1),
267
- ]
268
-
269
- switch (item.type) {
270
- case SectionTypes.header:
271
- return (
272
- <ListSection
273
- isStart={isStart}
274
- isEnd={isEnd}
275
- outerStyle={item?.sectionOuterStyle}
276
- innerStyle={item?.sectionInnerStyle}
277
- >
278
- <SectionHeading title={item.data.title} />
279
- </ListSection>
280
- )
281
- case SectionTypes.members:
282
- return (
283
- <ListSection
284
- isStart={isStart}
285
- isEnd={isEnd}
286
- outerStyle={item?.sectionOuterStyle}
287
- innerStyle={item?.sectionInnerStyle}
288
- >
289
- <Person person={{ ...item.data }} />
290
- </ListSection>
291
- )
292
- case SectionTypes.setting:
293
- return (
294
- <ListSection
295
- isStart={isStart}
296
- isEnd={isEnd}
297
- outerStyle={item?.sectionOuterStyle}
298
- innerStyle={item?.sectionInnerStyle}
299
- >
300
- <SettingRow {...item.data} />
301
- </ListSection>
302
- )
303
- case SectionTypes.view:
304
- return (
305
- <ListSection
306
- isStart={isStart}
307
- isEnd={isEnd}
308
- outerStyle={item?.sectionOuterStyle}
309
- innerStyle={item?.sectionInnerStyle}
310
- >
311
- <View {...item.data} style={item.data.style} />
312
- </ListSection>
313
- )
314
- default:
315
- return null
316
- }
317
- }}
318
- />
277
+ <View style={styles.listContainer}>
278
+ <FlashList
279
+ data={listData as SectionListData}
280
+ estimatedItemSize={52}
281
+ contentContainerStyle={styles.contentContainer}
282
+ renderItem={({ item, index }) => {
283
+ const [isStart, isEnd] = [
284
+ index === 0 || headerIndices.includes(index),
285
+ index === listData.length - 1 || headerIndices.includes(index + 1),
286
+ ]
287
+
288
+ switch (item.type) {
289
+ case SectionTypes.header:
290
+ return (
291
+ <ListSection
292
+ isStart={isStart}
293
+ isEnd={isEnd}
294
+ showBottomBorder={item?.showBottomBorder}
295
+ outerStyle={item?.sectionOuterStyle}
296
+ innerStyle={item?.sectionInnerStyle}
297
+ >
298
+ <Heading variant="h3">{item.data.title}</Heading>
299
+ </ListSection>
300
+ )
301
+ case SectionTypes.members:
302
+ return (
303
+ <ListSection
304
+ isStart={isStart}
305
+ isEnd={isEnd}
306
+ showBottomBorder={item?.showBottomBorder}
307
+ outerStyle={item?.sectionOuterStyle}
308
+ innerStyle={item?.sectionInnerStyle}
309
+ >
310
+ <Person person={{ ...item.data }} />
311
+ </ListSection>
312
+ )
313
+ case SectionTypes.setting:
314
+ return (
315
+ <ListSection
316
+ isStart={isStart}
317
+ isEnd={isEnd}
318
+ showBottomBorder={item?.showBottomBorder}
319
+ outerStyle={item?.sectionOuterStyle}
320
+ innerStyle={item?.sectionInnerStyle}
321
+ >
322
+ <SettingRow {...item.data} />
323
+ </ListSection>
324
+ )
325
+ case SectionTypes.view:
326
+ return (
327
+ <ListSection
328
+ isStart={isStart}
329
+ isEnd={isEnd}
330
+ showBottomBorder={item?.showBottomBorder}
331
+ outerStyle={item?.sectionOuterStyle}
332
+ innerStyle={item?.sectionInnerStyle}
333
+ >
334
+ <View {...item.data} style={item.data.style} />
335
+ </ListSection>
336
+ )
337
+ default:
338
+ return null
339
+ }
340
+ }}
341
+ />
342
+ </View>
319
343
  )
320
344
  }
321
345
 
322
346
  interface ListSectionProps {
323
347
  isStart?: boolean
324
348
  isEnd?: boolean
349
+ showBottomBorder?: boolean
325
350
  outerStyle?: ViewStyle
326
351
  innerStyle?: ViewStyle
327
352
  children: ReactNode
328
353
  }
329
354
 
330
- function ListSection({ isStart, isEnd, outerStyle, innerStyle, children }: ListSectionProps) {
355
+ function ListSection({
356
+ isStart,
357
+ isEnd,
358
+ showBottomBorder,
359
+ outerStyle,
360
+ innerStyle,
361
+ children,
362
+ }: ListSectionProps) {
331
363
  const styles = useStyles({ isStart, isEnd })
364
+ const bottomBorder = showBottomBorder ? styles.sectionInnerBottomBorder : {}
332
365
 
333
366
  return (
334
- <View style={[styles.sectionOuter, outerStyle]}>
335
- <View style={[styles.sectionInner, innerStyle]}>{children}</View>
336
- </View>
337
- )
338
- }
339
-
340
- interface SectionHeadingProps {
341
- title: string
342
- }
343
-
344
- function SectionHeading({ title }: SectionHeadingProps) {
345
- const styles = useStyles()
346
-
347
- return (
348
- <View style={styles.header}>
349
- <Heading variant="h3">{title}</Heading>
367
+ <View style={[styles.sectionOuterBase, outerStyle]}>
368
+ <View style={[styles.sectionInnerBase, bottomBorder, innerStyle]}>{children}</View>
350
369
  </View>
351
370
  )
352
371
  }
@@ -468,14 +487,17 @@ function TeamsGroup({ teams }: { teams: GroupResource[] }) {
468
487
 
469
488
  const useStyles = ({ isStart, isEnd }: { isStart?: boolean; isEnd?: boolean } = {}) => {
470
489
  const { colors } = useTheme()
490
+ const headerBottomPadding = space(0.5)
471
491
 
472
492
  return StyleSheet.create({
473
- contentContainer: {
493
+ listContainer: {
494
+ flex: 1,
474
495
  backgroundColor: colors.fillColorNeutral080,
496
+ },
497
+ contentContainer: {
475
498
  padding: space(2),
476
499
  },
477
- sectionOuter: {
478
- paddingTop: space(1),
500
+ sectionOuterBase: {
479
501
  paddingLeft: space(2),
480
502
  backgroundColor: colors.fillColorNeutral100Inverted,
481
503
  borderTopLeftRadius: isStart ? space(1) : 0,
@@ -484,15 +506,40 @@ const useStyles = ({ isStart, isEnd }: { isStart?: boolean; isEnd?: boolean } =
484
506
  borderBottomRightRadius: isEnd ? space(1) : 0,
485
507
  marginBottom: isEnd ? space(2) : 0,
486
508
  },
487
- sectionInner: {
488
- borderBottomWidth: 0,
489
- borderBottomColor: colors.borderColorDefaultBase,
509
+ sectionInnerBase: {
490
510
  paddingRight: space(2),
491
- paddingBottom: space(1),
511
+ paddingTop: isStart ? space(2) : space(1.5),
512
+ paddingBottom: isEnd ? space(2) : space(1.5),
513
+ },
514
+ sectionInnerHeader: {
515
+ paddingBottom: headerBottomPadding,
516
+ },
517
+ sectionInnerHeaderWithBottomBorder: {
518
+ paddingBottom: space(2),
492
519
  },
493
- addBottomBorder: {
520
+ sectionInnerBottomBorder: {
521
+ borderBottomColor: colors.borderColorDefaultBase,
494
522
  borderBottomWidth: isEnd ? 0 : 1,
495
523
  },
524
+ sectionInnerTitleInput: {
525
+ paddingTop: space(1.5), // paddingVertical doesn't override the sectionInner padding
526
+ paddingBottom: space(1.5),
527
+ },
528
+ sectionInnerChildNotice: {
529
+ paddingBottom: headerBottomPadding,
530
+ },
531
+ sectionInnerMiddleMiddle: {
532
+ paddingTop: 0,
533
+ paddingBottom: space(1.5),
534
+ },
535
+ sectionInnerFirstMember: {
536
+ paddingTop: space(1.5),
537
+ paddingBottom: space(1.5),
538
+ },
539
+ sectionInnerLastMember: {
540
+ paddingTop: 0,
541
+ paddingBottom: space(2),
542
+ },
496
543
  titleContainer: {
497
544
  gap: 4,
498
545
  },
@@ -520,9 +567,6 @@ const useStyles = ({ isStart, isEnd }: { isStart?: boolean; isEnd?: boolean } =
520
567
  borderTopWidth: 1,
521
568
  borderColor: colors.borderColorStatusError,
522
569
  },
523
- header: {
524
- paddingVertical: space(1.5),
525
- },
526
570
  settingRow: {
527
571
  flexDirection: 'row',
528
572
  justifyContent: 'space-between',
@@ -532,9 +576,6 @@ const useStyles = ({ isStart, isEnd }: { isStart?: boolean; isEnd?: boolean } =
532
576
  settingRowContent: {
533
577
  flex: 1,
534
578
  },
535
- deleteButton: {
536
- paddingVertical: 4,
537
- },
538
579
  deleteButtonText: {
539
580
  fontWeight: 'normal',
540
581
  },
@@ -546,15 +587,6 @@ const useStyles = ({ isStart, isEnd }: { isStart?: boolean; isEnd?: boolean } =
546
587
  gap: 4,
547
588
  flexWrap: 'wrap',
548
589
  },
549
- childNoticeSectionOuter: {
550
- paddingTop: 0,
551
- },
552
- memberSectionOuter: {
553
- paddingTop: 6,
554
- },
555
- memberSectionInner: {
556
- paddingBottom: 6,
557
- },
558
590
  headerTitleBadge: {
559
591
  alignSelf: Platform.select({ android: 'flex-start', default: 'center' }),
560
592
  marginTop: 2,