mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-05-22 16:25:49 +08:00
feat: add 'Copy as fetch' functionality (#685)
This commit is contained in:
@@ -159,6 +159,7 @@
|
||||
"copyRequestResponse": "Copy Request and Response",
|
||||
"copyCurl": "Copy cURL",
|
||||
"copyAsPythonRequests": "Copy as Python Requests",
|
||||
"copyAsFetch": "Copy as fetch",
|
||||
"delete": "Delete",
|
||||
"rename": "Rename",
|
||||
"repeat": "Repeat",
|
||||
|
||||
@@ -1014,6 +1014,12 @@ abstract class AppLocalizations {
|
||||
/// **'Copy as Python Requests'**
|
||||
String get copyAsPythonRequests;
|
||||
|
||||
/// No description provided for @copyAsFetch.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Copy as fetch'**
|
||||
String get copyAsFetch;
|
||||
|
||||
/// No description provided for @delete.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -473,6 +473,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get copyAsPythonRequests => 'Copy as Python Requests';
|
||||
|
||||
@override
|
||||
String get copyAsFetch => 'Copy as fetch';
|
||||
|
||||
@override
|
||||
String get delete => 'Delete';
|
||||
|
||||
|
||||
@@ -471,6 +471,9 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get copyAsPythonRequests => '复制 Python Requests';
|
||||
|
||||
@override
|
||||
String get copyAsFetch => '复制 fetch';
|
||||
|
||||
@override
|
||||
String get delete => '删除';
|
||||
|
||||
@@ -1559,6 +1562,9 @@ class AppLocalizationsZhHant extends AppLocalizationsZh {
|
||||
@override
|
||||
String get copyAsPythonRequests => '複製 Python Requests';
|
||||
|
||||
@override
|
||||
String get copyAsFetch => '複製 fetch';
|
||||
|
||||
@override
|
||||
String get delete => '刪除';
|
||||
|
||||
|
||||
@@ -160,6 +160,7 @@
|
||||
"copyRequestResponse": "复制 请求和响应",
|
||||
"copyCurl": "复制 cURL",
|
||||
"copyAsPythonRequests": "复制 Python Requests",
|
||||
"copyAsFetch": "复制 fetch",
|
||||
"delete": "删除",
|
||||
"rename": "重命名",
|
||||
"repeat": "重放",
|
||||
|
||||
@@ -152,6 +152,7 @@
|
||||
"copyRequestResponse": "複製 請求和回應",
|
||||
"copyCurl": "複製 cURL",
|
||||
"copyAsPythonRequests": "複製 Python Requests",
|
||||
"copyAsFetch": "複製 fetch",
|
||||
"delete": "刪除",
|
||||
"rename": "重新命名",
|
||||
"repeat": "重放",
|
||||
|
||||
@@ -45,8 +45,10 @@ class ShareWidget extends StatelessWidget {
|
||||
FlutterToastr.show(localizations.emptyData, context);
|
||||
return;
|
||||
}
|
||||
Share.share(request!.requestUrl,
|
||||
subject: localizations.proxyPinSoftware, sharePositionOrigin: await _sharePositionOrigin(context));
|
||||
SharePlus.instance.share(ShareParams(
|
||||
text: request!.requestUrl,
|
||||
subject: localizations.proxyPinSoftware,
|
||||
sharePositionOrigin: await _sharePositionOrigin(context)));
|
||||
},
|
||||
),
|
||||
PopupMenuItem(
|
||||
@@ -60,10 +62,11 @@ class ShareWidget extends StatelessWidget {
|
||||
var file = XFile.fromData(utf8.encode(copyRequest(request!, response)),
|
||||
name: localizations.captureDetail, mimeType: "txt");
|
||||
|
||||
Share.shareXFiles([file],
|
||||
SharePlus.instance.share(ShareParams(
|
||||
files: [file],
|
||||
fileNameOverrides: ['request.txt'],
|
||||
text: localizations.proxyPinSoftware,
|
||||
sharePositionOrigin: await _sharePositionOrigin(context));
|
||||
sharePositionOrigin: await _sharePositionOrigin(context)));
|
||||
}),
|
||||
PopupMenuItem(
|
||||
padding: const EdgeInsets.only(left: 10, right: 2),
|
||||
@@ -75,10 +78,22 @@ class ShareWidget extends StatelessWidget {
|
||||
var text = curlRequest(request!);
|
||||
var file = XFile.fromData(utf8.encode(text), name: "cURL.txt", mimeType: "txt");
|
||||
|
||||
Share.shareXFiles([file],
|
||||
SharePlus.instance.share(ShareParams(
|
||||
files: [file],
|
||||
fileNameOverrides: ["cURL.txt"],
|
||||
text: localizations.proxyPinSoftware,
|
||||
sharePositionOrigin: await _sharePositionOrigin(context));
|
||||
sharePositionOrigin: await _sharePositionOrigin(context)));
|
||||
}),
|
||||
PopupMenuItem(
|
||||
padding: const EdgeInsets.only(left: 10, right: 2),
|
||||
child: Text("${localizations.share} Fetch API"),
|
||||
onTap: () async {
|
||||
if (request == null) {
|
||||
return;
|
||||
}
|
||||
var text = copyAsFetch(request!);
|
||||
SharePlus.instance
|
||||
.share(ShareParams(text: text, sharePositionOrigin: await _sharePositionOrigin(context)));
|
||||
}),
|
||||
PopupMenuItem(
|
||||
enabled: QuickShareService.isRemoteConnected(proxyServer),
|
||||
|
||||
@@ -204,6 +204,13 @@ class _RequestWidgetState extends State<RequestWidget> {
|
||||
.then((value) => FlutterToastr.show(localizations.copied, rootNavigator: true, context));
|
||||
},
|
||||
),
|
||||
MenuItem(
|
||||
label: localizations.copyAsFetch,
|
||||
onClick: (_) {
|
||||
Clipboard.setData(ClipboardData(text: copyAsFetch(widget.request)))
|
||||
.then((value) => FlutterToastr.show(localizations.copied, rootNavigator: true, context));
|
||||
},
|
||||
),
|
||||
])),
|
||||
MenuItem.separator(),
|
||||
MenuItem(
|
||||
|
||||
@@ -546,8 +546,11 @@ class _MobileAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
|
||||
return AppBar(
|
||||
leading: bottomNavigation ? const SizedBox() : null,
|
||||
systemOverlayStyle:
|
||||
Platform.isAndroid ? SystemUiOverlayStyle(systemNavigationBarColor: ColorScheme.of(context).surface) : null,
|
||||
systemOverlayStyle: Platform.isAndroid
|
||||
? SystemUiOverlayStyle(
|
||||
systemNavigationBarColor: ColorScheme.of(context).surface,
|
||||
statusBarColor: ColorScheme.of(context).surface)
|
||||
: null,
|
||||
title: MobileSearch(
|
||||
key: MobileApp.searchStateKey, onSearch: (val) => MobileApp.requestStateKey.currentState?.search(val)),
|
||||
actions: [
|
||||
|
||||
@@ -17,6 +17,34 @@
|
||||
import 'package:proxypin/network/http/http.dart';
|
||||
import 'package:proxypin/network/http/http_headers.dart';
|
||||
import 'package:proxypin/utils/lang.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
/// 复制为 fetch 请求
|
||||
String copyAsFetch(HttpRequest request) {
|
||||
final headers = request.headers.entries
|
||||
.where((entry) => entry.key.toLowerCase() != 'content-length')
|
||||
.toList();
|
||||
|
||||
final sb = StringBuffer();
|
||||
sb.writeln('fetch(${jsonEncode(request.requestUrl)}, {');
|
||||
sb.writeln(' method: ${jsonEncode(request.method.name.toUpperCase())},');
|
||||
|
||||
if (headers.isNotEmpty) {
|
||||
sb.writeln(' headers: {');
|
||||
for (final entry in headers) {
|
||||
sb.writeln(' ${jsonEncode(entry.key)}: ${jsonEncode(entry.value)},');
|
||||
}
|
||||
sb.writeln(' },');
|
||||
}
|
||||
|
||||
if (request.bodyAsString.isNotEmpty) {
|
||||
sb.writeln(' body: ${jsonEncode(request.bodyAsString)},');
|
||||
}
|
||||
|
||||
sb.writeln('});');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
///复制cURL请求
|
||||
String curlRequest(HttpRequest request) {
|
||||
|
||||
Reference in New Issue
Block a user