diff --git a/core/config.go b/core/config.go index ecae3cbc..cbbe6793 100644 --- a/core/config.go +++ b/core/config.go @@ -227,27 +227,9 @@ func patchTun(target *LC.Tun, params *tunSchema) { if params.Device != nil { target.Device = *params.Device } - if params.RouteAddress != nil { - target.RouteAddress = *params.RouteAddress - } - if params.DNSHijack != nil { - target.DNSHijack = *params.DNSHijack - } if params.Stack != nil { target.Stack = *params.Stack } - if params.MTU != nil { - target.MTU = *params.MTU - } - if params.CongestionController != nil { - target.CongestionController = *params.CongestionController - } - if params.StrictRoute != nil { - target.StrictRoute = *params.StrictRoute - } - if params.RouteExcludeAddress != nil { - target.RouteExcludeAddress = *params.RouteExcludeAddress - } } func routeConfig(cfg *config.Config) *route.Config { diff --git a/core/config_test.go b/core/config_test.go index 00d10648..da8249a5 100644 --- a/core/config_test.go +++ b/core/config_test.go @@ -246,9 +246,9 @@ func TestUpdateConfigPatchesOnlyTheTunFieldsItWasGiven(t *testing.T) { func TestUpdateConfigDecodesTheTunSettingsTheHostSends(t *testing.T) { withCurrentConfig(t, &config.Config{General: &config.General{}, Controller: &config.Controller{}}) + currentConfig.General.Tun.MTU = 1400 var params UpdateParams - payload := `{"tun":{"enable":true,"mtu":1400,"congestion-controller":"bbr","strict-route":true, - "route-exclude-address":["10.0.0.0/8"]}}` + payload := `{"tun":{"enable":true,"device":"FlClash","stack":"gvisor","auto-route":true,"mtu":9000}}` if err := json.Unmarshal([]byte(payload), ¶ms); err != nil { t.Fatalf("decode: %v", err) } @@ -257,11 +257,11 @@ func TestUpdateConfigDecodesTheTunSettingsTheHostSends(t *testing.T) { t.Fatalf("updateConfig error: %v", err) } tun := currentConfig.General.Tun - if tun.MTU != 1400 || tun.CongestionController != "bbr" || !tun.StrictRoute { - t.Errorf("MTU = %d, CongestionController = %q, StrictRoute = %v", tun.MTU, tun.CongestionController, tun.StrictRoute) + if !tun.Enable || !tun.AutoRoute || tun.Device != "FlClash" || tun.Stack != constant.TunGvisor { + t.Errorf("Enable = %v, AutoRoute = %v, Device = %q, Stack = %v", tun.Enable, tun.AutoRoute, tun.Device, tun.Stack) } - if len(tun.RouteExcludeAddress) != 1 || tun.RouteExcludeAddress[0] != netip.MustParsePrefix("10.0.0.0/8") { - t.Errorf("RouteExcludeAddress = %v", tun.RouteExcludeAddress) + if tun.MTU != 1400 { + t.Errorf("MTU = %d, want the profile's value kept", tun.MTU) } } diff --git a/core/protocol.go b/core/protocol.go index 04f9aa3a..57242164 100644 --- a/core/protocol.go +++ b/core/protocol.go @@ -1,7 +1,6 @@ package core import ( - "net/netip" "time" "github.com/metacubex/http" @@ -147,16 +146,10 @@ type UpdateParams struct { } type tunSchema struct { - Enable bool `yaml:"enable" json:"enable"` - Device *string `yaml:"device" json:"device"` - Stack *constant.TUNStack `yaml:"stack" json:"stack"` - DNSHijack *[]string `yaml:"dns-hijack" json:"dns-hijack"` - AutoRoute *bool `yaml:"auto-route" json:"auto-route"` - RouteAddress *[]netip.Prefix `yaml:"route-address" json:"route-address,omitempty"` - MTU *uint32 `yaml:"mtu" json:"mtu"` - CongestionController *string `yaml:"congestion-controller" json:"congestion-controller"` - StrictRoute *bool `yaml:"strict-route" json:"strict-route"` - RouteExcludeAddress *[]netip.Prefix `yaml:"route-exclude-address" json:"route-exclude-address"` + Enable bool `yaml:"enable" json:"enable"` + Device *string `yaml:"device" json:"device"` + Stack *constant.TUNStack `yaml:"stack" json:"stack"` + AutoRoute *bool `yaml:"auto-route" json:"auto-route"` } type SideLoadParams struct { diff --git a/lib/common/proxy.dart b/lib/common/proxy.dart index 7e6c3728..5cc31b52 100644 --- a/lib/common/proxy.dart +++ b/lib/common/proxy.dart @@ -1,9 +1,57 @@ import 'package:fl_clash/common/constant.dart'; +import 'package:fl_clash/common/print.dart'; import 'package:fl_clash/common/system.dart'; +import 'package:fl_clash/enum/enum.dart'; +import 'package:fl_clash/models/models.dart' show ProxyState; import 'package:proxy/proxy.dart'; final proxy = system.isDesktop && !safeModeBuild ? Proxy() : null; +final systemProxyQueue = proxy == null ? null : SystemProxyQueue(proxy!); + +/// Exit's stop goes through the same queue as every other change, so a start +/// still waiting behind a slow call cannot turn the proxy back on after it. +class SystemProxyQueue { + final Proxy _proxy; + Future _tail = Future.value(); + bool _closed = false; + + SystemProxyQueue(this._proxy); + + Future apply(ProxyState state) { + return _enqueue(() async { + if (_closed) { + return; + } + final applied = state.isStart && state.systemProxy + ? await _proxy.startProxy(state.port, state.bassDomain) + : await _proxy.stopProxy(); + if (!applied) { + commonPrint.log( + 'update system proxy failed', + logLevel: LogLevel.warning, + ); + } + }); + } + + Future close() { + _closed = true; + return _enqueue(() async { + await _proxy.stopProxy(); + }); + } + + Future _enqueue(Future Function() task) { + return _tail = _tail.then((_) => task()).catchError((Object error) { + commonPrint.log( + 'update system proxy failed: $error', + logLevel: LogLevel.warning, + ); + }); + } +} + String proxyEnvCommand(int port, {required bool isWindows}) { final url = 'http://127.0.0.1:$port'; return isWindows ? 'set \$env:all_proxy=$url' : 'export all_proxy=$url'; diff --git a/lib/common/task.dart b/lib/common/task.dart index 7b8f7061..5460b956 100644 --- a/lib/common/task.dart +++ b/lib/common/task.dart @@ -207,11 +207,25 @@ Future _makeRealProfileTask(MakeRealProfileState data) async { rawConfig['authentication'] = data.authentication; rawConfig['skip-auth-prefixes'] = []; rawConfig['mode'] = realPatchConfig.mode.name; - rawConfig['tun'] = { + // auto-route is always on, so without auto-detect-interface the core sends + // its own outbound back into the TUN unless interface-name binds it, and + // interface-name wins over the detected interface anyway. A profile's own + // dns-hijack may leave queries to other resolvers unhijacked, so only a + // picked key replaces any:53. + final tun = { if (rawConfig['tun'] is Map) ...rawConfig['tun'] as Map, + 'dns-hijack': defaultDnsHijack, ...overrides.tun.overrideJson(overrides.tunOverrideKeys), - ...realPatchConfig.tun.toJson(), + ...realPatchConfig.tun.coreJson, + 'auto-detect-interface': true, }; + if (data.bypassPrivateRoute) { + tun['route-exclude-address'] = [ + if (tun['route-exclude-address'] case final List routes) ...routes, + ...privateRouteAddress, + ]; + } + rawConfig['tun'] = tun; rawConfig['geodata-loader'] = realPatchConfig.geodataLoader.name; rawConfig['geo-auto-update'] = realPatchConfig.geoAutoUpdate; rawConfig['geo-update-interval'] = realPatchConfig.geoUpdateInterval; diff --git a/lib/common/tray.dart b/lib/common/tray.dart index 4e1c879c..8c8aa776 100644 --- a/lib/common/tray.dart +++ b/lib/common/tray.dart @@ -67,6 +67,11 @@ class AppTray implements TrayPort { @override Future shutdown() async { _isShutDown = true; + // Removing a status item makes macOS forget where the user dragged it in + // the menu bar; one that goes away with the process keeps its place. + if (isMacOS) { + return; + } await Tray.instance.hide(); } @@ -83,7 +88,7 @@ class AppTray implements TrayPort { TraySpec( icon: TrayIcon.asset( getTrayIcon( - isStart: trayState.isStart, + isStart: trayState.isStart && !trayState.suspended, tunEnable: trayState.tunEnable, safeMode: trayState.safeMode, ), diff --git a/lib/enum/enum.dart b/lib/enum/enum.dart index ac77b451..b39e2c93 100644 --- a/lib/enum/enum.dart +++ b/lib/enum/enum.dart @@ -364,11 +364,24 @@ enum SnifferOverrideKey with OverrideKey { } /// Written over the profile's `tun` section, which Android's VPN never reads, -/// so these apply on desktop only. The network settings' `Tun` holds the rest. +/// so these apply on desktop only, beside the keys of `Tun.coreJson`. @JsonEnum(valueField: 'path') enum TunOverrideKey with OverrideKey { + mtu('mtu'), + congestionController('congestion-controller'), + strictRoute('strict-route'), + routeAddress('route-address'), + routeExcludeAddress('route-exclude-address'), + dnsHijack('dns-hijack'), + udpTimeout('udp-timeout'), disableIcmpForwarding('disable-icmp-forwarding'), - excludeInterface('exclude-interface'); + gso('gso'), + includeInterface('include-interface'), + excludeInterface('exclude-interface'), + includeUid('include-uid'), + excludeUid('exclude-uid'), + excludeSrcPort('exclude-src-port'), + excludeDstPort('exclude-dst-port'); const TunOverrideKey(this.path); @@ -793,7 +806,7 @@ enum RestoreStrategy { compatible, override } enum TabAnimation { slide, fade } -enum LiquidGlassMode { none, standard } +enum LiquidGlassMode { none, standard, ultra } enum Language { yaml, javaScript, json } diff --git a/lib/manager/proxy_manager.dart b/lib/manager/proxy_manager.dart index 910c0021..d761bb0a 100644 --- a/lib/manager/proxy_manager.dart +++ b/lib/manager/proxy_manager.dart @@ -1,7 +1,4 @@ import 'package:fl_clash/common/proxy.dart'; -import 'package:fl_clash/common/print.dart'; -import 'package:fl_clash/enum/enum.dart'; -import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/providers/state.dart'; import 'package:material_ui/material_ui.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -16,40 +13,12 @@ class ProxyManager extends ConsumerStatefulWidget { } class _ProxyManagerState extends ConsumerState { - Future _pendingUpdate = Future.value(); - - Future _updateProxy(ProxyState proxyState) async { - final isStart = proxyState.isStart; - final systemProxy = proxyState.systemProxy; - final port = proxyState.port; - bool? result; - if (isStart && systemProxy) { - result = await proxy?.startProxy(port, proxyState.bassDomain); - } else { - result = await proxy?.stopProxy(); - } - if (result == false) { - commonPrint.log('update system proxy failed', logLevel: LogLevel.warning); - } - } - - void _scheduleUpdateProxy(ProxyState proxyState) { - _pendingUpdate = _pendingUpdate - .then((_) => _updateProxy(proxyState)) - .catchError((Object error) { - commonPrint.log( - 'update system proxy failed: $error', - logLevel: LogLevel.warning, - ); - }); - } - @override void initState() { super.initState(); ref.listenManual(proxyStateProvider, (prev, next) { if (prev != next) { - _scheduleUpdateProxy(next); + systemProxyQueue?.apply(next); } }, fireImmediately: true); } diff --git a/lib/models/clash_config.dart b/lib/models/clash_config.dart index 2e529d98..c049e495 100644 --- a/lib/models/clash_config.dart +++ b/lib/models/clash_config.dart @@ -47,6 +47,16 @@ const minTunMtu = 1280; const maxTunMtu = 65535; const defaultCongestionController = 'cubic'; +// The congestion controls mipstack registers, cubic first as its default. +const congestionControllers = [ + defaultCongestionController, + 'reno', + 'bbr', + 'bbr3', +]; +const defaultDnsHijack = ['any:53']; +const defaultTunUdpTimeout = 300; + const privateRouteAddress = [ '0.0.0.0/8', '10.0.0.0/8', @@ -982,14 +992,13 @@ Map _rawSniff(Map raw) { }; } +/// The desktop TUN takes only [TunExt.coreJson]; Android's VPN starts from all. @freezed abstract class Tun with _$Tun { const factory Tun({ @Default(false) bool enable, @Default(appName) String device, - @JsonKey(name: 'auto-route') @Default(false) bool autoRoute, @Default(TunStack.mips) TunStack stack, - @JsonKey(name: 'dns-hijack') @Default(['any:53']) List dnsHijack, @JsonKey(name: 'route-address') @Default([]) List routeAddress, @JsonKey(fromJson: _mtuFromJson) @Default(defaultTunMtu) int mtu, @JsonKey( @@ -998,7 +1007,6 @@ abstract class Tun with _$Tun { ) @Default(defaultCongestionController) String congestionController, - @JsonKey(name: 'strict-route') @Default(false) bool strictRoute, @JsonKey(name: 'route-exclude-address') @Default([]) List routeExcludeAddress, @@ -1036,10 +1044,13 @@ extension TunExt on Tun { return subtractCidrsTask(routeAddress, excluded, wholeWhenEmpty: true); } - Tun getRealTun({required bool bypassPrivateRoute}) => copyWith( - autoRoute: true, - routeExcludeAddress: excludedRoutes(bypassPrivateRoute: bypassPrivateRoute), - ); + Map get coreJson { + final json = toJson(); + return { + for (final key in const ['enable', 'device', 'stack']) key: json[key], + 'auto-route': true, + }; + } } @freezed @@ -1409,12 +1420,33 @@ extension NtpOverrideExt on Ntp { @freezed abstract class ProfileTun with _$ProfileTun { const factory ProfileTun({ + @Default(defaultTunMtu) int mtu, + @Default(defaultCongestionController) + @JsonKey(name: 'congestion-controller') + String congestionController, + @Default(false) @JsonKey(name: 'strict-route') bool strictRoute, + @Default([]) @JsonKey(name: 'route-address') List routeAddress, + @Default([]) + @JsonKey(name: 'route-exclude-address') + List routeExcludeAddress, + @Default(defaultDnsHijack) + @JsonKey(name: 'dns-hijack') + List dnsHijack, + @Default(defaultTunUdpTimeout) @JsonKey(name: 'udp-timeout') int udpTimeout, @Default(false) @JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding, + @Default(false) bool gso, + @Default([]) + @JsonKey(name: 'include-interface') + List includeInterface, @Default([]) @JsonKey(name: 'exclude-interface') List excludeInterface, + @Default([]) @JsonKey(name: 'include-uid') List includeUid, + @Default([]) @JsonKey(name: 'exclude-uid') List excludeUid, + @Default([]) @JsonKey(name: 'exclude-src-port') List excludeSrcPort, + @Default([]) @JsonKey(name: 'exclude-dst-port') List excludeDstPort, }) = _ProfileTun; factory ProfileTun.fromJson(Map json) => @@ -1437,6 +1469,35 @@ extension TunOverrideExt on ProfileTun { _overrideJson(toJson(), TunOverrideKey.values, keys); } +/// Network TUN values changed from their defaults become app-wide overrides. +Map _withLegacyTunOverride(Map json) { + final raw = json['tun']; + if (json.containsKey(_tunOverrideKeysJsonKey) || raw is! Map) { + return json; + } + final tun = Tun.safeFormJson(Map.from(raw)); + final override = ProfileTun( + mtu: tun.mtu, + congestionController: tun.congestionController, + strictRoute: raw['strict-route'] == true, + routeAddress: tun.routeAddress, + routeExcludeAddress: tun.routeExcludeAddress, + ); + return { + ...json, + 'tun-override': override.toJson(), + _tunOverrideKeysJsonKey: [ + if (tun.mtu != defaultTunMtu) TunOverrideKey.mtu.path, + if (tun.congestionController != defaultCongestionController) + TunOverrideKey.congestionController.path, + if (override.strictRoute) TunOverrideKey.strictRoute.path, + if (tun.routeAddress.isNotEmpty) TunOverrideKey.routeAddress.path, + if (tun.routeExcludeAddress.isNotEmpty) + TunOverrideKey.routeExcludeAddress.path, + ], + }; +} + @freezed abstract class ProfileOverrides with _$ProfileOverrides { const factory ProfileOverrides({ @@ -1580,6 +1641,17 @@ extension ProfileOverridesExt on ProfileOverrides { bool get customSnifferEnabled => snifferOverrideKeys.contains(SnifferOverrideKey.enable) && sniffer.enable; + + ProfileOverrides overAppTun(ProfileTun tun, Set keys) { + final own = this.tun.toJson(); + return copyWith( + tun: ProfileTun.fromJson({ + ...tun.toJson(), + for (final key in tunOverrideKeys) key.path: own[key.path], + }), + tunOverrideKeys: {...keys, ...tunOverrideKeys}, + ); + } } @freezed @@ -1915,6 +1987,12 @@ abstract class PatchClashConfig with _$PatchClashConfig { @Default({}) @JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys, + @Default(defaultProfileTun) + @JsonKey(name: 'tun-override', fromJson: ProfileTun.safeFromJson) + ProfileTun tunOverride, + @Default({}) + @JsonKey(name: _tunOverrideKeysJsonKey, fromJson: _tunOverrideKeysFromJson) + Set tunOverrideKeys, @Default(defaultGeoXUrl) @JsonKey( name: 'geox-url', @@ -1936,7 +2014,9 @@ abstract class PatchClashConfig with _$PatchClashConfig { }) = _PatchClashConfig; factory PatchClashConfig.fromJson(Map json) => - _$PatchClashConfigFromJson(_withLegacyDnsOverrideKeys(json)); + _$PatchClashConfigFromJson( + _withLegacyTunOverride(_withLegacyDnsOverrideKeys(json)), + ); factory PatchClashConfig.safeFormJson(Map? json) { if (json == null) { @@ -1948,12 +2028,11 @@ abstract class PatchClashConfig with _$PatchClashConfig { extension PatchClashConfigExt on PatchClashConfig { UpdateParams toUpdateParams({ - required bool bypassPrivateRoute, required List authentication, required bool skipCertVerify, }) { return UpdateParams( - tun: tun.getRealTun(bypassPrivateRoute: bypassPrivateRoute), + tun: tun, authentication: authentication, allowLan: allowLan, findProcessMode: findProcessMode, diff --git a/lib/models/config.dart b/lib/models/config.dart index 534335f1..4cfdbffc 100644 --- a/lib/models/config.dart +++ b/lib/models/config.dart @@ -145,6 +145,12 @@ const _legacyDashboardWidgets = { 'trafficUsage': DashboardWidget.networkSpeed, }; +const _retiredDashboardWidgets = { + 'runTime', + 'overrideDnsButton', + 'overrideNtpButton', +}; + /// The current outbound card cannot be removed: a list without it predates it. List dashboardWidgetsFromJson( List? dashboardWidgets, @@ -171,7 +177,8 @@ List dashboardWidgetsFromJson( final kept = dashboardWidgets .map((e) => _legacyDashboardWidgets[e] ?? byName[e]) .nonNulls; - if (kept.isEmpty) { + if (kept.isEmpty && + !dashboardWidgets.every(_retiredDashboardWidgets.contains)) { return defaultDashboardWidgets; } return {DashboardWidget.currentOutbound, ...kept}.toList(); diff --git a/lib/models/core.dart b/lib/models/core.dart index d2c9b531..0b9f91ff 100644 --- a/lib/models/core.dart +++ b/lib/models/core.dart @@ -45,7 +45,7 @@ abstract class ProfileBase with _$ProfileBase { @freezed abstract class UpdateParams with _$UpdateParams { const factory UpdateParams({ - required Tun tun, + @JsonKey(toJson: _tunCoreJson) required Tun tun, @JsonKey(name: 'mixed-port') required int mixedPort, @JsonKey(name: 'allow-lan') required bool allowLan, @JsonKey(name: 'find-process-mode') @@ -69,6 +69,8 @@ abstract class UpdateParams with _$UpdateParams { _$UpdateParamsFromJson(json); } +Map _tunCoreJson(Tun tun) => tun.coreJson; + @freezed abstract class VpnOptions with _$VpnOptions { const factory VpnOptions({ diff --git a/lib/models/generated/clash_config.freezed.dart b/lib/models/generated/clash_config.freezed.dart index 55be0517..e709a025 100644 --- a/lib/models/generated/clash_config.freezed.dart +++ b/lib/models/generated/clash_config.freezed.dart @@ -3754,7 +3754,7 @@ as bool?, /// @nodoc mixin _$Tun { - bool get enable; String get device;@JsonKey(name: 'auto-route') bool get autoRoute; TunStack get stack;@JsonKey(name: 'dns-hijack') List get dnsHijack;@JsonKey(name: 'route-address') List get routeAddress;@JsonKey(fromJson: _mtuFromJson) int get mtu;@JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String get congestionController;@JsonKey(name: 'strict-route') bool get strictRoute;@JsonKey(name: 'route-exclude-address') List get routeExcludeAddress; + bool get enable; String get device; TunStack get stack;@JsonKey(name: 'route-address') List get routeAddress;@JsonKey(fromJson: _mtuFromJson) int get mtu;@JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String get congestionController;@JsonKey(name: 'route-exclude-address') List get routeExcludeAddress; /// Create a copy of Tun /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -3768,20 +3768,20 @@ $TunCopyWith get copyWith => _$TunCopyWithImpl(this as Tun, _$identity @override bool operator ==(Object other) { final _this = this as Tun; - return identical(this, other) || (other.runtimeType == runtimeType&&other is Tun&&(identical(other.enable, _this.enable) || other.enable == _this.enable)&&(identical(other.device, _this.device) || other.device == _this.device)&&(identical(other.autoRoute, _this.autoRoute) || other.autoRoute == _this.autoRoute)&&(identical(other.stack, _this.stack) || other.stack == _this.stack)&&const DeepCollectionEquality().equals(other.dnsHijack, _this.dnsHijack)&&const DeepCollectionEquality().equals(other.routeAddress, _this.routeAddress)&&(identical(other.mtu, _this.mtu) || other.mtu == _this.mtu)&&(identical(other.congestionController, _this.congestionController) || other.congestionController == _this.congestionController)&&(identical(other.strictRoute, _this.strictRoute) || other.strictRoute == _this.strictRoute)&&const DeepCollectionEquality().equals(other.routeExcludeAddress, _this.routeExcludeAddress)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is Tun&&(identical(other.enable, _this.enable) || other.enable == _this.enable)&&(identical(other.device, _this.device) || other.device == _this.device)&&(identical(other.stack, _this.stack) || other.stack == _this.stack)&&const DeepCollectionEquality().equals(other.routeAddress, _this.routeAddress)&&(identical(other.mtu, _this.mtu) || other.mtu == _this.mtu)&&(identical(other.congestionController, _this.congestionController) || other.congestionController == _this.congestionController)&&const DeepCollectionEquality().equals(other.routeExcludeAddress, _this.routeExcludeAddress)); } @JsonKey(includeFromJson: false, includeToJson: false) @override int get hashCode { final _this = this as Tun; - return Object.hash(runtimeType,_this.enable,_this.device,_this.autoRoute,_this.stack,const DeepCollectionEquality().hash(_this.dnsHijack),const DeepCollectionEquality().hash(_this.routeAddress),_this.mtu,_this.congestionController,_this.strictRoute,const DeepCollectionEquality().hash(_this.routeExcludeAddress)); + return Object.hash(runtimeType,_this.enable,_this.device,_this.stack,const DeepCollectionEquality().hash(_this.routeAddress),_this.mtu,_this.congestionController,const DeepCollectionEquality().hash(_this.routeExcludeAddress)); } @override String toString() { final _this = this as Tun; - return 'Tun(enable: ${_this.enable}, device: ${_this.device}, autoRoute: ${_this.autoRoute}, stack: ${_this.stack}, dnsHijack: ${_this.dnsHijack}, routeAddress: ${_this.routeAddress}, mtu: ${_this.mtu}, congestionController: ${_this.congestionController}, strictRoute: ${_this.strictRoute}, routeExcludeAddress: ${_this.routeExcludeAddress})'; + return 'Tun(enable: ${_this.enable}, device: ${_this.device}, stack: ${_this.stack}, routeAddress: ${_this.routeAddress}, mtu: ${_this.mtu}, congestionController: ${_this.congestionController}, routeExcludeAddress: ${_this.routeExcludeAddress})'; } @@ -3792,7 +3792,7 @@ abstract mixin class $TunCopyWith<$Res> { factory $TunCopyWith(Tun value, $Res Function(Tun) _then) = _$TunCopyWithImpl; @useResult $Res call({ - bool enable, String device,@JsonKey(name: 'auto-route') bool autoRoute, TunStack stack,@JsonKey(name: 'dns-hijack') List dnsHijack,@JsonKey(name: 'route-address') List routeAddress,@JsonKey(fromJson: _mtuFromJson) int mtu,@JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String congestionController,@JsonKey(name: 'strict-route') bool strictRoute,@JsonKey(name: 'route-exclude-address') List routeExcludeAddress + bool enable, String device, TunStack stack,@JsonKey(name: 'route-address') List routeAddress,@JsonKey(fromJson: _mtuFromJson) int mtu,@JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String congestionController,@JsonKey(name: 'route-exclude-address') List routeExcludeAddress }); @@ -3809,18 +3809,15 @@ class _$TunCopyWithImpl<$Res> /// Create a copy of Tun /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? enable = null,Object? device = null,Object? autoRoute = null,Object? stack = null,Object? dnsHijack = null,Object? routeAddress = null,Object? mtu = null,Object? congestionController = null,Object? strictRoute = null,Object? routeExcludeAddress = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? enable = null,Object? device = null,Object? stack = null,Object? routeAddress = null,Object? mtu = null,Object? congestionController = null,Object? routeExcludeAddress = null,}) { return _then(Tun( enable: null == enable ? _self.enable : enable // ignore: cast_nullable_to_non_nullable as bool,device: null == device ? _self.device : device // ignore: cast_nullable_to_non_nullable -as String,autoRoute: null == autoRoute ? _self.autoRoute : autoRoute // ignore: cast_nullable_to_non_nullable -as bool,stack: null == stack ? _self.stack : stack // ignore: cast_nullable_to_non_nullable -as TunStack,dnsHijack: null == dnsHijack ? _self.dnsHijack : dnsHijack // ignore: cast_nullable_to_non_nullable -as List,routeAddress: null == routeAddress ? _self.routeAddress : routeAddress // ignore: cast_nullable_to_non_nullable +as String,stack: null == stack ? _self.stack : stack // ignore: cast_nullable_to_non_nullable +as TunStack,routeAddress: null == routeAddress ? _self.routeAddress : routeAddress // ignore: cast_nullable_to_non_nullable as List,mtu: null == mtu ? _self.mtu : mtu // ignore: cast_nullable_to_non_nullable as int,congestionController: null == congestionController ? _self.congestionController : congestionController // ignore: cast_nullable_to_non_nullable -as String,strictRoute: null == strictRoute ? _self.strictRoute : strictRoute // ignore: cast_nullable_to_non_nullable -as bool,routeExcludeAddress: null == routeExcludeAddress ? _self.routeExcludeAddress : routeExcludeAddress // ignore: cast_nullable_to_non_nullable +as String,routeExcludeAddress: null == routeExcludeAddress ? _self.routeExcludeAddress : routeExcludeAddress // ignore: cast_nullable_to_non_nullable as List, )); } @@ -3906,10 +3903,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( bool enable, String device, @JsonKey(name: 'auto-route') bool autoRoute, TunStack stack, @JsonKey(name: 'dns-hijack') List dnsHijack, @JsonKey(name: 'route-address') List routeAddress, @JsonKey(fromJson: _mtuFromJson) int mtu, @JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String congestionController, @JsonKey(name: 'strict-route') bool strictRoute, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( bool enable, String device, TunStack stack, @JsonKey(name: 'route-address') List routeAddress, @JsonKey(fromJson: _mtuFromJson) int mtu, @JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String congestionController, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _Tun() when $default != null: -return $default(_that.enable,_that.device,_that.autoRoute,_that.stack,_that.dnsHijack,_that.routeAddress,_that.mtu,_that.congestionController,_that.strictRoute,_that.routeExcludeAddress);case _: +return $default(_that.enable,_that.device,_that.stack,_that.routeAddress,_that.mtu,_that.congestionController,_that.routeExcludeAddress);case _: return orElse(); } @@ -3927,10 +3924,10 @@ return $default(_that.enable,_that.device,_that.autoRoute,_that.stack,_that.dnsH /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( bool enable, String device, @JsonKey(name: 'auto-route') bool autoRoute, TunStack stack, @JsonKey(name: 'dns-hijack') List dnsHijack, @JsonKey(name: 'route-address') List routeAddress, @JsonKey(fromJson: _mtuFromJson) int mtu, @JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String congestionController, @JsonKey(name: 'strict-route') bool strictRoute, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( bool enable, String device, TunStack stack, @JsonKey(name: 'route-address') List routeAddress, @JsonKey(fromJson: _mtuFromJson) int mtu, @JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String congestionController, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress) $default,) {final _that = this; switch (_that) { case _Tun(): -return $default(_that.enable,_that.device,_that.autoRoute,_that.stack,_that.dnsHijack,_that.routeAddress,_that.mtu,_that.congestionController,_that.strictRoute,_that.routeExcludeAddress);case _: +return $default(_that.enable,_that.device,_that.stack,_that.routeAddress,_that.mtu,_that.congestionController,_that.routeExcludeAddress);case _: throw StateError('Unexpected subclass'); } @@ -3947,10 +3944,10 @@ return $default(_that.enable,_that.device,_that.autoRoute,_that.stack,_that.dnsH /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool enable, String device, @JsonKey(name: 'auto-route') bool autoRoute, TunStack stack, @JsonKey(name: 'dns-hijack') List dnsHijack, @JsonKey(name: 'route-address') List routeAddress, @JsonKey(fromJson: _mtuFromJson) int mtu, @JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String congestionController, @JsonKey(name: 'strict-route') bool strictRoute, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( bool enable, String device, TunStack stack, @JsonKey(name: 'route-address') List routeAddress, @JsonKey(fromJson: _mtuFromJson) int mtu, @JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String congestionController, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress)? $default,) {final _that = this; switch (_that) { case _Tun() when $default != null: -return $default(_that.enable,_that.device,_that.autoRoute,_that.stack,_that.dnsHijack,_that.routeAddress,_that.mtu,_that.congestionController,_that.strictRoute,_that.routeExcludeAddress);case _: +return $default(_that.enable,_that.device,_that.stack,_that.routeAddress,_that.mtu,_that.congestionController,_that.routeExcludeAddress);case _: return null; } @@ -3962,20 +3959,12 @@ return $default(_that.enable,_that.device,_that.autoRoute,_that.stack,_that.dnsH @JsonSerializable() class _Tun implements Tun { - const _Tun({this.enable = false, this.device = appName, @JsonKey(name: 'auto-route') this.autoRoute = false, this.stack = TunStack.mips, @JsonKey(name: 'dns-hijack') List dnsHijack = const ['any:53'], @JsonKey(name: 'route-address') List routeAddress = const [], @JsonKey(fromJson: _mtuFromJson) this.mtu = defaultTunMtu, @JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) this.congestionController = defaultCongestionController, @JsonKey(name: 'strict-route') this.strictRoute = false, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress = const []}): _dnsHijack = dnsHijack,_routeAddress = routeAddress,_routeExcludeAddress = routeExcludeAddress; + const _Tun({this.enable = false, this.device = appName, this.stack = TunStack.mips, @JsonKey(name: 'route-address') List routeAddress = const [], @JsonKey(fromJson: _mtuFromJson) this.mtu = defaultTunMtu, @JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) this.congestionController = defaultCongestionController, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress = const []}): _routeAddress = routeAddress,_routeExcludeAddress = routeExcludeAddress; factory _Tun.fromJson(Map json) => _$TunFromJson(json); @override@JsonKey() final bool enable; @override@JsonKey() final String device; -@override@JsonKey(name: 'auto-route') final bool autoRoute; @override@JsonKey() final TunStack stack; - final List _dnsHijack; -@override@JsonKey(name: 'dns-hijack') List get dnsHijack { - if (_dnsHijack is EqualUnmodifiableListView) return _dnsHijack; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_dnsHijack); -} - final List _routeAddress; @override@JsonKey(name: 'route-address') List get routeAddress { if (_routeAddress is EqualUnmodifiableListView) return _routeAddress; @@ -3985,7 +3974,6 @@ class _Tun implements Tun { @override@JsonKey(fromJson: _mtuFromJson) final int mtu; @override@JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) final String congestionController; -@override@JsonKey(name: 'strict-route') final bool strictRoute; final List _routeExcludeAddress; @override@JsonKey(name: 'route-exclude-address') List get routeExcludeAddress { if (_routeExcludeAddress is EqualUnmodifiableListView) return _routeExcludeAddress; @@ -4007,18 +3995,18 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _Tun&&(identical(other.enable, enable) || other.enable == enable)&&(identical(other.device, device) || other.device == device)&&(identical(other.autoRoute, autoRoute) || other.autoRoute == autoRoute)&&(identical(other.stack, stack) || other.stack == stack)&&const DeepCollectionEquality().equals(other.dnsHijack, _dnsHijack)&&const DeepCollectionEquality().equals(other.routeAddress, _routeAddress)&&(identical(other.mtu, mtu) || other.mtu == mtu)&&(identical(other.congestionController, congestionController) || other.congestionController == congestionController)&&(identical(other.strictRoute, strictRoute) || other.strictRoute == strictRoute)&&const DeepCollectionEquality().equals(other.routeExcludeAddress, _routeExcludeAddress)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _Tun&&(identical(other.enable, enable) || other.enable == enable)&&(identical(other.device, device) || other.device == device)&&(identical(other.stack, stack) || other.stack == stack)&&const DeepCollectionEquality().equals(other.routeAddress, _routeAddress)&&(identical(other.mtu, mtu) || other.mtu == mtu)&&(identical(other.congestionController, congestionController) || other.congestionController == congestionController)&&const DeepCollectionEquality().equals(other.routeExcludeAddress, _routeExcludeAddress)); } @JsonKey(includeFromJson: false, includeToJson: false) @override int get hashCode { - return Object.hash(runtimeType,enable,device,autoRoute,stack,const DeepCollectionEquality().hash(_dnsHijack),const DeepCollectionEquality().hash(_routeAddress),mtu,congestionController,strictRoute,const DeepCollectionEquality().hash(_routeExcludeAddress)); + return Object.hash(runtimeType,enable,device,stack,const DeepCollectionEquality().hash(_routeAddress),mtu,congestionController,const DeepCollectionEquality().hash(_routeExcludeAddress)); } @override String toString() { - return 'Tun(enable: $enable, device: $device, autoRoute: $autoRoute, stack: $stack, dnsHijack: $dnsHijack, routeAddress: $routeAddress, mtu: $mtu, congestionController: $congestionController, strictRoute: $strictRoute, routeExcludeAddress: $routeExcludeAddress)'; + return 'Tun(enable: $enable, device: $device, stack: $stack, routeAddress: $routeAddress, mtu: $mtu, congestionController: $congestionController, routeExcludeAddress: $routeExcludeAddress)'; } @@ -4029,7 +4017,7 @@ abstract mixin class _$TunCopyWith<$Res> implements $TunCopyWith<$Res> { factory _$TunCopyWith(_Tun value, $Res Function(_Tun) _then) = __$TunCopyWithImpl; @override @useResult $Res call({ - bool enable, String device,@JsonKey(name: 'auto-route') bool autoRoute, TunStack stack,@JsonKey(name: 'dns-hijack') List dnsHijack,@JsonKey(name: 'route-address') List routeAddress,@JsonKey(fromJson: _mtuFromJson) int mtu,@JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String congestionController,@JsonKey(name: 'strict-route') bool strictRoute,@JsonKey(name: 'route-exclude-address') List routeExcludeAddress + bool enable, String device, TunStack stack,@JsonKey(name: 'route-address') List routeAddress,@JsonKey(fromJson: _mtuFromJson) int mtu,@JsonKey(name: 'congestion-controller', fromJson: _congestionControllerFromJson) String congestionController,@JsonKey(name: 'route-exclude-address') List routeExcludeAddress }); @@ -4046,18 +4034,15 @@ class __$TunCopyWithImpl<$Res> /// Create a copy of Tun /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? enable = null,Object? device = null,Object? autoRoute = null,Object? stack = null,Object? dnsHijack = null,Object? routeAddress = null,Object? mtu = null,Object? congestionController = null,Object? strictRoute = null,Object? routeExcludeAddress = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? enable = null,Object? device = null,Object? stack = null,Object? routeAddress = null,Object? mtu = null,Object? congestionController = null,Object? routeExcludeAddress = null,}) { return _then(_Tun( enable: null == enable ? _self.enable : enable // ignore: cast_nullable_to_non_nullable as bool,device: null == device ? _self.device : device // ignore: cast_nullable_to_non_nullable -as String,autoRoute: null == autoRoute ? _self.autoRoute : autoRoute // ignore: cast_nullable_to_non_nullable -as bool,stack: null == stack ? _self.stack : stack // ignore: cast_nullable_to_non_nullable -as TunStack,dnsHijack: null == dnsHijack ? _self._dnsHijack : dnsHijack // ignore: cast_nullable_to_non_nullable -as List,routeAddress: null == routeAddress ? _self._routeAddress : routeAddress // ignore: cast_nullable_to_non_nullable +as String,stack: null == stack ? _self.stack : stack // ignore: cast_nullable_to_non_nullable +as TunStack,routeAddress: null == routeAddress ? _self._routeAddress : routeAddress // ignore: cast_nullable_to_non_nullable as List,mtu: null == mtu ? _self.mtu : mtu // ignore: cast_nullable_to_non_nullable as int,congestionController: null == congestionController ? _self.congestionController : congestionController // ignore: cast_nullable_to_non_nullable -as String,strictRoute: null == strictRoute ? _self.strictRoute : strictRoute // ignore: cast_nullable_to_non_nullable -as bool,routeExcludeAddress: null == routeExcludeAddress ? _self._routeExcludeAddress : routeExcludeAddress // ignore: cast_nullable_to_non_nullable +as String,routeExcludeAddress: null == routeExcludeAddress ? _self._routeExcludeAddress : routeExcludeAddress // ignore: cast_nullable_to_non_nullable as List, )); } @@ -5068,7 +5053,7 @@ as bool, /// @nodoc mixin _$ProfileTun { -@JsonKey(name: 'disable-icmp-forwarding') bool get disableIcmpForwarding;@JsonKey(name: 'exclude-interface') List get excludeInterface; + int get mtu;@JsonKey(name: 'congestion-controller') String get congestionController;@JsonKey(name: 'strict-route') bool get strictRoute;@JsonKey(name: 'route-address') List get routeAddress;@JsonKey(name: 'route-exclude-address') List get routeExcludeAddress;@JsonKey(name: 'dns-hijack') List get dnsHijack;@JsonKey(name: 'udp-timeout') int get udpTimeout;@JsonKey(name: 'disable-icmp-forwarding') bool get disableIcmpForwarding; bool get gso;@JsonKey(name: 'include-interface') List get includeInterface;@JsonKey(name: 'exclude-interface') List get excludeInterface;@JsonKey(name: 'include-uid') List get includeUid;@JsonKey(name: 'exclude-uid') List get excludeUid;@JsonKey(name: 'exclude-src-port') List get excludeSrcPort;@JsonKey(name: 'exclude-dst-port') List get excludeDstPort; /// Create a copy of ProfileTun /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -5082,20 +5067,20 @@ $ProfileTunCopyWith get copyWith => _$ProfileTunCopyWithImpl { factory $ProfileTunCopyWith(ProfileTun value, $Res Function(ProfileTun) _then) = _$ProfileTunCopyWithImpl; @useResult $Res call({ -@JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding,@JsonKey(name: 'exclude-interface') List excludeInterface + int mtu,@JsonKey(name: 'congestion-controller') String congestionController,@JsonKey(name: 'strict-route') bool strictRoute,@JsonKey(name: 'route-address') List routeAddress,@JsonKey(name: 'route-exclude-address') List routeExcludeAddress,@JsonKey(name: 'dns-hijack') List dnsHijack,@JsonKey(name: 'udp-timeout') int udpTimeout,@JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding, bool gso,@JsonKey(name: 'include-interface') List includeInterface,@JsonKey(name: 'exclude-interface') List excludeInterface,@JsonKey(name: 'include-uid') List includeUid,@JsonKey(name: 'exclude-uid') List excludeUid,@JsonKey(name: 'exclude-src-port') List excludeSrcPort,@JsonKey(name: 'exclude-dst-port') List excludeDstPort }); @@ -5123,11 +5108,24 @@ class _$ProfileTunCopyWithImpl<$Res> /// Create a copy of ProfileTun /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? disableIcmpForwarding = null,Object? excludeInterface = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? mtu = null,Object? congestionController = null,Object? strictRoute = null,Object? routeAddress = null,Object? routeExcludeAddress = null,Object? dnsHijack = null,Object? udpTimeout = null,Object? disableIcmpForwarding = null,Object? gso = null,Object? includeInterface = null,Object? excludeInterface = null,Object? includeUid = null,Object? excludeUid = null,Object? excludeSrcPort = null,Object? excludeDstPort = null,}) { return _then(ProfileTun( -disableIcmpForwarding: null == disableIcmpForwarding ? _self.disableIcmpForwarding : disableIcmpForwarding // ignore: cast_nullable_to_non_nullable -as bool,excludeInterface: null == excludeInterface ? _self.excludeInterface : excludeInterface // ignore: cast_nullable_to_non_nullable -as List, +mtu: null == mtu ? _self.mtu : mtu // ignore: cast_nullable_to_non_nullable +as int,congestionController: null == congestionController ? _self.congestionController : congestionController // ignore: cast_nullable_to_non_nullable +as String,strictRoute: null == strictRoute ? _self.strictRoute : strictRoute // ignore: cast_nullable_to_non_nullable +as bool,routeAddress: null == routeAddress ? _self.routeAddress : routeAddress // ignore: cast_nullable_to_non_nullable +as List,routeExcludeAddress: null == routeExcludeAddress ? _self.routeExcludeAddress : routeExcludeAddress // ignore: cast_nullable_to_non_nullable +as List,dnsHijack: null == dnsHijack ? _self.dnsHijack : dnsHijack // ignore: cast_nullable_to_non_nullable +as List,udpTimeout: null == udpTimeout ? _self.udpTimeout : udpTimeout // ignore: cast_nullable_to_non_nullable +as int,disableIcmpForwarding: null == disableIcmpForwarding ? _self.disableIcmpForwarding : disableIcmpForwarding // ignore: cast_nullable_to_non_nullable +as bool,gso: null == gso ? _self.gso : gso // ignore: cast_nullable_to_non_nullable +as bool,includeInterface: null == includeInterface ? _self.includeInterface : includeInterface // ignore: cast_nullable_to_non_nullable +as List,excludeInterface: null == excludeInterface ? _self.excludeInterface : excludeInterface // ignore: cast_nullable_to_non_nullable +as List,includeUid: null == includeUid ? _self.includeUid : includeUid // ignore: cast_nullable_to_non_nullable +as List,excludeUid: null == excludeUid ? _self.excludeUid : excludeUid // ignore: cast_nullable_to_non_nullable +as List,excludeSrcPort: null == excludeSrcPort ? _self.excludeSrcPort : excludeSrcPort // ignore: cast_nullable_to_non_nullable +as List,excludeDstPort: null == excludeDstPort ? _self.excludeDstPort : excludeDstPort // ignore: cast_nullable_to_non_nullable +as List, )); } @@ -5212,10 +5210,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function(@JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding, @JsonKey(name: 'exclude-interface') List excludeInterface)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( int mtu, @JsonKey(name: 'congestion-controller') String congestionController, @JsonKey(name: 'strict-route') bool strictRoute, @JsonKey(name: 'route-address') List routeAddress, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress, @JsonKey(name: 'dns-hijack') List dnsHijack, @JsonKey(name: 'udp-timeout') int udpTimeout, @JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding, bool gso, @JsonKey(name: 'include-interface') List includeInterface, @JsonKey(name: 'exclude-interface') List excludeInterface, @JsonKey(name: 'include-uid') List includeUid, @JsonKey(name: 'exclude-uid') List excludeUid, @JsonKey(name: 'exclude-src-port') List excludeSrcPort, @JsonKey(name: 'exclude-dst-port') List excludeDstPort)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _ProfileTun() when $default != null: -return $default(_that.disableIcmpForwarding,_that.excludeInterface);case _: +return $default(_that.mtu,_that.congestionController,_that.strictRoute,_that.routeAddress,_that.routeExcludeAddress,_that.dnsHijack,_that.udpTimeout,_that.disableIcmpForwarding,_that.gso,_that.includeInterface,_that.excludeInterface,_that.includeUid,_that.excludeUid,_that.excludeSrcPort,_that.excludeDstPort);case _: return orElse(); } @@ -5233,10 +5231,10 @@ return $default(_that.disableIcmpForwarding,_that.excludeInterface);case _: /// } /// ``` -@optionalTypeArgs TResult when(TResult Function(@JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding, @JsonKey(name: 'exclude-interface') List excludeInterface) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( int mtu, @JsonKey(name: 'congestion-controller') String congestionController, @JsonKey(name: 'strict-route') bool strictRoute, @JsonKey(name: 'route-address') List routeAddress, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress, @JsonKey(name: 'dns-hijack') List dnsHijack, @JsonKey(name: 'udp-timeout') int udpTimeout, @JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding, bool gso, @JsonKey(name: 'include-interface') List includeInterface, @JsonKey(name: 'exclude-interface') List excludeInterface, @JsonKey(name: 'include-uid') List includeUid, @JsonKey(name: 'exclude-uid') List excludeUid, @JsonKey(name: 'exclude-src-port') List excludeSrcPort, @JsonKey(name: 'exclude-dst-port') List excludeDstPort) $default,) {final _that = this; switch (_that) { case _ProfileTun(): -return $default(_that.disableIcmpForwarding,_that.excludeInterface);case _: +return $default(_that.mtu,_that.congestionController,_that.strictRoute,_that.routeAddress,_that.routeExcludeAddress,_that.dnsHijack,_that.udpTimeout,_that.disableIcmpForwarding,_that.gso,_that.includeInterface,_that.excludeInterface,_that.includeUid,_that.excludeUid,_that.excludeSrcPort,_that.excludeDstPort);case _: throw StateError('Unexpected subclass'); } @@ -5253,10 +5251,10 @@ return $default(_that.disableIcmpForwarding,_that.excludeInterface);case _: /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function(@JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding, @JsonKey(name: 'exclude-interface') List excludeInterface)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int mtu, @JsonKey(name: 'congestion-controller') String congestionController, @JsonKey(name: 'strict-route') bool strictRoute, @JsonKey(name: 'route-address') List routeAddress, @JsonKey(name: 'route-exclude-address') List routeExcludeAddress, @JsonKey(name: 'dns-hijack') List dnsHijack, @JsonKey(name: 'udp-timeout') int udpTimeout, @JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding, bool gso, @JsonKey(name: 'include-interface') List includeInterface, @JsonKey(name: 'exclude-interface') List excludeInterface, @JsonKey(name: 'include-uid') List includeUid, @JsonKey(name: 'exclude-uid') List excludeUid, @JsonKey(name: 'exclude-src-port') List excludeSrcPort, @JsonKey(name: 'exclude-dst-port') List excludeDstPort)? $default,) {final _that = this; switch (_that) { case _ProfileTun() when $default != null: -return $default(_that.disableIcmpForwarding,_that.excludeInterface);case _: +return $default(_that.mtu,_that.congestionController,_that.strictRoute,_that.routeAddress,_that.routeExcludeAddress,_that.dnsHijack,_that.udpTimeout,_that.disableIcmpForwarding,_that.gso,_that.includeInterface,_that.excludeInterface,_that.includeUid,_that.excludeUid,_that.excludeSrcPort,_that.excludeDstPort);case _: return null; } @@ -5268,10 +5266,43 @@ return $default(_that.disableIcmpForwarding,_that.excludeInterface);case _: @JsonSerializable() class _ProfileTun implements ProfileTun { - const _ProfileTun({@JsonKey(name: 'disable-icmp-forwarding') this.disableIcmpForwarding = false, @JsonKey(name: 'exclude-interface') List excludeInterface = const []}): _excludeInterface = excludeInterface; + const _ProfileTun({this.mtu = defaultTunMtu, @JsonKey(name: 'congestion-controller') this.congestionController = defaultCongestionController, @JsonKey(name: 'strict-route') this.strictRoute = false, @JsonKey(name: 'route-address') List routeAddress = const [], @JsonKey(name: 'route-exclude-address') List routeExcludeAddress = const [], @JsonKey(name: 'dns-hijack') List dnsHijack = defaultDnsHijack, @JsonKey(name: 'udp-timeout') this.udpTimeout = defaultTunUdpTimeout, @JsonKey(name: 'disable-icmp-forwarding') this.disableIcmpForwarding = false, this.gso = false, @JsonKey(name: 'include-interface') List includeInterface = const [], @JsonKey(name: 'exclude-interface') List excludeInterface = const [], @JsonKey(name: 'include-uid') List includeUid = const [], @JsonKey(name: 'exclude-uid') List excludeUid = const [], @JsonKey(name: 'exclude-src-port') List excludeSrcPort = const [], @JsonKey(name: 'exclude-dst-port') List excludeDstPort = const []}): _routeAddress = routeAddress,_routeExcludeAddress = routeExcludeAddress,_dnsHijack = dnsHijack,_includeInterface = includeInterface,_excludeInterface = excludeInterface,_includeUid = includeUid,_excludeUid = excludeUid,_excludeSrcPort = excludeSrcPort,_excludeDstPort = excludeDstPort; factory _ProfileTun.fromJson(Map json) => _$ProfileTunFromJson(json); +@override@JsonKey() final int mtu; +@override@JsonKey(name: 'congestion-controller') final String congestionController; +@override@JsonKey(name: 'strict-route') final bool strictRoute; + final List _routeAddress; +@override@JsonKey(name: 'route-address') List get routeAddress { + if (_routeAddress is EqualUnmodifiableListView) return _routeAddress; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_routeAddress); +} + + final List _routeExcludeAddress; +@override@JsonKey(name: 'route-exclude-address') List get routeExcludeAddress { + if (_routeExcludeAddress is EqualUnmodifiableListView) return _routeExcludeAddress; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_routeExcludeAddress); +} + + final List _dnsHijack; +@override@JsonKey(name: 'dns-hijack') List get dnsHijack { + if (_dnsHijack is EqualUnmodifiableListView) return _dnsHijack; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_dnsHijack); +} + +@override@JsonKey(name: 'udp-timeout') final int udpTimeout; @override@JsonKey(name: 'disable-icmp-forwarding') final bool disableIcmpForwarding; +@override@JsonKey() final bool gso; + final List _includeInterface; +@override@JsonKey(name: 'include-interface') List get includeInterface { + if (_includeInterface is EqualUnmodifiableListView) return _includeInterface; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_includeInterface); +} + final List _excludeInterface; @override@JsonKey(name: 'exclude-interface') List get excludeInterface { if (_excludeInterface is EqualUnmodifiableListView) return _excludeInterface; @@ -5279,6 +5310,34 @@ class _ProfileTun implements ProfileTun { return EqualUnmodifiableListView(_excludeInterface); } + final List _includeUid; +@override@JsonKey(name: 'include-uid') List get includeUid { + if (_includeUid is EqualUnmodifiableListView) return _includeUid; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_includeUid); +} + + final List _excludeUid; +@override@JsonKey(name: 'exclude-uid') List get excludeUid { + if (_excludeUid is EqualUnmodifiableListView) return _excludeUid; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_excludeUid); +} + + final List _excludeSrcPort; +@override@JsonKey(name: 'exclude-src-port') List get excludeSrcPort { + if (_excludeSrcPort is EqualUnmodifiableListView) return _excludeSrcPort; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_excludeSrcPort); +} + + final List _excludeDstPort; +@override@JsonKey(name: 'exclude-dst-port') List get excludeDstPort { + if (_excludeDstPort is EqualUnmodifiableListView) return _excludeDstPort; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(_excludeDstPort); +} + /// Create a copy of ProfileTun /// with the given fields replaced by the non-null parameter values. @@ -5293,18 +5352,18 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _ProfileTun&&(identical(other.disableIcmpForwarding, disableIcmpForwarding) || other.disableIcmpForwarding == disableIcmpForwarding)&&const DeepCollectionEquality().equals(other.excludeInterface, _excludeInterface)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ProfileTun&&(identical(other.mtu, mtu) || other.mtu == mtu)&&(identical(other.congestionController, congestionController) || other.congestionController == congestionController)&&(identical(other.strictRoute, strictRoute) || other.strictRoute == strictRoute)&&const DeepCollectionEquality().equals(other.routeAddress, _routeAddress)&&const DeepCollectionEquality().equals(other.routeExcludeAddress, _routeExcludeAddress)&&const DeepCollectionEquality().equals(other.dnsHijack, _dnsHijack)&&(identical(other.udpTimeout, udpTimeout) || other.udpTimeout == udpTimeout)&&(identical(other.disableIcmpForwarding, disableIcmpForwarding) || other.disableIcmpForwarding == disableIcmpForwarding)&&(identical(other.gso, gso) || other.gso == gso)&&const DeepCollectionEquality().equals(other.includeInterface, _includeInterface)&&const DeepCollectionEquality().equals(other.excludeInterface, _excludeInterface)&&const DeepCollectionEquality().equals(other.includeUid, _includeUid)&&const DeepCollectionEquality().equals(other.excludeUid, _excludeUid)&&const DeepCollectionEquality().equals(other.excludeSrcPort, _excludeSrcPort)&&const DeepCollectionEquality().equals(other.excludeDstPort, _excludeDstPort)); } @JsonKey(includeFromJson: false, includeToJson: false) @override int get hashCode { - return Object.hash(runtimeType,disableIcmpForwarding,const DeepCollectionEquality().hash(_excludeInterface)); + return Object.hash(runtimeType,mtu,congestionController,strictRoute,const DeepCollectionEquality().hash(_routeAddress),const DeepCollectionEquality().hash(_routeExcludeAddress),const DeepCollectionEquality().hash(_dnsHijack),udpTimeout,disableIcmpForwarding,gso,const DeepCollectionEquality().hash(_includeInterface),const DeepCollectionEquality().hash(_excludeInterface),const DeepCollectionEquality().hash(_includeUid),const DeepCollectionEquality().hash(_excludeUid),const DeepCollectionEquality().hash(_excludeSrcPort),const DeepCollectionEquality().hash(_excludeDstPort)); } @override String toString() { - return 'ProfileTun(disableIcmpForwarding: $disableIcmpForwarding, excludeInterface: $excludeInterface)'; + return 'ProfileTun(mtu: $mtu, congestionController: $congestionController, strictRoute: $strictRoute, routeAddress: $routeAddress, routeExcludeAddress: $routeExcludeAddress, dnsHijack: $dnsHijack, udpTimeout: $udpTimeout, disableIcmpForwarding: $disableIcmpForwarding, gso: $gso, includeInterface: $includeInterface, excludeInterface: $excludeInterface, includeUid: $includeUid, excludeUid: $excludeUid, excludeSrcPort: $excludeSrcPort, excludeDstPort: $excludeDstPort)'; } @@ -5315,7 +5374,7 @@ abstract mixin class _$ProfileTunCopyWith<$Res> implements $ProfileTunCopyWith<$ factory _$ProfileTunCopyWith(_ProfileTun value, $Res Function(_ProfileTun) _then) = __$ProfileTunCopyWithImpl; @override @useResult $Res call({ -@JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding,@JsonKey(name: 'exclude-interface') List excludeInterface + int mtu,@JsonKey(name: 'congestion-controller') String congestionController,@JsonKey(name: 'strict-route') bool strictRoute,@JsonKey(name: 'route-address') List routeAddress,@JsonKey(name: 'route-exclude-address') List routeExcludeAddress,@JsonKey(name: 'dns-hijack') List dnsHijack,@JsonKey(name: 'udp-timeout') int udpTimeout,@JsonKey(name: 'disable-icmp-forwarding') bool disableIcmpForwarding, bool gso,@JsonKey(name: 'include-interface') List includeInterface,@JsonKey(name: 'exclude-interface') List excludeInterface,@JsonKey(name: 'include-uid') List includeUid,@JsonKey(name: 'exclude-uid') List excludeUid,@JsonKey(name: 'exclude-src-port') List excludeSrcPort,@JsonKey(name: 'exclude-dst-port') List excludeDstPort }); @@ -5332,11 +5391,24 @@ class __$ProfileTunCopyWithImpl<$Res> /// Create a copy of ProfileTun /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? disableIcmpForwarding = null,Object? excludeInterface = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? mtu = null,Object? congestionController = null,Object? strictRoute = null,Object? routeAddress = null,Object? routeExcludeAddress = null,Object? dnsHijack = null,Object? udpTimeout = null,Object? disableIcmpForwarding = null,Object? gso = null,Object? includeInterface = null,Object? excludeInterface = null,Object? includeUid = null,Object? excludeUid = null,Object? excludeSrcPort = null,Object? excludeDstPort = null,}) { return _then(_ProfileTun( -disableIcmpForwarding: null == disableIcmpForwarding ? _self.disableIcmpForwarding : disableIcmpForwarding // ignore: cast_nullable_to_non_nullable -as bool,excludeInterface: null == excludeInterface ? _self._excludeInterface : excludeInterface // ignore: cast_nullable_to_non_nullable -as List, +mtu: null == mtu ? _self.mtu : mtu // ignore: cast_nullable_to_non_nullable +as int,congestionController: null == congestionController ? _self.congestionController : congestionController // ignore: cast_nullable_to_non_nullable +as String,strictRoute: null == strictRoute ? _self.strictRoute : strictRoute // ignore: cast_nullable_to_non_nullable +as bool,routeAddress: null == routeAddress ? _self._routeAddress : routeAddress // ignore: cast_nullable_to_non_nullable +as List,routeExcludeAddress: null == routeExcludeAddress ? _self._routeExcludeAddress : routeExcludeAddress // ignore: cast_nullable_to_non_nullable +as List,dnsHijack: null == dnsHijack ? _self._dnsHijack : dnsHijack // ignore: cast_nullable_to_non_nullable +as List,udpTimeout: null == udpTimeout ? _self.udpTimeout : udpTimeout // ignore: cast_nullable_to_non_nullable +as int,disableIcmpForwarding: null == disableIcmpForwarding ? _self.disableIcmpForwarding : disableIcmpForwarding // ignore: cast_nullable_to_non_nullable +as bool,gso: null == gso ? _self.gso : gso // ignore: cast_nullable_to_non_nullable +as bool,includeInterface: null == includeInterface ? _self._includeInterface : includeInterface // ignore: cast_nullable_to_non_nullable +as List,excludeInterface: null == excludeInterface ? _self._excludeInterface : excludeInterface // ignore: cast_nullable_to_non_nullable +as List,includeUid: null == includeUid ? _self._includeUid : includeUid // ignore: cast_nullable_to_non_nullable +as List,excludeUid: null == excludeUid ? _self._excludeUid : excludeUid // ignore: cast_nullable_to_non_nullable +as List,excludeSrcPort: null == excludeSrcPort ? _self._excludeSrcPort : excludeSrcPort // ignore: cast_nullable_to_non_nullable +as List,excludeDstPort: null == excludeDstPort ? _self._excludeDstPort : excludeDstPort // ignore: cast_nullable_to_non_nullable +as List, )); } @@ -7257,7 +7329,7 @@ as List, /// @nodoc mixin _$PatchClashConfig { -@JsonKey(name: 'mixed-port') int get mixedPort;@JsonKey(name: 'socks-port') int get socksPort;@JsonKey(name: 'port') int get port;@JsonKey(name: 'redir-port') int get redirPort;@JsonKey(name: 'tproxy-port') int get tproxyPort; Mode get mode;@JsonKey(name: 'allow-lan') bool get allowLan;@JsonKey(name: 'log-level') LogLevel get logLevel; bool get ipv6;@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode get findProcessMode;@JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode get interfaceNameMode;@JsonKey(name: 'interface-name') String get interfaceName;@JsonKey(name: 'keep-alive-interval') int get keepAliveInterval;@JsonKey(name: 'keep-alive-idle') int get keepAliveIdle;@JsonKey(name: 'disable-keep-alive') bool get disableKeepAlive;@JsonKey(name: 'routing-mark') int get routingMark;@JsonKey(name: 'unified-delay') bool get unifiedDelay;@JsonKey(name: 'tcp-concurrent') bool get tcpConcurrent;@JsonKey(fromJson: Tun.safeFormJson) Tun get tun;@JsonKey(fromJson: Dns.safeDnsFromJson) Dns get dns;@JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set get dnsOverrideKeys;@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map get geoXUrl;@JsonKey(name: 'geodata-loader') GeodataLoader get geodataLoader;@JsonKey(name: 'global-ua') String? get globalUa;@JsonKey(name: 'external-controller') ExternalControllerStatus get externalController; String get secret; Map get hosts;@JsonKey(name: 'geo-auto-update') bool get geoAutoUpdate;@JsonKey(name: 'geo-update-interval') int get geoUpdateInterval; +@JsonKey(name: 'mixed-port') int get mixedPort;@JsonKey(name: 'socks-port') int get socksPort;@JsonKey(name: 'port') int get port;@JsonKey(name: 'redir-port') int get redirPort;@JsonKey(name: 'tproxy-port') int get tproxyPort; Mode get mode;@JsonKey(name: 'allow-lan') bool get allowLan;@JsonKey(name: 'log-level') LogLevel get logLevel; bool get ipv6;@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode get findProcessMode;@JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode get interfaceNameMode;@JsonKey(name: 'interface-name') String get interfaceName;@JsonKey(name: 'keep-alive-interval') int get keepAliveInterval;@JsonKey(name: 'keep-alive-idle') int get keepAliveIdle;@JsonKey(name: 'disable-keep-alive') bool get disableKeepAlive;@JsonKey(name: 'routing-mark') int get routingMark;@JsonKey(name: 'unified-delay') bool get unifiedDelay;@JsonKey(name: 'tcp-concurrent') bool get tcpConcurrent;@JsonKey(fromJson: Tun.safeFormJson) Tun get tun;@JsonKey(fromJson: Dns.safeDnsFromJson) Dns get dns;@JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set get dnsOverrideKeys;@JsonKey(name: 'tun-override', fromJson: ProfileTun.safeFromJson) ProfileTun get tunOverride;@JsonKey(name: _tunOverrideKeysJsonKey, fromJson: _tunOverrideKeysFromJson) Set get tunOverrideKeys;@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map get geoXUrl;@JsonKey(name: 'geodata-loader') GeodataLoader get geodataLoader;@JsonKey(name: 'global-ua') String? get globalUa;@JsonKey(name: 'external-controller') ExternalControllerStatus get externalController; String get secret; Map get hosts;@JsonKey(name: 'geo-auto-update') bool get geoAutoUpdate;@JsonKey(name: 'geo-update-interval') int get geoUpdateInterval; /// Create a copy of PatchClashConfig /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -7271,20 +7343,20 @@ $PatchClashConfigCopyWith get copyWith => _$PatchClashConfigCo @override bool operator ==(Object other) { final _this = this as PatchClashConfig; - return identical(this, other) || (other.runtimeType == runtimeType&&other is PatchClashConfig&&(identical(other.mixedPort, _this.mixedPort) || other.mixedPort == _this.mixedPort)&&(identical(other.socksPort, _this.socksPort) || other.socksPort == _this.socksPort)&&(identical(other.port, _this.port) || other.port == _this.port)&&(identical(other.redirPort, _this.redirPort) || other.redirPort == _this.redirPort)&&(identical(other.tproxyPort, _this.tproxyPort) || other.tproxyPort == _this.tproxyPort)&&(identical(other.mode, _this.mode) || other.mode == _this.mode)&&(identical(other.allowLan, _this.allowLan) || other.allowLan == _this.allowLan)&&(identical(other.logLevel, _this.logLevel) || other.logLevel == _this.logLevel)&&(identical(other.ipv6, _this.ipv6) || other.ipv6 == _this.ipv6)&&(identical(other.findProcessMode, _this.findProcessMode) || other.findProcessMode == _this.findProcessMode)&&(identical(other.interfaceNameMode, _this.interfaceNameMode) || other.interfaceNameMode == _this.interfaceNameMode)&&(identical(other.interfaceName, _this.interfaceName) || other.interfaceName == _this.interfaceName)&&(identical(other.keepAliveInterval, _this.keepAliveInterval) || other.keepAliveInterval == _this.keepAliveInterval)&&(identical(other.keepAliveIdle, _this.keepAliveIdle) || other.keepAliveIdle == _this.keepAliveIdle)&&(identical(other.disableKeepAlive, _this.disableKeepAlive) || other.disableKeepAlive == _this.disableKeepAlive)&&(identical(other.routingMark, _this.routingMark) || other.routingMark == _this.routingMark)&&(identical(other.unifiedDelay, _this.unifiedDelay) || other.unifiedDelay == _this.unifiedDelay)&&(identical(other.tcpConcurrent, _this.tcpConcurrent) || other.tcpConcurrent == _this.tcpConcurrent)&&(identical(other.tun, _this.tun) || other.tun == _this.tun)&&(identical(other.dns, _this.dns) || other.dns == _this.dns)&&const DeepCollectionEquality().equals(other.dnsOverrideKeys, _this.dnsOverrideKeys)&&const DeepCollectionEquality().equals(other.geoXUrl, _this.geoXUrl)&&(identical(other.geodataLoader, _this.geodataLoader) || other.geodataLoader == _this.geodataLoader)&&(identical(other.globalUa, _this.globalUa) || other.globalUa == _this.globalUa)&&(identical(other.externalController, _this.externalController) || other.externalController == _this.externalController)&&(identical(other.secret, _this.secret) || other.secret == _this.secret)&&const DeepCollectionEquality().equals(other.hosts, _this.hosts)&&(identical(other.geoAutoUpdate, _this.geoAutoUpdate) || other.geoAutoUpdate == _this.geoAutoUpdate)&&(identical(other.geoUpdateInterval, _this.geoUpdateInterval) || other.geoUpdateInterval == _this.geoUpdateInterval)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is PatchClashConfig&&(identical(other.mixedPort, _this.mixedPort) || other.mixedPort == _this.mixedPort)&&(identical(other.socksPort, _this.socksPort) || other.socksPort == _this.socksPort)&&(identical(other.port, _this.port) || other.port == _this.port)&&(identical(other.redirPort, _this.redirPort) || other.redirPort == _this.redirPort)&&(identical(other.tproxyPort, _this.tproxyPort) || other.tproxyPort == _this.tproxyPort)&&(identical(other.mode, _this.mode) || other.mode == _this.mode)&&(identical(other.allowLan, _this.allowLan) || other.allowLan == _this.allowLan)&&(identical(other.logLevel, _this.logLevel) || other.logLevel == _this.logLevel)&&(identical(other.ipv6, _this.ipv6) || other.ipv6 == _this.ipv6)&&(identical(other.findProcessMode, _this.findProcessMode) || other.findProcessMode == _this.findProcessMode)&&(identical(other.interfaceNameMode, _this.interfaceNameMode) || other.interfaceNameMode == _this.interfaceNameMode)&&(identical(other.interfaceName, _this.interfaceName) || other.interfaceName == _this.interfaceName)&&(identical(other.keepAliveInterval, _this.keepAliveInterval) || other.keepAliveInterval == _this.keepAliveInterval)&&(identical(other.keepAliveIdle, _this.keepAliveIdle) || other.keepAliveIdle == _this.keepAliveIdle)&&(identical(other.disableKeepAlive, _this.disableKeepAlive) || other.disableKeepAlive == _this.disableKeepAlive)&&(identical(other.routingMark, _this.routingMark) || other.routingMark == _this.routingMark)&&(identical(other.unifiedDelay, _this.unifiedDelay) || other.unifiedDelay == _this.unifiedDelay)&&(identical(other.tcpConcurrent, _this.tcpConcurrent) || other.tcpConcurrent == _this.tcpConcurrent)&&(identical(other.tun, _this.tun) || other.tun == _this.tun)&&(identical(other.dns, _this.dns) || other.dns == _this.dns)&&const DeepCollectionEquality().equals(other.dnsOverrideKeys, _this.dnsOverrideKeys)&&(identical(other.tunOverride, _this.tunOverride) || other.tunOverride == _this.tunOverride)&&const DeepCollectionEquality().equals(other.tunOverrideKeys, _this.tunOverrideKeys)&&const DeepCollectionEquality().equals(other.geoXUrl, _this.geoXUrl)&&(identical(other.geodataLoader, _this.geodataLoader) || other.geodataLoader == _this.geodataLoader)&&(identical(other.globalUa, _this.globalUa) || other.globalUa == _this.globalUa)&&(identical(other.externalController, _this.externalController) || other.externalController == _this.externalController)&&(identical(other.secret, _this.secret) || other.secret == _this.secret)&&const DeepCollectionEquality().equals(other.hosts, _this.hosts)&&(identical(other.geoAutoUpdate, _this.geoAutoUpdate) || other.geoAutoUpdate == _this.geoAutoUpdate)&&(identical(other.geoUpdateInterval, _this.geoUpdateInterval) || other.geoUpdateInterval == _this.geoUpdateInterval)); } @JsonKey(includeFromJson: false, includeToJson: false) @override int get hashCode { final _this = this as PatchClashConfig; - return Object.hashAll([runtimeType,_this.mixedPort,_this.socksPort,_this.port,_this.redirPort,_this.tproxyPort,_this.mode,_this.allowLan,_this.logLevel,_this.ipv6,_this.findProcessMode,_this.interfaceNameMode,_this.interfaceName,_this.keepAliveInterval,_this.keepAliveIdle,_this.disableKeepAlive,_this.routingMark,_this.unifiedDelay,_this.tcpConcurrent,_this.tun,_this.dns,const DeepCollectionEquality().hash(_this.dnsOverrideKeys),const DeepCollectionEquality().hash(_this.geoXUrl),_this.geodataLoader,_this.globalUa,_this.externalController,_this.secret,const DeepCollectionEquality().hash(_this.hosts),_this.geoAutoUpdate,_this.geoUpdateInterval]); + return Object.hashAll([runtimeType,_this.mixedPort,_this.socksPort,_this.port,_this.redirPort,_this.tproxyPort,_this.mode,_this.allowLan,_this.logLevel,_this.ipv6,_this.findProcessMode,_this.interfaceNameMode,_this.interfaceName,_this.keepAliveInterval,_this.keepAliveIdle,_this.disableKeepAlive,_this.routingMark,_this.unifiedDelay,_this.tcpConcurrent,_this.tun,_this.dns,const DeepCollectionEquality().hash(_this.dnsOverrideKeys),_this.tunOverride,const DeepCollectionEquality().hash(_this.tunOverrideKeys),const DeepCollectionEquality().hash(_this.geoXUrl),_this.geodataLoader,_this.globalUa,_this.externalController,_this.secret,const DeepCollectionEquality().hash(_this.hosts),_this.geoAutoUpdate,_this.geoUpdateInterval]); } @override String toString() { final _this = this as PatchClashConfig; - return 'PatchClashConfig(mixedPort: ${_this.mixedPort}, socksPort: ${_this.socksPort}, port: ${_this.port}, redirPort: ${_this.redirPort}, tproxyPort: ${_this.tproxyPort}, mode: ${_this.mode}, allowLan: ${_this.allowLan}, logLevel: ${_this.logLevel}, ipv6: ${_this.ipv6}, findProcessMode: ${_this.findProcessMode}, interfaceNameMode: ${_this.interfaceNameMode}, interfaceName: ${_this.interfaceName}, keepAliveInterval: ${_this.keepAliveInterval}, keepAliveIdle: ${_this.keepAliveIdle}, disableKeepAlive: ${_this.disableKeepAlive}, routingMark: ${_this.routingMark}, unifiedDelay: ${_this.unifiedDelay}, tcpConcurrent: ${_this.tcpConcurrent}, tun: ${_this.tun}, dns: ${_this.dns}, dnsOverrideKeys: ${_this.dnsOverrideKeys}, geoXUrl: ${_this.geoXUrl}, geodataLoader: ${_this.geodataLoader}, globalUa: ${_this.globalUa}, externalController: ${_this.externalController}, secret: ${_this.secret}, hosts: ${_this.hosts}, geoAutoUpdate: ${_this.geoAutoUpdate}, geoUpdateInterval: ${_this.geoUpdateInterval})'; + return 'PatchClashConfig(mixedPort: ${_this.mixedPort}, socksPort: ${_this.socksPort}, port: ${_this.port}, redirPort: ${_this.redirPort}, tproxyPort: ${_this.tproxyPort}, mode: ${_this.mode}, allowLan: ${_this.allowLan}, logLevel: ${_this.logLevel}, ipv6: ${_this.ipv6}, findProcessMode: ${_this.findProcessMode}, interfaceNameMode: ${_this.interfaceNameMode}, interfaceName: ${_this.interfaceName}, keepAliveInterval: ${_this.keepAliveInterval}, keepAliveIdle: ${_this.keepAliveIdle}, disableKeepAlive: ${_this.disableKeepAlive}, routingMark: ${_this.routingMark}, unifiedDelay: ${_this.unifiedDelay}, tcpConcurrent: ${_this.tcpConcurrent}, tun: ${_this.tun}, dns: ${_this.dns}, dnsOverrideKeys: ${_this.dnsOverrideKeys}, tunOverride: ${_this.tunOverride}, tunOverrideKeys: ${_this.tunOverrideKeys}, geoXUrl: ${_this.geoXUrl}, geodataLoader: ${_this.geodataLoader}, globalUa: ${_this.globalUa}, externalController: ${_this.externalController}, secret: ${_this.secret}, hosts: ${_this.hosts}, geoAutoUpdate: ${_this.geoAutoUpdate}, geoUpdateInterval: ${_this.geoUpdateInterval})'; } @@ -7295,11 +7367,11 @@ abstract mixin class $PatchClashConfigCopyWith<$Res> { factory $PatchClashConfigCopyWith(PatchClashConfig value, $Res Function(PatchClashConfig) _then) = _$PatchClashConfigCopyWithImpl; @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, bool ipv6,@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode findProcessMode,@JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode interfaceNameMode,@JsonKey(name: 'interface-name') String interfaceName,@JsonKey(name: 'keep-alive-interval') int keepAliveInterval,@JsonKey(name: 'keep-alive-idle') int keepAliveIdle,@JsonKey(name: 'disable-keep-alive') bool disableKeepAlive,@JsonKey(name: 'routing-mark') int routingMark,@JsonKey(name: 'unified-delay') bool unifiedDelay,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(fromJson: Tun.safeFormJson) Tun tun,@JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,@JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys,@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl,@JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader,@JsonKey(name: 'global-ua') String? globalUa,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, Map hosts,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval +@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, bool ipv6,@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode findProcessMode,@JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode interfaceNameMode,@JsonKey(name: 'interface-name') String interfaceName,@JsonKey(name: 'keep-alive-interval') int keepAliveInterval,@JsonKey(name: 'keep-alive-idle') int keepAliveIdle,@JsonKey(name: 'disable-keep-alive') bool disableKeepAlive,@JsonKey(name: 'routing-mark') int routingMark,@JsonKey(name: 'unified-delay') bool unifiedDelay,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(fromJson: Tun.safeFormJson) Tun tun,@JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,@JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys,@JsonKey(name: 'tun-override', fromJson: ProfileTun.safeFromJson) ProfileTun tunOverride,@JsonKey(name: _tunOverrideKeysJsonKey, fromJson: _tunOverrideKeysFromJson) Set tunOverrideKeys,@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl,@JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader,@JsonKey(name: 'global-ua') String? globalUa,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, Map hosts,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval }); -$TunCopyWith<$Res> get tun;$DnsCopyWith<$Res> get dns; +$TunCopyWith<$Res> get tun;$DnsCopyWith<$Res> get dns;$ProfileTunCopyWith<$Res> get tunOverride; } /// @nodoc @@ -7312,7 +7384,7 @@ class _$PatchClashConfigCopyWithImpl<$Res> /// Create a copy of PatchClashConfig /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @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,Object? ipv6 = null,Object? findProcessMode = null,Object? interfaceNameMode = null,Object? interfaceName = null,Object? keepAliveInterval = null,Object? keepAliveIdle = null,Object? disableKeepAlive = null,Object? routingMark = null,Object? unifiedDelay = null,Object? tcpConcurrent = null,Object? tun = null,Object? dns = null,Object? dnsOverrideKeys = null,Object? geoXUrl = null,Object? geodataLoader = null,Object? globalUa = freezed,Object? externalController = null,Object? secret = null,Object? hosts = null,Object? geoAutoUpdate = null,Object? geoUpdateInterval = null,}) { +@pragma('vm:prefer-inline') @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,Object? ipv6 = null,Object? findProcessMode = null,Object? interfaceNameMode = null,Object? interfaceName = null,Object? keepAliveInterval = null,Object? keepAliveIdle = null,Object? disableKeepAlive = null,Object? routingMark = null,Object? unifiedDelay = null,Object? tcpConcurrent = null,Object? tun = null,Object? dns = null,Object? dnsOverrideKeys = null,Object? tunOverride = null,Object? tunOverrideKeys = null,Object? geoXUrl = null,Object? geodataLoader = null,Object? globalUa = freezed,Object? externalController = null,Object? secret = null,Object? hosts = null,Object? geoAutoUpdate = null,Object? geoUpdateInterval = null,}) { return _then(PatchClashConfig( mixedPort: null == mixedPort ? _self.mixedPort : mixedPort // ignore: cast_nullable_to_non_nullable as int,socksPort: null == socksPort ? _self.socksPort : socksPort // ignore: cast_nullable_to_non_nullable @@ -7335,7 +7407,9 @@ as bool,tcpConcurrent: null == tcpConcurrent ? _self.tcpConcurrent : tcpConcurre as bool,tun: null == tun ? _self.tun : tun // ignore: cast_nullable_to_non_nullable as Tun,dns: null == dns ? _self.dns : dns // ignore: cast_nullable_to_non_nullable as Dns,dnsOverrideKeys: null == dnsOverrideKeys ? _self.dnsOverrideKeys : dnsOverrideKeys // ignore: cast_nullable_to_non_nullable -as Set,geoXUrl: null == geoXUrl ? _self.geoXUrl : geoXUrl // ignore: cast_nullable_to_non_nullable +as Set,tunOverride: null == tunOverride ? _self.tunOverride : tunOverride // ignore: cast_nullable_to_non_nullable +as ProfileTun,tunOverrideKeys: null == tunOverrideKeys ? _self.tunOverrideKeys : tunOverrideKeys // ignore: cast_nullable_to_non_nullable +as Set,geoXUrl: null == geoXUrl ? _self.geoXUrl : geoXUrl // ignore: cast_nullable_to_non_nullable as Map,geodataLoader: null == geodataLoader ? _self.geodataLoader : geodataLoader // ignore: cast_nullable_to_non_nullable as GeodataLoader,globalUa: freezed == globalUa ? _self.globalUa : globalUa // ignore: cast_nullable_to_non_nullable as String?,externalController: null == externalController ? _self.externalController : externalController // ignore: cast_nullable_to_non_nullable @@ -7364,6 +7438,15 @@ $DnsCopyWith<$Res> get dns { return $DnsCopyWith<$Res>(_self.dns, (value) { return _then(_self.copyWith(dns: value)); }); +}/// Create a copy of PatchClashConfig +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$ProfileTunCopyWith<$Res> get tunOverride { + + return $ProfileTunCopyWith<$Res>(_self.tunOverride, (value) { + return _then(_self.copyWith(tunOverride: value)); + }); } } @@ -7446,10 +7529,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function(@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, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode findProcessMode, @JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode interfaceNameMode, @JsonKey(name: 'interface-name') String interfaceName, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'keep-alive-idle') int keepAliveIdle, @JsonKey(name: 'disable-keep-alive') bool disableKeepAlive, @JsonKey(name: 'routing-mark') int routingMark, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, Map hosts, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function(@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, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode findProcessMode, @JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode interfaceNameMode, @JsonKey(name: 'interface-name') String interfaceName, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'keep-alive-idle') int keepAliveIdle, @JsonKey(name: 'disable-keep-alive') bool disableKeepAlive, @JsonKey(name: 'routing-mark') int routingMark, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys, @JsonKey(name: 'tun-override', fromJson: ProfileTun.safeFromJson) ProfileTun tunOverride, @JsonKey(name: _tunOverrideKeysJsonKey, fromJson: _tunOverrideKeysFromJson) Set tunOverrideKeys, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, Map hosts, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _PatchClashConfig() when $default != null: -return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.interfaceNameMode,_that.interfaceName,_that.keepAliveInterval,_that.keepAliveIdle,_that.disableKeepAlive,_that.routingMark,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.dnsOverrideKeys,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.secret,_that.hosts,_that.geoAutoUpdate,_that.geoUpdateInterval);case _: +return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.interfaceNameMode,_that.interfaceName,_that.keepAliveInterval,_that.keepAliveIdle,_that.disableKeepAlive,_that.routingMark,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.dnsOverrideKeys,_that.tunOverride,_that.tunOverrideKeys,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.secret,_that.hosts,_that.geoAutoUpdate,_that.geoUpdateInterval);case _: return orElse(); } @@ -7467,10 +7550,10 @@ return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that /// } /// ``` -@optionalTypeArgs TResult when(TResult Function(@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, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode findProcessMode, @JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode interfaceNameMode, @JsonKey(name: 'interface-name') String interfaceName, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'keep-alive-idle') int keepAliveIdle, @JsonKey(name: 'disable-keep-alive') bool disableKeepAlive, @JsonKey(name: 'routing-mark') int routingMark, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, Map hosts, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function(@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, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode findProcessMode, @JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode interfaceNameMode, @JsonKey(name: 'interface-name') String interfaceName, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'keep-alive-idle') int keepAliveIdle, @JsonKey(name: 'disable-keep-alive') bool disableKeepAlive, @JsonKey(name: 'routing-mark') int routingMark, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys, @JsonKey(name: 'tun-override', fromJson: ProfileTun.safeFromJson) ProfileTun tunOverride, @JsonKey(name: _tunOverrideKeysJsonKey, fromJson: _tunOverrideKeysFromJson) Set tunOverrideKeys, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, Map hosts, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval) $default,) {final _that = this; switch (_that) { case _PatchClashConfig(): -return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.interfaceNameMode,_that.interfaceName,_that.keepAliveInterval,_that.keepAliveIdle,_that.disableKeepAlive,_that.routingMark,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.dnsOverrideKeys,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.secret,_that.hosts,_that.geoAutoUpdate,_that.geoUpdateInterval);case _: +return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.interfaceNameMode,_that.interfaceName,_that.keepAliveInterval,_that.keepAliveIdle,_that.disableKeepAlive,_that.routingMark,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.dnsOverrideKeys,_that.tunOverride,_that.tunOverrideKeys,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.secret,_that.hosts,_that.geoAutoUpdate,_that.geoUpdateInterval);case _: throw StateError('Unexpected subclass'); } @@ -7487,10 +7570,10 @@ return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function(@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, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode findProcessMode, @JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode interfaceNameMode, @JsonKey(name: 'interface-name') String interfaceName, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'keep-alive-idle') int keepAliveIdle, @JsonKey(name: 'disable-keep-alive') bool disableKeepAlive, @JsonKey(name: 'routing-mark') int routingMark, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, Map hosts, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function(@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, bool ipv6, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode findProcessMode, @JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode interfaceNameMode, @JsonKey(name: 'interface-name') String interfaceName, @JsonKey(name: 'keep-alive-interval') int keepAliveInterval, @JsonKey(name: 'keep-alive-idle') int keepAliveIdle, @JsonKey(name: 'disable-keep-alive') bool disableKeepAlive, @JsonKey(name: 'routing-mark') int routingMark, @JsonKey(name: 'unified-delay') bool unifiedDelay, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(fromJson: Tun.safeFormJson) Tun tun, @JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns, @JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys, @JsonKey(name: 'tun-override', fromJson: ProfileTun.safeFromJson) ProfileTun tunOverride, @JsonKey(name: _tunOverrideKeysJsonKey, fromJson: _tunOverrideKeysFromJson) Set tunOverrideKeys, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl, @JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader, @JsonKey(name: 'global-ua') String? globalUa, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, Map hosts, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval)? $default,) {final _that = this; switch (_that) { case _PatchClashConfig() when $default != null: -return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.interfaceNameMode,_that.interfaceName,_that.keepAliveInterval,_that.keepAliveIdle,_that.disableKeepAlive,_that.routingMark,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.dnsOverrideKeys,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.secret,_that.hosts,_that.geoAutoUpdate,_that.geoUpdateInterval);case _: +return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that.tproxyPort,_that.mode,_that.allowLan,_that.logLevel,_that.ipv6,_that.findProcessMode,_that.interfaceNameMode,_that.interfaceName,_that.keepAliveInterval,_that.keepAliveIdle,_that.disableKeepAlive,_that.routingMark,_that.unifiedDelay,_that.tcpConcurrent,_that.tun,_that.dns,_that.dnsOverrideKeys,_that.tunOverride,_that.tunOverrideKeys,_that.geoXUrl,_that.geodataLoader,_that.globalUa,_that.externalController,_that.secret,_that.hosts,_that.geoAutoUpdate,_that.geoUpdateInterval);case _: return null; } @@ -7502,7 +7585,7 @@ return $default(_that.mixedPort,_that.socksPort,_that.port,_that.redirPort,_that @JsonSerializable() class _PatchClashConfig implements PatchClashConfig { - const _PatchClashConfig({@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, this.ipv6 = false, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) this.findProcessMode = FindProcessMode.off, @JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) this.interfaceNameMode = InterfaceNameMode.clear, @JsonKey(name: 'interface-name') this.interfaceName = '', @JsonKey(name: 'keep-alive-interval') this.keepAliveInterval = defaultKeepAliveInterval, @JsonKey(name: 'keep-alive-idle') this.keepAliveIdle = 15, @JsonKey(name: 'disable-keep-alive') this.disableKeepAlive = false, @JsonKey(name: 'routing-mark') this.routingMark = 0, @JsonKey(name: 'unified-delay') this.unifiedDelay = true, @JsonKey(name: 'tcp-concurrent') this.tcpConcurrent = true, @JsonKey(fromJson: Tun.safeFormJson) this.tun = defaultTun, @JsonKey(fromJson: Dns.safeDnsFromJson) this.dns = defaultDns, @JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys = const {}, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl = defaultGeoXUrl, @JsonKey(name: 'geodata-loader') this.geodataLoader = GeodataLoader.memconservative, @JsonKey(name: 'global-ua') this.globalUa, @JsonKey(name: 'external-controller') this.externalController = ExternalControllerStatus.close, this.secret = '', Map hosts = const {}, @JsonKey(name: 'geo-auto-update') this.geoAutoUpdate = false, @JsonKey(name: 'geo-update-interval') this.geoUpdateInterval = 24}): _dnsOverrideKeys = dnsOverrideKeys,_geoXUrl = geoXUrl,_hosts = hosts; + const _PatchClashConfig({@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, this.ipv6 = false, @JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) this.findProcessMode = FindProcessMode.off, @JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) this.interfaceNameMode = InterfaceNameMode.clear, @JsonKey(name: 'interface-name') this.interfaceName = '', @JsonKey(name: 'keep-alive-interval') this.keepAliveInterval = defaultKeepAliveInterval, @JsonKey(name: 'keep-alive-idle') this.keepAliveIdle = 15, @JsonKey(name: 'disable-keep-alive') this.disableKeepAlive = false, @JsonKey(name: 'routing-mark') this.routingMark = 0, @JsonKey(name: 'unified-delay') this.unifiedDelay = true, @JsonKey(name: 'tcp-concurrent') this.tcpConcurrent = true, @JsonKey(fromJson: Tun.safeFormJson) this.tun = defaultTun, @JsonKey(fromJson: Dns.safeDnsFromJson) this.dns = defaultDns, @JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys = const {}, @JsonKey(name: 'tun-override', fromJson: ProfileTun.safeFromJson) this.tunOverride = defaultProfileTun, @JsonKey(name: _tunOverrideKeysJsonKey, fromJson: _tunOverrideKeysFromJson) Set tunOverrideKeys = const {}, @JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl = defaultGeoXUrl, @JsonKey(name: 'geodata-loader') this.geodataLoader = GeodataLoader.memconservative, @JsonKey(name: 'global-ua') this.globalUa, @JsonKey(name: 'external-controller') this.externalController = ExternalControllerStatus.close, this.secret = '', Map hosts = const {}, @JsonKey(name: 'geo-auto-update') this.geoAutoUpdate = false, @JsonKey(name: 'geo-update-interval') this.geoUpdateInterval = 24}): _dnsOverrideKeys = dnsOverrideKeys,_tunOverrideKeys = tunOverrideKeys,_geoXUrl = geoXUrl,_hosts = hosts; factory _PatchClashConfig.fromJson(Map json) => _$PatchClashConfigFromJson(json); @override@JsonKey(name: 'mixed-port') final int mixedPort; @@ -7532,6 +7615,14 @@ class _PatchClashConfig implements PatchClashConfig { return EqualUnmodifiableSetView(_dnsOverrideKeys); } +@override@JsonKey(name: 'tun-override', fromJson: ProfileTun.safeFromJson) final ProfileTun tunOverride; + final Set _tunOverrideKeys; +@override@JsonKey(name: _tunOverrideKeysJsonKey, fromJson: _tunOverrideKeysFromJson) Set get tunOverrideKeys { + if (_tunOverrideKeys is EqualUnmodifiableSetView) return _tunOverrideKeys; + // ignore: implicit_dynamic_type + return EqualUnmodifiableSetView(_tunOverrideKeys); +} + final Map _geoXUrl; @override@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map get geoXUrl { if (_geoXUrl is EqualUnmodifiableMapView) return _geoXUrl; @@ -7566,18 +7657,18 @@ Map toJson() { @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _PatchClashConfig&&(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)&&(identical(other.logLevel, logLevel) || other.logLevel == logLevel)&&(identical(other.ipv6, ipv6) || other.ipv6 == ipv6)&&(identical(other.findProcessMode, findProcessMode) || other.findProcessMode == findProcessMode)&&(identical(other.interfaceNameMode, interfaceNameMode) || other.interfaceNameMode == interfaceNameMode)&&(identical(other.interfaceName, interfaceName) || other.interfaceName == interfaceName)&&(identical(other.keepAliveInterval, keepAliveInterval) || other.keepAliveInterval == keepAliveInterval)&&(identical(other.keepAliveIdle, keepAliveIdle) || other.keepAliveIdle == keepAliveIdle)&&(identical(other.disableKeepAlive, disableKeepAlive) || other.disableKeepAlive == disableKeepAlive)&&(identical(other.routingMark, routingMark) || other.routingMark == routingMark)&&(identical(other.unifiedDelay, unifiedDelay) || other.unifiedDelay == unifiedDelay)&&(identical(other.tcpConcurrent, tcpConcurrent) || other.tcpConcurrent == tcpConcurrent)&&(identical(other.tun, tun) || other.tun == tun)&&(identical(other.dns, dns) || other.dns == dns)&&const DeepCollectionEquality().equals(other.dnsOverrideKeys, _dnsOverrideKeys)&&const DeepCollectionEquality().equals(other.geoXUrl, _geoXUrl)&&(identical(other.geodataLoader, geodataLoader) || other.geodataLoader == geodataLoader)&&(identical(other.globalUa, globalUa) || other.globalUa == globalUa)&&(identical(other.externalController, externalController) || other.externalController == externalController)&&(identical(other.secret, secret) || other.secret == secret)&&const DeepCollectionEquality().equals(other.hosts, _hosts)&&(identical(other.geoAutoUpdate, geoAutoUpdate) || other.geoAutoUpdate == geoAutoUpdate)&&(identical(other.geoUpdateInterval, geoUpdateInterval) || other.geoUpdateInterval == geoUpdateInterval)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _PatchClashConfig&&(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)&&(identical(other.logLevel, logLevel) || other.logLevel == logLevel)&&(identical(other.ipv6, ipv6) || other.ipv6 == ipv6)&&(identical(other.findProcessMode, findProcessMode) || other.findProcessMode == findProcessMode)&&(identical(other.interfaceNameMode, interfaceNameMode) || other.interfaceNameMode == interfaceNameMode)&&(identical(other.interfaceName, interfaceName) || other.interfaceName == interfaceName)&&(identical(other.keepAliveInterval, keepAliveInterval) || other.keepAliveInterval == keepAliveInterval)&&(identical(other.keepAliveIdle, keepAliveIdle) || other.keepAliveIdle == keepAliveIdle)&&(identical(other.disableKeepAlive, disableKeepAlive) || other.disableKeepAlive == disableKeepAlive)&&(identical(other.routingMark, routingMark) || other.routingMark == routingMark)&&(identical(other.unifiedDelay, unifiedDelay) || other.unifiedDelay == unifiedDelay)&&(identical(other.tcpConcurrent, tcpConcurrent) || other.tcpConcurrent == tcpConcurrent)&&(identical(other.tun, tun) || other.tun == tun)&&(identical(other.dns, dns) || other.dns == dns)&&const DeepCollectionEquality().equals(other.dnsOverrideKeys, _dnsOverrideKeys)&&(identical(other.tunOverride, tunOverride) || other.tunOverride == tunOverride)&&const DeepCollectionEquality().equals(other.tunOverrideKeys, _tunOverrideKeys)&&const DeepCollectionEquality().equals(other.geoXUrl, _geoXUrl)&&(identical(other.geodataLoader, geodataLoader) || other.geodataLoader == geodataLoader)&&(identical(other.globalUa, globalUa) || other.globalUa == globalUa)&&(identical(other.externalController, externalController) || other.externalController == externalController)&&(identical(other.secret, secret) || other.secret == secret)&&const DeepCollectionEquality().equals(other.hosts, _hosts)&&(identical(other.geoAutoUpdate, geoAutoUpdate) || other.geoAutoUpdate == geoAutoUpdate)&&(identical(other.geoUpdateInterval, geoUpdateInterval) || other.geoUpdateInterval == geoUpdateInterval)); } @JsonKey(includeFromJson: false, includeToJson: false) @override int get hashCode { - return Object.hashAll([runtimeType,mixedPort,socksPort,port,redirPort,tproxyPort,mode,allowLan,logLevel,ipv6,findProcessMode,interfaceNameMode,interfaceName,keepAliveInterval,keepAliveIdle,disableKeepAlive,routingMark,unifiedDelay,tcpConcurrent,tun,dns,const DeepCollectionEquality().hash(_dnsOverrideKeys),const DeepCollectionEquality().hash(_geoXUrl),geodataLoader,globalUa,externalController,secret,const DeepCollectionEquality().hash(_hosts),geoAutoUpdate,geoUpdateInterval]); + return Object.hashAll([runtimeType,mixedPort,socksPort,port,redirPort,tproxyPort,mode,allowLan,logLevel,ipv6,findProcessMode,interfaceNameMode,interfaceName,keepAliveInterval,keepAliveIdle,disableKeepAlive,routingMark,unifiedDelay,tcpConcurrent,tun,dns,const DeepCollectionEquality().hash(_dnsOverrideKeys),tunOverride,const DeepCollectionEquality().hash(_tunOverrideKeys),const DeepCollectionEquality().hash(_geoXUrl),geodataLoader,globalUa,externalController,secret,const DeepCollectionEquality().hash(_hosts),geoAutoUpdate,geoUpdateInterval]); } @override String toString() { - return 'PatchClashConfig(mixedPort: $mixedPort, socksPort: $socksPort, port: $port, redirPort: $redirPort, tproxyPort: $tproxyPort, mode: $mode, allowLan: $allowLan, logLevel: $logLevel, ipv6: $ipv6, findProcessMode: $findProcessMode, interfaceNameMode: $interfaceNameMode, interfaceName: $interfaceName, keepAliveInterval: $keepAliveInterval, keepAliveIdle: $keepAliveIdle, disableKeepAlive: $disableKeepAlive, routingMark: $routingMark, unifiedDelay: $unifiedDelay, tcpConcurrent: $tcpConcurrent, tun: $tun, dns: $dns, dnsOverrideKeys: $dnsOverrideKeys, geoXUrl: $geoXUrl, geodataLoader: $geodataLoader, globalUa: $globalUa, externalController: $externalController, secret: $secret, hosts: $hosts, geoAutoUpdate: $geoAutoUpdate, geoUpdateInterval: $geoUpdateInterval)'; + return 'PatchClashConfig(mixedPort: $mixedPort, socksPort: $socksPort, port: $port, redirPort: $redirPort, tproxyPort: $tproxyPort, mode: $mode, allowLan: $allowLan, logLevel: $logLevel, ipv6: $ipv6, findProcessMode: $findProcessMode, interfaceNameMode: $interfaceNameMode, interfaceName: $interfaceName, keepAliveInterval: $keepAliveInterval, keepAliveIdle: $keepAliveIdle, disableKeepAlive: $disableKeepAlive, routingMark: $routingMark, unifiedDelay: $unifiedDelay, tcpConcurrent: $tcpConcurrent, tun: $tun, dns: $dns, dnsOverrideKeys: $dnsOverrideKeys, tunOverride: $tunOverride, tunOverrideKeys: $tunOverrideKeys, geoXUrl: $geoXUrl, geodataLoader: $geodataLoader, globalUa: $globalUa, externalController: $externalController, secret: $secret, hosts: $hosts, geoAutoUpdate: $geoAutoUpdate, geoUpdateInterval: $geoUpdateInterval)'; } @@ -7588,11 +7679,11 @@ abstract mixin class _$PatchClashConfigCopyWith<$Res> implements $PatchClashConf factory _$PatchClashConfigCopyWith(_PatchClashConfig value, $Res Function(_PatchClashConfig) _then) = __$PatchClashConfigCopyWithImpl; @override @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, bool ipv6,@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode findProcessMode,@JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode interfaceNameMode,@JsonKey(name: 'interface-name') String interfaceName,@JsonKey(name: 'keep-alive-interval') int keepAliveInterval,@JsonKey(name: 'keep-alive-idle') int keepAliveIdle,@JsonKey(name: 'disable-keep-alive') bool disableKeepAlive,@JsonKey(name: 'routing-mark') int routingMark,@JsonKey(name: 'unified-delay') bool unifiedDelay,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(fromJson: Tun.safeFormJson) Tun tun,@JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,@JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys,@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl,@JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader,@JsonKey(name: 'global-ua') String? globalUa,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, Map hosts,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval +@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, bool ipv6,@JsonKey(name: 'find-process-mode', unknownEnumValue: FindProcessMode.off) FindProcessMode findProcessMode,@JsonKey(name: 'interface-name-mode', unknownEnumValue: InterfaceNameMode.clear) InterfaceNameMode interfaceNameMode,@JsonKey(name: 'interface-name') String interfaceName,@JsonKey(name: 'keep-alive-interval') int keepAliveInterval,@JsonKey(name: 'keep-alive-idle') int keepAliveIdle,@JsonKey(name: 'disable-keep-alive') bool disableKeepAlive,@JsonKey(name: 'routing-mark') int routingMark,@JsonKey(name: 'unified-delay') bool unifiedDelay,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(fromJson: Tun.safeFormJson) Tun tun,@JsonKey(fromJson: Dns.safeDnsFromJson) Dns dns,@JsonKey(name: _dnsOverrideKeysJsonKey, fromJson: _dnsOverrideKeysFromJson) Set dnsOverrideKeys,@JsonKey(name: 'tun-override', fromJson: ProfileTun.safeFromJson) ProfileTun tunOverride,@JsonKey(name: _tunOverrideKeysJsonKey, fromJson: _tunOverrideKeysFromJson) Set tunOverrideKeys,@JsonKey(name: 'geox-url', fromJson: _geoXUrlFromJson, toJson: _geoXUrlToJson) Map geoXUrl,@JsonKey(name: 'geodata-loader') GeodataLoader geodataLoader,@JsonKey(name: 'global-ua') String? globalUa,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, Map hosts,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval }); -@override $TunCopyWith<$Res> get tun;@override $DnsCopyWith<$Res> get dns; +@override $TunCopyWith<$Res> get tun;@override $DnsCopyWith<$Res> get dns;@override $ProfileTunCopyWith<$Res> get tunOverride; } /// @nodoc @@ -7605,7 +7696,7 @@ class __$PatchClashConfigCopyWithImpl<$Res> /// Create a copy of PatchClashConfig /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $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,Object? ipv6 = null,Object? findProcessMode = null,Object? interfaceNameMode = null,Object? interfaceName = null,Object? keepAliveInterval = null,Object? keepAliveIdle = null,Object? disableKeepAlive = null,Object? routingMark = null,Object? unifiedDelay = null,Object? tcpConcurrent = null,Object? tun = null,Object? dns = null,Object? dnsOverrideKeys = null,Object? geoXUrl = null,Object? geodataLoader = null,Object? globalUa = freezed,Object? externalController = null,Object? secret = null,Object? hosts = null,Object? geoAutoUpdate = null,Object? geoUpdateInterval = null,}) { +@override @pragma('vm:prefer-inline') $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,Object? ipv6 = null,Object? findProcessMode = null,Object? interfaceNameMode = null,Object? interfaceName = null,Object? keepAliveInterval = null,Object? keepAliveIdle = null,Object? disableKeepAlive = null,Object? routingMark = null,Object? unifiedDelay = null,Object? tcpConcurrent = null,Object? tun = null,Object? dns = null,Object? dnsOverrideKeys = null,Object? tunOverride = null,Object? tunOverrideKeys = null,Object? geoXUrl = null,Object? geodataLoader = null,Object? globalUa = freezed,Object? externalController = null,Object? secret = null,Object? hosts = null,Object? geoAutoUpdate = null,Object? geoUpdateInterval = null,}) { return _then(_PatchClashConfig( mixedPort: null == mixedPort ? _self.mixedPort : mixedPort // ignore: cast_nullable_to_non_nullable as int,socksPort: null == socksPort ? _self.socksPort : socksPort // ignore: cast_nullable_to_non_nullable @@ -7628,7 +7719,9 @@ as bool,tcpConcurrent: null == tcpConcurrent ? _self.tcpConcurrent : tcpConcurre as bool,tun: null == tun ? _self.tun : tun // ignore: cast_nullable_to_non_nullable as Tun,dns: null == dns ? _self.dns : dns // ignore: cast_nullable_to_non_nullable as Dns,dnsOverrideKeys: null == dnsOverrideKeys ? _self._dnsOverrideKeys : dnsOverrideKeys // ignore: cast_nullable_to_non_nullable -as Set,geoXUrl: null == geoXUrl ? _self._geoXUrl : geoXUrl // ignore: cast_nullable_to_non_nullable +as Set,tunOverride: null == tunOverride ? _self.tunOverride : tunOverride // ignore: cast_nullable_to_non_nullable +as ProfileTun,tunOverrideKeys: null == tunOverrideKeys ? _self._tunOverrideKeys : tunOverrideKeys // ignore: cast_nullable_to_non_nullable +as Set,geoXUrl: null == geoXUrl ? _self._geoXUrl : geoXUrl // ignore: cast_nullable_to_non_nullable as Map,geodataLoader: null == geodataLoader ? _self.geodataLoader : geodataLoader // ignore: cast_nullable_to_non_nullable as GeodataLoader,globalUa: freezed == globalUa ? _self.globalUa : globalUa // ignore: cast_nullable_to_non_nullable as String?,externalController: null == externalController ? _self.externalController : externalController // ignore: cast_nullable_to_non_nullable @@ -7658,6 +7751,15 @@ $DnsCopyWith<$Res> get dns { return $DnsCopyWith<$Res>(_self.dns, (value) { return _then(_self.copyWith(dns: value)); }); +}/// Create a copy of PatchClashConfig +/// with the given fields replaced by the non-null parameter values. +@override +@pragma('vm:prefer-inline') +$ProfileTunCopyWith<$Res> get tunOverride { + + return $ProfileTunCopyWith<$Res>(_self.tunOverride, (value) { + return _then(_self.copyWith(tunOverride: value)); + }); } } diff --git a/lib/models/generated/clash_config.g.dart b/lib/models/generated/clash_config.g.dart index 187bb1d6..d3803402 100644 --- a/lib/models/generated/clash_config.g.dart +++ b/lib/models/generated/clash_config.g.dart @@ -246,13 +246,7 @@ Map _$SnifferConfigToJson(_SnifferConfig instance) => _Tun _$TunFromJson(Map json) => _Tun( enable: json['enable'] as bool? ?? false, device: json['device'] as String? ?? appName, - autoRoute: json['auto-route'] as bool? ?? false, stack: $enumDecodeNullable(_$TunStackEnumMap, json['stack']) ?? TunStack.mips, - dnsHijack: - (json['dns-hijack'] as List?) - ?.map((e) => e as String) - .toList() ?? - const ['any:53'], routeAddress: (json['route-address'] as List?) ?.map((e) => e as String) @@ -264,7 +258,6 @@ _Tun _$TunFromJson(Map json) => _Tun( congestionController: json['congestion-controller'] == null ? defaultCongestionController : _congestionControllerFromJson(json['congestion-controller'] as String), - strictRoute: json['strict-route'] as bool? ?? false, routeExcludeAddress: (json['route-exclude-address'] as List?) ?.map((e) => e as String) @@ -275,13 +268,10 @@ _Tun _$TunFromJson(Map json) => _Tun( Map _$TunToJson(_Tun instance) => { 'enable': instance.enable, 'device': instance.device, - 'auto-route': instance.autoRoute, 'stack': _$TunStackEnumMap[instance.stack]!, - 'dns-hijack': instance.dnsHijack, 'route-address': instance.routeAddress, 'mtu': instance.mtu, 'congestion-controller': instance.congestionController, - 'strict-route': instance.strictRoute, 'route-exclude-address': instance.routeExcludeAddress, }; @@ -461,18 +451,77 @@ Map _$NtpToJson(_Ntp instance) => { }; _ProfileTun _$ProfileTunFromJson(Map json) => _ProfileTun( + mtu: (json['mtu'] as num?)?.toInt() ?? defaultTunMtu, + congestionController: + json['congestion-controller'] as String? ?? defaultCongestionController, + strictRoute: json['strict-route'] as bool? ?? false, + routeAddress: + (json['route-address'] as List?) + ?.map((e) => e as String) + .toList() ?? + const [], + routeExcludeAddress: + (json['route-exclude-address'] as List?) + ?.map((e) => e as String) + .toList() ?? + const [], + dnsHijack: + (json['dns-hijack'] as List?) + ?.map((e) => e as String) + .toList() ?? + defaultDnsHijack, + udpTimeout: (json['udp-timeout'] as num?)?.toInt() ?? defaultTunUdpTimeout, disableIcmpForwarding: json['disable-icmp-forwarding'] as bool? ?? false, + gso: json['gso'] as bool? ?? false, + includeInterface: + (json['include-interface'] as List?) + ?.map((e) => e as String) + .toList() ?? + const [], excludeInterface: (json['exclude-interface'] as List?) ?.map((e) => e as String) .toList() ?? const [], + includeUid: + (json['include-uid'] as List?) + ?.map((e) => (e as num).toInt()) + .toList() ?? + const [], + excludeUid: + (json['exclude-uid'] as List?) + ?.map((e) => (e as num).toInt()) + .toList() ?? + const [], + excludeSrcPort: + (json['exclude-src-port'] as List?) + ?.map((e) => (e as num).toInt()) + .toList() ?? + const [], + excludeDstPort: + (json['exclude-dst-port'] as List?) + ?.map((e) => (e as num).toInt()) + .toList() ?? + const [], ); Map _$ProfileTunToJson(_ProfileTun instance) => { + 'mtu': instance.mtu, + 'congestion-controller': instance.congestionController, + 'strict-route': instance.strictRoute, + 'route-address': instance.routeAddress, + 'route-exclude-address': instance.routeExcludeAddress, + 'dns-hijack': instance.dnsHijack, + 'udp-timeout': instance.udpTimeout, 'disable-icmp-forwarding': instance.disableIcmpForwarding, + 'gso': instance.gso, + 'include-interface': instance.includeInterface, 'exclude-interface': instance.excludeInterface, + 'include-uid': instance.includeUid, + 'exclude-uid': instance.excludeUid, + 'exclude-src-port': instance.excludeSrcPort, + 'exclude-dst-port': instance.excludeDstPort, }; _ProfileOverrides _$ProfileOverridesFromJson(Map json) => @@ -593,8 +642,21 @@ const _$SnifferOverrideKeyEnumMap = { }; const _$TunOverrideKeyEnumMap = { + TunOverrideKey.mtu: 'mtu', + TunOverrideKey.congestionController: 'congestion-controller', + TunOverrideKey.strictRoute: 'strict-route', + TunOverrideKey.routeAddress: 'route-address', + TunOverrideKey.routeExcludeAddress: 'route-exclude-address', + TunOverrideKey.dnsHijack: 'dns-hijack', + TunOverrideKey.udpTimeout: 'udp-timeout', TunOverrideKey.disableIcmpForwarding: 'disable-icmp-forwarding', + TunOverrideKey.gso: 'gso', + TunOverrideKey.includeInterface: 'include-interface', TunOverrideKey.excludeInterface: 'exclude-interface', + TunOverrideKey.includeUid: 'include-uid', + TunOverrideKey.excludeUid: 'exclude-uid', + TunOverrideKey.excludeSrcPort: 'exclude-src-port', + TunOverrideKey.excludeDstPort: 'exclude-dst-port', }; _ProviderHealthCheck _$ProviderHealthCheckFromJson(Map json) => @@ -814,6 +876,14 @@ _PatchClashConfig _$PatchClashConfigFromJson(Map json) => dnsOverrideKeys: json['dns-override-keys'] == null ? const {} : _dnsOverrideKeysFromJson(json['dns-override-keys'] as List), + tunOverride: json['tun-override'] == null + ? defaultProfileTun + : ProfileTun.safeFromJson( + json['tun-override'] as Map, + ), + tunOverrideKeys: json['tun-override-keys'] == null + ? const {} + : _tunOverrideKeysFromJson(json['tun-override-keys'] as List), geoXUrl: json['geox-url'] == null ? defaultGeoXUrl : _geoXUrlFromJson(json['geox-url'] as Map?), @@ -863,6 +933,10 @@ Map _$PatchClashConfigToJson(_PatchClashConfig instance) => 'dns-override-keys': instance.dnsOverrideKeys .map((e) => _$DnsOverrideKeyEnumMap[e]!) .toList(), + 'tun-override': instance.tunOverride, + 'tun-override-keys': instance.tunOverrideKeys + .map((e) => _$TunOverrideKeyEnumMap[e]!) + .toList(), 'geox-url': _geoXUrlToJson(instance.geoXUrl), 'geodata-loader': _$GeodataLoaderEnumMap[instance.geodataLoader]!, 'global-ua': instance.globalUa, diff --git a/lib/models/generated/core.freezed.dart b/lib/models/generated/core.freezed.dart index 02442507..ef42df31 100644 --- a/lib/models/generated/core.freezed.dart +++ b/lib/models/generated/core.freezed.dart @@ -895,7 +895,7 @@ as int, /// @nodoc mixin _$UpdateParams { - Tun get tun;@JsonKey(name: 'mixed-port') int get mixedPort;@JsonKey(name: 'allow-lan') bool get allowLan;@JsonKey(name: 'find-process-mode') FindProcessMode get findProcessMode; Mode get mode;@JsonKey(name: 'log-level') LogLevel get logLevel; bool get ipv6;@JsonKey(name: 'tcp-concurrent') bool get tcpConcurrent;@JsonKey(name: 'external-controller') ExternalControllerStatus get externalController; String get secret;@JsonKey(name: 'unified-delay') bool get unifiedDelay; List get authentication;@JsonKey(name: 'geo-auto-update') bool get geoAutoUpdate;@JsonKey(name: 'geo-update-interval') int get geoUpdateInterval;@JsonKey(name: 'geox-url') Map get geoXUrl;@JsonKey(name: 'skip-cert-verify') bool get skipCertVerify; +@JsonKey(toJson: _tunCoreJson) Tun get tun;@JsonKey(name: 'mixed-port') int get mixedPort;@JsonKey(name: 'allow-lan') bool get allowLan;@JsonKey(name: 'find-process-mode') FindProcessMode get findProcessMode; Mode get mode;@JsonKey(name: 'log-level') LogLevel get logLevel; bool get ipv6;@JsonKey(name: 'tcp-concurrent') bool get tcpConcurrent;@JsonKey(name: 'external-controller') ExternalControllerStatus get externalController; String get secret;@JsonKey(name: 'unified-delay') bool get unifiedDelay; List get authentication;@JsonKey(name: 'geo-auto-update') bool get geoAutoUpdate;@JsonKey(name: 'geo-update-interval') int get geoUpdateInterval;@JsonKey(name: 'geox-url') Map get geoXUrl;@JsonKey(name: 'skip-cert-verify') bool get skipCertVerify; /// Create a copy of UpdateParams /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -933,7 +933,7 @@ abstract mixin class $UpdateParamsCopyWith<$Res> { factory $UpdateParamsCopyWith(UpdateParams value, $Res Function(UpdateParams) _then) = _$UpdateParamsCopyWithImpl; @useResult $Res call({ - Tun tun,@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret,@JsonKey(name: 'unified-delay') bool unifiedDelay, List authentication,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval,@JsonKey(name: 'geox-url') Map geoXUrl,@JsonKey(name: 'skip-cert-verify') bool skipCertVerify +@JsonKey(toJson: _tunCoreJson) Tun tun,@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret,@JsonKey(name: 'unified-delay') bool unifiedDelay, List authentication,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval,@JsonKey(name: 'geox-url') Map geoXUrl,@JsonKey(name: 'skip-cert-verify') bool skipCertVerify }); @@ -1062,7 +1062,7 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, @JsonKey(name: 'unified-delay') bool unifiedDelay, List authentication, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval, @JsonKey(name: 'geox-url') Map geoXUrl, @JsonKey(name: 'skip-cert-verify') bool skipCertVerify)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function(@JsonKey(toJson: _tunCoreJson) Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, @JsonKey(name: 'unified-delay') bool unifiedDelay, List authentication, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval, @JsonKey(name: 'geox-url') Map geoXUrl, @JsonKey(name: 'skip-cert-verify') bool skipCertVerify)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _UpdateParams() when $default != null: return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_that.mode,_that.logLevel,_that.ipv6,_that.tcpConcurrent,_that.externalController,_that.secret,_that.unifiedDelay,_that.authentication,_that.geoAutoUpdate,_that.geoUpdateInterval,_that.geoXUrl,_that.skipCertVerify);case _: @@ -1083,7 +1083,7 @@ return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_ /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, @JsonKey(name: 'unified-delay') bool unifiedDelay, List authentication, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval, @JsonKey(name: 'geox-url') Map geoXUrl, @JsonKey(name: 'skip-cert-verify') bool skipCertVerify) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function(@JsonKey(toJson: _tunCoreJson) Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, @JsonKey(name: 'unified-delay') bool unifiedDelay, List authentication, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval, @JsonKey(name: 'geox-url') Map geoXUrl, @JsonKey(name: 'skip-cert-verify') bool skipCertVerify) $default,) {final _that = this; switch (_that) { case _UpdateParams(): return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_that.mode,_that.logLevel,_that.ipv6,_that.tcpConcurrent,_that.externalController,_that.secret,_that.unifiedDelay,_that.authentication,_that.geoAutoUpdate,_that.geoUpdateInterval,_that.geoXUrl,_that.skipCertVerify);case _: @@ -1103,7 +1103,7 @@ return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_ /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, @JsonKey(name: 'unified-delay') bool unifiedDelay, List authentication, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval, @JsonKey(name: 'geox-url') Map geoXUrl, @JsonKey(name: 'skip-cert-verify') bool skipCertVerify)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function(@JsonKey(toJson: _tunCoreJson) Tun tun, @JsonKey(name: 'mixed-port') int mixedPort, @JsonKey(name: 'allow-lan') bool allowLan, @JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode, @JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6, @JsonKey(name: 'tcp-concurrent') bool tcpConcurrent, @JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret, @JsonKey(name: 'unified-delay') bool unifiedDelay, List authentication, @JsonKey(name: 'geo-auto-update') bool geoAutoUpdate, @JsonKey(name: 'geo-update-interval') int geoUpdateInterval, @JsonKey(name: 'geox-url') Map geoXUrl, @JsonKey(name: 'skip-cert-verify') bool skipCertVerify)? $default,) {final _that = this; switch (_that) { case _UpdateParams() when $default != null: return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_that.mode,_that.logLevel,_that.ipv6,_that.tcpConcurrent,_that.externalController,_that.secret,_that.unifiedDelay,_that.authentication,_that.geoAutoUpdate,_that.geoUpdateInterval,_that.geoXUrl,_that.skipCertVerify);case _: @@ -1118,10 +1118,10 @@ return $default(_that.tun,_that.mixedPort,_that.allowLan,_that.findProcessMode,_ @JsonSerializable() class _UpdateParams implements UpdateParams { - const _UpdateParams({required this.tun, @JsonKey(name: 'mixed-port') required this.mixedPort, @JsonKey(name: 'allow-lan') required this.allowLan, @JsonKey(name: 'find-process-mode') required this.findProcessMode, required this.mode, @JsonKey(name: 'log-level') required this.logLevel, required this.ipv6, @JsonKey(name: 'tcp-concurrent') required this.tcpConcurrent, @JsonKey(name: 'external-controller') required this.externalController, this.secret = '', @JsonKey(name: 'unified-delay') required this.unifiedDelay, List authentication = const [], @JsonKey(name: 'geo-auto-update') this.geoAutoUpdate = false, @JsonKey(name: 'geo-update-interval') this.geoUpdateInterval = 24, @JsonKey(name: 'geox-url') Map geoXUrl = const {}, @JsonKey(name: 'skip-cert-verify') this.skipCertVerify = false}): _authentication = authentication,_geoXUrl = geoXUrl; + const _UpdateParams({@JsonKey(toJson: _tunCoreJson) required this.tun, @JsonKey(name: 'mixed-port') required this.mixedPort, @JsonKey(name: 'allow-lan') required this.allowLan, @JsonKey(name: 'find-process-mode') required this.findProcessMode, required this.mode, @JsonKey(name: 'log-level') required this.logLevel, required this.ipv6, @JsonKey(name: 'tcp-concurrent') required this.tcpConcurrent, @JsonKey(name: 'external-controller') required this.externalController, this.secret = '', @JsonKey(name: 'unified-delay') required this.unifiedDelay, List authentication = const [], @JsonKey(name: 'geo-auto-update') this.geoAutoUpdate = false, @JsonKey(name: 'geo-update-interval') this.geoUpdateInterval = 24, @JsonKey(name: 'geox-url') Map geoXUrl = const {}, @JsonKey(name: 'skip-cert-verify') this.skipCertVerify = false}): _authentication = authentication,_geoXUrl = geoXUrl; factory _UpdateParams.fromJson(Map json) => _$UpdateParamsFromJson(json); -@override final Tun tun; +@override@JsonKey(toJson: _tunCoreJson) final Tun tun; @override@JsonKey(name: 'mixed-port') final int mixedPort; @override@JsonKey(name: 'allow-lan') final bool allowLan; @override@JsonKey(name: 'find-process-mode') final FindProcessMode findProcessMode; @@ -1185,7 +1185,7 @@ abstract mixin class _$UpdateParamsCopyWith<$Res> implements $UpdateParamsCopyWi factory _$UpdateParamsCopyWith(_UpdateParams value, $Res Function(_UpdateParams) _then) = __$UpdateParamsCopyWithImpl; @override @useResult $Res call({ - Tun tun,@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret,@JsonKey(name: 'unified-delay') bool unifiedDelay, List authentication,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval,@JsonKey(name: 'geox-url') Map geoXUrl,@JsonKey(name: 'skip-cert-verify') bool skipCertVerify +@JsonKey(toJson: _tunCoreJson) Tun tun,@JsonKey(name: 'mixed-port') int mixedPort,@JsonKey(name: 'allow-lan') bool allowLan,@JsonKey(name: 'find-process-mode') FindProcessMode findProcessMode, Mode mode,@JsonKey(name: 'log-level') LogLevel logLevel, bool ipv6,@JsonKey(name: 'tcp-concurrent') bool tcpConcurrent,@JsonKey(name: 'external-controller') ExternalControllerStatus externalController, String secret,@JsonKey(name: 'unified-delay') bool unifiedDelay, List authentication,@JsonKey(name: 'geo-auto-update') bool geoAutoUpdate,@JsonKey(name: 'geo-update-interval') int geoUpdateInterval,@JsonKey(name: 'geox-url') Map geoXUrl,@JsonKey(name: 'skip-cert-verify') bool skipCertVerify }); diff --git a/lib/models/generated/core.g.dart b/lib/models/generated/core.g.dart index 5f9d7a53..36fbdc5f 100644 --- a/lib/models/generated/core.g.dart +++ b/lib/models/generated/core.g.dart @@ -90,7 +90,7 @@ _UpdateParams _$UpdateParamsFromJson(Map json) => Map _$UpdateParamsToJson(_UpdateParams instance) => { - 'tun': instance.tun, + 'tun': _tunCoreJson(instance.tun), 'mixed-port': instance.mixedPort, 'allow-lan': instance.allowLan, 'find-process-mode': _$FindProcessModeEnumMap[instance.findProcessMode]!, diff --git a/lib/models/generated/state.freezed.dart b/lib/models/generated/state.freezed.dart index e17cd6a2..f4f781fc 100644 --- a/lib/models/generated/state.freezed.dart +++ b/lib/models/generated/state.freezed.dart @@ -1119,7 +1119,7 @@ as int?, /// @nodoc mixin _$TrayState { - Mode get mode; int get port; bool get autoLaunch; bool get systemProxy; bool get tunEnable; bool get isStart; List get groups; Map get selectedMap; bool get showTrayTitle; bool get safeMode; Map get hotKeys; + Mode get mode; int get port; bool get autoLaunch; bool get systemProxy; bool get tunEnable; bool get isStart; bool get suspended; List get groups; Map get selectedMap; bool get showTrayTitle; bool get safeMode; Map get hotKeys; /// Create a copy of TrayState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -1131,20 +1131,20 @@ $TrayStateCopyWith get copyWith => _$TrayStateCopyWithImpl @override bool operator ==(Object other) { final _this = this as TrayState; - return identical(this, other) || (other.runtimeType == runtimeType&&other is TrayState&&(identical(other.mode, _this.mode) || other.mode == _this.mode)&&(identical(other.port, _this.port) || other.port == _this.port)&&(identical(other.autoLaunch, _this.autoLaunch) || other.autoLaunch == _this.autoLaunch)&&(identical(other.systemProxy, _this.systemProxy) || other.systemProxy == _this.systemProxy)&&(identical(other.tunEnable, _this.tunEnable) || other.tunEnable == _this.tunEnable)&&(identical(other.isStart, _this.isStart) || other.isStart == _this.isStart)&&const DeepCollectionEquality().equals(other.groups, _this.groups)&&const DeepCollectionEquality().equals(other.selectedMap, _this.selectedMap)&&(identical(other.showTrayTitle, _this.showTrayTitle) || other.showTrayTitle == _this.showTrayTitle)&&(identical(other.safeMode, _this.safeMode) || other.safeMode == _this.safeMode)&&const DeepCollectionEquality().equals(other.hotKeys, _this.hotKeys)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is TrayState&&(identical(other.mode, _this.mode) || other.mode == _this.mode)&&(identical(other.port, _this.port) || other.port == _this.port)&&(identical(other.autoLaunch, _this.autoLaunch) || other.autoLaunch == _this.autoLaunch)&&(identical(other.systemProxy, _this.systemProxy) || other.systemProxy == _this.systemProxy)&&(identical(other.tunEnable, _this.tunEnable) || other.tunEnable == _this.tunEnable)&&(identical(other.isStart, _this.isStart) || other.isStart == _this.isStart)&&(identical(other.suspended, _this.suspended) || other.suspended == _this.suspended)&&const DeepCollectionEquality().equals(other.groups, _this.groups)&&const DeepCollectionEquality().equals(other.selectedMap, _this.selectedMap)&&(identical(other.showTrayTitle, _this.showTrayTitle) || other.showTrayTitle == _this.showTrayTitle)&&(identical(other.safeMode, _this.safeMode) || other.safeMode == _this.safeMode)&&const DeepCollectionEquality().equals(other.hotKeys, _this.hotKeys)); } @override int get hashCode { final _this = this as TrayState; - return Object.hash(runtimeType,_this.mode,_this.port,_this.autoLaunch,_this.systemProxy,_this.tunEnable,_this.isStart,const DeepCollectionEquality().hash(_this.groups),const DeepCollectionEquality().hash(_this.selectedMap),_this.showTrayTitle,_this.safeMode,const DeepCollectionEquality().hash(_this.hotKeys)); + return Object.hash(runtimeType,_this.mode,_this.port,_this.autoLaunch,_this.systemProxy,_this.tunEnable,_this.isStart,_this.suspended,const DeepCollectionEquality().hash(_this.groups),const DeepCollectionEquality().hash(_this.selectedMap),_this.showTrayTitle,_this.safeMode,const DeepCollectionEquality().hash(_this.hotKeys)); } @override String toString() { final _this = this as TrayState; - return 'TrayState(mode: ${_this.mode}, port: ${_this.port}, autoLaunch: ${_this.autoLaunch}, systemProxy: ${_this.systemProxy}, tunEnable: ${_this.tunEnable}, isStart: ${_this.isStart}, groups: ${_this.groups}, selectedMap: ${_this.selectedMap}, showTrayTitle: ${_this.showTrayTitle}, safeMode: ${_this.safeMode}, hotKeys: ${_this.hotKeys})'; + return 'TrayState(mode: ${_this.mode}, port: ${_this.port}, autoLaunch: ${_this.autoLaunch}, systemProxy: ${_this.systemProxy}, tunEnable: ${_this.tunEnable}, isStart: ${_this.isStart}, suspended: ${_this.suspended}, groups: ${_this.groups}, selectedMap: ${_this.selectedMap}, showTrayTitle: ${_this.showTrayTitle}, safeMode: ${_this.safeMode}, hotKeys: ${_this.hotKeys})'; } @@ -1155,7 +1155,7 @@ abstract mixin class $TrayStateCopyWith<$Res> { factory $TrayStateCopyWith(TrayState value, $Res Function(TrayState) _then) = _$TrayStateCopyWithImpl; @useResult $Res call({ - Mode mode, int port, bool autoLaunch, bool systemProxy, bool tunEnable, bool isStart, List groups, Map selectedMap, bool showTrayTitle, bool safeMode, Map hotKeys + Mode mode, int port, bool autoLaunch, bool systemProxy, bool tunEnable, bool isStart, bool suspended, List groups, Map selectedMap, bool showTrayTitle, bool safeMode, Map hotKeys }); @@ -1172,7 +1172,7 @@ class _$TrayStateCopyWithImpl<$Res> /// Create a copy of TrayState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? mode = null,Object? port = null,Object? autoLaunch = null,Object? systemProxy = null,Object? tunEnable = null,Object? isStart = null,Object? groups = null,Object? selectedMap = null,Object? showTrayTitle = null,Object? safeMode = null,Object? hotKeys = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? mode = null,Object? port = null,Object? autoLaunch = null,Object? systemProxy = null,Object? tunEnable = null,Object? isStart = null,Object? suspended = null,Object? groups = null,Object? selectedMap = null,Object? showTrayTitle = null,Object? safeMode = null,Object? hotKeys = null,}) { return _then(TrayState( mode: null == mode ? _self.mode : mode // ignore: cast_nullable_to_non_nullable as Mode,port: null == port ? _self.port : port // ignore: cast_nullable_to_non_nullable @@ -1180,6 +1180,7 @@ as int,autoLaunch: null == autoLaunch ? _self.autoLaunch : autoLaunch // ignore: as bool,systemProxy: null == systemProxy ? _self.systemProxy : systemProxy // ignore: cast_nullable_to_non_nullable as bool,tunEnable: null == tunEnable ? _self.tunEnable : tunEnable // ignore: cast_nullable_to_non_nullable as bool,isStart: null == isStart ? _self.isStart : isStart // ignore: cast_nullable_to_non_nullable +as bool,suspended: null == suspended ? _self.suspended : suspended // ignore: cast_nullable_to_non_nullable as bool,groups: null == groups ? _self.groups : groups // ignore: cast_nullable_to_non_nullable as List,selectedMap: null == selectedMap ? _self.selectedMap : selectedMap // ignore: cast_nullable_to_non_nullable as Map,showTrayTitle: null == showTrayTitle ? _self.showTrayTitle : showTrayTitle // ignore: cast_nullable_to_non_nullable @@ -1270,10 +1271,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( Mode mode, int port, bool autoLaunch, bool systemProxy, bool tunEnable, bool isStart, List groups, Map selectedMap, bool showTrayTitle, bool safeMode, Map hotKeys)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( Mode mode, int port, bool autoLaunch, bool systemProxy, bool tunEnable, bool isStart, bool suspended, List groups, Map selectedMap, bool showTrayTitle, bool safeMode, Map hotKeys)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _TrayState() when $default != null: -return $default(_that.mode,_that.port,_that.autoLaunch,_that.systemProxy,_that.tunEnable,_that.isStart,_that.groups,_that.selectedMap,_that.showTrayTitle,_that.safeMode,_that.hotKeys);case _: +return $default(_that.mode,_that.port,_that.autoLaunch,_that.systemProxy,_that.tunEnable,_that.isStart,_that.suspended,_that.groups,_that.selectedMap,_that.showTrayTitle,_that.safeMode,_that.hotKeys);case _: return orElse(); } @@ -1291,10 +1292,10 @@ return $default(_that.mode,_that.port,_that.autoLaunch,_that.systemProxy,_that.t /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( Mode mode, int port, bool autoLaunch, bool systemProxy, bool tunEnable, bool isStart, List groups, Map selectedMap, bool showTrayTitle, bool safeMode, Map hotKeys) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( Mode mode, int port, bool autoLaunch, bool systemProxy, bool tunEnable, bool isStart, bool suspended, List groups, Map selectedMap, bool showTrayTitle, bool safeMode, Map hotKeys) $default,) {final _that = this; switch (_that) { case _TrayState(): -return $default(_that.mode,_that.port,_that.autoLaunch,_that.systemProxy,_that.tunEnable,_that.isStart,_that.groups,_that.selectedMap,_that.showTrayTitle,_that.safeMode,_that.hotKeys);case _: +return $default(_that.mode,_that.port,_that.autoLaunch,_that.systemProxy,_that.tunEnable,_that.isStart,_that.suspended,_that.groups,_that.selectedMap,_that.showTrayTitle,_that.safeMode,_that.hotKeys);case _: throw StateError('Unexpected subclass'); } @@ -1311,10 +1312,10 @@ return $default(_that.mode,_that.port,_that.autoLaunch,_that.systemProxy,_that.t /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( Mode mode, int port, bool autoLaunch, bool systemProxy, bool tunEnable, bool isStart, List groups, Map selectedMap, bool showTrayTitle, bool safeMode, Map hotKeys)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( Mode mode, int port, bool autoLaunch, bool systemProxy, bool tunEnable, bool isStart, bool suspended, List groups, Map selectedMap, bool showTrayTitle, bool safeMode, Map hotKeys)? $default,) {final _that = this; switch (_that) { case _TrayState() when $default != null: -return $default(_that.mode,_that.port,_that.autoLaunch,_that.systemProxy,_that.tunEnable,_that.isStart,_that.groups,_that.selectedMap,_that.showTrayTitle,_that.safeMode,_that.hotKeys);case _: +return $default(_that.mode,_that.port,_that.autoLaunch,_that.systemProxy,_that.tunEnable,_that.isStart,_that.suspended,_that.groups,_that.selectedMap,_that.showTrayTitle,_that.safeMode,_that.hotKeys);case _: return null; } @@ -1326,7 +1327,7 @@ return $default(_that.mode,_that.port,_that.autoLaunch,_that.systemProxy,_that.t class _TrayState implements TrayState { - const _TrayState({required this.mode, required this.port, required this.autoLaunch, required this.systemProxy, required this.tunEnable, required this.isStart, required List groups, required Map selectedMap, required this.showTrayTitle, required this.safeMode, Map hotKeys = const {}}): _groups = groups,_selectedMap = selectedMap,_hotKeys = hotKeys; + const _TrayState({required this.mode, required this.port, required this.autoLaunch, required this.systemProxy, required this.tunEnable, required this.isStart, this.suspended = false, required List groups, required Map selectedMap, required this.showTrayTitle, required this.safeMode, Map hotKeys = const {}}): _groups = groups,_selectedMap = selectedMap,_hotKeys = hotKeys; @override final Mode mode; @@ -1335,6 +1336,7 @@ class _TrayState implements TrayState { @override final bool systemProxy; @override final bool tunEnable; @override final bool isStart; +@override@JsonKey() final bool suspended; final List _groups; @override List get groups { if (_groups is EqualUnmodifiableListView) return _groups; @@ -1369,18 +1371,18 @@ _$TrayStateCopyWith<_TrayState> get copyWith => __$TrayStateCopyWithImpl<_TraySt @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _TrayState&&(identical(other.mode, mode) || other.mode == mode)&&(identical(other.port, port) || other.port == port)&&(identical(other.autoLaunch, autoLaunch) || other.autoLaunch == autoLaunch)&&(identical(other.systemProxy, systemProxy) || other.systemProxy == systemProxy)&&(identical(other.tunEnable, tunEnable) || other.tunEnable == tunEnable)&&(identical(other.isStart, isStart) || other.isStart == isStart)&&const DeepCollectionEquality().equals(other.groups, _groups)&&const DeepCollectionEquality().equals(other.selectedMap, _selectedMap)&&(identical(other.showTrayTitle, showTrayTitle) || other.showTrayTitle == showTrayTitle)&&(identical(other.safeMode, safeMode) || other.safeMode == safeMode)&&const DeepCollectionEquality().equals(other.hotKeys, _hotKeys)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _TrayState&&(identical(other.mode, mode) || other.mode == mode)&&(identical(other.port, port) || other.port == port)&&(identical(other.autoLaunch, autoLaunch) || other.autoLaunch == autoLaunch)&&(identical(other.systemProxy, systemProxy) || other.systemProxy == systemProxy)&&(identical(other.tunEnable, tunEnable) || other.tunEnable == tunEnable)&&(identical(other.isStart, isStart) || other.isStart == isStart)&&(identical(other.suspended, suspended) || other.suspended == suspended)&&const DeepCollectionEquality().equals(other.groups, _groups)&&const DeepCollectionEquality().equals(other.selectedMap, _selectedMap)&&(identical(other.showTrayTitle, showTrayTitle) || other.showTrayTitle == showTrayTitle)&&(identical(other.safeMode, safeMode) || other.safeMode == safeMode)&&const DeepCollectionEquality().equals(other.hotKeys, _hotKeys)); } @override int get hashCode { - return Object.hash(runtimeType,mode,port,autoLaunch,systemProxy,tunEnable,isStart,const DeepCollectionEquality().hash(_groups),const DeepCollectionEquality().hash(_selectedMap),showTrayTitle,safeMode,const DeepCollectionEquality().hash(_hotKeys)); + return Object.hash(runtimeType,mode,port,autoLaunch,systemProxy,tunEnable,isStart,suspended,const DeepCollectionEquality().hash(_groups),const DeepCollectionEquality().hash(_selectedMap),showTrayTitle,safeMode,const DeepCollectionEquality().hash(_hotKeys)); } @override String toString() { - return 'TrayState(mode: $mode, port: $port, autoLaunch: $autoLaunch, systemProxy: $systemProxy, tunEnable: $tunEnable, isStart: $isStart, groups: $groups, selectedMap: $selectedMap, showTrayTitle: $showTrayTitle, safeMode: $safeMode, hotKeys: $hotKeys)'; + return 'TrayState(mode: $mode, port: $port, autoLaunch: $autoLaunch, systemProxy: $systemProxy, tunEnable: $tunEnable, isStart: $isStart, suspended: $suspended, groups: $groups, selectedMap: $selectedMap, showTrayTitle: $showTrayTitle, safeMode: $safeMode, hotKeys: $hotKeys)'; } @@ -1391,7 +1393,7 @@ abstract mixin class _$TrayStateCopyWith<$Res> implements $TrayStateCopyWith<$Re factory _$TrayStateCopyWith(_TrayState value, $Res Function(_TrayState) _then) = __$TrayStateCopyWithImpl; @override @useResult $Res call({ - Mode mode, int port, bool autoLaunch, bool systemProxy, bool tunEnable, bool isStart, List groups, Map selectedMap, bool showTrayTitle, bool safeMode, Map hotKeys + Mode mode, int port, bool autoLaunch, bool systemProxy, bool tunEnable, bool isStart, bool suspended, List groups, Map selectedMap, bool showTrayTitle, bool safeMode, Map hotKeys }); @@ -1408,7 +1410,7 @@ class __$TrayStateCopyWithImpl<$Res> /// Create a copy of TrayState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? mode = null,Object? port = null,Object? autoLaunch = null,Object? systemProxy = null,Object? tunEnable = null,Object? isStart = null,Object? groups = null,Object? selectedMap = null,Object? showTrayTitle = null,Object? safeMode = null,Object? hotKeys = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? mode = null,Object? port = null,Object? autoLaunch = null,Object? systemProxy = null,Object? tunEnable = null,Object? isStart = null,Object? suspended = null,Object? groups = null,Object? selectedMap = null,Object? showTrayTitle = null,Object? safeMode = null,Object? hotKeys = null,}) { return _then(_TrayState( mode: null == mode ? _self.mode : mode // ignore: cast_nullable_to_non_nullable as Mode,port: null == port ? _self.port : port // ignore: cast_nullable_to_non_nullable @@ -1416,6 +1418,7 @@ as int,autoLaunch: null == autoLaunch ? _self.autoLaunch : autoLaunch // ignore: as bool,systemProxy: null == systemProxy ? _self.systemProxy : systemProxy // ignore: cast_nullable_to_non_nullable as bool,tunEnable: null == tunEnable ? _self.tunEnable : tunEnable // ignore: cast_nullable_to_non_nullable as bool,isStart: null == isStart ? _self.isStart : isStart // ignore: cast_nullable_to_non_nullable +as bool,suspended: null == suspended ? _self.suspended : suspended // ignore: cast_nullable_to_non_nullable as bool,groups: null == groups ? _self._groups : groups // ignore: cast_nullable_to_non_nullable as List,selectedMap: null == selectedMap ? _self._selectedMap : selectedMap // ignore: cast_nullable_to_non_nullable as Map,showTrayTitle: null == showTrayTitle ? _self.showTrayTitle : showTrayTitle // ignore: cast_nullable_to_non_nullable @@ -5934,7 +5937,7 @@ $ProxiesDataCopyWith<$Res> get proxiesData { /// @nodoc mixin _$MakeRealProfileState { - String get profilesPath; int get profileId; Map get rawConfig; PatchClashConfig get realPatchConfig; ProfileOverrides get overrides;/// Set for a subscription, whose own DNS values an emptied entry replaces. + String get profilesPath; int get profileId; Map get rawConfig; PatchClashConfig get realPatchConfig; ProfileOverrides get overrides; bool get bypassPrivateRoute;/// Set for a subscription, whose own DNS values an emptied entry replaces. bool get keepEmptyDnsOverrides; bool get appendSystemDns; List get proxyGroups; List get rules; List get addedRules; String get defaultUA; List get authentication; Map get injectedProxyProviders; Map get injectedRuleProviders; String? get matchTarget; bool get safeMode; /// Create a copy of MakeRealProfileState /// with the given fields replaced by the non-null parameter values. @@ -5947,20 +5950,20 @@ $MakeRealProfileStateCopyWith get copyWith => _$MakeRealPr @override bool operator ==(Object other) { final _this = this as MakeRealProfileState; - return identical(this, other) || (other.runtimeType == runtimeType&&other is MakeRealProfileState&&(identical(other.profilesPath, _this.profilesPath) || other.profilesPath == _this.profilesPath)&&(identical(other.profileId, _this.profileId) || other.profileId == _this.profileId)&&const DeepCollectionEquality().equals(other.rawConfig, _this.rawConfig)&&(identical(other.realPatchConfig, _this.realPatchConfig) || other.realPatchConfig == _this.realPatchConfig)&&(identical(other.overrides, _this.overrides) || other.overrides == _this.overrides)&&(identical(other.keepEmptyDnsOverrides, _this.keepEmptyDnsOverrides) || other.keepEmptyDnsOverrides == _this.keepEmptyDnsOverrides)&&(identical(other.appendSystemDns, _this.appendSystemDns) || other.appendSystemDns == _this.appendSystemDns)&&const DeepCollectionEquality().equals(other.proxyGroups, _this.proxyGroups)&&const DeepCollectionEquality().equals(other.rules, _this.rules)&&const DeepCollectionEquality().equals(other.addedRules, _this.addedRules)&&(identical(other.defaultUA, _this.defaultUA) || other.defaultUA == _this.defaultUA)&&const DeepCollectionEquality().equals(other.authentication, _this.authentication)&&const DeepCollectionEquality().equals(other.injectedProxyProviders, _this.injectedProxyProviders)&&const DeepCollectionEquality().equals(other.injectedRuleProviders, _this.injectedRuleProviders)&&(identical(other.matchTarget, _this.matchTarget) || other.matchTarget == _this.matchTarget)&&(identical(other.safeMode, _this.safeMode) || other.safeMode == _this.safeMode)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is MakeRealProfileState&&(identical(other.profilesPath, _this.profilesPath) || other.profilesPath == _this.profilesPath)&&(identical(other.profileId, _this.profileId) || other.profileId == _this.profileId)&&const DeepCollectionEquality().equals(other.rawConfig, _this.rawConfig)&&(identical(other.realPatchConfig, _this.realPatchConfig) || other.realPatchConfig == _this.realPatchConfig)&&(identical(other.overrides, _this.overrides) || other.overrides == _this.overrides)&&(identical(other.bypassPrivateRoute, _this.bypassPrivateRoute) || other.bypassPrivateRoute == _this.bypassPrivateRoute)&&(identical(other.keepEmptyDnsOverrides, _this.keepEmptyDnsOverrides) || other.keepEmptyDnsOverrides == _this.keepEmptyDnsOverrides)&&(identical(other.appendSystemDns, _this.appendSystemDns) || other.appendSystemDns == _this.appendSystemDns)&&const DeepCollectionEquality().equals(other.proxyGroups, _this.proxyGroups)&&const DeepCollectionEquality().equals(other.rules, _this.rules)&&const DeepCollectionEquality().equals(other.addedRules, _this.addedRules)&&(identical(other.defaultUA, _this.defaultUA) || other.defaultUA == _this.defaultUA)&&const DeepCollectionEquality().equals(other.authentication, _this.authentication)&&const DeepCollectionEquality().equals(other.injectedProxyProviders, _this.injectedProxyProviders)&&const DeepCollectionEquality().equals(other.injectedRuleProviders, _this.injectedRuleProviders)&&(identical(other.matchTarget, _this.matchTarget) || other.matchTarget == _this.matchTarget)&&(identical(other.safeMode, _this.safeMode) || other.safeMode == _this.safeMode)); } @override int get hashCode { final _this = this as MakeRealProfileState; - return Object.hash(runtimeType,_this.profilesPath,_this.profileId,const DeepCollectionEquality().hash(_this.rawConfig),_this.realPatchConfig,_this.overrides,_this.keepEmptyDnsOverrides,_this.appendSystemDns,const DeepCollectionEquality().hash(_this.proxyGroups),const DeepCollectionEquality().hash(_this.rules),const DeepCollectionEquality().hash(_this.addedRules),_this.defaultUA,const DeepCollectionEquality().hash(_this.authentication),const DeepCollectionEquality().hash(_this.injectedProxyProviders),const DeepCollectionEquality().hash(_this.injectedRuleProviders),_this.matchTarget,_this.safeMode); + return Object.hash(runtimeType,_this.profilesPath,_this.profileId,const DeepCollectionEquality().hash(_this.rawConfig),_this.realPatchConfig,_this.overrides,_this.bypassPrivateRoute,_this.keepEmptyDnsOverrides,_this.appendSystemDns,const DeepCollectionEquality().hash(_this.proxyGroups),const DeepCollectionEquality().hash(_this.rules),const DeepCollectionEquality().hash(_this.addedRules),_this.defaultUA,const DeepCollectionEquality().hash(_this.authentication),const DeepCollectionEquality().hash(_this.injectedProxyProviders),const DeepCollectionEquality().hash(_this.injectedRuleProviders),_this.matchTarget,_this.safeMode); } @override String toString() { final _this = this as MakeRealProfileState; - return 'MakeRealProfileState(profilesPath: ${_this.profilesPath}, profileId: ${_this.profileId}, rawConfig: ${_this.rawConfig}, realPatchConfig: ${_this.realPatchConfig}, overrides: ${_this.overrides}, keepEmptyDnsOverrides: ${_this.keepEmptyDnsOverrides}, appendSystemDns: ${_this.appendSystemDns}, proxyGroups: ${_this.proxyGroups}, rules: ${_this.rules}, addedRules: ${_this.addedRules}, defaultUA: ${_this.defaultUA}, authentication: ${_this.authentication}, injectedProxyProviders: ${_this.injectedProxyProviders}, injectedRuleProviders: ${_this.injectedRuleProviders}, matchTarget: ${_this.matchTarget}, safeMode: ${_this.safeMode})'; + return 'MakeRealProfileState(profilesPath: ${_this.profilesPath}, profileId: ${_this.profileId}, rawConfig: ${_this.rawConfig}, realPatchConfig: ${_this.realPatchConfig}, overrides: ${_this.overrides}, bypassPrivateRoute: ${_this.bypassPrivateRoute}, keepEmptyDnsOverrides: ${_this.keepEmptyDnsOverrides}, appendSystemDns: ${_this.appendSystemDns}, proxyGroups: ${_this.proxyGroups}, rules: ${_this.rules}, addedRules: ${_this.addedRules}, defaultUA: ${_this.defaultUA}, authentication: ${_this.authentication}, injectedProxyProviders: ${_this.injectedProxyProviders}, injectedRuleProviders: ${_this.injectedRuleProviders}, matchTarget: ${_this.matchTarget}, safeMode: ${_this.safeMode})'; } @@ -5971,7 +5974,7 @@ abstract mixin class $MakeRealProfileStateCopyWith<$Res> { factory $MakeRealProfileStateCopyWith(MakeRealProfileState value, $Res Function(MakeRealProfileState) _then) = _$MakeRealProfileStateCopyWithImpl; @useResult $Res call({ - String profilesPath, int profileId, Map rawConfig, PatchClashConfig realPatchConfig, ProfileOverrides overrides, bool keepEmptyDnsOverrides, bool appendSystemDns, List proxyGroups, List rules, List addedRules, String defaultUA, List authentication, Map injectedProxyProviders, Map injectedRuleProviders, String? matchTarget, bool safeMode + String profilesPath, int profileId, Map rawConfig, PatchClashConfig realPatchConfig, ProfileOverrides overrides, bool bypassPrivateRoute, bool keepEmptyDnsOverrides, bool appendSystemDns, List proxyGroups, List rules, List addedRules, String defaultUA, List authentication, Map injectedProxyProviders, Map injectedRuleProviders, String? matchTarget, bool safeMode }); @@ -5988,14 +5991,15 @@ class _$MakeRealProfileStateCopyWithImpl<$Res> /// Create a copy of MakeRealProfileState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? profilesPath = null,Object? profileId = null,Object? rawConfig = null,Object? realPatchConfig = null,Object? overrides = null,Object? keepEmptyDnsOverrides = null,Object? appendSystemDns = null,Object? proxyGroups = null,Object? rules = null,Object? addedRules = null,Object? defaultUA = null,Object? authentication = null,Object? injectedProxyProviders = null,Object? injectedRuleProviders = null,Object? matchTarget = freezed,Object? safeMode = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? profilesPath = null,Object? profileId = null,Object? rawConfig = null,Object? realPatchConfig = null,Object? overrides = null,Object? bypassPrivateRoute = null,Object? keepEmptyDnsOverrides = null,Object? appendSystemDns = null,Object? proxyGroups = null,Object? rules = null,Object? addedRules = null,Object? defaultUA = null,Object? authentication = null,Object? injectedProxyProviders = null,Object? injectedRuleProviders = null,Object? matchTarget = freezed,Object? safeMode = null,}) { return _then(MakeRealProfileState( profilesPath: null == profilesPath ? _self.profilesPath : profilesPath // ignore: cast_nullable_to_non_nullable as String,profileId: null == profileId ? _self.profileId : profileId // ignore: cast_nullable_to_non_nullable as int,rawConfig: null == rawConfig ? _self.rawConfig : rawConfig // ignore: cast_nullable_to_non_nullable as Map,realPatchConfig: null == realPatchConfig ? _self.realPatchConfig : realPatchConfig // ignore: cast_nullable_to_non_nullable as PatchClashConfig,overrides: null == overrides ? _self.overrides : overrides // ignore: cast_nullable_to_non_nullable -as ProfileOverrides,keepEmptyDnsOverrides: null == keepEmptyDnsOverrides ? _self.keepEmptyDnsOverrides : keepEmptyDnsOverrides // ignore: cast_nullable_to_non_nullable +as ProfileOverrides,bypassPrivateRoute: null == bypassPrivateRoute ? _self.bypassPrivateRoute : bypassPrivateRoute // ignore: cast_nullable_to_non_nullable +as bool,keepEmptyDnsOverrides: null == keepEmptyDnsOverrides ? _self.keepEmptyDnsOverrides : keepEmptyDnsOverrides // ignore: cast_nullable_to_non_nullable as bool,appendSystemDns: null == appendSystemDns ? _self.appendSystemDns : appendSystemDns // ignore: cast_nullable_to_non_nullable as bool,proxyGroups: null == proxyGroups ? _self.proxyGroups : proxyGroups // ignore: cast_nullable_to_non_nullable as List,rules: null == rules ? _self.rules : rules // ignore: cast_nullable_to_non_nullable @@ -6109,10 +6113,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String profilesPath, int profileId, Map rawConfig, PatchClashConfig realPatchConfig, ProfileOverrides overrides, bool keepEmptyDnsOverrides, bool appendSystemDns, List proxyGroups, List rules, List addedRules, String defaultUA, List authentication, Map injectedProxyProviders, Map injectedRuleProviders, String? matchTarget, bool safeMode)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String profilesPath, int profileId, Map rawConfig, PatchClashConfig realPatchConfig, ProfileOverrides overrides, bool bypassPrivateRoute, bool keepEmptyDnsOverrides, bool appendSystemDns, List proxyGroups, List rules, List addedRules, String defaultUA, List authentication, Map injectedProxyProviders, Map injectedRuleProviders, String? matchTarget, bool safeMode)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _MakeRealProfileState() when $default != null: -return $default(_that.profilesPath,_that.profileId,_that.rawConfig,_that.realPatchConfig,_that.overrides,_that.keepEmptyDnsOverrides,_that.appendSystemDns,_that.proxyGroups,_that.rules,_that.addedRules,_that.defaultUA,_that.authentication,_that.injectedProxyProviders,_that.injectedRuleProviders,_that.matchTarget,_that.safeMode);case _: +return $default(_that.profilesPath,_that.profileId,_that.rawConfig,_that.realPatchConfig,_that.overrides,_that.bypassPrivateRoute,_that.keepEmptyDnsOverrides,_that.appendSystemDns,_that.proxyGroups,_that.rules,_that.addedRules,_that.defaultUA,_that.authentication,_that.injectedProxyProviders,_that.injectedRuleProviders,_that.matchTarget,_that.safeMode);case _: return orElse(); } @@ -6130,10 +6134,10 @@ return $default(_that.profilesPath,_that.profileId,_that.rawConfig,_that.realPat /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String profilesPath, int profileId, Map rawConfig, PatchClashConfig realPatchConfig, ProfileOverrides overrides, bool keepEmptyDnsOverrides, bool appendSystemDns, List proxyGroups, List rules, List addedRules, String defaultUA, List authentication, Map injectedProxyProviders, Map injectedRuleProviders, String? matchTarget, bool safeMode) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String profilesPath, int profileId, Map rawConfig, PatchClashConfig realPatchConfig, ProfileOverrides overrides, bool bypassPrivateRoute, bool keepEmptyDnsOverrides, bool appendSystemDns, List proxyGroups, List rules, List addedRules, String defaultUA, List authentication, Map injectedProxyProviders, Map injectedRuleProviders, String? matchTarget, bool safeMode) $default,) {final _that = this; switch (_that) { case _MakeRealProfileState(): -return $default(_that.profilesPath,_that.profileId,_that.rawConfig,_that.realPatchConfig,_that.overrides,_that.keepEmptyDnsOverrides,_that.appendSystemDns,_that.proxyGroups,_that.rules,_that.addedRules,_that.defaultUA,_that.authentication,_that.injectedProxyProviders,_that.injectedRuleProviders,_that.matchTarget,_that.safeMode);case _: +return $default(_that.profilesPath,_that.profileId,_that.rawConfig,_that.realPatchConfig,_that.overrides,_that.bypassPrivateRoute,_that.keepEmptyDnsOverrides,_that.appendSystemDns,_that.proxyGroups,_that.rules,_that.addedRules,_that.defaultUA,_that.authentication,_that.injectedProxyProviders,_that.injectedRuleProviders,_that.matchTarget,_that.safeMode);case _: throw StateError('Unexpected subclass'); } @@ -6150,10 +6154,10 @@ return $default(_that.profilesPath,_that.profileId,_that.rawConfig,_that.realPat /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String profilesPath, int profileId, Map rawConfig, PatchClashConfig realPatchConfig, ProfileOverrides overrides, bool keepEmptyDnsOverrides, bool appendSystemDns, List proxyGroups, List rules, List addedRules, String defaultUA, List authentication, Map injectedProxyProviders, Map injectedRuleProviders, String? matchTarget, bool safeMode)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String profilesPath, int profileId, Map rawConfig, PatchClashConfig realPatchConfig, ProfileOverrides overrides, bool bypassPrivateRoute, bool keepEmptyDnsOverrides, bool appendSystemDns, List proxyGroups, List rules, List addedRules, String defaultUA, List authentication, Map injectedProxyProviders, Map injectedRuleProviders, String? matchTarget, bool safeMode)? $default,) {final _that = this; switch (_that) { case _MakeRealProfileState() when $default != null: -return $default(_that.profilesPath,_that.profileId,_that.rawConfig,_that.realPatchConfig,_that.overrides,_that.keepEmptyDnsOverrides,_that.appendSystemDns,_that.proxyGroups,_that.rules,_that.addedRules,_that.defaultUA,_that.authentication,_that.injectedProxyProviders,_that.injectedRuleProviders,_that.matchTarget,_that.safeMode);case _: +return $default(_that.profilesPath,_that.profileId,_that.rawConfig,_that.realPatchConfig,_that.overrides,_that.bypassPrivateRoute,_that.keepEmptyDnsOverrides,_that.appendSystemDns,_that.proxyGroups,_that.rules,_that.addedRules,_that.defaultUA,_that.authentication,_that.injectedProxyProviders,_that.injectedRuleProviders,_that.matchTarget,_that.safeMode);case _: return null; } @@ -6165,7 +6169,7 @@ return $default(_that.profilesPath,_that.profileId,_that.rawConfig,_that.realPat class _MakeRealProfileState implements MakeRealProfileState { - const _MakeRealProfileState({required this.profilesPath, required this.profileId, required Map rawConfig, required this.realPatchConfig, this.overrides = const ProfileOverrides(), this.keepEmptyDnsOverrides = false, required this.appendSystemDns, required List proxyGroups, required List rules, required List addedRules, required this.defaultUA, List authentication = const [], Map injectedProxyProviders = const {}, Map injectedRuleProviders = const {}, this.matchTarget, this.safeMode = false}): _rawConfig = rawConfig,_proxyGroups = proxyGroups,_rules = rules,_addedRules = addedRules,_authentication = authentication,_injectedProxyProviders = injectedProxyProviders,_injectedRuleProviders = injectedRuleProviders; + const _MakeRealProfileState({required this.profilesPath, required this.profileId, required Map rawConfig, required this.realPatchConfig, this.overrides = const ProfileOverrides(), this.bypassPrivateRoute = false, this.keepEmptyDnsOverrides = false, required this.appendSystemDns, required List proxyGroups, required List rules, required List addedRules, required this.defaultUA, List authentication = const [], Map injectedProxyProviders = const {}, Map injectedRuleProviders = const {}, this.matchTarget, this.safeMode = false}): _rawConfig = rawConfig,_proxyGroups = proxyGroups,_rules = rules,_addedRules = addedRules,_authentication = authentication,_injectedProxyProviders = injectedProxyProviders,_injectedRuleProviders = injectedRuleProviders; @override final String profilesPath; @@ -6179,6 +6183,7 @@ class _MakeRealProfileState implements MakeRealProfileState { @override final PatchClashConfig realPatchConfig; @override@JsonKey() final ProfileOverrides overrides; +@override@JsonKey() final bool bypassPrivateRoute; /// Set for a subscription, whose own DNS values an emptied entry replaces. @override@JsonKey() final bool keepEmptyDnsOverrides; @override final bool appendSystemDns; @@ -6238,18 +6243,18 @@ _$MakeRealProfileStateCopyWith<_MakeRealProfileState> get copyWith => __$MakeRea @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _MakeRealProfileState&&(identical(other.profilesPath, profilesPath) || other.profilesPath == profilesPath)&&(identical(other.profileId, profileId) || other.profileId == profileId)&&const DeepCollectionEquality().equals(other.rawConfig, _rawConfig)&&(identical(other.realPatchConfig, realPatchConfig) || other.realPatchConfig == realPatchConfig)&&(identical(other.overrides, overrides) || other.overrides == overrides)&&(identical(other.keepEmptyDnsOverrides, keepEmptyDnsOverrides) || other.keepEmptyDnsOverrides == keepEmptyDnsOverrides)&&(identical(other.appendSystemDns, appendSystemDns) || other.appendSystemDns == appendSystemDns)&&const DeepCollectionEquality().equals(other.proxyGroups, _proxyGroups)&&const DeepCollectionEquality().equals(other.rules, _rules)&&const DeepCollectionEquality().equals(other.addedRules, _addedRules)&&(identical(other.defaultUA, defaultUA) || other.defaultUA == defaultUA)&&const DeepCollectionEquality().equals(other.authentication, _authentication)&&const DeepCollectionEquality().equals(other.injectedProxyProviders, _injectedProxyProviders)&&const DeepCollectionEquality().equals(other.injectedRuleProviders, _injectedRuleProviders)&&(identical(other.matchTarget, matchTarget) || other.matchTarget == matchTarget)&&(identical(other.safeMode, safeMode) || other.safeMode == safeMode)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _MakeRealProfileState&&(identical(other.profilesPath, profilesPath) || other.profilesPath == profilesPath)&&(identical(other.profileId, profileId) || other.profileId == profileId)&&const DeepCollectionEquality().equals(other.rawConfig, _rawConfig)&&(identical(other.realPatchConfig, realPatchConfig) || other.realPatchConfig == realPatchConfig)&&(identical(other.overrides, overrides) || other.overrides == overrides)&&(identical(other.bypassPrivateRoute, bypassPrivateRoute) || other.bypassPrivateRoute == bypassPrivateRoute)&&(identical(other.keepEmptyDnsOverrides, keepEmptyDnsOverrides) || other.keepEmptyDnsOverrides == keepEmptyDnsOverrides)&&(identical(other.appendSystemDns, appendSystemDns) || other.appendSystemDns == appendSystemDns)&&const DeepCollectionEquality().equals(other.proxyGroups, _proxyGroups)&&const DeepCollectionEquality().equals(other.rules, _rules)&&const DeepCollectionEquality().equals(other.addedRules, _addedRules)&&(identical(other.defaultUA, defaultUA) || other.defaultUA == defaultUA)&&const DeepCollectionEquality().equals(other.authentication, _authentication)&&const DeepCollectionEquality().equals(other.injectedProxyProviders, _injectedProxyProviders)&&const DeepCollectionEquality().equals(other.injectedRuleProviders, _injectedRuleProviders)&&(identical(other.matchTarget, matchTarget) || other.matchTarget == matchTarget)&&(identical(other.safeMode, safeMode) || other.safeMode == safeMode)); } @override int get hashCode { - return Object.hash(runtimeType,profilesPath,profileId,const DeepCollectionEquality().hash(_rawConfig),realPatchConfig,overrides,keepEmptyDnsOverrides,appendSystemDns,const DeepCollectionEquality().hash(_proxyGroups),const DeepCollectionEquality().hash(_rules),const DeepCollectionEquality().hash(_addedRules),defaultUA,const DeepCollectionEquality().hash(_authentication),const DeepCollectionEquality().hash(_injectedProxyProviders),const DeepCollectionEquality().hash(_injectedRuleProviders),matchTarget,safeMode); + return Object.hash(runtimeType,profilesPath,profileId,const DeepCollectionEquality().hash(_rawConfig),realPatchConfig,overrides,bypassPrivateRoute,keepEmptyDnsOverrides,appendSystemDns,const DeepCollectionEquality().hash(_proxyGroups),const DeepCollectionEquality().hash(_rules),const DeepCollectionEquality().hash(_addedRules),defaultUA,const DeepCollectionEquality().hash(_authentication),const DeepCollectionEquality().hash(_injectedProxyProviders),const DeepCollectionEquality().hash(_injectedRuleProviders),matchTarget,safeMode); } @override String toString() { - return 'MakeRealProfileState(profilesPath: $profilesPath, profileId: $profileId, rawConfig: $rawConfig, realPatchConfig: $realPatchConfig, overrides: $overrides, keepEmptyDnsOverrides: $keepEmptyDnsOverrides, appendSystemDns: $appendSystemDns, proxyGroups: $proxyGroups, rules: $rules, addedRules: $addedRules, defaultUA: $defaultUA, authentication: $authentication, injectedProxyProviders: $injectedProxyProviders, injectedRuleProviders: $injectedRuleProviders, matchTarget: $matchTarget, safeMode: $safeMode)'; + return 'MakeRealProfileState(profilesPath: $profilesPath, profileId: $profileId, rawConfig: $rawConfig, realPatchConfig: $realPatchConfig, overrides: $overrides, bypassPrivateRoute: $bypassPrivateRoute, keepEmptyDnsOverrides: $keepEmptyDnsOverrides, appendSystemDns: $appendSystemDns, proxyGroups: $proxyGroups, rules: $rules, addedRules: $addedRules, defaultUA: $defaultUA, authentication: $authentication, injectedProxyProviders: $injectedProxyProviders, injectedRuleProviders: $injectedRuleProviders, matchTarget: $matchTarget, safeMode: $safeMode)'; } @@ -6260,7 +6265,7 @@ abstract mixin class _$MakeRealProfileStateCopyWith<$Res> implements $MakeRealPr factory _$MakeRealProfileStateCopyWith(_MakeRealProfileState value, $Res Function(_MakeRealProfileState) _then) = __$MakeRealProfileStateCopyWithImpl; @override @useResult $Res call({ - String profilesPath, int profileId, Map rawConfig, PatchClashConfig realPatchConfig, ProfileOverrides overrides, bool keepEmptyDnsOverrides, bool appendSystemDns, List proxyGroups, List rules, List addedRules, String defaultUA, List authentication, Map injectedProxyProviders, Map injectedRuleProviders, String? matchTarget, bool safeMode + String profilesPath, int profileId, Map rawConfig, PatchClashConfig realPatchConfig, ProfileOverrides overrides, bool bypassPrivateRoute, bool keepEmptyDnsOverrides, bool appendSystemDns, List proxyGroups, List rules, List addedRules, String defaultUA, List authentication, Map injectedProxyProviders, Map injectedRuleProviders, String? matchTarget, bool safeMode }); @@ -6277,14 +6282,15 @@ class __$MakeRealProfileStateCopyWithImpl<$Res> /// Create a copy of MakeRealProfileState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? profilesPath = null,Object? profileId = null,Object? rawConfig = null,Object? realPatchConfig = null,Object? overrides = null,Object? keepEmptyDnsOverrides = null,Object? appendSystemDns = null,Object? proxyGroups = null,Object? rules = null,Object? addedRules = null,Object? defaultUA = null,Object? authentication = null,Object? injectedProxyProviders = null,Object? injectedRuleProviders = null,Object? matchTarget = freezed,Object? safeMode = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? profilesPath = null,Object? profileId = null,Object? rawConfig = null,Object? realPatchConfig = null,Object? overrides = null,Object? bypassPrivateRoute = null,Object? keepEmptyDnsOverrides = null,Object? appendSystemDns = null,Object? proxyGroups = null,Object? rules = null,Object? addedRules = null,Object? defaultUA = null,Object? authentication = null,Object? injectedProxyProviders = null,Object? injectedRuleProviders = null,Object? matchTarget = freezed,Object? safeMode = null,}) { return _then(_MakeRealProfileState( profilesPath: null == profilesPath ? _self.profilesPath : profilesPath // ignore: cast_nullable_to_non_nullable as String,profileId: null == profileId ? _self.profileId : profileId // ignore: cast_nullable_to_non_nullable as int,rawConfig: null == rawConfig ? _self._rawConfig : rawConfig // ignore: cast_nullable_to_non_nullable as Map,realPatchConfig: null == realPatchConfig ? _self.realPatchConfig : realPatchConfig // ignore: cast_nullable_to_non_nullable as PatchClashConfig,overrides: null == overrides ? _self.overrides : overrides // ignore: cast_nullable_to_non_nullable -as ProfileOverrides,keepEmptyDnsOverrides: null == keepEmptyDnsOverrides ? _self.keepEmptyDnsOverrides : keepEmptyDnsOverrides // ignore: cast_nullable_to_non_nullable +as ProfileOverrides,bypassPrivateRoute: null == bypassPrivateRoute ? _self.bypassPrivateRoute : bypassPrivateRoute // ignore: cast_nullable_to_non_nullable +as bool,keepEmptyDnsOverrides: null == keepEmptyDnsOverrides ? _self.keepEmptyDnsOverrides : keepEmptyDnsOverrides // ignore: cast_nullable_to_non_nullable as bool,appendSystemDns: null == appendSystemDns ? _self.appendSystemDns : appendSystemDns // ignore: cast_nullable_to_non_nullable as bool,proxyGroups: null == proxyGroups ? _self._proxyGroups : proxyGroups // ignore: cast_nullable_to_non_nullable as List,rules: null == rules ? _self._rules : rules // ignore: cast_nullable_to_non_nullable diff --git a/lib/models/state.dart b/lib/models/state.dart index ad42a809..e025b32d 100644 --- a/lib/models/state.dart +++ b/lib/models/state.dart @@ -53,6 +53,7 @@ abstract class TrayState with _$TrayState { required bool systemProxy, required bool tunEnable, required bool isStart, + @Default(false) bool suspended, required List groups, required Map selectedMap, required bool showTrayTitle, @@ -218,6 +219,7 @@ abstract class MakeRealProfileState with _$MakeRealProfileState { required Map rawConfig, required PatchClashConfig realPatchConfig, @Default(ProfileOverrides()) ProfileOverrides overrides, + @Default(false) bool bypassPrivateRoute, /// Set for a subscription, whose own DNS values an emptied entry replaces. @Default(false) bool keepEmptyDnsOverrides, diff --git a/lib/providers/actions/setup.dart b/lib/providers/actions/setup.dart index 8b9c08c4..4df54712 100644 --- a/lib/providers/actions/setup.dart +++ b/lib/providers/actions/setup.dart @@ -319,7 +319,6 @@ class SetupAction extends _$SetupAction { final networkSetting = ref.read(networkSettingProvider); final message = await _core.updateConfig( _effectivePatchConfig(patchConfig).toUpdateParams( - bypassPrivateRoute: networkSetting.bypassPrivateRoute, authentication: networkSetting.authentication.credentials, skipCertVerify: !ref.read(appSettingProvider).checkCertificate, ), @@ -473,11 +472,6 @@ class SetupAction extends _$SetupAction { if (hasScript) { rawConfig = await handleEvaluate(scriptContent!, rawConfig); } - final realPatchConfig = patchConfig.copyWith( - tun: patchConfig.tun.getRealTun( - bypassPrivateRoute: networkSetting.bypassPrivateRoute, - ), - ); final directory = await appPath.profilesPath; final injected = await _resolveInjectedProviders( setupState, @@ -493,8 +487,9 @@ class SetupAction extends _$SetupAction { profilesPath: directory, profileId: profileId, rawConfig: rawConfig, - realPatchConfig: realPatchConfig, + realPatchConfig: patchConfig, overrides: setupState.overrides, + bypassPrivateRoute: networkSetting.bypassPrivateRoute, keepEmptyDnsOverrides: setupState.profileType != ProfileType.custom, appendSystemDns: appendSystemDns, addedRules: setupState.addedRules, @@ -723,6 +718,7 @@ class SetupAction extends _$SetupAction { // has no proxies, so until this push succeeds no applied config is known. _appliedInputs = null; globalState.lastConfigMd5 = null; + globalState.lastConfigCounts = null; if (system.isAndroid) { await ref.read(vpnOptionsProvider.future); await preferences.saveShareState(ref.read(sharedStateProvider)); @@ -746,6 +742,7 @@ class SetupAction extends _$SetupAction { preloadInvoke: preloadInvoke, ); if (message.isNotEmpty) { + globalState.lastConfigCounts = configCountsOf(const {}); await globalState.safeRun(() => onUpdated?.call()); throw MessageException(message); } diff --git a/lib/providers/actions/system.dart b/lib/providers/actions/system.dart index 96e90a0c..037f40b6 100644 --- a/lib/providers/actions/system.dart +++ b/lib/providers/actions/system.dart @@ -51,7 +51,7 @@ class SystemAction extends _$SystemAction { ?saveOperation, bootGuard.markClosed(), if (systemDnsCoordinator != null) systemDnsCoordinator!.shutdown(), - if (proxy != null) proxy!.stopProxy(), + ?systemProxyQueue?.close(), ]); } diff --git a/lib/providers/generated/state.g.dart b/lib/providers/generated/state.g.dart index f5769e84..5d25fee6 100644 --- a/lib/providers/generated/state.g.dart +++ b/lib/providers/generated/state.g.dart @@ -48,7 +48,7 @@ final class UpdateParamsProvider } } -String _$updateParamsHash() => r'7b4c3cb2b45e7cd33dd2c57dc65c5067011438ff'; +String _$updateParamsHash() => r'e46998c222b0902ef6a76c25fe83c094a6369036'; @ProviderFor(setupPatch) final setupPatchProvider = SetupPatchProvider._(); @@ -56,11 +56,30 @@ final setupPatchProvider = SetupPatchProvider._(); final class SetupPatchProvider extends $FunctionalProvider< - ({bool appendSystemDns, PatchClashConfig patchConfig}), - ({bool appendSystemDns, PatchClashConfig patchConfig}), - ({bool appendSystemDns, PatchClashConfig patchConfig}) + ({ + bool appendSystemDns, + bool bypassPrivateRoute, + PatchClashConfig patchConfig, + }), + ({ + bool appendSystemDns, + bool bypassPrivateRoute, + PatchClashConfig patchConfig, + }), + ({ + bool appendSystemDns, + bool bypassPrivateRoute, + PatchClashConfig patchConfig, + }) > - with $Provider<({bool appendSystemDns, PatchClashConfig patchConfig})> { + with + $Provider< + ({ + bool appendSystemDns, + bool bypassPrivateRoute, + PatchClashConfig patchConfig, + }) + > { SetupPatchProvider._() : super( from: null, @@ -77,29 +96,49 @@ final class SetupPatchProvider @$internal @override - $ProviderElement<({bool appendSystemDns, PatchClashConfig patchConfig})> + $ProviderElement< + ({ + bool appendSystemDns, + bool bypassPrivateRoute, + PatchClashConfig patchConfig, + }) + > $createElement($ProviderPointer pointer) => $ProviderElement(pointer); @override - ({bool appendSystemDns, PatchClashConfig patchConfig}) create(Ref ref) { + ({ + bool appendSystemDns, + bool bypassPrivateRoute, + PatchClashConfig patchConfig, + }) + create(Ref ref) { return setupPatch(ref); } /// {@macro riverpod.override_with_value} Override overrideWithValue( - ({bool appendSystemDns, PatchClashConfig patchConfig}) value, + ({ + bool appendSystemDns, + bool bypassPrivateRoute, + PatchClashConfig patchConfig, + }) + value, ) { return $ProviderOverride( origin: this, providerOverride: $SyncValueProvider< - ({bool appendSystemDns, PatchClashConfig patchConfig}) + ({ + bool appendSystemDns, + bool bypassPrivateRoute, + PatchClashConfig patchConfig, + }) >(value), ); } } -String _$setupPatchHash() => r'64d8f97c3b7f367ab0065f9b1d606beb5e6b5ebf'; +String _$setupPatchHash() => r'd09fb41d40ced4cd47c9131fe55e983e35128724'; @ProviderFor(trayState) final trayStateProvider = TrayStateProvider._(); @@ -140,7 +179,7 @@ final class TrayStateProvider } } -String _$trayStateHash() => r'e3e841e2d6ae95e4eafe27996c7da33f82edcc80'; +String _$trayStateHash() => r'b7da57e41143cd8c284260d33b368b1be044bd01'; /// Measured delays of the proxies the tray lists, by group and then proxy /// name. Resolved like a proxy card, so a nested group shows its selection. @@ -3417,7 +3456,7 @@ final class SetupStateProvider } } -String _$setupStateHash() => r'aa74b203b75682d0dbe067377d985378adb63709'; +String _$setupStateHash() => r'eef9f0d2ec0ecb6196c699b1e2c2a73d922f8964'; final class SetupStateFamily extends $Family with $FunctionalFamilyOverride, int?> { diff --git a/lib/providers/state/profile.dart b/lib/providers/state/profile.dart index f8f6ede8..641c926a 100644 --- a/lib/providers/state/profile.dart +++ b/lib/providers/state/profile.dart @@ -51,7 +51,12 @@ Future setupState(Ref ref, int? profileId) async { final profileType = profile?.type ?? ProfileType.file; final extendType = profile?.extendType ?? ExtendType.standard; final overrides = profileType == ProfileType.custom - ? profile?.overrides ?? const ProfileOverrides() + ? ref.watch( + patchClashConfigProvider.select( + (state) => (profile?.overrides ?? const ProfileOverrides()) + .overAppTun(state.tunOverride, state.tunOverrideKeys), + ), + ) : ref.watch( patchClashConfigProvider.select( (state) => ProfileOverrides( @@ -59,6 +64,8 @@ Future setupState(Ref ref, int? profileId) async { dnsOverrideKeys: state.dnsOverrideKeys.intersection( DnsOverrideKey.normalProfileKeys, ), + tun: state.tunOverride, + tunOverrideKeys: state.tunOverrideKeys, ), ), ); diff --git a/lib/providers/state/system.dart b/lib/providers/state/system.dart index 088f08b4..e8d5a6a6 100644 --- a/lib/providers/state/system.dart +++ b/lib/providers/state/system.dart @@ -2,9 +2,6 @@ part of '../state.dart'; @riverpod UpdateParams updateParams(Ref ref) { - final bypassPrivateRoute = ref.watch( - networkSettingProvider.select((state) => state.bypassPrivateRoute), - ); final authentication = ref.watch( networkSettingProvider.select((state) => state.authentication), ); @@ -14,7 +11,6 @@ UpdateParams updateParams(Ref ref) { return ref.watch( patchClashConfigProvider.select( (state) => state.toUpdateParams( - bypassPrivateRoute: bypassPrivateRoute, authentication: authentication.credentials, skipCertVerify: !checkCertificate, ), @@ -23,7 +19,8 @@ UpdateParams updateParams(Ref ref) { } @riverpod -({PatchClashConfig patchConfig, bool appendSystemDns}) setupPatch(Ref ref) { +({PatchClashConfig patchConfig, bool appendSystemDns, bool bypassPrivateRoute}) +setupPatch(Ref ref) { return ( patchConfig: ref.watch( patchClashConfigProvider.select((state) => state.setupOnly), @@ -31,6 +28,12 @@ UpdateParams updateParams(Ref ref) { appendSystemDns: ref.watch( networkSettingProvider.select((state) => state.appendSystemDns), ), + // Android's VPN service takes it on its next start instead. + bypassPrivateRoute: + system.isDesktop && + ref.watch( + networkSettingProvider.select((state) => state.bypassPrivateRoute), + ), ); } @@ -58,6 +61,7 @@ TrayState trayState(Ref ref) { final groups = ref.watch(currentGroupsStateProvider).value; final selectedMap = ref.watch(selectedMapProvider); final safeMode = ref.watch(safeModeProvider); + final suspended = ref.watch(suspendProvider); final hotKeys = _trayHotKeys(ref); return TrayState( @@ -67,6 +71,7 @@ TrayState trayState(Ref ref) { systemProxy: systemProxy, tunEnable: clashConfig.tunEnable, isStart: isStart, + suspended: isStart && suspended, groups: groups, selectedMap: selectedMap, showTrayTitle: appSetting.showTrayTitle, diff --git a/lib/views/config/network.dart b/lib/views/config/network.dart index ef5380ea..0b21f241 100644 --- a/lib/views/config/network.dart +++ b/lib/views/config/network.dart @@ -2,8 +2,11 @@ import 'dart:io'; import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/enum/enum.dart'; +import 'package:fl_clash/features/form/form.dart'; import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/providers/config.dart'; +import 'package:fl_clash/views/config/override.dart'; +import 'package:fl_clash/views/config/tun.dart'; import 'package:fl_clash/widgets/widgets.dart'; import 'package:material_ui/material_ui.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -286,14 +289,6 @@ class LoopbackItem extends StatelessWidget { const _maxUint32 = 0xFFFFFFFF; -// The congestion controls mipstack registers, cubic first as its default. -const _congestionControllers = [ - defaultCongestionController, - 'reno', - 'bbr', - 'bbr3', -]; - class _NumberItem extends ConsumerWidget { const _NumberItem({ required this.title, @@ -348,11 +343,9 @@ class _NumberItem extends ConsumerWidget { } } -List tunItems({ - required bool isLinux, - required bool isWindows, - required bool isMipsStack, -}) { +// Android's VPN service starts from these rows; the desktop TUN takes the +// same keys as overrides, so a profile's own values apply unless picked. +List tunItems({required bool isMipsStack}) { return [ _NumberItem( title: (l) => 'MTU', @@ -364,7 +357,7 @@ List tunItems({ if (isMipsStack) ConfigOptionsItem( title: (l) => l.congestionController, - options: _congestionControllers, + options: congestionControllers, textBuilder: (value) => value, selector: patchClashConfigProvider.select( (state) => state.tun.congestionController, @@ -373,16 +366,6 @@ List tunItems({ (state, value) => state.copyWith.tun(congestionController: value), ), ), - if (isLinux || isWindows) - ConfigToggleItem( - title: (l) => l.strictRoute, - selector: patchClashConfigProvider.select( - (state) => state.tun.strictRoute, - ), - onChanged: _tunWriter( - (state, value) => state.copyWith.tun(strictRoute: value), - ), - ), const BypassPrivateRouteItem(), const RouteAddressItem(), ConfigListEditItem( @@ -400,27 +383,60 @@ List tunItems({ } class TunSection extends ConsumerWidget { - const TunSection({super.key}); + const TunSection({ + super.key, + required this.isDesktop, + required this.isLinux, + required this.isWindows, + }); + + final bool isDesktop; + final bool isLinux; + final bool isWindows; @override Widget build(BuildContext context, WidgetRef ref) { - final isMipsStack = ref.watch( - patchClashConfigProvider.select( - (state) => state.tun.stack == TunStack.mips, - ), - ); final appLocalizations = context.appLocalizations; - return generateSection( + if (!isDesktop) { + final isMipsStack = ref.watch( + patchClashConfigProvider.select( + (state) => state.tun.stack == TunStack.mips, + ), + ); + return generateSection( + title: appLocalizations.tun, + items: tunItems(isMipsStack: isMipsStack), + footer: appLocalizations.bypassPrivateRouteDesc, + ); + } + final spec = appTunOverrideSpec(isLinux: isLinux, isWindows: isWindows); + final picked = ref.watch( + patchClashConfigProvider.select((state) => state.tunOverrideKeys), + ); + final listed = [ + for (final key in spec.values) + if (picked.contains(key)) key, + ]; + void handleAdd() => showOverrideAddSheet(context, ref, spec); + return generateAnimatedSection( title: appLocalizations.tun, - items: tunItems( - isLinux: system.isLinux, - isWindows: system.isWindows, - isMipsStack: isMipsStack, - ), + items: [ + const BypassPrivateRouteItem(key: ValueKey(#bypassPrivateRoute)), + for (final key in listed) + OverrideEntry(key: ValueKey(key), spec: spec, overrideKey: key), + if (listed.length < spec.values.length) + FormRow( + key: const ValueKey(#add), + leading: EntryButton.add(onPressed: handleAdd), + title: spec.target.addEntry(appLocalizations), + titleStyle: TextStyle(color: context.colorScheme.primary), + onPressed: handleAdd, + ), + ], footer: [ - if (system.isLinux || system.isWindows) - appLocalizations.strictRouteDesc, appLocalizations.bypassPrivateRouteDesc, + appLocalizations.tunOverrideDesc, + ?spec.footerOf(listed, appLocalizations), ].join('\n'), ); } @@ -577,7 +593,11 @@ class NetworkListView extends StatelessWidget { if (system.isAndroid) const VpnSections(), if (system.isDesktop) const SystemProxySection(), const NetworkOptionsSection(), - const TunSection(), + TunSection( + isDesktop: system.isDesktop, + isLinux: system.isLinux, + isWindows: system.isWindows, + ), generateSection( title: context.appLocalizations.outbound, items: outboundItems( diff --git a/lib/views/config/override.dart b/lib/views/config/override.dart index 8ece88eb..b2b17e86 100644 --- a/lib/views/config/override.dart +++ b/lib/views/config/override.dart @@ -116,7 +116,8 @@ class ProfileOverrideTarget required this.get, required this.set, this.issues, - }); + ConfigLabel? description, + }) : _description = description; final int profileId; @@ -129,9 +130,13 @@ class ProfileOverrideTarget ) set; + final ConfigLabel? _description; + @override - ConfigLabel get description => - (l) => l.profileSettingsDesc; + ConfigLabel get description => _description ?? _profileSettingsDesc; + + static String _profileSettingsDesc(AppLocalizations l) => + l.profileSettingsDesc; @override ConfigLabel get entries => @@ -210,18 +215,19 @@ class ToggleOverrideField extends ValueOverrideField { } } -class OptionsOverrideField extends ValueOverrideField { +class OptionsOverrideField + extends ValueOverrideField { const OptionsOverrideField( this.options, super.select, super.update, { - this.labelOf = _enumName, + this.labelOf = _nameOf, }); final List options; final String Function(T value) labelOf; - static String _enumName(Enum value) => value.name; + static String _nameOf(Object value) => value is Enum ? value.name : '$value'; @override Widget build( @@ -375,6 +381,11 @@ abstract class OverrideSpec { return (model: model, keys: state.keys.difference(keys)); } + String? footerOf(Iterable keys, AppLocalizations l) { + final lines = [for (final key in keys) ?description(key)?.call(l)]; + return lines.isEmpty ? null : lines.join('\n'); + } + List<(String, List)> sectionsOf(AppLocalizations l, Iterable keys) { final sections = >{}; for (final key in keys) { @@ -396,49 +407,56 @@ mixin OverrideQuickEdit on OverrideSpec { EditorSchema get schema; } +void showOverrideAddSheet( + BuildContext context, + WidgetRef ref, + OverrideSpec spec, +) { + final appLocalizations = context.appLocalizations; + final added = spec.target.read(ref).keys; + final remaining = spec.values.where((key) => !added.contains(key)); + showSheet( + context: context, + builder: (_) => SelectionSheet( + title: spec.target.addEntry(appLocalizations), + sections: [ + for (final (label, keys) in spec.sectionsOf( + appLocalizations, + remaining, + )) + SelectionSection( + label: label, + items: keys, + subtitleBuilder: (context, key) => + spec.description(key)?.call(context.appLocalizations), + ), + ], + labelBuilder: (key) => spec.label(key, appLocalizations), + selectedOf: (_) => null, + removeOnSelect: true, + onSelected: (key) { + if (!context.mounted) { + return; + } + spec.target.update( + ref, + (state) => ( + model: spec.fieldOf(key).reset(state.model, spec.defaults), + keys: {...state.keys, key}, + ), + ); + }, + ), + ); +} + class OverrideView extends ConsumerWidget { const OverrideView({super.key, required this.spec}); final OverrideSpec spec; - void _handleAdd(BuildContext context, WidgetRef ref) { - final appLocalizations = context.appLocalizations; - final added = spec.target.read(ref).keys; - final remaining = spec.values.where((key) => !added.contains(key)); - showSheet( - context: context, - builder: (_) => SelectionSheet( - title: spec.target.addEntry(appLocalizations), - sections: [ - for (final (label, keys) in spec.sectionsOf( - appLocalizations, - remaining, - )) - SelectionSection( - label: label, - items: keys, - subtitleBuilder: (context, key) => - spec.description(key)?.call(context.appLocalizations), - ), - ], - labelBuilder: (key) => spec.label(key, appLocalizations), - selectedOf: (_) => null, - removeOnSelect: true, - onSelected: (key) { - if (!context.mounted) { - return; - } - spec.target.update( - ref, - (state) => ( - model: spec.fieldOf(key).reset(state.model, spec.defaults), - keys: {...state.keys, key}, - ), - ); - }, - ), - ); - } + void _handleAdd(BuildContext context, WidgetRef ref) => + showOverrideAddSheet(context, ref, spec); Future _handleQuickEdit( BuildContext context, @@ -498,6 +516,7 @@ class OverrideView extends ConsumerWidget { '${compactError(error)}\n\n' '${currentAppLocalizations.discardChanges}', ), + destructive: true, ); return res == true; } @@ -557,13 +576,6 @@ class _OverrideList extends ConsumerWidget { final OverrideSpec spec; - String? _footerOf(List keys, AppLocalizations appLocalizations) { - final lines = [ - for (final key in keys) ?spec.description(key)?.call(appLocalizations), - ]; - return lines.isEmpty ? null : lines.join('\n'); - } - @override Widget build(BuildContext context, WidgetRef ref) { final appLocalizations = context.appLocalizations; @@ -586,24 +598,13 @@ class _OverrideList extends ConsumerWidget { key: ValueKey(title), child: generateAnimatedSection( title: title, - footer: _footerOf(keys, appLocalizations), + footer: spec.footerOf(keys, appLocalizations), items: [ for (final key in keys) - KeyedSubtree( + OverrideEntry( key: ValueKey(key), - child: spec - .fieldOf(key) - .build( - spec.fieldOf(key) is ValueOverrideField && - spec.target.emptyCancels - ? _ListedValue(spec, key) - : spec.target, - title: (l) => spec.label(key, l), - leading: _RemoveButton( - spec: spec, - overrideKey: key, - ), - ), + spec: spec, + overrideKey: key, ), ], ), @@ -611,7 +612,7 @@ class _OverrideList extends ConsumerWidget { ], ), Padding( - padding: EdgeInsets.only(top: 16.mAp), + padding: EdgeInsets.only(top: 16.mAp(context)), child: ListFooter(text: spec.target.description(appLocalizations)), ), ], @@ -619,6 +620,30 @@ class _OverrideList extends ConsumerWidget { } } +/// A picked key's row, led by the button that takes it off the list. +class OverrideEntry extends StatelessWidget { + const OverrideEntry({ + super.key, + required this.spec, + required this.overrideKey, + }); + + final OverrideSpec spec; + final K overrideKey; + + @override + Widget build(BuildContext context) { + final field = spec.fieldOf(overrideKey); + return field.build( + field is ValueOverrideField && spec.target.emptyCancels + ? _ListedValue(spec, overrideKey) + : spec.target, + title: (l) => spec.label(overrideKey, l), + leading: _RemoveButton(spec: spec, overrideKey: overrideKey), + ); + } +} + /// A key's own value; emptying it takes the key off the list. class _ListedValue implements OverrideModel { const _ListedValue(this.spec, this.overrideKey); diff --git a/lib/views/config/tun.dart b/lib/views/config/tun.dart index eacd4513..2afbff50 100644 --- a/lib/views/config/tun.dart +++ b/lib/views/config/tun.dart @@ -7,48 +7,162 @@ import 'package:fl_clash/widgets/widgets.dart'; extension on TunOverrideKey { String label(AppLocalizations l) => switch (this) { + TunOverrideKey.mtu => 'MTU', + TunOverrideKey.congestionController => l.congestionController, + TunOverrideKey.strictRoute => l.strictRoute, + TunOverrideKey.routeAddress => l.routeAddress, + TunOverrideKey.routeExcludeAddress => l.routeExcludeAddress, + TunOverrideKey.dnsHijack => l.dnsHijacking, + TunOverrideKey.udpTimeout => l.udpTimeout, TunOverrideKey.disableIcmpForwarding => l.disableIcmpForwarding, + TunOverrideKey.gso => 'GSO', + TunOverrideKey.includeInterface => l.includeInterface, TunOverrideKey.excludeInterface => l.excludeInterface, + TunOverrideKey.includeUid => l.includeUid, + TunOverrideKey.excludeUid => l.excludeUid, + TunOverrideKey.excludeSrcPort => l.excludeSrcPort, + TunOverrideKey.excludeDstPort => l.excludeDstPort, }; - ConfigLabel get description => switch (this) { + ConfigLabel? get description => switch (this) { + TunOverrideKey.mtu || + TunOverrideKey.routeAddress || + TunOverrideKey.routeExcludeAddress => null, + TunOverrideKey.congestionController => (l) => l.congestionControllerDesc, + TunOverrideKey.strictRoute => (l) => l.strictRouteDesc, + TunOverrideKey.dnsHijack => (l) => l.dnsHijackDesc, + TunOverrideKey.udpTimeout => (l) => l.udpTimeoutDesc, TunOverrideKey.disableIcmpForwarding => (l) => l.disableIcmpForwardingDesc, + TunOverrideKey.gso => null, + TunOverrideKey.includeInterface => (l) => l.includeInterfaceDesc, TunOverrideKey.excludeInterface => (l) => l.excludeInterfaceDesc, + TunOverrideKey.includeUid => (l) => l.includeUidDesc, + TunOverrideKey.excludeUid => (l) => l.excludeUidDesc, + TunOverrideKey.excludeSrcPort => (l) => l.excludeSrcPortDesc, + TunOverrideKey.excludeDstPort => (l) => l.excludeDstPortDesc, }; } +// Where sing-tun reads each key: strict-route in its Linux and Windows +// routing, the Linux-only ones in its Linux device setup and routing rules. +bool _isRead( + TunOverrideKey key, { + required bool isLinux, + required bool isWindows, +}) => switch (key) { + TunOverrideKey.strictRoute => isLinux || isWindows, + TunOverrideKey.gso || + TunOverrideKey.includeInterface || + TunOverrideKey.excludeInterface || + TunOverrideKey.includeUid || + TunOverrideKey.excludeUid || + TunOverrideKey.excludeSrcPort || + TunOverrideKey.excludeDstPort => isLinux, + _ => true, +}; + +const _maxUid = 0xFFFFFFFF; + +const _maxPort = 65535; + +List _tunOverrideKeys({ + required bool isLinux, + required bool isWindows, +}) => [ + for (final key in TunOverrideKey.values) + if (_isRead(key, isLinux: isLinux, isWindows: isWindows)) key, +]; + typedef _TunState = OverrideState; +_TunState _patchTun(PatchClashConfig config) => + (model: config.tunOverride, keys: config.tunOverrideKeys); + +PatchClashConfig _setPatchTun(PatchClashConfig config, _TunState state) => + config.copyWith(tunOverride: state.model, tunOverrideKeys: state.keys); + _TunState _profileTun(ProfileOverrides overrides) => (model: overrides.tun, keys: overrides.tunOverrideKeys); ProfileOverrides _setProfileTun(ProfileOverrides overrides, _TunState state) => overrides.copyWith(tun: state.model, tunOverrideKeys: state.keys); +String _patchTunDescription(AppLocalizations l) => l.tunOverrideDesc; + +String _profileTunDescription(AppLocalizations l) => l.profileTunSettingsDesc; + +OverrideSpec appTunOverrideSpec({ + required bool isLinux, + required bool isWindows, +}) => _TunOverrideSpec( + const PatchOverrideTarget( + get: _patchTun, + set: _setPatchTun, + description: _patchTunDescription, + ), + isLinux: isLinux, + isWindows: isWindows, +); + class TunView extends OverrideView { - TunView(int profileId, {super.key}) + TunView(int profileId, {super.key, bool? isLinux, bool? isWindows}) : super( spec: _TunOverrideSpec( ProfileOverrideTarget( profileId, get: _profileTun, set: _setProfileTun, + description: _profileTunDescription, ), + isLinux: isLinux ?? system.isLinux, + isWindows: isWindows ?? system.isWindows, ), ); } +ListOverrideField _numbersField( + List Function(ProfileTun tun) select, + ProfileTun Function(ProfileTun tun, List value) update, { + required ConfigLabel label, + required int min, + required int max, +}) { + return ListOverrideField( + (tun) => [for (final number in select(tun)) '$number'], + (tun, value) => + update(tun, [for (final item in value) int.parse(item.trim())]), + itemMaxLength: '$max'.length, + itemValidator: (value, l) { + final number = int.tryParse(value?.trim() ?? ''); + if (number == null) { + return l.numberTip(label(l)); + } + return number < min || number > max + ? l.numberRangeTip(label(l), '$min', '$max') + : null; + }, + ); +} + class _TunOverrideSpec extends OverrideSpec { - const _TunOverrideSpec(this.target); + const _TunOverrideSpec( + this.target, { + required this.isLinux, + required this.isWindows, + }); @override final OverrideTarget target; + final bool isLinux; + final bool isWindows; + @override String title(AppLocalizations l) => l.tun; @override - List get values => TunOverrideKey.values; + List get values => + _tunOverrideKeys(isLinux: isLinux, isWindows: isWindows); @override NullStatusIllustration get illustration => NullStatusIllustration.tun; @@ -60,18 +174,92 @@ class _TunOverrideSpec extends OverrideSpec { String label(TunOverrideKey key, AppLocalizations l) => key.label(l); @override - ConfigLabel description(TunOverrideKey key) => key.description; + ConfigLabel? description(TunOverrideKey key) => key.description; @override OverrideField fieldOf(TunOverrideKey key) => switch (key) { + TunOverrideKey.mtu => NumberOverrideField( + (tun) => tun.mtu, + (tun, value) => tun.copyWith(mtu: value), + min: minTunMtu, + max: maxTunMtu, + ), + TunOverrideKey.congestionController => OptionsOverrideField( + congestionControllers, + (tun) => tun.congestionController, + (tun, value) => tun.copyWith(congestionController: value), + ), + TunOverrideKey.strictRoute => ToggleOverrideField( + (tun) => tun.strictRoute, + (tun, value) => tun.copyWith(strictRoute: value), + ), + TunOverrideKey.routeAddress => ListOverrideField( + (tun) => tun.routeAddress, + (tun, value) => tun.copyWith(routeAddress: value), + itemMaxLength: TextInputLimits.cidr, + itemValidator: validateCidr, + ), + TunOverrideKey.routeExcludeAddress => ListOverrideField( + (tun) => tun.routeExcludeAddress, + (tun, value) => tun.copyWith(routeExcludeAddress: value), + itemMaxLength: TextInputLimits.cidr, + itemValidator: validateCidr, + ), + TunOverrideKey.dnsHijack => ListOverrideField( + (tun) => tun.dnsHijack, + (tun, value) => tun.copyWith(dnsHijack: value), + itemMaxLength: TextInputLimits.dnsListen, + ), + TunOverrideKey.udpTimeout => NumberOverrideField( + (tun) => tun.udpTimeout, + (tun, value) => tun.copyWith(udpTimeout: value), + min: 1, + ), TunOverrideKey.disableIcmpForwarding => ToggleOverrideField( (tun) => tun.disableIcmpForwarding, (tun, value) => tun.copyWith(disableIcmpForwarding: value), ), + TunOverrideKey.gso => ToggleOverrideField( + (tun) => tun.gso, + (tun, value) => tun.copyWith(gso: value), + ), + TunOverrideKey.includeInterface => ListOverrideField( + (tun) => tun.includeInterface, + (tun, value) => tun.copyWith(includeInterface: value), + itemMaxLength: TextInputLimits.name, + ), TunOverrideKey.excludeInterface => ListOverrideField( (tun) => tun.excludeInterface, (tun, value) => tun.copyWith(excludeInterface: value), itemMaxLength: TextInputLimits.name, ), + TunOverrideKey.includeUid => _numbersField( + (tun) => tun.includeUid, + (tun, value) => tun.copyWith(includeUid: value), + label: key.label, + min: 0, + max: _maxUid, + ), + TunOverrideKey.excludeUid => _numbersField( + (tun) => tun.excludeUid, + (tun, value) => tun.copyWith(excludeUid: value), + label: key.label, + min: 0, + max: _maxUid, + ), + TunOverrideKey.excludeSrcPort => _numbersField( + (tun) => tun.excludeSrcPort, + (tun, value) => tun.copyWith(excludeSrcPort: value), + label: key.label, + min: 1, + max: _maxPort, + ), + TunOverrideKey.excludeDstPort => _numbersField( + (tun) => tun.excludeDstPort, + (tun, value) => tun.copyWith(excludeDstPort: value), + label: key.label, + min: 1, + max: _maxPort, + ), }; } diff --git a/plugins/proxy/lib/src/windows_proxy.dart b/plugins/proxy/lib/src/windows_proxy.dart index 4a0bfc7e..d5790e37 100644 --- a/plugins/proxy/lib/src/windows_proxy.dart +++ b/plugins/proxy/lib/src/windows_proxy.dart @@ -1,13 +1,13 @@ import 'dart:io'; -/// WinINet rejects the whole list over one bare IPv6 literal, so the system -/// proxy is not set at all, and its `` token for single-label intranet -/// hosts like `nas` has no cross-platform pattern. Loopback needs no entry: -/// WinINet never proxies it. +/// WinINet rejects the whole list over one bare IPv6 literal or one entry +/// ending in `/`, so the system proxy is not set at all, and its `` +/// token for single-label intranet hosts like `nas` has no cross-platform +/// pattern. Loopback needs no entry: WinINet never proxies it. List windowsBypassList(List bypassDomain) { final entries = {}; for (final domain in bypassDomain) { - final entry = domain.trim(); + final entry = domain.trim().replaceFirst(_trailingSlashes, ''); if (entry.isEmpty) continue; final isBareIPv6 = InternetAddress.tryParse(entry)?.type == InternetAddressType.IPv6; @@ -15,3 +15,5 @@ List windowsBypassList(List bypassDomain) { } return {...entries, ''}.toList(); } + +final _trailingSlashes = RegExp(r'/+$'); diff --git a/plugins/proxy/test/proxy_test.dart b/plugins/proxy/test/proxy_test.dart index c30bd9f7..8c03f447 100644 --- a/plugins/proxy/test/proxy_test.dart +++ b/plugins/proxy/test/proxy_test.dart @@ -446,6 +446,13 @@ USB 10/100/1000 LAN ['[::1]', '[fe80::1]', '[fd00::1]', '*.lan', ''], ); }); + + test('drops trailing slashes that fail the whole list', () { + expect( + windowsBypassList(['example.test/', 'example.test', 'nas//', '/']), + ['example.test', 'nas', ''], + ); + }); }); group('MethodChannelProxy', () { diff --git a/test/common/proxy_test.dart b/test/common/proxy_test.dart new file mode 100644 index 00000000..68837c5d --- /dev/null +++ b/test/common/proxy_test.dart @@ -0,0 +1,84 @@ +import 'dart:async'; + +import 'package:fl_clash/common/proxy.dart'; +import 'package:fl_clash/models/models.dart' show ProxyState; +import 'package:flutter_test/flutter_test.dart'; +import 'package:proxy/proxy.dart'; + +class _FakeProxy implements Proxy { + final List calls = []; + Future? held; + Error? failure; + + Future _call(String name) async { + calls.add(name); + final error = failure; + failure = null; + if (error != null) { + throw error; + } + final result = held ?? Future.value(true); + held = null; + return result; + } + + @override + Future startProxy(int port, [List bypassDomain = const []]) { + return _call('start $port'); + } + + @override + Future stopProxy() => _call('stop'); +} + +ProxyState _state({required bool isStart}) { + return ProxyState( + isStart: isStart, + systemProxy: true, + bassDomain: const [], + port: 7890, + ); +} + +void main() { + test('applies changes in the order they come', () async { + final proxy = _FakeProxy(); + final queue = SystemProxyQueue(proxy); + + unawaited(queue.apply(_state(isStart: true))); + await queue.apply(_state(isStart: false)); + + expect(proxy.calls, ['start 7890', 'stop']); + }); + + test('close stops last and drops the starts queued before it', () async { + final proxy = _FakeProxy(); + final queue = SystemProxyQueue(proxy); + final inFlight = Completer(); + proxy.held = inFlight.future; + + unawaited(queue.apply(_state(isStart: false))); + await pumpEventQueue(); + unawaited(queue.apply(_state(isStart: true))); + final closed = queue.close(); + await pumpEventQueue(); + expect(proxy.calls, ['stop']); + + inFlight.complete(true); + await closed; + await queue.apply(_state(isStart: true)); + + expect(proxy.calls, ['stop', 'stop']); + }); + + test('a failing call does not stall the queue', () async { + final proxy = _FakeProxy(); + final queue = SystemProxyQueue(proxy); + proxy.failure = StateError('channel gone'); + + await queue.apply(_state(isStart: true)); + await queue.apply(_state(isStart: false)); + + expect(proxy.calls, ['start 7890', 'stop']); + }); +} diff --git a/test/common/task_test.dart b/test/common/task_test.dart index 63e6fe7b..b93fd0c6 100644 --- a/test/common/task_test.dart +++ b/test/common/task_test.dart @@ -720,21 +720,38 @@ void main() { return loadYaml(result.yaml) as YamlMap; } - test('tun settings replace the profile ones and leave the rest', () async { + test('tun takes its stack from the settings and the rest from the ' + 'profile', () async { final config = await runWith( - const PatchClashConfig(tun: Tun(mtu: 1400, strictRoute: true)), + const PatchClashConfig(tun: Tun(stack: TunStack.gvisor, mtu: 1400)), { - 'tun': {'mtu': 9000, 'strict-route': false, 'udp-timeout': 60}, + 'tun': { + 'stack': 'system', + 'mtu': 1500, + 'strict-route': true, + 'udp-timeout': 60, + }, }, ); final tun = config['tun'] as YamlMap; - expect(tun['mtu'], 1400); + expect(tun['stack'], 'gvisor'); + expect(tun['auto-route'], true); + expect(tun['mtu'], 1500); expect(tun['strict-route'], true); - expect(tun['congestion-controller'], 'cubic'); + expect(tun.containsKey('congestion-controller'), isFalse); expect(tun['udp-timeout'], 60); }); + test('tun detects the outbound interface over the profile', () async { + final config = await runWith(const PatchClashConfig(), { + 'tun': {'auto-detect-interface': false}, + }); + final tun = config['tun'] as YamlMap; + + expect(tun['auto-detect-interface'], true); + }); + test('outbound settings start at the core defaults', () async { final config = await runWith(const PatchClashConfig(), { 'routing-mark': 1, diff --git a/test/common/task_tun_override_test.dart b/test/common/task_tun_override_test.dart index 1dbd31db..1c5247bf 100644 --- a/test/common/task_tun_override_test.dart +++ b/test/common/task_tun_override_test.dart @@ -5,8 +5,13 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:yaml/yaml.dart'; const _overrides = ProfileOverrides( - tun: ProfileTun(disableIcmpForwarding: true, excludeInterface: ['docker0']), + tun: ProfileTun( + mtu: 1400, + disableIcmpForwarding: true, + excludeInterface: ['docker0'], + ), tunOverrideKeys: { + TunOverrideKey.mtu, TunOverrideKey.disableIcmpForwarding, TunOverrideKey.excludeInterface, }, @@ -15,14 +20,16 @@ const _overrides = ProfileOverrides( Future _tunOf({ required Map rawConfig, ProfileOverrides overrides = _overrides, + bool bypassPrivateRoute = false, }) async { final result = await makeRealProfileTask( MakeRealProfileState( profilesPath: '/profiles', profileId: 1, rawConfig: rawConfig, - realPatchConfig: const PatchClashConfig(tun: Tun(mtu: 1400)), + realPatchConfig: const PatchClashConfig(), overrides: overrides, + bypassPrivateRoute: bypassPrivateRoute, appendSystemDns: false, proxyGroups: const [], rules: const [], @@ -57,10 +64,54 @@ void main() { expect(tun['include-uid'], [1000]); }); + test('hijacks every port 53 query over the profile unless a key is ' + 'picked', () async { + const profileHijack = { + 'tun': { + 'dns-hijack': ['198.18.0.2:53'], + }, + }; + final tun = await _tunOf( + rawConfig: profileHijack, + overrides: const ProfileOverrides(), + ); + final picked = await _tunOf( + rawConfig: profileHijack, + overrides: const ProfileOverrides( + tun: ProfileTun(dnsHijack: ['tcp://any:53']), + tunOverrideKeys: {TunOverrideKey.dnsHijack}, + ), + ); + + expect(tun['dns-hijack'], defaultDnsHijack); + expect(picked['dns-hijack'], ['tcp://any:53']); + }); + + test( + 'excludes private ranges after the routes the profile excludes', + () async { + final tun = await _tunOf( + rawConfig: { + 'tun': { + 'route-exclude-address': ['100.64.0.0/10'], + }, + }, + overrides: const ProfileOverrides(), + bypassPrivateRoute: true, + ); + + expect(tun['route-exclude-address'], [ + '100.64.0.0/10', + ...privateRouteAddress, + ]); + }, + ); + test('leaves the profile alone without picked keys', () async { final tun = await _tunOf( rawConfig: { 'tun': { + 'mtu': 1500, 'exclude-interface': ['eth1'], }, }, @@ -69,6 +120,7 @@ void main() { ), ); + expect(tun['mtu'], 1500); expect(tun['exclude-interface'], ['eth1']); expect(tun.containsKey('disable-icmp-forwarding'), isFalse); }); diff --git a/test/common/tray_lifecycle_test.dart b/test/common/tray_lifecycle_test.dart index d117cc3d..7c7698a4 100644 --- a/test/common/tray_lifecycle_test.dart +++ b/test/common/tray_lifecycle_test.dart @@ -56,23 +56,45 @@ void main() { }); test('shutdown stops any later update from resurrecting the tray', () async { - await AppTray().update( + final tray = AppTray.forPlatform(isMacOS: false, isWindows: false); + await tray.update( trayState: _trayState(), traffic: const Traffic(), read: container.read, ); expect(calls.where((call) => call.method == 'show'), hasLength(1)); - await AppTray().shutdown(); + await tray.shutdown(); expect(calls.where((call) => call.method == 'hide'), hasLength(1)); calls.clear(); - await AppTray().update( + await tray.update( + trayState: _trayState(isStart: true), + traffic: const Traffic(), + read: container.read, + ); + await tray.updateTitle(showTrayTitle: true, traffic: const Traffic()); + + expect(calls, isEmpty); + }); + + test('macOS shutdown leaves the status item to the process', () async { + final tray = AppTray.forPlatform(isMacOS: true, isWindows: false); + await tray.update( + trayState: _trayState(), + traffic: const Traffic(), + read: container.read, + ); + + await tray.shutdown(); + expect(calls.where((call) => call.method == 'hide'), isEmpty); + + calls.clear(); + await tray.update( trayState: _trayState(isStart: true), traffic: const Traffic(), read: container.read, ); - await AppTray().updateTitle(showTrayTitle: true, traffic: const Traffic()); expect(calls, isEmpty); }); diff --git a/test/models/config_test.dart b/test/models/config_test.dart index 36cca0be..32754f0a 100644 --- a/test/models/config_test.dart +++ b/test/models/config_test.dart @@ -91,17 +91,12 @@ void main() { }); test('toUpdateParams sends geoXUrl to the Core under geox-url', () { - final params = - const PatchClashConfig( - geoXUrl: { - GeoResource.MMDB: 'https://example.com/geoip.metadb', - GeoResource.GEOSITE: 'https://example.com/geosite.dat', - }, - ).toUpdateParams( - bypassPrivateRoute: false, - authentication: const [], - skipCertVerify: false, - ); + final params = const PatchClashConfig( + geoXUrl: { + GeoResource.MMDB: 'https://example.com/geoip.metadb', + GeoResource.GEOSITE: 'https://example.com/geosite.dat', + }, + ).toUpdateParams(authentication: const [], skipCertVerify: false); final json = jsonDecode(jsonEncode(params)) as Map; expect(json['geox-url'], { @@ -112,7 +107,6 @@ void main() { test('toUpdateParams sends skipCertVerify under skip-cert-verify', () { final params = const PatchClashConfig().toUpdateParams( - bypassPrivateRoute: false, authentication: const [], skipCertVerify: true, ); @@ -199,6 +193,17 @@ void main() { expect(restored.dashboardWidgets, defaultDashboardWidgets); }); + test('an old dashboard emptied of cards keeps only the current ' + 'outbound', () { + for (final saved in [ + [], + ['runTime'], + ]) { + final restored = AppSettingProps.fromJson({'dashboardWidgets': saved}); + expect(restored.dashboardWidgets, [DashboardWidget.currentOutbound]); + } + }); + test('the outbound IP card left its place to the intranet one', () { final restored = AppSettingProps.fromJson({ 'dashboardWidgets': [ @@ -535,11 +540,7 @@ void main() { test('reaches the Core through the update params', () { final params = open .copyWith(secret: 'abc') - .toUpdateParams( - bypassPrivateRoute: false, - authentication: const [], - skipCertVerify: false, - ); + .toUpdateParams(authentication: const [], skipCertVerify: false); expect(params.secret, 'abc'); expect(params.toJson()['secret'], 'abc'); @@ -547,11 +548,8 @@ void main() { }); group('PatchClashConfig.setupOnly', () { - UpdateParams liveParams(PatchClashConfig config) => config.toUpdateParams( - bypassPrivateRoute: false, - authentication: const [], - skipCertVerify: false, - ); + UpdateParams liveParams(PatchClashConfig config) => + config.toUpdateParams(authentication: const [], skipCertVerify: false); test('drops every field the update params patch live', () { final live = defaultClashConfig.copyWith( @@ -593,6 +591,7 @@ void main() { defaultClashConfig.copyWith(globalUa: 'ua'), defaultClashConfig.copyWith(hosts: const {'a.test': '1.1.1.1'}), defaultClashConfig.copyWith(dns: defaultDns.copyWith(ipv6: true)), + defaultClashConfig.copyWith(tunOverrideKeys: {TunOverrideKey.gso}), ]; for (final config in setupOnlyChanges) { @@ -745,13 +744,15 @@ void main() { expect(modeOf(null), LiquidGlassMode.none); expect(modeOf(true), LiquidGlassMode.standard); expect(modeOf(false), LiquidGlassMode.none); - expect( - roundTrip( - const ThemeProps(liquidGlass: LiquidGlassMode.standard).toJson, - ThemeProps.fromJson, - ).liquidGlass, - LiquidGlassMode.standard, - ); + for (final mode in LiquidGlassMode.values) { + expect( + roundTrip( + ThemeProps(liquidGlass: mode).toJson, + ThemeProps.fromJson, + ).liquidGlass, + mode, + ); + } }); }); @@ -1179,16 +1180,21 @@ void main() { ); }); - test('drops the include-all keys', () { - for (final key in [ - 'include-all', - 'include-all-proxies', - 'include-all-providers', + test('reads include-all as both include-all keys', () { + for (final (key, keys) in [ + ('include-all', ['include-all-proxies', 'include-all-providers']), + ('include-all-proxies', ['include-all-proxies']), + ('include-all-providers', ['include-all-providers']), ]) { + final edited = group.withDefinitionYaml( + '${group.definitionYaml}$key: true\n', + ); + expect(edited.definition, { + ...group.definition, + for (final key in keys) key: true, + }, reason: key); expect( - group - .withDefinitionYaml('${group.definitionYaml}$key: true\n') - .definition, + edited.withDefinitionYaml(group.definitionYaml).definition, group.definition, reason: key, ); diff --git a/test/models/tun_override_test.dart b/test/models/tun_override_test.dart index b6e2b222..f1d2cfcf 100644 --- a/test/models/tun_override_test.dart +++ b/test/models/tun_override_test.dart @@ -26,13 +26,68 @@ void main() { }); test('no TunOverrideKey is one the network settings write', () { - final networkKeys = defaultTun.toJson().keys.toSet(); + final networkKeys = defaultTun.coreJson.keys.toSet(); for (final key in TunOverrideKey.values) { expect(networkKeys, isNot(contains(key.path))); } }); + group('PatchClashConfig from before the TUN override', () { + PatchClashConfig decode(Map json) => + PatchClashConfig.fromJson( + jsonDecode(jsonEncode(json)) as Map, + ); + + test('picks each network value changed from its default', () { + final config = decode({ + 'tun': { + 'mtu': 1400, + 'congestion-controller': 'cubic', + 'strict-route': true, + 'route-address': [], + 'route-exclude-address': ['10.0.0.0/8'], + }, + }); + + expect(config.tunOverrideKeys, { + TunOverrideKey.mtu, + TunOverrideKey.strictRoute, + TunOverrideKey.routeExcludeAddress, + }); + expect(config.tunOverride.mtu, 1400); + expect(config.tunOverride.strictRoute, isTrue); + expect(config.tunOverride.routeExcludeAddress, ['10.0.0.0/8']); + expect(config.tun.mtu, 1400); + }); + + test('a config saved with override keys is read as it is', () { + final json = const PatchClashConfig(tun: Tun(mtu: 1400)).toJson(); + + expect(decode(json).tunOverrideKeys, isEmpty); + }); + }); + + test('a custom profile picks its own TUN keys over the app-wide ones', () { + const custom = ProfileOverrides( + tun: ProfileTun(mtu: 1400, gso: true), + tunOverrideKeys: {TunOverrideKey.mtu}, + ); + final merged = custom.overAppTun( + const ProfileTun(mtu: 1500, strictRoute: true), + {TunOverrideKey.mtu, TunOverrideKey.strictRoute}, + ); + + expect(merged.tunOverrideKeys, { + TunOverrideKey.mtu, + TunOverrideKey.strictRoute, + }); + expect(merged.tun.overrideJson(merged.tunOverrideKeys), { + 'mtu': 1400, + 'strict-route': true, + }); + }); + group('ProfileTun.overrideJson', () { test('emits only the selected keys', () { const tun = ProfileTun( @@ -46,6 +101,21 @@ void main() { expect(tun.overrideJson({}), isEmpty); }); + test('writes user IDs and ports as the numbers the core parses', () { + const tun = ProfileTun(includeUid: [1000], excludeSrcPort: [22]); + + expect( + tun.overrideJson({ + TunOverrideKey.includeUid, + TunOverrideKey.excludeSrcPort, + }), + { + 'include-uid': [1000], + 'exclude-src-port': [22], + }, + ); + }); + test('a list key without items writes nothing', () { expect( const ProfileTun().overrideJson({ diff --git a/test/models/tun_test.dart b/test/models/tun_test.dart index 3d35fcf5..c7d819ed 100644 --- a/test/models/tun_test.dart +++ b/test/models/tun_test.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/models/models.dart'; import 'package:test/test.dart'; @@ -39,18 +40,26 @@ void main() { expect(Tun.fromJson({'mtu': 1500}).mtu, 1500); }); - test('the core keeps the route list and gets private ranges excluded', () { - final tun = const Tun( + test('the desktop TUN takes only its switch, device and stack, routed', () { + const tun = Tun( + enable: true, + stack: TunStack.gvisor, + mtu: 1400, routeAddress: ['1.0.0.0/8'], - routeExcludeAddress: ['1.1.1.0/24'], - ).getRealTun(bypassPrivateRoute: true); + ); - expect(tun.autoRoute, isTrue); - expect(tun.routeAddress, ['1.0.0.0/8']); - expect(tun.routeExcludeAddress, ['1.1.1.0/24', ...privateRouteAddress]); + expect(tun.coreJson, { + 'enable': true, + 'device': tun.device, + 'stack': 'gvisor', + 'auto-route': true, + }); }); - test('a config update patches every Tun key on desktop', () { - expect(_keysOf('core/protocol.go', 'tunSchema', 'json'), tunKeys); + test('a config update patches every key the desktop TUN takes', () { + expect( + _keysOf('core/protocol.go', 'tunSchema', 'json'), + const Tun().coreJson.keys.toSet(), + ); }); } diff --git a/test/providers/setup_action_test.dart b/test/providers/setup_action_test.dart index c69c7872..98d7e850 100644 --- a/test/providers/setup_action_test.dart +++ b/test/providers/setup_action_test.dart @@ -1375,6 +1375,11 @@ void main() { digest = 'second'; await setupAction.applyProfile(); expect(pushed, hasLength(2)); + + when(() => core.setupConfig(any())).thenAnswer((_) async => 'rejected'); + digest = 'third'; + expect(await setupAction.applyProfile(), isFalse); + expect(globalState.lastConfigCounts, (groups: 0, proxies: 0, rules: 0)); }); test('the preview shows the config the Core merges', () async { diff --git a/test/providers/state_derived_test.dart b/test/providers/state_derived_test.dart index cfb10db5..9ccb6f86 100644 --- a/test/providers/state_derived_test.dart +++ b/test/providers/state_derived_test.dart @@ -1,6 +1,7 @@ import 'package:fl_clash/common/app_ports.dart'; import 'package:fl_clash/common/cidr.dart'; import 'package:fl_clash/common/constant.dart'; +import 'package:fl_clash/common/system.dart'; import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/l10n/l10n.dart'; import 'package:fl_clash/models/models.dart'; @@ -972,7 +973,19 @@ void main() { .update( (state) => state.copyWith(appendSystemDns: !state.appendSystemDns), ); - expect(container.read(setupPatchProvider), isNot(withHosts)); + final withSystemDns = container.read(setupPatchProvider); + expect(withSystemDns, isNot(withHosts)); + + container + .read(networkSettingProvider.notifier) + .update( + (state) => + state.copyWith(bypassPrivateRoute: !state.bypassPrivateRoute), + ); + expect( + container.read(setupPatchProvider), + system.isDesktop ? isNot(withSystemDns) : withSystemDns, + ); }); test('shared state carries the notification stop action switch', () async { diff --git a/test/views/network_config_test.dart b/test/views/network_config_test.dart index 14fe92ba..ca412432 100644 --- a/test/views/network_config_test.dart +++ b/test/views/network_config_test.dart @@ -1,10 +1,12 @@ 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/app.dart'; import 'package:fl_clash/providers/config.dart'; import 'package:fl_clash/providers/database.dart'; import 'package:fl_clash/state.dart'; import 'package:fl_clash/views/config/network.dart'; +import 'package:fl_clash/views/config/tun.dart'; import 'package:material_ui/material_ui.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -189,19 +191,10 @@ void main() { }); group('tun settings', () { - List items({ - bool isLinux = false, - bool isWindows = false, - bool isMipsStack = true, - }) { - return tunItems( - isLinux: isLinux, - isWindows: isWindows, - isMipsStack: isMipsStack, - ); - } + List items({bool isMipsStack = true}) => + tunItems(isMipsStack: isMipsStack); - test('every platform gets the same route rows', () { + test('Android sets the routes its VPN service starts with', () { final types = items().map((item) => item.runtimeType); expect(types, contains(BypassPrivateRouteItem)); expect(types, contains(RouteAddressItem)); @@ -209,9 +202,63 @@ void main() { expect(items(isMipsStack: false), hasLength(4)); }); - test('strict route is offered where sing-tun enforces it', () { - expect(items(isWindows: true), hasLength(6)); - expect(items(isLinux: true), hasLength(6)); + Widget desktopSection({bool isWindows = false}) => + TunSection(isDesktop: true, isLinux: false, isWindows: isWindows); + + void setOverrideKeys(Set keys) { + container + .read(patchClashConfigProvider.notifier) + .update((state) => state.copyWith(tunOverrideKeys: keys)); + } + + testWidgets('desktop adds an override from the last row of the section', ( + tester, + ) async { + await pumpItem(tester, desktopSection()); + final l = currentAppLocalizations; + expect(find.text(l.bypassPrivateRoute), findsOneWidget); + expect(find.text('MTU'), findsNothing); + expect(find.textContaining(l.tunOverrideDesc), findsOneWidget); + + await tester.tap(find.text(l.addOverrideEntry)); + await tester.pumpAndSettle(); + expect(find.text(l.strictRoute), findsNothing); + await tester.tap(find.text('MTU')); + await tester.pumpAndSettle(); + await tester.tapAt(Offset.zero); + await tester.pumpAndSettle(); + + final config = container.read(patchClashConfigProvider); + expect(config.tunOverrideKeys, {TunOverrideKey.mtu}); + expect(config.tunOverride.mtu, defaultTunMtu); + expect(find.text('MTU'), findsOneWidget); + }); + + testWidgets('a listed override leaves the section with its button', ( + tester, + ) async { + setOverrideKeys({TunOverrideKey.strictRoute}); + await pumpItem(tester, desktopSection(isWindows: true)); + final l = currentAppLocalizations; + expect(find.text(l.strictRoute), findsOneWidget); + expect(find.textContaining(l.strictRouteDesc), findsOneWidget); + + await tester.tap(find.byTooltip(l.remove)); + await tester.pumpAndSettle(); + + expect(container.read(patchClashConfigProvider).tunOverrideKeys, isEmpty); + expect(find.text(l.strictRoute), findsNothing); + }); + + testWidgets('the add row leaves once every offered key is listed', ( + tester, + ) async { + setOverrideKeys( + appTunOverrideSpec(isLinux: false, isWindows: false).values.toSet(), + ); + await pumpItem(tester, desktopSection()); + + expect(find.text(currentAppLocalizations.addOverrideEntry), findsNothing); }); testWidgets('a number shows the core default and resets to it', ( diff --git a/test/views/tun_view_test.dart b/test/views/tun_view_test.dart index 82db9c72..2cda4262 100644 --- a/test/views/tun_view_test.dart +++ b/test/views/tun_view_test.dart @@ -5,6 +5,7 @@ import 'package:fl_clash/providers/app.dart'; import 'package:fl_clash/providers/database.dart'; import 'package:fl_clash/state.dart'; import 'package:fl_clash/views/config/tun.dart'; +import 'package:fl_clash/widgets/widgets.dart'; import 'package:material_ui/material_ui.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -19,7 +20,7 @@ void main() { late ProviderContainer container; - Future pumpView(WidgetTester tester) async { + Future pumpWidget(WidgetTester tester, Widget child) async { tester.view.physicalSize = const Size(1200, 1000); tester.view.devicePixelRatio = 1; addTearDown(tester.view.resetPhysicalSize); @@ -47,15 +48,33 @@ void main() { await tester.pumpWidget( UncontrolledProviderScope( container: container, - child: TestApp(child: TunView(_profileId)), + child: TestApp(child: child), ), ); await tester.pump(); } - ProfileOverrides config() => + Future pumpView( + WidgetTester tester, { + bool isLinux = true, + bool isWindows = false, + }) => pumpWidget( + tester, + TunView(_profileId, isLinux: isLinux, isWindows: isWindows), + ); + + ProfileOverrides overrides() => container.read(profilesProvider).getProfile(_profileId)!.overrides; + void setKeys(Set keys) { + container + .read(profilesProvider.notifier) + .updateProfile( + _profileId, + (profile) => profile.copyWith.overrides(tunOverrideKeys: keys), + ); + } + testWidgets('offers the TUN keys and lists a picked one at its default', ( tester, ) async { @@ -71,13 +90,13 @@ void main() { await tester.tapAt(Offset.zero); await tester.pumpAndSettle(); - expect(config().tunOverrideKeys, {TunOverrideKey.disableIcmpForwarding}); - expect(config().tun, defaultProfileTun); + expect(overrides().tunOverrideKeys, {TunOverrideKey.disableIcmpForwarding}); + expect(overrides().tun, defaultProfileTun); expect(find.text(l.disableIcmpForwardingDesc), findsOneWidget); await tester.tap(find.byType(Switch)); await tester.pump(); - expect(config().tun.disableIcmpForwarding, isTrue); + expect(overrides().tun.disableIcmpForwarding, isTrue); }); testWidgets('offers no quick edit for a part of the TUN section', ( @@ -87,4 +106,70 @@ void main() { expect(find.byTooltip(currentAppLocalizations.quickEdit), findsNothing); }); + + testWidgets('offers the keys only Linux routing reads on Linux alone', ( + tester, + ) async { + await pumpView(tester, isLinux: false); + final l = currentAppLocalizations; + + await tester.tap(find.text(l.addSettingEntry)); + await tester.pumpAndSettle(); + + expect(find.text('MTU'), findsOneWidget); + expect(find.text(l.dnsHijacking), findsOneWidget); + expect(find.text(l.udpTimeout), findsOneWidget); + expect(find.text(l.strictRoute), findsNothing); + expect(find.text('GSO'), findsNothing); + expect(find.text(l.excludeInterface), findsNothing); + expect(find.text(l.includeUid), findsNothing); + expect(find.text(l.excludeDstPort), findsNothing); + }); + + testWidgets('offers strict route where sing-tun enforces it', (tester) async { + await pumpView(tester, isLinux: false, isWindows: true); + final l = currentAppLocalizations; + + await tester.tap(find.text(l.addSettingEntry)); + await tester.pumpAndSettle(); + + expect(find.text(l.strictRoute), findsOneWidget); + expect(find.text(l.excludeInterface), findsNothing); + }); + + testWidgets('a custom profile says its keys win over the app-wide ones', ( + tester, + ) async { + await pumpView(tester); + + expect( + find.text(currentAppLocalizations.profileTunSettingsDesc), + findsOneWidget, + ); + }); + + testWidgets('a port list takes whole ports and writes them as numbers', ( + tester, + ) async { + await pumpView(tester); + setKeys({TunOverrideKey.excludeDstPort}); + await tester.pump(); + final l = currentAppLocalizations; + final ports = find.ancestor( + of: find.text(l.excludeDstPort), + matching: find.byType(ConfigListEditItem), + ); + final item = tester.widget(ports); + + expect(item.itemValidator!('443', l), isNull); + expect(item.itemValidator!('70000', l), isNotNull); + expect(item.itemValidator!('https', l), isNotNull); + + item.onChanged(tester.element(ports) as WidgetRef, const ['443', ' 8443']); + await tester.pump(); + expect(overrides().tun.excludeDstPort, [443, 8443]); + expect(overrides().tun.overrideJson(overrides().tunOverrideKeys), { + 'exclude-dst-port': [443, 8443], + }); + }); }