Compare commits

..

3 Commits

Author SHA1 Message Date
chen08209
c2f3b13deb Update ndk version 2025-04-15 16:52:52 +08:00
chen08209
edc4714488 cache 2025-04-15 16:39:20 +08:00
chen08209
aec325a19a Optimize android vpn performance
Optimize more details
2025-04-15 15:54:36 +08:00
128 changed files with 1618 additions and 5931 deletions

View File

@@ -1,57 +0,0 @@
name: 问题反馈 / Bug report
title: "[BUG] "
description: 反馈你遇到的问题 / Report the issue you are experiencing
body:
- type: markdown
attributes:
value: |
## 在提交问题之前,请确认以下事项:
1. 请务必给issue填写一个简洁明了的标题以便他人快速检索
2. 请确保[已有的问题](https://github.com/chen08209/FlClash/issues?q=is%3Aissue) 中没有人提交过相似issue否则请在已有的issue下进行讨论
3. 请务必按照模板规范详细描述问题否则issue将会被直接关闭
## Before submitting the issue, please make sure of the following checklist:
1. Please be sure to fill in a concise and clear title for the issue so that others can quickly search
2. Please make sure there is no similar issue in the [existing issues](https://github.com/chen08209/FlClash/issues?q=is%3Aissue), otherwise please discuss under the existing issue
3. Please describe the problem in detail according to the template specification, otherwise issue will be closed directly.
- type: textarea
id: description
attributes:
label: 问题描述 / Describe the bug
description: 详细清晰地描述你遇到的问题,并配合截图 / Describe the problem you encountered in detail and clearly, and provide screenshots
validations:
required: true
- type: textarea
attributes:
label: 软件版本 / Version
description: 请提供FlClash的具体版本 / Please provide the specific version of FlClash.
validations:
required: true
- type: textarea
attributes:
label: 复现步骤 / To Reproduce
description: 请提供复现问题的步骤 / Steps to reproduce the behavior
validations:
required: true
- type: dropdown
attributes:
label: 操作系统 / OS
options:
- Android
- Windows
- MacOS
- Linux
validations:
required: true
- type: input
attributes:
label: 操作系统版本 / OS Version
description: 请提供你的操作系统版本Linux请额外提供桌面环境及窗口系统 / Please provide your OS version, for Linux, please also provide the desktop environment and window system
validations:
required: true
- type: textarea
attributes:
label: 日志(勿上传日志文件,请粘贴日志内容) / Log (Do not upload the log file, paste the log content directly)
description: 请提供完整或相关部分的Debug日志请在“软件左侧菜单”->“设置”->“日志等级”调整到debug / Please provide a complete or relevant Debug log (please adjust it to debug in the left menu of software-> Settings-> Log Level)
validations:
required: true

View File

@@ -1,4 +0,0 @@
contact_links:
- name: 讨论交流 / Communication
url: https://t.me/+G-veVtwBOl4wODc1
about: 在 Telegram 群组中与其他用户讨论交流 / Communicate with other users in the Telegram group

View File

@@ -1,42 +0,0 @@
name: 功能请求 / Feature request
title: "[Feature] "
description: 提出你的功能请求 / Propose your feature request
body:
- type: markdown
attributes:
value: |
## 在提交问题之前,请确认以下事项:
1. 请务必给issue填写一个简洁明了的标题以便他人快速检索
2. 请确保[已有的问题](https://github.com/chen08209/FlClash/issues?q=is%3Aissue) 中没有人提交过相似issue否则请在已有的issue下进行讨论
3. 请务必按照模板规范详细描述问题否则issue将会被直接关闭
## Before submitting the issue, please make sure of the following checklist:
1. Please be sure to fill in a concise and clear title for the issue so that others can quickly search
2. Please make sure there is no similar issue in the [existing issues](https://github.com/chen08209/FlClash/issues?q=is%3Aissue), otherwise please discuss under the existing issue
3. Please describe the problem in detail according to the template specification, otherwise issue will be closed directly.
- type: textarea
id: description
attributes:
label: 功能描述 / Feature description
description: 详细清晰地描述你的功能请求 / A clear and concise description of what the feature is
validations:
required: true
- type: textarea
attributes:
label: 使用场景 / Use case
description: 请描述你的功能请求的使用场景 / Please describe the use case of your feature request
validations:
required: true
- type: checkboxes
id: os-labels
attributes:
label: 适用系统 / Target OS
description: 请选择该功能适用的操作系统(至少选择一个) / Please select the operating system(s) for this feature request (select at least one)
options:
- label: Android
- label: Windows
- label: MacOS
- label: Linux
validations:
required: true

View File

@@ -27,27 +27,29 @@ jobs:
- platform: macos
os: macos-latest
arch: arm64
- platform: windows
os: windows-11-arm
arch: arm64
- platform: linux
os: ubuntu-24.04-arm
arch: arm64
steps:
- name: Setup rust
if: startsWith(matrix.os, 'windows-11-arm')
run: |
Invoke-WebRequest -Uri "https://win.rustup.rs/aarch64" -OutFile rustup-init.exe
.\rustup-init.exe -y --default-toolchain stable
$cargoPath = "$env:USERPROFILE\.cargo\bin"
Add-Content $env:GITHUB_PATH $cargoPath
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup JAVA
if: startsWith(matrix.platform,'android')
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 17
- name: Setup NDK
if: startsWith(matrix.platform,'android')
uses: nttld/setup-ndk@v1
id: setup-ndk
with:
ndk-version: r28
add-to-path: true
link-to-sdk: true
- name: Setup Android Signing
if: startsWith(matrix.platform,'android')
run: |
@@ -56,17 +58,18 @@ jobs:
echo "storePassword=${{ secrets.STORE_PASSWORD }}" >> android/local.properties
echo "keyPassword=${{ secrets.KEY_PASSWORD }}" >> android/local.properties
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.24.0'
go-version: 'stable'
cache-dependency-path: |
core/go.sum
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: ${{ (startsWith(matrix.os, 'windows-11-arm') || startsWith(matrix.os, 'ubuntu-24.04-arm')) && 'master' || 'stable' }}
channel: stable
cache: true
- name: Get Flutter Dependency
@@ -201,7 +204,6 @@ 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
@@ -212,14 +214,6 @@ 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

View File

@@ -1,17 +1,3 @@
## v0.8.82
- Optimize android vpn performance
- Add custom primary color and color scheme
- Add linux nad windows arm release
- Optimize requests and logs page
- Fix map input page delete issues
- Update changelog
## v0.8.81
- Add rule override

View File

@@ -2,8 +2,6 @@ android_arm64:
dart ./setup.dart android --arch arm64
macos_arm64:
dart ./setup.dart macos --arch arm64
android_app:
dart ./setup.dart android
android_arm64_core:
dart ./setup.dart android --arch arm64 --out core
macos_arm64_core:

View File

@@ -31,8 +31,7 @@ def isRelease = defStoreFile.exists() && defStorePassword != null && defKeyAlias
android {
namespace "com.follow.clash"
compileSdk 35
ndkVersion = "28.0.13004108"
compileSdkVersion 35
compileOptions {
sourceCompatibility JavaVersion.VERSION_17

View File

@@ -44,7 +44,6 @@
<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" />

View File

@@ -20,10 +20,6 @@ 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

View File

@@ -1,5 +1,6 @@
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

View File

@@ -27,6 +27,7 @@ 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) {

View File

@@ -3,7 +3,6 @@ package com.follow.clash.models
data class Package(
val packageName: String,
val label: String,
val system: Boolean,
val internet: Boolean,
val isSystem: Boolean,
val lastUpdateTime: Long,
)

View File

@@ -293,17 +293,19 @@ 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.packageName == "android"
it.packageName != FlClashApplication.getAppContext().packageName && (
it.requestedPermissions?.contains(Manifest.permission.INTERNET) == true
|| it.packageName == "android"
)
}?.map {
Package(
packageName = it.packageName,
label = it.applicationInfo?.loadLabel(packageManager).toString(),
system = (it.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM)) == 1,
lastUpdateTime = it.lastUpdateTime,
internet = it.requestedPermissions?.contains(Manifest.permission.INTERNET) == true
)
}?.let { packages.addAll(it) }
Package(
packageName = it.packageName,
label = it.applicationInfo?.loadLabel(packageManager).toString(),
isSystem = (it.applicationInfo?.flags?.and(ApplicationInfo.FLAG_SYSTEM)) == 1,
lastUpdateTime = it.lastUpdateTime
)
}?.let { packages.addAll(it) }
return packages
}

View File

@@ -168,10 +168,8 @@ data object VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
try {
if (GlobalState.runState.value != RunState.START) return
val data = flutterMethodChannel.awaitResult<String>("getStartForegroundParams")
val startForegroundParams = if (data != null) Gson().fromJson(
val startForegroundParams = Gson().fromJson(
data, StartForegroundParams::class.java
) else StartForegroundParams(
title = "", content = ""
)
if (lastStartForegroundParams != startForegroundParams) {
lastStartForegroundParams = startForegroundParams

View File

@@ -1,26 +1,6 @@
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 {
@@ -29,70 +9,4 @@ interface BaseServiceInterface {
fun stop()
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)
}
}

View File

@@ -1,51 +1,29 @@
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() {
@@ -60,8 +38,93 @@ class FlClashService : Service(), BaseServiceInterface {
return super.onUnbind(intent)
}
override fun onDestroy() {
stop()
super.onDestroy()
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)
}
}
}

View File

@@ -1,8 +1,12 @@
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
@@ -13,13 +17,18 @@ 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
@@ -119,22 +128,82 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
}
}
private var cachedBuilder: NotificationCompat.Builder? = null
private val CHANNEL = "FlClash"
private suspend fun notificationBuilder(): NotificationCompat.Builder {
if (cachedBuilder == null) {
cachedBuilder = createFlClashNotificationBuilder().await()
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
)
}
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)
}
}
return cachedBuilder!!
}
private suspend fun getNotificationBuilder(): NotificationCompat.Builder {
return notificationBuilderDeferred.await()
}
@SuppressLint("ForegroundServiceType")
override suspend fun startForeground(title: String, content: String) {
startForeground(
notificationBuilder()
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()
)
.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 onTrimMemory(level: Int) {

View File

@@ -46,7 +46,7 @@ android {
}
}
val copyNativeLibs by tasks.register<Copy>("copyNativeLibs") {
tasks.register<Copy>("copyNativeLibs") {
doFirst {
delete("src/main/jniLibs")
}
@@ -54,9 +54,16 @@ val copyNativeLibs by tasks.register<Copy>("copyNativeLibs") {
into("src/main/jniLibs")
}
tasks.withType<MergeSourceSetFolders>().configureEach {
dependsOn("copyNativeLibs")
}
afterEvaluate {
tasks.named("preBuild") {
dependsOn(copyNativeLibs)
tasks.named("assembleDebug").configure {
dependsOn("copyNativeLibs")
}
tasks.named("assembleRelease").configure {
dependsOn("copyNativeLibs")
}
}

View File

@@ -1,8 +1,8 @@
cmake_minimum_required(VERSION 3.22.1)
project("core")
message("CMAKE_SOURCE_DIR ${CMAKE_SOURCE_DIR}")
if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
add_compile_options(-O3)
@@ -22,13 +22,10 @@ if (NOT "${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
-Wl,--exclude-libs=ALL
)
endif ()
set(LIB_CLASH_PATH "${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libclash.so")
message("LIB_CLASH_PATH ${LIB_CLASH_PATH}")
if (EXISTS ${LIB_CLASH_PATH})
message("Found libclash.so for ABI ${ANDROID_ABI}")
add_compile_definitions(LIBCLASH)
message(STATUS "Found libclash.so for ABI ${ANDROID_ABI}")
add_definitions(-D_LIBCLASH)
include_directories(${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
link_directories(${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
add_library(${CMAKE_PROJECT_NAME} SHARED
@@ -37,7 +34,6 @@ if (EXISTS ${LIB_CLASH_PATH})
target_link_libraries(${CMAKE_PROJECT_NAME}
clash)
else ()
message("Not found libclash.so for ABI ${ANDROID_ABI}")
add_library(${CMAKE_PROJECT_NAME} SHARED
jni_helper.cpp
core.cpp)

View File

@@ -1,6 +1,6 @@
#include <jni.h>
#ifdef LIBCLASH
#ifdef _LIBCLASH
#include <jni.h>
#include <string>
#include "jni_helper.h"
@@ -72,4 +72,17 @@ JNI_OnLoad(JavaVM *vm, void *reserved) {
&release_jni_object_impl);
return JNI_VERSION_1_6;
}
#else
extern "C"
JNIEXPORT void JNICALL
Java_com_follow_clash_core_Core_stopTun(JNIEnv *env, jobject thiz) {
}
extern "C"
JNIEXPORT void JNICALL
Java_com_follow_clash_core_Core_startTun(JNIEnv *env, jobject thiz, jint fd, jobject cb) {
}
#endif

View File

@@ -166,9 +166,6 @@ 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 {

View File

@@ -78,6 +78,7 @@ 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)

View File

@@ -82,7 +82,6 @@ const (
getRunTimeMethod Method = "getRunTime"
getCurrentProfileNameMethod Method = "getCurrentProfileName"
getProfileMethod Method = "getProfile"
crashMethod Method = "crash"
)
type Method string

View File

@@ -7,7 +7,6 @@ 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 (
@@ -53,20 +52,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.2 // indirect
github.com/metacubex/chacha v0.1.1 // 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/sing-quic v0.0.0-20250404030904-b2cc8aab562c // 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-shadowsocks v0.2.8 // indirect
github.com/metacubex/sing-shadowsocks2 v0.2.2 // 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-tun v0.4.6-0.20250312042506-6d3b4dc05c04 // 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.7.0-alpha.1 // indirect
github.com/metacubex/utls v1.6.8-alpha.4 // 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
@@ -85,6 +84,7 @@ 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,6 +107,7 @@ 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

View File

@@ -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.2 h1:QulCq3eVm3TO6+4nVIWJtmSe7BT2GMrgVHuAoqRQnlc=
github.com/metacubex/chacha v0.1.2/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
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/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/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/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-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-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-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-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.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/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/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,6 +174,8 @@ 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=

View File

@@ -442,10 +442,6 @@ 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{

View File

@@ -24,6 +24,7 @@ type AccessControl struct {
Mode string `json:"mode"`
AcceptList []string `json:"acceptList"`
RejectList []string `json:"rejectList"`
IsFilterSystemApp bool `json:"isFilterSystemApp"`
}
type AndroidVpnRawOptions struct {

View File

@@ -1,18 +1,20 @@
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';
import 'package:fl_clash/manager/hotkey_manager.dart';
import 'package:fl_clash/manager/manager.dart';
import 'package:fl_clash/plugins/app.dart';
import 'package:fl_clash/providers/providers.dart';
import 'package:fl_clash/providers/config.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/material.dart';
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 {
@@ -25,6 +27,7 @@ class Application extends ConsumerStatefulWidget {
}
class ApplicationState extends ConsumerState<Application> {
late ColorSchemes systemColorSchemes;
Timer? _autoUpdateGroupTaskTimer;
Timer? _autoUpdateProfilesTaskTimer;
@@ -40,8 +43,16 @@ class ApplicationState extends ConsumerState<Application> {
ColorScheme _getAppColorScheme({
required Brightness brightness,
int? primaryColor,
required ColorSchemes systemColorSchemes,
}) {
return ref.read(genColorSchemeProvider(brightness));
if (primaryColor != null) {
return ColorScheme.fromSeed(
seedColor: Color(primaryColor),
brightness: brightness,
);
} else {
return systemColorSchemes.getColorSchemeForBrightness(brightness);
}
}
@override
@@ -129,6 +140,19 @@ 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(
@@ -138,44 +162,51 @@ class ApplicationState extends ConsumerState<Application> {
final locale =
ref.watch(appSettingProvider.select((state) => state.locale));
final themeProps = ref.watch(themeSettingProvider);
return MaterialApp(
debugShowCheckedModeBanner: false,
navigatorKey: globalState.navigatorKey,
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
builder: (_, child) {
return AppEnvManager(
child: _buildPlatformApp(
_buildApp(child!),
return DynamicColorBuilder(
builder: (lightDynamic, darkDynamic) {
_updateSystemColorSchemes(lightDynamic, darkDynamic);
return MaterialApp(
debugShowCheckedModeBanner: false,
navigatorKey: globalState.navigatorKey,
localizationsDelegates: const [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate
],
builder: (_, child) {
return AppEnvManager(
child: _buildPlatformApp(
_buildApp(child!),
),
);
},
scrollBehavior: BaseScrollBehavior(),
title: appName,
locale: other.getLocaleForString(locale),
supportedLocales: AppLocalizations.delegate.supportedLocales,
themeMode: themeProps.themeMode,
theme: ThemeData(
useMaterial3: true,
pageTransitionsTheme: _pageTransitionsTheme,
colorScheme: _getAppColorScheme(
brightness: Brightness.light,
systemColorSchemes: systemColorSchemes,
primaryColor: themeProps.primaryColor,
),
),
darkTheme: ThemeData(
useMaterial3: true,
pageTransitionsTheme: _pageTransitionsTheme,
colorScheme: _getAppColorScheme(
brightness: Brightness.dark,
systemColorSchemes: systemColorSchemes,
primaryColor: themeProps.primaryColor,
).toPureBlack(themeProps.pureBlack),
),
home: child,
);
},
scrollBehavior: BaseScrollBehavior(),
title: appName,
locale: utils.getLocaleForString(locale),
supportedLocales: AppLocalizations.delegate.supportedLocales,
themeMode: themeProps.themeMode,
theme: ThemeData(
useMaterial3: true,
pageTransitionsTheme: _pageTransitionsTheme,
colorScheme: _getAppColorScheme(
brightness: Brightness.light,
primaryColor: themeProps.primaryColor,
),
),
darkTheme: ThemeData(
useMaterial3: true,
pageTransitionsTheme: _pageTransitionsTheme,
colorScheme: _getAppColorScheme(
brightness: Brightness.dark,
primaryColor: themeProps.primaryColor,
).toPureBlack(themeProps.pureBlack),
),
home: child,
);
},
child: const HomePage(),

View File

@@ -58,8 +58,6 @@ mixin ClashInterface {
stopLog();
Future<bool> crash();
FutureOr<String> getConnections();
FutureOr<bool> closeConnection(String id);
@@ -106,7 +104,6 @@ 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:
@@ -154,7 +151,7 @@ abstract class ClashHandlerInterface with ClashInterface {
Duration? timeout,
FutureOr<T> Function()? onTimeout,
}) async {
final id = "${method.name}#${utils.id}";
final id = "${method.name}#${other.id}";
callbackCompleterMap[id] = Completer<T>();
@@ -245,14 +242,6 @@ abstract class ClashHandlerInterface with ClashInterface {
);
}
@override
Future<bool> crash() {
return invoke<bool>(
method: ActionMethod.crash,
);
}
@override
Future<String> getProxies() {
return invoke<String>(

View File

@@ -1,5 +1,3 @@
import 'dart:math';
import 'package:flutter/material.dart';
extension ColorExtension on Color {
@@ -39,54 +37,11 @@ extension ColorExtension on Color {
return withAlpha(0);
}
int get value32bit {
return _floatToInt8(a) << 24 |
_floatToInt8(r) << 16 |
_floatToInt8(g) << 8 |
_floatToInt8(b) << 0;
}
int get alpha8bit => (0xff000000 & value32bit) >> 24;
int get red8bit => (0x00ff0000 & value32bit) >> 16;
int get green8bit => (0x0000ff00 & value32bit) >> 8;
int get blue8bit => (0x000000ff & value32bit) >> 0;
int _floatToInt8(double x) {
return (x * 255.0).round() & 0xff;
}
Color lighten([double amount = 10]) {
if (amount <= 0) return this;
if (amount > 100) return Colors.white;
final HSLColor hsl = this == const Color(0xFF000000)
? HSLColor.fromColor(this).withSaturation(0)
: HSLColor.fromColor(this);
return hsl
.withLightness(min(1, max(0, hsl.lightness + amount / 100)))
.toColor();
}
String get hex {
final value = toARGB32();
final red = (value >> 16) & 0xFF;
final green = (value >> 8) & 0xFF;
final blue = value & 0xFF;
return '#${red.toRadixString(16).padLeft(2, '0')}'
'${green.toRadixString(16).padLeft(2, '0')}'
'${blue.toRadixString(16).padLeft(2, '0')}'
.toUpperCase();
}
Color darken([final int amount = 10]) {
if (amount <= 0) return this;
if (amount > 100) return Colors.black;
final HSLColor hsl = HSLColor.fromColor(this);
return hsl
.withLightness(min(1, max(0, hsl.lightness - amount / 100)))
.toColor();
Color darken([double amount = .1]) {
assert(amount >= 0 && amount <= 1);
final hsl = HSLColor.fromColor(this);
final hslDark = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0));
return hslDark.toColor();
}
Color blendDarken(
@@ -119,7 +74,7 @@ extension ColorSchemeExtension on ColorScheme {
? copyWith(
surface: Colors.black,
surfaceContainer: surfaceContainer.darken(
5,
0.05,
),
)
: this;

View File

@@ -19,7 +19,7 @@ export 'navigation.dart';
export 'navigator.dart';
export 'network.dart';
export 'num.dart';
export 'utils.dart';
export 'other.dart';
export 'package.dart';
export 'path.dart';
export 'picker.dart';

View File

@@ -17,12 +17,15 @@ const packageName = "com.follow.clash";
final unixSocketPath = "/tmp/FlClashSocket_${Random().nextInt(10000)}.sock";
const helperPort = 47890;
const helperTag = "2024125";
final baseInfoEdgeInsets = EdgeInsets.symmetric(
vertical: 16.ap,
horizontal: 16.ap,
const baseInfoEdgeInsets = EdgeInsets.symmetric(
vertical: 16,
horizontal: 16,
);
final defaultTextScaleFactor = WidgetsBinding.instance.platformDispatcher.textScaleFactor;
double textScaleFactor = min(
WidgetsBinding.instance.platformDispatcher.textScaleFactor,
1.2,
);
const httpTimeoutDuration = Duration(milliseconds: 5000);
const moreDuration = Duration(milliseconds: 100);
const animateDuration = Duration(milliseconds: 100);
@@ -41,6 +44,7 @@ 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";
@@ -56,7 +60,6 @@ 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>();
@@ -75,22 +78,12 @@ const viewModeColumnsMap = {
ViewMode.desktop: [4, 3],
};
const defaultPrimaryColor = 0xFF795548;
const defaultPrimaryColor = Colors.brown;
double getWidgetHeight(num lines) {
return max(lines * 84 + (lines - 1) * 16, 0).ap;
return max(lines * 84 * textScaleFactor + (lines - 1) * 16, 0);
}
final mainIsolate = "FlClashMainIsolate";
final serviceIsolate = "FlClashServiceIsolate";
const defaultPrimaryColors = [
defaultPrimaryColor,
0xFF03A9F4,
0xFFFFFF00,
0XFFBBC9CC,
0XFFABD397,
0XFFD8C0C3,
0XFF665390,
];

View File

@@ -1,4 +1,4 @@
import 'package:fl_clash/manager/message_manager.dart';
import 'package:fl_clash/manager/manager.dart';
import 'package:fl_clash/widgets/scaffold.dart';
import 'package:flutter/material.dart';
@@ -11,36 +11,6 @@ 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;
}
@@ -57,10 +27,10 @@ extension BuildContextExtension on BuildContext {
T? state;
visitor(Element element) {
if (!element.mounted) {
if(!element.mounted){
return;
}
if (element is StatefulElement) {
if(element is StatefulElement){
if (element.state is T) {
state = element.state as T;
}

View File

@@ -1,7 +1,6 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:launch_at_startup/launch_at_startup.dart';
import 'constant.dart';
@@ -35,9 +34,6 @@ class AutoLaunch {
}
updateStatus(bool isAutoLaunch) async {
if(kDebugMode){
return;
}
if (await isEnable == isAutoLaunch) return;
if (isAutoLaunch == true) {
enable();

View File

@@ -3,13 +3,11 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Measure {
final TextScaler _textScaler;
final TextScaler _textScale;
final BuildContext context;
final Map<String, dynamic> _measureMap;
Measure.of(this.context, double textScaleFactor)
: _measureMap = {},
_textScaler = TextScaler.linear(
Measure.of(this.context)
: _textScale = TextScaler.linear(
textScaleFactor,
);
@@ -23,7 +21,7 @@ class Measure {
style: text.style,
),
maxLines: text.maxLines,
textScaler: _textScaler,
textScaler: _textScale,
textDirection: text.textDirection ?? TextDirection.ltr,
)..layout(
maxWidth: maxWidth,
@@ -31,75 +29,81 @@ class Measure {
return textPainter.size;
}
double? _bodyMediumHeight;
Size? _bodyLargeSize;
double? _bodySmallHeight;
double? _labelSmallHeight;
double? _labelMediumHeight;
double? _titleLargeHeight;
double? _titleMediumHeight;
double get bodyMediumHeight {
return _measureMap.getCacheValue(
"bodyMediumHeight",
computeTextSize(
Text(
"X",
style: context.textTheme.bodyMedium,
),
).height,
_bodyMediumHeight ??= computeTextSize(
Text(
"X",
style: context.textTheme.bodyMedium,
),
).height;
return _bodyMediumHeight!;
}
Size get bodyLargeSize {
_bodyLargeSize ??= computeTextSize(
Text(
"X",
style: context.textTheme.bodyLarge,
),
);
return _bodyLargeSize!;
}
double get bodySmallHeight {
return _measureMap.getCacheValue(
"bodySmallHeight",
computeTextSize(
Text(
"X",
style: context.textTheme.bodySmall,
),
).height,
);
_bodySmallHeight ??= computeTextSize(
Text(
"X",
style: context.textTheme.bodySmall,
),
).height;
return _bodySmallHeight!;
}
double get labelSmallHeight {
return _measureMap.getCacheValue(
"labelSmallHeight",
computeTextSize(
Text(
"X",
style: context.textTheme.labelSmall,
),
).height,
);
_labelSmallHeight ??= computeTextSize(
Text(
"X",
style: context.textTheme.labelSmall,
),
).height;
return _labelSmallHeight!;
}
double get labelMediumHeight {
return _measureMap.getCacheValue(
"labelMediumHeight",
computeTextSize(
Text(
"X",
style: context.textTheme.labelMedium,
),
).height,
);
_labelMediumHeight ??= computeTextSize(
Text(
"X",
style: context.textTheme.labelMedium,
),
).height;
return _labelMediumHeight!;
}
double get titleLargeHeight {
return _measureMap.getCacheValue(
"titleLargeHeight",
computeTextSize(
Text(
"X",
style: context.textTheme.titleLarge,
),
).height,
);
_titleLargeHeight ??= computeTextSize(
Text(
"X",
style: context.textTheme.titleLarge,
),
).height;
return _titleLargeHeight!;
}
double get titleMediumHeight {
return _measureMap.getCacheValue(
"titleMediumHeight",
computeTextSize(
Text(
"X",
style: context.textTheme.titleMedium,
),
).height,
);
_titleMediumHeight ??= computeTextSize(
Text(
"X",
style: context.textTheme.titleMedium,
),
).height;
return _titleMediumHeight!;
}
}

View File

@@ -1,4 +1,3 @@
import 'package:fl_clash/state.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
@@ -13,10 +12,6 @@ extension NumExt on num {
}
return formatted;
}
double get ap {
return this * (1 + (globalState.theme.textScaleFactor - 1) * 0.5);
}
}
extension DoubleExt on double {

View File

@@ -7,7 +7,7 @@ import 'package:fl_clash/enum/enum.dart';
import 'package:flutter/material.dart';
import 'package:lpinyin/lpinyin.dart';
class Utils {
class Other {
Color? getDelayColor(int? delay) {
if (delay == null) return null;
if (delay < 0) return Colors.red;
@@ -233,63 +233,6 @@ class Utils {
return max((viewWidth / 350).floor(), 1);
}
final _indexPrimary = [
50,
100,
200,
300,
400,
500,
600,
700,
800,
850,
900,
];
_createPrimarySwatch(Color color) {
final Map<int, Color> swatch = <int, Color>{};
final int a = color.alpha8bit;
final int r = color.red8bit;
final int g = color.green8bit;
final int b = color.blue8bit;
for (final int strength in _indexPrimary) {
final double ds = 0.5 - strength / 1000;
swatch[strength] = Color.fromARGB(
a,
r + ((ds < 0 ? r : (255 - r)) * ds).round(),
g + ((ds < 0 ? g : (255 - g)) * ds).round(),
b + ((ds < 0 ? b : (255 - b)) * ds).round(),
);
}
swatch[50] = swatch[50]!.lighten(18);
swatch[100] = swatch[100]!.lighten(16);
swatch[200] = swatch[200]!.lighten(14);
swatch[300] = swatch[300]!.lighten(10);
swatch[400] = swatch[400]!.lighten(6);
swatch[700] = swatch[700]!.darken(2);
swatch[800] = swatch[800]!.darken(3);
swatch[900] = swatch[900]!.darken(4);
return MaterialColor(color.value32bit, swatch);
}
List<Color> getMaterialColorShades(Color color) {
final swatch = _createPrimarySwatch(color);
return <Color>[
if (swatch[50] != null) swatch[50]!,
if (swatch[100] != null) swatch[100]!,
if (swatch[200] != null) swatch[200]!,
if (swatch[300] != null) swatch[300]!,
if (swatch[400] != null) swatch[400]!,
if (swatch[500] != null) swatch[500]!,
if (swatch[600] != null) swatch[600]!,
if (swatch[700] != null) swatch[700]!,
if (swatch[800] != null) swatch[800]!,
if (swatch[850] != null) swatch[850]!,
if (swatch[900] != null) swatch[900]!,
];
}
String getBackupFileName() {
return "${appName}_backup_${DateTime.now().show}.zip";
}
@@ -325,4 +268,4 @@ class Utils {
}
}
final utils = Utils();
final other = Other();

View File

@@ -1,3 +1,4 @@
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';
@@ -19,7 +20,10 @@ class CommonPrint {
return;
}
globalState.appController.addLog(
Log.app(payload),
Log(
logLevel: LogLevel.info,
payload: payload,
),
);
}
}

View File

@@ -54,4 +54,4 @@ class Render {
}
}
final Render? render = system.isDesktop ? Render() : null;
final render = system.isDesktop ? Render() : null;

View File

@@ -68,7 +68,7 @@ class Request {
final remoteVersion = data['tag_name'];
final version = globalState.packageInfo.version;
final hasUpdate =
utils.compareVersions(remoteVersion.replaceAll('v', ''), version) > 0;
other.compareVersions(remoteVersion.replaceAll('v', ''), version) > 0;
if (!hasUpdate) return null;
return data;
}

View File

@@ -4,12 +4,8 @@ import 'package:flutter/material.dart';
class CommonTheme {
final BuildContext context;
final Map<String, Color> _colorMap;
final double textScaleFactor;
CommonTheme.of(
this.context,
this.textScaleFactor,
) : _colorMap = {};
CommonTheme.of(this.context) : _colorMap = {};
Color get darkenSecondaryContainer {
return _colorMap.getCacheValue(

View File

@@ -1,6 +1,5 @@
import 'dart:io';
import 'package:fl_clash/common/utils.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/models.dart';
import 'package:fl_clash/state.dart';
@@ -11,6 +10,7 @@ import 'package:tray_manager/tray_manager.dart';
import 'app_localizations.dart';
import 'constant.dart';
import 'other.dart';
import 'window.dart';
class Tray {
@@ -25,7 +25,7 @@ class Tray {
await trayManager.destroy();
}
await trayManager.setIcon(
utils.getTrayIconPath(
other.getTrayIconPath(
brightness: brightness ??
WidgetsBinding.instance.platformDispatcher.platformBrightness,
),
@@ -80,7 +80,7 @@ class Tray {
);
}
menuItems.add(MenuItem.separator());
if (Platform.isMacOS) {
if (!Platform.isWindows) {
for (final group in trayState.groups) {
List<MenuItem> subMenuItems = [];
for (final proxy in group.all) {

View File

@@ -153,7 +153,7 @@ class AppController {
updateLocalIp() async {
_ref.read(localIpProvider.notifier).value = null;
await Future.delayed(commonDuration);
_ref.read(localIpProvider.notifier).value = await utils.getLocalIpAddress();
_ref.read(localIpProvider.notifier).value = await other.getLocalIpAddress();
}
Future<void> updateProfile(Profile profile) async {
@@ -334,22 +334,23 @@ class AppController {
try {
await updateProfile(profile);
} catch (e) {
commonPrint.log(e.toString());
_ref.read(logsProvider.notifier).addLog(
Log(
logLevel: LogLevel.info,
payload: 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 = [];
}
_ref.read(groupsProvider.notifier).value = await retry(
task: () async {
return await clashCore.getProxiesGroups();
},
retryIf: (res) => res.isEmpty,
);
}
updateProfiles() async {
@@ -361,6 +362,10 @@ class AppController {
}
}
updateSystemColorSchemes(ColorSchemes colorSchemes) {
_ref.read(appSchemesProvider.notifier).value = colorSchemes;
}
savePreferences() async {
commonPrint.log("save preferences");
await preferences.saveConfig(globalState.config);
@@ -405,14 +410,6 @@ class AppController {
}
}
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();
@@ -429,7 +426,7 @@ class AppController {
if (data != null) {
final tagName = data['tag_name'];
final body = data['body'];
final submits = utils.parseReleaseBody(body);
final submits = other.parseReleaseBody(body);
final textTheme = context.textTheme;
final res = await globalState.showMessage(
title: appLocalizations.discoverNewVersion,
@@ -674,9 +671,9 @@ class AppController {
List<Proxy> _sortOfName(List<Proxy> proxies) {
return List.of(proxies)
..sort(
(a, b) => utils.sortByChar(
utils.getPinyin(a.name),
utils.getPinyin(b.name),
(a, b) => other.sortByChar(
other.getPinyin(a.name),
other.getPinyin(b.name),
),
);
}
@@ -866,7 +863,7 @@ class AppController {
return utf8.encode(logsRawString);
});
return await picker.saveFile(
utils.logFile,
other.logFile,
Uint8List.fromList(data),
) !=
null;
@@ -941,34 +938,29 @@ class AppController {
_recovery(Config config, RecoveryOption recoveryOption) {
final profiles = config.profiles;
final oldProfiles = List.from(globalState.config.profiles);
_ref.read(profilesProvider.notifier).value = profiles;
for (final profile in oldProfiles) {
_ref.read(profilesProvider.notifier).setProfile(
profile,
force: false,
);
for (final profile in profiles) {
_ref.read(profilesProvider.notifier).setProfile(profile);
}
final onlyProfiles = recoveryOption == RecoveryOption.onlyProfiles;
if (!onlyProfiles) {
_ref.read(patchClashConfigProvider.notifier).value =
config.patchClashConfig;
_ref.read(appSettingProvider.notifier).value = config.appSetting;
_ref.read(currentProfileIdProvider.notifier).value =
config.currentProfileId;
_ref.read(appDAVSettingProvider.notifier).value = config.dav;
_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(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;
if (onlyProfiles) {
final currentProfile = _ref.read(currentProfileProvider);
if (currentProfile != null) {
_ref.read(currentProfileIdProvider.notifier).value = profiles.first.id;
}
return;
}
_ref.read(patchClashConfigProvider.notifier).value =
config.patchClashConfig;
_ref.read(appSettingProvider.notifier).value = config.appSetting;
_ref.read(currentProfileIdProvider.notifier).value =
config.currentProfileId;
_ref.read(appDAVSettingProvider.notifier).value = config.dav;
_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(overrideDnsProvider.notifier).value = config.overrideDns;
_ref.read(networkSettingProvider.notifier).value = config.networkProps;
_ref.read(hotKeyActionsProvider.notifier).value = config.hotKeyActions;
}
}

View File

@@ -91,14 +91,7 @@ enum Mode { rule, global, direct }
enum ViewMode { mobile, laptop, desktop }
enum LogLevel {
debug,
info,
warning,
error,
silent,
app,
}
enum LogLevel { debug, info, warning, error, silent }
enum TransportProtocol { udp, tcp }
@@ -269,7 +262,6 @@ enum ActionMethod {
getCountryCode,
getMemory,
getProfile,
crash,
///Android,
setFdMap,
@@ -316,12 +308,6 @@ enum DashboardWidget {
child: NetworkSpeed(),
),
),
outboundModeV2(
GridItem(
crossAxisCellCount: 8,
child: OutboundModeV2(),
),
),
outboundMode(
GridItem(
crossAxisCellCount: 4,
@@ -347,15 +333,6 @@ enum DashboardWidget {
),
platforms: desktopPlatforms,
),
vpnButton(
GridItem(
crossAxisCellCount: 4,
child: VpnButton(),
),
platforms: [
SupportPlatform.Android,
],
),
systemProxyButton(
GridItem(
crossAxisCellCount: 4,

View File

@@ -1,11 +1,7 @@
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 {
@@ -120,43 +116,33 @@ class AboutFragment extends StatelessWidget {
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Consumer(builder: (_, ref, ___) {
return _DeveloperModeDetector(
child: Wrap(
spacing: 16,
crossAxisAlignment: WrapCrossAlignment.center,
Wrap(
spacing: 16,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(12),
child: Image.asset(
'assets/images/icon.png',
width: 64,
height: 64,
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(12),
child: Image.asset(
'assets/images/icon.png',
width: 64,
height: 64,
),
Text(
appName,
style: Theme.of(context).textTheme.headlineSmall,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
appName,
style: Theme.of(context).textTheme.headlineSmall,
),
Text(
globalState.packageInfo.version,
style: Theme.of(context).textTheme.labelLarge,
)
],
Text(
globalState.packageInfo.version,
style: Theme.of(context).textTheme.labelLarge,
)
],
),
onEnterDeveloperMode: () {
ref.read(appSettingProvider.notifier).updateState(
(state) => state.copyWith(developerMode: true),
);
context.showNotifier(appLocalizations.developerModeEnableTip);
},
);
}),
)
],
),
const SizedBox(
height: 24,
),
@@ -223,52 +209,3 @@ 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,
);
}
}

View File

@@ -113,11 +113,15 @@ class _AccessFragmentState extends ConsumerState<AccessFragment> {
}
_intelligentSelected() async {
final packageNames = ref.read(
packageListSelectorStateProvider.select(
(state) => state.list.map((item) => item.packageName),
),
);
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 commonScaffoldState = context.commonScaffoldState;
if (commonScaffoldState?.mounted != true) return;
final selectedPackageNames =
@@ -190,7 +194,7 @@ class _AccessFragmentState extends ConsumerState<AccessFragment> {
final state = ref.watch(packageListSelectorStateProvider);
final accessControl = state.accessControl;
final accessControlMode = accessControl.mode;
final packages = state.getSortList(
final packages = state.getList(
accessControlMode == AccessControlMode.acceptSelected
? acceptList
: rejectList,
@@ -478,20 +482,14 @@ class AccessControlSearchDelegate extends SearchDelegate {
final lowQuery = query.toLowerCase();
return Consumer(
builder: (context, ref, __) {
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 state = ref.watch(packageListSelectorStateProvider);
final accessControl = state.accessControl;
final accessControlMode = accessControl.mode;
final packages = state.getList(
accessControlMode == AccessControlMode.acceptSelected
? acceptList
: rejectList,
);
final packages = vm3.a;
final queryPackages = packages
.where(
(package) =>
@@ -499,8 +497,8 @@ class AccessControlSearchDelegate extends SearchDelegate {
package.packageName.contains(lowQuery),
)
.toList();
final isAccessControl = vm3.b;
final currentList = vm3.c;
final isAccessControl = state.accessControl.enable;
final currentList = accessControl.currentList;
final packageNameList = packages.map((e) => e.packageName).toList();
final valueList = currentList.intersection(packageNameList);
return DisabledMask(
@@ -581,6 +579,13 @@ 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,
@@ -668,39 +673,25 @@ class _AccessControlPanelState extends ConsumerState<AccessControlPanel> {
scrollDirection: Axis.horizontal,
child: Consumer(
builder: (_, ref, __) {
final vm2 = ref.watch(
vpnSettingProvider.select(
(state) => VM2(
a: state.accessControl.isFilterSystemApp,
b: state.accessControl.isFilterNonInternetApp,
),
),
final isFilterSystemApp = ref.watch(
vpnSettingProvider
.select((state) => state.accessControl.isFilterSystemApp),
);
return Wrap(
spacing: 16,
children: [
SettingTextCard(
appLocalizations.systemApp,
isSelected: vm2.a == false,
onPressed: () {
ref.read(vpnSettingProvider.notifier).updateState(
(state) => state.copyWith.accessControl(
isFilterSystemApp: !vm2.a,
),
);
},
),
SettingTextCard(
appLocalizations.noNetworkApp,
isSelected: vm2.b == false,
onPressed: () {
ref.read(vpnSettingProvider.notifier).updateState(
(state) => state.copyWith.accessControl(
isFilterNonInternetApp: !vm2.b,
),
);
},
)
for (final item in [false, true])
SettingTextCard(
_getTextWithIsFilterSystemApp(item),
isSelected: isFilterSystemApp == item,
onPressed: () {
ref.read(vpnSettingProvider.notifier).updateState(
(state) => state.copyWith.accessControl(
isFilterSystemApp: item,
),
);
},
)
],
);
},

View File

@@ -75,7 +75,7 @@ class BackupAndRecovery extends ConsumerWidget {
() async {
final backupData = await globalState.appController.backupData();
final value = await picker.saveFile(
utils.getBackupFileName(),
other.getBackupFileName(),
Uint8List.fromList(backupData),
);
if (value == null) return false;

View File

@@ -61,6 +61,7 @@ class _ConfigFragmentState extends State<ConfigFragment> {
if (res != true) {
return;
}
ref.read(patchClashConfigProvider.notifier).updateState(
(state) => state.copyWith(
dns: defaultDns,

View File

@@ -11,6 +11,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'item.dart';
double _preOffset = 0;
class RequestsFragment extends ConsumerStatefulWidget {
const RequestsFragment({super.key});
@@ -24,8 +26,10 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
final _requestsStateNotifier =
ValueNotifier<ConnectionsState>(const ConnectionsState());
List<Connection> _requests = [];
final _cacheKey = ValueKey("requests_list");
late ScrollController _scrollController;
final ScrollController _scrollController = ScrollController(
initialScrollOffset: _preOffset != 0 ? _preOffset : double.maxFinite,
);
double _currentMaxWidth = 0;
@@ -45,13 +49,10 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
@override
void initState() {
super.initState();
final preOffset = globalState.cacheScrollPosition[_cacheKey] ?? -1;
_scrollController = ScrollController(
initialScrollOffset: preOffset > 0 ? preOffset : double.maxFinite,
);
_requestsStateNotifier.value = _requestsStateNotifier.value.copyWith(
connections: globalState.appState.requests.list,
);
ref.listenManual(
isCurrentPageProvider(
PageLabel.requests,
@@ -73,6 +74,7 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
updateRequestsThrottler();
}
},
fireImmediately: true,
);
}
@@ -148,77 +150,73 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
_handleTryClearCache(constraints.maxWidth - 40 - (value ? 60 : 0));
return child!;
},
child: TextScaleNotification(
child: ValueListenableBuilder<ConnectionsState>(
valueListenable: _requestsStateNotifier,
builder: (_, state, __) {
final connections = state.list;
if (connections.isEmpty) {
return NullStatus(
label: appLocalizations.nullRequestsDesc,
);
}
final items = connections
.map<Widget>(
(connection) => ConnectionItem(
key: Key(connection.id),
connection: connection,
onClickKeyword: (value) {
context.commonScaffoldState?.addKeyword(value);
},
),
)
.separated(
const Divider(
height: 0,
),
)
.toList();
return Align(
alignment: Alignment.topCenter,
child: ScrollToEndBox(
child: ValueListenableBuilder<ConnectionsState>(
valueListenable: _requestsStateNotifier,
builder: (_, state, __) {
final connections = state.list;
if (connections.isEmpty) {
return NullStatus(
label: appLocalizations.nullRequestsDesc,
);
}
final items = connections
.map<Widget>(
(connection) => ConnectionItem(
key: Key(connection.id),
connection: connection,
onClickKeyword: (value) {
context.commonScaffoldState?.addKeyword(value);
},
),
)
.separated(
const Divider(
height: 0,
),
)
.toList();
return Align(
alignment: Alignment.topCenter,
child: NotificationListener<ScrollEndNotification>(
onNotification: (details) {
_preOffset = details.metrics.pixels;
return false;
},
child: CommonScrollBar(
controller: _scrollController,
cacheKey: _cacheKey,
dataSource: connections,
child: CommonScrollBar(
child: CacheItemExtentListView(
key: _key,
reverse: true,
shrinkWrap: true,
physics: NextClampingScrollPhysics(),
controller: _scrollController,
child: CacheItemExtentListView(
key: _key,
reverse: true,
shrinkWrap: true,
physics: NextClampingScrollPhysics(),
controller: _scrollController,
itemExtentBuilder: (index) {
final widget = items[index];
if (widget.runtimeType == Divider) {
return 0;
}
final measure = globalState.measure;
final bodyMediumHeight = measure.bodyMediumHeight;
final connection = connections[(index / 2).floor()];
final height = _calcCacheHeight(connection);
return height + bodyMediumHeight + 32;
},
itemBuilder: (_, index) {
return items[index];
},
itemCount: items.length,
keyBuilder: (int index) {
final widget = items[index];
if (widget.runtimeType == Divider) {
return "divider";
}
final connection = connections[(index / 2).floor()];
return connection.id;
},
),
itemExtentBuilder: (index) {
final widget = items[index];
if (widget.runtimeType == Divider) {
return 0;
}
final measure = globalState.measure;
final bodyMediumHeight = measure.bodyMediumHeight;
final connection = connections[(index / 2).floor()];
final height = _calcCacheHeight(connection);
return height + bodyMediumHeight + 32;
},
itemBuilder: (_, index) {
return items[index];
},
itemCount: items.length,
keyBuilder: (int index) {
final widget = items[index];
if (widget.runtimeType == Divider) {
return "divider";
}
final connection = connections[(index / 2).floor()];
return connection.id;
},
),
),
);
},
),
onNotification: (_) {
_key.currentState?.clearCache();
),
);
},
),
);

View File

@@ -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 / 320).ceil()), 8);
final columns = max(4 * ((dashboardState.viewWidth / 350).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.ap,
mainAxisSpacing: 16.ap,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
children: [
...dashboardState.dashboardWidgets
.where(

View File

@@ -4,7 +4,6 @@ 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';
@@ -58,43 +57,37 @@ 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: [
SizedBox(
height: globalState.measure.bodyMediumHeight + 2,
child: ValueListenableBuilder(
valueListenable: _memoryInfoStateNotifier,
builder: (_, trafficValue, __) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text(
trafficValue.showValue,
style: context.textTheme.bodyMedium?.toLight
.adjustSize(1),
),
SizedBox(
width: 8,
),
Text(
trafficValue.showUnit,
style: context.textTheme.bodyMedium?.toLight
.adjustSize(1),
)
],
);
},
),
)
],
),
child: Column(
children: [
ValueListenableBuilder(
valueListenable: _memoryInfoStateNotifier,
builder: (_, trafficValue, __) {
return Padding(
padding: baseInfoEdgeInsets.copyWith(
bottom: 0,
top: 12,
),
child: Row(
children: [
Text(
trafficValue.showValue,
style:
context.textTheme.bodyMedium?.toLight.adjustSize(1),
),
SizedBox(
width: 8,
),
Text(
trafficValue.showUnit,
style:
context.textTheme.bodyMedium?.toLight.adjustSize(1),
)
],
),
);
},
),
],
),
),
);

View File

@@ -206,7 +206,7 @@ class _NetworkDetectionState extends ConsumerState<NetworkDetection> {
);
},
icon: Icon(
size: 16.ap,
size: 16,
Icons.info_outline,
color: context.colorScheme.onSurfaceVariant,
),

View File

@@ -17,146 +17,58 @@ class OutboundMode extends StatelessWidget {
height: height,
child: Consumer(
builder: (_, ref, __) {
final mode = ref.watch(
patchClashConfigProvider.select(
(state) => state.mode,
final mode =
ref.watch(patchClashConfigProvider.select((state) => state.mode));
return CommonCard(
onPressed: () {},
info: Info(
label: appLocalizations.outboundMode,
iconData: Icons.call_split_sharp,
),
child: Padding(
padding: const EdgeInsets.only(
top: 12,
bottom: 16,
),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
for (final item in Mode.values)
Flexible(
child: ListItem.radio(
dense: true,
horizontalTitleGap: 4,
padding: const EdgeInsets.only(
left: 12,
right: 16,
),
delegate: RadioDelegate(
value: item,
groupValue: mode,
onChanged: (value) async {
if (value == null) {
return;
}
globalState.appController.changeMode(value);
},
),
title: Text(
Intl.message(item.name),
style: Theme.of(context)
.textTheme
.bodyMedium
?.toSoftBold,
),
),
),
],
),
),
);
return Theme(
data: Theme.of(context).copyWith(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
hoverColor: Colors.transparent),
child: CommonCard(
onPressed: () {},
info: Info(
label: appLocalizations.outboundMode,
iconData: Icons.call_split_sharp,
),
child: Padding(
padding: const EdgeInsets.only(
top: 12,
bottom: 16,
),
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (final item in Mode.values)
Flexible(
fit: FlexFit.tight,
child: ListItem.radio(
dense: true,
horizontalTitleGap: 4,
padding: EdgeInsets.only(
left: 12.ap,
right: 16.ap,
),
delegate: RadioDelegate(
value: item,
groupValue: mode,
onChanged: (value) async {
if (value == null) {
return;
}
globalState.appController.changeMode(value);
},
),
title: Text(
Intl.message(item.name),
style: Theme.of(context)
.textTheme
.bodyMedium
?.toSoftBold,
),
),
),
],
),
),
));
},
),
);
}
}
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,
),
);
},
),
),
);
}
}

View File

@@ -165,87 +165,3 @@ 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,
),
);
},
);
},
)
],
),
),
),
);
}
}

View File

@@ -71,10 +71,10 @@ class _StartButtonState extends State<StartButton>
final textWidth = globalState.measure
.computeTextSize(
Text(
utils.getTimeDifference(
other.getTimeDifference(
DateTime.now(),
),
style: context.textTheme.titleMedium?.toSoftBold,
style: Theme.of(context).textTheme.titleMedium?.toSoftBold,
),
)
.width +
@@ -123,12 +123,10 @@ class _StartButtonState extends State<StartButton>
child: Consumer(
builder: (_, ref, __) {
final runTime = ref.watch(runTimeProvider);
final text = utils.getTimeText(runTime);
final text = other.getTimeText(runTime);
return Text(
text,
style: Theme.of(context).textTheme.titleMedium?.toSoftBold.copyWith(
color: context.colorScheme.onPrimaryContainer
),
style: Theme.of(context).textTheme.titleMedium?.toSoftBold,
);
},
),

View File

@@ -1,86 +0,0 @@
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/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';
class DeveloperView extends ConsumerWidget {
const DeveloperView({super.key});
Widget _getDeveloperList(BuildContext context) {
return generateSectionV2(
title: appLocalizations.options,
items: [
ListItem(
leading: Icon(Icons.ac_unit),
title: Text(appLocalizations.messageTest),
onTap: () {
context.showNotifier(
appLocalizations.messageTestTip,
);
},
),
ListItem(
leading: Icon(Icons.heart_broken),
title: Text(appLocalizations.crashTest),
onTap: () {
clashCore.clashInterface.crash();
},
),
ListItem(
leading: Icon(Icons.delete_forever),
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)
],
),
);
}
}

View File

@@ -11,4 +11,3 @@ export 'backup_and_recovery.dart';
export 'resources.dart';
export 'connection/requests.dart';
export 'connection/connections.dart';
export 'developer.dart';

View File

@@ -8,6 +8,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../models/models.dart';
import '../widgets/widgets.dart';
double _preOffset = 0;
class LogsFragment extends ConsumerStatefulWidget {
const LogsFragment({super.key});
@@ -17,8 +19,9 @@ class LogsFragment extends ConsumerStatefulWidget {
class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
final _logsStateNotifier = ValueNotifier<LogsState>(LogsState());
final _cacheKey = ValueKey("logs_list");
late ScrollController _scrollController;
final _scrollController = ScrollController(
initialScrollOffset: _preOffset != 0 ? _preOffset : double.maxFinite,
);
double _currentMaxWidth = 0;
final GlobalKey<CacheItemExtentListViewState> _key = GlobalKey();
@@ -27,13 +30,22 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
@override
void initState() {
super.initState();
final preOffset = globalState.cacheScrollPosition[_cacheKey] ?? -1;
_scrollController = ScrollController(
initialScrollOffset: preOffset > 0 ? preOffset : double.maxFinite,
);
_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,
);
ref.listenManual(
isCurrentPageProvider(
PageLabel.logs,
@@ -47,18 +59,6 @@ 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
@@ -122,7 +122,7 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
final height = globalState.measure
.computeTextSize(
Text(
log.payload,
log.payload ?? "",
style: globalState.appController.context.textTheme.bodyLarge,
),
maxWidth: _currentMaxWidth,
@@ -153,7 +153,8 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
return LayoutBuilder(
builder: (_, constraints) {
_handleTryClearCache(constraints.maxWidth - 40);
return TextScaleNotification(
return Align(
alignment: Alignment.topCenter,
child: ValueListenableBuilder<LogsState>(
valueListenable: _logsStateNotifier,
builder: (_, state, __) {
@@ -166,7 +167,7 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
final items = logs
.map<Widget>(
(log) => LogItem(
key: Key(log.dateTime),
key: Key(log.dateTime.toString()),
log: log,
onClick: (value) {
context.commonScaffoldState?.addKeyword(value);
@@ -179,49 +180,44 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
),
)
.toList();
return Align(
alignment: Alignment.topCenter,
child: ScrollToEndBox<Log>(
return NotificationListener<ScrollEndNotification>(
onNotification: (details) {
_preOffset = details.metrics.pixels;
return false;
},
child: CommonScrollBar(
controller: _scrollController,
cacheKey: _cacheKey,
dataSource: logs,
child: CommonScrollBar(
child: CacheItemExtentListView(
key: _key,
reverse: true,
shrinkWrap: true,
physics: NextClampingScrollPhysics(),
controller: _scrollController,
child: CacheItemExtentListView(
key: _key,
reverse: true,
shrinkWrap: true,
physics: NextClampingScrollPhysics(),
controller: _scrollController,
itemBuilder: (_, index) {
return items[index];
},
itemExtentBuilder: (index) {
final item = items[index];
if (item.runtimeType == Divider) {
return 0;
}
final log = logs[(index / 2).floor()];
return _getItemHeight(log);
},
itemCount: items.length,
keyBuilder: (int index) {
final item = items[index];
if (item.runtimeType == Divider) {
return "divider";
}
final log = logs[(index / 2).floor()];
return log.payload;
},
),
itemBuilder: (_, index) {
return items[index];
},
itemExtentBuilder: (index) {
final item = items[index];
if (item.runtimeType == Divider) {
return 0;
}
final log = logs[(index / 2).floor()];
return _getItemHeight(log);
},
itemCount: items.length,
keyBuilder: (int index) {
final item = items[index];
if (item.runtimeType == Divider) {
return "divider";
}
final log = logs[(index / 2).floor()];
return log.payload ?? "";
},
),
),
);
},
),
onNotification: (_) {
_key.currentState?.clearCache();
},
);
},
);
@@ -246,14 +242,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,
),

View File

@@ -104,13 +104,8 @@ class _URLFormDialogState extends State<URLFormDialog> {
runSpacing: 16,
children: [
TextField(
keyboardType: TextInputType.url,
minLines: 1,
maxLines: 5,
onSubmitted: (_) {
_handleAddProfileFormURL();
},
onEditingComplete: _handleAddProfileFormURL,
minLines: 1,
controller: urlController,
decoration: InputDecoration(
border: const OutlineInputBorder(),

View File

@@ -214,7 +214,6 @@ class _EditProfileState extends State<EditProfile> {
final items = [
ListItem(
title: TextFormField(
textInputAction: TextInputAction.next,
controller: labelController,
decoration: InputDecoration(
border: const OutlineInputBorder(),
@@ -231,8 +230,6 @@ 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,
@@ -261,7 +258,6 @@ class _EditProfileState extends State<EditProfile> {
if (autoUpdate)
ListItem(
title: TextFormField(
textInputAction: TextInputAction.next,
controller: autoUpdateDurationController,
decoration: InputDecoration(
border: const OutlineInputBorder(),

View File

@@ -228,7 +228,7 @@ class _OverrideProfileState extends State<OverrideProfile> {
message: TextSpan(
text: appLocalizations.saveTip,
),
confirmText: appLocalizations.save,
confirmText: appLocalizations.tip,
);
if (res != true) {
return;
@@ -873,8 +873,6 @@ class _AddRuleDialogState extends State<AddRuleDialog> {
builder: (filed) {
return DropdownMenu(
width: 200,
enableFilter: false,
enableSearch: false,
controller: _subRuleController,
label: Text(appLocalizations.subRule),
menuHeight: 250,
@@ -892,11 +890,11 @@ class _AddRuleDialogState extends State<AddRuleDialog> {
builder: (filed) {
return DropdownMenu(
controller: _ruleTargetController,
initialSelection: filed.value,
label: Text(appLocalizations.ruleTarget),
width: 200,
menuHeight: 250,
enableFilter: false,
enableSearch: false,
enableFilter: true,
dropdownMenuEntries: _targetItems,
errorText: filed.errorText,
);

View File

@@ -63,7 +63,7 @@ class ProxyCard extends StatelessWidget {
delay > 0 ? '$delay ms' : "Timeout",
style: context.textTheme.labelSmall?.copyWith(
overflow: TextOverflow.ellipsis,
color: utils.getDelayColor(
color: other.getDelayColor(
delay,
),
),

View File

@@ -6,7 +6,7 @@ import 'package:fl_clash/state.dart';
double get listHeaderHeight {
final measure = globalState.measure;
return 28 + measure.titleMediumHeight + 4 + measure.bodyMediumHeight;
return 24 + measure.titleMediumHeight + 4 + measure.bodyMediumHeight;
}
double getItemHeight(ProxyCardType proxyCardType) {

View File

@@ -414,10 +414,7 @@ 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) {
@@ -433,44 +430,30 @@ class _ListHeaderState extends State<ListHeader>
return this.icon;
}));
return switch (iconStyle) {
ProxiesIconStyle.standard => LayoutBuilder(
builder: (_, constraints) {
return Container(
margin: const EdgeInsets.only(
right: 16,
),
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),
),
clipBehavior: Clip.antiAlias,
child: CommonTargetIcon(
src: icon,
size: constraints.maxHeight - 12.ap,
),
),
),
);
},
ProxiesIconStyle.standard => Container(
height: 48,
width: 48,
margin: const EdgeInsets.only(
right: 16,
),
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: context.colorScheme.secondaryContainer,
borderRadius: BorderRadius.circular(12),
),
clipBehavior: Clip.antiAlias,
child: CommonTargetIcon(
src: icon,
size: 32,
),
),
ProxiesIconStyle.icon => Container(
margin: const EdgeInsets.only(
right: 16,
),
child: LayoutBuilder(
builder: (_, constraints) {
return CommonTargetIcon(
src: icon,
size: constraints.maxHeight - 8,
);
},
child: CommonTargetIcon(
src: icon,
size: 42,
),
),
ProxiesIconStyle.none => Container(),

View File

@@ -78,7 +78,7 @@ class _ProxiesFragmentState extends ConsumerState<ProxiesFragment>
return AdaptiveSheetScaffold(
type: type,
body: const ProxiesSetting(),
title: appLocalizations.settings,
title: appLocalizations.proxiesSetting,
);
},
);

View File

@@ -1,18 +1,9 @@
// ignore_for_file: deprecated_member_use
import 'dart:math';
import 'dart:ui' as ui;
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/enum/enum.dart';
import 'package:fl_clash/models/selector.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 'package:intl/intl.dart';
class ThemeModeItem {
final ThemeMode themeMode;
@@ -41,17 +32,25 @@ class ThemeFragment extends StatelessWidget {
@override
Widget build(BuildContext context) {
final previewCard = Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: CommonCard(
onPressed: () {},
info: Info(
label: appLocalizations.preview,
iconData: Icons.looks,
),
child: Container(
height: 200,
),
),
);
return SingleChildScrollView(
child: Column(
spacing: 24,
mainAxisSize: MainAxisSize.min,
children: [
_ThemeModeItem(),
_PrimaryColorItem(),
_PrueBlackItem(),
_TextScaleFactorItem(),
const SizedBox(
height: 64,
),
previewCard,
const ThemeColorsBox(),
],
),
);
@@ -61,30 +60,125 @@ class ThemeFragment extends StatelessWidget {
class ItemCard extends StatelessWidget {
final Widget child;
final Info info;
final List<Widget> actions;
const ItemCard({
super.key,
required this.info,
required this.child,
this.actions = const [],
});
@override
Widget build(BuildContext context) {
return Wrap(
runSpacing: 16,
return Padding(
padding: const EdgeInsets.only(
top: 16,
),
child: Wrap(
runSpacing: 16,
children: [
InfoHeader(
info: info,
),
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: [
InfoHeader(
info: info,
actions: actions,
// _FontFamilyItem(),
_ThemeModeItem(),
_PrimaryColorItem(),
_PrueBlackItem(),
const SizedBox(
height: 64,
),
child,
],
);
}
}
// class _FontFamilyItem extends ConsumerWidget {
// const _FontFamilyItem();
//
// @override
// Widget build(BuildContext context, WidgetRef ref) {
// final fontFamily =
// ref.watch(themeSettingProvider.select((state) => state.fontFamily));
// List<FontFamilyItem> fontFamilyItems = [
// FontFamilyItem(
// label: appLocalizations.systemFont,
// fontFamily: FontFamily.system,
// ),
// const FontFamilyItem(
// label: "roboto",
// fontFamily: FontFamily.roboto,
// ),
// ];
// return ItemCard(
// info: Info(
// label: appLocalizations.fontFamily,
// iconData: Icons.text_fields,
// ),
// child: Container(
// margin: const EdgeInsets.only(
// left: 16,
// right: 16,
// ),
// height: 48,
// child: ListView.separated(
// scrollDirection: Axis.horizontal,
// itemBuilder: (_, index) {
// final fontFamilyItem = fontFamilyItems[index];
// return CommonCard(
// isSelected: fontFamilyItem.fontFamily == fontFamily,
// onPressed: () {
// ref.read(themeSettingProvider.notifier).updateState(
// (state) => state.copyWith(
// fontFamily: fontFamilyItem.fontFamily,
// ),
// );
// },
// child: Padding(
// padding: const EdgeInsets.symmetric(horizontal: 16),
// child: Row(
// mainAxisSize: MainAxisSize.min,
// mainAxisAlignment: MainAxisAlignment.start,
// children: [
// Flexible(
// child: Text(
// fontFamilyItem.label,
// ),
// ),
// ],
// ),
// ),
// );
// },
// separatorBuilder: (_, __) {
// return const SizedBox(
// width: 16,
// );
// },
// itemCount: fontFamilyItems.length,
// ),
// ),
// );
// }
// }
class _ThemeModeItem extends ConsumerWidget {
const _ThemeModeItem();
@@ -116,7 +210,7 @@ class _ThemeModeItem extends ConsumerWidget {
),
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
height: 56,
height: 64,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemCount: themeModeItems.length,
@@ -164,272 +258,56 @@ class _ThemeModeItem extends ConsumerWidget {
}
}
class _PrimaryColorItem extends ConsumerStatefulWidget {
class _PrimaryColorItem extends ConsumerWidget {
const _PrimaryColorItem();
@override
ConsumerState<_PrimaryColorItem> createState() => _PrimaryColorItemState();
}
class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
int? _removablePrimaryColor;
int _calcColumns(double maxWidth) {
return max((maxWidth / 96).ceil(), 3);
}
_handleReset() async {
final res = await globalState.showMessage(
message: TextSpan(
text: appLocalizations.resetTip,
Widget build(BuildContext context, WidgetRef ref) {
final primaryColor =
ref.watch(themeSettingProvider.select((state) => state.primaryColor));
List<Color?> primaryColors = [
null,
defaultPrimaryColor,
Colors.pinkAccent,
Colors.lightBlue,
Colors.greenAccent,
Colors.yellowAccent,
Colors.purple,
];
return ItemCard(
info: Info(
label: appLocalizations.themeColor,
iconData: Icons.palette,
),
);
if (res != true) {
return;
}
ref.read(themeSettingProvider.notifier).updateState(
(state) {
return state.copyWith(
primaryColors: defaultPrimaryColors,
primaryColor: defaultPrimaryColor,
schemeVariant: DynamicSchemeVariant.tonalSpot,
);
},
);
}
_handleDel() async {
if (_removablePrimaryColor == null) {
return;
}
final res = await globalState.showMessage(
message: TextSpan(text: appLocalizations.deleteColorTip));
if (res != true) {
return;
}
ref.read(themeSettingProvider.notifier).updateState(
(state) {
final newPrimaryColors = List<int>.from(state.primaryColors)
..remove(_removablePrimaryColor);
int? newPrimaryColor = state.primaryColor;
if (state.primaryColor == _removablePrimaryColor) {
if (newPrimaryColors.contains(defaultPrimaryColor)) {
newPrimaryColor = defaultPrimaryColor;
} else {
newPrimaryColor = null;
}
}
return state.copyWith(
primaryColors: newPrimaryColors,
primaryColor: newPrimaryColor,
);
},
);
setState(() {
_removablePrimaryColor = null;
});
}
_handleAdd() async {
final res = await globalState.showCommonDialog<int>(
child: _PaletteDialog(),
);
if (res == null) {
return;
}
final isExists = ref.read(
themeSettingProvider.select((state) => state.primaryColors.contains(res)),
);
if (isExists && mounted) {
context.showNotifier(appLocalizations.colorExists);
return;
}
ref.read(themeSettingProvider.notifier).updateState(
(state) {
return state.copyWith(
primaryColors: List.from(
state.primaryColors,
)..add(res),
);
},
);
}
_handleChangeSchemeVariant() async {
final schemeVariant = ref.read(
themeSettingProvider.select(
(state) => state.schemeVariant,
),
);
final value = await globalState.showCommonDialog<DynamicSchemeVariant>(
child: OptionsDialog<DynamicSchemeVariant>(
title: appLocalizations.colorSchemes,
options: DynamicSchemeVariant.values,
textBuilder: (item) => Intl.message("${item.name}Scheme"),
value: schemeVariant,
),
);
if (value == null) {
return;
}
ref.read(themeSettingProvider.notifier).updateState(
(state) {
return state.copyWith(
schemeVariant: value,
);
},
);
}
@override
Widget build(BuildContext context) {
final vm4 = ref.watch(
themeSettingProvider.select(
(state) => VM4(
a: state.primaryColor,
b: state.primaryColors,
c: state.schemeVariant,
d: state.primaryColor == defaultPrimaryColor &&
intListEquality.equals(state.primaryColors, defaultPrimaryColors),
child: Container(
margin: const EdgeInsets.only(
left: 16,
right: 16,
bottom: 16,
),
),
);
final primaryColor = vm4.a;
final primaryColors = [null, ...vm4.b];
final schemeVariant = vm4.c;
final isEquals = vm4.d;
return CommonPopScope(
onPop: () {
if (_removablePrimaryColor != null) {
setState(() {
_removablePrimaryColor = null;
});
return false;
}
return true;
},
child: ItemCard(
info: Info(
label: appLocalizations.themeColor,
iconData: Icons.palette,
),
actions: genActions(
[
if (_removablePrimaryColor == null)
FilledButton(
style: ButtonStyle(
visualDensity: VisualDensity.compact,
),
onPressed: _handleChangeSchemeVariant,
child: Text(Intl.message("${schemeVariant.name}Scheme")),
),
if (_removablePrimaryColor != null)
FilledButton(
style: ButtonStyle(
visualDensity: VisualDensity.compact,
),
onPressed: () {
setState(() {
_removablePrimaryColor = null;
});
},
child: Text(appLocalizations.cancel),
),
if (_removablePrimaryColor == null && !isEquals)
IconButton.filledTonal(
iconSize: 20,
padding: EdgeInsets.all(4),
visualDensity: VisualDensity.compact,
onPressed: _handleReset,
icon: Icon(Icons.replay),
)
],
space: 8,
),
child: Container(
margin: const EdgeInsets.symmetric(
horizontal: 16,
),
child: LayoutBuilder(
builder: (_, constraints) {
final columns = _calcColumns(constraints.maxWidth);
final itemWidth =
(constraints.maxWidth - (columns - 1) * 16) / columns;
return Wrap(
spacing: 16,
runSpacing: 16,
children: [
for (final color in primaryColors)
Container(
clipBehavior: Clip.none,
width: itemWidth,
height: itemWidth,
child: Stack(
alignment: Alignment.center,
clipBehavior: Clip.none,
children: [
EffectGestureDetector(
child: ColorSchemeBox(
isSelected: color == primaryColor,
primaryColor: color != null ? Color(color) : null,
onPressed: () {
setState(() {
_removablePrimaryColor = null;
});
ref
.read(themeSettingProvider.notifier)
.updateState(
(state) => state.copyWith(
primaryColor: color,
),
);
},
),
onLongPress: () {
setState(() {
_removablePrimaryColor = color;
});
},
),
if (_removablePrimaryColor != null &&
_removablePrimaryColor == color)
Container(
color: Colors.white.opacity0,
padding: EdgeInsets.all(8),
child: IconButton.filledTonal(
onPressed: _handleDel,
padding: EdgeInsets.all(12),
iconSize: 30,
icon: Icon(
color: context.colorScheme.primary,
Icons.delete,
),
),
),
],
height: 88,
child: ListView.separated(
scrollDirection: Axis.horizontal,
itemBuilder: (_, index) {
final color = primaryColors[index];
return ColorSchemeBox(
isSelected: color?.toARGB32() == primaryColor,
primaryColor: color,
onPressed: () {
ref.read(themeSettingProvider.notifier).updateState(
(state) => state.copyWith(
primaryColor: color?.toARGB32(),
),
),
if (_removablePrimaryColor == null)
Container(
width: itemWidth,
height: itemWidth,
padding: EdgeInsets.all(
4,
),
child: IconButton.filledTonal(
onPressed: _handleAdd,
iconSize: 32,
icon: Icon(
color: context.colorScheme.primary,
Icons.add,
),
),
)
],
);
},
),
);
},
);
},
separatorBuilder: (_, __) {
return const SizedBox(
width: 16,
);
},
itemCount: primaryColors.length,
),
),
);
@@ -441,289 +319,27 @@ class _PrueBlackItem extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final prueBlack = ref.watch(
themeSettingProvider.select(
(state) => state.pureBlack,
),
);
return ListItem.switchItem(
leading: Icon(
Icons.contrast,
),
horizontalTitleGap: 12,
title: Text(
appLocalizations.pureBlackMode,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
color: context.colorScheme.onSurfaceVariant,
),
),
delegate: SwitchDelegate(
value: prueBlack,
onChanged: (value) {
ref.read(themeSettingProvider.notifier).updateState(
(state) => state.copyWith(
pureBlack: value,
),
);
},
),
);
}
}
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,
),
);
},
),
),
final prueBlack =
ref.watch(themeSettingProvider.select((state) => state.pureBlack));
return Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: ListItem.switchItem(
leading: Icon(
Icons.contrast,
color: context.colorScheme.primary,
),
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: 0.8,
max: 1.2,
value: textScale.scale,
onChanged: (value) {
ref.read(themeSettingProvider.notifier).updateState(
(state) => state.copyWith.textScale(
scale: value,
),
);
},
),
),
title: Text(appLocalizations.pureBlackMode),
delegate: SwitchDelegate(
value: prueBlack,
onChanged: (value) {
ref.read(themeSettingProvider.notifier).updateState(
(state) => state.copyWith(
pureBlack: value,
),
),
),
Padding(
padding: EdgeInsets.only(right: 4),
child: Text(
process,
style: context.textTheme.titleMedium,
),
),
],
),
),
],
);
}
}
class _PaletteDialog extends StatefulWidget {
const _PaletteDialog();
@override
State<_PaletteDialog> createState() => _PaletteDialogState();
}
class _PaletteDialogState extends State<_PaletteDialog> {
final _controller = ValueNotifier<ui.Color>(Colors.transparent);
@override
Widget build(BuildContext context) {
return CommonDialog(
title: appLocalizations.palette,
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
);
},
child: Text(appLocalizations.cancel),
),
TextButton(
onPressed: () {
Navigator.of(context).pop(_controller.value.toARGB32());
},
child: Text(appLocalizations.confirm),
),
],
child: Column(
children: [
SizedBox(
height: 8,
),
SizedBox(
width: 250,
height: 250,
child: Palette(
controller: _controller,
),
),
SizedBox(
height: 24,
),
ValueListenableBuilder(
valueListenable: _controller,
builder: (_, color, __) {
return PrimaryColorBox(
primaryColor: color,
child: FilledButton(
onPressed: () {},
child: Text(
_controller.value.hex,
),
),
);
},
),
],
),
);
}
}
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;
}

View File

@@ -14,7 +14,6 @@ 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;
@@ -55,12 +54,11 @@ class _ToolboxFragmentState extends ConsumerState<ToolsFragment> {
);
}
List<Widget> _getOtherList(bool enableDeveloperMode) {
List<Widget> _getOtherList() {
return generateSection(
title: appLocalizations.other,
items: [
_DisclaimerItem(),
if (enableDeveloperMode) _DeveloperItem(),
_InfoItem(),
],
);
@@ -84,11 +82,7 @@ class _ToolboxFragmentState extends ConsumerState<ToolsFragment> {
@override
Widget build(BuildContext context) {
final vm2 = ref.watch(
appSettingProvider.select(
(state) => VM2(a: state.locale, b: state.developerMode),
),
);
ref.watch(appSettingProvider.select((state) => state.locale));
final items = [
Consumer(
builder: (_, ref, __) {
@@ -105,7 +99,7 @@ class _ToolboxFragmentState extends ConsumerState<ToolsFragment> {
},
),
..._getSettingList(),
..._getOtherList(vm2.b),
..._getOtherList(),
];
return ListView.builder(
itemCount: items.length,
@@ -128,7 +122,7 @@ class _LocaleItem extends ConsumerWidget {
final locale =
ref.watch(appSettingProvider.select((state) => state.locale));
final subTitle = locale ?? appLocalizations.defaultText;
final currentLocale = utils.getLocaleForString(locale);
final currentLocale = other.getLocaleForString(locale);
return ListItem<Locale?>.options(
leading: const Icon(Icons.language_outlined),
title: Text(appLocalizations.language),
@@ -303,19 +297,3 @@ 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(),
),
);
}
}

View File

@@ -372,28 +372,5 @@
"generalDesc": "Modify general settings",
"findProcessModeDesc": "There is a certain performance loss after opening",
"tabAnimationDesc": "Effective only in mobile view",
"saveTip": "Are you sure you want to save?",
"deleteColorTip": "Are you sure you want to delete the current color?",
"colorExists": "Current color already exists",
"colorSchemes": "Color schemes",
"palette": "Palette",
"tonalSpotScheme": "TonalSpot",
"fidelityScheme": "Fidelity",
"monochromeScheme": "Monochrome",
"neutralScheme": "Neutral",
"vibrantScheme": "Vibrant",
"expressiveScheme": "Expressive",
"contentScheme": "Content",
"rainbowScheme": "Rainbow",
"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"
"saveTip": "Are you sure you want to save?"
}

View File

@@ -372,29 +372,5 @@
"generalDesc": "一般設定を変更",
"findProcessModeDesc": "有効化するとパフォーマンスが若干低下します",
"tabAnimationDesc": "モバイル表示でのみ有効",
"saveTip": "保存してもよろしいですか?",
"deleteColorTip": "現在の色を削除しますか?",
"colorExists": "この色は既に存在します",
"colorSchemes": "カラースキーム",
"palette": "パレット",
"tonalSpotScheme": "トーンスポット",
"fidelityScheme": "ハイファイデリティー",
"monochromeScheme": "モノクローム",
"neutralScheme": "ニュートラル",
"vibrantScheme": "ビブラント",
"expressiveScheme": "エクスプレッシブ",
"contentScheme": "コンテンツテーマ",
"rainbowScheme": "レインボー",
"fruitSaladScheme": "フルーツサラダ",
"developerMode": "デベロッパーモード",
"developerModeEnableTip": "デベロッパーモードが有効になりました。",
"messageTest": "メッセージテスト",
"messageTestTip": "これはメッセージです。",
"crashTest": "クラッシュテスト",
"clearData": "データを消去",
"zoom": "ズーム",
"textScale": "テキストスケーリング",
"internet": "インターネット",
"systemApp": "システムアプリ",
"noNetworkApp": "ネットワークなしアプリ"
"saveTip": "保存してもよろしいですか?"
}

View File

@@ -372,29 +372,5 @@
"generalDesc": "Изменение общих настроек",
"findProcessModeDesc": "При включении возможны небольшие потери производительности",
"tabAnimationDesc": "Действительно только в мобильном виде",
"saveTip": "Вы уверены, что хотите сохранить?",
"deleteColorTip": "Удалить текущий цвет?",
"colorExists": "Этот цвет уже существует",
"colorSchemes": "Цветовые схемы",
"palette": "Палитра",
"tonalSpotScheme": "Тональный акцент",
"fidelityScheme": "Точная передача",
"monochromeScheme": "Монохром",
"neutralScheme": "Нейтральные",
"vibrantScheme": "Яркие",
"expressiveScheme": "Экспрессивные",
"contentScheme": "Контентная тема",
"rainbowScheme": "Радужные",
"fruitSaladScheme": "Фруктовый микс",
"developerMode": "Режим разработчика",
"developerModeEnableTip": "Режим разработчика активирован.",
"messageTest": "Тестирование сообщения",
"messageTestTip": "Это сообщение.",
"crashTest": "Тест на сбои",
"clearData": "Очистить данные",
"zoom": "Масштаб",
"textScale": "Масштабирование текста",
"internet": "Интернет",
"systemApp": "Системное приложение",
"noNetworkApp": "Приложение без сети"
"saveTip": "Вы уверены, что хотите сохранить?"
}

View File

@@ -372,29 +372,5 @@
"generalDesc": "修改通用设置",
"findProcessModeDesc": "开启后会有一定性能损耗",
"tabAnimationDesc": "仅在移动视图中有效",
"saveTip": "确定要保存吗?",
"deleteColorTip": "确定删除当前颜色吗?",
"colorExists": "该颜色已存在",
"colorSchemes": "配色方案",
"palette": "调色板",
"tonalSpotScheme": "调性点缀",
"fidelityScheme": "高保真",
"monochromeScheme": "单色",
"neutralScheme": "中性",
"vibrantScheme": "活力",
"expressiveScheme": "表现力",
"contentScheme": "内容主题",
"rainbowScheme": "彩虹",
"fruitSaladScheme": "果缤纷",
"developerMode": "开发者模式",
"developerModeEnableTip": "开发者模式已启用。",
"messageTest": "消息测试",
"messageTestTip": "这是一条消息。",
"crashTest": "崩溃测试",
"clearData": "清除数据",
"zoom": "缩放",
"textScale": "文本缩放",
"internet": "互联网",
"systemApp": "系统应用",
"noNetworkApp": "无网络应用"
"saveTip": "确定要保存吗?"
}

View File

@@ -146,13 +146,8 @@ 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(
"Current color already exists",
),
"colorSchemes": MessageLookupByLibrary.simpleMessage("Color schemes"),
"columns": MessageLookupByLibrary.simpleMessage("Columns"),
"compatible": MessageLookupByLibrary.simpleMessage("Compatibility mode"),
"compatibleDesc": MessageLookupByLibrary.simpleMessage(
@@ -168,7 +163,6 @@ class MessageLookup extends MessageLookupByLibrary {
"contentEmptyTip": MessageLookupByLibrary.simpleMessage(
"Content cannot be empty",
),
"contentScheme": MessageLookupByLibrary.simpleMessage("Content"),
"copy": MessageLookupByLibrary.simpleMessage("Copy"),
"copyEnvVar": MessageLookupByLibrary.simpleMessage(
"Copying environment variables",
@@ -178,7 +172,6 @@ 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"),
@@ -195,9 +188,6 @@ class MessageLookup extends MessageLookupByLibrary {
"delay": MessageLookupByLibrary.simpleMessage("Delay"),
"delaySort": MessageLookupByLibrary.simpleMessage("Sort by delay"),
"delete": MessageLookupByLibrary.simpleMessage("Delete"),
"deleteColorTip": MessageLookupByLibrary.simpleMessage(
"Are you sure you want to delete the current color?",
),
"deleteProfileTip": MessageLookupByLibrary.simpleMessage(
"Sure you want to delete the current profile?",
),
@@ -210,10 +200,6 @@ 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(
@@ -248,7 +234,6 @@ class MessageLookup extends MessageLookupByLibrary {
"exportFile": MessageLookupByLibrary.simpleMessage("Export file"),
"exportLogs": MessageLookupByLibrary.simpleMessage("Export logs"),
"exportSuccess": MessageLookupByLibrary.simpleMessage("Export Success"),
"expressiveScheme": MessageLookupByLibrary.simpleMessage("Expressive"),
"externalController": MessageLookupByLibrary.simpleMessage(
"ExternalController",
),
@@ -266,7 +251,6 @@ class MessageLookup extends MessageLookupByLibrary {
"Generally use offshore DNS",
),
"fallbackFilter": MessageLookupByLibrary.simpleMessage("Fallback filter"),
"fidelityScheme": MessageLookupByLibrary.simpleMessage("Fidelity"),
"file": MessageLookupByLibrary.simpleMessage("File"),
"fileDesc": MessageLookupByLibrary.simpleMessage("Directly upload profile"),
"fileIsUpdate": MessageLookupByLibrary.simpleMessage(
@@ -281,7 +265,6 @@ class MessageLookup extends MessageLookupByLibrary {
),
"fontFamily": MessageLookupByLibrary.simpleMessage("FontFamily"),
"fourColumns": MessageLookupByLibrary.simpleMessage("Four columns"),
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("FruitSalad"),
"general": MessageLookupByLibrary.simpleMessage("General"),
"generalDesc": MessageLookupByLibrary.simpleMessage(
"Modify general settings",
@@ -326,7 +309,6 @@ 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(
@@ -369,10 +351,6 @@ class MessageLookup extends MessageLookupByLibrary {
),
"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(
@@ -380,7 +358,6 @@ class MessageLookup extends MessageLookupByLibrary {
),
"minutes": MessageLookupByLibrary.simpleMessage("Minutes"),
"mode": MessageLookupByLibrary.simpleMessage("Mode"),
"monochromeScheme": MessageLookupByLibrary.simpleMessage("Monochrome"),
"months": MessageLookupByLibrary.simpleMessage("Months"),
"more": MessageLookupByLibrary.simpleMessage("More"),
"name": MessageLookupByLibrary.simpleMessage("Name"),
@@ -403,14 +380,12 @@ class MessageLookup extends MessageLookupByLibrary {
"Network detection",
),
"networkSpeed": MessageLookupByLibrary.simpleMessage("Network speed"),
"neutralScheme": MessageLookupByLibrary.simpleMessage("Neutral"),
"noData": MessageLookupByLibrary.simpleMessage("No data"),
"noHotKey": MessageLookupByLibrary.simpleMessage("No HotKey"),
"noIcon": MessageLookupByLibrary.simpleMessage("None"),
"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",
@@ -461,7 +436,6 @@ class MessageLookup extends MessageLookupByLibrary {
"overrideOriginRules": MessageLookupByLibrary.simpleMessage(
"Override the original rule",
),
"palette": MessageLookupByLibrary.simpleMessage("Palette"),
"password": MessageLookupByLibrary.simpleMessage("Password"),
"passwordTip": MessageLookupByLibrary.simpleMessage(
"Password cannot be empty",
@@ -532,7 +506,6 @@ class MessageLookup extends MessageLookupByLibrary {
"qrcodeDesc": MessageLookupByLibrary.simpleMessage(
"Scan QR code to obtain profile",
),
"rainbowScheme": MessageLookupByLibrary.simpleMessage("Rainbow"),
"recovery": MessageLookupByLibrary.simpleMessage("Recovery"),
"recoveryAll": MessageLookupByLibrary.simpleMessage("Recovery all data"),
"recoveryProfiles": MessageLookupByLibrary.simpleMessage(
@@ -624,7 +597,6 @@ 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(
@@ -640,7 +612,6 @@ 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(
@@ -652,7 +623,6 @@ class MessageLookup extends MessageLookupByLibrary {
"time": MessageLookupByLibrary.simpleMessage("Time"),
"tip": MessageLookupByLibrary.simpleMessage("tip"),
"toggle": MessageLookupByLibrary.simpleMessage("Toggle"),
"tonalSpotScheme": MessageLookupByLibrary.simpleMessage("TonalSpot"),
"tools": MessageLookupByLibrary.simpleMessage("Tools"),
"trafficUsage": MessageLookupByLibrary.simpleMessage("Traffic usage"),
"tun": MessageLookupByLibrary.simpleMessage("TUN"),
@@ -681,7 +651,6 @@ class MessageLookup extends MessageLookupByLibrary {
"valueExists": MessageLookupByLibrary.simpleMessage(
"The current value already exists",
),
"vibrantScheme": MessageLookupByLibrary.simpleMessage("Vibrant"),
"view": MessageLookupByLibrary.simpleMessage("View"),
"vpnDesc": MessageLookupByLibrary.simpleMessage(
"Modify VPN related settings",

View File

@@ -104,11 +104,8 @@ 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("この色は既に存在します"),
"colorSchemes": MessageLookupByLibrary.simpleMessage("カラースキーム"),
"columns": MessageLookupByLibrary.simpleMessage(""),
"compatible": MessageLookupByLibrary.simpleMessage("互換モード"),
"compatibleDesc": MessageLookupByLibrary.simpleMessage(
@@ -120,7 +117,6 @@ class MessageLookup extends MessageLookupByLibrary {
"connectivity": MessageLookupByLibrary.simpleMessage("接続性:"),
"content": MessageLookupByLibrary.simpleMessage("内容"),
"contentEmptyTip": MessageLookupByLibrary.simpleMessage("内容は必須です"),
"contentScheme": MessageLookupByLibrary.simpleMessage("コンテンツテーマ"),
"copy": MessageLookupByLibrary.simpleMessage("コピー"),
"copyEnvVar": MessageLookupByLibrary.simpleMessage("環境変数をコピー"),
"copyLink": MessageLookupByLibrary.simpleMessage("リンクをコピー"),
@@ -128,7 +124,6 @@ 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("ダーク"),
@@ -143,7 +138,6 @@ class MessageLookup extends MessageLookupByLibrary {
"delay": MessageLookupByLibrary.simpleMessage("遅延"),
"delaySort": MessageLookupByLibrary.simpleMessage("遅延順"),
"delete": MessageLookupByLibrary.simpleMessage("削除"),
"deleteColorTip": MessageLookupByLibrary.simpleMessage("現在の色を削除しますか?"),
"deleteProfileTip": MessageLookupByLibrary.simpleMessage(
"現在のプロファイルを削除しますか?",
),
@@ -152,10 +146,6 @@ class MessageLookup extends MessageLookupByLibrary {
"ClashMetaベースのマルチプラットフォームプロキシクライアント。シンプルで使いやすく、オープンソースで広告なし。",
),
"detectionTip": MessageLookupByLibrary.simpleMessage("サードパーティAPIに依存参考値"),
"developerMode": MessageLookupByLibrary.simpleMessage("デベロッパーモード"),
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage(
"デベロッパーモードが有効になりました。",
),
"direct": MessageLookupByLibrary.simpleMessage("ダイレクト"),
"disclaimer": MessageLookupByLibrary.simpleMessage("免責事項"),
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
@@ -182,7 +172,6 @@ class MessageLookup extends MessageLookupByLibrary {
"exportFile": MessageLookupByLibrary.simpleMessage("ファイルをエクスポート"),
"exportLogs": MessageLookupByLibrary.simpleMessage("ログをエクスポート"),
"exportSuccess": MessageLookupByLibrary.simpleMessage("エクスポート成功"),
"expressiveScheme": MessageLookupByLibrary.simpleMessage("エクスプレッシブ"),
"externalController": MessageLookupByLibrary.simpleMessage("外部コントローラー"),
"externalControllerDesc": MessageLookupByLibrary.simpleMessage(
"有効化するとClashコアをポート9090で制御可能",
@@ -194,7 +183,6 @@ class MessageLookup extends MessageLookupByLibrary {
"fallback": MessageLookupByLibrary.simpleMessage("フォールバック"),
"fallbackDesc": MessageLookupByLibrary.simpleMessage("通常はオフショアDNSを使用"),
"fallbackFilter": MessageLookupByLibrary.simpleMessage("フォールバックフィルター"),
"fidelityScheme": MessageLookupByLibrary.simpleMessage("ハイファイデリティー"),
"file": MessageLookupByLibrary.simpleMessage("ファイル"),
"fileDesc": MessageLookupByLibrary.simpleMessage("プロファイルを直接アップロード"),
"fileIsUpdate": MessageLookupByLibrary.simpleMessage(
@@ -207,7 +195,6 @@ class MessageLookup extends MessageLookupByLibrary {
),
"fontFamily": MessageLookupByLibrary.simpleMessage("フォントファミリー"),
"fourColumns": MessageLookupByLibrary.simpleMessage("4列"),
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("フルーツサラダ"),
"general": MessageLookupByLibrary.simpleMessage("一般"),
"generalDesc": MessageLookupByLibrary.simpleMessage("一般設定を変更"),
"geoData": MessageLookupByLibrary.simpleMessage("地域データ"),
@@ -236,7 +223,6 @@ 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トラフィックを受信可能"),
@@ -265,8 +251,6 @@ class MessageLookup extends MessageLookupByLibrary {
"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(
@@ -274,7 +258,6 @@ class MessageLookup extends MessageLookupByLibrary {
),
"minutes": MessageLookupByLibrary.simpleMessage(""),
"mode": MessageLookupByLibrary.simpleMessage("モード"),
"monochromeScheme": MessageLookupByLibrary.simpleMessage("モノクローム"),
"months": MessageLookupByLibrary.simpleMessage(""),
"more": MessageLookupByLibrary.simpleMessage("詳細"),
"name": MessageLookupByLibrary.simpleMessage("名前"),
@@ -289,14 +272,12 @@ class MessageLookup extends MessageLookupByLibrary {
"networkDesc": MessageLookupByLibrary.simpleMessage("ネットワーク関連設定の変更"),
"networkDetection": MessageLookupByLibrary.simpleMessage("ネットワーク検出"),
"networkSpeed": MessageLookupByLibrary.simpleMessage("ネットワーク速度"),
"neutralScheme": MessageLookupByLibrary.simpleMessage("ニュートラル"),
"noData": MessageLookupByLibrary.simpleMessage("データなし"),
"noHotKey": MessageLookupByLibrary.simpleMessage("ホットキーなし"),
"noIcon": MessageLookupByLibrary.simpleMessage("なし"),
"noInfo": MessageLookupByLibrary.simpleMessage("情報なし"),
"noMoreInfoDesc": MessageLookupByLibrary.simpleMessage("追加情報なし"),
"noNetwork": MessageLookupByLibrary.simpleMessage("ネットワークなし"),
"noNetworkApp": MessageLookupByLibrary.simpleMessage("ネットワークなしアプリ"),
"noProxy": MessageLookupByLibrary.simpleMessage("プロキシなし"),
"noProxyDesc": MessageLookupByLibrary.simpleMessage(
"プロファイルを作成するか、有効なプロファイルを追加してください",
@@ -333,7 +314,6 @@ class MessageLookup extends MessageLookupByLibrary {
"有効化するとプロファイルのDNS設定を上書き",
),
"overrideOriginRules": MessageLookupByLibrary.simpleMessage("元のルールを上書き"),
"palette": MessageLookupByLibrary.simpleMessage("パレット"),
"password": MessageLookupByLibrary.simpleMessage("パスワード"),
"passwordTip": MessageLookupByLibrary.simpleMessage("パスワードは必須です"),
"paste": MessageLookupByLibrary.simpleMessage("貼り付け"),
@@ -390,7 +370,6 @@ class MessageLookup extends MessageLookupByLibrary {
"pureBlackMode": MessageLookupByLibrary.simpleMessage("純黒モード"),
"qrcode": MessageLookupByLibrary.simpleMessage("QRコード"),
"qrcodeDesc": MessageLookupByLibrary.simpleMessage("QRコードをスキャンしてプロファイルを取得"),
"rainbowScheme": MessageLookupByLibrary.simpleMessage("レインボー"),
"recovery": MessageLookupByLibrary.simpleMessage("復元"),
"recoveryAll": MessageLookupByLibrary.simpleMessage("全データ復元"),
"recoveryProfiles": MessageLookupByLibrary.simpleMessage("プロファイルのみ復元"),
@@ -462,7 +441,6 @@ 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(
@@ -474,7 +452,6 @@ 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("ダークモードの設定、色の調整"),
@@ -484,7 +461,6 @@ class MessageLookup extends MessageLookupByLibrary {
"time": MessageLookupByLibrary.simpleMessage("時間"),
"tip": MessageLookupByLibrary.simpleMessage("ヒント"),
"toggle": MessageLookupByLibrary.simpleMessage("トグル"),
"tonalSpotScheme": MessageLookupByLibrary.simpleMessage("トーンスポット"),
"tools": MessageLookupByLibrary.simpleMessage("ツール"),
"trafficUsage": MessageLookupByLibrary.simpleMessage("トラフィック使用量"),
"tun": MessageLookupByLibrary.simpleMessage("TUN"),
@@ -507,7 +483,6 @@ class MessageLookup extends MessageLookupByLibrary {
"useSystemHosts": MessageLookupByLibrary.simpleMessage("システムホストを使用"),
"value": MessageLookupByLibrary.simpleMessage(""),
"valueExists": MessageLookupByLibrary.simpleMessage("現在の値は既に存在します"),
"vibrantScheme": MessageLookupByLibrary.simpleMessage("ビブラント"),
"view": MessageLookupByLibrary.simpleMessage("表示"),
"vpnDesc": MessageLookupByLibrary.simpleMessage("VPN関連設定の変更"),
"vpnEnableDesc": MessageLookupByLibrary.simpleMessage(

View File

@@ -148,17 +148,12 @@ class MessageLookup extends MessageLookupByLibrary {
"Текущее приложение уже является последней версией",
),
"checking": MessageLookupByLibrary.simpleMessage("Проверка..."),
"clearData": MessageLookupByLibrary.simpleMessage("Очистить данные"),
"clipboardExport": MessageLookupByLibrary.simpleMessage(
"Экспорт в буфер обмена",
),
"clipboardImport": MessageLookupByLibrary.simpleMessage(
"Импорт из буфера обмена",
),
"colorExists": MessageLookupByLibrary.simpleMessage(
"Этот цвет уже существует",
),
"colorSchemes": MessageLookupByLibrary.simpleMessage("Цветовые схемы"),
"columns": MessageLookupByLibrary.simpleMessage("Столбцы"),
"compatible": MessageLookupByLibrary.simpleMessage("Режим совместимости"),
"compatibleDesc": MessageLookupByLibrary.simpleMessage(
@@ -174,7 +169,6 @@ class MessageLookup extends MessageLookupByLibrary {
"contentEmptyTip": MessageLookupByLibrary.simpleMessage(
"Содержание не может быть пустым",
),
"contentScheme": MessageLookupByLibrary.simpleMessage("Контентная тема"),
"copy": MessageLookupByLibrary.simpleMessage("Копировать"),
"copyEnvVar": MessageLookupByLibrary.simpleMessage(
"Копирование переменных окружения",
@@ -184,7 +178,6 @@ 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("Темный"),
@@ -203,9 +196,6 @@ class MessageLookup extends MessageLookupByLibrary {
"delay": MessageLookupByLibrary.simpleMessage("Задержка"),
"delaySort": MessageLookupByLibrary.simpleMessage("Сортировка по задержке"),
"delete": MessageLookupByLibrary.simpleMessage("Удалить"),
"deleteColorTip": MessageLookupByLibrary.simpleMessage(
"Удалить текущий цвет?",
),
"deleteProfileTip": MessageLookupByLibrary.simpleMessage(
"Вы уверены, что хотите удалить текущий профиль?",
),
@@ -218,10 +208,6 @@ class MessageLookup extends MessageLookupByLibrary {
"detectionTip": MessageLookupByLibrary.simpleMessage(
"Опирается на сторонний API, только для справки",
),
"developerMode": MessageLookupByLibrary.simpleMessage("Режим разработчика"),
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage(
"Режим разработчика активирован.",
),
"direct": MessageLookupByLibrary.simpleMessage("Прямой"),
"disclaimer": MessageLookupByLibrary.simpleMessage(
"Отказ от ответственности",
@@ -262,7 +248,6 @@ class MessageLookup extends MessageLookupByLibrary {
"exportFile": MessageLookupByLibrary.simpleMessage("Экспорт файла"),
"exportLogs": MessageLookupByLibrary.simpleMessage("Экспорт логов"),
"exportSuccess": MessageLookupByLibrary.simpleMessage("Экспорт успешен"),
"expressiveScheme": MessageLookupByLibrary.simpleMessage("Экспрессивные"),
"externalController": MessageLookupByLibrary.simpleMessage(
"Внешний контроллер",
),
@@ -282,7 +267,6 @@ class MessageLookup extends MessageLookupByLibrary {
"fallbackFilter": MessageLookupByLibrary.simpleMessage(
"Фильтр резервного DNS",
),
"fidelityScheme": MessageLookupByLibrary.simpleMessage("Точная передача"),
"file": MessageLookupByLibrary.simpleMessage("Файл"),
"fileDesc": MessageLookupByLibrary.simpleMessage("Прямая загрузка профиля"),
"fileIsUpdate": MessageLookupByLibrary.simpleMessage(
@@ -299,7 +283,6 @@ class MessageLookup extends MessageLookupByLibrary {
),
"fontFamily": MessageLookupByLibrary.simpleMessage("Семейство шрифтов"),
"fourColumns": MessageLookupByLibrary.simpleMessage("Четыре столбца"),
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("Фруктовый микс"),
"general": MessageLookupByLibrary.simpleMessage("Общие"),
"generalDesc": MessageLookupByLibrary.simpleMessage(
"Изменение общих настроек",
@@ -348,7 +331,6 @@ class MessageLookup extends MessageLookupByLibrary {
"intelligentSelected": MessageLookupByLibrary.simpleMessage(
"Интеллектуальный выбор",
),
"internet": MessageLookupByLibrary.simpleMessage("Интернет"),
"intranetIP": MessageLookupByLibrary.simpleMessage("Внутренний IP"),
"ipcidr": MessageLookupByLibrary.simpleMessage("IPCIDR"),
"ipv6Desc": MessageLookupByLibrary.simpleMessage(
@@ -393,10 +375,6 @@ class MessageLookup extends MessageLookupByLibrary {
),
"loose": MessageLookupByLibrary.simpleMessage("Свободный"),
"memoryInfo": MessageLookupByLibrary.simpleMessage("Информация о памяти"),
"messageTest": MessageLookupByLibrary.simpleMessage(
"Тестирование сообщения",
),
"messageTestTip": MessageLookupByLibrary.simpleMessage("Это сообщение."),
"min": MessageLookupByLibrary.simpleMessage("Мин"),
"minimizeOnExit": MessageLookupByLibrary.simpleMessage(
"Свернуть при выходе",
@@ -406,7 +384,6 @@ class MessageLookup extends MessageLookupByLibrary {
),
"minutes": MessageLookupByLibrary.simpleMessage("Минут"),
"mode": MessageLookupByLibrary.simpleMessage("Режим"),
"monochromeScheme": MessageLookupByLibrary.simpleMessage("Монохром"),
"months": MessageLookupByLibrary.simpleMessage("Месяцев"),
"more": MessageLookupByLibrary.simpleMessage("Еще"),
"name": MessageLookupByLibrary.simpleMessage("Имя"),
@@ -429,7 +406,6 @@ class MessageLookup extends MessageLookupByLibrary {
"Обнаружение сети",
),
"networkSpeed": MessageLookupByLibrary.simpleMessage("Скорость сети"),
"neutralScheme": MessageLookupByLibrary.simpleMessage("Нейтральные"),
"noData": MessageLookupByLibrary.simpleMessage("Нет данных"),
"noHotKey": MessageLookupByLibrary.simpleMessage("Нет горячей клавиши"),
"noIcon": MessageLookupByLibrary.simpleMessage("Нет иконки"),
@@ -438,7 +414,6 @@ class MessageLookup extends MessageLookupByLibrary {
"Нет дополнительной информации",
),
"noNetwork": MessageLookupByLibrary.simpleMessage("Нет сети"),
"noNetworkApp": MessageLookupByLibrary.simpleMessage("Приложение без сети"),
"noProxy": MessageLookupByLibrary.simpleMessage("Нет прокси"),
"noProxyDesc": MessageLookupByLibrary.simpleMessage(
"Пожалуйста, создайте профиль или добавьте действительный профиль",
@@ -491,7 +466,6 @@ class MessageLookup extends MessageLookupByLibrary {
"overrideOriginRules": MessageLookupByLibrary.simpleMessage(
"Переопределить оригинальное правило",
),
"palette": MessageLookupByLibrary.simpleMessage("Палитра"),
"password": MessageLookupByLibrary.simpleMessage("Пароль"),
"passwordTip": MessageLookupByLibrary.simpleMessage(
"Пароль не может быть пустым",
@@ -564,7 +538,6 @@ class MessageLookup extends MessageLookupByLibrary {
"qrcodeDesc": MessageLookupByLibrary.simpleMessage(
"Сканируйте QR-код для получения профиля",
),
"rainbowScheme": MessageLookupByLibrary.simpleMessage("Радужные"),
"recovery": MessageLookupByLibrary.simpleMessage("Восстановление"),
"recoveryAll": MessageLookupByLibrary.simpleMessage(
"Восстановить все данные",
@@ -662,7 +635,6 @@ 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(
@@ -678,7 +650,6 @@ class MessageLookup extends MessageLookupByLibrary {
"Включение позволит использовать параллелизм TCP",
),
"testUrl": MessageLookupByLibrary.simpleMessage("Тест URL"),
"textScale": MessageLookupByLibrary.simpleMessage("Масштабирование текста"),
"theme": MessageLookupByLibrary.simpleMessage("Тема"),
"themeColor": MessageLookupByLibrary.simpleMessage("Цвет темы"),
"themeDesc": MessageLookupByLibrary.simpleMessage(
@@ -690,7 +661,6 @@ class MessageLookup extends MessageLookupByLibrary {
"time": MessageLookupByLibrary.simpleMessage("Время"),
"tip": MessageLookupByLibrary.simpleMessage("подсказка"),
"toggle": MessageLookupByLibrary.simpleMessage("Переключить"),
"tonalSpotScheme": MessageLookupByLibrary.simpleMessage("Тональный акцент"),
"tools": MessageLookupByLibrary.simpleMessage("Инструменты"),
"trafficUsage": MessageLookupByLibrary.simpleMessage(
"Использование трафика",
@@ -725,7 +695,6 @@ class MessageLookup extends MessageLookupByLibrary {
"valueExists": MessageLookupByLibrary.simpleMessage(
"Текущее значение уже существует",
),
"vibrantScheme": MessageLookupByLibrary.simpleMessage("Яркие"),
"view": MessageLookupByLibrary.simpleMessage("Просмотр"),
"vpnDesc": MessageLookupByLibrary.simpleMessage(
"Изменение настроек, связанных с VPN",

View File

@@ -94,11 +94,8 @@ 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("该颜色已存在"),
"colorSchemes": MessageLookupByLibrary.simpleMessage("配色方案"),
"columns": MessageLookupByLibrary.simpleMessage("列数"),
"compatible": MessageLookupByLibrary.simpleMessage("兼容模式"),
"compatibleDesc": MessageLookupByLibrary.simpleMessage(
@@ -110,7 +107,6 @@ class MessageLookup extends MessageLookupByLibrary {
"connectivity": MessageLookupByLibrary.simpleMessage("连通性:"),
"content": MessageLookupByLibrary.simpleMessage("内容"),
"contentEmptyTip": MessageLookupByLibrary.simpleMessage("内容不能为空"),
"contentScheme": MessageLookupByLibrary.simpleMessage("内容主题"),
"copy": MessageLookupByLibrary.simpleMessage("复制"),
"copyEnvVar": MessageLookupByLibrary.simpleMessage("复制环境变量"),
"copyLink": MessageLookupByLibrary.simpleMessage("复制链接"),
@@ -118,7 +114,6 @@ 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("深色"),
@@ -131,15 +126,12 @@ class MessageLookup extends MessageLookupByLibrary {
"delay": MessageLookupByLibrary.simpleMessage("延迟"),
"delaySort": MessageLookupByLibrary.simpleMessage("按延迟排序"),
"delete": MessageLookupByLibrary.simpleMessage("删除"),
"deleteColorTip": MessageLookupByLibrary.simpleMessage("确定删除当前颜色吗?"),
"deleteProfileTip": MessageLookupByLibrary.simpleMessage("确定要删除当前配置吗?"),
"deleteRuleTip": MessageLookupByLibrary.simpleMessage("确定要删除选中的规则吗?"),
"desc": MessageLookupByLibrary.simpleMessage(
"基于ClashMeta的多平台代理客户端简单易用开源无广告。",
),
"detectionTip": MessageLookupByLibrary.simpleMessage("依赖第三方api仅供参考"),
"developerMode": MessageLookupByLibrary.simpleMessage("开发者模式"),
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage("开发者模式已启用。"),
"direct": MessageLookupByLibrary.simpleMessage("直连"),
"disclaimer": MessageLookupByLibrary.simpleMessage("免责声明"),
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
@@ -164,7 +156,6 @@ class MessageLookup extends MessageLookupByLibrary {
"exportFile": MessageLookupByLibrary.simpleMessage("导出文件"),
"exportLogs": MessageLookupByLibrary.simpleMessage("导出日志"),
"exportSuccess": MessageLookupByLibrary.simpleMessage("导出成功"),
"expressiveScheme": MessageLookupByLibrary.simpleMessage("表现力"),
"externalController": MessageLookupByLibrary.simpleMessage("外部控制器"),
"externalControllerDesc": MessageLookupByLibrary.simpleMessage(
"开启后将可以通过9090端口控制Clash内核",
@@ -176,7 +167,6 @@ class MessageLookup extends MessageLookupByLibrary {
"fallback": MessageLookupByLibrary.simpleMessage("Fallback"),
"fallbackDesc": MessageLookupByLibrary.simpleMessage("一般情况下使用境外DNS"),
"fallbackFilter": MessageLookupByLibrary.simpleMessage("Fallback过滤"),
"fidelityScheme": MessageLookupByLibrary.simpleMessage("高保真"),
"file": MessageLookupByLibrary.simpleMessage("文件"),
"fileDesc": MessageLookupByLibrary.simpleMessage("直接上传配置文件"),
"fileIsUpdate": MessageLookupByLibrary.simpleMessage("文件有修改,是否保存修改"),
@@ -185,7 +175,6 @@ class MessageLookup extends MessageLookupByLibrary {
"findProcessModeDesc": MessageLookupByLibrary.simpleMessage("开启后会有一定性能损耗"),
"fontFamily": MessageLookupByLibrary.simpleMessage("字体"),
"fourColumns": MessageLookupByLibrary.simpleMessage("四列"),
"fruitSaladScheme": MessageLookupByLibrary.simpleMessage("果缤纷"),
"general": MessageLookupByLibrary.simpleMessage("常规"),
"generalDesc": MessageLookupByLibrary.simpleMessage("修改通用设置"),
"geoData": MessageLookupByLibrary.simpleMessage("地理数据"),
@@ -210,7 +199,6 @@ 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流量"),
@@ -237,14 +225,11 @@ class MessageLookup extends MessageLookupByLibrary {
"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("修改系统默认退出事件"),
"minutes": MessageLookupByLibrary.simpleMessage("分钟"),
"mode": MessageLookupByLibrary.simpleMessage("模式"),
"monochromeScheme": MessageLookupByLibrary.simpleMessage("单色"),
"months": MessageLookupByLibrary.simpleMessage(""),
"more": MessageLookupByLibrary.simpleMessage("更多"),
"name": MessageLookupByLibrary.simpleMessage("名称"),
@@ -257,14 +242,12 @@ class MessageLookup extends MessageLookupByLibrary {
"networkDesc": MessageLookupByLibrary.simpleMessage("修改网络相关设置"),
"networkDetection": MessageLookupByLibrary.simpleMessage("网络检测"),
"networkSpeed": MessageLookupByLibrary.simpleMessage("网络速度"),
"neutralScheme": MessageLookupByLibrary.simpleMessage("中性"),
"noData": MessageLookupByLibrary.simpleMessage("暂无数据"),
"noHotKey": MessageLookupByLibrary.simpleMessage("暂无快捷键"),
"noIcon": MessageLookupByLibrary.simpleMessage("无图标"),
"noInfo": MessageLookupByLibrary.simpleMessage("暂无信息"),
"noMoreInfoDesc": MessageLookupByLibrary.simpleMessage("暂无更多信息"),
"noNetwork": MessageLookupByLibrary.simpleMessage("无网络"),
"noNetworkApp": MessageLookupByLibrary.simpleMessage("无网络应用"),
"noProxy": MessageLookupByLibrary.simpleMessage("暂无代理"),
"noProxyDesc": MessageLookupByLibrary.simpleMessage("请创建配置文件或者添加有效配置文件"),
"noResolve": MessageLookupByLibrary.simpleMessage("不解析IP"),
@@ -293,7 +276,6 @@ class MessageLookup extends MessageLookupByLibrary {
"overrideDns": MessageLookupByLibrary.simpleMessage("覆写DNS"),
"overrideDnsDesc": MessageLookupByLibrary.simpleMessage("开启后将覆盖配置中的DNS选项"),
"overrideOriginRules": MessageLookupByLibrary.simpleMessage("覆盖原始规则"),
"palette": MessageLookupByLibrary.simpleMessage("调色板"),
"password": MessageLookupByLibrary.simpleMessage("密码"),
"passwordTip": MessageLookupByLibrary.simpleMessage("密码不能为空"),
"paste": MessageLookupByLibrary.simpleMessage("粘贴"),
@@ -342,7 +324,6 @@ class MessageLookup extends MessageLookupByLibrary {
"pureBlackMode": MessageLookupByLibrary.simpleMessage("纯黑模式"),
"qrcode": MessageLookupByLibrary.simpleMessage("二维码"),
"qrcodeDesc": MessageLookupByLibrary.simpleMessage("扫描二维码获取配置文件"),
"rainbowScheme": MessageLookupByLibrary.simpleMessage("彩虹"),
"recovery": MessageLookupByLibrary.simpleMessage("恢复"),
"recoveryAll": MessageLookupByLibrary.simpleMessage("恢复所有数据"),
"recoveryProfiles": MessageLookupByLibrary.simpleMessage("仅恢复配置文件"),
@@ -406,7 +387,6 @@ 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("设置系统代理"),
@@ -416,7 +396,6 @@ 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("设置深色模式,调整色彩"),
@@ -426,7 +405,6 @@ class MessageLookup extends MessageLookupByLibrary {
"time": MessageLookupByLibrary.simpleMessage("时间"),
"tip": MessageLookupByLibrary.simpleMessage("提示"),
"toggle": MessageLookupByLibrary.simpleMessage("切换"),
"tonalSpotScheme": MessageLookupByLibrary.simpleMessage("调性点缀"),
"tools": MessageLookupByLibrary.simpleMessage("工具"),
"trafficUsage": MessageLookupByLibrary.simpleMessage("流量统计"),
"tun": MessageLookupByLibrary.simpleMessage("虚拟网卡"),
@@ -447,7 +425,6 @@ class MessageLookup extends MessageLookupByLibrary {
"useSystemHosts": MessageLookupByLibrary.simpleMessage("使用系统Hosts"),
"value": MessageLookupByLibrary.simpleMessage(""),
"valueExists": MessageLookupByLibrary.simpleMessage("当前值已存在"),
"vibrantScheme": MessageLookupByLibrary.simpleMessage("活力"),
"view": MessageLookupByLibrary.simpleMessage("查看"),
"vpnDesc": MessageLookupByLibrary.simpleMessage("修改VPN相关设置"),
"vpnEnableDesc": MessageLookupByLibrary.simpleMessage(

View File

@@ -2904,181 +2904,6 @@ class AppLocalizations {
args: [],
);
}
/// `Are you sure you want to delete the current color?`
String get deleteColorTip {
return Intl.message(
'Are you sure you want to delete the current color?',
name: 'deleteColorTip',
desc: '',
args: [],
);
}
/// `Current color already exists`
String get colorExists {
return Intl.message(
'Current color already exists',
name: 'colorExists',
desc: '',
args: [],
);
}
/// `Color schemes`
String get colorSchemes {
return Intl.message(
'Color schemes',
name: 'colorSchemes',
desc: '',
args: [],
);
}
/// `Palette`
String get palette {
return Intl.message('Palette', name: 'palette', desc: '', args: []);
}
/// `TonalSpot`
String get tonalSpotScheme {
return Intl.message(
'TonalSpot',
name: 'tonalSpotScheme',
desc: '',
args: [],
);
}
/// `Fidelity`
String get fidelityScheme {
return Intl.message('Fidelity', name: 'fidelityScheme', desc: '', args: []);
}
/// `Monochrome`
String get monochromeScheme {
return Intl.message(
'Monochrome',
name: 'monochromeScheme',
desc: '',
args: [],
);
}
/// `Neutral`
String get neutralScheme {
return Intl.message('Neutral', name: 'neutralScheme', desc: '', args: []);
}
/// `Vibrant`
String get vibrantScheme {
return Intl.message('Vibrant', name: 'vibrantScheme', desc: '', args: []);
}
/// `Expressive`
String get expressiveScheme {
return Intl.message(
'Expressive',
name: 'expressiveScheme',
desc: '',
args: [],
);
}
/// `Content`
String get contentScheme {
return Intl.message('Content', name: 'contentScheme', desc: '', args: []);
}
/// `Rainbow`
String get rainbowScheme {
return Intl.message('Rainbow', name: 'rainbowScheme', desc: '', args: []);
}
/// `FruitSalad`
String get fruitSaladScheme {
return Intl.message(
'FruitSalad',
name: 'fruitSaladScheme',
desc: '',
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: [],
);
}
}
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {

View File

@@ -2,7 +2,6 @@ import 'dart:async';
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class AppStateManager extends StatefulWidget {
@@ -22,6 +21,7 @@ class _AppStateManagerState extends State<AppStateManager>
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@@ -33,10 +33,10 @@ class _AppStateManagerState extends State<AppStateManager>
@override
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
commonPrint.log("$state");
if (state == AppLifecycleState.paused ||
state == AppLifecycleState.inactive) {
globalState.appController.savePreferences();
render?.pause();
} else {
render?.resume();
}
@@ -70,15 +70,6 @@ class AppEnvManager extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (kDebugMode) {
if (globalState.isPre) {
return Banner(
message: 'DEBUG',
location: BannerLocation.topEnd,
child: child,
);
}
}
if (globalState.isPre) {
return Banner(
message: 'PRE',

View File

@@ -73,7 +73,7 @@ class _ClashContainerState extends ConsumerState<ClashManager>
void onLog(Log log) {
ref.watch(logsProvider.notifier).addLog(log);
if (log.logLevel == LogLevel.error) {
globalState.showNotifier(log.payload);
globalState.showNotifier(log.payload ?? '');
}
super.onLog(log);
}

View File

@@ -21,7 +21,7 @@ class MessageManager extends StatefulWidget {
class MessageManagerState extends State<MessageManager> {
final _messagesNotifier = ValueNotifier<List<CommonMessage>>([]);
final List<CommonMessage> _bufferMessages = [];
bool _pushing = false;
Completer<bool>? _messageIngCompleter;
@override
void initState() {
@@ -36,31 +36,30 @@ class MessageManagerState extends State<MessageManager> {
Future<void> message(String text) async {
final commonMessage = CommonMessage(
id: utils.uuidV4,
id: other.uuidV4,
text: text,
);
_bufferMessages.add(commonMessage);
await _showMessage();
_showMessage();
}
_showMessage() async {
if (_pushing == true) {
if (_messageIngCompleter?.isCompleted == false) {
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);
});
if (_bufferMessages.isEmpty) {
_pushing = false;
}
_messageIngCompleter?.complete(true);
}
}
@@ -78,41 +77,41 @@ 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()
: LayoutBuilder(
key: Key(messages.last.id),
builder: (_, constraints) {
return Card(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(12.0),
),
key: Key(messages.last.id),
builder: (_, constraints) {
return Card(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(12.0),
),
),
elevation: 10,
margin: EdgeInsets.only(
top: kToolbarHeight,
left: 12,
right: 12,
),
color: context.colorScheme.surfaceContainerHigh,
child: Container(
width: min(
constraints.maxWidth,
400,
),
padding: EdgeInsets.symmetric(
horizontal: 12,
vertical: 16,
),
child: Text(
messages.last.text,
),
),
);
},
),
elevation: 10,
color: context.colorScheme.surfaceContainerHigh,
child: Container(
width: min(
constraints.maxWidth,
500,
),
padding: EdgeInsets.symmetric(
horizontal: 12,
vertical: 16,
),
child: Text(
messages.last.text,
),
),
);
},
),
);
},
),

View File

@@ -1,13 +1,10 @@
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 ConsumerWidget {
class ThemeManager extends StatelessWidget {
final Widget child;
const ThemeManager({
@@ -16,30 +13,14 @@ class ThemeManager extends ConsumerWidget {
});
@override
Widget build(BuildContext context, ref) {
final textScale = ref.read(
themeSettingProvider.select((state) => state.textScale),
);
final double textScaleFactor = max(
min(
textScale.enable ? textScale.scale : defaultTextScaleFactor,
1.2,
),
0.8,
);
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;
Widget build(BuildContext context) {
globalState.measure = Measure.of(context);
globalState.theme = CommonTheme.of(context);
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) {

View File

@@ -25,6 +25,7 @@ class WindowManager extends ConsumerStatefulWidget {
class _WindowContainerState extends ConsumerState<WindowManager>
with WindowListener, WindowExtListener {
@override
Widget build(BuildContext context) {
return widget.child;
@@ -59,10 +60,15 @@ class _WindowContainerState extends ConsumerState<WindowManager>
@override
void onWindowFocus() {
super.onWindowFocus();
commonPrint.log("focus");
render?.resume();
}
@override
void onWindowBlur() {
super.onWindowBlur();
render?.pause();
}
@override
Future<void> onShouldTerminate() async {
await globalState.appController.handleExit();
@@ -96,8 +102,6 @@ class _WindowContainerState extends ConsumerState<WindowManager>
@override
void onWindowMinimize() async {
globalState.appController.savePreferencesDebounce();
commonPrint.log("minimize");
render?.pause();
super.onWindowMinimize();
}
@@ -182,23 +186,19 @@ class _WindowHeaderState extends State<WindowHeader> {
super.dispose();
}
_updateMaximized() async {
final isMaximized = await windowManager.isMaximized();
switch (isMaximized) {
_updateMaximized() {
isMaximizedNotifier.value = !isMaximizedNotifier.value;
switch (isMaximizedNotifier.value) {
case true:
await windowManager.unmaximize();
break;
windowManager.maximize();
case false:
await windowManager.maximize();
break;
windowManager.unmaximize();
}
isMaximizedNotifier.value = await windowManager.isMaximized();
}
_updatePin() async {
final isAlwaysOnTop = await windowManager.isAlwaysOnTop();
await windowManager.setAlwaysOnTop(!isAlwaysOnTop);
isPinNotifier.value = await windowManager.isAlwaysOnTop();
_updatePin() {
isPinNotifier.value = !isPinNotifier.value;
windowManager.setAlwaysOnTop(isPinNotifier.value);
}
_buildActions() {

View File

@@ -16,6 +16,7 @@ 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,
@@ -35,7 +36,7 @@ class AppState with _$AppState {
}
extension AppStateExt on AppState {
ViewMode get viewMode => utils.getViewMode(viewSize.width);
ViewMode get viewMode => other.getViewMode(viewSize.width);
bool get isStart => runTime != null;
}

View File

@@ -361,7 +361,7 @@ class Rule with _$Rule {
factory Rule.value(String value) {
return Rule(
value: value,
id: utils.uuidV4,
id: other.uuidV4,
);
}
@@ -426,12 +426,12 @@ class ClashConfig with _$ClashConfig {
@Default(defaultMixedPort) @JsonKey(name: "mixed-port") int mixedPort,
@Default(Mode.rule) Mode mode,
@Default(false) @JsonKey(name: "allow-lan") bool allowLan,
@Default(LogLevel.error) @JsonKey(name: "log-level") LogLevel logLevel,
@Default(LogLevel.info) @JsonKey(name: "log-level") LogLevel logLevel,
@Default(false) bool ipv6,
@Default(FindProcessMode.off)
@JsonKey(
name: "find-process-mode",
unknownEnumValue: FindProcessMode.always,
unknownEnumValue: FindProcessMode.off,
)
FindProcessMode findProcessMode,
@Default(defaultKeepAliveInterval)

View File

@@ -30,8 +30,7 @@ class Package with _$Package {
const factory Package({
required String packageName,
required String label,
required bool system,
required bool internet,
required bool isSystem,
required int lastUpdateTime,
}) = _Package;
@@ -85,33 +84,33 @@ extension ConnectionExt on Connection {
}
}
String _logDateTime(_) {
return DateTime.now().toString();
}
@JsonSerializable()
class Log {
@JsonKey(name: "LogLevel")
LogLevel logLevel;
@JsonKey(name: "Payload")
String? payload;
DateTime _dateTime;
// String _logId(_) {
// return utils.id;
// }
Log({
required this.logLevel,
this.payload,
}) : _dateTime = DateTime.now();
@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;
DateTime get dateTime => _dateTime;
factory Log.app(
String payload,
) {
return Log(
payload: payload,
dateTime: _logDateTime(null),
// id: _logId(null),
);
factory Log.fromJson(Map<String, dynamic> json) {
return _$LogFromJson(json);
}
factory Log.fromJson(Map<String, Object?> json) => _$LogFromJson(json);
Map<String, dynamic> toJson() {
return _$LogToJson(this);
}
@override
String toString() {
return 'Log{logLevel: $logLevel, payload: $payload, dateTime: $dateTime}';
}
}
@freezed
@@ -128,10 +127,11 @@ 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)) || logLevelName.contains(lowQuery));
((payload?.contains(lowQuery) ?? false) ||
logLevelName.contains(lowQuery));
},
).toList();
}
@@ -369,32 +369,21 @@ class ColorSchemes with _$ColorSchemes {
}
extension ColorSchemesExt on ColorSchemes {
ColorScheme getColorSchemeForBrightness(
Brightness brightness,
DynamicSchemeVariant schemeVariant,
) {
ColorScheme getColorSchemeForBrightness(Brightness? brightness) {
if (brightness == Brightness.dark) {
return darkColorScheme != null
? ColorScheme.fromSeed(
seedColor: darkColorScheme!.primary,
brightness: Brightness.dark,
dynamicSchemeVariant: schemeVariant,
)
: ColorScheme.fromSeed(
seedColor: Color(defaultPrimaryColor),
seedColor: defaultPrimaryColor,
brightness: Brightness.dark,
dynamicSchemeVariant: schemeVariant,
);
}
return lightColorScheme != null
? ColorScheme.fromSeed(
seedColor: lightColorScheme!.primary,
dynamicSchemeVariant: schemeVariant,
)
: ColorScheme.fromSeed(
seedColor: Color(defaultPrimaryColor),
dynamicSchemeVariant: schemeVariant,
);
? ColorScheme.fromSeed(seedColor: lightColorScheme!.primary,dynamicSchemeVariant: DynamicSchemeVariant.vibrant)
: ColorScheme.fromSeed(seedColor: defaultPrimaryColor);
}
}
@@ -511,4 +500,4 @@ class PopupMenuItemData {
final VoidCallback? onPressed;
final IconData? icon;
final PopupMenuItemType? type;
}
}

View File

@@ -8,7 +8,6 @@ import 'package:freezed_annotation/freezed_annotation.dart';
import 'models.dart';
part 'generated/config.freezed.dart';
part 'generated/config.g.dart';
const defaultBypassDomain = [
@@ -37,8 +36,9 @@ const defaultNetworkProps = NetworkProps();
const defaultProxiesStyle = ProxiesStyle();
const defaultWindowProps = WindowProps();
const defaultAccessControl = AccessControl();
final defaultThemeProps = ThemeProps(
primaryColor: defaultPrimaryColor,
final defaultThemeProps = ThemeProps().copyWith(
primaryColor: defaultPrimaryColor.toARGB32(),
themeMode: ThemeMode.dark,
);
const List<DashboardWidget> defaultDashboardWidgets = [
@@ -75,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,
@@ -84,7 +84,6 @@ class AppSettingProps with _$AppSettingProps {
@Default(false) bool disclaimerAccepted,
@Default(true) bool minimizeOnExit,
@Default(false) bool hidden,
@Default(false) bool developerMode,
}) = _AppSettingProps;
factory AppSettingProps.fromJson(Map<String, Object?> json) =>
@@ -106,7 +105,6 @@ 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) =>
@@ -144,7 +142,7 @@ class VpnProps with _$VpnProps {
}) = _VpnProps;
factory VpnProps.fromJson(Map<String, Object?>? json) =>
json == null ? defaultVpnProps : _$VpnPropsFromJson(json);
json == null ? const VpnProps() : _$VpnPropsFromJson(json);
}
@freezed
@@ -174,26 +172,12 @@ 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({
int? primaryColor,
@Default(defaultPrimaryColors) List<int> primaryColors,
@Default(ThemeMode.dark) ThemeMode themeMode,
@Default(DynamicSchemeVariant.tonalSpot) DynamicSchemeVariant schemeVariant,
@Default(ThemeMode.system) ThemeMode themeMode,
@Default(false) bool pureBlack,
@Default(TextScale()) TextScale textScale,
}) = _ThemeProps;
factory ThemeProps.fromJson(Map<String, Object?> json) =>

View File

@@ -19,6 +19,7 @@ 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 =>
@@ -52,6 +53,7 @@ abstract class $AppStateCopyWith<$Res> {
{bool isInit,
PageLabel pageLabel,
List<Package> packages,
ColorSchemes colorSchemes,
int sortNum,
Size viewSize,
Map<String, Map<String, int?>> delayMap,
@@ -67,6 +69,8 @@ abstract class $AppStateCopyWith<$Res> {
FixedList<Traffic> traffics,
Traffic totalTraffic,
bool needApply});
$ColorSchemesCopyWith<$Res> get colorSchemes;
}
/// @nodoc
@@ -87,6 +91,7 @@ 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,
@@ -116,6 +121,10 @@ 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
@@ -178,6 +187,16 @@ 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
@@ -192,6 +211,7 @@ abstract class _$$AppStateImplCopyWith<$Res>
{bool isInit,
PageLabel pageLabel,
List<Package> packages,
ColorSchemes colorSchemes,
int sortNum,
Size viewSize,
Map<String, Map<String, int?>> delayMap,
@@ -207,6 +227,9 @@ abstract class _$$AppStateImplCopyWith<$Res>
FixedList<Traffic> traffics,
Traffic totalTraffic,
bool needApply});
@override
$ColorSchemesCopyWith<$Res> get colorSchemes;
}
/// @nodoc
@@ -225,6 +248,7 @@ class __$$AppStateImplCopyWithImpl<$Res>
Object? isInit = null,
Object? pageLabel = null,
Object? packages = null,
Object? colorSchemes = null,
Object? sortNum = null,
Object? viewSize = null,
Object? delayMap = null,
@@ -254,6 +278,10 @@ 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
@@ -325,6 +353,7 @@ 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 {},
@@ -360,6 +389,9 @@ class _$AppStateImpl implements _AppState {
return EqualUnmodifiableListView(_packages);
}
@override
@JsonKey()
final ColorSchemes colorSchemes;
@override
@JsonKey()
final int sortNum;
@@ -417,7 +449,7 @@ class _$AppStateImpl implements _AppState {
@override
String toString() {
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)';
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)';
}
@override
@@ -429,6 +461,8 @@ 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) &&
@@ -455,26 +489,28 @@ class _$AppStateImpl implements _AppState {
}
@override
int get hashCode => Object.hash(
runtimeType,
isInit,
pageLabel,
const DeepCollectionEquality().hash(_packages),
sortNum,
viewSize,
const DeepCollectionEquality().hash(_delayMap),
const DeepCollectionEquality().hash(_groups),
checkIpNum,
brightness,
runTime,
const DeepCollectionEquality().hash(_providers),
localIp,
requests,
version,
logs,
traffics,
totalTraffic,
needApply);
int get hashCode => Object.hashAll([
runtimeType,
isInit,
pageLabel,
const DeepCollectionEquality().hash(_packages),
colorSchemes,
sortNum,
viewSize,
const DeepCollectionEquality().hash(_delayMap),
const DeepCollectionEquality().hash(_groups),
checkIpNum,
brightness,
runTime,
const DeepCollectionEquality().hash(_providers),
localIp,
requests,
version,
logs,
traffics,
totalTraffic,
needApply
]);
/// Create a copy of AppState
/// with the given fields replaced by the non-null parameter values.
@@ -490,6 +526,7 @@ 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,
@@ -513,6 +550,8 @@ abstract class _AppState implements AppState {
@override
List<Package> get packages;
@override
ColorSchemes get colorSchemes;
@override
int get sortNum;
@override
Size get viewSize;

View File

@@ -2832,7 +2832,7 @@ mixin _$ClashConfig {
@JsonKey(name: "log-level")
LogLevel get logLevel => throw _privateConstructorUsedError;
bool get ipv6 => throw _privateConstructorUsedError;
@JsonKey(name: "find-process-mode", unknownEnumValue: FindProcessMode.always)
@JsonKey(name: "find-process-mode", unknownEnumValue: FindProcessMode.off)
FindProcessMode get findProcessMode => throw _privateConstructorUsedError;
@JsonKey(name: "keep-alive-interval")
int get keepAliveInterval => throw _privateConstructorUsedError;
@@ -2880,8 +2880,7 @@ abstract class $ClashConfigCopyWith<$Res> {
@JsonKey(name: "allow-lan") bool allowLan,
@JsonKey(name: "log-level") LogLevel logLevel,
bool ipv6,
@JsonKey(
name: "find-process-mode", unknownEnumValue: FindProcessMode.always)
@JsonKey(name: "find-process-mode", unknownEnumValue: FindProcessMode.off)
FindProcessMode findProcessMode,
@JsonKey(name: "keep-alive-interval") int keepAliveInterval,
@JsonKey(name: "unified-delay") bool unifiedDelay,
@@ -3058,8 +3057,7 @@ abstract class _$$ClashConfigImplCopyWith<$Res>
@JsonKey(name: "allow-lan") bool allowLan,
@JsonKey(name: "log-level") LogLevel logLevel,
bool ipv6,
@JsonKey(
name: "find-process-mode", unknownEnumValue: FindProcessMode.always)
@JsonKey(name: "find-process-mode", unknownEnumValue: FindProcessMode.off)
FindProcessMode findProcessMode,
@JsonKey(name: "keep-alive-interval") int keepAliveInterval,
@JsonKey(name: "unified-delay") bool unifiedDelay,
@@ -3200,10 +3198,9 @@ class _$ClashConfigImpl implements _ClashConfig {
{@JsonKey(name: "mixed-port") this.mixedPort = defaultMixedPort,
this.mode = Mode.rule,
@JsonKey(name: "allow-lan") this.allowLan = false,
@JsonKey(name: "log-level") this.logLevel = LogLevel.error,
@JsonKey(name: "log-level") this.logLevel = LogLevel.info,
this.ipv6 = false,
@JsonKey(
name: "find-process-mode", unknownEnumValue: FindProcessMode.always)
@JsonKey(name: "find-process-mode", unknownEnumValue: FindProcessMode.off)
this.findProcessMode = FindProcessMode.off,
@JsonKey(name: "keep-alive-interval")
this.keepAliveInterval = defaultKeepAliveInterval,
@@ -3245,7 +3242,7 @@ class _$ClashConfigImpl implements _ClashConfig {
@JsonKey()
final bool ipv6;
@override
@JsonKey(name: "find-process-mode", unknownEnumValue: FindProcessMode.always)
@JsonKey(name: "find-process-mode", unknownEnumValue: FindProcessMode.off)
final FindProcessMode findProcessMode;
@override
@JsonKey(name: "keep-alive-interval")
@@ -3388,8 +3385,7 @@ abstract class _ClashConfig implements ClashConfig {
@JsonKey(name: "allow-lan") final bool allowLan,
@JsonKey(name: "log-level") final LogLevel logLevel,
final bool ipv6,
@JsonKey(
name: "find-process-mode", unknownEnumValue: FindProcessMode.always)
@JsonKey(name: "find-process-mode", unknownEnumValue: FindProcessMode.off)
final FindProcessMode findProcessMode,
@JsonKey(name: "keep-alive-interval") final int keepAliveInterval,
@JsonKey(name: "unified-delay") final bool unifiedDelay,
@@ -3423,7 +3419,7 @@ abstract class _ClashConfig implements ClashConfig {
@override
bool get ipv6;
@override
@JsonKey(name: "find-process-mode", unknownEnumValue: FindProcessMode.always)
@JsonKey(name: "find-process-mode", unknownEnumValue: FindProcessMode.off)
FindProcessMode get findProcessMode;
@override
@JsonKey(name: "keep-alive-interval")

View File

@@ -268,11 +268,11 @@ _$ClashConfigImpl _$$ClashConfigImplFromJson(Map<String, dynamic> json) =>
mode: $enumDecodeNullable(_$ModeEnumMap, json['mode']) ?? Mode.rule,
allowLan: json['allow-lan'] as bool? ?? false,
logLevel: $enumDecodeNullable(_$LogLevelEnumMap, json['log-level']) ??
LogLevel.error,
LogLevel.info,
ipv6: json['ipv6'] as bool? ?? false,
findProcessMode: $enumDecodeNullable(
_$FindProcessModeEnumMap, json['find-process-mode'],
unknownValue: FindProcessMode.always) ??
unknownValue: FindProcessMode.off) ??
FindProcessMode.off,
keepAliveInterval: (json['keep-alive-interval'] as num?)?.toInt() ??
defaultKeepAliveInterval,
@@ -342,7 +342,6 @@ const _$LogLevelEnumMap = {
LogLevel.warning: 'warning',
LogLevel.error: 'error',
LogLevel.silent: 'silent',
LogLevel.app: 'app',
};
const _$FindProcessModeEnumMap = {

View File

@@ -289,8 +289,7 @@ Package _$PackageFromJson(Map<String, dynamic> json) {
mixin _$Package {
String get packageName => throw _privateConstructorUsedError;
String get label => throw _privateConstructorUsedError;
bool get system => throw _privateConstructorUsedError;
bool get internet => throw _privateConstructorUsedError;
bool get isSystem => throw _privateConstructorUsedError;
int get lastUpdateTime => throw _privateConstructorUsedError;
/// Serializes this Package to a JSON map.
@@ -308,11 +307,7 @@ abstract class $PackageCopyWith<$Res> {
_$PackageCopyWithImpl<$Res, Package>;
@useResult
$Res call(
{String packageName,
String label,
bool system,
bool internet,
int lastUpdateTime});
{String packageName, String label, bool isSystem, int lastUpdateTime});
}
/// @nodoc
@@ -332,8 +327,7 @@ class _$PackageCopyWithImpl<$Res, $Val extends Package>
$Res call({
Object? packageName = null,
Object? label = null,
Object? system = null,
Object? internet = null,
Object? isSystem = null,
Object? lastUpdateTime = null,
}) {
return _then(_value.copyWith(
@@ -345,13 +339,9 @@ class _$PackageCopyWithImpl<$Res, $Val extends Package>
? _value.label
: label // ignore: cast_nullable_to_non_nullable
as String,
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
isSystem: null == isSystem
? _value.isSystem
: isSystem // ignore: cast_nullable_to_non_nullable
as bool,
lastUpdateTime: null == lastUpdateTime
? _value.lastUpdateTime
@@ -369,11 +359,7 @@ abstract class _$$PackageImplCopyWith<$Res> implements $PackageCopyWith<$Res> {
@override
@useResult
$Res call(
{String packageName,
String label,
bool system,
bool internet,
int lastUpdateTime});
{String packageName, String label, bool isSystem, int lastUpdateTime});
}
/// @nodoc
@@ -391,8 +377,7 @@ class __$$PackageImplCopyWithImpl<$Res>
$Res call({
Object? packageName = null,
Object? label = null,
Object? system = null,
Object? internet = null,
Object? isSystem = null,
Object? lastUpdateTime = null,
}) {
return _then(_$PackageImpl(
@@ -404,13 +389,9 @@ class __$$PackageImplCopyWithImpl<$Res>
? _value.label
: label // ignore: cast_nullable_to_non_nullable
as String,
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
isSystem: null == isSystem
? _value.isSystem
: isSystem // ignore: cast_nullable_to_non_nullable
as bool,
lastUpdateTime: null == lastUpdateTime
? _value.lastUpdateTime
@@ -426,8 +407,7 @@ class _$PackageImpl implements _Package {
const _$PackageImpl(
{required this.packageName,
required this.label,
required this.system,
required this.internet,
required this.isSystem,
required this.lastUpdateTime});
factory _$PackageImpl.fromJson(Map<String, dynamic> json) =>
@@ -438,15 +418,13 @@ class _$PackageImpl implements _Package {
@override
final String label;
@override
final bool system;
@override
final bool internet;
final bool isSystem;
@override
final int lastUpdateTime;
@override
String toString() {
return 'Package(packageName: $packageName, label: $label, system: $system, internet: $internet, lastUpdateTime: $lastUpdateTime)';
return 'Package(packageName: $packageName, label: $label, isSystem: $isSystem, lastUpdateTime: $lastUpdateTime)';
}
@override
@@ -457,17 +435,16 @@ class _$PackageImpl implements _Package {
(identical(other.packageName, packageName) ||
other.packageName == packageName) &&
(identical(other.label, label) || other.label == label) &&
(identical(other.system, system) || other.system == system) &&
(identical(other.internet, internet) ||
other.internet == internet) &&
(identical(other.isSystem, isSystem) ||
other.isSystem == isSystem) &&
(identical(other.lastUpdateTime, lastUpdateTime) ||
other.lastUpdateTime == lastUpdateTime));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType, packageName, label, system, internet, lastUpdateTime);
int get hashCode =>
Object.hash(runtimeType, packageName, label, isSystem, lastUpdateTime);
/// Create a copy of Package
/// with the given fields replaced by the non-null parameter values.
@@ -489,8 +466,7 @@ abstract class _Package implements Package {
const factory _Package(
{required final String packageName,
required final String label,
required final bool system,
required final bool internet,
required final bool isSystem,
required final int lastUpdateTime}) = _$PackageImpl;
factory _Package.fromJson(Map<String, dynamic> json) = _$PackageImpl.fromJson;
@@ -500,9 +476,7 @@ abstract class _Package implements Package {
@override
String get label;
@override
bool get system;
@override
bool get internet;
bool get isSystem;
@override
int get lastUpdateTime;
@@ -1118,203 +1092,6 @@ 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;

View File

@@ -6,12 +6,29 @@ 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,
system: json['system'] as bool,
internet: json['internet'] as bool,
isSystem: json['isSystem'] as bool,
lastUpdateTime: (json['lastUpdateTime'] as num).toInt(),
);
@@ -19,8 +36,7 @@ Map<String, dynamic> _$$PackageImplToJson(_$PackageImpl instance) =>
<String, dynamic>{
'packageName': instance.packageName,
'label': instance.label,
'system': instance.system,
'internet': instance.internet,
'isSystem': instance.isSystem,
'lastUpdateTime': instance.lastUpdateTime,
};
@@ -71,28 +87,6 @@ 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,

View File

@@ -37,7 +37,6 @@ mixin _$AppSettingProps {
bool get disclaimerAccepted => throw _privateConstructorUsedError;
bool get minimizeOnExit => throw _privateConstructorUsedError;
bool get hidden => throw _privateConstructorUsedError;
bool get developerMode => throw _privateConstructorUsedError;
/// Serializes this AppSettingProps to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@@ -71,8 +70,7 @@ abstract class $AppSettingPropsCopyWith<$Res> {
bool showLabel,
bool disclaimerAccepted,
bool minimizeOnExit,
bool hidden,
bool developerMode});
bool hidden});
}
/// @nodoc
@@ -105,7 +103,6 @@ class _$AppSettingPropsCopyWithImpl<$Res, $Val extends AppSettingProps>
Object? disclaimerAccepted = null,
Object? minimizeOnExit = null,
Object? hidden = null,
Object? developerMode = null,
}) {
return _then(_value.copyWith(
locale: freezed == locale
@@ -168,10 +165,6 @@ 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,
) as $Val);
}
}
@@ -200,8 +193,7 @@ abstract class _$$AppSettingPropsImplCopyWith<$Res>
bool showLabel,
bool disclaimerAccepted,
bool minimizeOnExit,
bool hidden,
bool developerMode});
bool hidden});
}
/// @nodoc
@@ -232,7 +224,6 @@ class __$$AppSettingPropsImplCopyWithImpl<$Res>
Object? disclaimerAccepted = null,
Object? minimizeOnExit = null,
Object? hidden = null,
Object? developerMode = null,
}) {
return _then(_$AppSettingPropsImpl(
locale: freezed == locale
@@ -295,10 +286,6 @@ 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,
));
}
}
@@ -314,7 +301,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,
@@ -322,8 +309,7 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
this.showLabel = false,
this.disclaimerAccepted = false,
this.minimizeOnExit = true,
this.hidden = false,
this.developerMode = false})
this.hidden = false})
: _dashboardWidgets = dashboardWidgets;
factory _$AppSettingPropsImpl.fromJson(Map<String, dynamic> json) =>
@@ -380,13 +366,10 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
@override
@JsonKey()
final bool hidden;
@override
@JsonKey()
final bool developerMode;
@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, developerMode: $developerMode)';
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)';
}
@override
@@ -419,9 +402,7 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
other.disclaimerAccepted == disclaimerAccepted) &&
(identical(other.minimizeOnExit, minimizeOnExit) ||
other.minimizeOnExit == minimizeOnExit) &&
(identical(other.hidden, hidden) || other.hidden == hidden) &&
(identical(other.developerMode, developerMode) ||
other.developerMode == developerMode));
(identical(other.hidden, hidden) || other.hidden == hidden));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -442,8 +423,7 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
showLabel,
disclaimerAccepted,
minimizeOnExit,
hidden,
developerMode);
hidden);
/// Create a copy of AppSettingProps
/// with the given fields replaced by the non-null parameter values.
@@ -479,8 +459,7 @@ abstract class _AppSettingProps implements AppSettingProps {
final bool showLabel,
final bool disclaimerAccepted,
final bool minimizeOnExit,
final bool hidden,
final bool developerMode}) = _$AppSettingPropsImpl;
final bool hidden}) = _$AppSettingPropsImpl;
factory _AppSettingProps.fromJson(Map<String, dynamic> json) =
_$AppSettingPropsImpl.fromJson;
@@ -516,8 +495,6 @@ abstract class _AppSettingProps implements AppSettingProps {
bool get minimizeOnExit;
@override
bool get hidden;
@override
bool get developerMode;
/// Create a copy of AppSettingProps
/// with the given fields replaced by the non-null parameter values.
@@ -539,7 +516,6 @@ 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;
@@ -563,8 +539,7 @@ abstract class $AccessControlCopyWith<$Res> {
List<String> acceptList,
List<String> rejectList,
AccessSortType sort,
bool isFilterSystemApp,
bool isFilterNonInternetApp});
bool isFilterSystemApp});
}
/// @nodoc
@@ -588,7 +563,6 @@ 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
@@ -615,10 +589,6 @@ 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);
}
}
@@ -637,8 +607,7 @@ abstract class _$$AccessControlImplCopyWith<$Res>
List<String> acceptList,
List<String> rejectList,
AccessSortType sort,
bool isFilterSystemApp,
bool isFilterNonInternetApp});
bool isFilterSystemApp});
}
/// @nodoc
@@ -660,7 +629,6 @@ class __$$AccessControlImplCopyWithImpl<$Res>
Object? rejectList = null,
Object? sort = null,
Object? isFilterSystemApp = null,
Object? isFilterNonInternetApp = null,
}) {
return _then(_$AccessControlImpl(
enable: null == enable
@@ -687,10 +655,6 @@ 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,
));
}
}
@@ -704,8 +668,7 @@ class _$AccessControlImpl implements _AccessControl {
final List<String> acceptList = const [],
final List<String> rejectList = const [],
this.sort = AccessSortType.none,
this.isFilterSystemApp = true,
this.isFilterNonInternetApp = true})
this.isFilterSystemApp = true})
: _acceptList = acceptList,
_rejectList = rejectList;
@@ -742,13 +705,10 @@ 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, isFilterNonInternetApp: $isFilterNonInternetApp)';
return 'AccessControl(enable: $enable, mode: $mode, acceptList: $acceptList, rejectList: $rejectList, sort: $sort, isFilterSystemApp: $isFilterSystemApp)';
}
@override
@@ -764,9 +724,7 @@ class _$AccessControlImpl implements _AccessControl {
.equals(other._rejectList, _rejectList) &&
(identical(other.sort, sort) || other.sort == sort) &&
(identical(other.isFilterSystemApp, isFilterSystemApp) ||
other.isFilterSystemApp == isFilterSystemApp) &&
(identical(other.isFilterNonInternetApp, isFilterNonInternetApp) ||
other.isFilterNonInternetApp == isFilterNonInternetApp));
other.isFilterSystemApp == isFilterSystemApp));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -778,8 +736,7 @@ class _$AccessControlImpl implements _AccessControl {
const DeepCollectionEquality().hash(_acceptList),
const DeepCollectionEquality().hash(_rejectList),
sort,
isFilterSystemApp,
isFilterNonInternetApp);
isFilterSystemApp);
/// Create a copy of AccessControl
/// with the given fields replaced by the non-null parameter values.
@@ -804,8 +761,7 @@ abstract class _AccessControl implements AccessControl {
final List<String> acceptList,
final List<String> rejectList,
final AccessSortType sort,
final bool isFilterSystemApp,
final bool isFilterNonInternetApp}) = _$AccessControlImpl;
final bool isFilterSystemApp}) = _$AccessControlImpl;
factory _AccessControl.fromJson(Map<String, dynamic> json) =
_$AccessControlImpl.fromJson;
@@ -822,8 +778,6 @@ 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.
@@ -1763,170 +1717,6 @@ 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);
}
@@ -1934,11 +1724,8 @@ ThemeProps _$ThemePropsFromJson(Map<String, dynamic> json) {
/// @nodoc
mixin _$ThemeProps {
int? get primaryColor => throw _privateConstructorUsedError;
List<int> get primaryColors => throw _privateConstructorUsedError;
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;
@@ -1956,15 +1743,7 @@ abstract class $ThemePropsCopyWith<$Res> {
ThemeProps value, $Res Function(ThemeProps) then) =
_$ThemePropsCopyWithImpl<$Res, ThemeProps>;
@useResult
$Res call(
{int? primaryColor,
List<int> primaryColors,
ThemeMode themeMode,
DynamicSchemeVariant schemeVariant,
bool pureBlack,
TextScale textScale});
$TextScaleCopyWith<$Res> get textScale;
$Res call({int? primaryColor, ThemeMode themeMode, bool pureBlack});
}
/// @nodoc
@@ -1983,49 +1762,24 @@ class _$ThemePropsCopyWithImpl<$Res, $Val extends ThemeProps>
@override
$Res call({
Object? primaryColor = freezed,
Object? primaryColors = null,
Object? themeMode = null,
Object? schemeVariant = null,
Object? pureBlack = null,
Object? textScale = null,
}) {
return _then(_value.copyWith(
primaryColor: freezed == primaryColor
? _value.primaryColor
: primaryColor // ignore: cast_nullable_to_non_nullable
as int?,
primaryColors: null == primaryColors
? _value.primaryColors
: primaryColors // ignore: cast_nullable_to_non_nullable
as List<int>,
themeMode: null == themeMode
? _value.themeMode
: themeMode // ignore: cast_nullable_to_non_nullable
as ThemeMode,
schemeVariant: null == schemeVariant
? _value.schemeVariant
: schemeVariant // ignore: cast_nullable_to_non_nullable
as DynamicSchemeVariant,
pureBlack: null == pureBlack
? _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
@@ -2036,16 +1790,7 @@ abstract class _$$ThemePropsImplCopyWith<$Res>
__$$ThemePropsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int? primaryColor,
List<int> primaryColors,
ThemeMode themeMode,
DynamicSchemeVariant schemeVariant,
bool pureBlack,
TextScale textScale});
@override
$TextScaleCopyWith<$Res> get textScale;
$Res call({int? primaryColor, ThemeMode themeMode, bool pureBlack});
}
/// @nodoc
@@ -2062,37 +1807,22 @@ class __$$ThemePropsImplCopyWithImpl<$Res>
@override
$Res call({
Object? primaryColor = freezed,
Object? primaryColors = null,
Object? themeMode = null,
Object? schemeVariant = null,
Object? pureBlack = null,
Object? textScale = null,
}) {
return _then(_$ThemePropsImpl(
primaryColor: freezed == primaryColor
? _value.primaryColor
: primaryColor // ignore: cast_nullable_to_non_nullable
as int?,
primaryColors: null == primaryColors
? _value._primaryColors
: primaryColors // ignore: cast_nullable_to_non_nullable
as List<int>,
themeMode: null == themeMode
? _value.themeMode
: themeMode // ignore: cast_nullable_to_non_nullable
as ThemeMode,
schemeVariant: null == schemeVariant
? _value.schemeVariant
: schemeVariant // ignore: cast_nullable_to_non_nullable
as DynamicSchemeVariant,
pureBlack: null == pureBlack
? _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,
));
}
}
@@ -2102,43 +1832,24 @@ class __$$ThemePropsImplCopyWithImpl<$Res>
class _$ThemePropsImpl implements _ThemeProps {
const _$ThemePropsImpl(
{this.primaryColor,
final List<int> primaryColors = defaultPrimaryColors,
this.themeMode = ThemeMode.dark,
this.schemeVariant = DynamicSchemeVariant.tonalSpot,
this.pureBlack = false,
this.textScale = const TextScale()})
: _primaryColors = primaryColors;
this.themeMode = ThemeMode.system,
this.pureBlack = false});
factory _$ThemePropsImpl.fromJson(Map<String, dynamic> json) =>
_$$ThemePropsImplFromJson(json);
@override
final int? primaryColor;
final List<int> _primaryColors;
@override
@JsonKey()
List<int> get primaryColors {
if (_primaryColors is EqualUnmodifiableListView) return _primaryColors;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_primaryColors);
}
@override
@JsonKey()
final ThemeMode themeMode;
@override
@JsonKey()
final DynamicSchemeVariant schemeVariant;
@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, textScale: $textScale)';
return 'ThemeProps(primaryColor: $primaryColor, themeMode: $themeMode, pureBlack: $pureBlack)';
}
@override
@@ -2148,28 +1859,16 @@ class _$ThemePropsImpl implements _ThemeProps {
other is _$ThemePropsImpl &&
(identical(other.primaryColor, primaryColor) ||
other.primaryColor == primaryColor) &&
const DeepCollectionEquality()
.equals(other._primaryColors, _primaryColors) &&
(identical(other.themeMode, themeMode) ||
other.themeMode == themeMode) &&
(identical(other.schemeVariant, schemeVariant) ||
other.schemeVariant == schemeVariant) &&
(identical(other.pureBlack, pureBlack) ||
other.pureBlack == pureBlack) &&
(identical(other.textScale, textScale) ||
other.textScale == textScale));
other.pureBlack == pureBlack));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode => Object.hash(
runtimeType,
primaryColor,
const DeepCollectionEquality().hash(_primaryColors),
themeMode,
schemeVariant,
pureBlack,
textScale);
int get hashCode =>
Object.hash(runtimeType, primaryColor, themeMode, pureBlack);
/// Create a copy of ThemeProps
/// with the given fields replaced by the non-null parameter values.
@@ -2190,11 +1889,8 @@ class _$ThemePropsImpl implements _ThemeProps {
abstract class _ThemeProps implements ThemeProps {
const factory _ThemeProps(
{final int? primaryColor,
final List<int> primaryColors,
final ThemeMode themeMode,
final DynamicSchemeVariant schemeVariant,
final bool pureBlack,
final TextScale textScale}) = _$ThemePropsImpl;
final bool pureBlack}) = _$ThemePropsImpl;
factory _ThemeProps.fromJson(Map<String, dynamic> json) =
_$ThemePropsImpl.fromJson;
@@ -2202,15 +1898,9 @@ abstract class _ThemeProps implements ThemeProps {
@override
int? get primaryColor;
@override
List<int> get primaryColors;
@override
ThemeMode get themeMode;
@override
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.

View File

@@ -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,7 +26,6 @@ _$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,
);
Map<String, dynamic> _$$AppSettingPropsImplToJson(
@@ -49,17 +48,14 @@ Map<String, dynamic> _$$AppSettingPropsImplToJson(
'disclaimerAccepted': instance.disclaimerAccepted,
'minimizeOnExit': instance.minimizeOnExit,
'hidden': instance.hidden,
'developerMode': instance.developerMode,
};
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',
@@ -81,7 +77,6 @@ _$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) =>
@@ -92,7 +87,6 @@ Map<String, dynamic> _$$AccessControlImplToJson(_$AccessControlImpl instance) =>
'rejectList': instance.rejectList,
'sort': _$AccessSortTypeEnumMap[instance.sort]!,
'isFilterSystemApp': instance.isFilterSystemApp,
'isFilterNonInternetApp': instance.isFilterNonInternetApp,
};
const _$AccessControlModeEnumMap = {
@@ -225,44 +219,19 @@ 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(),
primaryColors: (json['primaryColors'] as List<dynamic>?)
?.map((e) => (e as num).toInt())
.toList() ??
defaultPrimaryColors,
themeMode: $enumDecodeNullable(_$ThemeModeEnumMap, json['themeMode']) ??
ThemeMode.dark,
schemeVariant: $enumDecodeNullable(
_$DynamicSchemeVariantEnumMap, json['schemeVariant']) ??
DynamicSchemeVariant.tonalSpot,
ThemeMode.system,
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) =>
<String, dynamic>{
'primaryColor': instance.primaryColor,
'primaryColors': instance.primaryColors,
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
'schemeVariant': _$DynamicSchemeVariantEnumMap[instance.schemeVariant]!,
'pureBlack': instance.pureBlack,
'textScale': instance.textScale,
};
const _$ThemeModeEnumMap = {
@@ -271,18 +240,6 @@ const _$ThemeModeEnumMap = {
ThemeMode.dark: 'dark',
};
const _$DynamicSchemeVariantEnumMap = {
DynamicSchemeVariant.tonalSpot: 'tonalSpot',
DynamicSchemeVariant.fidelity: 'fidelity',
DynamicSchemeVariant.monochrome: 'monochrome',
DynamicSchemeVariant.neutral: 'neutral',
DynamicSchemeVariant.vibrant: 'vibrant',
DynamicSchemeVariant.expressive: 'expressive',
DynamicSchemeVariant.content: 'content',
DynamicSchemeVariant.rainbow: 'rainbow',
DynamicSchemeVariant.fruitSalad: 'fruitSalad',
};
_$ConfigImpl _$$ConfigImplFromJson(Map<String, dynamic> json) => _$ConfigImpl(
appSetting: json['appSetting'] == null
? defaultAppSettingProps

View File

@@ -345,7 +345,6 @@ const _$ActionMethodEnumMap = {
ActionMethod.getCountryCode: 'getCountryCode',
ActionMethod.getMemory: 'getMemory',
ActionMethod.getProfile: 'getProfile',
ActionMethod.crash: 'crash',
ActionMethod.setFdMap: 'setFdMap',
ActionMethod.setProcessMap: 'setProcessMap',
ActionMethod.setState: 'setState',

View File

@@ -327,193 +327,6 @@ 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;

View File

@@ -173,7 +173,7 @@ extension ProfileExtension on Profile {
final disposition = response.headers.value("content-disposition");
final userinfo = response.headers.value('subscription-userinfo');
return await copyWith(
label: label ?? utils.getFileNameForDisposition(disposition) ?? id,
label: label ?? other.getFileNameForDisposition(disposition) ?? id,
subscriptionInfo: SubscriptionInfo.formHString(userinfo),
).saveFile(response.data);
}

View File

@@ -24,17 +24,6 @@ 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({
@@ -157,27 +146,18 @@ class PackageListSelectorState with _$PackageListSelectorState {
}
extension PackageListSelectorStateExt on PackageListSelectorState {
List<Package> get list {
List<Package> getList(List<String> selectedList) {
final isFilterSystemApp = accessControl.isFilterSystemApp;
final isFilterNonInternetApp = accessControl.isFilterNonInternetApp;
return packages
.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(
return packages
.where((item) => isFilterSystemApp ? item.isSystem == false : true)
.sorted(
(a, b) {
return switch (sort) {
AccessSortType.none => 0,
AccessSortType.name => utils.sortByChar(
utils.getPinyin(a.label),
utils.getPinyin(b.label),
AccessSortType.name => other.sortByChar(
other.getPinyin(a.label),
other.getPinyin(b.label),
),
AccessSortType.time => b.lastUpdateTime.compareTo(a.lastUpdateTime),
};
@@ -263,4 +243,4 @@ class ProfileOverrideStateModel with _$ProfileOverrideStateModel {
required Set<String> selectedRules,
OverrideData? overrideData,
}) = _ProfileOverrideStateModel;
}
}

View File

@@ -129,16 +129,6 @@ 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(
@@ -190,46 +180,43 @@ class CommonNavigationBar extends ConsumerWidget {
child: Column(
children: [
Expanded(
child: ScrollConfiguration(
behavior: HiddenBarScrollBehavior(),
child: SingleChildScrollView(
child: IntrinsicHeight(
child: NavigationRail(
backgroundColor: context.colorScheme.surfaceContainer,
selectedIconTheme: IconThemeData(
color: context.colorScheme.onSurfaceVariant,
),
unselectedIconTheme: IconThemeData(
color: context.colorScheme.onSurfaceVariant,
),
selectedLabelTextStyle:
context.textTheme.labelLarge!.copyWith(
color: context.colorScheme.onSurface,
),
unselectedLabelTextStyle:
context.textTheme.labelLarge!.copyWith(
color: context.colorScheme.onSurface,
),
destinations: navigationItems
.map(
(e) => NavigationRailDestination(
icon: e.icon,
label: Text(
Intl.message(e.label.name),
),
),
)
.toList(),
onDestinationSelected: (index) {
globalState.appController
.toPage(navigationItems[index].label);
},
extended: false,
selectedIndex: currentIndex,
labelType: showLabel
? NavigationRailLabelType.all
: NavigationRailLabelType.none,
child: SingleChildScrollView(
child: IntrinsicHeight(
child: NavigationRail(
backgroundColor: context.colorScheme.surfaceContainer,
selectedIconTheme: IconThemeData(
color: context.colorScheme.onSurfaceVariant,
),
unselectedIconTheme: IconThemeData(
color: context.colorScheme.onSurfaceVariant,
),
selectedLabelTextStyle:
context.textTheme.labelLarge!.copyWith(
color: context.colorScheme.onSurface,
),
unselectedLabelTextStyle:
context.textTheme.labelLarge!.copyWith(
color: context.colorScheme.onSurface,
),
destinations: navigationItems
.map(
(e) => NavigationRailDestination(
icon: e.icon,
label: Text(
Intl.message(e.label.name),
),
),
)
.toList(),
onDestinationSelected: (index) {
globalState.appController
.toPage(navigationItems[index].label);
},
extended: false,
selectedIndex: currentIndex,
labelType: showLabel
? NavigationRailLabelType.all
: NavigationRailLabelType.none,
),
),
),

View File

@@ -196,7 +196,7 @@ class ViewSize extends _$ViewSize with AutoDisposeNotifierMixin {
);
}
ViewMode get viewMode => utils.getViewMode(state.width);
ViewMode get viewMode => other.getViewMode(state.width);
bool get isMobileView => viewMode == ViewMode.mobile;
}
@@ -208,7 +208,7 @@ double viewWidth(Ref ref) {
@riverpod
ViewMode viewMode(Ref ref) {
return utils.getViewMode(ref.watch(viewWidthProvider));
return other.getViewMode(ref.watch(viewWidthProvider));
}
@riverpod
@@ -252,6 +252,21 @@ 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

View File

@@ -120,13 +120,13 @@ class Profiles extends _$Profiles with AutoDisposeNotifierMixin {
(element) => element.label == realLabel && element.id != id) !=
-1;
if (hasDup) {
return _getLabel(utils.getOverwriteLabel(realLabel), id);
return _getLabel(other.getOverwriteLabel(realLabel), id);
} else {
return label;
}
}
setProfile(Profile profile, {bool force = true}) {
setProfile(Profile profile) {
final List<Profile> profilesTemp = List.from(state);
final index =
profilesTemp.indexWhere((element) => element.id == profile.id);
@@ -135,7 +135,7 @@ class Profiles extends _$Profiles with AutoDisposeNotifierMixin {
);
if (index == -1) {
profilesTemp.add(updateProfile);
} else if (force == true) {
} else {
profilesTemp[index] = updateProfile;
}
state = profilesTemp;

Some files were not shown because too many files have changed in this diff Show More