allowing the re-emission of identical search terms, fixes the finish setup/give consent steps from not properly updating the UI

- also captures the fragmet resumed event in order to handle returning from the settings page and applying a identity server
This commit is contained in:
Adam Brown 2021-10-26 12:25:17 +01:00
parent c90dbf2f38
commit 10df75bd57
3 changed files with 35 additions and 7 deletions

View File

@ -25,4 +25,5 @@ sealed class UserListAction : VectorViewModelAction {
data class RemovePendingSelection(val pendingSelection: PendingSelection) : UserListAction() data class RemovePendingSelection(val pendingSelection: PendingSelection) : UserListAction()
object ComputeMatrixToLinkForSharing : UserListAction() object ComputeMatrixToLinkForSharing : UserListAction()
data class UpdateUserConsent(val consent: Boolean) : UserListAction() data class UpdateUserConsent(val consent: Boolean) : UserListAction()
object Resumed : UserListAction()
} }

View File

@ -222,6 +222,11 @@ class UserListFragment @Inject constructor(
) )
} }
override fun onResume() {
super.onResume()
viewModel.handle(UserListAction.Resumed)
}
override fun giveIdentityServerConsent() { override fun giveIdentityServerConsent() {
withState(viewModel) { state -> withState(viewModel) { state ->
requireContext().showIdentityServerConsentDialog( requireContext().showIdentityServerConsentDialog(

View File

@ -17,6 +17,7 @@
package im.vector.app.features.userdirectory package im.vector.app.features.userdirectory
import androidx.lifecycle.asFlow import androidx.lifecycle.asFlow
import com.airbnb.mvrx.Fail
import com.airbnb.mvrx.MavericksViewModelFactory import com.airbnb.mvrx.MavericksViewModelFactory
import com.airbnb.mvrx.Uninitialized import com.airbnb.mvrx.Uninitialized
import dagger.assisted.Assisted import dagger.assisted.Assisted
@ -40,6 +41,7 @@ import kotlinx.coroutines.flow.sample
import org.matrix.android.sdk.api.MatrixPatterns import org.matrix.android.sdk.api.MatrixPatterns
import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.extensions.tryOrNull
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.identity.IdentityServiceError
import org.matrix.android.sdk.api.session.identity.IdentityServiceListener import org.matrix.android.sdk.api.session.identity.IdentityServiceListener
import org.matrix.android.sdk.api.session.identity.ThreePid import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.profile.ProfileService import org.matrix.android.sdk.api.session.profile.ProfileService
@ -57,7 +59,7 @@ class UserListViewModel @AssistedInject constructor(@Assisted initialState: User
private val knownUsersSearch = MutableStateFlow("") private val knownUsersSearch = MutableStateFlow("")
private val directoryUsersSearch = MutableStateFlow("") private val directoryUsersSearch = MutableStateFlow("")
private val identityServerUsersSearch = MutableStateFlow("") private val identityServerUsersSearch = MutableStateFlow(UserSearch(searchTerm = ""))
@AssistedFactory @AssistedFactory
interface Factory : MavericksAssistedViewModelFactory<UserListViewModel, UserListViewState> { interface Factory : MavericksAssistedViewModelFactory<UserListViewModel, UserListViewState> {
@ -69,7 +71,7 @@ class UserListViewModel @AssistedInject constructor(@Assisted initialState: User
private val identityServerListener = object : IdentityServiceListener { private val identityServerListener = object : IdentityServiceListener {
override fun onIdentityServerChange() { override fun onIdentityServerChange() {
withState { withState {
identityServerUsersSearch.tryEmit(it.searchTerm) identityServerUsersSearch.tryEmit(UserSearch(it.searchTerm))
val identityServerURL = cleanISURL(session.identityService().getCurrentIdentityServerUrl()) val identityServerURL = cleanISURL(session.identityService().getCurrentIdentityServerUrl())
setState { setState {
copy(configuredIdentityServer = identityServerURL) copy(configuredIdentityServer = identityServerURL)
@ -105,16 +107,29 @@ class UserListViewModel @AssistedInject constructor(@Assisted initialState: User
is UserListAction.RemovePendingSelection -> handleRemoveSelectedUser(action) is UserListAction.RemovePendingSelection -> handleRemoveSelectedUser(action)
UserListAction.ComputeMatrixToLinkForSharing -> handleShareMyMatrixToLink() UserListAction.ComputeMatrixToLinkForSharing -> handleShareMyMatrixToLink()
is UserListAction.UpdateUserConsent -> handleISUpdateConsent(action) is UserListAction.UpdateUserConsent -> handleISUpdateConsent(action)
UserListAction.Resumed -> handleResumed()
}.exhaustive }.exhaustive
} }
private fun handleISUpdateConsent(action: UserListAction.UpdateUserConsent) { private fun handleISUpdateConsent(action: UserListAction.UpdateUserConsent) {
session.identityService().setUserConsent(action.consent) session.identityService().setUserConsent(action.consent)
withState { withState {
identityServerUsersSearch.tryEmit(it.searchTerm) retryUserSearch(it)
} }
} }
private fun handleResumed() {
withState {
if (it.hasNoIdentityServerConfigured()) {
retryUserSearch(it)
}
}
}
private fun retryUserSearch(state: UserListViewState) {
identityServerUsersSearch.tryEmit(UserSearch(state.searchTerm, cacheBuster = System.currentTimeMillis()))
}
private fun handleSearchUsers(searchTerm: String) { private fun handleSearchUsers(searchTerm: String) {
setState { setState {
copy( copy(
@ -130,7 +145,7 @@ class UserListViewModel @AssistedInject constructor(@Assisted initialState: User
) )
} }
} }
identityServerUsersSearch.tryEmit(searchTerm) identityServerUsersSearch.tryEmit(UserSearch(searchTerm))
knownUsersSearch.tryEmit(searchTerm) knownUsersSearch.tryEmit(searchTerm)
directoryUsersSearch.tryEmit(searchTerm) directoryUsersSearch.tryEmit(searchTerm)
} }
@ -144,7 +159,7 @@ class UserListViewModel @AssistedInject constructor(@Assisted initialState: User
private fun handleClearSearchUsers() { private fun handleClearSearchUsers() {
knownUsersSearch.tryEmit("") knownUsersSearch.tryEmit("")
directoryUsersSearch.tryEmit("") directoryUsersSearch.tryEmit("")
identityServerUsersSearch.tryEmit("") identityServerUsersSearch.tryEmit(UserSearch(""))
setState { setState {
copy(searchTerm = "") copy(searchTerm = "")
} }
@ -152,10 +167,10 @@ class UserListViewModel @AssistedInject constructor(@Assisted initialState: User
private fun observeUsers() = withState { state -> private fun observeUsers() = withState { state ->
identityServerUsersSearch identityServerUsersSearch
.filter { it.isEmail() } .filter { it.searchTerm.isEmail() }
.sample(300) .sample(300)
.onEach { search -> .onEach { search ->
executeSearchEmail(search) executeSearchEmail(search.searchTerm)
}.launchIn(viewModelScope) }.launchIn(viewModelScope)
knownUsersSearch knownUsersSearch
@ -239,3 +254,10 @@ class UserListViewModel @AssistedInject constructor(@Assisted initialState: User
setState { copy(pendingSelections = selections) } setState { copy(pendingSelections = selections) }
} }
} }
private fun UserListViewState.hasNoIdentityServerConfigured() = matchingEmail is Fail && matchingEmail.error == IdentityServiceError.NoIdentityServerConfigured
/**
* Wrapper class to allow identical search terms to be re-emitted
*/
private data class UserSearch(val searchTerm: String, val cacheBuster: Long = 0)