diff --git a/CHANGELOG.md b/CHANGELOG.md index c9d7284..ed3353d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## [1.2.0] + +* add flutterError view + ## [1.1.1-nullsafety.3] * fix context error. diff --git a/example/lib/main.dart b/example/lib/main.dart index 7cc78d9..e3c8a38 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -3,6 +3,11 @@ import 'package:flutter/material.dart'; import 'package:power_logger/power_logger.dart'; void main() { + WidgetsFlutterBinding.ensureInitialized(); + FlutterError.onError = (details) { + LoggerData.addData(details); + FlutterError.presentError(details); + }; runApp(MyApp()); } @@ -44,6 +49,8 @@ class _MyHomePageState extends State { bool loading = false; + String? nullableValue; + @override void dispose() { _textController.dispose(); @@ -56,15 +63,24 @@ class _MyHomePageState extends State { appBar: AppBar( title: Text(widget.title), ), - body: Container( - padding: EdgeInsets.all(10), - alignment: Alignment.center, - child: TextField( - controller: _textController, - decoration: InputDecoration( - filled: true, + body: Column( + children: [ + TextButton( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute(builder: (context) => Text(nullableValue!)), + ); + }, + child: Text('FAIL PAGE'), + ), + TextField( + controller: _textController, + decoration: InputDecoration( + filled: true, + ), ), - ), + ], ), floatingActionButton: FloatingActionButton.extended( icon: loading diff --git a/example/pubspec.lock b/example/pubspec.lock index 0a00903..457fab7 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -5,84 +5,84 @@ packages: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.0" auto_size_text: dependency: transitive description: name: auto_size_text - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0-nullsafety.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.15.0" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.2" device_info: dependency: transitive description: name: device_info - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" device_info_platform_interface: dependency: transitive description: name: device_info_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.1" dio: dependency: "direct main" description: name: dio - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.0.0" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" flutter: @@ -94,7 +94,7 @@ packages: dependency: transitive description: name: flutter_highlight - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.0" flutter_test: @@ -106,63 +106,63 @@ packages: dependency: "direct main" description: name: get - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.1.4" highlight: dependency: transitive description: name: highlight - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.0" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.0.0" logger: dependency: transitive description: name: logger - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.12.10" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" package_info: dependency: transitive description: name: package_info - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.8.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" power_logger: @@ -171,7 +171,7 @@ packages: path: ".." relative: true source: path - version: "1.1.1-nullsafety.3" + version: "1.2.0" sky_engine: dependency: transitive description: flutter @@ -181,56 +181,56 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.8.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.19" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" sdks: diff --git a/lib/src/builders/dio_error_builder.dart b/lib/src/builders/dio_error_builder.dart index cd2e8af..152332a 100644 --- a/lib/src/builders/dio_error_builder.dart +++ b/lib/src/builders/dio_error_builder.dart @@ -3,86 +3,43 @@ import 'package:flutter/material.dart'; import 'package:power_logger/src/view/dio_error_view.dart'; ///Dio Error builder -class DioErrorBuilder extends StatefulWidget { +class DioErrorBuilder extends StatelessWidget { final DioError data; final DateTime date; DioErrorBuilder({Key? key, required this.data, required this.date}) : super(key: key); - @override - _DioErrorBuilderState createState() => _DioErrorBuilderState(); -} - -class _DioErrorBuilderState extends State { - RequestOptions get _request => widget.data.requestOptions; - - String renderErrText(DioErrorType type) { - switch (type) { - case DioErrorType.connectTimeout: - return '连接超时'; - case DioErrorType.sendTimeout: - return '发送超时'; - case DioErrorType.receiveTimeout: - return '接收超时'; - case DioErrorType.response: - return '服务端错误'; - case DioErrorType.cancel: - return '取消连接'; - case DioErrorType.other: - return '未知错误'; - } - } - @override Widget build(BuildContext context) { - return Material( - color: Colors.red[100], - child: Column( + return ListTile( + tileColor: Colors.red.withOpacity(0.2), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DioErrorView(data: data), + ), + ); + }, + title: Text( + data.requestOptions.path, + style: TextStyle( + color: Colors.black87, + ), + ), + subtitle: Text( + '${data.message}\n$date', + style: TextStyle( + color: Colors.black45, + fontWeight: FontWeight.w300, + ), + ), + trailing: Row( mainAxisSize: MainAxisSize.min, children: [ - ListTile( - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => DioErrorView(data: widget.data), - ), - ); - }, - title: Text( - _request.path, - style: TextStyle( - color: Colors.black87, - ), - ), - subtitle: Text( - '${widget.data.message}\n${widget.date}', - style: TextStyle( - color: Colors.black45, - fontWeight: FontWeight.w300, - ), - ), - trailing: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Chip( - backgroundColor: Colors.green.withOpacity(0.8), - label: Text(_request.method), - ), - ], - ), - ), - Row( - children: [ - SizedBox(width: 24), - Text(widget.data.type.toString()), - Spacer(), - Chip( - backgroundColor: Colors.red.withOpacity(0.3), - label: Text(renderErrText(widget.data.type)), - ), - SizedBox(width: 24), - ], + Chip( + backgroundColor: Colors.blue.withOpacity(0.8), + label: Text(data.requestOptions.method), ), ], ), diff --git a/lib/src/builders/dio_responses_builder.dart b/lib/src/builders/dio_responses_builder.dart index 154d0d3..1b591ac 100644 --- a/lib/src/builders/dio_responses_builder.dart +++ b/lib/src/builders/dio_responses_builder.dart @@ -3,48 +3,37 @@ import 'package:flutter/material.dart'; import 'package:power_logger/src/view/dio_response_view.dart'; /// Dio Response Builder -class DioResponseBuilder extends StatefulWidget { +class DioResponseBuilder extends StatelessWidget { final Response data; final DateTime date; DioResponseBuilder({Key? key, required this.data, required this.date}) : super(key: key); - - @override - _DioResponseBuilderState createState() => _DioResponseBuilderState(); -} - -class _DioResponseBuilderState extends State { - RequestOptions? get _request => widget.data.requestOptions; - @override Widget build(BuildContext context) { - return Material( - elevation: 0, - color: Colors.green[100], - child: ListTile( - onTap: () => Navigator.push( - context, - MaterialPageRoute( - builder: (context) => DioResponseView(data: widget.data), - ), + return ListTile( + tileColor: Colors.green.withOpacity(0.2), + onTap: () => Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DioResponseView(data: data), ), - title: Text( - _request!.path, - style: TextStyle( - color: Colors.black87, - ), - ), - subtitle: Text(widget.date.toString()), - trailing: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Chip( - backgroundColor: Colors.green.withOpacity(0.8), - label: Text(_request!.method), - ), - ], + ), + title: Text( + data.requestOptions.path, + style: TextStyle( + color: Colors.black87, ), ), + subtitle: Text(date.toString()), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Chip( + backgroundColor: Colors.blue.withOpacity(0.8), + label: Text(data.requestOptions.method), + ), + ], + ), ); } } diff --git a/lib/src/builders/flutter_error_builder.dart b/lib/src/builders/flutter_error_builder.dart new file mode 100644 index 0000000..fe77d00 --- /dev/null +++ b/lib/src/builders/flutter_error_builder.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; +import 'package:power_logger/src/view/flutter_error_view.dart'; + +class FlutterErrorBuilder extends StatelessWidget { + final FlutterErrorDetails details; + FlutterErrorBuilder({Key? key, required this.details}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ListTile( + tileColor: Colors.red.withOpacity(0.4), + title: Text(details.exception.toString()), + trailing: Chip(label: Text('EXCEPTION'), backgroundColor: Colors.red), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => FlutterErrorView(details: details), + ), + ); + }, + ); + } +} diff --git a/lib/src/parser/data_parser.dart b/lib/src/parser/data_parser.dart index ed5edcd..28c510f 100644 --- a/lib/src/parser/data_parser.dart +++ b/lib/src/parser/data_parser.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:power_logger/power_logger.dart'; import 'package:power_logger/src/builders/dio_responses_builder.dart'; import 'package:power_logger/src/builders/dio_error_builder.dart'; +import 'package:power_logger/src/builders/flutter_error_builder.dart'; import 'package:power_logger/src/parser/unfocus_parser.dart'; ///LoggerDataParser @@ -18,6 +19,8 @@ class LoggerDataParser { data: data.rawData, date: data.date, ); + if (data.rawData is FlutterErrorDetails) + return FlutterErrorBuilder(details: data.rawData); return UnfocusParser(data: data.rawData, tag: data.tag); } } diff --git a/lib/src/view/flutter_error_view.dart b/lib/src/view/flutter_error_view.dart new file mode 100644 index 0000000..333c5c2 --- /dev/null +++ b/lib/src/view/flutter_error_view.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; + +class FlutterErrorView extends StatefulWidget { + final FlutterErrorDetails details; + FlutterErrorView({Key? key, required this.details}) : super(key: key); + + @override + _FlutterErrorViewState createState() => _FlutterErrorViewState(); +} + +class _FlutterErrorViewState extends State { + String get exceptionValue { + if (widget.details.exception is AssertionError) { + return (widget.details.exception as AssertionError).message.toString(); + } else + return widget.details.exception.toString(); + } + + List get _stringList { + return widget.details.stack.toString().split('\n'); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text('Flutter Error'), + ), + body: Column( + children: [ + Card( + margin: EdgeInsets.all(10), + child: Padding( + padding: EdgeInsets.all(10), + child: SelectableText( + exceptionValue, + style: TextStyle( + fontSize: 22, + ), + ), + ), + ), + Expanded( + child: ListView.separated( + padding: EdgeInsets.all(10), + itemBuilder: (context, index) { + return Text(_stringList[index]); + }, + separatorBuilder: (context, index) => SizedBox(height: 5), + itemCount: _stringList.length, + ), + ), + ], + ), + ); + } +} diff --git a/pubspec.lock b/pubspec.lock index ed4bc53..b63723f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,77 +5,77 @@ packages: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.5.0" auto_size_text: dependency: "direct main" description: name: auto_size_text - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "3.0.0-nullsafety.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" charcode: dependency: transitive description: name: charcode - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.15.0" device_info: dependency: "direct main" description: name: device_info - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" device_info_platform_interface: dependency: transitive description: name: device_info_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.1" dio: dependency: "direct main" description: name: dio - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.0.0" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" flutter: @@ -87,7 +87,7 @@ packages: dependency: "direct main" description: name: flutter_highlight - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.0" flutter_test: @@ -99,56 +99,56 @@ packages: dependency: transitive description: name: highlight - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.7.0" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "4.0.0" logger: dependency: "direct main" description: name: logger - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.0.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.12.10" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" package_info: dependency: "direct main" description: name: package_info - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.8.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" sky_engine: @@ -160,56 +160,56 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.8.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.10.0" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.2.0" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "0.2.19" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "1.3.0" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" sdks: diff --git a/pubspec.yaml b/pubspec.yaml index fcb2a5e..3d8f218 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,10 +1,10 @@ name: power_logger description: A well log tool on flutter, support Dio and custom type data. -version: 1.1.1-nullsafety.3 +version: 1.2.0 homepage: https://github.com/laiiihz/power_logger environment: - sdk: '>=2.12.0 <3.0.0' + sdk: ">=2.12.0 <3.0.0" flutter: ">=1.17.0" dependencies: