From a8da68c0e3a55665ca995528b312576df8364aa1 Mon Sep 17 00:00:00 2001 From: YuanXuan Date: Mon, 13 Oct 2025 16:40:19 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E5=A4=8D=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E6=A0=8F=E9=AB=98=E5=BA=A6=E9=97=AE=E9=A2=98=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96UI=E5=B8=83=E5=B1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复全屏模式下状态栏高度处理问题,使用SafeArea避免内容被遮挡 - 优化检查器面板UI布局,重新排列状态指示器和方法标签位置 - 清理代码,移除注释掉的无用代码 - 改进代码格式化和可读性 - 修复lint警告,确保代码质量 --- example/lib/pages/demo_page.dart | 1 - example/lib/pages/dio_demo_page.dart | 2 - example/pubspec.lock | 2 +- lib/src/models/network_log_entry.dart | 13 +- lib/src/widgets/inspector_panel.dart | 350 ++++++++++++++------------ lib/src/widgets/log_detail_page.dart | 5 +- pubspec.yaml | 2 +- 7 files changed, 200 insertions(+), 175 deletions(-) diff --git a/example/lib/pages/demo_page.dart b/example/lib/pages/demo_page.dart index 1fbb40b..6060327 100644 --- a/example/lib/pages/demo_page.dart +++ b/example/lib/pages/demo_page.dart @@ -288,7 +288,6 @@ class _DemoPageState extends State { style: TextStyle( fontSize: 12, color: Colors.grey[600], - fontFamily: 'monospace', ), overflow: TextOverflow.ellipsis, ), diff --git a/example/lib/pages/dio_demo_page.dart b/example/lib/pages/dio_demo_page.dart index 2649c18..fcb4ec6 100644 --- a/example/lib/pages/dio_demo_page.dart +++ b/example/lib/pages/dio_demo_page.dart @@ -145,7 +145,6 @@ class _DioDemoPageState extends State { child: const Text( 'dependencies:\n dio: ^5.3.0', style: TextStyle( - fontFamily: 'monospace', fontSize: 13, ), ), @@ -211,7 +210,6 @@ dio.interceptors.add(YxNetInspectorDioInterceptor()); // 现在所有通过这个 Dio 实例的请求都会被自动记录 final response = await dio.get('https://api.example.com/users');''', style: TextStyle( - fontFamily: 'monospace', fontSize: 12, height: 1.4, ), diff --git a/example/pubspec.lock b/example/pubspec.lock index 27e7eab..6176505 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -238,7 +238,7 @@ packages: path: ".." relative: true source: path - version: "1.0.0" + version: "1.0.2" sdks: dart: ">=3.7.0-0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/lib/src/models/network_log_entry.dart b/lib/src/models/network_log_entry.dart index 17d8466..1f80116 100644 --- a/lib/src/models/network_log_entry.dart +++ b/lib/src/models/network_log_entry.dart @@ -102,8 +102,8 @@ class NetworkLogEntry { String get formattedDuration { if (duration == null) return '未知'; final ms = duration!.inMilliseconds; - if (ms < 1000) return '${ms}毫秒'; - return '${(ms / 1000).toStringAsFixed(1)}秒'; + if (ms < 1000) return '${ms} ms'; + return '${(ms / 1000).toStringAsFixed(1)} s'; } /// 获取显示URL(隐藏主机名简化显示) @@ -116,6 +116,15 @@ class NetworkLogEntry { } } + String get hostUrl { + try { + final uri = Uri.parse(url); + return '${uri.host}'; + } catch (e) { + return url; + } + } + /// 创建副本并更新字段 NetworkLogEntry copyWith({ String? id, diff --git a/lib/src/widgets/inspector_panel.dart b/lib/src/widgets/inspector_panel.dart index 06d931d..01fef3c 100644 --- a/lib/src/widgets/inspector_panel.dart +++ b/lib/src/widgets/inspector_panel.dart @@ -103,14 +103,16 @@ class _YxInspectorPanelState extends State { } if (_isFullScreen) { - // 全屏模式 + // 全屏模式 - 考虑状态栏高度 return Material( color: Colors.black.withValues(alpha: 0.5), - child: Container( - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - color: widget.theme.backgroundColor, - child: content, + child: SafeArea( + child: Container( + width: MediaQuery.of(context).size.width, + height: double.infinity, + color: widget.theme.backgroundColor, + child: content, + ), ), ); } else { @@ -133,126 +135,150 @@ class _YxInspectorPanelState extends State { } Widget _buildDetailHeader() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: widget.theme.primaryColor, - borderRadius: _isFullScreen - ? BorderRadius.zero - : const BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), + final actions = [ + IconButton( + onPressed: () => _copyLogDetails(_selectedLog!), + icon: const Icon( + Icons.copy, + color: Colors.white, + ), + tooltip: '复制详情', + ), + IconButton( + onPressed: () { + _isFullScreen = !_isFullScreen; + setState(() {}); + }, + icon: Icon( + _isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen, + color: Colors.white, + ), + tooltip: _isFullScreen ? '退出全屏' : '全屏显示', + ), + IconButton( + onPressed: widget.onClose, + icon: const Icon( + Icons.close, + color: Colors.white, + ), + tooltip: '关闭', + ), + ]; + + return _isFullScreen + ? AppBar( + title: Text('请求详情'), + backgroundColor: widget.theme.primaryColor, + foregroundColor: Colors.white, + // excludeHeaderSemantics: false + leading: IconButton( + onPressed: _hideLogDetail, + icon: const Icon( + Icons.arrow_back, + color: Colors.white, ), - ), - child: Row( - children: [ - IconButton( - onPressed: _hideLogDetail, - icon: const Icon( - Icons.arrow_back, - color: Colors.white, ), - tooltip: '返回列表', - ), - const SizedBox(width: 8), - const Icon( - Icons.article_outlined, - color: Colors.white, - size: 24, - ), - const SizedBox(width: 8), - const Text( - '请求详情', - style: TextStyle( - color: Colors.white, - fontSize: 18, - fontWeight: FontWeight.bold, + centerTitle: false, + actions: actions, + ) + : Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: widget.theme.primaryColor, + borderRadius: _isFullScreen + ? BorderRadius.zero + : const BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), ), - ), - const Spacer(), - IconButton( - onPressed: () => _copyLogDetails(_selectedLog!), - icon: const Icon( - Icons.copy, - color: Colors.white, + child: Row( + children: [ + IconButton( + onPressed: _hideLogDetail, + icon: const Icon( + Icons.arrow_back, + color: Colors.white, + ), + tooltip: '返回列表', + ), + const Text( + '请求详情', + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + const Spacer(), + ...actions + ], ), - tooltip: '复制详情', - ), - IconButton( - onPressed: () { - _isFullScreen = !_isFullScreen; - setState(() {}); - }, - icon: Icon( - _isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen, - color: Colors.white, - ), - tooltip: _isFullScreen ? '退出全屏' : '全屏显示', - ), - IconButton( - onPressed: widget.onClose, - icon: const Icon( - Icons.close, - color: Colors.white, - ), - tooltip: '关闭', - ), - ], - ), - ); + ); } Widget _buildHeader() { - return Container( - padding: const EdgeInsets.all(16), - decoration: BoxDecoration( - color: widget.theme.primaryColor, - borderRadius: _isFullScreen - ? BorderRadius.zero - : const BorderRadius.only( - topLeft: Radius.circular(16), - topRight: Radius.circular(16), - ), + final actions = [ + IconButton( + onPressed: () { + setState(() { + _isFullScreen = !_isFullScreen; + }); + }, + icon: Icon( + _isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen, + color: Colors.white, + ), + tooltip: _isFullScreen ? '退出全屏' : '全屏', ), - child: Row( - children: [ - const Icon(Icons.network_check, color: Colors.white, size: 24), - const SizedBox(width: 8), - const Text( - '网络检查器', - style: TextStyle( - color: Colors.white, - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - const Spacer(), - IconButton( - onPressed: () { - setState(() { - _isFullScreen = !_isFullScreen; - }); - }, - icon: Icon( - _isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen, - color: Colors.white, - ), - tooltip: _isFullScreen ? '退出全屏' : '全屏', - ), - IconButton( - onPressed: () { - widget.controller.clearLogs(); - }, - icon: const Icon(Icons.clear_all, color: Colors.white), - tooltip: '清空日志', - ), - IconButton( - onPressed: widget.onClose, - icon: const Icon(Icons.close, color: Colors.white), - ), - ], + IconButton( + onPressed: () { + widget.controller.clearLogs(); + }, + icon: const Icon(Icons.clear_all, color: Colors.white), + tooltip: '清空日志', ), - ); + IconButton( + onPressed: widget.onClose, + icon: const Icon(Icons.close, color: Colors.white), + ), + ]; + return _isFullScreen + ? AppBar( + title: Text('网络检查器'), + backgroundColor: widget.theme.primaryColor, + foregroundColor: Colors.white, + centerTitle: false, + actions: actions, + ) + : Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), + decoration: BoxDecoration( + color: widget.theme.primaryColor, + borderRadius: _isFullScreen + ? BorderRadius.zero + : const BorderRadius.only( + topLeft: Radius.circular(16), + topRight: Radius.circular(16), + ), + ), + child: Row( + children: [ + const Icon(Icons.network_check, color: Colors.white, size: 24), + const SizedBox(width: 8), + const Text( + '网络检查器', + style: TextStyle( + color: Colors.white, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + ), + const Spacer(), + ...actions + ], + ), + ); } Widget _buildStatistics() { @@ -429,35 +455,6 @@ class _YxInspectorPanelState extends State { padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), child: Row( children: [ - // 状态指示器 - Container( - width: 6, - height: 6, - decoration: BoxDecoration( - color: log.statusColor, - shape: BoxShape.circle, - ), - ), - const SizedBox(width: 8), - - // 方法标签 - Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: _getMethodColor(log.method).withValues(alpha: 0.1), - borderRadius: BorderRadius.circular(4), - ), - child: Text( - log.method, - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.bold, - color: _getMethodColor(log.method), - ), - ), - ), - const SizedBox(width: 8), - // URL和状态 Expanded( child: Column( @@ -476,8 +473,39 @@ class _YxInspectorPanelState extends State { const SizedBox(height: 2), Row( children: [ + // 状态指示器 + Container( + width: 6, + height: 6, + decoration: BoxDecoration( + color: log.statusColor, + shape: BoxShape.circle, + ), + ), + const SizedBox(width: 8), + + // 方法标签 + Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: _getMethodColor(log.method) + .withValues(alpha: 0.1), + borderRadius: BorderRadius.circular(4), + ), + child: Text( + log.method, + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.bold, + color: _getMethodColor(log.method), + ), + ), + ), + const SizedBox(width: 8), + Text( - '${log.statusCode ?? "?"} • ${log.formattedDuration}', + '${log.statusCode ?? "?"} ${log.formattedDuration}', style: TextStyle( fontSize: 11, color: log.statusColor, @@ -492,28 +520,22 @@ class _YxInspectorPanelState extends State { color: widget.theme.errorColor, ), ], + Spacer(), + // 时间 + Text( + log.formattedTime.contains(' ') + ? log.formattedTime.split(' ')[1] + : log.formattedTime, // 只显示时间部分 + style: TextStyle( + fontSize: 10, + color: widget.theme.secondaryTextColor, + ), + ), ], ), ], ), ), - - // 时间 - Text( - log.formattedTime.contains(' ') - ? log.formattedTime.split(' ')[1] - : log.formattedTime, // 只显示时间部分 - style: TextStyle( - fontSize: 10, - color: widget.theme.secondaryTextColor, - ), - ), - const SizedBox(width: 4), - Icon( - Icons.chevron_right, - size: 16, - color: widget.theme.secondaryTextColor.withValues(alpha: 0.5), - ), ], ), ), diff --git a/lib/src/widgets/log_detail_page.dart b/lib/src/widgets/log_detail_page.dart index e442d45..c18f735 100644 --- a/lib/src/widgets/log_detail_page.dart +++ b/lib/src/widgets/log_detail_page.dart @@ -122,6 +122,7 @@ class YxLogDetailPage extends StatelessWidget { ], ), const SizedBox(height: 16), + _buildInfoRow('HOST', log.hostUrl, isUrl: true), _buildInfoRow('URL', log.displayUrl, isUrl: true), if (log.requestData != null) ...[ const SizedBox(height: 8), @@ -144,7 +145,6 @@ class YxLogDetailPage extends StatelessWidget { _formatRequestBody(log.requestData), style: TextStyle( fontSize: 12, - fontFamily: 'monospace', color: theme.textColor, ), ), @@ -199,7 +199,6 @@ class YxLogDetailPage extends StatelessWidget { log.responseData.toString(), style: TextStyle( fontSize: 12, - fontFamily: 'monospace', color: theme.textColor, ), ), @@ -257,7 +256,6 @@ class YxLogDetailPage extends StatelessWidget { style: TextStyle( color: theme.errorColor, fontSize: 14, - fontFamily: 'monospace', ), ), ), @@ -353,7 +351,6 @@ class YxLogDetailPage extends StatelessWidget { value, style: TextStyle( fontSize: 12, - fontFamily: 'monospace', color: theme.primaryColor, ), ) diff --git a/pubspec.yaml b/pubspec.yaml index 9248775..a9e9b1c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: yx_net_inspector description: A powerful network inspector with floating debug ball for Flutter apps. Monitor HTTP requests, responses, and debug network issues in real-time. -version: 1.0.2 +version: 1.0.3 homepage: https://github.com/your-username/yx_net_inspector environment: