Compare commits
No commits in common. "bcad10ae976e8dd14612aedbad2543813c5ba75f" and "509aae27df9554d9babd8d27868d11f0f4e749e7" have entirely different histories.
bcad10ae97
...
509aae27df
|
|
@ -288,6 +288,7 @@ class _DemoPageState extends State<DemoPage> {
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: Colors.grey[600],
|
color: Colors.grey[600],
|
||||||
|
fontFamily: 'monospace',
|
||||||
),
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,7 @@ class _DioDemoPageState extends State<DioDemoPage> {
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'dependencies:\n dio: ^5.3.0',
|
'dependencies:\n dio: ^5.3.0',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
fontFamily: 'monospace',
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -210,6 +211,7 @@ dio.interceptors.add(YxNetInspectorDioInterceptor());
|
||||||
// 现在所有通过这个 Dio 实例的请求都会被自动记录
|
// 现在所有通过这个 Dio 实例的请求都会被自动记录
|
||||||
final response = await dio.get('https://api.example.com/users');''',
|
final response = await dio.get('https://api.example.com/users');''',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
fontFamily: 'monospace',
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
height: 1.4,
|
height: 1.4,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,7 @@ packages:
|
||||||
path: ".."
|
path: ".."
|
||||||
relative: true
|
relative: true
|
||||||
source: path
|
source: path
|
||||||
version: "1.0.2"
|
version: "1.0.0"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.7.0-0 <4.0.0"
|
dart: ">=3.7.0-0 <4.0.0"
|
||||||
flutter: ">=3.18.0-18.0.pre.54"
|
flutter: ">=3.18.0-18.0.pre.54"
|
||||||
|
|
|
||||||
|
|
@ -102,8 +102,8 @@ class NetworkLogEntry {
|
||||||
String get formattedDuration {
|
String get formattedDuration {
|
||||||
if (duration == null) return '未知';
|
if (duration == null) return '未知';
|
||||||
final ms = duration!.inMilliseconds;
|
final ms = duration!.inMilliseconds;
|
||||||
if (ms < 1000) return '${ms} ms';
|
if (ms < 1000) return '${ms}毫秒';
|
||||||
return '${(ms / 1000).toStringAsFixed(1)} s';
|
return '${(ms / 1000).toStringAsFixed(1)}秒';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取显示URL(隐藏主机名简化显示)
|
/// 获取显示URL(隐藏主机名简化显示)
|
||||||
|
|
@ -116,15 +116,6 @@ class NetworkLogEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String get hostUrl {
|
|
||||||
try {
|
|
||||||
final uri = Uri.parse(url);
|
|
||||||
return '${uri.host}';
|
|
||||||
} catch (e) {
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 创建副本并更新字段
|
/// 创建副本并更新字段
|
||||||
NetworkLogEntry copyWith({
|
NetworkLogEntry copyWith({
|
||||||
String? id,
|
String? id,
|
||||||
|
|
|
||||||
|
|
@ -103,16 +103,14 @@ class _YxInspectorPanelState extends State<YxInspectorPanel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_isFullScreen) {
|
if (_isFullScreen) {
|
||||||
// 全屏模式 - 考虑状态栏高度
|
// 全屏模式
|
||||||
return Material(
|
return Material(
|
||||||
color: Colors.black.withValues(alpha: 0.5),
|
color: Colors.black.withValues(alpha: 0.5),
|
||||||
child: SafeArea(
|
child: Container(
|
||||||
child: Container(
|
width: MediaQuery.of(context).size.width,
|
||||||
width: MediaQuery.of(context).size.width,
|
height: MediaQuery.of(context).size.height,
|
||||||
height: double.infinity,
|
color: widget.theme.backgroundColor,
|
||||||
color: widget.theme.backgroundColor,
|
child: content,
|
||||||
child: content,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -135,150 +133,126 @@ class _YxInspectorPanelState extends State<YxInspectorPanel> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildDetailHeader() {
|
Widget _buildDetailHeader() {
|
||||||
final actions = [
|
return Container(
|
||||||
IconButton(
|
padding: const EdgeInsets.all(16),
|
||||||
onPressed: () => _copyLogDetails(_selectedLog!),
|
decoration: BoxDecoration(
|
||||||
icon: const Icon(
|
color: widget.theme.primaryColor,
|
||||||
Icons.copy,
|
borderRadius: _isFullScreen
|
||||||
color: Colors.white,
|
? BorderRadius.zero
|
||||||
),
|
: const BorderRadius.only(
|
||||||
tooltip: '复制详情',
|
topLeft: Radius.circular(16),
|
||||||
),
|
topRight: Radius.circular(16),
|
||||||
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,
|
||||||
),
|
),
|
||||||
centerTitle: false,
|
tooltip: '返回列表',
|
||||||
actions: actions,
|
),
|
||||||
)
|
const SizedBox(width: 8),
|
||||||
: Container(
|
const Icon(
|
||||||
padding: const EdgeInsets.all(16),
|
Icons.article_outlined,
|
||||||
decoration: BoxDecoration(
|
color: Colors.white,
|
||||||
color: widget.theme.primaryColor,
|
size: 24,
|
||||||
borderRadius: _isFullScreen
|
),
|
||||||
? BorderRadius.zero
|
const SizedBox(width: 8),
|
||||||
: const BorderRadius.only(
|
const Text(
|
||||||
topLeft: Radius.circular(16),
|
'请求详情',
|
||||||
topRight: Radius.circular(16),
|
style: TextStyle(
|
||||||
),
|
color: Colors.white,
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
child: Row(
|
),
|
||||||
children: [
|
const Spacer(),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: _hideLogDetail,
|
onPressed: () => _copyLogDetails(_selectedLog!),
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.arrow_back,
|
Icons.copy,
|
||||||
color: Colors.white,
|
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() {
|
Widget _buildHeader() {
|
||||||
final actions = [
|
return Container(
|
||||||
IconButton(
|
padding: const EdgeInsets.all(16),
|
||||||
onPressed: () {
|
decoration: BoxDecoration(
|
||||||
setState(() {
|
color: widget.theme.primaryColor,
|
||||||
_isFullScreen = !_isFullScreen;
|
borderRadius: _isFullScreen
|
||||||
});
|
? BorderRadius.zero
|
||||||
},
|
: const BorderRadius.only(
|
||||||
icon: Icon(
|
topLeft: Radius.circular(16),
|
||||||
_isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen,
|
topRight: Radius.circular(16),
|
||||||
color: Colors.white,
|
),
|
||||||
),
|
|
||||||
tooltip: _isFullScreen ? '退出全屏' : '全屏',
|
|
||||||
),
|
),
|
||||||
IconButton(
|
child: Row(
|
||||||
onPressed: () {
|
children: [
|
||||||
widget.controller.clearLogs();
|
const Icon(Icons.network_check, color: Colors.white, size: 24),
|
||||||
},
|
const SizedBox(width: 8),
|
||||||
icon: const Icon(Icons.clear_all, color: Colors.white),
|
const Text(
|
||||||
tooltip: '清空日志',
|
'网络检查器',
|
||||||
),
|
style: TextStyle(
|
||||||
IconButton(
|
color: Colors.white,
|
||||||
onPressed: widget.onClose,
|
fontSize: 18,
|
||||||
icon: const Icon(Icons.close, color: Colors.white),
|
fontWeight: FontWeight.bold,
|
||||||
),
|
|
||||||
];
|
|
||||||
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 Spacer(),
|
||||||
const Icon(Icons.network_check, color: Colors.white, size: 24),
|
IconButton(
|
||||||
const SizedBox(width: 8),
|
onPressed: () {
|
||||||
const Text(
|
setState(() {
|
||||||
'网络检查器',
|
_isFullScreen = !_isFullScreen;
|
||||||
style: TextStyle(
|
});
|
||||||
color: Colors.white,
|
},
|
||||||
fontSize: 18,
|
icon: Icon(
|
||||||
fontWeight: FontWeight.bold,
|
_isFullScreen ? Icons.fullscreen_exit : Icons.fullscreen,
|
||||||
),
|
color: Colors.white,
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
...actions
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
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),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildStatistics() {
|
Widget _buildStatistics() {
|
||||||
|
|
@ -455,6 +429,35 @@ class _YxInspectorPanelState extends State<YxInspectorPanel> {
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
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和状态
|
// URL和状态
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
|
@ -473,39 +476,8 @@ class _YxInspectorPanelState extends State<YxInspectorPanel> {
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
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(
|
Text(
|
||||||
'${log.statusCode ?? "?"} ${log.formattedDuration}',
|
'${log.statusCode ?? "?"} • ${log.formattedDuration}',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
color: log.statusColor,
|
color: log.statusColor,
|
||||||
|
|
@ -520,22 +492,28 @@ class _YxInspectorPanelState extends State<YxInspectorPanel> {
|
||||||
color: widget.theme.errorColor,
|
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),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -122,7 +122,6 @@ class YxLogDetailPage extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildInfoRow('HOST', log.hostUrl, isUrl: true),
|
|
||||||
_buildInfoRow('URL', log.displayUrl, isUrl: true),
|
_buildInfoRow('URL', log.displayUrl, isUrl: true),
|
||||||
if (log.requestData != null) ...[
|
if (log.requestData != null) ...[
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
|
@ -145,6 +144,7 @@ class YxLogDetailPage extends StatelessWidget {
|
||||||
_formatRequestBody(log.requestData),
|
_formatRequestBody(log.requestData),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
fontFamily: 'monospace',
|
||||||
color: theme.textColor,
|
color: theme.textColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -199,6 +199,7 @@ class YxLogDetailPage extends StatelessWidget {
|
||||||
log.responseData.toString(),
|
log.responseData.toString(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
fontFamily: 'monospace',
|
||||||
color: theme.textColor,
|
color: theme.textColor,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -256,6 +257,7 @@ class YxLogDetailPage extends StatelessWidget {
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: theme.errorColor,
|
color: theme.errorColor,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
|
fontFamily: 'monospace',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -351,6 +353,7 @@ class YxLogDetailPage extends StatelessWidget {
|
||||||
value,
|
value,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
|
fontFamily: 'monospace',
|
||||||
color: theme.primaryColor,
|
color: theme.primaryColor,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
name: yx_net_inspector
|
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.
|
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.3
|
version: 1.0.2
|
||||||
homepage: https://github.com/your-username/yx_net_inspector
|
homepage: https://github.com/your-username/yx_net_inspector
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue