mirror of
https://github.com/openlibrecommunity/olcng.git
synced 2026-07-03 14:05:17 +02:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| db511c9ab1 | |||
| 2623b3110b | |||
| 4bf125b4f5 | |||
| 50297d88cc | |||
| 2975b0cd1a | |||
| ea1f584422 | |||
| 73c81d02e7 |
@@ -167,5 +167,5 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
files: ${{ github.workspace }}/V2rayNG/app/build/outputs/apk/*/release/*.apk
|
files: ${{ github.workspace }}/V2rayNG/app/build/outputs/apk/*/release/*.apk
|
||||||
tag_name: ${{ github.event.inputs.release_tag || github.ref_name }}
|
tag_name: ${{ github.event.inputs.release_tag || github.ref_name }}
|
||||||
prerelease: true
|
prerelease: false
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
android:name="android.permission.QUERY_ALL_PACKAGES"
|
android:name="android.permission.QUERY_ALL_PACKAGES"
|
||||||
tools:ignore="PackageVisibilityPolicy,QueryAllPackagesPermission" />
|
tools:ignore="PackageVisibilityPolicy,QueryAllPackagesPermission" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
@@ -210,6 +211,16 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name=".receiver.ServiceControlReceiver"
|
||||||
|
android:exported="false"
|
||||||
|
android:process=":RunSoLibV2RayDaemon">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="${applicationId}.action.service.stop" />
|
||||||
|
<action android:name="${applicationId}.action.service.start" />
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
android:name=".service.QSTileService"
|
android:name=".service.QSTileService"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ object AppConfig {
|
|||||||
const val BROADCAST_ACTION_SERVICE = "$ANG_PACKAGE.action.service"
|
const val BROADCAST_ACTION_SERVICE = "$ANG_PACKAGE.action.service"
|
||||||
const val BROADCAST_ACTION_ACTIVITY = "$ANG_PACKAGE.action.activity"
|
const val BROADCAST_ACTION_ACTIVITY = "$ANG_PACKAGE.action.activity"
|
||||||
const val BROADCAST_ACTION_WIDGET_CLICK = "$ANG_PACKAGE.action.widget.click"
|
const val BROADCAST_ACTION_WIDGET_CLICK = "$ANG_PACKAGE.action.widget.click"
|
||||||
|
const val BROADCAST_ACTION_SERVICE_STOP = "$ANG_PACKAGE.action.service.stop"
|
||||||
|
const val BROADCAST_ACTION_SERVICE_START = "$ANG_PACKAGE.action.service.start"
|
||||||
|
|
||||||
/** Tasker extras. */
|
/** Tasker extras. */
|
||||||
const val TASKER_EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE"
|
const val TASKER_EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE"
|
||||||
|
|||||||
@@ -2,9 +2,12 @@ package xyz.zarazaex.olc.dto
|
|||||||
|
|
||||||
data class ServerAffiliationInfo(var testDelayMillis: Long = 0L) {
|
data class ServerAffiliationInfo(var testDelayMillis: Long = 0L) {
|
||||||
fun getTestDelayString(): String {
|
fun getTestDelayString(): String {
|
||||||
if (testDelayMillis == 0L) {
|
return when {
|
||||||
return ""
|
testDelayMillis == 0L -> ""
|
||||||
|
testDelayMillis < 0L -> "Error"
|
||||||
|
else -> "${testDelayMillis}ms"
|
||||||
}
|
}
|
||||||
return testDelayMillis.toString() + "ms"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isReachable(): Boolean = testDelayMillis > 0L
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ object V2RayServiceManager {
|
|||||||
private var currentConfig: ProfileItem? = null
|
private var currentConfig: ProfileItem? = null
|
||||||
private val operationLock = Any()
|
private val operationLock = Any()
|
||||||
@Volatile private var isOperationInProgress = false
|
@Volatile private var isOperationInProgress = false
|
||||||
|
@Volatile var isIntentionalStop = false
|
||||||
|
|
||||||
var serviceControl: SoftReference<ServiceControl>? = null
|
var serviceControl: SoftReference<ServiceControl>? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
@@ -49,6 +50,7 @@ object V2RayServiceManager {
|
|||||||
context.toast(R.string.app_tile_first_use)
|
context.toast(R.string.app_tile_first_use)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
isIntentionalStop = false
|
||||||
startContextService(context)
|
startContextService(context)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -74,6 +76,7 @@ object V2RayServiceManager {
|
|||||||
MmkvManager.setSelectServer(guid)
|
MmkvManager.setSelectServer(guid)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isIntentionalStop = false
|
||||||
startContextService(context)
|
startContextService(context)
|
||||||
} finally {
|
} finally {
|
||||||
synchronized(operationLock) {
|
synchronized(operationLock) {
|
||||||
@@ -87,8 +90,16 @@ object V2RayServiceManager {
|
|||||||
* @param context The context from which the service is stopped.
|
* @param context The context from which the service is stopped.
|
||||||
*/
|
*/
|
||||||
fun stopVService(context: Context) {
|
fun stopVService(context: Context) {
|
||||||
Log.i(AppConfig.TAG, "StartCore-Manager: stopVService called, serviceControl=${serviceControl?.get()}")
|
Log.i(AppConfig.TAG, "StartCore-Manager: stopVService called")
|
||||||
MessageUtil.sendMsg2Service(context, AppConfig.MSG_STATE_STOP, "")
|
isIntentionalStop = true
|
||||||
|
val svc = serviceControl?.get()
|
||||||
|
if (svc != null) {
|
||||||
|
svc.stopService()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val intent = Intent(AppConfig.BROADCAST_ACTION_SERVICE_STOP)
|
||||||
|
intent.setPackage(AppConfig.ANG_PACKAGE)
|
||||||
|
context.sendBroadcast(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -353,10 +364,24 @@ object V2RayServiceManager {
|
|||||||
override fun shutdown(): Long {
|
override fun shutdown(): Long {
|
||||||
val serviceControl = serviceControl?.get() ?: return -1
|
val serviceControl = serviceControl?.get() ?: return -1
|
||||||
return try {
|
return try {
|
||||||
serviceControl.stopService()
|
Log.w(AppConfig.TAG, "StartCore-Manager: Core shutdown callback, attempting restart")
|
||||||
|
val service = serviceControl.getService()
|
||||||
|
MessageUtil.sendMsg2UI(service, AppConfig.MSG_STATE_NOT_RUNNING, "")
|
||||||
|
if (isIntentionalStop) {
|
||||||
|
Log.i(AppConfig.TAG, "StartCore-Manager: Intentional stop, skipping restart")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
kotlinx.coroutines.delay(1000L)
|
||||||
|
val ctx = service.applicationContext
|
||||||
|
if (coreController.isRunning == false) {
|
||||||
|
Log.i(AppConfig.TAG, "StartCore-Manager: Restarting service after core shutdown")
|
||||||
|
startVService(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
0
|
0
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(AppConfig.TAG, "StartCore-Manager: Failed to stop service", e)
|
Log.e(AppConfig.TAG, "StartCore-Manager: Failed to handle core shutdown", e)
|
||||||
-1
|
-1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package xyz.zarazaex.olc.receiver
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import xyz.zarazaex.olc.AppConfig
|
||||||
|
import xyz.zarazaex.olc.handler.V2RayServiceManager
|
||||||
|
|
||||||
|
class ServiceControlReceiver : BroadcastReceiver() {
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
when (intent.action) {
|
||||||
|
AppConfig.BROADCAST_ACTION_SERVICE_STOP -> {
|
||||||
|
V2RayServiceManager.isIntentionalStop = true
|
||||||
|
V2RayServiceManager.stopVService(context)
|
||||||
|
}
|
||||||
|
AppConfig.BROADCAST_ACTION_SERVICE_START -> V2RayServiceManager.startVServiceFromToggle(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -77,50 +77,25 @@ class RealPingWorkerService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun startRealPing(guid: String): Long {
|
private suspend fun startRealPing(guid: String): Long {
|
||||||
val retFailure = -1L
|
|
||||||
val configResult = V2rayConfigManager.getV2rayConfig4Speedtest(context, guid)
|
val configResult = V2rayConfigManager.getV2rayConfig4Speedtest(context, guid)
|
||||||
if (!configResult.status) {
|
if (!configResult.status) return -1L
|
||||||
return retFailure
|
|
||||||
}
|
|
||||||
|
|
||||||
var bestDelay = retFailure
|
val urls = listOf(
|
||||||
|
SettingsManager.getDelayTestUrl(),
|
||||||
|
SettingsManager.getDelayTestUrl(true)
|
||||||
|
)
|
||||||
|
|
||||||
for (attempt in 0 until 2) {
|
for (url in urls) {
|
||||||
try {
|
try {
|
||||||
val delay = withTimeout(10000L) {
|
val delay = withTimeout(10000L) {
|
||||||
V2RayNativeManager.measureOutboundDelay(
|
V2RayNativeManager.measureOutboundDelay(configResult.content, url)
|
||||||
configResult.content,
|
|
||||||
SettingsManager.getDelayTestUrl()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delay > 0 && (bestDelay == retFailure || delay < bestDelay)) {
|
|
||||||
bestDelay = delay
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bestDelay > 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
if (attempt == 0) {
|
|
||||||
try {
|
|
||||||
val delay = withTimeout(10000L) {
|
|
||||||
V2RayNativeManager.measureOutboundDelay(
|
|
||||||
configResult.content,
|
|
||||||
SettingsManager.getDelayTestUrl(true)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delay > 0 && (bestDelay == retFailure || delay < bestDelay)) {
|
|
||||||
bestDelay = delay
|
|
||||||
}
|
|
||||||
} catch (_: Exception) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (delay > 0) return delay
|
||||||
|
} catch (_: Exception) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bestDelay
|
return -1L
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class V2RayProxyOnlyService : Service(), ServiceControl {
|
|||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
Log.i(AppConfig.TAG, "StartCore-Proxy: Service command received")
|
Log.i(AppConfig.TAG, "StartCore-Proxy: Service command received")
|
||||||
V2RayServiceManager.startCoreLoop(null)
|
V2RayServiceManager.startCoreLoop(null)
|
||||||
return START_STICKY
|
return START_NOT_STICKY
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import android.net.ProxyInfo
|
|||||||
import android.net.VpnService
|
import android.net.VpnService
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.ParcelFileDescriptor
|
import android.os.ParcelFileDescriptor
|
||||||
|
import android.os.PowerManager
|
||||||
import android.os.StrictMode
|
import android.os.StrictMode
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
@@ -35,6 +36,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
|||||||
private lateinit var mInterface: ParcelFileDescriptor
|
private lateinit var mInterface: ParcelFileDescriptor
|
||||||
private var isRunning = false
|
private var isRunning = false
|
||||||
private var tun2SocksService: Tun2SocksControl? = null
|
private var tun2SocksService: Tun2SocksControl? = null
|
||||||
|
private var wakeLock: PowerManager.WakeLock? = null
|
||||||
|
|
||||||
/**destroy
|
/**destroy
|
||||||
* Unfortunately registerDefaultNetworkCallback is going to return our VPN interface: https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e
|
* Unfortunately registerDefaultNetworkCallback is going to return our VPN interface: https://android.googlesource.com/platform/frameworks/base/+/dda156ab0c5d66ad82bdcf76cda07cbc0a9c8a2e
|
||||||
@@ -79,6 +81,9 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
|||||||
val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
|
val policy = StrictMode.ThreadPolicy.Builder().permitAll().build()
|
||||||
StrictMode.setThreadPolicy(policy)
|
StrictMode.setThreadPolicy(policy)
|
||||||
V2RayServiceManager.serviceControl = SoftReference(this)
|
V2RayServiceManager.serviceControl = SoftReference(this)
|
||||||
|
wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager)
|
||||||
|
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "v2rayng:vpn")
|
||||||
|
.also { it.acquire() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onRevoke() {
|
override fun onRevoke() {
|
||||||
@@ -94,16 +99,16 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
Log.i(AppConfig.TAG, "StartCore-VPN: Service destroyed")
|
Log.i(AppConfig.TAG, "StartCore-VPN: Service destroyed")
|
||||||
NotificationManager.cancelNotification()
|
stopAllService(false)
|
||||||
MessageUtil.sendMsg2UI(this, AppConfig.MSG_STATE_STOP_SUCCESS, "")
|
wakeLock?.let { if (it.isHeld) it.release() }
|
||||||
|
wakeLock = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
Log.i(AppConfig.TAG, "StartCore-VPN: Service command received")
|
Log.i(AppConfig.TAG, "StartCore-VPN: Service command received")
|
||||||
setupVpnService()
|
setupVpnService()
|
||||||
startService()
|
startService()
|
||||||
return START_STICKY
|
return START_NOT_STICKY
|
||||||
//return super.onStartCommand(intent, flags, startId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getService(): Service {
|
override fun getService(): Service {
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import xyz.zarazaex.olc.handler.SettingsChangeManager
|
|||||||
import xyz.zarazaex.olc.handler.SettingsManager
|
import xyz.zarazaex.olc.handler.SettingsManager
|
||||||
import xyz.zarazaex.olc.handler.UpdateCheckerManager
|
import xyz.zarazaex.olc.handler.UpdateCheckerManager
|
||||||
import xyz.zarazaex.olc.handler.V2RayServiceManager
|
import xyz.zarazaex.olc.handler.V2RayServiceManager
|
||||||
|
import xyz.zarazaex.olc.util.MessageUtil
|
||||||
import xyz.zarazaex.olc.util.Utils
|
import xyz.zarazaex.olc.util.Utils
|
||||||
import xyz.zarazaex.olc.viewmodel.MainViewModel
|
import xyz.zarazaex.olc.viewmodel.MainViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -147,7 +148,7 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
|
|||||||
setupGroupTab()
|
setupGroupTab()
|
||||||
setupViewModel()
|
setupViewModel()
|
||||||
mainViewModel.reloadServerList()
|
mainViewModel.reloadServerList()
|
||||||
importConfigViaSub()
|
importAllSubsOnStartup()
|
||||||
|
|
||||||
checkAndRequestPermission(PermissionType.POST_NOTIFICATIONS) {
|
checkAndRequestPermission(PermissionType.POST_NOTIFICATIONS) {
|
||||||
}
|
}
|
||||||
@@ -164,13 +165,15 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
|
|||||||
mainViewModel.sortByTestResults()
|
mainViewModel.sortByTestResults()
|
||||||
mainViewModel.reloadServerList()
|
mainViewModel.reloadServerList()
|
||||||
|
|
||||||
val firstServer = mainViewModel.serversCache.firstOrNull()
|
val firstReachable = mainViewModel.serversCache.firstOrNull { cache ->
|
||||||
if (firstServer != null) {
|
(MmkvManager.decodeServerAffiliationInfo(cache.guid)?.testDelayMillis ?: 0L) > 0L
|
||||||
MmkvManager.setSelectServer(firstServer.guid)
|
}
|
||||||
|
if (firstReachable != null) {
|
||||||
|
MmkvManager.setSelectServer(firstReachable.guid)
|
||||||
showStatus("Подключаемся к быстрейшему серверу")
|
showStatus("Подключаемся к быстрейшему серверу")
|
||||||
startV2RayWithPermission()
|
startV2RayWithPermission()
|
||||||
} else {
|
} else {
|
||||||
showStatus("Серверы не найдены!")
|
showStatus("Нет доступных серверов!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,20 +208,22 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
|
|||||||
}
|
}
|
||||||
isFabOperationInProgress = true
|
isFabOperationInProgress = true
|
||||||
|
|
||||||
|
val isRunning = mainViewModel.isRunning.value == true
|
||||||
|
|
||||||
applyRunningState(isLoading = true, isRunning = false)
|
applyRunningState(isLoading = true, isRunning = false)
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
try {
|
try {
|
||||||
if (mainViewModel.isRunning.value == true) {
|
if (isRunning) {
|
||||||
Log.d(AppConfig.TAG, "FAB: stopping service, isRunning=${mainViewModel.isRunning.value}")
|
Log.d(AppConfig.TAG, "FAB: stopping service")
|
||||||
V2RayServiceManager.stopVService(this@MainActivity)
|
V2RayServiceManager.stopVService(this@MainActivity)
|
||||||
} else {
|
} else {
|
||||||
Log.d(AppConfig.TAG, "FAB: starting service, isRunning=${mainViewModel.isRunning.value}")
|
Log.d(AppConfig.TAG, "FAB: starting service")
|
||||||
startV2RayWithPermission()
|
startV2RayWithPermission()
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(AppConfig.TAG, "FAB: error", e)
|
Log.e(AppConfig.TAG, "FAB: error", e)
|
||||||
applyRunningState(isLoading = false, isRunning = mainViewModel.isRunning.value ?: false)
|
applyRunningState(isLoading = false, isRunning = mainViewModel.isRunning.value == true)
|
||||||
} finally {
|
} finally {
|
||||||
isFabOperationInProgress = false
|
isFabOperationInProgress = false
|
||||||
}
|
}
|
||||||
@@ -367,6 +372,7 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
MessageUtil.sendMsg2Service(this, AppConfig.MSG_REGISTER_CLIENT, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
@@ -482,6 +488,20 @@ class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelect
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun importAllSubsOnStartup() {
|
||||||
|
showLoading()
|
||||||
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
val result = AngConfigManager.updateConfigViaSubAll()
|
||||||
|
delay(500L)
|
||||||
|
launch(Dispatchers.Main) {
|
||||||
|
if (result.configCount > 0) {
|
||||||
|
mainViewModel.reloadServerList()
|
||||||
|
showStatus(getString(R.string.title_update_config_count, result.configCount))
|
||||||
|
}
|
||||||
|
hideLoading()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* import config from sub
|
* import config from sub
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -96,7 +96,12 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
|
|||||||
val subServers = MmkvManager.decodeServerList(sub.guid)
|
val subServers = MmkvManager.decodeServerList(sub.guid)
|
||||||
subServers.forEach { guid ->
|
subServers.forEach { guid ->
|
||||||
val delay = MmkvManager.decodeServerAffiliationInfo(guid)?.testDelayMillis ?: 0L
|
val delay = MmkvManager.decodeServerAffiliationInfo(guid)?.testDelayMillis ?: 0L
|
||||||
allServers.add(ServerWithDelay(guid, if (delay <= 0L) 999999 else delay))
|
val sortKey = when {
|
||||||
|
delay > 0L -> delay
|
||||||
|
delay == 0L -> Long.MAX_VALUE - 1
|
||||||
|
else -> Long.MAX_VALUE
|
||||||
|
}
|
||||||
|
allServers.add(ServerWithDelay(guid, sortKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +487,12 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
|
|||||||
val serverList = MmkvManager.decodeServerList(sub.guid)
|
val serverList = MmkvManager.decodeServerList(sub.guid)
|
||||||
serverList.forEach { guid ->
|
serverList.forEach { guid ->
|
||||||
val delay = MmkvManager.decodeServerAffiliationInfo(guid)?.testDelayMillis ?: 0L
|
val delay = MmkvManager.decodeServerAffiliationInfo(guid)?.testDelayMillis ?: 0L
|
||||||
allServerDelays.add(ServerDelay(guid, if (delay <= 0L) 999999 else delay, sub.guid))
|
val sortKey = when {
|
||||||
|
delay > 0L -> delay
|
||||||
|
delay == 0L -> Long.MAX_VALUE - 1
|
||||||
|
else -> Long.MAX_VALUE
|
||||||
|
}
|
||||||
|
allServerDelays.add(ServerDelay(guid, sortKey, sub.guid))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -507,7 +517,12 @@ class MainViewModel(application: Application) : AndroidViewModel(application) {
|
|||||||
|
|
||||||
serverListToSort.forEach { key ->
|
serverListToSort.forEach { key ->
|
||||||
val delay = MmkvManager.decodeServerAffiliationInfo(key)?.testDelayMillis ?: 0L
|
val delay = MmkvManager.decodeServerAffiliationInfo(key)?.testDelayMillis ?: 0L
|
||||||
serverDelays.add(ServerDelay(key, if (delay <= 0L) 999999 else delay))
|
val sortKey = when {
|
||||||
|
delay > 0L -> delay
|
||||||
|
delay == 0L -> Long.MAX_VALUE - 1
|
||||||
|
else -> Long.MAX_VALUE
|
||||||
|
}
|
||||||
|
serverDelays.add(ServerDelay(key, sortKey))
|
||||||
}
|
}
|
||||||
serverDelays.sortBy { it.testDelayMillis }
|
serverDelays.sortBy { it.testDelayMillis }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user