diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/MainActivity.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/MainActivity.kt index e1cde82a..965a16c1 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/MainActivity.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/MainActivity.kt @@ -67,7 +67,6 @@ import com.zaneschepke.wireguardautotunnel.ui.screens.support.LogsScreen import com.zaneschepke.wireguardautotunnel.ui.screens.support.SupportScreen import com.zaneschepke.wireguardautotunnel.ui.theme.WireguardAutoTunnelTheme import com.zaneschepke.wireguardautotunnel.util.Constants -import com.zaneschepke.wireguardautotunnel.util.extensions.requestAutoTunnelTileServiceUpdate import com.zaneschepke.wireguardautotunnel.viewmodel.AppViewModel import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -121,20 +120,14 @@ class MainActivity : AppCompatActivity() { viewModel.getEmitSplitTunnelApps(this@MainActivity) } - LaunchedEffect(appUiState.autoTunnelActive) { - requestAutoTunnelTileServiceUpdate() - } - with(appUiState.appSettings) { - LaunchedEffect(isAutoTunnelEnabled) { - this@MainActivity.requestAutoTunnelTileServiceUpdate() - } LaunchedEffect(isShortcutsEnabled) { if (!isShortcutsEnabled) return@LaunchedEffect shortcutManager.removeShortcuts() shortcutManager.addShortcuts() } } + // TODO could improve this to cancel when no tuns or autotun on ServiceWorker.start(this) CompositionLocalProvider(LocalNavController provides navController) { @@ -221,14 +214,14 @@ class MainActivity : AppCompatActivity() { composable { LogsScreen() } - composable { - val args = it.toRoute() + composable { backStack -> + val args = backStack.toRoute() val config = appUiState.tunnels.firstOrNull { it.id == args.id } ConfigScreen(config, viewModel) } - composable { - val args = it.toRoute() + composable { backStack -> + val args = backStack.toRoute() val config = appUiState.tunnels.first { it.id == args.id } OptionsScreen(config) } @@ -241,13 +234,13 @@ class MainActivity : AppCompatActivity() { composable { KillSwitchScreen(appUiState, viewModel) } - composable { - val args = it.toRoute() + composable { backStack -> + val args = backStack.toRoute() val config = appUiState.tunnels.first { it.id == args.id } SplitTunnelScreen(config, viewModel) } - composable { - val args = it.toRoute() + composable { backStack -> + val args = backStack.toRoute() val config = appUiState.tunnels.first { it.id == args.id } TunnelAutoTunnelScreen(config, appUiState.appSettings) } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/broadcast/KernelReceiver.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/broadcast/KernelReceiver.kt index aaebea1e..ce4b810f 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/broadcast/KernelReceiver.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/broadcast/KernelReceiver.kt @@ -32,8 +32,8 @@ class KernelReceiver : BroadcastReceiver() { val action = intent.action ?: return applicationScope.launch { if (action == REFRESH_TUNNELS_ACTION) { - tunnelManager.runningTunnelNames().forEach { - val tunnel = tunnelRepository.findByTunnelName(it) + tunnelManager.runningTunnelNames().forEach { name -> + val tunnel = tunnelRepository.findByTunnelName(name) tunnel?.let { tunnelRepository.save(it.copy(isActive = true)) } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/service/autotunnel/AutoTunnelService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/service/autotunnel/AutoTunnelService.kt index 423560d8..9731f3d6 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/service/autotunnel/AutoTunnelService.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/service/autotunnel/AutoTunnelService.kt @@ -187,7 +187,7 @@ class AutoTunnelService : LifecycleService() { buildNetworkState(it) }.distinctUntilChanged(), ) { double, networkState -> - AutoTunnelState(tunnelManager.activeTunnels().value, networkState, double.first, double.second) + AutoTunnelState(tunnelManager.activeTunnels.value, networkState, double.first, double.second) }.collect { state -> autoTunnelStateFlow.update { it.copy(activeTunnels = state.activeTunnels, networkState = state.networkState, settings = state.settings, tunnels = state.tunnels) diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/service/tile/TunnelControlTile.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/service/tile/TunnelControlTile.kt index 98c0b810..d006e69f 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/service/tile/TunnelControlTile.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/service/tile/TunnelControlTile.kt @@ -52,9 +52,14 @@ class TunnelControlTile : TileService() { } fun updateTileState() = applicationScope.launch { - if (appDataRepository.tunnels.getAll().isEmpty()) return@launch setUnavailable() - with(tunnelManager.activeTunnels().value) { - if (isNotEmpty()) return@launch updateTile(if (size == 1) first().tunName else getString(R.string.multiple), true) + val tunnels = appDataRepository.tunnels.getAll() + if (tunnels.isEmpty()) return@launch setUnavailable() + with(tunnelManager.activeTunnels.value) { + if (isNotEmpty()) if (size == 1) { + tunnels.firstOrNull { it.id == keys.first() }?.let { return@launch updateTile(it.tunName, true) } + } else { + return@launch updateTile(getString(R.string.multiple), true) + } } appDataRepository.getStartTunnelConfig()?.let { updateTile(it.tunName, false) @@ -65,7 +70,7 @@ class TunnelControlTile : TileService() { super.onClick() unlockAndRun { applicationScope.launch { - if (tunnelManager.activeTunnels().value.isNotEmpty()) return@launch tunnelManager.stopTunnel() + if (tunnelManager.activeTunnels.value.isNotEmpty()) return@launch tunnelManager.stopTunnel() appDataRepository.getStartTunnelConfig()?.let { tunnelManager.startTunnel(it) } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/BaseTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/BaseTunnel.kt index 546c4fbf..e867c220 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/BaseTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/BaseTunnel.kt @@ -14,6 +14,7 @@ import com.zaneschepke.wireguardautotunnel.domain.enums.BackendError import com.zaneschepke.wireguardautotunnel.domain.enums.BackendState import com.zaneschepke.wireguardautotunnel.domain.enums.TunnelStatus import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository +import com.zaneschepke.wireguardautotunnel.domain.state.TunnelState import com.zaneschepke.wireguardautotunnel.domain.state.TunnelStatistics import com.zaneschepke.wireguardautotunnel.ui.common.snackbar.SnackbarController import com.zaneschepke.wireguardautotunnel.util.Constants @@ -45,6 +46,8 @@ open class BaseTunnel( internal val tunnels = MutableStateFlow>(emptyList()) + private val _activeTunnels = MutableStateFlow>(emptyMap()) + private val tunnelJobs = mutableMapOf() private val isNetworkAvailable = AtomicBoolean(false) @@ -67,8 +70,9 @@ open class BaseTunnel( removedItems.forEach { tun -> tunnelJobs[tun]?.cancelWithMessage("Canceling tunnel jobs for tunnel: ${tun.name}") tunnelJobs.remove(tun) + _activeTunnels.update { it - tun.id } + serviceManager.updateTunnelTile() } - serviceManager.updateTunnelTile() } } } @@ -83,6 +87,9 @@ open class BaseTunnel( launch { startTunnelConfigChangeJob(tunnel) } + launch { + startStateJob(tunnel) + } } override suspend fun bounceTunnel(tunnelConf: TunnelConf) { @@ -99,14 +106,13 @@ open class BaseTunnel( return emptySet() } - override suspend fun activeTunnels(): StateFlow> { - return tunnels.asStateFlow() - } + override val activeTunnels: StateFlow> + get() = _activeTunnels.asStateFlow() override suspend fun startTunnel(tunnelConf: TunnelConf) { - if (tunnels.value.any { it.id == tunnelConf.id }) return Timber.w("Tunnel already running") serviceManager.startBackgroundService(tunnelConf) appDataRepository.tunnels.save(tunnelConf.copy(isActive = true)) + addToActiveTunnels(tunnelConf) } override suspend fun stopTunnel(tunnelConf: TunnelConf?) { @@ -131,7 +137,7 @@ open class BaseTunnel( } } - internal fun addToActiveTunnels(conf: TunnelConf) { + private fun addToActiveTunnels(conf: TunnelConf) { tunnels.update { it.toMutableList().apply { add(conf) @@ -153,13 +159,22 @@ open class BaseTunnel( } } + private suspend fun startStateJob(tunnel: TunnelConf) { + tunnel.state.collect { state -> + _activeTunnels.update { + it + (tunnel.id to state) + } + serviceManager.updateTunnelTile() + } + } + private suspend fun startPingJob(tunnel: TunnelConf) = coroutineScope { while (isActive) { if (isNetworkAvailable.get() && tunnel.isActive) { val pingResult = tunnel.pingTunnel(ioDispatcher) handlePingResult(tunnel, pingResult) } - delay(CHECK_INTERVAL) + delay(tunnel.pingInterval ?: Constants.PING_INTERVAL) } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/KernelTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/KernelTunnel.kt index 6a2ee43e..a35a9731 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/KernelTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/KernelTunnel.kt @@ -33,10 +33,10 @@ class KernelTunnel @Inject constructor( override suspend fun startTunnel(tunnelConf: TunnelConf) { withContext(ioDispatcher) { - super.startTunnel(tunnelConf) + if (tunnels.value.any { it.id == tunnelConf.id }) return@withContext Timber.w("Tunnel already running") runCatching { backend.setState(tunnelConf, Tunnel.State.UP, tunnelConf.toWgConfig()) - addToActiveTunnels(tunnelConf) + super.startTunnel(tunnelConf) }.onFailure { onTunnelStop(tunnelConf) if (it is BackendException) { @@ -66,8 +66,8 @@ class KernelTunnel @Inject constructor( } } - override suspend fun toggleTunnel(tunnelConf: TunnelConf, status: TunnelStatus) { - when (status) { + override suspend fun toggleTunnel(tunnelConf: TunnelConf, state: TunnelStatus) { + when (state) { TunnelStatus.UP -> backend.setState(tunnelConf, Tunnel.State.UP, tunnelConf.toWgConfig()) TunnelStatus.DOWN -> backend.setState(tunnelConf, Tunnel.State.DOWN, tunnelConf.toWgConfig()) } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelManager.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelManager.kt index 85bb47ad..8794581e 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelManager.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelManager.kt @@ -11,10 +11,12 @@ import com.zaneschepke.wireguardautotunnel.domain.repository.AppDataRepository import com.zaneschepke.wireguardautotunnel.util.extensions.withData import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.plus import kotlinx.coroutines.withContext @@ -34,14 +36,21 @@ class TunnelManager @Inject constructor( initialValue = null, ) - override suspend fun activeTunnels(): StateFlow> { - return withContext(ioDispatcher) { - appSettings.filterNotNull().first().let { - if (it.isKernelEnabled) return@withContext kernelTunnel.activeTunnels() - userspaceTunnel.activeTunnels() + @OptIn(ExperimentalCoroutinesApi::class) + override val activeTunnels = appSettings + .filterNotNull() + .flatMapLatest { settings -> + if (settings.isKernelEnabled) { + kernelTunnel.activeTunnels + } else { + userspaceTunnel.activeTunnels } } - } + .stateIn( + scope = applicationScope, + started = SharingStarted.Eagerly, + initialValue = emptyMap(), + ) override suspend fun startTunnel(tunnelConf: TunnelConf) { appSettings.withData { @@ -84,14 +93,14 @@ class TunnelManager @Inject constructor( if (isRestoreOnBootEnabled) { val previouslyActiveTuns = appDataRepository.tunnels.getActive() // handle kernel mode - val tunsToStart = previouslyActiveTuns.filterNot { tun -> activeTunnels().value.any { tun.id == it.id } } + val tunsToStart = previouslyActiveTuns.filterNot { tun -> activeTunnels.value.any { tun.id == it.key } } if (isKernelEnabled) { return@withContext tunsToStart.forEach { startTunnel(it) } } // handle userspace - if (activeTunnels().value.isEmpty()) tunsToStart.firstOrNull()?.let { startTunnel(it) } + if (activeTunnels.value.isEmpty()) tunsToStart.firstOrNull()?.let { startTunnel(it) } } } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelProvider.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelProvider.kt index 233d6bde..61cde555 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelProvider.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/TunnelProvider.kt @@ -2,11 +2,12 @@ package com.zaneschepke.wireguardautotunnel.core.tunnel import com.zaneschepke.wireguardautotunnel.domain.entity.TunnelConf import com.zaneschepke.wireguardautotunnel.domain.enums.BackendState +import com.zaneschepke.wireguardautotunnel.domain.state.TunnelState import kotlinx.coroutines.flow.StateFlow interface TunnelProvider { - suspend fun activeTunnels(): StateFlow> + val activeTunnels: StateFlow> suspend fun startTunnel(tunnelConf: TunnelConf) diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/UserspaceTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/UserspaceTunnel.kt index 7ed3b1c6..39c7a7d2 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/UserspaceTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/tunnel/UserspaceTunnel.kt @@ -34,10 +34,13 @@ class UserspaceTunnel @Inject constructor( override suspend fun startTunnel(tunnelConf: TunnelConf) { withContext(ioDispatcher) { - super.startTunnel(tunnelConf) + if (tunnels.value.any { it.id == tunnelConf.id }) return@withContext Timber.w("Tunnel already running") + if (tunnels.value.isNotEmpty()) { + stopAllTunnels() + } runCatching { backend.setState(tunnelConf, Tunnel.State.UP, tunnelConf.toAmConfig()) - addToActiveTunnels(tunnelConf) + super.startTunnel(tunnelConf) }.onFailure { onTunnelStop(tunnelConf) if (it is BackendException) { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/worker/ServiceWorker.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/worker/ServiceWorker.kt index 87bc8d04..33d6139b 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/worker/ServiceWorker.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/core/worker/ServiceWorker.kt @@ -53,7 +53,7 @@ class ServiceWorker @AssistedInject constructor( Timber.i("Service worker started") with(appDataRepository.settings.get()) { if (isAutoTunnelEnabled && !serviceManager.autoTunnelActive.value) return@with serviceManager.startAutoTunnel(true) - if (tunnelManager.activeTunnels().value.isEmpty()) tunnelManager.restorePreviousState() + if (tunnelManager.activeTunnels.value.isEmpty()) tunnelManager.restorePreviousState() } Result.success() } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/domain/state/AutoTunnelState.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/domain/state/AutoTunnelState.kt index 06ca2cf7..ca414e6e 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/domain/state/AutoTunnelState.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/domain/state/AutoTunnelState.kt @@ -7,7 +7,7 @@ import com.zaneschepke.wireguardautotunnel.domain.events.AutoTunnelEvent import com.zaneschepke.wireguardautotunnel.util.extensions.isMatchingToWildcardList data class AutoTunnelState( - val activeTunnels: List = emptyList(), + val activeTunnels: Map = emptyMap(), val networkState: NetworkState = NetworkState(), val settings: AppSettings = AppSettings(), val tunnels: List = emptyList(), @@ -20,12 +20,12 @@ data class AutoTunnelState( private fun isMobileTunnelDataChangeNeeded(): Boolean { val preferredTunnel = preferredMobileDataTunnel() return preferredTunnel != null && - activeTunnels.isNotEmpty() && !activeTunnels.any { it.id == preferredTunnel.id } + activeTunnels.isNotEmpty() && !activeTunnels.any { it.key == preferredTunnel.id } } private fun isEthernetTunnelChangeNeeded(): Boolean { val preferredTunnel = preferredEthernetTunnel() - return preferredTunnel != null && activeTunnels.isNotEmpty() && !activeTunnels.any { it.id == preferredTunnel.id } + return preferredTunnel != null && activeTunnels.isNotEmpty() && !activeTunnels.any { it.key == preferredTunnel.id } } private fun preferredMobileDataTunnel(): TunnelConf? { @@ -62,7 +62,7 @@ data class AutoTunnelState( return settings.isVpnKillSwitchEnabled && (!settings.isDisableKillSwitchOnTrustedEnabled || !isCurrentSSIDTrusted()) } - fun isNoConnectivity(): Boolean { + private fun isNoConnectivity(): Boolean { return !networkState.isEthernetConnected && !networkState.isWifiConnected && !networkState.isMobileDataConnected } @@ -100,7 +100,7 @@ data class AutoTunnelState( private fun isWifiTunnelPreferred(): Boolean { val preferred = preferredWifiTunnel() - return activeTunnels.any { it.id == preferred?.id } + return activeTunnels.any { it.key == preferred?.id } } fun asAutoTunnelEvent(): AutoTunnelEvent { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt index 027fd789..fc76e19f 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt @@ -77,7 +77,7 @@ fun MainScreen(viewModel: MainViewModel = hiltViewModel(), uiState: AppUiState) var selectedTunnel by remember { mutableStateOf(null) } val isRunningOnTv = remember { context.isRunningOnTv() } - val activeTunnels by viewModel.activeTunnels.collectAsStateWithLifecycle(emptyList()) + val activeTunnels by viewModel.tunnelManager.activeTunnels.collectAsStateWithLifecycle(emptyMap()) val collator = Collator.getInstance(Locale.getDefault()) @@ -89,6 +89,7 @@ fun MainScreen(viewModel: MainViewModel = hiltViewModel(), uiState: AppUiState) val startTunnel = withVpnPermission { viewModel.onTunnelStart(it) } + val autoTunnelToggleBattery = withIgnoreBatteryOpt(uiState.generalState.isBatteryOptimizationDisableShown) { if (!uiState.generalState.isBatteryOptimizationDisableShown) viewModel.setBatteryOptimizeDisableShown() if (uiState.appSettings.isKernelEnabled) { @@ -132,15 +133,8 @@ fun MainScreen(viewModel: MainViewModel = hiltViewModel(), uiState: AppUiState) } fun onTunnelToggle(checked: Boolean, tunnel: TunnelConf) { - if (!checked) { - viewModel.onTunnelStop(tunnel) - return - } - if (uiState.appSettings.isKernelEnabled) { - viewModel.onTunnelStart(tunnel) - } else { - startTunnel.invoke(tunnel) - } + if (!checked) return viewModel.onTunnelStop(tunnel).let { } + if (uiState.appSettings.isKernelEnabled) viewModel.onTunnelStart(tunnel) else startTunnel(tunnel) } Scaffold( @@ -233,13 +227,13 @@ fun MainScreen(viewModel: MainViewModel = hiltViewModel(), uiState: AppUiState) key = { tunnel -> tunnel.id }, ) { tunnel -> val expanded = uiState.generalState.isTunnelStatsExpanded - val tunnelState = activeTunnels.firstOrNull { it.id == tunnel.id }?.state?.collectAsStateWithLifecycle() + val tunnelState = activeTunnels.getOrDefault(tunnel.id, TunnelState()) TunnelRowItem( - tunnel.isActive, + tunnelState.state.isUp(), expanded, selectedTunnel?.id == tunnel.id, tunnel, - tunnelState = tunnelState?.value ?: TunnelState(), + tunnelState = tunnelState, { selectedTunnel = tunnel }, { viewModel.onExpandedChanged(!expanded) }, onDelete = { showDeleteTunnelAlertDialog = true }, diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/AppViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/AppViewModel.kt index 879b4413..4446141e 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/AppViewModel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/AppViewModel.kt @@ -109,8 +109,8 @@ constructor( } private suspend fun initTunnels() { - tunnels.withData { - it.filter { it.isActive }.forEach { + tunnels.withData { tunnels -> + tunnels.filter { it.isActive }.forEach { tunnelManager.startTunnel(it) } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/MainViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/MainViewModel.kt index edf33751..d80ff3ed 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/viewmodel/MainViewModel.kt @@ -24,8 +24,6 @@ import com.zaneschepke.wireguardautotunnel.util.extensions.toWgQuickString import com.zaneschepke.wireguardautotunnel.util.extensions.withData import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.amnezia.awg.config.Config @@ -44,15 +42,6 @@ constructor( appDataRepository: AppDataRepository, ) : BaseViewModel(appDataRepository) { - private val _activeTunnels = MutableStateFlow>(emptyList()) - val activeTunnels = _activeTunnels.asStateFlow() - - init { - viewModelScope.launch { - tunnelManager.activeTunnels().collect(_activeTunnels::emit) - } - } - fun onDelete(tunnel: TunnelConf) = viewModelScope.launch { appSettings.withData { settings -> tunnels.withData {