From 7b224b9f6107aa42f1cbf3a793dd93a3aac6dcbc Mon Sep 17 00:00:00 2001 From: wanghongenpin Date: Fri, 5 Jan 2024 03:19:35 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=AB=98=E7=BA=A7=E9=87=8D?= =?UTF-8?q?=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle | 1 + ios/Runner/Info.plist | 2 + lib/l10n/app_en.arb | 6 +- lib/l10n/app_zh.arb | 6 +- lib/ui/desktop/desktop.dart | 4 +- lib/ui/desktop/left/favorite.dart | 31 +++++--- lib/ui/desktop/left/repeat.dart | 99 ++++++++++++++++++++++++++ lib/ui/desktop/left/request.dart | 27 +++++-- lib/ui/mobile/mobile.dart | 6 +- lib/ui/mobile/request/favorite.dart | 40 ++++++++--- lib/ui/mobile/request/repeat.dart | 105 ++++++++++++++++++++++++++++ lib/ui/mobile/request/request.dart | 40 ++++++++--- lib/ui/mobile/setting/script.dart | 2 +- pubspec.yaml | 2 +- 14 files changed, 327 insertions(+), 44 deletions(-) create mode 100644 lib/ui/desktop/left/repeat.dart create mode 100644 lib/ui/mobile/request/repeat.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 754ab3a..837efc3 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -51,6 +51,7 @@ android { defaultConfig { applicationId "com.network.proxy" + ndk { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86_64' } // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdkVersion 21 targetSdkVersion flutter.targetSdkVersion diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 338ce8d..f49480c 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -68,5 +68,7 @@ NSCameraUsageDescription 扫描二维码 + NSPhotoLibraryUsageDescription + 请求重写选择文件 diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 4373acd..957204d 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -120,7 +120,11 @@ "copyCurl": "Copy cURL", "delete": "Delete", "rename": "Rename", - "repeat": "Resend Request", + "repeat": "Repeat", + "customRepeat": "Custom Repeat", + "repeatCount": "Iterations", + "repeatInterval": "Interval(ms)", + "repeatDelay": "Delay(ms)", "editRequest": "Edit and Request", "reSendRequest": "The request has been resent", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 33aee8b..9b0e80c 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -120,7 +120,11 @@ "copyCurl": "复制 cURL 请求", "delete": "删除", "rename": "重命名", - "repeat": "重放请求", + "repeat": "重放", + "customRepeat": "高级重放", + "repeatCount": "次数", + "repeatInterval": "间隔(ms)", + "repeatDelay": "延时(ms)", "editRequest": "编辑请求重放", "reSendRequest": "已重新发送请求", diff --git a/lib/ui/desktop/desktop.dart b/lib/ui/desktop/desktop.dart index 65c6fb1..a1ace13 100644 --- a/lib/ui/desktop/desktop.dart +++ b/lib/ui/desktop/desktop.dart @@ -204,12 +204,14 @@ class _DesktopHomePagePageState extends State implements EventL '2. 请求重写支持文件选择;\n' '3. 抓包详情页面Headers默认展开配置;\n' '4. 请求编辑URL参数支持表单编辑;\n' + '5. 增加高级重放;\n' : 'Tips:By default, HTTPS packet capture will not be enabled. Please install the certificate before enabling HTTPS packet capture。\n' 'Click HTTPS Capture packets(Lock icon),Choose to install the root certificate and follow the prompts to proceed。\n\n' '1. Increase multilingual support;\n' '2. Request Rewrite support file selection;\n' '3. Details page Headers Expanded Config;\n' - '4. Request Edit URL parameter support for form editing;\n', + '4. Request Edit URL parameter support for form editing;\n' + '5. Support advanced replay;\n', style: const TextStyle(fontSize: 14))); }); } diff --git a/lib/ui/desktop/left/favorite.dart b/lib/ui/desktop/left/favorite.dart index a0cfd91..ea75755 100644 --- a/lib/ui/desktop/left/favorite.dart +++ b/lib/ui/desktop/left/favorite.dart @@ -16,6 +16,7 @@ import 'package:network_proxy/storage/favorites.dart'; import 'package:network_proxy/ui/component/utils.dart'; import 'package:network_proxy/ui/component/widgets.dart'; import 'package:network_proxy/ui/content/panel.dart'; +import 'package:network_proxy/ui/desktop/left/repeat.dart'; import 'package:network_proxy/utils/curl.dart'; import 'package:window_manager/window_manager.dart'; @@ -143,14 +144,8 @@ class _FavoriteItemState extends State<_FavoriteItem> { }), const PopupMenuDivider(height: 0.3), popupItem(localizations.rename, onTap: () => rename(widget.favorite)), - popupItem(localizations.repeat, onTap: () { - var httpRequest = request.copy(uri: request.requestUrl); - var proxyInfo = - widget.panel.proxyServer.isRunning ? ProxyInfo.of("127.0.0.1", widget.panel.proxyServer.port) : null; - HttpClients.proxyRequest(httpRequest, proxyInfo: proxyInfo); - - FlutterToastr.show(localizations.reSendRequest, context); - }), + popupItem(localizations.repeat, onTap: () => onRepeat(request)), + popupItem(localizations.customRepeat, onTap: () => showCustomRepeat(request)), popupItem(localizations.editRequest, onTap: () { WidgetsBinding.instance.addPostFrameCallback((_) { requestEdit(); @@ -164,6 +159,26 @@ class _FavoriteItemState extends State<_FavoriteItem> { ); } + //显示高级重发 + showCustomRepeat(HttpRequest request) { + showDialog( + context: context, + builder: (BuildContext context) { + return CustomRepeatDialog(onRepeat: () => onRepeat(request)); + }); + } + + onRepeat(HttpRequest request) { + var httpRequest = request.copy(uri: request.requestUrl); + var proxyInfo = + widget.panel.proxyServer.isRunning ? ProxyInfo.of("127.0.0.1", widget.panel.proxyServer.port) : null; + HttpClients.proxyRequest(httpRequest, proxyInfo: proxyInfo); + + if (mounted) { + FlutterToastr.show(localizations.reSendRequest, context); + } + } + PopupMenuItem popupItem(String text, {VoidCallback? onTap}) { return CustomPopupMenuItem(height: 35, onTap: onTap, child: Text(text, style: const TextStyle(fontSize: 13))); } diff --git a/lib/ui/desktop/left/repeat.dart b/lib/ui/desktop/left/repeat.dart new file mode 100644 index 0000000..99a97ea --- /dev/null +++ b/lib/ui/desktop/left/repeat.dart @@ -0,0 +1,99 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +///高级重放 +/// @author wang +class CustomRepeatDialog extends StatefulWidget { + final Function onRepeat; + + const CustomRepeatDialog({super.key, required this.onRepeat}); + + @override + State createState() => _CustomRepeatState(); +} + +class _CustomRepeatState extends State { + TextEditingController count = TextEditingController(text: '1'); + TextEditingController interval = TextEditingController(text: '0'); + TextEditingController delay = TextEditingController(text: '0'); + + AppLocalizations get localizations => AppLocalizations.of(context)!; + + @override + void dispose() { + count.dispose(); + interval.dispose(); + delay.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final formKey = GlobalKey(); + + return AlertDialog( + title: Text(localizations.customRepeat, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)), + content: SingleChildScrollView( + child: Form( + key: formKey, + child: ListBody( + children: [ + field(localizations.repeatCount, count), //次数 + field(localizations.repeatInterval, interval), //间隔 + field(localizations.repeatDelay, delay), //延时 + ], + ), + )), + actions: [ + TextButton( + child: Text(localizations.cancel), + onPressed: () => Navigator.of(context).pop(), + ), + TextButton( + child: Text(localizations.done), + onPressed: () { + if (!formKey.currentState!.validate()) { + return; + } + Future.delayed(Duration(milliseconds: int.parse(delay.text)), + () => submitTask(int.parse(count.text), int.parse(interval.text))); + Navigator.of(context).pop(); + }, + ), + ], + ); + } + + //定时重放 + submitTask(int counter, var interval) { + if (counter <= 0) { + return; + } + Future.delayed(Duration(milliseconds: interval), () { + widget.onRepeat.call(); + if (counter - 1 > 0) { + submitTask(counter - 1, interval); + } + }); + } + + Widget field(String label, TextEditingController controller) { + return Row( + children: [ + SizedBox(width: 90, child: Text(label)), + Expanded( + child: TextFormField( + controller: controller, + keyboardType: TextInputType.number, + inputFormatters: [FilteringTextInputFormatter.digitsOnly], + decoration: const InputDecoration(), + validator: (val) => val == null || val.isEmpty ? localizations.cannotBeEmpty : null, + ), + ), + ], + ); + } +} diff --git a/lib/ui/desktop/left/request.dart b/lib/ui/desktop/left/request.dart index a4c381a..ebd66ee 100644 --- a/lib/ui/desktop/left/request.dart +++ b/lib/ui/desktop/left/request.dart @@ -14,6 +14,7 @@ import 'package:network_proxy/storage/favorites.dart'; import 'package:network_proxy/ui/component/utils.dart'; import 'package:network_proxy/ui/component/widgets.dart'; import 'package:network_proxy/ui/content/panel.dart'; +import 'package:network_proxy/ui/desktop/left/repeat.dart'; import 'package:network_proxy/utils/curl.dart'; import 'package:network_proxy/utils/lang.dart'; import 'package:window_manager/window_manager.dart'; @@ -107,13 +108,8 @@ class _RequestWidgetState extends State { .then((value) => FlutterToastr.show(localizations.copied, context)); }), const PopupMenuDivider(height: 0.3), - popupItem(localizations.repeat, onTap: () { - var request = widget.request.copy(uri: widget.request.requestUrl); - var proxyInfo = widget.proxyServer.isRunning ? ProxyInfo.of("127.0.0.1", widget.proxyServer.port) : null; - HttpClients.proxyRequest(request, proxyInfo: proxyInfo); - - FlutterToastr.show(localizations.reSendRequest, context); - }), + popupItem(localizations.repeat, onTap: () => onRepeat(widget.request)), + popupItem(localizations.customRepeat, onTap: () => showCustomRepeat(widget.request)), popupItem(localizations.editRequest, onTap: () { WidgetsBinding.instance.addPostFrameCallback((_) { requestEdit(); @@ -131,6 +127,23 @@ class _RequestWidgetState extends State { ); } + //显示高级重发 + showCustomRepeat(HttpRequest request) { + showDialog( + context: context, + builder: (BuildContext context) { + return CustomRepeatDialog(onRepeat: () => onRepeat(request)); + }); + } + + onRepeat(HttpRequest httpRequest) { + var request = httpRequest.copy(uri: httpRequest.requestUrl); + var proxyInfo = widget.proxyServer.isRunning ? ProxyInfo.of("127.0.0.1", widget.proxyServer.port) : null; + HttpClients.proxyRequest(request, proxyInfo: proxyInfo); + + FlutterToastr.show(localizations.reSendRequest, context); + } + PopupMenuItem popupItem(String text, {VoidCallback? onTap}) { return CustomPopupMenuItem(height: 32, onTap: onTap, child: Text(text, style: const TextStyle(fontSize: 13))); } diff --git a/lib/ui/mobile/mobile.dart b/lib/ui/mobile/mobile.dart index f06f24d..3046cac 100644 --- a/lib/ui/mobile/mobile.dart +++ b/lib/ui/mobile/mobile.dart @@ -208,11 +208,13 @@ class MobileHomeState extends State implements EventListener, Li '2. 请求重写支持文件选择;\n' '3. 抓包详情页面Headers默认展开配置;\n' '4. 请求编辑URL参数支持表单编辑;\n' + '5. 增加高级重放;\n' : 'Tips:By default, HTTPS packet capture will not be enabled. Please install the certificate before enabling HTTPS packet capture。\n\n' '1. Increase multilingual support;\n' '2. Request Rewrite support file selection;\n' - '3. Details page Headers Expanded Config;\n'; - '5. Request Edit URL parameter support for form editing;\n'; + '3. Details page Headers Expanded Config;\n' + '4. Request Edit URL parameter support for form editing;\n' + '5. Support advanced replay;\n'; showAlertDialog(isCN ? '更新内容V1.0.7' : "Update content V1.0.7", content, () { widget.appConfiguration.upgradeNoticeV7 = false; widget.appConfiguration.flushConfig(); diff --git a/lib/ui/mobile/request/favorite.dart b/lib/ui/mobile/request/favorite.dart index 7fdd050..fd7a65c 100644 --- a/lib/ui/mobile/request/favorite.dart +++ b/lib/ui/mobile/request/favorite.dart @@ -12,6 +12,7 @@ import 'package:network_proxy/network/http_client.dart'; import 'package:network_proxy/storage/favorites.dart'; import 'package:network_proxy/ui/component/utils.dart'; import 'package:network_proxy/ui/content/panel.dart'; +import 'package:network_proxy/ui/mobile/request/repeat.dart'; import 'package:network_proxy/ui/mobile/request/request_editor.dart'; import 'package:network_proxy/utils/curl.dart'; @@ -119,28 +120,28 @@ class _FavoriteItemState extends State<_FavoriteItem> { builder: (ctx) { return Wrap(alignment: WrapAlignment.center, children: [ menuItem(localizations.copyUrl, () => request.requestUrl), - const Divider(thickness: 0.5), + const Divider(thickness: 0.5, height: 5), menuItem(localizations.copyCurl, () => curlRequest(request)), - const Divider(thickness: 0.5), + const Divider(thickness: 0.5, height: 5), TextButton( child: SizedBox(width: double.infinity, child: Text(localizations.rename, textAlign: TextAlign.center)), onPressed: () { Navigator.of(context).pop(); rename(widget.favorite); }), - const Divider(thickness: 0.5), + const Divider(thickness: 0.5, height: 5), TextButton( child: SizedBox(width: double.infinity, child: Text(localizations.repeat, textAlign: TextAlign.center)), onPressed: () { - var httpRequest = request.copy(uri: request.requestUrl); - HttpClients.proxyRequest( - proxyInfo: widget.proxyServer.isRunning ? ProxyInfo.of("127.0.0.1", widget.proxyServer.port) : null, - httpRequest); - - FlutterToastr.show(localizations.reSendRequest, context); + onRepeat(request); Navigator.of(context).pop(); }), - const Divider(thickness: 0.5), + const Divider(thickness: 0.5, height: 5), + TextButton( + child: SizedBox( + width: double.infinity, child: Text(localizations.customRepeat, textAlign: TextAlign.center)), + onPressed: () => showCustomRepeat(request)), + const Divider(thickness: 0.5, height: 5), TextButton( child: SizedBox(width: double.infinity, child: Text(localizations.editRequest, textAlign: TextAlign.center)), @@ -149,7 +150,7 @@ class _FavoriteItemState extends State<_FavoriteItem> { Navigator.of(context).push(MaterialPageRoute( builder: (context) => MobileRequestEditor(request: request, proxyServer: widget.proxyServer))); }), - const Divider(thickness: 0.5), + const Divider(thickness: 0.5, height: 5), TextButton( child: SizedBox( width: double.infinity, child: Text(localizations.deleteFavorite, textAlign: TextAlign.center)), @@ -174,6 +175,23 @@ class _FavoriteItemState extends State<_FavoriteItem> { ); } + //显示高级重发 + showCustomRepeat(HttpRequest request) { + Navigator.of(context).pop(); + Navigator.of(context) + .push(MaterialPageRoute(builder: (context) => MobileCustomRepeat(onRepeat: () => onRepeat(request)))); + } + + onRepeat(HttpRequest request) { + var httpRequest = request.copy(uri: request.requestUrl); + var proxyInfo = widget.proxyServer.isRunning ? ProxyInfo.of("127.0.0.1", widget.proxyServer.port) : null; + HttpClients.proxyRequest(httpRequest, proxyInfo: proxyInfo); + + if (mounted) { + FlutterToastr.show(localizations.reSendRequest, context); + } + } + Widget menuItem(String title, String Function() callback) { return TextButton( child: SizedBox(width: double.infinity, child: Text(title, textAlign: TextAlign.center)), diff --git a/lib/ui/mobile/request/repeat.dart b/lib/ui/mobile/request/repeat.dart new file mode 100644 index 0000000..804c1e9 --- /dev/null +++ b/lib/ui/mobile/request/repeat.dart @@ -0,0 +1,105 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +///高级重放 +/// @author wang +class MobileCustomRepeat extends StatefulWidget { + final Function onRepeat; + + const MobileCustomRepeat({super.key, required this.onRepeat}); + + @override + State createState() => _CustomRepeatState(); +} + +class _CustomRepeatState extends State { + TextEditingController count = TextEditingController(text: '1'); + TextEditingController interval = TextEditingController(text: '0'); + TextEditingController delay = TextEditingController(text: '0'); + + AppLocalizations get localizations => AppLocalizations.of(context)!; + + @override + void dispose() { + count.dispose(); + interval.dispose(); + delay.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final formKey = GlobalKey(); + + return Scaffold( + appBar: AppBar( + title: Text(localizations.customRepeat, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)), + actions: [ + TextButton( + child: Text(localizations.done), + onPressed: () { + if (!formKey.currentState!.validate()) { + return; + } + Future.delayed(Duration(milliseconds: int.parse(delay.text)), + () => submitTask(int.parse(count.text), int.parse(interval.text))); + Navigator.of(context).pop(); + }, + ) + ], + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(15), + child: Form( + key: formKey, + child: ListBody( + children: [ + field(localizations.repeatCount, count), //次数 + const SizedBox(height: 6), + field(localizations.repeatInterval, interval), //间隔 + const SizedBox(height: 6), + field(localizations.repeatDelay, delay), //延时 + ], + ), + ))); + } + + //定时重放 + submitTask(int counter, var interval) { + if (counter <= 0) { + return; + } + Future.delayed(Duration(milliseconds: interval), () { + widget.onRepeat.call(); + if (counter - 1 > 0) { + submitTask(counter - 1, interval); + } + }); + } + + Widget field(String label, TextEditingController controller) { + Color color = Theme.of(context).colorScheme.primary; + + return Row( + children: [ + SizedBox(width: 90, child: Text("$label :")), + Expanded( + child: TextFormField( + controller: controller, + keyboardType: TextInputType.number, + inputFormatters: [FilteringTextInputFormatter.digitsOnly], + decoration: InputDecoration( + contentPadding: const EdgeInsets.only(left: 10, right: 10, top: 5, bottom: 5), + border: OutlineInputBorder(borderSide: BorderSide(width: 1, color: color.withOpacity(0.3))), + enabledBorder: OutlineInputBorder(borderSide: BorderSide(width: 1.5, color: color.withOpacity(0.5))), + focusedBorder: OutlineInputBorder(borderSide: BorderSide(width: 2, color: color))), + validator: (val) => val == null || val.isEmpty ? localizations.cannotBeEmpty : null, + ), + ), + ], + ); + } +} diff --git a/lib/ui/mobile/request/request.dart b/lib/ui/mobile/request/request.dart index 6f790bd..d5a0fa9 100644 --- a/lib/ui/mobile/request/request.dart +++ b/lib/ui/mobile/request/request.dart @@ -10,6 +10,7 @@ import 'package:network_proxy/network/http_client.dart'; import 'package:network_proxy/storage/favorites.dart'; import 'package:network_proxy/ui/component/utils.dart'; import 'package:network_proxy/ui/content/panel.dart'; +import 'package:network_proxy/ui/mobile/request/repeat.dart'; import 'package:network_proxy/ui/mobile/request/request_editor.dart'; import 'package:network_proxy/utils/curl.dart'; import 'package:network_proxy/utils/lang.dart'; @@ -106,21 +107,21 @@ class RequestRowState extends State { builder: (ctx) { return Wrap(alignment: WrapAlignment.center, children: [ menuItem(localizations.copyUrl, () => widget.request.requestUrl), - const Divider(thickness: 0.5), + const Divider(thickness: 0.5, height: 5), menuItem(localizations.copyCurl, () => curlRequest(widget.request)), - const Divider(thickness: 0.5), + const Divider(thickness: 0.5, height: 5), TextButton( child: SizedBox(width: double.infinity, child: Text(localizations.repeat, textAlign: TextAlign.center)), onPressed: () { - var request = widget.request.copy(uri: widget.request.requestUrl); - HttpClients.proxyRequest( - proxyInfo: widget.proxyServer.isRunning ? ProxyInfo.of("127.0.0.1", widget.proxyServer.port) : null, - request); - - FlutterToastr.show(localizations.reSendRequest, context); + onRepeat(widget.request); Navigator.of(context).pop(); }), - const Divider(thickness: 0.5), + const Divider(thickness: 0.5, height: 5), + TextButton( + child: SizedBox( + width: double.infinity, child: Text(localizations.customRepeat, textAlign: TextAlign.center)), + onPressed: () => showCustomRepeat(widget.request)), + const Divider(thickness: 0.5, height: 5), TextButton( child: SizedBox(width: double.infinity, child: Text(localizations.editRequest, textAlign: TextAlign.center)), @@ -130,7 +131,7 @@ class RequestRowState extends State { builder: (context) => MobileRequestEditor(request: widget.request, proxyServer: widget.proxyServer))); }), - const Divider(thickness: 0.5), + const Divider(thickness: 0.5, height: 5), TextButton( child: SizedBox(width: double.infinity, child: Text(localizations.favorite, textAlign: TextAlign.center)), onPressed: () { @@ -138,7 +139,7 @@ class RequestRowState extends State { FlutterToastr.show(localizations.addSuccess, context); Navigator.of(context).pop(); }), - const Divider(thickness: 0.5), + const Divider(thickness: 0.5, height: 5), TextButton( child: SizedBox(width: double.infinity, child: Text(localizations.delete, textAlign: TextAlign.center)), onPressed: () { @@ -165,6 +166,23 @@ class RequestRowState extends State { ); } + //显示高级重发 + showCustomRepeat(HttpRequest request) { + Navigator.of(context).pop(); + Navigator.of(context) + .push(MaterialPageRoute(builder: (context) => MobileCustomRepeat(onRepeat: () => onRepeat(request)))); + } + + onRepeat(HttpRequest request) { + var httpRequest = request.copy(uri: request.requestUrl); + var proxyInfo = widget.proxyServer.isRunning ? ProxyInfo.of("127.0.0.1", widget.proxyServer.port) : null; + HttpClients.proxyRequest(httpRequest, proxyInfo: proxyInfo); + + if (mounted) { + FlutterToastr.show(localizations.reSendRequest, context); + } + } + Widget menuItem(String title, String Function() callback) { return TextButton( child: SizedBox(width: double.infinity, child: Text(title, textAlign: TextAlign.center)), diff --git a/lib/ui/mobile/setting/script.dart b/lib/ui/mobile/setting/script.dart index 41ca7a8..06b13e9 100644 --- a/lib/ui/mobile/setting/script.dart +++ b/lib/ui/mobile/setting/script.dart @@ -188,7 +188,7 @@ class _ScriptEditState extends State { return Scaffold( appBar: AppBar( title: Row(children: [ - Text(localizations.scriptEdit, style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500)), + Text(localizations.scriptEdit, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)), const SizedBox(width: 10), Text.rich(TextSpan( text: localizations.useGuide, diff --git a/pubspec.yaml b/pubspec.yaml index d821c85..7d0cbed 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: network_proxy description: ProxyPin publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 1.0.7+7 +version: 1.0.7+8 environment: sdk: '>=3.0.2 <4.0.0'