diff --git a/apps/mobile/components/ErrorBoundary.tsx b/apps/mobile/components/ErrorBoundary.tsx new file mode 100644 index 0000000..fd0452b --- /dev/null +++ b/apps/mobile/components/ErrorBoundary.tsx @@ -0,0 +1,68 @@ +import React from 'react'; +import { Pressable, StyleSheet, Text, View } from 'react-native'; + +// Catch render errors anywhere below this boundary and show a readable +// fallback. Without it, a thrown error during render produces a white +// screen on TestFlight / production builds with no way for the user to +// recover short of force-closing the app. Mounted once at the top of +// app/_layout.tsx so it wraps every screen. + +interface Props { + children: React.ReactNode; +} + +interface State { + error: Error | null; +} + +export class ErrorBoundary extends React.Component { + state: State = { error: null }; + + static getDerivedStateFromError(error: Error): State { + return { error }; + } + + componentDidCatch(error: Error, info: React.ErrorInfo): void { + // Bubble to Metro/console in dev so the redbox still shows; in prod + // builds this is the only place an exception trace surfaces. + console.error('[ErrorBoundary] caught render error', error, info.componentStack); + } + + reset = (): void => { + this.setState({ error: null }); + }; + + render(): React.ReactNode { + if (this.state.error) { + return ( + + Etwas ist schiefgelaufen + {this.state.error.message} + + Erneut versuchen + + + ); + } + return this.props.children; + } +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + backgroundColor: '#0b0b0f', + padding: 24, + }, + title: { color: '#fff', fontSize: 22, fontWeight: '600', marginBottom: 8 }, + message: { color: '#9ca3af', textAlign: 'center', marginBottom: 24 }, + button: { + backgroundColor: '#5865f2', + paddingHorizontal: 20, + paddingVertical: 12, + borderRadius: 10, + }, + buttonText: { color: '#fff', fontWeight: '600' }, +});