diff --git a/lib/error_log_widget.dart b/lib/error_log_widget.dart index 67a47c8..a99c4a2 100644 --- a/lib/error_log_widget.dart +++ b/lib/error_log_widget.dart @@ -16,7 +16,7 @@ class _ErrorLogWidgetState extends State { return Container( height: double.infinity, child: Center( - child: Text(widget.httpLog.err?.toString() ?? '请求正常'), + child: Text(widget.httpLog.err?.toString() ?? 'request success'), ), ); } diff --git a/lib/http_log_list_widget.dart b/lib/http_log_list_widget.dart index 6f0fb5f..5df0a92 100644 --- a/lib/http_log_list_widget.dart +++ b/lib/http_log_list_widget.dart @@ -23,9 +23,10 @@ class _HttpLogListWidgetState extends State { title: Text( 'request log', style: TextStyle( - fontSize: 18.0, - color: Color(0xFF4a4a4a), - fontWeight: FontWeight.bold), + fontSize: 14.0, + color: Color(0xFF4a4a4a), + fontWeight: FontWeight.normal, + ), ), backgroundColor: Colors.white, brightness: Brightness.light, @@ -61,9 +62,10 @@ class _HttpLogListWidgetState extends State { child: Text( item.options.baseUrl + item.options.path, style: TextStyle( - color: (item.response?.data == null) - ? Colors.red - : Colors.black), + color: (item.response?.data == null) + ? Colors.red + : Colors.black, + ), ), ), ), diff --git a/lib/json_view.dart b/lib/json_view.dart new file mode 100644 index 0000000..1d7e7b9 --- /dev/null +++ b/lib/json_view.dart @@ -0,0 +1,270 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +/// +/// Created by rich on 2019-07-17 +/// + +class JsonView extends StatefulWidget { + ///要展示的json数据 + final Map json; + + JsonView(this.json); + + @override + _JsonViewState createState() => _JsonViewState(); +} + +class _JsonViewState extends State { + Map showMap = Map(); + + ///当前节点编号 + int currentIndex = 0; + + ///文字大小 + double fontSize = 14; + + ///是否展开全部json + bool isShowAll = false; + @override + Widget build(BuildContext context) { + currentIndex = 0; + return Column( + children: [ + Row( + children: [ + RaisedButton( + onPressed: () { + _copy(widget.json?.toString()); + }, + child: Text('copy json'), + ), + SizedBox(width: 10), + Text(isShowAll ? 'shrink all' : 'expand all'), + Checkbox( + value: isShowAll, + onChanged: (check) { + isShowAll = check; + _flexAll(check); + }, + ), + Expanded( + child: Slider( + value: fontSize, + max: 30, + min: 1, + onChanged: (v) { + fontSize = v; + setState(() {}); + }, + ), + ), + ], + ), + Text( + 'Tip: long press a key to copy the value to the clipboard', + style: TextStyle(fontSize: 10), + ), + _buildObject(widget.json), + ], + ); + } + + ///构建object节点的展示 + Widget _buildObject(Map json, {String key}) { + List listW = []; + + ///增加一个节点 + currentIndex++; + + ///object节点 + Widget keyW; + if (_isShow(currentIndex)) { + keyW = _getDefText('${key == null ? '{' : '$key:{'}'); + } else { + keyW = _getDefText('${key == null ? '{...}' : '$key:{...}'}'); + } + listW.add(_wrapFlex(currentIndex, keyW)); + + ///object展示内容 + if (_isShow(currentIndex)) { + List listObj = []; + json.forEach((k, v) { + Widget w; + JsonType type = getType(v); + if (type == JsonType.object) { + w = _buildObject(v, key: k); + } else if (type == JsonType.array) { + List list = v as List; + w = _buildArray(list, k); + } else { + w = _buildKeyValue(v, k: k); + } + listObj.add(w); + }); + + listObj.add(_getDefText('},')); + + ///添加缩进 + listW.add( + Padding( + padding: EdgeInsets.only(left: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: listObj, + ), + ), + ); + } + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: listW, + ); + } + + ///构建array节点的展示 + Widget _buildArray(List listJ, String key) { + List listW = []; + + ///增加一个节点 + currentIndex++; + + ///添加key的展示 + Widget keyW; + if (_isShow(currentIndex)) { + keyW = _getDefText('$key:['); + } else { + keyW = _getDefText('$key:[...]'); + } + + ///添加key的点击事件 + ///添加key的展示 + listW.add(_wrapFlex(currentIndex, keyW)); + + if (_isShow(currentIndex)) { + List listArr = []; + listJ.forEach((val) { + var type = getType(val); + Widget w; + if (type == JsonType.object) { + w = _buildObject(val); + } else { + w = _buildKeyValue(val); + } + listArr.add(w); + }); + listArr.add(_getDefText(']')); + + ///添加缩进 + listW.add( + Padding( + padding: EdgeInsets.only(left: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: listArr, + ), + ), + ); + } + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: listW, + ); + } + + ///包裹展开按钮 + Widget _wrapFlex(int key, Widget keyW) { + return GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () { + _flexSwitch(key.toString()); + }, + child: Row( + children: [ + Transform.rotate( + angle: _isShow(key) ? 0 : 3.14 * 1.5, + child: Icon( + Icons.expand_more, + size: 12, + ), + ), + keyW, + ], + ), + ); + } + + ///构建子节点的展示 + Widget _buildKeyValue(v, {k}) { + Widget w = _getDefText( + '${k ?? ''}:${v is String ? '"$v"' : v?.toString() ?? null},'); + if (k != null) { + w = GestureDetector( + behavior: HitTestBehavior.translucent, + onLongPress: () { + _copy(v); + }, + child: w, + ); + } + return w; + } + + ///json节点是否展示 + bool _isShow(int key) { + ///说明是根节点 + if (key == 1) return true; + if (isShowAll) { + return showMap[key.toString()] ?? true; + } else { + return showMap[key.toString()] ?? false; + } + } + + ///展开合上的切换 + _flexSwitch(String key) { + showMap.putIfAbsent(key, () => false); + showMap[key] = !showMap[key]; + setState(() {}); + } + + ///展开合上所有 + _flexAll(bool flex) { + showMap.forEach((k, v) { + showMap[k] = flex; + }); + setState(() {}); + } + + ///判断value值的类型 + JsonType getType(dynamic json) { + if (json is List) { + return JsonType.array; + } else if (json is Map) { + return JsonType.object; + } else { + return JsonType.str; + } + } + + ///默认的文本大小 + Text _getDefText(String str) { + return Text( + str, + style: TextStyle(fontSize: fontSize), + ); + } + + _copy(value) { + var snackBar = + SnackBar(content: Text('"$value"\n\n copy success to clipboard')); + Scaffold.of(context).showSnackBar(snackBar); + Clipboard.setData(ClipboardData(text: value?.toString())); + } +} + +enum JsonType { + object, + array, + str, +} diff --git a/lib/request_log_widget.dart b/lib/request_log_widget.dart index e26464a..84f78a1 100644 --- a/lib/request_log_widget.dart +++ b/lib/request_log_widget.dart @@ -3,6 +3,8 @@ import 'package:dio_log/log_pool_manage.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'json_view.dart'; + class RequestLogWidget extends StatefulWidget { final HttpLog httpLog; @@ -83,6 +85,10 @@ class _RequestLogWidgetState extends State { _paramController), _buildCopyItem( 'cookie', options.headers['cookie'] ?? '', _cookieController), + Text('Headers:'), + JsonView(options.headers), + Text('extra:'), + JsonView(options.extra), ], ), ); @@ -139,7 +145,8 @@ class _RequestLogWidgetState extends State { RaisedButton( child: Text('copy'), onPressed: () { - var snackBar = SnackBar(content: Text('copy success')); + var snackBar = + SnackBar(content: Text('copy success to clipboard')); Scaffold.of(context).showSnackBar(snackBar); Clipboard.setData(ClipboardData(text: value)); }, diff --git a/lib/response_log_widget.dart b/lib/response_log_widget.dart index d615a72..edc5311 100644 --- a/lib/response_log_widget.dart +++ b/lib/response_log_widget.dart @@ -1,6 +1,7 @@ import 'package:dio_log/log_pool_manage.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; + +import 'json_view.dart'; class ResponseLogWidget extends StatefulWidget { final HttpLog httpLog; @@ -15,53 +16,12 @@ class _ResponseLogWidgetState extends State { @override Widget build(BuildContext context) { var response = widget.httpLog.response; - return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - RaisedButton( - onPressed: () { - var snackBar = SnackBar(content: Text('copy success')); - Scaffold.of(context).showSnackBar(snackBar); - Clipboard.setData(ClipboardData(text: response?.data?.toString())); - }, - child: Text('copy'), - ), - Container( - margin: EdgeInsets.all(12.0), - child: Text(_jsonFormat(response?.data?.toString())), - ), - ], - )); - } - - ///json显示格式化 - String _jsonFormat(String json) { - if (json == null || json.isEmpty) { - return '未收到服务端返回数据,请检查网络'; + if (response.data == null) { + return Center( + child: Text('No response received'), + ); } - json = json.replaceAll(RegExp('{'), '{\n '); - json = json.replaceAll(RegExp('}'), '\n }'); - json = json.replaceAll(RegExp('\\['), '[\n '); - json = json.replaceAll(RegExp('\\]'), '\n ]'); - json = json.replaceAll(RegExp(','), ',\n '); - return json; + Map data = response.data as Map; + return SingleChildScrollView(child: JsonView(data)); } } - -enum JsonLabel { - ///{ - LeftObject, - - ///} - RightObject, - - ///[ - LeftArray, - - ///] - RightArray, - - ///, - Comma, -} diff --git a/pubspec.yaml b/pubspec.yaml index d020695..bc4afb7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: dio_log -description: http requests log of dio 。This plugin helps you display log information for requests +description: http requests log of dio .This plugin helps you display log information for requests version: 1.0.3 author: rich homepage: https://github.com/flutterplugin/dio_log