v1.1.6-Beta

This commit is contained in:
wanghongenpin
2024-11-11 18:45:14 +08:00
parent 7a00960d71
commit ac8e1fd6b1
23 changed files with 148 additions and 67 deletions

View File

@@ -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?",

View File

@@ -226,7 +226,7 @@
"shareCurl": "分享 cURL 请求",
"shareRequestResponse": "分享请求和响应",
"captureDetail": "抓包详情",
"proxyPinSoftware": "ProxyPin全平台抓包软件",
"proxyPinSoftware": "ProxyPin全平台开源抓包软件",
"prompt": "提示",
"curlSchemeRequest": "识别到curl格式是否转换为HTTP请求",

View File

@@ -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);

View File

@@ -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)));

View File

@@ -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;
}
}
}

View File

@@ -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()) {

View File

@@ -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;

View File

@@ -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: [

View File

@@ -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,

View File

@@ -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'
: 'TipsBy 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))));
});

View File

@@ -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;
}

View File

@@ -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),

View File

@@ -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,

View File

@@ -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(

View File

@@ -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),

View File

@@ -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),

View File

@@ -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'
: 'TipsBy 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();
});
}

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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),

View File

@@ -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,