@planningcenter/chat-react-native 4.4.1-qa-staging.31 → 4.4.1-qa-staging.32
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/page/page_error_boundary.d.ts +9 -1
- package/build/components/page/page_error_boundary.d.ts.map +1 -1
- package/build/components/page/page_error_boundary.js +56 -31
- package/build/components/page/page_error_boundary.js.map +1 -1
- package/build/hooks/direct_messages/use_direct_message_candidates.d.ts +1 -3
- package/build/hooks/direct_messages/use_direct_message_candidates.d.ts.map +1 -1
- package/build/hooks/direct_messages/use_direct_message_candidates.js +29 -42
- package/build/hooks/direct_messages/use_direct_message_candidates.js.map +1 -1
- package/build/navigation/page_error_fallbacks.d.ts +7 -0
- package/build/navigation/page_error_fallbacks.d.ts.map +1 -0
- package/build/navigation/page_error_fallbacks.js +7 -0
- package/build/navigation/page_error_fallbacks.js.map +1 -0
- package/build/navigation/screenLayout.d.ts.map +1 -1
- package/build/navigation/screenLayout.js +10 -6
- 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 +1 -0
- package/build/screens/age_check/age_check_required_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 +168 -228
- package/build/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.js.map +1 -1
- package/build/screens/search/components/search_results_list.d.ts.map +1 -1
- package/build/screens/search/components/search_results_list.js +82 -94
- package/build/screens/search/components/search_results_list.js.map +1 -1
- package/package.json +3 -3
- package/src/components/page/__tests__/page_error_boundary.test.tsx +33 -0
- package/src/components/page/page_error_boundary.tsx +43 -12
- package/src/hooks/direct_messages/use_direct_message_candidates.ts +2 -2
- package/src/navigation/page_error_fallbacks.ts +14 -0
- package/src/navigation/screenLayout.tsx +3 -1
- package/src/screens/age_check/age_check_required_screen.tsx +5 -1
- package/src/screens/conversation_select_recipients/__tests__/conversation_select_direct_message_recipients_screen.test.tsx +25 -8
- package/src/screens/conversation_select_recipients/conversation_select_direct_message_recipients_screen.tsx +7 -32
- package/src/screens/search/components/search_results_list.tsx +11 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search_results_list.js","names":["React","useEffect","useRef","FlatList","StyleSheet","View","Banner","Spinner","Text","TextButton","useSearchResults","ConversationResults","MessageResultRow","ResultsSection","NoResultsBlankState","jsx","_jsx","Fragment","_Fragment","jsxs","_jsxs","SEARCH_ERROR_MESSAGE","SearchResultsList","t0","$","_c","term","onSelect","onSettled","header","prompt","results","failedTypes","isPending","isError","isFetchNextPageError","loadMore","hasNextPage","isFetchingNextPage","t1","trim","searching","length","t2","filter","isConversationResult","conversationResults","t3","isMessageResult","messageResults","settled","settledTermRef","undefined","t4","t5","current","conversationResultCount","messageResultCount","t6","t7","item","item_0","index","onPress","t8","includes","SectionFailure","type","t9","title","t10","children","t11","t12","ListEmpty","noResults","t13","accessibilityLabel","style","styles","loading","t14","retry","t15","t16","t17","t18","keyExtractor","_temp","contentInsetAdjustmentBehavior","keyboardShouldPersistTaps","keyboardDismissMode","contentContainerStyle","content","renderItem","ListHeaderComponent","ListEmptyComponent","ListFooterComponent","onEndReached","onEndReachedThreshold","id","Symbol","for","appearance","banner","accessibilityRole","variant","sectionFailure","result","create","flexGrow","justifyContent","margin","alignItems","paddingVertical","alignSelf","fontSize","paddingHorizontal"],"sources":["../../../../src/screens/search/components/search_results_list.tsx"],"sourcesContent":["import React, { ReactElement, useEffect, useRef } from 'react'\nimport { FlatList, StyleSheet, View } from 'react-native'\nimport { Banner, Spinner, Text, TextButton } from '../../../components'\nimport { useSearchResults } from '../../../hooks/use_search_results'\nimport type {\n ConversationSearchResultResource,\n MessageSearchResultResource,\n SearchResultResource,\n} from '../../../types/resources/search_result'\nimport { ConversationResults } from './conversation_results'\nimport { MessageResultRow } from './message_result_row'\nimport { ResultsSection } from './results_section'\nimport { NoResultsBlankState } from './search_blank_states'\n\nconst SEARCH_ERROR_MESSAGE = \"Couldn't search right now. Try again.\"\n\nexport interface SearchResultCounts {\n conversationResultCount: number\n messageResultCount: number\n}\n\ninterface SearchResultsListProps {\n term: string\n onSelect: (result: SearchResultResource, position: number) => void\n onSettled: (term: string, counts: SearchResultCounts) => void\n header: ReactElement\n prompt: ReactElement\n}\n\nexport function SearchResultsList({\n term,\n onSelect,\n onSettled,\n header,\n prompt,\n}: SearchResultsListProps) {\n const {\n results,\n failedTypes,\n isPending,\n isError,\n isFetchNextPageError,\n loadMore,\n hasNextPage,\n isFetchingNextPage,\n } = useSearchResults(term)\n const searching = term.trim().length > 0\n const conversationResults = searching ? results.filter(isConversationResult) : []\n const messageResults = searching ? results.filter(isMessageResult) : []\n const settled = searching && !isPending && !isError\n\n const settledTermRef = useRef<string | undefined>(undefined)\n\n useEffect(() => {\n if (!settled || settledTermRef.current === term) return\n\n settledTermRef.current = term\n onSettled(term, {\n conversationResultCount: conversationResults.length,\n messageResultCount: messageResults.length,\n })\n }, [settled, term, conversationResults.length, messageResults.length, onSettled])\n\n return (\n <FlatList\n data={messageResults}\n keyExtractor={item => item.id}\n contentInsetAdjustmentBehavior=\"automatic\"\n keyboardShouldPersistTaps=\"handled\"\n keyboardDismissMode=\"on-drag\"\n contentContainerStyle={styles.content}\n renderItem={({ item, index }) => (\n <MessageResultRow result={item} onPress={() => onSelect(item, index)} />\n )}\n ListHeaderComponent={\n <>\n {header}\n {conversationResults.length > 0 && (\n <ConversationResults results={conversationResults} onSelect={onSelect} />\n )}\n {searching && failedTypes.includes('conversation') && (\n <SectionFailure type=\"conversation\" />\n )}\n {messageResults.length > 0 && <ResultsSection title=\"Messages\" />}\n </>\n }\n ListEmptyComponent={\n <ListEmpty\n term={term}\n prompt={prompt}\n isError={isError}\n isPending={isPending}\n noResults={results.length === 0 && failedTypes.length === 0}\n />\n }\n ListFooterComponent={\n <>\n {isFetchingNextPage && (\n <View accessibilityLabel=\"Loading more results\" style={styles.loading}>\n <Spinner />\n </View>\n )}\n {isFetchNextPageError && !isFetchingNextPage && (\n <TextButton onPress={loadMore} style={styles.retry}>\n Try again\n </TextButton>\n )}\n {searching && failedTypes.includes('message') && <SectionFailure type=\"message\" />}\n </>\n }\n onEndReached={() => {\n if (hasNextPage && !isFetchingNextPage && !isFetchNextPageError) loadMore()\n }}\n onEndReachedThreshold={0.5}\n />\n )\n}\n\ninterface ListEmptyProps {\n term: string\n prompt: ReactElement\n isError: boolean\n isPending: boolean\n noResults: boolean\n}\n\nfunction ListEmpty({ term, prompt, isError, isPending, noResults }: ListEmptyProps) {\n if (term.trim().length === 0) return <View style={styles.prompt}>{prompt}</View>\n\n if (isError) {\n return <Banner appearance=\"error\" description={SEARCH_ERROR_MESSAGE} style={styles.banner} />\n }\n\n if (isPending) {\n return (\n <View accessibilityLabel=\"Loading results\" style={styles.loading}>\n <Spinner />\n </View>\n )\n }\n\n if (noResults) return <NoResultsBlankState term={term} />\n\n return null\n}\n\nfunction SectionFailure({ type }: { type: SearchResultResource['type'] }) {\n return (\n <Text accessibilityRole=\"alert\" variant=\"secondary\" style={styles.sectionFailure}>\n Couldn’t load {type}s.\n </Text>\n )\n}\n\nfunction isConversationResult(\n result: SearchResultResource\n): result is ConversationSearchResultResource {\n return result.type === 'conversation'\n}\n\nfunction isMessageResult(result: SearchResultResource): result is MessageSearchResultResource {\n return result.type === 'message'\n}\n\nconst styles = StyleSheet.create({\n content: {\n flexGrow: 1,\n },\n prompt: {\n flexGrow: 1,\n justifyContent: 'center',\n },\n banner: {\n margin: 16,\n },\n loading: {\n alignItems: 'center',\n paddingVertical: 16,\n },\n retry: {\n alignSelf: 'center',\n paddingVertical: 16,\n },\n sectionFailure: {\n fontSize: 14,\n paddingHorizontal: 16,\n paddingVertical: 8,\n },\n})\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"search_results_list.js","names":["React","useEffect","useRef","FlatList","StyleSheet","View","Banner","Spinner","Text","TextButton","useSearchResults","ConversationResults","MessageResultRow","ResultsSection","NoResultsBlankState","jsx","_jsx","Fragment","_Fragment","jsxs","_jsxs","SEARCH_ERROR_MESSAGE","SearchResultsList","t0","$","_c","term","onSelect","onSettled","header","prompt","results","failedTypes","isPending","isError","isFetchNextPageError","loadMore","hasNextPage","isFetchingNextPage","t1","trim","searching","length","t2","filter","isConversationResult","conversationResults","t3","isMessageResult","messageResults","settled","settledTermRef","undefined","t4","t5","current","conversationResultCount","messageResultCount","t6","t7","item","item_0","index","onPress","t8","includes","SectionFailure","type","t9","title","t10","children","t11","ListEmpty","noResults","style","styles","t12","accessibilityLabel","loading","t13","retry","t14","t15","t16","t17","keyExtractor","_temp","contentInsetAdjustmentBehavior","keyboardShouldPersistTaps","keyboardDismissMode","contentContainerStyle","content","renderItem","ListHeaderComponent","ListEmptyComponent","ListFooterComponent","onEndReached","onEndReachedThreshold","id","Symbol","for","appearance","banner","accessibilityRole","variant","sectionFailure","result","create","flexGrow","justifyContent","margin","alignItems","paddingVertical","alignSelf","fontSize","paddingHorizontal"],"sources":["../../../../src/screens/search/components/search_results_list.tsx"],"sourcesContent":["import React, { ReactElement, useEffect, useRef } from 'react'\nimport { FlatList, StyleSheet, View } from 'react-native'\nimport { Banner, Spinner, Text, TextButton } from '../../../components'\nimport { useSearchResults } from '../../../hooks/use_search_results'\nimport type {\n ConversationSearchResultResource,\n MessageSearchResultResource,\n SearchResultResource,\n} from '../../../types/resources/search_result'\nimport { ConversationResults } from './conversation_results'\nimport { MessageResultRow } from './message_result_row'\nimport { ResultsSection } from './results_section'\nimport { NoResultsBlankState } from './search_blank_states'\n\nconst SEARCH_ERROR_MESSAGE = \"Couldn't search right now. Try again.\"\n\nexport interface SearchResultCounts {\n conversationResultCount: number\n messageResultCount: number\n}\n\ninterface SearchResultsListProps {\n term: string\n onSelect: (result: SearchResultResource, position: number) => void\n onSettled: (term: string, counts: SearchResultCounts) => void\n header: ReactElement\n prompt: ReactElement\n}\n\nexport function SearchResultsList({\n term,\n onSelect,\n onSettled,\n header,\n prompt,\n}: SearchResultsListProps) {\n const {\n results,\n failedTypes,\n isPending,\n isError,\n isFetchNextPageError,\n loadMore,\n hasNextPage,\n isFetchingNextPage,\n } = useSearchResults(term)\n const searching = term.trim().length > 0\n const conversationResults = searching ? results.filter(isConversationResult) : []\n const messageResults = searching ? results.filter(isMessageResult) : []\n const settled = searching && !isPending && !isError\n\n const settledTermRef = useRef<string | undefined>(undefined)\n\n useEffect(() => {\n if (!settled || settledTermRef.current === term) return\n\n settledTermRef.current = term\n onSettled(term, {\n conversationResultCount: conversationResults.length,\n messageResultCount: messageResults.length,\n })\n }, [settled, term, conversationResults.length, messageResults.length, onSettled])\n\n return (\n <FlatList\n data={messageResults}\n keyExtractor={item => item.id}\n contentInsetAdjustmentBehavior=\"automatic\"\n keyboardShouldPersistTaps=\"handled\"\n keyboardDismissMode=\"on-drag\"\n contentContainerStyle={styles.content}\n renderItem={({ item, index }) => (\n <MessageResultRow result={item} onPress={() => onSelect(item, index)} />\n )}\n ListHeaderComponent={\n <>\n {header}\n {conversationResults.length > 0 && (\n <ConversationResults results={conversationResults} onSelect={onSelect} />\n )}\n {searching && failedTypes.includes('conversation') && (\n <SectionFailure type=\"conversation\" />\n )}\n {messageResults.length > 0 && <ResultsSection title=\"Messages\" />}\n </>\n }\n ListEmptyComponent={\n searching ? (\n <ListEmpty\n term={term}\n isError={isError}\n isPending={isPending}\n noResults={results.length === 0 && failedTypes.length === 0}\n />\n ) : (\n <View style={styles.prompt}>{prompt}</View>\n )\n }\n ListFooterComponent={\n <>\n {isFetchingNextPage && (\n <View accessibilityLabel=\"Loading more results\" style={styles.loading}>\n <Spinner />\n </View>\n )}\n {isFetchNextPageError && !isFetchingNextPage && (\n <TextButton onPress={loadMore} style={styles.retry}>\n Try again\n </TextButton>\n )}\n {searching && failedTypes.includes('message') && <SectionFailure type=\"message\" />}\n </>\n }\n onEndReached={() => {\n if (hasNextPage && !isFetchingNextPage && !isFetchNextPageError) loadMore()\n }}\n onEndReachedThreshold={0.5}\n />\n )\n}\n\ninterface ListEmptyProps {\n term: string\n isError: boolean\n isPending: boolean\n noResults: boolean\n}\n\nfunction ListEmpty({ term, isError, isPending, noResults }: ListEmptyProps) {\n if (isError) {\n return <Banner appearance=\"error\" description={SEARCH_ERROR_MESSAGE} style={styles.banner} />\n }\n\n if (isPending) {\n return (\n <View accessibilityLabel=\"Loading results\" style={styles.loading}>\n <Spinner />\n </View>\n )\n }\n\n if (noResults) return <NoResultsBlankState term={term} />\n\n return null\n}\n\nfunction SectionFailure({ type }: { type: SearchResultResource['type'] }) {\n return (\n <Text accessibilityRole=\"alert\" variant=\"secondary\" style={styles.sectionFailure}>\n Couldn’t load {type}s.\n </Text>\n )\n}\n\nfunction isConversationResult(\n result: SearchResultResource\n): result is ConversationSearchResultResource {\n return result.type === 'conversation'\n}\n\nfunction isMessageResult(result: SearchResultResource): result is MessageSearchResultResource {\n return result.type === 'message'\n}\n\nconst styles = StyleSheet.create({\n content: {\n flexGrow: 1,\n },\n prompt: {\n flexGrow: 1,\n justifyContent: 'center',\n },\n banner: {\n margin: 16,\n },\n loading: {\n alignItems: 'center',\n paddingVertical: 16,\n },\n retry: {\n alignSelf: 'center',\n paddingVertical: 16,\n },\n sectionFailure: {\n fontSize: 14,\n paddingHorizontal: 16,\n paddingVertical: 8,\n },\n})\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "4.4.1-qa-staging.
|
|
3
|
+
"version": "4.4.1-qa-staging.32",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@fortawesome/fontawesome-svg-core": "^7.2.0",
|
|
35
35
|
"@fortawesome/react-native-fontawesome": "^0.3.2",
|
|
36
|
-
"@planningcenter/emoji-keyboard": "4.4.1-qa-staging.
|
|
36
|
+
"@planningcenter/emoji-keyboard": "4.4.1-qa-staging.32",
|
|
37
37
|
"lodash-inflection": "^1.5.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
@@ -84,5 +84,5 @@
|
|
|
84
84
|
"sf-symbols-typescript": "^2.2.0",
|
|
85
85
|
"typescript": "~6.0.3"
|
|
86
86
|
},
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "1f71f59f1f9f115d21df50180c264c62c79f2908"
|
|
88
88
|
}
|
|
@@ -4,6 +4,7 @@ import { render } from '@testing-library/react-native'
|
|
|
4
4
|
import React from 'react'
|
|
5
5
|
import { buildTestQueryClient } from '../../../__utils__/query_client'
|
|
6
6
|
import { Log } from '../../../utils/native_adapters/configuration'
|
|
7
|
+
import { ResponseError } from '../../../utils/response_error'
|
|
7
8
|
import { PageErrorBoundary } from '../page_error_boundary'
|
|
8
9
|
|
|
9
10
|
jest.mock('../../primitive/blank_state_primitive', () => {
|
|
@@ -74,4 +75,36 @@ describe('PageErrorBoundary', () => {
|
|
|
74
75
|
expect(getByText('Oops!')).toBeTruthy()
|
|
75
76
|
expect(getByText('Something unexpected happened.')).toBeTruthy()
|
|
76
77
|
})
|
|
78
|
+
|
|
79
|
+
describe('with a generic fallback override', () => {
|
|
80
|
+
const genericFallback = { heading: 'Nothing here', body: 'Come back later.' }
|
|
81
|
+
const responseError = (status: number) =>
|
|
82
|
+
new ResponseError({ status, statusText: 'x', errors: [] } as never)
|
|
83
|
+
|
|
84
|
+
it.each([
|
|
85
|
+
['a plain error', new Error('boom')],
|
|
86
|
+
['an unhandled status', responseError(500)],
|
|
87
|
+
])('replaces the Oops copy for %s', (_label, thrown) => {
|
|
88
|
+
const { getByText, queryByText } = renderWithProviders(
|
|
89
|
+
<PageErrorBoundary genericFallback={genericFallback}>
|
|
90
|
+
<Boom thrown={thrown} />
|
|
91
|
+
</PageErrorBoundary>
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
expect(getByText('Nothing here')).toBeTruthy()
|
|
95
|
+
expect(getByText('Come back later.')).toBeTruthy()
|
|
96
|
+
expect(queryByText('Oops!')).toBeNull()
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it('leaves a known status alone', () => {
|
|
100
|
+
const { getByText, queryByText } = renderWithProviders(
|
|
101
|
+
<PageErrorBoundary genericFallback={genericFallback}>
|
|
102
|
+
<Boom thrown={responseError(403)} />
|
|
103
|
+
</PageErrorBoundary>
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
expect(getByText('Permission required')).toBeTruthy()
|
|
107
|
+
expect(queryByText('Nothing here')).toBeNull()
|
|
108
|
+
})
|
|
109
|
+
})
|
|
77
110
|
})
|
|
@@ -6,11 +6,26 @@ import { ResponseError } from '../../utils/response_error'
|
|
|
6
6
|
import BlankState from '../primitive/blank_state_primitive'
|
|
7
7
|
import { ErrorBoundary, ErrorBoundaryFallback, ErrorBoundaryProps } from './error_boundary'
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export type PageErrorFallback = { heading: string; body: string }
|
|
10
|
+
|
|
11
|
+
const GENERIC_FALLBACK: PageErrorFallback = {
|
|
12
|
+
heading: 'Oops!',
|
|
13
|
+
body: 'Something unexpected happened.',
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type PageErrorBoundaryProps = PropsWithChildren<
|
|
17
|
+
ErrorBoundaryProps & { genericFallback?: PageErrorFallback }
|
|
18
|
+
>
|
|
19
|
+
|
|
20
|
+
export function PageErrorBoundary({
|
|
21
|
+
children,
|
|
22
|
+
genericFallback = GENERIC_FALLBACK,
|
|
23
|
+
...props
|
|
24
|
+
}: PageErrorBoundaryProps) {
|
|
25
|
+
const renderPageFallback: ErrorBoundaryFallback = (error, reset) => (
|
|
26
|
+
<ErrorView error={error} reset={reset} generic={genericFallback} />
|
|
27
|
+
)
|
|
12
28
|
|
|
13
|
-
export function PageErrorBoundary({ children, ...props }: PropsWithChildren<ErrorBoundaryProps>) {
|
|
14
29
|
return (
|
|
15
30
|
<ErrorBoundary scope="screen" fallback={renderPageFallback} {...props}>
|
|
16
31
|
{children}
|
|
@@ -18,7 +33,15 @@ export function PageErrorBoundary({ children, ...props }: PropsWithChildren<Erro
|
|
|
18
33
|
)
|
|
19
34
|
}
|
|
20
35
|
|
|
21
|
-
function ErrorView({
|
|
36
|
+
function ErrorView({
|
|
37
|
+
error,
|
|
38
|
+
reset,
|
|
39
|
+
generic,
|
|
40
|
+
}: {
|
|
41
|
+
error: Error
|
|
42
|
+
reset: () => void
|
|
43
|
+
generic: PageErrorFallback
|
|
44
|
+
}) {
|
|
22
45
|
const { reset: resetQueries } = useQueryErrorResetBoundary()
|
|
23
46
|
|
|
24
47
|
const handleReset = useCallback(() => {
|
|
@@ -29,7 +52,7 @@ function ErrorView({ error, reset }: { error: Error; reset: () => void }) {
|
|
|
29
52
|
useEffect(() => handleReset, [handleReset])
|
|
30
53
|
|
|
31
54
|
if (error instanceof ResponseError) {
|
|
32
|
-
return <ResponseErrorView response={error.response} onReset={handleReset} />
|
|
55
|
+
return <ResponseErrorView response={error.response} onReset={handleReset} generic={generic} />
|
|
33
56
|
}
|
|
34
57
|
|
|
35
58
|
if (isNetworkError(error)) {
|
|
@@ -41,7 +64,7 @@ function ErrorView({ error, reset }: { error: Error; reset: () => void }) {
|
|
|
41
64
|
)
|
|
42
65
|
}
|
|
43
66
|
|
|
44
|
-
return <ErrorContent heading={
|
|
67
|
+
return <ErrorContent heading={generic.heading} body={generic.body} />
|
|
45
68
|
}
|
|
46
69
|
|
|
47
70
|
function isNetworkError(error: Error) {
|
|
@@ -54,7 +77,15 @@ function isNetworkError(error: Error) {
|
|
|
54
77
|
return new RegExp(networkFailedMessages.join('|'), 'i').test(error.message)
|
|
55
78
|
}
|
|
56
79
|
|
|
57
|
-
function ResponseErrorView({
|
|
80
|
+
function ResponseErrorView({
|
|
81
|
+
response,
|
|
82
|
+
onReset,
|
|
83
|
+
generic,
|
|
84
|
+
}: {
|
|
85
|
+
response: Response
|
|
86
|
+
onReset: () => void
|
|
87
|
+
generic: PageErrorFallback
|
|
88
|
+
}) {
|
|
58
89
|
const { status } = response
|
|
59
90
|
|
|
60
91
|
const heading = useMemo(() => {
|
|
@@ -64,9 +95,9 @@ function ResponseErrorView({ response, onReset }: { response: Response; onReset:
|
|
|
64
95
|
case 404:
|
|
65
96
|
return 'Content not found'
|
|
66
97
|
default:
|
|
67
|
-
return
|
|
98
|
+
return generic.heading
|
|
68
99
|
}
|
|
69
|
-
}, [status])
|
|
100
|
+
}, [status, generic.heading])
|
|
70
101
|
|
|
71
102
|
const body = useMemo(() => {
|
|
72
103
|
switch (status) {
|
|
@@ -75,9 +106,9 @@ function ResponseErrorView({ response, onReset }: { response: Response; onReset:
|
|
|
75
106
|
case 404:
|
|
76
107
|
return 'If you believe something should be here, please reach out to your administrator.'
|
|
77
108
|
default:
|
|
78
|
-
return
|
|
109
|
+
return generic.body
|
|
79
110
|
}
|
|
80
|
-
}, [status])
|
|
111
|
+
}, [status, generic.body])
|
|
81
112
|
|
|
82
113
|
useEffect(() => {
|
|
83
114
|
if (status !== 401) return
|
|
@@ -3,7 +3,7 @@ import { ApiCollection } from '../../types'
|
|
|
3
3
|
import { DirectMessageCandidateResource } from '../../types/resources/direct_message_candidate'
|
|
4
4
|
import { useApiClient } from '../use_api_client'
|
|
5
5
|
|
|
6
|
-
export function useDirectMessageCandidates(term: string
|
|
6
|
+
export function useDirectMessageCandidates(term: string) {
|
|
7
7
|
const apiClient = useApiClient()
|
|
8
8
|
return useQuery({
|
|
9
9
|
queryKey: ['chat', '/me/direct_message_candidates', term],
|
|
@@ -26,6 +26,6 @@ export function useDirectMessageCandidates(term: string, { throwOnError = true }
|
|
|
26
26
|
}) as Promise<ApiCollection<DirectMessageCandidateResource>>,
|
|
27
27
|
enabled: term.length >= 1,
|
|
28
28
|
staleTime: 1000 * 60,
|
|
29
|
-
throwOnError,
|
|
29
|
+
throwOnError: true,
|
|
30
30
|
})
|
|
31
31
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
}
|
|
@@ -4,12 +4,14 @@ import { Suspense } from 'react'
|
|
|
4
4
|
import { DefaultLoading } from '../components/page/loading'
|
|
5
5
|
import { PageErrorBoundary } from '../components/page/page_error_boundary'
|
|
6
6
|
import { ChatAccessGate } from './chat_access_gate'
|
|
7
|
+
import { PAGE_ERROR_FALLBACKS } from './page_error_fallbacks'
|
|
7
8
|
|
|
8
9
|
export function ScreenLayout({ children }: { children: React.ReactElement }) {
|
|
9
10
|
const route = useRoute()
|
|
11
|
+
const genericFallback = PAGE_ERROR_FALLBACKS[route.name as keyof typeof PAGE_ERROR_FALLBACKS]
|
|
10
12
|
|
|
11
13
|
return (
|
|
12
|
-
<PageErrorBoundary screenName={route.name}>
|
|
14
|
+
<PageErrorBoundary screenName={route.name} genericFallback={genericFallback}>
|
|
13
15
|
<Suspense fallback={<DefaultLoading />}>{children}</Suspense>
|
|
14
16
|
</PageErrorBoundary>
|
|
15
17
|
)
|
|
@@ -58,7 +58,11 @@ export function AgeCheckRequiredScreen() {
|
|
|
58
58
|
|
|
59
59
|
return (
|
|
60
60
|
<>
|
|
61
|
-
<ScrollView
|
|
61
|
+
<ScrollView
|
|
62
|
+
contentInsetAdjustmentBehavior="automatic"
|
|
63
|
+
style={styles.scrollView}
|
|
64
|
+
contentContainerStyle={styles.container}
|
|
65
|
+
>
|
|
62
66
|
<View style={styles.header}>
|
|
63
67
|
<View style={styles.heading}>
|
|
64
68
|
<Icon name="general.exclamationTriangle" size={20} style={styles.warningIcon} />
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { fireEvent, render } from '@testing-library/react-native'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import { SafeAreaProvider } from 'react-native-safe-area-context'
|
|
4
|
+
import { ScreenLayout } from '../../../navigation/screenLayout'
|
|
4
5
|
import { Log } from '../../../utils/native_adapters/configuration'
|
|
6
|
+
import { ResponseError } from '../../../utils/response_error'
|
|
5
7
|
import { ConversationSelectDirectMessageRecipientsScreen } from '../conversation_select_direct_message_recipients_screen'
|
|
6
8
|
|
|
7
9
|
jest.mock('@react-navigation/native', () => ({
|
|
8
10
|
...jest.requireActual('@react-navigation/native'),
|
|
9
|
-
useNavigation: () => ({ getParent: jest.fn() }),
|
|
11
|
+
useNavigation: () => ({ getParent: jest.fn(), goBack: jest.fn(), navigate: jest.fn() }),
|
|
12
|
+
useRoute: () => ({ name: 'ConversationSelectDirectMessageRecipients' }),
|
|
10
13
|
}))
|
|
11
14
|
jest.mock('../../../hooks/use_features', () => ({
|
|
12
15
|
...jest.requireActual('../../../hooks/use_features'),
|
|
@@ -33,10 +36,11 @@ jest.mock('../../../hooks/direct_messages/use_direct_message_affiliations', () =
|
|
|
33
36
|
resultsDescription: null,
|
|
34
37
|
}),
|
|
35
38
|
}))
|
|
39
|
+
let mockSearchFailure: Error = new TypeError('Network request failed')
|
|
36
40
|
jest.mock('../../../hooks/direct_messages/use_direct_message_candidates', () => ({
|
|
37
|
-
useDirectMessageCandidates: (term: string
|
|
38
|
-
if (term
|
|
39
|
-
return { data: undefined, isFetching: false
|
|
41
|
+
useDirectMessageCandidates: (term: string) => {
|
|
42
|
+
if (term) throw mockSearchFailure
|
|
43
|
+
return { data: undefined, isFetching: false }
|
|
40
44
|
},
|
|
41
45
|
}))
|
|
42
46
|
jest.mock('../../../components/display/action_button', () => ({ ActionButton: () => null }))
|
|
@@ -53,7 +57,9 @@ const renderScreen = () =>
|
|
|
53
57
|
insets: { top: 0, left: 0, right: 0, bottom: 0 },
|
|
54
58
|
}}
|
|
55
59
|
>
|
|
56
|
-
<
|
|
60
|
+
<ScreenLayout>
|
|
61
|
+
<ConversationSelectDirectMessageRecipientsScreen route={{ params: {} } as never} />
|
|
62
|
+
</ScreenLayout>
|
|
57
63
|
</SafeAreaProvider>
|
|
58
64
|
)
|
|
59
65
|
|
|
@@ -71,13 +77,24 @@ describe('ConversationSelectDirectMessageRecipientsScreen', () => {
|
|
|
71
77
|
consoleError.mockRestore()
|
|
72
78
|
})
|
|
73
79
|
|
|
74
|
-
it('
|
|
80
|
+
it('hands a failed search to the page error view', () => {
|
|
81
|
+
mockSearchFailure = new TypeError('Network request failed')
|
|
75
82
|
const view = renderScreen()
|
|
76
83
|
|
|
77
84
|
fireEvent.changeText(view.getByPlaceholderText('Search'), 'pi')
|
|
78
85
|
|
|
79
|
-
expect(view.getByText(
|
|
80
|
-
expect(view.
|
|
86
|
+
expect(view.getByText('Problem connecting!')).toBeTruthy()
|
|
87
|
+
expect(view.queryByPlaceholderText('Search')).toBeNull()
|
|
81
88
|
expect(reportError).toHaveBeenCalledTimes(1)
|
|
82
89
|
})
|
|
90
|
+
|
|
91
|
+
it("uses the screen's own wording when the search fails for no known reason", () => {
|
|
92
|
+
mockSearchFailure = new ResponseError({ status: 500, statusText: 'x', errors: [] } as never)
|
|
93
|
+
const view = renderScreen()
|
|
94
|
+
|
|
95
|
+
fireEvent.changeText(view.getByPlaceholderText('Search'), 'pi')
|
|
96
|
+
|
|
97
|
+
expect(view.getByText("Couldn't load people right now")).toBeTruthy()
|
|
98
|
+
expect(view.queryByText('Oops!')).toBeNull()
|
|
99
|
+
})
|
|
83
100
|
})
|
|
@@ -5,7 +5,6 @@ import { FlatList, Pressable, StyleSheet, TextInput, View } from 'react-native'
|
|
|
5
5
|
import { Avatar, Badge, Banner, Icon, KeyboardView, Spinner, Text } from '../../components'
|
|
6
6
|
import { ActionButton } from '../../components/display/action_button'
|
|
7
7
|
import { AutoFocusAwareTextInput } from '../../components/display/text_input'
|
|
8
|
-
import { ComponentErrorBoundary } from '../../components/page/component_error_boundary'
|
|
9
8
|
import { useTheme } from '../../hooks'
|
|
10
9
|
import { useDirectMessageAffiliations } from '../../hooks/direct_messages/use_direct_message_affiliations'
|
|
11
10
|
import { useDirectMessageCandidates } from '../../hooks/direct_messages/use_direct_message_candidates'
|
|
@@ -215,13 +214,13 @@ function CandidateResults({
|
|
|
215
214
|
header: ReactElement
|
|
216
215
|
}) {
|
|
217
216
|
const styles = useStyles()
|
|
218
|
-
const { data, isFetching
|
|
217
|
+
const { data, isFetching } = useDirectMessageCandidates(term)
|
|
219
218
|
const { groups, teams, resultsDescription } = useDirectMessageAffiliations()
|
|
220
219
|
|
|
221
220
|
const unselectedCandidates = (data?.data ?? []).filter(c => !selectedPeople.has(c.id))
|
|
222
221
|
const hasTruncated = (data?.meta.totalCount ?? 0) > (data?.data.length ?? 0)
|
|
223
222
|
const isAtLimit = selectedPeople.size >= MAX_RECIPIENTS
|
|
224
|
-
const showsResults = term.length >= 1 && !isAtLimit &&
|
|
223
|
+
const showsResults = term.length >= 1 && !isAtLimit && unselectedCandidates.length > 0
|
|
225
224
|
|
|
226
225
|
const emptyState = (() => {
|
|
227
226
|
if (showsResults) return null
|
|
@@ -240,23 +239,6 @@ function CandidateResults({
|
|
|
240
239
|
)
|
|
241
240
|
}
|
|
242
241
|
|
|
243
|
-
if (isError) {
|
|
244
|
-
return (
|
|
245
|
-
<ComponentErrorBoundary
|
|
246
|
-
key={term}
|
|
247
|
-
fallback={
|
|
248
|
-
<Banner
|
|
249
|
-
appearance="error"
|
|
250
|
-
description="Couldn't load people right now. Try again."
|
|
251
|
-
style={styles.errorBanner}
|
|
252
|
-
/>
|
|
253
|
-
}
|
|
254
|
-
>
|
|
255
|
-
<CandidateSearchError term={term} />
|
|
256
|
-
</ComponentErrorBoundary>
|
|
257
|
-
)
|
|
258
|
-
}
|
|
259
|
-
|
|
260
242
|
if (isAtLimit) {
|
|
261
243
|
return (
|
|
262
244
|
<View style={styles.emptyState}>
|
|
@@ -290,9 +272,8 @@ function CandidateResults({
|
|
|
290
272
|
<CandidateList
|
|
291
273
|
header={header}
|
|
292
274
|
candidates={showsResults ? unselectedCandidates : []}
|
|
293
|
-
hasTruncated={
|
|
294
|
-
description={
|
|
295
|
-
showsHeading={showsResults}
|
|
275
|
+
hasTruncated={hasTruncated}
|
|
276
|
+
description={resultsDescription}
|
|
296
277
|
emptyState={emptyState}
|
|
297
278
|
groups={groups}
|
|
298
279
|
teams={teams}
|
|
@@ -301,11 +282,6 @@ function CandidateResults({
|
|
|
301
282
|
)
|
|
302
283
|
}
|
|
303
284
|
|
|
304
|
-
function CandidateSearchError({ term }: { term: string }) {
|
|
305
|
-
useDirectMessageCandidates(term)
|
|
306
|
-
return null
|
|
307
|
-
}
|
|
308
|
-
|
|
309
285
|
function candidateBadges(candidate: DirectMessageCandidateResource) {
|
|
310
286
|
const badges = []
|
|
311
287
|
if (candidate.directMessagesDisabled) badges.push({ title: 'DMs off' })
|
|
@@ -335,7 +311,6 @@ function CandidateList({
|
|
|
335
311
|
candidates,
|
|
336
312
|
hasTruncated,
|
|
337
313
|
description,
|
|
338
|
-
showsHeading,
|
|
339
314
|
emptyState,
|
|
340
315
|
groups,
|
|
341
316
|
teams,
|
|
@@ -345,13 +320,13 @@ function CandidateList({
|
|
|
345
320
|
candidates: DirectMessageCandidateResource[]
|
|
346
321
|
hasTruncated: boolean
|
|
347
322
|
description: string | null
|
|
348
|
-
showsHeading: boolean
|
|
349
323
|
emptyState: ReactElement | null
|
|
350
324
|
groups: Map<number, string>
|
|
351
325
|
teams: Map<number, string>
|
|
352
326
|
onSelect: (candidate: DirectMessageCandidateResource) => void
|
|
353
327
|
}) {
|
|
354
328
|
const styles = useStyles()
|
|
329
|
+
const hasCandidates = candidates.length > 0
|
|
355
330
|
const available = candidates.filter(c => !c.directMessagesDisabled)
|
|
356
331
|
const dmDisabled = candidates.filter(c => c.directMessagesDisabled)
|
|
357
332
|
|
|
@@ -372,7 +347,7 @@ function CandidateList({
|
|
|
372
347
|
ListHeaderComponent={
|
|
373
348
|
<>
|
|
374
349
|
{header}
|
|
375
|
-
{
|
|
350
|
+
{hasCandidates && <ResultsHeading description={description} />}
|
|
376
351
|
</>
|
|
377
352
|
}
|
|
378
353
|
ListEmptyComponent={emptyState}
|
|
@@ -396,7 +371,7 @@ function CandidateList({
|
|
|
396
371
|
))}
|
|
397
372
|
</>
|
|
398
373
|
)}
|
|
399
|
-
{hasTruncated && (
|
|
374
|
+
{hasCandidates && hasTruncated && (
|
|
400
375
|
<View style={styles.truncatedFooter}>
|
|
401
376
|
<Text variant="secondary" style={styles.truncatedText}>
|
|
402
377
|
Keep typing to narrow your results.
|
|
@@ -85,13 +85,16 @@ export function SearchResultsList({
|
|
|
85
85
|
</>
|
|
86
86
|
}
|
|
87
87
|
ListEmptyComponent={
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
+
)
|
|
95
98
|
}
|
|
96
99
|
ListFooterComponent={
|
|
97
100
|
<>
|
|
@@ -118,15 +121,12 @@ export function SearchResultsList({
|
|
|
118
121
|
|
|
119
122
|
interface ListEmptyProps {
|
|
120
123
|
term: string
|
|
121
|
-
prompt: ReactElement
|
|
122
124
|
isError: boolean
|
|
123
125
|
isPending: boolean
|
|
124
126
|
noResults: boolean
|
|
125
127
|
}
|
|
126
128
|
|
|
127
|
-
function ListEmpty({ term,
|
|
128
|
-
if (term.trim().length === 0) return <View style={styles.prompt}>{prompt}</View>
|
|
129
|
-
|
|
129
|
+
function ListEmpty({ term, isError, isPending, noResults }: ListEmptyProps) {
|
|
130
130
|
if (isError) {
|
|
131
131
|
return <Banner appearance="error" description={SEARCH_ERROR_MESSAGE} style={styles.banner} />
|
|
132
132
|
}
|