mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-05-20 16:15:47 +08:00
v1.1.6-Beta
This commit is contained in:
@@ -226,7 +226,7 @@
|
||||
"shareCurl": "Share cURL Request",
|
||||
"shareRequestResponse": "Share Request and Response",
|
||||
"captureDetail": "Capture Detail",
|
||||
"proxyPinSoftware": "ProxyPin Full platform packet capture software",
|
||||
"proxyPinSoftware": "ProxyPin Open source traffic capture software for all platforms",
|
||||
|
||||
"prompt": "Prompt",
|
||||
"curlSchemeRequest": "If the curl format is recognized, should it be converted into an HTTP request?",
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
"shareCurl": "分享 cURL 请求",
|
||||
"shareRequestResponse": "分享请求和响应",
|
||||
"captureDetail": "抓包详情",
|
||||
"proxyPinSoftware": "ProxyPin全平台抓包软件",
|
||||
"proxyPinSoftware": "ProxyPin全平台开源抓包软件",
|
||||
|
||||
"prompt": "提示",
|
||||
"curlSchemeRequest": "识别到curl格式,是否转换为HTTP请求?",
|
||||
|
||||
@@ -85,7 +85,7 @@ Widget multiWindow(int windowId, Map<dynamic, dynamic> argument) {
|
||||
}
|
||||
|
||||
if (argument['name'] == 'CertHashPage') {
|
||||
return CertHashPage();
|
||||
return CertHashPage(windowId: windowId);
|
||||
}
|
||||
|
||||
if (argument['name'] == 'JavaScript') {
|
||||
@@ -93,7 +93,7 @@ Widget multiWindow(int windowId, Map<dynamic, dynamic> argument) {
|
||||
}
|
||||
|
||||
if (argument['name'] == 'RegExpPage') {
|
||||
return const RegExpPage();
|
||||
return RegExpPage(windowId: windowId);
|
||||
}
|
||||
if (argument['name'] == 'TimestampPage') {
|
||||
return TimestampPage(windowId: windowId);
|
||||
|
||||
@@ -79,7 +79,7 @@ InputDecoration decoration(BuildContext context, {String? label, String? hintTex
|
||||
labelText: label,
|
||||
hintText: hintText,
|
||||
suffixIcon: suffixIcon,
|
||||
hintStyle: TextStyle(color: Colors.grey.shade500),
|
||||
hintStyle: TextStyle(color: Colors.grey.shade500, fontSize: 15),
|
||||
border: OutlineInputBorder(borderSide: BorderSide(width: 0.8, color: color)),
|
||||
enabledBorder: OutlineInputBorder(borderSide: BorderSide(width: 1.3, color: color)),
|
||||
focusedBorder: OutlineInputBorder(borderSide: BorderSide(width: 2, color: color)));
|
||||
|
||||
@@ -15,20 +15,24 @@
|
||||
*/
|
||||
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_toastr/flutter_toastr.dart';
|
||||
import 'package:proxypin/network/util/cert/x509.dart';
|
||||
import 'package:proxypin/ui/component/buttons.dart';
|
||||
import 'package:proxypin/ui/component/text_field.dart';
|
||||
import 'package:proxypin/utils/platform.dart';
|
||||
|
||||
///证书哈希名称查看
|
||||
///@author Hongen Wang
|
||||
class CertHashPage extends StatefulWidget {
|
||||
const CertHashPage({super.key});
|
||||
final int? windowId;
|
||||
|
||||
const CertHashPage({super.key, this.windowId});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
@@ -42,13 +46,34 @@ class _CertHashPageState extends State<CertHashPage> {
|
||||
|
||||
AppLocalizations get localizations => AppLocalizations.of(context)!;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (Platforms.isDesktop() && widget.windowId != null) {
|
||||
HardwareKeyboard.instance.addHandler(onKeyEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
input.dispose();
|
||||
decodeData.dispose();
|
||||
HardwareKeyboard.instance.removeHandler(onKeyEvent);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool onKeyEvent(KeyEvent event) {
|
||||
if (widget.windowId == null) return false;
|
||||
if ((HardwareKeyboard.instance.isMetaPressed || HardwareKeyboard.instance.isControlPressed) &&
|
||||
event.logicalKey == LogicalKeyboardKey.keyW) {
|
||||
HardwareKeyboard.instance.removeHandler(onKeyEvent);
|
||||
WindowController.fromWindowId(widget.windowId!).close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -99,7 +124,8 @@ class _CertHashPageState extends State<CertHashPage> {
|
||||
decoration: decoration(context, label: localizations.inputContent))),
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: TextButton(onPressed: () {}, child: Text("${localizations.output}:", style: TextStyle(fontSize: 16)))),
|
||||
child: TextButton(
|
||||
onPressed: () {}, child: Text("${localizations.output}:", style: TextStyle(fontSize: 16)))),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(10),
|
||||
@@ -139,6 +165,4 @@ class _CertHashPageState extends State<CertHashPage> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -58,14 +59,31 @@ class _QrCodePageState extends State<QrCodePage> with SingleTickerProviderStateM
|
||||
if (Platforms.isMobile()) {
|
||||
tabController = TabController(initialIndex: 0, length: tabs.length, vsync: this);
|
||||
}
|
||||
|
||||
if (Platforms.isDesktop() && widget.windowId != null) {
|
||||
HardwareKeyboard.instance.addHandler(onKeyEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
tabController?.dispose();
|
||||
HardwareKeyboard.instance.removeHandler(onKeyEvent);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool onKeyEvent(KeyEvent event) {
|
||||
if (widget.windowId == null) return false;
|
||||
if ((HardwareKeyboard.instance.isMetaPressed || HardwareKeyboard.instance.isControlPressed) &&
|
||||
event.logicalKey == LogicalKeyboardKey.keyW) {
|
||||
HardwareKeyboard.instance.removeHandler(onKeyEvent);
|
||||
WindowController.fromWindowId(widget.windowId!).close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (Platforms.isDesktop()) {
|
||||
|
||||
@@ -14,17 +14,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_toastr/flutter_toastr.dart';
|
||||
import 'package:proxypin/ui/component/buttons.dart';
|
||||
import 'package:proxypin/ui/component/text_field.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:proxypin/utils/platform.dart';
|
||||
|
||||
///正则表达式工具
|
||||
///@author Hongen Wang
|
||||
class RegExpPage extends StatefulWidget {
|
||||
const RegExpPage({super.key});
|
||||
final int? windowId;
|
||||
|
||||
const RegExpPage({super.key, this.windowId});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
@@ -45,6 +49,10 @@ class _RegExpPageState extends State<RegExpPage> {
|
||||
super.initState();
|
||||
pattern.addListener(onInputChangeMatch);
|
||||
input.addListener(onInputChangeMatch);
|
||||
|
||||
if (Platforms.isDesktop() && widget.windowId != null) {
|
||||
HardwareKeyboard.instance.addHandler(onKeyEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -52,9 +60,22 @@ class _RegExpPageState extends State<RegExpPage> {
|
||||
pattern.dispose();
|
||||
input.dispose();
|
||||
replaceText.dispose();
|
||||
HardwareKeyboard.instance.removeHandler(onKeyEvent);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool onKeyEvent(KeyEvent event) {
|
||||
if (widget.windowId == null) return false;
|
||||
if ((HardwareKeyboard.instance.isMetaPressed || HardwareKeyboard.instance.isControlPressed) &&
|
||||
event.logicalKey == LogicalKeyboardKey.keyW) {
|
||||
HardwareKeyboard.instance.removeHandler(onKeyEvent);
|
||||
WindowController.fromWindowId(widget.windowId!).close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color primaryColor = Theme.of(context).colorScheme.primary;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
@@ -48,6 +49,10 @@ class _TimestampPageState extends State<TimestampPage> {
|
||||
}
|
||||
nowTimestamp.text = (DateTime.now().millisecondsSinceEpoch ~/ 1000).toString();
|
||||
});
|
||||
|
||||
if (Platforms.isDesktop() && widget.windowId != null) {
|
||||
HardwareKeyboard.instance.addHandler(onKeyEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -57,9 +62,22 @@ class _TimestampPageState extends State<TimestampPage> {
|
||||
dateTime.dispose();
|
||||
timestampOut.dispose();
|
||||
dateTimeOut.dispose();
|
||||
HardwareKeyboard.instance.removeHandler(onKeyEvent);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
bool onKeyEvent(KeyEvent event) {
|
||||
if (widget.windowId == null) return false;
|
||||
if ((HardwareKeyboard.instance.isMetaPressed || HardwareKeyboard.instance.isControlPressed) &&
|
||||
event.logicalKey == LogicalKeyboardKey.keyW) {
|
||||
HardwareKeyboard.instance.removeHandler(onKeyEvent);
|
||||
WindowController.fromWindowId(widget.windowId!).close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
TextStyle? get textStyle => Theme.of(context).textTheme.titleMedium;
|
||||
|
||||
bool get isCN => Localizations.localeOf(context) == const Locale.fromSubtags(languageCode: 'zh');
|
||||
@@ -89,9 +107,9 @@ class _TimestampPageState extends State<TimestampPage> {
|
||||
if (Platforms.isDesktop())
|
||||
Wrap(spacing: 10.0, runSpacing: 10.0, crossAxisAlignment: WrapCrossAlignment.center, children: [
|
||||
timestampLabel(),
|
||||
SizedBox(width: 210, child: timestampField()),
|
||||
SizedBox(width: 220, child: timestampField()),
|
||||
timestampButton(),
|
||||
SizedBox(width: 200, child: timestampOutField()),
|
||||
SizedBox(width: 210, child: timestampOutField()),
|
||||
]),
|
||||
if (Platforms.isMobile())
|
||||
Row(children: [
|
||||
@@ -112,9 +130,9 @@ class _TimestampPageState extends State<TimestampPage> {
|
||||
if (Platforms.isDesktop())
|
||||
Wrap(spacing: 10.0, runSpacing: 10.0, crossAxisAlignment: WrapCrossAlignment.center, children: [
|
||||
timeLabel(),
|
||||
SizedBox(width: 210, child: timeField()),
|
||||
SizedBox(width: 220, child: timeField()),
|
||||
timeButton(),
|
||||
SizedBox(width: 200, child: timeOutField())
|
||||
SizedBox(width: 210, child: timeOutField())
|
||||
]),
|
||||
if (Platforms.isMobile())
|
||||
Row(children: [
|
||||
|
||||
@@ -60,7 +60,7 @@ class AppConfiguration {
|
||||
Locale? _language;
|
||||
|
||||
//是否显示更新内容公告
|
||||
bool upgradeNoticeV15 = true;
|
||||
bool upgradeNoticeV16 = true;
|
||||
|
||||
/// 是否启用画中画
|
||||
ValueNotifier<bool> pipEnabled = ValueNotifier(Platform.isAndroid);
|
||||
@@ -177,7 +177,7 @@ class AppConfiguration {
|
||||
_theme = ThemeModel(mode: mode, useMaterial3: config['useMaterial3'] ?? true);
|
||||
_theme.color = config['themeColor'] ?? "Blue";
|
||||
|
||||
upgradeNoticeV15 = config['upgradeNoticeV15'] ?? true;
|
||||
upgradeNoticeV16 = config['upgradeNoticeV16'] ?? true;
|
||||
_language = config['language'] == null ? null : Locale.fromSubtags(languageCode: config['language']);
|
||||
pipEnabled.value = config['pipEnabled'] ?? true;
|
||||
pipIcon.value = config['pipIcon'] ?? false;
|
||||
@@ -222,7 +222,7 @@ class AppConfiguration {
|
||||
'mode': _theme.mode.name,
|
||||
'themeColor': _theme.color,
|
||||
'useMaterial3': _theme.useMaterial3,
|
||||
'upgradeNoticeV15': upgradeNoticeV15,
|
||||
'upgradeNoticeV16': upgradeNoticeV16,
|
||||
"language": _language?.languageCode,
|
||||
"headerExpanded": headerExpanded,
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ class _DesktopHomePagePageState extends State<DesktopHomePage> implements EventL
|
||||
proxyServer.addListener(this);
|
||||
panel = NetworkTabController(tabStyle: const TextStyle(fontSize: 16), proxyServer: proxyServer);
|
||||
|
||||
if (widget.appConfiguration.upgradeNoticeV15) {
|
||||
if (widget.appConfiguration.upgradeNoticeV16) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
showUpgradeNotice();
|
||||
});
|
||||
@@ -142,37 +142,37 @@ class _DesktopHomePagePageState extends State<DesktopHomePage> implements EventL
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
widget.appConfiguration.upgradeNoticeV15 = false;
|
||||
widget.appConfiguration.upgradeNoticeV16 = false;
|
||||
widget.appConfiguration.flushConfig();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text(localizations.cancel))
|
||||
],
|
||||
title: Text(isCN ? '更新内容V1.1.5' : "Update content V1.1.5", style: const TextStyle(fontSize: 18)),
|
||||
title: Text(isCN ? '更新内容V1.1.6' : "Update content V1.1.6", style: const TextStyle(fontSize: 18)),
|
||||
content: Container(
|
||||
constraints: const BoxConstraints(maxWidth: 600),
|
||||
child: SelectableText(
|
||||
isCN
|
||||
? '提示:默认不会开启HTTPS抓包,请安装证书后再开启HTTPS抓包。\n'
|
||||
'点击HTTPS抓包(加锁图标),选择安装根证书,按照提示操作即可。\n\n'
|
||||
'1. 请求重写升级UI优化, 请求修改增加匹配数据查看;\n'
|
||||
'2. 请求弹出菜单UI优化, 支持请求高亮;\n'
|
||||
'3. 脚本内置File Api, 支持文件读取、写入等操作, 详细查看wiki文档;\n'
|
||||
"4. 脚本内置MD5方法, md5('xxx');\n"
|
||||
'5. 支持内存自动清理设置, 到内存限制自动清理请求;\n'
|
||||
'6. 工具箱增加正则表达式, 支持匹配数据替换;\n'
|
||||
'7. ios支持生成新根证书, 生成需要重新安装根证书;\n'
|
||||
'8. 修复暗黑模式icon展示不清晰;\n'
|
||||
'1. 新增Hosts设置, 支持域名映射;\n'
|
||||
'2. 工具箱新增时间戳转换;\n'
|
||||
'3. 修复脚本编辑键盘弹出安全模式问题;\n'
|
||||
'4. 修复脚本URL编码问题;\n'
|
||||
'5. 修复请求屏蔽编辑多出空格问题;\n'
|
||||
'6. 修复ipad分享点击无效问题;\n'
|
||||
'7. 修复高级重放次数过多不执行问题;\n'
|
||||
'8. 应用黑白名单增加清除无效应用,添加过滤已存在应用;\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. Request to rewrite and upgrade UI optimization, request to modify and add matching data viewing;\n'
|
||||
'2. Request pop-up menu UI optimization, support request highlighting;\n'
|
||||
'3. The script has built-in File Api, which supports file reading, writing and other operations. For details, please refer to the wiki document;\n'
|
||||
"4. The script has built-in MD5 method, md5('xxx');\n"
|
||||
'5. Support memory automatic cleanup settings, memory limit automatic cleanup requests;\n'
|
||||
'6. Toolbox adds regular expressions to support matching data replacement;\n'
|
||||
'7. iOS supports generating new root certificates, which requires reinstalling the root certificate;\n'
|
||||
'8. Fixed unclear display of dark mode icon;\n'
|
||||
'1. Added Hosts settings to support domain name mapping;\n'
|
||||
'2. Toolbox adds timestamp conversion;\n'
|
||||
'3. Fixed script editing keyboard pop-up safe mode issue;\n'
|
||||
'4. Fixed script URL encoding issue;\n'
|
||||
'5. Fixed the issue of extra spaces in request mask editing;\n'
|
||||
'6. Fixed the issue that iPad share clicks are invalid;\n'
|
||||
'7. Fixed the issue that the advanced replay would not execute if there were too many times;\n'
|
||||
'8. Add and remove invalid applications in the application blacklist and whitelist;\n'
|
||||
'',
|
||||
style: const TextStyle(fontSize: 14))));
|
||||
});
|
||||
|
||||
@@ -256,7 +256,7 @@ class _HttpState extends State<_HttpWidget> {
|
||||
message = widget.message;
|
||||
body = TextEditingController(text: widget.message?.bodyAsString);
|
||||
if (widget.message?.headers == null && !widget.readOnly) {
|
||||
initHeader["User-Agent"] = ["ProxyPin/1.1.5"];
|
||||
initHeader["User-Agent"] = ["ProxyPin/1.1.6"];
|
||||
initHeader["Accept"] = ["*/*"];
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -349,9 +349,9 @@ class _DomainListState extends State<DomainList> {
|
||||
},
|
||||
child: Container(
|
||||
color: selected[index] == true
|
||||
? primaryColor.withOpacity(0.8)
|
||||
? primaryColor.withOpacity(0.6)
|
||||
: index.isEven
|
||||
? Colors.grey.withOpacity(0.15)
|
||||
? Colors.grey.withOpacity(0.1)
|
||||
: null,
|
||||
height: 38,
|
||||
padding: const EdgeInsets.symmetric(vertical: 3),
|
||||
|
||||
@@ -199,7 +199,7 @@ class _HostsDialogState extends State<HostsDialog> {
|
||||
color: selected.contains(item)
|
||||
? primaryColor.withOpacity(0.6)
|
||||
: isEven
|
||||
? Colors.grey.withOpacity(0.15)
|
||||
? Colors.grey.withOpacity(0.1)
|
||||
: null,
|
||||
height: 35,
|
||||
padding: padding ?? const EdgeInsets.symmetric(vertical: 3),
|
||||
@@ -311,7 +311,7 @@ class _HostsDialogState extends State<HostsDialog> {
|
||||
});
|
||||
}
|
||||
|
||||
showEdit({HostsItem? item, HostsItem? parent, bool? isFolder = false}) {
|
||||
showEdit({HostsItem? item, HostsItem? parent, bool? isFolder}) {
|
||||
isFolder ??= item?.isFolder == true;
|
||||
showDialog(
|
||||
context: context,
|
||||
|
||||
@@ -110,7 +110,7 @@ class _RequestBlockState extends State<RequestBlock> {
|
||||
onSecondaryTapDown: (details) => showMenus(details, index),
|
||||
onDoubleTap: () => showEdit(index),
|
||||
child: Container(
|
||||
color: index.isEven ? Colors.grey.withOpacity(0.15) : null,
|
||||
color: index.isEven ? Colors.grey.withOpacity(0.10) : null,
|
||||
height: 36,
|
||||
padding: const EdgeInsets.symmetric(vertical: 3),
|
||||
child: Row(
|
||||
|
||||
@@ -326,9 +326,9 @@ class _RequestRuleListState extends State<RequestRuleList> {
|
||||
},
|
||||
child: Container(
|
||||
color: selected[index] == true
|
||||
? primaryColor.withOpacity(0.8)
|
||||
? primaryColor.withOpacity(0.6)
|
||||
: index.isEven
|
||||
? Colors.grey.withOpacity(0.15)
|
||||
? Colors.grey.withOpacity(0.1)
|
||||
: null,
|
||||
height: 30,
|
||||
padding: const EdgeInsets.all(5),
|
||||
|
||||
@@ -404,7 +404,7 @@ class _UpdateListState extends State<UpdateList> {
|
||||
color: selected == index
|
||||
? primaryColor
|
||||
: index.isEven
|
||||
? Colors.grey.withOpacity(0.15)
|
||||
? Colors.grey.withOpacity(0.1)
|
||||
: null,
|
||||
height: 30,
|
||||
padding: const EdgeInsets.all(5),
|
||||
|
||||
@@ -114,7 +114,7 @@ class MobileHomeState extends State<MobileHomePage> implements EventListener, Li
|
||||
proxyServer.addListener(this);
|
||||
proxyServer.start();
|
||||
|
||||
if (widget.appConfiguration.upgradeNoticeV15) {
|
||||
if (widget.appConfiguration.upgradeNoticeV16) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
showUpgradeNotice();
|
||||
});
|
||||
@@ -261,25 +261,25 @@ class MobileHomeState extends State<MobileHomePage> implements EventListener, Li
|
||||
? '提示:默认不会开启HTTPS抓包,请安装证书后再开启HTTPS抓包。\n\n'
|
||||
'1. 新增Hosts设置, 支持域名映射;\n'
|
||||
'2. 工具箱新增时间戳转换;\n'
|
||||
'3. 脚本内置File Api, 支持文件读取、写入等操作, 详细查看wiki文档;\n'
|
||||
"4. 脚本内置MD5方法, md5('xxx');\n"
|
||||
'5. 支持内存自动清理设置, 到内存限制自动清理请求;\n'
|
||||
'6. 工具箱增加正则表达式, 支持匹配数据替换;\n'
|
||||
'7. ios支持生成新根证书, 生成需要重新安装根证书;\n'
|
||||
'8. 修复暗黑模式icon展示不清晰;\n'
|
||||
'3. 修复脚本编辑键盘弹出安全模式问题;\n'
|
||||
'4. 修复脚本URL编码问题;\n'
|
||||
'5. 修复请求屏蔽编辑多出空格问题;\n'
|
||||
'6. 修复ipad分享点击无效问题;\n'
|
||||
'7. 修复高级重放次数过多不执行问题;\n'
|
||||
'8. 应用黑白名单增加清除无效应用,添加过滤已存在应用;\n'
|
||||
: 'Tips:By default, HTTPS packet capture will not be enabled. Please install the certificate before enabling HTTPS packet capture。\n\n'
|
||||
'Click HTTPS Capture packets(Lock icon),Choose to install the root certificate and follow the prompts to proceed。\n\n'
|
||||
'1. Added Hosts settings to support domain name mapping;\n'
|
||||
'2. Toolbox adds timestamp conversion;\n'
|
||||
'3. The script has built-in File Api, which supports file reading, writing and other operations. For details, please refer to the wiki document;\n'
|
||||
"4. The script has built-in MD5 method, md5('xxx');\n"
|
||||
'5. Support memory automatic cleanup settings, memory limit automatic cleanup requests;\n'
|
||||
'6. Toolbox adds regular expressions to support matching data replacement;\n'
|
||||
'7. iOS supports generating new root certificates, which requires reinstalling the root certificate;\n'
|
||||
'8. Fixed unclear display of dark mode icon;\n'
|
||||
'3. Fixed script editing keyboard pop-up safe mode issue;\n'
|
||||
'4. Fixed script URL encoding issue;\n'
|
||||
'5. Fixed the issue of extra spaces in request mask editing;\n'
|
||||
'6. Fixed the issue that iPad share clicks are invalid;\n'
|
||||
'7. Fixed the issue that the advanced replay would not execute if there were too many times;\n'
|
||||
'8. Add and remove invalid applications in the application blacklist and whitelist;\n'
|
||||
'';
|
||||
showAlertDialog(isCN ? '更新内容V1.1.5' : "Update content V1.1.5", content, () {
|
||||
widget.appConfiguration.upgradeNoticeV15 = false;
|
||||
showAlertDialog(isCN ? '更新内容V1.1.6' : "Update content V1.1.6", content, () {
|
||||
widget.appConfiguration.upgradeNoticeV16 = false;
|
||||
widget.appConfiguration.flushConfig();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ class _HttpState extends State<_HttpWidget> with AutomaticKeepAliveClientMixin {
|
||||
message = widget.message;
|
||||
body = widget.message?.bodyAsString;
|
||||
if (widget.message?.headers == null && !widget.readOnly) {
|
||||
initHeader["User-Agent"] = ["ProxyPin/1.1.5"];
|
||||
initHeader["User-Agent"] = ["ProxyPin/1.1.6"];
|
||||
initHeader["Accept"] = ["*/*"];
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ class _HostsPageState extends State<HostsPage> {
|
||||
showEdit(isFolder: true);
|
||||
}
|
||||
|
||||
showEdit({HostsItem? item, HostsItem? parent, bool? isFolder = false}) {
|
||||
showEdit({HostsItem? item, HostsItem? parent, bool? isFolder}) {
|
||||
isFolder ??= item?.isFolder == true;
|
||||
showDialog(
|
||||
context: context,
|
||||
|
||||
@@ -39,7 +39,7 @@ class About extends StatelessWidget {
|
||||
padding: const EdgeInsets.only(left: 10, right: 10),
|
||||
child: Text(isCN ? "全平台开源免费抓包软件" : "Full platform open source free capture HTTP(S) traffic software")),
|
||||
const SizedBox(height: 10),
|
||||
const Text("V1.1.5"),
|
||||
const Text("V1.1.6"),
|
||||
ListTile(
|
||||
title: const Text("Github"),
|
||||
trailing: const Icon(Icons.arrow_right),
|
||||
|
||||
@@ -81,7 +81,7 @@ class Har {
|
||||
title = title.contains("ProxyPin") ? title : "[ProxyPin]$title";
|
||||
har["log"] = {
|
||||
"version": "1.2",
|
||||
"creator": {"name": "ProxyPin", "version": "1.1.5"},
|
||||
"creator": {"name": "ProxyPin", "version": "1.1.6"},
|
||||
"pages": [
|
||||
{
|
||||
"title": title,
|
||||
|
||||
Reference in New Issue
Block a user