手机端JS脚本

This commit is contained in:
wanghongen
2023-10-20 01:24:58 +08:00
parent 6d71982ee6
commit 9cc6a54892
11 changed files with 162 additions and 125 deletions

View File

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

View File

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

View File

@@ -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);
})
],
);

View File

@@ -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()),
))
]);

View File

@@ -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('同步成功')));
}
}),
],
);

View File

@@ -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();
}),

View File

@@ -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))),
],
)));
});
}