Use the SDK Client to check whether a homeserver is compatible (#5664)
* Use the SDK `Client` to check whether a HS is compatible * Remove usage of unused `WellKnown`, keep `ElementWellKnown` * Make `HomeServerLoginCompatibilityChecker.check` return `true/false` values to distinguish non-valid homeservers from a failed check * Use `inMemoryStore` and `serverNameOrHomeserverUrl` * Do some cleanup of `isValid` and `isWellknownValid` * Make the debounce for starting the search a bit higher, as checking for the homeservers seems more resource-intensive now
This commit is contained in:
parent
0061b625f1
commit
015b497d5a
27 changed files with 195 additions and 341 deletions
|
|
@ -13,5 +13,4 @@ data class AccountProvider(
|
|||
val subtitle: String? = null,
|
||||
val isPublic: Boolean = false,
|
||||
val isMatrixOrg: Boolean = false,
|
||||
val isValid: Boolean = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ open class AccountProviderProvider : PreviewParameterProvider<AccountProvider> {
|
|||
get() = sequenceOf(
|
||||
anAccountProvider(),
|
||||
anAccountProvider().copy(subtitle = null),
|
||||
anAccountProvider().copy(subtitle = null, title = "invalid", isValid = false),
|
||||
anAccountProvider().copy(subtitle = null, title = "invalid"),
|
||||
anAccountProvider().copy(subtitle = null, title = "Other", isPublic = false, isMatrixOrg = false),
|
||||
// Add other state here
|
||||
)
|
||||
|
|
@ -26,11 +26,9 @@ fun anAccountProvider(
|
|||
subtitle: String? = "Matrix.org is an open network for secure, decentralized communication.",
|
||||
isPublic: Boolean = true,
|
||||
isMatrixOrg: Boolean = true,
|
||||
isValid: Boolean = true,
|
||||
) = AccountProvider(
|
||||
url = url,
|
||||
subtitle = subtitle,
|
||||
isPublic = isPublic,
|
||||
isMatrixOrg = isMatrixOrg,
|
||||
isValid = isValid,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,4 @@ package io.element.android.features.login.impl.resolver
|
|||
data class HomeserverData(
|
||||
// The computed homeserver url, for which a wellknown file has been retrieved, or just a valid Url
|
||||
val homeserverUrl: String,
|
||||
// True if a wellknown file has been found and is valid. If false, it means that the [homeserverUrl] is valid
|
||||
val isWellknownValid: Boolean,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,19 +8,16 @@
|
|||
package io.element.android.features.login.impl.resolver
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.core.coroutine.parallelMap
|
||||
import io.element.android.libraries.core.data.tryOrNull
|
||||
import io.element.android.libraries.core.uri.ensureProtocol
|
||||
import io.element.android.libraries.core.uri.isValidUrl
|
||||
import io.element.android.libraries.wellknown.api.WellKnown
|
||||
import io.element.android.libraries.wellknown.api.WellknownRetriever
|
||||
import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker
|
||||
import kotlinx.coroutines.currentCoroutineContext
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.coroutines.withTimeout
|
||||
import timber.log.Timber
|
||||
import java.util.Collections
|
||||
|
||||
/**
|
||||
|
|
@ -29,7 +26,7 @@ import java.util.Collections
|
|||
@Inject
|
||||
class HomeserverResolver(
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
private val wellknownRetriever: WellknownRetriever,
|
||||
private val homeServerLoginCompatibilityChecker: HomeServerLoginCompatibilityChecker,
|
||||
) {
|
||||
fun resolve(userInput: String): Flow<List<HomeserverData>> = flow {
|
||||
val flowContext = currentCoroutineContext()
|
||||
|
|
@ -41,20 +38,14 @@ class HomeserverResolver(
|
|||
// Run all the requests in parallel
|
||||
withContext(dispatchers.io) {
|
||||
list.parallelMap { url ->
|
||||
val wellKnown = tryOrNull {
|
||||
withTimeout(5000) {
|
||||
wellknownRetriever.getWellKnown(url)
|
||||
}
|
||||
}
|
||||
val isValid = wellKnown?.dataOrNull()?.isValid().orFalse()
|
||||
val isValid = homeServerLoginCompatibilityChecker.check(url)
|
||||
.onFailure { Timber.w(it, "Failed to check compatibility with homeserver $url") }
|
||||
.getOrNull()
|
||||
?: return@parallelMap
|
||||
|
||||
// Emit the list as soon as possible
|
||||
if (isValid) {
|
||||
// Emit the list as soon as possible
|
||||
currentList.add(
|
||||
HomeserverData(
|
||||
homeserverUrl = url,
|
||||
isWellknownValid = true,
|
||||
)
|
||||
)
|
||||
currentList.add(HomeserverData(homeserverUrl = url))
|
||||
withContext(flowContext) {
|
||||
emit(currentList.toList())
|
||||
}
|
||||
|
|
@ -63,14 +54,7 @@ class HomeserverResolver(
|
|||
}
|
||||
// If list is empty, and the user has entered an URL, do not block the user.
|
||||
if (currentList.isEmpty() && trimmedUserInput.isValidUrl()) {
|
||||
emit(
|
||||
listOf(
|
||||
HomeserverData(
|
||||
homeserverUrl = trimmedUserInput,
|
||||
isWellknownValid = false,
|
||||
)
|
||||
)
|
||||
)
|
||||
emit(listOf(HomeserverData(homeserverUrl = trimmedUserInput)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,7 +72,3 @@ class HomeserverResolver(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun WellKnown.isValid(): Boolean {
|
||||
return homeServer?.baseURL?.isNotBlank().orFalse()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ class ChangeAccountProviderPresenter(
|
|||
subtitle = null,
|
||||
isPublic = url == AuthenticationConfig.MATRIX_ORG_URL,
|
||||
isMatrixOrg = url == AuthenticationConfig.MATRIX_ORG_URL,
|
||||
isValid = true,
|
||||
)
|
||||
}
|
||||
.toImmutableList()
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ class ChooseAccountProviderPresenter(
|
|||
subtitle = null,
|
||||
isPublic = url == AuthenticationConfig.MATRIX_ORG_URL,
|
||||
isMatrixOrg = url == AuthenticationConfig.MATRIX_ORG_URL,
|
||||
isValid = true,
|
||||
)
|
||||
}
|
||||
.toImmutableList()
|
||||
|
|
|
|||
|
|
@ -57,14 +57,14 @@ class SearchAccountProviderPresenter(
|
|||
userInput = userInput,
|
||||
userInputResult = data.value,
|
||||
changeServerState = changeServerState,
|
||||
eventSink = ::handleEvents
|
||||
eventSink = ::handleEvents,
|
||||
)
|
||||
}
|
||||
|
||||
private fun CoroutineScope.onUserInput(userInput: String, data: MutableState<AsyncData<List<HomeserverData>>>) = launch {
|
||||
data.value = AsyncData.Uninitialized
|
||||
// Debounce
|
||||
delay(300)
|
||||
delay(500)
|
||||
data.value = AsyncData.Loading()
|
||||
homeserverResolver.resolve(userInput).collect {
|
||||
data.value = AsyncData.Success(it)
|
||||
|
|
|
|||
|
|
@ -34,18 +34,14 @@ fun aSearchAccountProviderState(
|
|||
|
||||
fun aHomeserverDataList(): List<HomeserverData> {
|
||||
return listOf(
|
||||
aHomeserverData(isWellknownValid = true),
|
||||
aHomeserverData(homeserverUrl = "https://no.sliding.sync", isWellknownValid = true),
|
||||
aHomeserverData(homeserverUrl = "https://invalid", isWellknownValid = false),
|
||||
aHomeserverData(homeserverUrl = AuthenticationConfig.MATRIX_ORG_URL),
|
||||
aHomeserverData(homeserverUrl = "https://no.sliding.sync"),
|
||||
aHomeserverData(homeserverUrl = "https://invalid"),
|
||||
)
|
||||
}
|
||||
|
||||
fun aHomeserverData(
|
||||
homeserverUrl: String = AuthenticationConfig.MATRIX_ORG_URL,
|
||||
isWellknownValid: Boolean = true,
|
||||
): HomeserverData {
|
||||
return HomeserverData(
|
||||
homeserverUrl = homeserverUrl,
|
||||
isWellknownValid = isWellknownValid,
|
||||
)
|
||||
return HomeserverData(homeserverUrl = homeserverUrl,)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,6 @@ private fun HomeserverData.toAccountProvider(): AccountProvider {
|
|||
// There is no need to know for other servers right now
|
||||
isPublic = isMatrixOrg,
|
||||
isMatrixOrg = isMatrixOrg,
|
||||
isValid = isWellknownValid,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue