Compare commits
2 Commits
v0.8.85-pr
...
v0.8.83-pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cb5d40969 | ||
|
|
30ee6889ab |
9
.github/workflows/build.yaml
vendored
9
.github/workflows/build.yaml
vendored
@@ -201,6 +201,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
|
||||||
TAG: ${{ github.ref_name }}
|
TAG: ${{ github.ref_name }}
|
||||||
|
RUN_ID: ${{ github.run_id }}
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install requests
|
pip install requests
|
||||||
@@ -211,6 +212,14 @@ jobs:
|
|||||||
version=$(echo "${{ github.ref_name }}" | sed 's/^v//')
|
version=$(echo "${{ github.ref_name }}" | sed 's/^v//')
|
||||||
sed "s|VERSION|$version|g" ./.github/release_template.md >> release.md
|
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
|
- name: Release
|
||||||
if: ${{ env.IS_STABLE == 'true' }}
|
if: ${{ env.IS_STABLE == 'true' }}
|
||||||
uses: softprops/action-gh-release@v2
|
uses: softprops/action-gh-release@v2
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
|
<action android:name="android.service.quicksettings.action.QS_TILE_PREFERENCES" />
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ enum class RunState {
|
|||||||
object GlobalState {
|
object GlobalState {
|
||||||
val runLock = ReentrantLock()
|
val runLock = ReentrantLock()
|
||||||
|
|
||||||
|
const val NOTIFICATION_CHANNEL = "FlClash"
|
||||||
|
|
||||||
|
const val NOTIFICATION_ID = 1
|
||||||
|
|
||||||
val runState: MutableLiveData<RunState> = MutableLiveData<RunState>(RunState.STOP)
|
val runState: MutableLiveData<RunState> = MutableLiveData<RunState>(RunState.STOP)
|
||||||
var flutterEngine: FlutterEngine? = null
|
var flutterEngine: FlutterEngine? = null
|
||||||
private var serviceEngine: FlutterEngine? = null
|
private var serviceEngine: FlutterEngine? = null
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.follow.clash
|
package com.follow.clash
|
||||||
|
|
||||||
import com.follow.clash.core.Core
|
|
||||||
import com.follow.clash.plugins.AppPlugin
|
import com.follow.clash.plugins.AppPlugin
|
||||||
import com.follow.clash.plugins.ServicePlugin
|
import com.follow.clash.plugins.ServicePlugin
|
||||||
import com.follow.clash.plugins.TilePlugin
|
import com.follow.clash.plugins.TilePlugin
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import java.util.concurrent.locks.ReentrantLock
|
|||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.coroutines.suspendCoroutine
|
import kotlin.coroutines.suspendCoroutine
|
||||||
|
|
||||||
|
|
||||||
suspend fun Drawable.getBase64(): String {
|
suspend fun Drawable.getBase64(): String {
|
||||||
val drawable = this
|
val drawable = this
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(Dispatchers.IO) {
|
||||||
|
|||||||
@@ -168,8 +168,10 @@ data object VpnPlugin : FlutterPlugin, MethodChannel.MethodCallHandler {
|
|||||||
try {
|
try {
|
||||||
if (GlobalState.runState.value != RunState.START) return
|
if (GlobalState.runState.value != RunState.START) return
|
||||||
val data = flutterMethodChannel.awaitResult<String>("getStartForegroundParams")
|
val data = flutterMethodChannel.awaitResult<String>("getStartForegroundParams")
|
||||||
val startForegroundParams = Gson().fromJson(
|
val startForegroundParams = if (data != null) Gson().fromJson(
|
||||||
data, StartForegroundParams::class.java
|
data, StartForegroundParams::class.java
|
||||||
|
) else StartForegroundParams(
|
||||||
|
title = "", content = ""
|
||||||
)
|
)
|
||||||
if (lastStartForegroundParams != startForegroundParams) {
|
if (lastStartForegroundParams != startForegroundParams) {
|
||||||
lastStartForegroundParams = startForegroundParams
|
lastStartForegroundParams = startForegroundParams
|
||||||
|
|||||||
@@ -1,6 +1,26 @@
|
|||||||
package com.follow.clash.services
|
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 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 {
|
interface BaseServiceInterface {
|
||||||
|
|
||||||
@@ -9,4 +29,71 @@ interface BaseServiceInterface {
|
|||||||
fun stop()
|
fun stop()
|
||||||
|
|
||||||
suspend fun startForeground(title: String, content: String)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("[FlClash]","startForeground===>")
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||||
|
try {
|
||||||
|
startForeground(
|
||||||
|
GlobalState.NOTIFICATION_ID, notification, FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||||
|
)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
startForeground(GlobalState.NOTIFICATION_ID, notification)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startForeground(GlobalState.NOTIFICATION_ID, notification)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,29 +1,51 @@
|
|||||||
package com.follow.clash.services
|
package com.follow.clash.services
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
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.app.Service
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import com.follow.clash.GlobalState
|
import com.follow.clash.GlobalState
|
||||||
import com.follow.clash.MainActivity
|
|
||||||
import com.follow.clash.extensions.getActionPendingIntent
|
|
||||||
import com.follow.clash.models.VpnOptions
|
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 {
|
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()
|
private val binder = LocalBinder()
|
||||||
|
|
||||||
inner class LocalBinder : Binder() {
|
inner class LocalBinder : Binder() {
|
||||||
@@ -38,93 +60,8 @@ class FlClashService : Service(), BaseServiceInterface {
|
|||||||
return super.onUnbind(intent)
|
return super.onUnbind(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val CHANNEL = "FlClash"
|
override fun onDestroy() {
|
||||||
|
stop()
|
||||||
private val notificationId: Int = 1
|
super.onDestroy()
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,8 @@
|
|||||||
package com.follow.clash.services
|
package com.follow.clash.services
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
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.PendingIntent
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
|
||||||
import android.net.ProxyInfo
|
import android.net.ProxyInfo
|
||||||
import android.net.VpnService
|
import android.net.VpnService
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
@@ -17,18 +13,13 @@ import android.os.RemoteException
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import com.follow.clash.GlobalState
|
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.getIpv4RouteAddress
|
||||||
import com.follow.clash.extensions.getIpv6RouteAddress
|
import com.follow.clash.extensions.getIpv6RouteAddress
|
||||||
import com.follow.clash.extensions.toCIDR
|
import com.follow.clash.extensions.toCIDR
|
||||||
import com.follow.clash.models.AccessControlMode
|
import com.follow.clash.models.AccessControlMode
|
||||||
import com.follow.clash.models.VpnOptions
|
import com.follow.clash.models.VpnOptions
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Deferred
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
||||||
@@ -128,82 +119,22 @@ class FlClashVpnService : VpnService(), BaseServiceInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val CHANNEL = "FlClash"
|
private var cachedBuilder: NotificationCompat.Builder? = null
|
||||||
|
|
||||||
private val notificationId: Int = 1
|
private suspend fun notificationBuilder(): NotificationCompat.Builder {
|
||||||
|
if (cachedBuilder == null) {
|
||||||
private val notificationBuilderDeferred: Deferred<NotificationCompat.Builder> by lazy {
|
cachedBuilder = createFlClashNotificationBuilder().await()
|
||||||
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")
|
@SuppressLint("ForegroundServiceType")
|
||||||
override suspend fun startForeground(title: String, content: String) {
|
override suspend fun startForeground(title: String, content: String) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
startForeground(
|
||||||
val manager = getSystemService(NotificationManager::class.java)
|
notificationBuilder()
|
||||||
var channel = manager?.getNotificationChannel(CHANNEL)
|
|
||||||
if (channel == null) {
|
|
||||||
channel =
|
|
||||||
NotificationChannel(CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW)
|
|
||||||
manager?.createNotificationChannel(channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val notification =
|
|
||||||
getNotificationBuilder()
|
|
||||||
.setContentTitle(title)
|
.setContentTitle(title)
|
||||||
.setContentText(content)
|
.setContentText(content).build()
|
||||||
.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) {
|
override fun onTrimMemory(level: Int) {
|
||||||
|
|||||||
@@ -385,5 +385,12 @@
|
|||||||
"expressiveScheme": "Expressive",
|
"expressiveScheme": "Expressive",
|
||||||
"contentScheme": "Content",
|
"contentScheme": "Content",
|
||||||
"rainbowScheme": "Rainbow",
|
"rainbowScheme": "Rainbow",
|
||||||
"fruitSaladScheme": "FruitSalad"
|
"fruitSaladScheme": "FruitSalad",
|
||||||
|
"developerMode": "Developer mode",
|
||||||
|
"developerModeEnableTip": "Developer mode is enabled.",
|
||||||
|
"messageTest": "Message test",
|
||||||
|
"messageTestTip": "This is a message.",
|
||||||
|
"crashTest": "Crash test",
|
||||||
|
"clearData": "Clear Data",
|
||||||
|
"textScale": "Text Scaling"
|
||||||
}
|
}
|
||||||
@@ -385,5 +385,13 @@
|
|||||||
"expressiveScheme": "エクスプレッシブ",
|
"expressiveScheme": "エクスプレッシブ",
|
||||||
"contentScheme": "コンテンツテーマ",
|
"contentScheme": "コンテンツテーマ",
|
||||||
"rainbowScheme": "レインボー",
|
"rainbowScheme": "レインボー",
|
||||||
"fruitSaladScheme": "フルーツサラダ"
|
"fruitSaladScheme": "フルーツサラダ",
|
||||||
|
"developerMode": "デベロッパーモード",
|
||||||
|
"developerModeEnableTip": "デベロッパーモードが有効になりました。",
|
||||||
|
"messageTest": "メッセージテスト",
|
||||||
|
"messageTestTip": "これはメッセージです。",
|
||||||
|
"crashTest": "クラッシュテスト",
|
||||||
|
"clearData": "データを消去",
|
||||||
|
"zoom": "ズーム",
|
||||||
|
"textScale": "テキストスケーリング"
|
||||||
}
|
}
|
||||||
@@ -385,5 +385,13 @@
|
|||||||
"expressiveScheme": "Экспрессивные",
|
"expressiveScheme": "Экспрессивные",
|
||||||
"contentScheme": "Контентная тема",
|
"contentScheme": "Контентная тема",
|
||||||
"rainbowScheme": "Радужные",
|
"rainbowScheme": "Радужные",
|
||||||
"fruitSaladScheme": "Фруктовый микс"
|
"fruitSaladScheme": "Фруктовый микс",
|
||||||
|
"developerMode": "Режим разработчика",
|
||||||
|
"developerModeEnableTip": "Режим разработчика активирован.",
|
||||||
|
"messageTest": "Тестирование сообщения",
|
||||||
|
"messageTestTip": "Это сообщение.",
|
||||||
|
"crashTest": "Тест на сбои",
|
||||||
|
"clearData": "Очистить данные",
|
||||||
|
"zoom": "Масштаб",
|
||||||
|
"textScale": "Масштабирование текста"
|
||||||
}
|
}
|
||||||
@@ -385,5 +385,13 @@
|
|||||||
"expressiveScheme": "表现力",
|
"expressiveScheme": "表现力",
|
||||||
"contentScheme": "内容主题",
|
"contentScheme": "内容主题",
|
||||||
"rainbowScheme": "彩虹",
|
"rainbowScheme": "彩虹",
|
||||||
"fruitSaladScheme": "果缤纷"
|
"fruitSaladScheme": "果缤纷",
|
||||||
|
"developerMode": "开发者模式",
|
||||||
|
"developerModeEnableTip": "开发者模式已启用。",
|
||||||
|
"messageTest": "消息测试",
|
||||||
|
"messageTestTip": "这是一条消息。",
|
||||||
|
"crashTest": "崩溃测试",
|
||||||
|
"clearData": "清除数据",
|
||||||
|
"zoom": "缩放",
|
||||||
|
"textScale": "文本缩放"
|
||||||
}
|
}
|
||||||
Submodule core/Clash.Meta updated: f19dad529f...88a1848dfb
@@ -166,6 +166,9 @@ func handleAction(action *Action, result func(data interface{})) {
|
|||||||
data := action.Data.(string)
|
data := action.Data.(string)
|
||||||
handleSetState(data)
|
handleSetState(data)
|
||||||
result(true)
|
result(true)
|
||||||
|
case crashMethod:
|
||||||
|
result(true)
|
||||||
|
handleCrash()
|
||||||
default:
|
default:
|
||||||
handle := nextHandle(action, result)
|
handle := nextHandle(action, result)
|
||||||
if handle {
|
if handle {
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ func getRawConfigWithId(id string) *config.RawConfig {
|
|||||||
path := getProfilePath(id)
|
path := getProfilePath(id)
|
||||||
bytes, err := readFile(path)
|
bytes, err := readFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("profile is not exist")
|
|
||||||
return config.DefaultRawConfig()
|
return config.DefaultRawConfig()
|
||||||
}
|
}
|
||||||
prof, err := config.UnmarshalRawConfig(bytes)
|
prof, err := config.UnmarshalRawConfig(bytes)
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ const (
|
|||||||
getRunTimeMethod Method = "getRunTime"
|
getRunTimeMethod Method = "getRunTime"
|
||||||
getCurrentProfileNameMethod Method = "getCurrentProfileName"
|
getCurrentProfileNameMethod Method = "getCurrentProfileName"
|
||||||
getProfileMethod Method = "getProfile"
|
getProfileMethod Method = "getProfile"
|
||||||
|
crashMethod Method = "crash"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Method string
|
type Method string
|
||||||
|
|||||||
13
core/go.mod
13
core/go.mod
@@ -7,6 +7,7 @@ replace github.com/metacubex/mihomo => ./Clash.Meta
|
|||||||
require (
|
require (
|
||||||
github.com/metacubex/mihomo v0.0.0-00010101000000-000000000000
|
github.com/metacubex/mihomo v0.0.0-00010101000000-000000000000
|
||||||
github.com/samber/lo v1.49.1
|
github.com/samber/lo v1.49.1
|
||||||
|
golang.org/x/sync v0.11.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -52,20 +53,20 @@ require (
|
|||||||
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab // indirect
|
github.com/metacubex/amneziawg-go v0.0.0-20240922133038-fdf3a4d5a4ab // indirect
|
||||||
github.com/metacubex/bart v0.19.0 // indirect
|
github.com/metacubex/bart v0.19.0 // indirect
|
||||||
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 // indirect
|
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399 // indirect
|
||||||
github.com/metacubex/chacha v0.1.1 // indirect
|
github.com/metacubex/chacha v0.1.2 // indirect
|
||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // indirect
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 // indirect
|
||||||
github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // 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/quic-go v0.49.1-0.20250212162123-c135a4412996 // indirect
|
||||||
github.com/metacubex/randv2 v0.2.0 // indirect
|
github.com/metacubex/randv2 v0.2.0 // indirect
|
||||||
github.com/metacubex/reality v0.0.0-20250219003814-74e8d7850629 // indirect
|
github.com/metacubex/sing-quic v0.0.0-20250404030904-b2cc8aab562c // 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-shadowsocks v0.2.8 // indirect
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.2 // indirect
|
github.com/metacubex/sing-shadowsocks2 v0.2.2 // indirect
|
||||||
github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04 // indirect
|
github.com/metacubex/sing-shadowtls v0.0.0-20250412122235-0e9005731a63 // indirect
|
||||||
|
github.com/metacubex/sing-tun v0.4.6-0.20250412144348-c426cb167db5 // indirect
|
||||||
github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82 // indirect
|
github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82 // indirect
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589 // 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/tfo-go v0.0.0-20241231083714-66613d49c422 // indirect
|
||||||
github.com/metacubex/utls v1.6.8-alpha.4 // indirect
|
github.com/metacubex/utls v1.7.0-alpha.1 // indirect
|
||||||
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 // indirect
|
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 // indirect
|
||||||
github.com/miekg/dns v1.1.63 // indirect
|
github.com/miekg/dns v1.1.63 // indirect
|
||||||
github.com/mroth/weightedrand/v2 v2.1.0 // indirect
|
github.com/mroth/weightedrand/v2 v2.1.0 // indirect
|
||||||
@@ -84,7 +85,6 @@ require (
|
|||||||
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
||||||
github.com/sagernet/sing v0.5.2 // indirect
|
github.com/sagernet/sing v0.5.2 // indirect
|
||||||
github.com/sagernet/sing-mux v0.2.1 // 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/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
||||||
github.com/shirou/gopsutil/v4 v4.25.1 // indirect
|
github.com/shirou/gopsutil/v4 v4.25.1 // indirect
|
||||||
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect
|
github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect
|
||||||
@@ -107,7 +107,6 @@ require (
|
|||||||
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect
|
||||||
golang.org/x/mod v0.20.0 // indirect
|
golang.org/x/mod v0.20.0 // indirect
|
||||||
golang.org/x/net v0.35.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/sys v0.30.0 // indirect
|
||||||
golang.org/x/text v0.22.0 // indirect
|
golang.org/x/text v0.22.0 // indirect
|
||||||
golang.org/x/time v0.7.0 // indirect
|
golang.org/x/time v0.7.0 // indirect
|
||||||
|
|||||||
22
core/go.sum
22
core/go.sum
@@ -101,8 +101,8 @@ github.com/metacubex/bart v0.19.0 h1:XQ9AJeI+WO+phRPkUOoflAFwlqDJnm5BPQpixciJQBY
|
|||||||
github.com/metacubex/bart v0.19.0/go.mod h1:DCcyfP4MC+Zy7sLK7XeGuMw+P5K9mIRsYOBgiE8icsI=
|
github.com/metacubex/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 h1:oBowHVKZycNtAFbZ6avaCSZJYeme2Nrj+4RpV2cNJig=
|
||||||
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399/go.mod h1:4xcieuIK+M4bGQmQYZVqEaIYqjS1ahO4kXG7EmDgEro=
|
github.com/metacubex/bbolt v0.0.0-20240822011022-aed6d4850399/go.mod h1:4xcieuIK+M4bGQmQYZVqEaIYqjS1ahO4kXG7EmDgEro=
|
||||||
github.com/metacubex/chacha v0.1.1 h1:OHIv11Nd9CISAIzegpjfupIoZp9DYm6uQw41RxvmU/c=
|
github.com/metacubex/chacha v0.1.2 h1:QulCq3eVm3TO6+4nVIWJtmSe7BT2GMrgVHuAoqRQnlc=
|
||||||
github.com/metacubex/chacha v0.1.1/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
|
github.com/metacubex/chacha v0.1.2/go.mod h1:Djn9bPZxLTXbJFSeyo0/qzEzQI+gUSSzttuzZM75GH8=
|
||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI=
|
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI=
|
||||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
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=
|
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/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 h1:uP38uBvV2SxYfLj53kuvAjbND4RUDfFJjwr4UigMiLs=
|
||||||
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFqSPyj2cxY=
|
||||||
github.com/metacubex/reality v0.0.0-20250219003814-74e8d7850629 h1:aHsYiTvubfgMa3JMTDY//hDXVvFWrHg6ARckR52ttZs=
|
github.com/metacubex/sing-quic v0.0.0-20250404030904-b2cc8aab562c h1:OB3WmMA8YPJjE36RjD9X8xlrWGJ4orxbf2R/KAE28b0=
|
||||||
github.com/metacubex/reality v0.0.0-20250219003814-74e8d7850629/go.mod h1:TTeIOZLdGmzc07Oedn++vWUUfkZoXLF4sEMxWuhBFr8=
|
github.com/metacubex/sing-quic v0.0.0-20250404030904-b2cc8aab562c/go.mod h1:g7Mxj7b7zm7YVqD975mk/hSmrb0A0G4bVvIMr2MMzn8=
|
||||||
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 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJRafgwBHO5B4=
|
||||||
github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0=
|
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 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo=
|
||||||
github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q=
|
github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q=
|
||||||
github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04 h1:B211C+i/I8CWf4I/BaAV0mmkEHrDBJ0XR9EWxjPbFEg=
|
github.com/metacubex/sing-shadowtls v0.0.0-20250412122235-0e9005731a63 h1:vy/8ZYYtWUXYnOnw/NF8ThG1W/RqM/h5rkun+OXZMH0=
|
||||||
github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04/go.mod h1:V0N4rr0dWPBEE20ESkTXdbtx2riQYcb6YtwC5w/9wl0=
|
github.com/metacubex/sing-shadowtls v0.0.0-20250412122235-0e9005731a63/go.mod h1:eDZ2JpkSkewGmUlCoLSn2MRFn1D0jKPIys/6aogFx7U=
|
||||||
|
github.com/metacubex/sing-tun v0.4.6-0.20250412144348-c426cb167db5 h1:hcsz5e5lqhBxn3iQQDIF60FLZ8PQT542GTQZ+1wcIGo=
|
||||||
|
github.com/metacubex/sing-tun v0.4.6-0.20250412144348-c426cb167db5/go.mod h1:V0N4rr0dWPBEE20ESkTXdbtx2riQYcb6YtwC5w/9wl0=
|
||||||
github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82 h1:zZp5uct9+/0Hb1jKGyqDjCU4/72t43rs7qOq3Rc9oU8=
|
github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82 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-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 h1:Z6bNy0HLTjx6BKIkV48sV/yia/GP8Bnyb5JQuGgSGzg=
|
||||||
github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589/go.mod h1:4NclTLIZuk+QkHVCGrP87rHi/y8YjgPytxTgApJNMhc=
|
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 h1:zGeQt3UyNydIVrMRB97AA5WsYEau/TyCnRtTf1yUmJY=
|
||||||
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
||||||
github.com/metacubex/utls v1.6.8-alpha.4 h1:5EvsCHxDNneaOtAyc8CztoNSpmonLvkvuGs01lIeeEI=
|
github.com/metacubex/utls v1.7.0-alpha.1 h1:oMFsPh2oTlALJ7vKXPJuqgy0YeiZ+q/LLw+ZdxZ80l4=
|
||||||
github.com/metacubex/utls v1.6.8-alpha.4/go.mod h1:MEZ5WO/VLKYs/s/dOzEK/mlXOQxc04ESeLzRgjmLYtk=
|
github.com/metacubex/utls v1.7.0-alpha.1/go.mod h1:oknYT0qTOwE4hjPmZOEpzVdefnW7bAdGLvZcqmk4TLU=
|
||||||
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ=
|
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181 h1:hJLQviGySBuaynlCwf/oYgIxbVbGRUIKZCxdya9YrbQ=
|
||||||
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181/go.mod h1:phewKljNYiTVT31Gcif8RiCKnTUOgVWFJjccqYM8s+Y=
|
github.com/metacubex/wireguard-go v0.0.0-20240922131502-c182e7471181/go.mod h1:phewKljNYiTVT31Gcif8RiCKnTUOgVWFJjccqYM8s+Y=
|
||||||
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
||||||
@@ -174,8 +174,6 @@ github.com/sagernet/sing v0.5.2 h1:2OZQJNKGtji/66QLxbf/T/dqtK/3+fF/zuHH9tsGK7M=
|
|||||||
github.com/sagernet/sing v0.5.2/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
github.com/sagernet/sing 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 h1:N/3MHymfnFZRd29tE3TaXwPUVVgKvxhtOkiCMLp9HVo=
|
||||||
github.com/sagernet/sing-mux v0.2.1/go.mod h1:dm3BWL6NvES9pbib7llpylrq7Gq+LjlzG+0RacdxcyE=
|
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 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
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=
|
github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew=
|
||||||
|
|||||||
@@ -442,6 +442,10 @@ func handleSetState(params string) {
|
|||||||
_ = json.Unmarshal([]byte(params), state.CurrentState)
|
_ = json.Unmarshal([]byte(params), state.CurrentState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleCrash() {
|
||||||
|
panic("handle invoke crash")
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
adapter.UrlTestHook = func(url string, name string, delay uint16) {
|
adapter.UrlTestHook = func(url string, name string, delay uint16) {
|
||||||
delayData := &Delay{
|
delayData := &Delay{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:dynamic_color/dynamic_color.dart';
|
|
||||||
import 'package:fl_clash/clash/clash.dart';
|
import 'package:fl_clash/clash/clash.dart';
|
||||||
import 'package:fl_clash/common/common.dart';
|
import 'package:fl_clash/common/common.dart';
|
||||||
import 'package:fl_clash/l10n/l10n.dart';
|
import 'package:fl_clash/l10n/l10n.dart';
|
||||||
@@ -14,7 +13,6 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
import 'controller.dart';
|
import 'controller.dart';
|
||||||
import 'models/models.dart';
|
|
||||||
import 'pages/pages.dart';
|
import 'pages/pages.dart';
|
||||||
|
|
||||||
class Application extends ConsumerStatefulWidget {
|
class Application extends ConsumerStatefulWidget {
|
||||||
@@ -27,7 +25,6 @@ class Application extends ConsumerStatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ApplicationState extends ConsumerState<Application> {
|
class ApplicationState extends ConsumerState<Application> {
|
||||||
late ColorSchemes systemColorSchemes;
|
|
||||||
Timer? _autoUpdateGroupTaskTimer;
|
Timer? _autoUpdateGroupTaskTimer;
|
||||||
Timer? _autoUpdateProfilesTaskTimer;
|
Timer? _autoUpdateProfilesTaskTimer;
|
||||||
|
|
||||||
@@ -132,19 +129,6 @@ class ApplicationState extends ConsumerState<Application> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateSystemColorSchemes(
|
|
||||||
ColorScheme? lightDynamic,
|
|
||||||
ColorScheme? darkDynamic,
|
|
||||||
) {
|
|
||||||
systemColorSchemes = ColorSchemes(
|
|
||||||
lightColorScheme: lightDynamic,
|
|
||||||
darkColorScheme: darkDynamic,
|
|
||||||
);
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
globalState.appController.updateSystemColorSchemes(systemColorSchemes);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(context) {
|
Widget build(context) {
|
||||||
return _buildPlatformState(
|
return _buildPlatformState(
|
||||||
@@ -154,49 +138,44 @@ class ApplicationState extends ConsumerState<Application> {
|
|||||||
final locale =
|
final locale =
|
||||||
ref.watch(appSettingProvider.select((state) => state.locale));
|
ref.watch(appSettingProvider.select((state) => state.locale));
|
||||||
final themeProps = ref.watch(themeSettingProvider);
|
final themeProps = ref.watch(themeSettingProvider);
|
||||||
return DynamicColorBuilder(
|
return MaterialApp(
|
||||||
builder: (lightDynamic, darkDynamic) {
|
debugShowCheckedModeBanner: false,
|
||||||
_updateSystemColorSchemes(lightDynamic, darkDynamic);
|
navigatorKey: globalState.navigatorKey,
|
||||||
return MaterialApp(
|
localizationsDelegates: const [
|
||||||
debugShowCheckedModeBanner: false,
|
AppLocalizations.delegate,
|
||||||
navigatorKey: globalState.navigatorKey,
|
GlobalMaterialLocalizations.delegate,
|
||||||
localizationsDelegates: const [
|
GlobalCupertinoLocalizations.delegate,
|
||||||
AppLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate
|
||||||
GlobalMaterialLocalizations.delegate,
|
],
|
||||||
GlobalCupertinoLocalizations.delegate,
|
builder: (_, child) {
|
||||||
GlobalWidgetsLocalizations.delegate
|
return AppEnvManager(
|
||||||
],
|
child: _buildPlatformApp(
|
||||||
builder: (_, child) {
|
_buildApp(child!),
|
||||||
return AppEnvManager(
|
|
||||||
child: _buildPlatformApp(
|
|
||||||
_buildApp(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,
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
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(),
|
child: const HomePage(),
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ mixin ClashInterface {
|
|||||||
|
|
||||||
stopLog();
|
stopLog();
|
||||||
|
|
||||||
|
Future<bool> crash();
|
||||||
|
|
||||||
FutureOr<String> getConnections();
|
FutureOr<String> getConnections();
|
||||||
|
|
||||||
FutureOr<bool> closeConnection(String id);
|
FutureOr<bool> closeConnection(String id);
|
||||||
@@ -104,6 +106,7 @@ abstract class ClashHandlerInterface with ClashInterface {
|
|||||||
case ActionMethod.closeConnection:
|
case ActionMethod.closeConnection:
|
||||||
case ActionMethod.stopListener:
|
case ActionMethod.stopListener:
|
||||||
case ActionMethod.setState:
|
case ActionMethod.setState:
|
||||||
|
case ActionMethod.crash:
|
||||||
completer?.complete(result.data as bool);
|
completer?.complete(result.data as bool);
|
||||||
return;
|
return;
|
||||||
case ActionMethod.changeProxy:
|
case ActionMethod.changeProxy:
|
||||||
@@ -242,6 +245,14 @@ abstract class ClashHandlerInterface with ClashInterface {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> crash() {
|
||||||
|
return invoke<bool>(
|
||||||
|
method: ActionMethod.crash,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<String> getProxies() {
|
Future<String> getProxies() {
|
||||||
return invoke<String>(
|
return invoke<String>(
|
||||||
|
|||||||
@@ -17,15 +17,12 @@ const packageName = "com.follow.clash";
|
|||||||
final unixSocketPath = "/tmp/FlClashSocket_${Random().nextInt(10000)}.sock";
|
final unixSocketPath = "/tmp/FlClashSocket_${Random().nextInt(10000)}.sock";
|
||||||
const helperPort = 47890;
|
const helperPort = 47890;
|
||||||
const helperTag = "2024125";
|
const helperTag = "2024125";
|
||||||
const baseInfoEdgeInsets = EdgeInsets.symmetric(
|
final baseInfoEdgeInsets = EdgeInsets.symmetric(
|
||||||
vertical: 16,
|
vertical: 16.ap,
|
||||||
horizontal: 16,
|
horizontal: 16.ap,
|
||||||
);
|
);
|
||||||
|
|
||||||
double textScaleFactor = min(
|
final defaultTextScaleFactor = WidgetsBinding.instance.platformDispatcher.textScaleFactor;
|
||||||
WidgetsBinding.instance.platformDispatcher.textScaleFactor,
|
|
||||||
1.2,
|
|
||||||
);
|
|
||||||
const httpTimeoutDuration = Duration(milliseconds: 5000);
|
const httpTimeoutDuration = Duration(milliseconds: 5000);
|
||||||
const moreDuration = Duration(milliseconds: 100);
|
const moreDuration = Duration(milliseconds: 100);
|
||||||
const animateDuration = Duration(milliseconds: 100);
|
const animateDuration = Duration(milliseconds: 100);
|
||||||
@@ -44,7 +41,6 @@ const profilesDirectoryName = "profiles";
|
|||||||
const localhost = "127.0.0.1";
|
const localhost = "127.0.0.1";
|
||||||
const clashConfigKey = "clash_config";
|
const clashConfigKey = "clash_config";
|
||||||
const configKey = "config";
|
const configKey = "config";
|
||||||
const listItemPadding = EdgeInsets.symmetric(horizontal: 16);
|
|
||||||
const double dialogCommonWidth = 300;
|
const double dialogCommonWidth = 300;
|
||||||
const repository = "chen08209/FlClash";
|
const repository = "chen08209/FlClash";
|
||||||
const defaultExternalController = "127.0.0.1:9090";
|
const defaultExternalController = "127.0.0.1:9090";
|
||||||
@@ -81,7 +77,7 @@ const viewModeColumnsMap = {
|
|||||||
const defaultPrimaryColor = 0xFF795548;
|
const defaultPrimaryColor = 0xFF795548;
|
||||||
|
|
||||||
double getWidgetHeight(num lines) {
|
double getWidgetHeight(num lines) {
|
||||||
return max(lines * 84 * textScaleFactor + (lines - 1) * 16, 0);
|
return max(lines * 84 + (lines - 1) * 16, 0).ap;
|
||||||
}
|
}
|
||||||
|
|
||||||
final mainIsolate = "FlClashMainIsolate";
|
final mainIsolate = "FlClashMainIsolate";
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:fl_clash/manager/manager.dart';
|
import 'package:fl_clash/manager/message_manager.dart';
|
||||||
import 'package:fl_clash/widgets/scaffold.dart';
|
import 'package:fl_clash/widgets/scaffold.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -11,6 +11,36 @@ extension BuildContextExtension on BuildContext {
|
|||||||
return findAncestorStateOfType<MessageManagerState>()?.message(text);
|
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 {
|
Size get appSize {
|
||||||
return MediaQuery.of(this).size;
|
return MediaQuery.of(this).size;
|
||||||
}
|
}
|
||||||
@@ -27,10 +57,10 @@ extension BuildContextExtension on BuildContext {
|
|||||||
T? state;
|
T? state;
|
||||||
|
|
||||||
visitor(Element element) {
|
visitor(Element element) {
|
||||||
if(!element.mounted){
|
if (!element.mounted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(element is StatefulElement){
|
if (element is StatefulElement) {
|
||||||
if (element.state is T) {
|
if (element.state is T) {
|
||||||
state = element.state as T;
|
state = element.state as T;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,13 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class Measure {
|
class Measure {
|
||||||
final TextScaler _textScale;
|
final TextScaler _textScaler;
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
|
final Map<String, dynamic> _measureMap;
|
||||||
|
|
||||||
Measure.of(this.context)
|
Measure.of(this.context, double textScaleFactor)
|
||||||
: _textScale = TextScaler.linear(
|
: _measureMap = {},
|
||||||
|
_textScaler = TextScaler.linear(
|
||||||
textScaleFactor,
|
textScaleFactor,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -21,7 +23,7 @@ class Measure {
|
|||||||
style: text.style,
|
style: text.style,
|
||||||
),
|
),
|
||||||
maxLines: text.maxLines,
|
maxLines: text.maxLines,
|
||||||
textScaler: _textScale,
|
textScaler: _textScaler,
|
||||||
textDirection: text.textDirection ?? TextDirection.ltr,
|
textDirection: text.textDirection ?? TextDirection.ltr,
|
||||||
)..layout(
|
)..layout(
|
||||||
maxWidth: maxWidth,
|
maxWidth: maxWidth,
|
||||||
@@ -29,81 +31,75 @@ class Measure {
|
|||||||
return textPainter.size;
|
return textPainter.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
double? _bodyMediumHeight;
|
|
||||||
Size? _bodyLargeSize;
|
|
||||||
double? _bodySmallHeight;
|
|
||||||
double? _labelSmallHeight;
|
|
||||||
double? _labelMediumHeight;
|
|
||||||
double? _titleLargeHeight;
|
|
||||||
double? _titleMediumHeight;
|
|
||||||
|
|
||||||
double get bodyMediumHeight {
|
double get bodyMediumHeight {
|
||||||
_bodyMediumHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"bodyMediumHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.bodyMedium,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.bodyMedium,
|
||||||
return _bodyMediumHeight!;
|
),
|
||||||
}
|
).height,
|
||||||
|
|
||||||
Size get bodyLargeSize {
|
|
||||||
_bodyLargeSize ??= computeTextSize(
|
|
||||||
Text(
|
|
||||||
"X",
|
|
||||||
style: context.textTheme.bodyLarge,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
return _bodyLargeSize!;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double get bodySmallHeight {
|
double get bodySmallHeight {
|
||||||
_bodySmallHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"bodySmallHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.bodySmall,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.bodySmall,
|
||||||
return _bodySmallHeight!;
|
),
|
||||||
|
).height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double get labelSmallHeight {
|
double get labelSmallHeight {
|
||||||
_labelSmallHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"labelSmallHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.labelSmall,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.labelSmall,
|
||||||
return _labelSmallHeight!;
|
),
|
||||||
|
).height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double get labelMediumHeight {
|
double get labelMediumHeight {
|
||||||
_labelMediumHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"labelMediumHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.labelMedium,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.labelMedium,
|
||||||
return _labelMediumHeight!;
|
),
|
||||||
|
).height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double get titleLargeHeight {
|
double get titleLargeHeight {
|
||||||
_titleLargeHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"titleLargeHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.titleLarge,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.titleLarge,
|
||||||
return _titleLargeHeight!;
|
),
|
||||||
|
).height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double get titleMediumHeight {
|
double get titleMediumHeight {
|
||||||
_titleMediumHeight ??= computeTextSize(
|
return _measureMap.getCacheValue(
|
||||||
Text(
|
"titleMediumHeight",
|
||||||
"X",
|
computeTextSize(
|
||||||
style: context.textTheme.titleMedium,
|
Text(
|
||||||
),
|
"X",
|
||||||
).height;
|
style: context.textTheme.titleMedium,
|
||||||
return _titleMediumHeight!;
|
),
|
||||||
|
).height,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -12,6 +13,10 @@ extension NumExt on num {
|
|||||||
}
|
}
|
||||||
return formatted;
|
return formatted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double get ap {
|
||||||
|
return this * (1 + (globalState.theme.textScaleFactor - 1) * 0.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension DoubleExt on double {
|
extension DoubleExt on double {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import 'package:fl_clash/enum/enum.dart';
|
|
||||||
import 'package:fl_clash/models/models.dart';
|
import 'package:fl_clash/models/models.dart';
|
||||||
import 'package:fl_clash/state.dart';
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
@@ -20,10 +19,7 @@ class CommonPrint {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
globalState.appController.addLog(
|
globalState.appController.addLog(
|
||||||
Log(
|
Log.app(payload),
|
||||||
logLevel: LogLevel.info,
|
|
||||||
payload: payload,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,12 @@ import 'package:flutter/material.dart';
|
|||||||
class CommonTheme {
|
class CommonTheme {
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
final Map<String, Color> _colorMap;
|
final Map<String, Color> _colorMap;
|
||||||
|
final double textScaleFactor;
|
||||||
|
|
||||||
CommonTheme.of(this.context) : _colorMap = {};
|
CommonTheme.of(
|
||||||
|
this.context,
|
||||||
|
this.textScaleFactor,
|
||||||
|
) : _colorMap = {};
|
||||||
|
|
||||||
Color get darkenSecondaryContainer {
|
Color get darkenSecondaryContainer {
|
||||||
return _colorMap.getCacheValue(
|
return _colorMap.getCacheValue(
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ class Tray {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
menuItems.add(MenuItem.separator());
|
menuItems.add(MenuItem.separator());
|
||||||
if (!Platform.isWindows) {
|
if (Platform.isMacOS) {
|
||||||
for (final group in trayState.groups) {
|
for (final group in trayState.groups) {
|
||||||
List<MenuItem> subMenuItems = [];
|
List<MenuItem> subMenuItems = [];
|
||||||
for (final proxy in group.all) {
|
for (final proxy in group.all) {
|
||||||
|
|||||||
@@ -334,23 +334,22 @@ class AppController {
|
|||||||
try {
|
try {
|
||||||
await updateProfile(profile);
|
await updateProfile(profile);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_ref.read(logsProvider.notifier).addLog(
|
commonPrint.log(e.toString());
|
||||||
Log(
|
|
||||||
logLevel: LogLevel.info,
|
|
||||||
payload: e.toString(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> updateGroups() async {
|
Future<void> updateGroups() async {
|
||||||
_ref.read(groupsProvider.notifier).value = await retry(
|
try {
|
||||||
task: () async {
|
_ref.read(groupsProvider.notifier).value = await retry(
|
||||||
return await clashCore.getProxiesGroups();
|
task: () async {
|
||||||
},
|
return await clashCore.getProxiesGroups();
|
||||||
retryIf: (res) => res.isEmpty,
|
},
|
||||||
);
|
retryIf: (res) => res.isEmpty,
|
||||||
|
);
|
||||||
|
} catch (_) {
|
||||||
|
_ref.read(groupsProvider.notifier).value = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProfiles() async {
|
updateProfiles() async {
|
||||||
@@ -362,10 +361,6 @@ class AppController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSystemColorSchemes(ColorSchemes colorSchemes) {
|
|
||||||
_ref.read(appSchemesProvider.notifier).value = colorSchemes;
|
|
||||||
}
|
|
||||||
|
|
||||||
savePreferences() async {
|
savePreferences() async {
|
||||||
commonPrint.log("save preferences");
|
commonPrint.log("save preferences");
|
||||||
await preferences.saveConfig(globalState.config);
|
await preferences.saveConfig(globalState.config);
|
||||||
@@ -410,6 +405,14 @@ class AppController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future handleClear() async {
|
||||||
|
await preferences.clearPreferences();
|
||||||
|
commonPrint.log("clear preferences");
|
||||||
|
globalState.config = Config(
|
||||||
|
themeProps: defaultThemeProps,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
autoCheckUpdate() async {
|
autoCheckUpdate() async {
|
||||||
if (!_ref.read(appSettingProvider).autoCheckUpdate) return;
|
if (!_ref.read(appSettingProvider).autoCheckUpdate) return;
|
||||||
final res = await request.checkForUpdate();
|
final res = await request.checkForUpdate();
|
||||||
|
|||||||
@@ -91,7 +91,14 @@ enum Mode { rule, global, direct }
|
|||||||
|
|
||||||
enum ViewMode { mobile, laptop, desktop }
|
enum ViewMode { mobile, laptop, desktop }
|
||||||
|
|
||||||
enum LogLevel { debug, info, warning, error, silent }
|
enum LogLevel {
|
||||||
|
debug,
|
||||||
|
info,
|
||||||
|
warning,
|
||||||
|
error,
|
||||||
|
silent,
|
||||||
|
app,
|
||||||
|
}
|
||||||
|
|
||||||
enum TransportProtocol { udp, tcp }
|
enum TransportProtocol { udp, tcp }
|
||||||
|
|
||||||
@@ -262,6 +269,7 @@ enum ActionMethod {
|
|||||||
getCountryCode,
|
getCountryCode,
|
||||||
getMemory,
|
getMemory,
|
||||||
getProfile,
|
getProfile,
|
||||||
|
crash,
|
||||||
|
|
||||||
///Android,
|
///Android,
|
||||||
setFdMap,
|
setFdMap,
|
||||||
@@ -308,6 +316,12 @@ enum DashboardWidget {
|
|||||||
child: NetworkSpeed(),
|
child: NetworkSpeed(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
outboundModeV2(
|
||||||
|
GridItem(
|
||||||
|
crossAxisCellCount: 8,
|
||||||
|
child: OutboundModeV2(),
|
||||||
|
),
|
||||||
|
),
|
||||||
outboundMode(
|
outboundMode(
|
||||||
GridItem(
|
GridItem(
|
||||||
crossAxisCellCount: 4,
|
crossAxisCellCount: 4,
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:fl_clash/common/common.dart';
|
import 'package:fl_clash/common/common.dart';
|
||||||
|
import 'package:fl_clash/providers/config.dart';
|
||||||
import 'package:fl_clash/state.dart';
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:fl_clash/widgets/list.dart';
|
import 'package:fl_clash/widgets/list.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
@immutable
|
@immutable
|
||||||
class Contributor {
|
class Contributor {
|
||||||
@@ -116,33 +120,43 @@ class AboutFragment extends StatelessWidget {
|
|||||||
title: Column(
|
title: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Wrap(
|
Consumer(builder: (_, ref, ___) {
|
||||||
spacing: 16,
|
return _DeveloperModeDetector(
|
||||||
crossAxisAlignment: WrapCrossAlignment.center,
|
child: Wrap(
|
||||||
children: [
|
spacing: 16,
|
||||||
Padding(
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
padding: const EdgeInsets.all(12),
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/images/icon.png',
|
|
||||||
width: 64,
|
|
||||||
height: 64,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Padding(
|
||||||
appName,
|
padding: const EdgeInsets.all(12),
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
child: Image.asset(
|
||||||
|
'assets/images/icon.png',
|
||||||
|
width: 64,
|
||||||
|
height: 64,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Column(
|
||||||
globalState.packageInfo.version,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
style: Theme.of(context).textTheme.labelLarge,
|
children: [
|
||||||
|
Text(
|
||||||
|
appName,
|
||||||
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
|
),
|
||||||
|
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(
|
const SizedBox(
|
||||||
height: 24,
|
height: 24,
|
||||||
),
|
),
|
||||||
@@ -209,3 +223,52 @@ class Avatar extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _DeveloperModeDetector extends StatefulWidget {
|
||||||
|
final Widget child;
|
||||||
|
final VoidCallback onEnterDeveloperMode;
|
||||||
|
|
||||||
|
const _DeveloperModeDetector({
|
||||||
|
required this.child,
|
||||||
|
required this.onEnterDeveloperMode,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_DeveloperModeDetector> createState() => _DeveloperModeDetectorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DeveloperModeDetectorState extends State<_DeveloperModeDetector> {
|
||||||
|
int _counter = 0;
|
||||||
|
Timer? _timer;
|
||||||
|
|
||||||
|
void _handleTap() {
|
||||||
|
_counter++;
|
||||||
|
if (_counter >= 5) {
|
||||||
|
widget.onEnterDeveloperMode();
|
||||||
|
_resetCounter();
|
||||||
|
} else {
|
||||||
|
_timer?.cancel();
|
||||||
|
_timer = Timer(Duration(seconds: 1), _resetCounter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _resetCounter() {
|
||||||
|
_counter = 0;
|
||||||
|
_timer?.cancel();
|
||||||
|
_timer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_timer?.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: _handleTap,
|
||||||
|
child: widget.child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
|||||||
updateRequestsThrottler();
|
updateRequestsThrottler();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fireImmediately: true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,72 +148,77 @@ class _RequestsFragmentState extends ConsumerState<RequestsFragment>
|
|||||||
_handleTryClearCache(constraints.maxWidth - 40 - (value ? 60 : 0));
|
_handleTryClearCache(constraints.maxWidth - 40 - (value ? 60 : 0));
|
||||||
return child!;
|
return child!;
|
||||||
},
|
},
|
||||||
child: ValueListenableBuilder<ConnectionsState>(
|
child: TextScaleNotification(
|
||||||
valueListenable: _requestsStateNotifier,
|
child: ValueListenableBuilder<ConnectionsState>(
|
||||||
builder: (_, state, __) {
|
valueListenable: _requestsStateNotifier,
|
||||||
final connections = state.list;
|
builder: (_, state, __) {
|
||||||
if (connections.isEmpty) {
|
final connections = state.list;
|
||||||
return NullStatus(
|
if (connections.isEmpty) {
|
||||||
label: appLocalizations.nullRequestsDesc,
|
return NullStatus(
|
||||||
);
|
label: appLocalizations.nullRequestsDesc,
|
||||||
}
|
);
|
||||||
final items = connections
|
}
|
||||||
.map<Widget>(
|
final items = connections
|
||||||
(connection) => ConnectionItem(
|
.map<Widget>(
|
||||||
key: Key(connection.id),
|
(connection) => ConnectionItem(
|
||||||
connection: connection,
|
key: Key(connection.id),
|
||||||
onClickKeyword: (value) {
|
connection: connection,
|
||||||
context.commonScaffoldState?.addKeyword(value);
|
onClickKeyword: (value) {
|
||||||
},
|
context.commonScaffoldState?.addKeyword(value);
|
||||||
),
|
},
|
||||||
)
|
),
|
||||||
.separated(
|
)
|
||||||
const Divider(
|
.separated(
|
||||||
height: 0,
|
const Divider(
|
||||||
),
|
height: 0,
|
||||||
)
|
),
|
||||||
.toList();
|
)
|
||||||
return Align(
|
.toList();
|
||||||
alignment: Alignment.topCenter,
|
return Align(
|
||||||
child: ScrollToEndBox(
|
alignment: Alignment.topCenter,
|
||||||
controller: _scrollController,
|
child: ScrollToEndBox(
|
||||||
cacheKey: _cacheKey,
|
|
||||||
dataSource: connections,
|
|
||||||
child: CommonScrollBar(
|
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
child: CacheItemExtentListView(
|
cacheKey: _cacheKey,
|
||||||
key: _key,
|
dataSource: connections,
|
||||||
reverse: true,
|
child: CommonScrollBar(
|
||||||
shrinkWrap: true,
|
|
||||||
physics: NextClampingScrollPhysics(),
|
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
itemExtentBuilder: (index) {
|
child: CacheItemExtentListView(
|
||||||
final widget = items[index];
|
key: _key,
|
||||||
if (widget.runtimeType == Divider) {
|
reverse: true,
|
||||||
return 0;
|
shrinkWrap: true,
|
||||||
}
|
physics: NextClampingScrollPhysics(),
|
||||||
final measure = globalState.measure;
|
controller: _scrollController,
|
||||||
final bodyMediumHeight = measure.bodyMediumHeight;
|
itemExtentBuilder: (index) {
|
||||||
final connection = connections[(index / 2).floor()];
|
final widget = items[index];
|
||||||
final height = _calcCacheHeight(connection);
|
if (widget.runtimeType == Divider) {
|
||||||
return height + bodyMediumHeight + 32;
|
return 0;
|
||||||
},
|
}
|
||||||
itemBuilder: (_, index) {
|
final measure = globalState.measure;
|
||||||
return items[index];
|
final bodyMediumHeight = measure.bodyMediumHeight;
|
||||||
},
|
final connection = connections[(index / 2).floor()];
|
||||||
itemCount: items.length,
|
final height = _calcCacheHeight(connection);
|
||||||
keyBuilder: (int index) {
|
return height + bodyMediumHeight + 32;
|
||||||
final widget = items[index];
|
},
|
||||||
if (widget.runtimeType == Divider) {
|
itemBuilder: (_, index) {
|
||||||
return "divider";
|
return items[index];
|
||||||
}
|
},
|
||||||
final connection = connections[(index / 2).floor()];
|
itemCount: items.length,
|
||||||
return connection.id;
|
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();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ class _DashboardFragmentState extends ConsumerState<DashboardFragment>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final dashboardState = ref.watch(dashboardStateProvider);
|
final dashboardState = ref.watch(dashboardStateProvider);
|
||||||
final columns = max(4 * ((dashboardState.viewWidth / 350).ceil()), 8);
|
final columns = max(4 * ((dashboardState.viewWidth / 320).ceil()), 8);
|
||||||
return Align(
|
return Align(
|
||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
@@ -103,8 +103,8 @@ class _DashboardFragmentState extends ConsumerState<DashboardFragment>
|
|||||||
child: SuperGrid(
|
child: SuperGrid(
|
||||||
key: key,
|
key: key,
|
||||||
crossAxisCount: columns,
|
crossAxisCount: columns,
|
||||||
crossAxisSpacing: 16,
|
crossAxisSpacing: 16.ap,
|
||||||
mainAxisSpacing: 16,
|
mainAxisSpacing: 16.ap,
|
||||||
children: [
|
children: [
|
||||||
...dashboardState.dashboardWidgets
|
...dashboardState.dashboardWidgets
|
||||||
.where(
|
.where(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import 'dart:io';
|
|||||||
import 'package:fl_clash/clash/clash.dart';
|
import 'package:fl_clash/clash/clash.dart';
|
||||||
import 'package:fl_clash/common/common.dart';
|
import 'package:fl_clash/common/common.dart';
|
||||||
import 'package:fl_clash/models/common.dart';
|
import 'package:fl_clash/models/common.dart';
|
||||||
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:fl_clash/widgets/widgets.dart';
|
import 'package:fl_clash/widgets/widgets.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
@@ -57,37 +58,43 @@ class _MemoryInfoState extends State<MemoryInfo> {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
clashCore.requestGc();
|
clashCore.requestGc();
|
||||||
},
|
},
|
||||||
child: Column(
|
child: Container(
|
||||||
children: [
|
padding: baseInfoEdgeInsets.copyWith(
|
||||||
ValueListenableBuilder(
|
top: 0,
|
||||||
valueListenable: _memoryInfoStateNotifier,
|
),
|
||||||
builder: (_, trafficValue, __) {
|
child: Column(
|
||||||
return Padding(
|
mainAxisSize: MainAxisSize.max,
|
||||||
padding: baseInfoEdgeInsets.copyWith(
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
bottom: 0,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
top: 12,
|
children: [
|
||||||
),
|
SizedBox(
|
||||||
child: Row(
|
height: globalState.measure.bodyMediumHeight + 2,
|
||||||
children: [
|
child: ValueListenableBuilder(
|
||||||
Text(
|
valueListenable: _memoryInfoStateNotifier,
|
||||||
trafficValue.showValue,
|
builder: (_, trafficValue, __) {
|
||||||
style:
|
return Row(
|
||||||
context.textTheme.bodyMedium?.toLight.adjustSize(1),
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
),
|
children: [
|
||||||
SizedBox(
|
Text(
|
||||||
width: 8,
|
trafficValue.showValue,
|
||||||
),
|
style: context.textTheme.bodyMedium?.toLight
|
||||||
Text(
|
.adjustSize(1),
|
||||||
trafficValue.showUnit,
|
),
|
||||||
style:
|
SizedBox(
|
||||||
context.textTheme.bodyMedium?.toLight.adjustSize(1),
|
width: 8,
|
||||||
)
|
),
|
||||||
],
|
Text(
|
||||||
),
|
trafficValue.showUnit,
|
||||||
);
|
style: context.textTheme.bodyMedium?.toLight
|
||||||
},
|
.adjustSize(1),
|
||||||
),
|
)
|
||||||
],
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ class _NetworkDetectionState extends ConsumerState<NetworkDetection> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
size: 16,
|
size: 16.ap,
|
||||||
Icons.info_outline,
|
Icons.info_outline,
|
||||||
color: context.colorScheme.onSurfaceVariant,
|
color: context.colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -17,58 +17,145 @@ class OutboundMode extends StatelessWidget {
|
|||||||
height: height,
|
height: height,
|
||||||
child: Consumer(
|
child: Consumer(
|
||||||
builder: (_, ref, __) {
|
builder: (_, ref, __) {
|
||||||
final mode =
|
final mode = ref.watch(
|
||||||
ref.watch(patchClashConfigProvider.select((state) => state.mode));
|
patchClashConfigProvider.select(
|
||||||
return CommonCard(
|
(state) => state.mode,
|
||||||
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: _getTextColor(
|
||||||
|
context,
|
||||||
|
mode,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
groupValue: mode,
|
||||||
|
onValueChanged: (value) {
|
||||||
|
if (value == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
globalState.appController.changeMode(value);
|
||||||
|
},
|
||||||
|
thumbColor: thumbColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
86
lib/fragments/developer.dart
Normal file
86
lib/fragments/developer.dart
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
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)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,3 +11,4 @@ export 'backup_and_recovery.dart';
|
|||||||
export 'resources.dart';
|
export 'resources.dart';
|
||||||
export 'connection/requests.dart';
|
export 'connection/requests.dart';
|
||||||
export 'connection/connections.dart';
|
export 'connection/connections.dart';
|
||||||
|
export 'developer.dart';
|
||||||
|
|||||||
@@ -34,19 +34,6 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
_logsStateNotifier.value = _logsStateNotifier.value.copyWith(
|
_logsStateNotifier.value = _logsStateNotifier.value.copyWith(
|
||||||
logs: globalState.appState.logs.list,
|
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(
|
ref.listenManual(
|
||||||
isCurrentPageProvider(
|
isCurrentPageProvider(
|
||||||
PageLabel.logs,
|
PageLabel.logs,
|
||||||
@@ -60,6 +47,18 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
},
|
},
|
||||||
fireImmediately: true,
|
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
|
@override
|
||||||
@@ -123,7 +122,7 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
final height = globalState.measure
|
final height = globalState.measure
|
||||||
.computeTextSize(
|
.computeTextSize(
|
||||||
Text(
|
Text(
|
||||||
log.payload ?? "",
|
log.payload,
|
||||||
style: globalState.appController.context.textTheme.bodyLarge,
|
style: globalState.appController.context.textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
maxWidth: _currentMaxWidth,
|
maxWidth: _currentMaxWidth,
|
||||||
@@ -154,8 +153,7 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (_, constraints) {
|
builder: (_, constraints) {
|
||||||
_handleTryClearCache(constraints.maxWidth - 40);
|
_handleTryClearCache(constraints.maxWidth - 40);
|
||||||
return Align(
|
return TextScaleNotification(
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
child: ValueListenableBuilder<LogsState>(
|
child: ValueListenableBuilder<LogsState>(
|
||||||
valueListenable: _logsStateNotifier,
|
valueListenable: _logsStateNotifier,
|
||||||
builder: (_, state, __) {
|
builder: (_, state, __) {
|
||||||
@@ -168,7 +166,7 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
final items = logs
|
final items = logs
|
||||||
.map<Widget>(
|
.map<Widget>(
|
||||||
(log) => LogItem(
|
(log) => LogItem(
|
||||||
key: Key(log.dateTime.toString()),
|
key: Key(log.dateTime),
|
||||||
log: log,
|
log: log,
|
||||||
onClick: (value) {
|
onClick: (value) {
|
||||||
context.commonScaffoldState?.addKeyword(value);
|
context.commonScaffoldState?.addKeyword(value);
|
||||||
@@ -181,43 +179,49 @@ class _LogsFragmentState extends ConsumerState<LogsFragment> with PageMixin {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
return ScrollToEndBox<Log>(
|
return Align(
|
||||||
controller: _scrollController,
|
alignment: Alignment.topCenter,
|
||||||
cacheKey: _cacheKey,
|
child: ScrollToEndBox<Log>(
|
||||||
dataSource: logs,
|
|
||||||
child: CommonScrollBar(
|
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
child: CacheItemExtentListView(
|
cacheKey: _cacheKey,
|
||||||
key: _key,
|
dataSource: logs,
|
||||||
reverse: true,
|
child: CommonScrollBar(
|
||||||
shrinkWrap: true,
|
|
||||||
physics: NextClampingScrollPhysics(),
|
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
itemBuilder: (_, index) {
|
child: CacheItemExtentListView(
|
||||||
return items[index];
|
key: _key,
|
||||||
},
|
reverse: true,
|
||||||
itemExtentBuilder: (index) {
|
shrinkWrap: true,
|
||||||
final item = items[index];
|
physics: NextClampingScrollPhysics(),
|
||||||
if (item.runtimeType == Divider) {
|
controller: _scrollController,
|
||||||
return 0;
|
itemBuilder: (_, index) {
|
||||||
}
|
return items[index];
|
||||||
final log = logs[(index / 2).floor()];
|
},
|
||||||
return _getItemHeight(log);
|
itemExtentBuilder: (index) {
|
||||||
},
|
final item = items[index];
|
||||||
itemCount: items.length,
|
if (item.runtimeType == Divider) {
|
||||||
keyBuilder: (int index) {
|
return 0;
|
||||||
final item = items[index];
|
}
|
||||||
if (item.runtimeType == Divider) {
|
final log = logs[(index / 2).floor()];
|
||||||
return "divider";
|
return _getItemHeight(log);
|
||||||
}
|
},
|
||||||
final log = logs[(index / 2).floor()];
|
itemCount: items.length,
|
||||||
return log.payload ?? "";
|
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();
|
||||||
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -242,14 +246,14 @@ class LogItem extends StatelessWidget {
|
|||||||
vertical: 4,
|
vertical: 4,
|
||||||
),
|
),
|
||||||
title: SelectableText(
|
title: SelectableText(
|
||||||
log.payload ?? '',
|
log.payload,
|
||||||
style: context.textTheme.bodyLarge,
|
style: context.textTheme.bodyLarge,
|
||||||
),
|
),
|
||||||
subtitle: Column(
|
subtitle: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SelectableText(
|
SelectableText(
|
||||||
"${log.dateTime}",
|
log.dateTime,
|
||||||
style: context.textTheme.bodySmall?.copyWith(
|
style: context.textTheme.bodySmall?.copyWith(
|
||||||
color: context.colorScheme.primary,
|
color: context.colorScheme.primary,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -104,8 +104,13 @@ class _URLFormDialogState extends State<URLFormDialog> {
|
|||||||
runSpacing: 16,
|
runSpacing: 16,
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
maxLines: 5,
|
keyboardType: TextInputType.url,
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
|
maxLines: 5,
|
||||||
|
onSubmitted: (_) {
|
||||||
|
_handleAddProfileFormURL();
|
||||||
|
},
|
||||||
|
onEditingComplete: _handleAddProfileFormURL,
|
||||||
controller: urlController,
|
controller: urlController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
|
|||||||
@@ -214,6 +214,7 @@ class _EditProfileState extends State<EditProfile> {
|
|||||||
final items = [
|
final items = [
|
||||||
ListItem(
|
ListItem(
|
||||||
title: TextFormField(
|
title: TextFormField(
|
||||||
|
textInputAction: TextInputAction.next,
|
||||||
controller: labelController,
|
controller: labelController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
@@ -230,6 +231,8 @@ class _EditProfileState extends State<EditProfile> {
|
|||||||
if (widget.profile.type == ProfileType.url) ...[
|
if (widget.profile.type == ProfileType.url) ...[
|
||||||
ListItem(
|
ListItem(
|
||||||
title: TextFormField(
|
title: TextFormField(
|
||||||
|
textInputAction: TextInputAction.next,
|
||||||
|
keyboardType: TextInputType.url,
|
||||||
controller: urlController,
|
controller: urlController,
|
||||||
maxLines: 5,
|
maxLines: 5,
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
@@ -258,6 +261,7 @@ class _EditProfileState extends State<EditProfile> {
|
|||||||
if (autoUpdate)
|
if (autoUpdate)
|
||||||
ListItem(
|
ListItem(
|
||||||
title: TextFormField(
|
title: TextFormField(
|
||||||
|
textInputAction: TextInputAction.next,
|
||||||
controller: autoUpdateDurationController,
|
controller: autoUpdateDurationController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ class _OverrideProfileState extends State<OverrideProfile> {
|
|||||||
message: TextSpan(
|
message: TextSpan(
|
||||||
text: appLocalizations.saveTip,
|
text: appLocalizations.saveTip,
|
||||||
),
|
),
|
||||||
confirmText: appLocalizations.tip,
|
confirmText: appLocalizations.save,
|
||||||
);
|
);
|
||||||
if (res != true) {
|
if (res != true) {
|
||||||
return;
|
return;
|
||||||
@@ -873,6 +873,8 @@ class _AddRuleDialogState extends State<AddRuleDialog> {
|
|||||||
builder: (filed) {
|
builder: (filed) {
|
||||||
return DropdownMenu(
|
return DropdownMenu(
|
||||||
width: 200,
|
width: 200,
|
||||||
|
enableFilter: false,
|
||||||
|
enableSearch: false,
|
||||||
controller: _subRuleController,
|
controller: _subRuleController,
|
||||||
label: Text(appLocalizations.subRule),
|
label: Text(appLocalizations.subRule),
|
||||||
menuHeight: 250,
|
menuHeight: 250,
|
||||||
@@ -890,11 +892,11 @@ class _AddRuleDialogState extends State<AddRuleDialog> {
|
|||||||
builder: (filed) {
|
builder: (filed) {
|
||||||
return DropdownMenu(
|
return DropdownMenu(
|
||||||
controller: _ruleTargetController,
|
controller: _ruleTargetController,
|
||||||
initialSelection: filed.value,
|
|
||||||
label: Text(appLocalizations.ruleTarget),
|
label: Text(appLocalizations.ruleTarget),
|
||||||
width: 200,
|
width: 200,
|
||||||
menuHeight: 250,
|
menuHeight: 250,
|
||||||
enableFilter: true,
|
enableFilter: false,
|
||||||
|
enableSearch: false,
|
||||||
dropdownMenuEntries: _targetItems,
|
dropdownMenuEntries: _targetItems,
|
||||||
errorText: filed.errorText,
|
errorText: filed.errorText,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -39,7 +39,19 @@ class ThemeFragment extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SingleChildScrollView(child: ThemeColorsBox());
|
return SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_ThemeModeItem(),
|
||||||
|
_PrimaryColorItem(),
|
||||||
|
_PrueBlackItem(),
|
||||||
|
_TextScaleFactorItem(),
|
||||||
|
const SizedBox(
|
||||||
|
height: 64,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,29 +87,6 @@ class ItemCard extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ThemeColorsBox extends ConsumerStatefulWidget {
|
|
||||||
const ThemeColorsBox({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
ConsumerState<ThemeColorsBox> createState() => _ThemeColorsBoxState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ThemeColorsBoxState extends ConsumerState<ThemeColorsBox> {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
_ThemeModeItem(),
|
|
||||||
_PrimaryColorItem(),
|
|
||||||
_PrueBlackItem(),
|
|
||||||
const SizedBox(
|
|
||||||
height: 64,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _ThemeModeItem extends ConsumerWidget {
|
class _ThemeModeItem extends ConsumerWidget {
|
||||||
const _ThemeModeItem();
|
const _ThemeModeItem();
|
||||||
|
|
||||||
@@ -309,124 +298,138 @@ class _PrimaryColorItemState extends ConsumerState<_PrimaryColorItem> {
|
|||||||
final primaryColors = [null, ...vm3.b];
|
final primaryColors = [null, ...vm3.b];
|
||||||
final schemeVariant = vm3.c;
|
final schemeVariant = vm3.c;
|
||||||
|
|
||||||
return ItemCard(
|
return CommonPopScope(
|
||||||
info: Info(
|
onPop: () {
|
||||||
label: appLocalizations.themeColor,
|
if (_removablePrimaryColor != null) {
|
||||||
iconData: Icons.palette,
|
setState(() {
|
||||||
),
|
_removablePrimaryColor = null;
|
||||||
actions: genActions(
|
});
|
||||||
[
|
return false;
|
||||||
if (_removablePrimaryColor == null)
|
}
|
||||||
FilledButton(
|
return true;
|
||||||
style: ButtonStyle(
|
},
|
||||||
visualDensity: VisualDensity.compact,
|
child: ItemCard(
|
||||||
),
|
info: Info(
|
||||||
onPressed: _handleChangeSchemeVariant,
|
label: appLocalizations.themeColor,
|
||||||
child: Text(Intl.message("${schemeVariant.name}Scheme")),
|
iconData: Icons.palette,
|
||||||
),
|
|
||||||
_removablePrimaryColor != null
|
|
||||||
? FilledButton(
|
|
||||||
style: ButtonStyle(
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
_removablePrimaryColor = null;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
child: Text(appLocalizations.cancel),
|
|
||||||
)
|
|
||||||
: IconButton.filledTonal(
|
|
||||||
iconSize: 20,
|
|
||||||
padding: EdgeInsets.all(4),
|
|
||||||
visualDensity: VisualDensity.compact,
|
|
||||||
onPressed: _handleReset,
|
|
||||||
icon: Icon(Icons.replay),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
space: 8,
|
|
||||||
),
|
|
||||||
child: Container(
|
|
||||||
margin: const EdgeInsets.only(
|
|
||||||
left: 16,
|
|
||||||
right: 16,
|
|
||||||
bottom: 16,
|
|
||||||
),
|
),
|
||||||
child: LayoutBuilder(
|
actions: genActions(
|
||||||
builder: (_, constraints) {
|
[
|
||||||
final columns = _calcColumns(constraints.maxWidth);
|
if (_removablePrimaryColor == null)
|
||||||
final itemWidth =
|
FilledButton(
|
||||||
(constraints.maxWidth - (columns - 1) * 16) / columns;
|
style: ButtonStyle(
|
||||||
return Wrap(
|
visualDensity: VisualDensity.compact,
|
||||||
spacing: 16,
|
),
|
||||||
runSpacing: 16,
|
onPressed: _handleChangeSchemeVariant,
|
||||||
children: [
|
child: Text(Intl.message("${schemeVariant.name}Scheme")),
|
||||||
for (final color in primaryColors)
|
),
|
||||||
Container(
|
_removablePrimaryColor != null
|
||||||
clipBehavior: Clip.none,
|
? FilledButton(
|
||||||
width: itemWidth,
|
style: ButtonStyle(
|
||||||
height: itemWidth,
|
visualDensity: VisualDensity.compact,
|
||||||
child: Stack(
|
),
|
||||||
alignment: Alignment.center,
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_removablePrimaryColor = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Text(appLocalizations.cancel),
|
||||||
|
)
|
||||||
|
: IconButton.filledTonal(
|
||||||
|
iconSize: 20,
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
onPressed: _handleReset,
|
||||||
|
icon: Icon(Icons.replay),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
space: 8,
|
||||||
|
),
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
bottom: 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,
|
clipBehavior: Clip.none,
|
||||||
children: [
|
width: itemWidth,
|
||||||
EffectGestureDetector(
|
height: itemWidth,
|
||||||
child: ColorSchemeBox(
|
child: Stack(
|
||||||
isSelected: color == primaryColor,
|
alignment: Alignment.center,
|
||||||
primaryColor: color != null ? Color(color) : null,
|
clipBehavior: Clip.none,
|
||||||
onPressed: () {
|
children: [
|
||||||
ref
|
EffectGestureDetector(
|
||||||
.read(themeSettingProvider.notifier)
|
child: ColorSchemeBox(
|
||||||
.updateState(
|
isSelected: color == primaryColor,
|
||||||
(state) => state.copyWith(
|
primaryColor: color != null ? Color(color) : null,
|
||||||
primaryColor: color,
|
onPressed: () {
|
||||||
),
|
setState(() {
|
||||||
);
|
_removablePrimaryColor = null;
|
||||||
|
});
|
||||||
|
ref
|
||||||
|
.read(themeSettingProvider.notifier)
|
||||||
|
.updateState(
|
||||||
|
(state) => state.copyWith(
|
||||||
|
primaryColor: color,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
onLongPress: () {
|
||||||
|
setState(() {
|
||||||
|
_removablePrimaryColor = color;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
onLongPress: () {
|
if (_removablePrimaryColor != null &&
|
||||||
setState(() {
|
_removablePrimaryColor == color)
|
||||||
_removablePrimaryColor = color;
|
Container(
|
||||||
});
|
color: Colors.white.opacity0,
|
||||||
},
|
padding: EdgeInsets.all(8),
|
||||||
),
|
child: IconButton.filledTonal(
|
||||||
if (_removablePrimaryColor != null &&
|
onPressed: _handleDel,
|
||||||
_removablePrimaryColor == color)
|
padding: EdgeInsets.all(12),
|
||||||
Container(
|
iconSize: 30,
|
||||||
color: Colors.white.opacity0,
|
icon: Icon(
|
||||||
padding: EdgeInsets.all(8),
|
color: context.colorScheme.primary,
|
||||||
child: IconButton.filledTonal(
|
Icons.delete,
|
||||||
onPressed: _handleDel,
|
),
|
||||||
padding: EdgeInsets.all(12),
|
|
||||||
iconSize: 30,
|
|
||||||
icon: Icon(
|
|
||||||
color: context.colorScheme.primary,
|
|
||||||
Icons.delete,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
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,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -468,6 +471,77 @@ class _PrueBlackItem extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _TextScaleFactorItem extends ConsumerWidget {
|
||||||
|
const _TextScaleFactorItem();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final textScale = ref.watch(
|
||||||
|
themeSettingProvider.select(
|
||||||
|
(state) => state.textScale,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final String process =
|
||||||
|
"${((textScale.scale * 100) as double).round()}%";
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DisabledMask(
|
||||||
|
status: !textScale.enable,
|
||||||
|
child: ActivateBox(
|
||||||
|
active: textScale.enable,
|
||||||
|
child: SliderTheme(
|
||||||
|
data: _SliderDefaultsM3(context),
|
||||||
|
child: Slider(
|
||||||
|
min: 0.8,
|
||||||
|
divisions: 8,
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
|
max: 1.2,
|
||||||
|
label: process,
|
||||||
|
value: textScale.scale,
|
||||||
|
onChanged: (value) {
|
||||||
|
ref.read(themeSettingProvider.notifier).updateState(
|
||||||
|
(state) => state.copyWith.textScale(
|
||||||
|
scale: value,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _PaletteDialog extends StatefulWidget {
|
class _PaletteDialog extends StatefulWidget {
|
||||||
const _PaletteDialog();
|
const _PaletteDialog();
|
||||||
|
|
||||||
@@ -530,3 +604,112 @@ class _PaletteDialogState extends State<_PaletteDialog> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _SliderDefaultsM3 extends SliderThemeData {
|
||||||
|
_SliderDefaultsM3(this.context) : super(trackHeight: 16.0);
|
||||||
|
|
||||||
|
final BuildContext context;
|
||||||
|
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get activeTrackColor => _colors.primary;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get inactiveTrackColor => _colors.secondaryContainer;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get secondaryActiveTrackColor => _colors.primary.withOpacity(0.54);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledActiveTrackColor => _colors.onSurface.withOpacity(0.38);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledInactiveTrackColor => _colors.onSurface.withOpacity(0.12);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledSecondaryActiveTrackColor =>
|
||||||
|
_colors.onSurface.withOpacity(0.38);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get activeTickMarkColor => _colors.onPrimary.withOpacity(1.0);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get inactiveTickMarkColor =>
|
||||||
|
_colors.onSecondaryContainer.withOpacity(1.0);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledActiveTickMarkColor => _colors.onInverseSurface;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledInactiveTickMarkColor => _colors.onSurface;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get thumbColor => _colors.primary;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get disabledThumbColor => _colors.onSurface.withOpacity(0.38);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get overlayColor =>
|
||||||
|
WidgetStateColor.resolveWith((Set<WidgetState> states) {
|
||||||
|
if (states.contains(WidgetState.dragged)) {
|
||||||
|
return _colors.primary.withOpacity(0.1);
|
||||||
|
}
|
||||||
|
if (states.contains(WidgetState.hovered)) {
|
||||||
|
return _colors.primary.withOpacity(0.08);
|
||||||
|
}
|
||||||
|
if (states.contains(WidgetState.focused)) {
|
||||||
|
return _colors.primary.withOpacity(0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Colors.transparent;
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
TextStyle? get valueIndicatorTextStyle =>
|
||||||
|
Theme.of(context).textTheme.labelLarge!.copyWith(
|
||||||
|
color: _colors.onInverseSurface,
|
||||||
|
);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get valueIndicatorColor => _colors.inverseSurface;
|
||||||
|
|
||||||
|
@override
|
||||||
|
SliderComponentShape? get valueIndicatorShape =>
|
||||||
|
const RoundedRectSliderValueIndicatorShape();
|
||||||
|
|
||||||
|
@override
|
||||||
|
SliderComponentShape? get thumbShape => const HandleThumbShape();
|
||||||
|
|
||||||
|
@override
|
||||||
|
SliderTrackShape? get trackShape => const GappedSliderTrackShape();
|
||||||
|
|
||||||
|
@override
|
||||||
|
SliderComponentShape? get overlayShape => const RoundSliderOverlayShape();
|
||||||
|
|
||||||
|
@override
|
||||||
|
SliderTickMarkShape? get tickMarkShape =>
|
||||||
|
const RoundSliderTickMarkShape(tickMarkRadius: 4.0 / 2);
|
||||||
|
|
||||||
|
@override
|
||||||
|
WidgetStateProperty<Size?>? get thumbSize {
|
||||||
|
return WidgetStateProperty.resolveWith((Set<WidgetState> states) {
|
||||||
|
if (states.contains(WidgetState.disabled)) {
|
||||||
|
return const Size(4.0, 44.0);
|
||||||
|
}
|
||||||
|
if (states.contains(WidgetState.hovered)) {
|
||||||
|
return const Size(4.0, 44.0);
|
||||||
|
}
|
||||||
|
if (states.contains(WidgetState.focused)) {
|
||||||
|
return const Size(2.0, 44.0);
|
||||||
|
}
|
||||||
|
if (states.contains(WidgetState.pressed)) {
|
||||||
|
return const Size(2.0, 44.0);
|
||||||
|
}
|
||||||
|
return const Size(4.0, 44.0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
double? get trackGap => 6.0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'backup_and_recovery.dart';
|
import 'backup_and_recovery.dart';
|
||||||
|
import 'developer.dart';
|
||||||
import 'theme.dart';
|
import 'theme.dart';
|
||||||
import 'package:path/path.dart' show dirname, join;
|
import 'package:path/path.dart' show dirname, join;
|
||||||
|
|
||||||
@@ -54,11 +55,12 @@ class _ToolboxFragmentState extends ConsumerState<ToolsFragment> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _getOtherList() {
|
List<Widget> _getOtherList(bool enableDeveloperMode) {
|
||||||
return generateSection(
|
return generateSection(
|
||||||
title: appLocalizations.other,
|
title: appLocalizations.other,
|
||||||
items: [
|
items: [
|
||||||
_DisclaimerItem(),
|
_DisclaimerItem(),
|
||||||
|
if (enableDeveloperMode) _DeveloperItem(),
|
||||||
_InfoItem(),
|
_InfoItem(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -82,7 +84,11 @@ class _ToolboxFragmentState extends ConsumerState<ToolsFragment> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
ref.watch(appSettingProvider.select((state) => state.locale));
|
final vm2 = ref.watch(
|
||||||
|
appSettingProvider.select(
|
||||||
|
(state) => VM2(a: state.locale, b: state.developerMode),
|
||||||
|
),
|
||||||
|
);
|
||||||
final items = [
|
final items = [
|
||||||
Consumer(
|
Consumer(
|
||||||
builder: (_, ref, __) {
|
builder: (_, ref, __) {
|
||||||
@@ -99,7 +105,7 @@ class _ToolboxFragmentState extends ConsumerState<ToolsFragment> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
..._getSettingList(),
|
..._getSettingList(),
|
||||||
..._getOtherList(),
|
..._getOtherList(vm2.b),
|
||||||
];
|
];
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
itemCount: items.length,
|
itemCount: items.length,
|
||||||
@@ -297,3 +303,19 @@ class _InfoItem extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _DeveloperItem extends StatelessWidget {
|
||||||
|
const _DeveloperItem();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListItem.open(
|
||||||
|
leading: const Icon(Icons.developer_mode),
|
||||||
|
title: Text(appLocalizations.developerMode),
|
||||||
|
delegate: OpenDelegate(
|
||||||
|
title: appLocalizations.developerMode,
|
||||||
|
widget: const DeveloperView(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"The current application is already the latest version",
|
"The current application is already the latest version",
|
||||||
),
|
),
|
||||||
"checking": MessageLookupByLibrary.simpleMessage("Checking..."),
|
"checking": MessageLookupByLibrary.simpleMessage("Checking..."),
|
||||||
|
"clearData": MessageLookupByLibrary.simpleMessage("Clear Data"),
|
||||||
"clipboardExport": MessageLookupByLibrary.simpleMessage("Export clipboard"),
|
"clipboardExport": MessageLookupByLibrary.simpleMessage("Export clipboard"),
|
||||||
"clipboardImport": MessageLookupByLibrary.simpleMessage("Clipboard import"),
|
"clipboardImport": MessageLookupByLibrary.simpleMessage("Clipboard import"),
|
||||||
"colorExists": MessageLookupByLibrary.simpleMessage(
|
"colorExists": MessageLookupByLibrary.simpleMessage(
|
||||||
@@ -177,6 +178,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"core": MessageLookupByLibrary.simpleMessage("Core"),
|
"core": MessageLookupByLibrary.simpleMessage("Core"),
|
||||||
"coreInfo": MessageLookupByLibrary.simpleMessage("Core info"),
|
"coreInfo": MessageLookupByLibrary.simpleMessage("Core info"),
|
||||||
"country": MessageLookupByLibrary.simpleMessage("Country"),
|
"country": MessageLookupByLibrary.simpleMessage("Country"),
|
||||||
|
"crashTest": MessageLookupByLibrary.simpleMessage("Crash test"),
|
||||||
"create": MessageLookupByLibrary.simpleMessage("Create"),
|
"create": MessageLookupByLibrary.simpleMessage("Create"),
|
||||||
"cut": MessageLookupByLibrary.simpleMessage("Cut"),
|
"cut": MessageLookupByLibrary.simpleMessage("Cut"),
|
||||||
"dark": MessageLookupByLibrary.simpleMessage("Dark"),
|
"dark": MessageLookupByLibrary.simpleMessage("Dark"),
|
||||||
@@ -208,6 +210,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"detectionTip": MessageLookupByLibrary.simpleMessage(
|
"detectionTip": MessageLookupByLibrary.simpleMessage(
|
||||||
"Relying on third-party api is for reference only",
|
"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"),
|
"direct": MessageLookupByLibrary.simpleMessage("Direct"),
|
||||||
"disclaimer": MessageLookupByLibrary.simpleMessage("Disclaimer"),
|
"disclaimer": MessageLookupByLibrary.simpleMessage("Disclaimer"),
|
||||||
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
@@ -362,6 +368,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"loose": MessageLookupByLibrary.simpleMessage("Loose"),
|
"loose": MessageLookupByLibrary.simpleMessage("Loose"),
|
||||||
"memoryInfo": MessageLookupByLibrary.simpleMessage("Memory info"),
|
"memoryInfo": MessageLookupByLibrary.simpleMessage("Memory info"),
|
||||||
|
"messageTest": MessageLookupByLibrary.simpleMessage("Message test"),
|
||||||
|
"messageTestTip": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"This is a message.",
|
||||||
|
),
|
||||||
"min": MessageLookupByLibrary.simpleMessage("Min"),
|
"min": MessageLookupByLibrary.simpleMessage("Min"),
|
||||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("Minimize on exit"),
|
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("Minimize on exit"),
|
||||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
@@ -627,6 +637,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"Enabling it will allow TCP concurrency",
|
"Enabling it will allow TCP concurrency",
|
||||||
),
|
),
|
||||||
"testUrl": MessageLookupByLibrary.simpleMessage("Test url"),
|
"testUrl": MessageLookupByLibrary.simpleMessage("Test url"),
|
||||||
|
"textScale": MessageLookupByLibrary.simpleMessage("Text Scaling"),
|
||||||
"theme": MessageLookupByLibrary.simpleMessage("Theme"),
|
"theme": MessageLookupByLibrary.simpleMessage("Theme"),
|
||||||
"themeColor": MessageLookupByLibrary.simpleMessage("Theme color"),
|
"themeColor": MessageLookupByLibrary.simpleMessage("Theme color"),
|
||||||
"themeDesc": MessageLookupByLibrary.simpleMessage(
|
"themeDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"checkUpdate": MessageLookupByLibrary.simpleMessage("更新を確認"),
|
"checkUpdate": MessageLookupByLibrary.simpleMessage("更新を確認"),
|
||||||
"checkUpdateError": MessageLookupByLibrary.simpleMessage("アプリは最新版です"),
|
"checkUpdateError": MessageLookupByLibrary.simpleMessage("アプリは最新版です"),
|
||||||
"checking": MessageLookupByLibrary.simpleMessage("確認中..."),
|
"checking": MessageLookupByLibrary.simpleMessage("確認中..."),
|
||||||
|
"clearData": MessageLookupByLibrary.simpleMessage("データを消去"),
|
||||||
"clipboardExport": MessageLookupByLibrary.simpleMessage("クリップボードにエクスポート"),
|
"clipboardExport": MessageLookupByLibrary.simpleMessage("クリップボードにエクスポート"),
|
||||||
"clipboardImport": MessageLookupByLibrary.simpleMessage("クリップボードからインポート"),
|
"clipboardImport": MessageLookupByLibrary.simpleMessage("クリップボードからインポート"),
|
||||||
"colorExists": MessageLookupByLibrary.simpleMessage("この色は既に存在します"),
|
"colorExists": MessageLookupByLibrary.simpleMessage("この色は既に存在します"),
|
||||||
@@ -127,6 +128,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"core": MessageLookupByLibrary.simpleMessage("コア"),
|
"core": MessageLookupByLibrary.simpleMessage("コア"),
|
||||||
"coreInfo": MessageLookupByLibrary.simpleMessage("コア情報"),
|
"coreInfo": MessageLookupByLibrary.simpleMessage("コア情報"),
|
||||||
"country": MessageLookupByLibrary.simpleMessage("国"),
|
"country": MessageLookupByLibrary.simpleMessage("国"),
|
||||||
|
"crashTest": MessageLookupByLibrary.simpleMessage("クラッシュテスト"),
|
||||||
"create": MessageLookupByLibrary.simpleMessage("作成"),
|
"create": MessageLookupByLibrary.simpleMessage("作成"),
|
||||||
"cut": MessageLookupByLibrary.simpleMessage("切り取り"),
|
"cut": MessageLookupByLibrary.simpleMessage("切り取り"),
|
||||||
"dark": MessageLookupByLibrary.simpleMessage("ダーク"),
|
"dark": MessageLookupByLibrary.simpleMessage("ダーク"),
|
||||||
@@ -150,6 +152,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"ClashMetaベースのマルチプラットフォームプロキシクライアント。シンプルで使いやすく、オープンソースで広告なし。",
|
"ClashMetaベースのマルチプラットフォームプロキシクライアント。シンプルで使いやすく、オープンソースで広告なし。",
|
||||||
),
|
),
|
||||||
"detectionTip": MessageLookupByLibrary.simpleMessage("サードパーティAPIに依存(参考値)"),
|
"detectionTip": MessageLookupByLibrary.simpleMessage("サードパーティAPIに依存(参考値)"),
|
||||||
|
"developerMode": MessageLookupByLibrary.simpleMessage("デベロッパーモード"),
|
||||||
|
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"デベロッパーモードが有効になりました。",
|
||||||
|
),
|
||||||
"direct": MessageLookupByLibrary.simpleMessage("ダイレクト"),
|
"direct": MessageLookupByLibrary.simpleMessage("ダイレクト"),
|
||||||
"disclaimer": MessageLookupByLibrary.simpleMessage("免責事項"),
|
"disclaimer": MessageLookupByLibrary.simpleMessage("免責事項"),
|
||||||
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
@@ -258,6 +264,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"loopbackDesc": MessageLookupByLibrary.simpleMessage("UWPループバック解除用"),
|
"loopbackDesc": MessageLookupByLibrary.simpleMessage("UWPループバック解除用"),
|
||||||
"loose": MessageLookupByLibrary.simpleMessage("疎"),
|
"loose": MessageLookupByLibrary.simpleMessage("疎"),
|
||||||
"memoryInfo": MessageLookupByLibrary.simpleMessage("メモリ情報"),
|
"memoryInfo": MessageLookupByLibrary.simpleMessage("メモリ情報"),
|
||||||
|
"messageTest": MessageLookupByLibrary.simpleMessage("メッセージテスト"),
|
||||||
|
"messageTestTip": MessageLookupByLibrary.simpleMessage("これはメッセージです。"),
|
||||||
"min": MessageLookupByLibrary.simpleMessage("最小化"),
|
"min": MessageLookupByLibrary.simpleMessage("最小化"),
|
||||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("終了時に最小化"),
|
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("終了時に最小化"),
|
||||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
@@ -463,6 +471,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP並列処理"),
|
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP並列処理"),
|
||||||
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("TCP並列処理を許可"),
|
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("TCP並列処理を許可"),
|
||||||
"testUrl": MessageLookupByLibrary.simpleMessage("URLテスト"),
|
"testUrl": MessageLookupByLibrary.simpleMessage("URLテスト"),
|
||||||
|
"textScale": MessageLookupByLibrary.simpleMessage("テキストスケーリング"),
|
||||||
"theme": MessageLookupByLibrary.simpleMessage("テーマ"),
|
"theme": MessageLookupByLibrary.simpleMessage("テーマ"),
|
||||||
"themeColor": MessageLookupByLibrary.simpleMessage("テーマカラー"),
|
"themeColor": MessageLookupByLibrary.simpleMessage("テーマカラー"),
|
||||||
"themeDesc": MessageLookupByLibrary.simpleMessage("ダークモードの設定、色の調整"),
|
"themeDesc": MessageLookupByLibrary.simpleMessage("ダークモードの設定、色の調整"),
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"Текущее приложение уже является последней версией",
|
"Текущее приложение уже является последней версией",
|
||||||
),
|
),
|
||||||
"checking": MessageLookupByLibrary.simpleMessage("Проверка..."),
|
"checking": MessageLookupByLibrary.simpleMessage("Проверка..."),
|
||||||
|
"clearData": MessageLookupByLibrary.simpleMessage("Очистить данные"),
|
||||||
"clipboardExport": MessageLookupByLibrary.simpleMessage(
|
"clipboardExport": MessageLookupByLibrary.simpleMessage(
|
||||||
"Экспорт в буфер обмена",
|
"Экспорт в буфер обмена",
|
||||||
),
|
),
|
||||||
@@ -183,6 +184,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"core": MessageLookupByLibrary.simpleMessage("Ядро"),
|
"core": MessageLookupByLibrary.simpleMessage("Ядро"),
|
||||||
"coreInfo": MessageLookupByLibrary.simpleMessage("Информация о ядре"),
|
"coreInfo": MessageLookupByLibrary.simpleMessage("Информация о ядре"),
|
||||||
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
"country": MessageLookupByLibrary.simpleMessage("Страна"),
|
||||||
|
"crashTest": MessageLookupByLibrary.simpleMessage("Тест на сбои"),
|
||||||
"create": MessageLookupByLibrary.simpleMessage("Создать"),
|
"create": MessageLookupByLibrary.simpleMessage("Создать"),
|
||||||
"cut": MessageLookupByLibrary.simpleMessage("Вырезать"),
|
"cut": MessageLookupByLibrary.simpleMessage("Вырезать"),
|
||||||
"dark": MessageLookupByLibrary.simpleMessage("Темный"),
|
"dark": MessageLookupByLibrary.simpleMessage("Темный"),
|
||||||
@@ -216,6 +218,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"detectionTip": MessageLookupByLibrary.simpleMessage(
|
"detectionTip": MessageLookupByLibrary.simpleMessage(
|
||||||
"Опирается на сторонний API, только для справки",
|
"Опирается на сторонний API, только для справки",
|
||||||
),
|
),
|
||||||
|
"developerMode": MessageLookupByLibrary.simpleMessage("Режим разработчика"),
|
||||||
|
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Режим разработчика активирован.",
|
||||||
|
),
|
||||||
"direct": MessageLookupByLibrary.simpleMessage("Прямой"),
|
"direct": MessageLookupByLibrary.simpleMessage("Прямой"),
|
||||||
"disclaimer": MessageLookupByLibrary.simpleMessage(
|
"disclaimer": MessageLookupByLibrary.simpleMessage(
|
||||||
"Отказ от ответственности",
|
"Отказ от ответственности",
|
||||||
@@ -386,6 +392,10 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"loose": MessageLookupByLibrary.simpleMessage("Свободный"),
|
"loose": MessageLookupByLibrary.simpleMessage("Свободный"),
|
||||||
"memoryInfo": MessageLookupByLibrary.simpleMessage("Информация о памяти"),
|
"memoryInfo": MessageLookupByLibrary.simpleMessage("Информация о памяти"),
|
||||||
|
"messageTest": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Тестирование сообщения",
|
||||||
|
),
|
||||||
|
"messageTestTip": MessageLookupByLibrary.simpleMessage("Это сообщение."),
|
||||||
"min": MessageLookupByLibrary.simpleMessage("Мин"),
|
"min": MessageLookupByLibrary.simpleMessage("Мин"),
|
||||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage(
|
"minimizeOnExit": MessageLookupByLibrary.simpleMessage(
|
||||||
"Свернуть при выходе",
|
"Свернуть при выходе",
|
||||||
@@ -665,6 +675,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"Включение позволит использовать параллелизм TCP",
|
"Включение позволит использовать параллелизм TCP",
|
||||||
),
|
),
|
||||||
"testUrl": MessageLookupByLibrary.simpleMessage("Тест URL"),
|
"testUrl": MessageLookupByLibrary.simpleMessage("Тест URL"),
|
||||||
|
"textScale": MessageLookupByLibrary.simpleMessage("Масштабирование текста"),
|
||||||
"theme": MessageLookupByLibrary.simpleMessage("Тема"),
|
"theme": MessageLookupByLibrary.simpleMessage("Тема"),
|
||||||
"themeColor": MessageLookupByLibrary.simpleMessage("Цвет темы"),
|
"themeColor": MessageLookupByLibrary.simpleMessage("Цвет темы"),
|
||||||
"themeDesc": MessageLookupByLibrary.simpleMessage(
|
"themeDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"checkUpdate": MessageLookupByLibrary.simpleMessage("检查更新"),
|
"checkUpdate": MessageLookupByLibrary.simpleMessage("检查更新"),
|
||||||
"checkUpdateError": MessageLookupByLibrary.simpleMessage("当前应用已经是最新版了"),
|
"checkUpdateError": MessageLookupByLibrary.simpleMessage("当前应用已经是最新版了"),
|
||||||
"checking": MessageLookupByLibrary.simpleMessage("检测中..."),
|
"checking": MessageLookupByLibrary.simpleMessage("检测中..."),
|
||||||
|
"clearData": MessageLookupByLibrary.simpleMessage("清除数据"),
|
||||||
"clipboardExport": MessageLookupByLibrary.simpleMessage("导出剪贴板"),
|
"clipboardExport": MessageLookupByLibrary.simpleMessage("导出剪贴板"),
|
||||||
"clipboardImport": MessageLookupByLibrary.simpleMessage("剪贴板导入"),
|
"clipboardImport": MessageLookupByLibrary.simpleMessage("剪贴板导入"),
|
||||||
"colorExists": MessageLookupByLibrary.simpleMessage("该颜色已存在"),
|
"colorExists": MessageLookupByLibrary.simpleMessage("该颜色已存在"),
|
||||||
@@ -117,6 +118,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"core": MessageLookupByLibrary.simpleMessage("内核"),
|
"core": MessageLookupByLibrary.simpleMessage("内核"),
|
||||||
"coreInfo": MessageLookupByLibrary.simpleMessage("内核信息"),
|
"coreInfo": MessageLookupByLibrary.simpleMessage("内核信息"),
|
||||||
"country": MessageLookupByLibrary.simpleMessage("区域"),
|
"country": MessageLookupByLibrary.simpleMessage("区域"),
|
||||||
|
"crashTest": MessageLookupByLibrary.simpleMessage("崩溃测试"),
|
||||||
"create": MessageLookupByLibrary.simpleMessage("创建"),
|
"create": MessageLookupByLibrary.simpleMessage("创建"),
|
||||||
"cut": MessageLookupByLibrary.simpleMessage("剪切"),
|
"cut": MessageLookupByLibrary.simpleMessage("剪切"),
|
||||||
"dark": MessageLookupByLibrary.simpleMessage("深色"),
|
"dark": MessageLookupByLibrary.simpleMessage("深色"),
|
||||||
@@ -136,6 +138,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"基于ClashMeta的多平台代理客户端,简单易用,开源无广告。",
|
"基于ClashMeta的多平台代理客户端,简单易用,开源无广告。",
|
||||||
),
|
),
|
||||||
"detectionTip": MessageLookupByLibrary.simpleMessage("依赖第三方api,仅供参考"),
|
"detectionTip": MessageLookupByLibrary.simpleMessage("依赖第三方api,仅供参考"),
|
||||||
|
"developerMode": MessageLookupByLibrary.simpleMessage("开发者模式"),
|
||||||
|
"developerModeEnableTip": MessageLookupByLibrary.simpleMessage("开发者模式已启用。"),
|
||||||
"direct": MessageLookupByLibrary.simpleMessage("直连"),
|
"direct": MessageLookupByLibrary.simpleMessage("直连"),
|
||||||
"disclaimer": MessageLookupByLibrary.simpleMessage("免责声明"),
|
"disclaimer": MessageLookupByLibrary.simpleMessage("免责声明"),
|
||||||
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
"disclaimerDesc": MessageLookupByLibrary.simpleMessage(
|
||||||
@@ -232,6 +236,8 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"loopbackDesc": MessageLookupByLibrary.simpleMessage("用于UWP回环解锁"),
|
"loopbackDesc": MessageLookupByLibrary.simpleMessage("用于UWP回环解锁"),
|
||||||
"loose": MessageLookupByLibrary.simpleMessage("宽松"),
|
"loose": MessageLookupByLibrary.simpleMessage("宽松"),
|
||||||
"memoryInfo": MessageLookupByLibrary.simpleMessage("内存信息"),
|
"memoryInfo": MessageLookupByLibrary.simpleMessage("内存信息"),
|
||||||
|
"messageTest": MessageLookupByLibrary.simpleMessage("消息测试"),
|
||||||
|
"messageTestTip": MessageLookupByLibrary.simpleMessage("这是一条消息。"),
|
||||||
"min": MessageLookupByLibrary.simpleMessage("最小"),
|
"min": MessageLookupByLibrary.simpleMessage("最小"),
|
||||||
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("退出时最小化"),
|
"minimizeOnExit": MessageLookupByLibrary.simpleMessage("退出时最小化"),
|
||||||
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage("修改系统默认退出事件"),
|
"minimizeOnExitDesc": MessageLookupByLibrary.simpleMessage("修改系统默认退出事件"),
|
||||||
@@ -407,6 +413,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP并发"),
|
"tcpConcurrent": MessageLookupByLibrary.simpleMessage("TCP并发"),
|
||||||
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("开启后允许TCP并发"),
|
"tcpConcurrentDesc": MessageLookupByLibrary.simpleMessage("开启后允许TCP并发"),
|
||||||
"testUrl": MessageLookupByLibrary.simpleMessage("测速链接"),
|
"testUrl": MessageLookupByLibrary.simpleMessage("测速链接"),
|
||||||
|
"textScale": MessageLookupByLibrary.simpleMessage("文本缩放"),
|
||||||
"theme": MessageLookupByLibrary.simpleMessage("主题"),
|
"theme": MessageLookupByLibrary.simpleMessage("主题"),
|
||||||
"themeColor": MessageLookupByLibrary.simpleMessage("主题色彩"),
|
"themeColor": MessageLookupByLibrary.simpleMessage("主题色彩"),
|
||||||
"themeDesc": MessageLookupByLibrary.simpleMessage("设置深色模式,调整色彩"),
|
"themeDesc": MessageLookupByLibrary.simpleMessage("设置深色模式,调整色彩"),
|
||||||
|
|||||||
@@ -3004,6 +3004,61 @@ class AppLocalizations {
|
|||||||
args: [],
|
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: []);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
class AppLocalizationDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class _ClashContainerState extends ConsumerState<ClashManager>
|
|||||||
void onLog(Log log) {
|
void onLog(Log log) {
|
||||||
ref.watch(logsProvider.notifier).addLog(log);
|
ref.watch(logsProvider.notifier).addLog(log);
|
||||||
if (log.logLevel == LogLevel.error) {
|
if (log.logLevel == LogLevel.error) {
|
||||||
globalState.showNotifier(log.payload ?? '');
|
globalState.showNotifier(log.payload);
|
||||||
}
|
}
|
||||||
super.onLog(log);
|
super.onLog(log);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class MessageManager extends StatefulWidget {
|
|||||||
class MessageManagerState extends State<MessageManager> {
|
class MessageManagerState extends State<MessageManager> {
|
||||||
final _messagesNotifier = ValueNotifier<List<CommonMessage>>([]);
|
final _messagesNotifier = ValueNotifier<List<CommonMessage>>([]);
|
||||||
final List<CommonMessage> _bufferMessages = [];
|
final List<CommonMessage> _bufferMessages = [];
|
||||||
Completer<bool>? _messageIngCompleter;
|
bool _pushing = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -40,26 +40,27 @@ class MessageManagerState extends State<MessageManager> {
|
|||||||
text: text,
|
text: text,
|
||||||
);
|
);
|
||||||
_bufferMessages.add(commonMessage);
|
_bufferMessages.add(commonMessage);
|
||||||
_showMessage();
|
await _showMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
_showMessage() async {
|
_showMessage() async {
|
||||||
if (_messageIngCompleter?.isCompleted == false) {
|
if (_pushing == true) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_pushing = true;
|
||||||
while (_bufferMessages.isNotEmpty) {
|
while (_bufferMessages.isNotEmpty) {
|
||||||
final commonMessage = _bufferMessages.removeAt(0);
|
final commonMessage = _bufferMessages.removeAt(0);
|
||||||
_messagesNotifier.value = List.from(_messagesNotifier.value)
|
_messagesNotifier.value = List.from(_messagesNotifier.value)
|
||||||
..add(
|
..add(
|
||||||
commonMessage,
|
commonMessage,
|
||||||
);
|
);
|
||||||
|
|
||||||
_messageIngCompleter = Completer();
|
|
||||||
await Future.delayed(Duration(seconds: 1));
|
await Future.delayed(Duration(seconds: 1));
|
||||||
Future.delayed(commonMessage.duration, () {
|
Future.delayed(commonMessage.duration, () {
|
||||||
_handleRemove(commonMessage);
|
_handleRemove(commonMessage);
|
||||||
});
|
});
|
||||||
_messageIngCompleter?.complete(true);
|
if (_bufferMessages.isEmpty) {
|
||||||
|
_pushing = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,41 +78,41 @@ class MessageManagerState extends State<MessageManager> {
|
|||||||
valueListenable: _messagesNotifier,
|
valueListenable: _messagesNotifier,
|
||||||
builder: (_, messages, __) {
|
builder: (_, messages, __) {
|
||||||
return FadeThroughBox(
|
return FadeThroughBox(
|
||||||
|
margin: EdgeInsets.only(
|
||||||
|
top: kToolbarHeight + 8,
|
||||||
|
left: 12,
|
||||||
|
right: 12,
|
||||||
|
),
|
||||||
alignment: Alignment.topRight,
|
alignment: Alignment.topRight,
|
||||||
child: messages.isEmpty
|
child: messages.isEmpty
|
||||||
? SizedBox()
|
? SizedBox()
|
||||||
: LayoutBuilder(
|
: LayoutBuilder(
|
||||||
key: Key(messages.last.id),
|
key: Key(messages.last.id),
|
||||||
builder: (_, constraints) {
|
builder: (_, constraints) {
|
||||||
return Card(
|
return Card(
|
||||||
shape: const RoundedRectangleBorder(
|
shape: const RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.all(
|
borderRadius: BorderRadius.all(
|
||||||
Radius.circular(12.0),
|
Radius.circular(12.0),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
elevation: 10,
|
|
||||||
margin: EdgeInsets.only(
|
|
||||||
top: kToolbarHeight + 8,
|
|
||||||
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,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
|
import 'dart:math';
|
||||||
import 'package:fl_clash/common/constant.dart';
|
import 'package:fl_clash/common/constant.dart';
|
||||||
import 'package:fl_clash/common/measure.dart';
|
import 'package:fl_clash/common/measure.dart';
|
||||||
import 'package:fl_clash/common/theme.dart';
|
import 'package:fl_clash/common/theme.dart';
|
||||||
|
import 'package:fl_clash/providers/config.dart';
|
||||||
import 'package:fl_clash/state.dart';
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
class ThemeManager extends StatelessWidget {
|
class ThemeManager extends ConsumerWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
const ThemeManager({
|
const ThemeManager({
|
||||||
@@ -13,14 +16,30 @@ class ThemeManager extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context, ref) {
|
||||||
globalState.measure = Measure.of(context);
|
final textScale = ref.read(
|
||||||
globalState.theme = CommonTheme.of(context);
|
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;
|
||||||
return MediaQuery(
|
return MediaQuery(
|
||||||
data: MediaQuery.of(context).copyWith(
|
data: MediaQuery.of(context).copyWith(
|
||||||
textScaler: TextScaler.linear(
|
textScaler: TextScaler.linear(
|
||||||
textScaleFactor,
|
textScaleFactor,
|
||||||
),
|
),
|
||||||
|
padding: padding.copyWith(
|
||||||
|
top: padding.top > height * 0.3 ? 0.0 : padding.top,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: LayoutBuilder(
|
child: LayoutBuilder(
|
||||||
builder: (_, container) {
|
builder: (_, container) {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ class AppState with _$AppState {
|
|||||||
@Default(false) bool isInit,
|
@Default(false) bool isInit,
|
||||||
@Default(PageLabel.dashboard) PageLabel pageLabel,
|
@Default(PageLabel.dashboard) PageLabel pageLabel,
|
||||||
@Default([]) List<Package> packages,
|
@Default([]) List<Package> packages,
|
||||||
@Default(ColorSchemes()) ColorSchemes colorSchemes,
|
|
||||||
@Default(0) int sortNum,
|
@Default(0) int sortNum,
|
||||||
required Size viewSize,
|
required Size viewSize,
|
||||||
@Default({}) DelayMap delayMap,
|
@Default({}) DelayMap delayMap,
|
||||||
|
|||||||
@@ -84,33 +84,33 @@ extension ConnectionExt on Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonSerializable()
|
String _logDateTime(_) {
|
||||||
class Log {
|
return DateTime.now().toString();
|
||||||
@JsonKey(name: "LogLevel")
|
}
|
||||||
LogLevel logLevel;
|
|
||||||
@JsonKey(name: "Payload")
|
|
||||||
String? payload;
|
|
||||||
DateTime _dateTime;
|
|
||||||
|
|
||||||
Log({
|
// String _logId(_) {
|
||||||
required this.logLevel,
|
// return utils.id;
|
||||||
this.payload,
|
// }
|
||||||
}) : _dateTime = DateTime.now();
|
|
||||||
|
|
||||||
DateTime get dateTime => _dateTime;
|
@freezed
|
||||||
|
class Log with _$Log {
|
||||||
|
const factory Log({
|
||||||
|
@JsonKey(name: "LogLevel") @Default(LogLevel.app) LogLevel logLevel,
|
||||||
|
@JsonKey(name: "Payload") @Default("") String payload,
|
||||||
|
@JsonKey(fromJson: _logDateTime) required String dateTime,
|
||||||
|
}) = _Log;
|
||||||
|
|
||||||
factory Log.fromJson(Map<String, dynamic> json) {
|
factory Log.app(
|
||||||
return _$LogFromJson(json);
|
String payload,
|
||||||
|
) {
|
||||||
|
return Log(
|
||||||
|
payload: payload,
|
||||||
|
dateTime: _logDateTime(null),
|
||||||
|
// id: _logId(null),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
factory Log.fromJson(Map<String, Object?> json) => _$LogFromJson(json);
|
||||||
return _$LogToJson(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'Log{logLevel: $logLevel, payload: $payload, dateTime: $dateTime}';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@@ -127,11 +127,10 @@ extension LogsStateExt on LogsState {
|
|||||||
final lowQuery = query.toLowerCase();
|
final lowQuery = query.toLowerCase();
|
||||||
return logs.where(
|
return logs.where(
|
||||||
(log) {
|
(log) {
|
||||||
final payload = log.payload?.toLowerCase();
|
final payload = log.payload.toLowerCase();
|
||||||
final logLevelName = log.logLevel.name;
|
final logLevelName = log.logLevel.name;
|
||||||
return {logLevelName}.containsAll(keywords) &&
|
return {logLevelName}.containsAll(keywords) &&
|
||||||
((payload?.contains(lowQuery) ?? false) ||
|
((payload.contains(lowQuery)) || logLevelName.contains(lowQuery));
|
||||||
logLevelName.contains(lowQuery));
|
|
||||||
},
|
},
|
||||||
).toList();
|
).toList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ const defaultNetworkProps = NetworkProps();
|
|||||||
const defaultProxiesStyle = ProxiesStyle();
|
const defaultProxiesStyle = ProxiesStyle();
|
||||||
const defaultWindowProps = WindowProps();
|
const defaultWindowProps = WindowProps();
|
||||||
const defaultAccessControl = AccessControl();
|
const defaultAccessControl = AccessControl();
|
||||||
const defaultThemeProps = ThemeProps();
|
final defaultThemeProps = ThemeProps(
|
||||||
|
primaryColor: defaultPrimaryColor,
|
||||||
|
);
|
||||||
|
|
||||||
const List<DashboardWidget> defaultDashboardWidgets = [
|
const List<DashboardWidget> defaultDashboardWidgets = [
|
||||||
DashboardWidget.networkSpeed,
|
DashboardWidget.networkSpeed,
|
||||||
@@ -82,6 +84,7 @@ class AppSettingProps with _$AppSettingProps {
|
|||||||
@Default(false) bool disclaimerAccepted,
|
@Default(false) bool disclaimerAccepted,
|
||||||
@Default(true) bool minimizeOnExit,
|
@Default(true) bool minimizeOnExit,
|
||||||
@Default(false) bool hidden,
|
@Default(false) bool hidden,
|
||||||
|
@Default(false) bool developerMode,
|
||||||
}) = _AppSettingProps;
|
}) = _AppSettingProps;
|
||||||
|
|
||||||
factory AppSettingProps.fromJson(Map<String, Object?> json) =>
|
factory AppSettingProps.fromJson(Map<String, Object?> json) =>
|
||||||
@@ -170,18 +173,41 @@ class ProxiesStyle with _$ProxiesStyle {
|
|||||||
json == null ? defaultProxiesStyle : _$ProxiesStyleFromJson(json);
|
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
|
@freezed
|
||||||
class ThemeProps with _$ThemeProps {
|
class ThemeProps with _$ThemeProps {
|
||||||
const factory ThemeProps({
|
const factory ThemeProps({
|
||||||
@Default(defaultPrimaryColor) int? primaryColor,
|
int? primaryColor,
|
||||||
@Default(defaultPrimaryColors) List<int> primaryColors,
|
@Default(defaultPrimaryColors) List<int> primaryColors,
|
||||||
@Default(ThemeMode.dark) ThemeMode themeMode,
|
@Default(ThemeMode.dark) ThemeMode themeMode,
|
||||||
@Default(DynamicSchemeVariant.tonalSpot) DynamicSchemeVariant schemeVariant,
|
@Default(DynamicSchemeVariant.tonalSpot) DynamicSchemeVariant schemeVariant,
|
||||||
@Default(false) bool pureBlack,
|
@Default(false) bool pureBlack,
|
||||||
|
@Default(TextScale()) TextScale textScale,
|
||||||
}) = _ThemeProps;
|
}) = _ThemeProps;
|
||||||
|
|
||||||
factory ThemeProps.fromJson(Map<String, Object?>? json) =>
|
factory ThemeProps.fromJson(Map<String, Object?> json) =>
|
||||||
json == null ? defaultThemeProps : _$ThemePropsFromJson(json);
|
_$ThemePropsFromJson(json);
|
||||||
|
|
||||||
|
factory ThemeProps.safeFromJson(Map<String, Object?>? json) {
|
||||||
|
if (json == null) {
|
||||||
|
return defaultThemeProps;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return ThemeProps.fromJson(json);
|
||||||
|
} catch (_) {
|
||||||
|
return defaultThemeProps;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@@ -197,7 +223,7 @@ class Config with _$Config {
|
|||||||
DAV? dav,
|
DAV? dav,
|
||||||
@Default(defaultNetworkProps) NetworkProps networkProps,
|
@Default(defaultNetworkProps) NetworkProps networkProps,
|
||||||
@Default(defaultVpnProps) VpnProps vpnProps,
|
@Default(defaultVpnProps) VpnProps vpnProps,
|
||||||
@Default(defaultThemeProps) ThemeProps themeProps,
|
@JsonKey(fromJson: ThemeProps.safeFromJson) required ThemeProps themeProps,
|
||||||
@Default(defaultProxiesStyle) ProxiesStyle proxiesStyle,
|
@Default(defaultProxiesStyle) ProxiesStyle proxiesStyle,
|
||||||
@Default(defaultWindowProps) WindowProps windowProps,
|
@Default(defaultWindowProps) WindowProps windowProps,
|
||||||
@Default(defaultClashConfig) ClashConfig patchClashConfig,
|
@Default(defaultClashConfig) ClashConfig patchClashConfig,
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ mixin _$AppState {
|
|||||||
bool get isInit => throw _privateConstructorUsedError;
|
bool get isInit => throw _privateConstructorUsedError;
|
||||||
PageLabel get pageLabel => throw _privateConstructorUsedError;
|
PageLabel get pageLabel => throw _privateConstructorUsedError;
|
||||||
List<Package> get packages => throw _privateConstructorUsedError;
|
List<Package> get packages => throw _privateConstructorUsedError;
|
||||||
ColorSchemes get colorSchemes => throw _privateConstructorUsedError;
|
|
||||||
int get sortNum => throw _privateConstructorUsedError;
|
int get sortNum => throw _privateConstructorUsedError;
|
||||||
Size get viewSize => throw _privateConstructorUsedError;
|
Size get viewSize => throw _privateConstructorUsedError;
|
||||||
Map<String, Map<String, int?>> get delayMap =>
|
Map<String, Map<String, int?>> get delayMap =>
|
||||||
@@ -53,7 +52,6 @@ abstract class $AppStateCopyWith<$Res> {
|
|||||||
{bool isInit,
|
{bool isInit,
|
||||||
PageLabel pageLabel,
|
PageLabel pageLabel,
|
||||||
List<Package> packages,
|
List<Package> packages,
|
||||||
ColorSchemes colorSchemes,
|
|
||||||
int sortNum,
|
int sortNum,
|
||||||
Size viewSize,
|
Size viewSize,
|
||||||
Map<String, Map<String, int?>> delayMap,
|
Map<String, Map<String, int?>> delayMap,
|
||||||
@@ -69,8 +67,6 @@ abstract class $AppStateCopyWith<$Res> {
|
|||||||
FixedList<Traffic> traffics,
|
FixedList<Traffic> traffics,
|
||||||
Traffic totalTraffic,
|
Traffic totalTraffic,
|
||||||
bool needApply});
|
bool needApply});
|
||||||
|
|
||||||
$ColorSchemesCopyWith<$Res> get colorSchemes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -91,7 +87,6 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
|
|||||||
Object? isInit = null,
|
Object? isInit = null,
|
||||||
Object? pageLabel = null,
|
Object? pageLabel = null,
|
||||||
Object? packages = null,
|
Object? packages = null,
|
||||||
Object? colorSchemes = null,
|
|
||||||
Object? sortNum = null,
|
Object? sortNum = null,
|
||||||
Object? viewSize = null,
|
Object? viewSize = null,
|
||||||
Object? delayMap = null,
|
Object? delayMap = null,
|
||||||
@@ -121,10 +116,6 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
|
|||||||
? _value.packages
|
? _value.packages
|
||||||
: packages // ignore: cast_nullable_to_non_nullable
|
: packages // ignore: cast_nullable_to_non_nullable
|
||||||
as List<Package>,
|
as List<Package>,
|
||||||
colorSchemes: null == colorSchemes
|
|
||||||
? _value.colorSchemes
|
|
||||||
: colorSchemes // ignore: cast_nullable_to_non_nullable
|
|
||||||
as ColorSchemes,
|
|
||||||
sortNum: null == sortNum
|
sortNum: null == sortNum
|
||||||
? _value.sortNum
|
? _value.sortNum
|
||||||
: sortNum // ignore: cast_nullable_to_non_nullable
|
: sortNum // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -187,16 +178,6 @@ class _$AppStateCopyWithImpl<$Res, $Val extends AppState>
|
|||||||
as bool,
|
as bool,
|
||||||
) as $Val);
|
) 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
|
/// @nodoc
|
||||||
@@ -211,7 +192,6 @@ abstract class _$$AppStateImplCopyWith<$Res>
|
|||||||
{bool isInit,
|
{bool isInit,
|
||||||
PageLabel pageLabel,
|
PageLabel pageLabel,
|
||||||
List<Package> packages,
|
List<Package> packages,
|
||||||
ColorSchemes colorSchemes,
|
|
||||||
int sortNum,
|
int sortNum,
|
||||||
Size viewSize,
|
Size viewSize,
|
||||||
Map<String, Map<String, int?>> delayMap,
|
Map<String, Map<String, int?>> delayMap,
|
||||||
@@ -227,9 +207,6 @@ abstract class _$$AppStateImplCopyWith<$Res>
|
|||||||
FixedList<Traffic> traffics,
|
FixedList<Traffic> traffics,
|
||||||
Traffic totalTraffic,
|
Traffic totalTraffic,
|
||||||
bool needApply});
|
bool needApply});
|
||||||
|
|
||||||
@override
|
|
||||||
$ColorSchemesCopyWith<$Res> get colorSchemes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -248,7 +225,6 @@ class __$$AppStateImplCopyWithImpl<$Res>
|
|||||||
Object? isInit = null,
|
Object? isInit = null,
|
||||||
Object? pageLabel = null,
|
Object? pageLabel = null,
|
||||||
Object? packages = null,
|
Object? packages = null,
|
||||||
Object? colorSchemes = null,
|
|
||||||
Object? sortNum = null,
|
Object? sortNum = null,
|
||||||
Object? viewSize = null,
|
Object? viewSize = null,
|
||||||
Object? delayMap = null,
|
Object? delayMap = null,
|
||||||
@@ -278,10 +254,6 @@ class __$$AppStateImplCopyWithImpl<$Res>
|
|||||||
? _value._packages
|
? _value._packages
|
||||||
: packages // ignore: cast_nullable_to_non_nullable
|
: packages // ignore: cast_nullable_to_non_nullable
|
||||||
as List<Package>,
|
as List<Package>,
|
||||||
colorSchemes: null == colorSchemes
|
|
||||||
? _value.colorSchemes
|
|
||||||
: colorSchemes // ignore: cast_nullable_to_non_nullable
|
|
||||||
as ColorSchemes,
|
|
||||||
sortNum: null == sortNum
|
sortNum: null == sortNum
|
||||||
? _value.sortNum
|
? _value.sortNum
|
||||||
: sortNum // ignore: cast_nullable_to_non_nullable
|
: sortNum // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -353,7 +325,6 @@ class _$AppStateImpl implements _AppState {
|
|||||||
{this.isInit = false,
|
{this.isInit = false,
|
||||||
this.pageLabel = PageLabel.dashboard,
|
this.pageLabel = PageLabel.dashboard,
|
||||||
final List<Package> packages = const [],
|
final List<Package> packages = const [],
|
||||||
this.colorSchemes = const ColorSchemes(),
|
|
||||||
this.sortNum = 0,
|
this.sortNum = 0,
|
||||||
required this.viewSize,
|
required this.viewSize,
|
||||||
final Map<String, Map<String, int?>> delayMap = const {},
|
final Map<String, Map<String, int?>> delayMap = const {},
|
||||||
@@ -389,9 +360,6 @@ class _$AppStateImpl implements _AppState {
|
|||||||
return EqualUnmodifiableListView(_packages);
|
return EqualUnmodifiableListView(_packages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
@JsonKey()
|
|
||||||
final ColorSchemes colorSchemes;
|
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final int sortNum;
|
final int sortNum;
|
||||||
@@ -449,7 +417,7 @@ class _$AppStateImpl implements _AppState {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppState(isInit: $isInit, pageLabel: $pageLabel, packages: $packages, colorSchemes: $colorSchemes, sortNum: $sortNum, viewSize: $viewSize, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, needApply: $needApply)';
|
return 'AppState(isInit: $isInit, pageLabel: $pageLabel, packages: $packages, sortNum: $sortNum, viewSize: $viewSize, delayMap: $delayMap, groups: $groups, checkIpNum: $checkIpNum, brightness: $brightness, runTime: $runTime, providers: $providers, localIp: $localIp, requests: $requests, version: $version, logs: $logs, traffics: $traffics, totalTraffic: $totalTraffic, needApply: $needApply)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -461,8 +429,6 @@ class _$AppStateImpl implements _AppState {
|
|||||||
(identical(other.pageLabel, pageLabel) ||
|
(identical(other.pageLabel, pageLabel) ||
|
||||||
other.pageLabel == pageLabel) &&
|
other.pageLabel == pageLabel) &&
|
||||||
const DeepCollectionEquality().equals(other._packages, _packages) &&
|
const DeepCollectionEquality().equals(other._packages, _packages) &&
|
||||||
(identical(other.colorSchemes, colorSchemes) ||
|
|
||||||
other.colorSchemes == colorSchemes) &&
|
|
||||||
(identical(other.sortNum, sortNum) || other.sortNum == sortNum) &&
|
(identical(other.sortNum, sortNum) || other.sortNum == sortNum) &&
|
||||||
(identical(other.viewSize, viewSize) ||
|
(identical(other.viewSize, viewSize) ||
|
||||||
other.viewSize == viewSize) &&
|
other.viewSize == viewSize) &&
|
||||||
@@ -489,28 +455,26 @@ class _$AppStateImpl implements _AppState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([
|
int get hashCode => Object.hash(
|
||||||
runtimeType,
|
runtimeType,
|
||||||
isInit,
|
isInit,
|
||||||
pageLabel,
|
pageLabel,
|
||||||
const DeepCollectionEquality().hash(_packages),
|
const DeepCollectionEquality().hash(_packages),
|
||||||
colorSchemes,
|
sortNum,
|
||||||
sortNum,
|
viewSize,
|
||||||
viewSize,
|
const DeepCollectionEquality().hash(_delayMap),
|
||||||
const DeepCollectionEquality().hash(_delayMap),
|
const DeepCollectionEquality().hash(_groups),
|
||||||
const DeepCollectionEquality().hash(_groups),
|
checkIpNum,
|
||||||
checkIpNum,
|
brightness,
|
||||||
brightness,
|
runTime,
|
||||||
runTime,
|
const DeepCollectionEquality().hash(_providers),
|
||||||
const DeepCollectionEquality().hash(_providers),
|
localIp,
|
||||||
localIp,
|
requests,
|
||||||
requests,
|
version,
|
||||||
version,
|
logs,
|
||||||
logs,
|
traffics,
|
||||||
traffics,
|
totalTraffic,
|
||||||
totalTraffic,
|
needApply);
|
||||||
needApply
|
|
||||||
]);
|
|
||||||
|
|
||||||
/// Create a copy of AppState
|
/// Create a copy of AppState
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -526,7 +490,6 @@ abstract class _AppState implements AppState {
|
|||||||
{final bool isInit,
|
{final bool isInit,
|
||||||
final PageLabel pageLabel,
|
final PageLabel pageLabel,
|
||||||
final List<Package> packages,
|
final List<Package> packages,
|
||||||
final ColorSchemes colorSchemes,
|
|
||||||
final int sortNum,
|
final int sortNum,
|
||||||
required final Size viewSize,
|
required final Size viewSize,
|
||||||
final Map<String, Map<String, int?>> delayMap,
|
final Map<String, Map<String, int?>> delayMap,
|
||||||
@@ -550,8 +513,6 @@ abstract class _AppState implements AppState {
|
|||||||
@override
|
@override
|
||||||
List<Package> get packages;
|
List<Package> get packages;
|
||||||
@override
|
@override
|
||||||
ColorSchemes get colorSchemes;
|
|
||||||
@override
|
|
||||||
int get sortNum;
|
int get sortNum;
|
||||||
@override
|
@override
|
||||||
Size get viewSize;
|
Size get viewSize;
|
||||||
|
|||||||
@@ -342,6 +342,7 @@ const _$LogLevelEnumMap = {
|
|||||||
LogLevel.warning: 'warning',
|
LogLevel.warning: 'warning',
|
||||||
LogLevel.error: 'error',
|
LogLevel.error: 'error',
|
||||||
LogLevel.silent: 'silent',
|
LogLevel.silent: 'silent',
|
||||||
|
LogLevel.app: 'app',
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$FindProcessModeEnumMap = {
|
const _$FindProcessModeEnumMap = {
|
||||||
|
|||||||
@@ -1092,6 +1092,203 @@ abstract class _Connection implements Connection {
|
|||||||
throw _privateConstructorUsedError;
|
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
|
/// @nodoc
|
||||||
mixin _$LogsState {
|
mixin _$LogsState {
|
||||||
List<Log> get logs => throw _privateConstructorUsedError;
|
List<Log> get logs => throw _privateConstructorUsedError;
|
||||||
|
|||||||
@@ -6,24 +6,6 @@ part of '../common.dart';
|
|||||||
// JsonSerializableGenerator
|
// 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 _$$PackageImplFromJson(Map<String, dynamic> json) =>
|
||||||
_$PackageImpl(
|
_$PackageImpl(
|
||||||
packageName: json['packageName'] as String,
|
packageName: json['packageName'] as String,
|
||||||
@@ -87,6 +69,28 @@ Map<String, dynamic> _$$ConnectionImplToJson(_$ConnectionImpl instance) =>
|
|||||||
'chains': instance.chains,
|
'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(
|
_$DAVImpl _$$DAVImplFromJson(Map<String, dynamic> json) => _$DAVImpl(
|
||||||
uri: json['uri'] as String,
|
uri: json['uri'] as String,
|
||||||
user: json['user'] as String,
|
user: json['user'] as String,
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ mixin _$AppSettingProps {
|
|||||||
bool get disclaimerAccepted => throw _privateConstructorUsedError;
|
bool get disclaimerAccepted => throw _privateConstructorUsedError;
|
||||||
bool get minimizeOnExit => throw _privateConstructorUsedError;
|
bool get minimizeOnExit => throw _privateConstructorUsedError;
|
||||||
bool get hidden => throw _privateConstructorUsedError;
|
bool get hidden => throw _privateConstructorUsedError;
|
||||||
|
bool get developerMode => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
/// Serializes this AppSettingProps to a JSON map.
|
/// Serializes this AppSettingProps to a JSON map.
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
@@ -70,7 +71,8 @@ abstract class $AppSettingPropsCopyWith<$Res> {
|
|||||||
bool showLabel,
|
bool showLabel,
|
||||||
bool disclaimerAccepted,
|
bool disclaimerAccepted,
|
||||||
bool minimizeOnExit,
|
bool minimizeOnExit,
|
||||||
bool hidden});
|
bool hidden,
|
||||||
|
bool developerMode});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -103,6 +105,7 @@ class _$AppSettingPropsCopyWithImpl<$Res, $Val extends AppSettingProps>
|
|||||||
Object? disclaimerAccepted = null,
|
Object? disclaimerAccepted = null,
|
||||||
Object? minimizeOnExit = null,
|
Object? minimizeOnExit = null,
|
||||||
Object? hidden = null,
|
Object? hidden = null,
|
||||||
|
Object? developerMode = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_value.copyWith(
|
return _then(_value.copyWith(
|
||||||
locale: freezed == locale
|
locale: freezed == locale
|
||||||
@@ -165,6 +168,10 @@ class _$AppSettingPropsCopyWithImpl<$Res, $Val extends AppSettingProps>
|
|||||||
? _value.hidden
|
? _value.hidden
|
||||||
: hidden // ignore: cast_nullable_to_non_nullable
|
: hidden // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
developerMode: null == developerMode
|
||||||
|
? _value.developerMode
|
||||||
|
: developerMode // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
) as $Val);
|
) as $Val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,7 +200,8 @@ abstract class _$$AppSettingPropsImplCopyWith<$Res>
|
|||||||
bool showLabel,
|
bool showLabel,
|
||||||
bool disclaimerAccepted,
|
bool disclaimerAccepted,
|
||||||
bool minimizeOnExit,
|
bool minimizeOnExit,
|
||||||
bool hidden});
|
bool hidden,
|
||||||
|
bool developerMode});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -224,6 +232,7 @@ class __$$AppSettingPropsImplCopyWithImpl<$Res>
|
|||||||
Object? disclaimerAccepted = null,
|
Object? disclaimerAccepted = null,
|
||||||
Object? minimizeOnExit = null,
|
Object? minimizeOnExit = null,
|
||||||
Object? hidden = null,
|
Object? hidden = null,
|
||||||
|
Object? developerMode = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_$AppSettingPropsImpl(
|
return _then(_$AppSettingPropsImpl(
|
||||||
locale: freezed == locale
|
locale: freezed == locale
|
||||||
@@ -286,6 +295,10 @@ class __$$AppSettingPropsImplCopyWithImpl<$Res>
|
|||||||
? _value.hidden
|
? _value.hidden
|
||||||
: hidden // ignore: cast_nullable_to_non_nullable
|
: hidden // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
developerMode: null == developerMode
|
||||||
|
? _value.developerMode
|
||||||
|
: developerMode // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,7 +322,8 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
|
|||||||
this.showLabel = false,
|
this.showLabel = false,
|
||||||
this.disclaimerAccepted = false,
|
this.disclaimerAccepted = false,
|
||||||
this.minimizeOnExit = true,
|
this.minimizeOnExit = true,
|
||||||
this.hidden = false})
|
this.hidden = false,
|
||||||
|
this.developerMode = false})
|
||||||
: _dashboardWidgets = dashboardWidgets;
|
: _dashboardWidgets = dashboardWidgets;
|
||||||
|
|
||||||
factory _$AppSettingPropsImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$AppSettingPropsImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
@@ -366,10 +380,13 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
|
|||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final bool hidden;
|
final bool hidden;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final bool developerMode;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppSettingProps(locale: $locale, dashboardWidgets: $dashboardWidgets, onlyStatisticsProxy: $onlyStatisticsProxy, autoLaunch: $autoLaunch, silentLaunch: $silentLaunch, autoRun: $autoRun, openLogs: $openLogs, closeConnections: $closeConnections, testUrl: $testUrl, isAnimateToPage: $isAnimateToPage, autoCheckUpdate: $autoCheckUpdate, showLabel: $showLabel, disclaimerAccepted: $disclaimerAccepted, minimizeOnExit: $minimizeOnExit, hidden: $hidden)';
|
return 'AppSettingProps(locale: $locale, dashboardWidgets: $dashboardWidgets, onlyStatisticsProxy: $onlyStatisticsProxy, autoLaunch: $autoLaunch, silentLaunch: $silentLaunch, autoRun: $autoRun, openLogs: $openLogs, closeConnections: $closeConnections, testUrl: $testUrl, isAnimateToPage: $isAnimateToPage, autoCheckUpdate: $autoCheckUpdate, showLabel: $showLabel, disclaimerAccepted: $disclaimerAccepted, minimizeOnExit: $minimizeOnExit, hidden: $hidden, developerMode: $developerMode)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -402,7 +419,9 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
|
|||||||
other.disclaimerAccepted == disclaimerAccepted) &&
|
other.disclaimerAccepted == disclaimerAccepted) &&
|
||||||
(identical(other.minimizeOnExit, minimizeOnExit) ||
|
(identical(other.minimizeOnExit, minimizeOnExit) ||
|
||||||
other.minimizeOnExit == minimizeOnExit) &&
|
other.minimizeOnExit == minimizeOnExit) &&
|
||||||
(identical(other.hidden, hidden) || other.hidden == hidden));
|
(identical(other.hidden, hidden) || other.hidden == hidden) &&
|
||||||
|
(identical(other.developerMode, developerMode) ||
|
||||||
|
other.developerMode == developerMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -423,7 +442,8 @@ class _$AppSettingPropsImpl implements _AppSettingProps {
|
|||||||
showLabel,
|
showLabel,
|
||||||
disclaimerAccepted,
|
disclaimerAccepted,
|
||||||
minimizeOnExit,
|
minimizeOnExit,
|
||||||
hidden);
|
hidden,
|
||||||
|
developerMode);
|
||||||
|
|
||||||
/// Create a copy of AppSettingProps
|
/// Create a copy of AppSettingProps
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -459,7 +479,8 @@ abstract class _AppSettingProps implements AppSettingProps {
|
|||||||
final bool showLabel,
|
final bool showLabel,
|
||||||
final bool disclaimerAccepted,
|
final bool disclaimerAccepted,
|
||||||
final bool minimizeOnExit,
|
final bool minimizeOnExit,
|
||||||
final bool hidden}) = _$AppSettingPropsImpl;
|
final bool hidden,
|
||||||
|
final bool developerMode}) = _$AppSettingPropsImpl;
|
||||||
|
|
||||||
factory _AppSettingProps.fromJson(Map<String, dynamic> json) =
|
factory _AppSettingProps.fromJson(Map<String, dynamic> json) =
|
||||||
_$AppSettingPropsImpl.fromJson;
|
_$AppSettingPropsImpl.fromJson;
|
||||||
@@ -495,6 +516,8 @@ abstract class _AppSettingProps implements AppSettingProps {
|
|||||||
bool get minimizeOnExit;
|
bool get minimizeOnExit;
|
||||||
@override
|
@override
|
||||||
bool get hidden;
|
bool get hidden;
|
||||||
|
@override
|
||||||
|
bool get developerMode;
|
||||||
|
|
||||||
/// Create a copy of AppSettingProps
|
/// Create a copy of AppSettingProps
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -1717,6 +1740,170 @@ abstract class _ProxiesStyle implements ProxiesStyle {
|
|||||||
throw _privateConstructorUsedError;
|
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) {
|
ThemeProps _$ThemePropsFromJson(Map<String, dynamic> json) {
|
||||||
return _ThemeProps.fromJson(json);
|
return _ThemeProps.fromJson(json);
|
||||||
}
|
}
|
||||||
@@ -1728,6 +1915,7 @@ mixin _$ThemeProps {
|
|||||||
ThemeMode get themeMode => throw _privateConstructorUsedError;
|
ThemeMode get themeMode => throw _privateConstructorUsedError;
|
||||||
DynamicSchemeVariant get schemeVariant => throw _privateConstructorUsedError;
|
DynamicSchemeVariant get schemeVariant => throw _privateConstructorUsedError;
|
||||||
bool get pureBlack => throw _privateConstructorUsedError;
|
bool get pureBlack => throw _privateConstructorUsedError;
|
||||||
|
TextScale get textScale => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
/// Serializes this ThemeProps to a JSON map.
|
/// Serializes this ThemeProps to a JSON map.
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
@@ -1750,7 +1938,10 @@ abstract class $ThemePropsCopyWith<$Res> {
|
|||||||
List<int> primaryColors,
|
List<int> primaryColors,
|
||||||
ThemeMode themeMode,
|
ThemeMode themeMode,
|
||||||
DynamicSchemeVariant schemeVariant,
|
DynamicSchemeVariant schemeVariant,
|
||||||
bool pureBlack});
|
bool pureBlack,
|
||||||
|
TextScale textScale});
|
||||||
|
|
||||||
|
$TextScaleCopyWith<$Res> get textScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1773,6 +1964,7 @@ class _$ThemePropsCopyWithImpl<$Res, $Val extends ThemeProps>
|
|||||||
Object? themeMode = null,
|
Object? themeMode = null,
|
||||||
Object? schemeVariant = null,
|
Object? schemeVariant = null,
|
||||||
Object? pureBlack = null,
|
Object? pureBlack = null,
|
||||||
|
Object? textScale = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_value.copyWith(
|
return _then(_value.copyWith(
|
||||||
primaryColor: freezed == primaryColor
|
primaryColor: freezed == primaryColor
|
||||||
@@ -1795,8 +1987,22 @@ class _$ThemePropsCopyWithImpl<$Res, $Val extends ThemeProps>
|
|||||||
? _value.pureBlack
|
? _value.pureBlack
|
||||||
: pureBlack // ignore: cast_nullable_to_non_nullable
|
: pureBlack // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
textScale: null == textScale
|
||||||
|
? _value.textScale
|
||||||
|
: textScale // ignore: cast_nullable_to_non_nullable
|
||||||
|
as TextScale,
|
||||||
) as $Val);
|
) 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
|
/// @nodoc
|
||||||
@@ -1812,7 +2018,11 @@ abstract class _$$ThemePropsImplCopyWith<$Res>
|
|||||||
List<int> primaryColors,
|
List<int> primaryColors,
|
||||||
ThemeMode themeMode,
|
ThemeMode themeMode,
|
||||||
DynamicSchemeVariant schemeVariant,
|
DynamicSchemeVariant schemeVariant,
|
||||||
bool pureBlack});
|
bool pureBlack,
|
||||||
|
TextScale textScale});
|
||||||
|
|
||||||
|
@override
|
||||||
|
$TextScaleCopyWith<$Res> get textScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1833,6 +2043,7 @@ class __$$ThemePropsImplCopyWithImpl<$Res>
|
|||||||
Object? themeMode = null,
|
Object? themeMode = null,
|
||||||
Object? schemeVariant = null,
|
Object? schemeVariant = null,
|
||||||
Object? pureBlack = null,
|
Object? pureBlack = null,
|
||||||
|
Object? textScale = null,
|
||||||
}) {
|
}) {
|
||||||
return _then(_$ThemePropsImpl(
|
return _then(_$ThemePropsImpl(
|
||||||
primaryColor: freezed == primaryColor
|
primaryColor: freezed == primaryColor
|
||||||
@@ -1855,6 +2066,10 @@ class __$$ThemePropsImplCopyWithImpl<$Res>
|
|||||||
? _value.pureBlack
|
? _value.pureBlack
|
||||||
: pureBlack // ignore: cast_nullable_to_non_nullable
|
: pureBlack // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,
|
||||||
|
textScale: null == textScale
|
||||||
|
? _value.textScale
|
||||||
|
: textScale // ignore: cast_nullable_to_non_nullable
|
||||||
|
as TextScale,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1863,18 +2078,18 @@ class __$$ThemePropsImplCopyWithImpl<$Res>
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
class _$ThemePropsImpl implements _ThemeProps {
|
class _$ThemePropsImpl implements _ThemeProps {
|
||||||
const _$ThemePropsImpl(
|
const _$ThemePropsImpl(
|
||||||
{this.primaryColor = defaultPrimaryColor,
|
{this.primaryColor,
|
||||||
final List<int> primaryColors = defaultPrimaryColors,
|
final List<int> primaryColors = defaultPrimaryColors,
|
||||||
this.themeMode = ThemeMode.dark,
|
this.themeMode = ThemeMode.dark,
|
||||||
this.schemeVariant = DynamicSchemeVariant.tonalSpot,
|
this.schemeVariant = DynamicSchemeVariant.tonalSpot,
|
||||||
this.pureBlack = false})
|
this.pureBlack = false,
|
||||||
|
this.textScale = const TextScale()})
|
||||||
: _primaryColors = primaryColors;
|
: _primaryColors = primaryColors;
|
||||||
|
|
||||||
factory _$ThemePropsImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$ThemePropsImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
_$$ThemePropsImplFromJson(json);
|
_$$ThemePropsImplFromJson(json);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
|
||||||
final int? primaryColor;
|
final int? primaryColor;
|
||||||
final List<int> _primaryColors;
|
final List<int> _primaryColors;
|
||||||
@override
|
@override
|
||||||
@@ -1894,10 +2109,13 @@ class _$ThemePropsImpl implements _ThemeProps {
|
|||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
final bool pureBlack;
|
final bool pureBlack;
|
||||||
|
@override
|
||||||
|
@JsonKey()
|
||||||
|
final TextScale textScale;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ThemeProps(primaryColor: $primaryColor, primaryColors: $primaryColors, themeMode: $themeMode, schemeVariant: $schemeVariant, pureBlack: $pureBlack)';
|
return 'ThemeProps(primaryColor: $primaryColor, primaryColors: $primaryColors, themeMode: $themeMode, schemeVariant: $schemeVariant, pureBlack: $pureBlack, textScale: $textScale)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -1914,7 +2132,9 @@ class _$ThemePropsImpl implements _ThemeProps {
|
|||||||
(identical(other.schemeVariant, schemeVariant) ||
|
(identical(other.schemeVariant, schemeVariant) ||
|
||||||
other.schemeVariant == schemeVariant) &&
|
other.schemeVariant == schemeVariant) &&
|
||||||
(identical(other.pureBlack, pureBlack) ||
|
(identical(other.pureBlack, pureBlack) ||
|
||||||
other.pureBlack == pureBlack));
|
other.pureBlack == pureBlack) &&
|
||||||
|
(identical(other.textScale, textScale) ||
|
||||||
|
other.textScale == textScale));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -1925,7 +2145,8 @@ class _$ThemePropsImpl implements _ThemeProps {
|
|||||||
const DeepCollectionEquality().hash(_primaryColors),
|
const DeepCollectionEquality().hash(_primaryColors),
|
||||||
themeMode,
|
themeMode,
|
||||||
schemeVariant,
|
schemeVariant,
|
||||||
pureBlack);
|
pureBlack,
|
||||||
|
textScale);
|
||||||
|
|
||||||
/// Create a copy of ThemeProps
|
/// Create a copy of ThemeProps
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -1949,7 +2170,8 @@ abstract class _ThemeProps implements ThemeProps {
|
|||||||
final List<int> primaryColors,
|
final List<int> primaryColors,
|
||||||
final ThemeMode themeMode,
|
final ThemeMode themeMode,
|
||||||
final DynamicSchemeVariant schemeVariant,
|
final DynamicSchemeVariant schemeVariant,
|
||||||
final bool pureBlack}) = _$ThemePropsImpl;
|
final bool pureBlack,
|
||||||
|
final TextScale textScale}) = _$ThemePropsImpl;
|
||||||
|
|
||||||
factory _ThemeProps.fromJson(Map<String, dynamic> json) =
|
factory _ThemeProps.fromJson(Map<String, dynamic> json) =
|
||||||
_$ThemePropsImpl.fromJson;
|
_$ThemePropsImpl.fromJson;
|
||||||
@@ -1964,6 +2186,8 @@ abstract class _ThemeProps implements ThemeProps {
|
|||||||
DynamicSchemeVariant get schemeVariant;
|
DynamicSchemeVariant get schemeVariant;
|
||||||
@override
|
@override
|
||||||
bool get pureBlack;
|
bool get pureBlack;
|
||||||
|
@override
|
||||||
|
TextScale get textScale;
|
||||||
|
|
||||||
/// Create a copy of ThemeProps
|
/// Create a copy of ThemeProps
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -1988,6 +2212,7 @@ mixin _$Config {
|
|||||||
DAV? get dav => throw _privateConstructorUsedError;
|
DAV? get dav => throw _privateConstructorUsedError;
|
||||||
NetworkProps get networkProps => throw _privateConstructorUsedError;
|
NetworkProps get networkProps => throw _privateConstructorUsedError;
|
||||||
VpnProps get vpnProps => throw _privateConstructorUsedError;
|
VpnProps get vpnProps => throw _privateConstructorUsedError;
|
||||||
|
@JsonKey(fromJson: ThemeProps.safeFromJson)
|
||||||
ThemeProps get themeProps => throw _privateConstructorUsedError;
|
ThemeProps get themeProps => throw _privateConstructorUsedError;
|
||||||
ProxiesStyle get proxiesStyle => throw _privateConstructorUsedError;
|
ProxiesStyle get proxiesStyle => throw _privateConstructorUsedError;
|
||||||
WindowProps get windowProps => throw _privateConstructorUsedError;
|
WindowProps get windowProps => throw _privateConstructorUsedError;
|
||||||
@@ -2017,7 +2242,7 @@ abstract class $ConfigCopyWith<$Res> {
|
|||||||
DAV? dav,
|
DAV? dav,
|
||||||
NetworkProps networkProps,
|
NetworkProps networkProps,
|
||||||
VpnProps vpnProps,
|
VpnProps vpnProps,
|
||||||
ThemeProps themeProps,
|
@JsonKey(fromJson: ThemeProps.safeFromJson) ThemeProps themeProps,
|
||||||
ProxiesStyle proxiesStyle,
|
ProxiesStyle proxiesStyle,
|
||||||
WindowProps windowProps,
|
WindowProps windowProps,
|
||||||
ClashConfig patchClashConfig});
|
ClashConfig patchClashConfig});
|
||||||
@@ -2214,7 +2439,7 @@ abstract class _$$ConfigImplCopyWith<$Res> implements $ConfigCopyWith<$Res> {
|
|||||||
DAV? dav,
|
DAV? dav,
|
||||||
NetworkProps networkProps,
|
NetworkProps networkProps,
|
||||||
VpnProps vpnProps,
|
VpnProps vpnProps,
|
||||||
ThemeProps themeProps,
|
@JsonKey(fromJson: ThemeProps.safeFromJson) ThemeProps themeProps,
|
||||||
ProxiesStyle proxiesStyle,
|
ProxiesStyle proxiesStyle,
|
||||||
WindowProps windowProps,
|
WindowProps windowProps,
|
||||||
ClashConfig patchClashConfig});
|
ClashConfig patchClashConfig});
|
||||||
@@ -2329,7 +2554,7 @@ class _$ConfigImpl implements _Config {
|
|||||||
this.dav,
|
this.dav,
|
||||||
this.networkProps = defaultNetworkProps,
|
this.networkProps = defaultNetworkProps,
|
||||||
this.vpnProps = defaultVpnProps,
|
this.vpnProps = defaultVpnProps,
|
||||||
this.themeProps = defaultThemeProps,
|
@JsonKey(fromJson: ThemeProps.safeFromJson) required this.themeProps,
|
||||||
this.proxiesStyle = defaultProxiesStyle,
|
this.proxiesStyle = defaultProxiesStyle,
|
||||||
this.windowProps = defaultWindowProps,
|
this.windowProps = defaultWindowProps,
|
||||||
this.patchClashConfig = defaultClashConfig})
|
this.patchClashConfig = defaultClashConfig})
|
||||||
@@ -2374,7 +2599,7 @@ class _$ConfigImpl implements _Config {
|
|||||||
@JsonKey()
|
@JsonKey()
|
||||||
final VpnProps vpnProps;
|
final VpnProps vpnProps;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey(fromJson: ThemeProps.safeFromJson)
|
||||||
final ThemeProps themeProps;
|
final ThemeProps themeProps;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
@@ -2464,7 +2689,8 @@ abstract class _Config implements Config {
|
|||||||
final DAV? dav,
|
final DAV? dav,
|
||||||
final NetworkProps networkProps,
|
final NetworkProps networkProps,
|
||||||
final VpnProps vpnProps,
|
final VpnProps vpnProps,
|
||||||
final ThemeProps themeProps,
|
@JsonKey(fromJson: ThemeProps.safeFromJson)
|
||||||
|
required final ThemeProps themeProps,
|
||||||
final ProxiesStyle proxiesStyle,
|
final ProxiesStyle proxiesStyle,
|
||||||
final WindowProps windowProps,
|
final WindowProps windowProps,
|
||||||
final ClashConfig patchClashConfig}) = _$ConfigImpl;
|
final ClashConfig patchClashConfig}) = _$ConfigImpl;
|
||||||
@@ -2489,6 +2715,7 @@ abstract class _Config implements Config {
|
|||||||
@override
|
@override
|
||||||
VpnProps get vpnProps;
|
VpnProps get vpnProps;
|
||||||
@override
|
@override
|
||||||
|
@JsonKey(fromJson: ThemeProps.safeFromJson)
|
||||||
ThemeProps get themeProps;
|
ThemeProps get themeProps;
|
||||||
@override
|
@override
|
||||||
ProxiesStyle get proxiesStyle;
|
ProxiesStyle get proxiesStyle;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ _$AppSettingPropsImpl _$$AppSettingPropsImplFromJson(
|
|||||||
disclaimerAccepted: json['disclaimerAccepted'] as bool? ?? false,
|
disclaimerAccepted: json['disclaimerAccepted'] as bool? ?? false,
|
||||||
minimizeOnExit: json['minimizeOnExit'] as bool? ?? true,
|
minimizeOnExit: json['minimizeOnExit'] as bool? ?? true,
|
||||||
hidden: json['hidden'] as bool? ?? false,
|
hidden: json['hidden'] as bool? ?? false,
|
||||||
|
developerMode: json['developerMode'] as bool? ?? false,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$AppSettingPropsImplToJson(
|
Map<String, dynamic> _$$AppSettingPropsImplToJson(
|
||||||
@@ -48,10 +49,12 @@ Map<String, dynamic> _$$AppSettingPropsImplToJson(
|
|||||||
'disclaimerAccepted': instance.disclaimerAccepted,
|
'disclaimerAccepted': instance.disclaimerAccepted,
|
||||||
'minimizeOnExit': instance.minimizeOnExit,
|
'minimizeOnExit': instance.minimizeOnExit,
|
||||||
'hidden': instance.hidden,
|
'hidden': instance.hidden,
|
||||||
|
'developerMode': instance.developerMode,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$DashboardWidgetEnumMap = {
|
const _$DashboardWidgetEnumMap = {
|
||||||
DashboardWidget.networkSpeed: 'networkSpeed',
|
DashboardWidget.networkSpeed: 'networkSpeed',
|
||||||
|
DashboardWidget.outboundModeV2: 'outboundModeV2',
|
||||||
DashboardWidget.outboundMode: 'outboundMode',
|
DashboardWidget.outboundMode: 'outboundMode',
|
||||||
DashboardWidget.trafficUsage: 'trafficUsage',
|
DashboardWidget.trafficUsage: 'trafficUsage',
|
||||||
DashboardWidget.networkDetection: 'networkDetection',
|
DashboardWidget.networkDetection: 'networkDetection',
|
||||||
@@ -219,10 +222,21 @@ const _$ProxyCardTypeEnumMap = {
|
|||||||
ProxyCardType.min: 'min',
|
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 _$$ThemePropsImplFromJson(Map<String, dynamic> json) =>
|
||||||
_$ThemePropsImpl(
|
_$ThemePropsImpl(
|
||||||
primaryColor:
|
primaryColor: (json['primaryColor'] as num?)?.toInt(),
|
||||||
(json['primaryColor'] as num?)?.toInt() ?? defaultPrimaryColor,
|
|
||||||
primaryColors: (json['primaryColors'] as List<dynamic>?)
|
primaryColors: (json['primaryColors'] as List<dynamic>?)
|
||||||
?.map((e) => (e as num).toInt())
|
?.map((e) => (e as num).toInt())
|
||||||
.toList() ??
|
.toList() ??
|
||||||
@@ -233,6 +247,9 @@ _$ThemePropsImpl _$$ThemePropsImplFromJson(Map<String, dynamic> json) =>
|
|||||||
_$DynamicSchemeVariantEnumMap, json['schemeVariant']) ??
|
_$DynamicSchemeVariantEnumMap, json['schemeVariant']) ??
|
||||||
DynamicSchemeVariant.tonalSpot,
|
DynamicSchemeVariant.tonalSpot,
|
||||||
pureBlack: json['pureBlack'] as bool? ?? false,
|
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) =>
|
Map<String, dynamic> _$$ThemePropsImplToJson(_$ThemePropsImpl instance) =>
|
||||||
@@ -242,6 +259,7 @@ Map<String, dynamic> _$$ThemePropsImplToJson(_$ThemePropsImpl instance) =>
|
|||||||
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
|
'themeMode': _$ThemeModeEnumMap[instance.themeMode]!,
|
||||||
'schemeVariant': _$DynamicSchemeVariantEnumMap[instance.schemeVariant]!,
|
'schemeVariant': _$DynamicSchemeVariantEnumMap[instance.schemeVariant]!,
|
||||||
'pureBlack': instance.pureBlack,
|
'pureBlack': instance.pureBlack,
|
||||||
|
'textScale': instance.textScale,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$ThemeModeEnumMap = {
|
const _$ThemeModeEnumMap = {
|
||||||
@@ -287,9 +305,8 @@ _$ConfigImpl _$$ConfigImplFromJson(Map<String, dynamic> json) => _$ConfigImpl(
|
|||||||
vpnProps: json['vpnProps'] == null
|
vpnProps: json['vpnProps'] == null
|
||||||
? defaultVpnProps
|
? defaultVpnProps
|
||||||
: VpnProps.fromJson(json['vpnProps'] as Map<String, dynamic>?),
|
: VpnProps.fromJson(json['vpnProps'] as Map<String, dynamic>?),
|
||||||
themeProps: json['themeProps'] == null
|
themeProps:
|
||||||
? defaultThemeProps
|
ThemeProps.safeFromJson(json['themeProps'] as Map<String, Object?>?),
|
||||||
: ThemeProps.fromJson(json['themeProps'] as Map<String, dynamic>?),
|
|
||||||
proxiesStyle: json['proxiesStyle'] == null
|
proxiesStyle: json['proxiesStyle'] == null
|
||||||
? defaultProxiesStyle
|
? defaultProxiesStyle
|
||||||
: ProxiesStyle.fromJson(
|
: ProxiesStyle.fromJson(
|
||||||
|
|||||||
@@ -345,6 +345,7 @@ const _$ActionMethodEnumMap = {
|
|||||||
ActionMethod.getCountryCode: 'getCountryCode',
|
ActionMethod.getCountryCode: 'getCountryCode',
|
||||||
ActionMethod.getMemory: 'getMemory',
|
ActionMethod.getMemory: 'getMemory',
|
||||||
ActionMethod.getProfile: 'getProfile',
|
ActionMethod.getProfile: 'getProfile',
|
||||||
|
ActionMethod.crash: 'crash',
|
||||||
ActionMethod.setFdMap: 'setFdMap',
|
ActionMethod.setFdMap: 'setFdMap',
|
||||||
ActionMethod.setProcessMap: 'setProcessMap',
|
ActionMethod.setProcessMap: 'setProcessMap',
|
||||||
ActionMethod.setState: 'setState',
|
ActionMethod.setState: 'setState',
|
||||||
|
|||||||
@@ -129,6 +129,16 @@ class _HomePageViewState extends ConsumerState<_HomePageView> {
|
|||||||
controller: _pageController,
|
controller: _pageController,
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
itemCount: navigationItems.length,
|
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) {
|
itemBuilder: (_, index) {
|
||||||
final navigationItem = navigationItems[index];
|
final navigationItem = navigationItems[index];
|
||||||
return KeepScope(
|
return KeepScope(
|
||||||
|
|||||||
@@ -252,21 +252,6 @@ class CurrentPageLabel extends _$CurrentPageLabel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
|
||||||
class AppSchemes extends _$AppSchemes with AutoDisposeNotifierMixin {
|
|
||||||
@override
|
|
||||||
ColorSchemes build() {
|
|
||||||
return globalState.appState.colorSchemes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
onUpdate(value) {
|
|
||||||
globalState.appState = globalState.appState.copyWith(
|
|
||||||
colorSchemes: value,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
class SortNum extends _$SortNum with AutoDisposeNotifierMixin {
|
class SortNum extends _$SortNum with AutoDisposeNotifierMixin {
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -247,21 +247,6 @@ final currentPageLabelProvider =
|
|||||||
);
|
);
|
||||||
|
|
||||||
typedef _$CurrentPageLabel = AutoDisposeNotifier<PageLabel>;
|
typedef _$CurrentPageLabel = AutoDisposeNotifier<PageLabel>;
|
||||||
String _$appSchemesHash() => r'748f48f23539a879a92f318a21e1266b1df56aae';
|
|
||||||
|
|
||||||
/// See also [AppSchemes].
|
|
||||||
@ProviderFor(AppSchemes)
|
|
||||||
final appSchemesProvider =
|
|
||||||
AutoDisposeNotifierProvider<AppSchemes, ColorSchemes>.internal(
|
|
||||||
AppSchemes.new,
|
|
||||||
name: r'appSchemesProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product') ? null : _$appSchemesHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef _$AppSchemes = AutoDisposeNotifier<ColorSchemes>;
|
|
||||||
String _$sortNumHash() => r'0f85ebbc77124020eaccf988c6ac9d86a7f34d7e';
|
String _$sortNumHash() => r'0f85ebbc77124020eaccf988c6ac9d86a7f34d7e';
|
||||||
|
|
||||||
/// See also [SortNum].
|
/// See also [SortNum].
|
||||||
|
|||||||
@@ -1765,7 +1765,7 @@ class _GetProfileOverrideDataProviderElement
|
|||||||
String get profileId => (origin as GetProfileOverrideDataProvider).profileId;
|
String get profileId => (origin as GetProfileOverrideDataProvider).profileId;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$genColorSchemeHash() => r'a27ccae9b5c11d47cd46804f42f8e9dc7946a6c2';
|
String _$genColorSchemeHash() => r'b18f15c938a8132ee4ed02cdfc02f3b9f01724e2';
|
||||||
|
|
||||||
/// See also [genColorScheme].
|
/// See also [genColorScheme].
|
||||||
@ProviderFor(genColorScheme)
|
@ProviderFor(genColorScheme)
|
||||||
@@ -1780,12 +1780,12 @@ class GenColorSchemeFamily extends Family<ColorScheme> {
|
|||||||
GenColorSchemeProvider call(
|
GenColorSchemeProvider call(
|
||||||
Brightness brightness, {
|
Brightness brightness, {
|
||||||
Color? color,
|
Color? color,
|
||||||
bool isOverride = false,
|
bool ignoreConfig = false,
|
||||||
}) {
|
}) {
|
||||||
return GenColorSchemeProvider(
|
return GenColorSchemeProvider(
|
||||||
brightness,
|
brightness,
|
||||||
color: color,
|
color: color,
|
||||||
isOverride: isOverride,
|
ignoreConfig: ignoreConfig,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1796,7 +1796,7 @@ class GenColorSchemeFamily extends Family<ColorScheme> {
|
|||||||
return call(
|
return call(
|
||||||
provider.brightness,
|
provider.brightness,
|
||||||
color: provider.color,
|
color: provider.color,
|
||||||
isOverride: provider.isOverride,
|
ignoreConfig: provider.ignoreConfig,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1821,13 +1821,13 @@ class GenColorSchemeProvider extends AutoDisposeProvider<ColorScheme> {
|
|||||||
GenColorSchemeProvider(
|
GenColorSchemeProvider(
|
||||||
Brightness brightness, {
|
Brightness brightness, {
|
||||||
Color? color,
|
Color? color,
|
||||||
bool isOverride = false,
|
bool ignoreConfig = false,
|
||||||
}) : this._internal(
|
}) : this._internal(
|
||||||
(ref) => genColorScheme(
|
(ref) => genColorScheme(
|
||||||
ref as GenColorSchemeRef,
|
ref as GenColorSchemeRef,
|
||||||
brightness,
|
brightness,
|
||||||
color: color,
|
color: color,
|
||||||
isOverride: isOverride,
|
ignoreConfig: ignoreConfig,
|
||||||
),
|
),
|
||||||
from: genColorSchemeProvider,
|
from: genColorSchemeProvider,
|
||||||
name: r'genColorSchemeProvider',
|
name: r'genColorSchemeProvider',
|
||||||
@@ -1840,7 +1840,7 @@ class GenColorSchemeProvider extends AutoDisposeProvider<ColorScheme> {
|
|||||||
GenColorSchemeFamily._allTransitiveDependencies,
|
GenColorSchemeFamily._allTransitiveDependencies,
|
||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
color: color,
|
color: color,
|
||||||
isOverride: isOverride,
|
ignoreConfig: ignoreConfig,
|
||||||
);
|
);
|
||||||
|
|
||||||
GenColorSchemeProvider._internal(
|
GenColorSchemeProvider._internal(
|
||||||
@@ -1852,12 +1852,12 @@ class GenColorSchemeProvider extends AutoDisposeProvider<ColorScheme> {
|
|||||||
required super.from,
|
required super.from,
|
||||||
required this.brightness,
|
required this.brightness,
|
||||||
required this.color,
|
required this.color,
|
||||||
required this.isOverride,
|
required this.ignoreConfig,
|
||||||
}) : super.internal();
|
}) : super.internal();
|
||||||
|
|
||||||
final Brightness brightness;
|
final Brightness brightness;
|
||||||
final Color? color;
|
final Color? color;
|
||||||
final bool isOverride;
|
final bool ignoreConfig;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Override overrideWith(
|
Override overrideWith(
|
||||||
@@ -1874,7 +1874,7 @@ class GenColorSchemeProvider extends AutoDisposeProvider<ColorScheme> {
|
|||||||
debugGetCreateSourceHash: null,
|
debugGetCreateSourceHash: null,
|
||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
color: color,
|
color: color,
|
||||||
isOverride: isOverride,
|
ignoreConfig: ignoreConfig,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1889,7 +1889,7 @@ class GenColorSchemeProvider extends AutoDisposeProvider<ColorScheme> {
|
|||||||
return other is GenColorSchemeProvider &&
|
return other is GenColorSchemeProvider &&
|
||||||
other.brightness == brightness &&
|
other.brightness == brightness &&
|
||||||
other.color == color &&
|
other.color == color &&
|
||||||
other.isOverride == isOverride;
|
other.ignoreConfig == ignoreConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -1897,7 +1897,7 @@ class GenColorSchemeProvider extends AutoDisposeProvider<ColorScheme> {
|
|||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
hash = _SystemHash.combine(hash, brightness.hashCode);
|
hash = _SystemHash.combine(hash, brightness.hashCode);
|
||||||
hash = _SystemHash.combine(hash, color.hashCode);
|
hash = _SystemHash.combine(hash, color.hashCode);
|
||||||
hash = _SystemHash.combine(hash, isOverride.hashCode);
|
hash = _SystemHash.combine(hash, ignoreConfig.hashCode);
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
@@ -1912,8 +1912,8 @@ mixin GenColorSchemeRef on AutoDisposeProviderRef<ColorScheme> {
|
|||||||
/// The parameter `color` of this provider.
|
/// The parameter `color` of this provider.
|
||||||
Color? get color;
|
Color? get color;
|
||||||
|
|
||||||
/// The parameter `isOverride` of this provider.
|
/// The parameter `ignoreConfig` of this provider.
|
||||||
bool get isOverride;
|
bool get ignoreConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GenColorSchemeProviderElement
|
class _GenColorSchemeProviderElement
|
||||||
@@ -1925,7 +1925,7 @@ class _GenColorSchemeProviderElement
|
|||||||
@override
|
@override
|
||||||
Color? get color => (origin as GenColorSchemeProvider).color;
|
Color? get color => (origin as GenColorSchemeProvider).color;
|
||||||
@override
|
@override
|
||||||
bool get isOverride => (origin as GenColorSchemeProvider).isOverride;
|
bool get ignoreConfig => (origin as GenColorSchemeProvider).ignoreConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$profileOverrideStateHash() =>
|
String _$profileOverrideStateHash() =>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
import 'package:dynamic_color/dynamic_color.dart';
|
||||||
import 'package:fl_clash/common/common.dart';
|
import 'package:fl_clash/common/common.dart';
|
||||||
import 'package:fl_clash/enum/enum.dart';
|
import 'package:fl_clash/enum/enum.dart';
|
||||||
import 'package:fl_clash/models/models.dart';
|
import 'package:fl_clash/models/models.dart';
|
||||||
|
import 'package:fl_clash/state.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
@@ -511,7 +513,7 @@ ColorScheme genColorScheme(
|
|||||||
Ref ref,
|
Ref ref,
|
||||||
Brightness brightness, {
|
Brightness brightness, {
|
||||||
Color? color,
|
Color? color,
|
||||||
bool isOverride = false,
|
bool ignoreConfig = false,
|
||||||
}) {
|
}) {
|
||||||
final vm2 = ref.watch(
|
final vm2 = ref.watch(
|
||||||
themeSettingProvider.select(
|
themeSettingProvider.select(
|
||||||
@@ -521,11 +523,17 @@ ColorScheme genColorScheme(
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (color == null && (isOverride == true || vm2.a == null)) {
|
if (color == null && (ignoreConfig == true || vm2.a == null)) {
|
||||||
final colorSchemes = ref.watch(appSchemesProvider);
|
// if (globalState.corePalette != null) {
|
||||||
return colorSchemes.getColorSchemeForBrightness(
|
// return globalState.corePalette!.toColorScheme(brightness: brightness);
|
||||||
brightness,
|
// }
|
||||||
vm2.b,
|
return ColorScheme.fromSeed(
|
||||||
|
seedColor: globalState.corePalette
|
||||||
|
?.toColorScheme(brightness: brightness)
|
||||||
|
.primary ??
|
||||||
|
globalState.accentColor,
|
||||||
|
brightness: brightness,
|
||||||
|
dynamicSchemeVariant: vm2.b,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ColorScheme.fromSeed(
|
return ColorScheme.fromSeed(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:animations/animations.dart';
|
import 'package:animations/animations.dart';
|
||||||
|
import 'package:dynamic_color/dynamic_color.dart';
|
||||||
import 'package:fl_clash/clash/clash.dart';
|
import 'package:fl_clash/clash/clash.dart';
|
||||||
import 'package:fl_clash/common/theme.dart';
|
import 'package:fl_clash/common/theme.dart';
|
||||||
import 'package:fl_clash/enum/enum.dart';
|
import 'package:fl_clash/enum/enum.dart';
|
||||||
@@ -9,6 +10,7 @@ import 'package:fl_clash/plugins/service.dart';
|
|||||||
import 'package:fl_clash/widgets/dialog.dart';
|
import 'package:fl_clash/widgets/dialog.dart';
|
||||||
import 'package:fl_clash/widgets/scaffold.dart';
|
import 'package:fl_clash/widgets/scaffold.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:material_color_utilities/palettes/core_palette.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
@@ -21,6 +23,7 @@ typedef UpdateTasks = List<FutureOr Function()>;
|
|||||||
class GlobalState {
|
class GlobalState {
|
||||||
static GlobalState? _instance;
|
static GlobalState? _instance;
|
||||||
Map<Key, double> cacheScrollPosition = {};
|
Map<Key, double> cacheScrollPosition = {};
|
||||||
|
Map<Key, FixedMap<String, double>> cacheHeightMap = {};
|
||||||
bool isService = false;
|
bool isService = false;
|
||||||
Timer? timer;
|
Timer? timer;
|
||||||
Timer? groupsUpdateTimer;
|
Timer? groupsUpdateTimer;
|
||||||
@@ -31,6 +34,8 @@ class GlobalState {
|
|||||||
Function? updateCurrentDelayDebounce;
|
Function? updateCurrentDelayDebounce;
|
||||||
late Measure measure;
|
late Measure measure;
|
||||||
late CommonTheme theme;
|
late CommonTheme theme;
|
||||||
|
late Color accentColor;
|
||||||
|
CorePalette? corePalette;
|
||||||
DateTime? startTime;
|
DateTime? startTime;
|
||||||
UpdateTasks tasks = [];
|
UpdateTasks tasks = [];
|
||||||
final navigatorKey = GlobalKey<NavigatorState>();
|
final navigatorKey = GlobalKey<NavigatorState>();
|
||||||
@@ -55,9 +60,18 @@ class GlobalState {
|
|||||||
traffics: FixedList(30),
|
traffics: FixedList(30),
|
||||||
totalTraffic: Traffic(),
|
totalTraffic: Traffic(),
|
||||||
);
|
);
|
||||||
|
await _initDynamicColor();
|
||||||
await init();
|
await init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_initDynamicColor() async {
|
||||||
|
try {
|
||||||
|
corePalette = await DynamicColorPlugin.getCorePalette();
|
||||||
|
accentColor = await DynamicColorPlugin.getAccentColor() ??
|
||||||
|
Color(defaultPrimaryColor);
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
init() async {
|
init() async {
|
||||||
packageInfo = await PackageInfo.fromPlatform();
|
packageInfo = await PackageInfo.fromPlatform();
|
||||||
config = await preferences.getConfig() ??
|
config = await preferences.getConfig() ??
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ class PrimaryColorBox extends ConsumerWidget {
|
|||||||
genColorSchemeProvider(
|
genColorSchemeProvider(
|
||||||
themeData.brightness,
|
themeData.brightness,
|
||||||
color: primaryColor,
|
color: primaryColor,
|
||||||
isOverride: true,
|
ignoreConfig: true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Theme(
|
return Theme(
|
||||||
|
|||||||
73
lib/widgets/container.dart
Normal file
73
lib/widgets/container.dart
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class CommonSafeArea extends StatelessWidget {
|
||||||
|
const CommonSafeArea({
|
||||||
|
super.key,
|
||||||
|
this.left = true,
|
||||||
|
this.top = true,
|
||||||
|
this.right = true,
|
||||||
|
this.bottom = true,
|
||||||
|
this.minimum = EdgeInsets.zero,
|
||||||
|
this.maintainBottomViewPadding = false,
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
|
final bool left;
|
||||||
|
|
||||||
|
final bool top;
|
||||||
|
|
||||||
|
final bool right;
|
||||||
|
|
||||||
|
final bool bottom;
|
||||||
|
|
||||||
|
final EdgeInsets minimum;
|
||||||
|
|
||||||
|
final bool maintainBottomViewPadding;
|
||||||
|
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
assert(debugCheckHasMediaQuery(context));
|
||||||
|
EdgeInsets padding = MediaQuery.paddingOf(context);
|
||||||
|
final height = MediaQuery.of(context).size.height;
|
||||||
|
if (maintainBottomViewPadding) {
|
||||||
|
padding = padding.copyWith(
|
||||||
|
bottom: MediaQuery.viewPaddingOf(context).bottom,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final double realPaddingTop = padding.top > height * 0.5 ? 0 : padding.top;
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: math.max(left ? padding.left : 0.0, minimum.left),
|
||||||
|
top: math.max(top ? realPaddingTop : 0.0, minimum.top),
|
||||||
|
right: math.max(right ? padding.right : 0.0, minimum.right),
|
||||||
|
bottom: math.max(bottom ? padding.bottom : 0.0, minimum.bottom),
|
||||||
|
),
|
||||||
|
child: MediaQuery.removePadding(
|
||||||
|
context: context,
|
||||||
|
removeLeft: left,
|
||||||
|
removeTop: top,
|
||||||
|
removeRight: right,
|
||||||
|
removeBottom: bottom,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
|
super.debugFillProperties(properties);
|
||||||
|
properties
|
||||||
|
.add(FlagProperty('left', value: left, ifTrue: 'avoid left padding'));
|
||||||
|
properties
|
||||||
|
.add(FlagProperty('top', value: top, ifTrue: 'avoid top padding'));
|
||||||
|
properties.add(
|
||||||
|
FlagProperty('right', value: right, ifTrue: 'avoid right padding'));
|
||||||
|
properties.add(
|
||||||
|
FlagProperty('bottom', value: bottom, ifTrue: 'avoid bottom padding'));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -137,7 +137,7 @@ class DonutChartPainter extends CustomPainter {
|
|||||||
@override
|
@override
|
||||||
void paint(Canvas canvas, Size size) {
|
void paint(Canvas canvas, Size size) {
|
||||||
final center = Offset(size.width / 2, size.height / 2);
|
final center = Offset(size.width / 2, size.height / 2);
|
||||||
const strokeWidth = 10.0;
|
final strokeWidth = 10.0.ap;
|
||||||
final radius = min(size.width / 2, size.height / 2) - strokeWidth / 2;
|
final radius = min(size.width / 2, size.height / 2) - strokeWidth / 2;
|
||||||
|
|
||||||
final gapAngle = 2 * asin(strokeWidth * 1 / (2 * radius)) * 1.2;
|
final gapAngle = 2 * asin(strokeWidth * 1 / (2 * radius)) * 1.2;
|
||||||
|
|||||||
@@ -36,11 +36,13 @@ class FadeBox extends StatelessWidget {
|
|||||||
class FadeThroughBox extends StatelessWidget {
|
class FadeThroughBox extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final Alignment? alignment;
|
final Alignment? alignment;
|
||||||
|
final EdgeInsets? margin;
|
||||||
|
|
||||||
const FadeThroughBox({
|
const FadeThroughBox({
|
||||||
super.key,
|
super.key,
|
||||||
required this.child,
|
required this.child,
|
||||||
this.alignment,
|
this.alignment,
|
||||||
|
this.margin
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -52,6 +54,7 @@ class FadeThroughBox extends StatelessWidget {
|
|||||||
secondaryAnimation,
|
secondaryAnimation,
|
||||||
) {
|
) {
|
||||||
return Container(
|
return Container(
|
||||||
|
margin: margin,
|
||||||
alignment: alignment ?? Alignment.centerLeft,
|
alignment: alignment ?? Alignment.centerLeft,
|
||||||
child: FadeThroughTransition(
|
child: FadeThroughTransition(
|
||||||
animation: animation,
|
animation: animation,
|
||||||
|
|||||||
@@ -62,6 +62,22 @@ class OpenDelegate extends Delegate {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NextDelegate extends Delegate {
|
||||||
|
final Widget widget;
|
||||||
|
final String title;
|
||||||
|
final double? maxWidth;
|
||||||
|
final Widget? action;
|
||||||
|
final bool blur;
|
||||||
|
|
||||||
|
const NextDelegate({
|
||||||
|
required this.title,
|
||||||
|
required this.widget,
|
||||||
|
this.maxWidth,
|
||||||
|
this.action,
|
||||||
|
this.blur = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
class OptionsDelegate<T> extends Delegate {
|
class OptionsDelegate<T> extends Delegate {
|
||||||
final List<T> options;
|
final List<T> options;
|
||||||
final String title;
|
final String title;
|
||||||
@@ -138,6 +154,21 @@ class ListItem<T> extends StatelessWidget {
|
|||||||
this.tileTitleAlignment = ListTileTitleAlignment.center,
|
this.tileTitleAlignment = ListTileTitleAlignment.center,
|
||||||
}) : onTap = null;
|
}) : onTap = null;
|
||||||
|
|
||||||
|
const ListItem.next({
|
||||||
|
super.key,
|
||||||
|
required this.title,
|
||||||
|
this.subtitle,
|
||||||
|
this.leading,
|
||||||
|
this.padding = const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
this.trailing,
|
||||||
|
required NextDelegate this.delegate,
|
||||||
|
this.horizontalTitleGap,
|
||||||
|
this.dense,
|
||||||
|
this.titleTextStyle,
|
||||||
|
this.subtitleTextStyle,
|
||||||
|
this.tileTitleAlignment = ListTileTitleAlignment.center,
|
||||||
|
}) : onTap = null;
|
||||||
|
|
||||||
const ListItem.options({
|
const ListItem.options({
|
||||||
super.key,
|
super.key,
|
||||||
required this.title,
|
required this.title,
|
||||||
@@ -285,6 +316,34 @@ class ListItem<T> extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (delegate is NextDelegate) {
|
||||||
|
final nextDelegate = delegate as NextDelegate;
|
||||||
|
final child = SafeArea(
|
||||||
|
child: nextDelegate.widget,
|
||||||
|
);
|
||||||
|
|
||||||
|
return _buildListTile(
|
||||||
|
onTap: () {
|
||||||
|
showExtend(
|
||||||
|
context,
|
||||||
|
props: ExtendProps(
|
||||||
|
blur: nextDelegate.blur,
|
||||||
|
maxWidth: nextDelegate.maxWidth,
|
||||||
|
),
|
||||||
|
builder: (_, type) {
|
||||||
|
return AdaptiveSheetScaffold(
|
||||||
|
actions: [
|
||||||
|
if (nextDelegate.action != null) nextDelegate.action!,
|
||||||
|
],
|
||||||
|
type: type,
|
||||||
|
body: child,
|
||||||
|
title: nextDelegate.title,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
if (delegate is OptionsDelegate) {
|
if (delegate is OptionsDelegate) {
|
||||||
final optionsDelegate = delegate as OptionsDelegate<T>;
|
final optionsDelegate = delegate as OptionsDelegate<T>;
|
||||||
return _buildListTile(
|
return _buildListTile(
|
||||||
@@ -353,14 +412,11 @@ class ListItem<T> extends StatelessWidget {
|
|||||||
radioDelegate.onChanged!(radioDelegate.value);
|
radioDelegate.onChanged!(radioDelegate.value);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
leading: SizedBox(
|
leading: Radio<T>(
|
||||||
width: 32,
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
height: 32,
|
value: radioDelegate.value,
|
||||||
child: Radio<T>(
|
groupValue: radioDelegate.groupValue,
|
||||||
value: radioDelegate.value,
|
onChanged: radioDelegate.onChanged,
|
||||||
groupValue: radioDelegate.groupValue,
|
|
||||||
onChanged: radioDelegate.onChanged,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
trailing: trailing,
|
trailing: trailing,
|
||||||
);
|
);
|
||||||
@@ -466,6 +522,32 @@ List<Widget> generateSection({
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget generateSectionV2({
|
||||||
|
String? title,
|
||||||
|
required Iterable<Widget> items,
|
||||||
|
List<Widget>? actions,
|
||||||
|
bool separated = true,
|
||||||
|
}) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
if (items.isNotEmpty && title != null)
|
||||||
|
ListHeader(
|
||||||
|
title: title,
|
||||||
|
actions: actions,
|
||||||
|
),
|
||||||
|
CommonCard(
|
||||||
|
radius: 18,
|
||||||
|
type: CommonCardType.filled,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
...items,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
List<Widget> generateInfoSection({
|
List<Widget> generateInfoSection({
|
||||||
required Info info,
|
required Info info,
|
||||||
required Iterable<Widget> items,
|
required Iterable<Widget> items,
|
||||||
@@ -497,4 +579,4 @@ Widget generateListView(List<Widget> items) {
|
|||||||
bottom: 16,
|
bottom: 16,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
33
lib/widgets/notification.dart
Normal file
33
lib/widgets/notification.dart
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import 'package:fl_clash/models/config.dart';
|
||||||
|
import 'package:fl_clash/providers/config.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
class TextScaleNotification extends StatelessWidget {
|
||||||
|
final Widget child;
|
||||||
|
final Function(TextScale textScale) onNotification;
|
||||||
|
|
||||||
|
const TextScaleNotification({
|
||||||
|
super.key,
|
||||||
|
required this.child,
|
||||||
|
required this.onNotification,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Consumer(
|
||||||
|
builder: (_, ref, __) {
|
||||||
|
ref.listen(
|
||||||
|
themeSettingProvider.select((state) => state.textScale),
|
||||||
|
(prev, next) {
|
||||||
|
if (prev != next) {
|
||||||
|
onNotification(next);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return child;
|
||||||
|
},
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -125,25 +125,25 @@ class CommonScaffoldState extends State<CommonScaffold> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThemeData _appBarTheme(BuildContext context) {
|
Widget _buildSearchingAppBarTheme(Widget child) {
|
||||||
final ThemeData theme = Theme.of(context);
|
final ThemeData theme = Theme.of(context);
|
||||||
final ColorScheme colorScheme = theme.colorScheme;
|
final ColorScheme colorScheme = theme.colorScheme;
|
||||||
return theme.copyWith(
|
return Theme(
|
||||||
appBarTheme: AppBarTheme(
|
data: theme.copyWith(
|
||||||
systemOverlayStyle: colorScheme.brightness == Brightness.dark
|
appBarTheme: theme.appBarTheme.copyWith(
|
||||||
? SystemUiOverlayStyle.light
|
backgroundColor: colorScheme.brightness == Brightness.dark
|
||||||
: SystemUiOverlayStyle.dark,
|
? Colors.grey[900]
|
||||||
backgroundColor: colorScheme.brightness == Brightness.dark
|
: Colors.white,
|
||||||
? Colors.grey[900]
|
iconTheme: theme.primaryIconTheme.copyWith(color: Colors.grey),
|
||||||
: Colors.white,
|
titleTextStyle: theme.textTheme.titleLarge,
|
||||||
iconTheme: theme.primaryIconTheme.copyWith(color: Colors.grey),
|
toolbarTextStyle: theme.textTheme.bodyMedium,
|
||||||
titleTextStyle: theme.textTheme.titleLarge,
|
),
|
||||||
toolbarTextStyle: theme.textTheme.bodyMedium,
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
),
|
hintStyle: theme.inputDecorationTheme.hintStyle,
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
border: InputBorder.none,
|
||||||
hintStyle: theme.inputDecorationTheme.hintStyle,
|
),
|
||||||
border: InputBorder.none,
|
|
||||||
),
|
),
|
||||||
|
child: child,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,72 +318,66 @@ class CommonScaffoldState extends State<CommonScaffold> {
|
|||||||
child: appBar,
|
child: appBar,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return _isSearch
|
return _isSearch ? _buildSearchingAppBarTheme(appBar) : appBar;
|
||||||
? Theme(
|
|
||||||
data: _appBarTheme(context),
|
|
||||||
child: CommonPopScope(
|
|
||||||
onPop: () {
|
|
||||||
if (_isSearch) {
|
|
||||||
_handleExitSearching();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
child: appBar,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: appBar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PreferredSizeWidget _buildAppBar() {
|
PreferredSizeWidget _buildAppBar() {
|
||||||
return PreferredSize(
|
return PreferredSize(
|
||||||
preferredSize: const Size.fromHeight(kToolbarHeight),
|
preferredSize: const Size.fromHeight(kToolbarHeight),
|
||||||
child: Stack(
|
child: Theme(
|
||||||
alignment: Alignment.bottomCenter,
|
data: Theme.of(context).copyWith(
|
||||||
children: [
|
appBarTheme: AppBarTheme(
|
||||||
ValueListenableBuilder<AppBarState>(
|
systemOverlayStyle: SystemUiOverlayStyle(
|
||||||
valueListenable: _appBarState,
|
statusBarColor: Colors.transparent,
|
||||||
builder: (_, state, __) {
|
statusBarIconBrightness:
|
||||||
return _buildAppBarWrap(
|
Theme.of(context).brightness == Brightness.dark
|
||||||
AppBar(
|
? Brightness.light
|
||||||
centerTitle: widget.centerTitle ?? false,
|
: Brightness.dark,
|
||||||
systemOverlayStyle: SystemUiOverlayStyle(
|
systemNavigationBarIconBrightness:
|
||||||
statusBarColor: Colors.transparent,
|
Theme.of(context).brightness == Brightness.dark
|
||||||
statusBarIconBrightness:
|
? Brightness.light
|
||||||
Theme.of(context).brightness == Brightness.dark
|
: Brightness.dark,
|
||||||
? Brightness.light
|
systemNavigationBarColor: widget.bottomNavigationBar != null
|
||||||
: Brightness.dark,
|
? context.colorScheme.surfaceContainer
|
||||||
systemNavigationBarIconBrightness:
|
: context.colorScheme.surface,
|
||||||
Theme.of(context).brightness == Brightness.dark
|
systemNavigationBarDividerColor: Colors.transparent,
|
||||||
? Brightness.light
|
),
|
||||||
: Brightness.dark,
|
),
|
||||||
systemNavigationBarColor: widget.bottomNavigationBar != null
|
),
|
||||||
? context.colorScheme.surfaceContainer
|
child: widget.appBar ??
|
||||||
: context.colorScheme.surface,
|
Stack(
|
||||||
systemNavigationBarDividerColor: Colors.transparent,
|
alignment: Alignment.bottomCenter,
|
||||||
),
|
children: [
|
||||||
automaticallyImplyLeading: widget.automaticallyImplyLeading,
|
ValueListenableBuilder<AppBarState>(
|
||||||
leading: _buildLeading(),
|
valueListenable: _appBarState,
|
||||||
title: _buildTitle(state.searchState),
|
builder: (_, state, __) {
|
||||||
actions: _buildActions(
|
return _buildAppBarWrap(
|
||||||
state.searchState != null,
|
AppBar(
|
||||||
state.actions.isNotEmpty
|
centerTitle: widget.centerTitle ?? false,
|
||||||
? state.actions
|
automaticallyImplyLeading:
|
||||||
: widget.actions ?? [],
|
widget.automaticallyImplyLeading,
|
||||||
),
|
leading: _buildLeading(),
|
||||||
|
title: _buildTitle(state.searchState),
|
||||||
|
actions: _buildActions(
|
||||||
|
state.searchState != null,
|
||||||
|
state.actions.isNotEmpty
|
||||||
|
? state.actions
|
||||||
|
: widget.actions ?? [],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
);
|
ValueListenableBuilder(
|
||||||
},
|
valueListenable: _loading,
|
||||||
),
|
builder: (_, value, __) {
|
||||||
ValueListenableBuilder(
|
return value == true
|
||||||
valueListenable: _loading,
|
? const LinearProgressIndicator()
|
||||||
builder: (_, value, __) {
|
: Container();
|
||||||
return value == true
|
},
|
||||||
? const LinearProgressIndicator()
|
),
|
||||||
: Container();
|
],
|
||||||
},
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -391,56 +385,62 @@ class CommonScaffoldState extends State<CommonScaffold> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
assert(widget.appBar != null || widget.title != null);
|
assert(widget.appBar != null || widget.title != null);
|
||||||
final body = Column(
|
final body = SafeArea(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
ValueListenableBuilder(
|
children: [
|
||||||
valueListenable: _keywordsNotifier,
|
ValueListenableBuilder(
|
||||||
builder: (_, keywords, __) {
|
valueListenable: _keywordsNotifier,
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
builder: (_, keywords, __) {
|
||||||
if (_onKeywordsUpdate != null) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_onKeywordsUpdate!(keywords);
|
if (_onKeywordsUpdate != null) {
|
||||||
|
_onKeywordsUpdate!(keywords);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (keywords.isEmpty) {
|
||||||
|
return SizedBox();
|
||||||
}
|
}
|
||||||
});
|
return Padding(
|
||||||
if (keywords.isEmpty) {
|
padding: const EdgeInsets.symmetric(
|
||||||
return SizedBox();
|
horizontal: 16,
|
||||||
}
|
vertical: 16,
|
||||||
return Padding(
|
),
|
||||||
padding: const EdgeInsets.symmetric(
|
child: Wrap(
|
||||||
horizontal: 16,
|
runSpacing: 8,
|
||||||
vertical: 16,
|
spacing: 8,
|
||||||
),
|
children: [
|
||||||
child: Wrap(
|
for (final keyword in keywords)
|
||||||
runSpacing: 8,
|
CommonChip(
|
||||||
spacing: 8,
|
label: keyword,
|
||||||
children: [
|
type: ChipType.delete,
|
||||||
for (final keyword in keywords)
|
onPressed: () {
|
||||||
CommonChip(
|
_deleteKeyword(keyword);
|
||||||
label: keyword,
|
},
|
||||||
type: ChipType.delete,
|
),
|
||||||
onPressed: () {
|
],
|
||||||
_deleteKeyword(keyword);
|
),
|
||||||
},
|
);
|
||||||
),
|
},
|
||||||
],
|
),
|
||||||
),
|
Expanded(
|
||||||
);
|
child: widget.body,
|
||||||
},
|
),
|
||||||
),
|
],
|
||||||
Expanded(
|
),
|
||||||
child: widget.body,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
final scaffold = Scaffold(
|
final scaffold = Scaffold(
|
||||||
appBar: widget.appBar ?? _buildAppBar(),
|
appBar: _buildAppBar(),
|
||||||
body: body,
|
body: body,
|
||||||
backgroundColor: widget.backgroundColor,
|
backgroundColor: widget.backgroundColor,
|
||||||
floatingActionButton: ValueListenableBuilder<Widget?>(
|
floatingActionButton: ValueListenableBuilder<Widget?>(
|
||||||
valueListenable: _floatingActionButton,
|
valueListenable: _floatingActionButton,
|
||||||
builder: (_, value, __) {
|
builder: (_, value, __) {
|
||||||
return FadeScaleBox(
|
return IntrinsicWidth(
|
||||||
child: value ?? SizedBox(),
|
child: IntrinsicHeight(
|
||||||
|
child: FadeScaleBox(
|
||||||
|
child: value ?? SizedBox(),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -369,6 +369,7 @@ class SuperGridState extends State<SuperGrid> with TickerProviderStateMixin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_handleDelete(int index) async {
|
_handleDelete(int index) async {
|
||||||
|
await _transformCompleter?.future;
|
||||||
_preTransformState();
|
_preTransformState();
|
||||||
final indexWhere = _tempIndexList.indexWhere((i) => i == index);
|
final indexWhere = _tempIndexList.indexWhere((i) => i == index);
|
||||||
_tempIndexList.removeAt(indexWhere);
|
_tempIndexList.removeAt(indexWhere);
|
||||||
@@ -484,9 +485,24 @@ class SuperGridState extends State<SuperGrid> with TickerProviderStateMixin {
|
|||||||
Widget _draggableWrap({
|
Widget _draggableWrap({
|
||||||
required Widget childWhenDragging,
|
required Widget childWhenDragging,
|
||||||
required Widget feedback,
|
required Widget feedback,
|
||||||
required Widget target,
|
required Widget item,
|
||||||
required int index,
|
required int index,
|
||||||
}) {
|
}) {
|
||||||
|
final target = DragTarget<int>(
|
||||||
|
builder: (_, __, ___) {
|
||||||
|
return AbsorbPointer(
|
||||||
|
child: item,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onWillAcceptWithDetails: (_) {
|
||||||
|
debouncer.call(
|
||||||
|
DebounceTag.handleWill,
|
||||||
|
_handleWill,
|
||||||
|
args: [index],
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
);
|
||||||
final shakeTarget = ValueListenableBuilder(
|
final shakeTarget = ValueListenableBuilder(
|
||||||
valueListenable: _dragIndexNotifier,
|
valueListenable: _dragIndexNotifier,
|
||||||
builder: (_, dragIndex, child) {
|
builder: (_, dragIndex, child) {
|
||||||
@@ -539,7 +555,7 @@ class SuperGridState extends State<SuperGrid> with TickerProviderStateMixin {
|
|||||||
valueListenable: isEditNotifier,
|
valueListenable: isEditNotifier,
|
||||||
builder: (_, isEdit, child) {
|
builder: (_, isEdit, child) {
|
||||||
if (!isEdit) {
|
if (!isEdit) {
|
||||||
return target;
|
return item;
|
||||||
}
|
}
|
||||||
return child!;
|
return child!;
|
||||||
},
|
},
|
||||||
@@ -558,12 +574,10 @@ class SuperGridState extends State<SuperGrid> with TickerProviderStateMixin {
|
|||||||
_itemContexts[index] = context;
|
_itemContexts[index] = context;
|
||||||
final childWhenDragging = ActivateBox(
|
final childWhenDragging = ActivateBox(
|
||||||
child: Opacity(
|
child: Opacity(
|
||||||
opacity: 0.3,
|
opacity: 0.6,
|
||||||
child: _sizeBoxWrap(
|
child: _sizeBoxWrap(
|
||||||
CommonCard(
|
CommonCard(
|
||||||
child: Container(
|
child: child,
|
||||||
color: context.colorScheme.secondaryContainer,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
index,
|
index,
|
||||||
),
|
),
|
||||||
@@ -580,25 +594,11 @@ class SuperGridState extends State<SuperGrid> with TickerProviderStateMixin {
|
|||||||
index,
|
index,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
final target = DragTarget<int>(
|
|
||||||
builder: (_, __, ___) {
|
|
||||||
return child;
|
|
||||||
},
|
|
||||||
onWillAcceptWithDetails: (_) {
|
|
||||||
debouncer.call(
|
|
||||||
DebounceTag.handleWill,
|
|
||||||
_handleWill,
|
|
||||||
args: [index],
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return _wrapTransform(
|
return _wrapTransform(
|
||||||
_draggableWrap(
|
_draggableWrap(
|
||||||
childWhenDragging: childWhenDragging,
|
childWhenDragging: childWhenDragging,
|
||||||
feedback: feedback,
|
feedback: feedback,
|
||||||
target: target,
|
item: child,
|
||||||
index: index,
|
index: index,
|
||||||
),
|
),
|
||||||
index,
|
index,
|
||||||
@@ -666,8 +666,7 @@ class SuperGridState extends State<SuperGrid> with TickerProviderStateMixin {
|
|||||||
crossAxisSpacing: widget.crossAxisSpacing,
|
crossAxisSpacing: widget.crossAxisSpacing,
|
||||||
mainAxisSpacing: widget.mainAxisSpacing,
|
mainAxisSpacing: widget.mainAxisSpacing,
|
||||||
children: [
|
children: [
|
||||||
for (int i = 0; i < children.length; i++)
|
for (int i = 0; i < children.length; i++) _builderItem(i),
|
||||||
_builderItem(i),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
1100
lib/widgets/tab.dart
Normal file
1100
lib/widgets/tab.dart
Normal file
File diff suppressed because it is too large
Load Diff
@@ -84,6 +84,7 @@ class EmojiText extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return RichText(
|
return RichText(
|
||||||
|
textScaler: MediaQuery.of(context).textScaler,
|
||||||
maxLines: maxLines,
|
maxLines: maxLines,
|
||||||
overflow: overflow ?? TextOverflow.clip,
|
overflow: overflow ?? TextOverflow.clip,
|
||||||
text: TextSpan(
|
text: TextSpan(
|
||||||
|
|||||||
@@ -30,3 +30,6 @@ export 'scroll.dart';
|
|||||||
export 'dialog.dart';
|
export 'dialog.dart';
|
||||||
export 'effect.dart';
|
export 'effect.dart';
|
||||||
export 'palette.dart';
|
export 'palette.dart';
|
||||||
|
export 'tab.dart';
|
||||||
|
export 'container.dart';
|
||||||
|
export 'notification.dart';
|
||||||
|
|||||||
@@ -843,7 +843,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.17"
|
version: "0.12.17"
|
||||||
material_color_utilities:
|
material_color_utilities:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: material_color_utilities
|
name: material_color_utilities
|
||||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: fl_clash
|
name: fl_clash
|
||||||
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
description: A multi-platform proxy client based on ClashMeta, simple and easy to use, open-source and ad-free.
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 0.8.82+202504182
|
version: 0.8.83+202504231
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.1.0 <4.0.0'
|
sdk: '>=3.1.0 <4.0.0'
|
||||||
|
|
||||||
@@ -53,6 +53,7 @@ dependencies:
|
|||||||
flutter_riverpod: ^2.6.1
|
flutter_riverpod: ^2.6.1
|
||||||
riverpod_annotation: ^2.6.1
|
riverpod_annotation: ^2.6.1
|
||||||
riverpod: ^2.6.1
|
riverpod: ^2.6.1
|
||||||
|
material_color_utilities: ^0.11.1
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
@@ -92,5 +93,5 @@ ffigen:
|
|||||||
flutter_intl:
|
flutter_intl:
|
||||||
enabled: true
|
enabled: true
|
||||||
class_name: AppLocalizations
|
class_name: AppLocalizations
|
||||||
arb_dir: lib/l10n/arb
|
arb_dir: arb
|
||||||
output_dir: lib/l10n
|
output_dir: lib/l10n
|
||||||
@@ -4,6 +4,7 @@ import requests
|
|||||||
|
|
||||||
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
TELEGRAM_BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
||||||
TAG = os.getenv("TAG")
|
TAG = os.getenv("TAG")
|
||||||
|
RUN_ID = os.getenv("RUN_ID")
|
||||||
|
|
||||||
IS_STABLE = "-" not in TAG
|
IS_STABLE = "-" not in TAG
|
||||||
|
|
||||||
@@ -45,7 +46,8 @@ if TAG:
|
|||||||
|
|
||||||
if IS_STABLE:
|
if IS_STABLE:
|
||||||
text += f"\nhttps://github.com/chen08209/FlClash/releases/tag/{TAG}\n"
|
text += f"\nhttps://github.com/chen08209/FlClash/releases/tag/{TAG}\n"
|
||||||
|
else:
|
||||||
|
text += f"\nhttps://github.com/chen08209/FlClash/actions/runs/{RUN_ID}\n"
|
||||||
|
|
||||||
if os.path.exists(release):
|
if os.path.exists(release):
|
||||||
text += "\n"
|
text += "\n"
|
||||||
|
|||||||
83
windows/packaging/exe/inno_setup.iss
Normal file
83
windows/packaging/exe/inno_setup.iss
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
[Setup]
|
||||||
|
AppId={{APP_ID}}
|
||||||
|
AppVersion={{APP_VERSION}}
|
||||||
|
AppName={{DISPLAY_NAME}}
|
||||||
|
AppPublisher={{PUBLISHER_NAME}}
|
||||||
|
AppPublisherURL={{PUBLISHER_URL}}
|
||||||
|
AppSupportURL={{PUBLISHER_URL}}
|
||||||
|
AppUpdatesURL={{PUBLISHER_URL}}
|
||||||
|
DefaultDirName={{INSTALL_DIR_NAME}}
|
||||||
|
DisableProgramGroupPage=yes
|
||||||
|
OutputDir=.
|
||||||
|
OutputBaseFilename={{OUTPUT_BASE_FILENAME}}
|
||||||
|
Compression=lzma
|
||||||
|
SolidCompression=yes
|
||||||
|
SetupIconFile={{SETUP_ICON_FILE}}
|
||||||
|
WizardStyle=modern
|
||||||
|
PrivilegesRequired={{PRIVILEGES_REQUIRED}}
|
||||||
|
ArchitecturesAllowed={{ARCH}}
|
||||||
|
ArchitecturesInstallIn64BitMode={{ARCH}}
|
||||||
|
|
||||||
|
[Code]
|
||||||
|
procedure KillProcesses;
|
||||||
|
var
|
||||||
|
Processes: TArrayOfString;
|
||||||
|
i: Integer;
|
||||||
|
ResultCode: Integer;
|
||||||
|
begin
|
||||||
|
Processes := ['FlClash.exe', 'FlClashCore.exe', 'FlClashHelperService.exe'];
|
||||||
|
|
||||||
|
for i := 0 to GetArrayLength(Processes)-1 do
|
||||||
|
begin
|
||||||
|
Exec('taskkill', '/f /im ' + Processes[i], '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function InitializeSetup(): Boolean;
|
||||||
|
begin
|
||||||
|
KillProcesses;
|
||||||
|
Result := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
[Languages]
|
||||||
|
{% for locale in LOCALES %}
|
||||||
|
{% if locale.lang == 'en' %}Name: "english"; MessagesFile: "compiler:Default.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'hy' %}Name: "armenian"; MessagesFile: "compiler:Languages\\Armenian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'bg' %}Name: "bulgarian"; MessagesFile: "compiler:Languages\\Bulgarian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'ca' %}Name: "catalan"; MessagesFile: "compiler:Languages\\Catalan.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'zh' %}
|
||||||
|
Name: "chineseSimplified"; MessagesFile: {% if locale.file %}{{ locale.file }}{% else %}"compiler:Languages\\ChineseSimplified.isl"{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if locale.lang == 'co' %}Name: "corsican"; MessagesFile: "compiler:Languages\\Corsican.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'cs' %}Name: "czech"; MessagesFile: "compiler:Languages\\Czech.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'da' %}Name: "danish"; MessagesFile: "compiler:Languages\\Danish.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'nl' %}Name: "dutch"; MessagesFile: "compiler:Languages\\Dutch.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'fi' %}Name: "finnish"; MessagesFile: "compiler:Languages\\Finnish.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'fr' %}Name: "french"; MessagesFile: "compiler:Languages\\French.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'de' %}Name: "german"; MessagesFile: "compiler:Languages\\German.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'he' %}Name: "hebrew"; MessagesFile: "compiler:Languages\\Hebrew.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'is' %}Name: "icelandic"; MessagesFile: "compiler:Languages\\Icelandic.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'it' %}Name: "italian"; MessagesFile: "compiler:Languages\\Italian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'ja' %}Name: "japanese"; MessagesFile: "compiler:Languages\\Japanese.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'no' %}Name: "norwegian"; MessagesFile: "compiler:Languages\\Norwegian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'pl' %}Name: "polish"; MessagesFile: "compiler:Languages\\Polish.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'pt' %}Name: "portuguese"; MessagesFile: "compiler:Languages\\Portuguese.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'ru' %}Name: "russian"; MessagesFile: "compiler:Languages\\Russian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'sk' %}Name: "slovak"; MessagesFile: "compiler:Languages\\Slovak.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'sl' %}Name: "slovenian"; MessagesFile: "compiler:Languages\\Slovenian.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'es' %}Name: "spanish"; MessagesFile: "compiler:Languages\\Spanish.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'tr' %}Name: "turkish"; MessagesFile: "compiler:Languages\\Turkish.isl"{% endif %}
|
||||||
|
{% if locale.lang == 'uk' %}Name: "ukrainian"; MessagesFile: "compiler:Languages\\Ukrainian.isl"{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
[Tasks]
|
||||||
|
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: {% if CREATE_DESKTOP_ICON != true %}unchecked{% else %}checkedonce{% endif %}
|
||||||
|
[Files]
|
||||||
|
Source: "{{SOURCE_DIR}}\\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
|
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||||
|
|
||||||
|
[Icons]
|
||||||
|
Name: "{autoprograms}\\{{DISPLAY_NAME}}"; Filename: "{app}\\{{EXECUTABLE_NAME}}"
|
||||||
|
Name: "{autodesktop}\\{{DISPLAY_NAME}}"; Filename: "{app}\\{{EXECUTABLE_NAME}}"; Tasks: desktopicon
|
||||||
|
[Run]
|
||||||
|
Filename: "{app}\\{{EXECUTABLE_NAME}}"; Description: "{cm:LaunchProgram,{{DISPLAY_NAME}}}"; Flags: {% if PRIVILEGES_REQUIRED == 'admin' %}runascurrentuser{% endif %} nowait postinstall skipifsilent
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
script_template: inno_setup.iss
|
||||||
app_id: 728B3532-C74B-4870-9068-BE70FE12A3E6
|
app_id: 728B3532-C74B-4870-9068-BE70FE12A3E6
|
||||||
app_name: FlClash
|
app_name: FlClash
|
||||||
publisher: chen08209
|
publisher: chen08209
|
||||||
@@ -9,4 +10,5 @@ setup_icon_file: ..\windows\runner\resources\app_icon.ico
|
|||||||
locales:
|
locales:
|
||||||
- lang: zh
|
- lang: zh
|
||||||
file: ..\windows\packaging\exe\ChineseSimplified.isl
|
file: ..\windows\packaging\exe\ChineseSimplified.isl
|
||||||
- lang: en
|
- lang: en
|
||||||
|
privileges_required: admin
|
||||||
Reference in New Issue
Block a user