Fix android tile service
Support append system DNS Fix some issues
This commit is contained in:
@@ -66,6 +66,7 @@
|
||||
|
||||
<activity
|
||||
android:name=".TempActivity"
|
||||
android:excludeFromRecents="true"
|
||||
android:exported="true"
|
||||
android:theme="@style/TransparentTheme">
|
||||
<intent-filter>
|
||||
|
||||
@@ -20,7 +20,9 @@ class BroadcastReceiver : BroadcastReceiver() {
|
||||
|
||||
BroadcastAction.SERVICE_DESTROYED.action -> {
|
||||
GlobalState.log("Receiver service destroyed")
|
||||
State.handleStopServiceAction()
|
||||
GlobalState.launch {
|
||||
State.handleStopServiceAction()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,19 +65,30 @@ object State {
|
||||
}
|
||||
|
||||
suspend fun handleStartServiceAction() {
|
||||
tilePlugin?.handleStart()
|
||||
if (flutterEngine != null) {
|
||||
return
|
||||
runLock.withLock {
|
||||
if (runStateFlow.value != RunState.STOP) {
|
||||
return
|
||||
}
|
||||
tilePlugin?.handleStart()
|
||||
if (flutterEngine != null) {
|
||||
return
|
||||
}
|
||||
startServiceWithEngine()
|
||||
}
|
||||
startServiceWithEngine()
|
||||
|
||||
}
|
||||
|
||||
fun handleStopServiceAction() {
|
||||
tilePlugin?.handleStop()
|
||||
if (flutterEngine != null || serviceFlutterEngine != null) {
|
||||
return
|
||||
suspend fun handleStopServiceAction() {
|
||||
runLock.withLock {
|
||||
if (runStateFlow.value != RunState.START) {
|
||||
return
|
||||
}
|
||||
tilePlugin?.handleStop()
|
||||
if (flutterEngine != null || serviceFlutterEngine != null) {
|
||||
return
|
||||
}
|
||||
handleStopService()
|
||||
}
|
||||
handleStopService()
|
||||
}
|
||||
|
||||
fun handleStartService() {
|
||||
@@ -90,8 +101,23 @@ object State {
|
||||
startService()
|
||||
}
|
||||
|
||||
fun handleStopService() {
|
||||
GlobalState.launch {
|
||||
runLock.withLock {
|
||||
if (runStateFlow.value != RunState.START) {
|
||||
return@launch
|
||||
}
|
||||
runStateFlow.tryEmit(RunState.PENDING)
|
||||
runTime = Service.stopService()
|
||||
runStateFlow.tryEmit(RunState.STOP)
|
||||
}
|
||||
destroyServiceEngine()
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun destroyServiceEngine() {
|
||||
runLock.withLock {
|
||||
GlobalState.log("Destroy service engine")
|
||||
withContext(Dispatchers.Main) {
|
||||
runCatching {
|
||||
serviceFlutterEngine?.destroy()
|
||||
@@ -101,20 +127,24 @@ object State {
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun startServiceWithEngine() {
|
||||
runLock.withLock {
|
||||
if (serviceFlutterEngine != null || runStateFlow.value == RunState.PENDING || runStateFlow.value == RunState.START) {
|
||||
return
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
serviceFlutterEngine = FlutterEngine(GlobalState.application)
|
||||
serviceFlutterEngine?.plugins?.add(ServicePlugin())
|
||||
serviceFlutterEngine?.plugins?.add(AppPlugin())
|
||||
serviceFlutterEngine?.plugins?.add(TilePlugin())
|
||||
val dartEntrypoint = DartExecutor.DartEntrypoint(
|
||||
FlutterInjector.instance().flutterLoader().findAppBundlePath(), "_service"
|
||||
)
|
||||
serviceFlutterEngine?.dartExecutor?.executeDartEntrypoint(dartEntrypoint)
|
||||
private fun startServiceWithEngine() {
|
||||
GlobalState.launch {
|
||||
runLock.withLock {
|
||||
if (runStateFlow.value != RunState.STOP) {
|
||||
return@launch
|
||||
}
|
||||
GlobalState.log("Create service engine")
|
||||
withContext(Dispatchers.Main) {
|
||||
serviceFlutterEngine?.destroy()
|
||||
serviceFlutterEngine = FlutterEngine(GlobalState.application)
|
||||
serviceFlutterEngine?.plugins?.add(ServicePlugin())
|
||||
serviceFlutterEngine?.plugins?.add(AppPlugin())
|
||||
serviceFlutterEngine?.plugins?.add(TilePlugin())
|
||||
val dartEntrypoint = DartExecutor.DartEntrypoint(
|
||||
FlutterInjector.instance().flutterLoader().findAppBundlePath(), "_service"
|
||||
)
|
||||
serviceFlutterEngine?.dartExecutor?.executeDartEntrypoint(dartEntrypoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,7 +152,7 @@ object State {
|
||||
private fun startService() {
|
||||
GlobalState.launch {
|
||||
runLock.withLock {
|
||||
if (runStateFlow.value == RunState.PENDING || runStateFlow.value == RunState.START) {
|
||||
if (runStateFlow.value != RunState.STOP) {
|
||||
return@launch
|
||||
}
|
||||
runStateFlow.tryEmit(RunState.PENDING)
|
||||
@@ -141,20 +171,6 @@ object State {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun handleStopService() {
|
||||
GlobalState.launch {
|
||||
runLock.withLock {
|
||||
if (runStateFlow.value == RunState.PENDING || runStateFlow.value == RunState.STOP) {
|
||||
return@launch
|
||||
}
|
||||
runStateFlow.tryEmit(RunState.PENDING)
|
||||
runTime = Service.stopService()
|
||||
runStateFlow.tryEmit(RunState.STOP)
|
||||
}
|
||||
destroyServiceEngine()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,9 @@ class TempActivity : Activity(),
|
||||
}
|
||||
|
||||
QuickAction.STOP.action -> {
|
||||
State.handleStopServiceAction()
|
||||
launch {
|
||||
State.handleStopServiceAction()
|
||||
}
|
||||
}
|
||||
|
||||
QuickAction.TOGGLE.action -> {
|
||||
@@ -30,6 +32,6 @@ class TempActivity : Activity(),
|
||||
}
|
||||
}
|
||||
}
|
||||
finishAndRemoveTask()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
@@ -8,25 +8,9 @@ message("CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
|
||||
if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
# set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
||||
add_compile_options(-O3)
|
||||
|
||||
add_compile_options(-flto)
|
||||
|
||||
add_compile_options(-g0)
|
||||
|
||||
add_compile_options(-ffunction-sections -fdata-sections)
|
||||
|
||||
add_compile_options(-fno-exceptions -fno-rtti)
|
||||
|
||||
add_link_options(
|
||||
-flto
|
||||
-Wl,--gc-sections
|
||||
-Wl,--strip-all
|
||||
-Wl,--exclude-libs=ALL
|
||||
)
|
||||
|
||||
add_compile_options(-fvisibility=hidden -fvisibility-inlines-hidden)
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
||||
add_compile_options(-O3 -flto -g0 -fno-exceptions -fno-rtti)
|
||||
add_link_options(-flto -Wl,--gc-sections,--strip-all)
|
||||
endif ()
|
||||
|
||||
set(LIB_CLASH_PATH "${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libclash.so")
|
||||
|
||||
@@ -432,5 +432,7 @@
|
||||
"dataCollectionTip": "Data Collection Notice",
|
||||
"dataCollectionContent": "This app uses Firebase Crashlytics to collect crash information to improve app stability.\nThe collected data includes device information and crash details, but does not contain personal sensitive data.\nYou can disable this feature in settings.",
|
||||
"crashlytics": "Crash Analysis",
|
||||
"crashlyticsTip": "When enabled, automatically uploads crash logs without sensitive information when the app crashes"
|
||||
"crashlyticsTip": "When enabled, automatically uploads crash logs without sensitive information when the app crashes",
|
||||
"appendSystemDns": "Append System DNS",
|
||||
"appendSystemDnsTip": "Forcefully append system DNS to the configuration"
|
||||
}
|
||||
@@ -433,5 +433,7 @@
|
||||
"dataCollectionTip": "データ収集説明",
|
||||
"dataCollectionContent": "本アプリはFirebase Crashlyticsを使用してクラッシュ情報を収集し、アプリの安定性を向上させます。\n収集されるデータにはデバイス情報とクラッシュ詳細が含まれますが、個人の機密データは含まれません。\n設定でこの機能を無効にすることができます。",
|
||||
"crashlytics": "クラッシュ分析",
|
||||
"crashlyticsTip": "有効にすると、アプリがクラッシュした際に機密情報を含まないクラッシュログを自動的にアップロードします"
|
||||
"crashlyticsTip": "有効にすると、アプリがクラッシュした際に機密情報を含まないクラッシュログを自動的にアップロードします",
|
||||
"appendSystemDns": "システムDNSを追加",
|
||||
"appendSystemDnsTip": "設定にシステムDNSを強制的に追加します"
|
||||
}
|
||||
@@ -433,5 +433,7 @@
|
||||
"dataCollectionTip": "Уведомление о сборе данных",
|
||||
"dataCollectionContent": "Это приложение использует Firebase Crashlytics для сбора информации о сбоях nhằm улучшения стабильности приложения.\nСобираемые данные включают информацию об устройстве и подробности о сбоях, но не содержат персональных конфиденциальных данных.\nВы можете отключить эту функцию в настройках.",
|
||||
"crashlytics": "Анализ сбоев",
|
||||
"crashlyticsTip": "При включении автоматически загружает журналы сбоев без конфиденциальной информации, когда приложение выходит из строя"
|
||||
"crashlyticsTip": "При включении автоматически загружает журналы сбоев без конфиденциальной информации, когда приложение выходит из строя",
|
||||
"appendSystemDns": "Добавить системный DNS",
|
||||
"appendSystemDnsTip": "Принудительно добавить системный DNS к конфигурации"
|
||||
}
|
||||
@@ -433,5 +433,7 @@
|
||||
"dataCollectionTip": "数据收集说明",
|
||||
"dataCollectionContent": "本应用使用 Firebase Crashlytics 收集崩溃信息以改进应用稳定性。\n收集的数据包括设备信息和崩溃详情,不包含个人敏感数据。\n您可以在设置中关闭此功能。",
|
||||
"crashlytics": "崩溃分析",
|
||||
"crashlyticsTip": "开启后,应用崩溃时自动上传不包含敏感信息的崩溃日志"
|
||||
"crashlyticsTip": "开启后,应用崩溃时自动上传不包含敏感信息的崩溃日志",
|
||||
"appendSystemDns": "追加系统DNS",
|
||||
"appendSystemDnsTip": "强制为配置附加系统DNS"
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/metacubex/mihomo/tunnel"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -269,6 +270,7 @@ func setupConfig(params *SetupParams) error {
|
||||
hub.ApplyConfig(currentConfig)
|
||||
patchSelectGroup(params.SelectedMap)
|
||||
updateListeners()
|
||||
runtime.GC()
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module core
|
||||
|
||||
go 1.25
|
||||
go 1.20
|
||||
|
||||
replace github.com/metacubex/mihomo => ./Clash.Meta
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
github.com/RyuaNerin/go-krypto v1.3.0 h1:smavTzSMAx8iuVlGb4pEwl9MD2qicqMzuXR2QWp2/Pg=
|
||||
github.com/RyuaNerin/go-krypto v1.3.0/go.mod h1:9R9TU936laAIqAmjcHo/LsaXYOZlymudOAxjaBf62UM=
|
||||
github.com/RyuaNerin/testingutil v0.1.0 h1:IYT6JL57RV3U2ml3dLHZsVtPOP6yNK7WUVdzzlpNrss=
|
||||
github.com/RyuaNerin/testingutil v0.1.0/go.mod h1:yTqj6Ta/ycHMPJHRyO12Mz3VrvTloWOsy23WOZH19AA=
|
||||
github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 h1:cDVUiFo+npB0ZASqnw4q90ylaVAbnYyx0JYqK4YcGok=
|
||||
github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk=
|
||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||
@@ -32,7 +31,6 @@ github.com/ericlagergren/aegis v0.0.0-20250325060835-cd0defd64358/go.mod h1:hkIF
|
||||
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/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/go.mod h1:4RfsapbGx2j/vU5xC/5/9qB3kn9Awp1YDiEnN43QrJ4=
|
||||
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA=
|
||||
@@ -46,7 +44,6 @@ github.com/go-chi/chi/v5 v5.2.3/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hH
|
||||
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/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
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-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
@@ -61,7 +58,6 @@ github.com/gofrs/uuid/v5 v5.3.2 h1:2jfO8j3XgSwlz/wHqemAEugfnTlikAYHhnqQ8Xh4fE0=
|
||||
github.com/gofrs/uuid/v5 v5.3.2/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
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/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
|
||||
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
@@ -71,7 +67,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/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
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/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905 h1:q3OEI9RaN/wwcx+qgGo6ZaoJkCiDYe/gjDLfq7lQQF4=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250109001534-8abf58130905/go.mod h1:VvGYjkZoJyKqlmT1yzakUs4mfKMNB0XdODP0+rdml6k=
|
||||
@@ -157,7 +152,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/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||
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/low v0.1.21 h1:Tr2GNu4N/+rGRYdOsEHOE89cxUIaDViZbVmKz29uKGo=
|
||||
github.com/openacid/low v0.1.21/go.mod h1:q+MsKI6Pz2xsCkzV4BLj7NR5M4EX0sGz5AqotpZDVh0=
|
||||
@@ -198,7 +192,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
|
||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
@@ -213,7 +206,6 @@ github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
|
||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
|
||||
gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7 h1:UNrDfkQqiEYzdMlNsVvBYOAJWZjdktqFE9tQh5BT2+4=
|
||||
gitlab.com/go-extension/aes-ccm v0.0.0-20230221065045-e58665ef23c7/go.mod h1:E+rxHvJG9H6PUdzq9NRG6csuLN3XUx98BfGOVWNYnXs=
|
||||
gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec h1:FpfFs4EhNehiVfzQttTuxanPIT43FtkkCFypIod8LHo=
|
||||
@@ -254,7 +246,6 @@ golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
|
||||
15
core/hub.go
15
core/hub.go
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/metacubex/mihomo/component/updater"
|
||||
"github.com/metacubex/mihomo/config"
|
||||
"github.com/metacubex/mihomo/constant"
|
||||
"github.com/metacubex/mihomo/constant/features"
|
||||
cp "github.com/metacubex/mihomo/constant/provider"
|
||||
"github.com/metacubex/mihomo/hub/executor"
|
||||
"github.com/metacubex/mihomo/listener"
|
||||
@@ -21,6 +22,7 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -33,6 +35,8 @@ var (
|
||||
)
|
||||
|
||||
func handleInitClash(paramsString string) bool {
|
||||
runLock.Lock()
|
||||
defer runLock.Unlock()
|
||||
var params = InitParams{}
|
||||
err := json.Unmarshal([]byte(paramsString), ¶ms)
|
||||
if err != nil {
|
||||
@@ -69,16 +73,17 @@ func handleGetIsInit() bool {
|
||||
}
|
||||
|
||||
func handleForceGC() {
|
||||
go func() {
|
||||
log.Infoln("[APP] request force GC")
|
||||
runtime.GC()
|
||||
}()
|
||||
log.Infoln("[APP] request force GC")
|
||||
runtime.GC()
|
||||
if features.Android {
|
||||
debug.FreeOSMemory()
|
||||
}
|
||||
}
|
||||
|
||||
func handleShutdown() bool {
|
||||
stopListeners()
|
||||
executor.Shutdown()
|
||||
runtime.GC()
|
||||
handleForceGC()
|
||||
isInit = false
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ type TunHandler struct {
|
||||
}
|
||||
|
||||
func (th *TunHandler) start(fd int, stack, address, dns string) {
|
||||
runLock.Lock()
|
||||
defer runLock.Unlock()
|
||||
_ = th.limit.Acquire(context.TODO(), 4)
|
||||
defer th.limit.Release(4)
|
||||
th.initHook()
|
||||
|
||||
@@ -82,8 +82,22 @@ class AppController {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> tryStartCore() async {
|
||||
if (coreController.isCompleted) {
|
||||
return;
|
||||
}
|
||||
globalState.isUserDisconnected = true;
|
||||
await _connectCore();
|
||||
await _initCore();
|
||||
_ref.read(initProvider.notifier).value = true;
|
||||
if (_ref.read(isStartProvider)) {
|
||||
await globalState.handleStart();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateStatus(bool isStart) async {
|
||||
if (isStart) {
|
||||
await globalState.appController.tryStartCore();
|
||||
await globalState.handleStart([updateRunTime, updateTraffic]);
|
||||
final currentLastModified = await _ref
|
||||
.read(currentProfileProvider)
|
||||
@@ -309,7 +323,6 @@ class AppController {
|
||||
}
|
||||
|
||||
Future _applyProfile() async {
|
||||
await coreController.requestGc();
|
||||
await setupClashConfig();
|
||||
await updateGroups();
|
||||
await updateProviders();
|
||||
@@ -466,9 +479,6 @@ class AppController {
|
||||
Map<String, dynamic>? data,
|
||||
bool handleError = false,
|
||||
}) async {
|
||||
if (globalState.isPre) {
|
||||
return;
|
||||
}
|
||||
if (data != null) {
|
||||
final tagName = data['tag_name'];
|
||||
final body = data['body'];
|
||||
@@ -557,7 +567,6 @@ class AppController {
|
||||
if (!globalState.isService) Future.delayed(Duration(milliseconds: 300)),
|
||||
]);
|
||||
final String message = result[0];
|
||||
await Future.delayed(commonDuration);
|
||||
if (message.isNotEmpty) {
|
||||
_ref.read(coreStatusProvider.notifier).value = CoreStatus.disconnected;
|
||||
if (context.mounted) {
|
||||
@@ -962,7 +971,7 @@ class AppController {
|
||||
final res = await futureFunction();
|
||||
return res;
|
||||
} catch (e) {
|
||||
commonPrint.log('$futureFunction ===> $e', logLevel: LogLevel.warning);
|
||||
commonPrint.log('$title===> $e', logLevel: LogLevel.warning);
|
||||
if (realSilence) {
|
||||
globalState.showNotifier(e.toString());
|
||||
} else {
|
||||
|
||||
@@ -29,6 +29,8 @@ class CoreController {
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
bool get isCompleted => _interface.completer.isCompleted;
|
||||
|
||||
Future<String> preload() {
|
||||
return _interface.preload();
|
||||
}
|
||||
@@ -91,10 +93,17 @@ class CoreController {
|
||||
return await _interface.updateConfig(updateParams);
|
||||
}
|
||||
|
||||
Future<String> setupConfig(ClashConfig clashConfig) async {
|
||||
Future<String> setupConfig(
|
||||
ClashConfig clashConfig, {
|
||||
VoidCallback? preloadInvoke,
|
||||
}) async {
|
||||
await globalState.genConfigFile(clashConfig);
|
||||
final params = await globalState.getSetupParams();
|
||||
return await _interface.setupConfig(params);
|
||||
final res = _interface.setupConfig(params);
|
||||
if (preloadInvoke != null) {
|
||||
preloadInvoke();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
Future<List<Group>> getProxiesGroups({
|
||||
|
||||
@@ -77,7 +77,7 @@ mixin CoreInterface {
|
||||
}
|
||||
|
||||
abstract class CoreHandlerInterface with CoreInterface {
|
||||
Future get connected;
|
||||
Completer get completer;
|
||||
|
||||
FutureOr<bool> destroy();
|
||||
|
||||
@@ -86,7 +86,7 @@ abstract class CoreHandlerInterface with CoreInterface {
|
||||
dynamic data,
|
||||
Duration? timeout,
|
||||
}) async {
|
||||
await connected;
|
||||
await completer.future;
|
||||
if (kDebugMode) {
|
||||
commonPrint.log('Invoke ${method.name} ${DateTime.now()} $data');
|
||||
}
|
||||
@@ -157,7 +157,7 @@ abstract class CoreHandlerInterface with CoreInterface {
|
||||
@override
|
||||
Future<Result> getConfig(String path) async {
|
||||
return await _invoke<Result>(method: ActionMethod.getConfig, data: path) ??
|
||||
Result<Map<String, dynamic>>.success({});
|
||||
Result.success({});
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -62,7 +62,7 @@ class CoreLib extends CoreHandlerInterface {
|
||||
}
|
||||
|
||||
@override
|
||||
Future get connected => _connectedCompleter.future;
|
||||
Completer get completer => _connectedCompleter;
|
||||
}
|
||||
|
||||
CoreLib? get coreLib => system.isAndroid ? CoreLib() : null;
|
||||
|
||||
@@ -186,9 +186,7 @@ class CoreService extends CoreHandlerInterface {
|
||||
}
|
||||
|
||||
@override
|
||||
Future get connected {
|
||||
return _socketCompleter.future;
|
||||
}
|
||||
Completer get completer => _socketCompleter;
|
||||
}
|
||||
|
||||
final coreService = system.isDesktop ? CoreService() : null;
|
||||
|
||||
@@ -100,6 +100,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"appDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Processing app related settings",
|
||||
),
|
||||
"appendSystemDns": MessageLookupByLibrary.simpleMessage(
|
||||
"Append System DNS",
|
||||
),
|
||||
"appendSystemDnsTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Forcefully append system DNS to the configuration",
|
||||
),
|
||||
"application": MessageLookupByLibrary.simpleMessage("Application"),
|
||||
"applicationDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Modify application related settings",
|
||||
|
||||
@@ -80,6 +80,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"app": MessageLookupByLibrary.simpleMessage("アプリ"),
|
||||
"appAccessControl": MessageLookupByLibrary.simpleMessage("アプリアクセス制御"),
|
||||
"appDesc": MessageLookupByLibrary.simpleMessage("アプリ関連設定の処理"),
|
||||
"appendSystemDns": MessageLookupByLibrary.simpleMessage("システムDNSを追加"),
|
||||
"appendSystemDnsTip": MessageLookupByLibrary.simpleMessage(
|
||||
"設定にシステムDNSを強制的に追加します",
|
||||
),
|
||||
"application": MessageLookupByLibrary.simpleMessage("アプリケーション"),
|
||||
"applicationDesc": MessageLookupByLibrary.simpleMessage("アプリ関連設定を変更"),
|
||||
"auto": MessageLookupByLibrary.simpleMessage("自動"),
|
||||
|
||||
@@ -97,6 +97,12 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"appDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Обработка настроек, связанных с приложением",
|
||||
),
|
||||
"appendSystemDns": MessageLookupByLibrary.simpleMessage(
|
||||
"Добавить системный DNS",
|
||||
),
|
||||
"appendSystemDnsTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Принудительно добавить системный DNS к конфигурации",
|
||||
),
|
||||
"application": MessageLookupByLibrary.simpleMessage("Приложение"),
|
||||
"applicationDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Изменение настроек, связанных с приложением",
|
||||
|
||||
@@ -76,6 +76,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"app": MessageLookupByLibrary.simpleMessage("应用"),
|
||||
"appAccessControl": MessageLookupByLibrary.simpleMessage("应用访问控制"),
|
||||
"appDesc": MessageLookupByLibrary.simpleMessage("处理应用相关设置"),
|
||||
"appendSystemDns": MessageLookupByLibrary.simpleMessage("追加系统DNS"),
|
||||
"appendSystemDnsTip": MessageLookupByLibrary.simpleMessage("强制为配置附加系统DNS"),
|
||||
"application": MessageLookupByLibrary.simpleMessage("应用程序"),
|
||||
"applicationDesc": MessageLookupByLibrary.simpleMessage("修改应用程序相关设置"),
|
||||
"auto": MessageLookupByLibrary.simpleMessage("自动"),
|
||||
|
||||
@@ -3358,6 +3358,26 @@ class AppLocalizations {
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Append System DNS`
|
||||
String get appendSystemDns {
|
||||
return Intl.message(
|
||||
'Append System DNS',
|
||||
name: 'appendSystemDns',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Forcefully append system DNS to the configuration`
|
||||
String get appendSystemDnsTip {
|
||||
return Intl.message(
|
||||
'Forcefully append system DNS to the configuration',
|
||||
name: 'appendSystemDnsTip',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||
|
||||
@@ -33,16 +33,18 @@ Future<void> _service(List<String> flags) async {
|
||||
},
|
||||
),
|
||||
);
|
||||
Future(() async {
|
||||
app?.tip(appLocalizations.startVpn);
|
||||
final version = await system.version;
|
||||
await coreController.init(version);
|
||||
final clashConfig = globalState.config.patchClashConfig.copyWith.tun(
|
||||
enable: false,
|
||||
);
|
||||
await globalState.handleStart();
|
||||
await coreController.setupConfig(clashConfig);
|
||||
});
|
||||
app?.tip(appLocalizations.startVpn);
|
||||
final version = await system.version;
|
||||
await coreController.init(version);
|
||||
final clashConfig = globalState.config.patchClashConfig.copyWith.tun(
|
||||
enable: false,
|
||||
);
|
||||
coreController.setupConfig(
|
||||
clashConfig,
|
||||
preloadInvoke: () {
|
||||
globalState.handleStart();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@immutable
|
||||
|
||||
@@ -71,16 +71,16 @@ class _AppStateManagerState extends ConsumerState<AppStateManager>
|
||||
@override
|
||||
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
|
||||
commonPrint.log('$state');
|
||||
if (state == AppLifecycleState.paused ||
|
||||
state == AppLifecycleState.inactive) {
|
||||
globalState.appController.savePreferences();
|
||||
} else {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
render?.resume();
|
||||
}
|
||||
if (state == AppLifecycleState.inactive) {
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
detectionState.tryStartCheck();
|
||||
});
|
||||
if (system.isAndroid) {
|
||||
globalState.appController.tryStartCore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +93,8 @@ class _CoreContainerState extends ConsumerState<CoreManager>
|
||||
|
||||
@override
|
||||
Future<void> onCrash(String message) async {
|
||||
if (!globalState.isUserDisconnected) {
|
||||
if (!globalState.isUserDisconnected &&
|
||||
WidgetsBinding.instance.lifecycleState == AppLifecycleState.resumed) {
|
||||
context.showNotifier(message);
|
||||
}
|
||||
globalState.isUserDisconnected = false;
|
||||
|
||||
@@ -19,7 +19,7 @@ class _TileContainerState extends State<TileManager> with TileListener {
|
||||
}
|
||||
|
||||
@override
|
||||
void onStart() {
|
||||
Future<void> onStart() async {
|
||||
if (globalState.appState.isStart) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -153,6 +153,7 @@ abstract class NetworkProps with _$NetworkProps {
|
||||
@Default(defaultBypassDomain) List<String> bypassDomain,
|
||||
@Default(RouteMode.config) RouteMode routeMode,
|
||||
@Default(true) bool autoSetSystemDns,
|
||||
@Default(false) bool appendSystemDns,
|
||||
}) = _NetworkProps;
|
||||
|
||||
factory NetworkProps.fromJson(Map<String, Object?>? json) =>
|
||||
|
||||
@@ -192,7 +192,7 @@ extension ActionResultExt on ActionResult {
|
||||
if (code == ResultType.success) {
|
||||
return Result.success(data);
|
||||
} else {
|
||||
return Result.error(data);
|
||||
return Result.error('$data');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1199,7 +1199,7 @@ $AccessControlCopyWith<$Res> get accessControl {
|
||||
/// @nodoc
|
||||
mixin _$NetworkProps {
|
||||
|
||||
bool get systemProxy; List<String> get bypassDomain; RouteMode get routeMode; bool get autoSetSystemDns;
|
||||
bool get systemProxy; List<String> get bypassDomain; RouteMode get routeMode; bool get autoSetSystemDns; bool get appendSystemDns;
|
||||
/// Create a copy of NetworkProps
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -1212,16 +1212,16 @@ $NetworkPropsCopyWith<NetworkProps> get copyWith => _$NetworkPropsCopyWithImpl<N
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is NetworkProps&&(identical(other.systemProxy, systemProxy) || other.systemProxy == systemProxy)&&const DeepCollectionEquality().equals(other.bypassDomain, bypassDomain)&&(identical(other.routeMode, routeMode) || other.routeMode == routeMode)&&(identical(other.autoSetSystemDns, autoSetSystemDns) || other.autoSetSystemDns == autoSetSystemDns));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is NetworkProps&&(identical(other.systemProxy, systemProxy) || other.systemProxy == systemProxy)&&const DeepCollectionEquality().equals(other.bypassDomain, bypassDomain)&&(identical(other.routeMode, routeMode) || other.routeMode == routeMode)&&(identical(other.autoSetSystemDns, autoSetSystemDns) || other.autoSetSystemDns == autoSetSystemDns)&&(identical(other.appendSystemDns, appendSystemDns) || other.appendSystemDns == appendSystemDns));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,systemProxy,const DeepCollectionEquality().hash(bypassDomain),routeMode,autoSetSystemDns);
|
||||
int get hashCode => Object.hash(runtimeType,systemProxy,const DeepCollectionEquality().hash(bypassDomain),routeMode,autoSetSystemDns,appendSystemDns);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'NetworkProps(systemProxy: $systemProxy, bypassDomain: $bypassDomain, routeMode: $routeMode, autoSetSystemDns: $autoSetSystemDns)';
|
||||
return 'NetworkProps(systemProxy: $systemProxy, bypassDomain: $bypassDomain, routeMode: $routeMode, autoSetSystemDns: $autoSetSystemDns, appendSystemDns: $appendSystemDns)';
|
||||
}
|
||||
|
||||
|
||||
@@ -1232,7 +1232,7 @@ abstract mixin class $NetworkPropsCopyWith<$Res> {
|
||||
factory $NetworkPropsCopyWith(NetworkProps value, $Res Function(NetworkProps) _then) = _$NetworkPropsCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool systemProxy, List<String> bypassDomain, RouteMode routeMode, bool autoSetSystemDns
|
||||
bool systemProxy, List<String> bypassDomain, RouteMode routeMode, bool autoSetSystemDns, bool appendSystemDns
|
||||
});
|
||||
|
||||
|
||||
@@ -1249,12 +1249,13 @@ class _$NetworkPropsCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of NetworkProps
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? systemProxy = null,Object? bypassDomain = null,Object? routeMode = null,Object? autoSetSystemDns = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? systemProxy = null,Object? bypassDomain = null,Object? routeMode = null,Object? autoSetSystemDns = null,Object? appendSystemDns = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
systemProxy: null == systemProxy ? _self.systemProxy : systemProxy // ignore: cast_nullable_to_non_nullable
|
||||
as bool,bypassDomain: null == bypassDomain ? _self.bypassDomain : bypassDomain // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,routeMode: null == routeMode ? _self.routeMode : routeMode // ignore: cast_nullable_to_non_nullable
|
||||
as RouteMode,autoSetSystemDns: null == autoSetSystemDns ? _self.autoSetSystemDns : autoSetSystemDns // ignore: cast_nullable_to_non_nullable
|
||||
as bool,appendSystemDns: null == appendSystemDns ? _self.appendSystemDns : appendSystemDns // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
@@ -1340,10 +1341,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool systemProxy, List<String> bypassDomain, RouteMode routeMode, bool autoSetSystemDns)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool systemProxy, List<String> bypassDomain, RouteMode routeMode, bool autoSetSystemDns, bool appendSystemDns)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _NetworkProps() when $default != null:
|
||||
return $default(_that.systemProxy,_that.bypassDomain,_that.routeMode,_that.autoSetSystemDns);case _:
|
||||
return $default(_that.systemProxy,_that.bypassDomain,_that.routeMode,_that.autoSetSystemDns,_that.appendSystemDns);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -1361,10 +1362,10 @@ return $default(_that.systemProxy,_that.bypassDomain,_that.routeMode,_that.autoS
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool systemProxy, List<String> bypassDomain, RouteMode routeMode, bool autoSetSystemDns) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool systemProxy, List<String> bypassDomain, RouteMode routeMode, bool autoSetSystemDns, bool appendSystemDns) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _NetworkProps():
|
||||
return $default(_that.systemProxy,_that.bypassDomain,_that.routeMode,_that.autoSetSystemDns);case _:
|
||||
return $default(_that.systemProxy,_that.bypassDomain,_that.routeMode,_that.autoSetSystemDns,_that.appendSystemDns);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -1381,10 +1382,10 @@ return $default(_that.systemProxy,_that.bypassDomain,_that.routeMode,_that.autoS
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool systemProxy, List<String> bypassDomain, RouteMode routeMode, bool autoSetSystemDns)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool systemProxy, List<String> bypassDomain, RouteMode routeMode, bool autoSetSystemDns, bool appendSystemDns)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _NetworkProps() when $default != null:
|
||||
return $default(_that.systemProxy,_that.bypassDomain,_that.routeMode,_that.autoSetSystemDns);case _:
|
||||
return $default(_that.systemProxy,_that.bypassDomain,_that.routeMode,_that.autoSetSystemDns,_that.appendSystemDns);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -1396,7 +1397,7 @@ return $default(_that.systemProxy,_that.bypassDomain,_that.routeMode,_that.autoS
|
||||
@JsonSerializable()
|
||||
|
||||
class _NetworkProps implements NetworkProps {
|
||||
const _NetworkProps({this.systemProxy = true, final List<String> bypassDomain = defaultBypassDomain, this.routeMode = RouteMode.config, this.autoSetSystemDns = true}): _bypassDomain = bypassDomain;
|
||||
const _NetworkProps({this.systemProxy = true, final List<String> bypassDomain = defaultBypassDomain, this.routeMode = RouteMode.config, this.autoSetSystemDns = true, this.appendSystemDns = false}): _bypassDomain = bypassDomain;
|
||||
factory _NetworkProps.fromJson(Map<String, dynamic> json) => _$NetworkPropsFromJson(json);
|
||||
|
||||
@override@JsonKey() final bool systemProxy;
|
||||
@@ -1409,6 +1410,7 @@ class _NetworkProps implements NetworkProps {
|
||||
|
||||
@override@JsonKey() final RouteMode routeMode;
|
||||
@override@JsonKey() final bool autoSetSystemDns;
|
||||
@override@JsonKey() final bool appendSystemDns;
|
||||
|
||||
/// Create a copy of NetworkProps
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1423,16 +1425,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _NetworkProps&&(identical(other.systemProxy, systemProxy) || other.systemProxy == systemProxy)&&const DeepCollectionEquality().equals(other._bypassDomain, _bypassDomain)&&(identical(other.routeMode, routeMode) || other.routeMode == routeMode)&&(identical(other.autoSetSystemDns, autoSetSystemDns) || other.autoSetSystemDns == autoSetSystemDns));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _NetworkProps&&(identical(other.systemProxy, systemProxy) || other.systemProxy == systemProxy)&&const DeepCollectionEquality().equals(other._bypassDomain, _bypassDomain)&&(identical(other.routeMode, routeMode) || other.routeMode == routeMode)&&(identical(other.autoSetSystemDns, autoSetSystemDns) || other.autoSetSystemDns == autoSetSystemDns)&&(identical(other.appendSystemDns, appendSystemDns) || other.appendSystemDns == appendSystemDns));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,systemProxy,const DeepCollectionEquality().hash(_bypassDomain),routeMode,autoSetSystemDns);
|
||||
int get hashCode => Object.hash(runtimeType,systemProxy,const DeepCollectionEquality().hash(_bypassDomain),routeMode,autoSetSystemDns,appendSystemDns);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'NetworkProps(systemProxy: $systemProxy, bypassDomain: $bypassDomain, routeMode: $routeMode, autoSetSystemDns: $autoSetSystemDns)';
|
||||
return 'NetworkProps(systemProxy: $systemProxy, bypassDomain: $bypassDomain, routeMode: $routeMode, autoSetSystemDns: $autoSetSystemDns, appendSystemDns: $appendSystemDns)';
|
||||
}
|
||||
|
||||
|
||||
@@ -1443,7 +1445,7 @@ abstract mixin class _$NetworkPropsCopyWith<$Res> implements $NetworkPropsCopyWi
|
||||
factory _$NetworkPropsCopyWith(_NetworkProps value, $Res Function(_NetworkProps) _then) = __$NetworkPropsCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool systemProxy, List<String> bypassDomain, RouteMode routeMode, bool autoSetSystemDns
|
||||
bool systemProxy, List<String> bypassDomain, RouteMode routeMode, bool autoSetSystemDns, bool appendSystemDns
|
||||
});
|
||||
|
||||
|
||||
@@ -1460,12 +1462,13 @@ class __$NetworkPropsCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of NetworkProps
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? systemProxy = null,Object? bypassDomain = null,Object? routeMode = null,Object? autoSetSystemDns = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? systemProxy = null,Object? bypassDomain = null,Object? routeMode = null,Object? autoSetSystemDns = null,Object? appendSystemDns = null,}) {
|
||||
return _then(_NetworkProps(
|
||||
systemProxy: null == systemProxy ? _self.systemProxy : systemProxy // ignore: cast_nullable_to_non_nullable
|
||||
as bool,bypassDomain: null == bypassDomain ? _self._bypassDomain : bypassDomain // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,routeMode: null == routeMode ? _self.routeMode : routeMode // ignore: cast_nullable_to_non_nullable
|
||||
as RouteMode,autoSetSystemDns: null == autoSetSystemDns ? _self.autoSetSystemDns : autoSetSystemDns // ignore: cast_nullable_to_non_nullable
|
||||
as bool,appendSystemDns: null == appendSystemDns ? _self.appendSystemDns : appendSystemDns // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -171,6 +171,7 @@ _NetworkProps _$NetworkPropsFromJson(Map<String, dynamic> json) =>
|
||||
$enumDecodeNullable(_$RouteModeEnumMap, json['routeMode']) ??
|
||||
RouteMode.config,
|
||||
autoSetSystemDns: json['autoSetSystemDns'] as bool? ?? true,
|
||||
appendSystemDns: json['appendSystemDns'] as bool? ?? false,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$NetworkPropsToJson(_NetworkProps instance) =>
|
||||
@@ -179,6 +180,7 @@ Map<String, dynamic> _$NetworkPropsToJson(_NetworkProps instance) =>
|
||||
'bypassDomain': instance.bypassDomain,
|
||||
'routeMode': _$RouteModeEnumMap[instance.routeMode]!,
|
||||
'autoSetSystemDns': instance.autoSetSystemDns,
|
||||
'appendSystemDns': instance.appendSystemDns,
|
||||
};
|
||||
|
||||
const _$RouteModeEnumMap = {
|
||||
|
||||
@@ -732,7 +732,7 @@ return $default(_that.a,_that.b,_that.c,_that.d);case _:
|
||||
|
||||
|
||||
class _VM4<A,B,C,D> implements VM4<A, B, C, D> {
|
||||
const _VM4({required this.a, required this.b, required this.c, required this.d});
|
||||
const _VM4(this.a, this.b, this.c, this.d);
|
||||
|
||||
|
||||
@override final A a;
|
||||
@@ -789,10 +789,10 @@ class __$VM4CopyWithImpl<A,B,C,D,$Res>
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? a = freezed,Object? b = freezed,Object? c = freezed,Object? d = freezed,}) {
|
||||
return _then(_VM4<A, B, C, D>(
|
||||
a: freezed == a ? _self.a : a // ignore: cast_nullable_to_non_nullable
|
||||
as A,b: freezed == b ? _self.b : b // ignore: cast_nullable_to_non_nullable
|
||||
as B,c: freezed == c ? _self.c : c // ignore: cast_nullable_to_non_nullable
|
||||
as C,d: freezed == d ? _self.d : d // ignore: cast_nullable_to_non_nullable
|
||||
freezed == a ? _self.a : a // ignore: cast_nullable_to_non_nullable
|
||||
as A,freezed == b ? _self.b : b // ignore: cast_nullable_to_non_nullable
|
||||
as B,freezed == c ? _self.c : c // ignore: cast_nullable_to_non_nullable
|
||||
as C,freezed == d ? _self.d : d // ignore: cast_nullable_to_non_nullable
|
||||
as D,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@ abstract class VM3<A, B, C> with _$VM3<A, B, C> {
|
||||
|
||||
@freezed
|
||||
abstract class VM4<A, B, C, D> with _$VM4<A, B, C, D> {
|
||||
const factory VM4({required A a, required B b, required C c, required D d}) =
|
||||
_VM4;
|
||||
const factory VM4(A a, B b, C c, D d) = _VM4;
|
||||
}
|
||||
|
||||
@freezed
|
||||
|
||||
@@ -2139,11 +2139,11 @@ const needSetupProvider = NeedSetupProvider._();
|
||||
final class NeedSetupProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
VM3<String?, String?, Dns?>,
|
||||
VM3<String?, String?, Dns?>,
|
||||
VM3<String?, String?, Dns?>
|
||||
VM4<String?, String?, Dns?, bool>,
|
||||
VM4<String?, String?, Dns?, bool>,
|
||||
VM4<String?, String?, Dns?, bool>
|
||||
>
|
||||
with $Provider<VM3<String?, String?, Dns?>> {
|
||||
with $Provider<VM4<String?, String?, Dns?, bool>> {
|
||||
const NeedSetupProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
@@ -2160,25 +2160,27 @@ final class NeedSetupProvider
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$ProviderElement<VM3<String?, String?, Dns?>> $createElement(
|
||||
$ProviderElement<VM4<String?, String?, Dns?, bool>> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $ProviderElement(pointer);
|
||||
|
||||
@override
|
||||
VM3<String?, String?, Dns?> create(Ref ref) {
|
||||
VM4<String?, String?, Dns?, bool> create(Ref ref) {
|
||||
return needSetup(ref);
|
||||
}
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(VM3<String?, String?, Dns?> value) {
|
||||
Override overrideWithValue(VM4<String?, String?, Dns?, bool> value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<VM3<String?, String?, Dns?>>(value),
|
||||
providerOverride: $SyncValueProvider<VM4<String?, String?, Dns?, bool>>(
|
||||
value,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$needSetupHash() => r'3668e8dc9f40a9bea45c94321804eb3afa0e7c51';
|
||||
String _$needSetupHash() => r'25352164c340a5fb02add21246062dd1287595fb';
|
||||
|
||||
@ProviderFor(currentBrightness)
|
||||
const currentBrightnessProvider = CurrentBrightnessProvider._();
|
||||
|
||||
@@ -573,7 +573,7 @@ ColorScheme genColorScheme(
|
||||
}
|
||||
|
||||
@riverpod
|
||||
VM3<String?, String?, Dns?> needSetup(Ref ref) {
|
||||
VM4<String?, String?, Dns?, bool> needSetup(Ref ref) {
|
||||
final profileId = ref.watch(currentProfileIdProvider);
|
||||
final content = ref.watch(
|
||||
scriptStateProvider.select((state) => state.currentScript?.content),
|
||||
@@ -582,7 +582,10 @@ VM3<String?, String?, Dns?> needSetup(Ref ref) {
|
||||
final dns = overrideDns == true
|
||||
? ref.watch(patchClashConfigProvider.select((state) => state.dns))
|
||||
: null;
|
||||
return VM3(a: profileId, b: content, c: dns);
|
||||
final appendSystemDns = ref.watch(
|
||||
networkSettingProvider.select((state) => state.appendSystemDns),
|
||||
);
|
||||
return VM4(profileId, content, dns, appendSystemDns);
|
||||
}
|
||||
|
||||
@riverpod
|
||||
|
||||
@@ -304,7 +304,13 @@ class GlobalState {
|
||||
|
||||
Future<void> genConfigFile(ClashConfig pathConfig) async {
|
||||
final configFilePath = await appPath.configFilePath;
|
||||
final config = await patchRawConfig(patchConfig: pathConfig);
|
||||
var config = {};
|
||||
try {
|
||||
config = await patchRawConfig(patchConfig: pathConfig);
|
||||
} catch (e) {
|
||||
globalState.showNotifier(e.toString());
|
||||
config = {};
|
||||
}
|
||||
final res = await Isolate.run<String>(() async {
|
||||
try {
|
||||
final res = json.encode(config);
|
||||
@@ -469,10 +475,11 @@ class GlobalState {
|
||||
}
|
||||
final isEnableDns = rawConfig['dns']['enable'] == true;
|
||||
final overrideDns = globalState.config.overrideDns;
|
||||
final systemDns = 'system://';
|
||||
if (overrideDns || !isEnableDns) {
|
||||
final dns = switch (!isEnableDns) {
|
||||
true => realPatchConfig.dns.copyWith(
|
||||
nameserver: [...realPatchConfig.dns.nameserver, 'system://'],
|
||||
nameserver: [...realPatchConfig.dns.nameserver, systemDns],
|
||||
),
|
||||
false => realPatchConfig.dns,
|
||||
};
|
||||
@@ -483,6 +490,12 @@ class GlobalState {
|
||||
entry.value.splitByMultipleSeparators;
|
||||
}
|
||||
}
|
||||
if (config.networkProps.appendSystemDns) {
|
||||
final List<dynamic> nameserver = rawConfig['dns']['nameserver'] ?? [];
|
||||
if (!nameserver.contains(systemDns)) {
|
||||
rawConfig['dns']['nameserver'] = [...nameserver, systemDns];
|
||||
}
|
||||
}
|
||||
List rules = [];
|
||||
if (rawConfig['rules'] != null) {
|
||||
rules = rawConfig['rules'];
|
||||
|
||||
@@ -257,6 +257,30 @@ class Ipv6Item extends ConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class AppendSystemDNSItem extends ConsumerWidget {
|
||||
const AppendSystemDNSItem({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final appendSystemDNS = ref.watch(
|
||||
networkSettingProvider.select((state) => state.appendSystemDns),
|
||||
);
|
||||
return ListItem.switchItem(
|
||||
leading: const Icon(Icons.dns_outlined),
|
||||
title: Text(appLocalizations.appendSystemDns),
|
||||
subtitle: Text(appLocalizations.appendSystemDnsTip),
|
||||
delegate: SwitchDelegate(
|
||||
value: appendSystemDNS,
|
||||
onChanged: (bool value) async {
|
||||
ref
|
||||
.read(networkSettingProvider.notifier)
|
||||
.updateState((state) => state.copyWith(appendSystemDns: value));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AllowLanItem extends ConsumerWidget {
|
||||
const AllowLanItem({super.key});
|
||||
|
||||
@@ -437,6 +461,7 @@ final generalItems = <Widget>[
|
||||
Ipv6Item(),
|
||||
AllowLanItem(),
|
||||
UnifiedDelayItem(),
|
||||
AppendSystemDNSItem(),
|
||||
FindProcessItem(),
|
||||
TcpConcurrentItem(),
|
||||
GeodataLoaderItem(),
|
||||
|
||||
@@ -53,7 +53,6 @@ class _DashboardViewState extends ConsumerState<DashboardView> {
|
||||
if (res != true) {
|
||||
return;
|
||||
}
|
||||
await Future.delayed(commonDuration);
|
||||
globalState.appController.restartCore();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,11 @@ class _MemoryInfoState extends State<MemoryInfo> {
|
||||
Future<void> _updateMemory() async {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
final rss = ProcessInfo.currentRss;
|
||||
_memoryStateNotifier.value = await coreController.getMemory() + rss;
|
||||
if (coreController.isCompleted) {
|
||||
_memoryStateNotifier.value = await coreController.getMemory() + rss;
|
||||
} else {
|
||||
_memoryStateNotifier.value = rss;
|
||||
}
|
||||
timer = Timer(Duration(seconds: 2), () async {
|
||||
_updateMemory();
|
||||
});
|
||||
|
||||
@@ -40,6 +40,7 @@ class DeveloperView extends ConsumerWidget {
|
||||
title: Text(appLocalizations.crashTest),
|
||||
minVerticalPadding: 14,
|
||||
onTap: () {
|
||||
// coreController.crash();
|
||||
if (kDebugMode) {
|
||||
coreController.crash();
|
||||
}
|
||||
|
||||
@@ -488,7 +488,7 @@ class _ListHeaderState extends State<ListHeader> {
|
||||
return CommonCard(
|
||||
enterAnimated: widget.enterAnimated,
|
||||
key: widget.key,
|
||||
radius: 16.ap,
|
||||
radius: 18.ap,
|
||||
type: CommonCardType.filled,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
|
||||
@@ -147,7 +147,8 @@ class ProviderItem extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
Text(_buildProviderDesc()),
|
||||
if (provider.updateAt.microsecondsSinceEpoch > 0)
|
||||
Text(_buildProviderDesc()),
|
||||
const SizedBox(height: 4),
|
||||
if (provider.subscriptionInfo != null)
|
||||
SubscriptionInfoView(subscriptionInfo: provider.subscriptionInfo),
|
||||
|
||||
@@ -262,11 +262,10 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
|
||||
final vm4 = ref.watch(
|
||||
themeSettingProvider.select(
|
||||
(state) => VM4(
|
||||
a: state.primaryColor,
|
||||
b: state.primaryColors,
|
||||
c: state.schemeVariant,
|
||||
d:
|
||||
state.primaryColor == defaultPrimaryColor &&
|
||||
state.primaryColor,
|
||||
state.primaryColors,
|
||||
state.schemeVariant,
|
||||
state.primaryColor == defaultPrimaryColor &&
|
||||
intListEquality.equals(state.primaryColors, defaultPrimaryColors),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -79,7 +79,7 @@ class CommonCard extends StatelessWidget {
|
||||
this.type = CommonCardType.plain,
|
||||
this.onPressed,
|
||||
this.selectWidget,
|
||||
this.radius = 12,
|
||||
this.radius = 14,
|
||||
required this.child,
|
||||
this.padding,
|
||||
this.enterAnimated = false,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
name: fl_clash
|
||||
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
||||
publish_to: 'none'
|
||||
version: 0.8.89+2025092701
|
||||
version: 0.8.90+2025100801
|
||||
environment:
|
||||
sdk: '>=3.8.0 <4.0.0'
|
||||
|
||||
|
||||
@@ -140,6 +140,8 @@ class Build {
|
||||
bool runInShell = true,
|
||||
}) async {
|
||||
if (name != null) print('run $name');
|
||||
print('exec: ${executable.join(' ')}');
|
||||
print('env: ${environment.toString()}');
|
||||
final process = await Process.start(
|
||||
executable[0],
|
||||
executable.sublist(1),
|
||||
|
||||
Reference in New Issue
Block a user