Compare commits

..

2 Commits

Author SHA1 Message Date
zaneschepke 48a3ad64f4 chore: release 5.0.4 2026-06-20 13:13:19 -04:00
zaneschepke e5796d641d fix: auto tunnel rapid toggle bug
Improve notification efficiency
#1288
2026-06-20 12:33:25 -04:00
6 changed files with 29 additions and 11 deletions
@@ -27,13 +27,14 @@ import com.zaneschepke.wireguardautotunnel.util.Constants
import com.zaneschepke.wireguardautotunnel.util.extensions.to
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
@@ -77,13 +78,16 @@ class AutoTunnelService : LifecycleService() {
@Volatile private var hasUserOverride = false
private var lastNetworkFingerprint: AutoTunnelState.NetworkFingerprint? = null
@OptIn(FlowPreview::class)
private val autoTunnelStateFlow: Flow<AutoTunnelState> by lazy {
val networkFlow = networkEngine.stableState.mapNotNull { it?.state?.toDomain() }
val settingsFlow = combineSettings()
val backendFlow =
tunnelCoordinator.backendStatus.distinctUntilChangedBy { it.activeTunnels.keys.toSet() }
tunnelCoordinator.backendStatus
.distinctUntilChanged { old, new -> old.activeTunnels == new.activeTunnels }
.debounce(300L.milliseconds)
combine(networkFlow, settingsFlow, backendFlow) { network, settings, backend ->
AutoTunnelState(
+2 -2
View File
@@ -1,6 +1,6 @@
object Constants {
const val VERSION_NAME = "5.0.3"
const val VERSION_CODE = 50003
const val VERSION_NAME = "5.0.4"
const val VERSION_CODE = 50004
const val TARGET_SDK = 37
const val MIN_SDK = 26
@@ -0,0 +1,2 @@
What's new:
- Bugfix for auto tunnel rapid toggle
@@ -0,0 +1,13 @@
package com.zaneschepke.tunnel.service
import com.zaneschepke.tunnel.model.BackendMode
import com.zaneschepke.tunnel.state.BackendStatus
fun BackendStatus.toNotificationComparisonKey(): Any =
activeTunnels.mapValues { (_, tunnel) ->
Triple(
tunnel.transportState,
tunnel.bootstrapState,
tunnel.mode is BackendMode.Vpn || tunnel.mode is BackendMode.Proxy.KillSwitchPrimary,
)
} to (activeTunnels.keys to (killSwitch.enabled to dnsMode))
@@ -15,7 +15,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.launch
import org.koin.java.KoinJavaComponent.inject
import timber.log.Timber
@@ -61,12 +61,11 @@ class TunnelService : LifecycleService() {
private fun observeProxyPersistentNotification() {
lifecycleScope.launch {
backend.status
.distinctUntilChanged { old, new -> old.activeTunnels == new.activeTunnels }
.debounce(1_000.milliseconds)
.distinctUntilChangedBy { it.toNotificationComparisonKey() }
.debounce(700.milliseconds)
.collect { status ->
val notification =
backend.applicationProvider.buildProxyPersistentNotification(status)
notificationManager.notify(
backend.applicationProvider.proxyNotificationId,
notification,
@@ -10,7 +10,7 @@ import com.zaneschepke.tunnel.backend.Backend
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
import timber.log.Timber
@@ -43,8 +43,8 @@ class VpnCompanionService : LifecycleService() {
private fun observeVpnPersistentNotification() {
lifecycleScope.launch {
backend.status
.distinctUntilChanged { old, new -> old.activeTunnels == new.activeTunnels }
.debounce(1000.milliseconds)
.distinctUntilChangedBy { it.toNotificationComparisonKey() }
.debounce(700.milliseconds)
.collect { status ->
val notification =
backend.applicationProvider.buildVpnPersistentNotification(status)