Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
043648f998 | ||
|
|
3eb26e8061 | ||
|
|
5d6bd6466f |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,7 +1,7 @@
|
||||
[submodule "core/Clash.Meta"]
|
||||
path = core/Clash.Meta
|
||||
url = git@github.com:chen08209/Clash.Meta.git
|
||||
branch = FlClash
|
||||
branch = FlClash-Alpha
|
||||
[submodule "plugins/flutter_distributor"]
|
||||
path = plugins/flutter_distributor
|
||||
url = git@github.com:chen08209/flutter_distributor.git
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package com.follow.clash
|
||||
|
||||
import com.follow.clash.models.Props
|
||||
import com.follow.clash.models.TunProps
|
||||
|
||||
interface BaseServiceInterface {
|
||||
fun start(port: Int, props: Props?): Int?
|
||||
fun start(port: Int, props: Props?): TunProps?
|
||||
fun stop()
|
||||
fun startForeground(title: String, content: String)
|
||||
}
|
||||
@@ -39,8 +39,7 @@ object GlobalState {
|
||||
}
|
||||
|
||||
fun getCurrentVPNPlugin(): VpnPlugin? {
|
||||
val currentEngine = if (serviceEngine != null) serviceEngine else flutterEngine
|
||||
return currentEngine?.plugins?.get(VpnPlugin::class.java) as VpnPlugin?
|
||||
return serviceEngine?.plugins?.get(VpnPlugin::class.java) as VpnPlugin?
|
||||
}
|
||||
|
||||
fun destroyServiceEngine() {
|
||||
|
||||
@@ -1,28 +1,20 @@
|
||||
package com.follow.clash.extensions
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification.FOREGROUND_SERVICE_IMMEDIATE
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import android.system.OsConstants.IPPROTO_TCP
|
||||
import android.system.OsConstants.IPPROTO_UDP
|
||||
import android.util.Base64
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import com.follow.clash.MainActivity
|
||||
import com.follow.clash.R
|
||||
import com.follow.clash.models.Metadata
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.net.Inet4Address
|
||||
import java.net.Inet6Address
|
||||
import java.net.InetAddress
|
||||
|
||||
|
||||
suspend fun Drawable.getBase64(): String {
|
||||
@@ -41,6 +33,37 @@ fun Metadata.getProtocol(): Int? {
|
||||
return null
|
||||
}
|
||||
|
||||
private val CHANNEL = "FlClash"
|
||||
|
||||
private val notificationId: Int = 1
|
||||
fun ConnectivityManager.resolvePrimaryDns(network: Network?): String? {
|
||||
val properties = getLinkProperties(network) ?: return null
|
||||
return properties.dnsServers.firstOrNull()?.asSocketAddressText(53)
|
||||
}
|
||||
|
||||
fun InetAddress.asSocketAddressText(port: Int): String {
|
||||
return when (this) {
|
||||
is Inet6Address ->
|
||||
"[${numericToTextFormat(this.address)}]:$port"
|
||||
|
||||
is Inet4Address ->
|
||||
"${this.hostAddress}:$port"
|
||||
|
||||
else -> throw IllegalArgumentException("Unsupported Inet type ${this.javaClass}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun numericToTextFormat(src: ByteArray): String {
|
||||
val sb = StringBuilder(39)
|
||||
for (i in 0 until 8) {
|
||||
sb.append(
|
||||
Integer.toHexString(
|
||||
src[i shl 1].toInt() shl 8 and 0xff00
|
||||
or (src[(i shl 1) + 1].toInt() and 0xff)
|
||||
)
|
||||
)
|
||||
if (i < 7) {
|
||||
sb.append(":")
|
||||
}
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
26
android/app/src/main/kotlin/com/follow/clash/models/Dns.kt
Normal file
26
android/app/src/main/kotlin/com/follow/clash/models/Dns.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
package com.follow.clash.models
|
||||
|
||||
import android.net.NetworkCapabilities
|
||||
import android.os.Build
|
||||
|
||||
val TRANSPORT_PRIORITY = sequence {
|
||||
yield(NetworkCapabilities.TRANSPORT_CELLULAR)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 27) {
|
||||
yield(NetworkCapabilities.TRANSPORT_LOWPAN)
|
||||
}
|
||||
|
||||
yield(NetworkCapabilities.TRANSPORT_BLUETOOTH)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 26) {
|
||||
yield(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
|
||||
}
|
||||
|
||||
yield(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 31) {
|
||||
yield(NetworkCapabilities.TRANSPORT_USB)
|
||||
}
|
||||
|
||||
yield(NetworkCapabilities.TRANSPORT_ETHERNET)
|
||||
}.toList()
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.follow.clash.models
|
||||
|
||||
import java.util.Date
|
||||
|
||||
data class Package(
|
||||
val packageName: String,
|
||||
val label: String,
|
||||
|
||||
@@ -17,3 +17,13 @@ data class Props(
|
||||
val allowBypass: Boolean?,
|
||||
val systemProxy: Boolean?,
|
||||
)
|
||||
|
||||
data class TunProps(
|
||||
val fd: Int,
|
||||
val gateway: String,
|
||||
val gateway6: String,
|
||||
val portal: String,
|
||||
val portal6: String,
|
||||
val dns: String,
|
||||
val dns6: String
|
||||
)
|
||||
@@ -8,7 +8,6 @@ import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.ComponentInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.VpnService
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
@@ -17,12 +16,9 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.ContextCompat.getSystemService
|
||||
import com.android.tools.smali.dexlib2.dexbacked.DexBackedDexFile
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.content.getSystemService
|
||||
import com.follow.clash.GlobalState
|
||||
import com.follow.clash.extensions.getBase64
|
||||
import com.follow.clash.extensions.getProtocol
|
||||
import com.follow.clash.models.Package
|
||||
import com.follow.clash.models.Process
|
||||
import com.google.gson.Gson
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
@@ -37,7 +33,6 @@ import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
import java.net.InetSocketAddress
|
||||
import java.util.zip.ZipFile
|
||||
|
||||
class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware {
|
||||
@@ -52,11 +47,10 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
|
||||
|
||||
private lateinit var scope: CoroutineScope
|
||||
|
||||
private var connectivity: ConnectivityManager? = null
|
||||
|
||||
private var vpnCallBack: (() -> Unit)? = null
|
||||
|
||||
private val iconMap = mutableMapOf<String, String?>()
|
||||
|
||||
private val packages = mutableListOf<Package>()
|
||||
|
||||
private val skipPrefixList = listOf(
|
||||
@@ -114,7 +108,6 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
|
||||
("(" + chinaAppPrefixList.joinToString("|").replace(".", "\\.") + ").*").toRegex()
|
||||
}
|
||||
|
||||
|
||||
val VPN_PERMISSION_REQUEST_CODE = 1001
|
||||
|
||||
val NOTIFICATION_PERMISSION_REQUEST_CODE = 1002
|
||||
@@ -191,48 +184,6 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
|
||||
}
|
||||
}
|
||||
|
||||
"resolverProcess" -> {
|
||||
val data = call.argument<String>("data")
|
||||
val process =
|
||||
if (data != null) Gson().fromJson(
|
||||
data,
|
||||
Process::class.java
|
||||
) else null
|
||||
val metadata = process?.metadata
|
||||
val protocol = metadata?.getProtocol()
|
||||
if (protocol == null) {
|
||||
result.success(null)
|
||||
return
|
||||
}
|
||||
scope.launch {
|
||||
withContext(Dispatchers.Default) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
result.success(null)
|
||||
return@withContext
|
||||
}
|
||||
if (connectivity == null) {
|
||||
connectivity = context.getSystemService<ConnectivityManager>()
|
||||
}
|
||||
val src = InetSocketAddress(metadata.sourceIP, metadata.sourcePort)
|
||||
val dst = InetSocketAddress(
|
||||
metadata.destinationIP.ifEmpty { metadata.host },
|
||||
metadata.destinationPort
|
||||
)
|
||||
val uid = try {
|
||||
connectivity?.getConnectionOwnerUid(protocol, src, dst)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
if (uid == null || uid == -1) {
|
||||
result.success(null)
|
||||
return@withContext
|
||||
}
|
||||
val packages = context.packageManager?.getPackagesForUid(uid)
|
||||
result.success(packages?.first())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"tip" -> {
|
||||
val message = call.argument<String>("message")
|
||||
tip(message)
|
||||
@@ -379,7 +330,6 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun isChinaPackage(packageName: String): Boolean {
|
||||
val packageManager = context.packageManager ?: return false
|
||||
skipPrefixList.forEach {
|
||||
@@ -447,10 +397,6 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
|
||||
return false
|
||||
}
|
||||
|
||||
fun requestGc() {
|
||||
channel.invokeMethod("gc", null)
|
||||
}
|
||||
|
||||
override fun onAttachedToActivity(binding: ActivityPluginBinding) {
|
||||
activity = binding.activity;
|
||||
binding.addActivityResultListener(::onActivityResult)
|
||||
@@ -490,4 +436,4 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.follow.clash.plugins
|
||||
|
||||
import android.content.Context
|
||||
import android.net.ConnectivityManager
|
||||
import androidx.core.content.getSystemService
|
||||
import com.follow.clash.GlobalState
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
|
||||
@@ -5,19 +5,33 @@ import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkRequest
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import androidx.core.content.getSystemService
|
||||
import com.follow.clash.BaseServiceInterface
|
||||
import com.follow.clash.GlobalState
|
||||
import com.follow.clash.RunState
|
||||
import com.follow.clash.extensions.getProtocol
|
||||
import com.follow.clash.extensions.resolvePrimaryDns
|
||||
import com.follow.clash.models.Props
|
||||
import com.follow.clash.models.TunProps
|
||||
import com.follow.clash.services.FlClashService
|
||||
import com.follow.clash.services.FlClashVpnService
|
||||
import com.google.gson.Gson
|
||||
import io.flutter.embedding.engine.plugins.FlutterPlugin
|
||||
import io.flutter.plugin.common.MethodCall
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.net.InetSocketAddress
|
||||
import kotlin.concurrent.withLock
|
||||
import com.follow.clash.models.Process
|
||||
|
||||
|
||||
class VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
||||
@@ -26,6 +40,11 @@ class VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
||||
private var flClashService: BaseServiceInterface? = null
|
||||
private var port: Int = 7890
|
||||
private var props: Props? = null
|
||||
private lateinit var scope: CoroutineScope
|
||||
|
||||
private val connectivity by lazy {
|
||||
context.getSystemService<ConnectivityManager>()
|
||||
}
|
||||
|
||||
private val connection = object : ServiceConnection {
|
||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||
@@ -43,55 +62,104 @@ class VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
||||
}
|
||||
|
||||
override fun onAttachedToEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
scope = CoroutineScope(Dispatchers.Default)
|
||||
context = flutterPluginBinding.applicationContext
|
||||
scope.launch {
|
||||
registerNetworkCallback()
|
||||
}
|
||||
flutterMethodChannel = MethodChannel(flutterPluginBinding.binaryMessenger, "vpn")
|
||||
flutterMethodChannel.setMethodCallHandler(this)
|
||||
}
|
||||
|
||||
override fun onDetachedFromEngine(flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
unRegisterNetworkCallback()
|
||||
flutterMethodChannel.setMethodCallHandler(null)
|
||||
}
|
||||
|
||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) = when (call.method) {
|
||||
|
||||
"start" -> {
|
||||
port = call.argument<Int>("port")!!
|
||||
val args = call.argument<String>("args")
|
||||
props =
|
||||
if (args != null) Gson().fromJson(args, Props::class.java) else null
|
||||
when (props?.enable == true) {
|
||||
true -> handleStartVpn()
|
||||
false -> start()
|
||||
}
|
||||
result.success(true)
|
||||
}
|
||||
|
||||
"stop" -> {
|
||||
stop()
|
||||
result.success(true)
|
||||
}
|
||||
|
||||
"setProtect" -> {
|
||||
val fd = call.argument<Int>("fd")
|
||||
if (fd != null) {
|
||||
if (flClashService is FlClashVpnService) {
|
||||
(flClashService as FlClashVpnService).protect(fd)
|
||||
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
|
||||
when (call.method) {
|
||||
"start" -> {
|
||||
port = call.argument<Int>("port")!!
|
||||
val args = call.argument<String>("args")
|
||||
props =
|
||||
if (args != null) Gson().fromJson(args, Props::class.java) else null
|
||||
when (props?.enable == true) {
|
||||
true -> handleStartVpn()
|
||||
false -> start()
|
||||
}
|
||||
result.success(true)
|
||||
} else {
|
||||
result.success(false)
|
||||
}
|
||||
}
|
||||
|
||||
"startForeground" -> {
|
||||
val title = call.argument<String>("title") as String
|
||||
val content = call.argument<String>("content") as String
|
||||
startForeground(title, content)
|
||||
result.success(true)
|
||||
}
|
||||
"stop" -> {
|
||||
stop()
|
||||
result.success(true)
|
||||
}
|
||||
|
||||
else -> {
|
||||
result.notImplemented()
|
||||
"setProtect" -> {
|
||||
val fd = call.argument<Int>("fd")
|
||||
if (fd != null) {
|
||||
if (flClashService is FlClashVpnService) {
|
||||
(flClashService as FlClashVpnService).protect(fd)
|
||||
}
|
||||
result.success(true)
|
||||
} else {
|
||||
result.success(false)
|
||||
}
|
||||
}
|
||||
|
||||
"startForeground" -> {
|
||||
val title = call.argument<String>("title") as String
|
||||
val content = call.argument<String>("content") as String
|
||||
startForeground(title, content)
|
||||
result.success(true)
|
||||
}
|
||||
|
||||
"resolverProcess" -> {
|
||||
val data = call.argument<String>("data")
|
||||
val process =
|
||||
if (data != null) Gson().fromJson(
|
||||
data,
|
||||
Process::class.java
|
||||
) else null
|
||||
val metadata = process?.metadata
|
||||
if (metadata == null) {
|
||||
result.success(null)
|
||||
return
|
||||
}
|
||||
val protocol = metadata.getProtocol()
|
||||
if (protocol == null) {
|
||||
result.success(null)
|
||||
return
|
||||
}
|
||||
scope.launch {
|
||||
withContext(Dispatchers.Default) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
result.success(null)
|
||||
return@withContext
|
||||
}
|
||||
val src = InetSocketAddress(metadata.sourceIP, metadata.sourcePort)
|
||||
val dst = InetSocketAddress(
|
||||
metadata.destinationIP.ifEmpty { metadata.host },
|
||||
metadata.destinationPort
|
||||
)
|
||||
val uid = try {
|
||||
connectivity?.getConnectionOwnerUid(protocol, src, dst)
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
if (uid == null || uid == -1) {
|
||||
result.success(null)
|
||||
return@withContext
|
||||
}
|
||||
val packages = context.packageManager?.getPackagesForUid(uid)
|
||||
result.success(packages?.first())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
result.notImplemented()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +170,62 @@ class VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
||||
}
|
||||
}
|
||||
|
||||
fun requestGc() {
|
||||
flutterMethodChannel.invokeMethod("gc", null)
|
||||
}
|
||||
|
||||
val networks = mutableSetOf<Network>()
|
||||
|
||||
fun onUpdateNetwork() {
|
||||
val dns = networks.mapNotNull {
|
||||
connectivity?.resolvePrimaryDns(it)
|
||||
}.joinToString(separator = ",")
|
||||
scope.launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
flutterMethodChannel.invokeMethod("dnsChanged", dns)
|
||||
}
|
||||
}
|
||||
// if (flClashService is FlClashVpnService) {
|
||||
// val network = networks.maxByOrNull { net ->
|
||||
// connectivity?.getNetworkCapabilities(net)?.let { cap ->
|
||||
// TRANSPORT_PRIORITY.indexOfFirst { cap.hasTransport(it) }
|
||||
// } ?: -1
|
||||
// }
|
||||
// network?.let {
|
||||
// (flClashService as FlClashVpnService).updateUnderlyingNetworks(arrayOf(network))
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private val callback = object : ConnectivityManager.NetworkCallback() {
|
||||
override fun onAvailable(network: Network) {
|
||||
networks.add(network)
|
||||
onUpdateNetwork()
|
||||
}
|
||||
|
||||
override fun onLost(network: Network) {
|
||||
networks.remove(network)
|
||||
onUpdateNetwork()
|
||||
}
|
||||
}
|
||||
|
||||
private val request = NetworkRequest.Builder().apply {
|
||||
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
|
||||
addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
|
||||
addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
|
||||
}.build()
|
||||
|
||||
private fun registerNetworkCallback() {
|
||||
networks.clear()
|
||||
connectivity?.registerNetworkCallback(request, callback)
|
||||
}
|
||||
|
||||
private fun unRegisterNetworkCallback() {
|
||||
connectivity?.unregisterNetworkCallback(callback)
|
||||
networks.clear()
|
||||
onUpdateNetwork()
|
||||
}
|
||||
|
||||
@SuppressLint("ForegroundServiceType")
|
||||
private fun startForeground(title: String, content: String) {
|
||||
GlobalState.runLock.withLock {
|
||||
@@ -118,8 +242,11 @@ class VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
||||
GlobalState.runLock.withLock {
|
||||
if (GlobalState.runState.value == RunState.START) return
|
||||
GlobalState.runState.value = RunState.START
|
||||
val fd = flClashService?.start(port, props)
|
||||
flutterMethodChannel.invokeMethod("started", fd)
|
||||
val tunProps = flClashService?.start(port, props)
|
||||
flutterMethodChannel.invokeMethod(
|
||||
"started",
|
||||
Gson().toJson(tunProps, TunProps::class.java)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class FlClashService : Service(), BaseServiceInterface {
|
||||
}
|
||||
}
|
||||
|
||||
override fun start(port: Int, props: Props?): Int? = null
|
||||
override fun start(port: Int, props: Props?) = null
|
||||
|
||||
override fun stop() {
|
||||
stopSelf()
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Intent
|
||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
|
||||
import android.net.Network
|
||||
import android.net.ProxyInfo
|
||||
import android.net.VpnService
|
||||
import android.os.Binder
|
||||
@@ -22,6 +23,7 @@ import com.follow.clash.MainActivity
|
||||
import com.follow.clash.R
|
||||
import com.follow.clash.models.AccessControlMode
|
||||
import com.follow.clash.models.Props
|
||||
import com.follow.clash.models.TunProps
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -30,36 +32,53 @@ import kotlinx.coroutines.launch
|
||||
@SuppressLint("WrongConstant")
|
||||
class FlClashVpnService : VpnService(), BaseServiceInterface {
|
||||
|
||||
private val passList = listOf(
|
||||
"*zhihu.com",
|
||||
"*zhimg.com",
|
||||
"*jd.com",
|
||||
"100ime-iat-api.xfyun.cn",
|
||||
"*360buyimg.com",
|
||||
"localhost",
|
||||
"*.local",
|
||||
"127.*",
|
||||
"10.*",
|
||||
"172.16.*",
|
||||
"172.17.*",
|
||||
"172.18.*",
|
||||
"172.19.*",
|
||||
"172.2*",
|
||||
"172.30.*",
|
||||
"172.31.*",
|
||||
"192.168.*"
|
||||
)
|
||||
companion object {
|
||||
private val passList = listOf(
|
||||
"*zhihu.com",
|
||||
"*zhimg.com",
|
||||
"*jd.com",
|
||||
"100ime-iat-api.xfyun.cn",
|
||||
"*360buyimg.com",
|
||||
"localhost",
|
||||
"*.local",
|
||||
"127.*",
|
||||
"10.*",
|
||||
"172.16.*",
|
||||
"172.17.*",
|
||||
"172.18.*",
|
||||
"172.19.*",
|
||||
"172.2*",
|
||||
"172.30.*",
|
||||
"172.31.*",
|
||||
"192.168.*"
|
||||
)
|
||||
private const val TUN_MTU = 9000
|
||||
private const val TUN_SUBNET_PREFIX = 30
|
||||
private const val TUN_GATEWAY = "172.19.0.1"
|
||||
private const val TUN_SUBNET_PREFIX6 = 126
|
||||
private const val TUN_GATEWAY6 = "fdfe:dcba:9876::1"
|
||||
private const val TUN_PORTAL = "172.19.0.2"
|
||||
private const val TUN_PORTAL6 = "fdfe:dcba:9876::2"
|
||||
private const val TUN_DNS = TUN_PORTAL
|
||||
private const val TUN_DNS6 = TUN_PORTAL6
|
||||
private const val NET_ANY = "0.0.0.0"
|
||||
private const val NET_ANY6 = "::"
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
GlobalState.initServiceEngine(applicationContext)
|
||||
}
|
||||
|
||||
override fun start(port: Int, props: Props?): Int? {
|
||||
override fun start(port: Int, props: Props?): TunProps {
|
||||
return with(Builder()) {
|
||||
addAddress("172.16.0.1", 30)
|
||||
setMtu(9000)
|
||||
addRoute("0.0.0.0", 0)
|
||||
addAddress(TUN_GATEWAY, TUN_SUBNET_PREFIX)
|
||||
addAddress(TUN_GATEWAY6, TUN_SUBNET_PREFIX6)
|
||||
addRoute(NET_ANY, 0)
|
||||
addRoute(NET_ANY6, 0)
|
||||
addDnsServer(TUN_DNS)
|
||||
addDnsServer(TUN_DNS6)
|
||||
setMtu(TUN_MTU)
|
||||
props?.accessControl?.let { accessControl ->
|
||||
when (accessControl.mode) {
|
||||
AccessControlMode.acceptSelected -> {
|
||||
@@ -75,7 +94,6 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
|
||||
}
|
||||
}
|
||||
}
|
||||
addDnsServer("172.16.0.2")
|
||||
setSession("FlClash")
|
||||
setBlocking(false)
|
||||
if (Build.VERSION.SDK_INT >= 29) {
|
||||
@@ -93,10 +111,24 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
|
||||
)
|
||||
)
|
||||
}
|
||||
establish()?.detachFd()
|
||||
TunProps(
|
||||
fd = establish()?.detachFd()
|
||||
?: throw NullPointerException("Establish VPN rejected by system"),
|
||||
gateway = "$TUN_GATEWAY/$TUN_SUBNET_PREFIX",
|
||||
gateway6 = "$TUN_GATEWAY6/$TUN_SUBNET_PREFIX6",
|
||||
portal = TUN_PORTAL,
|
||||
portal6 = TUN_PORTAL6,
|
||||
dns = TUN_DNS,
|
||||
dns6 = TUN_DNS6
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateUnderlyingNetworks( networks: Array<Network>){
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
||||
this.setUnderlyingNetworks(networks)
|
||||
}
|
||||
}
|
||||
|
||||
override fun stop() {
|
||||
stopSelf()
|
||||
@@ -165,7 +197,7 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
|
||||
|
||||
override fun onTrimMemory(level: Int) {
|
||||
super.onTrimMemory(level)
|
||||
GlobalState.getCurrentAppPlugin()?.requestGc()
|
||||
GlobalState.getCurrentVPNPlugin()?.requestGc()
|
||||
}
|
||||
|
||||
private val binder = LocalBinder()
|
||||
|
||||
BIN
assets/images/icon_black.ico
Normal file
BIN
assets/images/icon_black.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
BIN
assets/images/icon_black.png
Normal file
BIN
assets/images/icon_black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
assets/images/icon_white.ico
Normal file
BIN
assets/images/icon_white.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Submodule core/Clash.Meta updated: a61c926a17...e89569916a
20
core/dns.go
Normal file
20
core/dns.go
Normal file
@@ -0,0 +1,20 @@
|
||||
//go:build android
|
||||
|
||||
package main
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"github.com/metacubex/mihomo/dns"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//export updateDns
|
||||
func updateDns(s *C.char) {
|
||||
dnsList := C.GoString(s)
|
||||
go func() {
|
||||
log.Infoln("[DNS] updateDns %s", dnsList)
|
||||
dns.UpdateSystemDNS(strings.Split(dnsList, ","))
|
||||
dns.FlushCacheWithDefaultResolver()
|
||||
}()
|
||||
}
|
||||
15
core/go.mod
15
core/go.mod
@@ -4,12 +4,9 @@ go 1.21.0
|
||||
|
||||
replace github.com/metacubex/mihomo => ./Clash.Meta
|
||||
|
||||
require (
|
||||
github.com/Kr328/tun2socket v0.0.0-20220414050025-d07c78d06d34
|
||||
github.com/metacubex/mihomo v1.17.1
|
||||
github.com/miekg/dns v1.1.62
|
||||
golang.org/x/sync v0.8.0
|
||||
)
|
||||
require github.com/metacubex/mihomo v1.17.1
|
||||
|
||||
replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297
|
||||
|
||||
require (
|
||||
github.com/3andne/restls-client-go v0.1.6 // indirect
|
||||
@@ -54,7 +51,7 @@ require (
|
||||
github.com/metacubex/chacha v0.1.0 // indirect
|
||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // indirect
|
||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec // indirect
|
||||
github.com/metacubex/quic-go v0.46.1-0.20240807232329-1c6cb2d67f58 // indirect
|
||||
github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4 // indirect
|
||||
github.com/metacubex/randv2 v0.2.0 // indirect
|
||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 // indirect
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8 // indirect
|
||||
@@ -64,6 +61,7 @@ require (
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20240826061955-1e4e67afe5cd // indirect
|
||||
github.com/metacubex/tfo-go v0.0.0-20240830120620-c5e019b67785 // indirect
|
||||
github.com/metacubex/utls v1.6.6 // indirect
|
||||
github.com/miekg/dns v1.1.62 // indirect
|
||||
github.com/mroth/weightedrand/v2 v2.1.0 // indirect
|
||||
github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
@@ -103,11 +101,12 @@ require (
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/net v0.28.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.24.0 // indirect
|
||||
golang.org/x/text v0.17.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect; indirect`
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
)
|
||||
|
||||
19
core/go.sum
19
core/go.sum
@@ -1,7 +1,5 @@
|
||||
github.com/3andne/restls-client-go v0.1.6 h1:tRx/YilqW7iHpgmEL4E1D8dAsuB0tFF3uvncS+B6I08=
|
||||
github.com/3andne/restls-client-go v0.1.6/go.mod h1:iEdTZNt9kzPIxjIGSMScUFSBrUH6bFRNg0BWlP4orEY=
|
||||
github.com/Kr328/tun2socket v0.0.0-20220414050025-d07c78d06d34 h1:USCTqih5d1bUXUxWNS9ZD5Tx/lb0jXHEtRIIx/F9dMc=
|
||||
github.com/Kr328/tun2socket v0.0.0-20220414050025-d07c78d06d34/go.mod h1:YR9wK13TgI5ww8iKWm91MHiSoHC7Oz0U4beCCmtXqLw=
|
||||
github.com/RyuaNerin/elliptic2 v1.0.0/go.mod h1:wWB8fWrJI/6EPJkyV/r1Rj0hxUgrusmqSj8JN6yNf/A=
|
||||
github.com/RyuaNerin/go-krypto v1.2.4 h1:mXuNdK6M317aPV0llW6Xpjbo4moOlPF7Yxz4tb4b4Go=
|
||||
github.com/RyuaNerin/go-krypto v1.2.4/go.mod h1:QqCYkoutU3yInyD9INt2PGolVRsc3W4oraQadVGXJ/8=
|
||||
@@ -106,10 +104,12 @@ github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvO
|
||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec h1:HxreOiFTUrJXJautEo8rnE1uKTVGY8wtZepY1Tii/Nc=
|
||||
github.com/metacubex/gvisor v0.0.0-20240320004321-933faba989ec/go.mod h1:8BVmQ+3cxjqzWElafm24rb2Ae4jRI6vAXNXWqWjfrXw=
|
||||
github.com/metacubex/quic-go v0.46.1-0.20240807232329-1c6cb2d67f58 h1:T6OxROLZBr9SOQxN5TzUslv81hEREy/dEgaUKVjaG7U=
|
||||
github.com/metacubex/quic-go v0.46.1-0.20240807232329-1c6cb2d67f58/go.mod h1:Yza2H7Ax1rxWPUcJx0vW+oAt9EsPuSiyQFhFabUPzwU=
|
||||
github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4 h1:CgdUBRxmNlxEGkp35HwvgQ10jwOOUJKWdOxpi8yWi8o=
|
||||
github.com/metacubex/quic-go v0.47.1-0.20240909010619-6b38f24bfcc4/go.mod h1:Y7yRGqFE6UQL/3aKPYmiYdjfVkeujJaStP4+jiZMcN8=
|
||||
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
||||
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
||||
github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297 h1:YG/JkwGPbca5rUtEMHIu8ZuqzR7BSVm1iqY8hNoMeMA=
|
||||
github.com/metacubex/sing v0.0.0-20240724044459-6f3cf5896297/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4 h1:HobpULaPK6OoxrHMmgcwLkwwIduXVmwdcznwUfH1GQM=
|
||||
github.com/metacubex/sing-quic v0.0.0-20240827003841-cd97758ed8b4/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8=
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJRafgwBHO5B4=
|
||||
@@ -162,9 +162,6 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
|
||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
|
||||
github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||
github.com/sagernet/sing v0.5.0-alpha.13 h1:fpR4TFZfu/9V3LbHSAnnnwcaXGMF8ijmAAPoY2WHSKw=
|
||||
github.com/sagernet/sing v0.5.0-alpha.13/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 h1:5bCAkvDDzSMITiHFjolBwpdqYsvycdTu71FsMEFXQ14=
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||
@@ -190,9 +187,15 @@ github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e/go.mod h1:+e
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
@@ -250,7 +253,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||
|
||||
@@ -378,27 +378,28 @@ func updateGeoData(geoType *C.char, geoName *C.char, port C.longlong) {
|
||||
geoTypeString := C.GoString(geoType)
|
||||
geoNameString := C.GoString(geoName)
|
||||
go func() {
|
||||
path := constant.Path.Resolve(geoNameString)
|
||||
switch geoTypeString {
|
||||
case "MMDB":
|
||||
err := updater.UpdateMMDB(constant.Path.Resolve(geoNameString))
|
||||
err := updater.UpdateMMDBWithPath(path)
|
||||
if err != nil {
|
||||
bridge.SendToPort(i, err.Error())
|
||||
return
|
||||
}
|
||||
case "ASN":
|
||||
err := updater.UpdateASN(constant.Path.Resolve(geoNameString))
|
||||
err := updater.UpdateASNWithPath(path)
|
||||
if err != nil {
|
||||
bridge.SendToPort(i, err.Error())
|
||||
return
|
||||
}
|
||||
case "GeoIp":
|
||||
err := updater.UpdateGeoIp(constant.Path.Resolve(geoNameString))
|
||||
err := updater.UpdateGeoIpWithPath(path)
|
||||
if err != nil {
|
||||
bridge.SendToPort(i, err.Error())
|
||||
return
|
||||
}
|
||||
case "GeoSite":
|
||||
err := updater.UpdateGeoSite(constant.Path.Resolve(geoNameString))
|
||||
err := updater.UpdateGeoSiteWithPath(path)
|
||||
if err != nil {
|
||||
bridge.SendToPort(i, err.Error())
|
||||
return
|
||||
|
||||
54
core/tun.go
54
core/tun.go
@@ -6,7 +6,9 @@ import "C"
|
||||
import (
|
||||
"core/platform"
|
||||
t "core/tun"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/metacubex/mihomo/listener/sing_tun"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -15,11 +17,9 @@ import (
|
||||
|
||||
"github.com/metacubex/mihomo/component/dialer"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
var tunLock sync.Mutex
|
||||
var tun *t.Tun
|
||||
var runTime *time.Time
|
||||
|
||||
type FdMap struct {
|
||||
@@ -35,13 +35,18 @@ func (cm *FdMap) Load(key int64) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
var fdMap FdMap
|
||||
var (
|
||||
tunListener *sing_tun.Listener
|
||||
fdMap FdMap
|
||||
fdCounter int64 = 0
|
||||
)
|
||||
|
||||
//export startTUN
|
||||
func startTUN(fd C.int, port C.longlong) {
|
||||
func startTUN(s *C.char, port C.longlong) {
|
||||
i := int64(port)
|
||||
ServicePort = i
|
||||
if fd == 0 {
|
||||
paramsString := C.GoString(s)
|
||||
if paramsString == "" {
|
||||
tunLock.Lock()
|
||||
defer tunLock.Unlock()
|
||||
now := time.Now()
|
||||
@@ -57,28 +62,22 @@ func startTUN(fd C.int, port C.longlong) {
|
||||
tunLock.Lock()
|
||||
defer tunLock.Unlock()
|
||||
|
||||
if tun != nil {
|
||||
tun.Close()
|
||||
tun = nil
|
||||
}
|
||||
|
||||
f := int(fd)
|
||||
gateway := "172.16.0.1/30"
|
||||
portal := "172.16.0.2"
|
||||
dns := "0.0.0.0"
|
||||
|
||||
tempTun := &t.Tun{Closed: false, Limit: semaphore.NewWeighted(4)}
|
||||
|
||||
closer, err := t.Start(f, gateway, portal, dns)
|
||||
|
||||
var tunProps = &t.Props{}
|
||||
err := json.Unmarshal([]byte(paramsString), tunProps)
|
||||
if err != nil {
|
||||
log.Errorln("startTUN error: %v", err)
|
||||
tempTun.Close()
|
||||
return
|
||||
}
|
||||
|
||||
tempTun.Closer = closer
|
||||
tunListener, err = t.Start(*tunProps)
|
||||
|
||||
tun = tempTun
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tunListener != nil {
|
||||
log.Infoln("TUN address: %v", tunListener.Address())
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
@@ -108,9 +107,8 @@ func stopTun() {
|
||||
|
||||
runTime = nil
|
||||
|
||||
if tun != nil {
|
||||
tun.Close()
|
||||
tun = nil
|
||||
if tunListener != nil {
|
||||
_ = tunListener.Close()
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -137,18 +135,12 @@ func markSocket(fd Fd) {
|
||||
})
|
||||
}
|
||||
|
||||
var fdCounter int64 = 0
|
||||
|
||||
func initSocketHook() {
|
||||
dialer.DefaultSocketHook = func(network, address string, conn syscall.RawConn) error {
|
||||
if platform.ShouldBlockConnection() {
|
||||
return errBlocked
|
||||
}
|
||||
return conn.Control(func(fd uintptr) {
|
||||
if tun == nil {
|
||||
return
|
||||
}
|
||||
|
||||
fdInt := int64(fd)
|
||||
timeout := time.After(100 * time.Millisecond)
|
||||
id := atomic.AddInt64(&fdCounter, 1)
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
//go:build android
|
||||
|
||||
package tun
|
||||
|
||||
import (
|
||||
"github.com/metacubex/mihomo/dns"
|
||||
D "github.com/miekg/dns"
|
||||
"net"
|
||||
)
|
||||
|
||||
func shouldHijackDns(dns net.IP, target net.IP, targetPort int) bool {
|
||||
if targetPort != 53 {
|
||||
return false
|
||||
}
|
||||
|
||||
return net.IPv4zero.Equal(dns) || target.Equal(dns)
|
||||
}
|
||||
|
||||
func relayDns(payload []byte) ([]byte, error) {
|
||||
msg := &D.Msg{}
|
||||
if err := msg.Unpack(payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r, err := dns.ServeDNSWithDefaultServer(msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r.SetRcode(msg, r.Rcode)
|
||||
|
||||
return r.Pack()
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
//go:build android
|
||||
|
||||
package tun
|
||||
|
||||
import (
|
||||
"github.com/metacubex/mihomo/constant"
|
||||
"net"
|
||||
)
|
||||
|
||||
func createMetadata(lAddr, rAddr *net.TCPAddr) *constant.Metadata {
|
||||
return &constant.Metadata{
|
||||
NetWork: constant.TCP,
|
||||
Type: constant.SOCKS5,
|
||||
SrcIP: lAddr.AddrPort().Addr(),
|
||||
DstIP: rAddr.AddrPort().Addr(),
|
||||
SrcPort: uint16(lAddr.Port),
|
||||
DstPort: uint16(rAddr.Port),
|
||||
Host: "",
|
||||
}
|
||||
}
|
||||
209
core/tun/tun.go
209
core/tun/tun.go
@@ -4,182 +4,65 @@ package tun
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"github.com/Kr328/tun2socket"
|
||||
"github.com/Kr328/tun2socket/nat"
|
||||
"github.com/metacubex/mihomo/adapter/inbound"
|
||||
"github.com/metacubex/mihomo/common/pool"
|
||||
"github.com/metacubex/mihomo/constant"
|
||||
LC "github.com/metacubex/mihomo/listener/config"
|
||||
"github.com/metacubex/mihomo/listener/sing_tun"
|
||||
"github.com/metacubex/mihomo/log"
|
||||
"github.com/metacubex/mihomo/transport/socks5"
|
||||
"github.com/metacubex/mihomo/tunnel"
|
||||
"golang.org/x/sync/semaphore"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
"net/netip"
|
||||
)
|
||||
|
||||
type Tun struct {
|
||||
Closer io.Closer
|
||||
|
||||
Closed bool
|
||||
Limit *semaphore.Weighted
|
||||
type Props struct {
|
||||
Fd int `json:"fd"`
|
||||
Gateway string `json:"gateway"`
|
||||
Gateway6 string `json:"gateway6"`
|
||||
Portal string `json:"portal"`
|
||||
Portal6 string `json:"portal6"`
|
||||
Dns string `json:"dns"`
|
||||
Dns6 string `json:"dns6"`
|
||||
}
|
||||
|
||||
func (t *Tun) Close() {
|
||||
_ = t.Limit.Acquire(context.TODO(), 4)
|
||||
defer t.Limit.Release(4)
|
||||
|
||||
t.Closed = true
|
||||
|
||||
if t.Closer != nil {
|
||||
_ = t.Closer.Close()
|
||||
}
|
||||
}
|
||||
|
||||
var _, ipv4LoopBack, _ = net.ParseCIDR("127.0.0.0/8")
|
||||
|
||||
func Start(fd int, gateway, portal, dns string) (io.Closer, error) {
|
||||
device := os.NewFile(uintptr(fd), "/dev/tun")
|
||||
ip, network, err := net.ParseCIDR(gateway)
|
||||
func Start(tunProps Props) (*sing_tun.Listener, error) {
|
||||
var prefix4 []netip.Prefix
|
||||
tempPrefix4, err := netip.ParsePrefix(tunProps.Gateway)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
} else {
|
||||
network.IP = ip
|
||||
log.Errorln("startTUN error:", err)
|
||||
return nil, err
|
||||
}
|
||||
stack, err := tun2socket.StartTun2Socket(device, network, net.ParseIP(portal))
|
||||
prefix4 = append(prefix4, tempPrefix4)
|
||||
|
||||
var prefix6 []netip.Prefix
|
||||
tempPrefix6, err := netip.ParsePrefix(tunProps.Gateway6)
|
||||
if err != nil {
|
||||
log.Errorln("startTUN error:", err)
|
||||
return nil, err
|
||||
}
|
||||
prefix6 = append(prefix6, tempPrefix6)
|
||||
|
||||
var dnsHijack []string
|
||||
dnsHijack = append(dnsHijack, net.JoinHostPort(tunProps.Dns, "53"))
|
||||
dnsHijack = append(dnsHijack, net.JoinHostPort(tunProps.Dns6, "53"))
|
||||
|
||||
options := LC.Tun{
|
||||
Enable: true,
|
||||
Device: sing_tun.InterfaceName,
|
||||
Stack: constant.TunSystem,
|
||||
DNSHijack: dnsHijack,
|
||||
AutoRoute: false,
|
||||
AutoDetectInterface: false,
|
||||
Inet4Address: prefix4,
|
||||
Inet6Address: prefix6,
|
||||
MTU: 9000,
|
||||
FileDescriptor: tunProps.Fd,
|
||||
}
|
||||
|
||||
listener, err := sing_tun.New(options, tunnel.Tunnel)
|
||||
|
||||
if err != nil {
|
||||
_ = device.Close()
|
||||
log.Errorln("startTUN error:", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dnsAddr := net.ParseIP(dns)
|
||||
|
||||
tcp := func() {
|
||||
defer func(tcp *nat.TCP) {
|
||||
_ = tcp.Close()
|
||||
}(stack.TCP())
|
||||
defer log.Debugln("TCP: closed")
|
||||
|
||||
for stack.TCP().SetDeadline(time.Time{}) == nil {
|
||||
conn, err := stack.TCP().Accept()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
lAddr := conn.LocalAddr().(*net.TCPAddr)
|
||||
rAddr := conn.RemoteAddr().(*net.TCPAddr)
|
||||
|
||||
if ipv4LoopBack.Contains(rAddr.IP) {
|
||||
_ = conn.Close()
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if shouldHijackDns(dnsAddr, rAddr.IP, rAddr.Port) {
|
||||
go func() {
|
||||
defer func(conn net.Conn) {
|
||||
_ = conn.Close()
|
||||
}(conn)
|
||||
|
||||
buf := pool.Get(pool.UDPBufferSize)
|
||||
defer func(buf []byte) {
|
||||
_ = pool.Put(buf)
|
||||
}(buf)
|
||||
|
||||
for {
|
||||
_ = conn.SetReadDeadline(time.Now().Add(constant.DefaultTCPTimeout))
|
||||
|
||||
length := uint16(0)
|
||||
if err := binary.Read(conn, binary.BigEndian, &length); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if int(length) > len(buf) {
|
||||
return
|
||||
}
|
||||
|
||||
n, err := conn.Read(buf[:length])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
msg, err := relayDns(buf[:n])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, _ = conn.Write(msg)
|
||||
}
|
||||
}()
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
go tunnel.Tunnel.HandleTCPConn(conn, createMetadata(lAddr, rAddr))
|
||||
}
|
||||
}
|
||||
|
||||
udp := func() {
|
||||
defer func(udp *nat.UDP) {
|
||||
_ = udp.Close()
|
||||
}(stack.UDP())
|
||||
defer log.Debugln("UDP: closed")
|
||||
|
||||
for {
|
||||
buf := pool.Get(pool.UDPBufferSize)
|
||||
|
||||
n, lRAddr, rRAddr, err := stack.UDP().ReadFrom(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
raw := buf[:n]
|
||||
lAddr := lRAddr.(*net.UDPAddr)
|
||||
rAddr := rRAddr.(*net.UDPAddr)
|
||||
|
||||
if ipv4LoopBack.Contains(rAddr.IP) {
|
||||
_ = pool.Put(buf)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if shouldHijackDns(dnsAddr, rAddr.IP, rAddr.Port) {
|
||||
go func() {
|
||||
defer func(buf []byte) {
|
||||
_ = pool.Put(buf)
|
||||
}(buf)
|
||||
|
||||
msg, err := relayDns(raw)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, _ = stack.UDP().WriteTo(msg, rAddr, lAddr)
|
||||
}()
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
pkt := &packet{
|
||||
local: lAddr,
|
||||
data: raw,
|
||||
writeBack: func(b []byte, addr net.Addr) (int, error) {
|
||||
return stack.UDP().WriteTo(b, addr, lAddr)
|
||||
},
|
||||
drop: func() {
|
||||
_ = pool.Put(buf)
|
||||
},
|
||||
}
|
||||
|
||||
tunnel.Tunnel.HandleUDPPacket(inbound.NewPacket(socks5.ParseAddrToSocksAddr(rAddr), pkt, constant.SOCKS5))
|
||||
}
|
||||
}
|
||||
|
||||
go tcp()
|
||||
go udp()
|
||||
|
||||
return stack, nil
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
//go:build android
|
||||
|
||||
package tun
|
||||
|
||||
import "net"
|
||||
|
||||
type packet struct {
|
||||
local *net.UDPAddr
|
||||
data []byte
|
||||
writeBack func(b []byte, addr net.Addr) (int, error)
|
||||
drop func()
|
||||
}
|
||||
|
||||
func (pkt *packet) Data() []byte {
|
||||
return pkt.data
|
||||
}
|
||||
|
||||
func (pkt *packet) WriteBack(b []byte, addr net.Addr) (n int, err error) {
|
||||
return pkt.writeBack(b, addr)
|
||||
}
|
||||
|
||||
func (pkt *packet) Drop() {
|
||||
pkt.drop()
|
||||
}
|
||||
|
||||
func (pkt *packet) LocalAddr() net.Addr {
|
||||
return pkt.local
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dynamic_color/dynamic_color.dart';
|
||||
import 'package:fl_clash/l10n/l10n.dart';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/manager/hotkey_manager.dart';
|
||||
import 'package:fl_clash/manager/manager.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:fl_clash/widgets/proxy_container.dart';
|
||||
import 'package:fl_clash/widgets/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@@ -53,6 +54,7 @@ class Application extends StatefulWidget {
|
||||
|
||||
class ApplicationState extends State<Application> {
|
||||
late SystemColorSchemes systemColorSchemes;
|
||||
Timer? timer;
|
||||
|
||||
final _pageTransitionsTheme = const PageTransitionsTheme(
|
||||
builders: <TargetPlatform, PageTransitionsBuilder>{
|
||||
@@ -81,6 +83,7 @@ class ApplicationState extends State<Application> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initTimer();
|
||||
globalState.appController = AppController(context);
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||
final currentContext = globalState.navigatorKey.currentContext;
|
||||
@@ -92,18 +95,36 @@ class ApplicationState extends State<Application> {
|
||||
});
|
||||
}
|
||||
|
||||
_initTimer() {
|
||||
_cancelTimer();
|
||||
timer = Timer.periodic(const Duration(milliseconds: 20000), (_) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
globalState.appController.updateGroupDebounce();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_cancelTimer() {
|
||||
if (timer != null) {
|
||||
timer?.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
_buildApp(Widget app) {
|
||||
if (system.isDesktop) {
|
||||
return WindowContainer(
|
||||
child: TrayContainer(
|
||||
child: ProxyContainer(
|
||||
child: app,
|
||||
return WindowManager(
|
||||
child: TrayManager(
|
||||
child: HotKeyManager(
|
||||
child: ProxyManager(
|
||||
child: app,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return AndroidContainer(
|
||||
child: TileContainer(
|
||||
return AndroidManager(
|
||||
child: TileManager(
|
||||
child: app,
|
||||
),
|
||||
);
|
||||
@@ -115,7 +136,7 @@ class ApplicationState extends State<Application> {
|
||||
child: page,
|
||||
);
|
||||
}
|
||||
return VpnContainer(
|
||||
return VpnManager(
|
||||
child: page,
|
||||
);
|
||||
}
|
||||
@@ -136,8 +157,8 @@ class ApplicationState extends State<Application> {
|
||||
@override
|
||||
Widget build(context) {
|
||||
return _buildApp(
|
||||
AppStateContainer(
|
||||
child: ClashContainer(
|
||||
AppStateManager(
|
||||
child: ClashManager(
|
||||
child: Selector2<AppState, Config, ApplicationSelectorState>(
|
||||
selector: (_, appState, config) => ApplicationSelectorState(
|
||||
locale: config.locale,
|
||||
@@ -158,7 +179,7 @@ class ApplicationState extends State<Application> {
|
||||
GlobalWidgetsLocalizations.delegate
|
||||
],
|
||||
builder: (_, child) {
|
||||
return MediaContainer(
|
||||
return MediaManager(
|
||||
child: _buildPage(child!),
|
||||
);
|
||||
},
|
||||
@@ -203,5 +224,6 @@ class ApplicationState extends State<Application> {
|
||||
linkManager.destroy();
|
||||
await globalState.appController.savePreferences();
|
||||
super.dispose();
|
||||
_cancelTimer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ class ClashCore {
|
||||
final externalProviderRawString =
|
||||
externalProviderRaw.cast<Utf8>().toDartString();
|
||||
clashFFI.freeCString(externalProviderRaw);
|
||||
if(externalProviderRawString.isEmpty) return null;
|
||||
if (externalProviderRawString.isEmpty) return null;
|
||||
return ExternalProvider.fromJson(json.decode(externalProviderRawString));
|
||||
}
|
||||
|
||||
@@ -322,9 +322,18 @@ class ClashCore {
|
||||
clashFFI.stopLog();
|
||||
}
|
||||
|
||||
startTun(int fd, int port) {
|
||||
startTun(TunProps? tunProps, int port) {
|
||||
if (!Platform.isAndroid) return;
|
||||
clashFFI.startTUN(fd, port);
|
||||
final tunPropsChar = json.encode(tunProps).toNativeUtf8().cast<Char>();
|
||||
clashFFI.startTUN(tunPropsChar, port);
|
||||
malloc.free(tunPropsChar);
|
||||
}
|
||||
|
||||
updateDns(String dns) {
|
||||
if (!Platform.isAndroid) return;
|
||||
final dnsChar = dns.toNativeUtf8().cast<Char>();
|
||||
clashFFI.updateDns(dnsChar);
|
||||
malloc.free(dnsChar);
|
||||
}
|
||||
|
||||
requestGc() {
|
||||
|
||||
@@ -5264,6 +5264,20 @@ class ClashFFI {
|
||||
late final _getProxies =
|
||||
_getProxiesPtr.asFunction<ffi.Pointer<ffi.Char> Function()>();
|
||||
|
||||
void updateDns(
|
||||
ffi.Pointer<ffi.Char> s,
|
||||
) {
|
||||
return _updateDns(
|
||||
s,
|
||||
);
|
||||
}
|
||||
|
||||
late final _updateDnsPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>(
|
||||
'updateDns');
|
||||
late final _updateDns =
|
||||
_updateDnsPtr.asFunction<void Function(ffi.Pointer<ffi.Char>)>();
|
||||
|
||||
void changeProxy(
|
||||
ffi.Pointer<ffi.Char> s,
|
||||
) {
|
||||
@@ -5567,19 +5581,20 @@ class ClashFFI {
|
||||
_setStatePtr.asFunction<void Function(ffi.Pointer<ffi.Char>)>();
|
||||
|
||||
void startTUN(
|
||||
int fd,
|
||||
ffi.Pointer<ffi.Char> s,
|
||||
int port,
|
||||
) {
|
||||
return _startTUN(
|
||||
fd,
|
||||
s,
|
||||
port,
|
||||
);
|
||||
}
|
||||
|
||||
late final _startTUNPtr =
|
||||
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int, ffi.LongLong)>>(
|
||||
'startTUN');
|
||||
late final _startTUN = _startTUNPtr.asFunction<void Function(int, int)>();
|
||||
late final _startTUNPtr = _lookup<
|
||||
ffi.NativeFunction<
|
||||
ffi.Void Function(ffi.Pointer<ffi.Char>, ffi.LongLong)>>('startTUN');
|
||||
late final _startTUN =
|
||||
_startTUNPtr.asFunction<void Function(ffi.Pointer<ffi.Char>, int)>();
|
||||
|
||||
ffi.Pointer<ffi.Char> getRunTime() {
|
||||
return _getRunTime();
|
||||
|
||||
@@ -27,4 +27,5 @@ export 'windows.dart';
|
||||
export 'iterable.dart';
|
||||
export 'scroll.dart';
|
||||
export 'icons.dart';
|
||||
export 'http.dart';
|
||||
export 'http.dart';
|
||||
export 'keyboard.dart';
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'dart:io';
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
@@ -16,7 +17,11 @@ const mmdbFileName = "geoip.metadb";
|
||||
const asnFileName = "ASN.mmdb";
|
||||
const geoIpFileName = "GeoIP.dat";
|
||||
const geoSiteFileName = "GeoSite.dat";
|
||||
final double kHeaderHeight = system.isDesktop ? 40 : 0;
|
||||
final double kHeaderHeight = system.isDesktop
|
||||
? !Platform.isMacOS
|
||||
? 40
|
||||
: 26
|
||||
: 0;
|
||||
const GeoXMap defaultGeoXMap = {
|
||||
"mmdb":
|
||||
"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb",
|
||||
|
||||
106
lib/common/keyboard.dart
Normal file
106
lib/common/keyboard.dart
Normal file
@@ -0,0 +1,106 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:uni_platform/uni_platform.dart';
|
||||
|
||||
final Map<PhysicalKeyboardKey, String> _knownKeyLabels =
|
||||
<PhysicalKeyboardKey, String>{
|
||||
PhysicalKeyboardKey.keyA: 'A',
|
||||
PhysicalKeyboardKey.keyB: 'B',
|
||||
PhysicalKeyboardKey.keyC: 'C',
|
||||
PhysicalKeyboardKey.keyD: 'D',
|
||||
PhysicalKeyboardKey.keyE: 'E',
|
||||
PhysicalKeyboardKey.keyF: 'F',
|
||||
PhysicalKeyboardKey.keyG: 'G',
|
||||
PhysicalKeyboardKey.keyH: 'H',
|
||||
PhysicalKeyboardKey.keyI: 'I',
|
||||
PhysicalKeyboardKey.keyJ: 'J',
|
||||
PhysicalKeyboardKey.keyK: 'K',
|
||||
PhysicalKeyboardKey.keyL: 'L',
|
||||
PhysicalKeyboardKey.keyM: 'M',
|
||||
PhysicalKeyboardKey.keyN: 'N',
|
||||
PhysicalKeyboardKey.keyO: 'O',
|
||||
PhysicalKeyboardKey.keyP: 'P',
|
||||
PhysicalKeyboardKey.keyQ: 'Q',
|
||||
PhysicalKeyboardKey.keyR: 'R',
|
||||
PhysicalKeyboardKey.keyS: 'S',
|
||||
PhysicalKeyboardKey.keyT: 'T',
|
||||
PhysicalKeyboardKey.keyU: 'U',
|
||||
PhysicalKeyboardKey.keyV: 'V',
|
||||
PhysicalKeyboardKey.keyW: 'W',
|
||||
PhysicalKeyboardKey.keyX: 'X',
|
||||
PhysicalKeyboardKey.keyY: 'Y',
|
||||
PhysicalKeyboardKey.keyZ: 'Z',
|
||||
PhysicalKeyboardKey.digit1: '1',
|
||||
PhysicalKeyboardKey.digit2: '2',
|
||||
PhysicalKeyboardKey.digit3: '3',
|
||||
PhysicalKeyboardKey.digit4: '4',
|
||||
PhysicalKeyboardKey.digit5: '5',
|
||||
PhysicalKeyboardKey.digit6: '6',
|
||||
PhysicalKeyboardKey.digit7: '7',
|
||||
PhysicalKeyboardKey.digit8: '8',
|
||||
PhysicalKeyboardKey.digit9: '9',
|
||||
PhysicalKeyboardKey.digit0: '0',
|
||||
PhysicalKeyboardKey.enter: 'ENTER',
|
||||
PhysicalKeyboardKey.escape: 'ESCAPE',
|
||||
PhysicalKeyboardKey.backspace: 'BACKSPACE',
|
||||
PhysicalKeyboardKey.tab: 'TAB',
|
||||
PhysicalKeyboardKey.space: 'SPACE',
|
||||
PhysicalKeyboardKey.minus: '-',
|
||||
PhysicalKeyboardKey.equal: '=',
|
||||
PhysicalKeyboardKey.bracketLeft: '[',
|
||||
PhysicalKeyboardKey.bracketRight: ']',
|
||||
PhysicalKeyboardKey.backslash: '\\',
|
||||
PhysicalKeyboardKey.semicolon: ';',
|
||||
PhysicalKeyboardKey.quote: '"',
|
||||
PhysicalKeyboardKey.backquote: '`',
|
||||
PhysicalKeyboardKey.comma: ',',
|
||||
PhysicalKeyboardKey.period: '.',
|
||||
PhysicalKeyboardKey.slash: '/',
|
||||
PhysicalKeyboardKey.capsLock: 'CAPSLOCK',
|
||||
PhysicalKeyboardKey.f1: 'F1',
|
||||
PhysicalKeyboardKey.f2: 'F2',
|
||||
PhysicalKeyboardKey.f3: 'F3',
|
||||
PhysicalKeyboardKey.f4: 'F4',
|
||||
PhysicalKeyboardKey.f5: 'F5',
|
||||
PhysicalKeyboardKey.f6: 'F6',
|
||||
PhysicalKeyboardKey.f7: 'F7',
|
||||
PhysicalKeyboardKey.f8: 'F8',
|
||||
PhysicalKeyboardKey.f9: 'F9',
|
||||
PhysicalKeyboardKey.f10: 'F10',
|
||||
PhysicalKeyboardKey.f11: 'F11',
|
||||
PhysicalKeyboardKey.f12: 'F12',
|
||||
PhysicalKeyboardKey.home: 'HOME',
|
||||
PhysicalKeyboardKey.pageUp: 'PAGEUP',
|
||||
PhysicalKeyboardKey.delete: 'DELETE',
|
||||
PhysicalKeyboardKey.end: 'END',
|
||||
PhysicalKeyboardKey.pageDown: 'PAGEDOWN',
|
||||
PhysicalKeyboardKey.arrowRight: '→',
|
||||
PhysicalKeyboardKey.arrowLeft: '←',
|
||||
PhysicalKeyboardKey.arrowDown: '↓',
|
||||
PhysicalKeyboardKey.arrowUp: '↑',
|
||||
PhysicalKeyboardKey.controlLeft: "CTRL",
|
||||
PhysicalKeyboardKey.shiftLeft: 'SHIFT',
|
||||
PhysicalKeyboardKey.altLeft: "ALT",
|
||||
PhysicalKeyboardKey.metaLeft: Platform.isMacOS ? '⌘' : 'WIN',
|
||||
PhysicalKeyboardKey.controlRight: "CTRL",
|
||||
PhysicalKeyboardKey.shiftRight: 'SHIFT',
|
||||
PhysicalKeyboardKey.altRight: "ALT",
|
||||
PhysicalKeyboardKey.metaRight: Platform.isMacOS ? '⌘' : 'WIN',
|
||||
PhysicalKeyboardKey.fn: 'FN',
|
||||
};
|
||||
|
||||
extension KeyboardKeyExt on KeyboardKey {
|
||||
String get label {
|
||||
PhysicalKeyboardKey? physicalKey;
|
||||
if (this is LogicalKeyboardKey) {
|
||||
physicalKey = (this as LogicalKeyboardKey).physicalKey;
|
||||
} else if (this is PhysicalKeyboardKey) {
|
||||
physicalKey = this as PhysicalKeyboardKey;
|
||||
}
|
||||
return _knownKeyLabels[physicalKey] ?? physicalKey?.debugName ?? 'Unknown';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -100,12 +100,18 @@ class Other {
|
||||
}
|
||||
}
|
||||
|
||||
String getTrayIconPath() {
|
||||
if (Platform.isWindows) {
|
||||
return "assets/images/icon.ico";
|
||||
} else {
|
||||
return "assets/images/icon_monochrome.png";
|
||||
String getTrayIconPath({
|
||||
required bool isStart,
|
||||
required Brightness brightness,
|
||||
}) {
|
||||
final suffix = Platform.isWindows ? "ico" : "png";
|
||||
if (!isStart && Platform.isWindows) {
|
||||
return switch (brightness) {
|
||||
Brightness.dark => "assets/images/icon_white.$suffix",
|
||||
Brightness.light => "assets/images/icon_black.$suffix",
|
||||
};
|
||||
}
|
||||
return "assets/images/icon.$suffix";
|
||||
}
|
||||
|
||||
int compareVersions(String version1, String version2) {
|
||||
@@ -201,9 +207,9 @@ class Other {
|
||||
int getProxiesColumns(double viewWidth, ProxiesLayout proxiesLayout) {
|
||||
final columns = max((viewWidth / 300).ceil(), 2);
|
||||
return switch (proxiesLayout) {
|
||||
ProxiesLayout.tight => columns - 1,
|
||||
ProxiesLayout.tight => columns + 1,
|
||||
ProxiesLayout.standard => columns,
|
||||
ProxiesLayout.loose => columns + 1,
|
||||
ProxiesLayout.loose => columns - 1,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'dart:typed_data';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/models/ip.dart';
|
||||
import 'package:fl_clash/models/models.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:fl_clash/plugins/app.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import 'window.dart';
|
||||
|
||||
@@ -24,6 +26,16 @@ class System {
|
||||
return result.exitCode == 0;
|
||||
}
|
||||
|
||||
Future<int> get version async {
|
||||
final deviceInfo = await DeviceInfoPlugin().deviceInfo;
|
||||
return switch (Platform.operatingSystem) {
|
||||
"macos" => (deviceInfo as MacOsDeviceInfo).majorVersion,
|
||||
"android" => (deviceInfo as AndroidDeviceInfo).version.sdkInt,
|
||||
"windows" => (deviceInfo as WindowsDeviceInfo).majorVersion,
|
||||
String() => 0
|
||||
};
|
||||
}
|
||||
|
||||
back() async {
|
||||
await app?.moveTaskToBack();
|
||||
await window?.hide();
|
||||
|
||||
16
lib/common/window.dart
Normal file → Executable file
16
lib/common/window.dart
Normal file → Executable file
@@ -9,7 +9,7 @@ import 'protocol.dart';
|
||||
import 'system.dart';
|
||||
|
||||
class Window {
|
||||
init(WindowProps props) async {
|
||||
init(WindowProps props, int version) async {
|
||||
if (Platform.isWindows) {
|
||||
await WindowsSingleInstance.ensureSingleInstance([], "FlClash");
|
||||
protocol.register("clash");
|
||||
@@ -20,8 +20,6 @@ class Window {
|
||||
WindowOptions windowOptions = WindowOptions(
|
||||
size: Size(props.width, props.height),
|
||||
minimumSize: const Size(380, 500),
|
||||
windowButtonVisibility: false,
|
||||
titleBarStyle: TitleBarStyle.hidden,
|
||||
);
|
||||
if (props.left != null || props.top != null) {
|
||||
await windowManager.setPosition(
|
||||
@@ -30,9 +28,9 @@ class Window {
|
||||
} else {
|
||||
await windowManager.setAlignment(Alignment.center);
|
||||
}
|
||||
// if(Platform.isWindows){
|
||||
// await windowManager.setTitleBarStyle(TitleBarStyle.hidden);
|
||||
// }
|
||||
if(!Platform.isMacOS || version > 10){
|
||||
await windowManager.setTitleBarStyle(TitleBarStyle.hidden);
|
||||
}
|
||||
await windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
await windowManager.setPreventClose(true);
|
||||
});
|
||||
@@ -41,6 +39,11 @@ class Window {
|
||||
show() async {
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
await windowManager.setSkipTaskbar(false);
|
||||
}
|
||||
|
||||
Future<bool> isVisible() async {
|
||||
return await windowManager.isVisible();
|
||||
}
|
||||
|
||||
close() async {
|
||||
@@ -49,6 +52,7 @@ class Window {
|
||||
|
||||
hide() async {
|
||||
await windowManager.hide();
|
||||
await windowManager.setSkipTaskbar(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -295,6 +295,10 @@ class AppController {
|
||||
}
|
||||
|
||||
init() async {
|
||||
final isDisclaimerAccepted = await handlerDisclaimer();
|
||||
if (!isDisclaimerAccepted) {
|
||||
system.exit();
|
||||
}
|
||||
updateLogStatus();
|
||||
if (!config.silentLaunch) {
|
||||
window?.show();
|
||||
@@ -311,14 +315,6 @@ class AppController {
|
||||
autoCheckUpdate();
|
||||
}
|
||||
|
||||
updateTray() {
|
||||
globalState.updateTray(
|
||||
appState: appState,
|
||||
config: config,
|
||||
clashConfig: clashConfig,
|
||||
);
|
||||
}
|
||||
|
||||
setDelay(Delay delay) {
|
||||
appState.setDelay(delay);
|
||||
}
|
||||
@@ -381,6 +377,47 @@ class AppController {
|
||||
globalState.showSnackBar(context, message: message);
|
||||
}
|
||||
|
||||
Future<bool> showDisclaimer() async {
|
||||
return await globalState.showCommonDialog<bool>(
|
||||
dismissible: false,
|
||||
child: AlertDialog(
|
||||
title: Text(appLocalizations.disclaimer),
|
||||
content: Container(
|
||||
width: dialogCommonWidth,
|
||||
constraints: const BoxConstraints(maxHeight: 200),
|
||||
child: SingleChildScrollView(
|
||||
child: SelectableText(
|
||||
appLocalizations.disclaimerDesc,
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop<bool>(false);
|
||||
},
|
||||
child: Text(appLocalizations.exit),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
config.isDisclaimerAccepted = true;
|
||||
Navigator.of(context).pop<bool>(true);
|
||||
},
|
||||
child: Text(appLocalizations.agree),
|
||||
)
|
||||
],
|
||||
),
|
||||
) ??
|
||||
false;
|
||||
}
|
||||
|
||||
Future<bool> handlerDisclaimer() async {
|
||||
if (config.isDisclaimerAccepted) {
|
||||
return true;
|
||||
}
|
||||
return showDisclaimer();
|
||||
}
|
||||
|
||||
addProfileFormURL(String url) async {
|
||||
if (globalState.navigatorKey.currentState?.canPop() ?? false) {
|
||||
globalState.navigatorKey.currentState?.popUntil((route) => route.isFirst);
|
||||
@@ -496,6 +533,44 @@ class AppController {
|
||||
});
|
||||
}
|
||||
|
||||
updateTun() {
|
||||
clashConfig.tun = clashConfig.tun.copyWith(
|
||||
enable: !clashConfig.tun.enable,
|
||||
);
|
||||
}
|
||||
|
||||
updateSystemProxy() {
|
||||
config.desktopProps = config.desktopProps.copyWith(
|
||||
systemProxy: !config.desktopProps.systemProxy,
|
||||
);
|
||||
}
|
||||
|
||||
updateStart() {
|
||||
updateStatus(!appState.isStart);
|
||||
}
|
||||
|
||||
updateAutoLaunch() {
|
||||
config.autoLaunch = !config.autoLaunch;
|
||||
}
|
||||
|
||||
updateVisible() async {
|
||||
final visible = await window?.isVisible();
|
||||
if (visible != null && !visible) {
|
||||
window?.show();
|
||||
} else {
|
||||
window?.hide();
|
||||
}
|
||||
}
|
||||
|
||||
updateMode() {
|
||||
final index = Mode.values.indexWhere((item) => item == clashConfig.mode);
|
||||
if (index == -1) {
|
||||
return;
|
||||
}
|
||||
final nextIndex = index + 1 > Mode.values.length - 1 ? 0 : index + 1;
|
||||
clashConfig.mode = Mode.values[nextIndex];
|
||||
}
|
||||
|
||||
recoveryData(
|
||||
List<int> data,
|
||||
RecoveryOption recoveryOption,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
// ignore_for_file: constant_identifier_names
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hotkey_manager/hotkey_manager.dart';
|
||||
|
||||
enum GroupType { Selector, URLTest, Fallback, LoadBalance, Relay }
|
||||
|
||||
@@ -92,7 +94,6 @@ enum ProxiesLayout { loose, standard, tight }
|
||||
|
||||
enum ProxyCardType { expand, shrink, min }
|
||||
|
||||
|
||||
enum DnsMode {
|
||||
normal,
|
||||
@JsonValue("fake-ip")
|
||||
@@ -102,3 +103,52 @@ enum DnsMode {
|
||||
hosts
|
||||
}
|
||||
|
||||
enum KeyboardModifier {
|
||||
alt([
|
||||
PhysicalKeyboardKey.altLeft,
|
||||
PhysicalKeyboardKey.altRight,
|
||||
]),
|
||||
capsLock([
|
||||
PhysicalKeyboardKey.capsLock,
|
||||
]),
|
||||
control([
|
||||
PhysicalKeyboardKey.controlLeft,
|
||||
PhysicalKeyboardKey.controlRight,
|
||||
]),
|
||||
fn([
|
||||
PhysicalKeyboardKey.fn,
|
||||
]),
|
||||
meta([
|
||||
PhysicalKeyboardKey.metaLeft,
|
||||
PhysicalKeyboardKey.metaRight,
|
||||
]),
|
||||
shift([
|
||||
PhysicalKeyboardKey.shiftLeft,
|
||||
PhysicalKeyboardKey.shiftRight,
|
||||
]);
|
||||
|
||||
final List<PhysicalKeyboardKey> physicalKeys;
|
||||
|
||||
const KeyboardModifier(this.physicalKeys);
|
||||
}
|
||||
|
||||
extension KeyboardModifierExt on KeyboardModifier {
|
||||
HotKeyModifier toHotKeyModifier() {
|
||||
return switch (this) {
|
||||
KeyboardModifier.alt => HotKeyModifier.alt,
|
||||
KeyboardModifier.capsLock => HotKeyModifier.capsLock,
|
||||
KeyboardModifier.control => HotKeyModifier.control,
|
||||
KeyboardModifier.fn => HotKeyModifier.fn,
|
||||
KeyboardModifier.meta => HotKeyModifier.meta,
|
||||
KeyboardModifier.shift => HotKeyModifier.shift,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
enum HotAction {
|
||||
start,
|
||||
view,
|
||||
mode,
|
||||
proxy,
|
||||
tun,
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@ import 'dart:typed_data';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/common/dav_client.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/models/config.dart';
|
||||
import 'package:fl_clash/models/dav.dart';
|
||||
import 'package:fl_clash/models/models.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:fl_clash/widgets/fade_box.dart';
|
||||
import 'package:fl_clash/widgets/list.dart';
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:fl_clash/models/config.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:fl_clash/widgets/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path/path.dart' show dirname, join;
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class CloseConnectionsSwitch extends StatelessWidget {
|
||||
@@ -58,32 +57,7 @@ class UsageSwitch extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class UWPLoopbackUtil extends StatelessWidget {
|
||||
const UWPLoopbackUtil({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector<Config, bool>(
|
||||
selector: (_, config) => config.onlyProxy,
|
||||
builder: (_, onlyProxy, __) {
|
||||
return ListItem(
|
||||
leading: const Icon(Icons.lock_open),
|
||||
title: Text(appLocalizations.loopback),
|
||||
subtitle: Text(appLocalizations.loopbackDesc),
|
||||
onTap: () {
|
||||
windows?.runas(
|
||||
'"${join(dirname(Platform.resolvedExecutable), "EnableLoopback.exe")}"',
|
||||
"",
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final appItems = [
|
||||
if (Platform.isWindows) const UWPLoopbackUtil(),
|
||||
const CloseConnectionsSwitch(),
|
||||
const UsageSwitch(),
|
||||
];
|
||||
|
||||
@@ -14,7 +14,7 @@ class OverrideItem extends StatelessWidget {
|
||||
_initActions(BuildContext context) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||
final commonScaffoldState =
|
||||
context.findAncestorStateOfType<CommonScaffoldState>();
|
||||
context.findAncestorStateOfType<CommonScaffoldState>();
|
||||
commonScaffoldState?.actions = [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
@@ -54,7 +54,8 @@ class OverrideItem extends StatelessWidget {
|
||||
class DnsDisabledContainer extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const DnsDisabledContainer(this.child, {
|
||||
const DnsDisabledContainer(
|
||||
this.child, {
|
||||
super.key,
|
||||
});
|
||||
|
||||
@@ -268,7 +269,7 @@ class FakeIpFilterItem extends StatelessWidget {
|
||||
widget: Selector<ClashConfig, List<String>>(
|
||||
selector: (_, clashConfig) => clashConfig.dns.fakeIpFilter,
|
||||
shouldRebuild: (prev, next) =>
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
builder: (_, fakeIpFilter, __) {
|
||||
return UpdatePage(
|
||||
title: appLocalizations.fakeipFilter,
|
||||
@@ -278,8 +279,7 @@ class FakeIpFilterItem extends StatelessWidget {
|
||||
final clashConfig = globalState.appController.clashConfig;
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fakeIpFilter: List.from(dns.fakeIpFilter)
|
||||
..remove(value),
|
||||
fakeIpFilter: List.from(dns.fakeIpFilter)..remove(value),
|
||||
);
|
||||
},
|
||||
onAdd: (value) {
|
||||
@@ -287,8 +287,7 @@ class FakeIpFilterItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
if (fakeIpFilter.contains(value)) return;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fakeIpFilter: List.from(dns.fakeIpFilter)
|
||||
..add(value),
|
||||
fakeIpFilter: List.from(dns.fakeIpFilter)..add(value),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -314,7 +313,7 @@ class DefaultNameserverItem extends StatelessWidget {
|
||||
widget: Selector<ClashConfig, List<String>>(
|
||||
selector: (_, clashConfig) => clashConfig.dns.defaultNameserver,
|
||||
shouldRebuild: (prev, next) =>
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
builder: (_, defaultNameserver, __) {
|
||||
return UpdatePage(
|
||||
title: appLocalizations.defaultNameserver,
|
||||
@@ -360,7 +359,7 @@ class NameserverItem extends StatelessWidget {
|
||||
widget: Selector<ClashConfig, List<String>>(
|
||||
selector: (_, clashConfig) => clashConfig.dns.nameserver,
|
||||
shouldRebuild: (prev, next) =>
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
builder: (_, nameserver, __) {
|
||||
return UpdatePage(
|
||||
title: "域名服务器",
|
||||
@@ -370,8 +369,7 @@ class NameserverItem extends StatelessWidget {
|
||||
final clashConfig = globalState.appController.clashConfig;
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
nameserver: List.from(dns.nameserver)
|
||||
..remove(value),
|
||||
nameserver: List.from(dns.nameserver)..remove(value),
|
||||
);
|
||||
},
|
||||
onAdd: (value) {
|
||||
@@ -379,8 +377,7 @@ class NameserverItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
if (nameserver.contains(value)) return;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
nameserver: List.from(dns.nameserver)
|
||||
..add(value),
|
||||
nameserver: List.from(dns.nameserver)..add(value),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -458,7 +455,7 @@ class NameserverPolicyItem extends StatelessWidget {
|
||||
widget: Selector<ClashConfig, Map<String, String>>(
|
||||
selector: (_, clashConfig) => clashConfig.dns.nameserverPolicy,
|
||||
shouldRebuild: (prev, next) =>
|
||||
!const MapEquality<String, String>().equals(prev, next),
|
||||
!const MapEquality<String, String>().equals(prev, next),
|
||||
builder: (_, nameserverPolicy, __) {
|
||||
return UpdatePage(
|
||||
title: appLocalizations.nameserverPolicy,
|
||||
@@ -505,7 +502,7 @@ class ProxyServerNameserverItem extends StatelessWidget {
|
||||
widget: Selector<ClashConfig, List<String>>(
|
||||
selector: (_, clashConfig) => clashConfig.dns.proxyServerNameserver,
|
||||
shouldRebuild: (prev, next) =>
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
builder: (_, proxyServerNameserver, __) {
|
||||
return UpdatePage(
|
||||
title: appLocalizations.proxyNameserver,
|
||||
@@ -551,7 +548,7 @@ class FallbackItem extends StatelessWidget {
|
||||
widget: Selector<ClashConfig, List<String>>(
|
||||
selector: (_, clashConfig) => clashConfig.dns.fallback,
|
||||
shouldRebuild: (prev, next) =>
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
builder: (_, fallback, __) {
|
||||
return UpdatePage(
|
||||
title: appLocalizations.fallback,
|
||||
@@ -561,8 +558,7 @@ class FallbackItem extends StatelessWidget {
|
||||
final clashConfig = globalState.appController.clashConfig;
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallback: List.from(dns.fallback)
|
||||
..remove(value),
|
||||
fallback: List.from(dns.fallback)..remove(value),
|
||||
);
|
||||
},
|
||||
onAdd: (value) {
|
||||
@@ -570,8 +566,7 @@ class FallbackItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
if (fallback.contains(value)) return;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallback: List.from(dns.fallback)
|
||||
..add(value),
|
||||
fallback: List.from(dns.fallback)..add(value),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -663,7 +658,7 @@ class GeositeItem extends StatelessWidget {
|
||||
widget: Selector<ClashConfig, List<String>>(
|
||||
selector: (_, clashConfig) => clashConfig.dns.fallbackFilter.geosite,
|
||||
shouldRebuild: (prev, next) =>
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
builder: (_, geosite, __) {
|
||||
return UpdatePage(
|
||||
title: "Geosite",
|
||||
@@ -674,8 +669,7 @@ class GeositeItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallbackFilter: dns.fallbackFilter.copyWith(
|
||||
geosite: List.from(geosite)
|
||||
..remove(value),
|
||||
geosite: List.from(geosite)..remove(value),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -684,8 +678,7 @@ class GeositeItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallbackFilter: dns.fallbackFilter.copyWith(
|
||||
geosite: List.from(geosite)
|
||||
..add(value),
|
||||
geosite: List.from(geosite)..add(value),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -711,7 +704,7 @@ class IpcidrItem extends StatelessWidget {
|
||||
widget: Selector<ClashConfig, List<String>>(
|
||||
selector: (_, clashConfig) => clashConfig.dns.fallbackFilter.ipcidr,
|
||||
shouldRebuild: (prev, next) =>
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
builder: (_, ipcidr, __) {
|
||||
return UpdatePage(
|
||||
title: appLocalizations.ipcidr,
|
||||
@@ -722,8 +715,7 @@ class IpcidrItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallbackFilter: dns.fallbackFilter.copyWith(
|
||||
ipcidr: List.from(ipcidr)
|
||||
..remove(value),
|
||||
ipcidr: List.from(ipcidr)..remove(value),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -732,8 +724,7 @@ class IpcidrItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallbackFilter: dns.fallbackFilter.copyWith(
|
||||
ipcidr: List.from(ipcidr)
|
||||
..add(value),
|
||||
ipcidr: List.from(ipcidr)..add(value),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -759,7 +750,7 @@ class DomainItem extends StatelessWidget {
|
||||
widget: Selector<ClashConfig, List<String>>(
|
||||
selector: (_, clashConfig) => clashConfig.dns.fallbackFilter.domain,
|
||||
shouldRebuild: (prev, next) =>
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
!const ListEquality<String>().equals(prev, next),
|
||||
builder: (_, domain, __) {
|
||||
return UpdatePage(
|
||||
title: appLocalizations.domain,
|
||||
@@ -770,8 +761,7 @@ class DomainItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallbackFilter: dns.fallbackFilter.copyWith(
|
||||
domain: List.from(domain)
|
||||
..remove(value),
|
||||
domain: List.from(domain)..remove(value),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -780,8 +770,7 @@ class DomainItem extends StatelessWidget {
|
||||
final dns = clashConfig.dns;
|
||||
clashConfig.dns = dns.copyWith(
|
||||
fallbackFilter: dns.fallbackFilter.copyWith(
|
||||
domain: List.from(domain)
|
||||
..add(value),
|
||||
domain: List.from(domain)..add(value),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -47,14 +47,16 @@ class TUNSwitch extends StatelessWidget {
|
||||
child: Selector<ClashConfig, bool>(
|
||||
selector: (_, clashConfig) => clashConfig.tun.enable,
|
||||
builder: (_, enable, __) {
|
||||
return Switch(
|
||||
value: enable,
|
||||
onChanged: (value) {
|
||||
final clashConfig = globalState.appController.clashConfig;
|
||||
clashConfig.tun = clashConfig.tun.copyWith(
|
||||
enable: value,
|
||||
);
|
||||
},
|
||||
return LocaleBuilder(
|
||||
builder: (_) => Switch(
|
||||
value: enable,
|
||||
onChanged: (value) {
|
||||
final clashConfig = globalState.appController.clashConfig;
|
||||
clashConfig.tun = clashConfig.tun.copyWith(
|
||||
enable: value,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -75,14 +77,16 @@ class ProxySwitch extends StatelessWidget {
|
||||
child: Selector<Config, bool>(
|
||||
selector: (_, config) => config.desktopProps.systemProxy,
|
||||
builder: (_, systemProxy, __) {
|
||||
return Switch(
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
value: systemProxy,
|
||||
onChanged: (value) {
|
||||
final config = globalState.appController.config;
|
||||
config.desktopProps =
|
||||
config.desktopProps.copyWith(systemProxy: value);
|
||||
},
|
||||
return LocaleBuilder(
|
||||
builder: (_) => Switch(
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
value: systemProxy,
|
||||
onChanged: (value) {
|
||||
final config = globalState.appController.config;
|
||||
config.desktopProps =
|
||||
config.desktopProps.copyWith(systemProxy: value);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
250
lib/fragments/hotkey.dart
Normal file
250
lib/fragments/hotkey.dart
Normal file
@@ -0,0 +1,250 @@
|
||||
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/state.dart';
|
||||
import 'package:fl_clash/widgets/card.dart';
|
||||
import 'package:fl_clash/widgets/list.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
extension IntlExt on Intl {
|
||||
static actionMessage(String messageText) =>
|
||||
Intl.message("action_$messageText");
|
||||
}
|
||||
|
||||
class HotKeyFragment extends StatelessWidget {
|
||||
const HotKeyFragment({super.key});
|
||||
|
||||
String getSubtitle(HotKeyAction hotKeyAction) {
|
||||
final key = hotKeyAction.key;
|
||||
if (key == null) {
|
||||
return appLocalizations.noHotKey;
|
||||
}
|
||||
final modifierLabels =
|
||||
hotKeyAction.modifiers.map((item) => item.physicalKeys.first.label);
|
||||
var text = "";
|
||||
if (modifierLabels.isNotEmpty) {
|
||||
text += "${modifierLabels.join(" ")}+";
|
||||
}
|
||||
text += PhysicalKeyboardKey(key).label;
|
||||
return text;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.builder(
|
||||
itemCount: HotAction.values.length,
|
||||
itemBuilder: (_, index) {
|
||||
final hotAction = HotAction.values[index];
|
||||
return Selector<Config, HotKeyAction>(
|
||||
selector: (_, config) {
|
||||
final index = config.hotKeyActions.indexWhere(
|
||||
(item) => item.action == hotAction,
|
||||
);
|
||||
return index != -1
|
||||
? config.hotKeyActions[index]
|
||||
: HotKeyAction(
|
||||
action: hotAction,
|
||||
);
|
||||
},
|
||||
builder: (_, value, __) {
|
||||
return ListItem(
|
||||
title: Text(IntlExt.actionMessage(hotAction.name)),
|
||||
subtitle: Text(
|
||||
getSubtitle(value),
|
||||
style: context.textTheme.bodyMedium
|
||||
?.copyWith(color: context.colorScheme.primary),
|
||||
),
|
||||
onTap: () {
|
||||
globalState.showCommonDialog(
|
||||
child: HotKeyRecorder(
|
||||
hotKeyAction: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HotKeyRecorder extends StatefulWidget {
|
||||
final HotKeyAction hotKeyAction;
|
||||
|
||||
const HotKeyRecorder({
|
||||
super.key,
|
||||
required this.hotKeyAction,
|
||||
});
|
||||
|
||||
@override
|
||||
State<HotKeyRecorder> createState() => _HotKeyRecorderState();
|
||||
}
|
||||
|
||||
class _HotKeyRecorderState extends State<HotKeyRecorder> {
|
||||
late ValueNotifier<HotKeyAction> hotKeyActionNotifier;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
hotKeyActionNotifier = ValueNotifier<HotKeyAction>(
|
||||
widget.hotKeyAction.copyWith(),
|
||||
);
|
||||
HardwareKeyboard.instance.addHandler(_handleKeyEvent);
|
||||
}
|
||||
|
||||
bool _handleKeyEvent(KeyEvent keyEvent) {
|
||||
if (keyEvent is KeyUpEvent) return false;
|
||||
final keys = HardwareKeyboard.instance.physicalKeysPressed;
|
||||
|
||||
final key = keyEvent.physicalKey;
|
||||
|
||||
final modifiers = KeyboardModifier.values
|
||||
.where((e) =>
|
||||
e.physicalKeys.any(keys.contains) && !e.physicalKeys.contains(key))
|
||||
.toSet();
|
||||
hotKeyActionNotifier.value = hotKeyActionNotifier.value.copyWith(
|
||||
modifiers: modifiers,
|
||||
key: key.usbHidUsage,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
HardwareKeyboard.instance.removeHandler(_handleKeyEvent);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
_handleRemove() {
|
||||
Navigator.of(context).pop();
|
||||
final config = globalState.appController.config;
|
||||
config.updateOrAddHotKeyAction(
|
||||
hotKeyActionNotifier.value.copyWith(
|
||||
modifiers: {},
|
||||
key: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_handleConfirm() {
|
||||
Navigator.of(context).pop();
|
||||
final config = globalState.appController.config;
|
||||
final currentHotkeyAction = hotKeyActionNotifier.value;
|
||||
if (currentHotkeyAction.key == null ||
|
||||
currentHotkeyAction.modifiers.isEmpty) {
|
||||
globalState.showMessage(
|
||||
title: appLocalizations.tip,
|
||||
message: TextSpan(text: appLocalizations.inputCorrectHotkey),
|
||||
);
|
||||
return;
|
||||
}
|
||||
final hotKeyActions = config.hotKeyActions;
|
||||
final index = hotKeyActions.indexWhere(
|
||||
(item) =>
|
||||
item.key == currentHotkeyAction.key &&
|
||||
keyboardModifiersEquality.equals(
|
||||
item.modifiers,
|
||||
currentHotkeyAction.modifiers,
|
||||
),
|
||||
);
|
||||
if (index != -1) {
|
||||
globalState.showMessage(
|
||||
title: appLocalizations.tip,
|
||||
message: TextSpan(text: appLocalizations.hotkeyConflict),
|
||||
);
|
||||
return;
|
||||
}
|
||||
config.updateOrAddHotKeyAction(
|
||||
currentHotkeyAction,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(IntlExt.actionMessage((widget.hotKeyAction.action.name))),
|
||||
content: ValueListenableBuilder(
|
||||
valueListenable: hotKeyActionNotifier,
|
||||
builder: (_, hotKeyAction, ___) {
|
||||
final key = hotKeyAction.key;
|
||||
final modifiers = hotKeyAction.modifiers;
|
||||
return SizedBox(
|
||||
width: dialogCommonWidth,
|
||||
child: key != null
|
||||
? Wrap(
|
||||
spacing: 8,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
for (final modifier in modifiers)
|
||||
KeyboardKeyBox(
|
||||
keyboardKey: modifier.physicalKeys.first,
|
||||
),
|
||||
if (modifiers.isNotEmpty)
|
||||
Text(
|
||||
"+",
|
||||
style: context.textTheme.titleMedium,
|
||||
),
|
||||
KeyboardKeyBox(
|
||||
keyboardKey: PhysicalKeyboardKey(key),
|
||||
),
|
||||
],
|
||||
)
|
||||
: Text(
|
||||
appLocalizations.pressKeyboard,
|
||||
style: context.textTheme.titleMedium,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
_handleRemove();
|
||||
},
|
||||
child: Text(appLocalizations.remove),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
_handleConfirm();
|
||||
},
|
||||
child: Text(
|
||||
appLocalizations.confirm,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class KeyboardKeyBox extends StatelessWidget {
|
||||
final KeyboardKey keyboardKey;
|
||||
|
||||
const KeyboardKeyBox({
|
||||
super.key,
|
||||
required this.keyboardKey,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CommonCard(
|
||||
type: CommonCardType.filled,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Text(
|
||||
keyboardKey.label,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
onPressed: () {},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -497,17 +497,17 @@ class _ReorderableProfilesState extends State<ReorderableProfiles> {
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8,
|
||||
vertical: 16,
|
||||
horizontal: 24,
|
||||
),
|
||||
child: FilledButton(
|
||||
child: FilledButton.tonal(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
globalState.appController.config.profiles = profiles;
|
||||
},
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStateProperty.all(
|
||||
const EdgeInsets.symmetric(vertical: 16),
|
||||
const EdgeInsets.symmetric(vertical: 8),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
|
||||
@@ -25,6 +25,10 @@ class ProxyCard extends StatelessWidget {
|
||||
|
||||
Measure get measure => globalState.measure;
|
||||
|
||||
_handleTestCurrentDelay() {
|
||||
proxyDelayTest(proxy);
|
||||
}
|
||||
|
||||
Widget _buildDelayText() {
|
||||
return SizedBox(
|
||||
height: measure.labelSmallHeight,
|
||||
@@ -36,24 +40,31 @@ class ProxyCard extends StatelessWidget {
|
||||
return FadeBox(
|
||||
child: Builder(
|
||||
builder: (_) {
|
||||
if (delay == null) {
|
||||
return Container();
|
||||
}
|
||||
if (delay == 0) {
|
||||
if (delay == 0 || delay == null) {
|
||||
return SizedBox(
|
||||
height: measure.labelSmallHeight,
|
||||
width: measure.labelSmallHeight,
|
||||
child: const CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
child: delay == 0
|
||||
? const CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
)
|
||||
: IconButton(
|
||||
icon: const Icon(Icons.bolt),
|
||||
iconSize: globalState.measure.labelSmallHeight,
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: _handleTestCurrentDelay,
|
||||
),
|
||||
);
|
||||
}
|
||||
return Text(
|
||||
delay > 0 ? '$delay ms' : "Timeout",
|
||||
style: context.textTheme.labelSmall?.copyWith(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: other.getDelayColor(
|
||||
delay,
|
||||
return GestureDetector(
|
||||
onTap: _handleTestCurrentDelay,
|
||||
child: Text(
|
||||
delay > 0 ? '$delay ms' : "Timeout",
|
||||
style: context.textTheme.labelSmall?.copyWith(
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: other.getDelayColor(
|
||||
delay,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:fl_clash/clash/clash.dart';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
@@ -40,10 +38,26 @@ double getItemHeight(ProxyCardType proxyCardType) {
|
||||
};
|
||||
}
|
||||
|
||||
proxyDelayTest(Proxy proxy) async {
|
||||
final appController = globalState.appController;
|
||||
final proxyName = appController.appState.getRealProxyName(proxy.name);
|
||||
globalState.appController.setDelay(
|
||||
Delay(
|
||||
name: proxyName,
|
||||
value: 0,
|
||||
),
|
||||
);
|
||||
globalState.appController.setDelay(await clashCore.getDelay(proxyName));
|
||||
}
|
||||
|
||||
delayTest(List<Proxy> proxies) async {
|
||||
final appController = globalState.appController;
|
||||
final delayProxies = proxies.map<Future>((proxy) async {
|
||||
final proxyName = appController.appState.getRealProxyName(proxy.name);
|
||||
final proxyNames = proxies
|
||||
.map((proxy) => appController.appState.getRealProxyName(proxy.name))
|
||||
.toSet()
|
||||
.toList();
|
||||
|
||||
final delayProxies = proxyNames.map<Future>((proxyName) async {
|
||||
globalState.appController.setDelay(
|
||||
Delay(
|
||||
name: proxyName,
|
||||
@@ -76,5 +90,5 @@ double getScrollToSelectedOffset({
|
||||
);
|
||||
final selectedIndex = findSelectedIndex != -1 ? findSelectedIndex : 0;
|
||||
final rows = (selectedIndex / columns).floor();
|
||||
return max(rows * (getItemHeight(proxyCardType) + 8) - 8, 0);
|
||||
return rows * getItemHeight(proxyCardType) + (rows - 1) * 8;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
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/state.dart';
|
||||
import 'package:fl_clash/widgets/builder.dart';
|
||||
import 'package:fl_clash/widgets/card.dart';
|
||||
import 'package:fl_clash/widgets/fade_box.dart';
|
||||
import 'package:fl_clash/widgets/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@@ -219,11 +221,15 @@ class _ProxiesListFragmentState extends State<ProxiesListFragment> {
|
||||
final currentInitOffset = _headerOffset[index];
|
||||
final proxies = _lastGroupNameProxiesMap[groupName];
|
||||
_controller.animateTo(
|
||||
currentInitOffset +
|
||||
getScrollToSelectedOffset(
|
||||
groupName: groupName,
|
||||
proxies: proxies ?? [],
|
||||
),
|
||||
min(
|
||||
currentInitOffset +
|
||||
8 +
|
||||
getScrollToSelectedOffset(
|
||||
groupName: groupName,
|
||||
proxies: proxies ?? [],
|
||||
),
|
||||
_controller.position.maxScrollExtent,
|
||||
),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeIn,
|
||||
);
|
||||
@@ -258,73 +264,75 @@ class _ProxiesListFragmentState extends State<ProxiesListFragment> {
|
||||
return prev != next;
|
||||
},
|
||||
builder: (_, state, __) {
|
||||
final items = _buildItems(
|
||||
groupNames: state.groupNames,
|
||||
currentUnfoldSet: state.currentUnfoldSet,
|
||||
columns: state.columns,
|
||||
type: state.proxyCardType,
|
||||
);
|
||||
final itemsOffset = _getItemHeightList(items, state.proxyCardType);
|
||||
return Scrollbar(
|
||||
controller: _controller,
|
||||
thumbVisibility: true,
|
||||
trackVisibility: true,
|
||||
thickness: 8,
|
||||
radius: const Radius.circular(8),
|
||||
interactive: true,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: ScrollConfiguration(
|
||||
behavior: HiddenBarScrollBehavior(),
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
controller: _controller,
|
||||
itemExtentBuilder: (index, __) {
|
||||
return itemsOffset[index];
|
||||
},
|
||||
itemCount: items.length,
|
||||
itemBuilder: (_, index) {
|
||||
return items[index];
|
||||
},
|
||||
return ScaleBuilder(builder: (_) {
|
||||
final items = _buildItems(
|
||||
groupNames: state.groupNames,
|
||||
currentUnfoldSet: state.currentUnfoldSet,
|
||||
columns: state.columns,
|
||||
type: state.proxyCardType,
|
||||
);
|
||||
final itemsOffset = _getItemHeightList(items, state.proxyCardType);
|
||||
return Scrollbar(
|
||||
controller: _controller,
|
||||
thumbVisibility: true,
|
||||
trackVisibility: true,
|
||||
thickness: 8,
|
||||
radius: const Radius.circular(8),
|
||||
interactive: true,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: ScrollConfiguration(
|
||||
behavior: HiddenBarScrollBehavior(),
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
controller: _controller,
|
||||
itemExtentBuilder: (index, __) {
|
||||
return itemsOffset[index];
|
||||
},
|
||||
itemCount: items.length,
|
||||
itemBuilder: (_, index) {
|
||||
return items[index];
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
LayoutBuilder(builder: (_, container) {
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: _headerStateNotifier,
|
||||
builder: (_, headerState, ___) {
|
||||
final index =
|
||||
headerState.currentIndex > state.groupNames.length - 1
|
||||
? 0
|
||||
: headerState.currentIndex;
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: -headerState.offset,
|
||||
child: Container(
|
||||
width: container.maxWidth,
|
||||
color: context.colorScheme.surface,
|
||||
padding: const EdgeInsets.only(
|
||||
top: 16,
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 8,
|
||||
),
|
||||
child: _buildHeader(
|
||||
groupName: state.groupNames[index],
|
||||
currentUnfoldSet: state.currentUnfoldSet,
|
||||
LayoutBuilder(builder: (_, container) {
|
||||
return ValueListenableBuilder(
|
||||
valueListenable: _headerStateNotifier,
|
||||
builder: (_, headerState, ___) {
|
||||
final index =
|
||||
headerState.currentIndex > state.groupNames.length - 1
|
||||
? 0
|
||||
: headerState.currentIndex;
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
top: -headerState.offset,
|
||||
child: Container(
|
||||
width: container.maxWidth,
|
||||
color: context.colorScheme.surface,
|
||||
padding: const EdgeInsets.only(
|
||||
top: 16,
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 8,
|
||||
),
|
||||
child: _buildHeader(
|
||||
groupName: state.groupNames[index],
|
||||
currentUnfoldSet: state.currentUnfoldSet,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
@@ -138,7 +140,7 @@ class ProxiesTabFragmentState extends State<ProxiesTabFragment>
|
||||
GroupNameKeyMap keyMap = {};
|
||||
final children = state.groupNames.map((groupName) {
|
||||
keyMap[groupName] = GlobalObjectKey(groupName);
|
||||
return KeepContainer(
|
||||
return KeepScope(
|
||||
child: ProxyGroupView(
|
||||
key: keyMap[groupName],
|
||||
groupName: groupName,
|
||||
@@ -266,11 +268,14 @@ class ProxyGroupViewState extends State<ProxyGroupView> {
|
||||
return;
|
||||
}
|
||||
_controller.animateTo(
|
||||
16 +
|
||||
getScrollToSelectedOffset(
|
||||
groupName: groupName,
|
||||
proxies: _lastProxies,
|
||||
),
|
||||
min(
|
||||
16 +
|
||||
getScrollToSelectedOffset(
|
||||
groupName: groupName,
|
||||
proxies: _lastProxies,
|
||||
),
|
||||
_controller.position.maxScrollExtent,
|
||||
),
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeIn,
|
||||
);
|
||||
@@ -309,26 +314,33 @@ class ProxyGroupViewState extends State<ProxyGroupView> {
|
||||
},
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: GridView.builder(
|
||||
controller: _controller,
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: columns,
|
||||
mainAxisSpacing: 8,
|
||||
crossAxisSpacing: 8,
|
||||
mainAxisExtent: getItemHeight(proxyCardType),
|
||||
child: ScaleBuilder(
|
||||
builder: (_) => GridView.builder(
|
||||
controller: _controller,
|
||||
padding: const EdgeInsets.only(
|
||||
top: 16,
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 80,
|
||||
),
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: columns,
|
||||
mainAxisSpacing: 8,
|
||||
crossAxisSpacing: 8,
|
||||
mainAxisExtent: getItemHeight(proxyCardType),
|
||||
),
|
||||
itemCount: sortedProxies.length,
|
||||
itemBuilder: (_, index) {
|
||||
final proxy = sortedProxies[index];
|
||||
return ProxyCard(
|
||||
groupType: state.groupType,
|
||||
type: proxyCardType,
|
||||
key: ValueKey('$groupName.${proxy.name}'),
|
||||
proxy: proxy,
|
||||
groupName: groupName,
|
||||
);
|
||||
},
|
||||
),
|
||||
itemCount: sortedProxies.length,
|
||||
itemBuilder: (_, index) {
|
||||
final proxy = sortedProxies[index];
|
||||
return ProxyCard(
|
||||
groupType: state.groupType,
|
||||
type: proxyCardType,
|
||||
key: ValueKey('$groupName.${proxy.name}'),
|
||||
proxy: proxy,
|
||||
groupName: groupName,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -5,15 +5,17 @@ import 'package:fl_clash/fragments/about.dart';
|
||||
import 'package:fl_clash/fragments/access.dart';
|
||||
import 'package:fl_clash/fragments/application_setting.dart';
|
||||
import 'package:fl_clash/fragments/config/config.dart';
|
||||
import 'package:fl_clash/fragments/hotkey.dart';
|
||||
import 'package:fl_clash/l10n/l10n.dart';
|
||||
import 'package:fl_clash/models/models.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:fl_clash/widgets/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../widgets/widgets.dart';
|
||||
import 'backup_and_recovery.dart';
|
||||
import 'theme.dart';
|
||||
import 'package:path/path.dart' show dirname, join;
|
||||
|
||||
class ToolsFragment extends StatefulWidget {
|
||||
const ToolsFragment({super.key});
|
||||
@@ -61,6 +63,17 @@ class _ToolboxFragmentState extends State<ToolsFragment> {
|
||||
return generateSection(
|
||||
title: appLocalizations.other,
|
||||
items: [
|
||||
ListItem(
|
||||
leading: const Icon(Icons.gavel),
|
||||
title: Text(appLocalizations.disclaimer),
|
||||
onTap: () async {
|
||||
final isDisclaimerAccepted =
|
||||
await globalState.appController.showDisclaimer();
|
||||
if (!isDisclaimerAccepted) {
|
||||
system.exit();
|
||||
}
|
||||
},
|
||||
),
|
||||
ListItem.open(
|
||||
leading: const Icon(Icons.info),
|
||||
title: Text(appLocalizations.about),
|
||||
@@ -88,10 +101,7 @@ class _ToolboxFragmentState extends State<ToolsFragment> {
|
||||
subtitle: Text(Intl.message(subTitle)),
|
||||
delegate: OptionsDelegate(
|
||||
title: appLocalizations.language,
|
||||
options: [
|
||||
null,
|
||||
...AppLocalizations.delegate.supportedLocales
|
||||
],
|
||||
options: [null, ...AppLocalizations.delegate.supportedLocales],
|
||||
onChanged: (Locale? value) {
|
||||
final config = context.read<Config>();
|
||||
config.locale = value?.toString();
|
||||
@@ -121,6 +131,28 @@ class _ToolboxFragmentState extends State<ToolsFragment> {
|
||||
widget: const BackupAndRecovery(),
|
||||
),
|
||||
),
|
||||
if (system.isDesktop)
|
||||
ListItem.open(
|
||||
leading: const Icon(Icons.keyboard),
|
||||
title: Text(appLocalizations.hotkeyManagement),
|
||||
subtitle: Text(appLocalizations.hotkeyManagementDesc),
|
||||
delegate: OpenDelegate(
|
||||
title: appLocalizations.hotkeyManagement,
|
||||
widget: const HotKeyFragment(),
|
||||
),
|
||||
),
|
||||
if (Platform.isWindows)
|
||||
ListItem(
|
||||
leading: const Icon(Icons.lock),
|
||||
title: Text(appLocalizations.loopback),
|
||||
subtitle: Text(appLocalizations.loopbackDesc),
|
||||
onTap: () {
|
||||
windows?.runas(
|
||||
'"${join(dirname(Platform.resolvedExecutable), "EnableLoopback.exe")}"',
|
||||
"",
|
||||
);
|
||||
},
|
||||
),
|
||||
if (Platform.isAndroid)
|
||||
ListItem.open(
|
||||
leading: const Icon(Icons.view_list),
|
||||
@@ -155,9 +187,8 @@ class _ToolboxFragmentState extends State<ToolsFragment> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector<Config, String?>(
|
||||
selector: (_, config) => config.locale,
|
||||
builder: (_, __, ___) {
|
||||
return LocaleBuilder(
|
||||
builder: (_) {
|
||||
final items = [
|
||||
Selector<AppState, MoreToolsSelectorState>(
|
||||
selector: (_, appState) {
|
||||
@@ -190,6 +221,7 @@ class _ToolboxFragmentState extends State<ToolsFragment> {
|
||||
return ListView.builder(
|
||||
itemCount: items.length,
|
||||
itemBuilder: (_, index) => items[index],
|
||||
padding: const EdgeInsets.only(bottom: 20),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -288,5 +288,20 @@
|
||||
"ipcidr": "Ipcidr",
|
||||
"domain": "Domain",
|
||||
"resetDns": "Reset Dns",
|
||||
"reset": "Reset"
|
||||
"reset": "Reset",
|
||||
"action_view": "Show/Hide",
|
||||
"action_start": "Start/Stop",
|
||||
"action_mode": "Switch mode",
|
||||
"action_proxy": "System proxy",
|
||||
"action_tun": "TUN",
|
||||
"disclaimer": "Disclaimer",
|
||||
"disclaimerDesc": "This software is only used for non-commercial purposes such as learning exchanges and scientific research. It is strictly prohibited to use this software for commercial purposes. Any commercial activity, if any, has nothing to do with this software.",
|
||||
"agree": "Agree",
|
||||
"hotkeyManagement": "Hotkey Management",
|
||||
"hotkeyManagementDesc": "Use keyboard to control applications",
|
||||
"pressKeyboard": "Please press the keyboard.",
|
||||
"inputCorrectHotkey": "Please enter the correct hotkey",
|
||||
"hotkeyConflict": "Hotkey conflict",
|
||||
"remove": "Remove",
|
||||
"noHotKey": "No HotKey"
|
||||
}
|
||||
@@ -238,9 +238,9 @@
|
||||
"clipboardImport": "剪贴板导入",
|
||||
"clipboardExport": "导出剪贴板",
|
||||
"layout": "布局",
|
||||
"tight": "宽松",
|
||||
"tight": "紧凑",
|
||||
"standard": "标准",
|
||||
"loose": "紧凑",
|
||||
"loose": "宽松",
|
||||
"profilesSort": "配置排序",
|
||||
"start": "启动",
|
||||
"stop": "暂停",
|
||||
@@ -288,5 +288,20 @@
|
||||
"ipcidr": "IP/掩码",
|
||||
"domain": "域名",
|
||||
"resetDns": "重置DNS",
|
||||
"reset": "重置"
|
||||
"reset": "重置",
|
||||
"action_view": "显示/隐藏",
|
||||
"action_start": "启动/停止",
|
||||
"action_mode": "切换模式",
|
||||
"action_proxy": "系统代理",
|
||||
"action_tun": "虚拟网卡",
|
||||
"disclaimer": "免责声明",
|
||||
"disclaimerDesc": "本软件仅供学习交流、科研等非商业性质的用途,严禁将本软件用于商业目的。如有任何商业行为,均与本软件无关。",
|
||||
"agree": "同意",
|
||||
"hotkeyManagement": "快捷键管理",
|
||||
"hotkeyManagementDesc": "使用键盘控制应用程序",
|
||||
"pressKeyboard": "请按下按键",
|
||||
"inputCorrectHotkey": "请输入正确的快捷键",
|
||||
"hotkeyConflict": "快捷键冲突",
|
||||
"remove": "移除",
|
||||
"noHotKey": "暂无快捷键"
|
||||
}
|
||||
@@ -34,6 +34,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"accountTip":
|
||||
MessageLookupByLibrary.simpleMessage("Account cannot be empty"),
|
||||
"action": MessageLookupByLibrary.simpleMessage("Action"),
|
||||
"action_mode": MessageLookupByLibrary.simpleMessage("Switch mode"),
|
||||
"action_proxy": MessageLookupByLibrary.simpleMessage("System proxy"),
|
||||
"action_start": MessageLookupByLibrary.simpleMessage("Start/Stop"),
|
||||
"action_tun": MessageLookupByLibrary.simpleMessage("TUN"),
|
||||
"action_view": MessageLookupByLibrary.simpleMessage("Show/Hide"),
|
||||
"add": MessageLookupByLibrary.simpleMessage("Add"),
|
||||
"address": MessageLookupByLibrary.simpleMessage("Address"),
|
||||
"addressHelp":
|
||||
@@ -41,6 +46,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"addressTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Please enter a valid WebDAV address"),
|
||||
"ago": MessageLookupByLibrary.simpleMessage(" Ago"),
|
||||
"agree": MessageLookupByLibrary.simpleMessage("Agree"),
|
||||
"allApps": MessageLookupByLibrary.simpleMessage("All apps"),
|
||||
"allowBypass": MessageLookupByLibrary.simpleMessage(
|
||||
"Allow applications to bypass VPN"),
|
||||
@@ -130,6 +136,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"desc": MessageLookupByLibrary.simpleMessage(
|
||||
"A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free."),
|
||||
"direct": MessageLookupByLibrary.simpleMessage("Direct"),
|
||||
"disclaimer": MessageLookupByLibrary.simpleMessage("Disclaimer"),
|
||||
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"This software is only used for non-commercial purposes such as learning exchanges and scientific research. It is strictly prohibited to use this software for commercial purposes. Any commercial activity, if any, has nothing to do with this software."),
|
||||
"discoverNewVersion":
|
||||
MessageLookupByLibrary.simpleMessage("Discover the new version"),
|
||||
"discovery":
|
||||
@@ -188,12 +197,20 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"go": MessageLookupByLibrary.simpleMessage("Go"),
|
||||
"goDownload": MessageLookupByLibrary.simpleMessage("Go to download"),
|
||||
"hostsDesc": MessageLookupByLibrary.simpleMessage("Add Hosts"),
|
||||
"hotkeyConflict":
|
||||
MessageLookupByLibrary.simpleMessage("Hotkey conflict"),
|
||||
"hotkeyManagement":
|
||||
MessageLookupByLibrary.simpleMessage("Hotkey Management"),
|
||||
"hotkeyManagementDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Use keyboard to control applications"),
|
||||
"hours": MessageLookupByLibrary.simpleMessage("Hours"),
|
||||
"importFromURL":
|
||||
MessageLookupByLibrary.simpleMessage("Import from URL"),
|
||||
"infiniteTime":
|
||||
MessageLookupByLibrary.simpleMessage("Long term effective"),
|
||||
"init": MessageLookupByLibrary.simpleMessage("Init"),
|
||||
"inputCorrectHotkey": MessageLookupByLibrary.simpleMessage(
|
||||
"Please enter the correct hotkey"),
|
||||
"intelligentSelected":
|
||||
MessageLookupByLibrary.simpleMessage("Intelligent selection"),
|
||||
"intranetIP": MessageLookupByLibrary.simpleMessage("Intranet IP"),
|
||||
@@ -247,6 +264,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"networkDetection":
|
||||
MessageLookupByLibrary.simpleMessage("Network detection"),
|
||||
"networkSpeed": MessageLookupByLibrary.simpleMessage("Network speed"),
|
||||
"noHotKey": MessageLookupByLibrary.simpleMessage("No HotKey"),
|
||||
"noInfo": MessageLookupByLibrary.simpleMessage("No info"),
|
||||
"noMoreInfoDesc": MessageLookupByLibrary.simpleMessage("No more info"),
|
||||
"noProxy": MessageLookupByLibrary.simpleMessage("No proxy"),
|
||||
@@ -293,6 +311,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"port": MessageLookupByLibrary.simpleMessage("Port"),
|
||||
"preferH3Desc": MessageLookupByLibrary.simpleMessage(
|
||||
"Prioritize the use of DOH\'s http/3"),
|
||||
"pressKeyboard":
|
||||
MessageLookupByLibrary.simpleMessage("Please press the keyboard."),
|
||||
"preview": MessageLookupByLibrary.simpleMessage("Preview"),
|
||||
"profile": MessageLookupByLibrary.simpleMessage("Profile"),
|
||||
"profileAutoUpdateIntervalInvalidValidationDesc":
|
||||
@@ -343,6 +363,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("Backup local data to WebDAV"),
|
||||
"remoteRecoveryDesc":
|
||||
MessageLookupByLibrary.simpleMessage("Recovery data from WebDAV"),
|
||||
"remove": MessageLookupByLibrary.simpleMessage("Remove"),
|
||||
"requests": MessageLookupByLibrary.simpleMessage("Requests"),
|
||||
"requestsDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"View recently request records"),
|
||||
|
||||
@@ -32,11 +32,17 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"account": MessageLookupByLibrary.simpleMessage("账号"),
|
||||
"accountTip": MessageLookupByLibrary.simpleMessage("账号不能为空"),
|
||||
"action": MessageLookupByLibrary.simpleMessage("操作"),
|
||||
"action_mode": MessageLookupByLibrary.simpleMessage("切换模式"),
|
||||
"action_proxy": MessageLookupByLibrary.simpleMessage("系统代理"),
|
||||
"action_start": MessageLookupByLibrary.simpleMessage("启动/停止"),
|
||||
"action_tun": MessageLookupByLibrary.simpleMessage("虚拟网卡"),
|
||||
"action_view": MessageLookupByLibrary.simpleMessage("显示/隐藏"),
|
||||
"add": MessageLookupByLibrary.simpleMessage("添加"),
|
||||
"address": MessageLookupByLibrary.simpleMessage("地址"),
|
||||
"addressHelp": MessageLookupByLibrary.simpleMessage("WebDAV服务器地址"),
|
||||
"addressTip": MessageLookupByLibrary.simpleMessage("请输入有效的WebDAV地址"),
|
||||
"ago": MessageLookupByLibrary.simpleMessage("前"),
|
||||
"agree": MessageLookupByLibrary.simpleMessage("同意"),
|
||||
"allApps": MessageLookupByLibrary.simpleMessage("所有应用"),
|
||||
"allowBypass": MessageLookupByLibrary.simpleMessage("允许应用绕过VPN"),
|
||||
"allowBypassDesc":
|
||||
@@ -107,6 +113,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"desc": MessageLookupByLibrary.simpleMessage(
|
||||
"基于ClashMeta的多平台代理客户端,简单易用,开源无广告。"),
|
||||
"direct": MessageLookupByLibrary.simpleMessage("直连"),
|
||||
"disclaimer": MessageLookupByLibrary.simpleMessage("免责声明"),
|
||||
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"本软件仅供学习交流、科研等非商业性质的用途,严禁将本软件用于商业目的。如有任何商业行为,均与本软件无关。"),
|
||||
"discoverNewVersion": MessageLookupByLibrary.simpleMessage("发现新版本"),
|
||||
"discovery": MessageLookupByLibrary.simpleMessage("发现新版本"),
|
||||
"dnsDesc": MessageLookupByLibrary.simpleMessage("更新DNS相关设置"),
|
||||
@@ -151,10 +160,15 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"go": MessageLookupByLibrary.simpleMessage("前往"),
|
||||
"goDownload": MessageLookupByLibrary.simpleMessage("前往下载"),
|
||||
"hostsDesc": MessageLookupByLibrary.simpleMessage("追加Hosts"),
|
||||
"hotkeyConflict": MessageLookupByLibrary.simpleMessage("快捷键冲突"),
|
||||
"hotkeyManagement": MessageLookupByLibrary.simpleMessage("快捷键管理"),
|
||||
"hotkeyManagementDesc":
|
||||
MessageLookupByLibrary.simpleMessage("使用键盘控制应用程序"),
|
||||
"hours": MessageLookupByLibrary.simpleMessage("小时"),
|
||||
"importFromURL": MessageLookupByLibrary.simpleMessage("从URL导入"),
|
||||
"infiniteTime": MessageLookupByLibrary.simpleMessage("长期有效"),
|
||||
"init": MessageLookupByLibrary.simpleMessage("初始化"),
|
||||
"inputCorrectHotkey": MessageLookupByLibrary.simpleMessage("请输入正确的快捷键"),
|
||||
"intelligentSelected": MessageLookupByLibrary.simpleMessage("智能选择"),
|
||||
"intranetIP": MessageLookupByLibrary.simpleMessage("内网 IP"),
|
||||
"ipcidr": MessageLookupByLibrary.simpleMessage("IP/掩码"),
|
||||
@@ -178,7 +192,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"logsDesc": MessageLookupByLibrary.simpleMessage("日志捕获记录"),
|
||||
"loopback": MessageLookupByLibrary.simpleMessage("回环解锁工具"),
|
||||
"loopbackDesc": MessageLookupByLibrary.simpleMessage("用于UWP回环解锁"),
|
||||
"loose": MessageLookupByLibrary.simpleMessage("紧凑"),
|
||||
"loose": MessageLookupByLibrary.simpleMessage("宽松"),
|
||||
"min": MessageLookupByLibrary.simpleMessage("最小"),
|
||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("退出时最小化"),
|
||||
"minimizeOnExitDesc":
|
||||
@@ -196,6 +210,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("指定对应域名服务器策略"),
|
||||
"networkDetection": MessageLookupByLibrary.simpleMessage("网络检测"),
|
||||
"networkSpeed": MessageLookupByLibrary.simpleMessage("网络速度"),
|
||||
"noHotKey": MessageLookupByLibrary.simpleMessage("暂无快捷键"),
|
||||
"noInfo": MessageLookupByLibrary.simpleMessage("暂无信息"),
|
||||
"noMoreInfoDesc": MessageLookupByLibrary.simpleMessage("暂无更多信息"),
|
||||
"noProxy": MessageLookupByLibrary.simpleMessage("暂无代理"),
|
||||
@@ -231,6 +246,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
MessageLookupByLibrary.simpleMessage("请上传有效的二维码"),
|
||||
"port": MessageLookupByLibrary.simpleMessage("端口"),
|
||||
"preferH3Desc": MessageLookupByLibrary.simpleMessage("优先使用DOH的http/3"),
|
||||
"pressKeyboard": MessageLookupByLibrary.simpleMessage("请按下按键"),
|
||||
"preview": MessageLookupByLibrary.simpleMessage("预览"),
|
||||
"profile": MessageLookupByLibrary.simpleMessage("配置"),
|
||||
"profileAutoUpdateIntervalInvalidValidationDesc":
|
||||
@@ -269,6 +285,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"remoteBackupDesc": MessageLookupByLibrary.simpleMessage("备份数据到WebDAV"),
|
||||
"remoteRecoveryDesc":
|
||||
MessageLookupByLibrary.simpleMessage("通过WebDAV恢复数据"),
|
||||
"remove": MessageLookupByLibrary.simpleMessage("移除"),
|
||||
"requests": MessageLookupByLibrary.simpleMessage("请求"),
|
||||
"requestsDesc": MessageLookupByLibrary.simpleMessage("查看最近请求记录"),
|
||||
"reset": MessageLookupByLibrary.simpleMessage("重置"),
|
||||
@@ -318,7 +335,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"themeDesc": MessageLookupByLibrary.simpleMessage("设置深色模式,调整色彩"),
|
||||
"themeMode": MessageLookupByLibrary.simpleMessage("主题模式"),
|
||||
"threeColumns": MessageLookupByLibrary.simpleMessage("三列"),
|
||||
"tight": MessageLookupByLibrary.simpleMessage("宽松"),
|
||||
"tight": MessageLookupByLibrary.simpleMessage("紧凑"),
|
||||
"time": MessageLookupByLibrary.simpleMessage("时间"),
|
||||
"tip": MessageLookupByLibrary.simpleMessage("提示"),
|
||||
"tools": MessageLookupByLibrary.simpleMessage("工具"),
|
||||
|
||||
@@ -2949,6 +2949,156 @@ class AppLocalizations {
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Show/Hide`
|
||||
String get action_view {
|
||||
return Intl.message(
|
||||
'Show/Hide',
|
||||
name: 'action_view',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Start/Stop`
|
||||
String get action_start {
|
||||
return Intl.message(
|
||||
'Start/Stop',
|
||||
name: 'action_start',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Switch mode`
|
||||
String get action_mode {
|
||||
return Intl.message(
|
||||
'Switch mode',
|
||||
name: 'action_mode',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `System proxy`
|
||||
String get action_proxy {
|
||||
return Intl.message(
|
||||
'System proxy',
|
||||
name: 'action_proxy',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `TUN`
|
||||
String get action_tun {
|
||||
return Intl.message(
|
||||
'TUN',
|
||||
name: 'action_tun',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Disclaimer`
|
||||
String get disclaimer {
|
||||
return Intl.message(
|
||||
'Disclaimer',
|
||||
name: 'disclaimer',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `This software is only used for non-commercial purposes such as learning exchanges and scientific research. It is strictly prohibited to use this software for commercial purposes. Any commercial activity, if any, has nothing to do with this software.`
|
||||
String get disclaimerDesc {
|
||||
return Intl.message(
|
||||
'This software is only used for non-commercial purposes such as learning exchanges and scientific research. It is strictly prohibited to use this software for commercial purposes. Any commercial activity, if any, has nothing to do with this software.',
|
||||
name: 'disclaimerDesc',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Agree`
|
||||
String get agree {
|
||||
return Intl.message(
|
||||
'Agree',
|
||||
name: 'agree',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Hotkey Management`
|
||||
String get hotkeyManagement {
|
||||
return Intl.message(
|
||||
'Hotkey Management',
|
||||
name: 'hotkeyManagement',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Use keyboard to control applications`
|
||||
String get hotkeyManagementDesc {
|
||||
return Intl.message(
|
||||
'Use keyboard to control applications',
|
||||
name: 'hotkeyManagementDesc',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Please press the keyboard.`
|
||||
String get pressKeyboard {
|
||||
return Intl.message(
|
||||
'Please press the keyboard.',
|
||||
name: 'pressKeyboard',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Please enter the correct hotkey`
|
||||
String get inputCorrectHotkey {
|
||||
return Intl.message(
|
||||
'Please enter the correct hotkey',
|
||||
name: 'inputCorrectHotkey',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Hotkey conflict`
|
||||
String get hotkeyConflict {
|
||||
return Intl.message(
|
||||
'Hotkey conflict',
|
||||
name: 'hotkeyConflict',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Remove`
|
||||
String get remove {
|
||||
return Intl.message(
|
||||
'Remove',
|
||||
name: 'remove',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `No HotKey`
|
||||
String get noHotKey {
|
||||
return Intl.message(
|
||||
'No HotKey',
|
||||
name: 'noHotKey',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||
|
||||
@@ -18,13 +18,15 @@ Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
clashCore.initMessage();
|
||||
globalState.packageInfo = await PackageInfo.fromPlatform();
|
||||
final version = await system.version;
|
||||
final config = await preferences.getConfig() ?? Config();
|
||||
globalState.autoRun = config.autoRun;
|
||||
final clashConfig = await preferences.getClashConfig() ?? ClashConfig();
|
||||
await android?.init();
|
||||
await window?.init(config.windowProps);
|
||||
await window?.init(config.windowProps, version);
|
||||
final appState = AppState(
|
||||
mode: clashConfig.mode,
|
||||
version: version,
|
||||
isCompatible: config.isCompatible,
|
||||
selectedMap: config.currentSelectedMap,
|
||||
);
|
||||
@@ -32,11 +34,6 @@ Future<void> main() async {
|
||||
openLogs: config.openLogs,
|
||||
hasProxies: false,
|
||||
);
|
||||
globalState.updateTray(
|
||||
appState: appState,
|
||||
config: config,
|
||||
clashConfig: clashConfig,
|
||||
);
|
||||
await globalState.init(
|
||||
appState: appState,
|
||||
config: config,
|
||||
@@ -56,12 +53,14 @@ Future<void> vpnService() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
globalState.isVpnService = true;
|
||||
globalState.packageInfo = await PackageInfo.fromPlatform();
|
||||
final version = await system.version;
|
||||
final config = await preferences.getConfig() ?? Config();
|
||||
final clashConfig = await preferences.getClashConfig() ?? ClashConfig();
|
||||
final appState = AppState(
|
||||
mode: clashConfig.mode,
|
||||
isCompatible: config.isCompatible,
|
||||
selectedMap: config.currentSelectedMap,
|
||||
version: version,
|
||||
);
|
||||
await globalState.init(
|
||||
appState: appState,
|
||||
@@ -76,7 +75,7 @@ Future<void> vpnService() async {
|
||||
clashCore.setFdMap(fd.id);
|
||||
},
|
||||
onProcess: (Process process) async {
|
||||
final packageName = await app?.resolverProcess(process);
|
||||
final packageName = await vpn?.resolverProcess(process);
|
||||
clashCore.setProcessMap(
|
||||
ProcessMapItem(
|
||||
id: process.id,
|
||||
|
||||
@@ -5,20 +5,25 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class AndroidContainer extends StatefulWidget {
|
||||
class AndroidManager extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const AndroidContainer({
|
||||
const AndroidManager({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AndroidContainer> createState() => _AndroidContainerState();
|
||||
State<AndroidManager> createState() => _AndroidContainerState();
|
||||
}
|
||||
|
||||
class _AndroidContainerState extends State<AndroidContainer>
|
||||
with WidgetsBindingObserver {
|
||||
class _AndroidContainerState extends State<AndroidManager> {
|
||||
@override
|
||||
void initState() {
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
Widget _excludeContainer(Widget child) {
|
||||
return Selector<Config, bool>(
|
||||
selector: (_, config) => config.isExclude,
|
||||
@@ -44,31 +49,10 @@ class _AndroidContainerState extends State<AndroidContainer>
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
|
||||
final isPaused = state == AppLifecycleState.paused;
|
||||
if (isPaused) {
|
||||
await globalState.appController.savePreferences();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _systemUiOverlayContainer(
|
||||
_excludeContainer(widget.child),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -4,14 +4,20 @@ import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class AppStateContainer extends StatelessWidget {
|
||||
class AppStateManager extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const AppStateContainer({
|
||||
const AppStateManager({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
State<AppStateManager> createState() => _AppStateManagerState();
|
||||
}
|
||||
|
||||
class _AppStateManagerState extends State<AppStateManager>
|
||||
with WidgetsBindingObserver {
|
||||
_updateNavigationsContainer(Widget child) {
|
||||
return Selector2<AppState, Config, UpdateNavigationsSelector>(
|
||||
selector: (_, appState, config) {
|
||||
@@ -38,10 +44,36 @@ class AppStateContainer extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
|
||||
final isPaused = state == AppLifecycleState.paused;
|
||||
if (isPaused) {
|
||||
await globalState.appController.savePreferences();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangePlatformBrightness() {
|
||||
globalState.appController.appState.brightness =
|
||||
WidgetsBinding.instance.platformDispatcher.platformBrightness;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return _updateNavigationsContainer(
|
||||
child,
|
||||
widget.child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -5,27 +5,27 @@ import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../common/function.dart';
|
||||
import '../../common/function.dart';
|
||||
|
||||
class ClashContainer extends StatefulWidget {
|
||||
class ClashManager extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const ClashContainer({
|
||||
const ClashManager({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
State<ClashContainer> createState() => _ClashContainerState();
|
||||
State<ClashManager> createState() => _ClashContainerState();
|
||||
}
|
||||
|
||||
class _ClashContainerState extends State<ClashContainer>
|
||||
class _ClashContainerState extends State<ClashManager>
|
||||
with AppMessageListener {
|
||||
Function? updateClashConfigDebounce;
|
||||
|
||||
Widget _updateContainer(Widget child) {
|
||||
return Selector2<Config,ClashConfig, ClashConfigState>(
|
||||
selector: (_,config, clashConfig) => ClashConfigState(
|
||||
return Selector2<Config, ClashConfig, ClashConfigState>(
|
||||
selector: (_, config, clashConfig) => ClashConfigState(
|
||||
overrideDns: config.overrideDns,
|
||||
mixedPort: clashConfig.mixedPort,
|
||||
allowLan: clashConfig.allowLan,
|
||||
@@ -45,14 +45,16 @@ class _ClashContainerState extends State<ClashContainer>
|
||||
rules: clashConfig.rules,
|
||||
globalRealUa: clashConfig.globalRealUa,
|
||||
),
|
||||
builder: (__, state, child) {
|
||||
if (updateClashConfigDebounce == null) {
|
||||
updateClashConfigDebounce = debounce<Function()>(() async {
|
||||
shouldRebuild: (prev, next) {
|
||||
if (prev != next) {
|
||||
updateClashConfigDebounce ??= debounce<Function()>(() async {
|
||||
await globalState.appController.updateClashConfig();
|
||||
});
|
||||
} else {
|
||||
updateClashConfigDebounce!();
|
||||
}
|
||||
return prev != next;
|
||||
},
|
||||
builder: (__, state, child) {
|
||||
return child!;
|
||||
},
|
||||
child: child,
|
||||
@@ -139,7 +141,7 @@ class _ClashContainerState extends State<ClashContainer>
|
||||
if (log.logLevel == LogLevel.error) {
|
||||
globalState.appController.showSnackBar(log.payload ?? '');
|
||||
}
|
||||
// debugPrint("$log");
|
||||
debugPrint("$log");
|
||||
super.onLog(log);
|
||||
}
|
||||
|
||||
75
lib/manager/hotkey_manager.dart
Normal file
75
lib/manager/hotkey_manager.dart
Normal file
@@ -0,0 +1,75 @@
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/models/common.dart';
|
||||
import 'package:fl_clash/models/config.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hotkey_manager/hotkey_manager.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class HotKeyManager extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const HotKeyManager({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
_handleHotKeyAction(HotAction action) async {
|
||||
switch (action) {
|
||||
case HotAction.mode:
|
||||
globalState.appController.updateMode();
|
||||
case HotAction.start:
|
||||
globalState.appController.updateStart();
|
||||
case HotAction.view:
|
||||
globalState.appController.updateVisible();
|
||||
case HotAction.proxy:
|
||||
globalState.appController.updateSystemProxy();
|
||||
case HotAction.tun:
|
||||
globalState.appController.updateTun();
|
||||
}
|
||||
}
|
||||
|
||||
_updateHotKeys({
|
||||
required List<HotKeyAction> hotKeyActions,
|
||||
}) async {
|
||||
await hotKeyManager.unregisterAll();
|
||||
final hotkeyActionHandles = hotKeyActions.where(
|
||||
(hotKeyAction) {
|
||||
return hotKeyAction.key != null && hotKeyAction.modifiers.isNotEmpty;
|
||||
},
|
||||
).map<Future>(
|
||||
(hotKeyAction) async {
|
||||
final modifiers = hotKeyAction.modifiers
|
||||
.map((item) => item.toHotKeyModifier())
|
||||
.toList();
|
||||
final hotKey = HotKey(
|
||||
key: PhysicalKeyboardKey(hotKeyAction.key!),
|
||||
modifiers: modifiers,
|
||||
);
|
||||
return await hotKeyManager.register(
|
||||
hotKey,
|
||||
keyDownHandler: (_) {
|
||||
_handleHotKeyAction(hotKeyAction.action);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
await Future.wait(hotkeyActionHandles);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector<Config, List<HotKeyAction>>(
|
||||
selector: (_, config) => config.hotKeyActions,
|
||||
shouldRebuild: (prev, next) {
|
||||
return !hotKeyActionsEquality.equals(prev, next);
|
||||
},
|
||||
builder: (_, hotKeyActions, __) {
|
||||
_updateHotKeys(hotKeyActions: hotKeyActions);
|
||||
return child;
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
9
lib/manager/manager.dart
Normal file
9
lib/manager/manager.dart
Normal file
@@ -0,0 +1,9 @@
|
||||
export 'tray_manager.dart';
|
||||
export 'window_manager.dart';
|
||||
export 'android_manager.dart';
|
||||
export 'clash_manager.dart';
|
||||
export 'tile_manager.dart';
|
||||
export 'app_state_manager.dart';
|
||||
export 'vpn_manager.dart';
|
||||
export 'media_manager.dart';
|
||||
export 'proxy_manager.dart';
|
||||
41
lib/manager/media_manager.dart
Normal file
41
lib/manager/media_manager.dart
Normal file
@@ -0,0 +1,41 @@
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/models/config.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MediaManager extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const MediaManager({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector<Config, ScaleProps>(
|
||||
selector: (_, config) => config.scaleProps,
|
||||
builder: (_, props, child) {
|
||||
globalState.measure = Measure.of(context);
|
||||
return child!;
|
||||
// final textScaleFactor =
|
||||
// WidgetsBinding.instance.platformDispatcher.textScaleFactor;
|
||||
// return MediaQuery(
|
||||
// data: MediaQuery.of(context).copyWith(
|
||||
// textScaler: props.custom
|
||||
// ? TextScaler.linear(props.scale * textScaleFactor)
|
||||
// : null,
|
||||
// ),
|
||||
// child: Builder(
|
||||
// builder: (context) {
|
||||
// globalState.measure = Measure.of(context);
|
||||
// return child!;
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@ import 'package:fl_clash/models/models.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ProxyContainer extends StatelessWidget {
|
||||
class ProxyManager extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const ProxyContainer({super.key, required this.child});
|
||||
const ProxyManager({super.key, required this.child});
|
||||
|
||||
_updateProxy(ProxyState proxyState) {
|
||||
final isStart = proxyState.isStart;
|
||||
@@ -2,19 +2,19 @@ import 'package:fl_clash/plugins/tile.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TileContainer extends StatefulWidget {
|
||||
class TileManager extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const TileContainer({
|
||||
const TileManager({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
State<TileContainer> createState() => _TileContainerState();
|
||||
State<TileManager> createState() => _TileContainerState();
|
||||
}
|
||||
|
||||
class _TileContainerState extends State<TileContainer> with TileListener {
|
||||
class _TileContainerState extends State<TileManager> with TileListener {
|
||||
|
||||
|
||||
@override
|
||||
177
lib/manager/tray_manager.dart
Executable file
177
lib/manager/tray_manager.dart
Executable file
@@ -0,0 +1,177 @@
|
||||
import 'dart:io';
|
||||
|
||||
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/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tray_manager/tray_manager.dart';
|
||||
|
||||
class TrayManager extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const TrayManager({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
State<TrayManager> createState() => _TrayContainerState();
|
||||
}
|
||||
|
||||
class _TrayContainerState extends State<TrayManager> with TrayListener {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
trayManager.addListener(this);
|
||||
}
|
||||
|
||||
_updateSystemTray({
|
||||
required bool isStart,
|
||||
required Brightness? brightness,
|
||||
}) async {
|
||||
if (Platform.isLinux) {
|
||||
await trayManager.destroy();
|
||||
}
|
||||
await trayManager.setIcon(
|
||||
other.getTrayIconPath(
|
||||
isStart: isStart,
|
||||
brightness: brightness ??
|
||||
WidgetsBinding.instance.platformDispatcher.platformBrightness,
|
||||
),
|
||||
);
|
||||
if(!Platform.isLinux){
|
||||
await trayManager.setToolTip(
|
||||
appName,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_updateTray(TrayState trayState) async {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (!Platform.isLinux) {
|
||||
_updateSystemTray(
|
||||
isStart: trayState.isStart,
|
||||
brightness: trayState.brightness,
|
||||
);
|
||||
}
|
||||
List<MenuItem> menuItems = [];
|
||||
final showMenuItem = MenuItem(
|
||||
label: appLocalizations.show,
|
||||
onClick: (_) {
|
||||
window?.show();
|
||||
},
|
||||
);
|
||||
menuItems.add(showMenuItem);
|
||||
final startMenuItem = MenuItem.checkbox(
|
||||
label:
|
||||
trayState.isStart ? appLocalizations.stop : appLocalizations.start,
|
||||
onClick: (_) async {
|
||||
globalState.appController.updateStart();
|
||||
},
|
||||
checked: false,
|
||||
);
|
||||
menuItems.add(startMenuItem);
|
||||
menuItems.add(MenuItem.separator());
|
||||
for (final mode in Mode.values) {
|
||||
menuItems.add(
|
||||
MenuItem.checkbox(
|
||||
label: Intl.message(mode.name),
|
||||
onClick: (_) {
|
||||
globalState.appController.clashConfig.mode = mode;
|
||||
},
|
||||
checked: mode == trayState.mode,
|
||||
),
|
||||
);
|
||||
}
|
||||
menuItems.add(MenuItem.separator());
|
||||
if (trayState.isStart) {
|
||||
menuItems.add(
|
||||
MenuItem.checkbox(
|
||||
label: appLocalizations.tun,
|
||||
onClick: (_) {
|
||||
globalState.appController.updateTun();
|
||||
},
|
||||
checked: trayState.tunEnable,
|
||||
),
|
||||
);
|
||||
menuItems.add(
|
||||
MenuItem.checkbox(
|
||||
label: appLocalizations.systemProxy,
|
||||
onClick: (_) {
|
||||
globalState.appController.updateSystemProxy();
|
||||
},
|
||||
checked: trayState.systemProxy,
|
||||
),
|
||||
);
|
||||
menuItems.add(MenuItem.separator());
|
||||
}
|
||||
final autoStartMenuItem = MenuItem.checkbox(
|
||||
label: appLocalizations.autoLaunch,
|
||||
onClick: (_) async {
|
||||
globalState.appController.updateAutoLaunch();
|
||||
},
|
||||
checked: trayState.autoLaunch,
|
||||
);
|
||||
menuItems.add(autoStartMenuItem);
|
||||
menuItems.add(MenuItem.separator());
|
||||
final exitMenuItem = MenuItem(
|
||||
label: appLocalizations.exit,
|
||||
onClick: (_) async {
|
||||
await globalState.appController.handleExit();
|
||||
},
|
||||
);
|
||||
menuItems.add(exitMenuItem);
|
||||
final menu = Menu();
|
||||
menu.items = menuItems;
|
||||
trayManager.setContextMenu(menu);
|
||||
if (Platform.isLinux) {
|
||||
_updateSystemTray(
|
||||
isStart: trayState.isStart,
|
||||
brightness: trayState.brightness,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector3<AppState, Config, ClashConfig, TrayState>(
|
||||
selector: (_, appState, config, clashConfig) => TrayState(
|
||||
mode: clashConfig.mode,
|
||||
autoLaunch: config.autoLaunch,
|
||||
isStart: appState.isStart,
|
||||
locale: config.locale,
|
||||
systemProxy: config.desktopProps.systemProxy,
|
||||
tunEnable: clashConfig.tun.enable,
|
||||
brightness: appState.brightness,
|
||||
),
|
||||
shouldRebuild: (prev, next) {
|
||||
return prev != next;
|
||||
},
|
||||
builder: (_, state, child) {
|
||||
_updateTray(state);
|
||||
return child!;
|
||||
},
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void onTrayIconRightMouseDown() {
|
||||
trayManager.popUpContextMenu();
|
||||
}
|
||||
|
||||
@override
|
||||
onTrayIconMouseDown() {
|
||||
window?.show();
|
||||
}
|
||||
|
||||
@override
|
||||
dispose() {
|
||||
trayManager.removeListener(this);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
@@ -4,21 +4,21 @@ import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../common/function.dart';
|
||||
import '../../common/function.dart';
|
||||
|
||||
class VpnContainer extends StatefulWidget {
|
||||
class VpnManager extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const VpnContainer({
|
||||
const VpnManager({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
State<VpnContainer> createState() => _VpnContainerState();
|
||||
State<VpnManager> createState() => _VpnContainerState();
|
||||
}
|
||||
|
||||
class _VpnContainerState extends State<VpnContainer> {
|
||||
class _VpnContainerState extends State<VpnManager> {
|
||||
Function? vpnTipDebounce;
|
||||
|
||||
showTip() {
|
||||
@@ -7,19 +7,19 @@ import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
class WindowContainer extends StatefulWidget {
|
||||
class WindowManager extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const WindowContainer({
|
||||
const WindowManager({
|
||||
super.key,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
@override
|
||||
State<WindowContainer> createState() => _WindowContainerState();
|
||||
State<WindowManager> createState() => _WindowContainerState();
|
||||
}
|
||||
|
||||
class _WindowContainerState extends State<WindowContainer> with WindowListener {
|
||||
class _WindowContainerState extends State<WindowManager> with WindowListener {
|
||||
Function? updateLaunchDebounce;
|
||||
|
||||
_autoLaunchContainer(Widget child) {
|
||||
@@ -99,21 +99,30 @@ class WindowHeaderContainer extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
Column(
|
||||
return Selector<AppState, int>(
|
||||
selector: (_, appState) => appState.version,
|
||||
builder: (_, version, child) {
|
||||
if (version <= 10 && Platform.isMacOS) {
|
||||
return child!;
|
||||
}
|
||||
return Stack(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: kHeaderHeight,
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: child,
|
||||
Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: kHeaderHeight,
|
||||
),
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: child!,
|
||||
),
|
||||
],
|
||||
),
|
||||
const WindowHeader(),
|
||||
],
|
||||
),
|
||||
const WindowHeader(),
|
||||
],
|
||||
);
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -240,14 +249,20 @@ class _WindowHeaderState extends State<WindowHeader> {
|
||||
),
|
||||
),
|
||||
),
|
||||
const Positioned(
|
||||
left: 0,
|
||||
child: AppIcon(),
|
||||
),
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: _buildActions(),
|
||||
),
|
||||
if (Platform.isMacOS)
|
||||
const Text(
|
||||
appName,
|
||||
)
|
||||
else ...[
|
||||
const Positioned(
|
||||
left: 0,
|
||||
child: AppIcon(),
|
||||
),
|
||||
Positioned(
|
||||
right: 0,
|
||||
child: _buildActions(),
|
||||
),
|
||||
]
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -4,16 +4,9 @@ import 'package:collection/collection.dart';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'connection.dart';
|
||||
import 'common.dart';
|
||||
import 'ffi.dart';
|
||||
import 'log.dart';
|
||||
import 'navigation.dart';
|
||||
import 'package.dart';
|
||||
import 'profile.dart';
|
||||
import 'proxy.dart';
|
||||
import 'system_color_scheme.dart';
|
||||
import 'traffic.dart';
|
||||
import 'version.dart';
|
||||
|
||||
typedef DelayMap = Map<String, int?>;
|
||||
|
||||
@@ -38,11 +31,14 @@ class AppState with ChangeNotifier {
|
||||
num _checkIpNum;
|
||||
List<ExternalProvider> _providers;
|
||||
List<Package> _packages;
|
||||
Brightness? _brightness;
|
||||
int _version;
|
||||
|
||||
AppState({
|
||||
required Mode mode,
|
||||
required bool isCompatible,
|
||||
required SelectedMap selectedMap,
|
||||
required int version,
|
||||
}) : _navigationItems = [],
|
||||
_isInit = false,
|
||||
_currentLabel = "dashboard",
|
||||
@@ -54,13 +50,15 @@ class AppState with ChangeNotifier {
|
||||
_checkIpNum = 0,
|
||||
_requests = [],
|
||||
_mode = mode,
|
||||
_brightness = null,
|
||||
_totalTraffic = Traffic(),
|
||||
_delayMap = {},
|
||||
_groups = [],
|
||||
_providers = [],
|
||||
_packages = [],
|
||||
_isCompatible = isCompatible,
|
||||
_systemColorSchemes = const SystemColorSchemes();
|
||||
_systemColorSchemes = const SystemColorSchemes(),
|
||||
_version = version;
|
||||
|
||||
String get currentLabel => _currentLabel;
|
||||
|
||||
@@ -354,7 +352,7 @@ class AppState with ChangeNotifier {
|
||||
}
|
||||
|
||||
setProvider(ExternalProvider? provider) {
|
||||
if(provider == null) return;
|
||||
if (provider == null) return;
|
||||
final index = _providers.indexWhere((item) => item.name == provider.name);
|
||||
if (index == -1) return;
|
||||
_providers = List.from(_providers)..[index] = provider;
|
||||
@@ -366,4 +364,22 @@ class AppState with ChangeNotifier {
|
||||
currentGroups.indexWhere((element) => element.name == groupName);
|
||||
return index != -1 ? currentGroups[index] : null;
|
||||
}
|
||||
|
||||
Brightness? get brightness => _brightness;
|
||||
|
||||
set brightness(Brightness? value) {
|
||||
if (_brightness != value) {
|
||||
_brightness = value;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
int get version => _version;
|
||||
|
||||
set version(int value) {
|
||||
if (_version != value) {
|
||||
_version = value;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
438
lib/models/common.dart
Normal file
438
lib/models/common.dart
Normal file
@@ -0,0 +1,438 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'generated/common.freezed.dart';
|
||||
|
||||
part 'generated/common.g.dart';
|
||||
|
||||
@freezed
|
||||
class NavigationItem with _$NavigationItem {
|
||||
const factory NavigationItem({
|
||||
required Icon icon,
|
||||
required String label,
|
||||
final String? description,
|
||||
required Widget fragment,
|
||||
@Default(true) bool keep,
|
||||
String? path,
|
||||
@Default([NavigationItemMode.mobile, NavigationItemMode.desktop])
|
||||
List<NavigationItemMode> modes,
|
||||
}) = _NavigationItem;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class Package with _$Package {
|
||||
const factory Package({
|
||||
required String packageName,
|
||||
required String label,
|
||||
required bool isSystem,
|
||||
required int firstInstallTime,
|
||||
}) = _Package;
|
||||
|
||||
factory Package.fromJson(Map<String, Object?> json) =>
|
||||
_$PackageFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class Metadata with _$Metadata {
|
||||
const factory Metadata({
|
||||
required int uid,
|
||||
required String network,
|
||||
required String sourceIP,
|
||||
required String sourcePort,
|
||||
required String destinationIP,
|
||||
required String destinationPort,
|
||||
required String host,
|
||||
required String process,
|
||||
required String remoteDestination,
|
||||
}) = _Metadata;
|
||||
|
||||
factory Metadata.fromJson(Map<String, Object?> json) =>
|
||||
_$MetadataFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class Connection with _$Connection {
|
||||
const factory Connection({
|
||||
required String id,
|
||||
num? upload,
|
||||
num? download,
|
||||
required DateTime start,
|
||||
required Metadata metadata,
|
||||
required List<String> chains,
|
||||
}) = _Connection;
|
||||
|
||||
factory Connection.fromJson(Map<String, Object?> json) =>
|
||||
_$ConnectionFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class Log {
|
||||
@JsonKey(name: "LogLevel")
|
||||
LogLevel logLevel;
|
||||
@JsonKey(name: "Payload")
|
||||
String? payload;
|
||||
DateTime _dateTime;
|
||||
|
||||
Log({
|
||||
required this.logLevel,
|
||||
this.payload,
|
||||
}) : _dateTime = DateTime.now();
|
||||
|
||||
DateTime get dateTime => _dateTime;
|
||||
|
||||
factory Log.fromJson(Map<String, dynamic> json) {
|
||||
return _$LogFromJson(json);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$LogToJson(this);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Log{logLevel: $logLevel, payload: $payload, dateTime: $dateTime}';
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class LogsAndKeywords with _$LogsAndKeywords {
|
||||
const factory LogsAndKeywords({
|
||||
@Default([]) List<Log> logs,
|
||||
@Default([]) List<String> keywords,
|
||||
}) = _LogsAndKeywords;
|
||||
|
||||
factory LogsAndKeywords.fromJson(Map<String, Object?> json) =>
|
||||
_$LogsAndKeywordsFromJson(json);
|
||||
}
|
||||
|
||||
extension LogsAndKeywordsExt on LogsAndKeywords {
|
||||
List<Log> get filteredLogs => logs
|
||||
.where(
|
||||
(log) => {log.logLevel.name}.containsAll(keywords),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ConnectionsAndKeywords with _$ConnectionsAndKeywords {
|
||||
const factory ConnectionsAndKeywords({
|
||||
@Default([]) List<Connection> connections,
|
||||
@Default([]) List<String> keywords,
|
||||
}) = _ConnectionsAndKeywords;
|
||||
|
||||
factory ConnectionsAndKeywords.fromJson(Map<String, Object?> json) =>
|
||||
_$ConnectionsAndKeywordsFromJson(json);
|
||||
}
|
||||
|
||||
extension ConnectionsAndKeywordsExt on ConnectionsAndKeywords {
|
||||
List<Connection> get filteredConnections => connections
|
||||
.where((connection) => {
|
||||
...connection.chains,
|
||||
connection.metadata.process,
|
||||
}.containsAll(keywords))
|
||||
.toList();
|
||||
}
|
||||
|
||||
const defaultDavFileName = "backup.zip";
|
||||
|
||||
@freezed
|
||||
class DAV with _$DAV {
|
||||
const factory DAV({
|
||||
required String uri,
|
||||
required String user,
|
||||
required String password,
|
||||
@Default(defaultDavFileName) String fileName,
|
||||
}) = _DAV;
|
||||
|
||||
factory DAV.fromJson(Map<String, Object?> json) => _$DAVFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class FileInfo with _$FileInfo {
|
||||
const factory FileInfo({
|
||||
required int size,
|
||||
required DateTime lastModified,
|
||||
}) = _FileInfo;
|
||||
}
|
||||
|
||||
extension FileInfoExt on FileInfo {
|
||||
String get desc =>
|
||||
"${TrafficValue(value: size).show} · ${lastModified.lastUpdateTimeDesc}";
|
||||
}
|
||||
|
||||
@freezed
|
||||
class VersionInfo with _$VersionInfo {
|
||||
const factory VersionInfo({
|
||||
@Default("") String clashName,
|
||||
@Default("") String version,
|
||||
}) = _VersionInfo;
|
||||
|
||||
factory VersionInfo.fromJson(Map<String, Object?> json) =>
|
||||
_$VersionInfoFromJson(json);
|
||||
}
|
||||
|
||||
class Traffic {
|
||||
int id;
|
||||
TrafficValue up;
|
||||
TrafficValue down;
|
||||
|
||||
Traffic({num? up, num? down})
|
||||
: id = DateTime.now().millisecondsSinceEpoch,
|
||||
up = TrafficValue(value: up),
|
||||
down = TrafficValue(value: down);
|
||||
|
||||
num get speed => up.value + down.value;
|
||||
|
||||
factory Traffic.fromMap(Map<String, dynamic> map) {
|
||||
return Traffic(
|
||||
up: map['up'],
|
||||
down: map['down'],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '$up↑ $down↓';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is Traffic &&
|
||||
runtimeType == other.runtimeType &&
|
||||
id == other.id &&
|
||||
up == other.up &&
|
||||
down == other.down;
|
||||
|
||||
@override
|
||||
int get hashCode => id.hashCode ^ up.hashCode ^ down.hashCode;
|
||||
}
|
||||
|
||||
@immutable
|
||||
class TrafficValueShow {
|
||||
final String value;
|
||||
final TrafficUnit unit;
|
||||
|
||||
const TrafficValueShow({
|
||||
required this.value,
|
||||
required this.unit,
|
||||
});
|
||||
}
|
||||
|
||||
@immutable
|
||||
class TrafficValue {
|
||||
final num _value;
|
||||
|
||||
const TrafficValue({num? value}) : _value = value ?? 0;
|
||||
|
||||
num get value => _value;
|
||||
|
||||
String get show => "$showValue $showUnit";
|
||||
|
||||
String get showValue => trafficValueShow.value;
|
||||
|
||||
String get showUnit => trafficValueShow.unit.name;
|
||||
|
||||
TrafficValueShow get trafficValueShow {
|
||||
if (_value > pow(1024, 4)) {
|
||||
return TrafficValueShow(
|
||||
value: (_value / pow(1024, 4)).fixed(),
|
||||
unit: TrafficUnit.TB,
|
||||
);
|
||||
}
|
||||
if (_value > pow(1024, 3)) {
|
||||
return TrafficValueShow(
|
||||
value: (_value / pow(1024, 3)).fixed(),
|
||||
unit: TrafficUnit.GB,
|
||||
);
|
||||
}
|
||||
if (_value > pow(1024, 2)) {
|
||||
return TrafficValueShow(
|
||||
value: (_value / pow(1024, 2)).fixed(), unit: TrafficUnit.MB);
|
||||
}
|
||||
if (_value > pow(1024, 1)) {
|
||||
return TrafficValueShow(
|
||||
value: (_value / pow(1024, 1)).fixed(),
|
||||
unit: TrafficUnit.KB,
|
||||
);
|
||||
}
|
||||
return TrafficValueShow(
|
||||
value: _value.fixed(),
|
||||
unit: TrafficUnit.B,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "$showValue$showUnit";
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
other is TrafficValue &&
|
||||
runtimeType == other.runtimeType &&
|
||||
_value == other._value;
|
||||
|
||||
@override
|
||||
int get hashCode => _value.hashCode;
|
||||
}
|
||||
|
||||
typedef ProxyMap = Map<String, Proxy>;
|
||||
|
||||
@freezed
|
||||
class Group with _$Group {
|
||||
const factory Group({
|
||||
required GroupType type,
|
||||
@Default([]) List<Proxy> all,
|
||||
String? now,
|
||||
bool? hidden,
|
||||
@Default("") String icon,
|
||||
required String name,
|
||||
}) = _Group;
|
||||
|
||||
factory Group.fromJson(Map<String, Object?> json) => _$GroupFromJson(json);
|
||||
}
|
||||
|
||||
extension GroupExt on Group {
|
||||
String get realNow => now ?? "";
|
||||
|
||||
String getCurrentSelectedName(String proxyName) {
|
||||
if (type == GroupType.URLTest) {
|
||||
return realNow.isNotEmpty ? realNow : proxyName;
|
||||
}
|
||||
return proxyName.isNotEmpty ? proxyName : realNow;
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class Proxy with _$Proxy {
|
||||
const factory Proxy({
|
||||
required String name,
|
||||
required String type,
|
||||
String? now,
|
||||
}) = _Proxy;
|
||||
|
||||
factory Proxy.fromJson(Map<String, Object?> json) => _$ProxyFromJson(json);
|
||||
}
|
||||
|
||||
@immutable
|
||||
class SystemColorSchemes {
|
||||
final ColorScheme? lightColorScheme;
|
||||
final ColorScheme? darkColorScheme;
|
||||
|
||||
const SystemColorSchemes({
|
||||
this.lightColorScheme,
|
||||
this.darkColorScheme,
|
||||
});
|
||||
|
||||
getSystemColorSchemeForBrightness(Brightness? brightness) {
|
||||
if (brightness == Brightness.dark) {
|
||||
return darkColorScheme != null
|
||||
? ColorScheme.fromSeed(
|
||||
seedColor: darkColorScheme!.primary,
|
||||
brightness: Brightness.dark,
|
||||
)
|
||||
: ColorScheme.fromSeed(
|
||||
seedColor: defaultPrimaryColor,
|
||||
brightness: Brightness.dark,
|
||||
);
|
||||
}
|
||||
return lightColorScheme != null
|
||||
? ColorScheme.fromSeed(seedColor: darkColorScheme!.primary)
|
||||
: ColorScheme.fromSeed(seedColor: defaultPrimaryColor);
|
||||
}
|
||||
}
|
||||
|
||||
class IpInfo {
|
||||
final String ip;
|
||||
final String countryCode;
|
||||
|
||||
const IpInfo({
|
||||
required this.ip,
|
||||
required this.countryCode,
|
||||
});
|
||||
|
||||
static IpInfo fromIpInfoIoJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
"ip": final String ip,
|
||||
"country": final String country,
|
||||
} =>
|
||||
IpInfo(
|
||||
ip: ip,
|
||||
countryCode: country,
|
||||
),
|
||||
_ => throw const FormatException("invalid json"),
|
||||
};
|
||||
}
|
||||
|
||||
static IpInfo fromIpApiCoJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
"ip": final String ip,
|
||||
"country_code": final String countryCode,
|
||||
} =>
|
||||
IpInfo(
|
||||
ip: ip,
|
||||
countryCode: countryCode,
|
||||
),
|
||||
_ => throw const FormatException("invalid json"),
|
||||
};
|
||||
}
|
||||
|
||||
static IpInfo fromIpSbJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
"ip": final String ip,
|
||||
"country_code": final String countryCode,
|
||||
} =>
|
||||
IpInfo(
|
||||
ip: ip,
|
||||
countryCode: countryCode,
|
||||
),
|
||||
_ => throw const FormatException("invalid json"),
|
||||
};
|
||||
}
|
||||
|
||||
static IpInfo fromIpwhoIsJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
"ip": final String ip,
|
||||
"country_code": final String countryCode,
|
||||
} =>
|
||||
IpInfo(
|
||||
ip: ip,
|
||||
countryCode: countryCode,
|
||||
),
|
||||
_ => throw const FormatException("invalid json"),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'IpInfo{ip: $ip, countryCode: $countryCode}';
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class HotKeyAction with _$HotKeyAction {
|
||||
const factory HotKeyAction({
|
||||
required HotAction action,
|
||||
int? key,
|
||||
@Default({}) Set<KeyboardModifier> modifiers,
|
||||
}) = _HotKeyAction;
|
||||
|
||||
factory HotKeyAction.fromJson(Map<String, Object?> json) =>
|
||||
_$HotKeyActionFromJson(json);
|
||||
}
|
||||
|
||||
const keyboardModifiersEquality = SetEquality<KeyboardModifier>();
|
||||
const hotKeyActionsEquality = ListEquality<HotKeyAction>();
|
||||
|
||||
@@ -143,6 +143,8 @@ class Config extends ChangeNotifier {
|
||||
DesktopProps _desktopProps;
|
||||
bool _showLabel;
|
||||
bool _overrideDns;
|
||||
List<HotKeyAction> _hotKeyActions;
|
||||
bool _isDisclaimerAccepted;
|
||||
|
||||
Config()
|
||||
: _profiles = [],
|
||||
@@ -172,7 +174,9 @@ class Config extends ChangeNotifier {
|
||||
_desktopProps = const DesktopProps(),
|
||||
_showLabel = false,
|
||||
_overrideDns = false,
|
||||
_scaleProps = const ScaleProps();
|
||||
_scaleProps = const ScaleProps(),
|
||||
_isDisclaimerAccepted = false,
|
||||
_hotKeyActions = [];
|
||||
|
||||
deleteProfileById(String id) {
|
||||
_profiles = profiles.where((element) => element.id != id).toList();
|
||||
@@ -597,6 +601,37 @@ class Config extends ChangeNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
@JsonKey(defaultValue: false)
|
||||
bool get isDisclaimerAccepted => _isDisclaimerAccepted;
|
||||
|
||||
set isDisclaimerAccepted(bool value) {
|
||||
if (_isDisclaimerAccepted != value) {
|
||||
_isDisclaimerAccepted = value;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
@JsonKey(defaultValue: [])
|
||||
List<HotKeyAction> get hotKeyActions => _hotKeyActions;
|
||||
|
||||
set hotKeyActions(List<HotKeyAction> value) {
|
||||
if (_hotKeyActions != value) {
|
||||
_hotKeyActions = value;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
updateOrAddHotKeyAction(HotKeyAction hotKeyAction) {
|
||||
final index =
|
||||
_hotKeyActions.indexWhere((item) => item.action == hotKeyAction.action);
|
||||
if (index == -1) {
|
||||
_hotKeyActions = List.from(_hotKeyActions)..add(hotKeyAction);
|
||||
} else {
|
||||
_hotKeyActions = List.from(_hotKeyActions)..[index] = hotKeyAction;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
update([
|
||||
Config? config,
|
||||
RecoveryOption recoveryOptions = RecoveryOption.all,
|
||||
@@ -636,6 +671,7 @@ class Config extends ChangeNotifier {
|
||||
_vpnProps = config._vpnProps;
|
||||
_overrideDns = config._overrideDns;
|
||||
_desktopProps = config._desktopProps;
|
||||
_hotKeyActions = config._hotKeyActions;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'generated/connection.g.dart';
|
||||
|
||||
part 'generated/connection.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class Metadata with _$Metadata {
|
||||
const factory Metadata({
|
||||
required int uid,
|
||||
required String network,
|
||||
required String sourceIP,
|
||||
required String sourcePort,
|
||||
required String destinationIP,
|
||||
required String destinationPort,
|
||||
required String host,
|
||||
required String process,
|
||||
required String remoteDestination,
|
||||
}) = _Metadata;
|
||||
|
||||
factory Metadata.fromJson(Map<String, Object?> json) =>
|
||||
_$MetadataFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class Connection with _$Connection {
|
||||
const factory Connection({
|
||||
required String id,
|
||||
num? upload,
|
||||
num? download,
|
||||
required DateTime start,
|
||||
required Metadata metadata,
|
||||
required List<String> chains,
|
||||
}) = _Connection;
|
||||
|
||||
factory Connection.fromJson(Map<String, Object?> json) =>
|
||||
_$ConnectionFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ConnectionsAndKeywords with _$ConnectionsAndKeywords {
|
||||
const factory ConnectionsAndKeywords({
|
||||
@Default([]) List<Connection> connections,
|
||||
@Default([]) List<String> keywords,
|
||||
}) = _ConnectionsAndKeywords;
|
||||
|
||||
factory ConnectionsAndKeywords.fromJson(Map<String, Object?> json) =>
|
||||
_$ConnectionsAndKeywordsFromJson(json);
|
||||
}
|
||||
|
||||
extension ConnectionsAndKeywordsExt on ConnectionsAndKeywords {
|
||||
List<Connection> get filteredConnections => connections
|
||||
.where((connection) => {
|
||||
...connection.chains,
|
||||
connection.metadata.process,
|
||||
}.containsAll(keywords))
|
||||
.toList();
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'generated/dav.g.dart';
|
||||
|
||||
part 'generated/dav.freezed.dart';
|
||||
|
||||
const defaultDavFileName = "backup.zip";
|
||||
|
||||
@freezed
|
||||
class DAV with _$DAV {
|
||||
const factory DAV({
|
||||
required String uri,
|
||||
required String user,
|
||||
required String password,
|
||||
@Default(defaultDavFileName) String fileName,
|
||||
}) = _DAV;
|
||||
|
||||
factory DAV.fromJson(Map<String, Object?> json) => _$DAVFromJson(json);
|
||||
}
|
||||
@@ -135,6 +135,22 @@ class ExternalProvider with _$ExternalProvider {
|
||||
_$ExternalProviderFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class TunProps with _$TunProps {
|
||||
const factory TunProps({
|
||||
required int fd,
|
||||
required String gateway,
|
||||
required String gateway6,
|
||||
required String portal,
|
||||
required String portal6,
|
||||
required String dns,
|
||||
required String dns6,
|
||||
}) = _TunProps;
|
||||
|
||||
factory TunProps.fromJson(Map<String, Object?> json) =>
|
||||
_$TunPropsFromJson(json);
|
||||
}
|
||||
|
||||
abstract mixin class AppMessageListener {
|
||||
void onLog(Log log) {}
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import 'package:fl_clash/common/datetime.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import 'traffic.dart';
|
||||
|
||||
part 'generated/file.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class FileInfo with _$FileInfo {
|
||||
const factory FileInfo({
|
||||
required int size,
|
||||
required DateTime lastModified,
|
||||
}) = _FileInfo;
|
||||
}
|
||||
|
||||
|
||||
extension FileInfoExt on FileInfo{
|
||||
String get desc => "${TrafficValue(value: size).show} · ${lastModified.lastUpdateTimeDesc}";
|
||||
}
|
||||
|
||||
|
||||
2470
lib/models/generated/common.freezed.dart
Normal file
2470
lib/models/generated/common.freezed.dart
Normal file
File diff suppressed because it is too large
Load Diff
232
lib/models/generated/common.g.dart
Normal file
232
lib/models/generated/common.g.dart
Normal file
@@ -0,0 +1,232 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of '../common.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Log _$LogFromJson(Map<String, dynamic> json) => Log(
|
||||
logLevel: $enumDecode(_$LogLevelEnumMap, json['LogLevel']),
|
||||
payload: json['Payload'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LogToJson(Log instance) => <String, dynamic>{
|
||||
'LogLevel': _$LogLevelEnumMap[instance.logLevel]!,
|
||||
'Payload': instance.payload,
|
||||
};
|
||||
|
||||
const _$LogLevelEnumMap = {
|
||||
LogLevel.debug: 'debug',
|
||||
LogLevel.info: 'info',
|
||||
LogLevel.warning: 'warning',
|
||||
LogLevel.error: 'error',
|
||||
LogLevel.silent: 'silent',
|
||||
};
|
||||
|
||||
_$PackageImpl _$$PackageImplFromJson(Map<String, dynamic> json) =>
|
||||
_$PackageImpl(
|
||||
packageName: json['packageName'] as String,
|
||||
label: json['label'] as String,
|
||||
isSystem: json['isSystem'] as bool,
|
||||
firstInstallTime: (json['firstInstallTime'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$PackageImplToJson(_$PackageImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'packageName': instance.packageName,
|
||||
'label': instance.label,
|
||||
'isSystem': instance.isSystem,
|
||||
'firstInstallTime': instance.firstInstallTime,
|
||||
};
|
||||
|
||||
_$MetadataImpl _$$MetadataImplFromJson(Map<String, dynamic> json) =>
|
||||
_$MetadataImpl(
|
||||
uid: (json['uid'] as num).toInt(),
|
||||
network: json['network'] as String,
|
||||
sourceIP: json['sourceIP'] as String,
|
||||
sourcePort: json['sourcePort'] as String,
|
||||
destinationIP: json['destinationIP'] as String,
|
||||
destinationPort: json['destinationPort'] as String,
|
||||
host: json['host'] as String,
|
||||
process: json['process'] as String,
|
||||
remoteDestination: json['remoteDestination'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$MetadataImplToJson(_$MetadataImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'uid': instance.uid,
|
||||
'network': instance.network,
|
||||
'sourceIP': instance.sourceIP,
|
||||
'sourcePort': instance.sourcePort,
|
||||
'destinationIP': instance.destinationIP,
|
||||
'destinationPort': instance.destinationPort,
|
||||
'host': instance.host,
|
||||
'process': instance.process,
|
||||
'remoteDestination': instance.remoteDestination,
|
||||
};
|
||||
|
||||
_$ConnectionImpl _$$ConnectionImplFromJson(Map<String, dynamic> json) =>
|
||||
_$ConnectionImpl(
|
||||
id: json['id'] as String,
|
||||
upload: json['upload'] as num?,
|
||||
download: json['download'] as num?,
|
||||
start: DateTime.parse(json['start'] as String),
|
||||
metadata: Metadata.fromJson(json['metadata'] as Map<String, dynamic>),
|
||||
chains:
|
||||
(json['chains'] as List<dynamic>).map((e) => e as String).toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ConnectionImplToJson(_$ConnectionImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'upload': instance.upload,
|
||||
'download': instance.download,
|
||||
'start': instance.start.toIso8601String(),
|
||||
'metadata': instance.metadata,
|
||||
'chains': instance.chains,
|
||||
};
|
||||
|
||||
_$LogsAndKeywordsImpl _$$LogsAndKeywordsImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$LogsAndKeywordsImpl(
|
||||
logs: (json['logs'] as List<dynamic>?)
|
||||
?.map((e) => Log.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
keywords: (json['keywords'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList() ??
|
||||
const [],
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$LogsAndKeywordsImplToJson(
|
||||
_$LogsAndKeywordsImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'logs': instance.logs,
|
||||
'keywords': instance.keywords,
|
||||
};
|
||||
|
||||
_$ConnectionsAndKeywordsImpl _$$ConnectionsAndKeywordsImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$ConnectionsAndKeywordsImpl(
|
||||
connections: (json['connections'] as List<dynamic>?)
|
||||
?.map((e) => Connection.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
keywords: (json['keywords'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList() ??
|
||||
const [],
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ConnectionsAndKeywordsImplToJson(
|
||||
_$ConnectionsAndKeywordsImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'connections': instance.connections,
|
||||
'keywords': instance.keywords,
|
||||
};
|
||||
|
||||
_$DAVImpl _$$DAVImplFromJson(Map<String, dynamic> json) => _$DAVImpl(
|
||||
uri: json['uri'] as String,
|
||||
user: json['user'] as String,
|
||||
password: json['password'] as String,
|
||||
fileName: json['fileName'] as String? ?? defaultDavFileName,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DAVImplToJson(_$DAVImpl instance) => <String, dynamic>{
|
||||
'uri': instance.uri,
|
||||
'user': instance.user,
|
||||
'password': instance.password,
|
||||
'fileName': instance.fileName,
|
||||
};
|
||||
|
||||
_$VersionInfoImpl _$$VersionInfoImplFromJson(Map<String, dynamic> json) =>
|
||||
_$VersionInfoImpl(
|
||||
clashName: json['clashName'] as String? ?? "",
|
||||
version: json['version'] as String? ?? "",
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$VersionInfoImplToJson(_$VersionInfoImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'clashName': instance.clashName,
|
||||
'version': instance.version,
|
||||
};
|
||||
|
||||
_$GroupImpl _$$GroupImplFromJson(Map<String, dynamic> json) => _$GroupImpl(
|
||||
type: $enumDecode(_$GroupTypeEnumMap, json['type']),
|
||||
all: (json['all'] as List<dynamic>?)
|
||||
?.map((e) => Proxy.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
now: json['now'] as String?,
|
||||
hidden: json['hidden'] as bool?,
|
||||
icon: json['icon'] as String? ?? "",
|
||||
name: json['name'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$GroupImplToJson(_$GroupImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'type': _$GroupTypeEnumMap[instance.type]!,
|
||||
'all': instance.all,
|
||||
'now': instance.now,
|
||||
'hidden': instance.hidden,
|
||||
'icon': instance.icon,
|
||||
'name': instance.name,
|
||||
};
|
||||
|
||||
const _$GroupTypeEnumMap = {
|
||||
GroupType.Selector: 'Selector',
|
||||
GroupType.URLTest: 'URLTest',
|
||||
GroupType.Fallback: 'Fallback',
|
||||
GroupType.LoadBalance: 'LoadBalance',
|
||||
GroupType.Relay: 'Relay',
|
||||
};
|
||||
|
||||
_$ProxyImpl _$$ProxyImplFromJson(Map<String, dynamic> json) => _$ProxyImpl(
|
||||
name: json['name'] as String,
|
||||
type: json['type'] as String,
|
||||
now: json['now'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ProxyImplToJson(_$ProxyImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
'type': instance.type,
|
||||
'now': instance.now,
|
||||
};
|
||||
|
||||
_$HotKeyActionImpl _$$HotKeyActionImplFromJson(Map<String, dynamic> json) =>
|
||||
_$HotKeyActionImpl(
|
||||
action: $enumDecode(_$HotActionEnumMap, json['action']),
|
||||
key: (json['key'] as num?)?.toInt(),
|
||||
modifiers: (json['modifiers'] as List<dynamic>?)
|
||||
?.map((e) => $enumDecode(_$KeyboardModifierEnumMap, e))
|
||||
.toSet() ??
|
||||
const {},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$HotKeyActionImplToJson(_$HotKeyActionImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'action': _$HotActionEnumMap[instance.action]!,
|
||||
'key': instance.key,
|
||||
'modifiers':
|
||||
instance.modifiers.map((e) => _$KeyboardModifierEnumMap[e]!).toList(),
|
||||
};
|
||||
|
||||
const _$HotActionEnumMap = {
|
||||
HotAction.start: 'start',
|
||||
HotAction.view: 'view',
|
||||
HotAction.mode: 'mode',
|
||||
HotAction.proxy: 'proxy',
|
||||
HotAction.tun: 'tun',
|
||||
};
|
||||
|
||||
const _$KeyboardModifierEnumMap = {
|
||||
KeyboardModifier.alt: 'alt',
|
||||
KeyboardModifier.capsLock: 'capsLock',
|
||||
KeyboardModifier.control: 'control',
|
||||
KeyboardModifier.fn: 'fn',
|
||||
KeyboardModifier.meta: 'meta',
|
||||
KeyboardModifier.shift: 'shift',
|
||||
};
|
||||
@@ -56,7 +56,12 @@ Config _$ConfigFromJson(Map<String, dynamic> json) => Config()
|
||||
..scaleProps =
|
||||
ScaleProps.fromJson(json['scaleProps'] as Map<String, dynamic>?)
|
||||
..showLabel = json['showLabel'] as bool? ?? false
|
||||
..overrideDns = json['overrideDns'] as bool? ?? false;
|
||||
..overrideDns = json['overrideDns'] as bool? ?? false
|
||||
..isDisclaimerAccepted = json['isDisclaimerAccepted'] as bool? ?? false
|
||||
..hotKeyActions = (json['hotKeyActions'] as List<dynamic>?)
|
||||
?.map((e) => HotKeyAction.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[];
|
||||
|
||||
Map<String, dynamic> _$ConfigToJson(Config instance) => <String, dynamic>{
|
||||
'profiles': instance.profiles,
|
||||
@@ -90,6 +95,8 @@ Map<String, dynamic> _$ConfigToJson(Config instance) => <String, dynamic>{
|
||||
'scaleProps': instance.scaleProps,
|
||||
'showLabel': instance.showLabel,
|
||||
'overrideDns': instance.overrideDns,
|
||||
'isDisclaimerAccepted': instance.isDisclaimerAccepted,
|
||||
'hotKeyActions': instance.hotKeyActions,
|
||||
};
|
||||
|
||||
const _$ThemeModeEnumMap = {
|
||||
|
||||
@@ -1,772 +0,0 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of '../connection.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
Metadata _$MetadataFromJson(Map<String, dynamic> json) {
|
||||
return _Metadata.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$Metadata {
|
||||
int get uid => throw _privateConstructorUsedError;
|
||||
String get network => throw _privateConstructorUsedError;
|
||||
String get sourceIP => throw _privateConstructorUsedError;
|
||||
String get sourcePort => throw _privateConstructorUsedError;
|
||||
String get destinationIP => throw _privateConstructorUsedError;
|
||||
String get destinationPort => throw _privateConstructorUsedError;
|
||||
String get host => throw _privateConstructorUsedError;
|
||||
String get process => throw _privateConstructorUsedError;
|
||||
String get remoteDestination => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$MetadataCopyWith<Metadata> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $MetadataCopyWith<$Res> {
|
||||
factory $MetadataCopyWith(Metadata value, $Res Function(Metadata) then) =
|
||||
_$MetadataCopyWithImpl<$Res, Metadata>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{int uid,
|
||||
String network,
|
||||
String sourceIP,
|
||||
String sourcePort,
|
||||
String destinationIP,
|
||||
String destinationPort,
|
||||
String host,
|
||||
String process,
|
||||
String remoteDestination});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$MetadataCopyWithImpl<$Res, $Val extends Metadata>
|
||||
implements $MetadataCopyWith<$Res> {
|
||||
_$MetadataCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? uid = null,
|
||||
Object? network = null,
|
||||
Object? sourceIP = null,
|
||||
Object? sourcePort = null,
|
||||
Object? destinationIP = null,
|
||||
Object? destinationPort = null,
|
||||
Object? host = null,
|
||||
Object? process = null,
|
||||
Object? remoteDestination = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
uid: null == uid
|
||||
? _value.uid
|
||||
: uid // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
network: null == network
|
||||
? _value.network
|
||||
: network // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
sourceIP: null == sourceIP
|
||||
? _value.sourceIP
|
||||
: sourceIP // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
sourcePort: null == sourcePort
|
||||
? _value.sourcePort
|
||||
: sourcePort // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
destinationIP: null == destinationIP
|
||||
? _value.destinationIP
|
||||
: destinationIP // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
destinationPort: null == destinationPort
|
||||
? _value.destinationPort
|
||||
: destinationPort // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
host: null == host
|
||||
? _value.host
|
||||
: host // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
process: null == process
|
||||
? _value.process
|
||||
: process // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
remoteDestination: null == remoteDestination
|
||||
? _value.remoteDestination
|
||||
: remoteDestination // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$MetadataImplCopyWith<$Res>
|
||||
implements $MetadataCopyWith<$Res> {
|
||||
factory _$$MetadataImplCopyWith(
|
||||
_$MetadataImpl value, $Res Function(_$MetadataImpl) then) =
|
||||
__$$MetadataImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{int uid,
|
||||
String network,
|
||||
String sourceIP,
|
||||
String sourcePort,
|
||||
String destinationIP,
|
||||
String destinationPort,
|
||||
String host,
|
||||
String process,
|
||||
String remoteDestination});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$MetadataImplCopyWithImpl<$Res>
|
||||
extends _$MetadataCopyWithImpl<$Res, _$MetadataImpl>
|
||||
implements _$$MetadataImplCopyWith<$Res> {
|
||||
__$$MetadataImplCopyWithImpl(
|
||||
_$MetadataImpl _value, $Res Function(_$MetadataImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? uid = null,
|
||||
Object? network = null,
|
||||
Object? sourceIP = null,
|
||||
Object? sourcePort = null,
|
||||
Object? destinationIP = null,
|
||||
Object? destinationPort = null,
|
||||
Object? host = null,
|
||||
Object? process = null,
|
||||
Object? remoteDestination = null,
|
||||
}) {
|
||||
return _then(_$MetadataImpl(
|
||||
uid: null == uid
|
||||
? _value.uid
|
||||
: uid // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
network: null == network
|
||||
? _value.network
|
||||
: network // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
sourceIP: null == sourceIP
|
||||
? _value.sourceIP
|
||||
: sourceIP // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
sourcePort: null == sourcePort
|
||||
? _value.sourcePort
|
||||
: sourcePort // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
destinationIP: null == destinationIP
|
||||
? _value.destinationIP
|
||||
: destinationIP // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
destinationPort: null == destinationPort
|
||||
? _value.destinationPort
|
||||
: destinationPort // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
host: null == host
|
||||
? _value.host
|
||||
: host // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
process: null == process
|
||||
? _value.process
|
||||
: process // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
remoteDestination: null == remoteDestination
|
||||
? _value.remoteDestination
|
||||
: remoteDestination // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$MetadataImpl implements _Metadata {
|
||||
const _$MetadataImpl(
|
||||
{required this.uid,
|
||||
required this.network,
|
||||
required this.sourceIP,
|
||||
required this.sourcePort,
|
||||
required this.destinationIP,
|
||||
required this.destinationPort,
|
||||
required this.host,
|
||||
required this.process,
|
||||
required this.remoteDestination});
|
||||
|
||||
factory _$MetadataImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$MetadataImplFromJson(json);
|
||||
|
||||
@override
|
||||
final int uid;
|
||||
@override
|
||||
final String network;
|
||||
@override
|
||||
final String sourceIP;
|
||||
@override
|
||||
final String sourcePort;
|
||||
@override
|
||||
final String destinationIP;
|
||||
@override
|
||||
final String destinationPort;
|
||||
@override
|
||||
final String host;
|
||||
@override
|
||||
final String process;
|
||||
@override
|
||||
final String remoteDestination;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Metadata(uid: $uid, network: $network, sourceIP: $sourceIP, sourcePort: $sourcePort, destinationIP: $destinationIP, destinationPort: $destinationPort, host: $host, process: $process, remoteDestination: $remoteDestination)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$MetadataImpl &&
|
||||
(identical(other.uid, uid) || other.uid == uid) &&
|
||||
(identical(other.network, network) || other.network == network) &&
|
||||
(identical(other.sourceIP, sourceIP) ||
|
||||
other.sourceIP == sourceIP) &&
|
||||
(identical(other.sourcePort, sourcePort) ||
|
||||
other.sourcePort == sourcePort) &&
|
||||
(identical(other.destinationIP, destinationIP) ||
|
||||
other.destinationIP == destinationIP) &&
|
||||
(identical(other.destinationPort, destinationPort) ||
|
||||
other.destinationPort == destinationPort) &&
|
||||
(identical(other.host, host) || other.host == host) &&
|
||||
(identical(other.process, process) || other.process == process) &&
|
||||
(identical(other.remoteDestination, remoteDestination) ||
|
||||
other.remoteDestination == remoteDestination));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
uid,
|
||||
network,
|
||||
sourceIP,
|
||||
sourcePort,
|
||||
destinationIP,
|
||||
destinationPort,
|
||||
host,
|
||||
process,
|
||||
remoteDestination);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$MetadataImplCopyWith<_$MetadataImpl> get copyWith =>
|
||||
__$$MetadataImplCopyWithImpl<_$MetadataImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$MetadataImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Metadata implements Metadata {
|
||||
const factory _Metadata(
|
||||
{required final int uid,
|
||||
required final String network,
|
||||
required final String sourceIP,
|
||||
required final String sourcePort,
|
||||
required final String destinationIP,
|
||||
required final String destinationPort,
|
||||
required final String host,
|
||||
required final String process,
|
||||
required final String remoteDestination}) = _$MetadataImpl;
|
||||
|
||||
factory _Metadata.fromJson(Map<String, dynamic> json) =
|
||||
_$MetadataImpl.fromJson;
|
||||
|
||||
@override
|
||||
int get uid;
|
||||
@override
|
||||
String get network;
|
||||
@override
|
||||
String get sourceIP;
|
||||
@override
|
||||
String get sourcePort;
|
||||
@override
|
||||
String get destinationIP;
|
||||
@override
|
||||
String get destinationPort;
|
||||
@override
|
||||
String get host;
|
||||
@override
|
||||
String get process;
|
||||
@override
|
||||
String get remoteDestination;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$MetadataImplCopyWith<_$MetadataImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
Connection _$ConnectionFromJson(Map<String, dynamic> json) {
|
||||
return _Connection.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$Connection {
|
||||
String get id => throw _privateConstructorUsedError;
|
||||
num? get upload => throw _privateConstructorUsedError;
|
||||
num? get download => throw _privateConstructorUsedError;
|
||||
DateTime get start => throw _privateConstructorUsedError;
|
||||
Metadata get metadata => throw _privateConstructorUsedError;
|
||||
List<String> get chains => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$ConnectionCopyWith<Connection> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ConnectionCopyWith<$Res> {
|
||||
factory $ConnectionCopyWith(
|
||||
Connection value, $Res Function(Connection) then) =
|
||||
_$ConnectionCopyWithImpl<$Res, Connection>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String id,
|
||||
num? upload,
|
||||
num? download,
|
||||
DateTime start,
|
||||
Metadata metadata,
|
||||
List<String> chains});
|
||||
|
||||
$MetadataCopyWith<$Res> get metadata;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ConnectionCopyWithImpl<$Res, $Val extends Connection>
|
||||
implements $ConnectionCopyWith<$Res> {
|
||||
_$ConnectionCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? id = null,
|
||||
Object? upload = freezed,
|
||||
Object? download = freezed,
|
||||
Object? start = null,
|
||||
Object? metadata = null,
|
||||
Object? chains = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
id: null == id
|
||||
? _value.id
|
||||
: id // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
upload: freezed == upload
|
||||
? _value.upload
|
||||
: upload // ignore: cast_nullable_to_non_nullable
|
||||
as num?,
|
||||
download: freezed == download
|
||||
? _value.download
|
||||
: download // ignore: cast_nullable_to_non_nullable
|
||||
as num?,
|
||||
start: null == start
|
||||
? _value.start
|
||||
: start // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
metadata: null == metadata
|
||||
? _value.metadata
|
||||
: metadata // ignore: cast_nullable_to_non_nullable
|
||||
as Metadata,
|
||||
chains: null == chains
|
||||
? _value.chains
|
||||
: chains // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$MetadataCopyWith<$Res> get metadata {
|
||||
return $MetadataCopyWith<$Res>(_value.metadata, (value) {
|
||||
return _then(_value.copyWith(metadata: value) as $Val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ConnectionImplCopyWith<$Res>
|
||||
implements $ConnectionCopyWith<$Res> {
|
||||
factory _$$ConnectionImplCopyWith(
|
||||
_$ConnectionImpl value, $Res Function(_$ConnectionImpl) then) =
|
||||
__$$ConnectionImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{String id,
|
||||
num? upload,
|
||||
num? download,
|
||||
DateTime start,
|
||||
Metadata metadata,
|
||||
List<String> chains});
|
||||
|
||||
@override
|
||||
$MetadataCopyWith<$Res> get metadata;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ConnectionImplCopyWithImpl<$Res>
|
||||
extends _$ConnectionCopyWithImpl<$Res, _$ConnectionImpl>
|
||||
implements _$$ConnectionImplCopyWith<$Res> {
|
||||
__$$ConnectionImplCopyWithImpl(
|
||||
_$ConnectionImpl _value, $Res Function(_$ConnectionImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? id = null,
|
||||
Object? upload = freezed,
|
||||
Object? download = freezed,
|
||||
Object? start = null,
|
||||
Object? metadata = null,
|
||||
Object? chains = null,
|
||||
}) {
|
||||
return _then(_$ConnectionImpl(
|
||||
id: null == id
|
||||
? _value.id
|
||||
: id // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
upload: freezed == upload
|
||||
? _value.upload
|
||||
: upload // ignore: cast_nullable_to_non_nullable
|
||||
as num?,
|
||||
download: freezed == download
|
||||
? _value.download
|
||||
: download // ignore: cast_nullable_to_non_nullable
|
||||
as num?,
|
||||
start: null == start
|
||||
? _value.start
|
||||
: start // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
metadata: null == metadata
|
||||
? _value.metadata
|
||||
: metadata // ignore: cast_nullable_to_non_nullable
|
||||
as Metadata,
|
||||
chains: null == chains
|
||||
? _value._chains
|
||||
: chains // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$ConnectionImpl implements _Connection {
|
||||
const _$ConnectionImpl(
|
||||
{required this.id,
|
||||
this.upload,
|
||||
this.download,
|
||||
required this.start,
|
||||
required this.metadata,
|
||||
required final List<String> chains})
|
||||
: _chains = chains;
|
||||
|
||||
factory _$ConnectionImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$ConnectionImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String id;
|
||||
@override
|
||||
final num? upload;
|
||||
@override
|
||||
final num? download;
|
||||
@override
|
||||
final DateTime start;
|
||||
@override
|
||||
final Metadata metadata;
|
||||
final List<String> _chains;
|
||||
@override
|
||||
List<String> get chains {
|
||||
if (_chains is EqualUnmodifiableListView) return _chains;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_chains);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Connection(id: $id, upload: $upload, download: $download, start: $start, metadata: $metadata, chains: $chains)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ConnectionImpl &&
|
||||
(identical(other.id, id) || other.id == id) &&
|
||||
(identical(other.upload, upload) || other.upload == upload) &&
|
||||
(identical(other.download, download) ||
|
||||
other.download == download) &&
|
||||
(identical(other.start, start) || other.start == start) &&
|
||||
(identical(other.metadata, metadata) ||
|
||||
other.metadata == metadata) &&
|
||||
const DeepCollectionEquality().equals(other._chains, _chains));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, id, upload, download, start,
|
||||
metadata, const DeepCollectionEquality().hash(_chains));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ConnectionImplCopyWith<_$ConnectionImpl> get copyWith =>
|
||||
__$$ConnectionImplCopyWithImpl<_$ConnectionImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$ConnectionImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Connection implements Connection {
|
||||
const factory _Connection(
|
||||
{required final String id,
|
||||
final num? upload,
|
||||
final num? download,
|
||||
required final DateTime start,
|
||||
required final Metadata metadata,
|
||||
required final List<String> chains}) = _$ConnectionImpl;
|
||||
|
||||
factory _Connection.fromJson(Map<String, dynamic> json) =
|
||||
_$ConnectionImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get id;
|
||||
@override
|
||||
num? get upload;
|
||||
@override
|
||||
num? get download;
|
||||
@override
|
||||
DateTime get start;
|
||||
@override
|
||||
Metadata get metadata;
|
||||
@override
|
||||
List<String> get chains;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$ConnectionImplCopyWith<_$ConnectionImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
ConnectionsAndKeywords _$ConnectionsAndKeywordsFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return _ConnectionsAndKeywords.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ConnectionsAndKeywords {
|
||||
List<Connection> get connections => throw _privateConstructorUsedError;
|
||||
List<String> get keywords => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$ConnectionsAndKeywordsCopyWith<ConnectionsAndKeywords> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ConnectionsAndKeywordsCopyWith<$Res> {
|
||||
factory $ConnectionsAndKeywordsCopyWith(ConnectionsAndKeywords value,
|
||||
$Res Function(ConnectionsAndKeywords) then) =
|
||||
_$ConnectionsAndKeywordsCopyWithImpl<$Res, ConnectionsAndKeywords>;
|
||||
@useResult
|
||||
$Res call({List<Connection> connections, List<String> keywords});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ConnectionsAndKeywordsCopyWithImpl<$Res,
|
||||
$Val extends ConnectionsAndKeywords>
|
||||
implements $ConnectionsAndKeywordsCopyWith<$Res> {
|
||||
_$ConnectionsAndKeywordsCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? connections = null,
|
||||
Object? keywords = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
connections: null == connections
|
||||
? _value.connections
|
||||
: connections // ignore: cast_nullable_to_non_nullable
|
||||
as List<Connection>,
|
||||
keywords: null == keywords
|
||||
? _value.keywords
|
||||
: keywords // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ConnectionsAndKeywordsImplCopyWith<$Res>
|
||||
implements $ConnectionsAndKeywordsCopyWith<$Res> {
|
||||
factory _$$ConnectionsAndKeywordsImplCopyWith(
|
||||
_$ConnectionsAndKeywordsImpl value,
|
||||
$Res Function(_$ConnectionsAndKeywordsImpl) then) =
|
||||
__$$ConnectionsAndKeywordsImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({List<Connection> connections, List<String> keywords});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ConnectionsAndKeywordsImplCopyWithImpl<$Res>
|
||||
extends _$ConnectionsAndKeywordsCopyWithImpl<$Res,
|
||||
_$ConnectionsAndKeywordsImpl>
|
||||
implements _$$ConnectionsAndKeywordsImplCopyWith<$Res> {
|
||||
__$$ConnectionsAndKeywordsImplCopyWithImpl(
|
||||
_$ConnectionsAndKeywordsImpl _value,
|
||||
$Res Function(_$ConnectionsAndKeywordsImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? connections = null,
|
||||
Object? keywords = null,
|
||||
}) {
|
||||
return _then(_$ConnectionsAndKeywordsImpl(
|
||||
connections: null == connections
|
||||
? _value._connections
|
||||
: connections // ignore: cast_nullable_to_non_nullable
|
||||
as List<Connection>,
|
||||
keywords: null == keywords
|
||||
? _value._keywords
|
||||
: keywords // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$ConnectionsAndKeywordsImpl implements _ConnectionsAndKeywords {
|
||||
const _$ConnectionsAndKeywordsImpl(
|
||||
{final List<Connection> connections = const [],
|
||||
final List<String> keywords = const []})
|
||||
: _connections = connections,
|
||||
_keywords = keywords;
|
||||
|
||||
factory _$ConnectionsAndKeywordsImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$ConnectionsAndKeywordsImplFromJson(json);
|
||||
|
||||
final List<Connection> _connections;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<Connection> get connections {
|
||||
if (_connections is EqualUnmodifiableListView) return _connections;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_connections);
|
||||
}
|
||||
|
||||
final List<String> _keywords;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<String> get keywords {
|
||||
if (_keywords is EqualUnmodifiableListView) return _keywords;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_keywords);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ConnectionsAndKeywords(connections: $connections, keywords: $keywords)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ConnectionsAndKeywordsImpl &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._connections, _connections) &&
|
||||
const DeepCollectionEquality().equals(other._keywords, _keywords));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(_connections),
|
||||
const DeepCollectionEquality().hash(_keywords));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ConnectionsAndKeywordsImplCopyWith<_$ConnectionsAndKeywordsImpl>
|
||||
get copyWith => __$$ConnectionsAndKeywordsImplCopyWithImpl<
|
||||
_$ConnectionsAndKeywordsImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$ConnectionsAndKeywordsImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _ConnectionsAndKeywords implements ConnectionsAndKeywords {
|
||||
const factory _ConnectionsAndKeywords(
|
||||
{final List<Connection> connections,
|
||||
final List<String> keywords}) = _$ConnectionsAndKeywordsImpl;
|
||||
|
||||
factory _ConnectionsAndKeywords.fromJson(Map<String, dynamic> json) =
|
||||
_$ConnectionsAndKeywordsImpl.fromJson;
|
||||
|
||||
@override
|
||||
List<Connection> get connections;
|
||||
@override
|
||||
List<String> get keywords;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$ConnectionsAndKeywordsImplCopyWith<_$ConnectionsAndKeywordsImpl>
|
||||
get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of '../connection.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$MetadataImpl _$$MetadataImplFromJson(Map<String, dynamic> json) =>
|
||||
_$MetadataImpl(
|
||||
uid: (json['uid'] as num).toInt(),
|
||||
network: json['network'] as String,
|
||||
sourceIP: json['sourceIP'] as String,
|
||||
sourcePort: json['sourcePort'] as String,
|
||||
destinationIP: json['destinationIP'] as String,
|
||||
destinationPort: json['destinationPort'] as String,
|
||||
host: json['host'] as String,
|
||||
process: json['process'] as String,
|
||||
remoteDestination: json['remoteDestination'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$MetadataImplToJson(_$MetadataImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'uid': instance.uid,
|
||||
'network': instance.network,
|
||||
'sourceIP': instance.sourceIP,
|
||||
'sourcePort': instance.sourcePort,
|
||||
'destinationIP': instance.destinationIP,
|
||||
'destinationPort': instance.destinationPort,
|
||||
'host': instance.host,
|
||||
'process': instance.process,
|
||||
'remoteDestination': instance.remoteDestination,
|
||||
};
|
||||
|
||||
_$ConnectionImpl _$$ConnectionImplFromJson(Map<String, dynamic> json) =>
|
||||
_$ConnectionImpl(
|
||||
id: json['id'] as String,
|
||||
upload: json['upload'] as num?,
|
||||
download: json['download'] as num?,
|
||||
start: DateTime.parse(json['start'] as String),
|
||||
metadata: Metadata.fromJson(json['metadata'] as Map<String, dynamic>),
|
||||
chains:
|
||||
(json['chains'] as List<dynamic>).map((e) => e as String).toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ConnectionImplToJson(_$ConnectionImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'upload': instance.upload,
|
||||
'download': instance.download,
|
||||
'start': instance.start.toIso8601String(),
|
||||
'metadata': instance.metadata,
|
||||
'chains': instance.chains,
|
||||
};
|
||||
|
||||
_$ConnectionsAndKeywordsImpl _$$ConnectionsAndKeywordsImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$ConnectionsAndKeywordsImpl(
|
||||
connections: (json['connections'] as List<dynamic>?)
|
||||
?.map((e) => Connection.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
keywords: (json['keywords'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList() ??
|
||||
const [],
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ConnectionsAndKeywordsImplToJson(
|
||||
_$ConnectionsAndKeywordsImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'connections': instance.connections,
|
||||
'keywords': instance.keywords,
|
||||
};
|
||||
@@ -1,202 +0,0 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of '../dav.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
DAV _$DAVFromJson(Map<String, dynamic> json) {
|
||||
return _DAV.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$DAV {
|
||||
String get uri => throw _privateConstructorUsedError;
|
||||
String get user => throw _privateConstructorUsedError;
|
||||
String get password => throw _privateConstructorUsedError;
|
||||
String get fileName => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$DAVCopyWith<DAV> get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $DAVCopyWith<$Res> {
|
||||
factory $DAVCopyWith(DAV value, $Res Function(DAV) then) =
|
||||
_$DAVCopyWithImpl<$Res, DAV>;
|
||||
@useResult
|
||||
$Res call({String uri, String user, String password, String fileName});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$DAVCopyWithImpl<$Res, $Val extends DAV> implements $DAVCopyWith<$Res> {
|
||||
_$DAVCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? uri = null,
|
||||
Object? user = null,
|
||||
Object? password = null,
|
||||
Object? fileName = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
uri: null == uri
|
||||
? _value.uri
|
||||
: uri // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
user: null == user
|
||||
? _value.user
|
||||
: user // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
password: null == password
|
||||
? _value.password
|
||||
: password // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
fileName: null == fileName
|
||||
? _value.fileName
|
||||
: fileName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$DAVImplCopyWith<$Res> implements $DAVCopyWith<$Res> {
|
||||
factory _$$DAVImplCopyWith(_$DAVImpl value, $Res Function(_$DAVImpl) then) =
|
||||
__$$DAVImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({String uri, String user, String password, String fileName});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$DAVImplCopyWithImpl<$Res> extends _$DAVCopyWithImpl<$Res, _$DAVImpl>
|
||||
implements _$$DAVImplCopyWith<$Res> {
|
||||
__$$DAVImplCopyWithImpl(_$DAVImpl _value, $Res Function(_$DAVImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? uri = null,
|
||||
Object? user = null,
|
||||
Object? password = null,
|
||||
Object? fileName = null,
|
||||
}) {
|
||||
return _then(_$DAVImpl(
|
||||
uri: null == uri
|
||||
? _value.uri
|
||||
: uri // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
user: null == user
|
||||
? _value.user
|
||||
: user // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
password: null == password
|
||||
? _value.password
|
||||
: password // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
fileName: null == fileName
|
||||
? _value.fileName
|
||||
: fileName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$DAVImpl implements _DAV {
|
||||
const _$DAVImpl(
|
||||
{required this.uri,
|
||||
required this.user,
|
||||
required this.password,
|
||||
this.fileName = defaultDavFileName});
|
||||
|
||||
factory _$DAVImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$DAVImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String uri;
|
||||
@override
|
||||
final String user;
|
||||
@override
|
||||
final String password;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String fileName;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DAV(uri: $uri, user: $user, password: $password, fileName: $fileName)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$DAVImpl &&
|
||||
(identical(other.uri, uri) || other.uri == uri) &&
|
||||
(identical(other.user, user) || other.user == user) &&
|
||||
(identical(other.password, password) ||
|
||||
other.password == password) &&
|
||||
(identical(other.fileName, fileName) ||
|
||||
other.fileName == fileName));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, uri, user, password, fileName);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$DAVImplCopyWith<_$DAVImpl> get copyWith =>
|
||||
__$$DAVImplCopyWithImpl<_$DAVImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$DAVImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _DAV implements DAV {
|
||||
const factory _DAV(
|
||||
{required final String uri,
|
||||
required final String user,
|
||||
required final String password,
|
||||
final String fileName}) = _$DAVImpl;
|
||||
|
||||
factory _DAV.fromJson(Map<String, dynamic> json) = _$DAVImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get uri;
|
||||
@override
|
||||
String get user;
|
||||
@override
|
||||
String get password;
|
||||
@override
|
||||
String get fileName;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$DAVImplCopyWith<_$DAVImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of '../dav.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$DAVImpl _$$DAVImplFromJson(Map<String, dynamic> json) => _$DAVImpl(
|
||||
uri: json['uri'] as String,
|
||||
user: json['user'] as String,
|
||||
password: json['password'] as String,
|
||||
fileName: json['fileName'] as String? ?? defaultDavFileName,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DAVImplToJson(_$DAVImpl instance) => <String, dynamic>{
|
||||
'uri': instance.uri,
|
||||
'user': instance.user,
|
||||
'password': instance.password,
|
||||
'fileName': instance.fileName,
|
||||
};
|
||||
@@ -1975,3 +1975,264 @@ abstract class _ExternalProvider implements ExternalProvider {
|
||||
_$$ExternalProviderImplCopyWith<_$ExternalProviderImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
TunProps _$TunPropsFromJson(Map<String, dynamic> json) {
|
||||
return _TunProps.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$TunProps {
|
||||
int get fd => throw _privateConstructorUsedError;
|
||||
String get gateway => throw _privateConstructorUsedError;
|
||||
String get gateway6 => throw _privateConstructorUsedError;
|
||||
String get portal => throw _privateConstructorUsedError;
|
||||
String get portal6 => throw _privateConstructorUsedError;
|
||||
String get dns => throw _privateConstructorUsedError;
|
||||
String get dns6 => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$TunPropsCopyWith<TunProps> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $TunPropsCopyWith<$Res> {
|
||||
factory $TunPropsCopyWith(TunProps value, $Res Function(TunProps) then) =
|
||||
_$TunPropsCopyWithImpl<$Res, TunProps>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{int fd,
|
||||
String gateway,
|
||||
String gateway6,
|
||||
String portal,
|
||||
String portal6,
|
||||
String dns,
|
||||
String dns6});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$TunPropsCopyWithImpl<$Res, $Val extends TunProps>
|
||||
implements $TunPropsCopyWith<$Res> {
|
||||
_$TunPropsCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? fd = null,
|
||||
Object? gateway = null,
|
||||
Object? gateway6 = null,
|
||||
Object? portal = null,
|
||||
Object? portal6 = null,
|
||||
Object? dns = null,
|
||||
Object? dns6 = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
fd: null == fd
|
||||
? _value.fd
|
||||
: fd // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
gateway: null == gateway
|
||||
? _value.gateway
|
||||
: gateway // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
gateway6: null == gateway6
|
||||
? _value.gateway6
|
||||
: gateway6 // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
portal: null == portal
|
||||
? _value.portal
|
||||
: portal // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
portal6: null == portal6
|
||||
? _value.portal6
|
||||
: portal6 // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
dns: null == dns
|
||||
? _value.dns
|
||||
: dns // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
dns6: null == dns6
|
||||
? _value.dns6
|
||||
: dns6 // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$TunPropsImplCopyWith<$Res>
|
||||
implements $TunPropsCopyWith<$Res> {
|
||||
factory _$$TunPropsImplCopyWith(
|
||||
_$TunPropsImpl value, $Res Function(_$TunPropsImpl) then) =
|
||||
__$$TunPropsImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{int fd,
|
||||
String gateway,
|
||||
String gateway6,
|
||||
String portal,
|
||||
String portal6,
|
||||
String dns,
|
||||
String dns6});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$TunPropsImplCopyWithImpl<$Res>
|
||||
extends _$TunPropsCopyWithImpl<$Res, _$TunPropsImpl>
|
||||
implements _$$TunPropsImplCopyWith<$Res> {
|
||||
__$$TunPropsImplCopyWithImpl(
|
||||
_$TunPropsImpl _value, $Res Function(_$TunPropsImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? fd = null,
|
||||
Object? gateway = null,
|
||||
Object? gateway6 = null,
|
||||
Object? portal = null,
|
||||
Object? portal6 = null,
|
||||
Object? dns = null,
|
||||
Object? dns6 = null,
|
||||
}) {
|
||||
return _then(_$TunPropsImpl(
|
||||
fd: null == fd
|
||||
? _value.fd
|
||||
: fd // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
gateway: null == gateway
|
||||
? _value.gateway
|
||||
: gateway // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
gateway6: null == gateway6
|
||||
? _value.gateway6
|
||||
: gateway6 // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
portal: null == portal
|
||||
? _value.portal
|
||||
: portal // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
portal6: null == portal6
|
||||
? _value.portal6
|
||||
: portal6 // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
dns: null == dns
|
||||
? _value.dns
|
||||
: dns // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
dns6: null == dns6
|
||||
? _value.dns6
|
||||
: dns6 // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$TunPropsImpl implements _TunProps {
|
||||
const _$TunPropsImpl(
|
||||
{required this.fd,
|
||||
required this.gateway,
|
||||
required this.gateway6,
|
||||
required this.portal,
|
||||
required this.portal6,
|
||||
required this.dns,
|
||||
required this.dns6});
|
||||
|
||||
factory _$TunPropsImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$TunPropsImplFromJson(json);
|
||||
|
||||
@override
|
||||
final int fd;
|
||||
@override
|
||||
final String gateway;
|
||||
@override
|
||||
final String gateway6;
|
||||
@override
|
||||
final String portal;
|
||||
@override
|
||||
final String portal6;
|
||||
@override
|
||||
final String dns;
|
||||
@override
|
||||
final String dns6;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TunProps(fd: $fd, gateway: $gateway, gateway6: $gateway6, portal: $portal, portal6: $portal6, dns: $dns, dns6: $dns6)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$TunPropsImpl &&
|
||||
(identical(other.fd, fd) || other.fd == fd) &&
|
||||
(identical(other.gateway, gateway) || other.gateway == gateway) &&
|
||||
(identical(other.gateway6, gateway6) ||
|
||||
other.gateway6 == gateway6) &&
|
||||
(identical(other.portal, portal) || other.portal == portal) &&
|
||||
(identical(other.portal6, portal6) || other.portal6 == portal6) &&
|
||||
(identical(other.dns, dns) || other.dns == dns) &&
|
||||
(identical(other.dns6, dns6) || other.dns6 == dns6));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, fd, gateway, gateway6, portal, portal6, dns, dns6);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$TunPropsImplCopyWith<_$TunPropsImpl> get copyWith =>
|
||||
__$$TunPropsImplCopyWithImpl<_$TunPropsImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$TunPropsImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _TunProps implements TunProps {
|
||||
const factory _TunProps(
|
||||
{required final int fd,
|
||||
required final String gateway,
|
||||
required final String gateway6,
|
||||
required final String portal,
|
||||
required final String portal6,
|
||||
required final String dns,
|
||||
required final String dns6}) = _$TunPropsImpl;
|
||||
|
||||
factory _TunProps.fromJson(Map<String, dynamic> json) =
|
||||
_$TunPropsImpl.fromJson;
|
||||
|
||||
@override
|
||||
int get fd;
|
||||
@override
|
||||
String get gateway;
|
||||
@override
|
||||
String get gateway6;
|
||||
@override
|
||||
String get portal;
|
||||
@override
|
||||
String get portal6;
|
||||
@override
|
||||
String get dns;
|
||||
@override
|
||||
String get dns6;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$TunPropsImplCopyWith<_$TunPropsImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
@@ -176,3 +176,25 @@ Map<String, dynamic> _$$ExternalProviderImplToJson(
|
||||
'vehicle-type': instance.vehicleType,
|
||||
'update-at': instance.updateAt.toIso8601String(),
|
||||
};
|
||||
|
||||
_$TunPropsImpl _$$TunPropsImplFromJson(Map<String, dynamic> json) =>
|
||||
_$TunPropsImpl(
|
||||
fd: (json['fd'] as num).toInt(),
|
||||
gateway: json['gateway'] as String,
|
||||
gateway6: json['gateway6'] as String,
|
||||
portal: json['portal'] as String,
|
||||
portal6: json['portal6'] as String,
|
||||
dns: json['dns'] as String,
|
||||
dns6: json['dns6'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$TunPropsImplToJson(_$TunPropsImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'fd': instance.fd,
|
||||
'gateway': instance.gateway,
|
||||
'gateway6': instance.gateway6,
|
||||
'portal': instance.portal,
|
||||
'portal6': instance.portal6,
|
||||
'dns': instance.dns,
|
||||
'dns6': instance.dns6,
|
||||
};
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of '../file.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$FileInfo {
|
||||
int get size => throw _privateConstructorUsedError;
|
||||
DateTime get lastModified => throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$FileInfoCopyWith<FileInfo> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $FileInfoCopyWith<$Res> {
|
||||
factory $FileInfoCopyWith(FileInfo value, $Res Function(FileInfo) then) =
|
||||
_$FileInfoCopyWithImpl<$Res, FileInfo>;
|
||||
@useResult
|
||||
$Res call({int size, DateTime lastModified});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$FileInfoCopyWithImpl<$Res, $Val extends FileInfo>
|
||||
implements $FileInfoCopyWith<$Res> {
|
||||
_$FileInfoCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? size = null,
|
||||
Object? lastModified = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
size: null == size
|
||||
? _value.size
|
||||
: size // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
lastModified: null == lastModified
|
||||
? _value.lastModified
|
||||
: lastModified // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$FileInfoImplCopyWith<$Res>
|
||||
implements $FileInfoCopyWith<$Res> {
|
||||
factory _$$FileInfoImplCopyWith(
|
||||
_$FileInfoImpl value, $Res Function(_$FileInfoImpl) then) =
|
||||
__$$FileInfoImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({int size, DateTime lastModified});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$FileInfoImplCopyWithImpl<$Res>
|
||||
extends _$FileInfoCopyWithImpl<$Res, _$FileInfoImpl>
|
||||
implements _$$FileInfoImplCopyWith<$Res> {
|
||||
__$$FileInfoImplCopyWithImpl(
|
||||
_$FileInfoImpl _value, $Res Function(_$FileInfoImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? size = null,
|
||||
Object? lastModified = null,
|
||||
}) {
|
||||
return _then(_$FileInfoImpl(
|
||||
size: null == size
|
||||
? _value.size
|
||||
: size // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
lastModified: null == lastModified
|
||||
? _value.lastModified
|
||||
: lastModified // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$FileInfoImpl implements _FileInfo {
|
||||
const _$FileInfoImpl({required this.size, required this.lastModified});
|
||||
|
||||
@override
|
||||
final int size;
|
||||
@override
|
||||
final DateTime lastModified;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'FileInfo(size: $size, lastModified: $lastModified)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$FileInfoImpl &&
|
||||
(identical(other.size, size) || other.size == size) &&
|
||||
(identical(other.lastModified, lastModified) ||
|
||||
other.lastModified == lastModified));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, size, lastModified);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$FileInfoImplCopyWith<_$FileInfoImpl> get copyWith =>
|
||||
__$$FileInfoImplCopyWithImpl<_$FileInfoImpl>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _FileInfo implements FileInfo {
|
||||
const factory _FileInfo(
|
||||
{required final int size,
|
||||
required final DateTime lastModified}) = _$FileInfoImpl;
|
||||
|
||||
@override
|
||||
int get size;
|
||||
@override
|
||||
DateTime get lastModified;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$FileInfoImplCopyWith<_$FileInfoImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of '../log.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
LogsAndKeywords _$LogsAndKeywordsFromJson(Map<String, dynamic> json) {
|
||||
return _LogsAndKeywords.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$LogsAndKeywords {
|
||||
List<Log> get logs => throw _privateConstructorUsedError;
|
||||
List<String> get keywords => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$LogsAndKeywordsCopyWith<LogsAndKeywords> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $LogsAndKeywordsCopyWith<$Res> {
|
||||
factory $LogsAndKeywordsCopyWith(
|
||||
LogsAndKeywords value, $Res Function(LogsAndKeywords) then) =
|
||||
_$LogsAndKeywordsCopyWithImpl<$Res, LogsAndKeywords>;
|
||||
@useResult
|
||||
$Res call({List<Log> logs, List<String> keywords});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$LogsAndKeywordsCopyWithImpl<$Res, $Val extends LogsAndKeywords>
|
||||
implements $LogsAndKeywordsCopyWith<$Res> {
|
||||
_$LogsAndKeywordsCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? logs = null,
|
||||
Object? keywords = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
logs: null == logs
|
||||
? _value.logs
|
||||
: logs // ignore: cast_nullable_to_non_nullable
|
||||
as List<Log>,
|
||||
keywords: null == keywords
|
||||
? _value.keywords
|
||||
: keywords // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$LogsAndKeywordsImplCopyWith<$Res>
|
||||
implements $LogsAndKeywordsCopyWith<$Res> {
|
||||
factory _$$LogsAndKeywordsImplCopyWith(_$LogsAndKeywordsImpl value,
|
||||
$Res Function(_$LogsAndKeywordsImpl) then) =
|
||||
__$$LogsAndKeywordsImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({List<Log> logs, List<String> keywords});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$LogsAndKeywordsImplCopyWithImpl<$Res>
|
||||
extends _$LogsAndKeywordsCopyWithImpl<$Res, _$LogsAndKeywordsImpl>
|
||||
implements _$$LogsAndKeywordsImplCopyWith<$Res> {
|
||||
__$$LogsAndKeywordsImplCopyWithImpl(
|
||||
_$LogsAndKeywordsImpl _value, $Res Function(_$LogsAndKeywordsImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? logs = null,
|
||||
Object? keywords = null,
|
||||
}) {
|
||||
return _then(_$LogsAndKeywordsImpl(
|
||||
logs: null == logs
|
||||
? _value._logs
|
||||
: logs // ignore: cast_nullable_to_non_nullable
|
||||
as List<Log>,
|
||||
keywords: null == keywords
|
||||
? _value._keywords
|
||||
: keywords // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$LogsAndKeywordsImpl implements _LogsAndKeywords {
|
||||
const _$LogsAndKeywordsImpl(
|
||||
{final List<Log> logs = const [], final List<String> keywords = const []})
|
||||
: _logs = logs,
|
||||
_keywords = keywords;
|
||||
|
||||
factory _$LogsAndKeywordsImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$LogsAndKeywordsImplFromJson(json);
|
||||
|
||||
final List<Log> _logs;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<Log> get logs {
|
||||
if (_logs is EqualUnmodifiableListView) return _logs;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_logs);
|
||||
}
|
||||
|
||||
final List<String> _keywords;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<String> get keywords {
|
||||
if (_keywords is EqualUnmodifiableListView) return _keywords;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_keywords);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LogsAndKeywords(logs: $logs, keywords: $keywords)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$LogsAndKeywordsImpl &&
|
||||
const DeepCollectionEquality().equals(other._logs, _logs) &&
|
||||
const DeepCollectionEquality().equals(other._keywords, _keywords));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(_logs),
|
||||
const DeepCollectionEquality().hash(_keywords));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$LogsAndKeywordsImplCopyWith<_$LogsAndKeywordsImpl> get copyWith =>
|
||||
__$$LogsAndKeywordsImplCopyWithImpl<_$LogsAndKeywordsImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$LogsAndKeywordsImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _LogsAndKeywords implements LogsAndKeywords {
|
||||
const factory _LogsAndKeywords(
|
||||
{final List<Log> logs,
|
||||
final List<String> keywords}) = _$LogsAndKeywordsImpl;
|
||||
|
||||
factory _LogsAndKeywords.fromJson(Map<String, dynamic> json) =
|
||||
_$LogsAndKeywordsImpl.fromJson;
|
||||
|
||||
@override
|
||||
List<Log> get logs;
|
||||
@override
|
||||
List<String> get keywords;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$LogsAndKeywordsImplCopyWith<_$LogsAndKeywordsImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of '../log.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Log _$LogFromJson(Map<String, dynamic> json) => Log(
|
||||
logLevel: $enumDecode(_$LogLevelEnumMap, json['LogLevel']),
|
||||
payload: json['Payload'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LogToJson(Log instance) => <String, dynamic>{
|
||||
'LogLevel': _$LogLevelEnumMap[instance.logLevel]!,
|
||||
'Payload': instance.payload,
|
||||
};
|
||||
|
||||
const _$LogLevelEnumMap = {
|
||||
LogLevel.debug: 'debug',
|
||||
LogLevel.info: 'info',
|
||||
LogLevel.warning: 'warning',
|
||||
LogLevel.error: 'error',
|
||||
LogLevel.silent: 'silent',
|
||||
};
|
||||
|
||||
_$LogsAndKeywordsImpl _$$LogsAndKeywordsImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$LogsAndKeywordsImpl(
|
||||
logs: (json['logs'] as List<dynamic>?)
|
||||
?.map((e) => Log.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
keywords: (json['keywords'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList() ??
|
||||
const [],
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$LogsAndKeywordsImplToJson(
|
||||
_$LogsAndKeywordsImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'logs': instance.logs,
|
||||
'keywords': instance.keywords,
|
||||
};
|
||||
@@ -1,271 +0,0 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of '../navigation.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$NavigationItem {
|
||||
Icon get icon => throw _privateConstructorUsedError;
|
||||
String get label => throw _privateConstructorUsedError;
|
||||
String? get description => throw _privateConstructorUsedError;
|
||||
Widget get fragment => throw _privateConstructorUsedError;
|
||||
bool get keep => throw _privateConstructorUsedError;
|
||||
String? get path => throw _privateConstructorUsedError;
|
||||
List<NavigationItemMode> get modes => throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$NavigationItemCopyWith<NavigationItem> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $NavigationItemCopyWith<$Res> {
|
||||
factory $NavigationItemCopyWith(
|
||||
NavigationItem value, $Res Function(NavigationItem) then) =
|
||||
_$NavigationItemCopyWithImpl<$Res, NavigationItem>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{Icon icon,
|
||||
String label,
|
||||
String? description,
|
||||
Widget fragment,
|
||||
bool keep,
|
||||
String? path,
|
||||
List<NavigationItemMode> modes});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$NavigationItemCopyWithImpl<$Res, $Val extends NavigationItem>
|
||||
implements $NavigationItemCopyWith<$Res> {
|
||||
_$NavigationItemCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? icon = null,
|
||||
Object? label = null,
|
||||
Object? description = freezed,
|
||||
Object? fragment = null,
|
||||
Object? keep = null,
|
||||
Object? path = freezed,
|
||||
Object? modes = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
icon: null == icon
|
||||
? _value.icon
|
||||
: icon // ignore: cast_nullable_to_non_nullable
|
||||
as Icon,
|
||||
label: null == label
|
||||
? _value.label
|
||||
: label // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
description: freezed == description
|
||||
? _value.description
|
||||
: description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
fragment: null == fragment
|
||||
? _value.fragment
|
||||
: fragment // ignore: cast_nullable_to_non_nullable
|
||||
as Widget,
|
||||
keep: null == keep
|
||||
? _value.keep
|
||||
: keep // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
path: freezed == path
|
||||
? _value.path
|
||||
: path // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
modes: null == modes
|
||||
? _value.modes
|
||||
: modes // ignore: cast_nullable_to_non_nullable
|
||||
as List<NavigationItemMode>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$NavigationItemImplCopyWith<$Res>
|
||||
implements $NavigationItemCopyWith<$Res> {
|
||||
factory _$$NavigationItemImplCopyWith(_$NavigationItemImpl value,
|
||||
$Res Function(_$NavigationItemImpl) then) =
|
||||
__$$NavigationItemImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{Icon icon,
|
||||
String label,
|
||||
String? description,
|
||||
Widget fragment,
|
||||
bool keep,
|
||||
String? path,
|
||||
List<NavigationItemMode> modes});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$NavigationItemImplCopyWithImpl<$Res>
|
||||
extends _$NavigationItemCopyWithImpl<$Res, _$NavigationItemImpl>
|
||||
implements _$$NavigationItemImplCopyWith<$Res> {
|
||||
__$$NavigationItemImplCopyWithImpl(
|
||||
_$NavigationItemImpl _value, $Res Function(_$NavigationItemImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? icon = null,
|
||||
Object? label = null,
|
||||
Object? description = freezed,
|
||||
Object? fragment = null,
|
||||
Object? keep = null,
|
||||
Object? path = freezed,
|
||||
Object? modes = null,
|
||||
}) {
|
||||
return _then(_$NavigationItemImpl(
|
||||
icon: null == icon
|
||||
? _value.icon
|
||||
: icon // ignore: cast_nullable_to_non_nullable
|
||||
as Icon,
|
||||
label: null == label
|
||||
? _value.label
|
||||
: label // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
description: freezed == description
|
||||
? _value.description
|
||||
: description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
fragment: null == fragment
|
||||
? _value.fragment
|
||||
: fragment // ignore: cast_nullable_to_non_nullable
|
||||
as Widget,
|
||||
keep: null == keep
|
||||
? _value.keep
|
||||
: keep // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
path: freezed == path
|
||||
? _value.path
|
||||
: path // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
modes: null == modes
|
||||
? _value._modes
|
||||
: modes // ignore: cast_nullable_to_non_nullable
|
||||
as List<NavigationItemMode>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$NavigationItemImpl implements _NavigationItem {
|
||||
const _$NavigationItemImpl(
|
||||
{required this.icon,
|
||||
required this.label,
|
||||
this.description,
|
||||
required this.fragment,
|
||||
this.keep = true,
|
||||
this.path,
|
||||
final List<NavigationItemMode> modes = const [
|
||||
NavigationItemMode.mobile,
|
||||
NavigationItemMode.desktop
|
||||
]})
|
||||
: _modes = modes;
|
||||
|
||||
@override
|
||||
final Icon icon;
|
||||
@override
|
||||
final String label;
|
||||
@override
|
||||
final String? description;
|
||||
@override
|
||||
final Widget fragment;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool keep;
|
||||
@override
|
||||
final String? path;
|
||||
final List<NavigationItemMode> _modes;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<NavigationItemMode> get modes {
|
||||
if (_modes is EqualUnmodifiableListView) return _modes;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_modes);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'NavigationItem(icon: $icon, label: $label, description: $description, fragment: $fragment, keep: $keep, path: $path, modes: $modes)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$NavigationItemImpl &&
|
||||
(identical(other.icon, icon) || other.icon == icon) &&
|
||||
(identical(other.label, label) || other.label == label) &&
|
||||
(identical(other.description, description) ||
|
||||
other.description == description) &&
|
||||
(identical(other.fragment, fragment) ||
|
||||
other.fragment == fragment) &&
|
||||
(identical(other.keep, keep) || other.keep == keep) &&
|
||||
(identical(other.path, path) || other.path == path) &&
|
||||
const DeepCollectionEquality().equals(other._modes, _modes));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, icon, label, description,
|
||||
fragment, keep, path, const DeepCollectionEquality().hash(_modes));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$NavigationItemImplCopyWith<_$NavigationItemImpl> get copyWith =>
|
||||
__$$NavigationItemImplCopyWithImpl<_$NavigationItemImpl>(
|
||||
this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _NavigationItem implements NavigationItem {
|
||||
const factory _NavigationItem(
|
||||
{required final Icon icon,
|
||||
required final String label,
|
||||
final String? description,
|
||||
required final Widget fragment,
|
||||
final bool keep,
|
||||
final String? path,
|
||||
final List<NavigationItemMode> modes}) = _$NavigationItemImpl;
|
||||
|
||||
@override
|
||||
Icon get icon;
|
||||
@override
|
||||
String get label;
|
||||
@override
|
||||
String? get description;
|
||||
@override
|
||||
Widget get fragment;
|
||||
@override
|
||||
bool get keep;
|
||||
@override
|
||||
String? get path;
|
||||
@override
|
||||
List<NavigationItemMode> get modes;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$NavigationItemImplCopyWith<_$NavigationItemImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of '../package.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
Package _$PackageFromJson(Map<String, dynamic> json) {
|
||||
return _Package.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$Package {
|
||||
String get packageName => throw _privateConstructorUsedError;
|
||||
String get label => throw _privateConstructorUsedError;
|
||||
bool get isSystem => throw _privateConstructorUsedError;
|
||||
int get firstInstallTime => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$PackageCopyWith<Package> get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $PackageCopyWith<$Res> {
|
||||
factory $PackageCopyWith(Package value, $Res Function(Package) then) =
|
||||
_$PackageCopyWithImpl<$Res, Package>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String packageName, String label, bool isSystem, int firstInstallTime});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$PackageCopyWithImpl<$Res, $Val extends Package>
|
||||
implements $PackageCopyWith<$Res> {
|
||||
_$PackageCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? packageName = null,
|
||||
Object? label = null,
|
||||
Object? isSystem = null,
|
||||
Object? firstInstallTime = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
packageName: null == packageName
|
||||
? _value.packageName
|
||||
: packageName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
label: null == label
|
||||
? _value.label
|
||||
: label // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
isSystem: null == isSystem
|
||||
? _value.isSystem
|
||||
: isSystem // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
firstInstallTime: null == firstInstallTime
|
||||
? _value.firstInstallTime
|
||||
: firstInstallTime // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$PackageImplCopyWith<$Res> implements $PackageCopyWith<$Res> {
|
||||
factory _$$PackageImplCopyWith(
|
||||
_$PackageImpl value, $Res Function(_$PackageImpl) then) =
|
||||
__$$PackageImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{String packageName, String label, bool isSystem, int firstInstallTime});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$PackageImplCopyWithImpl<$Res>
|
||||
extends _$PackageCopyWithImpl<$Res, _$PackageImpl>
|
||||
implements _$$PackageImplCopyWith<$Res> {
|
||||
__$$PackageImplCopyWithImpl(
|
||||
_$PackageImpl _value, $Res Function(_$PackageImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? packageName = null,
|
||||
Object? label = null,
|
||||
Object? isSystem = null,
|
||||
Object? firstInstallTime = null,
|
||||
}) {
|
||||
return _then(_$PackageImpl(
|
||||
packageName: null == packageName
|
||||
? _value.packageName
|
||||
: packageName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
label: null == label
|
||||
? _value.label
|
||||
: label // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
isSystem: null == isSystem
|
||||
? _value.isSystem
|
||||
: isSystem // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
firstInstallTime: null == firstInstallTime
|
||||
? _value.firstInstallTime
|
||||
: firstInstallTime // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$PackageImpl implements _Package {
|
||||
const _$PackageImpl(
|
||||
{required this.packageName,
|
||||
required this.label,
|
||||
required this.isSystem,
|
||||
required this.firstInstallTime});
|
||||
|
||||
factory _$PackageImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$PackageImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String packageName;
|
||||
@override
|
||||
final String label;
|
||||
@override
|
||||
final bool isSystem;
|
||||
@override
|
||||
final int firstInstallTime;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Package(packageName: $packageName, label: $label, isSystem: $isSystem, firstInstallTime: $firstInstallTime)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$PackageImpl &&
|
||||
(identical(other.packageName, packageName) ||
|
||||
other.packageName == packageName) &&
|
||||
(identical(other.label, label) || other.label == label) &&
|
||||
(identical(other.isSystem, isSystem) ||
|
||||
other.isSystem == isSystem) &&
|
||||
(identical(other.firstInstallTime, firstInstallTime) ||
|
||||
other.firstInstallTime == firstInstallTime));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, packageName, label, isSystem, firstInstallTime);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$PackageImplCopyWith<_$PackageImpl> get copyWith =>
|
||||
__$$PackageImplCopyWithImpl<_$PackageImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$PackageImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Package implements Package {
|
||||
const factory _Package(
|
||||
{required final String packageName,
|
||||
required final String label,
|
||||
required final bool isSystem,
|
||||
required final int firstInstallTime}) = _$PackageImpl;
|
||||
|
||||
factory _Package.fromJson(Map<String, dynamic> json) = _$PackageImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get packageName;
|
||||
@override
|
||||
String get label;
|
||||
@override
|
||||
bool get isSystem;
|
||||
@override
|
||||
int get firstInstallTime;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$PackageImplCopyWith<_$PackageImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of '../package.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$PackageImpl _$$PackageImplFromJson(Map<String, dynamic> json) =>
|
||||
_$PackageImpl(
|
||||
packageName: json['packageName'] as String,
|
||||
label: json['label'] as String,
|
||||
isSystem: json['isSystem'] as bool,
|
||||
firstInstallTime: (json['firstInstallTime'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$PackageImplToJson(_$PackageImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'packageName': instance.packageName,
|
||||
'label': instance.label,
|
||||
'isSystem': instance.isSystem,
|
||||
'firstInstallTime': instance.firstInstallTime,
|
||||
};
|
||||
@@ -1,428 +0,0 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of '../proxy.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
Group _$GroupFromJson(Map<String, dynamic> json) {
|
||||
return _Group.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$Group {
|
||||
GroupType get type => throw _privateConstructorUsedError;
|
||||
List<Proxy> get all => throw _privateConstructorUsedError;
|
||||
String? get now => throw _privateConstructorUsedError;
|
||||
bool? get hidden => throw _privateConstructorUsedError;
|
||||
String get icon => throw _privateConstructorUsedError;
|
||||
String get name => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$GroupCopyWith<Group> get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $GroupCopyWith<$Res> {
|
||||
factory $GroupCopyWith(Group value, $Res Function(Group) then) =
|
||||
_$GroupCopyWithImpl<$Res, Group>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{GroupType type,
|
||||
List<Proxy> all,
|
||||
String? now,
|
||||
bool? hidden,
|
||||
String icon,
|
||||
String name});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$GroupCopyWithImpl<$Res, $Val extends Group>
|
||||
implements $GroupCopyWith<$Res> {
|
||||
_$GroupCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? type = null,
|
||||
Object? all = null,
|
||||
Object? now = freezed,
|
||||
Object? hidden = freezed,
|
||||
Object? icon = null,
|
||||
Object? name = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
type: null == type
|
||||
? _value.type
|
||||
: type // ignore: cast_nullable_to_non_nullable
|
||||
as GroupType,
|
||||
all: null == all
|
||||
? _value.all
|
||||
: all // ignore: cast_nullable_to_non_nullable
|
||||
as List<Proxy>,
|
||||
now: freezed == now
|
||||
? _value.now
|
||||
: now // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
hidden: freezed == hidden
|
||||
? _value.hidden
|
||||
: hidden // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
icon: null == icon
|
||||
? _value.icon
|
||||
: icon // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
name: null == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$GroupImplCopyWith<$Res> implements $GroupCopyWith<$Res> {
|
||||
factory _$$GroupImplCopyWith(
|
||||
_$GroupImpl value, $Res Function(_$GroupImpl) then) =
|
||||
__$$GroupImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{GroupType type,
|
||||
List<Proxy> all,
|
||||
String? now,
|
||||
bool? hidden,
|
||||
String icon,
|
||||
String name});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$GroupImplCopyWithImpl<$Res>
|
||||
extends _$GroupCopyWithImpl<$Res, _$GroupImpl>
|
||||
implements _$$GroupImplCopyWith<$Res> {
|
||||
__$$GroupImplCopyWithImpl(
|
||||
_$GroupImpl _value, $Res Function(_$GroupImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? type = null,
|
||||
Object? all = null,
|
||||
Object? now = freezed,
|
||||
Object? hidden = freezed,
|
||||
Object? icon = null,
|
||||
Object? name = null,
|
||||
}) {
|
||||
return _then(_$GroupImpl(
|
||||
type: null == type
|
||||
? _value.type
|
||||
: type // ignore: cast_nullable_to_non_nullable
|
||||
as GroupType,
|
||||
all: null == all
|
||||
? _value._all
|
||||
: all // ignore: cast_nullable_to_non_nullable
|
||||
as List<Proxy>,
|
||||
now: freezed == now
|
||||
? _value.now
|
||||
: now // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
hidden: freezed == hidden
|
||||
? _value.hidden
|
||||
: hidden // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
icon: null == icon
|
||||
? _value.icon
|
||||
: icon // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
name: null == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$GroupImpl implements _Group {
|
||||
const _$GroupImpl(
|
||||
{required this.type,
|
||||
final List<Proxy> all = const [],
|
||||
this.now,
|
||||
this.hidden,
|
||||
this.icon = "",
|
||||
required this.name})
|
||||
: _all = all;
|
||||
|
||||
factory _$GroupImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$GroupImplFromJson(json);
|
||||
|
||||
@override
|
||||
final GroupType type;
|
||||
final List<Proxy> _all;
|
||||
@override
|
||||
@JsonKey()
|
||||
List<Proxy> get all {
|
||||
if (_all is EqualUnmodifiableListView) return _all;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_all);
|
||||
}
|
||||
|
||||
@override
|
||||
final String? now;
|
||||
@override
|
||||
final bool? hidden;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String icon;
|
||||
@override
|
||||
final String name;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Group(type: $type, all: $all, now: $now, hidden: $hidden, icon: $icon, name: $name)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$GroupImpl &&
|
||||
(identical(other.type, type) || other.type == type) &&
|
||||
const DeepCollectionEquality().equals(other._all, _all) &&
|
||||
(identical(other.now, now) || other.now == now) &&
|
||||
(identical(other.hidden, hidden) || other.hidden == hidden) &&
|
||||
(identical(other.icon, icon) || other.icon == icon) &&
|
||||
(identical(other.name, name) || other.name == name));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, type,
|
||||
const DeepCollectionEquality().hash(_all), now, hidden, icon, name);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$GroupImplCopyWith<_$GroupImpl> get copyWith =>
|
||||
__$$GroupImplCopyWithImpl<_$GroupImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$GroupImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Group implements Group {
|
||||
const factory _Group(
|
||||
{required final GroupType type,
|
||||
final List<Proxy> all,
|
||||
final String? now,
|
||||
final bool? hidden,
|
||||
final String icon,
|
||||
required final String name}) = _$GroupImpl;
|
||||
|
||||
factory _Group.fromJson(Map<String, dynamic> json) = _$GroupImpl.fromJson;
|
||||
|
||||
@override
|
||||
GroupType get type;
|
||||
@override
|
||||
List<Proxy> get all;
|
||||
@override
|
||||
String? get now;
|
||||
@override
|
||||
bool? get hidden;
|
||||
@override
|
||||
String get icon;
|
||||
@override
|
||||
String get name;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$GroupImplCopyWith<_$GroupImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
Proxy _$ProxyFromJson(Map<String, dynamic> json) {
|
||||
return _Proxy.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$Proxy {
|
||||
String get name => throw _privateConstructorUsedError;
|
||||
String get type => throw _privateConstructorUsedError;
|
||||
String? get now => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$ProxyCopyWith<Proxy> get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ProxyCopyWith<$Res> {
|
||||
factory $ProxyCopyWith(Proxy value, $Res Function(Proxy) then) =
|
||||
_$ProxyCopyWithImpl<$Res, Proxy>;
|
||||
@useResult
|
||||
$Res call({String name, String type, String? now});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ProxyCopyWithImpl<$Res, $Val extends Proxy>
|
||||
implements $ProxyCopyWith<$Res> {
|
||||
_$ProxyCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? name = null,
|
||||
Object? type = null,
|
||||
Object? now = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
name: null == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
type: null == type
|
||||
? _value.type
|
||||
: type // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
now: freezed == now
|
||||
? _value.now
|
||||
: now // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ProxyImplCopyWith<$Res> implements $ProxyCopyWith<$Res> {
|
||||
factory _$$ProxyImplCopyWith(
|
||||
_$ProxyImpl value, $Res Function(_$ProxyImpl) then) =
|
||||
__$$ProxyImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({String name, String type, String? now});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ProxyImplCopyWithImpl<$Res>
|
||||
extends _$ProxyCopyWithImpl<$Res, _$ProxyImpl>
|
||||
implements _$$ProxyImplCopyWith<$Res> {
|
||||
__$$ProxyImplCopyWithImpl(
|
||||
_$ProxyImpl _value, $Res Function(_$ProxyImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? name = null,
|
||||
Object? type = null,
|
||||
Object? now = freezed,
|
||||
}) {
|
||||
return _then(_$ProxyImpl(
|
||||
name: null == name
|
||||
? _value.name
|
||||
: name // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
type: null == type
|
||||
? _value.type
|
||||
: type // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
now: freezed == now
|
||||
? _value.now
|
||||
: now // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$ProxyImpl implements _Proxy {
|
||||
const _$ProxyImpl({required this.name, required this.type, this.now});
|
||||
|
||||
factory _$ProxyImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$ProxyImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String name;
|
||||
@override
|
||||
final String type;
|
||||
@override
|
||||
final String? now;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Proxy(name: $name, type: $type, now: $now)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ProxyImpl &&
|
||||
(identical(other.name, name) || other.name == name) &&
|
||||
(identical(other.type, type) || other.type == type) &&
|
||||
(identical(other.now, now) || other.now == now));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, name, type, now);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ProxyImplCopyWith<_$ProxyImpl> get copyWith =>
|
||||
__$$ProxyImplCopyWithImpl<_$ProxyImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$ProxyImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Proxy implements Proxy {
|
||||
const factory _Proxy(
|
||||
{required final String name,
|
||||
required final String type,
|
||||
final String? now}) = _$ProxyImpl;
|
||||
|
||||
factory _Proxy.fromJson(Map<String, dynamic> json) = _$ProxyImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get name;
|
||||
@override
|
||||
String get type;
|
||||
@override
|
||||
String? get now;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$ProxyImplCopyWith<_$ProxyImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of '../proxy.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$GroupImpl _$$GroupImplFromJson(Map<String, dynamic> json) => _$GroupImpl(
|
||||
type: $enumDecode(_$GroupTypeEnumMap, json['type']),
|
||||
all: (json['all'] as List<dynamic>?)
|
||||
?.map((e) => Proxy.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
now: json['now'] as String?,
|
||||
hidden: json['hidden'] as bool?,
|
||||
icon: json['icon'] as String? ?? "",
|
||||
name: json['name'] as String,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$GroupImplToJson(_$GroupImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'type': _$GroupTypeEnumMap[instance.type]!,
|
||||
'all': instance.all,
|
||||
'now': instance.now,
|
||||
'hidden': instance.hidden,
|
||||
'icon': instance.icon,
|
||||
'name': instance.name,
|
||||
};
|
||||
|
||||
const _$GroupTypeEnumMap = {
|
||||
GroupType.Selector: 'Selector',
|
||||
GroupType.URLTest: 'URLTest',
|
||||
GroupType.Fallback: 'Fallback',
|
||||
GroupType.LoadBalance: 'LoadBalance',
|
||||
GroupType.Relay: 'Relay',
|
||||
};
|
||||
|
||||
_$ProxyImpl _$$ProxyImplFromJson(Map<String, dynamic> json) => _$ProxyImpl(
|
||||
name: json['name'] as String,
|
||||
type: json['type'] as String,
|
||||
now: json['now'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ProxyImplToJson(_$ProxyImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'name': instance.name,
|
||||
'type': instance.type,
|
||||
'now': instance.now,
|
||||
};
|
||||
@@ -957,25 +957,24 @@ abstract class _ApplicationSelectorState implements ApplicationSelectorState {
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$TrayContainerSelectorState {
|
||||
mixin _$TrayState {
|
||||
Mode get mode => throw _privateConstructorUsedError;
|
||||
bool get autoLaunch => throw _privateConstructorUsedError;
|
||||
bool get systemProxy => throw _privateConstructorUsedError;
|
||||
bool get tunEnable => throw _privateConstructorUsedError;
|
||||
bool get isStart => throw _privateConstructorUsedError;
|
||||
String? get locale => throw _privateConstructorUsedError;
|
||||
Brightness? get brightness => throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$TrayContainerSelectorStateCopyWith<TrayContainerSelectorState>
|
||||
get copyWith => throw _privateConstructorUsedError;
|
||||
$TrayStateCopyWith<TrayState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $TrayContainerSelectorStateCopyWith<$Res> {
|
||||
factory $TrayContainerSelectorStateCopyWith(TrayContainerSelectorState value,
|
||||
$Res Function(TrayContainerSelectorState) then) =
|
||||
_$TrayContainerSelectorStateCopyWithImpl<$Res,
|
||||
TrayContainerSelectorState>;
|
||||
abstract class $TrayStateCopyWith<$Res> {
|
||||
factory $TrayStateCopyWith(TrayState value, $Res Function(TrayState) then) =
|
||||
_$TrayStateCopyWithImpl<$Res, TrayState>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{Mode mode,
|
||||
@@ -983,14 +982,14 @@ abstract class $TrayContainerSelectorStateCopyWith<$Res> {
|
||||
bool systemProxy,
|
||||
bool tunEnable,
|
||||
bool isStart,
|
||||
String? locale});
|
||||
String? locale,
|
||||
Brightness? brightness});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$TrayContainerSelectorStateCopyWithImpl<$Res,
|
||||
$Val extends TrayContainerSelectorState>
|
||||
implements $TrayContainerSelectorStateCopyWith<$Res> {
|
||||
_$TrayContainerSelectorStateCopyWithImpl(this._value, this._then);
|
||||
class _$TrayStateCopyWithImpl<$Res, $Val extends TrayState>
|
||||
implements $TrayStateCopyWith<$Res> {
|
||||
_$TrayStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
@@ -1006,6 +1005,7 @@ class _$TrayContainerSelectorStateCopyWithImpl<$Res,
|
||||
Object? tunEnable = null,
|
||||
Object? isStart = null,
|
||||
Object? locale = freezed,
|
||||
Object? brightness = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
mode: null == mode
|
||||
@@ -1032,17 +1032,20 @@ class _$TrayContainerSelectorStateCopyWithImpl<$Res,
|
||||
? _value.locale
|
||||
: locale // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
brightness: freezed == brightness
|
||||
? _value.brightness
|
||||
: brightness // ignore: cast_nullable_to_non_nullable
|
||||
as Brightness?,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$TrayContainerSelectorStateImplCopyWith<$Res>
|
||||
implements $TrayContainerSelectorStateCopyWith<$Res> {
|
||||
factory _$$TrayContainerSelectorStateImplCopyWith(
|
||||
_$TrayContainerSelectorStateImpl value,
|
||||
$Res Function(_$TrayContainerSelectorStateImpl) then) =
|
||||
__$$TrayContainerSelectorStateImplCopyWithImpl<$Res>;
|
||||
abstract class _$$TrayStateImplCopyWith<$Res>
|
||||
implements $TrayStateCopyWith<$Res> {
|
||||
factory _$$TrayStateImplCopyWith(
|
||||
_$TrayStateImpl value, $Res Function(_$TrayStateImpl) then) =
|
||||
__$$TrayStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
@@ -1051,17 +1054,16 @@ abstract class _$$TrayContainerSelectorStateImplCopyWith<$Res>
|
||||
bool systemProxy,
|
||||
bool tunEnable,
|
||||
bool isStart,
|
||||
String? locale});
|
||||
String? locale,
|
||||
Brightness? brightness});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$TrayContainerSelectorStateImplCopyWithImpl<$Res>
|
||||
extends _$TrayContainerSelectorStateCopyWithImpl<$Res,
|
||||
_$TrayContainerSelectorStateImpl>
|
||||
implements _$$TrayContainerSelectorStateImplCopyWith<$Res> {
|
||||
__$$TrayContainerSelectorStateImplCopyWithImpl(
|
||||
_$TrayContainerSelectorStateImpl _value,
|
||||
$Res Function(_$TrayContainerSelectorStateImpl) _then)
|
||||
class __$$TrayStateImplCopyWithImpl<$Res>
|
||||
extends _$TrayStateCopyWithImpl<$Res, _$TrayStateImpl>
|
||||
implements _$$TrayStateImplCopyWith<$Res> {
|
||||
__$$TrayStateImplCopyWithImpl(
|
||||
_$TrayStateImpl _value, $Res Function(_$TrayStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@@ -1073,8 +1075,9 @@ class __$$TrayContainerSelectorStateImplCopyWithImpl<$Res>
|
||||
Object? tunEnable = null,
|
||||
Object? isStart = null,
|
||||
Object? locale = freezed,
|
||||
Object? brightness = freezed,
|
||||
}) {
|
||||
return _then(_$TrayContainerSelectorStateImpl(
|
||||
return _then(_$TrayStateImpl(
|
||||
mode: null == mode
|
||||
? _value.mode
|
||||
: mode // ignore: cast_nullable_to_non_nullable
|
||||
@@ -1099,20 +1102,25 @@ class __$$TrayContainerSelectorStateImplCopyWithImpl<$Res>
|
||||
? _value.locale
|
||||
: locale // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
brightness: freezed == brightness
|
||||
? _value.brightness
|
||||
: brightness // ignore: cast_nullable_to_non_nullable
|
||||
as Brightness?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$TrayContainerSelectorStateImpl implements _TrayContainerSelectorState {
|
||||
const _$TrayContainerSelectorStateImpl(
|
||||
class _$TrayStateImpl implements _TrayState {
|
||||
const _$TrayStateImpl(
|
||||
{required this.mode,
|
||||
required this.autoLaunch,
|
||||
required this.systemProxy,
|
||||
required this.tunEnable,
|
||||
required this.isStart,
|
||||
required this.locale});
|
||||
required this.locale,
|
||||
required this.brightness});
|
||||
|
||||
@override
|
||||
final Mode mode;
|
||||
@@ -1126,17 +1134,19 @@ class _$TrayContainerSelectorStateImpl implements _TrayContainerSelectorState {
|
||||
final bool isStart;
|
||||
@override
|
||||
final String? locale;
|
||||
@override
|
||||
final Brightness? brightness;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TrayContainerSelectorState(mode: $mode, autoLaunch: $autoLaunch, systemProxy: $systemProxy, tunEnable: $tunEnable, isStart: $isStart, locale: $locale)';
|
||||
return 'TrayState(mode: $mode, autoLaunch: $autoLaunch, systemProxy: $systemProxy, tunEnable: $tunEnable, isStart: $isStart, locale: $locale, brightness: $brightness)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$TrayContainerSelectorStateImpl &&
|
||||
other is _$TrayStateImpl &&
|
||||
(identical(other.mode, mode) || other.mode == mode) &&
|
||||
(identical(other.autoLaunch, autoLaunch) ||
|
||||
other.autoLaunch == autoLaunch) &&
|
||||
@@ -1145,30 +1155,31 @@ class _$TrayContainerSelectorStateImpl implements _TrayContainerSelectorState {
|
||||
(identical(other.tunEnable, tunEnable) ||
|
||||
other.tunEnable == tunEnable) &&
|
||||
(identical(other.isStart, isStart) || other.isStart == isStart) &&
|
||||
(identical(other.locale, locale) || other.locale == locale));
|
||||
(identical(other.locale, locale) || other.locale == locale) &&
|
||||
(identical(other.brightness, brightness) ||
|
||||
other.brightness == brightness));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, mode, autoLaunch, systemProxy, tunEnable, isStart, locale);
|
||||
int get hashCode => Object.hash(runtimeType, mode, autoLaunch, systemProxy,
|
||||
tunEnable, isStart, locale, brightness);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$TrayContainerSelectorStateImplCopyWith<_$TrayContainerSelectorStateImpl>
|
||||
get copyWith => __$$TrayContainerSelectorStateImplCopyWithImpl<
|
||||
_$TrayContainerSelectorStateImpl>(this, _$identity);
|
||||
_$$TrayStateImplCopyWith<_$TrayStateImpl> get copyWith =>
|
||||
__$$TrayStateImplCopyWithImpl<_$TrayStateImpl>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _TrayContainerSelectorState
|
||||
implements TrayContainerSelectorState {
|
||||
const factory _TrayContainerSelectorState(
|
||||
abstract class _TrayState implements TrayState {
|
||||
const factory _TrayState(
|
||||
{required final Mode mode,
|
||||
required final bool autoLaunch,
|
||||
required final bool systemProxy,
|
||||
required final bool tunEnable,
|
||||
required final bool isStart,
|
||||
required final String? locale}) = _$TrayContainerSelectorStateImpl;
|
||||
required final String? locale,
|
||||
required final Brightness? brightness}) = _$TrayStateImpl;
|
||||
|
||||
@override
|
||||
Mode get mode;
|
||||
@@ -1183,9 +1194,11 @@ abstract class _TrayContainerSelectorState
|
||||
@override
|
||||
String? get locale;
|
||||
@override
|
||||
Brightness? get brightness;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$TrayContainerSelectorStateImplCopyWith<_$TrayContainerSelectorStateImpl>
|
||||
get copyWith => throw _privateConstructorUsedError;
|
||||
_$$TrayStateImplCopyWith<_$TrayStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -1332,7 +1345,7 @@ abstract class _UpdateNavigationsSelector implements UpdateNavigationsSelector {
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$HomeSelectorState {
|
||||
mixin _$HomeState {
|
||||
String get currentLabel => throw _privateConstructorUsedError;
|
||||
List<NavigationItem> get navigationItems =>
|
||||
throw _privateConstructorUsedError;
|
||||
@@ -1340,15 +1353,14 @@ mixin _$HomeSelectorState {
|
||||
String? get locale => throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$HomeSelectorStateCopyWith<HomeSelectorState> get copyWith =>
|
||||
$HomeStateCopyWith<HomeState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $HomeSelectorStateCopyWith<$Res> {
|
||||
factory $HomeSelectorStateCopyWith(
|
||||
HomeSelectorState value, $Res Function(HomeSelectorState) then) =
|
||||
_$HomeSelectorStateCopyWithImpl<$Res, HomeSelectorState>;
|
||||
abstract class $HomeStateCopyWith<$Res> {
|
||||
factory $HomeStateCopyWith(HomeState value, $Res Function(HomeState) then) =
|
||||
_$HomeStateCopyWithImpl<$Res, HomeState>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String currentLabel,
|
||||
@@ -1358,9 +1370,9 @@ abstract class $HomeSelectorStateCopyWith<$Res> {
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$HomeSelectorStateCopyWithImpl<$Res, $Val extends HomeSelectorState>
|
||||
implements $HomeSelectorStateCopyWith<$Res> {
|
||||
_$HomeSelectorStateCopyWithImpl(this._value, this._then);
|
||||
class _$HomeStateCopyWithImpl<$Res, $Val extends HomeState>
|
||||
implements $HomeStateCopyWith<$Res> {
|
||||
_$HomeStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
@@ -1397,11 +1409,11 @@ class _$HomeSelectorStateCopyWithImpl<$Res, $Val extends HomeSelectorState>
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$HomeSelectorStateImplCopyWith<$Res>
|
||||
implements $HomeSelectorStateCopyWith<$Res> {
|
||||
factory _$$HomeSelectorStateImplCopyWith(_$HomeSelectorStateImpl value,
|
||||
$Res Function(_$HomeSelectorStateImpl) then) =
|
||||
__$$HomeSelectorStateImplCopyWithImpl<$Res>;
|
||||
abstract class _$$HomeStateImplCopyWith<$Res>
|
||||
implements $HomeStateCopyWith<$Res> {
|
||||
factory _$$HomeStateImplCopyWith(
|
||||
_$HomeStateImpl value, $Res Function(_$HomeStateImpl) then) =
|
||||
__$$HomeStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
@@ -1412,11 +1424,11 @@ abstract class _$$HomeSelectorStateImplCopyWith<$Res>
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$HomeSelectorStateImplCopyWithImpl<$Res>
|
||||
extends _$HomeSelectorStateCopyWithImpl<$Res, _$HomeSelectorStateImpl>
|
||||
implements _$$HomeSelectorStateImplCopyWith<$Res> {
|
||||
__$$HomeSelectorStateImplCopyWithImpl(_$HomeSelectorStateImpl _value,
|
||||
$Res Function(_$HomeSelectorStateImpl) _then)
|
||||
class __$$HomeStateImplCopyWithImpl<$Res>
|
||||
extends _$HomeStateCopyWithImpl<$Res, _$HomeStateImpl>
|
||||
implements _$$HomeStateImplCopyWith<$Res> {
|
||||
__$$HomeStateImplCopyWithImpl(
|
||||
_$HomeStateImpl _value, $Res Function(_$HomeStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@@ -1427,7 +1439,7 @@ class __$$HomeSelectorStateImplCopyWithImpl<$Res>
|
||||
Object? viewMode = null,
|
||||
Object? locale = freezed,
|
||||
}) {
|
||||
return _then(_$HomeSelectorStateImpl(
|
||||
return _then(_$HomeStateImpl(
|
||||
currentLabel: null == currentLabel
|
||||
? _value.currentLabel
|
||||
: currentLabel // ignore: cast_nullable_to_non_nullable
|
||||
@@ -1450,8 +1462,8 @@ class __$$HomeSelectorStateImplCopyWithImpl<$Res>
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$HomeSelectorStateImpl implements _HomeSelectorState {
|
||||
const _$HomeSelectorStateImpl(
|
||||
class _$HomeStateImpl implements _HomeState {
|
||||
const _$HomeStateImpl(
|
||||
{required this.currentLabel,
|
||||
required final List<NavigationItem> navigationItems,
|
||||
required this.viewMode,
|
||||
@@ -1475,14 +1487,14 @@ class _$HomeSelectorStateImpl implements _HomeSelectorState {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HomeSelectorState(currentLabel: $currentLabel, navigationItems: $navigationItems, viewMode: $viewMode, locale: $locale)';
|
||||
return 'HomeState(currentLabel: $currentLabel, navigationItems: $navigationItems, viewMode: $viewMode, locale: $locale)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$HomeSelectorStateImpl &&
|
||||
other is _$HomeStateImpl &&
|
||||
(identical(other.currentLabel, currentLabel) ||
|
||||
other.currentLabel == currentLabel) &&
|
||||
const DeepCollectionEquality()
|
||||
@@ -1499,17 +1511,16 @@ class _$HomeSelectorStateImpl implements _HomeSelectorState {
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$HomeSelectorStateImplCopyWith<_$HomeSelectorStateImpl> get copyWith =>
|
||||
__$$HomeSelectorStateImplCopyWithImpl<_$HomeSelectorStateImpl>(
|
||||
this, _$identity);
|
||||
_$$HomeStateImplCopyWith<_$HomeStateImpl> get copyWith =>
|
||||
__$$HomeStateImplCopyWithImpl<_$HomeStateImpl>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _HomeSelectorState implements HomeSelectorState {
|
||||
const factory _HomeSelectorState(
|
||||
abstract class _HomeState implements HomeState {
|
||||
const factory _HomeState(
|
||||
{required final String currentLabel,
|
||||
required final List<NavigationItem> navigationItems,
|
||||
required final ViewMode viewMode,
|
||||
required final String? locale}) = _$HomeSelectorStateImpl;
|
||||
required final String? locale}) = _$HomeStateImpl;
|
||||
|
||||
@override
|
||||
String get currentLabel;
|
||||
@@ -1521,143 +1532,10 @@ abstract class _HomeSelectorState implements HomeSelectorState {
|
||||
String? get locale;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$HomeSelectorStateImplCopyWith<_$HomeSelectorStateImpl> get copyWith =>
|
||||
_$$HomeStateImplCopyWith<_$HomeStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$HomeBodySelectorState {
|
||||
List<NavigationItem> get navigationItems =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$HomeBodySelectorStateCopyWith<HomeBodySelectorState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $HomeBodySelectorStateCopyWith<$Res> {
|
||||
factory $HomeBodySelectorStateCopyWith(HomeBodySelectorState value,
|
||||
$Res Function(HomeBodySelectorState) then) =
|
||||
_$HomeBodySelectorStateCopyWithImpl<$Res, HomeBodySelectorState>;
|
||||
@useResult
|
||||
$Res call({List<NavigationItem> navigationItems});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$HomeBodySelectorStateCopyWithImpl<$Res,
|
||||
$Val extends HomeBodySelectorState>
|
||||
implements $HomeBodySelectorStateCopyWith<$Res> {
|
||||
_$HomeBodySelectorStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? navigationItems = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
navigationItems: null == navigationItems
|
||||
? _value.navigationItems
|
||||
: navigationItems // ignore: cast_nullable_to_non_nullable
|
||||
as List<NavigationItem>,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$HomeBodySelectorStateImplCopyWith<$Res>
|
||||
implements $HomeBodySelectorStateCopyWith<$Res> {
|
||||
factory _$$HomeBodySelectorStateImplCopyWith(
|
||||
_$HomeBodySelectorStateImpl value,
|
||||
$Res Function(_$HomeBodySelectorStateImpl) then) =
|
||||
__$$HomeBodySelectorStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({List<NavigationItem> navigationItems});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$HomeBodySelectorStateImplCopyWithImpl<$Res>
|
||||
extends _$HomeBodySelectorStateCopyWithImpl<$Res,
|
||||
_$HomeBodySelectorStateImpl>
|
||||
implements _$$HomeBodySelectorStateImplCopyWith<$Res> {
|
||||
__$$HomeBodySelectorStateImplCopyWithImpl(_$HomeBodySelectorStateImpl _value,
|
||||
$Res Function(_$HomeBodySelectorStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? navigationItems = null,
|
||||
}) {
|
||||
return _then(_$HomeBodySelectorStateImpl(
|
||||
navigationItems: null == navigationItems
|
||||
? _value._navigationItems
|
||||
: navigationItems // ignore: cast_nullable_to_non_nullable
|
||||
as List<NavigationItem>,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$HomeBodySelectorStateImpl implements _HomeBodySelectorState {
|
||||
const _$HomeBodySelectorStateImpl(
|
||||
{required final List<NavigationItem> navigationItems})
|
||||
: _navigationItems = navigationItems;
|
||||
|
||||
final List<NavigationItem> _navigationItems;
|
||||
@override
|
||||
List<NavigationItem> get navigationItems {
|
||||
if (_navigationItems is EqualUnmodifiableListView) return _navigationItems;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_navigationItems);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'HomeBodySelectorState(navigationItems: $navigationItems)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$HomeBodySelectorStateImpl &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._navigationItems, _navigationItems));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, const DeepCollectionEquality().hash(_navigationItems));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$HomeBodySelectorStateImplCopyWith<_$HomeBodySelectorStateImpl>
|
||||
get copyWith => __$$HomeBodySelectorStateImplCopyWithImpl<
|
||||
_$HomeBodySelectorStateImpl>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _HomeBodySelectorState implements HomeBodySelectorState {
|
||||
const factory _HomeBodySelectorState(
|
||||
{required final List<NavigationItem> navigationItems}) =
|
||||
_$HomeBodySelectorStateImpl;
|
||||
|
||||
@override
|
||||
List<NavigationItem> get navigationItems;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$HomeBodySelectorStateImplCopyWith<_$HomeBodySelectorStateImpl>
|
||||
get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ProxiesCardSelectorState {
|
||||
bool get isSelected => throw _privateConstructorUsedError;
|
||||
@@ -4003,3 +3881,152 @@ abstract class _ClashConfigState implements ClashConfigState {
|
||||
_$$ClashConfigStateImplCopyWith<_$ClashConfigStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$ThemeState {
|
||||
String? get locale => throw _privateConstructorUsedError;
|
||||
ScaleProps get scaleProps => throw _privateConstructorUsedError;
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
$ThemeStateCopyWith<ThemeState> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $ThemeStateCopyWith<$Res> {
|
||||
factory $ThemeStateCopyWith(
|
||||
ThemeState value, $Res Function(ThemeState) then) =
|
||||
_$ThemeStateCopyWithImpl<$Res, ThemeState>;
|
||||
@useResult
|
||||
$Res call({String? locale, ScaleProps scaleProps});
|
||||
|
||||
$ScalePropsCopyWith<$Res> get scaleProps;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$ThemeStateCopyWithImpl<$Res, $Val extends ThemeState>
|
||||
implements $ThemeStateCopyWith<$Res> {
|
||||
_$ThemeStateCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? locale = freezed,
|
||||
Object? scaleProps = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
locale: freezed == locale
|
||||
? _value.locale
|
||||
: locale // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
scaleProps: null == scaleProps
|
||||
? _value.scaleProps
|
||||
: scaleProps // ignore: cast_nullable_to_non_nullable
|
||||
as ScaleProps,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ScalePropsCopyWith<$Res> get scaleProps {
|
||||
return $ScalePropsCopyWith<$Res>(_value.scaleProps, (value) {
|
||||
return _then(_value.copyWith(scaleProps: value) as $Val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$ThemeStateImplCopyWith<$Res>
|
||||
implements $ThemeStateCopyWith<$Res> {
|
||||
factory _$$ThemeStateImplCopyWith(
|
||||
_$ThemeStateImpl value, $Res Function(_$ThemeStateImpl) then) =
|
||||
__$$ThemeStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({String? locale, ScaleProps scaleProps});
|
||||
|
||||
@override
|
||||
$ScalePropsCopyWith<$Res> get scaleProps;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$ThemeStateImplCopyWithImpl<$Res>
|
||||
extends _$ThemeStateCopyWithImpl<$Res, _$ThemeStateImpl>
|
||||
implements _$$ThemeStateImplCopyWith<$Res> {
|
||||
__$$ThemeStateImplCopyWithImpl(
|
||||
_$ThemeStateImpl _value, $Res Function(_$ThemeStateImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? locale = freezed,
|
||||
Object? scaleProps = null,
|
||||
}) {
|
||||
return _then(_$ThemeStateImpl(
|
||||
locale: freezed == locale
|
||||
? _value.locale
|
||||
: locale // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
scaleProps: null == scaleProps
|
||||
? _value.scaleProps
|
||||
: scaleProps // ignore: cast_nullable_to_non_nullable
|
||||
as ScaleProps,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$ThemeStateImpl implements _ThemeState {
|
||||
const _$ThemeStateImpl({required this.locale, required this.scaleProps});
|
||||
|
||||
@override
|
||||
final String? locale;
|
||||
@override
|
||||
final ScaleProps scaleProps;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ThemeState(locale: $locale, scaleProps: $scaleProps)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$ThemeStateImpl &&
|
||||
(identical(other.locale, locale) || other.locale == locale) &&
|
||||
(identical(other.scaleProps, scaleProps) ||
|
||||
other.scaleProps == scaleProps));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, locale, scaleProps);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$ThemeStateImplCopyWith<_$ThemeStateImpl> get copyWith =>
|
||||
__$$ThemeStateImplCopyWithImpl<_$ThemeStateImpl>(this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _ThemeState implements ThemeState {
|
||||
const factory _ThemeState(
|
||||
{required final String? locale,
|
||||
required final ScaleProps scaleProps}) = _$ThemeStateImpl;
|
||||
|
||||
@override
|
||||
String? get locale;
|
||||
@override
|
||||
ScaleProps get scaleProps;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$ThemeStateImplCopyWith<_$ThemeStateImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
@@ -1,171 +0,0 @@
|
||||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of '../version.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
|
||||
|
||||
VersionInfo _$VersionInfoFromJson(Map<String, dynamic> json) {
|
||||
return _VersionInfo.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$VersionInfo {
|
||||
String get clashName => throw _privateConstructorUsedError;
|
||||
String get version => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$VersionInfoCopyWith<VersionInfo> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $VersionInfoCopyWith<$Res> {
|
||||
factory $VersionInfoCopyWith(
|
||||
VersionInfo value, $Res Function(VersionInfo) then) =
|
||||
_$VersionInfoCopyWithImpl<$Res, VersionInfo>;
|
||||
@useResult
|
||||
$Res call({String clashName, String version});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$VersionInfoCopyWithImpl<$Res, $Val extends VersionInfo>
|
||||
implements $VersionInfoCopyWith<$Res> {
|
||||
_$VersionInfoCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? clashName = null,
|
||||
Object? version = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
clashName: null == clashName
|
||||
? _value.clashName
|
||||
: clashName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
version: null == version
|
||||
? _value.version
|
||||
: version // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$VersionInfoImplCopyWith<$Res>
|
||||
implements $VersionInfoCopyWith<$Res> {
|
||||
factory _$$VersionInfoImplCopyWith(
|
||||
_$VersionInfoImpl value, $Res Function(_$VersionInfoImpl) then) =
|
||||
__$$VersionInfoImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({String clashName, String version});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$VersionInfoImplCopyWithImpl<$Res>
|
||||
extends _$VersionInfoCopyWithImpl<$Res, _$VersionInfoImpl>
|
||||
implements _$$VersionInfoImplCopyWith<$Res> {
|
||||
__$$VersionInfoImplCopyWithImpl(
|
||||
_$VersionInfoImpl _value, $Res Function(_$VersionInfoImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? clashName = null,
|
||||
Object? version = null,
|
||||
}) {
|
||||
return _then(_$VersionInfoImpl(
|
||||
clashName: null == clashName
|
||||
? _value.clashName
|
||||
: clashName // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
version: null == version
|
||||
? _value.version
|
||||
: version // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$VersionInfoImpl implements _VersionInfo {
|
||||
const _$VersionInfoImpl({this.clashName = "", this.version = ""});
|
||||
|
||||
factory _$VersionInfoImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$VersionInfoImplFromJson(json);
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final String clashName;
|
||||
@override
|
||||
@JsonKey()
|
||||
final String version;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'VersionInfo(clashName: $clashName, version: $version)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$VersionInfoImpl &&
|
||||
(identical(other.clashName, clashName) ||
|
||||
other.clashName == clashName) &&
|
||||
(identical(other.version, version) || other.version == version));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, clashName, version);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$VersionInfoImplCopyWith<_$VersionInfoImpl> get copyWith =>
|
||||
__$$VersionInfoImplCopyWithImpl<_$VersionInfoImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$VersionInfoImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _VersionInfo implements VersionInfo {
|
||||
const factory _VersionInfo({final String clashName, final String version}) =
|
||||
_$VersionInfoImpl;
|
||||
|
||||
factory _VersionInfo.fromJson(Map<String, dynamic> json) =
|
||||
_$VersionInfoImpl.fromJson;
|
||||
|
||||
@override
|
||||
String get clashName;
|
||||
@override
|
||||
String get version;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$VersionInfoImplCopyWith<_$VersionInfoImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of '../version.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_$VersionInfoImpl _$$VersionInfoImplFromJson(Map<String, dynamic> json) =>
|
||||
_$VersionInfoImpl(
|
||||
clashName: json['clashName'] as String? ?? "",
|
||||
version: json['version'] as String? ?? "",
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$VersionInfoImplToJson(_$VersionInfoImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'clashName': instance.clashName,
|
||||
'version': instance.version,
|
||||
};
|
||||
@@ -1,70 +0,0 @@
|
||||
class IpInfo {
|
||||
final String ip;
|
||||
final String countryCode;
|
||||
|
||||
const IpInfo({
|
||||
required this.ip,
|
||||
required this.countryCode,
|
||||
});
|
||||
|
||||
static IpInfo fromIpInfoIoJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
"ip": final String ip,
|
||||
"country": final String country,
|
||||
} =>
|
||||
IpInfo(
|
||||
ip: ip,
|
||||
countryCode: country,
|
||||
),
|
||||
_ => throw const FormatException("invalid json"),
|
||||
};
|
||||
}
|
||||
|
||||
static IpInfo fromIpApiCoJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
"ip": final String ip,
|
||||
"country_code": final String countryCode,
|
||||
} =>
|
||||
IpInfo(
|
||||
ip: ip,
|
||||
countryCode: countryCode,
|
||||
),
|
||||
_ => throw const FormatException("invalid json"),
|
||||
};
|
||||
}
|
||||
|
||||
static IpInfo fromIpSbJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
"ip": final String ip,
|
||||
"country_code": final String countryCode,
|
||||
} =>
|
||||
IpInfo(
|
||||
ip: ip,
|
||||
countryCode: countryCode,
|
||||
),
|
||||
_ => throw const FormatException("invalid json"),
|
||||
};
|
||||
}
|
||||
|
||||
static IpInfo fromIpwhoIsJson(Map<String, dynamic> json) {
|
||||
return switch (json) {
|
||||
{
|
||||
"ip": final String ip,
|
||||
"country_code": final String countryCode,
|
||||
} =>
|
||||
IpInfo(
|
||||
ip: ip,
|
||||
countryCode: countryCode,
|
||||
),
|
||||
_ => throw const FormatException("invalid json"),
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'IpInfo{ip: $ip, countryCode: $countryCode}';
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
// ignore_for_file: invalid_annotation_target
|
||||
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'generated/log.g.dart';
|
||||
|
||||
part 'generated/log.freezed.dart';
|
||||
|
||||
@JsonSerializable()
|
||||
class Log {
|
||||
@JsonKey(name: "LogLevel")
|
||||
LogLevel logLevel;
|
||||
@JsonKey(name: "Payload")
|
||||
String? payload;
|
||||
DateTime _dateTime;
|
||||
|
||||
Log({
|
||||
required this.logLevel,
|
||||
this.payload,
|
||||
}) : _dateTime = DateTime.now();
|
||||
|
||||
DateTime get dateTime => _dateTime;
|
||||
|
||||
factory Log.fromJson(Map<String, dynamic> json) {
|
||||
return _$LogFromJson(json);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$LogToJson(this);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Log{logLevel: $logLevel, payload: $payload, dateTime: $dateTime}';
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class LogsAndKeywords with _$LogsAndKeywords {
|
||||
const factory LogsAndKeywords({
|
||||
@Default([]) List<Log> logs,
|
||||
@Default([]) List<String> keywords,
|
||||
}) = _LogsAndKeywords;
|
||||
|
||||
factory LogsAndKeywords.fromJson(Map<String, Object?> json) =>
|
||||
_$LogsAndKeywordsFromJson(json);
|
||||
}
|
||||
|
||||
extension LogsAndKeywordsExt on LogsAndKeywords {
|
||||
List<Log> get filteredLogs => logs
|
||||
.where(
|
||||
(log) => {log.logLevel.name}.containsAll(keywords),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
@@ -2,16 +2,6 @@ export 'app.dart';
|
||||
export 'clash_config.dart';
|
||||
export 'config.dart';
|
||||
export 'profile.dart';
|
||||
export 'proxy.dart';
|
||||
export 'version.dart';
|
||||
export 'traffic.dart';
|
||||
export 'log.dart';
|
||||
export 'system_color_scheme.dart';
|
||||
export 'connection.dart';
|
||||
export 'package.dart';
|
||||
export 'ffi.dart';
|
||||
export 'selector.dart';
|
||||
export 'navigation.dart';
|
||||
export 'dav.dart';
|
||||
export 'ip.dart';
|
||||
export 'file.dart';
|
||||
export 'common.dart';
|
||||
@@ -1,19 +0,0 @@
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'generated/navigation.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class NavigationItem with _$NavigationItem {
|
||||
const factory NavigationItem({
|
||||
required Icon icon,
|
||||
required String label,
|
||||
final String? description,
|
||||
required Widget fragment,
|
||||
@Default(true) bool keep,
|
||||
String? path,
|
||||
@Default([NavigationItemMode.mobile, NavigationItemMode.desktop])
|
||||
List<NavigationItemMode> modes,
|
||||
}) = _NavigationItem;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'generated/package.g.dart';
|
||||
part 'generated/package.freezed.dart';
|
||||
|
||||
@freezed
|
||||
class Package with _$Package {
|
||||
const factory Package({
|
||||
required String packageName,
|
||||
required String label,
|
||||
required bool isSystem,
|
||||
required int firstInstallTime,
|
||||
}) = _Package;
|
||||
|
||||
factory Package.fromJson(Map<String, Object?> json) =>
|
||||
_$PackageFromJson(json);
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import '../enum/enum.dart';
|
||||
|
||||
part 'generated/proxy.g.dart';
|
||||
|
||||
part 'generated/proxy.freezed.dart';
|
||||
|
||||
typedef ProxyMap = Map<String, Proxy>;
|
||||
|
||||
@freezed
|
||||
class Group with _$Group {
|
||||
const factory Group({
|
||||
required GroupType type,
|
||||
@Default([]) List<Proxy> all,
|
||||
String? now,
|
||||
bool? hidden,
|
||||
@Default("") String icon,
|
||||
required String name,
|
||||
}) = _Group;
|
||||
|
||||
factory Group.fromJson(Map<String, Object?> json) => _$GroupFromJson(json);
|
||||
}
|
||||
|
||||
extension GroupExt on Group {
|
||||
String get realNow => now ?? "";
|
||||
|
||||
String getCurrentSelectedName(String proxyName) {
|
||||
if (type == GroupType.URLTest) {
|
||||
return realNow.isNotEmpty ? realNow : proxyName;
|
||||
}
|
||||
return proxyName.isNotEmpty ? proxyName : realNow;
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class Proxy with _$Proxy {
|
||||
const factory Proxy({
|
||||
required String name,
|
||||
required String type,
|
||||
String? now,
|
||||
}) = _Proxy;
|
||||
|
||||
factory Proxy.fromJson(Map<String, Object?> json) => _$ProxyFromJson(json);
|
||||
}
|
||||
@@ -59,15 +59,16 @@ class ApplicationSelectorState with _$ApplicationSelectorState {
|
||||
}
|
||||
|
||||
@freezed
|
||||
class TrayContainerSelectorState with _$TrayContainerSelectorState {
|
||||
const factory TrayContainerSelectorState({
|
||||
class TrayState with _$TrayState {
|
||||
const factory TrayState({
|
||||
required Mode mode,
|
||||
required bool autoLaunch,
|
||||
required bool systemProxy,
|
||||
required bool tunEnable,
|
||||
required bool isStart,
|
||||
required String? locale,
|
||||
}) = _TrayContainerSelectorState;
|
||||
required Brightness? brightness,
|
||||
}) = _TrayState;
|
||||
}
|
||||
|
||||
@freezed
|
||||
@@ -79,21 +80,15 @@ class UpdateNavigationsSelector with _$UpdateNavigationsSelector {
|
||||
}
|
||||
|
||||
@freezed
|
||||
class HomeSelectorState with _$HomeSelectorState {
|
||||
const factory HomeSelectorState({
|
||||
class HomeState with _$HomeState {
|
||||
const factory HomeState({
|
||||
required String currentLabel,
|
||||
required List<NavigationItem> navigationItems,
|
||||
required ViewMode viewMode,
|
||||
required String? locale,
|
||||
}) = _HomeSelectorState;
|
||||
}) = _HomeState;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class HomeBodySelectorState with _$HomeBodySelectorState {
|
||||
const factory HomeBodySelectorState({
|
||||
required List<NavigationItem> navigationItems,
|
||||
}) = _HomeBodySelectorState;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ProxiesCardSelectorState with _$ProxiesCardSelectorState {
|
||||
@@ -245,3 +240,12 @@ class ClashConfigState with _$ClashConfigState {
|
||||
required String? globalRealUa,
|
||||
}) = _ClashConfigState;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ThemeState with _$ThemeState {
|
||||
const factory ThemeState({
|
||||
required String? locale,
|
||||
required ScaleProps scaleProps,
|
||||
}) = _ThemeState;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user