Add windows server mode start process verify
Add linux deb dependencies Add backup recovery strategy select Support custom text scaling Optimize the display of different text scale Optimize windows setup experience Optimize startTun performance Optimize android tv experience Optimize default option Optimize computed text size Optimize hyperOS freeform window Add developer mode Update core Optimize more details
This commit is contained in:
11
.github/workflows/build.yaml
vendored
11
.github/workflows/build.yaml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
os: windows-latest
|
||||
arch: amd64
|
||||
- platform: linux
|
||||
os: ubuntu-latest
|
||||
os: ubuntu-22.04
|
||||
arch: amd64
|
||||
- platform: macos
|
||||
os: macos-13
|
||||
@@ -201,6 +201,7 @@ jobs:
|
||||
env:
|
||||
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||
TAG: ${{ github.ref_name }}
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install requests
|
||||
@@ -211,6 +212,14 @@ jobs:
|
||||
version=$(echo "${{ github.ref_name }}" | sed 's/^v//')
|
||||
sed "s|VERSION|$version|g" ./.github/release_template.md >> release.md
|
||||
|
||||
- name: Generate sha256
|
||||
if: env.IS_STABLE == 'true'
|
||||
run: |
|
||||
cd ./dist
|
||||
for file in $(find . -type f -not -name "*.sha256"); do
|
||||
sha256sum "$file" > "${file}.sha256"
|
||||
done
|
||||
|
||||
- name: Release
|
||||
if: ${{ env.IS_STABLE == 'true' }}
|
||||
uses: softprops/action-gh-release@v2
|
||||
|
||||
@@ -41,8 +41,8 @@ on Mobile:
|
||||
⚠️ Make sure to install the following dependencies before using them
|
||||
|
||||
```bash
|
||||
sudo apt-get install appindicator3-0.1 libappindicator3-dev
|
||||
sudo apt-get install keybinder-3.0
|
||||
sudo apt-get install libayatana-appindicator3-dev
|
||||
sudo apt-get install libkeybinder-3.0-dev
|
||||
```
|
||||
|
||||
### Android
|
||||
|
||||
@@ -41,8 +41,8 @@ on Mobile:
|
||||
⚠️ 使用前请确保安装以下依赖
|
||||
|
||||
```bash
|
||||
sudo apt-get install appindicator3-0.1 libappindicator3-dev
|
||||
sudo apt-get install keybinder-3.0
|
||||
sudo apt-get install libayatana-appindicator3-dev
|
||||
sudo apt-get install libkeybinder-3.0-dev
|
||||
```
|
||||
|
||||
### Android
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
|
||||
|
||||
@@ -20,6 +20,10 @@ enum class RunState {
|
||||
object GlobalState {
|
||||
val runLock = ReentrantLock()
|
||||
|
||||
const val NOTIFICATION_CHANNEL = "FlClash"
|
||||
|
||||
const val NOTIFICATION_ID = 1
|
||||
|
||||
val runState: MutableLiveData<RunState> = MutableLiveData<RunState>(RunState.STOP)
|
||||
var flutterEngine: FlutterEngine? = null
|
||||
private var serviceEngine: FlutterEngine? = null
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.follow.clash
|
||||
|
||||
import com.follow.clash.core.Core
|
||||
import com.follow.clash.plugins.AppPlugin
|
||||
import com.follow.clash.plugins.ServicePlugin
|
||||
import com.follow.clash.plugins.TilePlugin
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
|
||||
suspend fun Drawable.getBase64(): String {
|
||||
val drawable = this
|
||||
return withContext(Dispatchers.IO) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.follow.clash.models
|
||||
data class Package(
|
||||
val packageName: String,
|
||||
val label: String,
|
||||
val isSystem: Boolean,
|
||||
val system: Boolean,
|
||||
val internet: Boolean,
|
||||
val lastUpdateTime: Long,
|
||||
)
|
||||
|
||||
@@ -293,17 +293,15 @@ class AppPlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware
|
||||
if (packages.isNotEmpty()) return packages
|
||||
packageManager?.getInstalledPackages(PackageManager.GET_META_DATA or PackageManager.GET_PERMISSIONS)
|
||||
?.filter {
|
||||
it.packageName != FlClashApplication.getAppContext().packageName && (
|
||||
it.requestedPermissions?.contains(Manifest.permission.INTERNET) == true
|
||||
|| it.packageName == "android"
|
||||
)
|
||||
it.packageName != FlClashApplication.getAppContext().packageName || it.packageName == "android"
|
||||
|
||||
}?.map {
|
||||
Package(
|
||||
packageName = it.packageName,
|
||||
label = it.applicationInfo?.loadLabel(packageManager).toString(),
|
||||
isSystem = (it.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM)) == 1,
|
||||
lastUpdateTime = it.lastUpdateTime
|
||||
system = (it.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM)) == 1,
|
||||
lastUpdateTime = it.lastUpdateTime,
|
||||
internet = it.requestedPermissions?.contains(Manifest.permission.INTERNET) == true
|
||||
)
|
||||
}?.let { packages.addAll(it) }
|
||||
return packages
|
||||
|
||||
@@ -168,8 +168,10 @@ data object VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
||||
try {
|
||||
if (GlobalState.runState.value != RunState.START) return
|
||||
val data = flutterMethodChannel.awaitResult<String>("getStartForegroundParams")
|
||||
val startForegroundParams = Gson().fromJson(
|
||||
val startForegroundParams = if (data != null) Gson().fromJson(
|
||||
data, StartForegroundParams::class.java
|
||||
) else StartForegroundParams(
|
||||
title = "", content = ""
|
||||
)
|
||||
if (lastStartForegroundParams != startForegroundParams) {
|
||||
lastStartForegroundParams = startForegroundParams
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
package com.follow.clash.services
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification
|
||||
import android.app.Notification.FOREGROUND_SERVICE_IMMEDIATE
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.follow.clash.GlobalState
|
||||
import com.follow.clash.MainActivity
|
||||
import com.follow.clash.R
|
||||
import com.follow.clash.extensions.getActionPendingIntent
|
||||
import com.follow.clash.models.VpnOptions
|
||||
import io.flutter.Log
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
|
||||
interface BaseServiceInterface {
|
||||
|
||||
@@ -10,3 +30,69 @@ interface BaseServiceInterface {
|
||||
|
||||
suspend fun startForeground(title: String, content: String)
|
||||
}
|
||||
|
||||
fun Service.createFlClashNotificationBuilder(): Deferred<NotificationCompat.Builder> =
|
||||
CoroutineScope(Dispatchers.Main).async {
|
||||
val stopText = GlobalState.getText("stop")
|
||||
val intent = Intent(this@createFlClashNotificationBuilder, MainActivity::class.java)
|
||||
|
||||
val pendingIntent = if (Build.VERSION.SDK_INT >= 31) {
|
||||
PendingIntent.getActivity(
|
||||
this@createFlClashNotificationBuilder,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
} else {
|
||||
PendingIntent.getActivity(
|
||||
this@createFlClashNotificationBuilder, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
}
|
||||
|
||||
with(
|
||||
NotificationCompat.Builder(
|
||||
this@createFlClashNotificationBuilder, GlobalState.NOTIFICATION_CHANNEL
|
||||
)
|
||||
) {
|
||||
setSmallIcon(R.drawable.ic_stat_name)
|
||||
setContentTitle("FlClash")
|
||||
setContentIntent(pendingIntent)
|
||||
setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
foregroundServiceBehavior = FOREGROUND_SERVICE_IMMEDIATE
|
||||
}
|
||||
setOngoing(true)
|
||||
addAction(
|
||||
0, stopText, getActionPendingIntent("STOP")
|
||||
)
|
||||
setShowWhen(false)
|
||||
setOnlyAlertOnce(true)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ForegroundServiceType")
|
||||
fun Service.startForeground(notification: Notification) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val manager = getSystemService(NotificationManager::class.java)
|
||||
var channel = manager?.getNotificationChannel(GlobalState.NOTIFICATION_CHANNEL)
|
||||
if (channel == null) {
|
||||
Log.d("[FlClash]","createNotificationChannel===>")
|
||||
channel = NotificationChannel(
|
||||
GlobalState.NOTIFICATION_CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW
|
||||
)
|
||||
manager?.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
try {
|
||||
startForeground(
|
||||
GlobalState.NOTIFICATION_ID, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
)
|
||||
} catch (_: Exception) {
|
||||
startForeground(GlobalState.NOTIFICATION_ID, notification)
|
||||
}
|
||||
} else {
|
||||
startForeground(GlobalState.NOTIFICATION_ID, notification)
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,51 @@
|
||||
package com.follow.clash.services
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification.FOREGROUND_SERVICE_IMMEDIATE
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
import android.os.Binder
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.follow.clash.GlobalState
|
||||
import com.follow.clash.MainActivity
|
||||
import com.follow.clash.extensions.getActionPendingIntent
|
||||
import com.follow.clash.models.VpnOptions
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
|
||||
|
||||
class FlClashService : Service(), BaseServiceInterface {
|
||||
|
||||
override fun start(options: VpnOptions) = 0
|
||||
|
||||
override fun stop() {
|
||||
stopSelf()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
}
|
||||
}
|
||||
|
||||
private var cachedBuilder: NotificationCompat.Builder? = null
|
||||
|
||||
private suspend fun notificationBuilder(): NotificationCompat.Builder {
|
||||
if (cachedBuilder == null) {
|
||||
cachedBuilder = createFlClashNotificationBuilder().await()
|
||||
}
|
||||
return cachedBuilder!!
|
||||
}
|
||||
|
||||
@SuppressLint("ForegroundServiceType")
|
||||
override suspend fun startForeground(title: String, content: String) {
|
||||
startForeground(
|
||||
notificationBuilder()
|
||||
.setContentTitle(title)
|
||||
.setContentText(content).build()
|
||||
)
|
||||
}
|
||||
|
||||
override fun onTrimMemory(level: Int) {
|
||||
super.onTrimMemory(level)
|
||||
GlobalState.getCurrentVPNPlugin()?.requestGc()
|
||||
}
|
||||
|
||||
|
||||
private val binder = LocalBinder()
|
||||
|
||||
inner class LocalBinder : Binder() {
|
||||
@@ -38,93 +60,8 @@ class FlClashService : Service(), BaseServiceInterface {
|
||||
return super.onUnbind(intent)
|
||||
}
|
||||
|
||||
private val CHANNEL = "FlClash"
|
||||
|
||||
private val notificationId: Int = 1
|
||||
|
||||
private val notificationBuilderDeferred: Deferred<NotificationCompat.Builder> by lazy {
|
||||
CoroutineScope(Dispatchers.Main).async {
|
||||
val stopText = GlobalState.getText("stop")
|
||||
|
||||
val intent = Intent(
|
||||
this@FlClashService, MainActivity::class.java
|
||||
)
|
||||
|
||||
val pendingIntent = if (Build.VERSION.SDK_INT >= 31) {
|
||||
PendingIntent.getActivity(
|
||||
this@FlClashService,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
} else {
|
||||
PendingIntent.getActivity(
|
||||
this@FlClashService,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
}
|
||||
|
||||
with(NotificationCompat.Builder(this@FlClashService, CHANNEL)) {
|
||||
setSmallIcon(com.follow.clash.R.drawable.ic_stat_name)
|
||||
setContentTitle("FlClash")
|
||||
setContentIntent(pendingIntent)
|
||||
setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
priority = NotificationCompat.PRIORITY_MIN
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
foregroundServiceBehavior = FOREGROUND_SERVICE_IMMEDIATE
|
||||
}
|
||||
addAction(
|
||||
0,
|
||||
stopText, // 使用 suspend 函数获取的文本
|
||||
getActionPendingIntent("STOP")
|
||||
)
|
||||
setOngoing(true)
|
||||
setShowWhen(false)
|
||||
setOnlyAlertOnce(true)
|
||||
setAutoCancel(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getNotificationBuilder(): NotificationCompat.Builder {
|
||||
return notificationBuilderDeferred.await()
|
||||
}
|
||||
|
||||
override fun start(options: VpnOptions) = 0
|
||||
|
||||
override fun stop() {
|
||||
stopSelf()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("ForegroundServiceType")
|
||||
override suspend fun startForeground(title: String, content: String) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val manager = getSystemService(NotificationManager::class.java)
|
||||
var channel = manager?.getNotificationChannel(CHANNEL)
|
||||
if (channel == null) {
|
||||
channel =
|
||||
NotificationChannel(CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW)
|
||||
manager?.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
val notification =
|
||||
getNotificationBuilder()
|
||||
.setContentTitle(title)
|
||||
.setContentText(content).build()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
try {
|
||||
startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC)
|
||||
} catch (_: Exception) {
|
||||
startForeground(notificationId, notification)
|
||||
}
|
||||
} else {
|
||||
startForeground(notificationId, notification)
|
||||
}
|
||||
override fun onDestroy() {
|
||||
stop()
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,7 @@
|
||||
package com.follow.clash.services
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification.FOREGROUND_SERVICE_IMMEDIATE
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.content.Intent
|
||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
import android.net.ProxyInfo
|
||||
import android.net.VpnService
|
||||
import android.os.Binder
|
||||
@@ -17,18 +12,13 @@ import android.os.RemoteException
|
||||
import android.util.Log
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.follow.clash.GlobalState
|
||||
import com.follow.clash.MainActivity
|
||||
import com.follow.clash.R
|
||||
import com.follow.clash.extensions.getActionPendingIntent
|
||||
import com.follow.clash.extensions.getIpv4RouteAddress
|
||||
import com.follow.clash.extensions.getIpv6RouteAddress
|
||||
import com.follow.clash.extensions.toCIDR
|
||||
import com.follow.clash.models.AccessControlMode
|
||||
import com.follow.clash.models.VpnOptions
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
||||
@@ -43,6 +33,10 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
|
||||
if (options.ipv4Address.isNotEmpty()) {
|
||||
val cidr = options.ipv4Address.toCIDR()
|
||||
addAddress(cidr.address, cidr.prefixLength)
|
||||
Log.d(
|
||||
"addAddress",
|
||||
"address: ${cidr.address} prefixLength:${cidr.prefixLength}"
|
||||
)
|
||||
val routeAddress = options.getIpv4RouteAddress()
|
||||
if (routeAddress.isNotEmpty()) {
|
||||
try {
|
||||
@@ -59,9 +53,16 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
|
||||
} else {
|
||||
addRoute("0.0.0.0", 0)
|
||||
}
|
||||
} else {
|
||||
addRoute("0.0.0.0", 0)
|
||||
}
|
||||
try {
|
||||
if (options.ipv6Address.isNotEmpty()) {
|
||||
val cidr = options.ipv6Address.toCIDR()
|
||||
Log.d(
|
||||
"addAddress6",
|
||||
"address: ${cidr.address} prefixLength:${cidr.prefixLength}"
|
||||
)
|
||||
addAddress(cidr.address, cidr.prefixLength)
|
||||
val routeAddress = options.getIpv6RouteAddress()
|
||||
if (routeAddress.isNotEmpty()) {
|
||||
@@ -80,6 +81,12 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
|
||||
addRoute("::", 0)
|
||||
}
|
||||
}
|
||||
}catch (_:Exception){
|
||||
Log.d(
|
||||
"addAddress6",
|
||||
"IPv6 is not supported."
|
||||
)
|
||||
}
|
||||
addDnsServer(options.dnsServerAddress)
|
||||
setMtu(9000)
|
||||
options.accessControl.let { accessControl ->
|
||||
@@ -128,82 +135,22 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
|
||||
}
|
||||
}
|
||||
|
||||
private val CHANNEL = "FlClash"
|
||||
private var cachedBuilder: NotificationCompat.Builder? = null
|
||||
|
||||
private val notificationId: Int = 1
|
||||
|
||||
private val notificationBuilderDeferred: Deferred<NotificationCompat.Builder> by lazy {
|
||||
CoroutineScope(Dispatchers.Main).async {
|
||||
val stopText = GlobalState.getText("stop")
|
||||
val intent = Intent(this@FlClashVpnService, MainActivity::class.java)
|
||||
|
||||
val pendingIntent = if (Build.VERSION.SDK_INT >= 31) {
|
||||
PendingIntent.getActivity(
|
||||
this@FlClashVpnService,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
} else {
|
||||
PendingIntent.getActivity(
|
||||
this@FlClashVpnService,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
private suspend fun notificationBuilder(): NotificationCompat.Builder {
|
||||
if (cachedBuilder == null) {
|
||||
cachedBuilder = createFlClashNotificationBuilder().await()
|
||||
}
|
||||
|
||||
with(NotificationCompat.Builder(this@FlClashVpnService, CHANNEL)) {
|
||||
setSmallIcon(R.drawable.ic_stat_name)
|
||||
setContentTitle("FlClash")
|
||||
setContentIntent(pendingIntent)
|
||||
setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
priority = NotificationCompat.PRIORITY_MIN
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
foregroundServiceBehavior = FOREGROUND_SERVICE_IMMEDIATE
|
||||
}
|
||||
setOngoing(true)
|
||||
addAction(
|
||||
0,
|
||||
stopText,
|
||||
getActionPendingIntent("STOP")
|
||||
)
|
||||
setShowWhen(false)
|
||||
setOnlyAlertOnce(true)
|
||||
setAutoCancel(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getNotificationBuilder(): NotificationCompat.Builder {
|
||||
return notificationBuilderDeferred.await()
|
||||
return cachedBuilder!!
|
||||
}
|
||||
|
||||
@SuppressLint("ForegroundServiceType")
|
||||
override suspend fun startForeground(title: String, content: String) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val manager = getSystemService(NotificationManager::class.java)
|
||||
var channel = manager?.getNotificationChannel(CHANNEL)
|
||||
if (channel == null) {
|
||||
channel =
|
||||
NotificationChannel(CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW)
|
||||
manager?.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
val notification =
|
||||
getNotificationBuilder()
|
||||
startForeground(
|
||||
notificationBuilder()
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.build()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
try {
|
||||
startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC)
|
||||
} catch (_: Exception) {
|
||||
startForeground(notificationId, notification)
|
||||
}
|
||||
} else {
|
||||
startForeground(notificationId, notification)
|
||||
}
|
||||
.setContentText(content).build()
|
||||
)
|
||||
}
|
||||
|
||||
override fun onTrimMemory(level: Int) {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import com.android.build.gradle.tasks.MergeSourceSetFolders
|
||||
|
||||
plugins {
|
||||
id("com.android.library")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
@@ -37,13 +35,17 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "11"
|
||||
jvmTarget = "17"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
implementation("androidx.annotation:annotation-jvm:1.9.1")
|
||||
}
|
||||
|
||||
val copyNativeLibs by tasks.register<Copy>("copyNativeLibs") {
|
||||
@@ -59,7 +61,3 @@ afterEvaluate {
|
||||
dependsOn(copyNativeLibs)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("androidx.core:core-ktx:1.16.0")
|
||||
}
|
||||
@@ -21,6 +21,8 @@ if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
|
||||
-Wl,--strip-all
|
||||
-Wl,--exclude-libs=ALL
|
||||
)
|
||||
|
||||
add_compile_options(-fvisibility=hidden -fvisibility-inlines-hidden)
|
||||
endif ()
|
||||
|
||||
set(LIB_CLASH_PATH "${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libclash.so")
|
||||
|
||||
@@ -385,5 +385,20 @@
|
||||
"expressiveScheme": "Expressive",
|
||||
"contentScheme": "Content",
|
||||
"rainbowScheme": "Rainbow",
|
||||
"fruitSaladScheme": "FruitSalad"
|
||||
"fruitSaladScheme": "FruitSalad",
|
||||
"developerMode": "Developer mode",
|
||||
"developerModeEnableTip": "Developer mode is enabled.",
|
||||
"messageTest": "Message test",
|
||||
"messageTestTip": "This is a message.",
|
||||
"crashTest": "Crash test",
|
||||
"clearData": "Clear Data",
|
||||
"textScale": "Text Scaling",
|
||||
"internet": "Internet",
|
||||
"systemApp": "System APP",
|
||||
"noNetworkApp": "No network APP",
|
||||
"contactMe": "Contact me",
|
||||
"recoveryStrategy": "Recovery strategy",
|
||||
"recoveryStrategy_override": "Override",
|
||||
"recoveryStrategy_compatible": "Compatible",
|
||||
"logsTest": "Logs test"
|
||||
}
|
||||
@@ -385,5 +385,21 @@
|
||||
"expressiveScheme": "エクスプレッシブ",
|
||||
"contentScheme": "コンテンツテーマ",
|
||||
"rainbowScheme": "レインボー",
|
||||
"fruitSaladScheme": "フルーツサラダ"
|
||||
"fruitSaladScheme": "フルーツサラダ",
|
||||
"developerMode": "デベロッパーモード",
|
||||
"developerModeEnableTip": "デベロッパーモードが有効になりました。",
|
||||
"messageTest": "メッセージテスト",
|
||||
"messageTestTip": "これはメッセージです。",
|
||||
"crashTest": "クラッシュテスト",
|
||||
"clearData": "データを消去",
|
||||
"zoom": "ズーム",
|
||||
"textScale": "テキストスケーリング",
|
||||
"internet": "インターネット",
|
||||
"systemApp": "システムアプリ",
|
||||
"noNetworkApp": "ネットワークなしアプリ",
|
||||
"contactMe": "連絡する",
|
||||
"recoveryStrategy": "リカバリー戦略",
|
||||
"recoveryStrategy_override": "オーバーライド",
|
||||
"recoveryStrategy_compatible": "互換性",
|
||||
"logsTest": "ログテスト"
|
||||
}
|
||||
@@ -385,5 +385,21 @@
|
||||
"expressiveScheme": "Экспрессивные",
|
||||
"contentScheme": "Контентная тема",
|
||||
"rainbowScheme": "Радужные",
|
||||
"fruitSaladScheme": "Фруктовый микс"
|
||||
"fruitSaladScheme": "Фруктовый микс",
|
||||
"developerMode": "Режим разработчика",
|
||||
"developerModeEnableTip": "Режим разработчика активирован.",
|
||||
"messageTest": "Тестирование сообщения",
|
||||
"messageTestTip": "Это сообщение.",
|
||||
"crashTest": "Тест на сбои",
|
||||
"clearData": "Очистить данные",
|
||||
"zoom": "Масштаб",
|
||||
"textScale": "Масштабирование текста",
|
||||
"internet": "Интернет",
|
||||
"systemApp": "Системное приложение",
|
||||
"noNetworkApp": "Приложение без сети",
|
||||
"contactMe": "Свяжитесь со мной",
|
||||
"recoveryStrategy": "Стратегия восстановления",
|
||||
"recoveryStrategy_override": "Переопределение",
|
||||
"recoveryStrategy_compatible": "Совместимый",
|
||||
"logsTest": "Тест журналов"
|
||||
}
|
||||
@@ -385,5 +385,21 @@
|
||||
"expressiveScheme": "表现力",
|
||||
"contentScheme": "内容主题",
|
||||
"rainbowScheme": "彩虹",
|
||||
"fruitSaladScheme": "果缤纷"
|
||||
"fruitSaladScheme": "果缤纷",
|
||||
"developerMode": "开发者模式",
|
||||
"developerModeEnableTip": "开发者模式已启用。",
|
||||
"messageTest": "消息测试",
|
||||
"messageTestTip": "这是一条消息。",
|
||||
"crashTest": "崩溃测试",
|
||||
"clearData": "清除数据",
|
||||
"zoom": "缩放",
|
||||
"textScale": "文本缩放",
|
||||
"internet": "互联网",
|
||||
"systemApp": "系统应用",
|
||||
"noNetworkApp": "无网络应用",
|
||||
"contactMe": "联系我",
|
||||
"recoveryStrategy": "恢复策略",
|
||||
"recoveryStrategy_override": "覆盖",
|
||||
"recoveryStrategy_compatible": "兼容",
|
||||
"logsTest": "日志测试"
|
||||
}
|
||||
Submodule core/Clash.Meta updated: f19dad529f...88a1848dfb
@@ -166,6 +166,9 @@ func handleAction(action *Action, result func(data interface{})) {
|
||||
data := action.Data.(string)
|
||||
handleSetState(data)
|
||||
result(true)
|
||||
case crashMethod:
|
||||
result(true)
|
||||
handleCrash()
|
||||
default:
|
||||
handle := nextHandle(action, result)
|
||||
if handle {
|
||||
|
||||
@@ -78,7 +78,6 @@ func getRawConfigWithId(id string) *config.RawConfig {
|
||||
path := getProfilePath(id)
|
||||
bytes, err := readFile(path)
|
||||
if err != nil {
|
||||
log.Errorln("profile is not exist")
|
||||
return config.DefaultRawConfig()
|
||||
}
|
||||
prof, err := config.UnmarshalRawConfig(bytes)
|
||||
|
||||
@@ -82,6 +82,7 @@ const (
|
||||
getRunTimeMethod Method = "getRunTime"
|
||||
getCurrentProfileNameMethod Method = "getCurrentProfileName"
|
||||
getProfileMethod Method = "getProfile"
|
||||
crashMethod Method = "crash"
|
||||
)
|
||||
|
||||
type Method string
|
||||
|
||||
13
core/go.mod
13
core/go.mod
@@ -7,6 +7,7 @@ replace github.com/metacubex/mihomo => ./Clash.Meta
|
||||
require (
|
||||
github.com/metacubex/mihomo v0.0.0-00010101000000-000000000000
|
||||
github.com/samber/lo v1.49.1
|
||||
golang.org/x/sync v0.11.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -52,20 +53,20 @@ require (
|
||||
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab // indirect
|
||||
github.com/metacubex/bart v0.19.0 // indirect
|
||||
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 // indirect
|
||||
github.com/metacubex/chacha v0.1.1 // indirect
|
||||
github.com/metacubex/chacha v0.1.2 // indirect
|
||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // indirect
|
||||
github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect
|
||||
github.com/metacubex/quic-go v0.49.1-0.20250212162123-c135a4412996 // indirect
|
||||
github.com/metacubex/randv2 v0.2.0 // indirect
|
||||
github.com/metacubex/reality v0.0.0-20250219003814-74e8d7850629 // indirect
|
||||
github.com/metacubex/sing-quic v0.0.0-20250119013740-2a19cce83925 // indirect
|
||||
github.com/metacubex/sing-quic v0.0.0-20250404030904-b2cc8aab562c // indirect
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8 // indirect
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.2 // indirect
|
||||
github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04 // indirect
|
||||
github.com/metacubex/sing-shadowtls v0.0.0-20250412122235-0e9005731a63 // indirect
|
||||
github.com/metacubex/sing-tun v0.4.6-0.20250412144348-c426cb167db5 // indirect
|
||||
github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82 // indirect
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589 // indirect
|
||||
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422 // indirect
|
||||
github.com/metacubex/utls v1.6.8-alpha.4 // indirect
|
||||
github.com/metacubex/utls v1.7.0-alpha.1 // indirect
|
||||
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 // indirect
|
||||
github.com/miekg/dns v1.1.63 // indirect
|
||||
github.com/mroth/weightedrand/v2 v2.1.0 // indirect
|
||||
@@ -84,7 +85,6 @@ require (
|
||||
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
||||
github.com/sagernet/sing v0.5.2 // indirect
|
||||
github.com/sagernet/sing-mux v0.2.1 // indirect
|
||||
github.com/sagernet/sing-shadowtls v0.1.5 // indirect
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.25.1 // indirect
|
||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect
|
||||
@@ -107,7 +107,6 @@ require (
|
||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
|
||||
22
core/go.sum
22
core/go.sum
@@ -101,8 +101,8 @@ github.com/metacubex/bart v0.19.0 h1:XQ9AJeI+WO+phRPkUOoflAFwlqDJnm5BPQpixciJQBY
|
||||
github.com/metacubex/bart v0.19.0/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI=
|
||||
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 h1:oBowHVKZycNtAFbZ6avaCSZJYeme2Nrj+4RpV2cNJig=
|
||||
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399/go.mod h1:4xcieuIK+M4bGQmQYZVqEaIYqjS1ahO4kXG7EmDgEro=
|
||||
github.com/metacubex/chacha v0.1.1 h1:OHIv11Nd9CISAIzegpjfupIoZp9DYm6uQw41RxvmU/c=
|
||||
github.com/metacubex/chacha v0.1.1/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
|
||||
github.com/metacubex/chacha v0.1.2 h1:QulCq3eVm3TO6+4nVIWJtmSe7BT2GMrgVHuAoqRQnlc=
|
||||
github.com/metacubex/chacha v0.1.2/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
|
||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI=
|
||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
||||
github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b h1:RUh4OdVPz/jDrM9MQ2ySuqu2aeBqcA8rtfWUYLZ8RtI=
|
||||
@@ -111,24 +111,24 @@ github.com/metacubex/quic-go v0.49.1-0.20250212162123-c135a4412996 h1:B+AP/Pj2/j
|
||||
github.com/metacubex/quic-go v0.49.1-0.20250212162123-c135a4412996/go.mod h1:ExVjGyEwTUjCFqx+5uxgV7MOoA3fZI+th4D40H35xmY=
|
||||
github.com/metacubex/randv2 v0.2.0 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
||||
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
||||
github.com/metacubex/reality v0.0.0-20250219003814-74e8d7850629 h1:aHsYiTvubfgMa3JMTDY//hDXVvFWrHg6ARckR52ttZs=
|
||||
github.com/metacubex/reality v0.0.0-20250219003814-74e8d7850629/go.mod h1:TTeIOZLdGmzc07Oedn++vWUUfkZoXLF4sEMxWuhBFr8=
|
||||
github.com/metacubex/sing-quic v0.0.0-20250119013740-2a19cce83925 h1:UkPoRAnoBQMn7IK5qpoIV3OejU15q+rqel3NrbSCFKA=
|
||||
github.com/metacubex/sing-quic v0.0.0-20250119013740-2a19cce83925/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8=
|
||||
github.com/metacubex/sing-quic v0.0.0-20250404030904-b2cc8aab562c h1:OB3WmMA8YPJjE36RjD9X8xlrWGJ4orxbf2R/KAE28b0=
|
||||
github.com/metacubex/sing-quic v0.0.0-20250404030904-b2cc8aab562c/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8=
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJRafgwBHO5B4=
|
||||
github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0=
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo=
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q=
|
||||
github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04 h1:B211C+i/I8CWf4I/BaAV0mmkEHrDBJ0XR9EWxjPbFEg=
|
||||
github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04/go.mod h1:V0N4rr0dWPBEE20ESkTXdbtx2riQYcb6YtwC5w/9wl0=
|
||||
github.com/metacubex/sing-shadowtls v0.0.0-20250412122235-0e9005731a63 h1:vy/8ZYYtWUXYnOnw/NF8ThG1W/RqM/h5rkun+OXZMH0=
|
||||
github.com/metacubex/sing-shadowtls v0.0.0-20250412122235-0e9005731a63/go.mod h1:eDZ2JpkSkewGmUlCoLSn2MRFn1D0jKPIys/6aogFx7U=
|
||||
github.com/metacubex/sing-tun v0.4.6-0.20250412144348-c426cb167db5 h1:hcsz5e5lqhBxn3iQQDIF60FLZ8PQT542GTQZ+1wcIGo=
|
||||
github.com/metacubex/sing-tun v0.4.6-0.20250412144348-c426cb167db5/go.mod h1:V0N4rr0dWPBEE20ESkTXdbtx2riQYcb6YtwC5w/9wl0=
|
||||
github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82 h1:zZp5uct9+/0Hb1jKGyqDjCU4/72t43rs7qOq3Rc9oU8=
|
||||
github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82/go.mod h1:nE7Mdzj/QUDwgRi/8BASPtsxtIFZTHA4Yst5GgwbGCQ=
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589 h1:Z6bNy0HLTjx6BKIkV48sV/yia/GP8Bnyb5JQuGgSGzg=
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589/go.mod h1:4NclTLIZuk+QkHVCGrP87rHi/y8YjgPytxTgApJNMhc=
|
||||
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422 h1:zGeQt3UyNydIVrMRB97AA5WsYEau/TyCnRtTf1yUmJY=
|
||||
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
||||
github.com/metacubex/utls v1.6.8-alpha.4 h1:5EvsCHxDNneaOtAyc8CztoNSpmonLvkvuGs01lIeeEI=
|
||||
github.com/metacubex/utls v1.6.8-alpha.4/go.mod h1:MEZ5WO/VLKYs/s/dOzEK/mlXOQxc04ESeLzRgjmLYtk=
|
||||
github.com/metacubex/utls v1.7.0-alpha.1 h1:oMFsPh2oTlALJ7vKXPJuqgy0YeiZ+q/LLw+ZdxZ80l4=
|
||||
github.com/metacubex/utls v1.7.0-alpha.1/go.mod h1:oknYT0qTOwE4hjPmZOEpzVdefnW7bAdGLvZcqmk4TLU=
|
||||
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ=
|
||||
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181/go.mod h1:phewKljNYiTVT31Gcif8RiCKnTUOgVWFJjccqYM8s+Y=
|
||||
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
||||
@@ -174,8 +174,6 @@ github.com/sagernet/sing v0.5.2 h1:2OZQJNKGtji/66QLxbf/T/dqtK/3+fF/zuHH9tsGK7M=
|
||||
github.com/sagernet/sing v0.5.2/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-mux v0.2.1 h1:N/3MHymfnFZRd29tE3TaXwPUVVgKvxhtOkiCMLp9HVo=
|
||||
github.com/sagernet/sing-mux v0.2.1/go.mod h1:dm3BWL6NvES9pbib7llpylrq7Gq+LjlzG+0RacdxcyE=
|
||||
github.com/sagernet/sing-shadowtls v0.1.5 h1:uXxmq/HXh8DIiBGLzpMjCbWnzIAFs+lIxiTOjdgG5qo=
|
||||
github.com/sagernet/sing-shadowtls v0.1.5/go.mod h1:tvrDPTGLrSM46Wnf7mSr+L8NHvgvF8M4YnJF790rZX4=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
||||
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
|
||||
|
||||
@@ -442,6 +442,10 @@ func handleSetState(params string) {
|
||||
_ = json.Unmarshal([]byte(params), state.CurrentState)
|
||||
}
|
||||
|
||||
func handleCrash() {
|
||||
panic("handle invoke crash")
|
||||
}
|
||||
|
||||
func init() {
|
||||
adapter.UrlTestHook = func(url string, name string, delay uint16) {
|
||||
delayData := &Delay{
|
||||
|
||||
@@ -98,13 +98,13 @@ func handleStopTun() {
|
||||
}
|
||||
}
|
||||
|
||||
func handleStartTun(fd int, callback unsafe.Pointer) bool {
|
||||
func handleStartTun(fd int, callback unsafe.Pointer) {
|
||||
handleStopTun()
|
||||
tunLock.Lock()
|
||||
defer tunLock.Unlock()
|
||||
now := time.Now()
|
||||
runTime = &now
|
||||
if fd != 0 {
|
||||
tunLock.Lock()
|
||||
defer tunLock.Unlock()
|
||||
tunHandler = &TunHandler{
|
||||
callback: callback,
|
||||
limit: semaphore.NewWeighted(4),
|
||||
@@ -113,13 +113,11 @@ func handleStartTun(fd int, callback unsafe.Pointer) bool {
|
||||
tunListener, _ := t.Start(fd, currentConfig.General.Tun.Device, currentConfig.General.Tun.Stack)
|
||||
if tunListener != nil {
|
||||
log.Infoln("TUN address: %v", tunListener.Address())
|
||||
tunHandler.listener = tunListener
|
||||
} else {
|
||||
removeTunHook()
|
||||
return false
|
||||
}
|
||||
tunHandler.listener = tunListener
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func handleGetRunTime() string {
|
||||
@@ -228,7 +226,10 @@ func quickStart(initParamsChar *C.char, paramsChar *C.char, stateParamsChar *C.c
|
||||
|
||||
//export startTUN
|
||||
func startTUN(fd C.int, callback unsafe.Pointer) bool {
|
||||
return handleStartTun(int(fd), callback)
|
||||
go func() {
|
||||
handleStartTun(int(fd), callback)
|
||||
}()
|
||||
return true
|
||||
}
|
||||
|
||||
//export getRunTime
|
||||
@@ -238,7 +239,9 @@ func getRunTime() *C.char {
|
||||
|
||||
//export stopTun
|
||||
func stopTun() {
|
||||
go func() {
|
||||
handleStopTun()
|
||||
}()
|
||||
}
|
||||
|
||||
//export getCurrentProfileName
|
||||
|
||||
@@ -24,7 +24,6 @@ type AccessControl struct {
|
||||
Mode string `json:"mode"`
|
||||
AcceptList []string `json:"acceptList"`
|
||||
RejectList []string `json:"rejectList"`
|
||||
IsFilterSystemApp bool `json:"isFilterSystemApp"`
|
||||
}
|
||||
|
||||
type AndroidVpnRawOptions struct {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:dynamic_color/dynamic_color.dart';
|
||||
import 'package:fl_clash/clash/clash.dart';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/l10n/l10n.dart';
|
||||
@@ -14,7 +13,6 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'controller.dart';
|
||||
import 'models/models.dart';
|
||||
import 'pages/pages.dart';
|
||||
|
||||
class Application extends ConsumerStatefulWidget {
|
||||
@@ -27,7 +25,6 @@ class Application extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class ApplicationState extends ConsumerState<Application> {
|
||||
late ColorSchemes systemColorSchemes;
|
||||
Timer? _autoUpdateGroupTaskTimer;
|
||||
Timer? _autoUpdateProfilesTaskTimer;
|
||||
|
||||
@@ -132,19 +129,6 @@ class ApplicationState extends ConsumerState<Application> {
|
||||
);
|
||||
}
|
||||
|
||||
_updateSystemColorSchemes(
|
||||
ColorScheme? lightDynamic,
|
||||
ColorScheme? darkDynamic,
|
||||
) {
|
||||
systemColorSchemes = ColorSchemes(
|
||||
lightColorScheme: lightDynamic,
|
||||
darkColorScheme: darkDynamic,
|
||||
);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
globalState.appController.updateSystemColorSchemes(systemColorSchemes);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(context) {
|
||||
return _buildPlatformState(
|
||||
@@ -154,9 +138,6 @@ class ApplicationState extends ConsumerState<Application> {
|
||||
final locale =
|
||||
ref.watch(appSettingProvider.select((state) => state.locale));
|
||||
final themeProps = ref.watch(themeSettingProvider);
|
||||
return DynamicColorBuilder(
|
||||
builder: (lightDynamic, darkDynamic) {
|
||||
_updateSystemColorSchemes(lightDynamic, darkDynamic);
|
||||
return MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
navigatorKey: globalState.navigatorKey,
|
||||
@@ -197,8 +178,6 @@ class ApplicationState extends ConsumerState<Application> {
|
||||
home: child,
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: const HomePage(),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -58,6 +58,8 @@ mixin ClashInterface {
|
||||
|
||||
stopLog();
|
||||
|
||||
Future<bool> crash();
|
||||
|
||||
FutureOr<String> getConnections();
|
||||
|
||||
FutureOr<bool> closeConnection(String id);
|
||||
@@ -104,6 +106,7 @@ abstract class ClashHandlerInterface with ClashInterface {
|
||||
case ActionMethod.closeConnection:
|
||||
case ActionMethod.stopListener:
|
||||
case ActionMethod.setState:
|
||||
case ActionMethod.crash:
|
||||
completer?.complete(result.data as bool);
|
||||
return;
|
||||
case ActionMethod.changeProxy:
|
||||
@@ -242,6 +245,13 @@ abstract class ClashHandlerInterface with ClashInterface {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> crash() {
|
||||
return invoke<bool>(
|
||||
method: ActionMethod.crash,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> getProxies() {
|
||||
return invoke<String>(
|
||||
|
||||
@@ -73,7 +73,7 @@ class ClashService extends ClashHandlerInterface {
|
||||
commonPrint.log(error.toString());
|
||||
if (error is SocketException) {
|
||||
globalState.showNotifier(error.toString());
|
||||
globalState.appController.restartCore();
|
||||
// globalState.appController.restartCore();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -92,13 +92,12 @@ class ClashService extends ClashHandlerInterface {
|
||||
final arg = Platform.isWindows
|
||||
? "${serverSocket.port}"
|
||||
: serverSocket.address.address;
|
||||
bool isSuccess = false;
|
||||
if (Platform.isWindows && await system.checkIsAdmin()) {
|
||||
isSuccess = await request.startCoreByHelper(arg);
|
||||
}
|
||||
final isSuccess = await request.startCoreByHelper(arg);
|
||||
if (isSuccess) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
process = await Process.start(
|
||||
appPath.corePath,
|
||||
[
|
||||
|
||||
@@ -12,7 +12,7 @@ export 'iterable.dart';
|
||||
export 'keyboard.dart';
|
||||
export 'launch.dart';
|
||||
export 'link.dart';
|
||||
export 'list.dart';
|
||||
export 'fixed.dart';
|
||||
export 'lock.dart';
|
||||
export 'measure.dart';
|
||||
export 'navigation.dart';
|
||||
|
||||
@@ -16,16 +16,14 @@ const browserUa =
|
||||
const packageName = "com.follow.clash";
|
||||
final unixSocketPath = "/tmp/FlClashSocket_${Random().nextInt(10000)}.sock";
|
||||
const helperPort = 47890;
|
||||
const helperTag = "2024125";
|
||||
const baseInfoEdgeInsets = EdgeInsets.symmetric(
|
||||
vertical: 16,
|
||||
horizontal: 16,
|
||||
const maxTextScale = 1.4;
|
||||
const minTextScale = 0.8;
|
||||
final baseInfoEdgeInsets = EdgeInsets.symmetric(
|
||||
vertical: 16.ap,
|
||||
horizontal: 16.ap,
|
||||
);
|
||||
|
||||
double textScaleFactor = min(
|
||||
WidgetsBinding.instance.platformDispatcher.textScaleFactor,
|
||||
1.2,
|
||||
);
|
||||
final defaultTextScaleFactor = WidgetsBinding.instance.platformDispatcher.textScaleFactor;
|
||||
const httpTimeoutDuration = Duration(milliseconds: 5000);
|
||||
const moreDuration = Duration(milliseconds: 100);
|
||||
const animateDuration = Duration(milliseconds: 100);
|
||||
@@ -44,7 +42,6 @@ const profilesDirectoryName = "profiles";
|
||||
const localhost = "127.0.0.1";
|
||||
const clashConfigKey = "clash_config";
|
||||
const configKey = "config";
|
||||
const listItemPadding = EdgeInsets.symmetric(horizontal: 16);
|
||||
const double dialogCommonWidth = 300;
|
||||
const repository = "chen08209/FlClash";
|
||||
const defaultExternalController = "127.0.0.1:9090";
|
||||
@@ -60,6 +57,7 @@ final commonFilter = ImageFilter.blur(
|
||||
const navigationItemListEquality = ListEquality<NavigationItem>();
|
||||
const connectionListEquality = ListEquality<Connection>();
|
||||
const stringListEquality = ListEquality<String>();
|
||||
const intListEquality = ListEquality<int>();
|
||||
const logListEquality = ListEquality<Log>();
|
||||
const groupListEquality = ListEquality<Group>();
|
||||
const externalProviderListEquality = ListEquality<ExternalProvider>();
|
||||
@@ -78,22 +76,24 @@ const viewModeColumnsMap = {
|
||||
ViewMode.desktop: [4, 3],
|
||||
};
|
||||
|
||||
const defaultPrimaryColor = 0xFF795548;
|
||||
const defaultPrimaryColor = 0XFFD8C0C3;
|
||||
|
||||
double getWidgetHeight(num lines) {
|
||||
return max(lines * 84 * textScaleFactor + (lines - 1) * 16, 0);
|
||||
return max(lines * 84 + (lines - 1) * 16, 0).ap;
|
||||
}
|
||||
|
||||
const maxLength = 150;
|
||||
|
||||
final mainIsolate = "FlClashMainIsolate";
|
||||
|
||||
final serviceIsolate = "FlClashServiceIsolate";
|
||||
|
||||
const defaultPrimaryColors = [
|
||||
defaultPrimaryColor,
|
||||
0xFF795548,
|
||||
0xFF03A9F4,
|
||||
0xFFFFFF00,
|
||||
0XFFBBC9CC,
|
||||
0XFFABD397,
|
||||
0XFFD8C0C3,
|
||||
defaultPrimaryColor,
|
||||
0XFF665390,
|
||||
];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:fl_clash/manager/manager.dart';
|
||||
import 'package:fl_clash/manager/message_manager.dart';
|
||||
import 'package:fl_clash/widgets/scaffold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -11,6 +11,36 @@ extension BuildContextExtension on BuildContext {
|
||||
return findAncestorStateOfType<MessageManagerState>()?.message(text);
|
||||
}
|
||||
|
||||
showSnackBar(
|
||||
String message, {
|
||||
SnackBarAction? action,
|
||||
}) {
|
||||
final width = viewWidth;
|
||||
EdgeInsets margin;
|
||||
if (width < 600) {
|
||||
margin = const EdgeInsets.only(
|
||||
bottom: 16,
|
||||
right: 16,
|
||||
left: 16,
|
||||
);
|
||||
} else {
|
||||
margin = EdgeInsets.only(
|
||||
bottom: 16,
|
||||
left: 16,
|
||||
right: width - 316,
|
||||
);
|
||||
}
|
||||
ScaffoldMessenger.of(this).showSnackBar(
|
||||
SnackBar(
|
||||
action: action,
|
||||
content: Text(message),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
duration: const Duration(milliseconds: 1500),
|
||||
margin: margin,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Size get appSize {
|
||||
return MediaQuery.of(this).size;
|
||||
}
|
||||
|
||||
79
lib/common/fixed.dart
Normal file
79
lib/common/fixed.dart
Normal file
@@ -0,0 +1,79 @@
|
||||
import 'iterable.dart';
|
||||
|
||||
class FixedList<T> {
|
||||
final int maxLength;
|
||||
final List<T> _list;
|
||||
|
||||
FixedList(this.maxLength, {List<T>? list})
|
||||
: _list = (list ?? [])..truncate(maxLength);
|
||||
|
||||
add(T item) {
|
||||
_list.add(item);
|
||||
_list.truncate(maxLength);
|
||||
}
|
||||
|
||||
clear() {
|
||||
_list.clear();
|
||||
}
|
||||
|
||||
List<T> get list => List.unmodifiable(_list);
|
||||
|
||||
int get length => _list.length;
|
||||
|
||||
T operator [](int index) => _list[index];
|
||||
|
||||
FixedList<T> copyWith() {
|
||||
return FixedList(
|
||||
maxLength,
|
||||
list: _list,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FixedMap<K, V> {
|
||||
int maxLength;
|
||||
late Map<K, V> _map;
|
||||
|
||||
FixedMap(this.maxLength, {Map<K, V>? map}) {
|
||||
_map = map ?? {};
|
||||
}
|
||||
|
||||
updateCacheValue(K key, V Function() callback) {
|
||||
final realValue = _map.updateCacheValue(
|
||||
key,
|
||||
callback,
|
||||
);
|
||||
_adjustMap();
|
||||
return realValue;
|
||||
}
|
||||
|
||||
clear() {
|
||||
_map.clear();
|
||||
}
|
||||
|
||||
updateMaxLength(int size) {
|
||||
maxLength = size;
|
||||
_adjustMap();
|
||||
}
|
||||
|
||||
updateMap(Map<K, V> map) {
|
||||
_map = map;
|
||||
_adjustMap();
|
||||
}
|
||||
|
||||
_adjustMap() {
|
||||
if (_map.length > maxLength) {
|
||||
_map = Map.fromEntries(
|
||||
map.entries.toList()..truncate(maxLength),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
V? get(K key) => _map[key];
|
||||
|
||||
bool containsKey(K key) => _map.containsKey(key);
|
||||
|
||||
int get length => _map.length;
|
||||
|
||||
Map<K, V> get map => Map.unmodifiable(_map);
|
||||
}
|
||||
@@ -38,6 +38,43 @@ extension IterableExt<T> on Iterable<T> {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
Iterable<T> takeLast({int count = 50}) {
|
||||
if (count <= 0) return Iterable.empty();
|
||||
return count >= length ? this : toList().skip(length - count);
|
||||
}
|
||||
}
|
||||
|
||||
extension ListExt<T> on List<T> {
|
||||
void truncate(int maxLength) {
|
||||
assert(maxLength > 0);
|
||||
if (length > maxLength) {
|
||||
removeRange(0, length - maxLength);
|
||||
}
|
||||
}
|
||||
|
||||
List<T> intersection(List<T> list) {
|
||||
return where((item) => list.contains(item)).toList();
|
||||
}
|
||||
|
||||
List<List<T>> batch(int maxConcurrent) {
|
||||
final batches = (length / maxConcurrent).ceil();
|
||||
final List<List<T>> res = [];
|
||||
for (int i = 0; i < batches; i++) {
|
||||
if (i != batches - 1) {
|
||||
res.add(sublist(i * maxConcurrent, maxConcurrent * (i + 1)));
|
||||
} else {
|
||||
res.add(sublist(i * maxConcurrent, length));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
List<T> safeSublist(int start) {
|
||||
if (start <= 0) return this;
|
||||
if (start > length) return [];
|
||||
return sublist(start);
|
||||
}
|
||||
}
|
||||
|
||||
extension DoubleListExt on List<double> {
|
||||
@@ -67,9 +104,9 @@ extension DoubleListExt on List<double> {
|
||||
}
|
||||
|
||||
extension MapExt<K, V> on Map<K, V> {
|
||||
getCacheValue(K key, V defaultValue) {
|
||||
updateCacheValue(K key, V Function() callback) {
|
||||
if (this[key] == null) {
|
||||
this[key] = defaultValue;
|
||||
this[key] = callback();
|
||||
}
|
||||
return this[key];
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
import 'dart:collection';
|
||||
|
||||
class FixedList<T> {
|
||||
final int maxLength;
|
||||
final List<T> _list;
|
||||
|
||||
FixedList(this.maxLength, {List<T>? list}) : _list = list ?? [];
|
||||
|
||||
add(T item) {
|
||||
if (_list.length == maxLength) {
|
||||
_list.removeAt(0);
|
||||
}
|
||||
_list.add(item);
|
||||
}
|
||||
|
||||
clear() {
|
||||
_list.clear();
|
||||
}
|
||||
|
||||
List<T> get list => List.unmodifiable(_list);
|
||||
|
||||
int get length => _list.length;
|
||||
|
||||
T operator [](int index) => _list[index];
|
||||
|
||||
FixedList<T> copyWith() {
|
||||
return FixedList(
|
||||
maxLength,
|
||||
list: _list,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class FixedMap<K, V> {
|
||||
int maxSize;
|
||||
final Map<K, V> _map = {};
|
||||
final Queue<K> _queue = Queue<K>();
|
||||
|
||||
FixedMap(this.maxSize);
|
||||
|
||||
put(K key, V value) {
|
||||
if (_map.length == maxSize) {
|
||||
final oldestKey = _queue.removeFirst();
|
||||
_map.remove(oldestKey);
|
||||
}
|
||||
_map[key] = value;
|
||||
_queue.add(key);
|
||||
return value;
|
||||
}
|
||||
|
||||
clear() {
|
||||
_map.clear();
|
||||
_queue.clear();
|
||||
}
|
||||
|
||||
updateMaxSize(int size){
|
||||
maxSize = size;
|
||||
}
|
||||
|
||||
V? get(K key) => _map[key];
|
||||
|
||||
|
||||
bool containsKey(K key) => _map.containsKey(key);
|
||||
|
||||
int get length => _map.length;
|
||||
|
||||
Map<K, V> get map => Map.unmodifiable(_map);
|
||||
}
|
||||
|
||||
extension ListExtension<T> on List<T> {
|
||||
List<T> intersection(List<T> list) {
|
||||
return where((item) => list.contains(item)).toList();
|
||||
}
|
||||
|
||||
List<List<T>> batch(int maxConcurrent) {
|
||||
final batches = (length / maxConcurrent).ceil();
|
||||
final List<List<T>> res = [];
|
||||
for (int i = 0; i < batches; i++) {
|
||||
if (i != batches - 1) {
|
||||
res.add(sublist(i * maxConcurrent, maxConcurrent * (i + 1)));
|
||||
} else {
|
||||
res.add(sublist(i * maxConcurrent, length));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
List<T> safeSublist(int start) {
|
||||
if (start <= 0) return this;
|
||||
if (start > length) return [];
|
||||
return sublist(start);
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,13 @@ import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Measure {
|
||||
final TextScaler _textScale;
|
||||
final TextScaler _textScaler;
|
||||
final BuildContext context;
|
||||
final Map<String, dynamic> _measureMap;
|
||||
|
||||
Measure.of(this.context)
|
||||
: _textScale = TextScaler.linear(
|
||||
Measure.of(this.context, double textScaleFactor)
|
||||
: _measureMap = {},
|
||||
_textScaler = TextScaler.linear(
|
||||
textScaleFactor,
|
||||
);
|
||||
|
||||
@@ -21,7 +23,7 @@ class Measure {
|
||||
style: text.style,
|
||||
),
|
||||
maxLines: text.maxLines,
|
||||
textScaler: _textScale,
|
||||
textScaler: _textScaler,
|
||||
textDirection: text.textDirection ?? TextDirection.ltr,
|
||||
)..layout(
|
||||
maxWidth: maxWidth,
|
||||
@@ -29,81 +31,87 @@ class Measure {
|
||||
return textPainter.size;
|
||||
}
|
||||
|
||||
double? _bodyMediumHeight;
|
||||
Size? _bodyLargeSize;
|
||||
double? _bodySmallHeight;
|
||||
double? _labelSmallHeight;
|
||||
double? _labelMediumHeight;
|
||||
double? _titleLargeHeight;
|
||||
double? _titleMediumHeight;
|
||||
|
||||
double get bodyMediumHeight {
|
||||
_bodyMediumHeight ??= computeTextSize(
|
||||
return _measureMap.updateCacheValue(
|
||||
"bodyMediumHeight",
|
||||
() => computeTextSize(
|
||||
Text(
|
||||
"X",
|
||||
style: context.textTheme.bodyMedium,
|
||||
),
|
||||
).height;
|
||||
return _bodyMediumHeight!;
|
||||
).height,
|
||||
);
|
||||
}
|
||||
|
||||
Size get bodyLargeSize {
|
||||
_bodyLargeSize ??= computeTextSize(
|
||||
double get bodyLargeHeight {
|
||||
return _measureMap.updateCacheValue(
|
||||
"bodyLargeHeight",
|
||||
() => computeTextSize(
|
||||
Text(
|
||||
"X",
|
||||
style: context.textTheme.bodyLarge,
|
||||
),
|
||||
).height,
|
||||
);
|
||||
return _bodyLargeSize!;
|
||||
}
|
||||
|
||||
double get bodySmallHeight {
|
||||
_bodySmallHeight ??= computeTextSize(
|
||||
return _measureMap.updateCacheValue(
|
||||
"bodySmallHeight",
|
||||
() => computeTextSize(
|
||||
Text(
|
||||
"X",
|
||||
style: context.textTheme.bodySmall,
|
||||
),
|
||||
).height;
|
||||
return _bodySmallHeight!;
|
||||
).height,
|
||||
);
|
||||
}
|
||||
|
||||
double get labelSmallHeight {
|
||||
_labelSmallHeight ??= computeTextSize(
|
||||
return _measureMap.updateCacheValue(
|
||||
"labelSmallHeight",
|
||||
() => computeTextSize(
|
||||
Text(
|
||||
"X",
|
||||
style: context.textTheme.labelSmall,
|
||||
),
|
||||
).height;
|
||||
return _labelSmallHeight!;
|
||||
).height,
|
||||
);
|
||||
}
|
||||
|
||||
double get labelMediumHeight {
|
||||
_labelMediumHeight ??= computeTextSize(
|
||||
return _measureMap.updateCacheValue(
|
||||
"labelMediumHeight",
|
||||
() => computeTextSize(
|
||||
Text(
|
||||
"X",
|
||||
style: context.textTheme.labelMedium,
|
||||
),
|
||||
).height;
|
||||
return _labelMediumHeight!;
|
||||
).height,
|
||||
);
|
||||
}
|
||||
|
||||
double get titleLargeHeight {
|
||||
_titleLargeHeight ??= computeTextSize(
|
||||
return _measureMap.updateCacheValue(
|
||||
"titleLargeHeight",
|
||||
() => computeTextSize(
|
||||
Text(
|
||||
"X",
|
||||
style: context.textTheme.titleLarge,
|
||||
),
|
||||
).height;
|
||||
return _titleLargeHeight!;
|
||||
).height,
|
||||
);
|
||||
}
|
||||
|
||||
double get titleMediumHeight {
|
||||
_titleMediumHeight ??= computeTextSize(
|
||||
return _measureMap.updateCacheValue(
|
||||
"titleMediumHeight",
|
||||
() => computeTextSize(
|
||||
Text(
|
||||
"X",
|
||||
style: context.textTheme.titleMedium,
|
||||
),
|
||||
).height;
|
||||
return _titleMediumHeight!;
|
||||
).height,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ class Navigation {
|
||||
const NavigationItem(
|
||||
icon: Icon(Icons.space_dashboard),
|
||||
label: PageLabel.dashboard,
|
||||
keep: false,
|
||||
fragment: DashboardFragment(
|
||||
key: GlobalObjectKey(PageLabel.dashboard),
|
||||
),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -12,6 +13,10 @@ extension NumExt on num {
|
||||
}
|
||||
return formatted;
|
||||
}
|
||||
|
||||
double get ap {
|
||||
return this * (1 + (globalState.theme.textScaleFactor - 1) * 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
extension DoubleExt on double {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/models/models.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
@@ -20,10 +19,7 @@ class CommonPrint {
|
||||
return;
|
||||
}
|
||||
globalState.appController.addLog(
|
||||
Log(
|
||||
logLevel: LogLevel.info,
|
||||
payload: payload,
|
||||
),
|
||||
Log.app(payload),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class Request {
|
||||
if (response.statusCode != HttpStatus.ok) {
|
||||
return false;
|
||||
}
|
||||
return (response.data as String) == helperTag;
|
||||
return (response.data as String) == globalState.coreSHA256;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -55,18 +55,24 @@ class System {
|
||||
}
|
||||
|
||||
Future<AuthorizeCode> authorizeCore() async {
|
||||
if (Platform.isAndroid) {
|
||||
return AuthorizeCode.none;
|
||||
}
|
||||
final corePath = appPath.corePath.replaceAll(' ', '\\\\ ');
|
||||
final isAdmin = await checkIsAdmin();
|
||||
if (isAdmin) {
|
||||
return AuthorizeCode.none;
|
||||
}
|
||||
|
||||
if (Platform.isWindows) {
|
||||
final result = await windows?.registerService();
|
||||
if (result == true) {
|
||||
return AuthorizeCode.success;
|
||||
}
|
||||
return AuthorizeCode.error;
|
||||
} else if (Platform.isMacOS) {
|
||||
}
|
||||
|
||||
if (Platform.isMacOS) {
|
||||
final shell = 'chown root:admin $corePath; chmod +sx $corePath';
|
||||
final arguments = [
|
||||
"-e",
|
||||
|
||||
@@ -4,36 +4,43 @@ import 'package:flutter/material.dart';
|
||||
class CommonTheme {
|
||||
final BuildContext context;
|
||||
final Map<String, Color> _colorMap;
|
||||
final double textScaleFactor;
|
||||
|
||||
CommonTheme.of(this.context) : _colorMap = {};
|
||||
CommonTheme.of(
|
||||
this.context,
|
||||
this.textScaleFactor,
|
||||
) : _colorMap = {};
|
||||
|
||||
Color get darkenSecondaryContainer {
|
||||
return _colorMap.getCacheValue(
|
||||
return _colorMap.updateCacheValue(
|
||||
"darkenSecondaryContainer",
|
||||
context.colorScheme.secondaryContainer.blendDarken(context, factor: 0.1),
|
||||
() => context.colorScheme.secondaryContainer
|
||||
.blendDarken(context, factor: 0.1),
|
||||
);
|
||||
}
|
||||
|
||||
Color get darkenSecondaryContainerLighter {
|
||||
return _colorMap.getCacheValue(
|
||||
return _colorMap.updateCacheValue(
|
||||
"darkenSecondaryContainerLighter",
|
||||
context.colorScheme.secondaryContainer
|
||||
() => context.colorScheme.secondaryContainer
|
||||
.blendDarken(context, factor: 0.1)
|
||||
.opacity60,
|
||||
);
|
||||
}
|
||||
|
||||
Color get darken2SecondaryContainer {
|
||||
return _colorMap.getCacheValue(
|
||||
return _colorMap.updateCacheValue(
|
||||
"darken2SecondaryContainer",
|
||||
context.colorScheme.secondaryContainer.blendDarken(context, factor: 0.2),
|
||||
() => context.colorScheme.secondaryContainer
|
||||
.blendDarken(context, factor: 0.2),
|
||||
);
|
||||
}
|
||||
|
||||
Color get darken3PrimaryContainer {
|
||||
return _colorMap.getCacheValue(
|
||||
return _colorMap.updateCacheValue(
|
||||
"darken3PrimaryContainer",
|
||||
context.colorScheme.primaryContainer.blendDarken(context, factor: 0.3),
|
||||
() => context.colorScheme.primaryContainer
|
||||
.blendDarken(context, factor: 0.3),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ class Tray {
|
||||
);
|
||||
}
|
||||
menuItems.add(MenuItem.separator());
|
||||
if (!Platform.isWindows) {
|
||||
if (Platform.isMacOS) {
|
||||
for (final group in trayState.groups) {
|
||||
List<MenuItem> subMenuItems = [];
|
||||
for (final proxy in group.all) {
|
||||
|
||||
@@ -260,9 +260,7 @@ class AppController {
|
||||
final patchConfig = _ref.read(patchClashConfigProvider);
|
||||
final appSetting = _ref.read(appSettingProvider);
|
||||
bool enableTun = patchConfig.tun.enable;
|
||||
if (enableTun != lastTunEnable &&
|
||||
lastTunEnable == false &&
|
||||
!Platform.isAndroid) {
|
||||
if (enableTun != lastTunEnable && lastTunEnable == false) {
|
||||
final code = await system.authorizeCore();
|
||||
switch (code) {
|
||||
case AuthorizeCode.none:
|
||||
@@ -314,6 +312,10 @@ class AppController {
|
||||
handleChangeProfile() {
|
||||
_ref.read(delayDataSourceProvider.notifier).value = {};
|
||||
applyProfile();
|
||||
_ref.read(logsProvider.notifier).value = FixedList(500);
|
||||
_ref.read(requestsProvider.notifier).value = FixedList(500);
|
||||
globalState.cacheHeightMap = {};
|
||||
globalState.cacheScrollPosition = {};
|
||||
}
|
||||
|
||||
updateBrightness(Brightness brightness) {
|
||||
@@ -334,23 +336,22 @@ class AppController {
|
||||
try {
|
||||
await updateProfile(profile);
|
||||
} catch (e) {
|
||||
_ref.read(logsProvider.notifier).addLog(
|
||||
Log(
|
||||
logLevel: LogLevel.info,
|
||||
payload: e.toString(),
|
||||
),
|
||||
);
|
||||
commonPrint.log(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateGroups() async {
|
||||
try {
|
||||
_ref.read(groupsProvider.notifier).value = await retry(
|
||||
task: () async {
|
||||
return await clashCore.getProxiesGroups();
|
||||
},
|
||||
retryIf: (res) => res.isEmpty,
|
||||
);
|
||||
} catch (_) {
|
||||
_ref.read(groupsProvider.notifier).value = [];
|
||||
}
|
||||
}
|
||||
|
||||
updateProfiles() async {
|
||||
@@ -362,10 +363,6 @@ class AppController {
|
||||
}
|
||||
}
|
||||
|
||||
updateSystemColorSchemes(ColorSchemes colorSchemes) {
|
||||
_ref.read(appSchemesProvider.notifier).value = colorSchemes;
|
||||
}
|
||||
|
||||
savePreferences() async {
|
||||
commonPrint.log("save preferences");
|
||||
await preferences.saveConfig(globalState.config);
|
||||
@@ -401,15 +398,23 @@ class AppController {
|
||||
handleExit() async {
|
||||
try {
|
||||
await updateStatus(false);
|
||||
await proxy?.stopProxy();
|
||||
await clashCore.shutdown();
|
||||
await clashService?.destroy();
|
||||
await proxy?.stopProxy();
|
||||
await savePreferences();
|
||||
} finally {
|
||||
system.exit();
|
||||
}
|
||||
}
|
||||
|
||||
Future handleClear() async {
|
||||
await preferences.clearPreferences();
|
||||
commonPrint.log("clear preferences");
|
||||
globalState.config = Config(
|
||||
themeProps: defaultThemeProps,
|
||||
);
|
||||
}
|
||||
|
||||
autoCheckUpdate() async {
|
||||
if (!_ref.read(appSettingProvider).autoCheckUpdate) return;
|
||||
final res = await request.checkForUpdate();
|
||||
@@ -484,10 +489,10 @@ class AppController {
|
||||
Future<void> _initCore() async {
|
||||
final isInit = await clashCore.isInit;
|
||||
if (!isInit) {
|
||||
await clashCore.init();
|
||||
await clashCore.setState(
|
||||
globalState.getCoreState(),
|
||||
);
|
||||
await clashCore.init();
|
||||
}
|
||||
await applyProfile();
|
||||
}
|
||||
@@ -937,18 +942,21 @@ class AppController {
|
||||
}
|
||||
|
||||
_recovery(Config config, RecoveryOption recoveryOption) {
|
||||
final recoveryStrategy = _ref.read(appSettingProvider.select(
|
||||
(state) => state.recoveryStrategy,
|
||||
));
|
||||
final profiles = config.profiles;
|
||||
if (recoveryStrategy == RecoveryStrategy.override) {
|
||||
_ref.read(profilesProvider.notifier).value = profiles;
|
||||
} else {
|
||||
for (final profile in profiles) {
|
||||
_ref.read(profilesProvider.notifier).setProfile(profile);
|
||||
_ref.read(profilesProvider.notifier).setProfile(
|
||||
profile,
|
||||
);
|
||||
}
|
||||
}
|
||||
final onlyProfiles = recoveryOption == RecoveryOption.onlyProfiles;
|
||||
if (onlyProfiles) {
|
||||
final currentProfile = _ref.read(currentProfileProvider);
|
||||
if (currentProfile != null) {
|
||||
_ref.read(currentProfileIdProvider.notifier).value = profiles.first.id;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!onlyProfiles) {
|
||||
_ref.read(patchClashConfigProvider.notifier).value =
|
||||
config.patchClashConfig;
|
||||
_ref.read(appSettingProvider.notifier).value = config.appSetting;
|
||||
@@ -958,9 +966,15 @@ class AppController {
|
||||
_ref.read(themeSettingProvider.notifier).value = config.themeProps;
|
||||
_ref.read(windowSettingProvider.notifier).value = config.windowProps;
|
||||
_ref.read(vpnSettingProvider.notifier).value = config.vpnProps;
|
||||
_ref.read(proxiesStyleSettingProvider.notifier).value = config.proxiesStyle;
|
||||
_ref.read(proxiesStyleSettingProvider.notifier).value =
|
||||
config.proxiesStyle;
|
||||
_ref.read(overrideDnsProvider.notifier).value = config.overrideDns;
|
||||
_ref.read(networkSettingProvider.notifier).value = config.networkProps;
|
||||
_ref.read(hotKeyActionsProvider.notifier).value = config.hotKeyActions;
|
||||
}
|
||||
final currentProfile = _ref.read(currentProfileProvider);
|
||||
if (currentProfile == null) {
|
||||
_ref.read(currentProfileIdProvider.notifier).value = profiles.first.id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,14 @@ enum Mode { rule, global, direct }
|
||||
|
||||
enum ViewMode { mobile, laptop, desktop }
|
||||
|
||||
enum LogLevel { debug, info, warning, error, silent }
|
||||
enum LogLevel {
|
||||
debug,
|
||||
info,
|
||||
warning,
|
||||
error,
|
||||
silent,
|
||||
app,
|
||||
}
|
||||
|
||||
enum TransportProtocol { udp, tcp }
|
||||
|
||||
@@ -262,6 +269,7 @@ enum ActionMethod {
|
||||
getCountryCode,
|
||||
getMemory,
|
||||
getProfile,
|
||||
crash,
|
||||
|
||||
///Android,
|
||||
setFdMap,
|
||||
@@ -285,6 +293,7 @@ enum WindowsHelperServiceStatus {
|
||||
|
||||
enum DebounceTag {
|
||||
updateClashConfig,
|
||||
updateStatus,
|
||||
updateGroups,
|
||||
addCheckIpNum,
|
||||
applyProfile,
|
||||
@@ -308,6 +317,12 @@ enum DashboardWidget {
|
||||
child: NetworkSpeed(),
|
||||
),
|
||||
),
|
||||
outboundModeV2(
|
||||
GridItem(
|
||||
crossAxisCellCount: 8,
|
||||
child: OutboundModeV2(),
|
||||
),
|
||||
),
|
||||
outboundMode(
|
||||
GridItem(
|
||||
crossAxisCellCount: 4,
|
||||
@@ -333,6 +348,15 @@ enum DashboardWidget {
|
||||
),
|
||||
platforms: desktopPlatforms,
|
||||
),
|
||||
vpnButton(
|
||||
GridItem(
|
||||
crossAxisCellCount: 4,
|
||||
child: VpnButton(),
|
||||
),
|
||||
platforms: [
|
||||
SupportPlatform.Android,
|
||||
],
|
||||
),
|
||||
systemProxyButton(
|
||||
GridItem(
|
||||
crossAxisCellCount: 4,
|
||||
@@ -447,3 +471,14 @@ enum RuleTarget {
|
||||
DIRECT,
|
||||
REJECT,
|
||||
}
|
||||
|
||||
enum RecoveryStrategy {
|
||||
compatible,
|
||||
override,
|
||||
}
|
||||
|
||||
enum CacheTag {
|
||||
logs,
|
||||
rules,
|
||||
requests,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/providers/config.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:fl_clash/widgets/list.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
@immutable
|
||||
class Contributor {
|
||||
@@ -43,6 +47,15 @@ class AboutFragment extends StatelessWidget {
|
||||
_checkUpdate(context);
|
||||
},
|
||||
),
|
||||
ListItem(
|
||||
title: Text(appLocalizations.contactMe),
|
||||
onTap: () {
|
||||
globalState.showMessage(
|
||||
title: appLocalizations.contactMe,
|
||||
message: TextSpan(text: "chen08209@gmail.com"),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListItem(
|
||||
title: const Text("Telegram"),
|
||||
onTap: () {
|
||||
@@ -116,7 +129,9 @@ class AboutFragment extends StatelessWidget {
|
||||
title: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Wrap(
|
||||
Consumer(builder: (_, ref, ___) {
|
||||
return _DeveloperModeDetector(
|
||||
child: Wrap(
|
||||
spacing: 16,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
@@ -143,6 +158,14 @@ class AboutFragment extends StatelessWidget {
|
||||
)
|
||||
],
|
||||
),
|
||||
onEnterDeveloperMode: () {
|
||||
ref.read(appSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith(developerMode: true),
|
||||
);
|
||||
context.showNotifier(appLocalizations.developerModeEnableTip);
|
||||
},
|
||||
);
|
||||
}),
|
||||
const SizedBox(
|
||||
height: 24,
|
||||
),
|
||||
@@ -209,3 +232,52 @@ class Avatar extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DeveloperModeDetector extends StatefulWidget {
|
||||
final Widget child;
|
||||
final VoidCallback onEnterDeveloperMode;
|
||||
|
||||
const _DeveloperModeDetector({
|
||||
required this.child,
|
||||
required this.onEnterDeveloperMode,
|
||||
});
|
||||
|
||||
@override
|
||||
State<_DeveloperModeDetector> createState() => _DeveloperModeDetectorState();
|
||||
}
|
||||
|
||||
class _DeveloperModeDetectorState extends State<_DeveloperModeDetector> {
|
||||
int _counter = 0;
|
||||
Timer? _timer;
|
||||
|
||||
void _handleTap() {
|
||||
_counter++;
|
||||
if (_counter >= 5) {
|
||||
widget.onEnterDeveloperMode();
|
||||
_resetCounter();
|
||||
} else {
|
||||
_timer?.cancel();
|
||||
_timer = Timer(Duration(seconds: 1), _resetCounter);
|
||||
}
|
||||
}
|
||||
|
||||
void _resetCounter() {
|
||||
_counter = 0;
|
||||
_timer?.cancel();
|
||||
_timer = null;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: _handleTap,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,15 +113,11 @@ class _AccessFragmentState extends ConsumerState<AccessFragment> {
|
||||
}
|
||||
|
||||
_intelligentSelected() async {
|
||||
final appState = globalState.appState;
|
||||
final config = globalState.config;
|
||||
final accessControl = config.vpnProps.accessControl;
|
||||
final packageNames = appState.packages
|
||||
.where(
|
||||
(item) =>
|
||||
accessControl.isFilterSystemApp ? item.isSystem == false : true,
|
||||
)
|
||||
.map((item) => item.packageName);
|
||||
final packageNames = ref.read(
|
||||
packageListSelectorStateProvider.select(
|
||||
(state) => state.list.map((item) => item.packageName),
|
||||
),
|
||||
);
|
||||
final commonScaffoldState = context.commonScaffoldState;
|
||||
if (commonScaffoldState?.mounted != true) return;
|
||||
final selectedPackageNames =
|
||||
@@ -194,7 +190,7 @@ class _AccessFragmentState extends ConsumerState<AccessFragment> {
|
||||
final state = ref.watch(packageListSelectorStateProvider);
|
||||
final accessControl = state.accessControl;
|
||||
final accessControlMode = accessControl.mode;
|
||||
final packages = state.getList(
|
||||
final packages = state.getSortList(
|
||||
accessControlMode == AccessControlMode.acceptSelected
|
||||
? acceptList
|
||||
: rejectList,
|
||||
@@ -482,14 +478,20 @@ class AccessControlSearchDelegate extends SearchDelegate {
|
||||
final lowQuery = query.toLowerCase();
|
||||
return Consumer(
|
||||
builder: (context, ref, __) {
|
||||
final state = ref.watch(packageListSelectorStateProvider);
|
||||
final accessControl = state.accessControl;
|
||||
final accessControlMode = accessControl.mode;
|
||||
final packages = state.getList(
|
||||
accessControlMode == AccessControlMode.acceptSelected
|
||||
final vm3 = ref.watch(
|
||||
packageListSelectorStateProvider.select(
|
||||
(state) => VM3(
|
||||
a: state.getSortList(
|
||||
state.accessControl.mode == AccessControlMode.acceptSelected
|
||||
? acceptList
|
||||
: rejectList,
|
||||
),
|
||||
b: state.accessControl.enable,
|
||||
c: state.accessControl.currentList,
|
||||
),
|
||||
),
|
||||
);
|
||||
final packages = vm3.a;
|
||||
final queryPackages = packages
|
||||
.where(
|
||||
(package) =>
|
||||
@@ -497,8 +499,8 @@ class AccessControlSearchDelegate extends SearchDelegate {
|
||||
package.packageName.contains(lowQuery),
|
||||
)
|
||||
.toList();
|
||||
final isAccessControl = state.accessControl.enable;
|
||||
final currentList = accessControl.currentList;
|
||||
final isAccessControl = vm3.b;
|
||||
final currentList = vm3.c;
|
||||
final packageNameList = packages.map((e) => e.packageName).toList();
|
||||
final valueList = currentList.intersection(packageNameList);
|
||||
return DisabledMask(
|
||||
@@ -579,13 +581,6 @@ class _AccessControlPanelState extends ConsumerState<AccessControlPanel> {
|
||||
};
|
||||
}
|
||||
|
||||
String _getTextWithIsFilterSystemApp(bool isFilterSystemApp) {
|
||||
return switch (isFilterSystemApp) {
|
||||
true => appLocalizations.onlyOtherApps,
|
||||
false => appLocalizations.allApps,
|
||||
};
|
||||
}
|
||||
|
||||
List<Widget> _buildModeSetting() {
|
||||
return generateSection(
|
||||
title: appLocalizations.mode,
|
||||
@@ -673,21 +668,35 @@ class _AccessControlPanelState extends ConsumerState<AccessControlPanel> {
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final isFilterSystemApp = ref.watch(
|
||||
vpnSettingProvider
|
||||
.select((state) => state.accessControl.isFilterSystemApp),
|
||||
final vm2 = ref.watch(
|
||||
vpnSettingProvider.select(
|
||||
(state) => VM2(
|
||||
a: state.accessControl.isFilterSystemApp,
|
||||
b: state.accessControl.isFilterNonInternetApp,
|
||||
),
|
||||
),
|
||||
);
|
||||
return Wrap(
|
||||
spacing: 16,
|
||||
children: [
|
||||
for (final item in [false, true])
|
||||
SettingTextCard(
|
||||
_getTextWithIsFilterSystemApp(item),
|
||||
isSelected: isFilterSystemApp == item,
|
||||
appLocalizations.systemApp,
|
||||
isSelected: vm2.a == false,
|
||||
onPressed: () {
|
||||
ref.read(vpnSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith.accessControl(
|
||||
isFilterSystemApp: item,
|
||||
isFilterSystemApp: !vm2.a,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
SettingTextCard(
|
||||
appLocalizations.noNetworkApp,
|
||||
isSelected: vm2.b == false,
|
||||
onPressed: () {
|
||||
ref.read(vpnSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith.accessControl(
|
||||
isFilterNonInternetApp: !vm2.b,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -8,10 +8,12 @@ import 'package:fl_clash/providers/config.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:fl_clash/widgets/dialog.dart';
|
||||
import 'package:fl_clash/widgets/fade_box.dart';
|
||||
import 'package:fl_clash/widgets/input.dart';
|
||||
import 'package:fl_clash/widgets/list.dart';
|
||||
import 'package:fl_clash/widgets/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class BackupAndRecovery extends ConsumerWidget {
|
||||
const BackupAndRecovery({super.key});
|
||||
@@ -134,6 +136,30 @@ class BackupAndRecovery extends ConsumerWidget {
|
||||
);
|
||||
}
|
||||
|
||||
_handleUpdateRecoveryStrategy(WidgetRef ref) async {
|
||||
final recoveryStrategy = ref.read(appSettingProvider.select(
|
||||
(state) => state.recoveryStrategy,
|
||||
));
|
||||
final res = await globalState.showCommonDialog(
|
||||
child: OptionsDialog<RecoveryStrategy>(
|
||||
title: appLocalizations.recoveryStrategy,
|
||||
options: RecoveryStrategy.values,
|
||||
textBuilder: (mode) => Intl.message(
|
||||
"recoveryStrategy_${mode.name}",
|
||||
),
|
||||
value: recoveryStrategy,
|
||||
),
|
||||
);
|
||||
if (res == null) {
|
||||
return;
|
||||
}
|
||||
ref.read(appSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
recoveryStrategy: res,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final dav = ref.watch(appDAVSettingProvider);
|
||||
@@ -256,6 +282,26 @@ class BackupAndRecovery extends ConsumerWidget {
|
||||
title: Text(appLocalizations.recovery),
|
||||
subtitle: Text(appLocalizations.localRecoveryDesc),
|
||||
),
|
||||
ListHeader(title: appLocalizations.options),
|
||||
Consumer(builder: (_, ref, __) {
|
||||
final recoveryStrategy = ref.watch(appSettingProvider.select(
|
||||
(state) => state.recoveryStrategy,
|
||||
));
|
||||
return ListItem(
|
||||
onTap: () {
|
||||
_handleUpdateRecoveryStrategy(ref);
|
||||
},
|
||||
title: Text(appLocalizations.recoveryStrategy),
|
||||
trailing: FilledButton(
|
||||
onPressed: () {
|
||||
_handleUpdateRecoveryStrategy(ref);
|
||||
},
|
||||
child: Text(
|
||||
Intl.message("recoveryStrategy_${recoveryStrategy.name}"),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -301,8 +301,11 @@ class RouteAddressItem extends ConsumerWidget {
|
||||
title: appLocalizations.routeAddress,
|
||||
widget: Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final routeAddress = ref.watch(patchClashConfigProvider
|
||||
.select((state) => state.tun.routeAddress));
|
||||
final routeAddress = ref.watch(
|
||||
patchClashConfigProvider.select(
|
||||
(state) => state.tun.routeAddress,
|
||||
),
|
||||
);
|
||||
return ListInputPage(
|
||||
title: appLocalizations.routeAddress,
|
||||
items: routeAddress,
|
||||
@@ -371,7 +374,9 @@ class NetworkListView extends ConsumerWidget {
|
||||
return;
|
||||
}
|
||||
ref.read(vpnSettingProvider.notifier).updateState(
|
||||
(state) => defaultVpnProps,
|
||||
(state) => defaultVpnProps.copyWith(
|
||||
accessControl: state.accessControl,
|
||||
),
|
||||
);
|
||||
ref.read(patchClashConfigProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
|
||||
@@ -20,12 +20,13 @@ class RequestsFragment extends ConsumerStatefulWidget {
|
||||
|
||||
class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
||||
with PageMixin {
|
||||
final GlobalKey<CacheItemExtentListViewState> _key = GlobalKey();
|
||||
final _requestsStateNotifier =
|
||||
ValueNotifier<ConnectionsState>(const ConnectionsState());
|
||||
final _requestsStateNotifier = ValueNotifier<ConnectionsState>(
|
||||
const ConnectionsState(loading: true),
|
||||
);
|
||||
List<Connection> _requests = [];
|
||||
final _cacheKey = ValueKey("requests_list");
|
||||
final _tag = CacheTag.requests;
|
||||
late ScrollController _scrollController;
|
||||
bool _isLoad = false;
|
||||
|
||||
double _currentMaxWidth = 0;
|
||||
|
||||
@@ -45,12 +46,13 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final preOffset = globalState.cacheScrollPosition[_cacheKey] ?? -1;
|
||||
final preOffset = globalState.cacheScrollPosition[_tag] ?? -1;
|
||||
_scrollController = ScrollController(
|
||||
initialScrollOffset: preOffset > 0 ? preOffset : double.maxFinite,
|
||||
);
|
||||
_requests = globalState.appState.requests.list;
|
||||
_requestsStateNotifier.value = _requestsStateNotifier.value.copyWith(
|
||||
connections: globalState.appState.requests.list,
|
||||
connections: _requests,
|
||||
);
|
||||
ref.listenManual(
|
||||
isCurrentPageProvider(
|
||||
@@ -73,7 +75,6 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
||||
updateRequestsThrottler();
|
||||
}
|
||||
},
|
||||
fireImmediately: true,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -98,14 +99,7 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
||||
final lines = (chainSize.height / baseHeight).round();
|
||||
final computerHeight =
|
||||
size.height + chainSize.height + 24 + 24 * (lines - 1);
|
||||
return computerHeight;
|
||||
}
|
||||
|
||||
_handleTryClearCache(double maxWidth) {
|
||||
if (_currentMaxWidth != maxWidth) {
|
||||
_currentMaxWidth = maxWidth;
|
||||
_key.currentState?.clearCache();
|
||||
}
|
||||
return computerHeight + 8 + 32 + globalState.measure.bodyMediumHeight;
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -133,6 +127,42 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
||||
}, duration: commonDuration);
|
||||
}
|
||||
|
||||
_preLoad() {
|
||||
if (_isLoad == true) {
|
||||
return;
|
||||
}
|
||||
_isLoad = true;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
final isMobileView = ref.read(isMobileViewProvider);
|
||||
if (isMobileView) {
|
||||
await Future.delayed(Duration(milliseconds: 300));
|
||||
}
|
||||
final parts = _requests.batch(10);
|
||||
globalState.cacheHeightMap[_tag] ??= FixedMap(
|
||||
_requests.length,
|
||||
);
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
final part = parts[i];
|
||||
await Future(
|
||||
() {
|
||||
for (final request in part) {
|
||||
globalState.cacheHeightMap[_tag]?.updateCacheValue(
|
||||
request.id,
|
||||
() => _calcCacheHeight(request),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
_requestsStateNotifier.value = _requestsStateNotifier.value.copyWith(
|
||||
loading: false,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
@@ -146,12 +176,14 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
||||
Platform.isAndroid,
|
||||
),
|
||||
);
|
||||
_handleTryClearCache(constraints.maxWidth - 40 - (value ? 60 : 0));
|
||||
_currentMaxWidth = constraints.maxWidth - 40 - (value ? 60 : 0);
|
||||
return child!;
|
||||
},
|
||||
child: TextScaleNotification(
|
||||
child: ValueListenableBuilder<ConnectionsState>(
|
||||
valueListenable: _requestsStateNotifier,
|
||||
builder: (_, state, __) {
|
||||
_preLoad();
|
||||
final connections = state.list;
|
||||
if (connections.isEmpty) {
|
||||
return NullStatus(
|
||||
@@ -174,47 +206,56 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return Align(
|
||||
final content = connections.isEmpty
|
||||
? NullStatus(
|
||||
label: appLocalizations.nullRequestsDesc,
|
||||
)
|
||||
: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ScrollToEndBox(
|
||||
controller: _scrollController,
|
||||
cacheKey: _cacheKey,
|
||||
tag: _tag,
|
||||
dataSource: connections,
|
||||
child: CommonScrollBar(
|
||||
controller: _scrollController,
|
||||
child: CacheItemExtentListView(
|
||||
key: _key,
|
||||
tag: _tag,
|
||||
reverse: true,
|
||||
shrinkWrap: true,
|
||||
physics: NextClampingScrollPhysics(),
|
||||
controller: _scrollController,
|
||||
itemExtentBuilder: (index) {
|
||||
final widget = items[index];
|
||||
if (widget.runtimeType == Divider) {
|
||||
if (index.isOdd) {
|
||||
return 0;
|
||||
}
|
||||
final measure = globalState.measure;
|
||||
final bodyMediumHeight = measure.bodyMediumHeight;
|
||||
final connection = connections[(index / 2).floor()];
|
||||
final height = _calcCacheHeight(connection);
|
||||
return height + bodyMediumHeight + 32;
|
||||
return _calcCacheHeight(
|
||||
connections[index ~/ 2]);
|
||||
},
|
||||
itemBuilder: (_, index) {
|
||||
return items[index];
|
||||
},
|
||||
itemCount: items.length,
|
||||
keyBuilder: (int index) {
|
||||
final widget = items[index];
|
||||
if (widget.runtimeType == Divider) {
|
||||
if (index.isOdd) {
|
||||
return "divider";
|
||||
}
|
||||
final connection = connections[(index / 2).floor()];
|
||||
return connection.id;
|
||||
return connections[index ~/ 2].id;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
return FadeBox(
|
||||
child: state.loading
|
||||
? Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
: content,
|
||||
);
|
||||
},
|
||||
),
|
||||
onNotification: (_) {
|
||||
globalState.cacheHeightMap[_tag]?.clear();
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -93,7 +93,7 @@ class _DashboardFragmentState extends ConsumerState<DashboardFragment>
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final dashboardState = ref.watch(dashboardStateProvider);
|
||||
final columns = max(4 * ((dashboardState.viewWidth / 350).ceil()), 8);
|
||||
final columns = max(4 * ((dashboardState.viewWidth / 320).ceil()), 8);
|
||||
return Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: SingleChildScrollView(
|
||||
@@ -103,8 +103,8 @@ class _DashboardFragmentState extends ConsumerState<DashboardFragment>
|
||||
child: SuperGrid(
|
||||
key: key,
|
||||
crossAxisCount: columns,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
crossAxisSpacing: 16.ap,
|
||||
mainAxisSpacing: 16.ap,
|
||||
children: [
|
||||
...dashboardState.dashboardWidgets
|
||||
.where(
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'dart:io';
|
||||
import 'package:fl_clash/clash/clash.dart';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/models/common.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:fl_clash/widgets/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@@ -57,39 +58,45 @@ class _MemoryInfoState extends State<MemoryInfo> {
|
||||
onPressed: () {
|
||||
clashCore.requestGc();
|
||||
},
|
||||
child: Container(
|
||||
padding: baseInfoEdgeInsets.copyWith(
|
||||
top: 0,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ValueListenableBuilder(
|
||||
SizedBox(
|
||||
height: globalState.measure.bodyMediumHeight + 2,
|
||||
child: ValueListenableBuilder(
|
||||
valueListenable: _memoryInfoStateNotifier,
|
||||
builder: (_, trafficValue, __) {
|
||||
return Padding(
|
||||
padding: baseInfoEdgeInsets.copyWith(
|
||||
bottom: 0,
|
||||
top: 12,
|
||||
),
|
||||
child: Row(
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
trafficValue.showValue,
|
||||
style:
|
||||
context.textTheme.bodyMedium?.toLight.adjustSize(1),
|
||||
style: context.textTheme.bodyMedium?.toLight
|
||||
.adjustSize(1),
|
||||
),
|
||||
SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
Text(
|
||||
trafficValue.showUnit,
|
||||
style:
|
||||
context.textTheme.bodyMedium?.toLight.adjustSize(1),
|
||||
style: context.textTheme.bodyMedium?.toLight
|
||||
.adjustSize(1),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ class _NetworkDetectionState extends ConsumerState<NetworkDetection> {
|
||||
);
|
||||
},
|
||||
icon: Icon(
|
||||
size: 16,
|
||||
size: 16.ap,
|
||||
Icons.info_outline,
|
||||
color: context.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
|
||||
@@ -17,9 +17,17 @@ class OutboundMode extends StatelessWidget {
|
||||
height: height,
|
||||
child: Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final mode =
|
||||
ref.watch(patchClashConfigProvider.select((state) => state.mode));
|
||||
return CommonCard(
|
||||
final mode = ref.watch(
|
||||
patchClashConfigProvider.select(
|
||||
(state) => state.mode,
|
||||
),
|
||||
);
|
||||
return Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
splashColor: Colors.transparent,
|
||||
highlightColor: Colors.transparent,
|
||||
hoverColor: Colors.transparent),
|
||||
child: CommonCard(
|
||||
onPressed: () {},
|
||||
info: Info(
|
||||
label: appLocalizations.outboundMode,
|
||||
@@ -33,16 +41,17 @@ class OutboundMode extends StatelessWidget {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
for (final item in Mode.values)
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child: ListItem.radio(
|
||||
dense: true,
|
||||
horizontalTitleGap: 4,
|
||||
padding: const EdgeInsets.only(
|
||||
left: 12,
|
||||
right: 16,
|
||||
padding: EdgeInsets.only(
|
||||
left: 12.ap,
|
||||
right: 16.ap,
|
||||
),
|
||||
delegate: RadioDelegate(
|
||||
value: item,
|
||||
@@ -66,9 +75,88 @@ class OutboundMode extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
));
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class OutboundModeV2 extends StatelessWidget {
|
||||
const OutboundModeV2({super.key});
|
||||
|
||||
Color _getTextColor(BuildContext context, Mode mode) {
|
||||
return switch (mode) {
|
||||
Mode.rule => context.colorScheme.onSecondaryContainer,
|
||||
Mode.global => context.colorScheme.onPrimaryContainer,
|
||||
Mode.direct => context.colorScheme.onTertiaryContainer,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final height = getWidgetHeight(0.72);
|
||||
return SizedBox(
|
||||
height: height,
|
||||
child: CommonCard(
|
||||
padding: EdgeInsets.zero,
|
||||
child: Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final mode = ref.watch(
|
||||
patchClashConfigProvider.select(
|
||||
(state) => state.mode,
|
||||
),
|
||||
);
|
||||
final thumbColor = switch (mode) {
|
||||
Mode.rule => context.colorScheme.secondaryContainer,
|
||||
Mode.global => globalState.theme.darken3PrimaryContainer,
|
||||
Mode.direct => context.colorScheme.tertiaryContainer,
|
||||
};
|
||||
return Container(
|
||||
constraints: BoxConstraints.expand(),
|
||||
child: CommonTabBar<Mode>(
|
||||
children: Map.fromEntries(
|
||||
Mode.values.map(
|
||||
(item) => MapEntry(
|
||||
item,
|
||||
Container(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(),
|
||||
height: height - 16,
|
||||
child: Text(
|
||||
Intl.message(item.name),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall
|
||||
?.adjustSize(1)
|
||||
.copyWith(
|
||||
color: item == mode
|
||||
? _getTextColor(
|
||||
context,
|
||||
item,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
groupValue: mode,
|
||||
onValueChanged: (value) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
globalState.appController.changeMode(value);
|
||||
},
|
||||
thumbColor: thumbColor,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,3 +165,87 @@ class SystemProxyButton extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class VpnButton extends StatelessWidget {
|
||||
const VpnButton({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: getWidgetHeight(1),
|
||||
child: CommonCard(
|
||||
onPressed: () {
|
||||
showSheet(
|
||||
context: context,
|
||||
builder: (_, type) {
|
||||
return AdaptiveSheetScaffold(
|
||||
type: type,
|
||||
body: generateListView(
|
||||
generateSection(
|
||||
items: [
|
||||
const VPNItem(),
|
||||
const VpnSystemProxyItem(),
|
||||
const TunStackItem(),
|
||||
],
|
||||
),
|
||||
),
|
||||
title: "VPN",
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
info: Info(
|
||||
label: "VPN",
|
||||
iconData: Icons.stacked_line_chart,
|
||||
),
|
||||
child: Container(
|
||||
padding: baseInfoEdgeInsets.copyWith(
|
||||
top: 4,
|
||||
bottom: 8,
|
||||
right: 8,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(
|
||||
flex: 1,
|
||||
child: TooltipText(
|
||||
text: Text(
|
||||
appLocalizations.options,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleSmall
|
||||
?.adjustSize(-2)
|
||||
.toLight,
|
||||
),
|
||||
),
|
||||
),
|
||||
Consumer(
|
||||
builder: (_, ref, __) {
|
||||
final enable = ref.watch(
|
||||
vpnSettingProvider.select(
|
||||
(state) => state.enable,
|
||||
),
|
||||
);
|
||||
return Switch(
|
||||
value: enable,
|
||||
onChanged: (value) {
|
||||
ref.read(vpnSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
enable: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/models/models.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/providers/providers.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -35,11 +35,15 @@ class _StartButtonState extends State<StartButton>
|
||||
}
|
||||
|
||||
handleSwitchStart() {
|
||||
if (isStart == globalState.appState.isStart) {
|
||||
isStart = !isStart;
|
||||
updateController();
|
||||
debouncer.call(
|
||||
DebounceTag.updateStatus,
|
||||
() {
|
||||
globalState.appController.updateStatus(isStart);
|
||||
}
|
||||
},
|
||||
duration: moreDuration,
|
||||
);
|
||||
}
|
||||
|
||||
updateController() {
|
||||
@@ -126,9 +130,11 @@ class _StartButtonState extends State<StartButton>
|
||||
final text = utils.getTimeText(runTime);
|
||||
return Text(
|
||||
text,
|
||||
style: Theme.of(context).textTheme.titleMedium?.toSoftBold.copyWith(
|
||||
color: context.colorScheme.onPrimaryContainer
|
||||
),
|
||||
style: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium
|
||||
?.toSoftBold
|
||||
.copyWith(color: context.colorScheme.onPrimaryContainer),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
120
lib/fragments/developer.dart
Normal file
120
lib/fragments/developer.dart
Normal file
@@ -0,0 +1,120 @@
|
||||
import 'package:fl_clash/clash/core.dart';
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/models/common.dart';
|
||||
import 'package:fl_clash/providers/config.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:fl_clash/widgets/widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../providers/app.dart';
|
||||
|
||||
class DeveloperView extends ConsumerWidget {
|
||||
const DeveloperView({super.key});
|
||||
|
||||
Widget _getDeveloperList(BuildContext context, WidgetRef ref) {
|
||||
return generateSectionV2(
|
||||
title: appLocalizations.options,
|
||||
items: [
|
||||
ListItem(
|
||||
title: Text(appLocalizations.messageTest),
|
||||
onTap: () {
|
||||
context.showNotifier(
|
||||
appLocalizations.messageTestTip,
|
||||
);
|
||||
},
|
||||
),
|
||||
ListItem(
|
||||
title: Text(appLocalizations.logsTest),
|
||||
onTap: () {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
ref.read(requestsProvider.notifier).addRequest(Connection(
|
||||
id: utils.id,
|
||||
start: DateTime.now(),
|
||||
metadata: Metadata(
|
||||
uid: i * i,
|
||||
network: utils.generateRandomString(
|
||||
maxLength: 1000,
|
||||
minLength: 20,
|
||||
),
|
||||
sourceIP: '',
|
||||
sourcePort: '',
|
||||
destinationIP: '',
|
||||
destinationPort: '',
|
||||
host: '',
|
||||
process: '',
|
||||
remoteDestination: "",
|
||||
),
|
||||
chains: ["chains"],
|
||||
));
|
||||
globalState.appController.addLog(
|
||||
Log.app(
|
||||
utils.generateRandomString(
|
||||
maxLength: 200,
|
||||
minLength: 20,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
ListItem(
|
||||
title: Text(appLocalizations.crashTest),
|
||||
onTap: () {
|
||||
clashCore.clashInterface.crash();
|
||||
},
|
||||
),
|
||||
ListItem(
|
||||
title: Text(appLocalizations.clearData),
|
||||
onTap: () async {
|
||||
await globalState.appController.handleClear();
|
||||
},
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final enable = ref.watch(
|
||||
appSettingProvider.select(
|
||||
(state) => state.developerMode,
|
||||
),
|
||||
);
|
||||
return SingleChildScrollView(
|
||||
padding: baseInfoEdgeInsets,
|
||||
child: Column(
|
||||
children: [
|
||||
CommonCard(
|
||||
type: CommonCardType.filled,
|
||||
radius: 18,
|
||||
child: ListItem.switchItem(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16,
|
||||
right: 16,
|
||||
top: 4,
|
||||
bottom: 4,
|
||||
),
|
||||
title: Text(appLocalizations.developerMode),
|
||||
delegate: SwitchDelegate(
|
||||
value: enable,
|
||||
onChanged: (value) {
|
||||
ref.read(appSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith(
|
||||
developerMode: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
_getDeveloperList(context, ref)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -11,3 +11,4 @@ export 'backup_and_recovery.dart';
|
||||
export 'resources.dart';
|
||||
export 'connection/requests.dart';
|
||||
export 'connection/connections.dart';
|
||||
export 'developer.dart';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/enum/enum.dart';
|
||||
import 'package:fl_clash/providers/providers.dart';
|
||||
@@ -16,36 +18,27 @@ class LogsFragment extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
||||
final _logsStateNotifier = ValueNotifier<LogsState>(LogsState());
|
||||
final _cacheKey = ValueKey("logs_list");
|
||||
final _logsStateNotifier = ValueNotifier<LogsState>(
|
||||
LogsState(loading: true),
|
||||
);
|
||||
late ScrollController _scrollController;
|
||||
|
||||
double _currentMaxWidth = 0;
|
||||
final GlobalKey<CacheItemExtentListViewState> _key = GlobalKey();
|
||||
final _tag = CacheTag.rules;
|
||||
bool _isLoad = false;
|
||||
|
||||
List<Log> _logs = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final preOffset = globalState.cacheScrollPosition[_cacheKey] ?? -1;
|
||||
final position = globalState.cacheScrollPosition[_tag] ?? -1;
|
||||
_scrollController = ScrollController(
|
||||
initialScrollOffset: preOffset > 0 ? preOffset : double.maxFinite,
|
||||
initialScrollOffset: position > 0 ? position : double.maxFinite,
|
||||
);
|
||||
_logs = globalState.appState.logs.list;
|
||||
_logsStateNotifier.value = _logsStateNotifier.value.copyWith(
|
||||
logs: globalState.appState.logs.list,
|
||||
);
|
||||
ref.listenManual(
|
||||
logsProvider.select((state) => state.list),
|
||||
(prev, next) {
|
||||
if (prev != next) {
|
||||
final isEquality = logListEquality.equals(prev, next);
|
||||
if (!isEquality) {
|
||||
_logs = next;
|
||||
updateLogsThrottler();
|
||||
}
|
||||
}
|
||||
},
|
||||
fireImmediately: true,
|
||||
logs: _logs,
|
||||
);
|
||||
ref.listenManual(
|
||||
isCurrentPageProvider(
|
||||
@@ -60,6 +53,18 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
||||
},
|
||||
fireImmediately: true,
|
||||
);
|
||||
ref.listenManual(
|
||||
logsProvider.select((state) => state.list),
|
||||
(prev, next) {
|
||||
if (prev != next) {
|
||||
final isEquality = logListEquality.equals(prev, next);
|
||||
if (!isEquality) {
|
||||
_logs = next;
|
||||
updateLogsThrottler();
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -94,13 +99,6 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
_handleTryClearCache(double maxWidth) {
|
||||
if (_currentMaxWidth != maxWidth) {
|
||||
_currentMaxWidth = maxWidth;
|
||||
_key.currentState?.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
_handleExport() async {
|
||||
final commonScaffoldState = context.commonScaffoldState;
|
||||
final res = await commonScaffoldState?.loadingRun<bool>(
|
||||
@@ -123,13 +121,13 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
||||
final height = globalState.measure
|
||||
.computeTextSize(
|
||||
Text(
|
||||
log.payload ?? "",
|
||||
style: globalState.appController.context.textTheme.bodyLarge,
|
||||
log.payload,
|
||||
style: context.textTheme.bodyLarge,
|
||||
),
|
||||
maxWidth: _currentMaxWidth,
|
||||
)
|
||||
.height;
|
||||
return height + bodySmallHeight + 8 + bodyMediumHeight + 40;
|
||||
return height + bodySmallHeight + 8 + bodyMediumHeight + 40 + 8;
|
||||
}
|
||||
|
||||
updateLogsThrottler() {
|
||||
@@ -142,33 +140,65 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
||||
return;
|
||||
}
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (mounted) {
|
||||
_logsStateNotifier.value = _logsStateNotifier.value.copyWith(
|
||||
logs: _logs,
|
||||
);
|
||||
}
|
||||
});
|
||||
}, duration: commonDuration);
|
||||
}
|
||||
|
||||
_preLoad() {
|
||||
if (_isLoad == true) {
|
||||
return;
|
||||
}
|
||||
_isLoad = true;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
final isMobileView = ref.read(isMobileViewProvider);
|
||||
if (isMobileView) {
|
||||
await Future.delayed(Duration(milliseconds: 300));
|
||||
}
|
||||
final parts = _logs.batch(10);
|
||||
globalState.cacheHeightMap[_tag] ??= FixedMap(
|
||||
_logs.length,
|
||||
);
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
final part = parts[i];
|
||||
await Future(
|
||||
() {
|
||||
for (final log in part) {
|
||||
globalState.cacheHeightMap[_tag]?.updateCacheValue(
|
||||
log.payload,
|
||||
() => _getItemHeight(log),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
_logsStateNotifier.value = _logsStateNotifier.value.copyWith(
|
||||
loading: false,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
_handleTryClearCache(constraints.maxWidth - 40);
|
||||
return Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: ValueListenableBuilder<LogsState>(
|
||||
_currentMaxWidth = constraints.maxWidth - 40;
|
||||
return ValueListenableBuilder<LogsState>(
|
||||
valueListenable: _logsStateNotifier,
|
||||
builder: (_, state, __) {
|
||||
_preLoad();
|
||||
final logs = state.list;
|
||||
if (logs.isEmpty) {
|
||||
return NullStatus(
|
||||
label: appLocalizations.nullLogsDesc,
|
||||
);
|
||||
}
|
||||
final items = logs
|
||||
.map<Widget>(
|
||||
(log) => LogItem(
|
||||
key: Key(log.dateTime.toString()),
|
||||
key: Key(log.dateTime),
|
||||
log: log,
|
||||
onClick: (value) {
|
||||
context.commonScaffoldState?.addKeyword(value);
|
||||
@@ -181,14 +211,20 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
return ScrollToEndBox<Log>(
|
||||
controller: _scrollController,
|
||||
cacheKey: _cacheKey,
|
||||
dataSource: logs,
|
||||
final content = logs.isEmpty
|
||||
? NullStatus(
|
||||
label: appLocalizations.nullLogsDesc,
|
||||
)
|
||||
: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: CommonScrollBar(
|
||||
controller: _scrollController,
|
||||
child: ScrollToEndBox(
|
||||
controller: _scrollController,
|
||||
tag: _tag,
|
||||
dataSource: logs,
|
||||
child: CacheItemExtentListView(
|
||||
key: _key,
|
||||
tag: _tag,
|
||||
reverse: true,
|
||||
shrinkWrap: true,
|
||||
physics: NextClampingScrollPhysics(),
|
||||
@@ -197,27 +233,30 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
||||
return items[index];
|
||||
},
|
||||
itemExtentBuilder: (index) {
|
||||
final item = items[index];
|
||||
if (item.runtimeType == Divider) {
|
||||
if (index.isOdd) {
|
||||
return 0;
|
||||
}
|
||||
final log = logs[(index / 2).floor()];
|
||||
return _getItemHeight(log);
|
||||
return _getItemHeight(logs[index ~/ 2]);
|
||||
},
|
||||
itemCount: items.length,
|
||||
keyBuilder: (int index) {
|
||||
final item = items[index];
|
||||
if (item.runtimeType == Divider) {
|
||||
if (index.isOdd) {
|
||||
return "divider";
|
||||
}
|
||||
final log = logs[(index / 2).floor()];
|
||||
return log.payload ?? "";
|
||||
return logs[index ~/ 2].payload;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
return FadeBox(
|
||||
child: state.loading
|
||||
? Center(
|
||||
child: CircularProgressIndicator(),
|
||||
)
|
||||
: content,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -242,14 +281,14 @@ class LogItem extends StatelessWidget {
|
||||
vertical: 4,
|
||||
),
|
||||
title: SelectableText(
|
||||
log.payload ?? '',
|
||||
log.payload,
|
||||
style: context.textTheme.bodyLarge,
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SelectableText(
|
||||
"${log.dateTime}",
|
||||
log.dateTime,
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
color: context.colorScheme.primary,
|
||||
),
|
||||
|
||||
@@ -104,8 +104,13 @@ class _URLFormDialogState extends State<URLFormDialog> {
|
||||
runSpacing: 16,
|
||||
children: [
|
||||
TextField(
|
||||
maxLines: 5,
|
||||
keyboardType: TextInputType.url,
|
||||
minLines: 1,
|
||||
maxLines: 5,
|
||||
onSubmitted: (_) {
|
||||
_handleAddProfileFormURL();
|
||||
},
|
||||
onEditingComplete: _handleAddProfileFormURL,
|
||||
controller: urlController,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
|
||||
@@ -214,6 +214,7 @@ class _EditProfileState extends State<EditProfile> {
|
||||
final items = [
|
||||
ListItem(
|
||||
title: TextFormField(
|
||||
textInputAction: TextInputAction.next,
|
||||
controller: labelController,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
@@ -230,6 +231,8 @@ class _EditProfileState extends State<EditProfile> {
|
||||
if (widget.profile.type == ProfileType.url) ...[
|
||||
ListItem(
|
||||
title: TextFormField(
|
||||
textInputAction: TextInputAction.next,
|
||||
keyboardType: TextInputType.url,
|
||||
controller: urlController,
|
||||
maxLines: 5,
|
||||
minLines: 1,
|
||||
@@ -258,6 +261,7 @@ class _EditProfileState extends State<EditProfile> {
|
||||
if (autoUpdate)
|
||||
ListItem(
|
||||
title: TextFormField(
|
||||
textInputAction: TextInputAction.next,
|
||||
controller: autoUpdateDurationController,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
|
||||
@@ -23,7 +23,6 @@ class OverrideProfile extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _OverrideProfileState extends State<OverrideProfile> {
|
||||
final GlobalKey<CacheItemExtentListViewState> _ruleListKey = GlobalKey();
|
||||
final _controller = ScrollController();
|
||||
double _currentMaxWidth = 0;
|
||||
|
||||
@@ -86,13 +85,6 @@ class _OverrideProfileState extends State<OverrideProfile> {
|
||||
);
|
||||
}
|
||||
|
||||
_handleTryClearCache(double maxWidth) {
|
||||
if (_currentMaxWidth != maxWidth) {
|
||||
_currentMaxWidth = maxWidth;
|
||||
_ruleListKey.currentState?.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
_buildContent() {
|
||||
return Consumer(
|
||||
builder: (_, ref, child) {
|
||||
@@ -116,7 +108,7 @@ class _OverrideProfileState extends State<OverrideProfile> {
|
||||
},
|
||||
child: LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
_handleTryClearCache(constraints.maxWidth - 104);
|
||||
_currentMaxWidth = constraints.maxWidth - 104;
|
||||
return CommonAutoHiddenScrollBar(
|
||||
controller: _controller,
|
||||
child: CustomScrollView(
|
||||
@@ -148,7 +140,6 @@ class _OverrideProfileState extends State<OverrideProfile> {
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 0),
|
||||
sliver: RuleContent(
|
||||
maxWidth: _currentMaxWidth,
|
||||
ruleListKey: _ruleListKey,
|
||||
),
|
||||
),
|
||||
SliverToBoxAdapter(
|
||||
@@ -228,7 +219,7 @@ class _OverrideProfileState extends State<OverrideProfile> {
|
||||
message: TextSpan(
|
||||
text: appLocalizations.saveTip,
|
||||
),
|
||||
confirmText: appLocalizations.tip,
|
||||
confirmText: appLocalizations.save,
|
||||
);
|
||||
if (res != true) {
|
||||
return;
|
||||
@@ -449,12 +440,10 @@ class RuleTitle extends ConsumerWidget {
|
||||
}
|
||||
|
||||
class RuleContent extends ConsumerWidget {
|
||||
final Key ruleListKey;
|
||||
final double maxWidth;
|
||||
|
||||
const RuleContent({
|
||||
super.key,
|
||||
required this.ruleListKey,
|
||||
required this.maxWidth,
|
||||
});
|
||||
|
||||
@@ -602,7 +591,7 @@ class RuleContent extends ConsumerWidget {
|
||||
);
|
||||
}
|
||||
return CacheItemExtentSliverReorderableList(
|
||||
key: ruleListKey,
|
||||
tag: CacheTag.rules,
|
||||
itemBuilder: (context, index) {
|
||||
final rule = rules[index];
|
||||
return GestureDetector(
|
||||
@@ -873,6 +862,8 @@ class _AddRuleDialogState extends State<AddRuleDialog> {
|
||||
builder: (filed) {
|
||||
return DropdownMenu(
|
||||
width: 200,
|
||||
enableFilter: false,
|
||||
enableSearch: false,
|
||||
controller: _subRuleController,
|
||||
label: Text(appLocalizations.subRule),
|
||||
menuHeight: 250,
|
||||
@@ -890,11 +881,11 @@ class _AddRuleDialogState extends State<AddRuleDialog> {
|
||||
builder: (filed) {
|
||||
return DropdownMenu(
|
||||
controller: _ruleTargetController,
|
||||
initialSelection: filed.value,
|
||||
label: Text(appLocalizations.ruleTarget),
|
||||
width: 200,
|
||||
menuHeight: 250,
|
||||
enableFilter: true,
|
||||
enableFilter: false,
|
||||
enableSearch: false,
|
||||
dropdownMenuEntries: _targetItems,
|
||||
errorText: filed.errorText,
|
||||
);
|
||||
|
||||
@@ -370,7 +370,7 @@ class ProfileItem extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
title: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:fl_clash/state.dart';
|
||||
|
||||
double get listHeaderHeight {
|
||||
final measure = globalState.measure;
|
||||
return 24 + measure.titleMediumHeight + 4 + measure.bodyMediumHeight;
|
||||
return 28 + measure.titleMediumHeight + 4 + measure.bodyMediumHeight;
|
||||
}
|
||||
|
||||
double getItemHeight(ProxyCardType proxyCardType) {
|
||||
|
||||
@@ -414,7 +414,10 @@ class _ListHeaderState extends State<ListHeader>
|
||||
return Consumer(
|
||||
builder: (_, ref, child) {
|
||||
final iconStyle = ref.watch(
|
||||
proxiesStyleSettingProvider.select((state) => state.iconStyle));
|
||||
proxiesStyleSettingProvider.select(
|
||||
(state) => state.iconStyle,
|
||||
),
|
||||
);
|
||||
final icon = ref.watch(proxiesStyleSettingProvider.select((state) {
|
||||
final iconMapEntryList = state.iconMap.entries.toList();
|
||||
final index = iconMapEntryList.indexWhere((item) {
|
||||
@@ -430,13 +433,19 @@ class _ListHeaderState extends State<ListHeader>
|
||||
return this.icon;
|
||||
}));
|
||||
return switch (iconStyle) {
|
||||
ProxiesIconStyle.standard => Container(
|
||||
height: 48,
|
||||
width: 48,
|
||||
ProxiesIconStyle.standard => LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(
|
||||
right: 16,
|
||||
),
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: Container(
|
||||
height: constraints.maxHeight,
|
||||
width: constraints.maxWidth,
|
||||
alignment: Alignment.center,
|
||||
padding: EdgeInsets.all(6.ap),
|
||||
decoration: BoxDecoration(
|
||||
color: context.colorScheme.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
@@ -444,16 +453,24 @@ class _ListHeaderState extends State<ListHeader>
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: CommonTargetIcon(
|
||||
src: icon,
|
||||
size: 32,
|
||||
size: constraints.maxHeight - 12.ap,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
ProxiesIconStyle.icon => Container(
|
||||
margin: const EdgeInsets.only(
|
||||
right: 16,
|
||||
),
|
||||
child: CommonTargetIcon(
|
||||
child: LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
return CommonTargetIcon(
|
||||
src: icon,
|
||||
size: 42,
|
||||
size: constraints.maxHeight - 8,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
ProxiesIconStyle.none => Container(),
|
||||
|
||||
@@ -78,7 +78,7 @@ class _ProxiesFragmentState extends ConsumerState<ProxiesFragment>
|
||||
return AdaptiveSheetScaffold(
|
||||
type: type,
|
||||
body: const ProxiesSetting(),
|
||||
title: appLocalizations.proxiesSetting,
|
||||
title: appLocalizations.settings,
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -123,8 +123,13 @@ class _ProxiesFragmentState extends ConsumerState<ProxiesFragment>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final proxiesType =
|
||||
ref.watch(proxiesStyleSettingProvider.select((state) => state.type));
|
||||
final proxiesType = ref.watch(
|
||||
proxiesStyleSettingProvider.select(
|
||||
(state) => state.type,
|
||||
),
|
||||
);
|
||||
|
||||
ref.watch(themeSettingProvider.select((state) => state.textScale));
|
||||
return switch (proxiesType) {
|
||||
ProxiesType.tab => ProxiesTabFragment(
|
||||
key: _proxiesTabKey,
|
||||
|
||||
@@ -147,21 +147,20 @@ class _GeoDataListItemState extends State<GeoDataListItem> {
|
||||
FutureBuilder<FileInfo>(
|
||||
future: _getGeoFileLastModified(geoItem.fileName),
|
||||
builder: (_, snapshot) {
|
||||
final height = globalState.measure.bodyMediumHeight;
|
||||
return SizedBox(
|
||||
height: 24,
|
||||
child: FadeThroughBox(
|
||||
key: Key("fade_box_${geoItem.label}"),
|
||||
height: height,
|
||||
child: snapshot.data == null
|
||||
? const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
? SizedBox(
|
||||
width: height,
|
||||
height: height,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
snapshot.data!.desc,
|
||||
),
|
||||
style: context.textTheme.bodyMedium,
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// ignore_for_file: deprecated_member_use
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'dart:ui' as ui;
|
||||
@@ -39,7 +41,20 @@ class ThemeFragment extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(child: ThemeColorsBox());
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
spacing: 24,
|
||||
children: [
|
||||
_ThemeModeItem(),
|
||||
_PrimaryColorItem(),
|
||||
_PrueBlackItem(),
|
||||
_TextScaleFactorItem(),
|
||||
const SizedBox(
|
||||
height: 64,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,11 +72,7 @@ class ItemCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
top: 16,
|
||||
),
|
||||
child: Wrap(
|
||||
return Wrap(
|
||||
runSpacing: 16,
|
||||
children: [
|
||||
InfoHeader(
|
||||
@@ -70,30 +81,6 @@ class ItemCard extends StatelessWidget {
|
||||
),
|
||||
child,
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ThemeColorsBox extends ConsumerStatefulWidget {
|
||||
const ThemeColorsBox({super.key});
|
||||
|
||||
@override
|
||||
ConsumerState<ThemeColorsBox> createState() => _ThemeColorsBoxState();
|
||||
}
|
||||
|
||||
class _ThemeColorsBoxState extends ConsumerState<ThemeColorsBox> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
_ThemeModeItem(),
|
||||
_PrimaryColorItem(),
|
||||
_PrueBlackItem(),
|
||||
const SizedBox(
|
||||
height: 64,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -296,20 +283,33 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final vm3 = ref.watch(
|
||||
final vm4 = ref.watch(
|
||||
themeSettingProvider.select(
|
||||
(state) => VM3(
|
||||
(state) => VM4(
|
||||
a: state.primaryColor,
|
||||
b: state.primaryColors,
|
||||
c: state.schemeVariant,
|
||||
d: state.primaryColor == defaultPrimaryColor &&
|
||||
intListEquality.equals(state.primaryColors, defaultPrimaryColors),
|
||||
),
|
||||
),
|
||||
);
|
||||
final primaryColor = vm3.a;
|
||||
final primaryColors = [null, ...vm3.b];
|
||||
final schemeVariant = vm3.c;
|
||||
final primaryColor = vm4.a;
|
||||
final primaryColors = [null, ...vm4.b];
|
||||
final schemeVariant = vm4.c;
|
||||
final isEquals = vm4.d;
|
||||
|
||||
return ItemCard(
|
||||
return CommonPopScope(
|
||||
onPop: () {
|
||||
if (_removablePrimaryColor != null) {
|
||||
setState(() {
|
||||
_removablePrimaryColor = null;
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
child: ItemCard(
|
||||
info: Info(
|
||||
label: appLocalizations.themeColor,
|
||||
iconData: Icons.palette,
|
||||
@@ -324,8 +324,8 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
|
||||
onPressed: _handleChangeSchemeVariant,
|
||||
child: Text(Intl.message("${schemeVariant.name}Scheme")),
|
||||
),
|
||||
_removablePrimaryColor != null
|
||||
? FilledButton(
|
||||
if (_removablePrimaryColor != null)
|
||||
FilledButton(
|
||||
style: ButtonStyle(
|
||||
visualDensity: VisualDensity.compact,
|
||||
),
|
||||
@@ -335,8 +335,9 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
|
||||
});
|
||||
},
|
||||
child: Text(appLocalizations.cancel),
|
||||
)
|
||||
: IconButton.filledTonal(
|
||||
),
|
||||
if (_removablePrimaryColor == null && !isEquals)
|
||||
IconButton.filledTonal(
|
||||
iconSize: 20,
|
||||
padding: EdgeInsets.all(4),
|
||||
visualDensity: VisualDensity.compact,
|
||||
@@ -347,10 +348,8 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
|
||||
space: 8,
|
||||
),
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(
|
||||
left: 16,
|
||||
right: 16,
|
||||
bottom: 16,
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
),
|
||||
child: LayoutBuilder(
|
||||
builder: (_, constraints) {
|
||||
@@ -375,6 +374,9 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
|
||||
isSelected: color == primaryColor,
|
||||
primaryColor: color != null ? Color(color) : null,
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_removablePrimaryColor = null;
|
||||
});
|
||||
ref
|
||||
.read(themeSettingProvider.notifier)
|
||||
.updateState(
|
||||
@@ -429,6 +431,7 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -438,11 +441,12 @@ class _PrueBlackItem extends ConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final prueBlack =
|
||||
ref.watch(themeSettingProvider.select((state) => state.pureBlack));
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: ListItem.switchItem(
|
||||
final prueBlack = ref.watch(
|
||||
themeSettingProvider.select(
|
||||
(state) => state.pureBlack,
|
||||
),
|
||||
);
|
||||
return ListItem.switchItem(
|
||||
leading: Icon(
|
||||
Icons.contrast,
|
||||
),
|
||||
@@ -463,8 +467,92 @@ class _PrueBlackItem extends ConsumerWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _TextScaleFactorItem extends ConsumerWidget {
|
||||
const _TextScaleFactorItem();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final textScale = ref.watch(
|
||||
themeSettingProvider.select(
|
||||
(state) => state.textScale,
|
||||
),
|
||||
);
|
||||
final String process = "${((textScale.scale * 100) as double).round()}%";
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(bottom: 8),
|
||||
child: ListItem.switchItem(
|
||||
leading: Icon(
|
||||
Icons.text_fields,
|
||||
),
|
||||
horizontalTitleGap: 12,
|
||||
title: Text(
|
||||
appLocalizations.textScale,
|
||||
style: Theme.of(context).textTheme.titleSmall?.copyWith(
|
||||
color: context.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
delegate: SwitchDelegate(
|
||||
value: textScale.enable,
|
||||
onChanged: (value) {
|
||||
ref.read(themeSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith.textScale(
|
||||
enable: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
spacing: 32,
|
||||
children: [
|
||||
Expanded(
|
||||
child: DisabledMask(
|
||||
status: !textScale.enable,
|
||||
child: ActivateBox(
|
||||
active: textScale.enable,
|
||||
child: SliderTheme(
|
||||
data: _SliderDefaultsM3(context),
|
||||
child: Slider(
|
||||
padding: EdgeInsets.zero,
|
||||
min: minTextScale,
|
||||
max: maxTextScale,
|
||||
value: textScale.scale,
|
||||
onChanged: (value) {
|
||||
ref.read(themeSettingProvider.notifier).updateState(
|
||||
(state) => state.copyWith.textScale(
|
||||
scale: value,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 4),
|
||||
child: Text(
|
||||
process,
|
||||
style: context.textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -530,3 +618,112 @@ class _PaletteDialogState extends State<_PaletteDialog> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SliderDefaultsM3 extends SliderThemeData {
|
||||
_SliderDefaultsM3(this.context) : super(trackHeight: 16.0);
|
||||
|
||||
final BuildContext context;
|
||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||
|
||||
@override
|
||||
Color? get activeTrackColor => _colors.primary;
|
||||
|
||||
@override
|
||||
Color? get inactiveTrackColor => _colors.secondaryContainer;
|
||||
|
||||
@override
|
||||
Color? get secondaryActiveTrackColor => _colors.primary.withOpacity(0.54);
|
||||
|
||||
@override
|
||||
Color? get disabledActiveTrackColor => _colors.onSurface.withOpacity(0.38);
|
||||
|
||||
@override
|
||||
Color? get disabledInactiveTrackColor => _colors.onSurface.withOpacity(0.12);
|
||||
|
||||
@override
|
||||
Color? get disabledSecondaryActiveTrackColor =>
|
||||
_colors.onSurface.withOpacity(0.38);
|
||||
|
||||
@override
|
||||
Color? get activeTickMarkColor => _colors.onPrimary.withOpacity(1.0);
|
||||
|
||||
@override
|
||||
Color? get inactiveTickMarkColor =>
|
||||
_colors.onSecondaryContainer.withOpacity(1.0);
|
||||
|
||||
@override
|
||||
Color? get disabledActiveTickMarkColor => _colors.onInverseSurface;
|
||||
|
||||
@override
|
||||
Color? get disabledInactiveTickMarkColor => _colors.onSurface;
|
||||
|
||||
@override
|
||||
Color? get thumbColor => _colors.primary;
|
||||
|
||||
@override
|
||||
Color? get disabledThumbColor => _colors.onSurface.withOpacity(0.38);
|
||||
|
||||
@override
|
||||
Color? get overlayColor =>
|
||||
WidgetStateColor.resolveWith((Set<WidgetState> states) {
|
||||
if (states.contains(WidgetState.dragged)) {
|
||||
return _colors.primary.withOpacity(0.1);
|
||||
}
|
||||
if (states.contains(WidgetState.hovered)) {
|
||||
return _colors.primary.withOpacity(0.08);
|
||||
}
|
||||
if (states.contains(WidgetState.focused)) {
|
||||
return _colors.primary.withOpacity(0.1);
|
||||
}
|
||||
|
||||
return Colors.transparent;
|
||||
});
|
||||
|
||||
@override
|
||||
TextStyle? get valueIndicatorTextStyle =>
|
||||
Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||
color: _colors.onInverseSurface,
|
||||
);
|
||||
|
||||
@override
|
||||
Color? get valueIndicatorColor => _colors.inverseSurface;
|
||||
|
||||
@override
|
||||
SliderComponentShape? get valueIndicatorShape =>
|
||||
const RoundedRectSliderValueIndicatorShape();
|
||||
|
||||
@override
|
||||
SliderComponentShape? get thumbShape => const HandleThumbShape();
|
||||
|
||||
@override
|
||||
SliderTrackShape? get trackShape => const GappedSliderTrackShape();
|
||||
|
||||
@override
|
||||
SliderComponentShape? get overlayShape => const RoundSliderOverlayShape();
|
||||
|
||||
@override
|
||||
SliderTickMarkShape? get tickMarkShape =>
|
||||
const RoundSliderTickMarkShape(tickMarkRadius: 4.0 / 2);
|
||||
|
||||
@override
|
||||
WidgetStateProperty<Size?>? get thumbSize {
|
||||
return WidgetStateProperty.resolveWith((Set<WidgetState> states) {
|
||||
if (states.contains(WidgetState.disabled)) {
|
||||
return const Size(4.0, 44.0);
|
||||
}
|
||||
if (states.contains(WidgetState.hovered)) {
|
||||
return const Size(4.0, 44.0);
|
||||
}
|
||||
if (states.contains(WidgetState.focused)) {
|
||||
return const Size(2.0, 44.0);
|
||||
}
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return const Size(2.0, 44.0);
|
||||
}
|
||||
return const Size(4.0, 44.0);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
double? get trackGap => 6.0;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'backup_and_recovery.dart';
|
||||
import 'developer.dart';
|
||||
import 'theme.dart';
|
||||
import 'package:path/path.dart' show dirname, join;
|
||||
|
||||
@@ -54,11 +55,12 @@ class _ToolboxFragmentState extends ConsumerState<ToolsFragment> {
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _getOtherList() {
|
||||
List<Widget> _getOtherList(bool enableDeveloperMode) {
|
||||
return generateSection(
|
||||
title: appLocalizations.other,
|
||||
items: [
|
||||
_DisclaimerItem(),
|
||||
if (enableDeveloperMode) _DeveloperItem(),
|
||||
_InfoItem(),
|
||||
],
|
||||
);
|
||||
@@ -82,7 +84,11 @@ class _ToolboxFragmentState extends ConsumerState<ToolsFragment> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ref.watch(appSettingProvider.select((state) => state.locale));
|
||||
final vm2 = ref.watch(
|
||||
appSettingProvider.select(
|
||||
(state) => VM2(a: state.locale, b: state.developerMode),
|
||||
),
|
||||
);
|
||||
final items = [
|
||||
Consumer(
|
||||
builder: (_, ref, __) {
|
||||
@@ -99,7 +105,7 @@ class _ToolboxFragmentState extends ConsumerState<ToolsFragment> {
|
||||
},
|
||||
),
|
||||
..._getSettingList(),
|
||||
..._getOtherList(),
|
||||
..._getOtherList(vm2.b),
|
||||
];
|
||||
return ListView.builder(
|
||||
itemCount: items.length,
|
||||
@@ -297,3 +303,19 @@ class _InfoItem extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DeveloperItem extends StatelessWidget {
|
||||
const _DeveloperItem();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListItem.open(
|
||||
leading: const Icon(Icons.developer_board),
|
||||
title: Text(appLocalizations.developerMode),
|
||||
delegate: OpenDelegate(
|
||||
title: appLocalizations.developerMode,
|
||||
widget: const DeveloperView(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +146,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"The current application is already the latest version",
|
||||
),
|
||||
"checking": MessageLookupByLibrary.simpleMessage("Checking..."),
|
||||
"clearData": MessageLookupByLibrary.simpleMessage("Clear Data"),
|
||||
"clipboardExport": MessageLookupByLibrary.simpleMessage("Export clipboard"),
|
||||
"clipboardImport": MessageLookupByLibrary.simpleMessage("Clipboard import"),
|
||||
"colorExists": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -163,6 +164,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"View current connections data",
|
||||
),
|
||||
"connectivity": MessageLookupByLibrary.simpleMessage("Connectivity:"),
|
||||
"contactMe": MessageLookupByLibrary.simpleMessage("Contact me"),
|
||||
"content": MessageLookupByLibrary.simpleMessage("Content"),
|
||||
"contentEmptyTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Content cannot be empty",
|
||||
@@ -177,6 +179,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"core": MessageLookupByLibrary.simpleMessage("Core"),
|
||||
"coreInfo": MessageLookupByLibrary.simpleMessage("Core info"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("Country"),
|
||||
"crashTest": MessageLookupByLibrary.simpleMessage("Crash test"),
|
||||
"create": MessageLookupByLibrary.simpleMessage("Create"),
|
||||
"cut": MessageLookupByLibrary.simpleMessage("Cut"),
|
||||
"dark": MessageLookupByLibrary.simpleMessage("Dark"),
|
||||
@@ -208,6 +211,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"detectionTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Relying on third-party api is for reference only",
|
||||
),
|
||||
"developerMode": MessageLookupByLibrary.simpleMessage("Developer mode"),
|
||||
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Developer mode is enabled.",
|
||||
),
|
||||
"direct": MessageLookupByLibrary.simpleMessage("Direct"),
|
||||
"disclaimer": MessageLookupByLibrary.simpleMessage("Disclaimer"),
|
||||
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -320,6 +327,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"intelligentSelected": MessageLookupByLibrary.simpleMessage(
|
||||
"Intelligent selection",
|
||||
),
|
||||
"internet": MessageLookupByLibrary.simpleMessage("Internet"),
|
||||
"intranetIP": MessageLookupByLibrary.simpleMessage("Intranet IP"),
|
||||
"ipcidr": MessageLookupByLibrary.simpleMessage("Ipcidr"),
|
||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -356,12 +364,17 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
),
|
||||
"logs": MessageLookupByLibrary.simpleMessage("Logs"),
|
||||
"logsDesc": MessageLookupByLibrary.simpleMessage("Log capture records"),
|
||||
"logsTest": MessageLookupByLibrary.simpleMessage("Logs test"),
|
||||
"loopback": MessageLookupByLibrary.simpleMessage("Loopback unlock tool"),
|
||||
"loopbackDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Used for UWP loopback unlocking",
|
||||
),
|
||||
"loose": MessageLookupByLibrary.simpleMessage("Loose"),
|
||||
"memoryInfo": MessageLookupByLibrary.simpleMessage("Memory info"),
|
||||
"messageTest": MessageLookupByLibrary.simpleMessage("Message test"),
|
||||
"messageTestTip": MessageLookupByLibrary.simpleMessage(
|
||||
"This is a message.",
|
||||
),
|
||||
"min": MessageLookupByLibrary.simpleMessage("Min"),
|
||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("Minimize on exit"),
|
||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -399,6 +412,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"noInfo": MessageLookupByLibrary.simpleMessage("No info"),
|
||||
"noMoreInfoDesc": MessageLookupByLibrary.simpleMessage("No more info"),
|
||||
"noNetwork": MessageLookupByLibrary.simpleMessage("No network"),
|
||||
"noNetworkApp": MessageLookupByLibrary.simpleMessage("No network APP"),
|
||||
"noProxy": MessageLookupByLibrary.simpleMessage("No proxy"),
|
||||
"noProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Please create a profile or add a valid profile",
|
||||
@@ -526,6 +540,15 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"recoveryProfiles": MessageLookupByLibrary.simpleMessage(
|
||||
"Only recovery profiles",
|
||||
),
|
||||
"recoveryStrategy": MessageLookupByLibrary.simpleMessage(
|
||||
"Recovery strategy",
|
||||
),
|
||||
"recoveryStrategy_compatible": MessageLookupByLibrary.simpleMessage(
|
||||
"Compatible",
|
||||
),
|
||||
"recoveryStrategy_override": MessageLookupByLibrary.simpleMessage(
|
||||
"Override",
|
||||
),
|
||||
"recoverySuccess": MessageLookupByLibrary.simpleMessage("Recovery success"),
|
||||
"redo": MessageLookupByLibrary.simpleMessage("redo"),
|
||||
"regExp": MessageLookupByLibrary.simpleMessage("RegExp"),
|
||||
@@ -612,6 +635,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"submit": MessageLookupByLibrary.simpleMessage("Submit"),
|
||||
"sync": MessageLookupByLibrary.simpleMessage("Sync"),
|
||||
"system": MessageLookupByLibrary.simpleMessage("System"),
|
||||
"systemApp": MessageLookupByLibrary.simpleMessage("System APP"),
|
||||
"systemFont": MessageLookupByLibrary.simpleMessage("System font"),
|
||||
"systemProxy": MessageLookupByLibrary.simpleMessage("System proxy"),
|
||||
"systemProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -627,6 +651,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Enabling it will allow TCP concurrency",
|
||||
),
|
||||
"testUrl": MessageLookupByLibrary.simpleMessage("Test url"),
|
||||
"textScale": MessageLookupByLibrary.simpleMessage("Text Scaling"),
|
||||
"theme": MessageLookupByLibrary.simpleMessage("Theme"),
|
||||
"themeColor": MessageLookupByLibrary.simpleMessage("Theme color"),
|
||||
"themeDesc": MessageLookupByLibrary.simpleMessage(
|
||||
|
||||
@@ -104,6 +104,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"checkUpdate": MessageLookupByLibrary.simpleMessage("更新を確認"),
|
||||
"checkUpdateError": MessageLookupByLibrary.simpleMessage("アプリは最新版です"),
|
||||
"checking": MessageLookupByLibrary.simpleMessage("確認中..."),
|
||||
"clearData": MessageLookupByLibrary.simpleMessage("データを消去"),
|
||||
"clipboardExport": MessageLookupByLibrary.simpleMessage("クリップボードにエクスポート"),
|
||||
"clipboardImport": MessageLookupByLibrary.simpleMessage("クリップボードからインポート"),
|
||||
"colorExists": MessageLookupByLibrary.simpleMessage("この色は既に存在します"),
|
||||
@@ -117,6 +118,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"connections": MessageLookupByLibrary.simpleMessage("接続"),
|
||||
"connectionsDesc": MessageLookupByLibrary.simpleMessage("現在の接続データを表示"),
|
||||
"connectivity": MessageLookupByLibrary.simpleMessage("接続性:"),
|
||||
"contactMe": MessageLookupByLibrary.simpleMessage("連絡する"),
|
||||
"content": MessageLookupByLibrary.simpleMessage("内容"),
|
||||
"contentEmptyTip": MessageLookupByLibrary.simpleMessage("内容は必須です"),
|
||||
"contentScheme": MessageLookupByLibrary.simpleMessage("コンテンツテーマ"),
|
||||
@@ -127,6 +129,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"core": MessageLookupByLibrary.simpleMessage("コア"),
|
||||
"coreInfo": MessageLookupByLibrary.simpleMessage("コア情報"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("国"),
|
||||
"crashTest": MessageLookupByLibrary.simpleMessage("クラッシュテスト"),
|
||||
"create": MessageLookupByLibrary.simpleMessage("作成"),
|
||||
"cut": MessageLookupByLibrary.simpleMessage("切り取り"),
|
||||
"dark": MessageLookupByLibrary.simpleMessage("ダーク"),
|
||||
@@ -150,6 +153,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"ClashMetaベースのマルチプラットフォームプロキシクライアント。シンプルで使いやすく、オープンソースで広告なし。",
|
||||
),
|
||||
"detectionTip": MessageLookupByLibrary.simpleMessage("サードパーティAPIに依存(参考値)"),
|
||||
"developerMode": MessageLookupByLibrary.simpleMessage("デベロッパーモード"),
|
||||
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage(
|
||||
"デベロッパーモードが有効になりました。",
|
||||
),
|
||||
"direct": MessageLookupByLibrary.simpleMessage("ダイレクト"),
|
||||
"disclaimer": MessageLookupByLibrary.simpleMessage("免責事項"),
|
||||
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -230,6 +237,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"init": MessageLookupByLibrary.simpleMessage("初期化"),
|
||||
"inputCorrectHotkey": MessageLookupByLibrary.simpleMessage("正しいホットキーを入力"),
|
||||
"intelligentSelected": MessageLookupByLibrary.simpleMessage("インテリジェント選択"),
|
||||
"internet": MessageLookupByLibrary.simpleMessage("インターネット"),
|
||||
"intranetIP": MessageLookupByLibrary.simpleMessage("イントラネットIP"),
|
||||
"ipcidr": MessageLookupByLibrary.simpleMessage("IPCIDR"),
|
||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage("有効化するとIPv6トラフィックを受信可能"),
|
||||
@@ -254,10 +262,13 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"logcatDesc": MessageLookupByLibrary.simpleMessage("無効化するとログエントリを非表示"),
|
||||
"logs": MessageLookupByLibrary.simpleMessage("ログ"),
|
||||
"logsDesc": MessageLookupByLibrary.simpleMessage("ログキャプチャ記録"),
|
||||
"logsTest": MessageLookupByLibrary.simpleMessage("ログテスト"),
|
||||
"loopback": MessageLookupByLibrary.simpleMessage("ループバック解除ツール"),
|
||||
"loopbackDesc": MessageLookupByLibrary.simpleMessage("UWPループバック解除用"),
|
||||
"loose": MessageLookupByLibrary.simpleMessage("疎"),
|
||||
"memoryInfo": MessageLookupByLibrary.simpleMessage("メモリ情報"),
|
||||
"messageTest": MessageLookupByLibrary.simpleMessage("メッセージテスト"),
|
||||
"messageTestTip": MessageLookupByLibrary.simpleMessage("これはメッセージです。"),
|
||||
"min": MessageLookupByLibrary.simpleMessage("最小化"),
|
||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("終了時に最小化"),
|
||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -287,6 +298,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"noInfo": MessageLookupByLibrary.simpleMessage("情報なし"),
|
||||
"noMoreInfoDesc": MessageLookupByLibrary.simpleMessage("追加情報なし"),
|
||||
"noNetwork": MessageLookupByLibrary.simpleMessage("ネットワークなし"),
|
||||
"noNetworkApp": MessageLookupByLibrary.simpleMessage("ネットワークなしアプリ"),
|
||||
"noProxy": MessageLookupByLibrary.simpleMessage("プロキシなし"),
|
||||
"noProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"プロファイルを作成するか、有効なプロファイルを追加してください",
|
||||
@@ -384,6 +396,11 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"recovery": MessageLookupByLibrary.simpleMessage("復元"),
|
||||
"recoveryAll": MessageLookupByLibrary.simpleMessage("全データ復元"),
|
||||
"recoveryProfiles": MessageLookupByLibrary.simpleMessage("プロファイルのみ復元"),
|
||||
"recoveryStrategy": MessageLookupByLibrary.simpleMessage("リカバリー戦略"),
|
||||
"recoveryStrategy_compatible": MessageLookupByLibrary.simpleMessage("互換性"),
|
||||
"recoveryStrategy_override": MessageLookupByLibrary.simpleMessage(
|
||||
"オーバーライド",
|
||||
),
|
||||
"recoverySuccess": MessageLookupByLibrary.simpleMessage("復元成功"),
|
||||
"redo": MessageLookupByLibrary.simpleMessage("やり直す"),
|
||||
"regExp": MessageLookupByLibrary.simpleMessage("正規表現"),
|
||||
@@ -452,6 +469,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"submit": MessageLookupByLibrary.simpleMessage("送信"),
|
||||
"sync": MessageLookupByLibrary.simpleMessage("同期"),
|
||||
"system": MessageLookupByLibrary.simpleMessage("システム"),
|
||||
"systemApp": MessageLookupByLibrary.simpleMessage("システムアプリ"),
|
||||
"systemFont": MessageLookupByLibrary.simpleMessage("システムフォント"),
|
||||
"systemProxy": MessageLookupByLibrary.simpleMessage("システムプロキシ"),
|
||||
"systemProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -463,6 +481,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP並列処理"),
|
||||
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("TCP並列処理を許可"),
|
||||
"testUrl": MessageLookupByLibrary.simpleMessage("URLテスト"),
|
||||
"textScale": MessageLookupByLibrary.simpleMessage("テキストスケーリング"),
|
||||
"theme": MessageLookupByLibrary.simpleMessage("テーマ"),
|
||||
"themeColor": MessageLookupByLibrary.simpleMessage("テーマカラー"),
|
||||
"themeDesc": MessageLookupByLibrary.simpleMessage("ダークモードの設定、色の調整"),
|
||||
|
||||
@@ -148,6 +148,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Текущее приложение уже является последней версией",
|
||||
),
|
||||
"checking": MessageLookupByLibrary.simpleMessage("Проверка..."),
|
||||
"clearData": MessageLookupByLibrary.simpleMessage("Очистить данные"),
|
||||
"clipboardExport": MessageLookupByLibrary.simpleMessage(
|
||||
"Экспорт в буфер обмена",
|
||||
),
|
||||
@@ -169,6 +170,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Просмотр текущих данных о соединениях",
|
||||
),
|
||||
"connectivity": MessageLookupByLibrary.simpleMessage("Связь:"),
|
||||
"contactMe": MessageLookupByLibrary.simpleMessage("Свяжитесь со мной"),
|
||||
"content": MessageLookupByLibrary.simpleMessage("Содержание"),
|
||||
"contentEmptyTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Содержание не может быть пустым",
|
||||
@@ -183,6 +185,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"core": MessageLookupByLibrary.simpleMessage("Ядро"),
|
||||
"coreInfo": MessageLookupByLibrary.simpleMessage("Информация о ядре"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||
"crashTest": MessageLookupByLibrary.simpleMessage("Тест на сбои"),
|
||||
"create": MessageLookupByLibrary.simpleMessage("Создать"),
|
||||
"cut": MessageLookupByLibrary.simpleMessage("Вырезать"),
|
||||
"dark": MessageLookupByLibrary.simpleMessage("Темный"),
|
||||
@@ -216,6 +219,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"detectionTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Опирается на сторонний API, только для справки",
|
||||
),
|
||||
"developerMode": MessageLookupByLibrary.simpleMessage("Режим разработчика"),
|
||||
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage(
|
||||
"Режим разработчика активирован.",
|
||||
),
|
||||
"direct": MessageLookupByLibrary.simpleMessage("Прямой"),
|
||||
"disclaimer": MessageLookupByLibrary.simpleMessage(
|
||||
"Отказ от ответственности",
|
||||
@@ -342,6 +349,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"intelligentSelected": MessageLookupByLibrary.simpleMessage(
|
||||
"Интеллектуальный выбор",
|
||||
),
|
||||
"internet": MessageLookupByLibrary.simpleMessage("Интернет"),
|
||||
"intranetIP": MessageLookupByLibrary.simpleMessage("Внутренний IP"),
|
||||
"ipcidr": MessageLookupByLibrary.simpleMessage("IPCIDR"),
|
||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -378,6 +386,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
),
|
||||
"logs": MessageLookupByLibrary.simpleMessage("Логи"),
|
||||
"logsDesc": MessageLookupByLibrary.simpleMessage("Записи захвата логов"),
|
||||
"logsTest": MessageLookupByLibrary.simpleMessage("Тест журналов"),
|
||||
"loopback": MessageLookupByLibrary.simpleMessage(
|
||||
"Инструмент разблокировки Loopback",
|
||||
),
|
||||
@@ -386,6 +395,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
),
|
||||
"loose": MessageLookupByLibrary.simpleMessage("Свободный"),
|
||||
"memoryInfo": MessageLookupByLibrary.simpleMessage("Информация о памяти"),
|
||||
"messageTest": MessageLookupByLibrary.simpleMessage(
|
||||
"Тестирование сообщения",
|
||||
),
|
||||
"messageTestTip": MessageLookupByLibrary.simpleMessage("Это сообщение."),
|
||||
"min": MessageLookupByLibrary.simpleMessage("Мин"),
|
||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage(
|
||||
"Свернуть при выходе",
|
||||
@@ -427,6 +440,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Нет дополнительной информации",
|
||||
),
|
||||
"noNetwork": MessageLookupByLibrary.simpleMessage("Нет сети"),
|
||||
"noNetworkApp": MessageLookupByLibrary.simpleMessage("Приложение без сети"),
|
||||
"noProxy": MessageLookupByLibrary.simpleMessage("Нет прокси"),
|
||||
"noProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
"Пожалуйста, создайте профиль или добавьте действительный профиль",
|
||||
@@ -560,6 +574,15 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"recoveryProfiles": MessageLookupByLibrary.simpleMessage(
|
||||
"Только восстановление профилей",
|
||||
),
|
||||
"recoveryStrategy": MessageLookupByLibrary.simpleMessage(
|
||||
"Стратегия восстановления",
|
||||
),
|
||||
"recoveryStrategy_compatible": MessageLookupByLibrary.simpleMessage(
|
||||
"Совместимый",
|
||||
),
|
||||
"recoveryStrategy_override": MessageLookupByLibrary.simpleMessage(
|
||||
"Переопределение",
|
||||
),
|
||||
"recoverySuccess": MessageLookupByLibrary.simpleMessage(
|
||||
"Восстановление успешно",
|
||||
),
|
||||
@@ -650,6 +673,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"submit": MessageLookupByLibrary.simpleMessage("Отправить"),
|
||||
"sync": MessageLookupByLibrary.simpleMessage("Синхронизация"),
|
||||
"system": MessageLookupByLibrary.simpleMessage("Система"),
|
||||
"systemApp": MessageLookupByLibrary.simpleMessage("Системное приложение"),
|
||||
"systemFont": MessageLookupByLibrary.simpleMessage("Системный шрифт"),
|
||||
"systemProxy": MessageLookupByLibrary.simpleMessage("Системный прокси"),
|
||||
"systemProxyDesc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -665,6 +689,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"Включение позволит использовать параллелизм TCP",
|
||||
),
|
||||
"testUrl": MessageLookupByLibrary.simpleMessage("Тест URL"),
|
||||
"textScale": MessageLookupByLibrary.simpleMessage("Масштабирование текста"),
|
||||
"theme": MessageLookupByLibrary.simpleMessage("Тема"),
|
||||
"themeColor": MessageLookupByLibrary.simpleMessage("Цвет темы"),
|
||||
"themeDesc": MessageLookupByLibrary.simpleMessage(
|
||||
|
||||
@@ -94,6 +94,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"checkUpdate": MessageLookupByLibrary.simpleMessage("检查更新"),
|
||||
"checkUpdateError": MessageLookupByLibrary.simpleMessage("当前应用已经是最新版了"),
|
||||
"checking": MessageLookupByLibrary.simpleMessage("检测中..."),
|
||||
"clearData": MessageLookupByLibrary.simpleMessage("清除数据"),
|
||||
"clipboardExport": MessageLookupByLibrary.simpleMessage("导出剪贴板"),
|
||||
"clipboardImport": MessageLookupByLibrary.simpleMessage("剪贴板导入"),
|
||||
"colorExists": MessageLookupByLibrary.simpleMessage("该颜色已存在"),
|
||||
@@ -107,6 +108,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"connections": MessageLookupByLibrary.simpleMessage("连接"),
|
||||
"connectionsDesc": MessageLookupByLibrary.simpleMessage("查看当前连接数据"),
|
||||
"connectivity": MessageLookupByLibrary.simpleMessage("连通性:"),
|
||||
"contactMe": MessageLookupByLibrary.simpleMessage("联系我"),
|
||||
"content": MessageLookupByLibrary.simpleMessage("内容"),
|
||||
"contentEmptyTip": MessageLookupByLibrary.simpleMessage("内容不能为空"),
|
||||
"contentScheme": MessageLookupByLibrary.simpleMessage("内容主题"),
|
||||
@@ -117,6 +119,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"core": MessageLookupByLibrary.simpleMessage("内核"),
|
||||
"coreInfo": MessageLookupByLibrary.simpleMessage("内核信息"),
|
||||
"country": MessageLookupByLibrary.simpleMessage("区域"),
|
||||
"crashTest": MessageLookupByLibrary.simpleMessage("崩溃测试"),
|
||||
"create": MessageLookupByLibrary.simpleMessage("创建"),
|
||||
"cut": MessageLookupByLibrary.simpleMessage("剪切"),
|
||||
"dark": MessageLookupByLibrary.simpleMessage("深色"),
|
||||
@@ -136,6 +139,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"基于ClashMeta的多平台代理客户端,简单易用,开源无广告。",
|
||||
),
|
||||
"detectionTip": MessageLookupByLibrary.simpleMessage("依赖第三方api,仅供参考"),
|
||||
"developerMode": MessageLookupByLibrary.simpleMessage("开发者模式"),
|
||||
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage("开发者模式已启用。"),
|
||||
"direct": MessageLookupByLibrary.simpleMessage("直连"),
|
||||
"disclaimer": MessageLookupByLibrary.simpleMessage("免责声明"),
|
||||
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
||||
@@ -206,6 +211,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"init": MessageLookupByLibrary.simpleMessage("初始化"),
|
||||
"inputCorrectHotkey": MessageLookupByLibrary.simpleMessage("请输入正确的快捷键"),
|
||||
"intelligentSelected": MessageLookupByLibrary.simpleMessage("智能选择"),
|
||||
"internet": MessageLookupByLibrary.simpleMessage("互联网"),
|
||||
"intranetIP": MessageLookupByLibrary.simpleMessage("内网 IP"),
|
||||
"ipcidr": MessageLookupByLibrary.simpleMessage("IP/掩码"),
|
||||
"ipv6Desc": MessageLookupByLibrary.simpleMessage("开启后将可以接收IPv6流量"),
|
||||
@@ -228,10 +234,13 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"logcatDesc": MessageLookupByLibrary.simpleMessage("禁用将会隐藏日志入口"),
|
||||
"logs": MessageLookupByLibrary.simpleMessage("日志"),
|
||||
"logsDesc": MessageLookupByLibrary.simpleMessage("日志捕获记录"),
|
||||
"logsTest": MessageLookupByLibrary.simpleMessage("日志测试"),
|
||||
"loopback": MessageLookupByLibrary.simpleMessage("回环解锁工具"),
|
||||
"loopbackDesc": MessageLookupByLibrary.simpleMessage("用于UWP回环解锁"),
|
||||
"loose": MessageLookupByLibrary.simpleMessage("宽松"),
|
||||
"memoryInfo": MessageLookupByLibrary.simpleMessage("内存信息"),
|
||||
"messageTest": MessageLookupByLibrary.simpleMessage("消息测试"),
|
||||
"messageTestTip": MessageLookupByLibrary.simpleMessage("这是一条消息。"),
|
||||
"min": MessageLookupByLibrary.simpleMessage("最小"),
|
||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("退出时最小化"),
|
||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage("修改系统默认退出事件"),
|
||||
@@ -257,6 +266,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"noInfo": MessageLookupByLibrary.simpleMessage("暂无信息"),
|
||||
"noMoreInfoDesc": MessageLookupByLibrary.simpleMessage("暂无更多信息"),
|
||||
"noNetwork": MessageLookupByLibrary.simpleMessage("无网络"),
|
||||
"noNetworkApp": MessageLookupByLibrary.simpleMessage("无网络应用"),
|
||||
"noProxy": MessageLookupByLibrary.simpleMessage("暂无代理"),
|
||||
"noProxyDesc": MessageLookupByLibrary.simpleMessage("请创建配置文件或者添加有效配置文件"),
|
||||
"noResolve": MessageLookupByLibrary.simpleMessage("不解析IP"),
|
||||
@@ -338,6 +348,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"recovery": MessageLookupByLibrary.simpleMessage("恢复"),
|
||||
"recoveryAll": MessageLookupByLibrary.simpleMessage("恢复所有数据"),
|
||||
"recoveryProfiles": MessageLookupByLibrary.simpleMessage("仅恢复配置文件"),
|
||||
"recoveryStrategy": MessageLookupByLibrary.simpleMessage("恢复策略"),
|
||||
"recoveryStrategy_compatible": MessageLookupByLibrary.simpleMessage("兼容"),
|
||||
"recoveryStrategy_override": MessageLookupByLibrary.simpleMessage("覆盖"),
|
||||
"recoverySuccess": MessageLookupByLibrary.simpleMessage("恢复成功"),
|
||||
"redo": MessageLookupByLibrary.simpleMessage("重做"),
|
||||
"regExp": MessageLookupByLibrary.simpleMessage("正则"),
|
||||
@@ -398,6 +411,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"submit": MessageLookupByLibrary.simpleMessage("提交"),
|
||||
"sync": MessageLookupByLibrary.simpleMessage("同步"),
|
||||
"system": MessageLookupByLibrary.simpleMessage("系统"),
|
||||
"systemApp": MessageLookupByLibrary.simpleMessage("系统应用"),
|
||||
"systemFont": MessageLookupByLibrary.simpleMessage("系统字体"),
|
||||
"systemProxy": MessageLookupByLibrary.simpleMessage("系统代理"),
|
||||
"systemProxyDesc": MessageLookupByLibrary.simpleMessage("设置系统代理"),
|
||||
@@ -407,6 +421,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
||||
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP并发"),
|
||||
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("开启后允许TCP并发"),
|
||||
"testUrl": MessageLookupByLibrary.simpleMessage("测速链接"),
|
||||
"textScale": MessageLookupByLibrary.simpleMessage("文本缩放"),
|
||||
"theme": MessageLookupByLibrary.simpleMessage("主题"),
|
||||
"themeColor": MessageLookupByLibrary.simpleMessage("主题色彩"),
|
||||
"themeDesc": MessageLookupByLibrary.simpleMessage("设置深色模式,调整色彩"),
|
||||
|
||||
@@ -3004,6 +3004,121 @@ class AppLocalizations {
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Developer mode`
|
||||
String get developerMode {
|
||||
return Intl.message(
|
||||
'Developer mode',
|
||||
name: 'developerMode',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Developer mode is enabled.`
|
||||
String get developerModeEnableTip {
|
||||
return Intl.message(
|
||||
'Developer mode is enabled.',
|
||||
name: 'developerModeEnableTip',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Message test`
|
||||
String get messageTest {
|
||||
return Intl.message(
|
||||
'Message test',
|
||||
name: 'messageTest',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `This is a message.`
|
||||
String get messageTestTip {
|
||||
return Intl.message(
|
||||
'This is a message.',
|
||||
name: 'messageTestTip',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Crash test`
|
||||
String get crashTest {
|
||||
return Intl.message('Crash test', name: 'crashTest', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `Clear Data`
|
||||
String get clearData {
|
||||
return Intl.message('Clear Data', name: 'clearData', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `Text Scaling`
|
||||
String get textScale {
|
||||
return Intl.message('Text Scaling', name: 'textScale', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `Internet`
|
||||
String get internet {
|
||||
return Intl.message('Internet', name: 'internet', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `System APP`
|
||||
String get systemApp {
|
||||
return Intl.message('System APP', name: 'systemApp', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `No network APP`
|
||||
String get noNetworkApp {
|
||||
return Intl.message(
|
||||
'No network APP',
|
||||
name: 'noNetworkApp',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Contact me`
|
||||
String get contactMe {
|
||||
return Intl.message('Contact me', name: 'contactMe', desc: '', args: []);
|
||||
}
|
||||
|
||||
/// `Recovery strategy`
|
||||
String get recoveryStrategy {
|
||||
return Intl.message(
|
||||
'Recovery strategy',
|
||||
name: 'recoveryStrategy',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Override`
|
||||
String get recoveryStrategy_override {
|
||||
return Intl.message(
|
||||
'Override',
|
||||
name: 'recoveryStrategy_override',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Compatible`
|
||||
String get recoveryStrategy_compatible {
|
||||
return Intl.message(
|
||||
'Compatible',
|
||||
name: 'recoveryStrategy_compatible',
|
||||
desc: '',
|
||||
args: [],
|
||||
);
|
||||
}
|
||||
|
||||
/// `Logs test`
|
||||
String get logsTest {
|
||||
return Intl.message('Logs test', name: 'logsTest', desc: '', args: []);
|
||||
}
|
||||
}
|
||||
|
||||
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||
|
||||
@@ -21,12 +21,16 @@ import 'common/common.dart';
|
||||
Future<void> main() async {
|
||||
globalState.isService = false;
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
FlutterError.onError = (details) {
|
||||
commonPrint.log(details.stack.toString());
|
||||
};
|
||||
final version = await system.version;
|
||||
await clashCore.preload();
|
||||
await globalState.initApp(version);
|
||||
await android?.init();
|
||||
await window?.init(version);
|
||||
globalState.isPre = const String.fromEnvironment("APP_ENV") != 'stable';
|
||||
globalState.coreSHA256 = const String.fromEnvironment("CORE_SHA256");
|
||||
HttpOverrides.global = FlClashHttpOverrides();
|
||||
runApp(ProviderScope(
|
||||
child: const Application(),
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:fl_clash/common/common.dart';
|
||||
import 'package:fl_clash/providers/providers.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class AppStateManager extends StatefulWidget {
|
||||
class AppStateManager extends ConsumerStatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const AppStateManager({
|
||||
@@ -14,15 +16,22 @@ class AppStateManager extends StatefulWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
State<AppStateManager> createState() => _AppStateManagerState();
|
||||
ConsumerState<AppStateManager> createState() => _AppStateManagerState();
|
||||
}
|
||||
|
||||
class _AppStateManagerState extends State<AppStateManager>
|
||||
class _AppStateManagerState extends ConsumerState<AppStateManager>
|
||||
with WidgetsBindingObserver {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addObserver(this);
|
||||
ref.listenManual(layoutChangeProvider, (prev, next) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (prev != next) {
|
||||
globalState.cacheHeightMap = {};
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -71,22 +71,22 @@ class _ClashContainerState extends ConsumerState<ClashManager>
|
||||
|
||||
@override
|
||||
void onLog(Log log) {
|
||||
ref.watch(logsProvider.notifier).addLog(log);
|
||||
ref.read(logsProvider.notifier).addLog(log);
|
||||
if (log.logLevel == LogLevel.error) {
|
||||
globalState.showNotifier(log.payload ?? '');
|
||||
globalState.showNotifier(log.payload);
|
||||
}
|
||||
super.onLog(log);
|
||||
}
|
||||
|
||||
@override
|
||||
void onRequest(Connection connection) async {
|
||||
ref.watch(requestsProvider.notifier).addRequest(connection);
|
||||
ref.read(requestsProvider.notifier).addRequest(connection);
|
||||
super.onRequest(connection);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onLoaded(String providerName) async {
|
||||
ref.watch(providersProvider.notifier).setProvider(
|
||||
ref.read(providersProvider.notifier).setProvider(
|
||||
await clashCore.getExternalProvider(
|
||||
providerName,
|
||||
),
|
||||
|
||||
@@ -21,7 +21,7 @@ class MessageManager extends StatefulWidget {
|
||||
class MessageManagerState extends State<MessageManager> {
|
||||
final _messagesNotifier = ValueNotifier<List<CommonMessage>>([]);
|
||||
final List<CommonMessage> _bufferMessages = [];
|
||||
Completer<bool>? _messageIngCompleter;
|
||||
bool _pushing = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -40,26 +40,27 @@ class MessageManagerState extends State<MessageManager> {
|
||||
text: text,
|
||||
);
|
||||
_bufferMessages.add(commonMessage);
|
||||
_showMessage();
|
||||
await _showMessage();
|
||||
}
|
||||
|
||||
_showMessage() async {
|
||||
if (_messageIngCompleter?.isCompleted == false) {
|
||||
if (_pushing == true) {
|
||||
return;
|
||||
}
|
||||
_pushing = true;
|
||||
while (_bufferMessages.isNotEmpty) {
|
||||
final commonMessage = _bufferMessages.removeAt(0);
|
||||
_messagesNotifier.value = List.from(_messagesNotifier.value)
|
||||
..add(
|
||||
commonMessage,
|
||||
);
|
||||
|
||||
_messageIngCompleter = Completer();
|
||||
await Future.delayed(Duration(seconds: 1));
|
||||
Future.delayed(commonMessage.duration, () {
|
||||
_handleRemove(commonMessage);
|
||||
});
|
||||
_messageIngCompleter?.complete(true);
|
||||
if (_bufferMessages.isEmpty) {
|
||||
_pushing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +78,11 @@ class MessageManagerState extends State<MessageManager> {
|
||||
valueListenable: _messagesNotifier,
|
||||
builder: (_, messages, __) {
|
||||
return FadeThroughBox(
|
||||
margin: EdgeInsets.only(
|
||||
top: kToolbarHeight + 8,
|
||||
left: 12,
|
||||
right: 12,
|
||||
),
|
||||
alignment: Alignment.topRight,
|
||||
child: messages.isEmpty
|
||||
? SizedBox()
|
||||
@@ -90,16 +96,11 @@ class MessageManagerState extends State<MessageManager> {
|
||||
),
|
||||
),
|
||||
elevation: 10,
|
||||
margin: EdgeInsets.only(
|
||||
top: kToolbarHeight + 8,
|
||||
left: 12,
|
||||
right: 12,
|
||||
),
|
||||
color: context.colorScheme.surfaceContainerHigh,
|
||||
child: Container(
|
||||
width: min(
|
||||
constraints.maxWidth,
|
||||
400,
|
||||
500,
|
||||
),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import 'dart:math';
|
||||
import 'package:fl_clash/common/constant.dart';
|
||||
import 'package:fl_clash/common/measure.dart';
|
||||
import 'package:fl_clash/common/theme.dart';
|
||||
import 'package:fl_clash/providers/config.dart';
|
||||
import 'package:fl_clash/state.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class ThemeManager extends StatelessWidget {
|
||||
class ThemeManager extends ConsumerWidget {
|
||||
final Widget child;
|
||||
|
||||
const ThemeManager({
|
||||
@@ -13,14 +16,30 @@ class ThemeManager extends StatelessWidget {
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
globalState.measure = Measure.of(context);
|
||||
globalState.theme = CommonTheme.of(context);
|
||||
Widget build(BuildContext context, ref) {
|
||||
final textScale = ref.read(
|
||||
themeSettingProvider.select((state) => state.textScale),
|
||||
);
|
||||
final double textScaleFactor = max(
|
||||
min(
|
||||
textScale.enable ? textScale.scale : defaultTextScaleFactor,
|
||||
maxTextScale,
|
||||
),
|
||||
minTextScale,
|
||||
);
|
||||
|
||||
globalState.measure = Measure.of(context, textScaleFactor);
|
||||
globalState.theme = CommonTheme.of(context, textScaleFactor);
|
||||
final padding = MediaQuery.of(context).padding;
|
||||
final height = MediaQuery.of(context).size.height;
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(
|
||||
textScaler: TextScaler.linear(
|
||||
textScaleFactor,
|
||||
),
|
||||
padding: padding.copyWith(
|
||||
top: padding.top > height * 0.3 ? 0.0 : padding.top,
|
||||
),
|
||||
),
|
||||
child: LayoutBuilder(
|
||||
builder: (_, container) {
|
||||
|
||||
@@ -25,7 +25,6 @@ class WindowManager extends ConsumerStatefulWidget {
|
||||
|
||||
class _WindowContainerState extends ConsumerState<WindowManager>
|
||||
with WindowListener, WindowExtListener {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return widget.child;
|
||||
@@ -183,19 +182,23 @@ class _WindowHeaderState extends State<WindowHeader> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
_updateMaximized() {
|
||||
isMaximizedNotifier.value = !isMaximizedNotifier.value;
|
||||
switch (isMaximizedNotifier.value) {
|
||||
_updateMaximized() async {
|
||||
final isMaximized = await windowManager.isMaximized();
|
||||
switch (isMaximized) {
|
||||
case true:
|
||||
windowManager.maximize();
|
||||
await windowManager.unmaximize();
|
||||
break;
|
||||
case false:
|
||||
windowManager.unmaximize();
|
||||
await windowManager.maximize();
|
||||
break;
|
||||
}
|
||||
isMaximizedNotifier.value = await windowManager.isMaximized();
|
||||
}
|
||||
|
||||
_updatePin() {
|
||||
isPinNotifier.value = !isPinNotifier.value;
|
||||
windowManager.setAlwaysOnTop(isPinNotifier.value);
|
||||
_updatePin() async {
|
||||
final isAlwaysOnTop = await windowManager.isAlwaysOnTop();
|
||||
await windowManager.setAlwaysOnTop(!isAlwaysOnTop);
|
||||
isPinNotifier.value = await windowManager.isAlwaysOnTop();
|
||||
}
|
||||
|
||||
_buildActions() {
|
||||
|
||||
@@ -16,7 +16,6 @@ class AppState with _$AppState {
|
||||
@Default(false) bool isInit,
|
||||
@Default(PageLabel.dashboard) PageLabel pageLabel,
|
||||
@Default([]) List<Package> packages,
|
||||
@Default(ColorSchemes()) ColorSchemes colorSchemes,
|
||||
@Default(0) int sortNum,
|
||||
required Size viewSize,
|
||||
@Default({}) DelayMap delayMap,
|
||||
|
||||
@@ -147,7 +147,8 @@ class Tun with _$Tun {
|
||||
const factory Tun({
|
||||
@Default(false) bool enable,
|
||||
@Default(appName) String device,
|
||||
@Default(TunStack.gvisor) TunStack stack,
|
||||
@JsonKey(name: "auto-route") @Default(false) bool autoRoute,
|
||||
@Default(TunStack.mixed) TunStack stack,
|
||||
@JsonKey(name: "dns-hijack") @Default(["any:53"]) List<String> dnsHijack,
|
||||
@JsonKey(name: "route-address") @Default([]) List<String> routeAddress,
|
||||
}) = _Tun;
|
||||
|
||||
@@ -30,7 +30,8 @@ class Package with _$Package {
|
||||
const factory Package({
|
||||
required String packageName,
|
||||
required String label,
|
||||
required bool isSystem,
|
||||
required bool system,
|
||||
required bool internet,
|
||||
required int lastUpdateTime,
|
||||
}) = _Package;
|
||||
|
||||
@@ -84,33 +85,33 @@ extension ConnectionExt on Connection {
|
||||
}
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class Log {
|
||||
@JsonKey(name: "LogLevel")
|
||||
LogLevel logLevel;
|
||||
@JsonKey(name: "Payload")
|
||||
String? payload;
|
||||
DateTime _dateTime;
|
||||
|
||||
Log({
|
||||
required this.logLevel,
|
||||
this.payload,
|
||||
}) : _dateTime = DateTime.now();
|
||||
|
||||
DateTime get dateTime => _dateTime;
|
||||
|
||||
factory Log.fromJson(Map<String, dynamic> json) {
|
||||
return _$LogFromJson(json);
|
||||
String _logDateTime(_) {
|
||||
return DateTime.now().toString();
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$LogToJson(this);
|
||||
// String _logId(_) {
|
||||
// return utils.id;
|
||||
// }
|
||||
|
||||
@freezed
|
||||
class Log with _$Log {
|
||||
const factory Log({
|
||||
@JsonKey(name: "LogLevel") @Default(LogLevel.app) LogLevel logLevel,
|
||||
@JsonKey(name: "Payload") @Default("") String payload,
|
||||
@JsonKey(fromJson: _logDateTime) required String dateTime,
|
||||
}) = _Log;
|
||||
|
||||
factory Log.app(
|
||||
String payload,
|
||||
) {
|
||||
return Log(
|
||||
payload: payload,
|
||||
dateTime: _logDateTime(null),
|
||||
// id: _logId(null),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Log{logLevel: $logLevel, payload: $payload, dateTime: $dateTime}';
|
||||
}
|
||||
factory Log.fromJson(Map<String, Object?> json) => _$LogFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
@@ -119,6 +120,7 @@ class LogsState with _$LogsState {
|
||||
@Default([]) List<Log> logs,
|
||||
@Default([]) List<String> keywords,
|
||||
@Default("") String query,
|
||||
@Default(false) bool loading,
|
||||
}) = _LogsState;
|
||||
}
|
||||
|
||||
@@ -127,11 +129,10 @@ extension LogsStateExt on LogsState {
|
||||
final lowQuery = query.toLowerCase();
|
||||
return logs.where(
|
||||
(log) {
|
||||
final payload = log.payload?.toLowerCase();
|
||||
final payload = log.payload.toLowerCase();
|
||||
final logLevelName = log.logLevel.name;
|
||||
return {logLevelName}.containsAll(keywords) &&
|
||||
((payload?.contains(lowQuery) ?? false) ||
|
||||
logLevelName.contains(lowQuery));
|
||||
((payload.contains(lowQuery)) || logLevelName.contains(lowQuery));
|
||||
},
|
||||
).toList();
|
||||
}
|
||||
@@ -143,6 +144,7 @@ class ConnectionsState with _$ConnectionsState {
|
||||
@Default([]) List<Connection> connections,
|
||||
@Default([]) List<String> keywords,
|
||||
@Default("") String query,
|
||||
@Default(false) bool loading,
|
||||
}) = _ConnectionsState;
|
||||
}
|
||||
|
||||
@@ -512,3 +514,17 @@ class PopupMenuItemData {
|
||||
final IconData? icon;
|
||||
final PopupMenuItemType? type;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class TextPainterParams with _$TextPainterParams {
|
||||
const factory TextPainterParams({
|
||||
required String? text,
|
||||
required double? fontSize,
|
||||
required double textScaleFactor,
|
||||
@Default(double.infinity) double maxWidth,
|
||||
int? maxLines,
|
||||
}) = _TextPainterParams;
|
||||
|
||||
factory TextPainterParams.fromJson(Map<String, Object?> json) =>
|
||||
_$TextPainterParamsFromJson(json);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,9 @@ const defaultNetworkProps = NetworkProps();
|
||||
const defaultProxiesStyle = ProxiesStyle();
|
||||
const defaultWindowProps = WindowProps();
|
||||
const defaultAccessControl = AccessControl();
|
||||
const defaultThemeProps = ThemeProps();
|
||||
final defaultThemeProps = ThemeProps(
|
||||
primaryColor: defaultPrimaryColor,
|
||||
);
|
||||
|
||||
const List<DashboardWidget> defaultDashboardWidgets = [
|
||||
DashboardWidget.networkSpeed,
|
||||
@@ -73,7 +75,7 @@ class AppSettingProps with _$AppSettingProps {
|
||||
@Default(false) bool autoLaunch,
|
||||
@Default(false) bool silentLaunch,
|
||||
@Default(false) bool autoRun,
|
||||
@Default(true) bool openLogs,
|
||||
@Default(false) bool openLogs,
|
||||
@Default(true) bool closeConnections,
|
||||
@Default(defaultTestUrl) String testUrl,
|
||||
@Default(true) bool isAnimateToPage,
|
||||
@@ -82,6 +84,8 @@ class AppSettingProps with _$AppSettingProps {
|
||||
@Default(false) bool disclaimerAccepted,
|
||||
@Default(true) bool minimizeOnExit,
|
||||
@Default(false) bool hidden,
|
||||
@Default(false) bool developerMode,
|
||||
@Default(RecoveryStrategy.compatible) RecoveryStrategy recoveryStrategy,
|
||||
}) = _AppSettingProps;
|
||||
|
||||
factory AppSettingProps.fromJson(Map<String, Object?> json) =>
|
||||
@@ -103,6 +107,7 @@ class AccessControl with _$AccessControl {
|
||||
@Default([]) List<String> rejectList,
|
||||
@Default(AccessSortType.none) AccessSortType sort,
|
||||
@Default(true) bool isFilterSystemApp,
|
||||
@Default(true) bool isFilterNonInternetApp,
|
||||
}) = _AccessControl;
|
||||
|
||||
factory AccessControl.fromJson(Map<String, Object?> json) =>
|
||||
@@ -170,18 +175,41 @@ class ProxiesStyle with _$ProxiesStyle {
|
||||
json == null ? defaultProxiesStyle : _$ProxiesStyleFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class TextScale with _$TextScale {
|
||||
const factory TextScale({
|
||||
@Default(false) enable,
|
||||
@Default(1.0) scale,
|
||||
}) = _TextScale;
|
||||
|
||||
factory TextScale.fromJson(Map<String, Object?> json) =>
|
||||
_$TextScaleFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ThemeProps with _$ThemeProps {
|
||||
const factory ThemeProps({
|
||||
@Default(defaultPrimaryColor) int? primaryColor,
|
||||
int? primaryColor,
|
||||
@Default(defaultPrimaryColors) List<int> primaryColors,
|
||||
@Default(ThemeMode.dark) ThemeMode themeMode,
|
||||
@Default(DynamicSchemeVariant.tonalSpot) DynamicSchemeVariant schemeVariant,
|
||||
@Default(DynamicSchemeVariant.content) DynamicSchemeVariant schemeVariant,
|
||||
@Default(false) bool pureBlack,
|
||||
@Default(TextScale()) TextScale textScale,
|
||||
}) = _ThemeProps;
|
||||
|
||||
factory ThemeProps.fromJson(Map<String, Object?>? json) =>
|
||||
json == null ? defaultThemeProps : _$ThemePropsFromJson(json);
|
||||
factory ThemeProps.fromJson(Map<String, Object?> json) =>
|
||||
_$ThemePropsFromJson(json);
|
||||
|
||||
factory ThemeProps.safeFromJson(Map<String, Object?>? json) {
|
||||
if (json == null) {
|
||||
return defaultThemeProps;
|
||||
}
|
||||
try {
|
||||
return ThemeProps.fromJson(json);
|
||||
} catch (_) {
|
||||
return defaultThemeProps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
@@ -197,7 +225,7 @@ class Config with _$Config {
|
||||
DAV? dav,
|
||||
@Default(defaultNetworkProps) NetworkProps networkProps,
|
||||
@Default(defaultVpnProps) VpnProps vpnProps,
|
||||
@Default(defaultThemeProps) ThemeProps themeProps,
|
||||
@JsonKey(fromJson: ThemeProps.safeFromJson) required ThemeProps themeProps,
|
||||
@Default(defaultProxiesStyle) ProxiesStyle proxiesStyle,
|
||||
@Default(defaultWindowProps) WindowProps windowProps,
|
||||
@Default(defaultClashConfig) ClashConfig patchClashConfig,
|
||||
|
||||
@@ -19,7 +19,6 @@ mixin _$AppState {
|
||||
bool get isInit => throw _privateConstructorUsedError;
|
||||
PageLabel get pageLabel => throw _privateConstructorUsedError;
|
||||
List<Package> get packages => throw _privateConstructorUsedError;
|
||||
ColorSchemes get colorSchemes => throw _privateConstructorUsedError;
|
||||
int get sortNum => throw _privateConstructorUsedError;
|
||||
Size get viewSize => throw _privateConstructorUsedError;
|
||||
Map<String, Map<String, int?>> get delayMap =>
|
||||
@@ -53,7 +52,6 @@ abstract class $AppStateCopyWith<$Res> {
|
||||
{bool isInit,
|
||||
PageLabel pageLabel,
|
||||
List<Package> packages,
|
||||
ColorSchemes colorSchemes,
|
||||
int sortNum,
|
||||
Size viewSize,
|
||||
Map<String, Map<String, int?>> delayMap,
|
||||
@@ -69,8 +67,6 @@ abstract class $AppStateCopyWith<$Res> {
|
||||
FixedList<Traffic> traffics,
|
||||
Traffic totalTraffic,
|
||||
bool needApply});
|
||||
|
||||
$ColorSchemesCopyWith<$Res> get colorSchemes;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -91,7 +87,6 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
|
||||
Object? isInit = null,
|
||||
Object? pageLabel = null,
|
||||
Object? packages = null,
|
||||
Object? colorSchemes = null,
|
||||
Object? sortNum = null,
|
||||
Object? viewSize = null,
|
||||
Object? delayMap = null,
|
||||
@@ -121,10 +116,6 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
|
||||
? _value.packages
|
||||
: packages // ignore: cast_nullable_to_non_nullable
|
||||
as List<Package>,
|
||||
colorSchemes: null == colorSchemes
|
||||
? _value.colorSchemes
|
||||
: colorSchemes // ignore: cast_nullable_to_non_nullable
|
||||
as ColorSchemes,
|
||||
sortNum: null == sortNum
|
||||
? _value.sortNum
|
||||
: sortNum // ignore: cast_nullable_to_non_nullable
|
||||
@@ -187,16 +178,6 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
|
||||
as bool,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
/// Create a copy of AppState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ColorSchemesCopyWith<$Res> get colorSchemes {
|
||||
return $ColorSchemesCopyWith<$Res>(_value.colorSchemes, (value) {
|
||||
return _then(_value.copyWith(colorSchemes: value) as $Val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -211,7 +192,6 @@ abstract class _$$AppStateImplCopyWith<$Res>
|
||||
{bool isInit,
|
||||
PageLabel pageLabel,
|
||||
List<Package> packages,
|
||||
ColorSchemes colorSchemes,
|
||||
int sortNum,
|
||||
Size viewSize,
|
||||
Map<String, Map<String, int?>> delayMap,
|
||||
@@ -227,9 +207,6 @@ abstract class _$$AppStateImplCopyWith<$Res>
|
||||
FixedList<Traffic> traffics,
|
||||
Traffic totalTraffic,
|
||||
bool needApply});
|
||||
|
||||
@override
|
||||
$ColorSchemesCopyWith<$Res> get colorSchemes;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -248,7 +225,6 @@ class __$$AppStateImplCopyWithImpl<$Res>
|
||||
Object? isInit = null,
|
||||
Object? pageLabel = null,
|
||||
Object? packages = null,
|
||||
Object? colorSchemes = null,
|
||||
Object? sortNum = null,
|
||||
Object? viewSize = null,
|
||||
Object? delayMap = null,
|
||||
@@ -278,10 +254,6 @@ class __$$AppStateImplCopyWithImpl<$Res>
|
||||
? _value._packages
|
||||
: packages // ignore: cast_nullable_to_non_nullable
|
||||
as List<Package>,
|
||||
colorSchemes: null == colorSchemes
|
||||
? _value.colorSchemes
|
||||
: colorSchemes // ignore: cast_nullable_to_non_nullable
|
||||
as ColorSchemes,
|
||||
sortNum: null == sortNum
|
||||
? _value.sortNum
|
||||
: sortNum // ignore: cast_nullable_to_non_nullable
|
||||
@@ -353,7 +325,6 @@ class _$AppStateImpl implements _AppState {
|
||||
{this.isInit = false,
|
||||
this.pageLabel = PageLabel.dashboard,
|
||||
final List<Package> packages = const [],
|
||||
this.colorSchemes = const ColorSchemes(),
|
||||
this.sortNum = 0,
|
||||
required this.viewSize,
|
||||
final Map<String, Map<String, int?>> delayMap = const {},
|
||||
@@ -389,9 +360,6 @@ class _$AppStateImpl implements _AppState {
|
||||
return EqualUnmodifiableListView(_packages);
|
||||
}
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final ColorSchemes colorSchemes;
|
||||
@override
|
||||
@JsonKey()
|
||||
final int sortNum;
|
||||
@@ -449,7 +417,7 @@ class _$AppStateImpl implements _AppState {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppState(isInit: $isInit, pageLabel: $pageLabel, packages: $packages, colorSchemes: $colorSchemes, sortNum: $sortNum, viewSize: $viewSize, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, needApply: $needApply)';
|
||||
return 'AppState(isInit: $isInit, pageLabel: $pageLabel, packages: $packages, sortNum: $sortNum, viewSize: $viewSize, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, needApply: $needApply)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -461,8 +429,6 @@ class _$AppStateImpl implements _AppState {
|
||||
(identical(other.pageLabel, pageLabel) ||
|
||||
other.pageLabel == pageLabel) &&
|
||||
const DeepCollectionEquality().equals(other._packages, _packages) &&
|
||||
(identical(other.colorSchemes, colorSchemes) ||
|
||||
other.colorSchemes == colorSchemes) &&
|
||||
(identical(other.sortNum, sortNum) || other.sortNum == sortNum) &&
|
||||
(identical(other.viewSize, viewSize) ||
|
||||
other.viewSize == viewSize) &&
|
||||
@@ -489,12 +455,11 @@ class _$AppStateImpl implements _AppState {
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hashAll([
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
isInit,
|
||||
pageLabel,
|
||||
const DeepCollectionEquality().hash(_packages),
|
||||
colorSchemes,
|
||||
sortNum,
|
||||
viewSize,
|
||||
const DeepCollectionEquality().hash(_delayMap),
|
||||
@@ -509,8 +474,7 @@ class _$AppStateImpl implements _AppState {
|
||||
logs,
|
||||
traffics,
|
||||
totalTraffic,
|
||||
needApply
|
||||
]);
|
||||
needApply);
|
||||
|
||||
/// Create a copy of AppState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -526,7 +490,6 @@ abstract class _AppState implements AppState {
|
||||
{final bool isInit,
|
||||
final PageLabel pageLabel,
|
||||
final List<Package> packages,
|
||||
final ColorSchemes colorSchemes,
|
||||
final int sortNum,
|
||||
required final Size viewSize,
|
||||
final Map<String, Map<String, int?>> delayMap,
|
||||
@@ -550,8 +513,6 @@ abstract class _AppState implements AppState {
|
||||
@override
|
||||
List<Package> get packages;
|
||||
@override
|
||||
ColorSchemes get colorSchemes;
|
||||
@override
|
||||
int get sortNum;
|
||||
@override
|
||||
Size get viewSize;
|
||||
|
||||
@@ -660,6 +660,8 @@ Tun _$TunFromJson(Map<String, dynamic> json) {
|
||||
mixin _$Tun {
|
||||
bool get enable => throw _privateConstructorUsedError;
|
||||
String get device => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "auto-route")
|
||||
bool get autoRoute => throw _privateConstructorUsedError;
|
||||
TunStack get stack => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "dns-hijack")
|
||||
List<String> get dnsHijack => throw _privateConstructorUsedError;
|
||||
@@ -683,6 +685,7 @@ abstract class $TunCopyWith<$Res> {
|
||||
$Res call(
|
||||
{bool enable,
|
||||
String device,
|
||||
@JsonKey(name: "auto-route") bool autoRoute,
|
||||
TunStack stack,
|
||||
@JsonKey(name: "dns-hijack") List<String> dnsHijack,
|
||||
@JsonKey(name: "route-address") List<String> routeAddress});
|
||||
@@ -704,6 +707,7 @@ class _$TunCopyWithImpl<$Res, $Val extends Tun> implements $TunCopyWith<$Res> {
|
||||
$Res call({
|
||||
Object? enable = null,
|
||||
Object? device = null,
|
||||
Object? autoRoute = null,
|
||||
Object? stack = null,
|
||||
Object? dnsHijack = null,
|
||||
Object? routeAddress = null,
|
||||
@@ -717,6 +721,10 @@ class _$TunCopyWithImpl<$Res, $Val extends Tun> implements $TunCopyWith<$Res> {
|
||||
? _value.device
|
||||
: device // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
autoRoute: null == autoRoute
|
||||
? _value.autoRoute
|
||||
: autoRoute // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
stack: null == stack
|
||||
? _value.stack
|
||||
: stack // ignore: cast_nullable_to_non_nullable
|
||||
@@ -742,6 +750,7 @@ abstract class _$$TunImplCopyWith<$Res> implements $TunCopyWith<$Res> {
|
||||
$Res call(
|
||||
{bool enable,
|
||||
String device,
|
||||
@JsonKey(name: "auto-route") bool autoRoute,
|
||||
TunStack stack,
|
||||
@JsonKey(name: "dns-hijack") List<String> dnsHijack,
|
||||
@JsonKey(name: "route-address") List<String> routeAddress});
|
||||
@@ -760,6 +769,7 @@ class __$$TunImplCopyWithImpl<$Res> extends _$TunCopyWithImpl<$Res, _$TunImpl>
|
||||
$Res call({
|
||||
Object? enable = null,
|
||||
Object? device = null,
|
||||
Object? autoRoute = null,
|
||||
Object? stack = null,
|
||||
Object? dnsHijack = null,
|
||||
Object? routeAddress = null,
|
||||
@@ -773,6 +783,10 @@ class __$$TunImplCopyWithImpl<$Res> extends _$TunCopyWithImpl<$Res, _$TunImpl>
|
||||
? _value.device
|
||||
: device // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
autoRoute: null == autoRoute
|
||||
? _value.autoRoute
|
||||
: autoRoute // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
stack: null == stack
|
||||
? _value.stack
|
||||
: stack // ignore: cast_nullable_to_non_nullable
|
||||
@@ -795,7 +809,8 @@ class _$TunImpl implements _Tun {
|
||||
const _$TunImpl(
|
||||
{this.enable = false,
|
||||
this.device = appName,
|
||||
this.stack = TunStack.gvisor,
|
||||
@JsonKey(name: "auto-route") this.autoRoute = false,
|
||||
this.stack = TunStack.mixed,
|
||||
@JsonKey(name: "dns-hijack")
|
||||
final List<String> dnsHijack = const ["any:53"],
|
||||
@JsonKey(name: "route-address")
|
||||
@@ -813,6 +828,9 @@ class _$TunImpl implements _Tun {
|
||||
@JsonKey()
|
||||
final String device;
|
||||
@override
|
||||
@JsonKey(name: "auto-route")
|
||||
final bool autoRoute;
|
||||
@override
|
||||
@JsonKey()
|
||||
final TunStack stack;
|
||||
final List<String> _dnsHijack;
|
||||
@@ -835,7 +853,7 @@ class _$TunImpl implements _Tun {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Tun(enable: $enable, device: $device, stack: $stack, dnsHijack: $dnsHijack, routeAddress: $routeAddress)';
|
||||
return 'Tun(enable: $enable, device: $device, autoRoute: $autoRoute, stack: $stack, dnsHijack: $dnsHijack, routeAddress: $routeAddress)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -845,6 +863,8 @@ class _$TunImpl implements _Tun {
|
||||
other is _$TunImpl &&
|
||||
(identical(other.enable, enable) || other.enable == enable) &&
|
||||
(identical(other.device, device) || other.device == device) &&
|
||||
(identical(other.autoRoute, autoRoute) ||
|
||||
other.autoRoute == autoRoute) &&
|
||||
(identical(other.stack, stack) || other.stack == stack) &&
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._dnsHijack, _dnsHijack) &&
|
||||
@@ -858,6 +878,7 @@ class _$TunImpl implements _Tun {
|
||||
runtimeType,
|
||||
enable,
|
||||
device,
|
||||
autoRoute,
|
||||
stack,
|
||||
const DeepCollectionEquality().hash(_dnsHijack),
|
||||
const DeepCollectionEquality().hash(_routeAddress));
|
||||
@@ -882,6 +903,7 @@ abstract class _Tun implements Tun {
|
||||
const factory _Tun(
|
||||
{final bool enable,
|
||||
final String device,
|
||||
@JsonKey(name: "auto-route") final bool autoRoute,
|
||||
final TunStack stack,
|
||||
@JsonKey(name: "dns-hijack") final List<String> dnsHijack,
|
||||
@JsonKey(name: "route-address") final List<String> routeAddress}) =
|
||||
@@ -894,6 +916,9 @@ abstract class _Tun implements Tun {
|
||||
@override
|
||||
String get device;
|
||||
@override
|
||||
@JsonKey(name: "auto-route")
|
||||
bool get autoRoute;
|
||||
@override
|
||||
TunStack get stack;
|
||||
@override
|
||||
@JsonKey(name: "dns-hijack")
|
||||
|
||||
@@ -66,8 +66,9 @@ Map<String, dynamic> _$$RuleProviderImplToJson(_$RuleProviderImpl instance) =>
|
||||
_$TunImpl _$$TunImplFromJson(Map<String, dynamic> json) => _$TunImpl(
|
||||
enable: json['enable'] as bool? ?? false,
|
||||
device: json['device'] as String? ?? appName,
|
||||
autoRoute: json['auto-route'] as bool? ?? false,
|
||||
stack: $enumDecodeNullable(_$TunStackEnumMap, json['stack']) ??
|
||||
TunStack.gvisor,
|
||||
TunStack.mixed,
|
||||
dnsHijack: (json['dns-hijack'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList() ??
|
||||
@@ -81,6 +82,7 @@ _$TunImpl _$$TunImplFromJson(Map<String, dynamic> json) => _$TunImpl(
|
||||
Map<String, dynamic> _$$TunImplToJson(_$TunImpl instance) => <String, dynamic>{
|
||||
'enable': instance.enable,
|
||||
'device': instance.device,
|
||||
'auto-route': instance.autoRoute,
|
||||
'stack': _$TunStackEnumMap[instance.stack]!,
|
||||
'dns-hijack': instance.dnsHijack,
|
||||
'route-address': instance.routeAddress,
|
||||
@@ -342,6 +344,7 @@ const _$LogLevelEnumMap = {
|
||||
LogLevel.warning: 'warning',
|
||||
LogLevel.error: 'error',
|
||||
LogLevel.silent: 'silent',
|
||||
LogLevel.app: 'app',
|
||||
};
|
||||
|
||||
const _$FindProcessModeEnumMap = {
|
||||
|
||||
@@ -289,7 +289,8 @@ Package _$PackageFromJson(Map<String, dynamic> json) {
|
||||
mixin _$Package {
|
||||
String get packageName => throw _privateConstructorUsedError;
|
||||
String get label => throw _privateConstructorUsedError;
|
||||
bool get isSystem => throw _privateConstructorUsedError;
|
||||
bool get system => throw _privateConstructorUsedError;
|
||||
bool get internet => throw _privateConstructorUsedError;
|
||||
int get lastUpdateTime => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this Package to a JSON map.
|
||||
@@ -307,7 +308,11 @@ abstract class $PackageCopyWith<$Res> {
|
||||
_$PackageCopyWithImpl<$Res, Package>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String packageName, String label, bool isSystem, int lastUpdateTime});
|
||||
{String packageName,
|
||||
String label,
|
||||
bool system,
|
||||
bool internet,
|
||||
int lastUpdateTime});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -327,7 +332,8 @@ class _$PackageCopyWithImpl<$Res, $Val extends Package>
|
||||
$Res call({
|
||||
Object? packageName = null,
|
||||
Object? label = null,
|
||||
Object? isSystem = null,
|
||||
Object? system = null,
|
||||
Object? internet = null,
|
||||
Object? lastUpdateTime = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
@@ -339,9 +345,13 @@ class _$PackageCopyWithImpl<$Res, $Val extends Package>
|
||||
? _value.label
|
||||
: label // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
isSystem: null == isSystem
|
||||
? _value.isSystem
|
||||
: isSystem // ignore: cast_nullable_to_non_nullable
|
||||
system: null == system
|
||||
? _value.system
|
||||
: system // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
internet: null == internet
|
||||
? _value.internet
|
||||
: internet // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
lastUpdateTime: null == lastUpdateTime
|
||||
? _value.lastUpdateTime
|
||||
@@ -359,7 +369,11 @@ abstract class _$$PackageImplCopyWith<$Res> implements $PackageCopyWith<$Res> {
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{String packageName, String label, bool isSystem, int lastUpdateTime});
|
||||
{String packageName,
|
||||
String label,
|
||||
bool system,
|
||||
bool internet,
|
||||
int lastUpdateTime});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -377,7 +391,8 @@ class __$$PackageImplCopyWithImpl<$Res>
|
||||
$Res call({
|
||||
Object? packageName = null,
|
||||
Object? label = null,
|
||||
Object? isSystem = null,
|
||||
Object? system = null,
|
||||
Object? internet = null,
|
||||
Object? lastUpdateTime = null,
|
||||
}) {
|
||||
return _then(_$PackageImpl(
|
||||
@@ -389,9 +404,13 @@ class __$$PackageImplCopyWithImpl<$Res>
|
||||
? _value.label
|
||||
: label // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
isSystem: null == isSystem
|
||||
? _value.isSystem
|
||||
: isSystem // ignore: cast_nullable_to_non_nullable
|
||||
system: null == system
|
||||
? _value.system
|
||||
: system // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
internet: null == internet
|
||||
? _value.internet
|
||||
: internet // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
lastUpdateTime: null == lastUpdateTime
|
||||
? _value.lastUpdateTime
|
||||
@@ -407,7 +426,8 @@ class _$PackageImpl implements _Package {
|
||||
const _$PackageImpl(
|
||||
{required this.packageName,
|
||||
required this.label,
|
||||
required this.isSystem,
|
||||
required this.system,
|
||||
required this.internet,
|
||||
required this.lastUpdateTime});
|
||||
|
||||
factory _$PackageImpl.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -418,13 +438,15 @@ class _$PackageImpl implements _Package {
|
||||
@override
|
||||
final String label;
|
||||
@override
|
||||
final bool isSystem;
|
||||
final bool system;
|
||||
@override
|
||||
final bool internet;
|
||||
@override
|
||||
final int lastUpdateTime;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Package(packageName: $packageName, label: $label, isSystem: $isSystem, lastUpdateTime: $lastUpdateTime)';
|
||||
return 'Package(packageName: $packageName, label: $label, system: $system, internet: $internet, lastUpdateTime: $lastUpdateTime)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -435,16 +457,17 @@ class _$PackageImpl implements _Package {
|
||||
(identical(other.packageName, packageName) ||
|
||||
other.packageName == packageName) &&
|
||||
(identical(other.label, label) || other.label == label) &&
|
||||
(identical(other.isSystem, isSystem) ||
|
||||
other.isSystem == isSystem) &&
|
||||
(identical(other.system, system) || other.system == system) &&
|
||||
(identical(other.internet, internet) ||
|
||||
other.internet == internet) &&
|
||||
(identical(other.lastUpdateTime, lastUpdateTime) ||
|
||||
other.lastUpdateTime == lastUpdateTime));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, packageName, label, isSystem, lastUpdateTime);
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, packageName, label, system, internet, lastUpdateTime);
|
||||
|
||||
/// Create a copy of Package
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -466,7 +489,8 @@ abstract class _Package implements Package {
|
||||
const factory _Package(
|
||||
{required final String packageName,
|
||||
required final String label,
|
||||
required final bool isSystem,
|
||||
required final bool system,
|
||||
required final bool internet,
|
||||
required final int lastUpdateTime}) = _$PackageImpl;
|
||||
|
||||
factory _Package.fromJson(Map<String, dynamic> json) = _$PackageImpl.fromJson;
|
||||
@@ -476,7 +500,9 @@ abstract class _Package implements Package {
|
||||
@override
|
||||
String get label;
|
||||
@override
|
||||
bool get isSystem;
|
||||
bool get system;
|
||||
@override
|
||||
bool get internet;
|
||||
@override
|
||||
int get lastUpdateTime;
|
||||
|
||||
@@ -1092,11 +1118,209 @@ abstract class _Connection implements Connection {
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
Log _$LogFromJson(Map<String, dynamic> json) {
|
||||
return _Log.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$Log {
|
||||
@JsonKey(name: "LogLevel")
|
||||
LogLevel get logLevel => throw _privateConstructorUsedError;
|
||||
@JsonKey(name: "Payload")
|
||||
String get payload => throw _privateConstructorUsedError;
|
||||
@JsonKey(fromJson: _logDateTime)
|
||||
String get dateTime => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this Log to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of Log
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$LogCopyWith<Log> get copyWith => throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $LogCopyWith<$Res> {
|
||||
factory $LogCopyWith(Log value, $Res Function(Log) then) =
|
||||
_$LogCopyWithImpl<$Res, Log>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{@JsonKey(name: "LogLevel") LogLevel logLevel,
|
||||
@JsonKey(name: "Payload") String payload,
|
||||
@JsonKey(fromJson: _logDateTime) String dateTime});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$LogCopyWithImpl<$Res, $Val extends Log> implements $LogCopyWith<$Res> {
|
||||
_$LogCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of Log
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? logLevel = null,
|
||||
Object? payload = null,
|
||||
Object? dateTime = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
logLevel: null == logLevel
|
||||
? _value.logLevel
|
||||
: logLevel // ignore: cast_nullable_to_non_nullable
|
||||
as LogLevel,
|
||||
payload: null == payload
|
||||
? _value.payload
|
||||
: payload // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
dateTime: null == dateTime
|
||||
? _value.dateTime
|
||||
: dateTime // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$LogImplCopyWith<$Res> implements $LogCopyWith<$Res> {
|
||||
factory _$$LogImplCopyWith(_$LogImpl value, $Res Function(_$LogImpl) then) =
|
||||
__$$LogImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{@JsonKey(name: "LogLevel") LogLevel logLevel,
|
||||
@JsonKey(name: "Payload") String payload,
|
||||
@JsonKey(fromJson: _logDateTime) String dateTime});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$LogImplCopyWithImpl<$Res> extends _$LogCopyWithImpl<$Res, _$LogImpl>
|
||||
implements _$$LogImplCopyWith<$Res> {
|
||||
__$$LogImplCopyWithImpl(_$LogImpl _value, $Res Function(_$LogImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of Log
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? logLevel = null,
|
||||
Object? payload = null,
|
||||
Object? dateTime = null,
|
||||
}) {
|
||||
return _then(_$LogImpl(
|
||||
logLevel: null == logLevel
|
||||
? _value.logLevel
|
||||
: logLevel // ignore: cast_nullable_to_non_nullable
|
||||
as LogLevel,
|
||||
payload: null == payload
|
||||
? _value.payload
|
||||
: payload // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
dateTime: null == dateTime
|
||||
? _value.dateTime
|
||||
: dateTime // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$LogImpl implements _Log {
|
||||
const _$LogImpl(
|
||||
{@JsonKey(name: "LogLevel") this.logLevel = LogLevel.app,
|
||||
@JsonKey(name: "Payload") this.payload = "",
|
||||
@JsonKey(fromJson: _logDateTime) required this.dateTime});
|
||||
|
||||
factory _$LogImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$LogImplFromJson(json);
|
||||
|
||||
@override
|
||||
@JsonKey(name: "LogLevel")
|
||||
final LogLevel logLevel;
|
||||
@override
|
||||
@JsonKey(name: "Payload")
|
||||
final String payload;
|
||||
@override
|
||||
@JsonKey(fromJson: _logDateTime)
|
||||
final String dateTime;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Log(logLevel: $logLevel, payload: $payload, dateTime: $dateTime)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$LogImpl &&
|
||||
(identical(other.logLevel, logLevel) ||
|
||||
other.logLevel == logLevel) &&
|
||||
(identical(other.payload, payload) || other.payload == payload) &&
|
||||
(identical(other.dateTime, dateTime) ||
|
||||
other.dateTime == dateTime));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, logLevel, payload, dateTime);
|
||||
|
||||
/// Create a copy of Log
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$LogImplCopyWith<_$LogImpl> get copyWith =>
|
||||
__$$LogImplCopyWithImpl<_$LogImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$LogImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _Log implements Log {
|
||||
const factory _Log(
|
||||
{@JsonKey(name: "LogLevel") final LogLevel logLevel,
|
||||
@JsonKey(name: "Payload") final String payload,
|
||||
@JsonKey(fromJson: _logDateTime) required final String dateTime}) =
|
||||
_$LogImpl;
|
||||
|
||||
factory _Log.fromJson(Map<String, dynamic> json) = _$LogImpl.fromJson;
|
||||
|
||||
@override
|
||||
@JsonKey(name: "LogLevel")
|
||||
LogLevel get logLevel;
|
||||
@override
|
||||
@JsonKey(name: "Payload")
|
||||
String get payload;
|
||||
@override
|
||||
@JsonKey(fromJson: _logDateTime)
|
||||
String get dateTime;
|
||||
|
||||
/// Create a copy of Log
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$LogImplCopyWith<_$LogImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$LogsState {
|
||||
List<Log> get logs => throw _privateConstructorUsedError;
|
||||
List<String> get keywords => throw _privateConstructorUsedError;
|
||||
String get query => throw _privateConstructorUsedError;
|
||||
bool get loading => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of LogsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1110,7 +1334,8 @@ abstract class $LogsStateCopyWith<$Res> {
|
||||
factory $LogsStateCopyWith(LogsState value, $Res Function(LogsState) then) =
|
||||
_$LogsStateCopyWithImpl<$Res, LogsState>;
|
||||
@useResult
|
||||
$Res call({List<Log> logs, List<String> keywords, String query});
|
||||
$Res call(
|
||||
{List<Log> logs, List<String> keywords, String query, bool loading});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -1131,6 +1356,7 @@ class _$LogsStateCopyWithImpl<$Res, $Val extends LogsState>
|
||||
Object? logs = null,
|
||||
Object? keywords = null,
|
||||
Object? query = null,
|
||||
Object? loading = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
logs: null == logs
|
||||
@@ -1145,6 +1371,10 @@ class _$LogsStateCopyWithImpl<$Res, $Val extends LogsState>
|
||||
? _value.query
|
||||
: query // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
loading: null == loading
|
||||
? _value.loading
|
||||
: loading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
@@ -1157,7 +1387,8 @@ abstract class _$$LogsStateImplCopyWith<$Res>
|
||||
__$$LogsStateImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({List<Log> logs, List<String> keywords, String query});
|
||||
$Res call(
|
||||
{List<Log> logs, List<String> keywords, String query, bool loading});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -1176,6 +1407,7 @@ class __$$LogsStateImplCopyWithImpl<$Res>
|
||||
Object? logs = null,
|
||||
Object? keywords = null,
|
||||
Object? query = null,
|
||||
Object? loading = null,
|
||||
}) {
|
||||
return _then(_$LogsStateImpl(
|
||||
logs: null == logs
|
||||
@@ -1190,6 +1422,10 @@ class __$$LogsStateImplCopyWithImpl<$Res>
|
||||
? _value.query
|
||||
: query // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
loading: null == loading
|
||||
? _value.loading
|
||||
: loading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1200,7 +1436,8 @@ class _$LogsStateImpl implements _LogsState {
|
||||
const _$LogsStateImpl(
|
||||
{final List<Log> logs = const [],
|
||||
final List<String> keywords = const [],
|
||||
this.query = ""})
|
||||
this.query = "",
|
||||
this.loading = false})
|
||||
: _logs = logs,
|
||||
_keywords = keywords;
|
||||
|
||||
@@ -1225,10 +1462,13 @@ class _$LogsStateImpl implements _LogsState {
|
||||
@override
|
||||
@JsonKey()
|
||||
final String query;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool loading;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LogsState(logs: $logs, keywords: $keywords, query: $query)';
|
||||
return 'LogsState(logs: $logs, keywords: $keywords, query: $query, loading: $loading)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -1238,7 +1478,8 @@ class _$LogsStateImpl implements _LogsState {
|
||||
other is _$LogsStateImpl &&
|
||||
const DeepCollectionEquality().equals(other._logs, _logs) &&
|
||||
const DeepCollectionEquality().equals(other._keywords, _keywords) &&
|
||||
(identical(other.query, query) || other.query == query));
|
||||
(identical(other.query, query) || other.query == query) &&
|
||||
(identical(other.loading, loading) || other.loading == loading));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -1246,7 +1487,8 @@ class _$LogsStateImpl implements _LogsState {
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(_logs),
|
||||
const DeepCollectionEquality().hash(_keywords),
|
||||
query);
|
||||
query,
|
||||
loading);
|
||||
|
||||
/// Create a copy of LogsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1261,7 +1503,8 @@ abstract class _LogsState implements LogsState {
|
||||
const factory _LogsState(
|
||||
{final List<Log> logs,
|
||||
final List<String> keywords,
|
||||
final String query}) = _$LogsStateImpl;
|
||||
final String query,
|
||||
final bool loading}) = _$LogsStateImpl;
|
||||
|
||||
@override
|
||||
List<Log> get logs;
|
||||
@@ -1269,6 +1512,8 @@ abstract class _LogsState implements LogsState {
|
||||
List<String> get keywords;
|
||||
@override
|
||||
String get query;
|
||||
@override
|
||||
bool get loading;
|
||||
|
||||
/// Create a copy of LogsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1283,6 +1528,7 @@ mixin _$ConnectionsState {
|
||||
List<Connection> get connections => throw _privateConstructorUsedError;
|
||||
List<String> get keywords => throw _privateConstructorUsedError;
|
||||
String get query => throw _privateConstructorUsedError;
|
||||
bool get loading => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of ConnectionsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1298,7 +1544,10 @@ abstract class $ConnectionsStateCopyWith<$Res> {
|
||||
_$ConnectionsStateCopyWithImpl<$Res, ConnectionsState>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{List<Connection> connections, List<String> keywords, String query});
|
||||
{List<Connection> connections,
|
||||
List<String> keywords,
|
||||
String query,
|
||||
bool loading});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -1319,6 +1568,7 @@ class _$ConnectionsStateCopyWithImpl<$Res, $Val extends ConnectionsState>
|
||||
Object? connections = null,
|
||||
Object? keywords = null,
|
||||
Object? query = null,
|
||||
Object? loading = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
connections: null == connections
|
||||
@@ -1333,6 +1583,10 @@ class _$ConnectionsStateCopyWithImpl<$Res, $Val extends ConnectionsState>
|
||||
? _value.query
|
||||
: query // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
loading: null == loading
|
||||
? _value.loading
|
||||
: loading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
@@ -1346,7 +1600,10 @@ abstract class _$$ConnectionsStateImplCopyWith<$Res>
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{List<Connection> connections, List<String> keywords, String query});
|
||||
{List<Connection> connections,
|
||||
List<String> keywords,
|
||||
String query,
|
||||
bool loading});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -1365,6 +1622,7 @@ class __$$ConnectionsStateImplCopyWithImpl<$Res>
|
||||
Object? connections = null,
|
||||
Object? keywords = null,
|
||||
Object? query = null,
|
||||
Object? loading = null,
|
||||
}) {
|
||||
return _then(_$ConnectionsStateImpl(
|
||||
connections: null == connections
|
||||
@@ -1379,6 +1637,10 @@ class __$$ConnectionsStateImplCopyWithImpl<$Res>
|
||||
? _value.query
|
||||
: query // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
loading: null == loading
|
||||
? _value.loading
|
||||
: loading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1389,7 +1651,8 @@ class _$ConnectionsStateImpl implements _ConnectionsState {
|
||||
const _$ConnectionsStateImpl(
|
||||
{final List<Connection> connections = const [],
|
||||
final List<String> keywords = const [],
|
||||
this.query = ""})
|
||||
this.query = "",
|
||||
this.loading = false})
|
||||
: _connections = connections,
|
||||
_keywords = keywords;
|
||||
|
||||
@@ -1414,10 +1677,13 @@ class _$ConnectionsStateImpl implements _ConnectionsState {
|
||||
@override
|
||||
@JsonKey()
|
||||
final String query;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool loading;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ConnectionsState(connections: $connections, keywords: $keywords, query: $query)';
|
||||
return 'ConnectionsState(connections: $connections, keywords: $keywords, query: $query, loading: $loading)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -1428,7 +1694,8 @@ class _$ConnectionsStateImpl implements _ConnectionsState {
|
||||
const DeepCollectionEquality()
|
||||
.equals(other._connections, _connections) &&
|
||||
const DeepCollectionEquality().equals(other._keywords, _keywords) &&
|
||||
(identical(other.query, query) || other.query == query));
|
||||
(identical(other.query, query) || other.query == query) &&
|
||||
(identical(other.loading, loading) || other.loading == loading));
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -1436,7 +1703,8 @@ class _$ConnectionsStateImpl implements _ConnectionsState {
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(_connections),
|
||||
const DeepCollectionEquality().hash(_keywords),
|
||||
query);
|
||||
query,
|
||||
loading);
|
||||
|
||||
/// Create a copy of ConnectionsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1452,7 +1720,8 @@ abstract class _ConnectionsState implements ConnectionsState {
|
||||
const factory _ConnectionsState(
|
||||
{final List<Connection> connections,
|
||||
final List<String> keywords,
|
||||
final String query}) = _$ConnectionsStateImpl;
|
||||
final String query,
|
||||
final bool loading}) = _$ConnectionsStateImpl;
|
||||
|
||||
@override
|
||||
List<Connection> get connections;
|
||||
@@ -1460,6 +1729,8 @@ abstract class _ConnectionsState implements ConnectionsState {
|
||||
List<String> get keywords;
|
||||
@override
|
||||
String get query;
|
||||
@override
|
||||
bool get loading;
|
||||
|
||||
/// Create a copy of ConnectionsState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -2955,3 +3226,243 @@ abstract class _Field implements Field {
|
||||
_$$FieldImplCopyWith<_$FieldImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
TextPainterParams _$TextPainterParamsFromJson(Map<String, dynamic> json) {
|
||||
return _TextPainterParams.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$TextPainterParams {
|
||||
String? get text => throw _privateConstructorUsedError;
|
||||
double? get fontSize => throw _privateConstructorUsedError;
|
||||
double get textScaleFactor => throw _privateConstructorUsedError;
|
||||
double get maxWidth => throw _privateConstructorUsedError;
|
||||
int? get maxLines => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this TextPainterParams to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of TextPainterParams
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$TextPainterParamsCopyWith<TextPainterParams> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $TextPainterParamsCopyWith<$Res> {
|
||||
factory $TextPainterParamsCopyWith(
|
||||
TextPainterParams value, $Res Function(TextPainterParams) then) =
|
||||
_$TextPainterParamsCopyWithImpl<$Res, TextPainterParams>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{String? text,
|
||||
double? fontSize,
|
||||
double textScaleFactor,
|
||||
double maxWidth,
|
||||
int? maxLines});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$TextPainterParamsCopyWithImpl<$Res, $Val extends TextPainterParams>
|
||||
implements $TextPainterParamsCopyWith<$Res> {
|
||||
_$TextPainterParamsCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of TextPainterParams
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? text = freezed,
|
||||
Object? fontSize = freezed,
|
||||
Object? textScaleFactor = null,
|
||||
Object? maxWidth = null,
|
||||
Object? maxLines = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
text: freezed == text
|
||||
? _value.text
|
||||
: text // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
fontSize: freezed == fontSize
|
||||
? _value.fontSize
|
||||
: fontSize // ignore: cast_nullable_to_non_nullable
|
||||
as double?,
|
||||
textScaleFactor: null == textScaleFactor
|
||||
? _value.textScaleFactor
|
||||
: textScaleFactor // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
maxWidth: null == maxWidth
|
||||
? _value.maxWidth
|
||||
: maxWidth // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
maxLines: freezed == maxLines
|
||||
? _value.maxLines
|
||||
: maxLines // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$TextPainterParamsImplCopyWith<$Res>
|
||||
implements $TextPainterParamsCopyWith<$Res> {
|
||||
factory _$$TextPainterParamsImplCopyWith(_$TextPainterParamsImpl value,
|
||||
$Res Function(_$TextPainterParamsImpl) then) =
|
||||
__$$TextPainterParamsImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{String? text,
|
||||
double? fontSize,
|
||||
double textScaleFactor,
|
||||
double maxWidth,
|
||||
int? maxLines});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$TextPainterParamsImplCopyWithImpl<$Res>
|
||||
extends _$TextPainterParamsCopyWithImpl<$Res, _$TextPainterParamsImpl>
|
||||
implements _$$TextPainterParamsImplCopyWith<$Res> {
|
||||
__$$TextPainterParamsImplCopyWithImpl(_$TextPainterParamsImpl _value,
|
||||
$Res Function(_$TextPainterParamsImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of TextPainterParams
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? text = freezed,
|
||||
Object? fontSize = freezed,
|
||||
Object? textScaleFactor = null,
|
||||
Object? maxWidth = null,
|
||||
Object? maxLines = freezed,
|
||||
}) {
|
||||
return _then(_$TextPainterParamsImpl(
|
||||
text: freezed == text
|
||||
? _value.text
|
||||
: text // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
fontSize: freezed == fontSize
|
||||
? _value.fontSize
|
||||
: fontSize // ignore: cast_nullable_to_non_nullable
|
||||
as double?,
|
||||
textScaleFactor: null == textScaleFactor
|
||||
? _value.textScaleFactor
|
||||
: textScaleFactor // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
maxWidth: null == maxWidth
|
||||
? _value.maxWidth
|
||||
: maxWidth // ignore: cast_nullable_to_non_nullable
|
||||
as double,
|
||||
maxLines: freezed == maxLines
|
||||
? _value.maxLines
|
||||
: maxLines // ignore: cast_nullable_to_non_nullable
|
||||
as int?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$TextPainterParamsImpl implements _TextPainterParams {
|
||||
const _$TextPainterParamsImpl(
|
||||
{required this.text,
|
||||
required this.fontSize,
|
||||
required this.textScaleFactor,
|
||||
this.maxWidth = double.infinity,
|
||||
this.maxLines});
|
||||
|
||||
factory _$TextPainterParamsImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$TextPainterParamsImplFromJson(json);
|
||||
|
||||
@override
|
||||
final String? text;
|
||||
@override
|
||||
final double? fontSize;
|
||||
@override
|
||||
final double textScaleFactor;
|
||||
@override
|
||||
@JsonKey()
|
||||
final double maxWidth;
|
||||
@override
|
||||
final int? maxLines;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TextPainterParams(text: $text, fontSize: $fontSize, textScaleFactor: $textScaleFactor, maxWidth: $maxWidth, maxLines: $maxLines)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$TextPainterParamsImpl &&
|
||||
(identical(other.text, text) || other.text == text) &&
|
||||
(identical(other.fontSize, fontSize) ||
|
||||
other.fontSize == fontSize) &&
|
||||
(identical(other.textScaleFactor, textScaleFactor) ||
|
||||
other.textScaleFactor == textScaleFactor) &&
|
||||
(identical(other.maxWidth, maxWidth) ||
|
||||
other.maxWidth == maxWidth) &&
|
||||
(identical(other.maxLines, maxLines) ||
|
||||
other.maxLines == maxLines));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, text, fontSize, textScaleFactor, maxWidth, maxLines);
|
||||
|
||||
/// Create a copy of TextPainterParams
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$TextPainterParamsImplCopyWith<_$TextPainterParamsImpl> get copyWith =>
|
||||
__$$TextPainterParamsImplCopyWithImpl<_$TextPainterParamsImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$TextPainterParamsImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _TextPainterParams implements TextPainterParams {
|
||||
const factory _TextPainterParams(
|
||||
{required final String? text,
|
||||
required final double? fontSize,
|
||||
required final double textScaleFactor,
|
||||
final double maxWidth,
|
||||
final int? maxLines}) = _$TextPainterParamsImpl;
|
||||
|
||||
factory _TextPainterParams.fromJson(Map<String, dynamic> json) =
|
||||
_$TextPainterParamsImpl.fromJson;
|
||||
|
||||
@override
|
||||
String? get text;
|
||||
@override
|
||||
double? get fontSize;
|
||||
@override
|
||||
double get textScaleFactor;
|
||||
@override
|
||||
double get maxWidth;
|
||||
@override
|
||||
int? get maxLines;
|
||||
|
||||
/// Create a copy of TextPainterParams
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$TextPainterParamsImplCopyWith<_$TextPainterParamsImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
@@ -6,29 +6,12 @@ part of '../common.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
Log _$LogFromJson(Map<String, dynamic> json) => Log(
|
||||
logLevel: $enumDecode(_$LogLevelEnumMap, json['LogLevel']),
|
||||
payload: json['Payload'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LogToJson(Log instance) => <String, dynamic>{
|
||||
'LogLevel': _$LogLevelEnumMap[instance.logLevel]!,
|
||||
'Payload': instance.payload,
|
||||
};
|
||||
|
||||
const _$LogLevelEnumMap = {
|
||||
LogLevel.debug: 'debug',
|
||||
LogLevel.info: 'info',
|
||||
LogLevel.warning: 'warning',
|
||||
LogLevel.error: 'error',
|
||||
LogLevel.silent: 'silent',
|
||||
};
|
||||
|
||||
_$PackageImpl _$$PackageImplFromJson(Map<String, dynamic> json) =>
|
||||
_$PackageImpl(
|
||||
packageName: json['packageName'] as String,
|
||||
label: json['label'] as String,
|
||||
isSystem: json['isSystem'] as bool,
|
||||
system: json['system'] as bool,
|
||||
internet: json['internet'] as bool,
|
||||
lastUpdateTime: (json['lastUpdateTime'] as num).toInt(),
|
||||
);
|
||||
|
||||
@@ -36,7 +19,8 @@ Map<String, dynamic> _$$PackageImplToJson(_$PackageImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'packageName': instance.packageName,
|
||||
'label': instance.label,
|
||||
'isSystem': instance.isSystem,
|
||||
'system': instance.system,
|
||||
'internet': instance.internet,
|
||||
'lastUpdateTime': instance.lastUpdateTime,
|
||||
};
|
||||
|
||||
@@ -87,6 +71,28 @@ Map<String, dynamic> _$$ConnectionImplToJson(_$ConnectionImpl instance) =>
|
||||
'chains': instance.chains,
|
||||
};
|
||||
|
||||
_$LogImpl _$$LogImplFromJson(Map<String, dynamic> json) => _$LogImpl(
|
||||
logLevel: $enumDecodeNullable(_$LogLevelEnumMap, json['LogLevel']) ??
|
||||
LogLevel.app,
|
||||
payload: json['Payload'] as String? ?? "",
|
||||
dateTime: _logDateTime(json['dateTime']),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$LogImplToJson(_$LogImpl instance) => <String, dynamic>{
|
||||
'LogLevel': _$LogLevelEnumMap[instance.logLevel]!,
|
||||
'Payload': instance.payload,
|
||||
'dateTime': instance.dateTime,
|
||||
};
|
||||
|
||||
const _$LogLevelEnumMap = {
|
||||
LogLevel.debug: 'debug',
|
||||
LogLevel.info: 'info',
|
||||
LogLevel.warning: 'warning',
|
||||
LogLevel.error: 'error',
|
||||
LogLevel.silent: 'silent',
|
||||
LogLevel.app: 'app',
|
||||
};
|
||||
|
||||
_$DAVImpl _$$DAVImplFromJson(Map<String, dynamic> json) => _$DAVImpl(
|
||||
uri: json['uri'] as String,
|
||||
user: json['user'] as String,
|
||||
@@ -192,3 +198,23 @@ const _$KeyboardModifierEnumMap = {
|
||||
KeyboardModifier.meta: 'meta',
|
||||
KeyboardModifier.shift: 'shift',
|
||||
};
|
||||
|
||||
_$TextPainterParamsImpl _$$TextPainterParamsImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$TextPainterParamsImpl(
|
||||
text: json['text'] as String?,
|
||||
fontSize: (json['fontSize'] as num?)?.toDouble(),
|
||||
textScaleFactor: (json['textScaleFactor'] as num).toDouble(),
|
||||
maxWidth: (json['maxWidth'] as num?)?.toDouble() ?? double.infinity,
|
||||
maxLines: (json['maxLines'] as num?)?.toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$TextPainterParamsImplToJson(
|
||||
_$TextPainterParamsImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'text': instance.text,
|
||||
'fontSize': instance.fontSize,
|
||||
'textScaleFactor': instance.textScaleFactor,
|
||||
'maxWidth': instance.maxWidth,
|
||||
'maxLines': instance.maxLines,
|
||||
};
|
||||
|
||||
@@ -37,6 +37,8 @@ mixin _$AppSettingProps {
|
||||
bool get disclaimerAccepted => throw _privateConstructorUsedError;
|
||||
bool get minimizeOnExit => throw _privateConstructorUsedError;
|
||||
bool get hidden => throw _privateConstructorUsedError;
|
||||
bool get developerMode => throw _privateConstructorUsedError;
|
||||
RecoveryStrategy get recoveryStrategy => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this AppSettingProps to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@@ -70,7 +72,9 @@ abstract class $AppSettingPropsCopyWith<$Res> {
|
||||
bool showLabel,
|
||||
bool disclaimerAccepted,
|
||||
bool minimizeOnExit,
|
||||
bool hidden});
|
||||
bool hidden,
|
||||
bool developerMode,
|
||||
RecoveryStrategy recoveryStrategy});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -103,6 +107,8 @@ class _$AppSettingPropsCopyWithImpl<$Res, $Val extends AppSettingProps>
|
||||
Object? disclaimerAccepted = null,
|
||||
Object? minimizeOnExit = null,
|
||||
Object? hidden = null,
|
||||
Object? developerMode = null,
|
||||
Object? recoveryStrategy = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
locale: freezed == locale
|
||||
@@ -165,6 +171,14 @@ class _$AppSettingPropsCopyWithImpl<$Res, $Val extends AppSettingProps>
|
||||
? _value.hidden
|
||||
: hidden // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
developerMode: null == developerMode
|
||||
? _value.developerMode
|
||||
: developerMode // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
recoveryStrategy: null == recoveryStrategy
|
||||
? _value.recoveryStrategy
|
||||
: recoveryStrategy // ignore: cast_nullable_to_non_nullable
|
||||
as RecoveryStrategy,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
@@ -193,7 +207,9 @@ abstract class _$$AppSettingPropsImplCopyWith<$Res>
|
||||
bool showLabel,
|
||||
bool disclaimerAccepted,
|
||||
bool minimizeOnExit,
|
||||
bool hidden});
|
||||
bool hidden,
|
||||
bool developerMode,
|
||||
RecoveryStrategy recoveryStrategy});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -224,6 +240,8 @@ class __$$AppSettingPropsImplCopyWithImpl<$Res>
|
||||
Object? disclaimerAccepted = null,
|
||||
Object? minimizeOnExit = null,
|
||||
Object? hidden = null,
|
||||
Object? developerMode = null,
|
||||
Object? recoveryStrategy = null,
|
||||
}) {
|
||||
return _then(_$AppSettingPropsImpl(
|
||||
locale: freezed == locale
|
||||
@@ -286,6 +304,14 @@ class __$$AppSettingPropsImplCopyWithImpl<$Res>
|
||||
? _value.hidden
|
||||
: hidden // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
developerMode: null == developerMode
|
||||
? _value.developerMode
|
||||
: developerMode // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
recoveryStrategy: null == recoveryStrategy
|
||||
? _value.recoveryStrategy
|
||||
: recoveryStrategy // ignore: cast_nullable_to_non_nullable
|
||||
as RecoveryStrategy,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -301,7 +327,7 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
|
||||
this.autoLaunch = false,
|
||||
this.silentLaunch = false,
|
||||
this.autoRun = false,
|
||||
this.openLogs = true,
|
||||
this.openLogs = false,
|
||||
this.closeConnections = true,
|
||||
this.testUrl = defaultTestUrl,
|
||||
this.isAnimateToPage = true,
|
||||
@@ -309,7 +335,9 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
|
||||
this.showLabel = false,
|
||||
this.disclaimerAccepted = false,
|
||||
this.minimizeOnExit = true,
|
||||
this.hidden = false})
|
||||
this.hidden = false,
|
||||
this.developerMode = false,
|
||||
this.recoveryStrategy = RecoveryStrategy.compatible})
|
||||
: _dashboardWidgets = dashboardWidgets;
|
||||
|
||||
factory _$AppSettingPropsImpl.fromJson(Map<String, dynamic> json) =>
|
||||
@@ -366,10 +394,16 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool hidden;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool developerMode;
|
||||
@override
|
||||
@JsonKey()
|
||||
final RecoveryStrategy recoveryStrategy;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppSettingProps(locale: $locale, dashboardWidgets: $dashboardWidgets, onlyStatisticsProxy: $onlyStatisticsProxy, autoLaunch: $autoLaunch, silentLaunch: $silentLaunch, autoRun: $autoRun, openLogs: $openLogs, closeConnections: $closeConnections, testUrl: $testUrl, isAnimateToPage: $isAnimateToPage, autoCheckUpdate: $autoCheckUpdate, showLabel: $showLabel, disclaimerAccepted: $disclaimerAccepted, minimizeOnExit: $minimizeOnExit, hidden: $hidden)';
|
||||
return 'AppSettingProps(locale: $locale, dashboardWidgets: $dashboardWidgets, onlyStatisticsProxy: $onlyStatisticsProxy, autoLaunch: $autoLaunch, silentLaunch: $silentLaunch, autoRun: $autoRun, openLogs: $openLogs, closeConnections: $closeConnections, testUrl: $testUrl, isAnimateToPage: $isAnimateToPage, autoCheckUpdate: $autoCheckUpdate, showLabel: $showLabel, disclaimerAccepted: $disclaimerAccepted, minimizeOnExit: $minimizeOnExit, hidden: $hidden, developerMode: $developerMode, recoveryStrategy: $recoveryStrategy)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -402,7 +436,11 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
|
||||
other.disclaimerAccepted == disclaimerAccepted) &&
|
||||
(identical(other.minimizeOnExit, minimizeOnExit) ||
|
||||
other.minimizeOnExit == minimizeOnExit) &&
|
||||
(identical(other.hidden, hidden) || other.hidden == hidden));
|
||||
(identical(other.hidden, hidden) || other.hidden == hidden) &&
|
||||
(identical(other.developerMode, developerMode) ||
|
||||
other.developerMode == developerMode) &&
|
||||
(identical(other.recoveryStrategy, recoveryStrategy) ||
|
||||
other.recoveryStrategy == recoveryStrategy));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -423,7 +461,9 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
|
||||
showLabel,
|
||||
disclaimerAccepted,
|
||||
minimizeOnExit,
|
||||
hidden);
|
||||
hidden,
|
||||
developerMode,
|
||||
recoveryStrategy);
|
||||
|
||||
/// Create a copy of AppSettingProps
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -459,7 +499,9 @@ abstract class _AppSettingProps implements AppSettingProps {
|
||||
final bool showLabel,
|
||||
final bool disclaimerAccepted,
|
||||
final bool minimizeOnExit,
|
||||
final bool hidden}) = _$AppSettingPropsImpl;
|
||||
final bool hidden,
|
||||
final bool developerMode,
|
||||
final RecoveryStrategy recoveryStrategy}) = _$AppSettingPropsImpl;
|
||||
|
||||
factory _AppSettingProps.fromJson(Map<String, dynamic> json) =
|
||||
_$AppSettingPropsImpl.fromJson;
|
||||
@@ -495,6 +537,10 @@ abstract class _AppSettingProps implements AppSettingProps {
|
||||
bool get minimizeOnExit;
|
||||
@override
|
||||
bool get hidden;
|
||||
@override
|
||||
bool get developerMode;
|
||||
@override
|
||||
RecoveryStrategy get recoveryStrategy;
|
||||
|
||||
/// Create a copy of AppSettingProps
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -516,6 +562,7 @@ mixin _$AccessControl {
|
||||
List<String> get rejectList => throw _privateConstructorUsedError;
|
||||
AccessSortType get sort => throw _privateConstructorUsedError;
|
||||
bool get isFilterSystemApp => throw _privateConstructorUsedError;
|
||||
bool get isFilterNonInternetApp => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this AccessControl to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@@ -539,7 +586,8 @@ abstract class $AccessControlCopyWith<$Res> {
|
||||
List<String> acceptList,
|
||||
List<String> rejectList,
|
||||
AccessSortType sort,
|
||||
bool isFilterSystemApp});
|
||||
bool isFilterSystemApp,
|
||||
bool isFilterNonInternetApp});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -563,6 +611,7 @@ class _$AccessControlCopyWithImpl<$Res, $Val extends AccessControl>
|
||||
Object? rejectList = null,
|
||||
Object? sort = null,
|
||||
Object? isFilterSystemApp = null,
|
||||
Object? isFilterNonInternetApp = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
enable: null == enable
|
||||
@@ -589,6 +638,10 @@ class _$AccessControlCopyWithImpl<$Res, $Val extends AccessControl>
|
||||
? _value.isFilterSystemApp
|
||||
: isFilterSystemApp // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
isFilterNonInternetApp: null == isFilterNonInternetApp
|
||||
? _value.isFilterNonInternetApp
|
||||
: isFilterNonInternetApp // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
@@ -607,7 +660,8 @@ abstract class _$$AccessControlImplCopyWith<$Res>
|
||||
List<String> acceptList,
|
||||
List<String> rejectList,
|
||||
AccessSortType sort,
|
||||
bool isFilterSystemApp});
|
||||
bool isFilterSystemApp,
|
||||
bool isFilterNonInternetApp});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -629,6 +683,7 @@ class __$$AccessControlImplCopyWithImpl<$Res>
|
||||
Object? rejectList = null,
|
||||
Object? sort = null,
|
||||
Object? isFilterSystemApp = null,
|
||||
Object? isFilterNonInternetApp = null,
|
||||
}) {
|
||||
return _then(_$AccessControlImpl(
|
||||
enable: null == enable
|
||||
@@ -655,6 +710,10 @@ class __$$AccessControlImplCopyWithImpl<$Res>
|
||||
? _value.isFilterSystemApp
|
||||
: isFilterSystemApp // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
isFilterNonInternetApp: null == isFilterNonInternetApp
|
||||
? _value.isFilterNonInternetApp
|
||||
: isFilterNonInternetApp // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -668,7 +727,8 @@ class _$AccessControlImpl implements _AccessControl {
|
||||
final List<String> acceptList = const [],
|
||||
final List<String> rejectList = const [],
|
||||
this.sort = AccessSortType.none,
|
||||
this.isFilterSystemApp = true})
|
||||
this.isFilterSystemApp = true,
|
||||
this.isFilterNonInternetApp = true})
|
||||
: _acceptList = acceptList,
|
||||
_rejectList = rejectList;
|
||||
|
||||
@@ -705,10 +765,13 @@ class _$AccessControlImpl implements _AccessControl {
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool isFilterSystemApp;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool isFilterNonInternetApp;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AccessControl(enable: $enable, mode: $mode, acceptList: $acceptList, rejectList: $rejectList, sort: $sort, isFilterSystemApp: $isFilterSystemApp)';
|
||||
return 'AccessControl(enable: $enable, mode: $mode, acceptList: $acceptList, rejectList: $rejectList, sort: $sort, isFilterSystemApp: $isFilterSystemApp, isFilterNonInternetApp: $isFilterNonInternetApp)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -724,7 +787,9 @@ class _$AccessControlImpl implements _AccessControl {
|
||||
.equals(other._rejectList, _rejectList) &&
|
||||
(identical(other.sort, sort) || other.sort == sort) &&
|
||||
(identical(other.isFilterSystemApp, isFilterSystemApp) ||
|
||||
other.isFilterSystemApp == isFilterSystemApp));
|
||||
other.isFilterSystemApp == isFilterSystemApp) &&
|
||||
(identical(other.isFilterNonInternetApp, isFilterNonInternetApp) ||
|
||||
other.isFilterNonInternetApp == isFilterNonInternetApp));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -736,7 +801,8 @@ class _$AccessControlImpl implements _AccessControl {
|
||||
const DeepCollectionEquality().hash(_acceptList),
|
||||
const DeepCollectionEquality().hash(_rejectList),
|
||||
sort,
|
||||
isFilterSystemApp);
|
||||
isFilterSystemApp,
|
||||
isFilterNonInternetApp);
|
||||
|
||||
/// Create a copy of AccessControl
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -761,7 +827,8 @@ abstract class _AccessControl implements AccessControl {
|
||||
final List<String> acceptList,
|
||||
final List<String> rejectList,
|
||||
final AccessSortType sort,
|
||||
final bool isFilterSystemApp}) = _$AccessControlImpl;
|
||||
final bool isFilterSystemApp,
|
||||
final bool isFilterNonInternetApp}) = _$AccessControlImpl;
|
||||
|
||||
factory _AccessControl.fromJson(Map<String, dynamic> json) =
|
||||
_$AccessControlImpl.fromJson;
|
||||
@@ -778,6 +845,8 @@ abstract class _AccessControl implements AccessControl {
|
||||
AccessSortType get sort;
|
||||
@override
|
||||
bool get isFilterSystemApp;
|
||||
@override
|
||||
bool get isFilterNonInternetApp;
|
||||
|
||||
/// Create a copy of AccessControl
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1717,6 +1786,170 @@ abstract class _ProxiesStyle implements ProxiesStyle {
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
TextScale _$TextScaleFromJson(Map<String, dynamic> json) {
|
||||
return _TextScale.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$TextScale {
|
||||
dynamic get enable => throw _privateConstructorUsedError;
|
||||
dynamic get scale => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this TextScale to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of TextScale
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$TextScaleCopyWith<TextScale> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $TextScaleCopyWith<$Res> {
|
||||
factory $TextScaleCopyWith(TextScale value, $Res Function(TextScale) then) =
|
||||
_$TextScaleCopyWithImpl<$Res, TextScale>;
|
||||
@useResult
|
||||
$Res call({dynamic enable, dynamic scale});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$TextScaleCopyWithImpl<$Res, $Val extends TextScale>
|
||||
implements $TextScaleCopyWith<$Res> {
|
||||
_$TextScaleCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of TextScale
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? enable = freezed,
|
||||
Object? scale = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
enable: freezed == enable
|
||||
? _value.enable
|
||||
: enable // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,
|
||||
scale: freezed == scale
|
||||
? _value.scale
|
||||
: scale // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$TextScaleImplCopyWith<$Res>
|
||||
implements $TextScaleCopyWith<$Res> {
|
||||
factory _$$TextScaleImplCopyWith(
|
||||
_$TextScaleImpl value, $Res Function(_$TextScaleImpl) then) =
|
||||
__$$TextScaleImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({dynamic enable, dynamic scale});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$TextScaleImplCopyWithImpl<$Res>
|
||||
extends _$TextScaleCopyWithImpl<$Res, _$TextScaleImpl>
|
||||
implements _$$TextScaleImplCopyWith<$Res> {
|
||||
__$$TextScaleImplCopyWithImpl(
|
||||
_$TextScaleImpl _value, $Res Function(_$TextScaleImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of TextScale
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? enable = freezed,
|
||||
Object? scale = freezed,
|
||||
}) {
|
||||
return _then(_$TextScaleImpl(
|
||||
enable: freezed == enable ? _value.enable! : enable,
|
||||
scale: freezed == scale ? _value.scale! : scale,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$TextScaleImpl implements _TextScale {
|
||||
const _$TextScaleImpl({this.enable = false, this.scale = 1.0});
|
||||
|
||||
factory _$TextScaleImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$TextScaleImplFromJson(json);
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final dynamic enable;
|
||||
@override
|
||||
@JsonKey()
|
||||
final dynamic scale;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TextScale(enable: $enable, scale: $scale)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$TextScaleImpl &&
|
||||
const DeepCollectionEquality().equals(other.enable, enable) &&
|
||||
const DeepCollectionEquality().equals(other.scale, scale));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(enable),
|
||||
const DeepCollectionEquality().hash(scale));
|
||||
|
||||
/// Create a copy of TextScale
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$TextScaleImplCopyWith<_$TextScaleImpl> get copyWith =>
|
||||
__$$TextScaleImplCopyWithImpl<_$TextScaleImpl>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$TextScaleImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _TextScale implements TextScale {
|
||||
const factory _TextScale({final dynamic enable, final dynamic scale}) =
|
||||
_$TextScaleImpl;
|
||||
|
||||
factory _TextScale.fromJson(Map<String, dynamic> json) =
|
||||
_$TextScaleImpl.fromJson;
|
||||
|
||||
@override
|
||||
dynamic get enable;
|
||||
@override
|
||||
dynamic get scale;
|
||||
|
||||
/// Create a copy of TextScale
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$TextScaleImplCopyWith<_$TextScaleImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
ThemeProps _$ThemePropsFromJson(Map<String, dynamic> json) {
|
||||
return _ThemeProps.fromJson(json);
|
||||
}
|
||||
@@ -1728,6 +1961,7 @@ mixin _$ThemeProps {
|
||||
ThemeMode get themeMode => throw _privateConstructorUsedError;
|
||||
DynamicSchemeVariant get schemeVariant => throw _privateConstructorUsedError;
|
||||
bool get pureBlack => throw _privateConstructorUsedError;
|
||||
TextScale get textScale => throw _privateConstructorUsedError;
|
||||
|
||||
/// Serializes this ThemeProps to a JSON map.
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@@ -1750,7 +1984,10 @@ abstract class $ThemePropsCopyWith<$Res> {
|
||||
List<int> primaryColors,
|
||||
ThemeMode themeMode,
|
||||
DynamicSchemeVariant schemeVariant,
|
||||
bool pureBlack});
|
||||
bool pureBlack,
|
||||
TextScale textScale});
|
||||
|
||||
$TextScaleCopyWith<$Res> get textScale;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -1773,6 +2010,7 @@ class _$ThemePropsCopyWithImpl<$Res, $Val extends ThemeProps>
|
||||
Object? themeMode = null,
|
||||
Object? schemeVariant = null,
|
||||
Object? pureBlack = null,
|
||||
Object? textScale = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
primaryColor: freezed == primaryColor
|
||||
@@ -1795,8 +2033,22 @@ class _$ThemePropsCopyWithImpl<$Res, $Val extends ThemeProps>
|
||||
? _value.pureBlack
|
||||
: pureBlack // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
textScale: null == textScale
|
||||
? _value.textScale
|
||||
: textScale // ignore: cast_nullable_to_non_nullable
|
||||
as TextScale,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
/// Create a copy of ThemeProps
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$TextScaleCopyWith<$Res> get textScale {
|
||||
return $TextScaleCopyWith<$Res>(_value.textScale, (value) {
|
||||
return _then(_value.copyWith(textScale: value) as $Val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -1812,7 +2064,11 @@ abstract class _$$ThemePropsImplCopyWith<$Res>
|
||||
List<int> primaryColors,
|
||||
ThemeMode themeMode,
|
||||
DynamicSchemeVariant schemeVariant,
|
||||
bool pureBlack});
|
||||
bool pureBlack,
|
||||
TextScale textScale});
|
||||
|
||||
@override
|
||||
$TextScaleCopyWith<$Res> get textScale;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@@ -1833,6 +2089,7 @@ class __$$ThemePropsImplCopyWithImpl<$Res>
|
||||
Object? themeMode = null,
|
||||
Object? schemeVariant = null,
|
||||
Object? pureBlack = null,
|
||||
Object? textScale = null,
|
||||
}) {
|
||||
return _then(_$ThemePropsImpl(
|
||||
primaryColor: freezed == primaryColor
|
||||
@@ -1855,6 +2112,10 @@ class __$$ThemePropsImplCopyWithImpl<$Res>
|
||||
? _value.pureBlack
|
||||
: pureBlack // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
textScale: null == textScale
|
||||
? _value.textScale
|
||||
: textScale // ignore: cast_nullable_to_non_nullable
|
||||
as TextScale,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1863,18 +2124,18 @@ class __$$ThemePropsImplCopyWithImpl<$Res>
|
||||
@JsonSerializable()
|
||||
class _$ThemePropsImpl implements _ThemeProps {
|
||||
const _$ThemePropsImpl(
|
||||
{this.primaryColor = defaultPrimaryColor,
|
||||
{this.primaryColor,
|
||||
final List<int> primaryColors = defaultPrimaryColors,
|
||||
this.themeMode = ThemeMode.dark,
|
||||
this.schemeVariant = DynamicSchemeVariant.tonalSpot,
|
||||
this.pureBlack = false})
|
||||
this.schemeVariant = DynamicSchemeVariant.content,
|
||||
this.pureBlack = false,
|
||||
this.textScale = const TextScale()})
|
||||
: _primaryColors = primaryColors;
|
||||
|
||||
factory _$ThemePropsImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$ThemePropsImplFromJson(json);
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final int? primaryColor;
|
||||
final List<int> _primaryColors;
|
||||
@override
|
||||
@@ -1894,10 +2155,13 @@ class _$ThemePropsImpl implements _ThemeProps {
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool pureBlack;
|
||||
@override
|
||||
@JsonKey()
|
||||
final TextScale textScale;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ThemeProps(primaryColor: $primaryColor, primaryColors: $primaryColors, themeMode: $themeMode, schemeVariant: $schemeVariant, pureBlack: $pureBlack)';
|
||||
return 'ThemeProps(primaryColor: $primaryColor, primaryColors: $primaryColors, themeMode: $themeMode, schemeVariant: $schemeVariant, pureBlack: $pureBlack, textScale: $textScale)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -1914,7 +2178,9 @@ class _$ThemePropsImpl implements _ThemeProps {
|
||||
(identical(other.schemeVariant, schemeVariant) ||
|
||||
other.schemeVariant == schemeVariant) &&
|
||||
(identical(other.pureBlack, pureBlack) ||
|
||||
other.pureBlack == pureBlack));
|
||||
other.pureBlack == pureBlack) &&
|
||||
(identical(other.textScale, textScale) ||
|
||||
other.textScale == textScale));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -1925,7 +2191,8 @@ class _$ThemePropsImpl implements _ThemeProps {
|
||||
const DeepCollectionEquality().hash(_primaryColors),
|
||||
themeMode,
|
||||
schemeVariant,
|
||||
pureBlack);
|
||||
pureBlack,
|
||||
textScale);
|
||||
|
||||
/// Create a copy of ThemeProps
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1949,7 +2216,8 @@ abstract class _ThemeProps implements ThemeProps {
|
||||
final List<int> primaryColors,
|
||||
final ThemeMode themeMode,
|
||||
final DynamicSchemeVariant schemeVariant,
|
||||
final bool pureBlack}) = _$ThemePropsImpl;
|
||||
final bool pureBlack,
|
||||
final TextScale textScale}) = _$ThemePropsImpl;
|
||||
|
||||
factory _ThemeProps.fromJson(Map<String, dynamic> json) =
|
||||
_$ThemePropsImpl.fromJson;
|
||||
@@ -1964,6 +2232,8 @@ abstract class _ThemeProps implements ThemeProps {
|
||||
DynamicSchemeVariant get schemeVariant;
|
||||
@override
|
||||
bool get pureBlack;
|
||||
@override
|
||||
TextScale get textScale;
|
||||
|
||||
/// Create a copy of ThemeProps
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1988,6 +2258,7 @@ mixin _$Config {
|
||||
DAV? get dav => throw _privateConstructorUsedError;
|
||||
NetworkProps get networkProps => throw _privateConstructorUsedError;
|
||||
VpnProps get vpnProps => throw _privateConstructorUsedError;
|
||||
@JsonKey(fromJson: ThemeProps.safeFromJson)
|
||||
ThemeProps get themeProps => throw _privateConstructorUsedError;
|
||||
ProxiesStyle get proxiesStyle => throw _privateConstructorUsedError;
|
||||
WindowProps get windowProps => throw _privateConstructorUsedError;
|
||||
@@ -2017,7 +2288,7 @@ abstract class $ConfigCopyWith<$Res> {
|
||||
DAV? dav,
|
||||
NetworkProps networkProps,
|
||||
VpnProps vpnProps,
|
||||
ThemeProps themeProps,
|
||||
@JsonKey(fromJson: ThemeProps.safeFromJson) ThemeProps themeProps,
|
||||
ProxiesStyle proxiesStyle,
|
||||
WindowProps windowProps,
|
||||
ClashConfig patchClashConfig});
|
||||
@@ -2214,7 +2485,7 @@ abstract class _$$ConfigImplCopyWith<$Res> implements $ConfigCopyWith<$Res> {
|
||||
DAV? dav,
|
||||
NetworkProps networkProps,
|
||||
VpnProps vpnProps,
|
||||
ThemeProps themeProps,
|
||||
@JsonKey(fromJson: ThemeProps.safeFromJson) ThemeProps themeProps,
|
||||
ProxiesStyle proxiesStyle,
|
||||
WindowProps windowProps,
|
||||
ClashConfig patchClashConfig});
|
||||
@@ -2329,7 +2600,7 @@ class _$ConfigImpl implements _Config {
|
||||
this.dav,
|
||||
this.networkProps = defaultNetworkProps,
|
||||
this.vpnProps = defaultVpnProps,
|
||||
this.themeProps = defaultThemeProps,
|
||||
@JsonKey(fromJson: ThemeProps.safeFromJson) required this.themeProps,
|
||||
this.proxiesStyle = defaultProxiesStyle,
|
||||
this.windowProps = defaultWindowProps,
|
||||
this.patchClashConfig = defaultClashConfig})
|
||||
@@ -2374,7 +2645,7 @@ class _$ConfigImpl implements _Config {
|
||||
@JsonKey()
|
||||
final VpnProps vpnProps;
|
||||
@override
|
||||
@JsonKey()
|
||||
@JsonKey(fromJson: ThemeProps.safeFromJson)
|
||||
final ThemeProps themeProps;
|
||||
@override
|
||||
@JsonKey()
|
||||
@@ -2464,7 +2735,8 @@ abstract class _Config implements Config {
|
||||
final DAV? dav,
|
||||
final NetworkProps networkProps,
|
||||
final VpnProps vpnProps,
|
||||
final ThemeProps themeProps,
|
||||
@JsonKey(fromJson: ThemeProps.safeFromJson)
|
||||
required final ThemeProps themeProps,
|
||||
final ProxiesStyle proxiesStyle,
|
||||
final WindowProps windowProps,
|
||||
final ClashConfig patchClashConfig}) = _$ConfigImpl;
|
||||
@@ -2489,6 +2761,7 @@ abstract class _Config implements Config {
|
||||
@override
|
||||
VpnProps get vpnProps;
|
||||
@override
|
||||
@JsonKey(fromJson: ThemeProps.safeFromJson)
|
||||
ThemeProps get themeProps;
|
||||
@override
|
||||
ProxiesStyle get proxiesStyle;
|
||||
|
||||
@@ -17,7 +17,7 @@ _$AppSettingPropsImpl _$$AppSettingPropsImplFromJson(
|
||||
autoLaunch: json['autoLaunch'] as bool? ?? false,
|
||||
silentLaunch: json['silentLaunch'] as bool? ?? false,
|
||||
autoRun: json['autoRun'] as bool? ?? false,
|
||||
openLogs: json['openLogs'] as bool? ?? true,
|
||||
openLogs: json['openLogs'] as bool? ?? false,
|
||||
closeConnections: json['closeConnections'] as bool? ?? true,
|
||||
testUrl: json['testUrl'] as String? ?? defaultTestUrl,
|
||||
isAnimateToPage: json['isAnimateToPage'] as bool? ?? true,
|
||||
@@ -26,6 +26,10 @@ _$AppSettingPropsImpl _$$AppSettingPropsImplFromJson(
|
||||
disclaimerAccepted: json['disclaimerAccepted'] as bool? ?? false,
|
||||
minimizeOnExit: json['minimizeOnExit'] as bool? ?? true,
|
||||
hidden: json['hidden'] as bool? ?? false,
|
||||
developerMode: json['developerMode'] as bool? ?? false,
|
||||
recoveryStrategy: $enumDecodeNullable(
|
||||
_$RecoveryStrategyEnumMap, json['recoveryStrategy']) ??
|
||||
RecoveryStrategy.compatible,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$AppSettingPropsImplToJson(
|
||||
@@ -48,14 +52,23 @@ Map<String, dynamic> _$$AppSettingPropsImplToJson(
|
||||
'disclaimerAccepted': instance.disclaimerAccepted,
|
||||
'minimizeOnExit': instance.minimizeOnExit,
|
||||
'hidden': instance.hidden,
|
||||
'developerMode': instance.developerMode,
|
||||
'recoveryStrategy': _$RecoveryStrategyEnumMap[instance.recoveryStrategy]!,
|
||||
};
|
||||
|
||||
const _$RecoveryStrategyEnumMap = {
|
||||
RecoveryStrategy.compatible: 'compatible',
|
||||
RecoveryStrategy.override: 'override',
|
||||
};
|
||||
|
||||
const _$DashboardWidgetEnumMap = {
|
||||
DashboardWidget.networkSpeed: 'networkSpeed',
|
||||
DashboardWidget.outboundModeV2: 'outboundModeV2',
|
||||
DashboardWidget.outboundMode: 'outboundMode',
|
||||
DashboardWidget.trafficUsage: 'trafficUsage',
|
||||
DashboardWidget.networkDetection: 'networkDetection',
|
||||
DashboardWidget.tunButton: 'tunButton',
|
||||
DashboardWidget.vpnButton: 'vpnButton',
|
||||
DashboardWidget.systemProxyButton: 'systemProxyButton',
|
||||
DashboardWidget.intranetIp: 'intranetIp',
|
||||
DashboardWidget.memoryInfo: 'memoryInfo',
|
||||
@@ -77,6 +90,7 @@ _$AccessControlImpl _$$AccessControlImplFromJson(Map<String, dynamic> json) =>
|
||||
sort: $enumDecodeNullable(_$AccessSortTypeEnumMap, json['sort']) ??
|
||||
AccessSortType.none,
|
||||
isFilterSystemApp: json['isFilterSystemApp'] as bool? ?? true,
|
||||
isFilterNonInternetApp: json['isFilterNonInternetApp'] as bool? ?? true,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$AccessControlImplToJson(_$AccessControlImpl instance) =>
|
||||
@@ -87,6 +101,7 @@ Map<String, dynamic> _$$AccessControlImplToJson(_$AccessControlImpl instance) =>
|
||||
'rejectList': instance.rejectList,
|
||||
'sort': _$AccessSortTypeEnumMap[instance.sort]!,
|
||||
'isFilterSystemApp': instance.isFilterSystemApp,
|
||||
'isFilterNonInternetApp': instance.isFilterNonInternetApp,
|
||||
};
|
||||
|
||||
const _$AccessControlModeEnumMap = {
|
||||
@@ -219,10 +234,21 @@ const _$ProxyCardTypeEnumMap = {
|
||||
ProxyCardType.min: 'min',
|
||||
};
|
||||
|
||||
_$TextScaleImpl _$$TextScaleImplFromJson(Map<String, dynamic> json) =>
|
||||
_$TextScaleImpl(
|
||||
enable: json['enable'] ?? false,
|
||||
scale: json['scale'] ?? 1.0,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$TextScaleImplToJson(_$TextScaleImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'enable': instance.enable,
|
||||
'scale': instance.scale,
|
||||
};
|
||||
|
||||
_$ThemePropsImpl _$$ThemePropsImplFromJson(Map<String, dynamic> json) =>
|
||||
_$ThemePropsImpl(
|
||||
primaryColor:
|
||||
(json['primaryColor'] as num?)?.toInt() ?? defaultPrimaryColor,
|
||||
primaryColor: (json['primaryColor'] as num?)?.toInt(),
|
||||
primaryColors: (json['primaryColors'] as List<dynamic>?)
|
||||
?.map((e) => (e as num).toInt())
|
||||
.toList() ??
|
||||
@@ -231,8 +257,11 @@ _$ThemePropsImpl _$$ThemePropsImplFromJson(Map<String, dynamic> json) =>
|
||||
ThemeMode.dark,
|
||||
schemeVariant: $enumDecodeNullable(
|
||||
_$DynamicSchemeVariantEnumMap, json['schemeVariant']) ??
|
||||
DynamicSchemeVariant.tonalSpot,
|
||||
DynamicSchemeVariant.content,
|
||||
pureBlack: json['pureBlack'] as bool? ?? false,
|
||||
textScale: json['textScale'] == null
|
||||
? const TextScale()
|
||||
: TextScale.fromJson(json['textScale'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$ThemePropsImplToJson(_$ThemePropsImpl instance) =>
|
||||
@@ -242,6 +271,7 @@ Map<String, dynamic> _$$ThemePropsImplToJson(_$ThemePropsImpl instance) =>
|
||||
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
|
||||
'schemeVariant': _$DynamicSchemeVariantEnumMap[instance.schemeVariant]!,
|
||||
'pureBlack': instance.pureBlack,
|
||||
'textScale': instance.textScale,
|
||||
};
|
||||
|
||||
const _$ThemeModeEnumMap = {
|
||||
@@ -287,9 +317,8 @@ _$ConfigImpl _$$ConfigImplFromJson(Map<String, dynamic> json) => _$ConfigImpl(
|
||||
vpnProps: json['vpnProps'] == null
|
||||
? defaultVpnProps
|
||||
: VpnProps.fromJson(json['vpnProps'] as Map<String, dynamic>?),
|
||||
themeProps: json['themeProps'] == null
|
||||
? defaultThemeProps
|
||||
: ThemeProps.fromJson(json['themeProps'] as Map<String, dynamic>?),
|
||||
themeProps:
|
||||
ThemeProps.safeFromJson(json['themeProps'] as Map<String, Object?>?),
|
||||
proxiesStyle: json['proxiesStyle'] == null
|
||||
? defaultProxiesStyle
|
||||
: ProxiesStyle.fromJson(
|
||||
|
||||
@@ -345,6 +345,7 @@ const _$ActionMethodEnumMap = {
|
||||
ActionMethod.getCountryCode: 'getCountryCode',
|
||||
ActionMethod.getMemory: 'getMemory',
|
||||
ActionMethod.getProfile: 'getProfile',
|
||||
ActionMethod.crash: 'crash',
|
||||
ActionMethod.setFdMap: 'setFdMap',
|
||||
ActionMethod.setProcessMap: 'setProcessMap',
|
||||
ActionMethod.setState: 'setState',
|
||||
|
||||
@@ -327,6 +327,193 @@ abstract class _VM3<A, B, C> implements VM3<A, B, C> {
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$VM4<A, B, C, D> {
|
||||
A get a => throw _privateConstructorUsedError;
|
||||
B get b => throw _privateConstructorUsedError;
|
||||
C get c => throw _privateConstructorUsedError;
|
||||
D get d => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of VM4
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
$VM4CopyWith<A, B, C, D, VM4<A, B, C, D>> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $VM4CopyWith<A, B, C, D, $Res> {
|
||||
factory $VM4CopyWith(
|
||||
VM4<A, B, C, D> value, $Res Function(VM4<A, B, C, D>) then) =
|
||||
_$VM4CopyWithImpl<A, B, C, D, $Res, VM4<A, B, C, D>>;
|
||||
@useResult
|
||||
$Res call({A a, B b, C c, D d});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$VM4CopyWithImpl<A, B, C, D, $Res, $Val extends VM4<A, B, C, D>>
|
||||
implements $VM4CopyWith<A, B, C, D, $Res> {
|
||||
_$VM4CopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
/// Create a copy of VM4
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? a = freezed,
|
||||
Object? b = freezed,
|
||||
Object? c = freezed,
|
||||
Object? d = freezed,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
a: freezed == a
|
||||
? _value.a
|
||||
: a // ignore: cast_nullable_to_non_nullable
|
||||
as A,
|
||||
b: freezed == b
|
||||
? _value.b
|
||||
: b // ignore: cast_nullable_to_non_nullable
|
||||
as B,
|
||||
c: freezed == c
|
||||
? _value.c
|
||||
: c // ignore: cast_nullable_to_non_nullable
|
||||
as C,
|
||||
d: freezed == d
|
||||
? _value.d
|
||||
: d // ignore: cast_nullable_to_non_nullable
|
||||
as D,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$VM4ImplCopyWith<A, B, C, D, $Res>
|
||||
implements $VM4CopyWith<A, B, C, D, $Res> {
|
||||
factory _$$VM4ImplCopyWith(_$VM4Impl<A, B, C, D> value,
|
||||
$Res Function(_$VM4Impl<A, B, C, D>) then) =
|
||||
__$$VM4ImplCopyWithImpl<A, B, C, D, $Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call({A a, B b, C c, D d});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$VM4ImplCopyWithImpl<A, B, C, D, $Res>
|
||||
extends _$VM4CopyWithImpl<A, B, C, D, $Res, _$VM4Impl<A, B, C, D>>
|
||||
implements _$$VM4ImplCopyWith<A, B, C, D, $Res> {
|
||||
__$$VM4ImplCopyWithImpl(
|
||||
_$VM4Impl<A, B, C, D> _value, $Res Function(_$VM4Impl<A, B, C, D>) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
/// Create a copy of VM4
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? a = freezed,
|
||||
Object? b = freezed,
|
||||
Object? c = freezed,
|
||||
Object? d = freezed,
|
||||
}) {
|
||||
return _then(_$VM4Impl<A, B, C, D>(
|
||||
a: freezed == a
|
||||
? _value.a
|
||||
: a // ignore: cast_nullable_to_non_nullable
|
||||
as A,
|
||||
b: freezed == b
|
||||
? _value.b
|
||||
: b // ignore: cast_nullable_to_non_nullable
|
||||
as B,
|
||||
c: freezed == c
|
||||
? _value.c
|
||||
: c // ignore: cast_nullable_to_non_nullable
|
||||
as C,
|
||||
d: freezed == d
|
||||
? _value.d
|
||||
: d // ignore: cast_nullable_to_non_nullable
|
||||
as D,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$VM4Impl<A, B, C, D> implements _VM4<A, B, C, D> {
|
||||
const _$VM4Impl(
|
||||
{required this.a, required this.b, required this.c, required this.d});
|
||||
|
||||
@override
|
||||
final A a;
|
||||
@override
|
||||
final B b;
|
||||
@override
|
||||
final C c;
|
||||
@override
|
||||
final D d;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'VM4<$A, $B, $C, $D>(a: $a, b: $b, c: $c, d: $d)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$VM4Impl<A, B, C, D> &&
|
||||
const DeepCollectionEquality().equals(other.a, a) &&
|
||||
const DeepCollectionEquality().equals(other.b, b) &&
|
||||
const DeepCollectionEquality().equals(other.c, c) &&
|
||||
const DeepCollectionEquality().equals(other.d, d));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType,
|
||||
const DeepCollectionEquality().hash(a),
|
||||
const DeepCollectionEquality().hash(b),
|
||||
const DeepCollectionEquality().hash(c),
|
||||
const DeepCollectionEquality().hash(d));
|
||||
|
||||
/// Create a copy of VM4
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$VM4ImplCopyWith<A, B, C, D, _$VM4Impl<A, B, C, D>> get copyWith =>
|
||||
__$$VM4ImplCopyWithImpl<A, B, C, D, _$VM4Impl<A, B, C, D>>(
|
||||
this, _$identity);
|
||||
}
|
||||
|
||||
abstract class _VM4<A, B, C, D> implements VM4<A, B, C, D> {
|
||||
const factory _VM4(
|
||||
{required final A a,
|
||||
required final B b,
|
||||
required final C c,
|
||||
required final D d}) = _$VM4Impl<A, B, C, D>;
|
||||
|
||||
@override
|
||||
A get a;
|
||||
@override
|
||||
B get b;
|
||||
@override
|
||||
C get c;
|
||||
@override
|
||||
D get d;
|
||||
|
||||
/// Create a copy of VM4
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
_$$VM4ImplCopyWith<A, B, C, D, _$VM4Impl<A, B, C, D>> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$StartButtonSelectorState {
|
||||
bool get isInit => throw _privateConstructorUsedError;
|
||||
@@ -3335,6 +3522,7 @@ mixin _$ClashConfigState {
|
||||
bool get overrideDns => throw _privateConstructorUsedError;
|
||||
ClashConfig get clashConfig => throw _privateConstructorUsedError;
|
||||
OverrideData get overrideData => throw _privateConstructorUsedError;
|
||||
RouteMode get routeMode => throw _privateConstructorUsedError;
|
||||
|
||||
/// Create a copy of ClashConfigState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -3350,7 +3538,10 @@ abstract class $ClashConfigStateCopyWith<$Res> {
|
||||
_$ClashConfigStateCopyWithImpl<$Res, ClashConfigState>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{bool overrideDns, ClashConfig clashConfig, OverrideData overrideData});
|
||||
{bool overrideDns,
|
||||
ClashConfig clashConfig,
|
||||
OverrideData overrideData,
|
||||
RouteMode routeMode});
|
||||
|
||||
$ClashConfigCopyWith<$Res> get clashConfig;
|
||||
$OverrideDataCopyWith<$Res> get overrideData;
|
||||
@@ -3374,6 +3565,7 @@ class _$ClashConfigStateCopyWithImpl<$Res, $Val extends ClashConfigState>
|
||||
Object? overrideDns = null,
|
||||
Object? clashConfig = null,
|
||||
Object? overrideData = null,
|
||||
Object? routeMode = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
overrideDns: null == overrideDns
|
||||
@@ -3388,6 +3580,10 @@ class _$ClashConfigStateCopyWithImpl<$Res, $Val extends ClashConfigState>
|
||||
? _value.overrideData
|
||||
: overrideData // ignore: cast_nullable_to_non_nullable
|
||||
as OverrideData,
|
||||
routeMode: null == routeMode
|
||||
? _value.routeMode
|
||||
: routeMode // ignore: cast_nullable_to_non_nullable
|
||||
as RouteMode,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
@@ -3421,7 +3617,10 @@ abstract class _$$ClashConfigStateImplCopyWith<$Res>
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{bool overrideDns, ClashConfig clashConfig, OverrideData overrideData});
|
||||
{bool overrideDns,
|
||||
ClashConfig clashConfig,
|
||||
OverrideData overrideData,
|
||||
RouteMode routeMode});
|
||||
|
||||
@override
|
||||
$ClashConfigCopyWith<$Res> get clashConfig;
|
||||
@@ -3445,6 +3644,7 @@ class __$$ClashConfigStateImplCopyWithImpl<$Res>
|
||||
Object? overrideDns = null,
|
||||
Object? clashConfig = null,
|
||||
Object? overrideData = null,
|
||||
Object? routeMode = null,
|
||||
}) {
|
||||
return _then(_$ClashConfigStateImpl(
|
||||
overrideDns: null == overrideDns
|
||||
@@ -3459,6 +3659,10 @@ class __$$ClashConfigStateImplCopyWithImpl<$Res>
|
||||
? _value.overrideData
|
||||
: overrideData // ignore: cast_nullable_to_non_nullable
|
||||
as OverrideData,
|
||||
routeMode: null == routeMode
|
||||
? _value.routeMode
|
||||
: routeMode // ignore: cast_nullable_to_non_nullable
|
||||
as RouteMode,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -3469,7 +3673,8 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
const _$ClashConfigStateImpl(
|
||||
{required this.overrideDns,
|
||||
required this.clashConfig,
|
||||
required this.overrideData});
|
||||
required this.overrideData,
|
||||
required this.routeMode});
|
||||
|
||||
@override
|
||||
final bool overrideDns;
|
||||
@@ -3477,10 +3682,12 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
final ClashConfig clashConfig;
|
||||
@override
|
||||
final OverrideData overrideData;
|
||||
@override
|
||||
final RouteMode routeMode;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ClashConfigState(overrideDns: $overrideDns, clashConfig: $clashConfig, overrideData: $overrideData)';
|
||||
return 'ClashConfigState(overrideDns: $overrideDns, clashConfig: $clashConfig, overrideData: $overrideData, routeMode: $routeMode)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -3493,12 +3700,14 @@ class _$ClashConfigStateImpl implements _ClashConfigState {
|
||||
(identical(other.clashConfig, clashConfig) ||
|
||||
other.clashConfig == clashConfig) &&
|
||||
(identical(other.overrideData, overrideData) ||
|
||||
other.overrideData == overrideData));
|
||||
other.overrideData == overrideData) &&
|
||||
(identical(other.routeMode, routeMode) ||
|
||||
other.routeMode == routeMode));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, overrideDns, clashConfig, overrideData);
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, overrideDns, clashConfig, overrideData, routeMode);
|
||||
|
||||
/// Create a copy of ClashConfigState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -3514,7 +3723,8 @@ abstract class _ClashConfigState implements ClashConfigState {
|
||||
const factory _ClashConfigState(
|
||||
{required final bool overrideDns,
|
||||
required final ClashConfig clashConfig,
|
||||
required final OverrideData overrideData}) = _$ClashConfigStateImpl;
|
||||
required final OverrideData overrideData,
|
||||
required final RouteMode routeMode}) = _$ClashConfigStateImpl;
|
||||
|
||||
@override
|
||||
bool get overrideDns;
|
||||
@@ -3522,6 +3732,8 @@ abstract class _ClashConfigState implements ClashConfigState {
|
||||
ClashConfig get clashConfig;
|
||||
@override
|
||||
OverrideData get overrideData;
|
||||
@override
|
||||
RouteMode get routeMode;
|
||||
|
||||
/// Create a copy of ClashConfigState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
|
||||
@@ -24,6 +24,17 @@ class VM3<A, B, C> with _$VM3<A, B, C> {
|
||||
}) = _VM3;
|
||||
}
|
||||
|
||||
@freezed
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@freezed
|
||||
class StartButtonSelectorState with _$StartButtonSelectorState {
|
||||
const factory StartButtonSelectorState({
|
||||
@@ -146,12 +157,21 @@ class PackageListSelectorState with _$PackageListSelectorState {
|
||||
}
|
||||
|
||||
extension PackageListSelectorStateExt on PackageListSelectorState {
|
||||
List<Package> getList(List<String> selectedList) {
|
||||
List<Package> get list {
|
||||
final isFilterSystemApp = accessControl.isFilterSystemApp;
|
||||
final sort = accessControl.sort;
|
||||
final isFilterNonInternetApp = accessControl.isFilterNonInternetApp;
|
||||
return packages
|
||||
.where((item) => isFilterSystemApp ? item.isSystem == false : true)
|
||||
.sorted(
|
||||
.where(
|
||||
(item) =>
|
||||
(isFilterSystemApp ? item.system == false : true) &&
|
||||
(isFilterNonInternetApp ? item.internet == true : true),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<Package> getSortList(List<String> selectedList) {
|
||||
final sort = accessControl.sort;
|
||||
return list.sorted(
|
||||
(a, b) {
|
||||
return switch (sort) {
|
||||
AccessSortType.none => 0,
|
||||
@@ -208,6 +228,7 @@ class ClashConfigState with _$ClashConfigState {
|
||||
required bool overrideDns,
|
||||
required ClashConfig clashConfig,
|
||||
required OverrideData overrideData,
|
||||
required RouteMode routeMode,
|
||||
}) = _ClashConfigState;
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ class _EditorPageState extends ConsumerState<EditorPage> {
|
||||
);
|
||||
},
|
||||
popup: CommonPopupMenu(
|
||||
minWidth: 180,
|
||||
items: [
|
||||
PopupMenuItemData(
|
||||
icon: Icons.search,
|
||||
@@ -189,7 +190,7 @@ class _EditorPageState extends ConsumerState<EditorPage> {
|
||||
shortcutsActivatorsBuilder: DefaultCodeShortcutsActivatorsBuilder(),
|
||||
controller: _controller,
|
||||
style: CodeEditorStyle(
|
||||
fontSize: 14,
|
||||
fontSize: 14.ap,
|
||||
fontFamily: FontFamily.jetBrainsMono.value,
|
||||
codeTheme: CodeHighlightTheme(
|
||||
languages: {
|
||||
|
||||
@@ -129,6 +129,16 @@ class _HomePageViewState extends ConsumerState<_HomePageView> {
|
||||
controller: _pageController,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: navigationItems.length,
|
||||
// onPageChanged: (index) {
|
||||
// debouncer.call(DebounceTag.pageChange, () {
|
||||
// WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
// if (_pageIndex != index) {
|
||||
// final pageLabel = navigationItems[index].label;
|
||||
// _toPage(pageLabel, true);
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// },
|
||||
itemBuilder: (_, index) {
|
||||
final navigationItem = navigationItems[index];
|
||||
return KeepScope(
|
||||
@@ -180,6 +190,8 @@ class CommonNavigationBar extends ConsumerWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ScrollConfiguration(
|
||||
behavior: HiddenBarScrollBehavior(),
|
||||
child: SingleChildScrollView(
|
||||
child: IntrinsicHeight(
|
||||
child: NavigationRail(
|
||||
@@ -221,6 +233,7 @@ class CommonNavigationBar extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
|
||||
@@ -252,21 +252,6 @@ class CurrentPageLabel extends _$CurrentPageLabel
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class AppSchemes extends _$AppSchemes with AutoDisposeNotifierMixin {
|
||||
@override
|
||||
ColorSchemes build() {
|
||||
return globalState.appState.colorSchemes;
|
||||
}
|
||||
|
||||
@override
|
||||
onUpdate(value) {
|
||||
globalState.appState = globalState.appState.copyWith(
|
||||
colorSchemes: value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class SortNum extends _$SortNum with AutoDisposeNotifierMixin {
|
||||
@override
|
||||
|
||||
@@ -247,21 +247,6 @@ final currentPageLabelProvider =
|
||||
);
|
||||
|
||||
typedef _$CurrentPageLabel = AutoDisposeNotifier<PageLabel>;
|
||||
String _$appSchemesHash() => r'748f48f23539a879a92f318a21e1266b1df56aae';
|
||||
|
||||
/// See also [AppSchemes].
|
||||
@ProviderFor(AppSchemes)
|
||||
final appSchemesProvider =
|
||||
AutoDisposeNotifierProvider<AppSchemes, ColorSchemes>.internal(
|
||||
AppSchemes.new,
|
||||
name: r'appSchemesProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : _$appSchemesHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$AppSchemes = AutoDisposeNotifier<ColorSchemes>;
|
||||
String _$sortNumHash() => r'0f85ebbc77124020eaccf988c6ac9d86a7f34d7e';
|
||||
|
||||
/// See also [SortNum].
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user