@planningcenter/chat-react-native 3.39.0-rc.0 → 3.39.0-rc.10

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 (205) hide show
  1. package/build/components/conversation/messages_disabled_banners.d.ts +6 -1
  2. package/build/components/conversation/messages_disabled_banners.d.ts.map +1 -1
  3. package/build/components/conversation/messages_disabled_banners.js +8 -2
  4. package/build/components/conversation/messages_disabled_banners.js.map +1 -1
  5. package/build/contexts/api_provider.js +2 -1
  6. package/build/contexts/api_provider.js.map +1 -1
  7. package/build/contexts/conversations_context.d.ts.map +1 -1
  8. package/build/contexts/conversations_context.js +6 -2
  9. package/build/contexts/conversations_context.js.map +1 -1
  10. package/build/hooks/direct_messages/use_direct_message_affiliations.d.ts +5 -0
  11. package/build/hooks/direct_messages/use_direct_message_affiliations.d.ts.map +1 -0
  12. package/build/hooks/direct_messages/use_direct_message_affiliations.js +20 -0
  13. package/build/hooks/direct_messages/use_direct_message_affiliations.js.map +1 -0
  14. package/build/hooks/direct_messages/use_direct_message_candidates.d.ts +4 -0
  15. package/build/hooks/direct_messages/use_direct_message_candidates.d.ts.map +1 -0
  16. package/build/hooks/direct_messages/use_direct_message_candidates.js +28 -0
  17. package/build/hooks/direct_messages/use_direct_message_candidates.js.map +1 -0
  18. package/build/hooks/direct_messages/use_direct_message_conversation_validate.d.ts +11 -0
  19. package/build/hooks/direct_messages/use_direct_message_conversation_validate.d.ts.map +1 -0
  20. package/build/hooks/direct_messages/use_direct_message_conversation_validate.js +25 -0
  21. package/build/hooks/direct_messages/use_direct_message_conversation_validate.js.map +1 -0
  22. package/build/hooks/direct_messages/use_find_or_create_direct_message_conversation.d.ts +13 -0
  23. package/build/hooks/direct_messages/use_find_or_create_direct_message_conversation.d.ts.map +1 -0
  24. package/build/hooks/direct_messages/use_find_or_create_direct_message_conversation.js +51 -0
  25. package/build/hooks/direct_messages/use_find_or_create_direct_message_conversation.js.map +1 -0
  26. package/build/hooks/groups/use_group_chat_conversation_payload.d.ts.map +1 -1
  27. package/build/hooks/groups/use_group_chat_conversation_payload.js +2 -1
  28. package/build/hooks/groups/use_group_chat_conversation_payload.js.map +1 -1
  29. package/build/hooks/index.d.ts +1 -0
  30. package/build/hooks/index.d.ts.map +1 -1
  31. package/build/hooks/index.js +1 -0
  32. package/build/hooks/index.js.map +1 -1
  33. package/build/hooks/services/use_services_chat_conversation_payload.d.ts.map +1 -1
  34. package/build/hooks/services/use_services_chat_conversation_payload.js +2 -1
  35. package/build/hooks/services/use_services_chat_conversation_payload.js.map +1 -1
  36. package/build/hooks/use_api.d.ts +5 -1
  37. package/build/hooks/use_api.d.ts.map +1 -1
  38. package/build/hooks/use_api.js +2 -1
  39. package/build/hooks/use_api.js.map +1 -1
  40. package/build/hooks/use_chat_configuration.d.ts.map +1 -1
  41. package/build/hooks/use_chat_configuration.js +2 -1
  42. package/build/hooks/use_chat_configuration.js.map +1 -1
  43. package/build/hooks/use_chat_permissions.d.ts.map +1 -1
  44. package/build/hooks/use_chat_permissions.js +4 -1
  45. package/build/hooks/use_chat_permissions.js.map +1 -1
  46. package/build/hooks/use_conversation.d.ts.map +1 -1
  47. package/build/hooks/use_conversation.js +1 -0
  48. package/build/hooks/use_conversation.js.map +1 -1
  49. package/build/hooks/use_conversation_jolt_events.d.ts.map +1 -1
  50. package/build/hooks/use_conversation_jolt_events.js +2 -2
  51. package/build/hooks/use_conversation_jolt_events.js.map +1 -1
  52. package/build/hooks/use_current_person.d.ts.map +1 -1
  53. package/build/hooks/use_current_person.js +4 -2
  54. package/build/hooks/use_current_person.js.map +1 -1
  55. package/build/hooks/use_features.d.ts.map +1 -1
  56. package/build/hooks/use_features.js +2 -1
  57. package/build/hooks/use_features.js.map +1 -1
  58. package/build/hooks/use_groups.d.ts.map +1 -1
  59. package/build/hooks/use_groups.js +2 -1
  60. package/build/hooks/use_groups.js.map +1 -1
  61. package/build/hooks/use_groups_groups.d.ts.map +1 -1
  62. package/build/hooks/use_groups_groups.js +2 -1
  63. package/build/hooks/use_groups_groups.js.map +1 -1
  64. package/build/hooks/use_has_direct_messages.d.ts +2 -0
  65. package/build/hooks/use_has_direct_messages.d.ts.map +1 -0
  66. package/build/hooks/use_has_direct_messages.js +17 -0
  67. package/build/hooks/use_has_direct_messages.js.map +1 -0
  68. package/build/hooks/use_jolt.d.ts.map +1 -1
  69. package/build/hooks/use_jolt.js +2 -1
  70. package/build/hooks/use_jolt.js.map +1 -1
  71. package/build/hooks/use_organization.d.ts.map +1 -1
  72. package/build/hooks/use_organization.js +4 -1
  73. package/build/hooks/use_organization.js.map +1 -1
  74. package/build/hooks/use_person_settings.d.ts +6 -0
  75. package/build/hooks/use_person_settings.d.ts.map +1 -0
  76. package/build/hooks/use_person_settings.js +26 -0
  77. package/build/hooks/use_person_settings.js.map +1 -0
  78. package/build/navigation/index.d.ts +13 -0
  79. package/build/navigation/index.d.ts.map +1 -1
  80. package/build/navigation/index.js +9 -0
  81. package/build/navigation/index.js.map +1 -1
  82. package/build/screens/conversation_details_screen.d.ts.map +1 -1
  83. package/build/screens/conversation_details_screen.js +2 -1
  84. package/build/screens/conversation_details_screen.js.map +1 -1
  85. package/build/screens/conversation_filters/components/conversation_filters.d.ts.map +1 -1
  86. package/build/screens/conversation_filters/components/conversation_filters.js +20 -5
  87. package/build/screens/conversation_filters/components/conversation_filters.js.map +1 -1
  88. package/build/screens/conversation_filters/components/rows.d.ts +2 -1
  89. package/build/screens/conversation_filters/components/rows.d.ts.map +1 -1
  90. package/build/screens/conversation_filters/components/rows.js +2 -2
  91. package/build/screens/conversation_filters/components/rows.js.map +1 -1
  92. package/build/screens/conversation_filters/context/conversation_filter_context.d.ts.map +1 -1
  93. package/build/screens/conversation_filters/context/conversation_filter_context.js +4 -0
  94. package/build/screens/conversation_filters/context/conversation_filter_context.js.map +1 -1
  95. package/build/screens/conversation_filters/filter_types.d.ts +1 -0
  96. package/build/screens/conversation_filters/filter_types.d.ts.map +1 -1
  97. package/build/screens/conversation_filters/filter_types.js +1 -0
  98. package/build/screens/conversation_filters/filter_types.js.map +1 -1
  99. package/build/screens/conversation_filters/screen_props.d.ts +1 -0
  100. package/build/screens/conversation_filters/screen_props.d.ts.map +1 -1
  101. package/build/screens/conversation_filters/screen_props.js.map +1 -1
  102. package/build/screens/conversation_screen.d.ts.map +1 -1
  103. package/build/screens/conversation_screen.js +1 -1
  104. package/build/screens/conversation_screen.js.map +1 -1
  105. package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.d.ts +1 -2
  106. package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.d.ts.map +1 -1
  107. package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.js +319 -10
  108. package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.js.map +1 -1
  109. package/build/screens/conversations/components/list_header_component.d.ts.map +1 -1
  110. package/build/screens/conversations/components/list_header_component.js +35 -17
  111. package/build/screens/conversations/components/list_header_component.js.map +1 -1
  112. package/build/screens/conversations/conversations_screen.d.ts +1 -0
  113. package/build/screens/conversations/conversations_screen.d.ts.map +1 -1
  114. package/build/screens/conversations/conversations_screen.js.map +1 -1
  115. package/build/screens/get_help_screen.d.ts.map +1 -1
  116. package/build/screens/get_help_screen.js +2 -18
  117. package/build/screens/get_help_screen.js.map +1 -1
  118. package/build/screens/index.d.ts +1 -0
  119. package/build/screens/index.d.ts.map +1 -1
  120. package/build/screens/index.js +1 -0
  121. package/build/screens/index.js.map +1 -1
  122. package/build/screens/settings_screen.d.ts +5 -0
  123. package/build/screens/settings_screen.d.ts.map +1 -0
  124. package/build/screens/settings_screen.js +56 -0
  125. package/build/screens/settings_screen.js.map +1 -0
  126. package/build/types/jolt_events/conversation_events.d.ts +2 -0
  127. package/build/types/jolt_events/conversation_events.d.ts.map +1 -1
  128. package/build/types/jolt_events/conversation_events.js.map +1 -1
  129. package/build/types/resources/conversation.d.ts +2 -0
  130. package/build/types/resources/conversation.d.ts.map +1 -1
  131. package/build/types/resources/conversation.js.map +1 -1
  132. package/build/types/resources/direct_message_affiliations.d.ts +8 -0
  133. package/build/types/resources/direct_message_affiliations.d.ts.map +1 -0
  134. package/build/types/resources/direct_message_affiliations.js +2 -0
  135. package/build/types/resources/direct_message_affiliations.js.map +1 -0
  136. package/build/types/resources/direct_message_candidate.d.ts +12 -0
  137. package/build/types/resources/direct_message_candidate.d.ts.map +1 -0
  138. package/build/types/resources/direct_message_candidate.js +2 -0
  139. package/build/types/resources/direct_message_candidate.js.map +1 -0
  140. package/build/types/resources/index.d.ts +2 -0
  141. package/build/types/resources/index.d.ts.map +1 -1
  142. package/build/types/resources/index.js +2 -0
  143. package/build/types/resources/index.js.map +1 -1
  144. package/build/types/resources/organization.d.ts +1 -0
  145. package/build/types/resources/organization.d.ts.map +1 -1
  146. package/build/types/resources/organization.js.map +1 -1
  147. package/build/types/resources/person.d.ts +1 -0
  148. package/build/types/resources/person.d.ts.map +1 -1
  149. package/build/types/resources/person.js.map +1 -1
  150. package/build/utils/request/conversation.d.ts +2 -1
  151. package/build/utils/request/conversation.d.ts.map +1 -1
  152. package/build/utils/request/conversation.js +15 -6
  153. package/build/utils/request/conversation.js.map +1 -1
  154. package/build/utils/time.d.ts +8 -0
  155. package/build/utils/time.d.ts.map +1 -0
  156. package/build/utils/time.js +15 -0
  157. package/build/utils/time.js.map +1 -0
  158. package/package.json +2 -2
  159. package/src/components/conversation/messages_disabled_banners.tsx +16 -2
  160. package/src/contexts/api_provider.tsx +4 -1
  161. package/src/contexts/conversations_context.tsx +6 -2
  162. package/src/hooks/direct_messages/use_direct_message_affiliations.ts +39 -0
  163. package/src/hooks/direct_messages/use_direct_message_candidates.ts +31 -0
  164. package/src/hooks/direct_messages/use_direct_message_conversation_validate.ts +35 -0
  165. package/src/hooks/direct_messages/use_find_or_create_direct_message_conversation.ts +66 -0
  166. package/src/hooks/groups/use_group_chat_conversation_payload.ts +2 -1
  167. package/src/hooks/index.ts +1 -0
  168. package/src/hooks/services/use_services_chat_conversation_payload.ts +2 -1
  169. package/src/hooks/use_api.ts +10 -1
  170. package/src/hooks/use_chat_configuration.ts +2 -1
  171. package/src/hooks/use_chat_permissions.ts +4 -1
  172. package/src/hooks/use_conversation.ts +1 -0
  173. package/src/hooks/use_conversation_jolt_events.ts +3 -2
  174. package/src/hooks/use_current_person.ts +4 -2
  175. package/src/hooks/use_features.ts +2 -1
  176. package/src/hooks/use_groups.ts +16 -12
  177. package/src/hooks/use_groups_groups.ts +19 -15
  178. package/src/hooks/use_has_direct_messages.ts +21 -0
  179. package/src/hooks/use_jolt.ts +2 -1
  180. package/src/hooks/use_organization.ts +4 -1
  181. package/src/hooks/use_person_settings.ts +29 -0
  182. package/src/navigation/index.tsx +11 -0
  183. package/src/screens/conversation_details_screen.tsx +2 -1
  184. package/src/screens/conversation_filters/components/conversation_filters.tsx +25 -5
  185. package/src/screens/conversation_filters/components/rows.tsx +16 -3
  186. package/src/screens/conversation_filters/context/conversation_filter_context.tsx +4 -0
  187. package/src/screens/conversation_filters/filter_types.ts +1 -0
  188. package/src/screens/conversation_filters/screen_props.ts +1 -0
  189. package/src/screens/conversation_screen.tsx +2 -1
  190. package/src/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.tsx +513 -10
  191. package/src/screens/conversations/components/list_header_component.tsx +84 -34
  192. package/src/screens/conversations/conversations_screen.tsx +1 -0
  193. package/src/screens/get_help_screen.tsx +2 -29
  194. package/src/screens/index.ts +1 -0
  195. package/src/screens/settings_screen.tsx +67 -0
  196. package/src/types/jolt_events/conversation_events.ts +2 -0
  197. package/src/types/resources/conversation.ts +3 -0
  198. package/src/types/resources/direct_message_affiliations.ts +8 -0
  199. package/src/types/resources/direct_message_candidate.ts +12 -0
  200. package/src/types/resources/index.ts +2 -0
  201. package/src/types/resources/organization.ts +1 -0
  202. package/src/types/resources/person.ts +1 -0
  203. package/src/utils/__tests__/conversation.test.ts +14 -0
  204. package/src/utils/request/conversation.ts +13 -5
  205. package/src/utils/time.ts +17 -0
@@ -2,12 +2,18 @@ import { RouteProp, useNavigation, useRoute } from '@react-navigation/native'
2
2
  import React, { useCallback, useMemo } from 'react'
3
3
  import { Alert, ScrollView, StyleSheet, View } from 'react-native'
4
4
  import { Heading, TextButton, ToggleButton } from '../../../components'
5
- import { useAtFontScaleBreakpoint, useCurrentPersonCache, useTheme } from '../../../hooks'
6
- import { useCanCreateConversations } from '../../../hooks'
5
+ import {
6
+ useAtFontScaleBreakpoint,
7
+ useCanCreateConversations,
8
+ useCurrentPersonCache,
9
+ useDirectMessagesEnabled,
10
+ useHasDirectMessages,
11
+ useNewConversationEntry,
12
+ useTheme,
13
+ } from '../../../hooks'
7
14
  import { useAppName } from '../../../hooks/use_app_name'
8
15
  import { useMarkAllRead } from '../../../hooks/use_conversations_actions'
9
16
  import { useCanDisplayGroups } from '../../../hooks/use_groups'
10
- import { useNewConversationEntry } from '../../../hooks/use_new_conversation_entry'
11
17
  import { useNewConversationFromFilter } from '../../../hooks/use_new_conversation_from_filter'
12
18
  import { GraphId } from '../../../types/resources/group_resource'
13
19
  import { MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../../utils'
@@ -22,6 +28,7 @@ enum FilterTypes {
22
28
  All = 'All',
23
29
  Groups = 'Groups',
24
30
  Teams = 'Teams',
31
+ DMs = 'DMs',
25
32
  More = 'More',
26
33
  }
27
34
 
@@ -29,8 +36,15 @@ export const ListHeaderComponent = () => {
29
36
  const navigation = useNavigation()
30
37
  const canFilterByTeams = useCanDisplayGroups({ source_app_name: 'Services', source_type: 'Team' })
31
38
  const canFilterByGroups = useCanDisplayGroups({ source_app_name: 'Groups', source_type: 'Group' })
39
+ const directMessagesEnabled = useDirectMessagesEnabled()
40
+ const hasDirectMessages = useHasDirectMessages()
41
+ const canFilterByDMs = directMessagesEnabled && hasDirectMessages
32
42
  const route = useRoute<RouteProp<ConversationsScreenProps['route']>>()
33
- const { chat_group_graph_id, group_source_app_name = '' } = route.params || {}
43
+ const {
44
+ chat_group_graph_id,
45
+ group_source_app_name = '',
46
+ show_direct_messages,
47
+ } = route.params || {}
34
48
  const currentPersonCache = useCurrentPersonCache()
35
49
  const { markAllRead, isPending } = useMarkAllRead()
36
50
  const canCreateConversations = useCanCreateConversations()
@@ -47,10 +61,12 @@ export const ListHeaderComponent = () => {
47
61
  return FilterTypes.Groups
48
62
  } else if (/services/i.test(group_source_app_name)) {
49
63
  return FilterTypes.Teams
64
+ } else if (show_direct_messages) {
65
+ return FilterTypes.DMs
50
66
  }
51
67
 
52
68
  return FilterTypes.All
53
- }, [chat_group_graph_id, group_source_app_name])
69
+ }, [chat_group_graph_id, group_source_app_name, show_direct_messages])
54
70
 
55
71
  const handleNewConversationNavigation = useCallback(() => {
56
72
  if (newConversationFromFilter || entryMode === 'select_type') {
@@ -75,6 +91,10 @@ export const ListHeaderComponent = () => {
75
91
  }
76
92
  }, [navigation, route.params, entryMode, newConversationFromFilter])
77
93
 
94
+ const handleChatSettings = useCallback(() => {
95
+ navigation.navigate('ChatSettings', {})
96
+ }, [navigation])
97
+
78
98
  const handleMoreOptions = useCallback(() => {
79
99
  navigation.navigate('ConversationsMoreActions')
80
100
  }, [navigation])
@@ -83,8 +103,9 @@ export const ListHeaderComponent = () => {
83
103
  navigation.navigate('ConversationFilters', {
84
104
  chat_group_graph_id,
85
105
  group_source_app_name,
106
+ show_direct_messages,
86
107
  })
87
- }, [navigation, chat_group_graph_id, group_source_app_name])
108
+ }, [navigation, chat_group_graph_id, group_source_app_name, show_direct_messages])
88
109
 
89
110
  const handleMarkAllRead = useCallback(() => {
90
111
  currentPersonCache.update({ unreadCount: 0 })
@@ -103,8 +124,8 @@ export const ListHeaderComponent = () => {
103
124
 
104
125
  const hasSomeSourceFilterCapability = canFilterByTeams || canFilterByGroups
105
126
  const hasMultiSourceFilterCapabilities = canFilterByTeams && canFilterByGroups
106
- const shouldShowHeaderFiltersButton =
107
- hasSomeSourceFilterCapability && !hasMultiSourceFilterCapabilities
127
+ const showFilterRow = hasMultiSourceFilterCapabilities || canFilterByDMs
128
+ const shouldShowHeaderFiltersButton = hasSomeSourceFilterCapability && !showFilterRow
108
129
  const moreFiltersButtonA11yLabel = shouldShowHeaderFiltersButton
109
130
  ? 'View filters'
110
131
  : 'View more filters'
@@ -136,6 +157,14 @@ export const ListHeaderComponent = () => {
136
157
  </TextButton>
137
158
  </View>
138
159
  <View style={styles.actionsContainer}>
160
+ {directMessagesEnabled && (
161
+ <ListHeaderActionButton
162
+ name="general.cog"
163
+ onPress={handleChatSettings}
164
+ accessibilityLabel="Chat settings"
165
+ maxFontSizeMultiplier={MAX_FONT_SIZE_MULTIPLIER_LANDMARK}
166
+ />
167
+ )}
139
168
  {canCreateConversations && (
140
169
  <ListHeaderActionButton
141
170
  name="churchCenter.signups"
@@ -156,7 +185,7 @@ export const ListHeaderComponent = () => {
156
185
  {shouldShowHeaderFiltersButton && <ToggleButton {...moreFiltersButtonProps} />}
157
186
  </View>
158
187
  </View>
159
- {hasMultiSourceFilterCapabilities && (
188
+ {showFilterRow && (
160
189
  <ScrollView
161
190
  horizontal
162
191
  showsHorizontalScrollIndicator={false}
@@ -170,36 +199,57 @@ export const ListHeaderComponent = () => {
170
199
  navigation.setParams({
171
200
  chat_group_graph_id: undefined,
172
201
  group_source_app_name: undefined,
202
+ show_direct_messages: undefined,
173
203
  })
174
204
  }
175
205
  accessibilityLabel="Show all conversations"
176
206
  style={styles.filterButton}
177
207
  />
178
- <ToggleButton
179
- title={FilterTypes.Groups}
180
- active={active === FilterTypes.Groups}
181
- onPress={() =>
182
- navigation.setParams({
183
- chat_group_graph_id: undefined,
184
- group_source_app_name: 'Groups',
185
- })
186
- }
187
- accessibilityLabel="Filter to group conversations"
188
- style={styles.filterButton}
189
- />
190
-
191
- <ToggleButton
192
- title={FilterTypes.Teams}
193
- active={active === FilterTypes.Teams}
194
- onPress={() =>
195
- navigation.setParams({
196
- chat_group_graph_id: undefined,
197
- group_source_app_name: 'Services',
198
- })
199
- }
200
- accessibilityLabel="Filter to team conversations"
201
- style={styles.filterButton}
202
- />
208
+ {canFilterByGroups && (
209
+ <ToggleButton
210
+ title={FilterTypes.Groups}
211
+ active={active === FilterTypes.Groups}
212
+ onPress={() =>
213
+ navigation.setParams({
214
+ chat_group_graph_id: undefined,
215
+ group_source_app_name: 'Groups',
216
+ show_direct_messages: undefined,
217
+ })
218
+ }
219
+ accessibilityLabel="Filter to group conversations"
220
+ style={styles.filterButton}
221
+ />
222
+ )}
223
+ {canFilterByTeams && (
224
+ <ToggleButton
225
+ title={FilterTypes.Teams}
226
+ active={active === FilterTypes.Teams}
227
+ onPress={() =>
228
+ navigation.setParams({
229
+ chat_group_graph_id: undefined,
230
+ group_source_app_name: 'Services',
231
+ show_direct_messages: undefined,
232
+ })
233
+ }
234
+ accessibilityLabel="Filter to team conversations"
235
+ style={styles.filterButton}
236
+ />
237
+ )}
238
+ {canFilterByDMs && (
239
+ <ToggleButton
240
+ title={FilterTypes.DMs}
241
+ active={active === FilterTypes.DMs}
242
+ onPress={() =>
243
+ navigation.setParams({
244
+ chat_group_graph_id: undefined,
245
+ group_source_app_name: undefined,
246
+ show_direct_messages: true,
247
+ })
248
+ }
249
+ accessibilityLabel="Filter to direct message conversations"
250
+ style={styles.filterButton}
251
+ />
252
+ )}
203
253
  <ToggleButton {...moreFiltersButtonProps} />
204
254
  </ScrollView>
205
255
  )}
@@ -12,6 +12,7 @@ export type ConversationsScreenProps = StaticScreenProps<{
12
12
  title?: string
13
13
  chat_group_graph_id?: GraphId
14
14
  group_source_app_name?: AppName
15
+ show_direct_messages?: boolean
15
16
  }>
16
17
 
17
18
  export function ConversationsScreen({ route }: ConversationsScreenProps) {
@@ -4,6 +4,7 @@ import { Alert, Linking, StyleSheet, View } from 'react-native'
4
4
  import { Heading, PressableRow, Text, TextInlineButton } from '../components'
5
5
  import { useApiGet, useTheme } from '../hooks'
6
6
  import { useAppName } from '../hooks/use_app_name'
7
+ import { useOrganization } from '../hooks/use_organization'
7
8
  import { ResourceObject } from '../types'
8
9
  import { Clipboard } from '../utils'
9
10
 
@@ -13,34 +14,6 @@ type GetHelpScreenRouteProps = {
13
14
 
14
15
  type GetHelpScreenProps = StaticScreenProps<GetHelpScreenRouteProps>
15
16
 
16
- interface OrganizationResource extends ResourceObject {
17
- id: number
18
- name: string
19
- contactEmail: string
20
- contactPhoneNumber: string
21
- churchCenterChatHelpUrl: string
22
- servicesChatHelpUrl: string
23
- }
24
-
25
- const useOrganization = () => {
26
- const { data: organization } = useApiGet<OrganizationResource>({
27
- url: '/',
28
- data: {
29
- fields: {
30
- Organization: [
31
- 'contact_phone_number',
32
- 'contact_email',
33
- 'name',
34
- 'church_center_chat_help_url',
35
- 'services_chat_help_url',
36
- ],
37
- },
38
- },
39
- })
40
-
41
- return organization
42
- }
43
-
44
17
  interface HelpUrlResource extends ResourceObject {
45
18
  id: number
46
19
  link: string
@@ -67,7 +40,7 @@ export const GetHelpScreen = ({ route }: GetHelpScreenProps) => {
67
40
  const styles = useStyles()
68
41
  const appName = useAppName()
69
42
  const navigation = useNavigation()
70
- const organization = useOrganization()
43
+ const { data: organization } = useOrganization()
71
44
  const contactPresent = organization?.contactEmail || organization?.contactPhoneNumber
72
45
  const helpUrls = useHelpUrls()
73
46
  const appSpecificHelpUrls = useMemo(
@@ -1,3 +1,4 @@
1
+ export * from './settings_screen'
1
2
  export * from './design_system_screen'
2
3
  export * from './conversation_details_screen'
3
4
  export * from './conversation_screen'
@@ -0,0 +1,67 @@
1
+ import { StaticScreenProps } from '@react-navigation/native'
2
+ import React from 'react'
3
+ import { StyleSheet, View } from 'react-native'
4
+ import { Heading, Text } from '../components'
5
+ import { Switch } from '../components/display/switch'
6
+ import { useTheme } from '../hooks'
7
+ import { usePersonSettings } from '../hooks/use_person_settings'
8
+
9
+ export type SettingsScreenProps = StaticScreenProps<{}>
10
+
11
+ export function SettingsScreen({}: SettingsScreenProps) {
12
+ const styles = useStyles()
13
+ const { directMessagesDisabled, setDirectMessagesDisabled, isMutating } = usePersonSettings()
14
+
15
+ return (
16
+ <View style={styles.container}>
17
+ <View style={styles.sectionOuter}>
18
+ <View style={styles.sectionHeader}>
19
+ <Heading variant="h2">Messages</Heading>
20
+ </View>
21
+ <View style={styles.settingRow}>
22
+ <View style={styles.settingRowText}>
23
+ <Text>Allow direct messages</Text>
24
+ <Text variant="tertiary">
25
+ When disabled, you won't be able to participate in direct messages.
26
+ </Text>
27
+ </View>
28
+ <Switch
29
+ value={!directMessagesDisabled}
30
+ onValueChange={enabled => setDirectMessagesDisabled(!enabled)}
31
+ disabled={isMutating}
32
+ />
33
+ </View>
34
+ </View>
35
+ </View>
36
+ )
37
+ }
38
+
39
+ const useStyles = () => {
40
+ const { colors } = useTheme()
41
+ return StyleSheet.create({
42
+ container: {
43
+ flex: 1,
44
+ },
45
+ sectionOuter: {
46
+ paddingLeft: 16,
47
+ },
48
+ sectionHeader: {
49
+ paddingRight: 16,
50
+ paddingTop: 24,
51
+ paddingBottom: 12,
52
+ borderBottomWidth: 1,
53
+ borderBottomColor: colors.borderColorDefaultBase,
54
+ },
55
+ settingRow: {
56
+ flexDirection: 'row',
57
+ alignItems: 'flex-start',
58
+ justifyContent: 'space-between',
59
+ paddingRight: 16,
60
+ paddingVertical: 12,
61
+ },
62
+ settingRowText: {
63
+ flex: 1,
64
+ gap: 8,
65
+ },
66
+ })
67
+ }
@@ -1,4 +1,5 @@
1
1
  import type { CustomMessage } from '@planningcenter/jolt-client/dist/types/JoltConnection'
2
+ import type { ConversationDisabledReason } from '../resources/conversation'
2
3
 
3
4
  type DateString = string
4
5
  interface BaseConversationEventData extends Record<string, unknown> {
@@ -15,6 +16,7 @@ interface BaseConversationEventData extends Record<string, unknown> {
15
16
  latest_read_message_sort_key?: string
16
17
  organization_id: number
17
18
  disabled: boolean
19
+ disabled_reason?: ConversationDisabledReason
18
20
  replies_disabled: boolean
19
21
  subtitle?: string
20
22
  title: string
@@ -4,6 +4,8 @@ import { ConversationMembershipResource } from './conversation_membership'
4
4
  import { GroupResource } from './group_resource'
5
5
  import { MemberAbilityResource } from './member_ability'
6
6
 
7
+ export type ConversationDisabledReason = 'safety_check' | 'direct_messages_disabled'
8
+
7
9
  export interface ConversationResource {
8
10
  type: 'Conversation'
9
11
  id: number
@@ -13,6 +15,7 @@ export interface ConversationResource {
13
15
  createdAt: string
14
16
  deleted?: boolean
15
17
  disabled?: boolean
18
+ disabledReason?: ConversationDisabledReason
16
19
  genderOption?: string | null
17
20
  groups?: GroupResource[]
18
21
  previewAvatarUrls?: string[]
@@ -0,0 +1,8 @@
1
+ import { ResourceObject } from '../api_primitives'
2
+
3
+ export interface DirectMessageAffiliationsResource extends ResourceObject {
4
+ type: 'DirectMessageAffiliations'
5
+ id: string
6
+ groups: Record<string, string>
7
+ teams: Record<string, string>
8
+ }
@@ -0,0 +1,12 @@
1
+ import { ResourceObject } from '../api_primitives'
2
+
3
+ export interface DirectMessageCandidateResource extends ResourceObject {
4
+ type: 'DirectMessageCandidate'
5
+ id: string
6
+ name: string
7
+ avatar: string
8
+ groups: number[]
9
+ teams: number[]
10
+ under_18: boolean
11
+ directMessagesDisabled: boolean
12
+ }
@@ -1,4 +1,6 @@
1
1
  export * from './analytics_metadata'
2
+ export * from './direct_message_affiliations'
3
+ export * from './direct_message_candidate'
2
4
  export * from './conversation'
3
5
  export * from './conversation_membership'
4
6
  export * from './conversation_validate'
@@ -3,5 +3,6 @@ import { ResourceObject } from '../api_primitives'
3
3
  export interface OrganizationResource extends ResourceObject {
4
4
  type: 'Organization'
5
5
  contactEmail?: string
6
+ contactPhoneNumber?: string
6
7
  name?: string
7
8
  }
@@ -21,4 +21,5 @@ export interface CurrentPersonResource extends PersonResource {
21
21
  unreadCount: number
22
22
  pcoChatEnabled: boolean
23
23
  ageQualificationStatus?: AgeQualificationStatus
24
+ directMessagesDisabled: boolean
24
25
  }
@@ -0,0 +1,14 @@
1
+ import { getConversationsRequestArgs } from '../request/conversation'
2
+
3
+ const groupId = 'Groups-Group-1' as const
4
+
5
+ describe('getConversationsRequestArgs', () => {
6
+ it.each([
7
+ ['no args', {}, 'mine_or_not_empty'],
8
+ ['group_source_app_name', { group_source_app_name: 'Groups' }, 'group_source_app_name'],
9
+ ['chat_group_graph_id', { chat_group_graph_id: groupId }, 'group'],
10
+ ['show_direct_messages', { show_direct_messages: true }, 'mine_or_not_empty,direct_message'],
11
+ ])('%s uses filter: %s', (_label, args, expectedFilter) => {
12
+ expect(getConversationsRequestArgs(args).data.filter).toBe(expectedFilter)
13
+ })
14
+ })
@@ -5,18 +5,25 @@ export interface ConversationRequestArgs {
5
5
  gids: string
6
6
  chat_group_graph_id?: GraphId
7
7
  group_source_app_name?: string
8
+ show_direct_messages?: boolean
8
9
  }
9
10
 
10
11
  export const getConversationsRequestArgs = ({
11
12
  gids,
12
13
  chat_group_graph_id,
13
14
  group_source_app_name,
15
+ show_direct_messages,
14
16
  }: Partial<ConversationRequestArgs> = {}): GetRequest => {
15
- const filter = chat_group_graph_id
16
- ? 'group'
17
- : group_source_app_name
18
- ? 'group_source_app_name'
19
- : 'mine_or_not_empty'
17
+ let filter: string
18
+ if (chat_group_graph_id) {
19
+ filter = 'group'
20
+ } else if (show_direct_messages) {
21
+ filter = 'mine_or_not_empty,direct_message'
22
+ } else if (group_source_app_name) {
23
+ filter = 'group_source_app_name'
24
+ } else {
25
+ filter = 'mine_or_not_empty'
26
+ }
20
27
 
21
28
  return {
22
29
  url: '/me/conversations',
@@ -32,6 +39,7 @@ export const getConversationsRequestArgs = ({
32
39
  'created_at',
33
40
  'badges',
34
41
  'disabled',
42
+ 'disabled_reason',
35
43
  'groups',
36
44
  'last_message_author_id',
37
45
  'last_message_author_name',
@@ -0,0 +1,17 @@
1
+ type TimeUnit = 'hours' | 'minutes' | 'seconds'
2
+
3
+ export function toMs(value: number, unit: TimeUnit): number {
4
+ switch (unit) {
5
+ case 'hours':
6
+ return value * 60 * 60 * 1000
7
+ case 'minutes':
8
+ return value * 60 * 1000
9
+ case 'seconds':
10
+ return value * 1000
11
+ }
12
+ }
13
+
14
+ export const FIVE_SECONDS = toMs(5, 'seconds')
15
+ export const FIVE_MINUTES = toMs(5, 'minutes')
16
+ export const THIRTY_MINUTES = toMs(30, 'minutes')
17
+ export const ONE_HOUR = toMs(1, 'hours')