android: prepare VPN when quick tile is clicked (#451)
Currently, the VPN is prepared when MainActivity is launched. If Tailscale is enabled by a quick tile, the VPN is not prepared. This change creates an application scoped view model and moves the VPN prep to the application class so that it is not dependent on MainActivity. Fixes tailscale/tailscale#12489 Signed-off-by: kari-ts <kari@tailscale.com>pull/470/head
parent
e6fc832494
commit
c6f3239b1b
@ -0,0 +1,48 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
package com.tailscale.ipn.ui.viewModel
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.net.VpnService
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
|
class VpnViewModelFactory(private val application: Application) : ViewModelProvider.Factory {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||||
|
if (modelClass.isAssignableFrom(VpnViewModel::class.java)) {
|
||||||
|
return VpnViewModel(application) as T
|
||||||
|
}
|
||||||
|
throw IllegalArgumentException("Unknown ViewModel class")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VpnViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
// Whether the VPN is prepared
|
||||||
|
val _vpnPrepared = MutableStateFlow(false)
|
||||||
|
val vpnPrepared: StateFlow<Boolean> = _vpnPrepared
|
||||||
|
|
||||||
|
init {
|
||||||
|
prepareVpn()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepareVpn() {
|
||||||
|
// Check if the user has granted permission yet.
|
||||||
|
if (!vpnPrepared.value) {
|
||||||
|
val vpnIntent = VpnService.prepare(getApplication())
|
||||||
|
if (vpnIntent != null) {
|
||||||
|
setVpnPrepared(false)
|
||||||
|
} else {
|
||||||
|
setVpnPrepared(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setVpnPrepared(prepared: Boolean) {
|
||||||
|
_vpnPrepared.value = prepared
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue