Get more info from WellKnown request.
This commit is contained in:
parent
5ed3164faf
commit
4df03762a8
11 changed files with 103 additions and 56 deletions
|
|
@ -21,4 +21,6 @@ data class AccountProvider constructor(
|
|||
val subtitle: String? = null,
|
||||
val isPublic: Boolean = false,
|
||||
val isMatrixOrg: Boolean = false,
|
||||
val isValid: Boolean = false,
|
||||
val supportSlidingSync: Boolean = false,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ open class AccountProviderProvider : PreviewParameterProvider<AccountProvider> {
|
|||
get() = sequenceOf(
|
||||
anAccountProvider(),
|
||||
anAccountProvider().copy(subtitle = null),
|
||||
anAccountProvider().copy(title = "Other", subtitle = null, isPublic = false, isMatrixOrg = false),
|
||||
anAccountProvider().copy(subtitle = null, title = "no.sliding.sync", supportSlidingSync = false),
|
||||
anAccountProvider().copy(subtitle = null, title = "invalid", isValid = false, supportSlidingSync = false),
|
||||
anAccountProvider().copy(subtitle = null, title = "Other", isPublic = false, isMatrixOrg = false),
|
||||
// Add other state here
|
||||
)
|
||||
}
|
||||
|
|
@ -33,4 +35,6 @@ fun anAccountProvider() = AccountProvider(
|
|||
subtitle = "Matrix.org is an open network for secure, decentralized communication.",
|
||||
isPublic = true,
|
||||
isMatrixOrg = true,
|
||||
isValid = true,
|
||||
supportSlidingSync = true,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ class ChangeAccountProviderPresenter @Inject constructor(
|
|||
subtitle = null,
|
||||
isPublic = true,
|
||||
isMatrixOrg = true,
|
||||
isValid = true,
|
||||
supportSlidingSync = true,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -39,23 +39,20 @@ fun aChangeAccountProviderFormState(
|
|||
|
||||
fun aHomeserverDataList(): List<HomeserverData> {
|
||||
return listOf(
|
||||
HomeserverData(
|
||||
userInput = "matrix",
|
||||
homeserverUrl = "https://matrix.org",
|
||||
isWellknownValid = true,
|
||||
),
|
||||
HomeserverData(
|
||||
userInput = "matrix",
|
||||
homeserverUrl = "https://matrix.io",
|
||||
isWellknownValid = false,
|
||||
)
|
||||
aHomeserverData(isWellknownValid = true, supportSlidingSync = true),
|
||||
aHomeserverData(homeserverUrl = "https://no.sliding.sync", isWellknownValid = true, supportSlidingSync = false),
|
||||
aHomeserverData(homeserverUrl = "https://invalid", isWellknownValid = false, supportSlidingSync = false),
|
||||
)
|
||||
}
|
||||
|
||||
fun aHomeserverData(): HomeserverData {
|
||||
fun aHomeserverData(
|
||||
homeserverUrl: String = "https://matrix.org",
|
||||
isWellknownValid: Boolean = true,
|
||||
supportSlidingSync: Boolean = true,
|
||||
): HomeserverData {
|
||||
return HomeserverData(
|
||||
userInput = "matrix",
|
||||
homeserverUrl = "https://matrix.org",
|
||||
isWellknownValid = true,
|
||||
homeserverUrl = homeserverUrl,
|
||||
isWellknownValid = isWellknownValid,
|
||||
supportSlidingSync = supportSlidingSync,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,13 +160,7 @@ fun ChangeAccountProviderFormView(
|
|||
}
|
||||
is Async.Success -> {
|
||||
state.userInputResult.state.forEach { homeserverData ->
|
||||
val isMatrixOrg = homeserverData.homeserverUrl == "https://matrix.org"
|
||||
val item = AccountProvider(
|
||||
title = homeserverData.homeserverUrl.removePrefix("http://").removePrefix("https://"),
|
||||
subtitle = if (isMatrixOrg) stringResource(id = R.string.screen_change_account_provider_matrix_org_subtitle) else null,
|
||||
isPublic = isMatrixOrg, // There is no need to know for other servers right now
|
||||
isMatrixOrg = isMatrixOrg,
|
||||
)
|
||||
val item = homeserverData.toAccountProvider()
|
||||
AccountProviderView(
|
||||
item = item,
|
||||
onClick = {
|
||||
|
|
@ -183,6 +177,19 @@ fun ChangeAccountProviderFormView(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HomeserverData.toAccountProvider(): AccountProvider {
|
||||
val isMatrixOrg = homeserverUrl == "https://matrix.org"
|
||||
return AccountProvider(
|
||||
title = homeserverUrl.removePrefix("http://").removePrefix("https://"),
|
||||
subtitle = if (isMatrixOrg) stringResource(id = R.string.screen_change_account_provider_matrix_org_subtitle) else null,
|
||||
isPublic = isMatrixOrg, // There is no need to know for other servers right now
|
||||
isMatrixOrg = isMatrixOrg,
|
||||
isValid = isWellknownValid,
|
||||
supportSlidingSync = supportSlidingSync,
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun ChangeAccountProviderFormViewLightPreview(@PreviewParameter(ChangeAccountProviderFormStateProvider::class) state: ChangeAccountProviderFormState) =
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import javax.inject.Inject
|
|||
class DefaultHomeserverResolver @Inject constructor(
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
private val wellknownRequest: WellknownRequest,
|
||||
): HomeserverResolver {
|
||||
) : HomeserverResolver {
|
||||
private val mutableFlow: MutableStateFlow<Async<List<HomeserverData>>> = MutableStateFlow(Async.Uninitialized)
|
||||
|
||||
override fun flow(): StateFlow<Async<List<HomeserverData>>> = mutableFlow
|
||||
|
|
@ -52,14 +52,14 @@ class DefaultHomeserverResolver @Inject constructor(
|
|||
|
||||
override suspend fun accept(userInput: String) {
|
||||
currentJob?.cancel()
|
||||
val cleanedUpUserInput = userInput.trim()
|
||||
val cleanedUpUserInput = userInput.trim().ensureProtocol().removeSuffix("/")
|
||||
mutableFlow.tryEmit(Async.Uninitialized)
|
||||
if (cleanedUpUserInput.length > 3) {
|
||||
delay(300)
|
||||
mutableFlow.tryEmit(Async.Loading())
|
||||
withContext(dispatchers.io) {
|
||||
val list = getUrlCandidate(cleanedUpUserInput)
|
||||
currentJob = resolveList(userInput, list)
|
||||
currentJob = resolveList(cleanedUpUserInput, list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -69,10 +69,18 @@ class DefaultHomeserverResolver @Inject constructor(
|
|||
return launch {
|
||||
list.map {
|
||||
async {
|
||||
val isValid = tryOrNull { wellknownRequest.execute(it) }.orFalse()
|
||||
val wellKnown = tryOrNull { wellknownRequest.execute(it) }
|
||||
val isValid = wellKnown?.isValid().orFalse()
|
||||
val supportSlidingSync = wellKnown?.supportSlidingSync().orFalse()
|
||||
if (isValid) {
|
||||
// Emit the list as soon as possible
|
||||
currentList.add(HomeserverData(userInput, it, true))
|
||||
currentList.add(
|
||||
HomeserverData(
|
||||
homeserverUrl = it,
|
||||
isWellknownValid = true,
|
||||
supportSlidingSync = supportSlidingSync
|
||||
)
|
||||
)
|
||||
mutableFlow.tryEmit(Async.Success(currentList))
|
||||
}
|
||||
}
|
||||
|
|
@ -85,9 +93,9 @@ class DefaultHomeserverResolver @Inject constructor(
|
|||
Async.Success(
|
||||
listOf(
|
||||
HomeserverData(
|
||||
userInput = userInput,
|
||||
homeserverUrl = userInput,
|
||||
isWellknownValid = false
|
||||
isWellknownValid = false,
|
||||
supportSlidingSync = false,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -102,18 +110,15 @@ class DefaultHomeserverResolver @Inject constructor(
|
|||
|
||||
private fun getUrlCandidate(data: String): List<String> {
|
||||
return buildList {
|
||||
val s = data.ensureProtocol()
|
||||
.removeSuffix("/")
|
||||
|
||||
// Always try what the user has entered
|
||||
add(s)
|
||||
add(data)
|
||||
|
||||
if (s.contains(".")) {
|
||||
if (data.contains(".")) {
|
||||
// TLD detected?
|
||||
} else {
|
||||
add("${s}.org")
|
||||
add("${s}.com")
|
||||
add("${s}.io")
|
||||
add("${data}.org")
|
||||
add("${data}.com")
|
||||
add("${data}.io")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@
|
|||
package io.element.android.features.login.impl.changeaccountprovider.form
|
||||
|
||||
data class HomeserverData constructor(
|
||||
// What the user has entered
|
||||
val userInput: String,
|
||||
// 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,
|
||||
// True if a wellknown file has been found and is valid and is claiming a sliding sync Url
|
||||
val supportSlidingSync: Boolean,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package io.element.android.features.login.impl.changeaccountprovider.form.network
|
||||
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
|
|
@ -28,6 +29,9 @@ import kotlinx.serialization.Serializable
|
|||
* },
|
||||
* "m.identity_server": {
|
||||
* "base_url": "https://vector.im"
|
||||
* },
|
||||
* "org.matrix.msc3575.proxy": {
|
||||
* "url": "https://slidingsync.lab.matrix.org"
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
|
|
@ -40,4 +44,15 @@ data class WellKnown(
|
|||
|
||||
@SerialName("m.identity_server")
|
||||
val identityServer: WellKnownBaseConfig? = null,
|
||||
)
|
||||
|
||||
@SerialName("org.matrix.msc3575.proxy")
|
||||
val slidingSyncProxy: WellKnownSlidingSyncConfig? = null,
|
||||
) {
|
||||
fun isValid(): Boolean {
|
||||
return homeServer?.baseURL?.isNotBlank().orFalse()
|
||||
}
|
||||
|
||||
fun supportSlidingSync(): Boolean {
|
||||
return slidingSyncProxy?.url?.isNotBlank().orFalse()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.login.impl.changeaccountprovider.form.network
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class WellKnownSlidingSyncConfig(
|
||||
@SerialName("url")
|
||||
val url: String? = null,
|
||||
)
|
||||
|
|
@ -15,32 +15,19 @@
|
|||
*/
|
||||
package io.element.android.features.login.impl.changeaccountprovider.form.network
|
||||
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.network.RetrofitFactory
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
class WellknownRequest @Inject constructor(
|
||||
private val retrofitFactory: RetrofitFactory,
|
||||
) {
|
||||
/**
|
||||
* Return true if the wellknown can be retrieved and is valid.
|
||||
* Return the WellKnown data, if found.
|
||||
* @param baseUrl for instance https://matrix.org
|
||||
*/
|
||||
suspend fun execute(baseUrl: String): Boolean {
|
||||
suspend fun execute(baseUrl: String): WellKnown {
|
||||
val wellknownApi = retrofitFactory.create(baseUrl)
|
||||
.create(WellknownAPI::class.java)
|
||||
|
||||
return try {
|
||||
val response = wellknownApi.getWellKnown()
|
||||
response.isValid()
|
||||
} catch (throwable: Throwable) {
|
||||
Timber.e(throwable)
|
||||
false
|
||||
}
|
||||
return wellknownApi.getWellKnown()
|
||||
}
|
||||
}
|
||||
|
||||
private fun WellKnown.isValid(): Boolean {
|
||||
return homeServer?.baseURL?.isNotBlank().orFalse()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ class ChangeAccountProviderPresenterTest {
|
|||
subtitle = null,
|
||||
isPublic = true,
|
||||
isMatrixOrg = true,
|
||||
isValid = true,
|
||||
supportSlidingSync = true,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue