mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-05-20 16:15:47 +08:00
手机端JS脚本
This commit is contained in:
@@ -21,7 +21,7 @@ async function onRequest(context, request) {
|
||||
//request.headers["X-New-Headers"] = "My-Value";
|
||||
|
||||
// Update Body 使用fetch API请求接口,具体文档可网上搜索fetch API
|
||||
//response.body = await fetch('https://www.baidu.com/').then(response => response.text());
|
||||
//request.body = await fetch('https://www.baidu.com/').then(response => response.text());
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -163,10 +163,10 @@ async function onResponse(context, request, response) {
|
||||
var context = jsonEncode(scriptContext(item));
|
||||
var jsRequest = jsonEncode(convertJsRequest(request));
|
||||
String script = await getScript(item);
|
||||
|
||||
var jsResult = await flutterJs.evaluateAsync(
|
||||
"""var request = $jsRequest, context = $context; request['context'] = context; $script\n onRequest(context, request)""");
|
||||
var result = await jsResultResolve(jsResult);
|
||||
|
||||
request.attributes['scriptContext'] = result['context'];
|
||||
return convertHttpRequest(request, result);
|
||||
}
|
||||
@@ -187,11 +187,10 @@ async function onResponse(context, request, response) {
|
||||
var context = jsonEncode(request.attributes['scriptContext'] ?? scriptContext(item));
|
||||
var jsRequest = jsonEncode(convertJsRequest(request));
|
||||
var jsResponse = jsonEncode(convertJsResponse(response));
|
||||
print(context);
|
||||
String script = await getScript(item);
|
||||
var jsResult = await flutterJs.evaluateAsync("""$script\n onResponse($context, $jsRequest,$jsResponse);""");
|
||||
// print("response: ${jsResult.isPromise} ${jsResult.isError} ${jsResult.rawResult}");
|
||||
var result = await jsResultResolve(jsResult);
|
||||
// print("response: ${jsResult.isPromise} ${jsResult.isError} $result");
|
||||
return convertHttpResponse(response, result);
|
||||
}
|
||||
}
|
||||
@@ -204,10 +203,11 @@ async function onResponse(context, request, response) {
|
||||
jsResult = await flutterJs.handlePromise(jsResult);
|
||||
}
|
||||
var result = jsResult.rawResult;
|
||||
if (Platform.isMacOS) {
|
||||
if (Platform.isMacOS || Platform.isIOS) {
|
||||
result = flutterJs.convertValue(jsResult);
|
||||
}
|
||||
if (result is Future) {
|
||||
flutterJs.executePendingJob();
|
||||
result = await (jsResult.rawResult as Future);
|
||||
}
|
||||
if (result is String) {
|
||||
|
||||
@@ -50,9 +50,9 @@ class FavoriteStorage {
|
||||
flushConfig();
|
||||
}
|
||||
|
||||
static Future<void> removeFavorite(HttpRequest request) async {
|
||||
static Future<void> removeFavorite(Favorite favorite) async {
|
||||
var list = await favorites;
|
||||
list.remove(request);
|
||||
list.remove(favorite);
|
||||
|
||||
flushConfig();
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ class _FavoritesState extends State<Favorites> {
|
||||
request,
|
||||
index: index,
|
||||
panel: widget.panel,
|
||||
onRemove: (HttpRequest request) {
|
||||
FavoriteStorage.removeFavorite(request);
|
||||
onRemove: (Favorite favorite) {
|
||||
FavoriteStorage.removeFavorite(favorite);
|
||||
FlutterToastr.show('已删除收藏', context);
|
||||
setState(() {});
|
||||
},
|
||||
@@ -68,7 +68,7 @@ class _FavoriteItem extends StatefulWidget {
|
||||
final int index;
|
||||
final Favorite favorite;
|
||||
final NetworkTabController panel;
|
||||
final Function(HttpRequest request)? onRemove;
|
||||
final Function(Favorite favorite)? onRemove;
|
||||
|
||||
const _FavoriteItem(this.favorite, {Key? key, required this.panel, required this.onRemove, required this.index})
|
||||
: super(key: key);
|
||||
@@ -148,7 +148,7 @@ class _FavoriteItemState extends State<_FavoriteItem> {
|
||||
}),
|
||||
const PopupMenuDivider(height: 0.3),
|
||||
popupItem("删除收藏", onTap: () {
|
||||
widget.onRemove?.call(request);
|
||||
widget.onRemove?.call(widget.favorite);
|
||||
})
|
||||
],
|
||||
);
|
||||
|
||||
@@ -294,10 +294,10 @@ class _ScriptEditState extends State<ScriptEdit> {
|
||||
keyboardType: keyboardType,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
contentPadding: const EdgeInsets.all(10),
|
||||
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
||||
focusedBorder: focusedBorder(),
|
||||
isDense: true,
|
||||
constraints: const BoxConstraints(maxHeight: 35),
|
||||
border: const OutlineInputBorder()),
|
||||
))
|
||||
]);
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:network_proxy/network/bin/configuration.dart';
|
||||
import 'package:network_proxy/network/bin/server.dart';
|
||||
import 'package:network_proxy/network/http_client.dart';
|
||||
import 'package:network_proxy/network/util/host_filter.dart';
|
||||
import 'package:network_proxy/network/util/script_manager.dart';
|
||||
|
||||
class RemoteModel {
|
||||
final bool connect;
|
||||
@@ -102,16 +103,18 @@ class ConfigSyncState extends State<ConfigSyncWidget> {
|
||||
bool syncWhiteList = true;
|
||||
bool syncBlackList = true;
|
||||
bool syncRewrite = true;
|
||||
bool syncScript = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('同步配置', style: TextStyle(fontSize: 16)),
|
||||
content: SizedBox(
|
||||
height: 230,
|
||||
height: 260,
|
||||
child: Column(
|
||||
children: [
|
||||
SwitchListTile(
|
||||
dense: true,
|
||||
subtitle: const Text("同步白名单过滤"),
|
||||
value: syncWhiteList,
|
||||
onChanged: (val) {
|
||||
@@ -120,6 +123,7 @@ class ConfigSyncState extends State<ConfigSyncWidget> {
|
||||
});
|
||||
}),
|
||||
SwitchListTile(
|
||||
dense: true,
|
||||
subtitle: const Text("同步黑名单过滤"),
|
||||
value: syncBlackList,
|
||||
onChanged: (val) {
|
||||
@@ -128,6 +132,7 @@ class ConfigSyncState extends State<ConfigSyncWidget> {
|
||||
});
|
||||
}),
|
||||
SwitchListTile(
|
||||
dense: true,
|
||||
subtitle: const Text("同步请求重写"),
|
||||
value: syncRewrite,
|
||||
onChanged: (val) {
|
||||
@@ -135,6 +140,15 @@ class ConfigSyncState extends State<ConfigSyncWidget> {
|
||||
syncRewrite = val;
|
||||
});
|
||||
}),
|
||||
SwitchListTile(
|
||||
dense: true,
|
||||
subtitle: const Text("同步脚本"),
|
||||
value: syncScript,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
syncScript = val;
|
||||
});
|
||||
}),
|
||||
],
|
||||
)),
|
||||
actions: [
|
||||
@@ -145,7 +159,7 @@ class ConfigSyncState extends State<ConfigSyncWidget> {
|
||||
}),
|
||||
TextButton(
|
||||
child: const Text('开始同步'),
|
||||
onPressed: () {
|
||||
onPressed: () async {
|
||||
if (syncWhiteList) {
|
||||
HostFilter.whitelist.load(widget.config['whitelist']);
|
||||
}
|
||||
@@ -156,9 +170,18 @@ class ConfigSyncState extends State<ConfigSyncWidget> {
|
||||
widget.configuration.requestRewrites.load(widget.config['requestRewrites']);
|
||||
widget.configuration.flushRequestRewriteConfig();
|
||||
}
|
||||
if (syncScript) {
|
||||
await ScriptManager.instance.then((script) async {
|
||||
script.list.clear();
|
||||
widget.config['scripts'].forEach((it) => script.addScript(ScriptItem.fromJson(it), it['script']));
|
||||
await script.flushConfig();
|
||||
});
|
||||
}
|
||||
widget.configuration.flushConfig();
|
||||
Navigator.pop(context);
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('同步成功')));
|
||||
if (mounted) {
|
||||
Navigator.pop(context);
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('同步成功')));
|
||||
}
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -46,8 +46,8 @@ class _FavoritesState extends State<MobileFavorites> {
|
||||
return _FavoriteItem(
|
||||
favorite,
|
||||
index: index,
|
||||
onRemove: (HttpRequest request) {
|
||||
FavoriteStorage.removeFavorite(request);
|
||||
onRemove: (Favorite favorite) {
|
||||
FavoriteStorage.removeFavorite(favorite);
|
||||
FlutterToastr.show('已删除收藏', context);
|
||||
setState(() {});
|
||||
},
|
||||
@@ -67,7 +67,7 @@ class _FavoriteItem extends StatefulWidget {
|
||||
final int index;
|
||||
final Favorite favorite;
|
||||
final ProxyServer proxyServer;
|
||||
final Function(HttpRequest request)? onRemove;
|
||||
final Function(Favorite favorite)? onRemove;
|
||||
|
||||
const _FavoriteItem(this.favorite, {Key? key, required this.onRemove, required this.proxyServer, required this.index})
|
||||
: super(key: key);
|
||||
@@ -121,8 +121,8 @@ class _FavoriteItemState extends State<_FavoriteItem> {
|
||||
TextButton(
|
||||
child: const SizedBox(width: double.infinity, child: Text("重命名", textAlign: TextAlign.center)),
|
||||
onPressed: () {
|
||||
rename(widget.favorite);
|
||||
Navigator.of(context).pop();
|
||||
rename(widget.favorite);
|
||||
}),
|
||||
const Divider(thickness: 0.5),
|
||||
TextButton(
|
||||
@@ -148,7 +148,7 @@ class _FavoriteItemState extends State<_FavoriteItem> {
|
||||
TextButton(
|
||||
child: const SizedBox(width: double.infinity, child: Text("删除收藏", textAlign: TextAlign.center)),
|
||||
onPressed: () {
|
||||
widget.onRemove?.call(request);
|
||||
widget.onRemove?.call(widget.favorite);
|
||||
FlutterToastr.show('删除成功', context);
|
||||
Navigator.of(context).pop();
|
||||
}),
|
||||
|
||||
@@ -64,26 +64,25 @@ class _MobileScriptState extends State<MobileScript> {
|
||||
_refreshScript();
|
||||
},
|
||||
)),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
const SizedBox(width: 10),
|
||||
FilledButton(
|
||||
style: ElevatedButton.styleFrom(padding: const EdgeInsets.only(left: 20, right: 20)),
|
||||
onPressed: scriptEdit,
|
||||
child: const Text("添加"),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
OutlinedButton(
|
||||
style: ElevatedButton.styleFrom(padding: const EdgeInsets.only(left: 20, right: 20)),
|
||||
onPressed: import,
|
||||
child: const Text("导入"),
|
||||
)
|
||||
],
|
||||
)),
|
||||
const SizedBox(width: 15)
|
||||
]),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
const SizedBox(width: 10),
|
||||
FilledButton(
|
||||
style: ElevatedButton.styleFrom(padding: const EdgeInsets.only(left: 20, right: 20)),
|
||||
onPressed: scriptEdit,
|
||||
child: const Text("添加"),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
OutlinedButton(
|
||||
style: ElevatedButton.styleFrom(padding: const EdgeInsets.only(left: 20, right: 20)),
|
||||
onPressed: import,
|
||||
child: const Text("导入"),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Container(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
@@ -98,7 +97,7 @@ class _MobileScriptState extends State<MobileScript> {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: 200, padding: const EdgeInsets.only(left: 10), child: const Text("名称")),
|
||||
width: 100, padding: const EdgeInsets.only(left: 10), child: const Text("名称")),
|
||||
const SizedBox(width: 50, child: Text("启用", textAlign: TextAlign.center)),
|
||||
const VerticalDivider(),
|
||||
const Expanded(child: Text("URL")),
|
||||
@@ -228,11 +227,11 @@ class _ScriptEditState extends State<ScriptEdit> {
|
||||
const Text("脚本:"),
|
||||
const SizedBox(height: 5),
|
||||
SizedBox(
|
||||
height: 400,
|
||||
height: 520,
|
||||
child: CodeTheme(
|
||||
data: CodeThemeData(styles: monokaiSublimeTheme),
|
||||
child: SingleChildScrollView(
|
||||
child: CodeField(textStyle: const TextStyle(fontSize: 13), controller: script))))
|
||||
child: CodeField(textStyle: const TextStyle(fontSize: 14), controller: script))))
|
||||
],
|
||||
))));
|
||||
}
|
||||
@@ -247,10 +246,10 @@ class _ScriptEditState extends State<ScriptEdit> {
|
||||
keyboardType: keyboardType,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
contentPadding: const EdgeInsets.all(10),
|
||||
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
||||
focusedBorder: focusedBorder(),
|
||||
isDense: true,
|
||||
constraints: const BoxConstraints(maxHeight: 38),
|
||||
border: const OutlineInputBorder()),
|
||||
))
|
||||
]);
|
||||
@@ -279,81 +278,83 @@ class _ScriptListState extends State<ScriptList> {
|
||||
|
||||
List<Widget> rows(List<ScriptItem> list) {
|
||||
return List.generate(list.length, (index) {
|
||||
return Ink(
|
||||
child: GestureDetector(
|
||||
onDoubleTap: () async {
|
||||
String script = await (await ScriptManager.instance).getScript(list[index]);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(builder: (context) => ScriptEdit(scriptItem: list[index], script: script)))
|
||||
.then((value) {
|
||||
if (value != null) {
|
||||
return InkWell(
|
||||
onDoubleTap: () async {
|
||||
String script = await (await ScriptManager.instance).getScript(list[index]);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(builder: (context) => ScriptEdit(scriptItem: list[index], script: script)))
|
||||
.then((value) {
|
||||
if (value != null) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
},
|
||||
onTapDown: (details) {
|
||||
showContextMenu(context, details.globalPosition, items: [
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("编辑"),
|
||||
onTap: () async {
|
||||
String script = await (await ScriptManager.instance).getScript(list[index]);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(
|
||||
builder: (context) => ScriptEdit(scriptItem: list[index], script: script)))
|
||||
.then((value) {
|
||||
if (value != null) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}),
|
||||
PopupMenuItem(height: 35, child: const Text("分享"), onTap: () => export(list[index])),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: list[index].enabled ? const Text("禁用") : const Text("启用"),
|
||||
onTap: () {
|
||||
list[index].enabled = !list[index].enabled;
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
},
|
||||
onLongPressDown: (details) {
|
||||
showContextMenu(context, details.globalPosition, items: [
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("编辑"),
|
||||
onTap: () async {
|
||||
String script = await (await ScriptManager.instance).getScript(list[index]);
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(
|
||||
builder: (context) => ScriptEdit(scriptItem: list[index], script: script)))
|
||||
.then((value) {
|
||||
if (value != null) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}),
|
||||
PopupMenuItem(height: 35, child: const Text("分享"), onTap: () => export(list[index])),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: list[index].enabled ? const Text("禁用") : const Text("启用"),
|
||||
onTap: () {
|
||||
list[index].enabled = !list[index].enabled;
|
||||
setState(() {});
|
||||
}),
|
||||
const PopupMenuDivider(),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("删除"),
|
||||
onTap: () async {
|
||||
(await ScriptManager.instance).removeScript(index);
|
||||
_refreshScript();
|
||||
setState(() {});
|
||||
if (context.mounted) FlutterToastr.show('删除成功', context);
|
||||
}),
|
||||
]);
|
||||
},
|
||||
child: Container(
|
||||
color: index.isEven ? Colors.grey.withOpacity(0.1) : null,
|
||||
height: 30,
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(width: 200, child: Text(list[index].name!, style: const TextStyle(fontSize: 13))),
|
||||
SizedBox(
|
||||
width: 40,
|
||||
child: Transform.scale(
|
||||
scale: 0.65,
|
||||
child: SwitchWidget(
|
||||
value: list[index].enabled,
|
||||
onChanged: (val) {
|
||||
list[index].enabled = val;
|
||||
_refreshScript();
|
||||
}))),
|
||||
const SizedBox(width: 20),
|
||||
Expanded(child: Text(list[index].url, style: const TextStyle(fontSize: 13))),
|
||||
],
|
||||
))));
|
||||
}),
|
||||
const PopupMenuDivider(),
|
||||
PopupMenuItem(
|
||||
height: 35,
|
||||
child: const Text("删除"),
|
||||
onTap: () async {
|
||||
(await ScriptManager.instance).removeScript(index);
|
||||
_refreshScript();
|
||||
setState(() {});
|
||||
if (context.mounted) FlutterToastr.show('删除成功', context);
|
||||
}),
|
||||
]);
|
||||
},
|
||||
child: Container(
|
||||
color: index.isEven ? Colors.grey.withOpacity(0.1) : null,
|
||||
height: 45,
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 100,
|
||||
child: Text(list[index].name!,
|
||||
style: const TextStyle(fontSize: 13), overflow: TextOverflow.ellipsis)),
|
||||
SizedBox(
|
||||
width: 50,
|
||||
child: Transform.scale(
|
||||
scale: 0.8,
|
||||
child: SwitchWidget(
|
||||
value: list[index].enabled,
|
||||
onChanged: (val) {
|
||||
list[index].enabled = val;
|
||||
_refreshScript();
|
||||
}))),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: Text(list[index].url, style: const TextStyle(fontSize: 13))),
|
||||
],
|
||||
)));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user