Skip to content

Commit

Permalink
Use new PlatformDispatcher onError method if available
Browse files Browse the repository at this point in the history
  • Loading branch information
matux committed Aug 2, 2023
1 parent daba1fc commit 1f5a479
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import 'package:flutter/foundation.dart';
import 'package:meta/meta.dart';

import 'package:rollbar_common/rollbar_common.dart';
import 'package:rollbar_dart/rollbar.dart';

import 'extension/diagnostics.dart';
import '../extension/diagnostics.dart';
import 'hook.dart';

extension RollbarFlutterError on FlutterError {
/// Called whenever the Flutter framework catches an error.
///
/// The default behavior is to call [presentError].
static void onError(FlutterErrorDetails error) {
@sealed
class FlutterHook implements Hook {
FlutterExceptionHandler? _originalOnError;

void onError(FlutterErrorDetails error) {
if (!error.silent) {
Rollbar.drop(
Breadcrumb.error(
Expand All @@ -27,6 +29,22 @@ extension RollbarFlutterError on FlutterError {
Rollbar.error(error.exception, error.stack ?? StackTrace.empty);
}

FlutterError.presentError(error);
if (_originalOnError != null) {
_originalOnError!(error);
}
}

@override
void install(_) {
_originalOnError = FlutterError.onError;
FlutterError.onError = onError;
}

@override
void uninstall() {
if (FlutterError.onError == onError) {
FlutterError.onError = _originalOnError;
_originalOnError = null;
}
}
}
9 changes: 9 additions & 0 deletions rollbar_flutter/lib/src/hooks/hook.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'dart:async';

import 'package:rollbar_dart/rollbar.dart';

abstract class Hook {
FutureOr<void> install(final Config config);

FutureOr<void> uninstall();
}
34 changes: 34 additions & 0 deletions rollbar_flutter/lib/src/hooks/platform_hook.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'dart:ui';
import 'package:rollbar_dart/rollbar.dart';
import 'hook.dart';

class PlatformHook implements Hook {
ErrorCallback? _originalOnError;
PlatformDispatcher? _platformDispatcher;

bool onError(Object exception, StackTrace stackTrace) {
Rollbar.error(exception, stackTrace);

if (_originalOnError != null) {
return _originalOnError!(exception, stackTrace);
}

return false;
}

@override
void install(_) {
_platformDispatcher = PlatformDispatcher.instance;
_originalOnError = _platformDispatcher?.onError;
_platformDispatcher?.onError = onError;
}

@override
void uninstall() {
if (_platformDispatcher?.onError == onError) {
_platformDispatcher?.onError = _originalOnError;
_originalOnError = null;
_platformDispatcher = null;
}
}
}
48 changes: 28 additions & 20 deletions rollbar_flutter/lib/src/rollbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import 'package:meta/meta.dart';

import 'package:rollbar_dart/rollbar.dart';

import 'flutter_error.dart';
import 'hooks/hook.dart';
import 'hooks/flutter_hook.dart';
import 'hooks/platform_hook.dart';
import 'platform_transformer.dart';

extension _Methods on MethodChannel {
Expand All @@ -22,48 +24,54 @@ extension _Methods on MethodChannel {
typedef RollbarClosure = FutureOr<void> Function();

@sealed
@immutable
class RollbarFlutter {
static const _platform = MethodChannel('com.rollbar.flutter');

RollbarFlutter._();
const RollbarFlutter._();

static Future<void> run(
Config config,
RollbarClosure appRunner,
) async {
if (!config.handleUncaughtErrors) {
WidgetsFlutterBinding.ensureInitialized();

await _run(config, appRunner, null);

return;
await _run(config, appRunner);
} else if (requiresCustomZone) {
await runZonedGuarded(
() async => await _run(config, appRunner, [FlutterHook()]),
Rollbar.error);
} else {
await _run(config, appRunner, [FlutterHook(), PlatformHook()]);
}

await runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();

await _run(config, appRunner, RollbarFlutterError.onError);
}, (exception, stackTrace) {
Rollbar.error(exception, stackTrace);
});
}

static Future<void> _run(
Config config,
RollbarClosure appRunner,
FlutterExceptionHandler? onError,
) async {
RollbarClosure appRunner, [
List<Hook> hooks = const [],
]) async {
WidgetsFlutterBinding.ensureInitialized();

await Rollbar.run(config.copyWith(
framework: 'flutter',
persistencePath: await _platform.persistencePath,
transformer: (_) => PlatformTransformer(),
));

if (onError != null) {
FlutterError.onError = onError;
for (final hook in hooks) {
await hook.install(config);
}

await _platform.initialize(config: config);
await appRunner();
}

static bool get requiresCustomZone {
try {
(PlatformDispatcher.instance as dynamic)?.onError;
return false;
} on NoSuchMethodError {
return true;
}
}
}

0 comments on commit 1f5a479

Please sign in to comment.