@planningcenter/chat-react-native 3.11.1 → 3.11.2-rc.0

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.
@@ -1,6 +1,7 @@
1
1
  import React, { PropsWithChildren } from 'react';
2
+ import { ResponseError } from '../../utils/response_error';
2
3
  type ErrorBoundaryState = {
3
- error: Response | Error | null;
4
+ error: ResponseError | Error | TypeError | null;
4
5
  unsubscriber: () => void;
5
6
  };
6
7
  declare class ErrorBoundary extends React.Component<PropsWithChildren<{
@@ -1 +1 @@
1
- {"version":3,"file":"error_boundary.d.ts","sourceRoot":"","sources":["../../../src/components/page/error_boundary.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAsB,MAAM,OAAO,CAAA;AAOpE,KAAK,kBAAkB,GAAG;IACxB,KAAK,EAAE,QAAQ,GAAG,KAAK,GAAG,IAAI,CAAA;IAC9B,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB,CAAA;AAED,cAAM,aAAc,SAAQ,KAAK,CAAC,SAAS,CAAC,iBAAiB,CAAC;IAAE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC,CAAC;IACtF,KAAK,EAAE,kBAAkB,CAGxB;IAED,iBAAiB,CAAC,KAAK,EAAE,GAAG;IAI5B,WAAW,CAAC,KAAK,EAAE,GAAG;IAItB,WAAW,aAGV;IAED,MAAM;CAOP;AAkGD,eAAe,aAAa,CAAA"}
1
+ {"version":3,"file":"error_boundary.d.ts","sourceRoot":"","sources":["../../../src/components/page/error_boundary.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAsB,MAAM,OAAO,CAAA;AAKpE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAE1D,KAAK,kBAAkB,GAAG;IACxB,KAAK,EAAE,aAAa,GAAG,KAAK,GAAG,SAAS,GAAG,IAAI,CAAA;IAC/C,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB,CAAA;AAED,cAAM,aAAc,SAAQ,KAAK,CAAC,SAAS,CAAC,iBAAiB,CAAC;IAAE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC,CAAC;IACtF,KAAK,EAAE,kBAAkB,CAGxB;IAED,iBAAiB,CAAC,KAAK,EAAE,GAAG;IAI5B,WAAW,CAAC,KAAK,EAAE,GAAG;IAItB,WAAW,aAGV;IAED,MAAM;CAOP;AAwHD,eAAe,aAAa,CAAA"}
@@ -43,8 +43,22 @@ function ErrorView({ error, onReset }) {
43
43
  if (error instanceof ResponseError) {
44
44
  return <ResponseErrorView response={error.response} onReset={onReset}/>;
45
45
  }
46
+ if (isNetworkError(error)) {
47
+ return (<ErrorContent heading={'Problem connecting!'} body={'Check your internet connection and try again.'}/>);
48
+ }
46
49
  return <ErrorContent heading={'Oops!'} body={'Something unexpected happened.'}/>;
47
50
  }
51
+ function isNetworkError(error) {
52
+ const isError = error instanceof Error;
53
+ const networkFailedMessages = [
54
+ 'Network request failed',
55
+ 'Network request timed out',
56
+ 'Failed to fetch',
57
+ ];
58
+ if (!isError)
59
+ return false;
60
+ return new RegExp(networkFailedMessages.join('|'), 'i').test(error.message);
61
+ }
48
62
  function ResponseErrorView({ response }) {
49
63
  const { status } = response;
50
64
  const heading = useMemo(() => {
@@ -80,10 +94,10 @@ function ErrorContent({ heading, body }) {
80
94
  </Heading>
81
95
  <Text style={styles.body}>{body}</Text>
82
96
  </View>
97
+ <Button variant="outline" onPress={navigation.goBack} title="Go back" size="md"/>
83
98
  <TextButton variant="tertiary" onPress={() => navigation.navigate('BugReport')}>
84
99
  Report a bug
85
100
  </TextButton>
86
- <Button variant="outline" onPress={navigation.goBack} title="Go back" size="md"/>
87
101
  </View>);
88
102
  }
89
103
  const useStyles = () => {
@@ -1 +1 @@
1
- {"version":3,"file":"error_boundary.js","sourceRoot":"","sources":["../../../src/components/page/error_boundary.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAA;AAClE,OAAO,KAAK,EAAE,EAAqB,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACpE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAO1D,MAAM,aAAc,SAAQ,KAAK,CAAC,SAAsD;IACtF,KAAK,GAAuB;QAC1B,KAAK,EAAE,IAAI;QACX,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;KACvB,CAAA;IAED,iBAAiB,CAAC,KAAU;QAC1B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;IACzB,CAAC;IAED,WAAW,CAAC,KAAU;QACpB,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;IAC1B,CAAC;IAED,WAAW,GAAG,GAAG,EAAE;QACjB,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAA;QACtB,IAAI,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAChC,CAAC,CAAA;IAED,MAAM;QACJ,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACrB,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAG,CAAA;QAC1E,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAA;QAC5B,CAAC;IACH,CAAC;CACF;AAED,SAAS,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAoD;IACrF,MAAM,EAAE,KAAK,EAAE,GAAG,0BAA0B,EAAE,CAAA;IAC9C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,KAAK;YAAE,OAAM;QAElB,OAAO,GAAG,EAAE;YACV,OAAO,EAAE,CAAA;YACT,KAAK,EAAE,CAAA;QACT,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAA;IAEpB,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;QACnC,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAG,CAAA;IAC1E,CAAC;IAED,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,gCAAgC,CAAC,EAAG,CAAA;AACnF,CAAC;AAED,SAAS,iBAAiB,CAAC,EAAE,QAAQ,EAA+C;IAClF,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAA;IAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE;QAC3B,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,GAAG;gBACN,OAAO,qBAAqB,CAAA;YAC9B,KAAK,GAAG;gBACN,OAAO,mBAAmB,CAAA;YAC5B;gBACE,OAAO,OAAO,CAAA;QAClB,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;QACxB,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,GAAG;gBACN,OAAO,wCAAwC,CAAA;YACjD,KAAK,GAAG;gBACN,OAAO,kFAAkF,CAAA;YAC3F;gBACE,OAAO,gCAAgC,CAAA;QAC3C,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAG,CAAA;AACvD,CAAC;AAED,SAAS,YAAY,CAAC,EAAE,OAAO,EAAE,IAAI,EAAqC;IACxE,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAC1B,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAElC,OAAO,CACL,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAC5B;MAAA,CAAC,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAC5E;MAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAC9B;QAAA,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAC1C;UAAA,CAAC,OAAO,CACV;QAAA,EAAE,OAAO,CACT;QAAA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,CACxC;MAAA,EAAE,IAAI,CACN;MAAA,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAC7E;;MACF,EAAE,UAAU,CACZ;MAAA,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EACjF;IAAA,EAAE,IAAI,CAAC,CACR,CAAA;AACH,CAAC;AAED,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAA;IACxB,MAAM,EAAE,MAAM,EAAE,GAAG,iBAAiB,EAAE,CAAA;IACtC,OAAO,UAAU,CAAC,MAAM,CAAC;QACvB,SAAS,EAAE;YACT,IAAI,EAAE,CAAC;YACP,cAAc,EAAE,QAAQ;YACxB,UAAU,EAAE,QAAQ;YACpB,GAAG,EAAE,EAAE;YACP,iBAAiB,EAAE,EAAE;YACrB,aAAa,EAAE,MAAM;SACtB;QACD,WAAW,EAAE;YACX,UAAU,EAAE,QAAQ;YACpB,GAAG,EAAE,CAAC;SACP;QACD,OAAO,EAAE;YACP,SAAS,EAAE,QAAQ;YACnB,UAAU,EAAE,EAAE;SACf;QACD,IAAI,EAAE;YACJ,SAAS,EAAE,QAAQ;YACnB,UAAU,EAAE,EAAE;SACf;QACD,IAAI,EAAE;YACJ,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,wBAAwB;SAC7C;KACF,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,eAAe,aAAa,CAAA","sourcesContent":["import { useNavigation } from '@react-navigation/native'\nimport { useQueryErrorResetBoundary } from '@tanstack/react-query'\nimport React, { PropsWithChildren, useEffect, useMemo } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Button, Heading, Icon, Text, TextButton } from '../display'\nimport { useTheme } from '../../hooks'\nimport { ResponseError } from '../../utils/response_error'\n\ntype ErrorBoundaryState = {\n error: Response | Error | null\n unsubscriber: () => void\n}\n\nclass ErrorBoundary extends React.Component<PropsWithChildren<{ onReset?: () => void }>> {\n state: ErrorBoundaryState = {\n error: null,\n unsubscriber: () => {},\n }\n\n componentDidCatch(error: any) {\n this.handleError(error)\n }\n\n handleError(error: any) {\n this.setState({ error })\n }\n\n handleReset = () => {\n this.props.onReset?.()\n this.setState({ error: null })\n }\n\n render() {\n if (this.state.error) {\n return <ErrorView error={this.state.error} onReset={this.handleReset} />\n } else {\n return this.props.children\n }\n }\n}\n\nfunction ErrorView({ error, onReset }: { error: Error | Response; onReset: () => void }) {\n const { reset } = useQueryErrorResetBoundary()\n useEffect(() => {\n if (!reset) return\n\n return () => {\n onReset()\n reset()\n }\n }, [reset, onReset])\n\n if (error instanceof ResponseError) {\n return <ResponseErrorView response={error.response} onReset={onReset} />\n }\n\n return <ErrorContent heading={'Oops!'} body={'Something unexpected happened.'} />\n}\n\nfunction ResponseErrorView({ response }: { response: Response; onReset: () => void }) {\n const { status } = response\n const heading = useMemo(() => {\n switch (status) {\n case 403:\n return 'Permission required'\n case 404:\n return 'Content not found'\n default:\n return 'Oops!'\n }\n }, [status])\n\n const body = useMemo(() => {\n switch (status) {\n case 403:\n return 'Contact your administrator for access.'\n case 404:\n return 'If you believe something should be here, please reach out to your administrator.'\n default:\n return 'Something unexpected happened.'\n }\n }, [status])\n\n return <ErrorContent heading={heading} body={body} />\n}\n\nfunction ErrorContent({ heading, body }: { heading: string; body: string }) {\n const styles = useStyles()\n const navigation = useNavigation()\n\n return (\n <View style={styles.container}>\n <Icon name=\"general.outlinedTextMessage\" size={32} color={styles.icon.color} />\n <View style={styles.information}>\n <Heading variant=\"h3\" style={styles.heading}>\n {heading}\n </Heading>\n <Text style={styles.body}>{body}</Text>\n </View>\n <TextButton variant=\"tertiary\" onPress={() => navigation.navigate('BugReport')}>\n Report a bug\n </TextButton>\n <Button variant=\"outline\" onPress={navigation.goBack} title=\"Go back\" size=\"md\" />\n </View>\n )\n}\n\nconst useStyles = () => {\n const theme = useTheme()\n const { bottom } = useSafeAreaInsets()\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n gap: 24,\n paddingHorizontal: 16,\n paddingBottom: bottom,\n },\n information: {\n alignItems: 'center',\n gap: 8,\n },\n heading: {\n textAlign: 'center',\n lineHeight: 20,\n },\n body: {\n textAlign: 'center',\n lineHeight: 20,\n },\n icon: {\n color: theme.colors.iconColorDefaultDisabled,\n },\n })\n}\n\nexport default ErrorBoundary\n"]}
1
+ {"version":3,"file":"error_boundary.js","sourceRoot":"","sources":["../../../src/components/page/error_boundary.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useNavigation } from '@react-navigation/native'\nimport { useQueryErrorResetBoundary } from '@tanstack/react-query'\nimport React, { PropsWithChildren, useEffect, useMemo } from 'react'\nimport { StyleSheet, View } from 'react-native'\nimport { useSafeAreaInsets } from 'react-native-safe-area-context'\nimport { Button, Heading, Icon, Text, TextButton } from '../display'\nimport { useTheme } from '../../hooks'\nimport { ResponseError } from '../../utils/response_error'\n\ntype ErrorBoundaryState = {\n error: ResponseError | Error | TypeError | null\n unsubscriber: () => void\n}\n\nclass ErrorBoundary extends React.Component<PropsWithChildren<{ onReset?: () => void }>> {\n state: ErrorBoundaryState = {\n error: null,\n unsubscriber: () => {},\n }\n\n componentDidCatch(error: any) {\n this.handleError(error)\n }\n\n handleError(error: any) {\n this.setState({ error })\n }\n\n handleReset = () => {\n this.props.onReset?.()\n this.setState({ error: null })\n }\n\n render() {\n if (this.state.error) {\n return <ErrorView error={this.state.error} onReset={this.handleReset} />\n } else {\n return this.props.children\n }\n }\n}\n\nfunction ErrorView({ error, onReset }: { error: Error | ResponseError; onReset: () => void }) {\n const { reset } = useQueryErrorResetBoundary()\n useEffect(() => {\n if (!reset) return\n\n return () => {\n onReset()\n reset()\n }\n }, [reset, onReset])\n\n if (error instanceof ResponseError) {\n return <ResponseErrorView response={error.response} onReset={onReset} />\n }\n\n if (isNetworkError(error)) {\n return (\n <ErrorContent\n heading={'Problem connecting!'}\n body={'Check your internet connection and try again.'}\n />\n )\n }\n\n return <ErrorContent heading={'Oops!'} body={'Something unexpected happened.'} />\n}\n\nfunction isNetworkError(error: ResponseError | Error | TypeError | null) {\n const isError = error instanceof Error\n const networkFailedMessages = [\n 'Network request failed',\n 'Network request timed out',\n 'Failed to fetch',\n ]\n\n if (!isError) return false\n\n return new RegExp(networkFailedMessages.join('|'), 'i').test(error.message)\n}\n\nfunction ResponseErrorView({ response }: { response: Response; onReset: () => void }) {\n const { status } = response\n const heading = useMemo(() => {\n switch (status) {\n case 403:\n return 'Permission required'\n case 404:\n return 'Content not found'\n default:\n return 'Oops!'\n }\n }, [status])\n\n const body = useMemo(() => {\n switch (status) {\n case 403:\n return 'Contact your administrator for access.'\n case 404:\n return 'If you believe something should be here, please reach out to your administrator.'\n default:\n return 'Something unexpected happened.'\n }\n }, [status])\n\n return <ErrorContent heading={heading} body={body} />\n}\n\nfunction ErrorContent({ heading, body }: { heading: string; body: string }) {\n const styles = useStyles()\n const navigation = useNavigation()\n\n return (\n <View style={styles.container}>\n <Icon name=\"general.outlinedTextMessage\" size={32} color={styles.icon.color} />\n <View style={styles.information}>\n <Heading variant=\"h3\" style={styles.heading}>\n {heading}\n </Heading>\n <Text style={styles.body}>{body}</Text>\n </View>\n <Button variant=\"outline\" onPress={navigation.goBack} title=\"Go back\" size=\"md\" />\n <TextButton variant=\"tertiary\" onPress={() => navigation.navigate('BugReport')}>\n Report a bug\n </TextButton>\n </View>\n )\n}\n\nconst useStyles = () => {\n const theme = useTheme()\n const { bottom } = useSafeAreaInsets()\n return StyleSheet.create({\n container: {\n flex: 1,\n justifyContent: 'center',\n alignItems: 'center',\n gap: 24,\n paddingHorizontal: 16,\n paddingBottom: bottom,\n },\n information: {\n alignItems: 'center',\n gap: 8,\n },\n heading: {\n textAlign: 'center',\n lineHeight: 20,\n },\n body: {\n textAlign: 'center',\n lineHeight: 20,\n },\n icon: {\n color: theme.colors.iconColorDefaultDisabled,\n },\n })\n}\n\nexport default ErrorBoundary\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@planningcenter/chat-react-native",
3
- "version": "3.11.1",
3
+ "version": "3.11.2-rc.0",
4
4
  "description": "",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -55,5 +55,5 @@
55
55
  "prettier": "^3.4.2",
56
56
  "typescript": "<5.6.0"
57
57
  },
58
- "gitHead": "9f0c1e748906ac5d2811d8182ae6219ed4879d7e"
58
+ "gitHead": "545911ee90ddead23c3a4ab0a4290ff87784d22d"
59
59
  }
@@ -8,7 +8,7 @@ import { useTheme } from '../../hooks'
8
8
  import { ResponseError } from '../../utils/response_error'
9
9
 
10
10
  type ErrorBoundaryState = {
11
- error: Response | Error | null
11
+ error: ResponseError | Error | TypeError | null
12
12
  unsubscriber: () => void
13
13
  }
14
14
 
@@ -40,7 +40,7 @@ class ErrorBoundary extends React.Component<PropsWithChildren<{ onReset?: () =>
40
40
  }
41
41
  }
42
42
 
43
- function ErrorView({ error, onReset }: { error: Error | Response; onReset: () => void }) {
43
+ function ErrorView({ error, onReset }: { error: Error | ResponseError; onReset: () => void }) {
44
44
  const { reset } = useQueryErrorResetBoundary()
45
45
  useEffect(() => {
46
46
  if (!reset) return
@@ -55,9 +55,31 @@ function ErrorView({ error, onReset }: { error: Error | Response; onReset: () =>
55
55
  return <ResponseErrorView response={error.response} onReset={onReset} />
56
56
  }
57
57
 
58
+ if (isNetworkError(error)) {
59
+ return (
60
+ <ErrorContent
61
+ heading={'Problem connecting!'}
62
+ body={'Check your internet connection and try again.'}
63
+ />
64
+ )
65
+ }
66
+
58
67
  return <ErrorContent heading={'Oops!'} body={'Something unexpected happened.'} />
59
68
  }
60
69
 
70
+ function isNetworkError(error: ResponseError | Error | TypeError | null) {
71
+ const isError = error instanceof Error
72
+ const networkFailedMessages = [
73
+ 'Network request failed',
74
+ 'Network request timed out',
75
+ 'Failed to fetch',
76
+ ]
77
+
78
+ if (!isError) return false
79
+
80
+ return new RegExp(networkFailedMessages.join('|'), 'i').test(error.message)
81
+ }
82
+
61
83
  function ResponseErrorView({ response }: { response: Response; onReset: () => void }) {
62
84
  const { status } = response
63
85
  const heading = useMemo(() => {
@@ -98,10 +120,10 @@ function ErrorContent({ heading, body }: { heading: string; body: string }) {
98
120
  </Heading>
99
121
  <Text style={styles.body}>{body}</Text>
100
122
  </View>
123
+ <Button variant="outline" onPress={navigation.goBack} title="Go back" size="md" />
101
124
  <TextButton variant="tertiary" onPress={() => navigation.navigate('BugReport')}>
102
125
  Report a bug
103
126
  </TextButton>
104
- <Button variant="outline" onPress={navigation.goBack} title="Go back" size="md" />
105
127
  </View>
106
128
  )
107
129
  }