Compare commits

..

1 Commits

Author SHA1 Message Date
chen08209
afbc5adb05 Support override script
Support proxies search

Support svg display

Optimize config persistence

Add some scenes auto close connections

Update core

Optimize more details
2025-06-07 23:52:27 +08:00
29 changed files with 349 additions and 49 deletions

View File

@@ -405,5 +405,6 @@
"portConflictTip": "Please enter a different port",
"import": "Import",
"importFile": "Import from file",
"importUrl": "Import from URL"
"importUrl": "Import from URL",
"autoSetSystemDns": "Auto set system DNS"
}

View File

@@ -406,5 +406,6 @@
"portConflictTip": "別のポートを入力してください",
"import": "インポート",
"importFile": "ファイルからインポート",
"importUrl": "URLからインポート"
"importUrl": "URLからインポート",
"autoSetSystemDns": "オートセットシステムDNS"
}

View File

@@ -406,5 +406,6 @@
"portConflictTip": "Введите другой порт",
"import": "Импорт",
"importFile": "Импорт из файла",
"importUrl": "Импорт по URL"
"importUrl": "Импорт по URL",
"autoSetSystemDns": "Автоматическая настройка системного DNS"
}

View File

@@ -406,5 +406,6 @@
"portConflictTip": "请输入不同的端口",
"import": "导入",
"importFile": "通过文件导入",
"importUrl": "通过URL导入"
"importUrl": "通过URL导入",
"autoSetSystemDns": "自动设置系统DNS"
}

View File

@@ -66,6 +66,11 @@ class ClashCore {
Future<bool> init() async {
await initGeo();
if (globalState.config.appSetting.openLogs) {
clashCore.startLog();
} else {
clashCore.stopLog();
}
final homeDirPath = await appPath.homeDirPath;
return await clashInterface.init(
InitParams(

View File

@@ -10,6 +10,7 @@ import 'package:flutter/services.dart';
class System {
static System? _instance;
List<String>? originDns;
System._internal();
@@ -104,6 +105,100 @@ class System {
return AuthorizeCode.error;
}
Future<String?> getMacOSDefaultServiceName() async {
if (!Platform.isMacOS) {
return null;
}
final result = await Process.run('route', ['-n', 'get', 'default']);
final output = result.stdout.toString();
final deviceLine = output
.split('\n')
.firstWhere((s) => s.contains('interface:'), orElse: () => "");
final lineSplits = deviceLine.trim().split(' ');
if (lineSplits.length != 2) {
return null;
}
final device = lineSplits[1];
final serviceResult = await Process.run(
'networksetup',
['-listnetworkserviceorder'],
);
final serviceResultOutput = serviceResult.stdout.toString();
final currentService = serviceResultOutput.split('\n\n').firstWhere(
(s) => s.contains("Device: $device"),
orElse: () => "",
);
if (currentService.isEmpty) {
return null;
}
final currentServiceNameLine = currentService.split("\n").firstWhere(
(line) => RegExp(r'^\(\d+\).*').hasMatch(line),
orElse: () => "");
final currentServiceNameLineSplits =
currentServiceNameLine.trim().split(' ');
if (currentServiceNameLineSplits.length < 2) {
return null;
}
return currentServiceNameLineSplits[1];
}
Future<List<String>?> getMacOSOriginDns() async {
if (!Platform.isMacOS) {
return null;
}
final deviceServiceName = await getMacOSDefaultServiceName();
if (deviceServiceName == null) {
return null;
}
final result = await Process.run(
'networksetup',
['-getdnsservers', deviceServiceName],
);
final output = result.stdout.toString().trim();
if (output.startsWith("There aren't any DNS Servers set on")) {
originDns = [];
} else {
originDns = output.split("\n");
}
return originDns;
}
setMacOSDns(bool restore) async {
if (!Platform.isMacOS) {
return;
}
final serviceName = await getMacOSDefaultServiceName();
if (serviceName == null) {
return;
}
List<String>? nextDns;
if (restore) {
nextDns = originDns;
} else {
final originDns = await system.getMacOSOriginDns();
if (originDns == null) {
return;
}
final needAddDns = "223.5.5.5";
if (originDns.contains(needAddDns)) {
return;
}
nextDns = List.from(originDns)..add(needAddDns);
}
if (nextDns == null) {
return;
}
await Process.run(
'networksetup',
[
'-setdnsservers',
serviceName,
if (nextDns.isNotEmpty) ...nextDns,
if (nextDns.isEmpty) "Empty",
],
);
}
back() async {
await app?.moveTaskToBack();
await window?.hide();

View File

@@ -22,7 +22,6 @@ import 'models/models.dart';
import 'views/profiles/override_profile.dart';
class AppController {
bool lastTunEnable = false;
int? lastProfileModified;
final BuildContext context;
@@ -263,29 +262,31 @@ class AppController {
if (res.isError) {
return;
}
lastTunEnable = res.data == true;
final realTunEnable = _ref.read(realTunEnableProvider);
final message = await clashCore.updateConfig(
updateParams.copyWith.tun(
enable: lastTunEnable,
enable: realTunEnable,
),
);
if (message.isNotEmpty) throw message;
}
Future<Result<bool>> _requestAdmin(bool enableTun) async {
if (enableTun != lastTunEnable && lastTunEnable == false) {
final realTunEnable = _ref.read(realTunEnableProvider);
if (enableTun != realTunEnable && realTunEnable == false) {
final code = await system.authorizeCore();
switch (code) {
case AuthorizeCode.none:
return Result.success(enableTun);
case AuthorizeCode.success:
await restartCore();
return Result.error("");
case AuthorizeCode.none:
break;
case AuthorizeCode.error:
enableTun = false;
return Result.success(false);
break;
}
}
_ref.read(realTunEnableProvider.notifier).value = enableTun;
return Result.success(enableTun);
}
@@ -304,8 +305,8 @@ class AppController {
if (res.isError) {
return;
}
lastTunEnable = res.data == true;
final realPatchConfig = patchConfig.copyWith.tun(enable: lastTunEnable);
final realTunEnable = _ref.read(realTunEnableProvider);
final realPatchConfig = patchConfig.copyWith.tun(enable: realTunEnable);
final params = await globalState.getSetupParams(
pathConfig: realPatchConfig,
);
@@ -443,6 +444,7 @@ class AppController {
});
try {
await savePreferences();
await system.setMacOSDns(true);
await proxy?.stopProxy();
await clashCore.shutdown();
await clashService?.destroy();

View File

@@ -123,6 +123,9 @@ class MessageLookup extends MessageLookupByLibrary {
"autoRunDesc": MessageLookupByLibrary.simpleMessage(
"Auto run when the application is opened",
),
"autoSetSystemDns": MessageLookupByLibrary.simpleMessage(
"Auto set system DNS",
),
"autoUpdate": MessageLookupByLibrary.simpleMessage("Auto update"),
"autoUpdateInterval": MessageLookupByLibrary.simpleMessage(
"Auto update interval (minutes)",

View File

@@ -93,6 +93,7 @@ class MessageLookup extends MessageLookupByLibrary {
"autoLaunchDesc": MessageLookupByLibrary.simpleMessage("システムの自動起動に従う"),
"autoRun": MessageLookupByLibrary.simpleMessage("自動実行"),
"autoRunDesc": MessageLookupByLibrary.simpleMessage("アプリ起動時に自動実行"),
"autoSetSystemDns": MessageLookupByLibrary.simpleMessage("オートセットシステムDNS"),
"autoUpdate": MessageLookupByLibrary.simpleMessage("自動更新"),
"autoUpdateInterval": MessageLookupByLibrary.simpleMessage("自動更新間隔(分)"),
"backup": MessageLookupByLibrary.simpleMessage("バックアップ"),

View File

@@ -120,6 +120,9 @@ class MessageLookup extends MessageLookupByLibrary {
"autoRunDesc": MessageLookupByLibrary.simpleMessage(
"Автоматический запуск при открытии приложения",
),
"autoSetSystemDns": MessageLookupByLibrary.simpleMessage(
"Автоматическая настройка системного DNS",
),
"autoUpdate": MessageLookupByLibrary.simpleMessage("Автообновление"),
"autoUpdateInterval": MessageLookupByLibrary.simpleMessage(
"Интервал автообновления (минуты)",

View File

@@ -87,6 +87,7 @@ class MessageLookup extends MessageLookupByLibrary {
"autoLaunchDesc": MessageLookupByLibrary.simpleMessage("跟随系统自启动"),
"autoRun": MessageLookupByLibrary.simpleMessage("自动运行"),
"autoRunDesc": MessageLookupByLibrary.simpleMessage("应用打开时自动运行"),
"autoSetSystemDns": MessageLookupByLibrary.simpleMessage("自动设置系统DNS"),
"autoUpdate": MessageLookupByLibrary.simpleMessage("自动更新"),
"autoUpdateInterval": MessageLookupByLibrary.simpleMessage("自动更新间隔(分钟)"),
"backup": MessageLookupByLibrary.simpleMessage("备份"),

View File

@@ -3129,6 +3129,16 @@ class AppLocalizations {
args: [],
);
}
/// `Auto set system DNS`
String get autoSetSystemDns {
return Intl.message(
'Auto set system DNS',
name: 'autoSetSystemDns',
desc: '',
args: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {

View File

@@ -46,10 +46,29 @@ class _AppStateManagerState extends ConsumerState<AppStateManager>
globalState.appController.savePreferencesDebounce();
}
});
ref.listenManual(
autoSetSystemDnsStateProvider,
(prev, next) async {
if (prev == next) {
return;
}
if (next.a == true && next.b == true) {
system.setMacOSDns(false);
} else {
system.setMacOSDns(true);
}
},
);
}
@override
void dispose() {
reassemble() {
super.reassemble();
}
@override
void dispose() async {
await system.setMacOSDns(true);
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}

View File

@@ -57,7 +57,6 @@ class _ClashContainerState extends ConsumerState<ClashManager>
clashCore.stopLog();
}
},
fireImmediately: true,
);
}

View File

@@ -32,6 +32,7 @@ class AppState with _$AppState {
required FixedList<Traffic> traffics,
required Traffic totalTraffic,
@Default("") String proxiesQuery,
@Default(false) bool realTunEnable,
}) = _AppState;
}

View File

@@ -152,7 +152,8 @@ class NetworkProps with _$NetworkProps {
const factory NetworkProps({
@Default(true) bool systemProxy,
@Default(defaultBypassDomain) List<String> bypassDomain,
@Default(RouteMode.bypassPrivate) RouteMode routeMode,
@Default(RouteMode.config) RouteMode routeMode,
@Default(true) bool autoSetSystemDns,
}) = _NetworkProps;
factory NetworkProps.fromJson(Map<String, Object?>? json) =>

View File

@@ -36,6 +36,7 @@ mixin _$AppState {
FixedList<Traffic> get traffics => throw _privateConstructorUsedError;
Traffic get totalTraffic => throw _privateConstructorUsedError;
String get proxiesQuery => throw _privateConstructorUsedError;
bool get realTunEnable => throw _privateConstructorUsedError;
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.
@@ -68,7 +69,8 @@ abstract class $AppStateCopyWith<$Res> {
FixedList<Log> logs,
FixedList<Traffic> traffics,
Traffic totalTraffic,
String proxiesQuery});
String proxiesQuery,
bool realTunEnable});
}
/// @nodoc
@@ -105,6 +107,7 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
Object? traffics = null,
Object? totalTraffic = null,
Object? proxiesQuery = null,
Object? realTunEnable = null,
}) {
return _then(_value.copyWith(
isInit: null == isInit
@@ -183,6 +186,10 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
? _value.proxiesQuery
: proxiesQuery // ignore: cast_nullable_to_non_nullable
as String,
realTunEnable: null == realTunEnable
? _value.realTunEnable
: realTunEnable // ignore: cast_nullable_to_non_nullable
as bool,
) as $Val);
}
}
@@ -214,7 +221,8 @@ abstract class _$$AppStateImplCopyWith<$Res>
FixedList<Log> logs,
FixedList<Traffic> traffics,
Traffic totalTraffic,
String proxiesQuery});
String proxiesQuery,
bool realTunEnable});
}
/// @nodoc
@@ -249,6 +257,7 @@ class __$$AppStateImplCopyWithImpl<$Res>
Object? traffics = null,
Object? totalTraffic = null,
Object? proxiesQuery = null,
Object? realTunEnable = null,
}) {
return _then(_$AppStateImpl(
isInit: null == isInit
@@ -327,6 +336,10 @@ class __$$AppStateImplCopyWithImpl<$Res>
? _value.proxiesQuery
: proxiesQuery // ignore: cast_nullable_to_non_nullable
as String,
realTunEnable: null == realTunEnable
? _value.realTunEnable
: realTunEnable // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
@@ -353,7 +366,8 @@ class _$AppStateImpl implements _AppState {
required this.logs,
required this.traffics,
required this.totalTraffic,
this.proxiesQuery = ""})
this.proxiesQuery = "",
this.realTunEnable = false})
: _packages = packages,
_delayMap = delayMap,
_groups = groups,
@@ -431,10 +445,13 @@ class _$AppStateImpl implements _AppState {
@override
@JsonKey()
final String proxiesQuery;
@override
@JsonKey()
final bool realTunEnable;
@override
String toString() {
return 'AppState(isInit: $isInit, backBlock: $backBlock, pageLabel: $pageLabel, packages: $packages, sortNum: $sortNum, viewSize: $viewSize, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, proxiesQuery: $proxiesQuery)';
return 'AppState(isInit: $isInit, backBlock: $backBlock, pageLabel: $pageLabel, packages: $packages, sortNum: $sortNum, viewSize: $viewSize, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, proxiesQuery: $proxiesQuery, realTunEnable: $realTunEnable)';
}
@override
@@ -470,7 +487,9 @@ class _$AppStateImpl implements _AppState {
(identical(other.totalTraffic, totalTraffic) ||
other.totalTraffic == totalTraffic) &&
(identical(other.proxiesQuery, proxiesQuery) ||
other.proxiesQuery == proxiesQuery));
other.proxiesQuery == proxiesQuery) &&
(identical(other.realTunEnable, realTunEnable) ||
other.realTunEnable == realTunEnable));
}
@override
@@ -494,7 +513,8 @@ class _$AppStateImpl implements _AppState {
logs,
traffics,
totalTraffic,
proxiesQuery
proxiesQuery,
realTunEnable
]);
/// Create a copy of AppState
@@ -526,7 +546,8 @@ abstract class _AppState implements AppState {
required final FixedList<Log> logs,
required final FixedList<Traffic> traffics,
required final Traffic totalTraffic,
final String proxiesQuery}) = _$AppStateImpl;
final String proxiesQuery,
final bool realTunEnable}) = _$AppStateImpl;
@override
bool get isInit;
@@ -566,6 +587,8 @@ abstract class _AppState implements AppState {
Traffic get totalTraffic;
@override
String get proxiesQuery;
@override
bool get realTunEnable;
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.

View File

@@ -1325,6 +1325,7 @@ mixin _$NetworkProps {
bool get systemProxy => throw _privateConstructorUsedError;
List<String> get bypassDomain => throw _privateConstructorUsedError;
RouteMode get routeMode => throw _privateConstructorUsedError;
bool get autoSetSystemDns => throw _privateConstructorUsedError;
/// Serializes this NetworkProps to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@@ -1342,7 +1343,11 @@ abstract class $NetworkPropsCopyWith<$Res> {
NetworkProps value, $Res Function(NetworkProps) then) =
_$NetworkPropsCopyWithImpl<$Res, NetworkProps>;
@useResult
$Res call({bool systemProxy, List<String> bypassDomain, RouteMode routeMode});
$Res call(
{bool systemProxy,
List<String> bypassDomain,
RouteMode routeMode,
bool autoSetSystemDns});
}
/// @nodoc
@@ -1363,6 +1368,7 @@ class _$NetworkPropsCopyWithImpl<$Res, $Val extends NetworkProps>
Object? systemProxy = null,
Object? bypassDomain = null,
Object? routeMode = null,
Object? autoSetSystemDns = null,
}) {
return _then(_value.copyWith(
systemProxy: null == systemProxy
@@ -1377,6 +1383,10 @@ class _$NetworkPropsCopyWithImpl<$Res, $Val extends NetworkProps>
? _value.routeMode
: routeMode // ignore: cast_nullable_to_non_nullable
as RouteMode,
autoSetSystemDns: null == autoSetSystemDns
? _value.autoSetSystemDns
: autoSetSystemDns // ignore: cast_nullable_to_non_nullable
as bool,
) as $Val);
}
}
@@ -1389,7 +1399,11 @@ abstract class _$$NetworkPropsImplCopyWith<$Res>
__$$NetworkPropsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({bool systemProxy, List<String> bypassDomain, RouteMode routeMode});
$Res call(
{bool systemProxy,
List<String> bypassDomain,
RouteMode routeMode,
bool autoSetSystemDns});
}
/// @nodoc
@@ -1408,6 +1422,7 @@ class __$$NetworkPropsImplCopyWithImpl<$Res>
Object? systemProxy = null,
Object? bypassDomain = null,
Object? routeMode = null,
Object? autoSetSystemDns = null,
}) {
return _then(_$NetworkPropsImpl(
systemProxy: null == systemProxy
@@ -1422,6 +1437,10 @@ class __$$NetworkPropsImplCopyWithImpl<$Res>
? _value.routeMode
: routeMode // ignore: cast_nullable_to_non_nullable
as RouteMode,
autoSetSystemDns: null == autoSetSystemDns
? _value.autoSetSystemDns
: autoSetSystemDns // ignore: cast_nullable_to_non_nullable
as bool,
));
}
}
@@ -1432,7 +1451,8 @@ class _$NetworkPropsImpl implements _NetworkProps {
const _$NetworkPropsImpl(
{this.systemProxy = true,
final List<String> bypassDomain = defaultBypassDomain,
this.routeMode = RouteMode.bypassPrivate})
this.routeMode = RouteMode.config,
this.autoSetSystemDns = true})
: _bypassDomain = bypassDomain;
factory _$NetworkPropsImpl.fromJson(Map<String, dynamic> json) =>
@@ -1453,10 +1473,13 @@ class _$NetworkPropsImpl implements _NetworkProps {
@override
@JsonKey()
final RouteMode routeMode;
@override
@JsonKey()
final bool autoSetSystemDns;
@override
String toString() {
return 'NetworkProps(systemProxy: $systemProxy, bypassDomain: $bypassDomain, routeMode: $routeMode)';
return 'NetworkProps(systemProxy: $systemProxy, bypassDomain: $bypassDomain, routeMode: $routeMode, autoSetSystemDns: $autoSetSystemDns)';
}
@override
@@ -1469,13 +1492,19 @@ class _$NetworkPropsImpl implements _NetworkProps {
const DeepCollectionEquality()
.equals(other._bypassDomain, _bypassDomain) &&
(identical(other.routeMode, routeMode) ||
other.routeMode == routeMode));
other.routeMode == routeMode) &&
(identical(other.autoSetSystemDns, autoSetSystemDns) ||
other.autoSetSystemDns == autoSetSystemDns));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(runtimeType, systemProxy,
const DeepCollectionEquality().hash(_bypassDomain), routeMode);
int get hashCode => Object.hash(
runtimeType,
systemProxy,
const DeepCollectionEquality().hash(_bypassDomain),
routeMode,
autoSetSystemDns);
/// Create a copy of NetworkProps
/// with the given fields replaced by the non-null parameter values.
@@ -1497,7 +1526,8 @@ abstract class _NetworkProps implements NetworkProps {
const factory _NetworkProps(
{final bool systemProxy,
final List<String> bypassDomain,
final RouteMode routeMode}) = _$NetworkPropsImpl;
final RouteMode routeMode,
final bool autoSetSystemDns}) = _$NetworkPropsImpl;
factory _NetworkProps.fromJson(Map<String, dynamic> json) =
_$NetworkPropsImpl.fromJson;
@@ -1508,6 +1538,8 @@ abstract class _NetworkProps implements NetworkProps {
List<String> get bypassDomain;
@override
RouteMode get routeMode;
@override
bool get autoSetSystemDns;
/// Create a copy of NetworkProps
/// with the given fields replaced by the non-null parameter values.

View File

@@ -160,7 +160,8 @@ _$NetworkPropsImpl _$$NetworkPropsImplFromJson(Map<String, dynamic> json) =>
.toList() ??
defaultBypassDomain,
routeMode: $enumDecodeNullable(_$RouteModeEnumMap, json['routeMode']) ??
RouteMode.bypassPrivate,
RouteMode.config,
autoSetSystemDns: json['autoSetSystemDns'] as bool? ?? true,
);
Map<String, dynamic> _$$NetworkPropsImplToJson(_$NetworkPropsImpl instance) =>
@@ -168,6 +169,7 @@ Map<String, dynamic> _$$NetworkPropsImplToJson(_$NetworkPropsImpl instance) =>
'systemProxy': instance.systemProxy,
'bypassDomain': instance.bypassDomain,
'routeMode': _$RouteModeEnumMap[instance.routeMode]!,
'autoSetSystemDns': instance.autoSetSystemDns,
};
const _$RouteModeEnumMap = {

View File

@@ -8,6 +8,21 @@ import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'generated/app.g.dart';
@riverpod
class RealTunEnable extends _$RealTunEnable with AutoDisposeNotifierMixin {
@override
bool build() {
return globalState.appState.realTunEnable;
}
@override
onUpdate(value) {
globalState.appState = globalState.appState.copyWith(
realTunEnable: value,
);
}
}
@riverpod
class Logs extends _$Logs with AutoDisposeNotifierMixin {
@override

View File

@@ -70,6 +70,22 @@ final viewHeightProvider = AutoDisposeProvider<double>.internal(
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
typedef ViewHeightRef = AutoDisposeProviderRef<double>;
String _$realTunEnableHash() => r'a4e995c86deca4c8307966470e69d93d64a40df6';
/// See also [RealTunEnable].
@ProviderFor(RealTunEnable)
final realTunEnableProvider =
AutoDisposeNotifierProvider<RealTunEnable, bool>.internal(
RealTunEnable.new,
name: r'realTunEnableProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
? null
: _$realTunEnableHash,
dependencies: null,
allTransitiveDependencies: null,
);
typedef _$RealTunEnable = AutoDisposeNotifier<bool>;
String _$logsHash() => r'56fb8aa9d62a97b026b749d204576a7384084737';
/// See also [Logs].

View File

@@ -1975,11 +1975,12 @@ class _GenColorSchemeProviderElement
bool get ignoreConfig => (origin as GenColorSchemeProvider).ignoreConfig;
}
String _$needSetupHash() => r'db01ec73ea3232c99d1c5445c80e31b98785f416';
String _$needSetupHash() => r'3668e8dc9f40a9bea45c94321804eb3afa0e7c51';
/// See also [needSetup].
@ProviderFor(needSetup)
final needSetupProvider = AutoDisposeProvider<VM3>.internal(
final needSetupProvider =
AutoDisposeProvider<VM3<String?, String?, Dns?>>.internal(
needSetup,
name: r'needSetupProvider',
debugGetCreateSourceHash:
@@ -1990,7 +1991,26 @@ final needSetupProvider = AutoDisposeProvider<VM3>.internal(
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
typedef NeedSetupRef = AutoDisposeProviderRef<VM3>;
typedef NeedSetupRef = AutoDisposeProviderRef<VM3<String?, String?, Dns?>>;
String _$autoSetSystemDnsStateHash() =>
r'2e0976e079100325b1ca797285df48a94c2c066c';
/// See also [autoSetSystemDnsState].
@ProviderFor(autoSetSystemDnsState)
final autoSetSystemDnsStateProvider =
AutoDisposeProvider<VM2<bool, bool>>.internal(
autoSetSystemDnsState,
name: r'autoSetSystemDnsStateProvider',
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
? null
: _$autoSetSystemDnsStateHash,
dependencies: null,
allTransitiveDependencies: null,
);
@Deprecated('Will be removed in 3.0. Use Ref instead')
// ignore: unused_element
typedef AutoSetSystemDnsStateRef = AutoDisposeProviderRef<VM2<bool, bool>>;
String _$profileOverrideStateHash() =>
r'fa26570a355ab39e27b1f93d1d2f358717065592';

View File

@@ -622,7 +622,7 @@ ColorScheme genColorScheme(
}
@riverpod
VM3 needSetup(Ref ref) {
VM3<String?, String?, Dns?> needSetup(Ref ref) {
final profileId = ref.watch(currentProfileIdProvider);
final content = ref.watch(
scriptStateProvider.select((state) => state.currentScript?.content));
@@ -638,3 +638,18 @@ VM3 needSetup(Ref ref) {
c: dns,
);
}
@riverpod
VM2<bool, bool> autoSetSystemDnsState(Ref ref) {
final isStart = ref.watch(runTimeProvider.select((state) => state != null));
final realTunEnable = ref.watch(realTunEnableProvider);
final autoSetSystemDns = ref.watch(
networkSettingProvider.select(
(state) => state.autoSetSystemDns,
),
);
return VM2(
a: isStart ? realTunEnable : false,
b: autoSetSystemDns,
);
}

View File

@@ -319,10 +319,15 @@ class GlobalState {
config.networkProps.routeMode == RouteMode.bypassPrivate
? defaultBypassPrivateRouteAddress
: patchConfig.tun.routeAddress;
final realPatchConfig = patchConfig.copyWith.tun(
autoRoute: routeAddress.isEmpty ? true : false,
routeAddress: routeAddress,
);
final realPatchConfig = !system.isDesktop
? patchConfig.copyWith.tun(
autoRoute: routeAddress.isEmpty ? true : false,
routeAddress: routeAddress,
)
: patchConfig.copyWith.tun(
autoRoute: true,
routeAddress: [],
);
rawConfig["external-controller"] = realPatchConfig.externalController.value;
rawConfig["external-ui"] = "";
rawConfig["interface-name"] = "";

View File

@@ -155,6 +155,29 @@ class Ipv6Item extends ConsumerWidget {
}
}
class AutoSetSystemDnsItem extends ConsumerWidget {
const AutoSetSystemDnsItem({super.key});
@override
Widget build(BuildContext context, ref) {
final autoSetSystemDns = ref.watch(
networkSettingProvider.select((state) => state.autoSetSystemDns));
return ListItem.switchItem(
title: Text(appLocalizations.autoSetSystemDns),
delegate: SwitchDelegate(
value: autoSetSystemDns,
onChanged: (bool value) async {
ref.read(networkSettingProvider.notifier).updateState(
(state) => state.copyWith(
autoSetSystemDns: value,
),
);
},
),
);
}
}
class TunStackItem extends ConsumerWidget {
const TunStackItem({super.key});
@@ -349,9 +372,12 @@ final networkItems = [
title: appLocalizations.options,
items: [
if (system.isDesktop) const TUNItem(),
if (Platform.isMacOS) const AutoSetSystemDnsItem(),
const TunStackItem(),
const RouteModeItem(),
const RouteAddressItem(),
if (!system.isDesktop) ...[
const RouteModeItem(),
const RouteAddressItem(),
]
],
),
];

View File

@@ -1,3 +1,5 @@
import 'dart:io';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/providers/config.dart';
import 'package:fl_clash/views/config/network.dart';
@@ -23,6 +25,7 @@ class TUNButton extends StatelessWidget {
generateSection(
items: [
if (system.isDesktop) const TUNItem(),
if (Platform.isMacOS) const AutoSetSystemDnsItem(),
const TunStackItem(),
],
),

View File

@@ -1,4 +1,3 @@
import 'package:fl_clash/clash/clash.dart';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart';
@@ -27,7 +26,7 @@ class _OverrideProfileViewState extends State<OverrideProfileView> {
_initState(WidgetRef ref) {
WidgetsBinding.instance.addPostFrameCallback((_) {
Future.delayed(Duration(milliseconds: 300), () async {
final rawConfig = await clashCore.getConfig(widget.profileId);
final rawConfig = await globalState.getProfileConfig(widget.profileId);
final snippet = ClashConfigSnippet.fromJson(rawConfig);
final overrideData = ref.read(
getProfileOverrideDataProvider(widget.profileId),
@@ -598,7 +597,7 @@ class RuleContent extends ConsumerWidget {
tag: CacheTag.rules,
itemBuilder: (context, index) {
final rule = rules[index];
return ReorderableDragStartListener(
return ReorderableDelayedDragStartListener(
key: ObjectKey(rule),
index: index,
child: _buildItem(

View File

@@ -288,7 +288,7 @@ class ListInputPage extends StatelessWidget {
final e = items[index];
return _InputItem(
key: ValueKey(e),
ReorderableDragStartListener(
ReorderableDelayedDragStartListener(
index: index,
child: CommonCard(
child: ListItem(
@@ -440,7 +440,7 @@ class MapInputPage extends StatelessWidget {
final e = items[index];
return _InputItem(
key: ValueKey(e.key),
ReorderableDragStartListener(
ReorderableDelayedDragStartListener(
index: index,
child: CommonCard(
child: ListItem(
@@ -613,7 +613,7 @@ class _InputItem extends StatelessWidget {
color: Colors.transparent,
child: Container(
padding: EdgeInsets.symmetric(horizontal: 16),
margin: EdgeInsets.symmetric(vertical: 4),
margin: EdgeInsets.symmetric(vertical: 8),
child: child,
),
);

View File

@@ -1,7 +1,7 @@
name: fl_clash
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
publish_to: 'none'
version: 0.8.85+202506062
version: 0.8.85+202506071
environment:
sdk: '>=3.1.0 <4.0.0'