MainActivity: bring activity to focus on login (#273)

Use CustomTabsIntent to launch login, but fall back to regular intent if Chrome is not installed
When logging in, on change in state to login complete, bring activity back to focus

Updates tailscale/corp#18202

Signed-off-by: kari-ts <kari@tailscale.com>
pull/276/head
kari-ts 2 months ago committed by GitHub
parent 1719d5d558
commit 9b27516e96
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -16,9 +16,11 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContract import androidx.activity.result.contract.ActivityResultContract
import androidx.browser.customtabs.CustomTabsIntent
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally import androidx.compose.animation.slideOutHorizontally
import androidx.core.net.toUri
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavType import androidx.navigation.NavType
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
@ -28,6 +30,7 @@ import androidx.navigation.navArgument
import androidx.navigation.navigation import androidx.navigation.navigation
import com.tailscale.ipn.Peer.RequestCodes import com.tailscale.ipn.Peer.RequestCodes
import com.tailscale.ipn.mdm.MDMSettings import com.tailscale.ipn.mdm.MDMSettings
import com.tailscale.ipn.ui.model.Ipn
import com.tailscale.ipn.ui.notifier.Notifier import com.tailscale.ipn.ui.notifier.Notifier
import com.tailscale.ipn.ui.theme.AppTheme import com.tailscale.ipn.ui.theme.AppTheme
import com.tailscale.ipn.ui.view.AboutView import com.tailscale.ipn.ui.view.AboutView
@ -52,6 +55,7 @@ import com.tailscale.ipn.ui.viewModel.ExitNodePickerNav
import com.tailscale.ipn.ui.viewModel.SettingsNav import com.tailscale.ipn.ui.viewModel.SettingsNav
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
@ -64,6 +68,7 @@ class MainActivity : ComponentActivity() {
@JvmStatic val requestPrepareVPN: Int = 1001 @JvmStatic val requestPrepareVPN: Int = 1001
const val WRITE_STORAGE_RESULT = 1000 const val WRITE_STORAGE_RESULT = 1000
private const val TAG = "Main Activity"
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -182,12 +187,43 @@ class MainActivity : ComponentActivity() {
} }
} }
private fun login(url: String) { private fun login(urlString: String) {
// (jonathan) TODO: This is functional, but the navigation doesn't quite work // Launch coroutine to listen for state changes. When the user completes login, relaunch
// as expected. There's probably a better built in way to do this. This will // MainActivity to bring the app back to focus.
// unblock in dev for the time being though. App.getApplication().applicationScope.launch {
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) try {
startActivity(browserIntent) Notifier.state.collect { state ->
if (state > Ipn.State.NeedsMachineAuth) {
val intent =
Intent(applicationContext, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
action = Intent.ACTION_MAIN
addCategory(Intent.CATEGORY_LAUNCHER)
}
startActivity(intent)
// Cancel coroutine once we've logged in
this@launch.cancel()
}
}
} catch (e: Exception) {
Log.e(TAG, "Login: failed to start MainActivity: $e")
}
}
val url = urlString.toUri()
try {
val customTabsIntent = CustomTabsIntent.Builder().build()
customTabsIntent.launchUrl(this, url)
} catch (e: Exception) {
// Fallback to a regular browser if CustomTabsIntent fails
try {
val fallbackIntent = Intent(Intent.ACTION_VIEW, url)
startActivity(fallbackIntent)
} catch (e: Exception) {
Log.e(TAG, "Login: failed to open browser: $e")
}
}
} }
override fun onResume() { override fun onResume() {

Loading…
Cancel
Save