Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1477f9b

Browse files
Fix windows tun issues
Optimize android get system dns Optimize more details
1 parent a06e813 commit 1477f9b

File tree

20 files changed

+164
-120
lines changed

20 files changed

+164
-120
lines changed

‎.github/workflows/build.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
with:
7676
channel: 'stable'
7777
cache: true
78-
flutter-version: 3.29.3
78+
# flutter-version: 3.29.3
7979

8080
- name: Get Flutter Dependency
8181
run: flutter pub get

‎android/app/src/main/kotlin/com/follow/clash/extensions/Ext.kt‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ fun ConnectivityManager.resolveDns(network: Network?): List<String> {
104104
fun InetAddress.asSocketAddressText(port: Int): String {
105105
return when (this) {
106106
is Inet6Address ->
107-
"[${numericToTextFormat(this.address)}]:$port"
107+
"[${numericToTextFormat(this)}]:$port"
108108

109109
is Inet4Address ->
110110
"${this.hostAddress}:$port"
@@ -141,7 +141,8 @@ fun Context.getActionPendingIntent(action: String): PendingIntent {
141141
}
142142
}
143143

144-
private fun numericToTextFormat(src: ByteArray): String {
144+
private fun numericToTextFormat(address: Inet6Address): String {
145+
val src = address.address
145146
val sb = StringBuilder(39)
146147
for (i in 0 until 8) {
147148
sb.append(
@@ -154,6 +155,10 @@ private fun numericToTextFormat(src: ByteArray): String {
154155
sb.append(":")
155156
}
156157
}
158+
if (address.scopeId > 0) {
159+
sb.append("%")
160+
sb.append(address.scopeId)
161+
}
157162
return sb.toString()
158163
}
159164

‎android/app/src/main/kotlin/com/follow/clash/plugins/VpnPlugin.kt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ data object VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
100100
}
101101

102102
fun handleStart(options: VpnOptions): Boolean {
103+
onUpdateNetwork();
103104
if (options.enable != this.options?.enable) {
104105
this.flClashService = null
105106
}

‎lib/common/request.dart‎

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:async';
12
import 'dart:convert';
23
import 'dart:io';
34
import 'dart:typed_data';
@@ -90,37 +91,37 @@ class Request {
9091
"https://ipinfo.io/json/": IpInfo.fromIpInfoIoJson,
9192
};
9293

93-
Future<IpInfo?> checkIp({CancelToken? cancelToken}) async {
94-
for (final source in _ipInfoSources.entries) {
95-
try {
96-
final response = await Dio()
97-
.get<Map<String, dynamic>>(
98-
source.key,
99-
cancelToken: cancelToken,
100-
options: Options(
101-
responseType: ResponseType.json,
102-
),
103-
)
104-
.timeout(
105-
Duration(
106-
seconds: 30,
107-
),
108-
);
109-
if (response.statusCode != 200 || response.data == null) {
110-
continue;
94+
Future<Result<IpInfo?>> checkIp({CancelToken? cancelToken}) async {
95+
var failureCount = 0;
96+
final futures = _ipInfoSources.entries.map((source) async {
97+
final Completer<Result<IpInfo?>> completer = Completer();
98+
final future = Dio().get<Map<String, dynamic>>(
99+
source.key,
100+
cancelToken: cancelToken,
101+
options: Options(
102+
responseType: ResponseType.json,
103+
),
104+
);
105+
future.then((res) {
106+
if (res.statusCode == HttpStatus.ok && res.data != null) {
107+
completer.complete(Result.success(source.value(res.data!)));
108+
} else {
109+
failureCount++;
110+
if (failureCount == _ipInfoSources.length) {
111+
completer.complete(Result.success(null));
112+
}
111113
}
112-
if (response.data == null) {
113-
continue;
114+
}).catchError((e) {
115+
failureCount++;
116+
if (e == DioExceptionType.cancel) {
117+
completer.complete(Result.error("cancelled"));
114118
}
115-
return source.value(response.data!);
116-
} catch (e) {
117-
commonPrint.log("checkIp error ===> $e");
118-
if (e is DioException && e.type == DioExceptionType.cancel) {
119-
throw "cancelled";
120-
}
121-
}
122-
}
123-
return null;
119+
});
120+
return completer.future;
121+
});
122+
final res = await Future.any(futures);
123+
cancelToken?.cancel();
124+
return res;
124125
}
125126

126127
Future<bool> pingHelper() async {

‎lib/main.dart‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Future<void> _service(List<String> flags) async {
6262
vpn?.addListener(
6363
_VpnListenerWithService(
6464
onDnsChanged: (String dns) {
65+
print("handle dns $dns");
6566
clashLibHandler.updateDns(dns);
6667
},
6768
),

‎lib/manager/message_manager.dart‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ class MessageManagerState extends State<MessageManager> {
9191
key: Key(messages.last.id),
9292
builder: (_, constraints) {
9393
return Card(
94-
shape: const RoundedRectangleBorder(
94+
shape: const RoundedSuperellipseBorder(
9595
borderRadius: BorderRadius.all(
9696
Radius.circular(12.0),
9797
),

‎lib/models/clash_config.dart‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,24 @@ class Tun with _$Tun {
200200
}
201201
}
202202

203+
extension TunExt on Tun {
204+
Tun getRealTun(RouteMode routeMode) {
205+
final mRouteAddress = routeMode == RouteMode.bypassPrivate
206+
? defaultBypassPrivateRouteAddress
207+
: routeAddress;
208+
return switch (system.isDesktop) {
209+
true => copyWith(
210+
autoRoute: true,
211+
routeAddress: [],
212+
),
213+
false => copyWith(
214+
autoRoute: mRouteAddress.isEmpty ? true : false,
215+
routeAddress: mRouteAddress,
216+
),
217+
};
218+
}
219+
}
220+
203221
@freezed
204222
class FallbackFilter with _$FallbackFilter {
205223
const factory FallbackFilter({

‎lib/providers/generated/state.g.dart‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎lib/providers/state.dart‎

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,15 @@ CoreState coreState(Ref ref) {
105105

106106
@riverpod
107107
UpdateParams updateParams(Ref ref) {
108+
final routeMode = ref.watch(
109+
networkSettingProvider.select(
110+
(state) => state.routeMode,
111+
),
112+
);
108113
return ref.watch(
109114
patchClashConfigProvider.select(
110115
(state) => UpdateParams(
111-
tun: state.tun,
116+
tun: state.tun.getRealTun(routeMode),
112117
allowLan: state.allowLan,
113118
findProcessMode: state.findProcessMode,
114119
mode: state.mode,
@@ -153,9 +158,11 @@ TrayState trayState(Ref ref) {
153158
final appSetting = ref.watch(
154159
appSettingProvider,
155160
);
156-
final groups = ref.watch(
157-
groupsProvider,
158-
);
161+
final groups = ref
162+
.watch(
163+
currentGroupsStateProvider,
164+
)
165+
.value;
159166
final brightness = ref.watch(
160167
appBrightnessProvider,
161168
);

‎lib/state.dart‎

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -315,19 +315,9 @@ class GlobalState {
315315
final profileId = profile.id;
316316
final configMap = await getProfileConfig(profileId);
317317
final rawConfig = await handleEvaluate(configMap);
318-
final routeAddress =
319-
config.networkProps.routeMode == RouteMode.bypassPrivate
320-
? defaultBypassPrivateRouteAddress
321-
: patchConfig.tun.routeAddress;
322-
final realPatchConfig = !system.isDesktop
323-
? patchConfig.copyWith.tun(
324-
autoRoute: routeAddress.isEmpty ? true : false,
325-
routeAddress: routeAddress,
326-
)
327-
: patchConfig.copyWith.tun(
328-
autoRoute: true,
329-
routeAddress: [],
330-
);
318+
final realPatchConfig = patchConfig.copyWith(
319+
tun: patchConfig.tun.getRealTun(config.networkProps.routeMode),
320+
);
331321
rawConfig["external-controller"] = realPatchConfig.externalController.value;
332322
rawConfig["external-ui"] = "";
333323
rawConfig["interface-name"] = "";
@@ -411,21 +401,23 @@ class GlobalState {
411401
for (final host in realPatchConfig.hosts.entries) {
412402
rawConfig["hosts"][host.key] = host.value.splitByMultipleSeparators;
413403
}
404+
if (rawConfig["dns"] == null) {
405+
rawConfig["dns"] = {};
406+
}
407+
final isEnableDns = rawConfig["dns"]["enable"] == true;
414408
final overrideDns = globalState.config.overrideDns;
415-
if (overrideDns) {
416-
rawConfig["dns"] = realPatchConfig.dns.toJson();
409+
if (overrideDns || !isEnableDns) {
410+
final dns = switch (!isEnableDns) {
411+
true => realPatchConfig.dns.copyWith(
412+
nameserver: [...realPatchConfig.dns.nameserver, "system://"]),
413+
false => realPatchConfig.dns,
414+
};
415+
rawConfig["dns"] = dns.toJson();
417416
rawConfig["dns"]["nameserver-policy"] = {};
418-
for (final entry in realPatchConfig.dns.nameserverPolicy.entries) {
417+
for (final entry in dns.nameserverPolicy.entries) {
419418
rawConfig["dns"]["nameserver-policy"][entry.key] =
420419
entry.value.splitByMultipleSeparators;
421420
}
422-
} else {
423-
if (rawConfig["dns"] == null) {
424-
rawConfig["dns"] = {};
425-
}
426-
if (rawConfig["dns"]["enable"] != false) {
427-
rawConfig["dns"]["enable"] = true;
428-
}
429421
}
430422
var rules = [];
431423
if (rawConfig["rules"] != null) {
@@ -509,6 +501,9 @@ class DetectionState {
509501
debouncer.call(
510502
FunctionTag.checkIp,
511503
_checkIp,
504+
duration: Duration(
505+
milliseconds: 1200,
506+
),
512507
);
513508
}
514509

@@ -533,36 +528,35 @@ class DetectionState {
533528
cancelToken = null;
534529
}
535530
cancelToken = CancelToken();
536-
try {
531+
state.value = state.value.copyWith(
532+
isTesting: true,
533+
);
534+
final res = await request.checkIp(cancelToken: cancelToken);
535+
if (res.isError) {
537536
state.value = state.value.copyWith(
538-
isTesting: true,
537+
isLoading: true,
538+
ipInfo: null,
539539
);
540-
final ipInfo = await request.checkIp(cancelToken: cancelToken);
540+
return;
541+
}
542+
final ipInfo = res.data;
543+
state.value = state.value.copyWith(
544+
isTesting: false,
545+
);
546+
if (ipInfo != null) {
541547
state.value = state.value.copyWith(
542-
isTesting: false,
548+
isLoading: false,
549+
ipInfo: ipInfo,
543550
);
544-
if (ipInfo != null) {
545-
state.value = state.value.copyWith(
546-
isLoading: false,
547-
ipInfo: ipInfo,
548-
);
549-
return;
550-
}
551-
_clearSetTimeoutTimer();
552-
_setTimeoutTimer = Timer(const Duration(milliseconds: 300), () {
553-
state.value = state.value.copyWith(
554-
isLoading: false,
555-
ipInfo: null,
556-
);
557-
});
558-
} catch (e) {
559-
if (e.toString() == "cancelled") {
560-
state.value = state.value.copyWith(
561-
isLoading: true,
562-
ipInfo: null,
563-
);
564-
}
551+
return;
565552
}
553+
_clearSetTimeoutTimer();
554+
_setTimeoutTimer = Timer(const Duration(milliseconds: 300), () {
555+
state.value = state.value.copyWith(
556+
isLoading: false,
557+
ipInfo: null,
558+
);
559+
});
566560
}
567561

568562
_clearSetTimeoutTimer() {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /