Skip to content

Commit 6cd72bf

Browse files
authored
Merge pull request #48 from Dip123Das/fix/mobile-recovery-diagnostics
Add safe startup recovery diagnostics
2 parents c73f22e + e6ffa47 commit 6cd72bf

1 file changed

Lines changed: 22 additions & 9 deletions

File tree

‎apps/mobile/src/features/recovery/AppRecoveryBoundary.tsx‎

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,33 @@ import { SafeAreaView } from "react-native-safe-area-context";
77
import { colors, radii, spacing, typography } from "@/theme/tokens";
88

99
type Props = { children: ReactNode };
10-
type State = { failed: boolean; recoveryFailed: boolean };
10+
type State = { failed: boolean; recoveryFailed: boolean; failureArea: string; errorKind: string };
11+
12+
const SAFE_ERROR_KINDS = new Set(["Error", "TypeError", "ReferenceError", "SyntaxError", "RangeError", "URIError", "EvalError"]);
13+
const SAFE_COMPONENTS = ["AuthGatewayScreen", "IndexRoute", "AuthProvider", "ScreenCaptureProtection", "DeviceReauthenticationProvider", "AppPrivacyShield", "NotificationResponseProvider", "RootLayout"] as const;
14+
15+
function safeErrorKind(error: Error) {
16+
return SAFE_ERROR_KINDS.has(error.name) ? error.name : "UnknownError";
17+
}
18+
19+
function safeFailureArea(componentStack: string | null | undefined) {
20+
return SAFE_COMPONENTS.find((name) => componentStack?.includes(name)) ?? "OtherAppComponent";
21+
}
1122

1223
export class AppRecoveryBoundary extends Component<Props, State> {
13-
state: State = { failed: false, recoveryFailed: false };
24+
state: State = { failed: false, recoveryFailed: false, failureArea: "", errorKind: "" };
1425

15-
static getDerivedStateFromError(): State {
16-
return { failed: true, recoveryFailed: false };
26+
static getDerivedStateFromError(error: Error): State {
27+
return { failed: true, recoveryFailed: false, failureArea: "", errorKind: safeErrorKind(error) };
1728
}
1829

19-
componentDidCatch(_error: Error, _info: ErrorInfo) {
20-
// Deliberately do not render, persist or transmit raw errors, stack traces,
21-
// session material, identity facts or business data from this boundary.
30+
componentDidCatch(_error: Error, info: ErrorInfo) {
31+
// Show only allowlisted code component names and JavaScript error classes.
32+
// Never render, persist or transmit raw errors, stack traces or user data.
33+
this.setState({ failureArea: safeFailureArea(info.componentStack) });
2234
}
2335

24-
private retry = () => this.setState({ failed: false, recoveryFailed: false });
36+
private retry = () => this.setState({ failed: false, recoveryFailed: false, failureArea: "", errorKind: "" });
2537

2638
private reload = async () => {
2739
try {
@@ -44,7 +56,8 @@ export class AppRecoveryBoundary extends Component<Props, State> {
4456
<Pressable accessibilityLabel="Try this screen again" accessibilityRole="button" onPress={this.retry} style={styles.primary}><Text style={styles.primaryText}>Try again</Text></Pressable>
4557
<Pressable accessibilityLabel="Reload the 3Bigha app" accessibilityRole="button" onPress={() => void this.reload()} style={styles.secondary}><Text style={styles.secondaryText}>Reload app</Text></Pressable>
4658
{this.state.recoveryFailed ? <Text accessibilityLiveRegion="polite" style={styles.warning}>Automatic reload is unavailable. Close and reopen 3Bigha when convenient.</Text> : null}
47-
<Text style={styles.meta}>Version {version} · {channel}</Text>
59+
<Text style={styles.meta}>Build {Application.nativeBuildVersion || "unknown"} · Version {version} · {channel}</Text>
60+
{this.state.failureArea ? <Text accessibilityLabel="Safe diagnostic details" style={styles.note}>Diagnostic: {this.state.failureArea} · {this.state.errorKind}</Text> : null}
4861
<Text style={styles.note}>No personal details, access tokens, raw error messages or stack traces are shown or stored here.</Text>
4962
</View></SafeAreaView>;
5063
}

0 commit comments

Comments
 (0)