mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-05-20 16:15:47 +08:00
@@ -62,6 +62,7 @@
|
||||
"importFailed": "Import failed",
|
||||
"export": "Export",
|
||||
"exportSuccess": "Export successful",
|
||||
"exportFailed": "Export failed",
|
||||
"deleteSuccess": "Delete successful",
|
||||
"send": "Send",
|
||||
"fail": "fail",
|
||||
|
||||
@@ -456,6 +456,12 @@ abstract class AppLocalizations {
|
||||
/// **'Export successful'**
|
||||
String get exportSuccess;
|
||||
|
||||
/// No description provided for @exportFailed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Export failed'**
|
||||
String get exportFailed;
|
||||
|
||||
/// No description provided for @deleteSuccess.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
|
||||
@@ -188,6 +188,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
@override
|
||||
String get exportSuccess => 'Export successful';
|
||||
|
||||
@override
|
||||
String get exportFailed => 'Export failed';
|
||||
|
||||
@override
|
||||
String get deleteSuccess => 'Delete successful';
|
||||
|
||||
|
||||
@@ -188,6 +188,9 @@ class AppLocalizationsZh extends AppLocalizations {
|
||||
@override
|
||||
String get exportSuccess => '导出成功';
|
||||
|
||||
@override
|
||||
String get exportFailed => '导出失败';
|
||||
|
||||
@override
|
||||
String get deleteSuccess => '删除成功';
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"importFailed": "导入失败",
|
||||
"export": "导出",
|
||||
"exportSuccess": "导出成功",
|
||||
"exportFailed": "导出失败",
|
||||
"deleteSuccess": "删除成功",
|
||||
"send": "发送",
|
||||
"fail": "失败",
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -41,6 +45,60 @@ class _RequestBreakpointPageState extends State<RequestBreakpointPage> {
|
||||
await _refreshConfig();
|
||||
}
|
||||
|
||||
Future<void> _import() async {
|
||||
|
||||
String? path;
|
||||
if (Platform.isMacOS) {
|
||||
path = await DesktopMultiWindow.invokeMethod(0, "pickFiles", {
|
||||
"allowedExtensions": ['json']
|
||||
});
|
||||
if (widget.windowId != null) WindowController.fromWindowId(widget.windowId!).show();
|
||||
} else {
|
||||
FilePickerResult? result =
|
||||
await FilePicker.platform.pickFiles(type: FileType.custom, allowedExtensions: ['json']);
|
||||
path = result?.files.single.path;
|
||||
}
|
||||
if (path == null) return;
|
||||
File file = File(path);
|
||||
try {
|
||||
String content = await file.readAsString();
|
||||
List<dynamic> list = jsonDecode(content);
|
||||
var rules = list.map((e) => RequestBreakpointRule.fromJson(e)).toList();
|
||||
for (var rule in rules) {
|
||||
manager?.list.add(rule);
|
||||
}
|
||||
await _save();
|
||||
setState(() {
|
||||
this.rules = manager!.list;
|
||||
});
|
||||
|
||||
if (mounted) CustomToast.success(localizations.importSuccess).show(context);
|
||||
} catch (e) {
|
||||
if (mounted) CustomToast.error(localizations.importFailed).show(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _export(List<RequestBreakpointRule> exportRules) async {
|
||||
if (exportRules.isEmpty) return;
|
||||
|
||||
String? outputFile;
|
||||
if (Platform.isMacOS) {
|
||||
outputFile = await DesktopMultiWindow.invokeMethod(0, "saveFile", {"fileName": 'request_breakpoint_rules.json'});
|
||||
if (widget.windowId != null) WindowController.fromWindowId(widget.windowId!).show();
|
||||
} else {
|
||||
outputFile = await FilePicker.platform.saveFile(fileName: 'request_breakpoint_rules.json');
|
||||
}
|
||||
if (outputFile == null) return;
|
||||
File file = File(outputFile);
|
||||
try {
|
||||
var json = exportRules.map((e) => e.toJson()).toList();
|
||||
await file.writeAsString(jsonEncode(json));
|
||||
if (mounted) CustomToast.success(localizations.exportSuccess).show(context);
|
||||
} catch (e) {
|
||||
if (mounted) CustomToast.error(localizations.exportFailed).show(context);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
@@ -114,7 +172,12 @@ class _RequestBreakpointPageState extends State<RequestBreakpointPage> {
|
||||
Expanded(
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.end, children: [
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.add, size: 18), label: Text(localizations.add), onPressed: _editRule)
|
||||
icon: const Icon(Icons.add, size: 18), label: Text(localizations.add), onPressed: _editRule),
|
||||
const SizedBox(width: 5),
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.input_rounded, size: 18),
|
||||
onPressed: _import,
|
||||
label: Text(localizations.import)),
|
||||
])),
|
||||
const SizedBox(width: 15)
|
||||
]),
|
||||
@@ -266,6 +329,22 @@ class _RequestBreakpointPageState extends State<RequestBreakpointPage> {
|
||||
}
|
||||
},
|
||||
),
|
||||
PopupMenuItem(
|
||||
height: 32,
|
||||
child: Text(localizations.export),
|
||||
onTap: () async {
|
||||
if (selected.isEmpty) return;
|
||||
var list = selected.toList();
|
||||
List<RequestBreakpointRule> exportRules = [];
|
||||
for (var i in list) {
|
||||
exportRules.add(rules[i]);
|
||||
}
|
||||
await _export(exportRules);
|
||||
setState(() {
|
||||
selected.clear();
|
||||
});
|
||||
},
|
||||
),
|
||||
PopupMenuItem(
|
||||
height: 32,
|
||||
child: Text(localizations.delete),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:collection';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -65,7 +66,7 @@ class _RequestBreakpointPageState extends State<MobileRequestBreakpointPage> {
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Row(children: [
|
||||
SizedBox(
|
||||
width: isEN ? 280 : 250,
|
||||
width: isEN ? 230 : 160,
|
||||
child: ListTile(
|
||||
title: Text("${localizations.enable} ${localizations.breakpoint}"),
|
||||
contentPadding: const EdgeInsets.only(left: 2),
|
||||
@@ -82,8 +83,15 @@ class _RequestBreakpointPageState extends State<MobileRequestBreakpointPage> {
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Row(mainAxisAlignment: MainAxisAlignment.end, children: [
|
||||
TextButton.icon(
|
||||
icon: const Icon(Icons.add, size: 18), label: Text(localizations.add), onPressed: _editRule),
|
||||
IconButton(
|
||||
icon: Icon(Icons.add, size: 22, color: Theme.of(context).colorScheme.primary),
|
||||
onPressed: _editRule,
|
||||
tooltip: localizations.add),
|
||||
const SizedBox(width: 5),
|
||||
IconButton(
|
||||
icon: Icon(Icons.input_rounded, size: 22, color: Theme.of(context).colorScheme.primary),
|
||||
onPressed: _import,
|
||||
tooltip: localizations.import),
|
||||
])),
|
||||
const SizedBox(width: 15)
|
||||
]),
|
||||
@@ -195,6 +203,32 @@ class _RequestBreakpointPageState extends State<MobileRequestBreakpointPage> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _import() async {
|
||||
try {
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.custom,
|
||||
allowedExtensions: ['json'],
|
||||
);
|
||||
if (result == null || result.files.isEmpty) return;
|
||||
File file = File(result.files.single.path!);
|
||||
String content = await file.readAsString();
|
||||
List<dynamic> list = jsonDecode(content);
|
||||
var newRules = list.map((e) => RequestBreakpointRule.fromJson(e)).toList();
|
||||
for (var rule in newRules) {
|
||||
manager?.list.add(rule);
|
||||
}
|
||||
await _save();
|
||||
setState(() {
|
||||
rules = manager!.list;
|
||||
});
|
||||
|
||||
if (mounted) FlutterToastr.show(localizations.importSuccess, context);
|
||||
} catch (e) {
|
||||
logger.e('Import failed', error: e);
|
||||
if (mounted) FlutterToastr.show(localizations.importFailed, context);
|
||||
}
|
||||
}
|
||||
|
||||
Stack _buildSelectionFooter() {
|
||||
final l10n = localizations;
|
||||
return Stack(children: [
|
||||
|
||||
Reference in New Issue
Block a user