@planningcenter/chat-react-native 4.4.1-qa-staging.40 → 4.4.1-qa-1036.2
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.
- package/build/components/conversation/message_list.d.ts.map +1 -1
- package/build/components/conversation/message_list.js +123 -155
- package/build/components/conversation/message_list.js.map +1 -1
- package/build/components/conversations/conversations.d.ts.map +1 -1
- package/build/components/conversations/conversations.js +0 -1
- package/build/components/conversations/conversations.js.map +1 -1
- package/build/components/display/filter_dropdown.d.ts +0 -1
- package/build/components/display/filter_dropdown.d.ts.map +1 -1
- package/build/components/display/filter_dropdown.js.map +1 -1
- package/build/components/display/keyboard_scroll_view.d.ts.map +1 -1
- package/build/components/display/keyboard_scroll_view.js +0 -1
- package/build/components/display/keyboard_scroll_view.js.map +1 -1
- package/build/components/page/page_error_boundary.d.ts +1 -9
- package/build/components/page/page_error_boundary.d.ts.map +1 -1
- package/build/components/page/page_error_boundary.js +31 -56
- package/build/components/page/page_error_boundary.js.map +1 -1
- package/build/navigation/index.d.ts.map +1 -1
- package/build/navigation/index.js +3 -11
- package/build/navigation/index.js.map +1 -1
- package/build/navigation/screenLayout.d.ts.map +1 -1
- package/build/navigation/screenLayout.js +6 -10
- package/build/navigation/screenLayout.js.map +1 -1
- package/build/screens/age_check/age_check_required_screen.d.ts.map +1 -1
- package/build/screens/age_check/age_check_required_screen.js +0 -1
- package/build/screens/age_check/age_check_required_screen.js.map +1 -1
- package/build/screens/conversation_details_screen.d.ts.map +1 -1
- package/build/screens/conversation_details_screen.js +0 -1
- package/build/screens/conversation_details_screen.js.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_new_entry_screen.d.ts.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_new_entry_screen.js +0 -1
- package/build/screens/conversation_select_recipients/conversation_new_entry_screen.js.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.d.ts.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.js +291 -332
- package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.js.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.d.ts.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.js +0 -1
- package/build/screens/conversation_select_recipients/conversation_select_group_recipients_screen.js.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_select_teams_i_lead_recipients_screen.d.ts.map +1 -1
- package/build/screens/conversation_select_recipients/conversation_select_teams_i_lead_recipients_screen.js +0 -1
- package/build/screens/conversation_select_recipients/conversation_select_teams_i_lead_recipients_screen.js.map +1 -1
- package/build/screens/conversations/components/filter_dropdown_list_header_component.d.ts.map +1 -1
- package/build/screens/conversations/components/filter_dropdown_list_header_component.js +7 -22
- package/build/screens/conversations/components/filter_dropdown_list_header_component.js.map +1 -1
- package/build/screens/get_help_screen.js +62 -56
- package/build/screens/get_help_screen.js.map +1 -1
- package/build/screens/group_notification_settings_screen.js +2 -3
- package/build/screens/group_notification_settings_screen.js.map +1 -1
- package/build/screens/notification_settings_screen.d.ts.map +1 -1
- package/build/screens/notification_settings_screen.js +0 -1
- package/build/screens/notification_settings_screen.js.map +1 -1
- package/build/screens/preferred_app_selection_screen.js +39 -45
- package/build/screens/preferred_app_selection_screen.js.map +1 -1
- package/build/screens/search/components/search_results_list.d.ts +1 -4
- package/build/screens/search/components/search_results_list.d.ts.map +1 -1
- package/build/screens/search/components/search_results_list.js +110 -136
- package/build/screens/search/components/search_results_list.js.map +1 -1
- package/build/screens/search/search_screen.d.ts.map +1 -1
- package/build/screens/search/search_screen.js +28 -21
- package/build/screens/search/search_screen.js.map +1 -1
- package/build/screens/settings_screen.d.ts.map +1 -1
- package/build/screens/settings_screen.js +6 -7
- package/build/screens/settings_screen.js.map +1 -1
- package/package.json +3 -3
- package/src/components/conversation/__tests__/message_list.test.tsx +0 -4
- package/src/components/conversation/message_list.tsx +0 -6
- package/src/components/conversations/conversations.tsx +0 -1
- package/src/components/display/filter_dropdown.tsx +0 -1
- package/src/components/display/keyboard_scroll_view.tsx +0 -1
- package/src/components/page/__tests__/page_error_boundary.test.tsx +0 -33
- package/src/components/page/page_error_boundary.tsx +12 -43
- package/src/navigation/index.tsx +2 -11
- package/src/navigation/screenLayout.tsx +1 -3
- package/src/screens/age_check/age_check_required_screen.tsx +1 -5
- package/src/screens/conversation_details_screen.tsx +0 -1
- package/src/screens/conversation_select_recipients/conversation_new_entry_screen.tsx +1 -4
- package/src/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.tsx +68 -78
- package/src/screens/conversation_select_recipients/conversation_select_group_recipients_screen.tsx +0 -1
- package/src/screens/conversation_select_recipients/conversation_select_teams_i_lead_recipients_screen.tsx +0 -1
- package/src/screens/conversations/components/__tests__/filter_dropdown_list_header_component.test.tsx +1 -59
- package/src/screens/conversations/components/filter_dropdown_list_header_component.tsx +9 -24
- package/src/screens/get_help_screen.tsx +4 -4
- package/src/screens/group_notification_settings_screen.tsx +3 -3
- package/src/screens/notification_settings_screen.tsx +0 -1
- package/src/screens/preferred_app_selection_screen.tsx +4 -4
- package/src/screens/search/__tests__/search_screen.test.tsx +7 -5
- package/src/screens/search/components/__tests__/search_results_list.test.tsx +2 -6
- package/src/screens/search/components/search_results_list.tsx +13 -34
- package/src/screens/search/search_screen.tsx +18 -8
- package/src/screens/settings_screen.tsx +25 -25
- package/build/navigation/page_error_fallbacks.d.ts +0 -7
- package/build/navigation/page_error_fallbacks.d.ts.map +0 -1
- package/build/navigation/page_error_fallbacks.js +0 -7
- package/build/navigation/page_error_fallbacks.js.map +0 -1
- package/src/navigation/page_error_fallbacks.ts +0 -14
- package/src/screens/conversation_select_recipients/__tests__/conversation_select_direct_message_recipients_screen.test.tsx +0 -100
package/src/screens/conversation_select_recipients/conversation_select_group_recipients_screen.tsx
CHANGED
|
@@ -60,7 +60,6 @@ export const ConversationSelectGroupRecipientsScreen = ({
|
|
|
60
60
|
|
|
61
61
|
return (
|
|
62
62
|
<SectionList<GroupsGroupResource, GroupsSection>
|
|
63
|
-
contentInsetAdjustmentBehavior="automatic"
|
|
64
63
|
sections={sections}
|
|
65
64
|
keyExtractor={item => item.id.toString()}
|
|
66
65
|
stickySectionHeadersEnabled={false}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fireEvent, render, screen } from '@testing-library/react-native'
|
|
2
2
|
import React from 'react'
|
|
3
|
-
import { Pressable,
|
|
3
|
+
import { Pressable, Text } from 'react-native'
|
|
4
4
|
import {
|
|
5
5
|
AudioAdapter,
|
|
6
6
|
ChatAdapters,
|
|
@@ -115,25 +115,6 @@ const setRouteParams = (params: Record<string, unknown>) => {
|
|
|
115
115
|
const menuItemNames = () =>
|
|
116
116
|
screen.getAllByRole('menuitem').map(item => item.props.accessibilityLabel)
|
|
117
117
|
|
|
118
|
-
const ROW_WIDTH = 360
|
|
119
|
-
const ROW_CONTENT_WIDTH = ROW_WIDTH - 16 * 2
|
|
120
|
-
const HEADING_ROW_GAP = 12
|
|
121
|
-
const WIDEST_LABEL_WIDTH = 150
|
|
122
|
-
|
|
123
|
-
const layOut = (testID: string, width: number) =>
|
|
124
|
-
fireEvent(screen.getByTestId(testID, { includeHiddenElements: true }), 'layout', {
|
|
125
|
-
nativeEvent: { layout: { width } },
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
const layOutHeader = ({ actionsWidth }: { actionsWidth: number }) => {
|
|
129
|
-
layOut('conversations-filter-heading-row', ROW_WIDTH)
|
|
130
|
-
layOut('conversations-filter-widest-label', WIDEST_LABEL_WIDTH)
|
|
131
|
-
layOut('conversations-filter-heading-actions', actionsWidth)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const triggerMaxWidth = (): number =>
|
|
135
|
-
StyleSheet.flatten(screen.getByRole('button', { name: 'All conversations' }).props.style).maxWidth
|
|
136
|
-
|
|
137
118
|
describe('FilterDropdownListHeaderComponent', () => {
|
|
138
119
|
beforeEach(() => {
|
|
139
120
|
mockNavigate.mockClear()
|
|
@@ -305,45 +286,6 @@ describe('FilterDropdownListHeaderComponent', () => {
|
|
|
305
286
|
)
|
|
306
287
|
})
|
|
307
288
|
|
|
308
|
-
it('caps the trigger short of the room beside the actions so a full label never wraps them', () => {
|
|
309
|
-
render(<FilterDropdownListHeaderComponent />)
|
|
310
|
-
|
|
311
|
-
layOutHeader({ actionsWidth: 120.4 })
|
|
312
|
-
|
|
313
|
-
expect(triggerMaxWidth()).toBeGreaterThanOrEqual(WIDEST_LABEL_WIDTH)
|
|
314
|
-
expect(triggerMaxWidth() + HEADING_ROW_GAP + 120.4).toBeLessThan(ROW_CONTENT_WIDTH)
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
it('holds the cap when the actions remeasure by less than a point', () => {
|
|
318
|
-
render(<FilterDropdownListHeaderComponent />)
|
|
319
|
-
|
|
320
|
-
layOutHeader({ actionsWidth: 120.4 })
|
|
321
|
-
const capBefore = triggerMaxWidth()
|
|
322
|
-
|
|
323
|
-
layOut('conversations-filter-heading-actions', 120.9)
|
|
324
|
-
|
|
325
|
-
expect(triggerMaxWidth()).toBe(capBefore)
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
it('recomputes the cap when the actions grow by a button', () => {
|
|
329
|
-
render(<FilterDropdownListHeaderComponent />)
|
|
330
|
-
|
|
331
|
-
layOutHeader({ actionsWidth: 120.4 })
|
|
332
|
-
const capBefore = triggerMaxWidth()
|
|
333
|
-
|
|
334
|
-
layOut('conversations-filter-heading-actions', 160)
|
|
335
|
-
|
|
336
|
-
expect(triggerMaxWidth()).toBeLessThan(capBefore)
|
|
337
|
-
})
|
|
338
|
-
|
|
339
|
-
it('caps the trigger to the row once All conversations no longer fits beside the actions', () => {
|
|
340
|
-
render(<FilterDropdownListHeaderComponent />)
|
|
341
|
-
|
|
342
|
-
layOutHeader({ actionsWidth: 200 })
|
|
343
|
-
|
|
344
|
-
expect(triggerMaxWidth()).toBe(ROW_CONTENT_WIDTH)
|
|
345
|
-
})
|
|
346
|
-
|
|
347
289
|
it('shows the search button only when search is enabled', () => {
|
|
348
290
|
mockSearchEnabled.mockReturnValue(false)
|
|
349
291
|
const view = render(<FilterDropdownListHeaderComponent />)
|
|
@@ -30,8 +30,6 @@ import { ListHeaderActionButton } from './list_header_action_button'
|
|
|
30
30
|
|
|
31
31
|
const ROW_PADDING_HORIZONTAL = 16
|
|
32
32
|
const HEADING_ROW_GAP = 12
|
|
33
|
-
const TRIGGER_CAP_SLACK = 2
|
|
34
|
-
const LAYOUT_JITTER = 1
|
|
35
33
|
const ALL_CONVERSATIONS_LABEL = 'All conversations'
|
|
36
34
|
const ARCHIVED_LABEL = 'Archived'
|
|
37
35
|
|
|
@@ -44,9 +42,6 @@ enum FilterTypes {
|
|
|
44
42
|
More = 'More',
|
|
45
43
|
}
|
|
46
44
|
|
|
47
|
-
const holdSubPointJitter = (previous: number | undefined, next: number) =>
|
|
48
|
-
previous !== undefined && Math.abs(next - previous) < LAYOUT_JITTER ? previous : next
|
|
49
|
-
|
|
50
45
|
const FILTER_PARAMS: Record<Exclude<FilterTypes, FilterTypes.More>, ConversationFiltersParams> = {
|
|
51
46
|
[FilterTypes.All]: {},
|
|
52
47
|
[FilterTypes.Groups]: { group_source_app_name: 'Groups' },
|
|
@@ -222,14 +217,14 @@ export const FilterDropdownListHeaderComponent = () => {
|
|
|
222
217
|
const [rowWidth, setRowWidth] = useState<number>()
|
|
223
218
|
const [actionsWidth, setActionsWidth] = useState<number>()
|
|
224
219
|
const [widestFixedLabelWidth, setWidestFixedLabelWidth] = useState<number>()
|
|
225
|
-
const handleRowLayout = useCallback((
|
|
226
|
-
setRowWidth(
|
|
220
|
+
const handleRowLayout = useCallback((event: LayoutChangeEvent) => {
|
|
221
|
+
setRowWidth(event.nativeEvent.layout.width)
|
|
227
222
|
}, [])
|
|
228
|
-
const handleActionsLayout = useCallback((
|
|
229
|
-
setActionsWidth(
|
|
223
|
+
const handleActionsLayout = useCallback((event: LayoutChangeEvent) => {
|
|
224
|
+
setActionsWidth(event.nativeEvent.layout.width)
|
|
230
225
|
}, [])
|
|
231
|
-
const handleWidestFixedLabelLayout = useCallback((
|
|
232
|
-
setWidestFixedLabelWidth(
|
|
226
|
+
const handleWidestFixedLabelLayout = useCallback((event: LayoutChangeEvent) => {
|
|
227
|
+
setWidestFixedLabelWidth(event.nativeEvent.layout.width)
|
|
233
228
|
}, [])
|
|
234
229
|
const triggerMaxWidth = useMemo(() => {
|
|
235
230
|
if (rowWidth === undefined) return undefined
|
|
@@ -237,8 +232,7 @@ export const FilterDropdownListHeaderComponent = () => {
|
|
|
237
232
|
const rowContentWidth = rowWidth - ROW_PADDING_HORIZONTAL * 2
|
|
238
233
|
if (actionsWidth === undefined || widestFixedLabelWidth === undefined) return rowContentWidth
|
|
239
234
|
|
|
240
|
-
const roomBesideActions =
|
|
241
|
-
Math.floor(rowContentWidth - actionsWidth - HEADING_ROW_GAP) - TRIGGER_CAP_SLACK
|
|
235
|
+
const roomBesideActions = rowContentWidth - actionsWidth - HEADING_ROW_GAP
|
|
242
236
|
return roomBesideActions >= widestFixedLabelWidth ? roomBesideActions : rowContentWidth
|
|
243
237
|
}, [rowWidth, actionsWidth, widestFixedLabelWidth])
|
|
244
238
|
|
|
@@ -248,16 +242,11 @@ export const FilterDropdownListHeaderComponent = () => {
|
|
|
248
242
|
<FilterDropdownTrigger
|
|
249
243
|
label={ALL_CONVERSATIONS_LABEL}
|
|
250
244
|
onLayout={handleWidestFixedLabelLayout}
|
|
251
|
-
testID="conversations-filter-widest-label"
|
|
252
245
|
accessibilityElementsHidden
|
|
253
246
|
importantForAccessibility="no-hide-descendants"
|
|
254
247
|
/>
|
|
255
248
|
</View>
|
|
256
|
-
<View
|
|
257
|
-
style={styles.headingRow}
|
|
258
|
-
onLayout={handleRowLayout}
|
|
259
|
-
testID="conversations-filter-heading-row"
|
|
260
|
-
>
|
|
249
|
+
<View style={styles.headingRow} onLayout={handleRowLayout}>
|
|
261
250
|
<View style={styles.titleContainer}>
|
|
262
251
|
<FilterDropdown
|
|
263
252
|
options={options}
|
|
@@ -269,11 +258,7 @@ export const FilterDropdownListHeaderComponent = () => {
|
|
|
269
258
|
maxWidth={triggerMaxWidth}
|
|
270
259
|
/>
|
|
271
260
|
</View>
|
|
272
|
-
<View
|
|
273
|
-
style={styles.actionsContainer}
|
|
274
|
-
onLayout={handleActionsLayout}
|
|
275
|
-
testID="conversations-filter-heading-actions"
|
|
276
|
-
>
|
|
261
|
+
<View style={styles.actionsContainer} onLayout={handleActionsLayout}>
|
|
277
262
|
<ListHeaderActionButton
|
|
278
263
|
name="general.cog"
|
|
279
264
|
onPress={handleChatSettings}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { StaticScreenProps, useNavigation } from '@react-navigation/native'
|
|
2
2
|
import { useCallback, useMemo } from 'react'
|
|
3
|
-
import { Alert, Linking,
|
|
3
|
+
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'
|
|
@@ -56,7 +56,7 @@ export const GetHelpScreen = ({ route }: GetHelpScreenProps) => {
|
|
|
56
56
|
}, [navigation])
|
|
57
57
|
|
|
58
58
|
return (
|
|
59
|
-
<
|
|
59
|
+
<View style={[styles.container]}>
|
|
60
60
|
{appSpecificHelpUrls.length > 0 && (
|
|
61
61
|
<Heading variant="h2" style={[styles.heading, styles.headingBottomBorder]}>
|
|
62
62
|
How-to articles
|
|
@@ -90,7 +90,7 @@ export const GetHelpScreen = ({ route }: GetHelpScreenProps) => {
|
|
|
90
90
|
to the development team.
|
|
91
91
|
</Text>
|
|
92
92
|
</View>
|
|
93
|
-
</
|
|
93
|
+
</View>
|
|
94
94
|
)
|
|
95
95
|
}
|
|
96
96
|
|
|
@@ -145,7 +145,7 @@ const useStyles = () => {
|
|
|
145
145
|
|
|
146
146
|
return StyleSheet.create({
|
|
147
147
|
container: {
|
|
148
|
-
|
|
148
|
+
flex: 1,
|
|
149
149
|
},
|
|
150
150
|
text: {
|
|
151
151
|
paddingVertical: 4,
|
|
@@ -2,7 +2,7 @@ import { PlatformPressable } from '@react-navigation/elements'
|
|
|
2
2
|
import { StaticScreenProps, useNavigation } from '@react-navigation/native'
|
|
3
3
|
import type { NativeStackNavigationProp } from '@react-navigation/native-stack'
|
|
4
4
|
import React, { useEffect } from 'react'
|
|
5
|
-
import { Platform,
|
|
5
|
+
import { Platform, StyleSheet, View } from 'react-native'
|
|
6
6
|
import { Heading, Icon, Text } from '../components'
|
|
7
7
|
import { useTheme } from '../hooks'
|
|
8
8
|
import { platformFontWeightBold } from '../utils/styles'
|
|
@@ -38,7 +38,7 @@ export function GroupNotificationSettingsScreen({ route }: GroupNotificationSett
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
return (
|
|
41
|
-
<
|
|
41
|
+
<View style={styles.container}>
|
|
42
42
|
<View style={styles.sectionOuter}>
|
|
43
43
|
<View style={styles.sectionInner}>
|
|
44
44
|
<Heading variant="h2" style={styles.sectionHeading}>
|
|
@@ -76,7 +76,7 @@ export function GroupNotificationSettingsScreen({ route }: GroupNotificationSett
|
|
|
76
76
|
)}
|
|
77
77
|
</View>
|
|
78
78
|
</PlatformPressable>
|
|
79
|
-
</
|
|
79
|
+
</View>
|
|
80
80
|
)
|
|
81
81
|
}
|
|
82
82
|
|
|
@@ -123,7 +123,6 @@ export function NotificationSettingsScreen({}: NotificationSettingsScreenProps)
|
|
|
123
123
|
return (
|
|
124
124
|
<View style={styles.listContainer}>
|
|
125
125
|
<FlatList
|
|
126
|
-
contentInsetAdjustmentBehavior="automatic"
|
|
127
126
|
data={listData as SectionListData}
|
|
128
127
|
contentContainerStyle={styles.contentContainer}
|
|
129
128
|
renderItem={({ item, index }) => {
|
|
@@ -2,7 +2,7 @@ import { PlatformPressable } from '@react-navigation/elements'
|
|
|
2
2
|
import { StaticScreenProps } from '@react-navigation/native'
|
|
3
3
|
import { useMutation } from '@tanstack/react-query'
|
|
4
4
|
import React, { type PropsWithChildren } from 'react'
|
|
5
|
-
import { Image,
|
|
5
|
+
import { Image, StyleSheet, View, type ViewStyle } from 'react-native'
|
|
6
6
|
import { Heading, Icon, Text } from '../components'
|
|
7
7
|
import { useApiClient, useTheme } from '../hooks'
|
|
8
8
|
import { useAppName } from '../hooks/use_app_name'
|
|
@@ -45,7 +45,7 @@ export function PreferredAppSelectionScreen({ route }: PreferredAppSelectionScre
|
|
|
45
45
|
const sectionTitle = chatType ? chatTypeLabel(chatType.title) : undefined
|
|
46
46
|
|
|
47
47
|
return (
|
|
48
|
-
<
|
|
48
|
+
<View style={styles.container}>
|
|
49
49
|
<View style={styles.section}>
|
|
50
50
|
<Heading variant="h2" style={styles.sectionHeading}>
|
|
51
51
|
{sectionTitle}
|
|
@@ -64,7 +64,7 @@ export function PreferredAppSelectionScreen({ route }: PreferredAppSelectionScre
|
|
|
64
64
|
</PressableRow>
|
|
65
65
|
))}
|
|
66
66
|
</View>
|
|
67
|
-
</
|
|
67
|
+
</View>
|
|
68
68
|
)
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -118,7 +118,7 @@ const PressableRow = ({
|
|
|
118
118
|
|
|
119
119
|
const styles = StyleSheet.create({
|
|
120
120
|
container: {
|
|
121
|
-
|
|
121
|
+
flex: 1,
|
|
122
122
|
},
|
|
123
123
|
section: {
|
|
124
124
|
paddingTop: 24,
|
|
@@ -106,13 +106,12 @@ describe('SearchScreen', () => {
|
|
|
106
106
|
fireEvent.changeText(input, ' budget ')
|
|
107
107
|
|
|
108
108
|
expect(view.getByText('Search chat')).toBeTruthy()
|
|
109
|
-
|
|
110
|
-
new Set(mockUseSearchResults.mock.calls.map(([term]) => term).filter(term => term.trim()))
|
|
111
|
-
expect([...searchedTerms()]).toEqual([])
|
|
109
|
+
expect(mockUseSearchResults).not.toHaveBeenCalled()
|
|
112
110
|
|
|
113
111
|
act(() => jest.advanceTimersByTime(200))
|
|
114
112
|
|
|
115
|
-
|
|
113
|
+
const searchedTerms = new Set(mockUseSearchResults.mock.calls.map(([term]) => term))
|
|
114
|
+
expect([...searchedTerms]).toEqual(['budget'])
|
|
116
115
|
expect(view.queryByText('Search chat')).toBeNull()
|
|
117
116
|
expect(view.getByLabelText('Loading results')).toBeTruthy()
|
|
118
117
|
})
|
|
@@ -122,7 +121,10 @@ describe('SearchScreen', () => {
|
|
|
122
121
|
|
|
123
122
|
const scrollView = view.UNSAFE_getByType(ScrollView)
|
|
124
123
|
expect(scrollView.props.keyboardShouldPersistTaps).toBe('handled')
|
|
125
|
-
expect(scrollView.props.contentContainerStyle).toMatchObject({
|
|
124
|
+
expect(scrollView.props.contentContainerStyle).toMatchObject({
|
|
125
|
+
flexGrow: 1,
|
|
126
|
+
justifyContent: 'center',
|
|
127
|
+
})
|
|
126
128
|
expect(view.getByText('Search chat')).toBeTruthy()
|
|
127
129
|
})
|
|
128
130
|
|
|
@@ -49,13 +49,9 @@ const messageResult = (id: string): MessageSearchResultResource => ({
|
|
|
49
49
|
},
|
|
50
50
|
})
|
|
51
51
|
|
|
52
|
-
const slots = { header: <></>, prompt: <></> }
|
|
53
|
-
|
|
54
52
|
const renderList = (state: Partial<SearchState>, onSettled = jest.fn()) => {
|
|
55
53
|
mockUseSearchResults.mockReturnValue(searchState(state))
|
|
56
|
-
const list = () => (
|
|
57
|
-
<SearchResultsList term="potluck" onSelect={jest.fn()} onSettled={onSettled} {...slots} />
|
|
58
|
-
)
|
|
54
|
+
const list = () => <SearchResultsList term="potluck" onSelect={jest.fn()} onSettled={onSettled} />
|
|
59
55
|
const view = render(list())
|
|
60
56
|
const rerenderWith = (next: Partial<SearchState>) => {
|
|
61
57
|
mockUseSearchResults.mockReturnValue(searchState(next))
|
|
@@ -134,7 +130,7 @@ describe('SearchResultsList', () => {
|
|
|
134
130
|
const results = [conversationResult('1'), messageResult('1'), messageResult('2')]
|
|
135
131
|
mockUseSearchResults.mockReturnValue(searchState({ results }))
|
|
136
132
|
const view = render(
|
|
137
|
-
<SearchResultsList term="potluck" onSelect={onSelect} onSettled={jest.fn()}
|
|
133
|
+
<SearchResultsList term="potluck" onSelect={onSelect} onSettled={jest.fn()} />
|
|
138
134
|
)
|
|
139
135
|
|
|
140
136
|
fireEvent.press(view.getByLabelText(/^Message 2/))
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { 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,17 +23,9 @@ 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
|
|
28
26
|
}
|
|
29
27
|
|
|
30
|
-
export function SearchResultsList({
|
|
31
|
-
term,
|
|
32
|
-
onSelect,
|
|
33
|
-
onSettled,
|
|
34
|
-
header,
|
|
35
|
-
prompt,
|
|
36
|
-
}: SearchResultsListProps) {
|
|
28
|
+
export function SearchResultsList({ term, onSelect, onSettled }: SearchResultsListProps) {
|
|
37
29
|
const {
|
|
38
30
|
results,
|
|
39
31
|
failedTypes,
|
|
@@ -44,10 +36,9 @@ export function SearchResultsList({
|
|
|
44
36
|
hasNextPage,
|
|
45
37
|
isFetchingNextPage,
|
|
46
38
|
} = useSearchResults(term)
|
|
47
|
-
const
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
const settled = searching && !isPending && !isError
|
|
39
|
+
const conversationResults = results.filter(isConversationResult)
|
|
40
|
+
const messageResults = results.filter(isMessageResult)
|
|
41
|
+
const settled = !isPending && !isError
|
|
51
42
|
|
|
52
43
|
const settledTermRef = useRef<string | undefined>(undefined)
|
|
53
44
|
|
|
@@ -65,7 +56,6 @@ export function SearchResultsList({
|
|
|
65
56
|
<FlatList
|
|
66
57
|
data={messageResults}
|
|
67
58
|
keyExtractor={item => item.id}
|
|
68
|
-
contentInsetAdjustmentBehavior="automatic"
|
|
69
59
|
keyboardShouldPersistTaps="handled"
|
|
70
60
|
keyboardDismissMode="on-drag"
|
|
71
61
|
contentContainerStyle={styles.content}
|
|
@@ -74,27 +64,20 @@ export function SearchResultsList({
|
|
|
74
64
|
)}
|
|
75
65
|
ListHeaderComponent={
|
|
76
66
|
<>
|
|
77
|
-
{header}
|
|
78
67
|
{conversationResults.length > 0 && (
|
|
79
68
|
<ConversationResults results={conversationResults} onSelect={onSelect} />
|
|
80
69
|
)}
|
|
81
|
-
{
|
|
82
|
-
<SectionFailure type="conversation" />
|
|
83
|
-
)}
|
|
70
|
+
{failedTypes.includes('conversation') && <SectionFailure type="conversation" />}
|
|
84
71
|
{messageResults.length > 0 && <ResultsSection title="Messages" />}
|
|
85
72
|
</>
|
|
86
73
|
}
|
|
87
74
|
ListEmptyComponent={
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
/>
|
|
95
|
-
) : (
|
|
96
|
-
<View style={styles.prompt}>{prompt}</View>
|
|
97
|
-
)
|
|
75
|
+
<ListEmpty
|
|
76
|
+
term={term}
|
|
77
|
+
isError={isError}
|
|
78
|
+
isPending={isPending}
|
|
79
|
+
noResults={results.length === 0 && failedTypes.length === 0}
|
|
80
|
+
/>
|
|
98
81
|
}
|
|
99
82
|
ListFooterComponent={
|
|
100
83
|
<>
|
|
@@ -108,7 +91,7 @@ export function SearchResultsList({
|
|
|
108
91
|
Try again
|
|
109
92
|
</TextButton>
|
|
110
93
|
)}
|
|
111
|
-
{
|
|
94
|
+
{failedTypes.includes('message') && <SectionFailure type="message" />}
|
|
112
95
|
</>
|
|
113
96
|
}
|
|
114
97
|
onEndReached={() => {
|
|
@@ -166,10 +149,6 @@ const styles = StyleSheet.create({
|
|
|
166
149
|
content: {
|
|
167
150
|
flexGrow: 1,
|
|
168
151
|
},
|
|
169
|
-
prompt: {
|
|
170
|
-
flexGrow: 1,
|
|
171
|
-
justifyContent: 'center',
|
|
172
|
-
},
|
|
173
152
|
banner: {
|
|
174
153
|
margin: 16,
|
|
175
154
|
},
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
NativeStackScreenProps,
|
|
5
5
|
} from '@react-navigation/native-stack'
|
|
6
6
|
import React, { useRef, useState } from 'react'
|
|
7
|
-
import { Keyboard, StyleSheet, View } from 'react-native'
|
|
7
|
+
import { Keyboard, ScrollView, StyleSheet, View } from 'react-native'
|
|
8
8
|
import { KeyboardView } from '../../components'
|
|
9
9
|
import {
|
|
10
10
|
composeOptions,
|
|
@@ -64,13 +64,19 @@ export function SearchScreen() {
|
|
|
64
64
|
return (
|
|
65
65
|
<KeyboardView>
|
|
66
66
|
<View style={styles.container} testID="search-screen">
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
+
)}
|
|
74
80
|
</View>
|
|
75
81
|
</KeyboardView>
|
|
76
82
|
)
|
|
@@ -80,4 +86,8 @@ const styles = StyleSheet.create({
|
|
|
80
86
|
container: {
|
|
81
87
|
flex: 1,
|
|
82
88
|
},
|
|
89
|
+
prompt: {
|
|
90
|
+
flexGrow: 1,
|
|
91
|
+
justifyContent: 'center',
|
|
92
|
+
},
|
|
83
93
|
})
|
|
@@ -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,
|
|
4
|
+
import { Platform, 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,31 +28,29 @@ export function SettingsScreen({}: SettingsScreenProps) {
|
|
|
28
28
|
|
|
29
29
|
return (
|
|
30
30
|
<View style={styles.container}>
|
|
31
|
-
<
|
|
32
|
-
<View style={styles.
|
|
33
|
-
<
|
|
34
|
-
<Heading variant="h2">Messages</Heading>
|
|
35
|
-
</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} />}
|
|
31
|
+
<View style={styles.sectionOuter}>
|
|
32
|
+
<View style={styles.sectionHeader}>
|
|
33
|
+
<Heading variant="h2">Messages</Heading>
|
|
54
34
|
</View>
|
|
55
|
-
|
|
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
|
+
/>
|
|
49
|
+
</View>
|
|
50
|
+
)}
|
|
51
|
+
<NavRow label="Notification settings" onPress={handleNotificationSettings} />
|
|
52
|
+
{appName !== 'services' && <NavRow label="Get help" onPress={handleGetHelp} />}
|
|
53
|
+
</View>
|
|
56
54
|
<View style={styles.footer}>
|
|
57
55
|
<VersionFooter />
|
|
58
56
|
</View>
|
|
@@ -92,6 +90,8 @@ const useStyles = () => {
|
|
|
92
90
|
flex: 1,
|
|
93
91
|
},
|
|
94
92
|
footer: {
|
|
93
|
+
flex: 1,
|
|
94
|
+
justifyContent: 'flex-end',
|
|
95
95
|
paddingBottom: Math.max(insets.bottom, 8),
|
|
96
96
|
},
|
|
97
97
|
sectionOuter: {
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { StaticParamList } from '@react-navigation/native';
|
|
2
|
-
import type { PageErrorFallback } from '../components/page/page_error_boundary';
|
|
3
|
-
import type { NewConversationStack } from './index';
|
|
4
|
-
type RouteName = keyof ReactNavigation.RootParamList | keyof StaticParamList<typeof NewConversationStack>;
|
|
5
|
-
export declare const PAGE_ERROR_FALLBACKS: Partial<Record<RouteName, PageErrorFallback>>;
|
|
6
|
-
export {};
|
|
7
|
-
//# sourceMappingURL=page_error_fallbacks.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"page_error_fallbacks.d.ts","sourceRoot":"","sources":["../../src/navigation/page_error_fallbacks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wCAAwC,CAAA;AAC/E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAEnD,KAAK,SAAS,GACV,MAAM,eAAe,CAAC,aAAa,GACnC,MAAM,eAAe,CAAC,OAAO,oBAAoB,CAAC,CAAA;AAEtD,eAAO,MAAM,oBAAoB,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAK9E,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"page_error_fallbacks.js","names":["PAGE_ERROR_FALLBACKS","ConversationSelectDirectMessageRecipients","heading","body"],"sources":["../../src/navigation/page_error_fallbacks.ts"],"sourcesContent":["import type { StaticParamList } from '@react-navigation/native'\nimport type { PageErrorFallback } from '../components/page/page_error_boundary'\nimport type { NewConversationStack } from './index'\n\ntype RouteName =\n | keyof ReactNavigation.RootParamList\n | keyof StaticParamList<typeof NewConversationStack>\n\nexport const PAGE_ERROR_FALLBACKS: Partial<Record<RouteName, PageErrorFallback>> = {\n ConversationSelectDirectMessageRecipients: {\n heading: \"Couldn't load people right now\",\n body: 'Try again.',\n },\n}\n"],"mappings":"AAQA,OAAO,MAAMA,oBAAmE,GAAG;EACjFC,yCAAyC,EAAE;IACzCC,OAAO,EAAE,gCAAgC;IACzCC,IAAI,EAAE;EACR;AACF,CAAC","ignoreList":[]}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { StaticParamList } from '@react-navigation/native'
|
|
2
|
-
import type { PageErrorFallback } from '../components/page/page_error_boundary'
|
|
3
|
-
import type { NewConversationStack } from './index'
|
|
4
|
-
|
|
5
|
-
type RouteName =
|
|
6
|
-
| keyof ReactNavigation.RootParamList
|
|
7
|
-
| keyof StaticParamList<typeof NewConversationStack>
|
|
8
|
-
|
|
9
|
-
export const PAGE_ERROR_FALLBACKS: Partial<Record<RouteName, PageErrorFallback>> = {
|
|
10
|
-
ConversationSelectDirectMessageRecipients: {
|
|
11
|
-
heading: "Couldn't load people right now",
|
|
12
|
-
body: 'Try again.',
|
|
13
|
-
},
|
|
14
|
-
}
|