Skip to content

Commit d894811

Browse files
committed
Fix windows tray issues
Support setting bypassDomain Update flutter version Fix android service issues Fix macos dock exit button issues Add route address setting Optimize provider view
1 parent 9dcb53b commit d894811

File tree

105 files changed

+7514
-8033
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+7514
-8033
lines changed

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

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import androidx.core.graphics.drawable.toBitmap
1515
import com.follow.clash.TempActivity
1616
import com.follow.clash.models.CIDR
1717
import com.follow.clash.models.Metadata
18+
import com.follow.clash.models.VpnOptions
1819
import io.flutter.plugin.common.MethodChannel
1920
import kotlinx.coroutines.Dispatchers
2021
import kotlinx.coroutines.withContext
@@ -42,6 +43,40 @@ fun Metadata.getProtocol(): Int? {
4243
return null
4344
}
4445

46+
fun VpnOptions.getIpv4RouteAddress(): List<CIDR> {
47+
return routeAddress.filter {
48+
it.isIpv4()
49+
}.map {
50+
it.toCIDR()
51+
}
52+
}
53+
54+
fun VpnOptions.getIpv6RouteAddress(): List<CIDR> {
55+
return routeAddress.filter {
56+
it.isIpv6()
57+
}.map {
58+
it.toCIDR()
59+
}
60+
}
61+
62+
fun String.isIpv4(): Boolean {
63+
val parts = split("/")
64+
if (parts.size != 2) {
65+
throw IllegalArgumentException("Invalid CIDR format")
66+
}
67+
val address = InetAddress.getByName(parts[0])
68+
return address.address.size == 4
69+
}
70+
71+
fun String.isIpv6(): Boolean {
72+
val parts = split("/")
73+
if (parts.size != 2) {
74+
throw IllegalArgumentException("Invalid CIDR format")
75+
}
76+
val address = InetAddress.getByName(parts[0])
77+
return address.address.size == 16
78+
}
79+
4580
fun String.toCIDR(): CIDR {
4681
val parts = split("/")
4782
if (parts.size != 2) {
@@ -79,7 +114,7 @@ fun InetAddress.asSocketAddressText(port: Int): String {
79114
}
80115
}
81116

82-
fun Context.wrapAction(action: String):String{
117+
fun Context.wrapAction(action: String): String {
83118
return "${this.packageName}.action.$action"
84119
}
85120

android/app/src/main/kotlin/com/follow/clash/models/Props.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ package com.follow.clash.models
33
import java.net.InetAddress
44

55
enum class AccessControlMode {
6-
acceptSelected,
7-
rejectSelected,
6+
acceptSelected, rejectSelected,
87
}
98

109
data class AccessControl(
@@ -22,6 +21,7 @@ data class VpnOptions(
2221
val allowBypass: Boolean,
2322
val systemProxy: Boolean,
2423
val bypassDomain: List<String>,
24+
val routeAddress: List<String>,
2525
val ipv4Address: String,
2626
val ipv6Address: String,
2727
val dnsServerAddress: String,

android/app/src/main/kotlin/com/follow/clash/services/FlClashService.kt

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ import com.follow.clash.GlobalState
1717
import com.follow.clash.MainActivity
1818
import com.follow.clash.extensions.getActionPendingIntent
1919
import com.follow.clash.models.VpnOptions
20+
import kotlinx.coroutines.CoroutineScope
21+
import kotlinx.coroutines.Dispatchers
22+
import kotlinx.coroutines.launch
2023

2124

2225
class FlClashService : Service(), BaseServiceInterface {
@@ -69,7 +72,7 @@ class FlClashService : Service(), BaseServiceInterface {
6972
addAction(
7073
0,
7174
GlobalState.getText("stop"),
72-
getActionPendingIntent("CHANGE")
75+
getActionPendingIntent("STOP")
7376
)
7477
setOngoing(true)
7578
setShowWhen(false)
@@ -89,21 +92,23 @@ class FlClashService : Service(), BaseServiceInterface {
8992

9093
@SuppressLint("ForegroundServiceType", "WrongConstant")
9194
override fun startForeground(title: String, content: String) {
92-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
93-
val manager = getSystemService(NotificationManager::class.java)
94-
var channel = manager?.getNotificationChannel(CHANNEL)
95-
if (channel == null) {
96-
channel =
97-
NotificationChannel(CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW)
98-
manager?.createNotificationChannel(channel)
95+
CoroutineScope(Dispatchers.Default).launch {
96+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
97+
val manager = getSystemService(NotificationManager::class.java)
98+
var channel = manager?.getNotificationChannel(CHANNEL)
99+
if (channel == null) {
100+
channel =
101+
NotificationChannel(CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW)
102+
manager?.createNotificationChannel(channel)
103+
}
104+
}
105+
val notification =
106+
notificationBuilder.setContentTitle(title).setContentText(content).build()
107+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
108+
startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_SPECIAL_USE)
109+
} else {
110+
startForeground(notificationId, notification)
99111
}
100-
}
101-
val notification =
102-
notificationBuilder.setContentTitle(title).setContentText(content).build()
103-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
104-
startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_SPECIAL_USE)
105-
} else {
106-
startForeground(notificationId, notification)
107112
}
108113
}
109114
}

android/app/src/main/kotlin/com/follow/clash/services/FlClashVpnService.kt

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,21 @@ import android.os.Build
1515
import android.os.IBinder
1616
import android.os.Parcel
1717
import android.os.RemoteException
18+
import android.util.Log
1819
import androidx.core.app.NotificationCompat
1920
import com.follow.clash.BaseServiceInterface
2021
import com.follow.clash.GlobalState
2122
import com.follow.clash.MainActivity
2223
import com.follow.clash.R
23-
import com.follow.clash.TempActivity
2424
import com.follow.clash.extensions.getActionPendingIntent
25+
import com.follow.clash.extensions.getIpv4RouteAddress
26+
import com.follow.clash.extensions.getIpv6RouteAddress
2527
import com.follow.clash.extensions.toCIDR
2628
import com.follow.clash.models.AccessControlMode
2729
import com.follow.clash.models.VpnOptions
2830
import kotlinx.coroutines.CoroutineScope
2931
import kotlinx.coroutines.Dispatchers
3032
import kotlinx.coroutines.launch
31-
import kotlinx.coroutines.runBlocking
3233

3334

3435
class FlClashVpnService : VpnService(), BaseServiceInterface {
@@ -42,12 +43,28 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
4243
if (options.ipv4Address.isNotEmpty()) {
4344
val cidr = options.ipv4Address.toCIDR()
4445
addAddress(cidr.address, cidr.prefixLength)
45-
addRoute("0.0.0.0", 0)
46+
val routeAddress = options.getIpv4RouteAddress()
47+
if (routeAddress.isNotEmpty()) {
48+
routeAddress.forEach { i ->
49+
Log.d("addRoute4", "address: ${i.address} prefixLength:${i.prefixLength}")
50+
addRoute(i.address, i.prefixLength)
51+
}
52+
} else {
53+
addRoute("0.0.0.0", 0)
54+
}
4655
}
4756
if (options.ipv6Address.isNotEmpty()) {
4857
val cidr = options.ipv6Address.toCIDR()
4958
addAddress(cidr.address, cidr.prefixLength)
50-
addRoute("::", 0)
59+
val routeAddress = options.getIpv6RouteAddress()
60+
if (routeAddress.isNotEmpty()) {
61+
routeAddress.forEach { i ->
62+
Log.d("addRoute6", "address: ${i.address} prefixLength:${i.prefixLength}")
63+
addRoute(i.address, i.prefixLength)
64+
}
65+
} else {
66+
addRoute("::", 0)
67+
}
5168
}
5269
addDnsServer(options.dnsServerAddress)
5370
setMtu(9000)

core/Clash.Meta

0 commit comments

Comments
 (0)