Compare commits
1 Commits
v0.8.85-pr
...
v0.8.85-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a98f4c345b |
@@ -385,7 +385,6 @@
|
||||
"logsTest": "Logs test",
|
||||
"emptyTip": "{label} cannot be empty",
|
||||
"urlTip": "{label} must be a url",
|
||||
"proxyPortTip": "proxy port must be between 1024 and 49151",
|
||||
"numberTip": "{label} must be a number",
|
||||
"interval": "Interval",
|
||||
"existsTip": "Current {label} already exists",
|
||||
@@ -397,5 +396,11 @@
|
||||
"rename": "Rename",
|
||||
"unnamed": "Unnamed",
|
||||
"pleaseEnterScriptName": "Please enter a script name",
|
||||
"overrideInvalidTip": "Does not take effect in script mode"
|
||||
"overrideInvalidTip": "Does not take effect in script mode",
|
||||
"mixedPort": "Mixed Port",
|
||||
"socksPort": "Socks Port",
|
||||
"redirPort": "Redir Port",
|
||||
"tproxyPort": "Tproxy Port",
|
||||
"portTip": "{label} must be between 1024 and 49151",
|
||||
"portConflictTip": "Please enter a different port"
|
||||
}
|
||||
@@ -386,7 +386,6 @@
|
||||
"logsTest": "ログテスト",
|
||||
"emptyTip": "{label}は空欄にできません",
|
||||
"urlTip": "{label}はURLである必要があります",
|
||||
"proxyPortTip": "プロキシポートは1024から49151の間でなければなりません",
|
||||
"numberTip": "{label}は数字でなければなりません",
|
||||
"interval": "インターバル",
|
||||
"existsTip": "現在の{label}は既に存在しています",
|
||||
@@ -398,5 +397,11 @@
|
||||
"rename": "リネーム",
|
||||
"unnamed": "無題",
|
||||
"pleaseEnterScriptName": "スクリプト名を入力してください",
|
||||
"overrideInvalidTip": "スクリプトモードでは有効になりません"
|
||||
"overrideInvalidTip": "スクリプトモードでは有効になりません",
|
||||
"mixedPort": "混合ポート",
|
||||
"socksPort": "Socksポート",
|
||||
"redirPort": "Redirポート",
|
||||
"tproxyPort": "Tproxyポート",
|
||||
"portTip": "{label} は 1024 から 49151 の間でなければなりません",
|
||||
"portConflictTip": "別のポートを入力してください"
|
||||
}
|
||||
@@ -386,7 +386,6 @@
|
||||
"logsTest": "Тест журналов",
|
||||
"emptyTip": "{label} не может быть пустым",
|
||||
"urlTip": "{label} должен быть URL",
|
||||
"proxyPortTip": "Порт прокси должен быть в диапазоне от 1024 до 49151",
|
||||
"numberTip": "{label} должно быть числом",
|
||||
"interval": "Интервал",
|
||||
"existsTip": "Текущий {label} уже существует",
|
||||
@@ -398,5 +397,11 @@
|
||||
"rename": "Переименовать",
|
||||
"unnamed": "Без имени",
|
||||
"pleaseEnterScriptName": "Пожалуйста, введите название скрипта",
|
||||
"overrideInvalidTip": "В скриптовом режиме не действует"
|
||||
"overrideInvalidTip": "В скриптовом режиме не действует",
|
||||
"mixedPort": "Смешанный порт",
|
||||
"socksPort": "Socks-порт",
|
||||
"redirPort": "Redir-порт",
|
||||
"tproxyPort": "Tproxy-порт",
|
||||
"portTip": "{label} должен быть числом от 1024 до 49151",
|
||||
"portConflictTip": "Введите другой порт"
|
||||
}
|
||||
@@ -386,7 +386,6 @@
|
||||
"logsTest": "日志测试",
|
||||
"emptyTip": "{label}不能为空",
|
||||
"urlTip": "{label}必须为URL",
|
||||
"proxyPortTip": "代理端口必须在1024到49151之间",
|
||||
"numberTip": "{label}必须为数字",
|
||||
"interval": "间隔",
|
||||
"existsTip": "{label}当前已存在",
|
||||
@@ -398,5 +397,11 @@
|
||||
"rename": "重命名",
|
||||
"unnamed": "未命名",
|
||||
"pleaseEnterScriptName": "请输入脚本名称",
|
||||
"overrideInvalidTip": "在脚本模式下不生效"
|
||||
"overrideInvalidTip": "在脚本模式下不生效",
|
||||
"mixedPort": "混合端口",
|
||||
"socksPort": "Socks端口",
|
||||
"redirPort": "Redir端口",
|
||||
"tproxyPort": "Tproxy端口",
|
||||
"portTip": "{label} 必须在 1024 到 49151 之间",
|
||||
"portConflictTip": "请输入不同的端口"
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ final defaultTextScaleFactor =
|
||||
const httpTimeoutDuration = Duration(milliseconds: 5000);
|
||||
const moreDuration = Duration(milliseconds: 100);
|
||||
const animateDuration = Duration(milliseconds: 100);
|
||||
const midDuration = Duration(milliseconds: 200);
|
||||
const commonDuration = Duration(milliseconds: 300);
|
||||
const defaultUpdateDuration = Duration(days: 1);
|
||||
const mmdbFileName = "geoip.metadb";
|
||||
|
||||
@@ -43,6 +43,16 @@ class Request {
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<Response> getTextResponseForUrl(String url) async {
|
||||
final response = await _clashDio.get(
|
||||
url,
|
||||
options: Options(
|
||||
responseType: ResponseType.plain,
|
||||
),
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
Future<MemoryImage?> getImage(String url) async {
|
||||
if (url.isEmpty) return null;
|
||||
final response = await _dio.get<Uint8List>(
|
||||
|
||||
@@ -34,9 +34,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
|
||||
static String m5(label) => "${label} must be a number";
|
||||
|
||||
static String m6(count) => "${count} items have been selected";
|
||||
static String m6(label) => "${label} must be between 1024 and 49151";
|
||||
|
||||
static String m7(label) => "${label} must be a url";
|
||||
static String m7(count) => "${count} items have been selected";
|
||||
|
||||
static String m8(label) => "${label} must be a url";
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||
@@ -382,6 +384,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Modify the default system exit event",
|
||||
),
|
||||
"minutes": MessageLookupByLibrary.simpleMessage("Minutes"),
|
||||
"mixedPort": MessageLookupByLibrary.simpleMessage("Mixed Port"),
|
||||
"mode": MessageLookupByLibrary.simpleMessage("Mode"),
|
||||
"monochromeScheme": MessageLookupByLibrary.simpleMessage("Monochrome"),
|
||||
"months": MessageLookupByLibrary.simpleMessage("Months"),
|
||||
@@ -478,6 +481,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Please upload a valid QR code",
|
||||
),
|
||||
"port": MessageLookupByLibrary.simpleMessage("Port"),
|
||||
"portConflictTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Please enter a different port",
|
||||
),
|
||||
"portTip": m6,
|
||||
"preferH3Desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Prioritize the use of DOH\'s http/3",
|
||||
),
|
||||
@@ -524,9 +531,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"proxyPortDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Set the Clash listening port",
|
||||
),
|
||||
"proxyPortTip": MessageLookupByLibrary.simpleMessage(
|
||||
"proxy port must be between 1024 and 49151",
|
||||
),
|
||||
"proxyProviders": MessageLookupByLibrary.simpleMessage("Proxy providers"),
|
||||
"pureBlackMode": MessageLookupByLibrary.simpleMessage("Pure black mode"),
|
||||
"qrcode": MessageLookupByLibrary.simpleMessage("QR code"),
|
||||
@@ -549,6 +553,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Override",
|
||||
),
|
||||
"recoverySuccess": MessageLookupByLibrary.simpleMessage("Recovery success"),
|
||||
"redirPort": MessageLookupByLibrary.simpleMessage("Redir Port"),
|
||||
"redo": MessageLookupByLibrary.simpleMessage("redo"),
|
||||
"regExp": MessageLookupByLibrary.simpleMessage("RegExp"),
|
||||
"remote": MessageLookupByLibrary.simpleMessage("Remote"),
|
||||
@@ -600,7 +605,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"seconds": MessageLookupByLibrary.simpleMessage("Seconds"),
|
||||
"selectAll": MessageLookupByLibrary.simpleMessage("Select all"),
|
||||
"selected": MessageLookupByLibrary.simpleMessage("Selected"),
|
||||
"selectedCountTitle": m6,
|
||||
"selectedCountTitle": m7,
|
||||
"settings": MessageLookupByLibrary.simpleMessage("Settings"),
|
||||
"show": MessageLookupByLibrary.simpleMessage("Show"),
|
||||
"shrink": MessageLookupByLibrary.simpleMessage("Shrink"),
|
||||
@@ -609,6 +614,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Start in the background",
|
||||
),
|
||||
"size": MessageLookupByLibrary.simpleMessage("Size"),
|
||||
"socksPort": MessageLookupByLibrary.simpleMessage("Socks Port"),
|
||||
"sort": MessageLookupByLibrary.simpleMessage("Sort"),
|
||||
"source": MessageLookupByLibrary.simpleMessage("Source"),
|
||||
"sourceIp": MessageLookupByLibrary.simpleMessage("Source IP"),
|
||||
@@ -657,6 +663,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"toggle": MessageLookupByLibrary.simpleMessage("Toggle"),
|
||||
"tonalSpotScheme": MessageLookupByLibrary.simpleMessage("TonalSpot"),
|
||||
"tools": MessageLookupByLibrary.simpleMessage("Tools"),
|
||||
"tproxyPort": MessageLookupByLibrary.simpleMessage("Tproxy Port"),
|
||||
"trafficUsage": MessageLookupByLibrary.simpleMessage("Traffic usage"),
|
||||
"tun": MessageLookupByLibrary.simpleMessage("TUN"),
|
||||
"tunDesc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -679,7 +686,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"urlDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Obtain profile through URL",
|
||||
),
|
||||
"urlTip": m7,
|
||||
"urlTip": m8,
|
||||
"useHosts": MessageLookupByLibrary.simpleMessage("Use hosts"),
|
||||
"useSystemHosts": MessageLookupByLibrary.simpleMessage("Use system hosts"),
|
||||
"value": MessageLookupByLibrary.simpleMessage("Value"),
|
||||
|
||||
@@ -32,9 +32,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
|
||||
static String m5(label) => "${label}は数字でなければなりません";
|
||||
|
||||
static String m6(count) => "${count} 項目が選択されています";
|
||||
static String m6(label) => "${label} は 1024 から 49151 の間でなければなりません";
|
||||
|
||||
static String m7(label) => "${label}はURLである必要があります";
|
||||
static String m7(count) => "${count} 項目が選択されています";
|
||||
|
||||
static String m8(label) => "${label}はURLである必要があります";
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||
@@ -286,6 +288,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"システムの終了イベントを変更",
|
||||
),
|
||||
"minutes": MessageLookupByLibrary.simpleMessage("分"),
|
||||
"mixedPort": MessageLookupByLibrary.simpleMessage("混合ポート"),
|
||||
"mode": MessageLookupByLibrary.simpleMessage("モード"),
|
||||
"monochromeScheme": MessageLookupByLibrary.simpleMessage("モノクローム"),
|
||||
"months": MessageLookupByLibrary.simpleMessage("月"),
|
||||
@@ -364,6 +367,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"有効なQRコードをアップロードしてください",
|
||||
),
|
||||
"port": MessageLookupByLibrary.simpleMessage("ポート"),
|
||||
"portConflictTip": MessageLookupByLibrary.simpleMessage("別のポートを入力してください"),
|
||||
"portTip": m6,
|
||||
"preferH3Desc": MessageLookupByLibrary.simpleMessage("DOHのHTTP/3を優先使用"),
|
||||
"pressKeyboard": MessageLookupByLibrary.simpleMessage("キーボードを押してください"),
|
||||
"preview": MessageLookupByLibrary.simpleMessage("プレビュー"),
|
||||
@@ -400,9 +405,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
),
|
||||
"proxyPort": MessageLookupByLibrary.simpleMessage("プロキシポート"),
|
||||
"proxyPortDesc": MessageLookupByLibrary.simpleMessage("Clashのリスニングポートを設定"),
|
||||
"proxyPortTip": MessageLookupByLibrary.simpleMessage(
|
||||
"プロキシポートは1024から49151の間でなければなりません",
|
||||
),
|
||||
"proxyProviders": MessageLookupByLibrary.simpleMessage("プロキシプロバイダー"),
|
||||
"pureBlackMode": MessageLookupByLibrary.simpleMessage("純黒モード"),
|
||||
"qrcode": MessageLookupByLibrary.simpleMessage("QRコード"),
|
||||
@@ -417,6 +419,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"オーバーライド",
|
||||
),
|
||||
"recoverySuccess": MessageLookupByLibrary.simpleMessage("復元成功"),
|
||||
"redirPort": MessageLookupByLibrary.simpleMessage("Redirポート"),
|
||||
"redo": MessageLookupByLibrary.simpleMessage("やり直す"),
|
||||
"regExp": MessageLookupByLibrary.simpleMessage("正規表現"),
|
||||
"remote": MessageLookupByLibrary.simpleMessage("リモート"),
|
||||
@@ -458,13 +461,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"seconds": MessageLookupByLibrary.simpleMessage("秒"),
|
||||
"selectAll": MessageLookupByLibrary.simpleMessage("すべて選択"),
|
||||
"selected": MessageLookupByLibrary.simpleMessage("選択済み"),
|
||||
"selectedCountTitle": m6,
|
||||
"selectedCountTitle": m7,
|
||||
"settings": MessageLookupByLibrary.simpleMessage("設定"),
|
||||
"show": MessageLookupByLibrary.simpleMessage("表示"),
|
||||
"shrink": MessageLookupByLibrary.simpleMessage("縮小"),
|
||||
"silentLaunch": MessageLookupByLibrary.simpleMessage("バックグラウンド起動"),
|
||||
"silentLaunchDesc": MessageLookupByLibrary.simpleMessage("バックグラウンドで起動"),
|
||||
"size": MessageLookupByLibrary.simpleMessage("サイズ"),
|
||||
"socksPort": MessageLookupByLibrary.simpleMessage("Socksポート"),
|
||||
"sort": MessageLookupByLibrary.simpleMessage("並び替え"),
|
||||
"source": MessageLookupByLibrary.simpleMessage("ソース"),
|
||||
"sourceIp": MessageLookupByLibrary.simpleMessage("送信元IP"),
|
||||
@@ -505,6 +509,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"toggle": MessageLookupByLibrary.simpleMessage("トグル"),
|
||||
"tonalSpotScheme": MessageLookupByLibrary.simpleMessage("トーンスポット"),
|
||||
"tools": MessageLookupByLibrary.simpleMessage("ツール"),
|
||||
"tproxyPort": MessageLookupByLibrary.simpleMessage("Tproxyポート"),
|
||||
"trafficUsage": MessageLookupByLibrary.simpleMessage("トラフィック使用量"),
|
||||
"tun": MessageLookupByLibrary.simpleMessage("TUN"),
|
||||
"tunDesc": MessageLookupByLibrary.simpleMessage("管理者モードでのみ有効"),
|
||||
@@ -523,7 +528,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"upload": MessageLookupByLibrary.simpleMessage("アップロード"),
|
||||
"url": MessageLookupByLibrary.simpleMessage("URL"),
|
||||
"urlDesc": MessageLookupByLibrary.simpleMessage("URL経由でプロファイルを取得"),
|
||||
"urlTip": m7,
|
||||
"urlTip": m8,
|
||||
"useHosts": MessageLookupByLibrary.simpleMessage("ホストを使用"),
|
||||
"useSystemHosts": MessageLookupByLibrary.simpleMessage("システムホストを使用"),
|
||||
"value": MessageLookupByLibrary.simpleMessage("値"),
|
||||
|
||||
@@ -33,9 +33,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
|
||||
static String m5(label) => "${label} должно быть числом";
|
||||
|
||||
static String m6(count) => "Выбрано ${count} элементов";
|
||||
static String m6(label) => "${label} должен быть числом от 1024 до 49151";
|
||||
|
||||
static String m7(label) => "${label} должен быть URL";
|
||||
static String m7(count) => "Выбрано ${count} элементов";
|
||||
|
||||
static String m8(label) => "${label} должен быть URL";
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||
@@ -407,6 +409,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Изменить стандартное событие выхода из системы",
|
||||
),
|
||||
"minutes": MessageLookupByLibrary.simpleMessage("Минут"),
|
||||
"mixedPort": MessageLookupByLibrary.simpleMessage("Смешанный порт"),
|
||||
"mode": MessageLookupByLibrary.simpleMessage("Режим"),
|
||||
"monochromeScheme": MessageLookupByLibrary.simpleMessage("Монохром"),
|
||||
"months": MessageLookupByLibrary.simpleMessage("Месяцев"),
|
||||
@@ -507,6 +510,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Пожалуйста, загрузите действительный QR-код",
|
||||
),
|
||||
"port": MessageLookupByLibrary.simpleMessage("Порт"),
|
||||
"portConflictTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Введите другой порт",
|
||||
),
|
||||
"portTip": m6,
|
||||
"preferH3Desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Приоритетное использование HTTP/3 для DOH",
|
||||
),
|
||||
@@ -555,9 +562,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"proxyPortDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Установить порт прослушивания Clash",
|
||||
),
|
||||
"proxyPortTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Порт прокси должен быть в диапазоне от 1024 до 49151",
|
||||
),
|
||||
"proxyProviders": MessageLookupByLibrary.simpleMessage("Провайдеры прокси"),
|
||||
"pureBlackMode": MessageLookupByLibrary.simpleMessage("Чисто черный режим"),
|
||||
"qrcode": MessageLookupByLibrary.simpleMessage("QR-код"),
|
||||
@@ -584,6 +588,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"recoverySuccess": MessageLookupByLibrary.simpleMessage(
|
||||
"Восстановление успешно",
|
||||
),
|
||||
"redirPort": MessageLookupByLibrary.simpleMessage("Redir-порт"),
|
||||
"redo": MessageLookupByLibrary.simpleMessage("Повторить"),
|
||||
"regExp": MessageLookupByLibrary.simpleMessage("Регулярное выражение"),
|
||||
"remote": MessageLookupByLibrary.simpleMessage("Удаленный"),
|
||||
@@ -637,7 +642,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"seconds": MessageLookupByLibrary.simpleMessage("Секунд"),
|
||||
"selectAll": MessageLookupByLibrary.simpleMessage("Выбрать все"),
|
||||
"selected": MessageLookupByLibrary.simpleMessage("Выбрано"),
|
||||
"selectedCountTitle": m6,
|
||||
"selectedCountTitle": m7,
|
||||
"settings": MessageLookupByLibrary.simpleMessage("Настройки"),
|
||||
"show": MessageLookupByLibrary.simpleMessage("Показать"),
|
||||
"shrink": MessageLookupByLibrary.simpleMessage("Сжать"),
|
||||
@@ -646,6 +651,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Запуск в фоновом режиме",
|
||||
),
|
||||
"size": MessageLookupByLibrary.simpleMessage("Размер"),
|
||||
"socksPort": MessageLookupByLibrary.simpleMessage("Socks-порт"),
|
||||
"sort": MessageLookupByLibrary.simpleMessage("Сортировка"),
|
||||
"source": MessageLookupByLibrary.simpleMessage("Источник"),
|
||||
"sourceIp": MessageLookupByLibrary.simpleMessage("Исходный IP"),
|
||||
@@ -694,6 +700,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"toggle": MessageLookupByLibrary.simpleMessage("Переключить"),
|
||||
"tonalSpotScheme": MessageLookupByLibrary.simpleMessage("Тональный акцент"),
|
||||
"tools": MessageLookupByLibrary.simpleMessage("Инструменты"),
|
||||
"tproxyPort": MessageLookupByLibrary.simpleMessage("Tproxy-порт"),
|
||||
"trafficUsage": MessageLookupByLibrary.simpleMessage(
|
||||
"Использование трафика",
|
||||
),
|
||||
@@ -720,7 +727,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"urlDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Получить профиль через URL",
|
||||
),
|
||||
"urlTip": m7,
|
||||
"urlTip": m8,
|
||||
"useHosts": MessageLookupByLibrary.simpleMessage("Использовать hosts"),
|
||||
"useSystemHosts": MessageLookupByLibrary.simpleMessage(
|
||||
"Использовать системные hosts",
|
||||
|
||||
@@ -32,9 +32,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
|
||||
static String m5(label) => "${label}必须为数字";
|
||||
|
||||
static String m6(count) => "已选择 ${count} 项";
|
||||
static String m6(label) => "${label} 必须在 1024 到 49151 之间";
|
||||
|
||||
static String m7(label) => "${label}必须为URL";
|
||||
static String m7(count) => "已选择 ${count} 项";
|
||||
|
||||
static String m8(label) => "${label}必须为URL";
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
|
||||
@@ -258,6 +260,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("退出时最小化"),
|
||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage("修改系统默认退出事件"),
|
||||
"minutes": MessageLookupByLibrary.simpleMessage("分钟"),
|
||||
"mixedPort": MessageLookupByLibrary.simpleMessage("混合端口"),
|
||||
"mode": MessageLookupByLibrary.simpleMessage("模式"),
|
||||
"monochromeScheme": MessageLookupByLibrary.simpleMessage("单色"),
|
||||
"months": MessageLookupByLibrary.simpleMessage("月"),
|
||||
@@ -318,6 +321,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"请上传有效的二维码",
|
||||
),
|
||||
"port": MessageLookupByLibrary.simpleMessage("端口"),
|
||||
"portConflictTip": MessageLookupByLibrary.simpleMessage("请输入不同的端口"),
|
||||
"portTip": m6,
|
||||
"preferH3Desc": MessageLookupByLibrary.simpleMessage("优先使用DOH的http/3"),
|
||||
"pressKeyboard": MessageLookupByLibrary.simpleMessage("请按下按键"),
|
||||
"preview": MessageLookupByLibrary.simpleMessage("预览"),
|
||||
@@ -350,7 +355,6 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"proxyNameserverDesc": MessageLookupByLibrary.simpleMessage("用于解析代理节点的域名"),
|
||||
"proxyPort": MessageLookupByLibrary.simpleMessage("代理端口"),
|
||||
"proxyPortDesc": MessageLookupByLibrary.simpleMessage("设置Clash监听端口"),
|
||||
"proxyPortTip": MessageLookupByLibrary.simpleMessage("代理端口必须在1024到49151之间"),
|
||||
"proxyProviders": MessageLookupByLibrary.simpleMessage("代理提供者"),
|
||||
"pureBlackMode": MessageLookupByLibrary.simpleMessage("纯黑模式"),
|
||||
"qrcode": MessageLookupByLibrary.simpleMessage("二维码"),
|
||||
@@ -363,6 +367,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"recoveryStrategy_compatible": MessageLookupByLibrary.simpleMessage("兼容"),
|
||||
"recoveryStrategy_override": MessageLookupByLibrary.simpleMessage("覆盖"),
|
||||
"recoverySuccess": MessageLookupByLibrary.simpleMessage("恢复成功"),
|
||||
"redirPort": MessageLookupByLibrary.simpleMessage("Redir端口"),
|
||||
"redo": MessageLookupByLibrary.simpleMessage("重做"),
|
||||
"regExp": MessageLookupByLibrary.simpleMessage("正则"),
|
||||
"remote": MessageLookupByLibrary.simpleMessage("远程"),
|
||||
@@ -398,13 +403,14 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"seconds": MessageLookupByLibrary.simpleMessage("秒"),
|
||||
"selectAll": MessageLookupByLibrary.simpleMessage("全选"),
|
||||
"selected": MessageLookupByLibrary.simpleMessage("已选择"),
|
||||
"selectedCountTitle": m6,
|
||||
"selectedCountTitle": m7,
|
||||
"settings": MessageLookupByLibrary.simpleMessage("设置"),
|
||||
"show": MessageLookupByLibrary.simpleMessage("显示"),
|
||||
"shrink": MessageLookupByLibrary.simpleMessage("紧凑"),
|
||||
"silentLaunch": MessageLookupByLibrary.simpleMessage("静默启动"),
|
||||
"silentLaunchDesc": MessageLookupByLibrary.simpleMessage("后台启动"),
|
||||
"size": MessageLookupByLibrary.simpleMessage("尺寸"),
|
||||
"socksPort": MessageLookupByLibrary.simpleMessage("Socks端口"),
|
||||
"sort": MessageLookupByLibrary.simpleMessage("排序"),
|
||||
"source": MessageLookupByLibrary.simpleMessage("来源"),
|
||||
"sourceIp": MessageLookupByLibrary.simpleMessage("源IP"),
|
||||
@@ -443,6 +449,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"toggle": MessageLookupByLibrary.simpleMessage("切换"),
|
||||
"tonalSpotScheme": MessageLookupByLibrary.simpleMessage("调性点缀"),
|
||||
"tools": MessageLookupByLibrary.simpleMessage("工具"),
|
||||
"tproxyPort": MessageLookupByLibrary.simpleMessage("Tproxy端口"),
|
||||
"trafficUsage": MessageLookupByLibrary.simpleMessage("流量统计"),
|
||||
"tun": MessageLookupByLibrary.simpleMessage("虚拟网卡"),
|
||||
"tunDesc": MessageLookupByLibrary.simpleMessage("仅在管理员模式生效"),
|
||||
@@ -459,7 +466,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"upload": MessageLookupByLibrary.simpleMessage("上传"),
|
||||
"url": MessageLookupByLibrary.simpleMessage("URL"),
|
||||
"urlDesc": MessageLookupByLibrary.simpleMessage("通过URL获取配置文件"),
|
||||
"urlTip": m7,
|
||||
"urlTip": m8,
|
||||
"useHosts": MessageLookupByLibrary.simpleMessage("使用Hosts"),
|
||||
"useSystemHosts": MessageLookupByLibrary.simpleMessage("使用系统Hosts"),
|
||||
"value": MessageLookupByLibrary.simpleMessage("值"),
|
||||
|
||||
@@ -2970,16 +2970,6 @@ class AppLocalizations {
|
||||
);
|
||||
}
|
||||
|
||||
/// `proxy port must be between 1024 and 49151`
|
||||
String get proxyPortTip {
|
||||
return Intl.message(
|
||||
'proxy port must be between 1024 and 49151',
|
||||
name: 'proxyPortTip',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `{label} must be a number`
|
||||
String numberTip(Object label) {
|
||||
return Intl.message(
|
||||
@@ -3074,6 +3064,46 @@ class AppLocalizations {
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Mixed Port`
|
||||
String get mixedPort {
|
||||
return Intl.message('Mixed Port', name: 'mixedPort', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `Socks Port`
|
||||
String get socksPort {
|
||||
return Intl.message('Socks Port', name: 'socksPort', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `Redir Port`
|
||||
String get redirPort {
|
||||
return Intl.message('Redir Port', name: 'redirPort', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `Tproxy Port`
|
||||
String get tproxyPort {
|
||||
return Intl.message('Tproxy Port', name: 'tproxyPort', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `{label} must be between 1024 and 49151`
|
||||
String portTip(Object label) {
|
||||
return Intl.message(
|
||||
'$label must be between 1024 and 49151',
|
||||
name: 'portTip',
|
||||
desc: '',
|
||||
args: [label],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Please enter a different port`
|
||||
String get portConflictTip {
|
||||
return Intl.message(
|
||||
'Please enter a different port',
|
||||
name: 'portConflictTip',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||
|
||||
@@ -458,6 +458,10 @@ class ClashConfigSnippet with _$ClashConfigSnippet {
|
||||
class ClashConfig with _$ClashConfig {
|
||||
const factory ClashConfig({
|
||||
@Default(defaultMixedPort) @JsonKey(name: "mixed-port") int mixedPort,
|
||||
@Default(0) @JsonKey(name: "socks-port") int socksPort,
|
||||
@Default(0) @JsonKey(name: "port") int port,
|
||||
@Default(0) @JsonKey(name: "redir-port") int redirPort,
|
||||
@Default(0) @JsonKey(name: "tproxy-port") int tproxyPort,
|
||||
@Default(Mode.rule) Mode mode,
|
||||
@Default(false) @JsonKey(name: "allow-lan") bool allowLan,
|
||||
@Default(LogLevel.error) @JsonKey(name: "log-level") LogLevel logLevel,
|
||||
|
||||
@@ -3486,6 +3486,14 @@ ClashConfig _$ClashConfigFromJson(Map<String, dynamic> json) {
|
||||
mixin _$ClashConfig {
|
||||
@JsonKey(name: "mixed-port")
|
||||
int get mixedPort => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "socks-port")
|
||||
int get socksPort => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "port")
|
||||
int get port => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "redir-port")
|
||||
int get redirPort => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "tproxy-port")
|
||||
int get tproxyPort => throw _privateConstructorUsedError;
|
||||
Mode get mode => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "allow-lan")
|
||||
bool get allowLan => throw _privateConstructorUsedError;
|
||||
@@ -3536,6 +3544,10 @@ abstract class $ClashConfigCopyWith<$Res> {
|
||||
@useResult
|
||||
$Res call(
|
||||
{@JsonKey(name: "mixed-port") int mixedPort,
|
||||
@JsonKey(name: "socks-port") int socksPort,
|
||||
@JsonKey(name: "port") int port,
|
||||
@JsonKey(name: "redir-port") int redirPort,
|
||||
@JsonKey(name: "tproxy-port") int tproxyPort,
|
||||
Mode mode,
|
||||
@JsonKey(name: "allow-lan") bool allowLan,
|
||||
@JsonKey(name: "log-level") LogLevel logLevel,
|
||||
@@ -3579,6 +3591,10 @@ class _$ClashConfigCopyWithImpl<$Res, $Val extends ClashConfig>
|
||||
@override
|
||||
$Res call({
|
||||
Object? mixedPort = null,
|
||||
Object? socksPort = null,
|
||||
Object? port = null,
|
||||
Object? redirPort = null,
|
||||
Object? tproxyPort = null,
|
||||
Object? mode = null,
|
||||
Object? allowLan = null,
|
||||
Object? logLevel = null,
|
||||
@@ -3602,6 +3618,22 @@ class _$ClashConfigCopyWithImpl<$Res, $Val extends ClashConfig>
|
||||
? _value.mixedPort
|
||||
: mixedPort // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
socksPort: null == socksPort
|
||||
? _value.socksPort
|
||||
: socksPort // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
port: null == port
|
||||
? _value.port
|
||||
: port // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
redirPort: null == redirPort
|
||||
? _value.redirPort
|
||||
: redirPort // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
tproxyPort: null == tproxyPort
|
||||
? _value.tproxyPort
|
||||
: tproxyPort // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
mode: null == mode
|
||||
? _value.mode
|
||||
: mode // ignore: cast_nullable_to_non_nullable
|
||||
@@ -3714,6 +3746,10 @@ abstract class _$$ClashConfigImplCopyWith<$Res>
|
||||
@useResult
|
||||
$Res call(
|
||||
{@JsonKey(name: "mixed-port") int mixedPort,
|
||||
@JsonKey(name: "socks-port") int socksPort,
|
||||
@JsonKey(name: "port") int port,
|
||||
@JsonKey(name: "redir-port") int redirPort,
|
||||
@JsonKey(name: "tproxy-port") int tproxyPort,
|
||||
Mode mode,
|
||||
@JsonKey(name: "allow-lan") bool allowLan,
|
||||
@JsonKey(name: "log-level") LogLevel logLevel,
|
||||
@@ -3758,6 +3794,10 @@ class __$$ClashConfigImplCopyWithImpl<$Res>
|
||||
@override
|
||||
$Res call({
|
||||
Object? mixedPort = null,
|
||||
Object? socksPort = null,
|
||||
Object? port = null,
|
||||
Object? redirPort = null,
|
||||
Object? tproxyPort = null,
|
||||
Object? mode = null,
|
||||
Object? allowLan = null,
|
||||
Object? logLevel = null,
|
||||
@@ -3781,6 +3821,22 @@ class __$$ClashConfigImplCopyWithImpl<$Res>
|
||||
? _value.mixedPort
|
||||
: mixedPort // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
socksPort: null == socksPort
|
||||
? _value.socksPort
|
||||
: socksPort // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
port: null == port
|
||||
? _value.port
|
||||
: port // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
redirPort: null == redirPort
|
||||
? _value.redirPort
|
||||
: redirPort // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
tproxyPort: null == tproxyPort
|
||||
? _value.tproxyPort
|
||||
: tproxyPort // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
mode: null == mode
|
||||
? _value.mode
|
||||
: mode // ignore: cast_nullable_to_non_nullable
|
||||
@@ -3858,6 +3914,10 @@ class __$$ClashConfigImplCopyWithImpl<$Res>
|
||||
class _$ClashConfigImpl implements _ClashConfig {
|
||||
const _$ClashConfigImpl(
|
||||
{@JsonKey(name: "mixed-port") this.mixedPort = defaultMixedPort,
|
||||
@JsonKey(name: "socks-port") this.socksPort = 0,
|
||||
@JsonKey(name: "port") this.port = 0,
|
||||
@JsonKey(name: "redir-port") this.redirPort = 0,
|
||||
@JsonKey(name: "tproxy-port") this.tproxyPort = 0,
|
||||
this.mode = Mode.rule,
|
||||
@JsonKey(name: "allow-lan") this.allowLan = false,
|
||||
@JsonKey(name: "log-level") this.logLevel = LogLevel.error,
|
||||
@@ -3893,6 +3953,18 @@ class _$ClashConfigImpl implements _ClashConfig {
|
||||
@JsonKey(name: "mixed-port")
|
||||
final int mixedPort;
|
||||
@override
|
||||
@JsonKey(name: "socks-port")
|
||||
final int socksPort;
|
||||
@override
|
||||
@JsonKey(name: "port")
|
||||
final int port;
|
||||
@override
|
||||
@JsonKey(name: "redir-port")
|
||||
final int redirPort;
|
||||
@override
|
||||
@JsonKey(name: "tproxy-port")
|
||||
final int tproxyPort;
|
||||
@override
|
||||
@JsonKey()
|
||||
final Mode mode;
|
||||
@override
|
||||
@@ -3963,7 +4035,7 @@ class _$ClashConfigImpl implements _ClashConfig {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ClashConfig(mixedPort: $mixedPort, mode: $mode, allowLan: $allowLan, logLevel: $logLevel, ipv6: $ipv6, findProcessMode: $findProcessMode, keepAliveInterval: $keepAliveInterval, unifiedDelay: $unifiedDelay, tcpConcurrent: $tcpConcurrent, tun: $tun, dns: $dns, geoXUrl: $geoXUrl, geodataLoader: $geodataLoader, proxyGroups: $proxyGroups, rule: $rule, globalUa: $globalUa, externalController: $externalController, hosts: $hosts)';
|
||||
return 'ClashConfig(mixedPort: $mixedPort, socksPort: $socksPort, port: $port, redirPort: $redirPort, tproxyPort: $tproxyPort, mode: $mode, allowLan: $allowLan, logLevel: $logLevel, ipv6: $ipv6, findProcessMode: $findProcessMode, keepAliveInterval: $keepAliveInterval, unifiedDelay: $unifiedDelay, tcpConcurrent: $tcpConcurrent, tun: $tun, dns: $dns, geoXUrl: $geoXUrl, geodataLoader: $geodataLoader, proxyGroups: $proxyGroups, rule: $rule, globalUa: $globalUa, externalController: $externalController, hosts: $hosts)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -3973,6 +4045,13 @@ class _$ClashConfigImpl implements _ClashConfig {
|
||||
other is _$ClashConfigImpl &&
|
||||
(identical(other.mixedPort, mixedPort) ||
|
||||
other.mixedPort == mixedPort) &&
|
||||
(identical(other.socksPort, socksPort) ||
|
||||
other.socksPort == socksPort) &&
|
||||
(identical(other.port, port) || other.port == port) &&
|
||||
(identical(other.redirPort, redirPort) ||
|
||||
other.redirPort == redirPort) &&
|
||||
(identical(other.tproxyPort, tproxyPort) ||
|
||||
other.tproxyPort == tproxyPort) &&
|
||||
(identical(other.mode, mode) || other.mode == mode) &&
|
||||
(identical(other.allowLan, allowLan) ||
|
||||
other.allowLan == allowLan) &&
|
||||
@@ -4004,26 +4083,31 @@ class _$ClashConfigImpl implements _ClashConfig {
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
mixedPort,
|
||||
mode,
|
||||
allowLan,
|
||||
logLevel,
|
||||
ipv6,
|
||||
findProcessMode,
|
||||
keepAliveInterval,
|
||||
unifiedDelay,
|
||||
tcpConcurrent,
|
||||
tun,
|
||||
dns,
|
||||
geoXUrl,
|
||||
geodataLoader,
|
||||
const DeepCollectionEquality().hash(_proxyGroups),
|
||||
const DeepCollectionEquality().hash(_rule),
|
||||
globalUa,
|
||||
externalController,
|
||||
const DeepCollectionEquality().hash(_hosts));
|
||||
int get hashCode => Object.hashAll([
|
||||
runtimeType,
|
||||
mixedPort,
|
||||
socksPort,
|
||||
port,
|
||||
redirPort,
|
||||
tproxyPort,
|
||||
mode,
|
||||
allowLan,
|
||||
logLevel,
|
||||
ipv6,
|
||||
findProcessMode,
|
||||
keepAliveInterval,
|
||||
unifiedDelay,
|
||||
tcpConcurrent,
|
||||
tun,
|
||||
dns,
|
||||
geoXUrl,
|
||||
geodataLoader,
|
||||
const DeepCollectionEquality().hash(_proxyGroups),
|
||||
const DeepCollectionEquality().hash(_rule),
|
||||
globalUa,
|
||||
externalController,
|
||||
const DeepCollectionEquality().hash(_hosts)
|
||||
]);
|
||||
|
||||
/// Create a copy of ClashConfig
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -4044,6 +4128,10 @@ class _$ClashConfigImpl implements _ClashConfig {
|
||||
abstract class _ClashConfig implements ClashConfig {
|
||||
const factory _ClashConfig(
|
||||
{@JsonKey(name: "mixed-port") final int mixedPort,
|
||||
@JsonKey(name: "socks-port") final int socksPort,
|
||||
@JsonKey(name: "port") final int port,
|
||||
@JsonKey(name: "redir-port") final int redirPort,
|
||||
@JsonKey(name: "tproxy-port") final int tproxyPort,
|
||||
final Mode mode,
|
||||
@JsonKey(name: "allow-lan") final bool allowLan,
|
||||
@JsonKey(name: "log-level") final LogLevel logLevel,
|
||||
@@ -4073,6 +4161,18 @@ abstract class _ClashConfig implements ClashConfig {
|
||||
@JsonKey(name: "mixed-port")
|
||||
int get mixedPort;
|
||||
@override
|
||||
@JsonKey(name: "socks-port")
|
||||
int get socksPort;
|
||||
@override
|
||||
@JsonKey(name: "port")
|
||||
int get port;
|
||||
@override
|
||||
@JsonKey(name: "redir-port")
|
||||
int get redirPort;
|
||||
@override
|
||||
@JsonKey(name: "tproxy-port")
|
||||
int get tproxyPort;
|
||||
@override
|
||||
Mode get mode;
|
||||
@override
|
||||
@JsonKey(name: "allow-lan")
|
||||
|
||||
@@ -333,6 +333,10 @@ Map<String, dynamic> _$$ClashConfigSnippetImplToJson(
|
||||
_$ClashConfigImpl _$$ClashConfigImplFromJson(Map<String, dynamic> json) =>
|
||||
_$ClashConfigImpl(
|
||||
mixedPort: (json['mixed-port'] as num?)?.toInt() ?? defaultMixedPort,
|
||||
socksPort: (json['socks-port'] as num?)?.toInt() ?? 0,
|
||||
port: (json['port'] as num?)?.toInt() ?? 0,
|
||||
redirPort: (json['redir-port'] as num?)?.toInt() ?? 0,
|
||||
tproxyPort: (json['tproxy-port'] as num?)?.toInt() ?? 0,
|
||||
mode: $enumDecodeNullable(_$ModeEnumMap, json['mode']) ?? Mode.rule,
|
||||
allowLan: json['allow-lan'] as bool? ?? false,
|
||||
logLevel: $enumDecodeNullable(_$LogLevelEnumMap, json['log-level']) ??
|
||||
@@ -378,6 +382,10 @@ _$ClashConfigImpl _$$ClashConfigImplFromJson(Map<String, dynamic> json) =>
|
||||
Map<String, dynamic> _$$ClashConfigImplToJson(_$ClashConfigImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'mixed-port': instance.mixedPort,
|
||||
'socks-port': instance.socksPort,
|
||||
'port': instance.port,
|
||||
'redir-port': instance.redirPort,
|
||||
'tproxy-port': instance.tproxyPort,
|
||||
'mode': _$ModeEnumMap[instance.mode]!,
|
||||
'allow-lan': instance.allowLan,
|
||||
'log-level': _$LogLevelEnumMap[instance.logLevel]!,
|
||||
|
||||
@@ -514,6 +514,215 @@ abstract class _VM4<A, B, C, D> implements VM4<A, B, C, D> {
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$VM5<A, B, C, D, E> {
|
||||
A get a => throw _privateConstructorUsedError;
|
||||
B get b => throw _privateConstructorUsedError;
|
||||
C get c => throw _privateConstructorUsedError;
|
||||
D get d => throw _privateConstructorUsedError;
|
||||
E get e => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of VM5
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$VM5CopyWith<A, B, C, D, E, VM5<A, B, C, D, E>> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $VM5CopyWith<A, B, C, D, E, $Res> {
|
||||
factory $VM5CopyWith(
|
||||
VM5<A, B, C, D, E> value, $Res Function(VM5<A, B, C, D, E>) then) =
|
||||
_$VM5CopyWithImpl<A, B, C, D, E, $Res, VM5<A, B, C, D, E>>;
|
||||
@useResult
|
||||
$Res call({A a, B b, C c, D d, E e});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$VM5CopyWithImpl<A, B, C, D, E, $Res, $Val extends VM5<A, B, C, D, E>>
|
||||
implements $VM5CopyWith<A, B, C, D, E, $Res> {
|
||||
_$VM5CopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of VM5
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? a = freezed,
|
||||
Object? b = freezed,
|
||||
Object? c = freezed,
|
||||
Object? d = freezed,
|
||||
Object? e = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
a: freezed == a
|
||||
? _value.a
|
||||
: a // ignore: cast_nullable_to_non_nullable
|
||||
as A,
|
||||
b: freezed == b
|
||||
? _value.b
|
||||
: b // ignore: cast_nullable_to_non_nullable
|
||||
as B,
|
||||
c: freezed == c
|
||||
? _value.c
|
||||
: c // ignore: cast_nullable_to_non_nullable
|
||||
as C,
|
||||
d: freezed == d
|
||||
? _value.d
|
||||
: d // ignore: cast_nullable_to_non_nullable
|
||||
as D,
|
||||
e: freezed == e
|
||||
? _value.e
|
||||
: e // ignore: cast_nullable_to_non_nullable
|
||||
as E,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$VM5ImplCopyWith<A, B, C, D, E, $Res>
|
||||
implements $VM5CopyWith<A, B, C, D, E, $Res> {
|
||||
factory _$$VM5ImplCopyWith(_$VM5Impl<A, B, C, D, E> value,
|
||||
$Res Function(_$VM5Impl<A, B, C, D, E>) then) =
|
||||
__$$VM5ImplCopyWithImpl<A, B, C, D, E, $Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({A a, B b, C c, D d, E e});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$VM5ImplCopyWithImpl<A, B, C, D, E, $Res>
|
||||
extends _$VM5CopyWithImpl<A, B, C, D, E, $Res, _$VM5Impl<A, B, C, D, E>>
|
||||
implements _$$VM5ImplCopyWith<A, B, C, D, E, $Res> {
|
||||
__$$VM5ImplCopyWithImpl(_$VM5Impl<A, B, C, D, E> _value,
|
||||
$Res Function(_$VM5Impl<A, B, C, D, E>) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of VM5
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? a = freezed,
|
||||
Object? b = freezed,
|
||||
Object? c = freezed,
|
||||
Object? d = freezed,
|
||||
Object? e = freezed,
|
||||
}) {
|
||||
return _then(_$VM5Impl<A, B, C, D, E>(
|
||||
a: freezed == a
|
||||
? _value.a
|
||||
: a // ignore: cast_nullable_to_non_nullable
|
||||
as A,
|
||||
b: freezed == b
|
||||
? _value.b
|
||||
: b // ignore: cast_nullable_to_non_nullable
|
||||
as B,
|
||||
c: freezed == c
|
||||
? _value.c
|
||||
: c // ignore: cast_nullable_to_non_nullable
|
||||
as C,
|
||||
d: freezed == d
|
||||
? _value.d
|
||||
: d // ignore: cast_nullable_to_non_nullable
|
||||
as D,
|
||||
e: freezed == e
|
||||
? _value.e
|
||||
: e // ignore: cast_nullable_to_non_nullable
|
||||
as E,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$VM5Impl<A, B, C, D, E> implements _VM5<A, B, C, D, E> {
|
||||
const _$VM5Impl(
|
||||
{required this.a,
|
||||
required this.b,
|
||||
required this.c,
|
||||
required this.d,
|
||||
required this.e});
|
||||
|
||||
@override
|
||||
final A a;
|
||||
@override
|
||||
final B b;
|
||||
@override
|
||||
final C c;
|
||||
@override
|
||||
final D d;
|
||||
@override
|
||||
final E e;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'VM5<$A, $B, $C, $D, $E>(a: $a, b: $b, c: $c, d: $d, e: $e)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$VM5Impl<A, B, C, D, E> &&
|
||||
const DeepCollectionEquality().equals(other.a, a) &&
|
||||
const DeepCollectionEquality().equals(other.b, b) &&
|
||||
const DeepCollectionEquality().equals(other.c, c) &&
|
||||
const DeepCollectionEquality().equals(other.d, d) &&
|
||||
const DeepCollectionEquality().equals(other.e, e));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(a),
|
||||
const DeepCollectionEquality().hash(b),
|
||||
const DeepCollectionEquality().hash(c),
|
||||
const DeepCollectionEquality().hash(d),
|
||||
const DeepCollectionEquality().hash(e));
|
||||
|
||||
/// Create a copy of VM5
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$VM5ImplCopyWith<A, B, C, D, E, _$VM5Impl<A, B, C, D, E>> get copyWith =>
|
||||
__$$VM5ImplCopyWithImpl<A, B, C, D, E, _$VM5Impl<A, B, C, D, E>>(
|
||||
this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _VM5<A, B, C, D, E> implements VM5<A, B, C, D, E> {
|
||||
const factory _VM5(
|
||||
{required final A a,
|
||||
required final B b,
|
||||
required final C c,
|
||||
required final D d,
|
||||
required final E e}) = _$VM5Impl<A, B, C, D, E>;
|
||||
|
||||
@override
|
||||
A get a;
|
||||
@override
|
||||
B get b;
|
||||
@override
|
||||
C get c;
|
||||
@override
|
||||
D get d;
|
||||
@override
|
||||
E get e;
|
||||
|
||||
/// Create a copy of VM5
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$VM5ImplCopyWith<A, B, C, D, E, _$VM5Impl<A, B, C, D, E>> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$StartButtonSelectorState {
|
||||
bool get isInit => throw _privateConstructorUsedError;
|
||||
|
||||
@@ -34,6 +34,17 @@ class VM4<A, B, C, D> with _$VM4<A, B, C, D> {
|
||||
}) = _VM4;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class VM5<A, B, C, D, E> with _$VM5<A, B, C, D, E> {
|
||||
const factory VM5({
|
||||
required A a,
|
||||
required B b,
|
||||
required C c,
|
||||
required D d,
|
||||
required E e,
|
||||
}) = _VM5;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class StartButtonSelectorState with _$StartButtonSelectorState {
|
||||
const factory StartButtonSelectorState({
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/models/common.dart';
|
||||
import 'package:fl_clash/providers/app.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:fl_clash/widgets/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
@@ -18,6 +19,7 @@ class EditorPage extends ConsumerStatefulWidget {
|
||||
final String title;
|
||||
final String content;
|
||||
final List<Language> languages;
|
||||
final bool supportRemoteDownload;
|
||||
final bool titleEditable;
|
||||
final Function(BuildContext context, String title, String content)? onSave;
|
||||
final Future<bool> Function(
|
||||
@@ -30,6 +32,7 @@ class EditorPage extends ConsumerStatefulWidget {
|
||||
this.titleEditable = false,
|
||||
this.onSave,
|
||||
this.onPop,
|
||||
this.supportRemoteDownload = false,
|
||||
this.languages = const [
|
||||
Language.yaml,
|
||||
],
|
||||
@@ -108,6 +111,30 @@ class _EditorPageState extends ConsumerState<EditorPage> {
|
||||
_findController.findMode();
|
||||
}
|
||||
|
||||
_handleRemoteDownload() async {
|
||||
final url = await globalState.showCommonDialog(
|
||||
child: InputDialog(
|
||||
title: appLocalizations.download,
|
||||
value: "",
|
||||
labelText: appLocalizations.url,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return appLocalizations.emptyTip(appLocalizations.value);
|
||||
}
|
||||
if (!value.isUrl) {
|
||||
return appLocalizations.urlTip(appLocalizations.value);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
);
|
||||
if (url == null) {
|
||||
return;
|
||||
}
|
||||
final res = await request.getTextResponseForUrl(url);
|
||||
_controller.text = res.data;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isMobileView = ref.watch(isMobileViewProvider);
|
||||
@@ -157,6 +184,13 @@ class _EditorPageState extends ConsumerState<EditorPage> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.supportRemoteDownload)
|
||||
IconButton(
|
||||
onPressed: _handleRemoteDownload,
|
||||
icon: Icon(
|
||||
Icons.arrow_downward,
|
||||
),
|
||||
),
|
||||
_wrapController(
|
||||
(value) => CommonPopupBox(
|
||||
targetBuilder: (open) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:ffi' show Pointer;
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
|
||||
@@ -338,6 +339,10 @@ class GlobalState {
|
||||
rawConfig["socks-port"] = 0;
|
||||
rawConfig["keep-alive-interval"] = realPatchConfig.keepAliveInterval;
|
||||
rawConfig["mixed-port"] = realPatchConfig.mixedPort;
|
||||
rawConfig["port"] = realPatchConfig.port;
|
||||
rawConfig["socks-port"] = realPatchConfig.socksPort;
|
||||
rawConfig["redir-port"] = realPatchConfig.redirPort;
|
||||
rawConfig["tproxy-port"] = realPatchConfig.tproxyPort;
|
||||
rawConfig["find-process-mode"] = realPatchConfig.findProcessMode.name;
|
||||
rawConfig["allow-lan"] = realPatchConfig.allowLan;
|
||||
rawConfig["mode"] = realPatchConfig.mode.name;
|
||||
@@ -351,8 +356,13 @@ class GlobalState {
|
||||
rawConfig["tun"]["route-address"] = realPatchConfig.tun.routeAddress;
|
||||
rawConfig["tun"]["auto-route"] = realPatchConfig.tun.autoRoute;
|
||||
rawConfig["geodata-loader"] = realPatchConfig.geodataLoader.name;
|
||||
if (rawConfig["sniffer"] != null) {
|
||||
rawConfig["sniffer"] = Sniffer.fromJson(rawConfig["sniffer"]);
|
||||
if (rawConfig["sniffer"]?["sniff"] != null) {
|
||||
for (final value in (rawConfig["sniffer"]?["sniff"] as Map).values) {
|
||||
if (value["ports"] != null && value["ports"] is List) {
|
||||
value["ports"] =
|
||||
value["ports"]?.map((item) => item.toString()).toList() ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rawConfig["profile"] == null) {
|
||||
rawConfig["profile"] = {};
|
||||
@@ -441,8 +451,11 @@ class GlobalState {
|
||||
if (res.isError) {
|
||||
throw res.stringResult;
|
||||
}
|
||||
final value = runtime.convertValue<Map<String, dynamic>>(res) ?? config;
|
||||
return value;
|
||||
final value = switch (res.rawResult is Pointer) {
|
||||
true => runtime.convertValue<Map<String, dynamic>>(res),
|
||||
false => Map<String, dynamic>.from(res.rawResult),
|
||||
};
|
||||
return value ?? config;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/models/models.dart';
|
||||
import 'package:fl_clash/providers/providers.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:fl_clash/widgets/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
@@ -150,46 +151,56 @@ class TestUrlItem extends ConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class MixedPortItem extends ConsumerWidget {
|
||||
const MixedPortItem({super.key});
|
||||
class PortItem extends ConsumerWidget {
|
||||
const PortItem({super.key});
|
||||
|
||||
handleShowPortDialog() async {
|
||||
await globalState.showCommonDialog(
|
||||
child: _PortDialog(),
|
||||
);
|
||||
// inputDelegate.onChanged(value);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final mixedPort =
|
||||
ref.watch(patchClashConfigProvider.select((state) => state.mixedPort));
|
||||
return ListItem.input(
|
||||
return ListItem(
|
||||
leading: const Icon(Icons.adjust_outlined),
|
||||
title: Text(appLocalizations.proxyPort),
|
||||
title: Text(appLocalizations.port),
|
||||
subtitle: Text("$mixedPort"),
|
||||
delegate: InputDelegate(
|
||||
title: appLocalizations.proxyPort,
|
||||
value: "$mixedPort",
|
||||
validator: (String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return appLocalizations.emptyTip(appLocalizations.proxyPort);
|
||||
}
|
||||
final mixedPort = int.tryParse(value);
|
||||
if (mixedPort == null) {
|
||||
return appLocalizations.numberTip(appLocalizations.proxyPort);
|
||||
}
|
||||
if (mixedPort < 1024 || mixedPort > 49151) {
|
||||
return appLocalizations.proxyPortTip;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged: (String? value) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
final mixedPort = int.parse(value);
|
||||
ref.read(patchClashConfigProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
mixedPort: mixedPort,
|
||||
),
|
||||
);
|
||||
},
|
||||
resetValue: "$defaultMixedPort",
|
||||
),
|
||||
onTap: () {
|
||||
handleShowPortDialog();
|
||||
},
|
||||
// delegate: InputDelegate(
|
||||
// title: appLocalizations.port,
|
||||
// value: "$mixedPort",
|
||||
// validator: (String? value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// return appLocalizations.emptyTip(appLocalizations.proxyPort);
|
||||
// }
|
||||
// final mixedPort = int.tryParse(value);
|
||||
// if (mixedPort == null) {
|
||||
// return appLocalizations.numberTip(appLocalizations.proxyPort);
|
||||
// }
|
||||
// if (mixedPort < 1024 || mixedPort > 49151) {
|
||||
// return appLocalizations.proxyPortTip;
|
||||
// }
|
||||
// return null;
|
||||
// },
|
||||
// onChanged: (String? value) {
|
||||
// if (value == null) {
|
||||
// return;
|
||||
// }
|
||||
// final mixedPort = int.parse(value);
|
||||
// ref.read(patchClashConfigProvider.notifier).updateState(
|
||||
// (state) => state.copyWith(
|
||||
// mixedPort: mixedPort,
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// resetValue: "$defaultMixedPort",
|
||||
// ),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -417,7 +428,7 @@ final generalItems = <Widget>[
|
||||
UaItem(),
|
||||
if (system.isDesktop) KeepAliveIntervalItem(),
|
||||
TestUrlItem(),
|
||||
MixedPortItem(),
|
||||
PortItem(),
|
||||
HostsItem(),
|
||||
Ipv6Item(),
|
||||
AllowLanItem(),
|
||||
@@ -433,3 +444,349 @@ final generalItems = <Widget>[
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
class _PortDialog extends ConsumerStatefulWidget {
|
||||
const _PortDialog();
|
||||
|
||||
@override
|
||||
ConsumerState<_PortDialog> createState() => _PortDialogState();
|
||||
}
|
||||
|
||||
class _PortDialogState extends ConsumerState<_PortDialog> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
bool _isMore = false;
|
||||
|
||||
late TextEditingController _mixedPortController;
|
||||
late TextEditingController _portController;
|
||||
late TextEditingController _socksPortController;
|
||||
late TextEditingController _redirPortController;
|
||||
late TextEditingController _tProxyPortController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final vm5 = ref.read(patchClashConfigProvider.select((state) {
|
||||
return VM5(
|
||||
a: state.mixedPort,
|
||||
b: state.port,
|
||||
c: state.socksPort,
|
||||
d: state.redirPort,
|
||||
e: state.tproxyPort,
|
||||
);
|
||||
}));
|
||||
_mixedPortController = TextEditingController(
|
||||
text: vm5.a.toString(),
|
||||
);
|
||||
_portController = TextEditingController(
|
||||
text: vm5.b.toString(),
|
||||
);
|
||||
_socksPortController = TextEditingController(
|
||||
text: vm5.c.toString(),
|
||||
);
|
||||
_redirPortController = TextEditingController(
|
||||
text: vm5.d.toString(),
|
||||
);
|
||||
_tProxyPortController = TextEditingController(
|
||||
text: vm5.e.toString(),
|
||||
);
|
||||
}
|
||||
|
||||
_handleReset() async {
|
||||
final res = await globalState.showMessage(
|
||||
message: TextSpan(
|
||||
text: appLocalizations.resetTip,
|
||||
),
|
||||
);
|
||||
if (res != true) {
|
||||
return;
|
||||
}
|
||||
ref.read(patchClashConfigProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
mixedPort: 7890,
|
||||
port: 0,
|
||||
socksPort: 0,
|
||||
redirPort: 0,
|
||||
tproxyPort: 0,
|
||||
),
|
||||
);
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
}
|
||||
|
||||
_handleUpdate() {
|
||||
if (_formKey.currentState?.validate() == false) return;
|
||||
ref.read(patchClashConfigProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
mixedPort: int.parse(_mixedPortController.text),
|
||||
port: int.parse(_portController.text),
|
||||
socksPort: int.parse(_socksPortController.text),
|
||||
redirPort: int.parse(_redirPortController.text),
|
||||
tproxyPort: int.parse(_tProxyPortController.text),
|
||||
),
|
||||
);
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
|
||||
_handleMore() {
|
||||
setState(() {
|
||||
_isMore = !_isMore;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CommonDialog(
|
||||
title: appLocalizations.port,
|
||||
actions: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
IconButton.filledTonal(
|
||||
onPressed: _handleMore,
|
||||
icon: CommonExpandIcon(
|
||||
expand: _isMore,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: _handleReset,
|
||||
child: Text(appLocalizations.reset),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: _handleUpdate,
|
||||
child: Text(appLocalizations.submit),
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
child: Form(
|
||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||
key: _formKey,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
child: AnimatedSize(
|
||||
duration: midDuration,
|
||||
curve: Curves.easeOutQuad,
|
||||
alignment: Alignment.topCenter,
|
||||
child: Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
TextFormField(
|
||||
keyboardType: TextInputType.url,
|
||||
maxLines: 1,
|
||||
minLines: 1,
|
||||
controller: _mixedPortController,
|
||||
onFieldSubmitted: (_) {
|
||||
_handleUpdate();
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: appLocalizations.mixedPort,
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return appLocalizations
|
||||
.emptyTip(appLocalizations.mixedPort);
|
||||
}
|
||||
final port = int.tryParse(value);
|
||||
if (port == null) {
|
||||
return appLocalizations
|
||||
.numberTip(appLocalizations.mixedPort);
|
||||
}
|
||||
if (port < 1024 || port > 49151) {
|
||||
return appLocalizations.mixedPort;
|
||||
}
|
||||
final ports = [
|
||||
_portController.text,
|
||||
_socksPortController.text,
|
||||
_tProxyPortController.text,
|
||||
_redirPortController.text
|
||||
].map((item) => item.trim());
|
||||
if (ports.contains(value.trim())) {
|
||||
return appLocalizations.portConflictTip;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
if (_isMore) ...[
|
||||
TextFormField(
|
||||
keyboardType: TextInputType.url,
|
||||
maxLines: 1,
|
||||
minLines: 1,
|
||||
controller: _portController,
|
||||
onFieldSubmitted: (_) {
|
||||
_handleUpdate();
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: appLocalizations.port,
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return appLocalizations.emptyTip(appLocalizations.port);
|
||||
}
|
||||
final port = int.tryParse(value);
|
||||
if (port == null) {
|
||||
return appLocalizations.numberTip(
|
||||
appLocalizations.port,
|
||||
);
|
||||
}
|
||||
if (port == 0) {
|
||||
return null;
|
||||
}
|
||||
if (port < 1024 || port > 49151) {
|
||||
return appLocalizations.portTip(appLocalizations.port);
|
||||
}
|
||||
final ports = [
|
||||
_mixedPortController.text,
|
||||
_socksPortController.text,
|
||||
_tProxyPortController.text,
|
||||
_redirPortController.text
|
||||
].map((item) => item.trim());
|
||||
if (ports.contains(value.trim())) {
|
||||
return appLocalizations.portConflictTip;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
keyboardType: TextInputType.url,
|
||||
maxLines: 1,
|
||||
minLines: 1,
|
||||
controller: _socksPortController,
|
||||
onFieldSubmitted: (_) {
|
||||
_handleUpdate();
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: appLocalizations.socksPort,
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return appLocalizations
|
||||
.emptyTip(appLocalizations.socksPort);
|
||||
}
|
||||
final port = int.tryParse(value);
|
||||
if (port == null) {
|
||||
return appLocalizations
|
||||
.numberTip(appLocalizations.socksPort);
|
||||
}
|
||||
if (port == 0) {
|
||||
return null;
|
||||
}
|
||||
if (port < 1024 || port > 49151) {
|
||||
return appLocalizations
|
||||
.portTip(appLocalizations.socksPort);
|
||||
}
|
||||
final ports = [
|
||||
_portController.text,
|
||||
_mixedPortController.text,
|
||||
_tProxyPortController.text,
|
||||
_redirPortController.text
|
||||
].map((item) => item.trim());
|
||||
if (ports.contains(value.trim())) {
|
||||
return appLocalizations.portConflictTip;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
keyboardType: TextInputType.url,
|
||||
maxLines: 1,
|
||||
minLines: 1,
|
||||
controller: _redirPortController,
|
||||
onFieldSubmitted: (_) {
|
||||
_handleUpdate();
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: appLocalizations.redirPort,
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return appLocalizations
|
||||
.emptyTip(appLocalizations.redirPort);
|
||||
}
|
||||
final port = int.tryParse(value);
|
||||
if (port == null) {
|
||||
return appLocalizations
|
||||
.numberTip(appLocalizations.redirPort);
|
||||
}
|
||||
if (port == 0) {
|
||||
return null;
|
||||
}
|
||||
if (port < 1024 || port > 49151) {
|
||||
return appLocalizations
|
||||
.portTip(appLocalizations.redirPort);
|
||||
}
|
||||
final ports = [
|
||||
_portController.text,
|
||||
_socksPortController.text,
|
||||
_tProxyPortController.text,
|
||||
_mixedPortController.text
|
||||
].map((item) => item.trim());
|
||||
if (ports.contains(value.trim())) {
|
||||
return appLocalizations.portConflictTip;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
keyboardType: TextInputType.url,
|
||||
maxLines: 1,
|
||||
minLines: 1,
|
||||
controller: _tProxyPortController,
|
||||
onFieldSubmitted: (_) {
|
||||
_handleUpdate();
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
labelText: appLocalizations.tproxyPort,
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return appLocalizations
|
||||
.emptyTip(appLocalizations.tproxyPort);
|
||||
}
|
||||
final port = int.tryParse(value);
|
||||
if (port == null) {
|
||||
return appLocalizations
|
||||
.numberTip(appLocalizations.tproxyPort);
|
||||
}
|
||||
if (port == 0) {
|
||||
return null;
|
||||
}
|
||||
if (port < 1024 || port > 49151) {
|
||||
return appLocalizations.portTip(
|
||||
appLocalizations.tproxyPort,
|
||||
);
|
||||
}
|
||||
final ports = [
|
||||
_portController.text,
|
||||
_socksPortController.text,
|
||||
_mixedPortController.text,
|
||||
_redirPortController.text
|
||||
].map((item) => item.trim());
|
||||
if (ports.contains(value.trim())) {
|
||||
return appLocalizations.portConflictTip;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,6 +198,7 @@ class _ScriptsViewState extends ConsumerState<ScriptsView> {
|
||||
EditorPage(
|
||||
titleEditable: true,
|
||||
title: title,
|
||||
supportRemoteDownload: true,
|
||||
onSave: (context, title, content) {
|
||||
_handleEditorSave(
|
||||
context,
|
||||
|
||||
@@ -357,10 +357,7 @@ class ListHeader extends StatefulWidget {
|
||||
State<ListHeader> createState() => _ListHeaderState();
|
||||
}
|
||||
|
||||
class _ListHeaderState extends State<ListHeader>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _animationController;
|
||||
late Animation<double> _iconTurns;
|
||||
class _ListHeaderState extends State<ListHeader> {
|
||||
var isLock = false;
|
||||
|
||||
String get icon => widget.group.icon;
|
||||
@@ -385,39 +382,6 @@ class _ListHeaderState extends State<ListHeader>
|
||||
widget.onChange(groupName);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_animationController = AnimationController(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
vsync: this,
|
||||
);
|
||||
_iconTurns = _animationController.drive(
|
||||
Tween<double>(begin: 0.0, end: 0.5),
|
||||
);
|
||||
if (isExpand) {
|
||||
_animationController.value = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_animationController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(ListHeader oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.isExpand != widget.isExpand) {
|
||||
if (isExpand) {
|
||||
_animationController.forward();
|
||||
} else {
|
||||
_animationController.reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildIcon() {
|
||||
return Consumer(
|
||||
builder: (_, ref, child) {
|
||||
@@ -599,21 +563,13 @@ class _ListHeaderState extends State<ListHeader>
|
||||
SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
AnimatedBuilder(
|
||||
animation: _animationController.view,
|
||||
builder: (_, __) {
|
||||
return IconButton.filledTonal(
|
||||
onPressed: () {
|
||||
_handleChange(groupName);
|
||||
},
|
||||
icon: RotationTransition(
|
||||
turns: _iconTurns,
|
||||
child: const Icon(
|
||||
Icons.expand_more,
|
||||
),
|
||||
),
|
||||
);
|
||||
IconButton.filledTonal(
|
||||
onPressed: () {
|
||||
_handleChange(groupName);
|
||||
},
|
||||
icon: CommonExpandIcon(
|
||||
expand: isExpand,
|
||||
),
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
@@ -60,6 +60,68 @@ class _EffectGestureDetectorState extends State<EffectGestureDetector>
|
||||
}
|
||||
}
|
||||
|
||||
class CommonExpandIcon extends StatefulWidget {
|
||||
final bool expand;
|
||||
|
||||
const CommonExpandIcon({
|
||||
super.key,
|
||||
this.expand = false,
|
||||
});
|
||||
|
||||
@override
|
||||
State<CommonExpandIcon> createState() => _CommonExpandIconState();
|
||||
}
|
||||
|
||||
class _CommonExpandIconState extends State<CommonExpandIcon>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _animationController;
|
||||
late Animation<double> _iconTurns;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_animationController = AnimationController(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
vsync: this,
|
||||
);
|
||||
_iconTurns = _animationController.drive(
|
||||
Tween<double>(begin: 0.0, end: 0.5),
|
||||
);
|
||||
if (widget.expand) {
|
||||
_animationController.value = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant CommonExpandIcon oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (oldWidget.expand != widget.expand) {
|
||||
if (widget.expand) {
|
||||
_animationController.forward();
|
||||
} else {
|
||||
_animationController.reverse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: _animationController.view,
|
||||
builder: (_, child) {
|
||||
return RotationTransition(
|
||||
turns: _iconTurns,
|
||||
child: child!,
|
||||
);
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.expand_more,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget proxyDecorator(
|
||||
Widget child,
|
||||
int index,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: fl_clash
|
||||
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
||||
publish_to: 'none'
|
||||
version: 0.8.85+202505281
|
||||
version: 0.8.85+202505291
|
||||
environment:
|
||||
sdk: '>=3.1.0 <4.0.0'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user