73 lines
		
	
	
	
		
			1.9 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			73 lines
		
	
	
	
		
			1.9 KiB
			
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
// Copyright 2025 Signal Messenger, LLC
 | 
						|
// SPDX-License-Identifier: AGPL-3.0-only
 | 
						|
import type { ReactNode, ErrorInfo } from 'react';
 | 
						|
import React, { Component, useCallback } from 'react';
 | 
						|
import { createLogger } from '../logging/log.js';
 | 
						|
import * as Errors from '../types/errors.js';
 | 
						|
 | 
						|
const log = createLogger('DonationsErrorBoundary');
 | 
						|
 | 
						|
type ErrorBoundaryProps = Readonly<{
 | 
						|
  children: ReactNode;
 | 
						|
  onError: (error: unknown, info: ErrorInfo) => void;
 | 
						|
  fallback: (error: unknown) => ReactNode;
 | 
						|
}>;
 | 
						|
 | 
						|
type ErrorBoundaryState = {
 | 
						|
  caught?: { error: unknown };
 | 
						|
};
 | 
						|
 | 
						|
class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
 | 
						|
  // eslint-disable-next-line react/state-in-constructor
 | 
						|
  override state: ErrorBoundaryState = {};
 | 
						|
 | 
						|
  static getDerivedStateFromError(error: unknown) {
 | 
						|
    return { caught: { error } };
 | 
						|
  }
 | 
						|
 | 
						|
  override componentDidCatch(error: unknown, info: ErrorInfo) {
 | 
						|
    this.props.onError(error, info);
 | 
						|
  }
 | 
						|
 | 
						|
  override render() {
 | 
						|
    if (this.state.caught != null) {
 | 
						|
      return this.props.fallback(this.state.caught.error);
 | 
						|
    }
 | 
						|
 | 
						|
    return this.props.children;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export type DonationsErrorBoundaryProps = Readonly<{
 | 
						|
  children: ReactNode;
 | 
						|
}>;
 | 
						|
 | 
						|
export function DonationsErrorBoundary(
 | 
						|
  props: DonationsErrorBoundaryProps
 | 
						|
): JSX.Element {
 | 
						|
  const fallback = useCallback(() => {
 | 
						|
    return <div className="DonationsErrorBoundary" />;
 | 
						|
  }, []);
 | 
						|
 | 
						|
  const handleError = useCallback((error: unknown, info: ErrorInfo) => {
 | 
						|
    log.error(
 | 
						|
      'DonationsErrorBoundary: Caught error',
 | 
						|
      Errors.toLogFormat(error),
 | 
						|
      info.componentStack
 | 
						|
    );
 | 
						|
 | 
						|
    if (window.reduxActions) {
 | 
						|
      window.reduxActions.globalModals.showDebugLogErrorModal({
 | 
						|
        description: window.i18n(
 | 
						|
          'icu:DonationsErrorBoundary__DonationUnexpectedError'
 | 
						|
        ),
 | 
						|
      });
 | 
						|
    }
 | 
						|
  }, []);
 | 
						|
 | 
						|
  return (
 | 
						|
    <ErrorBoundary fallback={fallback} onError={handleError}>
 | 
						|
      {props.children}
 | 
						|
    </ErrorBoundary>
 | 
						|
  );
 | 
						|
}
 |