1745 wystapien w 291 plikach (backend, scripts, mobile). Dominowal jeden ksztalt, ' — ' laczace zdania, wiec poszedl przecinek; myslnik otwierajacy mysl zdjety; zakresy 0–5 i A–Z na dywiz. Podzial komentarz/kod robil skaner stanow, nie regex, zeby nie ruszyc myslnika stojacego w stringu albo w wyrazeniu regularnym. Potwierdzone maszynowo: po wycieciu komentarzy z wersji HEAD i z dysku obie sa identyczne we wszystkich 291 plikach, czyli poza komentarzami nie zmienilo sie nic. 233 pliki .py parsuja sie bez bledu, tsc ma te same 11 bledow w tych samych 3 plikach co przed zmiana. Dwie rzeczy wymagaly poprawki po automacie: wyrownane listy definicji, gdzie myslnik byl separatorem kolumny (37 miejsc, kolumna przywrocona), i trzy przeniesienia mysli do nowej linii, gdzie zostawal wiszacy przecinek na poczatku (poprawione recznie). Bundla nie republikuje: Hermes i tak nie niesie komentarzy, wiec dla uzytkownika to zero zmiany. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
80 lines
2.5 KiB
TypeScript
80 lines
2.5 KiB
TypeScript
import * as Sentry from '@sentry/react-native';
|
|
import React from 'react';
|
|
import { ScrollView, StyleSheet, Text, View } from 'react-native';
|
|
import { theme } from './theme';
|
|
|
|
interface Props {
|
|
children: React.ReactNode;
|
|
/** Opcjonalny tag wysyłany do Sentry, pomaga rozróżnić top-level boundary od lokalnych. */
|
|
scope?: string;
|
|
}
|
|
|
|
interface State {
|
|
error: Error | null;
|
|
info: string | null;
|
|
}
|
|
|
|
export class ErrorBoundary extends React.Component<Props, State> {
|
|
state: State = { error: null, info: null };
|
|
|
|
static getDerivedStateFromError(error: Error): State {
|
|
return { error, info: null };
|
|
}
|
|
|
|
componentDidCatch(error: Error, info: React.ErrorInfo): void {
|
|
this.setState({ error, info: info.componentStack || null });
|
|
// Sentry.wrap()-owy boundary łapie tylko jeśli root nie jest manuanle wrapped.
|
|
// Dodajemy explicit capture żeby ten boundary też wysyłał, z tagiem `scope`
|
|
// żebyśmy w UI Sentry odróżnili global crash od per-tab crash.
|
|
Sentry.captureException(error, {
|
|
tags: { boundary: this.props.scope || 'global' },
|
|
contexts: { react: { componentStack: info.componentStack } },
|
|
});
|
|
// eslint-disable-next-line no-console
|
|
console.error('App crashed:', error, info);
|
|
}
|
|
|
|
render() {
|
|
if (this.state.error) {
|
|
return (
|
|
<ScrollView style={styles.container} contentContainerStyle={{ padding: 20 }}>
|
|
<Text style={styles.title}>App crashed</Text>
|
|
<Text style={styles.label}>Error</Text>
|
|
<Text style={styles.body}>{this.state.error.name}: {this.state.error.message}</Text>
|
|
{this.state.error.stack ? (
|
|
<>
|
|
<Text style={styles.label}>Stack</Text>
|
|
<Text style={styles.code}>{this.state.error.stack}</Text>
|
|
</>
|
|
) : null}
|
|
{this.state.info ? (
|
|
<>
|
|
<Text style={styles.label}>Component stack</Text>
|
|
<Text style={styles.code}>{this.state.info}</Text>
|
|
</>
|
|
) : null}
|
|
</ScrollView>
|
|
);
|
|
}
|
|
return <>{this.props.children}</>;
|
|
}
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
container: { flex: 1, backgroundColor: theme.bg },
|
|
title: { color: theme.bad, fontSize: 24, fontWeight: '700', marginBottom: 16 },
|
|
label: {
|
|
color: theme.muted,
|
|
fontSize: 12,
|
|
textTransform: 'uppercase',
|
|
letterSpacing: 0.6,
|
|
marginTop: 16,
|
|
marginBottom: 4,
|
|
},
|
|
body: { color: theme.fg, fontSize: 14 },
|
|
code: {
|
|
color: theme.fg,
|
|
fontSize: 11,
|
|
fontFamily: 'monospace',
|
|
},
|
|
});
|