-
Notifications
You must be signed in to change notification settings - Fork 25
/
index.js
143 lines (126 loc) · 4.7 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// @flow
// React Native doesn't have a functional URL as of Feb 2024
import "react-native-url-polyfill/auto";
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
import { NavigationContainer } from "@react-navigation/native";
import {
QueryClient,
QueryClientProvider
} from "@tanstack/react-query";
import App from "components/App";
import ErrorBoundary from "components/ErrorBoundary";
import initI18next from "i18n/initI18next";
import { t } from "i18next";
import inatjs from "inaturalistjs";
import INatPaperProvider from "providers/INatPaperProvider";
import RealmProvider from "providers/RealmProvider";
import React from "react";
import { Alert, AppRegistry } from "react-native";
import Config from "react-native-config";
import { setJSExceptionHandler, setNativeExceptionHandler } from "react-native-exception-handler";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import { startNetworkLogging } from "react-native-network-logger";
import { SafeAreaProvider } from "react-native-safe-area-context";
import { getInstallID } from "sharedHelpers/installData.ts";
import { reactQueryRetry } from "sharedHelpers/logging";
import { name as appName } from "./app.json";
import { log } from "./react-native-logs.config";
import { getUserAgent } from "./src/api/userAgent";
import { navigationRef } from "./src/navigation/navigationUtils";
const logger = log.extend( "index.js" );
// Log all unhandled promise rejections in release builds. Otherwise they will
// die in silence. Debug builds have a more useful UI w/ desymbolicated stack
// traces
/* eslint-disable no-undef */
if (
!__DEV__
&& typeof (
// $FlowIgnore
HermesInternal?.enablePromiseRejectionTracker === "function"
)
) {
// $FlowIgnore
HermesInternal.enablePromiseRejectionTracker( {
allRejections: true,
onUnhandled: ( id, error ) => {
logger.error( "Unhandled promise rejection: ", error );
}
} );
}
/* eslint-enable no-undef */
// I'm not convinced this ever catches anything... ~~~kueda 20240110
const jsErrorHandler = ( e, isFatal ) => {
if ( e?.message?.match( /No space left on device/ ) ) {
Alert.alert(
"Device-storage-full",
"iNaturalist may not be able to save your photos or may crash.",
[{ text: t( "OK" ) }]
);
}
// not 100% sure why jsErrorHandler logs e.name and e.message as undefined sometimes,
// but I believe it relates to this issue, which reports an unnecessary console.error
// under the hood: https://github.com/a7ul/react-native-exception-handler/issues/143
// possibly also related to error boundaries in React 16+:
// https://github.com/a7ul/react-native-exception-handler/issues/60
// if ( !e.name && !e.message ) return;
if ( isFatal ) {
logger.error( "Fatal JS Error: ", e );
Alert.alert( "D'OH", `${e.message}\n\n${e.stack}` );
} else {
// This should get logged by ErrorBoundary. For some reason this handler
// gets called too, so we don't want to double-report errors
}
};
// record JS exceptions; second parameter allows this to work in DEV mode
setJSExceptionHandler( jsErrorHandler, true );
// record native exceptions
// only works in bundled mode; will show red screen in dev mode
// tested this by raising an exception in RNGestureHandler.m
// https://stackoverflow.com/questions/63270492/how-to-raise-native-error-in-react-native-app
// https://github.com/a7ul/react-native-exception-handler#react-native-navigation-wix
setNativeExceptionHandler( exceptionString => {
logger.error( `Native Error: ${exceptionString}` );
}, false );
// Only in debug builds
// eslint-disable-next-line no-undef
if ( __DEV__ ) {
startNetworkLogging();
}
initI18next();
// Configure inatjs to use the chosen URLs
inatjs.setConfig( {
apiURL: Config.API_URL,
writeApiURL: Config.API_URL,
userAgent: getUserAgent(),
headers: {
"X-Installation-ID": getInstallID( )
}
} );
const queryClient = new QueryClient( {
defaultOptions: {
queries: {
retry: reactQueryRetry
}
}
} );
const AppWithProviders = ( ) => (
<QueryClientProvider client={queryClient}>
<RealmProvider>
<SafeAreaProvider>
<INatPaperProvider>
<GestureHandlerRootView className="flex-1">
<BottomSheetModalProvider>
{/* NavigationContainer needs to be nested above ObsEditProvider */}
<NavigationContainer ref={navigationRef}>
<ErrorBoundary>
<App />
</ErrorBoundary>
</NavigationContainer>
</BottomSheetModalProvider>
</GestureHandlerRootView>
</INatPaperProvider>
</SafeAreaProvider>
</RealmProvider>
</QueryClientProvider>
);
AppRegistry.registerComponent( appName, ( ) => AppWithProviders );