mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-06-01 17:15:48 +08:00
The script supports multiple URL matching
This commit is contained in:
@@ -335,7 +335,7 @@ class ScriptEdit extends StatefulWidget {
|
||||
class _ScriptEditState extends State<ScriptEdit> {
|
||||
late CodeController script;
|
||||
late TextEditingController nameController;
|
||||
late TextEditingController urlController;
|
||||
late List<TextEditingController> urlControllers;
|
||||
|
||||
AppLocalizations get localizations => AppLocalizations.of(context)!;
|
||||
|
||||
@@ -344,14 +344,18 @@ class _ScriptEditState extends State<ScriptEdit> {
|
||||
super.initState();
|
||||
script = CodeController(language: javascript, text: widget.script ?? ScriptManager.template);
|
||||
nameController = TextEditingController(text: widget.scriptItem?.name ?? widget.title);
|
||||
urlController = TextEditingController(text: widget.scriptItem?.url ?? widget.url);
|
||||
final urls = widget.scriptItem?.urls ?? (widget.url != null && widget.url!.isNotEmpty ? [widget.url!] : []);
|
||||
urlControllers =
|
||||
urls.isNotEmpty ? urls.map((u) => TextEditingController(text: u)).toList() : [TextEditingController()];
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
script.dispose();
|
||||
nameController.dispose();
|
||||
urlController.dispose();
|
||||
for (final c in urlControllers) {
|
||||
c.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -361,72 +365,130 @@ class _ScriptEditState extends State<ScriptEdit> {
|
||||
bool isCN = Localizations.localeOf(context) == const Locale.fromSubtags(languageCode: 'zh');
|
||||
|
||||
return AlertDialog(
|
||||
scrollable: true,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
|
||||
titlePadding: const EdgeInsets.only(left: 15, top: 5, right: 15),
|
||||
title: Row(children: [
|
||||
Text(localizations.scriptEdit, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
|
||||
const SizedBox(width: 10),
|
||||
Text.rich(TextSpan(
|
||||
text: localizations.useGuide,
|
||||
style: const TextStyle(color: Colors.blue, fontSize: 14),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => DesktopMultiWindow.invokeMethod(
|
||||
0,
|
||||
"launchUrl",
|
||||
isCN
|
||||
? 'https://gitee.com/wanghongenpin/proxypin/wikis/%E8%84%9A%E6%9C%AC'
|
||||
: 'https://github.com/wanghongenpin/proxypin/wiki/Script'))),
|
||||
const Expanded(child: Align(alignment: Alignment.topRight, child: CloseButton()))
|
||||
]),
|
||||
actionsPadding: const EdgeInsets.only(right: 10, bottom: 10),
|
||||
actions: [
|
||||
ElevatedButton(onPressed: () => Navigator.of(context).pop(), child: Text(localizations.cancel)),
|
||||
FilledButton(
|
||||
onPressed: () async {
|
||||
if (!(formKey.currentState as FormState).validate()) {
|
||||
FlutterToastr.show("${localizations.name} URL ${localizations.cannotBeEmpty}", context,
|
||||
position: FlutterToastr.top);
|
||||
return;
|
||||
}
|
||||
//新增
|
||||
if (widget.scriptItem == null) {
|
||||
var scriptItem = ScriptItem(true, nameController.text, urlController.text);
|
||||
await (await ScriptManager.instance).addScript(scriptItem, script.text);
|
||||
} else {
|
||||
widget.scriptItem?.name = nameController.text;
|
||||
widget.scriptItem?.url = urlController.text;
|
||||
widget.scriptItem?.urlReg = null;
|
||||
(await ScriptManager.instance).updateScript(widget.scriptItem!, script.text);
|
||||
}
|
||||
|
||||
_refreshScript();
|
||||
if (context.mounted) {
|
||||
Navigator.of(context).maybePop(true);
|
||||
}
|
||||
},
|
||||
child: Text(localizations.save)),
|
||||
],
|
||||
content: Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
textField("${localizations.name}:", nameController, localizations.pleaseEnter),
|
||||
const SizedBox(height: 10),
|
||||
textField("URL:", urlController, "github.com/api/*", keyboardType: TextInputType.url),
|
||||
const SizedBox(height: 10),
|
||||
Text("${localizations.script}:"),
|
||||
const SizedBox(height: 5),
|
||||
SizedBox(
|
||||
width: 850,
|
||||
height: 380,
|
||||
child: CodeTheme(
|
||||
data: CodeThemeData(styles: monokaiSublimeTheme),
|
||||
child: SingleChildScrollView(
|
||||
child: CodeField(textStyle: const TextStyle(fontSize: 13), controller: script))))
|
||||
],
|
||||
)));
|
||||
scrollable: true,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.0)),
|
||||
titlePadding: const EdgeInsets.only(left: 15, top: 5, right: 15),
|
||||
title: Row(children: [
|
||||
Text(localizations.scriptEdit, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
|
||||
const SizedBox(width: 10),
|
||||
Text.rich(TextSpan(
|
||||
text: localizations.useGuide,
|
||||
style: const TextStyle(color: Colors.blue, fontSize: 14),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () => DesktopMultiWindow.invokeMethod(
|
||||
0,
|
||||
"launchUrl",
|
||||
isCN
|
||||
? 'https://gitee.com/wanghongenpin/proxypin/wikis/%E8%84%9A%E6%9C%AC'
|
||||
: 'https://github.com/wanghongenpin/proxypin/wiki/Script'))),
|
||||
const Expanded(child: Align(alignment: Alignment.topRight, child: CloseButton()))
|
||||
]),
|
||||
actionsPadding: const EdgeInsets.only(right: 10, bottom: 10),
|
||||
actions: [
|
||||
ElevatedButton(onPressed: () => Navigator.of(context).pop(), child: Text(localizations.cancel)),
|
||||
FilledButton(
|
||||
onPressed: () async {
|
||||
if (!(formKey.currentState as FormState).validate()) {
|
||||
FlutterToastr.show("${localizations.name} URL ${localizations.cannotBeEmpty}", context,
|
||||
position: FlutterToastr.top);
|
||||
return;
|
||||
}
|
||||
final urls = urlControllers.map((c) => c.text.trim()).where((u) => u.isNotEmpty).toSet().toList();
|
||||
if (urls.isEmpty) {
|
||||
FlutterToastr.show("URL ${localizations.cannotBeEmpty}", context, position: FlutterToastr.top);
|
||||
return;
|
||||
}
|
||||
if (widget.scriptItem == null) {
|
||||
var scriptItem = ScriptItem(true, nameController.text, urls);
|
||||
await (await ScriptManager.instance).addScript(scriptItem, script.text);
|
||||
} else {
|
||||
widget.scriptItem?.name = nameController.text;
|
||||
widget.scriptItem?.urls = urls;
|
||||
widget.scriptItem?.urlRegs = null;
|
||||
(await ScriptManager.instance).updateScript(widget.scriptItem!, script.text);
|
||||
}
|
||||
_refreshScript();
|
||||
if (context.mounted) {
|
||||
Navigator.of(context).maybePop(true);
|
||||
}
|
||||
},
|
||||
child: Text(localizations.save)),
|
||||
],
|
||||
content: Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
textField("${localizations.name}:", nameController, localizations.pleaseEnter),
|
||||
const SizedBox(height: 3),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Text("URL(s):"),
|
||||
const SizedBox(width: 8),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.add_circle_outline, size: 20),
|
||||
tooltip: localizations.add,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
urlControllers.add(TextEditingController());
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
...List.generate(
|
||||
urlControllers.length,
|
||||
(i) => Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: urlControllers[i],
|
||||
validator: (val) => val?.isNotEmpty == true ? null : "",
|
||||
keyboardType: TextInputType.url,
|
||||
decoration: InputDecoration(
|
||||
hintText: "github.com/api/*",
|
||||
hintStyle: const TextStyle(fontSize: 14, color: Colors.grey),
|
||||
contentPadding: const EdgeInsets.all(10),
|
||||
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
||||
focusedBorder: focusedBorder(),
|
||||
isDense: true,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (urlControllers.length > 1)
|
||||
IconButton(
|
||||
icon: const Icon(Icons.remove_circle_outline, color: Colors.red),
|
||||
tooltip: localizations.delete,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
urlControllers[i].dispose();
|
||||
urlControllers.removeAt(i);
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"${localizations.script}:",
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
SizedBox(
|
||||
width: 850,
|
||||
height: 380,
|
||||
child: CodeTheme(
|
||||
data: CodeThemeData(styles: monokaiSublimeTheme),
|
||||
child: SingleChildScrollView(
|
||||
child: CodeField(textStyle: const TextStyle(fontSize: 13), controller: script))))
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
Widget textField(String label, TextEditingController controller, String hint, {TextInputType? keyboardType}) {
|
||||
@@ -439,6 +501,7 @@ class _ScriptEditState extends State<ScriptEdit> {
|
||||
keyboardType: keyboardType,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
hintStyle: const TextStyle(fontSize: 14, color: Colors.grey),
|
||||
contentPadding: const EdgeInsets.all(10),
|
||||
errorStyle: const TextStyle(height: 0, fontSize: 0),
|
||||
focusedBorder: focusedBorder(),
|
||||
@@ -573,13 +636,13 @@ class _ScriptListState extends State<ScriptList> {
|
||||
_refreshScript();
|
||||
}))),
|
||||
const SizedBox(width: 20),
|
||||
Expanded(child: Text(list[index].url, style: const TextStyle(fontSize: 13))),
|
||||
Expanded(child: Text(list[index].urls.join(', '), style: const TextStyle(fontSize: 13))),
|
||||
],
|
||||
)));
|
||||
});
|
||||
}
|
||||
|
||||
showGlobalMenu(Offset offset) {
|
||||
void showGlobalMenu(Offset offset) {
|
||||
showContextMenu(context, offset, items: [
|
||||
PopupMenuItem(height: 35, child: Text(localizations.newBuilt), onTap: () => showEdit()),
|
||||
PopupMenuItem(height: 35, child: Text(localizations.export), onTap: () => export(selected.toList())),
|
||||
|
||||
Reference in New Issue
Block a user