Compare commits
61 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c5d25c9dd5 | |||
| c65746709d | |||
| d2d9bdab02 | |||
| d0f8444b6d | |||
| fccabfbe27 | |||
| e9bb97c6ce | |||
| 068fe14d89 | |||
| 43c397007c | |||
| 5e801d5f5e | |||
| 52d61b15fd | |||
| fea3c14608 | |||
| 84be01a38a | |||
| 93da242148 | |||
| bb7e44da30 | |||
| 01f1b2d72f | |||
| 3074b1299e | |||
| bd5470b863 | |||
| 83fafa4b68 | |||
| b7fb969301 | |||
| 3ef3190785 | |||
| b1c763fcfa | |||
| 9452ffa514 | |||
| c9291e5027 | |||
| 3ba86dc9c2 | |||
| fd3040283c | |||
| 91d30c0f0e | |||
| c4b470ffaf | |||
| 9a07c785f2 | |||
| a134c32493 | |||
| 472cea9037 | |||
| 08d07498b9 | |||
| d5aa09949a | |||
| fd1dfe5c60 | |||
| 9f89fe8b29 | |||
| 78081a12e8 | |||
| 6896837f28 | |||
| 85eb903402 | |||
| 9aa9180f1f | |||
| feb9688a29 | |||
| 5c71992174 | |||
| 74c3d0ae25 | |||
| ecd1bcafd5 | |||
| 184d2d117a | |||
| 89e6f17794 | |||
| aef50fe0e3 | |||
| fc0767ed25 | |||
| dbf1724cca | |||
| 909aa4038e | |||
| 2d0a7d8d46 | |||
| ca96cd1d82 | |||
| 91ab1e5dac | |||
| b3a5f74df8 | |||
| 1f98be8ad8 | |||
| 453c7c98d0 | |||
| 91faed35c0 | |||
| 07bbaf6b6f | |||
| e8feb7c431 | |||
| 4d16820526 | |||
| 92294b49c6 | |||
| 8a188a37c9 | |||
| 48af16c265 |
@@ -17,8 +17,8 @@ jobs:
|
||||
os: windows-latest
|
||||
- platform: linux
|
||||
os: ubuntu-latest
|
||||
- platform: macos
|
||||
os: macos-13
|
||||
# - platform: macos
|
||||
# os: macos-13
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
@@ -34,6 +34,8 @@ on Mobile:
|
||||
|
||||
💡 Based on Material You Design, [Surfboard](https://github.com/getsurfboard/surfboard)-like UI
|
||||
|
||||
☁️ Supports data sync via WebDAV
|
||||
|
||||
✨ Support subscription link, Dark mode
|
||||
|
||||
## Contact
|
||||
|
||||
@@ -34,6 +34,8 @@ on Mobile:
|
||||
|
||||
💡 基本 Material You 设计, 类[Surfboard](https://github.com/getsurfboard/surfboard)用户界面
|
||||
|
||||
☁️ 支持通过WebDAV同步数据
|
||||
|
||||
✨ 支持一键导入订阅, 深色模式
|
||||
|
||||
## Contact
|
||||
|
||||
@@ -62,7 +62,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.follow.clash"
|
||||
minSdkVersion 21
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 34
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-feature
|
||||
android:name="android.software.leanback"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false" />
|
||||
@@ -17,8 +14,10 @@
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE"
|
||||
tools:ignore="SystemPermissionTypo" />
|
||||
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||
tools:ignore="QueryAllPackagesPermission" />
|
||||
|
||||
<application
|
||||
android:name="${applicationName}"
|
||||
@@ -73,7 +72,8 @@
|
||||
<service
|
||||
android:name=".services.FlClashTileService"
|
||||
android:exported="true"
|
||||
android:icon="@drawable/tile_icon"
|
||||
android:icon="@drawable/icon"
|
||||
android:foregroundServiceType="specialUse"
|
||||
android:label="FlClash"
|
||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
|
||||
<intent-filter>
|
||||
|
||||
@@ -19,7 +19,6 @@ import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.embedding.engine.dart.DartExecutor
|
||||
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
class FlClashTileService : TileService() {
|
||||
|
||||
private val observer = Observer<RunState> { runState ->
|
||||
@@ -43,19 +42,27 @@ class FlClashTileService : TileService() {
|
||||
GlobalState.runState.observeForever(observer)
|
||||
}
|
||||
|
||||
@SuppressLint("StartActivityAndCollapseDeprecated")
|
||||
private fun activityTransfer() {
|
||||
val intent = Intent(this, TempActivity::class.java)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
if (Build.VERSION.SDK_INT >= 34) {
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
val pendingIntent = if (Build.VERSION.SDK_INT >= 31) {
|
||||
PendingIntent.getActivity(
|
||||
this,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
startActivityAndCollapse(pendingIntent)
|
||||
} else {
|
||||
PendingIntent.getActivity(
|
||||
this,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
startActivityAndCollapse(pendingIntent)
|
||||
}else{
|
||||
startActivityAndCollapse(intent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package com.follow.clash.services
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification.FOREGROUND_SERVICE_IMMEDIATE
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
|
||||
import android.net.ProxyInfo
|
||||
@@ -13,15 +12,13 @@ import android.os.Binder
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import com.follow.clash.GlobalState
|
||||
import com.follow.clash.MainActivity
|
||||
import com.follow.clash.R
|
||||
import com.follow.clash.models.AccessControl
|
||||
import com.follow.clash.models.AccessControlMode
|
||||
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
class FlClashVpnService : VpnService() {
|
||||
|
||||
|
||||
@@ -100,10 +97,10 @@ class FlClashVpnService : VpnService() {
|
||||
}
|
||||
|
||||
|
||||
private val notificationBuilder by lazy {
|
||||
private val notificationBuilder: NotificationCompat.Builder by lazy {
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
|
||||
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
val pendingIntent = if (Build.VERSION.SDK_INT >= 31) {
|
||||
PendingIntent.getActivity(
|
||||
this,
|
||||
0,
|
||||
@@ -119,43 +116,43 @@ class FlClashVpnService : VpnService() {
|
||||
)
|
||||
}
|
||||
|
||||
val icon = IconCompat.createWithResource(this, this.applicationInfo.icon)
|
||||
|
||||
with(NotificationCompat.Builder(this, CHANNEL)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
setSmallIcon(icon)
|
||||
}
|
||||
setSmallIcon(R.drawable.ic_stat_name)
|
||||
setContentTitle("FlClash")
|
||||
foregroundServiceBehavior = FOREGROUND_SERVICE_IMMEDIATE
|
||||
setContentIntent(pendingIntent)
|
||||
setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
priority = NotificationCompat.PRIORITY_LOW
|
||||
priority = NotificationCompat.PRIORITY_MIN
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
foregroundServiceBehavior = FOREGROUND_SERVICE_IMMEDIATE
|
||||
}
|
||||
setOngoing(true)
|
||||
setShowWhen(false)
|
||||
setOnlyAlertOnce(true)
|
||||
setAutoCancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ForegroundServiceType", "WrongConstant")
|
||||
|
||||
fun startForeground(title: String, content: String) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val channel =
|
||||
NotificationChannel(CHANNEL, "FlClash", NotificationManager.IMPORTANCE_LOW)
|
||||
val manager = getSystemService(NotificationManager::class.java)
|
||||
manager.createNotificationChannel(channel)
|
||||
channel.setShowBadge(false)
|
||||
}
|
||||
val notification =
|
||||
notificationBuilder.setContentTitle(title).setContentText(content).build()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_SPECIAL_USE)
|
||||
} else {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
startForeground(notificationId, notification, FOREGROUND_SERVICE_TYPE_SPECIAL_USE)
|
||||
}else{
|
||||
startForeground(notificationId, notification)
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopForeground() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
stopForeground(Service.STOP_FOREGROUND_REMOVE)
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 763 B |
|
After Width: | Height: | Size: 520 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 105 KiB |
@@ -38,6 +38,7 @@ class _NetworkDetectionState extends State<NetworkDetection> {
|
||||
} else {
|
||||
timeoutNotifier.value = false;
|
||||
}
|
||||
_preIsStart = isStart;
|
||||
ipInfoNotifier.value = ipInfo;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
void main() async {
|
||||
String input = """
|
||||
您
|
||||
|
||||