Better error handling Rx call
This commit is contained in:
parent
baef9f5aa7
commit
6146925757
@ -33,7 +33,9 @@ import org.matrix.android.sdk.api.MatrixPatterns
|
|||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
import org.matrix.android.sdk.api.session.profile.ProfileService
|
import org.matrix.android.sdk.api.session.profile.ProfileService
|
||||||
import org.matrix.android.sdk.api.session.user.model.User
|
import org.matrix.android.sdk.api.session.user.model.User
|
||||||
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||||
|
import org.matrix.android.sdk.api.util.toOptional
|
||||||
import org.matrix.android.sdk.rx.rx
|
import org.matrix.android.sdk.rx.rx
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@ -57,9 +59,6 @@ class UserListViewModel @AssistedInject constructor(@Assisted initialState: User
|
|||||||
|
|
||||||
companion object : MvRxViewModelFactory<UserListViewModel, UserListViewState> {
|
companion object : MvRxViewModelFactory<UserListViewModel, UserListViewState> {
|
||||||
|
|
||||||
private val USER_NOT_FOUND_MAP = emptyMap<String, Any>()
|
|
||||||
private val USER_NOT_FOUND = User("")
|
|
||||||
|
|
||||||
override fun create(viewModelContext: ViewModelContext, state: UserListViewState): UserListViewModel? {
|
override fun create(viewModelContext: ViewModelContext, state: UserListViewState): UserListViewModel? {
|
||||||
val factory = when (viewModelContext) {
|
val factory = when (viewModelContext) {
|
||||||
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
|
is FragmentViewModelContext -> viewModelContext.fragment as? Factory
|
||||||
@ -124,65 +123,44 @@ class UserListViewModel @AssistedInject constructor(@Assisted initialState: User
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentUserSearchDisposable?.dispose()
|
currentUserSearchDisposable?.dispose()
|
||||||
|
|
||||||
directoryUsersSearch
|
directoryUsersSearch
|
||||||
.debounce(300, TimeUnit.MILLISECONDS)
|
.debounce(300, TimeUnit.MILLISECONDS)
|
||||||
.switchMapSingle { search ->
|
.switchMapSingle { search ->
|
||||||
val stream = if (search.isBlank()) {
|
val stream = if (search.isBlank()) {
|
||||||
Single.just(emptyList())
|
Single.just(emptyList<User>())
|
||||||
} else if (MatrixPatterns.isUserId(search)) {
|
|
||||||
// If it's a valid user id try to use Profile API
|
|
||||||
// because directory only returns users that are in public rooms or share a room with you, where as
|
|
||||||
// profile will work other federations
|
|
||||||
session.rx().searchUsersDirectory(search, 50, state.excludedUserIds ?: emptySet())
|
|
||||||
.map { users ->
|
|
||||||
users.sortedBy { it.toMatrixItem().firstLetterOfDisplayName() }
|
|
||||||
}
|
|
||||||
.zipWith(
|
|
||||||
session.rx().getProfileInfo(search)
|
|
||||||
// ... not sure how to handle that properly (manage error case in map and return optional)
|
|
||||||
.onErrorReturn { USER_NOT_FOUND_MAP }
|
|
||||||
.map { json ->
|
|
||||||
if (json === USER_NOT_FOUND_MAP) {
|
|
||||||
USER_NOT_FOUND
|
|
||||||
} else {
|
|
||||||
User(
|
|
||||||
userId = search,
|
|
||||||
displayName = json[ProfileService.DISPLAY_NAME_KEY] as? String,
|
|
||||||
avatarUrl = json[ProfileService.AVATAR_URL_KEY] as? String
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ t1, t2 ->
|
|
||||||
if (t2 == USER_NOT_FOUND) {
|
|
||||||
t1
|
|
||||||
}
|
|
||||||
// profile result might also be in search results, in this case keep search result
|
|
||||||
else if (t1.indexOfFirst { it.userId == t2.userId } != -1) {
|
|
||||||
t1
|
|
||||||
} else {
|
|
||||||
// put it first
|
|
||||||
listOf(t2) + t1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.doOnSubscribe {
|
|
||||||
currentUserSearchDisposable = it
|
|
||||||
}
|
|
||||||
.doOnDispose {
|
|
||||||
currentUserSearchDisposable = null
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
session.rx()
|
val searchObservable = session.rx()
|
||||||
.searchUsersDirectory(search, 50, state.excludedUserIds ?: emptySet())
|
.searchUsersDirectory(search, 50, state.excludedUserIds ?: emptySet())
|
||||||
.map { users ->
|
.map { users ->
|
||||||
users.sortedBy { it.toMatrixItem().firstLetterOfDisplayName() }
|
users.sortedBy { it.toMatrixItem().firstLetterOfDisplayName() }
|
||||||
}
|
}
|
||||||
.doOnSubscribe {
|
// If it's a valid user id try to use Profile API
|
||||||
currentUserSearchDisposable = it
|
// because directory only returns users that are in public rooms or share a room with you, where as
|
||||||
}
|
// profile will work other federations
|
||||||
.doOnDispose {
|
if (!MatrixPatterns.isUserId(search)) {
|
||||||
currentUserSearchDisposable = null
|
searchObservable
|
||||||
|
} else {
|
||||||
|
val profileObservable = session.rx().getProfileInfo(search)
|
||||||
|
.map { json ->
|
||||||
|
User(
|
||||||
|
userId = search,
|
||||||
|
displayName = json[ProfileService.DISPLAY_NAME_KEY] as? String,
|
||||||
|
avatarUrl = json[ProfileService.AVATAR_URL_KEY] as? String
|
||||||
|
).toOptional()
|
||||||
|
}
|
||||||
|
.onErrorReturn { Optional.empty() }
|
||||||
|
|
||||||
|
Single.zip(searchObservable, profileObservable, { searchResults, optionalProfile ->
|
||||||
|
val profile = optionalProfile.getOrNull() ?: return@zip searchResults
|
||||||
|
val searchContainsProfile = searchResults.indexOfFirst { it.userId == profile.userId } != -1
|
||||||
|
if (searchContainsProfile) {
|
||||||
|
searchResults
|
||||||
|
} else {
|
||||||
|
listOf(profile) + searchResults
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stream.toAsync {
|
stream.toAsync {
|
||||||
copy(directoryUsers = it)
|
copy(directoryUsers = it)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user