Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip login type selection when logging in via intent #1267

Open
wants to merge 7 commits into
base: main-ose
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,14 @@ class LoginActivityTest {
assertEquals("user", loginInfo.credentials!!.username)
assertEquals("password", loginInfo.credentials.password)
}

@Test
fun loginInfoFromIntent_implicit_email() {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("mailto:[email protected]"))
val loginInfo = LoginActivity.loginInfoFromIntent(intent)
assertEquals(null, loginInfo.baseUri)
assertEquals("[email protected]", loginInfo.credentials!!.username)
assertEquals(null, loginInfo.credentials.password)
}

}
81 changes: 44 additions & 37 deletions app/src/main/kotlin/at/bitfire/davdroid/ui/setup/LoginActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,33 @@ import javax.inject.Inject
@AndroidEntryPoint
class LoginActivity @Inject constructor(): AppCompatActivity() {

@Inject lateinit var loginTypesProvider: LoginTypesProvider

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val initialLoginType = loginTypesProvider.intentToInitialLoginType(intent)
val skipLoginTypePage = initialLoginType != loginTypesProvider.defaultLoginType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The defaultLoginType is UrlLogin. So this means when

  1. the Intent's URL is https://example.com/
  2. initialLoginType == LoginUrl (login with URL; except when Nextcloud Flow extra is set) →
  3. skipLoginTypePage is always false.

However, it's clear that "Login with URL" should be chosen, so shouldn't it skip the login type too and go directly to "Login with URL"?


setContent {
LoginScreen(
initialLoginType = initialLoginType,
skipLoginTypePage = skipLoginTypePage,
initialLoginInfo = loginInfoFromIntent(intent),
onNavUp = { onSupportNavigateUp() },
onFinish = { newAccount ->
finish()

if (newAccount != null) {
val intent = Intent(this, AccountActivity::class.java)
intent.putExtra(AccountActivity.EXTRA_ACCOUNT, newAccount)
startActivity(intent)
}
}
)
}
}

companion object {

/**
Expand Down Expand Up @@ -59,18 +86,23 @@ class LoginActivity @Inject constructor(): AppCompatActivity() {
var givenUsername: String? = null
var givenPassword: String? = null

// extract URI and optionally username/password from Intent data
// extract URI or email and optionally username/password from Intent data
val logger = Logger.getGlobal()
intent.data?.normalizeScheme()?.let { uri ->
try {
val realScheme = when (uri.scheme) {
// replace caldav[s]:// and carddav[s]:// with http[s]://
val realScheme = when (uri.scheme) {
"caldav", "carddav" -> "http"
"caldavs", "carddavs", "davx5" -> "https"
"http", "https" -> uri.scheme
else -> null
}
if (realScheme != null) {
"caldav", "carddav" -> "http"
"caldavs", "carddavs", "davx5" -> "https"

// keep these
"http", "https", "mailto" -> uri.scheme

// unknown scheme
else -> null
}

when (realScheme) {
"http", "https" -> {
// extract user info
uri.userInfo?.split(':')?.let { userInfo ->
givenUsername = userInfo.getOrNull(0)
Expand All @@ -85,8 +117,9 @@ class LoginActivity @Inject constructor(): AppCompatActivity() {
null
}
}
} catch (_: URISyntaxException) {
logger.warning("Got invalid URI from login Intent: $uri")

"mailto" ->
givenUsername = uri.schemeSpecificPart
}
}

Expand Down Expand Up @@ -114,30 +147,4 @@ class LoginActivity @Inject constructor(): AppCompatActivity() {

}

@Inject lateinit var loginTypesProvider: LoginTypesProvider

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val (initialLoginType, skipLoginTypePage) = loginTypesProvider.intentToInitialLoginType(intent)

setContent {
LoginScreen(
initialLoginType = initialLoginType,
skipLoginTypePage = skipLoginTypePage,
initialLoginInfo = loginInfoFromIntent(intent),
onNavUp = { onSupportNavigateUp() },
onFinish = { newAccount ->
finish()

if (newAccount != null) {
val intent = Intent(this, AccountActivity::class.java)
intent.putExtra(AccountActivity.EXTRA_ACCOUNT, newAccount)
startActivity(intent)
}
}
)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ interface LoginTypesProvider {
val defaultLoginType: LoginType

/**
* Which login type to use and whether to skip the login type selection page. Used for Nextcloud
* login flow. May be used by other login flows.
* Which login type to use. Used for Nextcloud login flow and may be used for other intent started flows.
*/
fun intentToInitialLoginType(intent: Intent): Pair<LoginType, Boolean> = Pair(defaultLoginType, false)
fun intentToInitialLoginType(intent: Intent): LoginType = defaultLoginType

/** Whether the [LoginTypePage] may be non-interactive. This causes it to be skipped in back navigation. */
val maybeNonInteractive: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,19 @@ class StandardLoginTypesProvider @Inject constructor() : LoginTypesProvider {

override val defaultLoginType = UrlLogin

override fun intentToInitialLoginType(intent: Intent) =
if (intent.hasExtra(LoginActivity.EXTRA_LOGIN_FLOW))
Pair(NextcloudLogin, true)
else
Pair(defaultLoginType, false)
override fun intentToInitialLoginType(intent: Intent): LoginType =
intent.data?.normalizeScheme().let { uri ->
when {
intent.hasExtra(LoginActivity.EXTRA_LOGIN_FLOW) ->
NextcloudLogin
uri?.scheme == "mailto" ->
EmailLogin
listOf("caldavs", "carddavs", "davx5", "http", "https").any { uri?.scheme == it } ->
UrlLogin
else ->
defaultLoginType
}
}

@Composable
override fun LoginTypePage(
Expand Down