Compare commits

..

1 Commits

Author SHA1 Message Date
chen08209
c5d25c9dd5 Fix android notification icon error 2024-06-08 22:51:58 +08:00
79 changed files with 942 additions and 2822 deletions

View File

@@ -3,7 +3,7 @@ name: build
on: on:
push: push:
tags: tags:
- 'v*' - '*'
jobs: jobs:
build: build:
@@ -17,16 +17,10 @@ jobs:
os: windows-latest os: windows-latest
- platform: linux - platform: linux
os: ubuntu-latest os: ubuntu-latest
- platform: macos # - platform: macos
os: macos-13 # os: macos-13
steps: steps:
- name: Check Matrix
run: |
echo "Running on ${{ matrix.os }}"
echo "Arch: ${{ runner.arch }}"
gcc --version
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
@@ -88,7 +82,7 @@ jobs:
upload-release: upload-release:
if: ${{ !contains(github.ref, '+') }} if: ${{ !endsWith(github.ref, '-debug') }}
permissions: write-all permissions: write-all
needs: [ build ] needs: [ build ]
runs-on: ubuntu-latest runs-on: ubuntu-latest

2
.gitmodules vendored
View File

@@ -5,4 +5,4 @@
[submodule "plugins/flutter_distributor"] [submodule "plugins/flutter_distributor"]
path = plugins/flutter_distributor path = plugins/flutter_distributor
url = git@github.com:chen08209/flutter_distributor.git url = git@github.com:chen08209/flutter_distributor.git
branch = FlClash branch = main

View File

@@ -22,7 +22,6 @@
<application <application
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:extractNativeLibs="true"
android:networkSecurityConfig="@xml/network_security_config" android:networkSecurityConfig="@xml/network_security_config"
android:label="FlClash"> android:label="FlClash">
<activity <activity

View File

@@ -1,7 +1,6 @@
package com.follow.clash package com.follow.clash
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.follow.clash.plugins.AppPlugin
import com.follow.clash.plugins.TilePlugin import com.follow.clash.plugins.TilePlugin
import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.FlutterEngine
import java.util.Date import java.util.Date
@@ -15,12 +14,10 @@ enum class RunState {
class GlobalState { class GlobalState {
companion object { companion object {
val runState: MutableLiveData<RunState> = MutableLiveData<RunState>(RunState.STOP) val runState: MutableLiveData<RunState> = MutableLiveData<RunState>(RunState.STOP)
var runTime: Date? = null
var flutterEngine: FlutterEngine? = null var flutterEngine: FlutterEngine? = null
fun getCurrentTilePlugin(): TilePlugin? = fun getCurrentTilePlugin(): TilePlugin? =
flutterEngine?.plugins?.get(TilePlugin::class.java) as TilePlugin? flutterEngine?.plugins?.get(TilePlugin::class.java) as TilePlugin?
fun getCurrentAppPlugin(): AppPlugin? =
flutterEngine?.plugins?.get(AppPlugin::class.java) as AppPlugin?
} }
} }

View File

@@ -1,18 +1,17 @@
package com.follow.clash.extensions package com.follow.clash.extensions
import java.net.InetSocketAddress
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.system.OsConstants.IPPROTO_TCP import android.system.OsConstants.IPPROTO_TCP
import android.system.OsConstants.IPPROTO_UDP import android.system.OsConstants.IPPROTO_UDP
import android.util.Base64 import android.util.Base64
import java.net.URL
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import com.follow.clash.models.Metadata import com.follow.clash.models.Metadata
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.net.InetAddress
import java.net.InetSocketAddress
suspend fun Drawable.getBase64(): String { suspend fun Drawable.getBase64(): String {
@@ -30,8 +29,3 @@ fun Metadata.getProtocol(): Int? {
if (network.startsWith("udp")) return IPPROTO_UDP if (network.startsWith("udp")) return IPPROTO_UDP
return null return null
} }
fun String.getInetSocketAddress(): InetSocketAddress {
val url = URL("https://$this")
return InetSocketAddress(InetAddress.getByName(url.host), url.port)
}

View File

@@ -10,9 +10,3 @@ data class AccessControl(
val acceptList: List<String>, val acceptList: List<String>,
val rejectList: List<String>, val rejectList: List<String>,
) )
data class Props(
val accessControl: AccessControl?,
val allowBypass: Boolean?,
val systemProxy: Boolean?,
)

View File

@@ -1,15 +1,11 @@
package com.follow.clash.models package com.follow.clash.models
data class Process(
val id: Int,
val metadata: Metadata,
)
data class Metadata( data class Metadata(
val network: String, val network: String,
val sourceIP: String, val sourceIP: String,
val sourcePort: Int, val sourcePort: Int,
val destinationIP: String, val destinationIP: String,
val destinationPort: Int, val destinationPort: Int,
val remoteDestination: String,
val host: String val host: String
) )

View File

@@ -6,16 +6,13 @@ import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.ConnectivityManager import android.net.ConnectivityManager
import android.net.Uri
import android.os.Build import android.os.Build
import android.widget.Toast import android.widget.Toast
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.toBitmap
import com.follow.clash.extensions.getBase64 import com.follow.clash.extensions.getBase64
import com.follow.clash.extensions.getInetSocketAddress
import com.follow.clash.extensions.getProtocol import com.follow.clash.extensions.getProtocol
import com.follow.clash.models.Process import com.follow.clash.models.Metadata
import com.follow.clash.models.Package import com.follow.clash.models.Package
import com.google.gson.Gson import com.google.gson.Gson
import io.flutter.embedding.engine.plugins.FlutterPlugin import io.flutter.embedding.engine.plugins.FlutterPlugin
@@ -81,34 +78,21 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
"getPackageIcon" -> { "getPackageIcon" -> {
scope.launch { scope.launch {
val packageName = call.argument<String>("packageName") val packageName = call.argument<String>("packageName")
if (packageName == null) { if (packageName != null) {
result.success(getPackageIcon(packageName))
} else {
result.success(null) result.success(null)
return@launch
}
val packageIcon = getPackageIcon(packageName)
packageIcon.let {
if (it != null) {
result.success(it)
return@launch
}
if (iconMap["default"] == null) {
iconMap["default"] =
context?.packageManager?.defaultActivityIcon?.getBase64()
}
result.success(iconMap["default"])
return@launch
} }
} }
} }
"resolverProcess" -> { "getPackageName" -> {
val data = call.argument<String>("data") val data = call.argument<String>("data")
val process = val metadata =
if (data != null) Gson().fromJson( if (data != null) Gson().fromJson(
data, data,
Process::class.java Metadata::class.java
) else null ) else null
val metadata = process?.metadata
val protocol = metadata?.getProtocol() val protocol = metadata?.getProtocol()
if (protocol == null) { if (protocol == null) {
result.success(null) result.success(null)
@@ -116,27 +100,17 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
} }
scope.launch { scope.launch {
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q){ if (context == null) result.success(null)
result.success(null) val source = InetSocketAddress(metadata.sourceIP, metadata.sourcePort)
return@withContext val target = InetSocketAddress(
} metadata.host.ifEmpty { metadata.destinationIP },
if (context == null) { metadata.destinationPort
result.success(null) )
return@withContext
}
if (connectivity == null) { if (connectivity == null) {
connectivity = context!!.getSystemService<ConnectivityManager>() connectivity = context!!.getSystemService<ConnectivityManager>()
} }
val src = InetSocketAddress(metadata.sourceIP, metadata.sourcePort) val uid =
val dst = InetSocketAddress( connectivity?.getConnectionOwnerUid(protocol, source, target)
metadata.destinationIP.ifEmpty { metadata.host },
metadata.destinationPort
)
val uid = try {
connectivity?.getConnectionOwnerUid(protocol, src, dst)
} catch (_: Exception) {
null
}
if (uid == null || uid == -1) { if (uid == null || uid == -1) {
result.success(null) result.success(null)
return@withContext return@withContext
@@ -163,18 +137,13 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
private suspend fun getPackageIcon(packageName: String): String? { private suspend fun getPackageIcon(packageName: String): String? {
val packageManager = context?.packageManager val packageManager = context?.packageManager
if (iconMap[packageName] == null) { if (iconMap[packageName] == null) {
iconMap[packageName] = try { iconMap[packageName] = packageManager?.getApplicationIcon(packageName)?.getBase64()
packageManager?.getApplicationIcon(packageName)?.getBase64()
} catch (_: Exception) {
null
}
} }
return iconMap[packageName] return iconMap[packageName]
} }
private suspend fun getPackages(): String { private suspend fun getPackages(): String {
return withContext(Dispatchers.Default) { return withContext(Dispatchers.Default){
val packageManager = context?.packageManager val packageManager = context?.packageManager
val packages: List<Package>? = val packages: List<Package>? =
packageManager?.getInstalledPackages(PackageManager.GET_META_DATA)?.filter { packageManager?.getInstalledPackages(PackageManager.GET_META_DATA)?.filter {
@@ -193,10 +162,6 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
} }
} }
fun requestGc() {
channel.invokeMethod("gc", null)
}
override fun onAttachedToActivity(binding: ActivityPluginBinding) { override fun onAttachedToActivity(binding: ActivityPluginBinding) {
activity = binding.activity; activity = binding.activity;
scope = CoroutineScope(Dispatchers.Default) scope = CoroutineScope(Dispatchers.Default)

View File

@@ -16,7 +16,7 @@ import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.follow.clash.GlobalState import com.follow.clash.GlobalState
import com.follow.clash.RunState import com.follow.clash.RunState
import com.follow.clash.models.Props import com.follow.clash.models.AccessControl
import com.follow.clash.services.FlClashVpnService import com.follow.clash.services.FlClashVpnService
import com.google.gson.Gson import com.google.gson.Gson
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
@@ -25,6 +25,7 @@ import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel
import java.util.Date
class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware { class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware {
@@ -40,7 +41,7 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
private var flClashVpnService: FlClashVpnService? = null private var flClashVpnService: FlClashVpnService? = null
private var isBound = false private var isBound = false
private var port: Int? = null private var port: Int? = null
private var props: Props? = null private var accessControl: AccessControl? = null
private lateinit var title: String private lateinit var title: String
private lateinit var content: String private lateinit var content: String
@@ -72,8 +73,8 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
"StartProxy" -> { "StartProxy" -> {
port = call.argument<Int>("port") port = call.argument<Int>("port")
val args = call.argument<String>("args") val args = call.argument<String>("args")
props = accessControl =
if (args != null) Gson().fromJson(args, Props::class.java) else null if (args != null) Gson().fromJson(args, AccessControl::class.java) else null
handleStartVpn() handleStartVpn()
result.success(true) result.success(true)
} }
@@ -93,6 +94,10 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
} }
} }
"GetRunTimeStamp" -> {
result.success(GlobalState.runTime?.time)
}
"startForeground" -> { "startForeground" -> {
title = call.argument<String>("title") as String title = call.argument<String>("title") as String
content = call.argument<String>("content") as String content = call.argument<String>("content") as String
@@ -116,8 +121,9 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
private fun startVpn(port: Int) { private fun startVpn(port: Int) {
if (GlobalState.runState.value == RunState.START) return; if (GlobalState.runState.value == RunState.START) return;
flClashVpnService?.start(port, props) flClashVpnService?.start(port, accessControl)
GlobalState.runState.value = RunState.START GlobalState.runState.value = RunState.START
GlobalState.runTime = Date()
startAfter() startAfter()
} }
@@ -126,6 +132,7 @@ class ProxyPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAwar
flClashVpnService?.stop() flClashVpnService?.stop()
unbindService() unbindService()
GlobalState.runState.value = RunState.STOP; GlobalState.runState.value = RunState.STOP;
GlobalState.runTime = null;
} }
@SuppressLint("ForegroundServiceType") @SuppressLint("ForegroundServiceType")

View File

@@ -44,7 +44,7 @@ class FlClashTileService : TileService() {
private fun activityTransfer() { private fun activityTransfer() {
val intent = Intent(this, TempActivity::class.java) val intent = Intent(this, TempActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val pendingIntent = if (Build.VERSION.SDK_INT >= 31) { val pendingIntent = if (Build.VERSION.SDK_INT >= 31) {
PendingIntent.getActivity( PendingIntent.getActivity(
this, this,

View File

@@ -15,8 +15,8 @@ import androidx.core.app.NotificationCompat
import com.follow.clash.GlobalState import com.follow.clash.GlobalState
import com.follow.clash.MainActivity import com.follow.clash.MainActivity
import com.follow.clash.R import com.follow.clash.R
import com.follow.clash.models.AccessControl
import com.follow.clash.models.AccessControlMode import com.follow.clash.models.AccessControlMode
import com.follow.clash.models.Props
class FlClashVpnService : VpnService() { class FlClashVpnService : VpnService() {
@@ -51,12 +51,12 @@ class FlClashVpnService : VpnService() {
return START_STICKY return START_STICKY
} }
fun start(port: Int, props: Props?) { fun start(port: Int, accessControl: AccessControl?) {
fd = with(Builder()) { fd = with(Builder()) {
addAddress("172.16.0.1", 30) addAddress("172.16.0.1", 30)
setMtu(9000) setMtu(9000)
addRoute("0.0.0.0", 0) addRoute("0.0.0.0", 0)
props?.accessControl?.let { accessControl -> if (accessControl != null) {
when (accessControl.mode) { when (accessControl.mode) {
AccessControlMode.acceptSelected -> { AccessControlMode.acceptSelected -> {
(accessControl.acceptList + packageName).forEach { (accessControl.acceptList + packageName).forEach {
@@ -77,10 +77,8 @@ class FlClashVpnService : VpnService() {
if (Build.VERSION.SDK_INT >= 29) { if (Build.VERSION.SDK_INT >= 29) {
setMetered(false) setMetered(false)
} }
if (props?.allowBypass == true) { allowBypass()
allowBypass() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && props?.systemProxy == true) {
setHttpProxy( setHttpProxy(
ProxyInfo.buildDirectProxy( ProxyInfo.buildDirectProxy(
"127.0.0.1", "127.0.0.1",
@@ -134,26 +132,20 @@ class FlClashVpnService : VpnService() {
} }
} }
override fun onTrimMemory(level: Int) {
super.onTrimMemory(level)
GlobalState.getCurrentAppPlugin()?.requestGc()
}
fun startForeground(title: String, content: String) { fun startForeground(title: String, content: String) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel =
NotificationChannel(CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW)
val manager = getSystemService(NotificationManager::class.java) val manager = getSystemService(NotificationManager::class.java)
var channel = manager?.getNotificationChannel(CHANNEL) manager.createNotificationChannel(channel)
if (channel == null) { channel.setShowBadge(false)
channel =
NotificationChannel(CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW)
manager?.createNotificationChannel(channel)
}
} }
val notification = val notification =
notificationBuilder.setContentTitle(title).setContentText(content).build() notificationBuilder.setContentTitle(title).setContentText(content).build()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_SPECIAL_USE) startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_SPECIAL_USE)
} else { }else{
startForeground(notificationId, notification) startForeground(notificationId, notification)
} }
} }

View File

@@ -4,6 +4,7 @@
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame --> the Flutter engine draws its first frame -->
<item name="android:windowBackground">@mipmap/ic_launcher_foreground</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started. <!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your This theme determines the color of the Android Window while your

View File

@@ -4,6 +4,7 @@
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame --> the Flutter engine draws its first frame -->
<item name="android:windowBackground">@mipmap/ic_launcher_foreground</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started. <!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your This theme determines the color of the Android Window while your

View File

@@ -2,24 +2,25 @@ package main
import "C" import "C"
import ( import (
"github.com/metacubex/mihomo/adapter"
"github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/adapter/inbound"
ap "github.com/metacubex/mihomo/adapter/provider" ap "github.com/metacubex/mihomo/adapter/provider"
"github.com/metacubex/mihomo/component/dialer" "github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/component/process"
"github.com/metacubex/mihomo/component/resolver" "github.com/metacubex/mihomo/component/resolver"
"github.com/metacubex/mihomo/config" "github.com/metacubex/mihomo/config"
"github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/constant/provider"
"github.com/metacubex/mihomo/hub" "github.com/metacubex/mihomo/dns"
"github.com/metacubex/mihomo/hub/executor" "github.com/metacubex/mihomo/hub/executor"
"github.com/metacubex/mihomo/hub/route"
"github.com/metacubex/mihomo/listener" "github.com/metacubex/mihomo/listener"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"github.com/metacubex/mihomo/tunnel" "github.com/metacubex/mihomo/tunnel"
"math"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
"sync"
"syscall" "syscall"
"time" "time"
) )
@@ -82,13 +83,10 @@ type Delay struct {
} }
type Process struct { type Process struct {
Id int64 `json:"id"` Uid uint32 `json:"uid"`
Metadata constant.Metadata `json:"metadata"` Network string `json:"network"`
} Source string `json:"source"`
Target string `json:"target"`
type ProcessMapItem struct {
Id int64 `json:"id"`
Value *string `json:"value"`
} }
type Now struct { type Now struct {
@@ -323,35 +321,33 @@ func generateProxyGroupAndRule(proxyGroup *[]map[string]any, rule *[]string) {
} }
func overwriteConfig(targetConfig *config.RawConfig, patchConfig config.RawConfig, compatible bool) { func overwriteConfig(targetConfig *config.RawConfig, patchConfig config.RawConfig, compatible bool) {
targetConfig.ExternalController = patchConfig.ExternalController targetConfig.ExternalController = ""
targetConfig.ExternalUI = "" targetConfig.ExternalUI = ""
targetConfig.Interface = "" targetConfig.Interface = ""
targetConfig.ExternalUIURL = "" targetConfig.ExternalUIURL = ""
targetConfig.TCPConcurrent = patchConfig.TCPConcurrent
targetConfig.UnifiedDelay = patchConfig.UnifiedDelay
targetConfig.GeodataMode = false targetConfig.GeodataMode = false
targetConfig.IPv6 = patchConfig.IPv6 //targetConfig.IPv6 = patchConfig.IPv6
targetConfig.LogLevel = patchConfig.LogLevel targetConfig.LogLevel = patchConfig.LogLevel
targetConfig.Port = 0 targetConfig.Port = 0
targetConfig.SocksPort = 0 targetConfig.SocksPort = 0
targetConfig.MixedPort = patchConfig.MixedPort targetConfig.MixedPort = patchConfig.MixedPort
targetConfig.FindProcessMode = patchConfig.FindProcessMode targetConfig.FindProcessMode = process.FindProcessAlways
targetConfig.AllowLan = patchConfig.AllowLan targetConfig.AllowLan = patchConfig.AllowLan
targetConfig.Mode = patchConfig.Mode targetConfig.Mode = patchConfig.Mode
targetConfig.Tun.Enable = patchConfig.Tun.Enable targetConfig.Tun.Enable = patchConfig.Tun.Enable
targetConfig.Tun.Device = patchConfig.Tun.Device targetConfig.Tun.Device = patchConfig.Tun.Device
//targetConfig.Tun.DNSHijack = patchConfig.Tun.DNSHijack targetConfig.Tun.DNSHijack = patchConfig.Tun.DNSHijack
//targetConfig.Tun.Stack = patchConfig.Tun.Stack targetConfig.Tun.Stack = patchConfig.Tun.Stack
targetConfig.GeodataLoader = patchConfig.GeodataLoader targetConfig.GeodataLoader = "standard"
targetConfig.Profile.StoreSelected = false targetConfig.Profile.StoreSelected = false
if targetConfig.DNS.Enable == false { if targetConfig.DNS.Enable == false {
targetConfig.DNS = patchConfig.DNS targetConfig.DNS = patchConfig.DNS
} }
//if runtime.GOOS == "android" { if runtime.GOOS == "android" {
// targetConfig.DNS.NameServer = append(targetConfig.DNS.NameServer, "dhcp://"+dns.SystemDNSPlaceholder) targetConfig.DNS.NameServer = append(targetConfig.DNS.NameServer, "dhcp://"+dns.SystemDNSPlaceholder)
//} else if runtime.GOOS == "windows" { } else if runtime.GOOS == "windows" {
// targetConfig.DNS.NameServer = append(targetConfig.DNS.NameServer, dns.SystemDNSPlaceholder) targetConfig.DNS.NameServer = append(targetConfig.DNS.NameServer, dns.SystemDNSPlaceholder)
//} }
if compatible == false { if compatible == false {
targetConfig.ProxyProvider = make(map[string]map[string]any) targetConfig.ProxyProvider = make(map[string]map[string]any)
targetConfig.RuleProvider = make(map[string]map[string]any) targetConfig.RuleProvider = make(map[string]map[string]any)
@@ -361,17 +357,14 @@ func overwriteConfig(targetConfig *config.RawConfig, patchConfig config.RawConfi
func patchConfig(general *config.General) { func patchConfig(general *config.General) {
log.Infoln("[Apply] patch") log.Infoln("[Apply] patch")
route.ReStartServer(general.ExternalController)
listener.SetAllowLan(general.AllowLan) listener.SetAllowLan(general.AllowLan)
inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes) inbound.SetSkipAuthPrefixes(general.SkipAuthPrefixes)
inbound.SetAllowedIPs(general.LanAllowedIPs) inbound.SetAllowedIPs(general.LanAllowedIPs)
inbound.SetDisAllowedIPs(general.LanDisAllowedIPs) inbound.SetDisAllowedIPs(general.LanDisAllowedIPs)
listener.SetBindAddress(general.BindAddress) listener.SetBindAddress(general.BindAddress)
tunnel.SetSniffing(general.Sniffing) tunnel.SetSniffing(general.Sniffing)
tunnel.SetFindProcessMode(general.FindProcessMode)
dialer.SetTcpConcurrent(general.TCPConcurrent) dialer.SetTcpConcurrent(general.TCPConcurrent)
dialer.DefaultInterface.Store(general.Interface) dialer.DefaultInterface.Store(general.Interface)
adapter.UnifiedDelay.Store(general.UnifiedDelay)
listener.ReCreateHTTP(general.Port, tunnel.Tunnel) listener.ReCreateHTTP(general.Port, tunnel.Tunnel)
listener.ReCreateSocks(general.SocksPort, tunnel.Tunnel) listener.ReCreateSocks(general.SocksPort, tunnel.Tunnel)
listener.ReCreateRedir(general.RedirPort, tunnel.Tunnel) listener.ReCreateRedir(general.RedirPort, tunnel.Tunnel)
@@ -384,10 +377,31 @@ func patchConfig(general *config.General) {
listener.ReCreateTuic(general.TuicServer, tunnel.Tunnel) listener.ReCreateTuic(general.TuicServer, tunnel.Tunnel)
tunnel.SetMode(general.Mode) tunnel.SetMode(general.Mode)
log.SetLevel(general.LogLevel) log.SetLevel(general.LogLevel)
resolver.DisableIPv6 = !general.IPv6 resolver.DisableIPv6 = !general.IPv6
} }
const concurrentCount = math.MaxInt
func hcCompatibleProvider(proxyProviders map[string]provider.ProxyProvider) {
wg := sync.WaitGroup{}
ch := make(chan struct{}, concurrentCount)
for _, proxyProvider := range proxyProviders {
proxyProvider := proxyProvider
if proxyProvider.VehicleType() == provider.Compatible {
log.Infoln("Start initial Compatible provider %s", proxyProvider.Name())
wg.Add(1)
ch <- struct{}{}
go func() {
defer func() { <-ch; wg.Done() }()
if err := proxyProvider.Initial(); err != nil {
log.Errorln("initial Compatible provider %s error: %v", proxyProvider.Name(), err)
}
}()
}
}
}
func applyConfig(isPatch bool) { func applyConfig(isPatch bool) {
cfg, err := config.ParseRawConfig(currentConfig) cfg, err := config.ParseRawConfig(currentConfig)
if err != nil { if err != nil {
@@ -396,8 +410,7 @@ func applyConfig(isPatch bool) {
if isPatch { if isPatch {
patchConfig(cfg.General) patchConfig(cfg.General)
} else { } else {
runtime.GC() executor.ApplyConfig(cfg, true)
executor.Shutdown() hcCompatibleProvider(tunnel.Providers())
hub.UltraApplyConfig(cfg, true)
} }
} }

View File

@@ -12,7 +12,6 @@ const (
Delay MessageType = "delay" Delay MessageType = "delay"
Now MessageType = "now" Now MessageType = "now"
Process MessageType = "process" Process MessageType = "process"
Request MessageType = "request"
) )
type Message struct { type Message struct {

View File

@@ -1,6 +1,6 @@
module core module core
go 1.21.0 go 1.20
replace github.com/metacubex/mihomo => ./Clash.Meta replace github.com/metacubex/mihomo => ./Clash.Meta
@@ -17,7 +17,6 @@ require (
github.com/RyuaNerin/go-krypto v1.2.4 // indirect github.com/RyuaNerin/go-krypto v1.2.4 // indirect
github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 // indirect github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 // indirect
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
github.com/ajg/form v1.5.1 // indirect
github.com/andybalholm/brotli v1.0.6 // indirect github.com/andybalholm/brotli v1.0.6 // indirect
github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect
@@ -31,9 +30,6 @@ require (
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gaukas/godicttls v0.0.4 // indirect github.com/gaukas/godicttls v0.0.4 // indirect
github.com/go-chi/chi/v5 v5.0.12 // indirect
github.com/go-chi/cors v1.2.1 // indirect
github.com/go-chi/render v1.0.3 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gobwas/httphead v0.1.0 // indirect github.com/gobwas/httphead v0.1.0 // indirect

View File

@@ -9,8 +9,6 @@ github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 h1:cDVUiFo+npB0ZASqnw4
github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk= github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk=
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
@@ -37,25 +35,16 @@ github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIF
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g= github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g=
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391/go.mod h1:K2R7GhgxrlJzHw2qiPWsCZXf/kXEJN9PLnQK73Ll0po= github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391/go.mod h1:K2R7GhgxrlJzHw2qiPWsCZXf/kXEJN9PLnQK73Ll0po=
github.com/ericlagergren/saferand v0.0.0-20220206064634-960a4dd2bc5c h1:RUzBDdZ+e/HEe2Nh8lYsduiPAZygUfVXJn0Ncj5sHMg= github.com/ericlagergren/saferand v0.0.0-20220206064634-960a4dd2bc5c h1:RUzBDdZ+e/HEe2Nh8lYsduiPAZygUfVXJn0Ncj5sHMg=
github.com/ericlagergren/saferand v0.0.0-20220206064634-960a4dd2bc5c/go.mod h1:ETASDWf/FmEb6Ysrtd1QhjNedUU/ZQxBCRLh60bQ/UI=
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 h1:tlDMEdcPRQKBEz5nGDMvswiajqh7k8ogWRlhRwKy5mY= github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 h1:tlDMEdcPRQKBEz5nGDMvswiajqh7k8ogWRlhRwKy5mY=
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1/go.mod h1:4RfsapbGx2j/vU5xC/5/9qB3kn9Awp1YDiEnN43QrJ4= github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1/go.mod h1:4RfsapbGx2j/vU5xC/5/9qB3kn9Awp1YDiEnN43QrJ4=
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA= github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA=
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010/go.mod h1:JtBcj7sBuTTRupn7c2bFspMDIObMJsVK8TeUvpShPok= github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010/go.mod h1:JtBcj7sBuTTRupn7c2bFspMDIObMJsVK8TeUvpShPok=
github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk= github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXbk=
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI= github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
@@ -71,7 +60,6 @@ github.com/gofrs/uuid/v5 v5.2.0 h1:qw1GMx6/y8vhVsx626ImfKMuS5CvJmhIKKtuyvfajMM=
github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gofrs/uuid/v5 v5.2.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -81,7 +69,6 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I= github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
github.com/google/tink/go v1.6.1/go.mod h1:IGW53kTgag+st5yPhKKwJ6u2l+SSp5/v9XF7spovjlY=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -96,9 +83,7 @@ github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6K
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc=
@@ -140,7 +125,6 @@ github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7/go.mod h1:U
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q= github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k= github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/openacid/errors v0.8.1/go.mod h1:GUQEJJOJE3W9skHm8E8Y4phdl2LLEN8iD7c5gcGgdx0= github.com/openacid/errors v0.8.1/go.mod h1:GUQEJJOJE3W9skHm8E8Y4phdl2LLEN8iD7c5gcGgdx0=
github.com/openacid/low v0.1.21 h1:Tr2GNu4N/+rGRYdOsEHOE89cxUIaDViZbVmKz29uKGo= github.com/openacid/low v0.1.21 h1:Tr2GNu4N/+rGRYdOsEHOE89cxUIaDViZbVmKz29uKGo=
github.com/openacid/low v0.1.21/go.mod h1:q+MsKI6Pz2xsCkzV4BLj7NR5M4EX0sGz5AqotpZDVh0= github.com/openacid/low v0.1.21/go.mod h1:q+MsKI6Pz2xsCkzV4BLj7NR5M4EX0sGz5AqotpZDVh0=
@@ -162,7 +146,6 @@ github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0=
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE= github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
@@ -266,7 +249,6 @@ golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
@@ -281,7 +263,6 @@ google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFW
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -60,14 +60,6 @@ func shutdownClash() bool {
return true return true
} }
//export forceGc
func forceGc() {
go func() {
log.Infoln("[APP] request force GC")
runtime.GC()
}()
}
//export validateConfig //export validateConfig
func validateConfig(s *C.char, port C.longlong) { func validateConfig(s *C.char, port C.longlong) {
i := int64(port) i := int64(port)
@@ -404,10 +396,4 @@ func init() {
Data: delayData, Data: delayData,
}) })
} }
statistic.DefaultRequestNotify = func(c statistic.Tracker) {
bridge.SendMessage(bridge.Message{
Type: bridge.Request,
Data: c,
})
}
} }

View File

@@ -18,9 +18,6 @@ func startLog() {
logSubscriber = log.Subscribe() logSubscriber = log.Subscribe()
go func() { go func() {
for logData := range logSubscriber { for logData := range logSubscriber {
if logData.LogLevel < log.Level() {
continue
}
message := &bridge.Message{ message := &bridge.Message{
Type: bridge.Log, Type: bridge.Log,
Data: logData, Data: logData,

View File

@@ -1,42 +0,0 @@
//go:build android
package platform
import "syscall"
var nullFd int
var maxFdCount int
func init() {
fd, err := syscall.Open("/dev/null", syscall.O_WRONLY, 0644)
if err != nil {
panic(err.Error())
}
nullFd = fd
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
maxFdCount = 1024
} else {
maxFdCount = int(limit.Cur)
}
maxFdCount = maxFdCount / 4 * 3
}
func ShouldBlockConnection() bool {
fd, err := syscall.Dup(nullFd)
if err != nil {
return true
}
_ = syscall.Close(fd)
if fd > maxFdCount {
return true
}
return false
}

View File

@@ -1,171 +0,0 @@
//go:build android
package platform
import (
"bufio"
"encoding/binary"
"encoding/hex"
"fmt"
"net"
"os"
"strconv"
"strings"
"unsafe"
)
var netIndexOfLocal = -1
var netIndexOfUid = -1
var nativeEndian binary.ByteOrder
func QuerySocketUidFromProcFs(source, _ net.Addr) int {
if netIndexOfLocal < 0 || netIndexOfUid < 0 {
return -1
}
network := source.Network()
if strings.HasSuffix(network, "4") || strings.HasSuffix(network, "6") {
network = network[:len(network)-1]
}
path := "/proc/net/" + network
var sIP net.IP
var sPort int
switch s := source.(type) {
case *net.TCPAddr:
sIP = s.IP
sPort = s.Port
case *net.UDPAddr:
sIP = s.IP
sPort = s.Port
default:
return -1
}
sIP = sIP.To16()
if sIP == nil {
return -1
}
uid := doQuery(path+"6", sIP, sPort)
if uid == -1 {
sIP = sIP.To4()
if sIP == nil {
return -1
}
uid = doQuery(path, sIP, sPort)
}
return uid
}
func doQuery(path string, sIP net.IP, sPort int) int {
file, err := os.Open(path)
if err != nil {
return -1
}
defer file.Close()
reader := bufio.NewReader(file)
var bytes [2]byte
binary.BigEndian.PutUint16(bytes[:], uint16(sPort))
local := fmt.Sprintf("%s:%s", hex.EncodeToString(nativeEndianIP(sIP)), hex.EncodeToString(bytes[:]))
for {
row, _, err := reader.ReadLine()
if err != nil {
return -1
}
fields := strings.Fields(string(row))
if len(fields) <= netIndexOfLocal || len(fields) <= netIndexOfUid {
continue
}
if strings.EqualFold(local, fields[netIndexOfLocal]) {
uid, err := strconv.Atoi(fields[netIndexOfUid])
if err != nil {
return -1
}
return uid
}
}
}
func nativeEndianIP(ip net.IP) []byte {
result := make([]byte, len(ip))
for i := 0; i < len(ip); i += 4 {
value := binary.BigEndian.Uint32(ip[i:])
nativeEndian.PutUint32(result[i:], value)
}
return result
}
func init() {
file, err := os.Open("/proc/net/tcp")
if err != nil {
return
}
defer file.Close()
reader := bufio.NewReader(file)
header, _, err := reader.ReadLine()
if err != nil {
return
}
columns := strings.Fields(string(header))
var txQueue, rxQueue, tr, tmWhen bool
for idx, col := range columns {
offset := 0
if txQueue && rxQueue {
offset--
}
if tr && tmWhen {
offset--
}
switch col {
case "tx_queue":
txQueue = true
case "rx_queue":
rxQueue = true
case "tr":
tr = true
case "tm->when":
tmWhen = true
case "local_address":
netIndexOfLocal = idx + offset
case "uid":
netIndexOfUid = idx + offset
}
}
}
func init() {
var x uint32 = 0x01020304
if *(*byte)(unsafe.Pointer(&x)) == 0x01 {
nativeEndian = binary.BigEndian
} else {
nativeEndian = binary.LittleEndian
}
}

View File

@@ -1,72 +1,3 @@
//go:build android //go:build android
package main package main
import "C"
import (
bridge "core/dart-bridge"
"encoding/json"
"errors"
"github.com/metacubex/mihomo/component/process"
"github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log"
"sync/atomic"
"time"
)
var (
counter int64
)
var processMap = make(map[int64]*string)
func init() {
process.DefaultPackageNameResolver = func(metadata *constant.Metadata) (string, error) {
if metadata == nil {
return "", process.ErrInvalidNetwork
}
id := atomic.AddInt64(&counter, 1)
timeout := time.After(200 * time.Millisecond)
message := &bridge.Message{
Type: bridge.Process,
Data: Process{
Id: id,
Metadata: *metadata,
},
}
bridge.SendMessage(*message)
for {
select {
case <-timeout:
return "", errors.New("package resolver timeout")
default:
value, exists := processMap[counter]
if exists {
if value != nil {
log.Infoln("[PKG] %s --> %s by [%s]", metadata.SourceAddress(), metadata.RemoteAddress(), *value)
return *value, nil
} else {
return "", process.ErrInvalidNetwork
}
}
time.Sleep(10 * time.Millisecond)
}
}
}
}
//export setProcessMap
func setProcessMap(s *C.char) {
go func() {
paramsString := C.GoString(s)
var processMapItem = &ProcessMapItem{}
err := json.Unmarshal([]byte(paramsString), processMapItem)
if err == nil {
processMap[processMapItem.Id] = processMapItem.Value
}
}()
}

View File

@@ -4,13 +4,10 @@ package main
import "C" import "C"
import ( import (
"core/platform"
t "core/tun" t "core/tun"
"errors"
"github.com/metacubex/mihomo/component/dialer" "github.com/metacubex/mihomo/component/dialer"
"github.com/metacubex/mihomo/log" "github.com/metacubex/mihomo/log"
"golang.org/x/sync/semaphore" "golang.org/x/sync/semaphore"
"strconv"
"sync" "sync"
"syscall" "syscall"
"time" "time"
@@ -18,16 +15,11 @@ import (
var tunLock sync.Mutex var tunLock sync.Mutex
var tun *t.Tun var tun *t.Tun
var runTime *time.Time
//export startTUN //export startTUN
func startTUN(fd C.int) { func startTUN(fd C.int) {
tunLock.Lock()
now := time.Now()
runTime = &now
go func() { go func() {
tunLock.Lock()
defer tunLock.Unlock() defer tunLock.Unlock()
if tun != nil { if tun != nil {
@@ -43,6 +35,8 @@ func startTUN(fd C.int) {
closer, err := t.Start(f, gateway, portal, dns) closer, err := t.Start(f, gateway, portal, dns)
applyConfig(true)
if err != nil { if err != nil {
log.Errorln("startTUN error: %v", err) log.Errorln("startTUN error: %v", err)
tempTun.Close() tempTun.Close()
@@ -51,30 +45,28 @@ func startTUN(fd C.int) {
tempTun.Closer = closer tempTun.Closer = closer
tun = tempTun tun = tempTun
applyConfig(true)
}() }()
} }
//export getRunTime //export updateMarkSocketPort
func getRunTime() *C.char { func updateMarkSocketPort(markSocketPort C.longlong) bool {
if runTime == nil { tunLock.Lock()
return C.CString("") defer tunLock.Unlock()
} //if tun != nil {
return C.CString(strconv.FormatInt(runTime.UnixMilli(), 10)) // tun.MarkSocketPort = int64(markSocketPort)
//}
return true
} }
//export stopTun //export stopTun
func stopTun() { func stopTun() {
tunLock.Lock()
runTime = nil
go func() { go func() {
tunLock.Lock()
defer tunLock.Unlock() defer tunLock.Unlock()
if tun != nil { if tun != nil {
tun.Close() tun.Close()
applyConfig(true)
tun = nil tun = nil
} }
}() }()
@@ -82,9 +74,6 @@ func stopTun() {
func init() { func init() {
dialer.DefaultSocketHook = func(network, address string, conn syscall.RawConn) error { dialer.DefaultSocketHook = func(network, address string, conn syscall.RawConn) error {
if platform.ShouldBlockConnection() {
return errors.New("blocked")
}
return conn.Control(func(fd uintptr) { return conn.Control(func(fd uintptr) {
if tun != nil { if tun != nil {
tun.MarkSocket(int(fd)) tun.MarkSocket(int(fd))

View File

@@ -82,11 +82,7 @@ class ApplicationState extends State<Application> {
super.initState(); super.initState();
globalState.appController = AppController(context); globalState.appController = AppController(context);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
final currentContext = globalState.navigatorKey.currentContext; globalState.appController.afterInit();
if (currentContext != null) {
globalState.appController = AppController(currentContext);
}
await globalState.appController.init();
globalState.appController.initLink(); globalState.appController.initLink();
_updateGroups(); _updateGroups();
}); });

View File

@@ -100,7 +100,7 @@ class ClashCore {
UsedProxy.GLOBAL.name, UsedProxy.GLOBAL.name,
...(proxies[UsedProxy.GLOBAL.name]["all"] as List).where((e) { ...(proxies[UsedProxy.GLOBAL.name]["all"] as List).where((e) {
final proxy = proxies[e]; final proxy = proxies[e];
return GroupTypeExtension.valueList.contains(proxy['type']) && proxy['hidden'] != true; return GroupTypeExtension.valueList.contains(proxy['type']);
}) })
]; ];
final groupsRaw = groupNames.map((groupName) { final groupsRaw = groupNames.map((groupName) {
@@ -210,24 +210,10 @@ class ClashCore {
clashFFI.startTUN(fd); clashFFI.startTUN(fd);
} }
requestGc() {
clashFFI.forceGc();
}
void stopTun() { void stopTun() {
clashFFI.stopTun(); clashFFI.stopTun();
} }
void setProcessMap(ProcessMapItem processMapItem) {
clashFFI.setProcessMap(json.encode(processMapItem).toNativeUtf8().cast());
}
DateTime? getRunTime() {
final runTimeString = clashFFI.getRunTime().cast<Utf8>().toDartString();
if (runTimeString.isEmpty) return null;
return DateTime.fromMillisecondsSinceEpoch(int.parse(runTimeString));
}
List<Connection> getConnections() { List<Connection> getConnections() {
final connectionsDataRaw = clashFFI.getConnections(); final connectionsDataRaw = clashFFI.getConnections();
final connectionsData = final connectionsData =

View File

@@ -893,14 +893,6 @@ class ClashFFI {
_lookup<ffi.NativeFunction<GoUint8 Function()>>('shutdownClash'); _lookup<ffi.NativeFunction<GoUint8 Function()>>('shutdownClash');
late final _shutdownClash = _shutdownClashPtr.asFunction<int Function()>(); late final _shutdownClash = _shutdownClashPtr.asFunction<int Function()>();
void forceGc() {
return _forceGc();
}
late final _forceGcPtr =
_lookup<ffi.NativeFunction<ffi.Void Function()>>('forceGc');
late final _forceGc = _forceGcPtr.asFunction<void Function()>();
void validateConfig( void validateConfig(
ffi.Pointer<ffi.Char> s, ffi.Pointer<ffi.Char> s,
int port, int port,
@@ -1130,21 +1122,7 @@ class ClashFFI {
_lookup<ffi.NativeFunction<ffi.Void Function()>>('stopLog'); _lookup<ffi.NativeFunction<ffi.Void Function()>>('stopLog');
late final _stopLog = _stopLogPtr.asFunction<void Function()>(); late final _stopLog = _stopLogPtr.asFunction<void Function()>();
void setProcessMap( int startTUN(
ffi.Pointer<ffi.Char> s,
) {
return _setProcessMap(
s,
);
}
late final _setProcessMapPtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>(
'setProcessMap');
late final _setProcessMap =
_setProcessMapPtr.asFunction<void Function(ffi.Pointer<ffi.Char>)>();
void startTUN(
int fd, int fd,
) { ) {
return _startTUN( return _startTUN(
@@ -1153,18 +1131,22 @@ class ClashFFI {
} }
late final _startTUNPtr = late final _startTUNPtr =
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Int)>>('startTUN'); _lookup<ffi.NativeFunction<GoUint8 Function(ffi.Int)>>('startTUN');
late final _startTUN = _startTUNPtr.asFunction<void Function(int)>(); late final _startTUN = _startTUNPtr.asFunction<int Function(int)>();
ffi.Pointer<ffi.Char> getRunTime() { int updateMarkSocketPort(
return _getRunTime(); int markSocketPort,
) {
return _updateMarkSocketPort(
markSocketPort,
);
} }
late final _getRunTimePtr = late final _updateMarkSocketPortPtr =
_lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function()>>( _lookup<ffi.NativeFunction<GoUint8 Function(ffi.LongLong)>>(
'getRunTime'); 'updateMarkSocketPort');
late final _getRunTime = late final _updateMarkSocketPort =
_getRunTimePtr.asFunction<ffi.Pointer<ffi.Char> Function()>(); _updateMarkSocketPortPtr.asFunction<int Function(int)>();
void stopTun() { void stopTun() {
return _stopTun(); return _stopTun();

View File

@@ -14,9 +14,7 @@ abstract mixin class ClashMessageListener {
void onDelay(Delay delay) {} void onDelay(Delay delay) {}
void onProcess(Process process) {} void onProcess(Metadata metadata) {}
void onRequest(Connection connection) {}
void onNow(Now now) {} void onNow(Now now) {}
} }
@@ -43,14 +41,11 @@ class ClashMessage {
listener.onDelay(Delay.fromJson(m.data)); listener.onDelay(Delay.fromJson(m.data));
break; break;
case MessageType.process: case MessageType.process:
listener.onProcess(Process.fromJson(m.data)); listener.onProcess(Metadata.fromJson(m.data));
break; break;
case MessageType.now: case MessageType.now:
listener.onNow(Now.fromJson(m.data)); listener.onNow(Now.fromJson(m.data));
break; break;
case MessageType.request:
listener.onRequest(Connection.fromJson(m.data));
break;
} }
} }
}); });

View File

@@ -7,7 +7,6 @@ class Android {
init() async { init() async {
app?.onExit = () { app?.onExit = () {
clashCore.shutdown(); clashCore.shutdown();
print("adsadda==>");
exit(0); exit(0);
}; };
} }

View File

@@ -18,11 +18,8 @@ const configKey = "config";
const listItemPadding = EdgeInsets.symmetric(horizontal: 16); const listItemPadding = EdgeInsets.symmetric(horizontal: 16);
const double dialogCommonWidth = 300; const double dialogCommonWidth = 300;
const repository = "chen08209/FlClash"; const repository = "chen08209/FlClash";
const defaultExternalController = "127.0.0.1:9090";
const maxMobileWidth = 600; const maxMobileWidth = 600;
const maxLaptopWidth = 840; const maxLaptopWidth = 840;
const geodataLoaderMemconservative = "memconservative";
const geodataLoaderStandard = "standard";
final filter = ImageFilter.blur( final filter = ImageFilter.blur(
sigmaX: 5, sigmaX: 5,
sigmaY: 5, sigmaY: 5,

View File

@@ -29,13 +29,6 @@ class Navigation {
label: "profiles", label: "profiles",
fragment: ProfilesFragment(), fragment: ProfilesFragment(),
), ),
const NavigationItem(
icon: Icon(Icons.ballot),
label: "requests",
fragment: RequestFragment(),
description: "requestsDesc",
modes: [NavigationItemMode.desktop, NavigationItemMode.more],
),
const NavigationItem( const NavigationItem(
icon: Icon(Icons.swap_vert_circle), icon: Icon(Icons.swap_vert_circle),
label: "resources", label: "resources",

View File

@@ -10,7 +10,8 @@ class Picker {
if (Platform.isAndroid) { if (Platform.isAndroid) {
filePickerResult = await FilePicker.platform.pickFiles( filePickerResult = await FilePicker.platform.pickFiles(
withData: true, withData: true,
allowMultiple: false, type: FileType.custom,
allowedExtensions: ['txt', 'conf'],
); );
} else { } else {
filePickerResult = await FilePicker.platform.pickFiles( filePickerResult = await FilePicker.platform.pickFiles(

View File

@@ -145,16 +145,7 @@ class AppController {
if (isNotNeedUpdate == false || profile.type == ProfileType.file) { if (isNotNeedUpdate == false || profile.type == ProfileType.file) {
continue; continue;
} }
try { await updateProfile(profile.id);
await updateProfile(profile.id);
} catch (e) {
appState.addLog(
Log(
logLevel: LogLevel.info,
payload: e.toString(),
),
);
}
} }
} }
@@ -231,21 +222,20 @@ class AppController {
final tagName = data['tag_name']; final tagName = data['tag_name'];
final body = data['body']; final body = data['body'];
final submits = other.parseReleaseBody(body); final submits = other.parseReleaseBody(body);
final textTheme = context.textTheme;
globalState.showMessage( globalState.showMessage(
title: appLocalizations.discoverNewVersion, title: appLocalizations.discoverNewVersion,
message: TextSpan( message: TextSpan(
text: "$tagName \n", text: "$tagName \n",
style: textTheme.headlineSmall, style: context.textTheme.headlineSmall,
children: [ children: [
TextSpan( TextSpan(
text: "\n", text: "\n",
style: textTheme.bodyMedium, style: context.textTheme.bodyMedium,
), ),
for (final submit in submits) for (final submit in submits)
TextSpan( TextSpan(
text: "- $submit \n", text: "- $submit \n",
style: textTheme.bodyMedium, style: context.textTheme.bodyMedium,
), ),
], ],
), ),
@@ -266,29 +256,6 @@ class AppController {
} }
} }
init() async {
if (!config.silentLaunch) {
window?.show();
}
final commonScaffoldState = globalState.homeScaffoldKey.currentState;
if (commonScaffoldState?.mounted == true) {
await commonScaffoldState?.loadingRun(() async {
await globalState.applyProfile(
appState: appState,
config: config,
clashConfig: clashConfig,
);
});
} else {
await globalState.applyProfile(
appState: appState,
config: config,
clashConfig: clashConfig,
);
}
await afterInit();
}
afterInit() async { afterInit() async {
if (config.autoRun) { if (config.autoRun) {
await updateSystemProxy(true); await updateSystemProxy(true);
@@ -298,6 +265,9 @@ class AppController {
} }
autoUpdateProfiles(); autoUpdateProfiles();
updateLogStatus(); updateLogStatus();
if (!config.silentLaunch) {
window?.show();
}
autoCheckUpdate(); autoCheckUpdate();
} }

View File

@@ -1,6 +1,6 @@
// ignore_for_file: constant_identifier_names // ignore_for_file: constant_identifier_names
enum GroupType { Selector, URLTest, Fallback, LoadBalance, Relay } enum GroupType { Selector, URLTest, Fallback }
enum GroupName { GLOBAL, Proxy, Auto, Fallback } enum GroupName { GLOBAL, Proxy, Auto, Fallback }
@@ -56,11 +56,9 @@ enum ProfileType { file, url }
enum ResultType { success, error } enum ResultType { success, error }
enum MessageType { log, tun, delay, process, now, request } enum MessageType { log, tun, delay, process, now }
enum FindProcessMode { always, off }
enum RecoveryOption { enum RecoveryOption {
all, all,
onlyProfiles, onlyProfiles,
} }

View File

@@ -8,13 +8,6 @@ import 'package:fl_clash/widgets/widgets.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
extension AccessControlExtension on AccessControl {
List<String> get currentList => switch (mode) {
AccessControlMode.acceptSelected => acceptList,
AccessControlMode.rejectSelected => rejectList,
};
}
class AccessFragment extends StatefulWidget { class AccessFragment extends StatefulWidget {
const AccessFragment({super.key}); const AccessFragment({super.key});
@@ -90,70 +83,136 @@ class _AccessFragmentState extends State<AccessFragment> {
); );
} }
Widget _buildSearchButton(List<Package> packages) { Widget _buildSelectedAllButton({
return IconButton(
tooltip: appLocalizations.search,
onPressed: () {
showSearch(
context: context,
delegate: AccessControlSearchDelegate(
packages: packages,
),
).then((_) => {setState(() {})});
},
icon: const Icon(Icons.search),
);
}
_buildSelectedAllButton({
required bool isAccessControl,
required bool isSelectedAll, required bool isSelectedAll,
required List<String> allValueList, required List<String> allValueList,
}) { }) {
WidgetsBinding.instance.addPostFrameCallback((_) { return Builder(
final tooltip = isSelectedAll builder: (context) {
? appLocalizations.cancelSelectAll final tooltip = isSelectedAll
: appLocalizations.selectAll; ? appLocalizations.cancelSelectAll
final commonScaffoldState = : appLocalizations.selectAll;
context.findAncestorStateOfType<CommonScaffoldState>(); return IconButton(
commonScaffoldState?.floatingActionButton = DisabledMask( tooltip: tooltip,
status: !isAccessControl, onPressed: () {
child: AbsorbPointer( final config = globalState.appController.config;
absorbing: !isAccessControl, final isAccept =
child: FloatingActionButton ( config.accessControl.mode == AccessControlMode.acceptSelected;
tooltip: tooltip,
onPressed: () {
final config = globalState.appController.config;
final isAccept =
config.accessControl.mode == AccessControlMode.acceptSelected;
if (isSelectedAll) { if (isSelectedAll) {
config.accessControl = switch (isAccept) { config.accessControl = switch (isAccept) {
true => config.accessControl.copyWith( true => config.accessControl.copyWith(
acceptList: [], acceptList: [],
), ),
false => config.accessControl.copyWith( false => config.accessControl.copyWith(
rejectList: [], rejectList: [],
), ),
}; };
} else { } else {
config.accessControl = switch (isAccept) { config.accessControl = switch (isAccept) {
true => config.accessControl.copyWith( true => config.accessControl.copyWith(
acceptList: allValueList, acceptList: allValueList,
), ),
false => config.accessControl.copyWith( false => config.accessControl.copyWith(
rejectList: allValueList, rejectList: allValueList,
), ),
}; };
} }
}, },
child: isSelectedAll icon: isSelectedAll
? const Icon(Icons.deselect) ? const Icon(Icons.deselect)
: const Icon(Icons.select_all), : const Icon(Icons.select_all),
), );
},
);
}
Widget _actionHeader({
required bool isAccessControl,
required List<String> valueList,
required String describe,
required List<String> packageNameList,
}) {
return AbsorbPointer(
absorbing: !isAccessControl,
child: Padding(
padding: const EdgeInsets.only(
top: 4,
bottom: 4,
left: 16,
right: 8,
), ),
); child: Row(
}); mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: IntrinsicHeight(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Row(
children: [
Flexible(
child: Text(
appLocalizations.selected,
style: Theme.of(context)
.textTheme
.labelLarge
?.copyWith(
color:
Theme.of(context).colorScheme.primary,
),
),
),
const Flexible(
child: SizedBox(
width: 8,
),
),
Flexible(
child: Text(
"${valueList.length}",
style: Theme.of(context)
.textTheme
.labelLarge
?.copyWith(
color:
Theme.of(context).colorScheme.primary,
),
),
),
],
),
),
Flexible(
child: Text(describe),
)
],
),
),
),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Flexible(
child: _buildSelectedAllButton(
isSelectedAll: const ListEquality<String>()
.equals(valueList, packageNameList),
allValueList: packageNameList,
),
),
Flexible(child: _buildFilterSystemAppButton()),
Flexible(child: _buildAppProxyModePopup()),
],
),
],
),
),
);
} }
Widget _buildPackageList() { Widget _buildPackageList() {
@@ -193,11 +252,14 @@ class _AccessFragmentState extends State<AccessFragment> {
accessControlMode == AccessControlMode.acceptSelected accessControlMode == AccessControlMode.acceptSelected
? acceptPackages ? acceptPackages
: rejectPackages; : rejectPackages;
final currentList = accessControl.currentList; final currentList =
accessControlMode == AccessControlMode.acceptSelected
? accessControl.acceptList
: accessControl.rejectList;
final currentPackages = isFilterSystemApp final currentPackages = isFilterSystemApp
? packages ? packages
.where((element) => element.isSystem == false) .where((element) => element.isSystem == false)
.toList() .toList()
: packages; : packages;
final packageNameList = final packageNameList =
currentPackages.map((e) => e.packageName).toList(); currentPackages.map((e) => e.packageName).toList();
@@ -206,91 +268,15 @@ class _AccessFragmentState extends State<AccessFragment> {
accessControlMode == AccessControlMode.acceptSelected accessControlMode == AccessControlMode.acceptSelected
? appLocalizations.accessControlAllowDesc ? appLocalizations.accessControlAllowDesc
: appLocalizations.accessControlNotAllowDesc; : appLocalizations.accessControlNotAllowDesc;
_buildSelectedAllButton(
isAccessControl: isAccessControl,
isSelectedAll: valueList.length == packageNameList.length,
allValueList: packageNameList,
);
return DisabledMask( return DisabledMask(
status: !isAccessControl, status: !isAccessControl,
child: Column( child: Column(
children: [ children: [
AbsorbPointer( _actionHeader(
absorbing: !isAccessControl, isAccessControl: isAccessControl,
child: Padding( valueList: valueList,
padding: const EdgeInsets.only( describe: describe,
top: 4, packageNameList: packageNameList,
bottom: 4,
left: 16,
right: 8,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: IntrinsicHeight(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Row(
children: [
Flexible(
child: Text(
appLocalizations.selected,
style: Theme.of(context)
.textTheme
.labelLarge
?.copyWith(
color: Theme.of(context)
.colorScheme
.primary,
),
),
),
const Flexible(
child: SizedBox(
width: 8,
),
),
Flexible(
child: Text(
"${valueList.length}",
style: Theme.of(context)
.textTheme
.labelLarge
?.copyWith(
color: Theme.of(context)
.colorScheme
.primary,
),
),
),
],
),
),
Flexible(
child: Text(describe),
)
],
),
),
),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Flexible(
child: _buildSearchButton(currentPackages)),
Flexible(child: _buildFilterSystemAppButton()),
Flexible(child: _buildAppProxyModePopup()),
],
),
],
),
),
), ),
Expanded( Expanded(
flex: 1, flex: 1,
@@ -443,111 +429,3 @@ class PackageListItem extends StatelessWidget {
); );
} }
} }
class AccessControlSearchDelegate extends SearchDelegate {
final List<Package> packages;
AccessControlSearchDelegate({
required this.packages,
});
List<Package> get _results {
final lowQuery = query.toLowerCase();
return packages
.where(
(package) =>
package.label.toLowerCase().contains(lowQuery) ||
package.packageName.contains(lowQuery),
)
.toList();
}
@override
List<Widget>? buildActions(BuildContext context) {
return [
IconButton(
onPressed: () {
if (query.isEmpty) {
close(context, null);
return;
}
query = '';
},
icon: const Icon(Icons.clear),
),
const SizedBox(
width: 8,
)
];
}
@override
Widget? buildLeading(BuildContext context) {
return IconButton(
onPressed: () {
close(context, null);
},
icon: const Icon(Icons.arrow_back),
);
}
Widget _packageList(List<Package> packages) {
return Selector<Config, PackageListSelectorState>(
selector: (_, config) => PackageListSelectorState(
accessControl: config.accessControl,
isAccessControl: config.isAccessControl,
),
builder: (context, state, __) {
final accessControl = state.accessControl;
final isAccessControl = state.isAccessControl;
final accessControlMode = accessControl.mode;
final currentList = accessControl.currentList;
final packageNameList =
this.packages.map((e) => e.packageName).toList();
final valueList = currentList.intersection(packageNameList);
return DisabledMask(
status: !isAccessControl,
child: ListView.builder(
itemCount: packages.length,
itemBuilder: (_, index) {
final package = packages[index];
return PackageListItem(
key: Key(package.packageName),
package: package,
value: valueList.contains(package.packageName),
isActive: isAccessControl,
onChanged: (value) {
if (value == true) {
valueList.add(package.packageName);
} else {
valueList.remove(package.packageName);
}
final config = globalState.appController.config;
if (accessControlMode == AccessControlMode.acceptSelected) {
config.accessControl = config.accessControl.copyWith(
acceptList: valueList,
);
} else {
config.accessControl = config.accessControl.copyWith(
rejectList: valueList,
);
}
},
);
},
),
);
},
);
}
@override
Widget buildResults(BuildContext context) {
return buildSuggestions(context);
}
@override
Widget buildSuggestions(BuildContext context) {
return _packageList(_results);
}
}

View File

@@ -1,5 +1,3 @@
import 'dart:io';
import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/models/models.dart';
@@ -39,132 +37,16 @@ class _ConfigFragmentState extends State<ConfigFragment> {
} }
} }
_buildAppSection() { _updateLoglevel(LogLevel? logLevel) {
final items = [ if (logLevel == null ||
if (Platform.isAndroid) logLevel == globalState.appController.clashConfig.logLevel) return;
Selector<Config, bool>( globalState.appController.clashConfig.logLevel = logLevel;
selector: (_, config) => config.allowBypass, globalState.appController.updateClashConfigDebounce();
builder: (_, allowBypass, __) {
return ListItem.switchItem(
leading: const Icon(Icons.arrow_forward_outlined),
title: Text(appLocalizations.allowBypass),
subtitle: Text(appLocalizations.allowBypassDesc),
delegate: SwitchDelegate(
value: allowBypass,
onChanged: (bool value) async {
final appController = globalState.appController;
appController.config.allowBypass = value;
},
),
);
},
),
if (Platform.isAndroid)
Selector<Config, bool>(
selector: (_, config) => config.systemProxy,
builder: (_, systemProxy, __) {
return ListItem.switchItem(
leading: const Icon(Icons.settings_ethernet),
title: Text(appLocalizations.systemProxy),
subtitle: Text(appLocalizations.systemProxyDesc),
delegate: SwitchDelegate(
value: systemProxy,
onChanged: (bool value) async {
final appController = globalState.appController;
appController.config.systemProxy = value;
},
),
);
},
),
Selector<Config, bool>(
selector: (_, config) => config.isCompatible,
builder: (_, isCompatible, __) {
return ListItem.switchItem(
leading: const Icon(Icons.expand_outlined),
title: Text(appLocalizations.compatible),
subtitle: Text(appLocalizations.compatibleDesc),
delegate: SwitchDelegate(
value: isCompatible,
onChanged: (bool value) async {
final appController = globalState.appController;
appController.config.isCompatible = value;
await appController.updateClashConfig(isPatch: false);
await appController.updateGroups();
appController.changeProxy();
},
),
);
},
),
];
return Section(
title: appLocalizations.app,
child: Column(
children: [
for (final item in items) ...[
item,
if (items.last != item)
const Divider(
height: 0,
)
]
],
),
);
} }
_showLogLevelDialog(LogLevel value) { @override
globalState.showCommonDialog( Widget build(BuildContext context) {
child: AlertDialog( List<Widget> items = [
title: Text(appLocalizations.logLevel),
contentPadding: const EdgeInsets.symmetric(
horizontal: 8,
vertical: 16,
),
content: SizedBox(
width: 250,
child: Wrap(
children: [
for (final logLevel in LogLevel.values)
ListItem.radio(
delegate: RadioDelegate<LogLevel>(
value: logLevel,
groupValue: value,
onChanged: (LogLevel? value) {
if (value == null) {
return;
}
final appController = globalState.appController;
appController.clashConfig.logLevel = value;
appController.updateClashConfigDebounce();
Navigator.of(context).pop();
},
),
title: Text(logLevel.name),
)
],
),
),
),
);
}
_buildGeneralSection() {
final items = [
Selector<ClashConfig, LogLevel>(
selector: (_, clashConfig) => clashConfig.logLevel,
builder: (_, value, __) {
return ListItem(
leading: const Icon(Icons.info_outline),
title: Text(appLocalizations.logLevel),
subtitle: Text(value.name),
onTab: () {
_showLogLevelDialog(value);
},
);
},
),
Selector<ClashConfig, int>( Selector<ClashConfig, int>(
selector: (_, clashConfig) => clashConfig.mixedPort, selector: (_, clashConfig) => clashConfig.mixedPort,
builder: (_, mixedPort, __) { builder: (_, mixedPort, __) {
@@ -172,9 +54,9 @@ class _ConfigFragmentState extends State<ConfigFragment> {
onTab: () { onTab: () {
_modifyMixedPort(mixedPort); _modifyMixedPort(mixedPort);
}, },
leading: const Icon(Icons.adjust_outlined), padding: const EdgeInsets.symmetric(horizontal: 16,vertical: 4),
leading: const Icon(Icons.adjust),
title: Text(appLocalizations.proxyPort), title: Text(appLocalizations.proxyPort),
subtitle: Text(appLocalizations.proxyPortDesc),
trailing: FilledButton.tonal( trailing: FilledButton.tonal(
onPressed: () { onPressed: () {
_modifyMixedPort(mixedPort); _modifyMixedPort(mixedPort);
@@ -186,24 +68,6 @@ class _ConfigFragmentState extends State<ConfigFragment> {
); );
}, },
), ),
Selector<ClashConfig, bool>(
selector: (_, clashConfig) => clashConfig.ipv6,
builder: (_, ipv6, __) {
return ListItem.switchItem(
leading: const Icon(Icons.water_outlined),
title: const Text("Ipv6"),
subtitle: Text(appLocalizations.ipv6Desc),
delegate: SwitchDelegate(
value: ipv6,
onChanged: (bool value) async {
final appController = globalState.appController;
appController.clashConfig.ipv6 = value;
appController.updateClashConfigDebounce();
},
),
);
},
),
Selector<ClashConfig, bool>( Selector<ClashConfig, bool>(
selector: (_, clashConfig) => clashConfig.allowLan, selector: (_, clashConfig) => clashConfig.allowLan,
builder: (_, allowLan, __) { builder: (_, allowLan, __) {
@@ -222,133 +86,92 @@ class _ConfigFragmentState extends State<ConfigFragment> {
); );
}, },
), ),
Selector<ClashConfig, bool>( // if (system.isDesktop)
selector: (_, clashConfig) => clashConfig.unifiedDelay, // Selector<ClashConfig, bool>(
builder: (_, unifiedDelay, __) { // selector: (_, clashConfig) => clashConfig.tun.enable,
// builder: (_, tunEnable, __) {
// return ListItem.switchItem(
// leading: const Icon(Icons.support),
// title: Text(appLocalizations.tun),
// subtitle: Text(appLocalizations.tunDesc),
// delegate: SwitchDelegate(
// value: tunEnable,
// onChanged: (bool value) async {
// final clashConfig = context.read<ClashConfig>();
// clashConfig.tun = Tun(enable: value);
// globalState.appController.updateClashConfigDebounce();
// },
// ),
// );
// },
// ),
Selector<Config, bool>(
selector: (_, config) => config.isCompatible,
builder: (_, isCompatible, __) {
return ListItem.switchItem( return ListItem.switchItem(
leading: const Icon(Icons.compress_outlined), leading: const Icon(Icons.expand),
title: Text(appLocalizations.unifiedDelay), title: Text(appLocalizations.compatible),
subtitle: Text(appLocalizations.unifiedDelayDesc), subtitle: Text(appLocalizations.compatibleDesc),
delegate: SwitchDelegate( delegate: SwitchDelegate(
value: unifiedDelay, value: isCompatible,
onChanged: (bool value) async { onChanged: (bool value) async {
final appController = globalState.appController; final appController = globalState.appController;
appController.clashConfig.unifiedDelay = value; appController.config.isCompatible = value;
appController.updateClashConfigDebounce(); await appController.updateClashConfig(isPatch: false);
await appController.updateGroups();
appController.changeProxy();
}, },
), ),
); );
}, },
), ),
Selector<ClashConfig, bool>( Padding(
selector: (_, clashConfig) => padding: kMaterialListPadding,
clashConfig.findProcessMode == FindProcessMode.always, child: Selector<ClashConfig, LogLevel>(
builder: (_, findProcess, __) { selector: (_, clashConfig) => clashConfig.logLevel,
return ListItem.switchItem( builder: (_, value, __) {
leading: const Icon(Icons.polymer_outlined), return ListItem(
title: Text(appLocalizations.findProcessMode), leading: const Icon(Icons.feedback),
subtitle: Text(appLocalizations.findProcessModeDesc), title: Text(appLocalizations.logLevel),
delegate: SwitchDelegate( trailing: SizedBox(
value: findProcess, height: 48,
onChanged: (bool value) async { child: DropdownMenu<LogLevel>(
final appController = globalState.appController; width: 124,
appController.clashConfig.findProcessMode = inputDecorationTheme: const InputDecorationTheme(
value ? FindProcessMode.always : FindProcessMode.off; filled: true,
appController.updateClashConfigDebounce(); contentPadding: EdgeInsets.symmetric(
}, vertical: 5,
), horizontal: 16,
); ),
}, ),
), initialSelection: value,
Selector<ClashConfig, bool>( dropdownMenuEntries: [
selector: (_, clashConfig) => clashConfig.tcpConcurrent, for (final logLevel in LogLevel.values)
builder: (_, tcpConcurrent, __) { DropdownMenuEntry<LogLevel>(
return ListItem.switchItem( value: logLevel,
leading: const Icon(Icons.double_arrow_outlined), label: logLevel.name,
title: Text(appLocalizations.tcpConcurrent), )
subtitle: Text(appLocalizations.tcpConcurrentDesc), ],
delegate: SwitchDelegate( onSelected: _updateLoglevel,
value: tcpConcurrent, ),
onChanged: (bool value) async { ),
final appController = globalState.appController; );
appController.clashConfig.tcpConcurrent = value; },
appController.updateClashConfigDebounce(); ),
},
),
);
},
),
Selector<ClashConfig, bool>(
selector: (_, clashConfig) =>
clashConfig.geodataLoader == geodataLoaderMemconservative,
builder: (_, memconservative, __) {
return ListItem.switchItem(
leading: const Icon(Icons.memory),
title: Text(appLocalizations.geodataLoader),
subtitle: Text(appLocalizations.geodataLoaderDesc),
delegate: SwitchDelegate(
value: memconservative,
onChanged: (bool value) async {
final appController = globalState.appController;
appController.clashConfig.geodataLoader = value
? geodataLoaderMemconservative
: geodataLoaderStandard;
appController.updateClashConfigDebounce();
},
),
);
},
),
Selector<ClashConfig, bool>(
selector: (_, clashConfig) => clashConfig.externalController.isNotEmpty,
builder: (_, hasExternalController, __) {
return ListItem.switchItem(
leading: const Icon(Icons.api_outlined),
title: Text(appLocalizations.externalController),
subtitle: Text(appLocalizations.externalControllerDesc),
delegate: SwitchDelegate(
value: hasExternalController,
onChanged: (bool value) async {
final appController = globalState.appController;
appController.clashConfig.externalController =
value ? defaultExternalController : '';
appController.updateClashConfigDebounce();
},
),
);
},
), ),
]; ];
return Section( return ListView.separated(
title: appLocalizations.general,
child: Column(
children: [
for (final item in items) ...[
item,
if (items.last != item)
const Divider(
height: 0,
)
]
],
),
);
}
@override
Widget build(BuildContext context) {
List<Widget> items = [
_buildAppSection(),
_buildGeneralSection(),
];
return ListView.builder(
padding: const EdgeInsets.only(bottom: 16),
itemBuilder: (_, index) { itemBuilder: (_, index) {
return Container( return Container(
alignment: Alignment.center, alignment: Alignment.center,
child: items[index], child: items[index],
); );
}, },
separatorBuilder: (_, __) {
return const Divider(
height: 0,
);
},
itemCount: items.length, itemCount: items.length,
); );
} }

View File

@@ -1,140 +1,140 @@
// import 'dart:async'; import 'dart:async';
//
// import 'package:fl_clash/clash/core.dart'; import 'package:fl_clash/clash/core.dart';
// import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/models/models.dart';
// import 'package:fl_clash/plugins/app.dart'; import 'package:fl_clash/plugins/app.dart';
// import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
// import 'package:fl_clash/widgets/widgets.dart'; import 'package:fl_clash/widgets/widgets.dart';
// import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
//
// class ConnectionsFragment extends StatefulWidget { class ConnectionsFragment extends StatefulWidget {
// const ConnectionsFragment({super.key}); const ConnectionsFragment({super.key});
//
// @override @override
// State<ConnectionsFragment> createState() => _ConnectionsFragmentState(); State<ConnectionsFragment> createState() => _ConnectionsFragmentState();
// } }
//
// class _ConnectionsFragmentState extends State<ConnectionsFragment> { class _ConnectionsFragmentState extends State<ConnectionsFragment> {
// final connectionsNotifier = ValueNotifier<List<Connection>>([]); final connectionsNotifier = ValueNotifier<List<Connection>>([]);
// Map<String, String?> idPackageNameMap = {}; Map<String, String?> idPackageNameMap = {};
//
// Timer? timer; Timer? timer;
//
// @override @override
// void initState() { void initState() {
// super.initState(); super.initState();
// WidgetsBinding.instance.addPostFrameCallback((timeStamp) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
// _getConnections(); _getConnections();
// if (timer != null) { if (timer != null) {
// timer?.cancel(); timer?.cancel();
// timer = null; timer = null;
// } }
// timer = Timer.periodic(const Duration(seconds: 3), (timer) { timer = Timer.periodic(const Duration(seconds: 3), (timer) {
// if (mounted) { if (mounted) {
// _getConnections(); _getConnections();
// } }
// }); });
// }); });
// } }
//
// _getConnections() { _getConnections() {
// connectionsNotifier.value = clashCore connectionsNotifier.value = clashCore
// .getConnections(); .getConnections();
// } }
//
// @override @override
// void dispose() { void dispose() {
// super.dispose(); super.dispose();
// timer?.cancel(); timer?.cancel();
// timer = null; timer = null;
// } }
//
// Future<ImageProvider?> _getPackageIconWithConnection( Future<ImageProvider?> _getPackageIconWithConnection(
// Connection connection) async { Connection connection) async {
// final uid = connection.metadata.uid; final uid = connection.metadata.uid;
// // if(globalState.packageNameMap[uid] == null){ // if(globalState.packageNameMap[uid] == null){
// // globalState.packageNameMap[uid] = await app?.getPackageName(connection.metadata); // globalState.packageNameMap[uid] = await app?.getPackageName(connection.metadata);
// // } // }
// final packageName = globalState.packageNameMap[uid]; final packageName = globalState.packageNameMap[uid];
// if(packageName == null) return null; if(packageName == null) return null;
// return await app?.getPackageIcon(packageName); return await app?.getPackageIcon(packageName);
// } }
//
// @override @override
// Widget build(BuildContext context) { Widget build(BuildContext context) {
// return ValueListenableBuilder<List<Connection>>( return ValueListenableBuilder<List<Connection>>(
// valueListenable: connectionsNotifier, valueListenable: connectionsNotifier,
// builder: (_, List<Connection> connections, __) { builder: (_, List<Connection> connections, __) {
// if (connections.isEmpty) { if (connections.isEmpty) {
// return const NullStatus( return const NullStatus(
// label: "未开启代理,或者没有连接数据", label: "未开启代理,或者没有连接数据",
// ); );
// } }
// return ListView.separated( return ListView.separated(
// physics: const AlwaysScrollableScrollPhysics(), physics: const AlwaysScrollableScrollPhysics(),
// itemBuilder: (_, index) { itemBuilder: (_, index) {
// final connection = connections[index]; final connection = connections[index];
// return ListTile( return ListTile(
// titleAlignment: ListTileTitleAlignment.top, titleAlignment: ListTileTitleAlignment.top,
// leading: Container( leading: Container(
// margin: const EdgeInsets.only(top: 4), margin: const EdgeInsets.only(top: 4),
// width: 48, width: 48,
// height: 48, height: 48,
// child: FutureBuilder<ImageProvider?>( child: FutureBuilder<ImageProvider?>(
// future: _getPackageIconWithConnection(connection), future: _getPackageIconWithConnection(connection),
// builder: (_, snapshot) { builder: (_, snapshot) {
// if (!snapshot.hasData && snapshot.data == null) { if (!snapshot.hasData && snapshot.data == null) {
// return Container(); return Container();
// } else { } else {
// return Image( return Image(
// image: snapshot.data!, image: snapshot.data!,
// gaplessPlayback: true, gaplessPlayback: true,
// width: 48, width: 48,
// height: 48, height: 48,
// ); );
// } }
// }, },
// ), ),
// ), ),
// contentPadding: contentPadding:
// const EdgeInsets.symmetric(vertical: 12, horizontal: 16), const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
// title: Column( title: Column(
// crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
// children: [ children: [
// Text(connection.metadata.host.isNotEmpty Text(connection.metadata.host.isNotEmpty
// ? connection.metadata.host ? connection.metadata.host
// : connection.metadata.destinationIP), : connection.metadata.destinationIP),
// Padding( Padding(
// padding: const EdgeInsets.only( padding: const EdgeInsets.only(
// top: 12, top: 12,
// ), ),
// child: Wrap( child: Wrap(
// runSpacing: 8, runSpacing: 8,
// spacing: 8, spacing: 8,
// children: [ children: [
// for (final chain in connection.chains) for (final chain in connection.chains)
// CommonChip( CommonChip(
// label: chain, label: chain,
// ), ),
// ], ],
// ), ),
// ), ),
// ], ],
// ), ),
// trailing: IconButton( trailing: IconButton(
// icon: const Icon(Icons.block), icon: const Icon(Icons.block),
// onPressed: () {}, onPressed: () {},
// ), ),
// ); );
// }, },
// separatorBuilder: (BuildContext context, int index) { separatorBuilder: (BuildContext context, int index) {
// return const Divider( return const Divider(
// height: 0, height: 0,
// ); );
// }, },
// itemCount: connections.length, itemCount: connections.length,
// ); );
// }, },
// ); );
// } }
// } }

View File

@@ -25,7 +25,6 @@ class _NetworkDetectionState extends State<NetworkDetection> {
bool isStart, bool isStart,
) async { ) async {
if (!isInit) return; if (!isInit) return;
timeoutNotifier.value = false;
if (_preIsStart == false && _preIsStart == isStart) return; if (_preIsStart == false && _preIsStart == isStart) return;
if (cancelToken != null) { if (cancelToken != null) {
cancelToken!.cancel(); cancelToken!.cancel();
@@ -152,10 +151,9 @@ class _NetworkDetectionState extends State<NetworkDetection> {
builder: (_, timeout, __) { builder: (_, timeout, __) {
if (timeout) { if (timeout) {
return Text( return Text(
"timeout", appLocalizations.ipCheckTimeout,
style: context.textTheme.titleMedium style: context.textTheme.titleLarge
?.copyWith(color: Colors.red) ?.toSoftBold(),
.toSoftBold(),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
); );

View File

@@ -9,5 +9,4 @@ export 'config.dart';
export 'application_setting.dart'; export 'application_setting.dart';
export 'about.dart'; export 'about.dart';
export 'backup_and_recovery.dart'; export 'backup_and_recovery.dart';
export 'resources.dart'; export 'resources.dart';
export 'requests.dart';

View File

@@ -1,6 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:collection/collection.dart';
import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
@@ -23,21 +22,14 @@ class _LogsFragmentState extends State<LogsFragment> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
final appState = globalState.appController.appState; logsNotifier.value = context.read<AppState>().logs;
logsNotifier.value = List<Log>.from(appState.logs);
if (timer != null) { if (timer != null) {
timer?.cancel(); timer?.cancel();
timer = null; timer = null;
} }
timer = Timer.periodic(const Duration(milliseconds: 200), (timer) { timer = Timer.periodic(const Duration(milliseconds: 200), (timer) {
final logs = List<Log>.from(appState.logs); logsNotifier.value = globalState.appController.appState.logs;
if (!const ListEquality<Log>().equals(
logsNotifier.value,
logs,
)) {
logsNotifier.value = logs;
}
}); });
}); });
} }

View File

@@ -152,7 +152,6 @@ class _EditProfileState extends State<EditProfile> {
vertical: 16, vertical: 16,
), ),
child: ListView.separated( child: ListView.separated(
primary: true,
itemBuilder: (_, index) { itemBuilder: (_, index) {
return items[index]; return items[index];
}, },

View File

@@ -17,16 +17,9 @@ enum ProfileActions {
delete, delete,
} }
class ProfilesFragment extends StatefulWidget { class ProfilesFragment extends StatelessWidget {
const ProfilesFragment({super.key}); const ProfilesFragment({super.key});
@override
State<ProfilesFragment> createState() => _ProfilesFragmentState();
}
class _ProfilesFragmentState extends State<ProfilesFragment> {
final hasPadding = ValueNotifier<bool>(false);
_handleShowAddExtendPage() { _handleShowAddExtendPage() {
showExtendPage( showExtendPage(
globalState.navigatorKey.currentState!.context, globalState.navigatorKey.currentState!.context,
@@ -48,7 +41,7 @@ class _ProfilesFragmentState extends State<ProfilesFragment> {
} }
} }
_initScaffoldState() { _initScaffoldState(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback( WidgetsBinding.instance.addPostFrameCallback(
(_) { (_) {
final commonScaffoldState = final commonScaffoldState =
@@ -62,7 +55,7 @@ class _ProfilesFragmentState extends State<ProfilesFragment> {
}, },
); );
}, },
icon: const Icon(Icons.sync), icon: const Icon(Icons.download),
), ),
const SizedBox( const SizedBox(
width: 8, width: 8,
@@ -85,7 +78,7 @@ class _ProfilesFragmentState extends State<ProfilesFragment> {
selector: (_, appState) => appState.currentLabel == 'profiles', selector: (_, appState) => appState.currentLabel == 'profiles',
builder: (_, isCurrent, child) { builder: (_, isCurrent, child) {
if (isCurrent) { if (isCurrent) {
_initScaffoldState(); _initScaffoldState(context);
} }
return child!; return child!;
}, },
@@ -105,46 +98,27 @@ class _ProfilesFragmentState extends State<ProfilesFragment> {
final isMobile = state.viewMode == ViewMode.mobile; final isMobile = state.viewMode == ViewMode.mobile;
return Align( return Align(
alignment: Alignment.topCenter, alignment: Alignment.topCenter,
child: NotificationListener<ScrollNotification>( child: SingleChildScrollView(
onNotification: (scrollNotification) { padding: !isMobile
WidgetsBinding.instance.addPostFrameCallback((_) { ? const EdgeInsets.symmetric(
hasPadding.value = horizontal: 16,
scrollNotification.metrics.maxScrollExtent > 0; vertical: 16,
}); )
return true; : EdgeInsets.zero,
}, child: Grid(
child: ValueListenableBuilder( mainAxisSpacing: isMobile ? 8 : 16,
valueListenable: hasPadding, crossAxisSpacing: 16,
builder: (_, hasPadding, __) { crossAxisCount: columns,
return SingleChildScrollView( children: [
padding: !isMobile for (final profile in state.profiles)
? EdgeInsets.only( GridItem(
left: 16, child: ProfileItem(
right: 16, profile: profile,
top: 16, groupValue: state.currentProfileId,
bottom: 16 + (hasPadding ? 56 : 0), onChanged: globalState.appController.changeProfile,
) ),
: EdgeInsets.only(
bottom: 0 + (hasPadding ? 56 : 0),
),
child: Grid(
mainAxisSpacing: isMobile ? 8 : 16,
crossAxisSpacing: 16,
crossAxisCount: columns,
children: [
for (final profile in state.profiles)
GridItem(
child: ProfileItem(
profile: profile,
groupValue: state.currentProfileId,
onChanged:
globalState.appController.changeProfile,
),
),
],
), ),
); ],
},
), ),
), ),
); );

View File

@@ -1,4 +1,3 @@
import 'package:collection/collection.dart';
import 'package:fl_clash/clash/clash.dart'; import 'package:fl_clash/clash/clash.dart';
import 'package:fl_clash/state.dart'; import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@@ -60,18 +59,6 @@ class _ProxiesFragmentState extends State<ProxiesFragment>
}); });
} }
_handleTabControllerChange() {
final indexIsChanging = _tabController?.indexIsChanging ?? false;
if (indexIsChanging) return;
final index = _tabController?.index;
if(index == null) return;
final appController = globalState.appController;
final currentGroups = appController.appState.currentGroups;
if (currentGroups.length > index) {
appController.config.updateCurrentGroupName(currentGroups[index].name);
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Selector<AppState, bool>( return Selector<AppState, bool>(
@@ -82,34 +69,26 @@ class _ProxiesFragmentState extends State<ProxiesFragment>
} }
return child!; return child!;
}, },
child: Selector2<AppState, Config, ProxiesSelectorState>( child: Selector3<AppState, Config, ClashConfig, ProxiesSelectorState>(
selector: (_, appState, config) { selector: (_, appState, config, clashConfig) {
final currentGroups = appState.currentGroups; final currentGroups = appState.currentGroups;
final groupNames = currentGroups.map((e) => e.name).toList(); final groupNames = currentGroups.map((e) => e.name).toList();
return ProxiesSelectorState( return ProxiesSelectorState(
groupNames: groupNames, groupNames: groupNames,
currentGroupName: config.currentGroupName,
); );
}, },
shouldRebuild: (prev, next) { shouldRebuild: (prev, next) {
if (!const ListEquality<String>() if (prev.groupNames.length != next.groupNames.length) {
.equals(prev.groupNames, next.groupNames)) {
_tabController?.removeListener(_handleTabControllerChange);
_tabController?.dispose(); _tabController?.dispose();
_tabController = null; _tabController = null;
return true;
} }
return false; return prev != next;
}, },
builder: (_, state, __) { builder: (_, state, __) {
final index = state.groupNames.indexWhere(
(item) => item == state.currentGroupName,
);
_tabController ??= TabController( _tabController ??= TabController(
length: state.groupNames.length, length: state.groupNames.length,
initialIndex: index == -1 ? 0 : index,
vsync: this, vsync: this,
)..addListener(_handleTabControllerChange); );
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -220,16 +199,10 @@ class ProxiesTabView extends StatelessWidget {
_delayTest(List<Proxy> proxies) async { _delayTest(List<Proxy> proxies) async {
for (final proxy in proxies) { for (final proxy in proxies) {
final appController = globalState.appController;
final proxyName =
appController.appState.getRealProxyName(proxy.name) ?? proxy.name;
globalState.appController.setDelay( globalState.appController.setDelay(
Delay( Delay(name: proxy.name, value: 0),
name: proxyName,
value: 0,
),
); );
clashCore.getDelay(proxyName).then((delay) { clashCore.getDelay(proxy.name).then((delay) {
globalState.appController.setDelay(delay); globalState.appController.setDelay(delay);
}); });
} }
@@ -461,7 +434,7 @@ class _DelayTestButtonContainerState extends State<DelayTestButtonContainer>
_controller = AnimationController( _controller = AnimationController(
vsync: this, vsync: this,
duration: const Duration( duration: const Duration(
milliseconds: 200, milliseconds: 600,
), ),
); );
_scale = Tween<double>( _scale = Tween<double>(

View File

@@ -1,178 +0,0 @@
import 'dart:async';
import 'dart:io';
import 'package:collection/collection.dart';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/plugins/app.dart';
import 'package:fl_clash/state.dart';
import 'package:fl_clash/widgets/widgets.dart';
import 'package:flutter/material.dart';
class RequestFragment extends StatefulWidget {
const RequestFragment({super.key});
@override
State<RequestFragment> createState() => _RequestFragmentState();
}
class _RequestFragmentState extends State<RequestFragment> {
final requestsNotifier = ValueNotifier<List<Connection>>([]);
final ScrollController _scrollController = ScrollController(
keepScrollOffset: false,
);
Timer? timer;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
final appState = globalState.appController.appState;
requestsNotifier.value = List<Connection>.from(appState.requests);
if (timer != null) {
timer?.cancel();
timer = null;
}
timer = Timer.periodic(const Duration(milliseconds: 200), (timer) {
final requests = List<Connection>.from(appState.requests);
if (!const ListEquality<Connection>().equals(
requestsNotifier.value,
requests,
)) {
requestsNotifier.value = requests;
}
});
});
}
@override
void dispose() {
super.dispose();
timer?.cancel();
_scrollController.dispose();
timer = null;
}
@override
Widget build(BuildContext context) {
return ValueListenableBuilder<List<Connection>>(
valueListenable: requestsNotifier,
builder: (_, List<Connection> connections, __) {
if (connections.isEmpty) {
return NullStatus(
label: appLocalizations.nullRequestsDesc,
);
}
connections = connections.reversed.toList();
return ListView.separated(
controller: _scrollController,
itemBuilder: (_, index) {
final connection = connections[index];
return RequestItem(
key: Key(connection.id),
connection: connection,
);
},
separatorBuilder: (BuildContext context, int index) {
return const Divider(
height: 0,
);
},
itemCount: connections.length,
);
},
);
}
}
class RequestItem extends StatelessWidget {
final Connection connection;
const RequestItem({
super.key,
required this.connection,
});
Future<ImageProvider?> _getPackageIcon(Connection connection) async {
return await app?.getPackageIcon(connection.metadata.process);
}
String _getRequestText(Metadata metadata) {
var text = "${metadata.network}:://";
final ips = [
metadata.host,
metadata.destinationIP,
].where((ip) => ip.isNotEmpty);
text += ips.join("/");
text += ":${metadata.destinationPort}";
return text;
}
String _getSourceText(Connection connection) {
final metadata = connection.metadata;
if (metadata.process.isEmpty) {
return connection.start.lastUpdateTimeDesc;
}
return "${metadata.process} · ${connection.start.lastUpdateTimeDesc}";
}
@override
Widget build(BuildContext context) {
return ListTile(
titleAlignment: ListTileTitleAlignment.top,
leading: Platform.isAndroid
? Container(
margin: const EdgeInsets.only(top: 4),
width: 48,
height: 48,
child: FutureBuilder<ImageProvider?>(
future: _getPackageIcon(connection),
builder: (_, snapshot) {
if (!snapshot.hasData && snapshot.data == null) {
return Container();
} else {
return Image(
image: snapshot.data!,
gaplessPlayback: true,
width: 48,
height: 48,
);
}
},
),
)
: null,
title: Text(
_getRequestText(connection.metadata),
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
height: 12,
),
Text(
_getSourceText(connection),
),
const SizedBox(
height: 12,
),
Wrap(
runSpacing: 8,
spacing: 8,
children: [
for (final chain in connection.chains)
CommonChip(
label: chain,
),
],
),
const SizedBox(
height: 12,
),
],
),
);
}
}

View File

@@ -166,7 +166,6 @@ class _ToolboxFragmentState extends State<ToolsFragment> {
delegate: OpenDelegate( delegate: OpenDelegate(
title: appLocalizations.override, title: appLocalizations.override,
widget: const ConfigFragment(), widget: const ConfigFragment(),
extendPageWidth: 360,
), ),
), ),
ListItem.open( ListItem.open(

View File

@@ -111,7 +111,6 @@
"noMoreInfoDesc": "No more info", "noMoreInfoDesc": "No more info",
"profileParseErrorDesc": "profile parse error", "profileParseErrorDesc": "profile parse error",
"proxyPort": "ProxyPort", "proxyPort": "ProxyPort",
"proxyPortDesc": "Set the clash listening port",
"port": "Port", "port": "Port",
"logLevel": "LogLevel", "logLevel": "LogLevel",
"show": "Show", "show": "Show",
@@ -161,25 +160,5 @@
"checking": "Checking...", "checking": "Checking...",
"country": "Country", "country": "Country",
"checkError": "Check error", "checkError": "Check error",
"ipCheckTimeout": "Ip check timeout", "ipCheckTimeout": "Ip check timeout"
"search": "Search",
"allowBypass": "Allow applications to bypass VPN",
"allowBypassDesc": "Some apps can bypass VPN when turned on",
"externalController": "ExternalController",
"externalControllerDesc": "Once enabled, the clash kernel can be controlled on port 9090",
"ipv6Desc": "When turned on it will be able to receive ipv6 traffic",
"app": "App",
"general": "General",
"systemProxyDesc": "Attach HTTP proxy to VpnService",
"unifiedDelay": "Unified delay",
"unifiedDelayDesc": "Remove extra delays such as handshaking",
"tcpConcurrent": "Tcp concurrent",
"tcpConcurrentDesc": "Enabling it will allow tcp concurrency",
"geodataLoader": "Geo Low Memory Mode",
"geodataLoaderDesc": "Enabling will use the Geo low memory loader",
"requests": "Requests",
"requestsDesc": "View recently requested data",
"nullRequestsDesc": "No proxy or no request",
"findProcessMode": "Find process",
"findProcessModeDesc": "There is a risk of flashback after opening"
} }

View File

@@ -111,7 +111,6 @@
"noMoreInfoDesc": "暂无更多信息", "noMoreInfoDesc": "暂无更多信息",
"profileParseErrorDesc": "配置文件解析错误", "profileParseErrorDesc": "配置文件解析错误",
"proxyPort": "代理端口", "proxyPort": "代理端口",
"proxyPortDesc": "设置clash监听端口",
"port": "端口", "port": "端口",
"logLevel": "日志等级", "logLevel": "日志等级",
"show": "显示", "show": "显示",
@@ -161,25 +160,5 @@
"checking": "检测中...", "checking": "检测中...",
"country": "区域", "country": "区域",
"checkError": "检测失败", "checkError": "检测失败",
"ipCheckTimeout": "Ip检测超时", "ipCheckTimeout": "Ip检测超时"
"search": "搜索",
"allowBypass": "允许应用绕过vpn",
"allowBypassDesc": "开启后部分应用可绕过VPN",
"externalController": "外部控制器",
"externalControllerDesc": "开启后将可以通过9090端口控制clash内核",
"ipv6Desc": "开启后将可以接收ipv6流量",
"app": "应用",
"general": "基础",
"systemProxyDesc": "为VpnService附加HTTP代理",
"unifiedDelay": "统一延迟",
"unifiedDelayDesc": "去除握手等额外延迟",
"tcpConcurrent": "TCP并发",
"tcpConcurrentDesc": "开启后允许tcp并发",
"geodataLoader": "Geo低内存模式",
"geodataLoaderDesc": "开启将使用Geo低内存加载器",
"requests": "请求",
"requestsDesc": "查看最近请求数据",
"nullRequestsDesc": "未开启代理或者没有请求",
"findProcessMode": "查找进程",
"findProcessModeDesc": "开启后存在闪退风险"
} }

View File

@@ -40,14 +40,9 @@ class MessageLookup extends MessageLookupByLibrary {
"addressTip": MessageLookupByLibrary.simpleMessage( "addressTip": MessageLookupByLibrary.simpleMessage(
"Please enter a valid WebDAV address"), "Please enter a valid WebDAV address"),
"ago": MessageLookupByLibrary.simpleMessage(" Ago"), "ago": MessageLookupByLibrary.simpleMessage(" Ago"),
"allowBypass": MessageLookupByLibrary.simpleMessage(
"Allow applications to bypass VPN"),
"allowBypassDesc": MessageLookupByLibrary.simpleMessage(
"Some apps can bypass VPN when turned on"),
"allowLan": MessageLookupByLibrary.simpleMessage("AllowLan"), "allowLan": MessageLookupByLibrary.simpleMessage("AllowLan"),
"allowLanDesc": MessageLookupByLibrary.simpleMessage( "allowLanDesc": MessageLookupByLibrary.simpleMessage(
"Allow access proxy through the LAN"), "Allow access proxy through the LAN"),
"app": MessageLookupByLibrary.simpleMessage("App"),
"appAccessControl": "appAccessControl":
MessageLookupByLibrary.simpleMessage("App access control"), MessageLookupByLibrary.simpleMessage("App access control"),
"application": MessageLookupByLibrary.simpleMessage("Application"), "application": MessageLookupByLibrary.simpleMessage("Application"),
@@ -117,10 +112,6 @@ class MessageLookup extends MessageLookupByLibrary {
"edit": MessageLookupByLibrary.simpleMessage("Edit"), "edit": MessageLookupByLibrary.simpleMessage("Edit"),
"en": MessageLookupByLibrary.simpleMessage("English"), "en": MessageLookupByLibrary.simpleMessage("English"),
"exit": MessageLookupByLibrary.simpleMessage("Exit"), "exit": MessageLookupByLibrary.simpleMessage("Exit"),
"externalController":
MessageLookupByLibrary.simpleMessage("ExternalController"),
"externalControllerDesc": MessageLookupByLibrary.simpleMessage(
"Once enabled, the clash kernel can be controlled on port 9090"),
"externalResources": "externalResources":
MessageLookupByLibrary.simpleMessage("External resources"), MessageLookupByLibrary.simpleMessage("External resources"),
"file": MessageLookupByLibrary.simpleMessage("File"), "file": MessageLookupByLibrary.simpleMessage("File"),
@@ -128,15 +119,7 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Directly upload profile"), MessageLookupByLibrary.simpleMessage("Directly upload profile"),
"filterSystemApp": "filterSystemApp":
MessageLookupByLibrary.simpleMessage("Filter system app"), MessageLookupByLibrary.simpleMessage("Filter system app"),
"findProcessMode": MessageLookupByLibrary.simpleMessage("Find process"),
"findProcessModeDesc": MessageLookupByLibrary.simpleMessage(
"There is a risk of flashback after opening"),
"general": MessageLookupByLibrary.simpleMessage("General"),
"geoData": MessageLookupByLibrary.simpleMessage("GeoData"), "geoData": MessageLookupByLibrary.simpleMessage("GeoData"),
"geodataLoader":
MessageLookupByLibrary.simpleMessage("Geo Low Memory Mode"),
"geodataLoaderDesc": MessageLookupByLibrary.simpleMessage(
"Enabling will use the Geo low memory loader"),
"global": MessageLookupByLibrary.simpleMessage("Global"), "global": MessageLookupByLibrary.simpleMessage("Global"),
"goDownload": MessageLookupByLibrary.simpleMessage("Go to download"), "goDownload": MessageLookupByLibrary.simpleMessage("Go to download"),
"hours": MessageLookupByLibrary.simpleMessage("Hours"), "hours": MessageLookupByLibrary.simpleMessage("Hours"),
@@ -144,8 +127,6 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Import from URL"), MessageLookupByLibrary.simpleMessage("Import from URL"),
"ipCheckTimeout": "ipCheckTimeout":
MessageLookupByLibrary.simpleMessage("Ip check timeout"), MessageLookupByLibrary.simpleMessage("Ip check timeout"),
"ipv6Desc": MessageLookupByLibrary.simpleMessage(
"When turned on it will be able to receive ipv6 traffic"),
"just": MessageLookupByLibrary.simpleMessage("Just"), "just": MessageLookupByLibrary.simpleMessage("Just"),
"language": MessageLookupByLibrary.simpleMessage("Language"), "language": MessageLookupByLibrary.simpleMessage("Language"),
"light": MessageLookupByLibrary.simpleMessage("Light"), "light": MessageLookupByLibrary.simpleMessage("Light"),
@@ -179,8 +160,6 @@ class MessageLookup extends MessageLookupByLibrary {
"nullLogsDesc": MessageLookupByLibrary.simpleMessage("No logs"), "nullLogsDesc": MessageLookupByLibrary.simpleMessage("No logs"),
"nullProfileDesc": MessageLookupByLibrary.simpleMessage( "nullProfileDesc": MessageLookupByLibrary.simpleMessage(
"No profile, Please add a profile"), "No profile, Please add a profile"),
"nullRequestsDesc":
MessageLookupByLibrary.simpleMessage("No proxy or no request"),
"other": MessageLookupByLibrary.simpleMessage("Other"), "other": MessageLookupByLibrary.simpleMessage("Other"),
"outboundMode": MessageLookupByLibrary.simpleMessage("Outbound mode"), "outboundMode": MessageLookupByLibrary.simpleMessage("Outbound mode"),
"override": MessageLookupByLibrary.simpleMessage("Override"), "override": MessageLookupByLibrary.simpleMessage("Override"),
@@ -216,8 +195,6 @@ class MessageLookup extends MessageLookupByLibrary {
"project": MessageLookupByLibrary.simpleMessage("Project"), "project": MessageLookupByLibrary.simpleMessage("Project"),
"proxies": MessageLookupByLibrary.simpleMessage("Proxies"), "proxies": MessageLookupByLibrary.simpleMessage("Proxies"),
"proxyPort": MessageLookupByLibrary.simpleMessage("ProxyPort"), "proxyPort": MessageLookupByLibrary.simpleMessage("ProxyPort"),
"proxyPortDesc": MessageLookupByLibrary.simpleMessage(
"Set the clash listening port"),
"qrcode": MessageLookupByLibrary.simpleMessage("QR code"), "qrcode": MessageLookupByLibrary.simpleMessage("QR code"),
"qrcodeDesc": MessageLookupByLibrary.simpleMessage( "qrcodeDesc": MessageLookupByLibrary.simpleMessage(
"Scan QR code to obtain profile"), "Scan QR code to obtain profile"),
@@ -230,15 +207,11 @@ class MessageLookup extends MessageLookupByLibrary {
MessageLookupByLibrary.simpleMessage("Only recovery profiles"), MessageLookupByLibrary.simpleMessage("Only recovery profiles"),
"recoverySuccess": "recoverySuccess":
MessageLookupByLibrary.simpleMessage("Recovery success"), MessageLookupByLibrary.simpleMessage("Recovery success"),
"requests": MessageLookupByLibrary.simpleMessage("Requests"),
"requestsDesc": MessageLookupByLibrary.simpleMessage(
"View recently requested data"),
"resources": MessageLookupByLibrary.simpleMessage("Resources"), "resources": MessageLookupByLibrary.simpleMessage("Resources"),
"resourcesDesc": MessageLookupByLibrary.simpleMessage( "resourcesDesc": MessageLookupByLibrary.simpleMessage(
"External resource related info"), "External resource related info"),
"rule": MessageLookupByLibrary.simpleMessage("Rule"), "rule": MessageLookupByLibrary.simpleMessage("Rule"),
"save": MessageLookupByLibrary.simpleMessage("Save"), "save": MessageLookupByLibrary.simpleMessage("Save"),
"search": MessageLookupByLibrary.simpleMessage("Search"),
"selectAll": MessageLookupByLibrary.simpleMessage("Select all"), "selectAll": MessageLookupByLibrary.simpleMessage("Select all"),
"selected": MessageLookupByLibrary.simpleMessage("Selected"), "selected": MessageLookupByLibrary.simpleMessage("Selected"),
"settings": MessageLookupByLibrary.simpleMessage("Settings"), "settings": MessageLookupByLibrary.simpleMessage("Settings"),
@@ -250,14 +223,9 @@ class MessageLookup extends MessageLookupByLibrary {
"stopVpn": MessageLookupByLibrary.simpleMessage("Stopping VPN..."), "stopVpn": MessageLookupByLibrary.simpleMessage("Stopping VPN..."),
"submit": MessageLookupByLibrary.simpleMessage("Submit"), "submit": MessageLookupByLibrary.simpleMessage("Submit"),
"systemProxy": MessageLookupByLibrary.simpleMessage("SystemProxy"), "systemProxy": MessageLookupByLibrary.simpleMessage("SystemProxy"),
"systemProxyDesc": MessageLookupByLibrary.simpleMessage(
"Attach HTTP proxy to VpnService"),
"tabAnimation": MessageLookupByLibrary.simpleMessage("Tab animation"), "tabAnimation": MessageLookupByLibrary.simpleMessage("Tab animation"),
"tabAnimationDesc": MessageLookupByLibrary.simpleMessage( "tabAnimationDesc": MessageLookupByLibrary.simpleMessage(
"When enabled, the home tab will add a toggle animation"), "When enabled, the home tab will add a toggle animation"),
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("Tcp concurrent"),
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage(
"Enabling it will allow tcp concurrency"),
"theme": MessageLookupByLibrary.simpleMessage("Theme"), "theme": MessageLookupByLibrary.simpleMessage("Theme"),
"themeColor": MessageLookupByLibrary.simpleMessage("Theme color"), "themeColor": MessageLookupByLibrary.simpleMessage("Theme color"),
"themeDesc": MessageLookupByLibrary.simpleMessage( "themeDesc": MessageLookupByLibrary.simpleMessage(
@@ -272,9 +240,6 @@ class MessageLookup extends MessageLookupByLibrary {
"unableToUpdateCurrentProfileDesc": "unableToUpdateCurrentProfileDesc":
MessageLookupByLibrary.simpleMessage( MessageLookupByLibrary.simpleMessage(
"unable to update current profile"), "unable to update current profile"),
"unifiedDelay": MessageLookupByLibrary.simpleMessage("Unified delay"),
"unifiedDelayDesc": MessageLookupByLibrary.simpleMessage(
"Remove extra delays such as handshaking"),
"unknown": MessageLookupByLibrary.simpleMessage("Unknown"), "unknown": MessageLookupByLibrary.simpleMessage("Unknown"),
"update": MessageLookupByLibrary.simpleMessage("Update"), "update": MessageLookupByLibrary.simpleMessage("Update"),
"upload": MessageLookupByLibrary.simpleMessage("Upload"), "upload": MessageLookupByLibrary.simpleMessage("Upload"),

View File

@@ -36,12 +36,8 @@ class MessageLookup extends MessageLookupByLibrary {
"addressHelp": MessageLookupByLibrary.simpleMessage("WebDAV服务器地址"), "addressHelp": MessageLookupByLibrary.simpleMessage("WebDAV服务器地址"),
"addressTip": MessageLookupByLibrary.simpleMessage("请输入有效的WebDAV地址"), "addressTip": MessageLookupByLibrary.simpleMessage("请输入有效的WebDAV地址"),
"ago": MessageLookupByLibrary.simpleMessage(""), "ago": MessageLookupByLibrary.simpleMessage(""),
"allowBypass": MessageLookupByLibrary.simpleMessage("允许应用绕过vpn"),
"allowBypassDesc":
MessageLookupByLibrary.simpleMessage("开启后部分应用可绕过VPN"),
"allowLan": MessageLookupByLibrary.simpleMessage("局域网代理"), "allowLan": MessageLookupByLibrary.simpleMessage("局域网代理"),
"allowLanDesc": MessageLookupByLibrary.simpleMessage("允许通过局域网访问代理"), "allowLanDesc": MessageLookupByLibrary.simpleMessage("允许通过局域网访问代理"),
"app": MessageLookupByLibrary.simpleMessage("应用"),
"appAccessControl": MessageLookupByLibrary.simpleMessage("应用访问控制"), "appAccessControl": MessageLookupByLibrary.simpleMessage("应用访问控制"),
"application": MessageLookupByLibrary.simpleMessage("应用程序"), "application": MessageLookupByLibrary.simpleMessage("应用程序"),
"applicationDesc": MessageLookupByLibrary.simpleMessage("修改应用程序相关设置"), "applicationDesc": MessageLookupByLibrary.simpleMessage("修改应用程序相关设置"),
@@ -97,27 +93,16 @@ class MessageLookup extends MessageLookupByLibrary {
"edit": MessageLookupByLibrary.simpleMessage("编辑"), "edit": MessageLookupByLibrary.simpleMessage("编辑"),
"en": MessageLookupByLibrary.simpleMessage("英语"), "en": MessageLookupByLibrary.simpleMessage("英语"),
"exit": MessageLookupByLibrary.simpleMessage("退出"), "exit": MessageLookupByLibrary.simpleMessage("退出"),
"externalController": MessageLookupByLibrary.simpleMessage("外部控制器"),
"externalControllerDesc":
MessageLookupByLibrary.simpleMessage("开启后将可以通过9090端口控制clash内核"),
"externalResources": MessageLookupByLibrary.simpleMessage("外部资源"), "externalResources": MessageLookupByLibrary.simpleMessage("外部资源"),
"file": MessageLookupByLibrary.simpleMessage("文件"), "file": MessageLookupByLibrary.simpleMessage("文件"),
"fileDesc": MessageLookupByLibrary.simpleMessage("直接上传配置文件"), "fileDesc": MessageLookupByLibrary.simpleMessage("直接上传配置文件"),
"filterSystemApp": MessageLookupByLibrary.simpleMessage("过滤系统应用"), "filterSystemApp": MessageLookupByLibrary.simpleMessage("过滤系统应用"),
"findProcessMode": MessageLookupByLibrary.simpleMessage("查找进程"),
"findProcessModeDesc":
MessageLookupByLibrary.simpleMessage("开启后存在闪退风险"),
"general": MessageLookupByLibrary.simpleMessage("基础"),
"geoData": MessageLookupByLibrary.simpleMessage("地理数据"), "geoData": MessageLookupByLibrary.simpleMessage("地理数据"),
"geodataLoader": MessageLookupByLibrary.simpleMessage("Geo低内存模式"),
"geodataLoaderDesc":
MessageLookupByLibrary.simpleMessage("开启将使用Geo低内存加载器"),
"global": MessageLookupByLibrary.simpleMessage("全局"), "global": MessageLookupByLibrary.simpleMessage("全局"),
"goDownload": MessageLookupByLibrary.simpleMessage("前往下载"), "goDownload": MessageLookupByLibrary.simpleMessage("前往下载"),
"hours": MessageLookupByLibrary.simpleMessage("小时"), "hours": MessageLookupByLibrary.simpleMessage("小时"),
"importFromURL": MessageLookupByLibrary.simpleMessage("从URL导入"), "importFromURL": MessageLookupByLibrary.simpleMessage("从URL导入"),
"ipCheckTimeout": MessageLookupByLibrary.simpleMessage("Ip检测超时"), "ipCheckTimeout": MessageLookupByLibrary.simpleMessage("Ip检测超时"),
"ipv6Desc": MessageLookupByLibrary.simpleMessage("开启后将可以接收ipv6流量"),
"just": MessageLookupByLibrary.simpleMessage("刚刚"), "just": MessageLookupByLibrary.simpleMessage("刚刚"),
"language": MessageLookupByLibrary.simpleMessage("语言"), "language": MessageLookupByLibrary.simpleMessage("语言"),
"light": MessageLookupByLibrary.simpleMessage("浅色"), "light": MessageLookupByLibrary.simpleMessage("浅色"),
@@ -146,7 +131,6 @@ class MessageLookup extends MessageLookupByLibrary {
"nullLogsDesc": MessageLookupByLibrary.simpleMessage("暂无日志"), "nullLogsDesc": MessageLookupByLibrary.simpleMessage("暂无日志"),
"nullProfileDesc": "nullProfileDesc":
MessageLookupByLibrary.simpleMessage("没有配置文件,请先添加配置文件"), MessageLookupByLibrary.simpleMessage("没有配置文件,请先添加配置文件"),
"nullRequestsDesc": MessageLookupByLibrary.simpleMessage("未开启代理或者没有请求"),
"other": MessageLookupByLibrary.simpleMessage("其他"), "other": MessageLookupByLibrary.simpleMessage("其他"),
"outboundMode": MessageLookupByLibrary.simpleMessage("出站模式"), "outboundMode": MessageLookupByLibrary.simpleMessage("出站模式"),
"override": MessageLookupByLibrary.simpleMessage("覆写"), "override": MessageLookupByLibrary.simpleMessage("覆写"),
@@ -176,7 +160,6 @@ class MessageLookup extends MessageLookupByLibrary {
"project": MessageLookupByLibrary.simpleMessage("项目"), "project": MessageLookupByLibrary.simpleMessage("项目"),
"proxies": MessageLookupByLibrary.simpleMessage("代理"), "proxies": MessageLookupByLibrary.simpleMessage("代理"),
"proxyPort": MessageLookupByLibrary.simpleMessage("代理端口"), "proxyPort": MessageLookupByLibrary.simpleMessage("代理端口"),
"proxyPortDesc": MessageLookupByLibrary.simpleMessage("设置clash监听端口"),
"qrcode": MessageLookupByLibrary.simpleMessage("二维码"), "qrcode": MessageLookupByLibrary.simpleMessage("二维码"),
"qrcodeDesc": MessageLookupByLibrary.simpleMessage("扫描二维码获取配置文件"), "qrcodeDesc": MessageLookupByLibrary.simpleMessage("扫描二维码获取配置文件"),
"recovery": MessageLookupByLibrary.simpleMessage("恢复"), "recovery": MessageLookupByLibrary.simpleMessage("恢复"),
@@ -184,13 +167,10 @@ class MessageLookup extends MessageLookupByLibrary {
"recoveryDesc": MessageLookupByLibrary.simpleMessage("从WebDAV恢复数据"), "recoveryDesc": MessageLookupByLibrary.simpleMessage("从WebDAV恢复数据"),
"recoveryProfiles": MessageLookupByLibrary.simpleMessage("仅恢复配置文件"), "recoveryProfiles": MessageLookupByLibrary.simpleMessage("仅恢复配置文件"),
"recoverySuccess": MessageLookupByLibrary.simpleMessage("恢复成功"), "recoverySuccess": MessageLookupByLibrary.simpleMessage("恢复成功"),
"requests": MessageLookupByLibrary.simpleMessage("请求"),
"requestsDesc": MessageLookupByLibrary.simpleMessage("查看最近请求数据"),
"resources": MessageLookupByLibrary.simpleMessage("资源"), "resources": MessageLookupByLibrary.simpleMessage("资源"),
"resourcesDesc": MessageLookupByLibrary.simpleMessage("外部资源相关信息"), "resourcesDesc": MessageLookupByLibrary.simpleMessage("外部资源相关信息"),
"rule": MessageLookupByLibrary.simpleMessage("规则"), "rule": MessageLookupByLibrary.simpleMessage("规则"),
"save": MessageLookupByLibrary.simpleMessage("保存"), "save": MessageLookupByLibrary.simpleMessage("保存"),
"search": MessageLookupByLibrary.simpleMessage("搜索"),
"selectAll": MessageLookupByLibrary.simpleMessage("全选"), "selectAll": MessageLookupByLibrary.simpleMessage("全选"),
"selected": MessageLookupByLibrary.simpleMessage("已选择"), "selected": MessageLookupByLibrary.simpleMessage("已选择"),
"settings": MessageLookupByLibrary.simpleMessage("设置"), "settings": MessageLookupByLibrary.simpleMessage("设置"),
@@ -201,13 +181,9 @@ class MessageLookup extends MessageLookupByLibrary {
"stopVpn": MessageLookupByLibrary.simpleMessage("正在停止VPN..."), "stopVpn": MessageLookupByLibrary.simpleMessage("正在停止VPN..."),
"submit": MessageLookupByLibrary.simpleMessage("提交"), "submit": MessageLookupByLibrary.simpleMessage("提交"),
"systemProxy": MessageLookupByLibrary.simpleMessage("系统代理"), "systemProxy": MessageLookupByLibrary.simpleMessage("系统代理"),
"systemProxyDesc":
MessageLookupByLibrary.simpleMessage("为VpnService附加HTTP代理"),
"tabAnimation": MessageLookupByLibrary.simpleMessage("选项卡动画"), "tabAnimation": MessageLookupByLibrary.simpleMessage("选项卡动画"),
"tabAnimationDesc": "tabAnimationDesc":
MessageLookupByLibrary.simpleMessage("开启后,主页选项卡将添加切换动画"), MessageLookupByLibrary.simpleMessage("开启后,主页选项卡将添加切换动画"),
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP并发"),
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("开启后允许tcp并发"),
"theme": MessageLookupByLibrary.simpleMessage("主题"), "theme": MessageLookupByLibrary.simpleMessage("主题"),
"themeColor": MessageLookupByLibrary.simpleMessage("主题色彩"), "themeColor": MessageLookupByLibrary.simpleMessage("主题色彩"),
"themeDesc": MessageLookupByLibrary.simpleMessage("设置深色模式,调整色彩"), "themeDesc": MessageLookupByLibrary.simpleMessage("设置深色模式,调整色彩"),
@@ -219,8 +195,6 @@ class MessageLookup extends MessageLookupByLibrary {
"tunDesc": MessageLookupByLibrary.simpleMessage("仅在管理员模式生效"), "tunDesc": MessageLookupByLibrary.simpleMessage("仅在管理员模式生效"),
"unableToUpdateCurrentProfileDesc": "unableToUpdateCurrentProfileDesc":
MessageLookupByLibrary.simpleMessage("无法更新当前配置文件"), MessageLookupByLibrary.simpleMessage("无法更新当前配置文件"),
"unifiedDelay": MessageLookupByLibrary.simpleMessage("统一延迟"),
"unifiedDelayDesc": MessageLookupByLibrary.simpleMessage("去除握手等额外延迟"),
"unknown": MessageLookupByLibrary.simpleMessage("未知"), "unknown": MessageLookupByLibrary.simpleMessage("未知"),
"update": MessageLookupByLibrary.simpleMessage("更新"), "update": MessageLookupByLibrary.simpleMessage("更新"),
"upload": MessageLookupByLibrary.simpleMessage("上传"), "upload": MessageLookupByLibrary.simpleMessage("上传"),

View File

@@ -1170,16 +1170,6 @@ class AppLocalizations {
); );
} }
/// `Set the clash listening port`
String get proxyPortDesc {
return Intl.message(
'Set the clash listening port',
name: 'proxyPortDesc',
desc: '',
args: [],
);
}
/// `Port` /// `Port`
String get port { String get port {
return Intl.message( return Intl.message(
@@ -1679,206 +1669,6 @@ class AppLocalizations {
args: [], args: [],
); );
} }
/// `Search`
String get search {
return Intl.message(
'Search',
name: 'search',
desc: '',
args: [],
);
}
/// `Allow applications to bypass VPN`
String get allowBypass {
return Intl.message(
'Allow applications to bypass VPN',
name: 'allowBypass',
desc: '',
args: [],
);
}
/// `Some apps can bypass VPN when turned on`
String get allowBypassDesc {
return Intl.message(
'Some apps can bypass VPN when turned on',
name: 'allowBypassDesc',
desc: '',
args: [],
);
}
/// `ExternalController`
String get externalController {
return Intl.message(
'ExternalController',
name: 'externalController',
desc: '',
args: [],
);
}
/// `Once enabled, the clash kernel can be controlled on port 9090`
String get externalControllerDesc {
return Intl.message(
'Once enabled, the clash kernel can be controlled on port 9090',
name: 'externalControllerDesc',
desc: '',
args: [],
);
}
/// `When turned on it will be able to receive ipv6 traffic`
String get ipv6Desc {
return Intl.message(
'When turned on it will be able to receive ipv6 traffic',
name: 'ipv6Desc',
desc: '',
args: [],
);
}
/// `App`
String get app {
return Intl.message(
'App',
name: 'app',
desc: '',
args: [],
);
}
/// `General`
String get general {
return Intl.message(
'General',
name: 'general',
desc: '',
args: [],
);
}
/// `Attach HTTP proxy to VpnService`
String get systemProxyDesc {
return Intl.message(
'Attach HTTP proxy to VpnService',
name: 'systemProxyDesc',
desc: '',
args: [],
);
}
/// `Unified delay`
String get unifiedDelay {
return Intl.message(
'Unified delay',
name: 'unifiedDelay',
desc: '',
args: [],
);
}
/// `Remove extra delays such as handshaking`
String get unifiedDelayDesc {
return Intl.message(
'Remove extra delays such as handshaking',
name: 'unifiedDelayDesc',
desc: '',
args: [],
);
}
/// `Tcp concurrent`
String get tcpConcurrent {
return Intl.message(
'Tcp concurrent',
name: 'tcpConcurrent',
desc: '',
args: [],
);
}
/// `Enabling it will allow tcp concurrency`
String get tcpConcurrentDesc {
return Intl.message(
'Enabling it will allow tcp concurrency',
name: 'tcpConcurrentDesc',
desc: '',
args: [],
);
}
/// `Geo Low Memory Mode`
String get geodataLoader {
return Intl.message(
'Geo Low Memory Mode',
name: 'geodataLoader',
desc: '',
args: [],
);
}
/// `Enabling will use the Geo low memory loader`
String get geodataLoaderDesc {
return Intl.message(
'Enabling will use the Geo low memory loader',
name: 'geodataLoaderDesc',
desc: '',
args: [],
);
}
/// `Requests`
String get requests {
return Intl.message(
'Requests',
name: 'requests',
desc: '',
args: [],
);
}
/// `View recently requested data`
String get requestsDesc {
return Intl.message(
'View recently requested data',
name: 'requestsDesc',
desc: '',
args: [],
);
}
/// `No proxy or no request`
String get nullRequestsDesc {
return Intl.message(
'No proxy or no request',
name: 'nullRequestsDesc',
desc: '',
args: [],
);
}
/// `Find process`
String get findProcessMode {
return Intl.message(
'Find process',
name: 'findProcessMode',
desc: '',
args: [],
);
}
/// `There is a risk of flashback after opening`
String get findProcessModeDesc {
return Intl.message(
'There is a risk of flashback after opening',
name: 'findProcessModeDesc',
desc: '',
args: [],
);
}
} }
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> { class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {

View File

@@ -22,15 +22,16 @@ Future<void> main() async {
isCompatible: config.isCompatible, isCompatible: config.isCompatible,
selectedMap: config.currentSelectedMap, selectedMap: config.currentSelectedMap,
); );
appState.navigationItems = navigation.getItems(
openLogs: config.openLogs,
hasProxies: false,
);
await globalState.init( await globalState.init(
appState: appState, appState: appState,
config: config, config: config,
clashConfig: clashConfig, clashConfig: clashConfig,
); );
globalState.updateNavigationItems(
appState: appState,
config: config,
clashConfig: clashConfig,
);
runAppWithPreferences( runAppWithPreferences(
const Application(), const Application(),
appState: appState, appState: appState,
@@ -60,16 +61,6 @@ Future<void> vpnService() async {
clashConfig: clashConfig, clashConfig: clashConfig,
); );
if (appState.isInit) {
await globalState.applyProfile(
appState: appState,
config: config,
clashConfig: clashConfig,
);
} else {
exit(0);
}
final appLocalizations = await AppLocalizations.load( final appLocalizations = await AppLocalizations.load(
other.getLocaleForString(config.locale) ?? other.getLocaleForString(config.locale) ??
WidgetsBinding.instance.platformDispatcher.locale, WidgetsBinding.instance.platformDispatcher.locale,

View File

@@ -1,10 +1,7 @@
import 'dart:io';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:fl_clash/common/common.dart'; import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'connection.dart';
import 'ffi.dart'; import 'ffi.dart';
import 'log.dart'; import 'log.dart';
import 'navigation.dart'; import 'navigation.dart';
@@ -32,7 +29,6 @@ class AppState with ChangeNotifier {
bool _isCompatible; bool _isCompatible;
List<Group> _groups; List<Group> _groups;
double _viewWidth; double _viewWidth;
List<Connection> _requests;
AppState({ AppState({
required Mode mode, required Mode mode,
@@ -46,7 +42,6 @@ class AppState with ChangeNotifier {
_viewWidth = 0, _viewWidth = 0,
_selectedMap = selectedMap, _selectedMap = selectedMap,
_sortNum = 0, _sortNum = 0,
_requests = [],
_mode = mode, _mode = mode,
_delayMap = {}, _delayMap = {},
_groups = [], _groups = [],
@@ -112,7 +107,7 @@ class AppState with ChangeNotifier {
} else { } else {
final index = groups.indexWhere((element) => element.name == proxyName); final index = groups.indexWhere((element) => element.name == proxyName);
if (index == -1) return type; if (index == -1) return type;
return "$type(${groups[index].now ?? '*'})"; return "$type(${groups[index].now})";
} }
} }
@@ -162,24 +157,6 @@ class AppState with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
List<Connection> get requests => _requests;
set requests(List<Connection> value) {
if (_requests != value) {
_requests = value;
notifyListeners();
}
}
addRequest(Connection value) {
_requests.add(value);
final maxLength = Platform.isAndroid ? 1000 : 60;
if (_requests.length > maxLength) {
_requests = _requests.sublist(_requests.length - maxLength);
}
notifyListeners();
}
List<Log> get logs => _logs; List<Log> get logs => _logs;
set logs(List<Log> value) { set logs(List<Log> value) {
@@ -191,10 +168,8 @@ class AppState with ChangeNotifier {
addLog(Log log) { addLog(Log log) {
_logs.add(log); _logs.add(log);
if (!Platform.isAndroid) { if (_logs.length > 60) {
if (_logs.length > 60) { _logs = _logs.sublist(_logs.length - 60);
_logs = _logs.sublist(_logs.length - 60);
}
} }
notifyListeners(); notifyListeners();
} }

View File

@@ -16,7 +16,7 @@ class Tun with _$Tun {
const factory Tun({ const factory Tun({
@Default(false) bool enable, @Default(false) bool enable,
@Default(appName) String device, @Default(appName) String device,
@Default(TunStack.gvisor) TunStack stack, @Default(TunStack.mixed) TunStack stack,
@JsonKey(name: "dns-hijack") @Default(["any:53"]) List<String> dnsHijack, @JsonKey(name: "dns-hijack") @Default(["any:53"]) List<String> dnsHijack,
}) = _Tun; }) = _Tun;
@@ -108,34 +108,29 @@ class Dns {
class ClashConfig extends ChangeNotifier { class ClashConfig extends ChangeNotifier {
int _mixedPort; int _mixedPort;
bool _allowLan; bool _allowLan;
bool _ipv6;
String _geodataLoader;
LogLevel _logLevel;
String _externalController;
Mode _mode; Mode _mode;
FindProcessMode _findProcessMode; LogLevel _logLevel;
bool _unifiedDelay;
bool _tcpConcurrent;
Tun _tun; Tun _tun;
Dns _dns; Dns _dns;
List<String> _rules; List<String> _rules;
ClashConfig() ClashConfig({
: _mixedPort = 7890, int? mixedPort,
_mode = Mode.rule, Mode? mode,
_ipv6 = false, bool? allowLan,
_findProcessMode = FindProcessMode.off, LogLevel? logLevel,
_allowLan = false, Tun? tun,
_tcpConcurrent = false, Dns? dns,
_logLevel = LogLevel.info, List<String>? rules,
_tun = const Tun(), }) : _mixedPort = mixedPort ?? 7890,
_unifiedDelay = false, _mode = mode ?? Mode.rule,
_geodataLoader = geodataLoaderMemconservative, _allowLan = allowLan ?? false,
_externalController = '', _logLevel = logLevel ?? LogLevel.info,
_dns = Dns(), _tun = tun ?? const Tun(),
_rules = []; _dns = dns ?? Dns(),
_rules = rules ?? [];
@JsonKey(name: "mixed-port", defaultValue: 7890) @JsonKey(name: "mixed-port")
int get mixedPort => _mixedPort; int get mixedPort => _mixedPort;
set mixedPort(int value) { set mixedPort(int value) {
@@ -145,7 +140,6 @@ class ClashConfig extends ChangeNotifier {
} }
} }
@JsonKey(defaultValue: Mode.rule)
Mode get mode => _mode; Mode get mode => _mode;
set mode(Mode value) { set mode(Mode value) {
@@ -155,16 +149,6 @@ class ClashConfig extends ChangeNotifier {
} }
} }
@JsonKey(name: "find-process-mode", defaultValue: FindProcessMode.off)
FindProcessMode get findProcessMode => _findProcessMode;
set findProcessMode(FindProcessMode value) {
if (_findProcessMode != value) {
_findProcessMode = value;
notifyListeners();
}
}
@JsonKey(name: "allow-lan") @JsonKey(name: "allow-lan")
bool get allowLan => _allowLan; bool get allowLan => _allowLan;
@@ -175,7 +159,7 @@ class ClashConfig extends ChangeNotifier {
} }
} }
@JsonKey(name: "log-level", defaultValue: LogLevel.info) @JsonKey(name: "log-level")
LogLevel get logLevel => _logLevel; LogLevel get logLevel => _logLevel;
set logLevel(LogLevel value) { set logLevel(LogLevel value) {
@@ -185,56 +169,6 @@ class ClashConfig extends ChangeNotifier {
} }
} }
@JsonKey(name: "external-controller", defaultValue: '')
String get externalController => _externalController;
set externalController(String value) {
if (_externalController != value) {
_externalController = value;
notifyListeners();
}
}
@JsonKey(defaultValue: false)
bool get ipv6 => _ipv6;
set ipv6(bool value) {
if (_ipv6 != value) {
_ipv6 = value;
notifyListeners();
}
}
@JsonKey(name: "geodata-loader", defaultValue: geodataLoaderMemconservative)
String get geodataLoader => _geodataLoader;
set geodataLoader(String value) {
if (_geodataLoader != value) {
_geodataLoader = value;
notifyListeners();
}
}
@JsonKey(name: "unified-delay", defaultValue: false)
bool get unifiedDelay => _unifiedDelay;
set unifiedDelay(bool value) {
if (_unifiedDelay != value) {
_unifiedDelay = value;
notifyListeners();
}
}
@JsonKey(name: "tcp-concurrent", defaultValue: false)
bool get tcpConcurrent => _tcpConcurrent;
set tcpConcurrent(bool value) {
if (_tcpConcurrent != value) {
_tcpConcurrent = value;
notifyListeners();
}
}
Tun get tun => _tun; Tun get tun => _tun;
set tun(Tun value) { set tun(Tun value) {
@@ -283,6 +217,17 @@ class ClashConfig extends ChangeNotifier {
return _$ClashConfigFromJson(json); return _$ClashConfigFromJson(json);
} }
ClashConfig copyWith({Tun? tun}) {
return ClashConfig(
mixedPort: mixedPort,
mode: mode,
logLevel: logLevel,
tun: tun ?? this.tun,
dns: dns,
allowLan: allowLan,
);
}
@override @override
String toString() { String toString() {
return 'ClashConfig{_mixedPort: $_mixedPort, _allowLan: $_allowLan, _mode: $_mode, _logLevel: $_logLevel, _tun: $_tun, _dns: $_dns, _rules: $_rules}'; return 'ClashConfig{_mixedPort: $_mixedPort, _allowLan: $_allowLan, _mode: $_mode, _logLevel: $_logLevel, _tun: $_tun, _dns: $_dns, _rules: $_rules}';

View File

@@ -8,7 +8,6 @@ import '../common/common.dart';
import 'models.dart'; import 'models.dart';
part 'generated/config.g.dart'; part 'generated/config.g.dart';
part 'generated/config.freezed.dart'; part 'generated/config.freezed.dart';
@freezed @freezed
@@ -24,17 +23,6 @@ class AccessControl with _$AccessControl {
_$AccessControlFromJson(json); _$AccessControlFromJson(json);
} }
@freezed
class Props with _$Props {
const factory Props({
AccessControl? accessControl,
bool? allowBypass,
bool? systemProxy,
}) = _Props;
factory Props.fromJson(Map<String, Object?> json) => _$PropsFromJson(json);
}
@JsonSerializable() @JsonSerializable()
class Config extends ChangeNotifier { class Config extends ChangeNotifier {
List<Profile> _profiles; List<Profile> _profiles;
@@ -53,8 +41,6 @@ class Config extends ChangeNotifier {
AccessControl _accessControl; AccessControl _accessControl;
bool _isAnimateToPage; bool _isAnimateToPage;
bool _autoCheckUpdate; bool _autoCheckUpdate;
bool _allowBypass;
bool _systemProxy;
DAV? _dav; DAV? _dav;
Config() Config()
@@ -70,10 +56,8 @@ class Config extends ChangeNotifier {
_isMinimizeOnExit = true, _isMinimizeOnExit = true,
_isAccessControl = false, _isAccessControl = false,
_autoCheckUpdate = true, _autoCheckUpdate = true,
_systemProxy = false,
_accessControl = const AccessControl(), _accessControl = const AccessControl(),
_isAnimateToPage = true, _isAnimateToPage = true;
_allowBypass = true;
deleteProfileById(String id) { deleteProfileById(String id) {
_profiles = profiles.where((element) => element.id != id).toList(); _profiles = profiles.where((element) => element.id != id).toList();
@@ -150,15 +134,6 @@ class Config extends ChangeNotifier {
} }
} }
String? get currentGroupName => currentProfile?.currentGroupName;
updateCurrentGroupName(String groupName) {
if (currentProfile?.currentGroupName != groupName) {
currentProfile?.currentGroupName = groupName;
notifyListeners();
}
}
SelectedMap get currentSelectedMap { SelectedMap get currentSelectedMap {
return currentProfile?.selectedMap ?? {}; return currentProfile?.selectedMap ?? {};
} }
@@ -330,34 +305,8 @@ class Config extends ChangeNotifier {
} }
} }
@JsonKey(defaultValue: true) update(
bool get allowBypass { [Config? config, RecoveryOption recoveryOptions = RecoveryOption.all]) {
return _allowBypass;
}
set allowBypass(bool value) {
if (_allowBypass != value) {
_allowBypass = value;
notifyListeners();
}
}
@JsonKey(defaultValue: true)
bool get systemProxy {
return _systemProxy;
}
set systemProxy(bool value) {
if (_systemProxy != value) {
_systemProxy = value;
notifyListeners();
}
}
update([
Config? config,
RecoveryOption recoveryOptions = RecoveryOption.all,
]) {
if (config != null) { if (config != null) {
_profiles = config._profiles; _profiles = config._profiles;
for (final profile in config._profiles) { for (final profile in config._profiles) {
@@ -376,7 +325,6 @@ class Config extends ChangeNotifier {
_openLog = config._openLog; _openLog = config._openLog;
_themeMode = config._themeMode; _themeMode = config._themeMode;
_locale = config._locale; _locale = config._locale;
_allowBypass = config._allowBypass;
_primaryColor = config._primaryColor; _primaryColor = config._primaryColor;
_proxiesSortType = config._proxiesSortType; _proxiesSortType = config._proxiesSortType;
_isMinimizeOnExit = config._isMinimizeOnExit; _isMinimizeOnExit = config._isMinimizeOnExit;

View File

@@ -14,7 +14,6 @@ class Metadata with _$Metadata {
required String destinationIP, required String destinationIP,
required String destinationPort, required String destinationPort,
required String host, required String host,
required String process,
required String remoteDestination, required String remoteDestination,
}) = _Metadata; }) = _Metadata;

View File

@@ -2,7 +2,6 @@
import 'package:fl_clash/enum/enum.dart'; import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/clash_config.dart'; import 'package:fl_clash/models/clash_config.dart';
import 'package:fl_clash/models/connection.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
part 'generated/ffi.g.dart'; part 'generated/ffi.g.dart';
@@ -67,25 +66,16 @@ class Now with _$Now {
@freezed @freezed
class Process with _$Process { class Process with _$Process {
const factory Process({ const factory Process({
required int id, required int uid,
required Metadata metadata, required String network,
required String source,
required String target,
}) = _Process; }) = _Process;
factory Process.fromJson(Map<String, Object?> json) => factory Process.fromJson(Map<String, Object?> json) =>
_$ProcessFromJson(json); _$ProcessFromJson(json);
} }
@freezed
class ProcessMapItem with _$ProcessMapItem {
const factory ProcessMapItem({
required int id,
String? value,
}) = _ProcessMapItem;
factory ProcessMapItem.fromJson(Map<String, Object?> json) =>
_$ProcessMapItemFromJson(json);
}
@freezed @freezed
class ExternalProvider with _$ExternalProvider { class ExternalProvider with _$ExternalProvider {
const factory ExternalProvider({ const factory ExternalProvider({

View File

@@ -135,7 +135,7 @@ class _$TunImpl implements _Tun {
const _$TunImpl( const _$TunImpl(
{this.enable = false, {this.enable = false,
this.device = appName, this.device = appName,
this.stack = TunStack.gvisor, this.stack = TunStack.mixed,
@JsonKey(name: "dns-hijack") @JsonKey(name: "dns-hijack")
final List<String> dnsHijack = const ["any:53"]}) final List<String> dnsHijack = const ["any:53"]})
: _dnsHijack = dnsHijack; : _dnsHijack = dnsHijack;

View File

@@ -35,36 +35,27 @@ Map<String, dynamic> _$DnsToJson(Dns instance) => <String, dynamic>{
'fake-ip-filter': instance.fakeIpFilter, 'fake-ip-filter': instance.fakeIpFilter,
}; };
ClashConfig _$ClashConfigFromJson(Map<String, dynamic> json) => ClashConfig() ClashConfig _$ClashConfigFromJson(Map<String, dynamic> json) => ClashConfig(
..mixedPort = (json['mixed-port'] as num?)?.toInt() ?? 7890 mixedPort: (json['mixed-port'] as num?)?.toInt(),
..mode = $enumDecodeNullable(_$ModeEnumMap, json['mode']) ?? Mode.rule mode: $enumDecodeNullable(_$ModeEnumMap, json['mode']),
..findProcessMode = $enumDecodeNullable( allowLan: json['allow-lan'] as bool?,
_$FindProcessModeEnumMap, json['find-process-mode']) ?? logLevel: $enumDecodeNullable(_$LogLevelEnumMap, json['log-level']),
FindProcessMode.off tun: json['tun'] == null
..allowLan = json['allow-lan'] as bool ? null
..logLevel = : Tun.fromJson(json['tun'] as Map<String, dynamic>),
$enumDecodeNullable(_$LogLevelEnumMap, json['log-level']) ?? LogLevel.info dns: json['dns'] == null
..externalController = json['external-controller'] as String? ?? '' ? null
..ipv6 = json['ipv6'] as bool? ?? false : Dns.fromJson(json['dns'] as Map<String, dynamic>),
..geodataLoader = json['geodata-loader'] as String? ?? 'memconservative' rules:
..unifiedDelay = json['unified-delay'] as bool? ?? false (json['rules'] as List<dynamic>?)?.map((e) => e as String).toList(),
..tcpConcurrent = json['tcp-concurrent'] as bool? ?? false );
..tun = Tun.fromJson(json['tun'] as Map<String, dynamic>)
..dns = Dns.fromJson(json['dns'] as Map<String, dynamic>)
..rules = (json['rules'] as List<dynamic>).map((e) => e as String).toList();
Map<String, dynamic> _$ClashConfigToJson(ClashConfig instance) => Map<String, dynamic> _$ClashConfigToJson(ClashConfig instance) =>
<String, dynamic>{ <String, dynamic>{
'mixed-port': instance.mixedPort, 'mixed-port': instance.mixedPort,
'mode': _$ModeEnumMap[instance.mode]!, 'mode': _$ModeEnumMap[instance.mode]!,
'find-process-mode': _$FindProcessModeEnumMap[instance.findProcessMode]!,
'allow-lan': instance.allowLan, 'allow-lan': instance.allowLan,
'log-level': _$LogLevelEnumMap[instance.logLevel]!, 'log-level': _$LogLevelEnumMap[instance.logLevel]!,
'external-controller': instance.externalController,
'ipv6': instance.ipv6,
'geodata-loader': instance.geodataLoader,
'unified-delay': instance.unifiedDelay,
'tcp-concurrent': instance.tcpConcurrent,
'tun': instance.tun, 'tun': instance.tun,
'dns': instance.dns, 'dns': instance.dns,
'rules': instance.rules, 'rules': instance.rules,
@@ -76,11 +67,6 @@ const _$ModeEnumMap = {
Mode.direct: 'direct', Mode.direct: 'direct',
}; };
const _$FindProcessModeEnumMap = {
FindProcessMode.always: 'always',
FindProcessMode.off: 'off',
};
const _$LogLevelEnumMap = { const _$LogLevelEnumMap = {
LogLevel.debug: 'debug', LogLevel.debug: 'debug',
LogLevel.info: 'info', LogLevel.info: 'info',
@@ -93,7 +79,7 @@ _$TunImpl _$$TunImplFromJson(Map<String, dynamic> json) => _$TunImpl(
enable: json['enable'] as bool? ?? false, enable: json['enable'] as bool? ?? false,
device: json['device'] as String? ?? appName, device: json['device'] as String? ?? appName,
stack: $enumDecodeNullable(_$TunStackEnumMap, json['stack']) ?? stack: $enumDecodeNullable(_$TunStackEnumMap, json['stack']) ??
TunStack.gvisor, TunStack.mixed,
dnsHijack: (json['dns-hijack'] as List<dynamic>?) dnsHijack: (json['dns-hijack'] as List<dynamic>?)
?.map((e) => e as String) ?.map((e) => e as String)
.toList() ?? .toList() ??

View File

@@ -239,193 +239,3 @@ abstract class _AccessControl implements AccessControl {
_$$AccessControlImplCopyWith<_$AccessControlImpl> get copyWith => _$$AccessControlImplCopyWith<_$AccessControlImpl> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
} }
Props _$PropsFromJson(Map<String, dynamic> json) {
return _Props.fromJson(json);
}
/// @nodoc
mixin _$Props {
AccessControl? get accessControl => throw _privateConstructorUsedError;
bool? get allowBypass => throw _privateConstructorUsedError;
bool? get systemProxy => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$PropsCopyWith<Props> get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $PropsCopyWith<$Res> {
factory $PropsCopyWith(Props value, $Res Function(Props) then) =
_$PropsCopyWithImpl<$Res, Props>;
@useResult
$Res call(
{AccessControl? accessControl, bool? allowBypass, bool? systemProxy});
$AccessControlCopyWith<$Res>? get accessControl;
}
/// @nodoc
class _$PropsCopyWithImpl<$Res, $Val extends Props>
implements $PropsCopyWith<$Res> {
_$PropsCopyWithImpl(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? accessControl = freezed,
Object? allowBypass = freezed,
Object? systemProxy = freezed,
}) {
return _then(_value.copyWith(
accessControl: freezed == accessControl
? _value.accessControl
: accessControl // ignore: cast_nullable_to_non_nullable
as AccessControl?,
allowBypass: freezed == allowBypass
? _value.allowBypass
: allowBypass // ignore: cast_nullable_to_non_nullable
as bool?,
systemProxy: freezed == systemProxy
? _value.systemProxy
: systemProxy // ignore: cast_nullable_to_non_nullable
as bool?,
) as $Val);
}
@override
@pragma('vm:prefer-inline')
$AccessControlCopyWith<$Res>? get accessControl {
if (_value.accessControl == null) {
return null;
}
return $AccessControlCopyWith<$Res>(_value.accessControl!, (value) {
return _then(_value.copyWith(accessControl: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$PropsImplCopyWith<$Res> implements $PropsCopyWith<$Res> {
factory _$$PropsImplCopyWith(
_$PropsImpl value, $Res Function(_$PropsImpl) then) =
__$$PropsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{AccessControl? accessControl, bool? allowBypass, bool? systemProxy});
@override
$AccessControlCopyWith<$Res>? get accessControl;
}
/// @nodoc
class __$$PropsImplCopyWithImpl<$Res>
extends _$PropsCopyWithImpl<$Res, _$PropsImpl>
implements _$$PropsImplCopyWith<$Res> {
__$$PropsImplCopyWithImpl(
_$PropsImpl _value, $Res Function(_$PropsImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? accessControl = freezed,
Object? allowBypass = freezed,
Object? systemProxy = freezed,
}) {
return _then(_$PropsImpl(
accessControl: freezed == accessControl
? _value.accessControl
: accessControl // ignore: cast_nullable_to_non_nullable
as AccessControl?,
allowBypass: freezed == allowBypass
? _value.allowBypass
: allowBypass // ignore: cast_nullable_to_non_nullable
as bool?,
systemProxy: freezed == systemProxy
? _value.systemProxy
: systemProxy // ignore: cast_nullable_to_non_nullable
as bool?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$PropsImpl implements _Props {
const _$PropsImpl({this.accessControl, this.allowBypass, this.systemProxy});
factory _$PropsImpl.fromJson(Map<String, dynamic> json) =>
_$$PropsImplFromJson(json);
@override
final AccessControl? accessControl;
@override
final bool? allowBypass;
@override
final bool? systemProxy;
@override
String toString() {
return 'Props(accessControl: $accessControl, allowBypass: $allowBypass, systemProxy: $systemProxy)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$PropsImpl &&
(identical(other.accessControl, accessControl) ||
other.accessControl == accessControl) &&
(identical(other.allowBypass, allowBypass) ||
other.allowBypass == allowBypass) &&
(identical(other.systemProxy, systemProxy) ||
other.systemProxy == systemProxy));
}
@JsonKey(ignore: true)
@override
int get hashCode =>
Object.hash(runtimeType, accessControl, allowBypass, systemProxy);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$PropsImplCopyWith<_$PropsImpl> get copyWith =>
__$$PropsImplCopyWithImpl<_$PropsImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$PropsImplToJson(
this,
);
}
}
abstract class _Props implements Props {
const factory _Props(
{final AccessControl? accessControl,
final bool? allowBypass,
final bool? systemProxy}) = _$PropsImpl;
factory _Props.fromJson(Map<String, dynamic> json) = _$PropsImpl.fromJson;
@override
AccessControl? get accessControl;
@override
bool? get allowBypass;
@override
bool? get systemProxy;
@override
@JsonKey(ignore: true)
_$$PropsImplCopyWith<_$PropsImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -32,9 +32,7 @@ Config _$ConfigFromJson(Map<String, dynamic> json) => Config()
: DAV.fromJson(json['dav'] as Map<String, dynamic>) : DAV.fromJson(json['dav'] as Map<String, dynamic>)
..isAnimateToPage = json['isAnimateToPage'] as bool? ?? true ..isAnimateToPage = json['isAnimateToPage'] as bool? ?? true
..isCompatible = json['isCompatible'] as bool? ?? true ..isCompatible = json['isCompatible'] as bool? ?? true
..autoCheckUpdate = json['autoCheckUpdate'] as bool? ?? true ..autoCheckUpdate = json['autoCheckUpdate'] as bool? ?? true;
..allowBypass = json['allowBypass'] as bool? ?? true
..systemProxy = json['systemProxy'] as bool? ?? true;
Map<String, dynamic> _$ConfigToJson(Config instance) => <String, dynamic>{ Map<String, dynamic> _$ConfigToJson(Config instance) => <String, dynamic>{
'profiles': instance.profiles, 'profiles': instance.profiles,
@@ -54,8 +52,6 @@ Map<String, dynamic> _$ConfigToJson(Config instance) => <String, dynamic>{
'isAnimateToPage': instance.isAnimateToPage, 'isAnimateToPage': instance.isAnimateToPage,
'isCompatible': instance.isCompatible, 'isCompatible': instance.isCompatible,
'autoCheckUpdate': instance.autoCheckUpdate, 'autoCheckUpdate': instance.autoCheckUpdate,
'allowBypass': instance.allowBypass,
'systemProxy': instance.systemProxy,
}; };
const _$ThemeModeEnumMap = { const _$ThemeModeEnumMap = {
@@ -97,19 +93,3 @@ const _$AccessControlModeEnumMap = {
AccessControlMode.acceptSelected: 'acceptSelected', AccessControlMode.acceptSelected: 'acceptSelected',
AccessControlMode.rejectSelected: 'rejectSelected', AccessControlMode.rejectSelected: 'rejectSelected',
}; };
_$PropsImpl _$$PropsImplFromJson(Map<String, dynamic> json) => _$PropsImpl(
accessControl: json['accessControl'] == null
? null
: AccessControl.fromJson(
json['accessControl'] as Map<String, dynamic>),
allowBypass: json['allowBypass'] as bool?,
systemProxy: json['systemProxy'] as bool?,
);
Map<String, dynamic> _$$PropsImplToJson(_$PropsImpl instance) =>
<String, dynamic>{
'accessControl': instance.accessControl,
'allowBypass': instance.allowBypass,
'systemProxy': instance.systemProxy,
};

View File

@@ -27,7 +27,6 @@ mixin _$Metadata {
String get destinationIP => throw _privateConstructorUsedError; String get destinationIP => throw _privateConstructorUsedError;
String get destinationPort => throw _privateConstructorUsedError; String get destinationPort => throw _privateConstructorUsedError;
String get host => throw _privateConstructorUsedError; String get host => throw _privateConstructorUsedError;
String get process => throw _privateConstructorUsedError;
String get remoteDestination => throw _privateConstructorUsedError; String get remoteDestination => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@@ -49,7 +48,6 @@ abstract class $MetadataCopyWith<$Res> {
String destinationIP, String destinationIP,
String destinationPort, String destinationPort,
String host, String host,
String process,
String remoteDestination}); String remoteDestination});
} }
@@ -73,7 +71,6 @@ class _$MetadataCopyWithImpl<$Res, $Val extends Metadata>
Object? destinationIP = null, Object? destinationIP = null,
Object? destinationPort = null, Object? destinationPort = null,
Object? host = null, Object? host = null,
Object? process = null,
Object? remoteDestination = null, Object? remoteDestination = null,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
@@ -105,10 +102,6 @@ class _$MetadataCopyWithImpl<$Res, $Val extends Metadata>
? _value.host ? _value.host
: host // ignore: cast_nullable_to_non_nullable : host // ignore: cast_nullable_to_non_nullable
as String, as String,
process: null == process
? _value.process
: process // ignore: cast_nullable_to_non_nullable
as String,
remoteDestination: null == remoteDestination remoteDestination: null == remoteDestination
? _value.remoteDestination ? _value.remoteDestination
: remoteDestination // ignore: cast_nullable_to_non_nullable : remoteDestination // ignore: cast_nullable_to_non_nullable
@@ -133,7 +126,6 @@ abstract class _$$MetadataImplCopyWith<$Res>
String destinationIP, String destinationIP,
String destinationPort, String destinationPort,
String host, String host,
String process,
String remoteDestination}); String remoteDestination});
} }
@@ -155,7 +147,6 @@ class __$$MetadataImplCopyWithImpl<$Res>
Object? destinationIP = null, Object? destinationIP = null,
Object? destinationPort = null, Object? destinationPort = null,
Object? host = null, Object? host = null,
Object? process = null,
Object? remoteDestination = null, Object? remoteDestination = null,
}) { }) {
return _then(_$MetadataImpl( return _then(_$MetadataImpl(
@@ -187,10 +178,6 @@ class __$$MetadataImplCopyWithImpl<$Res>
? _value.host ? _value.host
: host // ignore: cast_nullable_to_non_nullable : host // ignore: cast_nullable_to_non_nullable
as String, as String,
process: null == process
? _value.process
: process // ignore: cast_nullable_to_non_nullable
as String,
remoteDestination: null == remoteDestination remoteDestination: null == remoteDestination
? _value.remoteDestination ? _value.remoteDestination
: remoteDestination // ignore: cast_nullable_to_non_nullable : remoteDestination // ignore: cast_nullable_to_non_nullable
@@ -210,7 +197,6 @@ class _$MetadataImpl implements _Metadata {
required this.destinationIP, required this.destinationIP,
required this.destinationPort, required this.destinationPort,
required this.host, required this.host,
required this.process,
required this.remoteDestination}); required this.remoteDestination});
factory _$MetadataImpl.fromJson(Map<String, dynamic> json) => factory _$MetadataImpl.fromJson(Map<String, dynamic> json) =>
@@ -231,13 +217,11 @@ class _$MetadataImpl implements _Metadata {
@override @override
final String host; final String host;
@override @override
final String process;
@override
final String remoteDestination; final String remoteDestination;
@override @override
String toString() { String toString() {
return 'Metadata(uid: $uid, network: $network, sourceIP: $sourceIP, sourcePort: $sourcePort, destinationIP: $destinationIP, destinationPort: $destinationPort, host: $host, process: $process, remoteDestination: $remoteDestination)'; return 'Metadata(uid: $uid, network: $network, sourceIP: $sourceIP, sourcePort: $sourcePort, destinationIP: $destinationIP, destinationPort: $destinationPort, host: $host, remoteDestination: $remoteDestination)';
} }
@override @override
@@ -256,24 +240,14 @@ class _$MetadataImpl implements _Metadata {
(identical(other.destinationPort, destinationPort) || (identical(other.destinationPort, destinationPort) ||
other.destinationPort == destinationPort) && other.destinationPort == destinationPort) &&
(identical(other.host, host) || other.host == host) && (identical(other.host, host) || other.host == host) &&
(identical(other.process, process) || other.process == process) &&
(identical(other.remoteDestination, remoteDestination) || (identical(other.remoteDestination, remoteDestination) ||
other.remoteDestination == remoteDestination)); other.remoteDestination == remoteDestination));
} }
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
int get hashCode => Object.hash( int get hashCode => Object.hash(runtimeType, uid, network, sourceIP,
runtimeType, sourcePort, destinationIP, destinationPort, host, remoteDestination);
uid,
network,
sourceIP,
sourcePort,
destinationIP,
destinationPort,
host,
process,
remoteDestination);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@@ -298,7 +272,6 @@ abstract class _Metadata implements Metadata {
required final String destinationIP, required final String destinationIP,
required final String destinationPort, required final String destinationPort,
required final String host, required final String host,
required final String process,
required final String remoteDestination}) = _$MetadataImpl; required final String remoteDestination}) = _$MetadataImpl;
factory _Metadata.fromJson(Map<String, dynamic> json) = factory _Metadata.fromJson(Map<String, dynamic> json) =
@@ -319,8 +292,6 @@ abstract class _Metadata implements Metadata {
@override @override
String get host; String get host;
@override @override
String get process;
@override
String get remoteDestination; String get remoteDestination;
@override @override
@JsonKey(ignore: true) @JsonKey(ignore: true)

View File

@@ -15,7 +15,6 @@ _$MetadataImpl _$$MetadataImplFromJson(Map<String, dynamic> json) =>
destinationIP: json['destinationIP'] as String, destinationIP: json['destinationIP'] as String,
destinationPort: json['destinationPort'] as String, destinationPort: json['destinationPort'] as String,
host: json['host'] as String, host: json['host'] as String,
process: json['process'] as String,
remoteDestination: json['remoteDestination'] as String, remoteDestination: json['remoteDestination'] as String,
); );
@@ -28,7 +27,6 @@ Map<String, dynamic> _$$MetadataImplToJson(_$MetadataImpl instance) =>
'destinationIP': instance.destinationIP, 'destinationIP': instance.destinationIP,
'destinationPort': instance.destinationPort, 'destinationPort': instance.destinationPort,
'host': instance.host, 'host': instance.host,
'process': instance.process,
'remoteDestination': instance.remoteDestination, 'remoteDestination': instance.remoteDestination,
}; };

View File

@@ -848,8 +848,10 @@ Process _$ProcessFromJson(Map<String, dynamic> json) {
/// @nodoc /// @nodoc
mixin _$Process { mixin _$Process {
int get id => throw _privateConstructorUsedError; int get uid => throw _privateConstructorUsedError;
Metadata get metadata => throw _privateConstructorUsedError; String get network => throw _privateConstructorUsedError;
String get source => throw _privateConstructorUsedError;
String get target => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError; Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
@@ -861,9 +863,7 @@ abstract class $ProcessCopyWith<$Res> {
factory $ProcessCopyWith(Process value, $Res Function(Process) then) = factory $ProcessCopyWith(Process value, $Res Function(Process) then) =
_$ProcessCopyWithImpl<$Res, Process>; _$ProcessCopyWithImpl<$Res, Process>;
@useResult @useResult
$Res call({int id, Metadata metadata}); $Res call({int uid, String network, String source, String target});
$MetadataCopyWith<$Res> get metadata;
} }
/// @nodoc /// @nodoc
@@ -879,28 +879,30 @@ class _$ProcessCopyWithImpl<$Res, $Val extends Process>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? id = null, Object? uid = null,
Object? metadata = null, Object? network = null,
Object? source = null,
Object? target = null,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
id: null == id uid: null == uid
? _value.id ? _value.uid
: id // ignore: cast_nullable_to_non_nullable : uid // ignore: cast_nullable_to_non_nullable
as int, as int,
metadata: null == metadata network: null == network
? _value.metadata ? _value.network
: metadata // ignore: cast_nullable_to_non_nullable : network // ignore: cast_nullable_to_non_nullable
as Metadata, as String,
source: null == source
? _value.source
: source // ignore: cast_nullable_to_non_nullable
as String,
target: null == target
? _value.target
: target // ignore: cast_nullable_to_non_nullable
as String,
) as $Val); ) 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 /// @nodoc
@@ -910,10 +912,7 @@ abstract class _$$ProcessImplCopyWith<$Res> implements $ProcessCopyWith<$Res> {
__$$ProcessImplCopyWithImpl<$Res>; __$$ProcessImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({int id, Metadata metadata}); $Res call({int uid, String network, String source, String target});
@override
$MetadataCopyWith<$Res> get metadata;
} }
/// @nodoc /// @nodoc
@@ -927,18 +926,28 @@ class __$$ProcessImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline') @pragma('vm:prefer-inline')
@override @override
$Res call({ $Res call({
Object? id = null, Object? uid = null,
Object? metadata = null, Object? network = null,
Object? source = null,
Object? target = null,
}) { }) {
return _then(_$ProcessImpl( return _then(_$ProcessImpl(
id: null == id uid: null == uid
? _value.id ? _value.uid
: id // ignore: cast_nullable_to_non_nullable : uid // ignore: cast_nullable_to_non_nullable
as int, as int,
metadata: null == metadata network: null == network
? _value.metadata ? _value.network
: metadata // ignore: cast_nullable_to_non_nullable : network // ignore: cast_nullable_to_non_nullable
as Metadata, as String,
source: null == source
? _value.source
: source // ignore: cast_nullable_to_non_nullable
as String,
target: null == target
? _value.target
: target // ignore: cast_nullable_to_non_nullable
as String,
)); ));
} }
} }
@@ -946,19 +955,27 @@ class __$$ProcessImplCopyWithImpl<$Res>
/// @nodoc /// @nodoc
@JsonSerializable() @JsonSerializable()
class _$ProcessImpl implements _Process { class _$ProcessImpl implements _Process {
const _$ProcessImpl({required this.id, required this.metadata}); const _$ProcessImpl(
{required this.uid,
required this.network,
required this.source,
required this.target});
factory _$ProcessImpl.fromJson(Map<String, dynamic> json) => factory _$ProcessImpl.fromJson(Map<String, dynamic> json) =>
_$$ProcessImplFromJson(json); _$$ProcessImplFromJson(json);
@override @override
final int id; final int uid;
@override @override
final Metadata metadata; final String network;
@override
final String source;
@override
final String target;
@override @override
String toString() { String toString() {
return 'Process(id: $id, metadata: $metadata)'; return 'Process(uid: $uid, network: $network, source: $source, target: $target)';
} }
@override @override
@@ -966,14 +983,15 @@ class _$ProcessImpl implements _Process {
return identical(this, other) || return identical(this, other) ||
(other.runtimeType == runtimeType && (other.runtimeType == runtimeType &&
other is _$ProcessImpl && other is _$ProcessImpl &&
(identical(other.id, id) || other.id == id) && (identical(other.uid, uid) || other.uid == uid) &&
(identical(other.metadata, metadata) || (identical(other.network, network) || other.network == network) &&
other.metadata == metadata)); (identical(other.source, source) || other.source == source) &&
(identical(other.target, target) || other.target == target));
} }
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
int get hashCode => Object.hash(runtimeType, id, metadata); int get hashCode => Object.hash(runtimeType, uid, network, source, target);
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@@ -991,175 +1009,27 @@ class _$ProcessImpl implements _Process {
abstract class _Process implements Process { abstract class _Process implements Process {
const factory _Process( const factory _Process(
{required final int id, {required final int uid,
required final Metadata metadata}) = _$ProcessImpl; required final String network,
required final String source,
required final String target}) = _$ProcessImpl;
factory _Process.fromJson(Map<String, dynamic> json) = _$ProcessImpl.fromJson; factory _Process.fromJson(Map<String, dynamic> json) = _$ProcessImpl.fromJson;
@override @override
int get id; int get uid;
@override @override
Metadata get metadata; String get network;
@override
String get source;
@override
String get target;
@override @override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$ProcessImplCopyWith<_$ProcessImpl> get copyWith => _$$ProcessImplCopyWith<_$ProcessImpl> get copyWith =>
throw _privateConstructorUsedError; throw _privateConstructorUsedError;
} }
ProcessMapItem _$ProcessMapItemFromJson(Map<String, dynamic> json) {
return _ProcessMapItem.fromJson(json);
}
/// @nodoc
mixin _$ProcessMapItem {
int get id => throw _privateConstructorUsedError;
String? get value => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ProcessMapItemCopyWith<ProcessMapItem> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ProcessMapItemCopyWith<$Res> {
factory $ProcessMapItemCopyWith(
ProcessMapItem value, $Res Function(ProcessMapItem) then) =
_$ProcessMapItemCopyWithImpl<$Res, ProcessMapItem>;
@useResult
$Res call({int id, String? value});
}
/// @nodoc
class _$ProcessMapItemCopyWithImpl<$Res, $Val extends ProcessMapItem>
implements $ProcessMapItemCopyWith<$Res> {
_$ProcessMapItemCopyWithImpl(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? value = freezed,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
value: freezed == value
? _value.value
: value // ignore: cast_nullable_to_non_nullable
as String?,
) as $Val);
}
}
/// @nodoc
abstract class _$$ProcessMapItemImplCopyWith<$Res>
implements $ProcessMapItemCopyWith<$Res> {
factory _$$ProcessMapItemImplCopyWith(_$ProcessMapItemImpl value,
$Res Function(_$ProcessMapItemImpl) then) =
__$$ProcessMapItemImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({int id, String? value});
}
/// @nodoc
class __$$ProcessMapItemImplCopyWithImpl<$Res>
extends _$ProcessMapItemCopyWithImpl<$Res, _$ProcessMapItemImpl>
implements _$$ProcessMapItemImplCopyWith<$Res> {
__$$ProcessMapItemImplCopyWithImpl(
_$ProcessMapItemImpl _value, $Res Function(_$ProcessMapItemImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? value = freezed,
}) {
return _then(_$ProcessMapItemImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
value: freezed == value
? _value.value
: value // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ProcessMapItemImpl implements _ProcessMapItem {
const _$ProcessMapItemImpl({required this.id, this.value});
factory _$ProcessMapItemImpl.fromJson(Map<String, dynamic> json) =>
_$$ProcessMapItemImplFromJson(json);
@override
final int id;
@override
final String? value;
@override
String toString() {
return 'ProcessMapItem(id: $id, value: $value)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ProcessMapItemImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.value, value) || other.value == value));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, id, value);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ProcessMapItemImplCopyWith<_$ProcessMapItemImpl> get copyWith =>
__$$ProcessMapItemImplCopyWithImpl<_$ProcessMapItemImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ProcessMapItemImplToJson(
this,
);
}
}
abstract class _ProcessMapItem implements ProcessMapItem {
const factory _ProcessMapItem({required final int id, final String? value}) =
_$ProcessMapItemImpl;
factory _ProcessMapItem.fromJson(Map<String, dynamic> json) =
_$ProcessMapItemImpl.fromJson;
@override
int get id;
@override
String? get value;
@override
@JsonKey(ignore: true)
_$$ProcessMapItemImplCopyWith<_$ProcessMapItemImpl> get copyWith =>
throw _privateConstructorUsedError;
}
ExternalProvider _$ExternalProviderFromJson(Map<String, dynamic> json) { ExternalProvider _$ExternalProviderFromJson(Map<String, dynamic> json) {
return _ExternalProvider.fromJson(json); return _ExternalProvider.fromJson(json);
} }

View File

@@ -56,7 +56,6 @@ const _$MessageTypeEnumMap = {
MessageType.delay: 'delay', MessageType.delay: 'delay',
MessageType.process: 'process', MessageType.process: 'process',
MessageType.now: 'now', MessageType.now: 'now',
MessageType.request: 'request',
}; };
_$DelayImpl _$$DelayImplFromJson(Map<String, dynamic> json) => _$DelayImpl( _$DelayImpl _$$DelayImplFromJson(Map<String, dynamic> json) => _$DelayImpl(
@@ -82,27 +81,18 @@ Map<String, dynamic> _$$NowImplToJson(_$NowImpl instance) => <String, dynamic>{
_$ProcessImpl _$$ProcessImplFromJson(Map<String, dynamic> json) => _$ProcessImpl _$$ProcessImplFromJson(Map<String, dynamic> json) =>
_$ProcessImpl( _$ProcessImpl(
id: (json['id'] as num).toInt(), uid: (json['uid'] as num).toInt(),
metadata: Metadata.fromJson(json['metadata'] as Map<String, dynamic>), network: json['network'] as String,
source: json['source'] as String,
target: json['target'] as String,
); );
Map<String, dynamic> _$$ProcessImplToJson(_$ProcessImpl instance) => Map<String, dynamic> _$$ProcessImplToJson(_$ProcessImpl instance) =>
<String, dynamic>{ <String, dynamic>{
'id': instance.id, 'uid': instance.uid,
'metadata': instance.metadata, 'network': instance.network,
}; 'source': instance.source,
'target': instance.target,
_$ProcessMapItemImpl _$$ProcessMapItemImplFromJson(Map<String, dynamic> json) =>
_$ProcessMapItemImpl(
id: (json['id'] as num).toInt(),
value: json['value'] as String?,
);
Map<String, dynamic> _$$ProcessMapItemImplToJson(
_$ProcessMapItemImpl instance) =>
<String, dynamic>{
'id': instance.id,
'value': instance.value,
}; };
_$ExternalProviderImpl _$$ExternalProviderImplFromJson( _$ExternalProviderImpl _$$ExternalProviderImplFromJson(

View File

@@ -24,10 +24,10 @@ Profile _$ProfileFromJson(Map<String, dynamic> json) => Profile(
id: json['id'] as String?, id: json['id'] as String?,
label: json['label'] as String?, label: json['label'] as String?,
url: json['url'] as String?, url: json['url'] as String?,
currentGroupName: json['currentGroupName'] as String?,
userInfo: json['userInfo'] == null userInfo: json['userInfo'] == null
? null ? null
: UserInfo.fromJson(json['userInfo'] as Map<String, dynamic>), : UserInfo.fromJson(json['userInfo'] as Map<String, dynamic>),
proxyName: json['proxyName'] as String?,
lastUpdateDate: json['lastUpdateDate'] == null lastUpdateDate: json['lastUpdateDate'] == null
? null ? null
: DateTime.parse(json['lastUpdateDate'] as String), : DateTime.parse(json['lastUpdateDate'] as String),
@@ -43,7 +43,7 @@ Profile _$ProfileFromJson(Map<String, dynamic> json) => Profile(
Map<String, dynamic> _$ProfileToJson(Profile instance) => <String, dynamic>{ Map<String, dynamic> _$ProfileToJson(Profile instance) => <String, dynamic>{
'id': instance.id, 'id': instance.id,
'label': instance.label, 'label': instance.label,
'currentGroupName': instance.currentGroupName, 'proxyName': instance.proxyName,
'url': instance.url, 'url': instance.url,
'lastUpdateDate': instance.lastUpdateDate?.toIso8601String(), 'lastUpdateDate': instance.lastUpdateDate?.toIso8601String(),
'autoUpdateDuration': instance.autoUpdateDuration.inMicroseconds, 'autoUpdateDuration': instance.autoUpdateDuration.inMicroseconds,

View File

@@ -28,8 +28,6 @@ const _$GroupTypeEnumMap = {
GroupType.Selector: 'Selector', GroupType.Selector: 'Selector',
GroupType.URLTest: 'URLTest', GroupType.URLTest: 'URLTest',
GroupType.Fallback: 'Fallback', GroupType.Fallback: 'Fallback',
GroupType.LoadBalance: 'LoadBalance',
GroupType.Relay: 'Relay',
}; };
_$ProxyImpl _$$ProxyImplFromJson(Map<String, dynamic> json) => _$ProxyImpl( _$ProxyImpl _$$ProxyImplFromJson(Map<String, dynamic> json) => _$ProxyImpl(

View File

@@ -1583,7 +1583,6 @@ abstract class _ProxiesCardSelectorState implements ProxiesCardSelectorState {
/// @nodoc /// @nodoc
mixin _$ProxiesSelectorState { mixin _$ProxiesSelectorState {
List<String> get groupNames => throw _privateConstructorUsedError; List<String> get groupNames => throw _privateConstructorUsedError;
String? get currentGroupName => throw _privateConstructorUsedError;
@JsonKey(ignore: true) @JsonKey(ignore: true)
$ProxiesSelectorStateCopyWith<ProxiesSelectorState> get copyWith => $ProxiesSelectorStateCopyWith<ProxiesSelectorState> get copyWith =>
@@ -1596,7 +1595,7 @@ abstract class $ProxiesSelectorStateCopyWith<$Res> {
$Res Function(ProxiesSelectorState) then) = $Res Function(ProxiesSelectorState) then) =
_$ProxiesSelectorStateCopyWithImpl<$Res, ProxiesSelectorState>; _$ProxiesSelectorStateCopyWithImpl<$Res, ProxiesSelectorState>;
@useResult @useResult
$Res call({List<String> groupNames, String? currentGroupName}); $Res call({List<String> groupNames});
} }
/// @nodoc /// @nodoc
@@ -1614,17 +1613,12 @@ class _$ProxiesSelectorStateCopyWithImpl<$Res,
@override @override
$Res call({ $Res call({
Object? groupNames = null, Object? groupNames = null,
Object? currentGroupName = freezed,
}) { }) {
return _then(_value.copyWith( return _then(_value.copyWith(
groupNames: null == groupNames groupNames: null == groupNames
? _value.groupNames ? _value.groupNames
: groupNames // ignore: cast_nullable_to_non_nullable : groupNames // ignore: cast_nullable_to_non_nullable
as List<String>, as List<String>,
currentGroupName: freezed == currentGroupName
? _value.currentGroupName
: currentGroupName // ignore: cast_nullable_to_non_nullable
as String?,
) as $Val); ) as $Val);
} }
} }
@@ -1637,7 +1631,7 @@ abstract class _$$ProxiesSelectorStateImplCopyWith<$Res>
__$$ProxiesSelectorStateImplCopyWithImpl<$Res>; __$$ProxiesSelectorStateImplCopyWithImpl<$Res>;
@override @override
@useResult @useResult
$Res call({List<String> groupNames, String? currentGroupName}); $Res call({List<String> groupNames});
} }
/// @nodoc /// @nodoc
@@ -1652,17 +1646,12 @@ class __$$ProxiesSelectorStateImplCopyWithImpl<$Res>
@override @override
$Res call({ $Res call({
Object? groupNames = null, Object? groupNames = null,
Object? currentGroupName = freezed,
}) { }) {
return _then(_$ProxiesSelectorStateImpl( return _then(_$ProxiesSelectorStateImpl(
groupNames: null == groupNames groupNames: null == groupNames
? _value._groupNames ? _value._groupNames
: groupNames // ignore: cast_nullable_to_non_nullable : groupNames // ignore: cast_nullable_to_non_nullable
as List<String>, as List<String>,
currentGroupName: freezed == currentGroupName
? _value.currentGroupName
: currentGroupName // ignore: cast_nullable_to_non_nullable
as String?,
)); ));
} }
} }
@@ -1670,8 +1659,7 @@ class __$$ProxiesSelectorStateImplCopyWithImpl<$Res>
/// @nodoc /// @nodoc
class _$ProxiesSelectorStateImpl implements _ProxiesSelectorState { class _$ProxiesSelectorStateImpl implements _ProxiesSelectorState {
const _$ProxiesSelectorStateImpl( const _$ProxiesSelectorStateImpl({required final List<String> groupNames})
{required final List<String> groupNames, required this.currentGroupName})
: _groupNames = groupNames; : _groupNames = groupNames;
final List<String> _groupNames; final List<String> _groupNames;
@@ -1682,12 +1670,9 @@ class _$ProxiesSelectorStateImpl implements _ProxiesSelectorState {
return EqualUnmodifiableListView(_groupNames); return EqualUnmodifiableListView(_groupNames);
} }
@override
final String? currentGroupName;
@override @override
String toString() { String toString() {
return 'ProxiesSelectorState(groupNames: $groupNames, currentGroupName: $currentGroupName)'; return 'ProxiesSelectorState(groupNames: $groupNames)';
} }
@override @override
@@ -1696,14 +1681,12 @@ class _$ProxiesSelectorStateImpl implements _ProxiesSelectorState {
(other.runtimeType == runtimeType && (other.runtimeType == runtimeType &&
other is _$ProxiesSelectorStateImpl && other is _$ProxiesSelectorStateImpl &&
const DeepCollectionEquality() const DeepCollectionEquality()
.equals(other._groupNames, _groupNames) && .equals(other._groupNames, _groupNames));
(identical(other.currentGroupName, currentGroupName) ||
other.currentGroupName == currentGroupName));
} }
@override @override
int get hashCode => Object.hash(runtimeType, int get hashCode => Object.hash(
const DeepCollectionEquality().hash(_groupNames), currentGroupName); runtimeType, const DeepCollectionEquality().hash(_groupNames));
@JsonKey(ignore: true) @JsonKey(ignore: true)
@override @override
@@ -1716,14 +1699,11 @@ class _$ProxiesSelectorStateImpl implements _ProxiesSelectorState {
abstract class _ProxiesSelectorState implements ProxiesSelectorState { abstract class _ProxiesSelectorState implements ProxiesSelectorState {
const factory _ProxiesSelectorState( const factory _ProxiesSelectorState(
{required final List<String> groupNames, {required final List<String> groupNames}) = _$ProxiesSelectorStateImpl;
required final String? currentGroupName}) = _$ProxiesSelectorStateImpl;
@override @override
List<String> get groupNames; List<String> get groupNames;
@override @override
String? get currentGroupName;
@override
@JsonKey(ignore: true) @JsonKey(ignore: true)
_$$ProxiesSelectorStateImplCopyWith<_$ProxiesSelectorStateImpl> _$$ProxiesSelectorStateImplCopyWith<_$ProxiesSelectorStateImpl>
get copyWith => throw _privateConstructorUsedError; get copyWith => throw _privateConstructorUsedError;

View File

@@ -62,7 +62,7 @@ class UserInfo {
class Profile { class Profile {
String id; String id;
String? label; String? label;
String? currentGroupName; String? proxyName;
String? url; String? url;
DateTime? lastUpdateDate; DateTime? lastUpdateDate;
Duration autoUpdateDuration; Duration autoUpdateDuration;
@@ -74,8 +74,8 @@ class Profile {
String? id, String? id,
this.label, this.label,
this.url, this.url,
this.currentGroupName,
this.userInfo, this.userInfo,
this.proxyName,
this.lastUpdateDate, this.lastUpdateDate,
SelectedMap? selectedMap, SelectedMap? selectedMap,
Duration? autoUpdateDuration, Duration? autoUpdateDuration,
@@ -134,7 +134,6 @@ class Profile {
return _$ProfileFromJson(json); return _$ProfileFromJson(json);
} }
@override @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
@@ -142,31 +141,34 @@ class Profile {
runtimeType == other.runtimeType && runtimeType == other.runtimeType &&
id == other.id && id == other.id &&
label == other.label && label == other.label &&
currentGroupName == other.currentGroupName && proxyName == other.proxyName &&
url == other.url && url == other.url &&
lastUpdateDate == other.lastUpdateDate && lastUpdateDate == other.lastUpdateDate &&
autoUpdateDuration == other.autoUpdateDuration && autoUpdateDuration == other.autoUpdateDuration &&
userInfo == other.userInfo && userInfo == other.userInfo &&
autoUpdate == other.autoUpdate && autoUpdate == other.autoUpdate;
selectedMap == other.selectedMap;
@override @override
int get hashCode => int get hashCode =>
id.hashCode ^ id.hashCode ^
label.hashCode ^ label.hashCode ^
currentGroupName.hashCode ^ proxyName.hashCode ^
url.hashCode ^ url.hashCode ^
lastUpdateDate.hashCode ^ lastUpdateDate.hashCode ^
autoUpdateDuration.hashCode ^ autoUpdateDuration.hashCode ^
userInfo.hashCode ^ userInfo.hashCode ^
autoUpdate.hashCode ^ autoUpdate.hashCode;
selectedMap.hashCode;
@override
String toString() {
return 'Profile{id: $id, label: $label, proxyName: $proxyName, url: $url, lastUpdateDate: $lastUpdateDate, autoUpdateDuration: $autoUpdateDuration, userInfo: $userInfo, autoUpdate: $autoUpdate}';
}
Profile copyWith({ Profile copyWith({
String? label, String? label,
String? url, String? url,
UserInfo? userInfo, UserInfo? userInfo,
String? currentGroupName, String? groupName,
String? proxyName, String? proxyName,
DateTime? lastUpdateDate, DateTime? lastUpdateDate,
Duration? autoUpdateDuration, Duration? autoUpdateDuration,
@@ -177,7 +179,7 @@ class Profile {
id: id, id: id,
label: label ?? this.label, label: label ?? this.label,
url: url ?? this.url, url: url ?? this.url,
currentGroupName: currentGroupName ?? this.currentGroupName, proxyName: proxyName ?? this.proxyName,
userInfo: userInfo ?? this.userInfo, userInfo: userInfo ?? this.userInfo,
selectedMap: selectedMap ?? this.selectedMap, selectedMap: selectedMap ?? this.selectedMap,
lastUpdateDate: lastUpdateDate ?? this.lastUpdateDate, lastUpdateDate: lastUpdateDate ?? this.lastUpdateDate,

View File

@@ -94,7 +94,6 @@ class ProxiesCardSelectorState with _$ProxiesCardSelectorState {
class ProxiesSelectorState with _$ProxiesSelectorState { class ProxiesSelectorState with _$ProxiesSelectorState {
const factory ProxiesSelectorState({ const factory ProxiesSelectorState({
required List<String> groupNames, required List<String> groupNames,
required String? currentGroupName,
}) = _ProxiesSelectorState; }) = _ProxiesSelectorState;
} }

View File

@@ -107,9 +107,6 @@ class _ScanPageState extends State<ScanPage> with WidgetsBindingObserver {
case TorchState.unavailable: case TorchState.unavailable:
icon = const Icon(Icons.flash_off); icon = const Icon(Icons.flash_off);
backgroundColor = Colors.transparent; backgroundColor = Colors.transparent;
case TorchState.auto:
icon = const Icon(Icons.flash_auto);
backgroundColor = Colors.orange;
} }
return Container( return Container(
margin: const EdgeInsets.symmetric(horizontal: 8), margin: const EdgeInsets.symmetric(horizontal: 8),

View File

@@ -3,7 +3,6 @@ import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'dart:isolate'; import 'dart:isolate';
import 'package:fl_clash/clash/clash.dart';
import 'package:fl_clash/models/models.dart'; import 'package:fl_clash/models/models.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@@ -23,9 +22,6 @@ class App {
await onExit!(); await onExit!();
} }
break; break;
case "gc":
clashCore.requestGc();
break;
default: default:
throw MissingPluginException(); throw MissingPluginException();
} }
@@ -33,6 +29,10 @@ class App {
} }
} }
setOnExit(Function() onExit) {
this.onExit = onExit;
}
factory App() { factory App() {
_instance ??= App._internal(); _instance ??= App._internal();
return _instance!; return _instance!;
@@ -68,9 +68,9 @@ class App {
}); });
} }
Future<String?> resolverProcess(Process process) async { Future<String?> getPackageName(Metadata metadata) async {
return await methodChannel?.invokeMethod<String>("resolverProcess", { return await methodChannel?.invokeMethod<String>("getPackageName", {
"data": json.encode(process), "data": json.encode(metadata),
}); });
} }
} }

View File

@@ -56,6 +56,10 @@ class Proxy extends ProxyPlatform {
return await methodChannel.invokeMethod<bool?>("SetProtect", {'fd': fd}); return await methodChannel.invokeMethod<bool?>("SetProtect", {'fd': fd});
} }
Future<int?> getRunTimeStamp() async {
return await methodChannel.invokeMethod<int?>("GetRunTimeStamp");
}
Future<bool?> startForeground({ Future<bool?> startForeground({
required String title, required String title,
required String content, required String content,
@@ -76,7 +80,14 @@ class Proxy extends ProxyPlatform {
} }
updateStartTime() async { updateStartTime() async {
startTime = clashCore.getRunTime(); startTime = await getRunTime();
}
Future<DateTime?> getRunTime() async {
final runTimeStamp = await getRunTimeStamp();
return runTimeStamp != null
? DateTime.fromMillisecondsSinceEpoch(runTimeStamp)
: null;
} }
} }

View File

@@ -17,6 +17,7 @@ class GlobalState {
Function? updateCurrentDelayDebounce; Function? updateCurrentDelayDebounce;
PageController? pageController; PageController? pageController;
final navigatorKey = GlobalKey<NavigatorState>(); final navigatorKey = GlobalKey<NavigatorState>();
final Map<int, String?> packageNameMap = {};
late AppController appController; late AppController appController;
GlobalKey<CommonScaffoldState> homeScaffoldKey = GlobalKey(); GlobalKey<CommonScaffoldState> homeScaffoldKey = GlobalKey();
List<Function> updateFunctionLists = []; List<Function> updateFunctionLists = [];
@@ -60,14 +61,8 @@ class GlobalState {
required Config config, required Config config,
required ClashConfig clashConfig, required ClashConfig clashConfig,
}) async { }) async {
final args = config.isAccessControl final args =
? json.encode( config.isAccessControl ? json.encode(config.accessControl) : null;
Props(
accessControl: config.accessControl,
allowBypass: config.allowBypass,
),
)
: null;
await proxyManager.startProxy( await proxyManager.startProxy(
port: clashConfig.mixedPort, port: clashConfig.mixedPort,
args: args, args: args,
@@ -110,6 +105,12 @@ class GlobalState {
clashConfig: clashConfig, clashConfig: clashConfig,
); );
} }
if (!appState.isInit) return;
await applyProfile(
appState: appState,
config: config,
clashConfig: clashConfig,
);
updateCoreVersionInfo(appState); updateCoreVersionInfo(appState);
} }
@@ -132,6 +133,19 @@ class GlobalState {
}); });
} }
updateNavigationItems({
required AppState appState,
required Config config,
required ClashConfig clashConfig,
}) {
final group = appState.currentGroups;
final hasProfile = config.profiles.isNotEmpty;
appState.navigationItems = navigation.getItems(
openLogs: config.openLogs,
hasProxies: group.isNotEmpty && hasProfile,
);
}
Future<void> updateGroups(AppState appState) async { Future<void> updateGroups(AppState appState) async {
appState.groups = await clashCore.getProxiesGroups(); appState.groups = await clashCore.getProxiesGroups();
} }
@@ -211,30 +225,30 @@ class GlobalState {
required String message, required String message,
SnackBarAction? action, SnackBarAction? action,
}) { }) {
// final width = context.width; final width = context.width;
// EdgeInsets margin; EdgeInsets margin;
// if (width < 600) { if (width < 600) {
// margin = const EdgeInsets.only( margin = const EdgeInsets.only(
// bottom: 96, bottom: 96,
// right: 16, right: 16,
// left: 16, left: 16,
// ); );
// } else { } else {
// margin = EdgeInsets.only( margin = EdgeInsets.only(
// bottom: 16, bottom: 16,
// left: 16, left: 16,
// right: width - 316, right: width - 316,
// ); );
// } }
// ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
// SnackBar( SnackBar(
// action: action, action: action,
// content: Text(message), content: Text(message),
// behavior: SnackBarBehavior.floating, behavior: SnackBarBehavior.floating,
// duration: const Duration(milliseconds: 1500), duration: const Duration(milliseconds: 1500),
// margin: margin, margin: margin,
// ), ),
// ); );
} }
Future<T?> safeRun<T>( Future<T?> safeRun<T>(

View File

@@ -56,20 +56,9 @@ class _ClashMessageContainerState extends State<ClashMessageContainer>
} }
@override @override
void onProcess(Process process) async { void onProcess(Metadata metadata) async {
var packageName = await app?.resolverProcess(process); var packageName = await app?.getPackageName(metadata);
clashCore.setProcessMap( globalState.packageNameMap[metadata.uid] = packageName;
ProcessMapItem( super.onProcess(metadata);
id: process.id,
value: packageName,
),
);
super.onProcess(process);
}
@override
void onRequest(Connection connection) async {
globalState.appController.appState.addRequest(connection);
super.onRequest(connection);
} }
} }

View File

@@ -122,7 +122,7 @@ class CommonScaffoldState extends State<CommonScaffold> {
return floatingActionButton ?? Container(); return floatingActionButton ?? Container();
}, },
), ),
resizeToAvoidBottomInset: true, floatingActionButtonAnimator: FloatingActionButtonAnimator.scaling,
appBar: PreferredSize( appBar: PreferredSize(
preferredSize: const Size.fromHeight(kToolbarHeight), preferredSize: const Size.fromHeight(kToolbarHeight),
child: Stack( child: Stack(

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
name: fl_clash name: fl_clash
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free. description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
publish_to: 'none' publish_to: 'none'
version: 0.8.22 version: 0.8.16
environment: environment:
sdk: '>=3.1.0 <4.0.0' sdk: '>=3.1.0 <4.0.0'
@@ -17,14 +17,14 @@ dependencies:
provider: ^6.0.5 provider: ^6.0.5
window_manager: ^0.3.8 window_manager: ^0.3.8
ffi: ^2.1.0 ffi: ^2.1.0
dynamic_color: ^1.6.0 dynamic_color: ^1.7.0
proxy: proxy:
path: plugins/proxy path: plugins/proxy
launch_at_startup: ^0.2.2 launch_at_startup: ^0.2.2
windows_single_instance: ^1.0.1 windows_single_instance: ^1.0.1
json_annotation: ^4.9.0 json_annotation: ^4.9.0
file_picker: ^8.0.3 file_picker: ^8.0.3
mobile_scanner: ^5.1.1 mobile_scanner: 5.0.1
app_links: ^3.5.0 app_links: ^3.5.0
win32_registry: ^1.1.2 win32_registry: ^1.1.2
tray_manager: ^0.2.1 tray_manager: ^0.2.1

View File

@@ -12,7 +12,10 @@ enum PlatformType {
macos, macos,
} }
enum Arch { amd64, arm64, arm } enum Arch {
amd64,
arm64,
}
class BuildLibItem { class BuildLibItem {
PlatformType platform; PlatformType platform;
@@ -61,21 +64,16 @@ class Build {
arch: Arch.amd64, arch: Arch.amd64,
archName: 'amd64', archName: 'amd64',
), ),
// BuildLibItem(
// platform: PlatformType.android,
// arch: Arch.arm,
// archName: 'armeabi-v7a',
// ),
BuildLibItem( BuildLibItem(
platform: PlatformType.android, platform: PlatformType.android,
arch: Arch.arm64, arch: Arch.arm64,
archName: 'arm64-v8a', archName: 'arm64-v8a',
), ),
// BuildLibItem( BuildLibItem(
// platform: PlatformType.android, platform: PlatformType.android,
// arch: Arch.amd64, arch: Arch.amd64,
// archName: 'x86_64', archName: 'x86_64',
// ), ),
BuildLibItem( BuildLibItem(
platform: PlatformType.linux, platform: PlatformType.linux,
arch: Arch.amd64, arch: Arch.amd64,
@@ -336,7 +334,7 @@ class BuildCommand extends Command {
final archName = argResults?['arch']; final archName = argResults?['arch'];
final currentArches = final currentArches =
arches.where((element) => element.name == archName).toList(); arches.where((element) => element.name == archName).toList();
final arch = currentArches.isEmpty ? null : currentArches.first; final arch = currentArches.isEmpty ? null : arches.first;
await _buildLib(arch); await _buildLib(arch);
if (build != "all") { if (build != "all") {
return; return;
@@ -359,11 +357,10 @@ class BuildCommand extends Command {
break; break;
case PlatformType.android: case PlatformType.android:
final targetMap = { final targetMap = {
Arch.arm: "android-arm",
Arch.arm64: "android-arm64",
Arch.amd64: "android-x64", Arch.amd64: "android-x64",
Arch.arm64: "android-arm64"
}; };
final defaultArches = [Arch.arm, Arch.arm64, Arch.amd64]; final defaultArches = [Arch.amd64, Arch.arm64];
final defaultTargets = defaultArches final defaultTargets = defaultArches
.where((element) => arch == null ? true : element == arch) .where((element) => arch == null ? true : element == arch)
.map((e) => targetMap[e]) .map((e) => targetMap[e])