@planningcenter/chat-react-native 4.4.1-qa-1036.2 → 4.4.1-qa-staging.42

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 (113) hide show
  1. package/build/components/conversation/message_list.d.ts.map +1 -1
  2. package/build/components/conversation/message_list.js +155 -123
  3. package/build/components/conversation/message_list.js.map +1 -1
  4. package/build/components/conversations/conversations.d.ts.map +1 -1
  5. package/build/components/conversations/conversations.js +1 -0
  6. package/build/components/conversations/conversations.js.map +1 -1
  7. package/build/components/display/filter_dropdown.d.ts +1 -0
  8. package/build/components/display/filter_dropdown.d.ts.map +1 -1
  9. package/build/components/display/filter_dropdown.js.map +1 -1
  10. package/build/components/display/keyboard_scroll_view.d.ts.map +1 -1
  11. package/build/components/display/keyboard_scroll_view.js +1 -0
  12. package/build/components/display/keyboard_scroll_view.js.map +1 -1
  13. package/build/components/page/page_error_boundary.d.ts +9 -1
  14. package/build/components/page/page_error_boundary.d.ts.map +1 -1
  15. package/build/components/page/page_error_boundary.js +56 -31
  16. package/build/components/page/page_error_boundary.js.map +1 -1
  17. package/build/navigation/index.d.ts.map +1 -1
  18. package/build/navigation/index.js +11 -3
  19. package/build/navigation/index.js.map +1 -1
  20. package/build/navigation/page_error_fallbacks.d.ts +7 -0
  21. package/build/navigation/page_error_fallbacks.d.ts.map +1 -0
  22. package/build/navigation/page_error_fallbacks.js +7 -0
  23. package/build/navigation/page_error_fallbacks.js.map +1 -0
  24. package/build/navigation/screenLayout.d.ts.map +1 -1
  25. package/build/navigation/screenLayout.js +21 -13
  26. package/build/navigation/screenLayout.js.map +1 -1
  27. package/build/screens/age_check/age_check_required_screen.d.ts.map +1 -1
  28. package/build/screens/age_check/age_check_required_screen.js +1 -0
  29. package/build/screens/age_check/age_check_required_screen.js.map +1 -1
  30. package/build/screens/conversation_details_screen.d.ts.map +1 -1
  31. package/build/screens/conversation_details_screen.js +1 -0
  32. package/build/screens/conversation_details_screen.js.map +1 -1
  33. package/build/screens/conversation_new/components/groups_form.js +25 -18
  34. package/build/screens/conversation_new/components/groups_form.js.map +1 -1
  35. package/build/screens/conversation_new/components/services_form.js +51 -40
  36. package/build/screens/conversation_new/components/services_form.js.map +1 -1
  37. package/build/screens/conversation_select_recipients/conversation_new_entry_screen.d.ts.map +1 -1
  38. package/build/screens/conversation_select_recipients/conversation_new_entry_screen.js +1 -0
  39. package/build/screens/conversation_select_recipients/conversation_new_entry_screen.js.map +1 -1
  40. package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.d.ts.map +1 -1
  41. package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.js +332 -291
  42. package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.js.map +1 -1
  43. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.d.ts.map +1 -1
  44. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.js +1 -0
  45. package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.js.map +1 -1
  46. package/build/screens/conversation_select_recipients/conversation_select_teams_i_lead_recipients_screen.d.ts.map +1 -1
  47. package/build/screens/conversation_select_recipients/conversation_select_teams_i_lead_recipients_screen.js +1 -0
  48. package/build/screens/conversation_select_recipients/conversation_select_teams_i_lead_recipients_screen.js.map +1 -1
  49. package/build/screens/conversations/components/filter_dropdown_list_header_component.d.ts.map +1 -1
  50. package/build/screens/conversations/components/filter_dropdown_list_header_component.js +22 -7
  51. package/build/screens/conversations/components/filter_dropdown_list_header_component.js.map +1 -1
  52. package/build/screens/get_help_screen.js +56 -62
  53. package/build/screens/get_help_screen.js.map +1 -1
  54. package/build/screens/group_notification_settings_screen.js +3 -2
  55. package/build/screens/group_notification_settings_screen.js.map +1 -1
  56. package/build/screens/notification_settings_screen.d.ts.map +1 -1
  57. package/build/screens/notification_settings_screen.js +1 -0
  58. package/build/screens/notification_settings_screen.js.map +1 -1
  59. package/build/screens/preferred_app_selection_screen.js +45 -39
  60. package/build/screens/preferred_app_selection_screen.js.map +1 -1
  61. package/build/screens/search/components/search_results_list.d.ts +4 -1
  62. package/build/screens/search/components/search_results_list.d.ts.map +1 -1
  63. package/build/screens/search/components/search_results_list.js +136 -110
  64. package/build/screens/search/components/search_results_list.js.map +1 -1
  65. package/build/screens/search/search_screen.d.ts.map +1 -1
  66. package/build/screens/search/search_screen.js +21 -28
  67. package/build/screens/search/search_screen.js.map +1 -1
  68. package/build/screens/settings_screen.d.ts.map +1 -1
  69. package/build/screens/settings_screen.js +7 -6
  70. package/build/screens/settings_screen.js.map +1 -1
  71. package/build/utils/index.d.ts +1 -0
  72. package/build/utils/index.d.ts.map +1 -1
  73. package/build/utils/index.js +1 -0
  74. package/build/utils/index.js.map +1 -1
  75. package/build/utils/membership_sync_info_text.d.ts +2 -0
  76. package/build/utils/membership_sync_info_text.d.ts.map +1 -0
  77. package/build/utils/membership_sync_info_text.js +4 -0
  78. package/build/utils/membership_sync_info_text.js.map +1 -0
  79. package/package.json +3 -3
  80. package/src/__tests__/navigation/screen_layout.test.tsx +55 -0
  81. package/src/components/conversation/__tests__/message_list.test.tsx +4 -0
  82. package/src/components/conversation/message_list.tsx +6 -0
  83. package/src/components/conversations/conversations.tsx +1 -0
  84. package/src/components/display/filter_dropdown.tsx +1 -0
  85. package/src/components/display/keyboard_scroll_view.tsx +1 -0
  86. package/src/components/page/__tests__/page_error_boundary.test.tsx +33 -0
  87. package/src/components/page/page_error_boundary.tsx +43 -12
  88. package/src/navigation/index.tsx +11 -2
  89. package/src/navigation/page_error_fallbacks.ts +14 -0
  90. package/src/navigation/screenLayout.tsx +6 -3
  91. package/src/screens/age_check/age_check_required_screen.tsx +5 -1
  92. package/src/screens/conversation_details_screen.tsx +1 -0
  93. package/src/screens/conversation_new/components/groups_form.tsx +2 -2
  94. package/src/screens/conversation_new/components/services_form.tsx +2 -2
  95. package/src/screens/conversation_select_recipients/__tests__/conversation_select_direct_message_recipients_screen.test.tsx +100 -0
  96. package/src/screens/conversation_select_recipients/conversation_new_entry_screen.tsx +4 -1
  97. package/src/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.tsx +78 -68
  98. package/src/screens/conversation_select_recipients/conversation_select_group_recipients_screen.tsx +1 -0
  99. package/src/screens/conversation_select_recipients/conversation_select_teams_i_lead_recipients_screen.tsx +1 -0
  100. package/src/screens/conversations/components/__tests__/filter_dropdown_list_header_component.test.tsx +59 -1
  101. package/src/screens/conversations/components/filter_dropdown_list_header_component.tsx +24 -9
  102. package/src/screens/get_help_screen.tsx +4 -4
  103. package/src/screens/group_notification_settings_screen.tsx +3 -3
  104. package/src/screens/notification_settings_screen.tsx +1 -0
  105. package/src/screens/preferred_app_selection_screen.tsx +4 -4
  106. package/src/screens/search/__tests__/search_screen.test.tsx +5 -7
  107. package/src/screens/search/components/__tests__/search_results_list.test.tsx +6 -2
  108. package/src/screens/search/components/search_results_list.tsx +34 -13
  109. package/src/screens/search/search_screen.tsx +8 -18
  110. package/src/screens/settings_screen.tsx +25 -25
  111. package/src/utils/__tests__/membership_sync_info_text.test.ts +15 -0
  112. package/src/utils/index.ts +1 -0
  113. package/src/utils/membership_sync_info_text.ts +3 -0
@@ -49,9 +49,13 @@ const messageResult = (id: string): MessageSearchResultResource => ({
49
49
  },
50
50
  })
51
51
 
52
+ const slots = { header: <></>, prompt: <></> }
53
+
52
54
  const renderList = (state: Partial<SearchState>, onSettled = jest.fn()) => {
53
55
  mockUseSearchResults.mockReturnValue(searchState(state))
54
- const list = () => <SearchResultsList term="potluck" onSelect={jest.fn()} onSettled={onSettled} />
56
+ const list = () => (
57
+ <SearchResultsList term="potluck" onSelect={jest.fn()} onSettled={onSettled} {...slots} />
58
+ )
55
59
  const view = render(list())
56
60
  const rerenderWith = (next: Partial<SearchState>) => {
57
61
  mockUseSearchResults.mockReturnValue(searchState(next))
@@ -130,7 +134,7 @@ describe('SearchResultsList', () => {
130
134
  const results = [conversationResult('1'), messageResult('1'), messageResult('2')]
131
135
  mockUseSearchResults.mockReturnValue(searchState({ results }))
132
136
  const view = render(
133
- <SearchResultsList term="potluck" onSelect={onSelect} onSettled={jest.fn()} />
137
+ <SearchResultsList term="potluck" onSelect={onSelect} onSettled={jest.fn()} {...slots} />
134
138
  )
135
139
 
136
140
  fireEvent.press(view.getByLabelText(/^Message 2/))
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useRef } from 'react'
1
+ import React, { ReactElement, useEffect, useRef } from 'react'
2
2
  import { FlatList, StyleSheet, View } from 'react-native'
3
3
  import { Banner, Spinner, Text, TextButton } from '../../../components'
4
4
  import { useSearchResults } from '../../../hooks/use_search_results'
@@ -23,9 +23,17 @@ interface SearchResultsListProps {
23
23
  term: string
24
24
  onSelect: (result: SearchResultResource, position: number) => void
25
25
  onSettled: (term: string, counts: SearchResultCounts) => void
26
+ header: ReactElement
27
+ prompt: ReactElement
26
28
  }
27
29
 
28
- export function SearchResultsList({ term, onSelect, onSettled }: SearchResultsListProps) {
30
+ export function SearchResultsList({
31
+ term,
32
+ onSelect,
33
+ onSettled,
34
+ header,
35
+ prompt,
36
+ }: SearchResultsListProps) {
29
37
  const {
30
38
  results,
31
39
  failedTypes,
@@ -36,9 +44,10 @@ export function SearchResultsList({ term, onSelect, onSettled }: SearchResultsLi
36
44
  hasNextPage,
37
45
  isFetchingNextPage,
38
46
  } = useSearchResults(term)
39
- const conversationResults = results.filter(isConversationResult)
40
- const messageResults = results.filter(isMessageResult)
41
- const settled = !isPending && !isError
47
+ const searching = term.trim().length > 0
48
+ const conversationResults = searching ? results.filter(isConversationResult) : []
49
+ const messageResults = searching ? results.filter(isMessageResult) : []
50
+ const settled = searching && !isPending && !isError
42
51
 
43
52
  const settledTermRef = useRef<string | undefined>(undefined)
44
53
 
@@ -56,6 +65,7 @@ export function SearchResultsList({ term, onSelect, onSettled }: SearchResultsLi
56
65
  <FlatList
57
66
  data={messageResults}
58
67
  keyExtractor={item => item.id}
68
+ contentInsetAdjustmentBehavior="automatic"
59
69
  keyboardShouldPersistTaps="handled"
60
70
  keyboardDismissMode="on-drag"
61
71
  contentContainerStyle={styles.content}
@@ -64,20 +74,27 @@ export function SearchResultsList({ term, onSelect, onSettled }: SearchResultsLi
64
74
  )}
65
75
  ListHeaderComponent={
66
76
  <>
77
+ {header}
67
78
  {conversationResults.length > 0 && (
68
79
  <ConversationResults results={conversationResults} onSelect={onSelect} />
69
80
  )}
70
- {failedTypes.includes('conversation') && <SectionFailure type="conversation" />}
81
+ {searching && failedTypes.includes('conversation') && (
82
+ <SectionFailure type="conversation" />
83
+ )}
71
84
  {messageResults.length > 0 && <ResultsSection title="Messages" />}
72
85
  </>
73
86
  }
74
87
  ListEmptyComponent={
75
- <ListEmpty
76
- term={term}
77
- isError={isError}
78
- isPending={isPending}
79
- noResults={results.length === 0 && failedTypes.length === 0}
80
- />
88
+ searching ? (
89
+ <ListEmpty
90
+ term={term}
91
+ isError={isError}
92
+ isPending={isPending}
93
+ noResults={results.length === 0 && failedTypes.length === 0}
94
+ />
95
+ ) : (
96
+ <View style={styles.prompt}>{prompt}</View>
97
+ )
81
98
  }
82
99
  ListFooterComponent={
83
100
  <>
@@ -91,7 +108,7 @@ export function SearchResultsList({ term, onSelect, onSettled }: SearchResultsLi
91
108
  Try again
92
109
  </TextButton>
93
110
  )}
94
- {failedTypes.includes('message') && <SectionFailure type="message" />}
111
+ {searching && failedTypes.includes('message') && <SectionFailure type="message" />}
95
112
  </>
96
113
  }
97
114
  onEndReached={() => {
@@ -149,6 +166,10 @@ const styles = StyleSheet.create({
149
166
  content: {
150
167
  flexGrow: 1,
151
168
  },
169
+ prompt: {
170
+ flexGrow: 1,
171
+ justifyContent: 'center',
172
+ },
152
173
  banner: {
153
174
  margin: 16,
154
175
  },
@@ -4,7 +4,7 @@ import {
4
4
  NativeStackScreenProps,
5
5
  } from '@react-navigation/native-stack'
6
6
  import React, { useRef, useState } from 'react'
7
- import { Keyboard, ScrollView, StyleSheet, View } from 'react-native'
7
+ import { Keyboard, StyleSheet, View } from 'react-native'
8
8
  import { KeyboardView } from '../../components'
9
9
  import {
10
10
  composeOptions,
@@ -64,19 +64,13 @@ export function SearchScreen() {
64
64
  return (
65
65
  <KeyboardView>
66
66
  <View style={styles.container} testID="search-screen">
67
- <SearchField term={term} onChange={setTerm} />
68
- {debouncedTerm.length > 0 ? (
69
- <SearchResultsList
70
- key={debouncedTerm}
71
- term={debouncedTerm}
72
- onSelect={openResult}
73
- onSettled={publishSearch}
74
- />
75
- ) : (
76
- <ScrollView contentContainerStyle={styles.prompt} keyboardShouldPersistTaps="handled">
77
- <SearchPromptBlankState />
78
- </ScrollView>
79
- )}
67
+ <SearchResultsList
68
+ term={debouncedTerm}
69
+ onSelect={openResult}
70
+ onSettled={publishSearch}
71
+ header={<SearchField term={term} onChange={setTerm} />}
72
+ prompt={<SearchPromptBlankState />}
73
+ />
80
74
  </View>
81
75
  </KeyboardView>
82
76
  )
@@ -86,8 +80,4 @@ const styles = StyleSheet.create({
86
80
  container: {
87
81
  flex: 1,
88
82
  },
89
- prompt: {
90
- flexGrow: 1,
91
- justifyContent: 'center',
92
- },
93
83
  })
@@ -1,7 +1,7 @@
1
1
  import { PlatformPressable } from '@react-navigation/elements'
2
2
  import { StaticScreenProps, useNavigation } from '@react-navigation/native'
3
3
  import React, { useCallback } from 'react'
4
- import { Platform, StyleSheet, View } from 'react-native'
4
+ import { Platform, ScrollView, StyleSheet, View } from 'react-native'
5
5
  import { useSafeAreaInsets } from 'react-native-safe-area-context'
6
6
  import { Heading, Icon, Text, VersionFooter } from '../components'
7
7
  import { Switch } from '../components/display/switch'
@@ -28,29 +28,31 @@ export function SettingsScreen({}: SettingsScreenProps) {
28
28
 
29
29
  return (
30
30
  <View style={styles.container}>
31
- <View style={styles.sectionOuter}>
32
- <View style={styles.sectionHeader}>
33
- <Heading variant="h2">Messages</Heading>
34
- </View>
35
- {directMessagesEligible && (
36
- <View style={styles.settingRow}>
37
- <View style={styles.settingRowText}>
38
- <Text>Allow direct messages</Text>
39
- <Text variant="tertiary">
40
- When off, you can't be added to new direct messages, and any you're already in will
41
- be turned off.
42
- </Text>
43
- </View>
44
- <Switch
45
- value={!directMessagesDisabled}
46
- onValueChange={enabled => setDirectMessagesDisabled(!enabled)}
47
- disabled={isMutating}
48
- />
31
+ <ScrollView contentInsetAdjustmentBehavior="automatic">
32
+ <View style={styles.sectionOuter}>
33
+ <View style={styles.sectionHeader}>
34
+ <Heading variant="h2">Messages</Heading>
49
35
  </View>
50
- )}
51
- <NavRow label="Notification settings" onPress={handleNotificationSettings} />
52
- {appName !== 'services' && <NavRow label="Get help" onPress={handleGetHelp} />}
53
- </View>
36
+ {directMessagesEligible && (
37
+ <View style={styles.settingRow}>
38
+ <View style={styles.settingRowText}>
39
+ <Text>Allow direct messages</Text>
40
+ <Text variant="tertiary">
41
+ When off, you can't be added to new direct messages, and any you're already in
42
+ will be turned off.
43
+ </Text>
44
+ </View>
45
+ <Switch
46
+ value={!directMessagesDisabled}
47
+ onValueChange={enabled => setDirectMessagesDisabled(!enabled)}
48
+ disabled={isMutating}
49
+ />
50
+ </View>
51
+ )}
52
+ <NavRow label="Notification settings" onPress={handleNotificationSettings} />
53
+ {appName !== 'services' && <NavRow label="Get help" onPress={handleGetHelp} />}
54
+ </View>
55
+ </ScrollView>
54
56
  <View style={styles.footer}>
55
57
  <VersionFooter />
56
58
  </View>
@@ -90,8 +92,6 @@ const useStyles = () => {
90
92
  flex: 1,
91
93
  },
92
94
  footer: {
93
- flex: 1,
94
- justifyContent: 'flex-end',
95
95
  paddingBottom: Math.max(insets.bottom, 8),
96
96
  },
97
97
  sectionOuter: {
@@ -0,0 +1,15 @@
1
+ import { membershipSyncInfoText } from '../membership_sync_info_text'
2
+
3
+ describe('membershipSyncInfoText', () => {
4
+ it('explains membership sync and history visibility for a group', () => {
5
+ expect(membershipSyncInfoText('the group')).toBe(
6
+ 'This conversation will stay in sync with the group. Members will automatically be added or removed, and new members will see the history.'
7
+ )
8
+ })
9
+
10
+ it('explains membership sync and history visibility for teams', () => {
11
+ expect(membershipSyncInfoText('the teams')).toBe(
12
+ 'This conversation will stay in sync with the teams. Members will automatically be added or removed, and new members will see the history.'
13
+ )
14
+ })
15
+ })
@@ -8,6 +8,7 @@ export * from './convert_attachments_for_create'
8
8
  export * from './destructure_chat_group_graph_id'
9
9
  export * from './host_bridge'
10
10
  export * from './liquid_glass'
11
+ export * from './membership_sync_info_text'
11
12
  export * from './native_adapters'
12
13
  export * from './pluralize'
13
14
  export * from './conversation_safety_constants'
@@ -0,0 +1,3 @@
1
+ export function membershipSyncInfoText(source: string): string {
2
+ return `This conversation will stay in sync with ${source}. Members will automatically be added or removed, and new members will see the history.`
3
+ }