diff --git a/lib/services/metadata/metadata_edit_service.dart b/lib/services/metadata/metadata_edit_service.dart index ec3d48bac..4eeecbfed 100644 --- a/lib/services/metadata/metadata_edit_service.dart +++ b/lib/services/metadata/metadata_edit_service.dart @@ -6,8 +6,10 @@ import 'package:aves/model/entry/extensions/props.dart'; import 'package:aves/model/metadata/date_modifier.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves_model/aves_model.dart'; +import 'package:aves_report/aves_report.dart'; import 'package:collection/collection.dart'; import 'package:flutter/services.dart'; +import 'package:stack_trace/stack_trace.dart'; abstract class MetadataEditService { Future> rotate(AvesEntry entry, {required bool clockwise}); @@ -125,44 +127,52 @@ class PlatformMetadataEditService implements MetadataEditService { Future _processPlatformException(AvesEntry entry, PlatformException e, StackTrace stack) async { if (entry.isValid) { final code = e.code; + final customException = CustomPlatformException.fromStandard(e); if (code.endsWith('mp4largemoov')) { - await reportService.recordError(_Mp4LargeMoovException(code: e.code, message: e.message, details: e.details, stacktrace: e.stacktrace), stack); + await mp4LargeMoov(customException); } else if (code.endsWith('mp4largeother')) { - await reportService.recordError(_Mp4LargeOtherException(code: e.code, message: e.message, details: e.details, stacktrace: e.stacktrace), stack); + await mp4LargeOther(customException); } else if (code.endsWith('filenotfound')) { - await reportService.recordError(_FileNotFoundException(code: e.code, message: e.message, details: e.details, stacktrace: e.stacktrace), stack); + await fileNotFound(customException); } else { await reportService.recordError(e, stack); } } } + + StackTrace? _currentStack() => ReportService.buildReportStack(Trace.current(), level: 1); + + // distinct exceptions to convince Crashlytics to split reports into distinct issues + + Future mp4LargeMoov(CustomPlatformException e) => reportService.recordError(e, _currentStack()); + + Future mp4LargeOther(CustomPlatformException e) => reportService.recordError(e, _currentStack()); + + Future fileNotFound(CustomPlatformException e) => reportService.recordError(e, _currentStack()); } -// distinct exceptions to convince Crashlytics to split reports into distinct issues +class CustomPlatformException { + final String code; + final String? message; + final dynamic details; + final String? stacktrace; -class _Mp4LargeMoovException extends PlatformException { - _Mp4LargeMoovException({ - required super.code, - required super.message, - required super.details, - required super.stacktrace, + CustomPlatformException({ + required this.code, + this.message, + this.details, + this.stacktrace, }); -} -class _Mp4LargeOtherException extends PlatformException { - _Mp4LargeOtherException({ - required super.code, - required super.message, - required super.details, - required super.stacktrace, - }); -} + factory CustomPlatformException.fromStandard(PlatformException e) { + return CustomPlatformException( + code: e.code, + message: e.message, + details: e.details, + stacktrace: e.stacktrace, + ); + } -class _FileNotFoundException extends PlatformException { - _FileNotFoundException({ - required super.code, - required super.message, - required super.details, - required super.stacktrace, - }); + @override + String toString() => '$runtimeType($code, $message, $details, $stacktrace)'; } diff --git a/plugins/aves_report/lib/aves_report.dart b/plugins/aves_report/lib/aves_report.dart index 5c0cf8999..4675cf2b0 100644 --- a/plugins/aves_report/lib/aves_report.dart +++ b/plugins/aves_report/lib/aves_report.dart @@ -1,6 +1,8 @@ library aves_report; +import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; +import 'package:stack_trace/stack_trace.dart'; abstract class ReportService { Future init(); @@ -18,4 +20,18 @@ abstract class ReportService { Future recordError(dynamic exception, StackTrace? stack); Future recordFlutterError(FlutterErrorDetails flutterErrorDetails); + + static StackTrace? buildReportStack(StackTrace stack, {int level = 0}) { + // simply creating a trace with `Trace.current(1)` or creating a `Trace` from modified frames + // does not yield a stack trace that Crashlytics can segment, + // so we reconstruct a string stack trace instead + return StackTrace.fromString(Trace.from(stack) + .frames + .skip(level) + .toList() + .mapIndexed( + (i, f) => '#${(i++).toString().padRight(8)}${f.member} (${f.uri}:${f.line}:${f.column})', + ) + .join('\n')); + } } diff --git a/plugins/aves_report/pubspec.lock b/plugins/aves_report/pubspec.lock index 65a37f405..78b846b96 100644 --- a/plugins/aves_report/pubspec.lock +++ b/plugins/aves_report/pubspec.lock @@ -10,7 +10,7 @@ packages: source: hosted version: "1.3.0" collection: - dependency: transitive + dependency: "direct main" description: name: collection sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" @@ -62,11 +62,27 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + stack_trace: + dependency: "direct main" + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" vector_math: dependency: transitive description: diff --git a/plugins/aves_report/pubspec.yaml b/plugins/aves_report/pubspec.yaml index 60ad239de..ea3090164 100644 --- a/plugins/aves_report/pubspec.yaml +++ b/plugins/aves_report/pubspec.yaml @@ -8,6 +8,8 @@ environment: dependencies: flutter: sdk: flutter + collection: + stack_trace: dev_dependencies: flutter_lints: diff --git a/plugins/aves_report_crashlytics/lib/aves_report_platform.dart b/plugins/aves_report_crashlytics/lib/aves_report_platform.dart index cc501c381..67fd00aec 100644 --- a/plugins/aves_report_crashlytics/lib/aves_report_platform.dart +++ b/plugins/aves_report_crashlytics/lib/aves_report_platform.dart @@ -3,12 +3,10 @@ library aves_report_platform; import 'dart:async'; import 'package:aves_report/aves_report.dart'; -import 'package:collection/collection.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; -import 'package:stack_trace/stack_trace.dart'; class PlatformReportService extends ReportService { FirebaseCrashlytics? get _instance { @@ -71,17 +69,7 @@ class PlatformReportService extends ReportService { @override Future recordError(dynamic exception, StackTrace? stack) async { if (exception is PlatformException && stack != null) { - // simply creating a trace with `Trace.current(1)` or creating a `Trace` from modified frames - // does not yield a stack trace that Crashlytics can segment, - // so we reconstruct a string stack trace instead - stack = StackTrace.fromString(Trace.from(stack) - .frames - .skip(2) - .toList() - .mapIndexed( - (i, f) => '#${(i++).toString().padRight(8)}${f.member} (${f.uri}:${f.line}:${f.column})', - ) - .join('\n')); + stack = ReportService.buildReportStack(stack, level: 2); } return _instance?.recordError(exception, stack); } diff --git a/plugins/aves_report_crashlytics/pubspec.lock b/plugins/aves_report_crashlytics/pubspec.lock index c16f93235..18085d21c 100644 --- a/plugins/aves_report_crashlytics/pubspec.lock +++ b/plugins/aves_report_crashlytics/pubspec.lock @@ -49,7 +49,7 @@ packages: source: hosted version: "1.1.1" collection: - dependency: "direct main" + dependency: transitive description: name: collection sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" @@ -197,7 +197,7 @@ packages: source: hosted version: "1.9.1" stack_trace: - dependency: "direct main" + dependency: transitive description: name: stack_trace sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 diff --git a/plugins/aves_report_crashlytics/pubspec.yaml b/plugins/aves_report_crashlytics/pubspec.yaml index acaa8bdca..9186c9e74 100644 --- a/plugins/aves_report_crashlytics/pubspec.yaml +++ b/plugins/aves_report_crashlytics/pubspec.yaml @@ -10,12 +10,10 @@ dependencies: sdk: flutter aves_report: path: ../aves_report - collection: # as of `firebase_core` v2.10.0, upgrading packages downgrades `firebase_core` et al. # so that the transitive `path` gets upgraded to v1.8.3 firebase_core: ">=2.10.0" firebase_crashlytics: - stack_trace: dev_dependencies: flutter_lints: diff --git a/pubspec.lock b/pubspec.lock index 493185d63..8c6087c05 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1283,7 +1283,7 @@ packages: source: hosted version: "2.4.5" stack_trace: - dependency: transitive + dependency: "direct main" description: name: stack_trace sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 diff --git a/pubspec.yaml b/pubspec.yaml index 5fb272b2c..284ce2f78 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -108,6 +108,7 @@ dependencies: shared_preferences: smooth_page_indicator: sqflite: + stack_trace: streams_channel: git: url: https://github.com/deckerst/aves_streams_channel.git