diff --git a/lib/network/bin/configuration.dart b/lib/network/bin/configuration.dart index 266bcd3..632eb67 100644 --- a/lib/network/bin/configuration.dart +++ b/lib/network/bin/configuration.dart @@ -34,7 +34,7 @@ class Configuration { bool enableSystemProxy = true; //是否显示更新内容公告 - bool upgradeNoticeV2 = true; + bool upgradeNoticeV3 = true; //请求重写 RequestRewrites requestRewrites = RequestRewrites.instance; @@ -117,7 +117,7 @@ class Configuration { port = config['port'] ?? port; enableSsl = config['enableSsl'] == true; enableSystemProxy = config['enableSystemProxy'] ?? (config['enableDesktop'] ?? true); - upgradeNoticeV2 = config['upgradeNoticeV2'] ?? true; + upgradeNoticeV3 = config['upgradeNoticeV3'] ?? true; if (config['externalProxy'] != null) { externalProxy = ProxyInfo.fromJson(config['externalProxy']); } @@ -158,7 +158,7 @@ class Configuration { Map toJson() { return { - 'upgradeNoticeV2': upgradeNoticeV2, + 'upgradeNoticeV3': upgradeNoticeV3, 'port': port, 'enableSsl': enableSsl, 'enableSystemProxy': enableSystemProxy, diff --git a/lib/storage/histories.dart b/lib/storage/histories.dart index 6edafbb..5274278 100644 --- a/lib/storage/histories.dart +++ b/lib/storage/histories.dart @@ -63,7 +63,7 @@ class HistoryStorage { } /// 添加历史记录 - void addHistory(String name, File file, int requestLength) async { + Future addHistory(String name, File file, int requestLength) async { var size = await file.length(); _histories[name] = HistoryItem(file.path, requestLength, size); (await _path).writeAsString(jsonEncode(_histories)); diff --git a/lib/ui/component/utils.dart b/lib/ui/component/utils.dart index e745700..ddf73fb 100644 --- a/lib/ui/component/utils.dart +++ b/lib/ui/component/utils.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_toastr/flutter_toastr.dart'; import 'package:network_proxy/network/http/http.dart'; +import 'package:network_proxy/utils/platform.dart'; Icon getIcon(HttpResponse? response) { var map = { @@ -57,36 +58,46 @@ RelativeRect menuPosition(BuildContext context) { } Widget contextMenu(BuildContext context, EditableTextState editableTextState) { + List list = [ + ContextMenuButtonItem( + onPressed: () { + editableTextState.copySelection(SelectionChangedCause.tap); + FlutterToastr.show("已复制到剪切板", context); + unSelect(editableTextState); + editableTextState.hideToolbar(); + }, + type: ContextMenuButtonType.copy, + ), + ContextMenuButtonItem( + label: 'Copy Value', + onPressed: () { + unSelect(editableTextState); + Clipboard.setData(ClipboardData(text: editableTextState.textEditingValue.text)).then((value) { + FlutterToastr.show("已复制到剪切板", context); + editableTextState.hideToolbar(); + }); + }, + type: ContextMenuButtonType.custom, + ), + ContextMenuButtonItem( + onPressed: () { + editableTextState.selectAll(SelectionChangedCause.tap); + }, + type: ContextMenuButtonType.selectAll, + ) + ]; + if (Platforms.isDesktop()) { + list.add(ContextMenuButtonItem( + onPressed: () async { + editableTextState.shareSelection(SelectionChangedCause.toolbar); + }, + type: ContextMenuButtonType.share, + )); + } + return AdaptiveTextSelectionToolbar.buttonItems( anchors: editableTextState.contextMenuAnchors, - buttonItems: [ - ContextMenuButtonItem( - onPressed: () { - editableTextState.copySelection(SelectionChangedCause.tap); - FlutterToastr.show("已复制到剪切板", context); - unSelect(editableTextState); - editableTextState.hideToolbar(); - }, - type: ContextMenuButtonType.copy, - ), - ContextMenuButtonItem( - label: 'Copy Value', - onPressed: () { - unSelect(editableTextState); - Clipboard.setData(ClipboardData(text: editableTextState.textEditingValue.text)).then((value) { - FlutterToastr.show("已复制到剪切板", context); - editableTextState.hideToolbar(); - }); - }, - type: ContextMenuButtonType.custom, - ), - ContextMenuButtonItem( - onPressed: () { - editableTextState.selectAll(SelectionChangedCause.tap); - }, - type: ContextMenuButtonType.selectAll, - ), - ], + buttonItems: list, ); } diff --git a/lib/ui/desktop/desktop.dart b/lib/ui/desktop/desktop.dart index 564b480..cbc516f 100644 --- a/lib/ui/desktop/desktop.dart +++ b/lib/ui/desktop/desktop.dart @@ -54,7 +54,7 @@ class _DesktopHomePagePageState extends State implements EventL proxyServer.addListener(this); panel = NetworkTabController(tabStyle: const TextStyle(fontSize: 16), proxyServer: proxyServer); - if (widget.configuration.upgradeNoticeV2) { + if (widget.configuration.upgradeNoticeV3) { WidgetsBinding.instance.addPostFrameCallback((_) { showUpgradeNotice(); }); @@ -126,18 +126,18 @@ class _DesktopHomePagePageState extends State implements EventL actions: [ TextButton( onPressed: () { - widget.configuration.upgradeNoticeV2 = false; + widget.configuration.upgradeNoticeV3 = false; widget.configuration.flushConfig(); Navigator.pop(context); }, child: const Text('关闭')) ], - title: const Text('更新内容V1.0.2', style: TextStyle(fontSize: 18)), + title: const Text('更新内容V1.0.3', style: TextStyle(fontSize: 18)), content: const Text( '提示:默认不会开启HTTPS抓包,请安装证书后再开启HTTPS抓包。\n' '点击的HTTPS抓包(加锁图标),选择安装根证书,按照提示操作即可。\n\n' '新增更新:\n' - '1. 增加历史记录功能;\n' + '1. 增加历史记录功能,默认不会保存,需要去历史页点击保存;\n' '2. 请求重写增加名称&URL参数重写;\n' '3. 请求重写增加重定向;\n' '4. 建立连接异常显示请求体;\n' diff --git a/lib/ui/desktop/left/domain.dart b/lib/ui/desktop/left/domain.dart index 8638a2a..24df20c 100644 --- a/lib/ui/desktop/left/domain.dart +++ b/lib/ui/desktop/left/domain.dart @@ -1,6 +1,7 @@ import 'dart:collection'; import 'package:flutter/material.dart'; +import 'package:flutter_toastr/flutter_toastr.dart'; import 'package:network_proxy/network/bin/configuration.dart'; import 'package:network_proxy/network/bin/server.dart'; import 'package:network_proxy/network/channel.dart'; @@ -314,6 +315,7 @@ class _HeaderBodyState extends State { onTap: () { HostFilter.blacklist.add(widget.header.host); configuration.flushConfig(); + FlutterToastr.show('添加成功', context); }), CustomPopupMenuItem( height: 35, @@ -321,6 +323,7 @@ class _HeaderBodyState extends State { onTap: () { HostFilter.whitelist.add(widget.header.host); configuration.flushConfig(); + FlutterToastr.show('添加成功', context); }), CustomPopupMenuItem( height: 35, @@ -328,6 +331,7 @@ class _HeaderBodyState extends State { onTap: () { HostFilter.whitelist.remove(widget.header.host); configuration.flushConfig(); + FlutterToastr.show('删除成功', context); }), const PopupMenuDivider(height: 0.3), CustomPopupMenuItem( @@ -340,5 +344,6 @@ class _HeaderBodyState extends State { widget.channelIdPathMap.clear(); widget.body.clear(); widget.onRemove?.call(); + FlutterToastr.show('删除成功', context); } } diff --git a/lib/ui/desktop/left/history.dart b/lib/ui/desktop/left/history.dart index 6e1723f..e60e297 100644 --- a/lib/ui/desktop/left/history.dart +++ b/lib/ui/desktop/left/history.dart @@ -5,6 +5,7 @@ import 'dart:io'; import 'package:date_format/date_format.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_toastr/flutter_toastr.dart'; import 'package:network_proxy/network/bin/server.dart'; import 'package:network_proxy/network/channel.dart'; import 'package:network_proxy/network/handler.dart'; @@ -74,7 +75,7 @@ class _HistoryWidget extends StatefulWidget { } } -class _HistoryState extends State<_HistoryWidget> implements EventListener { +class _HistoryState extends State<_HistoryWidget> { ///是否保存会话 static bool _sessionSaved = false; static WriteTask? writeTask; @@ -149,8 +150,10 @@ class _HistoryState extends State<_HistoryWidget> implements EventListener { if (name == writeTask?.name) { writeTask?.timer?.cancel(); writeTask?.open.close(); + writeTask = null; } storage.removeHistory(name); + FlutterToastr.show('删除成功', context); }); }) ]) @@ -171,28 +174,19 @@ class _HistoryState extends State<_HistoryWidget> implements EventListener { var file = await HistoryStorage.openFile("${DateTime.now().millisecondsSinceEpoch}.txt"); print(file); RandomAccessFile open = await file.open(mode: FileMode.append); - storage.addHistory(name, file, 0); + await storage.addHistory(name, file, 0); writeTask = WriteTask(name, open, storage, callback: () => setState(() {})); writeTask?.writeList.addAll(container); + proxyServer.addListener(writeTask!); + await writeTask?.writeTask(); + writeTask?.startTask(); - - proxyServer.addListener(this); - } - - @override - void onRequest(Channel channel, HttpRequest request) {} - - @override - void onResponse(Channel channel, HttpResponse response) async { - if (response.request == null) { - return; - } - writeTask?.writeList.add(response.request!); + setState(() {}); } } -class WriteTask { +class WriteTask implements EventListener { final HistoryStorage historyStorage; final RandomAccessFile open; Queue writeList = Queue(); @@ -202,6 +196,17 @@ class WriteTask { WriteTask(this.name, this.open, this.historyStorage, {this.callback}); + @override + void onRequest(Channel channel, HttpRequest request) {} + + @override + void onResponse(Channel channel, HttpResponse response) { + if (response.request == null) { + return; + } + writeList.add(response.request!); + } + //写入任务 startTask() { timer = Timer.periodic(const Duration(seconds: 15), (it) => writeTask()); diff --git a/lib/ui/mobile/menu.dart b/lib/ui/mobile/menu.dart index 98a5626..0d09f62 100644 --- a/lib/ui/mobile/menu.dart +++ b/lib/ui/mobile/menu.dart @@ -12,6 +12,8 @@ import 'package:network_proxy/ui/desktop/toolbar/setting/setting.dart'; import 'package:network_proxy/ui/desktop/toolbar/setting/theme.dart'; import 'package:network_proxy/ui/mobile/connect_remote.dart'; import 'package:network_proxy/ui/mobile/request/favorite.dart'; +import 'package:network_proxy/ui/mobile/request/history.dart'; +import 'package:network_proxy/ui/mobile/request/list.dart'; import 'package:network_proxy/ui/mobile/setting/app_whitelist.dart'; import 'package:network_proxy/ui/mobile/setting/filter.dart'; import 'package:network_proxy/ui/mobile/setting/request_rewrite.dart'; @@ -24,8 +26,9 @@ import 'package:url_launcher/url_launcher.dart'; ///左侧抽屉 class DrawerWidget extends StatelessWidget { final ProxyServer proxyServer; + final GlobalKey requestStateKey; - const DrawerWidget({Key? key, required this.proxyServer}) : super(key: key); + const DrawerWidget({Key? key, required this.proxyServer, required this.requestStateKey}) : super(key: key); @override Widget build(BuildContext context) { @@ -43,14 +46,15 @@ class DrawerWidget extends StatelessWidget { trailing: const Icon(Icons.arrow_right), onTap: () => navigator(context, MobileFavorites(proxyServer: proxyServer))), ListTile( - leading: const Icon(Icons.construction), - title: const Text("工具箱"), - trailing: const Icon(Icons.arrow_right), - onTap: () => navigator( - context, - Scaffold( - appBar: AppBar(title: const Text("工具箱", style: TextStyle(fontSize: 16)), centerTitle: true), - body: const Toolbox()))), + leading: const Icon(Icons.history), + title: const Text("历史"), + trailing: const Icon(Icons.arrow_right), + onTap: () => navigator( + context, + Scaffold( + appBar: AppBar(title: const Text("历史记录", style: TextStyle(fontSize: 16)), centerTitle: true), + body: MobileHistory(proxyServer: proxyServer, requestStateKey: requestStateKey))), + ), const Divider(thickness: 0.3), Padding(padding: const EdgeInsets.only(left: 15), child: PortWidget(proxyServer: proxyServer)), ListTile( @@ -65,7 +69,6 @@ class DrawerWidget extends StatelessWidget { trailing: const Icon(Icons.arrow_right), onTap: () => navigator(context, AppWhitelist(proxyServer: proxyServer))), ListTile( - dense: true, title: const Text("域名白名单"), trailing: const Icon(Icons.arrow_right), onTap: () => navigator( @@ -123,7 +126,6 @@ class MoreEnum extends StatelessWidget { itemBuilder: (BuildContext context) { return [ PopupMenuItem( - padding: const EdgeInsets.only(left: 0), child: ListTile( dense: true, title: const Text("HTTPS抓包"), @@ -136,7 +138,6 @@ class MoreEnum extends StatelessWidget { ); })), PopupMenuItem( - padding: const EdgeInsets.only(left: 0), child: ListTile( dense: true, leading: const Icon(Icons.qr_code_scanner_outlined), @@ -146,7 +147,6 @@ class MoreEnum extends StatelessWidget { }, )), PopupMenuItem( - padding: const EdgeInsets.only(left: 0), child: ListTile( dense: true, leading: const Icon(Icons.phone_iphone), @@ -159,7 +159,6 @@ class MoreEnum extends StatelessWidget { }, )), PopupMenuItem( - padding: const EdgeInsets.only(left: 0), child: ListTile( dense: true, leading: const Icon(Icons.construction), diff --git a/lib/ui/mobile/mobile.dart b/lib/ui/mobile/mobile.dart index b5aea9a..5a0059a 100644 --- a/lib/ui/mobile/mobile.dart +++ b/lib/ui/mobile/mobile.dart @@ -26,7 +26,7 @@ class MobileHomePage extends StatefulWidget { } class MobileHomeState extends State implements EventListener { - final requestStateKey = GlobalKey(); + final GlobalKey requestStateKey = GlobalKey(); late ProxyServer proxyServer; ValueNotifier desktop = ValueNotifier(RemoteModel(connect: false)); @@ -57,7 +57,7 @@ class MobileHomeState extends State implements EventListener { }); super.initState(); - if (widget.configuration.upgradeNoticeV2) { + if (widget.configuration.upgradeNoticeV3) { WidgetsBinding.instance.addPostFrameCallback((_) { showUpgradeNotice(); }); @@ -86,7 +86,7 @@ class MobileHomeState extends State implements EventListener { MoreEnum(proxyServer: proxyServer, desktop: desktop), const SizedBox(width: 10) ]), - drawer: DrawerWidget(proxyServer: proxyServer), + drawer: DrawerWidget(proxyServer: proxyServer, requestStateKey: requestStateKey), floatingActionButton: FloatingActionButton( onPressed: null, child: Center( @@ -110,15 +110,13 @@ class MobileHomeState extends State implements EventListener { showUpgradeNotice() { String content = '提示:默认不会开启HTTPS抓包,请安装证书后再开启HTTPS抓包。\n\n' '新增更新:\n' - '1. 增加工具箱,提供常用编解码,增加HTTP请求,可粘贴cURL格式解析发起请求;\n' - '2. 请求编辑发送可直接查看响应体,发送请求无需开启代理;\n' - '3. 详情增加快速请求重写, 复制cURL格式可直接导入Postman;\n' - '4. 增加请求收藏功能;\n' - '5. 主题增加Material3切换;\n' - '6. 请求删除&大响应体直接转发;\n' - '7. 安卓应用白名单,调整请求展示列表;'; - showAlertDialog('更新内容V1.0.2', content, () { - widget.configuration.upgradeNoticeV2 = false; + '1. 增加历史记录功能,默认不会保存,需要去历史页点击保存;\n' + '2. 请求重写增加名称&URL参数重写;\n' + '3. 请求重写增加重定向;\n' + '4. 建立连接异常显示请求体;\n' + '5. 请求编辑重发响应体查看增加多种格式,详情Body体增加快速解码入口;'; + showAlertDialog('更新内容V1.0.3', content, () { + widget.configuration.upgradeNoticeV3 = false; widget.configuration.flushConfig(); }); } diff --git a/lib/ui/mobile/request/history.dart b/lib/ui/mobile/request/history.dart new file mode 100644 index 0000000..3735ae4 --- /dev/null +++ b/lib/ui/mobile/request/history.dart @@ -0,0 +1,200 @@ +import 'dart:async'; +import 'dart:collection'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:date_format/date_format.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_toastr/flutter_toastr.dart'; +import 'package:network_proxy/network/bin/server.dart'; +import 'package:network_proxy/network/channel.dart'; +import 'package:network_proxy/network/handler.dart'; +import 'package:network_proxy/network/http/http.dart'; +import 'package:network_proxy/storage/histories.dart'; +import 'package:network_proxy/ui/component/utils.dart'; +import 'package:network_proxy/ui/mobile/request/list.dart'; + +import '../../../utils/har.dart'; + +class MobileHistory extends StatefulWidget { + final ProxyServer proxyServer; + final GlobalKey requestStateKey; + + const MobileHistory({Key? key, required this.proxyServer, required this.requestStateKey}) : super(key: key); + + @override + State createState() { + return _MobileHistoryState(); + } +} + +class _MobileHistoryState extends State { + ///是否保存会话 + static bool _sessionSaved = false; + static WriteTask? writeTask; + + @override + Widget build(BuildContext context) { + return futureWidget(HistoryStorage.instance, (data) { + List children = []; + + var container = widget.requestStateKey.currentState?.container; + if (container?.isNotEmpty == true && !_sessionSaved) { + //当前会话未保存,是否保存当前会话 + children.add(buildSaveSession(data, container!)); + } + + var entries = data.histories.entries; + for (int i = entries.length - 1; i >= 0; i--) { + var entry = entries.elementAt(i); + children.add(buildItem(data, entry.key, entry.value)); + } + + if (children.isEmpty) { + return const Center(child: Text("暂无历史记录")); + } + return ListView.separated( + itemCount: children.length, + itemBuilder: (_, index) => children[index], + separatorBuilder: (_, index) => const Divider(thickness: 0.3, height: 0), + ); + }); + } + + //构建保存会话 + Widget buildSaveSession(HistoryStorage storage, List container) { + var name = formatDate(DateTime.now(), [mm, '-', d, ' ', HH, ':', nn, ':', ss]); + + return ListTile( + dense: true, + title: Text(name), + subtitle: Text("当前会话未保存 记录数 ${container.length}"), + trailing: TextButton.icon( + icon: const Icon(Icons.save), + label: const Text("保存"), + onPressed: () async { + await _writeHarFile(storage, container, name); + setState(() { + _sessionSaved = true; + }); + }, + ), + onTap: () {}); + } + + //写入文件 + _writeHarFile(HistoryStorage storage, List container, String name) async { + var file = await HistoryStorage.openFile("${DateTime.now().millisecondsSinceEpoch}.txt"); + print(file); + RandomAccessFile open = await file.open(mode: FileMode.append); + await storage.addHistory(name, file, 0); + + writeTask = WriteTask(name, open, storage); + writeTask?.writeList.addAll(container); + widget.proxyServer.addListener(writeTask!); + await writeTask?.writeTask(); + writeTask?.startTask(); + setState(() {}); + } + + //构建历史记录 + Widget buildItem(HistoryStorage storage, String name, HistoryItem item) { + return ListTile( + dense: true, + title: Text(name), + subtitle: Text("记录数 ${item.requestLength} 文件 ${item.size}"), + onTap: () { + Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) { + return Scaffold( + appBar: AppBar(title: Text('$name 记录数 ${item.requestLength}',style: const TextStyle(fontSize: 16))), + body: futureWidget( + loading: true, + storage.getRequests(name), + (data) => RequestListWidget(proxyServer: widget.proxyServer, list: data))); + })).then((value) => Future.delayed(const Duration(seconds: 60), () => storage.removeCache(name))); + }, + onLongPress: () => deleteHistory(storage, name)); + } + + //删除 + deleteHistory(HistoryStorage storage, String name) { + showDialog( + context: context, + builder: (ctx) { + return AlertDialog( + title: const Text("是否删除该历史记录?", style: TextStyle(fontSize: 18)), + actions: [ + TextButton( + onPressed: () { + Navigator.pop(context); + }, + child: const Text("取消")), + TextButton( + onPressed: () { + setState(() { + if (name == writeTask?.name) { + writeTask?.timer?.cancel(); + writeTask?.open.close(); + writeTask = null; + } + storage.removeHistory(name); + }); + FlutterToastr.show('删除成功', context); + Navigator.pop(context); + }, + child: const Text("删除")), + ], + ); + }); + } +} + +class WriteTask implements EventListener { + final HistoryStorage historyStorage; + final RandomAccessFile open; + Queue writeList = Queue(); + Timer? timer; + final String name; + + WriteTask(this.name, this.open, this.historyStorage); + + //写入任务 + startTask() { + timer = Timer.periodic(const Duration(seconds: 15), (it) => writeTask()); + } + + @override + void onRequest(Channel channel, HttpRequest request) {} + + @override + void onResponse(Channel channel, HttpResponse response) { + if (response.request == null) { + return; + } + writeList.add(response.request!); + } + + //写入任务 + writeTask() async { + if (writeList.isEmpty) { + return; + } + var history = historyStorage.getHistory(name); + int length = history.requestLength; + + while (writeList.isNotEmpty) { + var request = writeList.removeFirst(); + var har = Har.toHar(request); + + await open.writeString(jsonEncode(har)); + await open.writeString(",\n"); + length++; + } + + await open.flush(); //刷新 + + history.requestLength = length; + history.fileSize = await open.length(); + historyStorage.updateHistory(name, history); + } +} diff --git a/lib/ui/mobile/request/list.dart b/lib/ui/mobile/request/list.dart index 9a8a0b8..20e8220 100644 --- a/lib/ui/mobile/request/list.dart +++ b/lib/ui/mobile/request/list.dart @@ -14,8 +14,9 @@ import 'package:network_proxy/ui/mobile/request/request.dart'; class RequestListWidget extends StatefulWidget { final ProxyServer proxyServer; + final List? list; - const RequestListWidget({super.key, required this.proxyServer}); + const RequestListWidget({super.key, required this.proxyServer, this.list}); @override State createState() { @@ -29,18 +30,32 @@ class RequestListState extends State { const Tab(child: Text('域名列表')), ]; - GlobalKey requestSequenceKey = GlobalKey(); - GlobalKey domainListKey = GlobalKey(); + final GlobalKey requestSequenceKey = GlobalKey(); + final GlobalKey domainListKey = GlobalKey(); //请求列表容器 - static List container = []; + List container = []; + + @override + void initState() { + super.initState(); + if (widget.list != null) { + container.addAll(widget.list!); + } + print(domainListKey); + } + + @override + void dispose() { + super.dispose(); + } @override Widget build(BuildContext context) { return DefaultTabController( length: tabs.length, child: Scaffold( - appBar: AppBar(title: TabBar(tabs: tabs)), + appBar: AppBar(title: TabBar(tabs: tabs), automaticallyImplyLeading: false), body: TabBarView( children: [ RequestSequence( @@ -144,10 +159,8 @@ class RequestSequenceState extends State with AutomaticKeepAliv return; } - print("object ${searchModel?.filter(response.request!, response)} ${state == null}"); //搜索视图 if (searchModel?.filter(response.request!, response) == true && state == null) { - print("contains ${view.contains(response.request)}"); if (!view.contains(response.request)) { view.addFirst(response.request!); diff --git a/lib/ui/mobile/setting/request_rewrite.dart b/lib/ui/mobile/setting/request_rewrite.dart index 36626f4..9ab88e5 100644 --- a/lib/ui/mobile/setting/request_rewrite.dart +++ b/lib/ui/mobile/setting/request_rewrite.dart @@ -38,7 +38,7 @@ class _MobileRequestRewriteState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text("请求重写")), + appBar: AppBar(title: const Text("请求重写", style: TextStyle(fontSize: 16))), body: Container( padding: const EdgeInsets.all(10), child: Column( @@ -59,22 +59,22 @@ class _MobileRequestRewriteState extends State { const SizedBox(height: 10), Row(children: [ FilledButton.icon( - icon: const Icon(Icons.add), + icon: const Icon(Icons.add, size: 18), onPressed: () { add(); }, - label: const Text("增加")), + label: const Text("增加", style: TextStyle(fontSize: 14))), const SizedBox(width: 10), OutlinedButton.icon( onPressed: () { var selectedIndex = requestRuleList.currentSelectedIndex(); add(selectedIndex); }, - icon: const Icon(Icons.edit), - label: const Text("编辑")), + icon: const Icon(Icons.edit, size: 18), + label: const Text("编辑", style: TextStyle(fontSize: 14))), TextButton.icon( - icon: const Icon(Icons.remove), - label: const Text("删除"), + icon: const Icon(Icons.remove, size: 18), + label: const Text("删除", style: TextStyle(fontSize: 14)), onPressed: () { var removeSelected = requestRuleList.removeSelected(); if (removeSelected.isEmpty) { @@ -308,7 +308,9 @@ class _RequestRuleListState extends State { child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: DataTable( - dataRowMaxHeight: 100, + dataRowMinHeight: 30, + dataRowMaxHeight: 60, + columnSpacing: 10, border: TableBorder.symmetric(outside: BorderSide(width: 1, color: Theme.of(context).highlightColor)), columns: const [ DataColumn(label: Text('名称')), diff --git a/lib/ui/mobile/setting/ssl.dart b/lib/ui/mobile/setting/ssl.dart index 00d2006..8ef3d91 100644 --- a/lib/ui/mobile/setting/ssl.dart +++ b/lib/ui/mobile/setting/ssl.dart @@ -30,13 +30,13 @@ class _MobileSslState extends State { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text("HTTPS代理"), + title: const Text("HTTPS代理", style: TextStyle(fontSize: 16)), centerTitle: true, ), body: ListView(children: [ SwitchListTile( hoverColor: Colors.transparent, - title: const Text("启用HTTPS代理", style: TextStyle(fontSize: 16)), + title: const Text("启用HTTPS代理"), value: widget.proxyServer.enableSsl, onChanged: (val) { widget.proxyServer.enableSsl = val; diff --git a/lib/utils/har.dart b/lib/utils/har.dart index d44a2b3..07a9053 100644 --- a/lib/utils/har.dart +++ b/lib/utils/har.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:network_proxy/network/host_port.dart'; import 'package:network_proxy/network/http/http.dart'; class Har { @@ -118,6 +119,7 @@ class Har { httpRequest.response = httpResponse; httpResponse?.request = httpRequest; + httpRequest.hostAndPort = HostAndPort.of(httpRequest.requestUrl); return httpRequest; } } diff --git a/pubspec.yaml b/pubspec.yaml index 0901249..cd18ccb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: network_proxy description: network proxy publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 1.0.2+5 +version: 1.0.3+1 environment: sdk: '>=3.0.2 <4.0.0'